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.

1653 lines
41 KiB

  1. //============================================================================
  2. // Copyright (C) Microsoft Corporation, 1996 - 1999
  3. //
  4. // File: infobase.cpp
  5. //
  6. // History:
  7. // Abolade Gbadegesin Feb. 10, 1996 Created.
  8. //
  9. // V. Raman Nov. 1, 1996
  10. // Fixed alignment code in
  11. // CInfoBase::BlockListToArray
  12. //
  13. // Kenn Takara June 3, 1997
  14. // Wrapped code with a COM object wrapper.
  15. //
  16. // This file contains code for the CInfoBase class as well as
  17. // the Router registry-parsing classes.
  18. //============================================================================
  19. #include "stdafx.h"
  20. #include "globals.h" // holds the various string constants
  21. extern "C" {
  22. #include <rtinfo.h>
  23. }
  24. #ifdef _DEBUG
  25. #define new DEBUG_NEW
  26. #undef THIS_FILE
  27. static char THIS_FILE[] = __FILE__;
  28. #endif
  29. //----------------------------------------------------------------------------
  30. // Class: CInfoBase
  31. //
  32. // This function handles loading and saving of multi-block structures
  33. // stored in the registry by the router managers.
  34. //
  35. // The data are saved as REG_BINARY values, and are manipulated using
  36. // the RTR_INFO_BLOCK_HEADER structure as a template.
  37. //----------------------------------------------------------------------------
  38. class CInfoBase : public CObject {
  39. protected:
  40. IfDebug(DECLARE_DYNAMIC(CInfoBase))
  41. public:
  42. CInfoBase();
  43. ~CInfoBase();
  44. //--------------------------------------------------------------------
  45. // Registry-access methods
  46. //
  47. //--------------------------------------------------------------------
  48. //--------------------------------------------------------------------
  49. // Function: Load
  50. //
  51. // Loads value named 'pszValue' from subkey 'pszKey' of 'hkey'
  52. //--------------------------------------------------------------------
  53. HRESULT
  54. Load(
  55. IN HKEY hkey,
  56. IN LPCTSTR pszKey,
  57. IN LPCTSTR pszValue );
  58. //--------------------------------------------------------------------
  59. // Function: Save
  60. //
  61. // saves value named 'pszValue' to subkey 'pszKey' of 'hkey';
  62. // 'pszKey' cannot be a path
  63. //--------------------------------------------------------------------
  64. HRESULT
  65. Save(
  66. IN HKEY hkey,
  67. IN LPCTSTR pszKey,
  68. IN LPCTSTR pszValue );
  69. //--------------------------------------------------------------------
  70. // Function: Unload
  71. //
  72. // unloads current infobase contents
  73. //--------------------------------------------------------------------
  74. HRESULT
  75. Unload( );
  76. //--------------------------------------------------------------------
  77. // Function: CopyFrom
  78. //
  79. // copies contents of infobase 'src'
  80. //--------------------------------------------------------------------
  81. HRESULT
  82. CopyFrom(
  83. IN IInfoBase *pSrc);
  84. //--------------------------------------------------------------------
  85. // Function: LoadFrom
  86. //
  87. // loads from byte-array 'pBase'
  88. //--------------------------------------------------------------------
  89. HRESULT
  90. LoadFrom(
  91. IN PBYTE pBase,
  92. IN DWORD dwSize = 0 )
  93. { Unload(); return ArrayToBlockList(pBase, dwSize); }
  94. //--------------------------------------------------------------------
  95. // Function: WriteTo
  96. //
  97. // sets 'pBase' to point to allocated memory into which
  98. // opaque info is written; saves size of '*pBase' in 'dwSize'
  99. //--------------------------------------------------------------------
  100. HRESULT
  101. WriteTo(
  102. OUT PBYTE& pBase,
  103. OUT DWORD& dwSize )
  104. {
  105. return BlockListToArray(pBase, dwSize);
  106. }
  107. //--------------------------------------------------------------------
  108. // Structure manipulation methods
  109. //
  110. //--------------------------------------------------------------------
  111. //--------------------------------------------------------------------
  112. // Function: GetBlock
  113. //
  114. // retrieves 'dwNth' block of type 'dwType' from the list of blocks
  115. //--------------------------------------------------------------------
  116. HRESULT
  117. GetBlock(
  118. IN DWORD dwType,
  119. OUT InfoBlock*& pBlock,
  120. IN DWORD dwNth = 0 );
  121. //--------------------------------------------------------------------
  122. // Function: SetBlock
  123. //
  124. // Replaces 'dwNth' block of type 'dwType' with a copy of 'pBlock'.
  125. // Note that this copies the data for the block from 'pBlock->pData'.
  126. //--------------------------------------------------------------------
  127. HRESULT
  128. SetBlock(
  129. IN DWORD dwType,
  130. IN InfoBlock* pBlock,
  131. IN DWORD dwNth = 0 );
  132. //--------------------------------------------------------------------
  133. // Function: AddBlock
  134. //
  135. // Add's a new block of type 'dwType' to the list of blocks
  136. //--------------------------------------------------------------------
  137. HRESULT
  138. AddBlock(
  139. IN DWORD dwType,
  140. IN DWORD dwSize,
  141. IN PBYTE pData,
  142. IN DWORD dwCount = 1,
  143. IN BOOL bRemoveFirst = FALSE );
  144. //--------------------------------------------------------------------
  145. // Function: GetData
  146. //
  147. // Retrieves the data for the 'dwNth' block of type 'dwType'.
  148. //--------------------------------------------------------------------
  149. PBYTE
  150. GetData(
  151. IN DWORD dwType,
  152. IN DWORD dwNth = 0 );
  153. //--------------------------------------------------------------------
  154. // Function: SetData
  155. //
  156. // Replaces the data for the 'dwNth' block of type 'dwType'.
  157. // Note that this does not copy 'pData'; the block is changed
  158. // to point to 'pData', and thus 'pData' should not be a pointer
  159. // to data on the stack, and it should not be deleted.
  160. // Furthermore, it must have been allocated using 'new'.
  161. //--------------------------------------------------------------------
  162. HRESULT
  163. SetData(
  164. IN DWORD dwType,
  165. IN DWORD dwSize,
  166. IN PBYTE pData,
  167. IN DWORD dwCount = 1,
  168. IN DWORD dwNth = 0 );
  169. //--------------------------------------------------------------------
  170. // Function: RemoveBlock
  171. //
  172. // Removes the 'dwNth' block of type 'dwType' from the list of blocks.
  173. //--------------------------------------------------------------------
  174. HRESULT
  175. RemoveBlock(
  176. IN DWORD dwType,
  177. IN DWORD dwNth = 0 );
  178. //--------------------------------------------------------------------
  179. // Function: BlockExists
  180. //
  181. // Returns TRUE is a block of the specified type is in the block-list,
  182. // FALSE otherwise
  183. //--------------------------------------------------------------------
  184. BOOL
  185. BlockExists(
  186. IN DWORD dwType
  187. ) {
  188. InfoBlock *pblock;
  189. return (GetBlock(dwType, pblock) == NO_ERROR);
  190. }
  191. //--------------------------------------------------------------------
  192. // Function: ProtocolExists
  193. //
  194. // Returns TRUE if the given routing-protocol exists in the info-base;
  195. // this is so if the block is present and non-empty.
  196. //--------------------------------------------------------------------
  197. BOOL
  198. ProtocolExists(
  199. IN DWORD dwProtocol
  200. ) {
  201. InfoBlock *pblock;
  202. return (!GetBlock(dwProtocol, pblock) && pblock->dwSize);
  203. }
  204. //--------------------------------------------------------------------
  205. // Function: RemoveAllBlocks
  206. //
  207. // Removes all blocks from the list of blocks.
  208. //--------------------------------------------------------------------
  209. HRESULT
  210. RemoveAllBlocks( ) { return Unload(); }
  211. //--------------------------------------------------------------------
  212. // Function: QueryBlockList
  213. //
  214. // Returns a reference to the list of blocks;
  215. // the returned list contains items of type 'InfoBlock',
  216. // and the list must not be modified.
  217. //--------------------------------------------------------------------
  218. CPtrList&
  219. QueryBlockList( ) { return m_lBlocks; }
  220. //--------------------------------------------------------------------
  221. // Function: GetInfo
  222. //
  223. // Returns information about the infobase. This is useful for
  224. // determining if this is a new infobase or not.
  225. //
  226. // Returns the size (in bytes) of the InfoBase as well as the
  227. // number of blocks.
  228. //--------------------------------------------------------------------
  229. HRESULT
  230. GetInfo(DWORD *pcSize, int *pcBlocks);
  231. protected:
  232. PBYTE m_pBase; // opaque block of bytes loaded
  233. DWORD m_dwSize; // size of m_pBase
  234. CPtrList m_lBlocks; // list of blocks of type InfoBlock
  235. //--------------------------------------------------------------------
  236. // Functions: BlockListToArray
  237. // ArrayToBlockList
  238. //
  239. // These functions handle parsing opaque data into block-lists
  240. // and combining blocks into opaque data.
  241. //--------------------------------------------------------------------
  242. HRESULT
  243. BlockListToArray(
  244. IN PBYTE& pBase,
  245. IN DWORD& dwSize );
  246. HRESULT
  247. ArrayToBlockList(
  248. IN PBYTE pBase,
  249. IN DWORD dwSize );
  250. #ifdef _DEBUG
  251. BOOL m_fLoaded; // TRUE if data was loaded
  252. #endif
  253. };
  254. //---------------------------------------------------------------------------
  255. // Class: CInfoBase
  256. //---------------------------------------------------------------------------
  257. IfDebug(IMPLEMENT_DYNAMIC(CInfoBase, CObject));
  258. //---------------------------------------------------------------------------
  259. // Function: CInfoBase::CInfoBase
  260. //
  261. // minimal contructor
  262. //---------------------------------------------------------------------------
  263. CInfoBase::CInfoBase()
  264. : m_pBase(NULL), m_dwSize(0)
  265. #ifdef _DEBUG
  266. , m_fLoaded(FALSE)
  267. #endif
  268. { }
  269. //---------------------------------------------------------------------------
  270. // Function: CInfoBase::CInfoBase
  271. //
  272. // destructor.
  273. //---------------------------------------------------------------------------
  274. CInfoBase::~CInfoBase() { Unload(); }
  275. //---------------------------------------------------------------------------
  276. // Function: CInfoBase::CopyFrom
  277. //
  278. // Copies the contents of the given CInfoBase
  279. //---------------------------------------------------------------------------
  280. HRESULT
  281. CInfoBase::CopyFrom(
  282. IN IInfoBase *pSrc
  283. ) {
  284. SPIEnumInfoBlock spEnumInfoBlock;
  285. InfoBlock * pbsrc = NULL;
  286. InfoBlock * pbdst = NULL;
  287. HRESULT hr = hrOK;
  288. COM_PROTECT_TRY
  289. {
  290. // Unload the current information, if any
  291. Unload();
  292. // go through the source's blocks copying each one
  293. pSrc->QueryBlockList(&spEnumInfoBlock);
  294. if (spEnumInfoBlock == NULL)
  295. goto Error;
  296. spEnumInfoBlock->Reset();
  297. while (hrOK == spEnumInfoBlock->Next(1, &pbsrc, NULL))
  298. {
  299. // allocate space for the copy
  300. pbdst = new InfoBlock;
  301. Assert(pbdst);
  302. // copy the fields from the source
  303. pbdst->dwType = pbsrc->dwType;
  304. pbdst->dwSize = pbsrc->dwSize;
  305. pbdst->dwCount = pbsrc->dwCount;
  306. // allocate space for a copy of the data
  307. pbdst->pData = NULL;
  308. pbdst->pData = new BYTE[pbsrc->dwSize * pbsrc->dwCount];
  309. Assert(pbdst->pData);
  310. // copy the data
  311. ::CopyMemory(pbdst->pData, pbsrc->pData,
  312. pbsrc->dwSize * pbsrc->dwCount);
  313. // add the copy to our list of blocks
  314. m_lBlocks.AddTail(pbdst);
  315. pbdst = NULL;
  316. }
  317. COM_PROTECT_ERROR_LABEL;
  318. }
  319. COM_PROTECT_CATCH;
  320. // if something went wrong, make certain we're unloaded
  321. if (!FHrSucceeded(hr))
  322. {
  323. if (pbdst)
  324. delete pbdst->pData;
  325. delete pbdst;
  326. Unload();
  327. }
  328. #ifdef _DEBUG
  329. if (FHrSucceeded(hr))
  330. m_fLoaded = TRUE;
  331. #endif
  332. return hr;
  333. }
  334. //---------------------------------------------------------------------------
  335. // Function: CInfoBase::Load
  336. //
  337. // Loads the infobase from the specified registry path.
  338. //---------------------------------------------------------------------------
  339. HRESULT
  340. CInfoBase::Load(
  341. IN HKEY hkey,
  342. IN LPCTSTR pszSubKey,
  343. IN LPCTSTR pszValue
  344. ) {
  345. PBYTE pBase = NULL;
  346. DWORD dwErr, dwSize, dwType;
  347. RegKey regsubkey; // hold subkey that has to be freed
  348. RegKey regkey; // holds key, must NOT be closed
  349. HRESULT hr = hrOK;
  350. if (pszSubKey && StrLen(pszSubKey))
  351. {
  352. HKEY hkTemp = hkey;
  353. dwErr = regsubkey.Open(hkTemp, pszSubKey, KEY_READ);
  354. if (dwErr != ERROR_SUCCESS)
  355. return HRESULT_FROM_WIN32(dwErr);
  356. // We use this as THE key. However, since this key is attached
  357. // to a RegKey, it will get cleaned up on exit/thrown exception.
  358. hkey = (HKEY) regsubkey;
  359. }
  360. COM_PROTECT_TRY
  361. {
  362. do {
  363. // This regkey is used to utilize the class. Do NOT
  364. // close this regkey (it may be the key that was passed into us).
  365. regkey.Attach(hkey);
  366. // query the value specified for its size and type
  367. dwSize = 0;
  368. dwType = 0;
  369. dwErr = regkey.QueryTypeAndSize(pszValue, &dwType, &dwSize);
  370. if (dwErr != ERROR_SUCCESS)
  371. break;
  372. //$ Review: kennt, if the key is not the correct type
  373. // what error code do we want to return?
  374. if (dwErr != ERROR_SUCCESS || dwType != REG_BINARY)
  375. break;
  376. pBase = new BYTE[dwSize];
  377. Assert(pBase);
  378. // get the actual data
  379. dwErr = regkey.QueryValue(pszValue, (LPVOID) pBase, dwSize);
  380. if (dwErr != ERROR_SUCCESS)
  381. break;
  382. // convert the infobase into a list of blocks
  383. dwErr = ArrayToBlockList(pBase, dwSize);
  384. } while(FALSE);
  385. hr = HRESULT_FROM_WIN32(dwErr);
  386. }
  387. COM_PROTECT_CATCH;
  388. // free the memory allocated for the block
  389. delete [] pBase;
  390. // we do NOT want this key closed
  391. regkey.Detach();
  392. return hr;
  393. }
  394. //---------------------------------------------------------------------------
  395. // Function: CInfoBase::Unload
  396. //
  397. // frees resources used by infoblocks.
  398. //---------------------------------------------------------------------------
  399. HRESULT
  400. CInfoBase::Unload(
  401. ) {
  402. //
  403. // go through the list of blocks, deleting each one
  404. //
  405. while (!m_lBlocks.IsEmpty()) {
  406. InfoBlock *pBlock = (InfoBlock *)m_lBlocks.RemoveHead();
  407. if (pBlock->pData) { delete [] pBlock->pData; }
  408. delete pBlock;
  409. }
  410. //
  411. // if we have a copy of the opaque data, free that too
  412. //
  413. if (m_pBase) { delete [] m_pBase; m_pBase = NULL; m_dwSize = 0; }
  414. return HRESULT_FROM_WIN32(NO_ERROR);
  415. }
  416. //---------------------------------------------------------------------------
  417. // Function: CInfoBase::Save
  418. //
  419. // Saves the list of blocks as an infobase in the registry.
  420. //---------------------------------------------------------------------------
  421. HRESULT
  422. CInfoBase::Save(
  423. IN HKEY hkey,
  424. IN LPCTSTR pszSubKey,
  425. IN LPCTSTR pszValue
  426. ) {
  427. PBYTE pBase = NULL;
  428. DWORD dwErr, dwSize;
  429. RegKey regsubkey; // hold subkey that has to be freed
  430. RegKey regkey; // holds key, must NOT be closed
  431. HRESULT hr = hrOK;
  432. // create/open the key specified
  433. if (pszSubKey && lstrlen(pszSubKey))
  434. {
  435. dwErr = regsubkey.Create(hkey, pszSubKey,
  436. REG_OPTION_NON_VOLATILE, KEY_WRITE);
  437. if (dwErr != ERROR_SUCCESS)
  438. return HRESULT_FROM_WIN32(dwErr);
  439. // This subkey will get closed by the regsubkey destructor
  440. hkey = (HKEY) regsubkey;
  441. }
  442. COM_PROTECT_TRY
  443. {
  444. do {
  445. regkey.Attach(hkey);
  446. // convert our list of blocks into one block of data
  447. dwErr = BlockListToArray(pBase, dwSize);
  448. if (dwErr != NO_ERROR) { pBase = NULL; break; }
  449. if (!pBase || !dwSize) { break; }
  450. // attempt to set the value
  451. dwErr = regkey.SetValue(pszValue, (LPVOID) pBase, dwSize);
  452. if (dwErr != ERROR_SUCCESS) { break; }
  453. } while(FALSE);
  454. hr = HRESULT_FROM_WIN32(dwErr);
  455. }
  456. COM_PROTECT_CATCH;
  457. regkey.Detach();
  458. delete [] pBase;
  459. return hr;
  460. }
  461. //---------------------------------------------------------------------------
  462. // Function: CInfoBase::GetBlock
  463. //
  464. // Retrieves a block of data of the specified type
  465. // from the currently loaded infobase.
  466. //---------------------------------------------------------------------------
  467. HRESULT
  468. CInfoBase::GetBlock(
  469. IN DWORD dwType,
  470. OUT InfoBlock*& pBlock,
  471. IN DWORD dwNth
  472. ) {
  473. POSITION pos;
  474. InfoBlock *pib;
  475. // start at the head of the list, and look for the block requested
  476. pos = m_lBlocks.GetHeadPosition();
  477. while (pos)
  478. {
  479. // retrieve the next block
  480. pib = (InfoBlock *)m_lBlocks.GetNext(pos);
  481. if (pib->dwType != dwType) { continue; }
  482. if (dwNth-- != 0) { continue; }
  483. // this is the block requested
  484. pBlock = pib;
  485. return HRESULT_FROM_WIN32(NO_ERROR);
  486. }
  487. pBlock = NULL;
  488. return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  489. }
  490. //---------------------------------------------------------------------------
  491. // Function: CInfoBase::SetBlock
  492. //
  493. // Sets a block of data of the specified type to a copy of the given data
  494. // in the currently loaded infobase.
  495. //---------------------------------------------------------------------------
  496. HRESULT
  497. CInfoBase::SetBlock(
  498. IN DWORD dwType,
  499. IN InfoBlock* pBlock,
  500. IN DWORD dwNth
  501. ) {
  502. DWORD dwErr;
  503. HRESULT hr;
  504. PBYTE pData;
  505. InfoBlock *pib;
  506. // retrieve the block to be modified
  507. hr = GetBlock(dwType, pib, dwNth);
  508. if (!FHrSucceeded(hr))
  509. return hr;
  510. // modify the contents
  511. if (pBlock->dwSize == 0) { pData = NULL; }
  512. else
  513. {
  514. // allocate space for the new data
  515. pData = new BYTE[pBlock->dwSize * pBlock->dwCount];
  516. Assert(pData);
  517. ::CopyMemory(pData, pBlock->pData, pBlock->dwSize * pBlock->dwCount);
  518. }
  519. // if any space was allocated before, free it now
  520. if (pib->pData) { delete [] pib->pData; }
  521. // set the blocks new contents
  522. *pib = *pBlock;
  523. pib->pData = pData;
  524. return HRESULT_FROM_WIN32(NO_ERROR);
  525. }
  526. //--------------------------------------------------------------------
  527. // Function: GetData
  528. //
  529. // Retrieves the data for the 'dwNth' block of type 'dwType'.
  530. //--------------------------------------------------------------------
  531. PBYTE
  532. CInfoBase::GetData(
  533. IN DWORD dwType,
  534. IN DWORD dwNth
  535. ) {
  536. InfoBlock* pblock;
  537. if (!FHrSucceeded(GetBlock(dwType, pblock, dwNth)))
  538. return NULL;
  539. return pblock->pData;
  540. }
  541. //---------------------------------------------------------------------------
  542. // Function: CInfoBase::SetData
  543. //
  544. // Sets the data for an existing block.
  545. //---------------------------------------------------------------------------
  546. HRESULT
  547. CInfoBase::SetData(
  548. IN DWORD dwType,
  549. IN DWORD dwSize,
  550. IN PBYTE pData,
  551. IN DWORD dwCount,
  552. IN DWORD dwNth
  553. ) {
  554. DWORD dwErr;
  555. InfoBlock *pib;
  556. HRESULT hr;
  557. //
  558. // retrieve the block to be modified
  559. //
  560. hr = GetBlock(dwType, pib, dwNth);
  561. if (!FHrSucceeded(hr)) { return hr; }
  562. //
  563. // modify the data
  564. //
  565. if (pib->pData) { delete [] pib->pData; }
  566. pib->dwSize = dwSize;
  567. pib->dwCount = dwCount;
  568. pib->pData = pData;
  569. return HRESULT_FROM_WIN32(NO_ERROR);
  570. }
  571. //---------------------------------------------------------------------------
  572. // Function: CInfoBase::AddBlock
  573. //
  574. // Adds a block with the given values to the end of the block list.
  575. //---------------------------------------------------------------------------
  576. HRESULT
  577. CInfoBase::AddBlock(
  578. IN DWORD dwType,
  579. IN DWORD dwSize,
  580. IN PBYTE pData,
  581. IN DWORD dwCount,
  582. IN BOOL bRemoveFirst
  583. ) {
  584. InfoBlock *pBlock = NULL;
  585. HRESULT hr = hrOK;
  586. if (bRemoveFirst) { RemoveBlock(dwType); }
  587. COM_PROTECT_TRY
  588. {
  589. // allocate space for the block
  590. pBlock = new InfoBlock;
  591. Assert(pBlock);
  592. // initialize member fields with values passed in
  593. pBlock->dwType = dwType;
  594. pBlock->dwSize = dwSize;
  595. pBlock->dwCount = dwCount;
  596. // initialize the data field, copying the data passed in
  597. if (dwSize == 0 || dwCount == 0)
  598. pBlock->pData = NULL;
  599. else
  600. {
  601. pBlock->pData = NULL;
  602. pBlock->pData = new BYTE[dwSize * dwCount];
  603. Assert(pBlock->pData);
  604. ::CopyMemory(pBlock->pData, pData, dwSize * dwCount);
  605. }
  606. // add the new block to the end of the list
  607. m_lBlocks.AddTail(pBlock);
  608. }
  609. COM_PROTECT_CATCH;
  610. if (!FHrSucceeded(hr))
  611. {
  612. if (pBlock)
  613. delete pBlock->pData;
  614. delete pBlock;
  615. }
  616. return hr;
  617. }
  618. //---------------------------------------------------------------------------
  619. // Function: CInfoBase::RemoveBlock
  620. //
  621. // Removes a block of the gievn type from the list
  622. //---------------------------------------------------------------------------
  623. HRESULT
  624. CInfoBase::RemoveBlock(
  625. IN DWORD dwType,
  626. IN DWORD dwNth
  627. ) {
  628. POSITION pos;
  629. InfoBlock *pBlock;
  630. //
  631. // find the block
  632. //
  633. pos = m_lBlocks.GetHeadPosition();
  634. while (pos) {
  635. POSITION postemp = pos;
  636. pBlock = (InfoBlock *)m_lBlocks.GetNext(pos);
  637. if (pBlock->dwType != dwType) { continue; }
  638. if (dwNth-- != 0) { continue; }
  639. //
  640. // this is the block, remove it from the list
  641. //
  642. m_lBlocks.RemoveAt(postemp);
  643. //
  644. // free the block's memory as well
  645. //
  646. if (pBlock->pData) { delete [] pBlock->pData; }
  647. delete pBlock;
  648. return HRESULT_FROM_WIN32(NO_ERROR);
  649. }
  650. //
  651. // the block wasn't found
  652. //
  653. return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  654. }
  655. HRESULT CInfoBase::GetInfo(DWORD *pdwSize, int *pcBlocks)
  656. {
  657. if (pdwSize)
  658. *pdwSize = m_dwSize;
  659. if (pcBlocks)
  660. *pcBlocks = (int) m_lBlocks.GetCount();
  661. return hrOK;
  662. }
  663. //---------------------------------------------------------------------------
  664. // Function: CInfoBase::BlockListToArray
  665. //
  666. // Converts a list of blocks into an array.
  667. //---------------------------------------------------------------------------
  668. HRESULT
  669. CInfoBase::BlockListToArray(
  670. OUT PBYTE& pBase,
  671. OUT DWORD& dwSize
  672. ) {
  673. PBYTE pdata;
  674. DWORD dwCount;
  675. POSITION pos;
  676. RTR_INFO_BLOCK_HEADER *prtrbase;
  677. RTR_TOC_ENTRY *prtrblock;
  678. InfoBlock *pblock;
  679. HRESULT hr = hrOK;
  680. COM_PROTECT_TRY
  681. {
  682. // Compute the total size occupied by the infobase's blocks
  683. // base structure
  684. dwCount = 0;
  685. dwSize = FIELD_OFFSET(RTR_INFO_BLOCK_HEADER, TocEntry);
  686. // Table Of Contents Entries
  687. pos = m_lBlocks.GetHeadPosition();
  688. while (pos) {
  689. pblock = (InfoBlock *)m_lBlocks.GetNext(pos);
  690. dwSize += sizeof(RTR_TOC_ENTRY);
  691. ++dwCount;
  692. }
  693. // information blocks
  694. pos = m_lBlocks.GetHeadPosition();
  695. while (pos) {
  696. pblock = (InfoBlock *)m_lBlocks.GetNext(pos);
  697. dwSize += ALIGN_SHIFT;
  698. dwSize &= ALIGN_MASK;
  699. dwSize += pblock->dwSize * pblock->dwCount;
  700. }
  701. //
  702. // Allocate enough memory to hold the converted infobase
  703. //
  704. pBase = new BYTE[dwSize];
  705. Assert(pBase);
  706. ZeroMemory(pBase, dwSize);
  707. //
  708. // Initialize the header
  709. //
  710. prtrbase = (RTR_INFO_BLOCK_HEADER *)pBase;
  711. prtrbase->Size = dwSize;
  712. prtrbase->Version = RTR_INFO_BLOCK_VERSION;
  713. prtrbase->TocEntriesCount = dwCount;
  714. //
  715. // Now walk the list again, this time copying blocks over
  716. // along with their data
  717. //
  718. prtrblock = prtrbase->TocEntry;
  719. pdata = pBase + FIELD_OFFSET(RTR_INFO_BLOCK_HEADER, TocEntry) +
  720. dwCount * sizeof(RTR_TOC_ENTRY);
  721. pos = m_lBlocks.GetHeadPosition();
  722. while (pos) {
  723. pdata += ALIGN_SHIFT;
  724. pdata = (PBYTE)((LONG_PTR)pdata & ALIGN_MASK);
  725. pblock = (InfoBlock *)m_lBlocks.GetNext(pos);
  726. prtrblock->InfoType = pblock->dwType;
  727. prtrblock->Count = pblock->dwCount;
  728. prtrblock->InfoSize = pblock->dwSize;
  729. prtrblock->Offset = (ULONG)(pdata - pBase);
  730. if (pblock->pData) {
  731. ::CopyMemory(pdata, pblock->pData, pblock->dwSize * pblock->dwCount);
  732. }
  733. pdata += pblock->dwSize * pblock->dwCount;
  734. ++prtrblock;
  735. }
  736. }
  737. COM_PROTECT_CATCH;
  738. return hr;
  739. }
  740. //---------------------------------------------------------------------------
  741. // Function: CInfoBase::ArrayToBlockList
  742. //
  743. // This functions converts an array to a list of InfoBlock structures.
  744. //---------------------------------------------------------------------------
  745. HRESULT
  746. CInfoBase::ArrayToBlockList(
  747. IN PBYTE pBase,
  748. IN DWORD dwSize
  749. ) {
  750. PBYTE pdata;
  751. DWORD dwCount, dwErr;
  752. RTR_TOC_ENTRY *prtrblock;
  753. RTR_INFO_BLOCK_HEADER *prtrbase;
  754. HRESULT hr = hrOK;
  755. if (!pBase) { return HRESULT_FROM_WIN32(NO_ERROR); }
  756. //
  757. // Walk the infobase converting each block to an InfoBlock
  758. //
  759. prtrbase = (RTR_INFO_BLOCK_HEADER *)pBase;
  760. dwCount = prtrbase->TocEntriesCount;
  761. prtrblock = prtrbase->TocEntry;
  762. for ( ; dwCount > 0; dwCount--) {
  763. //
  764. // Get the next entry in the array
  765. //
  766. pdata = pBase + prtrblock->Offset;
  767. //
  768. // Add the array-entry to the list of blocks
  769. //
  770. hr = AddBlock(
  771. prtrblock->InfoType, prtrblock->InfoSize,
  772. pdata, prtrblock->Count
  773. );
  774. if (!FHrSucceeded(hr))
  775. {
  776. Unload();
  777. return hr;
  778. }
  779. ++prtrblock;
  780. }
  781. return HRESULT_FROM_WIN32(NO_ERROR);
  782. }
  783. //---------------------------------------------------------------------------
  784. //---------------------------------------------------------------------------
  785. //---------------------------------------------------------------------------
  786. //
  787. // This section is for the actual implementation of the various
  788. // COM objects, which wrap the previous C++ implementation.
  789. //
  790. //---------------------------------------------------------------------------
  791. //---------------------------------------------------------------------------
  792. //---------------------------------------------------------------------------
  793. /*---------------------------------------------------------------------------
  794. Class: InfoBase
  795. This is an interface wrapper around the CInfoBase class.
  796. ---------------------------------------------------------------------------*/
  797. class InfoBase :
  798. public IInfoBase
  799. {
  800. public:
  801. DeclareIUnknownMembers(IMPL)
  802. DeclareIInfoBaseMembers(IMPL)
  803. InfoBase();
  804. ~InfoBase();
  805. protected:
  806. CInfoBase m_cinfobase;
  807. LONG m_cRef;
  808. };
  809. /*---------------------------------------------------------------------------
  810. Class: InfoBlockEnumerator
  811. ---------------------------------------------------------------------------*/
  812. class InfoBlockEnumerator :
  813. public IEnumInfoBlock
  814. {
  815. public:
  816. DeclareIUnknownMembers(IMPL)
  817. DeclareIEnumInfoBlockMembers(IMPL)
  818. InfoBlockEnumerator(IInfoBase *pInfoBase, CPtrList* pPtrList);
  819. ~InfoBlockEnumerator();
  820. protected:
  821. SPIInfoBase m_spInfoBase;
  822. CPtrList * m_pPtrList;
  823. POSITION m_pos;
  824. LONG m_cRef;
  825. };
  826. /*---------------------------------------------------------------------------
  827. InfoBase implementation
  828. ---------------------------------------------------------------------------*/
  829. DEBUG_DECLARE_INSTANCE_COUNTER(InfoBase)
  830. InfoBase::InfoBase()
  831. : m_cRef(1)
  832. {
  833. DEBUG_INCREMENT_INSTANCE_COUNTER(InfoBase);
  834. }
  835. InfoBase::~InfoBase()
  836. {
  837. Unload();
  838. DEBUG_DECREMENT_INSTANCE_COUNTER(InfoBase);
  839. }
  840. IMPLEMENT_ADDREF_RELEASE(InfoBase);
  841. HRESULT InfoBase::QueryInterface(REFIID riid, LPVOID *ppv)
  842. {
  843. // Is the pointer bad?
  844. if (ppv == NULL)
  845. return E_INVALIDARG;
  846. // Place NULL in *ppv in case of failure
  847. *ppv = NULL;
  848. // This is the non-delegating IUnknown implementation
  849. if (riid == IID_IUnknown)
  850. *ppv = (LPVOID) this;
  851. else if (riid == IID_IInfoBase)
  852. *ppv = (IInfoBase *) this;
  853. // If we're going to return an interface, AddRef it first
  854. if (*ppv)
  855. {
  856. ((LPUNKNOWN) *ppv)->AddRef();
  857. return hrOK;
  858. }
  859. else
  860. return E_NOINTERFACE;
  861. }
  862. /*!--------------------------------------------------------------------------
  863. InfoBase::Load
  864. Implementation of IInfoBase::Load
  865. Author: KennT
  866. ---------------------------------------------------------------------------*/
  867. STDMETHODIMP InfoBase::Load(HKEY hKey,
  868. LPCOLESTR pszKey,
  869. LPCOLESTR pszValue)
  870. {
  871. HRESULT hr;
  872. COM_PROTECT_TRY
  873. {
  874. hr = m_cinfobase.Load(hKey, OLE2CT(pszKey), OLE2CT(pszValue));
  875. }
  876. COM_PROTECT_CATCH;
  877. return hr;
  878. }
  879. /*!--------------------------------------------------------------------------
  880. InfoBase::Save
  881. Implementation of IInfoBase::Save
  882. Author: KennT
  883. ---------------------------------------------------------------------------*/
  884. STDMETHODIMP InfoBase::Save(HKEY hKey,
  885. LPCOLESTR pszKey,
  886. LPCOLESTR pszValue)
  887. {
  888. HRESULT hr = hrOK;
  889. COM_PROTECT_TRY
  890. {
  891. hr = m_cinfobase.Save(hKey, OLE2CT(pszKey), OLE2CT(pszValue));
  892. }
  893. COM_PROTECT_CATCH;
  894. return hr;
  895. }
  896. /*!--------------------------------------------------------------------------
  897. InfoBase::Unload
  898. Implementation of IInfoBase::Unload
  899. Author: KennT
  900. ---------------------------------------------------------------------------*/
  901. STDMETHODIMP InfoBase::Unload()
  902. {
  903. HRESULT hr = hrOK;
  904. COM_PROTECT_TRY
  905. {
  906. hr = m_cinfobase.Unload();
  907. }
  908. COM_PROTECT_CATCH;
  909. return hr;
  910. }
  911. /*!--------------------------------------------------------------------------
  912. InfoBase::CopyFrom
  913. Implementation of IInfoBase::CopyFrom
  914. Author: KennT
  915. ---------------------------------------------------------------------------*/
  916. STDMETHODIMP InfoBase::CopyFrom(IInfoBase * pSrc)
  917. {
  918. HRESULT hr = hrOK;
  919. COM_PROTECT_TRY
  920. {
  921. hr = m_cinfobase.CopyFrom(pSrc);
  922. }
  923. COM_PROTECT_CATCH;
  924. return hr;
  925. }
  926. /*!--------------------------------------------------------------------------
  927. InfoBase::LoadFrom
  928. Implementation of IInfoBase::LoadFrom
  929. Author: KennT
  930. ---------------------------------------------------------------------------*/
  931. STDMETHODIMP InfoBase::LoadFrom(DWORD dwSize, PBYTE pBase)
  932. {
  933. HRESULT hr = hrOK;
  934. COM_PROTECT_TRY
  935. {
  936. hr = m_cinfobase.LoadFrom(pBase, dwSize);
  937. }
  938. COM_PROTECT_CATCH;
  939. return hr;
  940. }
  941. /*!--------------------------------------------------------------------------
  942. InfoBase::WriteTo
  943. Implementation of IInfoBase::WriteTo
  944. Author: KennT
  945. ---------------------------------------------------------------------------*/
  946. STDMETHODIMP InfoBase::WriteTo(PBYTE *ppBase,
  947. DWORD *pdwSize)
  948. {
  949. HRESULT hr = hrOK;
  950. PBYTE pBaseT = NULL;
  951. DWORD dwSizeT;
  952. Assert(ppBase);
  953. Assert(pdwSize);
  954. COM_PROTECT_TRY
  955. {
  956. hr = m_cinfobase.WriteTo(pBaseT, dwSizeT);
  957. if (FHrSucceeded(hr))
  958. {
  959. *ppBase = (PBYTE) CoTaskMemAlloc(dwSizeT);
  960. if (*ppBase == NULL)
  961. hr = E_OUTOFMEMORY;
  962. else
  963. {
  964. ::CopyMemory(*ppBase, pBaseT, dwSizeT);
  965. *pdwSize = dwSizeT;
  966. delete pBaseT;
  967. }
  968. }
  969. }
  970. COM_PROTECT_CATCH;
  971. return hr;
  972. }
  973. /*!--------------------------------------------------------------------------
  974. InfoBase::GetBlock
  975. Implementation of IInfoBase::GetBlock
  976. Author: KennT
  977. ---------------------------------------------------------------------------*/
  978. STDMETHODIMP InfoBase::GetBlock(DWORD dwType,
  979. InfoBlock **ppBlock,
  980. DWORD dwNth)
  981. {
  982. HRESULT hr = hrOK;
  983. Assert(ppBlock);
  984. COM_PROTECT_TRY
  985. {
  986. hr = m_cinfobase.GetBlock(dwType, *ppBlock, dwNth);
  987. }
  988. COM_PROTECT_CATCH;
  989. return hr;
  990. }
  991. /*!--------------------------------------------------------------------------
  992. InfoBase::SetBlock
  993. Implementation of IInfoBase::SetBlock
  994. Author: KennT
  995. ---------------------------------------------------------------------------*/
  996. STDMETHODIMP InfoBase::SetBlock(DWORD dwType,
  997. InfoBlock *pBlock,
  998. DWORD dwNth)
  999. {
  1000. HRESULT hr = hrOK;
  1001. COM_PROTECT_TRY
  1002. {
  1003. hr = m_cinfobase.SetBlock(dwType, pBlock, dwNth);
  1004. }
  1005. COM_PROTECT_CATCH;
  1006. return hr;
  1007. }
  1008. /*!--------------------------------------------------------------------------
  1009. InfoBase::AddBlock
  1010. Implementation of IInfoBase::AddBlock
  1011. Author: KennT
  1012. ---------------------------------------------------------------------------*/
  1013. STDMETHODIMP InfoBase::AddBlock(DWORD dwType,
  1014. DWORD dwSize,
  1015. PBYTE pData,
  1016. DWORD dwCount,
  1017. BOOL bRemoveFirst)
  1018. {
  1019. HRESULT hr = hrOK;
  1020. COM_PROTECT_TRY
  1021. {
  1022. hr = m_cinfobase.AddBlock(dwType, dwSize, pData, dwCount, bRemoveFirst);
  1023. }
  1024. COM_PROTECT_CATCH;
  1025. return hr;
  1026. }
  1027. /*!--------------------------------------------------------------------------
  1028. InfoBase::GetData
  1029. Implementation of IInfoBase::GetData
  1030. Author: KennT
  1031. ---------------------------------------------------------------------------*/
  1032. STDMETHODIMP InfoBase::GetData(DWORD dwType,
  1033. DWORD dwNth,
  1034. PBYTE * ppData)
  1035. {
  1036. HRESULT hr = hrOK;
  1037. PBYTE pb = NULL;
  1038. Assert(ppData);
  1039. COM_PROTECT_TRY
  1040. {
  1041. pb = m_cinfobase.GetData(dwType, dwNth);
  1042. *ppData = pb;
  1043. }
  1044. COM_PROTECT_CATCH;
  1045. return *ppData ? hr : E_INVALIDARG;
  1046. }
  1047. /*!--------------------------------------------------------------------------
  1048. InfoBase::SetData
  1049. Implementation of IInfoBase::SetData
  1050. Author: KennT
  1051. ---------------------------------------------------------------------------*/
  1052. STDMETHODIMP InfoBase::SetData(DWORD dwType,
  1053. DWORD dwSize,
  1054. PBYTE pData,
  1055. DWORD dwCount,
  1056. DWORD dwNth)
  1057. {
  1058. HRESULT hr = hrOK;
  1059. COM_PROTECT_TRY
  1060. {
  1061. hr = m_cinfobase.SetData(dwType, dwSize, pData, dwCount, dwNth);
  1062. }
  1063. COM_PROTECT_CATCH;
  1064. return hr;
  1065. }
  1066. /*!--------------------------------------------------------------------------
  1067. InfoBase::RemoveBlock
  1068. Implementation of IInfoBase::RemoveBlock
  1069. Author: KennT
  1070. ---------------------------------------------------------------------------*/
  1071. STDMETHODIMP InfoBase::RemoveBlock(DWORD dwType,
  1072. DWORD dwNth)
  1073. {
  1074. HRESULT hr = hrOK;
  1075. COM_PROTECT_TRY
  1076. {
  1077. hr = m_cinfobase.RemoveBlock(dwType, dwNth);
  1078. }
  1079. COM_PROTECT_CATCH;
  1080. return hr;
  1081. }
  1082. /*!--------------------------------------------------------------------------
  1083. InfoBase::BlockExists
  1084. Implementation of IInfoBase::BlockExists
  1085. Author: KennT
  1086. ---------------------------------------------------------------------------*/
  1087. STDMETHODIMP InfoBase::BlockExists(DWORD dwType )
  1088. {
  1089. HRESULT hr = hrOK;
  1090. COM_PROTECT_TRY
  1091. {
  1092. hr = m_cinfobase.BlockExists(dwType) ? hrOK : hrFalse;
  1093. }
  1094. COM_PROTECT_CATCH;
  1095. return hr;
  1096. }
  1097. /*!--------------------------------------------------------------------------
  1098. InfoBase::ProtocolExists
  1099. Implementation of IInfoBase::ProtocolExists
  1100. Author: KennT
  1101. ---------------------------------------------------------------------------*/
  1102. STDMETHODIMP InfoBase::ProtocolExists(DWORD dwProtocol )
  1103. {
  1104. HRESULT hr = hrOK;
  1105. BOOL bResult;
  1106. COM_PROTECT_TRY
  1107. {
  1108. bResult = m_cinfobase.ProtocolExists(dwProtocol);
  1109. hr = (bResult ? S_OK : S_FALSE);
  1110. }
  1111. COM_PROTECT_CATCH;
  1112. return hr;
  1113. }
  1114. /*!--------------------------------------------------------------------------
  1115. InfoBase::RemoveAllBlocks
  1116. Implementation of IInfoBase::RemoveAllBlocks
  1117. Author: KennT
  1118. ---------------------------------------------------------------------------*/
  1119. STDMETHODIMP InfoBase::RemoveAllBlocks()
  1120. {
  1121. HRESULT hr = hrOK;
  1122. COM_PROTECT_TRY
  1123. {
  1124. hr = m_cinfobase.RemoveAllBlocks();
  1125. }
  1126. COM_PROTECT_CATCH;
  1127. return hr;
  1128. }
  1129. /*!--------------------------------------------------------------------------
  1130. InfoBase::QueryBlockList
  1131. Implementation of IInfoBase::QueryBlockList
  1132. Author: KennT
  1133. ---------------------------------------------------------------------------*/
  1134. STDMETHODIMP InfoBase::QueryBlockList(IEnumInfoBlock **ppBlockEnum)
  1135. {
  1136. HRESULT hr = hrOK;
  1137. InfoBlockEnumerator *pIBEnum = NULL;
  1138. COM_PROTECT_TRY
  1139. {
  1140. pIBEnum = new InfoBlockEnumerator(this, &m_cinfobase.QueryBlockList());
  1141. Assert(pIBEnum);
  1142. }
  1143. COM_PROTECT_CATCH;
  1144. *ppBlockEnum = static_cast<IEnumInfoBlock *>(pIBEnum);
  1145. return hr;
  1146. }
  1147. STDMETHODIMP InfoBase::GetInfo(DWORD *pdwSize, int *pcBlocks)
  1148. {
  1149. return m_cinfobase.GetInfo(pdwSize, pcBlocks);
  1150. return hrOK;
  1151. }
  1152. /*!--------------------------------------------------------------------------
  1153. CreateInfoBase
  1154. Creates an IInfoBase object.
  1155. Author: KennT
  1156. ---------------------------------------------------------------------------*/
  1157. TFSCORE_API(HRESULT) CreateInfoBase(IInfoBase **ppInfoBase)
  1158. {
  1159. HRESULT hr = hrOK;
  1160. InfoBase * pinfobase = NULL;
  1161. Assert(ppInfoBase);
  1162. COM_PROTECT_TRY
  1163. {
  1164. pinfobase = new InfoBase;
  1165. *ppInfoBase = static_cast<IInfoBase *>(pinfobase);
  1166. }
  1167. COM_PROTECT_CATCH;
  1168. return hr;
  1169. }
  1170. /*---------------------------------------------------------------------------
  1171. InfoBlockEnumerator implementation
  1172. ---------------------------------------------------------------------------*/
  1173. DEBUG_DECLARE_INSTANCE_COUNTER(InfoBlockEnumerator);
  1174. InfoBlockEnumerator::InfoBlockEnumerator(IInfoBase *pInfoBase, CPtrList *pPtrList)
  1175. : m_cRef(1)
  1176. {
  1177. m_spInfoBase.Set(pInfoBase);
  1178. m_pPtrList = pPtrList;
  1179. DEBUG_INCREMENT_INSTANCE_COUNTER(InfoBlockEnumerator);
  1180. }
  1181. InfoBlockEnumerator::~InfoBlockEnumerator()
  1182. {
  1183. DEBUG_DECREMENT_INSTANCE_COUNTER(InfoBlockEnumerator);
  1184. }
  1185. IMPLEMENT_ADDREF_RELEASE(InfoBlockEnumerator);
  1186. HRESULT InfoBlockEnumerator::QueryInterface(REFIID riid, LPVOID *ppv)
  1187. {
  1188. // Is the pointer bad?
  1189. if (ppv == NULL)
  1190. return E_INVALIDARG;
  1191. // Place NULL in *ppv in case of failure
  1192. *ppv = NULL;
  1193. // This is the non-delegating IUnknown implementation
  1194. if (riid == IID_IUnknown)
  1195. *ppv = (LPVOID) this;
  1196. else if (riid == IID_IEnumInfoBlock)
  1197. *ppv = (IEnumInfoBlock *) this;
  1198. // If we're going to return an interface, AddRef it first
  1199. if (*ppv)
  1200. {
  1201. ((LPUNKNOWN) *ppv)->AddRef();
  1202. return hrOK;
  1203. }
  1204. else
  1205. return E_NOINTERFACE;
  1206. }
  1207. /*!--------------------------------------------------------------------------
  1208. InfoBlockEnumerator::Next
  1209. Implementation of IEnumInfoBlock::Next
  1210. Author: KennT
  1211. ---------------------------------------------------------------------------*/
  1212. STDMETHODIMP InfoBlockEnumerator::Next(ULONG uNum, InfoBlock **ppBlock,
  1213. ULONG *pNumReturned)
  1214. {
  1215. Assert(uNum == 1);
  1216. Assert(m_pPtrList);
  1217. Assert(ppBlock);
  1218. if (ppBlock)
  1219. *ppBlock = NULL;
  1220. if (!m_pos)
  1221. {
  1222. if (pNumReturned)
  1223. *pNumReturned = 0;
  1224. return S_FALSE;
  1225. }
  1226. *ppBlock = (InfoBlock *) m_pPtrList->GetNext(m_pos);
  1227. if (pNumReturned)
  1228. *pNumReturned = 1;
  1229. return hrOK;
  1230. }
  1231. /*!--------------------------------------------------------------------------
  1232. InfoBlockEnumerator::Skip
  1233. Implementation of IEnumInfoBlock::Skip
  1234. Author: KennT
  1235. ---------------------------------------------------------------------------*/
  1236. STDMETHODIMP InfoBlockEnumerator::Skip(ULONG uNum)
  1237. {
  1238. Assert(uNum == 1);
  1239. Assert(m_pPtrList);
  1240. if (!m_pos)
  1241. return S_FALSE;
  1242. m_pPtrList->GetNext(m_pos);
  1243. return hrOK;
  1244. }
  1245. /*!--------------------------------------------------------------------------
  1246. InfoBlockEnumerator::Reset
  1247. Implementation of IEnumInfoBlock::Reset
  1248. Author: KennT
  1249. ---------------------------------------------------------------------------*/
  1250. STDMETHODIMP InfoBlockEnumerator::Reset()
  1251. {
  1252. Assert(m_pPtrList);
  1253. m_pos = m_pPtrList->GetHeadPosition();
  1254. return hrOK;
  1255. }
  1256. /*!--------------------------------------------------------------------------
  1257. InfoBlockEnumerator::Clone
  1258. Implementation of IEnumInfoBlock::Clone
  1259. Author: KennT
  1260. ---------------------------------------------------------------------------*/
  1261. STDMETHODIMP InfoBlockEnumerator::Clone(IEnumInfoBlock **ppBlockEnum)
  1262. {
  1263. return E_NOTIMPL;
  1264. }