kernel32: Add a test for threads state when a process is being terminated.
Dmitry Timoshkov
dmitry at baikal.ru
Tue Apr 9 04:06:46 CDT 2013
This test demonstrates the problem reported in the bug 33331.
---
dlls/kernel32/tests/loader.c | 177 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 177 insertions(+)
diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c
index 92a2e0b..a992d3a 100644
--- a/dlls/kernel32/tests/loader.c
+++ b/dlls/kernel32/tests/loader.c
@@ -1037,6 +1037,180 @@ nt4_is_broken:
}
}
+#define MAX_COUNT 10
+static HANDLE hthread[MAX_COUNT];
+static DWORD count;
+
+static DWORD WINAPI thread_proc(void *param)
+{
+ SetEvent(param);
+
+ while (1)
+ {
+ trace("%04u: thread_proc: still alive\n", GetCurrentThreadId());
+ Sleep(50);
+ }
+
+ return 0;
+}
+
+static BOOL WINAPI dll_entry_point(HINSTANCE hinst, DWORD reason, LPVOID param)
+{
+ switch (reason)
+ {
+ case DLL_PROCESS_ATTACH:
+ trace("dll: %p, DLL_PROCESS_ATTACH, %p\n", hinst, param);
+ break;
+ case DLL_PROCESS_DETACH:
+ {
+ BOOL ret;
+ DWORD code, i;
+ trace("dll: %p, DLL_PROCESS_DETACH, %p\n", hinst, param);
+
+ ok(count != 0, "attached thread count should not be 0\n");
+
+ for (i = 0; i < count; i++)
+ {
+ ret = GetExitCodeThread(hthread[i], &code);
+ trace("dll: GetExitCodeThread(%u) => %d,%u\n", i, ret, code);
+ ok(ret == 1, "GetExitCodeThread returned %d, expected 1\n", ret);
+ todo_wine
+ ok(code == 0, "expected thread exit code 0, got %u\n", code);
+ }
+ break;
+ }
+ case DLL_THREAD_ATTACH:
+ trace("dll: %p, DLL_THREAD_ATTACH, %p\n", hinst, param);
+ if (count < MAX_COUNT)
+ {
+ DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &hthread[count],
+ 0, TRUE, DUPLICATE_SAME_ACCESS);
+ count++;
+ }
+ break;
+ case DLL_THREAD_DETACH:
+ trace("dll: %p, DLL_THREAD_DETACH, %p\n", hinst, param);
+ break;
+ default:
+ trace("dll: %p, %d, %p\n", hinst, reason, param);
+ break;
+ }
+
+ return TRUE;
+}
+
+static void test_ExitProcess(void)
+{
+#include "pshpack1.h"
+ static struct
+ {
+ BYTE mov_eax;
+ void *target;
+ BYTE jmp_eax[2];
+ } section_data = { 0xb8, 0, { 0xff,0xe0 } };
+#include "poppack.h"
+ static const char filler[0x1000];
+ DWORD dummy, file_align;
+ HANDLE file, thread, event;
+ HMODULE hmod;
+ SYSTEM_INFO si;
+ char dll_name[MAX_PATH];
+ DWORD ret;
+
+#ifndef __i386__
+ skip("x86 specific ExitProcess test\n");
+ return;
+#endif
+
+ GetSystemInfo(&si);
+ trace("system page size %#x\n", si.dwPageSize);
+
+ /* prevent displaying of the "Unable to load this DLL" message box */
+ SetErrorMode(SEM_FAILCRITICALERRORS);
+
+ GetTempPath(MAX_PATH, dll_name);
+ lstrcat(dll_name, "ldr_thrd.tst");
+
+ trace("creating %s\n", dll_name);
+ file = CreateFile(dll_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
+ if (file == INVALID_HANDLE_VALUE)
+ {
+ ok(0, "could not create %s\n", dll_name);
+ return;
+ }
+
+ SetLastError(0xdeadbeef);
+ ret = WriteFile(file, &dos_header, sizeof(dos_header), &dummy, NULL);
+ ok(ret, "WriteFile error %d\n", GetLastError());
+
+ nt_header.FileHeader.NumberOfSections = 1;
+ nt_header.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER);
+ nt_header.FileHeader.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL | IMAGE_FILE_RELOCS_STRIPPED;
+
+ nt_header.OptionalHeader.AddressOfEntryPoint = si.dwPageSize;
+ nt_header.OptionalHeader.SectionAlignment = si.dwPageSize;
+ nt_header.OptionalHeader.FileAlignment = 0x200;
+ nt_header.OptionalHeader.SizeOfImage = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + si.dwPageSize;
+ nt_header.OptionalHeader.SizeOfHeaders = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER);
+ SetLastError(0xdeadbeef);
+ ret = WriteFile(file, &nt_header, sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER), &dummy, NULL);
+ ok(ret, "WriteFile error %d\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ret = WriteFile(file, &nt_header.OptionalHeader, sizeof(IMAGE_OPTIONAL_HEADER), &dummy, NULL);
+ ok(ret, "WriteFile error %d\n", GetLastError());
+
+ section_data.target = dll_entry_point;
+ section.SizeOfRawData = sizeof(section_data);
+ section.PointerToRawData = nt_header.OptionalHeader.FileAlignment;
+ section.VirtualAddress = nt_header.OptionalHeader.SectionAlignment;
+ section.Misc.VirtualSize = nt_header.OptionalHeader.SectionAlignment;
+ section.Characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE;
+ SetLastError(0xdeadbeef);
+ ret = WriteFile(file, §ion, sizeof(section), &dummy, NULL);
+ ok(ret, "WriteFile error %d\n", GetLastError());
+
+ file_align = nt_header.OptionalHeader.FileAlignment - nt_header.OptionalHeader.SizeOfHeaders;
+ assert(file_align < sizeof(filler));
+ SetLastError(0xdeadbeef);
+ ret = WriteFile(file, filler, file_align, &dummy, NULL);
+ ok(ret, "WriteFile error %d\n", GetLastError());
+
+ /* section data */
+ SetLastError(0xdeadbeef);
+ ret = WriteFile(file, §ion_data, sizeof(section_data), &dummy, NULL);
+ ok(ret, "WriteFile error %d\n", GetLastError());
+
+ CloseHandle(file);
+
+ SetLastError(0xdeadbeef);
+ hmod = LoadLibrary(dll_name);
+ ok(hmod != 0, "LoadLibrary error %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ event = CreateEvent(NULL, 0, 0, NULL);
+ ok(event != 0, "CreateEvent error %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ thread = CreateThread(NULL, 0, thread_proc, event, 0, &dummy);
+ ok(thread != 0, "CreateThread error %d\n", GetLastError());
+ WaitForSingleObject(event, INFINITE);
+ CloseHandle(thread);
+
+ ResetEvent(event);
+
+ SetLastError(0xdeadbeef);
+ thread = CreateThread(NULL, 0, thread_proc, event, 0, &dummy);
+ ok(thread != 0, "CreateThread error %d\n", GetLastError());
+ WaitForSingleObject(event, INFINITE);
+ CloseHandle(thread);
+
+ CloseHandle(event);
+
+ Sleep(100);
+ trace("call ExitProcess()\n");
+ ExitProcess(0);
+}
+
START_TEST(loader)
{
pNtMapViewOfSection = (void *)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtMapViewOfSection");
@@ -1045,4 +1219,7 @@ START_TEST(loader)
test_Loader();
test_ImportDescriptors();
test_section_access();
+
+ /* ExitProcess test must be the last one */
+ test_ExitProcess();
}
--
1.8.2
More information about the wine-patches
mailing list