|
|
#include "winnt.hxx"
#pragma hdrstop
HRESULT ConvertSafeArrayToVariantArray( VARIANT varSafeArray, PVARIANT * ppVarArray, PDWORD pdwNumVariants );
HRESULT ConvertByRefSafeArrayToVariantArray( VARIANT varSafeArray, PVARIANT * ppVarArray, PDWORD pdwNumVariants );
HRESULT CreatePropEntry( LPWSTR szPropName, ADSTYPE dwADsType, VARIANT varData, REFIID riid, LPVOID * ppDispatch );
FILTERS Filters[] = { {L"user", WINNT_USER_ID}, {L"group", WINNT_GROUP_ID}, // for backward compatibility
{L"localgroup", WINNT_LOCALGROUP_ID}, {L"globalgroup", WINNT_GLOBALGROUP_ID}, {L"printqueue", WINNT_PRINTER_ID}, {L"domain", WINNT_DOMAIN_ID}, {L"computer", WINNT_COMPUTER_ID}, {L"service", WINNT_SERVICE_ID}, {L"fileshare", WINNT_FILESHARE_ID}, {L"schema", WINNT_SCHEMA_ID}, {L"class", WINNT_CLASS_ID}, {L"syntax", WINNT_SYNTAX_ID}, {L"property", WINNT_PROPERTY_ID}, {L"FPNWfileshare", WINNT_FPNW_FILESHARE_ID} };
#define MAX_FILTERS (sizeof(Filters)/sizeof(FILTERS))
PFILTERS gpFilters = Filters; DWORD gdwMaxFilters = MAX_FILTERS; extern WCHAR * szProviderName;
//+------------------------------------------------------------------------
//
// Class: Common
//
// Purpose: Contains Winnt routines and properties that are common to
// all Winnt objects. Winnt objects get the routines and
// properties through C++ inheritance.
//
//-------------------------------------------------------------------------
HRESULT BuildADsPath( LPWSTR Parent, LPWSTR Name, LPWSTR *pADsPath ) { WCHAR ADsPath[MAX_PATH]; WCHAR ProviderName[MAX_PATH]; HRESULT hr = S_OK; LPWSTR pszDisplayName = NULL;
//
// We will assert if bad parameters are passed to us.
// This is because this should never be the case. This
// is an internal call
//
ADsAssert(Parent && Name); ADsAssert(pADsPath);
if ( (wcslen(Parent) + wcslen(Name)) > MAX_PATH - 1) { RRETURN(E_FAIL); }
hr = GetDisplayName( Name, &pszDisplayName ); BAIL_ON_FAILURE(hr);
if (!pszDisplayName || !*pszDisplayName) { //
// The display name has to be valid.
//
BAIL_ON_FAILURE(hr = E_FAIL); }
//
// Special case the Namespace object; if
// the parent is L"ADs:", then Name = ADsPath
//
if (!_wcsicmp(Parent, L"ADs:")) { *pADsPath = AllocADsStr(pszDisplayName); if (*pADsPath == NULL) { BAIL_ON_FAILURE(hr = E_OUTOFMEMORY); } else { hr = S_OK; goto cleanup; } }
//
// The rest of the cases we expect valid data,
// Path, Parent and Name are read-only, the end-user
// cannot modify this data
//
//
// For the first object, the domain object we do not add
// the first backslash; so we examine that the parent is
// L"WinNT:" and skip the slash otherwise we start with
// the slash
//
wsprintf(ProviderName, L"%s:", szProviderName);
wcscpy(ADsPath, Parent);
if (_wcsicmp(ADsPath, ProviderName)) { wcscat(ADsPath, L"/"); }else { wcscat(ADsPath, L"//"); } wcscat(ADsPath, pszDisplayName);
*pADsPath = AllocADsStr(ADsPath);
if (*pADsPath == NULL) BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
cleanup: error:
if (pszDisplayName) { FreeADsMem(pszDisplayName); }
RRETURN(hr); }
HRESULT BuildSchemaPath( LPWSTR Parent, LPWSTR Name, LPWSTR Schema, LPWSTR *pSchemaPath ) { WCHAR SchemaPath[MAX_PATH]; WCHAR ProviderName[MAX_PATH]; HRESULT hr = S_OK;
OBJECTINFO ObjectInfo; POBJECTINFO pObjectInfo = &ObjectInfo; CLexer Lexer(Parent);
memset(pObjectInfo, 0, sizeof(OBJECTINFO));
//
// We will assert if bad parameters are passed to us.
// This is because this should never be the case. This
// is an internal call
//
ADsAssert(Parent); ADsAssert(pSchemaPath);
//
// If no schema name is passed in, then there is no schema path
//
if ( Schema == NULL || *Schema == 0 ){
*pSchemaPath = AllocADsStr(L""); RRETURN(*pSchemaPath ? S_OK: E_OUTOFMEMORY ); }
memset(pObjectInfo, 0, sizeof(OBJECTINFO)); hr = Object(&Lexer, pObjectInfo); BAIL_ON_FAILURE(hr);
wsprintf(SchemaPath, L"%s://", szProviderName);
if (!pObjectInfo->NumComponents) { if( (wcslen(Name) + wcslen(szProviderName) + 4) > MAX_PATH ) { BAIL_ON_FAILURE(hr = E_INVALIDARG); } wcscat(SchemaPath, Name); }else{ if( (wcslen(pObjectInfo->DisplayComponentArray[0]) + wcslen(szProviderName) + 4) > MAX_PATH ) { BAIL_ON_FAILURE(hr = E_INVALIDARG); } wcscat(SchemaPath, pObjectInfo->DisplayComponentArray[0]); }
if( (wcslen(SchemaPath) + wcslen(SCHEMA_NAME) + wcslen(Schema) + 3) > MAX_PATH ) { BAIL_ON_FAILURE(hr = E_INVALIDARG); } wcscat( SchemaPath, L"/"); wcscat( SchemaPath, SCHEMA_NAME ); wcscat( SchemaPath, L"/"); wcscat( SchemaPath, Schema );
*pSchemaPath = AllocADsStr(SchemaPath); hr = pSchemaPath ? S_OK: E_OUTOFMEMORY ;
error:
FreeObjectInfo( &ObjectInfo, TRUE );
RRETURN(hr); }
HRESULT BuildADsGuid( REFCLSID clsid, LPWSTR *pADsClass ) { WCHAR ADsClass[MAX_PATH];
if (!StringFromGUID2(clsid, ADsClass, MAX_PATH)) { //
// MAX_PATH should be more than enough for the GUID.
//
ADsAssert(!"GUID too big !!!"); RRETURN(E_FAIL); }
*pADsClass = AllocADsStr(ADsClass); RRETURN (*pADsClass ? S_OK: E_OUTOFMEMORY);
}
HRESULT MakeUncName( LPWSTR szSrcBuffer, LPWSTR szTargBuffer ) { ADsAssert(szSrcBuffer); wcscpy(szTargBuffer, L"\\\\"); wcscat(szTargBuffer, szSrcBuffer); RRETURN(S_OK); }
HRESULT ValidateOutParameter( BSTR * retval ) { if (!retval) { RRETURN(E_ADS_BAD_PARAMETER); } RRETURN(S_OK); }
HRESULT BuildObjectInfo( LPWSTR ADsParent, LPWSTR Name, POBJECTINFO * ppObjectInfo ) { WCHAR szBuffer[MAX_PATH]; HRESULT hr; POBJECTINFO pObjectInfo = NULL;
//
// Both should be set in this call, cannot have a NULL parent.
//
if (!ADsParent || !*ADsParent) { RRETURN(E_ADS_BAD_PARAMETER); } //
// We need to make sure that the path is not greater
// than MAX_PATH + 2 = 1 for / and another for \0
//
if ((wcslen(ADsParent) + wcslen(Name) + 2) > MAX_PATH) { RRETURN(E_ADS_BAD_PARAMETER); }
wcscpy(szBuffer, ADsParent); wcscat(szBuffer, L"/"); wcscat(szBuffer, Name);
CLexer Lexer(szBuffer);
pObjectInfo = (POBJECTINFO)AllocADsMem(sizeof(OBJECTINFO)); if (!pObjectInfo) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); } memset(pObjectInfo, 0, sizeof(OBJECTINFO)); hr = Object(&Lexer, pObjectInfo); BAIL_ON_FAILURE(hr);
*ppObjectInfo = pObjectInfo;
RRETURN(hr);
error:
if (pObjectInfo) { FreeObjectInfo(pObjectInfo); }
*ppObjectInfo = NULL;
RRETURN(hr); }
HRESULT BuildObjectInfo( LPWSTR ADsPath, POBJECTINFO * ppObjectInfo ) { HRESULT hr; POBJECTINFO pObjectInfo = NULL; CLexer Lexer(ADsPath);
pObjectInfo = (POBJECTINFO)AllocADsMem(sizeof(OBJECTINFO)); if (!pObjectInfo) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); } memset(pObjectInfo, 0, sizeof(OBJECTINFO)); hr = Object(&Lexer, pObjectInfo); BAIL_ON_FAILURE(hr);
*ppObjectInfo = pObjectInfo;
RRETURN(hr);
error:
if (pObjectInfo) { FreeObjectInfo(pObjectInfo); }
*ppObjectInfo = NULL;
RRETURN(hr); }
HRESULT MakeWinNTAccountName( POBJECTINFO pObjectInfo, LPWSTR szUserAccount, BOOL fConnectToReg ) { HRESULT hr = S_OK; DWORD dwNumComp = 0; DWORD dwProductType = PRODTYPE_INVALID; WCHAR szDomain[MAX_PATH]; WCHAR szSAMName[MAX_ADS_PATH]; BOOL fReplacedWithDC = FALSE;
// The credentials are needed to pass into WinNTGetCachedComputerName
CWinNTCredentials nullCredentials;
// Need szSAMName as dummy param
szSAMName[0] = L'\0';
if (!pObjectInfo || !szUserAccount) { RRETURN(E_ADS_BAD_PARAMETER); }
dwNumComp = pObjectInfo->NumComponents;
switch (dwNumComp) {
case 2: case 3:
//
// Check if machine is a dc
//
//
// Going to try getComputerName first as the NetWkstaGetInfo call
// times out faster than the RegConnect call we use in
// GetMachineProductType - AjayR 11-06-98.
//
if (fConnectToReg) {
if (dwNumComp==2) { //
// we don't have domain name in pObjectInfo, let's try
// to get it from the dc name (comp[0])
//
hr = WinNTGetCachedComputerName( pObjectInfo->ComponentArray[0], szUserAccount, szSAMName, nullCredentials );
if (SUCCEEDED(hr)) { fReplacedWithDC = TRUE; } }
else // dwNumComp==3
{ //
// We have domain name (comp[0]) in our objectInfo, let's use
// it. Can call ValidateComputerName here, but not needed
// since error will be caught next.
//
wcscpy(szUserAccount, pObjectInfo->ComponentArray[0]);
fReplacedWithDC = TRUE; }
if (fReplacedWithDC) { //
// Now try connecting to make sure it is a DC
// otherwise we should not do this replacement
//
hr = GetMachineProductType( pObjectInfo->ComponentArray[dwNumComp-2], &dwProductType ); BAIL_ON_FAILURE(hr);
if (dwProductType != PRODTYPE_DC) { //
// We cannot use szUserAccount as it has
// bad info
//
fReplacedWithDC = FALSE; hr = E_FAIL; }
}
}// if fConnectToReg
BAIL_ON_FAILURE(hr); //
// Do not want to replace machine name with domain since not dc or
// dc but can't replace - best efforts fail
//
if (fReplacedWithDC==FALSE) { wcscpy(szUserAccount, pObjectInfo->ComponentArray[dwNumComp-2]); }
//
// Add \UserName to account name
//
wcscat(szUserAccount, L"\\"); wcscat(szUserAccount, pObjectInfo->ComponentArray[dwNumComp-1]); break;
default:
RRETURN(E_ADS_UNKNOWN_OBJECT);
}
error: RRETURN(hr); }
HRESULT MakeWinNTDomainAndName( POBJECTINFO pObjectInfo, LPWSTR szDomName ) { DWORD dwNumComp = pObjectInfo->NumComponents;
switch (dwNumComp) { case 2: case 3: wcscpy(szDomName, pObjectInfo->ComponentArray[dwNumComp - 2]); wcscat(szDomName, L"\\"); wcscat(szDomName, pObjectInfo->ComponentArray[dwNumComp - 1]); break;
default: RRETURN(E_ADS_UNKNOWN_OBJECT);
} RRETURN(S_OK); }
HRESULT ValidateObject( DWORD dwObjectType, POBJECTINFO pObjectInfo, CWinNTCredentials& Credentials ) { ULONG uGroupType; DWORD dwParentId;
switch (dwObjectType) { case WINNT_USER_ID: RRETURN(ValidateUserObject(pObjectInfo, &dwParentId, Credentials));
case WINNT_GROUP_ID: RRETURN(ValidateGroupObject( pObjectInfo, &uGroupType, &dwParentId, Credentials ));
case WINNT_COMPUTER_ID: RRETURN(ValidateComputerObject(pObjectInfo, Credentials));
case WINNT_PRINTER_ID: RRETURN(ValidatePrinterObject(pObjectInfo, Credentials));
case WINNT_SERVICE_ID: RRETURN(ValidateServiceObject(pObjectInfo, Credentials));
case WINNT_FILESHARE_ID: RRETURN(ValidateFileShareObject(pObjectInfo, Credentials));
default: RRETURN(E_FAIL); } }
VOID FreeObjectInfo( POBJECTINFO pObjectInfo, BOOL fStatic ) { DWORD i = 0;
if (!pObjectInfo) { return; }
FreeADsStr( pObjectInfo->ProviderName );
for (i = 0; i < pObjectInfo->NumComponents; i++ ) { FreeADsStr(pObjectInfo->ComponentArray[i]); FreeADsStr(pObjectInfo->DisplayComponentArray[i]); }
if ( !fStatic ) FreeADsMem(pObjectInfo); }
HRESULT CopyObjectInfo( POBJECTINFO pSrcObjectInfo, POBJECTINFO *pTargObjectInfo ) { POBJECTINFO pObjectInfo = NULL; HRESULT hr S_OK; DWORD i;
if(!pSrcObjectInfo){ RRETURN(S_OK); } pObjectInfo = (POBJECTINFO)AllocADsMem(sizeof(OBJECTINFO));
if (!pObjectInfo) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); }
memset(pObjectInfo, 0, sizeof(OBJECTINFO));
pObjectInfo->ObjectType = pSrcObjectInfo->ObjectType; pObjectInfo->NumComponents = pSrcObjectInfo->NumComponents; pObjectInfo->ProviderName = AllocADsStr(pSrcObjectInfo->ProviderName);
for(i=0; i<pSrcObjectInfo->NumComponents; i++){ pObjectInfo->ComponentArray[i] = AllocADsStr(pSrcObjectInfo->ComponentArray[i]); pObjectInfo->DisplayComponentArray[i] = AllocADsStr(pSrcObjectInfo->DisplayComponentArray[i]); } *pTargObjectInfo = pObjectInfo; RRETURN(hr);
error: RRETURN(hr); }
HRESULT GetObjectType( PFILTERS pFilters, DWORD dwMaxFilters, LPWSTR ClassName, PDWORD pdwObjectType ) { DWORD i = 0;
ADsAssert(pdwObjectType);
for (i = 0; i < dwMaxFilters; i++) { if (!_wcsicmp(ClassName, (pFilters + i)->szObjectName)) { *pdwObjectType = (pFilters + i)->dwFilterId; RRETURN(S_OK); } } *pdwObjectType = 0; RRETURN(E_INVALIDARG); }
HRESULT ValidateProvider( POBJECTINFO pObjectInfo ) {
//
// The provider name is case-sensitive. This is a restriction that OLE
// has put on us.
//
if (!(wcscmp(pObjectInfo->ProviderName, szProviderName))) { RRETURN(S_OK); } RRETURN(E_FAIL); }
HRESULT GetDomainFromPath( LPTSTR ADsPath, LPTSTR szDomainName ) { OBJECTINFO ObjectInfo; POBJECTINFO pObjectInfo = &ObjectInfo; CLexer Lexer(ADsPath); HRESULT hr = S_OK;
//assumption: Valid strings are passed to GetDomainFromPath
ADsAssert(ADsPath); ADsAssert(szDomainName);
memset(pObjectInfo, 0, sizeof(OBJECTINFO)); hr = Object(&Lexer, pObjectInfo); BAIL_ON_FAILURE(hr);
if (pObjectInfo->NumComponents) { wcscpy(szDomainName, pObjectInfo->ComponentArray[0]); }else { hr = E_FAIL; }
error:
FreeObjectInfo( &ObjectInfo, TRUE );
RRETURN(hr); }
HRESULT GetServerFromPath( LPTSTR ADsPath, LPTSTR szServerName ) { OBJECTINFO ObjectInfo; POBJECTINFO pObjectInfo = &ObjectInfo; CLexer Lexer(ADsPath); HRESULT hr = S_OK;
//assumption: Valid strings are passed to GetDomainFromPath
ADsAssert(ADsPath); ADsAssert(szServerName);
memset(pObjectInfo, 0, sizeof(OBJECTINFO)); hr = Object(&Lexer, pObjectInfo); BAIL_ON_FAILURE(hr);
if (pObjectInfo->NumComponents > 1) { wcscpy(szServerName, pObjectInfo->ComponentArray[1]); }else { hr = E_FAIL; }
error:
FreeObjectInfo( &ObjectInfo, TRUE );
RRETURN(hr); }
DWORD TickCountDiff( DWORD dwTime1, DWORD dwTime2 ) { //
// does dwTime1 - dwTime2 and takes care of wraparound.
// The first time must be later than the second
// Restriction:: The two times must have been taken not more than
// 49.7 days apart
//
DWORD dwRetval;
if(dwTime1 >= dwTime2){ dwRetval = dwTime1 - dwTime2; }
else{ dwRetval = dwTime2 - dwTime1; dwRetval = MAX_DWORD - dwRetval; } return dwRetval; }
HRESULT DelimitedStringToVariant( LPTSTR pszString, VARIANT *pvar, TCHAR Delimiter ) { SAFEARRAYBOUND sabound[1]; DWORD dwElements; LPTSTR pszCurrPos = pszString; LPTSTR *rgszStrings = NULL; SAFEARRAY *psa = NULL; VARIANT v; HRESULT hr = S_OK; LONG i;
//
// This function converts a delimited string into a VARIANT of
// safe arrays.
//
// Assumption: a valid string are passed to this function
// note that the input string gets destroyed in the process
//
//
// scan the delimited string once to find out the dimension
//
//
// in order to filter for NULL input values do a sanity check for
// length of input string.
//
if (!pszString){ sabound[0].cElements = 0; sabound[0].lLbound = 0;
psa = SafeArrayCreate(VT_VARIANT, 1, sabound);
if (psa == NULL){ hr = E_OUTOFMEMORY; goto error; }
VariantInit(pvar); V_VT(pvar) = VT_ARRAY|VT_VARIANT; V_ARRAY(pvar) = psa; goto error; }
dwElements = (wcslen(pszString) == 0) ? 0: 1 ;
while(!(*pszCurrPos == TEXT('\0'))){ if(*pszCurrPos == Delimiter){ dwElements++; *pszCurrPos = TEXT('\0'); } pszCurrPos++; }
rgszStrings = (LPTSTR *)AllocADsMem(sizeof(LPTSTR)*dwElements);
if(!rgszStrings){ hr = E_OUTOFMEMORY; goto error; }
//
// scan string again and put the appropriate pointers
//
pszCurrPos = pszString; if(rgszStrings != NULL){ (*rgszStrings) = pszCurrPos; } i = 1;
while(i < (LONG)dwElements){
if(*pszCurrPos == TEXT('\0')){ *(rgszStrings+i) = ++pszCurrPos; i++; } pszCurrPos++; }
//
// create the safearray
//
sabound[0].cElements = dwElements; sabound[0].lLbound = 0;
psa = SafeArrayCreate(VT_VARIANT, 1, sabound);
if (psa == NULL){ hr = E_OUTOFMEMORY; goto error; }
for(i=0; i<(LONG)dwElements; i++){
VariantInit(&v); V_VT(&v) = VT_BSTR;
hr = ADsAllocString(*(rgszStrings+i), &(V_BSTR(&v)));
BAIL_ON_FAILURE(hr);
//
// Stick the caller provided data into the end of the SafeArray
//
hr = SafeArrayPutElement(psa, &i, &v); VariantClear(&v); BAIL_ON_FAILURE(hr);
}
//
// convert this safearray into a VARIANT
//
VariantInit(pvar); V_VT(pvar) = VT_ARRAY|VT_VARIANT; V_ARRAY(pvar) = psa;
error: if(rgszStrings && dwElements != 0){ FreeADsMem(rgszStrings); } RRETURN(hr); }
HRESULT BuildComputerFromObjectInfo( POBJECTINFO pObjectInfo, LPTSTR pszADsPath ) {
if(!pObjectInfo){ RRETURN(E_FAIL); }
if(pObjectInfo->NumComponents == 3) {
wsprintf( pszADsPath, L"%s://%s/%s", pObjectInfo->ProviderName, pObjectInfo->ComponentArray[0], pObjectInfo->ComponentArray[1] );
} else if (pObjectInfo->NumComponents == 2){
wsprintf( pszADsPath, L"%s://%s", pObjectInfo->ProviderName, pObjectInfo->ComponentArray[0] );
} else { RRETURN(E_FAIL); }
RRETURN(S_OK);
}
HRESULT FPNWSERVERADDRtoString( FPNWSERVERADDR WkstaAddress, LPWSTR * ppszString ) {
HRESULT hr = S_OK; TCHAR szNibble[2]; //one number and a null termination
USHORT usNibble; int i; TCHAR szWkstaAddr[MAX_PATH];
//
// assumption: valid input values are passed to this function.
//
//
// First 4 bytes is network address, then a dot and then bytes 5-10
// are physical node address. Each byte consumes 2 chars space.
// Then a byte for TEXT('\0')
//
_tcscpy(szWkstaAddr, TEXT(""));
for( i=0; i < 4; i++){
usNibble = WkstaAddress[i] & 0xF0; usNibble = usNibble >> 4; _itot(usNibble, szNibble, 16 ); _tcscat(szWkstaAddr, szNibble); usNibble = WkstaAddress[i] & 0xF; _itot(usNibble, szNibble, 16 ); _tcscat(szWkstaAddr, szNibble);
}
_tcscat(szWkstaAddr, TEXT("."));
for(i=4; i<10 ; i++){
usNibble = WkstaAddress[i] & 0xF0; usNibble = usNibble >> 4; _itot(usNibble, szNibble, 16 ); _tcscat(szWkstaAddr, szNibble); usNibble = WkstaAddress[i] & 0xF; _itot(usNibble, szNibble, 16 ); _tcscat(szWkstaAddr, szNibble); }
*ppszString = AllocADsStr(szWkstaAddr);
if(!*ppszString){ hr = E_OUTOFMEMORY; }
RRETURN(hr); }
PKEYDATA CreateTokenList( LPWSTR pKeyData ) { DWORD cTokens; DWORD cb; PKEYDATA pResult; LPWSTR pDest; LPWSTR psz = pKeyData; LPWSTR *ppToken;
if (!psz || !*psz) return NULL;
cTokens=1;
// Scan through the string looking for commas,
// ensuring that each is followed by a non-NULL character:
while ((psz = wcschr(psz, L',')) && psz[1]) {
cTokens++; psz++; }
cb = sizeof(KEYDATA) + (cTokens-1) * sizeof(LPWSTR) + wcslen(pKeyData)*sizeof(WCHAR) + sizeof(WCHAR);
if (!(pResult = (PKEYDATA)AllocADsMem(cb))) return NULL;
// Initialise pDest to point beyond the token pointers:
pDest = (LPWSTR)((LPBYTE)pResult + sizeof(KEYDATA) + (cTokens-1) * sizeof(LPWSTR));
// Then copy the key data buffer there:
wcscpy(pDest, pKeyData);
ppToken = pResult->pTokens;
// Remember, wcstok has the side effect of replacing the delimiter
// by NULL, which is precisely what we want:
psz = wcstok (pDest, L",");
while (psz) {
*ppToken++ = psz; psz = wcstok (NULL, L","); }
pResult->cTokens = cTokens;
return( pResult ); }
STDMETHODIMP GenericGetPropertyManager( CPropertyCache * pPropertyCache, THIS_ BSTR bstrName, VARIANT FAR* pvProp ) { HRESULT hr = S_OK; DWORD dwSyntaxId; DWORD dwNumValues; DWORD dwInfoLevel; LPNTOBJECT pNtSrcObjects = NULL;
//
// For those who know no not what they do
//
if (!pvProp) { BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER); }
//
// retrieve data object from cache; if one exists
hr = pPropertyCache->getproperty( bstrName, &dwSyntaxId, &dwNumValues, &pNtSrcObjects );
BAIL_ON_FAILURE(hr);
//
// translate the Nt objects to variants
//
if (dwNumValues == 1) {
hr = NtTypeToVarTypeCopy( pNtSrcObjects, pvProp );
}else {
hr = NtTypeToVarTypeCopyConstruct( pNtSrcObjects, dwNumValues, pvProp ); }
BAIL_ON_FAILURE(hr);
error:
if (pNtSrcObjects) {
NTTypeFreeNTObjects( pNtSrcObjects, dwNumValues ); }
RRETURN(hr); }
STDMETHODIMP GenericPutPropertyManager( CPropertyCache * pPropertyCache, PPROPERTYINFO pSchemaProps, DWORD dwSchemaPropSize, THIS_ BSTR bstrName, VARIANT vProp, BOOL fCheckSchemaWriteAccess ) { HRESULT hr = S_OK; DWORD dwSyntaxId = 0; DWORD dwIndex = 0; LPNTOBJECT pNtDestObjects = NULL;
VARIANT * pVarArray = NULL; VARIANT * pvProp = NULL; DWORD dwNumValues = 0;
//
// check if property in schema and get syntax of property
//
hr = ValidatePropertyinSchemaClass( pSchemaProps, dwSchemaPropSize, bstrName, &dwSyntaxId );
if(TRUE == fCheckSchemaWriteAccess) { //
// check if this is a writeable property in the schema
//
hr = ValidateIfWriteableProperty( pSchemaProps, dwSchemaPropSize, bstrName ); BAIL_ON_FAILURE(hr); }
//
// Issue: How do we handle multi-valued support
//
//
// A VT_BYREF|VT_VARIANT may expand to a VT_VARIANT|VT_ARRAY.
// We should dereference a VT_BYREF|VT_VARIANT once and see
// what's inside.
//
pvProp = &vProp; if (V_VT(pvProp) == (VT_BYREF|VT_VARIANT)) { pvProp = V_VARIANTREF(&vProp); }
if ((V_VT(pvProp) == (VT_VARIANT|VT_ARRAY)) || (V_VT(&vProp) == (VT_VARIANT|VT_ARRAY|VT_BYREF))) {
hr = ConvertByRefSafeArrayToVariantArray( *pvProp, &pVarArray, &dwNumValues ); BAIL_ON_FAILURE(hr);
if( (0 == dwNumValues) && (NULL == pVarArray) ) { // return error if the safearray had no elements. Otherwise, the
// NT object stored in the property cache is garbage.
BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER); }
pvProp = pVarArray;
}else {
dwNumValues = 1; }
hr = VarTypeToNtTypeCopyConstruct( dwSyntaxId, pvProp, dwNumValues, &pNtDestObjects ); BAIL_ON_FAILURE(hr);
//
// Find this property in the cache
//
hr = pPropertyCache->findproperty( bstrName, &dwIndex );
//
// If this property does not exist in the
// cache, add this property into the cache.
//
if (FAILED(hr)) { hr = pPropertyCache->addproperty( bstrName, dwSyntaxId, dwNumValues, pNtDestObjects ); //
// If the operation fails for some reason
// move on to the next property
//
BAIL_ON_FAILURE(hr);
}
//
// Now update the property in the cache
//
hr = pPropertyCache->putproperty( bstrName, dwSyntaxId, dwNumValues, pNtDestObjects ); BAIL_ON_FAILURE(hr);
error:
if (pNtDestObjects) { NTTypeFreeNTObjects( pNtDestObjects, dwNumValues );
}
if (pVarArray) {
DWORD i = 0;
for (i = 0; i < dwNumValues; i++) { VariantClear(pVarArray + i); } FreeADsMem(pVarArray); }
RRETURN(hr); }
STDMETHODIMP GenericGetExPropertyManager( DWORD dwObjectState, CPropertyCache * pPropertyCache, THIS_ BSTR bstrName, VARIANT FAR* pvProp ) { HRESULT hr = S_OK; DWORD dwSyntaxId; DWORD dwNumValues; LPNTOBJECT pNtSrcObjects = NULL;
//
// retrieve data object from cache; if one exis
//
if (dwObjectState == ADS_OBJECT_UNBOUND) {
hr = pPropertyCache->unboundgetproperty( bstrName, &dwSyntaxId, &dwNumValues, &pNtSrcObjects ); BAIL_ON_FAILURE(hr);
}else {
hr = pPropertyCache->getproperty( bstrName, &dwSyntaxId, &dwNumValues, &pNtSrcObjects ); BAIL_ON_FAILURE(hr); }
//
// translate the Nds objects to variants
//
hr = NtTypeToVarTypeCopyConstruct( pNtSrcObjects, dwNumValues, pvProp );
BAIL_ON_FAILURE(hr);
error: if (pNtSrcObjects) {
NTTypeFreeNTObjects( pNtSrcObjects, dwNumValues ); }
RRETURN(hr); }
STDMETHODIMP GenericPutExPropertyManager( CPropertyCache * pPropertyCache, PPROPERTYINFO pSchemaProps, DWORD dwSchemaPropSize, THIS_ BSTR bstrName, VARIANT vProp ) { HRESULT hr = S_OK; DWORD dwSyntaxId = 0; DWORD dwIndex = 0; LPNTOBJECT pNtDestObjects = NULL;
VARIANT * pVarArray = NULL; VARIANT * pvProp = NULL; DWORD dwNumValues = 0;
//
// check if property in schema and get syntax of property
//
hr = ValidatePropertyinSchemaClass( pSchemaProps, dwSchemaPropSize, bstrName, &dwSyntaxId );
//
// check if this is a writeable property in the schema
//
hr = ValidateIfWriteableProperty( pSchemaProps, dwSchemaPropSize, bstrName ); BAIL_ON_FAILURE(hr);
//
// Issue: How do we handle multi-valued support
//
//
// A VT_BYREF|VT_VARIANT may expand to a VT_VARIANT|VT_ARRAY.
// We should dereference a VT_BYREF|VT_VARIANT once and see
// what's inside.
//
pvProp = &vProp; if (V_VT(pvProp) == (VT_BYREF|VT_VARIANT)) { pvProp = V_VARIANTREF(&vProp); }
if ((V_VT(pvProp) == (VT_VARIANT|VT_ARRAY)) || (V_VT(&vProp) == (VT_VARIANT|VT_ARRAY|VT_BYREF))) {
hr = ConvertByRefSafeArrayToVariantArray( *pvProp, &pVarArray, &dwNumValues ); BAIL_ON_FAILURE(hr);
if( (0 == dwNumValues) && (NULL == pVarArray) ) { // return error if the safearray had no elements. Otherwise, the
// NT object stored in the property cache is garbage.
BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER); }
pvProp = pVarArray;
}else {
hr = E_FAIL; BAIL_ON_FAILURE(hr); }
//
// check if the variant maps to the syntax of this property
//
hr = VarTypeToNtTypeCopyConstruct( dwSyntaxId, pvProp, dwNumValues, &pNtDestObjects ); BAIL_ON_FAILURE(hr);
//
// Find this property in the cache
//
hr = pPropertyCache->findproperty( bstrName, &dwIndex );
//
// If this property does not exist in the
// cache, add this property into the cache.
//
if (FAILED(hr)) { hr = pPropertyCache->addproperty( bstrName, dwSyntaxId, dwNumValues, pNtDestObjects ); //
// If the operation fails for some reason
// move on to the next property
//
BAIL_ON_FAILURE(hr);
}
//
// Now update the property in the cache
//
hr = pPropertyCache->putproperty( bstrName, dwSyntaxId, dwNumValues, pNtDestObjects ); BAIL_ON_FAILURE(hr);
error:
if (pNtDestObjects) { NTTypeFreeNTObjects( pNtDestObjects, dwNumValues );
}
if (pVarArray) {
DWORD i = 0;
for (i = 0; i < dwNumValues; i++) { VariantClear(pVarArray + i); } FreeADsMem(pVarArray); }
RRETURN(hr); }
DWORD DelimitedStrSize( LPWSTR pszString, WCHAR Delimiter ) {
DWORD dwElements = (wcslen(pszString) == 0) ? 0: 1 ; LPTSTR pszCurrPos = pszString;
if (!pszString || !*pszString) { return dwElements; }
while(!(*pszCurrPos == TEXT('\0'))){
if(*pszCurrPos == Delimiter){ dwElements++; *pszCurrPos = TEXT('\0'); }
pszCurrPos++; }
return dwElements;
}
DWORD NulledStrSize( LPWSTR pszString ) {
DWORD dwElements = 0; LPTSTR pszCurrPos = pszString; BOOL foundNULL = FALSE;
if (!pszString || !*pszString) { return dwElements; }
while(!(*pszCurrPos == TEXT('\0') && foundNULL== TRUE)){
if(*pszCurrPos == TEXT('\0')){ dwElements++; foundNULL = TRUE; } else { foundNULL = FALSE; }
pszCurrPos++; }
return dwElements;
}
HRESULT GenericPropCountPropertyManager( CPropertyCache * pPropertyCache, PLONG plCount ) { HRESULT hr = E_FAIL;
if (pPropertyCache) { hr = pPropertyCache->get_PropertyCount((PDWORD)plCount); } RRETURN(hr); }
HRESULT GenericNextPropertyManager( CPropertyCache * pPropertyCache, VARIANT FAR *pVariant ) { HRESULT hr = E_FAIL; DWORD dwSyntaxId = 0; DWORD dwNumValues = 0; LPNTOBJECT pNtSrcObjects = NULL; VARIANT varData; IDispatch * pDispatch = NULL;
VariantInit(&varData);
hr = pPropertyCache->unboundgetproperty( pPropertyCache->get_CurrentIndex(), &dwSyntaxId, &dwNumValues, &pNtSrcObjects ); BAIL_ON_FAILURE(hr);
//
// translate the Nt objects to variants
//
hr = ConvertNtValuesToVariant( pPropertyCache->get_CurrentPropName(), pNtSrcObjects, dwNumValues, pVariant ); BAIL_ON_FAILURE(hr);
error:
//
// - goto next one even if error to avoid infinite looping at a property
// which we cannot convert (e.g. schemaless server property.)
// - do not return the result of Skip() as current operation does not
// depend on the sucess of Skip().
//
pPropertyCache->skip_propindex( 1 );
if (pNtSrcObjects) {
NTTypeFreeNTObjects( pNtSrcObjects, dwNumValues ); }
RRETURN(hr); }
HRESULT GenericSkipPropertyManager( CPropertyCache * pPropertyCache, ULONG cElements ) { HRESULT hr = E_FAIL;
hr = pPropertyCache->skip_propindex( cElements ); RRETURN(hr); }
HRESULT GenericResetPropertyManager( CPropertyCache * pPropertyCache ) { pPropertyCache->reset_propindex();
RRETURN(S_OK); }
HRESULT GenericDeletePropertyManager( CPropertyCache * pPropertyCache, VARIANT varEntry ) { HRESULT hr = S_OK; DWORD dwIndex = 0;
switch (V_VT(&varEntry)) {
case VT_BSTR:
hr = pPropertyCache->findproperty( V_BSTR(&varEntry), &dwIndex ); BAIL_ON_FAILURE(hr); break;
case VT_I4: dwIndex = V_I4(&varEntry); break;
case VT_I2: dwIndex = V_I2(&varEntry); break;
default: hr = E_FAIL; BAIL_ON_FAILURE(hr); }
hr = pPropertyCache->deleteproperty( dwIndex ); error: RRETURN(hr); }
HRESULT GenericPutPropItemPropertyManager( CPropertyCache * pPropertyCache, PPROPERTYINFO pSchemaProps, DWORD dwSchemaPropSize, VARIANT varData ) { HRESULT hr = S_OK; DWORD dwSyntaxId = 0; DWORD dwIndex = 0; WCHAR szPropertyName[MAX_PATH] = L""; LPNTOBJECT pNtDestObjects = NULL; DWORD dwNumValues = 0; DWORD dwControlCode = 0;
hr = ConvertVariantToNtValues( varData, pSchemaProps, dwSchemaPropSize, szPropertyName, &pNtDestObjects, &dwNumValues, &dwSyntaxId, &dwControlCode ); BAIL_ON_FAILURE(hr);
if (dwControlCode != ADS_PROPERTY_UPDATE) { BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER); }
//
// check if this is a writeable property in the schema
//
hr = ValidateIfWriteableProperty( pSchemaProps, dwSchemaPropSize, szPropertyName ); BAIL_ON_FAILURE(hr);
//
// Find this property in the cache
//
hr = pPropertyCache->findproperty( szPropertyName, &dwIndex );
//
// If this property does not exist in the
// cache, add this property into the cache.
//
if (FAILED(hr)) { hr = pPropertyCache->addproperty( szPropertyName, dwSyntaxId, dwNumValues, pNtDestObjects ); //
// If the operation fails for some reason
// move on to the next property
//
BAIL_ON_FAILURE(hr);
}
//
// Now update the property in the cache
//
hr = pPropertyCache->putproperty( szPropertyName, dwSyntaxId, dwNumValues, pNtDestObjects ); BAIL_ON_FAILURE(hr);
error:
if (pNtDestObjects) { NTTypeFreeNTObjects( pNtDestObjects, dwNumValues );
}
RRETURN(hr); }
HRESULT GenericGetPropItemPropertyManager( CPropertyCache * pPropertyCache, DWORD dwObjectState, BSTR bstrName, LONG lnADsType, VARIANT * pVariant ) { HRESULT hr = S_OK; DWORD dwSyntaxId; DWORD dwNumValues; LPNTOBJECT pNtSrcObjects = NULL;
//
// retrieve data object from cache; if one exis
//
if (dwObjectState == ADS_OBJECT_UNBOUND) {
hr = pPropertyCache->unboundgetproperty( bstrName, &dwSyntaxId, &dwNumValues, &pNtSrcObjects ); BAIL_ON_FAILURE(hr);
}else {
hr = pPropertyCache->getproperty( bstrName, &dwSyntaxId, &dwNumValues, &pNtSrcObjects ); BAIL_ON_FAILURE(hr); }
//
// translate the Nds objects to variants
//
hr = ConvertNtValuesToVariant( bstrName, pNtSrcObjects, dwNumValues, pVariant ); BAIL_ON_FAILURE(hr);
error: if (pNtSrcObjects) {
NTTypeFreeNTObjects( pNtSrcObjects, dwNumValues ); }
RRETURN(hr); }
HRESULT GenericItemPropertyManager( CPropertyCache * pPropertyCache, DWORD dwObjectState, VARIANT varIndex, VARIANT *pVariant ) { HRESULT hr = S_OK; DWORD dwSyntaxId; DWORD dwNumValues; LPNTOBJECT pNtSrcObjects = NULL; LPWSTR szPropName = NULL; VARIANT *pvVar = &varIndex;
//
// retrieve data object from cache; if one exis
//
if (V_VT(pvVar) == (VT_BYREF|VT_VARIANT)) { //
// The value is being passed in byref so we need to
// deref it for vbs stuff to work
//
pvVar = V_VARIANTREF(&varIndex); }
switch (V_VT(pvVar)) {
case VT_BSTR: if (dwObjectState == ADS_OBJECT_UNBOUND) {
hr = pPropertyCache->unboundgetproperty( V_BSTR(pvVar), &dwSyntaxId, &dwNumValues, &pNtSrcObjects ); BAIL_ON_FAILURE(hr);
}else {
hr = pPropertyCache->getproperty( V_BSTR(pvVar), &dwSyntaxId, &dwNumValues, &pNtSrcObjects ); BAIL_ON_FAILURE(hr); }
hr = ConvertNtValuesToVariant( V_BSTR(pvVar), pNtSrcObjects, dwNumValues, pVariant ); BAIL_ON_FAILURE(hr);
break;
case VT_I4:
hr = pPropertyCache->unboundgetproperty( V_I4(pvVar), &dwSyntaxId, &dwNumValues, &pNtSrcObjects ); BAIL_ON_FAILURE(hr);
szPropName = pPropertyCache->get_PropName(V_I4(pvVar));
hr = ConvertNtValuesToVariant( szPropName, pNtSrcObjects, dwNumValues, pVariant ); BAIL_ON_FAILURE(hr); break;
case VT_I2:
hr = pPropertyCache->unboundgetproperty( (DWORD)V_I2(pvVar), &dwSyntaxId, &dwNumValues, &pNtSrcObjects ); BAIL_ON_FAILURE(hr);
szPropName = pPropertyCache->get_PropName(V_I2(pvVar));
hr = ConvertNtValuesToVariant( szPropName, pNtSrcObjects, dwNumValues, pVariant ); BAIL_ON_FAILURE(hr); break;
default: hr = E_FAIL; BAIL_ON_FAILURE(hr);
}
error: if (pNtSrcObjects) {
NTTypeFreeNTObjects( pNtSrcObjects, dwNumValues ); }
RRETURN(hr);
}
HRESULT GenericPurgePropertyManager( CPropertyCache * pPropertyCache ) { pPropertyCache->flushpropcache(); RRETURN(S_OK); }
HRESULT CreatePropEntry( LPWSTR szPropName, ADSTYPE dwADsType, VARIANT varData, REFIID riid, LPVOID * ppDispatch )
{ HRESULT hr = S_OK; IADsPropertyEntry * pPropEntry = NULL;
hr = CoCreateInstance( CLSID_PropertyEntry, NULL, CLSCTX_INPROC_SERVER, IID_IADsPropertyEntry, (void **)&pPropEntry ); BAIL_ON_FAILURE(hr);
hr = pPropEntry->put_Name(szPropName);
BAIL_ON_FAILURE(hr);
hr = pPropEntry->put_Values(varData);
BAIL_ON_FAILURE(hr);
hr = pPropEntry->put_ADsType(dwADsType);
BAIL_ON_FAILURE(hr);
// no control code
hr = pPropEntry->QueryInterface( riid, ppDispatch ); BAIL_ON_FAILURE(hr);
error:
if (pPropEntry) { pPropEntry->Release(); }
RRETURN(hr);
}
HRESULT ConvertNtValuesToVariant( LPWSTR szPropertyName, PNTOBJECT pNtSrcObject, DWORD dwNumValues, PVARIANT pVariant ) { HRESULT hr = S_OK; VARIANT varData; IDispatch * pDispatch = NULL; PADSVALUE pAdsValues = NULL; ADSTYPE dwADsType = ADSTYPE_INVALID;
VariantInit(&varData); VariantInit(pVariant);
if (dwNumValues>0) {
hr = NTTypeToAdsTypeCopyConstruct( pNtSrcObject, dwNumValues, &pAdsValues );
if (SUCCEEDED(hr)) {
hr = AdsTypeToPropVariant( pAdsValues, dwNumValues, &varData ); BAIL_ON_FAILURE(hr);
dwADsType = pAdsValues->dwType; }
else if (hr==E_OUTOFMEMORY) {
BAIL_ON_FAILURE(hr); }
//
// failed because of NTType is not supported yet (e.g DelimitedString)
// in NTTypeToAdsTypeCopyConstruct() conversion
// -> use empty variant now.
//
else {
VariantInit(&varData); } }
hr = CreatePropEntry( szPropertyName, dwADsType, varData, IID_IDispatch, (void **)&pDispatch ); BAIL_ON_FAILURE(hr);
V_DISPATCH(pVariant) = pDispatch; V_VT(pVariant) = VT_DISPATCH;
error:
VariantClear(&varData);
if (pAdsValues) { AdsFreeAdsValues( pAdsValues, dwNumValues ); FreeADsMem( pAdsValues ); }
RRETURN(hr);
}
HRESULT ConvertVariantToVariantArray( VARIANT varData, VARIANT ** ppVarArray, DWORD * pdwNumValues ) { DWORD dwNumValues = 0; VARIANT * pVarArray = NULL; HRESULT hr = S_OK; VARIANT * pVarData = NULL;
*ppVarArray = NULL; *pdwNumValues = 0;
//
// A VT_BYREF|VT_VARIANT may expand to a VT_VARIANT|VT_ARRAY.
// We should dereference a VT_BYREF|VT_VARIANT once and see
// what's inside.
//
pVarData = &varData; if (V_VT(pVarData) == (VT_BYREF|VT_VARIANT)) { pVarData = V_VARIANTREF(&varData); }
if ((V_VT(pVarData) == (VT_VARIANT|VT_ARRAY|VT_BYREF)) || (V_VT(&varData) == (VT_VARIANT|VT_ARRAY))) {
hr = ConvertSafeArrayToVariantArray( *pVarData, &pVarArray, &dwNumValues ); BAIL_ON_FAILURE(hr);
} else {
hr = E_FAIL; BAIL_ON_FAILURE(hr); }
*ppVarArray = pVarArray; *pdwNumValues = dwNumValues;
error: RRETURN(hr); }
void FreeVariantArray( VARIANT * pVarArray, DWORD dwNumValues ) { if (pVarArray) {
DWORD i = 0;
for (i = 0; i < dwNumValues; i++) { VariantClear(pVarArray + i); } FreeADsMem(pVarArray); } }
HRESULT ConvertVariantToNtValues( VARIANT varData, PPROPERTYINFO pSchemaProps, DWORD dwSchemaPropSize, LPWSTR szPropertyName, PNTOBJECT *ppNtDestObjects, PDWORD pdwNumValues, PDWORD pdwSyntaxId, PDWORD pdwControlCode ) { HRESULT hr = S_OK; IADsPropertyEntry * pPropEntry = NULL; IDispatch * pDispatch = NULL; BSTR bstrPropName = NULL; DWORD dwControlCode = 0; DWORD dwAdsType = 0; VARIANT varValues; VARIANT * pVarArray = NULL; DWORD dwNumValues = 0; PADSVALUE pAdsValues = NULL; DWORD dwAdsValues = 0;
PNTOBJECT pNtDestObjects = 0; DWORD dwNumNtObjects = 0; DWORD dwNtSyntaxId = 0;
if (V_VT(&varData) != VT_DISPATCH) { RRETURN (hr = DISP_E_TYPEMISMATCH); }
pDispatch = V_DISPATCH(&varData);
hr = pDispatch->QueryInterface( IID_IADsPropertyEntry, (void **)&pPropEntry ); BAIL_ON_FAILURE(hr);
VariantInit(&varValues); VariantClear(&varValues);
hr = pPropEntry->get_Name(&bstrPropName); BAIL_ON_FAILURE(hr); if(wcslen(bstrPropName) < MAX_PATH) wcscpy(szPropertyName, bstrPropName); else { BAIL_ON_FAILURE(hr = E_INVALIDARG); }
hr = pPropEntry->get_ControlCode((long *)&dwControlCode); BAIL_ON_FAILURE(hr); *pdwControlCode = dwControlCode;
hr = pPropEntry->get_ADsType((long *)&dwAdsType); BAIL_ON_FAILURE(hr);
hr = pPropEntry->get_Values(&varValues); BAIL_ON_FAILURE(hr);
hr = ConvertVariantToVariantArray( varValues, &pVarArray, &dwNumValues ); BAIL_ON_FAILURE(hr);
if (dwNumValues) { hr = PropVariantToAdsType( pVarArray, dwNumValues, &pAdsValues, &dwAdsValues ); BAIL_ON_FAILURE(hr);
hr = AdsTypeToNTTypeCopyConstruct( pAdsValues, dwAdsValues, &pNtDestObjects, &dwNumNtObjects, &dwNtSyntaxId ); BAIL_ON_FAILURE(hr);
}
*pdwNumValues = dwNumValues; *ppNtDestObjects = pNtDestObjects; *pdwSyntaxId = dwNtSyntaxId;
error:
if (pVarArray) { FreeVariantArray( pVarArray, dwNumValues ); }
if (pPropEntry) { pPropEntry->Release(); } VariantClear(&varValues);
if (pAdsValues) { AdsFreeAdsValues( pAdsValues, dwAdsValues ); FreeADsMem( pAdsValues ); }
RRETURN(hr); }
HRESULT GetMachineProductType( IN LPTSTR pszServer, OUT PRODUCTTYPE *pdwProductType ) {
HRESULT hr = S_OK; LONG dwStatus; HKEY hkLocalMachine = NULL; HKEY hkProductOptions = NULL; DWORD dwValueType; WCHAR szData[20]; DWORD dwDataSize = sizeof(szData);
//
// pszServer can be NULL for local server
//
if (!pdwProductType) RRETURN(E_ADS_BAD_PARAMETER);
*pdwProductType = PRODTYPE_INVALID;
//
// Connect to remote's machine registry
//
dwStatus = RegConnectRegistry( pszServer, HKEY_LOCAL_MACHINE, &hkLocalMachine );
if (dwStatus != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(dwStatus); BAIL_ON_FAILURE(hr); }
//
// Open key ProductOptions
//
dwStatus = RegOpenKeyEx( hkLocalMachine, L"SYSTEM\\CurrentControlSet\\Control\\ProductOptions", 0, KEY_QUERY_VALUE, &hkProductOptions );
if (dwStatus != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(dwStatus); BAIL_ON_FAILURE(hr); }
//
// Get Value of Product Type
//
dwStatus = RegQueryValueEx( hkProductOptions, L"ProductType", NULL, &dwValueType, (LPBYTE) szData, &dwDataSize );
//
// check server type
//
if (_wcsicmp(szData, WINNT_A_LANMANNT_W)==0) { *pdwProductType = PRODTYPE_DC; } else if (_wcsicmp(szData, WINNT_A_SERVERNT_W)==0) { *pdwProductType = PRODTYPE_STDALONESVR; } else if (_wcsicmp(szData, WINNT_A_WINNT_W)==0) { *pdwProductType = PRODTYPE_WKSTA; } else { hr = E_FAIL; BAIL_ON_FAILURE(hr); }
error:
if ( hkLocalMachine ) RegCloseKey(hkLocalMachine);
if ( hkProductOptions ) RegCloseKey(hkProductOptions);
RRETURN(hr); }
//
// Get Sid of account name [lpszAccountName] from server [lpszServerName].
// Unmarshall the Sid into cache [pPropertyCache] if [fExplict] is TRUE.
// Use local machine if [lpszServerName] == NULL.
//
HRESULT GetSidIntoCache( IN LPTSTR lpszServerName, IN LPTSTR lpszAccountName, IN CPropertyCache * pPropertyCache, IN BOOL fExplicit ) { HRESULT hr = S_OK; BOOL fGotSid = FALSE; DWORD dwErr = 0; PSID pSid = NULL; DWORD dwSidLength = 0; WCHAR szNewAccountName[MAX_PATH+UNLEN+2]; LPTSTR lpSrvName;
//
// default cbSid size :
// - 1 (revision), 1 (authid), max sub(auth)
// - * 8 (rev, authid, subid all < 8), but use 8 in case of
// structure aligment because of compiler/machine (we want
// LookUpAccountName() to succeed at first attempt as much
// as possible to min this wired call)
//
const DWORD maxSid = (1+1+SID_MAX_SUB_AUTHORITIES) * 8; DWORD cbSid = maxSid;
//
// dummies
//
TCHAR szRefDomainName[MAX_PATH]; DWORD cbRefDomainName = MAX_PATH; SID_NAME_USE eNameUse;
if (!lpszAccountName) RRETURN(E_ADS_INVALID_USER_OBJECT);
if (!pPropertyCache) RRETURN(E_ADS_BAD_PARAMETER);
//
// allocate sid and RefDomainName buffer
//
pSid = (PSID) AllocADsMem( cbSid ); if (!pSid) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); } //
// get sid and other unused info from server
//
fGotSid = LookupAccountName( lpszServerName, lpszAccountName, pSid, &cbSid, szRefDomainName, &cbRefDomainName, &eNameUse );
if (!fGotSid) {
if (cbSid>maxSid) {
//
// Fail becuase buffer size required > what we have allocated
// for some reasons, retry with correct buffer size
//
FreeADsMem(pSid);
pSid = (PSID) AllocADsMem( cbSid ); if (!pSid) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); }
fGotSid = LookupAccountName( lpszServerName, lpszAccountName, pSid, &cbSid, szRefDomainName, &cbRefDomainName, &eNameUse );
if (!fGotSid) {
//
// Fail on retry with proper buffer size, can do no more
//
dwErr = GetLastError(); hr = HRESULT_FROM_WIN32(dwErr); }
} else {
//
// Fail becuase of reasons other then buffer size, not need to
// retry.
//
dwErr = GetLastError(); hr = HRESULT_FROM_WIN32(dwErr); } } if( fGotSid && (eNameUse == SidTypeDomain) ) { lpSrvName = lpszServerName; if (lpszServerName && (lpszServerName[0] == L'\\') && (lpszServerName[1] == L'\\')) { lpSrvName += 2; }
#ifdef WIN95
if (!_wcsicmp(lpszAccountName, lpSrvName)) { #else
if (CompareStringW( LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, lpszAccountName, -1, lpSrvName, -1 ) == CSTR_EQUAL ) { #endif
wcscpy(szNewAccountName, lpSrvName); wcscat(szNewAccountName, L"\\"); wcscat(szNewAccountName, lpszAccountName);
cbSid = maxSid; cbRefDomainName = MAX_PATH; fGotSid = LookupAccountName( lpszServerName, szNewAccountName, pSid, &cbSid, szRefDomainName, &cbRefDomainName, &eNameUse );
if (!fGotSid) {
if (cbSid>maxSid) {
//
// Fail becuase buffer size required > what we have allocated
// for some reasons, retry with correct buffer size
//
FreeADsMem(pSid);
pSid = (PSID) AllocADsMem( cbSid ); if (!pSid) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); }
fGotSid = LookupAccountName( lpszServerName, szNewAccountName, pSid, &cbSid, szRefDomainName, &cbRefDomainName, &eNameUse );
if (!fGotSid) {
//
// Fail on retry with proper buffer size, can do no more
//
dwErr = GetLastError(); hr = HRESULT_FROM_WIN32(dwErr); }
} else {
//
// Fail becuase of reasons other then buffer size, not need to
// retry.
//
dwErr = GetLastError(); hr = HRESULT_FROM_WIN32(dwErr); } } } }
BAIL_ON_FAILURE(hr);
//
// On NT4 for some reason GetLengthSID does not set lasterror to 0
//
SetLastError(NO_ERROR);
dwSidLength = GetLengthSid((PSID) pSid);
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); //
// store Sid in property cache
//
hr = SetOctetPropertyInCache( pPropertyCache, TEXT("objectSid"), (PBYTE) pSid, dwSidLength, fExplicit ); BAIL_ON_FAILURE(hr);
error:
if (pSid) { FreeADsMem(pSid); }
RRETURN(hr);
}
|