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.

830 lines
20 KiB

  1. //****************************************************************************
  2. // File: CCONF.CPP
  3. // Content:
  4. //
  5. //
  6. // Copyright (c) Microsoft Corporation 1997
  7. //
  8. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  9. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  10. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  11. // PARTICULAR PURPOSE.
  12. //****************************************************************************
  13. #include <precomp.h>
  14. #include "srvccall.h"
  15. #include "cstring.hpp"
  16. #define ZERO_DELAY "0"
  17. const int SERVICE_IN_CALL = 1001;
  18. const int SERVICE_NOT_IN_CALL = 1000;
  19. // Global Variables
  20. INmManager * g_pMgr = NULL; // The Conference Manager
  21. CMgrNotify * g_pMgrNotify = NULL; // Notifications for the Manager
  22. INmConference * g_pConference = NULL; // The Current Conference
  23. CConfNotify * g_pConferenceNotify =NULL; // Notifications for the Conference
  24. IAppSharing * g_pAS = NULL; // Interface to AppSharing
  25. int g_cPersonsInConf = 0;
  26. int g_cPersonsInShare = 0;
  27. extern BOOL g_fInShutdown;
  28. CHAR szConfName[64];
  29. static BOOL RunScrSaver(void);
  30. /* I N I T C O N F M G R */
  31. /*-------------------------------------------------------------------------
  32. %%Function: InitConfMgr
  33. -------------------------------------------------------------------------*/
  34. HRESULT InitConfMgr(void)
  35. {
  36. HRESULT hr;
  37. TRACE_OUT(("InitConfMgr"));
  38. ASSERT(!g_pMgr);
  39. hr = CreateNmManager(&g_pMgr);
  40. if (SUCCEEDED(hr))
  41. {
  42. // Connect to the conference manager object
  43. g_pMgrNotify = new CMgrNotify();
  44. if (NULL != g_pMgrNotify)
  45. {
  46. hr = g_pMgrNotify->Connect(g_pMgr);
  47. //
  48. // Now initialize, with the user name, credentials, and
  49. // port.
  50. //
  51. if (SUCCEEDED(hr))
  52. {
  53. HCERTSTORE hStore;
  54. PCCERT_CONTEXT pCertContext = NULL;
  55. DWORD dwResult = -1;
  56. TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH+1];
  57. DWORD dwComputerNameLength = sizeof(szComputerName) / sizeof(szComputerName[0]);
  58. // Open the "MY" local machine certificate store. This one will be
  59. // used when we're running as a service
  60. hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM,
  61. X509_ASN_ENCODING,
  62. 0,
  63. CERT_SYSTEM_STORE_LOCAL_MACHINE,
  64. L"MY" );
  65. if ( NULL != hStore )
  66. {
  67. #ifdef DUMPCERTS
  68. DumpCertStore(this, "Local Machine Store MY", hStore);
  69. #endif // DUMPCERTS
  70. // Check the local machine store for a certificate - any!
  71. pCertContext = CertFindCertificateInStore(hStore,
  72. X509_ASN_ENCODING,
  73. 0,
  74. CERT_FIND_ANY,
  75. NULL,
  76. NULL);
  77. CertCloseStore( hStore, 0);
  78. }
  79. if ( NULL == pCertContext )
  80. {
  81. // Open the RDS local machine certificate store.
  82. hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM,
  83. X509_ASN_ENCODING,
  84. 0,
  85. CERT_SYSTEM_STORE_LOCAL_MACHINE,
  86. WSZNMSTORE );
  87. if ( NULL != hStore )
  88. {
  89. #ifdef DUMPCERTS
  90. DumpCertStore(this, "Local Machine Store _RDSTR", hStore);
  91. #endif // DUMPCERTS
  92. // Check the local machine store for a certificate - any!
  93. pCertContext = CertFindCertificateInStore(hStore,
  94. X509_ASN_ENCODING,
  95. 0,
  96. CERT_FIND_ANY,
  97. NULL,
  98. NULL);
  99. CertCloseStore( hStore, 0);
  100. }
  101. }
  102. if ( NULL == pCertContext )
  103. {
  104. ERROR_OUT(("No service context cert found!"));
  105. }
  106. if ( !GetComputerName( szComputerName, &dwComputerNameLength))
  107. {
  108. lstrcpy(szComputerName,TEXT("?"));
  109. ERROR_OUT(("GetComputerName failed"));
  110. }
  111. //
  112. // Do the intialization
  113. //
  114. hr = g_pMgr->Initialize(BSTRING(szComputerName),
  115. (DWORD_PTR)pCertContext,
  116. DEFAULT_LISTEN_PORT,
  117. NMMANAGER_SERVICE | NMMANAGER_SERVER);
  118. if (pCertContext)
  119. {
  120. CertFreeCertificateContext ( pCertContext );
  121. }
  122. if (FAILED(hr))
  123. {
  124. ERROR_OUT(("g_pMgr->Initialize failed"));
  125. }
  126. }
  127. else
  128. ERROR_OUT(("g_pMgrNotify->Connect failed"));
  129. }
  130. else
  131. ERROR_OUT(("new CMgrNotify failed"));
  132. }
  133. if (!g_pMgr)
  134. {
  135. ERROR_OUT(("Failed to init conference manager"));
  136. return hr;
  137. }
  138. //
  139. // Init app sharing
  140. //
  141. hr = ::CreateASObject(g_pMgrNotify, AS_SERVICE | AS_UNATTENDED, &g_pAS);
  142. if (FAILED(hr))
  143. {
  144. ERROR_OUT(("Failed to start AppSharing"));
  145. return(hr);
  146. }
  147. //
  148. // Make sure that sharing is enabled
  149. //
  150. if ( !g_pAS->IsSharingAvailable() )
  151. {
  152. WARNING_OUT(("MNMSRVC: sharing not enabled"));
  153. return E_FAIL;
  154. }
  155. // Create conference
  156. ASSERT(g_pConference == NULL);
  157. //
  158. // Only allow remotes to send files, they can't initiate anything else
  159. // themselves.
  160. LoadString(GetModuleHandle(NULL), IDS_MNMSRVC_TITLE,
  161. szConfName, CCHMAX(szConfName));
  162. BSTRING bstrConfName(szConfName);
  163. hr = g_pMgr->CreateConference(&g_pConference, bstrConfName, NULL, TRUE);
  164. if (FAILED(hr))
  165. {
  166. ERROR_OUT(("Conference could not be created"));
  167. return hr;
  168. }
  169. hr = g_pConference->Host();
  170. if (FAILED(hr))
  171. {
  172. ERROR_OUT(("Could not host conference"));
  173. return hr;
  174. }
  175. return hr;
  176. }
  177. /* F R E E C O N F M G R */
  178. /*-------------------------------------------------------------------------
  179. %%Function: FreeConfMgr
  180. -------------------------------------------------------------------------*/
  181. VOID FreeConfMgr(void)
  182. {
  183. DebugEntry(FreeConfMgr);
  184. // Release conference manager notify
  185. if (NULL != g_pMgrNotify)
  186. {
  187. g_pMgrNotify->Disconnect();
  188. UINT ref = g_pMgrNotify->Release();
  189. TRACE_OUT(("g_pMgrNotify after Release: refcount: %d", ref));
  190. g_pMgrNotify = NULL;
  191. }
  192. // Release conference manager
  193. if (NULL != g_pMgr)
  194. {
  195. UINT ref;
  196. ref = g_pMgr->Release();
  197. TRACE_OUT(("g_pMgr after Release: refcount: %d", ref));
  198. g_pMgr = NULL;
  199. }
  200. DebugExitVOID(FreeConfMgr);
  201. }
  202. /* F R E E C O N F E R E N C E */
  203. /*-------------------------------------------------------------------------
  204. %%Function: FreeConference
  205. -------------------------------------------------------------------------*/
  206. VOID FreeConference(void)
  207. {
  208. DebugEntry(FreeConference);
  209. if (g_pConference)
  210. {
  211. g_pConference->Leave();
  212. }
  213. if (NULL != g_pConferenceNotify)
  214. {
  215. g_pConferenceNotify->Disconnect();
  216. g_pConferenceNotify->Release();
  217. g_pConferenceNotify = NULL;
  218. }
  219. if (NULL != g_pConference)
  220. {
  221. UINT ref = g_pConference->Release();
  222. ASSERT(1 == ref); // The confmgr holds last reference
  223. g_pConference = NULL;
  224. }
  225. else
  226. {
  227. WARNING_OUT(("FreeConference: no conference???"));
  228. }
  229. DebugExitVOID(FreeConference);
  230. }
  231. //////////////////////////////////////////////////////////////////////////
  232. // C C N F M G R N O T I F Y
  233. CMgrNotify::CMgrNotify() : RefCount(), CNotify()
  234. {
  235. TRACE_OUT(("CMgrNotify created"));
  236. }
  237. CMgrNotify::~CMgrNotify()
  238. {
  239. TRACE_OUT(("CMgrNotify destroyed"));
  240. }
  241. ///////////////////////////
  242. // CMgrNotify:IUnknown
  243. ULONG STDMETHODCALLTYPE CMgrNotify::AddRef(void)
  244. {
  245. return RefCount::AddRef();
  246. }
  247. ULONG STDMETHODCALLTYPE CMgrNotify::Release(void)
  248. {
  249. return RefCount::Release();
  250. }
  251. HRESULT STDMETHODCALLTYPE CMgrNotify::QueryInterface(REFIID riid, PVOID *ppvObject)
  252. {
  253. HRESULT hr = S_OK;
  254. TRACE_OUT(("CMgrNotify QI'd"));
  255. if (riid == IID_IUnknown || riid == IID_INmManagerNotify)
  256. {
  257. *ppvObject = (INmManagerNotify *)this;
  258. }
  259. else
  260. {
  261. hr = E_NOINTERFACE;
  262. *ppvObject = NULL;
  263. }
  264. if (S_OK == hr)
  265. {
  266. AddRef();
  267. }
  268. return hr;
  269. }
  270. ////////////////////////////
  271. // CMgrNotify:ICNotify
  272. HRESULT STDMETHODCALLTYPE CMgrNotify::Connect(IUnknown *pUnk)
  273. {
  274. TRACE_OUT(("CMgrNotify::Connect"));
  275. return CNotify::Connect(pUnk, IID_INmManagerNotify, (INmManagerNotify *)this);
  276. }
  277. HRESULT STDMETHODCALLTYPE CMgrNotify::Disconnect(void)
  278. {
  279. TRACE_OUT(("CMgrNotify::Disconnect"));
  280. return CNotify::Disconnect();
  281. }
  282. //////////////////////////////////
  283. // CMgrNotify:INmManagerNotify
  284. HRESULT STDMETHODCALLTYPE CMgrNotify::NmUI(CONFN confn)
  285. {
  286. TRACE_OUT(("CMgrNotify::NmUI"));
  287. return S_OK;
  288. }
  289. HRESULT STDMETHODCALLTYPE CMgrNotify::CallCreated(INmCall *pNmCall)
  290. {
  291. new CSrvcCall(pNmCall);
  292. TRACE_OUT(("CMgrNotify::CallCreated"));
  293. return S_OK;
  294. }
  295. HRESULT STDMETHODCALLTYPE CMgrNotify::ConferenceCreated(INmConference *pConference)
  296. {
  297. g_cPersonsInConf = 0;
  298. g_cPersonsInShare = 0;
  299. if (NULL == g_pConference)
  300. {
  301. TRACE_OUT(("CMgrNotify::ConferenceCreated"));
  302. HookConference(pConference);
  303. }
  304. else
  305. {
  306. ERROR_OUT(("Second conference created???"));
  307. }
  308. return S_OK;
  309. }
  310. // CMgrNotify::IAppSharingNotify
  311. HRESULT STDMETHODCALLTYPE CMgrNotify::OnReadyToShare(BOOL fReady)
  312. {
  313. TRACE_OUT(("CMgrNotify::OnReadyToShare"));
  314. return S_OK;
  315. }
  316. HRESULT STDMETHODCALLTYPE CMgrNotify::OnShareStarted()
  317. {
  318. TRACE_OUT(("CMgrNotify::OnShareStarted"));
  319. return S_OK;
  320. }
  321. HRESULT STDMETHODCALLTYPE CMgrNotify::OnSharingStarted()
  322. {
  323. TRACE_OUT(("CMgrNotify::OnSharingStarted"));
  324. return S_OK;
  325. }
  326. HRESULT STDMETHODCALLTYPE CMgrNotify::OnShareEnded()
  327. {
  328. TRACE_OUT(("CMgrNotify::OnShareEnded"));
  329. return S_OK;
  330. }
  331. HRESULT STDMETHODCALLTYPE CMgrNotify::OnPersonJoined(IAS_GCC_ID gccID)
  332. {
  333. TRACE_OUT(("CMgrNotify::OnPersonJoined"));
  334. ASSERT(g_pAS);
  335. ASSERT(g_cPersonsInShare >= 0);
  336. g_cPersonsInShare++;
  337. //
  338. // Once we are no longer alone in the share, invite the remote party to
  339. // take control of us.
  340. //
  341. if ( 2 == g_cPersonsInShare && g_pAS)
  342. {
  343. HRESULT hr;
  344. TRACE_OUT(("OnPersonJoined: giving control to 2nd dude %d",
  345. gccID));
  346. //
  347. // Give control to the remote party
  348. //
  349. hr = g_pAS->GiveControl(gccID);
  350. if ( S_OK != hr )
  351. {
  352. ERROR_OUT(("OnPersonJoined: GiveControl to %d failed: %x",
  353. gccID, hr));
  354. }
  355. }
  356. return S_OK;
  357. }
  358. HRESULT STDMETHODCALLTYPE CMgrNotify::OnPersonLeft(IAS_GCC_ID gccID)
  359. {
  360. TRACE_OUT(("CMgrNotify::OnPersonLeft"));
  361. ASSERT(g_pAS);
  362. g_cPersonsInShare--;
  363. ASSERT(g_cPersonsInShare >= 0);
  364. return S_OK;
  365. }
  366. HRESULT STDMETHODCALLTYPE CMgrNotify::OnStartInControl(IAS_GCC_ID gccID)
  367. {
  368. TRACE_OUT(("CMgrNotify::OnStartInControl"));
  369. return S_OK;
  370. }
  371. HRESULT STDMETHODCALLTYPE CMgrNotify::OnStopInControl(IAS_GCC_ID gccID)
  372. {
  373. TRACE_OUT(("CMgrNotify::OnStopInControl"));
  374. return S_OK;
  375. }
  376. HRESULT STDMETHODCALLTYPE CMgrNotify::OnControllable(BOOL fControllable)
  377. {
  378. TRACE_OUT(("CMgrNotify::OnControllable"));
  379. return S_OK;
  380. }
  381. HRESULT STDMETHODCALLTYPE CMgrNotify::OnStartControlled(IAS_GCC_ID gccID)
  382. {
  383. TRACE_OUT(("CMgrNotify::OnStartControlled"));
  384. return S_OK;
  385. }
  386. HRESULT STDMETHODCALLTYPE CMgrNotify::OnStopControlled(IAS_GCC_ID gccID)
  387. {
  388. TRACE_OUT(("CMgrNotify::OnStopControlled"));
  389. ::RunScrSaver();
  390. return S_OK;
  391. }
  392. /* H O O K C O N F E R E N C E */
  393. /*-------------------------------------------------------------------------
  394. %%Function: HookConference
  395. -------------------------------------------------------------------------*/
  396. HRESULT HookConference(INmConference * pConference)
  397. {
  398. HRESULT hr;
  399. DebugEntry(HookConference);
  400. TRACE_OUT(("HookConference"));
  401. ASSERT(NULL != pConference);
  402. ASSERT(NULL == g_pConference);
  403. TRACE_OUT(("Set g_pConference in HookConference"));
  404. g_pConference = pConference;
  405. pConference->AddRef();
  406. // Connect to the conference object
  407. ASSERT(NULL == g_pConferenceNotify);
  408. g_pConferenceNotify = new CConfNotify();
  409. if (NULL == g_pConferenceNotify)
  410. {
  411. ERROR_OUT(("failed to new CConfNotify"));
  412. hr = E_OUTOFMEMORY;
  413. }
  414. else
  415. {
  416. hr = g_pConferenceNotify->Connect(pConference);
  417. if (FAILED(hr))
  418. {
  419. ERROR_OUT(("Failed to connect to g_pConferenceNotify"));
  420. g_pConferenceNotify->Release();
  421. g_pConferenceNotify = NULL;
  422. }
  423. }
  424. DebugExitHRESULT(HookConference,hr);
  425. return hr;
  426. }
  427. //////////////////////////////////////////////////////////////////////////
  428. // C C N F N O T I F Y
  429. CConfNotify::CConfNotify() : RefCount(), CNotify()
  430. {
  431. TRACE_OUT(("CConfNotify created"));
  432. }
  433. CConfNotify::~CConfNotify()
  434. {
  435. TRACE_OUT(("CConfNotify destroyed"));
  436. }
  437. ///////////////////////////
  438. // CConfNotify:IUknown
  439. ULONG STDMETHODCALLTYPE CConfNotify::AddRef(void)
  440. {
  441. TRACE_OUT(("CConfNotify::AddRef"));
  442. return RefCount::AddRef();
  443. }
  444. ULONG STDMETHODCALLTYPE CConfNotify::Release(void)
  445. {
  446. TRACE_OUT(("CConfNotify::Release"));
  447. return RefCount::Release();
  448. }
  449. HRESULT STDMETHODCALLTYPE CConfNotify::QueryInterface(REFIID riid, PVOID *ppvObject)
  450. {
  451. HRESULT hr = S_OK;
  452. TRACE_OUT(("CConfNotify::QueryInterface"));
  453. if (riid == IID_IUnknown)
  454. {
  455. TRACE_OUT(("CConfNotify::QueryInterface IID_IUnknown"));
  456. *ppvObject = (IUnknown *)this;
  457. }
  458. else if (riid == IID_INmConferenceNotify)
  459. {
  460. TRACE_OUT(("CConfNotify::QueryInterface IID_INmConferenceNotify"));
  461. *ppvObject = (INmConferenceNotify *)this;
  462. }
  463. else
  464. {
  465. WARNING_OUT(("CConfNotify::QueryInterface bogus"));
  466. hr = E_NOINTERFACE;
  467. *ppvObject = NULL;
  468. }
  469. if (S_OK == hr)
  470. {
  471. AddRef();
  472. }
  473. return hr;
  474. }
  475. ////////////////////////////
  476. // CConfNotify:ICNotify
  477. HRESULT STDMETHODCALLTYPE CConfNotify::Connect(IUnknown *pUnk)
  478. {
  479. TRACE_OUT(("CConfNotify::Connect"));
  480. return CNotify::Connect(pUnk,IID_INmConferenceNotify,(IUnknown *)this);
  481. }
  482. HRESULT STDMETHODCALLTYPE CConfNotify::Disconnect(void)
  483. {
  484. TRACE_OUT(("CConfNotify::Disconnect"));
  485. //
  486. // Release for Addref in HookConference before CConfNotify::Connect
  487. //
  488. if ( g_pConference )
  489. g_pConference->Release();
  490. return CNotify::Disconnect();
  491. }
  492. //////////////////////////////////
  493. // CConfNotify:IConfNotify
  494. HRESULT STDMETHODCALLTYPE CConfNotify::NmUI(CONFN uNotify)
  495. {
  496. TRACE_OUT(("CConfNotify::NmUI"));
  497. TRACE_OUT(("NmUI called."));
  498. return S_OK;
  499. }
  500. HRESULT STDMETHODCALLTYPE CConfNotify::StateChanged(NM_CONFERENCE_STATE uState)
  501. {
  502. TRACE_OUT(("CConfNotify::StateChanged"));
  503. if (NULL == g_pConference)
  504. return S_OK; // weird
  505. switch (uState)
  506. {
  507. case NM_CONFERENCE_ACTIVE:
  508. if (IS_NT) {
  509. g_ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SHUTDOWN;
  510. SetServiceStatus(g_sshStatusHandle,&g_ssStatus);
  511. }
  512. break;
  513. case NM_CONFERENCE_INITIALIZING:
  514. break; // can't do anything just yet
  515. case NM_CONFERENCE_WAITING:
  516. if (IS_NT) {
  517. g_ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
  518. SetServiceStatus(g_sshStatusHandle,&g_ssStatus);
  519. }
  520. break;
  521. case NM_CONFERENCE_IDLE:
  522. break;
  523. }
  524. return S_OK;
  525. }
  526. HRESULT STDMETHODCALLTYPE CConfNotify::MemberChanged(NM_MEMBER_NOTIFY uNotify, INmMember *pMember)
  527. {
  528. switch (uNotify)
  529. {
  530. case NM_MEMBER_ADDED:
  531. {
  532. TRACE_OUT(("CConfNotify::MemberChanged() Member added"));
  533. ASSERT( g_cPersonsInConf >= 0 );
  534. g_cPersonsInConf++;
  535. //
  536. // Once we are no longer alone in the conference, share the desktop
  537. // and allow control:
  538. //
  539. if ( 2 == g_cPersonsInConf && g_pAS )
  540. {
  541. HRESULT hr;
  542. TRACE_OUT(("%d parties in conf, Sharing the desktop",
  543. g_cPersonsInConf));
  544. //
  545. // Share out the desktop
  546. //
  547. hr = g_pAS->ShareDesktop();
  548. if ( S_OK != hr )
  549. {
  550. ERROR_OUT(("OnPersonJoined: sharing desktop failed: %x",hr));
  551. }
  552. //
  553. // Allow control
  554. //
  555. hr = g_pAS->AllowControl ( TRUE );
  556. if ( S_OK != hr )
  557. {
  558. ERROR_OUT(("OnPersonJoined: allowing control failed: %x",hr));
  559. }
  560. }
  561. break;
  562. }
  563. case NM_MEMBER_REMOVED:
  564. {
  565. TRACE_OUT(("CConfNotify::MemberChanged() Member removed"));
  566. g_cPersonsInConf--;
  567. ASSERT( g_cPersonsInConf >= 0 );
  568. if ( 1 == g_cPersonsInConf && g_pAS )
  569. {
  570. HRESULT hr;
  571. TRACE_OUT(("%d parties in conf, Unsharing the desktop",
  572. g_cPersonsInConf));
  573. //
  574. // Disallow control
  575. //
  576. hr = g_pAS->AllowControl ( FALSE );
  577. if ( S_OK != hr )
  578. {
  579. ERROR_OUT(("Disallowing control failed: %x",hr));
  580. }
  581. //
  582. // Unshare the desktop
  583. //
  584. hr = g_pAS->UnshareDesktop();
  585. if ( S_OK != hr )
  586. {
  587. ERROR_OUT(("Unsharing desktop failed: %x",hr));
  588. }
  589. }
  590. break;
  591. }
  592. case NM_MEMBER_UPDATED:
  593. {
  594. TRACE_OUT(("CConfNotify::MemberChanged() Member updated"));
  595. break;
  596. }
  597. default:
  598. break;
  599. }
  600. return S_OK;
  601. }
  602. BOOL ServiceCtrlHandler(DWORD dwCtrlType)
  603. {
  604. HRESULT hr = S_OK;
  605. TRACE_OUT(("ServiceCtrlHandler received %d",dwCtrlType));
  606. switch (dwCtrlType)
  607. {
  608. case CTRL_SHUTDOWN_EVENT:
  609. if (g_pConference != NULL)
  610. {
  611. TRACE_OUT(("Leaving conference in CTRL_SHUTDOWN_EVENT"));
  612. hr = g_pConference->Leave();
  613. if (FAILED(hr))
  614. {
  615. WARNING_OUT(("Service Ctrl Handler failed to leave"));
  616. }
  617. }
  618. else
  619. {
  620. WARNING_OUT(("g_pConference NULL in CTRL_SHUTDOWN_EVENT"));
  621. }
  622. break;
  623. default:
  624. break;
  625. }
  626. return FALSE;
  627. }
  628. static BOOL RunScrSaver(void)
  629. {
  630. BOOL fIsScrSaverActive = FALSE;
  631. if (g_fInShutdown)
  632. {
  633. return FALSE;
  634. }
  635. if (!SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, &fIsScrSaverActive, 0))
  636. {
  637. ERROR_OUT(("RunScrSaver: SystemParametersInfo failed"));
  638. return FALSE;
  639. }
  640. if (fIsScrSaverActive)
  641. {
  642. RegEntry reWinlogon(IS_NT ? WINNT_WINLOGON_KEY : WIN95_WINLOGON_KEY, HKEY_LOCAL_MACHINE);
  643. CSTRING strGracePeriod = reWinlogon.GetString(REGVAL_SCREENSAVER_GRACEPERIOD);
  644. reWinlogon.SetValue(REGVAL_SCREENSAVER_GRACEPERIOD, ZERO_DELAY);
  645. reWinlogon.FlushKey();
  646. DefWindowProc(GetDesktopWindow(), WM_SYSCOMMAND, SC_SCREENSAVE, 0);
  647. if (lstrlen(strGracePeriod))
  648. {
  649. int cSeconds = RtStrToInt(strGracePeriod);
  650. if (cSeconds > 0 && cSeconds <= 20)
  651. {
  652. Sleep(1000*cSeconds);
  653. reWinlogon.SetValue(REGVAL_SCREENSAVER_GRACEPERIOD, strGracePeriod);
  654. reWinlogon.FlushKey();
  655. return TRUE;
  656. }
  657. }
  658. Sleep(5000);
  659. reWinlogon.DeleteValue(REGVAL_SCREENSAVER_GRACEPERIOD);
  660. reWinlogon.FlushKey();
  661. return TRUE;
  662. }
  663. else {
  664. return FALSE;
  665. }
  666. }