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.
 
 
 
 
 
 

627 lines
19 KiB

#include "pch.h"
#include <ole2.h>
#include "advpub.h"
#include "sdsutils.h"
#include "migrate.h"
#include "utils.h"
BOOL AppendString(LPSTR *lpBuffer, DWORD *lpdwSize, LPCSTR lpStr)
{
DWORD cbBufferUsed = 0;
DWORD dwNewSize = 0;
LPSTR lpTmp = NULL;
DWORD dwLen = 0;
// Sanity check
if (lpStr == NULL || *lpStr == '\0')
return FALSE;
if (*lpBuffer == NULL)
{
// Allocate the buffer.
*lpdwSize = sizeof(char) * MAX_PATH;
*lpBuffer = (char *) LocalAlloc(LPTR, *lpdwSize);
if (*lpBuffer == NULL)
{
#ifdef DEBUG
SetupLogError("IE6: AppendString memory failure\r\n",LogSevInformation);
#endif
return FALSE;
}
}
dwNewSize = lstrlen(lpStr);
// Get the number of bytes used up, excluding the second terminating NULL (-1)
cbBufferUsed = CountMultiStringBytes((LPCSTR)*lpBuffer) - 1;
if ( (*lpdwSize - cbBufferUsed) < (dwNewSize + 2))
{
LPSTR lpNewBuffer = NULL;
DWORD dwTemp = 0;
// Need to reallocate.
dwTemp = *lpdwSize + (max((sizeof(char) * MAX_PATH), dwNewSize+2));
lpNewBuffer = (char *) LocalAlloc(LPTR,dwTemp);
if ( lpNewBuffer == NULL)
{
#ifdef DEBUG
SetupLogError("IE6: AppendString memory failure\r\n",LogSevInformation);
#endif
return FALSE;
}
else
{
// Rearrange the IN pointer to point to the new block.
// Copy over the old info to the new allocated block.
// +1 for the one that we subtracted above.
CopyMemory(lpNewBuffer, *lpBuffer, cbBufferUsed+1);
// Free the old buffer.
LocalFree(*lpBuffer);
// Point to the new buffer.
*lpBuffer = (char *) lpNewBuffer;
*lpdwSize = dwTemp;
}
}
// Append the new string now.
lpTmp = *lpBuffer + cbBufferUsed;
lstrcpy(lpTmp,lpStr);
// Add the second terminating NULL to it now.
lpTmp += (dwNewSize + 1);
*lpTmp = '\0';
return TRUE;
}
// NOTE NOTE: This function is called during the QueryVersion phase. Hence it needs to be small and fast
// So we just do the check for the presence of the "HKLM\S\M\W\CV\Policies\Ratings" key and don't try to
// verify using MSRating API.
#define REGVAL_KEY "Key"
BOOL IsRatingsEnabled()
{
HKEY hKey;
BOOL bRet = FALSE;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,REGKEY_RATING,KEY_READ,NULL,&hKey) == ERROR_SUCCESS)
{
DWORD dwType;
if (RegQueryValueEx(hKey,REGVAL_KEY,NULL,&dwType, NULL, NULL) == ERROR_SUCCESS
&& dwType == REG_BINARY)
{
#ifdef DEBUG
SetupLogError("IE6: Located RATINGS\Key", LogSevInformation);
#endif
// The Ratings key exists and Password has been set. Means Ratings
// is enabled.
bRet = TRUE;
}
RegCloseKey(hKey);
}
return bRet;
}
// Returns the number of used bytes in a double NULL terminated string, including the two NULLS.
DWORD CountMultiStringBytes (LPCSTR lpString)
{
DWORD cbBytes;
LPSTR lpTmp;
DWORD dwLen;
// Sanity check
if (lpString == NULL)
return 0;
// Get to the double \0 termination of lpBuffer
lpTmp = (LPSTR)lpString;
cbBytes = 1;
while (lpTmp && *lpTmp != '\0')
{
dwLen = lstrlen(lpTmp) + 1;
lpTmp = lpTmp + dwLen;
cbBytes += dwLen;
}
return cbBytes;
}
BOOL PathEndsInFile(LPSTR lpPath, LPCSTR lpFile)
{
LPSTR pTmp = lpPath;
// Sanity check
if (lpPath == NULL || lpFile == NULL)
return FALSE;
#ifdef DEBUG
char szDebug[MAX_PATH*3];
wsprintf(szDebug,"IE5 (PathEndsInFile): %s :: %s \r\n", lpPath, lpFile);
SetupLogError(szDebug,LogSevInformation);
#endif
// Point pTmp to the terminating NULL
pTmp = lpPath + lstrlen(lpPath);
while (*pTmp != '\\' && pTmp != lpPath)
{
pTmp = CharPrev(lpPath, pTmp);
}
pTmp = CharNext(pTmp);
#ifdef DEBUG
wsprintf(szDebug,"IE5 (PathEndsInFile): %s :: %s \r\n", pTmp, lpFile);
SetupLogError(szDebug,LogSevInformation);
#endif
return (lstrcmpi(pTmp, lpFile) == 0);
}
// Helper function to get the path for "Ratings.pol" from the MIGRATE.INF
// The path is returned in a buffer allocated by the function.
// **********************************************************************
// *** NOTE *** : It is the caller function responsibilty to free memory.
// **********************************************************************
// Parameters:
// lpOutBuffer: Ptr to variable to hold the new string allocated.
// User can pass in NULL if only interested in existance of Ratings.pol
// and not the actual path to it.
BOOL GetRatingsPathFromMigInf( LPSTR *lpOutBuffer)
{
INFCONTEXT ic;
HINF hInf;
BOOL bFound = FALSE;
LPSTR lpBuf = NULL;
DWORD dwSize, dwNewSize;
if (lpOutBuffer)
*lpOutBuffer = NULL;
dwSize = MAX_PATH;
lpBuf = (char *) LocalAlloc(LPTR, sizeof(char)*dwSize);
if (lpBuf == NULL)
return FALSE;
// Before calling the migration DLL, Setup sets the CurrentDirectory to
// the directory assigned to that migration DLL. Hence can use this.
//hInf = SetupOpenInfFile(cszMIGRATEINF, NULL, INF_STYLE_WIN4, NULL);
hInf = SetupOpenInfFile(g_szMigrateInf, NULL, INF_STYLE_WIN4, NULL);
if (hInf)
{
#ifdef DEBUG
SetupLogError("IE6: Opened Miginf.inf \r\n", LogSevInformation);
#endif
if (SetupFindFirstLine(hInf,cszMIGINF_MIGRATION_PATHS,NULL,&ic))
{
do
{
dwNewSize = 0;
if( SetupGetLineTextA(&ic,hInf,NULL,NULL,lpBuf,dwSize,&dwNewSize) == 0 && dwNewSize > dwSize)
{ // Need more buffer space
// Free the old buffer space.
LocalFree(lpBuf);
// Try and allocate a new buffer.
dwSize = dwNewSize;
lpBuf = (char *) LocalAlloc(LPTR, sizeof(char)*dwSize);
if (lpBuf == NULL)
{
// Memory Error - break out.
break;
}
if (!SetupGetLineTextA(&ic,hInf,NULL,NULL,lpBuf,dwSize,&dwNewSize))
{
// The bFound check below takes care of LocalFree(lpBuf);
#ifdef DEBUG
SetupLogError("IE6: Error doing SetupGetTextLineA \r\n", LogSevInformation);
#endif
break; // Failure can't help it.
}
}
// So managed to read out the line. Check if it contains .pol
if (PathEndsInFile(lpBuf,cszRATINGSFILE))
{
if (lpOutBuffer)
{
*lpOutBuffer = lpBuf;
}
else
{ // User is not interested in Path. Free the block.
LocalFree(lpBuf);
}
bFound = TRUE;
#ifdef DEBUG
SetupLogError("IE6: Found Ratings.Pol in Migrate.Inf \r\n", LogSevInformation);
#endif
}
}
while (!bFound && SetupFindNextLine(&ic,&ic));
}
SetupCloseInfFile(hInf);
}
if (!bFound)
{
// Free the local buffer.
LocalFree(lpBuf);
}
return bFound;
}
//******************************************************************************
// GenerateFilePaths:
// NOTE NOTE NOTE: The migration DLL remains loaded from the "Initialize9x" phase
// right till the end of the "MigrateSystem9x" phase. And again from "InitializeNT" phase
// right till the end of the "MigrateSystemNT" phase. Hence these paths are usable
// through out.
//*******************************************************************************
void GenerateFilePaths()
{
*g_szMigrateInf = '\0';
*g_szPrivateInf = '\0';
if (g_lpWorkingDir)
{
// generate the path to the Migrate.Inf file
wsprintf(g_szMigrateInf, "%s\\%s", g_lpWorkingDir, cszMIGRATEINF);
#ifdef DEBUG
char szDebug[MAX_PATH];
wsprintf(szDebug,"IE6: g_szMigrateInf: %s \r\n",g_szMigrateInf);
SetupLogError(szDebug,LogSevInformation);
#endif
// generate the path to the Private.Inf file
wsprintf(g_szPrivateInf, "%s\\%s", g_lpWorkingDir, cszPRIVATEINF);
#ifdef DEBUG
wsprintf(szDebug,"IE6: g_szPrivateInf: %s \r\n",g_szPrivateInf);
SetupLogError(szDebug,LogSevInformation);
#endif
}
}
#define IE_KEY "Software\\Microsoft\\Internet Explorer"
#define VERSION_KEY "Version"
BOOL NeedToMigrateIE()
{
BOOL bRet = FALSE;
char szPath[MAX_PATH];
DWORD dwInstalledVer, dwInstalledBuild;
// Currently, the only thing we are interested in are the Ratings settings.
if (IsRatingsEnabled())
{
// Append the "ratings.pol" filename to the list of files needed.
// NOTE: AppendString allocates memory for the 1st parameter. User
// must remember to free it.
bRet |= AppendString(&g_lpNameBuf, &g_dwNameBufSize, cszRATINGSFILE);
}
if (!bRet)
{
GetSystemDirectory(szPath, sizeof(szPath));
AddPath(szPath, "shdocvw.dll");
GetVersionFromFile(szPath, &dwInstalledVer, &dwInstalledBuild, TRUE);
// are running with IE5.5 installed.
bRet = (dwInstalledVer == 0x00050032);
}
// Can add other modules that need to be migrated over here.
// use bRet |= (....) so that you don't stomp previous bRet settings.
return bRet;
}
void MyDelRegTree(HKEY hRoot, LPSTR szSubKey)
{
char szName[MAX_PATH];
DWORD dwIndex;
DWORD dwNameSize;
HKEY hKey;
dwIndex = 0;
dwNameSize = sizeof(szName);
if (RegOpenKeyEx(hRoot, szSubKey, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
{
while (RegEnumKey(hKey, dwIndex, szName, dwNameSize) == ERROR_SUCCESS)
{
MyDelRegTree(hKey,szName);
// dwIndex++; DONT INCR. SINCE WE HAVE DELETED A SUBKEY.
dwNameSize = sizeof(szName);
}
RegCloseKey(hKey);
//Finally delete the named subkey supplied above.
RegDeleteKey(hRoot, szSubKey);
}
}
// Recursively Enum values and subkey and copy them over. And then
// delete all subkeys of the Source key.
void MoveRegBranch(HKEY hFromKey, HKEY hToKey)
{
char szName[MAX_PATH];
char szValue[MAX_PATH];
DWORD dwNameSize;
DWORD dwValueSize;
DWORD dwType;
DWORD dwIndex;
// Enumerate all the values here and copy them over to the right
// location.
dwIndex = 0;
dwNameSize = sizeof(szName);
dwValueSize = sizeof(szValue);
while (RegEnumValue(hFromKey,dwIndex, szName, &dwNameSize, NULL,
&dwType, (LPBYTE)szValue, &dwValueSize) == ERROR_SUCCESS)
{
RegSetValueEx(hToKey,szName,0,dwType,(LPBYTE)szValue, dwValueSize);
// Get ready for the next round.
dwIndex++;
dwNameSize = sizeof(szName);
dwValueSize = sizeof(szValue);
}
// Next Enum all the subkeys under source and move them over.
dwIndex = 0;
dwNameSize = sizeof(szName);
while (RegEnumKey(hFromKey, dwIndex, szName, dwNameSize) == ERROR_SUCCESS)
{
HKEY hFromSubKey = NULL;
HKEY hToSubKey = NULL;
// Open this SubKey that we enumerated.
if (RegOpenKeyEx(hFromKey, szName, 0, KEY_ALL_ACCESS, &hFromSubKey) == ERROR_SUCCESS)
{
// Create the destination subkey.
if (RegCreateKeyEx(hToKey, szName, 0, NULL,REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS, NULL, &hToSubKey, NULL) == ERROR_SUCCESS)
{
// Move the subkeys...
MoveRegBranch(hFromSubKey, hToSubKey);
RegCloseKey(hToSubKey);
}
RegCloseKey(hFromSubKey);
}
// Get ready for the next round
dwIndex++;
dwNameSize = sizeof(szName);
}
// Now Delete all the SubKeys. The above recursive call ensures that
// the Subkeys are one-level deep and hence deletable.
dwIndex = 0;
dwNameSize = sizeof(szName);
while (RegEnumKey(hFromKey, dwIndex, szName, dwNameSize) == ERROR_SUCCESS)
{
RegDeleteKey(hFromKey,szName);
// dwIndex++; DONT INCR. SINCE WE HAVE DELETED A SUBKEY.
dwNameSize = sizeof(szName);
}
}
#define REGKEY_DEFAULT ".Default"
#define REGKEY_MIGRATE_HIVE "Software\\Microsoft\\Policies\\Users"
#define REGKEY_MIGRATE_PICSRULES "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Ratings\\PICSRules"
#define REGKEY_RATING_PICSRULES "PICSRules"
BOOL UpgradeRatings()
{
// Real Ratings locations...
// HKLM\S\M\W\CV\Policies\Ratings (called RATING)
// Open HKLM\software\Microsoft\Policies\Users.. This is where NT Setup puts
// the migrated Ratings HIVE.
// Users [FileNamex] gets copied to RATING [FileNamex]
// NOTE: Need to take care of SYSTEM/SYSTEM32.
// Users\.Default branch gets moved to RATING
// Users\S\M\W\CV\Policies\Ratings\PICSRules branch gets moved to RATING.
HKEY hRealRatings = NULL;
HKEY hRealDefault = NULL;
HKEY hRealPicsRules = NULL;
HKEY hMigratedRoot = NULL;
BOOL bRet = FALSE;
// Open the RegKey to the real location of Ratings.
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_RATING, 0, KEY_ALL_ACCESS,
&hRealRatings) != ERROR_SUCCESS)
goto Done;
// Open the RegKey to the real location of .Default
if (RegCreateKeyEx(hRealRatings, REGKEY_DEFAULT, 0,
NULL,REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hRealDefault, NULL) != ERROR_SUCCESS)
goto Done;
// Open the RegKey to the real location of PICSRules
if (RegCreateKeyEx(hRealRatings, REGKEY_RATING_PICSRULES, 0,
NULL,REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hRealPicsRules, NULL) != ERROR_SUCCESS)
goto Done;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_MIGRATE_HIVE, 0, KEY_ALL_ACCESS, &hMigratedRoot) == ERROR_SUCCESS)
{
HKEY hMigrateSubKey = NULL;
char szName[MAX_PATH];
char szValue[MAX_PATH];
DWORD dwNameSize;
DWORD dwValueSize;
DWORD dwType;
char szNewPath[MAX_PATH];
DWORD dwNewPathSize;
DWORD dwIndex;
// Enumerate all the values here and copy them over to the right
// location. Make sure to replace 'System' with 'System32'
dwIndex = 0;
dwNameSize = sizeof(szName);
dwValueSize = sizeof(szValue);
while (RegEnumValue(hMigratedRoot,dwIndex, szName, &dwNameSize, NULL,
&dwType, (LPBYTE)szValue, &dwValueSize) == ERROR_SUCCESS)
{
// Munge the Value and replace 'System' with System32.
// Return value includes the terminating NULL char, which is
// need by the RegSetValueEx API.
dwNewPathSize = GetFixedPath(szNewPath, MAX_PATH, szValue);
// Set the correct Ratings setting.
RegSetValueEx(hRealRatings,szName,0,dwType,(LPBYTE)szNewPath, dwNewPathSize);
// Get ready for the next round.
dwIndex++;
dwNameSize = sizeof(szName);
dwValueSize = sizeof(szValue);
}
// Now grab Users\.Default and move it to the right location.
if (RegOpenKeyEx(hMigratedRoot, REGKEY_DEFAULT, 0, KEY_ALL_ACCESS, &hMigrateSubKey) == ERROR_SUCCESS)
{
MoveRegBranch(hMigrateSubKey,hRealDefault);
RegCloseKey(hMigrateSubKey);
}
// Now grab Users\...\PICSRules and move it to the right location.
if (RegOpenKeyEx(hMigratedRoot, REGKEY_MIGRATE_PICSRULES, 0, KEY_ALL_ACCESS, &hMigrateSubKey) == ERROR_SUCCESS)
{
MoveRegBranch(hMigrateSubKey,hRealPicsRules);
RegCloseKey(hMigrateSubKey);
}
RegCloseKey(hMigratedRoot);
bRet = TRUE;
}
// Now clean the Migrated Hive.
MyDelRegTree(HKEY_LOCAL_MACHINE, REGKEY_MIGRATE_HIVE);
Done:
if (hRealRatings)
RegCloseKey(hRealRatings);
if (hRealDefault)
RegCloseKey(hRealDefault);
if (hRealPicsRules)
RegCloseKey(hRealPicsRules);
return bRet;
}
// Returns the size of NewPath including the terminating NULL.
DWORD GetFixedPath(LPSTR lpBuf, DWORD dwSize, LPCSTR lpPath)
{
char lpLocalCopy[MAX_PATH], szTemp[5];
char chSave;
DWORD dwCount = 0;
LPSTR pTmp, pTmp2;
if (lpBuf == NULL || lpPath == NULL)
return 0;
// Create a local copy to party on.
lstrcpy(lpLocalCopy, lpPath);
pTmp = lpLocalCopy;
*lpBuf = '\0';
while (*pTmp && dwCount < dwSize)
{
pTmp2 = pTmp;
while(*pTmp2 && *pTmp2 != '\\')
pTmp2 = CharNext(pTmp2);
chSave = *pTmp2;
*pTmp2 = '\0';
if (lstrcmpi(pTmp,"system")==0)
{
dwCount += 8;
if (dwSize <= dwCount)
{ //Error
*lpBuf = '\0';
return 0;
}
lstrcat(lpBuf,"system32");
}
else
{
dwCount += lstrlen(pTmp);
if (dwSize <= dwCount)
{ // Error
*lpBuf = '\0';
return 0;
}
lstrcat(lpBuf,pTmp);
}
// Append the saved character to Output buffer also.
wsprintf(szTemp,"%c",chSave);
dwCount += lstrlen(szTemp);
if (dwSize <= dwCount)
{ // Error
*lpBuf = '\0';
return 0;
}
lstrcat(lpBuf, szTemp);
*pTmp2 = chSave;
pTmp = CharNext(pTmp2);
}
return dwCount;
}
LPWSTR MakeWideStrFromAnsi(LPSTR psz)
{
LPWSTR pwsz;
int i;
// arg checking.
//
if (!psz)
return NULL;
// compute the length of the required BSTR
//
i = MultiByteToWideChar(CP_ACP, 0, psz, -1, NULL, 0);
if (i <= 0) return NULL;
// allocate the widestr
//
pwsz = (LPWSTR) CoTaskMemAlloc(i * sizeof(WCHAR));
if (!pwsz)
return NULL;
MultiByteToWideChar(CP_ACP, 0, psz, -1, pwsz, i);
pwsz[i - 1] = 0;
return pwsz;
}