00444 :
00445
00446 This routine
is used to disable or enable groups in
the specified
00447 token. The absence of some of
the groups listed to be changed
00448 won'
t effect
the successful modification of
the groups that are in
00449
the token. The previous enabled/disabled state of changed groups
00450 may optionally be capture (
for resetting later).
00451
00452 TOKEN_ADJUST_GROUPS access
is required to enable or disable groups
00453 in a token
00454
00455 Note that mandatory groups can not be disabled. An attempt
00456 disable any mandatory groups will cause
the call to fail, leaving
00457
the state of all groups unchanged.
00458
00459
00460 Arguments:
00461
00462 TokenHandle - Provides a handle to
the token to operate on.
00463
00464 ResetToDefault - The parameter indicates whether all
the groups
00465 in
the token are to be reset to their
default enabled/disabled
00466 state.
00467
00468 NewState - This parameter points to a TOKEN_GROUPS data structure
00469 containing
the groups whose states are to be adjusted
00470 (disabled or enabled). Only
the Enabled flag of
the
00471 attributes associated with each group
is used. It provides
00472
the new value that
is to be assigned to
the group in
the
00473 token. If
the ResetToDefault argument
is specified as
TRUE,
00474 then
this argument
is ignored. Otherwise,
it must be passed.
00475
00476 BufferLength - This optional parameter indicates
the length (in
00477 bytes) of
the PreviousState buffer. This value must be
00478 provided
if the PreviousState parameter
is provided.
00479
00480 PreviousState - This (optional) parameter points to a buffer to
00481 receive the state of any groups actually changed by this
00482 request. This information is formated as a TOKEN_GROUPS data
00483 structure which may be passed as the NewState parameter in a
00484 subsequent call to NtAdjustGroups to restore the original state
00485 of those groups. TOKEN_QUERY access is needed to use this
00486 parameter.
00487
00488 If this buffer does not contain enough space to receive the
00489 complete list of modified groups, then no group states are
00490 changed and STATUS_BUFFER_TOO_SMALL is returned. In this
00491 case, the ReturnLength return parameter will contain the
00492 actual number of bytes needed to hold the information.
00493
00494 ReturnLength - Indicates the actual number of bytes needed to
00495 contain the previous group state information.
00496 This parameter is ignored if the PreviousState argument is not
00497 passed.
00498
00499
00500 Return Value:
00501
00502 STATUS_SUCCESS - The service successfully completed the requested
00503 operation.
00504
00505 STATUS_NOT_ALL_ASSIGNED - This NT_SUCCESS severity return status
00506 indicates that not all the specified groups are currently
00507 assigned to the caller. All specified groups that are
00508 currently assigned have been successfully adjusted.
00509
00510 STATUS_CANT_DISABLE_MANDATORY - Indicates an attempt was made to
00511 disable a mandatory group. The states of all groups remains
00512 unchanged.
00513
00514 STATUS_BUFFER_TOO_SMALL - Indicates the optional buffer provided
00515 to receive the previous states of changed group wasn't large
00516 enough to receive that information. No changes to group
00517 states has been made. The number of bytes needed to hold the
00518 state change information is returned via the ReturnLength
00519 parameter.
00520
00521 STATUS_INVALID_PARAMETER - Indicates neither the ResetToDefault
00522 parameter was specified as true, nor was an explicit NewState
00523 provided.
00524
00525 --*/
00526 {
00527
00528
KPROCESSOR_MODE PreviousMode;
00529
NTSTATUS Status;
00530
00531
PTOKEN Token;
00532
00533 ACCESS_MASK DesiredAccess;
00534
00535 ULONG CapturedGroupCount;
00536 PSID_AND_ATTRIBUTES CapturedGroups =
NULL;
00537 ULONG CapturedGroupsLength;
00538
00539 ULONG LocalReturnLength;
00540 ULONG ChangeCount;
00541 BOOLEAN
ChangesMade;
00542 PSID SidBuffer;
00543
00544
PAGED_CODE();
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
if (!ResetToDefault && !ARGUMENT_PRESENT(NewState)) {
00559
return STATUS_INVALID_PARAMETER;
00560 }
00561
00562
00563
00564
00565
00566 PreviousMode = KeGetPreviousMode();
00567
if (PreviousMode !=
KernelMode) {
00568
try {
00569
00570
if (!ResetToDefault) {
00571
ProbeForRead(
00572 NewState,
00573
sizeof(TOKEN_GROUPS),
00574
sizeof(ULONG)
00575 );
00576 }
00577
00578
if (ARGUMENT_PRESENT(PreviousState)) {
00579
00580
ProbeForWrite(
00581 PreviousState,
00582 BufferLength,
00583
sizeof(ULONG)
00584 );
00585
00586
00587
00588
00589
00590
00591
ProbeForWriteUlong(ReturnLength);
00592
00593 }
00594
00595
00596 } except(EXCEPTION_EXECUTE_HANDLER) {
00597
return GetExceptionCode();
00598 }
00599 }
00600
00601
00602
00603
00604
00605
if (!ResetToDefault) {
00606
00607
try {
00608
00609 CapturedGroupCount = NewState->GroupCount;
00610
Status =
SeCaptureSidAndAttributesArray(
00611 &(NewState->Groups[0]),
00612 CapturedGroupCount,
00613 PreviousMode,
00614 NULL, 0,
00615 PagedPool,
00616 TRUE,
00617 &CapturedGroups,
00618 &CapturedGroupsLength
00619 );
00620
00621
if (!
NT_SUCCESS(Status)) {
00622
00623
return Status;
00624
00625 }
00626
00627 } except(EXCEPTION_EXECUTE_HANDLER) {
00628
00629
return GetExceptionCode();
00630
00631 }
00632 }
00633
00634
00635
00636
00637
00638
00639
00640
if (ARGUMENT_PRESENT(PreviousState)) {
00641 DesiredAccess = (TOKEN_ADJUST_GROUPS | TOKEN_QUERY);
00642 }
else {
00643 DesiredAccess = TOKEN_ADJUST_GROUPS;
00644 }
00645
00646
Status =
ObReferenceObjectByHandle(
00647 TokenHandle,
00648 DesiredAccess,
00649 SepTokenObjectType,
00650 PreviousMode,
00651 (PVOID *)&Token,
00652 NULL
00653 );
00654
00655
if ( !
NT_SUCCESS(Status) ) {
00656
00657
if (ARGUMENT_PRESENT(CapturedGroups)) {
00658
SeReleaseSidAndAttributesArray( CapturedGroups, PreviousMode, TRUE );
00659 }
00660
00661
return Status;
00662 }
00663
00664
00665
00666
00667
00668
SepAcquireTokenWriteLock( Token );
00669
00670
00671
00672
00673
00674
00675
00676
00677
Status =
SepAdjustGroups(
00678 Token,
00679 FALSE,
00680 ResetToDefault,
00681 CapturedGroupCount,
00682 CapturedGroups,
00683 PreviousState,
00684 NULL,
00685 &LocalReturnLength,
00686 &ChangeCount,
00687 &ChangesMade
00688 );
00689
00690
if (ARGUMENT_PRESENT(PreviousState)) {
00691
00692
try {
00693
00694 (*ReturnLength) = LocalReturnLength;
00695
00696 } except(EXCEPTION_EXECUTE_HANDLER) {
00697
00698
SepReleaseTokenWriteLock( Token, FALSE );
00699
ObDereferenceObject( Token );
00700
00701
if (ARGUMENT_PRESENT(CapturedGroups)) {
00702
SeReleaseSidAndAttributesArray(
00703 CapturedGroups,
00704 PreviousMode,
00705 TRUE
00706 );
00707 }
00708
00709
return GetExceptionCode();
00710 }
00711 }
00712
00713
00714
00715
00716
00717
if (!
NT_SUCCESS(Status)) {
00718
00719
SepReleaseTokenWriteLock( Token, FALSE );
00720
ObDereferenceObject( Token );
00721
00722
if (ARGUMENT_PRESENT(CapturedGroups)) {
00723
SeReleaseSidAndAttributesArray(
00724 CapturedGroups,
00725 PreviousMode,
00726 TRUE
00727 );
00728 }
00729
00730
return Status;
00731
00732 }
00733
00734
00735
00736
00737
00738
00739
if (ARGUMENT_PRESENT(PreviousState)) {
00740
if (LocalReturnLength > BufferLength) {
00741
00742
SepReleaseTokenWriteLock( Token, FALSE );
00743
ObDereferenceObject( Token );
00744
00745
if (ARGUMENT_PRESENT(CapturedGroups)) {
00746
SeReleaseSidAndAttributesArray(
00747 CapturedGroups,
00748 PreviousMode,
00749 TRUE
00750 );
00751 }
00752
00753
00754
return STATUS_BUFFER_TOO_SMALL;
00755 }
00756
00757
00758
00759
00760
00761
00762 SidBuffer = (PSID)(
LongAlignPtr(
00763 (PCHAR)PreviousState + (ULONG)
sizeof(TOKEN_GROUPS) +
00764 (ChangeCount * (ULONG)
sizeof(SID_AND_ATTRIBUTES)) -
00765 (ANYSIZE_ARRAY * (ULONG)
sizeof(SID_AND_ATTRIBUTES))
00766 ) );
00767
00768 }
00769
00770
00771
00772
00773
00774
try {
00775
00776
Status =
SepAdjustGroups(
00777 Token,
00778 TRUE,
00779 ResetToDefault,
00780 CapturedGroupCount,
00781 CapturedGroups,
00782 PreviousState,
00783 SidBuffer,
00784 &LocalReturnLength,
00785 &ChangeCount,
00786 &ChangesMade
00787 );
00788
00789
if (ARGUMENT_PRESENT(PreviousState)) {
00790
00791 PreviousState->GroupCount = ChangeCount;
00792 }
00793
00794 } except(EXCEPTION_EXECUTE_HANDLER) {
00795
00796
00797
SepReleaseTokenWriteLock( Token, TRUE );
00798
ObDereferenceObject( Token );
00799
if (ARGUMENT_PRESENT(CapturedGroups)) {
00800
SeReleaseSidAndAttributesArray( CapturedGroups, PreviousMode, TRUE );
00801 }
00802
return GetExceptionCode();
00803
00804 }
00805
00806
00807
SepReleaseTokenWriteLock( Token, ChangesMade );
00808
ObDereferenceObject( Token );
00809
00810
if (ARGUMENT_PRESENT(CapturedGroups)) {
00811
SeReleaseSidAndAttributesArray( CapturedGroups, PreviousMode, TRUE );
00812 }
00813
00814
return Status;
00815
00816 }