mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 00:45:24 +00:00
[NTDLL_APITEST] Write tests for NtQueryInformationToken and NtSetInformationToken
This commit is contained in:
parent
81e0f74a7a
commit
bac1bce605
4 changed files with 952 additions and 0 deletions
|
@ -35,6 +35,7 @@ list(APPEND SOURCE
|
||||||
NtQueryInformationFile.c
|
NtQueryInformationFile.c
|
||||||
NtQueryInformationProcess.c
|
NtQueryInformationProcess.c
|
||||||
NtQueryInformationThread.c
|
NtQueryInformationThread.c
|
||||||
|
NtQueryInformationToken.c
|
||||||
NtQueryKey.c
|
NtQueryKey.c
|
||||||
NtQuerySystemEnvironmentValue.c
|
NtQuerySystemEnvironmentValue.c
|
||||||
NtQuerySystemInformation.c
|
NtQuerySystemInformation.c
|
||||||
|
@ -45,6 +46,7 @@ list(APPEND SOURCE
|
||||||
NtSetInformationFile.c
|
NtSetInformationFile.c
|
||||||
NtSetInformationProcess.c
|
NtSetInformationProcess.c
|
||||||
NtSetInformationThread.c
|
NtSetInformationThread.c
|
||||||
|
NtSetInformationToken.c
|
||||||
NtSetValueKey.c
|
NtSetValueKey.c
|
||||||
NtSetVolumeInformationFile.c
|
NtSetVolumeInformationFile.c
|
||||||
NtUnloadDriver.c
|
NtUnloadDriver.c
|
||||||
|
|
699
modules/rostests/apitests/ntdll/NtQueryInformationToken.c
Normal file
699
modules/rostests/apitests/ntdll/NtQueryInformationToken.c
Normal file
|
@ -0,0 +1,699 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS API tests
|
||||||
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||||
|
* PURPOSE: Tests for the NtQueryInformationToken API
|
||||||
|
* COPYRIGHT: Copyright 2022 George Bișoc <george.bisoc@reactos.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "precomp.h"
|
||||||
|
|
||||||
|
static
|
||||||
|
HANDLE
|
||||||
|
OpenCurrentToken(VOID)
|
||||||
|
{
|
||||||
|
BOOL Success;
|
||||||
|
HANDLE Token;
|
||||||
|
|
||||||
|
Success = OpenProcessToken(GetCurrentProcess(),
|
||||||
|
TOKEN_READ | TOKEN_QUERY_SOURCE | TOKEN_DUPLICATE,
|
||||||
|
&Token);
|
||||||
|
if (!Success)
|
||||||
|
{
|
||||||
|
ok(0, "OpenProcessToken() has failed to get the process' token (error code: %lu)!\n", GetLastError());
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Token;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
QueryTokenUserTests(
|
||||||
|
_In_ HANDLE Token)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PTOKEN_USER UserToken;
|
||||||
|
ULONG BufferLength;
|
||||||
|
UNICODE_STRING SidString;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Query the exact buffer length to hold
|
||||||
|
* our stuff, STATUS_BUFFER_TOO_SMALL must
|
||||||
|
* be expected here.
|
||||||
|
*/
|
||||||
|
Status = NtQueryInformationToken(Token,
|
||||||
|
TokenUser,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&BufferLength);
|
||||||
|
ok_ntstatus(Status, STATUS_BUFFER_TOO_SMALL);
|
||||||
|
|
||||||
|
/* Allocate the buffer based on the size we got */
|
||||||
|
UserToken = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
|
||||||
|
if (!UserToken)
|
||||||
|
{
|
||||||
|
ok(0, "Failed to allocate from heap for token user (required buffer length %lu)!\n", BufferLength);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now do the actual query */
|
||||||
|
Status = NtQueryInformationToken(Token,
|
||||||
|
TokenUser,
|
||||||
|
UserToken,
|
||||||
|
BufferLength,
|
||||||
|
&BufferLength);
|
||||||
|
ok_ntstatus(Status, STATUS_SUCCESS);
|
||||||
|
|
||||||
|
RtlConvertSidToUnicodeString(&SidString, UserToken->User.Sid, TRUE);
|
||||||
|
trace("=============== TokenUser ===============\n");
|
||||||
|
trace("The SID of current token user is: %s\n", wine_dbgstr_w(SidString.Buffer));
|
||||||
|
trace("=========================================\n\n");
|
||||||
|
RtlFreeUnicodeString(&SidString);
|
||||||
|
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, UserToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
QueryTokenGroupsTests(
|
||||||
|
_In_ HANDLE Token)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PTOKEN_GROUPS Groups;
|
||||||
|
ULONG BufferLength;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Query the exact buffer length to hold
|
||||||
|
* our stuff, STATUS_BUFFER_TOO_SMALL must
|
||||||
|
* be expected here.
|
||||||
|
*/
|
||||||
|
Status = NtQueryInformationToken(Token,
|
||||||
|
TokenGroups,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&BufferLength);
|
||||||
|
ok_ntstatus(Status, STATUS_BUFFER_TOO_SMALL);
|
||||||
|
|
||||||
|
/* Allocate the buffer based on the size we got */
|
||||||
|
Groups = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
|
||||||
|
if (!Groups)
|
||||||
|
{
|
||||||
|
ok(0, "Failed to allocate from heap for token groups (required buffer length %lu)!\n", BufferLength);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now do the actual query and validate the
|
||||||
|
* number of groups.
|
||||||
|
*/
|
||||||
|
Status = NtQueryInformationToken(Token,
|
||||||
|
TokenGroups,
|
||||||
|
Groups,
|
||||||
|
BufferLength,
|
||||||
|
&BufferLength);
|
||||||
|
ok_ntstatus(Status, STATUS_SUCCESS);
|
||||||
|
ok(Groups->GroupCount == 10, "The number of groups must be 10 (current number %lu)!\n", Groups->GroupCount);
|
||||||
|
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, Groups);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
QueryTokenPrivilegesTests(
|
||||||
|
_In_ HANDLE Token)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PTOKEN_PRIVILEGES Privileges;
|
||||||
|
ULONG BufferLength;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Query the exact buffer length to hold
|
||||||
|
* our stuff, STATUS_BUFFER_TOO_SMALL must
|
||||||
|
* be expected here.
|
||||||
|
*/
|
||||||
|
Status = NtQueryInformationToken(Token,
|
||||||
|
TokenPrivileges,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&BufferLength);
|
||||||
|
ok_ntstatus(Status, STATUS_BUFFER_TOO_SMALL);
|
||||||
|
|
||||||
|
/* Allocate the buffer based on the size we got */
|
||||||
|
Privileges = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
|
||||||
|
if (!Privileges)
|
||||||
|
{
|
||||||
|
ok(0, "Failed to allocate from heap for token privileges (required buffer length %lu)!\n", BufferLength);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now do the actual query and validate the
|
||||||
|
* number of privileges.
|
||||||
|
*/
|
||||||
|
Status = NtQueryInformationToken(Token,
|
||||||
|
TokenPrivileges,
|
||||||
|
Privileges,
|
||||||
|
BufferLength,
|
||||||
|
&BufferLength);
|
||||||
|
ok_ntstatus(Status, STATUS_SUCCESS);
|
||||||
|
ok(Privileges->PrivilegeCount == 20, "The number of privileges must be 20 (current number %lu)!\n", Privileges->PrivilegeCount);
|
||||||
|
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, Privileges);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
QueryTokenOwnerTests(
|
||||||
|
_In_ HANDLE Token)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PTOKEN_OWNER Owner;
|
||||||
|
ULONG BufferLength;
|
||||||
|
UNICODE_STRING SidString;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Query the exact buffer length to hold
|
||||||
|
* our stuff, STATUS_BUFFER_TOO_SMALL must
|
||||||
|
* be expected here.
|
||||||
|
*/
|
||||||
|
Status = NtQueryInformationToken(Token,
|
||||||
|
TokenOwner,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&BufferLength);
|
||||||
|
ok_ntstatus(Status, STATUS_BUFFER_TOO_SMALL);
|
||||||
|
|
||||||
|
/* Allocate the buffer based on the size we got */
|
||||||
|
Owner = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
|
||||||
|
if (!Owner)
|
||||||
|
{
|
||||||
|
ok(0, "Failed to allocate from heap for token owner (required buffer length %lu)!\n", BufferLength);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now do the actual query and validate the
|
||||||
|
* token owner (must be the local admin).
|
||||||
|
*/
|
||||||
|
Status = NtQueryInformationToken(Token,
|
||||||
|
TokenOwner,
|
||||||
|
Owner,
|
||||||
|
BufferLength,
|
||||||
|
&BufferLength);
|
||||||
|
ok_ntstatus(Status, STATUS_SUCCESS);
|
||||||
|
|
||||||
|
RtlConvertSidToUnicodeString(&SidString, Owner->Owner, TRUE);
|
||||||
|
ok_wstr(SidString.Buffer, L"S-1-5-32-544");
|
||||||
|
RtlFreeUnicodeString(&SidString);
|
||||||
|
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, Owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
QueryTokenPrimaryGroupTests(
|
||||||
|
_In_ HANDLE Token)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PTOKEN_PRIMARY_GROUP PrimaryGroup;
|
||||||
|
ULONG BufferLength;
|
||||||
|
UNICODE_STRING SidString;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Query the exact buffer length to hold
|
||||||
|
* our stuff, STATUS_BUFFER_TOO_SMALL must
|
||||||
|
* be expected here.
|
||||||
|
*/
|
||||||
|
Status = NtQueryInformationToken(Token,
|
||||||
|
TokenPrimaryGroup,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&BufferLength);
|
||||||
|
ok_ntstatus(Status, STATUS_BUFFER_TOO_SMALL);
|
||||||
|
|
||||||
|
/* Allocate the buffer based on the size we got */
|
||||||
|
PrimaryGroup = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
|
||||||
|
if (!PrimaryGroup)
|
||||||
|
{
|
||||||
|
ok(0, "Failed to allocate from heap for token primary group (required buffer length %lu)!\n", BufferLength);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now do the actual query */
|
||||||
|
Status = NtQueryInformationToken(Token,
|
||||||
|
TokenPrimaryGroup,
|
||||||
|
PrimaryGroup,
|
||||||
|
BufferLength,
|
||||||
|
&BufferLength);
|
||||||
|
ok_ntstatus(Status, STATUS_SUCCESS);
|
||||||
|
|
||||||
|
RtlConvertSidToUnicodeString(&SidString, PrimaryGroup->PrimaryGroup, TRUE);
|
||||||
|
trace("=============== TokenPrimaryGroup ===============\n");
|
||||||
|
trace("The primary group SID of current token is: %s\n", wine_dbgstr_w(SidString.Buffer));
|
||||||
|
trace("=========================================\n\n");
|
||||||
|
RtlFreeUnicodeString(&SidString);
|
||||||
|
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, PrimaryGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
QueryTokenDefaultDaclTests(
|
||||||
|
_In_ HANDLE Token)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PTOKEN_DEFAULT_DACL Dacl;
|
||||||
|
ULONG BufferLength;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Query the exact buffer length to hold
|
||||||
|
* our stuff, STATUS_BUFFER_TOO_SMALL must
|
||||||
|
* be expected here.
|
||||||
|
*/
|
||||||
|
Status = NtQueryInformationToken(Token,
|
||||||
|
TokenDefaultDacl,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&BufferLength);
|
||||||
|
ok_ntstatus(Status, STATUS_BUFFER_TOO_SMALL);
|
||||||
|
|
||||||
|
/* Allocate the buffer based on the size we got */
|
||||||
|
Dacl = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
|
||||||
|
if (!Dacl)
|
||||||
|
{
|
||||||
|
ok(0, "Failed to allocate from heap for token default DACL (required buffer length %lu)!\n", BufferLength);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now do the actual query and validate the
|
||||||
|
* ACL revision and number count of ACEs.
|
||||||
|
*/
|
||||||
|
Status = NtQueryInformationToken(Token,
|
||||||
|
TokenDefaultDacl,
|
||||||
|
Dacl,
|
||||||
|
BufferLength,
|
||||||
|
&BufferLength);
|
||||||
|
ok_ntstatus(Status, STATUS_SUCCESS);
|
||||||
|
ok(Dacl->DefaultDacl->AclRevision == 2, "The ACL revision of token default DACL must be 2 (current revision %u)!\n", Dacl->DefaultDacl->AclRevision);
|
||||||
|
ok(Dacl->DefaultDacl->AceCount == 2, "The ACL's ACE count must be 2 (current ACE count %u)!\n", Dacl->DefaultDacl->AceCount);
|
||||||
|
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
QueryTokenSourceTests(
|
||||||
|
_In_ HANDLE Token)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PTOKEN_SOURCE Source;
|
||||||
|
ULONG BufferLength;
|
||||||
|
CHAR SourceName[8];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Query the exact buffer length to hold
|
||||||
|
* our stuff, STATUS_BUFFER_TOO_SMALL must
|
||||||
|
* be expected here.
|
||||||
|
*/
|
||||||
|
Status = NtQueryInformationToken(Token,
|
||||||
|
TokenSource,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&BufferLength);
|
||||||
|
ok_ntstatus(Status, STATUS_BUFFER_TOO_SMALL);
|
||||||
|
|
||||||
|
/* Allocate the buffer based on the size we got */
|
||||||
|
Source = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
|
||||||
|
if (!Source)
|
||||||
|
{
|
||||||
|
ok(0, "Failed to allocate from heap for token source (required buffer length %lu)!\n", BufferLength);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now do the actual query */
|
||||||
|
Status = NtQueryInformationToken(Token,
|
||||||
|
TokenSource,
|
||||||
|
Source,
|
||||||
|
BufferLength,
|
||||||
|
&BufferLength);
|
||||||
|
ok_ntstatus(Status, STATUS_SUCCESS);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Subtract the source name from the queried buffer
|
||||||
|
* and compare it. The source name in question must be
|
||||||
|
* "User32" as the primary token of the current calling
|
||||||
|
* process is generated when the user has successfully
|
||||||
|
* logged in and he's into the desktop.
|
||||||
|
*/
|
||||||
|
SourceName[0] = Source->SourceName[0];
|
||||||
|
SourceName[1] = Source->SourceName[1];
|
||||||
|
SourceName[2] = Source->SourceName[2];
|
||||||
|
SourceName[3] = Source->SourceName[3];
|
||||||
|
SourceName[4] = Source->SourceName[4];
|
||||||
|
SourceName[5] = Source->SourceName[5];
|
||||||
|
SourceName[6] = '\0';
|
||||||
|
ok_str(SourceName, "User32");
|
||||||
|
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, Source);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
QueryTokenTypeTests(
|
||||||
|
_In_ HANDLE Token)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
TOKEN_TYPE Type;
|
||||||
|
ULONG BufferLength;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Query the token type. The token of the
|
||||||
|
* current calling process must be primary
|
||||||
|
* since we aren't impersonating the security
|
||||||
|
* context of a client.
|
||||||
|
*/
|
||||||
|
Status = NtQueryInformationToken(Token,
|
||||||
|
TokenType,
|
||||||
|
&Type,
|
||||||
|
sizeof(TOKEN_TYPE),
|
||||||
|
&BufferLength);
|
||||||
|
ok_ntstatus(Status, STATUS_SUCCESS);
|
||||||
|
ok(Type == TokenPrimary, "The current token is not primary!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
QueryTokenImpersonationTests(
|
||||||
|
_In_ HANDLE Token)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
SECURITY_IMPERSONATION_LEVEL Level;
|
||||||
|
ULONG BufferLength;
|
||||||
|
HANDLE DupToken;
|
||||||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Windows throws STATUS_INVALID_INFO_CLASS here
|
||||||
|
* because one cannot simply query the impersonation
|
||||||
|
* level of a primary token.
|
||||||
|
*/
|
||||||
|
Status = NtQueryInformationToken(Token,
|
||||||
|
TokenImpersonationLevel,
|
||||||
|
&Level,
|
||||||
|
sizeof(SECURITY_IMPERSONATION_LEVEL),
|
||||||
|
&BufferLength);
|
||||||
|
ok_ntstatus(Status, STATUS_INVALID_INFO_CLASS);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the object attribute and duplicate
|
||||||
|
* the token into an actual impersonation one.
|
||||||
|
*/
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
Status = NtDuplicateToken(Token,
|
||||||
|
TOKEN_QUERY,
|
||||||
|
&ObjectAttributes,
|
||||||
|
FALSE,
|
||||||
|
TokenImpersonation,
|
||||||
|
&DupToken);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ok(0, "Failed to duplicate token (Status code %lx)!\n", Status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now do the actual query */
|
||||||
|
Status = NtQueryInformationToken(DupToken,
|
||||||
|
TokenImpersonationLevel,
|
||||||
|
&Level,
|
||||||
|
sizeof(SECURITY_IMPERSONATION_LEVEL),
|
||||||
|
&BufferLength);
|
||||||
|
ok_ntstatus(Status, STATUS_SUCCESS);
|
||||||
|
ok(Level == SecurityAnonymous, "The current token impersonation level is not anonymous!\n");
|
||||||
|
CloseHandle(DupToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
QueryTokenStatisticsTests(
|
||||||
|
_In_ HANDLE Token)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PTOKEN_STATISTICS Statistics;
|
||||||
|
ULONG BufferLength;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Query the exact buffer length to hold
|
||||||
|
* our stuff, STATUS_BUFFER_TOO_SMALL must
|
||||||
|
* be expected here.
|
||||||
|
*/
|
||||||
|
Status = NtQueryInformationToken(Token,
|
||||||
|
TokenStatistics,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&BufferLength);
|
||||||
|
ok_ntstatus(Status, STATUS_BUFFER_TOO_SMALL);
|
||||||
|
|
||||||
|
/* Allocate the buffer based on the size we got */
|
||||||
|
Statistics = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
|
||||||
|
if (!Statistics)
|
||||||
|
{
|
||||||
|
skip("Failed to allocate heap for token statistics!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do the actual query */
|
||||||
|
Status = NtQueryInformationToken(Token,
|
||||||
|
TokenStatistics,
|
||||||
|
Statistics,
|
||||||
|
BufferLength,
|
||||||
|
&BufferLength);
|
||||||
|
ok_ntstatus(Status, STATUS_SUCCESS);
|
||||||
|
|
||||||
|
trace("=============== TokenStatistics ===============\n");
|
||||||
|
trace("Token ID: %lu %lu\n", Statistics->TokenId.LowPart, Statistics->TokenId.HighPart);
|
||||||
|
trace("Authentication ID: %lu %lu\n", Statistics->AuthenticationId.LowPart, Statistics->AuthenticationId.HighPart);
|
||||||
|
trace("Dynamic Charged: %lu\n", Statistics->DynamicCharged);
|
||||||
|
trace("Dynamic Available: %lu\n", Statistics->DynamicAvailable);
|
||||||
|
trace("Modified ID: %lu %lu\n", Statistics->ModifiedId.LowPart, Statistics->ModifiedId.HighPart);
|
||||||
|
trace("=========================================\n\n");
|
||||||
|
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, Statistics);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
QueryTokenRestrictedSidsTest(
|
||||||
|
_In_ HANDLE Token)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PTOKEN_GROUPS RestrictedGroups;
|
||||||
|
TOKEN_GROUPS SidToRestrict;
|
||||||
|
ULONG BufferLength;
|
||||||
|
HANDLE FilteredToken;
|
||||||
|
PSID WorldSid;
|
||||||
|
static SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Query the exact buffer length to hold
|
||||||
|
* our stuff, STATUS_BUFFER_TOO_SMALL must
|
||||||
|
* be expected here.
|
||||||
|
*/
|
||||||
|
Status = NtQueryInformationToken(Token,
|
||||||
|
TokenRestrictedSids,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&BufferLength);
|
||||||
|
ok_ntstatus(Status, STATUS_BUFFER_TOO_SMALL);
|
||||||
|
|
||||||
|
/* Allocate the buffer based on the size we got */
|
||||||
|
RestrictedGroups = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
|
||||||
|
if (!RestrictedGroups)
|
||||||
|
{
|
||||||
|
ok(0, "Failed to allocate from heap for restricted SIDs (required buffer length %lu)!\n", BufferLength);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Query the number of restricted SIDs. Originally the token
|
||||||
|
* doesn't have any restricted SIDs inserted.
|
||||||
|
*/
|
||||||
|
Status = NtQueryInformationToken(Token,
|
||||||
|
TokenRestrictedSids,
|
||||||
|
RestrictedGroups,
|
||||||
|
BufferLength,
|
||||||
|
&BufferLength);
|
||||||
|
ok_ntstatus(Status, STATUS_SUCCESS);
|
||||||
|
ok(RestrictedGroups->GroupCount == 0, "There mustn't be any restricted SIDs before filtering (number of restricted SIDs %lu)!\n", RestrictedGroups->GroupCount);
|
||||||
|
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, RestrictedGroups);
|
||||||
|
RestrictedGroups = NULL;
|
||||||
|
|
||||||
|
Status = RtlAllocateAndInitializeSid(&WorldAuthority,
|
||||||
|
1,
|
||||||
|
SECURITY_WORLD_RID,
|
||||||
|
0, 0, 0, 0, 0, 0, 0,
|
||||||
|
&WorldSid);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ok(0, "Failed to allocate World SID (Status code %lx)!\n", Status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SidToRestrict.GroupCount = 1;
|
||||||
|
SidToRestrict.Groups[0].Attributes = 0;
|
||||||
|
SidToRestrict.Groups[0].Sid = WorldSid;
|
||||||
|
|
||||||
|
Status = NtFilterToken(Token,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&SidToRestrict,
|
||||||
|
&FilteredToken);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ok(0, "Failed to filter the current token (Status code %lx)!\n", Status);
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, WorldSid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = NtQueryInformationToken(FilteredToken,
|
||||||
|
TokenRestrictedSids,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&BufferLength);
|
||||||
|
ok_ntstatus(Status, STATUS_BUFFER_TOO_SMALL);
|
||||||
|
|
||||||
|
RestrictedGroups = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
|
||||||
|
if (!RestrictedGroups)
|
||||||
|
{
|
||||||
|
ok(0, "Failed to allocate from heap for restricted SIDs (required buffer length %lu)!\n", BufferLength);
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, WorldSid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do a query again, this time we must have a
|
||||||
|
* restricted SID inserted into the token.
|
||||||
|
*/
|
||||||
|
Status = NtQueryInformationToken(FilteredToken,
|
||||||
|
TokenRestrictedSids,
|
||||||
|
RestrictedGroups,
|
||||||
|
BufferLength,
|
||||||
|
&BufferLength);
|
||||||
|
ok_ntstatus(Status, STATUS_SUCCESS);
|
||||||
|
ok(RestrictedGroups->GroupCount == 1, "There must be only one restricted SID added in token (number of restricted SIDs %lu)!\n", RestrictedGroups->GroupCount);
|
||||||
|
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, RestrictedGroups);
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, WorldSid);
|
||||||
|
CloseHandle(FilteredToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
QueryTokenSessionIdTests(
|
||||||
|
_In_ HANDLE Token)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG SessionId;
|
||||||
|
ULONG BufferLength;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Query the session ID. Generally the current
|
||||||
|
* process token is not under any terminal service
|
||||||
|
* so the ID must be 0.
|
||||||
|
*/
|
||||||
|
Status = NtQueryInformationToken(Token,
|
||||||
|
TokenSessionId,
|
||||||
|
&SessionId,
|
||||||
|
sizeof(ULONG),
|
||||||
|
&BufferLength);
|
||||||
|
ok_ntstatus(Status, STATUS_SUCCESS);
|
||||||
|
ok(SessionId == 0, "The session ID of current token must be 0 (current session %lu)!\n", SessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
QueryTokenOriginTests(
|
||||||
|
_In_ HANDLE Token)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
TOKEN_ORIGIN Origin;
|
||||||
|
ULONG BufferLength;
|
||||||
|
|
||||||
|
/* Query the token origin */
|
||||||
|
Status = NtQueryInformationToken(Token,
|
||||||
|
TokenOrigin,
|
||||||
|
&Origin,
|
||||||
|
sizeof(TOKEN_ORIGIN),
|
||||||
|
&BufferLength);
|
||||||
|
ok_ntstatus(Status, STATUS_SUCCESS);
|
||||||
|
ok(Origin.OriginatingLogonSession.LowPart == 0x3e7, "The LowPart field of the originating logon session must be SYSTEM_LUID (current value %lu)!\n",
|
||||||
|
Origin.OriginatingLogonSession.LowPart);
|
||||||
|
ok(Origin.OriginatingLogonSession.HighPart == 0x0, "The HighPart field of the logon session must be 0 (current value %lu)!\n",
|
||||||
|
Origin.OriginatingLogonSession.HighPart);
|
||||||
|
}
|
||||||
|
|
||||||
|
START_TEST(NtQueryInformationToken)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
HANDLE Token;
|
||||||
|
PVOID Dummy;
|
||||||
|
ULONG DummyReturnLength;
|
||||||
|
|
||||||
|
/* ReturnLength is NULL */
|
||||||
|
Status = NtQueryInformationToken(NULL,
|
||||||
|
TokenUser,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
NULL);
|
||||||
|
ok_ntstatus(Status, STATUS_ACCESS_VIOLATION);
|
||||||
|
|
||||||
|
/* We don't give any token here */
|
||||||
|
Status = NtQueryInformationToken(NULL,
|
||||||
|
TokenUser,
|
||||||
|
&Dummy,
|
||||||
|
0,
|
||||||
|
&DummyReturnLength);
|
||||||
|
ok_ntstatus(Status, STATUS_INVALID_HANDLE);
|
||||||
|
|
||||||
|
Token = OpenCurrentToken();
|
||||||
|
|
||||||
|
/* Class 0 is unused on Windows */
|
||||||
|
Status = NtQueryInformationToken(Token,
|
||||||
|
0,
|
||||||
|
&Dummy,
|
||||||
|
0,
|
||||||
|
&DummyReturnLength);
|
||||||
|
ok_ntstatus(Status, STATUS_INVALID_INFO_CLASS);
|
||||||
|
|
||||||
|
/* We give a bogus info class */
|
||||||
|
Status = NtQueryInformationToken(Token,
|
||||||
|
0xa0a,
|
||||||
|
&Dummy,
|
||||||
|
0,
|
||||||
|
&DummyReturnLength);
|
||||||
|
ok_ntstatus(Status, STATUS_INVALID_INFO_CLASS);
|
||||||
|
|
||||||
|
/* Now perform tests for each class */
|
||||||
|
QueryTokenUserTests(Token);
|
||||||
|
QueryTokenGroupsTests(Token);
|
||||||
|
QueryTokenPrivilegesTests(Token);
|
||||||
|
QueryTokenOwnerTests(Token);
|
||||||
|
QueryTokenPrimaryGroupTests(Token);
|
||||||
|
QueryTokenDefaultDaclTests(Token);
|
||||||
|
QueryTokenSourceTests(Token);
|
||||||
|
QueryTokenTypeTests(Token);
|
||||||
|
QueryTokenImpersonationTests(Token);
|
||||||
|
QueryTokenStatisticsTests(Token);
|
||||||
|
QueryTokenRestrictedSidsTest(Token);
|
||||||
|
QueryTokenSessionIdTests(Token);
|
||||||
|
QueryTokenOriginTests(Token);
|
||||||
|
|
||||||
|
CloseHandle(Token);
|
||||||
|
}
|
247
modules/rostests/apitests/ntdll/NtSetInformationToken.c
Normal file
247
modules/rostests/apitests/ntdll/NtSetInformationToken.c
Normal file
|
@ -0,0 +1,247 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS API tests
|
||||||
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||||
|
* PURPOSE: Tests for the NtSetInformationToken API
|
||||||
|
* COPYRIGHT: Copyright 2022 George Bișoc <george.bisoc@reactos.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "precomp.h"
|
||||||
|
|
||||||
|
static
|
||||||
|
HANDLE
|
||||||
|
OpenCurrentToken(VOID)
|
||||||
|
{
|
||||||
|
BOOL Success;
|
||||||
|
HANDLE Token;
|
||||||
|
|
||||||
|
Success = OpenProcessToken(GetCurrentProcess(),
|
||||||
|
TOKEN_READ | TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID,
|
||||||
|
&Token);
|
||||||
|
if (!Success)
|
||||||
|
{
|
||||||
|
ok(0, "OpenProcessToken() has failed to get the process' token (error code: %lu)!\n", GetLastError());
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Token;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
PTOKEN_DEFAULT_DACL
|
||||||
|
QueryOriginalDefaultDacl(
|
||||||
|
_In_ HANDLE Token,
|
||||||
|
_Out_ PULONG DaclLength)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PTOKEN_DEFAULT_DACL Dacl;
|
||||||
|
ULONG BufferLength;
|
||||||
|
|
||||||
|
*DaclLength = 0;
|
||||||
|
|
||||||
|
Status = NtQueryInformationToken(Token,
|
||||||
|
TokenDefaultDacl,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&BufferLength);
|
||||||
|
if (!NT_SUCCESS(Status) && (Status != STATUS_BUFFER_TOO_SMALL))
|
||||||
|
{
|
||||||
|
ok(0, "Failed to query buffer length, STATUS_BUFFER_TOO_SMALL has to be expected (Status code %lx)!\n", Status);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dacl = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
|
||||||
|
if (!Dacl)
|
||||||
|
{
|
||||||
|
ok(0, "Failed to allocate from heap for token default DACL (required buffer length %lu)!\n", BufferLength);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = NtQueryInformationToken(Token,
|
||||||
|
TokenDefaultDacl,
|
||||||
|
Dacl,
|
||||||
|
BufferLength,
|
||||||
|
&BufferLength);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ok(0, "Failed to query default DACL (Status code %lx)!\n", Status);
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*DaclLength = BufferLength;
|
||||||
|
return Dacl;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
PACL
|
||||||
|
CreateNewDefaultDacl(
|
||||||
|
_Out_ PULONG DaclLength)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PACL Dacl;
|
||||||
|
ULONG Length;
|
||||||
|
PSID LocalSystemSid;
|
||||||
|
static SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
|
||||||
|
|
||||||
|
*DaclLength = 0;
|
||||||
|
|
||||||
|
Status = RtlAllocateAndInitializeSid(&NtAuthority,
|
||||||
|
1,
|
||||||
|
SECURITY_LOCAL_SYSTEM_RID,
|
||||||
|
0, 0, 0, 0, 0, 0, 0,
|
||||||
|
&LocalSystemSid);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ok(0, "Failed to allocate Local System SID (Status code %lx)!\n", Status);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Length = sizeof(ACL) +
|
||||||
|
sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(LocalSystemSid);
|
||||||
|
|
||||||
|
Dacl = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||||
|
HEAP_ZERO_MEMORY,
|
||||||
|
Length);
|
||||||
|
if (!Dacl)
|
||||||
|
{
|
||||||
|
ok(0, "Failed to allocate from heap for DACL!\n");
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, LocalSystemSid);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = RtlCreateAcl(Dacl,
|
||||||
|
Length,
|
||||||
|
ACL_REVISION);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ok(0, "Failed to create ACL (Status code %lx)!\n", Status);
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, LocalSystemSid);
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = RtlAddAccessAllowedAce(Dacl,
|
||||||
|
ACL_REVISION,
|
||||||
|
GENERIC_ALL,
|
||||||
|
LocalSystemSid);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ok(0, "Failed to add access allowed ACE (Status code %lx)!\n", Status);
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, LocalSystemSid);
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*DaclLength = Length;
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, LocalSystemSid);
|
||||||
|
return Dacl;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
SetTokenDefaultDaclTests(
|
||||||
|
_In_ HANDLE Token)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PACL NewDacl;
|
||||||
|
TOKEN_DEFAULT_DACL NewDefaultDacl;
|
||||||
|
PTOKEN_DEFAULT_DACL DefaultDacl;
|
||||||
|
ULONG OriginalDaclLength, NewDaclLength;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Query the original DACL of the token first,
|
||||||
|
* we don't want to leave the token tampered
|
||||||
|
* later on.
|
||||||
|
*/
|
||||||
|
DefaultDacl = QueryOriginalDefaultDacl(Token, &OriginalDaclLength);
|
||||||
|
if (!DefaultDacl)
|
||||||
|
{
|
||||||
|
ok(0, "Failed to query token's default DACL!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate new DACL */
|
||||||
|
NewDacl = CreateNewDefaultDacl(&NewDaclLength);
|
||||||
|
if (!DefaultDacl)
|
||||||
|
{
|
||||||
|
ok(0, "Failed to allocate buffer for new DACL!\n");
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, DefaultDacl);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NewDefaultDacl.DefaultDacl = NewDacl;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set a new DACL for the token.
|
||||||
|
*/
|
||||||
|
Status = NtSetInformationToken(Token,
|
||||||
|
TokenDefaultDacl,
|
||||||
|
&NewDefaultDacl,
|
||||||
|
NewDaclLength);
|
||||||
|
ok_ntstatus(Status, STATUS_SUCCESS);
|
||||||
|
|
||||||
|
/* Now set the original DACL */
|
||||||
|
Status = NtSetInformationToken(Token,
|
||||||
|
TokenDefaultDacl,
|
||||||
|
DefaultDacl,
|
||||||
|
OriginalDaclLength);
|
||||||
|
ok_ntstatus(Status, STATUS_SUCCESS);
|
||||||
|
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, DefaultDacl);
|
||||||
|
RtlFreeHeap(RtlGetProcessHeap(), 0, NewDacl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
SetTokenSessionIdTests(
|
||||||
|
_In_ HANDLE Token)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG SessionId = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We're not allowed to set a session ID
|
||||||
|
* because we don't have the TCB privilege.
|
||||||
|
*/
|
||||||
|
Status = NtSetInformationToken(Token,
|
||||||
|
TokenSessionId,
|
||||||
|
&SessionId,
|
||||||
|
sizeof(ULONG));
|
||||||
|
ok_ntstatus(Status, STATUS_PRIVILEGE_NOT_HELD);
|
||||||
|
}
|
||||||
|
|
||||||
|
START_TEST(NtSetInformationToken)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG DummyReturnLength = 0;
|
||||||
|
HANDLE Token;
|
||||||
|
|
||||||
|
/* Everything else is NULL */
|
||||||
|
Status = NtSetInformationToken(NULL,
|
||||||
|
TokenOwner,
|
||||||
|
NULL,
|
||||||
|
0);
|
||||||
|
ok_ntstatus(Status, STATUS_INVALID_HANDLE);
|
||||||
|
|
||||||
|
/* We don't give a token */
|
||||||
|
Status = NtSetInformationToken(NULL,
|
||||||
|
TokenOwner,
|
||||||
|
NULL,
|
||||||
|
DummyReturnLength);
|
||||||
|
ok_ntstatus(Status, STATUS_INVALID_HANDLE);
|
||||||
|
|
||||||
|
Token = OpenCurrentToken();
|
||||||
|
|
||||||
|
/* We give a bogus token class */
|
||||||
|
Status = NtSetInformationToken(Token,
|
||||||
|
0xa0a,
|
||||||
|
NULL,
|
||||||
|
DummyReturnLength);
|
||||||
|
ok_ntstatus(Status, STATUS_INVALID_INFO_CLASS);
|
||||||
|
|
||||||
|
/* Now perform tests for each class */
|
||||||
|
SetTokenDefaultDaclTests(Token);
|
||||||
|
SetTokenSessionIdTests(Token);
|
||||||
|
|
||||||
|
CloseHandle(Token);
|
||||||
|
}
|
|
@ -31,6 +31,7 @@ extern void func_NtProtectVirtualMemory(void);
|
||||||
extern void func_NtQueryInformationFile(void);
|
extern void func_NtQueryInformationFile(void);
|
||||||
extern void func_NtQueryInformationProcess(void);
|
extern void func_NtQueryInformationProcess(void);
|
||||||
extern void func_NtQueryInformationThread(void);
|
extern void func_NtQueryInformationThread(void);
|
||||||
|
extern void func_NtQueryInformationToken(void);
|
||||||
extern void func_NtQueryKey(void);
|
extern void func_NtQueryKey(void);
|
||||||
extern void func_NtQuerySystemEnvironmentValue(void);
|
extern void func_NtQuerySystemEnvironmentValue(void);
|
||||||
extern void func_NtQuerySystemInformation(void);
|
extern void func_NtQuerySystemInformation(void);
|
||||||
|
@ -41,6 +42,7 @@ extern void func_NtSaveKey(void);
|
||||||
extern void func_NtSetInformationFile(void);
|
extern void func_NtSetInformationFile(void);
|
||||||
extern void func_NtSetInformationProcess(void);
|
extern void func_NtSetInformationProcess(void);
|
||||||
extern void func_NtSetInformationThread(void);
|
extern void func_NtSetInformationThread(void);
|
||||||
|
extern void func_NtSetInformationToken(void);
|
||||||
extern void func_NtSetValueKey(void);
|
extern void func_NtSetValueKey(void);
|
||||||
extern void func_NtSetVolumeInformationFile(void);
|
extern void func_NtSetVolumeInformationFile(void);
|
||||||
extern void func_NtSystemInformation(void);
|
extern void func_NtSystemInformation(void);
|
||||||
|
@ -119,6 +121,7 @@ const struct test winetest_testlist[] =
|
||||||
{ "NtQueryInformationFile", func_NtQueryInformationFile },
|
{ "NtQueryInformationFile", func_NtQueryInformationFile },
|
||||||
{ "NtQueryInformationProcess", func_NtQueryInformationProcess },
|
{ "NtQueryInformationProcess", func_NtQueryInformationProcess },
|
||||||
{ "NtQueryInformationThread", func_NtQueryInformationThread },
|
{ "NtQueryInformationThread", func_NtQueryInformationThread },
|
||||||
|
{ "NtQueryInformationToken", func_NtQueryInformationToken },
|
||||||
{ "NtQueryKey", func_NtQueryKey },
|
{ "NtQueryKey", func_NtQueryKey },
|
||||||
{ "NtQuerySystemEnvironmentValue", func_NtQuerySystemEnvironmentValue },
|
{ "NtQuerySystemEnvironmentValue", func_NtQuerySystemEnvironmentValue },
|
||||||
{ "NtQuerySystemInformation", func_NtQuerySystemInformation },
|
{ "NtQuerySystemInformation", func_NtQuerySystemInformation },
|
||||||
|
@ -129,6 +132,7 @@ const struct test winetest_testlist[] =
|
||||||
{ "NtSetInformationFile", func_NtSetInformationFile },
|
{ "NtSetInformationFile", func_NtSetInformationFile },
|
||||||
{ "NtSetInformationProcess", func_NtSetInformationProcess },
|
{ "NtSetInformationProcess", func_NtSetInformationProcess },
|
||||||
{ "NtSetInformationThread", func_NtSetInformationThread },
|
{ "NtSetInformationThread", func_NtSetInformationThread },
|
||||||
|
{ "NtSetInformationToken", func_NtSetInformationToken },
|
||||||
{ "NtSetValueKey", func_NtSetValueKey},
|
{ "NtSetValueKey", func_NtSetValueKey},
|
||||||
{ "NtSetVolumeInformationFile", func_NtSetVolumeInformationFile },
|
{ "NtSetVolumeInformationFile", func_NtSetVolumeInformationFile },
|
||||||
{ "NtSystemInformation", func_NtSystemInformation },
|
{ "NtSystemInformation", func_NtSystemInformation },
|
||||||
|
|
Loading…
Reference in a new issue