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/wi…
==============================================================================
--- 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/dos3…
==============================================================================
--- 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?…
==============================================================================
--- 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/vd…
==============================================================================
--- 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 */