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.

1198 lines
28 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1997 - 1999
  3. Module Name:
  4. senssvc.cxx
  5. Abstract:
  6. This file implements the Init/Uninit functionality of System Event
  7. Notification service (SENS).
  8. Author:
  9. Gopal Parupudi <GopalP>
  10. [Notes:]
  11. optional-notes
  12. Revision History:
  13. GopalP 09-20-1997 Start.
  14. --*/
  15. #include <precomp.hxx>
  16. #define MIN_CALL_THREADS 1
  17. #define SENS_CLEANUP_TIMEOUT 15*1000 // Max wait
  18. #define SENS_WAITFORINIT_TIMEOUT 30*1000 // 30 seconds max
  19. //
  20. // Globals
  21. //
  22. IEventSystem *gpIEventSystem;
  23. HANDLE ghSensHeap;
  24. HANDLE ghSensStartedEvent;
  25. CRITICAL_SECTION gSensLock;
  26. DWORD gdwRegCO;
  27. DWORD gdwLocked;
  28. LPCLASSFACTORY gpChangeCF;
  29. #ifdef DBG
  30. DWORD gdwDebugOutputLevel;
  31. #endif // DBG
  32. //
  33. // External Globals
  34. //
  35. // Common
  36. extern LONG g_cFilterObj;
  37. extern LONG g_cFilterLock;
  38. extern LONG g_cSubChangeObj;
  39. extern LONG g_cSubChangeLock;
  40. extern LIST *gpReachList;
  41. extern BOOL gbIpInitSuccessful;
  42. extern BOOL gbIsRasInstalled;
  43. extern long gdwLastLANTime;
  44. extern long gdwLANState;
  45. extern HANDLE ghReachTimer;
  46. extern HANDLE ghMediaTimer;
  47. extern long gdwLastWANTime;
  48. extern long gdwWANState;
  49. extern IF_STATE gIfState[MAX_IF_ENTRIES];
  50. extern MIB_IPSTATS gIpStats;
  51. extern SYSTEM_POWER_STATUS gSystemPowerState;
  52. BOOL
  53. SensInitialize(
  54. void
  55. )
  56. /*++
  57. Routine Description:
  58. Main entry into SENS.
  59. Arguments:
  60. None.
  61. Return Value:
  62. TRUE, if successful.
  63. FALSE, otherwise
  64. --*/
  65. {
  66. BOOL bRetValue;
  67. BOOL bComInitialized;
  68. bRetValue = FALSE;
  69. bComInitialized = FALSE;
  70. #ifdef DBG
  71. DWORD dwNow = GetTickCount();
  72. EnableDebugOutputIfNecessary();
  73. #endif // DBG
  74. SensPrintA(SENS_INFO, ("[%d] Initializing SENS...\n", dwNow));
  75. // This will Initialize COM on success.
  76. if (FALSE == Init())
  77. {
  78. SensPrintA(SENS_ERR, ("[%d] Init() failed.\n",
  79. GetTickCount()));
  80. bRetValue = FALSE;
  81. goto Cleanup;
  82. }
  83. bComInitialized = TRUE;
  84. //
  85. // This will call CoRegisterClassObject and will help in service
  86. // startup. So, call this before ConfigureSensIfNecessary()
  87. //
  88. if (FALSE == DoEventSystemSetup())
  89. {
  90. SensPrintA(SENS_ERR, ("[%d] DoEventSystemSetup() failed.\n", GetTickCount()));
  91. }
  92. else
  93. {
  94. SensPrintA(SENS_INFO, ("[%d] DoEventSystemSetup() Succeeded.\n", GetTickCount()));
  95. }
  96. if (FALSE == ConfigureSensIfNecessary())
  97. {
  98. SensPrintA(SENS_ERR, ("[%d] ConfigureSensIfNecessary() failed.\n", GetTickCount()));
  99. }
  100. else
  101. {
  102. SensPrintA(SENS_INFO, ("[%d] ConfigureSensIfNecessary() Succeeded.\n", GetTickCount()));
  103. }
  104. if (FALSE == DoWanSetup())
  105. {
  106. SensPrintA(SENS_ERR, ("[%d] DoWanSetup() failed.\n", GetTickCount()));
  107. }
  108. else
  109. {
  110. SensPrintA(SENS_INFO, ("[%d] DoWanSetup() Succeeded.\n", GetTickCount()));
  111. }
  112. if (FALSE == DoLanSetup())
  113. {
  114. SensPrintA(SENS_ERR, ("[%d] DoLanSetup() failed.\n", GetTickCount()));
  115. bRetValue = FALSE;
  116. goto Cleanup;
  117. }
  118. SensPrintA(SENS_INFO, ("[%d] DoLanSetup() Succeeded.\n", GetTickCount()));
  119. if (FALSE == DoRpcSetup())
  120. {
  121. SensPrintA(SENS_ERR, ("[%d] DoRpcSetup() failed.\n", GetTickCount()));
  122. bRetValue = FALSE;
  123. goto Cleanup;
  124. }
  125. SensPrintA(SENS_INFO, ("[%d] DoRpcSetup() Succeeded.\n", GetTickCount()));
  126. bRetValue = TRUE;
  127. SensPrintA(SENS_DBG, ("[%d] Service start took %d msec.\n", GetTickCount(), (GetTickCount() - dwNow)));
  128. Cleanup:
  129. //
  130. // Cleanup
  131. //
  132. if (bComInitialized)
  133. {
  134. //
  135. // This thread (service start) will exit shortly after we return. Our event system
  136. // instance and other COM registrations are kept alive by the main svchost thread
  137. // which is initialized MTA.
  138. //
  139. CoUninitialize();
  140. }
  141. return bRetValue;
  142. }
  143. inline void
  144. InitializeSensGlobals(
  145. void
  146. )
  147. /*++
  148. Routine Description:
  149. Initialize the global variables. This is needed if we are to run
  150. within svchost.exe.
  151. Arguments:
  152. None.
  153. Notes:
  154. Some of the SENS globals are initialized during SensInitialize()
  155. processing. Look at ServiceMain(), DoLanSetup(), DoWanSetup() etc.
  156. Return Value:
  157. None.
  158. --*/
  159. {
  160. //
  161. // Common across platforms
  162. //
  163. // Pointers
  164. gpReachList = NULL;
  165. gpIEventSystem = NULL;
  166. gpSensCache = NULL;
  167. gpChangeCF = NULL;
  168. // Handles
  169. ghSensHeap = NULL;
  170. ghReachTimer = NULL;
  171. ghSensFileMap = NULL;
  172. ghSensStartedEvent = NULL;
  173. // BOOLs
  174. gbIpInitSuccessful = FALSE;
  175. gbIsRasInstalled = FALSE;
  176. gdwLocked = FALSE;
  177. // DWORDs
  178. gdwLastLANTime = 0x0;
  179. gdwLANState = 0x0;
  180. gdwLastWANTime = 0x0;
  181. gdwWANState = 0x0;
  182. gdwRegCO = 0x0;
  183. g_cFilterObj = 0x0;
  184. g_cFilterLock = 0x0;
  185. g_cSubChangeObj = 0x0;
  186. g_cSubChangeLock = 0x0;
  187. gdwMediaSenseState = SENSSVC_START;
  188. // Structures
  189. memset(gIfState, 0x0, (sizeof(IF_STATE) * MAX_IF_ENTRIES));
  190. memset(&gIpStats, 0x0, sizeof(MIB_IPSTATS));
  191. memset(&gSystemPowerState, 0x0, sizeof(SYSTEM_POWER_STATUS));
  192. memset(&gSensLock, 0x0, sizeof(CRITICAL_SECTION));
  193. }
  194. inline BOOL
  195. Init(
  196. void
  197. )
  198. /*++
  199. Routine Description:
  200. Perform initialization at startup.
  201. Arguments:
  202. None.
  203. Notes:
  204. This should be called early in SensInitialize().
  205. Return Value:
  206. TRUE, if successful.
  207. FALSE, otherwise
  208. --*/
  209. {
  210. HRESULT hr;
  211. BOOL bRetValue;
  212. BOOL bComInitialized;
  213. OSVERSIONINFO VersionInfo;
  214. hr = S_OK;
  215. bRetValue = FALSE;
  216. bComInitialized = FALSE;
  217. // Reset
  218. InitializeSensGlobals();
  219. //
  220. // Initialize COM
  221. //
  222. hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  223. ASSERT(SUCCEEDED(hr));
  224. if (FAILED(hr))
  225. {
  226. SensPrintA(SENS_ERR, ("[%d] CoInitializeEx() failed, HRESULT=%x\n", GetTickCount(), hr));
  227. bRetValue = FALSE;
  228. goto Cleanup;
  229. }
  230. bComInitialized = TRUE;
  231. // Use Default Process heap
  232. ghSensHeap = GetProcessHeap();
  233. if (ghSensHeap == NULL)
  234. {
  235. SensPrintToDebugger(SENS_DBG, ("[SENS] Failed to obtain ProcessHeap() - 0x%x!\n", GetLastError()));
  236. bRetValue = FALSE;
  237. goto Cleanup;
  238. }
  239. // Initialize Sens Global lock
  240. InitializeCriticalSection(&gSensLock);
  241. // Destination Reachability Event setup
  242. if (FALSE == InitReachabilityEngine())
  243. {
  244. SensPrintToDebugger(SENS_DBG, ("[SENS] Failed to initialize reachability engine!\n"));
  245. bRetValue = FALSE;
  246. goto Cleanup;
  247. }
  248. gpIEventSystem = NULL;
  249. if (FALSE == CreateSensCache())
  250. {
  251. SensPrintToDebugger(SENS_DBG, ("[SENS] Failed to create SENS Cache!\n"));
  252. }
  253. // Get a handle to the SensStartEvent.
  254. // The event is created in the wlnotify dll (winlogon).
  255. ghSensStartedEvent = OpenEvent(
  256. EVENT_ALL_ACCESS, // Access Flag
  257. FALSE, // Inheritable
  258. SENS_STARTED_EVENT // Name of the event
  259. );
  260. if (ghSensStartedEvent == NULL)
  261. {
  262. SensPrintToDebugger(SENS_DBG, ("[SENS] Failed to Open SensStartedEvent - 0x%x!\n", GetLastError()));
  263. }
  264. else
  265. {
  266. SensPrint(SENS_INFO, (SENS_STRING("[%d] Successfully opened SensStartedEvent.\n"), GetTickCount()));
  267. }
  268. bRetValue = TRUE;
  269. Cleanup:
  270. //
  271. // Cleanup stuff when we fail to Init properly.
  272. //
  273. if (FALSE == bRetValue)
  274. {
  275. // Release EventSystem
  276. if (gpIEventSystem != NULL)
  277. {
  278. gpIEventSystem->Release();
  279. gpIEventSystem = 0;
  280. }
  281. // Uninit COM because SensUninitialize() is not going to be called.
  282. if (TRUE == bComInitialized)
  283. {
  284. CoUninitialize();
  285. }
  286. }
  287. return bRetValue;
  288. }
  289. BOOL
  290. CreateSids(
  291. PSID* ppsidBuiltInAdministrators,
  292. PSID* ppsidSystem,
  293. PSID* ppsidWorld
  294. )
  295. /*++
  296. Routine Description:
  297. Creates and return pointers to three SIDs one for each of World,
  298. Local Administrators, and System.
  299. Note:
  300. IDENTICAL TO A FUNCTION IN OLE32\DCOMSS\WRAPPER\EPTS.C.
  301. Arguments:
  302. ppsidBuiltInAdministrators - Receives pointer to SID representing local
  303. administrators;
  304. ppsidSystem - Receives pointer to SID representing System;
  305. ppsidWorld - Receives pointer to SID representing World.
  306. Return Value:
  307. BOOL indicating success (TRUE) or failure (FALSE).
  308. Caller must free returned SIDs by calling FreeSid() for each returned
  309. SID when this function return TRUE; pointers should be assumed garbage
  310. when the function returns FALSE.
  311. --*/
  312. {
  313. //
  314. // An SID is built from an Identifier Authority and a set of Relative IDs
  315. // (RIDs). The Authority of interest to us SECURITY_NT_AUTHORITY.
  316. //
  317. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  318. SID_IDENTIFIER_AUTHORITY WorldAuthority = SECURITY_WORLD_SID_AUTHORITY;
  319. //
  320. // Each RID represents a sub-unit of the authority. Local
  321. // Administrators is in the "built in" domain. The other SIDs, for
  322. // Authenticated users and system, is based directly off of the
  323. // authority.
  324. //
  325. // For examples of other useful SIDs consult the list in
  326. // \nt\public\sdk\inc\ntseapi.h.
  327. //
  328. if (!AllocateAndInitializeSid(&NtAuthority,
  329. 2, // 2 sub-authorities
  330. SECURITY_BUILTIN_DOMAIN_RID,
  331. DOMAIN_ALIAS_RID_ADMINS,
  332. 0,0,0,0,0,0,
  333. ppsidBuiltInAdministrators)) {
  334. // error
  335. } else if (!AllocateAndInitializeSid(&NtAuthority,
  336. 1, // 1 sub-authorities
  337. SECURITY_LOCAL_SYSTEM_RID,
  338. 0,0,0,0,0,0,0,
  339. ppsidSystem)) {
  340. // error
  341. FreeSid(*ppsidBuiltInAdministrators);
  342. *ppsidBuiltInAdministrators = NULL;
  343. } else if (!AllocateAndInitializeSid(&WorldAuthority,
  344. 1, // 1 sub-authority
  345. SECURITY_WORLD_RID,
  346. 0,0,0,0,0,0,0,
  347. ppsidWorld)) {
  348. // error
  349. FreeSid(*ppsidBuiltInAdministrators);
  350. *ppsidBuiltInAdministrators = NULL;
  351. FreeSid(*ppsidSystem);
  352. *ppsidSystem = NULL;
  353. } else {
  354. return TRUE;
  355. }
  356. return FALSE;
  357. }
  358. PSECURITY_DESCRIPTOR
  359. CreateSd(
  360. VOID
  361. )
  362. /*++
  363. Routine Description:
  364. Creates and return a SECURITY_DESCRIPTOR with a DACL granting
  365. (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | SYNCHRONIZE) to World,
  366. and GENERIC_ALL to Local Administrators and System.
  367. Notes:
  368. SIMILAR TO A FUNCTION IN OLE32\DCOMSS\WRAPPER\EPTS.C.
  369. Arguments:
  370. None
  371. Return Value:
  372. Pointer to the created SECURITY_DESCRIPTOR, or NULL if an error occurred.
  373. Caller must free returned SECURITY_DESCRIPTOR back to process heap by
  374. a call to HeapFree.
  375. --*/
  376. {
  377. PSID psidWorld;
  378. PSID psidBuiltInAdministrators;
  379. PSID psidSystem;
  380. if (!CreateSids(&psidBuiltInAdministrators,
  381. &psidSystem,
  382. &psidWorld)) {
  383. // error
  384. } else {
  385. //
  386. // Calculate the size of and allocate a buffer for the DACL, we need
  387. // this value independently of the total alloc size for ACL init.
  388. //
  389. PSECURITY_DESCRIPTOR Sd = NULL;
  390. ULONG AclSize;
  391. //
  392. // "- sizeof (ULONG)" represents the SidStart field of the
  393. // ACCESS_ALLOWED_ACE. Since we're adding the entire length of the
  394. // SID, this field is counted twice.
  395. //
  396. AclSize = sizeof (ACL) +
  397. (3 * (sizeof (ACCESS_ALLOWED_ACE) - sizeof (ULONG))) +
  398. GetLengthSid(psidWorld) +
  399. GetLengthSid(psidBuiltInAdministrators) +
  400. GetLengthSid(psidSystem);
  401. Sd = (PSID)new char[SECURITY_DESCRIPTOR_MIN_LENGTH + AclSize];
  402. if (!Sd) {
  403. // error
  404. } else {
  405. ACL *Acl;
  406. Acl = (ACL *)((BYTE *)Sd + SECURITY_DESCRIPTOR_MIN_LENGTH);
  407. if (!InitializeAcl(Acl,
  408. AclSize,
  409. ACL_REVISION)) {
  410. // error
  411. } else if (!AddAccessAllowedAce(Acl,
  412. ACL_REVISION,
  413. SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE,
  414. psidWorld)) {
  415. // Failed to build the ACE granting "WORLD"
  416. // (SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE) access.
  417. } else if (!AddAccessAllowedAce(Acl,
  418. ACL_REVISION,
  419. GENERIC_ALL,
  420. psidBuiltInAdministrators)) {
  421. // Failed to build the ACE granting "Built-in Administrators"
  422. // (GENERIC_ALL) access.
  423. } else if (!AddAccessAllowedAce(Acl,
  424. ACL_REVISION,
  425. GENERIC_ALL,
  426. psidSystem)) {
  427. // Failed to build the ACE granting "System"
  428. // GENERIC_ALL access.
  429. } else if (!InitializeSecurityDescriptor(Sd,
  430. SECURITY_DESCRIPTOR_REVISION)) {
  431. // error
  432. } else if (!SetSecurityDescriptorDacl(Sd,
  433. TRUE,
  434. Acl,
  435. FALSE)) {
  436. // error
  437. } else {
  438. FreeSid(psidWorld);
  439. FreeSid(psidBuiltInAdministrators);
  440. FreeSid(psidSystem);
  441. return Sd;
  442. }
  443. delete (char *)Sd;
  444. }
  445. FreeSid(psidWorld);
  446. FreeSid(psidBuiltInAdministrators);
  447. FreeSid(psidSystem);
  448. }
  449. return NULL;
  450. }
  451. RPC_STATUS
  452. RPC_ENTRY
  453. SENS_CheckLocalCallback(
  454. RPC_IF_HANDLE ifhandle,
  455. void *Context
  456. )
  457. /*++
  458. Routine Description:
  459. SENS runs in a shared service host which means it is possible for a
  460. caller on another machine to call SENS. This is not expected and is
  461. blocked by this callback routine in order to reduce the potential
  462. attack surface of RPC.
  463. Arguments:
  464. ifhandle - interface this callback is registered with (ignored)
  465. context - context to discover information about the caller (ignored)
  466. Return Value:
  467. RPC_S_OK - caller allowed to call methods in the interface
  468. other - caller is blocked
  469. --*/
  470. {
  471. unsigned fLocal = FALSE;
  472. if ( (RPC_S_OK == I_RpcBindingIsClientLocal(0, &fLocal))
  473. && (fLocal) )
  474. {
  475. return RPC_S_OK;
  476. }
  477. return RPC_S_ACCESS_DENIED;
  478. }
  479. BOOL
  480. DoRpcSetup(
  481. void
  482. )
  483. /*++
  484. Routine Description:
  485. Perform RPC server initialization.
  486. Arguments:
  487. None.
  488. Return Value:
  489. TRUE, if successful.
  490. FALSE, otherwise
  491. --*/
  492. {
  493. RPC_STATUS status;
  494. BOOL fDontWait;
  495. BOOL bRetValue;
  496. PSECURITY_DESCRIPTOR psd;
  497. status = RPC_S_OK;
  498. fDontWait = TRUE;
  499. bRetValue = FALSE;
  500. // Make sure RPC allocates thread stacks of sufficient size.
  501. status = RpcMgmtSetServerStackSize(2*4096);
  502. ASSERT(status == RPC_S_OK);
  503. psd = CreateSd();
  504. if (!psd)
  505. {
  506. bRetValue = FALSE;
  507. goto Cleanup;
  508. }
  509. status = RpcServerUseProtseqEp(
  510. SENS_PROTSEQ,
  511. RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
  512. SENS_ENDPOINT,
  513. psd // Security descriptor
  514. );
  515. delete (char *)psd;
  516. if (RPC_S_DUPLICATE_ENDPOINT == status)
  517. {
  518. SensPrintA(SENS_ERR, ("[%d] DoRpcSetup(): Endpoint already created. Continuing!\n", GetTickCount()));
  519. status = RPC_S_OK;
  520. }
  521. if (RPC_S_OK != status)
  522. {
  523. SensPrintA(SENS_ERR, ("[%d] DoRpcSetup(): RpcServerUseProtseqEp() returned 0x%x\n", GetTickCount(), status));
  524. bRetValue = FALSE;
  525. goto Cleanup;
  526. }
  527. //
  528. // On NT platforms, use auto-listen interfaces. We don't need to call
  529. // RpcServerListen().
  530. //
  531. // SENS API interface
  532. status = RpcServerRegisterIfEx(
  533. SensApi_ServerIfHandle, // The interface
  534. NULL, // MgrTypeUuid
  535. NULL, // MgrEpv
  536. RPC_IF_AUTOLISTEN, // Flags
  537. RPC_C_LISTEN_MAX_CALLS_DEFAULT,// Max calls value
  538. SENS_CheckLocalCallback // Security Callback function
  539. );
  540. if (RPC_S_OK != status)
  541. {
  542. SensPrintA(SENS_ERR, ("[%d] DoRpcSetup(): RpcServerRegisterIfEx(1) returned 0x%x\n", GetTickCount(), status));
  543. bRetValue = FALSE;
  544. goto Cleanup;
  545. }
  546. // SensNotify interface
  547. status = RpcServerRegisterIfEx(
  548. SENSNotify_ServerIfHandle, // The interface
  549. NULL, // MgrTypeUuid
  550. NULL, // MgrEpv
  551. RPC_IF_AUTOLISTEN, // Flags
  552. RPC_C_LISTEN_MAX_CALLS_DEFAULT,// Max calls value
  553. SENS_CheckLocalCallback // Security Callback function
  554. );
  555. if (RPC_S_OK != status)
  556. {
  557. SensPrintA(SENS_ERR, ("[%d] DoRpcSetup(): RpcServerRegisterIfEx(2) returned 0x%x\n", GetTickCount(), status));
  558. bRetValue = FALSE;
  559. goto Cleanup;
  560. }
  561. // All's well.
  562. bRetValue = TRUE;
  563. Cleanup:
  564. //
  565. // Cleanup
  566. //
  567. return bRetValue;
  568. }
  569. BOOL
  570. SensUninitialize(
  571. void
  572. )
  573. /*++
  574. Routine Description:
  575. Perform any cleanup.
  576. Arguments:
  577. None.
  578. Return Value:
  579. TRUE, if successful.
  580. FALSE, otherwise
  581. --*/
  582. {
  583. int err;
  584. RPC_STATUS status;
  585. BOOL bRetValue;
  586. HRESULT hr;
  587. DWORD dwNow;
  588. bRetValue = TRUE;
  589. hr = S_OK;
  590. dwNow = GetTickCount();
  591. SensPrintA(SENS_ERR, ("[%d] Begin stopping of SENS Service...\n", dwNow));
  592. // Unregister media sense notifications.
  593. if (FALSE == MediaSenseUnregister())
  594. {
  595. SensPrintA(SENS_ERR, ("[%d] SensUninitialize(): MediaSenseUnregister() failed.\n", GetTickCount()));
  596. }
  597. else
  598. {
  599. SensPrintA(SENS_INFO, ("[%d] SensUninitialize(): MediaSenseUnregister() succeeded.\n", GetTickCount()));
  600. }
  601. // Unregister the RPC interface #1
  602. status = RpcServerUnregisterIf(
  603. SensApi_ServerIfHandle,
  604. NULL, // MgrTypeUuid
  605. FALSE // WaitForCallsToComplete
  606. );
  607. ASSERT(status == RPC_S_OK);
  608. if (RPC_S_OK != status)
  609. {
  610. SensPrintA(SENS_ERR, ("[%d] SensUninitialize(): RpcServerUnegisterIf(1) returned 0x%x\n", GetTickCount(), status));
  611. bRetValue = FALSE;
  612. goto Cleanup;
  613. }
  614. SensPrintA(SENS_INFO, ("[%d] SensUninitialize(): RpcServerUnregisterIf(1) succeeded.\n", GetTickCount()));
  615. // Unregister the RPC interface #2
  616. status = RpcServerUnregisterIf(
  617. SENSNotify_ServerIfHandle,
  618. NULL, // MgrTypeUuid
  619. FALSE // WaitForCallsToComplete
  620. );
  621. ASSERT(status == RPC_S_OK);
  622. if (RPC_S_OK != status)
  623. {
  624. SensPrintA(SENS_ERR, ("[%d] SensUninitialize(): RpcServerUnegisterIf(2) returned 0x%x\n", GetTickCount(), status));
  625. bRetValue = FALSE;
  626. goto Cleanup;
  627. }
  628. SensPrintA(SENS_INFO, ("[%d] SensUninitialize(): RpcServerUnregisterIf(2) succeeded.\n", GetTickCount()));
  629. //
  630. // Remove our classfactory from COM's cache.
  631. //
  632. if (0x0 != gdwRegCO)
  633. {
  634. hr = CoRevokeClassObject(gdwRegCO);
  635. }
  636. if (NULL != gpChangeCF)
  637. {
  638. gpChangeCF->Release();
  639. }
  640. //
  641. // EventSystem specific cleanup.
  642. //
  643. if (gpIEventSystem)
  644. {
  645. gpIEventSystem->Release();
  646. }
  647. //
  648. // Stop Reachability polling
  649. //
  650. StopReachabilityEngine();
  651. //
  652. // Empty the destination reachability list
  653. //
  654. if (NULL != gpReachList)
  655. {
  656. delete gpReachList;
  657. gpReachList = NULL;
  658. }
  659. //
  660. // Destroy SENS Cache
  661. //
  662. DeleteSensCache();
  663. // Cleanup started event handle
  664. CloseHandle(ghSensStartedEvent);
  665. ghSensStartedEvent = 0;
  666. // Delete Global SENS lock
  667. DeleteCriticalSection(&gSensLock);
  668. bRetValue = TRUE;
  669. SensPrintToDebugger(SENS_DBG, ("\n[SENS] [%d] Service Stopped.\n\n", GetTickCount()));
  670. Cleanup:
  671. //
  672. // Cleanup
  673. //
  674. // Cleanup Winsock.
  675. err = WSACleanup();
  676. if (err != 0)
  677. {
  678. SensPrintA(SENS_ERR, ("[%d] SensUninitialize(): WSACleanup() returned GLE of %d\n", GetTickCount(),
  679. WSAGetLastError()));
  680. }
  681. SensPrintA(SENS_INFO, ("[%d] Stopping SENS took %d msec.\n\n", GetTickCount(), (GetTickCount()-dwNow)));
  682. return bRetValue;
  683. }
  684. BOOL
  685. DoEventSystemSetup(
  686. void
  687. )
  688. /*++
  689. Routine Description:
  690. Perform the EventSystem specific initialization here.
  691. Arguments:
  692. None.
  693. Return Value:
  694. TRUE, if successful.
  695. FALSE, otherwise
  696. --*/
  697. {
  698. HRESULT hr;
  699. BOOL bRetValue;
  700. hr = S_OK;
  701. bRetValue = FALSE;
  702. //
  703. // Instantiate the Event System
  704. //
  705. hr = CoCreateInstance(
  706. CLSID_CEventSystem,
  707. NULL,
  708. CLSCTX_SERVER,
  709. IID_IEventSystem,
  710. (LPVOID *) &gpIEventSystem
  711. );
  712. if (FAILED(hr))
  713. {
  714. SensPrintA(SENS_ERR, ("[%d] Failed to create CEventSystem, HRESULT=%x\n", GetTickCount(), hr));
  715. goto Cleanup;
  716. }
  717. //
  718. // Create the IEventObjectChange ClassFactory and register it with COM.
  719. //
  720. gpChangeCF = new CIEventObjectChangeCF;
  721. if (NULL == gpChangeCF)
  722. {
  723. SensPrintA(SENS_ERR, ("[%d] Failed to allocate IEventObjectChange ClassFactory object", GetTickCount()));
  724. goto Cleanup;
  725. }
  726. // Add our reference to it.
  727. gpChangeCF->AddRef();
  728. SensPrintA(SENS_INFO, ("[%d] ClassFactory created successfully.\n", GetTickCount()));
  729. // Register the CLSID
  730. hr = CoRegisterClassObject(
  731. SENSGUID_SUBSCRIBER_LCE,
  732. (LPUNKNOWN) gpChangeCF,
  733. CLSCTX_LOCAL_SERVER,
  734. REGCLS_MULTIPLEUSE,
  735. &gdwRegCO
  736. );
  737. if (FAILED(hr))
  738. {
  739. SensPrintA(SENS_ERR, ("[%d] CoRegisterClassObject(IEventObjectChange) returned 0x%x.\n", GetTickCount(), hr));
  740. goto Cleanup;
  741. }
  742. SensPrintA(SENS_ERR, ("[%d] Successfully registered the Class Factories.\n", GetTickCount()));
  743. bRetValue = TRUE;
  744. Cleanup:
  745. //
  746. // Cleanup
  747. //
  748. if (FALSE == bRetValue)
  749. {
  750. if (0x0 != gdwRegCO)
  751. {
  752. hr = CoRevokeClassObject(gdwRegCO);
  753. gdwRegCO = 0x0;
  754. }
  755. if (gpChangeCF)
  756. {
  757. delete gpChangeCF;
  758. gpChangeCF = NULL;
  759. }
  760. }
  761. return bRetValue;
  762. }
  763. BOOL
  764. ConfigureSensIfNecessary(
  765. void
  766. )
  767. /*++
  768. Routine Description:
  769. Perform the configuration necessary for SENS.
  770. Arguments:
  771. None.
  772. Return Value:
  773. TRUE, if successful.
  774. FALSE, otherwise
  775. --*/
  776. {
  777. HRESULT hr;
  778. HKEY hKeySens;
  779. LONG RegStatus;
  780. BOOL bStatus;
  781. DWORD dwType;
  782. DWORD cbData;
  783. DWORD dwConfigured;
  784. LPBYTE lpbData;
  785. HMODULE hSensCfgDll;
  786. FARPROC pRegisterFunc;
  787. hr = S_OK;
  788. hKeySens = NULL;
  789. RegStatus = ERROR_SUCCESS;
  790. bStatus = FALSE;
  791. dwType = 0x0;
  792. cbData = 0x0;
  793. dwConfigured = CONFIG_VERSION_NONE;
  794. lpbData = NULL;
  795. hSensCfgDll = NULL;
  796. pRegisterFunc = NULL;
  797. RegStatus = RegOpenKeyEx(
  798. HKEY_LOCAL_MACHINE, // Handle of the key
  799. SENS_REGISTRY_KEY, // String which represents the sub-key to open
  800. 0, // Reserved (MBZ)
  801. KEY_ALL_ACCESS, // Security Access mask
  802. &hKeySens // Returned HKEY
  803. );
  804. if (RegStatus != ERROR_SUCCESS)
  805. {
  806. SensPrintA(SENS_ERR, ("RegOpenKeyEx(Sens) returned %d.\n", RegStatus));
  807. goto Cleanup;
  808. }
  809. //
  810. // Query the Configured value
  811. //
  812. lpbData = (LPBYTE) &dwConfigured;
  813. cbData = sizeof(DWORD);
  814. RegStatus = RegQueryValueEx(
  815. hKeySens, // Handle of the sub-key
  816. IS_SENS_CONFIGURED, // Name of the Value
  817. NULL, // Reserved (MBZ)
  818. &dwType, // Address of the type of the Value
  819. lpbData, // Address of the data of the Value
  820. &cbData // Address of size of data of the Value
  821. );
  822. if (RegStatus != ERROR_SUCCESS)
  823. {
  824. SensPrintA(SENS_ERR, ("RegQueryValueEx(IS_SENS_CONFIGURED) failed with 0x%x\n", RegStatus));
  825. goto Cleanup;
  826. }
  827. ASSERT(dwType == REG_DWORD);
  828. if (dwConfigured >= CONFIG_VERSION_CURRENT)
  829. {
  830. SensPrintA(SENS_ERR, ("[%d] SENS is already configured!\n", GetTickCount()));
  831. bStatus = TRUE;
  832. goto Cleanup;
  833. }
  834. //
  835. // Sens is not yet configured to the latest version. So, do the necessary
  836. // work now.
  837. //
  838. // Try to Load the Configuration Dll
  839. hSensCfgDll = LoadLibrary(SENS_CONFIGURATION_DLL);
  840. if (hSensCfgDll == NULL)
  841. {
  842. SensPrintA(SENS_ERR, ("LoadLibrary(SensCfg) returned 0x%x.\n", GetLastError()));
  843. goto Cleanup;
  844. }
  845. // Get the required entry point.
  846. pRegisterFunc = GetProcAddress(hSensCfgDll, SENS_REGISTER_FUNCTION);
  847. if (pRegisterFunc == NULL)
  848. {
  849. SensPrintA(SENS_ERR, ("GetProcAddress(Register) returned 0x%x.\n", GetLastError()));
  850. goto Cleanup;
  851. }
  852. // Do the registration now.
  853. hr = (HRESULT)((*pRegisterFunc)());
  854. if (FAILED(hr))
  855. {
  856. SensPrintA(SENS_ERR, ("RegisterSens() returned with 0x%x\n", hr));
  857. goto Cleanup;
  858. }
  859. // Update registry to reflect that SENS is now configured.
  860. dwConfigured = CONFIG_VERSION_CURRENT;
  861. RegStatus = RegSetValueEx(
  862. hKeySens, // Key to set Value for.
  863. IS_SENS_CONFIGURED, // Value to set
  864. 0, // Reserved
  865. REG_DWORD, // Value Type
  866. (BYTE*) &dwConfigured,// Address of Value data
  867. sizeof(DWORD) // Size of Value
  868. );
  869. if (RegStatus != ERROR_SUCCESS)
  870. {
  871. SensPrintA(SENS_ERR, ("RegSetValueEx(IS_SENS_CONFIGURED) failed with 0x%x\n", RegStatus));
  872. goto Cleanup;
  873. }
  874. SensPrintA(SENS_INFO, ("[%d] SENS is now configured successfully. Registry updated.\n", GetTickCount()));
  875. bStatus = TRUE;
  876. Cleanup:
  877. //
  878. // Cleanup
  879. //
  880. if (hKeySens)
  881. {
  882. RegCloseKey(hKeySens);
  883. }
  884. if (hSensCfgDll)
  885. {
  886. FreeLibrary(hSensCfgDll);
  887. }
  888. return bStatus;
  889. }
  890. extern "C" int APIENTRY
  891. DllMain(
  892. IN HINSTANCE hInstance,
  893. IN DWORD dwReason,
  894. IN LPVOID lpvReserved
  895. )
  896. /*++
  897. Routine Description:
  898. This routine will get called either when a process attaches to this dll
  899. or when a process detaches from this dll.
  900. Return Value:
  901. TRUE - Initialization successfully occurred.
  902. FALSE - Insufficient memory is available for the process to attach to
  903. this dll.
  904. --*/
  905. {
  906. BOOL bSuccess;
  907. switch (dwReason)
  908. {
  909. case DLL_PROCESS_ATTACH:
  910. // Disable Thread attach/detach calls
  911. bSuccess = DisableThreadLibraryCalls(hInstance);
  912. ASSERT(bSuccess == TRUE);
  913. // Use Default Process heap
  914. ghSensHeap = GetProcessHeap();
  915. ASSERT(ghSensHeap != NULL);
  916. break;
  917. case DLL_PROCESS_DETACH:
  918. break;
  919. }
  920. return(TRUE);
  921. }