From 28b957e9706fc1a55e81101ce20767cb2985cf98 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Sat, 12 Sep 2015 16:23:32 +0000 Subject: [PATCH 1/1] [KERNEL32] GetNextVDMCommand function: - Avoid using deep nested levels of indentation. - Fix the error check conditions (+ status value) for the CsrClientCallServer call to make it compatible with what windows' basesrv can return to us. [BASESRV] - Remove some useless "NTAPI" from functions. - Factor out some code used for creating and destroying console records, and for the destruction of the pair of event handles. - Use "IsListEmpty" when needed. - Fix BaseSrvFillCommandInfo so that it returns the needed lengths (even if the user-given lengths are zero) and set the expected status error in case the buffer lenghts are too small (not STATUS_BUFFER_TOO_SMALL but STATUS_INVALID_PARAMETER because it's what kernel32 error check expects, for windows compat; see above). - Fix initialization of new DOS records: no need to create a new one if there is one already free (status VDM_READY). - Fix the loop that searches for a valid DOS record containing command information available as well as the conditions in which case our caller needs to wait in GetNextVDMCommand call. NOTE: The internal state flags of the DOS records have normally nothing to do with the VDM state flags we report back to the user. CORE-8247 CORE-9711 CORE-9773 svn path=/trunk/; revision=69201 --- reactos/dll/win32/kernel32/client/vdm.c | 560 +++++++++++++----------- reactos/subsystems/win/basesrv/vdm.c | 471 +++++++++++--------- reactos/subsystems/win/basesrv/vdm.h | 19 +- 3 files changed, 574 insertions(+), 476 deletions(-) diff --git a/reactos/dll/win32/kernel32/client/vdm.c b/reactos/dll/win32/kernel32/client/vdm.c index 5f37d7a69d1..0164cb44385 100644 --- a/reactos/dll/win32/kernel32/client/vdm.c +++ b/reactos/dll/win32/kernel32/client/vdm.c @@ -1411,8 +1411,8 @@ BOOL WINAPI GetNextVDMCommand(PVDM_COMMAND_INFO CommandData) { + BOOL Success = FALSE; NTSTATUS Status; - BOOL Result = FALSE; BASE_API_MESSAGE ApiMessage; PBASE_GET_NEXT_VDM_COMMAND GetNextVdmCommand = &ApiMessage.Data.GetNextVDMCommandRequest; PBASE_IS_FIRST_VDM IsFirstVdm = &ApiMessage.Data.IsFirstVDMRequest; @@ -1420,311 +1420,343 @@ GetNextVDMCommand(PVDM_COMMAND_INFO CommandData) PCSR_CAPTURE_BUFFER CaptureBuffer = NULL; ULONG NumStrings = 0; - if (CommandData != NULL) + /* + * Special case to test whether the VDM is the first one. + */ + if (CommandData == NULL) { - if ((CommandData->VDMState == VDM_INC_REENTER_COUNT) - || (CommandData->VDMState == VDM_DEC_REENTER_COUNT)) + /* Call CSRSS */ + CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + NULL, + CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepIsFirstVDM), + sizeof(*IsFirstVdm)); + if (!NT_SUCCESS(ApiMessage.Status)) { - /* Setup the input parameters */ - SetReenterCount->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; - SetReenterCount->fIncDec = CommandData->VDMState; - - /* Call CSRSS */ - Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, - NULL, - CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepSetReenterCount), - sizeof(*SetReenterCount)); - BaseSetLastNTError(Status); - Result = NT_SUCCESS(Status); + BaseSetLastNTError(ApiMessage.Status); + return FALSE; } - else + + /* 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)) { - /* Clear the structure */ - ZeroMemory(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(STARTUPINFOA)); - if (CaptureBuffer == NULL) - { - BaseSetLastNTError(STATUS_NO_MEMORY); - goto Cleanup; - } + BaseSetLastNTError(ApiMessage.Status); + return FALSE; + } - /* Allocate memory for the startup info */ - CsrAllocateMessagePointer(CaptureBuffer, - sizeof(STARTUPINFOA), - (PVOID*)&GetNextVdmCommand->StartupInfo); + return TRUE; + } - if (CommandData->CmdLen) - { - /* Allocate memory for the command line */ - CsrAllocateMessagePointer(CaptureBuffer, - CommandData->CmdLen, - (PVOID*)&GetNextVdmCommand->CmdLine); - } + /* + * 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! - if (CommandData->AppLen) - { - /* Allocate memory for the application name */ - CsrAllocateMessagePointer(CaptureBuffer, - CommandData->AppLen, - (PVOID*)&GetNextVdmCommand->AppName); - } + /* + * Regular case. + */ - if (CommandData->PifLen) - { - /* Allocate memory for the PIF file name */ - CsrAllocateMessagePointer(CaptureBuffer, - CommandData->PifLen, - (PVOID*)&GetNextVdmCommand->PifFile); - } + /* Clear the structure */ + RtlZeroMemory(GetNextVdmCommand, sizeof(*GetNextVdmCommand)); - if (CommandData->CurDirectoryLen) - { - /* Allocate memory for the current directory */ - CsrAllocateMessagePointer(CaptureBuffer, - CommandData->CurDirectoryLen, - (PVOID*)&GetNextVdmCommand->CurDirectory); - } + /* 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++; - if (CommandData->EnvLen) - { - /* Allocate memory for the environment */ - CsrAllocateMessagePointer(CaptureBuffer, - CommandData->EnvLen, - (PVOID*)&GetNextVdmCommand->Env); - } + /* 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; + } - if (CommandData->DesktopLen) - { - /* Allocate memory for the desktop name */ - CsrAllocateMessagePointer(CaptureBuffer, - CommandData->DesktopLen, - (PVOID*)&GetNextVdmCommand->Desktop); - } + /* Capture the data */ - if (CommandData->TitleLen) - { - /* Allocate memory for the title */ - CsrAllocateMessagePointer(CaptureBuffer, - CommandData->TitleLen, - (PVOID*)&GetNextVdmCommand->Title); - } + CsrAllocateMessagePointer(CaptureBuffer, + sizeof(*GetNextVdmCommand->StartupInfo), + (PVOID*)&GetNextVdmCommand->StartupInfo); - if (CommandData->ReservedLen) - { - /* Allocate memory for the reserved parameter */ - CsrAllocateMessagePointer(CaptureBuffer, - CommandData->ReservedLen, - (PVOID*)&GetNextVdmCommand->Reserved); - } + if (CommandData->CmdLen) + { + CsrAllocateMessagePointer(CaptureBuffer, + CommandData->CmdLen, + (PVOID*)&GetNextVdmCommand->CmdLine); + } - do - { - /* Call CSRSS */ - Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, - CaptureBuffer, - CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepGetNextVDMCommand), - sizeof(*GetNextVdmCommand)); - if (!NT_SUCCESS(Status)) - { - /* Store the correct lengths */ - 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; - - BaseSetLastNTError(Status); - goto Cleanup; - } + if (CommandData->AppLen) + { + CsrAllocateMessagePointer(CaptureBuffer, + CommandData->AppLen, + (PVOID*)&GetNextVdmCommand->AppName); + } - /* Did we receive an event handle? */ - if (GetNextVdmCommand->WaitObjectForVDM != NULL) - { - /* Wait for the event to become signaled and try again */ - Status = NtWaitForSingleObject(GetNextVdmCommand->WaitObjectForVDM, - FALSE, - NULL); - if (!NT_SUCCESS(Status)) - { - BaseSetLastNTError(Status); - goto Cleanup; - } + if (CommandData->PifLen) + { + CsrAllocateMessagePointer(CaptureBuffer, + CommandData->PifLen, + (PVOID*)&GetNextVdmCommand->PifFile); + } - /* Set the retry flag and clear the exit code */ - GetNextVdmCommand->VDMState |= VDM_FLAG_RETRY; - GetNextVdmCommand->ExitCode = 0; - } - } - while (GetNextVdmCommand->WaitObjectForVDM != NULL); + if (CommandData->CurDirectoryLen) + { + CsrAllocateMessagePointer(CaptureBuffer, + CommandData->CurDirectoryLen, + (PVOID*)&GetNextVdmCommand->CurDirectory); + } - /* Write back the standard handles */ - CommandData->StdIn = GetNextVdmCommand->StdIn; - CommandData->StdOut = GetNextVdmCommand->StdOut; - CommandData->StdErr = GetNextVdmCommand->StdErr; + if (CommandData->EnvLen) + { + CsrAllocateMessagePointer(CaptureBuffer, + CommandData->EnvLen, + (PVOID*)&GetNextVdmCommand->Env); + } - /* Write back the startup info */ - RtlMoveMemory(&CommandData->StartupInfo, - GetNextVdmCommand->StartupInfo, - sizeof(STARTUPINFOA)); + if (CommandData->DesktopLen) + { + CsrAllocateMessagePointer(CaptureBuffer, + CommandData->DesktopLen, + (PVOID*)&GetNextVdmCommand->Desktop); + } - if (CommandData->CmdLen) - { - /* Write back the command line */ - RtlMoveMemory(CommandData->CmdLine, - GetNextVdmCommand->CmdLine, - GetNextVdmCommand->CmdLen); + if (CommandData->TitleLen) + { + CsrAllocateMessagePointer(CaptureBuffer, + CommandData->TitleLen, + (PVOID*)&GetNextVdmCommand->Title); + } - /* Set the actual length */ - CommandData->CmdLen = GetNextVdmCommand->CmdLen; - } + if (CommandData->ReservedLen) + { + CsrAllocateMessagePointer(CaptureBuffer, + CommandData->ReservedLen, + (PVOID*)&GetNextVdmCommand->Reserved); + } - if (CommandData->AppLen) - { - /* Write back the application name */ - RtlMoveMemory(CommandData->AppName, - GetNextVdmCommand->AppName, - GetNextVdmCommand->AppLen); + while (TRUE) + { + /* Call CSRSS */ + Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + CaptureBuffer, + CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepGetNextVDMCommand), + sizeof(*GetNextVdmCommand)); - /* Set the actual length */ - CommandData->AppLen = GetNextVdmCommand->AppLen; - } + /* Exit the waiting loop if we did not receive any event handle */ + if (GetNextVdmCommand->WaitObjectForVDM == NULL) + break; - if (CommandData->PifLen) - { - /* Write back the PIF file name */ - RtlMoveMemory(CommandData->PifFile, - GetNextVdmCommand->PifFile, - GetNextVdmCommand->PifLen); + /* 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 actual length */ - CommandData->PifLen = GetNextVdmCommand->PifLen; - } + /* Set the retry flag, clear the exit code, and retry a query */ + GetNextVdmCommand->VDMState |= VDM_FLAG_RETRY; + GetNextVdmCommand->ExitCode = 0; + } - if (CommandData->CurDirectoryLen) - { - /* Write back the current directory */ - RtlMoveMemory(CommandData->CurDirectory, - GetNextVdmCommand->CurDirectory, - GetNextVdmCommand->CurDirectoryLen); + 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; + } - /* Set the actual length */ - CommandData->CurDirectoryLen = GetNextVdmCommand->CurDirectoryLen; - } + BaseSetLastNTError(Status); + goto Cleanup; + } - if (CommandData->EnvLen) - { - /* Write back the environment */ - RtlMoveMemory(CommandData->Env, - GetNextVdmCommand->Env, - GetNextVdmCommand->EnvLen); + /* Write back the standard handles */ + CommandData->StdIn = GetNextVdmCommand->StdIn; + CommandData->StdOut = GetNextVdmCommand->StdOut; + CommandData->StdErr = GetNextVdmCommand->StdErr; - /* Set the actual length */ - CommandData->EnvLen = GetNextVdmCommand->EnvLen; - } + /* Write back the startup info */ + RtlMoveMemory(&CommandData->StartupInfo, + GetNextVdmCommand->StartupInfo, + sizeof(*GetNextVdmCommand->StartupInfo)); - if (CommandData->DesktopLen) - { - /* Write back the desktop name */ - RtlMoveMemory(CommandData->Desktop, - GetNextVdmCommand->Desktop, - GetNextVdmCommand->DesktopLen); + if (CommandData->CmdLen) + { + /* Write back the command line */ + RtlMoveMemory(CommandData->CmdLine, + GetNextVdmCommand->CmdLine, + GetNextVdmCommand->CmdLen); - /* Set the actual length */ - CommandData->DesktopLen = GetNextVdmCommand->DesktopLen; - } + /* Set the actual length */ + CommandData->CmdLen = GetNextVdmCommand->CmdLen; + } - if (CommandData->TitleLen) - { - /* Write back the title */ - RtlMoveMemory(CommandData->Title, - GetNextVdmCommand->Title, - GetNextVdmCommand->TitleLen); + if (CommandData->AppLen) + { + /* Write back the application name */ + RtlMoveMemory(CommandData->AppName, + GetNextVdmCommand->AppName, + GetNextVdmCommand->AppLen); - /* Set the actual length */ - CommandData->TitleLen = GetNextVdmCommand->TitleLen; - } + /* Set the actual length */ + CommandData->AppLen = GetNextVdmCommand->AppLen; + } - if (CommandData->ReservedLen) - { - /* Write back the reserved parameter */ - RtlMoveMemory(CommandData->Reserved, - GetNextVdmCommand->Reserved, - GetNextVdmCommand->ReservedLen); + if (CommandData->PifLen) + { + /* Write back the PIF file name */ + RtlMoveMemory(CommandData->PifFile, + GetNextVdmCommand->PifFile, + GetNextVdmCommand->PifLen); - /* Set the actual length */ - CommandData->ReservedLen = GetNextVdmCommand->ReservedLen; - } + /* Set the actual length */ + CommandData->PifLen = GetNextVdmCommand->PifLen; + } - /* 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 */ - Result = TRUE; - } + if (CommandData->CurDirectoryLen) + { + /* Write back the current directory */ + RtlMoveMemory(CommandData->CurDirectory, + GetNextVdmCommand->CurDirectory, + GetNextVdmCommand->CurDirectoryLen); + + /* Set the actual length */ + CommandData->CurDirectoryLen = GetNextVdmCommand->CurDirectoryLen; } - else + + if (CommandData->EnvLen) { - /* Call CSRSS */ - Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, - NULL, - CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepIsFirstVDM), - sizeof(*IsFirstVdm)); - if (!NT_SUCCESS(Status)) - { - BaseSetLastNTError(Status); - goto Cleanup; - } + /* Write back the environment */ + RtlMoveMemory(CommandData->Env, + GetNextVdmCommand->Env, + GetNextVdmCommand->EnvLen); - /* Return TRUE if this is the first VDM */ - Result = IsFirstVdm->FirstVDM; + /* 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 Result; + return Success; } diff --git a/reactos/subsystems/win/basesrv/vdm.c b/reactos/subsystems/win/basesrv/vdm.c index 2493120fdf8..ca9c33e7e7e 100644 --- a/reactos/subsystems/win/basesrv/vdm.c +++ b/reactos/subsystems/win/basesrv/vdm.c @@ -22,9 +22,31 @@ LIST_ENTRY VDMConsoleListHead; RTL_CRITICAL_SECTION DosCriticalSection; RTL_CRITICAL_SECTION WowCriticalSection; -/* FUNCTIONS ******************************************************************/ +/* HELPER FUNCTIONS ***********************************************************/ -NTSTATUS NTAPI BaseSrvGetConsoleRecord(HANDLE ConsoleHandle, PVDM_CONSOLE_RECORD *Record) +PVDM_CONSOLE_RECORD BaseSrvCreateConsoleRecord(VOID) +{ + PVDM_CONSOLE_RECORD ConsoleRecord; + + ConsoleRecord = RtlAllocateHeap(BaseSrvHeap, HEAP_ZERO_MEMORY, + sizeof(VDM_CONSOLE_RECORD)); + if (ConsoleRecord == NULL) + return NULL; + + /* Initialize the console record */ + ConsoleRecord->ConsoleHandle = NULL; + ConsoleRecord->ProcessHandle = NULL; + ConsoleRecord->ServerEvent = ConsoleRecord->ClientEvent = NULL; + ConsoleRecord->ReenterCount = 0; + ConsoleRecord->CurrentDirs = NULL; + ConsoleRecord->CurDirsLength = 0; + ConsoleRecord->SessionId = 0; + InitializeListHead(&ConsoleRecord->DosListHead); + + return ConsoleRecord; +} + +NTSTATUS BaseSrvGetConsoleRecord(HANDLE ConsoleHandle, PVDM_CONSOLE_RECORD *Record) { PLIST_ENTRY i; PVDM_CONSOLE_RECORD CurrentRecord = NULL; @@ -46,7 +68,31 @@ NTSTATUS NTAPI BaseSrvGetConsoleRecord(HANDLE ConsoleHandle, PVDM_CONSOLE_RECORD return CurrentRecord ? STATUS_SUCCESS : STATUS_NOT_FOUND; } -NTSTATUS NTAPI GetConsoleRecordBySessionId(ULONG TaskId, PVDM_CONSOLE_RECORD *Record) +VOID BaseSrvDestroyConsoleRecord(PVDM_CONSOLE_RECORD ConsoleRecord) +{ + if (ConsoleRecord->CurrentDirs != NULL) + { + /* Free the current directories */ + RtlFreeHeap(BaseSrvHeap, 0, ConsoleRecord->CurrentDirs); + ConsoleRecord->CurrentDirs = NULL; + ConsoleRecord->CurDirsLength = 0; + } + + /* Close the process handle */ + if (ConsoleRecord->ProcessHandle) + NtClose(ConsoleRecord->ProcessHandle); + + /* Close the event handle */ + if (ConsoleRecord->ServerEvent) + NtClose(ConsoleRecord->ServerEvent); + + /* Remove the console record */ + // RemoveEntryList(&ConsoleRecord->Entry); + RtlFreeHeap(BaseSrvHeap, 0, ConsoleRecord); + +} + +NTSTATUS GetConsoleRecordBySessionId(ULONG TaskId, PVDM_CONSOLE_RECORD *Record) { PLIST_ENTRY i; PVDM_CONSOLE_RECORD CurrentRecord = NULL; @@ -65,7 +111,7 @@ NTSTATUS NTAPI GetConsoleRecordBySessionId(ULONG TaskId, PVDM_CONSOLE_RECORD *Re return CurrentRecord ? STATUS_SUCCESS : STATUS_NOT_FOUND; } -ULONG NTAPI GetNextDosSesId(VOID) +ULONG GetNextDosSesId(VOID) { ULONG SessionId; PLIST_ENTRY i; @@ -94,7 +140,7 @@ ULONG NTAPI GetNextDosSesId(VOID) return SessionId; } -BOOLEAN NTAPI BaseSrvIsVdmAllowed(VOID) +BOOLEAN BaseSrvIsVdmAllowed(VOID) { NTSTATUS Status; BOOLEAN VdmAllowed = TRUE; @@ -191,7 +237,7 @@ BOOLEAN NTAPI BaseSrvIsVdmAllowed(VOID) return VdmAllowed; } -NTSTATUS NTAPI BaseSrvCreatePairWaitHandles(PHANDLE ServerEvent, PHANDLE ClientEvent) +NTSTATUS BaseSrvCreatePairWaitHandles(PHANDLE ServerEvent, PHANDLE ClientEvent) { NTSTATUS Status; @@ -212,7 +258,27 @@ NTSTATUS NTAPI BaseSrvCreatePairWaitHandles(PHANDLE ServerEvent, PHANDLE ClientE return Status; } -VOID NTAPI BaseSrvFreeVDMInfo(PVDM_COMMAND_INFO CommandInfo) +VOID BaseSrvDestroyPairWaitHandles(HANDLE ServerEvent, HANDLE ClientEvent) +{ + if (ServerEvent) NtClose(ServerEvent); + if (ClientEvent) + { + /* Close the remote handle */ + NtDuplicateObject(CsrGetClientThread()->Process->ProcessHandle, + ClientEvent, + NULL, + NULL, + 0, + 0, + DUPLICATE_CLOSE_SOURCE); + } +} + +/* WOW SUPPORT FUNCTIONS ******************************************************/ + +/* DOS SUPPORT FUNCTIONS ******************************************************/ + +VOID BaseSrvFreeVDMInfo(PVDM_COMMAND_INFO CommandInfo) { /* Free the allocated structure members */ if (CommandInfo->CmdLine != NULL) RtlFreeHeap(BaseSrvHeap, 0, CommandInfo->CmdLine); @@ -228,9 +294,7 @@ VOID NTAPI BaseSrvFreeVDMInfo(PVDM_COMMAND_INFO CommandInfo) RtlFreeHeap(BaseSrvHeap, 0, CommandInfo); } -VOID -NTAPI -BaseSrvCleanupVDMResources(IN PCSR_PROCESS CsrProcess) +VOID BaseSrvCleanupVDMResources(IN PCSR_PROCESS CsrProcess) { ULONG ProcessId = HandleToUlong(CsrProcess->ClientId.UniqueProcess); PVDM_CONSOLE_RECORD ConsoleRecord = NULL; @@ -241,22 +305,33 @@ BaseSrvCleanupVDMResources(IN PCSR_PROCESS CsrProcess) RtlEnterCriticalSection(&DosCriticalSection); /* Search for a record that has the same process handle */ - for (i = VDMConsoleListHead.Flink; i != &VDMConsoleListHead; i = i->Flink) + i = VDMConsoleListHead.Flink; + while (i != &VDMConsoleListHead) { ConsoleRecord = CONTAINING_RECORD(i, VDM_CONSOLE_RECORD, Entry); + i = i->Flink; if (ConsoleRecord->ProcessId == ProcessId) { + if (ConsoleRecord->ServerEvent) + { + NtClose(ConsoleRecord->ServerEvent); + ConsoleRecord->ServerEvent = NULL; + } + /* Cleanup the DOS records */ - while (ConsoleRecord->DosListHead.Flink != &ConsoleRecord->DosListHead) + while (!IsListEmpty(&ConsoleRecord->DosListHead)) { DosRecord = CONTAINING_RECORD(ConsoleRecord->DosListHead.Flink, - VDM_DOS_RECORD, - Entry); + VDM_DOS_RECORD, Entry); /* Set the event and close it */ - NtSetEvent(DosRecord->ServerEvent, NULL); - NtClose(DosRecord->ServerEvent); + if (DosRecord->ServerEvent) + { + NtSetEvent(DosRecord->ServerEvent, NULL); + NtClose(DosRecord->ServerEvent); + DosRecord->ServerEvent = NULL; + } /* Remove the DOS entry */ if (DosRecord->CommandInfo) BaseSrvFreeVDMInfo(DosRecord->CommandInfo); @@ -264,24 +339,9 @@ BaseSrvCleanupVDMResources(IN PCSR_PROCESS CsrProcess) RtlFreeHeap(BaseSrvHeap, 0, DosRecord); } - if (ConsoleRecord->CurrentDirs != NULL) - { - /* Free the current directories */ - RtlFreeHeap(BaseSrvHeap, 0, ConsoleRecord->CurrentDirs); - ConsoleRecord->CurrentDirs = NULL; - ConsoleRecord->CurDirsLength = 0; - } - - /* Close the process handle */ - if (ConsoleRecord->ProcessHandle) NtClose(ConsoleRecord->ProcessHandle); - - /* Close the event handle */ - if (ConsoleRecord->ServerEvent) NtClose(ConsoleRecord->ServerEvent); - /* Remove the console record */ - i = i->Blink; RemoveEntryList(&ConsoleRecord->Entry); - RtlFreeHeap(BaseSrvHeap, 0, ConsoleRecord); + BaseSrvDestroyConsoleRecord(ConsoleRecord); } } @@ -289,7 +349,7 @@ BaseSrvCleanupVDMResources(IN PCSR_PROCESS CsrProcess) RtlLeaveCriticalSection(&DosCriticalSection); } -BOOLEAN NTAPI BaseSrvCopyCommand(PBASE_CHECK_VDM CheckVdmRequest, PVDM_DOS_RECORD DosRecord) +BOOLEAN BaseSrvCopyCommand(PBASE_CHECK_VDM CheckVdmRequest, PVDM_DOS_RECORD DosRecord) { BOOLEAN Success = FALSE; PVDM_COMMAND_INFO CommandInfo = NULL; @@ -436,8 +496,8 @@ Cleanup: return Success; } -NTSTATUS NTAPI BaseSrvFillCommandInfo(PVDM_COMMAND_INFO CommandInfo, - PBASE_GET_NEXT_VDM_COMMAND Message) +NTSTATUS BaseSrvFillCommandInfo(PVDM_COMMAND_INFO CommandInfo, + PBASE_GET_NEXT_VDM_COMMAND Message) { NTSTATUS Status = STATUS_SUCCESS; @@ -453,116 +513,84 @@ NTSTATUS NTAPI BaseSrvFillCommandInfo(PVDM_COMMAND_INFO CommandInfo, Message->VDMState = CommandInfo->VDMState; Message->fComingFromBat = CommandInfo->ComingFromBat; - if (CommandInfo->CmdLen && Message->CmdLen) + if (Message->CmdLen >= CommandInfo->CmdLen) { - if (Message->CmdLen >= CommandInfo->CmdLen) - { - /* Copy the command line */ - RtlMoveMemory(Message->CmdLine, CommandInfo->CmdLine, CommandInfo->CmdLen); - } - else Status = STATUS_BUFFER_TOO_SMALL; - - Message->CmdLen = CommandInfo->CmdLen; + /* Copy the command line */ + RtlMoveMemory(Message->CmdLine, CommandInfo->CmdLine, CommandInfo->CmdLen); } + else Status = STATUS_INVALID_PARAMETER; + Message->CmdLen = CommandInfo->CmdLen; - if (CommandInfo->AppLen && Message->AppLen) + if (Message->AppLen >= CommandInfo->AppLen) { - if (Message->AppLen >= CommandInfo->AppLen) - { - /* Copy the application name */ - RtlMoveMemory(Message->AppName, CommandInfo->AppName, CommandInfo->AppLen); - } - else Status = STATUS_BUFFER_TOO_SMALL; - - Message->AppLen = CommandInfo->AppLen; + /* Copy the application name */ + RtlMoveMemory(Message->AppName, CommandInfo->AppName, CommandInfo->AppLen); } + else Status = STATUS_INVALID_PARAMETER; + Message->AppLen = CommandInfo->AppLen; - if (CommandInfo->PifLen && Message->PifLen) + if (Message->PifLen >= CommandInfo->PifLen) { - if (Message->PifLen >= CommandInfo->PifLen) - { - /* Copy the PIF file name */ - RtlMoveMemory(Message->PifFile, CommandInfo->PifFile, CommandInfo->PifLen); - } - else Status = STATUS_BUFFER_TOO_SMALL; - - Message->PifLen = CommandInfo->PifLen; + /* Copy the PIF file name */ + RtlMoveMemory(Message->PifFile, CommandInfo->PifFile, CommandInfo->PifLen); } + else Status = STATUS_INVALID_PARAMETER; + Message->PifLen = CommandInfo->PifLen; - if (CommandInfo->CurDirectoryLen && Message->CurDirectoryLen) + if (Message->CurDirectoryLen >= CommandInfo->CurDirectoryLen) { - if (Message->CurDirectoryLen >= CommandInfo->CurDirectoryLen) - { - /* Copy the current directory */ - RtlMoveMemory(Message->CurDirectory, CommandInfo->CurDirectory, CommandInfo->CurDirectoryLen); - } - else Status = STATUS_BUFFER_TOO_SMALL; - - Message->CurDirectoryLen = CommandInfo->CurDirectoryLen; + /* Copy the current directory */ + RtlMoveMemory(Message->CurDirectory, CommandInfo->CurDirectory, CommandInfo->CurDirectoryLen); } + else Status = STATUS_INVALID_PARAMETER; + Message->CurDirectoryLen = CommandInfo->CurDirectoryLen; - if (CommandInfo->EnvLen && Message->EnvLen) + if (Message->EnvLen >= CommandInfo->EnvLen) { - if (Message->EnvLen >= CommandInfo->EnvLen) - { - /* Copy the environment */ - RtlMoveMemory(Message->Env, CommandInfo->Env, CommandInfo->EnvLen); - } - else Status = STATUS_BUFFER_TOO_SMALL; - - Message->EnvLen = CommandInfo->EnvLen; + /* Copy the environment */ + RtlMoveMemory(Message->Env, CommandInfo->Env, CommandInfo->EnvLen); } + else Status = STATUS_INVALID_PARAMETER; + Message->EnvLen = CommandInfo->EnvLen; /* Copy the startup info */ RtlMoveMemory(Message->StartupInfo, &CommandInfo->StartupInfo, sizeof(STARTUPINFOA)); - if (CommandInfo->DesktopLen && Message->DesktopLen) + if (Message->DesktopLen >= CommandInfo->DesktopLen) { - if (Message->DesktopLen >= CommandInfo->DesktopLen) - { - /* Copy the desktop name */ - RtlMoveMemory(Message->Desktop, CommandInfo->Desktop, CommandInfo->DesktopLen); - } - else Status = STATUS_BUFFER_TOO_SMALL; - - Message->DesktopLen = CommandInfo->DesktopLen; + /* Copy the desktop name */ + RtlMoveMemory(Message->Desktop, CommandInfo->Desktop, CommandInfo->DesktopLen); } + else Status = STATUS_INVALID_PARAMETER; + Message->DesktopLen = CommandInfo->DesktopLen; - if (CommandInfo->TitleLen && Message->TitleLen) + if (Message->TitleLen >= CommandInfo->TitleLen) { - if (Message->TitleLen >= CommandInfo->TitleLen) - { - /* Copy the title */ - RtlMoveMemory(Message->Title, CommandInfo->Title, CommandInfo->TitleLen); - } - else Status = STATUS_BUFFER_TOO_SMALL; - - Message->TitleLen = CommandInfo->TitleLen; + /* Copy the title */ + RtlMoveMemory(Message->Title, CommandInfo->Title, CommandInfo->TitleLen); } + else Status = STATUS_INVALID_PARAMETER; + Message->TitleLen = CommandInfo->TitleLen; - if (CommandInfo->ReservedLen && Message->ReservedLen) + if (Message->ReservedLen >= CommandInfo->ReservedLen) { - if (Message->ReservedLen >= CommandInfo->ReservedLen) - { - /* Copy the reserved parameter */ - RtlMoveMemory(Message->Reserved, CommandInfo->Reserved, CommandInfo->ReservedLen); - } - else Status = STATUS_BUFFER_TOO_SMALL; - - Message->ReservedLen = CommandInfo->ReservedLen; + /* Copy the reserved parameter */ + RtlMoveMemory(Message->Reserved, CommandInfo->Reserved, CommandInfo->ReservedLen); } + else Status = STATUS_INVALID_PARAMETER; + Message->ReservedLen = CommandInfo->ReservedLen; return Status; } -VOID NTAPI BaseInitializeVDM(VOID) +VOID BaseInitializeVDM(VOID) { /* Initialize the list head */ InitializeListHead(&VDMConsoleListHead); - /* Initialize the critical section */ + /* Initialize the critical sections */ RtlInitializeCriticalSection(&DosCriticalSection); RtlInitializeCriticalSection(&WowCriticalSection); } @@ -577,6 +605,7 @@ CSR_API(BaseSrvCheckVDM) PVDM_CONSOLE_RECORD ConsoleRecord = NULL; PVDM_DOS_RECORD DosRecord = NULL; BOOLEAN NewConsoleRecord = FALSE; + BOOLEAN NewDosRecord = FALSE; /* Don't do anything if the VDM has been disabled in the registry */ if (!BaseSrvIsVdmAllowed()) return STATUS_VDM_DISALLOWED; @@ -627,53 +656,75 @@ CSR_API(BaseSrvCheckVDM) /* Get the console record */ Status = BaseSrvGetConsoleRecord(CheckVdmRequest->ConsoleHandle, &ConsoleRecord); - if (!NT_SUCCESS(Status)) { /* Allocate a new console record */ - ConsoleRecord = (PVDM_CONSOLE_RECORD)RtlAllocateHeap(BaseSrvHeap, - HEAP_ZERO_MEMORY, - sizeof(VDM_CONSOLE_RECORD)); + ConsoleRecord = BaseSrvCreateConsoleRecord(); if (ConsoleRecord == NULL) { Status = STATUS_NO_MEMORY; goto Cleanup; } - /* Remember that the console record was allocated here */ - NewConsoleRecord = TRUE; - /* Initialize the console record */ ConsoleRecord->ConsoleHandle = CheckVdmRequest->ConsoleHandle; - ConsoleRecord->ProcessHandle = NULL; - ConsoleRecord->ServerEvent = ConsoleRecord->ClientEvent = NULL; - ConsoleRecord->ReenterCount = 0; - ConsoleRecord->CurrentDirs = NULL; - ConsoleRecord->CurDirsLength = 0; - ConsoleRecord->SessionId = GetNextDosSesId(); - InitializeListHead(&ConsoleRecord->DosListHead); + if (ConsoleRecord->ConsoleHandle == NULL) + { + /* The parent doesn't have a console, get a new session ID */ + ConsoleRecord->SessionId = GetNextDosSesId(); + } + else + { + /* No session ID is needed */ + ConsoleRecord->SessionId = 0; + } + + /* Remember that the console record was allocated here */ + NewConsoleRecord = TRUE; } - /* Allocate a new DOS record */ - DosRecord = (PVDM_DOS_RECORD)RtlAllocateHeap(BaseSrvHeap, - HEAP_ZERO_MEMORY, - sizeof(VDM_DOS_RECORD)); - if (DosRecord == NULL) + if (!NewConsoleRecord) { - Status = STATUS_NO_MEMORY; - goto Cleanup; + /* Get the primary DOS record */ + DosRecord = (PVDM_DOS_RECORD)CONTAINING_RECORD(ConsoleRecord->DosListHead.Flink, + VDM_DOS_RECORD, Entry); + + if (DosRecord->State != VDM_READY) // == VDM_NOT_READY + { + /* Allocate a new DOS record */ + DosRecord = (PVDM_DOS_RECORD)RtlAllocateHeap(BaseSrvHeap, + HEAP_ZERO_MEMORY, + sizeof(VDM_DOS_RECORD)); + if (DosRecord == NULL) + { + Status = STATUS_NO_MEMORY; + goto Cleanup; + } + + /* Remember that the DOS record was allocated here */ + NewDosRecord = TRUE; + } + } + else + { + /* Allocate a new DOS record */ + DosRecord = (PVDM_DOS_RECORD)RtlAllocateHeap(BaseSrvHeap, + HEAP_ZERO_MEMORY, + sizeof(VDM_DOS_RECORD)); + if (DosRecord == NULL) + { + Status = STATUS_NO_MEMORY; + goto Cleanup; + } + + /* Remember that the DOS record was allocated here */ + NewDosRecord = TRUE; } /* Initialize the DOS record */ - DosRecord->State = VDM_NOT_LOADED; + DosRecord->State = VDM_NOT_READY; DosRecord->ExitCode = 0; - Status = BaseSrvCreatePairWaitHandles(&DosRecord->ServerEvent, &DosRecord->ClientEvent); - if (!NT_SUCCESS(Status)) goto Cleanup; - - /* Return the client event handle */ - CheckVdmRequest->WaitObjectForParent = DosRecord->ClientEvent; - /* Translate the input structure into a VDM command structure and set it in the DOS record */ if (!BaseSrvCopyCommand(CheckVdmRequest, DosRecord)) { @@ -682,9 +733,23 @@ CSR_API(BaseSrvCheckVDM) goto Cleanup; } - /* Add the DOS record */ - InsertHeadList(&ConsoleRecord->DosListHead, &DosRecord->Entry); + if (NewDosRecord) + { + /* Add the DOS record */ + InsertHeadList(&ConsoleRecord->DosListHead, &DosRecord->Entry); + } + + if (!NewConsoleRecord) + { + Status = BaseSrvCreatePairWaitHandles(&DosRecord->ServerEvent, &DosRecord->ClientEvent); + if (!NT_SUCCESS(Status)) goto Cleanup; + + /* Return the client event handle */ + CheckVdmRequest->WaitObjectForParent = DosRecord->ClientEvent; + } + // FIXME: We may notify ONLY if ConsoleRecord->nReEntrancy is > 0 + // in case NewConsoleRecord == FALSE AND NewDosRecord == TRUE. if (ConsoleRecord->ServerEvent) { /* Signal the session event */ @@ -697,13 +762,7 @@ CSR_API(BaseSrvCheckVDM) InsertTailList(&VDMConsoleListHead, &ConsoleRecord->Entry); } - if (ConsoleRecord->ConsoleHandle == NULL) - { - /* The parent doesn't have a console, so return the session ID */ - CheckVdmRequest->iTask = ConsoleRecord->SessionId; - } - else CheckVdmRequest->iTask = 0; - + CheckVdmRequest->iTask = ConsoleRecord->SessionId; CheckVdmRequest->VDMState = NewConsoleRecord ? VDM_NOT_LOADED : VDM_READY; Status = STATUS_SUCCESS; } @@ -718,21 +777,13 @@ Cleanup: /* Check if it failed */ if (!NT_SUCCESS(Status)) { - /* Free the DOS record */ - if (DosRecord != NULL) + /* Free the DOS record if it was allocated here */ + if (NewDosRecord) { - if (DosRecord->ServerEvent) NtClose(DosRecord->ServerEvent); - if (DosRecord->ClientEvent) - { - /* Close the remote handle */ - NtDuplicateObject(CsrGetClientThread()->Process->ProcessHandle, - DosRecord->ClientEvent, - NULL, - NULL, - 0, - 0, - DUPLICATE_CLOSE_SOURCE); - } + ASSERT(DosRecord != NULL); + + BaseSrvDestroyPairWaitHandles(DosRecord->ServerEvent, + DosRecord->ClientEvent); RtlFreeHeap(BaseSrvHeap, 0, DosRecord); DosRecord = NULL; @@ -741,6 +792,8 @@ Cleanup: /* Free the console record if it was allocated here */ if (NewConsoleRecord) { + ASSERT(ConsoleRecord != NULL); + RtlFreeHeap(BaseSrvHeap, 0, ConsoleRecord); ConsoleRecord = NULL; } @@ -787,8 +840,7 @@ CSR_API(BaseSrvUpdateVDMEntry) /* Get the primary DOS record */ DosRecord = (PVDM_DOS_RECORD)CONTAINING_RECORD(ConsoleRecord->DosListHead.Flink, - VDM_DOS_RECORD, - Entry); + VDM_DOS_RECORD, Entry); switch (UpdateVdmEntryRequest->EntryIndex) { @@ -811,10 +863,8 @@ CSR_API(BaseSrvUpdateVDMEntry) */ if (ConsoleRecord->DosListHead.Flink == &ConsoleRecord->DosListHead) { - if (ConsoleRecord->ProcessHandle) NtClose(ConsoleRecord->ProcessHandle); - if (ConsoleRecord->ServerEvent) NtClose(ConsoleRecord->ServerEvent); RemoveEntryList(&ConsoleRecord->Entry); - RtlFreeHeap(BaseSrvHeap, 0, ConsoleRecord); + BaseSrvDestroyConsoleRecord(ConsoleRecord); } } @@ -836,6 +886,10 @@ CSR_API(BaseSrvUpdateVDMEntry) DUPLICATE_SAME_ATTRIBUTES | DUPLICATE_SAME_ACCESS); if (!NT_SUCCESS(Status)) goto Cleanup; + // + // FIXME! Should we always do the following?? + // + /* Create a pair of handles to one event object */ Status = BaseSrvCreatePairWaitHandles(&DosRecord->ServerEvent, &DosRecord->ClientEvent); @@ -881,7 +935,7 @@ CSR_API(BaseSrvGetNextVDMCommand) { NTSTATUS Status; PBASE_GET_NEXT_VDM_COMMAND GetNextVdmCommandRequest = - &((PBASE_API_MESSAGE)ApiMessage)->Data.GetNextVDMCommandRequest; + &((PBASE_API_MESSAGE)ApiMessage)->Data.GetNextVDMCommandRequest; PRTL_CRITICAL_SECTION CriticalSection; PLIST_ENTRY i = NULL; PVDM_CONSOLE_RECORD ConsoleRecord = NULL; @@ -935,7 +989,14 @@ CSR_API(BaseSrvGetNextVDMCommand) /* Enter the critical section */ RtlEnterCriticalSection(CriticalSection); - if (!(GetNextVdmCommandRequest->VDMState & VDM_FLAG_WOW)) + if (GetNextVdmCommandRequest->VDMState & VDM_FLAG_WOW) + { + // TODO: WOW SUPPORT NOT IMPLEMENTED + UNIMPLEMENTED; + Status = STATUS_NOT_IMPLEMENTED; + goto Cleanup; + } + // else if (!(GetNextVdmCommandRequest->VDMState & VDM_FLAG_WOW)) { if (GetNextVdmCommandRequest->iTask != 0) { @@ -1018,16 +1079,16 @@ CSR_API(BaseSrvGetNextVDMCommand) DosRecord->ServerEvent = NULL; } - /* Search for a DOS record that isn't loaded yet */ + /* Search for a DOS record that is currently running and has command information */ for (i = ConsoleRecord->DosListHead.Flink; i != &ConsoleRecord->DosListHead; i = i->Flink) { DosRecord = CONTAINING_RECORD(i, VDM_DOS_RECORD, Entry); - if (DosRecord->State == VDM_NOT_LOADED) break; + if ((DosRecord->State == VDM_NOT_READY) && (DosRecord->CommandInfo != NULL)) break; } + /* Check if we found any */ if (i != &ConsoleRecord->DosListHead) { - /* DOS tasks which haven't been loaded yet should have a command info structure */ ASSERT(DosRecord->CommandInfo != NULL); /* Check if the caller only wants environment data */ @@ -1060,22 +1121,22 @@ CSR_API(BaseSrvGetNextVDMCommand) DosRecord->CommandInfo = NULL; /* Update the VDM state */ - GetNextVdmCommandRequest->VDMState = DosRecord->State = VDM_NOT_READY; + DosRecord->State = VDM_NOT_READY; } Status = STATUS_SUCCESS; goto Cleanup; } } - else - { - // TODO: WOW SUPPORT NOT IMPLEMENTED - Status = STATUS_NOT_IMPLEMENTED; - goto Cleanup; - } - /* There is no command yet */ - if (!(GetNextVdmCommandRequest->VDMState & VDM_FLAG_DONT_WAIT)) + GetNextVdmCommandRequest->WaitObjectForVDM = NULL; + + /* + * There is no command yet. Prepare for waiting if we asked so, + * and if we were not retrying a request. + */ + if (!(GetNextVdmCommandRequest->VDMState & VDM_FLAG_DONT_WAIT) || + !(GetNextVdmCommandRequest->VDMState & VDM_FLAG_RETRY)) { if (ConsoleRecord->ServerEvent) { @@ -1122,16 +1183,30 @@ CSR_API(BaseSrvExitVDM) Status = BaseSrvGetConsoleRecord(ExitVdmRequest->ConsoleHandle, &ConsoleRecord); if (!NT_SUCCESS(Status)) goto Cleanup; + if (ConsoleRecord->ServerEvent) + ExitVdmRequest->WaitObjectForVDM = ConsoleRecord->ClientEvent; + + // NOTE: The following is the same as in BaseSrvCleanupVDMResources. + + if (ConsoleRecord->ServerEvent) + { + NtClose(ConsoleRecord->ServerEvent); + ConsoleRecord->ServerEvent = NULL; + } + /* Cleanup the DOS records */ - while (ConsoleRecord->DosListHead.Flink != &ConsoleRecord->DosListHead) + while (!IsListEmpty(&ConsoleRecord->DosListHead)) { DosRecord = CONTAINING_RECORD(ConsoleRecord->DosListHead.Flink, - VDM_DOS_RECORD, - Entry); + VDM_DOS_RECORD, Entry); /* Set the event and close it */ - NtSetEvent(DosRecord->ServerEvent, NULL); - NtClose(DosRecord->ServerEvent); + if (DosRecord->ServerEvent) + { + NtSetEvent(DosRecord->ServerEvent, NULL); + NtClose(DosRecord->ServerEvent); + DosRecord->ServerEvent = NULL; + } /* Remove the DOS entry */ if (DosRecord->CommandInfo) BaseSrvFreeVDMInfo(DosRecord->CommandInfo); @@ -1139,20 +1214,9 @@ CSR_API(BaseSrvExitVDM) RtlFreeHeap(BaseSrvHeap, 0, DosRecord); } - if (ConsoleRecord->CurrentDirs != NULL) - { - /* Free the current directories */ - RtlFreeHeap(BaseSrvHeap, 0, ConsoleRecord->CurrentDirs); - ConsoleRecord->CurrentDirs = NULL; - ConsoleRecord->CurDirsLength = 0; - } - - /* Close the event handle */ - if (ConsoleRecord->ServerEvent) NtClose(ConsoleRecord->ServerEvent); - /* Remove the console record */ RemoveEntryList(&ConsoleRecord->Entry); - RtlFreeHeap(BaseSrvHeap, 0, ConsoleRecord); + BaseSrvDestroyConsoleRecord(ConsoleRecord); } else { @@ -1220,6 +1284,8 @@ CSR_API(BaseSrvGetVDMExitCode) /* Return the exit code */ GetVDMExitCodeRequest->ExitCode = DosRecord->ExitCode; + // FIXME: We may just change DosRecord->State to VDM_READY in some cases... + /* Since this is a zombie task record, remove it */ if (DosRecord->CommandInfo) BaseSrvFreeVDMInfo(DosRecord->CommandInfo); RemoveEntryList(&DosRecord->Entry); @@ -1245,13 +1311,20 @@ CSR_API(BaseSrvSetReenterCount) Status = BaseSrvGetConsoleRecord(SetReenterCountRequest->ConsoleHandle, &ConsoleRecord); if (!NT_SUCCESS(Status)) goto Cleanup; - if (SetReenterCountRequest->fIncDec == VDM_INC_REENTER_COUNT) ConsoleRecord->ReenterCount++; + if (SetReenterCountRequest->fIncDec == VDM_INC_REENTER_COUNT) + { + ConsoleRecord->ReenterCount++; + } else if (SetReenterCountRequest->fIncDec == VDM_DEC_REENTER_COUNT) { ConsoleRecord->ReenterCount--; - if (ConsoleRecord->ServerEvent != NULL) NtSetEvent(ConsoleRecord->ServerEvent, NULL); + if (ConsoleRecord->ServerEvent) + NtSetEvent(ConsoleRecord->ServerEvent, NULL); + } + else + { + Status = STATUS_INVALID_PARAMETER; } - else Status = STATUS_INVALID_PARAMETER; Cleanup: /* Leave the critical section */ diff --git a/reactos/subsystems/win/basesrv/vdm.h b/reactos/subsystems/win/basesrv/vdm.h index db11e65bce9..5f07c3e648e 100644 --- a/reactos/subsystems/win/basesrv/vdm.h +++ b/reactos/subsystems/win/basesrv/vdm.h @@ -43,18 +43,11 @@ typedef struct _VDM_DOS_RECORD /* FUNCTIONS ******************************************************************/ -NTSTATUS NTAPI BaseSrvGetConsoleRecord(HANDLE ConsoleHandle, PVDM_CONSOLE_RECORD *Record); -NTSTATUS NTAPI GetConsoleRecordBySessionId(ULONG TaskId, PVDM_CONSOLE_RECORD *Record); -ULONG NTAPI GetNextDosSesId(VOID); -BOOLEAN NTAPI BaseSrvIsVdmAllowed(VOID); -NTSTATUS NTAPI BaseSrvCreatePairWaitHandles(PHANDLE ServerEvent, PHANDLE ClientEvent); -VOID NTAPI BaseSrvFreeVDMInfo(PVDM_COMMAND_INFO CommandInfo); -VOID NTAPI BaseSrvCleanupVDMResources(IN PCSR_PROCESS CsrProcess); -BOOLEAN NTAPI BaseSrvCopyCommand(PBASE_CHECK_VDM CheckVdmRequest, PVDM_DOS_RECORD DosRecord); -NTSTATUS NTAPI BaseSrvFillCommandInfo( - PVDM_COMMAND_INFO CommandInfo, - PBASE_GET_NEXT_VDM_COMMAND Message -); -VOID NTAPI BaseInitializeVDM(VOID); +NTSTATUS BaseSrvGetConsoleRecord(HANDLE ConsoleHandle, PVDM_CONSOLE_RECORD *Record); +NTSTATUS GetConsoleRecordBySessionId(ULONG TaskId, PVDM_CONSOLE_RECORD *Record); + +BOOLEAN BaseSrvIsVdmAllowed(VOID); +VOID BaseInitializeVDM(VOID); +VOID BaseSrvCleanupVDMResources(IN PCSR_PROCESS CsrProcess); #endif // __VDM_H__ -- 2.17.1