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.

5717 lines
202 KiB

  1. #include "precomp.hxx"
  2. CIdToPointerMapper *g_PointerMapper = NULL;
  3. CMDCOM::CMDCOM():
  4. m_ImpIConnectionPointContainer(),
  5. m_hresConstructorError(ERROR_SUCCESS)
  6. {
  7. UINT i;
  8. m_dwRefCount = 0;
  9. g_hReadSaveSemaphore = NULL;
  10. g_PointerMapper = new CIdToPointerMapper (DEFAULT_START_NUMBER_OF_MAPS, DEFAULT_INCREASE_NUMBER_OF_MAPS);
  11. MD_ASSERT(g_PointerMapper);
  12. fFlusherInitialized = FALSE;
  13. dwMBFlushCookie = 0;
  14. msMBFlushTime = INETA_MB_FLUSH_DEFAULT;
  15. INITIALIZE_CRITICAL_SECTION( &csFlushLock );
  16. INITIALIZE_CRITICAL_SECTION( &g_csEditWhileRunning );
  17. // Null all entries in the connection point array.
  18. for (i=0; i<MAX_CONNECTION_POINTS; i++)
  19. m_aConnectionPoints[i] = NULL;
  20. HRESULT hr = NOERROR;
  21. g_hReadSaveSemaphore = IIS_CREATE_SEMAPHORE(
  22. "g_hReadSaveSemaphore",
  23. &g_hReadSaveSemaphore,
  24. 1,
  25. 1
  26. );
  27. if( g_hReadSaveSemaphore == NULL ) {
  28. hr = GetLastHResult();
  29. IIS_PRINTF((buff,"CreateSemaphore Failed with %x\n",hr));
  30. }
  31. else {
  32. COConnectionPoint* pCOConnPt;
  33. m_ImpIConnectionPointContainer.Init(this);
  34. // Rig this COPaper COM object to be connectable. Assign the connection
  35. // point array. This object's connection points are determined at
  36. // compile time--it currently has 2 connection points, one for ANSI,
  37. // one for UNICODE. Create a connection
  38. // point object for these and assign them into the array. This array could
  39. // easily grow to support additional connection points in the future.
  40. // First try creating a new connection point object. Pass 'this' as the
  41. // pHostObj pointer used by the connection point to pass its AddRef and
  42. // Release calls back to the host connectable object.
  43. pCOConnPt = new COConnectionPoint((IUnknown*)this);
  44. if (NULL != pCOConnPt)
  45. {
  46. // If creation succeeded then initialize it (including creating
  47. // its initial dynamic connection array).
  48. hr = pCOConnPt->Init(IID_IMDCOMSINK_A);
  49. MD_ASSERT(SUCCEEDED(hr));
  50. // If the init succeeded then use QueryInterface to obtain the
  51. // IConnectionPoint interface on the new connection point object.
  52. // The interface pointer is assigned directly into the
  53. // connection point array. The QI also does the needed AddRef.
  54. if (SUCCEEDED(hr))
  55. {
  56. hr = pCOConnPt->QueryInterface(
  57. IID_IConnectionPoint,
  58. (PPVOID)&m_aConnectionPoints[MD_CONNPOINT_WRITESINK_A]);
  59. MD_ASSERT(SUCCEEDED(hr));
  60. }
  61. if( FAILED(hr) )
  62. {
  63. delete pCOConnPt;
  64. }
  65. }
  66. pCOConnPt = new COConnectionPoint((IUnknown*)this);
  67. if (NULL != pCOConnPt)
  68. {
  69. // If creation succeeded then initialize it (including creating
  70. // its initial dynamic connection array).
  71. hr = pCOConnPt->Init(IID_IMDCOMSINK_W);
  72. MD_ASSERT(SUCCEEDED(hr));
  73. // If the init succeeded then use QueryInterface to obtain the
  74. // IConnectionPoint interface on the new connection point object.
  75. // The interface pointer is assigned directly into the
  76. // connection point array. The QI also does the needed AddRef.
  77. if (SUCCEEDED(hr))
  78. {
  79. hr = pCOConnPt->QueryInterface(
  80. IID_IConnectionPoint,
  81. (PPVOID)&m_aConnectionPoints[MD_CONNPOINT_WRITESINK_W]);
  82. MD_ASSERT(SUCCEEDED(hr));
  83. }
  84. if( FAILED(hr) )
  85. {
  86. delete pCOConnPt;
  87. }
  88. }
  89. }
  90. m_hresConstructorError = hr;
  91. }
  92. CMDCOM::~CMDCOM()
  93. {
  94. // SetEvent(hevtDone);
  95. UINT i;
  96. IConnectionPoint* pIConnectionPoint;
  97. // Do final release of the connection point objects.
  98. // If this isn't the final release, then the client has an outstanding
  99. // unbalanced reference to a connection point and a memory leak may
  100. // likely result because the host COPaper object is now going away yet
  101. // a connection point for this host object will not end up deleting
  102. // itself (and its connections array).
  103. for (i=0; i<MAX_CONNECTION_POINTS; i++)
  104. {
  105. pIConnectionPoint = m_aConnectionPoints[i];
  106. RELEASE_INTERFACE(pIConnectionPoint);
  107. }
  108. if (g_hReadSaveSemaphore != NULL) {
  109. CloseHandle(g_hReadSaveSemaphore);
  110. }
  111. DeleteCriticalSection( &csFlushLock );
  112. DeleteCriticalSection( &g_csEditWhileRunning );
  113. MD_ASSERT(g_PointerMapper);
  114. delete g_PointerMapper;
  115. }
  116. HRESULT
  117. CMDCOM::QueryInterface(REFIID riid, void **ppObject) {
  118. if (riid==IID_IUnknown || riid==IID_IMDCOM) {
  119. *ppObject = (IMDCOM *) this;
  120. AddRef();
  121. }
  122. else if ( IID_IMDCOM2 == riid )
  123. {
  124. *ppObject = (IMDCOM2 *) this;
  125. AddRef();
  126. }
  127. else if ( IID_IMDCOM3 == riid )
  128. {
  129. *ppObject = (IMDCOM3 *) this;
  130. AddRef();
  131. }
  132. else if (IID_IConnectionPointContainer == riid) {
  133. *ppObject = &m_ImpIConnectionPointContainer;
  134. AddRef();
  135. }
  136. else {
  137. return E_NOINTERFACE;
  138. }
  139. return NO_ERROR;
  140. }
  141. ULONG
  142. CMDCOM::AddRef()
  143. {
  144. DWORD dwRefCount;
  145. InterlockedIncrement((long *)&g_dwRefCount);
  146. dwRefCount = InterlockedIncrement((long *)&m_dwRefCount);
  147. return dwRefCount;
  148. }
  149. ULONG
  150. CMDCOM::Release()
  151. {
  152. DWORD dwRefCount;
  153. InterlockedDecrement((long *)&g_dwRefCount);
  154. dwRefCount = InterlockedDecrement((long *)&m_dwRefCount);
  155. //
  156. // This is now a member of class factory.
  157. // It is not dynamically allocated, so don't delete it.
  158. //
  159. /*
  160. if (dwRefCount == 0) {
  161. delete this;
  162. return 0;
  163. }
  164. */
  165. return dwRefCount;
  166. }
  167. HRESULT
  168. CMDCOM::ComMDInitialize()
  169. /*++
  170. Routine Description:
  171. Initializes the metadata database. This must be called before any other API.
  172. Reads in the existing database, if found. If errors occur reading in the
  173. existing database, warnings are returned and the metabase is initialized
  174. with not data.
  175. Arguments:
  176. Return Value:
  177. DWORD - Return Code
  178. ERROR_SUCCESS
  179. ERROR_ALREADY_INITIALIZED
  180. ERROR_NOT_ENOUGH_MEMORY
  181. ERROR_INVALID_DATA
  182. MD_WARNING_PATH_NOT_FOUND
  183. MD_WARNING_DUP_NAME
  184. MD_WARNING_INVALID_DATA
  185. Notes:
  186. This could take a long time to process, as it may load in a large amount of data.
  187. If a warning code is returned, the database has been successfully initialized, but
  188. some data in the database was not loaded successfully.
  189. --*/
  190. {
  191. InitializeFlusher ();
  192. return InitWorker(FALSE, NULL, NULL, NULL);
  193. }
  194. HRESULT
  195. CMDCOM::ComMDTerminate(IN BOOL)
  196. /*++
  197. Routine Description:
  198. DeInitailizes the metadata database. This must be before the application terminates
  199. or dunloads the dll.
  200. Arguments:
  201. SaveData - If TRUE, the metadata is saved before terminating.
  202. If the save fails, the metadata is not terminated.
  203. Return Value:
  204. DWORD - ERROR_SUCCESS
  205. MD_ERROR_NOT_INITIALIZED
  206. ERROR_NOT_ENOUGH_MEMORY
  207. Errors from the file system.
  208. Notes:
  209. This could take a long time to process, as it may save a large amount of data.
  210. --*/
  211. {
  212. HRESULT hr;
  213. hr = TerminateWorker1(FALSE);
  214. return hr;
  215. }
  216. HRESULT STDMETHODCALLTYPE
  217. CMDCOM::ComMDSendShutdownNotifications(VOID)
  218. /*++
  219. Routine Description:
  220. Sends the shutdown notifications.
  221. Arguments:
  222. None
  223. Return Value:
  224. HRESULT
  225. --*/
  226. {
  227. HRESULT hr = S_OK;
  228. SendShutdownNotifications();
  229. return hr;
  230. }
  231. HRESULT STDMETHODCALLTYPE
  232. CMDCOM::ComMDShutdown( void)
  233. {
  234. HRESULT hresReturn;
  235. IIS_CRYPTO_STORAGE CryptoStorage;
  236. PIIS_CRYPTO_BLOB pSessionKeyBlob;
  237. TerminateFlusher();
  238. //
  239. // Give applications some time to close their interfaces,
  240. // but don't wait too long, user is waiting.
  241. // Wait until references are closed, unless they take too long.
  242. // IISADMIN and factory both have refences we do not wait for.
  243. //
  244. //
  245. // Note, there are four references to the CMDCOM object that
  246. // are allowed to be active after this point.
  247. // 1) The reference taken in dllmain ( cleans up in dllmain ).
  248. // 2) The reference owned by COADMIN itself
  249. // ( this is called as part of it's shutdown )
  250. // 3) The reference owned by the MDWriter for backup and restore
  251. // ( it is released after TerminateComAdmindata is called )
  252. // 4) The reference owned by the Metabase holder,
  253. // which is used to validate that the metabase is up
  254. // and working if iisadmin is started.
  255. // ( it is also released after the TerminateComAdmindata is called )
  256. //
  257. for (int i = 0;
  258. (InterlockedIncrement((long *)&m_dwRefCount) > 5) &&
  259. (i < MD_SHUTDOWN_WAIT_SECONDS);
  260. i++) {
  261. InterlockedDecrement((long *)&m_dwRefCount);
  262. Sleep(1000);
  263. }
  264. InterlockedDecrement((long *)&m_dwRefCount);
  265. hresReturn = InitStorageAndSessionKey(
  266. &CryptoStorage,
  267. &pSessionKeyBlob
  268. );
  269. if( SUCCEEDED(hresReturn) ) {
  270. //
  271. // Need to hold a read lock here to make sure
  272. // Terminate doesn't occur during SaveAllData.
  273. //
  274. // Cannot hold a write lock, as SaveAllData gets
  275. // a read lock after getting ReadSaveSemaphore
  276. //
  277. g_LockMasterResource.ReadLock();
  278. if (g_dwInitialized > 0) {
  279. hresReturn = SaveAllData(TRUE, &CryptoStorage, pSessionKeyBlob);
  280. }
  281. else {
  282. if (g_dwInitialized > 0) {
  283. MD_REQUIRE(WaitForSingleObject(g_hReadSaveSemaphore, INFINITE) != WAIT_TIMEOUT);
  284. g_bSaveDisallowed = TRUE;
  285. MD_REQUIRE(ReleaseSemaphore(g_hReadSaveSemaphore, 1, NULL));
  286. }
  287. else {
  288. g_bSaveDisallowed = TRUE;
  289. }
  290. }
  291. g_LockMasterResource.ReadUnlock();
  292. ::IISCryptoFreeBlob(pSessionKeyBlob);
  293. }
  294. return hresReturn;
  295. }
  296. HRESULT STDMETHODCALLTYPE
  297. CMDCOM::ComMDAddMetaObjectA(
  298. /* [in] */ METADATA_HANDLE hMDHandle,
  299. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDPath)
  300. {
  301. return ComMDAddMetaObjectD(hMDHandle,
  302. pszMDPath,
  303. FALSE);
  304. }
  305. HRESULT STDMETHODCALLTYPE
  306. CMDCOM::ComMDAddMetaObjectW(
  307. /* [in] */ METADATA_HANDLE hMDHandle,
  308. /* [string][in][unique] */ LPCWSTR pszMDPath)
  309. {
  310. return ComMDAddMetaObjectD(hMDHandle,
  311. (PBYTE) pszMDPath,
  312. TRUE);
  313. }
  314. HRESULT
  315. CMDCOM::ComMDAddMetaObjectD(IN METADATA_HANDLE hMDHandle,
  316. IN PBYTE pszMDPath,
  317. IN BOOL bUnicode)
  318. /*++
  319. Routine Description:
  320. Creates a meta object and adds it to the list of child objects for the object specified by Path.
  321. Arguments:
  322. Handle - A handle returned by MDOpenMetaObject with write permission.
  323. Path - Path of the object to be added, relative to the path of Handle.
  324. Must not be NULL.
  325. eg. "Root Object/Child/GrandChild"
  326. Return Value:
  327. DWORD - Return Code
  328. ERROR_SUCCESS
  329. MD_ERROR_NOT_INITIALIZED
  330. ERROR_INVALID_PARAMETER
  331. ERROR_ACCESS_DENIED
  332. ERROR_NOT_ENOUGH_MEMORY
  333. ERROR_PATH_NOT_FOUND
  334. ERROR_DUP_NAME
  335. ERROR_INVALID_NAME
  336. Notes:
  337. METADATA_MASTER_ROOT_HANDLE is not valid for this operation.
  338. --*/
  339. {
  340. HRESULT hresReturn;
  341. CMDHandle *hHandleObject;
  342. if (g_dwInitialized == 0) {
  343. hresReturn = MD_ERROR_NOT_INITIALIZED;
  344. }
  345. else {
  346. WCHAR strPath[METADATA_MAX_NAME_LEN];
  347. LPSTR pszTempPath = (LPSTR)pszMDPath;
  348. //
  349. // ExtractNameFromPath assumes no preceding delimeter
  350. //
  351. if (pszTempPath != NULL) {
  352. SkipPathDelimeter(pszTempPath, bUnicode);
  353. }
  354. //
  355. // Make sure at least one new object was specified
  356. //
  357. hresReturn = ExtractNameFromPath(pszTempPath,
  358. (LPSTR)strPath,
  359. bUnicode);
  360. if (FAILED(hresReturn)) {
  361. hresReturn = E_INVALIDARG;
  362. }
  363. else {
  364. g_LockMasterResource.WriteLock();
  365. hHandleObject = GetHandleObject(hMDHandle);
  366. if(hHandleObject != NULL)
  367. {
  368. hresReturn = AddObjectToDataBase(hMDHandle,
  369. hHandleObject,
  370. (LPSTR)pszMDPath,
  371. bUnicode);
  372. if (SUCCEEDED(hresReturn)) {
  373. g_dwSystemChangeNumber++;
  374. INCREMENT_SCHEMA_CHANGE_NUMBER(hMDHandle,
  375. hHandleObject,
  376. (LPSTR)pszMDPath,
  377. bUnicode);
  378. }
  379. }
  380. else
  381. {
  382. hresReturn = E_HANDLE;
  383. }
  384. g_LockMasterResource.WriteUnlock();
  385. }
  386. }
  387. return hresReturn;
  388. }
  389. HRESULT STDMETHODCALLTYPE
  390. CMDCOM::ComMDDeleteMetaObjectA(
  391. /* [in] */ METADATA_HANDLE hMDHandle,
  392. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDPath)
  393. {
  394. return ComMDDeleteMetaObjectD(hMDHandle,
  395. pszMDPath,
  396. FALSE);
  397. }
  398. HRESULT STDMETHODCALLTYPE
  399. CMDCOM::ComMDDeleteMetaObjectW(
  400. /* [in] */ METADATA_HANDLE hMDHandle,
  401. /* [string][in][unique] */ LPCWSTR pszMDPath)
  402. {
  403. return ComMDDeleteMetaObjectD(hMDHandle,
  404. (PBYTE)pszMDPath,
  405. TRUE);
  406. }
  407. HRESULT
  408. CMDCOM::ComMDDeleteMetaObjectD(IN METADATA_HANDLE hMDHandle,
  409. IN PBYTE pszMDPath,
  410. IN BOOL bUnicode)
  411. /*++
  412. Routine Description:
  413. Deletes a meta object and all of its data. Recursively deletes all descendants.
  414. Arguments:
  415. Handle - A handle returned by MDOpenMetaObject with write permission.
  416. Path - Path of object to be deleted, relative to the path of Handle.
  417. Must not be NULL.
  418. eg. "Root Object/Child/GrandChild"
  419. Return Value:
  420. DWORD - Return Code
  421. ERROR_SUCCESS
  422. MD_ERROR_NOT_INITIALIZED
  423. ERROR_INVALID_PARAMETER
  424. ERROR_PATH_NOT_FOUND
  425. ERROR_ACCESS_DENIED
  426. Notes:
  427. METADATA_MASTER_ROOT_HANDLE is not valid for this operation.
  428. --*/
  429. {
  430. HRESULT hresReturn;
  431. if (g_dwInitialized == 0) {
  432. hresReturn = MD_ERROR_NOT_INITIALIZED;
  433. }
  434. else if ((LPSTR)pszMDPath == NULL) {
  435. hresReturn = E_INVALIDARG;
  436. }
  437. else {
  438. g_LockMasterResource.WriteLock();
  439. CMDHandle *hMDHandleObject = GetHandleObject(hMDHandle);
  440. if(hMDHandleObject != NULL)
  441. {
  442. hresReturn = RemoveObjectFromDataBase(hMDHandle,
  443. hMDHandleObject,
  444. (LPSTR)pszMDPath,
  445. bUnicode);
  446. }
  447. else
  448. {
  449. hresReturn = E_HANDLE;
  450. }
  451. if (SUCCEEDED(hresReturn)) {
  452. g_dwSystemChangeNumber++;
  453. INCREMENT_SCHEMA_CHANGE_NUMBER(hMDHandle,
  454. hMDHandleObject,
  455. (LPSTR)pszMDPath,
  456. bUnicode);
  457. }
  458. g_LockMasterResource.WriteUnlock();
  459. }
  460. return hresReturn;
  461. }
  462. HRESULT STDMETHODCALLTYPE
  463. CMDCOM::ComMDDeleteChildMetaObjectsA(
  464. /* [in] */ METADATA_HANDLE hMDHandle,
  465. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDPath)
  466. {
  467. return ComMDDeleteChildMetaObjectsD(hMDHandle,
  468. pszMDPath,
  469. FALSE);
  470. }
  471. HRESULT STDMETHODCALLTYPE
  472. CMDCOM::ComMDDeleteChildMetaObjectsW(
  473. /* [in] */ METADATA_HANDLE hMDHandle,
  474. /* [string][in][unique] */ LPCWSTR pszMDPath)
  475. {
  476. return ComMDDeleteChildMetaObjectsD(hMDHandle,
  477. (PBYTE)pszMDPath,
  478. TRUE);
  479. }
  480. HRESULT STDMETHODCALLTYPE
  481. CMDCOM::ComMDDeleteChildMetaObjectsD(
  482. /* [in] */ METADATA_HANDLE hMDHandle,
  483. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDPath,
  484. IN BOOL bUnicode)
  485. /*++
  486. Routine Description:
  487. Deletes all child meta objects of the specified object, with all of their
  488. data. Recursively deletes all descendants of the child objects.
  489. Arguments:
  490. Handle - A handle returned by MDOpenMetaObject with write permission.
  491. Path - Path of the parent of the objects to be deleted, relative to the path of Handle.
  492. eg. "Root Object/Child"
  493. Return Value:
  494. DWORD - Return Code
  495. ERROR_SUCCESS
  496. MD_ERROR_NOT_INITIALIZED
  497. ERROR_PATH_NOT_FOUND
  498. ERROR_ACCESS_DENIED
  499. Notes:
  500. METADATA_MASTER_ROOT_HANDLE is not valid for this operation.
  501. --*/
  502. {
  503. HRESULT hresReturn;
  504. LPSTR pszPath = (LPSTR)pszMDPath;
  505. CMDBaseObject *pboParent;
  506. CMDBaseObject *pboChild;
  507. CMDHandle *phoHandle;
  508. if (g_dwInitialized == 0) {
  509. hresReturn = MD_ERROR_NOT_INITIALIZED;
  510. }
  511. else {
  512. g_LockMasterResource.WriteLock();
  513. hresReturn = GetObjectFromPath(pboParent, hMDHandle, METADATA_PERMISSION_WRITE, pszPath, bUnicode);
  514. if (SUCCEEDED(hresReturn)) {
  515. phoHandle = GetHandleObject(hMDHandle);
  516. MD_ASSERT (phoHandle != NULL);
  517. while ((pboChild = pboParent->EnumChildObject(0)) != NULL) {
  518. MD_REQUIRE(pboParent->RemoveChildObject(pboChild) == ERROR_SUCCESS);
  519. if (phoHandle->SetChangeData(pboChild, MD_CHANGE_TYPE_DELETE_OBJECT, 0) != ERROR_SUCCESS) {
  520. delete(pboChild);
  521. }
  522. }
  523. g_dwSystemChangeNumber++;
  524. INCREMENT_SCHEMA_CHANGE_NUMBER(hMDHandle,
  525. phoHandle,
  526. (LPSTR)pszMDPath,
  527. bUnicode);
  528. }
  529. g_LockMasterResource.WriteUnlock();
  530. }
  531. return hresReturn;
  532. }
  533. HRESULT STDMETHODCALLTYPE
  534. CMDCOM::ComMDEnumMetaObjectsA(
  535. /* [in] */ METADATA_HANDLE hMDHandle,
  536. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDPath,
  537. /* [size_is][out] */ unsigned char __RPC_FAR *pszMDName,
  538. /* [in] */ DWORD dwMDEnumObjectIndex)
  539. {
  540. return ComMDEnumMetaObjectsD(hMDHandle,
  541. pszMDPath,
  542. pszMDName,
  543. dwMDEnumObjectIndex,
  544. FALSE);
  545. }
  546. HRESULT STDMETHODCALLTYPE
  547. CMDCOM::ComMDEnumMetaObjectsW(
  548. /* [in] */ METADATA_HANDLE hMDHandle,
  549. /* [string][in][unique] */ LPCWSTR pszMDPath,
  550. /* [size_is][out] */ LPWSTR pszMDName,
  551. /* [in] */ DWORD dwMDEnumObjectIndex)
  552. {
  553. return ComMDEnumMetaObjectsD(hMDHandle,
  554. (PBYTE)pszMDPath,
  555. (PBYTE)pszMDName,
  556. dwMDEnumObjectIndex,
  557. TRUE);
  558. }
  559. HRESULT STDMETHODCALLTYPE
  560. CMDCOM::ComMDEnumMetaObjectsD(
  561. /* [in] */ METADATA_HANDLE hMDHandle,
  562. /* [size_is][in] */ unsigned char __RPC_FAR *pszMDPath,
  563. /* [size_is][out] */ unsigned char __RPC_FAR *pszMDName,
  564. /* [in] */ DWORD dwMDEnumObjectIndex,
  565. IN BOOL bUnicode)
  566. /*++
  567. Routine Description:
  568. Enumerates all child metaobjects once per call. Child Objects are numbers from 0 to NumObjects - 1, where
  569. NumObjects is the number of current child objects. If EnumObjectIndex is >= NumObjects, ERROR_NO_MORE_ITEMS
  570. is returned.
  571. Arguments:
  572. Handle - METADATA_MASTER_ROOT_HANDLE or a handle returned by MDOpenMetaObject with read permission.
  573. Path - Path of parent object, relative to the path of Handle.
  574. eg. "Root Object/Child/GrandChild"
  575. Name - Buffer where the Name of the object is returned. Must be at least METADATA_MAX_NAME_LEN characters long.
  576. EnumObjectIndex - Index of the value to be retrieved. The caller is expected to set this to 0 before the first call and increment
  577. it by 1 on each successive call until ERROR_NO_MORE_ITEMS is returned.
  578. Return Value:
  579. DWORD - Return Code
  580. ERROR_SUCCESS
  581. MD_ERROR_NOT_INITIALIZED
  582. ERROR_INVALID_PARAMETER
  583. ERROR_ACCESS_DENIED
  584. ERROR_PATH_NOT_FOUND
  585. ERROR_NO_MORE_ITEMS
  586. Notes:
  587. METADATA_MASTER_ROOT_HANDLE is a valid handle, but provides no gaurantee that other threads will
  588. not also change things. If a consistent data state is desired, use a handle returned by MDOpenMetaObject.
  589. --*/
  590. {
  591. HRESULT hresReturn;
  592. LPSTR pszPath = (LPSTR)pszMDPath;
  593. if (g_dwInitialized == 0) {
  594. hresReturn = MD_ERROR_NOT_INITIALIZED;
  595. }
  596. else if ((LPSTR)pszMDName == NULL) {
  597. hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
  598. }
  599. else {
  600. g_LockMasterResource.ReadLock();
  601. CMDBaseObject *pboAffected, *pboChild;
  602. hresReturn = GetObjectFromPath(pboAffected, hMDHandle, METADATA_PERMISSION_READ, pszPath, bUnicode);
  603. if ( SUCCEEDED(hresReturn) && ( pboAffected == NULL ) )
  604. {
  605. hresReturn = E_FAIL;
  606. }
  607. if (SUCCEEDED(hresReturn)) {
  608. pboChild = pboAffected->EnumChildObject(dwMDEnumObjectIndex);
  609. if (pboChild != NULL) {
  610. PVOID pvName = (PVOID)pboChild->GetName(bUnicode);
  611. if (pvName == NULL) {
  612. hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  613. }
  614. else {
  615. hresReturn = ERROR_SUCCESS;
  616. if (bUnicode) {
  617. if( wcslen( (LPWSTR)pvName ) < METADATA_MAX_NAME_LEN )
  618. {
  619. wcscpy((LPWSTR)pszMDName, (LPWSTR)pvName);
  620. }
  621. else
  622. {
  623. hresReturn = RETURNCODETOHRESULT( ERROR_INSUFFICIENT_BUFFER );
  624. }
  625. }
  626. else {
  627. if( strlen( (LPSTR)pvName ) < METADATA_MAX_NAME_LEN )
  628. {
  629. MD_STRCPY((LPSTR)pszMDName, (LPSTR)pvName);
  630. }
  631. else
  632. {
  633. hresReturn = RETURNCODETOHRESULT( ERROR_INSUFFICIENT_BUFFER );
  634. }
  635. }
  636. }
  637. }
  638. else {
  639. hresReturn = RETURNCODETOHRESULT(ERROR_NO_MORE_ITEMS);
  640. }
  641. }
  642. g_LockMasterResource.ReadUnlock();
  643. }
  644. return hresReturn;
  645. }
  646. HRESULT STDMETHODCALLTYPE
  647. CMDCOM::ComMDCopyMetaObjectA(
  648. /* [in] */ METADATA_HANDLE hMDSourceHandle,
  649. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDSourcePath,
  650. /* [in] */ METADATA_HANDLE hMDDestHandle,
  651. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDDestPath,
  652. /* [in] */ BOOL bMDOverwriteFlag,
  653. /* [in] */ BOOL bMDCopyFlag)
  654. {
  655. return ComMDCopyMetaObjectD(hMDSourceHandle,
  656. pszMDSourcePath,
  657. hMDDestHandle,
  658. pszMDDestPath,
  659. bMDOverwriteFlag,
  660. bMDCopyFlag,
  661. FALSE);
  662. }
  663. HRESULT STDMETHODCALLTYPE
  664. CMDCOM::ComMDCopyMetaObjectW(
  665. /* [in] */ METADATA_HANDLE hMDSourceHandle,
  666. /* [string][in][unique] */ LPCWSTR pszMDSourcePath,
  667. /* [in] */ METADATA_HANDLE hMDDestHandle,
  668. /* [string][in][unique] */ LPCWSTR pszMDDestPath,
  669. /* [in] */ BOOL bMDOverwriteFlag,
  670. /* [in] */ BOOL bMDCopyFlag)
  671. {
  672. return ComMDCopyMetaObjectD(hMDSourceHandle,
  673. (PBYTE)pszMDSourcePath,
  674. hMDDestHandle,
  675. (PBYTE)pszMDDestPath,
  676. bMDOverwriteFlag,
  677. bMDCopyFlag,
  678. TRUE);
  679. }
  680. HRESULT STDMETHODCALLTYPE
  681. CMDCOM::ComMDCopyMetaObjectD(
  682. /* [in] */ METADATA_HANDLE hMDSourceHandle,
  683. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDSourcePath,
  684. /* [in] */ METADATA_HANDLE hMDDestHandle,
  685. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDDestPath,
  686. /* [in] */ BOOL bMDOverwriteFlag,
  687. /* [in] */ BOOL bMDCopyFlag,
  688. IN BOOL bUnicode)
  689. /*++
  690. Routine Description:
  691. Copies or moves Source meta object and it's data and descendants to Dest. The
  692. copied object is a child of Dest.
  693. Arguments:
  694. SourceHandle - The handle or the object to be copied. If copyflag is specified, read permission
  695. is requried. If not, read/write permission is required.
  696. SourcePath - Path of the object to be copied, relative to the path of SourceHandle.
  697. eg. "Root Object/Child/GrandChild"
  698. DestHandle - The handle of the new location for the object. Write permission is required.
  699. DestPath - The path of the new location for the object, relative to the path of
  700. DestHandle. The new object will be a child of the object specified by
  701. DestHandle/DestPath. Must not be a descendant of SourceHandle/SourePath.
  702. eg. "Root Object/Child2"
  703. OverwriteFlag - Determines the behavior if the a meta object with the same name as Source is
  704. already a child of Dest.
  705. If TRUE, the existing object and all of its data and
  706. descandants are deleted prior to copying/moving Source.
  707. If FALSE, the existing object, data, and descendants remain, and Source is merged
  708. in. In cases of data conflicts, the Source data overwrites the Dest data.
  709. CopyFlag - Determines whether Source is deleted from its original location.
  710. If TRUE, a copy is performed. Source is not deleted from its original location.
  711. If FALSE, a move is performed. Source is deleted from its original location.
  712. Return Value:
  713. DWORD - Return Code
  714. ERROR_SUCCESS
  715. MD_ERROR_NOT_INITIALIZED
  716. ERROR_INVALID_PARAMETER
  717. ERROR_ACCESS_DENIED
  718. ERROR_NOT_ENOUGH_MEMORY
  719. ERROR_PATH_NOT_FOUND
  720. ERROR_DUP_NAME
  721. Notes:
  722. --*/
  723. {
  724. return CopyMetaObject(
  725. hMDSourceHandle,
  726. pszMDSourcePath,
  727. true,
  728. NULL,
  729. hMDDestHandle,
  730. pszMDDestPath,
  731. bMDOverwriteFlag,
  732. bMDCopyFlag,
  733. bUnicode);
  734. }
  735. HRESULT STDMETHODCALLTYPE
  736. CMDCOM::ComMDRenameMetaObjectA(
  737. /* [in] */ METADATA_HANDLE hMDHandle,
  738. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDPath,
  739. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDNewName)
  740. {
  741. return ComMDRenameMetaObjectD(hMDHandle,
  742. pszMDPath,
  743. pszMDNewName,
  744. FALSE);
  745. }
  746. HRESULT STDMETHODCALLTYPE
  747. CMDCOM::ComMDRenameMetaObjectW(
  748. /* [in] */ METADATA_HANDLE hMDHandle,
  749. /* [string][in][unique] */ LPCWSTR pszMDPath,
  750. /* [string][in][unique] */ LPCWSTR pszMDNewName)
  751. {
  752. return ComMDRenameMetaObjectD(hMDHandle,
  753. (PBYTE)pszMDPath,
  754. (PBYTE)pszMDNewName,
  755. TRUE);
  756. }
  757. HRESULT STDMETHODCALLTYPE
  758. CMDCOM::ComMDRenameMetaObjectD(
  759. /* [in] */ METADATA_HANDLE hMDHandle,
  760. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDPath,
  761. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDNewName,
  762. IN BOOL bUnicode)
  763. {
  764. HRESULT hresReturn = ERROR_SUCCESS;
  765. LPSTR pszPath = (LPSTR)pszMDPath;
  766. if (g_dwInitialized == 0) {
  767. hresReturn = MD_ERROR_NOT_INITIALIZED;
  768. }
  769. else if (((LPSTR)pszMDNewName == NULL) ||
  770. //
  771. // ExtractNameFromPath, below, checks name length so don't need to
  772. // check that here.
  773. //
  774. (bUnicode &&
  775. ((wcschr((LPWSTR)pszMDNewName, MD_PATH_DELIMETERW) != NULL) ||
  776. (wcschr((LPWSTR)pszMDNewName, MD_ALT_PATH_DELIMETERW) != NULL))) ||
  777. (!bUnicode &&
  778. ((MD_STRCHR((LPSTR)pszMDNewName, MD_PATH_DELIMETERA) != NULL) ||
  779. (MD_STRCHR((LPSTR)pszMDNewName, MD_ALT_PATH_DELIMETERA) != NULL)))) {
  780. hresReturn = E_INVALIDARG;
  781. }
  782. else {
  783. WCHAR strName[METADATA_MAX_NAME_LEN];
  784. LPSTR pszNewName = (LPSTR)pszMDNewName;
  785. LPSTR pszTempName = pszNewName;
  786. hresReturn = ExtractNameFromPath(pszTempName, (LPSTR)strName, bUnicode);
  787. if (SUCCEEDED(hresReturn)) {
  788. g_LockMasterResource.WriteLock();
  789. CMDBaseObject *pboAffected, *pboParent;
  790. hresReturn = GetObjectFromPath(pboAffected, hMDHandle, METADATA_PERMISSION_WRITE, pszPath, bUnicode);
  791. if (SUCCEEDED(hresReturn)) {
  792. pboParent = pboAffected->GetParent();
  793. if ( pboParent == NULL) {
  794. //
  795. // Can't rename MasterRoot
  796. //
  797. hresReturn = E_INVALIDARG;
  798. }
  799. else {
  800. if (pboAffected->GetParent()->GetChildObject(pszNewName, &hresReturn, bUnicode) != NULL) {
  801. hresReturn = RETURNCODETOHRESULT(ERROR_ALREADY_EXISTS);
  802. }
  803. if (SUCCEEDED(hresReturn)) {
  804. BUFFER OriginalKeyName;
  805. DWORD dwStringLen = 0;
  806. hresReturn= GetObjectPath(pboAffected,
  807. &OriginalKeyName,
  808. dwStringLen,
  809. g_pboMasterRoot,
  810. bUnicode);
  811. if (SUCCEEDED(hresReturn)) {
  812. //
  813. // First Remove the object, to get it out of the hash table.
  814. //
  815. pboParent->RemoveChildObjectFromHash( pboAffected );
  816. //
  817. // Must use pszMDNewName, as this does not include delimeters
  818. //
  819. if (!pboAffected->SetName((LPSTR)pszMDNewName, bUnicode)) {
  820. hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  821. //
  822. // Attempt to reinsert the object
  823. // Preserve previous error code by ignoreing this one.
  824. //
  825. pboParent->AddChildObjectToHash(pboAffected);
  826. }
  827. else {
  828. CMDHandle *phoHandle;
  829. //
  830. // Reinsert the object with the new name.
  831. //
  832. hresReturn = pboParent->AddChildObjectToHash( pboAffected );
  833. phoHandle = GetHandleObject(hMDHandle);
  834. g_dwSystemChangeNumber++;
  835. MD_ASSERT(phoHandle != NULL);
  836. INCREMENT_SCHEMA_CHANGE_NUMBER(hMDHandle,
  837. phoHandle,
  838. (LPSTR)pszMDNewName,
  839. bUnicode
  840. );
  841. phoHandle->SetChangeData(pboAffected, MD_CHANGE_TYPE_RENAME_OBJECT,
  842. 0, (LPWSTR)OriginalKeyName.QueryPtr ());
  843. }
  844. }
  845. }
  846. }
  847. }
  848. g_LockMasterResource.WriteUnlock();
  849. }
  850. }
  851. return hresReturn;
  852. }
  853. HRESULT STDMETHODCALLTYPE
  854. CMDCOM::ComMDSetMetaDataA(
  855. /* [in] */ METADATA_HANDLE hMDHandle,
  856. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDPath,
  857. /* [in] */ PMETADATA_RECORD pmdrMDData)
  858. {
  859. return ComMDSetMetaDataD(hMDHandle,
  860. pszMDPath,
  861. pmdrMDData,
  862. FALSE);
  863. }
  864. HRESULT STDMETHODCALLTYPE
  865. CMDCOM::ComMDSetMetaDataW(
  866. /* [in] */ METADATA_HANDLE hMDHandle,
  867. /* [string][in][unique] */ LPCWSTR pszMDPath,
  868. /* [in] */ PMETADATA_RECORD pmdrMDData)
  869. {
  870. return ComMDSetMetaDataD(hMDHandle,
  871. (PBYTE)pszMDPath,
  872. pmdrMDData,
  873. TRUE);
  874. }
  875. HRESULT STDMETHODCALLTYPE
  876. CMDCOM::ComMDSetMetaDataD(
  877. /* [in] */ METADATA_HANDLE hMDHandle,
  878. /* [size_is][in] */ unsigned char __RPC_FAR *pszMDPath,
  879. /* [in] */ PMETADATA_RECORD pmdrMDData,
  880. IN BOOL bUnicode)
  881. /*++
  882. Routine Description:
  883. Sets a data object.
  884. If data of that name does not already exist, it creates and
  885. inserts a data object into the list of data objects of that type.
  886. If data of that name aready exists, it sets the new data values.
  887. Arguments:
  888. Handle - A handle returned by MDOpenMetaObject with write permission.
  889. Path - The path of the meta object with which this data is associated, relative to the
  890. path of Handle.
  891. Data - The data to set. See IMD.H.
  892. Return Value:
  893. DWORD - ERROR_SUCCESS
  894. MD_ERROR_NOT_INITIALIZED
  895. ERROR_INVALID_PARAMETER
  896. ERROR_PATH_NOT_FOUND
  897. ERROR_ACCESS_DENIED
  898. ERROR_NOT_ENOUGH_MEMORY
  899. MD_ERROR_CANNOT_REMOVE_SECURE_ATTRIBUTE
  900. Notes:
  901. METADATA_MASTER_ROOT_HANDLE is not valid for this operation.
  902. Duplicate data names are not allowed, even for different types.
  903. --*/
  904. {
  905. HRESULT hresReturn;
  906. CMDHandle *hHandleObject;
  907. LPSTR pszPath = (LPSTR)pszMDPath;
  908. if (g_dwInitialized == 0) {
  909. hresReturn = MD_ERROR_NOT_INITIALIZED;
  910. }
  911. else if (!ValidateData(pmdrMDData, bUnicode)) {
  912. hresReturn = E_INVALIDARG;
  913. }
  914. else {
  915. g_LockMasterResource.WriteLock();
  916. CMDBaseObject *AffectedObject = NULL;
  917. hHandleObject = GetHandleObject(hMDHandle);
  918. if(hHandleObject != NULL)
  919. {
  920. hresReturn = GetObjectFromPathWithHandle(AffectedObject,
  921. hMDHandle,
  922. hHandleObject,
  923. METADATA_PERMISSION_WRITE,
  924. pszPath,
  925. bUnicode);
  926. }
  927. else
  928. {
  929. hresReturn = E_HANDLE;
  930. }
  931. if (hresReturn == RETURNCODETOHRESULT(ERROR_PATH_NOT_FOUND)) {
  932. pszPath = (LPSTR)pszMDPath;
  933. MD_ASSERT(pszMDPath != NULL);
  934. hresReturn = AddObjectToDataBase(hMDHandle,
  935. hHandleObject,
  936. (LPSTR)pszMDPath,
  937. bUnicode);
  938. if (SUCCEEDED(hresReturn)) {
  939. g_dwSystemChangeNumber++;
  940. INCREMENT_SCHEMA_CHANGE_NUMBER(hMDHandle,
  941. hHandleObject,
  942. (LPSTR)pszMDPath,
  943. bUnicode);
  944. hresReturn = GetObjectFromPath(AffectedObject, hMDHandle, METADATA_PERMISSION_WRITE, pszPath, bUnicode);
  945. MD_ASSERT(SUCCEEDED(hresReturn));
  946. }
  947. }
  948. if (SUCCEEDED(hresReturn) && AffectedObject) {
  949. hresReturn = AffectedObject->SetDataObject(pmdrMDData, bUnicode);
  950. }
  951. if (SUCCEEDED(hresReturn)) {
  952. g_dwSystemChangeNumber++;
  953. INCREMENT_SCHEMA_CHANGE_NUMBER(hMDHandle,
  954. hHandleObject,
  955. (LPSTR)pszMDPath,
  956. bUnicode);
  957. hHandleObject = GetHandleObject( hMDHandle );
  958. if( !hHandleObject )
  959. {
  960. hresReturn = MD_ERROR_DATA_NOT_FOUND;
  961. }
  962. else
  963. {
  964. hHandleObject->SetChangeData(AffectedObject, MD_CHANGE_TYPE_SET_DATA, pmdrMDData->dwMDIdentifier);
  965. }
  966. }
  967. g_LockMasterResource.WriteUnlock();
  968. }
  969. return hresReturn;
  970. }
  971. HRESULT STDMETHODCALLTYPE
  972. CMDCOM::ComMDGetMetaDataA(
  973. /* [in] */ METADATA_HANDLE hMDHandle,
  974. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDPath,
  975. /* [out][in] */ PMETADATA_RECORD pmdrMDData,
  976. /* [out] */ DWORD __RPC_FAR *pdwMDRequiredDataLen)
  977. {
  978. return ComMDGetMetaDataD(hMDHandle,
  979. pszMDPath,
  980. pmdrMDData,
  981. pdwMDRequiredDataLen,
  982. FALSE);
  983. }
  984. HRESULT STDMETHODCALLTYPE
  985. CMDCOM::ComMDGetMetaDataW(
  986. /* [in] */ METADATA_HANDLE hMDHandle,
  987. /* [string][in][unique] */ LPCWSTR pszMDPath,
  988. /* [out][in] */ PMETADATA_RECORD pmdrMDData,
  989. /* [out] */ DWORD __RPC_FAR *pdwMDRequiredDataLen)
  990. {
  991. return ComMDGetMetaDataD(hMDHandle,
  992. (PBYTE)pszMDPath,
  993. pmdrMDData,
  994. pdwMDRequiredDataLen,
  995. TRUE);
  996. }
  997. HRESULT STDMETHODCALLTYPE
  998. CMDCOM::ComMDGetMetaDataD(
  999. /* [in] */ METADATA_HANDLE hMDHandle,
  1000. /* [string][in] */ unsigned char __RPC_FAR *pszMDPath,
  1001. /* [out][in] */ PMETADATA_RECORD pmdrMDData,
  1002. /* [out] */ DWORD __RPC_FAR *pdwMDRequiredDataLen,
  1003. IN BOOL bUnicode)
  1004. /*++
  1005. Routine Description:
  1006. Gets one metadata value.
  1007. Arguments:
  1008. Handle - METADATA_MASTER_ROOT_HANDLE or a handle returned by MDOpenMetaObject with read permission.
  1009. Path - The path of the meta object with which this data is associated, relative to the
  1010. path of Handle.
  1011. Data - The data structure. See IMD.H.
  1012. RequiredDataLen - If ERROR_INSUFFICIENT_BUFFER is returned, this is set to the required buffer size.
  1013. Return Value:
  1014. DWORD - ERROR_SUCCESS
  1015. MD_ERROR_NOT_INITIALIZED
  1016. ERROR_INVALID_PARAMETER
  1017. ERROR_ACCESS_DENIED
  1018. ERROR_PATH_NOT_FOUND
  1019. MD_ERROR_DATA_NOT_FOUND
  1020. ERROR_INSUFFICIENT_BUFFER
  1021. Notes:
  1022. METADATA_MASTER_ROOT_HANDLE is a valid handle, but provides no gaurantee that other threads will
  1023. not also change things. If a consistent data state is desired, use a handle returned by
  1024. ComMDOpenMetaObject.
  1025. --*/
  1026. {
  1027. HRESULT hresReturn;
  1028. CMDBaseData *pbdRetrieve = NULL;
  1029. CMDBaseObject *pboAssociated = NULL;
  1030. LPSTR pszPath = (LPSTR)pszMDPath;
  1031. BOOL bInheritableOnly = FALSE;
  1032. if (g_dwInitialized == 0) {
  1033. hresReturn = MD_ERROR_NOT_INITIALIZED;
  1034. }
  1035. else if ((pmdrMDData == NULL) ||
  1036. ((pmdrMDData->dwMDDataLen != 0) && (pmdrMDData->pbMDData == NULL)) ||
  1037. ((pmdrMDData->dwMDAttributes & METADATA_PARTIAL_PATH) &&
  1038. !(pmdrMDData->dwMDAttributes & METADATA_INHERIT)) ||
  1039. (pmdrMDData->dwMDDataType >= INVALID_END_METADATA)) {
  1040. hresReturn = E_INVALIDARG;
  1041. }
  1042. else {
  1043. g_LockMasterResource.ReadLock();
  1044. CMDBaseObject *pboAffected = NULL;
  1045. hresReturn = GetObjectFromPath(pboAffected, hMDHandle, METADATA_PERMISSION_READ, pszPath, bUnicode);
  1046. if ( SUCCEEDED(hresReturn) && ( pboAffected == NULL ) )
  1047. {
  1048. hresReturn = E_FAIL;
  1049. }
  1050. if (SUCCEEDED(hresReturn)) {
  1051. //
  1052. // Found the object, get the data.
  1053. //
  1054. pbdRetrieve = pboAffected->GetDataObject(pmdrMDData->dwMDIdentifier,
  1055. pmdrMDData->dwMDAttributes,
  1056. pmdrMDData->dwMDDataType,
  1057. &pboAssociated);
  1058. }
  1059. else if ((hresReturn == (RETURNCODETOHRESULT(ERROR_PATH_NOT_FOUND))) && (pboAffected != NULL) &&
  1060. (pmdrMDData->dwMDAttributes & METADATA_PARTIAL_PATH)) {
  1061. //
  1062. // Object not found, get inheritable data.
  1063. //
  1064. pbdRetrieve = pboAffected->GetInheritableDataObject(pmdrMDData->dwMDIdentifier,
  1065. pmdrMDData->dwMDDataType,
  1066. &pboAssociated);
  1067. hresReturn = ERROR_SUCCESS;
  1068. bInheritableOnly = TRUE;
  1069. }
  1070. if (SUCCEEDED(hresReturn)) {
  1071. if (pbdRetrieve == NULL) {
  1072. hresReturn = MD_ERROR_DATA_NOT_FOUND;
  1073. }
  1074. else {
  1075. PBYTE pbData = (PBYTE)(pbdRetrieve->GetData(bUnicode));
  1076. DWORD dwDataLen = pbdRetrieve->GetDataLen(bUnicode);
  1077. if (pbData == NULL) {
  1078. hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  1079. }
  1080. else {
  1081. if (((pmdrMDData->dwMDAttributes) & (pbdRetrieve->GetAttributes()) &
  1082. METADATA_REFERENCE) != 0) {
  1083. MD_ASSERT(((pbdRetrieve->GetAttributes()) & METADATA_INSERT_PATH) == 0);
  1084. pmdrMDData->pbMDData = (PBYTE) pbdRetrieve->GetData(bUnicode);
  1085. pbdRetrieve->IncrementReferenceCount();
  1086. pmdrMDData->dwMDDataTag = pbdRetrieve->GetMappingId();
  1087. }
  1088. else {
  1089. BUFFER bufData;
  1090. STRAU strData;
  1091. if ((pmdrMDData->dwMDAttributes & pbdRetrieve->GetAttributes() & METADATA_INSERT_PATH) != 0) {
  1092. hresReturn= InsertPathIntoData(&bufData,
  1093. &strData,
  1094. &pbData,
  1095. &dwDataLen,
  1096. pbdRetrieve,
  1097. hMDHandle,
  1098. pboAssociated,
  1099. bUnicode);
  1100. }
  1101. if (SUCCEEDED(hresReturn)) {
  1102. if (pmdrMDData->dwMDDataLen < dwDataLen) {
  1103. hresReturn = RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER);
  1104. pmdrMDData->dwMDDataLen = 0;
  1105. *pdwMDRequiredDataLen = dwDataLen;
  1106. }
  1107. else {
  1108. MD_COPY(pmdrMDData->pbMDData, pbData, dwDataLen);
  1109. pmdrMDData->dwMDDataTag = 0;
  1110. }
  1111. }
  1112. }
  1113. }
  1114. if (SUCCEEDED(hresReturn)) {
  1115. BOOL bIsInherited = FALSE;
  1116. if ((pmdrMDData->dwMDAttributes & METADATA_ISINHERITED) &&
  1117. (pmdrMDData->dwMDAttributes & METADATA_INHERIT)) {
  1118. //
  1119. // Set the ISINHERITED flag
  1120. //
  1121. if (bInheritableOnly) {
  1122. bIsInherited = TRUE;
  1123. }
  1124. else {
  1125. if (pboAffected->GetDataObject(pmdrMDData->dwMDIdentifier,
  1126. pmdrMDData->dwMDAttributes &
  1127. ~(METADATA_INHERIT | METADATA_PARTIAL_PATH),
  1128. pbdRetrieve->GetDataType()) == NULL) {
  1129. bIsInherited = TRUE;
  1130. }
  1131. }
  1132. }
  1133. pmdrMDData->dwMDAttributes =
  1134. (pbdRetrieve->GetAttributes() | ((bIsInherited) ? METADATA_ISINHERITED : 0));
  1135. pmdrMDData->dwMDUserType = pbdRetrieve->GetUserType();
  1136. pmdrMDData->dwMDDataType = pbdRetrieve->GetDataType();
  1137. pmdrMDData->dwMDDataLen = dwDataLen;
  1138. }
  1139. }
  1140. }
  1141. g_LockMasterResource.ReadUnlock();
  1142. }
  1143. return hresReturn;
  1144. }
  1145. HRESULT STDMETHODCALLTYPE
  1146. CMDCOM::ComMDEnumMetaDataA(
  1147. /* [in] */ METADATA_HANDLE hMDHandle,
  1148. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDPath,
  1149. /* [out][in] */ PMETADATA_RECORD pmdrMDData,
  1150. /* [in] */ DWORD dwMDEnumDataIndex,
  1151. /* [out] */ DWORD __RPC_FAR *pdwMDRequiredDataLen)
  1152. {
  1153. return ComMDEnumMetaDataD(hMDHandle,
  1154. pszMDPath,
  1155. pmdrMDData,
  1156. dwMDEnumDataIndex,
  1157. pdwMDRequiredDataLen,
  1158. FALSE);
  1159. }
  1160. HRESULT STDMETHODCALLTYPE
  1161. CMDCOM::ComMDEnumMetaDataW(
  1162. /* [in] */ METADATA_HANDLE hMDHandle,
  1163. /* [string][in][unique] */ LPCWSTR pszMDPath,
  1164. /* [out][in] */ PMETADATA_RECORD pmdrMDData,
  1165. /* [in] */ DWORD dwMDEnumDataIndex,
  1166. /* [out] */ DWORD __RPC_FAR *pdwMDRequiredDataLen)
  1167. {
  1168. return ComMDEnumMetaDataD(hMDHandle,
  1169. (PBYTE)pszMDPath,
  1170. pmdrMDData,
  1171. dwMDEnumDataIndex,
  1172. pdwMDRequiredDataLen,
  1173. TRUE);
  1174. }
  1175. HRESULT STDMETHODCALLTYPE
  1176. CMDCOM::ComMDEnumMetaDataD(
  1177. /* [in] */ METADATA_HANDLE hMDHandle,
  1178. /* [string][in] */ unsigned char __RPC_FAR *pszMDPath,
  1179. /* [out][in] */ PMETADATA_RECORD pmdrMDData,
  1180. /* [in] */ DWORD dwMDEnumDataIndex,
  1181. /* [out] */ DWORD __RPC_FAR *pdwMDRequiredDataLen,
  1182. IN BOOL bUnicode)
  1183. /*++
  1184. Routine Description:
  1185. Enumerates all metadata values once per call. Values are numbered from 0 to NumValues - 1, where
  1186. NumValues is the number of current valules. If EnumDataIndex is >= NumValues, ERROR_NO_MORE_ITEMS
  1187. is returned.
  1188. Arguments:
  1189. Handle - METADATA_MASTER_ROOT_HANDLE or a handle returned by MDOpenMetaObject with read permission.
  1190. Path - The path of the meta object with which this data is associated, , relative to the
  1191. path of Handle.
  1192. Data - The data structure. See IMD.H.
  1193. RequiredDataLen - If ERROR_INSUFFICIENT_BUFFER is returned, this is set to the required buffer size.
  1194. Return Value:
  1195. DWORD - ERROR_SUCCESS
  1196. MD_ERROR_NOT_INITIALIZED
  1197. ERROR_INVALID_PARAMETER
  1198. ERROR_PATH_NOT_FOUND
  1199. ERROR_ACCESS_DENIED
  1200. ERROR_INSUFFICIENT_BUFFER
  1201. ERROR_NO_MORE_ITEMS
  1202. Notes:
  1203. METADATA_MASTER_ROOT_HANDLE is a valid handle, but provides no gaurantee that other threads will
  1204. not also change things. If a consistent data state is desired, use a handle returned by MDOpenMetaObject.
  1205. --*/
  1206. {
  1207. HRESULT hresReturn;
  1208. CMDBaseData *pbdRetrieve = NULL;
  1209. CMDBaseObject *pboAssociated = NULL;
  1210. LPSTR pszPath = (LPSTR)pszMDPath;
  1211. BOOL bInheritableOnly = FALSE;
  1212. if (g_dwInitialized == 0) {
  1213. hresReturn = MD_ERROR_NOT_INITIALIZED;
  1214. }
  1215. else if ((pmdrMDData == NULL) ||
  1216. ((pmdrMDData->dwMDDataLen != 0) && (pmdrMDData->pbMDData == NULL)) ||
  1217. ((pmdrMDData->dwMDAttributes & METADATA_PARTIAL_PATH) &&
  1218. !(pmdrMDData->dwMDAttributes & METADATA_INHERIT)) ||
  1219. (pmdrMDData->dwMDDataType >= INVALID_END_METADATA)) {
  1220. hresReturn = E_INVALIDARG;
  1221. }
  1222. else {
  1223. g_LockMasterResource.ReadLock();
  1224. CMDBaseObject *pboAffected = NULL;
  1225. hresReturn = GetObjectFromPath(pboAffected, hMDHandle, METADATA_PERMISSION_READ, pszPath, bUnicode);
  1226. if ( SUCCEEDED(hresReturn) && ( pboAffected == NULL ) )
  1227. {
  1228. hresReturn = E_FAIL;
  1229. }
  1230. if (SUCCEEDED(hresReturn)) {
  1231. pbdRetrieve = pboAffected->EnumDataObject(dwMDEnumDataIndex,
  1232. pmdrMDData->dwMDAttributes,
  1233. pmdrMDData->dwMDUserType,
  1234. pmdrMDData->dwMDDataType,
  1235. &pboAssociated);
  1236. }
  1237. else if ((hresReturn == RETURNCODETOHRESULT(ERROR_PATH_NOT_FOUND)) && (pboAffected != NULL) &&
  1238. (pmdrMDData->dwMDAttributes & METADATA_PARTIAL_PATH)) {
  1239. pbdRetrieve = pboAffected->EnumInheritableDataObject(dwMDEnumDataIndex,
  1240. pmdrMDData->dwMDUserType,
  1241. pmdrMDData->dwMDDataType,
  1242. &pboAssociated);
  1243. hresReturn = ERROR_SUCCESS;
  1244. bInheritableOnly = TRUE;
  1245. }
  1246. if (SUCCEEDED(hresReturn)) {
  1247. if (pbdRetrieve == NULL) {
  1248. hresReturn = RETURNCODETOHRESULT(ERROR_NO_MORE_ITEMS);
  1249. }
  1250. else {
  1251. PBYTE pbData = (PBYTE)(pbdRetrieve->GetData(bUnicode));
  1252. DWORD dwDataLen = pbdRetrieve->GetDataLen(bUnicode);
  1253. if (pbData == NULL) {
  1254. hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  1255. }
  1256. else {
  1257. if (((pmdrMDData->dwMDAttributes) & (pbdRetrieve->GetAttributes()) &
  1258. METADATA_REFERENCE) != 0) {
  1259. MD_ASSERT(((pbdRetrieve->GetAttributes()) & METADATA_INSERT_PATH) == 0);
  1260. pmdrMDData->pbMDData = (PBYTE)pbdRetrieve->GetData(bUnicode);
  1261. pbdRetrieve->IncrementReferenceCount();
  1262. pmdrMDData->dwMDDataTag = pbdRetrieve->GetMappingId();
  1263. }
  1264. else {
  1265. BUFFER bufData;
  1266. STRAU strData;
  1267. if ((pmdrMDData->dwMDAttributes & pbdRetrieve->GetAttributes() & METADATA_INSERT_PATH) != 0) {
  1268. hresReturn= InsertPathIntoData(&bufData,
  1269. &strData,
  1270. &pbData,
  1271. &dwDataLen,
  1272. pbdRetrieve,
  1273. hMDHandle,
  1274. pboAssociated,
  1275. bUnicode);
  1276. }
  1277. if (SUCCEEDED(hresReturn)) {
  1278. if (pmdrMDData->dwMDDataLen < dwDataLen) {
  1279. hresReturn = RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER);
  1280. pmdrMDData->dwMDDataLen = 0;
  1281. *pdwMDRequiredDataLen = dwDataLen;
  1282. }
  1283. else {
  1284. MD_COPY(pmdrMDData->pbMDData, pbData, dwDataLen);
  1285. pmdrMDData->dwMDDataTag = 0;
  1286. }
  1287. }
  1288. }
  1289. }
  1290. if (SUCCEEDED(hresReturn)) {
  1291. BOOL bIsInherited = FALSE;
  1292. if ((pmdrMDData->dwMDAttributes & METADATA_ISINHERITED) &&
  1293. (pmdrMDData->dwMDAttributes & METADATA_INHERIT)) {
  1294. //
  1295. // Set the ISINHERITED flag
  1296. //
  1297. if (bInheritableOnly) {
  1298. bIsInherited = TRUE;
  1299. }
  1300. else {
  1301. if (pboAffected->GetDataObject(pbdRetrieve->GetIdentifier(),
  1302. pmdrMDData->dwMDAttributes &
  1303. ~(METADATA_INHERIT | METADATA_PARTIAL_PATH),
  1304. pbdRetrieve->GetDataType()) == NULL) {
  1305. bIsInherited = TRUE;
  1306. }
  1307. }
  1308. }
  1309. pmdrMDData->dwMDAttributes =
  1310. (pbdRetrieve->GetAttributes() | ((bIsInherited) ? METADATA_ISINHERITED : 0));
  1311. pmdrMDData->dwMDIdentifier = pbdRetrieve->GetIdentifier();
  1312. pmdrMDData->dwMDUserType = pbdRetrieve->GetUserType();
  1313. pmdrMDData->dwMDDataType = pbdRetrieve->GetDataType();
  1314. pmdrMDData->dwMDDataLen = dwDataLen;
  1315. hresReturn = ERROR_SUCCESS;
  1316. }
  1317. }
  1318. }
  1319. g_LockMasterResource.ReadUnlock();
  1320. }
  1321. return hresReturn;
  1322. }
  1323. HRESULT STDMETHODCALLTYPE
  1324. CMDCOM::ComMDDeleteMetaDataA(
  1325. /* [in] */ METADATA_HANDLE hMDHandle,
  1326. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDPath,
  1327. /* [in] */ DWORD dwMDIdentifier,
  1328. /* [in] */ DWORD dwMDDataType)
  1329. {
  1330. return ComMDDeleteMetaDataD(hMDHandle,
  1331. pszMDPath,
  1332. dwMDIdentifier,
  1333. dwMDDataType,
  1334. FALSE);
  1335. }
  1336. HRESULT STDMETHODCALLTYPE
  1337. CMDCOM::ComMDDeleteMetaDataW(
  1338. /* [in] */ METADATA_HANDLE hMDHandle,
  1339. /* [string][in][unique] */ LPCWSTR pszMDPath,
  1340. /* [in] */ DWORD dwMDIdentifier,
  1341. /* [in] */ DWORD dwMDDataType)
  1342. {
  1343. return ComMDDeleteMetaDataD(hMDHandle,
  1344. (PBYTE)pszMDPath,
  1345. dwMDIdentifier,
  1346. dwMDDataType,
  1347. TRUE);
  1348. }
  1349. HRESULT STDMETHODCALLTYPE
  1350. CMDCOM::ComMDDeleteMetaDataD(
  1351. /* [in] */ METADATA_HANDLE hMDHandle,
  1352. /* [string][in] */ unsigned char __RPC_FAR *pszMDPath,
  1353. /* [in] */ DWORD dwMDIdentifier,
  1354. /* [in] */ DWORD dwMDDataType,
  1355. IN BOOL bUnicode)
  1356. /*++
  1357. Routine Description:
  1358. Deletes a data object.
  1359. Arguments:
  1360. Handle - A handle returned by MDOpenMetaObject with write permission.
  1361. Path - The path of the meta object with which this data is associated, relative to the
  1362. path of Handle.
  1363. Identifier - The identifier of the data to remove.
  1364. DataType - Optional type of the data to remove. If specified, only data of that
  1365. type will be removed. See imd.h.
  1366. Return Value:
  1367. DWORD - ERROR_SUCCESS
  1368. MD_ERROR_NOT_INITIALIZED
  1369. ERROR_INVALID_PARAMETER
  1370. ERROR_PATH_NOT_FOUND
  1371. ERROR_ACCESS_DENIED
  1372. MD_ERROR_DATA_NOT_FOUND
  1373. Notes:
  1374. METADATA_MASTER_ROOT_HANDLE is not valid for this operation.
  1375. --*/
  1376. {
  1377. HRESULT hresReturn;
  1378. LPSTR pszPath = (LPSTR)pszMDPath;
  1379. if (g_dwInitialized == 0) {
  1380. hresReturn = MD_ERROR_NOT_INITIALIZED;
  1381. }
  1382. else if (dwMDDataType >= INVALID_END_METADATA) {
  1383. hresReturn = E_INVALIDARG;
  1384. }
  1385. else {
  1386. g_LockMasterResource.WriteLock();
  1387. CMDBaseObject *pboAffected;
  1388. hresReturn = GetObjectFromPath(pboAffected, hMDHandle, METADATA_PERMISSION_WRITE, pszPath, bUnicode);
  1389. if (SUCCEEDED(hresReturn)) {
  1390. if (pboAffected->RemoveDataObject(dwMDIdentifier, dwMDDataType, TRUE) != NULL) {
  1391. CMDHandle *phoHandle;
  1392. hresReturn = ERROR_SUCCESS;
  1393. g_dwSystemChangeNumber++;
  1394. phoHandle = GetHandleObject(hMDHandle);
  1395. if( !phoHandle )
  1396. {
  1397. hresReturn = MD_ERROR_DATA_NOT_FOUND;
  1398. }
  1399. else
  1400. {
  1401. phoHandle->SetChangeData(pboAffected, MD_CHANGE_TYPE_DELETE_DATA, dwMDIdentifier);
  1402. INCREMENT_SCHEMA_CHANGE_NUMBER(hMDHandle,
  1403. phoHandle,
  1404. (LPSTR)pszMDPath,
  1405. bUnicode);
  1406. }
  1407. }
  1408. else {
  1409. hresReturn = MD_ERROR_DATA_NOT_FOUND;
  1410. }
  1411. }
  1412. g_LockMasterResource.WriteUnlock();
  1413. }
  1414. return hresReturn;
  1415. }
  1416. HRESULT STDMETHODCALLTYPE
  1417. CMDCOM::ComMDGetAllMetaDataA(
  1418. /* [in] */ METADATA_HANDLE hMDHandle,
  1419. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDPath,
  1420. /* [in] */ DWORD dwMDAttributes,
  1421. /* [in] */ DWORD dwMDUserType,
  1422. /* [in] */ DWORD dwMDDataType,
  1423. /* [out] */ DWORD __RPC_FAR *pdwMDNumDataEntries,
  1424. /* [out] */ DWORD __RPC_FAR *pdwMDDataSetNumber,
  1425. /* [in] */ DWORD dwMDBufferSize,
  1426. /* [size_is][out] */ unsigned char __RPC_FAR *pbBuffer,
  1427. /* [out] */ DWORD __RPC_FAR *pdwMDRequiredBufferSize)
  1428. {
  1429. return ComMDGetAllMetaDataD(hMDHandle,
  1430. pszMDPath,
  1431. dwMDAttributes,
  1432. dwMDUserType,
  1433. dwMDDataType,
  1434. pdwMDNumDataEntries,
  1435. pdwMDDataSetNumber,
  1436. dwMDBufferSize,
  1437. pbBuffer,
  1438. pdwMDRequiredBufferSize,
  1439. FALSE);
  1440. }
  1441. HRESULT STDMETHODCALLTYPE
  1442. CMDCOM::ComMDGetAllMetaDataW(
  1443. /* [in] */ METADATA_HANDLE hMDHandle,
  1444. /* [string][in][unique] */ LPCWSTR pszMDPath,
  1445. /* [in] */ DWORD dwMDAttributes,
  1446. /* [in] */ DWORD dwMDUserType,
  1447. /* [in] */ DWORD dwMDDataType,
  1448. /* [out] */ DWORD __RPC_FAR *pdwMDNumDataEntries,
  1449. /* [out] */ DWORD __RPC_FAR *pdwMDDataSetNumber,
  1450. /* [in] */ DWORD dwMDBufferSize,
  1451. /* [size_is][out] */ unsigned char __RPC_FAR *pbBuffer,
  1452. /* [out] */ DWORD __RPC_FAR *pdwMDRequiredBufferSize)
  1453. {
  1454. return ComMDGetAllMetaDataD(hMDHandle,
  1455. (PBYTE)pszMDPath,
  1456. dwMDAttributes,
  1457. dwMDUserType,
  1458. dwMDDataType,
  1459. pdwMDNumDataEntries,
  1460. pdwMDDataSetNumber,
  1461. dwMDBufferSize,
  1462. pbBuffer,
  1463. pdwMDRequiredBufferSize,
  1464. TRUE);
  1465. }
  1466. HRESULT STDMETHODCALLTYPE
  1467. CMDCOM::ComMDGetAllMetaDataD(
  1468. /* [in] */ METADATA_HANDLE hMDHandle,
  1469. /* [string][in] */ unsigned char __RPC_FAR *pszMDPath,
  1470. /* [in] */ DWORD dwMDAttributes,
  1471. /* [in] */ DWORD dwMDUserType,
  1472. /* [in] */ DWORD dwMDDataType,
  1473. /* [out] */ DWORD __RPC_FAR *pdwMDNumDataEntries,
  1474. /* [out] */ DWORD __RPC_FAR *pdwMDDataSetNumber,
  1475. /* [in] */ DWORD dwMDBufferSize,
  1476. /* [size_is][out] */ unsigned char __RPC_FAR *pbBuffer,
  1477. /* [out] */ DWORD __RPC_FAR *pdwMDRequiredBufferSize,
  1478. IN BOOL bUnicode)
  1479. /*++
  1480. Routine Description:
  1481. Gets all data associated with a Meta Object.
  1482. Arguments:
  1483. Handle - METADATA_MASTER_ROOT_HANDLE or a handle returned by ComMDOpenMetaObject with read permission.
  1484. Path - The path of the meta object with which this data is associated, relative to the
  1485. path of Handle.
  1486. Attributes - The flags for the data. See imd.h.
  1487. UserType - The User Type for the data. If not set to ALL_METADATA, only metadata of the specified
  1488. User Type will be returned. Se imd.h.
  1489. DataType - The Type of the data. If not set to ALL_METADATA only metadata
  1490. of the specified Data Type will be returned. See imd.h.
  1491. NumDataEntries - On successful output, specifes the number of entries copied to Buffer.
  1492. DataSetNumber - A number associated with this data set. Can be used to identify common data sets.
  1493. Filled in if ERROR_SUCCESS or ERROR_INSUFFICIENT_BUFFER is returned. See ComMDGetDataSetNumber.
  1494. BufferSize - The size in bytes of buffer. If the return code is ERROR_INSUFFICIENT_BUFFER, this contains
  1495. the number of bytes needed.
  1496. Buffer - Buffer to store the data. On successful return it will
  1497. contain an array of METADATA_GETALL_RECORD.
  1498. RequiredBufferSize - If ERROR_INSUFFICIENT_BUFFER is returned, This contains
  1499. the required buffer length, in bytes.
  1500. Return Value:
  1501. DWORD - ERROR_SUCCESS
  1502. MD_ERROR_NOT_INITIALIZED
  1503. ERROR_INVALID_PARAMETER
  1504. ERROR_PATH_NOT_FOUND
  1505. ERROR_ACCESS_DENIED
  1506. ERROR_INSUFFICIENT_BUFFER
  1507. Notes:
  1508. METADATA_MASTER_ROOT_HANDLE is a valid handle, but provides no gaurantee that other threads will
  1509. not also change things. If a consistent data state is desired, use
  1510. a handle returned by ComMDOpenMetaObject.
  1511. DWORD data is aligned on non-Intel platforms. This may not hold true on remote clients.
  1512. --*/
  1513. {
  1514. BOOL fUseInternalStructure = !!(dwMDAttributes & METADATA_REFERENCE);
  1515. BOOL fNonSecureOnly = !!(dwMDAttributes & METADATA_NON_SECURE_ONLY);
  1516. HRESULT hresReturn;
  1517. BOOL bInheritableOnly = FALSE;
  1518. CMDBaseData *pbdCurrent;
  1519. DWORD i, dwNumDataObjects;
  1520. PVOID *ppvMainDataBuf = NULL;
  1521. LPSTR pszPath = (LPSTR)pszMDPath;
  1522. if (g_dwInitialized == 0) {
  1523. hresReturn = MD_ERROR_NOT_INITIALIZED;
  1524. }
  1525. else if ((pdwMDNumDataEntries == NULL) || ((dwMDBufferSize != 0) && (pbBuffer == NULL)) ||
  1526. ((dwMDAttributes & METADATA_PARTIAL_PATH) && !(dwMDAttributes & METADATA_INHERIT)) ||
  1527. (dwMDDataType >= INVALID_END_METADATA)) {
  1528. hresReturn = E_INVALIDARG;
  1529. }
  1530. else {
  1531. g_LockMasterResource.ReadLock();
  1532. CMDBaseObject *pboAffected = NULL;
  1533. hresReturn = GetObjectFromPath(pboAffected, hMDHandle, METADATA_PERMISSION_READ, pszPath, bUnicode);
  1534. if ( SUCCEEDED(hresReturn) && ( pboAffected == NULL ) )
  1535. {
  1536. hresReturn = E_FAIL;
  1537. }
  1538. if (SUCCEEDED(hresReturn)) {
  1539. if (pdwMDDataSetNumber != NULL) {
  1540. *pdwMDDataSetNumber = pboAffected->GetDataSetNumber();
  1541. }
  1542. bInheritableOnly = FALSE;
  1543. }
  1544. else if ((hresReturn == RETURNCODETOHRESULT(ERROR_PATH_NOT_FOUND)) &&
  1545. (pboAffected != NULL) &&
  1546. (dwMDAttributes & METADATA_PARTIAL_PATH)) {
  1547. if (pdwMDDataSetNumber != NULL) {
  1548. *pdwMDDataSetNumber = pboAffected->GetDescendantDataSetNumber();
  1549. }
  1550. bInheritableOnly = TRUE;
  1551. hresReturn = ERROR_SUCCESS;
  1552. }
  1553. if ( SUCCEEDED(hresReturn) )
  1554. {
  1555. ppvMainDataBuf = GetMainDataBuffer();
  1556. MD_ASSERT (ppvMainDataBuf != NULL);
  1557. if ( ppvMainDataBuf == NULL )
  1558. {
  1559. hresReturn = E_FAIL;
  1560. }
  1561. }
  1562. if (SUCCEEDED(hresReturn)) {
  1563. dwNumDataObjects = pboAffected->GetAllDataObjects(ppvMainDataBuf,
  1564. dwMDAttributes,
  1565. dwMDUserType,
  1566. dwMDDataType,
  1567. bInheritableOnly,
  1568. fNonSecureOnly
  1569. );
  1570. PBYTE pbEnd = pbBuffer + dwMDBufferSize;
  1571. PBYTE pbDataStart;
  1572. if (fUseInternalStructure)
  1573. {
  1574. pbDataStart = pbBuffer + (dwNumDataObjects * sizeof(METADATA_GETALL_INTERNAL_RECORD));
  1575. }
  1576. else
  1577. {
  1578. pbDataStart = pbBuffer + (dwNumDataObjects * sizeof(METADATA_GETALL_RECORD));
  1579. }
  1580. PBYTE pbNextDataStart = pbDataStart;
  1581. for (i = 0;
  1582. (i < dwNumDataObjects) ;
  1583. i++, pbDataStart = pbNextDataStart) {
  1584. pbdCurrent=(CMDBaseData *)GetItemFromDataBuffer(ppvMainDataBuf, i);
  1585. MD_ASSERT(pbdCurrent != NULL);
  1586. if ( pbdCurrent == NULL )
  1587. {
  1588. hresReturn = E_FAIL;
  1589. break;
  1590. }
  1591. DWORD dwDataLen = pbdCurrent->GetDataLen(bUnicode);
  1592. PBYTE pbData = (PBYTE)(pbdCurrent->GetData(bUnicode));
  1593. CMDBaseObject *pboAssociated;
  1594. BUFFER bufData;
  1595. STRAU strData;
  1596. if (pbData == NULL) {
  1597. hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  1598. break;
  1599. }
  1600. if ((dwMDAttributes & (pbdCurrent->GetAttributes()) &
  1601. METADATA_REFERENCE) == 0) {
  1602. if ((dwMDAttributes & pbdCurrent->GetAttributes() & METADATA_INSERT_PATH) != 0) {
  1603. //
  1604. // First do a get to get the metaobject associated with this data object
  1605. //
  1606. if (bInheritableOnly) {
  1607. MD_REQUIRE(pboAffected->GetInheritableDataObject(pbdCurrent->GetIdentifier(),
  1608. pbdCurrent->GetDataType(),
  1609. &pboAssociated) != NULL);
  1610. }
  1611. else {
  1612. MD_REQUIRE(pboAffected->GetDataObject(pbdCurrent->GetIdentifier(),
  1613. dwMDAttributes,
  1614. pbdCurrent->GetDataType(),
  1615. &pboAssociated) != NULL);
  1616. }
  1617. hresReturn= InsertPathIntoData(&bufData,
  1618. &strData,
  1619. &pbData,
  1620. &dwDataLen,
  1621. pbdCurrent,
  1622. hMDHandle,
  1623. pboAssociated,
  1624. bUnicode);
  1625. }
  1626. pbNextDataStart = (pbDataStart + dwDataLen);
  1627. // The following will ensure that the pointer remains on a DWORD boundary.
  1628. pbNextDataStart = (PBYTE)(((DWORD_PTR)pbNextDataStart + 3) & ~((DWORD_PTR)(3)));
  1629. }
  1630. if (SUCCEEDED(hresReturn)) {
  1631. if (pbEnd < pbNextDataStart) {
  1632. hresReturn = RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER);
  1633. }
  1634. else {
  1635. if (fUseInternalStructure)
  1636. {
  1637. if ((dwMDAttributes & (pbdCurrent->GetAttributes()) &
  1638. METADATA_REFERENCE) == 0) {
  1639. ((PMETADATA_GETALL_INTERNAL_RECORD)pbBuffer)[i].dwMDDataOffset = DIFF(pbDataStart - pbBuffer);
  1640. MD_COPY(pbDataStart, pbData, dwDataLen);
  1641. ((PMETADATA_GETALL_INTERNAL_RECORD)pbBuffer)[i].dwMDDataTag = 0;
  1642. }
  1643. else {
  1644. MD_ASSERT((dwMDAttributes & pbdCurrent->GetAttributes() & METADATA_INSERT_PATH) == 0);
  1645. MD_ASSERT(pbdCurrent->GetData(bUnicode) != NULL);
  1646. ((PMETADATA_GETALL_INTERNAL_RECORD)pbBuffer)[i].pbMDData = (PBYTE)pbdCurrent->GetData(bUnicode);
  1647. pbdCurrent->IncrementReferenceCount();
  1648. ((PMETADATA_GETALL_INTERNAL_RECORD)pbBuffer)[i].dwMDDataTag = pbdCurrent->GetMappingId();
  1649. }
  1650. ((PMETADATA_GETALL_INTERNAL_RECORD)pbBuffer)[i].dwMDIdentifier = pbdCurrent->GetIdentifier();
  1651. ((PMETADATA_GETALL_INTERNAL_RECORD)pbBuffer)[i].dwMDAttributes = pbdCurrent->GetAttributes();
  1652. ((PMETADATA_GETALL_INTERNAL_RECORD)pbBuffer)[i].dwMDUserType = pbdCurrent->GetUserType();
  1653. ((PMETADATA_GETALL_INTERNAL_RECORD)pbBuffer)[i].dwMDDataType = pbdCurrent->GetDataType();
  1654. ((PMETADATA_GETALL_INTERNAL_RECORD)pbBuffer)[i].dwMDDataLen = dwDataLen;
  1655. }
  1656. else
  1657. {
  1658. ((PMETADATA_GETALL_RECORD)pbBuffer)[i].dwMDDataOffset = (DWORD)DIFF(pbDataStart - pbBuffer);
  1659. MD_COPY(pbDataStart, pbData, dwDataLen);
  1660. ((PMETADATA_GETALL_RECORD)pbBuffer)[i].dwMDDataTag = 0;
  1661. ((PMETADATA_GETALL_RECORD)pbBuffer)[i].dwMDIdentifier = pbdCurrent->GetIdentifier();
  1662. ((PMETADATA_GETALL_RECORD)pbBuffer)[i].dwMDAttributes = pbdCurrent->GetAttributes();
  1663. ((PMETADATA_GETALL_RECORD)pbBuffer)[i].dwMDUserType = pbdCurrent->GetUserType();
  1664. ((PMETADATA_GETALL_RECORD)pbBuffer)[i].dwMDDataType = pbdCurrent->GetDataType();
  1665. ((PMETADATA_GETALL_RECORD)pbBuffer)[i].dwMDDataLen = dwDataLen;
  1666. }
  1667. }
  1668. }
  1669. }
  1670. FreeMainDataBuffer(ppvMainDataBuf);
  1671. if (SUCCEEDED(hresReturn)) {
  1672. *pdwMDNumDataEntries = dwNumDataObjects;
  1673. if ((dwNumDataObjects > 0) &&
  1674. (dwMDAttributes & METADATA_ISINHERITED) &&
  1675. (dwMDAttributes & METADATA_INHERIT)) {
  1676. //
  1677. // Set the ISINHERITED flag
  1678. //
  1679. if (bInheritableOnly) {
  1680. for (i = 0; i < dwNumDataObjects; i++) {
  1681. if (fUseInternalStructure)
  1682. {
  1683. ((PMETADATA_GETALL_INTERNAL_RECORD)pbBuffer)[i].dwMDAttributes |= METADATA_ISINHERITED;
  1684. }
  1685. else
  1686. {
  1687. ((PMETADATA_GETALL_RECORD)pbBuffer)[i].dwMDAttributes |= METADATA_ISINHERITED;
  1688. }
  1689. }
  1690. }
  1691. else {
  1692. ppvMainDataBuf = GetMainDataBuffer();
  1693. dwNumDataObjects = pboAffected->GetAllDataObjects(ppvMainDataBuf,
  1694. dwMDAttributes & ~(METADATA_INHERIT | METADATA_PARTIAL_PATH),
  1695. dwMDUserType,
  1696. dwMDDataType,
  1697. bInheritableOnly,
  1698. fNonSecureOnly);
  1699. //
  1700. // Current implementation puts the local items first
  1701. // So just set the rest to inherited
  1702. //
  1703. // DBG loop asserts that the implementation has not changed.
  1704. //
  1705. #if DBG
  1706. for (i = 0; i < dwNumDataObjects ; i++) {
  1707. pbdCurrent = (CMDBaseData *)GetItemFromDataBuffer(ppvMainDataBuf, i);
  1708. MD_ASSERT(pbdCurrent != NULL);
  1709. if (fUseInternalStructure)
  1710. {
  1711. MD_ASSERT(pbdCurrent->GetIdentifier() == ((PMETADATA_GETALL_INTERNAL_RECORD)pbBuffer)[i].dwMDIdentifier);
  1712. }
  1713. else
  1714. {
  1715. MD_ASSERT(pbdCurrent->GetIdentifier() == ((PMETADATA_GETALL_RECORD)pbBuffer)[i].dwMDIdentifier);
  1716. }
  1717. }
  1718. #endif //DBG
  1719. for (i = dwNumDataObjects; i < *pdwMDNumDataEntries; i++) {
  1720. if (fUseInternalStructure)
  1721. {
  1722. ((PMETADATA_GETALL_INTERNAL_RECORD)pbBuffer)[i].dwMDAttributes |= METADATA_ISINHERITED;
  1723. }
  1724. else
  1725. {
  1726. ((PMETADATA_GETALL_RECORD)pbBuffer)[i].dwMDAttributes |= METADATA_ISINHERITED;
  1727. }
  1728. }
  1729. FreeMainDataBuffer(ppvMainDataBuf);
  1730. }
  1731. }
  1732. }
  1733. *pdwMDRequiredBufferSize = (DWORD)DIFF(pbNextDataStart - pbBuffer);
  1734. #ifndef _X86_
  1735. //
  1736. // Alignment fluff. Alignment could cause up to 3 bytes to be added to
  1737. // the total needed if the buffer size ends in a different modulo 4
  1738. // than the one passed in.
  1739. //
  1740. if (FAILED(hresReturn)) {
  1741. *pdwMDRequiredBufferSize +=3;
  1742. }
  1743. #endif
  1744. }
  1745. g_LockMasterResource.ReadUnlock();
  1746. }
  1747. return hresReturn;
  1748. }
  1749. HRESULT STDMETHODCALLTYPE
  1750. CMDCOM::ComMDDeleteAllMetaDataA(
  1751. /* [in] */ METADATA_HANDLE hMDHandle,
  1752. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDPath,
  1753. /* [in] */ DWORD dwMDUserType,
  1754. /* [in] */ DWORD dwMDDataType)
  1755. {
  1756. return ComMDDeleteAllMetaDataD(hMDHandle,
  1757. pszMDPath,
  1758. dwMDUserType,
  1759. dwMDDataType,
  1760. FALSE);
  1761. }
  1762. HRESULT STDMETHODCALLTYPE
  1763. CMDCOM::ComMDDeleteAllMetaDataW(
  1764. /* [in] */ METADATA_HANDLE hMDHandle,
  1765. /* [string][in][unique] */ LPCWSTR pszMDPath,
  1766. /* [in] */ DWORD dwMDUserType,
  1767. /* [in] */ DWORD dwMDDataType)
  1768. {
  1769. return ComMDDeleteAllMetaDataD(hMDHandle,
  1770. (PBYTE)pszMDPath,
  1771. dwMDUserType,
  1772. dwMDDataType,
  1773. TRUE);
  1774. }
  1775. HRESULT STDMETHODCALLTYPE
  1776. CMDCOM::ComMDDeleteAllMetaDataD(
  1777. /* [in] */ METADATA_HANDLE hMDHandle,
  1778. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDPath,
  1779. /* [in] */ DWORD dwMDUserType,
  1780. /* [in] */ DWORD dwMDDataType,
  1781. IN BOOL bUnicode)
  1782. {
  1783. HRESULT hresReturn;
  1784. CMDBaseData *pbdCurrent;
  1785. DWORD i, dwNumDataObjects;
  1786. PVOID *ppvMainDataBuf = NULL;
  1787. CMDHandle *phoHandle;
  1788. CMDBaseObject *pboAffected;
  1789. DWORD dwCurrentDataID;
  1790. LPSTR pszPath = (LPSTR)pszMDPath;
  1791. if (g_dwInitialized == 0) {
  1792. hresReturn = MD_ERROR_NOT_INITIALIZED;
  1793. }
  1794. else if (dwMDDataType >= INVALID_END_METADATA) {
  1795. hresReturn = E_INVALIDARG;
  1796. }
  1797. else {
  1798. g_LockMasterResource.WriteLock();
  1799. hresReturn = GetObjectFromPath(pboAffected, hMDHandle, METADATA_PERMISSION_WRITE, pszPath, bUnicode);
  1800. if ( SUCCEEDED(hresReturn) && ( pboAffected == NULL ) )
  1801. {
  1802. hresReturn = E_FAIL;
  1803. }
  1804. if ( SUCCEEDED(hresReturn) )
  1805. {
  1806. ppvMainDataBuf = GetMainDataBuffer();
  1807. MD_ASSERT (ppvMainDataBuf != NULL);
  1808. if ( ppvMainDataBuf == NULL )
  1809. {
  1810. hresReturn = E_FAIL;
  1811. }
  1812. }
  1813. if (SUCCEEDED(hresReturn)) {
  1814. MD_REQUIRE((phoHandle = GetHandleObject(hMDHandle)) != NULL);
  1815. dwNumDataObjects = pboAffected->GetAllDataObjects(ppvMainDataBuf,
  1816. METADATA_NO_ATTRIBUTES,
  1817. dwMDUserType,
  1818. dwMDDataType,
  1819. FALSE,
  1820. FALSE);
  1821. for (i = 0; i < dwNumDataObjects ; i++) {
  1822. pbdCurrent=(CMDBaseData *)GetItemFromDataBuffer(ppvMainDataBuf, i);
  1823. MD_ASSERT(pbdCurrent != NULL);
  1824. dwCurrentDataID = pbdCurrent->GetIdentifier();
  1825. MD_REQUIRE(pboAffected->RemoveDataObject(pbdCurrent, TRUE) == ERROR_SUCCESS);
  1826. phoHandle->SetChangeData(pboAffected, MD_CHANGE_TYPE_DELETE_DATA, dwCurrentDataID);
  1827. }
  1828. if (dwNumDataObjects > 0) {
  1829. g_dwSystemChangeNumber++;
  1830. INCREMENT_SCHEMA_CHANGE_NUMBER(hMDHandle,
  1831. phoHandle,
  1832. (LPSTR)pszMDPath,
  1833. bUnicode);
  1834. }
  1835. FreeMainDataBuffer(ppvMainDataBuf);
  1836. }
  1837. g_LockMasterResource.WriteUnlock();
  1838. }
  1839. return hresReturn;
  1840. }
  1841. HRESULT STDMETHODCALLTYPE
  1842. CMDCOM::ComMDCopyMetaDataA(
  1843. /* [in] */ METADATA_HANDLE hMDSourceHandle,
  1844. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDSourcePath,
  1845. /* [in] */ METADATA_HANDLE hMDDestHandle,
  1846. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDDestPath,
  1847. /* [in] */ DWORD dwMDAttributes,
  1848. /* [in] */ DWORD dwMDUserType,
  1849. /* [in] */ DWORD dwMDDataType,
  1850. /* [in] */ BOOL bMDCopyFlag)
  1851. {
  1852. return ComMDCopyMetaDataD(hMDSourceHandle,
  1853. pszMDSourcePath,
  1854. hMDDestHandle,
  1855. pszMDDestPath,
  1856. dwMDAttributes,
  1857. dwMDUserType,
  1858. dwMDDataType,
  1859. bMDCopyFlag,
  1860. FALSE);
  1861. }
  1862. HRESULT STDMETHODCALLTYPE
  1863. CMDCOM::ComMDCopyMetaDataW(
  1864. /* [in] */ METADATA_HANDLE hMDSourceHandle,
  1865. /* [string][in][unique] */ LPCWSTR pszMDSourcePath,
  1866. /* [in] */ METADATA_HANDLE hMDDestHandle,
  1867. /* [string][in][unique] */ LPCWSTR pszMDDestPath,
  1868. /* [in] */ DWORD dwMDAttributes,
  1869. /* [in] */ DWORD dwMDUserType,
  1870. /* [in] */ DWORD dwMDDataType,
  1871. /* [in] */ BOOL bMDCopyFlag)
  1872. {
  1873. return ComMDCopyMetaDataD(hMDSourceHandle,
  1874. (PBYTE)pszMDSourcePath,
  1875. hMDDestHandle,
  1876. (PBYTE)pszMDDestPath,
  1877. dwMDAttributes,
  1878. dwMDUserType,
  1879. dwMDDataType,
  1880. bMDCopyFlag,
  1881. TRUE);
  1882. }
  1883. HRESULT STDMETHODCALLTYPE
  1884. CMDCOM::ComMDCopyMetaDataD(
  1885. /* [in] */ METADATA_HANDLE hMDSourceHandle,
  1886. /* [string][in] */ unsigned char __RPC_FAR *pszMDSourcePath,
  1887. /* [in] */ METADATA_HANDLE hMDDestHandle,
  1888. /* [string][in] */ unsigned char __RPC_FAR *pszMDDestPath,
  1889. /* [in] */ DWORD dwMDAttributes,
  1890. /* [in] */ DWORD dwMDUserType,
  1891. /* [in] */ DWORD dwMDDataType,
  1892. /* [in] */ BOOL bMDCopyFlag,
  1893. IN BOOL bUnicode)
  1894. /*++
  1895. Routine Description:
  1896. Copies or moves data associated with the source object to the destination object.
  1897. Optionally copies inherited data based on the value of Attributes.
  1898. Arguments:
  1899. SrcHandle - METADATA_MASTER_ROOT_HANDLE or a handle returned by MDOpenMetaObject with read permission.
  1900. SrcPath - The path of the meta object with which then source data is associated, relative to the
  1901. path of SrcHandle.
  1902. DestHandle - A handle returned by MDOpenMetaObject with write permission.
  1903. DestPath - The path of the meta object for data to be copied to, relative to the path of Handle.
  1904. Attributes - The flags for the data. See imd.h.
  1905. UserType - The User Type for the data. If not set to ALL_METADATA, only metadata of the specified
  1906. User Type will be copied. See imd.h.
  1907. DataType - Optional type of the data to copy. If not set to ALL_METADATA,
  1908. only data of that type will be copied.
  1909. CopyFlag - If true, data will be copied. If false, data will be moved.
  1910. Must be true if METADATA_INHERIT is set.
  1911. Return Value:
  1912. DWORD - ERROR_SUCCESS
  1913. MD_ERROR_NOT_INITIALIZED
  1914. ERROR_INVALID_PARAMETER
  1915. ERROR_PATH_NOT_FOUND
  1916. ERROR_ACCESS_DENIED
  1917. ERROR_NOT_ENOUGH_MEMORY
  1918. Notes:
  1919. METADATA_MASTER_ROOT_HANDLE is a valid source handle if CopyFlag == TRUE,
  1920. but provides no gaurantee that other threads will not also change
  1921. things. If a consistent data state is desired, use a handle returned by
  1922. MDOpenMetaObject. METADATA_MASTER_ROOT_HANDLE is not a valid destination
  1923. handle.
  1924. If inherited data is copied, it will be copied to the destination object,
  1925. not the corresponding ancestor objects.
  1926. --*/
  1927. {
  1928. HRESULT hresReturn;
  1929. BOOL bInheritableOnly = FALSE;
  1930. CMDBaseData *pbdCurrent;
  1931. DWORD i, dwNumDataObjects;
  1932. PVOID *ppvMainDataBuf = NULL;
  1933. CMDBaseObject *pboSource = NULL, *pboDest = NULL;
  1934. LPSTR pszSourcePath = (LPSTR)pszMDSourcePath;
  1935. LPSTR pszDestPath = (LPSTR)pszMDDestPath;
  1936. BOOL fReadLocked = FALSE;
  1937. if (g_dwInitialized == 0) {
  1938. hresReturn = MD_ERROR_NOT_INITIALIZED;
  1939. }
  1940. else if (((!bMDCopyFlag) && (dwMDAttributes & METADATA_INHERIT)) ||
  1941. ((dwMDAttributes & METADATA_PARTIAL_PATH) && !(dwMDAttributes & METADATA_INHERIT))){
  1942. hresReturn = E_INVALIDARG;
  1943. }
  1944. else {
  1945. //
  1946. // Lock for source object. If copying, just get read lock. If moving,
  1947. // Need write lock.
  1948. //
  1949. if (bMDCopyFlag)
  1950. {
  1951. g_LockMasterResource.ReadLock();
  1952. fReadLocked = TRUE;
  1953. }
  1954. else
  1955. {
  1956. g_LockMasterResource.WriteLock();
  1957. fReadLocked = FALSE;
  1958. }
  1959. hresReturn = GetObjectFromPath(pboSource,
  1960. hMDSourceHandle,
  1961. ((bMDCopyFlag) ? METADATA_PERMISSION_READ : METADATA_PERMISSION_WRITE),
  1962. (LPSTR)pszSourcePath,
  1963. bUnicode);
  1964. if ( SUCCEEDED(hresReturn) && ( pboSource == NULL ) )
  1965. {
  1966. hresReturn = E_FAIL;
  1967. }
  1968. if (SUCCEEDED(hresReturn)) {
  1969. bInheritableOnly = FALSE;
  1970. }
  1971. else if ((hresReturn == RETURNCODETOHRESULT(ERROR_PATH_NOT_FOUND)) &&
  1972. (pboSource != NULL) &&
  1973. (dwMDAttributes & METADATA_PARTIAL_PATH)) {
  1974. bInheritableOnly = TRUE;
  1975. hresReturn = ERROR_SUCCESS;
  1976. }
  1977. if ( SUCCEEDED(hresReturn) )
  1978. {
  1979. ppvMainDataBuf = GetMainDataBuffer();
  1980. MD_ASSERT (ppvMainDataBuf != NULL);
  1981. if ( ppvMainDataBuf == NULL )
  1982. {
  1983. hresReturn = E_FAIL;
  1984. }
  1985. }
  1986. if (SUCCEEDED(hresReturn)) {
  1987. dwNumDataObjects = pboSource->GetAllDataObjects(ppvMainDataBuf,
  1988. dwMDAttributes,
  1989. dwMDUserType,
  1990. dwMDDataType,
  1991. bInheritableOnly,
  1992. FALSE);
  1993. if (fReadLocked)
  1994. {
  1995. g_LockMasterResource.ConvertSharedToExclusive();
  1996. fReadLocked = FALSE;
  1997. }
  1998. CMDHandle *hMDDestHandleObject = GetHandleObject(hMDDestHandle);
  1999. if(hMDDestHandleObject == NULL)
  2000. {
  2001. hresReturn = E_HANDLE;
  2002. }
  2003. else
  2004. {
  2005. hresReturn = GetObjectFromPathWithHandle(pboDest,
  2006. hMDDestHandle,
  2007. hMDDestHandleObject,
  2008. METADATA_PERMISSION_WRITE,
  2009. (LPSTR)pszDestPath,
  2010. bUnicode);
  2011. }
  2012. if (SUCCEEDED(hresReturn)) {
  2013. for (i = 0; (i < dwNumDataObjects) && (SUCCEEDED(hresReturn)) ; i++) {
  2014. pbdCurrent=(CMDBaseData *)GetItemFromDataBuffer(ppvMainDataBuf, i);
  2015. MD_ASSERT(pbdCurrent != NULL);
  2016. hresReturn = pboDest->SetDataObject(pbdCurrent);
  2017. if (SUCCEEDED(hresReturn)) {
  2018. MD_ASSERT(GetHandleObject(hMDDestHandle) != NULL);
  2019. hMDDestHandleObject->SetChangeData(pboDest,
  2020. MD_CHANGE_TYPE_SET_DATA,
  2021. pbdCurrent->GetIdentifier());
  2022. }
  2023. }
  2024. if ((!bMDCopyFlag) && (SUCCEEDED(hresReturn))) {
  2025. for (i = 0; i < dwNumDataObjects; i++) {
  2026. pbdCurrent=(CMDBaseData *)GetItemFromDataBuffer(ppvMainDataBuf, i);
  2027. MD_ASSERT(pbdCurrent != NULL);
  2028. MD_REQUIRE(pboSource->RemoveDataObject(pbdCurrent, TRUE) == ERROR_SUCCESS);
  2029. MD_ASSERT(GetHandleObject(hMDSourceHandle) != NULL);
  2030. GetHandleObject(hMDSourceHandle)->SetChangeData(pboSource,
  2031. MD_CHANGE_TYPE_DELETE_DATA,
  2032. pbdCurrent->GetIdentifier());
  2033. }
  2034. }
  2035. g_dwSystemChangeNumber++;
  2036. INCREMENT_SCHEMA_CHANGE_NUMBER(hMDDestHandle,
  2037. hMDDestHandleObject,
  2038. pszDestPath,
  2039. bUnicode);
  2040. }
  2041. FreeMainDataBuffer(ppvMainDataBuf);
  2042. }
  2043. if (fReadLocked)
  2044. {
  2045. g_LockMasterResource.ReadUnlock();
  2046. }
  2047. else
  2048. {
  2049. g_LockMasterResource.WriteUnlock();
  2050. }
  2051. }
  2052. return hresReturn;
  2053. }
  2054. HRESULT STDMETHODCALLTYPE
  2055. CMDCOM::ComMDGetMetaDataPathsA(
  2056. /* [in] */ METADATA_HANDLE hMDHandle,
  2057. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDPath,
  2058. /* [in] */ DWORD dwMDIdentifier,
  2059. /* [in] */ DWORD dwMDDataType,
  2060. /* [in] */ DWORD dwMDBufferSize,
  2061. /* [size_is][out] */ unsigned char __RPC_FAR *pszMDBuffer,
  2062. /* [out] */ DWORD __RPC_FAR *pdwMDRequiredBufferSize)
  2063. {
  2064. return ComMDGetMetaDataPathsD(hMDHandle,
  2065. pszMDPath,
  2066. dwMDIdentifier,
  2067. dwMDDataType,
  2068. dwMDBufferSize,
  2069. pszMDBuffer,
  2070. pdwMDRequiredBufferSize,
  2071. FALSE);
  2072. }
  2073. HRESULT STDMETHODCALLTYPE
  2074. CMDCOM::ComMDGetMetaDataPathsW(
  2075. /* [in] */ METADATA_HANDLE hMDHandle,
  2076. /* [string][in][unique] */ LPCWSTR pszMDPath,
  2077. /* [in] */ DWORD dwMDIdentifier,
  2078. /* [in] */ DWORD dwMDDataType,
  2079. /* [in] */ DWORD dwMDBufferSize,
  2080. /* [size_is][out] */ LPWSTR pszMDBuffer,
  2081. /* [out] */ DWORD __RPC_FAR *pdwMDRequiredBufferSize)
  2082. {
  2083. return ComMDGetMetaDataPathsD(hMDHandle,
  2084. (PBYTE)pszMDPath,
  2085. dwMDIdentifier,
  2086. dwMDDataType,
  2087. dwMDBufferSize,
  2088. (PBYTE)pszMDBuffer,
  2089. pdwMDRequiredBufferSize,
  2090. TRUE);
  2091. }
  2092. HRESULT STDMETHODCALLTYPE
  2093. CMDCOM::ComMDGetMetaDataPathsD(
  2094. /* [in] */ METADATA_HANDLE hMDHandle,
  2095. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDPath,
  2096. /* [in] */ DWORD dwMDIdentifier,
  2097. /* [in] */ DWORD dwMDDataType,
  2098. /* [in] */ DWORD dwMDBufferSize,
  2099. /* [size_is][out] */ unsigned char __RPC_FAR *pszMDBuffer,
  2100. /* [out] */ DWORD __RPC_FAR *pdwMDRequiredBufferSize,
  2101. IN BOOL bUnicode)
  2102. {
  2103. HRESULT hresReturn = S_OK;
  2104. CMDHandle * phMDHandle;
  2105. CMDBaseObject *pboAssociated;
  2106. CMDBaseObject *pboHandle;
  2107. LPSTR pszPath = (LPSTR)pszMDPath;
  2108. DWORD i, dwNumMetaObjects;
  2109. DWORD dwBytesPerChar = ((bUnicode) ? sizeof(WCHAR) : sizeof(char));
  2110. if (g_dwInitialized == 0) {
  2111. hresReturn = MD_ERROR_NOT_INITIALIZED;
  2112. }
  2113. else if (((dwMDBufferSize != 0) && (pszMDBuffer == NULL)) ||
  2114. (dwMDDataType >= INVALID_END_METADATA) ||
  2115. (pdwMDRequiredBufferSize == NULL)) {
  2116. hresReturn = E_INVALIDARG;
  2117. }
  2118. else {
  2119. g_LockMasterResource.ReadLock();
  2120. hresReturn = GetObjectFromPath(pboAssociated, hMDHandle, METADATA_PERMISSION_READ, pszPath, bUnicode);
  2121. if (SUCCEEDED(hresReturn)) {
  2122. PBYTE pbDataStart = pszMDBuffer;
  2123. PBYTE pbNextDataStart = pbDataStart;
  2124. PBYTE pbDataEnd = pszMDBuffer + (dwMDBufferSize * dwBytesPerChar);
  2125. CMDBaseObject *pboCurrent;
  2126. BUFFER bufPath;
  2127. BUFFER bufMainDataBuf;
  2128. DWORD dwReturn;
  2129. phMDHandle = GetHandleObject(hMDHandle);
  2130. if( !phMDHandle )
  2131. {
  2132. hresReturn = MD_ERROR_DATA_NOT_FOUND;
  2133. }
  2134. else
  2135. {
  2136. pboHandle = phMDHandle->GetObject();
  2137. MD_ASSERT(pboHandle != NULL);
  2138. dwNumMetaObjects = 0;
  2139. hresReturn = pboAssociated->GetDataRecursive(&bufMainDataBuf,
  2140. dwMDIdentifier,
  2141. dwMDDataType,
  2142. dwNumMetaObjects);
  2143. if (SUCCEEDED(hresReturn)) {
  2144. if (dwNumMetaObjects != 0) {
  2145. CMDBaseObject **ppboList = (CMDBaseObject **)bufMainDataBuf.QueryPtr();
  2146. for (i = 0;
  2147. (i < dwNumMetaObjects) &&
  2148. ( SUCCEEDED(hresReturn) ||
  2149. hresReturn == RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER));
  2150. i++, pbDataStart = pbNextDataStart) {
  2151. pboCurrent=ppboList[i];
  2152. MD_ASSERT(pboCurrent != NULL);
  2153. DWORD dwStringLen = 0;
  2154. dwReturn = GetObjectPath(pboCurrent,
  2155. &bufPath,
  2156. dwStringLen,
  2157. pboHandle,
  2158. bUnicode);
  2159. if (dwReturn != ERROR_SUCCESS) {
  2160. //
  2161. // Only blow away previous hresReturn if this failed.
  2162. //
  2163. hresReturn = RETURNCODETOHRESULT(dwReturn);
  2164. }
  2165. else {
  2166. //
  2167. // Need 2 extra characters for "/"
  2168. //
  2169. pbNextDataStart = pbDataStart + ((dwStringLen + 2) * dwBytesPerChar);
  2170. if (pbDataEnd < pbNextDataStart) {
  2171. hresReturn = RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER);
  2172. }
  2173. else {
  2174. MD_COPY(pbDataStart,
  2175. bufPath.QueryPtr(),
  2176. dwStringLen * dwBytesPerChar);
  2177. if (bUnicode) {
  2178. *(((LPWSTR)pbDataStart) + dwStringLen) = MD_PATH_DELIMETERW;
  2179. *(((LPWSTR)pbDataStart) + (dwStringLen + 1)) = (WCHAR)L'\0';
  2180. }
  2181. else {
  2182. *(((LPSTR)pbDataStart) + dwStringLen) = MD_PATH_DELIMETER;
  2183. *(((LPSTR)pbDataStart) + (dwStringLen + 1)) = (CHAR)'\0';
  2184. }
  2185. }
  2186. }
  2187. }
  2188. //
  2189. // Append a final 0 for double NULL termination
  2190. //
  2191. pbNextDataStart = pbDataStart + dwBytesPerChar;
  2192. if (SUCCEEDED(hresReturn)) {
  2193. if ((pbDataStart + dwBytesPerChar) <= pbDataEnd) {
  2194. if (bUnicode) {
  2195. *((LPWSTR)pbDataStart) = (WCHAR)L'\0';
  2196. }
  2197. else {
  2198. *((LPSTR)pbDataStart) = (CHAR)'\0';
  2199. }
  2200. }
  2201. else {
  2202. hresReturn = RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER);
  2203. }
  2204. }
  2205. }
  2206. else {
  2207. if (pszMDBuffer != NULL) {
  2208. //
  2209. // If NULL, just return success
  2210. // No strings, need to append 2 0's for double NULL termination
  2211. //
  2212. pbNextDataStart = pbDataStart + (dwBytesPerChar * 2);
  2213. if (pbNextDataStart <= pbDataEnd) {
  2214. if (bUnicode) {
  2215. *((LPWSTR)pbDataStart) = (WCHAR)L'\0';
  2216. *(((LPWSTR)pbDataStart) + 1) = (WCHAR)L'\0';
  2217. }
  2218. else {
  2219. *((LPSTR)pbDataStart) = (CHAR)'\0';
  2220. *(((LPSTR)pbDataStart) + 1) = (CHAR)'\0';
  2221. }
  2222. }
  2223. else {
  2224. hresReturn = RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER);
  2225. }
  2226. }
  2227. }
  2228. if (hresReturn == RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER)) {
  2229. *pdwMDRequiredBufferSize = (DWORD)DIFF(pbNextDataStart - (PBYTE)pszMDBuffer) / dwBytesPerChar;
  2230. }
  2231. }
  2232. }
  2233. }
  2234. g_LockMasterResource.ReadUnlock();
  2235. }
  2236. return hresReturn;
  2237. }
  2238. HRESULT STDMETHODCALLTYPE
  2239. CMDCOM::ComMDOpenMetaObjectA(
  2240. /* [in] */ METADATA_HANDLE hMDHandle,
  2241. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDPath,
  2242. /* [in] */ DWORD dwMDAccessRequested,
  2243. /* [in] */ DWORD dwMDTimeOut,
  2244. /* [out] */ PMETADATA_HANDLE phMDNewHandle)
  2245. {
  2246. return ComMDOpenMetaObjectD(hMDHandle,
  2247. pszMDPath,
  2248. dwMDAccessRequested,
  2249. dwMDTimeOut,
  2250. phMDNewHandle,
  2251. FALSE);
  2252. }
  2253. HRESULT STDMETHODCALLTYPE
  2254. CMDCOM::ComMDOpenMetaObjectW(
  2255. /* [in] */ METADATA_HANDLE hMDHandle,
  2256. /* [string][in][unique] */ LPCWSTR pszMDPath,
  2257. /* [in] */ DWORD dwMDAccessRequested,
  2258. /* [in] */ DWORD dwMDTimeOut,
  2259. /* [out] */ PMETADATA_HANDLE phMDNewHandle)
  2260. {
  2261. return ComMDOpenMetaObjectD(hMDHandle,
  2262. (PBYTE)pszMDPath,
  2263. dwMDAccessRequested,
  2264. dwMDTimeOut,
  2265. phMDNewHandle,
  2266. TRUE);
  2267. }
  2268. HRESULT STDMETHODCALLTYPE
  2269. CMDCOM::ComMDOpenMetaObjectD(
  2270. /* [in] */ METADATA_HANDLE hMDHandle,
  2271. /* [string][in] */ unsigned char __RPC_FAR *pszMDPath,
  2272. /* [in] */ DWORD dwMDAccessRequested,
  2273. /* [in] */ DWORD dwMDTimeOut,
  2274. /* [out] */ PMETADATA_HANDLE phMDNewHandle,
  2275. IN BOOL bUnicode)
  2276. /*++
  2277. Routine Description:
  2278. Opens a meta object for read and/or write access. The returned handle is
  2279. used by several of the other API's. Opening an object for Read access
  2280. guarantees that that view of the data will not change while the object
  2281. is open. Opening an object for write gaurantees that no other objects
  2282. will read or write any changed data until the handle is closed.
  2283. Arguments:
  2284. Handle - METADATA_MASTER_ROOT_HANDLE or a handle returned by MDOpenMetaObject.
  2285. Path - The path of the object to be opened.
  2286. AccessRequested - The permissions requested. See imd.h.
  2287. TimeOut - The time to block waiting for open to succeed, in miliseconds.
  2288. NewHandle - The handled to be passed to other MD routines.
  2289. Return Value:
  2290. DWORD - ERROR_SUCCESS
  2291. MD_ERROR_NOT_INITIALIZED
  2292. ERROR_INVALID_PARAMETER
  2293. ERROR_PATH_NOT_FOUND
  2294. ERROR_PATH_BUSY
  2295. Notes:
  2296. Multiple read handles or a single write handle can be open on any given
  2297. object.
  2298. Opens for read will wait if the object being opened, any of its ancestor
  2299. objects, or any of its descendant objects is open for write.
  2300. Opens for write will wait if the object being opened, any of its ancestor
  2301. objects, or any of its descendant objects is open for read and/or write.
  2302. If the request is for write access or Handle has write access, Handle must be closed before
  2303. this request can succeed, unless Handle = METADATA_MASTER_ROOT_HANDLE.
  2304. Handles should be closed as quickly as possible, as open handles can cause other requests to block.
  2305. --*/
  2306. {
  2307. HRESULT hresReturn;
  2308. DWORD WaitRetCode;
  2309. METADATA_HANDLE mhTemp = NULL;
  2310. _int64 ExpireTime, CurrentTime, TimeLeft;
  2311. FILETIME TempTime;
  2312. BOOL bPermissionsAvailable = FALSE;
  2313. LPSTR pszPath = (LPSTR)pszMDPath;
  2314. BOOLEAN bSchemaKey = FALSE;
  2315. if (g_dwInitialized == 0) {
  2316. hresReturn = MD_ERROR_NOT_INITIALIZED;
  2317. }
  2318. else if ((phMDNewHandle == NULL) ||
  2319. ((dwMDAccessRequested & (METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE)) == 0)) {
  2320. hresReturn = E_INVALIDARG;
  2321. }
  2322. else {
  2323. CMDBaseObject *pboOpen = NULL;
  2324. GetSystemTimeAsFileTime(&TempTime);
  2325. ExpireTime = ((_int64)TempTime.dwHighDateTime << 32) +
  2326. (_int64)TempTime.dwLowDateTime +
  2327. ((_int64)dwMDTimeOut * 10000);
  2328. TimeLeft = dwMDTimeOut;
  2329. g_LockMasterResource.WriteLock();
  2330. hresReturn = GetObjectFromPath(pboOpen, hMDHandle, 0, pszPath, bUnicode);
  2331. if (SUCCEEDED(hresReturn)) {
  2332. bPermissionsAvailable = PermissionsAvailable(pboOpen, dwMDAccessRequested, 0);
  2333. }
  2334. //
  2335. // Spin loop waiting for permissions. Events get pulsed whenever a handle is closed.
  2336. // Use a wait interval in case the close comes between the Unlock and the Wait.
  2337. //
  2338. while ((SUCCEEDED(hresReturn)) && (!bPermissionsAvailable) && (TimeLeft > 0)) {
  2339. g_LockMasterResource.WriteUnlock();
  2340. if (dwMDAccessRequested & METADATA_PERMISSION_WRITE) {
  2341. WaitRetCode = WaitForMultipleObjects(EVENT_ARRAY_LENGTH, g_phEventHandles, FALSE, LESSOROF((DWORD)TimeLeft, OPEN_WAIT_INTERVAL));
  2342. }
  2343. else {
  2344. WaitRetCode = WaitForSingleObject(g_phEventHandles[EVENT_WRITE_INDEX], LESSOROF((DWORD)TimeLeft, OPEN_WAIT_INTERVAL));
  2345. }
  2346. GetSystemTimeAsFileTime(&TempTime);
  2347. CurrentTime = ((_int64)TempTime.dwHighDateTime << 32) + (_int64)TempTime.dwLowDateTime;
  2348. TimeLeft = ((ExpireTime - CurrentTime) / 10000);
  2349. g_LockMasterResource.WriteLock();
  2350. //
  2351. // Get object again to make sure the object hasn't been deleted
  2352. // Should probably put an exception handler PermissionsAvailable and use
  2353. // the current object
  2354. //
  2355. hresReturn = GetObjectFromPath(pboOpen, hMDHandle, 0, pszPath, bUnicode);
  2356. if (SUCCEEDED(hresReturn)) {
  2357. bPermissionsAvailable = PermissionsAvailable(pboOpen, dwMDAccessRequested, 0);
  2358. }
  2359. }
  2360. if (SUCCEEDED(hresReturn)) {
  2361. if (bPermissionsAvailable) {
  2362. if(METADATA_MASTER_ROOT_HANDLE == hMDHandle)
  2363. {
  2364. if((pszPath != NULL) && (0 != *pszPath))
  2365. {
  2366. if(bUnicode)
  2367. {
  2368. if( (0 == _wcsnicmp((LPWSTR)(pszMDPath), WSZSCHEMA_KEY_NAME1, WSZSCHEMA_KEY_LENGTH1)) ||
  2369. (0 == _wcsnicmp((LPWSTR)(pszMDPath), WSZSCHEMA_KEY_NAME2, WSZSCHEMA_KEY_LENGTH2)) ||
  2370. (0 == _wcsnicmp((LPWSTR)(pszMDPath), WSZSCHEMA_KEY_NAME3, WSZSCHEMA_KEY_LENGTH3))
  2371. )
  2372. {
  2373. bSchemaKey = TRUE;
  2374. }
  2375. }
  2376. else
  2377. {
  2378. if( (0 == _strnicmp((LPSTR)(pszMDPath), SZSCHEMA_KEY_NAME1, SZSCHEMA_KEY_LENGTH1)) ||
  2379. (0 == _strnicmp((LPSTR)(pszMDPath), SZSCHEMA_KEY_NAME2, SZSCHEMA_KEY_LENGTH2)) ||
  2380. (0 == _strnicmp((LPSTR)(pszMDPath), SZSCHEMA_KEY_NAME3, SZSCHEMA_KEY_LENGTH3))
  2381. )
  2382. {
  2383. bSchemaKey = TRUE;
  2384. }
  2385. }
  2386. }
  2387. }
  2388. else
  2389. {
  2390. CMDHandle *phoHandle;
  2391. phoHandle = GetHandleObject(hMDHandle);
  2392. if(phoHandle->IsSchemaHandle())
  2393. {
  2394. bSchemaKey = TRUE;
  2395. }
  2396. }
  2397. hresReturn = AddHandle(pboOpen, dwMDAccessRequested, mhTemp, bSchemaKey);
  2398. if (SUCCEEDED(hresReturn)) {
  2399. *phMDNewHandle = mhTemp;
  2400. }
  2401. }
  2402. else {
  2403. hresReturn = RETURNCODETOHRESULT(ERROR_PATH_BUSY);
  2404. }
  2405. }
  2406. if (bUnicode) {
  2407. if (SUCCEEDED(hresReturn)) {
  2408. DBGINFO((DBG_CONTEXT,
  2409. "Metabase handle %u opened, From handle %u and path %S, permissions = %u\n",
  2410. mhTemp,
  2411. hMDHandle,
  2412. ((pszMDPath == NULL) || *((WCHAR *)pszMDPath) == (WCHAR)L'\0') ? L"NULL" : (WCHAR *)pszMDPath,
  2413. dwMDAccessRequested));
  2414. }
  2415. else {
  2416. DBGINFO((DBG_CONTEXT,
  2417. "Metabase Open of handle %u and path %S failed, return code = %X\n",
  2418. hMDHandle,
  2419. ((pszMDPath == NULL) || *((WCHAR *)pszMDPath) == (WCHAR)L'\0') ? L"NULL" : (WCHAR *)pszMDPath,
  2420. hresReturn));
  2421. }
  2422. }
  2423. else {
  2424. if (SUCCEEDED(hresReturn)) {
  2425. DBGINFO((DBG_CONTEXT,
  2426. "Metabase handle %u opened, From handle %u and path %s, permissions = %u\n",
  2427. mhTemp,
  2428. hMDHandle,
  2429. ((pszMDPath == NULL) || *((CHAR *)pszMDPath) == (CHAR)'\0') ? "NULL" : (CHAR *)pszMDPath,
  2430. dwMDAccessRequested));
  2431. }
  2432. else {
  2433. DBGINFO((DBG_CONTEXT,
  2434. "Metabase Open of handle %u and path %s failed, return code = %X\n",
  2435. hMDHandle,
  2436. ((pszMDPath == NULL) || *((CHAR *)pszMDPath) == (CHAR)'\0') ? "NULL" : (CHAR *)pszMDPath,
  2437. hresReturn));
  2438. }
  2439. }
  2440. g_LockMasterResource.WriteUnlock();
  2441. }
  2442. return hresReturn;
  2443. }
  2444. HRESULT STDMETHODCALLTYPE
  2445. CMDCOM::ComMDCloseMetaObject(
  2446. /* [in] */ METADATA_HANDLE hMDHandle)
  2447. /*++
  2448. Routine Description:
  2449. Closes a handle to a meta object. If the handle was opened with write
  2450. permission and changes have been made via this handle, this will cause all
  2451. registered callback functions to be called.
  2452. Arguments:
  2453. Handle - The handle returned by MDOpenMetaObject.
  2454. Return Value:
  2455. DWORD - ERROR_SUCCESS
  2456. MD_ERROR_NOT_INITIALIZED
  2457. ERROR_INVALID_HANDLE
  2458. --*/
  2459. {
  2460. HRESULT hresReturn;
  2461. CMDHandle *hoTemp = NULL;
  2462. BOOL bPulseWrite = FALSE;
  2463. BOOL bPulseRead = FALSE;
  2464. BOOL bSendNotifications = FALSE;
  2465. BOOL bDeleteChangeData = FALSE;
  2466. DWORD dwNumChangeEntries = 0;
  2467. PMD_CHANGE_OBJECT_W pcoBuffer = NULL;
  2468. BUFFER **ppbufStorageArray = NULL;
  2469. BOOL fReadLocked = FALSE;
  2470. g_LockMasterResource.WriteLock();
  2471. if (g_dwInitialized == 0) {
  2472. hresReturn = MD_ERROR_NOT_INITIALIZED;
  2473. }
  2474. else if ((hMDHandle == METADATA_MASTER_ROOT_HANDLE) ||
  2475. ((hoTemp = RemoveHandleObject(hMDHandle)) == NULL)) {
  2476. hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_HANDLE);
  2477. }
  2478. else {
  2479. if (hoTemp->IsWriteAllowed()) {
  2480. RemovePermissions(hoTemp->GetObject(), METADATA_PERMISSION_WRITE);
  2481. bPulseWrite = TRUE;
  2482. bSendNotifications = TRUE;
  2483. bDeleteChangeData = TRUE;
  2484. }
  2485. if (hoTemp->IsReadAllowed()) {
  2486. RemovePermissions(hoTemp->GetObject(), METADATA_PERMISSION_READ);
  2487. bPulseRead = TRUE;
  2488. }
  2489. if (bPulseWrite) {
  2490. bPulseWrite = PulseEvent(g_phEventHandles[EVENT_WRITE_INDEX]);
  2491. }
  2492. if (bPulseRead && !bPulseWrite) {
  2493. //
  2494. // A write pulse activates everyone, so only do this if we didn't already do a write pulse
  2495. //
  2496. bPulseRead = PulseEvent(g_phEventHandles[EVENT_READ_INDEX]);
  2497. }
  2498. if (bSendNotifications) {
  2499. g_LockMasterResource.ConvertExclusiveToShared();
  2500. fReadLocked = TRUE;
  2501. if (FAILED(CreateNotifications(hoTemp,
  2502. &dwNumChangeEntries,
  2503. &pcoBuffer,
  2504. &ppbufStorageArray))) {
  2505. bSendNotifications = FALSE;
  2506. }
  2507. }
  2508. hresReturn = ERROR_SUCCESS;
  2509. }
  2510. if (SUCCEEDED(hresReturn)) {
  2511. DBGINFO((DBG_CONTEXT,
  2512. "Metabase handle %u closed\n",
  2513. hMDHandle));
  2514. }
  2515. if (fReadLocked)
  2516. {
  2517. g_LockMasterResource.ReadUnlock();
  2518. }
  2519. else
  2520. {
  2521. g_LockMasterResource.WriteUnlock();
  2522. }
  2523. if (bSendNotifications) {
  2524. SendNotifications(hMDHandle,
  2525. dwNumChangeEntries,
  2526. pcoBuffer,
  2527. ppbufStorageArray);
  2528. DeleteNotifications(dwNumChangeEntries,
  2529. pcoBuffer,
  2530. ppbufStorageArray);
  2531. }
  2532. if (bDeleteChangeData) {
  2533. //
  2534. // Need to delete handle with write lock held,
  2535. // Since this can delete metaobjects which can delete
  2536. // data which accesses the data cache table.
  2537. //
  2538. g_LockMasterResource.WriteLock();
  2539. }
  2540. delete (hoTemp);
  2541. if (bDeleteChangeData) {
  2542. g_LockMasterResource.WriteUnlock();
  2543. }
  2544. return hresReturn;
  2545. }
  2546. HRESULT STDMETHODCALLTYPE
  2547. CMDCOM::ComMDChangePermissions(
  2548. /* [in] */ METADATA_HANDLE hMDHandle,
  2549. /* [in] */ DWORD dwMDTimeOut,
  2550. /* [in] */ DWORD dwMDAccessRequested)
  2551. /*++
  2552. Routine Description:
  2553. Changes permissions on an open meta object handle. If the handle had write permission and is being changed
  2554. to read only, this will cause all registered callback functions to be called.
  2555. Arguments:
  2556. Handle - The handle to be modified.
  2557. TimeOut - The time to block waiting for open to succeed, in miliseconds.
  2558. AccessRequested - The requested permissions. See imd.h.
  2559. Return Value:
  2560. DWORD - ERROR_SUCCESS
  2561. MD_ERROR_NOT_INITIALIZED
  2562. ERROR_INVALID_HANDLE
  2563. ERROR_PATH_BUSY
  2564. Notes:
  2565. Success or failure when adding permissions follows the same rules as OpenMetaObject.
  2566. TimeOut values should be short for this call, as it is quite possible for 2 threads
  2567. with read permission on the same data to attempt to update to write at the same time.
  2568. Both will block until one read handle is closed.
  2569. --*/
  2570. {
  2571. HRESULT hresReturn = ERROR_SUCCESS;
  2572. CMDHandle *hoTemp = NULL;
  2573. DWORD WaitRetCode;
  2574. _int64 ExpireTime, CurrentTime, TimeLeft;
  2575. FILETIME TempTime;
  2576. BOOL bPermissionsAvailable;
  2577. BOOL bAddRead, bAddWrite, bRemoveRead, bRemoveWrite = FALSE;
  2578. BOOL bEventPulsed = FALSE;
  2579. BOOL bSendNotifications = FALSE;
  2580. CMDHandle *phoNotifyHandle = NULL;
  2581. DWORD dwNumChangeEntries = 0;
  2582. PMD_CHANGE_OBJECT_W pcoBuffer = NULL;
  2583. BUFFER **ppbufStorageArray = NULL;
  2584. g_LockMasterResource.WriteLock();
  2585. if (g_dwInitialized == 0) {
  2586. hresReturn = MD_ERROR_NOT_INITIALIZED;
  2587. }
  2588. else if ((hMDHandle == METADATA_MASTER_ROOT_HANDLE) || ((hoTemp = GetHandleObject(hMDHandle)) == NULL) ||
  2589. ((dwMDAccessRequested & (METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE)) == 0)) {
  2590. hresReturn = E_INVALIDARG;
  2591. }
  2592. else if ((hoTemp = GetHandleObject(hMDHandle)) == NULL) {
  2593. hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_HANDLE);
  2594. }
  2595. else {
  2596. bAddRead = (!(hoTemp->IsReadAllowed()) && (dwMDAccessRequested & METADATA_PERMISSION_READ));
  2597. bAddWrite = (!(hoTemp->IsWriteAllowed()) && (dwMDAccessRequested & METADATA_PERMISSION_WRITE));
  2598. bRemoveRead = ((hoTemp->IsReadAllowed()) && !(dwMDAccessRequested & METADATA_PERMISSION_READ));
  2599. bRemoveWrite = ((hoTemp->IsWriteAllowed()) && !(dwMDAccessRequested & METADATA_PERMISSION_WRITE));
  2600. MD_ASSERT(!(bAddRead && bAddWrite));
  2601. MD_ASSERT(!(bRemoveRead && bRemoveWrite));
  2602. MD_ASSERT(!(bAddRead && bRemoveRead));
  2603. MD_ASSERT(!(bAddWrite && bRemoveWrite));
  2604. //
  2605. // Add permissions first, because if delete comes first, another
  2606. // object could open a handle to this in the interim, and the
  2607. // object could get deleted.
  2608. // Also, AddWrite can fail so it must be before RemoveRead
  2609. // to avoid partial completion.
  2610. //
  2611. if (bAddWrite) {
  2612. MD_ASSERT(hoTemp->IsReadAllowed());
  2613. GetSystemTimeAsFileTime(&TempTime);
  2614. ExpireTime = ((_int64)TempTime.dwHighDateTime << 32) + (_int64)TempTime.dwLowDateTime + ((_int64)dwMDTimeOut * 10000);
  2615. TimeLeft = dwMDTimeOut;
  2616. bPermissionsAvailable = PermissionsAvailable(hoTemp->GetObject(), METADATA_PERMISSION_WRITE, 1);
  2617. while ((!bPermissionsAvailable) && (TimeLeft > 0) && (hoTemp!=NULL)) {
  2618. g_LockMasterResource.WriteUnlock();
  2619. WaitRetCode = WaitForMultipleObjects(EVENT_ARRAY_LENGTH, g_phEventHandles, FALSE, LESSOROF((DWORD)TimeLeft, OPEN_WAIT_INTERVAL));
  2620. GetSystemTimeAsFileTime(&TempTime);
  2621. CurrentTime = ((_int64)TempTime.dwHighDateTime << 32) + (_int64)TempTime.dwLowDateTime;
  2622. TimeLeft = ((ExpireTime - CurrentTime) / 10000);
  2623. g_LockMasterResource.WriteLock();
  2624. //
  2625. // The meta object could not have been deleted while the handle is open
  2626. // but the handle object could have been deleted, so get it again.
  2627. //
  2628. hoTemp = GetHandleObject(hMDHandle);
  2629. if (hoTemp != NULL) {
  2630. bPermissionsAvailable = PermissionsAvailable(hoTemp->GetObject(), METADATA_PERMISSION_WRITE, 1);
  2631. }
  2632. }
  2633. if (hoTemp == NULL) {
  2634. hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_HANDLE);
  2635. }
  2636. else if (!bPermissionsAvailable) {
  2637. hresReturn = RETURNCODETOHRESULT(ERROR_PATH_BUSY);
  2638. }
  2639. else {
  2640. AddPermissions(hoTemp->GetObject(), METADATA_PERMISSION_WRITE);
  2641. }
  2642. }
  2643. if (SUCCEEDED(hresReturn)) {
  2644. if (bAddRead) {
  2645. MD_ASSERT(hoTemp->IsWriteAllowed());
  2646. //
  2647. // Must already have write access
  2648. // Just add read access
  2649. //
  2650. AddPermissions(hoTemp->GetObject(), METADATA_PERMISSION_READ);
  2651. }
  2652. if (bRemoveRead) {
  2653. RemovePermissions(hoTemp->GetObject(), METADATA_PERMISSION_READ);
  2654. bEventPulsed = PulseEvent(g_phEventHandles[EVENT_READ_INDEX]);
  2655. }
  2656. if (bRemoveWrite) {
  2657. RemovePermissions(hoTemp->GetObject(), METADATA_PERMISSION_WRITE);
  2658. bEventPulsed = PulseEvent(g_phEventHandles[EVENT_WRITE_INDEX]);
  2659. }
  2660. hoTemp->SetPermissions(dwMDAccessRequested);
  2661. }
  2662. }
  2663. if ((SUCCEEDED(hresReturn)) && bRemoveWrite) {
  2664. if (SUCCEEDED(CreateNotifications(hoTemp,
  2665. &dwNumChangeEntries,
  2666. &pcoBuffer,
  2667. &ppbufStorageArray))) {
  2668. phoNotifyHandle = new CMDHandle(hoTemp);
  2669. if (phoNotifyHandle == NULL) {
  2670. DeleteNotifications(dwNumChangeEntries,
  2671. pcoBuffer,
  2672. ppbufStorageArray);
  2673. }
  2674. else {
  2675. bSendNotifications = TRUE;
  2676. hoTemp->ZeroChangeList();
  2677. }
  2678. }
  2679. hoTemp->RemoveNotifications();
  2680. }
  2681. g_LockMasterResource.WriteUnlock();
  2682. if (bSendNotifications) {
  2683. SendNotifications(hMDHandle,
  2684. dwNumChangeEntries,
  2685. pcoBuffer,
  2686. ppbufStorageArray);
  2687. DeleteNotifications(dwNumChangeEntries,
  2688. pcoBuffer,
  2689. ppbufStorageArray);
  2690. //
  2691. // Need to delete handle with write lock held,
  2692. // Since this can delete metaobjects which can delete
  2693. // data which accesses the data cache table.
  2694. //
  2695. g_LockMasterResource.WriteLock();
  2696. delete (phoNotifyHandle);
  2697. g_LockMasterResource.WriteUnlock();
  2698. }
  2699. return hresReturn;
  2700. }
  2701. HRESULT STDMETHODCALLTYPE
  2702. CMDCOM::ComMDSaveData(
  2703. IN METADATA_HANDLE hMDHandle)
  2704. /*++
  2705. Routine Description:
  2706. Saves all data changed since the last load or save to permanent storage.
  2707. Arguments:
  2708. Return Value:
  2709. DWORD - ERROR_SUCCESS
  2710. MD_ERROR_NOT_INITIALIZED
  2711. Errors returned by the file system.
  2712. Notes:
  2713. If the main file has been modified by other applications, this call will overwrite them.
  2714. --*/
  2715. {
  2716. HRESULT hresReturn;
  2717. IIS_CRYPTO_STORAGE CryptoStorage;
  2718. PIIS_CRYPTO_BLOB pSessionKeyBlob;
  2719. if (g_dwInitialized == 0) {
  2720. hresReturn = MD_ERROR_NOT_INITIALIZED;
  2721. }
  2722. else {
  2723. hresReturn = InitStorageAndSessionKey(
  2724. &CryptoStorage,
  2725. &pSessionKeyBlob
  2726. );
  2727. if( SUCCEEDED(hresReturn) ) {
  2728. if (g_dwInitialized == 0) {
  2729. hresReturn = MD_ERROR_NOT_INITIALIZED;
  2730. }
  2731. else {
  2732. hresReturn = SaveAllData(FALSE, &CryptoStorage, pSessionKeyBlob, NULL, NULL, hMDHandle);
  2733. }
  2734. ::IISCryptoFreeBlob(pSessionKeyBlob);
  2735. }
  2736. }
  2737. return hresReturn;
  2738. }
  2739. HRESULT STDMETHODCALLTYPE
  2740. CMDCOM::ComMDGetHandleInfo(
  2741. /* [in] */ METADATA_HANDLE hMDHandle,
  2742. /* [out] */ PMETADATA_HANDLE_INFO pmdhiInfo)
  2743. /*++
  2744. Routine Description:
  2745. Gets the information associated with a handle.
  2746. Arguments:
  2747. Handle - The handle to get information about.
  2748. Info - Structure filled in with the information. See imd.h.
  2749. Return Value:
  2750. DWORD - ERROR_SUCCESS
  2751. MD_ERROR_NOT_INITIALIZED
  2752. ERROR_INVALID_HANDLE
  2753. Notes:
  2754. pmdhiInfo->dwMDSystemChangeNumber will correspond to the System Change Number at the time
  2755. the handle was created. It will not change if writes are done via this handle, or any other
  2756. handle. A client can compare this number with the value returned by MDGetSystemChangeNumber
  2757. to see if any writes have been done since the handle was opened.
  2758. --*/
  2759. {
  2760. HRESULT hresReturn = ERROR_SUCCESS;
  2761. CMDHandle *HandleObject;
  2762. if (g_dwInitialized == 0) {
  2763. hresReturn = MD_ERROR_NOT_INITIALIZED;
  2764. }
  2765. else if (pmdhiInfo == NULL) {
  2766. hresReturn = E_INVALIDARG;
  2767. }
  2768. else {
  2769. g_LockMasterResource.ReadLock();
  2770. HandleObject = GetHandleObject(hMDHandle);
  2771. if (HandleObject == NULL) {
  2772. hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_HANDLE);
  2773. }
  2774. else {
  2775. HandleObject->GetHandleInfo(pmdhiInfo);
  2776. }
  2777. g_LockMasterResource.ReadUnlock();
  2778. }
  2779. return hresReturn;
  2780. }
  2781. HRESULT STDMETHODCALLTYPE
  2782. CMDCOM::ComMDGetSystemChangeNumber(
  2783. /* [out] */ DWORD __RPC_FAR *pdwSystemChangeNumber)
  2784. /*++
  2785. Routine Description:
  2786. Gets the System Change Number.
  2787. Arguments:
  2788. SystemChangeNumber - The system change number. This is incremented every time the metadata is updated.
  2789. Return Value:
  2790. DWORD - ERROR_SUCCESS
  2791. MD_ERROR_NOT_INITIALIZED
  2792. Notes:
  2793. --*/
  2794. {
  2795. HRESULT hresReturn = ERROR_SUCCESS;
  2796. if (g_dwInitialized == 0) {
  2797. hresReturn = MD_ERROR_NOT_INITIALIZED;
  2798. }
  2799. else if (pdwSystemChangeNumber == NULL) {
  2800. hresReturn = E_INVALIDARG;
  2801. }
  2802. else {
  2803. g_LockMasterResource.ReadLock();
  2804. *pdwSystemChangeNumber = g_dwSystemChangeNumber;
  2805. g_LockMasterResource.ReadUnlock();
  2806. }
  2807. return hresReturn;
  2808. }
  2809. HRESULT STDMETHODCALLTYPE
  2810. CMDCOM::ComMDGetDataSetNumberA(
  2811. /* [in] */ METADATA_HANDLE hMDHandle,
  2812. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDPath,
  2813. /* [out] */ DWORD __RPC_FAR *pdwMDDataSetNumber)
  2814. {
  2815. return ComMDGetDataSetNumberD(hMDHandle,
  2816. pszMDPath,
  2817. pdwMDDataSetNumber,
  2818. FALSE);
  2819. }
  2820. HRESULT STDMETHODCALLTYPE
  2821. CMDCOM::ComMDGetDataSetNumberW(
  2822. /* [in] */ METADATA_HANDLE hMDHandle,
  2823. /* [string][in][unique] */ LPCWSTR pszMDPath,
  2824. /* [out] */ DWORD __RPC_FAR *pdwMDDataSetNumber)
  2825. {
  2826. return ComMDGetDataSetNumberD(hMDHandle,
  2827. (PBYTE)pszMDPath,
  2828. pdwMDDataSetNumber,
  2829. TRUE);
  2830. }
  2831. HRESULT STDMETHODCALLTYPE
  2832. CMDCOM::ComMDGetDataSetNumberD(
  2833. /* [in] */ METADATA_HANDLE hMDHandle,
  2834. /* [string][in] */ unsigned char __RPC_FAR *pszMDPath,
  2835. /* [out] */ DWORD __RPC_FAR *pdwMDDataSetNumber,
  2836. IN BOOL bUnicode)
  2837. /*++
  2838. Routine Description:
  2839. Gets all the data set number associated with a Meta Object.
  2840. Arguments:
  2841. Handle - METADATA_MASTER_ROOT_HANDLE or a handle returned by MDOpenMetaObject with read permission.
  2842. Path - The path of the meta object with which this data is associated, relative to the
  2843. path of Handle.
  2844. DataSetNumber - A number associated with this data set. Can be used to identify common data sets.
  2845. Filled in if successful.
  2846. Return Value:
  2847. DWORD - ERROR_SUCCESS
  2848. MD_ERROR_NOT_INITIALIZED
  2849. ERROR_INVALID_PARAMETER
  2850. Notes:
  2851. All paths with the same data set number have identical data if inherited data is included.
  2852. The inverse is not true, eg. there may be paths with identical data but different data set numbers.
  2853. --*/
  2854. {
  2855. HRESULT hresReturn;
  2856. LPSTR pszPath = (LPSTR)pszMDPath;
  2857. if (g_dwInitialized == 0) {
  2858. hresReturn = MD_ERROR_NOT_INITIALIZED;
  2859. }
  2860. else if (pdwMDDataSetNumber == NULL){
  2861. hresReturn = E_INVALIDARG;
  2862. }
  2863. else {
  2864. g_LockMasterResource.ReadLock();
  2865. CMDBaseObject *pboQueried = NULL;
  2866. hresReturn = GetObjectFromPath(pboQueried, hMDHandle, METADATA_PERMISSION_READ, pszPath, bUnicode);
  2867. if ( SUCCEEDED(hresReturn) && ( pboQueried == NULL ) )
  2868. {
  2869. hresReturn = E_FAIL;
  2870. }
  2871. if (SUCCEEDED(hresReturn)) {
  2872. *pdwMDDataSetNumber=pboQueried->GetDataSetNumber();
  2873. }
  2874. else if ((hresReturn == RETURNCODETOHRESULT(ERROR_PATH_NOT_FOUND)) && (pboQueried != NULL)) {
  2875. *pdwMDDataSetNumber=pboQueried->GetDescendantDataSetNumber();
  2876. hresReturn = ERROR_SUCCESS;
  2877. }
  2878. g_LockMasterResource.ReadUnlock();
  2879. }
  2880. return hresReturn;
  2881. }
  2882. HRESULT STDMETHODCALLTYPE
  2883. CMDCOM::ComMDAddRefReferenceData(
  2884. /* [in] */ DWORD dwMDDataTag)
  2885. /*++
  2886. Routine Description:
  2887. AddRefs data gotten by reference via the ComMDGetMetaData, ComMDEnumMetadata, or ComMDGetAllMetadata.
  2888. Arguments:
  2889. DataTag - The tag returned with the data.
  2890. Return Value:
  2891. DWORD - ERROR_SUCCESS
  2892. MD_ERROR_NOT_INITIALIZED
  2893. ERROR_INVALID_PARAMETER
  2894. Notes:
  2895. Tags are used without validation. Clients must not pass in invalid tags.
  2896. --*/
  2897. {
  2898. HRESULT hresReturn = ERROR_SUCCESS;
  2899. if (g_dwInitialized == 0) {
  2900. hresReturn = MD_ERROR_NOT_INITIALIZED;
  2901. }
  2902. else if (dwMDDataTag == 0){
  2903. hresReturn = E_INVALIDARG;
  2904. }
  2905. else {
  2906. g_LockMasterResource.WriteLock();
  2907. #if DBG
  2908. //
  2909. // Make sure this is in the table
  2910. //
  2911. CMDBaseData *pbdAddRef = (CMDBaseData *)g_PointerMapper->FindMapping(dwMDDataTag);
  2912. DWORD dwHash = DATA_HASH(pbdAddRef->GetIdentifier());
  2913. CMDBaseData *pbdIndex;
  2914. BOOL bFound = FALSE;
  2915. if (g_ppbdDataHashTable[dwHash] == pbdAddRef) {
  2916. bFound = TRUE;
  2917. }
  2918. else {
  2919. for (pbdIndex=g_ppbdDataHashTable[dwHash];
  2920. (pbdIndex != NULL ) && (pbdIndex->GetNextPtr() != pbdAddRef);
  2921. pbdIndex = pbdIndex->GetNextPtr()) {
  2922. }
  2923. if (pbdIndex != NULL) {
  2924. bFound = TRUE;
  2925. }
  2926. }
  2927. MD_ASSERT(bFound);
  2928. #endif
  2929. ((CMDBaseData *)(g_PointerMapper->FindMapping(dwMDDataTag)))->IncrementReferenceCount();
  2930. g_LockMasterResource.WriteUnlock();
  2931. }
  2932. return hresReturn;
  2933. }
  2934. HRESULT STDMETHODCALLTYPE
  2935. CMDCOM::ComMDReleaseReferenceData(
  2936. /* [in] */ DWORD dwMDDataTag)
  2937. /*++
  2938. Routine Description:
  2939. Releases data gotten by reference via the ComMDGetMetaData, ComMDEnumMetadata, or ComMDGetAllMetadata.
  2940. Arguments:
  2941. DataTag - The tag returned with the data.
  2942. Return Value:
  2943. DWORD - ERROR_SUCCESS
  2944. MD_ERROR_NOT_INITIALIZED
  2945. ERROR_INVALID_PARAMETER
  2946. Notes:
  2947. Tags are used without validation. Clients must not pass in invalid tags.
  2948. --*/
  2949. {
  2950. HRESULT hresReturn = ERROR_SUCCESS;
  2951. if (g_dwInitialized == 0) {
  2952. hresReturn = MD_ERROR_NOT_INITIALIZED;
  2953. }
  2954. else if (dwMDDataTag == 0){
  2955. hresReturn = E_INVALIDARG;
  2956. }
  2957. else {
  2958. g_LockMasterResource.WriteLock();
  2959. DeleteDataObject((CMDBaseData *)(g_PointerMapper->FindMapping(dwMDDataTag)));
  2960. g_LockMasterResource.WriteUnlock();
  2961. }
  2962. return hresReturn;
  2963. }
  2964. HRESULT STDMETHODCALLTYPE
  2965. CMDCOM::ComMDSetLastChangeTimeA(
  2966. /* [in] */ METADATA_HANDLE hMDHandle,
  2967. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDPath,
  2968. /* [in] */ PFILETIME pftMDLastChangeTime)
  2969. {
  2970. return ComMDSetLastChangeTimeD(hMDHandle,
  2971. pszMDPath,
  2972. pftMDLastChangeTime,
  2973. FALSE);
  2974. }
  2975. HRESULT STDMETHODCALLTYPE
  2976. CMDCOM::ComMDSetLastChangeTimeW(
  2977. /* [in] */ METADATA_HANDLE hMDHandle,
  2978. /* [string][in][unique] */ LPCWSTR pszMDPath,
  2979. /* [in] */ PFILETIME pftMDLastChangeTime)
  2980. {
  2981. return ComMDSetLastChangeTimeD(hMDHandle,
  2982. (PBYTE)pszMDPath,
  2983. pftMDLastChangeTime,
  2984. TRUE);
  2985. }
  2986. HRESULT STDMETHODCALLTYPE
  2987. CMDCOM::ComMDSetLastChangeTimeD(
  2988. /* [in] */ METADATA_HANDLE hMDHandle,
  2989. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDPath,
  2990. /* [in] */ PFILETIME pftMDLastChangeTime,
  2991. IN BOOL bUnicode)
  2992. /*++
  2993. Routine Description:
  2994. Set the last change time associated with a Meta Object.
  2995. Arguments:
  2996. Handle - METADATA_MASTER_ROOT_HANDLE or a handle returned by MDOpenMetaObject with write permission.
  2997. Path - The path of the affected meta object, relative to the path of Handle.
  2998. LastChangeTime - The new change time for the meta object.
  2999. Return Value:
  3000. DWORD - ERROR_SUCCESS
  3001. MD_ERROR_NOT_INITIALIZED
  3002. ERROR_INVALID_PARAMETER
  3003. ERROR_PATH_NOT_FOUND
  3004. Notes:
  3005. Last change times are also updated whenever data or child objects are set, added, or deleted.
  3006. --*/
  3007. {
  3008. HRESULT hresReturn = ERROR_SUCCESS;
  3009. LPSTR pszPath = (LPSTR)pszMDPath;
  3010. if (g_dwInitialized == 0) {
  3011. hresReturn = MD_ERROR_NOT_INITIALIZED;
  3012. }
  3013. else if (pftMDLastChangeTime == NULL){
  3014. hresReturn = E_INVALIDARG;
  3015. }
  3016. else {
  3017. g_LockMasterResource.WriteLock();
  3018. CMDBaseObject *pboAffected = NULL;
  3019. hresReturn = GetObjectFromPath(pboAffected, hMDHandle, METADATA_PERMISSION_WRITE, pszPath, bUnicode);
  3020. if (SUCCEEDED(hresReturn)) {
  3021. pboAffected->SetLastChangeTime(pftMDLastChangeTime);
  3022. }
  3023. g_LockMasterResource.WriteUnlock();
  3024. }
  3025. return hresReturn;
  3026. }
  3027. HRESULT STDMETHODCALLTYPE
  3028. CMDCOM::ComMDGetLastChangeTimeA(
  3029. /* [in] */ METADATA_HANDLE hMDHandle,
  3030. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDPath,
  3031. /* [out] */ PFILETIME pftMDLastChangeTime)
  3032. {
  3033. return ComMDGetLastChangeTimeD(hMDHandle,
  3034. pszMDPath,
  3035. pftMDLastChangeTime,
  3036. FALSE);
  3037. }
  3038. HRESULT STDMETHODCALLTYPE
  3039. CMDCOM::ComMDGetLastChangeTimeW(
  3040. /* [in] */ METADATA_HANDLE hMDHandle,
  3041. /* [string][in][unique] */ LPCWSTR pszMDPath,
  3042. /* [out] */ PFILETIME pftMDLastChangeTime)
  3043. {
  3044. return ComMDGetLastChangeTimeD(hMDHandle,
  3045. (PBYTE)pszMDPath,
  3046. pftMDLastChangeTime,
  3047. TRUE);
  3048. }
  3049. HRESULT STDMETHODCALLTYPE
  3050. CMDCOM::ComMDGetLastChangeTimeD(
  3051. /* [in] */ METADATA_HANDLE hMDHandle,
  3052. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDPath,
  3053. /* [out] */ PFILETIME pftMDLastChangeTime,
  3054. IN BOOL bUnicode)
  3055. /*++
  3056. Routine Description:
  3057. Set the last change time associated with a Meta Object.
  3058. Arguments:
  3059. Handle - METADATA_MASTER_ROOT_HANDLE or a handle returned by MDOpenMetaObject with write permission.
  3060. Path - The path of the affected meta object, relative to the path of Handle.
  3061. LastChangeTime - Place to return the change time for the meta object.
  3062. Return Value:
  3063. DWORD - ERROR_SUCCESS
  3064. MD_ERROR_NOT_INITIALIZED
  3065. ERROR_INVALID_PARAMETER
  3066. ERROR_PATH_NOT_FOUND
  3067. Notes:
  3068. Last change times are also updated whenever data or child objects are set, added, or deleted.
  3069. --*/
  3070. {
  3071. HRESULT hresReturn = ERROR_SUCCESS;
  3072. LPSTR pszPath = (LPSTR)pszMDPath;
  3073. PFILETIME pftTemp;
  3074. if (g_dwInitialized == 0) {
  3075. hresReturn = MD_ERROR_NOT_INITIALIZED;
  3076. }
  3077. else if (pftMDLastChangeTime == NULL){
  3078. hresReturn = E_INVALIDARG;
  3079. }
  3080. else {
  3081. g_LockMasterResource.ReadLock();
  3082. CMDBaseObject *pboQueried = NULL;
  3083. hresReturn = GetObjectFromPath(pboQueried, hMDHandle, METADATA_PERMISSION_READ, pszPath, bUnicode);
  3084. if ((SUCCEEDED(hresReturn)) ||
  3085. ((hresReturn == RETURNCODETOHRESULT(ERROR_PATH_NOT_FOUND)) && (pboQueried != NULL))) {
  3086. pftTemp = pboQueried->GetLastChangeTime();
  3087. *pftMDLastChangeTime = *pftTemp;
  3088. }
  3089. g_LockMasterResource.ReadUnlock();
  3090. }
  3091. return hresReturn;
  3092. }
  3093. HRESULT STDMETHODCALLTYPE
  3094. CMDCOM::ComMDBackupA(
  3095. /* [in] */ METADATA_HANDLE hMDHandle,
  3096. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDBackupLocation,
  3097. /* [in] */ DWORD dwMDVersion,
  3098. /* [in] */ DWORD dwMDFlags)
  3099. {
  3100. return ComMDBackupD(hMDHandle,
  3101. (LPSTR) pszMDBackupLocation,
  3102. dwMDVersion,
  3103. dwMDFlags,
  3104. FALSE,
  3105. NULL);
  3106. }
  3107. HRESULT STDMETHODCALLTYPE
  3108. CMDCOM::ComMDBackupW(
  3109. /* [in] */ METADATA_HANDLE hMDHandle,
  3110. /* [string][in][unique] */ LPCWSTR pszMDBackupLocation,
  3111. /* [in] */ DWORD dwMDVersion,
  3112. /* [in] */ DWORD dwMDFlags)
  3113. {
  3114. return ComMDBackupD(hMDHandle,
  3115. (LPSTR) pszMDBackupLocation,
  3116. dwMDVersion,
  3117. dwMDFlags,
  3118. TRUE,
  3119. NULL);
  3120. }
  3121. HRESULT STDMETHODCALLTYPE
  3122. CMDCOM::ComMDBackupWithPasswdW(
  3123. /* [in] */ METADATA_HANDLE hMDHandle,
  3124. /* [string][in][unique] */ LPCWSTR pszMDBackupLocation,
  3125. /* [in] */ DWORD dwMDVersion,
  3126. /* [in] */ DWORD dwMDFlags,
  3127. /* [string][in][unique] */ LPCWSTR pszPasswd)
  3128. {
  3129. STRAU strauPasswd;
  3130. if( !strauPasswd.Copy( (LPWSTR)pszPasswd ) )
  3131. {
  3132. return E_OUTOFMEMORY;
  3133. }
  3134. return ComMDBackupD(hMDHandle,
  3135. (LPSTR) pszMDBackupLocation,
  3136. dwMDVersion,
  3137. dwMDFlags,
  3138. TRUE,
  3139. strauPasswd.QueryStrA());
  3140. }
  3141. HRESULT STDMETHODCALLTYPE
  3142. CMDCOM::ComMDBackupD(
  3143. /* [in] */ METADATA_HANDLE hMDHandle,
  3144. /* [in] */ LPSTR pszMDBackupLocation,
  3145. /* [in] */ DWORD dwMDVersion,
  3146. /* [in] */ DWORD dwMDFlags,
  3147. /* [in] */ BOOL bUnicode,
  3148. /* [in] */ LPSTR pszPasswd)
  3149. {
  3150. HRESULT hresReturn = ERROR_SUCCESS;
  3151. HRESULT hresWarning = ERROR_SUCCESS;
  3152. IIS_CRYPTO_STORAGE * pCryptoStorage = NULL;
  3153. PIIS_CRYPTO_BLOB pSessionKeyBlob = NULL;
  3154. OFSTRUCT ReOpenBuff;
  3155. STRAU strauBackupLocation;
  3156. STRAU strauSchemaLocation;
  3157. if (g_dwInitialized == 0) {
  3158. hresReturn = MD_ERROR_NOT_INITIALIZED;
  3159. }
  3160. else if (((dwMDFlags & !(MD_BACKUP_OVERWRITE |
  3161. MD_BACKUP_SAVE_FIRST |
  3162. MD_BACKUP_FORCE_BACKUP)) != 0) ||
  3163. (((dwMDFlags & MD_BACKUP_SAVE_FIRST) == 0) &&
  3164. ((dwMDFlags & MD_BACKUP_FORCE_BACKUP) != 0))) {
  3165. hresReturn = E_INVALIDARG;
  3166. }
  3167. else {
  3168. if( dwMDFlags == 0 )
  3169. {
  3170. dwMDFlags = MD_BACKUP_SAVE_FIRST;
  3171. }
  3172. hresReturn = CreateBackupFileName(pszMDBackupLocation,
  3173. dwMDVersion,
  3174. bUnicode,
  3175. &strauBackupLocation,
  3176. &strauSchemaLocation);
  3177. if( FAILED( hresReturn ) )
  3178. {
  3179. return hresReturn;
  3180. }
  3181. MD_ASSERT(strauBackupLocation.QueryStr(FALSE) != NULL);
  3182. MD_ASSERT(strauSchemaLocation.QueryStr(FALSE) != NULL);
  3183. if( ( ( dwMDFlags & MD_BACKUP_OVERWRITE ) == 0 ) &&
  3184. ( ( HFILE_ERROR != OpenFile( strauBackupLocation.QueryStr(FALSE),
  3185. &ReOpenBuff,
  3186. OF_EXIST ) ) ||
  3187. ( HFILE_ERROR != OpenFile( strauSchemaLocation.QueryStr(FALSE),
  3188. &ReOpenBuff,
  3189. OF_EXIST ) ) ) )
  3190. {
  3191. return HRESULT_FROM_WIN32( ERROR_FILE_EXISTS );
  3192. }
  3193. MD_REQUIRE(WaitForSingleObject(g_hReadSaveSemaphore, INFINITE) != WAIT_TIMEOUT);
  3194. if ((dwMDFlags & MD_BACKUP_SAVE_FIRST) != 0 || pszPasswd != NULL) {
  3195. if( !pszPasswd )
  3196. {
  3197. pCryptoStorage = new IIS_CRYPTO_STORAGE;
  3198. if( !pCryptoStorage )
  3199. {
  3200. hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  3201. }
  3202. else
  3203. {
  3204. hresReturn = InitStorageAndSessionKey(
  3205. pCryptoStorage,
  3206. &pSessionKeyBlob
  3207. );
  3208. }
  3209. }
  3210. else
  3211. {
  3212. pCryptoStorage = new IIS_CRYPTO_STORAGE2;
  3213. if( !pCryptoStorage )
  3214. {
  3215. hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  3216. }
  3217. else
  3218. {
  3219. hresReturn = InitStorageAndSessionKey2(
  3220. pszPasswd,
  3221. pCryptoStorage,
  3222. &pSessionKeyBlob
  3223. );
  3224. }
  3225. }
  3226. if( SUCCEEDED(hresReturn) ) {
  3227. if (g_dwInitialized == 0) {
  3228. hresReturn = MD_ERROR_NOT_INITIALIZED;
  3229. }
  3230. else {
  3231. if( !pszPasswd )
  3232. {
  3233. hresReturn = SaveAllData(FALSE,
  3234. pCryptoStorage,
  3235. pSessionKeyBlob,
  3236. NULL,
  3237. NULL,
  3238. hMDHandle,
  3239. TRUE
  3240. );
  3241. }
  3242. else
  3243. {
  3244. hresReturn = SaveAllData(FALSE,
  3245. pCryptoStorage,
  3246. pSessionKeyBlob,
  3247. (LPWSTR)strauBackupLocation.QueryStr(TRUE),
  3248. (LPWSTR)strauSchemaLocation.QueryStr(TRUE),
  3249. hMDHandle,
  3250. TRUE
  3251. );
  3252. }
  3253. }
  3254. if( !pszPasswd )
  3255. {
  3256. ::IISCryptoFreeBlob(pSessionKeyBlob);
  3257. }
  3258. else
  3259. {
  3260. ::IISCryptoFreeBlob2(pSessionKeyBlob);
  3261. }
  3262. }
  3263. if (FAILED(hresReturn)) {
  3264. hresWarning = MD_WARNING_SAVE_FAILED;
  3265. }
  3266. }
  3267. if (SUCCEEDED(hresReturn) || ((dwMDFlags & MD_BACKUP_FORCE_BACKUP) != 0)) {
  3268. //
  3269. // Copy the file
  3270. //
  3271. if ( !pszPasswd ) {
  3272. BOOL bFailIfExists = ((dwMDFlags & MD_BACKUP_OVERWRITE) == 0) ? TRUE : FALSE;
  3273. //
  3274. // Copy the file, for old backup method
  3275. //
  3276. if (!CopyFile(g_strRealFileName->QueryStr(),
  3277. strauBackupLocation.QueryStr(FALSE),
  3278. bFailIfExists) ||
  3279. !CopyFile(g_strSchemaFileName->QueryStr(),
  3280. strauSchemaLocation.QueryStr(FALSE),
  3281. bFailIfExists)) {
  3282. hresReturn = RETURNCODETOHRESULT(GetLastError());
  3283. }
  3284. }
  3285. if (SUCCEEDED(hresReturn)) {
  3286. HANDLE hTempFileHandle;
  3287. hTempFileHandle = CreateFile(strauBackupLocation.QueryStr(FALSE),
  3288. GENERIC_READ | GENERIC_WRITE,
  3289. 0,
  3290. NULL,
  3291. OPEN_EXISTING,
  3292. FILE_ATTRIBUTE_NORMAL,
  3293. 0);
  3294. if (hTempFileHandle != INVALID_HANDLE_VALUE) {
  3295. FILETIME ftCurrent;
  3296. GetSystemTimeAsFileTime(&ftCurrent);
  3297. SetFileTime(hTempFileHandle,
  3298. NULL, // Creation Time
  3299. &ftCurrent, // Last AccessTime
  3300. &ftCurrent); // Last Change Time
  3301. CloseHandle(hTempFileHandle);
  3302. }
  3303. hresReturn = BackupCertificates ((LPCWSTR)pszMDBackupLocation,
  3304. strauBackupLocation.QueryStr(FALSE),
  3305. g_strRealFileName->QueryStr());
  3306. }
  3307. }
  3308. MD_REQUIRE(ReleaseSemaphore(g_hReadSaveSemaphore, 1, NULL));
  3309. }
  3310. if (hresReturn == ERROR_SUCCESS) {
  3311. hresReturn = hresWarning;
  3312. }
  3313. if( pCryptoStorage )
  3314. {
  3315. delete pCryptoStorage;
  3316. pCryptoStorage = NULL;
  3317. }
  3318. return hresReturn;
  3319. }
  3320. HRESULT STDMETHODCALLTYPE
  3321. CMDCOM::ComMDRestoreA(
  3322. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDBackupLocation,
  3323. /* [in] */ DWORD dwMDVersion,
  3324. /* [in] */ DWORD dwMDFlags)
  3325. {
  3326. return ComMDRestoreD((LPSTR) pszMDBackupLocation,
  3327. dwMDVersion,
  3328. dwMDFlags,
  3329. FALSE,
  3330. NULL);
  3331. }
  3332. HRESULT STDMETHODCALLTYPE
  3333. CMDCOM::ComMDRestoreW(
  3334. /* [string][in][unique] */ LPCWSTR pszMDBackupLocation,
  3335. /* [in] */ DWORD dwMDVersion,
  3336. /* [in] */ DWORD dwMDFlags)
  3337. {
  3338. return ComMDRestoreD((LPSTR) pszMDBackupLocation,
  3339. dwMDVersion,
  3340. dwMDFlags,
  3341. TRUE,
  3342. NULL);
  3343. }
  3344. HRESULT STDMETHODCALLTYPE
  3345. CMDCOM::ComMDRestoreWithPasswdW(
  3346. /* [string][in][unique] */ LPCWSTR pszMDBackupLocation,
  3347. /* [in] */ DWORD dwMDVersion,
  3348. /* [in] */ DWORD dwMDFlags,
  3349. /* [string][in][unique] */ LPCWSTR pszPasswd
  3350. )
  3351. {
  3352. STRAU strauPasswd;
  3353. if( !strauPasswd.Copy( (LPWSTR)pszPasswd ) )
  3354. {
  3355. return E_OUTOFMEMORY;
  3356. }
  3357. return ComMDRestoreD((LPSTR) pszMDBackupLocation,
  3358. dwMDVersion,
  3359. dwMDFlags,
  3360. TRUE,
  3361. strauPasswd.QueryStrA());
  3362. }
  3363. HRESULT STDMETHODCALLTYPE
  3364. CMDCOM::ComMDRestoreD(
  3365. /* [in] */ LPSTR pszMDBackupLocation,
  3366. /* [in] */ DWORD dwMDVersion,
  3367. /* [in] */ DWORD dwMDFlags,
  3368. /* [in] */ BOOL bUnicode,
  3369. /* [in] */ LPSTR pszPasswd
  3370. )
  3371. {
  3372. HRESULT hresReturn = ERROR_SUCCESS;
  3373. if ((dwMDVersion == MD_BACKUP_NEXT_VERSION) ||
  3374. (dwMDFlags != 0)) {
  3375. //
  3376. // CreateBackupFileName checks for valid name,
  3377. // but it allows NEXT_VERSION, so we check that here.
  3378. // Currently, no flags are defined
  3379. //
  3380. hresReturn = E_INVALIDARG;
  3381. }
  3382. else {
  3383. STRAU strauBackupLocation;
  3384. STRAU strauSchemaLocation;
  3385. hresReturn = CreateBackupFileName(pszMDBackupLocation,
  3386. dwMDVersion,
  3387. bUnicode,
  3388. &strauBackupLocation,
  3389. &strauSchemaLocation);
  3390. if(SUCCEEDED(hresReturn))
  3391. {
  3392. hresReturn = Restore(
  3393. pszMDBackupLocation,
  3394. &strauBackupLocation,
  3395. &strauSchemaLocation,
  3396. pszPasswd);
  3397. }
  3398. }
  3399. return hresReturn;
  3400. }
  3401. HRESULT STDMETHODCALLTYPE
  3402. CMDCOM::ComMDEnumBackupsA(
  3403. /* [size_is (MD_BACKUP_MAX_LEN)][in, out] */ unsigned char __RPC_FAR *pszMDBackupLocation,
  3404. /* [out] */ DWORD *pdwMDVersion,
  3405. /* [out] */ PFILETIME pftMDBackupTime,
  3406. /* [in] */ DWORD dwMDEnumIndex)
  3407. {
  3408. return ComMDEnumBackupsD((LPSTR) pszMDBackupLocation,
  3409. pdwMDVersion,
  3410. pftMDBackupTime,
  3411. dwMDEnumIndex,
  3412. FALSE);
  3413. }
  3414. HRESULT STDMETHODCALLTYPE
  3415. CMDCOM::ComMDEnumBackupsW(
  3416. /* [size_is (MD_BACKUP_MAX_LEN)][in, out] */ LPWSTR pszMDBackupLocation,
  3417. /* [out] */ DWORD *pdwMDVersion,
  3418. /* [out] */ PFILETIME pftMDBackupTime,
  3419. /* [in] */ DWORD dwMDEnumIndex)
  3420. {
  3421. return ComMDEnumBackupsD((LPSTR) pszMDBackupLocation,
  3422. pdwMDVersion,
  3423. pftMDBackupTime,
  3424. dwMDEnumIndex,
  3425. TRUE);
  3426. }
  3427. HRESULT STDMETHODCALLTYPE
  3428. CMDCOM::ComMDEnumBackupsD(
  3429. /* [size_is (MD_BACKUP_MAX_LEN)][in, out] */ LPSTR pszMDBackupLocation,
  3430. /* [out] */ DWORD *pdwMDVersion,
  3431. /* [out] */ PFILETIME pftMDBackupTime,
  3432. /* [in] */ DWORD dwMDEnumIndex,
  3433. /* [in] */ BOOL bUnicode)
  3434. {
  3435. HRESULT hresReturn = ERROR_SUCCESS;
  3436. DWORD cchBackupNameLen;
  3437. if ((pszMDBackupLocation == NULL) ||
  3438. (pdwMDVersion == NULL)) {
  3439. //
  3440. // CreateBackupFileName checks for valid name,
  3441. // but it allows NEXT_VERSION, so we check that here.
  3442. // Currently, no flags are defined
  3443. //
  3444. hresReturn = E_INVALIDARG;
  3445. }
  3446. else {
  3447. MD_REQUIRE(WaitForSingleObject(g_hReadSaveSemaphore, INFINITE) != WAIT_TIMEOUT);
  3448. STRAU strauBackupLocation;
  3449. if (!strauBackupLocation.Copy(g_pstrBackupFilePath->QueryStr())) {
  3450. hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  3451. }
  3452. else if (!strauBackupLocation.Append("\\")) {
  3453. hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  3454. }
  3455. else {
  3456. if (bUnicode) {
  3457. if (*(LPWSTR)pszMDBackupLocation == (WCHAR)L'\0') {
  3458. if (!strauBackupLocation.Append(L"*")) {
  3459. hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  3460. }
  3461. }
  3462. else {
  3463. if (!strauBackupLocation.Append((LPWSTR)pszMDBackupLocation)) {
  3464. hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  3465. }
  3466. }
  3467. }
  3468. else {
  3469. if (*(LPSTR)pszMDBackupLocation == '\0') {
  3470. if (!strauBackupLocation.Append("*")) {
  3471. hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  3472. }
  3473. }
  3474. else {
  3475. if (!strauBackupLocation.Append((LPSTR)pszMDBackupLocation)) {
  3476. hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  3477. }
  3478. }
  3479. }
  3480. }
  3481. if (SUCCEEDED(hresReturn)) {
  3482. if (SUCCEEDED(hresReturn)) {
  3483. if (!strauBackupLocation.Append(MD_BACKUP_SUFFIX)) {
  3484. hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  3485. }
  3486. else {
  3487. if (!strauBackupLocation.Append("*")) {
  3488. hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  3489. }
  3490. else {
  3491. //
  3492. // Make sure MultiByte string is valid
  3493. //
  3494. if (strauBackupLocation.QueryStrA() == NULL) {
  3495. hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  3496. }
  3497. }
  3498. }
  3499. }
  3500. }
  3501. if (SUCCEEDED(hresReturn))
  3502. {
  3503. //
  3504. // Successfully created the search name
  3505. // Enumerate files
  3506. //
  3507. MD_ASSERT(strauBackupLocation.QueryStr(FALSE) != NULL);
  3508. HANDLE hFile = INVALID_HANDLE_VALUE;
  3509. WIN32_FIND_DATA wfdFile;
  3510. DWORD dwEnumIndex = (DWORD) -1;
  3511. hFile = FindFirstFile(strauBackupLocation.QueryStrA(),
  3512. &wfdFile);
  3513. if (hFile == INVALID_HANDLE_VALUE)
  3514. {
  3515. hresReturn = RETURNCODETOHRESULT(GetLastError());
  3516. }
  3517. else
  3518. {
  3519. if (CheckDigits(wfdFile.cFileName +
  3520. GetBackupNameLen(wfdFile.cFileName) +
  3521. (sizeof(MD_BACKUP_SUFFIX) - 1)))
  3522. {
  3523. if ((!strauBackupLocation.Copy(wfdFile.cFileName) ||
  3524. (strauBackupLocation.QueryStrW() == NULL)))
  3525. {
  3526. hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  3527. }
  3528. else
  3529. {
  3530. if ( bUnicode )
  3531. {
  3532. cchBackupNameLen = GetBackupNameLen( strauBackupLocation.QueryStrW() );
  3533. }
  3534. else
  3535. {
  3536. cchBackupNameLen = GetBackupNameLen( strauBackupLocation.QueryStrA() );
  3537. }
  3538. if ( ( cchBackupNameLen != 0 ) &&
  3539. ( cchBackupNameLen <= MD_BACKUP_MAX_LEN ) )
  3540. {
  3541. //
  3542. // One of our files
  3543. //
  3544. dwEnumIndex++;
  3545. }
  3546. }
  3547. }
  3548. while (SUCCEEDED(hresReturn) && (dwEnumIndex != dwMDEnumIndex))
  3549. {
  3550. //
  3551. // Process the remaining files
  3552. //
  3553. if (FindNextFile(hFile, &wfdFile))
  3554. {
  3555. if (CheckDigits(wfdFile.cFileName +
  3556. GetBackupNameLen(wfdFile.cFileName) +
  3557. (sizeof(MD_BACKUP_SUFFIX) - 1)))
  3558. {
  3559. if ((!strauBackupLocation.Copy(wfdFile.cFileName) ||
  3560. (strauBackupLocation.QueryStrW() == NULL)))
  3561. {
  3562. hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  3563. }
  3564. else
  3565. {
  3566. if ( bUnicode )
  3567. {
  3568. cchBackupNameLen = GetBackupNameLen( strauBackupLocation.QueryStrW() );
  3569. }
  3570. else
  3571. {
  3572. cchBackupNameLen = GetBackupNameLen( strauBackupLocation.QueryStrA() );
  3573. }
  3574. if ( ( cchBackupNameLen != 0 ) &&
  3575. ( cchBackupNameLen <= MD_BACKUP_MAX_LEN ) )
  3576. {
  3577. //
  3578. // One of our files
  3579. //
  3580. dwEnumIndex++;
  3581. }
  3582. }
  3583. }
  3584. }
  3585. else
  3586. {
  3587. hresReturn = GetLastHResult();
  3588. }
  3589. }
  3590. FindClose(hFile);
  3591. }
  3592. if (SUCCEEDED(hresReturn))
  3593. {
  3594. //
  3595. // Found the file
  3596. // File name is in wfdFile.cFileName
  3597. // Time is in wfdFile.ftLastWriteTime
  3598. // Need to separate the name and version
  3599. // Reuse strauBackupLocation
  3600. //
  3601. DWORD dwNameLen;
  3602. if ((!strauBackupLocation.Copy(wfdFile.cFileName) ||
  3603. (strauBackupLocation.QueryStrW() == NULL)))
  3604. {
  3605. hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  3606. }
  3607. else
  3608. {
  3609. //
  3610. // ANSI bytes might not equal characters, so use unicode
  3611. //
  3612. dwNameLen = GetBackupNameLen(strauBackupLocation.QueryStrW());
  3613. strauBackupLocation.SetLen(dwNameLen);
  3614. if ( bUnicode )
  3615. {
  3616. cchBackupNameLen = strauBackupLocation.QueryCCH();
  3617. }
  3618. else
  3619. {
  3620. cchBackupNameLen = strauBackupLocation.QueryCBA();
  3621. }
  3622. if ( ( cchBackupNameLen == 0 ) ||
  3623. ( cchBackupNameLen > MD_BACKUP_MAX_LEN ) )
  3624. {
  3625. hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_NAME);
  3626. }
  3627. else
  3628. {
  3629. MD_COPY(pszMDBackupLocation,
  3630. strauBackupLocation.QueryStr(bUnicode),
  3631. strauBackupLocation.QueryCB(bUnicode) +
  3632. ((bUnicode) ? sizeof(WCHAR) : sizeof(char)));
  3633. *pdwMDVersion = atol(wfdFile.cFileName +
  3634. //
  3635. // dwNameLen is # characters
  3636. // Need to add # bytes, so
  3637. // Get it from STRAU
  3638. //
  3639. strauBackupLocation.QueryCBA() +
  3640. (sizeof(MD_BACKUP_SUFFIX) - 1));
  3641. MD_COPY(pftMDBackupTime,
  3642. &(wfdFile.ftLastWriteTime),
  3643. sizeof(FILETIME));
  3644. }
  3645. }
  3646. }
  3647. else
  3648. {
  3649. if ((hresReturn == RETURNCODETOHRESULT(ERROR_FILE_NOT_FOUND)) ||
  3650. (hresReturn == RETURNCODETOHRESULT(ERROR_NO_MORE_FILES)))
  3651. {
  3652. hresReturn = RETURNCODETOHRESULT(ERROR_NO_MORE_ITEMS);
  3653. }
  3654. }
  3655. }
  3656. MD_REQUIRE(ReleaseSemaphore(g_hReadSaveSemaphore, 1, NULL));
  3657. }
  3658. return hresReturn;
  3659. }
  3660. HRESULT STDMETHODCALLTYPE
  3661. CMDCOM::ComMDDeleteBackupA(
  3662. /* [string][in][unique] */ unsigned char __RPC_FAR *pszMDBackupLocation,
  3663. /* [in] */ DWORD dwMDVersion)
  3664. {
  3665. return ComMDDeleteBackupD((LPSTR) pszMDBackupLocation,
  3666. dwMDVersion,
  3667. FALSE);
  3668. }
  3669. HRESULT STDMETHODCALLTYPE
  3670. CMDCOM::ComMDDeleteBackupW(
  3671. /* [string][in][unique] */ LPCWSTR pszMDBackupLocation,
  3672. /* [in] */ DWORD dwMDVersion)
  3673. {
  3674. return ComMDDeleteBackupD((LPSTR) pszMDBackupLocation,
  3675. dwMDVersion,
  3676. TRUE);
  3677. }
  3678. HRESULT STDMETHODCALLTYPE
  3679. CMDCOM::ComMDDeleteBackupD(
  3680. /* [in] */ LPSTR pszMDBackupLocation,
  3681. /* [in] */ DWORD dwMDVersion,
  3682. /* [in] */ BOOL bUnicode)
  3683. {
  3684. HRESULT hresReturn = ERROR_SUCCESS;
  3685. if (dwMDVersion == MD_BACKUP_NEXT_VERSION) {
  3686. //
  3687. // CreateBackupFileName checks for valid name,
  3688. // but it allows NEXT_VERSION, so we check that here.
  3689. //
  3690. hresReturn = E_INVALIDARG;
  3691. }
  3692. else {
  3693. MD_REQUIRE(WaitForSingleObject(g_hReadSaveSemaphore, INFINITE) != WAIT_TIMEOUT);
  3694. STRAU strauBackupLocation;
  3695. STRAU strauSchemaLocation;
  3696. hresReturn = CreateBackupFileName(pszMDBackupLocation,
  3697. dwMDVersion,
  3698. bUnicode,
  3699. &strauBackupLocation,
  3700. &strauSchemaLocation);
  3701. if (SUCCEEDED(hresReturn)) {
  3702. MD_ASSERT(strauBackupLocation.QueryStr(FALSE) != NULL);
  3703. //
  3704. // Delete the file
  3705. //
  3706. if (!DeleteFile(strauBackupLocation.QueryStr(FALSE)) ||
  3707. !DeleteFile(strauSchemaLocation.QueryStr(FALSE)) ) {
  3708. hresReturn = RETURNCODETOHRESULT(GetLastError());
  3709. }
  3710. }
  3711. MD_REQUIRE(ReleaseSemaphore(g_hReadSaveSemaphore, 1, NULL));
  3712. }
  3713. return hresReturn;
  3714. }
  3715. HRESULT STDMETHODCALLTYPE
  3716. CMDCOM::ComMDExportW(
  3717. /* [in] */ METADATA_HANDLE i_hMDHandle,
  3718. /* [string][in][unique] */ LPCWSTR i_wszPasswd,
  3719. /* [string][in][unique] */ LPCWSTR i_wszFileName,
  3720. /* [string][in][unique] */ LPCWSTR i_wszAbsSourcePath,
  3721. /* [in] */ DWORD i_dwMDFlags)
  3722. {
  3723. HRESULT hresReturn = ERROR_SUCCESS;
  3724. HRESULT hresWarning = ERROR_SUCCESS;
  3725. IIS_CRYPTO_STORAGE* pCryptoStorage = NULL;
  3726. PIIS_CRYPTO_BLOB pSessionKeyBlob = NULL;
  3727. //
  3728. // Validate parameters
  3729. //
  3730. if(i_wszFileName == NULL || i_wszAbsSourcePath == NULL)
  3731. {
  3732. return RETURNCODETOHRESULT(ERROR_INVALID_PARAMETER);
  3733. }
  3734. //
  3735. // Validate flags
  3736. //
  3737. if( (i_dwMDFlags & ~(MD_EXPORT_INHERITED | MD_EXPORT_NODE_ONLY)) != 0 &&
  3738. i_dwMDFlags != 0 )
  3739. {
  3740. return RETURNCODETOHRESULT(ERROR_INVALID_FLAGS);
  3741. }
  3742. //
  3743. // We need ansi versions of these
  3744. //
  3745. STRAU strauPasswd;
  3746. if (g_dwInitialized == 0)
  3747. {
  3748. return MD_ERROR_NOT_INITIALIZED;
  3749. }
  3750. if(!strauPasswd.Copy(i_wszPasswd == NULL ? L"" : (LPWSTR)i_wszPasswd))
  3751. {
  3752. return RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  3753. }
  3754. //
  3755. // TODO: Verify I need this semaphore.
  3756. // I think it is needed to read/write from the xml metabase. And, possibly
  3757. // for a temp file. I am not sure.
  3758. //
  3759. MD_REQUIRE(WaitForSingleObject(g_hReadSaveSemaphore, INFINITE) != WAIT_TIMEOUT);
  3760. //
  3761. // Never do machine dependent encryption.
  3762. //
  3763. pCryptoStorage = new IIS_CRYPTO_STORAGE2;
  3764. if( !pCryptoStorage )
  3765. {
  3766. hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  3767. }
  3768. else
  3769. {
  3770. hresReturn = InitStorageAndSessionKey2(
  3771. strauPasswd.QueryStrA(),
  3772. pCryptoStorage,
  3773. &pSessionKeyBlob);
  3774. }
  3775. if( SUCCEEDED(hresReturn) ) {
  3776. if (g_dwInitialized == 0) {
  3777. hresReturn = MD_ERROR_NOT_INITIALIZED;
  3778. }
  3779. else {
  3780. hresReturn = SaveSomeData(
  3781. i_dwMDFlags & MD_EXPORT_INHERITED,
  3782. i_dwMDFlags & MD_EXPORT_NODE_ONLY,
  3783. true, // bOverwriteFile
  3784. pCryptoStorage,
  3785. pSessionKeyBlob,
  3786. i_wszFileName,
  3787. i_hMDHandle,
  3788. i_wszAbsSourcePath,
  3789. TRUE);
  3790. }
  3791. ::IISCryptoFreeBlob2(pSessionKeyBlob);
  3792. }
  3793. // Now just set the file time
  3794. if (SUCCEEDED(hresReturn)) {
  3795. HANDLE hTempFileHandle;
  3796. hTempFileHandle = CreateFileW(i_wszFileName,
  3797. GENERIC_READ | GENERIC_WRITE,
  3798. 0,
  3799. NULL,
  3800. OPEN_EXISTING,
  3801. FILE_ATTRIBUTE_NORMAL,
  3802. 0);
  3803. if (hTempFileHandle != INVALID_HANDLE_VALUE) {
  3804. FILETIME ftCurrent;
  3805. GetSystemTimeAsFileTime(&ftCurrent);
  3806. SetFileTime(hTempFileHandle,
  3807. NULL, // Creation Time
  3808. &ftCurrent, // Last AccessTime
  3809. &ftCurrent); // Last Change Time
  3810. CloseHandle(hTempFileHandle);
  3811. }
  3812. //
  3813. // TODO: Figure out what this is and if i need it
  3814. //
  3815. /*hresReturn = BackupCertificates ((LPCWSTR)pszFileName,
  3816. strauFileName.QueryStr(FALSE),
  3817. g_strRealFileName->QueryStr());*/
  3818. }
  3819. MD_REQUIRE(ReleaseSemaphore(g_hReadSaveSemaphore, 1, NULL));
  3820. if (hresReturn == ERROR_SUCCESS) {
  3821. hresReturn = hresWarning;
  3822. }
  3823. if( pCryptoStorage )
  3824. {
  3825. delete pCryptoStorage;
  3826. pCryptoStorage = NULL;
  3827. }
  3828. return hresReturn;
  3829. }
  3830. HRESULT STDMETHODCALLTYPE
  3831. CMDCOM::ComMDImportW(
  3832. /* [in] */ METADATA_HANDLE i_hMDHandle,
  3833. /* [string][in][unique] */ LPCWSTR i_wszDestPath,
  3834. /* [string][in][unique] */ LPCWSTR i_wszKeyType,
  3835. /* [string][in][unique] */ LPCWSTR i_wszPasswd,
  3836. /* [string][in][unique] */ LPCWSTR i_wszFileName,
  3837. /* [string][in][unique] */ LPCWSTR i_wszSourcePath,
  3838. /* [in] */ DWORD i_dwMDFlags)
  3839. {
  3840. HRESULT hresReturn = ERROR_SUCCESS;
  3841. if (i_wszFileName == NULL ||
  3842. i_wszSourcePath == NULL ||
  3843. i_wszDestPath == NULL ||
  3844. i_wszKeyType == NULL)
  3845. {
  3846. return E_INVALIDARG;
  3847. }
  3848. //
  3849. // Validate flags
  3850. //
  3851. if( (i_dwMDFlags & ~(MD_IMPORT_INHERITED | MD_IMPORT_NODE_ONLY | MD_IMPORT_MERGE)) != 0 &&
  3852. i_dwMDFlags != 0 )
  3853. {
  3854. return RETURNCODETOHRESULT(ERROR_INVALID_FLAGS);
  3855. }
  3856. //
  3857. // We need ANSI versions of the following
  3858. //
  3859. STRAU strauPasswd;
  3860. if (g_dwInitialized == 0)
  3861. {
  3862. return MD_ERROR_NOT_INITIALIZED;
  3863. }
  3864. if(!strauPasswd.Copy(i_wszPasswd == NULL ? L"" : (LPWSTR)i_wszPasswd))
  3865. {
  3866. return E_OUTOFMEMORY;
  3867. }
  3868. CMDBaseObject* pboNew = NULL;
  3869. //
  3870. // Clean up source path.
  3871. //
  3872. ULONG cchSource = (ULONG)wcslen(i_wszSourcePath);
  3873. LPWSTR wszSource = new WCHAR[cchSource+1];
  3874. if(wszSource == NULL)
  3875. {
  3876. return RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  3877. }
  3878. for(ULONG i = 0; i <= cchSource; i++)
  3879. {
  3880. wszSource[i] = (i_wszSourcePath[i] == MD_ALT_PATH_DELIMETERW) ?
  3881. MD_PATH_DELIMETERW : i_wszSourcePath[i];
  3882. }
  3883. //
  3884. // Read the data from XML
  3885. //
  3886. if(SUCCEEDED(hresReturn))
  3887. {
  3888. hresReturn = ReadSomeDataFromXML(
  3889. strauPasswd.QueryStrA(),
  3890. (LPWSTR)i_wszFileName,
  3891. wszSource,
  3892. i_wszKeyType,
  3893. i_dwMDFlags,
  3894. FALSE, // do not have ReadSave semaphore
  3895. &pboNew);
  3896. if(FAILED(hresReturn)) {
  3897. DBGPRINTF(( DBG_CONTEXT,
  3898. "[CMDCOM::ComMDImportW] ReadSomeDataFromXML failed - error 0x%08lx\n", hresReturn));
  3899. }
  3900. }
  3901. //
  3902. // Copy the data into the metabase
  3903. //
  3904. if(SUCCEEDED(hresReturn)) {
  3905. hresReturn = CopyMetaObject(
  3906. NULL, //hMDSourceHandle
  3907. (LPBYTE)L"", //pszMDSourcePath
  3908. false, //bUseSourceHandle
  3909. pboNew, //we already have a pbo, use this instead
  3910. i_hMDHandle,
  3911. (LPBYTE)i_wszDestPath,
  3912. !(i_dwMDFlags & MD_IMPORT_MERGE),
  3913. TRUE, //bMDCopyFlag
  3914. TRUE //bUnicode
  3915. );
  3916. if(FAILED(hresReturn)) {
  3917. DBGPRINTF(( DBG_CONTEXT,
  3918. "[CMDCOM::ComMDImportW] CopyMetaObject failed - error 0x%08lx\n", hresReturn));
  3919. }
  3920. }
  3921. delete pboNew;
  3922. delete [] wszSource;
  3923. return hresReturn;
  3924. }
  3925. HRESULT STDMETHODCALLTYPE
  3926. CMDCOM::ComMDRestoreHistoryW(
  3927. /* [unique][in][string] */ LPCWSTR i_wszMDHistoryLocation,
  3928. /* [in] */ DWORD i_dwMDMajorVersion,
  3929. /* [in] */ DWORD i_dwMDMinorVersion,
  3930. /* [in] */ DWORD i_dwMDFlags)
  3931. {
  3932. int iLenHistoryLocation = 0;
  3933. HRESULT hresReturn = ERROR_SUCCESS;
  3934. //
  3935. // Validate string len
  3936. //
  3937. if(i_wszMDHistoryLocation)
  3938. {
  3939. for(iLenHistoryLocation = 0; iLenHistoryLocation < MD_BACKUP_MAX_LEN; iLenHistoryLocation++)
  3940. {
  3941. if(i_wszMDHistoryLocation[iLenHistoryLocation] == L'\0') break;
  3942. }
  3943. if(iLenHistoryLocation == MD_BACKUP_MAX_LEN)
  3944. {
  3945. hresReturn = E_INVALIDARG;
  3946. DBGERROR((DBG_CONTEXT, "hr=0x%x\n", hresReturn));
  3947. return hresReturn;
  3948. }
  3949. }
  3950. //
  3951. // Validate flags
  3952. //
  3953. if( (i_dwMDFlags & ~MD_HISTORY_LATEST) != 0 &&
  3954. i_dwMDFlags != 0 )
  3955. {
  3956. hresReturn = RETURNCODETOHRESULT(ERROR_INVALID_FLAGS);
  3957. DBGERROR((DBG_CONTEXT, "hr=0x%x\n", hresReturn));
  3958. return hresReturn;
  3959. }
  3960. LPWSTR wszHistoryPathPlusFile = NULL;
  3961. LPWSTR wszHistoryPathPlusSchema = NULL;
  3962. STRAU strauHistoryPathPlusFile;
  3963. STRAU strauHistoryPathPlusSchema;
  3964. LPCWSTR wszHistoryLocation = NULL;
  3965. ULONG cchHistoryLocation = NULL;
  3966. //
  3967. // Use i_wszMDHistoryLocation if supplied, else defaults
  3968. //
  3969. if(i_wszMDHistoryLocation == NULL || i_wszMDHistoryLocation[0] == L'\0' || iLenHistoryLocation == 0)
  3970. {
  3971. wszHistoryLocation = g_wszHistoryFileDir;
  3972. cchHistoryLocation = g_cchHistoryFileDir;
  3973. }
  3974. else
  3975. {
  3976. wszHistoryLocation = i_wszMDHistoryLocation;
  3977. cchHistoryLocation = iLenHistoryLocation;
  3978. }
  3979. //
  3980. // Construct wszHistoryPathPlusFile, wszHistoryPathPlusSchema
  3981. //
  3982. hresReturn = ConstructHistoryFileName(
  3983. &wszHistoryPathPlusFile,
  3984. (LPWSTR)wszHistoryLocation,
  3985. cchHistoryLocation,
  3986. g_wszRealFileNameWithoutPathWithoutExtension,
  3987. g_cchRealFileNameWithoutPathWithoutExtension,
  3988. g_wszRealFileNameExtension,
  3989. g_cchRealFileNameExtension,
  3990. i_dwMDMajorVersion,
  3991. i_dwMDMinorVersion);
  3992. if(FAILED(hresReturn))
  3993. {
  3994. DBGERROR((DBG_CONTEXT, "hr=0x%x\n", hresReturn));
  3995. goto exit;
  3996. }
  3997. hresReturn = ConstructHistoryFileName(
  3998. &wszHistoryPathPlusSchema,
  3999. (LPWSTR)wszHistoryLocation,
  4000. cchHistoryLocation,
  4001. g_wszSchemaFileNameWithoutPathWithoutExtension,
  4002. g_cchSchemaFileNameWithoutPathWithoutExtension,
  4003. g_wszSchemaFileNameExtension,
  4004. g_cchSchemaFileNameExtension,
  4005. i_dwMDMajorVersion,
  4006. i_dwMDMinorVersion);
  4007. if(FAILED(hresReturn))
  4008. {
  4009. DBGERROR((DBG_CONTEXT, "hr=0x%x\n", hresReturn));
  4010. goto exit;
  4011. }
  4012. //
  4013. // Use MD_HISTORY_LATEST flag if supplied
  4014. //
  4015. LPWSTR awszFiles[] = { wszHistoryPathPlusFile, wszHistoryPathPlusSchema, NULL };
  4016. LPWSTR awszExts[] = { g_wszRealFileNameExtension, g_wszSchemaFileNameExtension, NULL };
  4017. LPWSTR apInsert[] = { NULL, NULL, NULL };
  4018. if(i_dwMDFlags & MD_HISTORY_LATEST)
  4019. {
  4020. DWORD dwMajor = 0;
  4021. DWORD dwMinor = 0;
  4022. for(ULONG i = 0; awszFiles[i] != NULL; i++)
  4023. {
  4024. SIZE_T cch = wcslen(awszFiles[i]);
  4025. apInsert[i] = awszFiles[i] + cch;
  4026. apInsert[i] -= wcslen(awszExts[i]); // i.e. Go to start of: .xml
  4027. apInsert[i] -= MD_CCH_HISTORY_FILE_SEARCH_EXTENSIONW;
  4028. memcpy(
  4029. apInsert[i],
  4030. MD_HISTORY_FILE_SEARCH_EXTENSIONW,
  4031. (MD_CCH_HISTORY_FILE_SEARCH_EXTENSIONW) * sizeof(WCHAR));
  4032. }
  4033. hresReturn = GetMostRecentHistoryFile(
  4034. awszFiles[0], // this is: blah\metabase_??????????_??????????.xml
  4035. &dwMajor,
  4036. &dwMinor);
  4037. if(FAILED(hresReturn))
  4038. {
  4039. DBGERROR((DBG_CONTEXT, "hr=0x%x\n", hresReturn));
  4040. goto exit;
  4041. }
  4042. for(ULONG i = 0; apInsert[i] != NULL; i++)
  4043. {
  4044. // Move to first set of "?"
  4045. apInsert[i]++;
  4046. _snwprintf(apInsert[i], MD_DEFAULT_HISTORY_MAJOR_NUM_DIGITS, L"%010lu", dwMajor);
  4047. // Move to second set of "?"
  4048. apInsert[i] += MD_DEFAULT_HISTORY_MAJOR_NUM_DIGITS+1;
  4049. _snwprintf(apInsert[i], MD_DEFAULT_HISTORY_MINOR_NUM_DIGITS, L"%010lu", dwMinor);
  4050. }
  4051. }
  4052. if(!strauHistoryPathPlusFile.Copy(wszHistoryPathPlusFile))
  4053. {
  4054. hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  4055. DBGERROR((DBG_CONTEXT, "hr=0x%x\n", hresReturn));
  4056. goto exit;
  4057. }
  4058. if(!strauHistoryPathPlusSchema.Copy(wszHistoryPathPlusSchema))
  4059. {
  4060. hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  4061. DBGERROR((DBG_CONTEXT, "hr=0x%x\n", hresReturn));
  4062. goto exit;
  4063. }
  4064. hresReturn = Restore(
  4065. NULL,
  4066. &strauHistoryPathPlusFile,
  4067. &strauHistoryPathPlusSchema,
  4068. NULL);
  4069. if(FAILED(hresReturn))
  4070. {
  4071. DBGERROR((DBG_CONTEXT, "hr=0x%x\n", hresReturn));
  4072. goto exit;
  4073. }
  4074. exit:
  4075. delete [] wszHistoryPathPlusFile;
  4076. delete [] wszHistoryPathPlusSchema;
  4077. return hresReturn;
  4078. }
  4079. HRESULT STDMETHODCALLTYPE
  4080. CMDCOM::ComMDEnumHistoryW(
  4081. /* [size_is (MD_BACKUP_MAX_LEN)][in, out] */ LPWSTR io_wszMDHistoryLocation,
  4082. /* [out] */ DWORD *o_pdwMDMajorVersion,
  4083. /* [out] */ DWORD *o_pdwMDMinorVersion,
  4084. /* [out] */ PFILETIME o_pftMDHistoryTime,
  4085. /* [in] */ DWORD i_dwMDEnumIndex)
  4086. {
  4087. STRAU strauPattern;
  4088. int iLenHistoryLocation;
  4089. HRESULT hresReturn = ERROR_SUCCESS;
  4090. //
  4091. // Copies of out params
  4092. //
  4093. DWORD dwMDMajorVersion;
  4094. DWORD dwMDMinorVersion;
  4095. FILETIME ftMDHistoryTime;
  4096. //
  4097. // Validate parameters
  4098. //
  4099. if(io_wszMDHistoryLocation == NULL || o_pdwMDMajorVersion == NULL ||
  4100. o_pdwMDMinorVersion == NULL || o_pftMDHistoryTime == NULL) {
  4101. return E_INVALIDARG;
  4102. }
  4103. //
  4104. // Validate string len
  4105. //
  4106. for(iLenHistoryLocation = 0; iLenHistoryLocation < MD_BACKUP_MAX_LEN; iLenHistoryLocation++)
  4107. {
  4108. if(io_wszMDHistoryLocation[iLenHistoryLocation] == L'\0') break;
  4109. }
  4110. if(iLenHistoryLocation == MD_BACKUP_MAX_LEN) {
  4111. return E_INVALIDARG;
  4112. }
  4113. MD_REQUIRE(WaitForSingleObject(g_hReadSaveSemaphore, INFINITE) != WAIT_TIMEOUT);
  4114. //
  4115. // Eg. c:\windows\system32\inetsrv\history\
  4116. //
  4117. if(io_wszMDHistoryLocation[0] == L'\0') {
  4118. //
  4119. // TODO: Get more meaningful hr
  4120. //
  4121. if(wcslen(g_wszHistoryFileDir) > MD_BACKUP_MAX_LEN-1) {
  4122. hresReturn = E_INVALIDARG;
  4123. goto exit;
  4124. }
  4125. if(!strauPattern.Copy(g_wszHistoryFileDir)) {
  4126. hresReturn = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  4127. goto exit;
  4128. }
  4129. }
  4130. else {
  4131. if(!strauPattern.Copy(io_wszMDHistoryLocation)) {
  4132. hresReturn = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  4133. goto exit;
  4134. }
  4135. if(io_wszMDHistoryLocation[iLenHistoryLocation-1] != L'\\') {
  4136. if(!strauPattern.Append(L"\\")) {
  4137. hresReturn = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  4138. goto exit;
  4139. }
  4140. }
  4141. }
  4142. //
  4143. // Eg. c:\windows\system32\inetsrv\history\metabase_??????????_??????????.xml
  4144. //
  4145. if(!strauPattern.Append(g_wszRealFileNameWithoutPathWithoutExtension)) {
  4146. hresReturn = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  4147. goto exit;
  4148. }
  4149. if(!strauPattern.Append(MD_HISTORY_FILE_SEARCH_EXTENSIONW)) {
  4150. hresReturn = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  4151. goto exit;
  4152. }
  4153. if(!strauPattern.Append(g_wszRealFileNameExtension)) {
  4154. hresReturn = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  4155. goto exit;
  4156. }
  4157. hresReturn = EnumFiles(strauPattern.QueryStrW(),
  4158. i_dwMDEnumIndex,
  4159. &dwMDMajorVersion,
  4160. &dwMDMinorVersion,
  4161. &ftMDHistoryTime);
  4162. if(FAILED(hresReturn)) {
  4163. goto exit;
  4164. }
  4165. //
  4166. // If everything succeeded, set out parameters
  4167. //
  4168. if(io_wszMDHistoryLocation[0] == L'\0') {
  4169. if( wcslen( g_wszHistoryFileDir ) < MD_BACKUP_MAX_LEN )
  4170. {
  4171. wcscpy(io_wszMDHistoryLocation, g_wszHistoryFileDir);
  4172. }
  4173. else
  4174. {
  4175. hresReturn = HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER );
  4176. goto exit;
  4177. }
  4178. }
  4179. *o_pdwMDMajorVersion = dwMDMajorVersion;
  4180. *o_pdwMDMinorVersion = dwMDMinorVersion;
  4181. memcpy(o_pftMDHistoryTime, &ftMDHistoryTime, sizeof(FILETIME));
  4182. exit:
  4183. MD_REQUIRE(ReleaseSemaphore(g_hReadSaveSemaphore, 1, NULL));
  4184. return hresReturn;
  4185. }
  4186. HRESULT STDMETHODCALLTYPE
  4187. CMDCOM::ComMDGetChildPathsW(
  4188. /* [in] */ METADATA_HANDLE hMDHandle,
  4189. /* [unique, in, string] */ LPCWSTR pszMDPath,
  4190. /* [in] */ DWORD cchMDBufferSize,
  4191. /* [out, size_is(dwMDBufferSize)] */ WCHAR *pszBuffer,
  4192. /* [out] */ DWORD *pcchMDRequiredBufferSize)
  4193. /*++
  4194. Routine Description:
  4195. Retrieves all child metaobjects by name and places them in a MULTISZ containing strings terminated by an empty string
  4196. Arguments:
  4197. Handle - METADATA_MASTER_ROOT_HANDLE or a handle returned by MDOpenMetaObject with read permission.
  4198. Path - Path of parent object, relative to the path of Handle.
  4199. eg. "Root Object/Child/GrandChild"
  4200. cchMDBufferSize - sizeof buffer passed in, in wchars
  4201. pszBuffer - buffer, allocated by caller, that result is placed into
  4202. pcchMDRequiredBufferSize - required size, filled in only if buffer is insufficient
  4203. Return Value:
  4204. HRESULT, S_OK on success
  4205. --*/
  4206. {
  4207. HRESULT hresReturn = ERROR_SUCCESS;
  4208. PBASEOBJECT_CONTAINER pboContainer = NULL;
  4209. CMDBaseObject *pboAffected = NULL;
  4210. LPSTR pszPath = (LPSTR)pszMDPath;
  4211. BOOL fLocked = FALSE;
  4212. BUFFER buffTemp;
  4213. size_t stCurrentSize = 0;
  4214. BOOL fRet = TRUE;
  4215. if (g_dwInitialized == 0)
  4216. {
  4217. hresReturn = MD_ERROR_NOT_INITIALIZED;
  4218. goto done;
  4219. }
  4220. fLocked = TRUE;
  4221. g_LockMasterResource.ReadLock();
  4222. hresReturn = GetObjectFromPath(pboAffected, hMDHandle, METADATA_PERMISSION_READ, pszPath, TRUE);
  4223. if (FAILED(hresReturn))
  4224. {
  4225. goto done;
  4226. }
  4227. if ( pboAffected == NULL )
  4228. {
  4229. hresReturn = E_FAIL;
  4230. goto done;
  4231. }
  4232. // get the beginning of the child list (NULL)
  4233. pboContainer = pboAffected->NextChildObject(NULL);
  4234. while (pboContainer != NULL )
  4235. {
  4236. CMDBaseObject * pboChild;
  4237. pboChild = pboContainer->pboMetaObject;
  4238. // get the name of the child (the TRUE indicates in UNICODE)
  4239. LPWSTR pszName = (LPWSTR)pboChild->GetName(TRUE);
  4240. if (pszName == NULL)
  4241. {
  4242. hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  4243. goto done;
  4244. }
  4245. size_t stNameLen = wcslen(pszName);
  4246. // the new size is the current size + length of new string + 1 for terminating NULL
  4247. size_t stNewSize = stCurrentSize + stNameLen + 1;
  4248. fRet = buffTemp.Resize((UINT)(stNewSize * sizeof(WCHAR)), (UINT)(stNewSize * sizeof(WCHAR)));
  4249. if (FALSE == fRet)
  4250. {
  4251. hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  4252. goto done;
  4253. }
  4254. // setup the destination pointer for the current name
  4255. WCHAR *pDest = (WCHAR*)buffTemp.QueryPtr();
  4256. pDest += stCurrentSize;
  4257. // actually do the copy
  4258. memcpy(pDest, pszName, sizeof(WCHAR) * (stNameLen + 1));
  4259. // get the size setup for the next iteration of the loop
  4260. stCurrentSize = stNewSize;
  4261. // get the next child in the list
  4262. pboContainer = pboAffected->NextChildObject(pboContainer);
  4263. }
  4264. if (0 == stCurrentSize)
  4265. {
  4266. // there were no children, place a NULL into the buffer.
  4267. fRet = buffTemp.Resize(sizeof(WCHAR), 0);
  4268. if (FALSE == fRet)
  4269. {
  4270. hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  4271. goto done;
  4272. }
  4273. WCHAR *pDest = (WCHAR*)buffTemp.QueryPtr();
  4274. pDest[0] = '\0';
  4275. // and setup the currentsize correctly
  4276. stCurrentSize = 1;
  4277. }
  4278. // require one extra character for the extra terminating NULL
  4279. if (cchMDBufferSize >= (stCurrentSize + 1))
  4280. {
  4281. if (pszBuffer)
  4282. {
  4283. // copy over from the buffer to the outgoing buffer
  4284. memcpy(pszBuffer, buffTemp.QueryPtr(), stCurrentSize * sizeof(WCHAR));
  4285. // add the final terminating null
  4286. *( pszBuffer + stCurrentSize ) = L'\0';
  4287. // everything suceeded
  4288. hresReturn = ERROR_SUCCESS;
  4289. }
  4290. else
  4291. {
  4292. // received a buffer size that was large enough, but no buffer
  4293. hresReturn = HRESULT_FROM_WIN32(ERROR_BAD_ARGUMENTS);
  4294. }
  4295. }
  4296. else if (pcchMDRequiredBufferSize)
  4297. {
  4298. // didn't receive a large enough buffer.
  4299. // indicate the required size
  4300. *pcchMDRequiredBufferSize = (DWORD)(stCurrentSize + 1);
  4301. // and there was insufficient buffer
  4302. hresReturn = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  4303. }
  4304. else
  4305. {
  4306. // passed in buffer wasn't large enough, and nowhere to store the needed size
  4307. hresReturn = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  4308. }
  4309. done:
  4310. if (fLocked)
  4311. {
  4312. g_LockMasterResource.ReadUnlock();
  4313. }
  4314. return hresReturn;
  4315. }
  4316. HRESULT STDMETHODCALLTYPE
  4317. CMDCOM::ComMDStopEWR(VOID)
  4318. /*++
  4319. Routine Description:
  4320. Signal EWR to stop and waits for EWR thread to exit.
  4321. This must be done before ABO terminates, because EWR uses ABO although living in metadata.
  4322. Arguments:
  4323. None
  4324. Return Value:
  4325. HRESULT
  4326. --*/
  4327. {
  4328. // Locals
  4329. HRESULT hr = S_OK;
  4330. CListenerController * pListenerController = NULL;
  4331. if ( g_pListenerController == NULL )
  4332. {
  4333. goto exit;
  4334. }
  4335. g_LockMasterResource.ReadLock();
  4336. pListenerController = g_pListenerController;
  4337. if (pListenerController != NULL )
  4338. {
  4339. pListenerController->AddRef();
  4340. }
  4341. g_LockMasterResource.ReadUnlock();
  4342. if ( pListenerController != NULL )
  4343. {
  4344. hr = pListenerController->Stop( iSTATE_STOP_PERMANENT, NULL );
  4345. }
  4346. exit:
  4347. if ( pListenerController != NULL )
  4348. {
  4349. pListenerController->Release();
  4350. pListenerController = NULL;
  4351. }
  4352. return hr;
  4353. }
  4354. HRESULT CMDCOM::Restore(
  4355. LPSTR i_pszMDBackupLocation,
  4356. STRAU* i_pstrauFile,
  4357. STRAU* i_pstrauSchema,
  4358. LPSTR i_pszPasswd)
  4359. /*++
  4360. Synopsis:
  4361. Private method used by Restore and RestoreHistory
  4362. Arguments: [i_pszMDBackupLocation] - can be NULL
  4363. [i_pstrauFile] -
  4364. [i_pstrauSchema] -
  4365. [i_pszPasswd] - can be NULL (always NULL in case of RestoreHistory)
  4366. Return Value:
  4367. --*/
  4368. {
  4369. MD_ASSERT(i_pstrauFile);
  4370. MD_ASSERT(i_pstrauSchema);
  4371. HRESULT hresReturn = S_OK;
  4372. DWORD dwInitializedSave = 0;
  4373. //
  4374. // Send notifications before we grab locks in case users
  4375. // try to access metabase. It would be nice to check the
  4376. // file name before doing this but that requires ReadSaveSemaphore.
  4377. //
  4378. // Send Shutdown Notification since we don't have a Restore
  4379. // Notification and it's close enough.
  4380. //
  4381. SendShutdownNotifications();
  4382. //
  4383. // Give applications some time to close their interfaces,
  4384. // but don't wait too long, user is waiting.
  4385. // Wait until references are closed, unless they take too long.
  4386. // IISADMIN and factory both have refences we do not wait for.
  4387. //
  4388. // We don't actually need to wait during restore, since
  4389. // interfaces are preserved, but waiting will allow clients
  4390. // to cleanup properly.
  4391. //
  4392. for (int i = 0;
  4393. (InterlockedIncrement((long *)&m_dwRefCount) > 3) &&
  4394. (i < MD_SHUTDOWN_WAIT_SECONDS);
  4395. i++) {
  4396. InterlockedDecrement((long *)&m_dwRefCount);
  4397. Sleep(1000);
  4398. }
  4399. InterlockedDecrement((long *)&m_dwRefCount);
  4400. MD_REQUIRE(WaitForSingleObject(g_hReadSaveSemaphore, INFINITE) != WAIT_TIMEOUT);
  4401. if (SUCCEEDED(hresReturn)) {
  4402. //
  4403. // Got a valid name
  4404. // See if the file exists
  4405. //
  4406. MD_ASSERT(i_pstrauFile->QueryStr(FALSE) != NULL);
  4407. MD_ASSERT(i_pstrauSchema->QueryStr(FALSE) != NULL);
  4408. HANDLE hFile = INVALID_HANDLE_VALUE;
  4409. WIN32_FIND_DATA wfdFile;
  4410. STR strCopyOfMetabaseFileName (*g_strRealFileName);
  4411. hFile = FindFirstFile(i_pstrauFile->QueryStrA(),
  4412. &wfdFile);
  4413. if (hFile == INVALID_HANDLE_VALUE) {
  4414. hresReturn = RETURNCODETOHRESULT(GetLastError());
  4415. DBGERROR((DBG_CONTEXT, "hr=0x%x\n", hresReturn));
  4416. }
  4417. else {
  4418. FindClose(hFile);
  4419. //
  4420. // File actually exists,
  4421. // Go ahead and restore.
  4422. //
  4423. g_LockMasterResource.WriteLock();
  4424. //
  4425. // Prevent saves during termination.
  4426. //
  4427. BOOL bPrevSaveDisallowed = g_bSaveDisallowed;
  4428. g_bSaveDisallowed = TRUE;
  4429. dwInitializedSave = 0;
  4430. if( g_dwInitialized != 0 )
  4431. {
  4432. dwInitializedSave = g_dwInitialized;
  4433. while (g_dwInitialized > 0) {
  4434. TerminateWorker1(TRUE);
  4435. }
  4436. }
  4437. g_bSaveDisallowed = bPrevSaveDisallowed;
  4438. while (SUCCEEDED(hresReturn) && (g_dwInitialized < dwInitializedSave))
  4439. {
  4440. hresReturn = InitWorker(TRUE,
  4441. i_pszPasswd,
  4442. i_pstrauFile->QueryStr(FALSE),
  4443. i_pstrauSchema->QueryStr(FALSE));
  4444. if(HRESULT_FACILITY(hresReturn) == FACILITY_CONFIGURATION)
  4445. {
  4446. //
  4447. // Some facility_configuration errors are converted to md_error
  4448. // in InitWorker. For the remainder, this has to suffice.
  4449. //
  4450. DBGERROR((DBG_CONTEXT,
  4451. "[CMDCOM::Restore] InitWorker returned hr=0x%x\n", hresReturn));
  4452. hresReturn = MD_ERROR_READ_METABASE_FILE;
  4453. }
  4454. }
  4455. if( SUCCEEDED(hresReturn) && i_pszMDBackupLocation)
  4456. {
  4457. RestoreCertificates ((LPCWSTR)i_pszMDBackupLocation,
  4458. i_pstrauFile->QueryStr(FALSE),
  4459. strCopyOfMetabaseFileName.QueryStr());
  4460. }
  4461. //
  4462. // Need to flush the newly restored data out
  4463. //
  4464. g_dwSystemChangeNumber++;
  4465. g_dwSchemaChangeNumber++;
  4466. g_LockMasterResource.WriteUnlock();
  4467. //
  4468. // At this point all old handles are invalidated
  4469. // and all no new handles have been opened.
  4470. // So tell clients to invalidate any open handles now.
  4471. //
  4472. if (SUCCEEDED(hresReturn)) {
  4473. SendEventNotifications(MD_EVENT_MID_RESTORE);
  4474. }
  4475. }
  4476. }
  4477. MD_REQUIRE(ReleaseSemaphore(g_hReadSaveSemaphore, 1, NULL));
  4478. //
  4479. // Try to load metadata from metabase.bin file on failure
  4480. //
  4481. if( FAILED( hresReturn ) )
  4482. {
  4483. HRESULT hrTemp = S_OK;
  4484. while (SUCCEEDED(hrTemp) && (g_dwInitialized < dwInitializedSave))
  4485. {
  4486. hrTemp = InitWorker(FALSE, NULL, NULL, NULL);
  4487. //
  4488. // Some facility_configuration errors are converted to md_error
  4489. // in InitWorker. For the remainder, this has to suffice.
  4490. //
  4491. if(HRESULT_FACILITY(hresReturn) == FACILITY_CONFIGURATION)
  4492. {
  4493. DBGERROR((DBG_CONTEXT,
  4494. "[CMDCOM::Restore] InitWorker returned hr=0x%x\n", hresReturn));
  4495. hresReturn = MD_ERROR_READ_METABASE_FILE;
  4496. }
  4497. }
  4498. }
  4499. else
  4500. {
  4501. //
  4502. // Need to flush newly restored data to Metabase.bin file
  4503. //
  4504. hresReturn = ComMDSaveData( METADATA_MASTER_ROOT_HANDLE );
  4505. }
  4506. if(FAILED(hresReturn))
  4507. {
  4508. DBGERROR((DBG_CONTEXT, "hr=0x%x\n", hresReturn));
  4509. }
  4510. return hresReturn;
  4511. }
  4512. /*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
  4513. Method: COPaper::NotifySinks
  4514. Summary: Internal utility method of this COM object used to fire event
  4515. notification calls to all listening connection sinks in the
  4516. client.
  4517. Modifies: ...
  4518. Returns: HRESULT
  4519. Standard COM result code. S_OK for success.
  4520. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/
  4521. HRESULT
  4522. CMDCOM::NotifySinks(
  4523. METADATA_HANDLE hHandle,
  4524. PMD_CHANGE_OBJECT pcoChangeList,
  4525. DWORD dwNumEntries,
  4526. BOOL bUnicode,
  4527. DWORD dwNotificationType,
  4528. DWORD dwEvent)
  4529. {
  4530. HRESULT hr = S_OK;
  4531. HRESULT hrT = S_OK;
  4532. COConnectionPoint *pCoConnectionPoint = NULL;
  4533. CONNECTDATA *pConnData = NULL;
  4534. ULONG cConnData = 0;
  4535. ULONG i;
  4536. IMDCOMSINKA *pIMDCOMSINKA = NULL;
  4537. IMDCOMSINKW *pIMDCOMSINKW = NULL;
  4538. DBG_ASSERT( ( dwNotificationType == MD_SINK_MAIN ) ||
  4539. ( dwNotificationType == MD_SINK_SHUTDOWN ) ||
  4540. ( ( dwNotificationType == MD_SINK_EVENT ) && bUnicode ) );
  4541. FlushSomeData();
  4542. if ( bUnicode )
  4543. {
  4544. pCoConnectionPoint = (COConnectionPoint*)m_aConnectionPoints[MD_CONNPOINT_WRITESINK_W];
  4545. }
  4546. else
  4547. {
  4548. pCoConnectionPoint = (COConnectionPoint*)m_aConnectionPoints[MD_CONNPOINT_WRITESINK_A];
  4549. }
  4550. if ( pCoConnectionPoint == NULL )
  4551. {
  4552. goto exit;
  4553. }
  4554. pCoConnectionPoint->AddRef();
  4555. hr = pCoConnectionPoint->InternalEnumSinks( &pConnData, &cConnData );
  4556. if ( FAILED( hr ) || ( cConnData == 0 ) )
  4557. {
  4558. goto exit;
  4559. }
  4560. if (bUnicode)
  4561. {
  4562. // Loop thru the connection point's connections
  4563. // dispatch the event notification to that sink.
  4564. for ( i = 0; i<cConnData; i++ )
  4565. {
  4566. DBG_ASSERT( pConnData[i].pUnk != NULL );
  4567. hrT = pConnData[i].pUnk->QueryInterface( IID_IMDCOMSINK_W,
  4568. (VOID**)&pIMDCOMSINKW );
  4569. if ( FAILED( hrT ) )
  4570. {
  4571. continue;
  4572. }
  4573. DBG_ASSERT( pIMDCOMSINKW != NULL );
  4574. switch ( dwNotificationType )
  4575. {
  4576. case MD_SINK_MAIN:
  4577. pIMDCOMSINKW->ComMDSinkNotify( hHandle,
  4578. dwNumEntries,
  4579. (PMD_CHANGE_OBJECT_W)pcoChangeList );
  4580. break;
  4581. case MD_SINK_SHUTDOWN:
  4582. //
  4583. // Shutdown Notifications
  4584. //
  4585. pIMDCOMSINKW->ComMDShutdownNotify();
  4586. break;
  4587. case MD_SINK_EVENT:
  4588. pIMDCOMSINKW->ComMDEventNotify( dwEvent );
  4589. break;
  4590. }
  4591. pIMDCOMSINKW->Release();
  4592. pIMDCOMSINKW = NULL;
  4593. }
  4594. }
  4595. else
  4596. {
  4597. // Loop thru the connection point's connections
  4598. // dispatch the event notification to that sink.
  4599. for ( i = 0; i<cConnData; i++ )
  4600. {
  4601. DBG_ASSERT( pConnData[i].pUnk != NULL );
  4602. hrT = pConnData[i].pUnk->QueryInterface( IID_IMDCOMSINK_A,
  4603. (VOID**)&pIMDCOMSINKA );
  4604. if ( FAILED( hrT ) )
  4605. {
  4606. continue;
  4607. }
  4608. DBG_ASSERT( pIMDCOMSINKA != NULL );
  4609. switch ( dwNotificationType )
  4610. {
  4611. case MD_SINK_MAIN:
  4612. pIMDCOMSINKA->ComMDSinkNotify( hHandle,
  4613. dwNumEntries,
  4614. (PMD_CHANGE_OBJECT_A)pcoChangeList );
  4615. break;
  4616. case MD_SINK_SHUTDOWN:
  4617. //
  4618. // Shutdown Notifications
  4619. //
  4620. pIMDCOMSINKA->ComMDShutdownNotify();
  4621. break;
  4622. }
  4623. pIMDCOMSINKA->Release();
  4624. pIMDCOMSINKA = NULL;
  4625. }
  4626. }
  4627. exit:
  4628. DBG_ASSERT( pIMDCOMSINKA == NULL );
  4629. DBG_ASSERT( pIMDCOMSINKW == NULL );
  4630. if ( pConnData != NULL )
  4631. {
  4632. for ( i = 0; i<cConnData; i++ )
  4633. {
  4634. if ( pConnData[i].pUnk != NULL )
  4635. {
  4636. pConnData[i].pUnk->Release();
  4637. pConnData[i].pUnk = NULL;
  4638. }
  4639. }
  4640. delete [] pConnData;
  4641. pConnData = NULL;
  4642. }
  4643. if ( pCoConnectionPoint != NULL )
  4644. {
  4645. pCoConnectionPoint->Release();
  4646. pCoConnectionPoint = NULL;
  4647. }
  4648. return hr;
  4649. }
  4650. HRESULT
  4651. CMDCOM::ConvertNotificationsToDBCS(DWORD dwNumChangeEntries,
  4652. BUFFER **ppbufStorageArray)
  4653. {
  4654. HRESULT hresReturn = S_OK;
  4655. //
  4656. // ppbufStorageArray is an array of buffer pointers,
  4657. // where each buffer contains a UNICODE path string
  4658. // which needs to be converted to a Local System path string
  4659. //
  4660. STRAU strauPath;
  4661. STRAU strauPathOptional;
  4662. LPSTR pszDBCSPath;
  4663. LPSTR pszDBCSPathOptional = NULL;
  4664. LPSTR pmultiszTarget;
  4665. DWORD dwStrLen1,dwStrLen2 = 0;
  4666. for (DWORD i = 0; i < dwNumChangeEntries; i++) {
  4667. MD_ASSERT(ppbufStorageArray[i] != NULL);
  4668. pmultiszTarget = (LPSTR) ppbufStorageArray[i]->QueryPtr();
  4669. if (!strauPath.Copy((LPWSTR)pmultiszTarget))
  4670. {
  4671. hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  4672. }
  4673. else {
  4674. if ((PWORD)(pmultiszTarget + strauPath.QueryCBW() + sizeof (WCHAR)))
  4675. {
  4676. if (!strauPathOptional.Copy((LPWSTR)(pmultiszTarget + strauPath.QueryCBW() + sizeof (WCHAR))))
  4677. {
  4678. hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  4679. }
  4680. else
  4681. {
  4682. pszDBCSPathOptional = strauPathOptional.QueryStrA();
  4683. if (pszDBCSPathOptional == NULL)
  4684. {
  4685. hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  4686. }
  4687. else
  4688. {
  4689. dwStrLen2 = strauPathOptional.QueryCBA() + 1 ;
  4690. }
  4691. }
  4692. }
  4693. if (hresReturn == S_OK)
  4694. {
  4695. pszDBCSPath = strauPath.QueryStrA();
  4696. if (pszDBCSPath == NULL) {
  4697. hresReturn = RETURNCODETOHRESULT(ERROR_NOT_ENOUGH_MEMORY);
  4698. }
  4699. else
  4700. {
  4701. dwStrLen1 = strauPath.QueryCBA() + 1 ;
  4702. MD_ASSERT(ppbufStorageArray[i]->QuerySize() >= (dwStrLen1 + dwStrLen2 + sizeof(char)));
  4703. MD_COPY(pmultiszTarget, pszDBCSPath, dwStrLen1 );
  4704. if ( ( dwStrLen2 >0 ) && ( pszDBCSPathOptional != NULL ) )
  4705. {
  4706. MD_COPY(pmultiszTarget + dwStrLen1 , pszDBCSPathOptional, dwStrLen2 );
  4707. }
  4708. *(pmultiszTarget + dwStrLen1 + dwStrLen2) = '\0';
  4709. }
  4710. }
  4711. }
  4712. }
  4713. return hresReturn;
  4714. }
  4715. VOID
  4716. CMDCOM::SendShutdownNotifications()
  4717. {
  4718. NotifySinks(0,
  4719. NULL,
  4720. 0,
  4721. TRUE,
  4722. MD_SINK_SHUTDOWN);
  4723. NotifySinks(0,
  4724. NULL,
  4725. 0,
  4726. FALSE,
  4727. MD_SINK_SHUTDOWN);
  4728. }
  4729. VOID
  4730. CMDCOM::SendEventNotifications(DWORD dwEvent)
  4731. {
  4732. NotifySinks(0,
  4733. NULL,
  4734. 0,
  4735. TRUE,
  4736. MD_SINK_EVENT,
  4737. dwEvent);
  4738. }
  4739. VOID
  4740. CMDCOM::SendNotifications(METADATA_HANDLE hHandle,
  4741. DWORD dwTotalNumChangeEntries,
  4742. PMD_CHANGE_OBJECT_W pcoBuffer,
  4743. BUFFER **ppbufStorageArray
  4744. )
  4745. {
  4746. DWORD dwNumChangeEntries;
  4747. DWORD dwRemainingNumChangeEntries = dwTotalNumChangeEntries;
  4748. while (dwRemainingNumChangeEntries != 0) {
  4749. dwNumChangeEntries = LESSOROF(dwRemainingNumChangeEntries, MD_MAX_CHANGE_ENTRIES);
  4750. NotifySinks(hHandle,
  4751. (PMD_CHANGE_OBJECT)(pcoBuffer + (dwTotalNumChangeEntries - dwRemainingNumChangeEntries)),
  4752. dwNumChangeEntries,
  4753. TRUE,
  4754. MD_SINK_MAIN);
  4755. dwRemainingNumChangeEntries -= dwNumChangeEntries;
  4756. }
  4757. if (SUCCEEDED(ConvertNotificationsToDBCS(dwTotalNumChangeEntries,
  4758. ppbufStorageArray))) {
  4759. dwRemainingNumChangeEntries = dwTotalNumChangeEntries;
  4760. while (dwRemainingNumChangeEntries != 0) {
  4761. dwNumChangeEntries = LESSOROF(dwRemainingNumChangeEntries, MD_MAX_CHANGE_ENTRIES);
  4762. NotifySinks(hHandle,
  4763. (PMD_CHANGE_OBJECT)(pcoBuffer + (dwTotalNumChangeEntries - dwRemainingNumChangeEntries)),
  4764. dwNumChangeEntries,
  4765. FALSE,
  4766. MD_SINK_MAIN);
  4767. dwRemainingNumChangeEntries -= dwNumChangeEntries;
  4768. }
  4769. }
  4770. }
  4771. VOID
  4772. CMDCOM::DeleteNotifications(DWORD dwNumChangeEntries,
  4773. PMD_CHANGE_OBJECT_W pcoBuffer,
  4774. BUFFER **ppbufStorageArray
  4775. )
  4776. {
  4777. if (dwNumChangeEntries != 0 )
  4778. {
  4779. if( ppbufStorageArray != NULL )
  4780. {
  4781. for( DWORD i = 0; i < dwNumChangeEntries; i++ )
  4782. {
  4783. if (ppbufStorageArray[i] != NULL)
  4784. {
  4785. delete ppbufStorageArray[i];
  4786. ppbufStorageArray[i] = NULL;
  4787. }
  4788. }
  4789. delete [] ppbufStorageArray;
  4790. }
  4791. delete pcoBuffer;
  4792. }
  4793. }
  4794. HRESULT
  4795. CMDCOM::CreateNotifications(CMDHandle *phoHandle,
  4796. DWORD *pdwNumChangeEntries,
  4797. PMD_CHANGE_OBJECT_W *ppcoBuffer,
  4798. BUFFER ***pppbufStorageArray
  4799. )
  4800. {
  4801. HRESULT hRes = ERROR_SUCCESS;
  4802. DWORD dwReturn = ERROR_SUCCESS;
  4803. PCHANGE_ENTRY pceChange;
  4804. DWORD i;
  4805. BUFFER **ppbufStorageArray = NULL;
  4806. DWORD dwStringLen, dwStringOldNameLen;
  4807. DWORD dwNumChangeEntries;
  4808. PMD_CHANGE_OBJECT_W pcoBuffer = NULL;
  4809. dwNumChangeEntries = phoHandle->GetNumChangeEntries();
  4810. if (dwNumChangeEntries != 0) {
  4811. ppbufStorageArray = new BUFFER *[dwNumChangeEntries];
  4812. if (ppbufStorageArray == NULL) {
  4813. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  4814. }
  4815. else {
  4816. for (i = 0; i < dwNumChangeEntries; i++) {
  4817. ppbufStorageArray[i] = new BUFFER();
  4818. if (ppbufStorageArray[i] == NULL) {
  4819. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  4820. }
  4821. }
  4822. if (dwReturn == ERROR_SUCCESS) {
  4823. //
  4824. // Create UNICODE callbacks
  4825. //
  4826. pcoBuffer = new MD_CHANGE_OBJECT_W[dwNumChangeEntries];
  4827. if (pcoBuffer == NULL) {
  4828. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  4829. }
  4830. else {
  4831. for (i = 0;
  4832. (dwReturn == ERROR_SUCCESS) && (i < dwNumChangeEntries);
  4833. i++) {
  4834. MD_REQUIRE((pceChange = phoHandle->EnumChangeEntries(i)) != NULL);
  4835. dwStringLen = 0;
  4836. dwReturn = GetObjectPath(pceChange->pboChanged,
  4837. ppbufStorageArray[i],
  4838. dwStringLen,
  4839. g_pboMasterRoot,
  4840. TRUE);
  4841. if (dwReturn == ERROR_SUCCESS) {
  4842. dwStringOldNameLen = 0;
  4843. if ( pceChange->pStrOrigName !=NULL) {
  4844. dwStringOldNameLen = pceChange->pStrOrigName->QueryCCH ();
  4845. }
  4846. // we adding 5, because: 1 for path_delimiter first line 1 for term-zero for first line
  4847. // 1 for path_delimiter second line 1 for term-zero for second line
  4848. // and last 1 for multisz term-zero
  4849. if (!ppbufStorageArray[i]->Resize((dwStringLen + dwStringOldNameLen + 5 ) * sizeof(WCHAR))) {
  4850. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  4851. }
  4852. else {
  4853. pcoBuffer[i].dwMDChangeType = pceChange->dwChangeType;
  4854. pcoBuffer[i].pszMDPath = (LPWSTR)(ppbufStorageArray[i]->QueryPtr());
  4855. pcoBuffer[i].pszMDPath[dwStringLen] = MD_PATH_DELIMETERW;
  4856. pcoBuffer[i].pszMDPath[dwStringLen + 1] = (WCHAR)L'\0';
  4857. pcoBuffer[i].pszMDPath[dwStringLen + 2] = (WCHAR)L'\0';
  4858. if ( dwStringOldNameLen )
  4859. {
  4860. memcpy (&(pcoBuffer[i].pszMDPath[dwStringLen + 2]),
  4861. pceChange->pStrOrigName->QueryStrW(),
  4862. dwStringOldNameLen * sizeof(WCHAR) );
  4863. pcoBuffer[i].pszMDPath[dwStringLen + 2 + dwStringOldNameLen] = MD_PATH_DELIMETERW;
  4864. pcoBuffer[i].pszMDPath[dwStringLen + 3 + dwStringOldNameLen] = (WCHAR)L'\0';
  4865. }
  4866. pcoBuffer[i].dwMDNumDataIDs = pceChange->dwNumDataIDs;
  4867. if (pceChange->dwNumDataIDs != 0) {
  4868. MD_ASSERT(pceChange->pbufDataIDs != NULL);
  4869. pcoBuffer[i].pdwMDDataIDs = (DWORD *)(pceChange->pbufDataIDs->QueryPtr());
  4870. }
  4871. }
  4872. }
  4873. }
  4874. }
  4875. }
  4876. }
  4877. }
  4878. if (dwReturn != ERROR_SUCCESS) {
  4879. //
  4880. // Free Buffers
  4881. //
  4882. DeleteNotifications(dwNumChangeEntries,
  4883. pcoBuffer,
  4884. ppbufStorageArray);
  4885. hRes = RETURNCODETOHRESULT(dwReturn);
  4886. }
  4887. else {
  4888. //
  4889. // Pass back info
  4890. // DeleteNotifications will be called later
  4891. //
  4892. *pdwNumChangeEntries = dwNumChangeEntries;
  4893. *pppbufStorageArray = ppbufStorageArray;
  4894. *ppcoBuffer = pcoBuffer;
  4895. }
  4896. if (dwReturn != ERROR_SUCCESS) {
  4897. hRes = RETURNCODETOHRESULT(dwReturn);
  4898. }
  4899. return hRes;
  4900. }
  4901. VOID CMDCOM::InitializeFlusher (VOID)
  4902. {
  4903. if (!fFlusherInitialized)
  4904. {
  4905. fFlusherInitialized = TRUE;
  4906. EnterCriticalSection( &csFlushLock );
  4907. dwFlushCnt = 0;
  4908. dwFlushPeriodExtensions = 0;
  4909. if ( dwMBFlushCookie )
  4910. {
  4911. RemoveWorkItem( dwMBFlushCookie );
  4912. dwMBFlushCookie = 0;
  4913. }
  4914. LeaveCriticalSection( &csFlushLock );
  4915. }
  4916. }
  4917. // The algorithm for flushing changes of metabase to hard disk is the following:
  4918. // when change to metabase is made, and SlushSomeData is called from NotifySinks
  4919. // counter which counts the number of changes in metabase is incremented and first time
  4920. // the change happens work item is schedulled for scheduller to flush a metabase after 60 seconds
  4921. // if during 60 seconds more than INETA_MB_FLUSH_TRESHOLD changes will happen , then metabase will not
  4922. // flush changes to disk, but will extend flushing period for another 60 seconds. If during another 60 secs
  4923. // number of changes will be higer than INETA_MB_FLUSH_TRESHOLD agian period will be extended
  4924. // but no more times than INETA_MB_FLUSH_PERIODS_EXTENSION
  4925. // if in some period number of changes in metabase will be less than INETA_MB_FLUSH_TRESHOLD then
  4926. // peirod will not be extended and metabase will be saved to disk
  4927. VOID WINAPI CMDCOM::MetabaseLazyFlush(
  4928. VOID * pv
  4929. )
  4930. /*++
  4931. Description:
  4932. Scheduler callback for flushing the metabase
  4933. --*/
  4934. {
  4935. BOOL fExtendPeriod =FALSE;
  4936. CMDCOM *pMasterObject = (CMDCOM *)pv;
  4937. MD_ASSERT(pMasterObject != NULL);
  4938. EnterCriticalSection( &pMasterObject->csFlushLock );
  4939. if (pMasterObject->fFlusherInitialized)
  4940. {
  4941. RemoveWorkItem( pMasterObject->dwMBFlushCookie );
  4942. pMasterObject->dwMBFlushCookie = 0;
  4943. if ( pMasterObject->dwFlushCnt > INETA_MB_FLUSH_TRESHOLD)
  4944. {
  4945. if ( pMasterObject->dwFlushPeriodExtensions < INETA_MB_FLUSH_PERIODS_EXTENSION)
  4946. {
  4947. fExtendPeriod = TRUE;
  4948. pMasterObject->dwFlushPeriodExtensions ++;
  4949. }
  4950. }
  4951. pMasterObject->dwFlushCnt = 0;
  4952. if (!fExtendPeriod)
  4953. {
  4954. pMasterObject->dwFlushPeriodExtensions = 0;
  4955. }
  4956. else
  4957. {
  4958. pMasterObject->dwMBFlushCookie = ScheduleWorkItem( MetabaseLazyFlush,
  4959. pv, //context,
  4960. pMasterObject->msMBFlushTime);
  4961. }
  4962. }
  4963. LeaveCriticalSection( &pMasterObject->csFlushLock );
  4964. if (pMasterObject->fFlusherInitialized && !fExtendPeriod)
  4965. {
  4966. MB mb(pMasterObject);
  4967. mb.Save();
  4968. }
  4969. }
  4970. VOID CMDCOM::FlushSomeData (VOID)
  4971. {
  4972. EnterCriticalSection( &csFlushLock );
  4973. if ( fFlusherInitialized )
  4974. {
  4975. dwFlushCnt++;
  4976. if ( !dwMBFlushCookie )
  4977. {
  4978. dwMBFlushCookie = ScheduleWorkItem( MetabaseLazyFlush,
  4979. this, //context,
  4980. msMBFlushTime,
  4981. FALSE);
  4982. }
  4983. }
  4984. LeaveCriticalSection( &csFlushLock );
  4985. }
  4986. VOID CMDCOM::TerminateFlusher(VOID)
  4987. {
  4988. EnterCriticalSection( &csFlushLock );
  4989. if ( fFlusherInitialized )
  4990. {
  4991. fFlusherInitialized = FALSE;
  4992. if ( dwMBFlushCookie )
  4993. {
  4994. RemoveWorkItem( dwMBFlushCookie );
  4995. dwMBFlushCookie = 0;
  4996. }
  4997. }
  4998. LeaveCriticalSection( &csFlushLock );
  4999. }