2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/advapi32/token/token.c
5 * PURPOSE: Token functions
6 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
20 AdjustTokenGroups (HANDLE TokenHandle
,
22 PTOKEN_GROUPS NewState
,
24 PTOKEN_GROUPS PreviousState
,
29 Status
= NtAdjustGroupsToken (TokenHandle
,
34 (PULONG
)ReturnLength
);
35 if (!NT_SUCCESS (Status
))
37 SetLastError (RtlNtStatusToDosError (Status
));
49 AdjustTokenPrivileges (HANDLE TokenHandle
,
50 BOOL DisableAllPrivileges
,
51 PTOKEN_PRIVILEGES NewState
,
53 PTOKEN_PRIVILEGES PreviousState
,
58 Status
= NtAdjustPrivilegesToken (TokenHandle
,
63 (PULONG
)ReturnLength
);
64 if (STATUS_NOT_ALL_ASSIGNED
== Status
)
66 SetLastError(ERROR_NOT_ALL_ASSIGNED
);
69 if (! NT_SUCCESS(Status
))
71 SetLastError(RtlNtStatusToDosError(Status
));
75 SetLastError(ERROR_SUCCESS
); /* AdjustTokenPrivileges is documented to do this */
84 GetTokenInformation (HANDLE TokenHandle
,
85 TOKEN_INFORMATION_CLASS TokenInformationClass
,
86 LPVOID TokenInformation
,
87 DWORD TokenInformationLength
,
92 Status
= NtQueryInformationToken (TokenHandle
,
93 TokenInformationClass
,
95 TokenInformationLength
,
96 (PULONG
)ReturnLength
);
97 if (!NT_SUCCESS (Status
))
99 SetLastError (RtlNtStatusToDosError (Status
));
111 SetTokenInformation (HANDLE TokenHandle
,
112 TOKEN_INFORMATION_CLASS TokenInformationClass
,
113 LPVOID TokenInformation
,
114 DWORD TokenInformationLength
)
118 Status
= NtSetInformationToken (TokenHandle
,
119 TokenInformationClass
,
121 TokenInformationLength
);
122 if (!NT_SUCCESS (Status
))
124 SetLastError (RtlNtStatusToDosError (Status
));
136 AccessCheck (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
139 PGENERIC_MAPPING GenericMapping
,
140 PPRIVILEGE_SET PrivilegeSet
,
141 LPDWORD PrivilegeSetLength
,
142 LPDWORD GrantedAccess
,
148 Status
= NtAccessCheck (pSecurityDescriptor
,
153 (PULONG
)PrivilegeSetLength
,
154 (PACCESS_MASK
)GrantedAccess
,
156 if (!NT_SUCCESS (Status
))
158 SetLastError (RtlNtStatusToDosError (Status
));
162 if (!NT_SUCCESS (AccessStat
))
164 SetLastError (RtlNtStatusToDosError (Status
));
165 *AccessStatus
= FALSE
;
169 *AccessStatus
= TRUE
;
179 OpenProcessToken (HANDLE ProcessHandle
,
185 Status
= NtOpenProcessToken (ProcessHandle
,
188 if (!NT_SUCCESS (Status
))
190 SetLastError (RtlNtStatusToDosError (Status
));
202 OpenThreadToken (HANDLE ThreadHandle
,
209 Status
= NtOpenThreadToken (ThreadHandle
,
213 if (!NT_SUCCESS(Status
))
215 SetLastError (RtlNtStatusToDosError (Status
));
227 SetThreadToken (IN PHANDLE ThreadHandle OPTIONAL
,
228 IN HANDLE TokenHandle
)
233 hThread
= ((ThreadHandle
!= NULL
) ? *ThreadHandle
: NtCurrentThread());
235 Status
= NtSetInformationThread (hThread
,
236 ThreadImpersonationToken
,
239 if (!NT_SUCCESS(Status
))
241 SetLastError (RtlNtStatusToDosError (Status
));
253 DuplicateTokenEx (IN HANDLE ExistingTokenHandle
,
254 IN DWORD dwDesiredAccess
,
255 IN LPSECURITY_ATTRIBUTES lpTokenAttributes OPTIONAL
,
256 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
,
257 IN TOKEN_TYPE TokenType
,
258 OUT PHANDLE DuplicateTokenHandle
)
260 OBJECT_ATTRIBUTES ObjectAttributes
;
263 SECURITY_QUALITY_OF_SERVICE Sqos
;
265 Sqos
.Length
= sizeof(SECURITY_QUALITY_OF_SERVICE
);
266 Sqos
.ImpersonationLevel
= ImpersonationLevel
;
267 Sqos
.ContextTrackingMode
= 0;
268 Sqos
.EffectiveOnly
= FALSE
;
270 if (lpTokenAttributes
!= NULL
)
272 InitializeObjectAttributes(&ObjectAttributes
,
274 lpTokenAttributes
->bInheritHandle
? OBJ_INHERIT
: 0,
276 lpTokenAttributes
->lpSecurityDescriptor
);
280 InitializeObjectAttributes(&ObjectAttributes
,
287 ObjectAttributes
.SecurityQualityOfService
= &Sqos
;
289 Status
= NtDuplicateToken (ExistingTokenHandle
,
295 if (!NT_SUCCESS(Status
))
297 SetLastError(RtlNtStatusToDosError(Status
));
309 DuplicateToken (IN HANDLE ExistingTokenHandle
,
310 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
,
311 OUT PHANDLE DuplicateTokenHandle
)
313 return DuplicateTokenEx (ExistingTokenHandle
,
314 TOKEN_IMPERSONATE
| TOKEN_QUERY
,
318 DuplicateTokenHandle
);
326 CheckTokenMembership (HANDLE ExistingTokenHandle
,
330 HANDLE AccessToken
= NULL
;
334 PTOKEN_GROUPS lpGroups
= NULL
;
335 TOKEN_TYPE TokenInformation
;
337 if (IsMember
== NULL
)
339 SetLastError(ERROR_INVALID_PARAMETER
);
343 if (ExistingTokenHandle
== NULL
)
345 /* Get impersonation token of the calling thread */
346 if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY
, FALSE
, &ExistingTokenHandle
))
349 if (!DuplicateToken(ExistingTokenHandle
, SecurityAnonymous
, &AccessToken
))
351 CloseHandle(ExistingTokenHandle
);
354 CloseHandle(ExistingTokenHandle
);
358 if (!GetTokenInformation(ExistingTokenHandle
, TokenType
, &TokenInformation
, sizeof(TokenInformation
), &dwSize
))
360 if (TokenInformation
!= TokenImpersonation
)
362 /* Duplicate token to have a impersonation token */
363 if (!DuplicateToken(ExistingTokenHandle
, SecurityAnonymous
, &AccessToken
))
367 AccessToken
= ExistingTokenHandle
;
371 /* Search in groups of the token */
372 if (!GetTokenInformation(AccessToken
, TokenGroups
, NULL
, 0, &dwSize
))
374 lpGroups
= (PTOKEN_GROUPS
)HeapAlloc(GetProcessHeap(), 0, dwSize
);
377 if (!GetTokenInformation(AccessToken
, TokenGroups
, lpGroups
, dwSize
, &dwSize
))
379 for (i
= 0; i
< lpGroups
->GroupCount
; i
++)
381 if (EqualSid(SidToCheck
, &lpGroups
->Groups
[i
].Sid
))
388 /* FIXME: Search in users of the token? */
389 DPRINT1("CheckTokenMembership() partially implemented!\n");
393 if (lpGroups
!= NULL
)
394 HeapFree(GetProcessHeap(), 0, lpGroups
);
395 if (AccessToken
!= NULL
&& AccessToken
!= ExistingTokenHandle
)
396 CloseHandle(AccessToken
);
406 IsTokenRestricted(HANDLE TokenHandle
)
409 PTOKEN_GROUPS lpGroups
;
413 /* determine the required buffer size and allocate enough memory to read the
414 list of restricted SIDs */
416 Status
= NtQueryInformationToken(TokenHandle
,
421 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
423 SetLastError(RtlNtStatusToDosError(Status
));
427 AllocAndReadRestrictedSids
:
428 lpGroups
= (PTOKEN_GROUPS
)HeapAlloc(GetProcessHeap(),
431 if (lpGroups
== NULL
)
433 SetLastError(ERROR_OUTOFMEMORY
);
437 /* actually read the list of the restricted SIDs */
439 Status
= NtQueryInformationToken(TokenHandle
,
444 if (NT_SUCCESS(Status
))
446 Ret
= (lpGroups
->GroupCount
!= 0);
448 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
450 /* looks like the token was modified in the meanwhile, let's just try again */
452 HeapFree(GetProcessHeap(),
456 goto AllocAndReadRestrictedSids
;
460 SetLastError(RtlNtStatusToDosError(Status
));
463 /* free allocated memory */
465 HeapFree(GetProcessHeap(),