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.

1531 lines
45 KiB

  1. /*++
  2. Copyright (C) 1995-2001 Microsoft Corporation
  3. Module Name:
  4. PROVREG.CPP
  5. Abstract:
  6. Defines the acutal "Put" and "Get" functions for the
  7. registry provider. The mapping string format is;
  8. machine|regpath[|datafield]
  9. Examples:
  10. local|hkey_current_user\dave
  11. local|hkey_current_user\dave|stringdata
  12. local|hkey_local_machine\hardware\resourcemap\hardware abstraction layer\
  13. pc compatible eisa/isa HAL|.raw("internal")(0)(2)("interrupt.vector")
  14. LMPGM|hkey_local_machine\clone\clone\control|CurrentUser
  15. History:
  16. a-davj 9-27-95 Created.
  17. --*/
  18. #include "precomp.h"
  19. #include <initguid.h>
  20. #include "perfprov.h"
  21. #include "cvariant.h"
  22. #include "provreg.h"
  23. #include <genutils.h>
  24. #include <cominit.h>
  25. #include <userenv.h>
  26. #define NUM_FOR_LIST 4
  27. #define NUM_FOR_PARTIAL 2
  28. #define TYPE_OFFSET 0
  29. #define BUS_OFFSET 1
  30. #define PARTIAL_OFFSET 0
  31. #define DATA_OFFSET 1
  32. #define NUM_LIST_ONLY 2
  33. #define MIN_REG_TOKENS 2
  34. #define BOGUS 0
  35. // for certain "resource" registry item it is necessary to specify which bus
  36. // and what part of the data union is to be returned. These strings allow
  37. // the mapping string to specify both using text
  38. TCHAR * cpIntTypes[] = {
  39. TEXT("Internal"),TEXT("Isa"),TEXT("Eisa"),TEXT("MicroChannel"),TEXT("TurboChannel"),
  40. TEXT("PCIBus"),TEXT("VMEBus"),TEXT("NuBus"),TEXT("PCMCIABus"),TEXT("CBus"),
  41. TEXT("MPIBus"),TEXT("MPSABus"),TEXT("MaximumInterfaceType")};
  42. struct UnionOffset
  43. {
  44. TCHAR * tpName;
  45. int iOffset;
  46. int iType;
  47. int iSize;
  48. } Offsets[] =
  49. {
  50. {TEXT("Port.Start"),0,CmResourceTypePort,8},
  51. {TEXT("Port.PhysicalAddress"),0,CmResourceTypePort,8},
  52. {TEXT("Port.Physical Address"),0,CmResourceTypePort,8},
  53. {TEXT("Port.Length"),8,CmResourceTypePort,4},
  54. {TEXT("Interrupt.Level"),0,CmResourceTypeInterrupt,4},
  55. {TEXT("Interrupt.Vector"),4,CmResourceTypeInterrupt,4},
  56. {TEXT("Interrupt.Affinity"),8,CmResourceTypeInterrupt,4},
  57. {TEXT("Memory.Start"),0,CmResourceTypeMemory,8},
  58. {TEXT("Memory.PhysicalAddress"),0,CmResourceTypeMemory,8},
  59. {TEXT("Memory.Physical Address"),0,CmResourceTypeMemory,8},
  60. {TEXT("Memory.Length"),8,CmResourceTypeMemory,4},
  61. {TEXT("Dma.Channel"),0,CmResourceTypeDma,4},
  62. {TEXT("Dma.Port"),4,CmResourceTypeDma,4},
  63. {TEXT("Dma.Reserved1"),8,CmResourceTypeDma,4},
  64. {TEXT("DeviceSpecificData.DataSize"),0,CmResourceTypeDeviceSpecific,4},
  65. {TEXT("DeviceSpecificData.Data Size"),0,CmResourceTypeDeviceSpecific,4},
  66. {TEXT("DeviceSpecificData.Reserved1"),4,CmResourceTypeDeviceSpecific,4},
  67. {TEXT("DeviceSpecificData.Reserved2"),8,CmResourceTypeDeviceSpecific,4}
  68. };
  69. // Define the names of the basic registry handles
  70. struct BaseTypes
  71. {
  72. LPTSTR lpName;
  73. HKEY hKey;
  74. } Bases[] =
  75. {
  76. {TEXT("HKEY_CLASSES_ROOT") , HKEY_CLASSES_ROOT},
  77. {TEXT("HKEY_CURRENT_USER") , HKEY_CURRENT_USER},
  78. {TEXT("HKEY_LOCAL_MACHINE") , HKEY_LOCAL_MACHINE},
  79. {TEXT("HKEY_USERS") , HKEY_USERS},
  80. {TEXT("HKEY_PERFORMANCE_DATA") , HKEY_PERFORMANCE_DATA},
  81. {TEXT("HKEY_CURRENT_CONFIG") , HKEY_CURRENT_CONFIG},
  82. {TEXT("HKEY_DYN_DATA") , HKEY_DYN_DATA}};
  83. //***************************************************************************
  84. //
  85. // BOOL CImpReg::bGetOffsetData
  86. //
  87. // DESCRIPTION:
  88. //
  89. // Getting data from a resource list requires four offsets while getting
  90. // it from a single descriptor requires the last two offsets.
  91. //
  92. // PARAMETERS:
  93. //
  94. // dwReg Indicates if we are looking for a full or partial
  95. // resource descriptor.
  96. // ProvObj Object containing the property context string.
  97. // iIntType interface type - could be a string such as "eisa"
  98. // iBus bus number
  99. // iPartial partial descriptor number - each full descriptor
  100. // has several partial desc.
  101. // iDataOffset Data Offset - each partial descriptor has data in
  102. // a union and this is the byte offset. Could be a
  103. // sting such as "Dma.Channel"
  104. // iDataType Data type
  105. // iSourceSize Size of data
  106. // dwArray no longer used, should always be 0
  107. //
  108. // RETURN VALUE:
  109. //
  110. // TRUE if data is found
  111. //
  112. //***************************************************************************
  113. BOOL CImpReg::bGetOffsetData(
  114. IN DWORD dwReg,
  115. IN CProvObj & ProvObj,
  116. OUT IN int & iIntType,
  117. OUT IN int & iBus,
  118. OUT IN int & iPartial,
  119. OUT IN int & iDataOffset,
  120. OUT IN int & iDataType,
  121. OUT IN int & iSourceSize,
  122. DWORD dwArray)
  123. {
  124. int iNumRequired, iListOffset;
  125. int iLastToken = ProvObj.iGetNumTokens()-1;
  126. // determine the number needed for the type of data being requested
  127. if(dwReg == REG_RESOURCE_LIST)
  128. iNumRequired = NUM_FOR_LIST;
  129. else
  130. iNumRequired = NUM_FOR_PARTIAL;
  131. if(ProvObj.iGetNumExp(iLastToken) < iNumRequired)
  132. return FALSE;
  133. // Get the first two descriptors that are only needed in the list case.
  134. if(dwReg == REG_RESOURCE_LIST)
  135. {
  136. // the first offset can either be a string such as "EISA" or a
  137. // numeric offset.
  138. if(ProvObj.IsExpString(iLastToken,TYPE_OFFSET))
  139. iIntType = iLookUpInt(ProvObj.sGetStringExp(iLastToken,TYPE_OFFSET));
  140. else
  141. iIntType = ProvObj.iGetIntExp(iLastToken,TYPE_OFFSET,dwArray);
  142. iBus = ProvObj.iGetIntExp(iLastToken,BUS_OFFSET,dwArray);
  143. if(iBus == -1 || iIntType == -1)
  144. return FALSE;
  145. iListOffset = NUM_LIST_ONLY;
  146. }
  147. else
  148. iListOffset = 0;
  149. // Get the last two offsets which are for identenfying which partial
  150. // descriptor and the last is for specifying the offset inside the
  151. // union.
  152. iPartial = ProvObj.iGetIntExp(iLastToken,PARTIAL_OFFSET+iListOffset,dwArray);
  153. // The data offset can be a string such as "Dma.Port".
  154. iDataType = -1; // not necessarily an error, see the function
  155. // GetResourceDescriptorData for more info.
  156. iSourceSize = 0;
  157. if(ProvObj.IsExpString(iLastToken,DATA_OFFSET+iListOffset))
  158. iDataOffset = iLookUpOffset(ProvObj.sGetStringExp(iLastToken,
  159. DATA_OFFSET+iListOffset),
  160. iDataType,iSourceSize);
  161. else
  162. iDataOffset = ProvObj.iGetIntExp(iLastToken,DATA_OFFSET+iListOffset,dwArray);
  163. if(iPartial == -1 || iDataOffset == -1)
  164. return FALSE;
  165. return TRUE;
  166. }
  167. //***************************************************************************
  168. //
  169. // CImpReg::CImpReg
  170. //
  171. // DESCRIPTION:
  172. //
  173. // Constructor.
  174. //
  175. // PARAMETERS:
  176. //
  177. //***************************************************************************
  178. CImpReg::CImpReg()
  179. {
  180. wcscpy(wcCLSID,L"{FE9AF5C0-D3B6-11CE-A5B6-00AA00680C3F}");
  181. // To disable dmreg, uncomment hDMRegLib = NULL;
  182. // To disable dmreg, uncomment return;
  183. hDMRegLib = NULL; //LoadLibrary("DMREG.DLL");
  184. m_hRoot = NULL;
  185. m_hToken = NULL;
  186. m_bLoadedProfile = false;
  187. if(IsNT())
  188. {
  189. SCODE sc = WbemCoImpersonateClient();
  190. if(sc == S_OK)
  191. {
  192. sc = LoadProfile(m_hToken, m_hRoot);
  193. if(sc == S_OK)
  194. m_bLoadedProfile = true;
  195. WbemCoRevertToSelf();
  196. }
  197. }
  198. return;
  199. }
  200. //***************************************************************************
  201. //
  202. // CImpReg::~CImpReg
  203. //
  204. // DESCRIPTION:
  205. //
  206. // Destructor.
  207. //
  208. //***************************************************************************
  209. CImpReg::~CImpReg()
  210. {
  211. if(hDMRegLib)
  212. FreeLibrary(hDMRegLib);
  213. if(m_bLoadedProfile)
  214. UnloadUserProfile(m_hToken, m_hRoot);
  215. if(m_hToken)
  216. CloseHandle(m_hToken);
  217. }
  218. //***************************************************************************
  219. //
  220. // CImpReg::ConvertGetDataFromDesc
  221. //
  222. // DESCRIPTION:
  223. //
  224. // Extracts the data when it is in either the REG_RESOURCE_LIST or
  225. // REG_FULL_RESOURCE_DESCRIPTOR format. The REG_RESOURCE_LIST has a list
  226. // of "full resource" blocks and so in that case it is necessary to first
  227. // determine which block to extract from and after that the code is common.
  228. //
  229. // PARAMETERS:
  230. //
  231. // cVar reference to CVariant that get set with the result
  232. // pData raw data
  233. // dwRegType Indicates if we are looking for a full or partial
  234. // resource descriptor.
  235. // dwBufferSize not used
  236. // ProvObj Object containing the property context string.
  237. //
  238. // RETURN VALUE:
  239. //
  240. // S_OK all is well
  241. // WBEM_E_INVALID_PARAMETER couldnt find the data. Probably a bad context
  242. // string
  243. // otherwise, error converting the data in SetData()
  244. //***************************************************************************
  245. SCODE CImpReg::ConvertGetDataFromDesc(
  246. OUT CVariant & cVar,
  247. IN void * pData,
  248. IN DWORD dwRegType,
  249. IN DWORD dwBufferSize,
  250. IN CProvObj & ProvObj)
  251. {
  252. int iIntType, iBus, iPartial, iDataOffset,iDataType,iSourceSize;
  253. ULONG uCnt;
  254. PCM_FULL_RESOURCE_DESCRIPTOR pFull;
  255. PCM_PARTIAL_RESOURCE_DESCRIPTOR pPartial;
  256. // Get the various operator values. A typical provider string would
  257. // be "..|.raw("internal")(0)(2)("interrupt.vector")
  258. if(!bGetOffsetData(dwRegType,ProvObj,iIntType,iBus,iPartial,
  259. iDataOffset,iDataType, iSourceSize, BOGUS))
  260. return WBEM_E_INVALID_PARAMETER;
  261. // if list, get the right full resource block.
  262. if(dwRegType == REG_RESOURCE_LIST)
  263. {
  264. PCM_RESOURCE_LIST pList = (PCM_RESOURCE_LIST)pData;
  265. pFull = &pList->List[0];
  266. for(uCnt=0; uCnt < pList->Count; uCnt++)
  267. if(pFull->InterfaceType == iIntType && pFull->BusNumber == (unsigned)iBus)
  268. break; // found it!
  269. else
  270. pFull = GetNextFull(pFull);
  271. if(uCnt == pList->Count)
  272. return WBEM_E_INVALID_PARAMETER; // specified invalid type or bus number
  273. }
  274. else
  275. pFull = (PCM_FULL_RESOURCE_DESCRIPTOR)pData;
  276. // Get the partial resource descriptor. Each full
  277. // descriptor is a list of partial descriptors. If the
  278. // last expression was of the form ("interrupt.vector"),
  279. // then all the partial blocks that arn't interrupt data
  280. // will be ignored. If the last expression just has a
  281. // number, then the type of block is ignored.
  282. unsigned uSoFar = 0;
  283. pPartial = pFull->PartialResourceList.PartialDescriptors;
  284. unsigned uLimit = pFull->PartialResourceList.Count;
  285. for(uCnt = 0; uCnt < (unsigned)uLimit; uCnt++)
  286. {
  287. if(iDataType == -1 || iDataType == pPartial->Type)
  288. {
  289. if(uSoFar == (unsigned)iPartial)
  290. break; // got it!
  291. uSoFar++;
  292. }
  293. pPartial = GetNextPartial(pPartial);
  294. }
  295. if(uCnt == uLimit)
  296. return WBEM_E_INVALID_PARAMETER; // specified invalid block
  297. // Copy the data into a variant
  298. char * cpTemp = (char *)&pPartial->u.Dma.Channel + iDataOffset;
  299. if(iSourceSize == 1)
  300. return cVar.SetData(cpTemp,VT_UI1);
  301. else if(iSourceSize == 2)
  302. return cVar.SetData(cpTemp,VT_I2);
  303. else if(iSourceSize == 4)
  304. return cVar.SetData(cpTemp,VT_I4);
  305. else
  306. return cVar.SetData(cpTemp,VT_I8); //todo fix this VT_I8 dont work!!!
  307. }
  308. //***************************************************************************
  309. //
  310. // SCODE CImpReg::ConvertGetDataFromSimple
  311. //
  312. // DESCRIPTION:
  313. //
  314. // Converts that data returned by the registry into the closest VARIANT
  315. // type.
  316. //
  317. // PARAMETERS:
  318. //
  319. // cVar Reference to CVariant where result is to be put
  320. // pData pointer to data
  321. // dwRegType registry type, ex, REG_MUTISZ
  322. // dwBufferSize size of data
  323. // pClassInt Pointer to class object
  324. // PropName Property name.
  325. //
  326. // RETURN VALUE:
  327. //
  328. // S_OK all is well
  329. // else could fail if the "Get" on the property fails,
  330. // or if the data conversion fails in SetData.
  331. //***************************************************************************
  332. SCODE CImpReg::ConvertGetDataFromSimple(
  333. OUT CVariant & cVar,
  334. IN void * pData,
  335. IN DWORD dwRegType,
  336. IN DWORD dwBufferSize,
  337. IN IWbemClassObject FAR * pClassInt,
  338. IN BSTR PropName)
  339. {
  340. TCHAR tTemp[1];
  341. TCHAR * pTemp;
  342. SCODE sc = S_OK;
  343. int nSize;
  344. char * cpTo, * cpFrom;
  345. long vtProp;
  346. // Note that the current winnt.h file defines the constants
  347. // REG_DWORD_LITTLE_ENDIAN and REG_DWORD as being the same.
  348. // The compiler considers this an error in a switch statement and so
  349. // there is this "if" to ensure that they are handled the same even
  350. // if someday the constants become different
  351. if(dwRegType == REG_DWORD_LITTLE_ENDIAN)
  352. dwRegType = REG_DWORD;
  353. switch(dwRegType)
  354. {
  355. case REG_SZ:
  356. sc = cVar.SetData(pData, VT_BSTR,dwBufferSize);
  357. break;
  358. case REG_EXPAND_SZ:
  359. nSize = ExpandEnvironmentStrings((TCHAR *)pData,tTemp,1) + 1;
  360. pTemp = new TCHAR[nSize+1];
  361. if(pTemp == NULL)
  362. return WBEM_E_OUT_OF_MEMORY;
  363. ExpandEnvironmentStrings((TCHAR *)pData,pTemp,nSize+1);
  364. sc = cVar.SetData(pTemp, VT_BSTR, nSize+1);
  365. delete pTemp;
  366. break;
  367. case REG_BINARY:
  368. if(pClassInt)
  369. {
  370. sc = pClassInt->Get(PropName,0,NULL,&vtProp,NULL);
  371. if(sc != S_OK)
  372. return sc;
  373. }
  374. else
  375. vtProp = VT_UI1 | VT_ARRAY;
  376. if((vtProp & VT_ARRAY) == 0)
  377. sc = WBEM_E_FAILED; // Incompatible types
  378. else
  379. sc = cVar.SetData(pData,vtProp, dwBufferSize);
  380. break;
  381. case REG_DWORD:
  382. sc = cVar.SetData(pData,VT_I4);
  383. break;
  384. case REG_DWORD_BIG_ENDIAN:
  385. sc = cVar.SetData(pData,VT_I4);
  386. cpTo = (char *)cVar.GetDataPtr();
  387. cpFrom = (char *)pData;
  388. cpTo[0] = cpFrom[3];
  389. cpTo[1] = cpFrom[2];
  390. cpTo[2] = cpFrom[1];
  391. cpTo[3] = cpFrom[0];
  392. break;
  393. case REG_MULTI_SZ:
  394. sc = cVar.SetData(pData, VT_BSTR | VT_ARRAY, dwBufferSize);
  395. break;
  396. default:
  397. sc = WBEM_E_TYPE_MISMATCH;
  398. }
  399. return sc;
  400. }
  401. //***************************************************************************
  402. //
  403. // SCODE CImpReg::ConvertSetData
  404. //
  405. // DESCRIPTION:
  406. //
  407. // Takes WBEM type data and converts it into the proper
  408. // form for storage in the registry. There are two distinct
  409. // case: Binary array data and normal data.
  410. //
  411. // PARAMETERS:
  412. //
  413. // cVar Contains the source
  414. // **ppData pointer which will be set to point to some allocate
  415. // data. Note that the data allocated should be freed
  416. // using CoTaskMemFree
  417. // pdwRegType desired registry type
  418. // pdwBufferSize size of allocated data
  419. //
  420. // RETURN VALUE:
  421. //
  422. // S_OK all is well
  423. // WBEM_E_TYPE_MISMATCH invalied type
  424. // else error is set by GetData()
  425. //
  426. //***************************************************************************
  427. SCODE CImpReg::ConvertSetData(
  428. IN CVariant & cVar,
  429. OUT void **ppData,
  430. IN DWORD * pdwRegType,
  431. OUT DWORD * pdwBufferSize)
  432. {
  433. void * pRet = NULL;
  434. SCODE sc;
  435. switch (cVar.GetType() & ~VT_ARRAY)
  436. {
  437. case VT_I1:
  438. case VT_UI1:
  439. case VT_I2:
  440. case VT_UI2:
  441. case VT_I4:
  442. case VT_UI4:
  443. case VT_BOOL:
  444. case VT_INT:
  445. case VT_UINT:
  446. // convert data into DWORD format which is equivalent to
  447. // the REG_DWORD.
  448. *pdwRegType = (cVar.IsArray()) ? REG_BINARY : REG_DWORD;
  449. sc = cVar.GetData(ppData,*pdwRegType,pdwBufferSize);
  450. break;
  451. case VT_I8:
  452. case VT_UI8:
  453. case VT_LPSTR:
  454. case VT_LPWSTR:
  455. case VT_R4:
  456. case VT_R8:
  457. case VT_CY:
  458. case VT_DATE:
  459. case VT_BSTR:
  460. *pdwRegType = (cVar.IsArray()) ? REG_MULTI_SZ : REG_SZ;
  461. sc = cVar.GetData(ppData,*pdwRegType,pdwBufferSize);
  462. break;
  463. default:
  464. sc = WBEM_E_TYPE_MISMATCH;
  465. }
  466. return sc;
  467. }
  468. //***************************************************************************
  469. //
  470. // void CImpReg::EndBatch
  471. //
  472. // DESCRIPTION:
  473. //
  474. // Called at the end of a batch of Refrest/Update Property calls. Free up
  475. // any cached handles and then delete the handle cache.
  476. //
  477. // PARAMETERS:
  478. //
  479. // lFlags flags, not used
  480. // pClassInt class object, not used
  481. // *pObj pointer to our cache, free it
  482. // bGet indicates if a Refresh or Put was being done
  483. //
  484. //***************************************************************************
  485. void CImpReg::EndBatch(
  486. long lFlags,
  487. IWbemClassObject FAR * pClassInt,
  488. CObject *pObj,
  489. BOOL bGet)
  490. {
  491. if(pObj != NULL)
  492. {
  493. Free(0,(CHandleCache *)pObj);
  494. delete pObj;
  495. }
  496. }
  497. //***************************************************************************
  498. //
  499. // void CImpReg::Free
  500. //
  501. // DESCRIPTION:
  502. //
  503. // Frees up cached registry handles starting with position
  504. // iStart till the end. After freeing handles, the cache object
  505. // member function is used to delete the cache entries.
  506. //
  507. // PARAMETERS:
  508. //
  509. // iStart Where to start freeing. 0 indicates that whole
  510. // cache should be emptied
  511. // pCache Cache to be freed
  512. //
  513. //***************************************************************************
  514. void CImpReg::Free(
  515. IN int iStart,
  516. IN CHandleCache * pCache)
  517. {
  518. HKEY hClose;
  519. int iCurr; long lRet;
  520. for(iCurr = pCache->lGetNumEntries()-1; iCurr >= iStart; iCurr--)
  521. {
  522. hClose = (HKEY)pCache->hGetHandle(iCurr);
  523. if(hClose != NULL)
  524. if(hDMRegLib && !pCache->IsRemote())
  525. lRet = pClose(hClose);
  526. else
  527. lRet = RegCloseKey(hClose);
  528. }
  529. pCache->Delete(iStart); // get cache to delete the entries
  530. }
  531. //***************************************************************************
  532. //
  533. // PCM_FULL_RESOURCE_DESCRIPTOR CImpReg::GetNextFull
  534. //
  535. // DESCRIPTION:
  536. //
  537. // Returns a pointer to the next full resource descritor block. Used
  538. // when stepping through resource data.
  539. //
  540. // PARAMETERS:
  541. //
  542. // pCurr points to current location.
  543. //
  544. // RETURN VALUE:
  545. //
  546. // see description.
  547. //***************************************************************************
  548. PCM_FULL_RESOURCE_DESCRIPTOR CImpReg::GetNextFull(
  549. IN PCM_FULL_RESOURCE_DESCRIPTOR pCurr)
  550. {
  551. unsigned uCount;
  552. PCM_PARTIAL_RESOURCE_DESCRIPTOR pPartial;
  553. // Get a pointer to the first partial descriptor and then step
  554. // through each of the partial descriptor blocks.
  555. pPartial = &pCurr->PartialResourceList.PartialDescriptors[0];
  556. for(uCount = 0; uCount < pCurr->PartialResourceList.Count; uCount++)
  557. pPartial = GetNextPartial(pPartial);
  558. return (PCM_FULL_RESOURCE_DESCRIPTOR)pPartial;
  559. }
  560. //***************************************************************************
  561. //
  562. // PCM_PARTIAL_RESOURCE_DESCRIPTOR CImpReg::GetNextPartial
  563. //
  564. // DESCRIPTION:
  565. //
  566. // Returns a pointer to the next partial resource descritor block. Used
  567. // when stepping through resource data.
  568. //
  569. // PARAMETERS:
  570. //
  571. // pCurr Current location.
  572. //
  573. // RETURN VALUE:
  574. //
  575. // see description.
  576. //***************************************************************************
  577. PCM_PARTIAL_RESOURCE_DESCRIPTOR CImpReg::GetNextPartial(
  578. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pCurr)
  579. {
  580. char * cpTemp = (char *)pCurr;
  581. cpTemp += sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
  582. if(pCurr->Type == CmResourceTypeDeviceSpecific)
  583. cpTemp += pCurr->u.DeviceSpecificData.DataSize;
  584. return (PCM_PARTIAL_RESOURCE_DESCRIPTOR)cpTemp;
  585. }
  586. //***************************************************************************
  587. //
  588. // int CImpReg::GetRoot
  589. //
  590. // DESCRIPTION:
  591. //
  592. // Gets the starting registry key. The key can be on either the local
  593. // machine or a remote one. If there are handles in the cache, then
  594. // the starting key can be retrieved from it in so far as the paths match.
  595. //
  596. // PARAMETERS:
  597. //
  598. // pKey Set to point to the root key
  599. // Path registry path
  600. // pNewMachine Machine name
  601. // pCache Handle cache object
  602. // iNumSkip Set to the number of tokens that matched
  603. //
  604. // RETURN VALUE:
  605. //
  606. //
  607. //***************************************************************************
  608. int CImpReg::GetRoot(
  609. OUT HKEY * pKey,
  610. IN CProvObj & Path,
  611. IN const TCHAR * pNewMachine,
  612. OUT IN CHandleCache * pCache,
  613. OUT int & iNumSkip)
  614. {
  615. int iCnt;
  616. *pKey = NULL;
  617. iNumSkip = 0;
  618. int iRet;
  619. HKEY hRoot = NULL;
  620. const TCHAR * pNewRoot = Path.sGetFullToken(0);
  621. if(pNewRoot == NULL || pNewMachine == NULL)
  622. return ERROR_UNKNOWN; // bad mapping string
  623. // If there are handles in the cache, then they may be used if and
  624. // only if the machines names and root keys match.
  625. if(pCache->lGetNumEntries() > 0)
  626. {
  627. const TCHAR * pOldMachine = pCache->sGetString(0);
  628. const TCHAR * pOldRoot = pCache->sGetString(1);
  629. if(pOldMachine == NULL || pOldRoot == NULL)
  630. return ERROR_UNKNOWN;
  631. if(lstrcmpi(pOldMachine,pNewMachine) ||
  632. lstrcmpi(pOldRoot,pNewRoot))
  633. // Either machine or root key has changed, in either
  634. // case, free all the cached handles and get a new root.
  635. Free(0,pCache);
  636. else
  637. {
  638. // Machine and root are in common. Determine how much
  639. // else is in common, free what isnt in common, and return
  640. // the subkey share a common path.
  641. iNumSkip = pCache->lGetNumMatch(2,1,Path);
  642. Free(2+iNumSkip,pCache);
  643. *pKey = (HKEY)pCache->hGetHandle(1+iNumSkip);
  644. return ERROR_SUCCESS;
  645. }
  646. }
  647. // Got to get the root key. First, use the second token to determine
  648. // which predefined key to use. That would be something like;
  649. // HKEY_CURRENT_USER.
  650. int iSize= sizeof(Bases) / sizeof(struct BaseTypes);
  651. for(iCnt = 0; iCnt < iSize; iCnt++)
  652. if(!lstrcmpi(pNewRoot,Bases[iCnt].lpName))
  653. {
  654. hRoot = Bases[iCnt].hKey;
  655. break;
  656. }
  657. if(hRoot == HKEY_CURRENT_USER && m_bLoadedProfile)
  658. hRoot = m_hRoot;
  659. if(hRoot == NULL)
  660. return ERROR_UNKNOWN;
  661. // Now use the first key to determine if it is the local machine or
  662. // another.
  663. if(lstrcmpi(pNewMachine,TEXT("LOCAL")))
  664. {
  665. // Connect to a remote machine.
  666. int iRet;
  667. pCache->SetRemote(TRUE);
  668. // Note that RegConnectRegistry requires a NON constant name
  669. // pointer (ARG!) and thus a temp string must be created!!
  670. TString sTemp;
  671. sTemp = pNewMachine;
  672. iRet = RegConnectRegistry(sTemp, hRoot,pKey);
  673. sTemp.Empty();
  674. if(iRet == 0)
  675. iRet = pCache->lAddToList(pNewMachine,NULL); // dont need to free this
  676. if(iRet == 0)
  677. iRet = pCache->lAddToList(pNewRoot,*pKey); // do free this.
  678. return iRet;
  679. }
  680. else
  681. {
  682. // Local registry. Save tokens and handles. By adding NULL to the
  683. // cache, the handle will not be freed.
  684. pCache->SetRemote(FALSE);
  685. iRet = pCache->lAddToList(pNewMachine,NULL);
  686. if(iRet == 0)
  687. iRet = pCache->lAddToList(pNewRoot,NULL); // standard handles dont need to be freed
  688. *pKey = hRoot;
  689. }
  690. return iRet;
  691. }
  692. //***************************************************************************
  693. //
  694. // int CImpReg::iLookUpInt
  695. //
  696. // DESCRIPTION:
  697. //
  698. // Searches (case insensitive) the list of interface types and
  699. // returns the index of the match or -1 if no match.
  700. //
  701. // PARAMETERS:
  702. //
  703. // tpTest name to search for
  704. //
  705. // RETURN VALUE:
  706. //
  707. // see description.
  708. //***************************************************************************
  709. int CImpReg::iLookUpInt(
  710. const TCHAR * tpTest)
  711. {
  712. int iCnt,iSize;
  713. iSize = sizeof(cpIntTypes) / sizeof(TCHAR *);
  714. for(iCnt = 0; iCnt < iSize; iCnt++)
  715. if(tpTest != NULL && !lstrcmpi(tpTest,cpIntTypes[iCnt]))
  716. return iCnt;
  717. return -1;
  718. }
  719. //***************************************************************************
  720. //
  721. // int CImpReg::iLookUpOffset
  722. //
  723. // DESCRIPTION:
  724. //
  725. // Searches (case insensitive) the list data types held in
  726. // resource descripters.
  727. //
  728. // PARAMETERS:
  729. //
  730. // tpTest String to look for
  731. // iType Set to the type
  732. // iTypeSize Set to the type's size
  733. //
  734. // RETURN VALUE:
  735. //
  736. // Returns index if match is found (-1 for failure) and also
  737. // sets the referneces that specifiy which type and the type's
  738. // size.
  739. //
  740. //
  741. //***************************************************************************
  742. int CImpReg::iLookUpOffset(
  743. IN const TCHAR * tpTest,
  744. OUT int & iType,
  745. OUT int & iTypeSize)
  746. {
  747. int iCnt, iSize;
  748. iSize = sizeof(Offsets) / sizeof(struct UnionOffset);
  749. for(iCnt = 0; iCnt < iSize; iCnt++)
  750. if(tpTest != NULL && !lstrcmpi(tpTest,Offsets[iCnt].tpName))
  751. {
  752. iType = Offsets[iCnt].iType;
  753. iTypeSize = Offsets[iCnt].iSize;
  754. return Offsets[iCnt].iOffset;
  755. }
  756. return -1;
  757. }
  758. //***************************************************************************
  759. //
  760. // int CImpReg::OpenKeyForWritting
  761. //
  762. // DESCRIPTION:
  763. //
  764. // Opens a registry for updates. Since updates are writes, it is
  765. // possible that the key may need to be created. Since DM reg
  766. // does not support RegCreateKey, then it must be called and the
  767. // resulting key closed for the new key case.
  768. //
  769. // PARAMETERS:
  770. //
  771. // hCurr Parent key
  772. // pName sub key to be opened/created
  773. // pNew pointer to opened/created key
  774. // pCache handle cache.
  775. //
  776. // RETURN VALUE:
  777. //
  778. // 0 if OK,
  779. // else set by RegOpenKey or RegCreateKey
  780. //
  781. //***************************************************************************
  782. int CImpReg::OpenKeyForWritting(
  783. HKEY hCurr,
  784. LPTSTR pName,
  785. HKEY * pNew,
  786. CHandleCache * pCache)
  787. {
  788. int iRet;
  789. iRet = RegOpenKeyEx(hCurr,pName,0,KEY_WRITE,pNew);
  790. if(iRet == 0) // all done should be normal case.
  791. return 0;
  792. iRet = RegOpenKeyEx(hCurr,pName,0,KEY_SET_VALUE,pNew);
  793. if(iRet == 0) // all done should be normal case.
  794. return 0;
  795. // Try creating the key. If not using DM reg, just use the key from
  796. // here
  797. iRet = RegCreateKey(hCurr,pName,pNew);
  798. if(hDMRegLib!=NULL && !pCache->IsRemote() && iRet == 0)
  799. {
  800. // Close the key and reopen
  801. RegCloseKey(*pNew);
  802. iRet = pOpen(hCurr,pName,0,0,KEY_QUERY_VALUE,pNew);
  803. }
  804. return iRet;
  805. }
  806. //***************************************************************************
  807. //
  808. // SCODE CImpReg::ReadRegData
  809. //
  810. // DESCRIPTION:
  811. //
  812. // Allocates a buffer and reads the registry. If the buffer is not large
  813. // enough, then it is reallocated and reread.
  814. //
  815. // PARAMETERS:
  816. //
  817. // hKey Registry Key
  818. // pName Value Name
  819. // dwRegType Set to the type
  820. // dwSize set to the size
  821. // pData set to the allocated data. This must be freed via
  822. // CoTaskmemFree()
  823. // pCache Handle Cache.
  824. //
  825. // RETURN VALUE:
  826. //
  827. // Return: Registry value. Also sets the size and type of the registry data
  828. //
  829. //***************************************************************************
  830. SCODE CImpReg::ReadRegData(
  831. IN HKEY hKey,
  832. IN const TCHAR * pName,
  833. OUT DWORD & dwRegType,
  834. OUT DWORD & dwSize,
  835. OUT void ** pData,
  836. IN CHandleCache * pCache)
  837. {
  838. void * pRet;
  839. int iRet;
  840. // Initially the buffer is set to hold INIT_SIZE
  841. // bytes. If that isnt enough, the query will be
  842. // repeated a second time
  843. dwSize = INIT_SIZE;
  844. pRet = (unsigned char *)CoTaskMemAlloc(dwSize);
  845. if(pRet == NULL)
  846. {
  847. return WBEM_E_OUT_OF_MEMORY;
  848. }
  849. if(hDMRegLib && !pCache->IsRemote())
  850. iRet = pQueryValue(hKey, (TCHAR *) pName, 0l, &dwRegType, (LPBYTE)pRet,&dwSize);
  851. else
  852. iRet = RegQueryValueEx(hKey, pName, 0l, &dwRegType,
  853. (LPBYTE)pRet,&dwSize);
  854. // If we failed for lack of space, retry once.
  855. if(iRet == ERROR_MORE_DATA)
  856. {
  857. pRet= (char *)CoTaskMemRealloc(pRet, dwSize);
  858. if(pRet == NULL)
  859. {
  860. return WBEM_E_OUT_OF_MEMORY;
  861. }
  862. if(hDMRegLib && !pCache->IsRemote())
  863. iRet = pQueryValue(hKey, (TCHAR *) pName, 0l, &dwRegType,
  864. (LPBYTE)pRet,&dwSize);
  865. else
  866. iRet = RegQueryValueEx(hKey, pName, 0l, &dwRegType,
  867. (LPBYTE)pRet, &dwSize);
  868. }
  869. *pData = pRet;
  870. return iRet;
  871. }
  872. //***************************************************************************
  873. //
  874. // SCODE CImpReg::RefreshProperty
  875. //
  876. // DESCRIPTION:
  877. //
  878. // Gets the value of a single property from the registry.
  879. //
  880. // PARAMETERS:
  881. //
  882. // lFlags flags. Not currently used
  883. // pClassInt Instance object
  884. // PropName Property name
  885. // ProvObj Object containing the property context string.
  886. // pPackage Caching object
  887. // pVar Points to value to set
  888. // bTesterDetails Provide extra info for testers
  889. //
  890. // RETURN VALUE:
  891. //
  892. // S_OK
  893. // WBEM_E_INVALID_PARAMETER
  894. // or others??
  895. //***************************************************************************
  896. SCODE CImpReg::RefreshProperty(
  897. long lFlags,
  898. IWbemClassObject FAR * pClassInt,
  899. BSTR PropName,
  900. CProvObj & ProvObj,
  901. CObject * pPackage,
  902. CVariant * pVar, BOOL bTesterDetails)
  903. {
  904. int iCnt;
  905. int iNumSkip; // number of handles already provided by cache.
  906. CHandleCache * pCache = (CHandleCache *)pPackage;
  907. DWORD dwRegType,dwBufferSize;
  908. void * pData = NULL;
  909. const TCHAR * pName;
  910. HKEY hCurr,hNew;
  911. SCODE sc;
  912. // Do a second parse on the provider string. The initial parse
  913. // is done by the calling routine and it's first token is
  914. // the path. The path token is then parsed
  915. // into RegPath and it will have a token for each part of the
  916. // registry path.
  917. CProvObj RegPath(ProvObj.sGetFullToken(1),SUB_DELIM,true);
  918. sc = RegPath.dwGetStatus(1);
  919. if(sc != S_OK)
  920. return WBEM_E_INVALID_PARAMETER;
  921. // Get a handle to a place in the reg path. Note that it might be just
  922. // a root key (such as HKEY_LOCAL_MACHINE) or it might be a subkey
  923. // if the cache contains some open handles that can be used.
  924. sc = GetRoot(&hCurr,RegPath,ProvObj.sGetFullToken(0),
  925. pCache,iNumSkip);
  926. if(sc != ERROR_SUCCESS)
  927. return sc;
  928. // Go down the registry path till we get to the key
  929. for(iCnt = 1+iNumSkip; iCnt < RegPath.iGetNumTokens(); iCnt ++)
  930. {
  931. int iRet;
  932. if(hDMRegLib && !pCache->IsRemote())
  933. iRet = pOpen(hCurr,RegPath.sGetToken(iCnt),0,0,KEY_QUERY_VALUE,&hNew);
  934. else
  935. iRet = RegOpenKeyEx(hCurr,RegPath.sGetToken(iCnt),0,KEY_READ,&hNew);
  936. if(iRet != ERROR_SUCCESS)
  937. {
  938. sc = iRet; // bad path!
  939. return sc;
  940. }
  941. hCurr = hNew;
  942. sc = pCache->lAddToList(RegPath.sGetToken(iCnt),hNew);
  943. if(sc != ERROR_SUCCESS)
  944. return sc;
  945. }
  946. // If it is a named value, get a pointer to the name
  947. if(ProvObj.iGetNumTokens() > MIN_REG_TOKENS)
  948. pName = ProvObj.sGetToken(MIN_REG_TOKENS);
  949. else
  950. pName = NULL;
  951. // Time to get the data.
  952. sc = ReadRegData(hCurr, pName,dwRegType, dwBufferSize, &pData,pCache);
  953. if(sc == S_OK && dwBufferSize == 0)
  954. sc = 2;
  955. if(sc == S_OK)
  956. {
  957. CVariant cVar;
  958. if(dwRegType == REG_RESOURCE_LIST || dwRegType == REG_FULL_RESOURCE_DESCRIPTOR)
  959. sc = ConvertGetDataFromDesc(cVar,pData,dwRegType,dwBufferSize,ProvObj);
  960. else
  961. sc = ConvertGetDataFromSimple(cVar,pData,dwRegType,dwBufferSize,pClassInt,PropName);
  962. if(sc == S_OK)
  963. sc = cVar.DoPut(lFlags,pClassInt,PropName,pVar);
  964. }
  965. if(pData != NULL)
  966. CoTaskMemFree(pData);
  967. return sc;
  968. }
  969. //***************************************************************************
  970. //
  971. // SCODE CImpReg::StartBatch
  972. //
  973. // DESCRIPTION:
  974. //
  975. // Called at the start of a batch of Refrest/Update Property calls. Initialize
  976. // the handle cache.
  977. //
  978. // PARAMETERS:
  979. //
  980. // lFlags flags
  981. // pClassInt Points to an instance object
  982. // pObj Misc object pointer
  983. // bGet TRUE if we will be getting data.
  984. //
  985. // RETURN VALUE:
  986. //
  987. // S_OK all is well
  988. // WBEM_E_OUT_OF_MEMORY
  989. //***************************************************************************
  990. SCODE CImpReg::StartBatch(
  991. long lFlags,
  992. IWbemClassObject FAR * pClassInt,
  993. CObject **pObj,
  994. BOOL bGet)
  995. {
  996. *pObj = new CHandleCache;
  997. return (*pObj) ? S_OK : WBEM_E_OUT_OF_MEMORY;
  998. }
  999. //***************************************************************************
  1000. //
  1001. // SCODE CImpReg::UpdateProperty
  1002. //
  1003. // DESCRIPTION:
  1004. //
  1005. // Sets the value of a single property into the registry.
  1006. //
  1007. // PARAMETERS:
  1008. //
  1009. // lFlags not used
  1010. // pClassInt pointer to instance object
  1011. // PropName property name
  1012. // ProvObj Object containing the property context string.
  1013. // pPackage pointer to the handle cache
  1014. // pVar value to be set
  1015. //
  1016. // RETURN VALUE:
  1017. //
  1018. // S_OK if ok,
  1019. // otherwise misc errors.
  1020. //***************************************************************************
  1021. SCODE CImpReg::UpdateProperty(
  1022. IN long lFlags,
  1023. IN IWbemClassObject FAR * pClassInt,
  1024. IN BSTR PropName,
  1025. IN CProvObj & ProvObj,
  1026. IN CObject * pPackage,
  1027. IN CVariant * pVar)
  1028. {
  1029. int iCnt;
  1030. SCODE sc;
  1031. void * pData;
  1032. TString sProv;
  1033. CHandleCache * pCache = (CHandleCache *)pPackage;
  1034. const TCHAR * pName;
  1035. int iNumSkip;
  1036. HKEY hCurr,hNew;
  1037. DWORD dwRegType, dwBufferSize;
  1038. // Do a second parse on the provider string. The initial parse
  1039. // is done by the calling routine and it's first token is
  1040. // the path. The path token is then parsed
  1041. // into RegPath and it will have a token for each part of the
  1042. // registry path.
  1043. CProvObj RegPath(ProvObj.sGetFullToken(1),SUB_DELIM,true);
  1044. sc = RegPath.dwGetStatus(1);
  1045. if(sc != WBEM_NO_ERROR)
  1046. return sc;
  1047. // Get a handle to a place in the reg path. Note that it might be just
  1048. // a root key (such as HKEY_LOCAL_MACHINE) or it might be a subkey
  1049. // if the cache contains some open handles that can be used.
  1050. sc = GetRoot(&hCurr,RegPath,ProvObj.sGetFullToken(0),
  1051. pCache,iNumSkip);
  1052. if(sc != ERROR_SUCCESS)
  1053. return sc;
  1054. // Go down the registry path, creating keys if necessary
  1055. for(iCnt = 1+iNumSkip; iCnt < RegPath.iGetNumTokens(); iCnt ++)
  1056. {
  1057. int iRet;
  1058. iRet = OpenKeyForWritting(hCurr,(LPTSTR)RegPath.sGetToken(iCnt),
  1059. &hNew, pCache);
  1060. if(iRet != ERROR_SUCCESS)
  1061. {
  1062. sc = iRet;
  1063. return sc;
  1064. }
  1065. hCurr = hNew;
  1066. sc = pCache->lAddToList(RegPath.sGetToken(iCnt),hNew);
  1067. if(sc != ERROR_SUCCESS)
  1068. return sc;
  1069. }
  1070. // If it is a named value, get a pointer to the name
  1071. if(ProvObj.iGetNumTokens() > MIN_REG_TOKENS)
  1072. pName = ProvObj.sGetToken(MIN_REG_TOKENS);
  1073. else
  1074. pName = NULL;
  1075. // Get the data and set it
  1076. CVariant cVar;
  1077. if(pClassInt)
  1078. {
  1079. sc = pClassInt->Get(PropName,0,cVar.GetVarPtr(),NULL,NULL);
  1080. }
  1081. else if(pVar)
  1082. {
  1083. sc = OMSVariantChangeType(cVar.GetVarPtr(),
  1084. pVar->GetVarPtr(),0, pVar->GetType());
  1085. }
  1086. else
  1087. sc = WBEM_E_FAILED;
  1088. if(sc != S_OK)
  1089. return sc;
  1090. sc = ConvertSetData(cVar, &pData, &dwRegType, &dwBufferSize);
  1091. if(sc == S_OK)
  1092. {
  1093. if(hDMRegLib && !pCache->IsRemote())
  1094. sc = pSetValue(hCurr, pName, 0l,
  1095. dwRegType, (LPBYTE)pData, dwBufferSize);
  1096. else
  1097. sc = RegSetValueEx(hCurr, pName, 0l,
  1098. dwRegType, (LPBYTE)pData, dwBufferSize);
  1099. CoTaskMemFree(pData);
  1100. }
  1101. return sc;
  1102. }
  1103. //***************************************************************************
  1104. //
  1105. // SCODE CImpReg::MakeEnum
  1106. //
  1107. // DESCRIPTION:
  1108. //
  1109. // Creates a CEnumRegInfo object which can be used for enumeration
  1110. //
  1111. // PARAMETERS:
  1112. //
  1113. // pClass Pointer to the class object.
  1114. // ProvObj Object containing the property context string.
  1115. // ppInfo Set to point to an collection object which has
  1116. // the keynames of the instances.
  1117. //
  1118. // RETURN VALUE:
  1119. //
  1120. // S_OK all is well,
  1121. // WBEM_E_INVALID_PARAMETER bad context string
  1122. // WBEM_E_OUT_OF_MEMORY
  1123. // WBEM_E_FAILED couldnt open the root key
  1124. // or RegConnectRegistry failure,
  1125. // or RegOpenKeyEx failure
  1126. //
  1127. //***************************************************************************
  1128. SCODE CImpReg::MakeEnum(
  1129. IWbemClassObject * pClass,
  1130. CProvObj & ProvObj,
  1131. CEnumInfo ** ppInfo)
  1132. {
  1133. HKEY hRoot = NULL;
  1134. HKEY hKey = NULL;
  1135. HKEY hRemoteKey = NULL;
  1136. // Parse the class context
  1137. if(ProvObj.iGetNumTokens() < 2)
  1138. return WBEM_E_INVALID_PARAMETER;
  1139. TCHAR * pTemp = new TCHAR[lstrlen(ProvObj.sGetToken(1))+1];
  1140. if(pTemp == NULL)
  1141. return WBEM_E_OUT_OF_MEMORY;
  1142. lstrcpy(pTemp,ProvObj.sGetToken(1));
  1143. // Point to the root name and path. These initially in a single string
  1144. // and separated by a '\'. find the backslash and replace with a null
  1145. LPTSTR pRoot = pTemp;
  1146. LPTSTR pPath;
  1147. for(pPath = pRoot; *pPath; pPath++)
  1148. if(*pPath == TEXT('\\'))
  1149. break;
  1150. if(*pPath == NULL || pPath[1] == NULL)
  1151. {
  1152. pPath = NULL;
  1153. }
  1154. else
  1155. {
  1156. *pPath = NULL;
  1157. pPath ++;
  1158. }
  1159. // Got to get the root key. First, use the second token to determine
  1160. // which predefined key to use. That would be something like;
  1161. // HKEY_CURRENT_USER.
  1162. int iSize= sizeof(Bases) / sizeof(struct BaseTypes), iCnt;
  1163. for(iCnt = 0; iCnt < iSize; iCnt++)
  1164. if(!lstrcmpi(pRoot,Bases[iCnt].lpName))
  1165. {
  1166. hRoot = Bases[iCnt].hKey;
  1167. break;
  1168. }
  1169. if(hRoot == NULL)
  1170. {
  1171. delete pTemp;
  1172. return WBEM_E_FAILED;
  1173. }
  1174. if(hRoot == HKEY_CURRENT_USER && m_bLoadedProfile && !lstrcmpi(ProvObj.sGetToken(0),TEXT("local")))
  1175. hRoot = m_hRoot;
  1176. // If the machine is remote, hook up to it. Note that RegConnectRegistry
  1177. // requires a non constant arg for the machine name and so a temp string
  1178. // must be created.
  1179. if(lstrcmpi(ProvObj.sGetToken(0),TEXT("local")))
  1180. {
  1181. TCHAR * pMachine = new TCHAR[lstrlen(ProvObj.sGetToken(0))+1];
  1182. if(pMachine == NULL)
  1183. {
  1184. delete pTemp;
  1185. return WBEM_E_FAILED;
  1186. }
  1187. lstrcpy(pMachine,ProvObj.sGetToken(0));
  1188. int iRet = RegConnectRegistry(pMachine,hRoot,&hRemoteKey);
  1189. delete pMachine;
  1190. if(iRet != 0)
  1191. {
  1192. delete pTemp;
  1193. return iRet;
  1194. }
  1195. hRoot = hRemoteKey;
  1196. }
  1197. // Open the key down to be used for enumeration!
  1198. int iRet;
  1199. if(hDMRegLib && hRemoteKey == NULL)
  1200. iRet = pOpen(hRoot,pPath,0,0,KEY_ALL_ACCESS,&hKey);
  1201. else
  1202. iRet = RegOpenKeyEx(hRoot,pPath,0,KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS ,&hKey);
  1203. delete pTemp; // all done
  1204. if(iRet == ERROR_BAD_IMPERSONATION_LEVEL)
  1205. return WBEM_E_ACCESS_DENIED;
  1206. if(iRet != 0)
  1207. return WBEM_E_FAILED;
  1208. if(hDMRegLib && hRemoteKey == NULL)
  1209. *ppInfo = new CEnumRegInfo(hKey,hRemoteKey,pClose);
  1210. else
  1211. *ppInfo = new CEnumRegInfo(hKey,hRemoteKey,NULL);
  1212. return (*ppInfo) ? S_OK : WBEM_E_OUT_OF_MEMORY;
  1213. }
  1214. //***************************************************************************
  1215. //
  1216. // SCODE CImpReg::GetKey
  1217. //
  1218. // DESCRIPTION:
  1219. //
  1220. // Gets the key name of an entry in the enumeration list.
  1221. //
  1222. // PARAMETERS:
  1223. //
  1224. // pInfo Collection list
  1225. // iIndex Index in the collection
  1226. // ppKey Set to the string. MUST BE FREED with "delete"
  1227. //
  1228. // RETURN VALUE:
  1229. //
  1230. // S_OK if all is well
  1231. // WBEM_E_FAILED end of data
  1232. // WBEM_E_OUT_OF_MEMORY
  1233. //***************************************************************************
  1234. SCODE CImpReg::GetKey(
  1235. CEnumInfo * pInfo,
  1236. int iIndex,
  1237. LPWSTR * ppKey)
  1238. {
  1239. CEnumRegInfo * pRegInfo = (CEnumRegInfo *)pInfo;
  1240. BOOL bUseDM = (hDMRegLib && pRegInfo->GetRemoteKey() == NULL);
  1241. int iSize = 100;
  1242. LPTSTR pData = NULL;
  1243. *ppKey = NULL;
  1244. long lRet = ERROR_MORE_DATA;
  1245. while(lRet == ERROR_MORE_DATA && iSize < 1000)
  1246. {
  1247. FILETIME ft;
  1248. iSize *= 2;
  1249. if(pData)
  1250. delete pData;
  1251. pData = new TCHAR[iSize];
  1252. if(pData == NULL)
  1253. return WBEM_E_OUT_OF_MEMORY;
  1254. DWORD dwSize = iSize;
  1255. if(bUseDM)
  1256. lRet = pEnumKey(pRegInfo->GetKey(),iIndex,pData,&dwSize,NULL,NULL,NULL,&ft);
  1257. else
  1258. lRet = RegEnumKeyEx(pRegInfo->GetKey(),iIndex,pData,&dwSize,NULL,NULL,NULL,&ft);
  1259. }
  1260. if(lRet == 0)
  1261. {
  1262. // got data. if we are in unicode, just use the current buffer, otherwise
  1263. // we have to convert
  1264. #ifdef UNICODE
  1265. *ppKey = pData;
  1266. return S_OK;
  1267. #else
  1268. *ppKey = new WCHAR[lstrlen(pData)+1];
  1269. if(*ppKey == NULL)
  1270. {
  1271. delete pData;
  1272. return WBEM_E_OUT_OF_MEMORY;
  1273. }
  1274. mbstowcs(*ppKey,pData,lstrlen(pData)+1);
  1275. delete pData;
  1276. return S_OK;
  1277. #endif
  1278. }
  1279. delete pData;
  1280. return WBEM_E_FAILED;
  1281. }
  1282. //***************************************************************************
  1283. //
  1284. // CEnumRegInfo::CEnumRegInfo
  1285. //
  1286. // DESCRIPTION:
  1287. //
  1288. // Constructor.
  1289. //
  1290. // PARAMETERS:
  1291. //
  1292. // hKey Registry Key
  1293. // hRemoteKey Remote registry key
  1294. // pClose pointer to function used to close the handle
  1295. //
  1296. //***************************************************************************
  1297. CEnumRegInfo::CEnumRegInfo(
  1298. HKEY hKey,
  1299. HKEY hRemoteKey,
  1300. PCLOSE pClose)
  1301. {
  1302. m_pClose = pClose;
  1303. m_hKey = hKey;
  1304. m_hRemoteKey = hRemoteKey;
  1305. }
  1306. //***************************************************************************
  1307. //
  1308. // CEnumRegInfo::~CEnumRegInfo
  1309. //
  1310. // DESCRIPTION:
  1311. //
  1312. // Destructor.
  1313. //
  1314. //***************************************************************************
  1315. CEnumRegInfo::~CEnumRegInfo()
  1316. {
  1317. long lRet;
  1318. if(m_pClose != NULL && m_hRemoteKey == NULL)
  1319. lRet = m_pClose(m_hKey);
  1320. else
  1321. lRet = RegCloseKey(m_hKey);
  1322. if(m_hRemoteKey)
  1323. lRet = RegCloseKey(m_hRemoteKey);
  1324. }
  1325. //***************************************************************************
  1326. //
  1327. // CImpRegProp::CImpRegProp
  1328. //
  1329. // DESCRIPTION:
  1330. //
  1331. // Constructor.
  1332. //
  1333. //***************************************************************************
  1334. CImpRegProp::CImpRegProp()
  1335. {
  1336. m_pImpDynProv = new CImpReg();
  1337. }
  1338. //***************************************************************************
  1339. //
  1340. // CImpRegProp::~CImpRegProp
  1341. //
  1342. // DESCRIPTION:
  1343. //
  1344. // Destructor.
  1345. //
  1346. //***************************************************************************
  1347. CImpRegProp::~CImpRegProp()
  1348. {
  1349. if(m_pImpDynProv)
  1350. delete m_pImpDynProv;
  1351. }