mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-30 04:48:36 +00:00
ntdll: Implement NtQuerySystemInformation(SystemProcessIdInformation).
This commit is contained in:
parent
60eb5cb5d2
commit
deb273a926
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue