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.

769 lines
17 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. mb.cxx
  5. Abstract:
  6. This module implements the MB class.
  7. Author:
  8. Keith Moore (keithmo) 05-Feb-1997
  9. Moved from "inlines" in MB.HXX.
  10. Revision History:
  11. --*/
  12. #include "imiscp.hxx"
  13. //
  14. // Default timeout
  15. //
  16. #define MB_TIMEOUT (30 * 1000)
  17. //
  18. // Default timeout for SaveData
  19. //
  20. #define MB_SAVE_TIMEOUT (10 * 1000) // milliseconds
  21. MB::MB( IMDCOM * pMBCom )
  22. : _pMBCom( pMBCom ),
  23. _hMB ( NULL )
  24. {
  25. DBG_ASSERT( _pMBCom );
  26. }
  27. MB::~MB( VOID )
  28. {
  29. Close();
  30. _pMBCom = NULL;
  31. }
  32. BOOL MB::EnumObjects( const CHAR * pszPath,
  33. CHAR * Name,
  34. DWORD Index )
  35. {
  36. HRESULT hRes = _pMBCom->ComMDEnumMetaObjects( _hMB,
  37. (BYTE *)pszPath,
  38. (BYTE *)Name,
  39. Index );
  40. if ( SUCCEEDED( hRes ))
  41. {
  42. return TRUE;
  43. }
  44. SetLastError( HRESULTTOWIN32( hRes ));
  45. return FALSE;
  46. }
  47. BOOL MB::AddObject( const CHAR * pszPath )
  48. {
  49. HRESULT hRes = _pMBCom->ComMDAddMetaObject( _hMB,
  50. (BYTE *)pszPath );
  51. if ( SUCCEEDED( hRes ))
  52. {
  53. return TRUE;
  54. }
  55. SetLastError( HRESULTTOWIN32( hRes ));
  56. return FALSE;
  57. }
  58. BOOL MB::DeleteObject( const CHAR * pszPath )
  59. {
  60. HRESULT hRes = _pMBCom->ComMDDeleteMetaObject( _hMB,
  61. (BYTE *)pszPath );
  62. if ( SUCCEEDED( hRes ))
  63. {
  64. return TRUE;
  65. }
  66. SetLastError( HRESULTTOWIN32( hRes ));
  67. return FALSE;
  68. }
  69. BOOL MB::ReleaseReferenceData( DWORD dwTag )
  70. {
  71. HRESULT hRes = _pMBCom->ComMDReleaseReferenceData( dwTag );
  72. if ( SUCCEEDED( hRes ))
  73. {
  74. return TRUE;
  75. }
  76. SetLastError( HRESULTTOWIN32( hRes ));
  77. return FALSE;
  78. }
  79. BOOL MB::Save( VOID )
  80. {
  81. HRESULT hRes;
  82. METADATA_HANDLE mdhRoot;
  83. //
  84. // First try to lock the tree
  85. //
  86. hRes = _pMBCom->ComMDOpenMetaObjectW(METADATA_MASTER_ROOT_HANDLE,
  87. NULL,
  88. METADATA_PERMISSION_READ,
  89. MB_SAVE_TIMEOUT,
  90. &mdhRoot);
  91. //
  92. // If failed, then someone has a write handle open,
  93. // and there might be an inconsistent data state, so don't save.
  94. //
  95. if (SUCCEEDED(hRes)) {
  96. //
  97. // call metadata com api
  98. //
  99. hRes = _pMBCom->ComMDSaveData(mdhRoot);
  100. _pMBCom->ComMDCloseMetaObject(mdhRoot);
  101. }
  102. if ( SUCCEEDED( hRes ))
  103. {
  104. return TRUE;
  105. }
  106. SetLastError( HRESULTTOWIN32( hRes ));
  107. return FALSE;
  108. }
  109. BOOL MB::GetSystemChangeNumber( DWORD *pdwChangeNumber )
  110. {
  111. HRESULT hRes = _pMBCom->ComMDGetSystemChangeNumber(pdwChangeNumber);
  112. if ( SUCCEEDED( hRes ))
  113. {
  114. return TRUE;
  115. }
  116. SetLastError( HRESULTTOWIN32( hRes ));
  117. return FALSE;
  118. }
  119. BOOL MB::DeleteData(const CHAR * pszPath,
  120. DWORD dwPropID,
  121. DWORD dwUserType,
  122. DWORD dwDataType )
  123. {
  124. HRESULT hRes = _pMBCom->ComMDDeleteMetaData( _hMB,
  125. (LPBYTE) pszPath,
  126. dwPropID,
  127. dwDataType );
  128. if ( SUCCEEDED( hRes ))
  129. {
  130. return TRUE;
  131. }
  132. SetLastError( HRESULTTOWIN32( hRes ));
  133. return(FALSE);
  134. }
  135. BOOL MB::Close( VOID )
  136. {
  137. if ( _hMB )
  138. {
  139. DBG_REQUIRE( SUCCEEDED(_pMBCom->ComMDCloseMetaObject( _hMB )) );
  140. _hMB = NULL;
  141. }
  142. return TRUE;
  143. }
  144. BOOL
  145. MB::Open(
  146. METADATA_HANDLE hOpenRoot,
  147. const CHAR * pszPath,
  148. DWORD dwFlags
  149. )
  150. /*++
  151. Routine Description:
  152. Opens the metabase
  153. Arguments:
  154. hOpenRoot - Relative root or METADATA_MASTER_ROOT_HANDLE
  155. pszPath - Path to open
  156. dwFlags - Open flags
  157. Return:
  158. TRUE if success, FALSE on error, (call GetLastError())
  159. --*/
  160. {
  161. HRESULT hRes;
  162. DBG_ASSERT(_hMB == NULL);
  163. hRes = _pMBCom->ComMDOpenMetaObject( hOpenRoot,
  164. (BYTE *) pszPath,
  165. dwFlags,
  166. MB_TIMEOUT,
  167. &_hMB );
  168. if ( SUCCEEDED( hRes ))
  169. {
  170. return TRUE;
  171. }
  172. DBGPRINTF(( DBG_CONTEXT,
  173. "[MB::Open] Failed to open %s, error %x (%d)\n",
  174. pszPath,
  175. hRes,
  176. HRESULTTOWIN32( hRes ) ));
  177. SetLastError( HRESULTTOWIN32( hRes ) );
  178. return FALSE;
  179. }
  180. BOOL
  181. MB::SetData(
  182. const CHAR * pszPath,
  183. DWORD dwPropID,
  184. DWORD dwUserType,
  185. DWORD dwDataType,
  186. VOID * pvData,
  187. DWORD cbData,
  188. DWORD dwFlags
  189. )
  190. /*++
  191. Routine Description:
  192. Sets a metadata property on an openned metabase
  193. Arguments:
  194. pszPath - Path to set data on
  195. dwPropID - Metabase property ID
  196. dwUserType - User type for this property
  197. dwDataType - Type of data being set (dword, string etc)
  198. pvData - Pointer to data
  199. cbData - Size of data
  200. dwFlags - Inheritance flags
  201. Return:
  202. TRUE if success, FALSE on error, (call GetLastError())
  203. --*/
  204. {
  205. METADATA_RECORD mdRecord;
  206. HRESULT hRes;
  207. DBG_ASSERT( _hMB );
  208. mdRecord.dwMDIdentifier = dwPropID;
  209. mdRecord.dwMDAttributes = dwFlags;
  210. mdRecord.dwMDUserType = dwUserType;
  211. mdRecord.dwMDDataType = dwDataType;
  212. mdRecord.dwMDDataLen = cbData;
  213. mdRecord.pbMDData = (PBYTE) pvData;
  214. hRes = _pMBCom->ComMDSetMetaData( _hMB,
  215. (LPBYTE) pszPath,
  216. &mdRecord );
  217. if ( SUCCEEDED( hRes ))
  218. {
  219. return TRUE;
  220. }
  221. DBGPRINTF(( DBG_CONTEXT,
  222. "[MB::SetData] Failed to open %s, error %x (%d)\n",
  223. pszPath,
  224. hRes,
  225. HRESULTTOWIN32( hRes ) ));
  226. SetLastError( HRESULTTOWIN32( hRes ) );
  227. return FALSE;
  228. }
  229. BOOL
  230. MB::GetData(
  231. const CHAR * pszPath,
  232. DWORD dwPropID,
  233. DWORD dwUserType,
  234. DWORD dwDataType,
  235. VOID * pvData,
  236. DWORD * pcbData,
  237. DWORD dwFlags
  238. )
  239. /*++
  240. Routine Description:
  241. Retrieves a metadata property on an openned metabase
  242. Arguments:
  243. pszPath - Path to set data on
  244. dwPropID - Metabase property ID
  245. dwUserType - User type for this property
  246. dwDataType - Type of data being set (dword, string etc)
  247. pvData - Pointer to data
  248. pcbData - Size of pvData, receives size of object
  249. dwFlags - Inheritance flags
  250. Return:
  251. TRUE if success, FALSE on error, (call GetLastError())
  252. --*/
  253. {
  254. DBG_ASSERT( _hMB );
  255. DBG_ASSERT(pcbData);
  256. METADATA_RECORD mdRecord;
  257. HRESULT hRes;
  258. DWORD dwRequiredLen = *pcbData;
  259. mdRecord.dwMDIdentifier = dwPropID;
  260. mdRecord.dwMDAttributes = dwFlags;
  261. mdRecord.dwMDUserType = dwUserType;
  262. mdRecord.dwMDDataType = dwDataType;
  263. mdRecord.dwMDDataLen = *pcbData;
  264. mdRecord.pbMDData = (PBYTE) pvData;
  265. hRes = _pMBCom->ComMDGetMetaData( _hMB,
  266. (LPBYTE) pszPath,
  267. &mdRecord,
  268. &dwRequiredLen );
  269. if ( SUCCEEDED( hRes ))
  270. {
  271. *pcbData = mdRecord.dwMDDataLen;
  272. return TRUE;
  273. }
  274. *pcbData = dwRequiredLen;
  275. #if 0
  276. DBGPRINTF(( DBG_CONTEXT,
  277. "[MB::GetData] Failed, PropID(%d), UserType(%d) Flags(%d) on %s, hRes = 0x%08x (%d)\n",
  278. dwPropID,
  279. dwUserType,
  280. dwFlags,
  281. pszPath,
  282. hRes,
  283. HRESULTTOWIN32( hRes ) ));
  284. #endif
  285. SetLastError( HRESULTTOWIN32( hRes ) );
  286. return FALSE;
  287. }
  288. BOOL
  289. MB::ReferenceData(
  290. const CHAR * pszPath,
  291. DWORD dwPropID,
  292. DWORD dwUserType,
  293. DWORD dwDataType,
  294. VOID * * ppvData,
  295. DWORD * pcbData,
  296. DWORD * pdwTag,
  297. DWORD dwFlags
  298. )
  299. /*++
  300. Routine Description:
  301. References a metadata property item
  302. Arguments:
  303. pszPath - Path to set data on
  304. dwPropID - Metabase property ID
  305. dwUserType - User type for this property
  306. dwDataType - Type of data being set (dword, string etc)
  307. ppvData - Receives pointer to referenced data
  308. pdwTag - Receives dword tag for releasing this reference
  309. dwFlags - flags (must have METADATA_REFERENCE)
  310. Return:
  311. TRUE if success, FALSE on error, (call GetLastError())
  312. --*/
  313. {
  314. METADATA_RECORD mdRecord;
  315. HRESULT hRes;
  316. DWORD dwRequiredLen;
  317. DBG_ASSERT( _hMB );
  318. mdRecord.dwMDIdentifier = dwPropID;
  319. mdRecord.dwMDAttributes = dwFlags;
  320. mdRecord.dwMDUserType = dwUserType;
  321. mdRecord.dwMDDataType = dwDataType;
  322. mdRecord.dwMDDataLen = 0;
  323. mdRecord.pbMDData = NULL;
  324. hRes = _pMBCom->ComMDGetMetaData( _hMB,
  325. (LPBYTE) pszPath,
  326. &mdRecord,
  327. &dwRequiredLen );
  328. if ( SUCCEEDED( hRes ))
  329. {
  330. *ppvData = mdRecord.pbMDData;
  331. *pcbData = mdRecord.dwMDDataLen;
  332. *pdwTag = mdRecord.dwMDDataTag;
  333. return TRUE;
  334. }
  335. SetLastError( HRESULTTOWIN32( hRes ) );
  336. return FALSE;
  337. }
  338. BOOL MB::GetAll(
  339. const CHAR * pszPath,
  340. DWORD dwFlags,
  341. DWORD dwUserType,
  342. BUFFER * pBuff,
  343. DWORD * pcRecords,
  344. DWORD * pdwDataSetNumber
  345. )
  346. /*++
  347. Routine Description:
  348. Retrieves all the metabase properties on this path of the request type
  349. Arguments:
  350. pszPath - Path to set data on
  351. dwFlags - Inerhitance flags
  352. dwPropID - Metabase property ID
  353. dwUserType - User type for this property
  354. dwDataType - Type of data being set (dword, string etc)
  355. pvData - Pointer to data
  356. pcbData - Size of pvData, receives size of object
  357. dwFlags - Inheritance flags
  358. Return:
  359. TRUE if success, FALSE on error, (call GetLastError())
  360. --*/
  361. {
  362. DWORD RequiredSize;
  363. HRESULT hRes;
  364. DBG_ASSERT( _hMB );
  365. TryAgain:
  366. hRes = _pMBCom->ComMDGetAllMetaData( _hMB,
  367. (unsigned char *)pszPath,
  368. dwFlags,
  369. dwUserType,
  370. ALL_METADATA,
  371. pcRecords,
  372. pdwDataSetNumber,
  373. pBuff->QuerySize(),
  374. (PBYTE)pBuff->QueryPtr(),
  375. &RequiredSize
  376. );
  377. // See if we got it, and if we failed because of lack of buffer space
  378. // try again.
  379. if ( SUCCEEDED(hRes) )
  380. {
  381. return TRUE;
  382. }
  383. // Some sort of error, most likely not enough buffer space. Keep
  384. // trying until we get a non-fatal error.
  385. if (HRESULT_FACILITY(hRes) == FACILITY_WIN32 &&
  386. HRESULT_CODE(hRes) == ERROR_INSUFFICIENT_BUFFER) {
  387. // Not enough buffer space. RequiredSize contains the amount
  388. // the metabase thinks we need.
  389. if ( !pBuff->Resize(RequiredSize) ) {
  390. // Not enough memory to resize.
  391. return FALSE;
  392. }
  393. goto TryAgain;
  394. }
  395. return FALSE;
  396. }
  397. BOOL MB::GetDataSetNumber(
  398. const CHAR * pszPath,
  399. DWORD * pdwDataSetNumber
  400. )
  401. /*++
  402. Routine Description:
  403. Retrieves the data set number and size of the data from the
  404. metabase.
  405. Arguments:
  406. pszPath - Path to set data on
  407. pdwDataSetNumber - Where to return the data set number.
  408. Return:
  409. TRUE if success, FALSE on error, (call GetLastError())
  410. --*/
  411. {
  412. HRESULT hRes;
  413. //
  414. // We allow _hMB to be null (root handle) for this API (though technically
  415. // all the APIs allow the metabase handle to be null)
  416. //
  417. hRes = _pMBCom->ComMDGetDataSetNumber( _hMB,
  418. (unsigned char *)pszPath,
  419. pdwDataSetNumber );
  420. return SUCCEEDED(hRes);
  421. }
  422. BOOL
  423. MB::GetStr(
  424. const CHAR * pszPath,
  425. DWORD dwPropID,
  426. DWORD dwUserType,
  427. STR * pstrValue,
  428. DWORD dwFlags,
  429. const CHAR * pszDefault
  430. )
  431. /*++
  432. Routine Description:
  433. Retrieves the string from the metabase. If the value wasn't found and
  434. a default is supplied, then the default value is copied to the string.
  435. Arguments:
  436. pszPath - Path to get data on
  437. dwPropID - property id to retrieve
  438. dwUserType - User type for this property
  439. pstrValue - string that receives the value
  440. dwFlags - Metabase flags
  441. pszDefault - Default value to use if the string isn't found, NULL
  442. for no default value (i.e., will return an error).
  443. Return:
  444. TRUE if success, FALSE on error, (call GetLastError())
  445. --*/
  446. {
  447. DWORD cbSize = pstrValue->QuerySize();
  448. TryAgain:
  449. if ( !GetData( pszPath,
  450. dwPropID,
  451. dwUserType,
  452. STRING_METADATA,
  453. pstrValue->QueryStr(),
  454. &cbSize,
  455. dwFlags ))
  456. {
  457. if ( GetLastError() == MD_ERROR_DATA_NOT_FOUND )
  458. {
  459. if ( pszDefault != NULL )
  460. {
  461. return pstrValue->Copy( pszDefault );
  462. }
  463. return FALSE;
  464. }
  465. else if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER &&
  466. pstrValue->Resize( cbSize ) )
  467. {
  468. goto TryAgain;
  469. }
  470. return FALSE;
  471. }
  472. DBG_REQUIRE( pstrValue->SetLen( cbSize ? (cbSize - 1) : 0 ));
  473. return TRUE;
  474. }
  475. BOOL
  476. MB::GetMultisz(
  477. const CHAR * pszPath,
  478. DWORD dwPropID,
  479. DWORD dwUserType,
  480. MULTISZ * multiszValue,
  481. DWORD dwFlags
  482. )
  483. /*++
  484. Routine Description:
  485. Retrieves the string from the metabase. If the value wasn't found and
  486. a default is supplied, then the default value is copied to the string.
  487. Arguments:
  488. pszPath - Path to get data on
  489. dwPropID - property id to retrieve
  490. dwUserType - User type for this property
  491. multiszValue - multi-string that receives the value
  492. dwFlags - Metabase flags
  493. Return:
  494. TRUE if success, FALSE on error, (call GetLastError())
  495. --*/
  496. {
  497. DWORD cbSize = multiszValue->QuerySize();
  498. TryAgain:
  499. if ( !GetData( pszPath,
  500. dwPropID,
  501. dwUserType,
  502. MULTISZ_METADATA,
  503. multiszValue->QueryStr(),
  504. &cbSize,
  505. dwFlags ))
  506. {
  507. if ( GetLastError() == MD_ERROR_DATA_NOT_FOUND )
  508. {
  509. return FALSE;
  510. }
  511. else if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER &&
  512. multiszValue->Resize( cbSize ) )
  513. {
  514. goto TryAgain;
  515. }
  516. return FALSE;
  517. }
  518. //
  519. // Value was read directly into the buffer so update the member
  520. // variables
  521. //
  522. multiszValue->RecalcLen();
  523. return TRUE;
  524. }
  525. BOOL MB::GetDataPaths(
  526. const CHAR * pszPath,
  527. DWORD dwPropID,
  528. DWORD dwDataType,
  529. BUFFER * pBuff
  530. )
  531. /*++
  532. Routine Description:
  533. Retrieves all the metabase properties on this path of the request type
  534. Arguments:
  535. pszPath - Path to set data on
  536. dwFlags - Inerhitance flags
  537. dwPropID - Metabase property ID
  538. dwUserType - User type for this property
  539. dwDataType - Type of data being set (dword, string etc)
  540. pvData - Pointer to data
  541. pcbData - Size of pvData, receives size of object
  542. dwFlags - Inheritance flags
  543. Return:
  544. TRUE if success, FALSE on error, (call GetLastError())
  545. --*/
  546. {
  547. DWORD RequiredSize;
  548. HRESULT hRes;
  549. DBG_ASSERT( _hMB );
  550. DBG_ASSERT( pBuff != NULL );
  551. TryAgain:
  552. hRes = _pMBCom->ComMDGetMetaDataPaths( _hMB,
  553. (unsigned char *)pszPath,
  554. dwPropID,
  555. dwDataType,
  556. pBuff->QuerySize(),
  557. (PBYTE)pBuff->QueryPtr(),
  558. &RequiredSize
  559. );
  560. // See if we got it, and if we failed because of lack of buffer space
  561. // try again.
  562. if ( SUCCEEDED(hRes) )
  563. {
  564. return TRUE;
  565. }
  566. // Some sort of error, most likely not enough buffer space. Keep
  567. // trying until we get a non-fatal error.
  568. if (HRESULT_FACILITY(hRes) == FACILITY_WIN32 &&
  569. HRESULT_CODE(hRes) == ERROR_INSUFFICIENT_BUFFER) {
  570. // Not enough buffer space. RequiredSize contains the amount
  571. // the metabase thinks we need.
  572. if ( !pBuff->Resize(RequiredSize) ) {
  573. // Not enough memory to resize.
  574. return FALSE;
  575. }
  576. goto TryAgain;
  577. }
  578. return FALSE;
  579. }