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.

639 lines
18 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File:
  4. // dacache.cpp
  5. //
  6. // Contents:
  7. // implementation of the data advise cache - CDataAdviseCache
  8. //
  9. // Classes:
  10. // CDataAdviseCache
  11. //
  12. // Functions:
  13. //
  14. // History:
  15. // 31-Jan-95 t-ScottH add Dump method to CDataAdviseCache and
  16. // DumpCDataAdviseCache API
  17. // 24-Jan-94 alexgo first pass at converting to Cairo-style
  18. // memory allocation
  19. // 01/11/94 - AlexGo - added VDATEHEAP macros to every function
  20. // and method
  21. // 11/02/93 - ChrisWe - file inspection and cleanup
  22. // 12/15/92 - JasonFul - Created
  23. //
  24. //-----------------------------------------------------------------------------
  25. #include <le2int.h>
  26. #pragma SEG(dacache)
  27. #include <dacache.h>
  28. #include <reterr.h>
  29. #ifdef _DEBUG
  30. #include <dbgdump.h>
  31. #include <daholder.h>
  32. #endif // _DEBUG
  33. ASSERTDATA
  34. //+----------------------------------------------------------------------------
  35. //
  36. // Member:
  37. // CDataAdviseCache::CreateDataAdviseCache, static public
  38. //
  39. // Synopsis:
  40. // Creates an instance of the CDataAdviseCache
  41. //
  42. // Arguments:
  43. // [pp] -- pointer to a location to where to return the
  44. // newly created CDataAdviseCache
  45. //
  46. // Returns:
  47. // E_OUTOFMEMORY, S_OK
  48. //
  49. // Notes:
  50. //
  51. // History:
  52. // 11/02/93 - ChrisWe - file cleanup and inspection
  53. //
  54. //-----------------------------------------------------------------------------
  55. #pragma SEG(CreateDataAdviseCache)
  56. FARINTERNAL CDataAdviseCache::CreateDataAdviseCache(LPDATAADVCACHE FAR* pp)
  57. {
  58. VDATEHEAP();
  59. VDATEPTRIN(pp, LPDATAADVCACHE);
  60. // try to allocate the CDataAdviseCache
  61. if(NULL == (*pp = new DATAADVCACHE))
  62. return ReportResult(0, E_OUTOFMEMORY, 0, 0);
  63. // initialize the DataAdviseHolder member
  64. if(CreateDataAdviseHolder(&((*pp)->m_pDAH)) != NOERROR)
  65. {
  66. // free the DataAdviseCache
  67. delete *pp;
  68. *pp = NULL;
  69. return ReportResult(0, E_OUTOFMEMORY, 0, 0);
  70. }
  71. return(NOERROR);
  72. }
  73. //+----------------------------------------------------------------------------
  74. //
  75. // Member:
  76. // CDataAdviseCache::CDataAdviseCache, private
  77. //
  78. // Synopsis:
  79. // constructor
  80. //
  81. // Arguments:
  82. // none
  83. //
  84. // Notes:
  85. // This is private because it does not create a fully
  86. // formed CDataAdviseCache. m_pDAH must be allocated before
  87. // this can be used. That is done by the static member
  88. // CreateDataAdviseCache, which first calls this
  89. //
  90. // History:
  91. // 11/02/93 - ChrisWe - file cleanup and inspection
  92. //
  93. //-----------------------------------------------------------------------------
  94. #pragma SEG(CDataAdviseCache_ctor)
  95. CDataAdviseCache::CDataAdviseCache():
  96. m_mapClientToDelegate(MEMCTX_TASK)
  97. {
  98. VDATEHEAP();
  99. //now allocated with system allocator
  100. //Assert(CoMemctxOf(this) == MEMCTX_TASK);
  101. // no data advise holder allocated yet
  102. m_pDAH = NULL;
  103. }
  104. //+----------------------------------------------------------------------------
  105. //
  106. // Member:
  107. // CDataAdviseCache::~CDataAdviseCache, public
  108. //
  109. // Synopsis:
  110. // destructor
  111. //
  112. // Arguments:
  113. // none
  114. //
  115. // Requires:
  116. // successful call to CreateDataAdviseCache
  117. //
  118. // Notes:
  119. //
  120. // History:
  121. // 11/02/93 - ChrisWe - file cleanup and inspection
  122. //
  123. //-----------------------------------------------------------------------------
  124. #pragma SEG(CDataAdviseCache_dtor)
  125. CDataAdviseCache::~CDataAdviseCache()
  126. {
  127. VDATEHEAP();
  128. // release the data advise holder
  129. if( m_pDAH )
  130. {
  131. m_pDAH->Release();
  132. }
  133. }
  134. //+----------------------------------------------------------------------------
  135. //
  136. // Member:
  137. // CDataAdviseCache::Advise, public
  138. //
  139. // Synopsis:
  140. // Records an advise sink for later use. The sink will be
  141. // registered with the data object, if there is one, and
  142. // will be remembered for later registration with the data object,
  143. // in case it should go away, and return later.
  144. //
  145. // Effects:
  146. //
  147. // Arguments:
  148. // [pDataObject] -- the data object that the advise sink is
  149. // interested in changes to; may be null if the
  150. // data object isn't running
  151. // [pFetc] -- the format the advise sink would like to recieve
  152. // new data in
  153. // [advf] -- advise control flags ADVF_*
  154. // [pAdvise] -- the advise sink
  155. // [pdwClient] -- a token identifying the connection
  156. //
  157. // Returns:
  158. // E_OUTOFMEMORY, S_OK
  159. //
  160. // Notes:
  161. //
  162. // History:
  163. // 11/02/93 - ChrisWe - file cleanup and inspection
  164. //
  165. //-----------------------------------------------------------------------------
  166. #pragma SEG(CDataAdviseCache_Advise)
  167. HRESULT CDataAdviseCache::Advise(LPDATAOBJECT pDataObject,
  168. FORMATETC FAR* pFetc, DWORD advf, LPADVISESINK pAdvise,
  169. DWORD FAR* pdwClient)
  170. // first 4 parms are as in DataObject::Advise
  171. {
  172. VDATEHEAP();
  173. DWORD dwDelegate = 0; // the delegate connection number
  174. HRESULT hr;
  175. // if there is a data object, ask to be advised of changes
  176. if(pDataObject != NULL)
  177. RetErr(pDataObject->DAdvise(pFetc, advf, pAdvise, &dwDelegate));
  178. // if there is no data object, (i.e. the object is not active,
  179. // dwDelegate is zero
  180. // Here we are using the data advise holder only to hold advise
  181. // connections. We are not going to use it to send OnDataChange to
  182. // sinks.
  183. // REVIEW, handling of ADVF_ONLYONCE seems broken...
  184. // it's clear that we can't cope with this flag properly; we have
  185. // no way of knowing when the notification takes place, and therefore
  186. // we can't remove the entry from m_pDAH. The notification may have
  187. // taken place above, and it may not have. If the data object wasn't
  188. // around, then the advise request here is lost, and the sink will
  189. // never be notified. Or, if the request isn't PRIMEFIRST, and the
  190. // data object is deactivated, then the data object loses the request,
  191. // and on subsequent activation, we won't readvise it on EnumAndAdvise.
  192. // So, what good are we for ONLYONCE sinks? What does this break?
  193. if(advf & ADVF_ONLYONCE)
  194. return NOERROR;
  195. // keep a local copy of the advise
  196. hr = m_pDAH->Advise(NULL, pFetc, advf, pAdvise, pdwClient);
  197. // if we failed to keep a local reference to the advise sink,
  198. // we won't be able to maintain this mapping, so remove the
  199. // advise on the data object, if there is one
  200. if (hr != NOERROR)
  201. {
  202. Exit1:
  203. if (pDataObject != NULL)
  204. pDataObject->DUnadvise(dwDelegate);
  205. return(hr);
  206. }
  207. // create a map entry from *pdwClient -> dwDelegate
  208. // if the map entry creation failed, undo all work
  209. if (m_mapClientToDelegate.SetAt(*pdwClient, dwDelegate) != TRUE)
  210. {
  211. // map failed to allocate memory, undo advise since we won't
  212. // be able to find this one again
  213. m_pDAH->Unadvise(*pdwClient);
  214. // map entry creation must have failed from lack of allocation
  215. hr = ReportResult(0, E_OUTOFMEMORY, 0, 0);
  216. // undo the advise on the data object
  217. goto Exit1;
  218. }
  219. return(NOERROR);
  220. }
  221. //+----------------------------------------------------------------------------
  222. //
  223. // Member:
  224. // CDataAdviseCache::Unadvise, public
  225. //
  226. // Synopsis:
  227. // Remove an advise sink from the list of sinks the advise cache
  228. // maintains; the sink is also removed from the list of items
  229. // registered with the data object, if the data object is provided
  230. //
  231. // Effects:
  232. //
  233. // Arguments:
  234. // [pDataObject] -- the data object, if it is running, or NULL
  235. // [dwClient] -- the token that identifies this connection
  236. //
  237. // Returns:
  238. // OLE_E_NOCONNECTION, for a bad dwClient
  239. // S_OK
  240. //
  241. // Notes:
  242. //
  243. // History:
  244. // 11/02/93 - ChrisWe - file cleanup and inspection
  245. //
  246. //-----------------------------------------------------------------------------
  247. #pragma SEG(CDataAdviseCache_Unadvise)
  248. HRESULT CDataAdviseCache::Unadvise(IDataObject FAR* pDataObject, DWORD dwClient)
  249. {
  250. VDATEHEAP();
  251. DWORD dwDelegate = 0;
  252. // retrieve dwDelegate before removing from map
  253. if(pDataObject != NULL)
  254. RetErr(ClientToDelegate(dwClient, &dwDelegate));
  255. // do these first so error from remote unadvise is last(which might
  256. // be sync call during async dispatch
  257. RetErr(m_pDAH->Unadvise(dwClient));
  258. // If the above line succeeded, Remove Key must succeed.
  259. Verify(TRUE == m_mapClientToDelegate.RemoveKey(dwClient));
  260. // Delegate connection could be 0 if it did not accept the Advise
  261. if(pDataObject != NULL && dwDelegate != 0)
  262. {
  263. // Unadvise is asynchronous, don't worry about return value
  264. pDataObject->DUnadvise(dwDelegate);
  265. }
  266. return NOERROR;
  267. }
  268. //+----------------------------------------------------------------------------
  269. //
  270. // Member:
  271. // CDataAdviseCache::EnumAdvise, public
  272. //
  273. // Synopsis:
  274. // returns an enumerator over the advisory connections
  275. //
  276. // Arguments:
  277. // [ppenumAdvise] -- pointer to where to return the enumerator
  278. //
  279. // Returns:
  280. // E_OUTOFMEMORY, S_OK
  281. //
  282. // Notes:
  283. //
  284. // History:
  285. // 11/02/93 - ChrisWe - file cleanup and inspection
  286. //
  287. //-----------------------------------------------------------------------------
  288. #pragma SEG(CDataAdviseCache_EnumAdvise)
  289. HRESULT CDataAdviseCache::EnumAdvise(LPENUMSTATDATA FAR* ppenumAdvise)
  290. {
  291. VDATEHEAP();
  292. return m_pDAH->EnumAdvise(ppenumAdvise);
  293. }
  294. //+----------------------------------------------------------------------------
  295. //
  296. // Member:
  297. // CDataAdviseCache::ClientToDelegate, private
  298. //
  299. // Synopsis:
  300. // returns the delegate connection id for a given client
  301. // connection id
  302. //
  303. // Arguments:
  304. // [dwClient] -- the client connection identifier
  305. // [pdwDelegate] -- pointer to where to return the delegate
  306. // connection identifier
  307. //
  308. // Returns:
  309. // OLE_E_NOCONNECTION, for a bad dwClient
  310. // S_OK
  311. //
  312. // Notes:
  313. //
  314. // History:
  315. // 11/02/93 - ChrisWe - file cleanup and inspection
  316. //
  317. //-----------------------------------------------------------------------------
  318. #pragma SEG(CDataAdviseCache_ClientToDelegate)
  319. HRESULT CDataAdviseCache::ClientToDelegate(DWORD dwClient,
  320. DWORD FAR* pdwDelegate)
  321. {
  322. VDATEHEAP();
  323. VDATEPTRIN(pdwDelegate, DWORD);
  324. DWORD dwDelegate = *pdwDelegate = 0;
  325. if (FALSE == m_mapClientToDelegate.Lookup(dwClient, dwDelegate))
  326. return(ReportResult(0, OLE_E_NOCONNECTION, 0, 0));
  327. *pdwDelegate = dwDelegate;
  328. return NOERROR;
  329. }
  330. //+----------------------------------------------------------------------------
  331. //
  332. // Member:
  333. // CDataAdviseCache::EnumAndAdvise, public
  334. //
  335. // Synopsis:
  336. // Enumerate all the advise sinks registered in the data advise
  337. // cache. For each one, either register it with the
  338. // given data object, or deregister it, depending on [fAdvise].
  339. // Does not change what sinks are known to the data advise cache.
  340. //
  341. // Effects:
  342. //
  343. // Arguments:
  344. // [pDataDelegate] -- a data object that the advise sinks
  345. // are interested in
  346. // [fAdvise] -- if TRUE, register the advise sinks with
  347. // pDataDelegate object (with IDataObject::DAdvise();) if
  348. // FALSE, the deregister the advise sinks
  349. // (with DUnadvise().)
  350. //
  351. // Returns:
  352. // OLE_E_NOCONNECTION, if the mapping is corrupt (REVIEW!)
  353. // S_OK
  354. //
  355. // Notes:
  356. //
  357. // History:
  358. // 11/04/93 - ChrisWe - file cleanup and inspection
  359. //-----------------------------------------------------------------------------
  360. #pragma SEG(CDataAdviseCache_EnumAndAdvise)
  361. HRESULT CDataAdviseCache::EnumAndAdvise(LPDATAOBJECT pDataDelegate,
  362. BOOL fAdvise)
  363. {
  364. VDATEHEAP();
  365. if(pDataDelegate) {
  366. VDATEIFACE(pDataDelegate);
  367. }
  368. else {
  369. Win4Assert(!fAdvise);
  370. }
  371. LPENUMSTATDATA penumAdvise; // enumerator for the data advise holder
  372. DWORD dwDelegate; // delegate connection id for the current connection
  373. STATDATA statdata; // filled in by the penumAdvise enumerator
  374. HRESULT hresult = NOERROR; // current error status
  375. // get an enumerator from the data advise holder
  376. RetErr(m_pDAH->EnumAdvise(&penumAdvise));
  377. // repeat for each advise sink in the data advise holder...
  378. while(NOERROR == penumAdvise->Next(1, &statdata, NULL))
  379. {
  380. if(fAdvise)
  381. {
  382. // It is possible that the delegate's Advise will fail
  383. // even though we allowed the advise on the loaded
  384. // object to succeed(because the delegate is "pickier".)
  385. if(NOERROR==pDataDelegate->DAdvise(&statdata.formatetc,
  386. statdata.advf, statdata.pAdvSink,
  387. &dwDelegate))
  388. {
  389. // we know the key is present; this SetAt
  390. // should not fail
  391. Verify(m_mapClientToDelegate.SetAt(
  392. statdata.dwConnection,
  393. dwDelegate));
  394. }
  395. }
  396. else // unadvise
  397. {
  398. if((hresult=ClientToDelegate(statdata.dwConnection,
  399. &dwDelegate)) != NOERROR)
  400. {
  401. AssertSz(0, "Corrupt mapping");
  402. UtReleaseStatData(&statdata);
  403. goto errRtn;
  404. }
  405. if(dwDelegate != 0) {
  406. // Unadvise only if valid object
  407. if(pDataDelegate)
  408. pDataDelegate->DUnadvise(dwDelegate);
  409. // Always remove the key
  410. Verify(m_mapClientToDelegate.SetAt(statdata.dwConnection, 0));
  411. }
  412. }
  413. UtReleaseStatData(&statdata);
  414. }
  415. errRtn:
  416. // release the enumerator
  417. penumAdvise->Release();
  418. return hresult;
  419. }
  420. //+-------------------------------------------------------------------------
  421. //
  422. // Member: CDataAdviseCache::Dump, public (_DEBUG only)
  423. //
  424. // Synopsis: return a string containing the contents of the data members
  425. //
  426. // Effects:
  427. //
  428. // Arguments: [ppszDump] - an out pointer to a null terminated character array
  429. // [ulFlag] - flag determining prefix of all newlines of the
  430. // out character array (default is 0 - no prefix)
  431. // [nIndentLevel] - will add a indent prefix after the other prefix
  432. // for ALL newlines (including those with no prefix)
  433. //
  434. // Requires:
  435. //
  436. // Returns: HRESULT
  437. //
  438. // Signals:
  439. //
  440. // Modifies: [ppsz] - argument
  441. //
  442. // Derivation:
  443. //
  444. // Algorithm: use dbgstream to create a string containing information on the
  445. // content of data structures
  446. //
  447. // History: dd-mmm-yy Author Comment
  448. // 31-Jan-95 t-ScottH author
  449. //
  450. // Notes:
  451. //
  452. //--------------------------------------------------------------------------
  453. #ifdef _DEBUG
  454. HRESULT CDataAdviseCache::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
  455. {
  456. int i;
  457. char *pszPrefix;
  458. char *pszDAH;
  459. char *pszCMapDD;
  460. dbgstream dstrPrefix;
  461. dbgstream dstrDump(1000);
  462. // determine prefix of newlines
  463. if ( ulFlag & DEB_VERBOSE )
  464. {
  465. dstrPrefix << this << " _VB ";
  466. }
  467. // determine indentation prefix for all newlines
  468. for (i = 0; i < nIndentLevel; i++)
  469. {
  470. dstrPrefix << DUMPTAB;
  471. }
  472. pszPrefix = dstrPrefix.str();
  473. // put data members in stream
  474. if (m_pDAH != NULL)
  475. {
  476. pszDAH = DumpCDAHolder((CDAHolder *)m_pDAH, ulFlag, nIndentLevel + 1);
  477. dstrDump << pszPrefix << "CDAHolder: " << endl;
  478. dstrDump << pszDAH;
  479. CoTaskMemFree(pszDAH);
  480. }
  481. else
  482. {
  483. dstrDump << pszPrefix << "pIDataAdviseHolder = " << m_pDAH << endl;
  484. }
  485. pszCMapDD = DumpCMapDwordDword(&m_mapClientToDelegate, ulFlag, nIndentLevel + 1);
  486. dstrDump << pszPrefix << "Map of Clients to Delegate:" << endl;
  487. dstrDump << pszCMapDD;
  488. CoTaskMemFree(pszCMapDD);
  489. // cleanup and provide pointer to character array
  490. *ppszDump = dstrDump.str();
  491. if (*ppszDump == NULL)
  492. {
  493. *ppszDump = UtDupStringA(szDumpErrorMessage);
  494. }
  495. CoTaskMemFree(pszPrefix);
  496. return NOERROR;
  497. }
  498. #endif // _DEBUG
  499. //+-------------------------------------------------------------------------
  500. //
  501. // Function: DumpCDataAdviseCache, public (_DEBUG only)
  502. //
  503. // Synopsis: calls the CDataAdviseCache::Dump method, takes care of errors and
  504. // returns the zero terminated string
  505. //
  506. // Effects:
  507. //
  508. // Arguments: [pDAC] - pointer to CDataAdviseCache
  509. // [ulFlag] - flag determining prefix of all newlines of the
  510. // out character array (default is 0 - no prefix)
  511. // [nIndentLevel] - will add a indent prefix after the other prefix
  512. // for ALL newlines (including those with no prefix)
  513. //
  514. // Requires:
  515. //
  516. // Returns: character array of structure dump or error (null terminated)
  517. //
  518. // Signals:
  519. //
  520. // Modifies:
  521. //
  522. // Algorithm:
  523. //
  524. // History: dd-mmm-yy Author Comment
  525. // 31-Jan-95 t-ScottH author
  526. //
  527. // Notes:
  528. //
  529. //--------------------------------------------------------------------------
  530. #ifdef _DEBUG
  531. char *DumpCDataAdviseCache(CDataAdviseCache *pDAC, ULONG ulFlag, int nIndentLevel)
  532. {
  533. HRESULT hresult;
  534. char *pszDump;
  535. if (pDAC == NULL)
  536. {
  537. return UtDupStringA(szDumpBadPtr);
  538. }
  539. hresult = pDAC->Dump(&pszDump, ulFlag, nIndentLevel);
  540. if (hresult != NOERROR)
  541. {
  542. CoTaskMemFree(pszDump);
  543. return DumpHRESULT(hresult);
  544. }
  545. return pszDump;
  546. }
  547. #endif // _DEBUG
  548.