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.
 
 
 
 
 
 

486 lines
14 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation
//
// File: migrate.cpp
// xiaoyuw @ 2001/09
//
//--------------------------------------------------------------------------
#include <stdio.h>
#include <windows.h>
#include <setupapi.h>
#include <shlwapi.h>
// migration DLL version information
typedef struct {
CHAR CompanyName[256];
CHAR SupportNumber[256];
CHAR SupportUrl[256];
CHAR InstructionsToUser[1024];
} VENDORINFO, *PVENDORINFO;
typedef struct {
SIZE_T Size;
PCSTR StaticProductIdentifier;
UINT DllVersion;
PINT CodePageArray;
UINT SourceOs;
UINT TargetOs;
PCSTR * NeededFileList;
PVENDORINFO VendorInfo;
} MIGRATIONINFOA, *PMIGRATIONINFOA;
typedef enum {
OS_WINDOWS9X = 0,
OS_WINDOWSNT4X = 1,
OS_WINDOWS2000 = 2,
OS_WINDOWSWHISTLER = 3
} OS_TYPES, *POS_TYPES;
PMIGRATIONINFOA g_MigrationInfo = NULL;
const char g_szProductId[] = "Microsoft MSI Migration DLL v2.0";
VENDORINFO g_VendorInfo = { "Microsoft", "", "", "" };
// registry keys of note
const char szSideBySideKeyName[] = "Software\\Microsoft\\Windows\\CurrentVersion\\SideBySide";
const char szMigrateStatusKeyName[] = "Software\\Microsoft\\Windows\\CurrentVersion\\SideBySide\\MigrateMsiInstalledAssembly";
const char szRunOnceValueName[] = "Cleanup Msi 2.0 Migration";
const char szRunOnceSetupRegKey[]= "Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce";
const char szRunOnceValueCommandLine[]="reg.exe delete HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\SideBySide\\MigrateMsiInstalledAssembly /f";
typedef HRESULT (__stdcall *LPDLLGETVERSION)(DLLVERSIONINFO *);
typedef enum _FUSION_MSI_OS_VERSION
{
E_OS_UNKNOWN,
E_WIN95,
E_WIN_ME,
E_WIN_NT,
E_WIN98,
E_WIN2K,
E_WHISTLER,
E_WIN32_OTHERS
} FUSION_MSI_OS_VERSION;
typedef enum _FUSION_MSI_OS_TYPE
{
E_PERSONAL,
E_PROFESSIONAL,
E_DATA_CENTER,
E_STD_SERVER,
E_ADV_SERVER,
E_WORKSTATION,
E_SERVER
} FUSION_MSI_OS_TYPE;
HRESULT SxspGetOSVersion(FUSION_MSI_OS_VERSION & osv)
{
HRESULT hr = S_OK;
OSVERSIONINFO osvi;
BOOL bOsVersionInfoEx;
osv = E_OS_UNKNOWN;
if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
{
// If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO.
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
if (!GetVersionEx((OSVERSIONINFO *) &osvi))
{
hr = HRESULT_FROM_WIN32(::GetLastError());
goto Exit;
}
}
switch (osvi.dwPlatformId)
{
case VER_PLATFORM_WIN32_NT:
if ( osvi.dwMajorVersion <= 4 )
osv = E_WIN_NT;
else if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 )
osv = E_WIN2K;
else if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 )
osv = E_WHISTLER;
case VER_PLATFORM_WIN32_WINDOWS:
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
osv = E_WIN95;
else if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
osv = E_WIN98;
else if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
osv = E_WIN_ME;
break;
case VER_PLATFORM_WIN32s:
osv = E_WIN32_OTHERS;
break;
}
Exit:
return hr;
}
BOOL IsMigrationDone()
{
HKEY hk = NULL;
LONG iRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szMigrateStatusKeyName, 0, KEY_EXECUTE, &hk);
RegCloseKey(hk);
if (iRet == ERROR_SUCCESS) // the migration is done already
return TRUE; // no further migration
else
return FALSE;
}
/*
BOOL IsW9xOrNT(FUSION_MSI_OS_VERSION &osv)
{
osv = E_OS_UNKNOWN;
if (SUCCEEDED(SxspGetOSVersion(osv)))
{
if ((osv != E_WIN98) && (osv != E_WIN2K))
{
return FALSE;
}
}
else
{
return FALSE;
}
return TRUE;
}
*/
/*
BOOL IsMsi20Installed()
{
BOOL fInstalled = FALSE;
HMODULE hMSI = ::LoadLibraryA("MSI");
if (hMSI)
{
LPDLLGETVERSION pfVersion = (LPDLLGETVERSION)::GetProcAddress(hMSI, "DllGetVersion");
if (pfVersion)
{
// MSI detected. Determine version.
DLLVERSIONINFO VersionInfo;
VersionInfo.cbSize = sizeof(DLLVERSIONINFO);
(*pfVersion)(&VersionInfo);
if (VersionInfo.dwMajorVersion < 2)
{
fInstalled = FALSE; // we only deal with Winfuse Assemblise installed using msi2.0.
}
else
{
fInstalled = TRUE;
}
}
::FreeLibrary(hMSI);
}
return fInstalled;
}
*/
void DbgPrintMessageBox(PCSTR pszFunc)
{
#if DBG
CHAR str[256];
sprintf(str, "In %s of migrate.dll", pszFunc);
MessageBox(NULL, str, "migrate", MB_OK);
#endif
}
typedef HRESULT (_stdcall * PFN_MigrateFusionWin32AssemblyToXP)(PCWSTR pszInstallerDir);
LONG MigrateMSIInstalledWin32Assembly()
{
LONG lResult = ERROR_SUCCESS;
PFN_MigrateFusionWin32AssemblyToXP pfMigrateSystemNT;
HMODULE hNTMig = ::LoadLibraryA("fusemig");
if (!hNTMig)
{
// always return success. Its too late for any meaningful
// error recovery
return ERROR_SUCCESS;
}
pfMigrateSystemNT = (PFN_MigrateFusionWin32AssemblyToXP)GetProcAddress(hNTMig, "MsiInstallerDirectoryDirWalk");
if (pfMigrateSystemNT)
{
lResult = (pfMigrateSystemNT)(NULL) & 0X0000FFFF;
}
FreeLibrary(hNTMig);
//
// set the RegKey about the work is done already
//
{
DWORD dwDisposition = 0;
HKEY hkey = NULL;
if ( ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, szSideBySideKeyName, 0, NULL, 0, KEY_CREATE_SUB_KEY, NULL, &hkey, NULL)){ // create or open
RegCloseKey(hkey);
HKEY hkey2 = NULL;
if ( ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, szMigrateStatusKeyName, 0, NULL, 0, KEY_EXECUTE, NULL, &hkey2, NULL)){ // not care it fails or successes
RegCloseKey(hkey2);
}
}
RegCloseKey(hkey);
}
// return the result from the actual migration call
return lResult;
}
VOID SetRunOnceDeleteMigrationDoneRegKey()
{
// Create if not exist or just open RegKey : HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce\Setup
HKEY hk = NULL;
if ( ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, szRunOnceSetupRegKey, 0, NULL, 0, KEY_SET_VALUE, NULL, &hk, NULL))
{
// we do not care it success or fail, we could live with it
RegSetValueEx(hk, szRunOnceValueName, 0, REG_SZ, (CONST BYTE *)szRunOnceValueCommandLine,
strlen(szRunOnceValueCommandLine) + 1); // containing the trailing NULL
}
RegCloseKey(hk);
return;
}
///////////////////////////////////////////////////////////////////////
//
// API of WIN-NT MIGRATION Dll
//
///////////////////////////////////////////////////////////////////////
LONG CALLBACK QueryMigrationInfoA(PMIGRATIONINFOA * VersionInfo)
{
FUSION_MSI_OS_VERSION osv;
DbgPrintMessageBox("QueryMigrationInfo");
if (IsMigrationDone())
{
return ERROR_NOT_INSTALLED; // no further migration
}
/*
if (IsW9xOrNT(osv) == FALSE) // we only work on w9x and win2K
{
return ERROR_NOT_INSTALLED; // no further migration
}
*/
// only work for Win98 and win2k upgrade to winxp !!!
if (VersionInfo != NULL)
{
if (g_MigrationInfo == NULL)
{
g_MigrationInfo = (PMIGRATIONINFOA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MIGRATIONINFOA));
if (g_MigrationInfo == NULL)
return ERROR_NOT_ENOUGH_MEMORY;
g_MigrationInfo->Size = sizeof(MIGRATIONINFOA);
g_MigrationInfo->StaticProductIdentifier = g_szProductId;
g_MigrationInfo->DllVersion = 200;
g_MigrationInfo->CodePageArray = NULL;
g_MigrationInfo->SourceOs = (osv == E_WIN98 ? OS_WINDOWS9X : OS_WINDOWS2000);
g_MigrationInfo->TargetOs = OS_WINDOWSWHISTLER;
g_MigrationInfo->NeededFileList = NULL;
g_MigrationInfo->VendorInfo = &g_VendorInfo;
*VersionInfo = g_MigrationInfo;
}
}
return ERROR_SUCCESS;
}
LONG InitializeOnSource()
{
/*
// attempt to load MSI.DLL and grab the version. If this fails, MSI is not
// installed and there is no need for any further migration
if (IsMsi20Installed())
return ERROR_SUCCESS;
else
{
#if DBG
MessageBox(NULL, "MSI version of 2.0 or above is NOT installed, QUIT the migration", "migrate", MB_OK);
#endif
return ERROR_NOT_INSTALLED;
}
*/
return ERROR_SUCCESS;
}
///////////////////////////////////////////////////////////////////////
LONG __stdcall InitializeSrcA(LPCSTR WorkingDirectory, LPCSTR SourceDirectories, LPCSTR MediaDirectory, PVOID Reserved)
{
DbgPrintMessageBox("InitializeSrcA");
return InitializeOnSource();
}
/////////////////////////////////////////////////////////////////////////////
LONG CALLBACK GatherUserSettingsA(LPCSTR AnswerFile, HKEY UserRegKey, LPCSTR UserName, LPVOID Reserved)
{
DbgPrintMessageBox("GatherUserSettingsA");
return ERROR_SUCCESS;
}
LONG CALLBACK GatherSystemSettingsA(LPCSTR AnswerFile, LPVOID Reserved)
{
DbgPrintMessageBox("GatherSystemSettingsA");
return ERROR_SUCCESS;
}
///////////////////////////////////////////////////////////////////////
// Initialization routine on WinNT. Just stores of the migration
// working directory.
LONG CALLBACK InitializeDstA(LPCSTR WorkingDirectory, LPCSTR SourceDirectories, LPVOID Reserved)
{
DbgPrintMessageBox("InitializeDstA");
return ERROR_SUCCESS;
}
///////////////////////////////////////////////////////////////////////
LONG CALLBACK ApplyUserSettingsA(
HINF AnswerFileHandle,
HKEY UserRegKey,
LPCSTR UserName,
LPCSTR UserDomain,
LPCSTR FixedUserName,
LPVOID Reserved)
{
DbgPrintMessageBox("ApplyUserSettingsA");
return ERROR_SUCCESS;
}
///////////////////////////////////////////////////////////////////////
// Called once on NT
LONG CALLBACK ApplySystemSettingsA(HINF UnattendInfHandle, LPVOID Reserved)
{
DbgPrintMessageBox("ApplySystemSettingsA");
LONG lResult = MigrateMSIInstalledWin32Assembly();
SetRunOnceDeleteMigrationDoneRegKey();
return lResult;
}
BOOL
WINAPI
DllMain(
HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved
)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
g_MigrationInfo = NULL;
break;
case DLL_PROCESS_DETACH:
if (g_MigrationInfo != NULL)
{
if (lpvReserved != NULL)
{
HeapFree(GetProcessHeap(), 0, g_MigrationInfo);
}
g_MigrationInfo = NULL;
}
break;
}
return TRUE;
}
///////////////////////////////////////////////////////////////////////
//
// API of WIN9X MIGRATION Dll
//
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
// called by setup to extract migration DLL version and support
// information.
LONG CALLBACK QueryVersion(LPCSTR *ProductID, LPUINT DllVersion, LPINT *CodePageArray,
LPCSTR *ExeNamesBuf, PVENDORINFO *VendorInfo)
{
FUSION_MSI_OS_VERSION osv;
DbgPrintMessageBox("QueryVersion");
if (IsMigrationDone())
{
return ERROR_NOT_INSTALLED; // no further migration
}
/*
if (IsW9xOrNT(osv) == FALSE) // we only work on w9x and win2K
{
return ERROR_NOT_INSTALLED; // no further migration
}
*/
// product ID information
*ProductID = g_szProductId;
*DllVersion = 200;
// DLL is language independent.
*CodePageArray = NULL;
// no EXE search is required
*ExeNamesBuf = NULL;
// vendor information
*VendorInfo = &g_VendorInfo;
return ERROR_SUCCESS;
}
///////////////////////////////////////////////////////////////////////
LONG __stdcall Initialize9x(LPCSTR WorkingDirectory, LPCSTR SourceDirectories, LPCSTR MediaDirectory)
{
DbgPrintMessageBox("Initialize9x");
return InitializeOnSource();
}
/////////////////////////////////////////////////////////////////////////////
LONG CALLBACK MigrateUser9x(HWND ParentWnd, LPCSTR AnswerFile, HKEY UserRegKey, LPCSTR UserName, LPVOID Reserved)
{
DbgPrintMessageBox("MigrateUser9x");
return ERROR_SUCCESS;
}
LONG CALLBACK MigrateSystem9x(HWND ParentWnd, LPCSTR AnswerFile, LPVOID Reserved)
{
DbgPrintMessageBox("MigrateSystem9x");
return ERROR_SUCCESS;
}
///////////////////////////////////////////////////////////////////////
LONG CALLBACK InitializeNT(LPCWSTR WorkingDirectory, LPCWSTR SourceDirectories, LPVOID Reserved)
{
DbgPrintMessageBox("InitializeNT");
return ERROR_SUCCESS;
}
///////////////////////////////////////////////////////////////////////
LONG CALLBACK MigrateUserNT(HINF AnswerFileHandle, HKEY UserRegKey, LPCWSTR UserName, LPVOID Reserved)
{
DbgPrintMessageBox("MigrateUserNT");
return ERROR_SUCCESS;
}
typedef HRESULT (_stdcall * PFN_MigrateFusionWin32AssemblyToXP)(PCWSTR pszInstallerDir);
///////////////////////////////////////////////////////////////////////
LONG CALLBACK MigrateSystemNT(HINF UnattendInfHandle, LPVOID Reserved)
{
DbgPrintMessageBox("MigrateSystemNT");
LONG lResult = MigrateMSIInstalledWin32Assembly();
SetRunOnceDeleteMigrationDoneRegKey();
return lResult;
}