|
|
/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
migrate.c
Abstract:
This source file implements the windows 9x DEVUPGRD migration dll.
Author:
Marc R. Whitten (marcw) 07-January-2000
Revision History:
Ovidiu Temereanca (ovidiut) 04-Aug-2000 Fixed bugs and support for INF-less paths
--*/
#include "pch.h"
VENDORINFO g_VendorInfo = {"", "", "", ""}; CHAR g_ProductId [MAX_PATH]; PCSTR g_MigrateInfPath = NULL; HINF g_MigrateInf = INVALID_HANDLE_VALUE; HANDLE g_hHeap; HINSTANCE g_hInst; TCHAR g_DllDir[MAX_TCHAR_PATH];
#define D_DLLVERSION 2
#undef DEFMAC
#define MEMDB_CATEGORY_DLLENTRIES "MigDllEntries"
#define S_ACTIVE "Active"
#define DBG_MIGDLL "SMIGDLL"
//
// the temp file that records original sources location
//
#define S_MIGRATEDATA "migrate.dat"
#define S_MIGRATEDATW L"migrate.dat"
#define S_SECTION_DATAA "Data"
#define S_SECTION_DATAW L"Data"
#define S_KEY_SOURCESA "Sources"
#define S_KEY_SOURCESW L"Sources"
PCSTR g_WorkingDir = NULL; PCSTR g_DataFileA = NULL; PCWSTR g_DataFileW = NULL;
typedef BOOL (WINAPI INITROUTINE_PROTOTYPE)(HINSTANCE, DWORD, LPVOID);
INITROUTINE_PROTOTYPE MigUtil_Entry; POOLHANDLE g_GlobalPool;
#define DEVREGKEY "HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Setup\\UpgradeDrivers"
BOOL WINAPI DllMain ( IN HINSTANCE DllInstance, IN ULONG ReasonForCall, IN LPVOID Reserved ) { PSTR p; BOOL result = TRUE;
switch (ReasonForCall) {
case DLL_PROCESS_ATTACH:
//
// We don't need DLL_THREAD_ATTACH or DLL_THREAD_DETACH messages
//
DisableThreadLibraryCalls (DllInstance);
//
// Global init
//
g_hHeap = GetProcessHeap(); g_hInst = DllInstance;
//
// Init common controls
//
InitCommonControls();
//
// Get DLL path and strip directory
//
GetModuleFileNameA (DllInstance, g_DllDir, MAX_TCHAR_PATH); p = strrchr (g_DllDir, '\\'); MYASSERT (p); if (p) { *p = 0; }
if (!MigUtil_Entry (DllInstance, DLL_PROCESS_ATTACH, NULL)) { return FALSE; }
//
// Allocate a global pool
//
g_GlobalPool = PoolMemInitNamedPool ("Global Pool");
break;
case DLL_PROCESS_DETACH:
if (g_MigrateInfPath) { FreePathStringA (g_MigrateInfPath); g_MigrateInfPath = NULL; }
if (g_MigrateInf != INVALID_HANDLE_VALUE) { InfCloseInfFile (g_MigrateInf); g_MigrateInf = INVALID_HANDLE_VALUE; }
//
// Free standard pools
//
if (g_GlobalPool) { PoolMemDestroyPool (g_GlobalPool); g_GlobalPool = NULL; }
MigUtil_Entry (DllInstance, DLL_PROCESS_DETACH, NULL);
break; }
return result; }
LONG CALLBACK QueryVersion ( OUT PCSTR *ProductID, OUT PUINT DllVersion, OUT PINT *CodePageArray, OPTIONAL OUT PCSTR *ExeNamesBuf, OPTIONAL OUT PVENDORINFO *VendorInfo ) {
LONG result = ERROR_NOT_INSTALLED; PCSTR tempStr; HANDLE h;
//
// Fill the data.
//
tempStr = GetStringResourceA (MSG_PRODUCT_ID); if (tempStr) { StringCopyByteCountA (g_ProductId, tempStr, MAX_PATH); FreeStringResourceA (tempStr); }
*ProductID = g_ProductId; *DllVersion = D_DLLVERSION; *CodePageArray = NULL; *VendorInfo = &g_VendorInfo;
// now get the VendorInfo data from resources
tempStr = GetStringResourceA (MSG_VI_COMPANY_NAME); if (tempStr) { StringCopyByteCountA (g_VendorInfo.CompanyName, tempStr, 256); FreeStringResourceA (tempStr); } tempStr = GetStringResourceA (MSG_VI_SUPPORT_NUMBER); if (tempStr) { StringCopyByteCountA (g_VendorInfo.SupportNumber, tempStr, 256); FreeStringResourceA (tempStr); } tempStr = GetStringResourceA (MSG_VI_SUPPORT_URL); if (tempStr) { StringCopyByteCountA (g_VendorInfo.SupportUrl, tempStr, 256); FreeStringResourceA (tempStr); } tempStr = GetStringResourceA (MSG_VI_INSTRUCTIONS); if (tempStr) { StringCopyByteCountA (g_VendorInfo.InstructionsToUser, tempStr, 1024); FreeStringResourceA (tempStr); }
*ExeNamesBuf = NULL;
//
// See if the registry key exists. If it does not, return ERROR_NOT_INSTALLED.
//
h = OpenRegKeyStr (DEVREGKEY); if (h && h != INVALID_HANDLE_VALUE) { result = ERROR_SUCCESS; CloseRegKey (h); }
return result; }
LONG CALLBACK Initialize9x ( IN PCSTR WorkingDirectory, IN PCSTR SourceDirectories, IN PCSTR MediaDir ) { //
// remember source directory, so it can be removed on cleanup
//
g_DataFileA = JoinPathsExA (g_GlobalPool, WorkingDirectory, S_MIGRATEDATA); WritePrivateProfileStringA (S_SECTION_DATAA, S_KEY_SOURCESA, MediaDir, g_DataFileA); g_WorkingDir = DuplicatePathString (WorkingDirectory, 0); g_MigrateInfPath = JoinPathsExA (g_GlobalPool, WorkingDirectory, S_MIGRATE_INF); g_MigrateInf = InfOpenInfFileA (g_MigrateInfPath);
return ERROR_SUCCESS; }
LONG CALLBACK MigrateUser9x ( IN HWND ParentWnd, IN PCSTR UnattendFile, IN HKEY UserRegKey, IN PCSTR UserName, PVOID Reserved ) {
return ERROR_SUCCESS; }
LONG CALLBACK MigrateSystem9x ( IN HWND ParentWnd, IN PCSTR UnattendFile, PVOID Reserved ) {
HANDLE h; REGVALUE_ENUM eValue; REGTREE_ENUM eTree; BOOL found; PSTR value; PSTR p; PSTR end; PSTR dir; CHAR deviceInf [MEMDB_MAX]; HASHTABLE table; PSTR pnpId; DWORD attr;
table = HtAllocWithData (sizeof (PSTR)); if (!table) { return ERROR_OUTOFMEMORY; } __try {
//
// Gather list of pnpids registered on this machine.
//
h = OpenRegKeyStrA (DEVREGKEY); if (!h || h == INVALID_HANDLE_VALUE) { return ERROR_NOT_INSTALLED; }
if (EnumFirstRegValue (&eValue, h)) { do {
p = GetRegValueStringA (h, eValue.ValueName); if (!p) { continue; }
value = PoolMemDuplicateStringA (g_GlobalPool, p); MemFree (g_hHeap, 0, p); if (!value) { return ERROR_OUTOFMEMORY; }
HtAddStringAndDataA (table, eValue.ValueName, &value);
} while (EnumNextRegValue (&eValue)); }
CloseRegKey (h);
//
// Now, enumerate the registry.
//
if (EnumFirstRegKeyInTreeA (&eTree, "HKLM\\Enum")) { do { //
// For each registry key, look to see if we have a compatible id or hardware id
// that is in our hash table.
//
found = FALSE; value = GetRegValueStringA (eTree.CurrentKey->KeyHandle, "HardwareId");
if (value) {
if (HtFindStringAndDataA (table, value, &dir)) { found = TRUE; pnpId = PoolMemDuplicateStringA (g_GlobalPool, value); } else { p = value; while (p && !found) { end = _mbschr (p, ','); if (end) { *end = 0; }
if (HtFindStringAndDataA (table, p, &dir)) { found = TRUE; pnpId = PoolMemDuplicateStringA (g_GlobalPool, p); } else { p = end; if (p) { p++; } } } }
MemFree (g_hHeap, 0, value); }
if (!found) {
value = GetRegValueStringA (eTree.CurrentKey->KeyHandle, "CompatibleIds");
if (value) {
if (HtFindStringAndDataA (table, value, &dir)) { found = TRUE; pnpId = PoolMemDuplicateStringA (g_GlobalPool, value); } p = value; while (p && !found) { end = _mbschr (p, ','); if (end) { *end = 0; }
if (HtFindStringAndDataA (table, p, &dir)) { found = TRUE; pnpId = PoolMemDuplicateStringA (g_GlobalPool, p); } else { p = end; if (p) { p++; } } }
MemFree (g_hHeap, 0, value); } }
if (found) {
//
// build path to deviceInf (no OriginalInstallMedia since the directory will be blown away)
//
lstrcpyA (deviceInf, dir);
//
// GUI setup expects a path to the actual INF, not a directory,
// so let's fix it if this is the case
//
attr = GetFileAttributesA (deviceInf); if (attr == (DWORD)-1) { //
// invalid path spec; ignore it
//
continue; }
if (attr & FILE_ATTRIBUTE_DIRECTORY) { //
// just pick up the first INF
//
HANDLE h; WIN32_FIND_DATAA fd; PSTR pattern;
pattern = JoinPathsExA (g_GlobalPool, deviceInf, "*.inf"); h = FindFirstFileA (pattern, &fd);
if (h == INVALID_HANDLE_VALUE) { //
// no INF found here; skip
//
continue; } FindClose (h);
//
// build path to the INF; also handle the case when deviceInf ends with a \ //
pattern = JoinPathsExA (g_GlobalPool, deviceInf, fd.cFileName); lstrcpyA (deviceInf, pattern); }
//
// Handle the key (remove the message from the compatibility report).
//
WritePrivateProfileStringA ( "HANDLED", eTree.FullKeyName, "REGISTRY", g_MigrateInfPath );
//
// Add to the appropriate section of the SIF file.
//
WritePrivateProfileString ( "DeviceDrivers", pnpId, deviceInf, UnattendFile );
//
// Flush to disk.
//
WritePrivateProfileString (NULL, NULL, NULL, g_MigrateInfPath); WritePrivateProfileString (NULL, NULL, NULL, UnattendFile); }
} while (EnumNextRegKeyInTree (&eTree)); } } __finally {
//
// Clean up resources.
//
HtFree (table); }
return ERROR_SUCCESS; }
LONG CALLBACK InitializeNT ( IN PCWSTR WorkingDirectory, IN PCWSTR SourceDirectories, PVOID Reserved ) { g_DataFileW = JoinPathsExW (g_GlobalPool, WorkingDirectory, S_MIGRATEDATW);
return ERROR_SUCCESS; }
LONG CALLBACK MigrateUserNT ( IN HINF UnattendInfHandle, IN HKEY UserRegKey, IN PCWSTR UserName, PVOID Reserved ) { return ERROR_SUCCESS; }
LONG CALLBACK MigrateSystemNT ( IN HINF UnattendInfHandle, PVOID Reserved ) { WCHAR SourceDirectory[MAX_PATH + 2];
//
// remove original sources directories
//
if (GetPrivateProfileStringW ( S_SECTION_DATAW, S_KEY_SOURCESW, L"", SourceDirectory, MAX_PATH + 2, g_DataFileW )) { RemoveCompleteDirectoryW (SourceDirectory); }
return ERROR_SUCCESS; }
|