diff --git a/README.md b/README.md index 4c860890..4919f54c 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Wine. All those differences are also documented on the Included bug fixes and improvements =================================== -**Bugfixes and features included in the next upcoming release [21]:** +**Bugfixes and features included in the next upcoming release [22]:** * Add stub for D3DXComputeNormalMap * Add stub for D3DXComputeTangentFrameEx ([Wine Bug #31984](https://bugs.winehq.org/show_bug.cgi?id=31984)) @@ -50,6 +50,7 @@ Included bug fixes and improvements * Fix handling of subdirectory in FtpFindFirstFile ([Wine Bug #16526](https://bugs.winehq.org/show_bug.cgi?id=16526)) * Fix parameters for ConvertToIndexedBlendedMesh stub ([Wine Bug #36449](https://bugs.winehq.org/show_bug.cgi?id=36449)) * GetMonitorInfo returns the same name for all monitors ([Wine Bug #37709](https://bugs.winehq.org/show_bug.cgi?id=37709)) +* Hearthstone fails to start ([Wine Bug #36216](https://bugs.winehq.org/show_bug.cgi?id=36216)) * IOCTL_DVD_READ_STRUCTURE expects the wrong size of output buffer for some requests ([Wine Bug #37767](https://bugs.winehq.org/show_bug.cgi?id=37767)) * Implement ID3DXEffect::FindNextValidTechnique ([Wine Bug #34101](https://bugs.winehq.org/show_bug.cgi?id=34101)) * Implement IDXGIOutput::GetDesc diff --git a/debian/changelog b/debian/changelog index efe5ab74..3ff64032 100644 --- a/debian/changelog +++ b/debian/changelog @@ -5,6 +5,7 @@ wine-staging (1.7.34) UNRELEASED; urgency=low * Fix issue in DOS Attributes patch which broke ./configure on systems with alternative shells. * Fix issue in user32-WndProc patch which caused crashes for some 16-bit apps. * Fix issue in ws2_32-WriteWatches patch which can cause exceptions on the signal stack. + * Fix issue with invalid handles being incorrect when a new process is created. * Added patch for CreateProcess to prioritize the working directory over the system search path. * Added patch with stubs for WinSqm[Start|End]Session. * Added patch to fix handling of subdirectory in FtpFindFirstFile. diff --git a/patches/Makefile b/patches/Makefile index 5915477c..1d932921 100644 --- a/patches/Makefile +++ b/patches/Makefile @@ -51,6 +51,7 @@ PATCHLIST := \ imm32-Cross_Thread_Access.ok \ include-Winetest.ok \ iphlpapi-TCP_Table.ok \ + kernel32-Console_Handles.ok \ kernel32-GetFinalPathNameByHandle.ok \ kernel32-GetNumaProcessorNode.ok \ kernel32-GetStringTypeW.ok \ @@ -717,6 +718,21 @@ iphlpapi-TCP_Table.ok: echo '+ { "Erich E. Hoover", "iphlpapi: Implement AllocateAndGetTcpExTableFromStack.", 1 },'; \ ) > iphlpapi-TCP_Table.ok +# Patchset kernel32-Console_Handles +# | +# | This patchset fixes the following Wine bugs: +# | * [#36216] Hearthstone fails to start +# | +# | Modified files: +# | * dlls/kernel32/console.c, dlls/kernel32/environ.c, dlls/kernel32/tests/process.c +# | +.INTERMEDIATE: kernel32-Console_Handles.ok +kernel32-Console_Handles.ok: + $(call APPLY_FILE,kernel32-Console_Handles/0001-kernel32-Invalid-console-handles-for-new-processes-a.patch) + @( \ + echo '+ { "Erich E. Hoover", "kernel32: Invalid console handles for new processes are 0, not INVALID_HANDLE_VALUE.", 1 },'; \ + ) > kernel32-Console_Handles.ok + # Patchset kernel32-GetFinalPathNameByHandle # | # | This patchset fixes the following Wine bugs: diff --git a/patches/kernel32-Console_Handles/0001-kernel32-Invalid-console-handles-for-new-processes-a.patch b/patches/kernel32-Console_Handles/0001-kernel32-Invalid-console-handles-for-new-processes-a.patch new file mode 100644 index 00000000..a6b512b2 --- /dev/null +++ b/patches/kernel32-Console_Handles/0001-kernel32-Invalid-console-handles-for-new-processes-a.patch @@ -0,0 +1,187 @@ +From 6dbc9cf8b80fa44d77b1017b6932251d6ff12fe7 Mon Sep 17 00:00:00 2001 +From: "Erich E. Hoover" +Date: Sat, 3 Jan 2015 23:37:42 -0700 +Subject: 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 | 52 ++++++++++++++++++++++++++++++++++++++++++- + 3 files changed, 65 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 218a0d3..e621689 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 char base[MAX_PATH]; +@@ -201,6 +202,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"); +@@ -209,6 +212,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" ); + return TRUE; + } + +@@ -277,6 +281,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 + */ +@@ -2063,6 +2077,41 @@ static void test_DuplicateHandle(void) + CloseHandle(out); + } + ++void test_StartupNoConsole(void) ++{ ++ char buffer[MAX_PATH]; ++ PROCESS_INFORMATION info; ++ STARTUPINFOA startup; ++ 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 \"%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", (DWORD_PTR)INVALID_HANDLE_VALUE); ++ okChildInt("StartupInfoA", "hStdOutput", (DWORD_PTR)INVALID_HANDLE_VALUE); ++ okChildInt("StartupInfoA", "hStdError", (DWORD_PTR)INVALID_HANDLE_VALUE); ++ okChildInt("TEB", "hStdInput", (DWORD_PTR)0); ++ okChildInt("TEB", "hStdOutput", (DWORD_PTR)0); ++ okChildInt("TEB", "hStdError", (DWORD_PTR)0); ++ release_memory(); ++ assert(DeleteFileA(resfile) != 0); ++ ++} ++ + START_TEST(process) + { + BOOL b = init(); +@@ -2092,6 +2141,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) +-- +1.9.1 + diff --git a/patches/kernel32-Console_Handles/definition b/patches/kernel32-Console_Handles/definition new file mode 100644 index 00000000..25651521 --- /dev/null +++ b/patches/kernel32-Console_Handles/definition @@ -0,0 +1 @@ +Fixes: [36216] Hearthstone fails to start