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.

553 lines
15 KiB

  1. /*++
  2. Module Name:
  3. wrapmb.cpp
  4. Abstract:
  5. wrapper classes for the metabase class. Yes, I am wrapping a wrapper. Why?
  6. because including mb.hxx totally screws up the headers in my stdafx based
  7. MFC files. This way they can just include wrapmb.h and not have to worry
  8. about including all the other stuff. Also, I can set INITGUID here. That
  9. way I can use precompiled headers in the main project to Greatly increase
  10. compile times. If that isn't reason enough, then I can also manage the pointer
  11. to the interface object itself here.
  12. Author:
  13. Boyd Multerer boydm
  14. --*/
  15. #include "stdafx.h"
  16. #include <objbase.h>
  17. #include <initguid.h>
  18. #include <iadmw.h>
  19. #include "iiscnfg.h"
  20. #include "wrapmb.h"
  21. #ifdef _NO_TRACING_
  22. DECLARE_DEBUG_PRINTS_OBJECT();
  23. #endif
  24. #define MB_TIMEOUT 5000
  25. // a macro to automatically cast the pointer to the mb object
  26. //#define _pmb ((MB*)m_pvMB)
  27. // globals
  28. IMSAdminBase* g_pMBCom = NULL;
  29. //----------------------------------------------------------------
  30. BOOL FInitMetabaseWrapperEx( OLECHAR* pocMachineName, IMSAdminBase ** ppiab )
  31. {
  32. IClassFactory * pcsfFactory = NULL;
  33. COSERVERINFO csiMachineName;
  34. COSERVERINFO * pcsiParam = NULL;
  35. HRESULT hresError;
  36. if(!ppiab)
  37. {
  38. return FALSE;
  39. }
  40. //fill the structure for CoGetClassObject
  41. ZeroMemory( &csiMachineName, sizeof(csiMachineName) );
  42. // csiMachineName.pAuthInfo = NULL;
  43. // csiMachineName.dwFlags = 0;
  44. // csiMachineName.pServerInfoExt = NULL;
  45. csiMachineName.pwszName = pocMachineName;
  46. pcsiParam = &csiMachineName;
  47. hresError = CoGetClassObject(
  48. GETAdminBaseCLSID(TRUE),
  49. CLSCTX_SERVER,
  50. pcsiParam,
  51. IID_IClassFactory,
  52. (void**) &pcsfFactory
  53. );
  54. if (FAILED(hresError))
  55. {
  56. return FALSE;
  57. }
  58. // create the instance of the interface
  59. hresError = pcsfFactory->CreateInstance(NULL, IID_IMSAdminBase, (void **)ppiab);
  60. if (FAILED(hresError))
  61. {
  62. *ppiab = NULL;
  63. return FALSE;
  64. }
  65. // release the factory
  66. pcsfFactory->Release();
  67. // success
  68. return TRUE;
  69. }
  70. //----------------------------------------------------------------
  71. BOOL FCloseMetabaseWrapperEx(IMSAdminBase ** ppiab)
  72. {
  73. if ( ppiab && *ppiab)
  74. {
  75. (*ppiab)->Release();
  76. *ppiab = NULL;
  77. }
  78. return TRUE;
  79. }
  80. //----------------------------------------------------------------
  81. BOOL FInitMetabaseWrapper( OLECHAR * pocMachineName )
  82. {
  83. //release previous interface if needed
  84. if( g_pMBCom != NULL )
  85. {
  86. g_pMBCom->Release();
  87. g_pMBCom = NULL;
  88. }
  89. return FInitMetabaseWrapperEx(pocMachineName, &g_pMBCom);
  90. }
  91. //----------------------------------------------------------------
  92. BOOL FCloseMetabaseWrapper()
  93. {
  94. return FCloseMetabaseWrapperEx(&g_pMBCom);
  95. }
  96. //=================================================================== The wrapper class
  97. //----------------------------------------------------------------
  98. CWrapMetaBase::CWrapMetaBase():
  99. m_pMetabase( NULL ),
  100. m_hMeta( NULL ),
  101. m_count(0),
  102. m_pBuffer( NULL ),
  103. m_cbBuffer(0),
  104. m_pPathBuffer( NULL ),
  105. m_cchPathBuffer( 0 )
  106. {
  107. // attempt to allocate the general buffer
  108. m_pBuffer = GlobalAlloc( GPTR, BUFFER_SIZE );
  109. if ( m_pBuffer )
  110. m_cbBuffer = BUFFER_SIZE;
  111. }
  112. //----------------------------------------------------------------
  113. CWrapMetaBase::~CWrapMetaBase()
  114. {
  115. // make sure the metabase handle is closed
  116. Close();
  117. // free the buffer
  118. if ( m_pBuffer )
  119. GlobalFree( m_pBuffer );
  120. m_pBuffer = NULL;
  121. }
  122. //----------------------------------------------------------------
  123. BOOL CWrapMetaBase::FInit( PVOID pMBCom )
  124. {
  125. BOOL fAnswer = FALSE;
  126. // NULL was passed in, use the global reference - most cases will do this
  127. if ( pMBCom )
  128. {
  129. m_pMetabase = (IMSAdminBase *)pMBCom;
  130. }
  131. else
  132. {
  133. m_pMetabase = g_pMBCom;
  134. }
  135. // if the interface is not there, fail
  136. if ( !m_pMetabase )
  137. {
  138. return FALSE;
  139. }
  140. // return success
  141. return TRUE;
  142. }
  143. //==========================================================================================
  144. // open, close and save the object and such
  145. //----------------------------------------------------------------
  146. BOOL CWrapMetaBase::Open( LPCTSTR pszPath, DWORD dwFlags )
  147. {
  148. return Open( METADATA_MASTER_ROOT_HANDLE, pszPath, dwFlags );
  149. }
  150. //----------------------------------------------------------------
  151. BOOL CWrapMetaBase::Open( METADATA_HANDLE hOpenRoot, LPCTSTR pszPath, DWORD dwFlags )
  152. {
  153. m_count++;
  154. HRESULT hRes;
  155. // if a metabase handle is already open, close it
  156. if ( m_hMeta )
  157. Close();
  158. hRes = m_pMetabase->OpenKey( hOpenRoot, pszPath, dwFlags, MB_TIMEOUT, &m_hMeta );
  159. if ( SUCCEEDED( hRes ))
  160. return TRUE;
  161. SetLastError( HRESULTTOWIN32( hRes ) );
  162. return FALSE;
  163. }
  164. //----------------------------------------------------------------
  165. BOOL CWrapMetaBase::Close( void )
  166. {
  167. if ( m_hMeta )
  168. {
  169. m_count--;
  170. m_pMetabase->CloseKey( m_hMeta );
  171. }
  172. m_hMeta = NULL;
  173. return TRUE;
  174. }
  175. //----------------------------------------------------------------
  176. BOOL CWrapMetaBase::Save( void )
  177. {
  178. HRESULT hRes = m_pMetabase->SaveData();
  179. if ( SUCCEEDED( hRes ))
  180. return TRUE;
  181. SetLastError( HRESULTTOWIN32( hRes ));
  182. return FALSE;
  183. }
  184. // enumerate the objects
  185. //----------------------------------------------------------------
  186. // fortunately, we know that there is a max length to the name of any individual
  187. // key in the metabase of 256 characters
  188. BOOL CWrapMetaBase::EnumObjects(
  189. LPCTSTR pszPath,
  190. LPTSTR pName,
  191. DWORD cbNameBuf,
  192. DWORD Index
  193. )
  194. {
  195. // enumerate into the wide character buffer
  196. HRESULT hRes = m_pMetabase->EnumKeys( m_hMeta, pszPath, pName, Index );
  197. // Check for success
  198. if ( SUCCEEDED( hRes ))
  199. {
  200. return TRUE;
  201. }
  202. SetLastError( HRESULTTOWIN32( hRes ));
  203. return FALSE;
  204. }
  205. //==========================================================================================
  206. // Add and delete objects
  207. //----------------------------------------------------------------
  208. BOOL CWrapMetaBase::AddObject( LPCTSTR pszPath )
  209. {
  210. HRESULT hRes = m_pMetabase->AddKey( m_hMeta, pszPath );
  211. if ( SUCCEEDED( hRes ))
  212. return TRUE;
  213. SetLastError( HRESULTTOWIN32( hRes ));
  214. return FALSE;
  215. }
  216. //----------------------------------------------------------------
  217. BOOL CWrapMetaBase::DeleteObject( LPCTSTR pszPath )
  218. {
  219. HRESULT hRes = m_pMetabase->DeleteKey( m_hMeta, pszPath );
  220. if ( SUCCEEDED( hRes ))
  221. return TRUE;
  222. SetLastError( HRESULTTOWIN32( hRes ));
  223. return FALSE;
  224. }
  225. //==========================================================================================
  226. // access the metahandle
  227. //----------------------------------------------------------------
  228. METADATA_HANDLE CWrapMetaBase::QueryHandle()
  229. {
  230. return m_hMeta;
  231. }
  232. //==========================================================================================
  233. // setting values
  234. //----------------------------------------------------------------
  235. BOOL CWrapMetaBase::SetDword( LPCTSTR pszPath, DWORD dwPropID, DWORD dwUserType,
  236. DWORD dwValue, DWORD dwFlags )
  237. {
  238. return SetData( pszPath,
  239. dwPropID,
  240. dwUserType,
  241. DWORD_METADATA,
  242. (PVOID) &dwValue,
  243. sizeof( DWORD ),
  244. dwFlags );
  245. }
  246. //----------------------------------------------------------------
  247. BOOL CWrapMetaBase::SetString( LPCTSTR pszPath, DWORD dwPropID, DWORD dwUserType,
  248. LPCTSTR pszValue, DWORD dwFlags )
  249. {
  250. int len = wcslen( pszValue )+1;
  251. DWORD cbWide = len * sizeof(WCHAR);
  252. // set the string into place
  253. BOOL fAnswer = SetData( pszPath,
  254. dwPropID,
  255. dwUserType,
  256. STRING_METADATA,
  257. (PVOID)pszValue,
  258. cbWide, // string length ignored for inprocess clients
  259. dwFlags );
  260. // return the answer
  261. return fAnswer;
  262. }
  263. //==========================================================================================
  264. // getting values
  265. //----------------------------------------------------------------
  266. BOOL CWrapMetaBase::GetDword( LPCTSTR pszPath, DWORD dwPropID, DWORD dwUserType,
  267. DWORD* pdwValue, DWORD dwFlags )
  268. {
  269. DWORD cb = sizeof(DWORD);
  270. return GetData( pszPath,
  271. dwPropID,
  272. dwUserType,
  273. DWORD_METADATA,
  274. pdwValue,
  275. &cb,
  276. dwFlags );
  277. }
  278. //----------------------------------------------------------------
  279. BOOL CWrapMetaBase::GetString( LPCTSTR pszPath, DWORD dwPropID, DWORD dwUserType,
  280. LPTSTR pszValue, DWORD cchValue, DWORD dwFlags )
  281. {
  282. BOOL fAnswer = FALSE;
  283. // get the data and put it right into the buffer - this is the wide version
  284. if ( GetData( pszPath,
  285. dwPropID,
  286. dwUserType,
  287. STRING_METADATA,
  288. pszValue,
  289. &cchValue,
  290. dwFlags ) )
  291. {
  292. fAnswer = TRUE;
  293. }
  294. // return the answer
  295. return fAnswer;
  296. }
  297. BOOL CWrapMetaBase::GetMultiSZString(
  298. LPCTSTR pszPath,
  299. DWORD dwPropID,
  300. DWORD dwUserType,
  301. LPTSTR pszValue,
  302. DWORD cchValue,
  303. DWORD dwFlags)
  304. {
  305. BOOL fAnswer = FALSE;
  306. // get the data and put it right into the buffer - this is the wide version
  307. if (GetData( pszPath,
  308. dwPropID,
  309. dwUserType,
  310. MULTISZ_METADATA,
  311. pszValue,
  312. &cchValue,
  313. dwFlags ) )
  314. {
  315. fAnswer = TRUE;
  316. }
  317. // return the answer
  318. return fAnswer;
  319. }
  320. //==========================================================================================
  321. // deleting values
  322. //----------------------------------------------------------------
  323. BOOL CWrapMetaBase::DeleteData( LPCTSTR pszPath, DWORD dwPropID, DWORD dwDataType )
  324. {
  325. // go right ahead and delete it
  326. HRESULT hRes = m_pMetabase->DeleteData( m_hMeta, pszPath, dwPropID, dwDataType );
  327. // test for success
  328. if ( SUCCEEDED( hRes ))
  329. return TRUE;
  330. // clean up after a failure
  331. SetLastError( HRESULTTOWIN32( hRes ));
  332. return(FALSE);
  333. }
  334. //----------------------------------------------------------------
  335. BOOL CWrapMetaBase::RenameObject( LPCTSTR pszPathOld, LPCTSTR pszNewName )
  336. {
  337. // rename the key
  338. HRESULT hRes = m_pMetabase->RenameKey( m_hMeta, pszPathOld, pszNewName );
  339. // test for success
  340. if ( SUCCEEDED( hRes ))
  341. return TRUE;
  342. // clean up after a failure
  343. SetLastError( HRESULTTOWIN32( hRes ));
  344. return FALSE;
  345. }
  346. //=====================================================================================
  347. //----------------------------------------------------------------
  348. BOOL CWrapMetaBase::SetData( LPCTSTR pszPath, DWORD dwPropID, DWORD dwUserType, DWORD dwDataType,
  349. PVOID pData, DWORD cbData, DWORD dwFlags )
  350. {
  351. METADATA_RECORD mdRecord;
  352. HRESULT hRes;
  353. // prepare the set data record
  354. mdRecord.dwMDIdentifier = dwPropID;
  355. mdRecord.dwMDAttributes = dwFlags;
  356. mdRecord.dwMDUserType = dwUserType;
  357. mdRecord.dwMDDataType = dwDataType;
  358. mdRecord.dwMDDataLen = cbData;
  359. mdRecord.pbMDData = (PBYTE)pData;
  360. // set the data
  361. hRes = m_pMetabase->SetData( m_hMeta, pszPath, &mdRecord );
  362. // test for success
  363. if ( SUCCEEDED( hRes ))
  364. return TRUE;
  365. // there was an error, clean up
  366. SetLastError( HRESULTTOWIN32( hRes ) );
  367. return FALSE;
  368. }
  369. //----------------------------------------------------------------
  370. BOOL CWrapMetaBase::GetData( LPCTSTR pszPath, DWORD dwPropID, DWORD dwUserType, DWORD dwDataType,
  371. PVOID pData, DWORD* pcbData, DWORD dwFlags )
  372. {
  373. METADATA_RECORD mdRecord;
  374. HRESULT hRes;
  375. DWORD dwRequiredLen;
  376. // prepare the get data record
  377. mdRecord.dwMDIdentifier = dwPropID;
  378. mdRecord.dwMDAttributes = dwFlags;
  379. mdRecord.dwMDUserType = dwUserType;
  380. mdRecord.dwMDDataType = dwDataType;
  381. mdRecord.dwMDDataLen = *pcbData;
  382. mdRecord.pbMDData = (PBYTE)pData;
  383. // get the data
  384. hRes = m_pMetabase->GetData( m_hMeta, pszPath, &mdRecord, &dwRequiredLen );
  385. // test for success
  386. if ( SUCCEEDED( hRes ))
  387. {
  388. *pcbData = mdRecord.dwMDDataLen;
  389. return TRUE;
  390. }
  391. // there was a failure - clean up
  392. *pcbData = dwRequiredLen;
  393. SetLastError( HRESULTTOWIN32( hRes ) );
  394. return FALSE;
  395. }
  396. //----------------------------------------------------------------
  397. // another form of GetData that automatically allocates the buffer. It should then be
  398. // freed using GlobalFree(p);
  399. PVOID CWrapMetaBase::GetData( LPCTSTR pszPath, DWORD dwPropID, DWORD dwUserType, DWORD dwDataType,
  400. DWORD* pcbData, DWORD dwFlags )
  401. {
  402. PVOID pData = m_pBuffer;
  403. DWORD cbData = m_cbBuffer;
  404. DWORD err = 0;
  405. BOOL f;
  406. // first - attempt to get the data in the buffer that has already been allocated;
  407. f = GetData( pszPath, dwPropID, dwUserType, dwDataType, pData, &cbData, dwFlags );
  408. // if the get data function worked, we can pretty much leave
  409. if ( f )
  410. {
  411. // set the data size
  412. *pcbData = cbData;
  413. // return the allocated buffer
  414. return pData;
  415. }
  416. // check the error - it could be some sort of memory error
  417. err = GetLastError();
  418. // it is ok that the GetData failed, but the reason had better be ERROR_INSUFFICIENT_BUFFER
  419. // otherwise, it is something we can't handle
  420. if ( err != ERROR_INSUFFICIENT_BUFFER )
  421. return NULL;
  422. // allocate the buffer
  423. pData = GlobalAlloc( GPTR, cbData );
  424. if ( !pData )
  425. return NULL;
  426. // first, get the size of the data that we are looking for
  427. f = GetData( pszPath, dwPropID, dwUserType, dwDataType, pData, &cbData, dwFlags );
  428. // if that getting failed, we need to cleanup
  429. if ( !f )
  430. {
  431. GlobalFree( pData );
  432. pData = NULL;
  433. }
  434. // set the data size
  435. *pcbData = cbData;
  436. // return the allocated buffer
  437. return pData;
  438. }
  439. //----------------------------------------------------------------
  440. // free memory returned by GetData
  441. void CWrapMetaBase::FreeWrapData( PVOID pData )
  442. {
  443. // if it is trying to free the local buffer, do nothing
  444. if ( pData == m_pBuffer )
  445. {
  446. return;
  447. }
  448. // ah - but it was not the local buffer - we should dispose of it
  449. if ( pData )
  450. {
  451. GlobalFree( pData );
  452. }
  453. }