[1/2] kernel32: Add more process shutdown tests.

Dmitry Timoshkov dmitry at baikal.ru
Thu Apr 18 03:44:16 CDT 2013


---
 dlls/kernel32/tests/loader.c | 134 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 133 insertions(+), 1 deletion(-)

diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c
index 458b836..ca33ef7 100644
--- a/dlls/kernel32/tests/loader.c
+++ b/dlls/kernel32/tests/loader.c
@@ -1042,6 +1042,7 @@ nt4_is_broken:
 #define MAX_COUNT 10
 static HANDLE attached_thread[MAX_COUNT], stop_event, event, mutex, semaphore;
 static DWORD attached_thread_count;
+static LONG noop_thread_started;
 static int test_dll_phase;
 
 static DWORD WINAPI mutex_thread_proc(void *param)
@@ -1082,6 +1083,14 @@ static DWORD WINAPI semaphore_thread_proc(void *param)
     return 196;
 }
 
+static DWORD WINAPI noop_thread_proc(void *param)
+{
+    InterlockedIncrement(&noop_thread_started);
+
+    trace("%04u: noop_thread_proc: exiting\n", GetCurrentThreadId());
+    return 196;
+}
+
 static BOOL WINAPI dll_entry_point(HINSTANCE hinst, DWORD reason, LPVOID param)
 {
     DWORD ret;
@@ -1098,6 +1107,11 @@ static BOOL WINAPI dll_entry_point(HINSTANCE hinst, DWORD reason, LPVOID param)
     case DLL_PROCESS_DETACH:
     {
         DWORD code, expected_code, i;
+        HANDLE handle, process;
+        void *addr;
+        SIZE_T size;
+        LARGE_INTEGER offset;
+        DEBUG_EVENT de;
 
         trace("dll: %p, DLL_PROCESS_DETACH, %p\n", hinst, param);
 
@@ -1160,12 +1174,123 @@ static BOOL WINAPI dll_entry_point(HINSTANCE hinst, DWORD reason, LPVOID param)
             ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %#x\n", ret);
         }
 
+        /* win7 doesn't allow to create a thread during process shutdown,
+         * earlier Windows versions allow it.
+         */
+        noop_thread_started = 0;
+        SetLastError(0xdeadbeef);
+        handle = CreateThread(NULL, 0, noop_thread_proc, NULL, 0, &ret);
+        /* manual call to LdrShutdownProcess doesn't prevent thread creation */
+        if (param && test_dll_phase != 4)
+        {
+todo_wine
+            ok(!handle || broken(handle != 0) /* before win7 */, "CreateThread should fail\n");
+            if (!handle)
+                ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
+            else
+                CloseHandle(handle);
+        }
+        else
+        {
+            ok(handle != 0, "CreateThread error %d\n", GetLastError());
+            ret = WaitForSingleObject(handle, 1000);
+            /* FIXME: remove once Wine is fixed */
+            if (test_dll_phase == 4) todo_wine
+            {
+            ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret);
+            ok(!noop_thread_started || broken(noop_thread_started) /* XP64 */, "thread shouldn't start yet\n");
+            }
+            else
+            {
+            ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret);
+            ok(!noop_thread_started || broken(noop_thread_started) /* XP64 */, "thread shouldn't start yet\n");
+            }
+            CloseHandle(handle);
+        }
+
+        SetLastError(0xdeadbeef);
+        process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
+        ok(process != NULL, "OpenProcess error %d\n", GetLastError());
+
+        noop_thread_started = 0;
+        SetLastError(0xdeadbeef);
+        handle = CreateRemoteThread(process, NULL, 0, noop_thread_proc, NULL, 0, &ret);
+        /* manual call to LdrShutdownProcess doesn't prevent thread creation */
+        if (param && test_dll_phase != 4)
+        {
+todo_wine
+            ok(!handle || broken(handle != 0) /* before win7 */, "CreateRemoteThread should fail\n");
+            if (!handle)
+                ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
+            else
+                CloseHandle(handle);
+        }
+        else
+        {
+            ok(handle != 0, "CreateRemoteThread error %d\n", GetLastError());
+            ret = WaitForSingleObject(handle, 1000);
+            /* FIXME: remove once Wine is fixed */
+            if (test_dll_phase == 4) todo_wine
+            {
+            ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret);
+            ok(!noop_thread_started || broken(noop_thread_started) /* XP64 */, "thread shouldn't start yet\n");
+            }
+            else
+            {
+            ok(ret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %#x\n", ret);
+            ok(!noop_thread_started || broken(noop_thread_started) /* XP64 */, "thread shouldn't start yet\n");
+            }
+        }
+
+        SetLastError(0xdeadbeef);
+        handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, NULL);
+        ok(handle != 0, "CreateFileMapping error %d\n", GetLastError());
+
+        offset.u.LowPart = 0;
+        offset.u.HighPart = 0;
+        addr = NULL;
+        size = 0;
+        ret = pNtMapViewOfSection(handle, process, &addr, 0, 0, &offset,
+                                  &size, 1 /* ViewShare */, 0, PAGE_READONLY);
+        ok(ret == STATUS_SUCCESS, "NtMapViewOfSection error %#x\n", ret);
+        ret = pNtUnmapViewOfSection(process, addr);
+        ok(ret == STATUS_SUCCESS, "NtUnmapViewOfSection error %#x\n", ret);
+
+        CloseHandle(handle);
+        CloseHandle(process);
+
+        SetLastError(0xdeadbeef);
+        handle = GetModuleHandle("winver.exe");
+        ok(!handle, "winver.exe shouldn't be loaded yet\n");
+        handle = LoadLibrary("winver.exe");
+        ok(handle != 0, "LoadLibrary error %d\n", GetLastError());
+        SetLastError(0xdeadbeef);
+        ret = FreeLibrary(handle);
+        ok(ret, "LoadLibrary error %d\n", GetLastError());
+
+        SetLastError(0xdeadbeef);
+        ret = WaitForDebugEvent(&de, 0);
+        ok(!ret, "WaitForDebugEvent should fail\n");
+todo_wine
+        ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
+
+        SetLastError(0xdeadbeef);
+        ret = DebugActiveProcess(GetCurrentProcessId());
+        ok(!ret, "DebugActiveProcess should fail\n");
+        ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
+
+        SetLastError(0xdeadbeef);
+        ret = WaitForDebugEvent(&de, 0);
+        ok(!ret, "WaitForDebugEvent should fail\n");
+        ok(GetLastError() == ERROR_SEM_TIMEOUT, "expected ERROR_SEM_TIMEOUT, got %d\n", GetLastError());
+
         if (test_dll_phase == 2)
         {
             trace("dll: call ExitProcess()\n");
             *child_failures = winetest_get_failures();
             ExitProcess(197);
         }
+        trace("dll: %p, DLL_PROCESS_DETACH, %p => DONE\n", hinst, param);
         break;
     }
     case DLL_THREAD_ATTACH:
@@ -1185,7 +1310,14 @@ static BOOL WINAPI dll_entry_point(HINSTANCE hinst, DWORD reason, LPVOID param)
         trace("dll: %p, DLL_THREAD_DETACH, %p\n", hinst, param);
 
         ret = pRtlDllShutdownInProgress();
-        ok(!ret, "RtlDllShutdownInProgress returned %d\n", ret);
+        /* win7 doesn't allow to create a thread during process shutdown,
+         * earlier Windows versions allow it, and DLL_THREAD_DETACH is
+         * sent on thread exit, but DLL_THREAD_ATTACH is never received.
+         */
+        if (noop_thread_started)
+            ok(ret, "RtlDllShutdownInProgress returned %d\n", ret);
+        else
+            ok(!ret, "RtlDllShutdownInProgress returned %d\n", ret);
 
         break;
     default:
-- 
1.8.2.1




More information about the wine-patches mailing list