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.

647 lines
17 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. simplemb.cxx
  5. Abstract:
  6. based on mb.cxx from the iisrearc project
  7. This module implements the MB class using the DCOM interface.
  8. The old MB class (IIS4.0) was used internally within the IIS codebase to
  9. access the metabase objects locally inprocess. This allowed access to
  10. the metabase using the inprocess ANSI/COM interface.
  11. In the current incarnation, MB class attempts to support the following:
  12. o Support UNICODE only interface to items
  13. o Use only the DCOM interface of the Metabase (IMSAdminBase interface)
  14. o Expose similar functionality like the MB class.
  15. Return Values:
  16. Almost all MB class members return BOOL values.
  17. TRUE indicates success in the operation and FALSE indicates a failure.
  18. The class is expected to be used in-process for code that is mostly
  19. reliant on the Win32 style error reporting, it sets the error code in
  20. the thread and exposes them via GetLastError() interface.
  21. Author:
  22. Murali Krishnan (MuraliK) 03-Nov-1998
  23. Revision History:
  24. --*/
  25. /************************************************************
  26. * Include Headers
  27. ************************************************************/
  28. #include <nt.h>
  29. #include <ntrtl.h>
  30. #include <nturtl.h>
  31. #include <windows.h>
  32. #include <ole2.h>
  33. #include <iadmw.h>
  34. #include <simplemb.hxx>
  35. #include "dbgutil.h"
  36. //
  37. // Default timeout
  38. //
  39. #define MB_TIMEOUT (30 * 1000)
  40. //
  41. // Default timeout for SaveData
  42. //
  43. #define MB_SAVE_TIMEOUT (10 * 1000) // milliseconds
  44. /************************************************************
  45. * Member Functions of SimpleMB
  46. ************************************************************/
  47. SimpleMB::SimpleMB( IMSAdminBase * pAdminBase )
  48. : m_pAdminBase( pAdminBase ),
  49. m_hMBPath ( NULL)
  50. {
  51. DBG_ASSERT( m_pAdminBase != NULL);
  52. //
  53. // Add ref the admin base object so that we can keep this object around.
  54. //
  55. m_pAdminBase->AddRef();
  56. }
  57. SimpleMB::~SimpleMB( VOID )
  58. {
  59. //
  60. // Close the metabase handle if we have it open
  61. //
  62. if ( NULL != m_hMBPath) {
  63. //
  64. // Close can sometimes fail with error RPC_E_DISCONNECTED.
  65. // Do not Assert
  66. //
  67. Close();
  68. }
  69. //
  70. // Release the AdminBase object here
  71. //
  72. if ( NULL != m_pAdminBase) {
  73. m_pAdminBase->Release();
  74. m_pAdminBase = NULL;
  75. }
  76. } // SimpleMB::~SimpleMB()
  77. /*********************************************************************++
  78. Routine Description:
  79. Opens the metabase and saves the metabase handle in the current object.
  80. Note: If there is already an opened handle, this method will fail.
  81. Arguments:
  82. hOpenRoot - Relative root or METADATA_MASTER_ROOT_HANDLE
  83. pwszPath - Path to open
  84. dwFlags - Open flags
  85. Return:
  86. TRUE if success, FALSE on error, (call GetLastError())
  87. The handle opened is stored inside the MB object.
  88. --*********************************************************************/
  89. BOOL
  90. SimpleMB::Open( METADATA_HANDLE hOpenRoot,
  91. LPCWSTR pwszPath,
  92. DWORD dwFlags )
  93. {
  94. HRESULT hr;
  95. if ( m_hMBPath != NULL) {
  96. SetLastError( ERROR_PATH_NOT_FOUND );
  97. return (FALSE);
  98. }
  99. hr = m_pAdminBase->OpenKey( hOpenRoot,
  100. pwszPath,
  101. dwFlags,
  102. MB_TIMEOUT,
  103. &m_hMBPath );
  104. if ( SUCCEEDED( hr ))
  105. {
  106. return TRUE;
  107. }
  108. SetLastError( HRESULTTOWIN32( hr ) );
  109. return FALSE;
  110. } // SimpleMB::Open()
  111. /*********************************************************************++
  112. Routine Descrition:
  113. This function closes the metabase handle that we have open in
  114. this MB object
  115. Arguments:
  116. None
  117. Returns:
  118. TRUE on success
  119. FALSE if there are any errors. Use GetLastError() to retrieve the error
  120. on failure.
  121. --*********************************************************************/
  122. BOOL SimpleMB::Close( VOID )
  123. {
  124. if ( m_hMBPath )
  125. {
  126. HRESULT hr;
  127. hr = m_pAdminBase->CloseKey( m_hMBPath );
  128. if (FAILED(hr)) {
  129. SetLastError( HRESULTTOWIN32( hr));
  130. return (FALSE);
  131. }
  132. m_hMBPath = NULL;
  133. }
  134. return TRUE;
  135. } // SimpleMB::Close()
  136. /*********************************************************************++
  137. Routine Descrition:
  138. This function saves all the changes that we have made using current
  139. metabase object.
  140. Arguments:
  141. None
  142. Returns:
  143. TRUE on success
  144. FALSE if there are any errors. Use GetLastError() to retrieve the error
  145. on failure.
  146. --*********************************************************************/
  147. BOOL SimpleMB::Save( VOID )
  148. {
  149. HRESULT hr;
  150. if ( NULL != m_pAdminBase) {
  151. hr = m_pAdminBase->SaveData();
  152. if ( FAILED( hr)) {
  153. SetLastError( HRESULTTOWIN32( hr));
  154. return (FALSE);
  155. }
  156. }
  157. return (TRUE);
  158. } // SimpleMB::Save()
  159. /*********************************************************************++
  160. Routine Description:
  161. Retrieves all the metabase properties on this path of the request type
  162. Arguments:
  163. pszPath - Path to get the data on
  164. dwFlags - Inerhitance flags
  165. dwPropID - Metabase property ID
  166. dwUserType - User type for this property
  167. dwDataType - Type of data being set (dword, string etc)
  168. pvData - Pointer to data
  169. pcbData - Size of pvData, receives size of object
  170. dwFlags - Inheritance flags
  171. Return:
  172. TRUE if success, FALSE on error, (call GetLastError())
  173. --*********************************************************************/
  174. BOOL
  175. SimpleMB::GetAll( IN LPCWSTR pszPath,
  176. DWORD dwFlags,
  177. DWORD dwUserType,
  178. BUFFER * pBuff,
  179. DWORD * pcRecords,
  180. DWORD * pdwDataSetNumber )
  181. {
  182. DWORD RequiredSize;
  183. HRESULT hr;
  184. DBG_ASSERT( m_pAdminBase != NULL);
  185. DBG_ASSERT( m_hMBPath != NULL);
  186. do {
  187. hr = m_pAdminBase->
  188. GetAllData( m_hMBPath,
  189. pszPath,
  190. dwFlags,
  191. dwUserType,
  192. ALL_METADATA,
  193. pcRecords,
  194. pdwDataSetNumber,
  195. pBuff->QuerySize(),
  196. (PBYTE)pBuff->QueryPtr(),
  197. &RequiredSize
  198. );
  199. // See if we got it, and if we failed because of lack of buffer space
  200. // try again.
  201. if ( SUCCEEDED(hr) ) {
  202. return TRUE;
  203. }
  204. //
  205. // Some sort of error, most likely not enough buffer space. Keep
  206. // trying until we get a non-fatal error.
  207. //
  208. if (HRESULT_FACILITY(hr) == FACILITY_WIN32 &&
  209. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER) {
  210. // Not enough buffer space. RequiredSize contains the amount
  211. // the metabase thinks we need.
  212. if ( !pBuff->Resize(RequiredSize) ) {
  213. // Not enough memory to resize.
  214. return FALSE;
  215. }
  216. } else {
  217. //
  218. // Some other failure: return the failure to caller
  219. //
  220. SetLastError(HRESULTTOWIN32(hr));
  221. break;
  222. }
  223. } while (FAILED(hr));
  224. return FALSE;
  225. } // SimpleMB::GetAll()
  226. /*********************************************************************++
  227. Routine Description:
  228. This function retrieves the data set number from the metabase
  229. for the given path.
  230. Arguments:
  231. pszPath - pointer to string containing the path for metabase item
  232. pdwDataSetNumber - pointer to DWORD that will contain the dataset
  233. number on return.
  234. Returns:
  235. TRUE on success. FALSE for failure
  236. --*********************************************************************/
  237. BOOL
  238. SimpleMB::GetDataSetNumber(IN LPCWSTR pszPath,
  239. OUT DWORD * pdwDataSetNumber)
  240. {
  241. HRESULT hr;
  242. DBG_ASSERT ( m_pAdminBase != NULL);
  243. //
  244. // NULL metabase handle is permitted here
  245. //
  246. hr = m_pAdminBase->GetDataSetNumber( m_hMBPath, pszPath, pdwDataSetNumber);
  247. if (FAILED (hr)) {
  248. SetLastError( HRESULTTOWIN32( hr));
  249. return (FALSE);
  250. }
  251. return (TRUE);
  252. } // SimpleMB::GetDataSetNumber()
  253. /*********************************************************************++
  254. Routine Description:
  255. Enumerates and obtain the name of the object at given index position
  256. within the given path in the tree.
  257. Arguments:
  258. pszPath - pointer to string containing the path for metabase item
  259. pszName - pointer to a buffer that will contain the name of the item
  260. at index position [dwIndex]. The buffer should at least be
  261. ADMINDATA_MAX_NAME_LEN+1 character in length
  262. dwIndex - index for the item to be enumerated.
  263. Returns:
  264. TRUE on success. FALSE for failure.
  265. ERROR_NO_MORE_ITEMS when the end of the list is reached.
  266. A typical use is to enumerate for all items starting at index 0 and
  267. enumerating till the return value is FALSE with error = ERROR_NO_MORE_ITEMS
  268. --*********************************************************************/
  269. BOOL
  270. SimpleMB::EnumObjects( IN LPCWSTR pszPath,
  271. OUT LPWSTR pszName,
  272. IN DWORD dwIndex )
  273. {
  274. HRESULT hr = m_pAdminBase->EnumKeys( m_hMBPath,
  275. pszPath,
  276. pszName,
  277. dwIndex );
  278. if ( SUCCEEDED( hr ))
  279. {
  280. return TRUE;
  281. }
  282. SetLastError( HRESULTTOWIN32( hr ));
  283. return FALSE;
  284. } // SimpleMB::EnumObjects()
  285. BOOL
  286. SimpleMB::AddObject( IN LPCWSTR pszPath)
  287. {
  288. HRESULT hr;
  289. hr = m_pAdminBase->AddKey( m_hMBPath, pszPath);
  290. if (SUCCEEDED(hr)) {
  291. return ( TRUE);
  292. }
  293. SetLastError( HRESULTTOWIN32( hr));
  294. return (FALSE);
  295. } // SimpleMB::AddObject()
  296. BOOL
  297. SimpleMB::DeleteObject( IN LPCWSTR pszPath)
  298. {
  299. HRESULT hr;
  300. hr = m_pAdminBase->DeleteKey( m_hMBPath, pszPath);
  301. if (SUCCEEDED(hr)) {
  302. return ( TRUE);
  303. }
  304. SetLastError( HRESULTTOWIN32( hr));
  305. return (FALSE);
  306. } // SimpleMB::DeleteObject()
  307. BOOL
  308. SimpleMB::DeleteData(
  309. IN LPCWSTR pszPath,
  310. IN DWORD dwPropID,
  311. IN DWORD /*dwUserType*/,
  312. IN DWORD dwDataType )
  313. {
  314. HRESULT hr = m_pAdminBase->DeleteData( m_hMBPath,
  315. pszPath,
  316. dwPropID,
  317. dwDataType
  318. );
  319. if ( SUCCEEDED( hr ))
  320. {
  321. return TRUE;
  322. }
  323. SetLastError( HRESULTTOWIN32( hr ));
  324. return(FALSE);
  325. } // SimpleMB::DeleteData()
  326. BOOL
  327. SimpleMB::GetSystemChangeNumber( OUT DWORD * pdwChangeNumber)
  328. {
  329. HRESULT hr = m_pAdminBase->GetSystemChangeNumber( pdwChangeNumber);
  330. if (SUCCEEDED(hr)) {
  331. return ( TRUE);
  332. }
  333. SetLastError( HRESULTTOWIN32( hr));
  334. return (FALSE);
  335. }
  336. /*********************************************************************++
  337. Routine Description:
  338. Sets a metadata property on an opened metabase path.
  339. Arguments:
  340. pszPath - Path to set data on
  341. dwPropID - Metabase property ID
  342. dwUserType - User type for this property
  343. dwDataType - Type of data being set (dword, string etc)
  344. pvData - Pointer to data buffer containing the data.
  345. cbData - Size of data
  346. dwFlags - Inheritance flags
  347. Return:
  348. TRUE if success, FALSE on error, (call GetLastError())
  349. --*********************************************************************/
  350. BOOL
  351. SimpleMB::SetData( IN LPCWSTR pszPath,
  352. IN DWORD dwPropID,
  353. IN DWORD dwUserType,
  354. IN DWORD dwDataType,
  355. IN VOID * pvData,
  356. IN DWORD cbData,
  357. IN DWORD dwFlags )
  358. {
  359. HRESULT hr;
  360. METADATA_RECORD mdr;
  361. DBG_ASSERT( m_pAdminBase != NULL);
  362. DBG_ASSERT( m_hMBPath != NULL);
  363. mdr.dwMDIdentifier = dwPropID;
  364. mdr.dwMDAttributes = dwFlags;
  365. mdr.dwMDUserType = dwUserType;
  366. mdr.dwMDDataType = dwDataType;
  367. mdr.dwMDDataLen = cbData;
  368. mdr.pbMDData = (BYTE * ) pvData;
  369. hr = m_pAdminBase->SetData(m_hMBPath, pszPath, &mdr);
  370. if (SUCCEEDED(hr)) {
  371. return ( TRUE);
  372. }
  373. SetLastError( HRESULTTOWIN32( hr));
  374. return (FALSE);
  375. } // SimpleMB::SetData()
  376. /*********************************************************************++
  377. Routine Description:
  378. Obtains the metadata requested in the call.
  379. It uses the current opened metabase path for getting the data.
  380. Arguments:
  381. pszPath - Path to get data on
  382. dwPropID - Metabase property ID
  383. dwUserType - User type for this property
  384. dwDataType - Type of data being set (dword, string etc)
  385. pvData - Pointer to buffer in which the data will be obtained
  386. pcbData - Size of data
  387. dwFlags - Inheritance flags
  388. Return:
  389. TRUE if success, FALSE on error, (call GetLastError())
  390. --*********************************************************************/
  391. BOOL
  392. SimpleMB::GetData( IN LPCWSTR pszPath,
  393. IN DWORD dwPropID,
  394. IN DWORD dwUserType,
  395. IN DWORD dwDataType,
  396. OUT VOID * pvData,
  397. IN OUT DWORD * pcbData,
  398. IN DWORD dwFlags)
  399. {
  400. HRESULT hr;
  401. METADATA_RECORD mdr;
  402. DWORD dwRequiredDataLen;
  403. DBG_ASSERT( m_pAdminBase != NULL);
  404. DBG_ASSERT( m_hMBPath != NULL);
  405. mdr.dwMDIdentifier = dwPropID;
  406. mdr.dwMDAttributes = dwFlags;
  407. mdr.dwMDUserType = dwUserType;
  408. mdr.dwMDDataType = dwDataType;
  409. mdr.dwMDDataLen = *pcbData;
  410. mdr.pbMDData = (BYTE * ) pvData;
  411. hr = m_pAdminBase->GetData(m_hMBPath, pszPath, &mdr, &dwRequiredDataLen);
  412. if (SUCCEEDED(hr)) {
  413. *pcbData = mdr.dwMDDataLen;
  414. return ( TRUE);
  415. }
  416. *pcbData = dwRequiredDataLen;
  417. SetLastError( HRESULTTOWIN32( hr));
  418. return (FALSE);
  419. } // SimpleMB::GetData()
  420. /*********************************************************************++
  421. Routine Description:
  422. Obtains the paths beneath the given path in the metadata tree.
  423. It uses the current opened metabase path for getting the data.
  424. Arguments:
  425. pszPath - Path to get data on
  426. dwPropID - Metabase property ID
  427. dwDataType - Type of data being set (dword, string etc)
  428. pBuff - pointer to BUFFER object that will contain the resulting data
  429. Return:
  430. TRUE if success, FALSE on error, (call GetLastError())
  431. --*********************************************************************/
  432. BOOL
  433. SimpleMB::GetDataPaths(IN LPCWSTR pszPath,
  434. IN DWORD dwPropID,
  435. IN DWORD dwDataType,
  436. IN BUFFER * pBuff )
  437. {
  438. HRESULT hr;
  439. DWORD cchRequiredDataLen;
  440. DBG_ASSERT( m_pAdminBase != NULL);
  441. DBG_ASSERT( m_hMBPath != NULL);
  442. do {
  443. hr = m_pAdminBase->GetDataPaths( m_hMBPath,
  444. pszPath,
  445. dwPropID,
  446. dwDataType,
  447. pBuff->QuerySize() / sizeof(WCHAR),
  448. (LPWSTR ) pBuff->QueryPtr(),
  449. &cchRequiredDataLen
  450. );
  451. if ( SUCCEEDED( hr)) {
  452. return (TRUE);
  453. }
  454. // Some sort of error, most likely not enough buffer space. Keep
  455. // trying until we get a non-fatal error.
  456. if (HRESULT_FACILITY(hr) == FACILITY_WIN32 &&
  457. HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER)
  458. {
  459. // Not enough buffer space.
  460. // cchRequiredDataLen contains the # of wide chars that metabase
  461. // thinks we need.
  462. if ( !pBuff->Resize( (cchRequiredDataLen + 1) * sizeof(WCHAR)) )
  463. {
  464. // Not enough memory to resize.
  465. return FALSE;
  466. }
  467. } else {
  468. // unknown failure. return failure
  469. break;
  470. }
  471. } while (FAILED(hr));
  472. DBG_ASSERT( FAILED(hr));
  473. SetLastError( HRESULTTOWIN32( hr));
  474. return (FALSE);
  475. } // SimpleMB::GetDataPaths()