Erich E. Hoover : kernel32: Invalid console handles for new processes are 0, not INVALID_HANDLE_VALUE.

Alexandre Julliard julliard at wine.codeweavers.com
Thu Apr 23 07:04:14 CDT 2015


Module: wine
Branch: master
Commit: 4b559f02dd6ad61287fb79547c93105aaa2f7525
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=4b559f02dd6ad61287fb79547c93105aaa2f7525

Author: Erich E. Hoover <erich.e.hoover at wine-staging.com>
Date:   Sat Jan  3 23:37:42 2015 -0700

kernel32: Invalid console handles for new processes are 0, not INVALID_HANDLE_VALUE.

---

 dlls/kernel32/console.c       | 15 ++++++------
 dlls/kernel32/environ.c       | 12 +++++-----
 dlls/kernel32/tests/process.c | 53 ++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 66 insertions(+), 14 deletions(-)

diff --git a/dlls/kernel32/console.c b/dlls/kernel32/console.c
index 303b638..14f1189 100644
--- a/dlls/kernel32/console.c
+++ b/dlls/kernel32/console.c
@@ -3119,24 +3119,25 @@ BOOL CONSOLE_Init(RTL_USER_PROCESS_PARAMETERS *params)
     }
 
     /* convert value from server:
-     * + 0 => INVALID_HANDLE_VALUE
+     * + INVALID_HANDLE_VALUE => TEB: 0, STARTUPINFO: INVALID_HANDLE_VALUE
+     * + 0                    => TEB: 0, STARTUPINFO: INVALID_HANDLE_VALUE
      * + console handle needs to be mapped
      */
-    if (!params->hStdInput)
-        params->hStdInput = INVALID_HANDLE_VALUE;
+    if (!params->hStdInput || params->hStdInput == INVALID_HANDLE_VALUE)
+        params->hStdInput = 0;
     else if (VerifyConsoleIoHandle(console_handle_map(params->hStdInput)))
     {
         params->hStdInput = console_handle_map(params->hStdInput);
         save_console_mode(params->hStdInput);
     }
 
-    if (!params->hStdOutput)
-        params->hStdOutput = INVALID_HANDLE_VALUE;
+    if (!params->hStdOutput || params->hStdOutput == INVALID_HANDLE_VALUE)
+        params->hStdOutput = 0;
     else if (VerifyConsoleIoHandle(console_handle_map(params->hStdOutput)))
         params->hStdOutput = console_handle_map(params->hStdOutput);
 
-    if (!params->hStdError)
-        params->hStdError = INVALID_HANDLE_VALUE;
+    if (!params->hStdError || params->hStdError == INVALID_HANDLE_VALUE)
+        params->hStdError = 0;
     else if (VerifyConsoleIoHandle(console_handle_map(params->hStdError)))
         params->hStdError = console_handle_map(params->hStdError);
 
diff --git a/dlls/kernel32/environ.c b/dlls/kernel32/environ.c
index 57b6a1f..99bf706 100644
--- a/dlls/kernel32/environ.c
+++ b/dlls/kernel32/environ.c
@@ -464,9 +464,9 @@ void ENV_CopyStartupInformation(void)
     startup_infoW.wShowWindow          = rupp->wShowWindow;
     startup_infoW.cbReserved2          = rupp->RuntimeInfo.MaximumLength;
     startup_infoW.lpReserved2          = rupp->RuntimeInfo.MaximumLength ? (void*)rupp->RuntimeInfo.Buffer : NULL;
-    startup_infoW.hStdInput            = rupp->hStdInput;
-    startup_infoW.hStdOutput           = rupp->hStdOutput;
-    startup_infoW.hStdError            = rupp->hStdError;
+    startup_infoW.hStdInput            = rupp->hStdInput ? rupp->hStdInput : INVALID_HANDLE_VALUE;
+    startup_infoW.hStdOutput           = rupp->hStdOutput ? rupp->hStdOutput : INVALID_HANDLE_VALUE;
+    startup_infoW.hStdError            = rupp->hStdError ? rupp->hStdError : INVALID_HANDLE_VALUE;
 
     startup_infoA.cb                   = sizeof(startup_infoA);
     startup_infoA.lpReserved           = NULL;
@@ -485,9 +485,9 @@ void ENV_CopyStartupInformation(void)
     startup_infoA.wShowWindow          = rupp->wShowWindow;
     startup_infoA.cbReserved2          = rupp->RuntimeInfo.MaximumLength;
     startup_infoA.lpReserved2          = rupp->RuntimeInfo.MaximumLength ? (void*)rupp->RuntimeInfo.Buffer : NULL;
-    startup_infoA.hStdInput            = rupp->hStdInput;
-    startup_infoA.hStdOutput           = rupp->hStdOutput;
-    startup_infoA.hStdError            = rupp->hStdError;
+    startup_infoA.hStdInput            = rupp->hStdInput ? rupp->hStdInput : INVALID_HANDLE_VALUE;
+    startup_infoA.hStdOutput           = rupp->hStdOutput ? rupp->hStdOutput : INVALID_HANDLE_VALUE;
+    startup_infoA.hStdError            = rupp->hStdError ? rupp->hStdError : INVALID_HANDLE_VALUE;
 
     RtlReleasePebLock();
 }
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
index c63d6b1..4f7c58d 100644
--- a/dlls/kernel32/tests/process.c
+++ b/dlls/kernel32/tests/process.c
@@ -57,7 +57,7 @@
           wine_dbgstr_w(expected), wine_dbgstr_w(value)); \
     } while (0)
 
-static HINSTANCE hkernel32;
+static HINSTANCE hkernel32, hntdll;
 static void   (WINAPI *pGetNativeSystemInfo)(LPSYSTEM_INFO);
 static BOOL   (WINAPI *pGetSystemRegistryQuota)(PDWORD, PDWORD);
 static BOOL   (WINAPI *pIsWow64Process)(HANDLE,PBOOL);
@@ -66,6 +66,7 @@ static BOOL   (WINAPI *pVirtualFreeEx)(HANDLE, LPVOID, SIZE_T, DWORD);
 static BOOL   (WINAPI *pQueryFullProcessImageNameA)(HANDLE hProcess, DWORD dwFlags, LPSTR lpExeName, PDWORD lpdwSize);
 static BOOL   (WINAPI *pQueryFullProcessImageNameW)(HANDLE hProcess, DWORD dwFlags, LPWSTR lpExeName, PDWORD lpdwSize);
 static DWORD  (WINAPI *pK32GetProcessImageFileNameA)(HANDLE,LPSTR,DWORD);
+static struct _TEB * (WINAPI *pNtCurrentTeb)(void);
 static HANDLE (WINAPI *pCreateJobObjectW)(LPSECURITY_ATTRIBUTES sa, LPCWSTR name);
 static BOOL   (WINAPI *pAssignProcessToJobObject)(HANDLE job, HANDLE process);
 static BOOL   (WINAPI *pIsProcessInJob)(HANDLE process, HANDLE job, PBOOL result);
@@ -208,6 +209,8 @@ static BOOL init(void)
     if ((p = strrchr(exename, '/')) != NULL) exename = p + 1;
 
     hkernel32 = GetModuleHandleA("kernel32");
+    hntdll    = GetModuleHandleA("ntdll.dll");
+
     pGetNativeSystemInfo = (void *) GetProcAddress(hkernel32, "GetNativeSystemInfo");
     pGetSystemRegistryQuota = (void *) GetProcAddress(hkernel32, "GetSystemRegistryQuota");
     pIsWow64Process = (void *) GetProcAddress(hkernel32, "IsWow64Process");
@@ -216,6 +219,7 @@ static BOOL init(void)
     pQueryFullProcessImageNameA = (void *) GetProcAddress(hkernel32, "QueryFullProcessImageNameA");
     pQueryFullProcessImageNameW = (void *) GetProcAddress(hkernel32, "QueryFullProcessImageNameW");
     pK32GetProcessImageFileNameA = (void *) GetProcAddress(hkernel32, "K32GetProcessImageFileNameA");
+    pNtCurrentTeb = (void *)GetProcAddress(hntdll, "NtCurrentTeb");
     pCreateJobObjectW = (void *)GetProcAddress(hkernel32, "CreateJobObjectW");
     pAssignProcessToJobObject = (void *)GetProcAddress(hkernel32, "AssignProcessToJobObject");
     pIsProcessInJob = (void *)GetProcAddress(hkernel32, "IsProcessInJob");
@@ -291,6 +295,16 @@ static void     doChild(const char* file, const char* option)
                 siA.dwFlags, siA.wShowWindow,
                 (DWORD_PTR)siA.hStdInput, (DWORD_PTR)siA.hStdOutput, (DWORD_PTR)siA.hStdError);
 
+    if (pNtCurrentTeb)
+    {
+        RTL_USER_PROCESS_PARAMETERS *params = pNtCurrentTeb()->Peb->ProcessParameters;
+
+        /* check the console handles in the TEB */
+        childPrintf(hFile, "[TEB]\nhStdInput=%lu\nhStdOutput=%lu\nhStdError=%lu\n\n",
+                    (DWORD_PTR)params->hStdInput, (DWORD_PTR)params->hStdOutput,
+                    (DWORD_PTR)params->hStdError);
+    }
+
     /* since GetStartupInfoW is only implemented in win2k,
      * zero out before calling so we can notice the difference
      */
@@ -2642,6 +2656,42 @@ static void test_BreakawayOk(HANDLE job)
     ok(ret, "SetInformationJobObject error %u\n", GetLastError());
 }
 
+void test_StartupNoConsole(void)
+{
+#ifndef _WIN64
+    char                buffer[MAX_PATH];
+    STARTUPINFOA        startup;
+    PROCESS_INFORMATION info;
+    DWORD               code;
+
+    if (!pNtCurrentTeb)
+    {
+        win_skip( "NtCurrentTeb not supported\n" );
+        return;
+    }
+
+    memset(&startup, 0, sizeof(startup));
+    startup.cb = sizeof(startup);
+    startup.dwFlags = STARTF_USESHOWWINDOW;
+    startup.wShowWindow = SW_SHOWNORMAL;
+    get_file_name(resfile);
+    sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, resfile);
+    ok(CreateProcessA(NULL, buffer, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &startup,
+                      &info), "CreateProcess\n");
+    ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
+    ok(GetExitCodeProcess(info.hProcess, &code), "Getting exit code\n");
+    WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
+    okChildInt("StartupInfoA", "hStdInput", (UINT)INVALID_HANDLE_VALUE);
+    okChildInt("StartupInfoA", "hStdOutput", (UINT)INVALID_HANDLE_VALUE);
+    okChildInt("StartupInfoA", "hStdError", (UINT)INVALID_HANDLE_VALUE);
+    okChildInt("TEB", "hStdInput", 0);
+    okChildInt("TEB", "hStdOutput", 0);
+    okChildInt("TEB", "hStdError", 0);
+    release_memory();
+    DeleteFileA(resfile);
+#endif
+}
+
 START_TEST(process)
 {
     HANDLE job;
@@ -2690,6 +2740,7 @@ START_TEST(process)
     test_SystemInfo();
     test_RegistryQuota();
     test_DuplicateHandle();
+    test_StartupNoConsole();
     /* things that can be tested:
      *  lookup:         check the way program to be executed is searched
      *  handles:        check the handle inheritance stuff (+sec options)




More information about the wine-cvs mailing list