ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

priv.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:       See COPYING in the top level directory
00003  * PROJECT:         ReactOS kernel
00004  * FILE:            ntoskrnl/se/priv.c
00005  * PURPOSE:         Security manager
00006  *
00007  * PROGRAMMERS:     No programmer listed.
00008  */
00009 
00010 /* INCLUDES ******************************************************************/
00011 
00012 #include <ntoskrnl.h>
00013 #define NDEBUG
00014 #include <debug.h>
00015 
00016 #if defined (ALLOC_PRAGMA)
00017 #pragma alloc_text(INIT, SepInitPrivileges)
00018 #endif
00019 
00020 /* GLOBALS ********************************************************************/
00021 
00022 LUID SeCreateTokenPrivilege;
00023 LUID SeAssignPrimaryTokenPrivilege;
00024 LUID SeLockMemoryPrivilege;
00025 LUID SeIncreaseQuotaPrivilege;
00026 LUID SeUnsolicitedInputPrivilege;
00027 LUID SeTcbPrivilege;
00028 LUID SeSecurityPrivilege;
00029 LUID SeTakeOwnershipPrivilege;
00030 LUID SeLoadDriverPrivilege;
00031 LUID SeCreatePagefilePrivilege;
00032 LUID SeIncreaseBasePriorityPrivilege;
00033 LUID SeSystemProfilePrivilege;
00034 LUID SeSystemtimePrivilege;
00035 LUID SeProfileSingleProcessPrivilege;
00036 LUID SeCreatePermanentPrivilege;
00037 LUID SeBackupPrivilege;
00038 LUID SeRestorePrivilege;
00039 LUID SeShutdownPrivilege;
00040 LUID SeDebugPrivilege;
00041 LUID SeAuditPrivilege;
00042 LUID SeSystemEnvironmentPrivilege;
00043 LUID SeChangeNotifyPrivilege;
00044 LUID SeRemoteShutdownPrivilege;
00045 LUID SeUndockPrivilege;
00046 LUID SeSyncAgentPrivilege;
00047 LUID SeEnableDelegationPrivilege;
00048 
00049 /* PRIVATE FUNCTIONS **********************************************************/
00050 
00051 VOID
00052 INIT_FUNCTION
00053 NTAPI
00054 SepInitPrivileges(VOID)
00055 {
00056     SeCreateTokenPrivilege.LowPart = SE_CREATE_TOKEN_PRIVILEGE;
00057     SeCreateTokenPrivilege.HighPart = 0;
00058     SeAssignPrimaryTokenPrivilege.LowPart = SE_ASSIGNPRIMARYTOKEN_PRIVILEGE;
00059     SeAssignPrimaryTokenPrivilege.HighPart = 0;
00060     SeLockMemoryPrivilege.LowPart = SE_LOCK_MEMORY_PRIVILEGE;
00061     SeLockMemoryPrivilege.HighPart = 0;
00062     SeIncreaseQuotaPrivilege.LowPart = SE_INCREASE_QUOTA_PRIVILEGE;
00063     SeIncreaseQuotaPrivilege.HighPart = 0;
00064     SeUnsolicitedInputPrivilege.LowPart = SE_UNSOLICITED_INPUT_PRIVILEGE;
00065     SeUnsolicitedInputPrivilege.HighPart = 0;
00066     SeTcbPrivilege.LowPart = SE_TCB_PRIVILEGE;
00067     SeTcbPrivilege.HighPart = 0;
00068     SeSecurityPrivilege.LowPart = SE_SECURITY_PRIVILEGE;
00069     SeSecurityPrivilege.HighPart = 0;
00070     SeTakeOwnershipPrivilege.LowPart = SE_TAKE_OWNERSHIP_PRIVILEGE;
00071     SeTakeOwnershipPrivilege.HighPart = 0;
00072     SeLoadDriverPrivilege.LowPart = SE_LOAD_DRIVER_PRIVILEGE;
00073     SeLoadDriverPrivilege.HighPart = 0;
00074     SeSystemProfilePrivilege.LowPart = SE_SYSTEM_PROFILE_PRIVILEGE;
00075     SeSystemProfilePrivilege.HighPart = 0;
00076     SeSystemtimePrivilege.LowPart = SE_SYSTEMTIME_PRIVILEGE;
00077     SeSystemtimePrivilege.HighPart = 0;
00078     SeProfileSingleProcessPrivilege.LowPart = SE_PROF_SINGLE_PROCESS_PRIVILEGE;
00079     SeProfileSingleProcessPrivilege.HighPart = 0;
00080     SeIncreaseBasePriorityPrivilege.LowPart = SE_INC_BASE_PRIORITY_PRIVILEGE;
00081     SeIncreaseBasePriorityPrivilege.HighPart = 0;
00082     SeCreatePagefilePrivilege.LowPart = SE_CREATE_PAGEFILE_PRIVILEGE;
00083     SeCreatePagefilePrivilege.HighPart = 0;
00084     SeCreatePermanentPrivilege.LowPart = SE_CREATE_PERMANENT_PRIVILEGE;
00085     SeCreatePermanentPrivilege.HighPart = 0;
00086     SeBackupPrivilege.LowPart = SE_BACKUP_PRIVILEGE;
00087     SeBackupPrivilege.HighPart = 0;
00088     SeRestorePrivilege.LowPart = SE_RESTORE_PRIVILEGE;
00089     SeRestorePrivilege.HighPart = 0;
00090     SeShutdownPrivilege.LowPart = SE_SHUTDOWN_PRIVILEGE;
00091     SeShutdownPrivilege.HighPart = 0;
00092     SeDebugPrivilege.LowPart = SE_DEBUG_PRIVILEGE;
00093     SeDebugPrivilege.HighPart = 0;
00094     SeAuditPrivilege.LowPart = SE_AUDIT_PRIVILEGE;
00095     SeAuditPrivilege.HighPart = 0;
00096     SeSystemEnvironmentPrivilege.LowPart = SE_SYSTEM_ENVIRONMENT_PRIVILEGE;
00097     SeSystemEnvironmentPrivilege.HighPart = 0;
00098     SeChangeNotifyPrivilege.LowPart = SE_CHANGE_NOTIFY_PRIVILEGE;
00099     SeChangeNotifyPrivilege.HighPart = 0;
00100     SeRemoteShutdownPrivilege.LowPart = SE_REMOTE_SHUTDOWN_PRIVILEGE;
00101     SeRemoteShutdownPrivilege.HighPart = 0;
00102     SeUndockPrivilege.LowPart = SE_UNDOCK_PRIVILEGE;
00103     SeUndockPrivilege.HighPart = 0;
00104     SeSyncAgentPrivilege.LowPart = SE_SYNC_AGENT_PRIVILEGE;
00105     SeSyncAgentPrivilege.HighPart = 0;
00106     SeEnableDelegationPrivilege.LowPart = SE_ENABLE_DELEGATION_PRIVILEGE;
00107     SeEnableDelegationPrivilege.HighPart = 0;
00108 }
00109 
00110 
00111 BOOLEAN
00112 NTAPI
00113 SepPrivilegeCheck(PTOKEN Token,
00114                   PLUID_AND_ATTRIBUTES Privileges,
00115                   ULONG PrivilegeCount,
00116                   ULONG PrivilegeControl,
00117                   KPROCESSOR_MODE PreviousMode)
00118 {
00119     ULONG i;
00120     ULONG j;
00121     ULONG Required;
00122 
00123     DPRINT("SepPrivilegeCheck() called\n");
00124 
00125     PAGED_CODE();
00126 
00127     if (PreviousMode == KernelMode)
00128         return TRUE;
00129 
00130     /* Get the number of privileges that are required to match */
00131     Required = (PrivilegeControl & PRIVILEGE_SET_ALL_NECESSARY) ? PrivilegeCount : 1;
00132 
00133     /* Loop all requested privileges until we found the required ones */
00134     for (i = 0; i < PrivilegeCount && Required > 0; i++)
00135     {
00136         /* Loop the privileges of the token */
00137         for (j = 0; j < Token->PrivilegeCount; j++)
00138         {
00139             /* Check if the LUIDs match */
00140             if (Token->Privileges[j].Luid.LowPart == Privileges[i].Luid.LowPart &&
00141                 Token->Privileges[j].Luid.HighPart == Privileges[i].Luid.HighPart)
00142             {
00143                 DPRINT("Found privilege. Attributes: %lx\n",
00144                        Token->Privileges[j].Attributes);
00145 
00146                 /* Check if the privilege is enabled */
00147                 if (Token->Privileges[j].Attributes & SE_PRIVILEGE_ENABLED)
00148                 {
00149                     Privileges[i].Attributes |= SE_PRIVILEGE_USED_FOR_ACCESS;
00150                     Required--;
00151                 }
00152 
00153                 /* Leave the inner loop */
00154                 break;
00155             }
00156         }
00157     }
00158 
00159     /* Return whether we found all required privileges */
00160     return (Required == 0);
00161 }
00162 
00163 NTSTATUS
00164 NTAPI
00165 SeCaptureLuidAndAttributesArray(PLUID_AND_ATTRIBUTES Src,
00166                                 ULONG PrivilegeCount,
00167                                 KPROCESSOR_MODE PreviousMode,
00168                                 PLUID_AND_ATTRIBUTES AllocatedMem,
00169                                 ULONG AllocatedLength,
00170                                 POOL_TYPE PoolType,
00171                                 BOOLEAN CaptureIfKernel,
00172                                 PLUID_AND_ATTRIBUTES *Dest,
00173                                 PULONG Length)
00174 {
00175     ULONG BufferSize;
00176     NTSTATUS Status = STATUS_SUCCESS;
00177 
00178     PAGED_CODE();
00179 
00180     if (PrivilegeCount == 0)
00181     {
00182         *Dest = 0;
00183         *Length = 0;
00184         return STATUS_SUCCESS;
00185     }
00186 
00187     if (PreviousMode == KernelMode && !CaptureIfKernel)
00188     {
00189         *Dest = Src;
00190         return STATUS_SUCCESS;
00191     }
00192 
00193     /* FIXME - check PrivilegeCount for a valid number so we don't
00194      cause an integer overflow or exhaust system resources! */
00195 
00196     BufferSize = PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
00197     *Length = ROUND_UP(BufferSize, 4); /* round up to a 4 byte alignment */
00198 
00199     /* probe the buffer */
00200     if (PreviousMode != KernelMode)
00201     {
00202         _SEH2_TRY
00203         {
00204             ProbeForRead(Src,
00205                          BufferSize,
00206                          sizeof(ULONG));
00207         }
00208         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00209         {
00210             /* Return the exception code */
00211             _SEH2_YIELD(return _SEH2_GetExceptionCode());
00212         }
00213         _SEH2_END;
00214     }
00215 
00216     /* allocate enough memory or check if the provided buffer is
00217      large enough to hold the array */
00218     if (AllocatedMem != NULL)
00219     {
00220         if (AllocatedLength < BufferSize)
00221         {
00222             return STATUS_BUFFER_TOO_SMALL;
00223         }
00224 
00225         *Dest = AllocatedMem;
00226     }
00227     else
00228     {
00229         *Dest = ExAllocatePool(PoolType,
00230                                BufferSize);
00231         if (*Dest == NULL)
00232         {
00233             return STATUS_INSUFFICIENT_RESOURCES;
00234         }
00235     }
00236     
00237     /* copy the array to the buffer */
00238     _SEH2_TRY
00239     {
00240         RtlCopyMemory(*Dest,
00241                       Src,
00242                       BufferSize);
00243     }
00244     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00245     {
00246         Status = _SEH2_GetExceptionCode();
00247     }
00248     _SEH2_END;
00249 
00250     if (!NT_SUCCESS(Status) && AllocatedMem == NULL)
00251     {
00252         ExFreePool(*Dest);
00253     }
00254 
00255     return Status;
00256 }
00257 
00258 VOID
00259 NTAPI
00260 SeReleaseLuidAndAttributesArray(PLUID_AND_ATTRIBUTES Privilege,
00261                                 KPROCESSOR_MODE PreviousMode,
00262                                 BOOLEAN CaptureIfKernel)
00263 {
00264     PAGED_CODE();
00265 
00266     if (Privilege != NULL &&
00267         (PreviousMode != KernelMode || CaptureIfKernel))
00268     {
00269         ExFreePool(Privilege);
00270     }
00271 }
00272 
00273 /* PUBLIC FUNCTIONS ***********************************************************/
00274 
00275 /*
00276  * @implemented
00277  */
00278 NTSTATUS
00279 NTAPI
00280 SeAppendPrivileges(IN OUT PACCESS_STATE AccessState,
00281                    IN PPRIVILEGE_SET Privileges)
00282 {
00283     PAUX_ACCESS_DATA AuxData;
00284     ULONG OldPrivilegeSetSize;
00285     ULONG NewPrivilegeSetSize;
00286     PPRIVILEGE_SET PrivilegeSet;
00287 
00288     PAGED_CODE();
00289 
00290     /* Get the Auxiliary Data */
00291     AuxData = AccessState->AuxData;
00292 
00293     /* Calculate the size of the old privilege set */
00294     OldPrivilegeSetSize = sizeof(PRIVILEGE_SET) +
00295                           (AuxData->PrivilegeSet->PrivilegeCount - 1) * sizeof(LUID_AND_ATTRIBUTES);
00296 
00297     if (AuxData->PrivilegeSet->PrivilegeCount +
00298         Privileges->PrivilegeCount > INITIAL_PRIVILEGE_COUNT)
00299     {
00300         /* Calculate the size of the new privilege set */
00301         NewPrivilegeSetSize = OldPrivilegeSetSize +
00302                               Privileges->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
00303 
00304         /* Allocate a new privilege set */
00305         PrivilegeSet = ExAllocatePool(PagedPool, NewPrivilegeSetSize);
00306         if (PrivilegeSet == NULL)
00307             return STATUS_INSUFFICIENT_RESOURCES;
00308 
00309         /* Copy original privileges from the acess state */
00310         RtlCopyMemory(PrivilegeSet,
00311                       AuxData->PrivilegeSet,
00312                       OldPrivilegeSetSize);
00313 
00314         /* Append privileges from the privilege set*/
00315         RtlCopyMemory((PVOID)((ULONG_PTR)PrivilegeSet + OldPrivilegeSetSize),
00316                       (PVOID)((ULONG_PTR)Privileges + sizeof(PRIVILEGE_SET) - sizeof(LUID_AND_ATTRIBUTES)),
00317                       Privileges->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
00318 
00319         /* Adjust the number of privileges in the new privilege set */
00320         PrivilegeSet->PrivilegeCount += Privileges->PrivilegeCount;
00321 
00322         /* Free the old privilege set if it was allocated */
00323         if (AccessState->PrivilegesAllocated == TRUE)
00324             ExFreePool(AuxData->PrivilegeSet);
00325 
00326         /* Now we are using an allocated privilege set */
00327         AccessState->PrivilegesAllocated = TRUE;
00328 
00329         /* Assign the new privileges to the access state */
00330         AuxData->PrivilegeSet = PrivilegeSet;
00331     }
00332     else
00333     {
00334         /* Append privileges */
00335         RtlCopyMemory((PVOID)((ULONG_PTR)AuxData->PrivilegeSet + OldPrivilegeSetSize),
00336                       (PVOID)((ULONG_PTR)Privileges + sizeof(PRIVILEGE_SET) - sizeof(LUID_AND_ATTRIBUTES)),
00337                       Privileges->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
00338 
00339         /* Adjust the number of privileges in the target privilege set */
00340         AuxData->PrivilegeSet->PrivilegeCount += Privileges->PrivilegeCount;
00341     }
00342 
00343     return STATUS_SUCCESS;
00344 }
00345 
00346 /*
00347  * @implemented
00348  */
00349 VOID
00350 NTAPI
00351 SeFreePrivileges(IN PPRIVILEGE_SET Privileges)
00352 {
00353     PAGED_CODE();
00354     ExFreePool(Privileges);
00355 }
00356 
00357 /*
00358  * @implemented
00359  */
00360 BOOLEAN
00361 NTAPI
00362 SePrivilegeCheck(PPRIVILEGE_SET Privileges,
00363                  PSECURITY_SUBJECT_CONTEXT SubjectContext,
00364                  KPROCESSOR_MODE PreviousMode)
00365 {
00366     PACCESS_TOKEN Token = NULL;
00367 
00368     PAGED_CODE();
00369 
00370     if (SubjectContext->ClientToken == NULL)
00371     {
00372         Token = SubjectContext->PrimaryToken;
00373     }
00374     else
00375     {
00376         Token = SubjectContext->ClientToken;
00377         if (SubjectContext->ImpersonationLevel < 2)
00378         {
00379             return FALSE;
00380         }
00381     }
00382 
00383     return SepPrivilegeCheck(Token,
00384                              Privileges->Privilege,
00385                              Privileges->PrivilegeCount,
00386                              Privileges->Control,
00387                              PreviousMode);
00388 }
00389 
00390 /*
00391  * @implemented
00392  */
00393 BOOLEAN
00394 NTAPI
00395 SeSinglePrivilegeCheck(IN LUID PrivilegeValue,
00396                        IN KPROCESSOR_MODE PreviousMode)
00397 {
00398     SECURITY_SUBJECT_CONTEXT SubjectContext;
00399     PRIVILEGE_SET Priv;
00400     BOOLEAN Result;
00401 
00402     PAGED_CODE();
00403 
00404     SeCaptureSubjectContext(&SubjectContext);
00405 
00406     Priv.PrivilegeCount = 1;
00407     Priv.Control = PRIVILEGE_SET_ALL_NECESSARY;
00408     Priv.Privilege[0].Luid = PrivilegeValue;
00409     Priv.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
00410 
00411     Result = SePrivilegeCheck(&Priv,
00412                               &SubjectContext,
00413                               PreviousMode);
00414 
00415     if (PreviousMode != KernelMode)
00416     {
00417 #if 0
00418         SePrivilegedServiceAuditAlarm(0,
00419                                       &SubjectContext,
00420                                       &PrivilegeValue);
00421 #endif
00422     }
00423 
00424     SeReleaseSubjectContext(&SubjectContext);
00425 
00426     return Result;
00427 }
00428 
00429 BOOLEAN
00430 NTAPI
00431 SeCheckPrivilegedObject(IN LUID PrivilegeValue,
00432                         IN HANDLE ObjectHandle,
00433                         IN ACCESS_MASK DesiredAccess,
00434                         IN KPROCESSOR_MODE PreviousMode)
00435 {
00436     SECURITY_SUBJECT_CONTEXT SubjectContext;
00437     PRIVILEGE_SET Priv;
00438     BOOLEAN Result;
00439 
00440     PAGED_CODE();
00441 
00442     SeCaptureSubjectContext(&SubjectContext);
00443 
00444     Priv.PrivilegeCount = 1;
00445     Priv.Control = PRIVILEGE_SET_ALL_NECESSARY;
00446     Priv.Privilege[0].Luid = PrivilegeValue;
00447     Priv.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
00448 
00449     Result = SePrivilegeCheck(&Priv, &SubjectContext, PreviousMode);
00450     if (PreviousMode != KernelMode)
00451     {
00452 #if 0
00453         SePrivilegeObjectAuditAlarm(ObjectHandle,
00454                                     &SubjectContext,
00455                                     DesiredAccess,
00456                                     &PrivilegeValue,
00457                                     Result,
00458                                     PreviousMode);
00459 #endif
00460     }
00461 
00462     SeReleaseSubjectContext(&SubjectContext);
00463 
00464     return Result;
00465 }
00466 
00467 /* SYSTEM CALLS ***************************************************************/
00468 
00469 NTSTATUS
00470 NTAPI
00471 NtPrivilegeCheck(IN HANDLE ClientToken,
00472                  IN PPRIVILEGE_SET RequiredPrivileges,
00473                  OUT PBOOLEAN Result)
00474 {
00475     PLUID_AND_ATTRIBUTES Privileges;
00476     PTOKEN Token;
00477     ULONG PrivilegeCount = 0;
00478     ULONG PrivilegeControl = 0;
00479     ULONG Length;
00480     BOOLEAN CheckResult;
00481     KPROCESSOR_MODE PreviousMode;
00482     NTSTATUS Status;
00483 
00484     PAGED_CODE();
00485 
00486     PreviousMode = KeGetPreviousMode();
00487 
00488     /* probe the buffers */
00489     if (PreviousMode != KernelMode)
00490     {
00491         _SEH2_TRY
00492         {
00493             ProbeForWrite(RequiredPrivileges,
00494                           FIELD_OFFSET(PRIVILEGE_SET,
00495                                        Privilege),
00496                           sizeof(ULONG));
00497 
00498             PrivilegeCount = RequiredPrivileges->PrivilegeCount;
00499             PrivilegeControl = RequiredPrivileges->Control;
00500 
00501             /* Check PrivilegeCount to avoid an integer overflow! */
00502             if (FIELD_OFFSET(PRIVILEGE_SET,
00503                              Privilege[PrivilegeCount]) /
00504                 sizeof(RequiredPrivileges->Privilege[0]) != PrivilegeCount)
00505             {
00506                 _SEH2_YIELD(return STATUS_INVALID_PARAMETER);
00507             }
00508 
00509             /* probe all of the array */
00510             ProbeForWrite(RequiredPrivileges,
00511                           FIELD_OFFSET(PRIVILEGE_SET,
00512                                        Privilege[PrivilegeCount]),
00513                           sizeof(ULONG));
00514 
00515             ProbeForWriteBoolean(Result);
00516         }
00517         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00518         {
00519             /* Return the exception code */
00520             _SEH2_YIELD(return _SEH2_GetExceptionCode());
00521         }
00522         _SEH2_END;
00523     }
00524     else
00525     {
00526         PrivilegeCount = RequiredPrivileges->PrivilegeCount;
00527         PrivilegeControl = RequiredPrivileges->Control;
00528     }
00529 
00530     /* reference the token and make sure we're
00531      not doing an anonymous impersonation */
00532     Status = ObReferenceObjectByHandle(ClientToken,
00533                                        TOKEN_QUERY,
00534                                        SeTokenObjectType,
00535                                        PreviousMode,
00536                                        (PVOID*)&Token,
00537                                        NULL);
00538     if (!NT_SUCCESS(Status))
00539     {
00540         return Status;
00541     }
00542 
00543     if (Token->TokenType == TokenImpersonation &&
00544         Token->ImpersonationLevel < SecurityIdentification)
00545     {
00546         ObDereferenceObject(Token);
00547         return STATUS_BAD_IMPERSONATION_LEVEL;
00548     }
00549 
00550     /* capture the privileges */
00551     Status = SeCaptureLuidAndAttributesArray(RequiredPrivileges->Privilege,
00552                                              PrivilegeCount,
00553                                              PreviousMode,
00554                                              NULL,
00555                                              0,
00556                                              PagedPool,
00557                                              TRUE,
00558                                              &Privileges,
00559                                              &Length);
00560     if (!NT_SUCCESS(Status))
00561     {
00562         ObDereferenceObject (Token);
00563         return Status;
00564     }
00565 
00566     CheckResult = SepPrivilegeCheck(Token,
00567                                     Privileges,
00568                                     PrivilegeCount,
00569                                     PrivilegeControl,
00570                                     PreviousMode);
00571 
00572     ObDereferenceObject(Token);
00573 
00574     /* return the array */
00575     _SEH2_TRY
00576     {
00577         RtlCopyMemory(RequiredPrivileges->Privilege,
00578                       Privileges,
00579                       PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES));
00580         *Result = CheckResult;
00581         Status = STATUS_SUCCESS;
00582     }
00583     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00584     {
00585         Status = _SEH2_GetExceptionCode();
00586     }
00587     _SEH2_END;
00588 
00589     SeReleaseLuidAndAttributesArray(Privileges,
00590                                     PreviousMode,
00591                                     TRUE);
00592 
00593     return Status;
00594 }
00595 
00596 /* EOF */

Generated on Fri May 25 2012 04:36:06 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.