//--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1996 - 1997 // // File: common.cxx // // Contents: Microsoft ADs IIS Common routines // // History: 28-Feb-97 SophiaC Created. // //---------------------------------------------------------------------------- #include "iisext.hxx" extern SERVER_CACHE * g_pServerCache; extern WIN32_CRITSEC * g_pGlobalLock; #pragma hdrstop #define DEFAULT_TIMEOUT_VALUE 30000 //+------------------------------------------------------------------------ // // 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 MakeVariantFromStringArray( LPWSTR pszList, VARIANT *pvVariant ) { HRESULT hr = S_OK; SAFEARRAY *aList = NULL; SAFEARRAYBOUND aBound; LPWSTR pszStrList; WCHAR wchPath[MAX_PATH]; if (pszList != NULL) { long nCount = 0; long i = 0; pszStrList = pszList; if (*pszStrList == L'\0') { nCount = 1; pszStrList++; } while (*pszStrList != L'\0') { while (*pszStrList != L'\0') { pszStrList++; } nCount++; pszStrList++; } aBound.lLbound = 0; aBound.cElements = nCount; aList = SafeArrayCreate( VT_VARIANT, 1, &aBound ); if ( aList == NULL ) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); } pszStrList = pszList; for (i = 0; i < nCount; i++ ) { VARIANT v; VariantInit(&v); V_VT(&v) = VT_BSTR; hr = ADsAllocString( pszStrList, &(V_BSTR(&v))); BAIL_ON_FAILURE(hr); hr = SafeArrayPutElement( aList, &i, &v ); VariantClear(&v); BAIL_ON_FAILURE(hr); pszStrList += wcslen(pszStrList) + 1; } VariantInit( pvVariant ); V_VT(pvVariant) = VT_ARRAY | VT_VARIANT; V_ARRAY(pvVariant) = aList; } else { aBound.lLbound = 0; aBound.cElements = 0; aList = SafeArrayCreate( VT_VARIANT, 1, &aBound ); if ( aList == NULL ) { hr = E_OUTOFMEMORY; BAIL_ON_FAILURE(hr); } VariantInit( pvVariant ); V_VT(pvVariant) = VT_ARRAY | VT_VARIANT; V_ARRAY(pvVariant) = aList; } return S_OK; error: if ( aList ) SafeArrayDestroy( aList ); return hr; } HRESULT ReCacheAdminBase( IN LPWSTR pszServerName, IN OUT IMSAdminBase **ppAdminBase ) { HRESULT hr = S_OK; SERVER_CACHE_ITEM * item = NULL; DWORD dwThreadId; IMSAdminBase * pAdminBase = *ppAdminBase; IMSAdminBase * pOldAdminBase = *ppAdminBase; // RPC error caused this function to be called, so try to // recover the connection hr = InitAdminBase(pszServerName, &pAdminBase); BAIL_ON_FAILURE(hr); // we will return this one, so save it in the OUT param *ppAdminBase = pAdminBase; // update the cache dwThreadId = GetCurrentThreadId(); item = g_pServerCache->Find(pszServerName, dwThreadId); if (item != NULL) { UninitAdminBase(pOldAdminBase); item->UpdateAdminBase(pAdminBase, dwThreadId); } error : RRETURN(hr); } HRESULT OpenAdminBaseKey( IN LPWSTR pszServerName, IN LPWSTR pszPathName, IN DWORD dwAccessType, IN OUT IMSAdminBase **ppAdminBase, OUT METADATA_HANDLE *phHandle ) { HRESULT hr; IMSAdminBase *pAdminBase = *ppAdminBase; METADATA_HANDLE RootHandle = NULL; DWORD dwThreadId; hr = pAdminBase->OpenKey( METADATA_MASTER_ROOT_HANDLE, pszPathName, dwAccessType, DEFAULT_TIMEOUT_VALUE, &RootHandle ); if (FAILED(hr)) { if ((HRESULT_CODE(hr) == RPC_S_SERVER_UNAVAILABLE) || ((HRESULT_CODE(hr) >= RPC_S_NO_CALL_ACTIVE) && (HRESULT_CODE(hr) <= RPC_S_CALL_FAILED_DNE)) || hr == RPC_E_DISCONNECTED) { hr = ReCacheAdminBase(pszServerName, &pAdminBase); BAIL_ON_FAILURE(hr); *ppAdminBase = pAdminBase; hr = pAdminBase->OpenKey( METADATA_MASTER_ROOT_HANDLE, pszPathName, dwAccessType, DEFAULT_TIMEOUT_VALUE, &RootHandle ); BAIL_ON_FAILURE(hr); } } error : if (FAILED(hr)) { if (pAdminBase && RootHandle) { pAdminBase->CloseKey(RootHandle); } } else { *phHandle = RootHandle; } RRETURN(hr); } VOID CloseAdminBaseKey( IN IMSAdminBase *pAdminBase, IN METADATA_HANDLE hHandle ) { HRESULT hr; if (pAdminBase) { hr = pAdminBase->CloseKey(hHandle); } return; } HRESULT InitAdminBase( IN LPWSTR pszServerName, OUT IMSAdminBase **ppAdminBase ) { HRESULT hr = S_OK; COSERVERINFO csiName; COSERVERINFO *pcsiParam = &csiName; IClassFactory * pcsfFactory = NULL; IMSAdminBase * pAdminBase = NULL; IMSAdminBase * pAdminBaseT = NULL; memset(pcsiParam, 0, sizeof(COSERVERINFO)); // // special case to handle "localhost" to work-around ole32 bug // if (pszServerName == NULL || _wcsicmp(pszServerName,L"localhost") == 0) { pcsiParam->pwszName = NULL; } else { pcsiParam->pwszName = pszServerName; } csiName.pAuthInfo = NULL; pcsiParam = &csiName; hr = CoGetClassObject( CLSID_MSAdminBase, CLSCTX_SERVER, pcsiParam, IID_IClassFactory, (void**) &pcsfFactory ); BAIL_ON_FAILURE(hr); hr = pcsfFactory->CreateInstance( NULL, IID_IMSAdminBase, (void **) &pAdminBaseT ); BAIL_ON_FAILURE(hr); hr = pAdminBaseT->UnmarshalInterface((IMSAdminBaseW **)&pAdminBase); pAdminBaseT->Release(); pAdminBaseT = NULL; BAIL_ON_FAILURE(hr); *ppAdminBase = pAdminBase; error: if (pcsfFactory) { pcsfFactory->Release(); } RRETURN(hr); } VOID UninitAdminBase( IN IMSAdminBase * pAdminBase ) { if (pAdminBase != NULL) { pAdminBase->Release(); } } HRESULT InitServerInfo( IN LPWSTR pszServerName, OUT IMSAdminBase ** ppObject ) { HRESULT hr = S_OK; IMSAdminBase * pAdminBase = NULL; SERVER_CACHE_ITEM * item; BOOL Success; DWORD dwThreadId; ASSERT(g_pServerCache != NULL); // // We'll return the localhost machine config to the users if // pszServerName == NULL, e.g. IIS: // if (pszServerName == NULL) { pszServerName = L"Localhost"; } dwThreadId = GetCurrentThreadId(); if ((item = g_pServerCache->Find(pszServerName, dwThreadId)) == NULL) { // // get pAdminBase // hr = InitAdminBase(pszServerName, &pAdminBase); BAIL_ON_FAILURE(hr); item = new SERVER_CACHE_ITEM(pszServerName, pAdminBase, dwThreadId, Success); if (item == NULL || !Success) { if (item != NULL) { UninitAdminBase(pAdminBase); delete item; } RRETURN(E_OUTOFMEMORY); // OUT_OF_MEMORY; } if (g_pServerCache->Insert(item) == FALSE) { UninitAdminBase(pAdminBase); delete item; RRETURN(E_OUTOFMEMORY); // OUT_OF_MEMORY; } } *ppObject = item->pAdminBase; error : RRETURN(hr); } HRESULT InitWamAdmin( IN LPWSTR pszServerName, OUT IWamAdmin2 **ppWamAdmin ) { HRESULT hr = S_OK; COSERVERINFO csiName; COSERVERINFO *pcsiParam = &csiName; IClassFactory * pcsfFactory = NULL; IWamAdmin2 * pWamAdmin = NULL; memset(pcsiParam, 0, sizeof(COSERVERINFO)); // // special case to handle "localhost" to work-around ole32 bug // if (pszServerName == NULL || _wcsicmp(pszServerName,L"localhost") == 0) { pcsiParam->pwszName = NULL; } else { pcsiParam->pwszName = pszServerName; } csiName.pAuthInfo = NULL; pcsiParam = &csiName; hr = CoGetClassObject( CLSID_WamAdmin, CLSCTX_SERVER, pcsiParam, IID_IClassFactory, (void**) &pcsfFactory ); BAIL_ON_FAILURE(hr); hr = pcsfFactory->CreateInstance( NULL, IID_IWamAdmin2, (void **) &pWamAdmin ); BAIL_ON_FAILURE(hr); *ppWamAdmin = pWamAdmin; error: if (pcsfFactory) { pcsfFactory->Release(); } RRETURN(hr); } VOID UninitWamAdmin( IN IWamAdmin2 *pWamAdmin ) { if (pWamAdmin != NULL) { pWamAdmin->Release(); } } HRESULT BuildIISPathFromADsPath( POBJECTINFO pObjectInfo, LPWSTR pszIISPathName ) { DWORD dwNumComponents = 0; DWORD i = 0; dwNumComponents = pObjectInfo->NumComponents; // // wcscat "LM" to IIS Metabase path // wcscat(pszIISPathName, L"/LM/"); if (dwNumComponents) { for (i = 0; i < dwNumComponents; i++) { if (wcscmp(pObjectInfo->ComponentArray[i].szComponent, L"[Root]")){ wcscat(pszIISPathName, pObjectInfo->ComponentArray[i].szComponent); } else { if( i == dwNumComponents -1 ) { wcscat(pszIISPathName, L"/"); } } if( i < dwNumComponents -1 ) { wcscat(pszIISPathName,L"/"); } } } RRETURN(S_OK); } VOID FreeObjectInfo( POBJECTINFO pObjectInfo ) { if ( !pObjectInfo ) return; if (pObjectInfo->ProviderName) { FreeADsStr( pObjectInfo->ProviderName ); } if (pObjectInfo->TreeName) { FreeADsStr( pObjectInfo->TreeName ); } if ((pObjectInfo->ComponentArray) && (pObjectInfo->NumComponents)) { for ( DWORD i = 0; i < pObjectInfo->NumComponents; i++ ) { if (pObjectInfo->ComponentArray[i].szComponent) { FreeADsStr( pObjectInfo->ComponentArray[i].szComponent ); } if (pObjectInfo->ComponentArray[i].szValue) { FreeADsStr( pObjectInfo->ComponentArray[i].szValue ); } } } if (pObjectInfo->ComponentArray) { FreeADsMem(pObjectInfo->ComponentArray); } // We don't need to free pObjectInfo since the object is always a static // variable on the stack. }