几个函数

    技术2022-05-11  89

    /*++

    Copyright (c) 1991  Microsoft Corporation

    Module Name:

        security.c

    Abstract:

        This module implements Object Security APIs for Win32

    Author:

        Jim Anderson (JimA) 01-Jul-1991    Robert Reichel (RobertRe) 01-Jan-92

    Revision History:

    --*/

    #include "advapi.h"#include <ntlsa.h>#include <rpc.h>#include <rpcndr.h>#include <stdio.h>

    #define LSADEFINED

    ///                                                                         ////               Private Routine Prototypes                                ////                                                                         ///

    VOIDSepFormatAccountSid(    PSID iSid,    LPWSTR OutputBuffer    );

    ///                                                                         ////               Exported Routines                                         ////                                                                         ///

     

    BOOLAPIENTRYDuplicateToken(    HANDLE ExistingTokenHandle,    SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,    PHANDLE DuplicateTokenHandle    )

    /*++

    Routine Description:

        Create a new token that is a duplicate of an existing token.  The    new token will be an impersonation token of the supplied level.

    Arguments:

        ExistingTokenHandle - Is a handle to a token already open for        TOKEN_DUPLICATE access.

        ImpersonationLevel - Supplies the impersonation level of the new        token.

        DuplicateTokenHandle - Returns the handle to the new token.  The        handle will have TOKEN_IMPERSONATE and TOKEN_QUERY access to        the new token.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/

    {    return( DuplicateTokenEx( ExistingTokenHandle,                              TOKEN_IMPERSONATE | TOKEN_QUERY,                              NULL,                              ImpersonationLevel,                              TokenImpersonation,                              DuplicateTokenHandle                              ) );

    }

    BOOLDuplicateTokenEx(    HANDLE hExistingToken,    DWORD dwDesiredAccess,    LPSECURITY_ATTRIBUTES lpTokenAttributes,    SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,    TOKEN_TYPE TokenType,    PHANDLE phNewToken)/*++

        Routine Description:

        Create a new token that is a duplicate of an existing token.  This API    more fully exposes NtDuplicateToken .

        Arguments:

            hExistingToken - Is a handle to a token already open for                                        TOKEN_DUPLICATE access.

            dwDesiredAccess - desired access rights to the new token, e.g.                                       TOKEN_DUPLICATE, TOKEN_IMPERSONATE, etc.

            lpTokenAttributes - Desired security attributes for the new token.

            ImpersonationLevel - Supplies the impersonation level of the new token.

            TokenType - One of TokenImpersonation or TokenPrimary.

            phNewToken  - Returns the handle to the new token.

        Return Value:

            Returns TRUE for success, FALSE for failure.  Extended error status        is available using GetLastError.

    --*/

    {

        OBJECT_ATTRIBUTES ObjA;    SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;    PSECURITY_DESCRIPTOR SecurityDescriptor;    NTSTATUS Status;    ULONG Attributes;

        SecurityQualityOfService.Length = sizeof( SECURITY_QUALITY_OF_SERVICE  );    SecurityQualityOfService.ImpersonationLevel = ImpersonationLevel;    SecurityQualityOfService.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;    SecurityQualityOfService.EffectiveOnly = FALSE;

        if (lpTokenAttributes)    {        SecurityDescriptor = lpTokenAttributes->lpSecurityDescriptor;        if (lpTokenAttributes->bInheritHandle)        {            Attributes = OBJ_INHERIT;        }        else        {            Attributes = 0;        }    }    else    {        SecurityDescriptor = NULL;        Attributes = 0;    }

        InitializeObjectAttributes(        &ObjA,        NULL,        Attributes,        NULL,        SecurityDescriptor        );

        ObjA.SecurityQualityOfService = &SecurityQualityOfService;

        Status = NtDuplicateToken(                 hExistingToken,                 dwDesiredAccess,                 &ObjA,                 FALSE,                 TokenType,                 phNewToken                 );

        if ( !NT_SUCCESS( Status ) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return( TRUE );

    }

     

     

    BOOLAPIENTRYAllocateLocallyUniqueId(    PLUID Luid    )/*++

    Routine Description:

        Allocates a locally unique ID (LUID).

    Arguments:

        Luid - Supplies a pointer used to return the LUID.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/

    {   NTSTATUS Status;

        Status = NtAllocateLocallyUniqueId( Luid );    if ( !NT_SUCCESS( Status )) {        BaseSetLastNTError( Status );        return( FALSE );    }

        return( TRUE );}

     

    BOOLAPIENTRYAccessCheck (    PSECURITY_DESCRIPTOR pSecurityDescriptor,    HANDLE ClientToken,    DWORD DesiredAccess,    PGENERIC_MAPPING GenericMapping,    PPRIVILEGE_SET PrivilegeSet,    LPDWORD PrivilegeSetLength,    LPDWORD GrantedAccess,    LPBOOL AccessStatus    )/*++

    Routine Description:

        This routine compares the input Security Descriptor against the    input token and indicates by its return value if access is granted    or denied.  If access is granted then the desired access mask    becomes the granted access mask for the object.

        The semantics of the access check routine is described in the DSA    Security Architecture workbook.  Note that during an access check    only the discretionary ACL is examined.

    Arguments:

        SecurityDescriptor - Supplies the security descriptor protecting the object        being accessed

        ClientToken - Supplies the handle of the user's token.

        DesiredAccess - Supplies the desired access mask.

        GenericMapping - Supplies the generic mapping associated with this        object type.

        PrivilegeSet - A pointer to a buffer that upon return will contain        any privileges that were used to perform the access validation.        If no privileges were used, the buffer will contain a privilege        set consisting of zero privileges.

        PrivilegeSetLength - The size of the PrivilegeSet buffer in bytes.

        GrantedAccess - Returns an access mask describing the granted access.

        AccessStatus - Status value that may be returned indicating the         reason why access was denied.  Routines should avoid hardcoding a         return value of STATUS_ACCESS_DENIED so that a different value can         be returned when mandatory access control is implemented.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;    NTSTATUS RealStatus;

        Status = NtAccessCheck (                pSecurityDescriptor,                ClientToken,                DesiredAccess,                GenericMapping,                PrivilegeSet,                PrivilegeSetLength,                GrantedAccess,                &RealStatus                );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        if ( !NT_SUCCESS( RealStatus ) ) {        BaseSetLastNTError( RealStatus );        *AccessStatus = FALSE;        return( TRUE );    }

        *AccessStatus = TRUE;    return TRUE;}

     

    BOOLAPIENTRYOpenProcessToken (    HANDLE ProcessHandle,    DWORD DesiredAccess,    PHANDLE TokenHandle    )/*++

    Routine Description:

        Open a token object associated with a process and return a handle    that may be used to access that token.

    Arguments:

        ProcessHandle - Specifies the process whose token is to be        opened.

        DesiredAccess - Is an access mask indicating which access types        are desired to the token.  These access types are reconciled        with the Discretionary Access Control list of the token to        determine whether the accesses will be granted or denied.

        TokenHandle - Receives the handle of the newly opened token.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;

        Status = NtOpenProcessToken (        ProcessHandle,        DesiredAccess,        TokenHandle        );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

     

    BOOLAPIENTRYOpenThreadToken (    HANDLE ThreadHandle,    DWORD DesiredAccess,    BOOL OpenAsSelf,    PHANDLE TokenHandle    )/*++

    Routine Description:

    Open a token object associated with a thread and return a handle thatmay be used to access that token.

    Arguments:

        ThreadHandle - Specifies the thread whose token is to be opened.

        DesiredAccess - Is an access mask indicating which access types        are desired to the token.  These access types are reconciled        with the Discretionary Access Control list of the token to        determine whether the accesses will be granted or denied.

        OpenAsSelf - Is a boolean value indicating whether the access should        be made using the calling thread's current security context, which        may be that of a client if impersonating, or using the caller's        process-level security context.  A value of FALSE indicates the        caller's current context should be used un-modified.  A value of        TRUE indicates the request should be fulfilled using the process        level security context.

            This parameter is necessary to allow a server process to open        a client's token when the client specified IDENTIFICATION level        impersonation.  In this case, the caller would not be able to        open the client's token using the client's context (because you        can't create executive level objects using IDENTIFICATION level        impersonation).

        TokenHandle - Receives the handle of the newly opened token.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;

        Status = NtOpenThreadToken (        ThreadHandle,        DesiredAccess,        (BOOLEAN)OpenAsSelf,        TokenHandle        );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

    BOOLAPIENTRYGetTokenInformation (    HANDLE TokenHandle,    TOKEN_INFORMATION_CLASS TokenInformationClass,    PVOID TokenInformation,    DWORD TokenInformationLength,    PDWORD ReturnLength    )/*++

    Routine Description:

        Retrieve information about a specified token.

    Arguments:

        TokenHandle - Provides a handle to the token to operate on.

        TokenInformationClass - The token information class about which        to retrieve information.

        TokenInformation - The buffer to receive the requested class of        information.  The buffer must be aligned on at least a        longword boundary.  The actual structures returned are        dependent upon the information class requested, as defined in        the TokenInformationClass parameter description.

            TokenInformation Format By Information Class:

               TokenUser => TOKEN_USER data structure.  TOKEN_QUERY           access is needed to retrieve this information about a           token.

               TokenGroups => TOKEN_GROUPS data structure.  TOKEN_QUERY           access is needed to retrieve this information about a           token.

               TokenPrivileges => TOKEN_PRIVILEGES data structure.           TOKEN_QUERY access is needed to retrieve this information           about a token.

               TokenOwner => TOKEN_OWNER data structure.  TOKEN_QUERY           access is needed to retrieve this information about a           token.

               TokenPrimaryGroup => TOKEN_PRIMARY_GROUP data structure.           TOKEN_QUERY access is needed to retrieve this information           about a token.

               TokenDefaultDacl => TOKEN_DEFAULT_DACL data structure.           TOKEN_QUERY access is needed to retrieve this information           about a token.

               TokenSource => TOKEN_SOURCE data structure.           TOKEN_QUERY_SOURCE access is needed to retrieve this           information about a token.

               TokenType => TOKEN_TYPE data structure.           TOKEN_QUERY access is needed to retrieve this information           about a token.

               TokenStatistics => TOKEN_STATISTICS data structure.           TOKEN_QUERY access is needed to retrieve this           information about a token.

        TokenInformationLength - Indicates the length, in bytes, of the        TokenInformation buffer.

        ReturnLength - This parameter receives the actual length of the        requested information.  If this value is larger than that        provided by the TokenInformationLength parameter, then the        buffer provided to receive the requested information is not        large enough to hold that data and no data is returned.

            If the queried class is TokenDefaultDacl and there is no        default Dacl established for the token, then the return        length will be returned as zero, and no data will be returned.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;

        Status = NtQueryInformationToken (        TokenHandle,        TokenInformationClass,        TokenInformation,        TokenInformationLength,        ReturnLength        );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

     

    BOOLAPIENTRYSetTokenInformation (    HANDLE TokenHandle,    TOKEN_INFORMATION_CLASS TokenInformationClass,    PVOID TokenInformation,    DWORD TokenInformationLength    )/*++

    Routine Description:

        Modify information in a specified token.

    Arguments:

        TokenHandle - Provides a handle to the token to operate on.

        TokenInformationClass - The token information class being set.

        TokenInformation - The buffer containing the new values for the        specified class of information.  The buffer must be aligned        on at least a longword boundary.  The actual structures        provided are dependent upon the information class specified,        as defined in the TokenInformationClass parameter        description.

            TokenInformation Format By Information Class:

               TokenUser => This value is not a valid value for this API.           The User ID may not be replaced.

               TokenGroups => This value is not a valid value for this           API.  The Group IDs may not be replaced.  However, groups           may be enabled and disabled using NtAdjustGroupsToken().

               TokenPrivileges => This value is not a valid value for           this API.  Privilege information may not be replaced.           However, privileges may be explicitly enabled and disabled           using the NtAdjustPrivilegesToken API.

               TokenOwner => TOKEN_OWNER data structure.           TOKEN_ADJUST_DEFAULT access is needed to replace this           information in a token.  The owner values that may be           specified are restricted to the user and group IDs with an           attribute indicating they may be assigned as the owner of           objects.

               TokenPrimaryGroup => TOKEN_PRIMARY_GROUP data structure.           TOKEN_ADJUST_DEFAULT access is needed to replace this           information in a token.  The primary group values that may           be specified are restricted to be one of the group IDs           already in the token.

               TokenDefaultDacl => TOKEN_DEFAULT_DACL data structure.           TOKEN_ADJUST_DEFAULT access is needed to replace this           information in a token.  The ACL provided as a new default           discretionary ACL is not validated for structural           correctness or consistency.

               TokenSource => This value is not a valid value for this           API.  The source name and context handle  may not be           replaced.

               TokenStatistics => This value is not a valid value for this           API.  The statistics of a token are read-only.

        TokenInformationLength - Indicates the length, in bytes, of the        TokenInformation buffer.  This is only the length of the primary        buffer.  All extensions of the primary buffer are self describing.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;

        Status = NtSetInformationToken (        TokenHandle,        TokenInformationClass,        TokenInformation,        TokenInformationLength        );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

     

    BOOLAPIENTRYAdjustTokenPrivileges (    HANDLE TokenHandle,    BOOL DisableAllPrivileges,    PTOKEN_PRIVILEGES NewState,    DWORD BufferLength,    PTOKEN_PRIVILEGES PreviousState,    PDWORD ReturnLength    )/*++

    Routine Description:

        This routine is used to disable or enable privileges in the    specified token.  The absence of some of the privileges listed to    be changed won't effect the successful modification of the    privileges that are in the token.  The previous enabled/disabled    state of changed privileges may optionally be capture (for    resetting later).

        TOKEN_ADJUST_PRIVILEGES access is required to enable or disable    privileges in a token.

    Arguments:

        TokenHandle - Provides a handle to the token to operate on.

        DisableAllPrivileges - This boolean parameter may be        used to disable all privileges assigned to the token.  If        this parameter is specified as TRUE, then the NewState parameter is        ignored.

        NewState - This (optional) parameter points to a TOKEN_PRIVILEGES        data structure containing the privileges whose states are to        be adjusted (disabled or enabled).  Only the Enabled flag of        the attributes associated with each privilege is used.  It        provides the new value that is to be assigned to the privilege        in the token.

        BufferLength - This optional parameter indicates the length (in        bytes) of the PreviousState buffer.  This value must be        provided if the PreviousState parameter is provided.

        PreviousState - This (optional) parameter points to a buffer to        receive the state of any privileges actually changed by this        request.  This information is formated as a TOKEN_PRIVILEGES        data structure which may be passed as the NewState parameter        in a subsequent call to this routine to restore the original        state of those privilges.  TOKEN_QUERY access is needed to use        this parameter.

            If this buffer does not contain enough space to receive the        complete list of modified privileges, then no privilege        states are changed and STATUS_BUFFER_TOO_SMALL is returned.        In this case, the ReturnLength OUT parameter will        contain the actual number of bytes needed to hold the        information.

        ReturnLength - Indicates the actual number of bytes needed to        contain the previous privilege state information.  This        parameter is ignored if the PreviousState argument is not        passed.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;

        Status = NtAdjustPrivilegesToken (        TokenHandle,        (BOOLEAN)DisableAllPrivileges,        NewState,        BufferLength,        PreviousState,        ReturnLength        );

        //    // We need to set last error even for success because that    // is the only way to tell if the api successfully assigned    // all privileges.  That is, STATUS_NOT_ALL_ASSIGNED is a    // Success severity level.    //

        BaseSetLastNTError(Status);

        if ( !NT_SUCCESS(Status) ) {        return FALSE;    }

        return TRUE;}

     

    BOOLAPIENTRYAdjustTokenGroups (    HANDLE TokenHandle,    BOOL ResetToDefault,    PTOKEN_GROUPS NewState,    DWORD BufferLength,    PTOKEN_GROUPS PreviousState,    PDWORD ReturnLength    )/*++

    Routine Description:

        This routine is used to disable or enable groups in the specified    token.  The absence of some of the groups listed to be changed    won't effect the successful modification of the groups that are in    the token.  The previous enabled/disabled state of changed groups    may optionally be capture (for resetting later).

        TOKEN_ADJUST_GROUPS access is required to enable or disable groups    in a token

        Note that mandatory groups can not be disabled.  An attempt    disable any mandatory groups will cause the call to fail, leaving    the state of all groups unchanged.

    Arguments:

        TokenHandle - Provides a handle to the token to operate on.

        ResetToDefault - The parameter indicates whether all the groups        in the token are to be reset to their default enabled/disabled        state.

        NewState - This parameter points to a TOKEN_GROUPS data structure        containing the groups whose states are to be adjusted        (disabled or enabled).  Only the Enabled flag of the        attributes associated with each group is used.  It provides        the new value that is to be assigned to the group in the        token.  If the ResetToDefault argument is specified as TRUE,        then this argument is ignored.  Otherwise, it must be passed.

        BufferLength - This optional parameter indicates the length (in        bytes) of the PreviousState buffer.  This value must be        provided if the PreviousState parameter is provided.

        PreviousState - This (optional) parameter points to a buffer to        receive the state of any groups actually changed by this        request.  This information is formated as a TOKEN_GROUPS data        structure which may be passed as the NewState parameter in a        subsequent call to NtAdjustGroups to restore the original state        of those groups.  TOKEN_QUERY access is needed to use this        parameter.

            If this buffer does not contain enough space to receive the        complete list of modified groups, then no group states are        changed and STATUS_BUFFER_TOO_SMALL is returned.  In this        case, the ReturnLength return parameter will contain the        actual number of bytes needed to hold the information.

        ReturnLength - Indicates the actual number of bytes needed to        contain the previous group state information.        This parameter is ignored if the PreviousState argument is not        passed.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;

        Status = NtAdjustGroupsToken (        TokenHandle,        (BOOLEAN)ResetToDefault,        NewState,        BufferLength,        PreviousState,        ReturnLength        );

        //    // We need to set last error even for success because that    // is the only way to tell if the api successfully assigned    // all groups.  That is, STATUS_NOT_ALL_ASSIGNED is a    // Success severity level.    //

        BaseSetLastNTError(Status);

        if ( !NT_SUCCESS(Status) ) {        return FALSE;    }

        return TRUE;

    }

     

     

    BOOLAPIENTRYPrivilegeCheck (    HANDLE ClientToken,    PPRIVILEGE_SET RequiredPrivileges,    LPBOOL pfResult    )/*++

    Routine Description:

        This routine tests the caller's client's security context to see if it    contains the specified privileges.

        This API requires the caller have SeSecurityPrivilege privilege.    The test for this privilege is always against the primary token of    the calling process, not the impersonation token of the thread.

    Arguments:

        ClientToken - A handle to a token object representing a client        attempting access.  This handle must be obtained from a        communication session layer, such as from an LPC Port or Local        Named Pipe, to prevent possible security policy violations.

        RequiredPrivileges - Points to a set of privileges.  The client's        security context is to be checked to see which of the specified        privileges are present.  The results will be indicated in the        attributes associated with each privilege.  Note that        flags in this parameter indicate whether all the privileges listed        are needed, or any of the privileges.

        pfResult - Receives a boolean flag indicating whether the client        has all the specified privileges or not.  A value of TRUE        indicates the client has all the specified privileges.        Otherwise a value of FALSE is returned.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;    BOOLEAN Result;

        Status = NtPrivilegeCheck (                ClientToken,                RequiredPrivileges,                &Result                );

        *pfResult = Result;

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

     

    BOOLAPIENTRYAccessCheckAndAuditAlarmW(    LPCWSTR SubsystemName,    PVOID HandleId,    LPWSTR ObjectTypeName,    LPWSTR ObjectName,    PSECURITY_DESCRIPTOR SecurityDescriptor,    DWORD DesiredAccess,    PGENERIC_MAPPING GenericMapping,    BOOL ObjectCreation,    LPDWORD GrantedAccess,    LPBOOL AccessStatus,    LPBOOL pfGenerateOnClose    )/*++

    Routine Description:

        This routine compares the input Security Descriptor against the    caller's impersonation token and indicates if access is granted or    denied.  If access is granted then the desired access mask becomes    the granted access mask for the object.  The semantics of the    access check routine is described in the DSA Security Architecture    workbook.

        This routine will also generate any necessary audit messages as a    result of the access attempt.

    Arguments:

        SubsystemName - Supplies a name string identifying the subsystem        calling the routine.

        HandleId - A unique value that will be used to represent the client's        handle to the object.  This value is ignored (and may be re-used)        if the access is denied.

        ObjectTypeName - Supplies the name of the type of the object being        created or accessed.

        ObjectName - Supplies the name of the object being created or accessed.

        SecurityDescriptor - A pointer to the Security Descriptor against which        acccess is to be checked.

        DesiredAccess - The desired acccess mask.  This mask must have been        previously mapped to contain no generic accesses.

        GenericMapping - Supplies a pointer to the generic mapping associated        with this object type.

        ObjectCreation - A boolean flag indicated whether the access will        result in a new object being created if granted.  A value of TRUE        indicates an object will be created, FALSE indicates an existing        object will be opened.

        GrantedAccess - Receives a masking indicating which accesses have been        granted (only valid on success).

        AccessStatus - Receives an indication of the success or failure of the        access check.  If access is granted, STATUS_SUCCESS is returned.        If access is denied, a value appropriate for return to the client        is returned.  This will be STATUS_ACCESS_DENIED or, when mandatory        access controls are implemented, STATUS_OBJECT_NOT_FOUND.

        pfGenerateOnClose - Points to a boolean that is set by the audity        generation routine and must be passed to ObjectCloseAuditAlarm        when the object handle is closed.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;    NTSTATUS RealAccessStatus;    BOOLEAN GenerateOnClose;    UNICODE_STRING Subsystem;    UNICODE_STRING ObjectType;    UNICODE_STRING Object;

        RtlInitUnicodeString(        &Subsystem,        SubsystemName        );

        RtlInitUnicodeString(        &ObjectType,        ObjectTypeName        );

        RtlInitUnicodeString(        &Object,        ObjectName        );

        Status = NtAccessCheckAndAuditAlarm (                &Subsystem,                HandleId,                &ObjectType,                &Object,                SecurityDescriptor,                DesiredAccess,                GenericMapping,                (BOOLEAN)ObjectCreation,                GrantedAccess,                &RealAccessStatus,                &GenerateOnClose                );

        *pfGenerateOnClose = (BOOL)GenerateOnClose;

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        if ( !NT_SUCCESS( RealAccessStatus )) {        *AccessStatus = FALSE;        BaseSetLastNTError( RealAccessStatus );        return( TRUE );    }

        *AccessStatus = TRUE;    return TRUE;}

     

    BOOLAPIENTRYAccessCheckAndAuditAlarmA (    LPCSTR SubsystemName,    PVOID HandleId,    LPSTR ObjectTypeName,    LPSTR ObjectName,    PSECURITY_DESCRIPTOR SecurityDescriptor,    DWORD DesiredAccess,    PGENERIC_MAPPING GenericMapping,    BOOL ObjectCreation,    LPDWORD GrantedAccess,    LPBOOL AccessStatus,    LPBOOL pfGenerateOnClose    )/*++

    Routine Description:

        ANSI Thunk to AccessCheckAndAuditAlarmW

    --*/{    PUNICODE_STRING ObjectNameW;    ANSI_STRING AnsiString;    UNICODE_STRING SubsystemNameW;    UNICODE_STRING ObjectTypeNameW;    NTSTATUS Status;    BOOL RVal;

        ObjectNameW = &NtCurrentTeb()->StaticUnicodeString;

        RtlInitAnsiString(&AnsiString,SubsystemName);    Status = RtlAnsiStringToUnicodeString(&SubsystemNameW,&AnsiString,TRUE);

        if ( !NT_SUCCESS(Status) ) {

            BaseSetLastNTError(Status);        return FALSE;    }

     

        RtlInitAnsiString(&AnsiString,ObjectTypeName);    Status = RtlAnsiStringToUnicodeString(&ObjectTypeNameW,&AnsiString,TRUE);

        if ( !NT_SUCCESS(Status) ) {

            RtlFreeUnicodeString( &SubsystemNameW );

            BaseSetLastNTError(Status);        return FALSE;    }

        //    // Convert the object name string, but don't allocate memory to    // do it, since we've got the space in the TEB available.    //

        RtlInitAnsiString(&AnsiString,ObjectName);    Status = RtlAnsiStringToUnicodeString(ObjectNameW,&AnsiString,FALSE);

        if ( !NT_SUCCESS(Status) ) {

            RtlFreeUnicodeString( &SubsystemNameW );        RtlFreeUnicodeString( &ObjectTypeNameW );

            BaseSetLastNTError(Status);        return FALSE;    }

        RVal =  AccessCheckAndAuditAlarmW (                (LPCWSTR)SubsystemNameW.Buffer,                HandleId,                ObjectTypeNameW.Buffer,                ObjectNameW->Buffer,                SecurityDescriptor,                DesiredAccess,                GenericMapping,                ObjectCreation,                GrantedAccess,                AccessStatus,                pfGenerateOnClose                );

        RtlFreeUnicodeString( &SubsystemNameW );    RtlFreeUnicodeString( &ObjectTypeNameW );

        return( RVal );}

    BOOLAPIENTRYObjectOpenAuditAlarmA (    LPCSTR SubsystemName,    PVOID HandleId,    LPSTR ObjectTypeName,    LPSTR ObjectName,    PSECURITY_DESCRIPTOR pSecurityDescriptor,    HANDLE ClientToken,    DWORD DesiredAccess,    DWORD GrantedAccess,    PPRIVILEGE_SET Privileges OPTIONAL,    BOOL ObjectCreation,    BOOL AccessGranted,    LPBOOL GenerateOnClose    )/*++

    Routine Description:

        ANSI Thunk to ObjectOpenAuditAlarmW

    --*/{    PUNICODE_STRING ObjectNameW;    ANSI_STRING AnsiString;    UNICODE_STRING SubsystemNameW;    UNICODE_STRING ObjectTypeNameW;    NTSTATUS Status;    BOOL RVal;

        ObjectNameW = &NtCurrentTeb()->StaticUnicodeString;

        RtlInitAnsiString(&AnsiString,SubsystemName);    Status = RtlAnsiStringToUnicodeString(&SubsystemNameW,&AnsiString,TRUE);

        if ( !NT_SUCCESS(Status) ) {

            BaseSetLastNTError(Status);        return FALSE;    }

     

        RtlInitAnsiString(&AnsiString,ObjectTypeName);    Status = RtlAnsiStringToUnicodeString(&ObjectTypeNameW,&AnsiString,TRUE);

        if ( !NT_SUCCESS(Status) ) {

            RtlFreeUnicodeString( &SubsystemNameW );

            BaseSetLastNTError(Status);        return FALSE;    }

        //    // Convert the object name string, but don't allocate memory to    // do it, since we've got the space in the TEB available.    //

        RtlInitAnsiString(&AnsiString,ObjectName);    Status = RtlAnsiStringToUnicodeString(ObjectNameW,&AnsiString,FALSE);

        if ( !NT_SUCCESS(Status) ) {

            RtlFreeUnicodeString( &SubsystemNameW );        RtlFreeUnicodeString( &ObjectTypeNameW );

            BaseSetLastNTError(Status);        return FALSE;    }

        RVal = ObjectOpenAuditAlarmW (               (LPCWSTR)SubsystemNameW.Buffer,               HandleId,               ObjectTypeNameW.Buffer,               ObjectNameW->Buffer,               pSecurityDescriptor,               ClientToken,               DesiredAccess,               GrantedAccess,               Privileges,               ObjectCreation,               AccessGranted,               GenerateOnClose               );

        RtlFreeUnicodeString( &SubsystemNameW );    RtlFreeUnicodeString( &ObjectTypeNameW );

        return( RVal );

    }

     

    BOOLAPIENTRYObjectOpenAuditAlarmW (    LPCWSTR SubsystemName,    PVOID HandleId,    LPWSTR ObjectTypeName,    LPWSTR ObjectName,    PSECURITY_DESCRIPTOR pSecurityDescriptor,    HANDLE ClientToken,    DWORD DesiredAccess,    DWORD GrantedAccess,    PPRIVILEGE_SET Privileges OPTIONAL,    BOOL ObjectCreation,    BOOL AccessGranted,    LPBOOL GenerateOnClose    )/*++

        Routine Description:

        This routine is used to generate audit and alarm messages when an    attempt is made to access an existing protected subsystem object or    create a new one.  This routine may result in several messages being    generated and sent to Port objects.  This may result in a significant    latency before returning.  Design of routines that must call this    routine must take this potential latency into account.  This may have    an impact on the approach taken for data structure mutex locking, for    example.

        This routine may not be able to generate a complete audit record    due to memory restrictions.

        This API requires the caller have SeSecurityPrivilege privilege.    The test for this privilege is always against the primary token of    the calling process, not the impersonation token of the thread.

    Arguments:

        SubsystemName - Supplies a name string identifying the        subsystem calling the routine.

        HandleId - A unique value representing the client's handle to the        object.  If the access attempt was not successful (AccessGranted is        FALSE), then this parameter is ignored.

        ObjectTypeName - Supplies the name of the type of object being        accessed.

        ObjectName - Supplies the name of the object the client        accessed or attempted to access.

        pSecurityDescriptor - An optional pointer to the security        descriptor of the object being accessed.

        ClientToken - A handle to a token object representing the client that        requested the operation.  This handle must be obtained from a        communication session layer, such as from an LPC Port or Local        Named Pipe, to prevent possible security policy violations.

        DesiredAccess - The desired access mask.  This mask must have been        previously mapped to contain no generic accesses.

        GrantedAccess - The mask of accesses that were actually granted.

        Privileges - Optionally points to a set of privileges that were        required for the access attempt.  Those privileges that were held        by the subject are marked using the UsedForAccess flag of the        attributes associated with each privilege.

        ObjectCreation - A boolean flag indicating whether the access will        result in a new object being created if granted.  A value of TRUE        indicates an object will be created, FALSE indicates an existing        object will be opened.

        AccessGranted - Indicates whether the requested access was granted or        not.  A value of TRUE indicates the access was granted.  A value of        FALSE indicates the access was not granted.

        GenerateOnClose - Points to a boolean that is set by the audit        generation routine and must be passed to NtCloseObjectAuditAlarm()        when the object handle is closed.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;    UNICODE_STRING Subsystem;    UNICODE_STRING ObjectType;    UNICODE_STRING Object;

        RtlInitUnicodeString(        &Subsystem,        SubsystemName        );

        RtlInitUnicodeString(        &ObjectType,        ObjectTypeName        );

        RtlInitUnicodeString(        &Object,        ObjectName        );

        Status = NtOpenObjectAuditAlarm (                &Subsystem,                &HandleId,                &ObjectType,                &Object,                pSecurityDescriptor,                ClientToken,                DesiredAccess,                GrantedAccess,                Privileges,                (BOOLEAN)ObjectCreation,                (BOOLEAN)AccessGranted,                (PBOOLEAN)GenerateOnClose                );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

     

    BOOLAPIENTRYObjectPrivilegeAuditAlarmA (    LPCSTR SubsystemName,    PVOID HandleId,    HANDLE ClientToken,    DWORD DesiredAccess,    PPRIVILEGE_SET Privileges,    BOOL AccessGranted    )/*++

    Routine Description:

        ANSI Thunk to ObjectPrivilegeAuditAlarmW

    --*/{    PUNICODE_STRING SubsystemNameW;    ANSI_STRING AnsiString;    NTSTATUS Status;    BOOL RVal;

        SubsystemNameW = &NtCurrentTeb()->StaticUnicodeString;

        //    // Convert the object name string, but don't allocate memory to    // do it, since we've got the space in the TEB available.    //

        RtlInitAnsiString(&AnsiString,SubsystemName);    Status = RtlAnsiStringToUnicodeString(SubsystemNameW,&AnsiString,FALSE);

        if ( !NT_SUCCESS(Status) ) {

            BaseSetLastNTError(Status);        return FALSE;    }

        RVal = ObjectPrivilegeAuditAlarmW (                (LPCWSTR)SubsystemNameW->Buffer,                HandleId,                ClientToken,                DesiredAccess,                Privileges,                AccessGranted                );

        return( RVal );}

     

    BOOLAPIENTRYObjectPrivilegeAuditAlarmW (    LPCWSTR SubsystemName,    PVOID HandleId,    HANDLE ClientToken,    DWORD DesiredAccess,    PPRIVILEGE_SET Privileges,    BOOL AccessGranted    )/*++

    Routine Description:

        This routine is used to generate audit and alarm messages when an    attempt is made to perform privileged operations on a protected    subsystem object after the object is already opened.  This routine    may result in several messages being generated and sent to Port    objects.  This may result in a significant latency before    returning.  Design of routines that must call this routine must    take this potential latency into account.  This may have an impact    on the approach taken for data structure mutex locking, for    example.

        This API requires the caller have SeSecurityPrivilege privilege.    The test for this privilege is always against the primary token of    the calling process, allowing the caller to be impersonating a    client during the call with no ill effects.

    Arguments:

        SubsystemName - Supplies a name string identifying the subsystem        calling the routine.

        HandleId - A unique value representing the client's handle to the        object.

        ClientToken - A handle to a token object representing the client that        requested the operation.  This handle must be obtained from a        communication session layer, such as from an LPC Port or Local        Named Pipe, to prevent possible security policy violations.

        DesiredAccess - The desired access mask.  This mask must have been        previously mapped to contain no generic accesses.

        Privileges - The set of privileges required for the requested        operation.  Those privileges that were held by the subject are        marked using the UsedForAccess flag of the attributes        associated with each privilege.

        AccessGranted - Indicates whether the requested access was granted or        not.  A value of TRUE indicates the access was granted.  A value of        FALSE indicates the access was not granted.

    Return value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;    UNICODE_STRING Subsystem;

        RtlInitUnicodeString(        &Subsystem,        SubsystemName        );

        Status = NtPrivilegeObjectAuditAlarm (        &Subsystem,        HandleId,        ClientToken,        DesiredAccess,        Privileges,        (BOOLEAN)AccessGranted        );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

    BOOLAPIENTRYObjectCloseAuditAlarmA (    LPCSTR SubsystemName,    PVOID HandleId,    BOOL GenerateOnClose    )/*++

    Routine Description:

        ANSI Thunk to ObjectCloseAuditAlarmW

    --*/{    PUNICODE_STRING SubsystemNameW;    NTSTATUS Status;    ANSI_STRING AnsiString;

        SubsystemNameW = &NtCurrentTeb()->StaticUnicodeString;

        //    // Convert the object name string, but don't allocate memory to    // do it, since we've got the space in the TEB available.    //

        RtlInitAnsiString(&AnsiString,SubsystemName);    Status = RtlAnsiStringToUnicodeString(SubsystemNameW,&AnsiString,FALSE);

        if ( !NT_SUCCESS(Status) ) {

            BaseSetLastNTError(Status);        return FALSE;    }

        return ObjectCloseAuditAlarmW (               (LPCWSTR)SubsystemNameW->Buffer,               HandleId,               GenerateOnClose               );

    }

    BOOLAPIENTRYObjectCloseAuditAlarmW (    LPCWSTR SubsystemName,    PVOID HandleId,    BOOL GenerateOnClose    )/*++

    Routine Description:

        This routine is used to generate audit and alarm messages when a handle    to a protected subsystem object is deleted.  This routine may result in    several messages being generated and sent to Port objects.  This may    result in a significant latency before returning.  Design of routines    that must call this routine must take this potential latency into    account.  This may have an impact on the approach taken for data    structure mutex locking, for example.

        This API requires the caller have SeSecurityPrivilege privilege.  The test    for this privilege is always against the primary token of the calling    process, allowing the caller to be impersonating a client during the    call with no ill effects.

    Arguments:

        SubsystemName - Supplies a name string identifying the subsystem        calling the routine.

        HandleId - A unique value representing the client's handle to the        object.

        GenerateOnClose - Is a boolean value returned from a corresponding        AccessCheckAndAuditAlarm() call or ObjectOpenAuditAlarm() call        when the object handle was created.

    Return value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;    UNICODE_STRING Subsystem;

        RtlInitUnicodeString( &Subsystem, SubsystemName );

        Status = NtCloseObjectAuditAlarm (        &Subsystem,        HandleId,        (BOOLEAN)GenerateOnClose        );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

    BOOLAPIENTRYObjectDeleteAuditAlarmA (    LPCSTR SubsystemName,    PVOID HandleId,    BOOL GenerateOnClose    )/*++

    Routine Description:

        ANSI Thunk to ObjectDeleteAuditAlarmW

    --*/{    PUNICODE_STRING SubsystemNameW;    NTSTATUS Status;    ANSI_STRING AnsiString;

        SubsystemNameW = &NtCurrentTeb()->StaticUnicodeString;

        //    // Convert the object name string, but don't allocate memory to    // do it, since we've got the space in the TEB available.    //

        RtlInitAnsiString(&AnsiString,SubsystemName);    Status = RtlAnsiStringToUnicodeString(SubsystemNameW,&AnsiString,FALSE);

        if ( !NT_SUCCESS(Status) ) {

            BaseSetLastNTError(Status);        return FALSE;    }

        return ObjectDeleteAuditAlarmW (               (LPCWSTR)SubsystemNameW->Buffer,               HandleId,               GenerateOnClose               );

    }

    BOOLAPIENTRYObjectDeleteAuditAlarmW (    LPCWSTR SubsystemName,    PVOID HandleId,    BOOL GenerateOnClose    )/*++

    Routine Description:

        This routine is used to generate audit and alarm messages when an object    in a protected subsystem is deleted.  This routine may result in    several messages being generated and sent to Port objects.  This may    result in a significant latency before returning.  Design of routines    that must call this routine must take this potential latency into    account.  This may have an impact on the approach taken for data    structure mutex locking, for example.

        This API requires the caller have SeSecurityPrivilege privilege.  The test    for this privilege is always against the primary token of the calling    process, allowing the caller to be impersonating a client during the    call with no ill effects.

    Arguments:

        SubsystemName - Supplies a name string identifying the subsystem        calling the routine.

        HandleId - A unique value representing the client's handle to the        object.

        GenerateOnClose - Is a boolean value returned from a corresponding        AccessCheckAndAuditAlarm() call or ObjectOpenAuditAlarm() call        when the object handle was created.

    Return value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;    UNICODE_STRING Subsystem;

        RtlInitUnicodeString( &Subsystem, SubsystemName );

        Status = NtDeleteObjectAuditAlarm (        &Subsystem,        HandleId,        (BOOLEAN)GenerateOnClose        );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

     

    BOOLAPIENTRYPrivilegedServiceAuditAlarmA (    LPCSTR SubsystemName,    LPCSTR ServiceName,    HANDLE ClientToken,    PPRIVILEGE_SET Privileges,    BOOL AccessGranted    )/*++

    Routine Description:

        ANSI Thunk to PrivilegedServiceAuditAlarmW

    --*/{    PUNICODE_STRING ServiceNameW;    UNICODE_STRING SubsystemNameW;    ANSI_STRING  AnsiString;    NTSTATUS Status;    BOOL RVal;

        ServiceNameW = &NtCurrentTeb()->StaticUnicodeString;

        //    // Convert the object name string, but don't allocate memory to    // do it, since we've got the space in the TEB available.    //

        RtlInitAnsiString(&AnsiString,ServiceName);    Status = RtlAnsiStringToUnicodeString(ServiceNameW,&AnsiString,FALSE);

        if ( !NT_SUCCESS(Status) ) {

            BaseSetLastNTError(Status);        return FALSE;    }

        RtlInitAnsiString(&AnsiString,SubsystemName);    Status = RtlAnsiStringToUnicodeString(&SubsystemNameW,&AnsiString,TRUE);

        if ( !NT_SUCCESS(Status) ) {

            BaseSetLastNTError(Status);        return FALSE;    }

        RVal =  PrivilegedServiceAuditAlarmW (                (LPCWSTR)SubsystemNameW.Buffer,                (LPCWSTR)ServiceNameW->Buffer,                ClientToken,                Privileges,                AccessGranted                );

        RtlFreeUnicodeString( &SubsystemNameW );

        return( RVal );

    }

    BOOLAPIENTRYPrivilegedServiceAuditAlarmW (    LPCWSTR SubsystemName,    LPCWSTR ServiceName,    HANDLE ClientToken,    PPRIVILEGE_SET Privileges,    BOOL AccessGranted    )/*++

    Routine Description:

        This routine is used to generate audit and alarm messages when an    attempt is made to perform privileged system service operations.  This    routine may result in several messages being generated and sent to Port    objects.  This may result in a significant latency before returning.    Design of routines that must call this routine must take this potential    latency into account.  This may have an impact on the approach taken    for data structure mutex locking, for example.

        This API requires the caller have SeSecurityPrivilege privilege.  The test    for this privilege is always against the primary token of the calling    process, allowing the caller to be impersonating a client during the    call with no ill effects

    Arguments:

        SubsystemName - Supplies a name string identifying the subsystem        calling the routine.

        ServiceName - Supplies a name of the privileged subsystem service.  For        example, "RESET RUNTIME LOCAL SECURITY POLICY" might be specified        by a Local Security Authority service used to update the local        security policy database.

        ClientToken - A handle to a token object representing the client that        requested the operation.  This handle must be obtained from a        communication session layer, such as from an LPC Port or Local        Named Pipe, to prevent possible security policy violations.

        Privileges - Points to a set of privileges required to perform the        privileged operation.  Those privileges that were held by the        subject are marked using the UsedForAccess flag of the        attributes associated with each privilege.

        AccessGranted - Indicates whether the requested access was granted or        not.  A value of TRUE indicates the access was granted.  A value of        FALSE indicates the access was not granted.

    Return value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;    UNICODE_STRING Subsystem;    UNICODE_STRING Service;

        RtlInitUnicodeString( &Subsystem, SubsystemName );

        RtlInitUnicodeString( &Service, ServiceName );

        Status = NtPrivilegedServiceAuditAlarm (        &Subsystem,        &Service,        ClientToken,        Privileges,        (BOOLEAN)AccessGranted        );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

     

    BOOLAPIENTRYIsValidSid (    PSID pSid    )/*++

    Routine Description:

        This procedure validates an SID's structure.

    Arguments:

        pSid - Pointer to the SID structure to validate.

    Return Value:

        BOOLEAN - TRUE if the structure of pSid is valid.

    --*/{    return (BOOL) RtlValidSid (                      pSid                      );}

     

    BOOLAPIENTRYEqualSid (    PSID pSid1,    PSID pSid2    )/*++

    Routine Description:

        This procedure tests two SID values for equality.

    Arguments:

        pSid1, pSid2 - Supply pointers to the two SID values to compare.        The SID structures are assumed to be valid.

    Return Value:

        BOOLEAN - TRUE if the value of pSid1 is equal to pSid2, and FALSE        otherwise.

    --*/{    return (BOOL) RtlEqualSid (                    pSid1,                    pSid2                    );}

     

    BOOLAPIENTRYEqualPrefixSid (    PSID pSid1,    PSID pSid2    )/*++

    Routine Description:

        This procedure tests two SID prefix values for equality.

        An SID prefix is the entire SID except for the last sub-authority    value.

    Arguments:

        pSid1, pSid2 - Supply pointers to the two SID values to compare.        The SID structures are assumed to be valid.

    Return Value:

        BOOLEAN - TRUE if the prefix value of pSid1 is equal to pSid2, and        FALSE otherwise.

    --*/{    return (BOOL) RtlEqualPrefixSid (                    pSid1,                    pSid2                    );}

     

    DWORDAPIENTRYGetSidLengthRequired (    UCHAR nSubAuthorityCount    )/*++

    Routine Description:

        This routine returns the length, in bytes, required to store an SID    with the specified number of Sub-Authorities.

    Arguments:

        nSubAuthorityCount - The number of sub-authorities to be stored in        the SID.

    Return Value:

        DWORD - The length, in bytes, required to store the SID.

    --*/{    return RtlLengthRequiredSid (                nSubAuthorityCount                );}

     

    BOOLAPIENTRYInitializeSid (    PSID Sid,    PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,    BYTE nSubAuthorityCount    )

    /*++

    Routine Description:

        This function initializes an SID data structure.  It does not,    however, set the sub-authority values.  This must be done    separately.

    Arguments:

        Sid - Pointer to the SID data structure to initialize.

        pIdentifierAuthority - Pointer to the Identifier Authority value        to set in the SID.

        nSubAuthorityCount - The number of sub-authorities that will be        placed in the SID (a separate action).

    Return Value:

        None

    --*/{    NTSTATUS Status;

        Status = RtlInitializeSid (                Sid,                pIdentifierAuthority,                nSubAuthorityCount                );

        if ( !NT_SUCCESS( Status )) {        BaseSetLastNTError( Status );        return( FALSE );    }

        return( TRUE );}

     

    PVOIDAPIENTRYFreeSid(    PSID pSid    )

    /*++

    Routine Description:

        This function is used to free a SID previously allocated using    AllocateAndInitializeSid().

    Arguments:

        Sid - Pointer to the SID to free.

    Return Value:

        None.

    --*/{    return(RtlFreeSid( pSid ));}

     

    BOOLAPIENTRYAllocateAndInitializeSid (    PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,    BYTE nSubAuthorityCount,    DWORD nSubAuthority0,    DWORD nSubAuthority1,    DWORD nSubAuthority2,    DWORD nSubAuthority3,    DWORD nSubAuthority4,    DWORD nSubAuthority5,    DWORD nSubAuthority6,    DWORD nSubAuthority7,    PSID *pSid    )

    /*++

    Routine Description:

        This function allocates and initializes a sid with the specified    number of sub-authorities (up to 8).  A sid allocated with this    routine must be freed using FreeSid().

    Arguments:

        pIdentifierAuthority - Pointer to the Identifier Authority value to        set in the SID.

        nSubAuthorityCount - The number of sub-authorities to place in the SID.        This also identifies how many of the SubAuthorityN parameters        have meaningful values.  This must contain a value from 0 through        8.

        nSubAuthority0-7 - Provides the corresponding sub-authority value to        place in the SID.  For example, a SubAuthorityCount value of 3        indicates that SubAuthority0, SubAuthority1, and SubAuthority0        have meaningful values and the rest are to be ignored.

        Sid - Receives a pointer to the allocated and initialized SID data        structure.

    Return Value:

        ERROR_NO_MEMORY - The attempt to allocate memory for the SID        failed.

        ERROR_INVALID_SID - The number of sub-authorities specified did        not fall in the valid range for this api (0 through 8).

    --*/{    NTSTATUS Status;

        Status = RtlAllocateAndInitializeSid (                 pIdentifierAuthority,                 (UCHAR)nSubAuthorityCount,                 (ULONG)nSubAuthority0,                 (ULONG)nSubAuthority1,                 (ULONG)nSubAuthority2,                 (ULONG)nSubAuthority3,                 (ULONG)nSubAuthority4,                 (ULONG)nSubAuthority5,                 (ULONG)nSubAuthority6,                 (ULONG)nSubAuthority7,                 pSid                 );

        if ( !NT_SUCCESS( Status )) {        BaseSetLastNTError( Status );        return( FALSE );    }

        return( TRUE );}

     

    PSID_IDENTIFIER_AUTHORITYGetSidIdentifierAuthority (    PSID pSid    )/*++

    Routine Description:

        This function returns the address of an SID's IdentifierAuthority field.

    Arguments:

        Sid - Pointer to the SID data structure.

    Return Value:

        Address of an SID's Identifier Authority field.

    --*/{    return RtlIdentifierAuthoritySid (               pSid               );}

     

    PDWORDGetSidSubAuthority (    PSID pSid,    DWORD nSubAuthority    )/*++

    Routine Description:

        This function returns the address of a sub-authority array element of    an SID.

    Arguments:

        pSid - Pointer to the SID data structure.

        nSubAuthority - An index indicating which sub-authority is being        specified.  This value is not compared against the number of        sub-authorities in the SID for validity.

    Return Value:

        Address of a relative ID within the SID.

    --*/{    return RtlSubAuthoritySid (               pSid,               nSubAuthority               );}

    PUCHARGetSidSubAuthorityCount (    PSID pSid    )/*++

    Routine Description:

        This function returns the address of the sub-authority count field of    an SID.

    Arguments:

        pSid - Pointer to the SID data structure.

    Return Value:

        Address of the sub-authority count field of an SID.

    --*/{    return RtlSubAuthorityCountSid (               pSid               );}

     

    DWORDAPIENTRYGetLengthSid (    PSID pSid    )/*++

    Routine Description:

        This routine returns the length, in bytes, of a structurally valid SID.

    Arguments:

        pSid - Points to the SID whose length is to be returned.  The        SID's structure is assumed to be valid.

    Return Value:

        DWORD - The length, in bytes, of the SID.

    --*/{    return RtlLengthSid (                pSid                );}

     

    BOOLAPIENTRYCopySid (    DWORD nDestinationSidLength,    PSID pDestinationSid,    PSID pSourceSid    )/*++

    Routine Description:

        This routine copies the value of the source SID to the destination    SID.

    Arguments:

        nDestinationSidLength - Indicates the length, in bytes, of the        destination SID buffer.

        pDestinationSid - Pointer to a buffer to receive a copy of the        source Sid value.

        pSourceSid - Supplies the Sid value to be copied.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;

        Status = RtlCopySid (                nDestinationSidLength,                pDestinationSid,                pSourceSid                );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

     

    BOOLAPIENTRYAreAllAccessesGranted (    DWORD GrantedAccess,    DWORD DesiredAccess    )/*++

    Routine Description:

        This routine is used to check a desired access mask against a    granted access mask.

    Arguments:

            GrantedAccess - Specifies the granted access mask.

            DesiredAccess - Specifies the desired access mask.

    Return Value:

        BOOL - TRUE if the GrantedAccess mask has all the bits set that        the DesiredAccess mask has set.  That is, TRUE is returned if        all of the desired accesses have been granted.

    --*/{    return (BOOL) RtlAreAllAccessesGranted (        GrantedAccess,        DesiredAccess        );}

     

    BOOLAPIENTRYAreAnyAccessesGranted (    DWORD GrantedAccess,    DWORD DesiredAccess    )/*++

    Routine Description:

        This routine is used to test whether any of a set of desired    accesses are granted by a granted access mask.

    Arguments:

            GrantedAccess - Specifies the granted access mask.

            DesiredAccess - Specifies the desired access mask.

    Return Value:

        BOOL - TRUE if the GrantedAccess mask contains any of the bits        specified in the DesiredAccess mask.  That is, if any of the        desired accesses have been granted, TRUE is returned.

    --*/{    return (BOOL) RtlAreAnyAccessesGranted (        GrantedAccess,        DesiredAccess        );}

     

    VOIDAPIENTRYMapGenericMask (    PDWORD AccessMask,    PGENERIC_MAPPING GenericMapping    )/*++

    Routine Description:

        This routine maps all generic accesses in the provided access mask    to specific and standard accesses according to the provided    GenericMapping.  The resulting mask will not have any of the    generic bits set (GenericRead, GenericWrite, GenericExecute, or    GenericAll) or any undefined bits set, but may have any other bit    set.  If bits other than the generic bits are provided on input,    they will not be cleared bt the mapping.

    Arguments:

        AccessMask - Points to the access mask to be mapped.

        GenericMapping - The mapping of generic to specific and standard        access types.

    Return Value:

        None.

    --*/{    RtlMapGenericMask (        AccessMask,        GenericMapping        );}

     

    BOOLAPIENTRYIsValidAcl (    PACL pAcl    )/*++

    Routine Description:

        This procedure validates an ACL.

        This involves validating the revision level of the ACL and ensuring    that the number of ACEs specified in the AceCount fit in the space    specified by the AclSize field of the ACL header.

    Arguments:

        pAcl - Pointer to the ACL structure to validate.

    Return Value:

        BOOLEAN - TRUE if the structure of Acl is valid.

    --*/{    return (BOOL) RtlValidAcl (                    pAcl                    );}

     

    BOOLAPIENTRYInitializeAcl (    PACL pAcl,    DWORD nAclLength,    DWORD dwAclRevision    )/*++

    Routine Description:

        InitializeAcl creates a new ACL in the caller supplied memory    buffer.  The ACL contains zero ACEs; therefore, it is an empty ACL    as opposed to a nonexistent ACL.  That is, if the ACL is now set    to an object it will implicitly deny access to everyone.

    Arguments:

        pAcl - Supplies the buffer containing the ACL being initialized

        nAclLength - Supplies the length of the ace buffer in bytes

        dwAclRevision - Supplies the revision for this Acl

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;

        Status = RtlCreateAcl (                pAcl,                nAclLength,                dwAclRevision                );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

     

    BOOLAPIENTRYGetAclInformation (    PACL pAcl,    PVOID pAclInformation,    DWORD nAclInformationLength,    ACL_INFORMATION_CLASS dwAclInformationClass    )/*++

    Routine Description:

        This routine returns to the caller information about an ACL.  The requested    information can be AclRevisionInformation, or AclSizeInformation.

    Arguments:

        pAcl - Supplies the Acl being examined

        pAclInformation - Supplies the buffer to receive the information        being requested

        nAclInformationLength - Supplies the length of the AclInformation        buffer in bytes

        dwAclInformationClass - Supplies the type of information being        requested

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;

        Status = RtlQueryInformationAcl (                pAcl,                pAclInformation,                nAclInformationLength,                dwAclInformationClass                );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

     

    BOOLAPIENTRYSetAclInformation (    PACL pAcl,    PVOID pAclInformation,    DWORD nAclInformationLength,    ACL_INFORMATION_CLASS dwAclInformationClass    )/*++

    Routine Description:

        This routine sets the state of an ACL.  For now only the revision    level can be set and for now only a revision level of 1 is accepted    so this procedure is rather simple

    Arguments:

        pAcl - Supplies the Acl being altered

        pAclInformation - Supplies the buffer containing the information        being set

        nAclInformationLength - Supplies the length of the Acl information        buffer

        dwAclInformationClass - Supplies the type of information begin set

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;

        Status = RtlSetInformationAcl (                pAcl,                pAclInformation,                nAclInformationLength,                dwAclInformationClass                );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

    BOOLAPIENTRYAddAce (    PACL pAcl,    DWORD dwAceRevision,    DWORD dwStartingAceIndex,    PVOID pAceList,    DWORD nAceListLength    )/*++

    Routine Description:

        This routine adds a string of ACEs to an ACL.

    Arguments:

        pAcl - Supplies the Acl being modified

        dwAceRevision - Supplies the Acl/Ace revision of the ACE being        added

        dwStartingAceIndex - Supplies the ACE index which will be the        index of the first ace inserted in the acl.  0 for the        beginning of the list and MAXULONG for the end of the list.

        pAceList - Supplies the list of Aces to be added to the Acl

        nAceListLength - Supplies the size, in bytes, of the AceList        buffer

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;

        Status = RtlAddAce (        pAcl,        dwAceRevision,        dwStartingAceIndex,        pAceList,        nAceListLength        );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

    BOOLAPIENTRYDeleteAce (    PACL pAcl,    DWORD dwAceIndex    )/*++

    Routine Description:

        This routine deletes one ACE from an ACL.

    Arguments:

        pAcl - Supplies the Acl being modified

        dwAceIndex - Supplies the index of the Ace to delete.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;

        Status = RtlDeleteAce (                pAcl,                dwAceIndex                );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

    BOOLAPIENTRYGetAce (    PACL pAcl,    DWORD dwAceIndex,    PVOID *pAce    )/*++

    Routine Description:

        This routine returns a pointer to an ACE in an ACl referenced by    ACE index

    Arguments:

        pAcl - Supplies the ACL being queried

        dwAceIndex - Supplies the Ace index to locate

        pAce - Receives the address of the ACE within the ACL

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;

        Status = RtlGetAce (                pAcl,                dwAceIndex,                pAce                );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

    BOOLAPIENTRYAddAccessAllowedAce (    PACL pAcl,    DWORD dwAceRevision,    DWORD AccessMask,    PSID pSid    )/*++

    Routine Description:

        This routine adds an ACCESS_ALLOWED ACE to an ACL.  This is    expected to be a common form of ACL modification.

        A very bland ACE header is placed in the ACE.  It provides no    inheritance and no ACE flags.

    Arguments:

        PAcl - Supplies the Acl being modified

        dwAceRevision - Supplies the Acl/Ace revision of the ACE being added

        AccessMask - The mask of accesses to be granted to the specified SID.

        pSid - Pointer to the SID being granted access.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;

        Status = RtlAddAccessAllowedAce (                pAcl,                dwAceRevision,                AccessMask,                pSid                );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

     

    BOOLAPIENTRYAddAccessDeniedAce (    PACL pAcl,    DWORD dwAceRevision,    DWORD AccessMask,    PSID pSid    )/*++

    Routine Description:

        This routine adds an ACCESS_DENIED ACE to an ACL.  This is    expected to be a common form of ACL modification.

        A very bland ACE header is placed in the ACE.  It provides no    inheritance and no ACE flags.

    Arguments:

        pAcl - Supplies the Acl being modified

        dwAceRevision - Supplies the Acl/Ace revision of the ACE being added

        AccessMask - The mask of accesses to be denied to the specified SID.

        pSid - Pointer to the SID being denied access.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;

        Status = RtlAddAccessDeniedAce (                pAcl,                dwAceRevision,                AccessMask,                pSid                );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

     

    BOOLAPIENTRYAddAuditAccessAce(    PACL pAcl,    DWORD dwAceRevision,    DWORD dwAccessMask,    PSID pSid,    BOOL bAuditSuccess,    BOOL bAuditFailure    )/*++

    Routine Description:

        This routine adds a SYSTEM_AUDIT ACE to an ACL.  This is    expected to be a common form of ACL modification.

        A very bland ACE header is placed in the ACE.  It provides no    inheritance.

        Parameters are used to indicate whether auditing is to be performed    on success, failure, or both.

    Arguments:

        pAcl - Supplies the Acl being modified

        dwAceRevision - Supplies the Acl/Ace revision of the ACE being added

        dwAccessMask - The mask of accesses to be denied to the specified SID.

        pSid - Pointer to the SID to be audited.

        bAuditSuccess - If TRUE, indicates successful access attempts are to be        audited.

        bAuditFailure - If TRUE, indicated failed access attempts are to be        audited.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/

    {    NTSTATUS Status;

        Status =  RtlAddAuditAccessAce (                pAcl,                dwAceRevision,                dwAccessMask,                pSid,                (BOOLEAN)bAuditSuccess,                (BOOLEAN)bAuditFailure                );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

     

    BOOLAPIENTRYFindFirstFreeAce (    PACL pAcl,    PVOID *pAce    )/*++

    Routine Description:

        This routine returns a pointer to the first free byte in an Acl    or NULL if the acl is ill-formed.  If the Acl is full then the    return pointer is to the byte immediately following the acl, and    TRUE will be returned.

    Arguments:

        pAcl - Supplies a pointer to the Acl to examine

        pAce - Receives a pointer to the first free position in the Acl

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    return (BOOL) RtlFirstFreeAce (                    pAcl,                    pAce                    );}

    BOOLAPIENTRYInitializeSecurityDescriptor (    PSECURITY_DESCRIPTOR pSecurityDescriptor,    DWORD dwRevision    )/*++

    Routine Description:

        This procedure initializes a new "absolute format" security descriptor.    After the procedure call the security descriptor is initialized with no    system ACL, no discretionary ACL, no owner, no primary group and    all control flags set to false (null).

    Arguments:

        pSecurityDescriptor - Supplies the security descriptor to        initialize.

        dwRevision - Provides the revision level to assign to the security        descriptor.  This should be one (1) for this release.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;

        Status = RtlCreateSecurityDescriptor (                pSecurityDescriptor,                dwRevision                );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

     

    BOOLAPIENTRYIsValidSecurityDescriptor (    PSECURITY_DESCRIPTOR pSecurityDescriptor    )/*++

    Routine Description:

        This procedure validates a SecurityDescriptor's structure.  This    involves validating the revision levels of each component of the    security descriptor.

    Arguments:

        pSecurityDescriptor - Pointer to the SECURITY_DESCRIPTOR structure        to validate.

    Return Value:

        BOOL - TRUE if the structure of SecurityDescriptor is valid.

    --*/{    if (!RtlValidSecurityDescriptor ( pSecurityDescriptor )) {        BaseSetLastNTError( STATUS_INVALID_SECURITY_DESCR );        return( FALSE );    }

        return( TRUE );}

     

    DWORDAPIENTRYGetSecurityDescriptorLength (    PSECURITY_DESCRIPTOR pSecurityDescriptor    )/*++

    Routine Description:

        This routine returns the length, in bytes, necessary to capture a    structurally valid SECURITY_DESCRIPTOR.  The length includes the length    of all associated data structures (like SIDs and ACLs).  The length also    takes into account the alignment requirements of each component.

        The minimum length of a security descriptor (one which has no associated    SIDs or ACLs) is SECURITY_DESCRIPTOR_MIN_LENGTH.

    Arguments:

        pSecurityDescriptor - Points to the SECURITY_DESCRIPTOR whose        length is to be returned.  The SECURITY_DESCRIPTOR's structure        is assumed to be valid.

    Return Value:

        DWORD - The length, in bytes, of the SECURITY_DESCRIPTOR.

    --*/{    return RtlLengthSecurityDescriptor (        pSecurityDescriptor        );}

     

     

    BOOLAPIENTRYGetSecurityDescriptorControl (    PSECURITY_DESCRIPTOR pSecurityDescriptor,    PSECURITY_DESCRIPTOR_CONTROL pControl,    LPDWORD lpdwRevision    )/*++

    Routine Description:

        This procedure retrieves the control information from a security descriptor.

    Arguments:

        pSecurityDescriptor - Supplies the security descriptor.

        pControl - Receives the control information.

        lpdwRevision - Receives the revision of the security descriptor.        This value will always be returned, even if an error is        returned by this routine.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;

        Status = RtlGetControlSecurityDescriptor (                pSecurityDescriptor,                pControl,                lpdwRevision                );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

     

    BOOLAPIENTRYSetSecurityDescriptorDacl (    PSECURITY_DESCRIPTOR pSecurityDescriptor,    BOOL bDaclPresent,    PACL pDacl OPTIONAL,    BOOL bDaclDefaulted OPTIONAL    )/*++

    Routine Description:

        This procedure sets the discretionary ACL information of an absolute    format security descriptor.  If there is already a discretionary ACL    present in the security descriptor, it is superseded.

    Arguments:

        pSecurityDescriptor - Supplies the security descriptor to be which        the discretionary ACL is to be added.

        bDaclPresent - If FALSE, indicates the DaclPresent flag in the        security descriptor should be set to FALSE.  In this case, the        remaining optional parameters are ignored.  Otherwise, the        DaclPresent control flag in the security descriptor is set to        TRUE and the remaining optional parameters are not ignored.

        pDacl - Supplies the discretionary ACL for the security        descriptor.  If this optional parameter is not passed, then a        null ACL is assigned to the security descriptor.  A null        discretionary ACL unconditionally grants access.  The ACL is        referenced by, not copied into, by the security descriptor.

        bDaclDefaulted - When set, indicates the discretionary ACL was        picked up from some default mechanism (rather than explicitly        specified by a user).  This value is set in the DaclDefaulted        control flag in the security descriptor.  If this optional        parameter is not passed, then the DaclDefaulted flag will be        cleared.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;

        Status = RtlSetDaclSecurityDescriptor (        pSecurityDescriptor,        (BOOLEAN)bDaclPresent,        pDacl,        (BOOLEAN)bDaclDefaulted        );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

     

    BOOLAPIENTRYGetSecurityDescriptorDacl (    PSECURITY_DESCRIPTOR pSecurityDescriptor,    LPBOOL lpbDaclPresent,    PACL *pDacl,    LPBOOL lpbDaclDefaulted    )/*++

    Routine Description:

        This procedure retrieves the discretionary ACL information of a    security descriptor.

    Arguments:

        pSecurityDescriptor - Supplies the security descriptor.

        lpbDaclPresent - If TRUE, indicates that the security descriptor        does contain a discretionary ACL.  In this case, the        remaining OUT parameters will receive valid values.        Otherwise, the security descriptor does not contain a        discretionary ACL and the remaining OUT parameters will not        receive valid values.

        pDacl - This value is returned only if the value returned for the        DaclPresent flag is TRUE.  In this case, the Dacl parameter        receives the address of the security descriptor's        discretionary ACL.  If this value is returned as null, then        the security descriptor has a null discretionary ACL.

        lpbDaclDefaulted - This value is returned only if the value        returned for the DaclPresent flag is TRUE.  In this case, the        DaclDefaulted parameter receives the value of the security        descriptor's DaclDefaulted control flag.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;    BOOLEAN DaclPresent, DaclDefaulted;

        Status = RtlGetDaclSecurityDescriptor (        pSecurityDescriptor,        &DaclPresent,        pDacl,        &DaclDefaulted        );    *lpbDaclPresent = (BOOL)DaclPresent;    *lpbDaclDefaulted = (BOOL)DaclDefaulted;

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

     

    BOOLAPIENTRYSetSecurityDescriptorSacl (    PSECURITY_DESCRIPTOR pSecurityDescriptor,    BOOL bSaclPresent,    PACL pSacl OPTIONAL,    BOOL bSaclDefaulted    )/*++

    Routine Description:

        This procedure sets the system ACL information of an absolute security    descriptor.  If there is already a system ACL present in the    security descriptor, it is superseded.

    Arguments:

        pSecurityDescriptor - Supplies the security descriptor to be which        the system ACL is to be added.

        bSaclPresent - If FALSE, indicates the SaclPresent flag in the        security descriptor should be set to FALSE.  In this case,        the remaining optional parameters are ignored.  Otherwise,        the SaclPresent control flag in the security descriptor is        set to TRUE and the remaining optional parameters are not        ignored.

        pSacl - Supplies the system ACL for the security descriptor.  If        this optional parameter is not passed, then a null ACL is        assigned to the security descriptor.  The ACL is referenced        by, not copied into, by the security descriptor.

        bSaclDefaulted - When set, indicates the system ACL was picked up        from some default mechanism (rather than explicitly specified        by a user).  This value is set in the SaclDefaulted control        flag in the security descriptor.  If this optional parameter        is not passed, then the SaclDefaulted flag will be cleared.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;

        Status = RtlSetSaclSecurityDescriptor (                pSecurityDescriptor,                (BOOLEAN)bSaclPresent,                pSacl,                (BOOLEAN)bSaclDefaulted                );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

     

    BOOLAPIENTRYGetSecurityDescriptorSacl (    PSECURITY_DESCRIPTOR pSecurityDescriptor,    LPBOOL lpbSaclPresent,    PACL *pSacl,    LPBOOL lpbSaclDefaulted    )/*++

    Routine Description:

        This procedure retrieves the system ACL information of a security    descriptor.

    Arguments:

        pSecurityDescriptor - Supplies the security descriptor.

        lpbSaclPresent - If TRUE, indicates that the security descriptor        does contain a system ACL.  In this case, the remaining OUT        parameters will receive valid values.  Otherwise, the        security descriptor does not contain a system ACL and the        remaining OUT parameters will not receive valid values.

        pSacl - This value is returned only if the value returned for the        SaclPresent flag is TRUE.  In this case, the Sacl parameter        receives the address of the security descriptor's system ACL.        If this value is returned as null, then the security        descriptor has a null system ACL.

        lpbSaclDefaulted - This value is returned only if the value        returned for the SaclPresent flag is TRUE.  In this case, the        SaclDefaulted parameter receives the value of the security        descriptor's SaclDefaulted control flag.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;    BOOLEAN SaclPresent, SaclDefaulted;

        Status = RtlGetSaclSecurityDescriptor (        pSecurityDescriptor,        &SaclPresent,        pSacl,        &SaclDefaulted        );    *lpbSaclPresent = (BOOL)SaclPresent;    *lpbSaclDefaulted = (BOOL)SaclDefaulted;

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

     

    BOOLAPIENTRYSetSecurityDescriptorOwner (    PSECURITY_DESCRIPTOR pSecurityDescriptor,    PSID pOwner OPTIONAL,    BOOL bOwnerDefaulted OPTIONAL    )/*++

    Routine Description:

        This procedure sets the owner information of an absolute security    descriptor.  If there is already an owner present in the security    descriptor, it is superseded.

    Arguments:

        pSecurityDescriptor - Supplies the security descriptor in which        the owner is to be set.  If the security descriptor already        includes an owner, it will be superseded by the new owner.

        pOwner - Supplies the owner SID for the security descriptor.  If        this optional parameter is not passed, then the owner is        cleared (indicating the security descriptor has no owner).        The SID is referenced by, not copied into, the security        descriptor.

        bOwnerDefaulted - When set, indicates the owner was picked up from        some default mechanism (rather than explicitly specified by a        user).  This value is set in the OwnerDefaulted control flag        in the security descriptor.  If this optional parameter is        not passed, then the SaclDefaulted flag will be cleared.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;

        Status = RtlSetOwnerSecurityDescriptor (        pSecurityDescriptor,        pOwner,        (BOOLEAN)bOwnerDefaulted        );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

    BOOLAPIENTRYGetSecurityDescriptorOwner (    PSECURITY_DESCRIPTOR pSecurityDescriptor,    PSID *pOwner,    LPBOOL lpbOwnerDefaulted    )/*++

    Routine Description:

        This procedure retrieves the owner information of a security    descriptor.

    Arguments:

        pSecurityDescriptor - Supplies the security descriptor.

        pOwner - Receives a pointer to the owner SID.  If the security        descriptor does not currently contain an owner, then this        value will be returned as null.  In this case, the remaining        OUT parameters are not given valid return values.  Otherwise,        this parameter points to an SID and the remaining OUT        parameters are provided valid return values.

        lpbOwnerDefaulted - This value is returned only if the value        returned for the Owner parameter is not null.  In this case,        the OwnerDefaulted parameter receives the value of the        security descriptor's OwnerDefaulted control flag.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;    BOOLEAN OwnerDefaulted;

        Status = RtlGetOwnerSecurityDescriptor (        pSecurityDescriptor,        pOwner,        &OwnerDefaulted        );    *lpbOwnerDefaulted = (BOOL)OwnerDefaulted;

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

     

    BOOLAPIENTRYSetSecurityDescriptorGroup (    PSECURITY_DESCRIPTOR pSecurityDescriptor,    PSID pGroup OPTIONAL,    BOOL bGroupDefaulted OPTIONAL    )/*++

    Routine Description:

        This procedure sets the primary group information of an absolute security    descriptor.  If there is already an primary group present in the    security descriptor, it is superseded.

    Arguments:

        pSecurityDescriptor - Supplies the security descriptor in which        the primary group is to be set.  If the security descriptor        already includes a primary group, it will be superseded by        the new group.

        pGroup - Supplies the primary group SID for the security        descriptor.  If this optional parameter is not passed, then        the primary group is cleared (indicating the security        descriptor has no primary group).  The SID is referenced by,        not copied into, the security descriptor.

        bGroupDefaulted - When set, indicates the owner was picked up from        some default mechanism (rather than explicitly specified by a        user).  This value is set in the OwnerDefaulted control flag        in the security descriptor.  If this optional parameter is        not passed, then the SaclDefaulted flag will be cleared.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;

        Status = RtlSetGroupSecurityDescriptor (        pSecurityDescriptor,        pGroup,        (BOOLEAN)bGroupDefaulted        );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

     

    BOOLAPIENTRYGetSecurityDescriptorGroup (    PSECURITY_DESCRIPTOR pSecurityDescriptor,    PSID *pGroup,    LPBOOL lpbGroupDefaulted    )/*++

    Routine Description:

        This procedure retrieves the primary group information of a    security descriptor.

    Arguments:

        pSecurityDescriptor - Supplies the security descriptor.

        pGroup - Receives a pointer to the primary group SID.  If the        security descriptor does not currently contain a primary        group, then this value will be returned as null.  In this        case, the remaining OUT parameters are not given valid return        values.  Otherwise, this parameter points to an SID and the        remaining OUT parameters are provided valid return values.

        lpbGroupDefaulted - This value is returned only if the value        returned for the Group parameter is not null.  In this case,        the GroupDefaulted parameter receives the value of the        security descriptor's GroupDefaulted control flag.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;    BOOLEAN GroupDefaulted;

        Status = RtlGetGroupSecurityDescriptor (        pSecurityDescriptor,        pGroup,        &GroupDefaulted        );    *lpbGroupDefaulted = GroupDefaulted;

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

     

    BOOLAPIENTRYCreatePrivateObjectSecurity (    PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,    PSECURITY_DESCRIPTOR CreatorDescriptor OPTIONAL,    PSECURITY_DESCRIPTOR * NewDescriptor,    BOOL IsDirectoryObject,    HANDLE Token,    PGENERIC_MAPPING GenericMapping    )/*++

    Routine Description:

        The procedure is used to allocpate and initialize a self-relative    Security Descriptor for a new protected server's object.  It is called    when a new protected server object is being created.  The generated    security descriptor will be in self-relative form.

        This procedure, called only from user mode, is used to establish a    security descriptor for a new protected server's object.  When no    longer needed, this descriptor must be freed using    DestroyPrivateObjectSecurity().

    Arguments:

        ParentDescriptor - Supplies the Security Descriptor for the parent        directory under which a new object is being created.  If there is        no parent directory, then this argument is specified as NULL.

        CreatorDescriptor - (Optionally) Points to a security descriptor        presented by the creator of the object.  If the creator of the        object did not explicitly pass security information for the new        object, then a null pointer should be passed.

        NewDescriptor - Points to a pointer that is to be made to point to the        newly allocated self-relative security descriptor.

        IsDirectoryObject - Specifies if the new object is going to be a        directory object.  A value of TRUE indicates the object is a        container of other objects.

        Token - Supplies the token for the client on whose behalf the        object is being created.  If it is an impersonation token,        then it must be at SecurityIdentification level or higher.  If        it is not an impersonation token, the operation proceeds        normally.

            A client token is used to retrieve default security        information for the new object, such as default owner, primary        group, and discretionary access control.  The token must be        open for TOKEN_QUERY access.

        GenericMapping - Supplies a pointer to a generic mapping array denoting        the mapping between each generic right to specific rights.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;

        Status = RtlNewSecurityObject (        ParentDescriptor,        CreatorDescriptor,        NewDescriptor,        (BOOLEAN)IsDirectoryObject,        Token,        GenericMapping        );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

     

    BOOLAPIENTRYSetPrivateObjectSecurity (    SECURITY_INFORMATION SecurityInformation,    PSECURITY_DESCRIPTOR ModificationDescriptor,    PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,    PGENERIC_MAPPING GenericMapping,    HANDLE Token OPTIONAL    )/*++

    Routine Description:

        Modify an object's existing self-relative form security descriptor.

        This procedure, called only from user mode, is used to update a    security descriptor on an existing protected server's object.  It    applies changes requested by a new security descriptor to the existing    security descriptor.  If necessary, this routine will allocate    additional memory to produce a larger security descriptor.  All access    checking is expected to be done before calling this routine.  This    includes checking for WRITE_OWNER, WRITE_DAC, and privilege to assign a    system ACL as appropriate.

        The caller of this routine must not be impersonating a client.

    Arguments:

        SecurityInformation - Indicates which security information is        to be applied to the object.  The value(s) to be assigned are        passed in the ModificationDescriptor parameter.

        ModificationDescriptor - Supplies the input security descriptor to be        applied to the object.  The caller of this routine is expected        to probe and capture the passed security descriptor before calling        and release it after calling.

        ObjectsSecurityDescriptor - Supplies the address of a pointer to        the objects security descriptor that is going to be altered by        this procedure.  This security descriptor must be in self-        relative form or an error will be returned.

        GenericMapping - This argument provides the mapping of generic to        specific/standard access types for the object being accessed.        This mapping structure is expected to be safe to access        (i.e., captured if necessary) prior to be passed to this routine.

        Token - (optionally) Supplies the token for the client on whose        behalf the security is being modified.  This parameter is only        required to ensure that the client has provided a legitimate        value for a new owner SID.  The token must be open for        TOKEN_QUERY access.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;

        Status = RtlSetSecurityObject (        SecurityInformation,        ModificationDescriptor,        ObjectsSecurityDescriptor,        GenericMapping,        Token        );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

     

    BOOLAPIENTRYGetPrivateObjectSecurity (    PSECURITY_DESCRIPTOR ObjectDescriptor,    SECURITY_INFORMATION SecurityInformation,    PSECURITY_DESCRIPTOR ResultantDescriptor,    DWORD DescriptorLength,    PDWORD ReturnLength    )/*++

    Routine Description:

        Query information from a protected server object's existing security    descriptor.

        This procedure, called only from user mode, is used to retrieve    information from a security descriptor on an existing protected    server's object.  All access checking is expected to be done before    calling this routine.  This includes checking for READ_CONTROL, and    privilege to read a system ACL as appropriate.

    Arguments:

        ObjectDescriptor - Points to a pointer to a security descriptor to be        queried.

        SecurityInformation - Identifies the security information being        requested.

        ResultantDescriptor - Points to buffer to receive the resultant        security descriptor.  The resultant security descriptor will        contain all information requested by the SecurityInformation        parameter.

        DescriptorLength - Is an unsigned integer which indicates the length,        in bytes, of the buffer provided to receive the resultant        descriptor.

        ReturnLength - Receives an unsigned integer indicating the actual        number of bytes needed in the ResultantDescriptor to store the        requested information.  If the value returned is greater than the        value passed via the DescriptorLength parameter, then        STATUS_BUFFER_TOO_SMALL is returned and no information is returned.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;

        Status = RtlQuerySecurityObject (         ObjectDescriptor,         SecurityInformation,         ResultantDescriptor,         DescriptorLength,         ReturnLength         );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

     

    BOOLAPIENTRYDestroyPrivateObjectSecurity (    PSECURITY_DESCRIPTOR * ObjectDescriptor    )/*++

    Routine Description:

        Delete a protected server object's security descriptor.

        This procedure, called only from user mode, is used to delete a    security descriptor associated with a protected server's object.  This    routine will normally be called by a protected server during object    deletion.  The input descriptor is expected to be one created via    a call to CreatePrivateObjectSecurity.

    Arguments:

        ObjectDescriptor - Points to a pointer to a security descriptor to be        deleted.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;

        Status = RtlDeleteSecurityObject (        ObjectDescriptor        );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

     

    BOOLAPIENTRYMakeSelfRelativeSD (    PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,    PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,    LPDWORD lpdwBufferLength    )/*++

    Routine Description:

        Converts a security descriptor in absolute form to one in self-relative    form.

    Arguments:

        pAbsoluteSecurityDescriptor - Pointer to an absolute format        security descriptor.  This descriptor will not be modified.

        pSelfRelativeSecurityDescriptor - Pointer to a buffer that will        contain the returned self-relative security descriptor.

        lpdwBufferLength - Supplies the length of the buffer.  If the        supplied buffer is not large enough to hold the self-relative        security descriptor, an error will be returned, and this field        will return the minimum size required.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;

        Status = RtlAbsoluteToSelfRelativeSD (                pAbsoluteSecurityDescriptor,                pSelfRelativeSecurityDescriptor,                lpdwBufferLength                );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

    BOOLAPIENTRYMakeAbsoluteSD (    PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,    PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,    LPDWORD lpdwAbsoluteSecurityDescriptorSize,    PACL pDacl,    LPDWORD lpdwDaclSize,    PACL pSacl,    LPDWORD lpdwSaclSize,    PSID pOwner,    LPDWORD lpdwOwnerSize,    PSID pPrimaryGroup,    LPDWORD lpdwPrimaryGroupSize    )/*++

    Routine Description:

        Converts a security descriptor from self-relative format to absolute    format

    Arguments:

        pSecurityDescriptor - Supplies a pointer to a security descriptor        in Self-Relative format

        pAbsoluteSecurityDescriptor - A pointer to a buffer in which will        be placed the main body of the Absolute format security        descriptor.

        lpdwAbsoluteSecurityDescriptorSize - The size in bytes of the        buffer pointed to by pAbsoluteSecurityDescriptor.

        pDacl - Supplies a pointer to a buffer that will contain the Dacl        of the output descriptor.  This pointer will be referenced by,        not copied into, the output descriptor.

        lpdwDaclSize - Supplies the size of the buffer pointed to by Dacl.        In case of error, it will return the minimum size necessary to        contain the Dacl.

        pSacl - Supplies a pointer to a buffer that will contain the Sacl        of the output descriptor.  This pointer will be referenced by,        not copied into, the output descriptor.

        lpdwSaclSize - Supplies the size of the buffer pointed to by Sacl.        In case of error, it will return the minimum size necessary to        contain the Sacl.

        pOwner - Supplies a pointer to a buffer that will contain the        Owner of the output descriptor.  This pointer will be        referenced by, not copied into, the output descriptor.

        lpdwOwnerSize - Supplies the size of the buffer pointed to by        Owner.  In case of error, it will return the minimum size        necessary to contain the Owner.

        pPrimaryGroup - Supplies a pointer to a buffer that will contain        the PrimaryGroup of the output descriptor.  This pointer will        be referenced by, not copied into, the output descriptor.

        lpdwPrimaryGroupSize - Supplies the size of the buffer pointed to        by PrimaryGroup.  In case of error, it will return the minimum        size necessary to contain the PrimaryGroup.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{    NTSTATUS Status;

        Status = RtlSelfRelativeToAbsoluteSD (                pSelfRelativeSecurityDescriptor,                pAbsoluteSecurityDescriptor,                lpdwAbsoluteSecurityDescriptorSize,                pDacl,                lpdwDaclSize,                pSacl,                lpdwSaclSize,                pOwner,                lpdwOwnerSize,                pPrimaryGroup,                lpdwPrimaryGroupSize                );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

    VOIDSetSecurityAccessMask(    IN SECURITY_INFORMATION SecurityInformation,    OUT LPDWORD DesiredAccess    )

    /*++

    Routine Description:

        This routine builds an access mask representing the accesses necessary    to set the object security information specified in the SecurityInformation    parameter.  While it is not difficult to determine this information,    the use of a single routine to generate it will ensure minimal impact    when the security information associated with an object is extended in    the future (to include mandatory access control information).

    Arguments:

        SecurityInformation - Identifies the object's security information to be        modified.

        DesiredAccess - Points to an access mask to be set to represent the        accesses necessary to modify the information specified in the        SecurityInformation parameter.

    Return Value:

        None.

    --*/

    {

        //    // Figure out accesses needed to perform the indicated operation(s).    //

        (*DesiredAccess) = 0;

        if ((SecurityInformation & OWNER_SECURITY_INFORMATION) ||        (SecurityInformation & GROUP_SECURITY_INFORMATION)   ) {        (*DesiredAccess) |= WRITE_OWNER;    }

        if (SecurityInformation & DACL_SECURITY_INFORMATION) {        (*DesiredAccess) |= WRITE_DAC;    }

        if (SecurityInformation & SACL_SECURITY_INFORMATION) {        (*DesiredAccess) |= ACCESS_SYSTEM_SECURITY;    }

        return;

    }

    VOIDQuerySecurityAccessMask(    IN SECURITY_INFORMATION SecurityInformation,    OUT LPDWORD DesiredAccess    )

    /*++

    Routine Description:

        This routine builds an access mask representing the accesses necessary    to query the object security information specified in the    SecurityInformation parameter.  While it is not difficult to determine    this information, the use of a single routine to generate it will ensure    minimal impact when the security information associated with an object is    extended in the future (to include mandatory access control information).

    Arguments:

        SecurityInformation - Identifies the object's security information to be        queried.

        DesiredAccess - Points to an access mask to be set to represent the        accesses necessary to query the information specified in the        SecurityInformation parameter.

    Return Value:

        None.

    --*/

    {

        //    // Figure out accesses needed to perform the indicated operation(s).    //

        (*DesiredAccess) = 0;

        if ((SecurityInformation & OWNER_SECURITY_INFORMATION) ||        (SecurityInformation & GROUP_SECURITY_INFORMATION) ||        (SecurityInformation & DACL_SECURITY_INFORMATION)) {        (*DesiredAccess) |= READ_CONTROL;    }

        if ((SecurityInformation & SACL_SECURITY_INFORMATION)) {        (*DesiredAccess) |= ACCESS_SYSTEM_SECURITY;    }

        return;

    }

    BOOLAPIENTRYSetFileSecurityW(    LPCWSTR lpFileName,    SECURITY_INFORMATION SecurityInformation,    PSECURITY_DESCRIPTOR pSecurityDescriptor    )

    /*++

    Routine Description:

        This API can be used to set the security of a file or directory    (process, file, event, etc.).  This call is only successful if the    following conditions are met:

        o If the object's owner or group is to be set, the caller must      have WRITE_OWNER permission or have SeTakeOwnershipPrivilege.

        o If the object's DACL is to be set, the caller must have      WRITE_DAC permission or be the object's owner.

        o If the object's SACL is to be set, the caller must have      SeSecurityPrivilege.

    Arguments:

        lpFileName - Supplies the file name of the file to open.  Depending on        the value of the FailIfExists parameter, this name may or may        not already exist.

        SecurityInformation - A pointer to information describing the        contents of the Security Descriptor.

        pSecurityDescriptor - A pointer to a well formed Security        Descriptor.

    Return Value:

        TRUE - The operation was successful.

        FALSE/NULL - The operation failed. Extended error status is available        using GetLastError.

    --*/{    NTSTATUS Status;    HANDLE FileHandle;    ACCESS_MASK DesiredAccess;

        OBJECT_ATTRIBUTES Obja;    UNICODE_STRING FileName;    BOOLEAN TranslationStatus;    RTL_RELATIVE_NAME RelativeName;    IO_STATUS_BLOCK IoStatusBlock;    PVOID FreeBuffer;

        SetSecurityAccessMask(        SecurityInformation,        &DesiredAccess        );

        TranslationStatus = RtlDosPathNameToNtPathName_U(                            lpFileName,                            &FileName,                            NULL,                            &RelativeName                            );

        if ( !TranslationStatus ) {        BaseSetLastNTError(STATUS_OBJECT_NAME_INVALID);        return FALSE;        }

        FreeBuffer = FileName.Buffer;

        if ( RelativeName.RelativeName.Length ) {        FileName = *(PUNICODE_STRING)&RelativeName.RelativeName;        }    else {        RelativeName.ContainingDirectory = NULL;        }

        InitializeObjectAttributes(        &Obja,        &FileName,        OBJ_CASE_INSENSITIVE,        RelativeName.ContainingDirectory,        NULL        );

        Status = NtOpenFile(                 &FileHandle,                 DesiredAccess,                 &Obja,                 &IoStatusBlock,                 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,                 0                 );

        RtlFreeHeap(RtlProcessHeap(), 0,FreeBuffer);

        if ( !NT_SUCCESS( Status ) ) {        BaseSetLastNTError( Status );        return FALSE;        }

        Status = NtSetSecurityObject(                FileHandle,                SecurityInformation,                pSecurityDescriptor                );

        NtClose(FileHandle);

        if (!NT_SUCCESS(Status)) {        BaseSetLastNTError(Status);        return FALSE;        }

        return TRUE;}

    BOOLAPIENTRYSetFileSecurityA(    LPCSTR lpFileName,    SECURITY_INFORMATION SecurityInformation,    PSECURITY_DESCRIPTOR pSecurityDescriptor    )

    /*++

    Routine Description:

        ANSI thunk to SetFileSecurityW

    --*/

    {

        PUNICODE_STRING Unicode;    ANSI_STRING AnsiString;    NTSTATUS Status;

        Unicode = &NtCurrentTeb()->StaticUnicodeString;    RtlInitAnsiString(&AnsiString,lpFileName);    Status = RtlAnsiStringToUnicodeString(Unicode,&AnsiString,FALSE);    if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;        }    return ( SetFileSecurityW( (LPCWSTR)Unicode->Buffer,                               SecurityInformation,                               pSecurityDescriptor                        )           );}

    BOOLAPIENTRYGetFileSecurityW(    LPCWSTR lpFileName,    SECURITY_INFORMATION RequestedInformation,    PSECURITY_DESCRIPTOR pSecurityDescriptor,    DWORD nLength,    LPDWORD lpnLengthNeeded    )

    /*++

    Routine Description:

        This API returns top the caller a copy of the security descriptor    protecting a file or directory.  Based on the caller's access    rights and privileges, this procedure will return a security    descriptor containing the requested security descriptor fields.    To read the handle's security descriptor the caller must be    granted READ_CONTROL access or be the owner of the object.  In    addition, the caller must have SeSecurityPrivilege privilege to    read the system ACL.

    Arguments:

        lpFileName - Represents the name of the file or directory whose        security is being retrieved.

        RequestedInformation - A pointer to the security information being        requested.

        pSecurityDescriptor - A pointer to the buffer to receive a copy of        the secrity descriptor protecting the object that the caller        has the rigth to view.  The security descriptor is returned in        self-relative format.

        nLength - The size, in bytes, of the security descriptor buffer.

        lpnLengthNeeded - A pointer to the variable to receive the number        of bytes needed to store the complete secruity descriptor.  If        returned number of bytes is less than or equal to nLength then        the entire security descriptor is returned in the output        buffer, otherwise none of the descriptor is returned.

    Return Value:

        TRUE is returned for success, FALSE if access is denied or if the        buffer is too small to hold the security descriptor.

    --*/{    NTSTATUS Status;    HANDLE FileHandle;    ACCESS_MASK DesiredAccess;

        OBJECT_ATTRIBUTES Obja;    UNICODE_STRING FileName;    BOOLEAN TranslationStatus;    RTL_RELATIVE_NAME RelativeName;    IO_STATUS_BLOCK IoStatusBlock;    PVOID FreeBuffer;

        QuerySecurityAccessMask(        RequestedInformation,        &DesiredAccess        );

        TranslationStatus = RtlDosPathNameToNtPathName_U(                            lpFileName,                            &FileName,                            NULL,                            &RelativeName                            );

        if ( !TranslationStatus ) {        BaseSetLastNTError(STATUS_OBJECT_NAME_INVALID);        return FALSE;        }

        FreeBuffer = FileName.Buffer;

        if ( RelativeName.RelativeName.Length ) {        FileName = *(PUNICODE_STRING)&RelativeName.RelativeName;        }    else {        RelativeName.ContainingDirectory = NULL;        }

        InitializeObjectAttributes(        &Obja,        &FileName,        OBJ_CASE_INSENSITIVE,        RelativeName.ContainingDirectory,        NULL        );

        Status = NtOpenFile(                 &FileHandle,                 DesiredAccess,                 &Obja,                 &IoStatusBlock,                 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,                 0                 );

        RtlFreeHeap(RtlProcessHeap(), 0,FreeBuffer);

        if (NT_SUCCESS(Status)) {        Status = NtQuerySecurityObject(                     FileHandle,                     RequestedInformation,                     pSecurityDescriptor,                     nLength,                     lpnLengthNeeded                     );        NtClose(FileHandle);    }

        if (!NT_SUCCESS(Status)) {        BaseSetLastNTError(Status);        return FALSE;        }

        return TRUE;}

    BOOLAPIENTRYGetFileSecurityA(    LPCSTR lpFileName,    SECURITY_INFORMATION RequestedInformation,    PSECURITY_DESCRIPTOR pSecurityDescriptor,    DWORD nLength,    LPDWORD lpnLengthNeeded    )

    /*++

    Routine Description:

        ANSI thunk to GetFileSecurityW

    --*/

    {

        PUNICODE_STRING Unicode;    ANSI_STRING AnsiString;    NTSTATUS Status;

        Unicode = &NtCurrentTeb()->StaticUnicodeString;    RtlInitAnsiString(&AnsiString,lpFileName);    Status = RtlAnsiStringToUnicodeString(Unicode,&AnsiString,FALSE);    if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;        }    return ( GetFileSecurityW( (LPCWSTR)Unicode->Buffer,                               RequestedInformation,                               pSecurityDescriptor,                               nLength,                               lpnLengthNeeded                        )           );}

     

    BOOLAPIENTRYSetKernelObjectSecurity (    HANDLE Handle,    SECURITY_INFORMATION SecurityInformation,    PSECURITY_DESCRIPTOR SecurityDescriptor    )/*++

    Routine Description:

        This API can be used to set the security of a kernel object    (process, file, event, etc.).  This call is only successful if the    following conditions are met:

        o If the object's owner or group is to be set, the caller must      have WRITE_OWNER permission or have SeTakeOwnershipPrivilege.

        o If the object's DACL is to be set, the caller must have      WRITE_DAC permission or be the object's owner.

        o If the object's SACL is to be set, the caller must have      SeSecurityPrivilege.

    Arguments:

        Handle - Represents a handle of a kernel object.

        SecurityInformation - A pointer to information describing the        contents of the Security Descriptor.

        pSecurityDescriptor - A pointer to a well formed Security        Descriptor.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/

    {    NTSTATUS Status;

        Status = NtSetSecurityObject(                 Handle,                 SecurityInformation,                 SecurityDescriptor                 );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

     

    BOOLAPIENTRYGetKernelObjectSecurity (    HANDLE Handle,    SECURITY_INFORMATION RequestedInformation,    PSECURITY_DESCRIPTOR pSecurityDescriptor,    DWORD nLength,    LPDWORD lpnLengthNeeded    )/*++

    Routine Description:

        This API returns top the caller a copy of the security descriptor    protecting a kernel object.  Based on the caller's access rights    and privileges, this procedure will return a security descriptor    containing the requested security descriptor fields.  To read the    handle's security descriptor the caller must be granted    READ_CONTROL access or be the owner of the object.  In addition,    the caller must have SeSecurityPrivilege privilege to read the    system ACL.

    Arguments:

        Handle - Represents a handle of a kernel object.

        RequestedInformation - A pointer to the security information being        requested.

        pSecurityDescriptor - A pointer to the buffer to receive a copy of        the secrity descriptor protecting the object that the caller        has the rigth to view.  The security descriptor is returned in        self-relative format.

        nLength - The size, in bytes, of the security descriptor buffer.

        lpnLengthNeeded - A pointer to the variable to receive the number        of bytes needed to store the complete secruity descriptor.  If        returned number of bytes is less than or equal to nLength then        the entire security descriptor is returned in the output        buffer, otherwise none of the descriptor is returned.

    Return Value:

        return-value - Description of conditions needed to return value. - or -    None.

    --*/

    {    NTSTATUS Status;

        Status = NtQuerySecurityObject(                 Handle,                 RequestedInformation,                 pSecurityDescriptor,                 nLength,                 lpnLengthNeeded                 );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;

    }

    BOOLAPIENTRYImpersonateNamedPipeClient(    IN HANDLE hNamedPipe    )/*++

    Routine Description:

        Impersonate a named pipe client application.

    Arguments:

        hNamedPipe - Handle to a named pipe.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/

    {    NTSTATUS Status;    IO_STATUS_BLOCK IoStatusBlock;

        Status =  NtFsControlFile(                  hNamedPipe,                  NULL,                  NULL,                  NULL,                  &IoStatusBlock,                  FSCTL_PIPE_IMPERSONATE,                  NULL,                  0,                  NULL,                  0                 );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;}

    BOOLAPIENTRYImpersonateSelf(    SECURITY_IMPERSONATION_LEVEL ImpersonationLevel    )

    /*++

    Routine Description:

        This routine may be used to obtain an Impersonation token representing    your own process's context.  This may be useful for enabling a privilege    for a single thread rather than for the entire process; or changing    the default DACL for a single thread.

        The token is assigned to the callers thread.

     

    Arguments:

        ImpersonationLevel - The level to make the impersonation token.

     

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/{

        NTSTATUS Status;

        Status = RtlImpersonateSelf( ImpersonationLevel );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;

    }

     

    BOOLAPIENTRYRevertToSelf (    VOID    )/*++

    Routine Description:

        Terminate impersonation of a named pipe client application.

    Arguments:

        None.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/

    {    HANDLE NewToken;    NTSTATUS Status;

        NewToken = NULL;    Status = NtSetInformationThread(                 NtCurrentThread(),                 ThreadImpersonationToken,                 (PVOID)&NewToken,                 (ULONG)sizeof(HANDLE)                 );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;

    }

     

    BOOLAPIENTRYSetThreadToken (    PHANDLE Thread,    HANDLE Token    )/*++

    Routine Description:

        Assigns the specified impersonation token to the specified    thread.

    Arguments:

        Thread - Specifies the thread whose token is to be assigned.        If NULL is specified, then the caller's thread is assumed.

        Token - The token to assign.  Must be open for TOKEN_IMPERSONATE        access.  If null, then causes the specified thread to stop        impersonating.

    Return Value:

        Returns TRUE for success, FALSE for failure.  Extended error status    is available using GetLastError.

    --*/

    {    NTSTATUS Status;    HANDLE TargetThread;

        if (ARGUMENT_PRESENT(Thread)) {        TargetThread = (*Thread);    } else {        TargetThread = NtCurrentThread();    }

        Status = NtSetInformationThread(                 TargetThread,                 ThreadImpersonationToken,                 (PVOID)&Token,                 (ULONG)sizeof(HANDLE)                 );

        if ( !NT_SUCCESS(Status) ) {        BaseSetLastNTError(Status);        return FALSE;    }

        return TRUE;

    }

     

    BOOLAPIENTRYLookupAccountNameA(    LPCSTR lpSystemName,    LPCSTR lpAccountName,    PSID Sid,    LPDWORD cbSid,    LPSTR ReferencedDomainName,    LPDWORD cbReferencedDomainName,    PSID_NAME_USE peUse    )

    /*++

    Routine Description:

        ANSI Thunk to LookupAccountNameW

    Arguments:

        lpSystemName - Supplies the name of the system at which the lookup        is to be performed.  If the null string is provided, the local        system is assumed.

        lpAccountName - Supplies the account name.

        Sid - Returns the SID corresponding to the passed account name.

        cbSid - Supplies the size of the buffer passed in for Sid.  If        the buffer size is not big enough, this parameter will        return the size necessary to hold the output Sid.

        ReferencedDomainName - Returns the name of the domain in which the        name was found.

        cbReferencedDomainName - Supplies the size (in Ansi characters) of the        ReferencedDomainName buffer.  If the buffer size is not large        enough, this parameter will return the size necessary to hold        the null-terminated output domain name.  If the buffer size is        large enough, tis parameter will return the size (in Ansi characters,        excluding the terminating null) of the Referenced Domain name.

        peUse - Returns an enumerated type indicating the type of the        account.

    Return Value:

        BOOL - TRUE is returned if successful, else FALSE.

    --*/

    {    UNICODE_STRING Unicode;    UNICODE_STRING TmpUnicode;    ANSI_STRING  AnsiString;    PWSTR WReferencedDomainName = NULL;    UNICODE_STRING SystemName;    PWSTR pSystemName = NULL;    NTSTATUS Status;    BOOL rc = TRUE;    DWORD cbInitReferencedDomainName;

        Unicode.Buffer = NULL;    SystemName.Buffer = NULL;

        //    // Save the original buffer size    //

        cbInitReferencedDomainName = *cbReferencedDomainName;

        //    // Convert the passed lpAccountName to a WCHAR string to be    // passed to the ..W routine.  Note that we cannot use the    // StaticUnicodeString in the Thread Environment Block because    // this is used by LdrpWalkImportDescriptor, called from the    // client RPC stub code of the LsaOpenPolicy() call in    // LookupAccountNameW.    //

        RtlInitAnsiString( &AnsiString, lpAccountName );    Status = RtlAnsiStringToUnicodeString( &Unicode, &AnsiString, TRUE );

        if (!NT_SUCCESS(Status)) {

            rc = FALSE;    }

        //    // Allocate a temporary buffer for ReferencedDomainName that    // is twice as large as what was passed to adjust for the    // intermediate conversion to a WCHAR string.    //

        if (rc) {

            WReferencedDomainName = LocalAlloc(                                    LMEM_FIXED,                                    sizeof(WCHAR) * (*cbReferencedDomainName)                                    );

            if (WReferencedDomainName == NULL) {

                Status = STATUS_NO_MEMORY;            rc = FALSE;        }    }

        //    // If the target system name is non NULL, convert it to Unicode    //

        if (rc) {

            if ( ARGUMENT_PRESENT( lpSystemName ) ) {

                RtlInitAnsiString( &AnsiString, lpSystemName );            Status = RtlAnsiStringToUnicodeString( &SystemName, &AnsiString, TRUE );

                if (!NT_SUCCESS(Status)) {

                    rc = FALSE;            }

                pSystemName = SystemName.Buffer;        }    }

        //    // Lookup the Account Sid and obtain its Unicode Account Name.    //

        if (rc) {

            rc = LookupAccountNameW(                 (LPCWSTR)pSystemName,                 (LPCWSTR)Unicode.Buffer,                 Sid,                 cbSid,                 WReferencedDomainName,                 cbReferencedDomainName,                 peUse                 );    }

        if ( SystemName.Buffer != NULL ) {

            RtlFreeUnicodeString( &SystemName );    }

        //    // Convert the returned null-terminated WCHAR string    // back to a null-terminated CHAR string.    //

        if (rc) {

            RtlInitUnicodeString( &TmpUnicode, WReferencedDomainName );        AnsiString.Buffer = ReferencedDomainName;

            //        // Watch for 16-bit overflow of MaximumLength        //

            if (cbInitReferencedDomainName <= (DWORD) 65535) {

                AnsiString.MaximumLength = (USHORT) cbInitReferencedDomainName;

            } else {

                AnsiString.MaximumLength = (USHORT) 65535;        }

            Status = RtlUnicodeStringToAnsiString( &AnsiString, &TmpUnicode, FALSE );

            if ( NT_SUCCESS( Status )) {

                ReferencedDomainName[AnsiString.Length] = 0;

            } else {

                rc = FALSE;        }    }

        if ( WReferencedDomainName != NULL) {

            LocalFree( WReferencedDomainName );    }

        if (Unicode.Buffer != NULL) {

            RtlFreeUnicodeString(&Unicode);    }

        if (!NT_SUCCESS(Status)) {

            BaseSetLastNTError( Status );    }

        return( rc );}

     

    BOOLAPIENTRYLookupAccountNameW(    LPCWSTR lpSystemName,    LPCWSTR lpAccountName,    PSID Sid,    LPDWORD cbSid,    LPWSTR ReferencedDomainName,    LPDWORD cbReferencedDomainName,    PSID_NAME_USE peUse    )

    /*++

    Routine Description:

        Translates a passed name into an account SID.  It will also return    the name and SID of the first domain in which this name was found.

    Arguments:

        lpSystemName - Supplies the name of the system at which the lookup        is to be performed.  If the null string is provided, the local        system is assumed.

        lpAccountName - Supplies the account name.

        Sid - Returns the SID corresponding to the passed account name.

        cbSid - Supplies the size of the buffer passed in for Sid.  If        the buffer size is not big enough, this parameter will        return the size necessary to hold the output Sid.

        ReferencedDomainName - Returns the name of the domain in which the        name was found.

        cbReferencedDomainName - Supplies the size (in Wide characters) of the        ReferencedDomainName buffer.  If the buffer size is not large        enough, this parameter will return the size necessary to hold        the null-terminated output domain name.  If the buffer size is        large enough, tis parameter will return the size (in Ansi characters,        excluding the terminating null) of the Referenced Domain name.

        peUse - Returns an enumerated type inidicating the type of the        account.

    Return Value:

        BOOL - TRUE is returned if successful, else FALSE.

    --*/

    {    SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;    OBJECT_ATTRIBUTES ObjectAttributes;    LSA_HANDLE PolicyHandle;    NTSTATUS Status;    NTSTATUS TmpStatus;    UNICODE_STRING Name;    PLSA_REFERENCED_DOMAIN_LIST ReferencedDomains = NULL;    PLSA_TRANSLATED_SID TranslatedSid = NULL;    PSID ReturnedDomainSid;    UCHAR nSubAuthorities;    UNICODE_STRING TmpString;    DWORD ReturnedDomainNameSize;    DWORD SidLengthRequired;    BOOL Rc;    UNICODE_STRING SystemName;    PUNICODE_STRING pSystemName = NULL;

        SecurityQualityOfService.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);    SecurityQualityOfService.ImpersonationLevel = SecurityImpersonation;    SecurityQualityOfService.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;    SecurityQualityOfService.EffectiveOnly = FALSE;

        //    // Set up the object attributes prior to opening the LSA.    //

        InitializeObjectAttributes(        &ObjectAttributes,        NULL,        0L,        NULL,        NULL        );

        //    // The InitializeObjectAttributes macro presently stores NULL for    // the SecurityQualityOfService field, so we must manually copy that    // structure for now.    //

        ObjectAttributes.SecurityQualityOfService = &SecurityQualityOfService;

        if ( ARGUMENT_PRESENT( lpSystemName )) {        RtlInitUnicodeString( &SystemName, lpSystemName );        pSystemName = &SystemName;    }

        //    // Open the LSA Policy Database for the target system.  This is the    // starting point for the Name Lookup operation.    //

        Status = LsaOpenPolicy(                 pSystemName,                 &ObjectAttributes,                 POLICY_LOOKUP_NAMES,                 &PolicyHandle                 );

        if ( !NT_SUCCESS( Status )) {

            BaseSetLastNTError( Status );        return( FALSE );    }

        RtlInitUnicodeString( &Name, lpAccountName );

        //    // Attempt to translate the Name to a Sid.    //

        Status = LsaLookupNames(                 PolicyHandle,                 1,                 &Name,                 &ReferencedDomains,                 &TranslatedSid                 );

        //    // Close the Policy Handle,  which is not needed after here.    //

        TmpStatus = LsaClose( PolicyHandle );    ASSERT( NT_SUCCESS( TmpStatus ));

        //    // If an error was returned, check specifically for STATUS_NONE_MAPPED.    // In this case, we may need to dispose of the returned Referenced Domain    // List and Translated Sid structures.  For all other errors,    // LsaLookupNames() frees these structures prior to exit.    //

        if ( !NT_SUCCESS( Status )) {

            if (Status == STATUS_NONE_MAPPED) {

                if (ReferencedDomains != NULL) {

                    TmpStatus = LsaFreeMemory( ReferencedDomains );                ASSERT( NT_SUCCESS( TmpStatus ));            }

                if (TranslatedSid != NULL) {

                    TmpStatus = LsaFreeMemory( TranslatedSid );                ASSERT( NT_SUCCESS( TmpStatus ));            }        }

            BaseSetLastNTError( Status );        return( FALSE );    }

        //    // The Name was successfully translated.  There should be exactly    // one Referenced Domain and its DomainIndex should be zero.    //

        ASSERT ( TranslatedSid->DomainIndex == 0 );    ASSERT ( ReferencedDomains != NULL);    ASSERT ( ReferencedDomains->Domains != NULL );

        //    // Calculate the lengths of the returned Sid and Domain Name (in Wide    // Characters, excluding null).    //

        ReturnedDomainNameSize =        (ReferencedDomains->Domains->Name.Length / sizeof(WCHAR));    ReturnedDomainSid = ReferencedDomains->Domains[ TranslatedSid->DomainIndex ].Sid;    nSubAuthorities = (*GetSidSubAuthorityCount( ReturnedDomainSid )) + (UCHAR)1;    SidLengthRequired = GetSidLengthRequired( nSubAuthorities );

        //    // Check if buffer sizes are too small.  For the returned domain,    // the size in Wide characters provided must allow for the null    // terminator that will be appended to the returned name.    //

        if ( (SidLengthRequired > *cbSid) ||         (ReturnedDomainNameSize + 1 > *cbReferencedDomainName)       ) {

            //        // One or both buffers are too small.  Return sizes required for        // both buffers.        //

            *cbSid = SidLengthRequired;        *cbReferencedDomainName = ReturnedDomainNameSize + 1;        BaseSetLastNTError( STATUS_BUFFER_TOO_SMALL );        Rc = FALSE;

        } else {

            //        // The provided buffers are large enough.  Build the SID in the        // return buffer by combining the Domain Sid returned by        // LsaLookupNames() with the Relative Id returned.  The final SID        // will have one more SubAuthority than the Domain Sid.        //

            CopySid( *cbSid, Sid, ReturnedDomainSid );        *GetSidSubAuthorityCount( Sid ) = nSubAuthorities;        *GetSidSubAuthority( Sid, (DWORD)(nSubAuthorities - 1) ) = TranslatedSid->RelativeId;

            //        // Copy the Domain Name into the return buffer and NULL terminate it.        //

            TmpString.Buffer = ReferencedDomainName;        TmpString.Length = 0;

            //        // Watch for overflow of 16-bit name length        //

            if (*cbReferencedDomainName < (DWORD) 32767) {

                TmpString.MaximumLength = (USHORT)((*cbReferencedDomainName) * sizeof(WCHAR));

            } else {

                TmpString.MaximumLength = (USHORT) 65534;        }

            RtlCopyUnicodeString( &TmpString, &ReferencedDomains->Domains->Name );

            TmpString.Buffer[TmpString.Length/sizeof(WCHAR)] = (WCHAR) 0;

            //        // Copy the Sid Use field.        //

            *peUse = TranslatedSid->Use;

            //        // Return the size (in Wide Characters, excluding the terminating        // null) of the returned Referenced Domain Name.        //

            *cbReferencedDomainName = ReturnedDomainNameSize;

            Rc = TRUE;    }

        //    // If necessary, free the structures returned by the LsaLookupNames()    // function.    //

        if (ReferencedDomains !=  NULL) {

            Status = LsaFreeMemory( ReferencedDomains );        ASSERT( NT_SUCCESS( Status ));    }

        if (TranslatedSid != NULL) {

            Status = LsaFreeMemory( TranslatedSid );        ASSERT( NT_SUCCESS( Status ));    }

        return( Rc );}

    BOOLAPIENTRYLookupAccountSidA(    LPCSTR lpSystemName,    PSID lpSid,    LPSTR lpName,    LPDWORD cbName,    LPSTR lpReferencedDomainName,    LPDWORD cbReferencedDomainName,    PSID_NAME_USE peUse    )/*++

    Routine Description:

        ANSI Thunk to LookupAccountSidW

    Arguments:

        lpSystemName - Supplies the name of the system at which the lookup        is to be performed.  If the null string is provided, the local        system is assumed.

        lpSid - Supplies the account Sid.

        lpName - Returns the name corresponding to the passed account SID.

        cbName - Supplies the size (in Ansi characters) of the buffer passed in for        lpName.  This size must allow one character for the null terminator        that will be appended to the returned name.  If the buffer size is not        large enough, this parameter will return the size necessary to hold        the null-terminated output name.  If the buffer size is large enough,        this parameter will return the size (in Ansi characters, excluding        the null terminator) of the name returned.

        lpReferencedDomainName - Returns the name of the domain in which the        name was found.

        cbReferencedDomainName - Supplies the size (in Ansi characters) of the        ReferencedDomainName buffer.  This size must allow one charcter for the        null terminator that will be appended to the returned name.  If the        buffer size is not large enough, this parameter will return the size        necessary to hold the output null-terminated domain name.  If the        buffer size is large enough, the size of the returned name, excluding        the terminating null will be returned.

        peUse - Returns an enumerated type indicating the type of the        account.

    Return Value:

        BOOL - TRUE if successful, else FALSE.

    --*/

    {    NTSTATUS Status;    LPWSTR WName = NULL;    LPWSTR WReferencedDomainName = NULL;    BOOL BoolStatus;    ANSI_STRING AnsiString;    UNICODE_STRING UnicodeString;    UNICODE_STRING SystemName;    PWSTR pSystemName = NULL;    DWORD cbInitName, cbInitReferencedDomainName;

        //    // Save the original buffer sizes specified for the returned account Name    // and Referenced Domain Name.    //

        cbInitName = *cbName;    cbInitReferencedDomainName = *cbReferencedDomainName;

        //    // Construct temporary buffers for the Name and Domain information    // that are twice the size of those passed in to adjust for the    // intermediate conversion to WCHAR strings.    //

        if ( *cbName > 0 ) {        WName = LocalAlloc( LMEM_FIXED, (*cbName) * sizeof(WCHAR));    }

        if ( *cbReferencedDomainName > 0 ) {        WReferencedDomainName =            LocalAlloc( LMEM_FIXED, (*cbReferencedDomainName) * sizeof(WCHAR));    }

        if ( ARGUMENT_PRESENT( lpSystemName ) ) {

            RtlInitAnsiString( &AnsiString, lpSystemName );        RtlAnsiStringToUnicodeString( &SystemName, &AnsiString, TRUE );        pSystemName = SystemName.Buffer;    }

        BoolStatus = LookupAccountSidW(                     (LPCWSTR)pSystemName,                     lpSid,                     WName,                     cbName,                     WReferencedDomainName,                     cbReferencedDomainName,                     peUse                     );

        if ( ARGUMENT_PRESENT( lpSystemName ) ) {        RtlFreeUnicodeString( &SystemName );    }

        if ( BoolStatus ) {

            //        // Copy the Name and DomainName information into the passed CHAR        // buffers.        //

            if ( ARGUMENT_PRESENT(lpName) ) {

                AnsiString.Buffer = lpName;

                //            // Watch for 16-bit overflow on buffer size.  Clamp size to            // 16 bits if necessary.            //

                if (cbInitName <= (DWORD) 65535) {

                    AnsiString.MaximumLength = (USHORT) cbInitName;

                } else {

                    AnsiString.MaximumLength = (USHORT) 65535;            }

                RtlInitUnicodeString( &UnicodeString, WName );            Status = RtlUnicodeStringToAnsiString( &AnsiString,                                                   &UnicodeString,                                                   FALSE );            ASSERT(NT_SUCCESS(Status));            AnsiString.Buffer[AnsiString.Length] = 0;        }

            if ( ARGUMENT_PRESENT(lpReferencedDomainName) ) {

                AnsiString.Buffer = lpReferencedDomainName;

                //            // Watch for 16-bit overflow on buffer size.  Clamp size to            // 16 bits if necessary.            //

                if (cbInitReferencedDomainName <= (DWORD) 65535) {

                    AnsiString.MaximumLength = (USHORT) cbInitReferencedDomainName;

                } else {

                    AnsiString.MaximumLength = (USHORT) 65535;            }

                RtlInitUnicodeString( &UnicodeString, WReferencedDomainName );            Status = RtlUnicodeStringToAnsiString( &AnsiString,                                                   &UnicodeString,                                                   FALSE );            ASSERT(NT_SUCCESS(Status));            AnsiString.Buffer[AnsiString.Length] = 0;        }

        }

        if (ARGUMENT_PRESENT(WName)) {        LocalFree( WName );    }    if (ARGUMENT_PRESENT(WReferencedDomainName)) {        LocalFree( WReferencedDomainName );    }

        return( BoolStatus );}

     

    BOOLAPIENTRYLookupAccountSidW(    LPCWSTR lpSystemName,    PSID lpSid,    LPWSTR lpName,    LPDWORD cbName,    LPWSTR lpReferencedDomainName,    LPDWORD cbReferencedDomainName,    PSID_NAME_USE peUse    )

    /*++

    Routine Description:

        Translates a passed SID into an account name.  It will also return    the name and SID of the first domain in which this SID was found.

    Arguments:

        lpSystemName - Supplies the name of the system at which the lookup        is to be performed.  If the null string is provided, the local        system is assumed.

        lpSid - Supplies the account Sid.

        lpName - Returns the name corresponding to the passed account SID.

        cbName - Supplies the size (in Wide characters) of the buffer passed in for        lpName.  This size must allow one character for the null terminator        that will be appended to the returned name.  If the buffer size is not        large enough, this parameter will return the size necessary to hold        the null-terminated output name.  If the buffer size is large enough,        this parameter will return the size (in Ansi characters, excluding        the null terminator) of the name returned.

        lpReferencedDomainName - Returns the name of the domain in which the        name was found.

        cbReferencedDomainName - Supplies the size (in Wide characters) of the        ReferencedDomainName buffer.  This size must allow one charcter for the        null terminator that will be appended to the returned name.  If the        buffer size is not large enough, this parameter will return the size        necessary to hold the output null-terminated domain name.  If the        buffer size is large enough, the size of the returned name, excluding        the terminating null will be returned.

        peUse - Returns an enumerated type inidicating the type of the        account.

    Return Value:

        BOOL - TRUE if successful, else FALSE.

    --*/

    {    PLSA_TRANSLATED_NAME Names;    OBJECT_ATTRIBUTES ObjectAttributes;    LSA_HANDLE PolicyHandle;    PLSA_REFERENCED_DOMAIN_LIST ReferencedDomains;    DWORD ReturnedDomainNameSize;    DWORD ReturnedNameSize;    SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;    NTSTATUS Status;    UNICODE_STRING TmpString;    NTSTATUS TmpStatus;    UNICODE_STRING SystemName;    PUNICODE_STRING pSystemName = NULL;    BOOLEAN Rc = FALSE;

        SecurityQualityOfService.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);    SecurityQualityOfService.ImpersonationLevel = SecurityImpersonation;    SecurityQualityOfService.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;    SecurityQualityOfService.EffectiveOnly = FALSE;

        //    // Set up the object attributes prior to opening the LSA.    //

        InitializeObjectAttributes(        &ObjectAttributes,        NULL,        0L,        NULL,        NULL        );

        //    // The InitializeObjectAttributes macro presently stores NULL for    // the SecurityQualityOfService field, so we must manually copy that    // structure for now.    //

        ObjectAttributes.SecurityQualityOfService = &SecurityQualityOfService;

        if ( ARGUMENT_PRESENT( lpSystemName )) {        RtlInitUnicodeString( &SystemName, lpSystemName );        pSystemName = &SystemName;    }

        Status = LsaOpenPolicy(                 pSystemName,                 &ObjectAttributes,                 POLICY_LOOKUP_NAMES,                 &PolicyHandle                 );

        if ( !NT_SUCCESS( Status )) {

            BaseSetLastNTError( Status );        return( FALSE );    }

        Status = LsaLookupSids(                 PolicyHandle,                 1,                 &lpSid,                 &ReferencedDomains,                 &Names                 );

        TmpStatus = LsaClose( PolicyHandle );

        if (!NT_SUCCESS( TmpStatus )) {        RpcSsDestroyClientContext( &PolicyHandle );    }

        //    // If an error was returned, check specifically for STATUS_NONE_MAPPED.    // In this case, we may need to dispose of the returned Referenced Domain    // List and Names structures.  For all other errors, LsaLookupSids()    // frees these structures prior to exit.    //

        if ( !NT_SUCCESS( Status )) {

            if (Status == STATUS_NONE_MAPPED) {

                if (ReferencedDomains != NULL) {

                    TmpStatus = LsaFreeMemory( ReferencedDomains );                ASSERT( NT_SUCCESS( TmpStatus ));            }

                if (Names != NULL) {

                    TmpStatus = LsaFreeMemory( Names );                ASSERT( NT_SUCCESS( TmpStatus ));            }        }

            BaseSetLastNTError( Status );        return( FALSE );    }

        //    // The Sid was successfully translated.  There should be exactly    // one Referenced Domain and its DomainIndex should be zero.    //

        ReturnedNameSize = (Names->Name.Length / sizeof(WCHAR));

        ASSERT(Names->DomainIndex == 0);    ASSERT(ReferencedDomains != NULL);    ASSERT(ReferencedDomains->Domains != NULL);    ReturnedDomainNameSize = (ReferencedDomains->Domains->Name.Length / sizeof(WCHAR));

        //    // Check if buffer sizes  for the Name and Referenced Domain Name are too    // small.  The sizes in Wide characters provided must allow for the null    // terminator that will be appended to the returned names.    //

        if ((ReturnedNameSize + 1 > *cbName) ||        (ReturnedDomainNameSize + 1 > *cbReferencedDomainName)) {

            //        // One or both buffers are too small.  Return sizes required for        // both buffers, allowing one character for the null terminator.        //

            *cbReferencedDomainName = ReturnedDomainNameSize + 1;        *cbName = ReturnedNameSize + 1;        BaseSetLastNTError( STATUS_BUFFER_TOO_SMALL );        Rc = FALSE;

        } else {

            //        // Both buffers are of sufficient size.  Copy in the Name        // information and add NULL terminators.        //

            TmpString.Buffer = lpName;        TmpString.Length = 0;

            //        // Watch for 16-bit overflow on buffer size.  Clamp size to        // 16 bits if necessary.        //

            if (*cbName <= 32766) {

                TmpString.MaximumLength = (USHORT)((*cbName) * sizeof(WCHAR));

            } else {

                TmpString.MaximumLength = (USHORT) 65532;        }

            if ((*cbName) > 0) {

                RtlCopyUnicodeString( &TmpString, &Names->Name );            TmpString.Buffer[TmpString.Length/sizeof(WCHAR)] = (WCHAR) 0;        }

            //        // Copy in the Referenced Domain information.        //

            TmpString.Buffer = lpReferencedDomainName;        TmpString.Length = 0;

            //        // Watch for 16-bit overflow on buffer size.  Clamp size to        // 16 bits if necessary.        //

            if (*cbReferencedDomainName <= 32767) {

                TmpString.MaximumLength = (USHORT)((*cbReferencedDomainName) * sizeof(WCHAR));

            } else {

                TmpString.MaximumLength = (USHORT) 65534;        }

            RtlCopyUnicodeString( &TmpString, &ReferencedDomains->Domains->Name );        TmpString.Buffer[TmpString.Length/sizeof(WCHAR)] = (WCHAR) 0;

            //        // Return the sizes (in Wide Characters, excluding the terminating        // null) of the name and domain name.        //

            *cbReferencedDomainName = ReturnedDomainNameSize;        *cbName = ReturnedNameSize;

            // Copy in the Use field.        //

            *peUse = Names->Use;        Rc = TRUE;    }

        //    // If necessary, free output buffers returned by LsaLookupSids    //

        if (Names != NULL) {

            Status = LsaFreeMemory( Names );        ASSERT( NT_SUCCESS( Status ));    }

        if (ReferencedDomains != NULL) {

            Status = LsaFreeMemory( ReferencedDomains );        ASSERT( NT_SUCCESS( Status ));    }

        return(Rc);}

    BOOLAPIENTRYLookupPrivilegeValueA(    LPCSTR lpSystemName,    LPCSTR lpName,    PLUID lpLuid    )/*++

    Routine Description:

        ANSI Thunk to LookupPrivilegeValueW().

    Arguments:

    Return Value:

    --*/{    NTSTATUS Status;    UNICODE_STRING USystemName, UName;    ANSI_STRING ASystemName, AName;    BOOL bool;

        RtlInitAnsiString( &ASystemName, lpSystemName );    RtlInitAnsiString( &AName, lpName );

        USystemName.Buffer = NULL;    UName.Buffer = NULL;

        Status = RtlAnsiStringToUnicodeString( &USystemName, &ASystemName, TRUE );    if (NT_SUCCESS(Status)) {

            Status = RtlAnsiStringToUnicodeString( &UName, &AName, TRUE );        if (NT_SUCCESS(Status)) {

                bool = LookupPrivilegeValueW( (LPCWSTR)USystemName.Buffer,                                          (LPCWSTR)UName.Buffer,                                          lpLuid                                          );

                RtlFreeUnicodeString( &UName );        }

            RtlFreeUnicodeString( &USystemName );    }

        if (!NT_SUCCESS(Status)) {

            BaseSetLastNTError( Status );        return( FALSE );

        }

        return(bool);

    } BOOLAPIENTRYLookupPrivilegeValueW(    LPCWSTR lpSystemName,    LPCWSTR lpName,    PLUID  lpLuid    )

    /*++

    Routine Description:

        This function retrieves the value used on the target system    to locally represent the specified privilege.  The privilege    is specified by programmatic name.

    Arguments:

        lpSystemName - Supplies the name of the system at which the lookup        is to be performed.  If the null string is provided, the local        system is assumed.

        lpName - provides the privilege's programmatic name.

        lpLuid - Receives the locally unique ID the privilege is known by on the        target machine.

    Return Value:

     

    --*/{    NTSTATUS                    Status,                                TmpStatus;

        LSA_HANDLE                  PolicyHandle;

        OBJECT_ATTRIBUTES           ObjectAttributes;

        SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;

        UNICODE_STRING              USystemName,                                UName;

        PUNICODE_STRING             SystemName = NULL;

        SecurityQualityOfService.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);    SecurityQualityOfService.ImpersonationLevel = SecurityImpersonation;    SecurityQualityOfService.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;    SecurityQualityOfService.EffectiveOnly = FALSE;

        //    // Set up the object attributes prior to opening the LSA.    //

        InitializeObjectAttributes( &ObjectAttributes, NULL, 0L, NULL, NULL );    ObjectAttributes.SecurityQualityOfService = &SecurityQualityOfService;

        if ( ARGUMENT_PRESENT( lpSystemName )) {        RtlInitUnicodeString( &USystemName, lpSystemName );        SystemName = &USystemName;    }

        Status = LsaOpenPolicy(                 SystemName,                 &ObjectAttributes,                 POLICY_LOOKUP_NAMES,                 &PolicyHandle                 );

        if ( !NT_SUCCESS( Status )) {        BaseSetLastNTError( Status );        return( FALSE );    }

     

        RtlInitUnicodeString( &UName, lpName );    Status = LsaLookupPrivilegeValue( PolicyHandle, &UName, lpLuid );

        TmpStatus = LsaClose( PolicyHandle );    ASSERT( NT_SUCCESS( TmpStatus ));

        if ( !NT_SUCCESS( Status )) {        BaseSetLastNTError( Status );        return( FALSE );    }

        return(TRUE);}

    BOOLAPIENTRYLookupPrivilegeNameA(    LPCSTR   lpSystemName,    PLUID   lpLuid,    LPSTR   lpName,    LPDWORD cchName    )/*++

    Routine Description:

        ANSI Thunk to LookupPrivilegeValueW().

    Arguments:

    Return Value:

    --*/{    NTSTATUS       Status;

        ANSI_STRING    AnsiName;    LPWSTR         UnicodeBuffer;    UNICODE_STRING UnicodeString;

        ANSI_STRING    AnsiSystemName;    UNICODE_STRING UnicodeSystemName;    DWORD          LengthRequired;

        //    // Convert the passed SystemName to Unicode.  Let the Rtl function    // allocate the memory we need.    //

        RtlInitAnsiString( &AnsiSystemName, lpSystemName );    Status = RtlAnsiStringToUnicodeString( &UnicodeSystemName, &AnsiSystemName, TRUE );

        if (!NT_SUCCESS( Status )) {

            BaseSetLastNTError( Status );        return( FALSE );    }

        //    // Make sure we don't exceed the limits of a unicode string.    //

        if (*cchName > 0xFFFC) {        *cchName = 0xFFFC;    }

        UnicodeBuffer = RtlAllocateHeap( RtlProcessHeap(), 0, *cchName * sizeof(WCHAR) );

        if (UnicodeBuffer == NULL) {

            RtlFreeUnicodeString( &UnicodeSystemName );        BaseSetLastNTError( STATUS_NO_MEMORY );        return( FALSE );    }

        //    // Don't pass in cchName, since it will be overwritten by LookupPrivilegeNameW,    // and we need it later.    //

        LengthRequired = *cchName;

        if (!LookupPrivilegeNameW( (LPCWSTR)UnicodeSystemName.Buffer,                               lpLuid,                               UnicodeBuffer,                               &LengthRequired                               )) {

            RtlFreeHeap( RtlProcessHeap(), 0, UnicodeBuffer );        RtlFreeUnicodeString( &UnicodeSystemName );        *cchName = LengthRequired;        return(FALSE);    }

        //    // Now convert back to ANSI for the caller    //

        RtlInitUnicodeString(&UnicodeString, UnicodeBuffer);

        AnsiName.Buffer = lpName;    AnsiName.Length = 0;    AnsiName.MaximumLength = (USHORT)*cchName;

        Status = RtlUnicodeStringToAnsiString(&AnsiName, &UnicodeString, FALSE);

        ASSERT( NT_SUCCESS( Status ));

        *cchName = AnsiName.Length;

        RtlFreeHeap( RtlProcessHeap(), 0, UnicodeBuffer );    RtlFreeUnicodeString( &UnicodeSystemName );

        return(TRUE);}

    BOOLAPIENTRYLookupPrivilegeNameW(    LPCWSTR  lpSystemName,    PLUID   lpLuid,    LPWSTR  lpName,    LPDWORD cchName    )/*++

    Routine Description:

        This function returns the programmatic name corresponding to    the privilege represented on the target system by the provided    LUID.

    Arguments:

        lpSystemName - Supplies the name of the system at which the lookup        is to be performed.  If the null string is provided, the local        system is assumed.

        lpLuid - is the locally unique ID the privilege is known by on the        target machine.

        lpName - Receives the privilege's programmatic name.

        cchName - indicates how large the buffer is (in characters).  This        count does not include the null-terminator that is added at the        end of the string.

     

    Return Value:

     

    --*/{    NTSTATUS                    Status,                                TmpStatus;    LSA_HANDLE                  PolicyHandle;    OBJECT_ATTRIBUTES           ObjectAttributes;    SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;    UNICODE_STRING              USystemName;    PUNICODE_STRING             SystemName,                                UName;

        SecurityQualityOfService.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);    SecurityQualityOfService.ImpersonationLevel = SecurityImpersonation;    SecurityQualityOfService.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;    SecurityQualityOfService.EffectiveOnly = FALSE;

        //    // Set up the object attributes prior to opening the LSA.    //

        InitializeObjectAttributes( &ObjectAttributes, NULL, 0L, NULL, NULL );    ObjectAttributes.SecurityQualityOfService = &SecurityQualityOfService;

        SystemName = NULL;    if ( ARGUMENT_PRESENT( lpSystemName )) {        RtlInitUnicodeString( &USystemName, lpSystemName );        SystemName = &USystemName;    }

        Status = LsaOpenPolicy(                 SystemName,                 &ObjectAttributes,                 POLICY_LOOKUP_NAMES,                 &PolicyHandle                 );

        if ( !NT_SUCCESS( Status )) {        BaseSetLastNTError( Status );        return( FALSE );    }

        UName = NULL;    Status = LsaLookupPrivilegeName( PolicyHandle,lpLuid, &UName );

        if (NT_SUCCESS(Status) ) {

            if ((DWORD)UName->Length + sizeof( WCHAR) > (*cchName) * sizeof( WCHAR )) {            Status = STATUS_BUFFER_TOO_SMALL;            (*cchName) = ( UName->Length + sizeof( WCHAR) ) / sizeof( WCHAR );

            } else {

                RtlMoveMemory( lpName, UName->Buffer, UName->Length );            lpName[UName->Length/sizeof(WCHAR)] = 0;  // NULL terminate it            (*cchName) = UName->Length / sizeof( WCHAR );        }

            LsaFreeMemory( UName->Buffer );        LsaFreeMemory( UName );    }

        TmpStatus = LsaClose( PolicyHandle );    ASSERT( NT_SUCCESS( TmpStatus ));

        if ( !NT_SUCCESS( Status )) {        BaseSetLastNTError( Status );        return( FALSE );    }

        return(TRUE);}

    BOOLAPIENTRYLookupPrivilegeDisplayNameA(    LPCSTR   lpSystemName,    LPCSTR   lpName,    LPSTR   lpDisplayName,    LPDWORD cchDisplayName,    LPDWORD lpLanguageId    )

    /*++

    Routine Description:

        ANSI Thunk to LookupPrivilegeValueW().

    Arguments:

    Return Value:

    --*/{    NTSTATUS                Status;

        UNICODE_STRING          UnicodeSystemName;    UNICODE_STRING          UnicodeString;    UNICODE_STRING          UnicodeName;

        ANSI_STRING             AnsiSystemName;    ANSI_STRING             AnsiDisplayName;    ANSI_STRING             AnsiName;

        LPWSTR                  UnicodeBuffer;    DWORD                   RequiredLength;

        RtlInitAnsiString( &AnsiSystemName, lpSystemName );    Status = RtlAnsiStringToUnicodeString( &UnicodeSystemName, &AnsiSystemName, TRUE );

        if (!NT_SUCCESS( Status )) {

            BaseSetLastNTError( Status );        return( FALSE );    }

        //    // Make sure we don't exceed that limits of a unicode string.    //

        if (*cchDisplayName > 0xFFFC) {        *cchDisplayName = 0xFFFC;    }

        UnicodeBuffer =  RtlAllocateHeap( RtlProcessHeap(), 0, *cchDisplayName * sizeof(WCHAR));

        if (UnicodeBuffer == NULL) {

            RtlFreeUnicodeString( &UnicodeSystemName );        BaseSetLastNTError( STATUS_NO_MEMORY );        return( FALSE );    }

        RtlInitAnsiString( &AnsiName, lpName );    Status = RtlAnsiStringToUnicodeString( &UnicodeName, &AnsiName, TRUE );

        if (!NT_SUCCESS( Status )) {

            RtlFreeUnicodeString( &UnicodeSystemName );        RtlFreeHeap( RtlProcessHeap(), 0, UnicodeBuffer );        BaseSetLastNTError( Status );        return( FALSE );    }

        RequiredLength = *cchDisplayName;

        if (! LookupPrivilegeDisplayNameW( (LPCWSTR)UnicodeSystemName.Buffer,                                       (LPCWSTR)UnicodeName.Buffer,                                       UnicodeBuffer,                                       &RequiredLength,                                       lpLanguageId                                       )) {

            //        // No need to set last error here, we can assume the W routine did so.        //

            *cchDisplayName = RequiredLength;

            RtlFreeUnicodeString( &UnicodeSystemName );        RtlFreeUnicodeString( &UnicodeName );        RtlFreeHeap( RtlProcessHeap(), 0, UnicodeBuffer );        return( FALSE );    }

        //    // Now convert back to ANSI for the caller    //

        RtlInitUnicodeString( &UnicodeString, UnicodeBuffer );

        AnsiDisplayName.Buffer = lpDisplayName;    AnsiDisplayName.Length = 0;    AnsiDisplayName.MaximumLength = (USHORT)(*cchDisplayName);

        Status = RtlUnicodeStringToAnsiString( &AnsiDisplayName, &UnicodeString, FALSE );

        ASSERT( NT_SUCCESS( Status ));

        *cchDisplayName = AnsiDisplayName.Length;

        RtlFreeUnicodeString( &UnicodeSystemName );    RtlFreeUnicodeString( &UnicodeName );    RtlFreeHeap( RtlProcessHeap(), 0, UnicodeBuffer );

        return( TRUE );}

    BOOLAPIENTRYLookupPrivilegeDisplayNameW(    LPCWSTR  lpSystemName,    LPCWSTR  lpName,    LPWSTR  lpDisplayName,    LPDWORD cchDisplayName,    LPDWORD lpLanguageId    )

    /*++

    Routine Description:

        This function retrieves a displayable name representing the    specified privilege.

    Arguments:

        lpSystemName - Supplies the name of the system at which the lookup        is to be performed.  If the null string is provided, the local        system is assumed.

        lpName - provides the privilege's programmatic name.

        lpDisplayName - Receives the privilege's displayable name.

        cchDisplayName - indicates how large the buffer is (in characters).  This        count does not include the null-terminator that is added at the        end of the string.

        lpLanguageId - Receives the language of the returned displayable        name.

    Return Value:

    --*/

    {    NTSTATUS                    Status,                                TmpStatus;

        LSA_HANDLE                  PolicyHandle;

        OBJECT_ATTRIBUTES           ObjectAttributes;

        SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;

        UNICODE_STRING              USystemName,                                UName;

        PUNICODE_STRING             SystemName,                                UDisplayName;

        SHORT                       LanguageId;

        SecurityQualityOfService.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);    SecurityQualityOfService.ImpersonationLevel = SecurityImpersonation;    SecurityQualityOfService.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;    SecurityQualityOfService.EffectiveOnly = FALSE;

        //    // Set up the object attributes prior to opening the LSA.    //

        InitializeObjectAttributes( &ObjectAttributes, NULL, 0L, NULL, NULL );    ObjectAttributes.SecurityQualityOfService = &SecurityQualityOfService;

        SystemName = NULL;    if ( ARGUMENT_PRESENT( lpSystemName )) {        RtlInitUnicodeString( &USystemName, lpSystemName );        SystemName = &USystemName;    }

        Status = LsaOpenPolicy(                 SystemName,                 &ObjectAttributes,                 POLICY_LOOKUP_NAMES,                 &PolicyHandle                 );

        if ( !NT_SUCCESS( Status )) {        BaseSetLastNTError( Status );        return( FALSE );    }

        RtlInitUnicodeString( &UName, lpName );

        UDisplayName = NULL;    Status = LsaLookupPrivilegeDisplayName( PolicyHandle,                                            &UName,                                            &UDisplayName,                                            &LanguageId                                            );    (*lpLanguageId) = LanguageId;

        if (NT_SUCCESS(Status)) {

            if (UDisplayName->Length + sizeof(WCHAR) > (*cchDisplayName) * sizeof(WCHAR)) {            Status = STATUS_BUFFER_TOO_SMALL;            (*cchDisplayName) = (UDisplayName->Length + sizeof( WCHAR )) / sizeof( WCHAR );

            } else {

                RtlMoveMemory( lpDisplayName,                           UDisplayName->Buffer,                           UDisplayName->Length                           );            lpDisplayName[UDisplayName->Length/sizeof(WCHAR)] = 0;  // Null terminate it.            (*cchDisplayName) = UDisplayName->Length / sizeof( WCHAR );        }

            LsaFreeMemory( UDisplayName->Buffer );        LsaFreeMemory( UDisplayName );

        }    TmpStatus = LsaClose( PolicyHandle );    ASSERT( NT_SUCCESS( TmpStatus ));

        if ( !NT_SUCCESS( Status )) {        BaseSetLastNTError( Status );        return( FALSE );    }

        return(TRUE);}

    ///                                                                         ////               Private Routines                                          ////                                                                         ///

    VOIDSepFormatAccountSid(    PSID Sid,    LPWSTR OutputBuffer    ){    UCHAR Buffer[128];    UCHAR TmpBuffer[128];    ANSI_STRING AccountName;    UCHAR i;    ULONG Tmp;    UNICODE_STRING OutputString;    PISID iSid;    NTSTATUS Status;

        //    // Do everything as ANSI for the time being, and then    // convert to wide-char at the bottom.    //    // We need to do this until we have more complete c-runtime support    // for w-char strings.    //

        iSid = (PISID) Sid;

        OutputString.Buffer = OutputBuffer;    OutputString.MaximumLength = 127;

        Buffer[0] = 0;    TmpBuffer[0] = 0;

        AccountName.MaximumLength = 127;    AccountName.Length = (USHORT)((GetLengthSid( Sid ) > MAXUSHORT) ? MAXUSHORT : GetLengthSid( Sid ));    AccountName.Buffer = Buffer;

        sprintf(TmpBuffer, "S-%u-", (USHORT)iSid->Revision );    lstrcpy(Buffer, TmpBuffer);

        if (  (iSid->IdentifierAuthority.Value[0] != 0)  ||          (iSid->IdentifierAuthority.Value[1] != 0)     ){        sprintf(TmpBuffer, "0xhxhxhxhxhxhx",                    (USHORT)iSid->IdentifierAuthority.Value[0],                    (USHORT)iSid->IdentifierAuthority.Value[1],                    (USHORT)iSid->IdentifierAuthority.Value[2],                    (USHORT)iSid->IdentifierAuthority.Value[3],                    (USHORT)iSid->IdentifierAuthority.Value[4],                    (USHORT)iSid->IdentifierAuthority.Value[5] );        lstrcat(Buffer, TmpBuffer);    } else {        Tmp = (ULONG)iSid->IdentifierAuthority.Value[5]          +              (ULONG)(iSid->IdentifierAuthority.Value[4] <<  8)  +              (ULONG)(iSid->IdentifierAuthority.Value[3] << 16)  +              (ULONG)(iSid->IdentifierAuthority.Value[2] << 24);        sprintf(TmpBuffer, "%lu", Tmp);        lstrcat(Buffer, TmpBuffer);    }

        for (i=0;i<iSid->SubAuthorityCount ;i++ ) {        sprintf(TmpBuffer, "-%lu", iSid->SubAuthority[i]);        lstrcat(Buffer, TmpBuffer);    }

        Status = RtlAnsiStringToUnicodeString( &OutputString, &AccountName, FALSE );

        ASSERT( NT_SUCCESS( Status ));

        return;} 


    最新回复(0)