[KERNEL32][BASESRV]
[reactos.git] / dll / win32 / kernel32 / client / vdm.c
index 9601f10..c37a3cf 100644 (file)
@@ -574,7 +574,7 @@ BaseGetVdmConfigInfo(IN LPCWSTR CommandLineReserved,
          * %s%c  : Nothing if DOS VDM, -w if WoW VDM, -ws if separate WoW VDM.
          */
         _snwprintf(CommandLine,
-                   sizeof(CommandLine),
+                   sizeof(CommandLine) / sizeof(CommandLine[0]),
                    L"\"%s\\ntvdm.exe\" -i%lx %s%c",
                    Buffer,
                    DosSeqId,
@@ -588,7 +588,7 @@ BaseGetVdmConfigInfo(IN LPCWSTR CommandLineReserved,
          * %s%c  : Nothing if DOS VDM, -w if WoW VDM, -ws if separate WoW VDM.
          */
         _snwprintf(CommandLine,
-                   sizeof(CommandLine),
+                   sizeof(CommandLine) / sizeof(CommandLine[0]),
                    L"\"%s\\ntvdm.exe\" %s%c",
                    Buffer,
                    (BinaryType == BINARY_TYPE_DOS) ? L" " : L"-w",
@@ -677,7 +677,7 @@ BaseCreateVDMEnvironment(IN PWCHAR lpEnvironment,
     if (!lpEnvironment)
     {
         /* Nope, create one */
-        Status = RtlCreateEnvironment(TRUE, (PWCHAR*)&Environment);
+        Status = RtlCreateEnvironment(TRUE, &Environment);
         if (!NT_SUCCESS(Status)) goto Quickie;
     }
     else
@@ -718,6 +718,7 @@ BaseCreateVDMEnvironment(IN PWCHAR lpEnvironment,
     p = NewEnvironment;
 
     /* FIXME: Code here */
+    DPRINT1("BaseCreateVDMEnvironment is half-plemented!\n");
 
     /* Terminate it */
     *p++ = UNICODE_NULL;
@@ -916,7 +917,7 @@ InternalGetBinaryType(HANDLE hFile)
       return BINARY_PE_EXE32;
     }
 
-    if(!memcmp(magic, "NE", 1))
+    if(!memcmp(magic, "NE", 2))
     {
       /* This is a Windows executable (NE) header.  This can
        * mean either a 16-bit OS/2 or a 16-bit Windows or even a
@@ -1124,16 +1125,323 @@ 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;
+    PBASE_SET_REENTER_COUNT SetReenterCount = &ApiMessage.Data.SetReenterCountRequest;
+    PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
+    ULONG NumStrings = 0;
+
+    if (CommandData != NULL)
+    {
+        if (CommandData->VDMState & (VDM_NOT_LOADED | VDM_NOT_READY | VDM_READY))
+        {
+            /* 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(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;
+                    }
+
+                    /* 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;
+        }
+        else 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 */
+            Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
+                                         NULL,
+                                         CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepSetReenterCount),
+                                         sizeof(BASE_SET_REENTER_COUNT));
+            BaseSetLastNTError(Status);
+            Result = NT_SUCCESS(Status);
+        }
+        else
+        {
+            BaseSetLastNTError(STATUS_INVALID_PARAMETER);
+            Result = FALSE;
+        }
+    }
+    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;
 }
 
 
@@ -1297,12 +1605,15 @@ VDMConsoleOperation (
 /*
  * @unimplemented
  */
-DWORD
+BOOL
 WINAPI
-VDMOperationStarted (
-    DWORD   Unknown0
-    )
+VDMOperationStarted(IN ULONG Unknown0)
 {
-    STUB;
-    return 0;
+    DPRINT1("VDMOperationStarted(%d)\n", Unknown0);
+
+    return
+    BaseUpdateVDMEntry(VdmEntryUpdateControlCHandler,
+                       NULL,
+                       0,
+                       Unknown0);
 }