Author: aandrejevic Date: Thu May 1 23:52:36 2014 New Revision: 63098
URL: http://svn.reactos.org/svn/reactos?rev=63098&view=rev Log: [BASESRV][KERNEL32][NTVDM] Make our BaseSrvGetNextVDMCommand and GetNextVDMCommand a bit more Windows-compatible, and modify NTVDM accordingly.
Modified: branches/ntvdm/dll/win32/kernel32/client/vdm.c branches/ntvdm/include/reactos/subsys/win/vdm.h branches/ntvdm/subsystems/ntvdm/dos/dos32krnl/dos.c branches/ntvdm/subsystems/ntvdm/ntvdm.c branches/ntvdm/subsystems/win/basesrv/vdm.c
Modified: branches/ntvdm/dll/win32/kernel32/client/vdm.c URL: http://svn.reactos.org/svn/reactos/branches/ntvdm/dll/win32/kernel32/client/... ============================================================================== --- branches/ntvdm/dll/win32/kernel32/client/vdm.c [iso-8859-1] (original) +++ branches/ntvdm/dll/win32/kernel32/client/vdm.c [iso-8859-1] Thu May 1 23:52:36 2014 @@ -1281,6 +1281,10 @@ 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);
Modified: branches/ntvdm/include/reactos/subsys/win/vdm.h URL: http://svn.reactos.org/svn/reactos/branches/ntvdm/include/reactos/subsys/win... ============================================================================== --- branches/ntvdm/include/reactos/subsys/win/vdm.h [iso-8859-1] (original) +++ branches/ntvdm/include/reactos/subsys/win/vdm.h [iso-8859-1] Thu May 1 23:52:36 2014 @@ -48,11 +48,22 @@ #define VDM_READY 0x04
// -// VDM Magic Values +// VDM Flags // +#define VDM_FLAG_FIRST_TASK 0x01 #define VDM_FLAG_WOW 0x02 +#define VDM_FLAG_DOS 0x04 +#define VDM_FLAG_RETRY 0x08 #define VDM_INC_REENTER_COUNT 0x10 #define VDM_DEC_REENTER_COUNT 0x20 +#define VDM_FLAG_NESTED_TASK 0x40 +#define VDM_FLAG_DONT_WAIT 0x80 +#define VDM_GET_FIRST_COMMAND 0x100 +#define VDM_GET_ENVIRONMENT 0x400 +#define VDM_FLAG_SEPARATE_WOW 0x800 +#define VDM_LIST_WOW_PROCESSES 0x1000 +#define VDM_LIST_WOW_TASKS 0x4000 +#define VDM_ADD_WOW_TASK 0x8000
typedef struct {
Modified: branches/ntvdm/subsystems/ntvdm/dos/dos32krnl/dos.c URL: http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/dos/dos32... ============================================================================== --- branches/ntvdm/subsystems/ntvdm/dos/dos32krnl/dos.c [iso-8859-1] (original) +++ branches/ntvdm/subsystems/ntvdm/dos/dos32krnl/dos.c [iso-8859-1] Thu May 1 23:52:36 2014 @@ -1336,7 +1336,7 @@ ZeroMemory(&CommandInfo, sizeof(CommandInfo));
/* Initialize the structure members */ - CommandInfo.VDMState = VDM_NOT_READY; + CommandInfo.VDMState = VDM_FLAG_NESTED_TASK | VDM_FLAG_DONT_WAIT; CommandInfo.CmdLine = CmdLine; CommandInfo.CmdLen = sizeof(CmdLine); CommandInfo.AppName = AppName; @@ -1399,6 +1399,7 @@ PDOS_MCB CurrentMcb; LPDWORD IntVecTable = (LPDWORD)((ULONG_PTR)BaseAddress); PDOS_PSP PspBlock = SEGMENT_TO_PSP(Psp); + VDM_COMMAND_INFO CommandInfo;
DPRINT("DosTerminateProcess: Psp 0x%04X, ReturnCode 0x%02X\n", Psp, @@ -1443,6 +1444,22 @@ { CurrentPsp = PspBlock->ParentPsp; if (CurrentPsp == SYSTEM_PSP) VdmRunning = FALSE; + } + + // FIXME: This is probably not the best way to do it + /* Check if this was a nested DOS task */ + if (VdmRunning) + { + /* Decrement the re-entry count */ + CommandInfo.VDMState = VDM_DEC_REENTER_COUNT; + GetNextVDMCommand(&CommandInfo); + + /* Clear the structure */ + ZeroMemory(&CommandInfo, sizeof(CommandInfo)); + + /* Update the VDM state of the task */ + CommandInfo.VDMState = VDM_FLAG_DONT_WAIT; + GetNextVDMCommand(&CommandInfo); }
/* Save the return code - Normal termination */
Modified: branches/ntvdm/subsystems/ntvdm/ntvdm.c URL: http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/ntvdm.c?r... ============================================================================== --- branches/ntvdm/subsystems/ntvdm/ntvdm.c [iso-8859-1] (original) +++ branches/ntvdm/subsystems/ntvdm/ntvdm.c [iso-8859-1] Thu May 1 23:52:36 2014 @@ -390,6 +390,7 @@
DWORD WINAPI CommandThreadProc(LPVOID Parameter) { + BOOLEAN First = TRUE; DWORD Result; VDM_COMMAND_INFO CommandInfo; CHAR CmdLine[MAX_PATH]; @@ -407,7 +408,7 @@ ZeroMemory(&CommandInfo, sizeof(CommandInfo));
/* Initialize the structure members */ - CommandInfo.VDMState = VDM_NOT_LOADED; + CommandInfo.VDMState = VDM_FLAG_DOS; CommandInfo.CmdLine = CmdLine; CommandInfo.CmdLen = sizeof(CmdLine); CommandInfo.AppName = AppName; @@ -421,6 +422,12 @@ CommandInfo.Env = Env; CommandInfo.EnvLen = sizeof(Env);
+ if (First) + { + CommandInfo.VDMState |= VDM_FLAG_FIRST_TASK; + First = FALSE; + } + /* Wait for the next available VDM */ if (!GetNextVDMCommand(&CommandInfo)) break;
Modified: branches/ntvdm/subsystems/win/basesrv/vdm.c URL: http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/win/basesrv/vdm... ============================================================================== --- branches/ntvdm/subsystems/win/basesrv/vdm.c [iso-8859-1] (original) +++ branches/ntvdm/subsystems/win/basesrv/vdm.c [iso-8859-1] Thu May 1 23:52:36 2014 @@ -905,21 +905,58 @@ GetNextVdmCommandRequest->iTask = ConsoleRecord->SessionId; GetNextVdmCommandRequest->WaitObjectForVDM = NULL;
- if (!(GetNextVdmCommandRequest->VDMState & VDM_NOT_READY)) - { + if (GetNextVdmCommandRequest->VDMState & VDM_GET_FIRST_COMMAND) + { + /* Check if the DOS record list is empty */ + if (ConsoleRecord->DosListHead.Flink == &ConsoleRecord->DosListHead) + { + Status = STATUS_INVALID_PARAMETER; + goto Cleanup; + } + + /* Get the first DOS record */ + DosRecord = CONTAINING_RECORD(ConsoleRecord->DosListHead.Flink, VDM_DOS_RECORD, Entry); + + /* Make sure its command information is still there */ + if (DosRecord->CommandInfo == NULL) + { + Status = STATUS_INVALID_PARAMETER; + goto Cleanup; + } + + /* Fill the command information */ + Status = BaseSrvFillCommandInfo(DosRecord->CommandInfo, GetNextVdmCommandRequest); + goto Cleanup; + } + + /* Check if we should set the state of a running DOS record to ready */ + if (!(GetNextVdmCommandRequest->VDMState + & (VDM_FLAG_FIRST_TASK | VDM_FLAG_RETRY | VDM_FLAG_NESTED_TASK))) + { + /* Search for a DOS record that is currently running */ for (i = ConsoleRecord->DosListHead.Flink; i != &ConsoleRecord->DosListHead; i = i->Flink) { DosRecord = CONTAINING_RECORD(i, VDM_DOS_RECORD, Entry); - if (DosRecord->State == VDM_NOT_READY) - { - /* If NTVDM is asking for a new command, it means these are done */ - DosRecord->State = VDM_READY; - - NtSetEvent(DosRecord->ServerEvent, NULL); - NtClose(DosRecord->ServerEvent); - DosRecord->ServerEvent = NULL; - } - } + if (DosRecord->State == VDM_NOT_READY) break; + } + + /* Check if we found any */ + if (i == &ConsoleRecord->DosListHead) + { + Status = STATUS_INVALID_PARAMETER; + goto Cleanup; + } + + /* Set the exit code */ + DosRecord->ExitCode = GetNextVdmCommandRequest->ExitCode; + + /* Update the VDM state */ + DosRecord->State = VDM_READY; + + /* Notify all waiting threads that the task is finished */ + NtSetEvent(DosRecord->ServerEvent, NULL); + NtClose(DosRecord->ServerEvent); + DosRecord->ServerEvent = NULL; }
/* Search for a DOS record that isn't loaded yet */ @@ -931,16 +968,40 @@
if (i != &ConsoleRecord->DosListHead) { - /* Fill the command information */ - Status = BaseSrvFillCommandInfo(DosRecord->CommandInfo, GetNextVdmCommandRequest); - if (!NT_SUCCESS(Status)) goto Cleanup; - - /* Free the command information, it's no longer needed */ - BaseSrvFreeVDMInfo(DosRecord->CommandInfo); - DosRecord->CommandInfo = NULL; - - /* Update the VDM state */ - DosRecord->State = VDM_NOT_READY; + /* 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 */ + if (GetNextVdmCommandRequest->VDMState & VDM_GET_ENVIRONMENT) + { + if (GetNextVdmCommandRequest->EnvLen < DosRecord->CommandInfo->EnvLen) + { + /* Not enough space was reserved */ + GetNextVdmCommandRequest->EnvLen = DosRecord->CommandInfo->EnvLen; + Status = STATUS_BUFFER_OVERFLOW; + goto Cleanup; + } + + /* Copy the environment data */ + RtlMoveMemory(GetNextVdmCommandRequest->Env, + DosRecord->CommandInfo->Env, + DosRecord->CommandInfo->EnvLen); + + /* Return the actual size to the caller */ + GetNextVdmCommandRequest->EnvLen = DosRecord->CommandInfo->EnvLen; + } + else + { + /* Fill the command information */ + Status = BaseSrvFillCommandInfo(DosRecord->CommandInfo, GetNextVdmCommandRequest); + + /* Free the command information, it's no longer needed */ + BaseSrvFreeVDMInfo(DosRecord->CommandInfo); + DosRecord->CommandInfo = NULL; + + /* Update the VDM state */ + GetNextVdmCommandRequest->VDMState = DosRecord->State = VDM_NOT_READY; + }
Status = STATUS_SUCCESS; goto Cleanup; @@ -954,21 +1015,25 @@ }
/* There is no command yet */ - if (ConsoleRecord->ServerEvent) - { - /* Reset the event */ - NtResetEvent(ConsoleRecord->ServerEvent, NULL); - } - else - { - /* Create a pair of wait handles */ - Status = BaseSrvCreatePairWaitHandles(&ConsoleRecord->ServerEvent, - &ConsoleRecord->ClientEvent); - if (!NT_SUCCESS(Status)) goto Cleanup; - } - - /* Return the client event handle */ - GetNextVdmCommandRequest->WaitObjectForVDM = ConsoleRecord->ClientEvent; + if ((GetNextVdmCommandRequest->VDMState & (VDM_FLAG_DONT_WAIT | VDM_FLAG_RETRY)) + != (VDM_FLAG_DONT_WAIT | VDM_FLAG_RETRY)) + { + if (ConsoleRecord->ServerEvent) + { + /* Reset the event */ + NtResetEvent(ConsoleRecord->ServerEvent, NULL); + } + else + { + /* Create a pair of wait handles */ + Status = BaseSrvCreatePairWaitHandles(&ConsoleRecord->ServerEvent, + &ConsoleRecord->ClientEvent); + if (!NT_SUCCESS(Status)) goto Cleanup; + } + + /* Return the client event handle */ + GetNextVdmCommandRequest->WaitObjectForVDM = ConsoleRecord->ClientEvent; + }
Cleanup: /* Leave the critical section */