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