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.

1671 lines
43 KiB

  1. // SUPPORT.cpp: implementation of the CEnumRegistryValues and CEnumPrivileges classes.
  2. //
  3. // Copyright (c)1997-1999 Microsoft Corporation
  4. //
  5. //////////////////////////////////////////////////////////////////////
  6. #include "precomp.h"
  7. #include "support.h"
  8. #include "persistmgr.h"
  9. #include <io.h>
  10. #include "requestobject.h"
  11. /*
  12. Routine Description:
  13. Name:
  14. CEnumRegistryValues::CEnumRegistryValues
  15. Functionality:
  16. This is the constructor. Pass along the parameters to the base class
  17. Virtual:
  18. No (you know that, constructor won't be virtual!)
  19. Arguments:
  20. pKeyChain - Pointer to the ISceKeyChain COM interface which is prepared
  21. by the caller who constructs this instance.
  22. pNamespace - Pointer to WMI namespace of our provider (COM interface).
  23. Passed along by the caller. Must not be NULL.
  24. pCtx - Pointer to WMI context object (COM interface). Passed along
  25. by the caller. It's up to WMI whether this interface pointer is NULL or not.
  26. Return Value:
  27. None as any constructor
  28. Notes:
  29. if you create any local members, think about initialize them here
  30. */
  31. CEnumRegistryValues::CEnumRegistryValues (
  32. IN ISceKeyChain * pKeyChain,
  33. IN IWbemServices * pNamespace,
  34. IN IWbemContext * pCtx
  35. )
  36. :
  37. CGenericClass(pKeyChain, pNamespace, pCtx)
  38. {
  39. }
  40. /*
  41. Routine Description:
  42. Name:
  43. CEnumRegistryValues::~CEnumRegistryValues
  44. Functionality:
  45. Destructor. Necessary as good C++ discipline since we have virtual functions.
  46. Virtual:
  47. Yes.
  48. Arguments:
  49. none as any destructor
  50. Return Value:
  51. None as any destructor
  52. Notes:
  53. if you create any local members, think about whether
  54. there is any need for a non-trivial destructor
  55. */
  56. CEnumRegistryValues::~CEnumRegistryValues()
  57. {
  58. }
  59. /*
  60. Routine Description:
  61. Name:
  62. CEnumRegistryValues::CreateObject
  63. Functionality:
  64. Create WMI objects (Sce_KnownRegistryValues). Depending on parameter atAction,
  65. this creation may mean:
  66. (a) Get a single instance (atAction == ACTIONTYPE_GET)
  67. (b) Get several instances satisfying some criteria (atAction == ACTIONTYPE_QUERY)
  68. (c) Delete an instance (atAction == ACTIONTYPE_DELETE)
  69. Virtual:
  70. Yes.
  71. Arguments:
  72. pHandler - COM interface pointer for notifying WMI for creation result.
  73. atAction - Get single instance ACTIONTYPE_GET
  74. Get several instances ACTIONTYPE_QUERY
  75. Delete a single instance ACTIONTYPE_DELETE
  76. Return Value:
  77. Success: it must return success code (use SUCCEEDED to test). It is
  78. not guaranteed to return WBEM_NO_ERROR. The returned objects are indicated to WMI,
  79. not directly passed back via parameters.
  80. Failure: Various errors may occurs. Except WBEM_E_NOT_FOUND, any such error should indicate
  81. the failure of getting the wanted instance. If WBEM_E_NOT_FOUND is returned in querying
  82. situations, this may not be an error depending on caller's intention.
  83. Notes:
  84. */
  85. HRESULT CEnumRegistryValues::CreateObject (
  86. IN IWbemObjectSink * pHandler,
  87. IN ACTIONTYPE atAction
  88. )
  89. {
  90. //
  91. // we know how to:
  92. // Enumerate instances ACTIONTYPE_ENUM
  93. // Get single instance ACTIONTYPE_GET
  94. // Get several instances ACTIONTYPE_QUERY
  95. // Delete a single instance ACTIONTYPE_DELETE
  96. //
  97. HRESULT hr = WBEM_S_NO_ERROR;
  98. if ( ACTIONTYPE_ENUM != atAction &&
  99. ACTIONTYPE_GET != atAction &&
  100. ACTIONTYPE_QUERY != atAction &&
  101. ACTIONTYPE_DELETE != atAction )
  102. {
  103. return WBEM_E_NOT_SUPPORTED;
  104. }
  105. //
  106. // We must have the pPathName property.
  107. //
  108. CComVariant varPathName;
  109. if ( ACTIONTYPE_ENUM != atAction )
  110. {
  111. //
  112. // We are not enumerating, let's determine the scope of enumeration
  113. // by testing the path property. If it existis, it must be a bstr.
  114. //
  115. hr = m_srpKeyChain->GetKeyPropertyValue(pPathName, &varPathName);
  116. }
  117. //
  118. // if enumeratig, or querying without a path, then get all
  119. //
  120. if ( ACTIONTYPE_ENUM == atAction ||
  121. (ACTIONTYPE_QUERY == atAction && varPathName.vt != VT_BSTR ) )
  122. {
  123. //
  124. // enumerate all supported registry values
  125. //
  126. hr = EnumerateInstances(pHandler);
  127. }
  128. else if (varPathName.vt == VT_BSTR )
  129. {
  130. //
  131. // convert the reg path from \ to /
  132. // Create the registry value instance
  133. //
  134. CComBSTR bstrKeyName;
  135. CComBSTR bstrLogName;
  136. hr = MakeSingleBackSlashPath(varPathName.bstrVal, L'\\', &bstrLogName);
  137. if ( SUCCEEDED(hr) )
  138. {
  139. bstrKeyName = SysAllocString(bstrLogName);
  140. if ( bstrKeyName )
  141. {
  142. for ( PWSTR pTemp = (PWSTR)bstrKeyName; *pTemp != L'\0'; pTemp++ )
  143. {
  144. if ( *pTemp == L'\\' )
  145. {
  146. *pTemp = L'/';
  147. }
  148. }
  149. hr = WBEM_S_NO_ERROR;
  150. }
  151. else
  152. {
  153. hr = WBEM_E_OUT_OF_MEMORY;
  154. }
  155. }
  156. //
  157. // successfully converted the backslashed path to forward slashed path
  158. //
  159. if ( SUCCEEDED(hr) )
  160. {
  161. if ( ACTIONTYPE_DELETE == atAction )
  162. {
  163. hr = DeleteInstance(pHandler, bstrKeyName);
  164. }
  165. else
  166. {
  167. hr = ConstructInstance(pHandler, bstrKeyName, bstrLogName, NULL);
  168. }
  169. }
  170. }
  171. return hr;
  172. }
  173. /*
  174. Routine Description:
  175. Name:
  176. CEnumRegistryValues::PutInst
  177. Functionality:
  178. Put an instance as instructed by WMI. Since this class implements Sce_KnownRegistryValues,
  179. which is registry persistence oriented, this will cause the Sce_KnownRegistryValues object's property
  180. information to be saved in the registry.
  181. Virtual:
  182. Yes.
  183. Arguments:
  184. pInst - COM interface pointer to the WMI class (Sce_KnownRegistryValues) object.
  185. pHandler - COM interface pointer for notifying WMI of any events.
  186. pCtx - COM interface pointer. This interface is just something we pass around.
  187. WMI may mandate it (not now) in the future. But we never construct
  188. such an interface and so, we just pass around for various WMI API's
  189. Return Value:
  190. Success: it must return success code (use SUCCEEDED to test). It is
  191. not guaranteed to return WBEM_NO_ERROR.
  192. Failure: Various errors may occurs. Any such error should indicate the failure of persisting
  193. the instance.
  194. Notes:
  195. Since GetProperty will return a success code (WBEM_S_RESET_TO_DEFAULT) when the
  196. requested property is not present, don't simply use SUCCEEDED or FAILED macros
  197. to test for the result of retrieving a property.
  198. */
  199. HRESULT CEnumRegistryValues::PutInst (
  200. IN IWbemClassObject * pInst,
  201. IN IWbemObjectSink * pHandler,
  202. IN IWbemContext * pCtx
  203. )
  204. {
  205. HRESULT hr = WBEM_E_INVALID_PARAMETER;
  206. CComBSTR bstrRegPath;
  207. CComBSTR bstrConvertPath;
  208. CComBSTR bstrDispName;
  209. CComBSTR bstrUnits;
  210. PSCE_NAME_LIST pnlChoice = NULL;
  211. PSCE_NAME_LIST pnlResult = NULL;
  212. //
  213. // CScePropertyMgr helps us to access WMI object's properties
  214. // create an instance and attach the WMI object to it.
  215. // This will always succeed.
  216. //
  217. CScePropertyMgr ScePropMgr;
  218. ScePropMgr.Attach(pInst);
  219. DWORD RegType=0;
  220. DWORD DispType=0;
  221. //
  222. // the use of the macro SCE_PROV_IfErrorGotoCleanup cause
  223. // a "goto CleanUp;" with hr set to the return value from
  224. // the function (macro parameter)
  225. //
  226. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.GetProperty(pPathName, &bstrRegPath));
  227. //
  228. // convert double back slash to /
  229. //
  230. SCE_PROV_IfErrorGotoCleanup(MakeSingleBackSlashPath(bstrRegPath, L'/', &bstrConvertPath));
  231. //
  232. // make sure single back slash is handled too.
  233. //
  234. for ( PWSTR pTemp= bstrConvertPath; *pTemp != L'\0'; pTemp++)
  235. {
  236. if ( *pTemp == L'\\' )
  237. {
  238. *pTemp = L'/';
  239. }
  240. }
  241. //
  242. // type info must exists
  243. //
  244. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.GetProperty(pType, &RegType));
  245. if ( hr == WBEM_S_RESET_TO_DEFAULT)
  246. {
  247. hr = WBEM_E_ILLEGAL_NULL;
  248. goto CleanUp;
  249. }
  250. //
  251. // We also need DisplayDialog property
  252. //
  253. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.GetProperty(pDisplayDialog, &DispType));
  254. if ( hr == WBEM_S_RESET_TO_DEFAULT)
  255. {
  256. hr = WBEM_E_ILLEGAL_NULL;
  257. goto CleanUp;
  258. }
  259. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.GetProperty(pDisplayName, &bstrDispName));
  260. if ( DispType == SCE_REG_DISPLAY_CHOICE )
  261. {
  262. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.GetProperty(pDisplayChoice, &pnlChoice));
  263. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.GetProperty(pDisplayChoiceResult, &pnlResult));
  264. }
  265. else if ( DispType == SCE_REG_DISPLAY_NUMBER )
  266. {
  267. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.GetProperty(pUnits, &bstrUnits));
  268. }
  269. //
  270. // now save the info to registry
  271. //
  272. hr = SavePropertyToReg( bstrConvertPath, RegType, DispType, bstrDispName, bstrUnits, pnlChoice, pnlResult);
  273. CleanUp:
  274. if ( pnlChoice )
  275. {
  276. SceFreeMemory(pnlChoice, SCE_STRUCT_NAME_LIST);
  277. }
  278. if ( pnlResult )
  279. {
  280. SceFreeMemory(pnlResult, SCE_STRUCT_NAME_LIST);
  281. }
  282. return hr;
  283. }
  284. /*
  285. Routine Description:
  286. Name:
  287. CEnumRegistryValues::EnumerateInstances
  288. Functionality:
  289. Private helper to enumerate all registry values supported by SCE from registry.
  290. Virtual:
  291. No.
  292. Arguments:
  293. pHandler - COM interface pointer for notifying WMI of any events.
  294. Return Value:
  295. Success: it must return success code (use SUCCEEDED to test). It is
  296. not guaranteed to return WBEM_NO_ERROR.
  297. Failure: Various errors may occurs. Any such error should indicate the failure of persisting
  298. the instance.
  299. Notes:
  300. This is a registry reading routine. Refer to MSDN if you have questions.
  301. */
  302. HRESULT
  303. CEnumRegistryValues::EnumerateInstances (
  304. IN IWbemObjectSink *pHandler
  305. )
  306. {
  307. DWORD Win32Rc;
  308. HKEY hKey=NULL;
  309. DWORD cSubKeys = 0;
  310. DWORD nMaxLen;
  311. HRESULT hr;
  312. PWSTR szName=NULL;
  313. BSTR bstrName=NULL;
  314. Win32Rc = RegOpenKeyEx(
  315. HKEY_LOCAL_MACHINE,
  316. SCE_ROOT_REGVALUE_PATH,
  317. 0,
  318. KEY_READ,
  319. &hKey
  320. );
  321. if ( Win32Rc == ERROR_SUCCESS )
  322. {
  323. //
  324. // enumerate all subkeys of the key
  325. //
  326. Win32Rc = RegQueryInfoKey (
  327. hKey,
  328. NULL,
  329. NULL,
  330. NULL,
  331. &cSubKeys,
  332. &nMaxLen,
  333. NULL,
  334. NULL,
  335. NULL,
  336. NULL,
  337. NULL,
  338. NULL
  339. );
  340. }
  341. hr = ProvDosErrorToWbemError(Win32Rc);
  342. if ( Win32Rc == ERROR_SUCCESS && cSubKeys > 0 )
  343. {
  344. szName = (PWSTR)LocalAlloc(0, (nMaxLen+2)*sizeof(WCHAR));
  345. if ( !szName )
  346. {
  347. hr = WBEM_E_OUT_OF_MEMORY;
  348. }
  349. else
  350. {
  351. DWORD BufSize;
  352. DWORD index = 0;
  353. do {
  354. BufSize = nMaxLen + 1;
  355. Win32Rc = RegEnumKeyEx(
  356. hKey,
  357. index,
  358. szName,
  359. &BufSize,
  360. NULL,
  361. NULL,
  362. NULL,
  363. NULL);
  364. if ( ERROR_SUCCESS == Win32Rc )
  365. {
  366. index++;
  367. //
  368. // convert the path name (from single / to double \\)
  369. //
  370. bstrName = SysAllocString(szName);
  371. if ( bstrName == NULL )
  372. {
  373. hr = WBEM_E_OUT_OF_MEMORY;
  374. break;
  375. }
  376. //
  377. // replace / with \.
  378. //
  379. for ( PWSTR pTemp=(PWSTR)bstrName; *pTemp != L'\0'; pTemp++)
  380. {
  381. if ( *pTemp == L'/' )
  382. {
  383. *pTemp = L'\\';
  384. }
  385. }
  386. //
  387. // get all information from registry for this key
  388. // and create an instance
  389. //
  390. hr = ConstructInstance(pHandler, szName, bstrName, hKey);
  391. SysFreeString(bstrName);
  392. bstrName = NULL;
  393. if ( FAILED(hr) )
  394. {
  395. break;
  396. }
  397. }
  398. else if ( ERROR_NO_MORE_ITEMS != Win32Rc )
  399. {
  400. hr = ProvDosErrorToWbemError(Win32Rc);
  401. break;
  402. }
  403. } while ( Win32Rc != ERROR_NO_MORE_ITEMS );
  404. LocalFree(szName);
  405. szName = NULL;
  406. if ( bstrName )
  407. {
  408. SysFreeString(bstrName);
  409. }
  410. }
  411. }
  412. if ( hKey )
  413. {
  414. RegCloseKey(hKey);
  415. }
  416. return hr;
  417. }
  418. /*
  419. Routine Description:
  420. Name:
  421. CEnumRegistryValues::ConstructInstance
  422. Functionality:
  423. This is private function to create an instance of Sce_KnownRegistryValues.
  424. Virtual:
  425. No.
  426. Arguments:
  427. pHandler - COM interface pointer for notifying WMI of any events.
  428. wszRegKeyName - name of the registry key.
  429. wszRegPath - the registry key's path.
  430. hKeyRoot - Root key.
  431. Return Value:
  432. Success: it must return success code (use SUCCEEDED to test). It is
  433. not guaranteed to return WBEM_NO_ERROR.
  434. Failure: Various errors may occurs. Any such error should indicate the creating the instance.
  435. Notes:
  436. (1) This is a registry reading routine. Refer to MSDN if you have questions.
  437. (2) There are numerous memory allocations. Make sure that you don't blindly
  438. short-circuit return and cause memory leaks.
  439. (3) It also opens registry keys. Don't forget to close them. Make sure that
  440. you don't blindly short-circuit return and cause key handle leaks.
  441. */
  442. HRESULT CEnumRegistryValues::ConstructInstance (
  443. IN IWbemObjectSink * pHandler,
  444. IN LPCWSTR wszRegKeyName,
  445. IN LPCWSTR wszRegPath,
  446. IN HKEY hKeyRoot OPTIONAL
  447. )
  448. {
  449. //
  450. // Get registry information
  451. //
  452. HRESULT hr = WBEM_S_NO_ERROR;
  453. DWORD Win32Rc = NO_ERROR;
  454. HKEY hKey1 = NULL;
  455. HKEY hKey = NULL;
  456. DWORD dSize = sizeof(DWORD);
  457. DWORD RegType = 0;
  458. PWSTR szDisplayName = NULL;
  459. PWSTR szUnit = NULL;
  460. PWSTR mszChoices = NULL;
  461. int dType = -1;
  462. int dDispType = -1;
  463. if ( hKeyRoot )
  464. {
  465. hKey = hKeyRoot;
  466. }
  467. else
  468. {
  469. //
  470. // open the root key
  471. //
  472. Win32Rc = RegOpenKeyEx(
  473. HKEY_LOCAL_MACHINE,
  474. SCE_ROOT_REGVALUE_PATH,
  475. 0,
  476. KEY_READ,
  477. &hKey
  478. );
  479. if ( Win32Rc != NO_ERROR )
  480. {
  481. //
  482. // translate win32 error into HRESULT error
  483. //
  484. return ProvDosErrorToWbemError(Win32Rc);
  485. }
  486. }
  487. //
  488. // try to open the reg key
  489. //
  490. if (( Win32Rc = RegOpenKeyEx(hKey,
  491. wszRegKeyName,
  492. 0,
  493. KEY_READ,
  494. &hKey1
  495. )) == ERROR_SUCCESS )
  496. {
  497. //
  498. // get reg type
  499. //
  500. Win32Rc = RegQueryValueEx(hKey1,
  501. SCE_REG_VALUE_TYPE,
  502. 0,
  503. &RegType,
  504. (BYTE *)&dType,
  505. &dSize
  506. );
  507. if ( Win32Rc == ERROR_FILE_NOT_FOUND )
  508. {
  509. Win32Rc = NO_ERROR;
  510. }
  511. if ( Win32Rc == NO_ERROR )
  512. {
  513. //
  514. // get display type
  515. //
  516. dSize = sizeof(DWORD);
  517. Win32Rc = RegQueryValueEx(hKey1,
  518. SCE_REG_DISPLAY_TYPE,
  519. 0,
  520. &RegType,
  521. (BYTE *)&dDispType,
  522. &dSize
  523. );
  524. if ( Win32Rc == ERROR_FILE_NOT_FOUND )
  525. {
  526. Win32Rc = NO_ERROR;
  527. }
  528. if ( Win32Rc == NO_ERROR )
  529. {
  530. //
  531. // get display name
  532. //
  533. dSize = 0;
  534. Win32Rc = RegQueryValueEx(hKey1,
  535. SCE_REG_DISPLAY_NAME,
  536. 0,
  537. &RegType,
  538. NULL,
  539. &dSize
  540. );
  541. if ( Win32Rc == NO_ERROR )
  542. {
  543. if ( RegType != REG_SZ )
  544. {
  545. Win32Rc = ERROR_INVALID_DATA;
  546. }
  547. }
  548. if ( Win32Rc == NO_ERROR )
  549. {
  550. //
  551. // need to free it!
  552. //
  553. szDisplayName = (PWSTR)LocalAlloc(LPTR, (dSize+1)*sizeof(WCHAR));
  554. if ( szDisplayName == NULL )
  555. {
  556. Win32Rc = ERROR_NOT_ENOUGH_MEMORY;
  557. }
  558. }
  559. if ( Win32Rc == NO_ERROR )
  560. {
  561. Win32Rc = RegQueryValueEx(hKey1,
  562. SCE_REG_DISPLAY_NAME,
  563. 0,
  564. &RegType,
  565. (BYTE *)szDisplayName, // prefast will complain about this line
  566. &dSize
  567. );
  568. }
  569. if ( Win32Rc == ERROR_FILE_NOT_FOUND )
  570. {
  571. Win32Rc = NO_ERROR;
  572. }
  573. if ( Win32Rc == NO_ERROR )
  574. {
  575. //
  576. // get display unit
  577. //
  578. dSize = 0;
  579. Win32Rc = RegQueryValueEx(hKey1,
  580. SCE_REG_DISPLAY_UNIT,
  581. 0,
  582. &RegType,
  583. NULL,
  584. &dSize
  585. );
  586. if ( Win32Rc == NO_ERROR )
  587. {
  588. if ( RegType != REG_SZ )
  589. {
  590. Win32Rc = ERROR_INVALID_DATA;
  591. }
  592. }
  593. if ( Win32Rc == NO_ERROR )
  594. {
  595. //
  596. // need to free it!
  597. //
  598. szUnit = (PWSTR)LocalAlloc(LPTR, (dSize+1)*sizeof(WCHAR));
  599. if ( szUnit == NULL )
  600. {
  601. Win32Rc = ERROR_NOT_ENOUGH_MEMORY;
  602. }
  603. }
  604. if ( Win32Rc == NO_ERROR )
  605. {
  606. Win32Rc = RegQueryValueEx(hKey1,
  607. SCE_REG_DISPLAY_UNIT,
  608. 0,
  609. &RegType,
  610. (BYTE *)szUnit, // prefast will complain about this line
  611. &dSize
  612. );
  613. }
  614. if ( Win32Rc == ERROR_FILE_NOT_FOUND )
  615. {
  616. Win32Rc = NO_ERROR;
  617. }
  618. if ( Win32Rc == NO_ERROR )
  619. {
  620. //
  621. // get display choices
  622. //
  623. dSize = 0;
  624. Win32Rc = RegQueryValueEx(hKey1,
  625. SCE_REG_DISPLAY_CHOICES,
  626. 0,
  627. &RegType,
  628. NULL,
  629. &dSize
  630. ) ;
  631. if ( Win32Rc == NO_ERROR )
  632. {
  633. if ( RegType != REG_MULTI_SZ )
  634. {
  635. Win32Rc = ERROR_INVALID_DATA;
  636. }
  637. }
  638. if ( Win32Rc == NO_ERROR )
  639. {
  640. //
  641. // Need to free it
  642. //
  643. mszChoices = (PWSTR)LocalAlloc(LPTR, (dSize+2)*sizeof(WCHAR));
  644. if ( mszChoices == NULL )
  645. {
  646. Win32Rc = ERROR_NOT_ENOUGH_MEMORY;
  647. }
  648. }
  649. if ( Win32Rc == NO_ERROR )
  650. {
  651. Win32Rc = RegQueryValueEx(hKey1,
  652. SCE_REG_DISPLAY_CHOICES,
  653. 0,
  654. &RegType,
  655. (BYTE *)mszChoices, // prefast will complain about this line
  656. &dSize
  657. );
  658. }
  659. if ( Win32Rc == ERROR_FILE_NOT_FOUND )
  660. {
  661. Win32Rc = NO_ERROR;
  662. }
  663. }
  664. }
  665. }
  666. }
  667. }
  668. hr = ProvDosErrorToWbemError(Win32Rc);
  669. PSCE_NAME_LIST pnlChoice=NULL;
  670. PSCE_NAME_LIST pnlResult=NULL;
  671. if ( Win32Rc == NO_ERROR )
  672. {
  673. //
  674. // break up choices
  675. //
  676. PWSTR pT2;
  677. DWORD Len;
  678. SCESTATUS rc;
  679. for ( PWSTR pTemp = mszChoices; pTemp != NULL && pTemp[0] != L'\0'; )
  680. {
  681. Len = wcslen(pTemp);
  682. pT2 = wcschr(pTemp, L'|');
  683. if ( pT2 )
  684. {
  685. rc = SceAddToNameList(&pnlResult, pTemp, (DWORD)(pT2-pTemp));
  686. if ( rc == SCESTATUS_SUCCESS )
  687. {
  688. rc = SceAddToNameList(&pnlChoice, pT2 + 1, Len - (DWORD)(pT2 - pTemp) - 1);
  689. }
  690. Win32Rc = ProvSceStatusToDosError(rc);
  691. pTemp += Len + 1;
  692. }
  693. else
  694. {
  695. Win32Rc = ERROR_INVALID_DATA;
  696. break;
  697. }
  698. }
  699. }
  700. hr = ProvDosErrorToWbemError(Win32Rc);
  701. //
  702. // the use of the macro SCE_PROV_IfErrorGotoCleanup cause
  703. // a "goto CleanUp;" with hr set to the return value from
  704. // the function (macro parameter)
  705. //
  706. if ( Win32Rc == NO_ERROR )
  707. {
  708. //
  709. // now create the WMI instance
  710. //
  711. CComPtr<IWbemClassObject> srpObj;
  712. SCE_PROV_IfErrorGotoCleanup(SpawnAnInstance(&srpObj));
  713. //
  714. // CScePropertyMgr helps us to access WMI object's properties
  715. // create an instance and attach the WMI object to it.
  716. // This will always succeed.
  717. //
  718. CScePropertyMgr ScePropMgr;
  719. ScePropMgr.Attach(srpObj);
  720. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pPathName, wszRegPath));
  721. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pType, (DWORD)dType ));
  722. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pDisplayDialog, (DWORD)dDispType ));
  723. if ( szDisplayName )
  724. {
  725. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pDisplayName, szDisplayName ));
  726. }
  727. if ( szUnit )
  728. {
  729. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pUnits, szUnit ));
  730. }
  731. if ( pnlChoice )
  732. {
  733. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pDisplayChoice, pnlChoice ));
  734. }
  735. if ( pnlResult )
  736. {
  737. SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pDisplayChoiceResult, pnlResult ));
  738. }
  739. //
  740. // give WMI the instance
  741. //
  742. hr = pHandler->Indicate(1, &srpObj);
  743. }
  744. CleanUp:
  745. if( hKey1 )
  746. {
  747. RegCloseKey( hKey1 );
  748. }
  749. if ( szDisplayName )
  750. {
  751. LocalFree(szDisplayName);
  752. }
  753. if ( szUnit )
  754. {
  755. LocalFree(szUnit);
  756. }
  757. if ( mszChoices )
  758. {
  759. LocalFree(mszChoices);
  760. }
  761. if ( pnlChoice )
  762. {
  763. SceFreeMemory(pnlChoice, SCE_STRUCT_NAME_LIST);
  764. }
  765. if ( pnlResult )
  766. {
  767. SceFreeMemory(pnlResult, SCE_STRUCT_NAME_LIST);
  768. }
  769. if ( hKey != hKeyRoot )
  770. {
  771. RegCloseKey(hKey);
  772. }
  773. return hr;
  774. }
  775. /*
  776. Routine Description:
  777. Name:
  778. CEnumRegistryValues::DeleteInstance
  779. Functionality:
  780. This is private function to delete an instance of Sce_KnownRegistryValues.
  781. Virtual:
  782. No.
  783. Arguments:
  784. pHandler - COM interface pointer for notifying WMI of any events. Not used here.
  785. wszRegKeyName - name of the registry key.
  786. Return Value:
  787. Success: it must return success code (use SUCCEEDED to test). It is
  788. not guaranteed to return WBEM_NO_ERROR.
  789. Failure: Various errors may occurs. Any such error should indicate the creating the instance.
  790. Notes:
  791. (1) This is a registry reading routine. Refer to MSDN if you have questions.
  792. (2) It also opens registry keys. Don't forget to close them. Make sure that
  793. you don't blindly short-circuit return and cause key handle leaks.
  794. Notes:
  795. */
  796. HRESULT CEnumRegistryValues::DeleteInstance (
  797. IN IWbemObjectSink * pHandler,
  798. IN LPCWSTR wszRegKeyName
  799. )
  800. {
  801. HKEY hKey = NULL;
  802. DWORD Win32Rc;
  803. //
  804. // open the root key
  805. //
  806. Win32Rc = RegOpenKeyEx(
  807. HKEY_LOCAL_MACHINE,
  808. SCE_ROOT_REGVALUE_PATH,
  809. 0,
  810. KEY_WRITE,
  811. &hKey
  812. );
  813. if ( Win32Rc == NO_ERROR )
  814. {
  815. //
  816. // delete the subkey
  817. //
  818. Win32Rc = RegDeleteKey (hKey, wszRegKeyName);
  819. }
  820. if ( hKey )
  821. {
  822. RegCloseKey(hKey);
  823. }
  824. return ProvDosErrorToWbemError(Win32Rc);
  825. }
  826. /*
  827. Routine Description:
  828. Name:
  829. CEnumRegistryValues::SavePropertyToReg
  830. Functionality:
  831. This is private function to save instance of Sce_KnownRegistryValues to registry.
  832. Virtual:
  833. No.
  834. Arguments:
  835. wszKeyName - name of the registry key. Property of the WMI class (Sce_KnownRegistryValues).
  836. RegType - Property of the WMI class.
  837. DispType - Property of the WMI class.
  838. wszDispName - Property of the WMI class.
  839. wszUnits - Property of the WMI class.
  840. pnlChoice - Property of the WMI class.
  841. pnlResult - name of the registry key.
  842. Return Value:
  843. Success: it must return success code (use SUCCEEDED to test). It is
  844. not guaranteed to return WBEM_NO_ERROR.
  845. Failure: Various errors may occurs. Any such error should indicate the creating the instance.
  846. Notes:
  847. (1) This is a registry reading routine. Refer to MSDN if you have questions.
  848. (2) It also opens registry keys. Don't forget to close them. Make sure that
  849. you don't blindly short-circuit return and cause key handle leaks.
  850. (3) It also allocates heap memory. Make sure that you don't blindly
  851. short-circuit return and cause memory leaks.
  852. Notes:
  853. */
  854. HRESULT CEnumRegistryValues::SavePropertyToReg (
  855. IN LPCWSTR wszKeyName,
  856. IN int RegType,
  857. IN int DispType,
  858. IN LPCWSTR wszDispName,
  859. IN LPCWSTR wszUnits,
  860. IN PSCE_NAME_LIST pnlChoice,
  861. IN PSCE_NAME_LIST pnlResult
  862. )
  863. {
  864. if ( wszKeyName == NULL )
  865. {
  866. return WBEM_E_INVALID_PARAMETER;
  867. }
  868. //
  869. // merge pnlChoice and pnlResult to one buffer
  870. //
  871. DWORD Len=0;
  872. PSCE_NAME_LIST pName;
  873. DWORD cnt1,cnt2;
  874. for ( cnt1=0, pName=pnlChoice; pName != NULL; cnt1++, pName=pName->Next)
  875. {
  876. Len += wcslen(pName->Name);
  877. }
  878. for ( cnt2=0, pName=pnlResult; pName != NULL; cnt2++, pName=pName->Next)
  879. {
  880. Len += wcslen(pName->Name);
  881. }
  882. if ( cnt1 != cnt2 )
  883. {
  884. return WBEM_E_INVALID_PARAMETER;
  885. }
  886. PWSTR mszChoices=NULL;
  887. if ( cnt1 != 0 )
  888. {
  889. //
  890. // each string has a | and a \0
  891. //
  892. Len += cnt1 * 2 + 1;
  893. //
  894. // need to free the memory pointed to by mszChoices
  895. //
  896. mszChoices = (PWSTR)LocalAlloc(LPTR, Len*sizeof(WCHAR));
  897. if ( mszChoices == NULL )
  898. {
  899. return WBEM_E_OUT_OF_MEMORY;
  900. }
  901. }
  902. PWSTR pTemp = mszChoices;
  903. pName = pnlResult;
  904. PSCE_NAME_LIST pName2 = pnlChoice;
  905. while ( pName )
  906. {
  907. //
  908. // these wcscpy are not overrunning the buffer. See size of allocation above
  909. //
  910. wcscpy(pTemp, pName->Name);
  911. pTemp += wcslen(pName->Name);
  912. *pTemp++ = L'|';
  913. wcscpy(pTemp, pName2->Name);
  914. pTemp += wcslen(pName2->Name);
  915. *pTemp++ = L'\0';
  916. pName = pName->Next;
  917. pName2 = pName2->Next;
  918. }
  919. HRESULT hr=WBEM_S_NO_ERROR;
  920. DWORD rc;
  921. DWORD Disp;
  922. HKEY hKeyRoot=NULL;
  923. HKEY hKey=NULL;
  924. rc = RegCreateKeyEx(
  925. HKEY_LOCAL_MACHINE,
  926. SCE_ROOT_REGVALUE_PATH,
  927. 0,
  928. NULL, // LPTSTR lpClass,
  929. REG_OPTION_NON_VOLATILE,
  930. KEY_WRITE, // KEY_SET_VALUE,
  931. NULL, // &SecurityAttributes,
  932. &hKeyRoot,
  933. &Disp
  934. );
  935. if ( rc == ERROR_SUCCESS )
  936. {
  937. rc = RegCreateKeyEx(
  938. hKeyRoot,
  939. wszKeyName,
  940. 0,
  941. NULL,
  942. 0,
  943. KEY_WRITE,
  944. NULL,
  945. &hKey,
  946. &Disp
  947. );
  948. if ( rc == ERROR_SUCCESS )
  949. {
  950. DWORD dValue = RegType;
  951. rc = RegSetValueEx (hKey,
  952. SCE_REG_VALUE_TYPE,
  953. 0,
  954. REG_DWORD,
  955. (BYTE *)&dValue,
  956. sizeof(DWORD)
  957. );
  958. if ( rc == ERROR_SUCCESS )
  959. {
  960. dValue = DispType;
  961. rc = RegSetValueEx (hKey,
  962. SCE_REG_DISPLAY_TYPE,
  963. 0,
  964. REG_DWORD,
  965. (BYTE *)&dValue,
  966. sizeof(DWORD)
  967. );
  968. if ( rc == ERROR_SUCCESS && wszDispName )
  969. {
  970. rc = RegSetValueEx (hKey,
  971. SCE_REG_DISPLAY_NAME,
  972. 0,
  973. REG_SZ,
  974. (BYTE *)wszDispName, // prefast will complain about this line
  975. (wcslen(wszDispName)+1)*sizeof(WCHAR)
  976. );
  977. }
  978. if ( rc == ERROR_SUCCESS && wszUnits )
  979. {
  980. rc = RegSetValueEx (hKey,
  981. SCE_REG_DISPLAY_UNIT,
  982. 0,
  983. REG_SZ,
  984. (BYTE *)wszUnits, // prefast will complain about this line
  985. (wcslen(wszUnits)+1)*sizeof(WCHAR)
  986. );
  987. }
  988. if ( rc == ERROR_SUCCESS && mszChoices )
  989. {
  990. rc = RegSetValueEx (hKey,
  991. SCE_REG_DISPLAY_CHOICES,
  992. 0,
  993. REG_MULTI_SZ,
  994. (BYTE *)mszChoices, // prefast will complain about this line
  995. Len*sizeof(WCHAR)
  996. );
  997. }
  998. }
  999. if ( rc != ERROR_SUCCESS && REG_CREATED_NEW_KEY == Disp )
  1000. {
  1001. //
  1002. // something failed during create/save the registry thing
  1003. // delete it if it's created
  1004. //
  1005. RegCloseKey(hKey);
  1006. hKey = NULL;
  1007. RegDeleteKey (hKeyRoot, wszKeyName);
  1008. }
  1009. }
  1010. }
  1011. if ( hKeyRoot )
  1012. {
  1013. RegCloseKey(hKeyRoot);
  1014. }
  1015. if ( hKey )
  1016. {
  1017. RegCloseKey(hKey);
  1018. }
  1019. hr = ProvDosErrorToWbemError(rc);
  1020. LocalFree(mszChoices);
  1021. return hr;
  1022. }
  1023. //=====================================================================
  1024. // implementing CEnumPrivileges
  1025. //=====================================================================
  1026. /*
  1027. Routine Description:
  1028. Name:
  1029. CEnumPrivileges::CEnumPrivileges
  1030. Functionality:
  1031. This is the constructor. Pass along the parameters to the base class
  1032. Virtual:
  1033. No (you know that, constructor won't be virtual!)
  1034. Arguments:
  1035. pKeyChain - Pointer to the ISceKeyChain COM interface which is prepared
  1036. by the caller who constructs this instance.
  1037. pNamespace - Pointer to WMI namespace of our provider (COM interface).
  1038. Passed along by the caller. Must not be NULL.
  1039. pCtx - Pointer to WMI context object (COM interface). Passed along
  1040. by the caller. It's up to WMI whether this interface pointer is NULL or not.
  1041. Return Value:
  1042. None as any constructor
  1043. Notes:
  1044. if you create any local members, think about initialize them here
  1045. */
  1046. CEnumPrivileges::CEnumPrivileges (
  1047. IN ISceKeyChain * pKeyChain,
  1048. IN IWbemServices * pNamespace,
  1049. IN IWbemContext * pCtx
  1050. )
  1051. :
  1052. CGenericClass(pKeyChain, pNamespace, pCtx)
  1053. {
  1054. }
  1055. /*
  1056. Routine Description:
  1057. Name:
  1058. CEnumPrivileges::~CEnumPrivileges
  1059. Functionality:
  1060. Destructor. Necessary as good C++ discipline since we have virtual functions.
  1061. Virtual:
  1062. Yes.
  1063. Arguments:
  1064. none as any destructor
  1065. Return Value:
  1066. None as any destructor
  1067. Notes:
  1068. if you create any local members, think about whether
  1069. there is any need for a non-trivial destructor
  1070. */
  1071. CEnumPrivileges::~CEnumPrivileges ()
  1072. {
  1073. }
  1074. /*
  1075. Routine Description:
  1076. Name:
  1077. CEnumPrivileges::CreateObject
  1078. Functionality:
  1079. Create WMI objects (Sce_SupportedPrivileges). Depending on parameter atAction,
  1080. this creation may mean:
  1081. (a) Get a single instance (atAction == ACTIONTYPE_GET)
  1082. (b) Get several instances satisfying some criteria (atAction == ACTIONTYPE_QUERY)
  1083. (c) Enumerate instances (atAction == ACTIONTYPE_ENUM)
  1084. Virtual:
  1085. Yes.
  1086. Arguments:
  1087. pHandler - COM interface pointer for notifying WMI for creation result.
  1088. atAction - Get single instance ACTIONTYPE_GET
  1089. Get several instances ACTIONTYPE_QUERY
  1090. Enumerate instances ACTIONTYPE_ENUM
  1091. Return Value:
  1092. Success: it must return success code (use SUCCEEDED to test). It is
  1093. not guaranteed to return WBEM_NO_ERROR. The returned objects are indicated to WMI,
  1094. not directly passed back via parameters.
  1095. Failure: Various errors may occurs. Except WBEM_E_NOT_FOUND, any such error should indicate
  1096. the failure of getting the wanted instance. If WBEM_E_NOT_FOUND is returned in querying
  1097. situations, this may not be an error depending on caller's intention.
  1098. Notes:
  1099. */
  1100. HRESULT
  1101. CEnumPrivileges::CreateObject (
  1102. IN IWbemObjectSink * pHandler,
  1103. IN ACTIONTYPE atAction
  1104. )
  1105. {
  1106. //
  1107. // we know how to:
  1108. // Enumerate instances ACTIONTYPE_ENUM
  1109. // Get single instance ACTIONTYPE_GET
  1110. // Get several instances ACTIONTYPE_QUERY
  1111. //
  1112. if ( ACTIONTYPE_ENUM != atAction &&
  1113. ACTIONTYPE_GET != atAction &&
  1114. ACTIONTYPE_QUERY != atAction )
  1115. {
  1116. return WBEM_E_NOT_SUPPORTED;
  1117. }
  1118. HRESULT hr = WBEM_S_NO_ERROR;
  1119. //
  1120. // if not enumerating, then see if we have the Right name property
  1121. //
  1122. CComVariant varRightName;
  1123. if ( ACTIONTYPE_ENUM != atAction )
  1124. {
  1125. //
  1126. // this property must be a bstr
  1127. //
  1128. hr = m_srpKeyChain->GetKeyPropertyValue(pRightName, &varRightName);
  1129. }
  1130. if ( ACTIONTYPE_ENUM == atAction ||
  1131. (ACTIONTYPE_QUERY == atAction && varRightName.vt != VT_BSTR) )
  1132. {
  1133. //
  1134. // if enumeration or query for all instances
  1135. //
  1136. WCHAR PrivName[128];
  1137. SCESTATUS rc;
  1138. for ( int i = 0; i < cPrivCnt; i++ )
  1139. {
  1140. int cbName = 128;
  1141. //
  1142. // get the privilege right name so that we can constrcut the instance
  1143. //
  1144. rc = SceLookupPrivRightName(
  1145. i,
  1146. PrivName,
  1147. &cbName
  1148. );
  1149. if ( SCESTATUS_SUCCESS != rc )
  1150. {
  1151. //
  1152. // SCE returned errors needs to be translated to HRESULT.
  1153. //
  1154. hr = ProvDosErrorToWbemError(ProvSceStatusToDosError(rc));
  1155. }
  1156. else
  1157. {
  1158. //
  1159. // get one privilege
  1160. //
  1161. hr = ConstructInstance(pHandler, PrivName);
  1162. }
  1163. if ( FAILED(hr) )
  1164. {
  1165. break;
  1166. }
  1167. }
  1168. }
  1169. else if (varRightName.vt == VT_BSTR)
  1170. {
  1171. //
  1172. // Create the privilege instance
  1173. //
  1174. hr = ConstructInstance(pHandler, varRightName.bstrVal);
  1175. }
  1176. return hr;
  1177. }
  1178. /*
  1179. Routine Description:
  1180. Name:
  1181. CEnumPrivileges::ConstructInstance
  1182. Functionality:
  1183. This is private function to create an instance of Sce_SupportedPrivileges.
  1184. Virtual:
  1185. No.
  1186. Arguments:
  1187. pHandler - COM interface pointer for notifying WMI of any events.
  1188. PrivName - privilege name.
  1189. Return Value:
  1190. Success: it must return success code (use SUCCEEDED to test). It is
  1191. not guaranteed to return WBEM_NO_ERROR.
  1192. Failure: Various errors may occurs. Any such error should indicate the creating the instance.
  1193. Notes:
  1194. */
  1195. HRESULT CEnumPrivileges::ConstructInstance (
  1196. IN IWbemObjectSink * pHandler,
  1197. IN LPCWSTR PrivName
  1198. )
  1199. {
  1200. //
  1201. // lookup privilege display name
  1202. //
  1203. HRESULT hr = WBEM_S_NO_ERROR;
  1204. DWORD dwLang;
  1205. WCHAR DispName[256];
  1206. DWORD cbName = 255;
  1207. DispName[0] = L'\0';
  1208. if ( LookupPrivilegeDisplayName(NULL, PrivName, DispName, &cbName,&dwLang) )
  1209. {
  1210. //
  1211. // create a blank instance so that we can fill in the properties
  1212. //
  1213. CComPtr<IWbemClassObject> srpObj;
  1214. if (FAILED(hr = SpawnAnInstance(&srpObj)))
  1215. {
  1216. return hr;
  1217. }
  1218. //
  1219. // CScePropertyMgr helps us to access WMI object's properties
  1220. // create an instance and attach the WMI object to it.
  1221. // This will always succeed.
  1222. //
  1223. CScePropertyMgr ScePropMgr;
  1224. ScePropMgr.Attach(srpObj);
  1225. hr = ScePropMgr.PutProperty(pRightName, PrivName);
  1226. if (SUCCEEDED(hr) && DispName[0] != L'\0' )
  1227. {
  1228. ScePropMgr.PutProperty(pDisplayName, DispName );
  1229. }
  1230. hr = pHandler->Indicate(1, &srpObj);
  1231. }
  1232. //
  1233. // if not find it (it's a user right, ignore it)
  1234. //
  1235. return hr;
  1236. }