1 //
2 // screensave.c
3 //
4 // Entrypoint for a win32 screensaver
5 //
6 // NOTES: Screen savers don't like being UPX'd (compressed). Don't
7 // know why, it just is. C-runtime has been stripped with
8 // "libctiny.lib".
9 //
10 // v1.0 1/12/2003 J Brown
11 //
12 #include <windows.h>
13 #include <windowsx.h>
14 #include <tchar.h>
15 #include "globals.h"
16 #include "message.h"
17 #include "matrix.h"
18 #include "resource.h"
19
20 //#pragma comment(lib, "libctiny.lib")
21 //#pragma comment(linker, "/OPT:NOWIN98")
22
23 //
24 // Added: Multimonitor support!!
25 //
26 HMONITOR (WINAPI * pfnEnumDisplayMonitors)(HDC, LPCRECT, MONITORENUMPROC, LPARAM);
27 BOOL (WINAPI * pfnGetMonitorInfo)(HMONITOR, LPMONITORINFO);
28
29 //
30 // Callback function for EnumDisplayMonitors API. Use this function
31 // to kickstart a screen-saver window for each monitor in the system
32 //
MonitorEnumProc(HMONITOR hMonitor,HDC hdcMonitor,RECT * rcMonitor,LPARAM Param)33 BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, RECT *rcMonitor, LPARAM Param)
34 {
35 HWND hwnd;
36
37 // Create a screensaver on this monitor!
38 hwnd = CreateScreenSaveWnd((HWND)Param, rcMonitor);
39
40 // For some reason windows always places this window at 0,0...
41 // position it ourselves
42 SetWindowPos(hwnd, 0, rcMonitor->left, rcMonitor->top, 0, 0,
43 SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE|SWP_SHOWWINDOW);
44
45 return TRUE;
46 }
47
48 //
49 // Start screen saver!
50 //
ScreenSaver(HWND hwndParent)51 BOOL ScreenSaver(HWND hwndParent)
52 {
53 HMODULE hUser32;
54 UINT nPreviousState;
55 MSG msg;
56
57 InitScreenSaveClass(hwndParent);
58
59 SystemParametersInfo(SPI_SETSCREENSAVERRUNNING, TRUE, &nPreviousState, 0);
60
61 // Dynamically locate API call from USER32 - not present in all versions
62 hUser32 = GetModuleHandle(_T("USER32.DLL"));
63 pfnEnumDisplayMonitors = (PVOID)GetProcAddress(hUser32, "EnumDisplayMonitors");
64
65 // If we're running Win2k+ then the API is available...so call it!
66 if(pfnEnumDisplayMonitors && hwndParent == 0)
67 {
68 pfnEnumDisplayMonitors(NULL, NULL, MonitorEnumProc, 0);
69 }
70 // Otherwise simulate by calling enum-proc manually
71 else
72 {
73 RECT rect;
74
75 rect.left = 0;
76 rect.right = GetSystemMetrics(SM_CXSCREEN);
77 rect.top = 0;
78 rect.bottom = GetSystemMetrics(SM_CYSCREEN);
79
80 MonitorEnumProc(NULL, NULL, &rect, (LPARAM)hwndParent);
81 }
82
83 // run message loop to handle all screen-saver windows
84 while(GetMessage(&msg, NULL,0,0))
85 {
86 TranslateMessage(&msg);
87 DispatchMessage(&msg);
88 }
89
90 SystemParametersInfo(SPI_SETSCREENSAVERRUNNING, FALSE, &nPreviousState, 0);
91
92 return TRUE;
93 }
94
95 //
96 // Look for any options Windows has passed to us:
97 //
98 // -a <hwnd> (set password)
99 // -s (screensave)
100 // -p <hwnd> (preview)
101 // -c <hwnd> (configure)
102 //
ParseCommandLine(LPWSTR szCmdLine,UCHAR * chOption,HWND * hwndParent)103 VOID ParseCommandLine(LPWSTR szCmdLine, UCHAR *chOption, HWND *hwndParent)
104 {
105 UCHAR ch = *szCmdLine++;
106
107 if(ch == '-' || ch == '/')
108 ch = *szCmdLine++;
109
110 if(ch >= 'A' && ch <= 'Z')
111 ch += 'a' - 'A'; //convert to lower case
112
113 *chOption = ch;
114 ch = *szCmdLine++;
115
116 if(ch == ':')
117 ch = *szCmdLine++;
118
119 while(ch == ' ' || ch == '\t')
120 ch = *szCmdLine++;
121
122 if(isdigit(ch))
123 {
124 ULONG_PTR i = _wtoi(szCmdLine - 1);
125 *hwndParent = (HWND)i;
126 }
127 else
128 *hwndParent = NULL;
129 }
130
131 //
132 // Entrypoint for screen-saver: it's just a normal win32 app!
133 //
wWinMain(HINSTANCE hInst,HINSTANCE hPrev,LPWSTR lpCmdLine,int iCmdShow)134 int CALLBACK wWinMain (HINSTANCE hInst, HINSTANCE hPrev, LPWSTR lpCmdLine, int iCmdShow)
135 {
136 HWND hwndParent;
137 UCHAR chOption;
138
139 // Make sure that only 1 instance runs at a time -
140 // Win98 seems to want us to restart every 5 seconds!!
141 if(FindWindowEx(NULL, NULL, APPNAME, APPNAME))
142 {
143 return 0;
144 }
145
146 LoadSettings();
147
148 ParseCommandLine(lpCmdLine, &chOption, &hwndParent);
149
150 switch(chOption)
151 {
152 case 's': return ScreenSaver(NULL); // screen save
153 case 'p': return ScreenSaver(hwndParent); // preview in small window
154 case 'a': return ChangePassword(hwndParent); // ask for password
155 case 'c': return Configure(hwndParent); // configuration dialog
156 default: return Configure(hwndParent); // configuration dialog
157 }
158
159 return 0;
160 }
161