#include "pch.h" #include #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; }