static void test_alertable(void) { IO_STATUS_BLOCK iosb; HANDLE hEvent; HANDLE hPipe; NTSTATUS res; HANDLE hThread; DWORD ret; memset(&iosb, 0x55, sizeof(iosb)); hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); ok(hEvent != INVALID_HANDLE_VALUE, "can't create event, GetLastError: %x\n", GetLastError()); res = create_pipe(&hPipe, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_ALERT); ok(!res, "NtCreateNamedPipeFile returned %x\n", res); /* queue an user apc before calling listen */ userapc_called = FALSE; ret = pQueueUserAPC(&userapc, GetCurrentThread(), 0); ok(ret, "can't queue user apc, GetLastError: %x\n", GetLastError()); res = listen_pipe(hPipe, hEvent, &iosb, TRUE); todo_wine ok(res == STATUS_CANCELLED, "NtFsControlFile returned %x\n", res); todo_wine ok(userapc_called, "user apc didn't run\n"); ok(U(iosb).Status == 0x55555555, "iosb.Status got changed to %x\n", U(iosb).Status); todo_wine ok(WaitForSingleObjectEx(hEvent, 0, TRUE) == WAIT_TIMEOUT, "hEvent signaled\n"); ok(!ioapc_called, "IOAPC ran\n"); /* queue an user apc from a different thread */ hThread = CreateThread(NULL, 0, &thread, pOpenThread(MAXIMUM_ALLOWED, FALSE, GetCurrentThreadId()), 0, 0); ok(hThread != INVALID_HANDLE_VALUE, "can't create thread, GetLastError: %x\n", GetLastError()); /* wine_todo: the earlier NtFsControlFile call gets cancelled after the pipe gets set into listen state instead of before, so this NtFsControlFile will fail STATUS_INVALID_HANDLE */ res = listen_pipe(hPipe, hEvent, &iosb, TRUE); todo_wine ok(res == STATUS_CANCELLED, "NtFsControlFile returned %x\n", res); ok(userapc_called, "user apc didn't run\n"); todo_wine ok(U(iosb).Status == 0x55555555, "iosb.Status got changed to %x\n", U(iosb).Status); ok(WaitForSingleObjectEx(hEvent, 0, TRUE) == WAIT_TIMEOUT, "hEvent signaled\n"); ok(!ioapc_called, "IOAPC ran\n"); WaitForSingleObject(hThread, INFINITE); SleepEx(0, TRUE); /* get rid of the userapc, if NtFsControlFile failed */ ok(open_succeeded, "couldn't open client side pipe\n"); CloseHandle(hThread); DisconnectNamedPipe(hPipe); /* finally try without an apc */ hThread = CreateThread(NULL, 0, &thread, 0, 0, 0); ok(hThread != INVALID_HANDLE_VALUE, "can't create thread, GetLastError: %x\n", GetLastError()); res = listen_pipe(hPipe, hEvent, &iosb, TRUE); todo_wine ok(!res, "NtFsControlFile returned %x\n", res); ok(open_succeeded, "couldn't open client side pipe\n"); ok(!U(iosb).Status, "Wrong iostatus %x\n", U(iosb).Status); todo_wine ok(WaitForSingleObject(hEvent, 0) == 0, "hEvent not signaled\n"); WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); CloseHandle(hEvent); CloseHandle(hPipe); }
static void dump_thread(void *arg) { HANDLE dbghelp; BOOL (WINAPI *pSymInitialize)(HANDLE, const char *, BOOL); BOOL (WINAPI *pSymCleanup)(HANDLE); BOOL (WINAPI *pStackWalk64)(DWORD, HANDLE, HANDLE, STACKFRAME64 *, void *, PREAD_PROCESS_MEMORY_ROUTINE64, PFUNCTION_TABLE_ACCESS_ROUTINE64, PGET_MODULE_BASE_ROUTINE64, PTRANSLATE_ADDRESS_ROUTINE64); DWORD64 (WINAPI *pSymGetModuleBase64)(HANDLE, DWORD64); BOOL (WINAPI *pSymFromAddr)(HANDLE, DWORD64, DWORD64 *, SYMBOL_INFO *); BOOL (WINAPI *pSymGetLineFromAddr64)(HANDLE, DWORD64, DWORD *, IMAGEHLP_LINE64 *); HANDLE (WINAPI *pOpenThread)(DWORD, BOOL, DWORD); DWORD tid = *(DWORD *)arg; HANDLE ph; HANDLE th; dbghelp = LoadLibrary("dbghelp.dll"); if (!dbghelp) return; pSymInitialize = (BOOL (WINAPI *)(HANDLE, const char *, BOOL))GetProcAddress(dbghelp, "SymInitialize"); pSymCleanup = (BOOL (WINAPI *)(HANDLE))GetProcAddress(dbghelp, "SymCleanup"); pStackWalk64 = (BOOL (WINAPI *)(DWORD, HANDLE, HANDLE, STACKFRAME64 *, void *, PREAD_PROCESS_MEMORY_ROUTINE64, PFUNCTION_TABLE_ACCESS_ROUTINE64, PGET_MODULE_BASE_ROUTINE64, PTRANSLATE_ADDRESS_ROUTINE64))GetProcAddress(dbghelp, "StackWalk64"); pSymGetModuleBase64 = (DWORD64 (WINAPI *)(HANDLE, DWORD64))GetProcAddress(dbghelp, "SymGetModuleBase64"); pSymFromAddr = (BOOL (WINAPI *)(HANDLE, DWORD64, DWORD64 *, SYMBOL_INFO *))GetProcAddress(dbghelp, "SymFromAddr"); pSymGetLineFromAddr64 = (BOOL (WINAPI *)(HANDLE, DWORD64, DWORD *, IMAGEHLP_LINE64 *))GetProcAddress(dbghelp, "SymGetLineFromAddr64"); pOpenThread = (HANDLE (WINAPI *)(DWORD, BOOL, DWORD))GetProcAddress(GetModuleHandle("kernel32.dll"), "OpenThread"); if (pSymInitialize && pSymCleanup && pStackWalk64 && pSymGetModuleBase64 && pSymFromAddr && pSymGetLineFromAddr64 && pOpenThread) { SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG | SYMOPT_LOAD_LINES); ph = GetCurrentProcess(); pSymInitialize(ph, NULL, TRUE); th = pOpenThread(THREAD_SUSPEND_RESUME|THREAD_GET_CONTEXT, FALSE, tid); if (th) { if (SuspendThread(th) != (DWORD)-1) { CONTEXT context; memset(&context, 0, sizeof(context)); context.ContextFlags = CONTEXT_FULL; if (GetThreadContext(th, &context)) { char libpath[MAX_PATH]; char buf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME]; SYMBOL_INFO *info = (SYMBOL_INFO *)buf; DWORD mac; STACKFRAME64 frame; memset(&frame, 0, sizeof(frame)); #if defined(_M_AMD64) || defined(__x86_64__) mac = IMAGE_FILE_MACHINE_AMD64; frame.AddrPC.Mode = AddrModeFlat; frame.AddrPC.Offset = context.Rip; frame.AddrFrame.Mode = AddrModeFlat; frame.AddrFrame.Offset = context.Rbp; frame.AddrStack.Mode = AddrModeFlat; frame.AddrStack.Offset = context.Rsp; #elif defined(_M_IA64) || defined(__ia64__) mac = IMAGE_FILE_MACHINE_IA64; frame.AddrPC.Mode = AddrModeFlat; frame.AddrPC.Offset = context.StIIP; frame.AddrBStore.Mode = AddrModeFlat; frame.AddrBStore.Offset = context.RsBSP; frame.AddrStack.Mode = AddrModeFlat; frame.AddrStack.Offset = context.IntSp; #else /* i386 */ mac = IMAGE_FILE_MACHINE_I386; frame.AddrPC.Mode = AddrModeFlat; frame.AddrPC.Offset = context.Eip; frame.AddrFrame.Mode = AddrModeFlat; frame.AddrFrame.Offset = context.Ebp; frame.AddrStack.Mode = AddrModeFlat; frame.AddrStack.Offset = context.Esp; #endif while (pStackWalk64(mac, ph, th, &frame, &context, NULL, NULL, NULL, NULL)) { DWORD64 addr = frame.AddrPC.Offset; IMAGEHLP_LINE64 line; DWORD64 displacement; DWORD tmp; if (addr == frame.AddrReturn.Offset || addr == 0 || frame.AddrReturn.Offset == 0) break; memset(buf, 0, sizeof(buf)); info->SizeOfStruct = sizeof(SYMBOL_INFO); info->MaxNameLen = MAX_SYM_NAME; if (pSymFromAddr(ph, addr, &displacement, info)) { if (GetModuleFileName((HANDLE)(uintptr_t)pSymGetModuleBase64(ph, addr), libpath, sizeof(libpath))) fprintf(stderr, "%s", libpath); fprintf(stderr, "(%s+0x%I64x)", info->Name, displacement); } fprintf(stderr, " [0x%p]", (void *)(VALUE)addr); memset(&line, 0, sizeof(line)); line.SizeOfStruct = sizeof(line); if (pSymGetLineFromAddr64(ph, addr, &tmp, &line)) fprintf(stderr, " %s:%lu", line.FileName, line.LineNumber); fprintf(stderr, "\n"); } } ResumeThread(th); } CloseHandle(th); } pSymCleanup(ph); } FreeLibrary(dbghelp); }