909 lines
27 KiB
C
909 lines
27 KiB
C
//----------------------------------------------------------------------------
|
|
//
|
|
// SCRNSAVE.C -- skeleton for screen saver application
|
|
//
|
|
// 4/5/94 francish merged NT and Win4 saver code, folded in SCRNSAVE.SCR
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#define WIN31
|
|
#include <windows.h>
|
|
#include <windowsx.h>
|
|
#include "scrnsave.h"
|
|
#include <regstr.h>
|
|
#include <commctrl.h>
|
|
#include <imm.h>
|
|
|
|
#define DBG_MSGS 0
|
|
|
|
const TCHAR szScreenSaverKey[] = REGSTR_PATH_SCREENSAVE;
|
|
TCHAR szPasswordActiveValue[] = REGSTR_VALUE_USESCRPASSWORD;
|
|
const TCHAR szPasswordValue[] = REGSTR_VALUE_SCRPASSWORD;
|
|
TCHAR szPwdDLL[] = TEXT("PASSWORD.CPL");
|
|
CHAR szFnName[] = "VerifyScreenSavePwd"; // Proc name, must be ANSI
|
|
TCHAR szImmDLL[] = TEXT("IMM32.DLL");
|
|
CHAR szImmFnc[] = "ImmAssociateContext"; // Proc name, must be ANSI
|
|
#if 0
|
|
TCHAR szCoolSaverHacks[] = REGSTR_PATH_SETUP TEXT("\\Screen Savers");
|
|
TCHAR szMouseThreshold[] = TEXT("Mouse Threshold");
|
|
TCHAR szPasswordDelay[] = TEXT("Password Delay");
|
|
#endif
|
|
|
|
typedef BOOL (FAR PASCAL * VERIFYPWDPROC) (HWND);
|
|
typedef HIMC (FAR PASCAL * IMMASSOCPROC) (HWND,HIMC);
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// variables declared in SCRNSAVE.H
|
|
HINSTANCE hMainInstance = 0;
|
|
HWND hMainWindow = 0;
|
|
BOOL fChildPreview = FALSE;
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// other globals
|
|
POINT ptMouse;
|
|
BOOL fClosing = FALSE;
|
|
BOOL fCheckingPassword = FALSE;
|
|
HINSTANCE hInstPwdDLL = NULL;
|
|
VERIFYPWDPROC VerifyPassword = NULL;
|
|
static BOOL preview_like_fullscreen = FALSE;
|
|
static UINT uShellAutoPlayQueryMessage = 0;
|
|
HINSTANCE hInstImm = NULL;
|
|
IMMASSOCPROC ImmFnc = NULL;
|
|
HIMC hPrevImc = (HIMC)0L;
|
|
|
|
|
|
static BOOL fOnWin95 = FALSE; //TRUE if on Chicago, FALSE if on Cairo
|
|
|
|
//----------------------------------------------------------------------------
|
|
// random junk
|
|
DWORD dwWakeThreshold = 4; //default to slight movement
|
|
DWORD dwPasswordDelay = 0;
|
|
DWORD dwBlankTime = 0;
|
|
#define MAX_PASSWORD_DELAY_IN_SECONDS (60)
|
|
|
|
BYTE bACLineStatus = AC_LINE_UNKNOWN; // Last state of AC line
|
|
|
|
//----------------------------------------------------------------------------
|
|
// forward declarations of internal fns
|
|
static INT_PTR DoScreenSave( HWND hParent );
|
|
static INT_PTR DoSaverPreview( LPCTSTR szUINTHandle );
|
|
static INT_PTR DoConfigBox( HWND hParent );
|
|
static INT_PTR DoChangePw( LPCTSTR szUINTHandle );
|
|
static BOOL DoPasswordCheck( HWND hParent );
|
|
VOID LoadPwdDLL(VOID);
|
|
VOID UnloadPwdDLL(VOID);
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// helper for time
|
|
static DWORD
|
|
GetElapsedTime(DWORD from, DWORD to)
|
|
{
|
|
return (to >= from)? (to - from) : (1 + to + (((DWORD)-1) - from));
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// helper to convert text to unsigned int
|
|
static UINT_PTR
|
|
atoui( LPCTSTR szUINT )
|
|
{
|
|
UINT_PTR uValue = 0;
|
|
|
|
while( ( *szUINT >= TEXT('0') ) && ( *szUINT <= TEXT('9') ) )
|
|
uValue = ( ( uValue * 10 ) + ( *szUINT++ - TEXT('0') ) );
|
|
|
|
return uValue;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Local reboot and hotkey control (on Win95)
|
|
static void
|
|
HogMachine( BOOL value )
|
|
{
|
|
BOOL dummy;
|
|
|
|
//
|
|
// NT is always secure, therefore we don't need to call this on Cairo/NT
|
|
//
|
|
if (fOnWin95) {
|
|
SystemParametersInfo( SPI_SCREENSAVERRUNNING, value, &dummy, 0 );
|
|
}
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// entry point (duh)
|
|
INT_PTR PASCAL
|
|
WinMainN( HINSTANCE hInst, HINSTANCE hPrev, LPTSTR szCmdLine, int nCmdShow )
|
|
{
|
|
LPCTSTR pch = szCmdLine;
|
|
HWND hParent = 0;
|
|
OSVERSIONINFO osvi;
|
|
INITCOMMONCONTROLSEX icce = {0};
|
|
|
|
ZeroMemory(&icce, sizeof(icce));
|
|
icce.dwSize = sizeof(icce);
|
|
icce.dwICC = ICC_TAB_CLASSES;
|
|
InitCommonControlsEx(&icce);
|
|
|
|
hMainInstance = hInst;
|
|
|
|
osvi.dwOSVersionInfoSize = sizeof(osvi);
|
|
fOnWin95 = (GetVersionEx(&osvi) &&
|
|
osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
|
|
|
|
_try
|
|
{
|
|
for(;;) switch( *pch )
|
|
{
|
|
case TEXT('S'):
|
|
case TEXT('s'):
|
|
return DoScreenSave( NULL );
|
|
|
|
case TEXT('L'):
|
|
case TEXT('l'):
|
|
// special switch for tests such as WinBench
|
|
// this is NOT a hack to make bechmarks look good
|
|
// it's a hack to allow you to benchmark a screen saver
|
|
// many bechmarking apps require the whole screen in foreground
|
|
// which makes it hard to measure how a screensaver adds CPU load
|
|
// you must provide a parent window (just like preview mode)
|
|
preview_like_fullscreen = TRUE;
|
|
case TEXT('P'):
|
|
case TEXT('p'):
|
|
do pch++; while( *pch == TEXT(' ') ); // skip to the good stuff
|
|
return DoSaverPreview( pch );
|
|
|
|
case TEXT('A'):
|
|
case TEXT('a'):
|
|
if (!fOnWin95)
|
|
return -1;
|
|
do pch++; while( *pch == TEXT(' ') ); // skip to the good stuff
|
|
return DoChangePw( pch );
|
|
|
|
case TEXT('C'):
|
|
case TEXT('c'): {
|
|
HWND hwndParent = NULL
|
|
;
|
|
// Look for optional parent window after the "C",
|
|
// syntax is "C:hwnd_value"
|
|
if (*(++pch) == TEXT(':')) {
|
|
hwndParent = (HWND)atoui( ++pch );
|
|
}
|
|
|
|
if (hwndParent == NULL || !IsWindow(hwndParent))
|
|
hwndParent = GetForegroundWindow();
|
|
|
|
return DoConfigBox( hwndParent );
|
|
}
|
|
|
|
case TEXT('\0'):
|
|
return DoConfigBox( NULL );
|
|
|
|
case TEXT(' '):
|
|
case TEXT('-'):
|
|
case TEXT('/'):
|
|
pch++; // skip spaces and common switch prefixes
|
|
break;
|
|
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
_except(UnhandledExceptionFilter(GetExceptionInformation()))
|
|
{
|
|
// don't leave local reboot and hotkeys disabled on Win95
|
|
HogMachine( FALSE );
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// default screen-saver proc, declared in SCRNSAVE.H
|
|
// intended to be called by the consumer's ScreenSaverProc where
|
|
// DefWindowProc would normally be called
|
|
LRESULT WINAPI
|
|
DefScreenSaverProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
#if DBG_MSGS
|
|
TCHAR szBuff[80];
|
|
|
|
wsprintf( szBuff, TEXT("*** DefSSP received:\t0x%04lx 0x%08lx 0x%08lx\n"), uMsg, wParam, lParam );
|
|
OutputDebugString(szBuff);
|
|
#endif
|
|
SYSTEM_POWER_STATUS sps;
|
|
BYTE bCurrentLineStatus;
|
|
|
|
if( !fChildPreview && !fClosing )
|
|
{
|
|
switch( uMsg )
|
|
{
|
|
case WM_CLOSE:
|
|
//
|
|
// Only do password check if on Windows 95. WinNT (Cairo) has
|
|
// the password check built into the security desktop for
|
|
// C2 compliance.
|
|
//
|
|
if (fOnWin95) {
|
|
if( !DoPasswordCheck( hWnd ) )
|
|
{
|
|
GetCursorPos( &ptMouse ); // re-establish
|
|
return FALSE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SCRM_VERIFYPW:
|
|
if (fOnWin95)
|
|
return ( VerifyPassword? (LRESULT)VerifyPassword( hWnd ) : 1L );
|
|
break;
|
|
|
|
default:
|
|
{
|
|
POINT ptMove, ptCheck;
|
|
|
|
if( fCheckingPassword )
|
|
break;
|
|
|
|
switch( uMsg )
|
|
{
|
|
case WM_SHOWWINDOW:
|
|
if( (BOOL)wParam )
|
|
SetCursor( NULL );
|
|
break;
|
|
|
|
case WM_SETCURSOR:
|
|
SetCursor( NULL );
|
|
return TRUE;
|
|
|
|
case WM_MOUSEMOVE:
|
|
GetCursorPos( &ptCheck );
|
|
if( ( ptMove.x = ptCheck.x - ptMouse.x ) && ( ptMove.x < 0 ) )
|
|
ptMove.x *= -1;
|
|
if( ( ptMove.y = ptCheck.y - ptMouse.y ) && ( ptMove.y < 0 ) )
|
|
ptMove.y *= -1;
|
|
if( ((DWORD)ptMove.x + (DWORD)ptMove.y) > dwWakeThreshold )
|
|
{
|
|
PostMessage( hWnd, WM_CLOSE, 0, 0l );
|
|
ptMouse = ptCheck;
|
|
}
|
|
break;
|
|
|
|
|
|
//
|
|
// Handle Power Management event
|
|
//
|
|
case WM_POWERBROADCAST:
|
|
switch (wParam)
|
|
{
|
|
case PBT_APMPOWERSTATUSCHANGE:
|
|
if (GetSystemPowerStatus(&sps)) {
|
|
bCurrentLineStatus = sps.ACLineStatus;
|
|
}
|
|
else {
|
|
// we can't determine the power status, use default
|
|
bCurrentLineStatus = AC_LINE_UNKNOWN;
|
|
}
|
|
|
|
// If the current line status differs from the previous
|
|
// exit the screen saver, otherwise just keep running
|
|
if (bCurrentLineStatus != bACLineStatus) {
|
|
bACLineStatus = bCurrentLineStatus;
|
|
goto PostClose;
|
|
}
|
|
else {
|
|
bACLineStatus = bCurrentLineStatus;
|
|
}
|
|
|
|
break;
|
|
|
|
case PBT_APMRESUMECRITICAL:
|
|
case PBT_APMRESUMESUSPEND:
|
|
case PBT_APMRESUMESTANDBY:
|
|
case PBT_APMRESUMEAUTOMATIC:
|
|
|
|
// If the system is resuming from a real suspend
|
|
// (as opposed to a failed suspend) deactivate
|
|
// the screensaver.
|
|
if ((lParam & PBTF_APMRESUMEFROMFAILURE) == 0)
|
|
{
|
|
goto PostClose;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
goto PostClose;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_POWER:
|
|
//
|
|
// a critical resume does not generate a WM_POWERBROADCAST
|
|
// to windows for some reason, but it does generate an old
|
|
// WM_POWER message.
|
|
//
|
|
if (wParam == PWR_CRITICALRESUME)
|
|
goto PostClose;
|
|
break;
|
|
|
|
case WM_ACTIVATEAPP:
|
|
if( wParam ) break;
|
|
case WM_LBUTTONDOWN:
|
|
case WM_MBUTTONDOWN:
|
|
case WM_RBUTTONDOWN:
|
|
case WM_KEYDOWN:
|
|
case WM_SYSKEYDOWN:
|
|
PostClose:
|
|
PostMessage( hWnd, WM_CLOSE, 0, 0l );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// the shell sends this message to the foreground window before running an
|
|
// AutoPlay app. On Win95, we return 1 to cancel autoplay if we are password protected
|
|
//
|
|
// On WinNT, secure screen savers run on a secure separate desktop, and will never see
|
|
// this message, therefore, this code will never get executed.
|
|
//
|
|
//
|
|
// APPCOMPAT -
|
|
// On NT we don't want to take down the screen saver unless it is running
|
|
// on the same desktop as the autoplay shell. There is code in the
|
|
// NT autoplay shell that looks for this and does not run the app if
|
|
// that is the case; however, I not positive that the uShellAutoPlayQueryMessage
|
|
// will not go between desktops. (BradG assures me that it will not, but you
|
|
// never know.) If secure screensavers on NT randomly close when you put
|
|
// an autoplay cd in the drive, then this code should be examined closely.
|
|
//
|
|
if ((uMsg == uShellAutoPlayQueryMessage) && uMsg)
|
|
{
|
|
PostMessage(hWnd, WM_CLOSE, 0, 0L);
|
|
return (VerifyPassword != NULL);
|
|
}
|
|
|
|
return DefWindowProc( hWnd, uMsg, wParam, lParam );
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// This window procedure takes care of important stuff before calling the
|
|
// consumer's ScreenSaverProc. This helps to prevent us from getting hosed
|
|
// by wacky consumer code.
|
|
LRESULT WINAPI
|
|
RealScreenSaverProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
switch( uMsg )
|
|
{
|
|
case WM_CREATE:
|
|
// screen saver does not need the IME
|
|
if ((hInstImm = GetModuleHandle(szImmDLL)) &&
|
|
(ImmFnc = (IMMASSOCPROC)GetProcAddress(hInstImm,szImmFnc)))
|
|
hPrevImc = ImmFnc(hWnd, (HIMC)0);
|
|
|
|
// establish the mouse position
|
|
GetCursorPos( &ptMouse );
|
|
|
|
if( !fChildPreview )
|
|
SetCursor( NULL );
|
|
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
// screen saver does not need the IME
|
|
if( hInstImm && ImmFnc && hPrevImc )
|
|
ImmFnc(hWnd, hPrevImc);
|
|
|
|
PostQuitMessage( 0 );
|
|
break;
|
|
|
|
case WM_SETTEXT:
|
|
// don't let some fool change our title
|
|
// we need to be able to use FindWindow() to find running instances
|
|
// of full-screen windows screen savers
|
|
// NOTE: USER slams our title in during WM_NCCREATE by calling the
|
|
// defproc for WM_SETTEXT directly, so the initial title will get
|
|
// there. If this ever changes, we can simply set a bypass flag
|
|
// during WM_NCCREATE processing.
|
|
return FALSE;
|
|
|
|
case WM_SYSCOMMAND:
|
|
if (!fChildPreview)
|
|
{
|
|
switch (wParam)
|
|
{
|
|
case SC_NEXTWINDOW: // no Alt-tabs
|
|
case SC_PREVWINDOW: // no shift-alt-tabs
|
|
case SC_SCREENSAVE: // no more screensavers
|
|
return FALSE;
|
|
break;
|
|
case SC_MONITORPOWER:
|
|
//
|
|
// The monitor is shutting down. Tell our client that he needs to
|
|
// cleanup and exit.
|
|
//
|
|
PostMessage( hWnd, WM_CLOSE, 0, 0l );
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_HELP:
|
|
case WM_CONTEXTMENU:
|
|
if( fChildPreview )
|
|
{
|
|
// if we're in preview mode, pump the help stuff to our owner
|
|
HWND hParent = GetParent( hWnd );
|
|
|
|
if( hParent && IsWindow( hParent ) )
|
|
PostMessage( hParent, uMsg, (WPARAM)hParent, lParam );
|
|
return TRUE;
|
|
}
|
|
break;
|
|
|
|
case WM_TIMER:
|
|
if( fClosing )
|
|
return FALSE;
|
|
Sleep( 0 );
|
|
break;
|
|
|
|
case WM_MOUSEMOVE:
|
|
case WM_LBUTTONDOWN:
|
|
case WM_MBUTTONDOWN:
|
|
case WM_RBUTTONDOWN:
|
|
case WM_KEYDOWN:
|
|
case WM_SYSKEYDOWN:
|
|
if( fClosing )
|
|
return DefWindowProc( hWnd, uMsg, wParam, lParam );
|
|
break;
|
|
|
|
case WM_PAINT:
|
|
if( fClosing )
|
|
return DefWindowProc( hWnd, uMsg, wParam, lParam );
|
|
if( !fChildPreview )
|
|
SetCursor( NULL );
|
|
break;
|
|
}
|
|
|
|
return ScreenSaverProc( hWnd, uMsg, wParam, lParam );
|
|
}
|
|
|
|
static void
|
|
InitRealScreenSave()
|
|
{
|
|
#if 0
|
|
HKEY hkey;
|
|
|
|
if (RegOpenKey(HKEY_CURRENT_USER, szCoolSaverHacks, &hkey) ==
|
|
ERROR_SUCCESS)
|
|
{
|
|
DWORD data, len, type;
|
|
|
|
len = sizeof(data);
|
|
if ((RegQueryValueEx(hkey, szMouseThreshold, NULL, &type,
|
|
(LPBYTE)&data, &len) == ERROR_SUCCESS) && (type == REG_DWORD))
|
|
{
|
|
dwWakeThreshold = max(dwWakeThreshold, data);
|
|
}
|
|
|
|
len = sizeof(data);
|
|
if ((RegQueryValueEx(hkey, szPasswordDelay, NULL, &type,
|
|
(LPBYTE)&data, &len) == ERROR_SUCCESS) && (type == REG_DWORD) && data)
|
|
{
|
|
data = min(MAX_PASSWORD_DELAY_IN_SECONDS, data);
|
|
dwPasswordDelay = data * 1000;
|
|
dwBlankTime = GetTickCount();
|
|
}
|
|
}
|
|
#endif
|
|
|
|
LoadPwdDLL();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
static INT_PTR
|
|
DoScreenSave( HWND hParent )
|
|
{
|
|
LPCTSTR pszWindowClass = TEXT("WindowsScreenSaverClass");
|
|
LPCTSTR pszWindowTitle;
|
|
|
|
WNDCLASS cls;
|
|
MSG msg;
|
|
UINT uStyle;
|
|
UINT uExStyle;
|
|
int ncx, ncy;
|
|
int nx, ny;
|
|
|
|
SYSTEM_POWER_STATUS sps;
|
|
|
|
cls.hCursor = NULL;
|
|
cls.hIcon = LoadIcon( hMainInstance, MAKEINTATOM( ID_APP ) );
|
|
cls.lpszMenuName = NULL;
|
|
cls.lpszClassName = pszWindowClass;
|
|
cls.hbrBackground = GetStockObject( BLACK_BRUSH );
|
|
cls.hInstance = hMainInstance;
|
|
cls.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS | CS_OWNDC;
|
|
cls.lpfnWndProc = RealScreenSaverProc;
|
|
cls.cbWndExtra = 0;
|
|
cls.cbClsExtra = 0;
|
|
|
|
if( hParent )
|
|
{
|
|
RECT rcParent;
|
|
GetClientRect( hParent, &rcParent );
|
|
ncx = rcParent.right;
|
|
ncy = rcParent.bottom;
|
|
nx = 0;
|
|
ny = 0;
|
|
uStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN;
|
|
uExStyle = 0;
|
|
|
|
fChildPreview = TRUE;
|
|
pszWindowTitle = TEXT("Preview"); // MUST differ from full screen
|
|
}
|
|
else
|
|
{
|
|
HWND hOther;
|
|
|
|
#ifdef SM_CXVIRTUALSCREEN
|
|
nx = GetSystemMetrics( SM_XVIRTUALSCREEN );
|
|
ny = GetSystemMetrics( SM_YVIRTUALSCREEN );
|
|
ncx = GetSystemMetrics( SM_CXVIRTUALSCREEN );
|
|
ncy = GetSystemMetrics( SM_CYVIRTUALSCREEN );
|
|
|
|
if (ncx == 0 || ncy == 0)
|
|
#endif
|
|
{
|
|
RECT rc;
|
|
HDC hdc = GetDC(NULL);
|
|
GetClipBox(hdc, &rc);
|
|
ReleaseDC(NULL, hdc);
|
|
nx = rc.left;
|
|
ny = rc.top;
|
|
ncx = rc.right - rc.left;
|
|
ncy = rc.bottom - rc.top;
|
|
}
|
|
|
|
uStyle = WS_POPUP | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
|
|
uExStyle = WS_EX_TOPMOST;
|
|
|
|
pszWindowTitle = TEXT("Screen Saver"); // MUST differ from preview
|
|
|
|
// if there is another NORMAL screen save instance, switch to it
|
|
hOther = FindWindow( pszWindowClass, pszWindowTitle );
|
|
|
|
if( hOther && IsWindow( hOther ) )
|
|
{
|
|
SetForegroundWindow( hOther );
|
|
return 0;
|
|
}
|
|
|
|
// Get current system power status and store it
|
|
if (GetSystemPowerStatus(&sps)) {
|
|
bACLineStatus = sps.ACLineStatus;
|
|
}
|
|
else {
|
|
// we can't determine the power status, use default
|
|
bACLineStatus = AC_LINE_UNKNOWN;
|
|
}
|
|
|
|
|
|
InitRealScreenSave();
|
|
}
|
|
|
|
//
|
|
// the shell sends this message to the foreground window before running an
|
|
// AutoPlay app. we return 1 to cancel autoplay if we are password protected
|
|
//
|
|
if (fOnWin95) {
|
|
uShellAutoPlayQueryMessage = RegisterWindowMessage(TEXT("QueryCancelAutoPlay"));
|
|
} else {
|
|
uShellAutoPlayQueryMessage = 0;
|
|
}
|
|
|
|
if( RegisterClass( &cls ) )
|
|
{
|
|
hMainWindow = CreateWindowEx( uExStyle, pszWindowClass, pszWindowTitle,
|
|
uStyle, nx, ny, ncx, ncy, hParent, (HMENU)NULL,
|
|
hMainInstance, (LPVOID)NULL );
|
|
}
|
|
|
|
msg.wParam = 0;
|
|
if( hMainWindow )
|
|
{
|
|
if( !fChildPreview )
|
|
SetForegroundWindow( hMainWindow );
|
|
|
|
while( GetMessage( &msg, NULL, 0, 0 ) )
|
|
{
|
|
TranslateMessage( &msg );
|
|
DispatchMessage( &msg );
|
|
}
|
|
}
|
|
|
|
// free password-handling DLL if loaded
|
|
UnloadPwdDLL();
|
|
|
|
return msg.wParam;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
static INT_PTR
|
|
DoSaverPreview( LPCTSTR szUINTHandle )
|
|
{
|
|
// get parent handle from string
|
|
HWND hParent = (HWND)atoui( szUINTHandle );
|
|
|
|
// only preview on a valid parent window (NOT full screen)
|
|
return ( (hParent && IsWindow( hParent ))? DoScreenSave( hParent ) : -1 );
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
static INT_PTR
|
|
DoConfigBox( HWND hParent )
|
|
{
|
|
// let the consumer register any special controls for the dialog
|
|
if( !RegisterDialogClasses( hMainInstance ) )
|
|
return FALSE;
|
|
|
|
return DialogBox( hMainInstance, MAKEINTRESOURCE( DLG_SCRNSAVECONFIGURE ),
|
|
hParent, (WNDPROC)ScreenSaverConfigureDialog );
|
|
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
static INT_PTR
|
|
DoChangePw( LPCTSTR szUINTHandle )
|
|
{
|
|
// get parent handle from string
|
|
HWND hParent = (HWND)atoui( szUINTHandle );
|
|
|
|
if( !hParent || !IsWindow( hParent ) )
|
|
hParent = GetForegroundWindow();
|
|
|
|
// allow the library to be hooked
|
|
ScreenSaverChangePassword( hParent );
|
|
return 0;
|
|
}
|
|
|
|
static const TCHAR szMprDll[] = TEXT("MPR.DLL"); // not to be localized
|
|
static const TCHAR szProviderName[] = TEXT("SCRSAVE"); // not to be localized
|
|
|
|
#ifdef UNICODE
|
|
static const CHAR szPwdChangePW[] = "PwdChangePasswordW"; // not to be localized
|
|
#else
|
|
static const CHAR szPwdChangePW[] = "PwdChangePasswordA"; // not to be localized
|
|
#endif
|
|
|
|
// bogus prototype
|
|
typedef DWORD (FAR PASCAL *PWCHGPROC)( LPCTSTR, HWND, DWORD, LPVOID );
|
|
|
|
void WINAPI
|
|
ScreenSaverChangePassword( HWND hParent )
|
|
{
|
|
HINSTANCE mpr = LoadLibrary( szMprDll );
|
|
|
|
if( mpr )
|
|
{
|
|
// netland hasn't cracked MNRENTRY yet
|
|
PWCHGPROC pwd = (PWCHGPROC)GetProcAddress( mpr, szPwdChangePW );
|
|
|
|
if( pwd )
|
|
pwd( szProviderName, hParent, 0, NULL );
|
|
|
|
FreeLibrary( mpr );
|
|
}
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
static BOOL
|
|
DoPasswordCheck( HWND hParent )
|
|
{
|
|
// don't reenter and don't check when we've already decided
|
|
if( fCheckingPassword || fClosing )
|
|
return FALSE;
|
|
|
|
if( VerifyPassword )
|
|
{
|
|
static DWORD lastcheck = (DWORD)-1;
|
|
DWORD curtime = GetTickCount();
|
|
MSG msg;
|
|
|
|
if (dwPasswordDelay &&
|
|
(GetElapsedTime(dwBlankTime, curtime) < dwPasswordDelay))
|
|
{
|
|
fClosing = TRUE;
|
|
goto _didcheck;
|
|
}
|
|
|
|
// no rapid checking...
|
|
if ((lastcheck != (DWORD)-1) &&
|
|
(GetElapsedTime(lastcheck, curtime) < 200))
|
|
{
|
|
goto _didcheck;
|
|
}
|
|
|
|
// do the check
|
|
fCheckingPassword = TRUE;
|
|
|
|
// flush WM_TIMER messages before putting up the dialog
|
|
PeekMessage( &msg, hParent, WM_TIMER, WM_TIMER, PM_REMOVE | PM_NOYIELD );
|
|
PeekMessage( &msg, hParent, WM_TIMER, WM_TIMER, PM_REMOVE | PM_NOYIELD );
|
|
|
|
// call the password verify proc
|
|
fClosing = (BOOL)SendMessage( hParent, SCRM_VERIFYPW, 0, 0L );
|
|
|
|
fCheckingPassword = FALSE;
|
|
|
|
if (!fClosing)
|
|
SetCursor(NULL);
|
|
|
|
// curtime may be outdated by now
|
|
lastcheck = GetTickCount();
|
|
}
|
|
else
|
|
{
|
|
// passwords disabled or unable to load handler DLL, always allow exit
|
|
fClosing = TRUE;
|
|
}
|
|
|
|
_didcheck:
|
|
return fClosing;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// stolen from the CRT, used to shirink our code
|
|
|
|
int _stdcall
|
|
DummyEntry( void )
|
|
{
|
|
int i;
|
|
STARTUPINFO si;
|
|
LPTSTR pszCmdLine = GetCommandLine();
|
|
|
|
if ( *pszCmdLine == TEXT('\"')) {
|
|
/*
|
|
* Scan, and skip over, subsequent characters until
|
|
* another double-quote or a null is encountered.
|
|
*/
|
|
while (*(pszCmdLine = CharNext(pszCmdLine)) &&
|
|
(*pszCmdLine != TEXT('\"')) );
|
|
/*
|
|
* If we stopped on a double-quote (usual case), skip
|
|
* over it.
|
|
*/
|
|
if ( *pszCmdLine == TEXT('\"') )
|
|
pszCmdLine++;
|
|
}
|
|
else {
|
|
while ((UINT)*pszCmdLine > (UINT)TEXT(' '))
|
|
pszCmdLine = CharNext(pszCmdLine);
|
|
}
|
|
|
|
/*
|
|
* Skip past any white space preceeding the second token.
|
|
*/
|
|
while (*pszCmdLine && ((UINT)*pszCmdLine <= (UINT)TEXT(' '))) {
|
|
pszCmdLine = CharNext(pszCmdLine);
|
|
}
|
|
|
|
si.dwFlags = 0;
|
|
GetStartupInfo(&si);
|
|
|
|
i = (int)WinMainN(GetModuleHandle(NULL), NULL, pszCmdLine,
|
|
si.dwFlags & STARTF_USESHOWWINDOW ? si.wShowWindow : SW_SHOWDEFAULT);
|
|
|
|
ExitProcess(i);
|
|
return i; // We never comes here.
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// main() entry point to satisfy old NT screen savers
|
|
void _cdecl main( int argc, char *argv[] ) {
|
|
DummyEntry();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// WinMain() entry point to satisfy old NT screen savers
|
|
int PASCAL WinMain( HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow ) {
|
|
DummyEntry();
|
|
return 0;
|
|
|
|
// reference unreferenced parameters
|
|
(void)hInst;
|
|
(void)hPrev;
|
|
(void)szCmdLine;
|
|
(void)nCmdShow;
|
|
}
|
|
|
|
|
|
VOID LoadPwdDLL(VOID)
|
|
{
|
|
HKEY hKey;
|
|
|
|
if (!fOnWin95)
|
|
return;
|
|
|
|
if (hInstPwdDLL)
|
|
UnloadPwdDLL();
|
|
|
|
// look in registry to see if password turned on, otherwise don't
|
|
// bother to load password handler DLL
|
|
if (RegOpenKey(HKEY_CURRENT_USER,szScreenSaverKey,&hKey) ==
|
|
ERROR_SUCCESS)
|
|
{
|
|
DWORD dwVal,dwSize=sizeof(dwVal);
|
|
|
|
if ((RegQueryValueEx(hKey,szPasswordActiveValue,
|
|
NULL,NULL,(BYTE *) &dwVal,&dwSize) == ERROR_SUCCESS)
|
|
&& dwVal)
|
|
{
|
|
|
|
// try to load the DLL that contains password proc.
|
|
hInstPwdDLL = LoadLibrary(szPwdDLL);
|
|
if (hInstPwdDLL)
|
|
{
|
|
VerifyPassword = (VERIFYPWDPROC) GetProcAddress(hInstPwdDLL,
|
|
szFnName);
|
|
|
|
if( VerifyPassword )
|
|
HogMachine( TRUE );
|
|
else
|
|
UnloadPwdDLL();
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
}
|
|
|
|
VOID UnloadPwdDLL(VOID)
|
|
{
|
|
if (!fOnWin95)
|
|
return;
|
|
|
|
if (hInstPwdDLL)
|
|
{
|
|
FreeLibrary(hInstPwdDLL);
|
|
hInstPwdDLL = NULL;
|
|
|
|
if( VerifyPassword )
|
|
{
|
|
VerifyPassword = NULL;
|
|
HogMachine( FALSE );
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// compatbility stuff (to make porting easier)
|
|
TCHAR szAppName[ APPNAMEBUFFERLEN ];
|
|
TCHAR szName[ TITLEBARNAMELEN ];
|
|
TCHAR szIniFile[ MAXFILELEN ];
|
|
TCHAR szScreenSaver[ 22 ];
|
|
TCHAR szHelpFile[ MAXFILELEN ];
|
|
TCHAR szNoHelpMemory[ BUFFLEN ];
|
|
|
|
// Quick fix for old screen savers that don't know about context
|
|
// sensitive help
|
|
UINT MyHelpMessage = WM_HELP;
|