test: icmupg.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# icmupg.c

Go to the documentation of this file.

    00001 /****************************Module*Header******************************\
    00002 * Module Name: ICMUPG.C
    00003 *
    00004 * Module Descripton: This file has code that upgrades Win9x ICM to
    00005 *                    Memphis and NT 5.0
    00006 *
    00007 * Warnings:
    00008 *
    00009 * Issues:
    00010 *
    00011 * Public Routines:
    00012 *
    00013 * Created:  14 November 1996
    00014 * Author:   Srinivasan Chandrasekar    [srinivac]
    00015 *
    00016 * Copyright (c) 1996, 1997  Microsoft Corporation
    00017 \***********************************************************************/
    00018
    00019 #include "icmupg.h"
    00020 #include "msg.h"
    00021 #include <setupapi.h>
    00022 #include <stdio.h>
    00023
    00024
    00025 //#define ICM_MIG_DEBUG
    00026
    00027 #ifdef UNICODE
    00028 error.
    00029 This dll needs to be built with ANSI, not UNICODE because it must run on
    00030 Win95, Win98 and on Windows 2000
    00031 #endif
    00032
    00033
    00034 //
    00035 // Local typedefs
    00036 //
    00037
    00038 typedef struct tagMANUMODELIDS {
    00039     DWORD dwManuID;
    00040     DWORD dwModelID;
    00041 } MANUMODELIDS, *PMANUMODELIDS;
    00042
    00043 typedef struct tagREGDATA {
    00044     DWORD dwRefCount;
    00045     DWORD dwManuID;
    00046     DWORD dwModelID;
    00047 } REGDATA, *PREGDATA;
    00048
    00049 typedef BOOL (WINAPI *PFNINSTALLCOLORPROFILEA)(PSTR, PSTR);
    00050 typedef BOOL (WINAPI *PFNINSTALLCOLORPROFILE)(LPCTSTR, LPCTSTR);
    00051 typedef BOOL (WINAPI *PFNENUMCOLORPROFILES)(PCTSTR, PENUMTYPE, PBYTE, PDWORD, PDWORD);
    00052
    00053 typedef struct {
    00054     CHAR CompanyName[256];
    00055     CHAR SupportNumber[256];
    00056     CHAR SupportUrl[256];
    00057     CHAR InstructionsToUser[1024];
    00058 } VENDORINFO, *PVENDORINFO;
    00059
    00060
    00061 //
    00062 // Global variables
    00063 //
    00064
    00065 TCHAR  const gszICMRegPath[]     = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\ICM";
    00066 TCHAR  const gszProfile[]        = "profile";
    00067 TCHAR  const gszMSCMSdll[]       = "mscms.dll";
    00068
    00069 char   const gszProductID[]      = "Microsoft Color Management System";
    00070
    00071 char   const gszInstallColorProfile[] = "InstallColorProfileA";
    00072 char   const gszGetColorDirectory[]   = "GetColorDirectoryA";
    00073 char   const gszEnumColorProfiles[]   = "EnumColorProfilesA";
    00074 VENDORINFO   gVendorInfo;
    00075 char         gszMigInf[MAX_PATH];
    00076 char   const gszFullICMRegPath[]      = "\"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\ICM\"";
    00077
    00078 char   const gszInstallColorProfileA[] = "InstallColorProfileA";
    00079
    00080
    00081 //BOOL gbWin98 = FALSE;
    00082
    00083 #ifdef DBG
    00084 DWORD  gdwDebugControl;
    00085 #endif
    00086 TCHAR  szValue[MAX_PATH];
    00087 TCHAR  szName[MAX_PATH];
    00088
    00089 PFNINSTALLCOLORPROFILEA pInstallColorProfileA = NULL;
    00090 PFNINSTALLCOLORPROFILE pInstallColorProfile = NULL;
    00091 PFNENUMCOLORPROFILES   pEnumColorProfiles = NULL;
    00092
    00093 //
    00094 // Local functions
    00095 //
    00096
    00097 VOID  InternalUpgradeICM();
    00098 VOID  UpgradeClass(HKEY);
    00099 BOOL  AssociateMonitorProfile();
    00100 BOOL  AssociatePrinterProfiles(HKEY);
    00101 VOID  InstallProfiles();
    00102 VOID  DeleteOldICMKey();
    00103 void  GetManuAndModelIDs(PTSTR, DWORD*, DWORD*);
    00104 int   lstrcmpn(PTSTR, PTSTR, DWORD);
    00105
    00106 HINSTANCE hinstMigDll;
    00107
    00108
    00109 BOOL WINAPI
    00110 DllEntryPoint(HINSTANCE hinstDll, DWORD dwReason, LPVOID lpReserved) {
    00111   if(dwReason==DLL_PROCESS_ATTACH) {
    00112     hinstMigDll = hinstDll;
    00113   }
    00114   return TRUE;
    00115 }
    00116
    00117
    00118
    00119 /******************************************************************************
    00120  *
    00121  *                            QueryVersion
    00122  *
    00123  *  Function:
    00124  *       This function is called to get the DLL version information.
    00125  *
    00126  *  Arguments:
    00127  *       pszProductID - Fill in a unique string identifying us.
    00128  *       puDllVersion - Our DLL version
    00129  *
    00130  *       None of the other arguments are used
    00131  *
    00132  *  Returns:
    00133  *       ERROR_SUCCESS to indicate success
    00134  *
    00135  ******************************************************************************/
    00136
    00137 LONG
    00138 CALLBACK
    00139 QueryVersion(
    00140         OUT LPCSTR  *pszProductID,
    00141         OUT LPUINT  puDllVersion,
    00142         OUT LPINT   *pCodePageArray,    OPTIONAL
    00143         OUT LPCSTR  *ppszExeNamesBuf,   OPTIONAL
    00144         OUT PVENDORINFO  *ppVendorInfo
    00145         )
    00146 {
    00147     *pszProductID = gszProductID;
    00148     *puDllVersion = 1;
    00149     *ppszExeNamesBuf    = NULL;
    00150     *pCodePageArray = NULL;
    00151     *ppVendorInfo = &gVendorInfo;
    00152     memset(&gVendorInfo, 0, sizeof(VENDORINFO));
    00153     FormatMessageA(
    00154                  FORMAT_MESSAGE_FROM_HMODULE,
    00155                  hinstMigDll,
    00156                  MSG_VI_COMPANY_NAME,
    00157                  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
    00158                  gVendorInfo.CompanyName,
    00159                  sizeof(gVendorInfo.CompanyName),
    00160                  NULL
    00161                  );
    00162
    00163     FormatMessageA(
    00164                  FORMAT_MESSAGE_FROM_HMODULE,
    00165                  hinstMigDll,
    00166                  MSG_VI_SUPPORT_NUMBER,
    00167                  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
    00168                  gVendorInfo.SupportNumber,
    00169                  sizeof(gVendorInfo.SupportNumber),
    00170                  NULL
    00171                  );
    00172
    00173     FormatMessageA(
    00174                  FORMAT_MESSAGE_FROM_HMODULE,
    00175                  hinstMigDll,
    00176                  MSG_VI_SUPPORT_URL,
    00177                  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
    00178                  gVendorInfo.SupportUrl,
    00179                  sizeof(gVendorInfo.SupportUrl),
    00180                  NULL
    00181                  );
    00182
    00183     FormatMessageA(
    00184                  FORMAT_MESSAGE_FROM_HMODULE,
    00185                  hinstMigDll,
    00186                  MSG_VI_INSTRUCTIONS,
    00187                  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
    00188                  gVendorInfo.InstructionsToUser,
    00189                  sizeof(gVendorInfo.InstructionsToUser),
    00190                  NULL
    00191                  );
    00192     WARNING((__TEXT("QueryVersion called\n")));
    00193     return ERROR_SUCCESS;
    00194 }
    00195
    00196
    00197 /******************************************************************************
    00198  *
    00199  *                            Initialize9x
    00200  *
    00201  *  Function:
    00202  *       This function is called when upgrading to NT 5.0 from Win9x on the
    00203  *       Win9x side.
    00204  *
    00205  *  Arguments:
    00206  *       pszWorkingDir - Directory where migrate.inf will be found
    00207  *
    00208  *  Returns:
    00209  *       ERROR_SUCCESS to indicate success
    00210  *
    00211  ******************************************************************************/
    00212
    00213 LONG
    00214 CALLBACK
    00215 Initialize9x(
    00216     IN  LPCSTR   pszWorkingDir,
    00217     IN  LPCSTR   pszSourceDir,
    00218     IN  LPVOID   pvReserved
    00219     )
    00220 {
    00221   //
    00222   // Lets figure out if we're on a Win98 or Win95 system
    00223   // We don't migrate Win95 because Win95 doesn't have a
    00224   // profile database to migrate.
    00225   //
    00226
    00227 /*  OSVERSIONINFO osVer;
    00228
    00229   osVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    00230   GetVersionEx(&osVer);
    00231   gbWin98 =
    00232     (osVer.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) &&
    00233     ( (osVer.dwMajorVersion > 4) ||
    00234     ( (osVer.dwMajorVersion == 4) && (osVer.dwMinorVersion > 0) ) );
    00235  */
    00236   WARNING((__TEXT("Initialize9x called\n")));
    00237
    00238   lstrcpyA(gszMigInf, pszWorkingDir);
    00239   lstrcatA(gszMigInf, "\\migrate.inf");
    00240
    00241   return ERROR_SUCCESS;
    00242 }
    00243
    00244
    00245 /******************************************************************************
    00246  *
    00247  *                            MigrateUser9x
    00248  *
    00249  *  Function:
    00250  *       This function is called on Win9x to upgrade per user settings.
    00251  *
    00252  *  Arguments:
    00253  *       None of the arguments are used
    00254  *
    00255  *  Returns:
    00256  *       ERROR_SUCCES to indicate success
    00257  *
    00258  ******************************************************************************/
    00259
    00260 LONG
    00261 CALLBACK
    00262 MigrateUser9x(
    00263     IN  HWND     hwndParent,
    00264     IN  LPCSTR   pszUnattendFile,
    00265     IN  HKEY     hUserRegKey,
    00266     IN  LPCSTR   pszUserName,
    00267     LPVOID       pvReserved
    00268     )
    00269 {
    00270     //
    00271     // Nothing to do
    00272     //
    00273
    00274     WARNING((__TEXT("MigrateUser9x called\n")));
    00275     return  ERROR_SUCCESS;
    00276 }
    00277
    00278
    00279 /******************************************************************************
    00280  *
    00281  *                            MigrateSystem9x
    00282  *
    00283  *  Function:
    00284  *       This function is called on the Win9x to upgrade system settings.
    00285  *
    00286  *  Arguments:
    00287  *       None of the arguments are used
    00288  *
    00289  *  Returns:
    00290  *       ERROR_SUCCES to indicate success
    00291  *
    00292  ******************************************************************************/
    00293
    00294 LONG
    00295 CALLBACK
    00296 MigrateSystem9x(
    00297     IN  HWND    hwndParent,
    00298     IN  LPCSTR  pszUnattendFile,
    00299     LPVOID      pvReserved
    00300     )
    00301 {
    00302     DWORD            nProfiles;
    00303     DWORD            dwSize;
    00304     char             szColorDir[MAX_PATH];
    00305     char             szNewColorDir[MAX_PATH];
    00306     char             szDrive[2];
    00307     HMODULE          hModule;
    00308     ENUMTYPE         et = {sizeof (ENUMTYPE), ENUM_TYPE_VERSION, 0, NULL};
    00309     PBYTE            pBuffer;
    00310     PSTR             pstrBuffer;
    00311     PSTR             pstrTraversal;
    00312
    00313     WARNING((__TEXT("MigrateSystem9x called\n")));
    00314
    00315     //
    00316     // Produce the Win9x Color Directory.
    00317     //
    00318
    00319     GetWindowsDirectoryA(szColorDir, MAX_PATH);
    00320     if (szColorDir[lstrlenA(szColorDir)-1] != '\\')
    00321     {
    00322         lstrcatA(szColorDir,"\\");
    00323     }
    00324     lstrcatA(szColorDir, "system\\color\\");
    00325
    00326     GetWindowsDirectoryA(szNewColorDir, MAX_PATH);
    00327     if (szNewColorDir[lstrlenA(szNewColorDir)-1] != '\\')
    00328     {
    00329         lstrcatA(szNewColorDir,"\\");
    00330     }
    00331     lstrcatA(szNewColorDir, "system32\\spool\\drivers\\color\\");
    00332
    00333
    00334     //
    00335     // If this is a Win95 system we have nothing to do because
    00336     // Win95 doesn't have a color profile database.
    00337     //
    00338
    00339
    00340     //
    00341     // We can't have mscms as an implib because when they try to load us in
    00342     // Win95, they won't find mscms.dll and reject us.
    00343     //
    00344
    00345     hModule = LoadLibrary(gszMSCMSdll);
    00346     if (hModule) {
    00347       #ifdef ICM_MIG_DEBUG
    00348       WritePrivateProfileStringA("ICM Debug", "hModule", "not NULL", gszMigInf);
    00349       WritePrivateProfileStringA("ICM Debug", "gbWin98", "TRUE", gszMigInf);
    00350       #endif
    00351
    00352       pEnumColorProfiles = (PFNENUMCOLORPROFILES)GetProcAddress(hModule, gszEnumColorProfiles);
    00353       if (pEnumColorProfiles) {
    00354
    00355         #ifdef ICM_MIG_DEBUG
    00356         WritePrivateProfileStringA("ICM Debug", "pEnumColorProfiles", "not NULL", gszMigInf);
    00357         #endif
    00358
    00359         //
    00360         // Compute the size of the EnumColorProfiles buffer.
    00361         //
    00362
    00363         dwSize = 0;
    00364         pEnumColorProfiles(NULL, &et, NULL, &dwSize, &nProfiles);
    00365
    00366         if(dwSize==0)
    00367         {
    00368           #ifdef ICM_MIG_DEBUG
    00369           WritePrivateProfileStringA("ICM Debug", "dwSize", "0", gszMigInf);
    00370           #endif
    00371           //
    00372           // Need to exit - nothing to do if there are no profiles installed,
    00373           // except to move the directory and registry settings.
    00374           //
    00375           WARNING((__TEXT("No profiles installed\n")));
    00376           goto EndMigrateSystem9x;
    00377         }
    00378
    00379
    00380         //
    00381         // Enumerate all the currently installed color profiles.
    00382         //
    00383
    00384         #ifdef ICM_MIG_DEBUG
    00385         WritePrivateProfileStringA("ICM Debug", "Enumerate", "Start", gszMigInf);
    00386         #endif
    00387
    00388         pBuffer = (BYTE *)malloc(dwSize);
    00389         pstrBuffer = (PSTR)pBuffer;
    00390
    00391         #ifdef ICM_MIG_DEBUG
    00392         WritePrivateProfileStringA("ICM Debug", "Enumerate", "TRUE", gszMigInf);
    00393         #endif
    00394
    00395         if(pEnumColorProfiles(NULL, &et, pBuffer, &dwSize, &nProfiles))
    00396         {
    00397             #ifdef ICM_MIG_DEBUG
    00398             WritePrivateProfileStringA("ICM Debug", "Enumerate", "for", gszMigInf);
    00399             #endif
    00400
    00401             for(pstrTraversal = pstrBuffer;
    00402                 nProfiles--;
    00403                 pstrTraversal += 1 + lstrlenA(pstrTraversal)) {
    00404
    00405                 //
    00406                 // Write the fact into the Migration Information file.
    00407                 //
    00408
    00409                 WritePrivateProfileStringA("Installed ICM Profiles", pstrTraversal, "1", gszMigInf);
    00410             }
    00411         }
    00412         free(pBuffer);
    00413       }
    00414       #ifdef ICM_MIG_DEBUG
    00415         else {
    00416         WritePrivateProfileStringA("ICM Debug", "pEnumColorProfiles", "NULL", gszMigInf);
    00417       }
    00418       #endif
    00419
    00420
    00421       EndMigrateSystem9x:
    00422       if (hModule)
    00423       {
    00424           FreeLibrary(hModule);
    00425       }
    00426   }
    00427   #ifdef ICM_MIG_DEBUG
    00428     else {
    00429     WritePrivateProfileStringA("ICM Debug", "hModule", "NULL", gszMigInf);
    00430     WritePrivateProfileStringA("ICM Debug", "gbWin98", "FALSE", gszMigInf);
    00431   }
    00432   #endif
    00433
    00434   //
    00435   // We'll handle the ICM branch of the registry
    00436   //
    00437
    00438   WritePrivateProfileStringA("Handled", gszFullICMRegPath, "Registry", gszMigInf);
    00439
    00440
    00441   //
    00442   // We'll be moving the entire subdirectory.
    00443   //
    00444
    00445   WritePrivateProfileStringA("Moved", szColorDir, szNewColorDir, gszMigInf);
    00446
    00447
    00448   return  ERROR_SUCCESS;
    00449 }
    00450
    00451
    00452 /******************************************************************************
    00453  *
    00454  *                            InitializeNT
    00455  *
    00456  *  Function:
    00457  *       This function is called when upgrading to NT 5.0 from Win9x on the NT
    00458  *       side. Its main purpose is to initialize us.
    00459  *
    00460  *  Arguments:
    00461  *       None of the arguments are used
    00462  *
    00463  *  Returns:
    00464  *       ERROR_SUCCESS to indicate success
    00465  *
    00466  ******************************************************************************/
    00467
    00468 LONG
    00469 CALLBACK
    00470 InitializeNT(
    00471     IN  LPCWSTR pszWorkingDir,
    00472     IN  LPCWSTR pszSourceDir,
    00473     LPVOID      pvReserved
    00474     )
    00475 {
    00476     SetupOpenLog(FALSE);
    00477     SetupLogError("ICM Migration: InitializeNT called\r\n", LogSevInformation);
    00478     return ERROR_SUCCESS;
    00479 }
    00480
    00481
    00482 /******************************************************************************
    00483  *
    00484  *                            MigrateUserNT
    00485  *
    00486  *  Function:
    00487  *       This function is called on the NT to upgrade per user settings.
    00488  *
    00489  *  Arguments:
    00490  *       None of the arguments are used
    00491  *
    00492  *  Returns:
    00493  *       ERROR_SUCCES to indicate success
    00494  *
    00495  ******************************************************************************/
    00496
    00497 LONG
    00498 CALLBACK
    00499 MigrateUserNT(
    00500     IN  HANDLE    hUnattendInf,
    00501     IN  HKEY      hUserRegKey,
    00502     IN  LPCWSTR   pszUserName,
    00503     LPVOID        pvReserved
    00504     )
    00505 {
    00506     SetupLogError("ICM Migration: MigrateUserNT called\r\n", LogSevInformation);
    00507
    00508     //
    00509     // Nothing to do
    00510     //
    00511
    00512     return  ERROR_SUCCESS;
    00513 }
    00514
    00515
    00516 /******************************************************************************
    00517  *
    00518  *                            MigrateSystemNT
    00519  *
    00520  *  Function:
    00521  *       This function is called on the Win9x to upgrade system settings. This
    00522  *       is where we upgrade ICM 2.0
    00523  *
    00524  *  Arguments:
    00525  *       None of the other arguments are used
    00526  *
    00527  *  Returns:
    00528  *       ERROR_SUCCES to indicate success
    00529  *
    00530  ******************************************************************************/
    00531
    00532 LONG
    00533 CALLBACK
    00534 MigrateSystemNT(
    00535     IN  HANDLE  hUnattendInf,
    00536     LPVOID      pvReserved
    00537     )
    00538 {
    00539     HINSTANCE hModule;
    00540     LONG      rc = ERROR_FILE_NOT_FOUND;
    00541     CHAR      szMessage[MAX_PATH];
    00542
    00543     SetupLogError("ICM Migration: MigrateSystemNT called\r\n", LogSevInformation);
    00544
    00545     //
    00546     // We can't have mscms as an implib because when they try to load us in
    00547     // Win95, they won't find mscms.dll and reject us.
    00548     //
    00549
    00550     hModule = LoadLibrary(gszMSCMSdll);
    00551     if (!hModule)
    00552     {
    00553         sprintf(szMessage, "ICM Migration: Fatal Error, cannot load mscms.dll. Error %d\r\n", GetLastError());
    00554         SetupLogError(szMessage, LogSevFatalError);
    00555         return rc;
    00556     }
    00557
    00558     pInstallColorProfileA = (PFNINSTALLCOLORPROFILEA)GetProcAddress(hModule, gszInstallColorProfileA);
    00559     pInstallColorProfile = (PFNINSTALLCOLORPROFILE)GetProcAddress(hModule, gszInstallColorProfile);
    00560
    00561     if (!pInstallColorProfile || !pInstallColorProfileA)
    00562     {
    00563         SetupLogError("ICM Migration: Fatal Error, cannot find mscms functions. \r\n", LogSevFatalError);
    00564         goto EndMigrateSystemNT;
    00565     }
    00566
    00567     InternalUpgradeICM();   // Upgrade over Win9x
    00568     InstallProfiles();      // Install all profiles in the old color directory
    00569     DeleteOldICMKey();
    00570
    00571     rc = ERROR_SUCCESS;
    00572
    00573 EndMigrateSystemNT:
    00574
    00575     if (hModule)
    00576     {
    00577         FreeLibrary(hModule);
    00578     }
    00579
    00580     return rc;
    00581 }
    00582
    00583
    00584 /******************************************************************************
    00585  *
    00586  *                           DeleteOldICMKey
    00587  *
    00588  *  Function:
    00589  *       This function deletes the ICM key and subkeys from the Windows branch.
    00590  *
    00591  *  Arguments:
    00592  *       None
    00593  *
    00594  *  Returns:
    00595  *       Nothing
    00596  *
    00597  ******************************************************************************/
    00598
    00599 VOID
    00600 DeleteOldICMKey()
    00601 {
    00602     HKEY      hkICM = NULL;         // key to ICM branch in registry
    00603     DWORD nSubkeys, i;
    00604     TCHAR szKeyName[32];
    00605
    00606     //
    00607     // Open the registry path where profiles used to be kept
    00608     //
    00609
    00610     if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, gszICMRegPath, 0, NULL,
    00611                        REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
    00612                        NULL, &hkICM, NULL) != ERROR_SUCCESS)
    00613     {
    00614
    00615         SetupLogError("ICM Migration: Cannot open ICM branch of registry\r\n", LogSevError);
    00616         return;
    00617     }
    00618
    00619     if (RegQueryInfoKey(hkICM, NULL, NULL, 0, &nSubkeys, NULL, NULL,
    00620         NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
    00621     {
    00622         SetupLogError("ICM Migration: Cannot enumerate ICM branch of registry\r\n", LogSevError);
    00623         goto EndDeleteOldICMKey;
    00624     }
    00625
    00626     //
    00627     // Go through all the device classes and delete all subkeys - this should
    00628     // only be one level deep
    00629     //
    00630
    00631     for (i=nSubkeys; i>0; i--)
    00632     {
    00633         RegEnumKey(hkICM, i-1, szKeyName, sizeof(szKeyName));
    00634         RegDeleteKey(hkICM, szKeyName);
    00635     }
    00636
    00637 EndDeleteOldICMKey:
    00638     if (hkICM)
    00639     {
    00640         RegCloseKey(hkICM);
    00641     }
    00642     RegDeleteKey(HKEY_LOCAL_MACHINE, gszICMRegPath);
    00643
    00644     return;
    00645 }
    00646
    00647
    00648 //
    00649 // Move directory with contents.
    00650 // Note this is not recursive.
    00651 // The purpose of this routine is to move the old color directory to the
    00652 // new color directory. During setup the new color directory may have already
    00653 // been created and populated with files. Vendor apps may have populated the
    00654 // old color directory with private subdirectories and files which will not
    00655 // appear in the new directory created by setup. This routine is designed
    00656 // to move those files.
    00657 //
    00658 // Note it'll fail to move a subdirectory of the old color directory if
    00659 // a similar subdirectory exists in the new color directory - this should not
    00660 // be the case.
    00661 //
    00662 // s and d should have the trailing slash.
    00663 //
    00664
    00665 void MyMoveDir(char *s, char *d) {
    00666   WIN32_FIND_DATA rf;
    00667   HANDLE hf;
    00668   char s2[MAX_PATH];
    00669   char s_[MAX_PATH];
    00670   char d_[MAX_PATH];
    00671   char err[MAX_PATH];
    00672
    00673   //
    00674   // If MoveFileEx succeeds, we're done.
    00675   //
    00676
    00677   if(!MoveFileEx(s, d, MOVEFILE_REPLACE_EXISTING)) {
    00678     sprintf(s2, "%s*", s);
    00679     hf = FindFirstFile(s2, &rf);
    00680     do {
    00681       // don't move . and ..
    00682       if(!(strcmp(".", rf.cFileName)==0 ||
    00683            strcmp("..", rf.cFileName)==0) ) {
    00684         sprintf(s_, "%s%s", s, rf.cFileName);
    00685         sprintf(d_, "%s%s", d, rf.cFileName);
    00686         if(!MoveFileEx(s_, d_, MOVEFILE_REPLACE_EXISTING)) {
    00687           int e = GetLastError();
    00688           sprintf(err, "ICM Migration: Failed the move of %s with %d\r\n", s_, e);
    00689           SetupLogError(err, LogSevError);
    00690         } else {
    00691           sprintf(err, "ICM Migration: Moved %s to %s\n", s_, d_);
    00692           SetupLogError(err, LogSevInformation);
    00693         }
    00694       }
    00695
    00696     } while(FindNextFile(hf, &rf));
    00697     FindClose(hf);
    00698   }
    00699
    00700   //
    00701   // source directory should theoretically be empty at this point
    00702   // If there are errors, we'll leave files behind and report this in
    00703   // the setup log as a LogSevError.
    00704   //
    00705 }
    00706
    00707
    00708
    00709 /******************************************************************************
    00710  *
    00711  *                           InstallProfiles
    00712  *
    00713  *  Function:
    00714  *       This function installs all profiles in %windir%\system\color.
    00715  *       This is used when upgrading from Win9x to NT 5.0.
    00716  *
    00717  *  Arguments:
    00718  *       None
    00719  *
    00720  *  Returns:
    00721  *       Nothing
    00722  *
    00723  ******************************************************************************/
    00724
    00725 VOID
    00726 InstallProfiles()
    00727 {
    00728     WIN32_FIND_DATAA wfd;
    00729     PSTR             pNewColorDirEnd;
    00730     HANDLE           hFindFile;
    00731     CHAR             szOldColorDir[MAX_PATH];
    00732     CHAR             szNewColorDir[MAX_PATH];
    00733     CHAR             szReturnString[2];
    00734     CHAR             szDefaultString[2];
    00735     CHAR             szMessage[2*MAX_PATH+100];
    00736
    00737     GetWindowsDirectoryA(szOldColorDir, MAX_PATH);
    00738     if (szOldColorDir[lstrlenA(szOldColorDir)-1] != '\\')
    00739         lstrcatA(szOldColorDir, "\\");
    00740     lstrcatA(szOldColorDir, "system\\color\\");
    00741
    00742
    00743     GetWindowsDirectoryA(szNewColorDir, MAX_PATH);
    00744     if (szNewColorDir[lstrlenA(szNewColorDir)-1] != '\\')
    00745     {
    00746         lstrcatA(szNewColorDir, "\\");
    00747     }
    00748     lstrcatA(szNewColorDir, "system32\\spool\\drivers\\color\\");
    00749
    00750     ASSERT(pInstallColorProfileA != NULL);
    00751
    00752
    00753     //
    00754     // Eat any errors on the MoveFile. This is just in case the migration
    00755     // was stopped after a previous move and now the source doesn't exist.
    00756     //
    00757
    00758     MyMoveDir(szOldColorDir, szNewColorDir);
    00759
    00760     //
    00761     // Now we have presumably moved everything so run through the list of
    00762     // previously installed profiles and install those in the new directory
    00763     // (if we find them).
    00764     //
    00765
    00766     pNewColorDirEnd = szNewColorDir + lstrlenA(szNewColorDir);
    00767     lstrcatA(szNewColorDir, "*.*");
    00768
    00769
    00770
    00771     szDefaultString[0]='0';
    00772     szDefaultString[1]=0;
    00773     hFindFile = FindFirstFileA(szNewColorDir, &wfd);
    00774
    00775
    00776     if (hFindFile != INVALID_HANDLE_VALUE)
    00777     {
    00778         do
    00779         {
    00780             lstrcpyA(pNewColorDirEnd, wfd.cFileName);
    00781
    00782             //
    00783             // Check to see if the profile was installed on Win9x
    00784             //
    00785
    00786             GetPrivateProfileStringA("Installed ICM Profiles", wfd.cFileName, szDefaultString, szReturnString, 2, gszMigInf);
    00787
    00788             //
    00789             // If it was installed, attempt to install it on NT
    00790             //
    00791
    00792             if(szReturnString[0]=='1') {
    00793                 if (!(*pInstallColorProfileA)(NULL, szNewColorDir))
    00794                 {
    00795                     sprintf(szMessage, "ICM Migration: Error %d installing profile %s\r\n", GetLastError(), szNewColorDir);
    00796                     SetupLogError(szMessage, LogSevError);
    00797                 }
    00798                 else
    00799                 {
    00800                     sprintf(szMessage, "ICM Migration: Installed profile %s\r\n", szNewColorDir);
    00801                     SetupLogError(szMessage, LogSevInformation);
    00802                 }
    00803             }
    00804
    00805         } while (FindNextFileA(hFindFile, &wfd));
    00806
    00807         FindClose(hFindFile);
    00808     }
    00809     else
    00810     {
    00811         SetupLogError("ICM Migration: FindFirstFile returned an invalid handle\r\n", LogSevFatalError);
    00812     }
    00813 }
    00814
    00815
    00816 /******************************************************************************
    00817  *
    00818  *                           InternalUpgradeICM
    00819  *
    00820  *  Function:
    00821  *       This function forms the core of the upgrade code. It installs all
    00822  *       profiles in the regsitry, and associates with the right devices
    00823  *
    00824  *  Arguments:
    00825  *       None
    00826  *
    00827  *  Returns:
    00828  *       Nothing
    00829  *
    00830  ******************************************************************************/
    00831
    00832 VOID
    00833 InternalUpgradeICM()
    00834 {
    00835     HKEY      hkICM = NULL;         // key to ICM branch in registry
    00836     HKEY      hkDevice = NULL;      // key to ICM device branch in registry
    00837     int       i;                    // counter variable
    00838     TCHAR    *pszClasses[] = {      // different profile classes
    00839         __TEXT("mntr"),
    00840         __TEXT("prtr"),
    00841         __TEXT("scnr"),
    00842         __TEXT("link"),
    00843         __TEXT("abst"),
    00844         __TEXT("spac"),
    00845         __TEXT("nmcl")
    00846     };
    00847     CHAR szMessage[MAX_PATH];
    00848     LONG errcode;
    00849
    00850     //
    00851     // Open the registry path where profiles are kept
    00852     //
    00853
    00854     if (errcode = RegCreateKeyEx(HKEY_LOCAL_MACHINE, gszICMRegPath, 0, NULL,
    00855                                  REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
    00856                                  &hkICM, NULL) != ERROR_SUCCESS)
    00857     {
    00858         sprintf(szMessage, "ICM Migration: Fatal Error, cannot open registry entry (%s) code:%d\r\n",
    00859                 gszICMRegPath, errcode);
    00860         SetupLogError(szMessage, LogSevFatalError);
    00861         return;
    00862     }
    00863
    00864     //
    00865     // Go through all the device classes and install the profiles
    00866     //
    00867
    00868     for (i=0; i<sizeof(pszClasses)/sizeof(PTSTR); i++)
    00869     {
    00870         if (RegOpenKeyEx(hkICM, pszClasses[i], 0, KEY_ALL_ACCESS, &hkDevice) != ERROR_SUCCESS)
    00871         {
    00872             continue;           // go to next key
    00873         }
    00874
    00875         sprintf(szMessage, "ICM Migration: Upgrading %s\r\n", pszClasses[i]);
    00876         SetupLogError(szMessage, LogSevInformation);
    00877         UpgradeClass(hkDevice);
    00878
    00879         RegCloseKey(hkDevice);
    00880     }
    00881
    00882     //
    00883     // Set default monitor profile
    00884     //
    00885
    00886     // AssociateMonitorProfile(); - Not needed for Memphis
    00887     // If Pnp moves everything from Win9x PnP S/W section to NT 5.0 PnP S/W
    00888     // section, then we don't need this for NT either
    00889
    00890     if (hkICM)
    00891     {
    00892         RegCloseKey(hkICM);
    00893     }
    00894
    00895     return;
    00896 }
    00897
    00898
    00899 /******************************************************************************
    00900  *
    00901  *                           UpgradeClass
    00902  *
    00903  *  Function:
    00904  *       This function recursively calls itself to go down a registry path
    00905  *       till it reaches the leaf, and installs all profiles it finds there
    00906  *
    00907  *  Arguments:
    00908  *       hKey            - registry key for root node
    00909  *
    00910  *  Returns:
    00911  *       Nothing
    00912  *
    00913  ******************************************************************************/
    00914
    00915 VOID
    00916 UpgradeClass(
    00917     HKEY  hKey
    00918     )
    00919 {
    00920     HKEY  hSubkey;
    00921     DWORD nSubkeys, nValues, i, cbName, cbValue;
    00922     TCHAR szKeyName[32];
    00923     CHAR  szMessage[MAX_PATH];
    00924
    00925     //
    00926     // If there is an error, return
    00927     //
    00928
    00929     if (RegQueryInfoKey(hKey, NULL, NULL, 0, &nSubkeys, NULL, NULL,
    00930         &nValues, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
    00931     {
    00932         return;
    00933     }
    00934
    00935     if (nSubkeys > 0)
    00936     {
    00937         //
    00938         // This is not the leaf node, recurse
    00939         //
    00940
    00941         for (i=nSubkeys; i>0; i--)
    00942         {
    00943             RegEnumKey(hKey, i-1, szKeyName, sizeof(szKeyName));
    00944             if (RegOpenKeyEx(hKey, szKeyName, 0, KEY_ALL_ACCESS, &hSubkey) == ERROR_SUCCESS)
    00945             {
    00946                 UpgradeClass(hSubkey);
    00947                 RegCloseKey(hSubkey);
    00948                 RegDeleteKey(hKey, szKeyName);
    00949             }
    00950         }
    00951     }
    00952     else
    00953     {
    00954         //
    00955         // This is the leaf node - install all the profiles registered
    00956         //
    00957
    00958         ASSERT(pInstallColorProfile != NULL);
    00959
    00960         for (i=nValues; i>0; i--)
    00961         {
    00962             cbName = MAX_PATH;
    00963             cbValue = MAX_PATH;
    00964             if (RegEnumValue(hKey, i-1, szName, &cbName, 0, NULL, (LPBYTE)szValue,
    00965                 &cbValue) == ERROR_SUCCESS)
    00966             {
    00967                 if (! lstrcmpn(szName, (PTSTR)gszProfile, lstrlen(gszProfile)))
    00968                 {
    00969                     if (! (*pInstallColorProfile)(NULL, szValue))
    00970                     {
    00971                         sprintf(szMessage, "ICM Migration: Error installing profile %s\r\n", szValue);
    00972                         SetupLogError(szMessage, LogSevError);
    00973                     }
    00974                     else
    00975                     {
    00976                         sprintf(szMessage, "ICM Migration: Installed profile %s\r\n", szValue);
    00977                         SetupLogError(szMessage, LogSevInformation);
    00978                     }
    00979                 }
    00980                 else
    00981                 {
    00982                     PTSTR pProfile;
    00983
    00984                     //
    00985                     // We might be upgrading over Memphis or later
    00986                     // In Memphis it is "file name" "value" instead of
    00987                     // "profilexx" "value" in Win95 & OSR2
    00988                     //
    00989
    00990                     if (szName[1] == ':')
    00991                     {
    00992                         //
    00993                         // Assume full path name
    00994                         //
    00995
    00996                         pProfile = szName;
    00997
    00998                     }
    00999                     else
    01000                     {
    01001                         GetWindowsDirectory(szValue, MAX_PATH);
    01002                         if (szValue[lstrlen(szValue)-1] != '\\')
    01003                             lstrcat(szValue, __TEXT("\\"));
    01004                         lstrcat(szValue, __TEXT("system\\color\\"));
    01005                         lstrcat(szValue, szName);
    01006                         pProfile = szValue;
    01007                     }
    01008
    01009                     if (! (*pInstallColorProfile)(NULL, pProfile))
    01010                     {
    01011                         sprintf(szMessage, "ICM Migration: Error installing profile %s\r\n", pProfile);
    01012                         SetupLogError(szMessage, LogSevError);
    01013                     }
    01014                     else
    01015                     {
    01016                         sprintf(szMessage, "ICM Migration: Installed Profile %s\r\n", pProfile);
    01017                         SetupLogError(szMessage, LogSevInformation);
    01018                     }
    01019                 }
    01020                 RegDeleteValue(hKey, szName);
    01021             }
    01022         }
    01023     }
    01024
    01025     return;
    01026 }
    01027
    01028
    01029 /******************************************************************************
    01030  *
    01031  *                            lstrcmpn
    01032  *
    01033  *  Function:
    01034  *       This function compares dwLen characters of two strings and decides if
    01035  *       they are equal
    01036  *
    01037  *  Arguments:
    01038  *       pStr1           - pointer to string 1
    01039  *       pStr2           - pointer to string 2
    01040  *       dwLen           - number of characters to compare
    01041  *
    01042  *  Returns:
    01043  *       Zero if the strings are equal, non zero otherwise
    01044  *
    01045  ******************************************************************************/
    01046
    01047 int
    01048 lstrcmpn(
    01049     PTSTR pStr1,
    01050     PTSTR pStr2,
    01051     DWORD dwLen
    01052     )
    01053 {
    01054     //
    01055     // Assume no NULL strings
    01056     //
    01057
    01058     while (*pStr1 && *pStr2 && --dwLen)
    01059     {
    01060         if (*pStr1 != *pStr2)
    01061             break;
    01062
    01063         pStr1++;
    01064         pStr2++;
    01065     }
    01066
    01067     return (int)(*pStr1 - *pStr2);
    01068 }
    01069 #if DBG
    01070
    01071 /******************************************************************************
    01072  *
    01073  *                              MyDebugPrint
    01074  *
    01075  *  Function:
    01076  *       This function takes a format string and paramters, composes a string
    01077  *       and sends it out to the debug port. Available only in debug build.
    01078  *
    01079  *  Arguments:
    01080  *       pFormat  - pointer to format string
    01081  *       .......  - parameters based on the format string like printf()
    01082  *
    01083  *  Returns:
    01084  *       No return value
    01085  *
    01086  ******************************************************************************/
    01087
    01088 VOID
    01089 MyDebugPrintA(
    01090     PSTR pFormat,
    01091     ...
    01092     )
    01093 {
    01094     char     szBuffer[256];
    01095     va_list  arglist;
    01096
    01097     va_start(arglist, pFormat);
    01098     wvsprintfA(szBuffer, pFormat, arglist);
    01099     va_end(arglist);
    01100
    01101     OutputDebugStringA(szBuffer);
    01102
    01103     return;
    01104 }
    01105
    01106
    01107 VOID
    01108 MyDebugPrintW(
    01109     PWSTR pFormat,
    01110     ...
    01111     )
    01112 {
    01113     WCHAR    szBuffer[256];
    01114     va_list  arglist;
    01115
    01116     va_start(arglist, pFormat);
    01117     wvsprintfW(szBuffer, pFormat, arglist);
    01118     va_end(arglist);
    01119
    01120     OutputDebugStringW(szBuffer);
    01121
    01122     return;
    01123 }
    01124
    01125 /******************************************************************************
    01126  *
    01127  *                              StripDirPrefixA
    01128  *
    01129  *  Function:
    01130  *       This function takes a path name and returns a pointer to the filename
    01131  *       part. This is availabel only for the debug build.
    01132  *
    01133  *  Arguments:
    01134  *       pszPathName - path name of file (can be file name alone)
    01135  *
    01136  *  Returns:
    01137  *       A pointer to the file name
    01138  *
    01139  ******************************************************************************/
    01140
    01141 PSTR
    01142 StripDirPrefixA(
    01143     PSTR pszPathName
    01144     )
    01145 {
    01146     DWORD dwLen = lstrlenA(pszPathName);
    01147
    01148     pszPathName += dwLen - 1;       // go to the end
    01149
    01150     while (*pszPathName != '\\' && dwLen--)
    01151     {
    01152         pszPathName--;
    01153     }
    01154
    01155     return pszPathName + 1;
    01156 }
    01157
    01158 #endif
    01159
    01160 #ifdef STANDALONE
    01161
    01162 //
    01163 // For testing
    01164 //
    01165
    01166 main()
    01167 {
    01168     UpgradeICM(NULL, NULL, NULL, 0);
    01169
    01170     TCHAR buffer[MAX_PATH];
    01171     MigrateInit(buffer, NULL, 0, NULL, NULL);
    01172     MigrateInit(NULL, NULL, 0, NULL, NULL);
    01173     MigrateLocalMachine(NULL, NULL);
    01174     return 0;
    01175 }
    01176 #endif
    01177