Author: ion Date: Tue Dec 20 16:53:11 2011 New Revision: 54710
URL: http://svn.reactos.org/svn/reactos?rev=54710&view=rev Log: [KERNEL32]: Implement some VDM code that will be needed for future CreateProcessInternalW work. Not called yet.
Modified: trunk/reactos/dll/win32/kernel32/client/vdm.c
Modified: trunk/reactos/dll/win32/kernel32/client/vdm.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/client/v... ============================================================================== --- trunk/reactos/dll/win32/kernel32/client/vdm.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/kernel32/client/vdm.c [iso-8859-1] Tue Dec 20 16:53:11 2011 @@ -15,7 +15,293 @@
/* TYPES **********************************************************************/
+typedef struct _ENV_INFO +{ + ULONG NameType; + ULONG NameLength; + PWCHAR Name; +} ENV_INFO, *PENV_INFO; + +/* GLOBALS ********************************************************************/ + +ENV_INFO BasepEnvNameType[] = +{ + {3, sizeof(L"PATH"), L"PATH"}, + {2, sizeof(L"WINDIR"), L"WINDIR"}, + {2, sizeof(L"SYSTEMROOT"), L"SYSTEMROOT"}, + {3, sizeof(L"TEMP"), L"TEMP"}, + {3, sizeof(L"TMP"), L"TMP"}, +}; + +UNICODE_STRING BaseDotComSuffixName = RTL_CONSTANT_STRING(L".com"); +UNICODE_STRING BaseDotPifSuffixName = RTL_CONSTANT_STRING(L".pif"); +UNICODE_STRING BaseDotExeSuffixName = RTL_CONSTANT_STRING(L".exe"); + /* FUNCTIONS ******************************************************************/ + +ULONG +WINAPI +BaseIsDosApplication(IN PUNICODE_STRING PathName, + IN NTSTATUS Status) +{ + UNICODE_STRING String; + + /* Is it a .com? */ + String.Length = BaseDotComSuffixName.Length; + String.Buffer = &PathName->Buffer[(PathName->Length - String.Length) / sizeof(WCHAR)]; + if (RtlEqualUnicodeString(&String, &BaseDotComSuffixName, TRUE)) return 2; + + /* Is it a .pif? */ + String.Length = BaseDotPifSuffixName.Length; + String.Buffer = &PathName->Buffer[(PathName->Length - String.Length) / sizeof(WCHAR)]; + if (RtlEqualUnicodeString(&String, &BaseDotPifSuffixName, TRUE)) return 3; + + /* Is it an exe? */ + String.Length = BaseDotExeSuffixName.Length; + String.Buffer = &PathName->Buffer[(PathName->Length - String.Length) / sizeof(WCHAR)]; + if (RtlEqualUnicodeString(&String, &BaseDotExeSuffixName, TRUE)) return 1; + return 0; +} + +BOOL +WINAPI +BaseCheckForVDM(IN HANDLE hProcess, + OUT LPDWORD lpExitCode) +{ + NTSTATUS Status; + EVENT_BASIC_INFORMATION EventBasicInfo; + + /* It's VDM if the process is actually a wait handle (an event) */ + Status = NtQueryEvent(hProcess, + EventBasicInformation, + &EventBasicInfo, + sizeof(EventBasicInfo), + NULL); + if (!NT_SUCCESS(Status)) return FALSE; + + /* FIXME: Send a message to csrss */ + return FALSE; +} + +BOOL +WINAPI +BaseGetVdmConfigInfo(IN LPCWSTR Reserved, + IN ULONG DosSeqId, + IN ULONG BinaryType, + IN PUNICODE_STRING CmdLineString, + OUT PULONG VdmSize) +{ + WCHAR Buffer[MAX_PATH]; + WCHAR CommandLine[MAX_PATH * 2]; + ULONG Length; + + /* Clear the buffer in case we fail */ + CmdLineString->Buffer = 0; + + /* Always return the same size */ + *VdmSize = 0x1000000; + + /* Get the system directory */ + Length = GetSystemDirectoryW(Buffer, MAX_PATH); + if (!(Length) || (Length >= MAX_PATH)) + { + /* Eliminate no path or path too big */ + SetLastError(ERROR_INVALID_NAME); + return FALSE; + } + + /* Check if this is VDM with a DOS Sequence ID */ + if (DosSeqId) + { + /* Build the VDM string for it */ + _snwprintf(CommandLine, + sizeof(CommandLine), + L""%s\ntvdm.exe" -i%lx %s%c", + Buffer, + DosSeqId, + (BinaryType == 0x10) ? L" " : L"-w", + (BinaryType == 0x40) ? 's' : ' '); + } + else + { + /* Non-DOS, build the stirng for it without the task ID */ + _snwprintf(CommandLine, + sizeof(CommandLine), + L""%s\ntvdm.exe" %s%c", + Buffer, + (BinaryType == 0x10) ? L" " : L"-w", + (BinaryType == 0x40) ? 's' : ' '); + } + + /* Create the actual string */ + return RtlCreateUnicodeString(CmdLineString, CommandLine); +} + +UINT +WINAPI +BaseGetEnvNameType_U(IN PWCHAR Name, + IN ULONG NameLength) +{ + PENV_INFO EnvInfo; + ULONG NameType, i; + + /* Start by assuming unknown type */ + NameType = 1; + + /* Loop all the environment names */ + for (i = 0; i < (sizeof(BasepEnvNameType) / sizeof(ENV_INFO)); i++) + { + /* Get this entry */ + EnvInfo = &BasepEnvNameType[i]; + + /* Check if it matches the name */ + if ((EnvInfo->NameLength == NameLength) && + !(_wcsnicmp(EnvInfo->Name, Name, NameLength))) + { + /* It does, return the type */ + NameType = EnvInfo->NameType; + break; + } + } + + /* Return what we found, or unknown if nothing */ + return NameType; +} + +BOOL +NTAPI +BaseDestroyVDMEnvironment(IN PANSI_STRING AnsiEnv, + IN PUNICODE_STRING UnicodeEnv) +{ + ULONG Dummy = 0; + + /* Clear the ASCII buffer since Rtl creates this for us */ + if (AnsiEnv->Buffer) RtlFreeAnsiString(AnsiEnv); + + /* The Unicode buffer is build by hand, though */ + if (UnicodeEnv->Buffer) + { + /* So clear it through the API */ + NtFreeVirtualMemory(NtCurrentProcess(), + (PVOID*)&UnicodeEnv->Buffer, + &Dummy, + MEM_RELEASE); + } + + /* All done */ + return TRUE; +} + +BOOL +NTAPI +BaseCreateVDMEnvironment(IN PWCHAR lpEnvironment, + IN PANSI_STRING AnsiEnv, + IN PUNICODE_STRING UnicodeEnv) +{ + BOOL Result; + ULONG RegionSize, EnvironmentSize = 0; + PWCHAR p, Environment, NewEnvironment; + NTSTATUS Status; + + /* Make sure we have both strings */ + if (!(AnsiEnv) || !(UnicodeEnv)) + { + /* Fail */ + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + /* Check if an environment was passed in */ + if (!lpEnvironment) + { + /* Nope, create one */ + Status = RtlCreateEnvironment(TRUE, (PWCHAR*)&Environment); + if (!NT_SUCCESS(Status)) goto Quickie; + } + else + { + /* Use the one we got */ + Environment = lpEnvironment; + } + + /* Do we have something now ? */ + if (!Environment) + { + /* Still not, fail out */ + SetLastError(ERROR_BAD_ENVIRONMENT); + goto Quickie; + } + + /* Count how much space the whole environment takes */ + p = Environment; + while ((*p++ != UNICODE_NULL) && (*p != UNICODE_NULL)) EnvironmentSize++; + EnvironmentSize += sizeof(UNICODE_NULL); + + /* Allocate a new copy */ + RegionSize = (EnvironmentSize + MAX_PATH) * sizeof(WCHAR); + if (!NT_SUCCESS(NtAllocateVirtualMemory(NtCurrentProcess(), + (PVOID*)&NewEnvironment, + 0, + &RegionSize, + MEM_COMMIT, + PAGE_READWRITE))) + { + /* We failed, bail out */ + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + NewEnvironment = NULL; + goto Quickie; + } + + /* Begin parsing the new environment */ + p = NewEnvironment; + + /* FIXME: Code here */ + + /* Terminate it */ + *p++ = UNICODE_NULL; + + /* Initialize the unicode string to hold it */ + EnvironmentSize = (p - NewEnvironment) * sizeof(WCHAR); + RtlInitEmptyUnicodeString(UnicodeEnv, NewEnvironment, EnvironmentSize); + UnicodeEnv->Length = EnvironmentSize; + + /* Create the ASCII version of it */ + Status = RtlUnicodeStringToAnsiString(AnsiEnv, UnicodeEnv, TRUE); + if (!NT_SUCCESS(Status)) + { + /* Set last error if conversion failure */ + BaseSetLastNTError(Status); + } + else + { + /* Everything went okay, so return success */ + Result = TRUE; + NewEnvironment = NULL; + } + +Quickie: + /* Cleanup path starts here, start by destroying the envrionment copy */ + if (!(lpEnvironment) && (Environment)) RtlDestroyEnvironment(Environment); + + /* See if we are here due to failure */ + if (NewEnvironment) + { + /* Initialize the paths to be empty */ + RtlInitEmptyUnicodeString(UnicodeEnv, NULL, 0); + RtlInitEmptyAnsiString(AnsiEnv, NULL, 0); + + /* Free the environment copy */ + RegionSize = 0; + Status = NtFreeVirtualMemory(NtCurrentProcess(), + (PVOID*)&NewEnvironment, + &RegionSize, + MEM_RELEASE); + ASSERT(NT_SUCCESS(Status)); + } + + /* Return the result */ + return Result; +}
/* Check whether a file is an OS/2 or a very old Windows executable