Commit 95a91bd8 authored by Zebediah Figura's avatar Zebediah Figura Committed by Alexandre Julliard

ntdll: Implement NtSetInformationProcess(ProcessAccessToken).

parent 3103adb6
......@@ -20,6 +20,7 @@
#include "ntdll_test.h"
#include <winnls.h>
#include <ddk/ntddk.h>
#include <stdio.h>
static NTSTATUS (WINAPI * pNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG);
......@@ -3758,6 +3759,78 @@ static void test_system_debug_control(void)
}
}
static void test_process_token(int argc, char **argv)
{
STARTUPINFOA si = {.cb = sizeof(si)};
PROCESS_ACCESS_TOKEN token_info = {0};
TOKEN_STATISTICS stats1, stats2;
HANDLE token, their_token;
PROCESS_INFORMATION pi;
char cmdline[MAX_PATH];
NTSTATUS status;
DWORD size;
BOOL ret;
token_info.Thread = (HANDLE)0xdeadbeef;
sprintf( cmdline, "%s %s dummy", argv[0], argv[1] );
ret = CreateProcessA( NULL, cmdline, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi );
ok( ret, "got error %lu\n", GetLastError() );
status = pNtSetInformationProcess( pi.hProcess, ProcessAccessToken, &token_info, sizeof(token_info) - 1 );
ok( status == STATUS_INFO_LENGTH_MISMATCH, "got %#lx\n", status );
status = pNtSetInformationProcess( pi.hProcess, ProcessAccessToken, &token_info, sizeof(token_info) );
ok( status == STATUS_INVALID_HANDLE, "got %#lx\n", status );
ret = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY | READ_CONTROL | TOKEN_DUPLICATE
| TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_DEFAULT, &token );
ok( ret, "got error %lu\n", GetLastError() );
token_info.Token = token;
status = pNtSetInformationProcess( pi.hProcess, ProcessAccessToken, &token_info, sizeof(token_info) );
todo_wine ok( status == STATUS_TOKEN_ALREADY_IN_USE, "got %#lx\n", status );
ret = DuplicateTokenEx( token, TOKEN_ALL_ACCESS, NULL, SecurityAnonymous, TokenImpersonation, &token_info.Token );
ok( ret, "got error %lu\n", GetLastError() );
status = pNtSetInformationProcess( pi.hProcess, ProcessAccessToken, &token_info, sizeof(token_info) );
todo_wine ok( status == STATUS_BAD_IMPERSONATION_LEVEL, "got %#lx\n", status );
CloseHandle( token_info.Token );
ret = DuplicateTokenEx( token, TOKEN_QUERY, NULL, SecurityAnonymous, TokenPrimary, &token_info.Token );
ok( ret, "got error %lu\n", GetLastError() );
status = pNtSetInformationProcess( pi.hProcess, ProcessAccessToken, &token_info, sizeof(token_info) );
ok( status == STATUS_ACCESS_DENIED, "got %#lx\n", status );
CloseHandle( token_info.Token );
ret = DuplicateTokenEx( token, TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY, NULL, SecurityAnonymous, TokenPrimary, &token_info.Token );
ok(ret, "got error %lu\n", GetLastError());
status = pNtSetInformationProcess( pi.hProcess, ProcessAccessToken, &token_info, sizeof(token_info) );
ok( status == STATUS_SUCCESS, "got %#lx\n", status );
ret = OpenProcessToken( pi.hProcess, TOKEN_QUERY, &their_token );
ok( ret, "got error %lu\n", GetLastError() );
/* The tokens should be the same. */
ret = GetTokenInformation( token_info.Token, TokenStatistics, &stats1, sizeof(stats1), &size );
ok( ret, "got error %lu\n", GetLastError() );
ret = GetTokenInformation( their_token, TokenStatistics, &stats2, sizeof(stats2), &size );
ok( ret, "got error %lu\n", GetLastError() );
ok( !memcmp( &stats1.TokenId, &stats2.TokenId, sizeof(LUID) ), "expected same IDs\n" );
CloseHandle( token_info.Token );
CloseHandle( their_token );
ResumeThread( pi.hThread );
ret = WaitForSingleObject( pi.hProcess, 1000 );
ok( !ret, "got %d\n", ret );
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
CloseHandle( token );
}
START_TEST(info)
{
char **argv;
......@@ -3834,4 +3907,5 @@ START_TEST(info)
test_ThreadEnableAlignmentFaultFixup();
test_process_instrumentation_callback();
test_system_debug_control();
test_process_token(argc, argv);
}
......@@ -65,6 +65,7 @@
#include "windef.h"
#include "winternl.h"
#include "winioctl.h"
#include "ddk/ntddk.h"
#include "unix_private.h"
#include "wine/condrv.h"
#include "wine/server.h"
......@@ -1600,6 +1601,23 @@ NTSTATUS WINAPI NtSetInformationProcess( HANDLE handle, PROCESSINFOCLASS class,
switch (class)
{
case ProcessAccessToken:
{
const PROCESS_ACCESS_TOKEN *token = info;
if (size != sizeof(PROCESS_ACCESS_TOKEN)) return STATUS_INFO_LENGTH_MISMATCH;
SERVER_START_REQ( set_process_info )
{
req->handle = wine_server_obj_handle( handle );
req->token = wine_server_obj_handle( token->Token );
req->mask = SET_PROCESS_INFO_TOKEN;
ret = wine_server_call( req );
}
SERVER_END_REQ;
break;
}
case ProcessDefaultHardErrorMode:
if (size != sizeof(UINT)) return STATUS_INVALID_PARAMETER;
process_error_mode = *(UINT *)info;
......
......@@ -26,6 +26,7 @@
#include "winbase.h"
#include "winnt.h"
#include "winternl.h"
#include "ddk/ntddk.h"
#include "wow64_private.h"
#include "wine/asm.h"
#include "wine/exception.h"
......@@ -835,6 +836,18 @@ NTSTATUS WINAPI wow64_NtSetInformationProcess( UINT *args )
case ProcessLeapSecondInformation: /* PROCESS_LEAP_SECOND_INFO */
return NtSetInformationProcess( handle, class, ptr, len );
case ProcessAccessToken: /* PROCESS_ACCESS_TOKEN */
if (len == sizeof(PROCESS_ACCESS_TOKEN32))
{
PROCESS_ACCESS_TOKEN32 *stack = ptr;
PROCESS_ACCESS_TOKEN info;
info.Thread = ULongToHandle( stack->Thread );
info.Token = ULongToHandle( stack->Token );
return NtSetInformationProcess( handle, class, &info, sizeof(info) );
}
else return STATUS_INFO_LENGTH_MISMATCH;
case ProcessAffinityMask: /* ULONG_PTR */
if (len == sizeof(ULONG))
{
......
......@@ -722,4 +722,10 @@ typedef struct DECLSPEC_ALIGN(8)
};
} MEM_EXTENDED_PARAMETER32;
typedef struct
{
ULONG Token;
ULONG Thread;
} PROCESS_ACCESS_TOKEN32;
#endif /* __WOW64_STRUCT32_H */
......@@ -146,6 +146,12 @@ typedef struct _FILE_VALID_DATA_LENGTH_INFORMATION
LARGE_INTEGER ValidDataLength;
} FILE_VALID_DATA_LENGTH_INFORMATION, *PFILE_VALID_DATA_LENGTH_INFORMATION;
typedef struct _PROCESS_ACCESS_TOKEN
{
HANDLE Token;
HANDLE Thread;
} PROCESS_ACCESS_TOKEN, *PPROCESS_ACCESS_TOKEN;
typedef enum _RTL_GENERIC_COMPARE_RESULTS
{
GenericLessThan,
......
......@@ -1114,6 +1114,8 @@ struct set_process_info_request
int mask;
int priority;
affinity_t affinity;
obj_handle_t token;
char __pad_36[4];
};
struct set_process_info_reply
{
......@@ -1121,6 +1123,7 @@ struct set_process_info_reply
};
#define SET_PROCESS_INFO_PRIORITY 0x01
#define SET_PROCESS_INFO_AFFINITY 0x02
#define SET_PROCESS_INFO_TOKEN 0x04
......@@ -6502,7 +6505,7 @@ union generic_reply
/* ### protocol_version begin ### */
#define SERVER_PROTOCOL_VERSION 795
#define SERVER_PROTOCOL_VERSION 796
/* ### protocol_version end ### */
......
......@@ -1626,6 +1626,16 @@ DECL_HANDLER(set_process_info)
{
if (req->mask & SET_PROCESS_INFO_PRIORITY) process->priority = req->priority;
if (req->mask & SET_PROCESS_INFO_AFFINITY) set_process_affinity( process, req->affinity );
if (req->mask & SET_PROCESS_INFO_TOKEN)
{
struct token *token;
if ((token = get_token_obj( current->process, req->token, TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY )))
{
release_object( process->token );
process->token = token;
}
}
release_object( process );
}
}
......
......@@ -1047,9 +1047,11 @@ typedef struct
int mask; /* setting mask (see below) */
int priority; /* priority class */
affinity_t affinity; /* affinity mask */
obj_handle_t token; /* primary token */
@END
#define SET_PROCESS_INFO_PRIORITY 0x01
#define SET_PROCESS_INFO_AFFINITY 0x02
#define SET_PROCESS_INFO_TOKEN 0x04
/* Retrieve information about a thread */
......
......@@ -848,7 +848,8 @@ C_ASSERT( FIELD_OFFSET(struct set_process_info_request, handle) == 12 );
C_ASSERT( FIELD_OFFSET(struct set_process_info_request, mask) == 16 );
C_ASSERT( FIELD_OFFSET(struct set_process_info_request, priority) == 20 );
C_ASSERT( FIELD_OFFSET(struct set_process_info_request, affinity) == 24 );
C_ASSERT( sizeof(struct set_process_info_request) == 32 );
C_ASSERT( FIELD_OFFSET(struct set_process_info_request, token) == 32 );
C_ASSERT( sizeof(struct set_process_info_request) == 40 );
C_ASSERT( FIELD_OFFSET(struct get_thread_info_request, handle) == 12 );
C_ASSERT( FIELD_OFFSET(struct get_thread_info_request, access) == 16 );
C_ASSERT( sizeof(struct get_thread_info_request) == 24 );
......
......@@ -1568,6 +1568,7 @@ static void dump_set_process_info_request( const struct set_process_info_request
fprintf( stderr, ", mask=%d", req->mask );
fprintf( stderr, ", priority=%d", req->priority );
dump_uint64( ", affinity=", &req->affinity );
fprintf( stderr, ", token=%04x", req->token );
}
static void dump_get_thread_info_request( const struct get_thread_info_request *req )
......
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