#define _WIN32_DCOM #include #include #include #include #include #include // COM Interface header file. #include // MD_ & IIS_MD_ #defines header file. #include #include #include #include "util.h" #include "auth.h" #include "filecopy.h" #include "mbase.h" #define ORIGINAL_BUFFER_SIZE 256 #define KEYTYPE_NAME_BUFFER 32 #pragma comment(lib,"Shlwapi.lib") HRESULT CreateAndCopyKey( IMSAdminBase* pIMetaSource, METADATA_HANDLE hMDSourceHandle, //metabase handle to the source key. wchar_t* pszMDSourcePath, //path of the source relative to hMDSourceHandle. IMSAdminBase* pIMetaTarget, METADATA_HANDLE hMDDestHandle, //metabase handle to the destination. wchar_t* pszMDDestPath, //path of the destination, relative to hMDDestHandle. BOOL bMDCopySubKeys //whether to copy all subkey data ) { HRESULT hRes = S_OK; DWORD indx = 0; WCHAR SubKeyName[MAX_PATH*2]; _bstr_t bstrTargetSubKeyPath; _bstr_t bstrSourceSubKeyPath; ATLASSERT(pIMetaSource != NULL); ATLASSERT(pIMetaTarget != NULL); ATLASSERT(pszMDSourcePath); ATLASSERT(pszMDDestPath); // first this will create the destination key. pIMetaTarget->AddKey(hMDDestHandle,pszMDDestPath); while (SUCCEEDED(hRes)) { hRes = pIMetaSource->EnumKeys(hMDSourceHandle, pszMDSourcePath, SubKeyName, indx); if(SUCCEEDED(hRes)) { bstrTargetSubKeyPath = pszMDDestPath; bstrTargetSubKeyPath += L"/"; bstrTargetSubKeyPath += SubKeyName; bstrSourceSubKeyPath = pszMDSourcePath; bstrSourceSubKeyPath += L"/"; bstrSourceSubKeyPath += SubKeyName; //wprintf(L"%s %s\n",SubKeyName,KeyType); CreateAndCopyKey (pIMetaSource,hMDSourceHandle,bstrSourceSubKeyPath,pIMetaTarget, hMDDestHandle,bstrTargetSubKeyPath, bMDCopySubKeys); } indx++; } //while (SUCCEEDED(hRes)) hRes = EnumProperties(pIMetaSource,hMDSourceHandle,pszMDSourcePath,pIMetaTarget,hMDDestHandle,pszMDDestPath); return hRes; } HRESULT EnumProperties(IMSAdminBase* pIMetaSource, METADATA_HANDLE hKeySource, wchar_t* SourceMDPath, IMSAdminBase* pIMetaTarget, METADATA_HANDLE hKeyTarget, wchar_t* TargetMDPath ) { HRESULT hRes = 0; METADATA_RECORD mRec; DWORD indx = 0; DWORD dwReqBufLen = 0; DWORD dwBufLen = ORIGINAL_BUFFER_SIZE; PBYTE pbBuffer = new BYTE[dwBufLen]; wchar_t *ptemp = 0; while (SUCCEEDED(hRes)){ mRec.dwMDAttributes = METADATA_ISINHERITED; mRec.dwMDUserType = ALL_METADATA; //IIS_MD_UT_FILE ; mRec.dwMDDataType = ALL_METADATA; mRec.dwMDDataLen = dwBufLen; mRec.pbMDData = pbBuffer; hRes = pIMetaSource->EnumData(hKeySource, SourceMDPath, &mRec, indx, &dwReqBufLen); if (hRes == RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER)) { delete [] (pbBuffer); pbBuffer = new BYTE[dwReqBufLen]; dwBufLen = dwReqBufLen; mRec.dwMDDataLen = dwReqBufLen; mRec.pbMDData = pbBuffer; hRes = pIMetaSource->EnumData(hKeySource, SourceMDPath, &mRec, indx, &dwReqBufLen); } if ( SUCCEEDED(hRes) ) { // write the property to the target if( mRec.dwMDIdentifier == MD_APP_ROOT ) { // mRec.pbMDData = new WCHAR[MAX_PATH]; wcscpy((LPWSTR)mRec.pbMDData, _bstr_t(L"/LM") + _bstr_t(TargetMDPath) ); mRec.dwMDDataLen = (DWORD)(wcslen((LPWSTR)mRec.pbMDData)+1)*2; } hRes = pIMetaTarget->SetData(hKeyTarget,TargetMDPath,&mRec); if( !SUCCEEDED(hRes) ) return hRes; } // Increment the index. indx++; } // End while. delete pbBuffer; //wprintf(L"Done numerating properties set at: %s ...\n",SourceMDPath); return S_OK; } // INPUT canonicalized source path node in relation to the root key "/LM" ex: /w3svc/1 HRESULT CopyIISConfig(COSERVERINFO *pCoServerInfoSource, COSERVERINFO *pCoServerInfoTarget, WCHAR *pwszSourceKey, _bstr_t &bstrTargetKey) { HRESULT hRes; METADATA_HANDLE hKeySource; METADATA_HANDLE hKeyTarget; CComPtr pIMetaSource = 0L; CComPtr pIMetaTarget = 0L; BOOL bIsLocal; _bstr_t bstrRootKey = L"/LM"; _bstr_t bstrTargetNode; long lTargetSiteID; // Declare a MULTI_QI for remote usage MULTI_QI rgmqi[1] = { &IID_IMSAdminBase,0,0 }; ATLASSERT(pCoServerInfoSource); ATLASSERT(pCoServerInfoTarget); bIsLocal = IsServerLocal( (char*)_bstr_t(pCoServerInfoSource->pwszName) ); hRes = CoCreateInstanceEx(CLSID_MSAdminBase,NULL, CLSCTX_ALL, pCoServerInfoSource, 1, rgmqi); if(SUCCEEDED(hRes)) pIMetaSource = reinterpret_cast(rgmqi[0].pItf); else { wprintf( L"error creating IMSAdminbase on machine: %s. HRESULT=%x\n", pCoServerInfoSource->pwszName, hRes); return hRes; } if( pCoServerInfoSource->pAuthInfo->pAuthIdentityData->User ) { //hRes = SetBlanket(pIMetaSource); if (!SUCCEEDED(SetBlanket(pIMetaSource,pCoServerInfoSource->pAuthInfo->pAuthIdentityData->User, pCoServerInfoSource->pAuthInfo->pAuthIdentityData->Domain, pCoServerInfoSource->pAuthInfo->pAuthIdentityData->Password) ) ) { _tprintf(_T("error setting COM impersonation: HRESULT=%x\n"), hRes); return hRes; } } if(bIsLocal) //hRes = pIMetaSource->QueryInterface(IID_IMSAdminBase,(void**)&pIMetaTarget); pIMetaTarget = pIMetaSource; else { // Create the IMSAdminBase object on the target server rgmqi[0].pItf = 0L; rgmqi[0].hr = 0L; hRes = CoCreateInstanceEx(CLSID_MSAdminBase,NULL, CLSCTX_ALL, pCoServerInfoTarget, 1, rgmqi); if(SUCCEEDED(hRes)) pIMetaTarget = reinterpret_cast(rgmqi[0].pItf); else { _tprintf(_T("error creating IMSAdminbase on this machine: %s. HRESULT=%x\n"), (char*)_bstr_t(pCoServerInfoTarget->pwszName), hRes); return hRes; } } // Open the metabase on the source and target if( bIsLocal ) { if( !SUCCEEDED( hRes = pIMetaSource->OpenKey(METADATA_MASTER_ROOT_HANDLE, bstrRootKey, METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE, 10000, &hKeySource) ) ) { _tprintf( _T("OpenKey() failed on the root key %s on server: %s, hr = %x\n"), (char*)bstrRootKey, (char*)_bstr_t(pCoServerInfoSource->pwszName), hRes ); return hRes; } hKeyTarget = hKeySource; } else { // Get a handle to the Root key of the Source machine if( !SUCCEEDED( hRes = pIMetaSource->OpenKey(METADATA_MASTER_ROOT_HANDLE, bstrRootKey, METADATA_PERMISSION_READ , 10000, &hKeySource) )) { _tprintf( _T("OpenKey() failed on the root key %s on server: %s, hr = %x\n"), (char*)bstrRootKey, (char*)_bstr_t(pCoServerInfoSource->pwszName), hRes ); return hRes; } // Get a handle to the Root key of the Target machine if( !SUCCEEDED( hRes = pIMetaTarget->OpenKey(METADATA_MASTER_ROOT_HANDLE, bstrRootKey, METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE, 10000, &hKeyTarget) )) { _tprintf( _T("OpenKey() failed on the root key %s on server: %s, hr = %x\n"), (char*)bstrRootKey, (char*)_bstr_t(pCoServerInfoTarget->pwszName), hRes ); pIMetaSource->CloseKey(hKeySource); return hRes; } } if( bstrTargetKey.length() == 0 ) { lTargetSiteID = GetAvailableSiteID(pIMetaTarget,hKeyTarget); bstrTargetNode = L"/W3SVC/"; bstrTargetNode += _bstr_t(lTargetSiteID); bstrTargetKey = bstrTargetNode; } else bstrTargetNode = bstrTargetKey; // replicate the metabase node fwprintf(stderr, L"replicating IIS metabase properties set at: %s ...\n",pwszSourceKey); hRes = CreateAndCopyKey(pIMetaSource,hKeySource, pwszSourceKey, pIMetaTarget, hKeyTarget,bstrTargetNode, true ); if( !SUCCEEDED(hRes) ) { _tprintf( _T("Error encountered in metabase copy operation\n") ); } pIMetaSource->CloseKey(hKeySource); if( !bIsLocal ) pIMetaTarget->CloseKey( hKeyTarget ); pIMetaSource = 0; pIMetaTarget = 0; return hRes; } HRESULT ApplyMBFixUp(COSERVERINFO *pCoServerInfo, WCHAR * pwszKey, WCHAR * pwszAppPoolID, PXCOPYTASKITEM pXCOPYList, WCHAR * pwszServerBinding, BOOL bApplyFPSE) { HRESULT hRes; METADATA_HANDLE hKey; CComPtr pIMeta = 0L; MULTI_QI rgmqi[1] = { &IID_IMSAdminBase,0,0 }; WCHAR DataBuf[MAX_PATH]; memset (DataBuf,0,sizeof(DataBuf) ); PXCOPYTASKITEM pList = pXCOPYList; bstr_t bstrRealTargetPath; WCHAR *pTemp = NULL; DWORD dwFPSEBOOL; DWORD dwSize = sizeof(DWORD); _bstr_t bstrCommandline; TCHAR szOwsAdmPath[MAX_PATH]; ZeroMemory(szOwsAdmPath,sizeof(szOwsAdmPath)); ATLASSERT(pwszKey); if( !pCoServerInfo ) return E_UNEXPECTED; if( SUCCEEDED(hRes = CoCreateInstanceEx(CLSID_MSAdminBase,NULL, CLSCTX_ALL, pCoServerInfo,1, rgmqi) ) ) pIMeta = reinterpret_cast(rgmqi[0].pItf); else { fwprintf( stderr, L"error creating IMSAdminbase on machine: %s. HRESULT=%x\n", pCoServerInfo->pwszName, hRes); return hRes; } if( UsesImpersonation(pCoServerInfo) ) { if (!SUCCEEDED(hRes = SetBlanket(pIMeta,pCoServerInfo->pAuthInfo->pAuthIdentityData->User, pCoServerInfo->pAuthInfo->pAuthIdentityData->Domain, pCoServerInfo->pAuthInfo->pAuthIdentityData->Password) ) ) { fwprintf( stderr, L"error setting CoSetProxyBlanket on machine: %s for user: %s HRESULT=%x\n", pCoServerInfo->pwszName,pCoServerInfo->pAuthInfo->pAuthIdentityData->User, hRes); pIMeta = 0; return hRes; } } if( !SUCCEEDED( hRes = pIMeta->OpenKey(METADATA_MASTER_ROOT_HANDLE, L"/LM", METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE , 10000, &hKey) ) ) { fwprintf( stderr, L"Error opening key: %s on computer: %s. HRESULT=%x\n", L"/LM", pCoServerInfo->pwszName, hRes); pIMeta = 0; return hRes; } if( !SUCCEEDED( hRes = CreateAppPool(pIMeta,hKey,pwszAppPoolID) ) ) { return hRes; } // Now set the AppPoolID property of the Key // wcscpy((LPWSTR)DataBuf, pwszAppPoolID); hRes = SetPropertyData(pIMeta,hKey,_bstr_t(pwszKey) + _bstr_t(L"/root"), MD_APP_APPPOOL_ID, METADATA_INHERIT, IIS_MD_UT_SERVER,STRING_METADATA, (PBYTE)pwszAppPoolID, (wcslen(pwszAppPoolID) + 1) * sizeof(WCHAR) ); // Loope thought the list and reset any Path direcrories if( pList ) { ATLASSERT(pList->pwszMBPath); ATLASSERT(pList->pwszDestPath); pTemp = wcsstr(_wcslwr(pList->pwszMBPath),L"/root"); bstrRealTargetPath = _bstr_t(pwszKey) + _bstr_t(pTemp); hRes = SetPropertyData(pIMeta,hKey,bstrRealTargetPath, MD_VR_PATH, METADATA_INHERIT, IIS_MD_UT_FILE,STRING_METADATA, pList->pwszDestPath, (wcslen(pList->pwszDestPath) + 1) * sizeof(WCHAR) ); while( pList->pNextItem ) { pList = pList->pNextItem; pTemp = wcsstr(_wcslwr(pList->pwszMBPath),L"/root"); bstrRealTargetPath = _bstr_t(pwszKey) + _bstr_t(pTemp); hRes = SetPropertyData(pIMeta,hKey,bstrRealTargetPath, MD_VR_PATH, METADATA_INHERIT, IIS_MD_UT_FILE,STRING_METADATA, pList->pwszDestPath, (wcslen(pList->pwszDestPath) + 1) * sizeof(WCHAR) ); } } // Set the serverbinding string if present if( pwszServerBinding ) { hRes = SetPropertyData(pIMeta,hKey,pwszKey, MD_SERVER_BINDINGS, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER,MULTISZ_METADATA, pwszServerBinding, (wcslen(pwszServerBinding) + 1) * sizeof(WCHAR) + 1 * sizeof(WCHAR)); } if (bApplyFPSE) { // Check to see if the web is front page extended bstrCommandline = "-o install -p /lm"; bstrCommandline += _bstr_t(pwszKey); hRes = GetPropertyData(pIMeta,hKey,pwszKey,MD_FRONTPAGE_WEB,METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, DWORD_METADATA, &dwFPSEBOOL, &dwSize ); if( SUCCEEDED(hRes) ) { if(SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES_COMMON , NULL, SHGFP_TYPE_CURRENT, szOwsAdmPath)) ) { PathAppend(szOwsAdmPath, TEXT("Microsoft Shared\\Web Server Extensions\\50\\bin\\owsadm.exe") ); } } } if( !SUCCEEDED(hRes = pIMeta->CloseKey(hKey) ) ) { fwprintf( stderr, L"Error closing key: /LM/W3SVC on computer: %s. HRESULT=%x\n", pCoServerInfo->pwszName, hRes); } pIMeta = 0; if( bApplyFPSE ) { fwprintf(stderr,L"reconfiguring FPSE settings...\n" ); MyCreateProcess(szOwsAdmPath,bstrCommandline,CREATE_NEW_PROCESS_GROUP,360000); } return hRes; } HRESULT CreateAppPool(IMSAdminBase* pIMeta,METADATA_HANDLE hKey,WCHAR *pAppPoolID) { HRESULT hRes; _bstr_t bstrAppPoolPath(L"/w3svc/AppPools/"); WCHAR DataBuf[MAX_PATH]; memset (DataBuf,0,sizeof(DataBuf) ); bstrAppPoolPath += pAppPoolID; hRes = pIMeta->AddKey(hKey,bstrAppPoolPath); // Set the KeyType property of the AppPool // hRes = SetKeyType( pIMeta, hKey, bstrAppPoolPath, L"IIsApplicationPool" ); hRes = SetPropertyData(pIMeta,hKey,bstrAppPoolPath,MD_KEY_TYPE,METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER,STRING_METADATA,L"IIsApplicationPool",(wcslen(L"IIsApplicationPool") + 1) * sizeof(WCHAR) ); return hRes; }