branch update for HEAD-2003021201
[reactos.git] / lib / kernel32 / process / create.c
index 9abb98f..776057c 100644 (file)
 
 /* INCLUDES ****************************************************************/
 
-#include <ddk/ntddk.h>
-#include <windows.h>
-#include <kernel32/proc.h>
-#include <kernel32/thread.h>
-#include <wchar.h>
-#include <string.h>
-#include <napi/i386/segment.h>
-#include <ntdll/ldr.h>
-#include <napi/teb.h>
-#include <ntdll/base.h>
-#include <ntdll/rtl.h>
-#include <csrss/csrss.h>
-#include <ntdll/csr.h>
+#include <k32.h>
 
 #define NDEBUG
 #include <kernel32/kernel32.h>
-#include <kernel32/error.h>
 
 /* FUNCTIONS ****************************************************************/
 
@@ -167,44 +154,62 @@ CreateProcessA (LPCSTR                    lpApplicationName,
        return Result;
 }
 
+static int _except_recursion_trap = 0;
 
-static\r
-EXCEPTION_DISPOSITION\r
-__cdecl\r
-_except_handler(\r
-    struct _EXCEPTION_RECORD *ExceptionRecord,\r
-    void * EstablisherFrame,\r
-    struct _CONTEXT *ContextRecord,\r
-    void * DispatcherContext )\r
-{\r
-       DPRINT("Process terminated abnormally...\n");\r
-\r
-       if (/* FIXME: */ TRUE) /* Not a service */\r
-       {\r
-               ExitProcess(0);
+struct _CONTEXT;
+struct __EXCEPTION_RECORD;
+
+static
+EXCEPTION_DISPOSITION
+__cdecl
+_except_handler(
+    struct _EXCEPTION_RECORD *ExceptionRecord,
+    void * EstablisherFrame,
+    struct _CONTEXT *ContextRecord,
+    void * DispatcherContext )
+{
+       DPRINT("Process terminated abnormally...\n");
+
+       if (++_except_recursion_trap > 3) {
+        DPRINT("_except_handler(...) appears to be recursing.\n");
+        DPRINT("Process HALTED.\n");
+               for (;;) {}
+       }
+
+       if (/* FIXME: */ TRUE) /* Not a service */
+       {
+        DPRINT("  calling ExitProcess(0) no, lets try ExitThread . . .\n");
+               //ExitProcess(0);
+               ExitThread(0);
        }
        else
        {
+        DPRINT("  calling ExitThread(0) . . .\n");
                ExitThread(0);
        }
 
+    DPRINT("  We should not get to here !!!\n");
        /* We should not get to here */
        return ExceptionContinueSearch;
-}\r
+}
 
 VOID STDCALL
 BaseProcessStart(LPTHREAD_START_ROUTINE lpStartAddress,
-                                DWORD lpParameter)
+                DWORD lpParameter)
 {
        UINT uExitCode = 0;
 
+    DPRINT("\nBaseProcessStart(..) - setting up exception frame.\n\n");
+
        __try1(_except_handler)
        {
-               uExitCode = (lpStartAddress)(lpParameter);
+               uExitCode = (lpStartAddress)((PVOID)lpParameter);
        } __except1
        {
        }
 
+    DPRINT("\nBaseProcessStart(..) - cleaned up exception frame.\n\n");
+
        ExitThread(uExitCode);
 }
 
@@ -520,7 +525,7 @@ KlInitPeb (HANDLE ProcessHandle,
 
    /* create the PPB */
    PpbBase = NULL;
-   PpbSize = Ppb->AllocationSize;\r
+   PpbSize = Ppb->AllocationSize;
    Status = NtAllocateVirtualMemory(ProcessHandle,
                                    &PpbBase,
                                    0,
@@ -532,11 +537,11 @@ KlInitPeb (HANDLE ProcessHandle,
        return(Status);
      }
 
-   DPRINT("Ppb->MaximumLength %x\n", Ppb->MaximumLength);
+   //DPRINT("Ppb->MaximumLength %x\n", Ppb->MaximumLength);
    NtWriteVirtualMemory(ProcessHandle,
                        PpbBase,
                        Ppb,
-                       Ppb->AllocationSize,\r
+                       Ppb->AllocationSize,
                        &BytesWritten);
 
    /* write pointer to environment */
@@ -658,7 +663,7 @@ CreateProcessW(LPCWSTR lpApplicationName,
       {
          s = TempApplicationNameW;
       }
-      s = wcsrchr(TempApplicationNameW, L'.');
+      s = wcsrchr(s, L'.');
       if (s == NULL)
         wcscat(TempApplicationNameW, L".exe");
    }
@@ -741,9 +746,94 @@ CreateProcessW(LPCWSTR lpApplicationName,
    hSection = KlMapFile (ImagePathName);
    if (hSection == NULL)
    {
-       return FALSE;
+/////////////////////////////////////////
+        /*
+         * Inspect the image to determine executable flavour
+         */
+        IO_STATUS_BLOCK IoStatusBlock;
+        UNICODE_STRING ApplicationNameString;
+        OBJECT_ATTRIBUTES ObjectAttributes;
+        PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
+        IMAGE_DOS_HEADER DosHeader;
+        IO_STATUS_BLOCK Iosb;
+        LARGE_INTEGER Offset;
+        HANDLE hFile = NULL;
+
+        DPRINT("Inspecting Image Header for image type id\n");
+
+        // Find the application name
+        if (!RtlDosPathNameToNtPathName_U((LPWSTR)lpApplicationName,
+                &ApplicationNameString, NULL, NULL)) {
+            return FALSE;
+        }
+        DPRINT("ApplicationName %S\n",ApplicationNameString.Buffer);
+
+        InitializeObjectAttributes(&ObjectAttributes,
+                             &ApplicationNameString,
+                             OBJ_CASE_INSENSITIVE,
+                             NULL,
+                             SecurityDescriptor);
+
+        // Try to open the executable
+        Status = NtOpenFile(&hFile,
+                       SYNCHRONIZE|FILE_EXECUTE|FILE_READ_DATA,
+                       &ObjectAttributes,
+                       &IoStatusBlock,
+                       FILE_SHARE_DELETE|FILE_SHARE_READ,
+                       FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE);
+
+        RtlFreeUnicodeString(&ApplicationNameString);
+
+        if (!NT_SUCCESS(Status)) {
+            DPRINT("Failed to open file\n");
+            SetLastErrorByStatus(Status);
+            return FALSE;
+        }
+
+        // Read the dos header
+        Offset.QuadPart = 0;
+        Status = ZwReadFile(hFile,
+                     NULL,
+                     NULL,
+                     NULL,
+                     &Iosb,
+                     &DosHeader,
+                     sizeof(DosHeader),
+                     &Offset,
+                     0);
+
+        if (!NT_SUCCESS(Status)) {
+            DPRINT("Failed to read from file\n");
+            SetLastErrorByStatus(Status);
+            return FALSE;
+        }
+        if (Iosb.Information != sizeof(DosHeader)) {
+            DPRINT("Failed to read dos header from file\n");
+            SetLastErrorByStatus(STATUS_INVALID_IMAGE_FORMAT);
+            return FALSE;
+        }
+
+        // Check the DOS signature
+        if (DosHeader.e_magic != IMAGE_DOS_SIGNATURE) {
+            DPRINT("Failed dos magic check\n");
+            SetLastErrorByStatus(STATUS_INVALID_IMAGE_FORMAT);
+            return FALSE;
+        }
+        NtClose(hFile);
+
+        DPRINT("Launching VDM...\n");
+        return CreateProcessW(L"ntvdm.exe",
+                (LPWSTR)lpApplicationName,
+                lpProcessAttributes,
+                lpThreadAttributes,
+                bInheritHandles,
+                dwCreationFlags,
+                lpEnvironment,
+                lpCurrentDirectory,
+                lpStartupInfo,
+                lpProcessInformation);
    }
-   
+/////////////////////////////////////////
    /*
     * Create a new process
     */
@@ -775,7 +865,7 @@ CreateProcessW(LPCWSTR lpApplicationName,
         RuntimeInfo_U.Buffer = RtlAllocateHeap(GetProcessHeap(), 0, RuntimeInfo_U.Length);
         memcpy(RuntimeInfo_U.Buffer, lpStartupInfo->lpReserved2, lpStartupInfo->cbReserved2);
       }
-   } 
+   }
 
    /*
     * Create the PPB
@@ -793,28 +883,28 @@ CreateProcessW(LPCWSTR lpApplicationName,
 
    if (lpStartupInfo && lpStartupInfo->lpReserved2)
        RtlFreeHeap(GetProcessHeap(), 0, RuntimeInfo_U.Buffer);
-  
+
 
    /*
     * Translate some handles for the new process
     */
-   if (Ppb->CurrentDirectoryHandle)\r
+   if (Ppb->CurrentDirectoryHandle)
    {
-      Status = NtDuplicateObject (NtCurrentProcess(), 
-                        Ppb->CurrentDirectoryHandle,\r
+      Status = NtDuplicateObject (NtCurrentProcess(),
+                        Ppb->CurrentDirectoryHandle,
                         hProcess,
-                        &Ppb->CurrentDirectoryHandle,\r
+                        &Ppb->CurrentDirectoryHandle,
                         0,
                         TRUE,
                         DUPLICATE_SAME_ACCESS);
    }
 
-   if (Ppb->hConsole)\r
+   if (Ppb->hConsole)
    {
       Status = NtDuplicateObject (NtCurrentProcess(), 
-                        Ppb->hConsole,\r
+                        Ppb->hConsole,
                         hProcess,
-                        &Ppb->hConsole,\r
+                        &Ppb->hConsole,
                         0,
                         TRUE,
                         DUPLICATE_SAME_ACCESS);
@@ -862,31 +952,31 @@ CreateProcessW(LPCWSTR lpApplicationName,
      }
 
    // Set the child console handles 
-   Ppb->hStdInput = NtCurrentPeb()->ProcessParameters->hStdInput;\r
-   Ppb->hStdOutput = NtCurrentPeb()->ProcessParameters->hStdOutput;\r
-   Ppb->hStdError = NtCurrentPeb()->ProcessParameters->hStdError;\r
+   Ppb->hStdInput = NtCurrentPeb()->ProcessParameters->hStdInput;
+   Ppb->hStdOutput = NtCurrentPeb()->ProcessParameters->hStdOutput;
+   Ppb->hStdError = NtCurrentPeb()->ProcessParameters->hStdError;
 
    if (lpStartupInfo && (lpStartupInfo->dwFlags & STARTF_USESTDHANDLES))
    {
       if (lpStartupInfo->hStdInput)
-        Ppb->hStdInput = lpStartupInfo->hStdInput;\r
+        Ppb->hStdInput = lpStartupInfo->hStdInput;
       if (lpStartupInfo->hStdOutput)
-        Ppb->hStdOutput = lpStartupInfo->hStdOutput;\r
+        Ppb->hStdOutput = lpStartupInfo->hStdOutput;
       if (lpStartupInfo->hStdError)
-        Ppb->hStdError = lpStartupInfo->hStdError;\r
+        Ppb->hStdError = lpStartupInfo->hStdError;
    }
 
-   if (IsConsoleHandle(Ppb->hStdInput))\r
+   if (IsConsoleHandle(Ppb->hStdInput))
    {
-      Ppb->hStdInput = CsrReply.Data.CreateProcessReply.InputHandle;\r
+      Ppb->hStdInput = CsrReply.Data.CreateProcessReply.InputHandle;
    }
    else
    {
       DPRINT("Duplicate input handle\n");
       Status = NtDuplicateObject (NtCurrentProcess(), 
-                                 Ppb->hStdInput,\r
+                                 Ppb->hStdInput,
                                  hProcess,
-                                 &Ppb->hStdInput,\r
+                                 &Ppb->hStdInput,
                                  0,
                                  TRUE,
                                  DUPLICATE_SAME_ACCESS);
@@ -896,17 +986,17 @@ CreateProcessW(LPCWSTR lpApplicationName,
       }
    }
 
-   if (IsConsoleHandle(Ppb->hStdOutput))\r
+   if (IsConsoleHandle(Ppb->hStdOutput))
    {
-      Ppb->hStdOutput = CsrReply.Data.CreateProcessReply.OutputHandle;\r
+      Ppb->hStdOutput = CsrReply.Data.CreateProcessReply.OutputHandle;
    }
    else
    {
       DPRINT("Duplicate output handle\n");
       Status = NtDuplicateObject (NtCurrentProcess(), 
-                                 Ppb->hStdOutput,\r
+                                 Ppb->hStdOutput,
                                  hProcess,
-                                 &Ppb->hStdOutput,\r
+                                 &Ppb->hStdOutput,
                                  0,
                                  TRUE,
                                  DUPLICATE_SAME_ACCESS);
@@ -915,17 +1005,17 @@ CreateProcessW(LPCWSTR lpApplicationName,
         DPRINT("NtDuplicateObject failed, status %x\n", Status);
       }
    }
-   if (IsConsoleHandle(Ppb->hStdError))\r
+   if (IsConsoleHandle(Ppb->hStdError))
    {
-      Ppb->hStdError = CsrReply.Data.CreateProcessReply.OutputHandle;\r
+      Ppb->hStdError = CsrReply.Data.CreateProcessReply.OutputHandle;
    }
    else
    {
       DPRINT("Duplicate error handle\n");
       Status = NtDuplicateObject (NtCurrentProcess(), 
-                                 Ppb->hStdError,\r
+                                 Ppb->hStdError,
                                  hProcess,
-                                 &Ppb->hStdError,\r
+                                 &Ppb->hStdError,
                                  0,
                                  TRUE,
                                  DUPLICATE_SAME_ACCESS);
@@ -940,20 +1030,20 @@ CreateProcessW(LPCWSTR lpApplicationName,
     */
    if (lpStartupInfo)
      {
-       Ppb->dwFlags = lpStartupInfo->dwFlags;\r
-       if (Ppb->dwFlags & STARTF_USESHOWWINDOW)\r
+       Ppb->dwFlags = lpStartupInfo->dwFlags;
+       if (Ppb->dwFlags & STARTF_USESHOWWINDOW)
         {
-          Ppb->wShowWindow = lpStartupInfo->wShowWindow;\r
+          Ppb->wShowWindow = lpStartupInfo->wShowWindow;
         }
        else
         {
-          Ppb->wShowWindow = SW_SHOWDEFAULT;\r
+          Ppb->wShowWindow = SW_SHOWDEFAULT;
         }
-       Ppb->dwX = lpStartupInfo->dwX;\r
-       Ppb->dwY = lpStartupInfo->dwY;\r
-       Ppb->dwXSize = lpStartupInfo->dwXSize;\r
-       Ppb->dwYSize = lpStartupInfo->dwYSize;\r
-       Ppb->dwFillAttribute = lpStartupInfo->dwFillAttribute;\r
+       Ppb->dwX = lpStartupInfo->dwX;
+       Ppb->dwY = lpStartupInfo->dwY;
+       Ppb->dwXSize = lpStartupInfo->dwXSize;
+       Ppb->dwYSize = lpStartupInfo->dwYSize;
+       Ppb->dwFillAttribute = lpStartupInfo->dwFillAttribute;
      }
    else
      {