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.

813 lines
28 KiB

  1. /* INIT.C
  2. Resident Code Segment // Tweak: make non-resident
  3. Initialization and destroy routines
  4. InitFrost()
  5. CloseFrost()
  6. Frosting: Master Theme Selector for Windows '95
  7. Copyright (c) 1994-1999 Microsoft Corporation. All rights reserved.
  8. */
  9. // ---------------------------------------------
  10. // Brief file history:
  11. // Alpha:
  12. // Beta:
  13. // Bug fixes
  14. // ---------
  15. //
  16. // ---------------------------------------------
  17. #include "windows.h"
  18. #include "frost.h"
  19. #include "global.h"
  20. #include "schedule.h"
  21. #include "htmlprev.h"
  22. // Local Routines
  23. BOOL InitInstance(HINSTANCE, HINSTANCE, int);
  24. BOOL GetRotateTheme(LPTSTR);
  25. // Globals
  26. TCHAR szPlus_CurTheme[] = TEXT("Software\\Microsoft\\Plus!\\Themes\\Current");
  27. TCHAR szPlus_CBs[] = TEXT("Software\\Microsoft\\Plus!\\Themes\\Apply");
  28. #define bThemed (*szCurThemeFile)
  29. // Reg paths for finding potential Theme directories
  30. #define PLUS95_KEY TEXT("Software\\Microsoft\\Plus!\\Setup")
  31. #define PLUS95_PATH TEXT("DestPath")
  32. #define PLUS98_KEY TEXT("Software\\Microsoft\\Plus!98")
  33. #define PLUS98_PATH TEXT("Path")
  34. #define KIDS_KEY TEXT("Software\\Microsoft\\Microsoft Kids\\Kids Plus!")
  35. #define KIDS_PATH TEXT("InstallDir")
  36. #define PROGRAMFILES_KEY TEXT("Software\\Microsoft\\Windows\\CurrentVersion")
  37. #define PROGRAMFILES_PATH TEXT("ProgramFilesDir")
  38. // ProcessCmdLine
  39. //
  40. // Very basic commandline: "/s themefile" to apply theme
  41. // "themefile" to open app with theme selected
  42. // and curdir to be that file's dir
  43. //
  44. // Return: TRUE if we should exit the app
  45. // FALSE to continue execution
  46. //
  47. BOOL ProcessCmdLine(LPTSTR lpCmdLine)
  48. {
  49. extern TCHAR szFrostSection[], szMagic[], szVerify[];
  50. BOOL fSetTheme = FALSE;
  51. BOOL fRotateTheme = FALSE;
  52. LPTSTR lpszThemeFile;
  53. BOOL fStopOnQuote = FALSE;
  54. WIN32_FIND_DATA wfdFind;
  55. HANDLE hFind;
  56. TCHAR szRotateTheme[MAX_PATH];
  57. // TCHAR szThemesExe[MAX_PATH];
  58. DWORD dwRet;
  59. HKEY hKey;
  60. extern TCHAR szPlus_CurTheme[];
  61. Assert(0, TEXT("Cmd line: '"));
  62. Assert(0, lpCmdLine);
  63. Assert(0, TEXT("'\n"));
  64. // Skip leading whitespace.
  65. while (*lpCmdLine && (*lpCmdLine != TEXT('/')))
  66. lpCmdLine = CharNext(lpCmdLine);
  67. // Check for special switches.
  68. if (*lpCmdLine == TEXT('/')) {
  69. lpCmdLine = CharNext(lpCmdLine);
  70. switch (*lpCmdLine) {
  71. // "Set" theme as active.
  72. case TEXT('s'):
  73. case TEXT('S'):
  74. fSetTheme = TRUE;
  75. lpCmdLine = CharNext(lpCmdLine);
  76. break;
  77. case TEXT('r'):
  78. case TEXT('R'):
  79. fRotateTheme = TRUE;
  80. lpCmdLine = CharNext(lpCmdLine);
  81. break;
  82. default:
  83. return FALSE; // invalid flag so continue execution EXIT
  84. }
  85. while (*lpCmdLine == TEXT(' '))
  86. lpCmdLine = CharNext(lpCmdLine);
  87. }
  88. // Handle quoted long file names. Even if the name isn't quoted, we'll
  89. // still parse to the end of the commandline.
  90. if (*lpCmdLine == TEXT('\"')) {
  91. fStopOnQuote = TRUE;
  92. lpCmdLine = CharNext(lpCmdLine);
  93. }
  94. lpszThemeFile = lpCmdLine;
  95. // Parse until end of line or we find the closing quote.
  96. while (*lpCmdLine && !(fStopOnQuote && *lpCmdLine == TEXT('\"')))
  97. lpCmdLine = CharNext(lpCmdLine);
  98. // Back up to the last non-whitespace character.
  99. while (lpCmdLine > lpszThemeFile && *(lpCmdLine-1) == TEXT(' '))
  100. lpCmdLine = CharPrev(lpszThemeFile, lpCmdLine);
  101. // If there's anything after the closing quote, so what?
  102. *lpCmdLine = TEXT('\0');
  103. // This is our chance to fake a theme rotation "/r" into the
  104. // "/s" paradigm. Let's get a string to the next theme in the
  105. // rotation.
  106. if (fRotateTheme) {
  107. if (GetRotateTheme(szRotateTheme)) {
  108. fSetTheme = TRUE;
  109. lpszThemeFile = szRotateTheme;
  110. }
  111. // GetRotateTheme failed. If we fall through we're likely
  112. // to display the main dialog and we don't want to do that
  113. // in the "/r" case. Just exit the app.
  114. else return TRUE;
  115. }
  116. // After all that work, nothing was specified on the commandline.
  117. if (lpszThemeFile == lpCmdLine)
  118. return FALSE; // no filename so continue execution EXIT
  119. //
  120. // OK: you've got a theme file. if it is for real, save it for use.
  121. // first check existence
  122. hFind = FindFirstFile(lpszThemeFile, (LPWIN32_FIND_DATA)&wfdFind);
  123. if (INVALID_HANDLE_VALUE == hFind)
  124. return (TRUE); // file doesn't exist so continue execution EXIT
  125. // PLUS98 BUG 1293 -- this used to return FALSE
  126. // and open the Theme applet if /s had an invalid
  127. // file. Now we return TRUE which closes Themes
  128. // then check for magic string
  129. GetPrivateProfileString((LPTSTR)szFrostSection,
  130. (LPTSTR)szMagic,
  131. (LPTSTR)szNULL,
  132. (LPTSTR)szMsg, MAX_MSGLEN,
  133. lpszThemeFile);
  134. // magic str check
  135. if (lstrcmp((LPTSTR)szMsg, (LPTSTR)szVerify)) {
  136. // No magic string so this must not be a real theme file.
  137. // If this was from a "/r" rotate we want to return TRUE and
  138. // bail out. Otherwise return FALSE so we open the Theme
  139. // app. (this was the existing Plus 95 behavior):
  140. if (fRotateTheme) return (TRUE);
  141. else return (FALSE);
  142. }
  143. //
  144. // get the confirmed theme into the necessary globals
  145. // save theme file using the long filename
  146. lstrcpy(szCurThemeFile, lpszThemeFile); // actual pathname verified
  147. // save cur dir (not theme dir)
  148. lstrcpy(szCurDir, szCurThemeFile);
  149. *(FileFromPath(szCurDir)) = 0;
  150. // save theme name
  151. lstrcpy(szCurThemeName, wfdFind.cFileName); // make sure long filename
  152. TruncateExt(szCurThemeName);
  153. // now maybe we just want to apply the theme and exit
  154. if (fSetTheme) {
  155. // Make sure there is even enough space to do theme
  156. // But don't complain, if there isn't
  157. if (! CheckSpace (NULL, FALSE)) // definition in Regutils.c
  158. return FALSE;
  159. // Make the apply code write out everything.
  160. InitCheckboxes();
  161. // Simulate a left shift keypress to wake up the screensaver.
  162. // Otherwise if the SS is running and we apply a new SS you
  163. // can wind up with dueling savers...
  164. keybd_event(VK_LSHIFT, 0, 0, 0);
  165. keybd_event(VK_LSHIFT, 0, KEYEVENTF_KEYUP, 0);
  166. ApplyThemeFile(lpszThemeFile);
  167. // APPCOMPAT -- Plus95 Themes was not updating the Current Theme
  168. // setting in the registry on this codepath. Need to fix that
  169. // here.
  170. dwRet = RegOpenKeyEx(HKEY_CURRENT_USER, szPlus_CurTheme,
  171. (DWORD)0, KEY_SET_VALUE, (PHKEY)&hKey );
  172. if (dwRet != ERROR_SUCCESS) {
  173. DWORD dwDisposition;
  174. Assert(FALSE, TEXT("couldn't RegOpenKey save theme file\n"));
  175. dwRet = RegCreateKeyEx( HKEY_CURRENT_USER, szPlus_CurTheme,
  176. (DWORD)0, (LPTSTR)szNULL, REG_OPTION_NON_VOLATILE,
  177. KEY_SET_VALUE, (LPSECURITY_ATTRIBUTES)NULL,
  178. (PHKEY)&hKey, (LPDWORD)&dwDisposition );
  179. }
  180. // if open or create worked
  181. if (dwRet == ERROR_SUCCESS) {
  182. dwRet = RegSetValueEx(hKey, (LPTSTR)NULL, // default value
  183. 0,
  184. (DWORD)REG_SZ,
  185. (LPBYTE)lpszThemeFile,
  186. (DWORD)( SZSIZEINBYTES((LPTSTR)szCurThemeFile) + 1 ));
  187. RegCloseKey(hKey);
  188. }
  189. Assert(dwRet == ERROR_SUCCESS, TEXT("couldn't open, set or create Registry save theme file\n"));
  190. return TRUE; // set the theme so now just exit app EXIT
  191. } // end if fSetTheme
  192. return FALSE; // continue execution
  193. }
  194. // InitFrost
  195. // Since there are no window classes to register, this routine just loads
  196. // the strings and, since there's only one instance, calls InitInstance().
  197. //
  198. // Returns: success of initialization
  199. BOOL FAR InitFrost(hPrevInstance, hInstance, lpCmdLine, nCmdShow)
  200. HINSTANCE hPrevInstance;
  201. HINSTANCE hInstance; /* Current instance identifier. */
  202. LPTSTR lpCmdLine;
  203. int nCmdShow; /* Param for first ShowWindow() call. */
  204. {
  205. LPTSTR lpScan, lpTemp;
  206. WNDCLASS WndClass;
  207. BOOL bret;
  208. BOOL bGotThemeDir;
  209. HDC hdc;
  210. //
  211. // Get initial strings
  212. // (Gauranteed enough mem at app init for these loads)
  213. InitNoMem(hInstance);
  214. LoadString(hInstance, STR_APPNAME, szAppName, MAX_STRLEN);
  215. LoadString(hInstance, STR_CURSET, szCurSettings, MAX_STRLEN);
  216. LoadString(hInstance, STR_PREVSET, szPrevSettings, MAX_STRLEN);
  217. LoadString(hInstance, STR_PREVSETFILE, szPrevSettingsFilename, MAX_STRLEN);
  218. LoadString(hInstance, STR_OTHERTHM, szOther, MAX_STRLEN);
  219. LoadString(hInstance, STR_THMEXT, szExt, MAX_STRLEN);
  220. LoadString(hInstance, STR_PREVIEWTITLE, szPreviewTitle, MAX_STRLEN);
  221. LoadString(hInstance, STR_HELPFILE, szHelpFile, MAX_STRLEN);
  222. LoadString(hInstance, STR_HELPFILE98, szHelpFile98, MAX_STRLEN);
  223. LoadString(hInstApp, STR_SUGGEST, szNewFile, MAX_STRLEN);
  224. LoadString(hInstApp, STR_SAVETITLE, szSaveTitle, MAX_STRLEN);
  225. LoadString(hInstApp, STR_OPENTITLE, szOpenTitle, MAX_STRLEN);
  226. LoadString(hInstApp, STR_FILETYPE, szFileTypeDesc, MAX_STRLEN);
  227. WndClass.style = CS_DBLCLKS | CS_BYTEALIGNWINDOW | CS_GLOBALCLASS;
  228. WndClass.lpfnWndProc = DefDlgProc;
  229. WndClass.cbClsExtra = 0;
  230. WndClass.cbWndExtra = DLGWINDOWEXTRA;
  231. WndClass.hInstance = hInstApp;
  232. WndClass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(FROST_ICON));
  233. WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
  234. WndClass.hbrBackground = (HBRUSH) (COLOR_3DFACE + 1);
  235. WndClass.lpszMenuName = NULL;
  236. WndClass.lpszClassName = szClassName;
  237. if (!RegisterClass(&WndClass))
  238. return FALSE;
  239. // Initialize our g_bGradient flag
  240. hdc = GetDC(NULL);
  241. g_bGradient = (BOOL)(GetDeviceCaps(hdc, BITSPIXEL) > 8);
  242. ReleaseDC(NULL, hdc);
  243. //
  244. // build file search string
  245. lpScan = (LPTSTR)szFileTypeDesc;
  246. while (*lpScan) {
  247. if (2 == CompareString(LOCALE_USER_DEFAULT, NORM_IGNOREWIDTH,
  248. (LPTSTR)TEXT("|"), 1, lpScan, 1)) {
  249. lpTemp = lpScan;
  250. lpScan = CharNext(lpScan);
  251. *lpTemp = 0;
  252. }
  253. else
  254. lpScan = CharNext(lpScan);
  255. }
  256. //
  257. // init directory strings
  258. // theme directory - for now it is subdir of EXE dir
  259. GetModuleFileName(hInstApp, (LPTSTR)szThemeDir, MAX_PATHLEN);
  260. *(FileFromPath((LPTSTR)szThemeDir)) = 0; // leaves trailing '\'
  261. // Save this path momentarily -- if we can't find any good Themes
  262. // directory we're going to fall back to this directory.
  263. lstrcpy(szCurDir, szThemeDir);
  264. // Tack a "Themes" onto the path
  265. LoadString(hInstance, STR_THEMESUBDIR, // includes trailing '\'
  266. (LPTSTR)(szThemeDir + lstrlen((LPTSTR)szThemeDir)), MAX_STRLEN);
  267. // Find out if this ThemeDir even exists. If it doesn't we need
  268. // to get creative in finding our ThemeDir by searching the
  269. // following locales:
  270. //
  271. // Plus!98 Install Path\Themes
  272. // Plus!95 Install Path\Themes
  273. // Kids for Plus! Install Path\Themes
  274. // Program Files\Plus!\Themes
  275. bGotThemeDir = FALSE;
  276. Assert(0, TEXT("Themes.exe\\Themes path: "));
  277. Assert(0, szThemeDir);
  278. Assert(0, TEXT("\n"));
  279. if (0xFFFFFFFF != GetFileAttributes(szThemeDir)) bGotThemeDir = TRUE;
  280. if (!bGotThemeDir)
  281. {
  282. // Haven't found ThemeDir yet. Try the Plus!98 location
  283. bret = HandGet(HKEY_LOCAL_MACHINE, PLUS98_KEY,
  284. PLUS98_PATH, (LPTSTR)szThemeDir);
  285. if (bret)
  286. {
  287. // Tack a "Themes" onto the path
  288. lstrcat(szThemeDir, TEXT("\\"));
  289. LoadString(hInstance, STR_THEMESUBDIR,
  290. (szThemeDir + lstrlen((LPTSTR)szThemeDir)), MAX_STRLEN);
  291. Assert(0, TEXT("Plus! 98 path: "));
  292. Assert(0, szThemeDir);
  293. Assert(0, TEXT("\n"));
  294. if (0xFFFFFFFF != GetFileAttributes(szThemeDir)) bGotThemeDir = TRUE;
  295. }
  296. }
  297. if (!bGotThemeDir)
  298. {
  299. // Still haven't found ThemeDir. Try the Plus! 95 location
  300. bret = HandGet(HKEY_LOCAL_MACHINE, PLUS95_KEY,
  301. PLUS95_PATH, (LPTSTR)szThemeDir);
  302. if (bret)
  303. {
  304. // Tack on a "Themes" onto the path
  305. // Plus!95 DestPath has "Plus!.dll" on the end so get rid
  306. // of that.
  307. *(FileFromPath(szThemeDir)) = 0;
  308. LoadString(hInstance, STR_THEMESUBDIR,
  309. (szThemeDir + lstrlen((LPTSTR)szThemeDir)), MAX_STRLEN);
  310. Assert(0, TEXT("Plus! 95 path: "));
  311. Assert(0, szThemeDir);
  312. Assert(0, TEXT("\n"));
  313. if (0xFFFFFFFF != GetFileAttributes(szThemeDir)) bGotThemeDir = TRUE;
  314. }
  315. }
  316. if (!bGotThemeDir)
  317. {
  318. // Still haven't found ThemeDir. Try the Kids for Plus! location
  319. bret = HandGet(HKEY_LOCAL_MACHINE, KIDS_KEY,
  320. KIDS_PATH, (LPTSTR)szThemeDir);
  321. if (bret)
  322. {
  323. // Tack a "\Plus! for Kids\Themes" onto the path
  324. lstrcat(szThemeDir, TEXT("\\Plus! for Kids\\"));
  325. LoadString(hInstance, STR_THEMESUBDIR,
  326. (szThemeDir + lstrlen((LPTSTR)szThemeDir)), MAX_STRLEN);
  327. Assert(0, TEXT("Kids Plus! path: "));
  328. Assert(0, szThemeDir);
  329. Assert(0, TEXT("\n"));
  330. if (0xFFFFFFFF != GetFileAttributes(szThemeDir)) bGotThemeDir = TRUE;
  331. }
  332. }
  333. if (!bGotThemeDir)
  334. {
  335. // Still haven't found ThemeDir. Try the Program Files\Plus! location
  336. bret = HandGet(HKEY_LOCAL_MACHINE, PROGRAMFILES_KEY,
  337. PROGRAMFILES_PATH, (LPTSTR)szThemeDir);
  338. if (bret)
  339. {
  340. // Tack a "Plus!\Themes" onto the path
  341. lstrcat(szThemeDir, TEXT("\\Plus!\\"));
  342. LoadString(hInstance, STR_THEMESUBDIR,
  343. (szThemeDir + lstrlen((LPTSTR)szThemeDir)), MAX_STRLEN);
  344. Assert(0, TEXT("Program Files path: "));
  345. Assert(0, szThemeDir);
  346. Assert(0, TEXT("\n"));
  347. if (0xFFFFFFFF != GetFileAttributes(szThemeDir)) bGotThemeDir = TRUE;
  348. }
  349. }
  350. if (!bGotThemeDir)
  351. {
  352. // After all that searching we still haven't found a good Theme
  353. // dir. So we'll just use the directory where Themes.exe is
  354. // located -- we saved this in szCurDir before we started this
  355. // search process.
  356. lstrcpy(szThemeDir, szCurDir);
  357. Assert(0, TEXT("Themes.exe path: "));
  358. Assert(0, szThemeDir);
  359. Assert(0, TEXT("\n"));
  360. }
  361. // default current dir
  362. lstrcpy((LPTSTR)szCurDir, (LPTSTR)szThemeDir);
  363. // Windows directory
  364. GetWindowsDirectory((LPTSTR)szWinDir, MAX_PATHLEN);
  365. if (TEXT('\\') != szWinDir[lstrlen((LPTSTR)szWinDir)-1])
  366. lstrcat((LPTSTR)szWinDir, (LPTSTR)TEXT("\\"));
  367. //
  368. // see if there is a previous theme file to return to
  369. bret = HandGet(HKEY_CURRENT_USER, szPlus_CurTheme,
  370. (LPTSTR)NULL, (LPTSTR)szMsg);
  371. Assert(bret, TEXT("no previous theme file in Registry!\n"));
  372. if (bret) {
  373. // get init cur dir from prev theme file
  374. lstrcpy(szCurDir, szMsg);
  375. *(FileFromPath(szCurDir)) = 0;
  376. // Used to actually set the cur theme file/name to prev theme.
  377. // Now we just use the directory if there is a prev theme.
  378. // No longer care if it is a real file or a theme file or not.
  379. #ifdef REVERT
  380. WIN32_FIND_DATA wfdFind;
  381. HANDLE hFind;
  382. extern TCHAR szFrostSection[], szMagic[], szVerify[];
  383. TCHAR szMagicTest[MAX_STRLEN+1];
  384. // first check if it is for real: existence
  385. hFind = FindFirstFile(szMsg, (LPWIN32_FIND_DATA)&wfdFind);
  386. if (INVALID_HANDLE_VALUE != hFind) {
  387. // then check if it is for real: theme file magic string
  388. GetPrivateProfileString((LPTSTR)szFrostSection,
  389. (LPTSTR)szMagic,
  390. (LPTSTR)szNULL,
  391. (LPTSTR)szMagicTest, MAX_STRLEN,
  392. szMsg);
  393. if (!lstrcmp((LPTSTR)szMagicTest, (LPTSTR)szVerify)) {
  394. //
  395. // now you're convinced that the prev theme file is legit
  396. //
  397. // then use it to set some globals
  398. lstrcpy(szCurThemeFile, szMsg);
  399. // save cur dir (not theme dir)
  400. lstrcpy(szCurDir, szCurThemeFile);
  401. *(FileFromPath(szCurDir)) = 0;
  402. // save theme name
  403. lstrcpy(szCurThemeName, FileFromPath(szCurThemeFile));
  404. TruncateExt(szCurThemeName);
  405. }
  406. }
  407. #endif // REVERT
  408. }
  409. // then look if there is a command line that may override things
  410. if (ProcessCmdLine(lpCmdLine))
  411. return TRUE; // don't run app EXIT, hWndApp==NULL as flag
  412. // Single-instance application can call InitInstance() here
  413. // Return success of inst initialization
  414. return(InitInstance(hPrevInstance, hInstance, nCmdShow));
  415. }
  416. // InitInstance
  417. // Create main window; assign globals for instance and window handles.
  418. //
  419. // Returns: success of initialization
  420. BOOL InitInstance(hPrevInstance, hInstance, nCmdShow)
  421. HINSTANCE hPrevInstance;
  422. HINSTANCE hInstance; /* Current instance identifier. */
  423. int nCmdShow; /* Param for first ShowWindow() call. */
  424. {
  425. RECT rWndApp, rWorkArea;
  426. TCHAR szThemesExe[MAX_PATH];
  427. // assign global instance handle
  428. hInstApp = hInstance;
  429. // create main window and assign global window handle
  430. bNoMem = FALSE; // clear out of mem flag
  431. hWndApp = CreateDialog( hInstApp,
  432. MAKEINTRESOURCE(DLG_MAIN),
  433. (HWND)NULL,
  434. PreviewDlgProc
  435. );
  436. if (!hWndApp || bNoMem) // if problems, then bail
  437. return (FALSE);
  438. InitHTMLBM(); // Init the IThumbnail interface for HTML wallpaper support
  439. // have to init preview painting stuff after create dlg
  440. if (!PreviewInit()) {
  441. DestroyWindow(hWndApp);
  442. return (FALSE); // low mem on dc/bmp create EXIT
  443. }
  444. // this doesn't work from WM_INITDIALOG, so added here, too
  445. InitCheckboxes(); // init stored values
  446. RestoreCheckboxes(); // init actual cbs from stored values
  447. if (bThemed) // kinda kludgy to put here but it works
  448. EnableWindow(GetDlgItem(hWndApp, PB_SAVE), FALSE);
  449. // also, can now make init Preview bmp for init paint
  450. BuildPreviewBitmap((LPTSTR)szCurThemeFile);
  451. // center main window on screen
  452. GetWindowRect(hWndApp, (LPRECT)&rWndApp);
  453. SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID)(LPRECT)&rWorkArea, 0);
  454. MoveWindow(hWndApp,
  455. ((rWorkArea.right-rWorkArea.left) - (rWndApp.right-rWndApp.left))/2,
  456. ((rWorkArea.bottom-rWorkArea.top) - (rWndApp.bottom-rWndApp.top))/2,
  457. // (GetSystemMetrics(SM_CXSCREEN) - (rWndApp.right-rWndApp.left))/2,
  458. // (GetSystemMetrics(SM_CYSCREEN) - (rWndApp.bottom-rWndApp.top))/2,
  459. rWndApp.right-rWndApp.left, rWndApp.bottom-rWndApp.top,
  460. FALSE); // don't repaint
  461. // Make the main window visible; update its client area
  462. ShowWindow(hWndApp, nCmdShow); /* Show the window */
  463. UpdateWindow(hWndApp); /* Sends WM_PAINT message */
  464. // Check to see if CB_SCHEDULE is checked and verify that Task
  465. // Scheduler is running and the Themes task exists as appropriate
  466. if (bCBStates[FC_SCHEDULE]) {
  467. if (IsTaskSchedulerRunning()) {
  468. if (!IsThemesScheduled()) {
  469. GetModuleFileName(hInstApp, (LPTSTR)szThemesExe, MAX_PATH);
  470. if (!AddThemesTask(szThemesExe, TRUE /*Show errors*/)) {
  471. // Couldn't add task -- ATT gave error but need to clear
  472. // SCHEDULE CB
  473. bCBStates[FC_SCHEDULE] = FALSE;
  474. RestoreCheckboxes();
  475. SaveStates(); // Write checkbox states to registry
  476. }
  477. } // Themes.job exists so do nothing
  478. }
  479. else {
  480. // Zonk -- Task Scheduler isn't running. Start it.
  481. if (StartTaskScheduler(TRUE /*prompt user*/)) {
  482. // Task scheduler started -- check if themes task already
  483. // exists
  484. if (!IsThemesScheduled()) {
  485. GetModuleFileName(hInstApp, (LPTSTR)szThemesExe, MAX_PATH);
  486. if (!AddThemesTask(szThemesExe, TRUE /*Show errors*/)) {
  487. // Couldn't add task -- ATT gave error but need to clear
  488. // SCHEDULE CB
  489. bCBStates[FC_SCHEDULE] = FALSE;
  490. RestoreCheckboxes();
  491. SaveStates(); // Write checkbox states to registry
  492. }
  493. } //TS is running now and Themes.job exists
  494. }
  495. else {
  496. // Couldn't start TS -- STS() gave error. Need to clear
  497. // SCHEDULE CB and HandDelete any existing Themes.job.
  498. // CheckDlgButton(hdlg, CB_SCHEDULE, BST_UNCHECKED);
  499. bCBStates[FC_SCHEDULE] = FALSE;
  500. RestoreCheckboxes();
  501. SaveStates(); // Write checkbox states to the registry
  502. HandDeleteThemesTask();
  503. }
  504. } // END ELSE Task Scheduler isn't running
  505. }
  506. else { // bCBStates[FC_CHECKBOX] != TRUE
  507. // SCHEDULE Checkbox is clear -- should delete Themes task.
  508. if (IsTaskSchedulerRunning()) DeleteThemesTask();
  509. else HandDeleteThemesTask();
  510. }
  511. // cleanup
  512. return (TRUE); // success
  513. }
  514. // CloseFrost
  515. //
  516. // Cleanup your objects, thunks, etc.
  517. //
  518. void FAR CloseFrost()
  519. {
  520. // just extra tidy housekeeping
  521. hWndApp = NULL;
  522. hInstApp = NULL;
  523. PreviewDestroy();
  524. }
  525. // SaveStates
  526. //
  527. // Remember persistent states: currently checkboxes.
  528. // Last applied theme is remembered at Apply time.
  529. //
  530. void FAR SaveStates()
  531. {
  532. LONG lret;
  533. HKEY hKey;
  534. int iter;
  535. //
  536. // checkboxes
  537. //
  538. lret = RegOpenKeyEx(HKEY_CURRENT_USER, szPlus_CBs,
  539. (DWORD)0, KEY_SET_VALUE, (PHKEY)&hKey );
  540. if (lret != ERROR_SUCCESS) {
  541. DWORD dwDisposition;
  542. Assert(FALSE, TEXT("couldn't RegOpenKey save checkboxes\n"));
  543. lret = RegCreateKeyEx( HKEY_CURRENT_USER, szPlus_CBs,
  544. (DWORD)0, (LPTSTR)szNULL, REG_OPTION_NON_VOLATILE,
  545. KEY_SET_VALUE, (LPSECURITY_ATTRIBUTES)NULL,
  546. (PHKEY)&hKey, (LPDWORD)&dwDisposition );
  547. }
  548. // if open or create worked
  549. if (lret == ERROR_SUCCESS) {
  550. for (iter = 0; iter < MAX_FCHECKS; iter ++) {
  551. if (bThemed)
  552. RegSetValueEx(hKey, (LPTSTR)szCBNames[iter],
  553. 0,
  554. (DWORD)REG_SZ,
  555. (LPBYTE)(IsDlgButtonChecked(hWndApp, iCBIDs[iter]) ?
  556. TEXT("1") : TEXT("0")),
  557. (DWORD)2*sizeof(TCHAR));
  558. else // cur win settings --> real states saved in bCBStates[]
  559. RegSetValueEx(hKey, (LPTSTR)szCBNames[iter],
  560. 0,
  561. (DWORD)REG_SZ,
  562. (LPBYTE)(bCBStates[iter] ? TEXT("1") : TEXT("0")),
  563. (DWORD)2*sizeof(TCHAR));
  564. }
  565. // close when finished
  566. RegCloseKey(hKey);
  567. }
  568. else {
  569. Assert(FALSE, TEXT("couldn't open or create Registry save checkboxes\n"));
  570. }
  571. }
  572. BOOL GetRotateTheme(LPTSTR lpszRotateTheme)
  573. {
  574. BOOL bRet = FALSE;
  575. TCHAR szThemesdir[MAX_PATH];
  576. HANDLE hFF;
  577. WIN32_FIND_DATA FindData;
  578. // WARNING -- If "next" .Theme file is not valid theme file we'll never rotate!
  579. // See if there is a current theme.
  580. szThemesdir[0] = TEXT('\0');
  581. bRet = HandGet(HKEY_CURRENT_USER, szPlus_CurTheme,
  582. (LPTSTR)NULL, (LPTSTR)szThemesdir);
  583. // Do we have a current Theme?
  584. hFF = INVALID_HANDLE_VALUE;
  585. if (szThemesdir[0]) {
  586. // Yes we do, so do a FindFirst on it and make sure we've
  587. // got the long filename.
  588. ZeroMemory(&FindData, sizeof(WIN32_FIND_DATA));
  589. hFF = FindFirstFile(szThemesdir, &FindData);
  590. }
  591. // Did we find the file on FindFirst? If so, proceed with finding
  592. // the next Theme in that directory else assume that the registry's
  593. // Current Theme setting is bogus and look in the default dir.
  594. if (INVALID_HANDLE_VALUE != hFF) {
  595. // Copy long filename.
  596. lstrcpy(lpszRotateTheme, FindData.cFileName);
  597. FindClose(hFF);
  598. // We've got the longfilename to the current Theme
  599. // Now do a FF/FN on *.Theme in the Theme dir until
  600. // we find the current theme.
  601. // Strip the theme file off the path.
  602. *(FileFromPath(szThemesdir)) = 0;
  603. lstrcat(szThemesdir, TEXT("*\0"));
  604. LoadString(NULL, STR_THMEXT, (szThemesdir + lstrlen(szThemesdir)),
  605. MAX_PATH);
  606. ZeroMemory(&FindData, sizeof(WIN32_FIND_DATA));
  607. hFF = FindFirstFile(szThemesdir, &FindData);
  608. if (INVALID_HANDLE_VALUE == hFF) {
  609. // We shouldn't hit this since we just found our current
  610. // theme in this directory. If we do, just bail out.
  611. lpszRotateTheme[0] = TEXT('\0');
  612. return FALSE;
  613. }
  614. // Step through the .Theme files in this dir until we find our
  615. // current theme file.
  616. bRet = TRUE;
  617. while (lstrcmp(FindData.cFileName, lpszRotateTheme) && bRet) {
  618. bRet = FindNextFile(hFF, &FindData);
  619. }
  620. if (lstrcmp(FindData.cFileName, lpszRotateTheme)) {
  621. // We ran out of files before finding the current theme!?!?
  622. // Not likely... Bail out.
  623. FindClose(hFF);
  624. lpszRotateTheme[0] = TEXT('\0');
  625. return FALSE;
  626. }
  627. // Assume the FindNext file is our current theme. Let's
  628. // get the Next .Theme file -- that's what we're rotating to...
  629. if (FindNextFile(hFF, &FindData)) {
  630. *(FileFromPath(szThemesdir)) = 0;
  631. lstrcat(szThemesdir, FindData.cFileName);
  632. lstrcpy(lpszRotateTheme, szThemesdir);
  633. FindClose(hFF);
  634. return TRUE;
  635. }
  636. // OK, we failed to find another Theme file in the current dir
  637. // so assume our current Theme is the last in the list. Go
  638. // back to the beginning and use the first Theme file we find
  639. // as our "rotate to" theme.
  640. else {
  641. FindClose(hFF);
  642. ZeroMemory(&FindData, sizeof(WIN32_FIND_DATA));
  643. hFF = FindFirstFile(szThemesdir, &FindData);
  644. if (INVALID_HANDLE_VALUE == hFF) {
  645. // This shouldn't fail since we just found our current
  646. // theme in this dir. If it does, bail out.
  647. lpszRotateTheme[0] = TEXT('\0');
  648. return FALSE;
  649. }
  650. // This is our new/rotate file
  651. *(FileFromPath(szThemesdir)) = 0;
  652. lstrcat(szThemesdir, FindData.cFileName);
  653. lstrcpy (lpszRotateTheme, szThemesdir);
  654. FindClose(hFF);
  655. return TRUE;
  656. }
  657. }
  658. // No current theme applied or the Current Theme setting in the
  659. // registry is bogus so use the global szThemeDir setting and
  660. // look for a theme in that directory.
  661. else {
  662. lstrcpy(szThemesdir, szThemeDir);
  663. lstrcat(szThemesdir, TEXT("*\0"));
  664. LoadString(NULL, STR_THMEXT, (szThemesdir + lstrlen(szThemesdir)),
  665. MAX_PATH);
  666. ZeroMemory(&FindData, sizeof(WIN32_FIND_DATA));
  667. hFF = FindFirstFile(szThemesdir, &FindData);
  668. if (INVALID_HANDLE_VALUE == hFF) {
  669. // Apparently there are no themes available in the default
  670. // Themes directory. We're hosed -- no rotation today.
  671. lpszRotateTheme[0] = TEXT('\0');
  672. return FALSE;
  673. }
  674. // This is our new/rotate file
  675. *(FileFromPath(szThemesdir)) = 0;
  676. lstrcat(szThemesdir, FindData.cFileName);
  677. lstrcpy (lpszRotateTheme, szThemesdir);
  678. FindClose(hFF);
  679. return TRUE;
  680. }
  681. return FALSE;
  682. }