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.

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