Leaked source code of windows server 2003
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
29 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. SensPrintA(SENS_INFO, ("[%d] Initializing SENS...\n", dwNow));
  74. #endif // DBG
  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 may also be created in the wlnotify dll (winlogon).
  255. ghSensStartedEvent = CreateEvent(NULL, // Specific Security Attributes
  256. TRUE, // Event is ManualReset
  257. FALSE, // Initial state is not Signalled
  258. SENS_STARTED_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. ResetEvent(ghSensStartedEvent);
  665. CloseHandle(ghSensStartedEvent);
  666. ghSensStartedEvent = 0;
  667. // Delete Global SENS lock
  668. DeleteCriticalSection(&gSensLock);
  669. bRetValue = TRUE;
  670. SensPrintToDebugger(SENS_DBG, ("\n[SENS] [%d] Service Stopped.\n\n", GetTickCount()));
  671. Cleanup:
  672. //
  673. // Cleanup
  674. //
  675. // Cleanup Winsock.
  676. err = WSACleanup();
  677. if (err != 0)
  678. {
  679. SensPrintA(SENS_ERR, ("[%d] SensUninitialize(): WSACleanup() returned GLE of %d\n", GetTickCount(),
  680. WSAGetLastError()));
  681. }
  682. SensPrintA(SENS_INFO, ("[%d] Stopping SENS took %d msec.\n\n", GetTickCount(), (GetTickCount()-dwNow)));
  683. return bRetValue;
  684. }
  685. BOOL
  686. DoEventSystemSetup(
  687. void
  688. )
  689. /*++
  690. Routine Description:
  691. Perform the EventSystem specific initialization here.
  692. Arguments:
  693. None.
  694. Return Value:
  695. TRUE, if successful.
  696. FALSE, otherwise
  697. --*/
  698. {
  699. HRESULT hr;
  700. BOOL bRetValue;
  701. hr = S_OK;
  702. bRetValue = FALSE;
  703. //
  704. // Instantiate the Event System
  705. //
  706. hr = CoCreateInstance(
  707. CLSID_CEventSystem,
  708. NULL,
  709. CLSCTX_SERVER,
  710. IID_IEventSystem,
  711. (LPVOID *) &gpIEventSystem
  712. );
  713. if (FAILED(hr))
  714. {
  715. SensPrintA(SENS_ERR, ("[%d] Failed to create CEventSystem, HRESULT=%x\n", GetTickCount(), hr));
  716. goto Cleanup;
  717. }
  718. //
  719. // Create the IEventObjectChange ClassFactory and register it with COM.
  720. //
  721. gpChangeCF = new CIEventObjectChangeCF;
  722. if (NULL == gpChangeCF)
  723. {
  724. SensPrintA(SENS_ERR, ("[%d] Failed to allocate IEventObjectChange ClassFactory object", GetTickCount()));
  725. goto Cleanup;
  726. }
  727. // Add our reference to it.
  728. gpChangeCF->AddRef();
  729. SensPrintA(SENS_INFO, ("[%d] ClassFactory created successfully.\n", GetTickCount()));
  730. // Register the CLSID
  731. hr = CoRegisterClassObject(
  732. SENSGUID_SUBSCRIBER_LCE,
  733. (LPUNKNOWN) gpChangeCF,
  734. CLSCTX_LOCAL_SERVER,
  735. REGCLS_MULTIPLEUSE,
  736. &gdwRegCO
  737. );
  738. if (FAILED(hr))
  739. {
  740. SensPrintA(SENS_ERR, ("[%d] CoRegisterClassObject(IEventObjectChange) returned 0x%x.\n", GetTickCount(), hr));
  741. goto Cleanup;
  742. }
  743. SensPrintA(SENS_ERR, ("[%d] Successfully registered the Class Factories.\n", GetTickCount()));
  744. bRetValue = TRUE;
  745. Cleanup:
  746. //
  747. // Cleanup
  748. //
  749. if (FALSE == bRetValue)
  750. {
  751. if (0x0 != gdwRegCO)
  752. {
  753. hr = CoRevokeClassObject(gdwRegCO);
  754. gdwRegCO = 0x0;
  755. }
  756. if (gpChangeCF)
  757. {
  758. delete gpChangeCF;
  759. gpChangeCF = NULL;
  760. }
  761. }
  762. return bRetValue;
  763. }
  764. BOOL
  765. ConfigureSensIfNecessary(
  766. void
  767. )
  768. /*++
  769. Routine Description:
  770. Perform the configuration necessary for SENS.
  771. Arguments:
  772. None.
  773. Return Value:
  774. TRUE, if successful.
  775. FALSE, otherwise
  776. --*/
  777. {
  778. HRESULT hr;
  779. HKEY hKeySens;
  780. LONG RegStatus;
  781. BOOL bStatus;
  782. DWORD dwType;
  783. DWORD cbData;
  784. DWORD dwConfigured;
  785. LPBYTE lpbData;
  786. HMODULE hSensCfgDll;
  787. FARPROC pRegisterFunc;
  788. hr = S_OK;
  789. hKeySens = NULL;
  790. RegStatus = ERROR_SUCCESS;
  791. bStatus = FALSE;
  792. dwType = 0x0;
  793. cbData = 0x0;
  794. dwConfigured = CONFIG_VERSION_NONE;
  795. lpbData = NULL;
  796. hSensCfgDll = NULL;
  797. pRegisterFunc = NULL;
  798. RegStatus = RegOpenKeyEx(
  799. HKEY_LOCAL_MACHINE, // Handle of the key
  800. SENS_REGISTRY_KEY, // String which represents the sub-key to open
  801. 0, // Reserved (MBZ)
  802. KEY_ALL_ACCESS, // Security Access mask
  803. &hKeySens // Returned HKEY
  804. );
  805. if (RegStatus != ERROR_SUCCESS)
  806. {
  807. SensPrintA(SENS_ERR, ("RegOpenKeyEx(Sens) returned %d.\n", RegStatus));
  808. goto Cleanup;
  809. }
  810. //
  811. // Query the Configured value
  812. //
  813. lpbData = (LPBYTE) &dwConfigured;
  814. cbData = sizeof(DWORD);
  815. RegStatus = RegQueryValueEx(
  816. hKeySens, // Handle of the sub-key
  817. IS_SENS_CONFIGURED, // Name of the Value
  818. NULL, // Reserved (MBZ)
  819. &dwType, // Address of the type of the Value
  820. lpbData, // Address of the data of the Value
  821. &cbData // Address of size of data of the Value
  822. );
  823. if (RegStatus != ERROR_SUCCESS)
  824. {
  825. SensPrintA(SENS_ERR, ("RegQueryValueEx(IS_SENS_CONFIGURED) failed with 0x%x\n", RegStatus));
  826. goto Cleanup;
  827. }
  828. ASSERT(dwType == REG_DWORD);
  829. if (dwConfigured >= CONFIG_VERSION_CURRENT)
  830. {
  831. SensPrintA(SENS_ERR, ("[%d] SENS is already configured!\n", GetTickCount()));
  832. bStatus = TRUE;
  833. goto Cleanup;
  834. }
  835. //
  836. // Sens is not yet configured to the latest version. So, do the necessary
  837. // work now.
  838. //
  839. // Try to Load the Configuration Dll
  840. hSensCfgDll = LoadLibrary(SENS_CONFIGURATION_DLL);
  841. if (hSensCfgDll == NULL)
  842. {
  843. SensPrintA(SENS_ERR, ("LoadLibrary(SensCfg) returned 0x%x.\n", GetLastError()));
  844. goto Cleanup;
  845. }
  846. // Get the required entry point.
  847. pRegisterFunc = GetProcAddress(hSensCfgDll, SENS_REGISTER_FUNCTION);
  848. if (pRegisterFunc == NULL)
  849. {
  850. SensPrintA(SENS_ERR, ("GetProcAddress(Register) returned 0x%x.\n", GetLastError()));
  851. goto Cleanup;
  852. }
  853. // Do the registration now.
  854. hr = (HRESULT)((*pRegisterFunc)());
  855. if (FAILED(hr))
  856. {
  857. SensPrintA(SENS_ERR, ("RegisterSens() returned with 0x%x\n", hr));
  858. goto Cleanup;
  859. }
  860. // Update registry to reflect that SENS is now configured.
  861. dwConfigured = CONFIG_VERSION_CURRENT;
  862. RegStatus = RegSetValueEx(
  863. hKeySens, // Key to set Value for.
  864. IS_SENS_CONFIGURED, // Value to set
  865. 0, // Reserved
  866. REG_DWORD, // Value Type
  867. (BYTE*) &dwConfigured,// Address of Value data
  868. sizeof(DWORD) // Size of Value
  869. );
  870. if (RegStatus != ERROR_SUCCESS)
  871. {
  872. SensPrintA(SENS_ERR, ("RegSetValueEx(IS_SENS_CONFIGURED) failed with 0x%x\n", RegStatus));
  873. goto Cleanup;
  874. }
  875. SensPrintA(SENS_INFO, ("[%d] SENS is now configured successfully. Registry updated.\n", GetTickCount()));
  876. bStatus = TRUE;
  877. Cleanup:
  878. //
  879. // Cleanup
  880. //
  881. if (hKeySens)
  882. {
  883. RegCloseKey(hKeySens);
  884. }
  885. if (hSensCfgDll)
  886. {
  887. FreeLibrary(hSensCfgDll);
  888. }
  889. return bStatus;
  890. }
  891. extern "C" int APIENTRY
  892. DllMain(
  893. IN HINSTANCE hInstance,
  894. IN DWORD dwReason,
  895. IN LPVOID lpvReserved
  896. )
  897. /*++
  898. Routine Description:
  899. This routine will get called either when a process attaches to this dll
  900. or when a process detaches from this dll.
  901. Return Value:
  902. TRUE - Initialization successfully occurred.
  903. FALSE - Insufficient memory is available for the process to attach to
  904. this dll.
  905. --*/
  906. {
  907. BOOL bSuccess;
  908. switch (dwReason)
  909. {
  910. case DLL_PROCESS_ATTACH:
  911. // Disable Thread attach/detach calls
  912. bSuccess = DisableThreadLibraryCalls(hInstance);
  913. ASSERT(bSuccess == TRUE);
  914. // Use Default Process heap
  915. ghSensHeap = GetProcessHeap();
  916. ASSERT(ghSensHeap != NULL);
  917. break;
  918. case DLL_PROCESS_DETACH:
  919. break;
  920. }
  921. return(TRUE);
  922. }