Source code of Windows XP (NT5)
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.

929 lines
23 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. scrnsave.c
  5. Abstract:
  6. This source file implements the seven required functions for a
  7. Windows NT 5.0 migration DLL. The DLL demonstrates how the
  8. interface works by performing the Windows 9x screen saver
  9. upgrade.
  10. The source here is a subset of the actual screen saver DLL
  11. that ships with Windows NT Setup.
  12. This sample demonstrates:
  13. - How to detect installation of your application
  14. - A typical implementation of QueryVersion, Initialize9x,
  15. MigrateUser9x, MigrateSystem9x, InitializeNT,
  16. MigrateUserNT and MigraetSystemNT
  17. - How to provide language-dependent incompatibility
  18. messages to the user
  19. - How to remove Setup's incompatibility messages via
  20. [Handled] section
  21. - Saving settings to a temporarly file in the working
  22. directory
  23. - Mix use of ANSI and UNICODE
  24. - Use of the SetupLogError API
  25. - Deleting files
  26. - Handling the move from system to system32
  27. Author:
  28. Jim Schmidt 11-Apr-1997
  29. Revision History:
  30. --*/
  31. #include "pch.h"
  32. BOOL
  33. pLoadFileNames (
  34. VOID
  35. );
  36. //
  37. // Constants
  38. //
  39. #define CP_USASCII 1252
  40. #define CP_JAPANESE 932
  41. #define CP_CHT 950
  42. #define CP_CHS 936
  43. #define CP_KOREAN 949
  44. #define END_OF_CODEPAGES -1
  45. //
  46. // Code page array
  47. //
  48. INT g_CodePageArray[] = {
  49. CP_USASCII,
  50. CP_JAPANESE,
  51. CP_CHT,
  52. CP_CHS,
  53. CP_KOREAN,
  54. END_OF_CODEPAGES
  55. };
  56. //
  57. // Multi-sz (i.e., double-nul terminated) list of files to find
  58. //
  59. CHAR g_ExeNamesBuf[1024];
  60. CHAR g_MyProductId[MAX_PATH];
  61. CHAR g_DefaultUser[MAX_PATH];
  62. //
  63. // Copies of the working directory and source directory
  64. //
  65. LPSTR g_WorkingDirectory = NULL;
  66. LPSTR g_SourceDirectories = NULL; // multi-sz
  67. LPSTR g_SettingsFile = NULL;
  68. LPSTR g_MigrateDotInf = NULL;
  69. //
  70. // Registry locations and INI file sections
  71. //
  72. #define REGKEY_DESKTOP "Control Panel\\Desktop"
  73. #define FULL_REGKEY_DESKTOP "HKR\\Control Panel\\Desktop"
  74. #define FULL_REGKEY_PWD_PROVIDER "HKLM\\System\\CurrentControlSet\\Control\\PwdProvider\\SCRSAVE"
  75. #define REGVAL_SCREENSAVEACTIVE "ScreenSaveActive"
  76. #define REGVAL_SCREENSAVELOWPOWERACTIVE "ScreenSaveLowPowerActive"
  77. #define REGVAL_SCREENSAVELOWPOWERTIMEOUT "ScreenSaveLowPowerTimeout"
  78. #define REGVAL_SCREENSAVEPOWEROFFACTIVE "ScreenSavePowerOffActive"
  79. #define REGVAL_SCREENSAVEPOWEROFFTIMEOUT "ScreenSavePowerOffTimeout"
  80. #define REGVAL_SCREENSAVETIMEOUT "ScreenSaveTimeOut"
  81. #define REGVAL_SCREENSAVEUSEPASSWORD "ScreenSaveUsePassword"
  82. #define REGVAL_LOWPOWERACTIVE "LowPowerActive"
  83. #define REGVAL_LOWPOWERTIMEOUT "LowPowerTimeout"
  84. #define REGVAL_POWEROFFACTIVE "PowerOffActive"
  85. #define REGVAL_POWEROFFTIMEOUT "PowerOffTimeout"
  86. #define REGVAL_SCREENSAVERISSECURE "ScreenSaverIsSecure"
  87. //
  88. // State variables
  89. //
  90. BOOL g_FoundPassword = FALSE;
  91. LPCSTR g_User;
  92. CHAR g_UserNameBuf[MAX_PATH];
  93. HANDLE g_hHeap;
  94. HINSTANCE g_hInst;
  95. BOOL
  96. WINAPI
  97. DllMain (
  98. IN HANDLE DllInstance,
  99. IN ULONG ReasonForCall,
  100. IN LPVOID Reserved
  101. )
  102. {
  103. PCSTR Message;
  104. switch (ReasonForCall) {
  105. case DLL_PROCESS_ATTACH:
  106. //
  107. // We don't need DLL_THREAD_ATTACH or DLL_THREAD_DETACH messages
  108. //
  109. DisableThreadLibraryCalls (DllInstance);
  110. //
  111. // Global init
  112. //
  113. g_hInst = DllInstance;
  114. g_hHeap = GetProcessHeap();
  115. if (!MigInf_Initialize()) {
  116. return FALSE;
  117. }
  118. Message = ParseMessage (MSG_PRODUCT_ID);
  119. if (Message) {
  120. _mbscpy (g_MyProductId, Message);
  121. FreeMessage (Message);
  122. }
  123. Message = ParseMessage (MSG_DEFAULT_USER);
  124. if (Message) {
  125. _mbscpy (g_DefaultUser, Message);
  126. FreeMessage (Message);
  127. }
  128. // Open log; FALSE means do not delete existing log
  129. SetupOpenLog (FALSE);
  130. break;
  131. case DLL_PROCESS_DETACH:
  132. MigInf_CleanUp();
  133. // Clean up strings
  134. if (g_WorkingDirectory) {
  135. HeapFree (g_hHeap, 0, g_WorkingDirectory);
  136. }
  137. if (g_SourceDirectories) {
  138. HeapFree (g_hHeap, 0, g_SourceDirectories);
  139. }
  140. if (g_SettingsFile) {
  141. HeapFree (g_hHeap, 0, g_SettingsFile);
  142. }
  143. if (g_MigrateDotInf) {
  144. HeapFree (g_hHeap, 0, g_MigrateDotInf);
  145. }
  146. SetupCloseLog();
  147. break;
  148. }
  149. return TRUE;
  150. }
  151. LONG
  152. CALLBACK
  153. QueryVersion (
  154. OUT LPCSTR *ProductID,
  155. OUT LPUINT DllVersion,
  156. OUT LPINT *CodePageArray, OPTIONAL
  157. OUT LPCSTR *ExeNamesBuf, OPTIONAL
  158. LPVOID Reserved
  159. )
  160. {
  161. //
  162. // Complete load of string resources, act like not installed
  163. // on resource error (unexpected condition).
  164. //
  165. if (!g_MyProductId[0] || !g_DefaultUser[0]) {
  166. return ERROR_NOT_INSTALLED;
  167. }
  168. if (!pLoadFileNames()) {
  169. return ERROR_NOT_INSTALLED;
  170. }
  171. //
  172. // We do some preliminary investigation to see if
  173. // our components are installed.
  174. //
  175. if (!GetScrnSaveExe()) {
  176. //
  177. // We didn't detect any components, so we return
  178. // ERROR_NOT_INSTALLED and the DLL will stop being called.
  179. // Use this method as much as possible, because user enumeration
  180. // for MigrateUser9x is relatively slow. However, don't spend too
  181. // much time here because QueryVersion is expected to run quickly.
  182. //
  183. return ERROR_NOT_INSTALLED;
  184. }
  185. //
  186. // Screen saver is enabled, so tell Setup who we are. ProductID is used
  187. // for display, so it must be localized. The ProductID string is
  188. // converted to UNICODE for use on Windows NT via the MultiByteToWideChar
  189. // Win32 API. It uses the same code page as FormatMessage to do
  190. // its conversion.
  191. //
  192. *ProductID = g_MyProductId;
  193. //
  194. // Report our version. Zero is reserved for use by DLLs that
  195. // ship with Windows NT.
  196. //
  197. *DllVersion = 1;
  198. //
  199. // We return an array that has all ANSI code pages that we have
  200. // text for.
  201. //
  202. // Tip: If it makes more sense for your DLL to use locales,
  203. // return ERROR_NOT_INSTALLED if the DLL detects that an appropriate
  204. // locale is not installed on the machine.
  205. //
  206. *CodePageArray = g_CodePageArray;
  207. //
  208. // ExeNamesBuf - we pass a list of file names (the long versions)
  209. // and let Setup find them for us. Keep this list short because
  210. // every instance of the file on every hard drive will be reported
  211. // in migrate.inf.
  212. //
  213. // Most applications don't need this behavior, because the registry
  214. // usually contains full paths to installed components. We need it,
  215. // though, because there are no registry settings that give us the
  216. // paths of the screen saver DLLs.
  217. //
  218. *ExeNamesBuf = g_ExeNamesBuf;
  219. return ERROR_SUCCESS;
  220. }
  221. LONG
  222. CALLBACK
  223. Initialize9x (
  224. IN LPCSTR WorkingDirectory,
  225. IN LPCSTR SourceDirectories,
  226. LPVOID Reserved
  227. )
  228. {
  229. INT Len;
  230. //
  231. // Because we returned ERROR_SUCCESS in QueryVersion, we are being
  232. // called for initialization. Therefore, we know screen savers are
  233. // enabled on the machine at this point.
  234. //
  235. //
  236. // Make global copies of WorkingDirectory and SourceDirectories --
  237. // we will not get this information again, and we shouldn't
  238. // count on Setup keeping the pointer valid for the life of our
  239. // DLL.
  240. //
  241. Len = CountStringBytes (WorkingDirectory);
  242. g_WorkingDirectory = HeapAlloc (g_hHeap, 0, Len);
  243. if (!g_WorkingDirectory) {
  244. return GetLastError();
  245. }
  246. CopyMemory (g_WorkingDirectory, WorkingDirectory, Len);
  247. Len = CountMultiStringBytes (SourceDirectories);
  248. g_SourceDirectories = HeapAlloc (g_hHeap, 0, Len);
  249. if (!g_SourceDirectories) {
  250. return GetLastError();
  251. }
  252. CopyMemory (g_SourceDirectories, SourceDirectories, Len);
  253. //
  254. // Now create our private 'settings file' path
  255. //
  256. GenerateFilePaths();
  257. //
  258. // Return success to have MigrateUser9x called
  259. //
  260. // Tip: A DLL can save system settings during Initialize9x as
  261. // well as MigrateSystem9x.
  262. //
  263. //
  264. return ERROR_SUCCESS;
  265. }
  266. LONG
  267. CALLBACK
  268. MigrateUser9x (
  269. IN HWND ParentWnd,
  270. IN LPCSTR UnattendFile,
  271. IN HKEY UserRegKey,
  272. IN LPCSTR UserName,
  273. LPVOID Reserved
  274. )
  275. {
  276. HKEY RegKey;
  277. LPCSTR ScrnSaveExe;
  278. DWORD rc = ERROR_SUCCESS;
  279. LPSTR SectionNameBuf, p;
  280. DWORD SectionNameSize;
  281. DWORD Len;
  282. //
  283. // This DLL does not require input from the user to upgrade
  284. // their settings, so ParentWnd is not used. Avoid displaying
  285. // any user interface when possible.
  286. //
  287. // We don't need to use UnattendFile settings because we are not
  288. // a service (such as a network redirector). Therefore, we do not
  289. // use the UnattendFile parameter.
  290. //
  291. // We don't have any files that need to be generated or expanded on
  292. // the NT side of Setup, so we do not write to the
  293. // [NT Disk Space Requirements] section of migrate.inf.
  294. //
  295. //
  296. // We must collect a few registry keys:
  297. //
  298. // HKCU\Control Panel\Desktop
  299. // ScreenSaveActive
  300. // ScreenSaveLowPowerActive
  301. // ScreenSaveLowPowerTimeout
  302. // ScreenSavePowerOffActive
  303. // ScreenSavePowerOffTimeout
  304. // ScreenSaveTimeOut
  305. // ScreenSaveUsePassword
  306. //
  307. // If ScreenSave_Data exists, we tell the user that their
  308. // password is not supported by writing an incompatiility
  309. // message.
  310. //
  311. //
  312. // Save the user name in a global so our utils write to the
  313. // correct section.
  314. //
  315. if (UserName) {
  316. g_User = UserName;
  317. } else {
  318. g_User = g_DefaultUser;
  319. }
  320. // OpenRegKey is our utility (in utils.c)
  321. RegKey = OpenRegKey (UserRegKey, REGKEY_DESKTOP);
  322. if (!RegKey) {
  323. //
  324. // User's registry is invalid, so skip the user
  325. //
  326. return ERROR_NOT_INSTALLED;
  327. }
  328. //
  329. // Note: NO changes allowed on Win9x side, we can only read our
  330. // settings and save them in a file.
  331. //
  332. if (!CopyRegValueToDatFile (RegKey, REGVAL_SCREENSAVEACTIVE) ||
  333. !CopyRegValueToDatFile (RegKey, REGVAL_SCREENSAVELOWPOWERACTIVE) ||
  334. !CopyRegValueToDatFile (RegKey, REGVAL_SCREENSAVELOWPOWERTIMEOUT) ||
  335. !CopyRegValueToDatFile (RegKey, REGVAL_SCREENSAVEPOWEROFFACTIVE) ||
  336. !CopyRegValueToDatFile (RegKey, REGVAL_SCREENSAVEPOWEROFFTIMEOUT) ||
  337. !CopyRegValueToDatFile (RegKey, REGVAL_SCREENSAVETIMEOUT) ||
  338. !CopyRegValueToDatFile (RegKey, REGVAL_SCREENSAVEUSEPASSWORD)
  339. ) {
  340. rc = GetLastError();
  341. }
  342. if (atoi (GetRegValueString (RegKey, REGVAL_SCREENSAVEUSEPASSWORD))) {
  343. // Queue change so there is only one message
  344. g_FoundPassword = TRUE;
  345. }
  346. //
  347. // Save EXE location in our dat file
  348. //
  349. ScrnSaveExe = GetScrnSaveExe();
  350. if (ScrnSaveExe) {
  351. if (!SaveDatFileKeyAndVal (S_SCRNSAVE_EXE, ScrnSaveExe)) {
  352. rc = GetLastError();
  353. }
  354. }
  355. //
  356. // Copy control.ini sections to our dat file
  357. //
  358. SectionNameSize = 32768;
  359. SectionNameBuf = (LPSTR) HeapAlloc (g_hHeap, 0, SectionNameSize);
  360. if (!SectionNameBuf) {
  361. return GetLastError();
  362. }
  363. GetPrivateProfileString (
  364. NULL,
  365. NULL,
  366. S_DOUBLE_EMPTY,
  367. SectionNameBuf,
  368. SectionNameSize,
  369. S_CONTROL_INI
  370. );
  371. Len = _mbslen (S_SCRNSAVE_DOT);
  372. for (p = SectionNameBuf ; *p ; p = _mbschr (p, 0) + 1) {
  373. //
  374. // Determine if section name has "Screen Saver." at the beginning
  375. //
  376. if (!_mbsnicmp (p, S_SCRNSAVE_DOT, Len)) {
  377. //
  378. // It does, so save it to our private file
  379. //
  380. SaveControlIniSection (p, p + Len);
  381. }
  382. }
  383. CloseRegKey (RegKey);
  384. if (rc != ERROR_SUCCESS) {
  385. LOG ((LOG_ERROR, MSG_PROCESSING_ERROR, g_User, rc));
  386. } else {
  387. //
  388. // Write handled for every setting we are processing. Because this
  389. // DLL supports only some of the values in the Desktop key, we must
  390. // be very specific as to which values are actually handled. If
  391. // your DLL handles all registry values AND subkeys of a registry
  392. // key, you can specify NULL in the second parameter of
  393. // MigInf_AddHandledRegistry.
  394. //
  395. MigInf_AddHandledRegistry (FULL_REGKEY_DESKTOP, REGVAL_SCREENSAVEACTIVE);
  396. MigInf_AddHandledRegistry (FULL_REGKEY_DESKTOP, REGVAL_SCREENSAVELOWPOWERACTIVE);
  397. MigInf_AddHandledRegistry (FULL_REGKEY_DESKTOP, REGVAL_SCREENSAVELOWPOWERTIMEOUT);
  398. MigInf_AddHandledRegistry (FULL_REGKEY_DESKTOP, REGVAL_SCREENSAVEPOWEROFFACTIVE);
  399. MigInf_AddHandledRegistry (FULL_REGKEY_DESKTOP, REGVAL_SCREENSAVEPOWEROFFTIMEOUT);
  400. MigInf_AddHandledRegistry (FULL_REGKEY_DESKTOP, REGVAL_SCREENSAVETIMEOUT);
  401. //
  402. // We do not say that we handle REGVAL_SCREENSAVEUSEPASSWORD when we write
  403. // an incompatibility message for it. If we did, we would be suppressing
  404. // our own message!
  405. //
  406. if (!g_FoundPassword) {
  407. MigInf_AddHandledRegistry (FULL_REGKEY_DESKTOP, REGVAL_SCREENSAVEUSEPASSWORD);
  408. }
  409. }
  410. return rc;
  411. }
  412. LONG
  413. CALLBACK
  414. MigrateSystem9x (
  415. IN HWND ParentWnd,
  416. IN LPCSTR UnattendFile,
  417. LPVOID Reserved
  418. )
  419. {
  420. HINF MigrateInf;
  421. INFCONTEXT ic;
  422. CHAR FileName[MAX_PATH*2];
  423. PCSTR Message;
  424. //
  425. // We handle the password provider incompatibility
  426. //
  427. MigInf_AddHandledRegistry (FULL_REGKEY_PWD_PROVIDER, NULL);
  428. //
  429. // Write incompatibility message if necessary (detected in MigrateUser9x)
  430. //
  431. if (g_FoundPassword) {
  432. Message = ParseMessage (MSG_PASSWORD_ALERT);
  433. MigInf_AddMessage (g_MyProductId, Message);
  434. FreeMessage (Message);
  435. MigInf_AddMessageRegistry (
  436. g_MyProductId,
  437. FULL_REGKEY_DESKTOP,
  438. REGVAL_SCREENSAVEUSEPASSWORD
  439. );
  440. }
  441. //
  442. // Use Setup APIs to scan migration paths section
  443. //
  444. MigrateInf = SetupOpenInfFile (
  445. g_MigrateDotInf,
  446. NULL,
  447. INF_STYLE_WIN4,
  448. NULL
  449. );
  450. if (MigrateInf != INVALID_HANDLE_VALUE) {
  451. if (SetupFindFirstLine (MigrateInf, S_MIGRATION_PATHS, NULL, &ic)) {
  452. do {
  453. if (SetupGetStringField (&ic, 0, FileName, MAX_PATH, NULL)) {
  454. //
  455. // We will be deleting the file, so we must notify Setup
  456. // by writing an entry to [Moved] that has an empty right
  457. // side.
  458. //
  459. MigInf_AddMovedFile (FileName, "");
  460. }
  461. } while (SetupFindNextLine (&ic, &ic));
  462. }
  463. SetupCloseInfFile (MigrateInf);
  464. } else {
  465. return GetLastError();
  466. }
  467. //
  468. // Write memory version of migrate.inf to disk
  469. //
  470. if (!MigInf_WriteInfToDisk()) {
  471. return GetLastError();
  472. }
  473. return ERROR_SUCCESS;
  474. }
  475. LONG
  476. CALLBACK
  477. InitializeNT (
  478. IN LPCWSTR WorkingDirectory,
  479. IN LPCWSTR SourceDirectories,
  480. LPVOID Reserved
  481. )
  482. {
  483. INT Length;
  484. LPCWSTR p;
  485. //
  486. // Save our working directory and source directory. We
  487. // convert UNICODE to ANSI, and we use the system code page.
  488. //
  489. //GetSystemCodePage
  490. //
  491. // Compute length of source directories
  492. //
  493. p = SourceDirectories;
  494. while (*p) {
  495. p = wcschr (p, 0) + 1;
  496. }
  497. p++;
  498. Length = (p - SourceDirectories) / sizeof (WCHAR);
  499. //
  500. // Convert the directories from UNICODE to DBCS. This DLL is
  501. // compiled in ANSI.
  502. //
  503. g_WorkingDirectory = (LPSTR) HeapAlloc (g_hHeap, 0, MAX_PATH);
  504. if (!g_WorkingDirectory) {
  505. return GetLastError();
  506. }
  507. WideCharToMultiByte (
  508. CP_ACP,
  509. 0,
  510. WorkingDirectory,
  511. -1,
  512. g_WorkingDirectory,
  513. MAX_PATH,
  514. NULL,
  515. NULL
  516. );
  517. g_SourceDirectories = (LPSTR) HeapAlloc (g_hHeap, 0, Length * sizeof(WCHAR));
  518. if (!g_SourceDirectories) {
  519. return GetLastError();
  520. }
  521. WideCharToMultiByte (
  522. CP_ACP,
  523. 0,
  524. SourceDirectories,
  525. Length,
  526. g_SourceDirectories,
  527. Length * sizeof (WCHAR),
  528. NULL,
  529. NULL
  530. );
  531. //
  532. // Now generate the derived file names
  533. //
  534. GenerateFilePaths();
  535. //
  536. // Note: We have no use for g_SourceDirectories for the screen saver
  537. // upgrade. The g_SourceDirectories string points to the Windows
  538. // NT media (i.e. e:\i386) and optional directories specified on
  539. // the WINNT32 command line.
  540. //
  541. return ERROR_SUCCESS;
  542. }
  543. LONG
  544. CALLBACK
  545. MigrateUserNT (
  546. IN HINF UnattendInfHandle,
  547. IN HKEY UserRegKey,
  548. IN LPCWSTR UserName,
  549. LPVOID Reserved
  550. )
  551. {
  552. HKEY DesktopRegKey;
  553. DWORD rc = ERROR_SUCCESS;
  554. BOOL b = TRUE;
  555. //
  556. // Setup gives us the UnattendInfHandle instead of the file name,
  557. // so we don't have to open the inf file repeatitively. Since
  558. // Setup opened the handle, let Setup close it.
  559. //
  560. //
  561. // Convert UserName to ANSI
  562. //
  563. if (UserName) {
  564. WideCharToMultiByte (
  565. CP_ACP,
  566. 0,
  567. UserName,
  568. -1,
  569. g_UserNameBuf,
  570. MAX_PATH,
  571. NULL,
  572. NULL
  573. );
  574. g_User = g_UserNameBuf;
  575. } else {
  576. g_User = g_DefaultUser;
  577. }
  578. //
  579. // Setup copies all of the Win9x registry, EXCEPT for the registry
  580. // keys that are suppressed in usermig.inf or wkstamig.inf.
  581. //
  582. // We need the HKCU\Control Panel\Desktop key, and because this is
  583. // an OS key, the settings have been altered. Most applications
  584. // store their settings in HKCU\Software, HKLM\Software or
  585. // HKCC\Software, and all three of these keys are copied in their
  586. // entirety (except the operating system settings in
  587. // Software\Microsoft\Windows).
  588. //
  589. // When the non-OS software settings are copied from Win9x to NT, Setup
  590. // sometimes alters their value. For example, all registry values
  591. // that point to a file that was moved from SYSTEM to SYSTEM32
  592. // are modified to point to the right place.
  593. //
  594. //
  595. // Note: we use CreateRegKey here, but actually the key always exists
  596. // because the NT defaults have been copied into the user's registry
  597. // already. This approach reduces the possibility of failure.
  598. //
  599. DesktopRegKey = CreateRegKey (UserRegKey, REGKEY_DESKTOP);
  600. if (!DesktopRegKey) {
  601. rc = GetLastError();
  602. LOG ((LOG_ERROR, MSG_REGISTRY_ERROR, g_User, rc));
  603. return rc;
  604. }
  605. // The variable b is used to fall through when we fail unexpectedly
  606. b = TranslateGeneralSetting (
  607. DesktopRegKey,
  608. REGVAL_SCREENSAVEACTIVE,
  609. NULL
  610. );
  611. if (b) {
  612. b = TranslateGeneralSetting (
  613. DesktopRegKey,
  614. REGVAL_SCREENSAVELOWPOWERACTIVE,
  615. REGVAL_LOWPOWERACTIVE
  616. );
  617. }
  618. if (b) {
  619. b = TranslateGeneralSetting (
  620. DesktopRegKey,
  621. REGVAL_SCREENSAVELOWPOWERTIMEOUT,
  622. REGVAL_LOWPOWERTIMEOUT
  623. );
  624. }
  625. if (b) {
  626. b = TranslateGeneralSetting (
  627. DesktopRegKey,
  628. REGVAL_SCREENSAVEPOWEROFFACTIVE,
  629. REGVAL_POWEROFFACTIVE
  630. );
  631. }
  632. if (b) {
  633. b = TranslateGeneralSetting (
  634. DesktopRegKey,
  635. REGVAL_SCREENSAVEPOWEROFFTIMEOUT,
  636. REGVAL_POWEROFFTIMEOUT
  637. );
  638. }
  639. if (b) {
  640. b = TranslateGeneralSetting (
  641. DesktopRegKey,
  642. REGVAL_SCREENSAVETIMEOUT,
  643. NULL
  644. );
  645. }
  646. if (b) {
  647. b = TranslateGeneralSetting (
  648. DesktopRegKey,
  649. REGVAL_SCREENSAVEUSEPASSWORD,
  650. REGVAL_SCREENSAVERISSECURE
  651. );
  652. }
  653. if (b) {
  654. b = SaveScrName (DesktopRegKey, S_SCRNSAVE_EXE);
  655. }
  656. if (b) {
  657. //
  658. // For screen savers work differently on Win9x and NT, perform
  659. // translation.
  660. //
  661. TranslateScreenSavers (UserRegKey);
  662. //
  663. // The other settings just need to be copied from control.ini
  664. // to the registry.
  665. //
  666. CopyUntranslatedSettings (UserRegKey);
  667. }
  668. CloseRegKey (DesktopRegKey);
  669. //
  670. // Always return success, because if an error occurred for one user,
  671. // we don't have a reason not to process the next user. If your DLL
  672. // runs into a fatal problem, such as a disk space shortage, you
  673. // should return the error.
  674. //
  675. return ERROR_SUCCESS;
  676. }
  677. LONG
  678. CALLBACK
  679. MigrateSystemNT (
  680. IN HINF UnattendInfHandle,
  681. LPVOID Reserved
  682. )
  683. {
  684. CHAR FileName[MAX_PATH];
  685. HINF MigrateInf;
  686. INFCONTEXT ic;
  687. //
  688. // We now delete the Win9x screen savers that were replaced
  689. // by Windows NT.
  690. //
  691. MigrateInf = SetupOpenInfFile (
  692. g_MigrateDotInf,
  693. NULL,
  694. INF_STYLE_WIN4,
  695. NULL
  696. );
  697. if (MigrateInf != INVALID_HANDLE_VALUE) {
  698. //
  699. // Use Setup APIs to scan migration paths section
  700. //
  701. if (SetupFindFirstLine (MigrateInf, S_MIGRATION_PATHS, NULL, &ic)) {
  702. do {
  703. if (SetupGetStringField (&ic, 0, FileName, MAX_PATH, NULL)) {
  704. //
  705. // All 32-bit binaries located in the Win9x system directory
  706. // were moved to system32. However, since we listed the
  707. // screen savers in [Migration Paths], the screen savers were
  708. // not moved.
  709. //
  710. // Now delete the file. Ignore errors because user may have
  711. // lost power, and we may be going through this a second time.
  712. //
  713. if (!DeleteFile (FileName)) {
  714. if (GetLastError() != ERROR_FILE_NOT_FOUND) {
  715. LOG ((LOG_ERROR, MSG_DELETEFILE_ERROR));
  716. }
  717. } else {
  718. LOG ((LOG_INFORMATION, MSG_DELETEFILE_SUCCESS, FileName));
  719. }
  720. }
  721. } while (SetupFindNextLine (&ic, &ic));
  722. }
  723. SetupCloseInfFile (MigrateInf);
  724. }
  725. return ERROR_SUCCESS;
  726. }
  727. BOOL
  728. pLoadFileNames (
  729. VOID
  730. )
  731. {
  732. PSTR p;
  733. PCSTR Message;
  734. Message = ParseMessage (MSG_FILENAMES);
  735. _mbscpy (g_ExeNamesBuf, Message);
  736. FreeMessage (Message);
  737. if (!g_ExeNamesBuf[0]) {
  738. return FALSE;
  739. }
  740. p = g_ExeNamesBuf;
  741. while (*p) {
  742. if (_mbsnextc (p) == '|') {
  743. *p = 0;
  744. }
  745. p = _mbsinc (p);
  746. }
  747. return TRUE;
  748. }