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.

1887 lines
46 KiB

  1. /*++
  2. Copyright (c) 1999-2001 Microsoft Corporation
  3. Module Name:
  4. service.cpp
  5. Abstract:
  6. This module implements routines for service
  7. specific SSR Knowledge Base processing.
  8. Author:
  9. Vishnu Patankar (VishnuP) - Oct 2001
  10. Environment:
  11. User mode only.
  12. Exported Functions:
  13. Revision History:
  14. Created - Oct 2001
  15. --*/
  16. #include "stdafx.h"
  17. #include "kbproc.h"
  18. #include "process.h"
  19. HRESULT
  20. process::SsrpProcessService(
  21. IN CComPtr <IXMLDOMElement> pXMLDocElemRoot,
  22. IN CComPtr <IXMLDOMNode> pXMLServiceNode,
  23. IN PWSTR pszMode,
  24. OUT BOOL *pbRoleIsSatisfiable,
  25. OUT BOOL *pbSomeRequiredServiceDisabled
  26. )
  27. /*++
  28. Routine Description:
  29. Routine called to process each service
  30. Arguments:
  31. pXMLDocElemRoot - root of document
  32. pXMLServiceNode - service node
  33. pszMode - mode value
  34. pbRoleIsSatisfiable - boolean to fill regarding role satisfiability
  35. pbSomeRequiredServiceDisabled - boolean to fill in if required service is disabled
  36. Return:
  37. HRESULT error code
  38. ++*/
  39. {
  40. HRESULT hr = S_OK;
  41. CComBSTR bstrName;
  42. //CComBSTR bstrRequired;
  43. CComPtr <IXMLDOMNode> pServiceSelect;
  44. CComPtr <IXMLDOMNode> pServiceRequired;
  45. CComPtr <IXMLDOMNodeList> pSelectChildList;
  46. CComPtr <IXMLDOMNode> pServiceName;
  47. DWORD rc = ERROR_SUCCESS;
  48. if (pbRoleIsSatisfiable == NULL || pbSomeRequiredServiceDisabled == NULL ) {
  49. return E_INVALIDARG;
  50. }
  51. /*
  52. hr = pXMLServiceNode->selectSingleNode(L"Required", &pServiceRequired);
  53. if (FAILED(hr) || pServiceRequired == NULL ) {
  54. SsrpLogParseError(hr);
  55. goto ExitHandler;
  56. }
  57. pServiceRequired->get_text(&bstrRequired);
  58. hr = pXMLServiceNode->selectSingleNode(L"Select", &pServiceSelect);
  59. if (FAILED(hr) || pServiceSelect == NULL ) {
  60. SsrpLogParseError(hr);
  61. goto ExitHandler;
  62. }
  63. hr = SsrpDeleteChildren(pServiceSelect);
  64. if (FAILED(hr) ) {
  65. SsrpLogParseError(hr);
  66. goto ExitHandler;
  67. }
  68. */
  69. hr = pXMLServiceNode->selectSingleNode(L"Name", &pServiceName);
  70. if (FAILED(hr) || pServiceName == NULL ) {
  71. SsrpLogParseError(hr);
  72. goto ExitHandler;
  73. }
  74. pServiceName->get_text(&bstrName);
  75. BOOL bIsServiceInstalled = FALSE;
  76. bIsServiceInstalled = SsrpIsServiceInstalled(bstrName);
  77. BYTE byStartupType = SERVICE_DISABLED;
  78. BOOL bServiceIsDisabled = FALSE;
  79. rc = SsrpQueryServiceStartupType(bstrName, &byStartupType);
  80. if (rc == ERROR_SERVICE_DOES_NOT_EXIST) {
  81. rc = ERROR_SUCCESS;
  82. }
  83. if ( rc != ERROR_SUCCESS ) {
  84. SsrpLogError(L"Startup type for some service was not queried\n");
  85. goto ExitHandler;
  86. }
  87. bServiceIsDisabled = (byStartupType == SERVICE_DISABLED ? TRUE: FALSE);
  88. /*
  89. BOOL bIsServiceOptional = FALSE;
  90. hr = SsrpCheckIfOptionalService(
  91. pXMLDocElemRoot,
  92. bstrName,
  93. &bIsServiceOptional
  94. );
  95. if (FAILED(hr) ) {
  96. SsrpLogParseError(hr);
  97. goto ExitHandler;
  98. }
  99. */
  100. *pbRoleIsSatisfiable = *pbRoleIsSatisfiable && bIsServiceInstalled;
  101. *pbSomeRequiredServiceDisabled = *pbSomeRequiredServiceDisabled || bServiceIsDisabled;
  102. /*
  103. if (0 == SsrpICompareBstrPwstr(bstrRequired, L"TRUE")) {
  104. hr = pServiceSelect->put_text(L"TRUE");
  105. if (FAILED(hr) ) {
  106. SsrpLogParseError(hr);
  107. goto ExitHandler;
  108. }
  109. *pbRoleIsSatisfiable = *pbRoleIsSatisfiable && bIsServiceInstalled;
  110. *pbSomeRequiredServiceDisabled = *pbSomeRequiredServiceDisabled || bServiceIsDisabled;
  111. }
  112. else {
  113. //
  114. // service is not required
  115. //
  116. BOOL bServiceSelect = FALSE;
  117. CComPtr <IXMLDOMNamedNodeMap> pXMLAttribNode;
  118. CComPtr <IXMLDOMNode> pXMLValueNode;
  119. CComPtr <IXMLDOMNode> pXMLServiceModeNode;
  120. hr = pServiceSelect->selectSingleNode(pszMode, &pXMLServiceModeNode );
  121. if (FAILED(hr) || pXMLServiceModeNode == NULL){
  122. SsrpLogParseError(hr);
  123. goto ExitHandler;
  124. }
  125. hr = pXMLServiceModeNode->get_attributes( &pXMLAttribNode );
  126. if (FAILED(hr) || pXMLAttribNode == NULL){
  127. SsrpLogParseError(hr);
  128. goto ExitHandler;
  129. }
  130. hr = pXMLAttribNode->getNamedItem(L"Value", &pXMLValueNode );
  131. if (FAILED(hr) || pXMLValueNode == NULL){
  132. SsrpLogParseError(hr);
  133. goto ExitHandler;
  134. }
  135. CComBSTR bstrValue;
  136. hr = pXMLValueNode->get_text(&bstrValue);
  137. if (FAILED(hr) || !bstrValue ) {
  138. SsrpLogParseError(hr);
  139. goto ExitHandler;
  140. }
  141. if (0 == SsrpICompareBstrPwstr(bstrValue, L"TRUE")) {
  142. bServiceSelect = TRUE;
  143. }
  144. else if (0 == SsrpICompareBstrPwstr(bstrValue, L"FALSE")) {
  145. bServiceSelect = TRUE;
  146. }
  147. else if (0 == SsrpICompareBstrPwstr(bstrValue, L"DEFAULT")) {
  148. if (bIsServiceOptional && bIsServiceInstalled && !bServiceIsDisabled ) {
  149. bServiceSelect = TRUE;
  150. }
  151. }
  152. else if (0 == SsrpICompareBstrPwstr(bstrValue, L"CUSTOM")) {
  153. //
  154. // get the attributes "FunctionName" and "DLLName"
  155. //
  156. CComPtr <IXMLDOMNode> pXMLFunctionName;
  157. CComBSTR bstrFunctionName;
  158. hr = pXMLAttribNode->getNamedItem(L"FunctionName", &pXMLFunctionName );
  159. if (FAILED(hr) || pXMLFunctionName == NULL){
  160. SsrpLogParseError(hr);
  161. goto ExitHandler;
  162. }
  163. hr = pXMLFunctionName->get_text(&bstrFunctionName);
  164. if (FAILED(hr) || !bstrFunctionName){
  165. SsrpLogParseError(hr);
  166. goto ExitHandler;
  167. }
  168. CComPtr <IXMLDOMNode> pXMLDLLName;
  169. CComBSTR bstrDLLName;
  170. hr = pXMLAttribNode->getNamedItem(L"DLLName", &pXMLDLLName );
  171. if (FAILED(hr) || pXMLDLLName == NULL){
  172. SsrpLogParseError(hr);
  173. goto ExitHandler;
  174. }
  175. hr = pXMLDLLName->get_text(&bstrDLLName);
  176. if (FAILED(hr) || !bstrDLLName ){
  177. SsrpLogParseError(hr);
  178. goto ExitHandler;
  179. }
  180. rc = SsrpEvaluateCustomFunction(bstrDLLName, bstrFunctionName, &bServiceSelect);
  181. if (rc != ERROR_SUCCESS) {
  182. SsrpLogWin32Error(rc);
  183. goto ExitHandler;
  184. }
  185. }
  186. hr = SsrpDeleteChildren(pServiceSelect);
  187. if (FAILED(hr) ) {
  188. SsrpLogParseError(hr);
  189. goto ExitHandler;
  190. }
  191. // hr = pServiceSelect->put_text(bServiceSelect ? L"TRUE" : L"FALSE");
  192. if (FAILED(hr) ) {
  193. SsrpLogParseError(hr);
  194. goto ExitHandler;
  195. }
  196. }
  197. */
  198. ExitHandler:
  199. return rc;
  200. }
  201. DWORD
  202. process::SsrpQueryInstalledServicesInfo(
  203. IN PWSTR pszMachineName
  204. )
  205. /*++
  206. Routine Description:
  207. Routine called to initialize service information
  208. Arguments:
  209. pszMachineName - name of machine to lookup SCM information
  210. Return:
  211. HRESULT error code
  212. ++*/
  213. {
  214. DWORD rc = ERROR_SUCCESS;
  215. DWORD cbInfo = 0;
  216. DWORD dwErr = ERROR_SUCCESS;
  217. DWORD dwResume = 0;
  218. //
  219. // Connect to the service controller.
  220. //
  221. m_hScm = OpenSCManager(
  222. pszMachineName,
  223. NULL,
  224. GENERIC_READ);
  225. if (m_hScm == NULL) {
  226. rc = GetLastError();
  227. goto ExitHandler;
  228. }
  229. if ((!EnumServicesStatusEx(
  230. m_hScm,
  231. SC_ENUM_PROCESS_INFO,
  232. SERVICE_WIN32,
  233. SERVICE_STATE_ALL,
  234. NULL,
  235. 0,
  236. &cbInfo,
  237. &m_dwNumServices,
  238. &dwResume,
  239. NULL)) && ERROR_MORE_DATA == GetLastError()) {
  240. m_pInstalledServicesInfo = (LPENUM_SERVICE_STATUS_PROCESS)LocalAlloc(LMEM_ZEROINIT, cbInfo);
  241. if (m_pInstalledServicesInfo == NULL) {
  242. rc = ERROR_NOT_ENOUGH_MEMORY;
  243. goto ExitHandler;
  244. }
  245. }
  246. else {
  247. rc = GetLastError();
  248. goto ExitHandler;
  249. }
  250. if (!EnumServicesStatusEx(
  251. m_hScm,
  252. SC_ENUM_PROCESS_INFO,
  253. SERVICE_WIN32,
  254. SERVICE_STATE_ALL,
  255. (LPBYTE)m_pInstalledServicesInfo,
  256. cbInfo,
  257. &cbInfo,
  258. &m_dwNumServices,
  259. &dwResume,
  260. NULL)) {
  261. rc = GetLastError();
  262. goto ExitHandler;
  263. }
  264. m_bArrServiceInKB = (DWORD *) LocalAlloc(LMEM_ZEROINIT, m_dwNumServices * sizeof(DWORD));
  265. if (m_bArrServiceInKB == NULL){
  266. rc = ERROR_NOT_ENOUGH_MEMORY;
  267. goto ExitHandler;
  268. }
  269. memset(m_bArrServiceInKB, 0, m_dwNumServices * sizeof(DWORD));
  270. ExitHandler:
  271. return rc;
  272. }
  273. HRESULT
  274. process::SsrpCheckIfOptionalService(
  275. IN CComPtr <IXMLDOMElement> pXMLDocElemRoot,
  276. IN BSTR bstrServiceName,
  277. IN BOOL *pbOptional
  278. )
  279. /*++
  280. Routine Description:
  281. Routine called to check if service is optional
  282. Arguments:
  283. pXMLDocElemRoot - root of document
  284. bstrServiceName - name of service
  285. pbOptional - boolean to fill if optional or not
  286. Return:
  287. HRESULT error code
  288. ++*/
  289. {
  290. HRESULT hr;
  291. CComPtr <IXMLDOMNode> pService;
  292. CComPtr <IXMLDOMNode> pOptional;
  293. CComPtr <IXMLDOMNodeList> pServiceList;
  294. if (pbOptional == NULL) {
  295. E_INVALIDARG;
  296. }
  297. *pbOptional = FALSE;
  298. hr = pXMLDocElemRoot->selectNodes(L"Services/Service", &pServiceList);
  299. if (FAILED(hr) || pServiceList == NULL ) {
  300. SsrpLogParseError(hr);
  301. goto ExitHandler;
  302. }
  303. hr = pServiceList->nextNode(&pService);
  304. if (FAILED(hr)) {
  305. SsrpLogParseError(hr);
  306. goto ExitHandler;
  307. }
  308. while (pService) {
  309. CComBSTR bstrText;
  310. CComPtr <IXMLDOMNode> pName;
  311. hr = pService->selectSingleNode(L"Name", &pName);
  312. if (FAILED(hr) || pName == NULL ) {
  313. SsrpLogParseError(hr);
  314. goto ExitHandler;
  315. }
  316. hr = pName->get_text(&bstrText);
  317. if (FAILED(hr) || !bstrText ) {
  318. SsrpLogParseError(hr);
  319. goto ExitHandler;
  320. }
  321. if (0 == SsrpICompareBstrPwstr(bstrServiceName, bstrText)) {
  322. hr = pService->selectSingleNode(L"Optional", &pOptional);
  323. if (FAILED(hr) || pOptional == NULL ) {
  324. SsrpLogParseError(hr);
  325. goto ExitHandler;
  326. }
  327. CComBSTR bstrOptional;
  328. hr = pOptional->get_text(&bstrOptional);
  329. if (FAILED(hr) || !bstrOptional ) {
  330. SsrpLogParseError(hr);
  331. goto ExitHandler;
  332. }
  333. if (0 == SsrpICompareBstrPwstr(bstrOptional, L"TRUE"))
  334. *pbOptional = TRUE;
  335. else
  336. *pbOptional = FALSE;
  337. return hr;
  338. }
  339. pService.Release();
  340. hr = pServiceList->nextNode(&pService);
  341. if (FAILED(hr)) {
  342. SsrpLogParseError(hr);
  343. goto ExitHandler;
  344. }
  345. }
  346. ExitHandler:
  347. return hr;
  348. }
  349. DWORD
  350. process::SsrpQueryServiceStartupType(
  351. IN PWSTR pszServiceName,
  352. OUT BYTE *pbyStartupType
  353. )
  354. /*++
  355. Routine Description:
  356. Routine called to check service startup type
  357. Arguments:
  358. pszServiceName - name of service
  359. pbyStartupType - startup type
  360. Return:
  361. Win32 error code
  362. ++*/
  363. {
  364. DWORD rc = ERROR_SUCCESS;
  365. DWORD dwBytesNeeded = 0;
  366. SC_HANDLE hService = NULL;
  367. LPQUERY_SERVICE_CONFIG pServiceConfig=NULL;
  368. if (pbyStartupType == NULL || pszServiceName == NULL)
  369. return ERROR_INVALID_PARAMETER;
  370. *pbyStartupType = SERVICE_DISABLED;
  371. SsrpConvertBstrToPwstr(pszServiceName);
  372. hService = OpenService(
  373. m_hScm,
  374. pszServiceName,
  375. SERVICE_QUERY_CONFIG |
  376. READ_CONTROL
  377. );
  378. if ( hService == NULL ) {
  379. rc = GetLastError();
  380. goto ExitHandler;
  381. }
  382. if ( !QueryServiceConfig(
  383. hService,
  384. NULL,
  385. 0,
  386. &dwBytesNeeded
  387. )) {
  388. if (ERROR_INSUFFICIENT_BUFFER != (rc = GetLastError()))
  389. goto ExitHandler;
  390. }
  391. rc = ERROR_SUCCESS;
  392. pServiceConfig = (LPQUERY_SERVICE_CONFIG)LocalAlloc(LMEM_ZEROINIT, dwBytesNeeded);
  393. if ( pServiceConfig == NULL ) {
  394. rc = ERROR_NOT_ENOUGH_MEMORY;
  395. goto ExitHandler;
  396. }
  397. if ( !QueryServiceConfig(
  398. hService,
  399. pServiceConfig,
  400. dwBytesNeeded,
  401. &dwBytesNeeded) )
  402. {
  403. rc = GetLastError();
  404. goto ExitHandler;
  405. }
  406. *pbyStartupType = (BYTE)(pServiceConfig->dwStartType) ;
  407. ExitHandler:
  408. if (pServiceConfig) {
  409. LocalFree(pServiceConfig);
  410. }
  411. if (hService) {
  412. CloseServiceHandle(hService);
  413. }
  414. return rc;
  415. }
  416. HRESULT
  417. process::SsrpAddUnknownSection(
  418. IN CComPtr <IXMLDOMElement> pElementRoot,
  419. IN CComPtr <IXMLDOMDocument> pXMLDoc
  420. )
  421. /*++
  422. Routine Description:
  423. Routine called to add extra services
  424. Arguments:
  425. pElementRoot - the root element pointer
  426. pXMLDoc - document pointer
  427. Return:
  428. HRESULT error code
  429. ++*/
  430. {
  431. CComPtr <IXMLDOMNode> pNewChild;
  432. CComPtr <IXMLDOMNode> pXDNodeUnknownNode;
  433. CComPtr <IXMLDOMNode> pXDNodeServices;
  434. CComPtr <IXMLDOMNode> pXDNodeName;
  435. CComPtr <IXMLDOMNode> pXDNodeSatisfiable;
  436. CComPtr <IXMLDOMNode> pXDNodeSelected;
  437. CComPtr <IXMLDOMNode> pXDNodeRole;
  438. CComPtr <IXMLDOMNodeList> pRolesList;
  439. CComPtr <IXMLDOMNode> pRole;
  440. BOOL bOtherRolePresent = FALSE;
  441. LPSERVICE_DESCRIPTION pServiceDescription = NULL;
  442. CComPtr <IXMLDOMNode> pServicesNode;
  443. CComVariant Type(NODE_ELEMENT);
  444. CComVariant vtRefChild;
  445. HRESULT hr;
  446. DWORD rc = ERROR_SUCCESS;
  447. hr = pXMLDoc->createNode(
  448. Type,
  449. L"Unknown",
  450. NULL,
  451. &pXDNodeUnknownNode);
  452. if (FAILED(hr) || pXDNodeUnknownNode == NULL) {
  453. SsrpLogParseError(hr);
  454. goto ExitHandler;
  455. }
  456. hr = SsrpAddWhiteSpace(
  457. pXMLDoc,
  458. pXDNodeUnknownNode,
  459. L"\n\t\t\t"
  460. );
  461. if (FAILED(hr)) {
  462. SsrpLogParseError(hr);
  463. goto ExitHandler;
  464. }
  465. hr = pXMLDoc->createNode(
  466. Type,
  467. L"Services",
  468. NULL,
  469. &pXDNodeServices);
  470. if (FAILED(hr) || pXDNodeServices == NULL) {
  471. SsrpLogParseError(hr);
  472. goto ExitHandler;
  473. }
  474. hr = pXDNodeUnknownNode->appendChild(pXDNodeServices, NULL);
  475. if (FAILED(hr) ) {
  476. SsrpLogParseError(hr);
  477. goto ExitHandler;
  478. }
  479. hr = SsrpAddWhiteSpace(
  480. pXMLDoc,
  481. pXDNodeUnknownNode,
  482. L"\n\t\t\t\t\t"
  483. );
  484. if (FAILED(hr)) {
  485. SsrpLogParseError(hr);
  486. goto ExitHandler;
  487. }
  488. for (DWORD ServiceIndex=0;
  489. ServiceIndex < m_dwNumServices;
  490. ServiceIndex++ ) {
  491. if (m_bArrServiceInKB[ServiceIndex] == 0){
  492. CComPtr <IXMLDOMNode> pXDNodeService;
  493. CComPtr <IXMLDOMNode> pXDNodeServiceName;
  494. CComPtr <IXMLDOMNode> pXDNodeServiceDescription;
  495. CComPtr <IXMLDOMNode> pXDNodeServiceDisplayName;
  496. CComPtr <IXMLDOMNode> pXDNodeServiceMaximum;
  497. CComPtr <IXMLDOMNode> pXDNodeServiceTypical;
  498. hr = SsrpAddWhiteSpace(
  499. pXMLDoc,
  500. pXDNodeServices,
  501. L"\n\t\t\t\t\t"
  502. );
  503. if (FAILED(hr)) {
  504. SsrpLogParseError(hr);
  505. goto ExitHandler;
  506. }
  507. hr = pXMLDoc->createNode(
  508. Type,
  509. L"Service",
  510. NULL,
  511. &pXDNodeService);
  512. if (FAILED(hr) || pXDNodeService == NULL) {
  513. SsrpLogParseError(hr);
  514. goto ExitHandler;
  515. }
  516. hr = pXDNodeServices->appendChild(pXDNodeService, NULL);
  517. if (FAILED(hr)) {
  518. SsrpLogParseError(hr);
  519. goto ExitHandler;
  520. }
  521. hr = SsrpAddWhiteSpace(
  522. pXMLDoc,
  523. pXDNodeService,
  524. L"\n\t\t\t\t\t\t"
  525. );
  526. if (FAILED(hr)) {
  527. SsrpLogParseError(hr);
  528. goto ExitHandler;
  529. }
  530. hr = pXMLDoc->createNode(
  531. Type,
  532. L"Name",
  533. NULL,
  534. &pXDNodeServiceName);
  535. if (FAILED(hr) || pXDNodeServiceName == NULL) {
  536. SsrpLogParseError(hr);
  537. goto ExitHandler;
  538. }
  539. hr = pXDNodeServiceName->put_text(m_pInstalledServicesInfo[ServiceIndex].lpServiceName);
  540. if (FAILED(hr)) {
  541. SsrpLogParseError(hr);
  542. goto ExitHandler;
  543. }
  544. hr = pXDNodeService->appendChild(pXDNodeServiceName, NULL);
  545. if (FAILED(hr)) {
  546. SsrpLogParseError(hr);
  547. goto ExitHandler;
  548. }
  549. hr = SsrpAddWhiteSpace(
  550. pXMLDoc,
  551. pXDNodeService,
  552. L"\n\t\t\t\t\t\t"
  553. );
  554. if (FAILED(hr)) {
  555. SsrpLogParseError(hr);
  556. goto ExitHandler;
  557. }
  558. /* hr = pXMLDoc->createNode(
  559. Type,
  560. L"DisplayName",
  561. NULL,
  562. &pXDNodeServiceDisplayName);
  563. if (FAILED(hr) || pXDNodeServiceDisplayName == NULL) {
  564. SsrpLogParseError(hr);
  565. goto ExitHandler;
  566. }
  567. hr = pXDNodeServiceDisplayName->put_text(m_pInstalledServicesInfo[ServiceIndex].lpDisplayName);
  568. if (FAILED(hr)) {
  569. SsrpLogParseError(hr);
  570. goto ExitHandler;
  571. }
  572. hr = pXDNodeService->appendChild(pXDNodeServiceDisplayName, NULL);
  573. if (FAILED(hr)) {
  574. SsrpLogParseError(hr);
  575. goto ExitHandler;
  576. }
  577. hr = SsrpAddWhiteSpace(
  578. pXMLDoc,
  579. pXDNodeService,
  580. L"\n\t\t\t\t\t\t"
  581. );
  582. if (FAILED(hr)) {
  583. SsrpLogParseError(hr);
  584. goto ExitHandler;
  585. }
  586. hr = pXMLDoc->createNode(
  587. Type,
  588. L"Description",
  589. NULL,
  590. &pXDNodeServiceDescription);
  591. if (FAILED(hr) || pXDNodeServiceDescription == NULL) {
  592. SsrpLogParseError(hr);
  593. goto ExitHandler;
  594. }
  595. rc = SsrpQueryServiceDescription(m_pInstalledServicesInfo[ServiceIndex].lpServiceName,
  596. &pServiceDescription);
  597. if (rc != ERROR_SUCCESS ) {
  598. SsrpLogParseError(hr);
  599. goto ExitHandler;
  600. }
  601. hr = pXDNodeServiceDescription->put_text(
  602. (pServiceDescription == NULL) ? L"" : pServiceDescription->lpDescription);
  603. if (FAILED(hr)) {
  604. SsrpLogParseError(hr);
  605. goto ExitHandler;
  606. }
  607. if (pServiceDescription) {
  608. LocalFree(pServiceDescription);
  609. pServiceDescription = NULL;
  610. }
  611. hr = pXDNodeService->appendChild(pXDNodeServiceDescription, NULL);
  612. if (FAILED(hr)) {
  613. SsrpLogParseError(hr);
  614. goto ExitHandler;
  615. }
  616. hr = SsrpAddWhiteSpace(
  617. pXMLDoc,
  618. pXDNodeService,
  619. L"\n\t\t\t\t\t"
  620. );
  621. if (FAILED(hr)) {
  622. SsrpLogParseError(hr);
  623. goto ExitHandler;
  624. }
  625. hr = SsrpAddWhiteSpace(
  626. pXMLDoc,
  627. pXDNodeServiceDescription,
  628. L"\n\t\t\t\t\t\t\t"
  629. );
  630. if (FAILED(hr)) {
  631. SsrpLogParseError(hr);
  632. goto ExitHandler;
  633. }
  634. */
  635. }
  636. }
  637. hr = pElementRoot->selectSingleNode(L"Services", &pServicesNode);
  638. if (FAILED(hr) || pServicesNode == NULL ) {
  639. SsrpLogParseError(hr);
  640. goto ExitHandler;
  641. }
  642. vtRefChild = pServicesNode;
  643. hr = pElementRoot->insertBefore(pXDNodeUnknownNode,
  644. vtRefChild,
  645. NULL);
  646. if (FAILED(hr)) {
  647. SsrpLogParseError(hr);
  648. goto ExitHandler;
  649. }
  650. ExitHandler:
  651. return hr;
  652. }
  653. HRESULT
  654. process::SsrpAddUnknownServicesInfoToServiceLoc(
  655. IN CComPtr <IXMLDOMElement> pElementRoot,
  656. IN CComPtr <IXMLDOMDocument> pXMLDoc
  657. )
  658. /*++
  659. Routine Description:
  660. Routine called to add unknown service display and description to
  661. <Service Localization>
  662. Arguments:
  663. pElementRoot - the root element pointer
  664. pXMLDoc - document pointer
  665. Return:
  666. HRESULT error code
  667. ++*/
  668. {
  669. CComPtr <IXMLDOMNode> pNewChild;
  670. CComPtr <IXMLDOMNode> pXDNodeUnknownNode;
  671. CComPtr <IXMLDOMNode> pXDNodeServices;
  672. CComPtr <IXMLDOMNode> pXDNodeName;
  673. CComPtr <IXMLDOMNode> pXDNodeSatisfiable;
  674. CComPtr <IXMLDOMNode> pXDNodeSelected;
  675. CComPtr <IXMLDOMNode> pXDNodeRole;
  676. CComPtr <IXMLDOMNodeList> pRolesList;
  677. CComPtr <IXMLDOMNode> pRole;
  678. BOOL bOtherRolePresent = FALSE;
  679. LPSERVICE_DESCRIPTION pServiceDescription = NULL;
  680. CComPtr <IXMLDOMNode> pServicesNode;
  681. CComPtr <IXMLDOMNode> pServiceLoc;
  682. CComVariant Type(NODE_ELEMENT);
  683. CComVariant vtRefChild;
  684. HRESULT hr;
  685. DWORD rc = ERROR_SUCCESS;
  686. //
  687. // get the "ServiceLocalization" section node
  688. //
  689. hr = pElementRoot->selectSingleNode(L"ServiceLocalization", &pServiceLoc);
  690. if (FAILED(hr) || pServiceLoc == NULL ) {
  691. SsrpLogParseError(hr);
  692. goto ExitHandler;
  693. }
  694. for (DWORD ServiceIndex=0;
  695. ServiceIndex < m_dwNumServices;
  696. ServiceIndex++ ) {
  697. if (m_bArrServiceInKB[ServiceIndex] == 0){
  698. CComPtr <IXMLDOMNode> pXDNodeService;
  699. CComPtr <IXMLDOMNode> pXDNodeServiceName;
  700. CComPtr <IXMLDOMNode> pXDNodeServiceDescription;
  701. CComPtr <IXMLDOMNode> pXDNodeServiceDisplayName;
  702. CComPtr <IXMLDOMNode> pXDNodeServiceMaximum;
  703. CComPtr <IXMLDOMNode> pXDNodeServiceTypical;
  704. hr = pXMLDoc->createNode(
  705. Type,
  706. L"Service",
  707. NULL,
  708. &pXDNodeService);
  709. if (FAILED(hr) || pXDNodeService == NULL) {
  710. SsrpLogParseError(hr);
  711. goto ExitHandler;
  712. }
  713. hr = pServiceLoc->appendChild(pXDNodeService, NULL);
  714. if (FAILED(hr)) {
  715. SsrpLogParseError(hr);
  716. goto ExitHandler;
  717. }
  718. hr = SsrpAddWhiteSpace(
  719. pXMLDoc,
  720. pXDNodeService,
  721. L"\n\t\t\t\t\t\t"
  722. );
  723. if (FAILED(hr)) {
  724. SsrpLogParseError(hr);
  725. goto ExitHandler;
  726. }
  727. hr = pXMLDoc->createNode(
  728. Type,
  729. L"Name",
  730. NULL,
  731. &pXDNodeServiceName);
  732. if (FAILED(hr) || pXDNodeServiceName == NULL) {
  733. SsrpLogParseError(hr);
  734. goto ExitHandler;
  735. }
  736. hr = pXDNodeServiceName->put_text(m_pInstalledServicesInfo[ServiceIndex].lpServiceName);
  737. if (FAILED(hr)) {
  738. SsrpLogParseError(hr);
  739. goto ExitHandler;
  740. }
  741. hr = pXDNodeService->appendChild(pXDNodeServiceName, NULL);
  742. if (FAILED(hr)) {
  743. SsrpLogParseError(hr);
  744. goto ExitHandler;
  745. }
  746. hr = SsrpAddWhiteSpace(
  747. pXMLDoc,
  748. pXDNodeService,
  749. L"\n\t\t\t\t\t\t"
  750. );
  751. if (FAILED(hr)) {
  752. SsrpLogParseError(hr);
  753. goto ExitHandler;
  754. }
  755. hr = pXMLDoc->createNode(
  756. Type,
  757. L"DisplayName",
  758. NULL,
  759. &pXDNodeServiceDisplayName);
  760. if (FAILED(hr) || pXDNodeServiceDisplayName == NULL) {
  761. SsrpLogParseError(hr);
  762. goto ExitHandler;
  763. }
  764. hr = pXDNodeServiceDisplayName->put_text(m_pInstalledServicesInfo[ServiceIndex].lpDisplayName);
  765. if (FAILED(hr)) {
  766. SsrpLogParseError(hr);
  767. goto ExitHandler;
  768. }
  769. hr = pXDNodeService->appendChild(pXDNodeServiceDisplayName, NULL);
  770. if (FAILED(hr)) {
  771. SsrpLogParseError(hr);
  772. goto ExitHandler;
  773. }
  774. hr = SsrpAddWhiteSpace(
  775. pXMLDoc,
  776. pXDNodeService,
  777. L"\n\t\t\t\t\t\t"
  778. );
  779. if (FAILED(hr)) {
  780. SsrpLogParseError(hr);
  781. goto ExitHandler;
  782. }
  783. hr = pXMLDoc->createNode(
  784. Type,
  785. L"Description",
  786. NULL,
  787. &pXDNodeServiceDescription);
  788. if (FAILED(hr) || pXDNodeServiceDescription == NULL) {
  789. SsrpLogParseError(hr);
  790. goto ExitHandler;
  791. }
  792. rc = SsrpQueryServiceDescription(m_pInstalledServicesInfo[ServiceIndex].lpServiceName,
  793. &pServiceDescription);
  794. if (rc != ERROR_SUCCESS ) {
  795. SsrpLogParseError(hr);
  796. goto ExitHandler;
  797. }
  798. hr = pXDNodeServiceDescription->put_text(
  799. (pServiceDescription == NULL) ? L"" : pServiceDescription->lpDescription);
  800. if (FAILED(hr)) {
  801. SsrpLogParseError(hr);
  802. goto ExitHandler;
  803. }
  804. if (pServiceDescription) {
  805. LocalFree(pServiceDescription);
  806. pServiceDescription = NULL;
  807. }
  808. hr = pXDNodeService->appendChild(pXDNodeServiceDescription, NULL);
  809. if (FAILED(hr)) {
  810. SsrpLogParseError(hr);
  811. goto ExitHandler;
  812. }
  813. hr = SsrpAddWhiteSpace(
  814. pXMLDoc,
  815. pXDNodeService,
  816. L"\n\t\t\t\t\t"
  817. );
  818. if (FAILED(hr)) {
  819. SsrpLogParseError(hr);
  820. goto ExitHandler;
  821. }
  822. hr = SsrpAddWhiteSpace(
  823. pXMLDoc,
  824. pXDNodeServiceDescription,
  825. L"\n\t\t\t\t\t\t\t"
  826. );
  827. if (FAILED(hr)) {
  828. SsrpLogParseError(hr);
  829. goto ExitHandler;
  830. }
  831. }
  832. }
  833. ExitHandler:
  834. return hr;
  835. }
  836. BOOL
  837. process::SsrpIsServiceInstalled(
  838. IN BSTR bstrService
  839. )
  840. /*++
  841. Routine Description:
  842. Routine called to check if service is installed
  843. Arguments:
  844. bstrService - service name
  845. Return:
  846. TRUE if installed, FALSE otherwise
  847. ++*/
  848. {
  849. if (bstrService) {
  850. for (DWORD ServiceIndex=0; ServiceIndex < m_dwNumServices; ServiceIndex++ ) {
  851. if (m_pInstalledServicesInfo[ServiceIndex].lpServiceName &&
  852. 0 == SsrpICompareBstrPwstr(bstrService, m_pInstalledServicesInfo[ServiceIndex].lpServiceName)) {
  853. if (m_bDbg)
  854. wprintf(L"SERVICE is installed: %s\n", bstrService);
  855. m_bArrServiceInKB[ServiceIndex] = 1;
  856. return TRUE;
  857. }
  858. }
  859. }
  860. return FALSE;
  861. }
  862. HRESULT
  863. process::SsrpAddServiceStartup(
  864. IN CComPtr <IXMLDOMElement> pXMLDocElemRoot,
  865. IN CComPtr <IXMLDOMDocument> pXMLDoc
  866. )
  867. /*++
  868. Routine Description:
  869. Routine called to add service startup mode
  870. Arguments:
  871. pXMLDoc - document pointer
  872. pXMLDoc - pointer to document
  873. Return:
  874. HRESULT error code
  875. ++*/
  876. {
  877. HRESULT hr;
  878. CComPtr <IXMLDOMNode> pService;
  879. CComPtr <IXMLDOMNode> pOptional;
  880. CComPtr <IXMLDOMNodeList> pServiceList;
  881. CComVariant Type(NODE_ELEMENT);
  882. WCHAR szStartup[15];
  883. hr = pXMLDocElemRoot->selectNodes(L"Services/Service", &pServiceList);
  884. if (FAILED(hr) || pServiceList == NULL ) {
  885. SsrpLogParseError(hr);
  886. goto ExitHandler;
  887. }
  888. hr = pServiceList->nextNode(&pService);
  889. if (FAILED(hr)) {
  890. SsrpLogParseError(hr);
  891. goto ExitHandler;
  892. }
  893. while (pService) {
  894. CComBSTR bstrText;
  895. CComPtr <IXMLDOMNode> pName;
  896. CComPtr <IXMLDOMNode> pXDNodeServiceStartup;
  897. CComPtr <IXMLDOMNode> pXDNodeServiceInstalled;
  898. hr = pService->selectSingleNode(L"Name", &pName);
  899. if (FAILED(hr) || pName == NULL ) {
  900. SsrpLogParseError(hr);
  901. goto ExitHandler;
  902. }
  903. hr = pName->get_text(&bstrText);
  904. if (FAILED(hr) || !bstrText ) {
  905. SsrpLogParseError(hr);
  906. goto ExitHandler;
  907. }
  908. BYTE byStartupType = FALSE;
  909. BOOL bIsServiceInstalled = FALSE;
  910. DWORD rc = ERROR_SUCCESS;
  911. bIsServiceInstalled = SsrpIsServiceInstalled(bstrText);
  912. if (bIsServiceInstalled) {
  913. rc = SsrpQueryServiceStartupType(bstrText, &byStartupType);
  914. if ( rc != ERROR_SUCCESS) {
  915. //wprintf(L"\nName is %s error %d", bstrText, rc);
  916. goto ExitHandler;
  917. }
  918. if (byStartupType == SERVICE_DISABLED) {
  919. wcscpy(szStartup, L"Disabled");
  920. }
  921. else if (byStartupType == SERVICE_AUTO_START) {
  922. wcscpy(szStartup, L"Automatic");
  923. }
  924. else if (byStartupType == SERVICE_DEMAND_START) {
  925. wcscpy(szStartup, L"Manual");
  926. }
  927. else if (byStartupType == SERVICE_DEMAND_START) {
  928. wcscpy(szStartup, L"");
  929. }
  930. hr = pXMLDoc->createNode(
  931. Type,
  932. L"Current_startup",
  933. NULL,
  934. &pXDNodeServiceStartup);
  935. if (FAILED(hr) || pXDNodeServiceStartup == NULL) {
  936. SsrpLogParseError(hr);
  937. goto ExitHandler;
  938. }
  939. hr = pXDNodeServiceStartup->put_text(szStartup);
  940. if (FAILED(hr)) {
  941. SsrpLogParseError(hr);
  942. goto ExitHandler;
  943. }
  944. hr = pService->appendChild(pXDNodeServiceStartup, NULL);
  945. if (FAILED(hr)) {
  946. SsrpLogParseError(hr);
  947. goto ExitHandler;
  948. }
  949. }
  950. hr = pXMLDoc->createNode(
  951. Type,
  952. L"Installed",
  953. NULL,
  954. &pXDNodeServiceInstalled);
  955. if (FAILED(hr) || pXDNodeServiceInstalled == NULL) {
  956. SsrpLogParseError(hr);
  957. goto ExitHandler;
  958. }
  959. hr = pXDNodeServiceInstalled->put_text((bIsServiceInstalled ? L"TRUE" : L"FALSE"));
  960. if (FAILED(hr)) {
  961. SsrpLogParseError(hr);
  962. goto ExitHandler;
  963. }
  964. hr = pService->appendChild(pXDNodeServiceInstalled, NULL);
  965. if (FAILED(hr)) {
  966. SsrpLogParseError(hr);
  967. goto ExitHandler;
  968. }
  969. pService.Release();
  970. hr = pServiceList->nextNode(&pService);
  971. if (FAILED(hr)) {
  972. SsrpLogParseError(hr);
  973. goto ExitHandler;
  974. }
  975. }
  976. ExitHandler:
  977. return hr;
  978. }
  979. HRESULT
  980. process::SsrpAddUnknownServicestoServices(
  981. IN CComPtr <IXMLDOMElement> pXMLDocElemRoot,
  982. IN CComPtr <IXMLDOMDocument> pXMLDoc
  983. )
  984. /*++
  985. Routine Description:
  986. Routine called to add unknown services to <Services> in the following way
  987. <Service>
  988. <Name> Browser </Name>
  989. <Optional> TRUE </Optional> [This would always be set to TRUE]
  990. <Startup_Default> Manual </Startup_Default> [This would be set to whatever the current startup mode is]
  991. <Current_startup xmlns="">Manual</Current_startup>
  992. <Installed xmlns="">TRUE</Installed> [THIS would always be set to TRUE]
  993. </Service>
  994. Arguments:
  995. pXMLDoc - document pointer
  996. pXMLDoc - pointer to document
  997. Return:
  998. HRESULT error code
  999. ++*/
  1000. {
  1001. HRESULT hr;
  1002. CComPtr <IXMLDOMNode> pServices;
  1003. CComPtr <IXMLDOMNode> pOptional;
  1004. CComPtr <IXMLDOMNodeList> pServiceList;
  1005. CComVariant Type(NODE_ELEMENT);
  1006. WCHAR szStartup[15];
  1007. hr = pXMLDocElemRoot->selectSingleNode(L"Services", &pServices);
  1008. if (FAILED(hr) || pServices == NULL ) {
  1009. SsrpLogParseError(hr);
  1010. goto ExitHandler;
  1011. }
  1012. for (DWORD ServiceIndex=0;
  1013. ServiceIndex < m_dwNumServices;
  1014. ServiceIndex++ ) {
  1015. if (m_bArrServiceInKB[ServiceIndex] == 0){
  1016. CComPtr <IXMLDOMNode> pXDNodeService;
  1017. CComPtr <IXMLDOMNode> pXDNodeServiceName;
  1018. CComPtr <IXMLDOMNode> pXDNodeServiceDescription;
  1019. CComPtr <IXMLDOMNode> pXDNodeServiceDisplayName;
  1020. CComPtr <IXMLDOMNode> pXDNodeServiceMaximum;
  1021. CComPtr <IXMLDOMNode> pXDNodeServiceTypical;
  1022. CComPtr <IXMLDOMNode> pXDNodeInstalled;
  1023. CComPtr <IXMLDOMNode> pXDNodeCurrentStartup;
  1024. hr = SsrpAddWhiteSpace(
  1025. pXMLDoc,
  1026. pServices,
  1027. L"\n\t\t\t\t\t"
  1028. );
  1029. if (FAILED(hr)) {
  1030. SsrpLogParseError(hr);
  1031. goto ExitHandler;
  1032. }
  1033. hr = pXMLDoc->createNode(
  1034. Type,
  1035. L"Service",
  1036. NULL,
  1037. &pXDNodeService);
  1038. if (FAILED(hr) || pXDNodeService == NULL) {
  1039. SsrpLogParseError(hr);
  1040. goto ExitHandler;
  1041. }
  1042. hr = pServices->appendChild(pXDNodeService, NULL);
  1043. if (FAILED(hr)) {
  1044. SsrpLogParseError(hr);
  1045. goto ExitHandler;
  1046. }
  1047. hr = SsrpAddWhiteSpace(
  1048. pXMLDoc,
  1049. pXDNodeService,
  1050. L"\n\t\t\t\t\t\t"
  1051. );
  1052. if (FAILED(hr)) {
  1053. SsrpLogParseError(hr);
  1054. goto ExitHandler;
  1055. }
  1056. hr = pXMLDoc->createNode(
  1057. Type,
  1058. L"Name",
  1059. NULL,
  1060. &pXDNodeServiceName);
  1061. if (FAILED(hr) || pXDNodeServiceName == NULL) {
  1062. SsrpLogParseError(hr);
  1063. goto ExitHandler;
  1064. }
  1065. hr = pXDNodeServiceName->put_text(m_pInstalledServicesInfo[ServiceIndex].lpServiceName);
  1066. if (FAILED(hr)) {
  1067. SsrpLogParseError(hr);
  1068. goto ExitHandler;
  1069. }
  1070. hr = pXDNodeService->appendChild(pXDNodeServiceName, NULL);
  1071. if (FAILED(hr)) {
  1072. SsrpLogParseError(hr);
  1073. goto ExitHandler;
  1074. }
  1075. hr = SsrpAddWhiteSpace(
  1076. pXMLDoc,
  1077. pXDNodeService,
  1078. L"\n\t\t\t\t\t\t"
  1079. );
  1080. if (FAILED(hr)) {
  1081. SsrpLogParseError(hr);
  1082. goto ExitHandler;
  1083. }
  1084. hr = pXMLDoc->createNode(
  1085. Type,
  1086. L"Optional",
  1087. NULL,
  1088. &pXDNodeServiceDisplayName);
  1089. if (FAILED(hr) || pXDNodeServiceDisplayName == NULL) {
  1090. SsrpLogParseError(hr);
  1091. goto ExitHandler;
  1092. }
  1093. hr = pXDNodeServiceDisplayName->put_text(L"TRUE");
  1094. if (FAILED(hr)) {
  1095. SsrpLogParseError(hr);
  1096. goto ExitHandler;
  1097. }
  1098. hr = pXDNodeService->appendChild(pXDNodeServiceDisplayName, NULL);
  1099. if (FAILED(hr)) {
  1100. SsrpLogParseError(hr);
  1101. goto ExitHandler;
  1102. }
  1103. hr = SsrpAddWhiteSpace(
  1104. pXMLDoc,
  1105. pXDNodeService,
  1106. L"\n\t\t\t\t\t\t"
  1107. );
  1108. if (FAILED(hr)) {
  1109. SsrpLogParseError(hr);
  1110. goto ExitHandler;
  1111. }
  1112. hr = pXMLDoc->createNode(
  1113. Type,
  1114. L"Startup_Default",
  1115. NULL,
  1116. &pXDNodeServiceDescription);
  1117. if (FAILED(hr) || pXDNodeServiceDescription == NULL) {
  1118. SsrpLogParseError(hr);
  1119. goto ExitHandler;
  1120. }
  1121. hr = pXMLDoc->createNode(
  1122. Type,
  1123. L"Current_Startup",
  1124. NULL,
  1125. &pXDNodeCurrentStartup);
  1126. if (FAILED(hr) || pXDNodeCurrentStartup == NULL) {
  1127. SsrpLogParseError(hr);
  1128. goto ExitHandler;
  1129. }
  1130. BYTE byStartupType = SERVICE_DISABLED;
  1131. DWORD rc = ERROR_SUCCESS;
  1132. rc = SsrpQueryServiceStartupType(m_pInstalledServicesInfo[ServiceIndex].lpServiceName, &byStartupType);
  1133. if ( rc != ERROR_SUCCESS) {
  1134. //wprintf(L"\nName is %s error %d", m_pInstalledServicesInfo[ServiceIndex].lpServiceName, rc);
  1135. goto ExitHandler;
  1136. }
  1137. if (byStartupType == SERVICE_DISABLED) {
  1138. wcscpy(szStartup, L"Disabled");
  1139. }
  1140. else if (byStartupType == SERVICE_AUTO_START) {
  1141. wcscpy(szStartup, L"Automatic");
  1142. }
  1143. else if (byStartupType == SERVICE_DEMAND_START) {
  1144. wcscpy(szStartup, L"Manual");
  1145. }
  1146. else if (byStartupType == SERVICE_DEMAND_START) {
  1147. wcscpy(szStartup, L"");
  1148. }
  1149. hr = pXDNodeServiceDescription->put_text(szStartup);
  1150. if (FAILED(hr)) {
  1151. SsrpLogParseError(hr);
  1152. goto ExitHandler;
  1153. }
  1154. hr = pXDNodeCurrentStartup->put_text(szStartup);
  1155. if (FAILED(hr)) {
  1156. SsrpLogParseError(hr);
  1157. goto ExitHandler;
  1158. }
  1159. hr = pXDNodeService->appendChild(pXDNodeServiceDescription, NULL);
  1160. if (FAILED(hr)) {
  1161. SsrpLogParseError(hr);
  1162. goto ExitHandler;
  1163. }
  1164. hr = pXDNodeService->appendChild(pXDNodeCurrentStartup, NULL);
  1165. if (FAILED(hr)) {
  1166. SsrpLogParseError(hr);
  1167. goto ExitHandler;
  1168. }
  1169. hr = pXMLDoc->createNode(
  1170. Type,
  1171. L"Installed",
  1172. NULL,
  1173. &pXDNodeInstalled);
  1174. if (FAILED(hr) || pXDNodeInstalled == NULL) {
  1175. SsrpLogParseError(hr);
  1176. goto ExitHandler;
  1177. }
  1178. hr = pXDNodeInstalled->put_text(L"TRUE");
  1179. if (FAILED(hr)) {
  1180. SsrpLogParseError(hr);
  1181. goto ExitHandler;
  1182. }
  1183. hr = pXDNodeService->appendChild(pXDNodeInstalled, NULL);
  1184. if (FAILED(hr)) {
  1185. SsrpLogParseError(hr);
  1186. goto ExitHandler;
  1187. }
  1188. hr = SsrpAddWhiteSpace(
  1189. pXMLDoc,
  1190. pXDNodeService,
  1191. L"\n\t\t\t\t\t\t"
  1192. );
  1193. if (FAILED(hr)) {
  1194. SsrpLogParseError(hr);
  1195. goto ExitHandler;
  1196. }
  1197. }
  1198. }
  1199. ExitHandler:
  1200. return hr;
  1201. }
  1202. DWORD
  1203. process::SsrpQueryServiceDescription(
  1204. IN PWSTR pszServiceName,
  1205. OUT LPSERVICE_DESCRIPTION *ppServiceDescription
  1206. )
  1207. /*++
  1208. Routine Description:
  1209. Routine called to get service description
  1210. Arguments:
  1211. pszServiceName - name of service
  1212. ppServiceDescription - description structure (to be freed outside)
  1213. Return:
  1214. Win32 error code
  1215. ++*/
  1216. {
  1217. DWORD rc = ERROR_SUCCESS;
  1218. DWORD dwBytesNeeded = 0;
  1219. SC_HANDLE hService = NULL;
  1220. LPSERVICE_DESCRIPTION pServiceDescription = NULL;
  1221. if (ppServiceDescription == NULL || pszServiceName == NULL)
  1222. return ERROR_INVALID_PARAMETER;
  1223. *ppServiceDescription = NULL;
  1224. SsrpConvertBstrToPwstr(pszServiceName);
  1225. hService = OpenService(
  1226. m_hScm,
  1227. pszServiceName,
  1228. SERVICE_QUERY_CONFIG |
  1229. READ_CONTROL
  1230. );
  1231. if ( hService == NULL ) {
  1232. rc = GetLastError();
  1233. goto ExitHandler;
  1234. }
  1235. if ( !QueryServiceConfig2(
  1236. hService,
  1237. SERVICE_CONFIG_DESCRIPTION,
  1238. NULL,
  1239. 0,
  1240. &dwBytesNeeded
  1241. )) {
  1242. if (ERROR_INSUFFICIENT_BUFFER != (rc = GetLastError()))
  1243. goto ExitHandler;
  1244. }
  1245. rc = ERROR_SUCCESS;
  1246. pServiceDescription = (LPSERVICE_DESCRIPTION)LocalAlloc(LMEM_ZEROINIT, dwBytesNeeded);
  1247. if ( pServiceDescription == NULL ) {
  1248. rc = ERROR_NOT_ENOUGH_MEMORY;
  1249. goto ExitHandler;
  1250. }
  1251. if ( !QueryServiceConfig2(
  1252. hService,
  1253. SERVICE_CONFIG_DESCRIPTION,
  1254. (LPBYTE)pServiceDescription,
  1255. dwBytesNeeded,
  1256. &dwBytesNeeded
  1257. )) {
  1258. LocalFree(pServiceDescription);
  1259. pServiceDescription = NULL;
  1260. rc = GetLastError();
  1261. goto ExitHandler;
  1262. }
  1263. *ppServiceDescription = pServiceDescription;
  1264. ExitHandler:
  1265. if (hService) {
  1266. CloseServiceHandle(hService);
  1267. }
  1268. return rc;
  1269. }
  1270. PWSTR
  1271. process::SsrpQueryServiceDisplayName(
  1272. IN BSTR bstrService
  1273. )
  1274. /*++
  1275. Routine Description:
  1276. Routine called to get service display name
  1277. Arguments:
  1278. pszServiceName - name of service
  1279. Return:
  1280. pointer to display name string
  1281. ++*/
  1282. {
  1283. for (DWORD ServiceIndex=0; ServiceIndex < m_dwNumServices; ServiceIndex++ ) {
  1284. if (m_pInstalledServicesInfo[ServiceIndex].lpServiceName &&
  1285. 0 == SsrpICompareBstrPwstr(bstrService, m_pInstalledServicesInfo[ServiceIndex].lpServiceName)) {
  1286. return m_pInstalledServicesInfo[ServiceIndex].lpDisplayName;
  1287. }
  1288. }
  1289. return NULL;
  1290. }