Windows2003-3790/inetcore/setup/active/ntmigrat/migrate.cpp
2020-09-30 16:53:55 +02:00

569 lines
18 KiB
C++

// This is the migration dll for NT5 upgrades.
// As per the Migration Extension Interface of NT5 Setup, this DLL needs to
// implement the folowing six functions:
// QueryVersion
// Initialize9x
// MigrateUser9x (called once for every user)
// MigrateSystem9x
// InitializeNT
// MigrateUserNT (called once for every user)
// MigrateSystemNT
//
// Written : ShabbirS (5/7/99)
// Revision:
//
#include "pch.h"
#include <ole2.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <excppkg.h>
#ifdef __cplusplus
}
#endif /* __cplusplus */
#include "sdsutils.h"
#include "advpub.h"
#include "migrate.h"
#include "utils.h"
#include "resource.h"
// Constants:
#define CP_USASCII 1252
#define END_OF_CODEPAGES -1
// Globals that are passed back to Setup.
//////////////////////////////////////////
// Vendor Info:
VENDORINFO g_VendorInfo = { "Microsoft Corporation",
" ",
"http://www.microsoft.com/support",
"Please contact Microsoft Technical Support for assistance with this problem. "};
// Product ID:
char g_cszProductID[] = "Microsoft Internet Explorer";
// Version number of this Migration Dll
UINT g_uVersion = 3;
// Array of integers specifying the CodePages we use. (Terminated with -1)
int g_rCodePages[] = {CP_USASCII, END_OF_CODEPAGES};
// Multi-SZ ie double Null terminated list of strings.
char *g_lpNameBuf = NULL;
DWORD g_dwNameBufSize = 0;
char *g_lpWorkingDir = NULL;
char *g_lpSourceDirs = NULL;
char *g_lpMediaDir = NULL;
char g_szMigrateInf[MAX_PATH];
char g_szPrivateInf[MAX_PATH];
LONG
CALLBACK
QueryVersion( OUT LPCSTR *ProductID,
OUT LPUINT DllVersion,
OUT LPINT *CodePageArray, OPTIONAL
OUT LPCSTR *ExeNameBuf, OPTIONAL
OUT PVENDORINFO *VendorInfo
)
{
// NOTE: There is timing restriction on the return from this function
// So keep this as short and sweet as possible.
VENDORINFO myVendorInfo;
LONG lRet = ERROR_SUCCESS;
AppendString(&g_lpNameBuf, &g_dwNameBufSize, cszRATINGSFILE);
AppendString(&g_lpNameBuf, &g_dwNameBufSize, cszIEXPLOREFILE);
// Pass back to Setup the product name.
*ProductID = g_cszProductID;
// Pass back to Setup the version number of this DLL.
*DllVersion = g_uVersion;
// We will use English messages only but don't specify a code page or
// the migration dll won't run on alternate code pages.
*CodePageArray = NULL;
// Pass back to Setup the list of files we want detected on this system.
*ExeNameBuf = g_lpNameBuf;
// Pass back the VendorInfo.
if (LoadString(g_hInstance, IDS_COMPANY, myVendorInfo.CompanyName, sizeof(myVendorInfo.CompanyName)) == 0)
lstrcpy(myVendorInfo.CompanyName, "Microsoft Corporation");
if (LoadString(g_hInstance, IDS_SUPPORTNUMBER, myVendorInfo.SupportNumber, sizeof(myVendorInfo.SupportNumber)) == 0)
lstrcpy(myVendorInfo.SupportNumber, " ");
if (LoadString(g_hInstance, IDS_SUPPORTURL, myVendorInfo.SupportUrl, sizeof(myVendorInfo.SupportUrl)) == 0)
lstrcpy(myVendorInfo.SupportUrl, "http://www.microsoft.com/support");
if (LoadString(g_hInstance, IDS_INSTRUCTIONS, myVendorInfo.InstructionsToUser, sizeof(myVendorInfo.InstructionsToUser)) == 0)
lstrcpy(myVendorInfo.InstructionsToUser, "Please contact Microsoft Technical Support for assistance with this problem. ");
*VendorInfo = &myVendorInfo;
#ifdef DEBUG
char szDebugMsg[MAX_PATH*3];
wsprintf(szDebugMsg,"IE6:ProductID: %s \r\n", *ProductID);
SetupLogError(szDebugMsg, LogSevInformation);
#endif
return lRet;
}
LONG
CALLBACK
Initialize9x( IN LPCSTR WorkingDir,
IN LPCSTR SourceDirs,
IN LPCSTR MediaDirs
)
{
// Called by NT Setup if QUeryVersion returned SUCCESS
// At this point we have been relocated to some specific location
// on the local drive by the Setup process.
INT len;
// Keep track of our new location (ie. the Working Directory).
// NT Setup will create the "MIGRATE.INF" file in this dir and use that
// to exchange info with us.
// Also we can use this Dir for saving our private stuff. NT Setup will
// ensure this folder stays till end of NT Migration. After that it will
// be cleaned.
len = lstrlen(WorkingDir) + 1;
g_lpWorkingDir = (char *) LocalAlloc(LPTR,sizeof(char)*len);
if (!g_lpWorkingDir)
{
return GetLastError();
}
CopyMemory(g_lpWorkingDir, WorkingDir, len);
len = lstrlen(MediaDirs) + 1;
g_lpMediaDir = (char *) LocalAlloc(LPTR,sizeof(char)*len);
if (!g_lpMediaDir)
{
return GetLastError();
}
CopyMemory(g_lpMediaDir, MediaDirs, len);
// Also keep track of the NT installation files path (ie Sources Dir).
// NOTE: Right now we don't need it, so skip doing it.
// Generate the path names to Migrate.inf and the private files
// (private.inf) that we need
GenerateFilePaths();
// If NT Setup has succeeded in getting path to Ratings.Pol, it implies
// Ratings information exists. Enable our private marker to do the right
// thing in MigrateSystemNT phase.
if (GetRatingsPathFromMigInf(NULL))
{ // Put a marker in PRIVATE.INF so that MigrateSystemNT phase knows
// that it has to munge the Rating.
// Private.Inf does not exist at this point so why this check!!!
// if (GetFileAttributes(g_szPrivateInf) != 0xffffffff)
WritePrivateProfileString(cszIEPRIVATE, cszRATINGS, "Yes", g_szPrivateInf);
// Flush the cached entries to disk.
WritePrivateProfileString(NULL,NULL,NULL,g_szPrivateInf);
#ifdef DEBUG
SetupLogError("IE6: Created PRIVATE.INF\r\n", LogSevInformation);
#endif
}
return ERROR_SUCCESS;
}
LONG
CALLBACK
MigrateUser9x( IN HWND ParentWnd,
IN LPCSTR UnattendFile,
IN HKEY UserRegKey,
IN LPCSTR UserName,
LPVOID Reserved
)
{
// This function is called by NT Setup for each user.
// Currently for the Ratings scenario, we don't need any PerUser action.
#ifdef DEBUG
SetupLogError("IE6: Skipping MigrateUser9x \r\n", LogSevInformation);
#endif
return ERROR_SUCCESS;
}
LONG
CALLBACK
MigrateSystem9x( IN HWND ParentWnd,
IN LPCSTR AnswerFile,
LPVOID Reserved
)
{
// This function is called once by NT Setup to let us save System wide info.
//
// we are writing the "incompatibility report here if IE5.5 is installed and
// the user does not have the full migration pack installed.
//
char szCab[MAX_PATH];
WORD wVer[4];
char szBuf[MAX_PATH];
// Check if we have the full exception pack which re-installs IE5.5
// NOTE: g_lpMediaDir is the location where the migration dll was installed/registered
// This is the same location where the INF is.
lstrcpy(szCab, g_lpMediaDir);
AddPath(szCab, "ieexinst.inf");
if (GetPrivateProfileString("Info", "Version", "", szBuf , MAX_PATH, szCab) != 0)
{
// Convert version
ConvertVersionString( szBuf, wVer, '.' );
if ((wVer[0] == 5) && (wVer[1] == 50))
{
// We don't have the full exception pack.
// generate the "incompatibility report"
// g_szMigrateInf
lstrcpy(szBuf, g_lpMediaDir);
GetParentDir(szBuf);
if (LoadString(g_hInstance, IDS_INCOMPAT_MSG, szCab, sizeof(szCab)))
{
WritePrivateProfileString(cszMIGINF_INCOMPAT_MSG, g_cszProductID, szCab, g_szMigrateInf);
WritePrivateProfileString(g_cszProductID, szBuf, "Report", g_szMigrateInf);
WritePrivateProfileString(NULL,NULL,NULL,g_szMigrateInf);
}
}
}
WritePrivateProfileString(cszMIGINF_HANDLED, "HKLM\\Software\\Microsoft\\Active Setup\\ClsidFeature", "Registry", g_szMigrateInf);
WritePrivateProfileString(cszMIGINF_HANDLED, "HKLM\\Software\\Microsoft\\Active Setup\\FeatureComponentID", "Registry", g_szMigrateInf);
WritePrivateProfileString(cszMIGINF_HANDLED, "HKLM\\Software\\Microsoft\\Active Setup\\MimeFeature", "Registry", g_szMigrateInf);
WritePrivateProfileString(NULL,NULL,NULL,g_szMigrateInf);
#ifdef DEBUG
SetupLogError("IE6: MigrateSystem9x \r\n", LogSevInformation);
#endif
return ERROR_SUCCESS;
}
LONG
CALLBACK
InitializeNT (
IN LPCWSTR WorkingDirectory,
IN LPCWSTR SourceDirectories,
LPVOID Reserved
)
{
INT Length;
LPCWSTR p;
//
// Save our working directory and source directory. We
// convert UNICODE to ANSI, and we use the system code page.
//
//
// Compute length of source directories
//
p = SourceDirectories;
while (*p) {
p = wcschr (p, 0) + 1;
}
p++;
Length = (p - SourceDirectories) / sizeof (WCHAR);
//
// Convert the directories from UNICODE to DBCS. This DLL is
// compiled in ANSI.
//
g_lpWorkingDir = (LPSTR) LocalAlloc(LPTR, MAX_PATH);
if (!g_lpWorkingDir) {
return GetLastError();
}
WideCharToMultiByte (
CP_ACP,
0,
WorkingDirectory,
-1,
g_lpWorkingDir,
MAX_PATH,
NULL,
NULL
);
// Also save the SourceDirectories that points to the Windows
// NT media (i.e. e:\i386) and optional directories specified on
// the WINNT32 command line. Not used currently, so skip.
// Now generate the derived file names
GenerateFilePaths();
#ifdef DEBUG
SetupLogError("IE6: Done InitializeNT \r\n", LogSevInformation);
#endif
return ERROR_SUCCESS;
}
LONG
CALLBACK
MigrateUserNT (
IN HINF UnattendInfHandle,
IN HKEY UserRegKey,
IN LPCWSTR UserName,
LPVOID Reserved
)
{
// No per-user settings for Ratings upgrade.
#ifdef DEBUG
SetupLogError("IE6: Skipping MigrateUserNT \r\n", LogSevInformation);
#endif
return ERROR_SUCCESS;
}
#define PACKAGE_GUID "{89820200-ECBD-11cf-8B85-00AA005B4383}"
#define PACKAGE_DIRECTORY "%windir%\\RegisteredPackages\\"
LONG
CALLBACK
MigrateSystemNT (
IN HINF UnattendInfHandle,
LPVOID Reserved
)
{ // NOTE: This phase MUST finish in 60 seconds or will be terminated.
// Check if our PRIVATE.INF exists and perform relevant actions based on its contents.
CHAR szBuffer[3+10];
if (GetFileAttributes(g_szPrivateInf) != 0xffffffff)
{
GetPrivateProfileString(cszIEPRIVATE, cszRATINGS, "", szBuffer, sizeof(szBuffer), g_szPrivateInf);
if (lstrcmpi(szBuffer,"Yes")==0)
{
UpgradeRatings();
SetupLogError("IE Migration: Upgraded Ratings info.\r\n", LogSevInformation);
}
}
else
{
SetupLogError("IE Migration: No Rating migration. Private.Inf does not exist.\r\n",LogSevInformation);
}
#if 0
// Do the W2K IE5.5 migration work here.
// 1. Copy all files from the IE location to the registered migration pack location
// 2. Register the migration pack
SETUP_OS_COMPONENT_DATA ComponentData,cd;
SETUP_OS_EXCEPTION_DATA ExceptionData,ed;
GUID MyGuid;
PWSTR GuidString;
PSTR t;
BOOL bContinue = FALSE;
WCHAR szMsg[1024];
char szPath[MAX_PATH];
LPWSTR pszwPath;
WORD wVer[4];
char szBuf[MAX_PATH];
char szInf[MAX_PATH];
char szGUID[MAX_PATH];
char szCab[MAX_PATH];
char szDir[MAX_PATH];
#ifdef DEBUG
char sz[1024];
#endif
HRESULT hr;
char szCabs[1024];
LPSTR pCab = NULL;
// Get the INF which is installed in the W2K folder.
// This INF tells us the info about the IE exception pack.
// g_lpWorkingDir contains all fiels and sub folders which are in the same place
// as the registerd migration dll. Since we install the files in the same folder, we can use it.
lstrcpy(szInf, g_lpWorkingDir);
AddPath(szInf, "ieexinst.inf");
#ifdef DEBUG
wsprintf(sz, "IE exception INF :%s:\r\n", szInf);
SetupLogError(sz,LogSevInformation);
#endif
if (GetFileAttributes(szInf) != (DWORD)-1)
{
// Get the GUID
if (GetPrivateProfileString("Info", "ComponentId", "", szGUID, sizeof(szGUID), szInf) == 0)
lstrcpy(szGUID, PACKAGE_GUID);
ExpandEnvironmentStrings( PACKAGE_DIRECTORY, szDir, sizeof(szDir));
if (GetFileAttributes(szDir) == (DWORD)-1)
CreateDirectory( szDir, NULL );
AddPath(szDir, szGUID);
if (GetFileAttributes(szDir) == (DWORD)-1)
CreateDirectory( szDir, NULL );
// BUGBUG:
// The extraction of the CAB file(s) should be done after we found out
// If the user has already a newer exception pack registered.
// This check is done below. Could not change it anymore, because of
// time constrains. Found this in the code review
//
// Extract all CABs into the package fodler.
#ifdef DEBUG
wsprintf(sz, "cab folder :%s:\r\n", g_lpWorkingDir);
SetupLogError(sz,LogSevInformation);
wsprintf(sz, "extract folder :%s:\r\n", szDir);
SetupLogError(sz,LogSevInformation);
#endif
if (GetPrivateProfileSection("Cab.List", szCabs, sizeof(szCabs), szInf) != 0)
{
pCab = szCabs;
while (*pCab != '\0')
{
lstrcpy(szCab, g_lpWorkingDir);
AddPath(szCab, pCab);
#ifdef DEBUG
wsprintf(sz, "Extract :%s: to :%s:\r\n", szCab, szDir);
SetupLogError(sz,LogSevInformation);
#endif
hr = ExtractFiles(szCab, szDir, 0, NULL, NULL, 0);
pCab += (lstrlen(pCab) + 1);
}
bContinue = TRUE;
}
}
if (bContinue)
{
if (GetPrivateProfileString("Info", "Version", "", szBuf , MAX_PATH, szInf) != 0)
{
// Convert version
ConvertVersionString( szBuf, wVer, '.' );
ComponentData.SizeOfStruct = sizeof(SETUP_OS_COMPONENT_DATA);
ExceptionData.SizeOfStruct = sizeof(SETUP_OS_EXCEPTION_DATA);
pszwPath = MakeWideStrFromAnsi(szGUID);
if (pszwPath)
{
IIDFromString( pszwPath, &MyGuid);
CoTaskMemFree(pszwPath);
if (SetupQueryRegisteredOsComponent(
&MyGuid,
&ComponentData,
&ExceptionData))
{
if ((ComponentData.VersionMajor < wVer[0]) ||
((ComponentData.VersionMajor == wVer[0]) && (ComponentData.VersionMinor <= wVer[1])) )
{
bContinue = SetupUnRegisterOsComponent(&MyGuid);
SetupLogError("IE6: SetupUnRegisterOsComponent.\r\n",LogSevInformation);
}
// BUGBUG: Missing the below else. Found in code review
// else
// bContinue = FALSE;
}
}
else
bContinue = FALSE;
}
else
bContinue = FALSE;
}
if (bContinue)
{
SetupLogError("IE6: Preparing SetupRegisterOsComponent.\r\n",LogSevInformation);
ExpandEnvironmentStrings( PACKAGE_DIRECTORY, szPath, sizeof(szPath));
AddPath( szPath, szGUID );
ComponentData.VersionMajor = wVer[0];
ComponentData.VersionMinor = wVer[1];
RtlMoveMemory(&ComponentData.ComponentGuid, &MyGuid,sizeof(GUID));
t = szPath + lstrlen(szPath);
*t = '\0';
GetPrivateProfileString("Info", "InfFile", "", szBuf, MAX_PATH, szInf);
AddPath( szPath, szBuf);
pszwPath = MakeWideStrFromAnsi(szPath);
if (pszwPath)
{
wcscpy(ExceptionData.ExceptionInfName, pszwPath);
CoTaskMemFree(pszwPath);
}
*t = '\0';
GetPrivateProfileString("Info", "CatalogFile", "", szBuf, MAX_PATH, szInf);
AddPath( szPath, szBuf);
pszwPath = MakeWideStrFromAnsi(szPath);
if (pszwPath)
{
wcscpy(ExceptionData.CatalogFileName, pszwPath);
CoTaskMemFree(pszwPath);
}
LoadString(g_hInstance, IDS_FRIENDLYNAME, szPath, sizeof(szPath));
pszwPath = MakeWideStrFromAnsi(szPath);
if (pszwPath)
{
wcscpy(ComponentData.FriendlyName, pszwPath);
CoTaskMemFree(pszwPath);
}
wsprintfW(szMsg, L"IE6: ExceptionData\r\n\tInf: %ws\r\n\tCatalog: %ws\r\n",
ExceptionData.ExceptionInfName,ExceptionData.CatalogFileName);
SetupLogErrorW(szMsg,LogSevInformation);
if (SetupRegisterOsComponent(&ComponentData, &ExceptionData))
{
SetupLogError("IE6: SetupRegisterOsComponent succeeded.\r\n",LogSevInformation);
#ifdef DEBUG
cd.SizeOfStruct = sizeof(SETUP_OS_COMPONENT_DATA);
ed.SizeOfStruct = sizeof(SETUP_OS_EXCEPTION_DATA);
if (SetupQueryRegisteredOsComponent( &MyGuid, &cd, &ed))
{
StringFromIID(cd.ComponentGuid, &GuidString);
wsprintfW(szMsg, L"IE6: Component Data\r\n\tName: %ws\r\n\tGuid: %ws\r\n\tVersionMajor: %d\r\n\tVersionMinor: %d\r\n",
cd.FriendlyName,GuidString,cd.VersionMajor,cd.VersionMinor);
SetupLogErrorW(szMsg,LogSevInformation);
wsprintfW(szMsg, L"IE6: ExceptionData\r\n\tInf: %ws\r\n\tCatalog: %ws\r\n",
ed.ExceptionInfName,ed.CatalogFileName);
SetupLogErrorW(szMsg,LogSevInformation);
CoTaskMemFree( GuidString );
}
#endif
}
}
// In future, check for other settings here and perform necessary upgrade actions.
#endif
#ifdef DEBUG
SetupLogError("IE6: Done MigrateSystemNT \r\n", LogSevInformation);
#endif
return ERROR_SUCCESS;
}