From f0a5045254111774130846bd7b56224c06a2b999 Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Sun, 14 Mar 2010 21:53:27 +0100 Subject: [PATCH] ntdll: Improve support for the ProcessDebugPort info class in NtQueryInformationProcess(). --- dlls/ntdll/process.c | 19 +++++++++- dlls/ntdll/tests/info.c | 83 ++++++++++++++++++++++++++++++++++++++++++ include/wine/server_protocol.h | 4 +- server/process.c | 1 + server/protocol.def | 1 + server/request.h | 1 + server/trace.c | 1 + 7 files changed, 107 insertions(+), 3 deletions(-) diff --git a/dlls/ntdll/process.c b/dlls/ntdll/process.c index 9be133910d0..6fdceae498a 100644 --- a/dlls/ntdll/process.c +++ b/dlls/ntdll/process.c @@ -295,7 +295,24 @@ NTSTATUS WINAPI NtQueryInformationProcess( * set it to 0 aka "no debugger" to satisfy copy protections */ len = sizeof(DWORD_PTR); if (ProcessInformationLength == len) - memset(ProcessInformation, 0, ProcessInformationLength); + { + if (!ProcessInformation) + ret = STATUS_ACCESS_VIOLATION; + else if (!ProcessHandle) + ret = STATUS_INVALID_HANDLE; + else + { + SERVER_START_REQ(get_process_info) + { + req->handle = wine_server_obj_handle( ProcessHandle ); + if ((ret = wine_server_call( req )) == STATUS_SUCCESS) + { + *(DWORD_PTR *)ProcessInformation = reply->debugger_present ? ~(DWORD_PTR)0 : 0; + } + } + SERVER_END_REQ; + } + } else ret = STATUS_INFO_LENGTH_MISMATCH; break; diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c index c7d451c70b3..a8e19f929e6 100644 --- a/dlls/ntdll/tests/info.c +++ b/dlls/ntdll/tests/info.c @@ -20,6 +20,7 @@ #include "ntdll_test.h" #include +#include static NTSTATUS (WINAPI * pNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG); static NTSTATUS (WINAPI * pNtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG); @@ -751,6 +752,78 @@ static void test_query_process_times(void) "Inconsistent length %d\n", ReturnLength); } +static void test_query_process_debug_port(int argc, char **argv) +{ + DWORD_PTR debug_port = 0xdeadbeef; + char cmdline[MAX_PATH]; + PROCESS_INFORMATION pi; + STARTUPINFO si = { 0 }; + NTSTATUS status; + BOOL ret; + + sprintf(cmdline, "%s %s %s", argv[0], argv[1], "debuggee"); + + si.cb = sizeof(si); + ret = CreateProcess(NULL, cmdline, NULL, NULL, FALSE, DEBUG_PROCESS, NULL, NULL, &si, &pi); + ok(ret, "CreateProcess failed, last error %#x.\n", GetLastError()); + if (!ret) return; + + status = pNtQueryInformationProcess(NULL, ProcessDebugPort, + NULL, 0, NULL); + ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status); + + status = pNtQueryInformationProcess(NULL, ProcessDebugPort, + NULL, sizeof(debug_port), NULL); + ok(status == STATUS_INVALID_HANDLE || status == STATUS_ACCESS_VIOLATION, + "Expected STATUS_INVALID_HANDLE, got %#x.\n", status); + + status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort, + NULL, sizeof(debug_port), NULL); + ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got %#x.\n", status); + + status = pNtQueryInformationProcess(NULL, ProcessDebugPort, + &debug_port, sizeof(debug_port), NULL); + ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_ACCESS_VIOLATION, got %#x.\n", status); + + status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort, + &debug_port, sizeof(debug_port) - 1, NULL); + ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status); + + status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort, + &debug_port, sizeof(debug_port) + 1, NULL); + ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status); + + status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort, + &debug_port, sizeof(debug_port), NULL); + ok(!status, "NtQueryInformationProcess failed, status %#x.\n", status); + ok(debug_port == 0, "Expected port 0, got %#lx.\n", debug_port); + + status = pNtQueryInformationProcess(pi.hProcess, ProcessDebugPort, + &debug_port, sizeof(debug_port), NULL); + ok(!status, "NtQueryInformationProcess failed, status %#x.\n", status); + ok(debug_port == ~(DWORD_PTR)0, "Expected port %#lx, got %#lx.\n", ~(DWORD_PTR)0, debug_port); + + for (;;) + { + DEBUG_EVENT ev; + + ret = WaitForDebugEvent(&ev, INFINITE); + ok(ret, "WaitForDebugEvent failed, last error %#x.\n", GetLastError()); + if (!ret) break; + + if (ev.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break; + + ret = ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE); + ok(ret, "ContinueDebugEvent failed, last error %#x.\n", GetLastError()); + if (!ret) break; + } + + ret = CloseHandle(pi.hThread); + ok(ret, "CloseHandle failed, last error %#x.\n", GetLastError()); + ret = CloseHandle(pi.hProcess); + ok(ret, "CloseHandle failed, last error %#x.\n", GetLastError()); +} + static void test_query_process_handlecount(void) { NTSTATUS status; @@ -978,9 +1051,15 @@ static void test_affinity(void) START_TEST(info) { + char **argv; + int argc; + if(!InitFunctionPtrs()) return; + argc = winetest_get_mainargs(&argv); + if (argc >= 3) return; /* Child */ + /* NtQuerySystemInformation */ /* 0x0 SystemBasicInformation */ @@ -1049,6 +1128,10 @@ START_TEST(info) trace("Starting test_query_process_times()\n"); test_query_process_times(); + /* 0x7 ProcessDebugPort */ + trace("Starting test_process_debug_port()\n"); + test_query_process_debug_port(argc, argv); + /* 0x14 ProcessHandleCount */ trace("Starting test_query_process_handlecount()\n"); test_query_process_handlecount(); diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 47c032e728e..0c3155ddf9e 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -725,7 +725,7 @@ struct get_process_info_reply int exit_code; int priority; cpu_type_t cpu; - char __pad_60[4]; + int debugger_present; }; @@ -5397,6 +5397,6 @@ union generic_reply struct free_user_handle_reply free_user_handle_reply; }; -#define SERVER_PROTOCOL_VERSION 395 +#define SERVER_PROTOCOL_VERSION 396 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/process.c b/server/process.c index e4dca68cb5b..36e462ab2c0 100644 --- a/server/process.c +++ b/server/process.c @@ -1091,6 +1091,7 @@ DECL_HANDLER(get_process_info) reply->start_time = process->start_time; reply->end_time = process->end_time; reply->cpu = process->cpu; + reply->debugger_present = !!process->debugger; release_object( process ); } } diff --git a/server/protocol.def b/server/protocol.def index 04f6e2ba891..e9c5cba1809 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -692,6 +692,7 @@ typedef union int exit_code; /* process exit code */ int priority; /* priority class */ cpu_type_t cpu; /* CPU that this process is running on */ + int debugger_present; /* process is being debugged */ @END diff --git a/server/request.h b/server/request.h index 41c64091eb8..11382d8f7f0 100644 --- a/server/request.h +++ b/server/request.h @@ -697,6 +697,7 @@ C_ASSERT( FIELD_OFFSET(struct get_process_info_reply, end_time) == 40 ); C_ASSERT( FIELD_OFFSET(struct get_process_info_reply, exit_code) == 48 ); C_ASSERT( FIELD_OFFSET(struct get_process_info_reply, priority) == 52 ); C_ASSERT( FIELD_OFFSET(struct get_process_info_reply, cpu) == 56 ); +C_ASSERT( FIELD_OFFSET(struct get_process_info_reply, debugger_present) == 60 ); C_ASSERT( sizeof(struct get_process_info_reply) == 64 ); C_ASSERT( FIELD_OFFSET(struct set_process_info_request, handle) == 12 ); C_ASSERT( FIELD_OFFSET(struct set_process_info_request, mask) == 16 ); diff --git a/server/trace.c b/server/trace.c index a250a2e866a..4b13ed57a84 100644 --- a/server/trace.c +++ b/server/trace.c @@ -1118,6 +1118,7 @@ static void dump_get_process_info_reply( const struct get_process_info_reply *re fprintf( stderr, ", exit_code=%d", req->exit_code ); fprintf( stderr, ", priority=%d", req->priority ); dump_cpu_type( ", cpu=", &req->cpu ); + fprintf( stderr, ", debugger_present=%d", req->debugger_present ); } static void dump_set_process_info_request( const struct set_process_info_request *req ) -- 2.11.4.GIT