/****************************Module*Header******************************\ * Module Name: ICMUPG.C * * Module Descripton: This file has code that upgrades Win9x ICM to * Memphis and NT 5.0 * * Warnings: * * Issues: * * Public Routines: * * Created: 14 November 1996 * Author: Srinivasan Chandrasekar [srinivac] * * Copyright (c) 1996, 1997 Microsoft Corporation \***********************************************************************/ #include "icmupg.h" #include "msg.h" #include #include //#define ICM_MIG_DEBUG #ifdef UNICODE error. This dll needs to be built with ANSI, not UNICODE because it must run on Win95, Win98 and on Windows 2000 #endif // // Local typedefs // typedef struct tagMANUMODELIDS { DWORD dwManuID; DWORD dwModelID; } MANUMODELIDS, *PMANUMODELIDS; typedef struct tagREGDATA { DWORD dwRefCount; DWORD dwManuID; DWORD dwModelID; } REGDATA, *PREGDATA; typedef BOOL (WINAPI *PFNINSTALLCOLORPROFILEA)(PSTR, PSTR); typedef BOOL (WINAPI *PFNINSTALLCOLORPROFILE)(LPCTSTR, LPCTSTR); typedef BOOL (WINAPI *PFNENUMCOLORPROFILES)(PCTSTR, PENUMTYPE, PBYTE, PDWORD, PDWORD); typedef struct { CHAR CompanyName[256]; CHAR SupportNumber[256]; CHAR SupportUrl[256]; CHAR InstructionsToUser[1024]; } VENDORINFO, *PVENDORINFO; // // Global variables // TCHAR const gszICMRegPath[] = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\ICM"; TCHAR const gszProfile[] = "profile"; TCHAR const gszMSCMSdll[] = "mscms.dll"; char const gszProductID[] = "Microsoft Color Management System"; char const gszInstallColorProfile[] = "InstallColorProfileA"; char const gszGetColorDirectory[] = "GetColorDirectoryA"; char const gszEnumColorProfiles[] = "EnumColorProfilesA"; VENDORINFO gVendorInfo; char gszMigInf[MAX_PATH]; char const gszFullICMRegPath[] = "\"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\ICM\""; char const gszInstallColorProfileA[] = "InstallColorProfileA"; //BOOL gbWin98 = FALSE; #if DBG DWORD gdwDebugControl; #endif TCHAR szValue[MAX_PATH]; TCHAR szName[MAX_PATH]; PFNINSTALLCOLORPROFILEA pInstallColorProfileA = NULL; PFNINSTALLCOLORPROFILE pInstallColorProfile = NULL; PFNENUMCOLORPROFILES pEnumColorProfiles = NULL; // // Local functions // VOID InternalUpgradeICM(); VOID UpgradeClass(HKEY); BOOL AssociateMonitorProfile(); BOOL AssociatePrinterProfiles(HKEY); VOID InstallProfiles(); VOID DeleteOldICMKey(); void GetManuAndModelIDs(PTSTR, DWORD*, DWORD*); int lstrcmpn(PTSTR, PTSTR, DWORD); HINSTANCE hinstMigDll; BOOL WINAPI DllEntryPoint(HINSTANCE hinstDll, DWORD dwReason, LPVOID lpReserved) { if(dwReason==DLL_PROCESS_ATTACH) { hinstMigDll = hinstDll; } return TRUE; } /****************************************************************************** * * QueryVersion * * Function: * This function is called to get the DLL version information. * * Arguments: * pszProductID - Fill in a unique string identifying us. * puDllVersion - Our DLL version * * None of the other arguments are used * * Returns: * ERROR_SUCCESS to indicate success * ******************************************************************************/ LONG CALLBACK QueryVersion( OUT LPCSTR *pszProductID, OUT LPUINT puDllVersion, OUT LPINT *pCodePageArray, OPTIONAL OUT LPCSTR *ppszExeNamesBuf, OPTIONAL OUT PVENDORINFO *ppVendorInfo ) { *pszProductID = gszProductID; *puDllVersion = 1; *ppszExeNamesBuf = NULL; *pCodePageArray = NULL; *ppVendorInfo = &gVendorInfo; memset(&gVendorInfo, 0, sizeof(VENDORINFO)); FormatMessageA( FORMAT_MESSAGE_FROM_HMODULE, hinstMigDll, MSG_VI_COMPANY_NAME, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), gVendorInfo.CompanyName, sizeof(gVendorInfo.CompanyName), NULL ); FormatMessageA( FORMAT_MESSAGE_FROM_HMODULE, hinstMigDll, MSG_VI_SUPPORT_NUMBER, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), gVendorInfo.SupportNumber, sizeof(gVendorInfo.SupportNumber), NULL ); FormatMessageA( FORMAT_MESSAGE_FROM_HMODULE, hinstMigDll, MSG_VI_SUPPORT_URL, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), gVendorInfo.SupportUrl, sizeof(gVendorInfo.SupportUrl), NULL ); FormatMessageA( FORMAT_MESSAGE_FROM_HMODULE, hinstMigDll, MSG_VI_INSTRUCTIONS, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), gVendorInfo.InstructionsToUser, sizeof(gVendorInfo.InstructionsToUser), NULL ); WARNING((__TEXT("QueryVersion called\n"))); return ERROR_SUCCESS; } /****************************************************************************** * * Initialize9x * * Function: * This function is called when upgrading to NT 5.0 from Win9x on the * Win9x side. * * Arguments: * pszWorkingDir - Directory where migrate.inf will be found * * Returns: * ERROR_SUCCESS to indicate success * ******************************************************************************/ LONG CALLBACK Initialize9x( IN LPCSTR pszWorkingDir, IN LPCSTR pszSourceDir, IN LPVOID pvReserved ) { // // Lets figure out if we're on a Win98 or Win95 system // We don't migrate Win95 because Win95 doesn't have a // profile database to migrate. // /* OSVERSIONINFO osVer; osVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&osVer); gbWin98 = (osVer.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) && ( (osVer.dwMajorVersion > 4) || ( (osVer.dwMajorVersion == 4) && (osVer.dwMinorVersion > 0) ) ); */ WARNING((__TEXT("Initialize9x called\n"))); lstrcpyA(gszMigInf, pszWorkingDir); lstrcatA(gszMigInf, "\\migrate.inf"); return ERROR_SUCCESS; } /****************************************************************************** * * MigrateUser9x * * Function: * This function is called on Win9x to upgrade per user settings. * * Arguments: * None of the arguments are used * * Returns: * ERROR_SUCCES to indicate success * ******************************************************************************/ LONG CALLBACK MigrateUser9x( IN HWND hwndParent, IN LPCSTR pszUnattendFile, IN HKEY hUserRegKey, IN LPCSTR pszUserName, LPVOID pvReserved ) { // // Nothing to do // WARNING((__TEXT("MigrateUser9x called\n"))); return ERROR_SUCCESS; } /****************************************************************************** * * MigrateSystem9x * * Function: * This function is called on the Win9x to upgrade system settings. * * Arguments: * None of the arguments are used * * Returns: * ERROR_SUCCES to indicate success * ******************************************************************************/ LONG CALLBACK MigrateSystem9x( IN HWND hwndParent, IN LPCSTR pszUnattendFile, LPVOID pvReserved ) { DWORD nProfiles; DWORD dwSize; char szColorDir[MAX_PATH]; char szNewColorDir[MAX_PATH]; char szDrive[2]; HMODULE hModule; ENUMTYPE et = {sizeof (ENUMTYPE), ENUM_TYPE_VERSION, 0, NULL}; PBYTE pBuffer; PSTR pstrBuffer; PSTR pstrTraversal; WARNING((__TEXT("MigrateSystem9x called\n"))); // // Produce the Win9x Color Directory. // if(GetWindowsDirectoryA(szColorDir, MAX_PATH)==0) { // If we can't get the windows directory during an upgrade, we can't do anything return ERROR_BAD_PATHNAME; } if (szColorDir[lstrlenA(szColorDir)-1] != '\\') { lstrcatA(szColorDir,"\\"); } lstrcatA(szColorDir, "system\\color\\"); if(GetWindowsDirectoryA(szNewColorDir, MAX_PATH)==0) { // If we can't get the windows directory during an upgrade, we can't do anything return ERROR_BAD_PATHNAME; } if (szNewColorDir[lstrlenA(szNewColorDir)-1] != '\\') { lstrcatA(szNewColorDir,"\\"); } lstrcatA(szNewColorDir, "system32\\spool\\drivers\\color\\"); // // If this is a Win95 system we have nothing to do because // Win95 doesn't have a color profile database. // // // We can't have mscms as an implib because when they try to load us in // Win95, they won't find mscms.dll and reject us. // hModule = LoadLibrary(gszMSCMSdll); if (hModule) { #ifdef ICM_MIG_DEBUG WritePrivateProfileStringA("ICM Debug", "hModule", "not NULL", gszMigInf); WritePrivateProfileStringA("ICM Debug", "gbWin98", "TRUE", gszMigInf); #endif pEnumColorProfiles = (PFNENUMCOLORPROFILES)GetProcAddress(hModule, gszEnumColorProfiles); if (pEnumColorProfiles) { #ifdef ICM_MIG_DEBUG WritePrivateProfileStringA("ICM Debug", "pEnumColorProfiles", "not NULL", gszMigInf); #endif // // Compute the size of the EnumColorProfiles buffer. // dwSize = 0; pEnumColorProfiles(NULL, &et, NULL, &dwSize, &nProfiles); if(dwSize==0) { #ifdef ICM_MIG_DEBUG WritePrivateProfileStringA("ICM Debug", "dwSize", "0", gszMigInf); #endif // // Need to exit - nothing to do if there are no profiles installed, // except to move the directory and registry settings. // WARNING((__TEXT("No profiles installed\n"))); goto EndMigrateSystem9x; } // // Enumerate all the currently installed color profiles. // #ifdef ICM_MIG_DEBUG WritePrivateProfileStringA("ICM Debug", "Enumerate", "Start", gszMigInf); #endif pBuffer = (BYTE *)malloc(dwSize); pstrBuffer = (PSTR)pBuffer; #ifdef ICM_MIG_DEBUG WritePrivateProfileStringA("ICM Debug", "Enumerate", "TRUE", gszMigInf); #endif if(pEnumColorProfiles(NULL, &et, pBuffer, &dwSize, &nProfiles)) { #ifdef ICM_MIG_DEBUG WritePrivateProfileStringA("ICM Debug", "Enumerate", "for", gszMigInf); #endif for(pstrTraversal = pstrBuffer; nProfiles--; pstrTraversal += 1 + lstrlenA(pstrTraversal)) { // // Write the fact into the Migration Information file. // WritePrivateProfileStringA("Installed ICM Profiles", pstrTraversal, "1", gszMigInf); } } free(pBuffer); } #ifdef ICM_MIG_DEBUG else { WritePrivateProfileStringA("ICM Debug", "pEnumColorProfiles", "NULL", gszMigInf); } #endif EndMigrateSystem9x: if (hModule) { FreeLibrary(hModule); } } #ifdef ICM_MIG_DEBUG else { WritePrivateProfileStringA("ICM Debug", "hModule", "NULL", gszMigInf); WritePrivateProfileStringA("ICM Debug", "gbWin98", "FALSE", gszMigInf); } #endif // // We'll handle the ICM branch of the registry // WritePrivateProfileStringA("Handled", gszFullICMRegPath, "Registry", gszMigInf); // // We'll be moving the entire subdirectory. // WritePrivateProfileStringA("Moved", szColorDir, szNewColorDir, gszMigInf); return ERROR_SUCCESS; } /****************************************************************************** * * InitializeNT * * Function: * This function is called when upgrading to NT 5.0 from Win9x on the NT * side. Its main purpose is to initialize us. * * Arguments: * None of the arguments are used * * Returns: * ERROR_SUCCESS to indicate success * ******************************************************************************/ LONG CALLBACK InitializeNT( IN LPCWSTR pszWorkingDir, IN LPCWSTR pszSourceDir, LPVOID pvReserved ) { SetupOpenLog(FALSE); SetupLogError("ICM Migration: InitializeNT called\r\n", LogSevInformation); return ERROR_SUCCESS; } /****************************************************************************** * * MigrateUserNT * * Function: * This function is called on the NT to upgrade per user settings. * * Arguments: * None of the arguments are used * * Returns: * ERROR_SUCCES to indicate success * ******************************************************************************/ LONG CALLBACK MigrateUserNT( IN HANDLE hUnattendInf, IN HKEY hUserRegKey, IN LPCWSTR pszUserName, LPVOID pvReserved ) { SetupLogError("ICM Migration: MigrateUserNT called\r\n", LogSevInformation); // // Nothing to do // return ERROR_SUCCESS; } /****************************************************************************** * * MigrateSystemNT * * Function: * This function is called on the Win9x to upgrade system settings. This * is where we upgrade ICM 2.0 * * Arguments: * None of the other arguments are used * * Returns: * ERROR_SUCCES to indicate success * ******************************************************************************/ LONG CALLBACK MigrateSystemNT( IN HANDLE hUnattendInf, LPVOID pvReserved ) { HINSTANCE hModule; LONG rc = ERROR_FILE_NOT_FOUND; CHAR szMessage[MAX_PATH]; SetupLogError("ICM Migration: MigrateSystemNT called\r\n", LogSevInformation); // // We can't have mscms as an implib because when they try to load us in // Win95, they won't find mscms.dll and reject us. // hModule = LoadLibrary(gszMSCMSdll); if (!hModule) { sprintf(szMessage, "ICM Migration: Fatal Error, cannot load mscms.dll. Error %d\r\n", GetLastError()); SetupLogError(szMessage, LogSevFatalError); return rc; } pInstallColorProfileA = (PFNINSTALLCOLORPROFILEA)GetProcAddress(hModule, gszInstallColorProfileA); pInstallColorProfile = (PFNINSTALLCOLORPROFILE)GetProcAddress(hModule, gszInstallColorProfile); if (!pInstallColorProfile || !pInstallColorProfileA) { SetupLogError("ICM Migration: Fatal Error, cannot find mscms functions. \r\n", LogSevFatalError); goto EndMigrateSystemNT; } InternalUpgradeICM(); // Upgrade over Win9x InstallProfiles(); // Install all profiles in the old color directory DeleteOldICMKey(); rc = ERROR_SUCCESS; EndMigrateSystemNT: if (hModule) { FreeLibrary(hModule); } return rc; } /****************************************************************************** * * DeleteOldICMKey * * Function: * This function deletes the ICM key and subkeys from the Windows branch. * * Arguments: * None * * Returns: * Nothing * ******************************************************************************/ VOID DeleteOldICMKey() { HKEY hkICM = NULL; // key to ICM branch in registry DWORD nSubkeys, i; TCHAR szKeyName[32]; // // Open the registry path where profiles used to be kept // if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, gszICMRegPath, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkICM, NULL) != ERROR_SUCCESS) { SetupLogError("ICM Migration: Cannot open ICM branch of registry\r\n", LogSevError); return; } if (RegQueryInfoKey(hkICM, NULL, NULL, 0, &nSubkeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) { SetupLogError("ICM Migration: Cannot enumerate ICM branch of registry\r\n", LogSevError); goto EndDeleteOldICMKey; } // // Go through all the device classes and delete all subkeys - this should // only be one level deep // for (i=nSubkeys; i>0; i--) { RegEnumKey(hkICM, i-1, szKeyName, sizeof(szKeyName)); RegDeleteKey(hkICM, szKeyName); } EndDeleteOldICMKey: if (hkICM) { RegCloseKey(hkICM); } RegDeleteKey(HKEY_LOCAL_MACHINE, gszICMRegPath); return; } // // Move directory with contents. // Note this is not recursive. // The purpose of this routine is to move the old color directory to the // new color directory. During setup the new color directory may have already // been created and populated with files. Vendor apps may have populated the // old color directory with private subdirectories and files which will not // appear in the new directory created by setup. This routine is designed // to move those files. // // Note it'll fail to move a subdirectory of the old color directory if // a similar subdirectory exists in the new color directory - this should not // be the case. // // s and d should have the trailing slash. // void MyMoveDir(char *s, char *d) { WIN32_FIND_DATA rf; HANDLE hf; char s2[MAX_PATH]; char s_[MAX_PATH]; char d_[MAX_PATH]; char err[MAX_PATH]; // // If MoveFileEx succeeds, we're done. // if(!MoveFileEx(s, d, MOVEFILE_REPLACE_EXISTING)) { sprintf(s2, "%s*", s); hf = FindFirstFile(s2, &rf); do { // don't move . and .. if(!(strcmp(".", rf.cFileName)==0 || strcmp("..", rf.cFileName)==0) ) { sprintf(s_, "%s%s", s, rf.cFileName); sprintf(d_, "%s%s", d, rf.cFileName); if(!MoveFileEx(s_, d_, MOVEFILE_REPLACE_EXISTING)) { int e = GetLastError(); sprintf(err, "ICM Migration: Failed the move of %s with %d\r\n", s_, e); SetupLogError(err, LogSevError); } else { sprintf(err, "ICM Migration: Moved %s to %s\n", s_, d_); SetupLogError(err, LogSevInformation); } } } while(FindNextFile(hf, &rf)); FindClose(hf); } // // source directory should theoretically be empty at this point // If there are errors, we'll leave files behind and report this in // the setup log as a LogSevError. // } /****************************************************************************** * * InstallProfiles * * Function: * This function installs all profiles in %windir%\system\color. * This is used when upgrading from Win9x to NT 5.0. * * Arguments: * None * * Returns: * Nothing * ******************************************************************************/ VOID InstallProfiles() { WIN32_FIND_DATAA wfd; PSTR pNewColorDirEnd; HANDLE hFindFile; CHAR szOldColorDir[MAX_PATH]; CHAR szNewColorDir[MAX_PATH]; CHAR szReturnString[2]; CHAR szDefaultString[2]; CHAR szMessage[2*MAX_PATH+100]; if(GetWindowsDirectoryA(szOldColorDir, MAX_PATH)==0) { // If we can't get the windows directory during an upgrade, we can't do anything sprintf(szMessage, "ICM Migration: GetWindowsDirectory() failed with code %d\r\n", GetLastError()); SetupLogError(szMessage, LogSevFatalError); return; } if (szOldColorDir[lstrlenA(szOldColorDir)-1] != '\\') lstrcatA(szOldColorDir, "\\"); lstrcatA(szOldColorDir, "system\\color\\"); if(GetWindowsDirectoryA(szNewColorDir, MAX_PATH)==0) { // If we can't get the windows directory during an upgrade, we can't do anything sprintf(szMessage, "ICM Migration: GetWindowsDirectory() failed with code %d\r\n", GetLastError()); SetupLogError(szMessage, LogSevFatalError); return; } if (szNewColorDir[lstrlenA(szNewColorDir)-1] != '\\') { lstrcatA(szNewColorDir, "\\"); } lstrcatA(szNewColorDir, "system32\\spool\\drivers\\color\\"); ASSERT(pInstallColorProfileA != NULL); // // Eat any errors on the MoveFile. This is just in case the migration // was stopped after a previous move and now the source doesn't exist. // MyMoveDir(szOldColorDir, szNewColorDir); // // Now we have presumably moved everything so run through the list of // previously installed profiles and install those in the new directory // (if we find them). // pNewColorDirEnd = szNewColorDir + lstrlenA(szNewColorDir); lstrcatA(szNewColorDir, "*.*"); szDefaultString[0]='0'; szDefaultString[1]=0; hFindFile = FindFirstFileA(szNewColorDir, &wfd); if (hFindFile != INVALID_HANDLE_VALUE) { do { lstrcpyA(pNewColorDirEnd, wfd.cFileName); // // Check to see if the profile was installed on Win9x // GetPrivateProfileStringA("Installed ICM Profiles", wfd.cFileName, szDefaultString, szReturnString, 2, gszMigInf); // // If it was installed, attempt to install it on NT // if(szReturnString[0]=='1') { if (!(*pInstallColorProfileA)(NULL, szNewColorDir)) { sprintf(szMessage, "ICM Migration: Error %d installing profile %s\r\n", GetLastError(), szNewColorDir); SetupLogError(szMessage, LogSevError); } else { sprintf(szMessage, "ICM Migration: Installed profile %s\r\n", szNewColorDir); SetupLogError(szMessage, LogSevInformation); } } } while (FindNextFileA(hFindFile, &wfd)); FindClose(hFindFile); } else { SetupLogError("ICM Migration: FindFirstFile returned an invalid handle\r\n", LogSevFatalError); } } /****************************************************************************** * * InternalUpgradeICM * * Function: * This function forms the core of the upgrade code. It installs all * profiles in the regsitry, and associates with the right devices * * Arguments: * None * * Returns: * Nothing * ******************************************************************************/ VOID InternalUpgradeICM() { HKEY hkICM = NULL; // key to ICM branch in registry HKEY hkDevice = NULL; // key to ICM device branch in registry int i; // counter variable TCHAR *pszClasses[] = { // different profile classes __TEXT("mntr"), __TEXT("prtr"), __TEXT("scnr"), __TEXT("link"), __TEXT("abst"), __TEXT("spac"), __TEXT("nmcl") }; CHAR szMessage[MAX_PATH]; LONG errcode; // // Open the registry path where profiles are kept // if (errcode = RegCreateKeyEx(HKEY_LOCAL_MACHINE, gszICMRegPath, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkICM, NULL) != ERROR_SUCCESS) { sprintf(szMessage, "ICM Migration: Fatal Error, cannot open registry entry (%s) code:%d\r\n", gszICMRegPath, errcode); SetupLogError(szMessage, LogSevFatalError); return; } // // Go through all the device classes and install the profiles // for (i=0; i 0) { // // This is not the leaf node, recurse // for (i=nSubkeys; i>0; i--) { RegEnumKey(hKey, i-1, szKeyName, sizeof(szKeyName)); if (RegOpenKeyEx(hKey, szKeyName, 0, KEY_ALL_ACCESS, &hSubkey) == ERROR_SUCCESS) { UpgradeClass(hSubkey); RegCloseKey(hSubkey); RegDeleteKey(hKey, szKeyName); } } } else { // // This is the leaf node - install all the profiles registered // ASSERT(pInstallColorProfile != NULL); for (i=nValues; i>0; i--) { cbName = MAX_PATH; cbValue = MAX_PATH; if (RegEnumValue(hKey, i-1, szName, &cbName, 0, NULL, (LPBYTE)szValue, &cbValue) == ERROR_SUCCESS) { if (! lstrcmpn(szName, (PTSTR)gszProfile, lstrlen(gszProfile))) { if (! (*pInstallColorProfile)(NULL, szValue)) { sprintf(szMessage, "ICM Migration: Error installing profile %s\r\n", szValue); SetupLogError(szMessage, LogSevError); } else { sprintf(szMessage, "ICM Migration: Installed profile %s\r\n", szValue); SetupLogError(szMessage, LogSevInformation); } } else { PTSTR pProfile; // // We might be upgrading over Memphis or later // In Memphis it is "file name" "value" instead of // "profilexx" "value" in Win95 & OSR2 // if (szName[1] == ':') { // // Assume full path name // pProfile = szName; } else { GetWindowsDirectory(szValue, MAX_PATH); if (szValue[lstrlen(szValue)-1] != '\\') lstrcat(szValue, __TEXT("\\")); lstrcat(szValue, __TEXT("system\\color\\")); lstrcat(szValue, szName); pProfile = szValue; } if (! (*pInstallColorProfile)(NULL, pProfile)) { sprintf(szMessage, "ICM Migration: Error installing profile %s\r\n", pProfile); SetupLogError(szMessage, LogSevError); } else { sprintf(szMessage, "ICM Migration: Installed Profile %s\r\n", pProfile); SetupLogError(szMessage, LogSevInformation); } } RegDeleteValue(hKey, szName); } } } return; } /****************************************************************************** * * lstrcmpn * * Function: * This function compares dwLen characters of two strings and decides if * they are equal * * Arguments: * pStr1 - pointer to string 1 * pStr2 - pointer to string 2 * dwLen - number of characters to compare * * Returns: * Zero if the strings are equal, non zero otherwise * ******************************************************************************/ int lstrcmpn( PTSTR pStr1, PTSTR pStr2, DWORD dwLen ) { // // Assume no NULL strings // while (*pStr1 && *pStr2 && --dwLen) { if (*pStr1 != *pStr2) break; pStr1++; pStr2++; } return (int)(*pStr1 - *pStr2); } #if DBG /****************************************************************************** * * MyDebugPrint * * Function: * This function takes a format string and paramters, composes a string * and sends it out to the debug port. Available only in debug build. * * Arguments: * pFormat - pointer to format string * ....... - parameters based on the format string like printf() * * Returns: * No return value * ******************************************************************************/ VOID MyDebugPrintA( PSTR pFormat, ... ) { char szBuffer[256]; va_list arglist; va_start(arglist, pFormat); wvsprintfA(szBuffer, pFormat, arglist); va_end(arglist); OutputDebugStringA(szBuffer); return; } VOID MyDebugPrintW( PWSTR pFormat, ... ) { WCHAR szBuffer[256]; va_list arglist; va_start(arglist, pFormat); wvsprintfW(szBuffer, pFormat, arglist); va_end(arglist); OutputDebugStringW(szBuffer); return; } /****************************************************************************** * * StripDirPrefixA * * Function: * This function takes a path name and returns a pointer to the filename * part. This is availabel only for the debug build. * * Arguments: * pszPathName - path name of file (can be file name alone) * * Returns: * A pointer to the file name * ******************************************************************************/ PSTR StripDirPrefixA( PSTR pszPathName ) { DWORD dwLen = lstrlenA(pszPathName); pszPathName += dwLen - 1; // go to the end while (*pszPathName != '\\' && dwLen--) { pszPathName--; } return pszPathName + 1; } #endif #ifdef STANDALONE // // For testing // main() { UpgradeICM(NULL, NULL, NULL, 0); TCHAR buffer[MAX_PATH]; MigrateInit(buffer, NULL, 0, NULL, NULL); MigrateInit(NULL, NULL, 0, NULL, NULL); MigrateLocalMachine(NULL, NULL); return 0; } #endif