814 lines
28 KiB
C
814 lines
28 KiB
C
|
/* INIT.C
|
||
|
Resident Code Segment // Tweak: make non-resident
|
||
|
|
||
|
Initialization and destroy routines
|
||
|
|
||
|
InitFrost()
|
||
|
CloseFrost()
|
||
|
|
||
|
Frosting: Master Theme Selector for Windows '95
|
||
|
Copyright (c) 1994-1999 Microsoft Corporation. All rights reserved.
|
||
|
*/
|
||
|
|
||
|
// ---------------------------------------------
|
||
|
// Brief file history:
|
||
|
// Alpha:
|
||
|
// Beta:
|
||
|
// Bug fixes
|
||
|
// ---------
|
||
|
//
|
||
|
// ---------------------------------------------
|
||
|
|
||
|
#include "windows.h"
|
||
|
#include "frost.h"
|
||
|
#include "global.h"
|
||
|
#include "schedule.h"
|
||
|
#include "htmlprev.h"
|
||
|
|
||
|
// Local Routines
|
||
|
BOOL InitInstance(HINSTANCE, HINSTANCE, int);
|
||
|
BOOL GetRotateTheme(LPTSTR);
|
||
|
|
||
|
// Globals
|
||
|
TCHAR szPlus_CurTheme[] = TEXT("Software\\Microsoft\\Plus!\\Themes\\Current");
|
||
|
TCHAR szPlus_CBs[] = TEXT("Software\\Microsoft\\Plus!\\Themes\\Apply");
|
||
|
|
||
|
#define bThemed (*szCurThemeFile)
|
||
|
|
||
|
// Reg paths for finding potential Theme directories
|
||
|
#define PLUS95_KEY TEXT("Software\\Microsoft\\Plus!\\Setup")
|
||
|
#define PLUS95_PATH TEXT("DestPath")
|
||
|
#define PLUS98_KEY TEXT("Software\\Microsoft\\Plus!98")
|
||
|
#define PLUS98_PATH TEXT("Path")
|
||
|
#define KIDS_KEY TEXT("Software\\Microsoft\\Microsoft Kids\\Kids Plus!")
|
||
|
#define KIDS_PATH TEXT("InstallDir")
|
||
|
#define PROGRAMFILES_KEY TEXT("Software\\Microsoft\\Windows\\CurrentVersion")
|
||
|
#define PROGRAMFILES_PATH TEXT("ProgramFilesDir")
|
||
|
|
||
|
// ProcessCmdLine
|
||
|
//
|
||
|
// Very basic commandline: "/s themefile" to apply theme
|
||
|
// "themefile" to open app with theme selected
|
||
|
// and curdir to be that file's dir
|
||
|
//
|
||
|
// Return: TRUE if we should exit the app
|
||
|
// FALSE to continue execution
|
||
|
//
|
||
|
BOOL ProcessCmdLine(LPTSTR lpCmdLine)
|
||
|
{
|
||
|
extern TCHAR szFrostSection[], szMagic[], szVerify[];
|
||
|
BOOL fSetTheme = FALSE;
|
||
|
BOOL fRotateTheme = FALSE;
|
||
|
LPTSTR lpszThemeFile;
|
||
|
BOOL fStopOnQuote = FALSE;
|
||
|
WIN32_FIND_DATA wfdFind;
|
||
|
HANDLE hFind;
|
||
|
TCHAR szRotateTheme[MAX_PATH];
|
||
|
// TCHAR szThemesExe[MAX_PATH];
|
||
|
DWORD dwRet;
|
||
|
HKEY hKey;
|
||
|
extern TCHAR szPlus_CurTheme[];
|
||
|
|
||
|
Assert(0, TEXT("Cmd line: '"));
|
||
|
Assert(0, lpCmdLine);
|
||
|
Assert(0, TEXT("'\n"));
|
||
|
|
||
|
// Skip leading whitespace.
|
||
|
while (*lpCmdLine && (*lpCmdLine != TEXT('/')))
|
||
|
lpCmdLine = CharNext(lpCmdLine);
|
||
|
|
||
|
// Check for special switches.
|
||
|
if (*lpCmdLine == TEXT('/')) {
|
||
|
lpCmdLine = CharNext(lpCmdLine);
|
||
|
switch (*lpCmdLine) {
|
||
|
// "Set" theme as active.
|
||
|
case TEXT('s'):
|
||
|
case TEXT('S'):
|
||
|
fSetTheme = TRUE;
|
||
|
lpCmdLine = CharNext(lpCmdLine);
|
||
|
break;
|
||
|
case TEXT('r'):
|
||
|
case TEXT('R'):
|
||
|
fRotateTheme = TRUE;
|
||
|
lpCmdLine = CharNext(lpCmdLine);
|
||
|
break;
|
||
|
default:
|
||
|
return FALSE; // invalid flag so continue execution EXIT
|
||
|
}
|
||
|
while (*lpCmdLine == TEXT(' '))
|
||
|
lpCmdLine = CharNext(lpCmdLine);
|
||
|
}
|
||
|
|
||
|
// Handle quoted long file names. Even if the name isn't quoted, we'll
|
||
|
// still parse to the end of the commandline.
|
||
|
if (*lpCmdLine == TEXT('\"')) {
|
||
|
fStopOnQuote = TRUE;
|
||
|
lpCmdLine = CharNext(lpCmdLine);
|
||
|
}
|
||
|
|
||
|
lpszThemeFile = lpCmdLine;
|
||
|
|
||
|
// Parse until end of line or we find the closing quote.
|
||
|
while (*lpCmdLine && !(fStopOnQuote && *lpCmdLine == TEXT('\"')))
|
||
|
lpCmdLine = CharNext(lpCmdLine);
|
||
|
|
||
|
// Back up to the last non-whitespace character.
|
||
|
while (lpCmdLine > lpszThemeFile && *(lpCmdLine-1) == TEXT(' '))
|
||
|
lpCmdLine = CharPrev(lpszThemeFile, lpCmdLine);
|
||
|
|
||
|
// If there's anything after the closing quote, so what?
|
||
|
*lpCmdLine = TEXT('\0');
|
||
|
|
||
|
// This is our chance to fake a theme rotation "/r" into the
|
||
|
// "/s" paradigm. Let's get a string to the next theme in the
|
||
|
// rotation.
|
||
|
|
||
|
if (fRotateTheme) {
|
||
|
if (GetRotateTheme(szRotateTheme)) {
|
||
|
fSetTheme = TRUE;
|
||
|
lpszThemeFile = szRotateTheme;
|
||
|
}
|
||
|
// GetRotateTheme failed. If we fall through we're likely
|
||
|
// to display the main dialog and we don't want to do that
|
||
|
// in the "/r" case. Just exit the app.
|
||
|
else return TRUE;
|
||
|
}
|
||
|
|
||
|
// After all that work, nothing was specified on the commandline.
|
||
|
if (lpszThemeFile == lpCmdLine)
|
||
|
return FALSE; // no filename so continue execution EXIT
|
||
|
|
||
|
//
|
||
|
// OK: you've got a theme file. if it is for real, save it for use.
|
||
|
// first check existence
|
||
|
hFind = FindFirstFile(lpszThemeFile, (LPWIN32_FIND_DATA)&wfdFind);
|
||
|
if (INVALID_HANDLE_VALUE == hFind)
|
||
|
return (TRUE); // file doesn't exist so continue execution EXIT
|
||
|
// PLUS98 BUG 1293 -- this used to return FALSE
|
||
|
// and open the Theme applet if /s had an invalid
|
||
|
// file. Now we return TRUE which closes Themes
|
||
|
|
||
|
// then check for magic string
|
||
|
GetPrivateProfileString((LPTSTR)szFrostSection,
|
||
|
(LPTSTR)szMagic,
|
||
|
(LPTSTR)szNULL,
|
||
|
(LPTSTR)szMsg, MAX_MSGLEN,
|
||
|
lpszThemeFile);
|
||
|
|
||
|
// magic str check
|
||
|
if (lstrcmp((LPTSTR)szMsg, (LPTSTR)szVerify)) {
|
||
|
// No magic string so this must not be a real theme file.
|
||
|
// If this was from a "/r" rotate we want to return TRUE and
|
||
|
// bail out. Otherwise return FALSE so we open the Theme
|
||
|
// app. (this was the existing Plus 95 behavior):
|
||
|
if (fRotateTheme) return (TRUE);
|
||
|
else return (FALSE);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// get the confirmed theme into the necessary globals
|
||
|
|
||
|
// save theme file using the long filename
|
||
|
lstrcpy(szCurThemeFile, lpszThemeFile); // actual pathname verified
|
||
|
// save cur dir (not theme dir)
|
||
|
lstrcpy(szCurDir, szCurThemeFile);
|
||
|
*(FileFromPath(szCurDir)) = 0;
|
||
|
// save theme name
|
||
|
lstrcpy(szCurThemeName, wfdFind.cFileName); // make sure long filename
|
||
|
TruncateExt(szCurThemeName);
|
||
|
|
||
|
// now maybe we just want to apply the theme and exit
|
||
|
if (fSetTheme) {
|
||
|
// Make sure there is even enough space to do theme
|
||
|
// But don't complain, if there isn't
|
||
|
if (! CheckSpace (NULL, FALSE)) // definition in Regutils.c
|
||
|
return FALSE;
|
||
|
|
||
|
// Make the apply code write out everything.
|
||
|
InitCheckboxes();
|
||
|
|
||
|
// Simulate a left shift keypress to wake up the screensaver.
|
||
|
// Otherwise if the SS is running and we apply a new SS you
|
||
|
// can wind up with dueling savers...
|
||
|
keybd_event(VK_LSHIFT, 0, 0, 0);
|
||
|
keybd_event(VK_LSHIFT, 0, KEYEVENTF_KEYUP, 0);
|
||
|
|
||
|
ApplyThemeFile(lpszThemeFile);
|
||
|
// APPCOMPAT -- Plus95 Themes was not updating the Current Theme
|
||
|
// setting in the registry on this codepath. Need to fix that
|
||
|
// here.
|
||
|
|
||
|
dwRet = RegOpenKeyEx(HKEY_CURRENT_USER, szPlus_CurTheme,
|
||
|
(DWORD)0, KEY_SET_VALUE, (PHKEY)&hKey );
|
||
|
if (dwRet != ERROR_SUCCESS) {
|
||
|
DWORD dwDisposition;
|
||
|
Assert(FALSE, TEXT("couldn't RegOpenKey save theme file\n"));
|
||
|
dwRet = RegCreateKeyEx( HKEY_CURRENT_USER, szPlus_CurTheme,
|
||
|
(DWORD)0, (LPTSTR)szNULL, REG_OPTION_NON_VOLATILE,
|
||
|
KEY_SET_VALUE, (LPSECURITY_ATTRIBUTES)NULL,
|
||
|
(PHKEY)&hKey, (LPDWORD)&dwDisposition );
|
||
|
}
|
||
|
// if open or create worked
|
||
|
if (dwRet == ERROR_SUCCESS) {
|
||
|
dwRet = RegSetValueEx(hKey, (LPTSTR)NULL, // default value
|
||
|
0,
|
||
|
(DWORD)REG_SZ,
|
||
|
(LPBYTE)lpszThemeFile,
|
||
|
(DWORD)( SZSIZEINBYTES((LPTSTR)szCurThemeFile) + 1 ));
|
||
|
RegCloseKey(hKey);
|
||
|
}
|
||
|
|
||
|
Assert(dwRet == ERROR_SUCCESS, TEXT("couldn't open, set or create Registry save theme file\n"));
|
||
|
return TRUE; // set the theme so now just exit app EXIT
|
||
|
} // end if fSetTheme
|
||
|
|
||
|
return FALSE; // continue execution
|
||
|
}
|
||
|
|
||
|
// InitFrost
|
||
|
// Since there are no window classes to register, this routine just loads
|
||
|
// the strings and, since there's only one instance, calls InitInstance().
|
||
|
//
|
||
|
// Returns: success of initialization
|
||
|
|
||
|
BOOL FAR InitFrost(hPrevInstance, hInstance, lpCmdLine, nCmdShow)
|
||
|
HINSTANCE hPrevInstance;
|
||
|
HINSTANCE hInstance; /* Current instance identifier. */
|
||
|
LPTSTR lpCmdLine;
|
||
|
int nCmdShow; /* Param for first ShowWindow() call. */
|
||
|
{
|
||
|
LPTSTR lpScan, lpTemp;
|
||
|
WNDCLASS WndClass;
|
||
|
BOOL bret;
|
||
|
BOOL bGotThemeDir;
|
||
|
HDC hdc;
|
||
|
|
||
|
//
|
||
|
// Get initial strings
|
||
|
// (Gauranteed enough mem at app init for these loads)
|
||
|
InitNoMem(hInstance);
|
||
|
LoadString(hInstance, STR_APPNAME, szAppName, MAX_STRLEN);
|
||
|
LoadString(hInstance, STR_CURSET, szCurSettings, MAX_STRLEN);
|
||
|
LoadString(hInstance, STR_PREVSET, szPrevSettings, MAX_STRLEN);
|
||
|
LoadString(hInstance, STR_PREVSETFILE, szPrevSettingsFilename, MAX_STRLEN);
|
||
|
LoadString(hInstance, STR_OTHERTHM, szOther, MAX_STRLEN);
|
||
|
LoadString(hInstance, STR_THMEXT, szExt, MAX_STRLEN);
|
||
|
LoadString(hInstance, STR_PREVIEWTITLE, szPreviewTitle, MAX_STRLEN);
|
||
|
LoadString(hInstance, STR_HELPFILE, szHelpFile, MAX_STRLEN);
|
||
|
LoadString(hInstance, STR_HELPFILE98, szHelpFile98, MAX_STRLEN);
|
||
|
LoadString(hInstApp, STR_SUGGEST, szNewFile, MAX_STRLEN);
|
||
|
LoadString(hInstApp, STR_SAVETITLE, szSaveTitle, MAX_STRLEN);
|
||
|
LoadString(hInstApp, STR_OPENTITLE, szOpenTitle, MAX_STRLEN);
|
||
|
LoadString(hInstApp, STR_FILETYPE, szFileTypeDesc, MAX_STRLEN);
|
||
|
|
||
|
WndClass.style = CS_DBLCLKS | CS_BYTEALIGNWINDOW | CS_GLOBALCLASS;
|
||
|
WndClass.lpfnWndProc = DefDlgProc;
|
||
|
WndClass.cbClsExtra = 0;
|
||
|
WndClass.cbWndExtra = DLGWINDOWEXTRA;
|
||
|
WndClass.hInstance = hInstApp;
|
||
|
WndClass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(FROST_ICON));
|
||
|
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||
|
WndClass.hbrBackground = (HBRUSH) (COLOR_3DFACE + 1);
|
||
|
WndClass.lpszMenuName = NULL;
|
||
|
WndClass.lpszClassName = szClassName;
|
||
|
|
||
|
if (!RegisterClass(&WndClass))
|
||
|
return FALSE;
|
||
|
|
||
|
// Initialize our g_bGradient flag
|
||
|
hdc = GetDC(NULL);
|
||
|
g_bGradient = (BOOL)(GetDeviceCaps(hdc, BITSPIXEL) > 8);
|
||
|
ReleaseDC(NULL, hdc);
|
||
|
|
||
|
//
|
||
|
// build file search string
|
||
|
lpScan = (LPTSTR)szFileTypeDesc;
|
||
|
while (*lpScan) {
|
||
|
if (2 == CompareString(LOCALE_USER_DEFAULT, NORM_IGNOREWIDTH,
|
||
|
(LPTSTR)TEXT("|"), 1, lpScan, 1)) {
|
||
|
lpTemp = lpScan;
|
||
|
lpScan = CharNext(lpScan);
|
||
|
*lpTemp = 0;
|
||
|
}
|
||
|
else
|
||
|
lpScan = CharNext(lpScan);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// init directory strings
|
||
|
|
||
|
// theme directory - for now it is subdir of EXE dir
|
||
|
GetModuleFileName(hInstApp, (LPTSTR)szThemeDir, MAX_PATHLEN);
|
||
|
*(FileFromPath((LPTSTR)szThemeDir)) = 0; // leaves trailing '\'
|
||
|
|
||
|
// Save this path momentarily -- if we can't find any good Themes
|
||
|
// directory we're going to fall back to this directory.
|
||
|
lstrcpy(szCurDir, szThemeDir);
|
||
|
|
||
|
// Tack a "Themes" onto the path
|
||
|
LoadString(hInstance, STR_THEMESUBDIR, // includes trailing '\'
|
||
|
(LPTSTR)(szThemeDir + lstrlen((LPTSTR)szThemeDir)), MAX_STRLEN);
|
||
|
|
||
|
// Find out if this ThemeDir even exists. If it doesn't we need
|
||
|
// to get creative in finding our ThemeDir by searching the
|
||
|
// following locales:
|
||
|
//
|
||
|
// Plus!98 Install Path\Themes
|
||
|
// Plus!95 Install Path\Themes
|
||
|
// Kids for Plus! Install Path\Themes
|
||
|
// Program Files\Plus!\Themes
|
||
|
|
||
|
bGotThemeDir = FALSE;
|
||
|
|
||
|
Assert(0, TEXT("Themes.exe\\Themes path: "));
|
||
|
Assert(0, szThemeDir);
|
||
|
Assert(0, TEXT("\n"));
|
||
|
if (0xFFFFFFFF != GetFileAttributes(szThemeDir)) bGotThemeDir = TRUE;
|
||
|
|
||
|
if (!bGotThemeDir)
|
||
|
{
|
||
|
// Haven't found ThemeDir yet. Try the Plus!98 location
|
||
|
|
||
|
bret = HandGet(HKEY_LOCAL_MACHINE, PLUS98_KEY,
|
||
|
PLUS98_PATH, (LPTSTR)szThemeDir);
|
||
|
|
||
|
if (bret)
|
||
|
{
|
||
|
// Tack a "Themes" onto the path
|
||
|
lstrcat(szThemeDir, TEXT("\\"));
|
||
|
LoadString(hInstance, STR_THEMESUBDIR,
|
||
|
(szThemeDir + lstrlen((LPTSTR)szThemeDir)), MAX_STRLEN);
|
||
|
|
||
|
Assert(0, TEXT("Plus! 98 path: "));
|
||
|
Assert(0, szThemeDir);
|
||
|
Assert(0, TEXT("\n"));
|
||
|
if (0xFFFFFFFF != GetFileAttributes(szThemeDir)) bGotThemeDir = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!bGotThemeDir)
|
||
|
{
|
||
|
// Still haven't found ThemeDir. Try the Plus! 95 location
|
||
|
|
||
|
bret = HandGet(HKEY_LOCAL_MACHINE, PLUS95_KEY,
|
||
|
PLUS95_PATH, (LPTSTR)szThemeDir);
|
||
|
|
||
|
if (bret)
|
||
|
{
|
||
|
// Tack on a "Themes" onto the path
|
||
|
// Plus!95 DestPath has "Plus!.dll" on the end so get rid
|
||
|
// of that.
|
||
|
*(FileFromPath(szThemeDir)) = 0;
|
||
|
LoadString(hInstance, STR_THEMESUBDIR,
|
||
|
(szThemeDir + lstrlen((LPTSTR)szThemeDir)), MAX_STRLEN);
|
||
|
|
||
|
Assert(0, TEXT("Plus! 95 path: "));
|
||
|
Assert(0, szThemeDir);
|
||
|
Assert(0, TEXT("\n"));
|
||
|
|
||
|
if (0xFFFFFFFF != GetFileAttributes(szThemeDir)) bGotThemeDir = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!bGotThemeDir)
|
||
|
{
|
||
|
// Still haven't found ThemeDir. Try the Kids for Plus! location
|
||
|
|
||
|
bret = HandGet(HKEY_LOCAL_MACHINE, KIDS_KEY,
|
||
|
KIDS_PATH, (LPTSTR)szThemeDir);
|
||
|
|
||
|
if (bret)
|
||
|
{
|
||
|
// Tack a "\Plus! for Kids\Themes" onto the path
|
||
|
lstrcat(szThemeDir, TEXT("\\Plus! for Kids\\"));
|
||
|
LoadString(hInstance, STR_THEMESUBDIR,
|
||
|
(szThemeDir + lstrlen((LPTSTR)szThemeDir)), MAX_STRLEN);
|
||
|
|
||
|
Assert(0, TEXT("Kids Plus! path: "));
|
||
|
Assert(0, szThemeDir);
|
||
|
Assert(0, TEXT("\n"));
|
||
|
|
||
|
if (0xFFFFFFFF != GetFileAttributes(szThemeDir)) bGotThemeDir = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!bGotThemeDir)
|
||
|
{
|
||
|
// Still haven't found ThemeDir. Try the Program Files\Plus! location
|
||
|
|
||
|
bret = HandGet(HKEY_LOCAL_MACHINE, PROGRAMFILES_KEY,
|
||
|
PROGRAMFILES_PATH, (LPTSTR)szThemeDir);
|
||
|
|
||
|
if (bret)
|
||
|
{
|
||
|
// Tack a "Plus!\Themes" onto the path
|
||
|
lstrcat(szThemeDir, TEXT("\\Plus!\\"));
|
||
|
LoadString(hInstance, STR_THEMESUBDIR,
|
||
|
(szThemeDir + lstrlen((LPTSTR)szThemeDir)), MAX_STRLEN);
|
||
|
|
||
|
Assert(0, TEXT("Program Files path: "));
|
||
|
Assert(0, szThemeDir);
|
||
|
Assert(0, TEXT("\n"));
|
||
|
|
||
|
if (0xFFFFFFFF != GetFileAttributes(szThemeDir)) bGotThemeDir = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!bGotThemeDir)
|
||
|
{
|
||
|
// After all that searching we still haven't found a good Theme
|
||
|
// dir. So we'll just use the directory where Themes.exe is
|
||
|
// located -- we saved this in szCurDir before we started this
|
||
|
// search process.
|
||
|
|
||
|
lstrcpy(szThemeDir, szCurDir);
|
||
|
|
||
|
Assert(0, TEXT("Themes.exe path: "));
|
||
|
Assert(0, szThemeDir);
|
||
|
Assert(0, TEXT("\n"));
|
||
|
|
||
|
}
|
||
|
|
||
|
// default current dir
|
||
|
lstrcpy((LPTSTR)szCurDir, (LPTSTR)szThemeDir);
|
||
|
|
||
|
// Windows directory
|
||
|
GetWindowsDirectory((LPTSTR)szWinDir, MAX_PATHLEN);
|
||
|
if (TEXT('\\') != szWinDir[lstrlen((LPTSTR)szWinDir)-1])
|
||
|
lstrcat((LPTSTR)szWinDir, (LPTSTR)TEXT("\\"));
|
||
|
|
||
|
//
|
||
|
// see if there is a previous theme file to return to
|
||
|
bret = HandGet(HKEY_CURRENT_USER, szPlus_CurTheme,
|
||
|
(LPTSTR)NULL, (LPTSTR)szMsg);
|
||
|
Assert(bret, TEXT("no previous theme file in Registry!\n"));
|
||
|
if (bret) {
|
||
|
|
||
|
// get init cur dir from prev theme file
|
||
|
lstrcpy(szCurDir, szMsg);
|
||
|
*(FileFromPath(szCurDir)) = 0;
|
||
|
|
||
|
// Used to actually set the cur theme file/name to prev theme.
|
||
|
// Now we just use the directory if there is a prev theme.
|
||
|
// No longer care if it is a real file or a theme file or not.
|
||
|
#ifdef REVERT
|
||
|
WIN32_FIND_DATA wfdFind;
|
||
|
HANDLE hFind;
|
||
|
extern TCHAR szFrostSection[], szMagic[], szVerify[];
|
||
|
TCHAR szMagicTest[MAX_STRLEN+1];
|
||
|
|
||
|
// first check if it is for real: existence
|
||
|
hFind = FindFirstFile(szMsg, (LPWIN32_FIND_DATA)&wfdFind);
|
||
|
if (INVALID_HANDLE_VALUE != hFind) {
|
||
|
|
||
|
// then check if it is for real: theme file magic string
|
||
|
GetPrivateProfileString((LPTSTR)szFrostSection,
|
||
|
(LPTSTR)szMagic,
|
||
|
(LPTSTR)szNULL,
|
||
|
(LPTSTR)szMagicTest, MAX_STRLEN,
|
||
|
szMsg);
|
||
|
if (!lstrcmp((LPTSTR)szMagicTest, (LPTSTR)szVerify)) {
|
||
|
|
||
|
//
|
||
|
// now you're convinced that the prev theme file is legit
|
||
|
//
|
||
|
|
||
|
// then use it to set some globals
|
||
|
lstrcpy(szCurThemeFile, szMsg);
|
||
|
// save cur dir (not theme dir)
|
||
|
lstrcpy(szCurDir, szCurThemeFile);
|
||
|
*(FileFromPath(szCurDir)) = 0;
|
||
|
// save theme name
|
||
|
lstrcpy(szCurThemeName, FileFromPath(szCurThemeFile));
|
||
|
TruncateExt(szCurThemeName);
|
||
|
}
|
||
|
}
|
||
|
#endif // REVERT
|
||
|
}
|
||
|
|
||
|
// then look if there is a command line that may override things
|
||
|
if (ProcessCmdLine(lpCmdLine))
|
||
|
return TRUE; // don't run app EXIT, hWndApp==NULL as flag
|
||
|
|
||
|
// Single-instance application can call InitInstance() here
|
||
|
// Return success of inst initialization
|
||
|
return(InitInstance(hPrevInstance, hInstance, nCmdShow));
|
||
|
}
|
||
|
|
||
|
|
||
|
// InitInstance
|
||
|
// Create main window; assign globals for instance and window handles.
|
||
|
//
|
||
|
// Returns: success of initialization
|
||
|
|
||
|
BOOL InitInstance(hPrevInstance, hInstance, nCmdShow)
|
||
|
HINSTANCE hPrevInstance;
|
||
|
HINSTANCE hInstance; /* Current instance identifier. */
|
||
|
int nCmdShow; /* Param for first ShowWindow() call. */
|
||
|
|
||
|
{
|
||
|
RECT rWndApp, rWorkArea;
|
||
|
TCHAR szThemesExe[MAX_PATH];
|
||
|
|
||
|
// assign global instance handle
|
||
|
hInstApp = hInstance;
|
||
|
|
||
|
// create main window and assign global window handle
|
||
|
bNoMem = FALSE; // clear out of mem flag
|
||
|
hWndApp = CreateDialog( hInstApp,
|
||
|
MAKEINTRESOURCE(DLG_MAIN),
|
||
|
(HWND)NULL,
|
||
|
PreviewDlgProc
|
||
|
);
|
||
|
if (!hWndApp || bNoMem) // if problems, then bail
|
||
|
return (FALSE);
|
||
|
|
||
|
InitHTMLBM(); // Init the IThumbnail interface for HTML wallpaper support
|
||
|
|
||
|
// have to init preview painting stuff after create dlg
|
||
|
if (!PreviewInit()) {
|
||
|
DestroyWindow(hWndApp);
|
||
|
return (FALSE); // low mem on dc/bmp create EXIT
|
||
|
}
|
||
|
|
||
|
|
||
|
// this doesn't work from WM_INITDIALOG, so added here, too
|
||
|
InitCheckboxes(); // init stored values
|
||
|
RestoreCheckboxes(); // init actual cbs from stored values
|
||
|
if (bThemed) // kinda kludgy to put here but it works
|
||
|
EnableWindow(GetDlgItem(hWndApp, PB_SAVE), FALSE);
|
||
|
|
||
|
// also, can now make init Preview bmp for init paint
|
||
|
BuildPreviewBitmap((LPTSTR)szCurThemeFile);
|
||
|
|
||
|
// center main window on screen
|
||
|
GetWindowRect(hWndApp, (LPRECT)&rWndApp);
|
||
|
SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID)(LPRECT)&rWorkArea, 0);
|
||
|
MoveWindow(hWndApp,
|
||
|
((rWorkArea.right-rWorkArea.left) - (rWndApp.right-rWndApp.left))/2,
|
||
|
((rWorkArea.bottom-rWorkArea.top) - (rWndApp.bottom-rWndApp.top))/2,
|
||
|
// (GetSystemMetrics(SM_CXSCREEN) - (rWndApp.right-rWndApp.left))/2,
|
||
|
// (GetSystemMetrics(SM_CYSCREEN) - (rWndApp.bottom-rWndApp.top))/2,
|
||
|
rWndApp.right-rWndApp.left, rWndApp.bottom-rWndApp.top,
|
||
|
FALSE); // don't repaint
|
||
|
|
||
|
// Make the main window visible; update its client area
|
||
|
ShowWindow(hWndApp, nCmdShow); /* Show the window */
|
||
|
UpdateWindow(hWndApp); /* Sends WM_PAINT message */
|
||
|
|
||
|
// Check to see if CB_SCHEDULE is checked and verify that Task
|
||
|
// Scheduler is running and the Themes task exists as appropriate
|
||
|
|
||
|
if (bCBStates[FC_SCHEDULE]) {
|
||
|
if (IsTaskSchedulerRunning()) {
|
||
|
if (!IsThemesScheduled()) {
|
||
|
GetModuleFileName(hInstApp, (LPTSTR)szThemesExe, MAX_PATH);
|
||
|
if (!AddThemesTask(szThemesExe, TRUE /*Show errors*/)) {
|
||
|
// Couldn't add task -- ATT gave error but need to clear
|
||
|
// SCHEDULE CB
|
||
|
bCBStates[FC_SCHEDULE] = FALSE;
|
||
|
RestoreCheckboxes();
|
||
|
SaveStates(); // Write checkbox states to registry
|
||
|
}
|
||
|
} // Themes.job exists so do nothing
|
||
|
}
|
||
|
else {
|
||
|
// Zonk -- Task Scheduler isn't running. Start it.
|
||
|
if (StartTaskScheduler(TRUE /*prompt user*/)) {
|
||
|
// Task scheduler started -- check if themes task already
|
||
|
// exists
|
||
|
if (!IsThemesScheduled()) {
|
||
|
GetModuleFileName(hInstApp, (LPTSTR)szThemesExe, MAX_PATH);
|
||
|
if (!AddThemesTask(szThemesExe, TRUE /*Show errors*/)) {
|
||
|
// Couldn't add task -- ATT gave error but need to clear
|
||
|
// SCHEDULE CB
|
||
|
bCBStates[FC_SCHEDULE] = FALSE;
|
||
|
RestoreCheckboxes();
|
||
|
SaveStates(); // Write checkbox states to registry
|
||
|
}
|
||
|
} //TS is running now and Themes.job exists
|
||
|
}
|
||
|
else {
|
||
|
// Couldn't start TS -- STS() gave error. Need to clear
|
||
|
// SCHEDULE CB and HandDelete any existing Themes.job.
|
||
|
// CheckDlgButton(hdlg, CB_SCHEDULE, BST_UNCHECKED);
|
||
|
bCBStates[FC_SCHEDULE] = FALSE;
|
||
|
RestoreCheckboxes();
|
||
|
SaveStates(); // Write checkbox states to the registry
|
||
|
HandDeleteThemesTask();
|
||
|
}
|
||
|
} // END ELSE Task Scheduler isn't running
|
||
|
}
|
||
|
else { // bCBStates[FC_CHECKBOX] != TRUE
|
||
|
// SCHEDULE Checkbox is clear -- should delete Themes task.
|
||
|
if (IsTaskSchedulerRunning()) DeleteThemesTask();
|
||
|
else HandDeleteThemesTask();
|
||
|
}
|
||
|
|
||
|
// cleanup
|
||
|
return (TRUE); // success
|
||
|
}
|
||
|
|
||
|
|
||
|
// CloseFrost
|
||
|
//
|
||
|
// Cleanup your objects, thunks, etc.
|
||
|
//
|
||
|
|
||
|
void FAR CloseFrost()
|
||
|
{
|
||
|
// just extra tidy housekeeping
|
||
|
hWndApp = NULL;
|
||
|
hInstApp = NULL;
|
||
|
|
||
|
PreviewDestroy();
|
||
|
}
|
||
|
|
||
|
|
||
|
// SaveStates
|
||
|
//
|
||
|
// Remember persistent states: currently checkboxes.
|
||
|
// Last applied theme is remembered at Apply time.
|
||
|
//
|
||
|
void FAR SaveStates()
|
||
|
{
|
||
|
LONG lret;
|
||
|
HKEY hKey;
|
||
|
int iter;
|
||
|
|
||
|
//
|
||
|
// checkboxes
|
||
|
//
|
||
|
lret = RegOpenKeyEx(HKEY_CURRENT_USER, szPlus_CBs,
|
||
|
(DWORD)0, KEY_SET_VALUE, (PHKEY)&hKey );
|
||
|
if (lret != ERROR_SUCCESS) {
|
||
|
DWORD dwDisposition;
|
||
|
Assert(FALSE, TEXT("couldn't RegOpenKey save checkboxes\n"));
|
||
|
lret = RegCreateKeyEx( HKEY_CURRENT_USER, szPlus_CBs,
|
||
|
(DWORD)0, (LPTSTR)szNULL, REG_OPTION_NON_VOLATILE,
|
||
|
KEY_SET_VALUE, (LPSECURITY_ATTRIBUTES)NULL,
|
||
|
(PHKEY)&hKey, (LPDWORD)&dwDisposition );
|
||
|
}
|
||
|
// if open or create worked
|
||
|
if (lret == ERROR_SUCCESS) {
|
||
|
|
||
|
for (iter = 0; iter < MAX_FCHECKS; iter ++) {
|
||
|
if (bThemed)
|
||
|
RegSetValueEx(hKey, (LPTSTR)szCBNames[iter],
|
||
|
0,
|
||
|
(DWORD)REG_SZ,
|
||
|
(LPBYTE)(IsDlgButtonChecked(hWndApp, iCBIDs[iter]) ?
|
||
|
TEXT("1") : TEXT("0")),
|
||
|
(DWORD)2*sizeof(TCHAR));
|
||
|
else // cur win settings --> real states saved in bCBStates[]
|
||
|
RegSetValueEx(hKey, (LPTSTR)szCBNames[iter],
|
||
|
0,
|
||
|
(DWORD)REG_SZ,
|
||
|
(LPBYTE)(bCBStates[iter] ? TEXT("1") : TEXT("0")),
|
||
|
(DWORD)2*sizeof(TCHAR));
|
||
|
}
|
||
|
|
||
|
// close when finished
|
||
|
RegCloseKey(hKey);
|
||
|
}
|
||
|
else {
|
||
|
Assert(FALSE, TEXT("couldn't open or create Registry save checkboxes\n"));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BOOL GetRotateTheme(LPTSTR lpszRotateTheme)
|
||
|
{
|
||
|
BOOL bRet = FALSE;
|
||
|
TCHAR szThemesdir[MAX_PATH];
|
||
|
HANDLE hFF;
|
||
|
WIN32_FIND_DATA FindData;
|
||
|
|
||
|
// WARNING -- If "next" .Theme file is not valid theme file we'll never rotate!
|
||
|
|
||
|
// See if there is a current theme.
|
||
|
szThemesdir[0] = TEXT('\0');
|
||
|
bRet = HandGet(HKEY_CURRENT_USER, szPlus_CurTheme,
|
||
|
(LPTSTR)NULL, (LPTSTR)szThemesdir);
|
||
|
|
||
|
// Do we have a current Theme?
|
||
|
hFF = INVALID_HANDLE_VALUE;
|
||
|
if (szThemesdir[0]) {
|
||
|
|
||
|
// Yes we do, so do a FindFirst on it and make sure we've
|
||
|
// got the long filename.
|
||
|
ZeroMemory(&FindData, sizeof(WIN32_FIND_DATA));
|
||
|
hFF = FindFirstFile(szThemesdir, &FindData);
|
||
|
}
|
||
|
|
||
|
// Did we find the file on FindFirst? If so, proceed with finding
|
||
|
// the next Theme in that directory else assume that the registry's
|
||
|
// Current Theme setting is bogus and look in the default dir.
|
||
|
|
||
|
if (INVALID_HANDLE_VALUE != hFF) {
|
||
|
// Copy long filename.
|
||
|
lstrcpy(lpszRotateTheme, FindData.cFileName);
|
||
|
FindClose(hFF);
|
||
|
|
||
|
// We've got the longfilename to the current Theme
|
||
|
// Now do a FF/FN on *.Theme in the Theme dir until
|
||
|
// we find the current theme.
|
||
|
|
||
|
// Strip the theme file off the path.
|
||
|
*(FileFromPath(szThemesdir)) = 0;
|
||
|
lstrcat(szThemesdir, TEXT("*\0"));
|
||
|
LoadString(NULL, STR_THMEXT, (szThemesdir + lstrlen(szThemesdir)),
|
||
|
MAX_PATH);
|
||
|
|
||
|
ZeroMemory(&FindData, sizeof(WIN32_FIND_DATA));
|
||
|
hFF = FindFirstFile(szThemesdir, &FindData);
|
||
|
|
||
|
if (INVALID_HANDLE_VALUE == hFF) {
|
||
|
// We shouldn't hit this since we just found our current
|
||
|
// theme in this directory. If we do, just bail out.
|
||
|
lpszRotateTheme[0] = TEXT('\0');
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// Step through the .Theme files in this dir until we find our
|
||
|
// current theme file.
|
||
|
bRet = TRUE;
|
||
|
while (lstrcmp(FindData.cFileName, lpszRotateTheme) && bRet) {
|
||
|
bRet = FindNextFile(hFF, &FindData);
|
||
|
}
|
||
|
|
||
|
if (lstrcmp(FindData.cFileName, lpszRotateTheme)) {
|
||
|
// We ran out of files before finding the current theme!?!?
|
||
|
// Not likely... Bail out.
|
||
|
FindClose(hFF);
|
||
|
lpszRotateTheme[0] = TEXT('\0');
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// Assume the FindNext file is our current theme. Let's
|
||
|
// get the Next .Theme file -- that's what we're rotating to...
|
||
|
|
||
|
if (FindNextFile(hFF, &FindData)) {
|
||
|
*(FileFromPath(szThemesdir)) = 0;
|
||
|
lstrcat(szThemesdir, FindData.cFileName);
|
||
|
lstrcpy(lpszRotateTheme, szThemesdir);
|
||
|
FindClose(hFF);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
// OK, we failed to find another Theme file in the current dir
|
||
|
// so assume our current Theme is the last in the list. Go
|
||
|
// back to the beginning and use the first Theme file we find
|
||
|
// as our "rotate to" theme.
|
||
|
|
||
|
else {
|
||
|
FindClose(hFF);
|
||
|
ZeroMemory(&FindData, sizeof(WIN32_FIND_DATA));
|
||
|
hFF = FindFirstFile(szThemesdir, &FindData);
|
||
|
|
||
|
if (INVALID_HANDLE_VALUE == hFF) {
|
||
|
// This shouldn't fail since we just found our current
|
||
|
// theme in this dir. If it does, bail out.
|
||
|
lpszRotateTheme[0] = TEXT('\0');
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// This is our new/rotate file
|
||
|
*(FileFromPath(szThemesdir)) = 0;
|
||
|
lstrcat(szThemesdir, FindData.cFileName);
|
||
|
lstrcpy (lpszRotateTheme, szThemesdir);
|
||
|
FindClose(hFF);
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// No current theme applied or the Current Theme setting in the
|
||
|
// registry is bogus so use the global szThemeDir setting and
|
||
|
// look for a theme in that directory.
|
||
|
else {
|
||
|
lstrcpy(szThemesdir, szThemeDir);
|
||
|
lstrcat(szThemesdir, TEXT("*\0"));
|
||
|
LoadString(NULL, STR_THMEXT, (szThemesdir + lstrlen(szThemesdir)),
|
||
|
MAX_PATH);
|
||
|
|
||
|
ZeroMemory(&FindData, sizeof(WIN32_FIND_DATA));
|
||
|
hFF = FindFirstFile(szThemesdir, &FindData);
|
||
|
|
||
|
if (INVALID_HANDLE_VALUE == hFF) {
|
||
|
// Apparently there are no themes available in the default
|
||
|
// Themes directory. We're hosed -- no rotation today.
|
||
|
lpszRotateTheme[0] = TEXT('\0');
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// This is our new/rotate file
|
||
|
*(FileFromPath(szThemesdir)) = 0;
|
||
|
lstrcat(szThemesdir, FindData.cFileName);
|
||
|
lstrcpy (lpszRotateTheme, szThemesdir);
|
||
|
FindClose(hFF);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|