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.

1198 lines
32 KiB

  1. /****************************Module*Header******************************\
  2. * Module Name: ICMUPG.C
  3. *
  4. * Module Descripton: This file has code that upgrades Win9x ICM to
  5. * Memphis and NT 5.0
  6. *
  7. * Warnings:
  8. *
  9. * Issues:
  10. *
  11. * Public Routines:
  12. *
  13. * Created: 14 November 1996
  14. * Author: Srinivasan Chandrasekar [srinivac]
  15. *
  16. * Copyright (c) 1996, 1997 Microsoft Corporation
  17. \***********************************************************************/
  18. #include "icmupg.h"
  19. #include "msg.h"
  20. #include <setupapi.h>
  21. #include <stdio.h>
  22. //#define ICM_MIG_DEBUG
  23. #ifdef UNICODE
  24. error.
  25. This dll needs to be built with ANSI, not UNICODE because it must run on
  26. Win95, Win98 and on Windows 2000
  27. #endif
  28. //
  29. // Local typedefs
  30. //
  31. typedef struct tagMANUMODELIDS {
  32. DWORD dwManuID;
  33. DWORD dwModelID;
  34. } MANUMODELIDS, *PMANUMODELIDS;
  35. typedef struct tagREGDATA {
  36. DWORD dwRefCount;
  37. DWORD dwManuID;
  38. DWORD dwModelID;
  39. } REGDATA, *PREGDATA;
  40. typedef BOOL (WINAPI *PFNINSTALLCOLORPROFILEA)(PSTR, PSTR);
  41. typedef BOOL (WINAPI *PFNINSTALLCOLORPROFILE)(LPCTSTR, LPCTSTR);
  42. typedef BOOL (WINAPI *PFNENUMCOLORPROFILES)(PCTSTR, PENUMTYPE, PBYTE, PDWORD, PDWORD);
  43. typedef struct {
  44. CHAR CompanyName[256];
  45. CHAR SupportNumber[256];
  46. CHAR SupportUrl[256];
  47. CHAR InstructionsToUser[1024];
  48. } VENDORINFO, *PVENDORINFO;
  49. //
  50. // Global variables
  51. //
  52. TCHAR const gszICMRegPath[] = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\ICM";
  53. TCHAR const gszProfile[] = "profile";
  54. TCHAR const gszMSCMSdll[] = "mscms.dll";
  55. char const gszProductID[] = "Microsoft Color Management System";
  56. char const gszInstallColorProfile[] = "InstallColorProfileA";
  57. char const gszGetColorDirectory[] = "GetColorDirectoryA";
  58. char const gszEnumColorProfiles[] = "EnumColorProfilesA";
  59. VENDORINFO gVendorInfo;
  60. char gszMigInf[MAX_PATH];
  61. char const gszFullICMRegPath[] = "\"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\ICM\"";
  62. char const gszInstallColorProfileA[] = "InstallColorProfileA";
  63. //BOOL gbWin98 = FALSE;
  64. #if DBG
  65. DWORD gdwDebugControl;
  66. #endif
  67. TCHAR szValue[MAX_PATH];
  68. TCHAR szName[MAX_PATH];
  69. PFNINSTALLCOLORPROFILEA pInstallColorProfileA = NULL;
  70. PFNINSTALLCOLORPROFILE pInstallColorProfile = NULL;
  71. PFNENUMCOLORPROFILES pEnumColorProfiles = NULL;
  72. //
  73. // Local functions
  74. //
  75. VOID InternalUpgradeICM();
  76. VOID UpgradeClass(HKEY);
  77. BOOL AssociateMonitorProfile();
  78. BOOL AssociatePrinterProfiles(HKEY);
  79. VOID InstallProfiles();
  80. VOID DeleteOldICMKey();
  81. void GetManuAndModelIDs(PTSTR, DWORD*, DWORD*);
  82. int lstrcmpn(PTSTR, PTSTR, DWORD);
  83. HINSTANCE hinstMigDll;
  84. BOOL WINAPI
  85. DllEntryPoint(HINSTANCE hinstDll, DWORD dwReason, LPVOID lpReserved) {
  86. if(dwReason==DLL_PROCESS_ATTACH) {
  87. hinstMigDll = hinstDll;
  88. }
  89. return TRUE;
  90. }
  91. /******************************************************************************
  92. *
  93. * QueryVersion
  94. *
  95. * Function:
  96. * This function is called to get the DLL version information.
  97. *
  98. * Arguments:
  99. * pszProductID - Fill in a unique string identifying us.
  100. * puDllVersion - Our DLL version
  101. *
  102. * None of the other arguments are used
  103. *
  104. * Returns:
  105. * ERROR_SUCCESS to indicate success
  106. *
  107. ******************************************************************************/
  108. LONG
  109. CALLBACK
  110. QueryVersion(
  111. OUT LPCSTR *pszProductID,
  112. OUT LPUINT puDllVersion,
  113. OUT LPINT *pCodePageArray, OPTIONAL
  114. OUT LPCSTR *ppszExeNamesBuf, OPTIONAL
  115. OUT PVENDORINFO *ppVendorInfo
  116. )
  117. {
  118. *pszProductID = gszProductID;
  119. *puDllVersion = 1;
  120. *ppszExeNamesBuf = NULL;
  121. *pCodePageArray = NULL;
  122. *ppVendorInfo = &gVendorInfo;
  123. memset(&gVendorInfo, 0, sizeof(VENDORINFO));
  124. FormatMessageA(
  125. FORMAT_MESSAGE_FROM_HMODULE,
  126. hinstMigDll,
  127. MSG_VI_COMPANY_NAME,
  128. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  129. gVendorInfo.CompanyName,
  130. sizeof(gVendorInfo.CompanyName),
  131. NULL
  132. );
  133. FormatMessageA(
  134. FORMAT_MESSAGE_FROM_HMODULE,
  135. hinstMigDll,
  136. MSG_VI_SUPPORT_NUMBER,
  137. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  138. gVendorInfo.SupportNumber,
  139. sizeof(gVendorInfo.SupportNumber),
  140. NULL
  141. );
  142. FormatMessageA(
  143. FORMAT_MESSAGE_FROM_HMODULE,
  144. hinstMigDll,
  145. MSG_VI_SUPPORT_URL,
  146. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  147. gVendorInfo.SupportUrl,
  148. sizeof(gVendorInfo.SupportUrl),
  149. NULL
  150. );
  151. FormatMessageA(
  152. FORMAT_MESSAGE_FROM_HMODULE,
  153. hinstMigDll,
  154. MSG_VI_INSTRUCTIONS,
  155. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  156. gVendorInfo.InstructionsToUser,
  157. sizeof(gVendorInfo.InstructionsToUser),
  158. NULL
  159. );
  160. WARNING((__TEXT("QueryVersion called\n")));
  161. return ERROR_SUCCESS;
  162. }
  163. /******************************************************************************
  164. *
  165. * Initialize9x
  166. *
  167. * Function:
  168. * This function is called when upgrading to NT 5.0 from Win9x on the
  169. * Win9x side.
  170. *
  171. * Arguments:
  172. * pszWorkingDir - Directory where migrate.inf will be found
  173. *
  174. * Returns:
  175. * ERROR_SUCCESS to indicate success
  176. *
  177. ******************************************************************************/
  178. LONG
  179. CALLBACK
  180. Initialize9x(
  181. IN LPCSTR pszWorkingDir,
  182. IN LPCSTR pszSourceDir,
  183. IN LPVOID pvReserved
  184. )
  185. {
  186. //
  187. // Lets figure out if we're on a Win98 or Win95 system
  188. // We don't migrate Win95 because Win95 doesn't have a
  189. // profile database to migrate.
  190. //
  191. /* OSVERSIONINFO osVer;
  192. osVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  193. GetVersionEx(&osVer);
  194. gbWin98 =
  195. (osVer.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) &&
  196. ( (osVer.dwMajorVersion > 4) ||
  197. ( (osVer.dwMajorVersion == 4) && (osVer.dwMinorVersion > 0) ) );
  198. */
  199. WARNING((__TEXT("Initialize9x called\n")));
  200. lstrcpyA(gszMigInf, pszWorkingDir);
  201. lstrcatA(gszMigInf, "\\migrate.inf");
  202. return ERROR_SUCCESS;
  203. }
  204. /******************************************************************************
  205. *
  206. * MigrateUser9x
  207. *
  208. * Function:
  209. * This function is called on Win9x to upgrade per user settings.
  210. *
  211. * Arguments:
  212. * None of the arguments are used
  213. *
  214. * Returns:
  215. * ERROR_SUCCES to indicate success
  216. *
  217. ******************************************************************************/
  218. LONG
  219. CALLBACK
  220. MigrateUser9x(
  221. IN HWND hwndParent,
  222. IN LPCSTR pszUnattendFile,
  223. IN HKEY hUserRegKey,
  224. IN LPCSTR pszUserName,
  225. LPVOID pvReserved
  226. )
  227. {
  228. //
  229. // Nothing to do
  230. //
  231. WARNING((__TEXT("MigrateUser9x called\n")));
  232. return ERROR_SUCCESS;
  233. }
  234. /******************************************************************************
  235. *
  236. * MigrateSystem9x
  237. *
  238. * Function:
  239. * This function is called on the Win9x to upgrade system settings.
  240. *
  241. * Arguments:
  242. * None of the arguments are used
  243. *
  244. * Returns:
  245. * ERROR_SUCCES to indicate success
  246. *
  247. ******************************************************************************/
  248. LONG
  249. CALLBACK
  250. MigrateSystem9x(
  251. IN HWND hwndParent,
  252. IN LPCSTR pszUnattendFile,
  253. LPVOID pvReserved
  254. )
  255. {
  256. DWORD nProfiles;
  257. DWORD dwSize;
  258. char szColorDir[MAX_PATH];
  259. char szNewColorDir[MAX_PATH];
  260. char szDrive[2];
  261. HMODULE hModule;
  262. ENUMTYPE et = {sizeof (ENUMTYPE), ENUM_TYPE_VERSION, 0, NULL};
  263. PBYTE pBuffer;
  264. PSTR pstrBuffer;
  265. PSTR pstrTraversal;
  266. WARNING((__TEXT("MigrateSystem9x called\n")));
  267. //
  268. // Produce the Win9x Color Directory.
  269. //
  270. if(GetWindowsDirectoryA(szColorDir, MAX_PATH)==0)
  271. {
  272. // If we can't get the windows directory during an upgrade, we can't do anything
  273. return ERROR_BAD_PATHNAME;
  274. }
  275. if (szColorDir[lstrlenA(szColorDir)-1] != '\\')
  276. {
  277. lstrcatA(szColorDir,"\\");
  278. }
  279. lstrcatA(szColorDir, "system\\color\\");
  280. if(GetWindowsDirectoryA(szNewColorDir, MAX_PATH)==0)
  281. {
  282. // If we can't get the windows directory during an upgrade, we can't do anything
  283. return ERROR_BAD_PATHNAME;
  284. }
  285. if (szNewColorDir[lstrlenA(szNewColorDir)-1] != '\\')
  286. {
  287. lstrcatA(szNewColorDir,"\\");
  288. }
  289. lstrcatA(szNewColorDir, "system32\\spool\\drivers\\color\\");
  290. //
  291. // If this is a Win95 system we have nothing to do because
  292. // Win95 doesn't have a color profile database.
  293. //
  294. //
  295. // We can't have mscms as an implib because when they try to load us in
  296. // Win95, they won't find mscms.dll and reject us.
  297. //
  298. hModule = LoadLibrary(gszMSCMSdll);
  299. if (hModule) {
  300. #ifdef ICM_MIG_DEBUG
  301. WritePrivateProfileStringA("ICM Debug", "hModule", "not NULL", gszMigInf);
  302. WritePrivateProfileStringA("ICM Debug", "gbWin98", "TRUE", gszMigInf);
  303. #endif
  304. pEnumColorProfiles = (PFNENUMCOLORPROFILES)GetProcAddress(hModule, gszEnumColorProfiles);
  305. if (pEnumColorProfiles) {
  306. #ifdef ICM_MIG_DEBUG
  307. WritePrivateProfileStringA("ICM Debug", "pEnumColorProfiles", "not NULL", gszMigInf);
  308. #endif
  309. //
  310. // Compute the size of the EnumColorProfiles buffer.
  311. //
  312. dwSize = 0;
  313. pEnumColorProfiles(NULL, &et, NULL, &dwSize, &nProfiles);
  314. if(dwSize==0)
  315. {
  316. #ifdef ICM_MIG_DEBUG
  317. WritePrivateProfileStringA("ICM Debug", "dwSize", "0", gszMigInf);
  318. #endif
  319. //
  320. // Need to exit - nothing to do if there are no profiles installed,
  321. // except to move the directory and registry settings.
  322. //
  323. WARNING((__TEXT("No profiles installed\n")));
  324. goto EndMigrateSystem9x;
  325. }
  326. //
  327. // Enumerate all the currently installed color profiles.
  328. //
  329. #ifdef ICM_MIG_DEBUG
  330. WritePrivateProfileStringA("ICM Debug", "Enumerate", "Start", gszMigInf);
  331. #endif
  332. pBuffer = (BYTE *)malloc(dwSize);
  333. pstrBuffer = (PSTR)pBuffer;
  334. #ifdef ICM_MIG_DEBUG
  335. WritePrivateProfileStringA("ICM Debug", "Enumerate", "TRUE", gszMigInf);
  336. #endif
  337. if(pEnumColorProfiles(NULL, &et, pBuffer, &dwSize, &nProfiles))
  338. {
  339. #ifdef ICM_MIG_DEBUG
  340. WritePrivateProfileStringA("ICM Debug", "Enumerate", "for", gszMigInf);
  341. #endif
  342. for(pstrTraversal = pstrBuffer;
  343. nProfiles--;
  344. pstrTraversal += 1 + lstrlenA(pstrTraversal)) {
  345. //
  346. // Write the fact into the Migration Information file.
  347. //
  348. WritePrivateProfileStringA("Installed ICM Profiles", pstrTraversal, "1", gszMigInf);
  349. }
  350. }
  351. free(pBuffer);
  352. }
  353. #ifdef ICM_MIG_DEBUG
  354. else {
  355. WritePrivateProfileStringA("ICM Debug", "pEnumColorProfiles", "NULL", gszMigInf);
  356. }
  357. #endif
  358. EndMigrateSystem9x:
  359. if (hModule)
  360. {
  361. FreeLibrary(hModule);
  362. }
  363. }
  364. #ifdef ICM_MIG_DEBUG
  365. else {
  366. WritePrivateProfileStringA("ICM Debug", "hModule", "NULL", gszMigInf);
  367. WritePrivateProfileStringA("ICM Debug", "gbWin98", "FALSE", gszMigInf);
  368. }
  369. #endif
  370. //
  371. // We'll handle the ICM branch of the registry
  372. //
  373. WritePrivateProfileStringA("Handled", gszFullICMRegPath, "Registry", gszMigInf);
  374. //
  375. // We'll be moving the entire subdirectory.
  376. //
  377. WritePrivateProfileStringA("Moved", szColorDir, szNewColorDir, gszMigInf);
  378. return ERROR_SUCCESS;
  379. }
  380. /******************************************************************************
  381. *
  382. * InitializeNT
  383. *
  384. * Function:
  385. * This function is called when upgrading to NT 5.0 from Win9x on the NT
  386. * side. Its main purpose is to initialize us.
  387. *
  388. * Arguments:
  389. * None of the arguments are used
  390. *
  391. * Returns:
  392. * ERROR_SUCCESS to indicate success
  393. *
  394. ******************************************************************************/
  395. LONG
  396. CALLBACK
  397. InitializeNT(
  398. IN LPCWSTR pszWorkingDir,
  399. IN LPCWSTR pszSourceDir,
  400. LPVOID pvReserved
  401. )
  402. {
  403. SetupOpenLog(FALSE);
  404. SetupLogError("ICM Migration: InitializeNT called\r\n", LogSevInformation);
  405. return ERROR_SUCCESS;
  406. }
  407. /******************************************************************************
  408. *
  409. * MigrateUserNT
  410. *
  411. * Function:
  412. * This function is called on the NT to upgrade per user settings.
  413. *
  414. * Arguments:
  415. * None of the arguments are used
  416. *
  417. * Returns:
  418. * ERROR_SUCCES to indicate success
  419. *
  420. ******************************************************************************/
  421. LONG
  422. CALLBACK
  423. MigrateUserNT(
  424. IN HANDLE hUnattendInf,
  425. IN HKEY hUserRegKey,
  426. IN LPCWSTR pszUserName,
  427. LPVOID pvReserved
  428. )
  429. {
  430. SetupLogError("ICM Migration: MigrateUserNT called\r\n", LogSevInformation);
  431. //
  432. // Nothing to do
  433. //
  434. return ERROR_SUCCESS;
  435. }
  436. /******************************************************************************
  437. *
  438. * MigrateSystemNT
  439. *
  440. * Function:
  441. * This function is called on the Win9x to upgrade system settings. This
  442. * is where we upgrade ICM 2.0
  443. *
  444. * Arguments:
  445. * None of the other arguments are used
  446. *
  447. * Returns:
  448. * ERROR_SUCCES to indicate success
  449. *
  450. ******************************************************************************/
  451. LONG
  452. CALLBACK
  453. MigrateSystemNT(
  454. IN HANDLE hUnattendInf,
  455. LPVOID pvReserved
  456. )
  457. {
  458. HINSTANCE hModule;
  459. LONG rc = ERROR_FILE_NOT_FOUND;
  460. CHAR szMessage[MAX_PATH];
  461. SetupLogError("ICM Migration: MigrateSystemNT called\r\n", LogSevInformation);
  462. //
  463. // We can't have mscms as an implib because when they try to load us in
  464. // Win95, they won't find mscms.dll and reject us.
  465. //
  466. hModule = LoadLibrary(gszMSCMSdll);
  467. if (!hModule)
  468. {
  469. sprintf(szMessage, "ICM Migration: Fatal Error, cannot load mscms.dll. Error %d\r\n", GetLastError());
  470. SetupLogError(szMessage, LogSevFatalError);
  471. return rc;
  472. }
  473. pInstallColorProfileA = (PFNINSTALLCOLORPROFILEA)GetProcAddress(hModule, gszInstallColorProfileA);
  474. pInstallColorProfile = (PFNINSTALLCOLORPROFILE)GetProcAddress(hModule, gszInstallColorProfile);
  475. if (!pInstallColorProfile || !pInstallColorProfileA)
  476. {
  477. SetupLogError("ICM Migration: Fatal Error, cannot find mscms functions. \r\n", LogSevFatalError);
  478. goto EndMigrateSystemNT;
  479. }
  480. InternalUpgradeICM(); // Upgrade over Win9x
  481. InstallProfiles(); // Install all profiles in the old color directory
  482. DeleteOldICMKey();
  483. rc = ERROR_SUCCESS;
  484. EndMigrateSystemNT:
  485. if (hModule)
  486. {
  487. FreeLibrary(hModule);
  488. }
  489. return rc;
  490. }
  491. /******************************************************************************
  492. *
  493. * DeleteOldICMKey
  494. *
  495. * Function:
  496. * This function deletes the ICM key and subkeys from the Windows branch.
  497. *
  498. * Arguments:
  499. * None
  500. *
  501. * Returns:
  502. * Nothing
  503. *
  504. ******************************************************************************/
  505. VOID
  506. DeleteOldICMKey()
  507. {
  508. HKEY hkICM = NULL; // key to ICM branch in registry
  509. DWORD nSubkeys, i;
  510. TCHAR szKeyName[32];
  511. //
  512. // Open the registry path where profiles used to be kept
  513. //
  514. if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, gszICMRegPath, 0, NULL,
  515. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
  516. NULL, &hkICM, NULL) != ERROR_SUCCESS)
  517. {
  518. SetupLogError("ICM Migration: Cannot open ICM branch of registry\r\n", LogSevError);
  519. return;
  520. }
  521. if (RegQueryInfoKey(hkICM, NULL, NULL, 0, &nSubkeys, NULL, NULL,
  522. NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
  523. {
  524. SetupLogError("ICM Migration: Cannot enumerate ICM branch of registry\r\n", LogSevError);
  525. goto EndDeleteOldICMKey;
  526. }
  527. //
  528. // Go through all the device classes and delete all subkeys - this should
  529. // only be one level deep
  530. //
  531. for (i=nSubkeys; i>0; i--)
  532. {
  533. RegEnumKey(hkICM, i-1, szKeyName, sizeof(szKeyName));
  534. RegDeleteKey(hkICM, szKeyName);
  535. }
  536. EndDeleteOldICMKey:
  537. if (hkICM)
  538. {
  539. RegCloseKey(hkICM);
  540. }
  541. RegDeleteKey(HKEY_LOCAL_MACHINE, gszICMRegPath);
  542. return;
  543. }
  544. //
  545. // Move directory with contents.
  546. // Note this is not recursive.
  547. // The purpose of this routine is to move the old color directory to the
  548. // new color directory. During setup the new color directory may have already
  549. // been created and populated with files. Vendor apps may have populated the
  550. // old color directory with private subdirectories and files which will not
  551. // appear in the new directory created by setup. This routine is designed
  552. // to move those files.
  553. //
  554. // Note it'll fail to move a subdirectory of the old color directory if
  555. // a similar subdirectory exists in the new color directory - this should not
  556. // be the case.
  557. //
  558. // s and d should have the trailing slash.
  559. //
  560. void MyMoveDir(char *s, char *d) {
  561. WIN32_FIND_DATA rf;
  562. HANDLE hf;
  563. char s2[MAX_PATH];
  564. char s_[MAX_PATH];
  565. char d_[MAX_PATH];
  566. char err[MAX_PATH];
  567. //
  568. // If MoveFileEx succeeds, we're done.
  569. //
  570. if(!MoveFileEx(s, d, MOVEFILE_REPLACE_EXISTING)) {
  571. sprintf(s2, "%s*", s);
  572. hf = FindFirstFile(s2, &rf);
  573. do {
  574. // don't move . and ..
  575. if(!(strcmp(".", rf.cFileName)==0 ||
  576. strcmp("..", rf.cFileName)==0) ) {
  577. sprintf(s_, "%s%s", s, rf.cFileName);
  578. sprintf(d_, "%s%s", d, rf.cFileName);
  579. if(!MoveFileEx(s_, d_, MOVEFILE_REPLACE_EXISTING)) {
  580. int e = GetLastError();
  581. sprintf(err, "ICM Migration: Failed the move of %s with %d\r\n", s_, e);
  582. SetupLogError(err, LogSevError);
  583. } else {
  584. sprintf(err, "ICM Migration: Moved %s to %s\n", s_, d_);
  585. SetupLogError(err, LogSevInformation);
  586. }
  587. }
  588. } while(FindNextFile(hf, &rf));
  589. FindClose(hf);
  590. }
  591. //
  592. // source directory should theoretically be empty at this point
  593. // If there are errors, we'll leave files behind and report this in
  594. // the setup log as a LogSevError.
  595. //
  596. }
  597. /******************************************************************************
  598. *
  599. * InstallProfiles
  600. *
  601. * Function:
  602. * This function installs all profiles in %windir%\system\color.
  603. * This is used when upgrading from Win9x to NT 5.0.
  604. *
  605. * Arguments:
  606. * None
  607. *
  608. * Returns:
  609. * Nothing
  610. *
  611. ******************************************************************************/
  612. VOID
  613. InstallProfiles()
  614. {
  615. WIN32_FIND_DATAA wfd;
  616. PSTR pNewColorDirEnd;
  617. HANDLE hFindFile;
  618. CHAR szOldColorDir[MAX_PATH];
  619. CHAR szNewColorDir[MAX_PATH];
  620. CHAR szReturnString[2];
  621. CHAR szDefaultString[2];
  622. CHAR szMessage[2*MAX_PATH+100];
  623. if(GetWindowsDirectoryA(szOldColorDir, MAX_PATH)==0)
  624. {
  625. // If we can't get the windows directory during an upgrade, we can't do anything
  626. sprintf(szMessage, "ICM Migration: GetWindowsDirectory() failed with code %d\r\n", GetLastError());
  627. SetupLogError(szMessage, LogSevFatalError);
  628. return;
  629. }
  630. if (szOldColorDir[lstrlenA(szOldColorDir)-1] != '\\')
  631. lstrcatA(szOldColorDir, "\\");
  632. lstrcatA(szOldColorDir, "system\\color\\");
  633. if(GetWindowsDirectoryA(szNewColorDir, MAX_PATH)==0)
  634. {
  635. // If we can't get the windows directory during an upgrade, we can't do anything
  636. sprintf(szMessage, "ICM Migration: GetWindowsDirectory() failed with code %d\r\n", GetLastError());
  637. SetupLogError(szMessage, LogSevFatalError);
  638. return;
  639. }
  640. if (szNewColorDir[lstrlenA(szNewColorDir)-1] != '\\')
  641. {
  642. lstrcatA(szNewColorDir, "\\");
  643. }
  644. lstrcatA(szNewColorDir, "system32\\spool\\drivers\\color\\");
  645. ASSERT(pInstallColorProfileA != NULL);
  646. //
  647. // Eat any errors on the MoveFile. This is just in case the migration
  648. // was stopped after a previous move and now the source doesn't exist.
  649. //
  650. MyMoveDir(szOldColorDir, szNewColorDir);
  651. //
  652. // Now we have presumably moved everything so run through the list of
  653. // previously installed profiles and install those in the new directory
  654. // (if we find them).
  655. //
  656. pNewColorDirEnd = szNewColorDir + lstrlenA(szNewColorDir);
  657. lstrcatA(szNewColorDir, "*.*");
  658. szDefaultString[0]='0';
  659. szDefaultString[1]=0;
  660. hFindFile = FindFirstFileA(szNewColorDir, &wfd);
  661. if (hFindFile != INVALID_HANDLE_VALUE)
  662. {
  663. do
  664. {
  665. lstrcpyA(pNewColorDirEnd, wfd.cFileName);
  666. //
  667. // Check to see if the profile was installed on Win9x
  668. //
  669. GetPrivateProfileStringA("Installed ICM Profiles", wfd.cFileName, szDefaultString, szReturnString, 2, gszMigInf);
  670. //
  671. // If it was installed, attempt to install it on NT
  672. //
  673. if(szReturnString[0]=='1') {
  674. if (!(*pInstallColorProfileA)(NULL, szNewColorDir))
  675. {
  676. sprintf(szMessage, "ICM Migration: Error %d installing profile %s\r\n", GetLastError(), szNewColorDir);
  677. SetupLogError(szMessage, LogSevError);
  678. }
  679. else
  680. {
  681. sprintf(szMessage, "ICM Migration: Installed profile %s\r\n", szNewColorDir);
  682. SetupLogError(szMessage, LogSevInformation);
  683. }
  684. }
  685. } while (FindNextFileA(hFindFile, &wfd));
  686. FindClose(hFindFile);
  687. }
  688. else
  689. {
  690. SetupLogError("ICM Migration: FindFirstFile returned an invalid handle\r\n", LogSevFatalError);
  691. }
  692. }
  693. /******************************************************************************
  694. *
  695. * InternalUpgradeICM
  696. *
  697. * Function:
  698. * This function forms the core of the upgrade code. It installs all
  699. * profiles in the regsitry, and associates with the right devices
  700. *
  701. * Arguments:
  702. * None
  703. *
  704. * Returns:
  705. * Nothing
  706. *
  707. ******************************************************************************/
  708. VOID
  709. InternalUpgradeICM()
  710. {
  711. HKEY hkICM = NULL; // key to ICM branch in registry
  712. HKEY hkDevice = NULL; // key to ICM device branch in registry
  713. int i; // counter variable
  714. TCHAR *pszClasses[] = { // different profile classes
  715. __TEXT("mntr"),
  716. __TEXT("prtr"),
  717. __TEXT("scnr"),
  718. __TEXT("link"),
  719. __TEXT("abst"),
  720. __TEXT("spac"),
  721. __TEXT("nmcl")
  722. };
  723. CHAR szMessage[MAX_PATH];
  724. LONG errcode;
  725. //
  726. // Open the registry path where profiles are kept
  727. //
  728. if (errcode = RegCreateKeyEx(HKEY_LOCAL_MACHINE, gszICMRegPath, 0, NULL,
  729. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
  730. &hkICM, NULL) != ERROR_SUCCESS)
  731. {
  732. sprintf(szMessage, "ICM Migration: Fatal Error, cannot open registry entry (%s) code:%d\r\n",
  733. gszICMRegPath, errcode);
  734. SetupLogError(szMessage, LogSevFatalError);
  735. return;
  736. }
  737. //
  738. // Go through all the device classes and install the profiles
  739. //
  740. for (i=0; i<sizeof(pszClasses)/sizeof(PTSTR); i++)
  741. {
  742. if (RegOpenKeyEx(hkICM, pszClasses[i], 0, KEY_ALL_ACCESS, &hkDevice) != ERROR_SUCCESS)
  743. {
  744. continue; // go to next key
  745. }
  746. sprintf(szMessage, "ICM Migration: Upgrading %s\r\n", pszClasses[i]);
  747. SetupLogError(szMessage, LogSevInformation);
  748. UpgradeClass(hkDevice);
  749. RegCloseKey(hkDevice);
  750. }
  751. //
  752. // Set default monitor profile
  753. //
  754. // AssociateMonitorProfile(); - Not needed for Memphis
  755. // If Pnp moves everything from Win9x PnP S/W section to NT 5.0 PnP S/W
  756. // section, then we don't need this for NT either
  757. if (hkICM)
  758. {
  759. RegCloseKey(hkICM);
  760. }
  761. return;
  762. }
  763. /******************************************************************************
  764. *
  765. * UpgradeClass
  766. *
  767. * Function:
  768. * This function recursively calls itself to go down a registry path
  769. * till it reaches the leaf, and installs all profiles it finds there
  770. *
  771. * Arguments:
  772. * hKey - registry key for root node
  773. *
  774. * Returns:
  775. * Nothing
  776. *
  777. ******************************************************************************/
  778. VOID
  779. UpgradeClass(
  780. HKEY hKey
  781. )
  782. {
  783. HKEY hSubkey;
  784. DWORD nSubkeys, nValues, i, cbName, cbValue;
  785. TCHAR szKeyName[32];
  786. CHAR szMessage[MAX_PATH];
  787. //
  788. // If there is an error, return
  789. //
  790. if (RegQueryInfoKey(hKey, NULL, NULL, 0, &nSubkeys, NULL, NULL,
  791. &nValues, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
  792. {
  793. return;
  794. }
  795. if (nSubkeys > 0)
  796. {
  797. //
  798. // This is not the leaf node, recurse
  799. //
  800. for (i=nSubkeys; i>0; i--)
  801. {
  802. RegEnumKey(hKey, i-1, szKeyName, sizeof(szKeyName));
  803. if (RegOpenKeyEx(hKey, szKeyName, 0, KEY_ALL_ACCESS, &hSubkey) == ERROR_SUCCESS)
  804. {
  805. UpgradeClass(hSubkey);
  806. RegCloseKey(hSubkey);
  807. RegDeleteKey(hKey, szKeyName);
  808. }
  809. }
  810. }
  811. else
  812. {
  813. //
  814. // This is the leaf node - install all the profiles registered
  815. //
  816. ASSERT(pInstallColorProfile != NULL);
  817. for (i=nValues; i>0; i--)
  818. {
  819. cbName = MAX_PATH;
  820. cbValue = MAX_PATH;
  821. if (RegEnumValue(hKey, i-1, szName, &cbName, 0, NULL, (LPBYTE)szValue,
  822. &cbValue) == ERROR_SUCCESS)
  823. {
  824. if (! lstrcmpn(szName, (PTSTR)gszProfile, lstrlen(gszProfile)))
  825. {
  826. if (! (*pInstallColorProfile)(NULL, szValue))
  827. {
  828. sprintf(szMessage, "ICM Migration: Error installing profile %s\r\n", szValue);
  829. SetupLogError(szMessage, LogSevError);
  830. }
  831. else
  832. {
  833. sprintf(szMessage, "ICM Migration: Installed profile %s\r\n", szValue);
  834. SetupLogError(szMessage, LogSevInformation);
  835. }
  836. }
  837. else
  838. {
  839. PTSTR pProfile;
  840. //
  841. // We might be upgrading over Memphis or later
  842. // In Memphis it is "file name" "value" instead of
  843. // "profilexx" "value" in Win95 & OSR2
  844. //
  845. if (szName[1] == ':')
  846. {
  847. //
  848. // Assume full path name
  849. //
  850. pProfile = szName;
  851. }
  852. else
  853. {
  854. GetWindowsDirectory(szValue, MAX_PATH);
  855. if (szValue[lstrlen(szValue)-1] != '\\')
  856. lstrcat(szValue, __TEXT("\\"));
  857. lstrcat(szValue, __TEXT("system\\color\\"));
  858. lstrcat(szValue, szName);
  859. pProfile = szValue;
  860. }
  861. if (! (*pInstallColorProfile)(NULL, pProfile))
  862. {
  863. sprintf(szMessage, "ICM Migration: Error installing profile %s\r\n", pProfile);
  864. SetupLogError(szMessage, LogSevError);
  865. }
  866. else
  867. {
  868. sprintf(szMessage, "ICM Migration: Installed Profile %s\r\n", pProfile);
  869. SetupLogError(szMessage, LogSevInformation);
  870. }
  871. }
  872. RegDeleteValue(hKey, szName);
  873. }
  874. }
  875. }
  876. return;
  877. }
  878. /******************************************************************************
  879. *
  880. * lstrcmpn
  881. *
  882. * Function:
  883. * This function compares dwLen characters of two strings and decides if
  884. * they are equal
  885. *
  886. * Arguments:
  887. * pStr1 - pointer to string 1
  888. * pStr2 - pointer to string 2
  889. * dwLen - number of characters to compare
  890. *
  891. * Returns:
  892. * Zero if the strings are equal, non zero otherwise
  893. *
  894. ******************************************************************************/
  895. int
  896. lstrcmpn(
  897. PTSTR pStr1,
  898. PTSTR pStr2,
  899. DWORD dwLen
  900. )
  901. {
  902. //
  903. // Assume no NULL strings
  904. //
  905. while (*pStr1 && *pStr2 && --dwLen)
  906. {
  907. if (*pStr1 != *pStr2)
  908. break;
  909. pStr1++;
  910. pStr2++;
  911. }
  912. return (int)(*pStr1 - *pStr2);
  913. }
  914. #if DBG
  915. /******************************************************************************
  916. *
  917. * MyDebugPrint
  918. *
  919. * Function:
  920. * This function takes a format string and paramters, composes a string
  921. * and sends it out to the debug port. Available only in debug build.
  922. *
  923. * Arguments:
  924. * pFormat - pointer to format string
  925. * ....... - parameters based on the format string like printf()
  926. *
  927. * Returns:
  928. * No return value
  929. *
  930. ******************************************************************************/
  931. VOID
  932. MyDebugPrintA(
  933. PSTR pFormat,
  934. ...
  935. )
  936. {
  937. char szBuffer[256];
  938. va_list arglist;
  939. va_start(arglist, pFormat);
  940. wvsprintfA(szBuffer, pFormat, arglist);
  941. va_end(arglist);
  942. OutputDebugStringA(szBuffer);
  943. return;
  944. }
  945. VOID
  946. MyDebugPrintW(
  947. PWSTR pFormat,
  948. ...
  949. )
  950. {
  951. WCHAR szBuffer[256];
  952. va_list arglist;
  953. va_start(arglist, pFormat);
  954. wvsprintfW(szBuffer, pFormat, arglist);
  955. va_end(arglist);
  956. OutputDebugStringW(szBuffer);
  957. return;
  958. }
  959. /******************************************************************************
  960. *
  961. * StripDirPrefixA
  962. *
  963. * Function:
  964. * This function takes a path name and returns a pointer to the filename
  965. * part. This is availabel only for the debug build.
  966. *
  967. * Arguments:
  968. * pszPathName - path name of file (can be file name alone)
  969. *
  970. * Returns:
  971. * A pointer to the file name
  972. *
  973. ******************************************************************************/
  974. PSTR
  975. StripDirPrefixA(
  976. PSTR pszPathName
  977. )
  978. {
  979. DWORD dwLen = lstrlenA(pszPathName);
  980. pszPathName += dwLen - 1; // go to the end
  981. while (*pszPathName != '\\' && dwLen--)
  982. {
  983. pszPathName--;
  984. }
  985. return pszPathName + 1;
  986. }
  987. #endif
  988. #ifdef STANDALONE
  989. //
  990. // For testing
  991. //
  992. main()
  993. {
  994. UpgradeICM(NULL, NULL, NULL, 0);
  995. TCHAR buffer[MAX_PATH];
  996. MigrateInit(buffer, NULL, 0, NULL, NULL);
  997. MigrateInit(NULL, NULL, 0, NULL, NULL);
  998. MigrateLocalMachine(NULL, NULL);
  999. return 0;
  1000. }
  1001. #endif