Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

986 lines
28 KiB

#include "stdafx.h"
#include <ole2.h>
#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 "<path>,<username>,<perm>"
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);
}