/* Screen saver library by Anders Norlander This library is (hopefully) compatible with Microsoft's screen saver library. This is public domain software. */ #include #include #include /* screen saver window class */ #define CLASS_SCRNSAVE TEXT("WindowsScreenSaverClass") /* globals */ HWND hMainWindow = NULL; BOOL fChildPreview = FALSE; HINSTANCE hMainInstance; TCHAR szName[TITLEBARNAMELEN]; TCHAR szAppName[APPNAMEBUFFERLEN]; TCHAR szIniFile[MAXFILELEN]; TCHAR szScreenSaver[22]; TCHAR szHelpFile[MAXFILELEN]; TCHAR szNoHelpMemory[BUFFLEN]; UINT MyHelpMessage; /* local house keeping */ static HINSTANCE hPwdLib = NULL; static POINT pt_orig; static BOOL checking_pwd = FALSE; static BOOL closing = FALSE; static BOOL w95 = FALSE; typedef BOOL (WINAPI *VERIFYPWDPROC)(HWND); typedef DWORD (WINAPI *CHPWDPROC)(LPCTSTR, HWND, DWORD, PVOID); static VERIFYPWDPROC VerifyScreenSavePwd = NULL; /* function names */ #define szVerifyPassword "VerifyScreenSavePwd" #ifdef UNICODE #define szPwdChangePassword "PwdChangePasswordW" #else #define szPwdChangePassword "PwdChangePasswordA" #endif static void TerminateScreenSaver(HWND hWnd); static BOOL RegisterClasses(void); static LRESULT WINAPI SysScreenSaverProc(HWND,UINT,WPARAM,LPARAM); static int LaunchScreenSaver(HWND hParent); static void LaunchConfig(void); static int ISSPACE(char c) { return (c == ' ' || c == '\t'); } #define ISNUM(c) ((c) >= '0' && c <= '9') static unsigned long _toul(const char *s) { unsigned long res; unsigned long n; const char *p; for (p = s; *p; p++) if (!ISNUM(*p)) break; p--; res = 0; for (n = 1; p >= s; p--, n *= 10) res += (*p - '0') * n; return res; } /* screen saver entry point */ int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR CmdLine, int nCmdShow) { LPSTR p; OSVERSIONINFO vi; /* initialize */ hMainInstance = hInst; vi.dwOSVersionInfoSize = sizeof(vi); GetVersionEx(&vi); /* check if we are going to check for passwords */ if (vi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) { HKEY hKey; /* we are using windows 95 */ w95 = TRUE; if (RegOpenKey(HKEY_CURRENT_USER, REGSTR_PATH_SCREENSAVE ,&hKey) == ERROR_SUCCESS) { DWORD check_pwd; DWORD size = sizeof(DWORD); DWORD type; LONG res; res = RegQueryValueEx(hKey, REGSTR_VALUE_USESCRPASSWORD, NULL, &type, (PBYTE) &check_pwd, &size); if (check_pwd && res == ERROR_SUCCESS) { hPwdLib = LoadLibrary(TEXT("PASSWORD.CPL")); if (hPwdLib) VerifyScreenSavePwd = GetProcAddress(hPwdLib, szVerifyPassword); } RegCloseKey(hKey); } } /* parse arguments */ for (p = CmdLine; *p; p++) { switch (*p) { case 'S': case 's': /* start screen saver */ return LaunchScreenSaver(NULL); case 'P': case 'p': { /* start screen saver in preview window */ HWND hParent; fChildPreview = TRUE; while (ISSPACE(*++p)); hParent = (HWND) _toul(p); if (hParent && IsWindow(hParent)) return LaunchScreenSaver(hParent); } return 0; case 'C': case 'c': /* display configure dialog */ LaunchConfig(); return 0; case 'A': case 'a': { /* change screen saver password */ HWND hParent; while (ISSPACE(*++p)); hParent = (HWND) _toul(p); if (!hParent || !IsWindow(hParent)) hParent = GetForegroundWindow(); ScreenSaverChangePassword(hParent); } return 0; case '-': case '/': case ' ': default: break; } } LaunchConfig(); return 0; } static void LaunchConfig(void) { /* FIXME: should this be called */ RegisterDialogClasses(hMainInstance); /* display configure dialog */ DialogBox(hMainInstance, MAKEINTRESOURCE(DLG_SCRNSAVECONFIGURE), GetForegroundWindow(), (DLGPROC) ScreenSaverConfigureDialog); } static int LaunchScreenSaver(HWND hParent) { BOOL foo; UINT style; RECT rc; MSG msg; /* don't allow other tasks to get into the foreground */ if (w95 && !fChildPreview) SystemParametersInfo(SPI_SCREENSAVERRUNNING, TRUE, &foo, 0); msg.wParam = 0; /* register classes, both user defined and classes used by screen saver library */ if (!RegisterClasses()) { MessageBox(NULL, TEXT("RegisterClasses() failed"), NULL, MB_ICONHAND); goto restore; } /* a slightly different approach needs to be used when displaying in a preview window */ if (hParent) { style = WS_CHILD; GetClientRect(hParent, &rc); } else { style = WS_POPUP; rc.right = GetSystemMetrics(SM_CXSCREEN); rc.bottom = GetSystemMetrics(SM_CYSCREEN); style |= WS_VISIBLE; } /* create main screen saver window */ hMainWindow = CreateWindowEx(hParent ? 0 : WS_EX_TOPMOST, CLASS_SCRNSAVE, TEXT("SCREENSAVER"), style, 0, 0, rc.right, rc.bottom, hParent, NULL, hMainInstance, NULL); /* display window and start pumping messages */ if (hMainWindow) { UpdateWindow(hMainWindow); ShowWindow(hMainWindow, SW_SHOW); while (GetMessage(&msg, NULL, 0, 0) == TRUE) { TranslateMessage(&msg); DispatchMessage(&msg); } } restore: /* restore system */ if (w95 && !fChildPreview) SystemParametersInfo(SPI_SCREENSAVERRUNNING, FALSE, &foo, 0); FreeLibrary(hPwdLib); return msg.wParam; } /* this function takes care of *must* do tasks, like terminating screen saver */ static LRESULT WINAPI SysScreenSaverProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_CREATE: if (!fChildPreview) SetCursor(NULL); /* mouse is not supposed to move from this position */ GetCursorPos(&pt_orig); break; case WM_DESTROY: PostQuitMessage(0); break; case WM_TIMER: if (closing) return 0; break; case WM_PAINT: if (closing) return DefWindowProc(hWnd, msg, wParam, lParam); break; case WM_SYSCOMMAND: if (!fChildPreview) switch (wParam) { case SC_CLOSE: case SC_SCREENSAVE: case SC_NEXTWINDOW: case SC_PREVWINDOW: return FALSE; } break; case WM_MOUSEMOVE: case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: case WM_MBUTTONDOWN: case WM_KEYDOWN: case WM_SYSKEYDOWN: case WM_NCACTIVATE: case WM_ACTIVATE: case WM_ACTIVATEAPP: if (closing) return DefWindowProc(hWnd, msg, wParam, lParam); break; } return ScreenSaverProc(hWnd, msg, wParam, lParam); } LONG WINAPI DefScreenSaverProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { /* don't do any special processing when in preview mode */ if (fChildPreview || closing) return DefWindowProc(hWnd, msg, wParam, lParam); switch (msg) { case WM_CLOSE: TerminateScreenSaver(hWnd); /* do NOT pass this to DefWindowProc; it will terminate even if an invalid password was given. */ return 0; case SCRM_VERIFYPW: /* verify password or return TRUE if password checking is turned off */ if (VerifyScreenSavePwd) return VerifyScreenSavePwd(hWnd); else return TRUE; case WM_SETCURSOR: if (checking_pwd) break; SetCursor(NULL); return TRUE; case WM_NCACTIVATE: case WM_ACTIVATE: case WM_ACTIVATEAPP: if (wParam != FALSE) break; case WM_MOUSEMOVE: { POINT pt; GetCursorPos(&pt); if (pt.x == pt_orig.x && pt.y == pt_orig.y) break; } case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: case WM_MBUTTONDOWN: case WM_KEYDOWN: case WM_SYSKEYDOWN: /* try to terminate screen saver */ if (!checking_pwd) PostMessage(hWnd, WM_CLOSE, 0, 0); break; } return DefWindowProc(hWnd, msg, wParam, lParam); } static void TerminateScreenSaver(HWND hWnd) { /* don't allow recursion */ if (checking_pwd || closing) return; /* verify password */ if (VerifyScreenSavePwd) { checking_pwd = TRUE; closing = SendMessage(hWnd, SCRM_VERIFYPW, 0, 0); checking_pwd = FALSE; } else closing = TRUE; /* are we closing? */ if (closing) { DestroyWindow(hWnd); } else GetCursorPos(&pt_orig); /* if not: get new mouse position */ } /* Register screen saver window class and call user supplied hook. */ static BOOL RegisterClasses(void) { WNDCLASS cls; cls.hCursor = NULL; cls.hIcon = LoadIcon(hMainInstance, MAKEINTATOM(ID_APP)); cls.lpszMenuName = NULL; cls.lpszClassName = CLASS_SCRNSAVE; cls.hbrBackground = GetStockObject(BLACK_BRUSH); cls.hInstance = hMainInstance; cls.style = CS_VREDRAW | CS_HREDRAW | CS_SAVEBITS | CS_PARENTDC; cls.lpfnWndProc = (WNDPROC) SysScreenSaverProc; cls.cbWndExtra = 0; cls.cbClsExtra = 0; if (!RegisterClass(&cls)) return FALSE; return RegisterDialogClasses(hMainInstance); } void WINAPI ScreenSaverChangePassword(HWND hParent) { /* load Master Password Router (MPR) */ HINSTANCE hMpr = LoadLibrary(TEXT("MPR.DLL")); if (hMpr) { CHPWDPROC ChangePassword; ChangePassword = (CHPWDPROC) GetProcAddress(hMpr, szPwdChangePassword); /* change password for screen saver provider */ if (ChangePassword) ChangePassword(TEXT("SCRSAVE"), hParent, 0, NULL); FreeLibrary(hMpr); } }