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.

2274 lines
56 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1997 - 1999
  3. Module Name:
  4. senscfg.cxx
  5. Abstract:
  6. Code to do the configuration (install/uninstall) for SENS.
  7. Author:
  8. Gopal Parupudi <GopalP>
  9. [Notes:]
  10. optional-notes
  11. Revision History:
  12. GopalP 11/11/1997 Start.
  13. --*/
  14. #define INITGUID
  15. #include <common.hxx>
  16. #include <objbase.h>
  17. #include <coguid.h>
  18. #include <eventsys.h>
  19. #include <sensevts.h>
  20. #include <sens.h>
  21. #include <wininet.h>
  22. #include <winineti.h>
  23. #include "senscfg.hxx"
  24. #include "sensinfo.hxx"
  25. #include "memfunc.hxx"
  26. #define MAJOR_VER 1
  27. #define MINOR_VER 0
  28. #define DEFAULT_LCID 0x0
  29. #define MAX_QUERY_SIZE 512
  30. #define SENS_SETUP "SENSCFG: "
  31. #define SENS_SERVICEA "SENS"
  32. #define SENS_SETUPW SENS_BSTR("SENSCFG: ")
  33. #define SENS_SERVICE SENS_STRING("SENS")
  34. #define SENS_DISPLAY_NAME SENS_STRING("System Event Notification")
  35. #define SENS_SERVICE_GROUP SENS_STRING("Network")
  36. #define EVENTSYSTEM_REMOVE SENS_STRING("esserver /remove")
  37. #define EVENTSYSTEM_INSTALL SENS_STRING("esserver /install")
  38. #define SENS_WINLOGON_DLL SENS_STRING("senslogn.dll")
  39. #define GUID_STR_SIZE sizeof("{12345678-1234-1234-1234-123456789012}")
  40. #define EVENTSYSTEM_KEY SENS_STRING("SOFTWARE\\Microsoft\\EventSystem")
  41. #define WINLOGON_NOTIFY_KEY SENS_STRING("SOFTWARE\\Microsoft\\Windows NT\\") \
  42. SENS_STRING("CurrentVersion\\Winlogon\\Notify\\") \
  43. SENS_STRING("senslogn")
  44. #define WININET_SENS_EVENTS INETEVT_RAS_CONNECT | \
  45. INETEVT_RAS_DISCONNECT | \
  46. INETEVT_LOGON | \
  47. INETEVT_LOGOFF
  48. //
  49. // DLL vs EXE dependent constants
  50. //
  51. #if defined(SENS_NT4)
  52. #define SENS_TLBA "SENS.EXE"
  53. #define SENS_BINARYA "SENS.EXE"
  54. #define SENS_TLB SENS_STRING("SENS.EXE")
  55. #define SENS_BINARY SENS_STRING("SENS.EXE")
  56. #else // SENS_NT4
  57. #define SENS_TLBA "SENS.DLL"
  58. #define SENS_BINARYA "SENS.DLL"
  59. #define SENS_TLB SENS_STRING("SENS.DLL")
  60. #define SENS_BINARY SENS_STRING("SENS.DLL")
  61. #endif // SENS_NT4
  62. //
  63. // Misc debugging constants
  64. //
  65. #ifdef STRICT_HRESULT_CHECKS
  66. #ifdef SUCCEEDED
  67. #undef SUCCEEDED
  68. #define SUCCEEDED(_HR_) (_HR_ == S_OK)
  69. #endif // SUCCEEDED
  70. #ifdef FAILED
  71. #undef FAILED
  72. #define FAILED(_HR_) (_HR_ != S_OK)
  73. #endif // FAILED
  74. #endif // STRICT_HRESULT_CHECKS
  75. //
  76. // Globals
  77. //
  78. IEventSystem *gpIEventSystem;
  79. ITypeLib *gpITypeLib;
  80. #ifdef DBG
  81. DWORD gdwDebugOutputLevel;
  82. #endif // DBG
  83. HRESULT APIENTRY
  84. SensRegister(
  85. void
  86. )
  87. /*++
  88. Routine Description:
  89. Register SENS.
  90. Arguments:
  91. None.
  92. Return Value:
  93. HRESULT returned from SensConfigurationHelper()
  94. --*/
  95. {
  96. return (SensConfigurationHelper(FALSE));
  97. }
  98. HRESULT APIENTRY
  99. SensUnregister(
  100. void
  101. )
  102. /*++
  103. Routine Description:
  104. Unregister SENS.
  105. Arguments:
  106. None.
  107. Return Value:
  108. HRESULT returned from SensConfigurationHelper()
  109. --*/
  110. {
  111. return (SensConfigurationHelper(TRUE));
  112. }
  113. HRESULT
  114. SensConfigurationHelper(
  115. BOOL bUnregister
  116. )
  117. /*++
  118. Routine Description:
  119. Main entry into the SENS configuration utility.
  120. Arguments:
  121. bUnregister - If TRUE, then unregister SENS as a publisher.
  122. Return Value:
  123. S_OK, if successful
  124. hr, otherwise
  125. --*/
  126. {
  127. HRESULT hr;
  128. hr = S_OK;
  129. gpIEventSystem = NULL;
  130. gpITypeLib = NULL;
  131. #ifdef DBG
  132. EnableDebugOutputIfNecessary();
  133. #endif // DBG
  134. #if !defined(SENS_CHICAGO)
  135. //
  136. // Configure EventSystem first during an install and last during an uninstall.
  137. //
  138. if (FALSE == bUnregister)
  139. {
  140. hr = SensConfigureEventSystem(FALSE);
  141. if (FAILED(hr))
  142. {
  143. SensPrintA(SENS_ERR, (SENS_SETUP "Failed to configure EventSystem, HRESULT=%x\n", hr));
  144. goto Cleanup;
  145. }
  146. SensPrintA(SENS_INFO, (SENS_SETUP "Successfully configured EventSystem\n"));
  147. }
  148. #endif // SENS_CHICAGO
  149. //
  150. // Instantiate the Event System
  151. //
  152. hr = CoCreateInstance(
  153. CLSID_CEventSystem,
  154. NULL,
  155. CLSCTX_SERVER,
  156. IID_IEventSystem,
  157. (LPVOID *) &gpIEventSystem
  158. );
  159. if (FAILED(hr))
  160. {
  161. SensPrintA(SENS_ERR, (SENS_SETUP "Failed to create CEventSystem, HRESULT=%x\n", hr));
  162. goto Cleanup;
  163. }
  164. SensPrintA(SENS_INFO, (SENS_SETUP "Successfully created CEventSystem\n"));
  165. //
  166. // Register Event Classes (and hence, indirectly events) published by SENS.
  167. //
  168. hr = RegisterSensEventClasses(bUnregister);
  169. if (FAILED(hr))
  170. {
  171. SensPrintA(SENS_ERR, (SENS_SETUP "Failed to %sregister SENS Events"
  172. " - hr = <%x>\n", bUnregister ? "un" : "", hr));
  173. goto Cleanup;
  174. }
  175. SensPrintA(SENS_INFO, (SENS_SETUP "%segistered SENS Publisher Events.\n",
  176. bUnregister ? "Unr" : "R", hr));
  177. //
  178. // Register the subscriptions of SENS.
  179. //
  180. hr = RegisterSensSubscriptions(bUnregister);
  181. if (FAILED(hr))
  182. {
  183. SensPrintA(SENS_ERR, (SENS_SETUP "Failed to %sregister SENS Subscriptions"
  184. " - hr = <%x>\n", bUnregister ? "un" : "", hr));
  185. goto Cleanup;
  186. }
  187. SensPrintA(SENS_ERR, (SENS_SETUP "%segistered SENS Subscriptions.\n",
  188. bUnregister ? "Unr" : "R", hr));
  189. //
  190. // Register the SENS TypeLibs.
  191. //
  192. hr = RegisterSensTypeLibraries(bUnregister);
  193. if (FAILED(hr))
  194. {
  195. SensPrintA(SENS_ERR, (SENS_SETUP "Failed to %sregister SENS Type Libraries"
  196. " - hr = <%x>\n", bUnregister ? "un" : "", hr));
  197. // Abort only during the Install phase...
  198. if (bUnregister == FALSE)
  199. {
  200. goto Cleanup;
  201. }
  202. }
  203. SensPrintA(SENS_INFO, (SENS_SETUP "%segistered SENS Type Libraries.\n",
  204. bUnregister ? "Unr" : "R", hr));
  205. #if !defined(SENS_CHICAGO)
  206. #if defined(SENS_NT4)
  207. //
  208. // Register SENS as a service with SCM.
  209. //
  210. hr = RegisterSensAsService(bUnregister);
  211. if (FAILED(hr))
  212. {
  213. SensPrintA(SENS_ERR, (SENS_SETUP "Failed to %sregister SENS as a Service"
  214. " - hr = <%x>\n", bUnregister ? "un" : "", hr));
  215. goto Cleanup;
  216. }
  217. SensPrintA(SENS_INFO, (SENS_SETUP "%segistered SENS as a Service.\n",
  218. bUnregister ? "Unr" : "R", hr));
  219. #endif // SENS_NT4
  220. //
  221. // Configure EventSystem first during an install and last during an uninstall.
  222. //
  223. if (TRUE == bUnregister)
  224. {
  225. hr = SensConfigureEventSystem(TRUE);
  226. if (FAILED(hr))
  227. {
  228. SensPrintA(SENS_ERR, (SENS_SETUP "Failed to configure EventSystem, HRESULT=%x\n", hr));
  229. goto Cleanup;
  230. }
  231. SensPrintA(SENS_INFO, (SENS_SETUP "Successfully configured EventSystem\n"));
  232. }
  233. #endif // SENS_CHICAGO
  234. //
  235. // Register SENS CLSID in the registry.
  236. //
  237. hr = RegisterSensCLSID(
  238. SENSGUID_SUBSCRIBER_LCE,
  239. SENS_SUBSCRIBER_NAME_EVENTOBJECTCHANGE,
  240. bUnregister
  241. );
  242. if (FAILED(hr))
  243. {
  244. SensPrintA(SENS_ERR, (SENS_SETUP "Failed to %sregister SENS CLSID"
  245. " - hr = <%x>\n", bUnregister ? "un" : "", hr));
  246. goto Cleanup;
  247. }
  248. SensPrintA(SENS_INFO, (SENS_SETUP "%segistered SENS CLSID.\n",
  249. bUnregister ? "Unr" : "R", hr));
  250. //
  251. // Update Configured value
  252. //
  253. hr = SensUpdateVersion(bUnregister);
  254. if (FAILED(hr))
  255. {
  256. SensPrintA(SENS_ERR, (SENS_SETUP "Failed to update SENS version"
  257. " - hr = <%x>\n", hr));
  258. goto Cleanup;
  259. }
  260. SensPrintA(SENS_INFO, (SENS_SETUP "Updated SENS version.\n"));
  261. Cleanup:
  262. //
  263. // Cleanup
  264. //
  265. if (gpIEventSystem)
  266. {
  267. gpIEventSystem->Release();
  268. }
  269. if (gpITypeLib)
  270. {
  271. gpITypeLib->Release();
  272. }
  273. SensPrintA(SENS_ERR, ("\n" SENS_SETUP "SENS Configuration %s.\n",
  274. SUCCEEDED(hr) ? "successful" : "failed"));
  275. return (hr);
  276. }
  277. HRESULT
  278. RegisterSensEventClasses(
  279. BOOL bUnregister
  280. )
  281. /*++
  282. Routine Description:
  283. Register/Unregister all the Events published by SENS.
  284. Arguments:
  285. bUnregister - If TRUE, then unregister all SENS Events.
  286. Return Value:
  287. S_OK, if successful
  288. hr, otherwise
  289. --*/
  290. {
  291. int i;
  292. int errorIndex;
  293. HRESULT hr;
  294. LPOLESTR strGuid;
  295. LPOLESTR strEventClassID;
  296. WCHAR szQuery[MAX_QUERY_SIZE];
  297. BSTR bstrEventClassID;
  298. BSTR bstrEventClassName;
  299. BSTR bstrFiringInterface;
  300. IEventClass *pIEventClass;
  301. hr = S_OK;
  302. strGuid = NULL;
  303. errorIndex = 0;
  304. strEventClassID = NULL;
  305. bstrEventClassID = NULL;
  306. bstrEventClassName = NULL;
  307. bstrFiringInterface = NULL;
  308. pIEventClass = NULL;
  309. for (i = 0; i < SENS_PUBLISHER_EVENTCLASS_COUNT; i++)
  310. {
  311. // Get a new IEventClass.
  312. hr = CoCreateInstance(
  313. CLSID_CEventClass,
  314. NULL,
  315. CLSCTX_SERVER,
  316. IID_IEventClass,
  317. (LPVOID *) &pIEventClass
  318. );
  319. if (FAILED(hr))
  320. {
  321. SensPrintA(SENS_ERR, (SENS_SETUP "RegisterSensEventClasses() failed to create "
  322. "IEventClass - hr = <%x>\n", hr));
  323. goto Cleanup;
  324. }
  325. if (bUnregister)
  326. {
  327. // Form the query
  328. wcscpy(szQuery, SENS_BSTR("EventClassID"));
  329. wcscat(szQuery, SENS_BSTR("="));
  330. AllocateStrFromGuid(strEventClassID, *(gSensEventClasses[i].pEventClassID));
  331. wcscat(szQuery, strEventClassID);
  332. wcscat(szQuery, SENS_BSTR(""));
  333. hr = gpIEventSystem->Remove(
  334. PROGID_EventClass,
  335. szQuery,
  336. &errorIndex
  337. );
  338. FreeStr(strEventClassID);
  339. if (FAILED(hr))
  340. {
  341. SensPrintA(SENS_ERR, (SENS_SETUP "RegisterSensEventClasses(%d) failed to Store"
  342. " - hr = <%x>\n", i, hr));
  343. goto Cleanup;
  344. }
  345. pIEventClass->Release();
  346. pIEventClass = NULL;
  347. continue;
  348. }
  349. AllocateBstrFromGuid(bstrEventClassID, *(gSensEventClasses[i].pEventClassID));
  350. hr = pIEventClass->put_EventClassID(bstrEventClassID);
  351. ASSERT(SUCCEEDED(hr));
  352. AllocateBstrFromString(bstrEventClassName, gSensEventClasses[i].strEventClassName);
  353. hr = pIEventClass->put_EventClassName(bstrEventClassName);
  354. ASSERT(SUCCEEDED(hr));
  355. AllocateBstrFromGuid(bstrFiringInterface, *(gSensEventClasses[i].pFiringInterfaceGUID));
  356. hr = pIEventClass->put_FiringInterfaceID(bstrFiringInterface);
  357. ASSERT(SUCCEEDED(hr));
  358. FreeBstr(bstrEventClassID);
  359. FreeBstr(bstrEventClassName);
  360. FreeBstr(bstrFiringInterface);
  361. hr = gpIEventSystem->Store(PROGID_EventClass, pIEventClass);
  362. if (FAILED(hr))
  363. {
  364. SensPrintA(SENS_ERR, (SENS_SETUP "RegisterSensEventClasses(%d) failed to Store"
  365. " - hr = <%x>\n", i, hr));
  366. goto Cleanup;
  367. }
  368. pIEventClass->Release();
  369. pIEventClass = NULL;
  370. } // for loop
  371. Cleanup:
  372. //
  373. // Cleanup
  374. //
  375. if (pIEventClass)
  376. {
  377. pIEventClass->Release();
  378. }
  379. FreeStr(strGuid);
  380. return (hr);
  381. }
  382. HRESULT
  383. RegisterSensSubscriptions(
  384. BOOL bUnregister
  385. )
  386. /*++
  387. Routine Description:
  388. Register/Unregister the Event subscriptions of SENS.
  389. Arguments:
  390. bUnregister - If TRUE, then unregister all subscriptions of SENS.
  391. Return Value:
  392. S_OK, if successful
  393. hr, otherwise
  394. --*/
  395. {
  396. int i;
  397. int errorIndex;
  398. HRESULT hr;
  399. LPOLESTR strGuid;
  400. LPOLESTR strSubscriptionID;
  401. LPOLESTR strEventClassID;
  402. WCHAR szQuery[MAX_QUERY_SIZE];
  403. BSTR bstrEventClassID;
  404. BSTR bstrInterfaceID;
  405. BSTR bstrPublisherID;
  406. BSTR bstrSubscriptionID;
  407. BSTR bstrSubscriptionName;
  408. BSTR bstrSubscriberCLSID;
  409. BSTR bstrMethodName;
  410. BSTR bstrPublisherPropertyName;
  411. BSTR bstrPublisherPropertyValue;
  412. VARIANT variantPublisherPropertyValue;
  413. BSTR bstrPROGID_EventSubscription;
  414. IEventSubscription *pIEventSubscription;
  415. hr = S_OK;
  416. strGuid = NULL;
  417. errorIndex = 0;
  418. strEventClassID = NULL;
  419. bstrEventClassID = NULL;
  420. bstrInterfaceID = NULL;
  421. bstrPublisherID = NULL;
  422. strSubscriptionID = NULL;
  423. bstrSubscriptionID = NULL;
  424. bstrSubscriberCLSID = NULL;
  425. bstrSubscriptionName = NULL;
  426. bstrMethodName = NULL;
  427. bstrPublisherPropertyName = NULL;
  428. bstrPublisherPropertyValue = NULL;
  429. bstrPROGID_EventSubscription = NULL;
  430. pIEventSubscription = NULL;
  431. AllocateBstrFromGuid(bstrPublisherID, SENSGUID_PUBLISHER);
  432. AllocateBstrFromGuid(bstrSubscriberCLSID, SENSGUID_SUBSCRIBER_LCE);
  433. AllocateBstrFromString(bstrPROGID_EventSubscription, PROGID_EventSubscription);
  434. for (i = 0; i < SENS_SUBSCRIPTIONS_COUNT; i++)
  435. {
  436. if (bUnregister)
  437. {
  438. // Form the query
  439. wcscpy(szQuery, SENS_BSTR("SubscriptionID"));
  440. wcscat(szQuery, SENS_BSTR("="));
  441. AllocateStrFromGuid(strSubscriptionID, *(gSensSubscriptions[i].pSubscriptionID));
  442. wcscat(szQuery, strSubscriptionID);
  443. hr = gpIEventSystem->Remove(
  444. PROGID_EventSubscription,
  445. szQuery,
  446. &errorIndex
  447. );
  448. FreeStr(strSubscriptionID);
  449. if (FAILED(hr))
  450. {
  451. SensPrintA(SENS_ERR, (SENS_SETUP "RegisterSensSubscriptionis(%d) failed to Remove"
  452. " - hr = <%x>\n", i, hr));
  453. goto Cleanup;
  454. }
  455. continue;
  456. }
  457. // Get a new IEventSubscription object to play with.
  458. hr = CoCreateInstance(
  459. CLSID_CEventSubscription,
  460. NULL,
  461. CLSCTX_SERVER,
  462. IID_IEventSubscription,
  463. (LPVOID *) &pIEventSubscription
  464. );
  465. if (FAILED(hr))
  466. {
  467. SensPrintA(SENS_ERR, (SENS_SETUP "RegisterSensSubscriptions(%d) failed to create "
  468. "IEventSubscriptions - hr = <%x>\n", i, hr));
  469. goto Cleanup;
  470. }
  471. AllocateBstrFromGuid(bstrSubscriptionID, *(gSensSubscriptions[i].pSubscriptionID));
  472. hr = pIEventSubscription->put_SubscriptionID(bstrSubscriptionID);
  473. ASSERT(SUCCEEDED(hr));
  474. hr = pIEventSubscription->put_PublisherID(bstrPublisherID);
  475. ASSERT(SUCCEEDED(hr));
  476. hr = pIEventSubscription->put_SubscriberCLSID(bstrSubscriberCLSID);
  477. ASSERT(SUCCEEDED(hr));
  478. AllocateBstrFromString(bstrSubscriptionName, gSensSubscriptions[i].strSubscriptionName);
  479. hr = pIEventSubscription->put_SubscriptionName(bstrSubscriptionName);
  480. ASSERT(SUCCEEDED(hr));
  481. AllocateBstrFromString(bstrMethodName, gSensSubscriptions[i].strMethodName);
  482. hr = pIEventSubscription->put_MethodName(bstrMethodName);
  483. ASSERT(SUCCEEDED(hr));
  484. AllocateBstrFromGuid(bstrEventClassID, *(gSensSubscriptions[i].pEventClassID));
  485. hr = pIEventSubscription->put_EventClassID(bstrEventClassID);
  486. ASSERT(SUCCEEDED(hr));
  487. AllocateBstrFromGuid(bstrInterfaceID, *(gSensSubscriptions[i].pInterfaceID));
  488. hr = pIEventSubscription->put_InterfaceID(bstrInterfaceID);
  489. ASSERT(SUCCEEDED(hr));
  490. if (gSensSubscriptions[i].bPublisherPropertyPresent == TRUE)
  491. {
  492. if (NULL != (gSensSubscriptions[i].pPropertyEventClassIDValue))
  493. {
  494. // Create the Query string.
  495. wcscpy(szQuery, gSensSubscriptions[i].strPropertyEventClassID);
  496. wcscat(szQuery, SENS_BSTR("="));
  497. AllocateStrFromGuid(strEventClassID, *(gSensSubscriptions[i].pPropertyEventClassIDValue));
  498. wcscat(szQuery, strEventClassID);
  499. wcscat(szQuery, SENS_BSTR(" AND "));
  500. wcscat(szQuery, gSensSubscriptions[i].strPropertyMethodName);
  501. wcscat(szQuery, SENS_BSTR("=\'"));
  502. wcscat(szQuery, gSensSubscriptions[i].strPropertyMethodNameValue);
  503. wcscat(szQuery, SENS_BSTR("\'"));
  504. AllocateBstrFromString(bstrPublisherPropertyName, SENS_BSTR("Criteria"));
  505. AllocateBstrFromString(bstrPublisherPropertyValue, szQuery);
  506. InitializeBstrVariant(&variantPublisherPropertyValue, bstrPublisherPropertyValue);
  507. hr = pIEventSubscription->PutPublisherProperty(
  508. bstrPublisherPropertyName,
  509. &variantPublisherPropertyValue
  510. );
  511. ASSERT(SUCCEEDED(hr));
  512. SensPrintA(SENS_INFO, (SENS_SETUP "PutPublisherProperty(Criteria) returned 0x%x\n", hr));
  513. FreeStr(strEventClassID);
  514. FreeBstr(bstrPublisherPropertyName);
  515. FreeBstr(bstrPublisherPropertyValue);
  516. }
  517. else
  518. {
  519. //
  520. // We are dealing with the "ANY" subscription of SENS.
  521. //
  522. // Create the Query string.
  523. wcscpy(szQuery, gSensSubscriptions[i].strPropertyEventClassID);
  524. wcscat(szQuery, SENS_BSTR("="));
  525. AllocateStrFromGuid(strEventClassID, SENSGUID_EVENTCLASS_NETWORK);
  526. wcscat(szQuery, strEventClassID);
  527. wcscat(szQuery, SENS_BSTR(" OR "));
  528. FreeStr(strEventClassID);
  529. wcscat(szQuery, gSensSubscriptions[i].strPropertyEventClassID);
  530. wcscat(szQuery, SENS_BSTR("="));
  531. AllocateStrFromGuid(strEventClassID, SENSGUID_EVENTCLASS_LOGON);
  532. wcscat(szQuery, strEventClassID);
  533. wcscat(szQuery, SENS_BSTR(" OR "));
  534. FreeStr(strEventClassID);
  535. wcscat(szQuery, gSensSubscriptions[i].strPropertyEventClassID);
  536. wcscat(szQuery, SENS_BSTR("="));
  537. AllocateStrFromGuid(strEventClassID, SENSGUID_EVENTCLASS_ONNOW);
  538. wcscat(szQuery, strEventClassID);
  539. FreeStr(strEventClassID);
  540. AllocateBstrFromString(bstrPublisherPropertyName, SENS_BSTR("Criteria"));
  541. AllocateBstrFromString(bstrPublisherPropertyValue, szQuery);
  542. InitializeBstrVariant(&variantPublisherPropertyValue, bstrPublisherPropertyValue);
  543. hr = pIEventSubscription->PutPublisherProperty(
  544. bstrPublisherPropertyName,
  545. &variantPublisherPropertyValue
  546. );
  547. ASSERT(SUCCEEDED(hr));
  548. SensPrintA(SENS_INFO, (SENS_SETUP "PutPublisherProperty(Criteria) returned 0x%x\n", hr));
  549. FreeBstr(bstrPublisherPropertyName);
  550. FreeBstr(bstrPublisherPropertyValue);
  551. }
  552. }
  553. FreeBstr(bstrSubscriptionID);
  554. FreeBstr(bstrSubscriptionName);
  555. FreeBstr(bstrMethodName);
  556. FreeBstr(bstrEventClassID);
  557. FreeBstr(bstrInterfaceID);
  558. hr = gpIEventSystem->Store(bstrPROGID_EventSubscription, pIEventSubscription);
  559. if (FAILED(hr))
  560. {
  561. SensPrintA(SENS_ERR, (SENS_SETUP "RegisterSensSubscriptions(%d) failed to Store"
  562. " - hr = <%x>\n", i, hr));
  563. goto Cleanup;
  564. }
  565. pIEventSubscription->Release();
  566. pIEventSubscription = NULL;
  567. } // for loop
  568. Cleanup:
  569. //
  570. // Cleanup
  571. //
  572. if (pIEventSubscription)
  573. {
  574. pIEventSubscription->Release();
  575. }
  576. FreeBstr(bstrPublisherID);
  577. FreeBstr(bstrSubscriberCLSID);
  578. FreeBstr(bstrPROGID_EventSubscription);
  579. FreeStr(strGuid);
  580. return (hr);
  581. }
  582. HRESULT
  583. RegisterSensTypeLibraries(
  584. BOOL bUnregister
  585. )
  586. /*++
  587. Routine Description:
  588. Register/Unregister the Type Libraries of SENS.
  589. Arguments:
  590. bUnregister - If TRUE, then unregister all subscriptions of SENS.
  591. Return Value:
  592. S_OK, if successful
  593. hr, otherwise
  594. --*/
  595. {
  596. HRESULT hr;
  597. UINT uiLength;
  598. TCHAR buffer[MAX_PATH+1+sizeof(SENS_BINARYA)+1]; // +1 for '\'
  599. WCHAR *bufferW;
  600. hr = S_OK;
  601. uiLength = 0;
  602. bufferW = NULL;
  603. //
  604. // Get the Full path name to the SENS TLB (which is a resource in SENS.EXE)
  605. //
  606. uiLength = GetSystemDirectory(
  607. buffer,
  608. MAX_PATH
  609. );
  610. if (uiLength == 0)
  611. {
  612. hr = HRESULT_FROM_WIN32(GetLastError());
  613. SensPrintA(SENS_ERR, (SENS_SETUP "GetSystemDirectory(%s) failed - hr = <%x>\n",
  614. SENS_TLBA, hr));
  615. goto Cleanup;
  616. }
  617. _tcscat(buffer, SENS_STRING("\\"));
  618. _tcscat(buffer, SENS_TLB);
  619. //
  620. // Convert the string to UNICODE, if necessary
  621. //
  622. #if !defined(SENS_CHICAGO)
  623. bufferW = buffer;
  624. #else // SENS_CHICAGO
  625. bufferW = SensAnsiStringToUnicode(buffer);
  626. if (NULL == bufferW)
  627. {
  628. goto Cleanup;
  629. }
  630. #endif // SENS_CHICAGO
  631. hr = LoadTypeLibEx(
  632. bufferW,
  633. REGKIND_NONE,
  634. &gpITypeLib
  635. );
  636. if (FAILED(hr))
  637. {
  638. SensPrintA(SENS_ERR, (SENS_SETUP "LoadTypeLib(%s) failed "
  639. " - hr = <%x>\n", SENS_TLBA, hr));
  640. goto Cleanup;
  641. }
  642. //
  643. // Ensure that the TypeLib is (un)registered
  644. //
  645. if (bUnregister)
  646. {
  647. hr = UnRegisterTypeLib(
  648. LIBID_SensEvents,
  649. MAJOR_VER,
  650. MINOR_VER,
  651. DEFAULT_LCID,
  652. SYS_WIN32
  653. );
  654. }
  655. else
  656. {
  657. hr = RegisterTypeLib(
  658. gpITypeLib,
  659. bufferW,
  660. NULL
  661. );
  662. }
  663. if (FAILED(hr))
  664. {
  665. SensPrintA(SENS_ERR, (SENS_SETUP "%sRegisterTypeLib(%s) failed "
  666. " - hr = <%x>\n", (bUnregister ? "Un" : ""), SENS_TLBA, hr));
  667. }
  668. Cleanup:
  669. //
  670. // Cleanup
  671. //
  672. #if defined(SENS_CHICAGO)
  673. if (bufferW != NULL)
  674. {
  675. delete bufferW;
  676. }
  677. #endif // SENS_CHICAGO
  678. return (hr);
  679. }
  680. HRESULT
  681. RegisterSensCLSID(
  682. REFIID clsid,
  683. TCHAR* strSubscriberName,
  684. BOOL bUnregister
  685. )
  686. /*++
  687. Routine Description:
  688. Register/Unregister the CLSID of SENS.
  689. Arguments:
  690. clsid - CLSID of the Subscriber for LCE events.
  691. strSubscriberName - Name of the Subscriber.
  692. bUnregister - If TRUE, then unregister the CLSID of SENS.
  693. Notes:
  694. This function also registers SENS to receive IE5's WININET events.
  695. Return Value:
  696. S_OK, if successful
  697. hr, otherwise
  698. --*/
  699. {
  700. HRESULT hr;
  701. HMODULE hModule;
  702. HKEY appidKey;
  703. HKEY clsidKey;
  704. HKEY serverKey;
  705. WCHAR *szCLSID;
  706. WCHAR *szCLSID2;
  707. WCHAR *szLIBID;
  708. TCHAR *szCLSID_t;
  709. TCHAR *szCLSID2_t;
  710. TCHAR *szLIBID_t;
  711. TCHAR *szFriendlyName;
  712. TCHAR szPath[MAX_PATH+1+sizeof(SENS_BINARYA)+1]; // +1 for '\'
  713. UINT uiLength;
  714. DWORD dwDisposition;
  715. LONG lResult;
  716. hr = S_OK;
  717. appidKey = NULL;
  718. clsidKey = NULL;
  719. serverKey = NULL;
  720. szCLSID = NULL;
  721. szCLSID2 = NULL;
  722. szLIBID = NULL;
  723. szCLSID_t = NULL;
  724. szCLSID2_t = NULL;
  725. szLIBID_t = NULL;
  726. uiLength = 0;
  727. dwDisposition = 0x0;
  728. szFriendlyName = strSubscriberName;
  729. //
  730. // Get the Full path name to the SENS executable
  731. //
  732. uiLength = GetSystemDirectory(
  733. szPath,
  734. MAX_PATH
  735. );
  736. if (uiLength == 0)
  737. {
  738. hr = HRESULT_FROM_WIN32(GetLastError());
  739. SensPrintA(SENS_ERR, (SENS_SETUP "GetSystemDirectory(%s) failed - hr = <%x>\n",
  740. SENS_BINARYA, hr));
  741. goto Cleanup;
  742. }
  743. _tcscat(szPath, SENS_STRING("\\"));
  744. _tcscat(szPath, SENS_BINARY);
  745. //
  746. // Convert the CLSID into a WCHAR.
  747. //
  748. hr = StringFromCLSID(clsid, &szCLSID);
  749. if (FAILED(hr))
  750. {
  751. goto Cleanup;
  752. }
  753. if (bUnregister == FALSE)
  754. {
  755. hr = StringFromCLSID(LIBID_SensEvents, &szLIBID);
  756. if (FAILED(hr))
  757. {
  758. goto Cleanup;
  759. }
  760. }
  761. //
  762. // Convert UNICODE strings into ANSI, if necessary
  763. //
  764. #if !defined(SENS_CHICAGO)
  765. szCLSID_t = szCLSID;
  766. szLIBID_t = szLIBID;
  767. #else // SENS_CHICAGO
  768. szCLSID_t = SensUnicodeStringToAnsi(szCLSID);
  769. szLIBID_t = SensUnicodeStringToAnsi(szLIBID);
  770. if ( (NULL == szCLSID_t)
  771. || (NULL == szLIBID_t))
  772. {
  773. goto Cleanup;
  774. }
  775. #endif // SENS_CHICAGO
  776. // Build the key CLSID\\{clsid}
  777. TCHAR clsidKeyName[sizeof "CLSID\\{12345678-1234-1234-1234-123456789012}"];
  778. _tcscpy(clsidKeyName, SENS_STRING("CLSID\\"));
  779. _tcscat(clsidKeyName, szCLSID_t);
  780. // Build the key AppID\\{clsid}
  781. TCHAR appidKeyName[sizeof "AppID\\{12345678-1234-1234-1234-123456789012}"];
  782. _tcscpy(appidKeyName, SENS_STRING("AppID\\"));
  783. _tcscat(appidKeyName, szCLSID_t);
  784. if (bUnregister)
  785. {
  786. hr = RecursiveDeleteKey(HKEY_CLASSES_ROOT, clsidKeyName);
  787. if (FAILED(hr))
  788. {
  789. goto Cleanup;
  790. }
  791. hr = RecursiveDeleteKey(HKEY_CLASSES_ROOT, appidKeyName);
  792. goto Cleanup;
  793. }
  794. // Create the CLSID\\{clsid} key
  795. hr = CreateKey(
  796. HKEY_CLASSES_ROOT,
  797. clsidKeyName,
  798. szFriendlyName,
  799. &clsidKey
  800. );
  801. if (FAILED(hr))
  802. {
  803. goto Cleanup;
  804. }
  805. //
  806. // Under the CLSID\\{clsid} key, create a named value
  807. // AppID = {clsid}
  808. hr = CreateNamedValue(clsidKey, SENS_STRING("AppID"), szCLSID_t);
  809. if (FAILED(hr))
  810. {
  811. goto Cleanup;
  812. }
  813. //
  814. // Create the appropriate server key beneath the clsid key.
  815. // For servers, this is CLSID\\{clsid}\\LocalServer32.
  816. // In both cases, the default value is the module path name.
  817. //
  818. hr = CreateKey(
  819. clsidKey,
  820. SENS_STRING("LocalServer32"),
  821. szPath,
  822. &serverKey
  823. );
  824. if (FAILED(hr))
  825. {
  826. goto Cleanup;
  827. }
  828. RegCloseKey(serverKey);
  829. //
  830. // Create CLSID\\{clsid}\\TypeLib subkey with a default value of
  831. // the LIBID of the TypeLib
  832. //
  833. hr = CreateKey(
  834. clsidKey,
  835. SENS_STRING("TypeLib"),
  836. szLIBID_t,
  837. &serverKey
  838. );
  839. if (FAILED(hr))
  840. {
  841. goto Cleanup;
  842. }
  843. RegCloseKey(serverKey);
  844. // Register APPID.
  845. hr = CreateKey(
  846. HKEY_CLASSES_ROOT,
  847. appidKeyName,
  848. szFriendlyName,
  849. &appidKey
  850. );
  851. if (FAILED(hr))
  852. {
  853. goto Cleanup;
  854. }
  855. #if !defined(SENS_CHICAGO)
  856. // Under AppId\{clsid} key, create a named value [LocalService = "SENS"]
  857. hr = CreateNamedValue(appidKey, SENS_STRING("LocalService"), SENS_STRING("SENS"));
  858. if (FAILED(hr))
  859. {
  860. goto Cleanup;
  861. }
  862. #else // SENS_CHICAGO
  863. // Under AppId\{clsid} key, create a named value [RunAs = "Interactive User"]
  864. hr = CreateNamedValue(appidKey, SENS_STRING("RunAs"), SENS_STRING("Interactive User"));
  865. if (FAILED(hr))
  866. {
  867. goto Cleanup;
  868. }
  869. #endif // SENS_CHICAGO
  870. Cleanup:
  871. //
  872. // Cleanup
  873. //
  874. CoTaskMemFree(szCLSID);
  875. CoTaskMemFree(szLIBID);
  876. if (clsidKey != NULL)
  877. {
  878. RegCloseKey(clsidKey);
  879. }
  880. if (appidKey != NULL)
  881. {
  882. RegCloseKey(appidKey);
  883. }
  884. #if defined(SENS_CHICAGO)
  885. if (szCLSID_t != NULL)
  886. {
  887. delete szCLSID_t;
  888. }
  889. if (szLIBID_t != NULL)
  890. {
  891. delete szLIBID_t;
  892. }
  893. #endif // SENS_CHICAGO
  894. return hr;
  895. }
  896. #if defined(SENS_NT4)
  897. HRESULT
  898. RegisterSensAsService(
  899. BOOL bUnregister
  900. )
  901. /*++
  902. Routine Description:
  903. Configure SENS as a Win32 System service.
  904. Arguments:
  905. bUnregister - If TRUE, then unregister SENS as a service.
  906. Return Value:
  907. S_OK, if successful
  908. hr, otherwise
  909. --*/
  910. {
  911. HRESULT hr;
  912. hr = S_OK;
  913. if (bUnregister)
  914. {
  915. hr = RemoveService();
  916. }
  917. else
  918. {
  919. hr = InstallService();
  920. }
  921. return hr;
  922. }
  923. HRESULT
  924. InstallService(
  925. void
  926. )
  927. /*++
  928. Routine Description:
  929. Install SENS as a service with the Service Control Manager.
  930. Arguments:
  931. None.
  932. Return Value:
  933. S_OK, if successful
  934. hr, otherwise
  935. --*/
  936. {
  937. HRESULT hr;
  938. TCHAR szPath[MAX_PATH+1+sizeof(SENS_BINARYA)+1]; // +1 for '\'
  939. LPTSTR pFilePart;
  940. UINT uiLength;
  941. SC_HANDLE hSCM;
  942. SC_HANDLE hSens;
  943. hr = S_OK;
  944. pFilePart = NULL;
  945. uiLength = 0;
  946. hSCM = NULL;
  947. hSens = NULL;
  948. //
  949. // Get the Full path name to the SENS executable
  950. //
  951. uiLength = GetSystemDirectory(
  952. szPath,
  953. MAX_PATH
  954. );
  955. if (uiLength == 0)
  956. {
  957. hr = HRESULT_FROM_WIN32(GetLastError());
  958. SensPrintA(SENS_ERR, (SENS_SETUP "GetSystemDirectory(%s) failed - hr = <%x>\n",
  959. SENS_BINARYA, hr));
  960. goto Cleanup;
  961. }
  962. _tcscat(szPath, SENS_STRING("\\"));
  963. _tcscat(szPath, SENS_BINARY);
  964. //
  965. // Register ourselves with the SCM
  966. //
  967. // Open the SCM for the local machine.
  968. hSCM = OpenSCManager(
  969. NULL,
  970. NULL,
  971. SC_MANAGER_ALL_ACCESS
  972. );
  973. if (NULL == hSCM)
  974. {
  975. hr = HRESULT_FROM_WIN32(GetLastError());
  976. SensPrint(SENS_ERR, (SENS_SETUPW SENS_STRING("OpenSCManager(%s) failed - hr = <%x>\n"),
  977. SENS_SERVICE, hr));
  978. goto Cleanup;
  979. }
  980. hSens = CreateService(
  981. hSCM, // Handle to SCM
  982. SENS_SERVICE, // Name of the service executable
  983. SENS_DISPLAY_NAME, // Service Display name
  984. SERVICE_ALL_ACCESS, // Access to the service
  985. SERVICE_WIN32_OWN_PROCESS, // Type of the service
  986. SERVICE_DEMAND_START, // Start type of the service
  987. SERVICE_ERROR_NORMAL, // Severity of the error during startup
  988. szPath, // Binary path name
  989. SENS_SERVICE_GROUP, // Load ordering group
  990. NULL, // No tag identifier
  991. SENS_STRING("EventSystem\0"), // Dependencies
  992. NULL, // LocalSystem account
  993. NULL // No password
  994. );
  995. if (NULL == hSens)
  996. {
  997. if (GetLastError() != ERROR_SERVICE_EXISTS)
  998. {
  999. hr = HRESULT_FROM_WIN32(GetLastError());
  1000. SensPrint(SENS_ERR, (SENS_SETUPW SENS_STRING("CreateService(%s) failed - hr = <%x>\n"),
  1001. SENS_SERVICE, hr));
  1002. }
  1003. else
  1004. {
  1005. SensPrint(SENS_WARN, (SENS_SETUPW SENS_STRING("SENS service is already installed.\n")));
  1006. BOOL bRetValue;
  1007. //
  1008. // Get a handle to SCM
  1009. //
  1010. hSens = OpenService(
  1011. hSCM,
  1012. SENS_SERVICE,
  1013. SERVICE_ALL_ACCESS
  1014. );
  1015. if (NULL == hSens)
  1016. {
  1017. hr = HRESULT_FROM_WIN32(GetLastError());
  1018. goto Cleanup;
  1019. }
  1020. //
  1021. // Mark the service to demand-start by default.
  1022. // NULL parameter implies no change.
  1023. //
  1024. bRetValue = ChangeServiceConfig(
  1025. hSens, // Handle to service
  1026. SERVICE_NO_CHANGE, // Type of service
  1027. SERVICE_DEMAND_START, // When to start service
  1028. SERVICE_NO_CHANGE, // Severity if service fails to start
  1029. NULL, // Pointer to service binary file name
  1030. NULL, // Pointer to load ordering group name
  1031. NULL, // Pointer to variable to get tag identifier
  1032. NULL, // Pointer to array of dependency names
  1033. NULL, // Pointer to account name of service
  1034. NULL, // Pointer to password for service account
  1035. NULL // Pointer to display name
  1036. );
  1037. if (FALSE == bRetValue)
  1038. {
  1039. hr = HRESULT_FROM_WIN32(GetLastError());
  1040. }
  1041. SensPrint(SENS_ERR, (SENS_SETUPW SENS_STRING("ChangeServiceConfig(%s)")
  1042. SENS_STRING(" returned hr - <%x>\n"), SENS_SERVICE, hr));
  1043. }
  1044. goto Cleanup;
  1045. }
  1046. SensPrint(SENS_INFO, (SENS_SETUPW SENS_STRING("SENS service successfully installed.\n")));
  1047. Cleanup:
  1048. //
  1049. // Cleanup
  1050. //
  1051. if (hSens != NULL)
  1052. {
  1053. //
  1054. // Give everyone the ability to start the service.
  1055. //
  1056. hr = SetServiceWorldAccessMask(hSens, SERVICE_START);
  1057. SensPrint(SENS_ERR, (SENS_SETUPW SENS_STRING("SerServiceWorldAccessMask(%s)")
  1058. SENS_STRING(" returned hr - <%x>\n"), SENS_SERVICE, hr));
  1059. CloseServiceHandle(hSens);
  1060. }
  1061. if (hSCM != NULL)
  1062. {
  1063. CloseServiceHandle(hSCM);
  1064. }
  1065. return hr;
  1066. }
  1067. HRESULT
  1068. RemoveService(
  1069. void
  1070. )
  1071. /*++
  1072. Routine Description:
  1073. Remove SENS as a service.
  1074. Arguments:
  1075. None.
  1076. Return Value:
  1077. S_OK, if successful
  1078. hr, otherwise
  1079. --*/
  1080. {
  1081. HRESULT hr;
  1082. SC_HANDLE hSCM;
  1083. SC_HANDLE hSens;
  1084. BOOL bSuccess;
  1085. SERVICE_STATUS SvcStatus;
  1086. hr = S_OK;
  1087. hSCM = NULL;
  1088. hSens = NULL;
  1089. bSuccess = FALSE;
  1090. //
  1091. // Unregister ourselves from the SCM
  1092. //
  1093. // Open the SCM for the local machine.
  1094. hSCM = OpenSCManager(
  1095. NULL,
  1096. NULL,
  1097. SC_MANAGER_ALL_ACCESS
  1098. );
  1099. if (NULL == hSCM)
  1100. {
  1101. hr = HRESULT_FROM_WIN32(GetLastError());
  1102. SensPrint(SENS_ERR, (SENS_SETUPW SENS_STRING("OpenSCManager() failed - hr = <%x>\n"), hr));
  1103. goto Cleanup;
  1104. }
  1105. hSens = OpenService(
  1106. hSCM,
  1107. SENS_SERVICE,
  1108. SERVICE_ALL_ACCESS
  1109. );
  1110. if (NULL == hSens)
  1111. {
  1112. hr = HRESULT_FROM_WIN32(GetLastError());
  1113. SensPrint(SENS_ERR, (SENS_SETUPW SENS_STRING("OpenService(%s) failed - hr = <%x>\n"),
  1114. SENS_SERVICE, hr));
  1115. goto Cleanup;
  1116. }
  1117. //
  1118. // Try to stop the service
  1119. //
  1120. bSuccess = ControlService(
  1121. hSens,
  1122. SERVICE_CONTROL_STOP,
  1123. &SvcStatus
  1124. );
  1125. if (bSuccess == TRUE)
  1126. {
  1127. SensPrint(SENS_INFO, (SENS_SETUPW SENS_STRING("Stopping %s."), SENS_SERVICE));
  1128. do
  1129. {
  1130. Sleep(1000);
  1131. if (SvcStatus.dwCurrentState == SERVICE_STOP_PENDING)
  1132. {
  1133. SensPrint(SENS_INFO, (SENS_STRING(".")));
  1134. }
  1135. else
  1136. {
  1137. SensPrint(SENS_INFO, (SENS_STRING("\n")));
  1138. break;
  1139. }
  1140. }
  1141. while (QueryServiceStatus(hSens, &SvcStatus));
  1142. if (SvcStatus.dwCurrentState == SERVICE_STOPPED)
  1143. {
  1144. SensPrint(SENS_INFO, (SENS_SETUPW SENS_STRING("\n%s stopped.\n"), SENS_SERVICE));
  1145. }
  1146. else
  1147. {
  1148. SensPrint(SENS_ERR, (SENS_SETUPW SENS_STRING("\n%s failed to stop.\n"), SENS_SERVICE));
  1149. }
  1150. }
  1151. //
  1152. // Now, remove the service
  1153. //
  1154. if (DeleteService(hSens))
  1155. {
  1156. SensPrint(SENS_INFO, (SENS_SETUPW SENS_STRING("%s removed.\n"), SENS_SERVICE));
  1157. }
  1158. else
  1159. {
  1160. hr = HRESULT_FROM_WIN32(GetLastError());
  1161. SensPrint(SENS_ERR, (SENS_SETUPW SENS_STRING("%s removal failed.\n"), SENS_SERVICE));
  1162. }
  1163. Cleanup:
  1164. //
  1165. // Cleanup
  1166. //
  1167. if (hSens != NULL)
  1168. {
  1169. CloseServiceHandle(hSens);
  1170. }
  1171. if (hSCM != NULL)
  1172. {
  1173. CloseServiceHandle(hSCM);
  1174. }
  1175. return hr;
  1176. }
  1177. HRESULT
  1178. SetServiceWorldAccessMask(
  1179. SC_HANDLE hService,
  1180. DWORD dwAccessMask
  1181. )
  1182. /*++
  1183. Routine Description:
  1184. Add the access rights specified in the dwAccessMask to Everyone (World)
  1185. with respect to this service. This was written to add SERVICE_START right
  1186. to Everyone wrt SENS.
  1187. Arguments:
  1188. hService - The service in question.
  1189. dwAccessMask - The desired access rights to be set.
  1190. Notes:
  1191. a. This code assumes that the WorldSid is present in the DACL of SENS
  1192. service. This is true for NT4.
  1193. b. This a security hole. This security hole is not going to be plugged
  1194. in future Service Packs of NT4 since some applications will break.
  1195. c. This code needs to be modified to make it work on NT5.
  1196. Return Value:
  1197. S_OK, if successful.
  1198. HRESULT, on failure.
  1199. --*/
  1200. {
  1201. int i;
  1202. PSID pWorldSid;
  1203. SID_IDENTIFIER_AUTHORITY WorldAuthority = SECURITY_WORLD_SID_AUTHORITY;
  1204. DWORD dwError;
  1205. DWORD dwSize;
  1206. PSECURITY_DESCRIPTOR pSD;
  1207. PACL pDacl;
  1208. BOOL bStatus;
  1209. BOOL bDaclPresent;
  1210. BOOL bDaclDefaulted;
  1211. PACCESS_ALLOWED_ACE pAce;
  1212. i = 0;
  1213. pWorldSid = NULL;
  1214. pSD = NULL;
  1215. pDacl = NULL;
  1216. dwSize = 0x0;
  1217. dwError = ERROR_SUCCESS;
  1218. bStatus = FALSE;
  1219. bDaclPresent = FALSE;
  1220. bDaclDefaulted = FALSE;
  1221. pAce = NULL;
  1222. //
  1223. // Allocate WorldSid
  1224. //
  1225. bStatus = AllocateAndInitializeSid(
  1226. &WorldAuthority, // Pointer to identifier authority
  1227. 1, // Count of subauthority
  1228. SECURITY_WORLD_RID, // Subauthority 0
  1229. 0, // Subauthority 1
  1230. 0, // Subauthority 2
  1231. 0, // Subauthority 3
  1232. 0, // Subauthority 4
  1233. 0, // Subauthority 5
  1234. 0, // Subauthority 6
  1235. 0, // Subauthority 7
  1236. &pWorldSid // pointer to pointer to SID
  1237. );
  1238. if (FALSE == bStatus)
  1239. {
  1240. dwError = GetLastError();
  1241. SensPrintA(SENS_ERR, ("SetServiceWorldAccessMask(): AllocateAndInitiali"
  1242. "zeSid() failed with %d.\n", dwError));
  1243. goto Cleanup;
  1244. }
  1245. //
  1246. // Figure out how much buffer is needed for holding the service's
  1247. // Security Descriptor (SD).
  1248. //
  1249. // NOTE: We pass &pSD instead of pSD because this parameter should
  1250. // not be NULL. For this call to QueryServiceObjectSecurity()
  1251. // we just need to pass some non-zero and valid buffer.
  1252. //
  1253. bStatus = QueryServiceObjectSecurity(
  1254. hService, // Handle of the service
  1255. DACL_SECURITY_INFORMATION, // Type of info requested
  1256. &pSD, // Address of Security descriptor
  1257. 0, // Size of SD buffer
  1258. &dwSize // Size of buffer needed
  1259. );
  1260. if ( (TRUE == bStatus)
  1261. || (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
  1262. {
  1263. dwError = GetLastError();
  1264. SensPrintA(SENS_ERR, ("SetServiceWorldAccessMask(): QueryServiceObject"
  1265. "Security() returned unexpected result - %d.\n", dwError));
  1266. goto Cleanup;
  1267. }
  1268. //
  1269. // Allocate the SD
  1270. //
  1271. pSD = (PSECURITY_DESCRIPTOR) new char[dwSize];
  1272. if (NULL == pSD)
  1273. {
  1274. dwError = ERROR_OUTOFMEMORY;
  1275. SensPrintA(SENS_ERR, ("SetServiceWorldAccessMask(): Failed to allocate"
  1276. "memory for a Security Descriptor.\n"));
  1277. goto Cleanup;
  1278. }
  1279. //
  1280. // Now, we are ready to get the service's SD.
  1281. //
  1282. bStatus = QueryServiceObjectSecurity(
  1283. hService, // Handle of the service
  1284. DACL_SECURITY_INFORMATION, // Type of info requested
  1285. pSD, // Address of Security descriptor
  1286. dwSize, // Size of SD buffer
  1287. &dwSize // Size of buffer needed
  1288. );
  1289. if (FALSE == bStatus)
  1290. {
  1291. dwError = GetLastError();
  1292. ASSERT(dwError != ERROR_INSUFFICIENT_BUFFER);
  1293. SensPrintA(SENS_ERR, ("SetServiceWorldAccessMask(): QueryServiceObject"
  1294. "Security() failed with %d.\n", dwError));
  1295. goto Cleanup;
  1296. }
  1297. //
  1298. // Get the DACL from SD, if present.
  1299. //
  1300. bStatus = GetSecurityDescriptorDacl(
  1301. pSD, // Address of SD
  1302. &bDaclPresent, // Address of flag for presence of DACL
  1303. &pDacl, // Address of pointer to DACL
  1304. &bDaclDefaulted // Address of flag that indicates if
  1305. ); // DACL was defaulted.
  1306. if (FALSE == bStatus)
  1307. {
  1308. dwError = GetLastError();
  1309. SensPrintA(SENS_ERR, ("SetServiceWorldAccessMask(): GetSecurityDescriptor"
  1310. "Dacl() failed with %d.\n", dwError));
  1311. goto Cleanup;
  1312. }
  1313. //
  1314. // For a service, we always expect to see a DACL.
  1315. //
  1316. ASSERT(bDaclPresent && (pDacl != NULL));
  1317. if ( (FALSE == bDaclPresent)
  1318. || (NULL == pDacl))
  1319. {
  1320. dwError = E_UNEXPECTED;
  1321. SensPrintA(SENS_ERR, ("SetServiceWorldAccessMask(): DACL is not present"
  1322. "or DACL is NULL. Returning %d.\n", dwError));
  1323. goto Cleanup;
  1324. }
  1325. //
  1326. // Find the WorldSid ACE in the ACL and update it's Mask.
  1327. //
  1328. for (i = 0; i < pDacl->AceCount; i++)
  1329. {
  1330. bStatus = GetAce(
  1331. pDacl, // pointer to ACL
  1332. i, // index of ACE to retrieve
  1333. (LPVOID*) &pAce // pointer to pointer to ACE
  1334. );
  1335. if (FALSE == bStatus)
  1336. {
  1337. dwError = GetLastError();
  1338. SensPrintA(SENS_ERR, ("SetServiceWorldAccessMask(): GetAce()"
  1339. "failed with %d.\n", dwError));
  1340. goto Cleanup;
  1341. }
  1342. if (EqualSid(pWorldSid, &(pAce->SidStart)))
  1343. {
  1344. pAce->Mask |= dwAccessMask;
  1345. }
  1346. } // for ()
  1347. //
  1348. // Set the new SD on the service handle
  1349. //
  1350. bStatus = SetServiceObjectSecurity(
  1351. hService, // Handle to the service.
  1352. DACL_SECURITY_INFORMATION, // Type of info being set
  1353. pSD // Address of the new SD
  1354. );
  1355. if (FALSE == bStatus)
  1356. {
  1357. dwError = GetLastError();
  1358. SensPrintA(SENS_ERR, ("SetServiceWorldAccessMask(): SetServiceObject"
  1359. "Security() failed with %d.\n", dwError));
  1360. goto Cleanup;
  1361. }
  1362. Cleanup:
  1363. //
  1364. // Cleanup
  1365. //
  1366. if (NULL != pWorldSid)
  1367. {
  1368. FreeSid(pWorldSid);
  1369. }
  1370. if (NULL != pSD)
  1371. {
  1372. delete pSD;
  1373. }
  1374. return HRESULT_FROM_WIN32(dwError);
  1375. }
  1376. void CALLBACK
  1377. MarkSensAsDemandStart(
  1378. HWND hwnd,
  1379. HINSTANCE hinst,
  1380. LPSTR lpszCmdLine,
  1381. int nCmdShow
  1382. )
  1383. /*++
  1384. Routine Description:
  1385. A function compatible with RunDll32 that will mark SENS as manual start.
  1386. Arguments:
  1387. hwnd - Window handle that should be used as the owner window for
  1388. any windows this DLL creates.
  1389. hinst - This DLL's instance handle
  1390. lpszCmdLine - ASCII command line the DLL should parse
  1391. nCmdShow - Describes how the DLL's windows should be displayed
  1392. Return Value:
  1393. None.
  1394. --*/
  1395. {
  1396. SC_HANDLE hSCM;
  1397. SC_HANDLE hSens;
  1398. BOOL bStatus;
  1399. DWORD dwError;
  1400. SERVICE_STATUS ServiceStatus;
  1401. bStatus = FALSE;
  1402. dwError = ERROR_SUCCESS;
  1403. #ifdef DBG
  1404. EnableDebugOutputIfNecessary();
  1405. #endif // DBG
  1406. hSCM = OpenSCManager(
  1407. NULL, // Local machine
  1408. NULL, // Default database - SERVICES_ACTIVE_DATABASE
  1409. SC_MANAGER_ALL_ACCESS // NT4 NOTE: Only for Administrators.
  1410. );
  1411. if (NULL == hSCM)
  1412. {
  1413. dwError = GetLastError();
  1414. SensPrintA(SENS_ERR, (SENS_SETUP "OpenSCManager() failed with 0x%x\n", dwError));
  1415. goto Cleanup;
  1416. }
  1417. //
  1418. // Get a handle to SCM
  1419. //
  1420. hSens = OpenService(
  1421. hSCM, // Handle to SCM database
  1422. SENS_SERVICE, // Name of the service in question
  1423. SERVICE_ALL_ACCESS // Type of access requested to the service
  1424. );
  1425. if (NULL == hSens)
  1426. {
  1427. dwError = GetLastError();
  1428. SensPrintA(SENS_ERR, (SENS_SETUP "OpenService() failed with 0x%x\n", dwError));
  1429. goto Cleanup;
  1430. }
  1431. //
  1432. // Mark the service to Manual. NULL parameter implies no change.
  1433. //
  1434. bStatus = ChangeServiceConfig(
  1435. hSens, // Handle to service
  1436. SERVICE_NO_CHANGE, // Type of service
  1437. SERVICE_DEMAND_START, // When to start service
  1438. SERVICE_NO_CHANGE, // Severity if service fails to start
  1439. NULL, // Pointer to service binary file name
  1440. NULL, // Pointer to load ordering group name
  1441. NULL, // Pointer to variable to get tag identifier
  1442. NULL, // Pointer to array of dependency names
  1443. NULL, // Pointer to account name of service
  1444. NULL, // Pointer to password for service account
  1445. NULL // Pointer to display name
  1446. );
  1447. if (FALSE == bStatus)
  1448. {
  1449. dwError = GetLastError();
  1450. SensPrintA(SENS_ERR, (SENS_SETUP "ChangeServiceConfig() failed with 0x%x\n", dwError));
  1451. goto Cleanup;
  1452. }
  1453. SensPrintA(SENS_ERR, (SENS_SETUP "SENS now marked as DEMAND START\n\n"));
  1454. Cleanup:
  1455. //
  1456. // Cleanup
  1457. //
  1458. if (NULL != hSCM)
  1459. {
  1460. CloseServiceHandle(hSCM);
  1461. }
  1462. if (NULL != hSens)
  1463. {
  1464. CloseServiceHandle(hSens);
  1465. }
  1466. }
  1467. #endif // SENS_NT4
  1468. HRESULT
  1469. CreateKey(
  1470. HKEY hParentKey,
  1471. const TCHAR* KeyName,
  1472. const TCHAR* defaultValue,
  1473. HKEY* hKey
  1474. )
  1475. /*++
  1476. Routine Description:
  1477. Create a key (with an optional default value). The handle to the key is
  1478. returned as an [out] parameter. If NULL is passed as the key parameter,
  1479. the key is created in the registry, then closed.
  1480. Arguments:
  1481. hParentKey - Handle to the parent Key.
  1482. KeyName - Name of the key to create.
  1483. defaultValue - The default value for the key to create.
  1484. hKey - OUT Handle to key that was created.
  1485. Return Value:
  1486. S_OK, if successful
  1487. hr, otherwise
  1488. --*/
  1489. {
  1490. HKEY hTempKey;
  1491. LONG lResult;
  1492. hTempKey = NULL;
  1493. lResult = RegCreateKeyEx(
  1494. hParentKey, // Handle to open key
  1495. KeyName, // Subkey name
  1496. 0, // Reserved
  1497. NULL, // Class string
  1498. REG_OPTION_NON_VOLATILE, // Options Flag
  1499. KEY_ALL_ACCESS, // Desired Security access
  1500. NULL, // Pointer to Security Attributes structure
  1501. &hTempKey, // Handle of the opened/created key
  1502. NULL // Disposition value
  1503. );
  1504. if (lResult != ERROR_SUCCESS)
  1505. {
  1506. return HRESULT_FROM_WIN32(lResult);
  1507. }
  1508. // Set the default value for the key
  1509. if (defaultValue != NULL)
  1510. {
  1511. lResult = RegSetValueEx(
  1512. hTempKey, // Key to set Value for.
  1513. NULL, // Value to set
  1514. 0, // Reserved
  1515. REG_SZ, // Value Type
  1516. (BYTE*) defaultValue, // Address of Value data
  1517. sizeof(TCHAR) * (_tcslen(defaultValue)+1) // Size of Value
  1518. );
  1519. if (lResult != ERROR_SUCCESS)
  1520. {
  1521. RegCloseKey(hTempKey);
  1522. return HRESULT_FROM_WIN32(lResult);
  1523. }
  1524. }
  1525. if (hKey == NULL)
  1526. {
  1527. RegCloseKey(hTempKey);
  1528. }
  1529. else
  1530. {
  1531. *hKey = hTempKey;
  1532. }
  1533. return S_OK;
  1534. }
  1535. HRESULT
  1536. CreateNamedValue(
  1537. HKEY hKey,
  1538. const TCHAR* title,
  1539. const TCHAR* value
  1540. )
  1541. /*++
  1542. Routine Description:
  1543. Create a named value under a key
  1544. Arguments:
  1545. hKey - Handle to the parent Key.
  1546. title - Name of the Value to create.
  1547. value - The data for the Value under the Key.
  1548. Return Value:
  1549. S_OK, if successful
  1550. hr, otherwise
  1551. --*/
  1552. {
  1553. HRESULT hr;
  1554. LONG lResult;
  1555. hr = S_OK;
  1556. lResult = RegSetValueEx(
  1557. hKey, // Key to set Value for.
  1558. title, // Value to set
  1559. 0, // Reserved
  1560. REG_SZ, // Value Type
  1561. (BYTE*) value, // Address of Value data
  1562. sizeof(TCHAR) * (_tcslen(value)+1) // Size of Value
  1563. );
  1564. if (lResult != ERROR_SUCCESS)
  1565. {
  1566. hr = HRESULT_FROM_WIN32(lResult);
  1567. }
  1568. return hr;
  1569. }
  1570. HRESULT
  1571. CreateNamedDwordValue(
  1572. HKEY hKey,
  1573. const TCHAR* title,
  1574. DWORD dwValue
  1575. )
  1576. /*++
  1577. Routine Description:
  1578. Create a named DWORD value under a key
  1579. Arguments:
  1580. hKey - Handle to the parent Key.
  1581. title - Name of the Value to create.
  1582. dwValue - The data for the Value under the Key.
  1583. Return Value:
  1584. S_OK, if successful
  1585. hr, otherwise
  1586. --*/
  1587. {
  1588. HRESULT hr;
  1589. LONG lResult;
  1590. hr = S_OK;
  1591. lResult = RegSetValueEx(
  1592. hKey, // Key to set Value for.
  1593. title, // Value to set
  1594. 0, // Reserved
  1595. REG_DWORD, // Value Type
  1596. (BYTE*) &dwValue, // Address of Value data
  1597. sizeof(DWORD) // Size of Value
  1598. );
  1599. if (lResult != ERROR_SUCCESS)
  1600. {
  1601. hr = HRESULT_FROM_WIN32(lResult);
  1602. }
  1603. return hr;
  1604. }
  1605. HRESULT
  1606. RecursiveDeleteKey(
  1607. HKEY hKeyParent,
  1608. const TCHAR* lpszKeyChild
  1609. )
  1610. /*++
  1611. Routine Description:
  1612. Delete a key and all of its descendents.
  1613. Arguments:
  1614. hKeyParent - Handle to the parent Key.
  1615. lpszKeyChild - The data for the Value under the Key.
  1616. Return Value:
  1617. S_OK, if successful
  1618. hr, otherwise
  1619. --*/
  1620. {
  1621. HKEY hKeyChild;
  1622. LONG lResult;
  1623. //
  1624. // Open the child.
  1625. //
  1626. lResult = RegOpenKeyEx(
  1627. hKeyParent, // Handle to the Parent
  1628. lpszKeyChild, // Name of the child key
  1629. 0, // Reserved
  1630. KEY_ALL_ACCESS, // Security Access Mask
  1631. &hKeyChild // Handle to the opened key
  1632. );
  1633. if (lResult != ERROR_SUCCESS)
  1634. {
  1635. return HRESULT_FROM_WIN32(lResult);
  1636. }
  1637. //
  1638. // Enumerate all of the decendents of this child.
  1639. //
  1640. FILETIME time;
  1641. TCHAR szBuffer[MAX_PATH+1];
  1642. const DWORD bufSize = sizeof szBuffer / sizeof szBuffer[0];
  1643. DWORD dwSize = bufSize;
  1644. while (TRUE)
  1645. {
  1646. lResult = RegEnumKeyEx(
  1647. hKeyChild, // Handle of the key to enumerate
  1648. 0, // Index of the subkey to retrieve
  1649. szBuffer, // OUT Name of the subkey
  1650. &dwSize, // OUT Size of the buffer for name of subkey
  1651. NULL, // Reserved
  1652. NULL, // OUT Class of the enumerated subkey
  1653. NULL, // OUT Size of the class of the subkey
  1654. &time // OUT Last time the subkey was written to
  1655. );
  1656. if (lResult != ERROR_SUCCESS)
  1657. {
  1658. break;
  1659. }
  1660. // Delete the decendents of this child.
  1661. lResult = RecursiveDeleteKey(hKeyChild, szBuffer);
  1662. if (lResult != ERROR_SUCCESS)
  1663. {
  1664. // Cleanup before exiting.
  1665. RegCloseKey(hKeyChild);
  1666. return HRESULT_FROM_WIN32(lResult);
  1667. }
  1668. dwSize = bufSize;
  1669. } // while
  1670. // Close the child.
  1671. RegCloseKey(hKeyChild);
  1672. // Delete this child.
  1673. lResult = RegDeleteKey(hKeyParent, lpszKeyChild);
  1674. return HRESULT_FROM_WIN32(lResult);
  1675. }
  1676. HRESULT
  1677. SensConfigureEventSystem(
  1678. BOOL bUnregister
  1679. )
  1680. /*++
  1681. Routine Description:
  1682. As of NTbuild 1750, EventSystem is not auto-configured. So, SENS does
  1683. the work of configuring EventSystem.
  1684. Arguments:
  1685. bUnregister - If TRUE, then install EventSystem.
  1686. Notes:
  1687. o This is a dummy call on NT4 because we don't need to configure
  1688. EventSystem on NT4. IE5 setup (Webcheck.dll) configures LCE.
  1689. Return Value:
  1690. S_OK, if successful
  1691. hr, otherwise
  1692. --*/
  1693. {
  1694. return S_OK;
  1695. }
  1696. HRESULT
  1697. SensUpdateVersion(
  1698. BOOL bUnregister
  1699. )
  1700. /*++
  1701. Routine Description:
  1702. Update the version of SENS in the registry.
  1703. Arguments:
  1704. bUnregister - usual.
  1705. Return Value:
  1706. S_OK, if successful
  1707. hr, otherwise
  1708. --*/
  1709. {
  1710. HRESULT hr;
  1711. HKEY hKeySens;
  1712. LONG RegStatus;
  1713. DWORD dwConfigured;
  1714. hr = S_OK;
  1715. hKeySens = NULL;
  1716. RegStatus = ERROR_SUCCESS;
  1717. RegStatus = RegOpenKeyEx(
  1718. HKEY_LOCAL_MACHINE, // Handle of the key
  1719. SENS_REGISTRY_KEY, // String which represents the sub-key to open
  1720. 0, // Reserved (MBZ)
  1721. KEY_ALL_ACCESS, // Security Access mask
  1722. &hKeySens // Returned HKEY
  1723. );
  1724. if (RegStatus != ERROR_SUCCESS)
  1725. {
  1726. SensPrintA(SENS_ERR, (SENS_SETUP "RegOpenKeyEx(Sens) returned %d.\n", RegStatus));
  1727. hr = HRESULT_FROM_WIN32(RegStatus);
  1728. goto Cleanup;
  1729. }
  1730. if (TRUE == bUnregister)
  1731. {
  1732. dwConfigured = CONFIG_VERSION_NONE;
  1733. }
  1734. else
  1735. {
  1736. dwConfigured = CONFIG_VERSION_CURRENT;
  1737. }
  1738. // Update registry to reflect that SENS is now configured.
  1739. RegStatus = RegSetValueEx(
  1740. hKeySens, // Key to set Value for.
  1741. IS_SENS_CONFIGURED, // Value to set
  1742. 0, // Reserved
  1743. REG_DWORD, // Value Type
  1744. (BYTE*) &dwConfigured,// Address of Value data
  1745. sizeof(DWORD) // Size of Value
  1746. );
  1747. if (RegStatus != ERROR_SUCCESS)
  1748. {
  1749. SensPrintA(SENS_ERR, (SENS_SETUP "RegSetValueEx(IS_SENS_CONFIGURED) failed with 0x%x\n", RegStatus));
  1750. hr = HRESULT_FROM_WIN32(RegStatus);
  1751. goto Cleanup;
  1752. }
  1753. SensPrintA(SENS_INFO, (SENS_SETUP "SENS is now configured successfully. "
  1754. "Registry updated to 0x%x.\n", dwConfigured));
  1755. Cleanup:
  1756. //
  1757. // Cleanup
  1758. //
  1759. if (hKeySens)
  1760. {
  1761. RegCloseKey(hKeySens);
  1762. }
  1763. return hr;
  1764. }
  1765. #if defined(SENS_CHICAGO)
  1766. extern "C" int APIENTRY
  1767. DllMain(
  1768. IN HINSTANCE hInstance,
  1769. IN DWORD dwReason,
  1770. IN LPVOID lpvReserved
  1771. )
  1772. /*++
  1773. Routine Description:
  1774. This routine will get called either when a process attaches to this dll
  1775. or when a process detaches from this dll.
  1776. Return Value:
  1777. TRUE - Initialization successfully occurred.
  1778. FALSE - Insufficient memory is available for the process to attach to
  1779. this dll.
  1780. --*/
  1781. {
  1782. BOOL bSuccess;
  1783. switch (dwReason)
  1784. {
  1785. case DLL_PROCESS_ATTACH:
  1786. // Disable Thread attach/detach calls
  1787. bSuccess = DisableThreadLibraryCalls(hInstance);
  1788. ASSERT(bSuccess == TRUE);
  1789. break;
  1790. case DLL_PROCESS_DETACH:
  1791. break;
  1792. }
  1793. return(TRUE);
  1794. }
  1795. #endif // SENS_CHICAGO