#include "stdafx.h" #include #undef UNICODE #include "iadm.h" #define UNICODE #include "iiscnfg.h" #include "mdkey.h" #include "setupapi.h" #include "elem.h" #include "mdentry.h" #include "inetinfo.h" #include "helper.h" DWORD atodw(LPCTSTR lpszData) { DWORD i = 0, sum = 0; TCHAR *s, *t; s = (LPTSTR)lpszData; t = (LPTSTR)lpszData; while (*t) t++; t--; if (*s == _T('0') && (*(s+1) == _T('x') || *(s+1) == _T('X'))) s += 2; while (s <= t) { if ( *s >= _T('0') && *s <= _T('9') ) i = *s - _T('0'); else if ( *s >= _T('a') && *s <= _T('f') ) i = *s - _T('a') + 10; else if ( *s >= _T('A') && *s <= _T('F') ) i = *s - _T('A') + 10; else break; sum = sum * 16 + i; s++; } return sum; } #define MAX_FIELDS 12 #define FIELD_SEPERATOR _T("\t") LPTSTR field[MAX_FIELDS]; BYTE g_DataBuf[1024 * 16]; DWORD g_dwValue; // Split a line of entry into 10 fields for MDEntry datatype BOOL SplitLine(LPTSTR szLine) { int i = 0; TCHAR *token; token = _tcstok(szLine, FIELD_SEPERATOR); while (token && i < MAX_FIELDS) { field[i++] = token; token = _tcstok(NULL, FIELD_SEPERATOR); } if (i == MAX_FIELDS) return TRUE; else { SetLastError(ERROR_INVALID_DATA); return FALSE; } } // Fill in the structure of MDEntry BOOL SetupMDEntry(LPTSTR szLine, BOOL fUpgrade) { BOOL fMigrate; BOOL fKeepOldReg; HKEY hRegRootKey; LPTSTR szRegSubKey; LPTSTR szRegValueName; LPBYTE pbData = g_DataBuf; DWORD cbData; static TCHAR szMDPath[MAX_PATH]; MDEntry mdentry, *pMDEntry = &mdentry; DWORD dwIndex=0; TCHAR pszEnumName[MAX_PATH]; DWORD cbEnumName = sizeof(pszEnumName); BOOL fDoSet; BOOL fSetOnlyIfNotPresent; if (!SplitLine(szLine)) return FALSE; if ( lstrcmp(field[0], _T("1")) == 0) { fMigrate = (TRUE && fUpgrade); fDoSet = TRUE; fSetOnlyIfNotPresent = FALSE; } else if (lstrcmp(field[0], _T("2")) == 0) { fMigrate = (TRUE && fUpgrade); fDoSet = FALSE; fSetOnlyIfNotPresent = FALSE; } else if (lstrcmp(field[0], _T("4")) == 0) { fMigrate = FALSE; fDoSet = TRUE; fSetOnlyIfNotPresent = TRUE; } else { fMigrate = FALSE; fDoSet = TRUE; fSetOnlyIfNotPresent = FALSE; } if ( lstrcmp(field[1], _T("1")) == 0) fKeepOldReg = TRUE; else fKeepOldReg = FALSE; if (lstrcmpi(field[2], _T("HKLM")) == 0) hRegRootKey = HKEY_LOCAL_MACHINE; else if (lstrcmpi(field[2], _T("HKCR")) == 0) hRegRootKey = HKEY_CLASSES_ROOT; else if (lstrcmpi(field[2], _T("HKCU")) == 0) hRegRootKey = HKEY_CURRENT_USER; else if (lstrcmpi(field[2], _T("HKU")) == 0) hRegRootKey = HKEY_USERS; else hRegRootKey = HKEY_LOCAL_MACHINE; szRegSubKey = field[3]; szRegValueName = field[4]; pMDEntry->szMDPath = field[5]; pMDEntry->dwMDIdentifier = _ttoi(field[6]); pMDEntry->dwMDAttributes = atodw(field[7]); pMDEntry->dwMDUserType = _ttoi(field[8]); pMDEntry->dwMDDataType = _ttoi(field[9]); pMDEntry->dwMDDataLen = _ttoi(field[10]); DebugOutput(_T("SetupMDEntry(): szLine: field[4]=%s, [5]=%s, [6]=%s"), field[4], field[5], field[6]); if ( pMDEntry->dwMDDataType == DWORD_METADATA ) { g_dwValue = atodw(field[11]); pMDEntry->pbMDData = (LPBYTE) &g_dwValue; } else if ( pMDEntry->dwMDDataType == BINARY_METADATA ) { BYTE rgbBinaryBuf[4096]; TCHAR rgtcByteValue[3] = { _T('\0'), _T('\0'), _T('\0') }; LPTSTR pbBinary = field[11]; DWORD dwCount = lstrlen(pbBinary); DWORD dwLen = 0; if ((dwCount+1)/2 > sizeof(rgbBinaryBuf)) return FALSE; // Convert to binary data: // "000102030405ff06" becomes // BYTE [] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0xff, 0x06 } while (dwCount) { if (dwCount == 1) { rgtcByteValue[0] = *pbBinary++; rgtcByteValue[1] = _T('\0'); dwCount--; } else { rgtcByteValue[0] = *pbBinary++; rgtcByteValue[1] = *pbBinary++; dwCount -= 2; } rgbBinaryBuf[dwLen++] = (BYTE)atodw(rgtcByteValue); } // Set the records straight pMDEntry->pbMDData = rgbBinaryBuf; pMDEntry->dwMDDataLen = dwLen; } else { TCHAR szStringBuf[4096]; TCHAR *pszStringData = field[11]; *szStringBuf = 0; // // do env substitution if necessary // int iStart, iEnd = 0; do { for (iStart = iEnd; pszStringData[iStart] != 0; iStart++) { if (pszStringData[iStart] == _T('%')) break; } if (pszStringData[iStart] != 0) { // copy from the last substitution to here pszStringData[iStart] = 0; lstrcat(szStringBuf, pszStringData + iEnd); pszStringData[iStart] = _T('%'); // find the end % for (iEnd = iStart + 1; pszStringData[iEnd] != 0; iEnd++) { if (pszStringData[iEnd] == _T('%')) break; } if (iStart + 1 == iEnd) { // found %%, replace with % lstrcat(szStringBuf, _T("%")); iEnd++; } else if (pszStringData[iEnd] != 0) { // do the substitution pszStringData[iEnd] = 0; DWORD cbBuf = lstrlen(szStringBuf); GetEnvironmentVariable(pszStringData + iStart + 1, szStringBuf+cbBuf, sizeof(szStringBuf)/sizeof(szStringBuf[0])-cbBuf); pszStringData[iEnd] = _T('%'); iEnd++; } else { // no ending %, copy the rest lstrcat(szStringBuf, pszStringData + iStart); } } } while (pszStringData[iStart] != 0); lstrcat(szStringBuf, pszStringData + iEnd); lstrcpy(pszStringData, szStringBuf); pMDEntry->pbMDData = (LPBYTE)pszStringData; } BOOL fMore = TRUE; while (fMore) { // // reg enumeration support // TCHAR szBuf[MAX_PATH + 1]; LPTSTR szRegKey = szBuf; // see if there is an '*' in the szRegSubKey field int iStar; for (iStar = 0; szRegSubKey[iStar] != 0; iStar++) { if (szRegSubKey[iStar] == _T('*')) break; } if (szRegSubKey[iStar] != 0 && (szRegSubKey[iStar + 1] == _T('\\') || szRegSubKey[iStar + 1] == 0)) { DWORD ec; HKEY hKey = NULL; // copy the base szRegSubKey[iStar] = 0; lstrcpy(szRegKey, szRegSubKey); szRegSubKey[iStar] = _T('*'); // open the key ec = RegOpenKeyEx(hRegRootKey, szRegKey, 0, KEY_ALL_ACCESS, &hKey); if (ec == ERROR_SUCCESS) { // do an enum to find out what we should be opening cbEnumName = sizeof(pszEnumName) / sizeof(pszEnumName[0]); ec = RegEnumKeyEx(hKey, dwIndex++, pszEnumName, &cbEnumName, NULL, NULL, 0, NULL); if (ec != ERROR_SUCCESS) { fMore = FALSE; RegCloseKey(hKey); continue; } else { fMore = TRUE; } lstrcat(szRegKey, pszEnumName); if (szRegSubKey[iStar + 1] != 0) lstrcat(szRegKey, szRegSubKey + iStar + 1); RegCloseKey(hKey); } else { // couldn't open key lstrcpy(szRegKey, szRegSubKey); fMore = FALSE; } } else { // no star lstrcpy(szRegKey, szRegSubKey); fMore = FALSE; } // migrate if necessary if (fMigrate) { HKEY hKey = NULL; LONG err = ERROR_SUCCESS; DWORD dwType = 0; cbData = sizeof(g_DataBuf); err = RegOpenKeyEx(hRegRootKey, szRegKey, 0, KEY_ALL_ACCESS, &hKey); if ( err == ERROR_SUCCESS ) { err = RegQueryValueEx(hKey, szRegValueName, NULL, &dwType, pbData, &cbData); if (err == ERROR_MORE_DATA) { #ifdef DEBUG DebugBreak(); #endif } if ( err == ERROR_SUCCESS) { pMDEntry->pbMDData = pbData; pMDEntry->dwMDDataLen = cbData; fDoSet = TRUE; } if (fKeepOldReg == FALSE) err = RegDeleteValue(hKey, szRegValueName); RegCloseKey(hKey); } } else if (fKeepOldReg == FALSE) { HKEY hKey = NULL; LONG err = ERROR_SUCCESS; DWORD dwType = 0; err = RegOpenKeyEx(hRegRootKey, szRegKey, 0, KEY_ALL_ACCESS, &hKey); if ( err == ERROR_SUCCESS ) { err = RegDeleteValue(hKey, szRegValueName); RegCloseKey(hKey); } } switch (pMDEntry->dwMDDataType) { case DWORD_METADATA: pMDEntry->dwMDDataLen = 4; break; case STRING_METADATA: case EXPANDSZ_METADATA: pMDEntry->dwMDDataLen = (lstrlen((LPTSTR)pMDEntry->pbMDData) + 1) * sizeof(TCHAR); break; case MULTISZ_METADATA: // We only allow a single string even for a multi-sz. pMDEntry->dwMDDataLen = (lstrlen((LPTSTR)pMDEntry->pbMDData) + 1) * sizeof(TCHAR); // Append the second NULL and bump the length by one at the same time *(LPTSTR)((LPBYTE)pMDEntry->pbMDData + pMDEntry->dwMDDataLen) = _T('\0'); pMDEntry->dwMDDataLen += sizeof(TCHAR); break; case BINARY_METADATA: // Everything is set upstream break; } if (fDoSet) { SetMDEntry(pMDEntry, pszEnumName, fSetOnlyIfNotPresent); } } return TRUE; } void SetMDEntry(MDEntry *pMDEntry, LPTSTR pszEnumName, BOOL fSetOnlyIfNotPresent) { CMDKey cmdKey; BOOL fSet = TRUE; TCHAR szBuf[MAX_PATH + 1]; LPTSTR szMDPath = szBuf; DebugOutput(_T("SetMDEntry(): pMDEntry=0x%x"), pMDEntry); if (pszEnumName != NULL) { // see if there is an '*' in the szMDPath field int iStar; for (iStar = 0; pMDEntry->szMDPath[iStar] != 0; iStar++) { if (pMDEntry->szMDPath[iStar] == _T('*')) break; } if (pMDEntry->szMDPath[iStar] != 0 && (pMDEntry->szMDPath[iStar + 1] == _T('\\') || pMDEntry->szMDPath[iStar + 1] == 0)) { // copy the base pMDEntry->szMDPath[iStar] = 0; lstrcpy(szMDPath, pMDEntry->szMDPath); pMDEntry->szMDPath[iStar] = _T('*'); // copy the substitued path lstrcat(szMDPath, pszEnumName); // finish the copy if (pMDEntry->szMDPath[iStar + 1] != 0) lstrcat(szMDPath, pMDEntry->szMDPath + iStar + 1); } else { // no star szMDPath = pMDEntry->szMDPath; } } else { szMDPath = pMDEntry->szMDPath; } cmdKey.CreateNode(METADATA_MASTER_ROOT_HANDLE, (LPCTSTR)szMDPath); if ( (METADATA_HANDLE)cmdKey ) { BYTE pbData[32]; DWORD dwAttr, dwUType, dwDType; DWORD dwLen=sizeof(pbData); if (fSetOnlyIfNotPresent && cmdKey.GetData( pMDEntry->dwMDIdentifier, &dwAttr, &dwUType, &dwDType, &dwLen, pbData)) { fSet = FALSE; } if (fSet) { cmdKey.SetData( pMDEntry->dwMDIdentifier, pMDEntry->dwMDAttributes, pMDEntry->dwMDUserType, pMDEntry->dwMDDataType, pMDEntry->dwMDDataLen, pMDEntry->pbMDData); } cmdKey.Close(); } return; } void MigrateIMSToMD(HINF hInf, LPCTSTR szServerName, LPCTSTR szSection, DWORD dwRoutingSourcesMDID, BOOL fUpgrade, BOOL k2UpgradeToEE) { TCHAR buf[MAX_COMPUTERNAME_LENGTH + 1]; DWORD dwLen = MAX_COMPUTERNAME_LENGTH + 1; CString csDefaultSiteName; DebugOutput(_T("MigradeIMSToMD(): szSection=%s, fUpgrade=%d"), szSection, fUpgrade); GetComputerName(buf, &dwLen); AddVRootsToMD(szServerName, fUpgrade); // Migrate Virtual Roots and routing sources only on upgrade case if (fUpgrade && !k2UpgradeToEE) { MigrateRoutingSourcesToMD(szServerName, dwRoutingSourcesMDID); } theApp.GetLogFileFormats(); MyLoadString(IDS_SMTP_DEFAULT_SITE_NAME, csDefaultSiteName); SetEnvironmentVariable(_T("__INETPUB"), theApp.m_csPathInetpub); SetEnvironmentVariable(_T("__MAILROOT"), theApp.m_csPathMailroot); SetEnvironmentVariable(_T("__EQUALS"), _T("=")); SetEnvironmentVariable(_T("__EMPTY"), _T("")); SetEnvironmentVariable(_T("__SEMICOL"), _T(";")); SetEnvironmentVariable(_T("__SMTP_DEFAULT_SITE_NAME"), csDefaultSiteName); SetEnvironmentVariable(_T("__SMTP_LOG_FILE_FORMATS"), theApp.m_csLogFileFormats); SetEnvironmentVariable(_T("__MACHINENAME"), buf); MigrateInfSectionToMD(hInf, szSection, fUpgrade); if (!fUpgrade && !k2UpgradeToEE) { // If we are not upgrading, we will have to install the default // Mailroots and routing sources CString csFreshSection = szSection; csFreshSection += _T("_FRESH"); MigrateInfSectionToMD(hInf, (LPCTSTR)csFreshSection, fUpgrade); } SetEnvironmentVariable(_T("__INETPUB"), NULL); SetEnvironmentVariable(_T("__MAILROOT"), NULL); SetEnvironmentVariable(_T("__EQUALS"), NULL); SetEnvironmentVariable(_T("__EMPTY"), NULL); SetEnvironmentVariable(_T("__SEMICOL"), NULL); SetEnvironmentVariable(_T("__SMTP_DEFAULT_SITE_NAME"), NULL); SetEnvironmentVariable(_T("__SMTP_LOG_FILE_FORMATS"), NULL); SetEnvironmentVariable(_T("__MACHINENAME"), NULL); } void MigrateNNTPToMD(HINF hInf, LPCTSTR szSection, BOOL fUpgrade) { TCHAR buf[MAX_COMPUTERNAME_LENGTH + 1]; DWORD dwLen = MAX_COMPUTERNAME_LENGTH + 1; DebugOutput(_T("MigradeNNTPToMD(): szSection=%s, fUpgrade=%d"), szSection, fUpgrade); GetComputerName(buf, &dwLen); // About Virtual Roots AddVRootsToMD(_T("NNTPSVC"), fUpgrade); CString csDefaultSiteName; CString csServiceName; CString csAdminName; CString csAdminEmail; MyLoadString(IDS_NNTP_DEFAULT_SITE_NAME, csDefaultSiteName); MyLoadString(IDS_NNTP_SERVICE_NAME, csServiceName); MyLoadString(IDS_NNTP_DEFAULT_ADMIN_NAME, csAdminName); MyLoadString(IDS_NNTP_DEFAULT_ADMIN_EMAIL, csAdminEmail); theApp.GetLogFileFormats(); SetEnvironmentVariable(_T("__NNTPFILE"), theApp.m_csPathNntpFile); SetEnvironmentVariable(_T("__NNTPROOT"), theApp.m_csPathNntpRoot); SetEnvironmentVariable(_T("__MACHINENAME"), buf); SetEnvironmentVariable(_T("__INETPUB"), theApp.m_csPathInetpub); SetEnvironmentVariable(_T("__EMPTY"), NULL); SetEnvironmentVariable(_T("__NNTP_DEFAULT_SITE_NAME"), csDefaultSiteName); SetEnvironmentVariable(_T("__NNTP_SERVICE_NAME"), csServiceName); SetEnvironmentVariable(_T("__NNTP_DEFAULT_ADMIN_NAME"), csAdminName); SetEnvironmentVariable(_T("__NNTP_DEFAULT_ADMIN_EMAIL"), csAdminEmail); SetEnvironmentVariable(_T("__NNTP_LOG_FILE_FORMATS"), theApp.m_csLogFileFormats); MigrateInfSectionToMD(hInf, szSection, fUpgrade); SetEnvironmentVariable(_T("__NNTPFILE"), NULL); SetEnvironmentVariable(_T("__NNTPROOT"), NULL); SetEnvironmentVariable(_T("__MACHINENAME"), NULL); SetEnvironmentVariable(_T("__INETPUB"), NULL); SetEnvironmentVariable(_T("__NNTP_DEFAULT_SITE_NAME"), NULL); SetEnvironmentVariable(_T("__NNTP_SERVICE_NAME"), NULL); SetEnvironmentVariable(_T("__NNTP_DEFAULT_ADMIN_NAME"), NULL); SetEnvironmentVariable(_T("__NNTP_DEFAULT_ADMIN_EMAIL"), NULL); SetEnvironmentVariable(_T("__NNTP_LOG_FILE_FORMATS"), NULL); } void CreateVRMap(CMapStringToOb *pMap, LPCTSTR szVRootRegKey, LPCTSTR szRootDir, DWORD dwMdFlags, BOOL fUpgrade) { CMapStringToString *pGlobalObj; DebugOutput(_T("CreateVRMap(): pMap=0x%x, szVRootRegKey=%s, szRootDir=%s, dwMdFlags=%d, fUpgrade=%d"), pMap, szVRootRegKey, szRootDir, dwMdFlags, fUpgrade); if (fUpgrade) { CElem elem; elem.ReadRegVRoots(szVRootRegKey, pMap); } if (pMap->IsEmpty() || pMap->Lookup(_T("null"), (CObject*&)pGlobalObj) == FALSE) { CString ip, name, value; CMapStringToString *pNew; pNew = new CMapStringToString; if (pNew != NULL) { ip = _T("null"); name = _T("/"); value.Format(_T("%s,,%d"), szRootDir, dwMdFlags); pNew->SetAt(name, value); pMap->SetAt(ip, pNew); } } } void MigrateInfSectionToMD(HINF hFile, LPCTSTR szSection, BOOL fUpgrade) { TCHAR szLine[3 * 1024]; // So SetupMDEntry won't cause problems DWORD dwLineLen = 0, dwRequiredSize; DWORD dwIndex = 0; BOOL b = FALSE; INFCONTEXT Context; DebugOutput(_T("MigrateInfSectionToMD(): szSection=%s, fUpgrade=%d"), szSection, fUpgrade); b = SetupFindFirstLine(hFile, szSection, NULL, &Context); if (!b) return; while (b) { BOOL fLoop = TRUE; #ifdef DEBUG b = SetupGetLineText(&Context, NULL, NULL, NULL, NULL, 0, &dwRequiredSize); _ASSERT(dwRequiredSize < sizeof(szLine)); #endif ZeroMemory(szLine, sizeof(szLine)); if (SetupGetLineText(&Context, NULL, NULL, NULL, szLine, sizeof(szLine)/sizeof(szLine[0]), NULL) == FALSE) { // We're done return; } dwIndex++; if (!SetupMDEntry(szLine, fUpgrade)) { // If this fails we wiil not set up metabase stuff. _stprintf(szLine, TEXT("SplitLine [%s] line %u"), szSection, dwIndex); SetErrMsg(szLine, GetLastError()); } b = SetupFindNextLine(&Context, &Context); } return; } void SplitVRString(CString csValue, LPTSTR szPath, LPTSTR szUserName, DWORD *pdwPerm) { // csValue should be in format of ",," CString csPath, csUserName; int i; DebugOutput(_T("SplitVRString(): csValue=%s, szPath=%s, szUserName=%s"), csValue, szPath, szUserName); csValue.TrimLeft(); csValue.TrimRight(); csPath = csValue; csUserName = _T(""); *pdwPerm = 0; i = csValue.Find(_T(",")); if (i != -1) { csPath = csValue.Mid(0, i); csPath.TrimRight(); csValue = csValue.Mid(i+1); csValue.TrimLeft(); i = csValue.Find(_T(",")); if (i != -1) { csUserName = csValue.Mid(0, i); csUserName.TrimRight(); csValue = csValue.Mid(i+1); csValue.TrimLeft(); *pdwPerm = (DWORD)_ttoi((LPCTSTR)csValue); } } lstrcpyn(szPath, (LPCTSTR)csPath,_MAX_PATH); lstrcpyn(szUserName, (LPCTSTR)csUserName,_MAX_PATH); return; } void ApplyGlobalToMDVRootTree(CString csKeyPath, CMapStringToString *pGlobalObj) { DebugOutput(_T("ApplyGlobalToMDVRootTree(): csKeyPath=%s, pGlobalObj=0x%x"), csKeyPath, pGlobalObj); if (pGlobalObj->GetCount() == 0) return; POSITION pos = pGlobalObj->GetStartPosition(); while (pos) { BOOL fSkip = FALSE; CMDKey cmdKey; CString csName, csValue, csPath; pGlobalObj->GetNextAssoc(pos, csName, csValue); csPath = csKeyPath; if (csName.GetLength() > 0 && csName.Compare(_T("/")) != 0) { csPath += _T("/"); csPath += csName; // LM/*SVC/N//iisadmin } cmdKey.OpenNode(csPath); if ( (METADATA_HANDLE)cmdKey ) { if (csName.Compare(_T("/")) == 0) { if (cmdKey.IsEmpty() == FALSE) fSkip = TRUE; } else { fSkip = TRUE; } cmdKey.Close(); } if ( !fSkip ) { CreateMDVRootTree(csKeyPath, csName, csValue); } } } void CreateMDVRootTree(CString csKeyPath, CString csName, CString csValue) { CMDKey cmdKey; DebugOutput(_T("CreateMDVRootTree(): csKeyPath=%s, csName=%s, csValue=%s"), csKeyPath, csName, csValue); csKeyPath += _T("/Root"); if (csName.Compare(_T("/")) != 0) csKeyPath += csName; // LM/W3SVC/N/Root/iisadmin csKeyPath.MakeUpper(); cmdKey.CreateNode(METADATA_MASTER_ROOT_HANDLE, csKeyPath); if ( (METADATA_HANDLE)cmdKey ) { TCHAR szPath[_MAX_PATH], szUserName[_MAX_PATH]; DWORD dwPerm; memset( (PVOID)szPath, 0, sizeof(szPath)); memset( (PVOID)szUserName, 0, sizeof(szUserName)); SplitVRString(csValue, szPath, szUserName, &dwPerm); cmdKey.SetData( MD_VR_PATH, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, (lstrlen(szPath) + 1) * sizeof(TCHAR), (LPBYTE)szPath); if (szUserName[0] != _T('\0')) { // do have username and path is UNC cmdKey.SetData( MD_VR_USERNAME, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, (lstrlen(szUserName) + 1) * sizeof(TCHAR), (LPBYTE)szUserName); } cmdKey.SetData( MD_ACCESS_PERM, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, 4, (LPBYTE)&dwPerm); cmdKey.Close(); } } int GetMultiStrLen(LPTSTR p) { int c = 0; while (1) { if (*p) { p++; c++; } else { c++; if (*(p+1)) { p++; } else { c++; break; } } } return c; } UINT GetInstNumber(LPCTSTR szMDPath, UINT i) { return 1; } int GetPortNum(LPCTSTR szSvcName) { CString csPath = _T("SYSTEM\\CurrentControlSet\\Control\\Service Provider\\Service Types\\"); csPath += szSvcName; DWORD dwPort = 0; if (lstrcmpi(szSvcName, _T("SMTPSVC")) == 0) dwPort = 25; if (lstrcmpi(szSvcName, _T("NNTPSVC")) == 0) dwPort = 119; CRegKey regKey(HKEY_LOCAL_MACHINE, csPath); if ( (HKEY)regKey ) { regKey.QueryValue(_T("TcpPort"), dwPort); } return (int)dwPort; } void AddVRMapToMD(LPCTSTR szSvcName, CMapStringToOb *pMap) { UINT i = 1; // instance number is in range of 1 - 4 billion UINT n; CString csRoot = _T("LM/"); csRoot += szSvcName; // "LM/*SVC" csRoot.MakeUpper(); TCHAR Buf[10]; CMDKey cmdKey; DebugOutput(_T("AddVRMapToMD(): szSvcName=%s"), szSvcName ); CMapStringToString *pGlobalObj; pMap->Lookup(_T("null"), (CObject*&)pGlobalObj); POSITION pos0 = pMap->GetStartPosition(); while (pos0) { CMapStringToString *pObj; CString csIP; pMap->GetNextAssoc(pos0, csIP, (CObject*&)pObj); TCHAR szIP[256]; lstrcpy(szIP, csIP); if (lstrcmp(szIP, TEXT("null")) == 0) szIP[0] = 0; n = GetInstNumber(csRoot, i); _itot(n, Buf, 10); CString csKeyPath = csRoot; csKeyPath += _T("/"); csKeyPath += Buf; // "LM/*SVC/N" cmdKey.CreateNode(METADATA_MASTER_ROOT_HANDLE, csKeyPath); if ( (METADATA_HANDLE)cmdKey ) { cmdKey.Close(); MDEntry stMDEntry; HGLOBAL hBlock = NULL; hBlock = GlobalAlloc(GPTR, _MAX_PATH * sizeof(TCHAR)); if (hBlock) { stMDEntry.szMDPath = (LPTSTR)(LPCTSTR)csKeyPath; stMDEntry.dwMDIdentifier = MD_SERVER_BINDINGS; // need to be created in iiscnfg.h stMDEntry.dwMDAttributes = METADATA_INHERIT; stMDEntry.dwMDUserType = IIS_MD_UT_SERVER; stMDEntry.dwMDDataType = MULTISZ_METADATA; _stprintf((LPTSTR)hBlock, _T("%s:%d:"), szIP, GetPortNum(szSvcName)); stMDEntry.dwMDDataLen = GetMultiStrLen((LPTSTR)hBlock) * sizeof(TCHAR); stMDEntry.pbMDData = (LPBYTE)hBlock; SetMDEntry(&stMDEntry, NULL); } POSITION pos1 = pObj->GetStartPosition(); while (pos1) { CString csValue; CString csName; pObj->GetNextAssoc(pos1, csName, csValue); CreateMDVRootTree(csKeyPath, csName, csValue); } } if (szIP[0] != 0) { ApplyGlobalToMDVRootTree(csKeyPath, pGlobalObj); } i = n+1; } } void EmptyMap(CMapStringToOb *pMap) { POSITION pos = pMap->GetStartPosition(); while (pos) { CString csKey; CMapStringToString *pObj; pMap->GetNextAssoc(pos, csKey, (CObject*&)pObj); delete pObj; } pMap->RemoveAll(); } void SsyncVRoots(LPCTSTR szSvcName, CMapStringToOb *pMap) { CString csParam = _T("System\\CurrentControlSet\\Services\\"); csParam += szSvcName; csParam += _T("\\Parameters"); CRegKey regParam(HKEY_LOCAL_MACHINE, csParam); if ((HKEY)regParam) { // remove the old virtual roots key regParam.DeleteTree(_T("Virtual Roots")); // recreate the key CRegKey regVRoots(_T("Virtual Roots"), (HKEY)regParam); if ((HKEY)regVRoots) { CMapStringToString *pGlobalObj; pMap->Lookup(_T("null"), (CObject*&)pGlobalObj); POSITION pos = pGlobalObj->GetStartPosition(); while (pos) { CString csValue; CString csName; pGlobalObj->GetNextAssoc(pos, csName, csValue); regVRoots.SetValue(csName, csValue); } } } } void AddVRootsToMD(LPCTSTR szSvcName, BOOL fUpgrade) { CMapStringToOb Map; DebugOutput(_T("AddVRootsToMD(): szSvcName=%s, fUpgrade=%d"), szSvcName, fUpgrade ); if (lstrcmpi(szSvcName, _T("NNTPSVC")) == 0) CreateVRMap(&Map, REG_NNTPVROOTS, theApp.m_csPathNntpRoot, MD_ACCESS_READ | MD_ACCESS_WRITE, fUpgrade); else if (lstrcmpi(szSvcName, _T("SMTPSVC")) == 0) return; AddVRMapToMD(szSvcName, &Map); EmptyMap(&Map); } BOOL MigrateRoutingSourcesToMD(LPCTSTR szSvcName, DWORD dwMDID) { BOOL fResult = TRUE; DWORD ec; HKEY hKey = NULL; CString csKey; CString csRegKey; DWORD dwType; DWORD dwIndex; TCHAR pszEnumName[MAX_PATH]; TCHAR pszData[MAX_PATH]; const int cchMultiSz = 4096; TCHAR pszMultiSz[cchMultiSz+1]; TCHAR *pszTemp = pszMultiSz; DWORD cbEnumName = sizeof(pszEnumName); DWORD cbData = sizeof(pszData); DWORD cchData; DWORD cbMultiSz; DebugOutput(_T("MigrateRoutingSourcesToMD(): szSvcName=%s, dwMDID=%d"), szSvcName, dwMDID); // Initialize the paths csRegKey = REG_SERVICES; csRegKey += _T("\\"); csRegKey += szSvcName; csRegKey += REG_ROUTING_SOURCES_SUFFIX; csKey = _T("LM/"); csKey += szSvcName; csKey += _T("/1/Parameters"); // Initialize the MultiSz pszMultiSz[0] = pszMultiSz[1] = 0; // Open the key ec = RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCTSTR)csRegKey, 0, KEY_ALL_ACCESS, &hKey); if (ec == ERROR_SUCCESS) { dwIndex = 0; do { // do an enum to find out what we should be opening cbEnumName = sizeof(pszEnumName) / sizeof(TCHAR); cbData = sizeof(pszData); ec = RegEnumValue(hKey, dwIndex++, pszEnumName, &cbEnumName, NULL, &dwType, (LPBYTE)pszData, &cbData); if (ec != ERROR_SUCCESS) { // We are done if no more items, error otherwise if (ec != ERROR_NO_MORE_ITEMS) { TCHAR DebugStr[128]; wsprintf(DebugStr, _T("\nError migrating routing sources (%u)\n"), ec); DebugOutput(DebugStr); fResult = FALSE; } break; } // Process this value, basically, append it to the multisz DebugOutput(pszData); cchData = cbData / sizeof(TCHAR); if (pszTemp -pszMultiSz + cchData > cchMultiSz - 1) { DebugOutput(_T("Too many routing sources\n")); fResult = FALSE; break; } lstrcpyn(pszTemp, pszData, cchData); pszTemp += cchData; } while (1); // Add the final terminating NULL; *pszTemp++ = 0; RegCloseKey(hKey); // Now, we have the full MultiSz of routing sources, we can set it to // the Metabase. cbMultiSz = (DWORD)(pszTemp - pszMultiSz); if (cbMultiSz == 1) cbMultiSz++; MDEntry stMDEntry; stMDEntry.szMDPath = (LPTSTR)(LPCTSTR)csKey; stMDEntry.dwMDIdentifier = dwMDID; stMDEntry.dwMDAttributes = 0; stMDEntry.dwMDUserType = IIS_MD_UT_SERVER; stMDEntry.dwMDDataType = MULTISZ_METADATA; stMDEntry.dwMDDataLen = cbMultiSz * sizeof(TCHAR); stMDEntry.pbMDData = (LPBYTE)pszMultiSz; SetMDEntry(&stMDEntry, NULL); } else { DebugOutput(_T("Unable to open registry key: ")); DebugOutput(csRegKey); fResult = FALSE; } DebugOutput(_T("\nFinished Migrating Routing Sources\n")); return(fResult); }