/* TYPES **********************************************************************/
+#define BINARY_UNKNOWN (0)
+#define BINARY_PE_EXE32 (1)
+#define BINARY_PE_DLL32 (2)
+#define BINARY_PE_EXE64 (3)
+#define BINARY_PE_DLL64 (4)
+#define BINARY_WIN16 (5)
+#define BINARY_OS216 (6)
+#define BINARY_DOS (7)
+#define BINARY_UNIX_EXE (8)
+#define BINARY_UNIX_LIB (9)
+
+
+typedef enum _ENV_NAME_TYPE
+{
+ EnvNameNotAPath = 1,
+ EnvNameSinglePath ,
+ EnvNameMultiplePath
+} ENV_NAME_TYPE;
+
typedef struct _ENV_INFO
{
- ULONG NameType;
- ULONG NameLength;
+ ENV_NAME_TYPE NameType;
+ ULONG NameLength;
PWCHAR Name;
} ENV_INFO, *PENV_INFO;
/* GLOBALS ********************************************************************/
-ENV_INFO BasepEnvNameType[] =
+#define ENV_NAME_ENTRY(type, name) \
+ {(type), _ARRAYSIZE(name) - 1, (name)}
+
+static 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" },
+ ENV_NAME_ENTRY(EnvNameMultiplePath, L"PATH"),
+ ENV_NAME_ENTRY(EnvNameSinglePath , L"WINDIR"),
+ ENV_NAME_ENTRY(EnvNameSinglePath , L"SYSTEMROOT"),
+ ENV_NAME_ENTRY(EnvNameMultiplePath, L"TEMP"),
+ ENV_NAME_ENTRY(EnvNameMultiplePath, 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");
+static UNICODE_STRING BaseDotComSuffixName = RTL_CONSTANT_STRING(L".com");
+static UNICODE_STRING BaseDotPifSuffixName = RTL_CONSTANT_STRING(L".pif");
+static UNICODE_STRING BaseDotExeSuffixName = RTL_CONSTANT_STRING(L".exe");
/* FUNCTIONS ******************************************************************/
return 0;
}
-BOOL
+NTSTATUS
WINAPI
BaseCheckVDM(IN ULONG BinaryType,
IN PCWCH ApplicationName,
IN PCWCH CommandLine,
IN PCWCH CurrentDirectory,
IN PANSI_STRING AnsiEnvironment,
- IN PCSR_API_MESSAGE ApiMessage,
+ IN PBASE_API_MESSAGE ApiMessage,
IN OUT PULONG iTask,
IN DWORD CreationFlags,
IN LPSTARTUPINFOW StartupInfo,
IN HANDLE hUserToken OPTIONAL)
{
- /* This is not supported */
- UNIMPLEMENTED;
- return FALSE;
+ NTSTATUS Status;
+ PBASE_CHECK_VDM CheckVdm = &ApiMessage->Data.CheckVDMRequest;
+ PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
+ PWCHAR CurrentDir = NULL;
+ PWCHAR ShortAppName = NULL;
+ PWCHAR ShortCurrentDir = NULL;
+ ULONG Length;
+ PCHAR AnsiCmdLine = NULL;
+ PCHAR AnsiAppName = NULL;
+ PCHAR AnsiCurDirectory = NULL;
+ PCHAR AnsiDesktop = NULL;
+ PCHAR AnsiTitle = NULL;
+ PCHAR AnsiReserved = NULL;
+ STARTUPINFOA AnsiStartupInfo;
+ ULONG NumStrings = 5;
+
+ /* Parameters validation */
+ if (ApplicationName == NULL || CommandLine == NULL)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* Trim leading whitespace from ApplicationName */
+ while (*ApplicationName == L' ' || *ApplicationName == L'\t')
+ ++ApplicationName;
+
+ /* Calculate the size of the short application name */
+ Length = GetShortPathNameW(ApplicationName, NULL, 0);
+ if (Length == 0)
+ {
+ Status = STATUS_OBJECT_PATH_INVALID;
+ goto Cleanup;
+ }
+
+ /* Allocate memory for the short application name */
+ ShortAppName = (PWCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ Length * sizeof(WCHAR));
+ if (!ShortAppName)
+ {
+ Status = STATUS_NO_MEMORY;
+ goto Cleanup;
+ }
+
+ /* Get the short application name */
+ if (GetShortPathNameW(ApplicationName, ShortAppName, Length) == 0)
+ {
+ /* Try to determine which error occurred */
+ switch (GetLastError())
+ {
+ case ERROR_NOT_ENOUGH_MEMORY:
+ {
+ Status = STATUS_NO_MEMORY;
+ break;
+ }
+
+ case ERROR_INVALID_PARAMETER:
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ default:
+ {
+ Status = STATUS_OBJECT_PATH_INVALID;
+ }
+ }
+
+ goto Cleanup;
+ }
+
+ /* Trim leading whitespace from CommandLine */
+ while (*CommandLine == L' ' || *CommandLine == L'\t')
+ ++CommandLine;
+
+ /*
+ * CommandLine is usually formatted as: 'ApplicationName param0 ...'.
+ * So we want to strip the first token (ApplicationName) from it.
+ * Two cases are in fact possible:
+ * - either the first token is indeed ApplicationName, so we just skip it;
+ * - or the first token is not exactly ApplicationName, because it happened
+ * that somebody else already preprocessed CommandLine. Therefore we
+ * suppose that the first token corresponds to an application name and
+ * we skip it. Care should be taken when quotes are present in this token.
+ */
+ if (*CommandLine)
+ {
+ /* The first part of CommandLine should be the ApplicationName... */
+ Length = wcslen(ApplicationName);
+ if (Length <= wcslen(CommandLine) &&
+ _wcsnicmp(ApplicationName, CommandLine, Length) == 0)
+ {
+ /* Skip it */
+ CommandLine += Length;
+ }
+ /*
+ * ... but it is not, however we still have a token. We suppose that
+ * it corresponds to some sort of application name, so we skip it too.
+ */
+ else
+ {
+ /* Get rid of the first token. We stop when we see whitespace. */
+ while (*CommandLine && !(*CommandLine == L' ' || *CommandLine == L'\t'))
+ {
+ if (*CommandLine == L'\"')
+ {
+ /* We enter a quoted part, skip it */
+ ++CommandLine;
+ while (*CommandLine && *CommandLine++ != L'\"') ;
+ }
+ else
+ {
+ /* Go to the next character */
+ ++CommandLine;
+ }
+ }
+ }
+ }
+
+ /*
+ * Trim remaining whitespace from CommandLine that may be
+ * present between the application name and the parameters.
+ */
+ while (*CommandLine == L' ' || *CommandLine == L'\t')
+ ++CommandLine;
+
+ /* Get the current directory */
+ if (CurrentDirectory == NULL)
+ {
+ /* Allocate memory for the current directory path */
+ Length = GetCurrentDirectoryW(0, NULL);
+ CurrentDir = (PWCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ Length * sizeof(WCHAR));
+ if (CurrentDir == NULL)
+ {
+ Status = STATUS_NO_MEMORY;
+ goto Cleanup;
+ }
+
+ /* Get the current directory */
+ GetCurrentDirectoryW(Length, CurrentDir);
+ CurrentDirectory = CurrentDir;
+ }
+
+ /* Calculate the size of the short current directory path */
+ Length = GetShortPathNameW(CurrentDirectory, NULL, 0);
+
+ /* Allocate memory for the short current directory path */
+ ShortCurrentDir = (PWCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ Length * sizeof(WCHAR));
+ if (!ShortCurrentDir)
+ {
+ Status = STATUS_NO_MEMORY;
+ goto Cleanup;
+ }
+
+ /* Get the short current directory path */
+ if (!GetShortPathNameW(CurrentDirectory, ShortCurrentDir, Length))
+ {
+ /* Try to determine which error occurred */
+ switch (GetLastError())
+ {
+ case ERROR_NOT_ENOUGH_MEMORY:
+ {
+ Status = STATUS_NO_MEMORY;
+ break;
+ }
+
+ case ERROR_INVALID_PARAMETER:
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ default:
+ {
+ Status = STATUS_OBJECT_PATH_INVALID;
+ }
+ }
+ goto Cleanup;
+ }
+
+ /* Setup the input parameters */
+ CheckVdm->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
+ CheckVdm->BinaryType = BinaryType;
+ CheckVdm->CodePage = CP_ACP;
+ CheckVdm->dwCreationFlags = CreationFlags;
+ CheckVdm->CurDrive = CurrentDirectory[0] - L'A';
+ CheckVdm->CmdLen = wcslen(CommandLine) + 1;
+ CheckVdm->AppLen = wcslen(ShortAppName) + 1;
+ CheckVdm->PifLen = 0; // TODO: PIF file support!
+ CheckVdm->CurDirectoryLen = wcslen(ShortCurrentDir) + 1;
+ CheckVdm->EnvLen = AnsiEnvironment->Length;
+ CheckVdm->DesktopLen = (StartupInfo->lpDesktop != NULL) ? (wcslen(StartupInfo->lpDesktop) + 1) : 0;
+ CheckVdm->TitleLen = (StartupInfo->lpTitle != NULL) ? (wcslen(StartupInfo->lpTitle) + 1) : 0;
+ CheckVdm->ReservedLen = (StartupInfo->lpReserved != NULL) ? (wcslen(StartupInfo->lpReserved) + 1) : 0;
+
+ if (StartupInfo->dwFlags & STARTF_USESTDHANDLES)
+ {
+ /* Set the standard handles */
+ CheckVdm->StdIn = StartupInfo->hStdInput;
+ CheckVdm->StdOut = StartupInfo->hStdOutput;
+ CheckVdm->StdErr = StartupInfo->hStdError;
+ }
+
+ /* Allocate memory for the ANSI strings */
+ // We need to add the newline characters '\r\n' to the command line
+ AnsiCmdLine = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, CheckVdm->CmdLen + 2);
+ AnsiAppName = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, CheckVdm->AppLen);
+ AnsiCurDirectory = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, CheckVdm->CurDirectoryLen);
+ if (StartupInfo->lpDesktop)
+ AnsiDesktop = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ CheckVdm->DesktopLen);
+ if (StartupInfo->lpTitle)
+ AnsiTitle = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ CheckVdm->TitleLen);
+ if (StartupInfo->lpReserved)
+ AnsiReserved = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ CheckVdm->ReservedLen);
+
+ if (!AnsiCmdLine
+ || !AnsiAppName
+ || !AnsiCurDirectory
+ || (StartupInfo->lpDesktop && !AnsiDesktop)
+ || (StartupInfo->lpTitle && !AnsiTitle)
+ || (StartupInfo->lpReserved && !AnsiReserved))
+ {
+ Status = STATUS_NO_MEMORY;
+ goto Cleanup;
+ }
+
+ /* Convert the command line into an ANSI string */
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ CommandLine,
+ CheckVdm->CmdLen,
+ AnsiCmdLine,
+ CheckVdm->CmdLen,
+ NULL,
+ NULL);
+ /* Add the needed newline and NULL-terminate */
+ CheckVdm->CmdLen--; // Rewind back to the NULL character
+ AnsiCmdLine[CheckVdm->CmdLen++] = '\r';
+ AnsiCmdLine[CheckVdm->CmdLen++] = '\n';
+ AnsiCmdLine[CheckVdm->CmdLen++] = 0;
+
+ /* Convert the short application name into an ANSI string */
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ ShortAppName,
+ CheckVdm->AppLen,
+ AnsiAppName,
+ CheckVdm->AppLen,
+ NULL,
+ NULL);
+
+ /* Convert the short current directory path into an ANSI string */
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ ShortCurrentDir,
+ CheckVdm->CurDirectoryLen,
+ AnsiCurDirectory,
+ CheckVdm->CurDirectoryLen,
+ NULL,
+ NULL);
+
+ if (StartupInfo->lpDesktop)
+ {
+ /* Convert the desktop name into an ANSI string */
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ StartupInfo->lpDesktop,
+ CheckVdm->DesktopLen,
+ AnsiDesktop,
+ CheckVdm->DesktopLen,
+ NULL,
+ NULL);
+ NumStrings++;
+ }
+
+ if (StartupInfo->lpTitle)
+ {
+ /* Convert the title into an ANSI string */
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ StartupInfo->lpTitle,
+ CheckVdm->TitleLen,
+ AnsiTitle,
+ CheckVdm->TitleLen,
+ NULL,
+ NULL);
+ NumStrings++;
+ }
+
+ if (StartupInfo->lpReserved)
+ {
+ /* Convert the reserved value into an ANSI string */
+ WideCharToMultiByte(CP_ACP,
+ 0,
+ StartupInfo->lpReserved,
+ CheckVdm->ReservedLen,
+ AnsiReserved,
+ CheckVdm->ReservedLen,
+ NULL,
+ NULL);
+ NumStrings++;
+ }
+
+ /* Fill the ANSI startup info structure */
+ RtlCopyMemory(&AnsiStartupInfo, StartupInfo, sizeof(AnsiStartupInfo));
+ AnsiStartupInfo.lpReserved = AnsiReserved;
+ AnsiStartupInfo.lpDesktop = AnsiDesktop;
+ AnsiStartupInfo.lpTitle = AnsiTitle;
+
+ /* Allocate the capture buffer */
+ CaptureBuffer = CsrAllocateCaptureBuffer(NumStrings,
+ CheckVdm->CmdLen
+ + CheckVdm->AppLen
+ + CheckVdm->PifLen
+ + CheckVdm->CurDirectoryLen
+ + CheckVdm->DesktopLen
+ + CheckVdm->TitleLen
+ + CheckVdm->ReservedLen
+ + CheckVdm->EnvLen
+ + sizeof(*CheckVdm->StartupInfo));
+ if (CaptureBuffer == NULL)
+ {
+ Status = STATUS_NO_MEMORY;
+ goto Cleanup;
+ }
+
+ /* Capture the command line */
+ CsrCaptureMessageBuffer(CaptureBuffer,
+ AnsiCmdLine,
+ CheckVdm->CmdLen,
+ (PVOID*)&CheckVdm->CmdLine);
+
+ /* Capture the application name */
+ CsrCaptureMessageBuffer(CaptureBuffer,
+ AnsiAppName,
+ CheckVdm->AppLen,
+ (PVOID*)&CheckVdm->AppName);
+
+ CheckVdm->PifFile = NULL; // TODO: PIF file support!
+
+ /* Capture the current directory */
+ CsrCaptureMessageBuffer(CaptureBuffer,
+ AnsiCurDirectory,
+ CheckVdm->CurDirectoryLen,
+ (PVOID*)&CheckVdm->CurDirectory);
+
+ /* Capture the environment */
+ CsrCaptureMessageBuffer(CaptureBuffer,
+ AnsiEnvironment->Buffer,
+ CheckVdm->EnvLen,
+ (PVOID*)&CheckVdm->Env);
+
+ /* Capture the startup info structure */
+ CsrCaptureMessageBuffer(CaptureBuffer,
+ &AnsiStartupInfo,
+ sizeof(*CheckVdm->StartupInfo),
+ (PVOID*)&CheckVdm->StartupInfo);
+
+ if (StartupInfo->lpDesktop)
+ {
+ /* Capture the desktop name */
+ CsrCaptureMessageBuffer(CaptureBuffer,
+ AnsiDesktop,
+ CheckVdm->DesktopLen,
+ (PVOID*)&CheckVdm->Desktop);
+ }
+ else CheckVdm->Desktop = NULL;
+
+ if (StartupInfo->lpTitle)
+ {
+ /* Capture the title */
+ CsrCaptureMessageBuffer(CaptureBuffer,
+ AnsiTitle,
+ CheckVdm->TitleLen,
+ (PVOID*)&CheckVdm->Title);
+ }
+ else CheckVdm->Title = NULL;
+
+ if (StartupInfo->lpReserved)
+ {
+ /* Capture the reserved parameter */
+ CsrCaptureMessageBuffer(CaptureBuffer,
+ AnsiReserved,
+ CheckVdm->ReservedLen,
+ (PVOID*)&CheckVdm->Reserved);
+ }
+ else CheckVdm->Reserved = NULL;
+
+ /* Send the message to CSRSS */
+ Status = CsrClientCallServer((PCSR_API_MESSAGE)ApiMessage,
+ CaptureBuffer,
+ CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepCheckVDM),
+ sizeof(*CheckVdm));
+
+ /* Write back the task ID */
+ *iTask = CheckVdm->iTask;
+
+Cleanup:
+
+ /* Free the ANSI strings */
+ if (AnsiCmdLine) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiCmdLine);
+ if (AnsiAppName) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiAppName);
+ if (AnsiCurDirectory) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiCurDirectory);
+ if (AnsiDesktop) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiDesktop);
+ if (AnsiTitle) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiTitle);
+ if (AnsiReserved) RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiReserved);
+
+ /* Free the capture buffer */
+ if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
+
+ /* Free the current directory, if it was allocated here, and its short path */
+ if (ShortCurrentDir) RtlFreeHeap(RtlGetProcessHeap(), 0, ShortCurrentDir);
+ if (CurrentDir) RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentDir);
+
+ /* Free the short app name */
+ if (ShortAppName) RtlFreeHeap(RtlGetProcessHeap(), 0, ShortAppName);
+
+ return Status;
}
BOOL
IN ULONG IndexInfo,
IN ULONG BinaryType)
{
-#if 0 // Unimplemented in BASESRV
- NTSTATUS Status;
BASE_API_MESSAGE ApiMessage;
- PBASE_UPDATE_VDM_ENTRY UpdateVdmEntry = &ApiMessage.Data.UpdateVdmEntry;
+ PBASE_UPDATE_VDM_ENTRY UpdateVdmEntry = &ApiMessage.Data.UpdateVDMEntryRequest;
/* Check what update is being sent */
switch (UpdateIndex)
UpdateVdmEntry->BinaryType = BinaryType;
/* Send the message to CSRSS */
- Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
- NULL,
- CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepUpdateVDMEntry),
- sizeof(BASE_UPDATE_VDM_ENTRY));
- if (!NT_SUCCESS(Status))
+ CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
+ NULL,
+ CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepUpdateVDMEntry),
+ sizeof(*UpdateVdmEntry));
+ if (!NT_SUCCESS(ApiMessage.Status))
{
/* Handle failure */
- BaseSetLastNTError(Status);
+ BaseSetLastNTError(ApiMessage.Status);
return FALSE;
}
/* Return it to the caller */
*WaitHandle = UpdateVdmEntry->WaitObjectForParent;
}
-#endif
+
/* We made it */
return TRUE;
}
BaseCheckForVDM(IN HANDLE ProcessHandle,
OUT LPDWORD ExitCode)
{
-#if 0 // Unimplemented in BASESRV
NTSTATUS Status;
EVENT_BASIC_INFORMATION EventBasicInfo;
BASE_API_MESSAGE ApiMessage;
- PBASE_GET_VDM_EXIT_CODE GetVdmExitCode = &ApiMessage.Data.GetVdmExitCode;
+ PBASE_GET_VDM_EXIT_CODE GetVdmExitCode = &ApiMessage.Data.GetVDMExitCodeRequest;
/* It's VDM if the process is actually a wait handle (an event) */
Status = NtQueryEvent(ProcessHandle,
Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
NULL,
CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepGetVDMExitCode),
- sizeof(BASE_GET_VDM_EXIT_CODE));
+ sizeof(*GetVdmExitCode));
if (!NT_SUCCESS(Status)) return FALSE;
/* Get the exit code from the reply */
*ExitCode = GetVdmExitCode->ExitCode;
-#endif
return TRUE;
}
* %s%c : Nothing if DOS VDM, -w if WoW VDM, -ws if separate WoW VDM.
*/
_snwprintf(CommandLine,
- sizeof(CommandLine),
+ ARRAYSIZE(CommandLine),
L"\"%s\\ntvdm.exe\" -i%lx %s%c",
Buffer,
DosSeqId,
* %s%c : Nothing if DOS VDM, -w if WoW VDM, -ws if separate WoW VDM.
*/
_snwprintf(CommandLine,
- sizeof(CommandLine),
+ ARRAYSIZE(CommandLine),
L"\"%s\\ntvdm.exe\" %s%c",
Buffer,
(BinaryType == BINARY_TYPE_DOS) ? L" " : L"-w",
return RtlCreateUnicodeString(CmdLineString, CommandLine);
}
-UINT
+ENV_NAME_TYPE
WINAPI
BaseGetEnvNameType_U(IN PWCHAR Name,
IN ULONG NameLength)
{
PENV_INFO EnvInfo;
- ULONG NameType, i;
+ ENV_NAME_TYPE NameType;
+ ULONG i;
- /* Start by assuming unknown type */
- NameType = 1;
+ /* Start by assuming the environment variable doesn't describe paths */
+ NameType = EnvNameNotAPath;
/* Loop all the environment names */
- for (i = 0; i < (sizeof(BasepEnvNameType) / sizeof(ENV_INFO)); i++)
+ for (i = 0; i < ARRAYSIZE(BasepEnvNameType); i++)
{
/* Get this entry */
EnvInfo = &BasepEnvNameType[i];
/* Check if it matches the name */
if ((EnvInfo->NameLength == NameLength) &&
- !(_wcsnicmp(EnvInfo->Name, Name, NameLength)))
+ (_wcsnicmp(EnvInfo->Name, Name, NameLength) == 0))
{
/* It does, return the type */
NameType = EnvInfo->NameType;
}
}
- /* Return what we found, or unknown if nothing */
return NameType;
}
BOOL
NTAPI
-BaseDestroyVDMEnvironment(IN PANSI_STRING AnsiEnv,
- IN PUNICODE_STRING UnicodeEnv)
+BaseCreateVDMEnvironment(IN PWCHAR lpEnvironment,
+ OUT PANSI_STRING AnsiEnv,
+ OUT 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);
- }
+#define IS_ALPHA(x) \
+ ( ((x) >= L'A' && (x) <= L'Z') || ((x) >= L'a' && (x) <= L'z') )
- /* All done */
- return TRUE;
-}
+// From lib/rtl/path.c :
+// Can be put in some .h ??
+#define IS_PATH_SEPARATOR(x) ((x) == L'\\' || (x) == L'/')
-BOOL
-NTAPI
-BaseCreateVDMEnvironment(IN PWCHAR lpEnvironment,
- IN PANSI_STRING AnsiEnv,
- IN PUNICODE_STRING UnicodeEnv)
-{
- BOOL Result;
- ULONG RegionSize, EnvironmentSize = 0;
- PWCHAR p, Environment, NewEnvironment = NULL;
+ BOOL Success = FALSE;
NTSTATUS Status;
+ ULONG RegionSize, EnvironmentSize = 0;
+ PWCHAR Environment, NewEnvironment = NULL;
+ ENV_NAME_TYPE NameType;
+ ULONG NameLength, NumChars, Remaining;
+ PWCHAR SourcePtr, DestPtr, StartPtr;
/* Make sure we have both strings */
- if (!(AnsiEnv) || !(UnicodeEnv))
+ if (!AnsiEnv || !UnicodeEnv)
{
/* Fail */
SetLastError(ERROR_INVALID_PARAMETER);
if (!lpEnvironment)
{
/* Nope, create one */
- Status = RtlCreateEnvironment(TRUE, (PWCHAR*)&Environment);
- if (!NT_SUCCESS(Status)) goto Quickie;
+ Status = RtlCreateEnvironment(TRUE, &Environment);
+ if (!NT_SUCCESS(Status)) goto Cleanup;
}
else
{
/* Do we have something now ? */
if (!Environment)
{
- /* Still not, fail out */
+ /* Still not, bail out */
SetLastError(ERROR_BAD_ENVIRONMENT);
- goto Quickie;
+ goto Cleanup;
}
- /* 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 */
+ /*
+ * Count how much space the whole environment takes. The environment block is
+ * doubly NULL-terminated (NULL from last string and final NULL terminator).
+ */
+ SourcePtr = Environment;
+ while (!(*SourcePtr++ == UNICODE_NULL && *SourcePtr == UNICODE_NULL))
+ ++EnvironmentSize;
+ EnvironmentSize += 2; // Add the two terminating NULLs
+
+ /*
+ * Allocate a new copy large enough to hold all the environment with paths
+ * in their short form. Since the short form of a path can be a bit longer
+ * than its long form, for example in the case where characters that are
+ * invalid in the 8.3 representation are present in the long path name:
+ * 'C:\\a+b' --> 'C:\\A_B~1', or:
+ * 'C:\\a b' --> 'C:\\AB2761~1' (with checksum inserted),
+ * we suppose that the possible total number of extra characters needed to
+ * convert the long paths into their short form is at most equal to MAX_PATH.
+ */
RegionSize = (EnvironmentSize + MAX_PATH) * sizeof(WCHAR);
- if (!NT_SUCCESS(NtAllocateVirtualMemory(NtCurrentProcess(),
- (PVOID*)&NewEnvironment,
- 0,
- &RegionSize,
- MEM_COMMIT,
- PAGE_READWRITE)))
+ Status = NtAllocateVirtualMemory(NtCurrentProcess(),
+ (PVOID*)&NewEnvironment,
+ 0,
+ &RegionSize,
+ MEM_COMMIT,
+ PAGE_READWRITE);
+ if (!NT_SUCCESS(Status))
{
/* We failed, bail out */
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
NewEnvironment = NULL;
- goto Quickie;
+ goto Cleanup;
}
- /* Begin parsing the new environment */
- p = NewEnvironment;
+ /* Parse the environment block */
+ Remaining = MAX_PATH - 2; // '-2': remove the last two NULLs. FIXME: is it really needed??
+ SourcePtr = Environment;
+ DestPtr = NewEnvironment;
+
+ /* Loop through all the environment strings */
+ while (*SourcePtr != UNICODE_NULL)
+ {
+ /*
+ * 1. Check the type of the environment variable and copy its name.
+ */
+
+ /* Regular environment variable */
+ if (*SourcePtr != L'=')
+ {
+ StartPtr = SourcePtr;
+
+ /* Copy the environment variable name, including the '=' */
+ while (*SourcePtr != UNICODE_NULL)
+ {
+ *DestPtr++ = *SourcePtr;
+ if (*SourcePtr++ == L'=') break;
+ }
- /* FIXME: Code here */
+ /* Guess the type of the environment variable */
+ NameType = BaseGetEnvNameType_U(StartPtr, SourcePtr - StartPtr - 1);
+ }
+ /* 'Current directory' environment variable (i.e. of '=X:=' form) */
+ else // if (*SourcePtr == L'=')
+ {
+ /* First assume we have a possibly malformed environment variable */
+ NameType = EnvNameNotAPath;
+
+ /* Check for a valid 'Current directory' environment variable */
+ if (IS_ALPHA(SourcePtr[1]) && SourcePtr[2] == L':' && SourcePtr[3] == L'=')
+ {
+ /*
+ * Small optimization: convert the path to short form only if
+ * the current directory is not the root directory (i.e. not
+ * of the '=X:=Y:\' form), otherwise just do a simple copy.
+ */
+ if ( wcslen(SourcePtr) >= ARRAYSIZE("=X:=Y:\\")-1 &&
+ !( IS_ALPHA(SourcePtr[4]) && SourcePtr[5] == L':' &&
+ IS_PATH_SEPARATOR(SourcePtr[6]) && SourcePtr[7] == UNICODE_NULL ) )
+ {
+ NameType = EnvNameSinglePath;
+
+ /* Copy the '=X:=' prefix */
+ *DestPtr++ = SourcePtr[0];
+ *DestPtr++ = SourcePtr[1];
+ *DestPtr++ = SourcePtr[2];
+ *DestPtr++ = SourcePtr[3];
+ SourcePtr += 4;
+ }
+ }
+ else
+ {
+ /*
+ * Invalid stuff starting with '=', i.e.:
+ * =? (with '?' not being a letter)
+ * =X??? (with '?' not being ":=" and not followed by something longer than 3 characters)
+ * =X:=??? (with '?' not being "X:\\")
+ *
+ * 'NameType' is already set to 'EnvNameNotAPath'.
+ */
+ }
+ }
+
+
+ /*
+ * 2. Copy the environment value and perform conversions accordingly.
+ */
+
+ if (NameType == EnvNameNotAPath)
+ {
+ /* Copy everything, including the NULL terminator */
+ do
+ {
+ *DestPtr++ = *SourcePtr;
+ } while (*SourcePtr++ != UNICODE_NULL);
+ }
+ else if (NameType == EnvNameSinglePath)
+ {
+ /* Convert the path to its short form */
+ NameLength = wcslen(SourcePtr);
+ NumChars = GetShortPathNameW(SourcePtr, DestPtr, NameLength + 1 + Remaining);
+ if (NumChars == 0 || NumChars > NameLength + Remaining)
+ {
+ /* If the conversion failed, just copy the original value */
+ RtlCopyMemory(DestPtr, SourcePtr, NameLength * sizeof(WCHAR));
+ NumChars = NameLength;
+ }
+ DestPtr += NumChars;
+ if (NumChars > NameLength)
+ Remaining -= (NumChars - NameLength);
+
+ SourcePtr += NameLength;
+
+ /* Copy the NULL terminator */
+ *DestPtr++ = *SourcePtr++;
+ }
+ else // if (NameType == EnvNameMultiplePath)
+ {
+ WCHAR Delimiter;
+
+ /* Loop through the list of paths (delimited by ';') and convert each path to its short form */
+ do
+ {
+ /* Copy any trailing ';' before going to the next path */
+ while (*SourcePtr == L';')
+ {
+ *DestPtr++ = *SourcePtr++;
+ }
+
+ StartPtr = SourcePtr;
+
+ /* Find the next path list delimiter or the NULL terminator */
+ while (*SourcePtr != UNICODE_NULL && *SourcePtr != L';')
+ {
+ ++SourcePtr;
+ }
+ Delimiter = *SourcePtr;
+
+ NameLength = SourcePtr - StartPtr;
+ if (NameLength)
+ {
+ /*
+ * Temporarily replace the possible path list delimiter by NULL.
+ * 'lpEnvironment' must point to a read+write memory buffer!
+ */
+ *SourcePtr = UNICODE_NULL;
+
+ NumChars = GetShortPathNameW(StartPtr, DestPtr, NameLength + 1 + Remaining);
+ if ( NumChars == 0 ||
+ (Delimiter == L';' ? NumChars > NameLength + Remaining
+ : NumChars > NameLength /* + Remaining ?? */) )
+ {
+ /* If the conversion failed, just copy the original value */
+ RtlCopyMemory(DestPtr, StartPtr, NameLength * sizeof(WCHAR));
+ NumChars = NameLength;
+ }
+ DestPtr += NumChars;
+ if (NumChars > NameLength)
+ Remaining -= (NumChars - NameLength);
+
+ /* If removed, restore the path list delimiter in the source environment value and copy it */
+ if (Delimiter != UNICODE_NULL)
+ {
+ *SourcePtr = Delimiter;
+ *DestPtr++ = *SourcePtr++;
+ }
+ }
+ } while (*SourcePtr != UNICODE_NULL);
+
+ /* Copy the NULL terminator */
+ *DestPtr++ = *SourcePtr++;
+ }
+ }
- /* Terminate it */
- *p++ = UNICODE_NULL;
+ /* NULL-terminate the environment block */
+ *DestPtr++ = UNICODE_NULL;
- /* Initialize the unicode string to hold it */
- EnvironmentSize = (p - NewEnvironment) * sizeof(WCHAR);
- RtlInitEmptyUnicodeString(UnicodeEnv, NewEnvironment, EnvironmentSize);
- UnicodeEnv->Length = EnvironmentSize;
+ /* Initialize the Unicode string to hold it */
+ RtlInitEmptyUnicodeString(UnicodeEnv, NewEnvironment,
+ (DestPtr - NewEnvironment) * sizeof(WCHAR));
+ UnicodeEnv->Length = UnicodeEnv->MaximumLength;
- /* Create the ASCII version of it */
+ /* Create its ANSI version */
Status = RtlUnicodeStringToAnsiString(AnsiEnv, UnicodeEnv, TRUE);
if (!NT_SUCCESS(Status))
{
else
{
/* Everything went okay, so return success */
- Result = TRUE;
+ Success = TRUE;
NewEnvironment = NULL;
}
-Quickie:
- /* Cleanup path starts here, start by destroying the envrionment copy */
- if (!(lpEnvironment) && (Environment)) RtlDestroyEnvironment(Environment);
+Cleanup:
+ /* Cleanup path starts here, start by destroying the environment copy */
+ if (!lpEnvironment && Environment) RtlDestroyEnvironment(Environment);
/* See if we are here due to failure */
if (NewEnvironment)
}
/* Return the result */
- return Result;
+ return Success;
+}
+
+BOOL
+NTAPI
+BaseDestroyVDMEnvironment(IN PANSI_STRING AnsiEnv,
+ IN PUNICODE_STRING UnicodeEnv)
+{
+ ULONG Dummy = 0;
+
+ /* Clear the ANSI 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;
}
return BINARY_UNKNOWN;
}
- /* Mach-o File with Endian set to Big Endian or Little Endian*/
+ /* Mach-o File with Endian set to Big Endian or Little Endian*/
if(Header.macho.magic == 0xFEEDFACE ||
Header.macho.magic == 0xCEFAEDFE)
{
return BINARY_PE_EXE32;
}
- if(!memcmp(magic, "NE", 1))
+ if(!memcmp(magic, "NE", 2))
{
/* This is a Windows executable (NE) header. This can
* mean either a 16-bit OS/2 or a 16-bit Windows or even a
}
/*
- * @unimplemented
+ * @implemented
*/
-DWORD
+VOID
WINAPI
-ExitVDM (
- DWORD Unknown0,
- DWORD Unknown1
- )
+ExitVDM(BOOL IsWow, ULONG iWowTask)
{
- STUB;
- return 0;
-}
+ BASE_API_MESSAGE ApiMessage;
+ PBASE_EXIT_VDM ExitVdm = &ApiMessage.Data.ExitVDMRequest;
+
+ /* Setup the input parameters */
+ ExitVdm->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
+ ExitVdm->iWowTask = IsWow ? iWowTask : 0; /* Always zero for DOS tasks */
+ ExitVdm->WaitObjectForVDM = NULL;
+ /* Call CSRSS */
+ CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
+ NULL,
+ CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepExitVDM),
+ sizeof(*ExitVdm));
+
+ /* Close the returned wait object handle, if any */
+ if (NT_SUCCESS(ApiMessage.Status) && (ExitVdm->WaitObjectForVDM != NULL))
+ {
+ CloseHandle(ExitVdm->WaitObjectForVDM);
+ }
+}
/*
- * @unimplemented
+ * @implemented
*/
-DWORD
+BOOL
WINAPI
-GetNextVDMCommand (
- DWORD Unknown0
- )
+GetNextVDMCommand(PVDM_COMMAND_INFO CommandData)
{
- STUB;
- return 0;
+ BOOL Success = FALSE;
+ NTSTATUS Status;
+ BASE_API_MESSAGE ApiMessage;
+ PBASE_GET_NEXT_VDM_COMMAND GetNextVdmCommand = &ApiMessage.Data.GetNextVDMCommandRequest;
+ PBASE_IS_FIRST_VDM IsFirstVdm = &ApiMessage.Data.IsFirstVDMRequest;
+ PBASE_SET_REENTER_COUNT SetReenterCount = &ApiMessage.Data.SetReenterCountRequest;
+ PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
+ ULONG NumStrings = 0;
+
+ /*
+ * Special case to test whether the VDM is the first one.
+ */
+ if (CommandData == NULL)
+ {
+ /* Call CSRSS */
+ CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
+ NULL,
+ CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepIsFirstVDM),
+ sizeof(*IsFirstVdm));
+ if (!NT_SUCCESS(ApiMessage.Status))
+ {
+ BaseSetLastNTError(ApiMessage.Status);
+ return FALSE;
+ }
+
+ /* Return TRUE if this is the first VDM */
+ return IsFirstVdm->FirstVDM;
+ }
+
+ /* CommandData != NULL */
+
+ /*
+ * Special case to increment or decrement the reentrancy count.
+ */
+ if ((CommandData->VDMState == VDM_INC_REENTER_COUNT) ||
+ (CommandData->VDMState == VDM_DEC_REENTER_COUNT))
+ {
+ /* Setup the input parameters */
+ SetReenterCount->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
+ SetReenterCount->fIncDec = CommandData->VDMState;
+
+ /* Call CSRSS */
+ CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
+ NULL,
+ CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepSetReenterCount),
+ sizeof(*SetReenterCount));
+ if (!NT_SUCCESS(ApiMessage.Status))
+ {
+ BaseSetLastNTError(ApiMessage.Status);
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ /*
+ * TODO!
+ * Special case to retrieve or set WOW information.
+ */
+ // TODO: if CommandData->VDMState & (VDM_LIST_WOW_PROCESSES | VDM_LIST_WOW_TASKS | VDM_ADD_WOW_TASK)
+ // then call BasepGetNextVDMCommand in a simpler way!
+
+ /*
+ * Regular case.
+ */
+
+ /* Clear the structure */
+ RtlZeroMemory(GetNextVdmCommand, sizeof(*GetNextVdmCommand));
+
+ /* Setup the input parameters */
+ GetNextVdmCommand->iTask = CommandData->TaskId;
+ GetNextVdmCommand->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
+ GetNextVdmCommand->CmdLen = CommandData->CmdLen;
+ GetNextVdmCommand->AppLen = CommandData->AppLen;
+ GetNextVdmCommand->PifLen = CommandData->PifLen;
+ GetNextVdmCommand->CurDirectoryLen = CommandData->CurDirectoryLen;
+ GetNextVdmCommand->EnvLen = CommandData->EnvLen;
+ GetNextVdmCommand->DesktopLen = CommandData->DesktopLen;
+ GetNextVdmCommand->TitleLen = CommandData->TitleLen;
+ GetNextVdmCommand->ReservedLen = CommandData->ReservedLen;
+ GetNextVdmCommand->VDMState = CommandData->VDMState;
+
+ /* Count the number of strings */
+ if (CommandData->CmdLen) NumStrings++;
+ if (CommandData->AppLen) NumStrings++;
+ if (CommandData->PifLen) NumStrings++;
+ if (CommandData->CurDirectoryLen) NumStrings++;
+ if (CommandData->EnvLen) NumStrings++;
+ if (CommandData->DesktopLen) NumStrings++;
+ if (CommandData->TitleLen) NumStrings++;
+ if (CommandData->ReservedLen) NumStrings++;
+
+ /* Allocate the capture buffer */
+ CaptureBuffer = CsrAllocateCaptureBuffer(NumStrings + 1,
+ GetNextVdmCommand->CmdLen
+ + GetNextVdmCommand->AppLen
+ + GetNextVdmCommand->PifLen
+ + GetNextVdmCommand->CurDirectoryLen
+ + GetNextVdmCommand->EnvLen
+ + GetNextVdmCommand->DesktopLen
+ + GetNextVdmCommand->TitleLen
+ + GetNextVdmCommand->ReservedLen
+ + sizeof(*GetNextVdmCommand->StartupInfo));
+ if (CaptureBuffer == NULL)
+ {
+ BaseSetLastNTError(STATUS_NO_MEMORY);
+ goto Cleanup;
+ }
+
+ /* Capture the data */
+
+ CsrAllocateMessagePointer(CaptureBuffer,
+ sizeof(*GetNextVdmCommand->StartupInfo),
+ (PVOID*)&GetNextVdmCommand->StartupInfo);
+
+ if (CommandData->CmdLen)
+ {
+ CsrAllocateMessagePointer(CaptureBuffer,
+ CommandData->CmdLen,
+ (PVOID*)&GetNextVdmCommand->CmdLine);
+ }
+
+ if (CommandData->AppLen)
+ {
+ CsrAllocateMessagePointer(CaptureBuffer,
+ CommandData->AppLen,
+ (PVOID*)&GetNextVdmCommand->AppName);
+ }
+
+ if (CommandData->PifLen)
+ {
+ CsrAllocateMessagePointer(CaptureBuffer,
+ CommandData->PifLen,
+ (PVOID*)&GetNextVdmCommand->PifFile);
+ }
+
+ if (CommandData->CurDirectoryLen)
+ {
+ CsrAllocateMessagePointer(CaptureBuffer,
+ CommandData->CurDirectoryLen,
+ (PVOID*)&GetNextVdmCommand->CurDirectory);
+ }
+
+ if (CommandData->EnvLen)
+ {
+ CsrAllocateMessagePointer(CaptureBuffer,
+ CommandData->EnvLen,
+ (PVOID*)&GetNextVdmCommand->Env);
+ }
+
+ if (CommandData->DesktopLen)
+ {
+ CsrAllocateMessagePointer(CaptureBuffer,
+ CommandData->DesktopLen,
+ (PVOID*)&GetNextVdmCommand->Desktop);
+ }
+
+ if (CommandData->TitleLen)
+ {
+ CsrAllocateMessagePointer(CaptureBuffer,
+ CommandData->TitleLen,
+ (PVOID*)&GetNextVdmCommand->Title);
+ }
+
+ if (CommandData->ReservedLen)
+ {
+ CsrAllocateMessagePointer(CaptureBuffer,
+ CommandData->ReservedLen,
+ (PVOID*)&GetNextVdmCommand->Reserved);
+ }
+
+ while (TRUE)
+ {
+ /* Call CSRSS */
+ Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
+ CaptureBuffer,
+ CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepGetNextVDMCommand),
+ sizeof(*GetNextVdmCommand));
+
+ /* Exit the waiting loop if we did not receive any event handle */
+ if (GetNextVdmCommand->WaitObjectForVDM == NULL)
+ break;
+
+ /* Wait for the event to become signaled and try again */
+ Status = NtWaitForSingleObject(GetNextVdmCommand->WaitObjectForVDM,
+ FALSE, NULL);
+ if (Status != STATUS_SUCCESS)
+ {
+ /* Fail if we timed out, or if some other error happened */
+ BaseSetLastNTError(Status);
+ goto Cleanup;
+ }
+
+ /* Set the retry flag, clear the exit code, and retry a query */
+ GetNextVdmCommand->VDMState |= VDM_FLAG_RETRY;
+ GetNextVdmCommand->ExitCode = 0;
+ }
+
+ if (!NT_SUCCESS(Status))
+ {
+ if (Status == STATUS_INVALID_PARAMETER)
+ {
+ /*
+ * One of the buffer lengths was less than required. Store the correct ones.
+ * Note that the status code is not STATUS_BUFFER_TOO_SMALL as one would expect,
+ * in order to keep compatibility with Windows 2003 BASESRV.DLL.
+ */
+ CommandData->CmdLen = GetNextVdmCommand->CmdLen;
+ CommandData->AppLen = GetNextVdmCommand->AppLen;
+ CommandData->PifLen = GetNextVdmCommand->PifLen;
+ CommandData->CurDirectoryLen = GetNextVdmCommand->CurDirectoryLen;
+ CommandData->EnvLen = GetNextVdmCommand->EnvLen;
+ CommandData->DesktopLen = GetNextVdmCommand->DesktopLen;
+ CommandData->TitleLen = GetNextVdmCommand->TitleLen;
+ CommandData->ReservedLen = GetNextVdmCommand->ReservedLen;
+ }
+ else
+ {
+ /* Any other failure */
+ CommandData->CmdLen = 0;
+ CommandData->AppLen = 0;
+ CommandData->PifLen = 0;
+ CommandData->CurDirectoryLen = 0;
+ CommandData->EnvLen = 0;
+ CommandData->DesktopLen = 0;
+ CommandData->TitleLen = 0;
+ CommandData->ReservedLen = 0;
+ }
+
+ BaseSetLastNTError(Status);
+ goto Cleanup;
+ }
+
+ /* Write back the standard handles */
+ CommandData->StdIn = GetNextVdmCommand->StdIn;
+ CommandData->StdOut = GetNextVdmCommand->StdOut;
+ CommandData->StdErr = GetNextVdmCommand->StdErr;
+
+ /* Write back the startup info */
+ RtlMoveMemory(&CommandData->StartupInfo,
+ GetNextVdmCommand->StartupInfo,
+ sizeof(*GetNextVdmCommand->StartupInfo));
+
+ if (CommandData->CmdLen)
+ {
+ /* Write back the command line */
+ RtlMoveMemory(CommandData->CmdLine,
+ GetNextVdmCommand->CmdLine,
+ GetNextVdmCommand->CmdLen);
+
+ /* Set the actual length */
+ CommandData->CmdLen = GetNextVdmCommand->CmdLen;
+ }
+
+ if (CommandData->AppLen)
+ {
+ /* Write back the application name */
+ RtlMoveMemory(CommandData->AppName,
+ GetNextVdmCommand->AppName,
+ GetNextVdmCommand->AppLen);
+
+ /* Set the actual length */
+ CommandData->AppLen = GetNextVdmCommand->AppLen;
+ }
+
+ if (CommandData->PifLen)
+ {
+ /* Write back the PIF file name */
+ RtlMoveMemory(CommandData->PifFile,
+ GetNextVdmCommand->PifFile,
+ GetNextVdmCommand->PifLen);
+
+ /* Set the actual length */
+ CommandData->PifLen = GetNextVdmCommand->PifLen;
+ }
+
+ if (CommandData->CurDirectoryLen)
+ {
+ /* Write back the current directory */
+ RtlMoveMemory(CommandData->CurDirectory,
+ GetNextVdmCommand->CurDirectory,
+ GetNextVdmCommand->CurDirectoryLen);
+
+ /* Set the actual length */
+ CommandData->CurDirectoryLen = GetNextVdmCommand->CurDirectoryLen;
+ }
+
+ if (CommandData->EnvLen)
+ {
+ /* Write back the environment */
+ RtlMoveMemory(CommandData->Env,
+ GetNextVdmCommand->Env,
+ GetNextVdmCommand->EnvLen);
+
+ /* Set the actual length */
+ CommandData->EnvLen = GetNextVdmCommand->EnvLen;
+ }
+
+ if (CommandData->DesktopLen)
+ {
+ /* Write back the desktop name */
+ RtlMoveMemory(CommandData->Desktop,
+ GetNextVdmCommand->Desktop,
+ GetNextVdmCommand->DesktopLen);
+
+ /* Set the actual length */
+ CommandData->DesktopLen = GetNextVdmCommand->DesktopLen;
+ }
+
+ if (CommandData->TitleLen)
+ {
+ /* Write back the title */
+ RtlMoveMemory(CommandData->Title,
+ GetNextVdmCommand->Title,
+ GetNextVdmCommand->TitleLen);
+
+ /* Set the actual length */
+ CommandData->TitleLen = GetNextVdmCommand->TitleLen;
+ }
+
+ if (CommandData->ReservedLen)
+ {
+ /* Write back the reserved parameter */
+ RtlMoveMemory(CommandData->Reserved,
+ GetNextVdmCommand->Reserved,
+ GetNextVdmCommand->ReservedLen);
+
+ /* Set the actual length */
+ CommandData->ReservedLen = GetNextVdmCommand->ReservedLen;
+ }
+
+ /* Write the remaining output parameters */
+ CommandData->TaskId = GetNextVdmCommand->iTask;
+ CommandData->CreationFlags = GetNextVdmCommand->dwCreationFlags;
+ CommandData->CodePage = GetNextVdmCommand->CodePage;
+ CommandData->ExitCode = GetNextVdmCommand->ExitCode;
+ CommandData->CurrentDrive = GetNextVdmCommand->CurrentDrive;
+ CommandData->VDMState = GetNextVdmCommand->VDMState;
+ CommandData->ComingFromBat = GetNextVdmCommand->fComingFromBat;
+
+ /* It was successful */
+ Success = TRUE;
+
+Cleanup:
+ if (CaptureBuffer != NULL) CsrFreeCaptureBuffer(CaptureBuffer);
+ return Success;
}
/*
- * @unimplemented
+ * @implemented
*/
DWORD
WINAPI
-GetVDMCurrentDirectories (
- DWORD Unknown0,
- DWORD Unknown1
- )
+GetVDMCurrentDirectories(DWORD cchCurDirs, PCHAR lpszzCurDirs)
{
- STUB;
- return 0;
+ BASE_API_MESSAGE ApiMessage;
+ PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest = &ApiMessage.Data.VDMCurrentDirsRequest;
+ PCSR_CAPTURE_BUFFER CaptureBuffer;
+
+ /* Allocate the capture buffer */
+ CaptureBuffer = CsrAllocateCaptureBuffer(1, cchCurDirs);
+ if (CaptureBuffer == NULL)
+ {
+ BaseSetLastNTError(STATUS_NO_MEMORY);
+ return 0;
+ }
+
+ /* Setup the input parameters */
+ VDMCurrentDirsRequest->cchCurDirs = cchCurDirs;
+ CsrAllocateMessagePointer(CaptureBuffer,
+ cchCurDirs,
+ (PVOID*)&VDMCurrentDirsRequest->lpszzCurDirs);
+
+ /* Call CSRSS */
+ CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
+ CaptureBuffer,
+ CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepGetVDMCurDirs),
+ sizeof(*VDMCurrentDirsRequest));
+
+ /* Set the last error */
+ BaseSetLastNTError(ApiMessage.Status);
+
+ if (NT_SUCCESS(ApiMessage.Status))
+ {
+ /* Copy the result */
+ RtlMoveMemory(lpszzCurDirs, VDMCurrentDirsRequest->lpszzCurDirs, cchCurDirs);
+ }
+
+ /* Free the capture buffer */
+ CsrFreeCaptureBuffer(CaptureBuffer);
+
+ /* Return the size if it was successful, or if the buffer was too small */
+ return (NT_SUCCESS(ApiMessage.Status) || (ApiMessage.Status == STATUS_BUFFER_TOO_SMALL))
+ ? VDMCurrentDirsRequest->cchCurDirs : 0;
}
/*
- * @unimplemented
+ * @implemented (undocumented)
*/
BOOL
WINAPI
-RegisterConsoleVDM (
- DWORD Unknown0,
- DWORD Unknown1,
- DWORD Unknown2,
- DWORD Unknown3,
- DWORD Unknown4,
- DWORD Unknown5,
- DWORD Unknown6,
- DWORD Unknown7,
- DWORD Unknown8,
- DWORD Unknown9,
- DWORD Unknown10
- )
+RegisterConsoleVDM(IN DWORD dwRegisterFlags,
+ IN HANDLE hStartHardwareEvent,
+ IN HANDLE hEndHardwareEvent,
+ IN HANDLE hErrorHardwareEvent,
+ IN DWORD dwUnusedVar,
+ OUT LPDWORD lpVideoStateLength,
+ OUT PVOID* lpVideoState, // PVIDEO_HARDWARE_STATE_HEADER*
+ IN PVOID lpUnusedBuffer,
+ IN DWORD dwUnusedBufferLength,
+ IN COORD dwVDMBufferSize,
+ OUT PVOID* lpVDMBuffer)
{
- STUB;
- return FALSE;
+ BOOL Success;
+ CONSOLE_API_MESSAGE ApiMessage;
+ PCONSOLE_REGISTERVDM RegisterVDMRequest = &ApiMessage.Data.RegisterVDMRequest;
+ PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
+
+ /* Set up the data to send to the Console Server */
+ RegisterVDMRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
+ RegisterVDMRequest->RegisterFlags = dwRegisterFlags;
+
+ if (dwRegisterFlags != 0)
+ {
+ RegisterVDMRequest->StartHardwareEvent = hStartHardwareEvent;
+ RegisterVDMRequest->EndHardwareEvent = hEndHardwareEvent;
+ RegisterVDMRequest->ErrorHardwareEvent = hErrorHardwareEvent;
+
+ RegisterVDMRequest->VDMBufferSize = dwVDMBufferSize;
+
+#if 0
+ RegisterVDMRequest->UnusedBufferLength = dwUnusedBufferLength;
+
+ /* Allocate a Capture Buffer */
+ CaptureBuffer = CsrAllocateCaptureBuffer(1, dwUnusedBufferLength);
+ if (CaptureBuffer == NULL)
+ {
+ DPRINT1("CsrAllocateCaptureBuffer failed!\n");
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+
+ /* Capture the buffer to write */
+ CsrCaptureMessageBuffer(CaptureBuffer,
+ (PVOID)lpUnusedBuffer,
+ dwUnusedBufferLength,
+ (PVOID*)&RegisterVDMRequest->UnusedBuffer);
+#endif
+ }
+ else
+ {
+ // CaptureBuffer = NULL;
+ }
+
+ /* Call the server */
+ CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
+ CaptureBuffer,
+ CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepRegisterVDM),
+ sizeof(*RegisterVDMRequest));
+
+ /* Check for success */
+ Success = NT_SUCCESS(ApiMessage.Status);
+
+ /* Release the capture buffer if needed */
+ if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
+
+ /* Retrieve the results */
+ if (Success)
+ {
+ if (dwRegisterFlags != 0)
+ {
+ _SEH2_TRY
+ {
+ *lpVideoStateLength = RegisterVDMRequest->VideoStateLength;
+ *lpVideoState = RegisterVDMRequest->VideoState;
+ *lpVDMBuffer = RegisterVDMRequest->VDMBuffer;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ SetLastError(ERROR_INVALID_ACCESS);
+ Success = FALSE;
+ }
+ _SEH2_END;
+ }
+ }
+ else
+ {
+ BaseSetLastNTError(ApiMessage.Status);
+ }
+
+ /* Return success status */
+ return Success;
}
/*
- * @unimplemented
+ * @implemented
*/
BOOL
WINAPI
-SetVDMCurrentDirectories (
- DWORD Unknown0,
- DWORD Unknown1
- )
+SetVDMCurrentDirectories(DWORD cchCurDirs, PCHAR lpszzCurDirs)
{
- STUB;
- return FALSE;
+ BASE_API_MESSAGE ApiMessage;
+ PBASE_GETSET_VDM_CURDIRS VDMCurrentDirsRequest = &ApiMessage.Data.VDMCurrentDirsRequest;
+ PCSR_CAPTURE_BUFFER CaptureBuffer;
+
+ /* Allocate the capture buffer */
+ CaptureBuffer = CsrAllocateCaptureBuffer(1, cchCurDirs);
+ if (CaptureBuffer == NULL)
+ {
+ BaseSetLastNTError(STATUS_NO_MEMORY);
+ return FALSE;
+ }
+
+ /* Setup the input parameters */
+ VDMCurrentDirsRequest->cchCurDirs = cchCurDirs;
+ CsrCaptureMessageBuffer(CaptureBuffer,
+ lpszzCurDirs,
+ cchCurDirs,
+ (PVOID*)&VDMCurrentDirsRequest->lpszzCurDirs);
+
+ /* Call CSRSS */
+ CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
+ CaptureBuffer,
+ CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepSetVDMCurDirs),
+ sizeof(*VDMCurrentDirsRequest));
+
+ /* Free the capture buffer */
+ CsrFreeCaptureBuffer(CaptureBuffer);
+
+ /* Set the last error */
+ BaseSetLastNTError(ApiMessage.Status);
+
+ return NT_SUCCESS(ApiMessage.Status) ? TRUE : FALSE;
}
/*
/*
* @unimplemented
*/
-DWORD
+BOOL
WINAPI
-VDMOperationStarted (
- DWORD Unknown0
- )
+VDMOperationStarted(IN ULONG Unknown0)
{
- STUB;
- return 0;
+ DPRINT1("VDMOperationStarted(%d)\n", Unknown0);
+
+ return BaseUpdateVDMEntry(VdmEntryUpdateControlCHandler,
+ NULL,
+ 0,
+ Unknown0);
}