#include "stdafx.h" #include "acl.hxx" #include "dcomperm.h" #include "Sddl.h" // Constructor // CSecurityDescriptor::CSecurityDescriptor() { m_bSDValid = FALSE; // Initialize DAcl to NULL m_pDAcl = NULL; m_pOwner = NULL; m_pGroup = NULL; // Initialize SA m_SA.nLength = sizeof( SECURITY_ATTRIBUTES ); m_SA.lpSecurityDescriptor = &m_SD; m_SA.bInheritHandle = FALSE; // Do all the resetting logic in ResetSD ResetSD(); } // Desctructor // CSecurityDescriptor::~CSecurityDescriptor() { // Reset SD, so everything is freed ResetSD(); } // InitializeSD // // Intialize the SD, and either fail or succeeded. If it // is already initialized, then we NOP. This is so that // the user does not need to call initialize themselves, // we can do it automatically for them // BOOL CSecurityDescriptor::InitializeSD() { if ( !m_bSDValid ) { // At this point, nothing should have been done to the ACL, or // there is an error ASSERT( m_pDAcl == NULL ); // Not initalize yet, so lets do it. m_bSDValid = InitializeSecurityDescriptor( &m_SD, SECURITY_DESCRIPTOR_REVISION ) && SetSecurityDescriptorControl( &m_SD, SE_DACL_PROTECTED, SE_DACL_PROTECTED); } return m_bSDValid; } // SetDAcl // // Set the DAcl for the SD, and set the pDAcl internal pointer // BOOL CSecurityDescriptor::SetDAcl( PACL pAcl ) { BOOL bRet; // Try to set SD with correct DACL if ( pAcl ) { // Set Security Descriptor bRet = SetSecurityDescriptorDacl( &m_SD, TRUE, pAcl, FALSE ); } else { // Clear it since pAcl is NULL bRet = SetSecurityDescriptorDacl( &m_SD, FALSE, NULL, TRUE ); } if ( bRet ) { // If it was set correctly, then lets free the old pointer, // and set the new pointer accordingly if ( m_pDAcl ) { LocalFree( m_pDAcl ); } m_pDAcl = pAcl; } return bRet; } // SetOwner // // Set the owner of the SD // BOOL CSecurityDescriptor::SetOwner( PSID pSid ) { if ( !InitializeSD() ) { return FALSE; } if ( !SetSecurityDescriptorOwner( &m_SD, pSid, FALSE ) ) { // Failed to Set return FALSE; } m_pOwner = pSid; return TRUE; } // SetGroup // // Set the group for the SD // BOOL CSecurityDescriptor::SetGroup( PSID pSid ) { if ( !InitializeSD() ) { return FALSE; } if ( !SetSecurityDescriptorGroup( &m_SD, pSid, FALSE ) ) { // Failed to Set return FALSE; } m_pGroup = pSid; return TRUE; } // ResetSD // // Reset the SD by removing everything inside of it. Return it to // its original State. // If you want, you can call this in the begining, just to make sure the // initialization worked. // BOOL CSecurityDescriptor::ResetSD() { if ( !InitializeSD() ) { return FALSE; } // Initialize to ACL not inheritted m_bDAclIsInheritted = FALSE; if ( m_pOwner ) { FreeSid( m_pOwner ); m_pOwner = NULL; } if ( m_pGroup ) { FreeSid( m_pGroup ); m_pGroup = NULL; } return SetDAcl( NULL ); } // CreateAdminDAcl // // This is a wrapper function, that just creates an Admin DAcl. What // this means is that we create an ACL that ONLY allows // Administrators and Local System, and allow them FULL access // BOOL CSecurityDescriptor::CreateAdminDAcl( BOOL bIheritable ) { return AddAccessAcebyWellKnownID( CSecurityDescriptor::GROUP_ADMINISTRATORS, CSecurityDescriptor::ACCESS_FULL, TRUE, bIheritable ) && AddAccessAcebyWellKnownID( CSecurityDescriptor::USER_LOCALSYSTEM, CSecurityDescriptor::ACCESS_FULL, TRUE, bIheritable ); } // GetCurrentDAcl // // Return a ppointer to the current DAcl // PACL CSecurityDescriptor::GetCurrentDAcl() { return m_pDAcl; } // UpdateDACLwithNewACE // // Update the DACL with a new ACE. Based on the AccessMode, this can be used to: // 1) Add Deny or Allow Ace's // 2) Remove Ace's // BOOL CSecurityDescriptor::UpdateDACLwithNewACE( TRUSTEE_FORM TrusteeForm, LPTSTR szTrusteeName, DWORD dwAccess, ACCESS_MODE dwAccessMode, DWORD dwInheitance) { PACL pNewDacl = NULL; EXPLICIT_ACCESS ea; BOOL bRet = TRUE; if ( !InitializeSD() ) { // Count not initialize SD return FALSE; } ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS)); ea.grfAccessPermissions = dwAccess; ea.grfAccessMode = dwAccessMode; ea.grfInheritance = dwInheitance; ea.Trustee.TrusteeForm = TrusteeForm; ea.Trustee.ptstrName = szTrusteeName; if ( SetEntriesInAcl(1, &ea, GetCurrentDAcl(), &pNewDacl) != ERROR_SUCCESS ) { // Failed to Set Acl return FALSE; } if ( !SetDAcl( pNewDacl ) ) { // We could not set it, so lets free it, and fail LocalFree( pNewDacl ); bRet = FALSE; } return bRet; } // QueryEffectiveRightsForTrustee // // Query the effective rights for a Trustee // // Parameters: // dwTrustee - The trustee to query for // pAccessMask - [out] The effective AccessMask // // Return Values: // TRUE - Success // FALSE - Failure BOOL CSecurityDescriptor::QueryEffectiveRightsForTrustee( DWORD dwTrustee, PACCESS_MASK pAccessMask ) { PSID pSid; TRUSTEE Trustee; BOOL bRet; pSid = CreateWellKnowSid( dwTrustee ); if ( !pSid ) { // Failed to create sid, so fail return FALSE; } // Query Trustee information Trustee.pMultipleTrustee = NULL; Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; Trustee.TrusteeForm = TRUSTEE_IS_SID; Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; Trustee.ptstrName = (LPTSTR) pSid; bRet = GetEffectiveRightsFromAcl( GetCurrentDAcl(), &Trustee, pAccessMask ) == ERROR_SUCCESS; FreeSid( pSid ); return bRet; } // AddAccessAceByName // // Add either an Access Allowed or Access Denied ACE to this ACL // // Parameters: // szName - The name of the user or group to be added to the ACL // dwAccess - The access mask to be applied // bAllow - If TRUE then added Allow ACE, if FALSE, then add Deny ACE // bInherit - Should this be inherited by children // BOOL CSecurityDescriptor::AddAccessAcebyName( LPTSTR szName, DWORD dwAccess, BOOL bAllow /*= TRUE*/ , BOOL bInherit /*= FALSE*/ ) { return UpdateDACLwithNewACE( TRUSTEE_IS_NAME, // Trustee is a name szName, // Username/Group dwAccess, // Access bAllow ? SET_ACCESS: DENY_ACCESS, bInherit ? ( OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE ) : NO_INHERITANCE); } // AddAccessAcebyStringSid // // Add an Access ace to the SD by it's string SID // BOOL CSecurityDescriptor::AddAccessAcebyStringSid( LPTSTR szStringSid, DWORD dwAccess, BOOL bAllow /* = TRUE */ , BOOL bInherit /* = FALSE */ ) { PSID pSid; BOOL bRet; if ( !ConvertStringSidToSid( szStringSid, &pSid ) ) { // Failed to convert to String Sid return FALSE; } bRet = UpdateDACLwithNewACE( TRUSTEE_IS_SID, // Trustee is a name (LPTSTR) pSid, // SID dwAccess, // Access bAllow ? SET_ACCESS: DENY_ACCESS, bInherit ? ( OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE ) : NO_INHERITANCE); // Free the Sid that was returned LocalFree( pSid ); return bRet; } // RemoveAccessAcebyName // // Remove all DAcl's in our current DAcl for the particular name // specified // BOOL CSecurityDescriptor::RemoveAccessAcebyName( LPTSTR szName ,BOOL bInherit /*= FALSE*/ ) { BOOL bUserExisted = TRUE; DWORD dwReturn = ERROR_SUCCESS; if ( !m_pDAcl ) { // If there is no ACL, then we don'e have to worry about // removing this ACE for it. return TRUE; } while ( bUserExisted && ( dwReturn == ERROR_SUCCESS ) ) { dwReturn = RemovePrincipalFromACL( m_pDAcl, szName, &bUserExisted ); } return ( dwReturn == ERROR_SUCCESS ); } // AddAccessAcebyWellKnownID // // Add either an Access Allowed or Access Denied ACE to this ACL for a Well Know // User or Group // // Parameters: // dwID - The id of the User/Group to be added (taken from the const in this class) // dwAccess - The access mask to be applied // bAllow - If TRUE then added Allow ACE, if FALSE, then add Deny ACE // bInherit - Should this be inherited by children // BOOL CSecurityDescriptor::AddAccessAcebyWellKnownID( DWORD dwID, DWORD dwAccess, BOOL bAllow /*= TRUE*/ , BOOL bInherit /*= FALSE*/ ) { BOOL bRet = TRUE; PSID pSid; pSid = CreateWellKnowSid( dwID ); if ( !pSid ) { return FALSE; } bRet = UpdateDACLwithNewACE( TRUSTEE_IS_SID, // Trustee is a name (LPTSTR) pSid, // SID dwAccess, // Access bAllow ? SET_ACCESS: DENY_ACCESS, bInherit ? ( OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE ) : NO_INHERITANCE); FreeSid( pSid ); return bRet; } // SetOwnerbyWellKnownID // // Set the Ownder of the SD by Well Know ID // BOOL CSecurityDescriptor::SetOwnerbyWellKnownID( DWORD dwID ) { BOOL bRet = TRUE; PSID pSid; pSid = CreateWellKnowSid( dwID ); if ( !pSid ) { return FALSE; } bRet = SetOwner( pSid ); if ( !bRet ) { // Failed, so must set ourself FreeSid( pSid ); } return bRet; } // SetGroupbyWellKnownID // // Set the Group of the SD by Well Know ID // BOOL CSecurityDescriptor::SetGroupbyWellKnownID( DWORD dwID ) { BOOL bRet = TRUE; PSID pSid; pSid = CreateWellKnowSid( dwID ); if ( !pSid ) { return FALSE; } bRet = SetGroup( pSid ); if ( !bRet ) { // Failed, so must set ourself FreeSid( pSid ); } return bRet; } // QuerySD // // Query a pointer to the Security Descriptor // PSECURITY_DESCRIPTOR CSecurityDescriptor::QuerySD() { // We should not call this, before doing some work ASSERT( m_bSDValid ); if ( !m_bSDValid ) { // Return NULL, since the SD is not valid return NULL; } return &m_SD; } // QuerySA // // Query a pointer to the Security Attributes, created for this SD // PSECURITY_ATTRIBUTES CSecurityDescriptor::QuerySA() { // We should not call this, before doing some work ASSERT( m_bSDValid ); return &m_SA; } // CreateSidFromName // // Create a Sid for the user givem // /*BOOL CSecurityDescriptor::CreateSidFromName( LPTSTR szTrustee ) { } */ // CreateWellKnownSid // // Create a Well know sid, so that we can use it in the other functions // to change ACL's // PSID CSecurityDescriptor::CreateWellKnowSid( DWORD dwId ) { SID_IDENTIFIER_AUTHORITY SidIdentifierNTAuthority = SECURITY_NT_AUTHORITY; SID_IDENTIFIER_AUTHORITY SidIdentifierWORLDAuthority = SECURITY_WORLD_SID_AUTHORITY; PSID_IDENTIFIER_AUTHORITY pSidIdentifierAuthority; DWORD dwCount = 0; DWORD dwRID[8]; BOOL bRet = TRUE; PSID pSid = NULL; // Clear dwRID memset(&(dwRID[0]), 0, sizeof(dwRID)); switch ( dwId ) { case GROUP_ADMINISTRATORS: pSidIdentifierAuthority = &SidIdentifierNTAuthority; dwRID[dwCount++] = SECURITY_BUILTIN_DOMAIN_RID; dwRID[dwCount++] = DOMAIN_ALIAS_RID_ADMINS; break; case GROUP_USERS: pSidIdentifierAuthority = &SidIdentifierNTAuthority; dwRID[dwCount++] = SECURITY_BUILTIN_DOMAIN_RID; dwRID[dwCount++] = DOMAIN_ALIAS_RID_USERS; break; case USER_LOCALSYSTEM: pSidIdentifierAuthority = &SidIdentifierNTAuthority; dwRID[dwCount++] = SECURITY_LOCAL_SYSTEM_RID; break; case USER_LOCALSERVICE: pSidIdentifierAuthority = &SidIdentifierNTAuthority; dwRID[dwCount] = SECURITY_LOCAL_SERVICE_RID; break; case USER_NETWORKSERVICE: pSidIdentifierAuthority = &SidIdentifierNTAuthority; dwRID[dwCount++] = SECURITY_NETWORK_SERVICE_RID; break; case USER_EVERYONE: pSidIdentifierAuthority = &SidIdentifierWORLDAuthority; dwRID[dwCount++] = SECURITY_WORLD_RID; break; default: bRet = FALSE; } if ( bRet ) { bRet = AllocateAndInitializeSid( pSidIdentifierAuthority, (BYTE)dwCount, dwRID[0], dwRID[1], dwRID[2], dwRID[3], dwRID[4], dwRID[5], dwRID[6], dwRID[7], &pSid ); } if ( !bRet ) { if ( pSid ) { FreeSid( pSid ); } return NULL; } return pSid; } // SetSecurityInfoOnHandle // // Explicity set the SecurityInfo on the Handle Given // BOOL CSecurityDescriptor::SetSecurityInfoOnHandle( HANDLE hHandle, SE_OBJECT_TYPE ObjectType, BOOL bAllowInheritance ) { // At ths point our SD should be valid ASSERT( m_bSDValid ); if ( m_bDAclIsInheritted ) { // Even though they say not to use inheritance, we retrieved an ACL // which was inheritted. So if we don't set with inheritted, the // ACL will be different bAllowInheritance = TRUE; } return ( SetSecurityInfo( hHandle, // The Handle ObjectType, // Object type DACL_SECURITY_INFORMATION | ( bAllowInheritance ? UNPROTECTED_DACL_SECURITY_INFORMATION : PROTECTED_DACL_SECURITY_INFORMATION ), NULL, // Owner Sid NULL, // Group Sid GetCurrentDAcl(), // DAcl NULL ) == // SAcl ERROR_SUCCESS ); } // SetSecurityInfoonFile // // Explicity set the Security Info on a File // // (If you do not want it to fail on file not existing, call SetSecurityInfoonFiles) // BOOL CSecurityDescriptor::SetSecurityInfoOnFile( LPTSTR szFile, BOOL bAllowInheritance ) { HANDLE hFile; BOOL bRet; hFile = CreateFile( szFile, WRITE_DAC|READ_CONTROL, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, // No need for security, since it won't do what we want anyways OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS, NULL ); if ( hFile == INVALID_HANDLE_VALUE ) { // Failed to open File return FALSE; } bRet = SetSecurityInfoOnHandle( hFile, SE_FILE_OBJECT, bAllowInheritance ); CloseHandle( hFile ); return bRet; } // SetSecurityInfoonFiles // // Explicity set the Security Info on a Multiple Files // The regular wildcard semantics to specify the files (ie. metbase*.xml) // // Note: Use this function, instead of SetSecurityInfoonFile if you do not // want it to fail if the file does not exist. This will ignore such // errors. // BOOL CSecurityDescriptor::SetSecurityInfoOnFiles( LPTSTR szFile, BOOL bAllowInheritance ) { BOOL bRet = TRUE; HANDLE hFiles; WIN32_FIND_DATA fd; TSTR_PATH strFileName; TSTR_PATH strPath; LPTSTR szLastSlash; if ( !strPath.Copy( szFile ) ) { return FALSE; } szLastSlash = _tcsrchr( strPath.QueryStr(), _T('\\') ); if ( szLastSlash != NULL ) { // Lets find the path (ie. c:\foo\test* -> c:\foo, c:\foo\test -> c:\foo) *szLastSlash = '\0'; } hFiles = FindFirstFile( szFile, &fd ); if ( hFiles == INVALID_HANDLE_VALUE ) { if ( ( GetLastError() == ERROR_FILE_NOT_FOUND ) || ( GetLastError() == ERROR_PATH_NOT_FOUND ) || ( GetLastError() == ERROR_NO_MORE_FILES ) ) { // If this is the case, then there is nothing to acl // so return success return TRUE; } // Failed to find the first instance of the file return FALSE; } do { if ( ( _tcscmp( fd.cFileName, _T(".") ) == 0 ) || ( _tcscmp( fd.cFileName, _T("..") ) == 0 ) ) { // Ignore the . and .. dirs continue; } if ( !strFileName.Copy( strPath ) || !strFileName.PathAppend( fd.cFileName ) || !SetSecurityInfoOnFile( strFileName.QueryStr() , bAllowInheritance ) ) { // Failed to set ACL bRet = FALSE; } } while ( FindNextFile( hFiles, &fd ) ); FindClose( hFiles ); return ( bRet && ( GetLastError() == ERROR_NO_MORE_FILES ) ); } // DuplicateACL // // Take an ACL, and Duplicate it // // Note: This will NOT duplicate the inheritted items in the ACL // // Parameters: // pSourceAcl [in] - The ACL to Duplicate // pNewlyCreateAcl [out] - The ACL that has been created as a duplicated // NOTE: If we return TRUE, this must be free'd with LocalFree // Return Values: // FALSE - Failed to duplicate // TRUE - Success (don't forget to free) BOOL CSecurityDescriptor::DuplicateACL( PACL pSourceAcl, PACL *pNewlyCreateAcl ) { BOOL bRet = FALSE; PEXPLICIT_ACCESS pEA; ULONG lNumberofEntries; if ( GetExplicitEntriesFromAcl( pSourceAcl, &lNumberofEntries, &pEA ) == ERROR_SUCCESS ) { if ( SetEntriesInAcl( lNumberofEntries, pEA, NULL, pNewlyCreateAcl ) == ERROR_SUCCESS ) { if ( *pNewlyCreateAcl == NULL ) { // All the entries were inheritted, so create an empty ACL, instead // or returning NULL! *pNewlyCreateAcl = ( PACL ) LocalAlloc( LMEM_FIXED, sizeof(ACL) ); if ( *pNewlyCreateAcl && InitializeAcl( *pNewlyCreateAcl, sizeof(ACL) , ACL_REVISION ) ) { bRet = TRUE; } if ( !bRet && ( *pNewlyCreateAcl != NULL ) ) { // Free memory on failure LocalFree( *pNewlyCreateAcl ); *pNewlyCreateAcl = NULL; } } else { // Acl was created bRet = TRUE; } } LocalFree( pEA ); } return bRet; } // IsInerittedAcl // // Determines if the acl was inheritted by a parent? // // This is important, because when we duplicate an ACL, it does not // duplicate the inheritted ACE's, so when we set it, we must say to // inherit the ACE's from parent // // Parameters // pSourceAcl - The Acl to test. NULL is valid here. // // Return Values: // TRUE - It is inheritting from parent // FALSE - It is not inheritting from parent // BOOL CSecurityDescriptor::IsInherittedAcl( PACL pSourceAcl ) { BOOL bIsInheritted = FALSE; LPVOID pAce; ACE_HEADER *pAceHeader; DWORD dwCurrentAce = 0; if ( !pSourceAcl ) { // If a NULL Acl is specified, then it is not inheritted, // since it has nothing in it. return FALSE; } while ( !bIsInheritted && GetAce( pSourceAcl, dwCurrentAce, &pAce ) ) { dwCurrentAce++; pAceHeader = (ACE_HEADER *) pAce; if ( pAceHeader->AceFlags & INHERITED_ACE ) { // This ACE was inheritted, so mark it as such bIsInheritted = TRUE; } } return bIsInheritted; } // GetSecurityInfoOnHandle // // Retrieve the security Information for a particular Handle // BOOL CSecurityDescriptor::GetSecurityInfoOnHandle( HANDLE hHandle, SE_OBJECT_TYPE ObjectType ) { BOOL bRet; PACL pDAcl; PACL pNewDAcl = NULL; PSECURITY_DESCRIPTOR pSD; if ( !InitializeSD() ) { // Count not initialize SD return FALSE; } bRet = GetSecurityInfo( hHandle, // The Handle ObjectType, // Object type DACL_SECURITY_INFORMATION, // right now only retrieve security info NULL, // Owner Sid NULL, // Group Sid &pDAcl, // DAcl NULL, // SAcl &pSD ) == ERROR_SUCCESS; if ( bRet ) { // This duplication does not copy inherited ACL's, only those // explicity set on this item, thus we must make sure that the // set does inherit acl's bRet = DuplicateACL( pDAcl, &pNewDAcl ); if ( bRet && !SetDAcl( pNewDAcl ) ) { // Failed to set DAcl LocalFree( pNewDAcl); bRet = FALSE; } if ( bRet ) { // Since during the duplication, we lost the inheritted acl's // we must set that bit now m_bDAclIsInheritted = IsInherittedAcl( pDAcl ); } // Free the Sources Descriptor since we don't use it LocalFree(pSD); } return bRet; } BOOL CSecurityDescriptor::GetSecurityInfoOnFile( LPTSTR szFile ) { HANDLE hFile; BOOL bRet; hFile = CreateFile( szFile, READ_CONTROL, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, // No need for security, since it won't do what we want anyways OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS, NULL ); if ( hFile == INVALID_HANDLE_VALUE ) { // Failed to open File return FALSE; } bRet = GetSecurityInfoOnHandle( hFile, SE_FILE_OBJECT ); CloseHandle( hFile ); return bRet; } // DuplicateSD // // Duplicate the security descriptor that is send in, into // our class // BOOL CSecurityDescriptor::DuplicateSD( PSECURITY_DESCRIPTOR pSD ) { SECURITY_DESCRIPTOR_CONTROL sdc; PACL pOldAcl; PACL pNewAcl; BOOL bAclPresent; BOOL bAclDefaulted; DWORD dwVersion; if ( !InitializeSD() ) { // Count not initialize SD return FALSE; } if ( !GetSecurityDescriptorControl( pSD, &sdc, &dwVersion ) || !SetSecurityDescriptorControl( &m_SD, SE_DACL_AUTO_INHERIT_REQ | // Mask of bits to set SE_DACL_AUTO_INHERITED | SE_DACL_PROTECTED | SE_SACL_AUTO_INHERIT_REQ | SE_SACL_AUTO_INHERITED | SE_SACL_PROTECTED, sdc ) ) { // Failed to get current Security Descriptor Control, // or to set it return FALSE; } if ( !GetSecurityDescriptorDacl( &m_SD, &bAclPresent, &pOldAcl, &bAclDefaulted ) ) { // Failed to get acl from old SD return FALSE; } if ( bAclPresent ) { // If ACL is present, we must duplicate and set for current if ( !DuplicateACL( pOldAcl, &pNewAcl ) ) { // Failed to duplicate DACL return FALSE; } if ( !SetDAcl( pNewAcl ) ) { // Failed to set as current, so must delete pointer delete pNewAcl; return FALSE; } } return TRUE; } // CreateSelfRelativeSD // // Create a SelfRelative Source Descriptor // // Parameters: // pBuff - [in/out] Pointer to a BUFFER object as input. It is // filled with the contents of the SD, so it does // not have to be freed // pdwSize = [out] The length of the SD inside pBuff // BOOL CSecurityDescriptor::CreateSelfRelativeSD( BUFFER *pBuff, LPDWORD pdwSize ) { DWORD dwSize = 0; ASSERT( pdwSize != NULL ); ASSERT( pBuff != NULL ); if ( MakeSelfRelativeSD( &m_SD, NULL, &dwSize ) || !pBuff->Resize( dwSize ) ) { // Either MakeSelfRelative did not fail as we expected with // the size, or Resize failed return FALSE; } if ( !MakeSelfRelativeSD( &m_SD, (PSECURITY_DESCRIPTOR) pBuff->QueryPtr(), &dwSize ) ) { // Failed to make self relative return FALSE; } *pdwSize = dwSize; return TRUE; } // CreateDirectoryWithSA // // Create a Directory with a specific ACL. If the directory already exists, // then change the acl, and succeed. // BOOL CreateDirectoryWithSA( LPTSTR szPath, CSecurityDescriptor &pSD, BOOL bAllowInheritance ) { BOOL bRet; // Check if the directory exists if ( IsFileExist( szPath ) ) { // If it exists, then set ACL's on it bRet = pSD.SetSecurityInfoOnFile( szPath, bAllowInheritance ); } else { // Create Directory with ACL's we specified bRet = CreateDirectory( szPath, pSD.QuerySA() ); } return bRet; } // DoesFileSystemSupportACLs // // Does the File System Supplied here support ACLs // BOOL CSecurityDescriptor::DoesFileSystemSupportACLs( LPTSTR szPath, LPBOOL pbSupportAcls ) { TSTR_PATH strDrivePath; DWORD dwSystemFlags; ASSERT( szPath ); if ( !strDrivePath.Copy( szPath ) || !strDrivePath.PathAppend( _T("") ) || ( strDrivePath.QueryLen() < 3 ) ) { return FALSE; } // Null terminate drive *( strDrivePath.QueryStr() + 3 ) = _T('\0'); if ( !GetVolumeInformation( strDrivePath.QueryStr(), NULL, // Volume Name Buffer 0, // Size of Buffer NULL, // Serial Number Buffer NULL, // Max Component Lenght &dwSystemFlags, // System Flags NULL, // FS Type 0 ) ) { // Failed to do query return FALSE; } *pbSupportAcls = ( dwSystemFlags & FS_PERSISTENT_ACLS ) != 0; return TRUE; }