diff --git a/dlls/ntdll/process.c b/dlls/ntdll/process.c index b059c94b9c5..b5e6a643887 100644 --- a/dlls/ntdll/process.c +++ b/dlls/ntdll/process.c @@ -137,7 +137,6 @@ NTSTATUS WINAPI NtQueryInformationProcess( UNIMPLEMENTED_INFO_CLASS(ProcessDeviceMap); UNIMPLEMENTED_INFO_CLASS(ProcessSessionInformation); UNIMPLEMENTED_INFO_CLASS(ProcessForegroundInformation); - UNIMPLEMENTED_INFO_CLASS(ProcessImageFileName); UNIMPLEMENTED_INFO_CLASS(ProcessLUIDDeviceMapsEnabled); UNIMPLEMENTED_INFO_CLASS(ProcessBreakOnTermination); UNIMPLEMENTED_INFO_CLASS(ProcessDebugObjectHandle); @@ -309,6 +308,27 @@ NTSTATUS WINAPI NtQueryInformationProcess( } else ret = STATUS_INFO_LENGTH_MISMATCH; break; + case ProcessImageFileName: + SERVER_START_REQ(get_dll_info) + { + UNICODE_STRING *image_file_name_str = ProcessInformation; + + req->handle = ProcessHandle; + req->base_address = NULL; /* main module */ + wine_server_set_reply( req, image_file_name_str ? image_file_name_str + 1 : NULL, + ProcessInformationLength > sizeof(UNICODE_STRING) ? ProcessInformationLength - sizeof(UNICODE_STRING) : 0 ); + ret = wine_server_call( req ); + if (ret == STATUS_BUFFER_TOO_SMALL) ret = STATUS_INFO_LENGTH_MISMATCH; + + len = sizeof(UNICODE_STRING) + reply->filename_len; + if (ret == STATUS_SUCCESS) + { + image_file_name_str->MaximumLength = image_file_name_str->Length = reply->filename_len; + image_file_name_str->Buffer = (PWSTR)(image_file_name_str + 1); + } + } + SERVER_END_REQ; + break; default: FIXME("(%p,info_class=%d,%p,0x%08x,%p) Unknown information class\n", ProcessHandle,ProcessInformationClass, diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c index 526c62e20cc..08ab1928677 100644 --- a/dlls/ntdll/tests/info.c +++ b/dlls/ntdll/tests/info.c @@ -19,6 +19,7 @@ */ #include "ntdll_test.h" +#include static NTSTATUS (WINAPI * pNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG); static NTSTATUS (WINAPI * pNtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG); @@ -754,6 +755,37 @@ static void test_query_process_handlecount(void) } } +static void test_query_process_image_file_name(void) +{ + DWORD status; + ULONG ReturnLength; + UNICODE_STRING image_file_name; + void *buffer; + char *file_nameA; + INT len; + + status = pNtQueryInformationProcess(NULL, ProcessImageFileName, &image_file_name, sizeof(image_file_name), NULL); + ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08x\n", status); + + status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessImageFileName, &image_file_name, 2, &ReturnLength); + ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status); + + status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessImageFileName, &image_file_name, sizeof(image_file_name), &ReturnLength); + ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status); + + buffer = HeapAlloc(GetProcessHeap(), 0, ReturnLength); + status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessImageFileName, buffer, ReturnLength, &ReturnLength); + ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status); + memcpy(&image_file_name, buffer, sizeof(image_file_name)); + len = WideCharToMultiByte(CP_ACP, 0, image_file_name.Buffer, image_file_name.Length/sizeof(WCHAR), NULL, 0, NULL, NULL); + file_nameA = HeapAlloc(GetProcessHeap(), 0, len + 1); + WideCharToMultiByte(CP_ACP, 0, image_file_name.Buffer, image_file_name.Length/sizeof(WCHAR), file_nameA, len, NULL, NULL); + file_nameA[len] = '\0'; + HeapFree(GetProcessHeap(), 0, buffer); + trace("process image file name: %s\n", file_nameA); + HeapFree(GetProcessHeap(), 0, file_nameA); +} + static void test_readvirtualmemory(void) { @@ -886,6 +918,10 @@ START_TEST(info) trace("Starting test_query_process_handlecount()\n"); test_query_process_handlecount(); + /* 27 ProcessImageFileName */ + trace("Starting test_query_process_image_file_name()\n"); + test_query_process_image_file_name(); + /* belongs into it's own file */ trace("Starting test_readvirtualmemory()\n"); test_readvirtualmemory(); diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 9c56089a9ac..5564ae37f80 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -672,6 +672,7 @@ struct get_dll_info_reply struct reply_header __header; size_t size; void* entry_point; + data_size_t filename_len; /* VARARG(filename,unicode_str); */ }; @@ -4905,6 +4906,6 @@ union generic_reply struct add_fd_completion_reply add_fd_completion_reply; }; -#define SERVER_PROTOCOL_VERSION 331 +#define SERVER_PROTOCOL_VERSION 332 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/process.c b/server/process.c index 7031e14413e..e276dc49089 100644 --- a/server/process.c +++ b/server/process.c @@ -1129,16 +1129,25 @@ DECL_HANDLER(get_dll_info) if ((process = get_process_from_handle( req->handle, PROCESS_QUERY_INFORMATION ))) { - struct process_dll *dll = find_process_dll( process, req->base_address ); + struct process_dll *dll; + + if (req->base_address) + dll = find_process_dll( process, req->base_address ); + else /* NULL means main module */ + dll = list_head( &process->dlls ) ? + LIST_ENTRY(list_head( &process->dlls ), struct process_dll, entry) : NULL; if (dll) { reply->size = dll->size; reply->entry_point = NULL; /* FIXME */ + reply->filename_len = dll->namelen; if (dll->filename) { - data_size_t len = min( dll->namelen, get_reply_max_size() ); - set_reply_data( dll->filename, len ); + if (dll->namelen <= get_reply_max_size()) + set_reply_data( dll->filename, dll->namelen ); + else + set_error( STATUS_BUFFER_TOO_SMALL ); } } else diff --git a/server/protocol.def b/server/protocol.def index dfb5d484e0a..ae5f2acf564 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -620,6 +620,7 @@ typedef union @REPLY size_t size; /* module size */ void* entry_point; + data_size_t filename_len; /* buffer len in bytes required to store filename */ VARARG(filename,unicode_str); /* file name of module */ @END diff --git a/server/trace.c b/server/trace.c index c580139a1f8..38a29917e44 100644 --- a/server/trace.c +++ b/server/trace.c @@ -1004,6 +1004,7 @@ static void dump_get_dll_info_reply( const struct get_dll_info_reply *req ) { fprintf( stderr, " size=%lu,", (unsigned long)req->size ); fprintf( stderr, " entry_point=%p,", req->entry_point ); + fprintf( stderr, " filename_len=%u,", req->filename_len ); fprintf( stderr, " filename=" ); dump_varargs_unicode_str( cur_size ); }