Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

910 lines
25 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // SCRNSAVE.C -- skeleton for screen saver application
  4. //
  5. // 4/5/94 francish merged NT and Win4 saver code, folded in SCRNSAVE.SCR
  6. //
  7. // - 3/14/96: marcfo Pulled this file in from shell\control\scrnsave\common.
  8. // All changes marked with GL_SCRNSAVE.
  9. //----------------------------------------------------------------------------
  10. #define GL_SCRNSAVE 1
  11. #define WIN31
  12. #include <windows.h>
  13. #include <windowsx.h>
  14. #include "scrnsave.h"
  15. #include <regstr.h>
  16. #include <imm.h>
  17. #ifdef GL_SCRNSAVE
  18. #include "glscrnsv.h"
  19. #endif
  20. #define DBG_MSGS 0
  21. const TCHAR szScreenSaverKey[] = REGSTR_PATH_SCREENSAVE;
  22. TCHAR szPasswordActiveValue[] = REGSTR_VALUE_USESCRPASSWORD;
  23. const TCHAR szPasswordValue[] = REGSTR_VALUE_SCRPASSWORD;
  24. TCHAR szPwdDLL[] = TEXT("PASSWORD.CPL");
  25. CHAR szFnName[] = "VerifyScreenSavePwd"; // Proc name, must be ANSI
  26. TCHAR szImmDLL[] = TEXT("IMM32.DLL");
  27. CHAR szImmFnc[] = "ImmAssociateContext"; // Proc name, must be ANSI
  28. #if 0
  29. TCHAR szCoolSaverHacks[] = REGSTR_PATH_SETUP TEXT("\\Screen Savers");
  30. TCHAR szMouseThreshold[] = TEXT("Mouse Threshold");
  31. TCHAR szPasswordDelay[] = TEXT("Password Delay");
  32. #endif
  33. typedef BOOL (FAR PASCAL * VERIFYPWDPROC) (HWND);
  34. typedef HIMC (FAR PASCAL * IMMASSOCPROC) (HWND,HIMC);
  35. //----------------------------------------------------------------------------
  36. // variables declared in SCRNSAVE.H
  37. HINSTANCE hMainInstance = 0;
  38. HWND hMainWindow = 0;
  39. BOOL fChildPreview = FALSE;
  40. //----------------------------------------------------------------------------
  41. // other globals
  42. POINT ptMouse;
  43. BOOL fClosing = FALSE;
  44. BOOL fCheckingPassword = FALSE;
  45. HINSTANCE hInstPwdDLL = NULL;
  46. VERIFYPWDPROC VerifyPassword = NULL;
  47. static BOOL preview_like_fullscreen = FALSE;
  48. static UINT uShellAutoPlayQueryMessage = 0;
  49. HINSTANCE hInstImm = NULL;
  50. IMMASSOCPROC ImmFnc = NULL;
  51. HIMC hPrevImc = (HIMC)0L;
  52. static BOOL fOnWin95 = FALSE; //TRUE if on Chicago, FALSE if on Cairo
  53. //----------------------------------------------------------------------------
  54. // random junk
  55. DWORD dwWakeThreshold = 4; //default to slight movement
  56. DWORD dwPasswordDelay = 0;
  57. DWORD dwBlankTime = 0;
  58. #define MAX_PASSWORD_DELAY_IN_SECONDS (60)
  59. //----------------------------------------------------------------------------
  60. // forward declarations of internal fns
  61. #ifndef GL_SCRNSAVE
  62. // These are hooked out to glscrnsv.cxx
  63. static INT_PTR DoScreenSave( HWND hParent );
  64. static INT_PTR DoConfigBox( HWND hParent );
  65. #endif
  66. static INT_PTR DoSaverPreview( LPCTSTR szUINTHandle );
  67. static INT_PTR DoChangePw( LPCTSTR szUINTHandle );
  68. static BOOL DoPasswordCheck( HWND hParent );
  69. VOID LoadPwdDLL(VOID);
  70. VOID UnloadPwdDLL(VOID);
  71. //----------------------------------------------------------------------------
  72. // helper for time
  73. static DWORD
  74. GetElapsedTime(DWORD from, DWORD to)
  75. {
  76. return (to >= from)? (to - from) : (1 + to + (((DWORD)-1) - from));
  77. }
  78. //----------------------------------------------------------------------------
  79. // helper to convert text to unsigned int
  80. static UINT_PTR
  81. atoui( LPCTSTR szUINT )
  82. {
  83. UINT_PTR uValue = 0;
  84. while( ( *szUINT >= TEXT('0') ) && ( *szUINT <= TEXT('9') ) )
  85. uValue = ( ( uValue * 10 ) + ( *szUINT++ - TEXT('0') ) );
  86. return uValue;
  87. }
  88. //----------------------------------------------------------------------------
  89. // Local reboot and hotkey control (on Win95)
  90. static void
  91. HogMachine( BOOL value )
  92. {
  93. BOOL dummy;
  94. //
  95. // NT is always secure, therefore we don't need to call this on Cairo/NT
  96. //
  97. if (fOnWin95) {
  98. SystemParametersInfo( SPI_SCREENSAVERRUNNING, value, &dummy, 0 );
  99. }
  100. }
  101. //----------------------------------------------------------------------------
  102. // entry point (duh)
  103. INT_PTR PASCAL
  104. WinMainN( HINSTANCE hInst, HINSTANCE hPrev, LPTSTR szCmdLine, int nCmdShow )
  105. {
  106. LPCTSTR pch = szCmdLine;
  107. HWND hParent = 0;
  108. OSVERSIONINFO osvi;
  109. hMainInstance = hInst;
  110. osvi.dwOSVersionInfoSize = sizeof(osvi);
  111. fOnWin95 = (GetVersionEx(&osvi) &&
  112. osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
  113. #ifdef GL_SCRNSAVE
  114. //
  115. // the shell sends this message to the foreground window before running an
  116. // AutoPlay app. we return 1 to cancel autoplay if we are password protected
  117. //
  118. if (fOnWin95) {
  119. uShellAutoPlayQueryMessage = RegisterWindowMessage(TEXT("QueryCancelAutoPlay"));
  120. } else {
  121. uShellAutoPlayQueryMessage = 0;
  122. }
  123. #endif
  124. _try
  125. {
  126. for(;;) switch( *pch )
  127. {
  128. case TEXT('S'):
  129. case TEXT('s'):
  130. return DoScreenSave( NULL );
  131. #ifdef GL_SCRNSAVE
  132. case TEXT('W'):
  133. case TEXT('w'):
  134. do pch++; while( *pch == TEXT(' ') ); // size parameters
  135. return DoWindowedScreenSave( pch );
  136. #endif
  137. case TEXT('L'):
  138. case TEXT('l'):
  139. // special switch for tests such as WinBench
  140. // this is NOT a hack to make bechmarks look good
  141. // it's a hack to allow you to benchmark a screen saver
  142. // many bechmarking apps require the whole screen in foreground
  143. // which makes it hard to measure how a screensaver adds CPU load
  144. // you must provide a parent window (just like preview mode)
  145. preview_like_fullscreen = TRUE;
  146. case TEXT('P'):
  147. case TEXT('p'):
  148. do pch++; while( *pch == TEXT(' ') ); // skip to the good stuff
  149. return DoSaverPreview( pch );
  150. case TEXT('A'):
  151. case TEXT('a'):
  152. if (!fOnWin95)
  153. return -1;
  154. do pch++; while( *pch == TEXT(' ') ); // skip to the good stuff
  155. return DoChangePw( pch );
  156. case TEXT('C'):
  157. case TEXT('c'): {
  158. HWND hwndParent = NULL
  159. ;
  160. // Look for optional parent window after the "C",
  161. // syntax is "C:hwnd_value"
  162. if (*(++pch) == TEXT(':')) {
  163. hwndParent = (HWND)atoui( ++pch );
  164. }
  165. if (hwndParent == NULL || !IsWindow(hwndParent))
  166. hwndParent = GetForegroundWindow();
  167. return DoConfigBox( hwndParent );
  168. }
  169. case TEXT('\0'):
  170. return DoConfigBox( NULL );
  171. case TEXT(' '):
  172. case TEXT('-'):
  173. case TEXT('/'):
  174. pch++; // skip spaces and common switch prefixes
  175. break;
  176. default:
  177. return -1;
  178. }
  179. }
  180. _except(UnhandledExceptionFilter(GetExceptionInformation()))
  181. {
  182. // don't leave local reboot and hotkeys disabled on Win95
  183. HogMachine( FALSE );
  184. }
  185. return -1;
  186. }
  187. //----------------------------------------------------------------------------
  188. // default screen-saver proc, declared in SCRNSAVE.H
  189. // intended to be called by the consumer's ScreenSaverProc where
  190. // DefWindowProc would normally be called
  191. LRESULT WINAPI
  192. DefScreenSaverProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  193. {
  194. #if DBG_MSGS
  195. TCHAR szBuff[80];
  196. wsprintf( szBuff, TEXT("*** DefSSP received:\t0x%04lx 0x%08lx 0x%08lx\n"), uMsg, wParam, lParam );
  197. OutputDebugString(szBuff);
  198. #endif
  199. if( !fChildPreview && !fClosing )
  200. {
  201. switch( uMsg )
  202. {
  203. case WM_CLOSE:
  204. //
  205. // Only do password check if on Windows 95. WinNT (Cairo) has
  206. // the password check built into the security desktop for
  207. // C2 compliance.
  208. //
  209. if (fOnWin95) {
  210. if( !DoPasswordCheck( hWnd ) )
  211. {
  212. GetCursorPos( &ptMouse ); // re-establish
  213. return FALSE;
  214. }
  215. }
  216. #ifdef GL_SCRNSAVE
  217. // We need to know when we're being terminated, so we can do
  218. // various clean-up stuff
  219. SendMessage( hWnd, SS_WM_CLOSING, 0, 0 );
  220. #endif
  221. break;
  222. case SCRM_VERIFYPW:
  223. if (fOnWin95)
  224. return ( VerifyPassword? (LRESULT)VerifyPassword( hWnd ) : 1L );
  225. break;
  226. default:
  227. {
  228. POINT ptMove, ptCheck;
  229. if( fCheckingPassword )
  230. break;
  231. switch( uMsg )
  232. {
  233. case WM_SHOWWINDOW:
  234. if( (BOOL)wParam )
  235. SetCursor( NULL );
  236. break;
  237. case WM_SETCURSOR:
  238. SetCursor( NULL );
  239. return TRUE;
  240. case WM_MOUSEMOVE:
  241. GetCursorPos( &ptCheck );
  242. if( ( ptMove.x = ptCheck.x - ptMouse.x ) && ( ptMove.x < 0 ) )
  243. ptMove.x *= -1;
  244. if( ( ptMove.y = ptCheck.y - ptMouse.y ) && ( ptMove.y < 0 ) )
  245. ptMove.y *= -1;
  246. if( ((DWORD)ptMove.x + (DWORD)ptMove.y) > dwWakeThreshold )
  247. {
  248. PostMessage( hWnd, WM_CLOSE, 0, 0l );
  249. ptMouse = ptCheck;
  250. }
  251. break;
  252. case WM_POWERBROADCAST:
  253. switch (wParam)
  254. {
  255. case PBT_APMRESUMECRITICAL:
  256. case PBT_APMRESUMESUSPEND:
  257. case PBT_APMRESUMESTANDBY:
  258. case PBT_APMRESUMEAUTOMATIC:
  259. // If the system is resuming from a real suspend
  260. // (as opposed to a failed suspend) deactivate
  261. // the screensaver.
  262. if ((lParam & PBTF_APMRESUMEFROMFAILURE) == 0)
  263. goto PostClose;
  264. break;
  265. default:
  266. // The standard screensaver code shuts down on
  267. // all power broadcast messages. This doesn't
  268. // make much sense, but match the behavior so
  269. // that all screensavers operate the same way.
  270. goto PostClose;
  271. }
  272. break;
  273. case WM_POWER:
  274. //
  275. // a critical resume does not generate a WM_POWERBROADCAST
  276. // to windows for some reason, but it does generate an old
  277. // WM_POWER message.
  278. //
  279. if (wParam == PWR_CRITICALRESUME)
  280. goto PostClose;
  281. break;
  282. case WM_ACTIVATEAPP:
  283. if( wParam ) break;
  284. case WM_LBUTTONDOWN:
  285. case WM_MBUTTONDOWN:
  286. case WM_RBUTTONDOWN:
  287. case WM_KEYDOWN:
  288. case WM_SYSKEYDOWN:
  289. PostClose:
  290. PostMessage( hWnd, WM_CLOSE, 0, 0l );
  291. break;
  292. }
  293. }
  294. }
  295. }
  296. //
  297. // the shell sends this message to the foreground window before running an
  298. // AutoPlay app. On Win95, we return 1 to cancel autoplay if we are password protected
  299. //
  300. // On WinNT, secure screen savers run on a secure separate desktop, and will never see
  301. // this message, therefore, this code will never get executed.
  302. //
  303. //
  304. //
  305. // On NT we don't want to take down the screen saver unless it is running
  306. // on the same desktop as the autoplay shell. There is code in the
  307. // NT autoplay shell that looks for this and does not run the app if
  308. // that is the case; however, I not positive that the uShellAutoPlayQueryMessage
  309. // will not go between desktops. (BradG assures me that it will not, but you
  310. // never know.) If secure screensavers on NT randomly close when you put
  311. // an autoplay cd in the drive, then this code should be examined closely.
  312. //
  313. if ((uMsg == uShellAutoPlayQueryMessage) && uMsg)
  314. {
  315. PostMessage(hWnd, WM_CLOSE, 0, 0L);
  316. return (VerifyPassword != NULL);
  317. }
  318. return DefWindowProc( hWnd, uMsg, wParam, lParam );
  319. }
  320. //----------------------------------------------------------------------------
  321. // This window procedure takes care of important stuff before calling the
  322. // consumer's ScreenSaverProc. This helps to prevent us from getting hosed
  323. // by wacky consumer code.
  324. LRESULT WINAPI
  325. RealScreenSaverProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  326. {
  327. switch( uMsg )
  328. {
  329. case WM_CREATE:
  330. // screen saver does not need the IME
  331. if ((hInstImm = GetModuleHandle(szImmDLL)) &&
  332. (ImmFnc = (IMMASSOCPROC)GetProcAddress(hInstImm,szImmFnc)))
  333. hPrevImc = ImmFnc(hWnd, (HIMC)0);
  334. // establish the mouse position
  335. GetCursorPos( &ptMouse );
  336. if( !fChildPreview )
  337. SetCursor( NULL );
  338. break;
  339. case WM_DESTROY:
  340. // screen saver does not need the IME
  341. if( hInstImm && ImmFnc && hPrevImc )
  342. ImmFnc(hWnd, hPrevImc);
  343. PostQuitMessage( 0 );
  344. break;
  345. case WM_SETTEXT:
  346. // don't let some fool change our title
  347. // we need to be able to use FindWindow() to find running instances
  348. // of full-screen windows screen savers
  349. // NOTE: USER slams our title in during WM_NCCREATE by calling the
  350. // defproc for WM_SETTEXT directly, so the initial title will get
  351. // there. If this ever changes, we can simply set a bypass flag
  352. // during WM_NCCREATE processing.
  353. return FALSE;
  354. case WM_SYSCOMMAND:
  355. if (!fChildPreview)
  356. {
  357. switch (wParam)
  358. {
  359. case SC_NEXTWINDOW: // no Alt-tabs
  360. case SC_PREVWINDOW: // no shift-alt-tabs
  361. case SC_SCREENSAVE: // no more screensavers
  362. return FALSE;
  363. }
  364. }
  365. break;
  366. case WM_HELP:
  367. case WM_CONTEXTMENU:
  368. if( fChildPreview )
  369. {
  370. // if we're in preview mode, pump the help stuff to our owner
  371. HWND hParent = GetParent( hWnd );
  372. if( hParent && IsWindow( hParent ) )
  373. PostMessage( hParent, uMsg, (WPARAM)hParent, lParam );
  374. return TRUE;
  375. }
  376. break;
  377. case WM_TIMER:
  378. if( fClosing )
  379. return FALSE;
  380. Sleep( 0 );
  381. break;
  382. case WM_IME_NOTIFY:
  383. // Eat IMN_OPENSTATUSWINDOW so that the status window
  384. // isn't displayed.
  385. if (wParam == IMN_OPENSTATUSWINDOW)
  386. {
  387. return 0;
  388. }
  389. break;
  390. case WM_MOUSEMOVE:
  391. case WM_LBUTTONDOWN:
  392. case WM_MBUTTONDOWN:
  393. case WM_RBUTTONDOWN:
  394. case WM_KEYDOWN:
  395. case WM_SYSKEYDOWN:
  396. if( fClosing )
  397. return DefWindowProc( hWnd, uMsg, wParam, lParam );
  398. break;
  399. case WM_PAINT:
  400. if( fClosing )
  401. return DefWindowProc( hWnd, uMsg, wParam, lParam );
  402. if( !fChildPreview )
  403. SetCursor( NULL );
  404. break;
  405. }
  406. return ScreenSaverProc( hWnd, uMsg, wParam, lParam );
  407. }
  408. #ifdef GL_SCRNSAVE
  409. void
  410. #else
  411. static void
  412. #endif
  413. InitRealScreenSave()
  414. {
  415. #if 0
  416. HKEY hkey;
  417. if (RegOpenKey(HKEY_CURRENT_USER, szCoolSaverHacks, &hkey) ==
  418. ERROR_SUCCESS)
  419. {
  420. DWORD data, len, type;
  421. len = sizeof(data);
  422. if ((RegQueryValueEx(hkey, szMouseThreshold, NULL, &type,
  423. (LPBYTE)&data, &len) == ERROR_SUCCESS) && (type == REG_DWORD))
  424. {
  425. dwWakeThreshold = max(dwWakeThreshold, data);
  426. }
  427. len = sizeof(data);
  428. if ((RegQueryValueEx(hkey, szPasswordDelay, NULL, &type,
  429. (LPBYTE)&data, &len) == ERROR_SUCCESS) && (type == REG_DWORD) && data)
  430. {
  431. data = min(MAX_PASSWORD_DELAY_IN_SECONDS, data);
  432. dwPasswordDelay = data * 1000;
  433. dwBlankTime = GetTickCount();
  434. }
  435. }
  436. #endif
  437. LoadPwdDLL();
  438. }
  439. //----------------------------------------------------------------------------
  440. #ifndef GL_SCRNSAVE
  441. static INT_PTR
  442. DoScreenSave( HWND hParent )
  443. {
  444. LPCTSTR pszWindowClass = TEXT("WindowsScreenSaverClass");
  445. LPCTSTR pszWindowTitle;
  446. WNDCLASS cls;
  447. MSG msg;
  448. UINT uStyle;
  449. UINT uExStyle;
  450. int ncx, ncy;
  451. int nx, ny;
  452. cls.hCursor = NULL;
  453. cls.hIcon = LoadIcon( hMainInstance, MAKEINTATOM( ID_APP ) );
  454. cls.lpszMenuName = NULL;
  455. cls.lpszClassName = pszWindowClass;
  456. cls.hbrBackground = GetStockObject( BLACK_BRUSH );
  457. cls.hInstance = hMainInstance;
  458. cls.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS | CS_OWNDC;
  459. cls.lpfnWndProc = RealScreenSaverProc;
  460. cls.cbWndExtra = 0;
  461. cls.cbClsExtra = 0;
  462. if( hParent )
  463. {
  464. RECT rcParent;
  465. GetClientRect( hParent, &rcParent );
  466. ncx = rcParent.right;
  467. ncy = rcParent.bottom;
  468. nx = 0;
  469. ny = 0;
  470. uStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN;
  471. uExStyle = 0;
  472. fChildPreview = TRUE;
  473. pszWindowTitle = TEXT("Preview"); // MUST differ from full screen
  474. }
  475. else
  476. {
  477. HWND hOther;
  478. #ifdef SM_CXVIRTUALSCREEN
  479. nx = GetSystemMetrics( SM_XVIRTUALSCREEN );
  480. ny = GetSystemMetrics( SM_YVIRTUALSCREEN );
  481. ncx = GetSystemMetrics( SM_CXVIRTUALSCREEN );
  482. ncy = GetSystemMetrics( SM_CYVIRTUALSCREEN );
  483. if (ncx == 0 || ncy == 0)
  484. #endif
  485. {
  486. RECT rc;
  487. HDC hdc = GetDC(NULL);
  488. GetClipBox(hdc, &rc);
  489. ReleaseDC(NULL, hdc);
  490. nx = rc.left;
  491. ny = rc.top;
  492. ncx = rc.right - rc.left;
  493. ncy = rc.bottom - rc.top;
  494. }
  495. uStyle = WS_POPUP | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
  496. uExStyle = WS_EX_TOPMOST;
  497. pszWindowTitle = TEXT("Screen Saver"); // MUST differ from preview
  498. // if there is another NORMAL screen save instance, switch to it
  499. hOther = FindWindow( pszWindowClass, pszWindowTitle );
  500. if( hOther && IsWindow( hOther ) )
  501. {
  502. SetForegroundWindow( hOther );
  503. return 0;
  504. }
  505. InitRealScreenSave();
  506. }
  507. //
  508. // the shell sends this message to the foreground window before running an
  509. // AutoPlay app. we return 1 to cancel autoplay if we are password protected
  510. //
  511. if (fOnWin95) {
  512. uShellAutoPlayQueryMessage = RegisterWindowMessage(TEXT("QueryCancelAutoPlay"));
  513. } else {
  514. uShellAutoPlayQueryMessage = 0;
  515. }
  516. if( RegisterClass( &cls ) )
  517. {
  518. hMainWindow = CreateWindowEx( uExStyle, pszWindowClass, pszWindowTitle,
  519. uStyle, nx, ny, ncx, ncy, hParent, (HMENU)NULL,
  520. hMainInstance, (LPVOID)NULL );
  521. }
  522. if( hMainWindow )
  523. {
  524. if( !fChildPreview )
  525. SetForegroundWindow( hMainWindow );
  526. while( GetMessage( &msg, NULL, 0, 0 ) )
  527. {
  528. TranslateMessage( &msg );
  529. DispatchMessage( &msg );
  530. }
  531. }
  532. // free password-handling DLL if loaded
  533. UnloadPwdDLL();
  534. return msg.wParam;
  535. }
  536. #endif
  537. //----------------------------------------------------------------------------
  538. static INT_PTR
  539. DoSaverPreview( LPCTSTR szUINTHandle )
  540. {
  541. // get parent handle from string
  542. HWND hParent = (HWND)atoui( szUINTHandle );
  543. // only preview on a valid parent window (NOT full screen)
  544. return ( (hParent && IsWindow( hParent ))? DoScreenSave( hParent ) : -1 );
  545. }
  546. //----------------------------------------------------------------------------
  547. #ifndef GL_SCRNSAVE
  548. static INT_PTR
  549. DoConfigBox( HWND hParent )
  550. {
  551. // let the consumer register any special controls for the dialog
  552. if( !RegisterDialogClasses( hMainInstance ) )
  553. return FALSE;
  554. return DialogBox( hMainInstance, MAKEINTRESOURCE( DLG_SCRNSAVECONFIGURE ),
  555. hParent, (DLGPROC)ScreenSaverConfigureDialog );
  556. }
  557. #endif
  558. //----------------------------------------------------------------------------
  559. static INT_PTR
  560. DoChangePw( LPCTSTR szUINTHandle )
  561. {
  562. // get parent handle from string
  563. HWND hParent = (HWND)atoui( szUINTHandle );
  564. if( !hParent || !IsWindow( hParent ) )
  565. hParent = GetForegroundWindow();
  566. // allow the library to be hooked
  567. ScreenSaverChangePassword( hParent );
  568. return 0;
  569. }
  570. static const TCHAR szMprDll[] = TEXT("MPR.DLL"); // not to be localized
  571. static const TCHAR szProviderName[] = TEXT("SCRSAVE"); // not to be localized
  572. #ifdef UNICODE
  573. static const CHAR szPwdChangePW[] = "PwdChangePasswordW"; // not to be localized
  574. #else
  575. static const CHAR szPwdChangePW[] = "PwdChangePasswordA"; // not to be localized
  576. #endif
  577. // bogus prototype
  578. typedef DWORD (FAR PASCAL *PWCHGPROC)( LPCTSTR, HWND, DWORD, LPVOID );
  579. void WINAPI
  580. ScreenSaverChangePassword( HWND hParent )
  581. {
  582. HINSTANCE mpr = LoadLibrary( szMprDll );
  583. if( mpr )
  584. {
  585. // netland hasn't cracked MNRENTRY yet
  586. PWCHGPROC pwd = (PWCHGPROC)GetProcAddress( mpr, szPwdChangePW );
  587. if( pwd )
  588. pwd( szProviderName, hParent, 0, NULL );
  589. FreeLibrary( mpr );
  590. }
  591. }
  592. //----------------------------------------------------------------------------
  593. static BOOL
  594. DoPasswordCheck( HWND hParent )
  595. {
  596. // don't reenter and don't check when we've already decided
  597. if( fCheckingPassword || fClosing )
  598. return FALSE;
  599. if( VerifyPassword )
  600. {
  601. static DWORD lastcheck = (DWORD)-1;
  602. DWORD curtime = GetTickCount();
  603. MSG msg;
  604. if (dwPasswordDelay &&
  605. (GetElapsedTime(dwBlankTime, curtime) < dwPasswordDelay))
  606. {
  607. fClosing = TRUE;
  608. goto _didcheck;
  609. }
  610. // no rapid checking...
  611. if ((lastcheck != (DWORD)-1) &&
  612. (GetElapsedTime(lastcheck, curtime) < 200))
  613. {
  614. goto _didcheck;
  615. }
  616. // do the check
  617. fCheckingPassword = TRUE;
  618. #ifdef GL_SCRNSAVE
  619. // Put ss in idle mode during password dialog processing
  620. SendMessage( hParent, SS_WM_IDLE, SS_IDLE_ON, 0L );
  621. #endif
  622. // flush WM_TIMER messages before putting up the dialog
  623. PeekMessage( &msg, hParent, WM_TIMER, WM_TIMER, PM_REMOVE | PM_NOYIELD );
  624. PeekMessage( &msg, hParent, WM_TIMER, WM_TIMER, PM_REMOVE | PM_NOYIELD );
  625. // call the password verify proc
  626. fClosing = (BOOL)SendMessage( hParent, SCRM_VERIFYPW, 0, 0L );
  627. fCheckingPassword = FALSE;
  628. #ifdef GL_SCRNSAVE
  629. // Restore normal display mode
  630. SendMessage( hParent, SS_WM_IDLE, SS_IDLE_OFF, 0L );
  631. #endif
  632. if (!fClosing)
  633. SetCursor(NULL);
  634. // curtime may be outdated by now
  635. lastcheck = GetTickCount();
  636. }
  637. else
  638. {
  639. // passwords disabled or unable to load handler DLL, always allow exit
  640. fClosing = TRUE;
  641. }
  642. _didcheck:
  643. return fClosing;
  644. }
  645. //----------------------------------------------------------------------------
  646. // stolen from the CRT, used to shirink our code
  647. int _stdcall
  648. DummyEntry( void )
  649. {
  650. int i;
  651. STARTUPINFO si;
  652. LPTSTR pszCmdLine = GetCommandLine();
  653. if ( *pszCmdLine == TEXT('\"')) {
  654. /*
  655. * Scan, and skip over, subsequent characters until
  656. * another double-quote or a null is encountered.
  657. */
  658. while (*(pszCmdLine = CharNext(pszCmdLine)) &&
  659. (*pszCmdLine != TEXT('\"')) );
  660. /*
  661. * If we stopped on a double-quote (usual case), skip
  662. * over it.
  663. */
  664. if ( *pszCmdLine == TEXT('\"') )
  665. pszCmdLine++;
  666. }
  667. else {
  668. while ((UINT)*pszCmdLine > (UINT)TEXT(' '))
  669. pszCmdLine = CharNext(pszCmdLine);
  670. }
  671. /*
  672. * Skip past any white space preceeding the second token.
  673. */
  674. while (*pszCmdLine && ((UINT)*pszCmdLine <= (UINT)TEXT(' '))) {
  675. pszCmdLine = CharNext(pszCmdLine);
  676. }
  677. si.dwFlags = 0;
  678. GetStartupInfo(&si);
  679. i = (int)WinMainN(GetModuleHandle(NULL), NULL, pszCmdLine,
  680. si.dwFlags & STARTF_USESHOWWINDOW ? si.wShowWindow : SW_SHOWDEFAULT);
  681. ExitProcess(i);
  682. return i; // We never comes here.
  683. }
  684. //----------------------------------------------------------------------------
  685. // main() entry point to satisfy old NT screen savers
  686. void _cdecl main( int argc, char *argv[] ) {
  687. DummyEntry();
  688. }
  689. //----------------------------------------------------------------------------
  690. // WinMain() entry point to satisfy old NT screen savers
  691. int PASCAL WinMain( HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow ) {
  692. DummyEntry();
  693. return 0;
  694. // reference unreferenced parameters
  695. (void)hInst;
  696. (void)hPrev;
  697. (void)szCmdLine;
  698. (void)nCmdShow;
  699. }
  700. VOID LoadPwdDLL(VOID)
  701. {
  702. HKEY hKey;
  703. if (!fOnWin95)
  704. return;
  705. if (hInstPwdDLL)
  706. UnloadPwdDLL();
  707. // look in registry to see if password turned on, otherwise don't
  708. // bother to load password handler DLL
  709. if (RegOpenKey(HKEY_CURRENT_USER,szScreenSaverKey,&hKey) ==
  710. ERROR_SUCCESS)
  711. {
  712. DWORD dwVal,dwSize=sizeof(dwVal);
  713. if ((RegQueryValueEx(hKey,szPasswordActiveValue,
  714. NULL,NULL,(BYTE *) &dwVal,&dwSize) == ERROR_SUCCESS)
  715. && dwVal)
  716. {
  717. // try to load the DLL that contains password proc.
  718. hInstPwdDLL = LoadLibrary(szPwdDLL);
  719. if (hInstPwdDLL)
  720. {
  721. VerifyPassword = (VERIFYPWDPROC) GetProcAddress(hInstPwdDLL,
  722. szFnName);
  723. if( VerifyPassword )
  724. HogMachine( TRUE );
  725. else
  726. UnloadPwdDLL();
  727. }
  728. }
  729. RegCloseKey(hKey);
  730. }
  731. }
  732. VOID UnloadPwdDLL(VOID)
  733. {
  734. if (!fOnWin95)
  735. return;
  736. if (hInstPwdDLL)
  737. {
  738. FreeLibrary(hInstPwdDLL);
  739. hInstPwdDLL = NULL;
  740. if( VerifyPassword )
  741. {
  742. VerifyPassword = NULL;
  743. HogMachine( FALSE );
  744. }
  745. }
  746. }
  747. //----------------------------------------------------------------------------
  748. // compatbility stuff (to make porting easier)
  749. TCHAR szAppName[ APPNAMEBUFFERLEN ];
  750. TCHAR szName[ TITLEBARNAMELEN ];
  751. TCHAR szIniFile[ MAXFILELEN ];
  752. TCHAR szScreenSaver[ 22 ];
  753. TCHAR szHelpFile[ MAXFILELEN ];
  754. TCHAR szNoHelpMemory[ BUFFLEN ];
  755. // Quick fix for old screen savers that don't know about context
  756. // sensitive help
  757. UINT MyHelpMessage = WM_HELP;