[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
This commit is contained in:
Hermès Bélusca-Maïto 2015-09-12 16:23:32 +00:00
parent 38b81a6049
commit 28b957e970
3 changed files with 599 additions and 501 deletions

View file

@ -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
{
/* 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;
}
/* Allocate memory for the startup info */
CsrAllocateMessagePointer(CaptureBuffer,
sizeof(STARTUPINFOA),
(PVOID*)&GetNextVdmCommand->StartupInfo);
if (CommandData->CmdLen)
{
/* Allocate memory for the command line */
CsrAllocateMessagePointer(CaptureBuffer,
CommandData->CmdLen,
(PVOID*)&GetNextVdmCommand->CmdLine);
}
if (CommandData->AppLen)
{
/* Allocate memory for the application name */
CsrAllocateMessagePointer(CaptureBuffer,
CommandData->AppLen,
(PVOID*)&GetNextVdmCommand->AppName);
}
if (CommandData->PifLen)
{
/* Allocate memory for the PIF file name */
CsrAllocateMessagePointer(CaptureBuffer,
CommandData->PifLen,
(PVOID*)&GetNextVdmCommand->PifFile);
}
if (CommandData->CurDirectoryLen)
{
/* Allocate memory for the current directory */
CsrAllocateMessagePointer(CaptureBuffer,
CommandData->CurDirectoryLen,
(PVOID*)&GetNextVdmCommand->CurDirectory);
}
if (CommandData->EnvLen)
{
/* Allocate memory for the environment */
CsrAllocateMessagePointer(CaptureBuffer,
CommandData->EnvLen,
(PVOID*)&GetNextVdmCommand->Env);
}
if (CommandData->DesktopLen)
{
/* Allocate memory for the desktop name */
CsrAllocateMessagePointer(CaptureBuffer,
CommandData->DesktopLen,
(PVOID*)&GetNextVdmCommand->Desktop);
}
if (CommandData->TitleLen)
{
/* Allocate memory for the title */
CsrAllocateMessagePointer(CaptureBuffer,
CommandData->TitleLen,
(PVOID*)&GetNextVdmCommand->Title);
}
if (CommandData->ReservedLen)
{
/* Allocate memory for the reserved parameter */
CsrAllocateMessagePointer(CaptureBuffer,
CommandData->ReservedLen,
(PVOID*)&GetNextVdmCommand->Reserved);
}
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;
}
/* 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;
}
/* Set the retry flag and clear the exit code */
GetNextVdmCommand->VDMState |= VDM_FLAG_RETRY;
GetNextVdmCommand->ExitCode = 0;
}
}
while (GetNextVdmCommand->WaitObjectForVDM != NULL);
/* 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(STARTUPINFOA));
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 */
Result = TRUE;
}
/* Return TRUE if this is the first VDM */
return IsFirstVdm->FirstVDM;
}
else
/* 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,
NULL,
CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepIsFirstVDM),
sizeof(*IsFirstVdm));
if (!NT_SUCCESS(Status))
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;
}
/* Return TRUE if this is the first VDM */
Result = IsFirstVdm->FirstVDM;
/* 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 Result;
return Success;
}

View file

@ -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 */

View file

@ -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__