|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 2000.
//
// File: cadssec.cxx
//
// Contents: This file contains the support ADsSecurityUtility class
// implementation and the support routines it requires. The
// default interface for the ADsSecurityClassUtility class
// is IADsSecurityUtility.
//
// History: 10-11-00 AjayR Created.
//
//----------------------------------------------------------------------------
#include "oleds.hxx"
//
// Helper functions.
//
//+---------------------------------------------------------------------------
// Function: GetServerAndResource - Helper routine.
//
// Synopsis: Splits the string into a serverName piece and rest piece.
// This is used for fileshare paths like \\Computer\share to return
// \\computer and share. In the case of registry a string like
// \\Computer\HKLM\Microsoft will be split into \\Computer and
// HKLM\Microsoft. if there is no computer name specified, then
// the serverName will be NULL.
//
// Arguments: pszName - Name to be split.
// ppszServer - Return value for server name.
// ppszResource - Return value for rest of string.
//
// Returns: S_OK or any appropriate error code.
//
// Modifies: ppSD and pdwLength on success.
//
//----------------------------------------------------------------------------
HRESULT GetServerAndResource( LPWSTR pszName, LPWSTR *ppszServer, LPWSTR *ppszResource ) { HRESULT hr = S_OK; DWORD dwLength = wcslen(pszName); LPWSTR pszTemp = pszName; LPWSTR pszServer = NULL; LPWSTR pszResource = NULL; DWORD dwLen = 0; BOOL fNoServer = FALSE;
*ppszServer = NULL; *ppszResource = NULL;
//
// If we have just 1 \ or no \'s there is no server name.
//
if ((dwLength < 2) || (pszName[0] != L'\\') || (pszName[1] != L'\\') ) { fNoServer = TRUE; } if (fNoServer) { //
// Name is the entire string passed in.
//
pszResource = AllocADsStr(pszName); if (!pszResource) { BAIL_ON_FAILURE(hr = E_FAIL); }
*ppszResource = pszResource; RRETURN(hr); }
//
// Make sure that the first 2 chars are \\ //
if (pszTemp[0] != L'\\' || pszTemp[1] != L'\\' ) { BAIL_ON_FAILURE(hr = E_INVALIDARG); } pszTemp += 2;
while (pszTemp && *pszTemp != L'\\') { dwLen++; pszTemp++; }
if (!pszTemp || !*pszTemp || !dwLen ) { BAIL_ON_FAILURE(hr = E_INVALIDARG); }
dwLen += 2; // the 2 \\ in the serverName
//
// Advance past the \ in \\testShare\FileShare.
//
pszTemp++; if (!pszTemp || !*pszTemp) { BAIL_ON_FAILURE(hr = E_INVALIDARG) }
//
// If we get here we have valid server and share names.
//
pszServer = (LPWSTR) AllocADsMem((dwLen+1) * sizeof(WCHAR)); if (!pszServer) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
wcsncpy(pszServer, pszName, dwLen);
pszResource = AllocADsStr(pszTemp); if (!pszResource) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
*ppszServer = pszServer; *ppszResource = pszResource;
error:
if (FAILED(hr)) { if (pszResource) { FreeADsMem(pszResource); }
if (pszServer) { FreeADsMem(pszServer); } }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: GetKeyRootAndSubKey - Helper routine.
//
// Synopsis: Gets the root (such as HKLM) from the registry key path. This
// is needed when we open a handle to the key. The rest of the path
// constitutes the SubKey name.
//
// Arguments: pszKeyName - Name of the key we need to open.
// ppszSubKey - Return value for the subKey
// phKey - Return value for key root to open.
//
// Returns: S_OK or any appropriate error code.
//
// Modifies: phKey, NULL on failure and one of
// HKEY_USERS, HKEY_CURRENT_USER, HKEY_CURRENT_CONFIG,
// HKEY_LOCAL_MACHINE, HKEY_CLASSES_ROOT
// or HKEY_PERFORMANCE_DATA on success.
//
//----------------------------------------------------------------------------
HRESULT GetKeyRootAndSubKey( LPWSTR pszKeyName, LPWSTR * ppszSubKey, HKEY * phKey ) { HRESULT hr = S_OK; HKEY hKey = NULL; LPWSTR pszRoot = NULL; LPWSTR pszTemp = pszKeyName; LPWSTR pszSubKey = NULL; DWORD dwLen = 0;
*phKey = NULL; *ppszSubKey = NULL;
while (pszTemp && *pszTemp && *pszTemp != L'\\') { dwLen++; pszTemp++; }
//
// If the length is less than 3 something is wrong.
//
if ((dwLen < 3) || !pszTemp || !*pszTemp ) { BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER); }
//
// To get the subkey, we need to move past the \.
//
pszTemp++; if (pszTemp && *pszTemp) { pszSubKey = AllocADsStr(pszTemp); if (!pszSubKey) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); } }
pszRoot = (LPWSTR) AllocADsMem((dwLen+1) * sizeof(WCHAR)); if (!pszRoot) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
//
// Copy over the root so we can use it in the subsequent comparisions.
//
wcsncpy(pszRoot, pszKeyName, dwLen);
if (_wcsicmp( pszRoot, L"HKEY_CLASSES_ROOT") == 0 || _wcsicmp( pszRoot, L"HKCR") == 0 ) { hKey = HKEY_CLASSES_ROOT; } else if (_wcsicmp( pszRoot, L"HKEY_LOCAL_MACHINE") == 0 || _wcsicmp( pszRoot, L"HKLM") == 0 ) { hKey = HKEY_LOCAL_MACHINE; } else if (_wcsicmp(pszRoot, L"HKEY_CURRENT_CONFIG") == 0 || _wcsicmp(pszRoot, L"HKCC") == 0 ) { hKey = HKEY_CURRENT_CONFIG; } else if (_wcsicmp(pszRoot, L"HKEY_CURRENT_USER" ) == 0 || _wcsicmp( pszRoot, L"HKCU") == 0 ) { hKey = HKEY_CURRENT_USER; } else if (_wcsicmp(pszRoot, L"HKEY_USERS") == 0 || _wcsicmp(pszRoot, L"HKU") ) { hKey = HKEY_USERS; } else if ( _wcsicmp(pszRoot, L"HKEY_PERFORMANCE_DATA") == 0) { hKey = HKEY_PERFORMANCE_DATA; } else { //
// Has to be one of the above.
//
BAIL_ON_FAILURE(hr = E_FAIL); } *phKey = hKey; *ppszSubKey = pszSubKey;
error:
if (pszRoot) { FreeADsStr(pszRoot); }
if (FAILED(hr) && pszSubKey) { FreeADsStr(pszSubKey); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: ConvertRawSDToBinary - Helper routine.
//
// Synopsis: Converts the binary SD to a VT_UI1 | VT_ARRAY.
//
// Arguments: pSecurityDescriptor - Binary sd to convert.
// dwLength - Length of SD.
// pVariant - Return value.
//
// Returns: S_OK or any appropriate error code.
//
// Modifies: pVariant to point to IID_IADsSecurityDescriptor on success.
//
//----------------------------------------------------------------------------
HRESULT ConvertRawSDToBinary( PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD dwLength, VARIANT *pVariant ) { HRESULT hr = S_OK; SAFEARRAY * aList = NULL; SAFEARRAYBOUND aBound; CHAR HUGEP *pArray = NULL; aBound.lLbound = 0; aBound.cElements = dwLength;
aList = SafeArrayCreate( VT_UI1, 1, &aBound ); if (!aList) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
hr = SafeArrayAccessData( aList, (void HUGEP * FAR *) &pArray ); BAIL_ON_FAILURE(hr);
memcpy( pArray, pSecurityDescriptor, aBound.cElements ); SafeArrayUnaccessData( aList );
V_VT(pVariant) = VT_ARRAY | VT_UI1; V_ARRAY(pVariant) = aList;
RRETURN(hr);
error:
if ( aList ) { SafeArrayDestroy( aList ); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: ConvertRawSDToHexString - Helper routine.
//
// Synopsis: Converts the binary SD to a VT_BSTR in hex string format.
//
// Arguments: pSecurityDescriptor - Binary sd to convert.
// dwLength - Length of SD.
// pVariant - Return value for VT_BSTR.
//
// Returns: S_OK or any appropriate error code.
//
// Modifies: pVariant to point to IID_IADsSecurityDescriptor on success.
//
//----------------------------------------------------------------------------
HRESULT ConvertRawSDToHexString( PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD dwLength, VARIANT *pVariant ) { HRESULT hr = S_OK; LPWSTR pszHexStr = NULL; BSTR bstrHexSD = NULL; WCHAR szSmallStr[10]; pszHexStr = (LPWSTR) AllocADsMem((dwLength+1) * 2 * sizeof(WCHAR)); if (!pszHexStr) { BAIL_ON_FAILURE(hr); }
for (DWORD dwCtr = 0; dwCtr < dwLength; dwCtr++) { wsprintf( szSmallStr, L"%02x", ((BYTE*)pSecurityDescriptor)[dwCtr] ); wcscat(pszHexStr, szSmallStr); }
hr = ADsAllocString(pszHexStr, &bstrHexSD);
if (SUCCEEDED(hr)) { pVariant->vt = VT_BSTR; pVariant->bstrVal = bstrHexSD; }
error:
if (pszHexStr) { FreeADsMem(pszHexStr); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: ConvertHexSDToRawSD - Helper routine.
//
// Synopsis: Converts the hex string SD to a binary SD.
//
// Arguments: pVarHexSD - Variant with hex string.
// ppSecurityDescriptor - Return value for binary SD
// pdwLength - Return value for length of SD.
//
// Returns: S_OK or any appropriate error code.
//
// Modifies: ppSecurityDescriptor and pdwLength updated accordingly.
//
//----------------------------------------------------------------------------
HRESULT ConvertHexSDToRawSD( PVARIANT pVarHexSD, PSECURITY_DESCRIPTOR *ppSecurityDescriptor, DWORD *pdwLength ) { HRESULT hr = S_OK; LPWSTR pszHexSD = V_BSTR(pVarHexSD); DWORD dwLen; LPBYTE lpByte = NULL;
*ppSecurityDescriptor = NULL; *pdwLength = 0;
if (!pszHexSD || ((dwLen = wcslen(pszHexSD)) == 0) ) { //
// NULL SD.
//
RRETURN(S_OK); }
dwLen = wcslen(pszHexSD);
//
// Length has to be even.
//
if (((dwLen/2) * 2) != dwLen) { BAIL_ON_FAILURE(hr = E_ADS_CANT_CONVERT_DATATYPE); }
dwLen /= 2;
if (dwLen) { lpByte = (LPBYTE) AllocADsMem(dwLen); if (!lpByte) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); } //
// Go through and read one 2 hex chars at a time.
//
for ( DWORD dwCtr = 0; (dwCtr < dwLen) && (pszHexSD && *pszHexSD); dwCtr++ ) {
DWORD dwCount, dwHexVal; dwCount = swscanf(pszHexSD, L"%02x", &dwHexVal); //
// The read has to be successful and the data valid.
//
if (dwCount != 1) { BAIL_ON_FAILURE(hr = E_FAIL); }
//
// Make sure that the value is in the correct range.
//
if (dwHexVal & (0xFFFFFF00)) { BAIL_ON_FAILURE(hr = E_INVALIDARG); }
lpByte[dwCtr] = (BYTE) dwHexVal;
pszHexSD++; if (!pszHexSD) { BAIL_ON_FAILURE(hr = E_INVALIDARG); } pszHexSD++; } // for loop
//
// The sd translation was succesful.
//
*ppSecurityDescriptor = (PSECURITY_DESCRIPTOR)(LPVOID) lpByte; *pdwLength = dwLen; } // if the string had any data in it.
error:
if (FAILED(hr) && lpByte) { FreeADsMem(lpByte); } RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: ConvertBinarySDToRawSD - Helper routine.
//
// Synopsis: Converts a VT_UI1 | VT_ARRAY to a binary SD.
//
// Arguments: pvVarBinSD - The input variant array to convert.
// ppSecurityDescriptor - Return value for binary sd.
// pdwLength - Return value for length of binary sd.
//
// Returns: S_OK or any appropriate error code.
//
// Modifies: ppSecurityDescriptor and pdwLength modified appropriately.
//
//----------------------------------------------------------------------------
HRESULT ConvertBinarySDToRawSD( PVARIANT pvVarBinSD, PSECURITY_DESCRIPTOR *ppSecurityDescriptor, DWORD *pdwLength ) { HRESULT hr = S_OK; LPVOID lpMem = NULL; long lBoundLower = -1; long lBoundUpper = -1; CHAR HUGEP *pArray = NULL;
*ppSecurityDescriptor = NULL; *pdwLength = 0; //
// Make sure we have an array and then get length.
//
if( pvVarBinSD->vt != (VT_ARRAY | VT_UI1)) { RRETURN(hr = E_ADS_CANT_CONVERT_DATATYPE); }
hr = SafeArrayGetLBound( V_ARRAY(pvVarBinSD), 1, &lBoundLower ); BAIL_ON_FAILURE(hr);
hr = SafeArrayGetUBound( V_ARRAY(pvVarBinSD), 1, &lBoundUpper ); BAIL_ON_FAILURE(hr);
if ((lBoundUpper == -1) && (lBoundLower == -1) ) { //
// Nothing further to do in this case.
//
; } else { long lLength;
lLength = (lBoundUpper - lBoundLower) + 1; lpMem = AllocADsMem(lLength); if (!lpMem) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
hr = SafeArrayAccessData( V_ARRAY(pvVarBinSD), (void HUGEP * FAR *) &pArray ); BAIL_ON_FAILURE(hr);
memcpy(lpMem, pArray, lLength);
SafeArrayUnaccessData(V_ARRAY(pvVarBinSD));
*ppSecurityDescriptor = (PSECURITY_DESCRIPTOR) lpMem; *pdwLength = (DWORD) lLength; }
error:
if (FAILED(hr) && lpMem) { FreeADsMem(lpMem); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: GetRawSDFromFile - Helper routine.
//
// Synopsis: Gets the security descriptor from the file in binary format.
//
// Arguments: pszFileName - Name of file to get sd from.
// secInfo - Security mask to use for the operation.
// ppSD - Return value for the SD.
// pdwLength - Return value for the lenght of the SD.
//
// Returns: S_OK or any appropriate error code.
//
// Modifies: ppSD and pdwLength on success.
//
//----------------------------------------------------------------------------
HRESULT GetRawSDFromFile( LPWSTR pszFileName, SECURITY_INFORMATION secInfo, PSECURITY_DESCRIPTOR *ppSD, PDWORD pdwLength ) { HRESULT hr = S_OK; DWORD dwLength = 0; PSECURITY_DESCRIPTOR pSD = NULL;
*ppSD = NULL; *pdwLength = 0;
//
// Get the length of the SD.
//
if (!GetFileSecurity( pszFileName, secInfo, NULL, 0, &dwLength ) && (dwLength == 0) ) { //
// There was an error.
//
BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(GetLastError())); }
if (dwLength == 0) { BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(GetLastError())); } pSD = (PSECURITY_DESCRIPTOR) AllocADsMem(dwLength); if (!pSD) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
if (!GetFileSecurity( pszFileName, secInfo, pSD, dwLength, &dwLength ) ) { BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(GetLastError())); }
*pdwLength = dwLength; *ppSD = pSD;
error:
if (FAILED(hr) && pSD) { FreeADsMem(pSD); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: SetRawSDToFile - Helper routine.
//
// Synopsis: Sets the binary security descriptor on the file.
//
// Arguments: pszFileName - Name of file to set sd on.
// secInfo - Security mask to use for the operation.
// pSD - Value of SD to set.
// dwLength - Length of the sd.
//
// Returns: S_OK or any appropriate error code.
//
// Modifies: N/A.
//
//----------------------------------------------------------------------------
HRESULT SetRawSDToFile( LPWSTR pszFileName, SECURITY_INFORMATION secInfo, PSECURITY_DESCRIPTOR pSD ) { HRESULT hr = S_OK; if (!SetFileSecurity( pszFileName, secInfo, pSD ) ) { RRETURN(HRESULT_FROM_WIN32(GetLastError())); } else { RRETURN(S_OK); } }
//+---------------------------------------------------------------------------
// Function: GetRawSDFromFileShare - Helper routine.
//
// Synopsis: Gets the security descriptor from the fileshare in bin format.
//
// Arguments: pszFileShareName - Name of fileshare to get sd from.
// ppSD - Return value for the SD.
// pdwLength - Return value for the lenght of the SD.
//
// Returns: S_OK or any appropriate error code.
//
// Modifies: ppSD and pdwLength on success.
//
//----------------------------------------------------------------------------
HRESULT GetRawSDFromFileShare( LPWSTR pszFileShareName, PSECURITY_DESCRIPTOR *ppSD, PDWORD pdwLength ) { HRESULT hr = S_OK; LPWSTR pszServerName = NULL; LPWSTR pszShareName = NULL; DWORD dwLength = 0; PSECURITY_DESCRIPTOR pSD = NULL; SHARE_INFO_502 * pShareInfo502 = NULL; NET_API_STATUS nasStatus = NERR_Success;
*ppSD = NULL; *pdwLength = 0;
//
// We need to split the name into serverName and shareName
//
hr = GetServerAndResource( pszFileShareName, &pszServerName, &pszShareName ); BAIL_ON_FAILURE(hr);
//
// Only 502 level call returns the SD Info.
//
nasStatus = NetShareGetInfo( pszServerName, pszShareName, 502, (LPBYTE *)&pShareInfo502 ); if (nasStatus != NERR_Success) { BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(nasStatus)); }
//
// If the SD is non NULL process the SD.
//
if (pShareInfo502->shi502_security_descriptor) { //
// Get the length of the SD, it should not be 0.
//
SetLastError(0); dwLength = GetSecurityDescriptorLength( pShareInfo502->shi502_security_descriptor );
//
// The return length should not be zero.
//
if (dwLength == 0) { BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(GetLastError())); } pSD = (PSECURITY_DESCRIPTOR) AllocADsMem(dwLength); if (!pSD) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); } memcpy(pSD, pShareInfo502->shi502_security_descriptor, dwLength); *ppSD = pSD; *pdwLength = dwLength; } else { //
// The SD was NULL the ret values are set correctly
//
; }
error:
if (pszServerName) { FreeADsStr(pszServerName); }
if (pszShareName) { FreeADsStr(pszShareName); }
if (pShareInfo502) { NetApiBufferFree(pShareInfo502); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: SetRawSDToFileShare - Helper routine.
//
// Synopsis: Sets the binary SD on the fileshare.
//
// Arguments: pszFileShare - Name of fileshare to set sd on.
// pSD - The SD to set.
//
// Returns: S_OK or any appropriate error code.
//
// Modifies: N/A.
//
//----------------------------------------------------------------------------
HRESULT SetRawSDToFileShare( LPWSTR pszFileShare, PSECURITY_DESCRIPTOR pSD ) { HRESULT hr = S_OK; LPWSTR pszServerName = NULL; LPWSTR pszShareName = NULL; SHARE_INFO_502 * pShareInfo502 = NULL; NET_API_STATUS nasStatus = NERR_Success; PSECURITY_DESCRIPTOR pTempSD = NULL;
//
// We need to split the name into serverName and shareName
//
hr = GetServerAndResource( pszFileShare, &pszServerName, &pszShareName ); BAIL_ON_FAILURE(hr);
//
// Ideally we should use 1501 level but that is only on Win2k. So
// we need to read the info, update SD and then set it.
//
nasStatus = NetShareGetInfo( pszServerName, pszShareName, 502, (LPBYTE *) &pShareInfo502 ); if (nasStatus != NERR_Success) { BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(nasStatus)); }
//
// Store away the SD so we restore before free.
//
pTempSD = pShareInfo502->shi502_security_descriptor;
pShareInfo502->shi502_security_descriptor = pSD;
nasStatus = NetShareSetInfo( pszServerName, pszShareName, 502, (LPBYTE) pShareInfo502, NULL );
pShareInfo502->shi502_security_descriptor = pTempSD;
if (nasStatus != NERR_Success) { BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(nasStatus)); }
error:
if (pShareInfo502) { NetApiBufferFree(pShareInfo502); }
if (pszServerName) { FreeADsStr(pszServerName); } if (pszShareName) { FreeADsStr(pszShareName); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: GetRawSDFromRegistry - Helper routine.
//
// Synopsis: Gets the security descriptor from the registry in bin format.
//
// Arguments: pszFileRegKeyName - Name of fileshare to get sd from.
// secInfo - Security mask to use for the operation.
// ppSD - Return value for the SD.
// pdwLength - Return value for the lenght of the SD.
//
// Returns: S_OK or any appropriate error code.
//
// Modifies: ppSD and pdwLength on success.
//
//----------------------------------------------------------------------------
HRESULT GetRawSDFromRegistry( LPWSTR pszFileRegKeyName, SECURITY_INFORMATION secInfo, PSECURITY_DESCRIPTOR *ppSD, PDWORD pdwLength ) { HRESULT hr; LPWSTR pszServerName = NULL; LPWSTR pszKeyName = NULL; LPWSTR pszSubKey = NULL; DWORD dwLength = 0; DWORD dwErr; PSECURITY_DESCRIPTOR pSD = NULL; HKEY hKey = NULL; HKEY hKeyRoot = NULL; HKEY hKeyMachine = NULL;
*ppSD = NULL; *pdwLength = 0;
//
// We need to split the name into serverName and shareName
//
hr = GetServerAndResource( pszFileRegKeyName, &pszServerName, &pszKeyName ); BAIL_ON_FAILURE(hr);
//
// pszKeyName has to have a valid string. We need to process it
// to find out which key set we need to open (such as HKLM).
//
hr = GetKeyRootAndSubKey(pszKeyName, &pszSubKey, &hKeyRoot); BAIL_ON_FAILURE(hr);
//
// Need to open the hKeyRoot on the appropriate machine.
// If the serverName is NULL it will be local machine.
//
dwErr = RegConnectRegistry( pszServerName, hKeyRoot, &hKeyMachine ); if (dwErr) { BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(dwErr)); }
//
// Open the key and try and read the security descriptor
//
dwErr = RegOpenKeyEx( hKeyMachine, pszSubKey, 0, KEY_READ, &hKey ); if (dwErr) { BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(dwErr)); }
dwErr = RegGetKeySecurity( hKey, secInfo, pSD, &dwLength ); if (dwLength == 0) { BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(dwErr)); }
pSD = (PSECURITY_DESCRIPTOR) AllocADsMem(dwLength); if (!pSD) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
dwErr = RegGetKeySecurity( hKey, secInfo, pSD, &dwLength ); if (dwErr) { BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(dwErr)); }
*ppSD = pSD; *pdwLength = dwLength;
error:
if (pszServerName) { FreeADsStr(pszServerName); }
if (pszKeyName) { FreeADsStr(pszKeyName); }
if (pszSubKey) { FreeADsStr(pszSubKey); }
if (hKey) { RegCloseKey(hKey); }
if (hKeyMachine) { RegCloseKey(hKeyMachine); }
if (FAILED(hr) && pSD) { FreeADsMem(pSD); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: SetRawSDToRegistry - Helper routine.
//
// Synopsis: Sets the security descriptor to the specified key.
//
// Arguments: pszFileRegKeyName - Name of fileshare to set sd on.
// secInfo - Security mask to use for the operation.
// pSD - SD to set on the reg key.
//
// Returns: S_OK or any appropriate error code.
//
// Modifies: N/A.
//
//----------------------------------------------------------------------------
HRESULT SetRawSDToRegistry( LPWSTR pszFileRegKeyName, SECURITY_INFORMATION secInfo, PSECURITY_DESCRIPTOR pSD ) { HRESULT hr; LPWSTR pszServerName = NULL; LPWSTR pszKeyName = NULL; LPWSTR pszSubKey = NULL; DWORD dwErr; HKEY hKey = NULL; HKEY hKeyRoot = NULL; HKEY hKeyMachine = NULL;
//
// We need to split the name into serverName and shareName
//
hr = GetServerAndResource( pszFileRegKeyName, &pszServerName, &pszKeyName ); BAIL_ON_FAILURE(hr); //
// pszKeyName has to have a valid string. We need to process it
// to find out which key set we need to open (such as HKLM).
//
hr = GetKeyRootAndSubKey(pszKeyName, &pszSubKey, &hKeyRoot); BAIL_ON_FAILURE(hr);
//
// Need to open the hKeyRoot on the appropriate machine.
// If the serverName is NULL it will be local machine.
//
dwErr = RegConnectRegistry( pszServerName, hKeyRoot, &hKeyMachine ); if (dwErr) { BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(dwErr)); } //
// Open the key and try and read the security descriptor
//
dwErr = RegOpenKeyEx( hKeyMachine, pszSubKey, 0, KEY_WRITE, &hKey ); if (dwErr) { BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(dwErr)); }
dwErr = RegSetKeySecurity( hKey, secInfo, pSD ); if (dwErr) { BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(dwErr)); }
error:
if (pszServerName) { FreeADsStr(pszServerName); }
if (pszKeyName) { FreeADsStr(pszKeyName); }
if (pszSubKey) { FreeADsStr(pszSubKey); }
if (hKey) { RegCloseKey(hKey); }
if (hKeyMachine) { RegCloseKey(hKeyMachine); }
RRETURN(hr); }
/****************************************************************************/ //
// CADsSecurityUtility Class.
//
/****************************************************************************/
DEFINE_IDispatch_Implementation(CADsSecurityUtility)
//+---------------------------------------------------------------------------
// Function: CSecurity::CSecurityDescriptor - Constructor.
//
// Synopsis: Standard constructor.
//
// Arguments: N/A.
//
// Returns: N/A.
//
// Modifies: N/A.
//
//----------------------------------------------------------------------------
CADsSecurityUtility::CADsSecurityUtility(): _secInfo( DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION ), _pDispMgr(NULL) { }
//+---------------------------------------------------------------------------
// Function: CADsSecurityUtility::~CADsSecurityUtility - Destructor.
//
// Synopsis: Standard destructor.
//
// Arguments: N/A.
//
// Returns: N/A.
//
// Modifies: N/A.
//
//----------------------------------------------------------------------------
CADsSecurityUtility::~CADsSecurityUtility() { //
// Only the dispmgr needs to be cleaned up.
//
delete _pDispMgr; }
//+---------------------------------------------------------------------------
// Function: CADsSecurityUtility::AllocateADsSecurityUtilityObject -
// Static helper method.
//
// Synopsis: Standard static allocation routine.
//
// Arguments: ppADsSecurityUtil - Return ptr.
//
// Returns: S_OK on success or appropriate error code on failure.
//
// Modifies: *ppADsSecurity.
//
//----------------------------------------------------------------------------
HRESULT CADsSecurityUtility::AllocateADsSecurityUtilityObject( CADsSecurityUtility **ppADsSecurityUtil ) { HRESULT hr = S_OK; CADsSecurityUtility FAR * pADsSecurityUtil = NULL; CDispatchMgr FAR * pDispMgr = NULL;
pADsSecurityUtil = new CADsSecurityUtility();
if (!pADsSecurityUtil) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
pDispMgr = new CDispatchMgr;
if (!pDispMgr) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); }
hr = LoadTypeInfoEntry( pDispMgr, LIBID_ADs, IID_IADsSecurityUtility, (IADsSecurityUtility *)pADsSecurityUtil, DISPID_REGULAR ); BAIL_ON_FAILURE(hr);
pADsSecurityUtil->_pDispMgr = pDispMgr; *ppADsSecurityUtil = pADsSecurityUtil;
RRETURN(hr);
error:
delete pADsSecurityUtil; delete pDispMgr;
RRETURN_EXP_IF_ERR(hr); }
//+---------------------------------------------------------------------------
// Function: CADsSecurityUtility::CreateADsSecurityUtility - Static
// helper method.
//
// Synopsis: Standard static class factor helper method.
//
// Arguments: riid - IID needed on returned object.
// ppvObj - Return ptr.
//
// Returns: S_OK on success or appropriate error code on failure.
//
// Modifies: *ppvObj is suitably modified.
//
//----------------------------------------------------------------------------
HRESULT CADsSecurityUtility::CreateADsSecurityUtility( REFIID riid, void **ppvObj ) { CADsSecurityUtility FAR * pADsSecurityUtil = NULL; HRESULT hr = S_OK;
hr = AllocateADsSecurityUtilityObject(&pADsSecurityUtil); BAIL_ON_FAILURE(hr);
hr = pADsSecurityUtil->QueryInterface(riid, ppvObj); BAIL_ON_FAILURE(hr);
pADsSecurityUtil->Release();
RRETURN(hr);
error: delete pADsSecurityUtil;
RRETURN_EXP_IF_ERR(hr);
}
//+---------------------------------------------------------------------------
// Function: CADsSecurityUtility::QueryInterface --- IUnknown support.
//
// Synopsis: Standard query interface method.
//
// Arguments: iid - Interface requested.
// ppInterface - Return pointer to interface requested.
//
// Returns: S_OK on success. Error code otherwise.
//
// Modifies: *ppInterface to return interface pointer.
//
//----------------------------------------------------------------------------
STDMETHODIMP CADsSecurityUtility::QueryInterface( REFIID iid, LPVOID *ppInterface ) { HRESULT hr = S_OK;
if (!ppInterface) { RRETURN(E_INVALIDARG); }
if (IsEqualIID(iid, IID_IUnknown)) { *ppInterface = (IADsSecurityUtility *) this; } else if (IsEqualIID(iid, IID_IDispatch)) { *ppInterface = (IADsSecurityUtility *) this; } else if (IsEqualIID(iid, IID_IADsSecurityUtility)) { *ppInterface = (IADsSecurityUtility *) this; } else if (IsEqualIID(iid, IID_ISupportErrorInfo)) { *ppInterface = (ISupportErrorInfo *) this; } else { RRETURN(E_NOINTERFACE); }
AddRef(); RRETURN(S_OK);
}
//+---------------------------------------------------------------------------
// Function: CADsSecurityUtility::InterfaceSupportserrorInfo
// ISupportErrorInfo support.
//
// Synopsis: N/A.
//
// Arguments: riid - Interface being tested..
//
// Returns: S_OK or S_FALSE on failure.
//
// Modifies: N/A.
//
//----------------------------------------------------------------------------
STDMETHODIMP CADsSecurityUtility::InterfaceSupportsErrorInfo(THIS_ REFIID riid) { if (IsEqualIID(riid, IID_IADsSecurityUtility)) { return S_OK; } else { return S_FALSE; } }
//+---------------------------------------------------------------------------
// Function: CADsSecurityUtility::GetSecurityDescriptor -
// IADsSecurityUtility support.
//
// Synopsis: Gets the security descriptor from the named object.
//
// Arguments: varPath - Path of object to get SD from.
// lPathFormat - Specifies type of object path.
// Only ADS_PATH_FILE, ADS_PATH_FILESHARE
// and ADS_PATH_REGISTRY are supported.
// lOutFormat - Specifies output SD format.
// pVariant - Return value for SD.
//
// Returns: S_OK or any appropriate error code.
//
// Modifies: pVariant is update appropriately.
//
//----------------------------------------------------------------------------
STDMETHODIMP CADsSecurityUtility::GetSecurityDescriptor( IN VARIANT varPath, IN long lPathFormat, IN OPTIONAL long lOutFormat, OUT VARIANT *pVariant ) { HRESULT hr = S_OK; PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL; DWORD dwLength = 0; VARIANT *pvPath = NULL;
//
// Make sure the params are correct.
//
if (!pVariant) { BAIL_ON_FAILURE(hr = E_INVALIDARG); }
VariantInit(pVariant); if (lPathFormat < ADS_PATH_FILE || lPathFormat > ADS_PATH_REGISTRY ) { BAIL_ON_FAILURE(hr = E_INVALIDARG); }
//
// Make sure we handle byRef params correctly.
//
pvPath = &varPath; if (V_VT(pvPath) == (VT_BYREF|VT_VARIANT)) { pvPath = V_VARIANTREF(&varPath); } //
// For the path to be valid for now, it has to be a string.
//
if (pvPath->vt != VT_BSTR) { BAIL_ON_FAILURE(hr = E_INVALIDARG); }
if (pvPath->bstrVal == NULL) { BAIL_ON_FAILURE(hr = E_INVALIDARG); }
if (lOutFormat < ADS_SD_FORMAT_IID || lOutFormat > ADS_SD_FORMAT_HEXSTRING ) { BAIL_ON_FAILURE(hr); }
//
// Time to get the raw sd from the source.
//
switch (lPathFormat) { case ADS_PATH_FILE: hr = GetRawSDFromFile( pvPath->bstrVal, _secInfo, &pSecurityDescriptor, &dwLength ); break;
case ADS_PATH_FILESHARE: hr = GetRawSDFromFileShare( pvPath->bstrVal, &pSecurityDescriptor, &dwLength ); break; case ADS_PATH_REGISTRY: hr = GetRawSDFromRegistry( pvPath->bstrVal, _secInfo, &pSecurityDescriptor, &dwLength ); break;
default: hr = E_INVALIDARG; break; } // end of case to read sd.
BAIL_ON_FAILURE(hr); //
// Now convert the sd to the required format.
//
switch (lOutFormat) { case ADS_SD_FORMAT_IID: hr = BinarySDToSecurityDescriptor( pSecurityDescriptor, pVariant, NULL, NULL, NULL, 0 ); break;
case ADS_SD_FORMAT_RAW: hr = ConvertRawSDToBinary( pSecurityDescriptor, dwLength, pVariant ); break;
case ADS_SD_FORMAT_HEXSTRING: hr = ConvertRawSDToHexString( pSecurityDescriptor, dwLength, pVariant ); break;
default: hr = E_INVALIDARG; } // end of case for output format.
error:
if (pSecurityDescriptor) { FreeADsMem(pSecurityDescriptor); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: CADsSecurityUtility::SetSecurityDescriptor -
// IADsSecurityUtility support.
//
// Synopsis: Sets the security descriptor from the named object.
//
// Arguments: varPath - Path of object to set SD on.
// lPathFormat - Format of path.
// varData - Variant with SD to set.
// lDataFormat - Format of the SD data.
//
// Returns: S_OK or any appropriate error code.
//
// Modifies: N/A.
//
//----------------------------------------------------------------------------
STDMETHODIMP CADsSecurityUtility::SetSecurityDescriptor( IN VARIANT varPath, IN long lPathFormat, IN VARIANT varData, IN long lDataFormat ) { HRESULT hr = E_INVALIDARG; VARIANT *pvPath = NULL; VARIANT *pvData = NULL; PSECURITY_DESCRIPTOR pSD = NULL; DWORD dwLength = 0;
if ((lPathFormat < ADS_PATH_FILE) || (lPathFormat > ADS_PATH_REGISTRY) || (lDataFormat < ADS_SD_FORMAT_IID) || (lDataFormat > ADS_SD_FORMAT_HEXSTRING) ) { BAIL_ON_FAILURE(hr = E_INVALIDARG); } //
// Make sure we handle byRef params correctly.
//
pvPath = &varPath; if (V_VT(pvPath) == (VT_BYREF | VT_VARIANT)) { pvPath = V_VARIANTREF(&varPath); }
pvData = &varData; if (V_VT(pvData) == (VT_BYREF | VT_VARIANT)) { pvData = V_VARIANTREF(&varData); }
//
// Find out what format the SD is in and convert to raw binary
// format as that is what we need to set.
//
switch (lDataFormat) { case ADS_SD_FORMAT_IID: hr = SecurityDescriptorToBinarySD( *pvData, &pSD, &dwLength, NULL, NULL, NULL, 0 ); break;
case ADS_SD_FORMAT_HEXSTRING: if (V_VT(pvData) == VT_BSTR) { hr = ConvertHexSDToRawSD( pvData, &pSD, &dwLength ); } break;
case ADS_SD_FORMAT_RAW: if (V_VT(pvData) == (VT_UI1 | VT_ARRAY)) { hr = ConvertBinarySDToRawSD( pvData, &pSD, &dwLength ); }
default: hr = E_INVALIDARG; break; } // end switch type of input data.
//
// This will catch conversion failures as well as bad params.
//
BAIL_ON_FAILURE(hr); //
// For now the path has to be a string.
//
if (pvPath->vt != VT_BSTR) { BAIL_ON_FAILURE(hr = E_INVALIDARG); }
switch (lPathFormat) { case ADS_PATH_FILE: hr = SetRawSDToFile( pvPath->bstrVal, _secInfo, pSD ); break;
case ADS_PATH_FILESHARE: hr = SetRawSDToFileShare( pvPath->bstrVal, pSD ); break;
case ADS_PATH_REGISTRY: hr = SetRawSDToRegistry( pvPath->bstrVal, _secInfo, pSD ); break;
default: hr = E_INVALIDARG; break; }
BAIL_ON_FAILURE(hr);
error:
if (pSD) { FreeADsMem(pSD); }
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function: CADsSecurityUtility::ConvertSecurityDescriptor -
// IADsSecurityUtility method.
//
// Synopsis: Converts the input SD to the appropriate format requested.
//
// Arguments: varData - Input SD to convert.
// lDataFormat - Input SD format.
// loutFormat - Format of output SD.
// pvResult - Return value.
//
// Returns: S_OK or any appropriate error code.
//
// Modifies: pvResult with appropriate value.
//
//----------------------------------------------------------------------------
STDMETHODIMP CADsSecurityUtility::ConvertSecurityDescriptor( IN VARIANT varData, IN long lDataFormat, IN long lOutFormat, OUT VARIANT *pvResult ) { HRESULT hr; PSECURITY_DESCRIPTOR pSD = NULL; DWORD dwLenSD; VARIANT *pVarData = &varData;
if (!pvResult) { BAIL_ON_FAILURE(hr= E_INVALIDARG); }
if (V_VT(pVarData) == (VT_BYREF | VT_VARIANT)) { pVarData = V_VARIANTREF(&varData); } //
// We will convert to binary format and then to
// the requested format.
//
switch (lDataFormat) { case ADS_SD_FORMAT_IID: hr = SecurityDescriptorToBinarySD( *pVarData, &pSD, &dwLenSD, NULL, NULL, NULL, 0 ); break;
case ADS_SD_FORMAT_RAW : hr = ConvertBinarySDToRawSD( pVarData, &pSD, &dwLenSD ); break;
case ADS_SD_FORMAT_HEXSTRING: hr = ConvertHexSDToRawSD( pVarData, &pSD, &dwLenSD ); break;
default: hr = E_INVALIDARG; break; } BAIL_ON_FAILURE(hr);
//
// Convert to the requested format.
//
switch (lOutFormat) { case ADS_SD_FORMAT_IID: hr = BinarySDToSecurityDescriptor( pSD, pvResult, NULL, NULL, NULL, 0 ); break;
case ADS_SD_FORMAT_RAW: hr = ConvertRawSDToBinary( pSD, dwLenSD, pvResult ); break; case ADS_SD_FORMAT_HEXSTRING: hr = ConvertRawSDToHexString( pSD, dwLenSD, pvResult ); break;
default: hr = E_INVALIDARG; break; }
error:
if (pSD) { FreeADsMem(pSD); }
RRETURN(hr); }
STDMETHODIMP CADsSecurityUtility::put_SecurityMask( long lSecurityMask ) { _secInfo = (SECURITY_INFORMATION) lSecurityMask; RRETURN(S_OK); }
STDMETHODIMP CADsSecurityUtility::get_SecurityMask( long *plSecurityMask ) { if (!plSecurityMask) { RRETURN(E_INVALIDARG); }
*plSecurityMask = (long) _secInfo;
RRETURN(S_OK); }
|