You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
643 lines
19 KiB
643 lines
19 KiB
#ifndef _AUSRUTIL_H
|
|
#define _AUSRUTIL_H
|
|
|
|
#include <activeds.h>
|
|
#include "EscStr.h"
|
|
|
|
#include <lm.h>
|
|
#include <lmapibuf.h>
|
|
#include <lmshare.h>
|
|
|
|
#define SECURITY_WIN32
|
|
#include <security.h>
|
|
|
|
enum NameContextType
|
|
{
|
|
NAMECTX_SCHEMA = 0,
|
|
NAMECTX_CONFIG = 1,
|
|
NAMECTX_COUNT
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// GetADNamingContext()
|
|
// ----------------------------------------------------------------------------
|
|
inline HRESULT GetADNamingContext(NameContextType ctx, LPCWSTR* ppszContextDN)
|
|
{
|
|
const static LPCWSTR pszContextName[NAMECTX_COUNT] = { L"schemaNamingContext", L"configurationNamingContext"};
|
|
static CString strContextDN[NAMECTX_COUNT];
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if (strContextDN[ctx].IsEmpty())
|
|
{
|
|
CComVariant var;
|
|
CComPtr<IADs> pObj;
|
|
|
|
hr = ADsGetObject(L"LDAP://rootDSE", IID_IADs, (void**)&pObj);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
CComBSTR bstrProp = pszContextName[ctx];
|
|
hr = pObj->Get( bstrProp, &var );
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
strContextDN[ctx] = var.bstrVal;
|
|
*ppszContextDN = strContextDN[ctx];
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*ppszContextDN = strContextDN[ctx];
|
|
hr = S_OK;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// EnableButton
|
|
//
|
|
// Enables or disables a dialog control. If the control has the focus when
|
|
// it is disabled, the focus is moved to the next control
|
|
//--------------------------------------------------------------------------
|
|
inline void EnableButton(HWND hwndDialog, int iCtrlID, BOOL bEnable)
|
|
{
|
|
HWND hWndCtrl = ::GetDlgItem(hwndDialog, iCtrlID);
|
|
ATLASSERT(::IsWindow(hWndCtrl));
|
|
|
|
if (!bEnable && ::GetFocus() == hWndCtrl)
|
|
{
|
|
HWND hWndNextCtrl = ::GetNextDlgTabItem(hwndDialog, hWndCtrl, FALSE);
|
|
if (hWndNextCtrl != NULL && hWndNextCtrl != hWndCtrl)
|
|
{
|
|
::SetFocus(hWndNextCtrl);
|
|
}
|
|
}
|
|
|
|
::EnableWindow(hWndCtrl, bEnable);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// ErrorMsg()
|
|
// ----------------------------------------------------------------------------
|
|
inline void ErrorMsg(UINT uiError, UINT uiTitle)
|
|
{
|
|
CString csError;
|
|
CString csTitle;
|
|
|
|
csError.LoadString(uiError);
|
|
csTitle.LoadString(uiTitle);
|
|
|
|
::MessageBox(NULL, (LPCWSTR)csError, (LPCWSTR)csTitle, MB_OK | MB_TASKMODAL | MB_ICONERROR);
|
|
}
|
|
|
|
inline BOOL StrContainsDBCS(LPCTSTR szIn)
|
|
{
|
|
if( !szIn ) return FALSE;
|
|
|
|
BOOL bFound = FALSE;
|
|
TCHAR *pch = NULL;
|
|
|
|
for ( pch=(LPTSTR)szIn; *pch && !bFound; pch=_tcsinc(pch) )
|
|
{
|
|
if ( IsDBCSLeadByte((BYTE)*pch) )
|
|
{
|
|
bFound = TRUE;
|
|
}
|
|
}
|
|
|
|
return bFound;
|
|
}
|
|
|
|
inline BOOL LdapToDCName(LPCTSTR pszPath, LPTSTR pszOutBuf, int nOutBufSize)
|
|
{
|
|
if( !pszPath || !pszOutBuf || !nOutBufSize ) return FALSE;
|
|
|
|
pszOutBuf[0] = 0;
|
|
|
|
TCHAR* pszTemp = _tcsstr( pszPath, _T("DC=") );
|
|
if( !pszTemp ) return FALSE;
|
|
|
|
DWORD dwSize = nOutBufSize;
|
|
|
|
BOOLEAN bSuccess = TranslateName( pszTemp, NameFullyQualifiedDN, NameCanonical, pszOutBuf, &dwSize );
|
|
|
|
if( bSuccess && (dwSize > 2) )
|
|
{
|
|
if( pszOutBuf[dwSize-2] == _T('/') )
|
|
{
|
|
pszOutBuf[dwSize-2] = 0;
|
|
}
|
|
}
|
|
|
|
return (BOOL)bSuccess;
|
|
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// FindADsObject()
|
|
//
|
|
// szFilterFmt must be of the format "(|(cn=%1)(ou=%1))"
|
|
// NOTE: szFilterFmt must contain ONLY %1's.. i.e. %2 is right out!
|
|
// ----------------------------------------------------------------------------
|
|
inline HRESULT FindADsObject( LPCTSTR szOU, LPCTSTR szObject, LPCTSTR szFilterFmt, CString &csResult, DWORD dwRetType/*=0*/, BOOL bRoot/*=FALSE*/ )
|
|
{
|
|
if( !szOU || !szObject || !szFilterFmt ) return E_POINTER;
|
|
|
|
// Find out if the szObject contains any '(' or ')'s.. if so then we have to exit.
|
|
if ( _tcschr(szObject, _T('(')) ||
|
|
_tcschr(szObject, _T(')')) )
|
|
{
|
|
return S_FALSE;
|
|
}
|
|
|
|
HRESULT hr = S_OK;
|
|
CString csTmp = szOU;
|
|
CString csOU = L"LDAP://";
|
|
TCHAR *pch = NULL;
|
|
|
|
if ( bRoot )
|
|
{
|
|
csTmp.MakeUpper();
|
|
pch = _tcsstr( (LPCTSTR)csTmp, L"DC=" ); // Find the first DC=
|
|
if ( !pch ) return E_FAIL;
|
|
|
|
csOU += pch; // Append from the DC= on.
|
|
|
|
if ( (pch = _tcschr((LPCTSTR)csOU + 7, L'/')) != NULL )
|
|
{
|
|
// Hmmm. . something was after the DC='s... I don't even know
|
|
// if that's allowed.
|
|
// (e.g. LDAP://DC=ted,DC=microsoft,DC=com/foo)
|
|
// If so, let's end the string at the /
|
|
*pch = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
csTmp.MakeUpper();
|
|
pch = _tcsstr( (LPCTSTR)csTmp, L"LDAP://" ); // Did the string include the LDAP://?
|
|
if ( !pch )
|
|
{
|
|
csOU += csTmp;
|
|
}
|
|
else
|
|
{
|
|
csOU = csTmp;
|
|
}
|
|
// Now csOU contains the LDAP:// for sure.
|
|
}
|
|
|
|
// Set query parameters
|
|
CComPtr<IDirectorySearch> spDirSearch = NULL;
|
|
ADS_SEARCH_HANDLE hSearch; // Handle used for searching.
|
|
ADS_SEARCH_COLUMN col; // Used to hold the current column.
|
|
CString csFilter;
|
|
LPTSTR pszAttr[] = { _T("cn"), _T("distinguishedName"), _T("description"), _T("sAMAccountName"), _T("mailNickname") };
|
|
DWORD dwCount = sizeof(pszAttr) / sizeof(LPTSTR);
|
|
|
|
|
|
csFilter.FormatMessage(szFilterFmt, szObject);
|
|
|
|
// Open our search object.
|
|
hr = ::ADsOpenObject(const_cast<LPTSTR>((LPCTSTR)csOU), NULL, NULL, ADS_SECURE_AUTHENTICATION, IID_IDirectorySearch, (void**)&spDirSearch);
|
|
if ( !SUCCEEDED(hr) )
|
|
{
|
|
_ASSERT(FALSE);
|
|
return hr;
|
|
}
|
|
|
|
// Search for out object.
|
|
hr = spDirSearch->ExecuteSearch(const_cast<LPTSTR>((LPCTSTR)csFilter), pszAttr, dwCount, &hSearch);
|
|
if ( !SUCCEEDED(hr) )
|
|
{
|
|
return(hr);
|
|
}
|
|
|
|
if ( spDirSearch->GetNextRow(hSearch) == S_ADS_NOMORE_ROWS )
|
|
{
|
|
spDirSearch->CloseSearchHandle(hSearch);
|
|
return(E_FAIL);
|
|
}
|
|
|
|
// If we got to here, then we got the object, so let's get the LDAP path to the
|
|
// object so that we can return it to the caller.
|
|
hr = spDirSearch->GetColumn(hSearch, pszAttr[dwRetType], &col);
|
|
if ( !SUCCEEDED(hr) )
|
|
{
|
|
_ASSERT(FALSE);
|
|
csResult = _T("");
|
|
}
|
|
else
|
|
{
|
|
csResult = col.pADsValues->CaseExactString;
|
|
spDirSearch->FreeColumn(&col);
|
|
}
|
|
|
|
spDirSearch->CloseSearchHandle(hSearch);
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
inline tstring GetDomainPath( LPCTSTR lpServer )
|
|
{
|
|
if( !lpServer ) return _T("");
|
|
|
|
// get the domain information
|
|
CComVariant var;
|
|
tstring strRet = _T("");
|
|
|
|
TCHAR pszString[MAX_PATH*2] = {0};
|
|
_sntprintf( pszString, (MAX_PATH*2)-1, L"LDAP://%s/rootDSE", lpServer );
|
|
|
|
CComPtr<IADs> pDS = NULL;
|
|
HRESULT hr = ::ADsGetObject( pszString, IID_IADs, (void**)&pDS );
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
CComBSTR bstrProp = _T("defaultNamingContext");
|
|
hr = pDS->Get( bstrProp, &var );
|
|
}
|
|
|
|
if( SUCCEEDED(hr) && (V_VT(&var) == VT_BSTR) )
|
|
{
|
|
strRet = V_BSTR( &var );
|
|
}
|
|
|
|
|
|
return strRet;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: RemoveTrailingWhitespace
|
|
//
|
|
// Synopsis: Trailing white space is replaced by NULLs.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
inline void RemoveTrailingWhitespace(LPTSTR pszIn)
|
|
{
|
|
if( !pszIn ) return;
|
|
|
|
int nLen = _tcslen(pszIn);
|
|
|
|
while( nLen )
|
|
{
|
|
if( !iswspace(pszIn[nLen - 1]) )
|
|
{
|
|
return;
|
|
}
|
|
pszIn[nLen - 1] = L'\0';
|
|
nLen--;
|
|
}
|
|
}
|
|
|
|
inline tstring StrFormatSystemError( HRESULT hrErr )
|
|
{
|
|
tstring strError = _T("");
|
|
LPVOID lpMsgBuf = NULL;
|
|
|
|
// look up the error from the system
|
|
if ( ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL,
|
|
hrErr,
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
(LPTSTR)&lpMsgBuf,
|
|
0,
|
|
NULL ))
|
|
{
|
|
if( lpMsgBuf )
|
|
{
|
|
strError = (LPTSTR)lpMsgBuf;
|
|
LocalFree( lpMsgBuf );
|
|
}
|
|
}
|
|
|
|
// return the error string
|
|
return strError;
|
|
}
|
|
|
|
inline tstring StrGetWindowText( HWND hWnd )
|
|
{
|
|
if( !hWnd || !IsWindow(hWnd) )
|
|
{
|
|
return _T("");
|
|
}
|
|
|
|
TSTRING strRet = _T("");
|
|
INT iLen = GetWindowTextLength(hWnd);
|
|
TCHAR* pszText = new TCHAR[ iLen + 1 ];
|
|
if ( pszText )
|
|
{
|
|
if ( GetWindowText(hWnd, pszText, iLen + 1) )
|
|
{
|
|
strRet = pszText;
|
|
}
|
|
|
|
delete[] pszText;
|
|
}
|
|
|
|
return strRet;
|
|
}
|
|
|
|
inline HRESULT SetSecInfoMask( LPUNKNOWN punk, SECURITY_INFORMATION si )
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
if( punk )
|
|
{
|
|
CComPtr<IADsObjectOptions> spOptions;
|
|
hr = punk->QueryInterface( IID_IADsObjectOptions, (void**)&spOptions );
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
VARIANT var;
|
|
VariantInit( &var );
|
|
V_VT( &var ) = VT_I4;
|
|
V_I4( &var ) = si;
|
|
|
|
hr = spOptions->SetOption( ADS_OPTION_SECURITY_MASK, var );
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: GetSDForDsObject
|
|
// Synopsis: Reads the security descriptor from the specied DS object
|
|
// It only reads the DACL portion of the security descriptor
|
|
//
|
|
// Arguments: [IN pDsObject] -- DS object
|
|
// [ppDACL] --pointer to dacl in ppSD is returned here
|
|
// [OUT ppSD] -- Security descriptor returned here.
|
|
// calling API must free this by calling LocalFree
|
|
//
|
|
// Notes: The returned security descriptor must be freed with LocalFree
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline HRESULT GetSDForDsObject( IDirectoryObject* pDsObject, PACL* ppDACL, PSECURITY_DESCRIPTOR* ppSD )
|
|
{
|
|
if(!pDsObject || !ppSD) return E_POINTER;
|
|
|
|
*ppSD = NULL;
|
|
if(ppDACL)
|
|
{
|
|
*ppDACL = NULL;
|
|
}
|
|
|
|
HRESULT hr = S_OK;
|
|
PADS_ATTR_INFO pSDAttributeInfo = NULL;
|
|
|
|
WCHAR const c_szSDProperty[] = L"nTSecurityDescriptor";
|
|
LPWSTR pszProperty = (LPWSTR)c_szSDProperty;
|
|
|
|
// Set the SECURITY_INFORMATION mask to DACL_SECURITY_INFORMATION
|
|
hr = SetSecInfoMask(pDsObject, DACL_SECURITY_INFORMATION);
|
|
|
|
DWORD dwAttributesReturned;
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
// Read the security descriptor attribute
|
|
hr = pDsObject->GetObjectAttributes( &pszProperty, 1, &pSDAttributeInfo, &dwAttributesReturned );
|
|
if(SUCCEEDED(hr) && !pSDAttributeInfo)
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
}
|
|
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
if((ADSTYPE_NT_SECURITY_DESCRIPTOR == pSDAttributeInfo->dwADsType) &&
|
|
(ADSTYPE_NT_SECURITY_DESCRIPTOR == pSDAttributeInfo->pADsValues->dwType))
|
|
{
|
|
*ppSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, pSDAttributeInfo->pADsValues->SecurityDescriptor.dwLength);
|
|
if (!*ppSD)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
}
|
|
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
CopyMemory( *ppSD, pSDAttributeInfo->pADsValues->SecurityDescriptor.lpValue, pSDAttributeInfo->pADsValues->SecurityDescriptor.dwLength );
|
|
|
|
if( ppDACL )
|
|
{
|
|
BOOL bDaclPresent,bDaclDeafulted;
|
|
if( !GetSecurityDescriptorDacl(*ppSD, &bDaclPresent, ppDACL, &bDaclDeafulted) )
|
|
{
|
|
DWORD dwErr = GetLastError();
|
|
hr = HRESULT_FROM_WIN32(dwErr);
|
|
}
|
|
}
|
|
}
|
|
|
|
if( pSDAttributeInfo )
|
|
{
|
|
FreeADsMem( pSDAttributeInfo );
|
|
}
|
|
|
|
if( FAILED(hr) )
|
|
{
|
|
if(*ppSD)
|
|
{
|
|
LocalFree(*ppSD);
|
|
*ppSD = NULL;
|
|
if(ppDACL)
|
|
*ppDACL = NULL;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: GetSDForDsObjectPath
|
|
// Synopsis: Reads the security descriptor from the specied DS object
|
|
// It only reads the DACL portion of the security descriptor
|
|
//
|
|
// Arguments: [IN pszObjectPath] -- LDAP Path of ds object
|
|
// [ppDACL] --pointer to dacl in ppSD is returned here
|
|
// [OUT ppSD] -- Security descriptor returned here.
|
|
// calling API must free this by calling LocalFree
|
|
//
|
|
// Notes: The returned security descriptor must be freed with LocalFree
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
inline HRESULT GetSDForDsObjectPath( LPCWSTR pszObjectPath, PACL* ppDACL, PSECURITY_DESCRIPTOR* ppSecurityDescriptor )
|
|
{
|
|
if(!pszObjectPath || !ppSecurityDescriptor) return E_POINTER;
|
|
|
|
CComPtr<IDirectoryObject> spDsObject = NULL;
|
|
HRESULT hr = ADsGetObject(pszObjectPath, IID_IDirectoryObject,(void**)&spDsObject);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = GetSDForDsObject( spDsObject, ppDACL, ppSecurityDescriptor );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: SetDaclForDsObject
|
|
// Synopsis: Sets the the DACL for the specified DS object
|
|
//
|
|
// Arguments: [IN pDsObject] -- ds object
|
|
// [IN pDACL] --pointer to dacl to be set
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
inline HRESULT SetDaclForDsObject( IDirectoryObject* pDsObject, PACL pDACL )
|
|
{
|
|
if(!pDsObject || !pDACL) return E_POINTER;
|
|
|
|
WCHAR const c_szSDProperty[] = L"nTSecurityDescriptor";
|
|
PSECURITY_DESCRIPTOR pSD = NULL;
|
|
PSECURITY_DESCRIPTOR pSDCurrent = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
//Get the current SD for the object
|
|
hr = GetSDForDsObject(pDsObject,NULL,&pSDCurrent);
|
|
|
|
//Get the control for the current security descriptor
|
|
SECURITY_DESCRIPTOR_CONTROL currentControl;
|
|
DWORD dwRevision = 0;
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
if( !GetSecurityDescriptorControl(pSDCurrent, ¤tControl, &dwRevision) )
|
|
{
|
|
DWORD dwErr = GetLastError();
|
|
hr = HRESULT_FROM_WIN32(dwErr);
|
|
}
|
|
}
|
|
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
//Allocate the buffer for Security Descriptor
|
|
pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH + pDACL->AclSize);
|
|
if(!pSD)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
if(!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION))
|
|
{
|
|
DWORD dwErr = GetLastError();
|
|
hr = HRESULT_FROM_WIN32(dwErr);
|
|
}
|
|
}
|
|
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
PISECURITY_DESCRIPTOR pISD = (PISECURITY_DESCRIPTOR)pSD;
|
|
|
|
//
|
|
// Finally, build the security descriptor
|
|
//
|
|
pISD->Control |= SE_DACL_PRESENT | SE_DACL_AUTO_INHERIT_REQ | (currentControl & (SE_DACL_PROTECTED | SE_DACL_AUTO_INHERITED));
|
|
|
|
if (pDACL->AclSize > 0)
|
|
{
|
|
pISD->Dacl = (PACL)(pISD + 1);
|
|
CopyMemory(pISD->Dacl, pDACL, pDACL->AclSize);
|
|
}
|
|
|
|
// We are only setting DACL information
|
|
hr = SetSecInfoMask(pDsObject, DACL_SECURITY_INFORMATION);
|
|
}
|
|
|
|
SECURITY_DESCRIPTOR_CONTROL sdControl = 0;
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
//
|
|
// If necessary, make a self-relative copy of the security descriptor
|
|
//
|
|
if(!GetSecurityDescriptorControl(pSD, &sdControl, &dwRevision))
|
|
{
|
|
DWORD dwErr = GetLastError();
|
|
hr = HRESULT_FROM_WIN32(dwErr);
|
|
}
|
|
}
|
|
|
|
DWORD dwSDLength = 0;
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
// Need the total size
|
|
dwSDLength = GetSecurityDescriptorLength(pSD);
|
|
|
|
if (!(sdControl & SE_SELF_RELATIVE))
|
|
{
|
|
PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, dwSDLength);
|
|
|
|
if (psd == NULL || !MakeSelfRelativeSD(pSD, psd, &dwSDLength))
|
|
{
|
|
DWORD dwErr = GetLastError();
|
|
hr = HRESULT_FROM_WIN32(dwErr);
|
|
}
|
|
|
|
// Point to the self-relative copy
|
|
LocalFree(pSD);
|
|
pSD = psd;
|
|
}
|
|
}
|
|
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
ADSVALUE attributeValue;
|
|
attributeValue.dwType = ADSTYPE_NT_SECURITY_DESCRIPTOR;
|
|
attributeValue.SecurityDescriptor.dwLength = dwSDLength;
|
|
attributeValue.SecurityDescriptor.lpValue = (LPBYTE)pSD;
|
|
|
|
ADS_ATTR_INFO attributeInfo;
|
|
attributeInfo.pszAttrName = (LPWSTR)c_szSDProperty;
|
|
attributeInfo.dwControlCode = ADS_ATTR_UPDATE;
|
|
attributeInfo.dwADsType = ADSTYPE_NT_SECURITY_DESCRIPTOR;
|
|
attributeInfo.pADsValues = &attributeValue;
|
|
attributeInfo.dwNumValues = 1;
|
|
|
|
// Write the security descriptor
|
|
DWORD dwAttributesModified;
|
|
hr = pDsObject->SetObjectAttributes(&attributeInfo, 1, &dwAttributesModified);
|
|
}
|
|
|
|
if(pSDCurrent)
|
|
{
|
|
LocalFree(pSDCurrent);
|
|
}
|
|
|
|
if(pSD)
|
|
{
|
|
LocalFree(pSD);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
inline HRESULT SetDaclForDsObjectPath( LPCWSTR pszObjectPath, PACL pDACL )
|
|
{
|
|
// VAlidate the parameters
|
|
if(!pszObjectPath || !pDACL) return E_POINTER;
|
|
|
|
// Get the object and then pass it on to the helper function
|
|
CComPtr<IDirectoryObject> spDsObject = NULL;
|
|
HRESULT hr = ADsGetObject( pszObjectPath, IID_IDirectoryObject, (void**)&spDsObject );
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
hr = SetDaclForDsObject( spDsObject, pDACL );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
#endif // _AUSRUTIL_H
|