Commit deb273a9 authored by Paul Gofman's avatar Paul Gofman Committed by Alexandre Julliard

ntdll: Implement NtQuerySystemInformation(SystemProcessIdInformation).

parent 60eb5cb5
......@@ -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();
}
......@@ -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;
......
......@@ -526,6 +526,12 @@ typedef struct
typedef struct
{
ULONG ProcessId;
UNICODE_STRING32 ImageName;
} SYSTEM_PROCESS_ID_INFORMATION32;
typedef struct
{
ULONG OwnerPid;
BYTE ObjectType;
BYTE HandleFlags;
......
......@@ -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))
{
......
......@@ -1089,8 +1089,8 @@ struct get_process_image_name_request
{
struct request_header __header;
obj_handle_t handle;
process_id_t pid;
int win32;
char __pad_20[4];
};
struct get_process_image_name_reply
{
......@@ -6522,7 +6522,7 @@ union generic_reply
/* ### protocol_version begin ### */
#define SERVER_PROTOCOL_VERSION 799
#define SERVER_PROTOCOL_VERSION 800
/* ### protocol_version end ### */
......
......@@ -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;
......
......@@ -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)
......
......@@ -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 */
......
......@@ -831,7 +831,8 @@ C_ASSERT( FIELD_OFFSET(struct get_process_debug_info_reply, debug) == 8 );
C_ASSERT( FIELD_OFFSET(struct get_process_debug_info_reply, debug_children) == 12 );
C_ASSERT( sizeof(struct get_process_debug_info_reply) == 16 );
C_ASSERT( FIELD_OFFSET(struct get_process_image_name_request, handle) == 12 );
C_ASSERT( FIELD_OFFSET(struct get_process_image_name_request, win32) == 16 );
C_ASSERT( FIELD_OFFSET(struct get_process_image_name_request, pid) == 16 );
C_ASSERT( FIELD_OFFSET(struct get_process_image_name_request, win32) == 20 );
C_ASSERT( sizeof(struct get_process_image_name_request) == 24 );
C_ASSERT( FIELD_OFFSET(struct get_process_image_name_reply, len) == 8 );
C_ASSERT( sizeof(struct get_process_image_name_reply) == 16 );
......
......@@ -1543,6 +1543,7 @@ static void dump_get_process_debug_info_reply( const struct get_process_debug_in
static void dump_get_process_image_name_request( const struct get_process_image_name_request *req )
{
fprintf( stderr, " handle=%04x", req->handle );
fprintf( stderr, ", pid=%04x", req->pid );
fprintf( stderr, ", win32=%d", req->win32 );
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment