From: Paul Gofman <pgofman(a)codeweavers.com>
---
dlls/ntdll/tests/info.c | 129 +++++++++++++++++++++++++++++++++++++++
dlls/ntdll/unix/system.c | 39 ++++++++++++
dlls/wow64/struct32.h | 6 ++
dlls/wow64/system.c | 18 ++++++
include/winternl.h | 6 ++
server/process.c | 5 +-
server/protocol.def | 1 +
7 files changed, 203 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c
index ce5475df763..88086a83f59 100644
--- a/dlls/ntdll/tests/info.c
+++ b/dlls/ntdll/tests/info.c
@@ -28,6 +28,7 @@
#include "winternl.h"
#include "winnls.h"
#include "ddk/ntddk.h"
+#include "psapi.h"
#include "wine/test.h"
static NTSTATUS (WINAPI * pNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID,
ULONG, PULONG);
@@ -3892,6 +3893,133 @@ static void test_process_token(int argc, char **argv)
CloseHandle( token );
}
+static void test_process_id(void)
+{
+ char image_name_buffer[1024 * sizeof(WCHAR)];
+ UNICODE_STRING *image_name = (UNICODE_STRING *)image_name_buffer;
+ SYSTEM_PROCESS_ID_INFORMATION info;
+ unsigned int i, length;
+ DWORD pids[2048];
+ WCHAR name[2048];
+ NTSTATUS status;
+ HANDLE process;
+ ULONG len;
+ BOOL bret;
+
+ status = NtQueryInformationProcess( GetCurrentProcess(), ProcessImageFileName,
image_name,
+ sizeof(image_name_buffer), NULL );
+ ok( !status, "got %#lx.\n", status );
+ length = image_name->Length;
+ image_name->Buffer[length] = 0;
+
+ len = 0xdeadbeef;
+ status = pNtQuerySystemInformation( SystemProcessIdInformation, NULL, 0, &len );
+ ok( status == STATUS_INFO_LENGTH_MISMATCH || (is_wow64 && status ==
STATUS_ACCESS_VIOLATION), "got %#lx.\n", status );
+ ok( len == sizeof(info) || (is_wow64 && len == 0xdeadbeef), "got
%#lx.\n", len );
+
+ info.ProcessId = 0xdeadbeef;
+ info.ImageName.Length = info.ImageName.MaximumLength = 0;
+ info.ImageName.Buffer = NULL;
+ status = pNtQuerySystemInformation( SystemProcessIdInformation, &info,
sizeof(info), &len );
+ ok( status == STATUS_INVALID_CID, "got %#lx.\n", status );
+ ok( !info.ImageName.Length, "got %#x.\n", info.ImageName.Length );
+ ok( !info.ImageName.MaximumLength, "got %#x.\n",
info.ImageName.MaximumLength );
+
+ info.ProcessId = GetCurrentProcessId();
+ status = pNtQuerySystemInformation( SystemProcessIdInformation, &info,
sizeof(info), &len );
+ ok( status == STATUS_INFO_LENGTH_MISMATCH, "got %#lx.\n", status );
+ ok( len == sizeof(info), "got %#lx.\n", len );
+ ok( !info.ImageName.Length, "got %#x.\n", info.ImageName.Length );
+ ok( info.ImageName.MaximumLength == length + 2 || (is_wow64 &&
!info.ImageName.MaximumLength),
+ "got %#x.\n", info.ImageName.MaximumLength );
+
+ info.ImageName.MaximumLength = sizeof(name);
+ len = 0xdeadbeef;
+ status = pNtQuerySystemInformation( SystemProcessIdInformation, &info,
sizeof(info), &len );
+ ok( status == STATUS_ACCESS_VIOLATION, "got %#lx.\n", status );
+ ok( len == sizeof(info), "got %#lx.\n", len );
+ ok( info.ImageName.Length == length || (is_wow64 && !info.ImageName.Length),
+ "got %u.\n", info.ImageName.Length );
+ ok( info.ImageName.MaximumLength == length + 2 || (is_wow64 &&
!info.ImageName.Length),
+ "got %#x.\n", info.ImageName.MaximumLength );
+
+ info.ProcessId = 0xdeadbeef;
+ info.ImageName.MaximumLength = sizeof(name);
+ info.ImageName.Buffer = name;
+ info.ImageName.Length = 0;
+ status = pNtQuerySystemInformation( SystemProcessIdInformation, &info,
sizeof(info), &len );
+ ok( status == STATUS_INVALID_CID, "got %#lx.\n", status );
+ ok( !info.ImageName.Length, "got %#x.\n", info.ImageName.Length );
+ ok( info.ImageName.MaximumLength == sizeof(name), "got %#x.\n",
info.ImageName.MaximumLength );
+ ok( info.ImageName.Buffer == name, "got %p, %p.\n", info.ImageName.Buffer,
name );
+
+ info.ProcessId = 0;
+ info.ImageName.MaximumLength = sizeof(name);
+ info.ImageName.Buffer = name;
+ info.ImageName.Length = 0;
+ status = pNtQuerySystemInformation( SystemProcessIdInformation, &info,
sizeof(info), &len );
+ ok( status == STATUS_INVALID_CID, "got %#lx.\n", status );
+ ok( !info.ImageName.Length, "got %#x.\n", info.ImageName.Length );
+ ok( info.ImageName.MaximumLength == sizeof(name), "got %#x.\n",
info.ImageName.MaximumLength );
+ ok( info.ImageName.Buffer == name, "got non NULL.\n" );
+
+ info.ProcessId = 0;
+ info.ImageName.MaximumLength = sizeof(name);
+ info.ImageName.Buffer = name;
+ info.ImageName.Length = 4;
+ status = pNtQuerySystemInformation( SystemProcessIdInformation, &info,
sizeof(info), &len );
+ ok( status == STATUS_INVALID_PARAMETER, "got %#lx.\n", status );
+ ok( info.ImageName.Length == 4, "got %#x.\n", info.ImageName.Length );
+ ok( info.ImageName.MaximumLength == sizeof(name), "got %#x.\n",
info.ImageName.MaximumLength );
+ ok( info.ImageName.Buffer == name, "got non NULL.\n" );
+
+ info.ProcessId = GetCurrentProcessId();
+ info.ImageName.MaximumLength = sizeof(name);
+ info.ImageName.Buffer = name;
+ info.ImageName.Length = 4;
+ status = pNtQuerySystemInformation( SystemProcessIdInformation, &info,
sizeof(info), NULL );
+ ok( status == STATUS_INVALID_PARAMETER, "got %#lx.\n", status );
+ ok( info.ImageName.Length == 4, "got %#x.\n", info.ImageName.Length );
+ ok( info.ImageName.MaximumLength == sizeof(name), "got %#x.\n",
info.ImageName.MaximumLength );
+
+ info.ImageName.Length = 0;
+ memset( name, 0xcc, sizeof(name) );
+ status = pNtQuerySystemInformation( SystemProcessIdInformation, &info,
sizeof(info), &len );
+ ok( !status, "got %#lx.\n", status );
+ ok( info.ImageName.Length == length, "got %#x.\n", info.ImageName.Length
);
+ ok( len == sizeof(info), "got %#lx.\n", len );
+ ok( info.ImageName.MaximumLength == info.ImageName.Length + 2, "got
%#x.\n", info.ImageName.MaximumLength );
+ ok( !name[info.ImageName.Length / 2], "got %#x.\n",
name[info.ImageName.Length / 2] );
+
+ ok( info.ImageName.Length == image_name->Length, "got %#x, %#x.\n",
info.ImageName.Length, image_name->Length );
+ ok( !wcscmp( name, image_name->Buffer ), "got %s, %s.\n",
debugstr_w(name), debugstr_w(image_name->Buffer) );
+
+ bret = EnumProcesses( pids, sizeof(pids), &len );
+ ok( bret, "got error %lu.\n", GetLastError() );
+ for (i = 0; i < len / sizeof(*pids); ++i)
+ {
+ process = OpenProcess( PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pids[i] );
+ if (pids[i] && !process && GetLastError() !=
ERROR_ACCESS_DENIED)
+ {
+ /* process is gone already. */
+ continue;
+ }
+ info.ProcessId = pids[i];
+ info.ImageName.Length = 0;
+ info.ImageName.MaximumLength = sizeof(name);
+ info.ImageName.Buffer = name;
+ status = pNtQuerySystemInformation( SystemProcessIdInformation, &info,
sizeof(info), &len );
+ ok( info.ImageName.Buffer == name || (!info.ImageName.MaximumLength &&
!info.ImageName.Length),
+ "got %p, %p, pid %lu, lengh %u / %u.\n", info.ImageName.Buffer,
name, pids[i],
+ info.ImageName.Length, info.ImageName.MaximumLength );
+ if (pids[i])
+ ok( !status, "got %#lx, pid %lu.\n", status, pids[i] );
+ else
+ ok( status == STATUS_INVALID_CID, "got %#lx, pid %lu.\n", status,
pids[i] );
+ if (process) CloseHandle( process );
+ }
+}
+
START_TEST(info)
{
char **argv;
@@ -3970,4 +4098,5 @@ START_TEST(info)
test_process_instrumentation_callback();
test_system_debug_control();
test_process_token(argc, argv);
+ test_process_id();
}
diff --git a/dlls/ntdll/unix/system.c b/dlls/ntdll/unix/system.c
index 15c4a49e611..6e240e38cad 100644
--- a/dlls/ntdll/unix/system.c
+++ b/dlls/ntdll/unix/system.c
@@ -3289,6 +3289,45 @@ NTSTATUS WINAPI NtQuerySystemInformation( SYSTEM_INFORMATION_CLASS
class,
break;
}
+ case SystemProcessIdInformation: /* 88 */
+ {
+ SYSTEM_PROCESS_ID_INFORMATION *id = info;
+ UNICODE_STRING *str = &id->ImageName;
+ ULONG name_len = 0;
+ void *buffer;
+
+ len = sizeof(*id);
+ if (ret_size) *ret_size = len;
+
+ if (len > size) ret = STATUS_INFO_LENGTH_MISMATCH;
+ else if (id->ImageName.Length) ret = STATUS_INVALID_PARAMETER;
+ else if (!id->ProcessId) ret = STATUS_INVALID_CID;
+
+ if (ret) return ret;
+
+ buffer = malloc( str->MaximumLength );
+ SERVER_START_REQ( get_process_image_name )
+ {
+ req->pid = id->ProcessId;
+ wine_server_set_reply( req, buffer, str->MaximumLength );
+ ret = wine_server_call( req );
+ name_len = reply->len;
+ }
+ SERVER_END_REQ;
+
+ if (ret == STATUS_BUFFER_TOO_SMALL) ret = STATUS_INFO_LENGTH_MISMATCH;
+ if (!ret && name_len + sizeof(WCHAR) > str->MaximumLength) ret =
STATUS_INFO_LENGTH_MISMATCH;
+ if (!ret || ret == STATUS_INFO_LENGTH_MISMATCH) str->MaximumLength = name_len
+ sizeof(WCHAR);
+ if (!ret)
+ {
+ str->Length = name_len;
+ memcpy( str->Buffer, buffer, str->Length );
+ str->Buffer[str->Length / sizeof(WCHAR)] = 0;
+ }
+ free( buffer );
+ return ret;
+ }
+
case SystemDynamicTimeZoneInformation: /* 102 */
{
RTL_DYNAMIC_TIME_ZONE_INFORMATION tz;
diff --git a/dlls/wow64/struct32.h b/dlls/wow64/struct32.h
index 9535fba3a84..87e219045f4 100644
--- a/dlls/wow64/struct32.h
+++ b/dlls/wow64/struct32.h
@@ -524,6 +524,12 @@ typedef struct
ULONG Flags;
} SYSTEM_CACHE_INFORMATION32;
+typedef struct
+{
+ ULONG ProcessId;
+ UNICODE_STRING32 ImageName;
+} SYSTEM_PROCESS_ID_INFORMATION32;
+
typedef struct
{
ULONG OwnerPid;
diff --git a/dlls/wow64/system.c b/dlls/wow64/system.c
index b2c8eec8769..6e78c462984 100644
--- a/dlls/wow64/system.c
+++ b/dlls/wow64/system.c
@@ -406,6 +406,24 @@ NTSTATUS WINAPI wow64_NtQuerySystemInformation( UINT *args )
}
return status;
+ case SystemProcessIdInformation: /* SYSTEM_PROCESS_ID_INFORMATION */
+ {
+ SYSTEM_PROCESS_ID_INFORMATION32 *info32 = ptr;
+ SYSTEM_PROCESS_ID_INFORMATION info;
+
+ if (retlen) *retlen = sizeof(*info32);
+ if (len < sizeof(*info32)) return STATUS_INFO_LENGTH_MISMATCH;
+
+ info.ProcessId = info32->ProcessId;
+ unicode_str_32to64( &info.ImageName, &info32->ImageName );
+ if (!(status = NtQuerySystemInformation( class, &info, sizeof(info), NULL
)))
+ {
+ info32->ImageName.MaximumLength = info.ImageName.MaximumLength;
+ info32->ImageName.Length = info.ImageName.Length;
+ }
+ return status;
+ }
+
case SystemHandleInformation: /* SYSTEM_HANDLE_INFORMATION */
if (len >= sizeof(SYSTEM_HANDLE_INFORMATION32))
{
diff --git a/include/winternl.h b/include/winternl.h
index 5b897b0276c..22cdceeaedb 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -3023,6 +3023,12 @@ typedef struct _SYSTEM_FIRMWARE_TABLE_INFORMATION
UCHAR TableBuffer[1];
} SYSTEM_FIRMWARE_TABLE_INFORMATION, *PSYSTEM_FIRMWARE_TABLE_INFORMATION;
+typedef struct _SYSTEM_PROCESS_ID_INFORMATION
+{
+ ULONG_PTR ProcessId;
+ UNICODE_STRING ImageName;
+} SYSTEM_PROCESS_ID_INFORMATION, *PSYSTEM_PROCESS_ID_INFORMATION;
+
typedef struct _TIME_FIELDS
{ CSHORT Year;
CSHORT Month;
diff --git a/server/process.c b/server/process.c
index b7c7df38e44..f6d1641cb94 100644
--- a/server/process.c
+++ b/server/process.c
@@ -1512,7 +1512,10 @@ DECL_HANDLER(get_process_debug_info)
/* fetch the name of the process image */
DECL_HANDLER(get_process_image_name)
{
- struct process *process = get_process_from_handle( req->handle,
PROCESS_QUERY_LIMITED_INFORMATION );
+ struct process *process;
+
+ if (req->pid) process = get_process_from_id( req->pid );
+ else process = get_process_from_handle( req->handle,
PROCESS_QUERY_LIMITED_INFORMATION );
if (!process) return;
if (process->image)
diff --git a/server/protocol.def b/server/protocol.def
index 69b8db3ebef..f6d644d6182 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1034,6 +1034,7 @@ typedef struct
/* Fetch the name of the process image */
@REQ(get_process_image_name)
obj_handle_t handle; /* process handle */
+ process_id_t pid; /* process id */
int win32; /* return a win32 filename? */
@REPLY
data_size_t len; /* len in bytes required to store filename */
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/5494