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.

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