Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

tokenset.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 Tokenset.c 00008 00009 Abstract: 00010 00011 This module implements the SET function for the executive 00012 token object. 00013 00014 Author: 00015 00016 Jim Kelly (JimK) 15-June-1990 00017 00018 00019 Revision History: 00020 00021 --*/ 00022 00023 #include "sep.h" 00024 #include "sertlp.h" 00025 #include "tokenp.h" 00026 00027 #ifdef ALLOC_PRAGMA 00028 #pragma alloc_text(PAGE,NtSetInformationToken) 00029 #pragma alloc_text(PAGE,SepFreePrimaryGroup) 00030 #pragma alloc_text(PAGE,SepFreeDefaultDacl) 00031 #pragma alloc_text(PAGE,SepAppendPrimaryGroup) 00032 #pragma alloc_text(PAGE,SepAppendDefaultDacl) 00033 #endif 00034 00035 00036 NTSTATUS 00037 NtSetInformationToken ( 00038 IN HANDLE TokenHandle, 00039 IN TOKEN_INFORMATION_CLASS TokenInformationClass, 00040 IN PVOID TokenInformation, 00041 IN ULONG TokenInformationLength 00042 ) 00043 00044 /*++ 00045 00046 00047 Routine Description: 00048 00049 Modify information in a specified token. 00050 00051 Arguments: 00052 00053 TokenHandle - Provides a handle to the token to operate on. 00054 00055 TokenInformationClass - The token information class being set. 00056 00057 TokenInformation - The buffer containing the new values for the 00058 specified class of information. The buffer must be aligned 00059 on at least a longword boundary. The actual structures 00060 provided are dependent upon the information class specified, 00061 as defined in the TokenInformationClass parameter 00062 description. 00063 00064 TokenInformation Format By Information Class: 00065 00066 TokenUser => This value is not a valid value for this API. 00067 The User ID may not be replaced. 00068 00069 TokenGroups => This value is not a valid value for this 00070 API. The Group IDs may not be replaced. However, groups 00071 may be enabled and disabled using NtAdjustGroupsToken(). 00072 00073 TokenPrivileges => This value is not a valid value for 00074 this API. Privilege information may not be replaced. 00075 However, privileges may be explicitly enabled and disabled 00076 using the NtAdjustPrivilegesToken API. 00077 00078 TokenOwner => TOKEN_OWNER data structure. 00079 TOKEN_ADJUST_DEFAULT access is needed to replace this 00080 information in a token. The owner values that may be 00081 specified are restricted to the user and group IDs with an 00082 attribute indicating they may be assigned as the owner of 00083 objects. 00084 00085 TokenPrimaryGroup => TOKEN_PRIMARY_GROUP data structure. 00086 TOKEN_ADJUST_DEFAULT access is needed to replace this 00087 information in a token. The primary group values that may 00088 be specified are restricted to be one of the group IDs 00089 already in the token. 00090 00091 TokenDefaultDacl => TOKEN_DEFAULT_DACL data structure. 00092 TOKEN_ADJUST_DEFAULT access is needed to replace this 00093 information in a token. The ACL provided as a new default 00094 discretionary ACL is not validated for structural 00095 correctness or consistency. 00096 00097 TokenSource => This value is not a valid value for this 00098 API. The source name and context handle may not be 00099 replaced. 00100 00101 TokenStatistics => This value is not a valid value for this 00102 API. The statistics of a token are read-only. 00103 00104 TokenInformationLength - Indicates the length, in bytes, of the 00105 TokenInformation buffer. This is only the length of the primary 00106 buffer. All extensions of the primary buffer are self describing. 00107 00108 Return Value: 00109 00110 STATUS_SUCCESS - The operation was successful. 00111 00112 STATUS_INVALID_OWNER - The ID specified to be an owner (or 00113 default owner) is not one the caller may assign as the owner 00114 of an object. 00115 00116 STATUS_INVALID_INFO_CLASS - The specified information class is 00117 not one that may be specified in this API. 00118 00119 STATUS_ALLOTTED_SPACE_EXCEEDED - The space allotted for storage 00120 of the default discretionary access control and the primary 00121 group ID is not large enough to accept the new value of one 00122 of these fields. 00123 00124 --*/ 00125 { 00126 00127 KPROCESSOR_MODE PreviousMode; 00128 NTSTATUS Status; 00129 00130 PTOKEN Token; 00131 00132 ULONG Index; 00133 BOOLEAN Found; 00134 BOOLEAN TokenModified = FALSE; 00135 00136 ULONG NewLength; 00137 ULONG CurrentLength; 00138 00139 PSID CapturedOwner; 00140 PSID CapturedPrimaryGroup; 00141 PACL CapturedDefaultDacl; 00142 ACCESS_MASK DesiredAccess; 00143 00144 PAGED_CODE(); 00145 00146 // 00147 // Get previous processor mode and probe input buffer if necessary. 00148 // 00149 00150 PreviousMode = KeGetPreviousMode(); 00151 if (PreviousMode != KernelMode) { 00152 try { 00153 00154 // 00155 // This just probes the main part of the information buffer. 00156 // Any information class-specific data hung off the primary 00157 // buffer are self describing and must be probed separately 00158 // below. 00159 // 00160 00161 ProbeForRead( 00162 TokenInformation, 00163 TokenInformationLength, 00164 sizeof(ULONG) 00165 ); 00166 00167 } except(EXCEPTION_EXECUTE_HANDLER) { 00168 return GetExceptionCode(); 00169 } 00170 } 00171 00172 // 00173 // Return error if not legal class 00174 // 00175 if ( (TokenInformationClass != TokenOwner) && 00176 (TokenInformationClass != TokenPrimaryGroup) && 00177 (TokenInformationClass != TokenSessionId) && 00178 (TokenInformationClass != TokenDefaultDacl) ) { 00179 00180 return STATUS_INVALID_INFO_CLASS; 00181 00182 } 00183 00184 // 00185 // Check access rights and reference token 00186 // 00187 00188 00189 DesiredAccess = TOKEN_ADJUST_DEFAULT; 00190 if (TokenInformationClass == TokenSessionId) { 00191 DesiredAccess |= TOKEN_ADJUST_SESSIONID; 00192 } 00193 00194 Status = ObReferenceObjectByHandle( 00195 TokenHandle, // Handle 00196 DesiredAccess, // DesiredAccess 00197 SepTokenObjectType, // ObjectType 00198 PreviousMode, // AccessMode 00199 (PVOID *)&Token, // Object 00200 NULL // GrantedAccess 00201 ); 00202 00203 if ( !NT_SUCCESS(Status) ) { 00204 return Status; 00205 } 00206 00207 00208 // 00209 // Case on information class. 00210 // 00211 00212 switch ( TokenInformationClass ) { 00213 00214 case TokenOwner: 00215 00216 // 00217 // Make sure the buffer is large enough to hold the 00218 // necessary information class data structure. 00219 // 00220 00221 if (TokenInformationLength < (ULONG)sizeof(TOKEN_OWNER)) { 00222 00223 ObDereferenceObject( Token ); 00224 return STATUS_INFO_LENGTH_MISMATCH; 00225 } 00226 00227 // 00228 // Capture and copy 00229 00230 try { 00231 00232 // 00233 // Capture Owner SID 00234 // 00235 00236 CapturedOwner = ((PTOKEN_OWNER)TokenInformation)->Owner; 00237 Status = SeCaptureSid( 00238 CapturedOwner, 00239 PreviousMode, 00240 NULL, 0, 00241 PagedPool, 00242 TRUE, 00243 &CapturedOwner 00244 ); 00245 00246 } except(EXCEPTION_EXECUTE_HANDLER) { 00247 00248 ObDereferenceObject( Token ); 00249 return GetExceptionCode(); 00250 } 00251 00252 if (!NT_SUCCESS(Status)) { 00253 ObDereferenceObject( Token ); 00254 return Status; 00255 } 00256 00257 // 00258 // Gain write access to the token. 00259 // 00260 00261 SepAcquireTokenWriteLock( Token ); 00262 00263 // 00264 // Walk through the list of user and group IDs looking 00265 // for a match to the specified SID. If one is found, 00266 // make sure it may be assigned as an owner. If it can, 00267 // then set the index in the token's OwnerIndex field. 00268 // Otherwise, return invalid owner error. 00269 // 00270 00271 Index = 0; 00272 while (Index < Token->UserAndGroupCount) { 00273 00274 try { 00275 00276 Found = RtlEqualSid( 00277 CapturedOwner, 00278 Token->UserAndGroups[Index].Sid 00279 ); 00280 00281 if ( Found ) { 00282 00283 if ( SepIdAssignableAsOwner(Token,Index) ){ 00284 00285 Token->DefaultOwnerIndex = Index; 00286 TokenModified = TRUE; 00287 Status = STATUS_SUCCESS; 00288 00289 } else { 00290 00291 Status = STATUS_INVALID_OWNER; 00292 00293 } //endif assignable 00294 00295 SepReleaseTokenWriteLock( Token, TokenModified ); 00296 ObDereferenceObject( Token ); 00297 SeReleaseSid( CapturedOwner, PreviousMode, TRUE); 00298 return Status; 00299 00300 } //endif Found 00301 00302 } except(EXCEPTION_EXECUTE_HANDLER) { 00303 00304 SepReleaseTokenWriteLock( Token, TokenModified ); 00305 ObDereferenceObject( Token ); 00306 SeReleaseSid( CapturedOwner, PreviousMode, TRUE); 00307 return GetExceptionCode(); 00308 00309 } //endtry 00310 00311 Index += 1; 00312 00313 } //endwhile 00314 00315 SepReleaseTokenWriteLock( Token, TokenModified ); 00316 ObDereferenceObject( Token ); 00317 SeReleaseSid( CapturedOwner, PreviousMode, TRUE); 00318 return STATUS_INVALID_OWNER; 00319 00320 case TokenPrimaryGroup: 00321 00322 // 00323 // Assuming everything works out, the strategy is to move everything 00324 // in the Dynamic part of the token (exept the primary group) to 00325 // the beginning of the dynamic part, freeing up the entire end of 00326 // the dynamic part for the new primary group. 00327 // 00328 00329 // 00330 // Make sure the buffer is large enough to hold the 00331 // necessary information class data structure. 00332 // 00333 00334 if (TokenInformationLength < (ULONG)sizeof(TOKEN_PRIMARY_GROUP)) { 00335 00336 ObDereferenceObject( Token ); 00337 return STATUS_INFO_LENGTH_MISMATCH; 00338 } 00339 00340 // 00341 // Capture And Validate TOKEN_PRIMARY_GROUP and corresponding SID. 00342 // 00343 00344 try { 00345 00346 CapturedPrimaryGroup = 00347 ((PTOKEN_PRIMARY_GROUP)TokenInformation)->PrimaryGroup; 00348 00349 Status = SeCaptureSid( 00350 CapturedPrimaryGroup, 00351 PreviousMode, 00352 NULL, 0, 00353 PagedPool, 00354 TRUE, 00355 &CapturedPrimaryGroup 00356 ); 00357 00358 } except(EXCEPTION_EXECUTE_HANDLER) { 00359 00360 ObDereferenceObject( Token ); 00361 return GetExceptionCode(); 00362 } 00363 00364 if (!NT_SUCCESS(Status)) { 00365 ObDereferenceObject( Token ); 00366 return Status; 00367 } 00368 00369 if (!SepIdAssignableAsGroup( Token, CapturedPrimaryGroup )) { 00370 ObDereferenceObject( Token ); 00371 SeReleaseSid( CapturedPrimaryGroup, PreviousMode, TRUE); 00372 return STATUS_INVALID_PRIMARY_GROUP; 00373 } 00374 00375 // 00376 // Gain write access to the token. 00377 // 00378 00379 SepAcquireTokenWriteLock( Token ); 00380 00381 // 00382 // See if there is enough room in the dynamic part of the token 00383 // to replace the current Primary Group with the one specified. 00384 // 00385 00386 NewLength = SeLengthSid( CapturedPrimaryGroup ); 00387 CurrentLength = SeLengthSid( Token->PrimaryGroup ); 00388 00389 if (NewLength > (CurrentLength + Token->DynamicAvailable) ) { 00390 00391 SepReleaseTokenWriteLock( Token, TokenModified ); 00392 ObDereferenceObject( Token ); 00393 SeReleaseSid( CapturedPrimaryGroup, PreviousMode, TRUE); 00394 return STATUS_ALLOTTED_SPACE_EXCEEDED; 00395 } 00396 00397 // 00398 // Free up the existing primary group 00399 // 00400 00401 SepFreePrimaryGroup( Token ); 00402 00403 // 00404 // And put the new SID in its place 00405 // 00406 00407 SepAppendPrimaryGroup( Token, CapturedPrimaryGroup ); 00408 00409 TokenModified = TRUE; 00410 00411 // 00412 // All done. 00413 // 00414 00415 SepReleaseTokenWriteLock( Token, TokenModified ); 00416 ObDereferenceObject( Token ); 00417 SeReleaseSid( CapturedPrimaryGroup, PreviousMode, TRUE); 00418 return STATUS_SUCCESS; 00419 00420 00421 case TokenDefaultDacl: 00422 00423 // 00424 // Assuming everything works out, the strategy is to move everything 00425 // in the Dynamic part of the token (exept the default Dacl) to 00426 // the beginning of the dynamic part, freeing up the entire end of 00427 // the dynamic part for the new default Dacl. 00428 // 00429 00430 // 00431 // Make sure the buffer is large enough to hold the 00432 // necessary information class data structure. 00433 // 00434 00435 if (TokenInformationLength < (ULONG)sizeof(TOKEN_DEFAULT_DACL)) { 00436 00437 ObDereferenceObject( Token ); 00438 return STATUS_INFO_LENGTH_MISMATCH; 00439 } 00440 00441 // 00442 // Capture And Validate TOKEN_DEFAULT_DACL and corresponding ACL. 00443 // 00444 00445 try { 00446 00447 CapturedDefaultDacl = 00448 ((PTOKEN_DEFAULT_DACL)TokenInformation)->DefaultDacl; 00449 00450 if (ARGUMENT_PRESENT(CapturedDefaultDacl)) { 00451 Status = SeCaptureAcl( 00452 CapturedDefaultDacl, 00453 PreviousMode, 00454 NULL, 0, 00455 PagedPool, 00456 TRUE, 00457 &CapturedDefaultDacl, 00458 &NewLength 00459 ); 00460 00461 } else { 00462 NewLength = 0; 00463 Status = STATUS_SUCCESS; 00464 } 00465 00466 } except(EXCEPTION_EXECUTE_HANDLER) { 00467 00468 ObDereferenceObject( Token ); 00469 return GetExceptionCode(); 00470 } 00471 00472 if (!NT_SUCCESS(Status)) { 00473 ObDereferenceObject( Token ); 00474 return Status; 00475 } 00476 00477 // 00478 // Gain write access to the token. 00479 // 00480 00481 SepAcquireTokenWriteLock( Token ); 00482 00483 // 00484 // See if there is enough room in the dynamic part of the token 00485 // to replace the current Default Dacl with the one specified. 00486 // 00487 00488 if (ARGUMENT_PRESENT(Token->DefaultDacl)) { 00489 CurrentLength = Token->DefaultDacl->AclSize; 00490 } else { 00491 CurrentLength = 0; 00492 } 00493 00494 if (NewLength > (CurrentLength + Token->DynamicAvailable) ) { 00495 00496 SepReleaseTokenWriteLock( Token, TokenModified ); 00497 ObDereferenceObject( Token ); 00498 if (ARGUMENT_PRESENT(CapturedDefaultDacl)) { 00499 SeReleaseAcl( CapturedDefaultDacl, PreviousMode, TRUE); 00500 } 00501 return STATUS_ALLOTTED_SPACE_EXCEEDED; 00502 } 00503 00504 // 00505 // Free up the existing Default Dacl 00506 // 00507 00508 SepFreeDefaultDacl( Token ); 00509 00510 // 00511 // And put the new ACL in its place 00512 // 00513 00514 if (ARGUMENT_PRESENT(CapturedDefaultDacl)) { 00515 SepAppendDefaultDacl( Token, CapturedDefaultDacl ); 00516 } 00517 00518 TokenModified = TRUE; 00519 00520 // 00521 // All done. 00522 // 00523 00524 SepReleaseTokenWriteLock( Token, TokenModified ); 00525 ObDereferenceObject( Token ); 00526 if (ARGUMENT_PRESENT(CapturedDefaultDacl)) { 00527 SeReleaseAcl( CapturedDefaultDacl, PreviousMode, TRUE); 00528 } 00529 return STATUS_SUCCESS; 00530 00531 case TokenSessionId: 00532 { 00533 ULONG SessionId; 00534 00535 if ( TokenInformationLength != sizeof(ULONG) ) { 00536 ObDereferenceObject( Token ); 00537 return( STATUS_INFO_LENGTH_MISMATCH ); 00538 } 00539 00540 try { 00541 00542 SessionId = *(PULONG)TokenInformation; 00543 00544 } except(EXCEPTION_EXECUTE_HANDLER) { 00545 ObDereferenceObject( Token ); 00546 return GetExceptionCode(); 00547 } 00548 00549 // 00550 // We only allow TCB to set SessionId's 00551 // 00552 if ( !SeSinglePrivilegeCheck(SeTcbPrivilege,PreviousMode) ) { 00553 ObDereferenceObject( Token ); 00554 return( STATUS_PRIVILEGE_NOT_HELD ); 00555 } 00556 00557 // 00558 // Set SessionId for the token 00559 // 00560 SeSetSessionIdToken( (PACCESS_TOKEN)Token, 00561 SessionId ); 00562 00563 ObDereferenceObject( Token ); 00564 return( STATUS_SUCCESS ); 00565 } 00566 00567 } //endswitch 00568 00569 ASSERT( TRUE == FALSE ); // Should never reach here. 00570 return( STATUS_INVALID_PARAMETER ); 00571 00572 } 00573 00574 00575 VOID 00576 SepFreePrimaryGroup( 00577 IN PTOKEN Token 00578 ) 00579 00580 /*++ 00581 00582 00583 Routine Description: 00584 00585 Free up the space in the dynamic part of the token take up by the primary 00586 group. 00587 00588 The token is assumed to be locked for write access before calling 00589 this routine. 00590 00591 Arguments: 00592 00593 Token - Pointer to the token. 00594 00595 Return Value: 00596 00597 None. 00598 00599 --*/ 00600 { 00601 PAGED_CODE(); 00602 00603 // 00604 // Add the size of the primary group to the DynamicAvailable field. 00605 // 00606 00607 Token->DynamicAvailable += SeLengthSid( Token->PrimaryGroup ); 00608 00609 // 00610 // If there is a default discretionary ACL, and it is not already at the 00611 // beginning of the dynamic part, move it there (remember to update the 00612 // pointer to it). 00613 // 00614 00615 if (ARGUMENT_PRESENT(Token->DefaultDacl)) { 00616 if (Token->DynamicPart != (PULONG)(Token->DefaultDacl)) { 00617 00618 RtlMoveMemory( 00619 (PVOID)(Token->DynamicPart), 00620 (PVOID)(Token->DefaultDacl), 00621 Token->DefaultDacl->AclSize 00622 ); 00623 00624 Token->DefaultDacl = (PACL)(Token->DynamicPart); 00625 00626 } 00627 } 00628 00629 return; 00630 00631 } 00632 00633 00634 VOID 00635 SepFreeDefaultDacl( 00636 IN PTOKEN Token 00637 ) 00638 00639 /*++ 00640 00641 00642 Routine Description: 00643 00644 Free up the space in the dynamic part of the token take up by the default 00645 discretionary access control list. 00646 00647 The token is assumed to be locked for write access before calling 00648 this routine. 00649 00650 Arguments: 00651 00652 Token - Pointer to the token. 00653 00654 Return Value: 00655 00656 None. 00657 00658 --*/ 00659 { 00660 ULONG PrimaryGroupSize; 00661 00662 PAGED_CODE(); 00663 00664 // 00665 // Add the size of the Default Dacl (if there is one) to the 00666 // DynamicAvailable field. 00667 // 00668 if (ARGUMENT_PRESENT(Token->DefaultDacl)) { 00669 00670 Token->DynamicAvailable += Token->DefaultDacl->AclSize; 00671 Token->DefaultDacl = NULL; 00672 00673 } 00674 00675 // 00676 // If it is not already at the beginning of the dynamic part, move 00677 // the primary group there (remember to update the pointer to it). 00678 // 00679 00680 if (Token->DynamicPart != (PULONG)(Token->PrimaryGroup)) { 00681 00682 PrimaryGroupSize = SeLengthSid( Token->PrimaryGroup ); 00683 00684 RtlMoveMemory( 00685 (PVOID)(Token->DynamicPart), 00686 (PVOID)(Token->PrimaryGroup), 00687 PrimaryGroupSize 00688 ); 00689 00690 Token->PrimaryGroup = (PSID)(Token->DynamicPart); 00691 } 00692 00693 return; 00694 } 00695 00696 VOID 00697 SepAppendPrimaryGroup( 00698 IN PTOKEN Token, 00699 IN PSID PSid 00700 ) 00701 00702 /*++ 00703 00704 00705 Routine Description: 00706 00707 Add a primary group SID to the available space at the end of the dynamic 00708 part of the token. It is the caller's responsibility to ensure that the 00709 primary group SID fits within the available space of the dynamic part of 00710 the token. 00711 00712 The token is assumed to be locked for write access before calling 00713 this routine. 00714 00715 Arguments: 00716 00717 Token - Pointer to the token. 00718 00719 PSid - Pointer to the SID to add. 00720 00721 Return Value: 00722 00723 None. 00724 00725 --*/ 00726 { 00727 ULONG_PTR NextFree; 00728 ULONG SidSize; 00729 00730 PAGED_CODE(); 00731 00732 // 00733 // Add the size of the Default Dacl (if there is one) to the 00734 // address of the Dynamic Part of the token to establish 00735 // where the primary group should be placed. 00736 // 00737 00738 if (ARGUMENT_PRESENT(Token->DefaultDacl)) { 00739 00740 // ASSERT( (ULONG)(Token->DefaultDacl->AclSize) == 00741 // (ULONG)LongAlignSize(Token->DefaultDacl->AclSize) ); 00742 00743 NextFree = (ULONG_PTR)(Token->DynamicPart) + Token->DefaultDacl->AclSize; 00744 00745 } else { 00746 00747 NextFree = (ULONG_PTR)(Token->DynamicPart); 00748 00749 } 00750 00751 // 00752 // Now copy the primary group SID. 00753 // 00754 00755 00756 SidSize = SeLengthSid( PSid ); 00757 00758 RtlCopyMemory( 00759 (PVOID)NextFree, 00760 (PVOID)PSid, 00761 SidSize 00762 ); 00763 00764 Token->PrimaryGroup = (PSID)NextFree; 00765 00766 // 00767 // And decrement the amount of the dynamic part that is available. 00768 // 00769 00770 ASSERT( SidSize <= (Token->DynamicAvailable) ); 00771 Token->DynamicAvailable -= SidSize; 00772 00773 return; 00774 00775 } 00776 00777 VOID 00778 SepAppendDefaultDacl( 00779 IN PTOKEN Token, 00780 IN PACL PAcl 00781 ) 00782 00783 /*++ 00784 00785 00786 Routine Description: 00787 00788 Add a default discretionary ACL to the available space at the end of the 00789 dynamic part of the token. It is the caller's responsibility to ensure 00790 that the default Dacl fits within the available space of the dynamic 00791 part of the token. 00792 00793 The token is assumed to be locked for write access before calling 00794 this routine. 00795 00796 Arguments: 00797 00798 Token - Pointer to the token. 00799 00800 PAcl - Pointer to the ACL to add. 00801 00802 Return Value: 00803 00804 None. 00805 00806 --*/ 00807 { 00808 ULONG_PTR NextFree; 00809 ULONG AclSize; 00810 00811 PAGED_CODE(); 00812 00813 // 00814 // Add the size of the primary group to the 00815 // address of the Dynamic Part of the token to establish 00816 // where the primary group should be placed. 00817 // 00818 00819 ASSERT(ARGUMENT_PRESENT(Token->PrimaryGroup)); 00820 00821 NextFree = (ULONG_PTR)(Token->DynamicPart) + SeLengthSid(Token->PrimaryGroup); 00822 00823 // 00824 // Now copy the default Dacl 00825 // 00826 00827 AclSize = (ULONG)(PAcl->AclSize); 00828 // ASSERT(AclSize == (ULONG)LongAlignSize(AclSize)); 00829 00830 RtlCopyMemory( 00831 (PVOID)NextFree, 00832 (PVOID)PAcl, 00833 AclSize 00834 ); 00835 00836 Token->DefaultDacl = (PACL)NextFree; 00837 00838 // 00839 // And decrement the amount of the dynamic part that is available. 00840 // 00841 00842 ASSERT( AclSize <= (Token->DynamicAvailable) ); 00843 Token->DynamicAvailable -= AclSize; 00844 00845 return; 00846 00847 } 00848 00849 00850 NTSTATUS 00851 SeSetSessionIdToken( 00852 PACCESS_TOKEN Token, 00853 ULONG SessionId 00854 ) 00855 /*++ 00856 00857 00858 Routine Description: 00859 00860 Sets the SessionId for the specified token object. 00861 00862 Arguments: 00863 00864 pOpaqueToken (input) 00865 Opaque kernel Token access pointer 00866 00867 SessionId (input) 00868 SessionId to store in token 00869 00870 Return Value: 00871 00872 STATUS_SUCCESS - no error 00873 00874 --*/ 00875 { 00876 00877 00878 // 00879 // Gain write access to the token. 00880 // 00881 00882 SepAcquireTokenWriteLock( Token ); 00883 00884 ((PTOKEN)Token)->SessionId = SessionId; 00885 00886 SepReleaseTokenWriteLock( Token, TRUE ); 00887 00888 return( STATUS_SUCCESS ); 00889 }

Generated on Sat May 15 19:42:02 2004 for test by doxygen 1.3.7