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.

928 lines
23 KiB

  1. /*++
  2. Copyright (C) 1998-2001 Microsoft Corporation
  3. Module Name:
  4. REGMETHODS.CPP
  5. Abstract:
  6. Purpose: Implements the registry provider methods.
  7. History:
  8. --*/
  9. #include "precomp.h"
  10. #include "perfprov.h"
  11. #include "cvariant.h"
  12. #include "provreg.h"
  13. #include "reg.h"
  14. #include "genutils.h"
  15. #include <cominit.h>
  16. #include <arrtempl.h>
  17. #include <userenv.h>
  18. enum StringType{SIMPLE, EXPANDED};
  19. void CopyOrConvert(TCHAR * pTo, WCHAR * pFrom, int iLen)
  20. {
  21. #ifdef UNICODE
  22. wcsncpy(pTo, pFrom,iLen);
  23. #else
  24. wcstombs(pTo, pFrom, iLen);
  25. #endif
  26. pTo[iLen-1] = 0;
  27. return;
  28. }
  29. BSTR GetBSTR(TCHAR * pIn)
  30. {
  31. #ifdef UNICODE
  32. return SysAllocString(pIn);
  33. #else
  34. int iBuffLen = lstrlen(pIn)+1;
  35. WCHAR * pTemp = new WCHAR[iBuffLen];
  36. if(pTemp == NULL)
  37. return NULL;
  38. mbstowcs(pTemp, pIn, iBuffLen);
  39. BSTR bRet = SysAllocString(pTemp);
  40. delete []pTemp;
  41. return bRet;
  42. #endif
  43. }
  44. BOOL IsTypeMismatch(Registry & reg, TCHAR * pValueName, DWORD dwExpectedType)
  45. {
  46. DWORD dwType;
  47. long lRet = reg.GetType(pValueName, &dwType);
  48. if(lRet == ERROR_SUCCESS && dwExpectedType != dwType)
  49. return TRUE;
  50. else
  51. return FALSE;
  52. }
  53. //***************************************************************************
  54. //
  55. // HRESULT SetStatusAndReturnOK;
  56. //
  57. // Purpose: Sets the status code in the sink.
  58. //
  59. //***************************************************************************
  60. HRESULT SetStatusAndReturnOK(SCODE sc, IWbemObjectSink* pSink)
  61. {
  62. pSink->SetStatus(0,sc, NULL, NULL);
  63. return S_OK;
  64. }
  65. //***************************************************************************
  66. //
  67. // SAFEARRAY FAR* MySafeArrayCreate
  68. //
  69. // Purpose: Creates a safearray.
  70. //
  71. // Return: pointer to safearray, NULL if error.
  72. //
  73. //***************************************************************************
  74. SAFEARRAY FAR* MySafeArrayCreate(long lNumElement, VARTYPE vt)
  75. {
  76. SAFEARRAYBOUND rgsabound[1];
  77. rgsabound[0].lLbound = 0;
  78. rgsabound[0].cElements = lNumElement;
  79. return SafeArrayCreate( vt, 1 , rgsabound );
  80. }
  81. //***************************************************************************
  82. //
  83. // bool GetInArgString
  84. //
  85. // Purpose: Reads a string argument from the input object and puts it into
  86. // a value allocated by the caller.
  87. //
  88. // Return: true if OK.
  89. //
  90. //***************************************************************************
  91. TCHAR * GetInArgString(IWbemClassObject* pInParams, WCHAR * pwcName)
  92. {
  93. TCHAR * pOut = NULL;
  94. if(pInParams == NULL || pwcName == NULL)
  95. return NULL;
  96. VARIANT var;
  97. VariantInit(&var);
  98. SCODE sc = pInParams->Get(pwcName, 0, &var, NULL, NULL);
  99. if(sc == S_OK && var.vt == VT_BSTR)
  100. {
  101. pOut = new TCHAR[wcslen(var.bstrVal) + 1];
  102. if(pOut)
  103. wcscpy(pOut, var.bstrVal);
  104. }
  105. VariantClear(&var);
  106. return pOut;
  107. }
  108. //***************************************************************************
  109. //
  110. // SCODE EnumKey
  111. //
  112. // Purpose: Enumerate the subkeys and loads them into the output arguments.
  113. //
  114. // Return: error code or 0 if OK.
  115. //
  116. //***************************************************************************
  117. SCODE EnumKey(HKEY hRoot, TCHAR * cSubKey, IWbemClassObject* pOutParams)
  118. {
  119. SCODE sc;
  120. DWORD dwNumSubKeys, dwMaxSubKeyLen, dwNumValues, dwMaxValueNameLen;
  121. TCHAR * pcTemp = NULL;
  122. // Open the key
  123. HKEY hKey;
  124. long lRet = RegOpenKeyEx(hRoot, cSubKey, 0, KEY_ENUMERATE_SUB_KEYS|KEY_QUERY_VALUE , &hKey);
  125. if(lRet != ERROR_SUCCESS)
  126. return lRet;
  127. // Count the number of keys and the max size
  128. lRet = RegQueryInfoKey(hKey, NULL, NULL, NULL,
  129. &dwNumSubKeys, // number of subkeys
  130. &dwMaxSubKeyLen, // longest subkey name
  131. NULL,
  132. &dwNumValues, // number of value entries
  133. &dwMaxValueNameLen, // longest value name
  134. NULL, NULL, NULL);
  135. if(lRet != ERROR_SUCCESS || dwMaxSubKeyLen == 0)
  136. return lRet;
  137. pcTemp = new TCHAR[dwMaxSubKeyLen+1];
  138. if(pcTemp == NULL)
  139. return WBEM_E_OUT_OF_MEMORY;
  140. CVectorDeleteMe<TCHAR> dm(pcTemp);
  141. // Create the safe array for returning the data
  142. SAFEARRAY FAR* psa = MySafeArrayCreate(dwNumSubKeys, VT_BSTR);
  143. if(psa == NULL)
  144. {
  145. RegCloseKey(hKey);
  146. return WBEM_E_OUT_OF_MEMORY;
  147. }
  148. // Put each value name into the array
  149. for(long lTry = 0; lTry < dwNumSubKeys; lTry++)
  150. {
  151. lRet = RegEnumKey(hKey, lTry, pcTemp, dwMaxSubKeyLen+1);
  152. if(lRet == ERROR_SUCCESS)
  153. {
  154. BSTR bstr = GetBSTR(pcTemp);
  155. if(bstr)
  156. {
  157. sc = SafeArrayPutElement(psa, &lTry, bstr);
  158. SysFreeString(bstr);
  159. if(FAILED(sc))
  160. {
  161. SafeArrayDestroy(psa);
  162. return sc;
  163. }
  164. }
  165. }
  166. }
  167. // Write the data back!
  168. VARIANT var;
  169. var.vt = VT_BSTR | VT_ARRAY;
  170. var.parray = psa;
  171. sc = pOutParams->Put( L"sNames", 0, &var, 0);
  172. VariantClear(&var);
  173. RegCloseKey(hKey);
  174. return sc;
  175. }
  176. //***************************************************************************
  177. //
  178. // SCODE EnumValue
  179. //
  180. // Purpose: Enumerates the value names and types and puts the results into
  181. // the output object.
  182. //
  183. // Return: error code or 0 if OK.
  184. //
  185. //***************************************************************************
  186. SCODE EnumValue(HKEY hRoot, TCHAR * cSubKey, IWbemClassObject* pOutParams)
  187. {
  188. SCODE sc1, sc2;
  189. DWORD dwNumSubKeys, dwMaxSubKeyLen, dwNumValues, dwMaxValueNameLen;
  190. TCHAR * pcTemp = NULL;
  191. DWORD dwType, dwSize;
  192. // Open the registry key
  193. HKEY hKey;
  194. long lRet = RegOpenKeyEx((HKEY)hRoot, cSubKey, 0, KEY_QUERY_VALUE, &hKey);
  195. if(lRet != ERROR_SUCCESS)
  196. return lRet;
  197. // Count the number of values and the max size
  198. lRet = RegQueryInfoKey(hKey, NULL, NULL, NULL,
  199. &dwNumSubKeys, // number of subkeys
  200. &dwMaxSubKeyLen, // longest subkey name
  201. NULL,
  202. &dwNumValues, // number of value entries
  203. &dwMaxValueNameLen, // longest value name
  204. NULL, NULL, NULL);
  205. if(lRet != ERROR_SUCCESS || dwMaxValueNameLen == 0)
  206. return lRet;
  207. pcTemp = new TCHAR[dwMaxValueNameLen+1];
  208. if(pcTemp == NULL)
  209. return WBEM_E_OUT_OF_MEMORY;
  210. CVectorDeleteMe<TCHAR> dm(pcTemp);
  211. // Create safe arrays for the data names and types
  212. SAFEARRAY FAR* psaNames = MySafeArrayCreate(dwNumValues, VT_BSTR);
  213. if(psaNames == NULL)
  214. {
  215. RegCloseKey(hKey);
  216. return WBEM_E_OUT_OF_MEMORY;
  217. }
  218. SAFEARRAY FAR* psaTypes = MySafeArrayCreate(dwNumValues, VT_I4);
  219. if(psaTypes == NULL)
  220. {
  221. SafeArrayDestroy(psaNames);
  222. RegCloseKey(hKey);
  223. return WBEM_E_OUT_OF_MEMORY;
  224. }
  225. // Fill in the arrays
  226. for(long lTry = 0; lTry < dwNumValues; lTry++)
  227. {
  228. dwSize = dwMaxValueNameLen+1;
  229. lRet = RegEnumValue(hKey, lTry, pcTemp, &dwSize, 0, &dwType, NULL, 0);
  230. if(lRet == ERROR_SUCCESS)
  231. {
  232. BSTR bstr = GetBSTR(pcTemp);
  233. if(bstr)
  234. {
  235. sc1 = SafeArrayPutElement(psaNames, &lTry, bstr);
  236. sc2 = SafeArrayPutElement(psaTypes, &lTry, &dwType);
  237. SysFreeString(bstr);
  238. if(FAILED(sc1) || FAILED(sc2))
  239. {
  240. SafeArrayDestroy(psaNames);
  241. SafeArrayDestroy(psaTypes);
  242. return WBEM_E_OUT_OF_MEMORY;
  243. }
  244. }
  245. }
  246. }
  247. // Put the arrays containing the value names and types into the output object
  248. VARIANT var;
  249. var.vt = VT_BSTR | VT_ARRAY;
  250. var.parray = psaNames;
  251. pOutParams->Put( L"sNames", 0, &var, 0);
  252. VariantClear(&var);
  253. var.vt = VT_I4 | VT_ARRAY;
  254. var.parray = psaTypes;
  255. SCODE sc = pOutParams->Put( L"Types", 0, &var, 0);
  256. VariantClear(&var);
  257. RegCloseKey(hKey);
  258. return sc;
  259. }
  260. //***************************************************************************
  261. //
  262. // SCODE GetStr
  263. //
  264. // Purpose: Reads a string and puts it into the output argument. Note that
  265. // this works with either normal strings or expanded registry strings.
  266. //
  267. // Return: error code or 0 if OK.
  268. //
  269. //***************************************************************************
  270. SCODE GetStr(HKEY hRoot, TCHAR * cSubKey, TCHAR * cValueName, IWbemClassObject* pOutParams)
  271. {
  272. Registry reg(hRoot, KEY_QUERY_VALUE, (TCHAR *)cSubKey);
  273. long lRet = reg.GetLastError();
  274. if(lRet != ERROR_SUCCESS)
  275. return lRet;
  276. // Get the string
  277. TCHAR * pcValue;
  278. lRet = reg.GetStr(cValueName, &pcValue);
  279. if(lRet != ERROR_SUCCESS)
  280. {
  281. DWORD dwType;
  282. long lRet2 = reg.GetType(cValueName, &dwType);
  283. if(lRet2 == ERROR_SUCCESS && dwType != REG_SZ && dwType != REG_EXPAND_SZ)
  284. return WBEM_E_TYPE_MISMATCH;
  285. return lRet;
  286. }
  287. CDeleteMe<TCHAR> dm(pcValue);
  288. VARIANT var;
  289. var.bstrVal = GetBSTR(pcValue);
  290. var.vt = VT_BSTR;
  291. if(var.bstrVal == NULL)
  292. return WBEM_E_OUT_OF_MEMORY;
  293. lRet = pOutParams->Put( L"sValue", 0, &var, 0);
  294. VariantClear(&var);
  295. return lRet;
  296. }
  297. //***************************************************************************
  298. //
  299. // SCODE SetMultiStrValue
  300. //
  301. // Purpose: Writes multi string values to the registry.
  302. //
  303. // Return: error code or 0 if OK.
  304. //
  305. //***************************************************************************
  306. SCODE SetMultiStrValue(HKEY hRoot, TCHAR * cSubKey, TCHAR * cValueName, IWbemClassObject* pInParams)
  307. {
  308. SCODE sc;
  309. Registry reg(hRoot, KEY_SET_VALUE, (TCHAR *)cSubKey);
  310. if(reg.GetLastError() != 0)
  311. return reg.GetLastError();
  312. VARIANT var;
  313. VariantInit(&var);
  314. sc = pInParams->Get(L"sValue", 0, &var, NULL, NULL);
  315. if(sc != S_OK)
  316. return sc;
  317. if(var.vt != (VT_ARRAY | VT_BSTR))
  318. {
  319. VariantClear(&var);
  320. return WBEM_E_INVALID_PARAMETER;
  321. }
  322. SAFEARRAY * psa = var.parray;
  323. long lLbound, lUbound;
  324. sc = SafeArrayGetLBound(psa, 1, &lLbound );
  325. sc |= SafeArrayGetUBound(psa, 1, &lUbound );
  326. if(sc != S_OK)
  327. {
  328. VariantClear(&var);
  329. return WBEM_E_INVALID_PARAMETER;
  330. }
  331. long lNumElements = lUbound - lLbound + 1;
  332. // Calculate the necessary size
  333. long lSize = 1, lTry;
  334. for(lTry = lLbound; lTry <= lUbound; lTry++)
  335. {
  336. BSTR bstr;
  337. if(S_OK == SafeArrayGetElement(psa, &lTry, &bstr))
  338. {
  339. lSize += SysStringLen(bstr) + 1;
  340. SysFreeString(bstr);
  341. }
  342. }
  343. WCHAR * pMulti = new WCHAR [lSize];
  344. if(pMulti == NULL)
  345. {
  346. VariantClear(&var);
  347. return WBEM_E_OUT_OF_MEMORY;
  348. }
  349. memset(pMulti, 0, lSize * sizeof(WCHAR));
  350. WCHAR * pNext = pMulti;
  351. // Do the conversion;
  352. for(lTry = lLbound; lTry <= lUbound; lTry++)
  353. {
  354. BSTR bstr;
  355. if(S_OK == SafeArrayGetElement(psa, &lTry, &bstr))
  356. {
  357. wcscpy(pNext, bstr);
  358. pNext += SysStringLen(bstr) + 1;
  359. SysFreeString(bstr);
  360. }
  361. }
  362. VariantClear(&var);
  363. long lRet;
  364. lRet = reg.SetMultiStr(cValueName, pMulti, lSize * sizeof(WCHAR));
  365. delete [] pMulti;
  366. return lRet;
  367. }
  368. //***************************************************************************
  369. //
  370. // SCODE GetMultiStrValue
  371. //
  372. // Purpose: Reads multi strings from the registry.
  373. //
  374. // Return: error code or 0 if OK.
  375. //
  376. //***************************************************************************
  377. SCODE GetMultiStrValue(HKEY hRoot, TCHAR * cSubKey, TCHAR * cValueName, IWbemClassObject* pOutParams)
  378. {
  379. SCODE sc;
  380. Registry reg(hRoot, KEY_QUERY_VALUE, (TCHAR *)cSubKey);
  381. if(reg.GetLastError() != 0)
  382. return reg.GetLastError();
  383. DWORD dwSize = 0;
  384. TCHAR * pMulti = reg.GetMultiStr(cValueName, dwSize);
  385. if(pMulti == NULL)
  386. return reg.GetLastError();
  387. CVectorDeleteMe<TCHAR> dm(pMulti);
  388. // count the number of strings
  389. long lNumString = 0;
  390. TCHAR * pNext;
  391. for(pNext = pMulti; *pNext; pNext += lstrlen(pNext) + 1)
  392. lNumString++;
  393. // create the bstr array
  394. SAFEARRAY FAR* psa = MySafeArrayCreate(lNumString, VT_BSTR);
  395. if(psa == NULL)
  396. {
  397. return WBEM_E_OUT_OF_MEMORY;
  398. }
  399. pNext = pMulti;
  400. for(long lTry = 0; lTry < lNumString; lTry++, pNext += lstrlen(pNext) + 1)
  401. {
  402. int iLen = lstrlen(pNext) + 1;
  403. BSTR bstr = GetBSTR(pNext);
  404. if(bstr)
  405. {
  406. sc = SafeArrayPutElement(psa, &lTry, bstr);
  407. SysFreeString(bstr);
  408. if(FAILED(sc))
  409. {
  410. SafeArrayDestroy(psa);
  411. return sc;
  412. }
  413. }
  414. }
  415. // put the data
  416. VARIANT var;
  417. var.vt = VT_BSTR | VT_ARRAY;
  418. var.parray = psa;
  419. sc = pOutParams->Put( L"sValue", 0, &var, 0);
  420. VariantClear(&var);
  421. return sc;
  422. }
  423. //***************************************************************************
  424. //
  425. // SCODE SetStringValue
  426. //
  427. // Purpose: Writes strings to the registry. These strings may
  428. // contain environment strings.
  429. //
  430. // Return: error code or 0 if OK.
  431. //
  432. //***************************************************************************
  433. SCODE SetStringValue(HKEY hRoot, TCHAR * cSubKey, TCHAR * cValueName, IWbemClassObject* pInParams,
  434. StringType st)
  435. {
  436. Registry reg(hRoot, KEY_SET_VALUE, (TCHAR *)cSubKey);
  437. long lRet = reg.GetLastError();
  438. if(lRet != ERROR_SUCCESS)
  439. return lRet;
  440. VARIANT var;
  441. VariantInit(&var);
  442. SCODE sc = pInParams->Get(L"sValue", 0, &var, NULL, NULL);
  443. if(sc != S_OK)
  444. return sc;
  445. if(var.vt != VT_BSTR)
  446. {
  447. VariantClear(&var);
  448. return WBEM_E_INVALID_PARAMETER;
  449. }
  450. int iLen = 2*wcslen(var.bstrVal) + 2;
  451. TCHAR * pValue = new TCHAR[iLen];
  452. if(pValue)
  453. {
  454. CopyOrConvert(pValue, var.bstrVal, iLen);
  455. if(st == SIMPLE)
  456. sc = reg.SetStr(cValueName, pValue);
  457. else
  458. sc = reg.SetExpandStr(cValueName, pValue);
  459. delete [] pValue;
  460. }
  461. else
  462. sc = WBEM_E_OUT_OF_MEMORY;
  463. VariantClear(&var);
  464. return sc;
  465. }
  466. //***************************************************************************
  467. //
  468. // SCODE SetBinaryValue
  469. //
  470. // Purpose: Writes binary data to the registry.
  471. //
  472. // Return: error code or 0 if OK.
  473. //
  474. //***************************************************************************
  475. SCODE SetBinaryValue(HKEY hRoot, TCHAR * cSubKey, TCHAR * cValueName, IWbemClassObject* pInParams)
  476. {
  477. Registry reg(hRoot, KEY_SET_VALUE, (TCHAR *)cSubKey);
  478. if(reg.GetLastError() != 0)
  479. return reg.GetLastError();
  480. VARIANT var;
  481. VariantInit(&var);
  482. SCODE sc = pInParams->Get(L"uValue", 0, &var, NULL, NULL);
  483. if(sc != S_OK)
  484. return sc;
  485. if(var.vt != (VT_ARRAY | VT_UI1) || var.parray == NULL)
  486. {
  487. VariantClear(&var);
  488. return WBEM_E_INVALID_PARAMETER;
  489. }
  490. SAFEARRAY * psa = var.parray;
  491. long lLbound, lUbound;
  492. sc = SafeArrayGetLBound(psa, 1, &lLbound );
  493. sc |= SafeArrayGetUBound(psa, 1, &lUbound );
  494. if(sc == S_OK)
  495. {
  496. byte * pData;
  497. sc = SafeArrayAccessData(psa, (void HUGEP* FAR*)&pData);
  498. if(sc == S_OK)
  499. {
  500. sc = reg.SetBinary(cValueName, pData, DWORD(lUbound - lLbound + 1));
  501. }
  502. }
  503. VariantClear(&var);
  504. return sc;
  505. }
  506. //***************************************************************************
  507. //
  508. // SCODE GetBinaryValue
  509. //
  510. // Purpose: Reads binary data from the registry.
  511. //
  512. // Return: error code or 0 if OK.
  513. //
  514. //***************************************************************************
  515. SCODE GetBinaryValue(HKEY hRoot, TCHAR * cSubKey, TCHAR * cValueName, IWbemClassObject* pOutParams)
  516. {
  517. Registry reg(hRoot, KEY_QUERY_VALUE, (TCHAR *)cSubKey);
  518. if(reg.GetLastError() != 0)
  519. return reg.GetLastError();
  520. SCODE sc;
  521. DWORD dwSize;
  522. byte * pRegData;
  523. long lRet = reg.GetBinary(cValueName, &pRegData, &dwSize);
  524. if(lRet != ERROR_SUCCESS || pRegData == NULL)
  525. {
  526. if(IsTypeMismatch(reg, cValueName, REG_BINARY))
  527. return WBEM_E_TYPE_MISMATCH;
  528. else
  529. return lRet;
  530. }
  531. SAFEARRAY FAR* psa = MySafeArrayCreate(dwSize, VT_UI1);
  532. if(psa)
  533. {
  534. TCHAR * pData = NULL;
  535. sc = SafeArrayAccessData(psa, (void HUGEP* FAR*)&pData);
  536. if(sc == S_OK)
  537. {
  538. memcpy(pData, pRegData, dwSize);
  539. SafeArrayUnaccessData(psa);
  540. VARIANT var;
  541. var.vt = VT_UI1|VT_ARRAY;
  542. var.parray = psa;
  543. sc = pOutParams->Put(L"uValue" , 0, &var, 0);
  544. VariantClear(&var);
  545. }
  546. }
  547. else
  548. sc = WBEM_E_OUT_OF_MEMORY;
  549. delete [] pRegData;
  550. return sc;
  551. }
  552. //***************************************************************************
  553. //
  554. // SCODE LoadProfile
  555. //
  556. // Purpose: Sets up all the arguments needed for calling LoadUserProfile
  557. //
  558. // Return: error code or 0 if OK.
  559. //
  560. //***************************************************************************
  561. SCODE LoadProfile(HANDLE & hToken,HKEY & hRoot)
  562. {
  563. PROFILEINFO pi;
  564. memset((void *)&pi, 0, sizeof(pi));
  565. pi.dwSize = sizeof(pi);
  566. SCODE sc;
  567. BOOL bRes;
  568. bRes = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_IMPERSONATE,
  569. TRUE, &hToken);
  570. if(!bRes)
  571. return WBEM_E_FAILED;
  572. TCHAR cUsername[MAX_PATH];
  573. cUsername[0] = 0;
  574. DWORD dwSize = MAX_PATH;
  575. GetUserName(cUsername, &dwSize);
  576. pi.lpUserName = cUsername;
  577. pi.dwFlags = 1;
  578. WbemCoRevertToSelf();
  579. BOOL bRet = LoadUserProfile(hToken, &pi);
  580. if(bRet == 0)
  581. {
  582. hRoot = NULL;
  583. sc = WbemCoImpersonateClient();
  584. return WBEM_E_FAILED;
  585. }
  586. else
  587. hRoot = (HKEY)pi.hProfile;
  588. sc = WbemCoImpersonateClient();
  589. if(FAILED(sc))
  590. {
  591. UnloadUserProfile(hToken, hRoot);
  592. hRoot = NULL;
  593. }
  594. return sc;
  595. }
  596. /************************************************************************
  597. * *
  598. *CMethodPro::ExecMethodAsync *
  599. * *
  600. *Purpose: This is the Async function implementation. *
  601. * *
  602. ************************************************************************/
  603. SCODE CImpReg::MethodAsync(const BSTR ObjectPath, const BSTR MethodName,
  604. long lFlags, IWbemContext* pCtx, IWbemClassObject* pInParams,
  605. IWbemObjectSink* pSink)
  606. {
  607. HRESULT hr;
  608. IWbemClassObject * pClass = NULL;
  609. IWbemClassObject * pOutClass = NULL;
  610. IWbemClassObject* pOutParams = NULL;
  611. TCHAR * pcValueName = NULL;
  612. TCHAR * pcSubKey = NULL;
  613. long lRet = 0;
  614. if(ObjectPath == NULL || MethodName == NULL || pInParams == NULL || pSink == NULL)
  615. return WBEM_E_INVALID_PARAMETER;
  616. // Kevin needs a way to tell if something is write
  617. // Get the class object, this is hard coded and matches the class
  618. // in the MOF. Then create the output argument
  619. hr = m_pGateway->GetObject(L"StdRegProv", 0, pCtx, &pClass, NULL);
  620. if(hr == S_OK)
  621. {
  622. hr = pClass->GetMethod(MethodName, 0, NULL, &pOutClass);
  623. if(hr == S_OK)
  624. {
  625. hr = pOutClass->SpawnInstance(0, &pOutParams);
  626. pOutClass->Release();
  627. }
  628. pClass->Release();
  629. }
  630. if(hr != S_OK)
  631. return SetStatusAndReturnOK(hr, pSink);
  632. CReleaseMe rm0(pOutParams);
  633. // Get the root key and subkeys
  634. VARIANT var;
  635. VariantInit(&var); // Get the input argument
  636. hr = pInParams->Get(L"hDefKey", 0, &var, NULL, NULL);
  637. if(hr != S_OK)
  638. return SetStatusAndReturnOK(hr, pSink);
  639. #ifdef _WIN64
  640. HKEY hRoot = (HKEY)IntToPtr(var.lVal);
  641. #else
  642. HKEY hRoot = (HKEY)var.lVal;
  643. #endif
  644. pcSubKey = GetInArgString(pInParams, L"sSubKeyName");
  645. if(pcSubKey == NULL)
  646. return SetStatusAndReturnOK(WBEM_E_INVALID_PARAMETER, pSink);
  647. CVectorDeleteMe<TCHAR> dm1(pcSubKey);
  648. // This may or may not work since the value name isnt required
  649. pcValueName = GetInArgString(pInParams, L"sValueName");
  650. CVectorDeleteMe<TCHAR> dm2(pcValueName);
  651. SCODE sc = S_OK;
  652. // Impersonate if using NT
  653. if(IsNT() && IsDcomEnabled())
  654. {
  655. sc = WbemCoImpersonateClient();
  656. if(sc != S_OK)
  657. return sc;
  658. }
  659. // If we are using HKCU, the hive may need to be loaded
  660. bool bUsingHKCU = IsNT() && hRoot == HKEY_CURRENT_USER;
  661. HANDLE hToken = INVALID_HANDLE_VALUE;
  662. CCloseMe cm(hToken);
  663. if(bUsingHKCU)
  664. sc = LoadProfile(hToken, hRoot);
  665. if(sc != S_OK)
  666. return sc;
  667. if(!_wcsicmp(MethodName, L"CreateKey"))
  668. {
  669. HKEY hKey;
  670. if(lstrlen(pcSubKey) < 1)
  671. sc = WBEM_E_INVALID_PARAMETER;
  672. else
  673. {
  674. lRet = RegCreateKey(hRoot, pcSubKey, &hKey);
  675. if(lRet == ERROR_SUCCESS)
  676. RegCloseKey(hKey);
  677. }
  678. }
  679. else if(!_wcsicmp(MethodName, L"DeleteKey"))
  680. {
  681. if(lstrlen(pcSubKey) < 1)
  682. sc = WBEM_E_INVALID_PARAMETER;
  683. else
  684. lRet = RegDeleteKey(hRoot, pcSubKey);
  685. }
  686. else if(!_wcsicmp(MethodName, L"DeleteValue"))
  687. {
  688. HKEY hKey;
  689. lRet = RegOpenKey(hRoot, pcSubKey, &hKey);
  690. if(lRet == ERROR_SUCCESS)
  691. {
  692. lRet = RegDeleteValue(hKey, pcValueName);
  693. RegCloseKey(hKey);
  694. }
  695. }
  696. else if(!_wcsicmp(MethodName, L"EnumKey"))
  697. {
  698. lRet = EnumKey(hRoot, pcSubKey, pOutParams);
  699. }
  700. else if(!_wcsicmp(MethodName, L"EnumValues"))
  701. {
  702. lRet = EnumValue(hRoot, pcSubKey, pOutParams);
  703. }
  704. else if(!_wcsicmp(MethodName, L"GetStringValue") ||
  705. !_wcsicmp(MethodName, L"GetExpandedStringValue"))
  706. {
  707. lRet = GetStr(hRoot, pcSubKey, pcValueName, pOutParams);
  708. }
  709. else if(!_wcsicmp(MethodName, L"SetMultiStringValue"))
  710. {
  711. lRet = SetMultiStrValue(hRoot,pcSubKey,pcValueName,pInParams);
  712. }
  713. else if(!_wcsicmp(MethodName, L"GetMultiStringValue"))
  714. {
  715. lRet = GetMultiStrValue(hRoot,pcSubKey,pcValueName,pOutParams);
  716. }
  717. else if(!_wcsicmp(MethodName, L"SetExpandedStringValue"))
  718. {
  719. lRet = SetStringValue(hRoot, pcSubKey, pcValueName, pInParams, EXPANDED);
  720. }
  721. else if(!_wcsicmp(MethodName, L"SetStringValue"))
  722. {
  723. lRet = SetStringValue(hRoot, pcSubKey, pcValueName, pInParams, SIMPLE);
  724. }
  725. else if(!_wcsicmp(MethodName, L"SetBinaryValue"))
  726. {
  727. lRet = SetBinaryValue(hRoot, pcSubKey, pcValueName, pInParams);
  728. }
  729. else if(!_wcsicmp(MethodName, L"SetDWORDValue"))
  730. {
  731. lRet = pInParams->Get(L"uValue", 0, &var, NULL, NULL);
  732. if(lRet == S_OK)
  733. {
  734. DWORD dwValue = var.lVal;
  735. Registry reg(hRoot, KEY_SET_VALUE, (TCHAR *)pcSubKey);
  736. lRet = reg.GetLastError();
  737. if(lRet ==0)
  738. lRet = reg.SetDWORD(pcValueName, dwValue);
  739. }
  740. }
  741. else if(!_wcsicmp(MethodName, L"GetDWORDValue"))
  742. {
  743. // Get the value name
  744. Registry reg(hRoot, KEY_QUERY_VALUE, (TCHAR *)pcSubKey);
  745. lRet = reg.GetLastError();
  746. if(lRet == 0)
  747. lRet = reg.GetDWORD(pcValueName, (DWORD *)&var.lVal);
  748. if(lRet == ERROR_SUCCESS)
  749. {
  750. var.vt = VT_I4;
  751. lRet = pOutParams->Put( L"uValue", 0, &var, 0);
  752. }
  753. else if(IsTypeMismatch(reg, pcValueName, REG_DWORD))
  754. lRet = WBEM_E_TYPE_MISMATCH;
  755. }
  756. else if(!_wcsicmp(MethodName, L"GetBinaryValue"))
  757. {
  758. lRet = GetBinaryValue(hRoot,pcSubKey,pcValueName,pOutParams);
  759. }
  760. else if(!_wcsicmp(MethodName, L"CheckAccess"))
  761. {
  762. lRet = pInParams->Get(L"uRequired", 0, &var, NULL, NULL);
  763. if(lRet == S_OK)
  764. {
  765. BOOL bSuccess = FALSE;
  766. DWORD dwValue = var.lVal;
  767. HKEY hKey;
  768. lRet = RegOpenKeyEx(hRoot, pcSubKey, 0, dwValue, &hKey);
  769. if(lRet == ERROR_SUCCESS)
  770. {
  771. RegCloseKey(hKey);
  772. bSuccess = TRUE;
  773. }
  774. var.vt = VT_BOOL;
  775. var.boolVal = (bSuccess) ? VARIANT_TRUE : VARIANT_FALSE;
  776. pOutParams->Put( L"bGranted", 0, &var, 0);
  777. }
  778. }
  779. else
  780. sc = WBEM_E_INVALID_METHOD;
  781. if(bUsingHKCU)
  782. {
  783. WbemCoRevertToSelf();
  784. UnloadUserProfile(hToken, hRoot);
  785. }
  786. // Set the return value
  787. if(sc == S_OK)
  788. {
  789. BSTR retValName = SysAllocString(L"ReturnValue");
  790. if(retValName)
  791. {
  792. var.vt = VT_I4;
  793. var.lVal = lRet;
  794. pOutParams->Put(retValName , 0, &var, 0);
  795. SysFreeString(retValName);
  796. }
  797. hr = pSink->Indicate(1, &pOutParams);
  798. }
  799. return SetStatusAndReturnOK(sc, pSink);
  800. }