You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by mt...@apache.org on 2010/01/26 17:23:13 UTC

svn commit: r903304 - /commons/sandbox/runtime/trunk/src/main/native/support/win32/wsuexec.c

Author: mturk
Date: Tue Jan 26 16:23:13 2010
New Revision: 903304

URL: http://svn.apache.org/viewvc?rev=903304&view=rev
Log:
Stage 3 of wsuexec

Modified:
    commons/sandbox/runtime/trunk/src/main/native/support/win32/wsuexec.c

Modified: commons/sandbox/runtime/trunk/src/main/native/support/win32/wsuexec.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/support/win32/wsuexec.c?rev=903304&r1=903303&r2=903304&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/support/win32/wsuexec.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/support/win32/wsuexec.c Tue Jan 26 16:23:13 2010
@@ -40,11 +40,25 @@
  * Begin of argument processing code
  * ---------------------------------------------------------------------
  */
-#define ERRFAILED           0xE0000000
-#define ERRSUCESS           0x20000000
+#define ERRFAILED           0x80000000
+#define ERRSUCESS           0x40000000
+#define WIFPIDMASK          0x0FFFFFFF
+#define WIFERRMASK          0x0FFFFFFF
+#define WIFSTATMASK         0xC0000000
+
+#define WIFEXITED(S)        (((S)  & WIFPIDMASK) == (S))
+#define WIFSIGNALED(S)      ((S)   & ERRFAILED)
+#define WEXITSTATUS(S)      ((((S) & ~WIFERRMASK) << 2) == WIFSTATMASK ? \
+                              ((S) | ~WIFERRMASK) : ((((S) & ~WIFERRMASK) << 2) | (S) & WIFERRMASK))
+#define WEXITERROR(S)       ((((S) & ~WIFERRMASK) << 2) | ((S) & WIFERRMASK))
+#define WEXITPID(S)         ((S)   & WIFPIDMASK)
+
+#define RWEXITPID(S)        ((S)   & WIFPIDMASK)
+#define RWEXITSTATUS(S)     ((((S) >> 2) & ~WIFERRMASK) | ((S) & WIFERRMASK) | ERRSUCESS)
+#define RWEXITERROR(S)      ((((S) >> 2) & ~WIFERRMASK) | ((S) & WIFERRMASK) | ERRFAILED)
+
+#define GWEXITERROR()       RWEXITERROR(GetLastError())
 
-#define RCERROR(x)          ((x) | ERRFAILED)
-#define GETLASTERROR()      (GetLastError() | ERRFAILED)
 #define RESOURCE_NAME_LEN   64
 #define RESOURCE_SSID_LEN   256
 #define RESOURCE_USER_LEN   256
@@ -571,7 +585,7 @@
 /* To share the objects with other processes, we need a NULL ACL
  * Code from MS KB Q106387
  */
-PSECURITY_ATTRIBUTES GetSaWithNullDacl()
+PSECURITY_ATTRIBUTES GetSaWithNullDacl(BOOL bInherit)
 {
     DWORD rc = 0;
     PSECURITY_DESCRIPTOR pSD;
@@ -601,7 +615,7 @@
         goto cleanup;
     }
     pNullSA->lpSecurityDescriptor = pSD;
-    pNullSA->bInheritHandle       = FALSE;
+    pNullSA->bInheritHandle       = bInherit;
 
     SetLastError(0);
     return pNullSA;
@@ -749,7 +763,7 @@
         *lphToken = INVALID_HANDLE_VALUE;
     }
     CloseHandle(hProcess);
-    if (!DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, GetSaWithNullDacl(),
+    if (!DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, GetSaWithNullDacl(FALSE),
                           SecurityIdentification, TokenPrimary,
                           lphToken)) {
         CloseHandle(hToken);
@@ -825,7 +839,7 @@
         return FALSE;
     }
     CloseHandle(hProcess);
-    rs = DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, GetSaWithNullDacl(),
+    rs = DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, GetSaWithNullDacl(FALSE),
                           SecurityIdentification, TokenPrimary,
                           lphToken);
     CloseHandle(hToken);
@@ -852,7 +866,7 @@
         if (rc != ERROR_SUCCESS)
             return FALSE;
     }
-    if (!DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, GetSaWithNullDacl(),
+    if (!DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, GetSaWithNullDacl(FALSE),
                           SecurityIdentification, TokenPrimary,
                           lphToken)) {
         CloseHandle(hToken);
@@ -1174,7 +1188,7 @@
         return NULL;
     }
     hShm = CreateFileMappingW(INVALID_HANDLE_VALUE,
-                              GetSaWithNullDacl(),
+                              GetSaWithNullDacl(FALSE),
                               PAGE_READWRITE,
                               0,
                               cbSize,
@@ -1244,7 +1258,7 @@
                                   0,
                                   65536,
                                   1,
-                                  GetSaWithNullDacl());
+                                  GetSaWithNullDacl(FALSE));
         if (IS_INVALID_HANDLE(hRpipe))
             return FALSE;
     }
@@ -1256,7 +1270,7 @@
         hWpipe = CreateFileW(szPipeName,
                              GENERIC_WRITE,
                              0,
-                             GetSaWithNullDacl(),
+                             GetSaWithNullDacl(FALSE),
                              OPEN_EXISTING,
                              dwOpenMode,
                              NULL);
@@ -1298,7 +1312,7 @@
     hNull = CreateFileW(L"NUL",
                         dwFlags,
                         0,
-                        GetSaWithNullDacl(),
+                        GetSaWithNullDacl(FALSE),
                         OPEN_EXISTING,
                         FILE_ATTRIBUTE_NORMAL,
                         NULL);
@@ -1629,14 +1643,14 @@
                               MEM_COMMIT | MEM_RESERVE,
                               PAGE_READWRITE | PAGE_NOCACHE);
     if (!lpForkData) {
-        rc =  GETLASTERROR();
+        rc =  GWEXITERROR();
         DBG_PRINTF((__LINE__, "[ERROR] VirtualAlloc err=%d", GetLastError()));
         goto cleanup;
     }
     lpForkData->cb  = sizeof(FORK_DATA);
     hCurrentProcess = GetCurrentProcess();
     if (!GetCurrentAccessToken(&hToken)) {
-        rc = GETLASTERROR();
+        rc = GWEXITERROR();
         DBG_PRINTF((__LINE__, "[ERROR] GetCurrentAccessToken err=%d", GetLastError()));
         goto cleanup;
     }
@@ -1647,7 +1661,7 @@
     DBG_PRINTF((__LINE__, "[INFO] Running in Session %d", dwSourceSessionId));
     args = CommandLineToArrayW(GetCommandLineW(), &argc);
     if (args == NULL) {
-        rc = GETLASTERROR();
+        rc = GWEXITERROR();
         DBG_PRINTF((__LINE__, "[ERROR] CommandLineToArrayW err=%d", GetLastError()));
         goto cleanup;
     }
@@ -1690,7 +1704,7 @@
             else if (*opt == L't') {
                 if (!val || !*val) {
                     /* Invalid timeout argument */
-                    rc = RCERROR(ERROR_INVALID_PARAMETER);
+                    rc = RWEXITERROR(ERROR_INVALID_PARAMETER);
                     DBG_PRINTF((__LINE__, "[ERROR] Missing Timeout param"));
                     goto cleanup;
                 }
@@ -1698,7 +1712,7 @@
                 lpForkData->dwTimeout = (DWORD)wcstoul(val, &cep, 10);
                 if (*cep) {
                     /* Invalid timeout argument */
-                    rc = RCERROR(ERROR_INVALID_PARAMETER);
+                    rc = RWEXITERROR(ERROR_INVALID_PARAMETER);
                     DBG_PRINTF((__LINE__, "[ERROR] Invalid Timeout param %S", val));
                     goto cleanup;
                 }
@@ -1714,7 +1728,7 @@
                     dwTargetSessionId = (DWORD)wcstoul(val, &cep, 10);
                     if (*cep) {
                         /* Invalid parent pid argument */
-                        rc = RCERROR(ERROR_INVALID_PARAMETER);
+                        rc = RWEXITERROR(ERROR_INVALID_PARAMETER);
                         DBG_PRINTF((__LINE__, "[ERROR] Invalid Session param %S", val));
                         goto cleanup;
                     }
@@ -1725,7 +1739,7 @@
                 if (val)
                     wcslcpy(lpForkData->szpCryptoSalt, val, RESOURCE_NAME_LEN);
                 else {
-                    rc = RCERROR(ERROR_INVALID_PARAMETER);
+                    rc = RWEXITERROR(ERROR_INVALID_PARAMETER);
                     DBG_PRINTF((__LINE__, "[ERROR] Param --h is missing"));
                     goto cleanup;
                 }
@@ -1733,7 +1747,7 @@
             else if (*opt == L'u' && val) {
                 DWORD cb = RESOURCE_SSID_LEN;
                 if (!GetStringSidFromAccountName(val, lpForkData->szUserSsid, &cb)) {
-                    rc = GETLASTERROR();
+                    rc = GWEXITERROR();
                     DBG_PRINTF((__LINE__, "[ERROR] GetStringSidFromAccountName %S err=%d", val, GetLastError()));
                     goto cleanup;
                 }
@@ -1750,7 +1764,7 @@
                                      lpForkData->szpCryptoSalt,
                                      lpForkData->bpEncPassword,
                                     &lpForkData->cbEncPassword)) {
-                    rc = RCERROR(ERROR_INVALID_PARAMETER);
+                    rc = RWEXITERROR(ERROR_INVALID_PARAMETER);
                     DBG_PRINTF((__LINE__, "[ERROR] EncryptPassword err=%d", GetLastError()));
                     goto cleanup;
                 }
@@ -1808,7 +1822,7 @@
             }
             else {
                 DBG_PRINTF((__LINE__, "[ERROR] Unknown command option: --%S[=%S]", val, opt));
-                rc = RCERROR(ERROR_INVALID_PARAMETER);
+                rc = RWEXITERROR(ERROR_INVALID_PARAMETER);
                 goto cleanup;
             }
         }
@@ -1826,7 +1840,7 @@
     if (bFork) {
         const wchar_t *c[3] = { _wpgmptr, szVmsMem, NULL };
         if (!(argv = MergeArrays(c, argv))) {
-            rc = GETLASTERROR();
+            rc = GWEXITERROR();
             DBG_PRINTF((__LINE__, "[ERROR] MergeArrays err=%d", GetLastError()));
             goto cleanup;
         }
@@ -1837,19 +1851,19 @@
             /* We don't have the valid
              * for the supplied parent
              */
-            rc = RCERROR(ERROR_INVALID_PARAMETER);
+            rc = RWEXITERROR(ERROR_INVALID_PARAMETER);
             DBG_PRINTF((__LINE__, "[ERROR] Missing Memory Pointer for %d", dwParentPid));
             goto cleanup;
         }
         hParent = OpenProcess(PROCESS_VM_READ, FALSE, dwParentPid);
         if (IS_INVALID_HANDLE(hParent)) {
-            rc = GETLASTERROR();
+            rc = GWEXITERROR();
             DBG_PRINTF((__LINE__, "[ERROR] OpenProcess %d err=%d", dwParentPid, GetLastError()));
             goto cleanup;
         }
         if (!ReadProcessMemory(hParent, lpVmsPtr,
                                lpForkData, sizeof(FORK_DATA), NULL)) {
-            rc = GETLASTERROR();
+            rc = GWEXITERROR();
             DBG_PRINTF((__LINE__, "[ERROR] ReadProcessMemory err=%d", GetLastError()));
             goto cleanup;
         }
@@ -1858,12 +1872,12 @@
     if (argc < 1) {
         /* We need at least one argument.
          */
-        rc = RCERROR(ERROR_INVALID_PARAMETER);
+        rc = RWEXITERROR(ERROR_INVALID_PARAMETER);
         DBG_PRINTF((__LINE__, "[ERROR] Invalid Nuber of Arguments"));
         goto cleanup;
     }
     if (!(cmdline = ArgvToCommandLineW(argv))) {
-        rc = RCERROR(ERROR_NOT_ENOUGH_MEMORY);
+        rc = RWEXITERROR(ERROR_NOT_ENOUGH_MEMORY);
         DBG_PRINTF((__LINE__, "[ERROR] ArgvToCommandLineW err=%d", GetLastError()));
         goto cleanup;
     }
@@ -1889,7 +1903,7 @@
                 /* Failed to obtain required Session token.
                  * Probably we are missing privileges
                  */
-                rc = GETLASTERROR();
+                rc = GWEXITERROR();
                 DBG_PRINTF((__LINE__, "[ERROR] GetSession0Token err=%d", GetLastError()));
                 goto cleanup;
             }
@@ -1902,7 +1916,7 @@
                 /* Failed to obtain required Session token.
                  * Probably we are missing privileges
                  */
-                rc = GETLASTERROR();
+                rc = GWEXITERROR();
                 DBG_PRINTF((__LINE__, "[ERROR] GetSessionToken session=%d err=%d", dwTargetSessionId, GetLastError()));
                 goto cleanup;
             }
@@ -1926,7 +1940,7 @@
                                   &si,
                                   &pi);
         if (!rs) {
-            rc = GETLASTERROR();
+            rc = GWEXITERROR();
             DBG_PRINTF((__LINE__, "[ERROR] CreateProcessAsUserW proc=%S err=%d", argv[0], rc));
             goto cleanup;
         }
@@ -1944,7 +1958,7 @@
              * Return the child pid in the exit code
              */
             rc = pi.dwProcessId;
-            goto finally;
+            goto cleanup;
         }
         /* Wait until forked child exits. It will report us the
          * PID of the grand child in the return value
@@ -1952,24 +1966,23 @@
         rc = WaitForSingleObject(pi.hProcess, INFINITE);
         if (rc == WAIT_OBJECT_0) {
             if (!GetExitCodeProcess(pi.hProcess, &dwChildExitval)) {
-                rc = GETLASTERROR();
+                rc = GWEXITERROR();
                 DBG_PRINTF((__LINE__, "[ERROR] GetExitCodeProcess pid=%d err=%d", pi.dwProcessId, GetLastError()));
-                goto cleanup;
             }
             else {
                 DBG_PRINTF((__LINE__, "[INFO] GetExitCodeProcess pid=%d exitval=%08X", pi.dwProcessId, dwChildExitval));
-                /* Unmask the exit value */
-                rc = dwChildExitval & ~ERRSUCESS;
+                rc = dwChildExitval;
+                goto cleanup;
             }
         }
         else {
-            DWORD wr = rc;
+            DWORD ws = rc;
             /* Something wrong with the wait */
-            rc = GETLASTERROR();
+            rc = GWEXITERROR();
             DBG_PRINTF((__LINE__, "[ERROR] WaitForSingleObject wait=%d err=%d",
-                        wr, GetLastError()));
-            goto cleanup;
+                        ws, GetLastError()));
         }
+        goto cleanup;
     }
     else {
         /* We are inside forked child.
@@ -1992,7 +2005,7 @@
                                 NULL,
                                 lpForkData->szStdInpName,
                                 PIPE_FULL_BLOCK)) {
-                rc = GETLASTERROR();
+                rc = GWEXITERROR();
                 DBG_PRINTF((__LINE__, "[ERROR] CreatePipePair pipe=%S err=%d",
                             lpForkData->szStdInpName, GetLastError()));
                 goto cleanup;
@@ -2010,7 +2023,7 @@
                                 &hPipes[PIPE_STDINP_WRS],
                                 NULL,
                                 PIPE_READ_BLOCK)) {
-                rc = GETLASTERROR();
+                rc = GWEXITERROR();
                 DBG_PRINTF((__LINE__, "[ERROR] CreatePipePair err=%d",
                             GetLastError()));
                 goto cleanup;
@@ -2020,7 +2033,7 @@
             if (!lpForkData->szDllEntry[0] &&
                 !CreateNullPipe(&hPipes[PIPE_STDINP_RDS],
                                 GENERIC_READ)) {
-                rc = GETLASTERROR();
+                rc = GWEXITERROR();
                 DBG_PRINTF((__LINE__, "[ERROR] CreateNullPipe err=%d",
                             GetLastError()));
                 goto cleanup;
@@ -2035,7 +2048,7 @@
                                 &hPpipe[PIPE_STDOUT_RPC],
                                 lpForkData->szStdOutName,
                                 PIPE_FULL_BLOCK)) {
-                rc = GETLASTERROR();
+                rc = GWEXITERROR();
                 DBG_PRINTF((__LINE__, "[ERROR] CreatePipePair pipe=%S err=%d",
                             lpForkData->szStdOutName, GetLastError()));
                 goto cleanup;
@@ -2047,7 +2060,7 @@
                                 &hPipes[PIPE_STDOUT_WRS],
                                 NULL,
                                 PIPE_WRITE_BLOCK)) {
-                rc = GETLASTERROR();
+                rc = GWEXITERROR();
                 DBG_PRINTF((__LINE__, "[ERROR] CreatePipePair err=%d",
                             GetLastError()));
                 goto cleanup;
@@ -2057,7 +2070,7 @@
             if (!lpForkData->szDllEntry[0] &&
                 !CreateNullPipe(&hPipes[PIPE_STDOUT_WRS],
                                 GENERIC_WRITE)) {
-                rc = GETLASTERROR();
+                rc = GWEXITERROR();
                 DBG_PRINTF((__LINE__, "[ERROR] CreateNullPipe err=%d",
                             GetLastError()));
                 goto cleanup;
@@ -2072,7 +2085,7 @@
                                 &hPpipe[PIPE_STDERR_RPC],
                                 lpForkData->szStdErrName,
                                 PIPE_FULL_BLOCK)) {
-                rc = GETLASTERROR();
+                rc = GWEXITERROR();
                 DBG_PRINTF((__LINE__, "[ERROR] CreatePipePair pipe=%S err=%d",
                             lpForkData->szStdErrName, GetLastError()));
                 goto cleanup;
@@ -2084,7 +2097,7 @@
                                 &hPipes[PIPE_STDERR_WRS],
                                 NULL,
                                 PIPE_WRITE_BLOCK)) {
-                rc = GETLASTERROR();
+                rc = GWEXITERROR();
                 DBG_PRINTF((__LINE__, "[ERROR] CreatePipePair err=%d",
                             GetLastError()));
                 goto cleanup;
@@ -2094,7 +2107,7 @@
             if (!lpForkData->szDllEntry[0] &&
                 !CreateNullPipe(&hPipes[PIPE_STDERR_WRS],
                                 GENERIC_WRITE)) {
-                rc = GETLASTERROR();
+                rc = GWEXITERROR();
                 DBG_PRINTF((__LINE__, "[ERROR] CreateNullPipe err=%d",
                             GetLastError()));
                 goto cleanup;
@@ -2107,18 +2120,38 @@
                 hPipes[PIPE_STDERR_WRS] = hPipes[PIPE_STDOUT_WRS];
         }
         if (lpForkData->szDllEntry[0]) {
-
+            /* Setup std descriptors do we can used them
+             * immediately from DllMain
+             */
+            if (IS_VALID_HANDLE(hPpipe[PIPE_STDINP_RPC])) {
+                int fd = _open_osfhandle((ptrdiff_t)hPpipe[PIPE_STDINP_RPC], _O_RDONLY);
+                if (fd > 0)
+                    dup2(fd, 0);
+                hPpipe[PIPE_STDINP_RPC] = NULL;
+            }
+            if (IS_VALID_HANDLE(hPpipe[PIPE_STDOUT_RPC])) {
+                int fd = _open_osfhandle((ptrdiff_t)hPpipe[PIPE_STDOUT_RPC], _O_WRONLY);
+                if (fd > 1)
+                    dup2(fd, 1);
+                hPpipe[PIPE_STDOUT_RPC] = NULL;
+            }
+            if (IS_VALID_HANDLE(hPpipe[PIPE_STDERR_RPC])) {
+                int fd = _open_osfhandle((ptrdiff_t)hPpipe[PIPE_STDERR_RPC], _O_WRONLY);
+                if (fd > 2)
+                    dup2(fd, 2);
+                hPpipe[PIPE_STDERR_RPC] = NULL;
+            }
             DBG_PRINTF((__LINE__, "[INFO] LoadLibrary dll=%S func=%s", argv[0], lpForkData->szDllEntry));
             hModule = LoadLibraryW(argv[0]);
             if (IS_INVALID_HANDLE(hModule)) {
-                rc = GETLASTERROR();
+                rc = GWEXITERROR();
                 DBG_PRINTF((__LINE__, "[ERROR] LoadLibrary dll=%S err=%d", argv[0], GetLastError()));
                 goto cleanup;
             }
 
             fnDllMain = (lpfnDllMain)GetProcAddress(hModule, lpForkData->szDllEntry);
             if (!fnDllMain) {
-                rc = GETLASTERROR();
+                rc = GWEXITERROR();
                 DBG_PRINTF((__LINE__, "[ERROR] GetProcAddress func=%s err=%d", lpForkData->szDllEntry, GetLastError()));
                 goto cleanup;
             }
@@ -2130,7 +2163,7 @@
                 if (!DecryptPassword(lpForkData->bpEncPassword,
                                      lpForkData->cbEncPassword,
                                      lpForkData->szpCryptoSalt, szPassword)) {
-                    rc = GETLASTERROR();
+                    rc = GWEXITERROR();
                     DBG_PRINTF((__LINE__, "[ERROR] DecryptPassword err=%d", GetLastError()));
                     goto cleanup;
                 }
@@ -2140,7 +2173,7 @@
                 if (!StoreEncryptedPassword(lpForkData->szUserSsid,
                                             lpForkData->bpEncPassword,
                                             lpForkData->cbEncPassword)) {
-                    rc = GETLASTERROR();
+                    rc = GWEXITERROR();
                     DBG_PRINTF((__LINE__, "[ERROR] StoreEncryptedPassword err=%d", GetLastError()));
                     goto cleanup;
                 }
@@ -2157,7 +2190,7 @@
                                          lpForkData->cbEncPassword,
                                          lpForkData->szpCryptoSalt,
                                          szPassword)) {
-                        rc = GETLASTERROR();
+                        rc = GWEXITERROR();
                         DBG_PRINTF((__LINE__, "[ERROR] DecryptPassword err=%d", GetLastError()));
                         goto cleanup;
                     }
@@ -2181,7 +2214,7 @@
                            LOGON32_LOGON_NETWORK,
                            LOGON32_PROVIDER_DEFAULT,
                            &hUser)) {
-                rc = GETLASTERROR();
+                rc = GWEXITERROR();
                 DBG_PRINTF((__LINE__, "[ERROR] LogonUser user=%S err=%d", lpForkData->szUserName, GetLastError()));
                 goto cleanup;
 
@@ -2192,7 +2225,7 @@
             if (!DuplicateTokenEx(hUser, MAXIMUM_ALLOWED, NULL,
                                   SecurityImpersonation, TokenPrimary,
                                   &hToken)) {
-                rc = GETLASTERROR();
+                rc = GWEXITERROR();
                 DBG_PRINTF((__LINE__, "[ERROR] DuplicateTokenEx err=%d", GetLastError()));
                 CloseHandle(hUser);
                 goto cleanup;
@@ -2204,7 +2237,7 @@
             if (!ImpersonateLoggedOnUser(hToken)) {
                 /* Althugh logged in, we cannot imersonate the user
                  */
-                rc = GETLASTERROR();
+                rc = GWEXITERROR();
                 DBG_PRINTF((__LINE__, "[ERROR] ImpersonateLoggedOnUser err=%d", GetLastError()));
                 goto cleanup;
             }
@@ -2213,25 +2246,6 @@
                          RESOURCE_NAME_LEN * sizeof(WCHAR));
 
         if (fnDllMain) {
-            /* Setup std descriptors */
-            if (IS_VALID_HANDLE(hPpipe[PIPE_STDINP_RPC])) {
-                int fd = _open_osfhandle((intptr_t)hPpipe[PIPE_STDINP_RPC], _O_RDONLY);
-                if (fd > 0)
-                    dup2(fd, 0);
-                hPpipe[PIPE_STDINP_RPC] = NULL;
-            }
-            if (IS_VALID_HANDLE(hPpipe[PIPE_STDOUT_RPC])) {
-                int fd = _open_osfhandle((intptr_t)hPpipe[PIPE_STDOUT_RPC], _O_WRONLY);
-                if (fd > 1)
-                    dup2(fd, 1);
-                hPpipe[PIPE_STDOUT_RPC] = NULL;
-            }
-            if (IS_VALID_HANDLE(hPpipe[PIPE_STDERR_RPC])) {
-                int fd = _open_osfhandle((intptr_t)hPpipe[PIPE_STDERR_RPC], _O_WRONLY);
-                if (fd > 2)
-                    dup2(fd, 2);
-                hPpipe[PIPE_STDERR_RPC] = NULL;
-            }
             /* Execute the Loaded DLL enty point.
              * Note that we call RevertToSelf afterwards meaning
              * that we run under the impersonated user account.
@@ -2244,7 +2258,7 @@
             DBG_PRINTF((__LINE__, "[INFO] DLL Module rv=%d", rc));
             if (lpForkData->szUserName[0])
                 RevertToSelf();
-            rc &= ~ERRFAILED;
+            rc = RWEXITSTATUS(rc);
         }
         else {
             LPWCH lpEnv = NULL;
@@ -2252,14 +2266,14 @@
                 if (!RevertToSelf()) {
                     /* If RevertToSelf fails, bail out.
                      */
-                    rc = GETLASTERROR();
+                    rc = GWEXITERROR();
                     DBG_PRINTF((__LINE__, "[ERROR] RevertToSelf err=%d", GetLastError()));
                     goto cleanup;
                 }
             }
             if (lpForkData->bUseCgiEnv) {
                 if (!(lpEnv = GetSafeEnvironmentBlock(lpForkData->szSafeEnvars))) {
-                    rc = GETLASTERROR();
+                    rc = GWEXITERROR();
                     DBG_PRINTF((__LINE__, "[ERROR] GetSafeEnvironmentBlock err=%d", GetLastError()));
                     goto cleanup;
                 }
@@ -2290,7 +2304,7 @@
                                       &pi);
 
             if (!rs) {
-                rc = GETLASTERROR();
+                rc = GWEXITERROR();
                 DBG_PRINTF((__LINE__, "[ERROR] CreateProcessAsUserW %S err=%d", argv[0], rc));
                 x_free(lpEnv);
                 goto cleanup;
@@ -2300,14 +2314,14 @@
             SAFE_CLOSE_HANDLE(hPipes[PIPE_STDINP_RDS]);
             SAFE_CLOSE_HANDLE(hPipes[PIPE_STDOUT_WRS]);
             SAFE_CLOSE_HANDLE(hPipes[PIPE_STDERR_WRS]);
-            /* Our exit value will contain the child pid
-             */
-            rc = pi.dwProcessId;
             ResumeThread(pi.hThread);
             x_free(lpEnv);
             if (lpForkData->dwTimeout == 0) {
-                /* Detached process */
-                goto finally;
+                /* Detached process.
+                 * Our exit value will contain the child pid
+                 */
+                rc = RWEXITPID(pi.dwProcessId);
+                goto cleanup;
             }
 
             /* Setup wait handles
@@ -2540,25 +2554,32 @@
             if (rc != ERROR_NO_MORE_FILES) {
                 /* Kill the process */
                 TerminateProcess(pi.hProcess, 9);
+                rc = RWEXITERROR(rc);
+                goto cleanup;
             }
-            /* XXX: How long should we wait for TerminateProcess ? */
-            switch (WaitForSingleObject(pi.hProcess, 1000) {
+            /* Wait for the remaining of the timeout left if any */
+            if ((dwTimeout = GetTimeRunning()) > lpForkData->dwTimeout)
+                dwTimeout = 0;
+            else
+                dwTimeout = lpForkData->dwTimeout - dwTimeout;
+            switch (WaitForSingleObject(pi.hProcess, dwTimeout)) {
                 case WAIT_OBJECT_0:
-                    GetExitCodeProcess(pi.hProcess, &rc);
+                    GetExitCodeProcess(pi.hProcess, &dwChildExitval);
+                    /* Unmask the return value.
+                     * This is the only place where we can have problems
+                     * reporting the real child exit value.
+                     */
+                    rc = RWEXITSTATUS(dwChildExitval);
                 break;
                 default:
+                    DBG_PRINTF((__LINE__, "[INFO] TerminateProcess pid=%d", pi.dwProcessId));
                     TerminateProcess(pi.hProcess, 9);
-                     rc = 9;
+                    rc = RWEXITERROR(ERROR_TIMEOUT);
                 break;
             }
         }
     }
 
-finally:
-    /* Mask the value with ERRSUCESS
-     */
-    rc |= ERRSUCESS;
-
 cleanup:
     SAFE_CLOSE_HANDLE(hModule);
     SAFE_CLOSE_HANDLE(hParent);
@@ -2591,5 +2612,15 @@
      * but add Error Severity and Customer code set.
      */
     DBG_PRINTF((__LINE__, "[INFO] ExitMain rv=%08X", rc));
+    if (WIFEXITED(rc)) {
+        DBG_PRINTF((__LINE__, "[INFO] Exited pid=%08X", WEXITPID(rc)));
+    }
+    else if (WIFSIGNALED(rc)) {
+        DBG_PRINTF((__LINE__, "[INFO] Exited error=%08X", WEXITERROR(rc)));
+    }
+    else  {
+        DBG_PRINTF((__LINE__, "[INFO] Exited status=%08X", WEXITSTATUS(rc)));
+    }
     return rc;
 }
+