mirror of
https://github.com/reactos/reactos.git
synced 2024-07-22 04:08:08 +00:00
[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:
parent
38b81a6049
commit
28b957e970
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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__
|
||||
|
|
Loading…
Reference in a new issue