[KERNEL32]
[reactos.git] / dll / win32 / kernel32 / client / vdm.c
index 9601f10..fa90b3a 100644 (file)
@@ -1124,16 +1124,293 @@ ExitVDM(BOOL IsWow, ULONG iWowTask)
     }
 }
 
-
 /*
- * @unimplemented
+ * @implemented
  */
-DWORD
+BOOL
 WINAPI
 GetNextVDMCommand(PVDM_COMMAND_INFO CommandData)
 {
-    STUB;
-    return 0;
+    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;
+    PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
+    ULONG NumStrings = 1;
+
+    if (CommandData != NULL)
+    {
+        /* Clear the structure */
+        ZeroMemory(GetNextVdmCommand, sizeof(GetNextVdmCommand));
+
+        /* Setup the input parameters */
+        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;
+
+        /* 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,
+                                                 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(BASE_GET_NEXT_VDM_COMMAND));
+
+            if (!NT_SUCCESS(Status))
+            {
+                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;
+                }
+            }
+        }
+        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;
+    }
+    else
+    {
+        /* Call CSRSS */
+        Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
+                                     NULL,
+                                     CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepIsFirstVDM),
+                                     sizeof(BASE_IS_FIRST_VDM));
+        if (!NT_SUCCESS(Status))
+        {
+            BaseSetLastNTError(Status);
+            goto Cleanup;
+        }
+
+        /* Return TRUE if this is the first VDM */
+        Result = IsFirstVdm->FirstVDM;
+    }
+
+Cleanup:
+    if (CaptureBuffer != NULL) CsrFreeCaptureBuffer(CaptureBuffer); 
+    return Result;
 }