|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995.
//
// File: libmain.cxx
//
// Contents: LibMain for nds.dll
//
// Functions: LibMain, DllGetClassObject
//
// History: 25-Oct-94 KrishnaG Created.
//
//----------------------------------------------------------------------------
#include "oleds.hxx"
#pragma hdrstop
CRITICAL_SECTION g_StringsCriticalSection; WCHAR g_szBuiltin[100]; WCHAR g_szNT_Authority[100]; WCHAR g_szAccountOperators[100]; WCHAR g_szPrintOperators[100]; WCHAR g_szBackupOperators[100]; WCHAR g_szServerOperators[100]; WCHAR g_szPreWindows2000[100];
BOOL g_fStringsLoaded = FALSE;
//
// Global variables for dynamically loaded fn's.
//
HANDLE g_hDllAdvapi32 = NULL; BOOL g_fDllsLoaded = FALSE;
extern "C" {
HRESULT ConvertSidToString( PSID pSid, LPWSTR String ); }
DWORD GetDomainDNSNameForDomain( LPWSTR pszDomainFlatName, BOOL fVerify, BOOL fWriteable, LPWSTR pszServerName, LPWSTR pszDomainDNSName );
#define GetAce ADSIGetAce
#define AddAce ADSIAddAce
#define DeleteAce ADSIDeleteAce
#define GetAclInformation ADSIGetAclInformation
#define SetAclInformation ADSISetAclInformation
#define IsValidAcl ADSIIsValidAcl
#define InitializeAcl ADSIInitializeAcl
#define SetSecurityDescriptorControl ADSISetControlSecurityDescriptor
#define SE_VALID_CONTROL_BITS ( SE_DACL_UNTRUSTED | \
SE_SERVER_SECURITY | \ SE_DACL_AUTO_INHERIT_REQ | \ SE_SACL_AUTO_INHERIT_REQ | \ SE_DACL_AUTO_INHERITED | \ SE_SACL_AUTO_INHERITED | \ SE_DACL_PROTECTED | \ SE_SACL_PROTECTED )
BOOL EquivalentServers( LPWSTR pszTargetServer, LPWSTR pszSourceServer );
HRESULT SecCreateSidFromArray ( OUT PSID *PPSid, IN PSID_IDENTIFIER_AUTHORITY PSidAuthority, IN UCHAR SubAuthorityCount, IN ULONG SubAuthorities[], OUT PDWORD pdwSidSize );
HRESULT ConvertStringToSid( IN PWSTR string, OUT PSID *sid, OUT PDWORD pdwSidSize );
HRESULT AddFilteredACEs( PACL pAcl, DWORD dwAclRevision, PACE_HEADER *ppAceHdr, DWORD dwCountACEs, DWORD *pdwAclPosition, BOOL fInheritedACEs, BOOL fDenyACEs, BOOL fDenyObjectACEs, BOOL fGrantACEs, BOOL fGrantObjectACEs, BOOL fAuditACEs );
//
// These wrapper functions are needed as some fn's need to
// be loaded dynamically as they are not available on NT4
//
#define SET_SD_CONTROL_API "SetSecurityDescriptorControl"
// load library helper
HMODULE LoadLibraryHelper( LPTSTR pszFileName ) { const DWORD iSize = GetSystemDirectory(NULL, 0); TCHAR* buffer = NULL; DWORD dwTemp = 0; HMODULE handle = NULL;
if(iSize == 0) { goto error; }
buffer = new TCHAR[iSize + _tcslen(__TEXT("\\")) + _tcslen(pszFileName)]; // iSize includes the NULL terminiator
if(!buffer) { goto error; }
dwTemp = GetSystemDirectory(buffer, iSize); if(dwTemp == 0) { goto error; }
_tcscat(buffer, __TEXT("\\")); _tcscat(buffer, pszFileName);
handle = LoadLibrary(buffer);
error:
if(buffer) { delete [] buffer; buffer = NULL; } return handle; }
//
// Helper that loads functions in advapi32.
//
PVOID LoadAdvapi32Function(CHAR *function) { //
// Since the strings critical section is only used in this file,
// be fine just re-using it here.
//
if (!g_fDllsLoaded) { EnterCriticalSection(&g_StringsCriticalSection); if (!g_fDllsLoaded) { g_hDllAdvapi32 = LoadLibraryHelper(L"ADVAPI32.DLL"); //
// Even if this fails, there is nothing we can do.
//
g_fDllsLoaded = TRUE; } LeaveCriticalSection(&g_StringsCriticalSection); }
if (g_hDllAdvapi32) { return((PVOID*) GetProcAddress((HMODULE) g_hDllAdvapi32, function)); }
return NULL; }
typedef DWORD (*PF_SetSecurityDescriptorControl) ( IN PSECURITY_DESCRIPTOR pSecurityDescriptor, IN SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest, IN SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet );
//
// Wrapper function for the same.
//
DWORD SetSecurityDescriptorControlWrapper( IN PSECURITY_DESCRIPTOR pSecurityDescriptor, IN SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest, IN SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet ) { static PF_SetSecurityDescriptorControl pfSetSecDescControl = NULL; static BOOL f_LoadAttempted = FALSE;
//
// Load the fn and set the variables accordingly.
//
if (!f_LoadAttempted && pfSetSecDescControl == NULL) { pfSetSecDescControl = (PF_SetSecurityDescriptorControl) LoadAdvapi32Function(SET_SD_CONTROL_API); f_LoadAttempted = TRUE; }
if (pfSetSecDescControl != NULL) { return ((*pfSetSecDescControl)( pSecurityDescriptor, ControlBitsOfInterest, ControlBitsToSet ) ); } else { //
// This will call the routine in acledit.cxx.
// We should be in this codepath only in pre win2k
// machines.
//
return SetSecurityDescriptorControl( pSecurityDescriptor, ControlBitsOfInterest, ControlBitsToSet ); }
}
HRESULT ConvertSecurityDescriptorToSecDes( LPWSTR pszServerName, CCredentials& Credentials, IADsSecurityDescriptor FAR * pSecDes, PSECURITY_DESCRIPTOR * ppSecurityDescriptor, PDWORD pdwSDLength, BOOL fNTDSType ) { HRESULT hr = S_OK;
SECURITY_DESCRIPTOR AbsoluteSD; PSECURITY_DESCRIPTOR pRelative = NULL; BOOL Defaulted = FALSE; BOOL DaclPresent = FALSE; BOOL SaclPresent = FALSE;
BOOL fDaclDefaulted = FALSE; BOOL fSaclDefaulted = FALSE; BOOL fOwnerDefaulted = FALSE; BOOL fGroupDefaulted = FALSE;
PSID pOwnerSid = NULL; PSID pGroupSid = NULL; PACL pDacl = NULL; PACL pSacl = NULL; DWORD dwSDLength = 0; BOOL dwStatus = 0;
DWORD dwControl = 0; DWORD dwRevision = 0;
hr = pSecDes->get_Revision((long *)&dwRevision); BAIL_ON_FAILURE(hr);
dwStatus = InitializeSecurityDescriptor ( &AbsoluteSD, dwRevision ); if (!dwStatus) { hr = HRESULT_FROM_WIN32(GetLastError()); BAIL_ON_FAILURE(hr); }
hr = pSecDes->get_Control((long *)&dwControl); BAIL_ON_FAILURE(hr);
dwStatus = SetSecurityDescriptorControlWrapper( &AbsoluteSD, SE_VALID_CONTROL_BITS, (SECURITY_DESCRIPTOR_CONTROL) (dwControl & SE_VALID_CONTROL_BITS) ); if (!dwStatus) { hr = HRESULT_FROM_WIN32(GetLastError()); BAIL_ON_FAILURE(hr); }
hr = GetOwnerSecurityIdentifier( pszServerName, Credentials, pSecDes, &pOwnerSid, &fOwnerDefaulted, fNTDSType ); BAIL_ON_FAILURE(hr);
dwStatus = SetSecurityDescriptorOwner( &AbsoluteSD, pOwnerSid, fOwnerDefaulted ); if (!dwStatus) { hr = HRESULT_FROM_WIN32(GetLastError()); BAIL_ON_FAILURE(hr); }
hr = GetGroupSecurityIdentifier( pszServerName, Credentials, pSecDes, &pGroupSid, &fGroupDefaulted, fNTDSType ); BAIL_ON_FAILURE(hr);
dwStatus = SetSecurityDescriptorGroup( &AbsoluteSD, pGroupSid, fGroupDefaulted );
if (!dwStatus) { hr = HRESULT_FROM_WIN32(GetLastError()); BAIL_ON_FAILURE(hr); }
hr = GetDacl( pszServerName, Credentials, pSecDes, &pDacl, &fDaclDefaulted, fNTDSType ); BAIL_ON_FAILURE(hr);
if (pDacl || fDaclDefaulted) { DaclPresent = TRUE; }
//
// This is a special case, basically the DACL is defaulted
// and pDacl is NULL. In order for this to work correctly,
// pDacl should be an empty ACL not null.
//
if (DaclPresent && !pDacl) { pDacl = (PACL) AllocADsMem(sizeof(ACL)); if (!pDacl) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
dwStatus = InitializeAcl( pDacl, sizeof(ACL), ACL_REVISION // this revision will work for NT4 and Win2k
); if (!dwStatus) { hr = HRESULT_FROM_WIN32(GetLastError()); BAIL_ON_FAILURE(hr); } }
dwStatus = SetSecurityDescriptorDacl( &AbsoluteSD, DaclPresent, pDacl, fDaclDefaulted ); if (!dwStatus) { hr = HRESULT_FROM_WIN32(GetLastError()); BAIL_ON_FAILURE(hr); }
hr = GetSacl( pszServerName, Credentials, pSecDes, &pSacl, &fSaclDefaulted, fNTDSType ); BAIL_ON_FAILURE(hr);
if (pSacl || fSaclDefaulted) { SaclPresent = TRUE; }
dwStatus = SetSecurityDescriptorSacl( &AbsoluteSD, SaclPresent, pSacl, fSaclDefaulted );
if (!dwStatus) { hr = HRESULT_FROM_WIN32(GetLastError()); BAIL_ON_FAILURE(hr); }
dwSDLength = GetSecurityDescriptorLength( &AbsoluteSD );
pRelative = AllocADsMem(dwSDLength); if (!pRelative) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); }
if (!MakeSelfRelativeSD (&AbsoluteSD, pRelative, &dwSDLength)) { FreeADsMem(pRelative);
hr = HRESULT_FROM_WIN32(GetLastError()); BAIL_ON_FAILURE(hr); }
*ppSecurityDescriptor = pRelative; *pdwSDLength = dwSDLength;
cleanup:
if (pDacl) { FreeADsMem(pDacl); }
if (pSacl) { FreeADsMem(pSacl); }
if (pOwnerSid) { FreeADsMem(pOwnerSid); }
if (pGroupSid) { FreeADsMem(pGroupSid); }
RRETURN(hr);
error: *ppSecurityDescriptor = NULL; *pdwSDLength = 0;
goto cleanup;
}
HRESULT GetOwnerSecurityIdentifier( LPWSTR pszServerName, CCredentials& Credentials, IADsSecurityDescriptor FAR * pSecDes, PSID * ppSid, PBOOL pfOwnerDefaulted, BOOL fNTDSType ) { BSTR bstrOwner = NULL; DWORD dwSidSize = 0; HRESULT hr = S_OK; VARIANT_BOOL varBool = VARIANT_FALSE;
hr = pSecDes->get_Owner( &bstrOwner ); BAIL_ON_FAILURE(hr);
hr = pSecDes->get_OwnerDefaulted( &varBool ); BAIL_ON_FAILURE(hr);
if (varBool == VARIANT_FALSE) {
if (bstrOwner && *bstrOwner) {
hr = ConvertTrusteeToSid( pszServerName, Credentials, bstrOwner, ppSid, &dwSidSize, fNTDSType ); BAIL_ON_FAILURE(hr); *pfOwnerDefaulted = FALSE; }else {
*ppSid = NULL; *pfOwnerDefaulted = FALSE; }
}else { *ppSid = NULL; dwSidSize = 0; *pfOwnerDefaulted = TRUE; }
error:
if (bstrOwner) { ADsFreeString(bstrOwner); }
RRETURN(hr); }
HRESULT GetGroupSecurityIdentifier( LPWSTR pszServerName, CCredentials& Credentials, IADsSecurityDescriptor FAR * pSecDes, PSID * ppSid, PBOOL pfGroupDefaulted, BOOL fNTDSType ) { BSTR bstrGroup = NULL; DWORD dwSidSize = 0; HRESULT hr = S_OK; VARIANT_BOOL varBool = VARIANT_FALSE;
hr = pSecDes->get_Group( &bstrGroup ); BAIL_ON_FAILURE(hr);
hr = pSecDes->get_GroupDefaulted( &varBool ); BAIL_ON_FAILURE(hr);
if (varBool == VARIANT_FALSE) {
if (bstrGroup && *bstrGroup) {
hr = ConvertTrusteeToSid( pszServerName, Credentials, bstrGroup, ppSid, &dwSidSize, fNTDSType ); BAIL_ON_FAILURE(hr); *pfGroupDefaulted = FALSE; }else { *ppSid = NULL; *pfGroupDefaulted = FALSE; }
}else { *ppSid = NULL; dwSidSize = 0; *pfGroupDefaulted = TRUE; }
error:
if (bstrGroup) { ADsFreeString(bstrGroup); }
RRETURN(hr);
}
HRESULT GetDacl( LPWSTR pszServerName, CCredentials& Credentials, IADsSecurityDescriptor FAR * pSecDes, PACL * ppDacl, PBOOL pfDaclDefaulted, BOOL fNTDSType ) { IADsAccessControlList FAR * pDiscAcl = NULL; IDispatch FAR * pDispatch = NULL; HRESULT hr = S_OK; VARIANT_BOOL varBool = VARIANT_FALSE;
hr = pSecDes->get_DaclDefaulted( &varBool ); BAIL_ON_FAILURE(hr);
if (varBool == VARIANT_FALSE) { *pfDaclDefaulted = FALSE; }else { *pfDaclDefaulted = TRUE; }
hr = pSecDes->get_DiscretionaryAcl( &pDispatch ); BAIL_ON_FAILURE(hr);
if (!pDispatch) { *ppDacl = NULL; goto error; }
hr = pDispatch->QueryInterface( IID_IADsAccessControlList, (void **)&pDiscAcl ); BAIL_ON_FAILURE(hr);
hr = ConvertAccessControlListToAcl( pszServerName, Credentials, pDiscAcl, ppDacl, fNTDSType ); BAIL_ON_FAILURE(hr);
error:
if (pDispatch) { pDispatch->Release(); }
if (pDiscAcl) { pDiscAcl->Release(); }
RRETURN(hr); }
HRESULT GetSacl( LPWSTR pszServerName, CCredentials& Credentials, IADsSecurityDescriptor FAR * pSecDes, PACL * ppSacl, PBOOL pfSaclDefaulted, BOOL fNTDSType ) { IADsAccessControlList FAR * pSystemAcl = NULL; IDispatch FAR * pDispatch = NULL; HRESULT hr = S_OK; VARIANT_BOOL varBool = VARIANT_FALSE;
hr = pSecDes->get_SaclDefaulted( &varBool ); BAIL_ON_FAILURE(hr);
if (varBool == VARIANT_FALSE) { *pfSaclDefaulted = FALSE; }else { *pfSaclDefaulted = TRUE; }
hr = pSecDes->get_SystemAcl( &pDispatch ); BAIL_ON_FAILURE(hr);
if (!pDispatch) { *ppSacl = NULL; goto error; }
hr = pDispatch->QueryInterface( IID_IADsAccessControlList, (void **)&pSystemAcl ); BAIL_ON_FAILURE(hr);
hr = ConvertAccessControlListToAcl( pszServerName, Credentials, pSystemAcl, ppSacl, fNTDSType ); BAIL_ON_FAILURE(hr);
error:
if (pDispatch) { pDispatch->Release(); }
if (pSystemAcl) { pSystemAcl->Release(); }
RRETURN(hr); }
HRESULT ConvertAccessControlListToAcl( LPWSTR pszServerName, CCredentials& Credentials, IADsAccessControlList FAR * pAccessList, PACL * ppAcl, BOOL fNTDSType ) { IUnknown * pUnknown = NULL; IEnumVARIANT * pEnumerator = NULL; HRESULT hr = S_OK; DWORD i = 0; DWORD iAclPosition = 0; DWORD cReturned = 0; VARIANT varAce;
DWORD dwAceCount = 0;
IADsAccessControlEntry FAR * pAccessControlEntry = NULL;
LPBYTE pTempAce = NULL; DWORD dwCount = 0;
PACL pAcl = NULL; DWORD dwAclSize = 0; PACE_HEADER * ppAceHdr = NULL;
DWORD dwRet = 0; DWORD dwAclRevision = 0; DWORD dwError = 0;
//
// Defines the canonical ordering of the ACEs.
//
struct AceOrderElement { BOOL fInheritedACEs; BOOL fDenyACEs; BOOL fDenyObjectACEs; BOOL fGrantACEs; BOOL fGrantObjectACEs; BOOL fAuditACEs; } AceOrderSequence [] = { {FALSE, FALSE, FALSE, FALSE, FALSE, TRUE}, {FALSE, TRUE, FALSE, FALSE, FALSE, FALSE}, {FALSE, FALSE, TRUE, FALSE, FALSE, FALSE}, {FALSE, FALSE, FALSE, TRUE, FALSE, FALSE}, {FALSE, FALSE, FALSE, FALSE, TRUE, FALSE},
{TRUE, FALSE, FALSE, FALSE, FALSE, TRUE}, {TRUE, TRUE, FALSE, FALSE, FALSE, FALSE}, {TRUE, FALSE, TRUE, FALSE, FALSE, FALSE}, {TRUE, FALSE, FALSE, TRUE, FALSE, FALSE}, {TRUE, FALSE, FALSE, FALSE, TRUE, FALSE} };
DWORD dwAceOrderSequenceLen = sizeof(AceOrderSequence) / sizeof (AceOrderElement);
hr = pAccessList->get_AceCount((long *)&dwAceCount); BAIL_ON_FAILURE(hr);
hr = pAccessList->get__NewEnum( &pUnknown ); BAIL_ON_FAILURE(hr);
hr = pUnknown->QueryInterface( IID_IEnumVARIANT, (void FAR * FAR *)&pEnumerator ); BAIL_ON_FAILURE(hr);
ppAceHdr = (PACE_HEADER *)AllocADsMem(sizeof(PACE_HEADER)*dwAceCount); if (!ppAceHdr) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); }
for (i = 0; i < dwAceCount; i++) {
VariantInit(&varAce);
hr = pEnumerator->Next( 1, &varAce, &cReturned );
//
// Need to BAIL here as we could not convert an ACL.
//
BAIL_ON_FAILURE(hr);
hr = (V_DISPATCH(&varAce))->QueryInterface( IID_IADsAccessControlEntry, (void **)&pAccessControlEntry );
VariantClear(&varAce); BAIL_ON_FAILURE(hr);
hr = ConvertAccessControlEntryToAce( pszServerName, Credentials, pAccessControlEntry, &(pTempAce), fNTDSType );
if (pAccessControlEntry) { pAccessControlEntry->Release(); pAccessControlEntry = NULL; } BAIL_ON_FAILURE(hr);
*(ppAceHdr + dwCount) = (PACE_HEADER)pTempAce;
dwCount++; }
hr = ComputeTotalAclSize(ppAceHdr, dwCount, &dwAclSize); BAIL_ON_FAILURE(hr);
pAcl = (PACL)AllocADsMem(dwAclSize); if (!pAcl) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); }
hr = pAccessList->get_AclRevision((long *)&dwAclRevision); BAIL_ON_FAILURE(hr);
dwRet = InitializeAcl( pAcl, dwAclSize, dwAclRevision ); if (!dwRet) { hr = HRESULT_FROM_WIN32(GetLastError()); BAIL_ON_FAILURE(hr); }
//
// Add the ACEs in canonical ordering:
// All Explitic Audit
// All Explicit Deny
// All Explicit Object Deny
// All Explicit Allow
// All Explicit Object Allow
//
// All Inherited Audit
// All Inherited Deny
// All Inherited Object Deny
// All Inherited Allow
// All Inherited Object Allow
//
for (i=0; i < dwAceOrderSequenceLen; i++) {
hr = AddFilteredACEs( pAcl, dwAclRevision, ppAceHdr, dwCount, &iAclPosition, AceOrderSequence[i].fInheritedACEs, AceOrderSequence[i].fDenyACEs, AceOrderSequence[i].fDenyObjectACEs, AceOrderSequence[i].fGrantACEs, AceOrderSequence[i].fGrantObjectACEs, AceOrderSequence[i].fAuditACEs ); BAIL_ON_FAILURE(hr); }
*ppAcl = pAcl;
error:
if (ppAceHdr) { for (i = 0; i < dwCount; i++) { if (*(ppAceHdr + i)) {
FreeADsMem(*(ppAceHdr + i)); } }
FreeADsMem(ppAceHdr); }
if (pUnknown) { pUnknown->Release(); }
if (pEnumerator) { pEnumerator->Release(); }
if(FAILED(hr) && pAcl) { FreeADsMem(pAcl); }
RRETURN(hr); }
/*
* AddFilteredACEs * * Adds ACEs from ppAceHdr (of size dwCountACEs) to the ACL pAcl * (of revision dwAclRevision), starting at position *pdwAclPosition in * the ACL, based on the filter settings fInheritedACEs, fDenyACEs, * fGrantACEs, fDenyObjectACEs, fGrantObjectACEs, and fAuditACEs. * * On return, *pdwAclPosition is the position to continue adding * ACEs at. * */ HRESULT AddFilteredACEs( PACL pAcl, // the ACL to add the ACEs to
DWORD dwAclRevision, // the revision of the ACL
PACE_HEADER *ppAceHdr, // the ACEs to add
DWORD dwCountACEs, // number of ACEs in ppAceHdr
DWORD *pdwAclPosition, // starting(in)/ending(out) position
BOOL fInheritedACEs, // include explicit or inherited ACEs?
BOOL fDenyACEs, // include access-deny ACEs?
BOOL fDenyObjectACEs, // include access-deny-object ACEs?
BOOL fGrantACEs, // include access-grant ACEs?
BOOL fGrantObjectACEs, // include access-grant-object ACEs?
BOOL fAuditACEs // include audit ACEs?
) { HRESULT hr = S_OK; DWORD dwStatus;
DWORD i; DWORD iAclPosition = *pdwAclPosition; BOOL fAddIt;
BOOL fIsAceInherited;
for (i = 0; i < dwCountACEs; i++) {
//
// Filter based on whether we're adding explicit or inherited ACEs
//
fIsAceInherited = (((*(ppAceHdr + i))->AceFlags) & INHERITED_ACE) ? TRUE : FALSE;
if ( fIsAceInherited == fInheritedACEs) {
fAddIt = FALSE;
//
// Filter based on ACE type
//
switch ((*(ppAceHdr + i))->AceType) { case ACCESS_ALLOWED_ACE_TYPE: if (fGrantACEs) { fAddIt = TRUE; } break;
case ACCESS_ALLOWED_OBJECT_ACE_TYPE: if (fGrantObjectACEs) { fAddIt = TRUE; } break;
case ACCESS_DENIED_ACE_TYPE: if (fDenyACEs) { fAddIt = TRUE; } break; case ACCESS_DENIED_OBJECT_ACE_TYPE: if (fDenyObjectACEs) { fAddIt = TRUE; } break; case SYSTEM_AUDIT_ACE_TYPE: case SYSTEM_AUDIT_OBJECT_ACE_TYPE: if (fAuditACEs) { fAddIt = TRUE; } break;
default: BAIL_ON_FAILURE(hr = E_INVALIDARG); break; }
//
// If the ACE met the criteria, add it to the ACL
//
if (fAddIt) { dwStatus = AddAce( pAcl, dwAclRevision, iAclPosition++, (LPBYTE)*(ppAceHdr + i), (*(ppAceHdr + i))->AceSize ); if (!dwStatus) {
BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(GetLastError())); } } } }
error:
*pdwAclPosition = iAclPosition; RRETURN(hr); }
HRESULT ConvertAccessControlEntryToAce( LPWSTR pszServerName, CCredentials& Credentials, IADsAccessControlEntry * pAccessControlEntry, LPBYTE * ppAce, BOOL fNTDSType ) {
DWORD dwAceType = 0; HRESULT hr = S_OK; BSTR bstrTrustee = NULL; PSID pSid = NULL; DWORD dwSidSize = 0;
DWORD dwAceFlags = 0; DWORD dwAccessMask = 0; DWORD dwAceSize = 0; LPBYTE pAce = NULL; PACCESS_MASK pAccessMask = NULL; PSID pSidAddress = NULL;
PUSHORT pCompoundAceType = NULL; DWORD dwCompoundAceType = 0;
PACE_HEADER pAceHeader = NULL;
LPBYTE pOffset = NULL;
BSTR bstrObjectTypeClsid = NULL; BSTR bstrInheritedObjectTypeClsid = NULL;
GUID ObjectTypeGUID; GUID InheritedObjectTypeGUID; PULONG pFlags; DWORD dwFlags = 0; BOOL fLookupTrustee = TRUE; BOOL fSidValid = FALSE; IADsAcePrivate *pPrivAce = NULL;
hr = pAccessControlEntry->get_AceType((LONG *)&dwAceType); BAIL_ON_FAILURE(hr);
hr = pAccessControlEntry->get_Trustee(&bstrTrustee); BAIL_ON_FAILURE(hr);
//
// We need to see if we can use a cached SID here.
//
hr = pAccessControlEntry->QueryInterface( IID_IADsAcePrivate, (void **)&pPrivAce ); if (SUCCEEDED(hr)) { //
// See if the SID is valid and if so try and retrieve it.
//
hr = pPrivAce->isSidValid(&fSidValid); if (SUCCEEDED(hr) && fSidValid) { hr = pPrivAce->getSid( &pSid, &dwSidSize );
if (SUCCEEDED(hr)) { fLookupTrustee = FALSE; } }
}
if (fLookupTrustee) {
hr = ConvertTrusteeToSid( pszServerName, Credentials, bstrTrustee, &pSid, &dwSidSize, fNTDSType ); }
BAIL_ON_FAILURE(hr);
hr = pAccessControlEntry->get_AceFlags((long *)&dwAceFlags); BAIL_ON_FAILURE(hr);
hr = pAccessControlEntry->get_AccessMask((long *)&dwAccessMask); BAIL_ON_FAILURE(hr);
//
// we will compensateby adding the entire ACE size
//
dwAceSize = dwSidSize - sizeof(ULONG);
switch (dwAceType) {
case ACCESS_ALLOWED_ACE_TYPE: dwAceSize += sizeof(ACCESS_ALLOWED_ACE); pAce = (LPBYTE)AllocADsMem(dwAceSize); if (!pAce) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); } pAceHeader = (PACE_HEADER)pAce; pAceHeader->AceType = (UCHAR)dwAceType; pAceHeader->AceFlags = (UCHAR)dwAceFlags; pAceHeader->AceSize = (USHORT)dwAceSize;
pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
*pAccessMask = (ACCESS_MASK)dwAccessMask;
pSidAddress = (PSID)((LPBYTE)pAccessMask + sizeof(ACCESS_MASK)); memcpy(pSidAddress, pSid, dwSidSize); break;
case ACCESS_DENIED_ACE_TYPE: dwAceSize += sizeof(ACCESS_ALLOWED_ACE); pAce = (LPBYTE)AllocADsMem(dwAceSize); if (!pAce) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); } pAceHeader = (PACE_HEADER)pAce; pAceHeader->AceType = (UCHAR)dwAceType; pAceHeader->AceFlags = (UCHAR)dwAceFlags; pAceHeader->AceSize = (USHORT)dwAceSize;
pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
*pAccessMask = (ACCESS_MASK)dwAccessMask;
pSidAddress = (PSID)((LPBYTE)pAccessMask + sizeof(ACCESS_MASK)); memcpy(pSidAddress, pSid, dwSidSize); break;
case SYSTEM_AUDIT_ACE_TYPE: dwAceSize += sizeof(ACCESS_ALLOWED_ACE); pAce = (LPBYTE)AllocADsMem(dwAceSize); if (!pAce) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); } pAceHeader = (PACE_HEADER)pAce; pAceHeader->AceType = (UCHAR)dwAceType; pAceHeader->AceFlags = (UCHAR)dwAceFlags; pAceHeader->AceSize = (USHORT)dwAceSize;
pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
*pAccessMask = (ACCESS_MASK)dwAccessMask;
pSidAddress = (PSID)((LPBYTE)pAccessMask + sizeof(ACCESS_MASK)); memcpy(pSidAddress, pSid, dwSidSize); break;
case SYSTEM_ALARM_ACE_TYPE: dwAceSize += sizeof(ACCESS_ALLOWED_ACE); pAce = (LPBYTE)AllocADsMem(dwAceSize); if (!pAce) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); } pAceHeader = (PACE_HEADER)pAce; pAceHeader->AceType = (UCHAR)dwAceType; pAceHeader->AceFlags = (UCHAR)dwAceFlags; pAceHeader->AceSize = (USHORT)dwAceSize;
pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
*pAccessMask = (ACCESS_MASK)dwAccessMask;
pSidAddress = (PSID)((LPBYTE)pAccessMask + sizeof(ACCESS_MASK)); memcpy(pSidAddress, pSid, dwSidSize); break;
case ACCESS_ALLOWED_COMPOUND_ACE_TYPE: dwAceSize += sizeof(COMPOUND_ACCESS_ALLOWED_ACE); pAce = (LPBYTE)AllocADsMem(dwAceSize); if (!pAce) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); } pAceHeader = (PACE_HEADER)pAce; pAceHeader->AceType = (UCHAR)dwAceType; pAceHeader->AceFlags = (UCHAR)dwAceFlags; pAceHeader->AceSize = (USHORT)dwAceSize;
pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
*pAccessMask = (ACCESS_MASK)dwAccessMask;
pCompoundAceType = (PUSHORT)(pAccessMask + sizeof(ACCESS_MASK)); *pCompoundAceType = (USHORT)dwCompoundAceType;
//
// Fill in the reserved field here.
//
pSidAddress = (PSID)((LPBYTE)pCompoundAceType + sizeof(DWORD)); memcpy(pSidAddress, pSid, dwSidSize); break;
case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
case ACCESS_DENIED_OBJECT_ACE_TYPE:
case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
case SYSTEM_ALARM_OBJECT_ACE_TYPE:
hr = pAccessControlEntry->get_AceFlags((LONG *)&dwAceFlags); BAIL_ON_FAILURE(hr);
hr = pAccessControlEntry->get_Flags((LONG *)&dwFlags); BAIL_ON_FAILURE(hr);
if (dwFlags & ACE_OBJECT_TYPE_PRESENT) { dwAceSize += sizeof(GUID); }
if (dwFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT) { dwAceSize += sizeof(GUID); }
hr = pAccessControlEntry->get_ObjectType(&bstrObjectTypeClsid); BAIL_ON_FAILURE(hr);
hr = CLSIDFromString(bstrObjectTypeClsid, &ObjectTypeGUID); BAIL_ON_FAILURE(hr);
hr = pAccessControlEntry->get_InheritedObjectType(&bstrInheritedObjectTypeClsid); BAIL_ON_FAILURE(hr);
hr = CLSIDFromString(bstrInheritedObjectTypeClsid, &InheritedObjectTypeGUID); BAIL_ON_FAILURE(hr);
dwAceSize += sizeof(ACCESS_ALLOWED_OBJECT_ACE); pAce = (LPBYTE)AllocADsMem(dwAceSize); if (!pAce) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); }
pAceHeader = (PACE_HEADER)pAce; pAceHeader->AceType = (UCHAR)dwAceType; pAceHeader->AceFlags = (UCHAR)dwAceFlags; pAceHeader->AceSize = (USHORT)dwAceSize;
pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
*pAccessMask = (ACCESS_MASK)dwAccessMask;
//
// Fill in Flags
//
pOffset = (LPBYTE)((LPBYTE)pAceHeader + sizeof(ACE_HEADER) + sizeof(ACCESS_MASK));
pFlags = (PULONG)(pOffset);
*pFlags = dwFlags;
pOffset += sizeof(ULONG);
if (dwFlags & ACE_OBJECT_TYPE_PRESENT) {
memcpy(pOffset, &ObjectTypeGUID, sizeof(GUID));
pOffset += sizeof(GUID);
}
if (dwFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT) {
memcpy(pOffset, &InheritedObjectTypeGUID, sizeof(GUID));
pOffset += sizeof(GUID); }
pSidAddress = (PSID)((LPBYTE)pOffset); memcpy(pSidAddress, pSid, dwSidSize); break;
default: hr = HRESULT_FROM_WIN32(ERROR_INVALID_ACL); BAIL_ON_FAILURE(hr); break;
}
*ppAce = pAce;
error:
if (bstrTrustee) { ADsFreeString(bstrTrustee); }
if (pSid) { FreeADsMem(pSid); }
if (bstrObjectTypeClsid) { SysFreeString(bstrObjectTypeClsid); }
if (bstrInheritedObjectTypeClsid) { SysFreeString(bstrInheritedObjectTypeClsid); }
if (pPrivAce) { pPrivAce->Release(); }
RRETURN(hr); }
HRESULT ComputeTotalAclSize( PACE_HEADER * ppAceHdr, DWORD dwAceCount, PDWORD pdwAclSize ) { DWORD i = 0; PACE_HEADER pAceHdr = NULL; DWORD dwAceSize = 0; DWORD dwAclSize = 0;
for (i = 0; i < dwAceCount; i++) {
pAceHdr = *(ppAceHdr + i); dwAceSize = pAceHdr->AceSize; dwAclSize += dwAceSize; }
dwAclSize += sizeof(ACL);
*pdwAclSize = dwAclSize;
RRETURN(S_OK);
}
HRESULT ParseAccountName(LPWSTR szFullAccountName, LPWSTR *pszUserDomainName, LPWSTR *pszUserAccountName) { HRESULT hr = S_OK; DWORD dwDomain = 0; BOOLEAN bFound = FALSE; LPWSTR szUserDomainName = NULL; LPWSTR szUserAccountName = NULL; LPWSTR szCount = szFullAccountName;
if (!szFullAccountName) { hr = E_FAIL; BAIL_ON_FAILURE(hr); }
while (*szCount) { if (*szCount == '\\') { bFound = TRUE; break; } dwDomain++; szCount++; }
if (bFound) { DWORD dwRest = 0; szUserDomainName = (LPWSTR)AllocADsMem(sizeof(WCHAR) * (dwDomain+1)); if (!szUserDomainName) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); } wcsncpy(szUserDomainName, szFullAccountName, dwDomain); szUserDomainName[dwDomain] = L'\0';
szUserAccountName = AllocADsStr(szCount+1); if (!szUserAccountName) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); } } else { szUserAccountName = AllocADsStr(szFullAccountName); if (!szUserAccountName) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); } szUserDomainName = NULL; } *pszUserAccountName = szUserAccountName; *pszUserDomainName = szUserDomainName; return hr;
error: if (szUserAccountName) { FreeADsMem(szUserAccountName); } if (szUserDomainName) { FreeADsMem(szUserDomainName); } return hr; }
HRESULT ConvertTrusteeToSid( LPWSTR pszServerName, CCredentials& Credentials, BSTR bstrTrustee, PSID * ppSid, PDWORD pdwSidSize, BOOL fNTDSType ) { HRESULT hr = S_OK; BYTE Sid[MAX_PATH]; DWORD dwSidSize = sizeof(Sid); DWORD dwRet = 0; DWORD dwErr = 0; WCHAR szDomainName[MAX_PATH]; DWORD dwDomainSize = sizeof(szDomainName)/sizeof(WCHAR); SID_NAME_USE eUse;
PSID pSid = NULL;
LPWSTR szUserDomainName = NULL; LPWSTR szUserAccountName = NULL; LPWSTR szAccountName = NULL; BOOL fForceVerify = FALSE;
//
// Load the strings into table if necessary
//
if (!g_fStringsLoaded) {
EnterCriticalSection(&g_StringsCriticalSection);
//
// Verify flag again.
//
if (!g_fStringsLoaded) {
dwRet = LoadStringW( g_hInst, ADS_BUILTIN, g_szBuiltin, sizeof( g_szBuiltin ) / sizeof( WCHAR ) );
if (!dwRet) { //
// Default to English values.
//
wcscpy(g_szBuiltin, L"BUILTIN"); }
dwRet = LoadStringW( g_hInst, ADS_NT_AUTHORITY, g_szNT_Authority, sizeof( g_szNT_Authority ) / sizeof( WCHAR ) );
if (!dwRet) { //
// Default to English values.
//
wcscpy(g_szNT_Authority, L"NT AUTHORITY"); }
dwRet = LoadStringW( g_hInst, ADS_ACCOUNT_OPERATORS, g_szAccountOperators, sizeof( g_szAccountOperators ) / sizeof( WCHAR ) );
if (!dwRet) { //
// Default to English values.
//
wcscpy(g_szAccountOperators, L"Account Operators"); }
dwRet = LoadStringW( g_hInst, ADS_PRINT_OPERATORS, g_szPrintOperators, sizeof( g_szPrintOperators ) / sizeof( WCHAR ) );
if (!dwRet) { //
// Default to English values.
//
wcscpy(g_szPrintOperators, L"Print Operators"); }
dwRet = LoadStringW( g_hInst, ADS_BACKUP_OPERATORS, g_szBackupOperators, sizeof( g_szBackupOperators ) / sizeof( WCHAR ) );
if (!dwRet) { //
// Default to English values.
//
wcscpy(g_szBackupOperators, L"Backup Operators"); }
dwRet = LoadStringW( g_hInst, ADS_SERVER_OPERATORS, g_szServerOperators, sizeof( g_szServerOperators ) / sizeof( WCHAR ) );
if (!dwRet) { //
// Default to English values.
//
wcscpy(g_szServerOperators, L"Server Operators"); }
dwRet = LoadStringW( g_hInst, ADS_PRE_WIN2000, g_szPreWindows2000, sizeof( g_szPreWindows2000 ) / sizeof( WCHAR ) );
if (!dwRet) { //
// Default to English values.
//
wcscpy( g_szPreWindows2000, L"Pre-Windows 2000 Compatible Access" ); }
}
g_fStringsLoaded = TRUE;
LeaveCriticalSection(&g_StringsCriticalSection);
}
//
//
// parse Trustee and determine whether its NTDS or U2
//
if (fNTDSType) { WCHAR szDomainName[MAX_PATH]; WCHAR szServerName[MAX_PATH]; LPWSTR szLookupServer = NULL; BOOL fSpecialLookup = FALSE; BOOL fLookupOnServer = FALSE; DWORD dwTmpSidLen = 0;
dwSidSize = sizeof(Sid); szAccountName = bstrTrustee;
hr = ParseAccountName(bstrTrustee, &szUserDomainName, &szUserAccountName); BAIL_ON_FAILURE(hr);
//
// Need to look these up on the server only.
//
if (szUserAccountName && ((_wcsicmp(szUserAccountName, g_szAccountOperators) == 0) || (_wcsicmp(szUserAccountName, g_szPrintOperators) == 0) || (_wcsicmp(szUserAccountName, g_szBackupOperators) == 0) || (_wcsicmp(szUserAccountName, g_szServerOperators) == 0) || (_wcsicmp(szUserAccountName, g_szPreWindows2000) == 0) ) ) { if (szUserDomainName && (_wcsicmp(szUserDomainName, g_szBuiltin)) == 0) { fSpecialLookup = TRUE; } else { fSpecialLookup = FALSE; } } // special users
if (fSpecialLookup || (szUserDomainName && (_wcsicmp(szUserDomainName, g_szBuiltin) != 0) && (_wcsicmp(szUserDomainName, g_szNT_Authority) != 0)) ) {
//
// We will come back here and do a force retry
// if the server is down.
//
retryForce: //
// Force hr to S_OK. This will be needed especially
// when we jump to the retryForce label.
//
hr = S_OK;
//
// Set Lookup on server to true so that later
// on we do not do the lookup on the server again.
// In some cases just like we fall back to local machine,
// we need to look at the server if the local machine fails.
// this will be the case for mixed locale domains.
//
DWORD dwStatus = GetDomainDNSNameForDomain( fSpecialLookup ? NULL : szUserDomainName, fForceVerify, // forceVerify
FALSE, szServerName, szDomainName );
fLookupOnServer = TRUE;
if (dwStatus) { szLookupServer = NULL; } else { szLookupServer = szServerName; } szAccountName = szUserAccountName; }
dwRet = LookupAccountName( szLookupServer, bstrTrustee, Sid, &dwSidSize, szDomainName, &dwDomainSize, (PSID_NAME_USE)&eUse ); if (!dwRet) { hr = HRESULT_FROM_WIN32(GetLastError()); } else { //
// Update the length of the SID.
//
//
// Call needed on NT4 where GetLenghtSid does not
// reset the error correctly leading to false errors.
//
SetLastError(NO_ERROR); dwTmpSidLen = GetLengthSid(Sid); if ((dwRet = GetLastError()) == NO_ERROR) { //
// Got the correct length so update dwSidSize
//
dwSidSize = dwTmpSidLen; } }
if (FAILED(hr) && hr != HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)) {
//
// This code path should not be hit often but it can
// happen on multi locale domains. The server when might
// have returned say Builtin instead of german for the same.
// If the client is german we will be looking for germanbuiltin
// and that wont work. The lookup will fail locally but
// will succeed on the server. This is especially true for
// Builtin\Print Operators as that can only be resolved on the DC.
//
if (pszServerName) { //
// Before we do a dsgetdc, we should try with
// the serverName passed in.
//
hr = S_OK; dwRet = LookupAccountName( pszServerName, bstrTrustee, Sid, &dwSidSize, szDomainName, &dwDomainSize, (PSID_NAME_USE)&eUse ); if (!dwRet) { hr = HRESULT_FROM_WIN32(GetLastError()); //
// force server name to NULL so we wont
// try this again.
//
pszServerName = NULL; } else { //
// Update the length of the SID.
//
//
// Call needed on NT4 where GetLenghtSid does not
// reset the error correctly leading to false errors.
//
SetLastError(NO_ERROR); dwTmpSidLen = GetLengthSid(Sid); if ((dwRet = GetLastError()) == NO_ERROR) { //
// Got the correct length so update dwSidSize
//
dwSidSize = dwTmpSidLen; } } }
if (FAILED(hr)) { //
// We could be here if either pszServerName was always
// NULL or if the call to the server failed.
// The only thing we can do is to retry if we know
// that the szLookupServer was NULL (that is local machine)
// or if szLookupServer was something other than the default
// server for the machine (that is we called DsGetDC with
// the name of a domain rather than NULL).
// In all other cases we should not retry and just return
// the error.
//
if (fSpecialLookup) { //
// We should not retry in this case as we will not
// get anything useful. Setting fLookupOnServer
// to true will force this (if you look above this
// is not really needed but it helps clear things)
//
fLookupOnServer = TRUE; } else { //
// This was not a special lookup, so we
// need to retry irrespective of what
// szLookupServer was.
//
fLookupOnServer = FALSE; szLookupServer = NULL; }
}
//
// This will do the correct thing even if the above
// LookUpCall failed. If not we should go down this
// as we can get stuck in an infinite loop.
//
if (FAILED(hr) && !pszServerName && !szLookupServer && !fLookupOnServer ) { //
// In this case we want to try and call
// DsGetDCName and hopefully we will get the right
// DC. fSpecialLookup will be true so that we go to
// the default DC for the machine/user.
//
fSpecialLookup = TRUE; goto retryForce; } }
//
// If failure was due to an expected error then retry
//
if (FAILED(hr) && hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE) ) { if (!fForceVerify) { fForceVerify = TRUE; goto retryForce; } }
}else {
//
// We know that LookupAccountName failed,
// so now try the U2 DS
//
dwSidSize = 0;
hr = ConvertU2TrusteeToSid( pszServerName, Credentials, bstrTrustee, Sid, &dwSidSize ); }
//
// If neither the NTDS nor the U2 conversion
// worked, then try a textual translation
//
if (FAILED(hr)) {
hr = ConvertStringToSid( bstrTrustee, &pSid, &dwSidSize ); BAIL_ON_FAILURE(hr);
memcpy(Sid,pSid, dwSidSize);
if (pSid) { LocalFree(pSid); }
}
//
// On NT4 for some reason GetLengthSID does not set lasterror to 0
//
SetLastError(NO_ERROR);
dwSidSize = GetLengthSid((PSID) Sid);
dwErr = GetLastError();
//
// This is an extra check to make sure that we have the
// correct length.
//
if (dwErr != NO_ERROR) { hr = HRESULT_FROM_WIN32(dwErr); }
BAIL_ON_FAILURE(hr); ; pSid = AllocADsMem(dwSidSize); if (!pSid) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); }
memcpy(pSid, Sid, dwSidSize);
*pdwSidSize = dwSidSize;
*ppSid = pSid;
error:
if (szUserDomainName) { FreeADsStr(szUserDomainName); }; if (szUserAccountName) { FreeADsStr(szUserAccountName); }
RRETURN(hr); }
/*
+--------------------------------------------------------------------------------+
NAME: get_sid_out_of_string
FUNCTION: Convert a string representation of a SID back into a sid. The expected format of the string is: L"S-1-5-32-549"
If a string in a different format or an incorrect or incomplete string is given, the operation is failed.
The returned sid must be free via a call to SEC_FREE.
Arguments:
string - The wide string to be converted
sid - Where the created SID is to be returned
end - Where in the string we stopped processing
RETURN:
NTSTATUS error codes or success.
+--------------------------------------------------------------------------------+ */ HRESULT ConvertStringToSid( IN PWSTR string, OUT PSID *sid, OUT PDWORD pdwSidSize ) { HRESULT hr = S_OK; BOOL fResult = FALSE;
fResult = ConvertStringSidToSid(string, sid); if(fResult) { fResult = IsValidSid(*sid); if(fResult) { *pdwSidSize = GetLengthSid(*sid); } else { if(*sid) { LocalFree(*sid); *sid = NULL; } hr = HRESULT_FROM_WIN32(ERROR_INVALID_SID); BAIL_ON_FAILURE(hr); } } else { hr = HRESULT_FROM_WIN32(ERROR_INVALID_SID); BAIL_ON_FAILURE(hr); } error:
RRETURN(hr); }
HRESULT SecCreateSidFromArray ( OUT PSID *PPSid, IN PSID_IDENTIFIER_AUTHORITY PSidAuthority, IN UCHAR SubAuthorityCount, IN ULONG SubAuthorities[], OUT PDWORD pdwSidSize ) /*++
Routine Description:
Creates a SID with desired authority and sub authorities.
NOTE: This routine allocates memory for the SID. When finished the caller should free memory using SEC_FREE (PSid).
Arguments:
PPSid -- addr of ptr to SID to be created Note: if SID creation fails ptr set to NULL
PSidAuthority -- desired value for SID authority
SubAuthorityCount -- number of sub authorities desired
SubAuthorities -- sub-authority values, MUST SPECIFY contain at least SubAuthorityCount number of values
Return Value:
STATUS_SUCCESS if SID created. STATUS_UNSUCCESSFUL otherwise.
--*/ { USHORT iSub; /* sub-authority index */ DWORD dwSidSize = 0; HRESULT hr = S_OK;
/* allocate memory for SID */
dwSidSize = RtlLengthRequiredSid(SubAuthorityCount); *PPSid = (PSID) AllocADsMem( dwSidSize ); if (! *PPSid){ hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); }
*pdwSidSize = dwSidSize;
/* initialize SID with top level SID identifier authority */ RtlInitializeSid( *PPSid, PSidAuthority, SubAuthorityCount);
/* fill in sub authorities */ for (iSub=0; iSub < SubAuthorityCount; iSub++) * RtlSubAuthoritySid( *PPSid, iSub) = SubAuthorities[iSub];
/* sanity check */
if ( ! RtlValidSid( *PPSid) ) { FreeADsMem( *PPSid); *PPSid = NULL; hr = HRESULT_FROM_WIN32(ERROR_INVALID_SID); BAIL_ON_FAILURE(hr); }
error:
RRETURN(hr); }
BOOL EquivalentServers( LPWSTR pszTargetServer, LPWSTR pszSourceServer ) { if (!pszTargetServer && !pszSourceServer) { return(TRUE); }
if (pszTargetServer && pszSourceServer) {
#ifdef WIN95
if (!_wcsicmp(pszTargetServer, pszSourceServer)) { #else
if (CompareStringW( LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, pszTargetServer, -1, pszSourceServer, -1 ) == CSTR_EQUAL ) { #endif
return(TRUE); } }
return(FALSE); }
|