[FORMATTING]
[reactos.git] / reactos / lib / sdk / scrnsave / scrnsave.c
1 /*
2 Screen saver library by Anders Norlander <anorland@hem2.passagen.se>
3
4 This library is (hopefully) compatible with Microsoft's
5 screen saver library.
6
7 This is public domain software.
8
9 */
10
11 #include <windows.h>
12 #include <scrnsave.h>
13 #include <regstr.h>
14
15 /* screen saver window class */
16 #define CLASS_SCRNSAVE TEXT("WindowsScreenSaverClass")
17
18 /* globals */
19 HWND hMainWindow = NULL;
20 BOOL fChildPreview = FALSE;
21 HINSTANCE hMainInstance;
22 TCHAR szName[TITLEBARNAMELEN];
23 TCHAR szAppName[APPNAMEBUFFERLEN];
24 TCHAR szIniFile[MAXFILELEN];
25 TCHAR szScreenSaver[22];
26 TCHAR szHelpFile[MAXFILELEN];
27 TCHAR szNoHelpMemory[BUFFLEN];
28 UINT MyHelpMessage;
29
30 /* local house keeping */
31 static HINSTANCE hPwdLib = NULL;
32 static POINT pt_orig;
33 static BOOL checking_pwd = FALSE;
34 static BOOL closing = FALSE;
35 static BOOL w95 = FALSE;
36
37 typedef BOOL (WINAPI *VERIFYPWDPROC)(HWND);
38 typedef DWORD (WINAPI *CHPWDPROC)(LPCTSTR, HWND, DWORD, PVOID);
39 static VERIFYPWDPROC VerifyScreenSavePwd = NULL;
40
41 /* function names */
42 #define szVerifyPassword "VerifyScreenSavePwd"
43
44 #ifdef UNICODE
45 #define szPwdChangePassword "PwdChangePasswordW"
46 #else
47 #define szPwdChangePassword "PwdChangePasswordA"
48 #endif
49
50 static void TerminateScreenSaver(HWND hWnd);
51 static BOOL RegisterClasses(void);
52 static LRESULT WINAPI SysScreenSaverProc(HWND,UINT,WPARAM,LPARAM);
53 static int LaunchScreenSaver(HWND hParent);
54 static void LaunchConfig(void);
55
56 static int ISSPACE(char c)
57 {
58 return (c == ' ' || c == '\t');
59 }
60
61 #define ISNUM(c) ((c) >= '0' && c <= '9')
62
63 static unsigned long
64 _toul(const char *s)
65 {
66 unsigned long res;
67 unsigned long n;
68 const char *p;
69
70 for (p = s; *p; p++)
71 if (!ISNUM(*p))
72 break;
73
74 p--;
75 res = 0;
76
77 for (n = 1; p >= s; p--, n *= 10)
78 res += (*p - '0') * n;
79
80 return res;
81 }
82
83 /* screen saver entry point */
84 int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInst,
85 LPSTR CmdLine, int nCmdShow)
86 {
87 LPSTR p;
88 OSVERSIONINFO vi;
89
90 /* initialize */
91 hMainInstance = hInst;
92
93 vi.dwOSVersionInfoSize = sizeof(vi);
94 GetVersionEx(&vi);
95 /* check if we are going to check for passwords */
96 if (vi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
97 {
98 HKEY hKey;
99 /* we are using windows 95 */
100 w95 = TRUE;
101 if (RegOpenKey(HKEY_CURRENT_USER, REGSTR_PATH_SCREENSAVE ,&hKey) ==
102 ERROR_SUCCESS)
103 {
104 DWORD check_pwd;
105 DWORD size = sizeof(DWORD);
106 DWORD type;
107 LONG res;
108
109 res = RegQueryValueEx(hKey, REGSTR_VALUE_USESCRPASSWORD,
110 NULL, &type, (PBYTE) &check_pwd, &size);
111
112 if (check_pwd && res == ERROR_SUCCESS)
113 {
114 hPwdLib = LoadLibrary(TEXT("PASSWORD.CPL"));
115 if (hPwdLib)
116 VerifyScreenSavePwd = GetProcAddress(hPwdLib, szVerifyPassword);
117 }
118
119 RegCloseKey(hKey);
120 }
121 }
122
123 /* parse arguments */
124 for (p = CmdLine; *p; p++)
125 {
126 switch (*p)
127 {
128 case 'S':
129 case 's':
130 /* start screen saver */
131 return LaunchScreenSaver(NULL);
132
133 case 'P':
134 case 'p':
135 {
136 /* start screen saver in preview window */
137 HWND hParent;
138 fChildPreview = TRUE;
139
140 while (ISSPACE(*++p));
141 hParent = (HWND) _toul(p);
142
143 if (hParent && IsWindow(hParent))
144 return LaunchScreenSaver(hParent);
145 }
146 return 0;
147
148 case 'C':
149 case 'c':
150 /* display configure dialog */
151 LaunchConfig();
152 return 0;
153
154 case 'A':
155 case 'a':
156 {
157 /* change screen saver password */
158 HWND hParent;
159 while (ISSPACE(*++p));
160 hParent = (HWND) _toul(p);
161
162 if (!hParent || !IsWindow(hParent))
163 hParent = GetForegroundWindow();
164
165 ScreenSaverChangePassword(hParent);
166 }
167 return 0;
168
169 case '-':
170 case '/':
171 case ' ':
172 default:
173 break;
174 }
175 }
176
177 LaunchConfig();
178
179 return 0;
180 }
181
182 static void LaunchConfig(void)
183 {
184 /* FIXME: should this be called */
185 RegisterDialogClasses(hMainInstance);
186
187 /* display configure dialog */
188 DialogBox(hMainInstance, MAKEINTRESOURCE(DLG_SCRNSAVECONFIGURE),
189 GetForegroundWindow(), (DLGPROC) ScreenSaverConfigureDialog);
190 }
191
192 static int LaunchScreenSaver(HWND hParent)
193 {
194 BOOL foo;
195 UINT style;
196 RECT rc;
197 MSG msg;
198
199 /* don't allow other tasks to get into the foreground */
200 if (w95 && !fChildPreview)
201 SystemParametersInfo(SPI_SCREENSAVERRUNNING, TRUE, &foo, 0);
202
203 msg.wParam = 0;
204
205 /* register classes, both user defined and classes used by screen saver
206 library */
207 if (!RegisterClasses())
208 {
209 MessageBox(NULL, TEXT("RegisterClasses() failed"), NULL, MB_ICONHAND);
210 goto restore;
211 }
212
213 /* a slightly different approach needs to be used when displaying
214 in a preview window */
215 if (hParent)
216 {
217 style = WS_CHILD;
218 GetClientRect(hParent, &rc);
219 }
220 else
221 {
222 style = WS_POPUP;
223 rc.right = GetSystemMetrics(SM_CXSCREEN);
224 rc.bottom = GetSystemMetrics(SM_CYSCREEN);
225 style |= WS_VISIBLE;
226 }
227
228 /* create main screen saver window */
229 hMainWindow = CreateWindowEx(hParent ? 0 : WS_EX_TOPMOST, CLASS_SCRNSAVE,
230 TEXT("SCREENSAVER"), style,
231 0, 0, rc.right, rc.bottom, hParent, NULL,
232 hMainInstance, NULL);
233
234 /* display window and start pumping messages */
235 if (hMainWindow)
236 {
237 UpdateWindow(hMainWindow);
238 ShowWindow(hMainWindow, SW_SHOW);
239
240 while (GetMessage(&msg, NULL, 0, 0) == TRUE)
241 {
242 TranslateMessage(&msg);
243 DispatchMessage(&msg);
244 }
245 }
246
247 restore:
248 /* restore system */
249 if (w95 && !fChildPreview)
250 SystemParametersInfo(SPI_SCREENSAVERRUNNING, FALSE, &foo, 0);
251
252 FreeLibrary(hPwdLib);
253 return msg.wParam;
254 }
255
256 /* this function takes care of *must* do tasks, like terminating
257 screen saver */
258 static LRESULT WINAPI SysScreenSaverProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
259 {
260 switch (msg)
261 {
262 case WM_CREATE:
263 if (!fChildPreview)
264 SetCursor(NULL);
265 /* mouse is not supposed to move from this position */
266 GetCursorPos(&pt_orig);
267 break;
268
269 case WM_DESTROY:
270 PostQuitMessage(0);
271 break;
272
273 case WM_TIMER:
274 if (closing)
275 return 0;
276 break;
277
278 case WM_PAINT:
279 if (closing)
280 return DefWindowProc(hWnd, msg, wParam, lParam);
281 break;
282
283 case WM_SYSCOMMAND:
284 if (!fChildPreview)
285 {
286 switch (wParam)
287 {
288 case SC_CLOSE:
289 case SC_SCREENSAVE:
290 case SC_NEXTWINDOW:
291 case SC_PREVWINDOW:
292 return FALSE;
293 }
294 }
295 break;
296
297 case WM_MOUSEMOVE:
298 case WM_LBUTTONDOWN:
299 case WM_RBUTTONDOWN:
300 case WM_MBUTTONDOWN:
301 case WM_KEYDOWN:
302 case WM_SYSKEYDOWN:
303 case WM_NCACTIVATE:
304 case WM_ACTIVATE:
305 case WM_ACTIVATEAPP:
306 if (closing)
307 return DefWindowProc(hWnd, msg, wParam, lParam);
308
309 break;
310 }
311
312 return ScreenSaverProc(hWnd, msg, wParam, lParam);
313 }
314
315 LONG WINAPI DefScreenSaverProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
316 {
317 /* don't do any special processing when in preview mode */
318 if (fChildPreview || closing)
319 return DefWindowProc(hWnd, msg, wParam, lParam);
320
321 switch (msg)
322 {
323 case WM_CLOSE:
324 TerminateScreenSaver(hWnd);
325 /* do NOT pass this to DefWindowProc; it will terminate even if
326 an invalid password was given.
327 */
328 return 0;
329
330 case SCRM_VERIFYPW:
331 /* verify password or return TRUE if password checking is turned off */
332 if (VerifyScreenSavePwd)
333 return VerifyScreenSavePwd(hWnd);
334 else
335 return TRUE;
336
337 case WM_SETCURSOR:
338 if (checking_pwd)
339 break;
340 SetCursor(NULL);
341 return TRUE;
342
343 case WM_NCACTIVATE:
344 case WM_ACTIVATE:
345 case WM_ACTIVATEAPP:
346 if (wParam != FALSE)
347 break;
348
349 case WM_MOUSEMOVE:
350 {
351 POINT pt;
352 GetCursorPos(&pt);
353 if (pt.x == pt_orig.x && pt.y == pt_orig.y)
354 break;
355 }
356
357 case WM_LBUTTONDOWN:
358 case WM_RBUTTONDOWN:
359 case WM_MBUTTONDOWN:
360 case WM_KEYDOWN:
361 case WM_SYSKEYDOWN:
362 /* try to terminate screen saver */
363 if (!checking_pwd)
364 PostMessage(hWnd, WM_CLOSE, 0, 0);
365 break;
366 }
367
368 return DefWindowProc(hWnd, msg, wParam, lParam);
369 }
370
371 static void TerminateScreenSaver(HWND hWnd)
372 {
373 /* don't allow recursion */
374 if (checking_pwd || closing)
375 return;
376
377 /* verify password */
378 if (VerifyScreenSavePwd)
379 {
380 checking_pwd = TRUE;
381 closing = SendMessage(hWnd, SCRM_VERIFYPW, 0, 0);
382 checking_pwd = FALSE;
383 }
384 else
385 closing = TRUE;
386
387 /* are we closing? */
388 if (closing)
389 {
390 DestroyWindow(hWnd);
391 }
392 else
393 GetCursorPos(&pt_orig); /* if not: get new mouse position */
394 }
395
396 /*
397 Register screen saver window class and call user
398 supplied hook.
399 */
400 static BOOL RegisterClasses(void)
401 {
402 WNDCLASS cls;
403 ZeroMemory(&cls, sizeof(cls));
404 cls.hCursor = NULL;
405 cls.hIcon = LoadIcon(hMainInstance, MAKEINTATOM(ID_APP));
406 cls.lpszMenuName = NULL;
407 cls.lpszClassName = CLASS_SCRNSAVE;
408 cls.hbrBackground = NULL; //(HBRUSH)GetStockObject(BLACK_BRUSH);
409 cls.hInstance = hMainInstance;
410 cls.style = CS_VREDRAW | CS_HREDRAW | CS_SAVEBITS | CS_PARENTDC;
411 cls.lpfnWndProc = (WNDPROC) SysScreenSaverProc;
412 cls.cbWndExtra = 0;
413 cls.cbClsExtra = 0;
414
415 if (!RegisterClass(&cls))
416 return FALSE;
417
418 return RegisterDialogClasses(hMainInstance);
419 }
420
421 void WINAPI ScreenSaverChangePassword(HWND hParent)
422 {
423 /* load Master Password Router (MPR) */
424 HINSTANCE hMpr = LoadLibrary(TEXT("MPR.DLL"));
425
426 if (hMpr)
427 {
428 CHPWDPROC ChangePassword;
429 ChangePassword = (CHPWDPROC) GetProcAddress(hMpr, szPwdChangePassword);
430
431 /* change password for screen saver provider */
432 if (ChangePassword)
433 ChangePassword(TEXT("SCRSAVE"), hParent, 0, NULL);
434
435 FreeLibrary(hMpr);
436 }
437 }