// ImportUI.cpp : Implementation of CImportUI #include "stdafx.h" #include "IISUIObj.h" #include "ImportExportConfig.h" #include "ExportUI.h" #include "ImportUI.h" #include "Defaults.h" #include "util.h" #include "ddxv.h" #include #define HIDD_IISUIOBJ_IMPORT 0x50401 #define LAST_USED_IMPORT_FILE _T("LastImportFile") LPTSTR GimmiePointerToLastPart(LPCTSTR lpszMDPath) { LPTSTR lpszReturn = NULL; ASSERT_PTR(lpszMDPath); if (!lpszMDPath || !*lpszMDPath) { return NULL; } LPCTSTR lp = lpszMDPath + _tcslen(lpszMDPath) - 1; // // Skip trailing separator // if (*lp == SZ_MBN_SEP_CHAR) { --lp; } while (*lp && *lp != SZ_MBN_SEP_CHAR) { lpszReturn = (LPTSTR) (lp--); } return lpszReturn; } void InitListView(HWND hList) { LV_COLUMN lvCol; RECT rect; LONG width; ZeroMemory(&rect, sizeof(rect)); GetWindowRect(hList, &rect); width = rect.right - rect.left - 4; // -4 to prevent the horizontal scrollbar from appearing ZeroMemory(&lvCol, sizeof(lvCol)); lvCol.mask = LVCF_TEXT | LVCF_WIDTH; lvCol.fmt = LVCFMT_LEFT; lvCol.cx = width; ListView_InsertColumn(hList, 0, &lvCol); return; } HRESULT DoImportConfigFromFile(PCONNECTION_INFO pConnectionInfo,BSTR bstrFileNameAndPath,BSTR bstrMetabaseSourcePath,BSTR bstrMetabaseDestinationPath,BSTR bstrPassword,DWORD dwImportFlags) { HRESULT hr = E_FAIL; IMSAdminBase *pIMSAdminBase = NULL; IMSAdminBase2 *pIMSAdminBase2 = NULL; LPWSTR lpwstrTempPassword = NULL; if (!pConnectionInfo) { return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER); } if (pConnectionInfo->pszUserPasswordEncrypted) { if (FAILED(DecryptMemoryPassword((LPWSTR) pConnectionInfo->pszUserPasswordEncrypted,&lpwstrTempPassword,pConnectionInfo->cbUserPasswordEncrypted))) { return HRESULT_FROM_WIN32(ERROR_DECRYPTION_FAILED); } } CComAuthInfo auth(pConnectionInfo->pszMachineName,pConnectionInfo->pszUserName,lpwstrTempPassword); if (!bstrFileNameAndPath) { return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER); } // Bufferfer overflow paranoia, make sure it's less than 255 characters long if (wcslen(bstrFileNameAndPath) > (_MAX_PATH)){return RPC_S_STRING_TOO_LONG;} if (wcslen(bstrMetabaseSourcePath) > (_MAX_PATH * 3)){return RPC_S_STRING_TOO_LONG;} if (wcslen(bstrMetabaseDestinationPath) > (_MAX_PATH * 3)){return RPC_S_STRING_TOO_LONG;} if (bstrPassword) { if (wcslen(bstrPassword) > (_MAX_PATH)){return RPC_S_STRING_TOO_LONG;} } if(FAILED(hr = CoInitializeEx(NULL, COINIT_MULTITHREADED))) { if(FAILED(hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED))) { return hr; } } // RPC_C_AUTHN_LEVEL_DEFAULT 0 // RPC_C_AUTHN_LEVEL_NONE 1 // RPC_C_AUTHN_LEVEL_CONNECT 2 // RPC_C_AUTHN_LEVEL_CALL 3 // RPC_C_AUTHN_LEVEL_PKT 4 // RPC_C_AUTHN_LEVEL_PKT_INTEGRITY 5 // RPC_C_AUTHN_LEVEL_PKT_PRIVACY 6 COSERVERINFO * pcsiName = auth.CreateServerInfoStruct(RPC_C_AUTHN_LEVEL_DEFAULT); MULTI_QI res[1] = { {&IID_IMSAdminBase, NULL, 0} }; if (FAILED(hr = CoCreateInstanceEx(CLSID_MSAdminBase,NULL,CLSCTX_ALL,pcsiName,1,res))) { goto DoImportConfigFromFile_Exit; } pIMSAdminBase = (IMSAdminBase *)res[0].pItf; if (auth.UsesImpersonation()) { if (FAILED(hr = auth.ApplyProxyBlanket(pIMSAdminBase))) { goto DoImportConfigFromFile_Exit; } // There is a remote IUnknown interface that lurks behind IUnknown. // If that is not set, then the Release call can return access denied. IUnknown * pUnk = NULL; hr = pIMSAdminBase->QueryInterface(IID_IUnknown, (void **)&pUnk); if(FAILED(hr)) { return hr; } if (FAILED(hr = auth.ApplyProxyBlanket(pUnk))) { goto DoImportConfigFromFile_Exit; } pUnk->Release();pUnk = NULL; } if (FAILED(hr = pIMSAdminBase->QueryInterface(IID_IMSAdminBase2, (void **)&pIMSAdminBase2))) { goto DoImportConfigFromFile_Exit; } if (auth.UsesImpersonation()) { if (FAILED(hr = auth.ApplyProxyBlanket(pIMSAdminBase2))) { goto DoImportConfigFromFile_Exit; } } else { // the local call needs min RPC_C_IMP_LEVEL_IMPERSONATE // for the pIMSAdminBase2 objects Import/Export functions! if (FAILED(hr = SetBlanket(pIMSAdminBase2))) { //goto DoImportConfigFromFile_Exit; } } //#define MD_IMPORT_INHERITED 0x00000001 //#define MD_IMPORT_NODE_ONLY 0x00000002 //#define MD_IMPORT_MERGE 0x00000004 IISDebugOutput(_T("Import:MetabasePathSource=%s,MetabasePathDestination=%s\r\n"),bstrMetabaseSourcePath,bstrMetabaseDestinationPath); hr = pIMSAdminBase2->Import(bstrPassword,bstrFileNameAndPath,bstrMetabaseSourcePath,bstrMetabaseDestinationPath,dwImportFlags); DoImportConfigFromFile_Exit: IISDebugOutput(_T("Import:ret=0x%x\r\n"),hr); if (lpwstrTempPassword) { // security percaution:Make sure to zero out memory that temporary password was used for. SecureZeroMemory(lpwstrTempPassword,pConnectionInfo->cbUserPasswordEncrypted); LocalFree(lpwstrTempPassword); lpwstrTempPassword = NULL; } if (pIMSAdminBase2) { pIMSAdminBase2->Release(); pIMSAdminBase2 = NULL; } if (pIMSAdminBase) { pIMSAdminBase->Release(); pIMSAdminBase = NULL; } CoUninitialize(); return hr; } INT_PTR CALLBACK ShowSiteExistsDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: EnableWindow(GetDlgItem(hDlg, IDC_RADIO1), TRUE); EnableWindow(GetDlgItem(hDlg, IDC_RADIO2), TRUE); CheckDlgButton(hDlg,IDC_RADIO1,BST_CHECKED); CheckDlgButton(hDlg,IDC_RADIO2,BST_UNCHECKED); CenterWindow(GetParent(hDlg), hDlg); UpdateWindow(hDlg); break; case WM_CLOSE: EndDialog(hDlg, IDCANCEL); return FALSE; break; case WM_COMMAND: switch (wParam) { case IDCANCEL: EndDialog(hDlg, (int) wParam); return FALSE; case IDOK: if (BST_CHECKED == IsDlgButtonChecked(hDlg,IDC_RADIO1)) { EndDialog(hDlg, (int) IDC_RADIO1); } else if (BST_CHECKED == IsDlgButtonChecked(hDlg,IDC_RADIO2)) { EndDialog(hDlg, (int) IDC_RADIO2); } return TRUE; } break; } return FALSE; } INT_PTR CALLBACK ShowVDirExistsDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { static LPTSTR szReturnString = NULL; switch (msg) { case WM_INITDIALOG: szReturnString = (LPTSTR) lParam; EnableWindow(GetDlgItem(hDlg, IDC_RADIO1), TRUE); EnableWindow(GetDlgItem(hDlg, IDC_RADIO2), TRUE); CheckDlgButton(hDlg,IDC_RADIO1,BST_CHECKED); CheckDlgButton(hDlg,IDC_RADIO2,BST_UNCHECKED); SendDlgItemMessage(hDlg, IDC_EDIT_NEW_NAME, EM_LIMITTEXT, _MAX_PATH, 0); EnableWindow(GetDlgItem(hDlg,IDC_EDIT_NEW_NAME), TRUE); SetDlgItemText(hDlg, IDC_EDIT_NEW_NAME, _T("")); CenterWindow(GetParent(hDlg), hDlg); UpdateWindow(hDlg); break; case WM_CLOSE: EndDialog(hDlg, IDCANCEL); return FALSE; break; case WM_COMMAND: switch(LOWORD(wParam)) { case IDC_EDIT_NEW_NAME: { switch (HIWORD(wParam)) { case EN_CHANGE: EditHideBalloon(); // If the contents of the edit control have changed, if (BST_CHECKED == IsDlgButtonChecked(hDlg,IDC_RADIO1)) { EnableWindow(GetDlgItem(hDlg, IDOK),(SendMessage(GetDlgItem(hDlg,LOWORD(wParam)),EM_LINELENGTH,(WPARAM) -1, 0) != 0)); } break; case EN_MAXTEXT: case EN_ERRSPACE: // If the control is out of space, honk MessageBeep (0); break; default: break; } return TRUE; } case IDC_RADIO1: EnableWindow(GetDlgItem(hDlg, IDC_EDIT_NEW_NAME), TRUE); EnableWindow(GetDlgItem(hDlg, IDOK),(SendMessage(GetDlgItem(hDlg,IDC_EDIT_NEW_NAME),EM_LINELENGTH,(WPARAM) -1, 0) != 0)); SetFocus(GetDlgItem(hDlg, IDC_EDIT_NEW_NAME)); return TRUE; case IDC_RADIO2: EnableWindow(GetDlgItem(hDlg, IDC_EDIT_NEW_NAME), FALSE); EnableWindow(GetDlgItem(hDlg, IDOK),TRUE); return TRUE; case IDCANCEL: EndDialog(hDlg, (int) wParam); return FALSE; case IDOK: TCHAR szEditString[_MAX_PATH + 1]; ZeroMemory(szEditString, sizeof(szEditString)); GetDlgItemText(hDlg, IDC_EDIT_NEW_NAME, szEditString, _MAX_PATH); // sizeof szReturnString = _MAX_PATH + 1 StringCbCopy(szReturnString,_MAX_PATH + 1, szEditString); if (BST_CHECKED == IsDlgButtonChecked(hDlg,IDC_RADIO1)) { EndDialog(hDlg, (int) IDC_RADIO1); } else if (BST_CHECKED == IsDlgButtonChecked(hDlg,IDC_RADIO2)) { EndDialog(hDlg, (int) IDC_RADIO2); } return TRUE; } break; } return FALSE; } INT_PTR CALLBACK ShowAppPoolExistsDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { static LPTSTR szReturnString = NULL; switch (msg) { case WM_INITDIALOG: szReturnString = (LPTSTR) lParam; EnableWindow(GetDlgItem(hDlg, IDC_RADIO1), TRUE); EnableWindow(GetDlgItem(hDlg, IDC_RADIO2), TRUE); CheckDlgButton(hDlg,IDC_RADIO1,BST_CHECKED); CheckDlgButton(hDlg,IDC_RADIO2,BST_UNCHECKED); SendDlgItemMessage(hDlg, IDC_EDIT_NEW_NAME, EM_LIMITTEXT, _MAX_PATH, 0); EnableWindow(GetDlgItem(hDlg,IDC_EDIT_NEW_NAME), TRUE); SetDlgItemText(hDlg, IDC_EDIT_NEW_NAME, _T("")); CenterWindow(GetParent(hDlg), hDlg); UpdateWindow(hDlg); break; case WM_CLOSE: EndDialog(hDlg, IDCANCEL); return FALSE; break; case WM_COMMAND: switch(LOWORD(wParam)) { case IDC_EDIT_NEW_NAME: { switch (HIWORD(wParam)) { case EN_CHANGE: EditHideBalloon(); // If the contents of the edit control have changed, if (BST_CHECKED == IsDlgButtonChecked(hDlg,IDC_RADIO1)) { EnableWindow(GetDlgItem(hDlg, IDOK),(SendMessage(GetDlgItem(hDlg,LOWORD(wParam)),EM_LINELENGTH,(WPARAM) -1, 0) != 0)); } break; case EN_MAXTEXT: case EN_ERRSPACE: // If the control is out of space, honk MessageBeep (0); break; default: break; } return TRUE; } case IDC_RADIO1: EnableWindow(GetDlgItem(hDlg, IDC_EDIT_NEW_NAME), TRUE); EnableWindow(GetDlgItem(hDlg, IDOK),(SendMessage(GetDlgItem(hDlg,IDC_EDIT_NEW_NAME),EM_LINELENGTH,(WPARAM) -1, 0) != 0)); SetFocus(GetDlgItem(hDlg, IDC_EDIT_NEW_NAME)); return TRUE; case IDC_RADIO2: EnableWindow(GetDlgItem(hDlg, IDC_EDIT_NEW_NAME), FALSE); EnableWindow(GetDlgItem(hDlg, IDOK),TRUE); return TRUE; case IDCANCEL: EndDialog(hDlg, (int) wParam); return FALSE; case IDOK: TCHAR szEditString[_MAX_PATH + 1]; ZeroMemory(szEditString, sizeof(szEditString)); if (BST_CHECKED == IsDlgButtonChecked(hDlg,IDC_RADIO1)) { GetDlgItemText(hDlg, IDC_EDIT_NEW_NAME, szEditString, _MAX_PATH); // check for invalid entry TCHAR bad_chars[] = _T("\\/"); if (_tcslen(szEditString) != _tcscspn(szEditString, bad_chars)) { CString strCaption; CString strMsg; strCaption.LoadString(_Module.GetResourceInstance(), IDS_MSGBOX_CAPTION); strMsg.LoadString(_Module.GetResourceInstance(), IDS_INVALID_ENTRY); MessageBox(hDlg,strMsg,strCaption,MB_ICONEXCLAMATION | MB_OK); *szReturnString = 0; } else { // sizeof szReturnString = _MAX_PATH + 1 StringCbCopy(szReturnString,_MAX_PATH + 1, szEditString); EndDialog(hDlg, (int) IDC_RADIO1); } } else if (BST_CHECKED == IsDlgButtonChecked(hDlg,IDC_RADIO2)) { *szReturnString = 0; EndDialog(hDlg, (int) IDC_RADIO2); } } break; } return FALSE; } INT_PTR CALLBACK ShowPasswordDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { static LPTSTR szReturnString = NULL; switch (msg) { case WM_INITDIALOG: szReturnString = (LPTSTR) lParam; SendDlgItemMessage(hDlg, IDC_EDIT_GET_PASSWORD, EM_LIMITTEXT, PWLEN, 0); SendDlgItemMessage(hDlg, IDC_EDIT_GET_PASSWORD, EM_SETPASSWORDCHAR, WPARAM('*'), 0); EnableWindow(GetDlgItem(hDlg,IDC_EDIT_GET_PASSWORD), TRUE); SetDlgItemText(hDlg, IDC_EDIT_GET_PASSWORD, _T("")); UpdateWindow(hDlg); break; case WM_CLOSE: EndDialog(hDlg, IDCANCEL); return FALSE; break; case WM_COMMAND: switch (wParam) { case IDCANCEL: EndDialog(hDlg,(int)wParam); return FALSE; case IDOK: { TCHAR szPassword[PWLEN + 1]; SecureZeroMemory(szPassword, sizeof(szPassword)); GetDlgItemText(hDlg, IDC_EDIT_GET_PASSWORD, szPassword, PWLEN); // sizeof szReturnString = _MAX_PATH + 1 StringCbCopy(szReturnString,_MAX_PATH + 1, szPassword); // security percaution:Make sure to zero out memory that temporary password was used for. SecureZeroMemory(szPassword, sizeof(szPassword)); EndDialog(hDlg,(int)wParam); return TRUE; } } break; } return FALSE; } HRESULT FillListBoxWithMultiSzData(HWND hList,LPCTSTR szKeyType,WCHAR * pszBuffer) { HRESULT hr = E_FAIL; WCHAR szBuffer[_MAX_PATH + 1]; WCHAR * pszBufferTemp1 = NULL; WCHAR * pszBufferTemp2 = NULL; LVITEM ItemIndex; LV_COLUMN lvcol; INT iIndex = 0; DWORD dwCount = 0; BOOL bMultiSzIsPaired = FALSE; BOOL bPleaseAddItem = TRUE; BOOL bPleaseFilterThisSitesList = FALSE; if (0 == _tcscmp(szKeyType,IIS_CLASS_WEB_SERVER_W) || 0 == _tcscmp(szKeyType,IIS_CLASS_FTP_SERVER_W) ) { bPleaseFilterThisSitesList = TRUE; } pszBufferTemp1 = pszBuffer; // forget this, it's always paired. //bMultiSzIsPaired = IsMultiSzPaired(pszBufferTemp1); bMultiSzIsPaired = TRUE; // Erase existing data in list box... ListView_DeleteAllItems(hList); // Delete all of the columns. for (int i=0;i <= ListView_GetItemCount(hList);i++) {ListView_DeleteColumn(hList,i);} // // Decide on the column widths // RECT rect; GetClientRect(hList, &rect); LONG lWidth; if (dwCount > (DWORD)ListView_GetCountPerPage(hList)) { lWidth = (rect.right - rect.left) - GetSystemMetrics(SM_CYHSCROLL); } else { lWidth = rect.right - rect.left; } // // Insert the component name column // memset(&lvcol, 0, sizeof(lvcol)); // zero memory ZeroMemory(szBuffer, sizeof(szBuffer)); lvcol.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH; lvcol.fmt = LVCFMT_LEFT; lvcol.pszText = szBuffer; lvcol.cx = lWidth; LoadString(_Module.m_hInst, IDS_COL_LOCATION, szBuffer, ARRAYSIZE(szBuffer)); ListView_InsertColumn(hList, 0, &lvcol); SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE,(WPARAM) 0, LVS_EX_FULLROWSELECT | LVS_EX_LABELTIP); if (!pszBufferTemp1) { return ERROR_SUCCESS; } while (1) { if (pszBufferTemp1) { hr = ERROR_SUCCESS; ZeroMemory (&ItemIndex, sizeof(ItemIndex)); if (bMultiSzIsPaired) { bPleaseAddItem = TRUE; // ----------- // paired list // value1a value1b // value2a value2b // ... // ----------- // make a copy of this baby pszBufferTemp2 = pszBufferTemp1; // then increment until we hit another null. // to get value #2 -- which is the description while (*pszBufferTemp1) { pszBufferTemp1++; } // check for the ending \0\0 if ( *(pszBufferTemp1+1) == NULL) { break; } else { pszBufferTemp1++; } // Check if pszBufferTemp1 is an empty string // if it is then display something else. //IISDebugOutput(_T("key=%s,friendly=%s\r\n"),pszBufferTemp2,pszBufferTemp1); if (IsSpaces(pszBufferTemp1)) { ItemIndex.pszText = pszBufferTemp2; ItemIndex.pszText = GimmiePointerToLastPart(pszBufferTemp2); } else { ItemIndex.pszText = pszBufferTemp1; } if (bPleaseFilterThisSitesList) { // Check if it is a true site node -- like // /LM/W3SVC/1 // /LM/MSFTPSVC/1 // and not /LM/W3SVC/SOMETHINGELSE // DWORD dwInstanceNum = CMetabasePath::GetInstanceNumber(pszBufferTemp2); if (dwInstanceNum == 0 || dwInstanceNum == 0xffffffff) { // this is not a valid site path bPleaseAddItem = FALSE; } } if (bPleaseAddItem) { ItemIndex.mask = LVIF_TEXT | LVIF_PARAM; ItemIndex.iItem = iIndex; ItemIndex.lParam = (LPARAM) pszBufferTemp2; iIndex = ListView_InsertItem (hList, &ItemIndex); } // then increment until we hit another null. // to get value #2 while (*pszBufferTemp1) { pszBufferTemp1++; } // check for the ending \0\0 if ( *(pszBufferTemp1+1) == NULL) { break; } else { pszBufferTemp1++; } } else { // ----------- // single list // value1a // value2a // ... // ----------- ItemIndex.mask = LVIF_TEXT | LVIF_PARAM; ItemIndex.iItem = iIndex; ItemIndex.pszText = pszBufferTemp1; ItemIndex.lParam = (LPARAM) pszBufferTemp1; iIndex = ListView_InsertItem (hList, &ItemIndex); // then increment until we hit another null. // to get value #2 while (*pszBufferTemp1) { pszBufferTemp1++; } } // check for the ending \0\0 if ( *(pszBufferTemp1+1) == NULL) { break; } else { pszBufferTemp1++; } iIndex++; } } return hr; } HRESULT DoEnumDataFromFile(PCONNECTION_INFO pConnectionInfo,BSTR bstrFileNameAndPath,BSTR bstrPathType,WCHAR ** pszMetabaseMultiszList) { HRESULT hr = E_FAIL; IMSAdminBase *pIMSAdminBase = NULL; IMSImpExpHelp * pIMSImpExpHelp = NULL; WCHAR * pszBuffer = NULL; DWORD dwBufferSize = 1; LPWSTR lpwstrTempPassword = NULL; if (!pConnectionInfo) { return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER); } if (pConnectionInfo->pszUserPasswordEncrypted) { if (FAILED(DecryptMemoryPassword((LPWSTR) pConnectionInfo->pszUserPasswordEncrypted,&lpwstrTempPassword,pConnectionInfo->cbUserPasswordEncrypted))) { return HRESULT_FROM_WIN32(ERROR_DECRYPTION_FAILED); } } CComAuthInfo auth(pConnectionInfo->pszMachineName,pConnectionInfo->pszUserName,lpwstrTempPassword); if (!bstrFileNameAndPath) { return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER); } if (!bstrPathType) { return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER); } // Buffer overflow paranoia, make sure it's less than 255 characters long if (wcslen(bstrFileNameAndPath) > (_MAX_PATH)){return RPC_S_STRING_TOO_LONG;} if (wcslen(bstrPathType) > (_MAX_PATH)){return RPC_S_STRING_TOO_LONG;} if(FAILED(hr = CoInitializeEx(NULL, COINIT_MULTITHREADED))) { if(FAILED(hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED))) { return hr; } } // RPC_C_AUTHN_LEVEL_DEFAULT 0 // RPC_C_AUTHN_LEVEL_NONE 1 // RPC_C_AUTHN_LEVEL_CONNECT 2 // RPC_C_AUTHN_LEVEL_CALL 3 // RPC_C_AUTHN_LEVEL_PKT 4 // RPC_C_AUTHN_LEVEL_PKT_INTEGRITY 5 // RPC_C_AUTHN_LEVEL_PKT_PRIVACY 6 COSERVERINFO * pcsiName = auth.CreateServerInfoStruct(RPC_C_AUTHN_LEVEL_DEFAULT); MULTI_QI res[1] = { {&IID_IMSAdminBase, NULL, 0} }; if (FAILED(hr = CoCreateInstanceEx(CLSID_MSAdminBase,NULL,CLSCTX_ALL,pcsiName,1,res))) { goto DoEnumDataFromFile_Exit; } pIMSAdminBase = (IMSAdminBase *)res[0].pItf; if (auth.UsesImpersonation()) { if (FAILED(hr = auth.ApplyProxyBlanket(pIMSAdminBase))) { goto DoEnumDataFromFile_Exit; } // There is a remote IUnknown interface that lurks behind IUnknown. // If that is not set, then the Release call can return access denied. IUnknown * pUnk = NULL; hr = pIMSAdminBase->QueryInterface(IID_IUnknown, (void **)&pUnk); if(FAILED(hr)) { return hr; } if (FAILED(hr = auth.ApplyProxyBlanket(pUnk))) { goto DoEnumDataFromFile_Exit; } pUnk->Release();pUnk = NULL; } if (FAILED(hr = pIMSAdminBase->QueryInterface(IID_IMSImpExpHelp, (void **)&pIMSImpExpHelp))) { goto DoEnumDataFromFile_Exit; } if (auth.UsesImpersonation()) { if (FAILED(hr = auth.ApplyProxyBlanket(pIMSImpExpHelp))) { goto DoEnumDataFromFile_Exit; } } else { // the local call needs min RPC_C_IMP_LEVEL_IMPERSONATE // for the pIMSAdminBase2 objects Import/Export functions! if (FAILED(hr = SetBlanket(pIMSImpExpHelp))) { //goto DoEnumDataFromFile_Exit; } } IISDebugOutput(_T("EnumeratePathsInFile:FileName=%s,PathType=%s\r\n"),bstrFileNameAndPath,bstrPathType); if (FAILED(hr = pIMSImpExpHelp->EnumeratePathsInFile(bstrFileNameAndPath, bstrPathType, dwBufferSize, pszBuffer, &dwBufferSize))) { goto DoEnumDataFromFile_Exit; } pszBuffer = (WCHAR *) ::CoTaskMemAlloc(dwBufferSize * sizeof(WCHAR)); if (NULL == pszBuffer) { hr = E_OUTOFMEMORY; goto DoEnumDataFromFile_Exit; } if (FAILED(hr = pIMSImpExpHelp->EnumeratePathsInFile(bstrFileNameAndPath, bstrPathType, dwBufferSize, pszBuffer, &dwBufferSize))) { // free existing amount of space we asked for if (pszBuffer) { ::CoTaskMemFree(pszBuffer); pszBuffer = NULL; } goto DoEnumDataFromFile_Exit; } if (!pszBuffer || dwBufferSize <= 0) { goto DoEnumDataFromFile_Exit; } // see if returned an empty list... if (0 == _tcscmp(pszBuffer,_T(""))) { goto DoEnumDataFromFile_Exit; } *pszMetabaseMultiszList = pszBuffer; DoEnumDataFromFile_Exit: IISDebugOutput(_T("EnumeratePathsInFile:ret=0x%x\r\n"),hr); if (lpwstrTempPassword) { // security percaution:Make sure to zero out memory that temporary password was used for. SecureZeroMemory(lpwstrTempPassword,pConnectionInfo->cbUserPasswordEncrypted); LocalFree(lpwstrTempPassword); lpwstrTempPassword = NULL; } if (pIMSImpExpHelp) { pIMSImpExpHelp->Release(); pIMSImpExpHelp = NULL; } if (pIMSAdminBase) { pIMSAdminBase->Release(); pIMSAdminBase = NULL; } CoUninitialize(); return hr; } void ImportDlgEnableButtons(HWND hDlg,PCOMMONDLGPARAM pcdParams,LPCTSTR lpszCurrentEnumedFileName) { BOOL fEnableListControl = FALSE; BOOL fEnableOK = FALSE; BOOL fEnableBrowse = FALSE; BOOL fEnableEnum = FALSE; TCHAR szFullFileName[_MAX_PATH + 1]; ZeroMemory(szFullFileName, sizeof(szFullFileName)); GetDlgItemText(hDlg, IDC_EDIT_FILE, szFullFileName, _MAX_PATH); HWND hList = GetDlgItem(hDlg, IDC_LIST_OBJECT); int ItemIndex = ListView_GetNextItem(hList, -1, LVNI_ALL); if (ItemIndex < 0) { // no items in listview,disable what we need to fEnableListControl = FALSE; fEnableOK = FALSE; } else { fEnableListControl = TRUE; // Check if something is selected ItemIndex = ListView_GetNextItem(hList, -1, LVNI_SELECTED); if (ItemIndex < 0) { fEnableOK = FALSE; } else { fEnableOK = TRUE; } } // Check if we should enable the listcontrol at all... // see if the filename is the same if (0 != _tcsicmp(_T(""),lpszCurrentEnumedFileName)) { // check for % characters // if there are any, expand them. LPTSTR pch = _tcschr( (LPTSTR) szFullFileName, _T('%')); if (pch && pcdParams->ConnectionInfo.IsLocal) { TCHAR szValue[_MAX_PATH + 1]; TCHAR szValue2[_MAX_PATH + 1]; StringCbCopy(szValue, sizeof(szValue), szFullFileName); StringCbCopy(szValue2, sizeof(szValue2), lpszCurrentEnumedFileName); if (!ExpandEnvironmentStrings( (LPCTSTR)szFullFileName, szValue, sizeof(szValue)/sizeof(TCHAR))) {StringCbCopy(szValue, sizeof(szValue), szFullFileName);} if (!ExpandEnvironmentStrings( (LPCTSTR)lpszCurrentEnumedFileName, szValue2, sizeof(szValue2)/sizeof(TCHAR))) {StringCbCopy(szValue2, sizeof(szValue2), lpszCurrentEnumedFileName);} if (0 != _tcsicmp(szValue,szValue2)) { // it's not the same file // so let's erase and disable the info in the list box. fEnableListControl = FALSE; } } else { if (0 != _tcsicmp(szFullFileName,lpszCurrentEnumedFileName)) { // it's not the same file // so let's erase and disable the info in the list box. fEnableListControl = FALSE; } } } EnableWindow(hList, fEnableListControl); if (FALSE == IsWindowEnabled(hList)) { fEnableOK = FALSE; } // Set focus on listbox //if (fEnableListControl){SetFocus(GetDlgItem(hDlg, IDC_LIST_OBJECT));} fEnableEnum = (SendMessage(GetDlgItem(hDlg,IDC_EDIT_FILE),EM_LINELENGTH,(WPARAM) -1, 0) != 0); // no browse button for remote case if (pcdParams) { if (pcdParams->ConnectionInfo.IsLocal) {fEnableBrowse = TRUE;} } // enable enum button EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_ENUM_FILE),fEnableEnum); // enable browse button EnableWindow(GetDlgItem(hDlg,IDC_BUTTON_BROWSE), fEnableBrowse); // enable OK button EnableWindow(GetDlgItem(hDlg, IDOK), fEnableOK); UpdateWindow(hDlg); } INT_PTR CALLBACK ShowImportDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { static PCOMMONDLGPARAM pcdParams; static TCHAR * pszMetabaseMultiszList = NULL; static CString strCurrentFileNameEnum; switch (msg) { case WM_INITDIALOG: pcdParams = (PCOMMONDLGPARAM)lParam; pszMetabaseMultiszList = NULL; TCHAR szFullFileName1[_MAX_PATH + 1]; ZeroMemory(szFullFileName1, sizeof(szFullFileName1)); if (DefaultValueSettingsLoad(pcdParams->ConnectionInfo.pszMachineName,LAST_USED_IMPORT_FILE,szFullFileName1)) { if (0 != _tcscmp(szFullFileName1, _T(""))) { SetDlgItemText(hDlg, IDC_EDIT_FILE, szFullFileName1); } } strCurrentFileNameEnum = _T(""); InitListView(GetDlgItem(hDlg, IDC_LIST_OBJECT)); CenterWindow(GetParent(hDlg), hDlg); SetFocus(GetDlgItem(hDlg, IDC_EDIT_FILE)); ImportDlgEnableButtons(hDlg,pcdParams,strCurrentFileNameEnum); EnableWindow(GetDlgItem(hDlg, IDC_LIST_OBJECT), FALSE); break; /* case WM_ACTIVATE: if (wParam == 0) { } break; */ case WM_NOTIFY: { if((int)((LPNMHDR)lParam)->idFrom == IDC_LIST_OBJECT) { switch (((LPNMHDR)lParam)->code) { case LVN_ITEMCHANGED: ImportDlgEnableButtons(hDlg,pcdParams,strCurrentFileNameEnum); break; case NM_CLICK: ImportDlgEnableButtons(hDlg,pcdParams,strCurrentFileNameEnum); break; case NM_DBLCLK: if((int)((LPNMHDR)lParam)->idFrom == IDC_LIST_OBJECT) { PostMessage(hDlg,WM_COMMAND,IDOK,NULL); } break; default: break; } } return FALSE; break; } case WM_CLOSE: ListView_DeleteAllItems(GetDlgItem(hDlg, IDC_LIST_OBJECT)); EndDialog(hDlg, IDCANCEL); return FALSE; break; case WM_HELP: LaunchHelp(hDlg,HIDD_IISUIOBJ_IMPORT); return TRUE; break; case WM_COMMAND: switch(LOWORD(wParam)) { case IDC_EDIT_FILE: { switch (HIWORD(wParam)) { case EN_CHANGE: EditHideBalloon(); { // If the contents of the edit control have changed, // check if it's the same as the file that is currently enumed... HWND hList = GetDlgItem(hDlg, IDC_LIST_OBJECT); if (ListView_GetItemCount(hList) > 0) { TCHAR szFullFileName3[_MAX_PATH + 1]; ZeroMemory(szFullFileName3, sizeof(szFullFileName3)); GetDlgItemText(hDlg, IDC_EDIT_FILE, szFullFileName3, _MAX_PATH); // see if the filename is the same as this one! if (!strCurrentFileNameEnum.IsEmpty()) { if (0 != _tcsicmp(szFullFileName3,strCurrentFileNameEnum)) { // it's not the same file // so let's erase and disable the info in the list box. EnableWindow(hList, FALSE); } } } ImportDlgEnableButtons(hDlg,pcdParams,strCurrentFileNameEnum); break; } case EN_MAXTEXT: case EN_ERRSPACE: // If the control is out of space, honk MessageBeep (0); break; default: break; } return TRUE; break; } case IDC_BUTTON_BROWSE: { TCHAR szOldFilePath[_MAX_PATH + 1]; GetDlgItemText(hDlg, IDC_EDIT_FILE, szOldFilePath, _MAX_PATH); TCHAR szNewFilePath[_MAX_PATH + 1]; ZeroMemory(szNewFilePath, sizeof(szNewFilePath)); if (BrowseForFile(szOldFilePath,szNewFilePath,sizeof(szNewFilePath))) { if (0 != _tcsicmp(szNewFilePath, _T(""))) { SetDlgItemText(hDlg, IDC_EDIT_FILE, szNewFilePath); UpdateWindow(hDlg); } } ImportDlgEnableButtons(hDlg,pcdParams,strCurrentFileNameEnum); return FALSE; break; } case IDC_BUTTON_ENUM_FILE: { BOOL bThingsAreKool = TRUE; TCHAR szFullFileName2[_MAX_PATH + 1]; ZeroMemory(szFullFileName2, sizeof(szFullFileName2)); GetDlgItemText(hDlg, IDC_EDIT_FILE, szFullFileName2, _MAX_PATH); // check for % characters // if there are any, expand them. LPTSTR pch = _tcschr( (LPTSTR) szFullFileName2, _T('%')); if (pch) { if (pcdParams->ConnectionInfo.IsLocal) { TCHAR szValue[_MAX_PATH + 1]; StringCbCopy(szValue, sizeof(szValue), szFullFileName2); if (!ExpandEnvironmentStrings( (LPCTSTR)szFullFileName2, szValue, sizeof(szValue)/sizeof(TCHAR))) { StringCbCopy(szValue, sizeof(szValue), szFullFileName2); } StringCbCopy(szFullFileName2, sizeof(szFullFileName2), szValue); bThingsAreKool = TRUE; } else { // we don't support % characters on remote systems. EditShowBalloon(GetDlgItem(hDlg, IDC_EDIT_FILE),_Module.GetResourceInstance(),IDS_FILENAME_NOREMOTE_EXPAND); bThingsAreKool = FALSE; } } if (bThingsAreKool) { if (pcdParams->ConnectionInfo.IsLocal) { if (!IsFileExist(szFullFileName2)) { bThingsAreKool = FALSE; EditShowBalloon(GetDlgItem(hDlg, IDC_EDIT_FILE),_Module.GetResourceInstance(),IDS_FILE_NOT_FOUND); } } } if (bThingsAreKool) { TCHAR szNodeType[50]; ZeroMemory(szNodeType, sizeof(szNodeType)); if (pcdParams->pszKeyType) { HRESULT hr = ERROR_SUCCESS; StringCbCopy(szNodeType, sizeof(szNodeType), pcdParams->pszKeyType); if (0 != _tcsicmp(szNodeType,_T(""))) { HWND hList = GetDlgItem(hDlg, IDC_LIST_OBJECT); // Erase existing data in list box... ListView_DeleteAllItems(hList); // free up the preiously used pointer if we already have memory freed if (pszMetabaseMultiszList) { ::CoTaskMemFree(pszMetabaseMultiszList); pszMetabaseMultiszList = NULL; } if (SUCCEEDED(hr = DoEnumDataFromFile(&pcdParams->ConnectionInfo,szFullFileName2,szNodeType,&pszMetabaseMultiszList))) { strCurrentFileNameEnum = szFullFileName2; if (pszMetabaseMultiszList) { // filter out stuff we don't want the user to see... hr = FillListBoxWithMultiSzData(hList,szNodeType,pszMetabaseMultiszList); //DumpStrInMultiStr(pszMetabaseMultiszList); if (SUCCEEDED(hr)) { if (0 != _tcscmp(szFullFileName2, _T(""))) { DefaultValueSettingsSave(pcdParams->ConnectionInfo.pszMachineName,LAST_USED_IMPORT_FILE,szFullFileName2); } } } else { // check if there was anything returned... // if there was then we got something back // which doesn't have the objects we asked for CString strMsg; CString strFormat; CString strObjectType; BOOL bFound = FALSE; //IIS_CLASS_WEB_SERVER_W //IIS_CLASS_FTP_SERVER_W //IIS_CLASS_WEB_VDIR_W //IIS_CLASS_FTP_VDIR_W //IIsApplicationPool if (0 == _tcscmp(szNodeType,IIS_CLASS_WEB_SERVER_W)) { strObjectType = IIS_CLASS_WEB_SERVER_W; strObjectType.LoadString(_Module.GetResourceInstance(), IDS_STRING_WEB_SERVER); bFound = TRUE; } else if (0 == _tcscmp(szNodeType,IIS_CLASS_FTP_SERVER_W)) { strObjectType = IIS_CLASS_FTP_SERVER_W; strObjectType.LoadString(_Module.GetResourceInstance(), IDS_STRING_FTP_SERVER); bFound = TRUE; } else if (0 == _tcscmp(szNodeType,IIS_CLASS_WEB_VDIR_W)) { strObjectType = IIS_CLASS_WEB_VDIR_W; strObjectType.LoadString(_Module.GetResourceInstance(), IDS_STRING_WEB_VDIR); bFound = TRUE; } else if (0 == _tcscmp(szNodeType,IIS_CLASS_FTP_VDIR_W)) { strObjectType = IIS_CLASS_FTP_VDIR_W; strObjectType.LoadString(_Module.GetResourceInstance(), IDS_STRING_FTP_VDIR); bFound = TRUE; } else if (0 == _tcscmp(szNodeType,_T("IIsApplicationPool"))) { strObjectType = _T("IIsApplicationPool"); strObjectType.LoadString(_Module.GetResourceInstance(), IDS_STRING_APP_POOL); bFound = TRUE; } if (bFound) { strFormat.LoadString(_Module.GetResourceInstance(), IDS_IMPORT_MISMATCH); strMsg.FormatMessage((LPCTSTR) strFormat,(LPCTSTR) strObjectType,(LPCTSTR) strObjectType,(LPCTSTR) strObjectType); EditShowBalloon(GetDlgItem(hDlg, IDC_EDIT_FILE),(LPCTSTR) strMsg); } } } else { if (HRESULTTOWIN32(hr) == ERROR_FILE_NOT_FOUND) { EditShowBalloon( GetDlgItem(hDlg, IDC_EDIT_FILE), _Module.GetResourceInstance(),IDS_FILE_NOT_FOUND); } } } } } ImportDlgEnableButtons(hDlg,pcdParams,strCurrentFileNameEnum); return FALSE; break; } case IDC_LIST_OBJECT: { ImportDlgEnableButtons(hDlg,pcdParams,strCurrentFileNameEnum); return FALSE; break; } case IDHELP: LaunchHelp(hDlg,HIDD_IISUIOBJ_IMPORT); return TRUE; case IDCANCEL: { ListView_DeleteAllItems(GetDlgItem(hDlg, IDC_LIST_OBJECT)); // free up memory we may have allocated... if (pszMetabaseMultiszList) { ::CoTaskMemFree(pszMetabaseMultiszList); pszMetabaseMultiszList = NULL; } EndDialog(hDlg,(int)wParam); return FALSE; break; } case IDOK: if (TRUE == OnImportOK(hDlg,&pcdParams->ConnectionInfo,pcdParams->pszKeyType,pcdParams->pszMetabasePath,pcdParams->dwImportFlags)) { TCHAR szFullFileName3[_MAX_PATH + 1]; ZeroMemory(szFullFileName3, sizeof(szFullFileName3)); GetDlgItemText(hDlg, IDC_EDIT_FILE, szFullFileName3, _MAX_PATH); ListView_DeleteAllItems(GetDlgItem(hDlg, IDC_LIST_OBJECT)); // free up memory we may have allocated... if (pszMetabaseMultiszList) { ::CoTaskMemFree(pszMetabaseMultiszList); pszMetabaseMultiszList = NULL; } return TRUE; } else { return FALSE; } break; } break; } return FALSE; } BOOL OnImportOK(HWND hDlg,PCONNECTION_INFO pConnectionInfo,LPCTSTR szKeyType,LPCTSTR szCurrentMetabasePath,DWORD dwImportFlags) { BOOL bPleaseProceed = FALSE; HRESULT hr = ERROR_SUCCESS; INT iReturnedFlag = 0; TCHAR szFullFileName[_MAX_PATH + 1]; TCHAR szNewPassword[PWLEN + 1]; LPTSTR pszSourcePath = NULL; LPTSTR pszDestinationPathMungeAble = NULL; DWORD dwDestinationPathMungeAble = 0; LPTSTR pszSaveSafeCopy = NULL; int ItemIndex = 0; LVITEM lviGet; memset(&lviGet, 0, sizeof(lviGet)); // Get the filepath which this tree was created from. // could have changed since user edited edit box... // so get the one that the tree was created from... GetDlgItemText(hDlg, IDC_EDIT_FILE, szFullFileName, _MAX_PATH); SecureZeroMemory(szNewPassword, sizeof(szNewPassword)); if (ListView_GetSelectedCount(GetDlgItem(hDlg, IDC_LIST_OBJECT)) <= 0) { goto OnImportOK_Exit; } // Get the metabase path the user selected.. ItemIndex = ListView_GetNextItem(GetDlgItem(hDlg, IDC_LIST_OBJECT), -1, LVNI_SELECTED); if (-1 == ItemIndex) { goto OnImportOK_Exit; } ZeroMemory(&lviGet, sizeof(LVITEM)); lviGet.iItem = ItemIndex; lviGet.iSubItem = 0; lviGet.mask = LVIF_PARAM; lviGet.lParam = NULL; if (FALSE == ListView_GetItem(GetDlgItem(hDlg, IDC_LIST_OBJECT), &lviGet)) { goto OnImportOK_Exit; } if (lviGet.lParam) { // figure out how big of a buffer do we need... int iLen = _tcslen((LPTSTR) lviGet.lParam) + 1; pszSourcePath = (LPTSTR) LocalAlloc(LPTR, iLen * sizeof(TCHAR)); if (!pszSourcePath) { goto OnImportOK_Exit; } StringCbCopy(pszSourcePath,(iLen * sizeof(TCHAR)), (WCHAR *) lviGet.lParam); dwDestinationPathMungeAble = iLen * sizeof(TCHAR); pszDestinationPathMungeAble = (LPTSTR) LocalAlloc(LPTR, dwDestinationPathMungeAble); if (!pszDestinationPathMungeAble) { goto OnImportOK_Exit; } // make the destination path the same as what we got from the file! StringCbCopy(pszDestinationPathMungeAble,dwDestinationPathMungeAble,pszSourcePath); } // Clean the metabase to work with Import... // we have something like this in the list // LM/W3SVC/1/ROOT/MyDir // ----------------------------------- // Check to see if the destination path already exists!!!! // if it already does, then popup a msg box to get another from the user! // ----------------------------------- do { iReturnedFlag = 0; IISDebugOutput(_T("CleanDestinationPathForVdirs:before:KeyType=%s,CurPath=%s,MetabasePathDestination=%s\r\n"),szKeyType,szCurrentMetabasePath,pszDestinationPathMungeAble); if (FAILED(hr = CleanDestinationPathForVdirs(szKeyType,szCurrentMetabasePath,&pszDestinationPathMungeAble,&dwDestinationPathMungeAble))) { // something failed, let's just stay on this dialog bPleaseProceed = FALSE; goto OnImportOK_Exit; } IISDebugOutput(_T("CleanDestinationPathForVdirs:after :KeyType=%s,CurPath=%s,MetabasePathDestination=%s\r\n"),szKeyType,szCurrentMetabasePath,pszDestinationPathMungeAble); // allocate the new space int cbSafeCopy = (_tcslen(pszDestinationPathMungeAble)+ 1) * sizeof(TCHAR); if (pszSaveSafeCopy) {LocalFree(pszSaveSafeCopy);pszSaveSafeCopy=NULL;} pszSaveSafeCopy = (LPTSTR) LocalAlloc(LPTR, cbSafeCopy); if (!pszSaveSafeCopy) { bPleaseProceed = FALSE; goto OnImportOK_Exit; } // copy the data to the new buffer StringCbCopy(pszSaveSafeCopy,cbSafeCopy,pszDestinationPathMungeAble); if (FALSE == GetNewDestinationPathIfEntryExists(hDlg,pConnectionInfo,szKeyType,&pszDestinationPathMungeAble,&dwDestinationPathMungeAble,&iReturnedFlag)) { // cancelled, so let's just stay on this dialog bPleaseProceed = FALSE; goto OnImportOK_Exit; } else { if (1 == iReturnedFlag) { // The destination path already exists and we should overwrite // we should overwrite // Get the original destination path // since it could already have been munged... StringCbCopy(pszDestinationPathMungeAble,dwDestinationPathMungeAble,pszSaveSafeCopy); break; } else if (2 == iReturnedFlag) { // the path didn't already exists so we can write it out now... break; } else { // we got a new pszDestinationPathMungeAble // go thru the loop again. } } } while (TRUE); // if we get down here // it's because we have a pszDestinationPathMungeAble that we // can write to or overwrite... // we will never get here is the user cancelled... do { // Perform the action... // if it fails then ask for a password... if (FAILED(hr = DoImportConfigFromFile(pConnectionInfo,szFullFileName,pszSourcePath,pszDestinationPathMungeAble,szNewPassword,dwImportFlags))) { // Check if it failed because the site/vdir/app pool already exists... // if that's the error, then ask the user for a new path... // If it failed because of bad password, then say so if (0x8007052B == hr) { // See if the user wants to try again. // if they do, then try it with the new password... if (IDCANCEL == DialogBoxParam((HINSTANCE) _Module.m_hInst, MAKEINTRESOURCE(IDD_DIALOG_GET_PASSWORD), hDlg, ShowPasswordDlgProc, (LPARAM) szNewPassword)) { // the user cancelled... // so we should just stay on this page... // cancelled, so let's just stay on this dialog bPleaseProceed = FALSE; break; } else { // try it again with the new password... } } else if (HRESULTTOWIN32(hr) == ERROR_NO_MATCH) { bPleaseProceed = FALSE; break; } else { // if it failed or some reason // then get out of loop // hr holds the error CError err(hr); err.MessageBox(); bPleaseProceed = FALSE; break; } } else { // Succeeded to import the config from the file // let's get out bPleaseProceed = TRUE; ListView_DeleteAllItems(GetDlgItem(hDlg, IDC_LIST_OBJECT)); // // If we imported then, we need to do some fixup.... // // make sure to append on the "root" stuff... if (0 == _tcscmp(szKeyType,IIS_CLASS_WEB_SERVER_W)) { // figure out how big of a buffer do we need... int iLen = _tcslen((LPTSTR) pszSourcePath) + _tcslen(_T("/ROOT")) + 1; LPTSTR pszNewPath = (LPTSTR) LocalAlloc(LPTR, iLen * sizeof(TCHAR)); if (pszNewPath) { StringCbCopy(pszNewPath,(iLen * sizeof(TCHAR)), (TCHAR *) pszSourcePath); StringCbCat(pszNewPath,(iLen * sizeof(TCHAR)), (TCHAR *) _T("/ROOT")); // figure out how big of a buffer do we need... iLen = _tcslen((LPTSTR) pszDestinationPathMungeAble) + _tcslen(_T("/ROOT")) + 1; LPTSTR pszNewPath2 = (LPTSTR) LocalAlloc(LPTR, iLen * sizeof(TCHAR)); if (pszNewPath2) { StringCbCopy(pszNewPath2,(iLen * sizeof(TCHAR)), (TCHAR *) pszDestinationPathMungeAble); StringCbCat(pszNewPath2,(iLen * sizeof(TCHAR)), (TCHAR *) _T("/ROOT")); hr = FixupImportAppRoot(pConnectionInfo,pszNewPath,pszNewPath2); } } } else if (0 == _tcscmp(szKeyType,IIS_CLASS_WEB_VDIR_W)) { hr = FixupImportAppRoot(pConnectionInfo,pszSourcePath,pszDestinationPathMungeAble); } EndDialog(hDlg, IDOK); break; } } while (FAILED(hr)); OnImportOK_Exit: if (pszSourcePath) { LocalFree(pszSourcePath);pszSourcePath=NULL; } if (pszDestinationPathMungeAble) { LocalFree(pszDestinationPathMungeAble);pszDestinationPathMungeAble=NULL; } if (pszSaveSafeCopy) { LocalFree(pszSaveSafeCopy);pszSaveSafeCopy=NULL; } // make sure this doesn't hang around in memory SecureZeroMemory(szNewPassword, sizeof(szNewPassword)); return bPleaseProceed; } // IIsWebServer // IIsWebVirtualDir // IIsFtpServer // IIsFtpVirtualDir // IIsApplicationPool BOOL GetNewDestinationPathIfEntryExists(HWND hDlg,PCONNECTION_INFO pConnectionInfo,LPCTSTR szKeyType,LPTSTR * pszDestinationPathMungeAble,DWORD * pcbDestinationPathMungeAble,INT * iReturnedFlag) { BOOL bPleaseProceed = FALSE; // IF iReturnedFlag = 0 then don't overwrite and don't use the new path // IF iReturnedFlag = 1 then overwrite the existing entry // IF iReturnedFlag = 2 then use the newly created path *iReturnedFlag = 0; if (!pConnectionInfo) { goto GetNewDestinationPathIfEntryExists_Exit; } BOOL bEntryAlreadyThere = IsMetabaseWebSiteKeyExistAuth(pConnectionInfo,*pszDestinationPathMungeAble); if (FALSE == bEntryAlreadyThere) { bPleaseProceed = TRUE; *iReturnedFlag = 2; goto GetNewDestinationPathIfEntryExists_Exit; } // at this point // the destination path already exists in the metabase // Popup a dialog to get the user to pick a different DestinationPath // figure out which one of the dialogs we need to display and get another path from the user... if (0 == _tcscmp(szKeyType,IIS_CLASS_WEB_SERVER_W) || 0 == _tcscmp(szKeyType,IIS_CLASS_FTP_SERVER_W) ) { INT_PTR iRet = DialogBox((HINSTANCE) _Module.m_hInst, MAKEINTRESOURCE(IDD_DIALOG_EXISTS_SITE), hDlg, ShowSiteExistsDlgProc); switch(iRet) { case IDCANCEL: bPleaseProceed = FALSE; *iReturnedFlag = 0; break; case IDC_RADIO1: // create new site... { bPleaseProceed = TRUE; *iReturnedFlag = 0; // Get the new size that we're going to need... LPTSTR pNewPointer = NULL; INT iNewSize = 0; if (0 == _tcscmp(szKeyType,IIS_CLASS_WEB_SERVER_W)) { iNewSize = _tcslen(SZ_MBN_MACHINE SZ_MBN_SEP_STR SZ_MBN_WEB SZ_MBN_SEP_STR) + 10 + 1; } else { iNewSize = _tcslen(SZ_MBN_MACHINE SZ_MBN_SEP_STR SZ_MBN_FTP SZ_MBN_SEP_STR) + 10 + 1; } pNewPointer = (LPTSTR) LocalAlloc(LPTR, iNewSize * sizeof(TCHAR)); if (!pNewPointer) { bPleaseProceed = FALSE; *iReturnedFlag = 0; goto GetNewDestinationPathIfEntryExists_Exit; } // Generate a new site ID if (0 == _tcscmp(szKeyType,IIS_CLASS_WEB_SERVER_W)) { StringCbPrintf(pNewPointer,(iNewSize * sizeof(TCHAR)),SZ_MBN_MACHINE SZ_MBN_SEP_STR SZ_MBN_WEB SZ_MBN_SEP_STR _T("%d"), GetUniqueSite(SZ_MBN_MACHINE SZ_MBN_SEP_STR SZ_MBN_WEB)); } else { StringCbPrintf(pNewPointer,(iNewSize * sizeof(TCHAR)),SZ_MBN_MACHINE SZ_MBN_SEP_STR SZ_MBN_FTP SZ_MBN_SEP_STR _T("%d"), GetUniqueSite(SZ_MBN_MACHINE SZ_MBN_SEP_STR SZ_MBN_FTP)); } LocalFree((LPTSTR) *pszDestinationPathMungeAble);*pszDestinationPathMungeAble=NULL; *pszDestinationPathMungeAble = pNewPointer; *pcbDestinationPathMungeAble = (iNewSize * sizeof(TCHAR)); //IISDebugOutput(_T("Create new site:[%s]\r\n"),*pszDestinationPathMungeAble); break; } case IDC_RADIO2: // replace existing.. bPleaseProceed = TRUE; *iReturnedFlag = 1; break; default: bPleaseProceed = FALSE; *iReturnedFlag = 0; break; } } else if (0 == _tcscmp(szKeyType,IIS_CLASS_WEB_VDIR_W) || 0 == _tcscmp(szKeyType,IIS_CLASS_FTP_VDIR_W)) { TCHAR szMetabaseVDir[_MAX_PATH + 1]; ZeroMemory(szMetabaseVDir, sizeof(szMetabaseVDir)); INT_PTR iRet = DialogBoxParam((HINSTANCE) _Module.m_hInst, MAKEINTRESOURCE(IDD_DIALOG_EXISTS_VDIR), hDlg, ShowVDirExistsDlgProc, (LPARAM) szMetabaseVDir); switch(iRet) { case IDCANCEL: bPleaseProceed = FALSE; *iReturnedFlag = 0; break; case IDC_RADIO1: // create new site... { bPleaseProceed = TRUE; *iReturnedFlag = 0; // Get VDir Name that the user input on that screeen... // Generate a VDir Name CString strOriginalDestPath = *pszDestinationPathMungeAble; CString strNewPath, strRemainder; // Is this the root?? LPCTSTR lpPath1 = CMetabasePath::GetRootPath(strOriginalDestPath, strNewPath, &strRemainder); if (lpPath1) { // Allocate enough space for the new path... LPTSTR pNewPointer = NULL; DWORD iNewSize = 0; iNewSize = _tcslen(lpPath1) + _tcslen(szMetabaseVDir) + 2; pNewPointer = (LPTSTR) LocalAlloc(LPTR, iNewSize * sizeof(TCHAR)); if (!pNewPointer) { bPleaseProceed = FALSE; *iReturnedFlag = 0; goto GetNewDestinationPathIfEntryExists_Exit; } // if this is the root dir... StringCbCopy(pNewPointer,iNewSize * sizeof(TCHAR),lpPath1); AddEndingMetabaseSlashIfNeedTo(pNewPointer,iNewSize * sizeof(TCHAR)); StringCbCat(pNewPointer,iNewSize * sizeof(TCHAR),szMetabaseVDir); LocalFree((LPTSTR) *pszDestinationPathMungeAble);*pszDestinationPathMungeAble=NULL; *pszDestinationPathMungeAble = pNewPointer; *pcbDestinationPathMungeAble = (iNewSize * sizeof(TCHAR)); //IISDebugOutput(_T("Create new vdir:[%s]\r\n"),*pszDestinationPathMungeAble); } break; } case IDC_RADIO2: // replace existing... bPleaseProceed = TRUE; *iReturnedFlag = 1; break; default: bPleaseProceed = FALSE; *iReturnedFlag = 0; break; } } else if (0 == _tcscmp(szKeyType,L"IIsApplicationPool")) { TCHAR szMetabaseAppPool[_MAX_PATH + 1]; ZeroMemory(szMetabaseAppPool,sizeof(szMetabaseAppPool)); INT_PTR iRet = DialogBoxParam((HINSTANCE) _Module.m_hInst, MAKEINTRESOURCE(IDD_DIALOG_EXISTS_APP_POOL), hDlg, ShowAppPoolExistsDlgProc, (LPARAM) szMetabaseAppPool); switch(iRet) { case IDCANCEL: bPleaseProceed = FALSE; *iReturnedFlag = 0; break; case IDC_RADIO1: // create new site... { bPleaseProceed = TRUE; *iReturnedFlag = 0; // Allocate enough space for the new path... LPTSTR pNewPointer = NULL; INT iNewSize = 0; iNewSize = _tcslen(SZ_MBN_MACHINE SZ_MBN_SEP_STR SZ_MBN_WEB SZ_MBN_SEP_STR SZ_MBN_APP_POOLS SZ_MBN_SEP_STR) + _tcslen(szMetabaseAppPool) + 1; pNewPointer = (LPTSTR) LocalAlloc(LPTR, iNewSize * sizeof(TCHAR)); if (!pNewPointer) { bPleaseProceed = FALSE; *iReturnedFlag = 0; goto GetNewDestinationPathIfEntryExists_Exit; } // Get The New AppPool Name that the user input on that screeen... StringCbPrintf(pNewPointer,(iNewSize * sizeof(TCHAR)),SZ_MBN_MACHINE SZ_MBN_SEP_STR SZ_MBN_WEB SZ_MBN_SEP_STR SZ_MBN_APP_POOLS SZ_MBN_SEP_STR _T("%s"),szMetabaseAppPool); LocalFree((LPTSTR) *pszDestinationPathMungeAble);*pszDestinationPathMungeAble=NULL; *pszDestinationPathMungeAble = pNewPointer; *pcbDestinationPathMungeAble = (iNewSize * sizeof(TCHAR)); //IISDebugOutput(_T("Create new AppPool:[%s]\r\n"),*pszDestinationPathMungeAble); break; } case IDC_RADIO2: // replace existing... bPleaseProceed = TRUE; *iReturnedFlag = 1; break; default: bPleaseProceed = FALSE; *iReturnedFlag = 0; break; } } else { // nothing matches, get out bPleaseProceed = FALSE; } GetNewDestinationPathIfEntryExists_Exit: return bPleaseProceed; } HRESULT CleanDestinationPathForVdirs(LPCTSTR szKeyType,LPCTSTR szCurrentMetabasePath,LPTSTR * pszDestinationPathMungeMe,DWORD * pcbDestinationPathMungeMe) { HRESULT hReturn = E_FAIL; BOOL bCreateAFirstLevelVdir = FALSE; LPTSTR pszLastPart = NULL; LPTSTR pszLastPartNew = NULL; int iLastPartNewSize = 0; INT iChars = 0; DWORD cbNewPointer = 0; LPTSTR pNewPointer = NULL; if (!CleanMetaPath(pszDestinationPathMungeMe,pcbDestinationPathMungeMe)) { hReturn = E_POINTER; } if (0 == _tcscmp(szKeyType,IIS_CLASS_WEB_SERVER_W) || 0 == _tcscmp(szKeyType,IIS_CLASS_FTP_SERVER_W) ) { hReturn = S_OK; } else if (0 == _tcscmp(szKeyType,IIS_CLASS_WEB_VDIR_W) || 0 == _tcscmp(szKeyType,IIS_CLASS_FTP_VDIR_W)) { hReturn = E_FAIL; // szCurrentMetabasePath probably looks like: // lm/w3svc/500/ROOT/CurrentSite // lm/w3svc/500/ROOT // lm/w3svc/500 // *pszDestinationPathMungeMe probably looks like: // lm/w3svc/23/ROOT/MyOldSite // lm/w3svc/23/ROOT // // make *pszDestinationPathMungeMe look like lm/w3svc/500/ROOT/MyOldSite // // Get the lm/w3svc/sitenum part of szCurrentMetabasePath // if (0 == _tcscmp(szKeyType,IIS_CLASS_WEB_VDIR_W)) { //IISDebugOutput(_T("CleanDestinationPathForVdirs:KeyType=%s,CurPath=%s,MetabasePathDestination=%s\r\n"),szKeyType,szCurrentMetabasePath,*pszDestinationPathMungeMe); // Get Vdir we want to append... // should look like "ROOT/MyVdir" CString strSiteNode, strRemainder_WithRoot; LPCTSTR lpPath1 = CMetabasePath::TruncatePath(3, *pszDestinationPathMungeMe, strSiteNode, &strRemainder_WithRoot); if (lpPath1){} if (strRemainder_WithRoot.IsEmpty()) { hReturn = E_INVALIDARG; goto CleanDestinationPathForVdirs_Exit; } if (IsWebSitePath(szCurrentMetabasePath)) { // if our current metabase path is already a site node, then add them together // /LM/W3SVC/1 + / + ROOT/MyVdir // figure out how much space we need. iChars = _tcslen(szCurrentMetabasePath) + _tcslen(strRemainder_WithRoot) + 2; // includes extra slash cbNewPointer = iChars * sizeof(TCHAR); // allocate the new space pNewPointer = NULL; pNewPointer = (LPTSTR) LocalAlloc(LPTR, cbNewPointer); if (!pNewPointer) { hReturn = E_OUTOFMEMORY; goto CleanDestinationPathForVdirs_Exit; } // copy the data to the new buffer StringCbCopy(pNewPointer,cbNewPointer,szCurrentMetabasePath); AddEndingMetabaseSlashIfNeedTo(pNewPointer,cbNewPointer); StringCbCat(pNewPointer,cbNewPointer,(LPCTSTR) strRemainder_WithRoot); // Free the old one. LocalFree(*pszDestinationPathMungeMe);*pszDestinationPathMungeMe=NULL; // point to the new buffer *pszDestinationPathMungeMe = pNewPointer; *pcbDestinationPathMungeMe = cbNewPointer; hReturn = S_OK; } else if (IsWebSiteVDirPath(szCurrentMetabasePath,FALSE)) { // we failed to get farther, just treat it as a new vdir bCreateAFirstLevelVdir = TRUE; // if our current metabase path is already a vdir/physical path dir...then do some funky magic pszLastPart = NULL; pszLastPartNew = NULL; iLastPartNewSize = 0; BOOL bIsRootVdir = IsRootVDir(*pszDestinationPathMungeMe); pszLastPart = GimmiePointerToLastPart(*pszDestinationPathMungeMe); if (pszLastPart) { bCreateAFirstLevelVdir = FALSE; iLastPartNewSize = _tcslen(pszLastPart) + 1; pszLastPartNew = (LPTSTR) LocalAlloc(LPTR, iLastPartNewSize * sizeof(TCHAR)); if (!pszLastPartNew) { hReturn = E_OUTOFMEMORY; goto CleanDestinationPathForVdirs_Exit; } StringCbCopy(pszLastPartNew, iLastPartNewSize * sizeof(TCHAR),pszLastPart); } // check if the site that the user is currently on, is a vdir or physical dir... if (bCreateAFirstLevelVdir) { // /LM/W3SVC/1 + / + ROOT/MyNewVdir CString strRemainder_Temp; LPCTSTR lpPath2 = CMetabasePath::TruncatePath(3, szCurrentMetabasePath, strSiteNode, &strRemainder_Temp); if (lpPath2){} if (strSiteNode.IsEmpty()) { hReturn = E_INVALIDARG; goto CleanDestinationPathForVdirs_Exit; } // figure out how much space we need. iChars = _tcslen(strSiteNode) + _tcslen(strRemainder_WithRoot) + 2; // includes extra slash cbNewPointer = iChars * sizeof(TCHAR); // allocate it pNewPointer = NULL; pNewPointer = (LPTSTR) LocalAlloc(LPTR, cbNewPointer); if (!pNewPointer) { hReturn = E_OUTOFMEMORY; goto CleanDestinationPathForVdirs_Exit; } // Copy to new buffer StringCbCopy(pNewPointer,cbNewPointer,strSiteNode); AddEndingMetabaseSlashIfNeedTo(pNewPointer,cbNewPointer); StringCbCat(pNewPointer,cbNewPointer,(LPCTSTR) strRemainder_WithRoot); // Free the old one. LocalFree(*pszDestinationPathMungeMe);*pszDestinationPathMungeMe=NULL; // point to the new buffer *pszDestinationPathMungeMe = pNewPointer; *pcbDestinationPathMungeMe = cbNewPointer; } else { // /LM/W3SVC/1/ROOT/MyOldVdirThatIwantToKeep + / + MyNewVdir // figure out how much space we need. iChars = _tcslen(szCurrentMetabasePath) + 2; // includes extra slash if (pszLastPartNew) { iChars = iChars + _tcslen(pszLastPartNew); } cbNewPointer = iChars * sizeof(TCHAR); // allocate the new amt of space pNewPointer = NULL; pNewPointer = (LPTSTR) LocalAlloc(LPTR, cbNewPointer); if (!pNewPointer) { hReturn = E_OUTOFMEMORY; goto CleanDestinationPathForVdirs_Exit; } // Copy to new buffer StringCbCopy(pNewPointer,cbNewPointer,szCurrentMetabasePath); if (pszLastPartNew) { // Don't copy over if the end of this part is root // and the part we want to copy over is "root" if (!bIsRootVdir) { AddEndingMetabaseSlashIfNeedTo(pNewPointer,cbNewPointer); StringCbCat(pNewPointer,cbNewPointer,pszLastPartNew); } } // Free the old one. LocalFree(*pszDestinationPathMungeMe);*pszDestinationPathMungeMe=NULL; // point to the new buffer *pszDestinationPathMungeMe = pNewPointer; *pcbDestinationPathMungeMe = cbNewPointer; } hReturn = S_OK; } else { hReturn = E_INVALIDARG; goto CleanDestinationPathForVdirs_Exit; } } else { // Get Vdir we want to append... CString strSiteNode, strRemainder_WithRoot; LPCTSTR lpPath3 = CMetabasePath::TruncatePath(3, *pszDestinationPathMungeMe, strSiteNode, &strRemainder_WithRoot); if (lpPath3){} if (strRemainder_WithRoot.IsEmpty()) { hReturn = E_INVALIDARG; goto CleanDestinationPathForVdirs_Exit; } if (IsFTPSitePath(szCurrentMetabasePath)) { // if our current metabase path is already a site node, then add them together // /LM/MSFTPSVC/1 + / + ROOT/MyVdir // figure out how much space we need. iChars = _tcslen(szCurrentMetabasePath) + _tcslen(strRemainder_WithRoot) + 2; cbNewPointer = iChars * sizeof(TCHAR); // allocate the new amt of space pNewPointer = NULL; pNewPointer = (LPTSTR) LocalAlloc(LPTR, cbNewPointer); if (!pNewPointer) { hReturn = E_OUTOFMEMORY; goto CleanDestinationPathForVdirs_Exit; } // Copy to new buffer StringCbCopy(pNewPointer,cbNewPointer,szCurrentMetabasePath); AddEndingMetabaseSlashIfNeedTo(pNewPointer,cbNewPointer); StringCbCat(pNewPointer,cbNewPointer,(LPCTSTR) strRemainder_WithRoot); // Free the old one. LocalFree(*pszDestinationPathMungeMe);*pszDestinationPathMungeMe=NULL; // point to the new buffer *pszDestinationPathMungeMe = pNewPointer; *pcbDestinationPathMungeMe = cbNewPointer; hReturn = S_OK; } else if (IsFTPSiteVDirPath(szCurrentMetabasePath,FALSE)) { // we failed to get farther, just treat it as a new vdir bCreateAFirstLevelVdir = TRUE; // if our current metabase path is already a vdir/physical path dir...then do some funky magic pszLastPart = NULL; pszLastPartNew = NULL; iLastPartNewSize = 0; BOOL bIsRootVdir = IsRootVDir(*pszDestinationPathMungeMe); pszLastPart = GimmiePointerToLastPart(*pszDestinationPathMungeMe); if (pszLastPart) { bCreateAFirstLevelVdir = FALSE; iLastPartNewSize = _tcslen(pszLastPart) + 1; pszLastPartNew = (LPTSTR) LocalAlloc(LPTR, iLastPartNewSize * sizeof(TCHAR)); if (!pszLastPartNew) { hReturn = E_OUTOFMEMORY; goto CleanDestinationPathForVdirs_Exit; } StringCbCopy(pszLastPartNew, iLastPartNewSize * sizeof(TCHAR),pszLastPart); } // check if the site that the user is currently on, is a vdir or physical dir... if (bCreateAFirstLevelVdir) { CString strRemainder_Temp; LPCTSTR lpPath4 = CMetabasePath::TruncatePath(3, szCurrentMetabasePath, strSiteNode, &strRemainder_Temp); if (lpPath4){} if (strSiteNode.IsEmpty()) { hReturn = E_INVALIDARG; goto CleanDestinationPathForVdirs_Exit; } // figure out how much space we need. iChars = _tcslen(szCurrentMetabasePath) + _tcslen(strRemainder_WithRoot) + 2; cbNewPointer = iChars * sizeof(TCHAR); // allocate the new amt of space pNewPointer = NULL; pNewPointer = (LPTSTR) LocalAlloc(LPTR, cbNewPointer); if (!pNewPointer) { hReturn = E_OUTOFMEMORY; goto CleanDestinationPathForVdirs_Exit; } // Copy to new buffer StringCbCopy(pNewPointer,cbNewPointer,strSiteNode); AddEndingMetabaseSlashIfNeedTo(pNewPointer,cbNewPointer); StringCbCat(pNewPointer,cbNewPointer,(LPCTSTR) strRemainder_WithRoot); // Free the old one. LocalFree(*pszDestinationPathMungeMe);*pszDestinationPathMungeMe=NULL; // point to the new buffer *pszDestinationPathMungeMe = pNewPointer; *pcbDestinationPathMungeMe = cbNewPointer; } else { // /LM/MSFTPSVC/1/ROOT/MyOldVdirThatIwantToKeep + / + MyNewVdir // figure out how much space we need. iChars = _tcslen(szCurrentMetabasePath) + 2; if (pszLastPartNew) { iChars = iChars + _tcslen(pszLastPartNew); } cbNewPointer = iChars * sizeof(TCHAR); // allocate the new amt of space pNewPointer = NULL; pNewPointer = (LPTSTR) LocalAlloc(LPTR, cbNewPointer); if (!pNewPointer) { hReturn = E_OUTOFMEMORY; goto CleanDestinationPathForVdirs_Exit; } // Copy to new buffer StringCbCopy(pNewPointer,cbNewPointer,szCurrentMetabasePath); if (pszLastPartNew) { // Don't copy over if the end of this part is root // and the part we want to copy over is "root" if (!bIsRootVdir) { AddEndingMetabaseSlashIfNeedTo(pNewPointer,cbNewPointer); StringCbCat(pNewPointer,cbNewPointer,pszLastPartNew); } } // Free the old one. LocalFree(*pszDestinationPathMungeMe);*pszDestinationPathMungeMe=NULL; // point to the new buffer *pszDestinationPathMungeMe = pNewPointer; *pcbDestinationPathMungeMe = cbNewPointer; } hReturn = S_OK; } else { hReturn = E_INVALIDARG; goto CleanDestinationPathForVdirs_Exit; } } } else if (0 == _tcscmp(szKeyType,L"IIsApplicationPool")) { hReturn = S_OK; } else { // nothing matches, get out hReturn = E_INVALIDARG; } CleanDestinationPathForVdirs_Exit: if (pszLastPartNew) { LocalFree(pszLastPartNew);pszLastPartNew=NULL; } return hReturn; } #define DEFAULT_TIMEOUT_VALUE 30000 HRESULT FixupImportAppRoot(PCONNECTION_INFO pConnectionInfo,LPCWSTR pszSourcePath,LPCWSTR pszDestPath) { HRESULT hr = S_OK; IMSAdminBase *pIMSAdminBase = NULL; IMSAdminBase2 *pIMSAdminBase2 = NULL; METADATA_HANDLE hObjHandle = NULL; DWORD dwMDMetaID = MD_APP_ROOT; DWORD dwBufferSize = 0; DWORD dwReqdBufferSize = 0; WCHAR *pBuffer = NULL; DWORD dwRecBufSize = 0; WCHAR *pRecBuf = NULL; METADATA_RECORD mdrMDData; const WCHAR c_slash = L'/'; WCHAR *pSourcePath = NULL; DWORD dwSLen = 0; WCHAR *pFoundStr = NULL; WCHAR *pOrigBuffer = NULL; WCHAR *pNewAppRoot = NULL; BOOL bCoInitCalled = FALSE; LPWSTR lpwstrTempPassword = NULL; if ((!pszSourcePath)||(!pszDestPath)) { return RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER); } if (!pConnectionInfo) { return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER); } if (pConnectionInfo->pszUserPasswordEncrypted) { if (FAILED(DecryptMemoryPassword((LPWSTR) pConnectionInfo->pszUserPasswordEncrypted,&lpwstrTempPassword,pConnectionInfo->cbUserPasswordEncrypted))) { return HRESULT_FROM_WIN32(ERROR_DECRYPTION_FAILED); } } CComAuthInfo auth(pConnectionInfo->pszMachineName,pConnectionInfo->pszUserName,lpwstrTempPassword); _wcsupr((WCHAR*)pszSourcePath); _wcsupr((WCHAR*)pszDestPath); // Make sure that pSourcePath has a trailing slash. dwSLen = (DWORD)wcslen(pszSourcePath); if (c_slash == pszSourcePath[dwSLen - 1]) { pSourcePath = new WCHAR[dwSLen+ 1]; if (!pSourcePath) { hr = E_OUTOFMEMORY; goto done; } StringCbCopyW(pSourcePath,((dwSLen+1) * sizeof(WCHAR)), pszSourcePath); } else { pSourcePath = new WCHAR[dwSLen + 2]; if (!pSourcePath) { hr = E_OUTOFMEMORY; goto done; } StringCbCopyW(pSourcePath,((dwSLen+2) * sizeof(WCHAR)), pszSourcePath); pSourcePath[dwSLen] = c_slash; pSourcePath[dwSLen+1] = 0; } if(FAILED(hr = CoInitializeEx(NULL, COINIT_MULTITHREADED))) { if(FAILED(hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED))) { goto done; } } bCoInitCalled = TRUE; // RPC_C_AUTHN_LEVEL_DEFAULT 0 // RPC_C_AUTHN_LEVEL_NONE 1 // RPC_C_AUTHN_LEVEL_CONNECT 2 // RPC_C_AUTHN_LEVEL_CALL 3 // RPC_C_AUTHN_LEVEL_PKT 4 // RPC_C_AUTHN_LEVEL_PKT_INTEGRITY 5 // RPC_C_AUTHN_LEVEL_PKT_PRIVACY 6 COSERVERINFO * pcsiName = auth.CreateServerInfoStruct(RPC_C_AUTHN_LEVEL_DEFAULT); MULTI_QI res[1] = { {&IID_IMSAdminBase, NULL, 0} }; if (FAILED(hr = CoCreateInstanceEx(CLSID_MSAdminBase,NULL,CLSCTX_ALL,pcsiName,1,res))) { goto done; } pIMSAdminBase = (IMSAdminBase *)res[0].pItf; if (auth.UsesImpersonation()) { if (FAILED(hr = auth.ApplyProxyBlanket(pIMSAdminBase))) { goto done; } // There is a remote IUnknown interface that lurks behind IUnknown. // If that is not set, then the Release call can return access denied. IUnknown * pUnk = NULL; hr = pIMSAdminBase->QueryInterface(IID_IUnknown, (void **)&pUnk); if(FAILED(hr)) { goto done; } if (FAILED(hr = auth.ApplyProxyBlanket(pUnk))) { goto done; } pUnk->Release();pUnk = NULL; } if (FAILED(hr = pIMSAdminBase->QueryInterface(IID_IMSAdminBase2, (void **)&pIMSAdminBase2))) { goto done; } if (auth.UsesImpersonation()) { if (FAILED(hr = auth.ApplyProxyBlanket(pIMSAdminBase2))) { goto done; } } else { // the local call needs min RPC_C_IMP_LEVEL_IMPERSONATE // for the pIMSAdminBase2 objects Import/Export functions! if (FAILED(hr = SetBlanket(pIMSAdminBase2))) { //goto done; } } hr = pIMSAdminBase2->OpenKey( METADATA_MASTER_ROOT_HANDLE, (LPWSTR)L"", METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE, DEFAULT_TIMEOUT_VALUE, &hObjHandle ); if (FAILED(hr)) { goto done; } hr = pIMSAdminBase2->GetDataPaths( hObjHandle, pszDestPath, dwMDMetaID, ALL_METADATA, dwBufferSize, (LPWSTR)L"", &dwReqdBufferSize ); if (FAILED(hr)) { if (hr != HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) { goto done; } } pBuffer = new WCHAR[dwReqdBufferSize]; if (!pBuffer) { hr = E_OUTOFMEMORY; goto done; } dwBufferSize = dwReqdBufferSize; hr = pIMSAdminBase2->GetDataPaths( hObjHandle, pszDestPath, dwMDMetaID, ALL_METADATA, dwBufferSize, (LPWSTR)pBuffer, &dwReqdBufferSize ); pOrigBuffer = pBuffer; if (FAILED(hr)) { goto done; } // look at AppRoot at each path while (*pBuffer) { // Create the new AppRoot for this record... int iNewAppRootLen = wcslen(pBuffer) + 1; pNewAppRoot = new WCHAR[iNewAppRootLen]; if (!pNewAppRoot) { hr = E_OUTOFMEMORY; goto done; } StringCbCopy(pNewAppRoot,iNewAppRootLen * sizeof(WCHAR),pBuffer); _wcsupr((WCHAR*)pNewAppRoot); // make sure it doesn't end with a slash... if (_T('/') == pNewAppRoot[iNewAppRootLen - 2]) { // cut if off if it's there pNewAppRoot[iNewAppRootLen - 2] = '\0'; } MD_SET_DATA_RECORD(&mdrMDData, dwMDMetaID, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, dwRecBufSize, pRecBuf); hr = pIMSAdminBase2->GetData( hObjHandle, pBuffer, &mdrMDData, &dwRecBufSize ); if (FAILED(hr)) { if (hr != HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) { goto done; } } pRecBuf = new WCHAR[dwRecBufSize + 1]; // for extra slash if we need it if (!pRecBuf) { hr = E_OUTOFMEMORY; goto done; } MD_SET_DATA_RECORD(&mdrMDData, dwMDMetaID, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, dwRecBufSize, pRecBuf); hr = pIMSAdminBase2->GetData( hObjHandle, pBuffer, &mdrMDData, &dwRecBufSize ); if (FAILED(hr)) { goto done; } _wcsupr(pRecBuf); // Make sure that pRecBuf has a trailing slash. dwSLen = (DWORD)wcslen(pRecBuf); if (c_slash != pRecBuf[dwSLen - 1]) { pRecBuf[dwSLen] = c_slash; pRecBuf[dwSLen+1] = 0; } pFoundStr = wcsstr(pRecBuf,pSourcePath); if (pFoundStr) { if (pNewAppRoot) { // now set the new AppRoot MD_SET_DATA_RECORD(&mdrMDData, dwMDMetaID, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, (DWORD)((wcslen(pNewAppRoot)+1)*sizeof(WCHAR)), (PBYTE)pNewAppRoot); hr = pIMSAdminBase2->SetData( hObjHandle, pBuffer, &mdrMDData ); IISDebugOutput(_T("FixupImportAppRoot:NewAppRoot=%s\r\n"),(LPCTSTR) pNewAppRoot); } else { hr = E_OUTOFMEMORY; } if (FAILED(hr)) { goto done; } if (pNewAppRoot) { delete[] pNewAppRoot; pNewAppRoot = NULL; } } if (pRecBuf) { delete [] pRecBuf; pRecBuf = NULL; } pBuffer += wcslen(pBuffer) + 1; } done: if (lpwstrTempPassword) { // security percaution:Make sure to zero out memory that temporary password was used for. SecureZeroMemory(lpwstrTempPassword,pConnectionInfo->cbUserPasswordEncrypted); LocalFree(lpwstrTempPassword); lpwstrTempPassword = NULL; } if (hObjHandle) { pIMSAdminBase2->CloseKey(hObjHandle); } if (pIMSAdminBase2) { pIMSAdminBase2->Release(); pIMSAdminBase2 = NULL; } if (pIMSAdminBase) { pIMSAdminBase->Release(); pIMSAdminBase = NULL; } if (pRecBuf) { delete[] pRecBuf; pRecBuf = NULL; } if (pNewAppRoot) { delete[] pNewAppRoot; pNewAppRoot = NULL; } if (pOrigBuffer) { // pOrigBuffer is pBuffer before we moved through it. delete pOrigBuffer; pOrigBuffer = NULL; pBuffer = NULL; } if (pSourcePath) { delete[] pSourcePath; pSourcePath = NULL; } if (bCoInitCalled) { CoUninitialize(); } return hr; }