Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

7584 lines
186 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1996.
  5. //
  6. // File: deflink.h
  7. //
  8. // Contents: Implementation of the standard link object
  9. //
  10. // Classes: CDefLink
  11. //
  12. // Functions:
  13. //
  14. // Author:
  15. // Craig Wittenberg (craigwi) 8/12/92
  16. //
  17. // History: dd-mmm-yy Author Comment
  18. // 20-Feb-95 KentCe Buffered stream i/o.
  19. // 01-Feb-95 t-ScottH added Dump method to CDefLink
  20. // added DumpCDefLink API
  21. // added DLFlag to indicate if aggregated
  22. // (_DEBUG only)
  23. // 09-Jan-95 t-scotth changed VDATETHREAD to accept a pointer
  24. // 09-Jan-95 alexgo fixed a ton of link tracking bugs from
  25. // 16bit OLE.
  26. // 21-Nov-94 alexgo memory optimization
  27. // 28-Aug-94 alexgo added IsReallyRunning
  28. // 02-Aug-94 alexgo added object stabilization
  29. // 30-Jun-94 alexgo handles re-entrant shutdowns better
  30. // 31-May-94 alexgo now recovers from crashed servers
  31. // 06-May-94 alexgo made IsRunning work properly
  32. // 07-Mar-94 alexgo added call tracing
  33. // 03-Feb-94 alexgo fixed errors with SendOnLinkSrcChange
  34. // 11-Jan-94 alexgo added VDATEHEAP macros to every function
  35. // and method. Also fixed an aggregation bug,
  36. // allowing linking to work.
  37. // 22-Nov-93 alexgo removed overloaded GUID ==
  38. // 15-Nov-93 alexgo 32bit port
  39. //
  40. // ChrisWe 11/09/93 Changed COleCache::Update to COleCache::UpdateCache,
  41. // which does the same thing without an indirect fuction call
  42. // srinik 09/11/92 Removed IOleCache implementation, as a result of
  43. // removing voncache.cpp, and moving IViewObject
  44. // implementation into olecache.cpp.
  45. //
  46. // SriniK 06/04/92 Fixed problems in IPersistStorage methods
  47. //--------------------------------------------------------------------------
  48. #include <le2int.h>
  49. #include <scode.h>
  50. #include <objerror.h>
  51. #include "deflink.h"
  52. #include "defutil.h"
  53. #ifdef _DEBUG
  54. #include <dbgdump.h>
  55. #endif // _DEBUG
  56. #ifdef _TRACKLINK_
  57. #include <itrkmnk.hxx>
  58. #endif
  59. ASSERTDATA
  60. /*
  61. * IMPLEMENTATION of CDefLink
  62. */
  63. //+-------------------------------------------------------------------------
  64. //
  65. // Member: CDefLink::Create
  66. //
  67. // Synopsis: Static function to create an instance of a link object
  68. //
  69. // Arguments: [pUnkOuter] -- Controlling unknown
  70. //
  71. // Returns: Pointer to IUnkown interface on DefLink
  72. //
  73. // History: dd-mmm-yy Author Comment
  74. // 28-Jan-96 Gopalk Rewritten
  75. //--------------------------------------------------------------------------
  76. IUnknown *CDefLink::Create(IUnknown *pUnkOuter)
  77. {
  78. LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::Create(%p)\n",
  79. NULL /* this */, pUnkOuter));
  80. // Validation check
  81. VDATEHEAP();
  82. // Local variable
  83. CDefLink *pDefLink = NULL;
  84. IUnknown *pUnk = NULL;
  85. // Create DefLink
  86. pDefLink = new CDefLink(pUnkOuter);
  87. if(pDefLink) {
  88. // Make the ref count equal to 1
  89. pDefLink->m_Unknown.AddRef();
  90. // Create Ole Cache
  91. pDefLink->m_pCOleCache = new COleCache(pDefLink->m_pUnkOuter, CLSID_NULL);
  92. if(pDefLink->m_pCOleCache) {
  93. // Create Data Advise Cache
  94. if(CDataAdviseCache::CreateDataAdviseCache(&pDefLink->m_pDataAdvCache)
  95. == NOERROR) {
  96. pUnk = &pDefLink->m_Unknown;
  97. }
  98. }
  99. }
  100. if(pUnk == NULL) {
  101. // Something has gone wrong. Cleanup
  102. if(pDefLink)
  103. pDefLink->m_Unknown.Release();
  104. }
  105. LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::Create(%p)\n",
  106. NULL /* this */, pUnk ));
  107. return pUnk;
  108. }
  109. //+-------------------------------------------------------------------------
  110. //
  111. // Member: CDefLink::CDefLink
  112. //
  113. // Synopsis: Constructor
  114. //
  115. // Arguments: [pUnkOuter] -- Controlling IUnknown
  116. //
  117. // History: dd-mmm-yy Author Comment
  118. // 28-Jan-96 Gopalk Rewritten to use CRefExportCount
  119. //--------------------------------------------------------------------------
  120. CDefLink::CDefLink(IUnknown *pUnkOuter) :
  121. CRefExportCount(pUnkOuter)
  122. {
  123. // Validation check
  124. VDATEHEAP();
  125. // Initialize the controlling unknown
  126. if(!pUnkOuter)
  127. pUnkOuter = &m_Unknown;
  128. // Initialize member variables
  129. m_pUnkOuter = pUnkOuter;
  130. m_clsid = CLSID_NULL;
  131. m_dwUpdateOpt = OLEUPDATE_ALWAYS;
  132. m_pStg = NULL;
  133. m_flags = 0;
  134. m_dwObjFlags = 0;
  135. // Initialize sub objects
  136. m_pCOleCache = NULL;
  137. m_pCOAHolder = NULL;
  138. m_dwConnOle = 0;
  139. m_pDataAdvCache = NULL;
  140. m_dwConnTime = 0;
  141. // Initialize client site
  142. m_pAppClientSite = NULL;
  143. // Intialize delegates
  144. m_pUnkDelegate = NULL;
  145. m_pDataDelegate = NULL;
  146. m_pOleDelegate = NULL;
  147. m_pRODelegate = NULL;
  148. m_pOleItemContainerDelegate = NULL;
  149. // Initialize monikers
  150. m_pMonikerAbs = NULL;
  151. m_pMonikerRel = NULL;
  152. // zero out times
  153. memset(&m_ltChangeOfUpdate, 0, sizeof(m_ltChangeOfUpdate));
  154. memset(&m_ltKnownUpToDate, 0, sizeof(m_ltKnownUpToDate));
  155. memset(&m_rtUpdate, 0, sizeof(m_rtUpdate));
  156. // Initialize member variables used for caching MiscStatus bits
  157. m_ContentSRVMSHResult = 0xFFFFFFFF;
  158. m_ContentSRVMSBits = 0;
  159. m_ContentREGMSHResult = 0xFFFFFFFF;
  160. m_ContentREGMSBits = 0;
  161. #ifdef _DEBUG
  162. if(pUnkOuter != &m_Unknown)
  163. m_flags |= DL_AGGREGATED;
  164. #endif // _DEBUG
  165. }
  166. //+-------------------------------------------------------------------------
  167. //
  168. // Member: CDefObject::CleanupFn, private, virtual
  169. //
  170. // Synopsis: This function is called by CRefExportCount when the object
  171. // enters zombie state
  172. //
  173. // Arguments: None
  174. //
  175. // History: dd-mmm-yy Author Comment
  176. // 28-Jan-07 Gopalk Creation
  177. //--------------------------------------------------------------------------
  178. void CDefLink::CleanupFn(void)
  179. {
  180. LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::CleanupFn()\n", this));
  181. // Validation check
  182. VDATEHEAP();
  183. // Unbind source if neccessary
  184. UnbindSource();
  185. // Release monikers
  186. if(m_pMonikerAbs) {
  187. m_pMonikerAbs->Release();
  188. m_pMonikerAbs = NULL;
  189. }
  190. if(m_pMonikerRel) {
  191. m_pMonikerRel->Release();
  192. m_pMonikerRel = NULL;
  193. }
  194. // Release sub objects
  195. if(m_pCOleCache) {
  196. m_pCOleCache->m_UnkPrivate.Release();
  197. m_pCOleCache = NULL;
  198. }
  199. if(m_pCOAHolder) {
  200. m_pCOAHolder->Release();
  201. m_pCOAHolder = NULL;
  202. }
  203. if(m_pDataAdvCache) {
  204. delete m_pDataAdvCache;
  205. m_pDataAdvCache = NULL;
  206. }
  207. // Release container side objects
  208. Win4Assert(!(m_flags & DL_LOCKED_CONTAINER));
  209. if(m_pAppClientSite) {
  210. m_pAppClientSite->Release();
  211. m_pAppClientSite = NULL;
  212. }
  213. if(m_pStg) {
  214. m_pStg->Release();
  215. m_pStg = NULL;
  216. }
  217. // Update flags
  218. m_flags &= ~(DL_DIRTY_LINK);
  219. m_flags |= DL_CLEANEDUP;
  220. LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::CleanupFn()\n", this ));
  221. }
  222. //+-------------------------------------------------------------------------
  223. //
  224. // Function: DumpSzTime
  225. //
  226. // Synopsis: Prints the time in the FILETIME strucutre
  227. //
  228. // Effects:
  229. //
  230. // Arguments:
  231. //
  232. // Requires:
  233. //
  234. // Returns:
  235. //
  236. // Signals:
  237. //
  238. // Modifies:
  239. //
  240. // Algorithm:
  241. //
  242. // History: dd-mmm-yy Author Comment
  243. //
  244. // Notes: NYI for 32bit
  245. //
  246. //--------------------------------------------------------------------------
  247. #ifdef LINK_DEBUG
  248. INTERNAL_(void) DumpSzTime( LPOLESTR szMsg, FILETIME ft )
  249. {
  250. VDATEHEAP();
  251. WORD wDate, wTime;
  252. XCHAR szBuffer[24];
  253. CoFileTimeToDosDateTime(&ft, &wDate, &wTime);
  254. int Day = ( wDate & 0x001F);
  255. int Month = ( (wDate>>5) & 0x000F);
  256. int Year = 1980 + ((wDate>>9) & 0x007F);
  257. int Sec = ( wTime & 0x001F);
  258. int Min = ( (wTime>>5) & 0x003F);
  259. int Hour = ( (wTime>>11) & 0x001F);
  260. wsprintf((LPOLESTR)szBuffer, " %02d:%02d:%02d on %02d/%02d/%04d\n",
  261. Hour, Min, Sec, Month, Day, Year);
  262. OutputDebugString(szMsg);
  263. OutputDebugString(szBuffer);
  264. }
  265. #else
  266. #define DumpSzTime(a,b)
  267. #endif
  268. //+-------------------------------------------------------------------------
  269. //
  270. // Member: CDefLink::SetUpdateTimes
  271. //
  272. // Synopsis: Internal function to save local and remote times for
  273. // link->IsUpToDate calculations
  274. //
  275. // Effects:
  276. //
  277. // Arguments: void
  278. //
  279. // Requires:
  280. //
  281. // Returns: HRESULT
  282. //
  283. // Signals:
  284. //
  285. // Modifies:
  286. //
  287. // Derivation:
  288. //
  289. // Algorithm: See notes below
  290. //
  291. // History: dd-mmm-yy Author Comment
  292. // 21-Nov-94 alexgo memory optimization
  293. // 18-Nov-93 alexgo 32bit port
  294. //
  295. // Notes:
  296. // The basic problem in calculating link IsUpToDate is that
  297. // the local clock may be different than the remote clock.
  298. // The solution is to keep track of both times on *both*
  299. // clocks (i.e. time now and time of change on both the local
  300. // and remote clocks). IsUpToDate is calculated by comparing
  301. // the differences between the times on the two clocks. This,
  302. // of course, assumes that both clocks equivalently measure
  303. // a second.
  304. //
  305. //--------------------------------------------------------------------------
  306. INTERNAL CDefLink::SetUpdateTimes( void )
  307. {
  308. VDATEHEAP();
  309. FILETIME rtNewUpdate;
  310. LPMONIKER pmkAbs = NULL;
  311. HRESULT hresult;
  312. LPBINDCTX pbc = NULL;
  313. LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::SetUpdateTimes ( )\n",
  314. this ));
  315. //use the relative moniker if it exists and if the container has a
  316. //moniker
  317. if (NOERROR != GetAbsMkFromRel(&pmkAbs, NULL))
  318. {
  319. //otherwise use the absolute moniker
  320. pmkAbs = m_pMonikerAbs;
  321. if (pmkAbs)
  322. {
  323. pmkAbs->AddRef();
  324. }
  325. }
  326. if (pmkAbs == NULL)
  327. {
  328. hresult = E_UNSPEC;
  329. goto errRet;
  330. }
  331. hresult = CreateBindCtx( 0, &pbc );
  332. if (hresult != NOERROR)
  333. {
  334. goto errRet;
  335. }
  336. //debugging aids
  337. DumpSzTime("SetUpdateTimes (going in): rtUpdate = ",m_rtUpdate);
  338. DumpSzTime("SetUpdateTimes (going in): ltKnownUpToDate = ",
  339. m_ltKnownUpToDate);
  340. DumpSzTime("SetUpdateTimes (going in): ltChangeOfUpdate = ",
  341. m_ltChangeOfUpdate);
  342. //get the current local time.
  343. CoFileTimeNow(&m_ltKnownUpToDate);
  344. //debugging aids
  345. DumpSzTime("SetUpdateTimes: time now is ",m_ltKnownUpToDate);
  346. //get the time of last change on the remote machine
  347. hresult = pmkAbs->GetTimeOfLastChange(pbc, NULL, &rtNewUpdate);
  348. if (hresult == NOERROR)
  349. {
  350. //if the remote time of last change is different than
  351. //what we previously stored as the remote time of last change,
  352. //then we update the remote time of last change and update
  353. //our local time of last change.
  354. //Since the IsUpToDate algorithm relies on taking the
  355. //differences between times on the same clock and comparing
  356. //those differences between machines, it is important that
  357. //the two times (local and remote) are *set* simulataneously.
  358. if ((rtNewUpdate.dwLowDateTime != m_rtUpdate.dwLowDateTime)||
  359. (rtNewUpdate.dwHighDateTime !=
  360. m_rtUpdate.dwHighDateTime))
  361. {
  362. // rtUpdate value is changing
  363. m_rtUpdate = rtNewUpdate;
  364. //debugging aid
  365. DumpSzTime("rtUpdate changing to ", m_rtUpdate);
  366. m_ltChangeOfUpdate = m_ltKnownUpToDate;
  367. //debugging aid
  368. DumpSzTime("ltChangeOfUpdate changing to ",
  369. m_ltChangeOfUpdate);
  370. m_flags |= DL_DIRTY_LINK;
  371. }
  372. }
  373. errRet:
  374. //debugging aids
  375. DumpSzTime("SetUpdateTimes (going out): rtUpdate = ",m_rtUpdate);
  376. DumpSzTime("SetUpdateTimes (going out): ltKnownUpToDate = ",
  377. m_ltKnownUpToDate);
  378. DumpSzTime("SetUpdateTimes (going out): ltChangeOfUpdate = ",
  379. m_ltChangeOfUpdate);
  380. if (pmkAbs)
  381. {
  382. pmkAbs->Release();
  383. }
  384. if (pbc)
  385. {
  386. pbc->Release();
  387. }
  388. LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::SetUpdateTimes ( %lx )\n",
  389. this, hresult));
  390. return(hresult);
  391. }
  392. //+-------------------------------------------------------------------------
  393. //
  394. // Member: CDefLink::UpdateUserClassID
  395. //
  396. // Synopsis: Grabs the class ID from the remote server (our delegate)
  397. //
  398. // Effects:
  399. //
  400. // Arguments: void
  401. //
  402. // Requires:
  403. //
  404. // Returns: void
  405. //
  406. // Signals:
  407. //
  408. // Modifies:
  409. //
  410. // Derivation:
  411. //
  412. // Algorithm:
  413. //
  414. // History: dd-mmm-yy Author Comment
  415. // 21-Nov-94 alexgo memory optimization
  416. // 18-Nov-93 alexgo 32bit port
  417. //
  418. // Notes:
  419. //
  420. // update clsid from server if running; necessary because link source in
  421. // treatas case may decide to change the clsid (e.g., if features are used
  422. // which aren't supported by the old clsid).
  423. //--------------------------------------------------------------------------
  424. INTERNAL_(void) CDefLink::UpdateUserClassID(void)
  425. {
  426. VDATEHEAP();
  427. CLSID clsid;
  428. IOleObject *pOleDelegate;
  429. LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::UpdateUserClass ( )\n",
  430. this));
  431. if( (pOleDelegate = GetOleDelegate()) != NULL &&
  432. pOleDelegate->GetUserClassID(&clsid) == NOERROR)
  433. {
  434. m_clsid = clsid;
  435. }
  436. LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::UpdateUserClass ( )\n",
  437. this ));
  438. }
  439. //+-------------------------------------------------------------------------
  440. //
  441. // Member: CDefLink::~CDefLink
  442. //
  443. // Synopsis: Destructor
  444. //
  445. // Arguments: None
  446. //
  447. // History: dd-mmm-yy Author Comment
  448. // 10-Jan-07 Gopalk Rewritten
  449. //--------------------------------------------------------------------------
  450. CDefLink::~CDefLink (void)
  451. {
  452. VDATEHEAP();
  453. Win4Assert(m_flags & DL_CLEANEDUP);
  454. Win4Assert(!(m_flags & DL_LOCKED_CONTAINER) );
  455. Win4Assert(!(m_flags & DL_DIRTY_LINK));
  456. Win4Assert(m_pMonikerAbs == NULL);
  457. Win4Assert(m_pMonikerRel == NULL);
  458. Win4Assert(m_pUnkDelegate == NULL);
  459. Win4Assert(m_pStg == NULL);
  460. Win4Assert(m_pCOleCache == NULL);
  461. Win4Assert(m_pCOAHolder == NULL);
  462. Win4Assert(m_pAppClientSite == NULL);
  463. }
  464. //+----------------------------------------------------------------------------
  465. //
  466. // Member:
  467. // CDefLink::CPrivUnknown::AddRef, private
  468. //
  469. // Synopsis:
  470. // implements IUnknown::AddRef
  471. //
  472. // Arguments:
  473. // none
  474. //
  475. // Returns:
  476. // the parent object's reference count
  477. //
  478. // History:
  479. // Gopalk Rewritten Jan 28, 97
  480. //-----------------------------------------------------------------------------
  481. STDMETHODIMP_(ULONG) CDefLink::CPrivUnknown::AddRef( void )
  482. {
  483. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::CPrivUnknown::AddRef()\n",
  484. this));
  485. // Validation check
  486. VDATEHEAP();
  487. // Local variables
  488. CDefLink *pDefLink = GETPPARENT(this, CDefLink, m_Unknown);
  489. ULONG cRefs;
  490. // Addref the parent object
  491. cRefs = pDefLink->SafeAddRef();
  492. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::CPrivUnknown::AddRef(%lu)\n",
  493. this, cRefs));
  494. return cRefs;
  495. }
  496. //+----------------------------------------------------------------------------
  497. //
  498. // Member:
  499. // CDefLink::CPrivUnknown::Release, private
  500. //
  501. // Synopsis:
  502. // implements IUnknown::Release
  503. //
  504. // Arguments:
  505. // none
  506. //
  507. // Returns:
  508. // the parent object's reference count
  509. //
  510. // History:
  511. // Gopalk Rewritten Jan 28, 97
  512. //-----------------------------------------------------------------------------
  513. STDMETHODIMP_(ULONG) CDefLink::CPrivUnknown::Release( void )
  514. {
  515. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::CPrivUnknown::Release()\n",
  516. this));
  517. // Validation check
  518. VDATEHEAP();
  519. // Local variables
  520. CDefLink *pDefLink = GETPPARENT(this, CDefLink, m_Unknown);
  521. ULONG cRefs;
  522. // Release parent object
  523. cRefs = pDefLink->SafeRelease();
  524. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::CPrivUnknown::Release(%lu)\n",
  525. this, cRefs));
  526. return cRefs;
  527. }
  528. //+-------------------------------------------------------------------------
  529. //
  530. // Member: CDefLink::CPrivUnknown::QueryInterface
  531. //
  532. // Synopsis: The link's private QI implementation
  533. //
  534. // Effects:
  535. //
  536. // Arguments: [iid] -- the requested interface ID
  537. // [ppv] -- where to put the pointer to the interface
  538. //
  539. // Requires:
  540. //
  541. // Returns: HRESULT
  542. //
  543. // Signals:
  544. //
  545. // Modifies:
  546. //
  547. // Derivation: IUnknown
  548. //
  549. // Algorithm:
  550. //
  551. // History: dd-mmm-yy Author Comment
  552. // 21-Nov-94 alexgo memory optimization
  553. // 11-Jan-94 alexgo QI to the cache now queries to the cache's
  554. // private IUnknown implementation
  555. // 22-Nov-93 alexgo removed overloaded GUID ==
  556. // 18-Nov-93 alexgo 32bit port
  557. //
  558. // Notes:
  559. //
  560. //--------------------------------------------------------------------------
  561. STDMETHODIMP CDefLink::CPrivUnknown::QueryInterface(REFIID iid,
  562. LPLPVOID ppv)
  563. {
  564. HRESULT hresult = NOERROR;
  565. CDefLink *pDefLink = GETPPARENT(this, CDefLink, m_Unknown);
  566. VDATEHEAP();
  567. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::CPrivUnknown::QueryInterface"
  568. " ( %p , %p )\n", pDefLink, iid, ppv));
  569. if (IsEqualIID(iid, IID_IUnknown))
  570. {
  571. *ppv = (void FAR *)&pDefLink->m_Unknown;
  572. //AddRef this object (not the aggregate)
  573. AddRef();
  574. // hresult already set to NOERROR;
  575. goto errRtn;
  576. }
  577. else if (IsEqualIID(iid, IID_IOleObject))
  578. {
  579. *ppv = (void FAR *) (IOleObject *)pDefLink;
  580. }
  581. else if (IsEqualIID(iid, IID_IDataObject))
  582. {
  583. *ppv = (void FAR *) (IDataObject *)pDefLink;
  584. }
  585. else if (IsEqualIID(iid, IID_IOleLink))
  586. {
  587. *ppv = (void FAR *) (IOleLink *)pDefLink;
  588. }
  589. else if (IsEqualIID(iid, IID_IRunnableObject))
  590. {
  591. *ppv = (void FAR *) (IRunnableObject *)pDefLink;
  592. }
  593. else if (IsEqualIID(iid, IID_IViewObject) ||
  594. IsEqualIID(iid, IID_IOleCache) ||
  595. IsEqualIID(iid, IID_IViewObject2) ||
  596. IsEqualIID(iid, IID_IOleCache2) )
  597. {
  598. hresult =
  599. pDefLink->m_pCOleCache->m_UnkPrivate.QueryInterface(iid,ppv);
  600. goto errRtn;
  601. }
  602. else if (IsEqualIID(iid, IID_IPersistStorage) ||
  603. IsEqualIID(iid, IID_IPersist))
  604. {
  605. *ppv = (void FAR *) (IPersistStorage *)pDefLink;
  606. }
  607. else
  608. {
  609. *ppv = NULL;
  610. hresult = E_NOINTERFACE;
  611. goto errRtn;
  612. }
  613. pDefLink->m_pUnkOuter->AddRef();
  614. errRtn:
  615. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::CPrivUnknown::QueryInterface"
  616. " ( %lx ) [ %p ]\n", pDefLink, hresult, *ppv));
  617. return(hresult);
  618. }
  619. /*
  620. * IMPLEMENTATION of IUnknown methods
  621. */
  622. //+-------------------------------------------------------------------------
  623. //
  624. // Member: CDefLink::QueryInterface
  625. //
  626. // Synopsis: QI's to the controlling IUnknown
  627. //
  628. // Effects:
  629. //
  630. // Arguments: [riid] -- the interface ID
  631. // [ppv] -- where to put it
  632. //
  633. // Requires:
  634. //
  635. // Returns: HRESULT
  636. //
  637. // Signals:
  638. //
  639. // Modifies:
  640. //
  641. // Derivation: IUnknown
  642. //
  643. // Algorithm:
  644. //
  645. // History: dd-mmm-yy Author Comment
  646. // 15-Nov-94 alexgo author
  647. //
  648. // Notes: We do *not* need to stabilize this method as only
  649. // one outgoing call is made and we do not use the
  650. // 'this' pointer afterwards
  651. //
  652. //--------------------------------------------------------------------------
  653. STDMETHODIMP CDefLink::QueryInterface( REFIID riid, void **ppv )
  654. {
  655. HRESULT hresult;
  656. VDATEHEAP();
  657. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::QueryInterface ( %lx , "
  658. "%p )\n", this, riid, ppv));
  659. Assert(m_pUnkOuter);
  660. hresult = m_pUnkOuter->QueryInterface(riid, ppv);
  661. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::QueryInterface ( %lx ) "
  662. "[ %p ]\n", this, hresult, *ppv));
  663. return hresult;
  664. }
  665. //+-------------------------------------------------------------------------
  666. //
  667. // Member: CDefLink::AddRef
  668. //
  669. // Synopsis: delegates AddRef to the controlling IUnknown
  670. //
  671. // Effects:
  672. //
  673. // Arguments: void
  674. //
  675. // Requires:
  676. //
  677. // Returns: ULONG -- the new reference count
  678. //
  679. // Signals:
  680. //
  681. // Modifies:
  682. //
  683. // Derivation: IUnknown
  684. //
  685. // Algorithm:
  686. //
  687. // History: dd-mmm-yy Author Comment
  688. // 15-Nov-94 alexgo author
  689. //
  690. // Notes:
  691. //
  692. //--------------------------------------------------------------------------
  693. STDMETHODIMP_(ULONG) CDefLink::AddRef( void )
  694. {
  695. ULONG crefs;;
  696. VDATEHEAP();
  697. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::AddRef ( )\n", this));
  698. Assert(m_pUnkOuter);
  699. crefs = m_pUnkOuter->AddRef();
  700. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::AddRef ( %ld ) ", this,
  701. crefs));
  702. return crefs;
  703. }
  704. //+-------------------------------------------------------------------------
  705. //
  706. // Member: CDefLink::Release
  707. //
  708. // Synopsis: delegates Release to the controlling IUnknown
  709. //
  710. // Effects:
  711. //
  712. // Arguments: void
  713. //
  714. // Requires:
  715. //
  716. // Returns: ULONG -- the new reference count
  717. //
  718. // Signals:
  719. //
  720. // Modifies:
  721. //
  722. // Derivation: IUnknown
  723. //
  724. // Algorithm:
  725. //
  726. // History: dd-mmm-yy Author Comment
  727. // 15-Nov-94 alexgo author
  728. //
  729. // Notes:
  730. //
  731. //--------------------------------------------------------------------------
  732. STDMETHODIMP_(ULONG) CDefLink::Release( void )
  733. {
  734. ULONG crefs;;
  735. VDATEHEAP();
  736. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::Release ( )\n", this));
  737. Assert(m_pUnkOuter);
  738. crefs = m_pUnkOuter->Release();
  739. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::Release ( %ld )\n", this,
  740. crefs));
  741. return crefs;
  742. }
  743. /*
  744. * IMPLEMENTATION of CDataObjectImpl methods
  745. */
  746. //+-------------------------------------------------------------------------
  747. //
  748. // Member: CDefLink::GetDataDelegate
  749. //
  750. // Synopsis: Private method to get the IDataObject interface on
  751. // the server delegate for the link
  752. //
  753. // Effects:
  754. //
  755. // Arguments: void
  756. //
  757. // Requires:
  758. //
  759. // Returns: IDataObject *
  760. //
  761. // Signals:
  762. //
  763. // Modifies:
  764. //
  765. // Derivation:
  766. //
  767. // Algorithm:
  768. //
  769. // History: dd-mmm-yy Author Comment
  770. // 21-Nov-94 alexgo memory optimization
  771. // 18-Nov-93 alexgo 32bit port
  772. //
  773. // Notes:
  774. // This function may return misleading information if the
  775. // server has died (i.e., you'll return a pointer to a cached
  776. // interface proxy). It is the responsibility of the caller
  777. // to handler server crashes.
  778. //
  779. //--------------------------------------------------------------------------
  780. INTERNAL_(IDataObject *) CDefLink::GetDataDelegate(void)
  781. {
  782. VDATEHEAP();
  783. IDataObject *pDataDelegate;
  784. LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::GetDataDelegate ( )\n",
  785. this ));
  786. if( !IsZombie() )
  787. {
  788. DuCacheDelegate(&m_pUnkDelegate,
  789. IID_IDataObject, (LPLPVOID)&m_pDataDelegate, NULL);
  790. pDataDelegate = m_pDataDelegate;
  791. #if DBG == 1
  792. if( m_pDataDelegate )
  793. {
  794. Assert(m_pUnkDelegate);
  795. }
  796. #endif // DBG == 1
  797. }
  798. else
  799. {
  800. pDataDelegate = NULL;
  801. }
  802. LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::GetData"
  803. "Delegate ( %p )\n", this, pDataDelegate));
  804. return pDataDelegate;
  805. }
  806. //+-------------------------------------------------------------------------
  807. //
  808. // Member: CDefLink::ReleaseDataDelegate
  809. //
  810. // Synopsis: Private method to release the IDataObject pointer on the
  811. // server to which we are linked
  812. //
  813. // Effects:
  814. //
  815. // Arguments: void
  816. //
  817. // Requires:
  818. //
  819. // Returns: void
  820. //
  821. // Signals:
  822. //
  823. // Modifies:
  824. //
  825. // Derivation:
  826. //
  827. // Algorithm:
  828. //
  829. // History: dd-mmm-yy Author Comment
  830. // 21-Nov-94 alexgo memory optimization
  831. // 18-Nov-93 alexgo 32bit port
  832. //
  833. // Notes:
  834. //
  835. //--------------------------------------------------------------------------
  836. INTERNAL_(void) CDefLink::ReleaseDataDelegate(void)
  837. {
  838. VDATEHEAP();
  839. LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::ReleaseDataDelegate ( )\n",
  840. this));
  841. if (m_pDataDelegate)
  842. {
  843. SafeReleaseAndNULL((IUnknown **)&m_pDataDelegate);
  844. }
  845. LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::ReleaseData"
  846. "Delegate ( )\n", this ));
  847. }
  848. //+-------------------------------------------------------------------------
  849. //
  850. // Member: CDefLink::GetData
  851. //
  852. // Synopsis: Gets data from the server
  853. //
  854. // Effects:
  855. //
  856. // Arguments: [pfromatetcIn] -- the requested data format
  857. // [pmedium] -- where to put the data
  858. //
  859. // Requires:
  860. //
  861. // Returns: HRESULT
  862. //
  863. // Signals:
  864. //
  865. // Modifies:
  866. //
  867. // Derivation: IDataObject
  868. //
  869. // Algorithm: Tries the cache first, then asks the server
  870. //
  871. // History: dd-mmm-yy Author Comment
  872. // 21-Nov-94 alexgo memory optimization
  873. // 03-Aug-94 alexgo stabilized
  874. // 18-Nov-93 alexgo 32bit port
  875. //
  876. // Notes:
  877. //
  878. //--------------------------------------------------------------------------
  879. STDMETHODIMP CDefLink::GetData(LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium )
  880. {
  881. HRESULT hresult = NOERROR;
  882. VDATEHEAP();
  883. VDATETHREAD(this);
  884. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::GetData"
  885. " ( %p , %p )\n", this, pformatetcIn, pmedium));
  886. VDATEPTROUT( pmedium, STGMEDIUM );
  887. VDATEREADPTRIN( pformatetcIn, FORMATETC );
  888. CRefStabilize stabilize(this);
  889. if( !HasValidLINDEX(pformatetcIn) )
  890. {
  891. return DV_E_LINDEX;
  892. }
  893. pmedium->tymed = TYMED_NULL;
  894. pmedium->pUnkForRelease = NULL;
  895. Assert(m_pCOleCache != NULL);
  896. if( m_pCOleCache->m_Data.GetData(pformatetcIn, pmedium) != NOERROR)
  897. {
  898. if( GetDataDelegate() )
  899. {
  900. hresult = m_pDataDelegate->GetData(pformatetcIn,
  901. pmedium);
  902. AssertOutStgmedium(hresult, pmedium);
  903. }
  904. else
  905. {
  906. hresult = OLE_E_NOTRUNNING;
  907. }
  908. }
  909. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::GetData"
  910. " ( %lx )\n", this, hresult));
  911. return(hresult);
  912. }
  913. //+-------------------------------------------------------------------------
  914. //
  915. // Member: CDefLink::GetDataHere
  916. //
  917. // Synopsis: Retrieves data into the specified pmedium
  918. //
  919. // Effects:
  920. //
  921. // Arguments: [pformatetcIn] -- the requested format
  922. // [pmedium] -- where to put the data
  923. //
  924. // Requires:
  925. //
  926. // Returns: HRESULT
  927. //
  928. // Signals:
  929. //
  930. // Modifies:
  931. //
  932. // Derivation: IDataObject
  933. //
  934. // Algorithm: Asks the cache first, then the server delegate
  935. //
  936. // History: dd-mmm-yy Author Comment
  937. // 21-Nov-94 alexgo memory optimization
  938. // 03-Aug-94 alexgo stabilized
  939. // 18-Nov-93 alexgo 32bit port
  940. //
  941. // Notes:
  942. //
  943. //--------------------------------------------------------------------------
  944. STDMETHODIMP CDefLink::GetDataHere( LPFORMATETC pformatetcIn,
  945. LPSTGMEDIUM pmedium )
  946. {
  947. HRESULT hresult = NOERROR;
  948. VDATEHEAP();
  949. VDATETHREAD(this);
  950. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::GetDataHere"
  951. " ( %p , %p )\n", this, pformatetcIn, pmedium));
  952. VDATEREADPTRIN( pformatetcIn, FORMATETC );
  953. VDATEREADPTRIN( pmedium, STGMEDIUM );
  954. CRefStabilize stabilize(this);
  955. if( !HasValidLINDEX(pformatetcIn) )
  956. {
  957. return DV_E_LINDEX;
  958. }
  959. Assert(m_pCOleCache != NULL);
  960. if( m_pCOleCache->m_Data.GetDataHere(pformatetcIn, pmedium) != NOERROR )
  961. {
  962. if ( GetDataDelegate() )
  963. {
  964. hresult = m_pDataDelegate->GetDataHere(pformatetcIn,
  965. pmedium);
  966. }
  967. else
  968. {
  969. hresult = OLE_E_NOTRUNNING;
  970. }
  971. }
  972. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::GetDataHere"
  973. " ( %lx )\n", this, hresult));
  974. return hresult;
  975. }
  976. //+-------------------------------------------------------------------------
  977. //
  978. // Member: CDefLink::QueryGetData
  979. //
  980. // Synopsis: Returns whether or not a GetData call for the requested
  981. // format would succeed.
  982. //
  983. // Effects:
  984. //
  985. // Arguments: [pformatetcIn] -- the requested data format
  986. //
  987. // Requires:
  988. //
  989. // Returns: HRESULT (NOERROR == GetData would succeed)
  990. //
  991. // Signals:
  992. //
  993. // Modifies:
  994. //
  995. // Derivation: IDataObject
  996. //
  997. // Algorithm: Asks the cache first, then the server delegate (if the
  998. // cache call fails)
  999. //
  1000. // History: dd-mmm-yy Author Comment
  1001. // 21-Nov-94 alexgo memory optimization
  1002. // 03-Aug-94 alexgo stabilized
  1003. // 18-Nov-93 alexgo 32bit port
  1004. //
  1005. // Notes:
  1006. //
  1007. //--------------------------------------------------------------------------
  1008. STDMETHODIMP CDefLink::QueryGetData(LPFORMATETC pformatetcIn )
  1009. {
  1010. HRESULT hresult = NOERROR;
  1011. VDATEHEAP();
  1012. VDATETHREAD(this);
  1013. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::QueryGetData"
  1014. " ( %p )\n", this, pformatetcIn));
  1015. VDATEREADPTRIN( pformatetcIn, FORMATETC );
  1016. CRefStabilize stabilize(this);
  1017. if( !HasValidLINDEX(pformatetcIn) )
  1018. {
  1019. hresult = DV_E_LINDEX;
  1020. goto errRtn;
  1021. }
  1022. Assert(m_pCOleCache != NULL);
  1023. if( m_pCOleCache->m_Data.QueryGetData(pformatetcIn) != NOERROR )
  1024. {
  1025. if ( GetDataDelegate() )
  1026. {
  1027. hresult = m_pDataDelegate->QueryGetData(pformatetcIn);
  1028. }
  1029. else
  1030. {
  1031. hresult = OLE_E_NOTRUNNING;
  1032. }
  1033. }
  1034. errRtn:
  1035. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::QueryGetData"
  1036. " ( %lx )\n", this, hresult));
  1037. return hresult;
  1038. }
  1039. //+-------------------------------------------------------------------------
  1040. //
  1041. // Member: CDefLink::GetCanonicalFormatEtc
  1042. //
  1043. // Synopsis: Gets the cannonical (or preferred) data format for the
  1044. // object (choosing from the given formats)
  1045. //
  1046. // Effects:
  1047. //
  1048. // Arguments: [pformatetc] -- the requested formats
  1049. // [pformatetcOut] -- where to to put the canonical format
  1050. //
  1051. // Requires:
  1052. //
  1053. // Returns: HRESULT
  1054. //
  1055. // Signals:
  1056. //
  1057. // Modifies:
  1058. //
  1059. // Derivation: IDataObject
  1060. //
  1061. // Algorithm: Delegates to the server (if running)
  1062. //
  1063. // History: dd-mmm-yy Author Comment
  1064. // 21-Nov-94 alexgo memory optimization
  1065. // 03-Aug-94 alexgo stabilized
  1066. // 18-Nov-93 alexgo 32bit port
  1067. //
  1068. // Notes:
  1069. //
  1070. //--------------------------------------------------------------------------
  1071. STDMETHODIMP CDefLink::GetCanonicalFormatEtc( LPFORMATETC pformatetc,
  1072. LPFORMATETC pformatetcOut)
  1073. {
  1074. HRESULT hresult;
  1075. VDATEHEAP();
  1076. VDATETHREAD(this);
  1077. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::Get"
  1078. "CanonicalFormatetc ( %p , %p )\n", this, pformatetc,
  1079. pformatetcOut));
  1080. VDATEPTROUT( pformatetcOut, FORMATETC );
  1081. VDATEREADPTRIN( pformatetc, FORMATETC );
  1082. CRefStabilize stabilize(this);
  1083. pformatetcOut->ptd = NULL;
  1084. pformatetcOut->tymed = TYMED_NULL;
  1085. if (!HasValidLINDEX(pformatetc))
  1086. {
  1087. return DV_E_LINDEX;
  1088. }
  1089. if( GetDataDelegate() )
  1090. {
  1091. hresult = m_pDataDelegate->GetCanonicalFormatEtc(pformatetc,
  1092. pformatetcOut);
  1093. }
  1094. else
  1095. {
  1096. hresult = OLE_E_NOTRUNNING;
  1097. }
  1098. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::Get"
  1099. "CanonicalFormatetc ( %lx )\n", this, hresult));
  1100. return hresult;
  1101. }
  1102. //+-------------------------------------------------------------------------
  1103. //
  1104. // Member: CDefLink::SetData
  1105. //
  1106. // Synopsis: Stuffs data into an object (such as an icon)
  1107. //
  1108. // Effects:
  1109. //
  1110. // Arguments: [pformatetc] -- the format of the data
  1111. // [pmedium] -- the data
  1112. // [fRelease] -- if TRUE, then the data should be free'd
  1113. //
  1114. // Requires:
  1115. //
  1116. // Returns: HRESULT
  1117. //
  1118. // Signals:
  1119. //
  1120. // Modifies:
  1121. //
  1122. // Derivation: IDataObject
  1123. //
  1124. // Algorithm: Delegates to the server
  1125. //
  1126. // History: dd-mmm-yy Author Comment
  1127. // 21-Nov-94 alexgo memory optimization
  1128. // 03-Aug-94 alexgo stabilized
  1129. // 18-Nov-93 alexgo 32bit port
  1130. //
  1131. // Notes: The cache gets updated via a OnDataChange advise
  1132. //
  1133. //--------------------------------------------------------------------------
  1134. STDMETHODIMP CDefLink::SetData( LPFORMATETC pformatetc,
  1135. LPSTGMEDIUM pmedium, BOOL fRelease)
  1136. {
  1137. HRESULT hresult;
  1138. VDATEHEAP();
  1139. VDATETHREAD(this);
  1140. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::SetData"
  1141. " ( %p , %p , %lu )\n", this, pformatetc, pmedium,
  1142. fRelease));
  1143. VDATEREADPTRIN( pformatetc, FORMATETC );
  1144. VDATEREADPTRIN( pmedium, STGMEDIUM );
  1145. CRefStabilize stabilize(this);
  1146. if( !HasValidLINDEX(pformatetc) )
  1147. {
  1148. hresult = DV_E_LINDEX;
  1149. goto errRtn;
  1150. }
  1151. if( GetDataDelegate() )
  1152. {
  1153. hresult = m_pDataDelegate->SetData(pformatetc, pmedium,
  1154. fRelease);
  1155. }
  1156. else
  1157. {
  1158. hresult = OLE_E_NOTRUNNING;
  1159. }
  1160. errRtn:
  1161. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::SetData "
  1162. "( %lx )\n", this, hresult));
  1163. return hresult;
  1164. }
  1165. //+-------------------------------------------------------------------------
  1166. //
  1167. // Member: CDefLink::EnumFormatEtc
  1168. //
  1169. // Synopsis: Enumerates the formats accepted for either GetData or SetData
  1170. //
  1171. // Effects:
  1172. //
  1173. // Arguments: [dwDirection] -- which formats (1 == GetData or
  1174. // 2 == SetData)
  1175. // [ppenumFormatEtc] -- where to put the enumerator
  1176. //
  1177. // Requires:
  1178. //
  1179. // Returns: HRESULT
  1180. //
  1181. // Signals:
  1182. //
  1183. // Modifies:
  1184. //
  1185. // Derivation: IDataObject
  1186. //
  1187. // Algorithm: Delegates to the server, if not available or the server
  1188. // returns OLE_E_USEREG
  1189. //
  1190. // History: dd-mmm-yy Author Comment
  1191. // 21-Nov-94 alexgo memory optimization
  1192. // 03-Aug-94 alexgo stabilized
  1193. // 30-May-94 alexgo now handles crashed servers
  1194. // 18-Nov-93 alexgo 32bit port
  1195. //
  1196. // Notes:
  1197. //
  1198. //--------------------------------------------------------------------------
  1199. STDMETHODIMP CDefLink::EnumFormatEtc( DWORD dwDirection,
  1200. LPENUMFORMATETC *ppenumFormatEtc)
  1201. {
  1202. HRESULT hresult;
  1203. VDATEHEAP();
  1204. VDATETHREAD(this);
  1205. VDATEPTROUT(ppenumFormatEtc, LPENUMFORMATETC);
  1206. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::EnumFormat"
  1207. "Etc ( %lu , %p )\n", this, dwDirection,
  1208. ppenumFormatEtc));
  1209. CRefStabilize stabilize(this);
  1210. if( GetDataDelegate() )
  1211. {
  1212. hresult=m_pDataDelegate->EnumFormatEtc (dwDirection,
  1213. ppenumFormatEtc);
  1214. if( !GET_FROM_REGDB(hresult) )
  1215. {
  1216. if( SUCCEEDED(hresult) || IsReallyRunning() )
  1217. {
  1218. // if we failed, but the server is still
  1219. // running, then go ahead and propogate the
  1220. // error to the caller.
  1221. // Note that IsReallyRunning will clean up our
  1222. // state if the server had crashed.
  1223. goto errRtn;
  1224. }
  1225. // FALL-THROUGH!! This is deliberate. If
  1226. // the call failed and the server is no longer
  1227. // running, then we assume the server has crashed.
  1228. // We want to go ahead and fetch the information
  1229. // from the registry.
  1230. }
  1231. }
  1232. // Not running or object wants to use reg db anyway
  1233. hresult = OleRegEnumFormatEtc(m_clsid, dwDirection,
  1234. ppenumFormatEtc);
  1235. errRtn:
  1236. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::EnumFormat"
  1237. "Etc ( %lx ) [ %p ]\n", this, hresult,
  1238. *ppenumFormatEtc));
  1239. return hresult;
  1240. }
  1241. //+-------------------------------------------------------------------------
  1242. //
  1243. // Member: CDefLink::DAdvise
  1244. //
  1245. // Synopsis: Sets up a data advise connection
  1246. //
  1247. // Effects:
  1248. //
  1249. // Arguments: [pFormatetc] -- the data format to advise on
  1250. // [advf] -- advise flags
  1251. // [pAdvSink] -- whom to notify
  1252. // [pdwConnection] -- where to put the advise connection ID
  1253. //
  1254. // Requires:
  1255. //
  1256. // Returns: HRESULT
  1257. //
  1258. // Signals:
  1259. //
  1260. // Modifies:
  1261. //
  1262. // Derivation: IDataObject
  1263. //
  1264. // Algorithm: Delegates to the advise cache
  1265. //
  1266. // History: dd-mmm-yy Author Comment
  1267. // 21-Nov-94 alexgo memory optimization
  1268. // 03-Aug-94 alexgo stabilized
  1269. // 18-Nov-93 alexgo 32bit port
  1270. //
  1271. // Notes:
  1272. //
  1273. //--------------------------------------------------------------------------
  1274. STDMETHODIMP CDefLink::DAdvise(FORMATETC *pFormatetc, DWORD advf,
  1275. IAdviseSink *pAdvSink, DWORD *pdwConnection)
  1276. {
  1277. HRESULT hresult;
  1278. IDataObject * pDataDelegate;
  1279. VDATEHEAP();
  1280. VDATETHREAD(this);
  1281. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::DAdvise "
  1282. "( %p , %lu , %p , %p )\n", this, pFormatetc, advf,
  1283. pAdvSink, pdwConnection ));
  1284. VDATEREADPTRIN( pFormatetc, FORMATETC );
  1285. VDATEIFACE( pAdvSink );
  1286. if (pdwConnection)
  1287. {
  1288. VDATEPTROUT( pdwConnection, DWORD );
  1289. *pdwConnection = NULL;
  1290. }
  1291. CRefStabilize stabilize(this);
  1292. if (!HasValidLINDEX(pFormatetc))
  1293. {
  1294. hresult = DV_E_LINDEX;
  1295. goto errRtn;
  1296. }
  1297. pDataDelegate = GetDataDelegate(); // NULL if not running
  1298. hresult = m_pDataAdvCache->Advise(pDataDelegate,
  1299. pFormatetc, advf, pAdvSink, pdwConnection);
  1300. errRtn:
  1301. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::DAdvise "
  1302. "( %lx ) [ %p ]\n", this, hresult, (pdwConnection) ?
  1303. *pdwConnection : 0 ));
  1304. return hresult;
  1305. }
  1306. //+-------------------------------------------------------------------------
  1307. //
  1308. // Member: CDefLink::DUnadvise
  1309. //
  1310. // Synopsis: Destroys a data advise connection
  1311. //
  1312. // Effects:
  1313. //
  1314. // Arguments: [dwConnection] -- the connection to dismantle
  1315. //
  1316. // Requires:
  1317. //
  1318. // Returns: HRESULT
  1319. //
  1320. // Signals:
  1321. //
  1322. // Modifies:
  1323. //
  1324. // Derivation: IDataObject
  1325. //
  1326. // Algorithm: delegates to the data advise cache
  1327. //
  1328. // History: dd-mmm-yy Author Comment
  1329. // 21-Nov-94 alexgo memory optimization
  1330. // 03-Aug-94 alexgo stabilized
  1331. // 18-Nov-93 alexgo 32bit port
  1332. //
  1333. // Notes:
  1334. //
  1335. //--------------------------------------------------------------------------
  1336. STDMETHODIMP CDefLink::DUnadvise(DWORD dwConnection)
  1337. {
  1338. HRESULT hresult;
  1339. IDataObject FAR* pDataDelegate;
  1340. VDATEHEAP();
  1341. VDATETHREAD(this);
  1342. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::DUnadvise"
  1343. " ( %lu )\n", this, dwConnection ));
  1344. CRefStabilize stabilize(this);
  1345. pDataDelegate = GetDataDelegate();// NULL if not running
  1346. hresult = m_pDataAdvCache->Unadvise(pDataDelegate, dwConnection);
  1347. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::DUnadvise ( %lx )\n",
  1348. this, hresult));
  1349. return hresult;
  1350. }
  1351. //+-------------------------------------------------------------------------
  1352. //
  1353. // Member: CDefLink::EnumDAdvise
  1354. //
  1355. // Synopsis: Enumerates the data advise connections to the object
  1356. //
  1357. // Effects:
  1358. //
  1359. // Arguments: [ppenumAdvise] -- where to put the enumerator
  1360. //
  1361. // Requires:
  1362. //
  1363. // Returns: HRESULT
  1364. //
  1365. // Signals:
  1366. //
  1367. // Modifies:
  1368. //
  1369. // Derivation: IDataObject
  1370. //
  1371. // Algorithm: delegates to the data advise cache
  1372. //
  1373. // History: dd-mmm-yy Author Comment
  1374. // 21-Nov-94 alexgo memory optimization
  1375. // 18-Nov-93 alexgo 32bit port
  1376. //
  1377. // Notes: This method does NOT have to be stabilized as we are
  1378. // only going to be allocating memory for the enumerator
  1379. //
  1380. //--------------------------------------------------------------------------
  1381. STDMETHODIMP CDefLink::EnumDAdvise( LPENUMSTATDATA *ppenumAdvise )
  1382. {
  1383. HRESULT hresult;
  1384. VDATEHEAP();
  1385. VDATETHREAD(this);
  1386. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::EnumDAdvise"
  1387. " ( %p )\n", this, ppenumAdvise));
  1388. hresult = m_pDataAdvCache->EnumAdvise (ppenumAdvise);
  1389. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::EnumDAdvise"
  1390. " ( %lx ) [ %p ]\n", this, hresult, *ppenumAdvise));
  1391. return hresult;
  1392. }
  1393. /*
  1394. * IMPLEMENTATION of COleObjectImpl methods
  1395. *
  1396. */
  1397. //+-------------------------------------------------------------------------
  1398. //
  1399. // Member: CDefLink::GetOleDelegate
  1400. //
  1401. // Synopsis: Gets the IOleObject interface from the server, private method
  1402. //
  1403. // Effects:
  1404. //
  1405. // Arguments: [void]
  1406. //
  1407. // Requires:
  1408. //
  1409. // Returns: IOleObject *
  1410. //
  1411. // Signals:
  1412. //
  1413. // Modifies:
  1414. //
  1415. // Derivation:
  1416. //
  1417. // Algorithm:
  1418. //
  1419. // History: dd-mmm-yy Author Comment
  1420. // 21-Nov-94 alexgo memory optimization
  1421. // 03-Aug-94 alexgo stabilized and handled the zombie state
  1422. // 18-Nov-93 alexgo 32bit port
  1423. //
  1424. // Notes:
  1425. // This function may return misleading information if the
  1426. // server has died (i.e., you'll return a pointer to a cached
  1427. // interface proxy). It is the responsibility of the caller
  1428. // to handler server crashes.
  1429. //
  1430. //
  1431. //--------------------------------------------------------------------------
  1432. INTERNAL_(IOleObject *) CDefLink::GetOleDelegate(void)
  1433. {
  1434. IOleObject *pOleDelegate;
  1435. VDATEHEAP();
  1436. LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::GetOle"
  1437. "Delegate ( )\n", this ));
  1438. if( !IsZombie() )
  1439. {
  1440. DuCacheDelegate(&m_pUnkDelegate,
  1441. IID_IOleObject, (LPLPVOID)&m_pOleDelegate, NULL);
  1442. pOleDelegate = m_pOleDelegate;
  1443. #if DBG == 1
  1444. if( m_pOleDelegate )
  1445. {
  1446. Assert(m_pUnkDelegate);
  1447. }
  1448. #endif // DBG == 1
  1449. }
  1450. else
  1451. {
  1452. pOleDelegate = NULL;
  1453. }
  1454. LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::GetOle"
  1455. "Delegate ( %p )\n", this, pOleDelegate));
  1456. return pOleDelegate;
  1457. }
  1458. //+-------------------------------------------------------------------------
  1459. //
  1460. // Member: CDefLink::ReleaseOleDelegate (private)
  1461. //
  1462. // Synopsis: Releases the IOleObject pointer from the server
  1463. //
  1464. // Effects:
  1465. //
  1466. // Arguments: void
  1467. //
  1468. // Requires:
  1469. //
  1470. // Returns: void
  1471. //
  1472. // Signals:
  1473. //
  1474. // Modifies:
  1475. //
  1476. // Derivation:
  1477. //
  1478. // Algorithm:
  1479. //
  1480. // History: dd-mmm-yy Author Comment
  1481. // 21-Nov-94 alexgo memory optimization
  1482. // 18-Nov-93 alexgo 32bit port
  1483. //
  1484. // Notes:
  1485. //
  1486. //--------------------------------------------------------------------------
  1487. INTERNAL_(void) CDefLink::ReleaseOleDelegate(void)
  1488. {
  1489. VDATEHEAP();
  1490. LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::ReleaseOle"
  1491. "Delegate ( )\n", this ));
  1492. if (m_pOleDelegate)
  1493. {
  1494. SafeReleaseAndNULL((IUnknown **)&m_pOleDelegate);
  1495. }
  1496. LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::ReleaseOle"
  1497. "Delegate ( )\n", this ));
  1498. }
  1499. //+-------------------------------------------------------------------------
  1500. //
  1501. // Member: CDefLink::SetClientSite
  1502. //
  1503. // Synopsis: Sets the client site for the object
  1504. //
  1505. // Effects:
  1506. //
  1507. // Arguments: [pClientSite] -- the client site
  1508. //
  1509. // Requires:
  1510. //
  1511. // Returns: HRESULT
  1512. //
  1513. // Signals:
  1514. //
  1515. // Modifies:
  1516. //
  1517. // Derivation: IOleObject
  1518. //
  1519. // Algorithm: Stores the pointer; if the link is running, then
  1520. // the LockContainer is called via the client site by
  1521. // the DuSetClientSite helper function
  1522. //
  1523. // History: dd-mmm-yy Author Comment
  1524. // 21-Nov-94 alexgo memory optimization
  1525. // 03-Aug-94 alexgo stabilized and handled zombie state
  1526. // 18-Nov-93 alexgo 32bit port
  1527. //
  1528. // Notes:
  1529. //
  1530. //--------------------------------------------------------------------------
  1531. STDMETHODIMP CDefLink::SetClientSite( IOleClientSite *pClientSite )
  1532. {
  1533. HRESULT hresult;
  1534. VDATEHEAP();
  1535. VDATETHREAD(this);
  1536. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::SetClientSite"
  1537. " ( %p )\n", this, pClientSite));
  1538. CRefStabilize stabilize(this);
  1539. if( IsZombie() )
  1540. {
  1541. // we don't want to change our state (i.e. reset the
  1542. // the client site) if we're zombied, because it's possible
  1543. // that we'd never be able to release the client site again
  1544. // resulting in memory leaks or faults.
  1545. hresult = CO_E_RELEASED;
  1546. }
  1547. else
  1548. {
  1549. BOOL fLockedContainer = (m_flags & DL_LOCKED_CONTAINER);
  1550. // here we use whether or not we've been bound to the server
  1551. // as the test for whether or not we're running (even though
  1552. // the server may have crashed since we last bound). We do
  1553. // this because DuSetClientSite will Unlock the old container
  1554. // and lock the new if we're running. Thus, if we've ever been
  1555. // running, we need to unlock the old container (even though
  1556. // we may not currently be running).
  1557. hresult = DuSetClientSite(
  1558. m_pUnkDelegate ? TRUE : FALSE,
  1559. pClientSite,
  1560. &m_pAppClientSite,
  1561. &fLockedContainer);
  1562. if(fLockedContainer)
  1563. {
  1564. m_flags |= DL_LOCKED_CONTAINER;
  1565. }
  1566. else
  1567. {
  1568. m_flags &= ~(DL_LOCKED_CONTAINER);
  1569. }
  1570. }
  1571. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::SetClientSite"
  1572. " ( %lx )\n", this, hresult));
  1573. return hresult;
  1574. }
  1575. //+-------------------------------------------------------------------------
  1576. //
  1577. // Member: CDefLink::GetClientSite
  1578. //
  1579. // Synopsis: Retrieves the stored client site pointer
  1580. //
  1581. // Effects:
  1582. //
  1583. // Arguments: [ppClientSite] -- where to put the client site pointer
  1584. //
  1585. // Requires:
  1586. //
  1587. // Returns: HRESULT
  1588. //
  1589. // Signals:
  1590. //
  1591. // Modifies:
  1592. //
  1593. // Derivation: IOleObject
  1594. //
  1595. // Algorithm:
  1596. //
  1597. // History: dd-mmm-yy Author Comment
  1598. // 21-Nov-94 alexgo memory optimization
  1599. // 03-Aug-94 alexgo stabilized
  1600. // 22-Nov-93 alexgo inlined DuGetClientSite
  1601. // 18-Nov-93 alexgo 32bit port
  1602. //
  1603. // Notes:
  1604. //
  1605. //--------------------------------------------------------------------------
  1606. STDMETHODIMP CDefLink::GetClientSite( IOleClientSite **ppClientSite )
  1607. {
  1608. VDATEHEAP();
  1609. VDATETHREAD(this);
  1610. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::GetClientSite ( %p )\n",
  1611. this, ppClientSite));
  1612. VDATEPTROUT(ppClientSite, IOleClientSite *);
  1613. CRefStabilize stabilize(this);
  1614. *ppClientSite = m_pAppClientSite;
  1615. if( *ppClientSite )
  1616. {
  1617. (*ppClientSite)->AddRef();
  1618. }
  1619. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::GetClientSite"
  1620. " ( %lx ) [ %p ] \n", this, NOERROR, *ppClientSite));
  1621. return NOERROR;
  1622. }
  1623. //+-------------------------------------------------------------------------
  1624. //
  1625. // Member: CDefLink::SetHostNames
  1626. //
  1627. // Synopsis: In principal, should set the names to be drawn for
  1628. // the server object. Not relevant for links (link servers
  1629. // are not a part of the document being edited).
  1630. //
  1631. // Effects:
  1632. //
  1633. // Arguments: [szContainerApp] -- the name of the container
  1634. // [szContainerObj] -- the container's name for the object
  1635. //
  1636. // Requires:
  1637. //
  1638. // Returns: HRESULT (NOERROR currently)
  1639. //
  1640. // Signals:
  1641. //
  1642. // Modifies:
  1643. //
  1644. // Derivation: IOleObject
  1645. //
  1646. // Algorithm:
  1647. //
  1648. // History: dd-mmm-yy Author Comment
  1649. // 21-Nov-94 alexgo memory optimization
  1650. // 18-Nov-93 alexgo 32bit port
  1651. //
  1652. // Notes:
  1653. //
  1654. //--------------------------------------------------------------------------
  1655. STDMETHODIMP CDefLink::SetHostNames
  1656. (LPCOLESTR szContainerApp, LPCOLESTR szContainerObj)
  1657. {
  1658. VDATEHEAP();
  1659. VDATETHREAD(this);
  1660. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::SetHostNames"
  1661. " ( %p , %p )\n", this, szContainerApp, szContainerObj));
  1662. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::SetHostNames"
  1663. " ( %lx )\n", this, NOERROR));
  1664. return NOERROR; // makes the embedded/link case more the same
  1665. }
  1666. //+-------------------------------------------------------------------------
  1667. //
  1668. // Member: CDefLink::Close
  1669. //
  1670. // Synopsis: Closes the object (in this case, just saves and unbinds the
  1671. // link)
  1672. //
  1673. // Effects:
  1674. //
  1675. // Arguments: [dwFlags] -- clising flags (such as SAVEIFDIRTY)
  1676. //
  1677. // Requires:
  1678. //
  1679. // Returns: HRESULT
  1680. //
  1681. // Signals:
  1682. //
  1683. // Modifies:
  1684. //
  1685. // Derivation: IOleObject
  1686. //
  1687. // Algorithm:
  1688. //
  1689. // History: dd-mmm-yy Author Comment
  1690. // 21-Nov-94 alexgo memory optimization
  1691. // 03-Aug-94 alexgo stabilized
  1692. // 18-Nov-93 alexgo 32bit port
  1693. //
  1694. // Notes:
  1695. //
  1696. //--------------------------------------------------------------------------
  1697. STDMETHODIMP CDefLink::Close( DWORD dwFlags )
  1698. {
  1699. VDATEHEAP();
  1700. VDATETHREAD(this);
  1701. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::Close "
  1702. "( %lu )\n", this, dwFlags));
  1703. CRefStabilize stabilize(this);
  1704. if (dwFlags != OLECLOSE_NOSAVE)
  1705. {
  1706. AssertSz(dwFlags == OLECLOSE_SAVEIFDIRTY,
  1707. "OLECLOSE_PROMPTSAVE is inappropriate\n");
  1708. if( IsDirty() == NOERROR )
  1709. {
  1710. if( m_pAppClientSite )
  1711. {
  1712. m_pAppClientSite->SaveObject();
  1713. }
  1714. }
  1715. }
  1716. // just unbind.
  1717. UnbindSource();
  1718. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::Close "
  1719. "( %lx )\n", this, NOERROR));
  1720. return NOERROR;
  1721. }
  1722. //+-------------------------------------------------------------------------
  1723. //
  1724. // Member: CDefLink::SetMoniker
  1725. //
  1726. // Synopsis: Sets the moniker to the link object
  1727. //
  1728. // Effects:
  1729. //
  1730. // Arguments: [dwWhichMoniker] -- which moniker
  1731. // [pmk] -- the new moniker
  1732. //
  1733. // Requires:
  1734. //
  1735. // Returns: HRESULT
  1736. //
  1737. // Signals:
  1738. //
  1739. // Modifies:
  1740. //
  1741. // Derivation: IOleObject
  1742. //
  1743. // Algorithm: calls utility method UpdateRelMkFromAbsMk
  1744. //
  1745. // History: dd-mmm-yy Author Comment
  1746. // 21-Nov-94 alexgo memory optimization
  1747. // 03-Aug-94 alexgo stabilized
  1748. // 18-Nov-93 alexgo 32bit port
  1749. //
  1750. // Notes:
  1751. //
  1752. // The moniker of the container is changing.
  1753. // The next time we bind, we will try using the container moniker
  1754. // composed with the relative moniker, and then, if that fails,
  1755. // the absolute moniker, so there is no real need for us to
  1756. // change these monikers.
  1757. //
  1758. // However, there are two cases when we know the absolute moniker
  1759. // is the correct one, and we can take this opportunity to
  1760. // recompute the relative moniker (which is changing because
  1761. // the container moniker is changing). The advantage of this is
  1762. // that GetDisplayName can return a better result in the interim
  1763. //
  1764. //--------------------------------------------------------------------------
  1765. STDMETHODIMP CDefLink::SetMoniker( DWORD dwWhichMoniker, LPMONIKER pmk )
  1766. {
  1767. HRESULT hresult = NOERROR;
  1768. VDATEHEAP();
  1769. VDATETHREAD(this);
  1770. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::SetMoniker "
  1771. "( %lx , %p )\n", this, dwWhichMoniker, pmk));
  1772. CRefStabilize stabilize(this);
  1773. if( IsZombie() )
  1774. {
  1775. hresult = CO_E_RELEASED;
  1776. }
  1777. else if (dwWhichMoniker == OLEWHICHMK_CONTAINER
  1778. || dwWhichMoniker == OLEWHICHMK_OBJFULL)
  1779. {
  1780. if( m_pMonikerRel == NULL || m_pUnkDelegate)
  1781. {
  1782. UpdateRelMkFromAbsMk(pmk);
  1783. }
  1784. }
  1785. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::SetMoniker"
  1786. " ( %lx )\n", this, hresult));
  1787. return hresult;
  1788. }
  1789. //+-------------------------------------------------------------------------
  1790. //
  1791. // Member: CDefLink::GetMoniker
  1792. //
  1793. // Synopsis: Retrieves the moniker for the object
  1794. //
  1795. // Effects:
  1796. //
  1797. // Arguments: [dwAssign] -- flags (such as wether a moniker should
  1798. // be assigned to the object if none currently
  1799. // exits)
  1800. // [dwWhichMoniker]-- which moniker to get (relative/absolute/etc)
  1801. // [ppmk] -- where to put a pointer to the moniker
  1802. //
  1803. // Requires:
  1804. //
  1805. // Returns: HRESULT
  1806. //
  1807. // Signals:
  1808. //
  1809. // Modifies:
  1810. //
  1811. // Derivation: IOleObject
  1812. //
  1813. // Algorithm: asks the client site for the moniker
  1814. //
  1815. // History: dd-mmm-yy Author Comment
  1816. // 21-Nov-94 alexgo memory optimization
  1817. // 03-Aug-94 alexgo stabilized
  1818. // 18-Nov-93 alexgo 32bit port
  1819. //
  1820. // Notes:
  1821. //
  1822. //--------------------------------------------------------------------------
  1823. STDMETHODIMP CDefLink::GetMoniker( DWORD dwAssign, DWORD dwWhichMoniker,
  1824. LPMONIKER *ppmk)
  1825. {
  1826. HRESULT hresult;
  1827. VDATEHEAP();
  1828. VDATETHREAD(this);
  1829. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::GetMoniker "
  1830. "( %lx , %lx , %p )\n", this, dwAssign, dwWhichMoniker,
  1831. ppmk));
  1832. CRefStabilize stabilize(this);
  1833. if( m_pAppClientSite )
  1834. {
  1835. hresult = m_pAppClientSite->GetMoniker(dwAssign, dwWhichMoniker,
  1836. ppmk);
  1837. }
  1838. else
  1839. {
  1840. // no client site
  1841. *ppmk = NULL;
  1842. hresult = E_UNSPEC;
  1843. }
  1844. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::GetMoniker "
  1845. "( %lx ) [ %p ]\n", this, hresult, *ppmk ));
  1846. return hresult;
  1847. }
  1848. //+-------------------------------------------------------------------------
  1849. //
  1850. // Member: CDefLink::InitFromData
  1851. //
  1852. // Synopsis: Initializes the object from the given data
  1853. //
  1854. // Effects:
  1855. //
  1856. // Arguments: [pDataObject] -- the data object to initialize from
  1857. // [fCreation] -- TRUE indicates the object is being
  1858. // created, FALSE a data transfer
  1859. // [dwReserved] -- unused
  1860. //
  1861. // Requires:
  1862. //
  1863. // Returns: HRESULT
  1864. //
  1865. // Signals:
  1866. //
  1867. // Modifies:
  1868. //
  1869. // Derivation: IOleObject
  1870. //
  1871. // Algorithm: Delegates to the server
  1872. //
  1873. // History: dd-mmm-yy Author Comment
  1874. // 21-Nov-94 alexgo memory optimization
  1875. // 03-Aug-94 alexgo stabilized
  1876. // 18-Nov-93 alexgo 32bit port
  1877. //
  1878. // Notes:
  1879. //
  1880. //--------------------------------------------------------------------------
  1881. STDMETHODIMP CDefLink::InitFromData( LPDATAOBJECT pDataObject, BOOL fCreation,
  1882. DWORD dwReserved)
  1883. {
  1884. HRESULT hresult;
  1885. VDATEHEAP();
  1886. VDATETHREAD(this);
  1887. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::InitFromData "
  1888. "( %p , %lu , %lx )\n", this, pDataObject, fCreation,
  1889. dwReserved));
  1890. CRefStabilize stabilize(this);
  1891. if( GetOleDelegate() )
  1892. {
  1893. hresult = m_pOleDelegate->InitFromData(pDataObject,
  1894. fCreation, dwReserved);
  1895. }
  1896. else
  1897. {
  1898. hresult = OLE_E_NOTRUNNING;
  1899. }
  1900. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::InitFromData "
  1901. "( %lx )\n", this, hresult));
  1902. return hresult;
  1903. }
  1904. //+-------------------------------------------------------------------------
  1905. //
  1906. // Member: CDefLink::GetClipboardData
  1907. //
  1908. // Synopsis: Retrieves a data object that could be put on the clipboard
  1909. //
  1910. // Effects:
  1911. //
  1912. // Arguments: [dwReserved] -- unused
  1913. // [ppDataObject] -- where to put the pointer to the data
  1914. // object
  1915. //
  1916. // Requires:
  1917. //
  1918. // Returns: HRESULT
  1919. //
  1920. // Signals:
  1921. //
  1922. // Modifies:
  1923. //
  1924. // Derivation: IOleObject
  1925. //
  1926. // Algorithm: Delegates to the server object
  1927. //
  1928. // History: dd-mmm-yy Author Comment
  1929. // 21-Nov-94 alexgo memory optimization
  1930. // 03-Aug-94 alexgo stabilized
  1931. // 18-Nov-93 alexgo 32bit port
  1932. //
  1933. // Notes:
  1934. //
  1935. //--------------------------------------------------------------------------
  1936. STDMETHODIMP CDefLink::GetClipboardData( DWORD dwReserved,
  1937. LPDATAOBJECT *ppDataObject)
  1938. {
  1939. HRESULT hresult;
  1940. VDATEHEAP();
  1941. VDATETHREAD(this);
  1942. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::GetClipboard"
  1943. "Data ( %lx , %p )\n", this, dwReserved, ppDataObject));
  1944. CRefStabilize stabilize(this);
  1945. if ( GetOleDelegate() )
  1946. {
  1947. hresult = m_pOleDelegate->GetClipboardData (dwReserved,
  1948. ppDataObject);
  1949. }
  1950. else
  1951. {
  1952. hresult = OLE_E_NOTRUNNING;
  1953. }
  1954. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::GetClipboard"
  1955. "Data ( %lx ) [ %p ]\n", this, hresult, *ppDataObject));
  1956. return hresult;
  1957. }
  1958. //+-------------------------------------------------------------------------
  1959. //
  1960. // Member: CDefLink::DoVerb
  1961. //
  1962. // Synopsis: Sends a verb to the object (such as Open)
  1963. //
  1964. // Effects:
  1965. //
  1966. // Arguments: [iVerb] -- the verb
  1967. // [lpmsg] -- the window's message that caused the verb
  1968. // [pActiveSite] -- the site where the object was activated
  1969. // [lindex] -- unused currently
  1970. // [hwndParent] -- the parent window of the container
  1971. // [lprcPosRect] -- the rectange bounding the object
  1972. //
  1973. // Requires:
  1974. //
  1975. // Returns: HRESULT
  1976. //
  1977. // Signals:
  1978. //
  1979. // Modifies:
  1980. //
  1981. // Derivation: IOleObject
  1982. //
  1983. // Algorithm: Binds to the server and then delegates the DoVerb call
  1984. //
  1985. // History: dd-mmm-yy Author Comment
  1986. // 21-Nov-94 alexgo memory optimization
  1987. // 03-Aug-94 alexgo stabilized
  1988. // 18-Nov-93 alexgo 32bit port
  1989. //
  1990. // Notes: If we had bound to the server and it crashed, we pretend it
  1991. // was still running anyway for DoVerb (our call to BindToSource
  1992. // will re-run it). Essentially, this algorithm "fixes" the
  1993. // crash and restores the link's state.
  1994. //
  1995. //--------------------------------------------------------------------------
  1996. STDMETHODIMP CDefLink::DoVerb
  1997. (LONG iVerb, LPMSG lpmsg, LPOLECLIENTSITE pActiveSite, LONG lindex,
  1998. HWND hwndParent, LPCRECT lprcPosRect)
  1999. {
  2000. HRESULT hresult;
  2001. BOOL bStartedNow = !m_pUnkDelegate;
  2002. VDATEHEAP();
  2003. VDATETHREAD(this);
  2004. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::DoVerb "
  2005. "( %ld , %ld , %p , %ld , %lx , %p )\n", this, iVerb,
  2006. lpmsg, pActiveSite, lindex, hwndParent, lprcPosRect));
  2007. if( lpmsg )
  2008. {
  2009. VDATEPTRIN( lpmsg, MSG );
  2010. }
  2011. if( pActiveSite )
  2012. {
  2013. VDATEIFACE( pActiveSite );
  2014. }
  2015. if( lprcPosRect )
  2016. {
  2017. VDATEPTRIN(lprcPosRect, RECT);
  2018. }
  2019. CRefStabilize stabilize(this);
  2020. if( lindex != 0 && lindex != -1 )
  2021. {
  2022. hresult = DV_E_LINDEX;
  2023. goto errRtn;
  2024. }
  2025. // if we had crashed, BindToSource will reconnect us
  2026. if ( FAILED(hresult = BindToSource(0, NULL)) )
  2027. {
  2028. goto errRtn;
  2029. }
  2030. // we don't propogate hide to server; this (and other behavior)
  2031. // favors the link object as serving an OLE container rather than
  2032. // a general programmability client. This leave the link running,
  2033. // possibly invisible.
  2034. if (iVerb == OLEIVERB_HIDE)
  2035. {
  2036. hresult = NOERROR;
  2037. goto errRtn;
  2038. }
  2039. if( GetOleDelegate() )
  2040. {
  2041. hresult = m_pOleDelegate->DoVerb(iVerb, lpmsg, pActiveSite,
  2042. lindex, hwndParent, lprcPosRect);
  2043. }
  2044. else
  2045. {
  2046. hresult = E_NOINTERFACE;
  2047. }
  2048. if (bStartedNow && FAILED(hresult))
  2049. {
  2050. UnbindSource();
  2051. }
  2052. errRtn:
  2053. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::DoVerb "
  2054. "( %lx )\n", this, hresult));
  2055. return hresult;
  2056. }
  2057. //+-------------------------------------------------------------------------
  2058. //
  2059. // Member: CDefLink::EnumVerbs
  2060. //
  2061. // Synopsis: Enumerate the verbs accepted by this object
  2062. //
  2063. // Effects:
  2064. //
  2065. // Arguments: [ppenumOleVerb] -- where to put the pointer to the enumerator
  2066. //
  2067. // Requires:
  2068. //
  2069. // Returns: HRESULT
  2070. //
  2071. // Signals:
  2072. //
  2073. // Modifies:
  2074. //
  2075. // Derivation: IOleObject
  2076. //
  2077. // Algorithm: askes the server delegate. If not there or it returns
  2078. // OLE_E_USEREG, then we get the info from the registration
  2079. // database
  2080. //
  2081. // History: dd-mmm-yy Author Comment
  2082. // 21-Nov-94 alexgo memory optimization
  2083. // 03-Aug-94 alexgo stabilized
  2084. // 30-May-94 alexgo now handles crashed servers
  2085. // 18-Nov-93 alexgo 32bit port
  2086. //
  2087. // Notes:
  2088. //
  2089. //--------------------------------------------------------------------------
  2090. STDMETHODIMP CDefLink::EnumVerbs( IEnumOLEVERB **ppenumOleVerb )
  2091. {
  2092. HRESULT hresult;
  2093. VDATEHEAP();
  2094. VDATETHREAD(this);
  2095. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::EnumVerbs "
  2096. "( %p )\n", this, ppenumOleVerb));
  2097. CRefStabilize stabilize(this);
  2098. if( GetOleDelegate() )
  2099. {
  2100. hresult = m_pOleDelegate->EnumVerbs(ppenumOleVerb);
  2101. if( !GET_FROM_REGDB(hresult) )
  2102. {
  2103. if( SUCCEEDED(hresult) || IsReallyRunning() )
  2104. {
  2105. // if we failed, but the server is still
  2106. // running, then go ahead and propogate the
  2107. // error to the caller.
  2108. // Note that IsReallyRunning will clean up our
  2109. // state if the server had crashed.
  2110. goto errRtn;
  2111. }
  2112. // FALL-THROUGH!! This is deliberate. If
  2113. // the call failed and the server is no longer
  2114. // running, then we assume the server has crashed.
  2115. // We want to go ahead and fetch the information
  2116. // from the registry.
  2117. }
  2118. }
  2119. // Not running or object wants to use reg db anyway
  2120. hresult = OleRegEnumVerbs(m_clsid, ppenumOleVerb);
  2121. errRtn:
  2122. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::EnumVerbs "
  2123. "( %lx ) [ %p ]\n", this, hresult, *ppenumOleVerb));
  2124. return hresult;
  2125. }
  2126. //+-------------------------------------------------------------------------
  2127. //
  2128. // Member: CDefLink::GetUserClassID
  2129. //
  2130. // Synopsis: Retrieves the class id of the linked object
  2131. //
  2132. // Effects:
  2133. //
  2134. // Arguments: [pClassID] -- where to put the class ID
  2135. //
  2136. // Requires:
  2137. //
  2138. // Returns: HRESULT
  2139. //
  2140. // Signals:
  2141. //
  2142. // Modifies:
  2143. //
  2144. // Derivation: IOleObject
  2145. //
  2146. // Algorithm:
  2147. //
  2148. // History: dd-mmm-yy Author Comment
  2149. // 21-Nov-94 alexgo memory optimization
  2150. // 18-Nov-93 alexgo 32bit port
  2151. //
  2152. // Notes: No need to stabilize as we make no outgoing calls
  2153. //
  2154. //--------------------------------------------------------------------------
  2155. STDMETHODIMP CDefLink::GetUserClassID(CLSID *pClassID)
  2156. {
  2157. VDATEHEAP();
  2158. VDATETHREAD(this);
  2159. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::GetUserClass"
  2160. "ID ( %p )\n", this, pClassID));
  2161. VDATEPTROUT(pClassID, CLSID);
  2162. *pClassID = m_clsid;
  2163. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::GetUserClass"
  2164. "ID ( %lx )\n", this, NOERROR ));
  2165. return NOERROR;
  2166. }
  2167. //+-------------------------------------------------------------------------
  2168. //
  2169. // Member: CDefLink::GetUserType
  2170. //
  2171. // Synopsis: Retrieves a descriptive string about the server type
  2172. //
  2173. // Effects:
  2174. //
  2175. // Arguments: [dwFormOfType] -- indicates whether a short or long string
  2176. // description is desired
  2177. // [pszUserType] -- where to put the string
  2178. //
  2179. // Requires:
  2180. //
  2181. // Returns: HRESULT
  2182. //
  2183. // Signals:
  2184. //
  2185. // Modifies:
  2186. //
  2187. // Derivation: IOleObject
  2188. //
  2189. // Algorithm: Asks the server delegate, if that fails or the server
  2190. // returns OLE_E_USEREG, then get the info from the registration
  2191. // database
  2192. //
  2193. // History: dd-mmm-yy Author Comment
  2194. // 21-Nov-94 alexgo memory optimization
  2195. // 03-Aug-94 alexgo stabilized
  2196. // 30-May-94 alexgo now handles crashed servers
  2197. // 18-Nov-93 alexgo 32bit port
  2198. //
  2199. // Notes:
  2200. //
  2201. //--------------------------------------------------------------------------
  2202. STDMETHODIMP CDefLink::GetUserType(DWORD dwFormOfType,
  2203. LPOLESTR *ppszUserType)
  2204. {
  2205. HRESULT hresult;
  2206. VDATEHEAP();
  2207. VDATETHREAD(this);
  2208. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::GetUserType "
  2209. "( %lu , %p )\n", this, dwFormOfType, ppszUserType));
  2210. VDATEPTROUT(ppszUserType, LPOLESTR);
  2211. *ppszUserType = NULL;
  2212. CRefStabilize stabilize(this);
  2213. if( GetOleDelegate() )
  2214. {
  2215. hresult = m_pOleDelegate->GetUserType (dwFormOfType,
  2216. ppszUserType);
  2217. if( !GET_FROM_REGDB(hresult) )
  2218. {
  2219. if( SUCCEEDED(hresult) || IsReallyRunning() )
  2220. {
  2221. // if we failed, but the server is still
  2222. // running, then go ahead and propogate the
  2223. // error to the caller.
  2224. // Note that IsReallyRunning will clean up our
  2225. // state if the server had crashed.
  2226. goto errRtn;
  2227. }
  2228. // FALL-THROUGH!! This is deliberate. If
  2229. // the call failed and the server is no longer
  2230. // running, then we assume the server has crashed.
  2231. // We want to go ahead and fetch the information
  2232. // from the registry.
  2233. }
  2234. }
  2235. // Not running, or object wants to use reg db anyway
  2236. // Consult reg db
  2237. hresult = OleRegGetUserType(m_clsid, dwFormOfType,
  2238. ppszUserType);
  2239. // it is not appropriate to read from the stg since the storage is
  2240. // owned by the link, not the link source (thus, the link source
  2241. // never has the opportunity to call WriteFmtUserTypeStg on the
  2242. // link object's storage).
  2243. // We also do not need to bother storing the last known user
  2244. // type because if we can get it for one particular clsid, we
  2245. // should always be able to get it. If we can't get the user type,
  2246. // then either we have never gotten a user type (and thus don't
  2247. // have a "last known") or we've changed clsid's (in which case,
  2248. // the last known user type would be wrong).
  2249. errRtn:
  2250. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::GetUserType "
  2251. "( %lx ) [ %p ]\n", this, hresult, *ppszUserType));
  2252. return hresult;
  2253. }
  2254. //+-------------------------------------------------------------------------
  2255. //
  2256. // Member: CDefLink::Update
  2257. //
  2258. // Synopsis: Updates the link (by calling IOleLink->Update)
  2259. //
  2260. // Effects:
  2261. //
  2262. // Arguments: void
  2263. //
  2264. // Requires:
  2265. //
  2266. // Returns: HRESULT
  2267. //
  2268. // Signals:
  2269. //
  2270. // Modifies:
  2271. //
  2272. // Derivation: IOleObject
  2273. //
  2274. // Algorithm:
  2275. //
  2276. // History: dd-mmm-yy Author Comment
  2277. // 21-Nov-94 alexgo memory optimization
  2278. // 03-Aug-94 alexgo stabilized
  2279. // 18-Nov-93 alexgo 32bit port
  2280. //
  2281. // Notes:
  2282. //
  2283. //--------------------------------------------------------------------------
  2284. STDMETHODIMP CDefLink::Update(void)
  2285. {
  2286. HRESULT hresult;
  2287. VDATEHEAP();
  2288. VDATETHREAD(this);
  2289. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::Update ( )\n",
  2290. this ));
  2291. CRefStabilize stabilize(this);
  2292. hresult = Update(NULL);
  2293. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::Update ( "
  2294. "%lx )\n", this, hresult));
  2295. return hresult;
  2296. }
  2297. //fudge value
  2298. #define TwoSeconds 0x01312D00
  2299. //+-------------------------------------------------------------------------
  2300. //
  2301. // Member: CDefLink::IsUpToDate
  2302. //
  2303. // Synopsis: Determines whether or not a link is up-to-date
  2304. //
  2305. // Effects:
  2306. //
  2307. // Arguments: void
  2308. //
  2309. // Requires:
  2310. //
  2311. // Returns: HRESULT -- NOERROR == IsUpToDate, S_FALSE == out of date
  2312. //
  2313. // Signals:
  2314. //
  2315. // Modifies:
  2316. //
  2317. // Derivation: IOleObject
  2318. //
  2319. // Algorithm: The current time is compared with the last time known
  2320. // up-to-date on *both* machines (the process of the container
  2321. // and the process of the link). These time differences are
  2322. // compared to determine whether the link is out-of-date.
  2323. // See the UpdateTimes method.
  2324. //
  2325. // History: dd-mmm-yy Author Comment
  2326. // 09-Jan-95 alexgo correctly answer IsUpToDate now; also
  2327. // fixup monikers if needed.
  2328. // 21-Nov-94 alexgo memory optimization
  2329. // 03-Aug-94 alexgo stabilized
  2330. // 19-Nov-93 alexgo 32bit port
  2331. //
  2332. // Notes: The arithmetic calculations in this method assume
  2333. // two's complement arithmetic and a high order sign bit
  2334. // (true for most current machines)
  2335. //
  2336. //--------------------------------------------------------------------------
  2337. STDMETHODIMP CDefLink::IsUpToDate(void)
  2338. {
  2339. FILETIME rtTimeOfLastChange;
  2340. LPMONIKER pmkAbs = NULL;
  2341. IMoniker * pmkContainer = NULL;
  2342. HRESULT hresult = NOERROR;
  2343. LPBINDCTX pbc = NULL;
  2344. FILETIME rtDiff;
  2345. FILETIME ltDiff;
  2346. FILETIME ftTemp;
  2347. FILETIME ftNow;
  2348. BOOL fHighBitSet;
  2349. VDATEHEAP();
  2350. VDATETHREAD(this);
  2351. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::IsUpToDate "
  2352. "( )\n", this ));
  2353. CRefStabilize stabilize(this);
  2354. if (m_dwUpdateOpt == OLEUPDATE_ALWAYS &&
  2355. IsRunning())
  2356. {
  2357. // hresult == NOERROR from default initializer
  2358. goto errRet;
  2359. }
  2360. // use the relative moniker if it exists and if the container
  2361. // has a moniker
  2362. if (NOERROR != GetAbsMkFromRel(&pmkAbs, &pmkContainer))
  2363. {
  2364. // otherwise use the absolute moniker
  2365. if (pmkAbs = m_pMonikerAbs)
  2366. {
  2367. pmkAbs->AddRef();
  2368. }
  2369. }
  2370. if (pmkAbs == NULL)
  2371. {
  2372. hresult = MK_E_UNAVAILABLE;
  2373. goto errRet;
  2374. }
  2375. hresult = CreateBindCtx( 0, &pbc );
  2376. if (hresult != NOERROR)
  2377. {
  2378. goto errRet;
  2379. }
  2380. //get the remote time of last change
  2381. hresult = pmkAbs->GetTimeOfLastChange(pbc, NULL, &rtTimeOfLastChange);
  2382. if (hresult != NOERROR)
  2383. {
  2384. // if GetTimeOfLastChange failed, it's possible that the moniker
  2385. // we constructed is bogus. Try again using the *real* absolute
  2386. // moniker. We do this to mimic bind behaviour. The moniker
  2387. // we use above is constructed from the relative moniker. In binding,
  2388. // if the relative moniker fails, then we fall back to the last
  2389. // known real absolute moniker.
  2390. BOOL fSuccess = FALSE;
  2391. if( m_pMonikerAbs )
  2392. {
  2393. if (pmkAbs != m_pMonikerAbs)
  2394. {
  2395. // do this if we did the bind on the relative one.above
  2396. hresult = m_pMonikerAbs->GetTimeOfLastChange(pbc, NULL,
  2397. &rtTimeOfLastChange);
  2398. if( hresult == NOERROR )
  2399. {
  2400. fSuccess = TRUE;
  2401. // hang onto the better absolute moniker
  2402. pmkAbs->Release(); // releases the one we contructed
  2403. // in GetAbsMkFromRel
  2404. pmkAbs = m_pMonikerAbs;
  2405. pmkAbs->AddRef(); // so the Release() down below
  2406. } // doesn't hose us.
  2407. }
  2408. #ifdef _TRACKLINK_
  2409. if (!fSuccess)
  2410. {
  2411. // at this point we have tried either: relative then absolute OR
  2412. // just absolute. We now should try the reduced absolute one.
  2413. IMoniker *pmkReduced;
  2414. EnableTracking(m_pMonikerAbs, OT_ENABLEREDUCE);
  2415. hresult = m_pMonikerAbs->Reduce(pbc, MKRREDUCE_ALL, NULL, &pmkReduced);
  2416. EnableTracking(m_pMonikerAbs, OT_DISABLEREDUCE);
  2417. if (hresult == NOERROR)
  2418. {
  2419. hresult = pmkReduced->GetTimeOfLastChange(pbc, NULL,
  2420. &rtTimeOfLastChange);
  2421. if (hresult != NOERROR)
  2422. {
  2423. pmkReduced->Release();
  2424. }
  2425. else
  2426. {
  2427. fSuccess = TRUE;
  2428. pmkAbs->Release();
  2429. pmkAbs = pmkReduced;
  2430. }
  2431. }
  2432. }
  2433. #endif
  2434. }
  2435. if (!fSuccess)
  2436. {
  2437. hresult = MK_E_UNAVAILABLE;
  2438. goto errRet;
  2439. }
  2440. }
  2441. // once we get this far, we know that either 1. the relative moniker
  2442. // is good, or 2. the absolute moniker is good. In any event, pmkAbs
  2443. // now points to a (semi)-reasonable spot. (I say 'semi', because
  2444. // even though GetTimeOfLastChange succeeded, we aren't guaranteed that
  2445. // a Bind would be successful.
  2446. //
  2447. // check to see if we need to update the relative moniker (if we don't
  2448. // already have one, don't bother.) It is also possible that the
  2449. // absolute moniker is now bad. Use the known 'good' one and update
  2450. // both monikers
  2451. // we ignore the return code here; if this call fails, it is not
  2452. // serious.
  2453. // pmkContainer may be NULL if our container doesn't offer us one.
  2454. if( pmkContainer )
  2455. {
  2456. UpdateMksFromAbs(pmkContainer, pmkAbs);
  2457. pmkContainer->Release();
  2458. }
  2459. // compute rtDiff = max(0, rtTimeOfLastChange - rtUpdate)
  2460. // possibly optimize with _fmemcopy
  2461. // debugging aid
  2462. DumpSzTime("IsUpToDate: rtTimeOfLastChange = ", rtTimeOfLastChange);
  2463. // start rtDiff calculation
  2464. rtDiff = rtTimeOfLastChange;
  2465. // debugging aid
  2466. DumpSzTime("IsUpToDate: rtUpdate = ", m_rtUpdate);
  2467. // the following subtractions rely on two's complement
  2468. if (m_rtUpdate.dwLowDateTime > rtDiff.dwLowDateTime)
  2469. {
  2470. //handle the carry
  2471. rtDiff.dwHighDateTime =
  2472. (DWORD)((LONG)rtDiff.dwHighDateTime - 1);
  2473. }
  2474. rtDiff.dwLowDateTime = (DWORD)((LONG)rtDiff.dwLowDateTime -
  2475. (LONG)m_rtUpdate.dwLowDateTime);
  2476. rtDiff.dwHighDateTime = (DWORD)((LONG)rtDiff.dwHighDateTime -
  2477. (LONG)m_rtUpdate.dwHighDateTime);
  2478. // if rtDiff < 0, say we are out of date.
  2479. if ((LONG)rtDiff.dwHighDateTime < 0)
  2480. {
  2481. hresult = S_FALSE;
  2482. goto errRet;
  2483. }
  2484. if (rtDiff.dwHighDateTime == 0 && rtDiff.dwLowDateTime == 0)
  2485. {
  2486. // no time difference. could be due to large clock ticks,
  2487. // so we say we are up to date only if several seconds have
  2488. // elapsed since last known update time.
  2489. CoFileTimeNow( &ftNow );
  2490. ftTemp = m_ltKnownUpToDate;
  2491. // This bit of logic may seem strange. All we want is
  2492. // is to test the high bit in a portable fashion
  2493. // between 32/64bit machines (so a constant isn't good)
  2494. // As long as the sign bit is the high order bit, then
  2495. // this trick will do
  2496. fHighBitSet = ((LONG)ftTemp.dwLowDateTime < 0);
  2497. ftTemp.dwLowDateTime += TwoSeconds;
  2498. // if the high bit was set, and now it's zero, then we
  2499. // had a carry
  2500. if (fHighBitSet && ((LONG)ftTemp.dwLowDateTime >= 0))
  2501. {
  2502. ftTemp.dwHighDateTime++; // handle the carry.
  2503. }
  2504. // compare times
  2505. if ((ftNow.dwHighDateTime > ftTemp.dwHighDateTime) ||
  2506. ((ftNow.dwHighDateTime == ftTemp.dwHighDateTime) &&
  2507. (ftNow.dwLowDateTime > ftTemp.dwLowDateTime)))
  2508. {
  2509. hresult = NOERROR;
  2510. }
  2511. else
  2512. {
  2513. hresult = S_FALSE;
  2514. }
  2515. }
  2516. else
  2517. {
  2518. // there was a time difference
  2519. // compute ltDiff = max(0, m_ltKnownUpToDate -
  2520. // m_ltChangeOfUpdate);
  2521. // Actually, by this time we know rtDiff >= 0, so we can
  2522. // simply compare ltDiff with rtDiff -- no need to compute
  2523. // the max.
  2524. ltDiff = m_ltKnownUpToDate;
  2525. // debugging aid
  2526. DumpSzTime("IsUpToDate: ltKnownUpToDate = ",ltDiff);
  2527. DumpSzTime("IsUpToDate: ltChangeOfUpdate = ",
  2528. m_ltChangeOfUpdate);
  2529. // these calc's rely on two's complement.
  2530. if (m_ltChangeOfUpdate.dwLowDateTime >
  2531. ltDiff.dwLowDateTime)
  2532. {
  2533. // handle carry
  2534. ltDiff.dwHighDateTime =
  2535. (DWORD)((LONG)ltDiff.dwHighDateTime - 1);
  2536. }
  2537. ltDiff.dwLowDateTime = (DWORD)((LONG)ltDiff.dwLowDateTime -
  2538. (LONG)m_ltChangeOfUpdate.dwLowDateTime);
  2539. ltDiff.dwHighDateTime = (DWORD)((LONG)ltDiff.dwHighDateTime -
  2540. (LONG)m_ltChangeOfUpdate.dwHighDateTime);
  2541. // Now determine if rtDiff < ltDiff
  2542. if (ltDiff.dwHighDateTime > rtDiff.dwHighDateTime)
  2543. {
  2544. hresult = NOERROR;
  2545. }
  2546. else if (ltDiff.dwHighDateTime == rtDiff.dwHighDateTime)
  2547. {
  2548. if (ltDiff.dwLowDateTime > rtDiff.dwLowDateTime)
  2549. {
  2550. hresult = NOERROR;
  2551. }
  2552. else
  2553. {
  2554. hresult = S_FALSE;
  2555. }
  2556. }
  2557. else
  2558. {
  2559. hresult = S_FALSE;
  2560. }
  2561. }
  2562. // all cases should have been handled by this point. Release
  2563. // any resources grabbed.
  2564. errRet:
  2565. if (pmkAbs)
  2566. {
  2567. pmkAbs->Release();
  2568. }
  2569. if (pbc)
  2570. {
  2571. pbc->Release();
  2572. }
  2573. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::IsUpToDate "
  2574. "( %lx )\n", this, hresult));
  2575. return hresult;
  2576. }
  2577. //+-------------------------------------------------------------------------
  2578. //
  2579. // Member: CDefLink::SetExtent
  2580. //
  2581. // Synopsis: Sets the drawing extents, not allowed for links
  2582. //
  2583. // Effects:
  2584. //
  2585. // Arguments: [dwDrawAspect] -- the drawing aspect
  2586. // [lpsizel] -- the new extents
  2587. //
  2588. // Requires:
  2589. //
  2590. // Returns: E_UNSPEC (not allowed)
  2591. //
  2592. // Signals:
  2593. //
  2594. // Modifies:
  2595. //
  2596. // Derivation: IOleObject
  2597. //
  2598. // Algorithm:
  2599. //
  2600. // History: dd-mmm-yy Author Comment
  2601. // 21-Nov-94 alexgo memory optimization
  2602. // 19-Nov-93 alexgo 32 bit port
  2603. //
  2604. // Notes:
  2605. //
  2606. //--------------------------------------------------------------------------
  2607. STDMETHODIMP CDefLink::SetExtent(DWORD dwDrawAspect, LPSIZEL lpsizel)
  2608. {
  2609. VDATEHEAP();
  2610. VDATETHREAD(this);
  2611. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::SetExtent "
  2612. "( %lx , %p )\n", this, dwDrawAspect, lpsizel));
  2613. LEDebugOut((DEB_WARN, "Set Extent called for links, E_UNSPEC \n"));
  2614. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::SetExtent "
  2615. "( %lx )\n", this, E_UNSPEC));
  2616. return E_UNSPEC; // can't call this for a link
  2617. }
  2618. //+-------------------------------------------------------------------------
  2619. //
  2620. // Member: CDefLink::GetExtent
  2621. //
  2622. // Synopsis: Get's the size (extents) of the object
  2623. //
  2624. // Effects:
  2625. //
  2626. // Arguments: [dwDrawAspect] -- the drawing aspect
  2627. // [lpsizel] -- where to put the extents
  2628. //
  2629. // Requires:
  2630. //
  2631. // Returns: HRESULT
  2632. //
  2633. // Signals:
  2634. //
  2635. // Modifies:
  2636. //
  2637. // Derivation: IOleObject
  2638. //
  2639. // Algorithm: Asks the server first, if not running or an error
  2640. // then delegate to the cache
  2641. //
  2642. // History: dd-mmm-yy Author Comment
  2643. // 21-Nov-94 alexgo memory optimization
  2644. // 03-Aug-94 alexgo stabilized
  2645. // 19-Nov-93 alexgo 32bit port
  2646. //
  2647. // Notes:
  2648. //
  2649. //--------------------------------------------------------------------------
  2650. STDMETHODIMP CDefLink::GetExtent( DWORD dwDrawAspect, LPSIZEL lpsizel)
  2651. {
  2652. HRESULT error = E_FAIL;
  2653. VDATEHEAP();
  2654. VDATETHREAD(this);
  2655. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::GetExtent "
  2656. "( %lx , %p )\n", this, dwDrawAspect, lpsizel));
  2657. VDATEPTROUT(lpsizel, SIZEL);
  2658. CRefStabilize stabilize(this);
  2659. lpsizel->cx = 0;
  2660. lpsizel->cy = 0;
  2661. // if server is running try to get extents from the server
  2662. if( GetOleDelegate() )
  2663. {
  2664. error = m_pOleDelegate->GetExtent(dwDrawAspect, lpsizel);
  2665. }
  2666. // if there is error or object is not running get extents from Cache
  2667. if( error != NOERROR )
  2668. {
  2669. Assert(m_pCOleCache != NULL);
  2670. error = m_pCOleCache->GetExtent(dwDrawAspect,
  2671. lpsizel);
  2672. }
  2673. // WordArt2.0 is giving negative extents!!
  2674. if (SUCCEEDED(error))
  2675. {
  2676. lpsizel->cx = LONG_ABS(lpsizel->cx);
  2677. lpsizel->cy = LONG_ABS(lpsizel->cy);
  2678. }
  2679. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::GetExtent "
  2680. "( %lx )\n", this, error ));
  2681. return error;
  2682. }
  2683. //+-------------------------------------------------------------------------
  2684. //
  2685. // Member: CDefLink::Advise
  2686. //
  2687. // Synopsis: Sets up an advise connection to the object for things like
  2688. // Close, Save, etc.
  2689. //
  2690. // Effects:
  2691. //
  2692. // Arguments: [pAdvSink] -- whom to notify
  2693. // [pdwConnection] -- where to put the connection ID
  2694. //
  2695. // Requires:
  2696. //
  2697. // Returns: HRESULT
  2698. //
  2699. // Signals:
  2700. //
  2701. // Modifies:
  2702. //
  2703. // Derivation: IOleObject
  2704. //
  2705. // Algorithm: Creates an OleAdvise holder (if one not already present
  2706. // and then delegates to it)
  2707. //
  2708. // History: dd-mmm-yy Author Comment
  2709. // 21-Nov-94 alexgo memory optimization
  2710. // 03-Aug-94 alexgo stabilized and handle zombie case
  2711. // 19-Nov-93 alexgo 32bit port
  2712. //
  2713. // Notes:
  2714. //
  2715. //--------------------------------------------------------------------------
  2716. STDMETHODIMP CDefLink::Advise(IAdviseSink *pAdvSink,
  2717. DWORD *pdwConnection)
  2718. {
  2719. HRESULT hresult;
  2720. VDATEHEAP();
  2721. VDATETHREAD(this);
  2722. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::Advise "
  2723. "( %p , %p )\n", this, pAdvSink, pdwConnection));
  2724. CRefStabilize stabilize(this);
  2725. if( IsZombie() )
  2726. {
  2727. hresult = CO_E_RELEASED;
  2728. goto errRtn;
  2729. }
  2730. // if we haven't got an advise holder yet, allocate one
  2731. if (m_pCOAHolder == NULL)
  2732. {
  2733. // allocate the advise holder
  2734. m_pCOAHolder = new FAR COAHolder;
  2735. // check to make sure we got one
  2736. if (m_pCOAHolder == NULL)
  2737. {
  2738. hresult = E_OUTOFMEMORY;
  2739. goto errRtn;
  2740. }
  2741. }
  2742. // delegate the call to the advise holder
  2743. hresult = m_pCOAHolder->Advise(pAdvSink, pdwConnection);
  2744. errRtn:
  2745. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::Advise "
  2746. "( %lx ) [ %lu ]\n", this, hresult,
  2747. (pdwConnection) ? *pdwConnection : 0 ));
  2748. return hresult;
  2749. }
  2750. //+-------------------------------------------------------------------------
  2751. //
  2752. // Member: CDefLink::Unadvise
  2753. //
  2754. // Synopsis: Removes an advise connection to the object
  2755. //
  2756. // Effects:
  2757. //
  2758. // Arguments: [dwConnection] -- the connection ID to remove
  2759. //
  2760. // Requires:
  2761. //
  2762. // Returns: HRESULT
  2763. //
  2764. // Signals:
  2765. //
  2766. // Modifies:
  2767. //
  2768. // Derivation: IOleObject
  2769. //
  2770. // Algorithm: Delegates to the OleAdvise holder (which was created
  2771. // during the Advise--if it wasn't, then we are in a strange
  2772. // state).
  2773. //
  2774. // History: dd-mmm-yy Author Comment
  2775. // 21-Nov-94 alexgo memory optimization
  2776. // 03-Aug-94 alexgo stabilized
  2777. // 19-Nov-93 alexgo 32bit port
  2778. //
  2779. // Notes:
  2780. //
  2781. //--------------------------------------------------------------------------
  2782. STDMETHODIMP CDefLink::Unadvise(DWORD dwConnection)
  2783. {
  2784. HRESULT hresult;
  2785. VDATEHEAP();
  2786. VDATETHREAD(this);
  2787. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::Unadvise "
  2788. "( %lu )\n", this, dwConnection ));
  2789. CRefStabilize stabilize(this);
  2790. if (m_pCOAHolder == NULL)
  2791. {
  2792. // no one registered
  2793. hresult = E_UNEXPECTED;
  2794. }
  2795. else
  2796. {
  2797. hresult = m_pCOAHolder->Unadvise(dwConnection);
  2798. }
  2799. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::Unadvise "
  2800. "( %lx )\n", this, hresult ));
  2801. return hresult;
  2802. }
  2803. //+-------------------------------------------------------------------------
  2804. //
  2805. // Member: CDefLink::EnumAdvise
  2806. //
  2807. // Synopsis: Enumerates the advise connections on the object
  2808. //
  2809. // Effects:
  2810. //
  2811. // Arguments: [ppenumAdvise] -- where to put the pointer to the advise
  2812. // enumerator
  2813. //
  2814. // Requires:
  2815. //
  2816. // Returns: HRESULT
  2817. //
  2818. // Signals:
  2819. //
  2820. // Modifies:
  2821. //
  2822. // Derivation: IOleObject
  2823. //
  2824. // Algorithm: Delegates to the advise holder
  2825. //
  2826. // History: dd-mmm-yy Author Comment
  2827. // 21-Nov-94 alexgo memory optimization
  2828. // 19-Nov-93 alexgo 32bit port
  2829. //
  2830. // Notes: We do not need to stabilize this method as we only allocate
  2831. // memory for hte advise enumerator
  2832. //
  2833. //--------------------------------------------------------------------------
  2834. STDMETHODIMP CDefLink::EnumAdvise( LPENUMSTATDATA *ppenumAdvise )
  2835. {
  2836. HRESULT hresult;
  2837. VDATEHEAP();
  2838. VDATETHREAD(this);
  2839. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::EnumAdvise "
  2840. "( %p )\n", this, ppenumAdvise ));
  2841. if (m_pCOAHolder == NULL)
  2842. {
  2843. // no one registered
  2844. hresult = E_UNSPEC;
  2845. }
  2846. else
  2847. {
  2848. hresult = m_pCOAHolder->EnumAdvise(ppenumAdvise);
  2849. }
  2850. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::EnumAdvise "
  2851. "( %lx ) [ %p ]\n", this, hresult, *ppenumAdvise ));
  2852. return hresult;
  2853. }
  2854. //+-------------------------------------------------------------------------
  2855. //
  2856. // Member: CDefLink::GetMiscStatus
  2857. //
  2858. // Synopsis: Gets the miscellaneous status bits (such as
  2859. // OLEMISC_ONLYICONIC)
  2860. //
  2861. // Effects:
  2862. //
  2863. // Arguments: [dwAspect] -- the drawing aspect
  2864. // [pdwStatus] -- where to put the status bits
  2865. //
  2866. // Requires:
  2867. //
  2868. // Returns: HRESULT
  2869. //
  2870. // Signals:
  2871. //
  2872. // Modifies:
  2873. //
  2874. // Derivation: IOleObject
  2875. //
  2876. // Algorithm: Asks the server first, if not running or if it returns
  2877. // OLE_E_USEREG, then get the info from the registration
  2878. // database. We always add link-specific bits regardless
  2879. // of error conditions or what the server or regdb says.
  2880. //
  2881. // History: dd-mmm-yy Author Comment
  2882. // 21-Nov-94 alexgo memory optimization
  2883. // 03-Aug-94 alexgo stabilized
  2884. // 30-May-94 alexgo now handles crashed servers
  2885. // 19-Nov-93 alexgo 32bit port
  2886. //
  2887. // Notes:
  2888. //
  2889. //--------------------------------------------------------------------------
  2890. STDMETHODIMP CDefLink::GetMiscStatus( DWORD dwAspect, DWORD *pdwStatus)
  2891. {
  2892. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::GetMiscStatus(%lx, %p)\n",
  2893. this, dwAspect, pdwStatus ));
  2894. // Validation checks
  2895. VDATEHEAP();
  2896. VDATETHREAD(this);
  2897. VDATEPTROUT(pdwStatus, DWORD);
  2898. // Local variables
  2899. HRESULT hresult;
  2900. // Stabilize
  2901. CRefStabilize stabilize(this);
  2902. // Initialize
  2903. *pdwStatus = 0;
  2904. hresult = OLE_S_USEREG;
  2905. if(GetOleDelegate()) {
  2906. // Check if MiscStatus bits have been cached for this instance
  2907. // of server for DVASPECT_CONTENT
  2908. if(m_ContentSRVMSHResult != 0xFFFFFFFF && dwAspect == DVASPECT_CONTENT) {
  2909. *pdwStatus = m_ContentSRVMSBits;
  2910. hresult = m_ContentSRVMSHResult;
  2911. }
  2912. else {
  2913. // Ask the running server
  2914. hresult = m_pOleDelegate->GetMiscStatus (dwAspect, pdwStatus);
  2915. // Cache the server MiscStatus bits for DVASPECT_CONTENT
  2916. if(dwAspect == DVASPECT_CONTENT) {
  2917. m_ContentSRVMSBits = *pdwStatus;
  2918. m_ContentSRVMSHResult = hresult;
  2919. }
  2920. }
  2921. if(FAILED(hresult) && !GET_FROM_REGDB(hresult)) {
  2922. // Check if server is really running
  2923. BOOL fRunning = FALSE;
  2924. // Note that IsReallyRunning will cleanup if the
  2925. // server had crashed
  2926. fRunning = IsReallyRunning();
  2927. Win4Assert(fRunning);
  2928. // Hit the registry if the server crashed
  2929. if(!fRunning)
  2930. hresult = OLE_S_USEREG;
  2931. }
  2932. }
  2933. // Check if we have to obtain MiscStatus bits from the registry
  2934. if (GET_FROM_REGDB(hresult)) {
  2935. // Check if registry MiscStatus bits have been cached for DVASPECT_CONTENT
  2936. if(m_ContentREGMSHResult != 0xFFFFFFFF && dwAspect == DVASPECT_CONTENT) {
  2937. *pdwStatus = m_ContentREGMSBits;
  2938. hresult = m_ContentREGMSHResult;
  2939. }
  2940. else {
  2941. // Hit the registry
  2942. hresult = OleRegGetMiscStatus (m_clsid, dwAspect, pdwStatus);
  2943. // Cache the registry MiscStatus bits for DVASPECT_CONTENT
  2944. if(hresult == NOERROR && dwAspect == DVASPECT_CONTENT) {
  2945. m_ContentREGMSBits = *pdwStatus;
  2946. m_ContentREGMSHResult = hresult;
  2947. }
  2948. }
  2949. }
  2950. // Add link-specific bits (even if error) and return.
  2951. // we add them even if an error because in order to get here, we
  2952. // have to have instantiated this link object; thus, it is always
  2953. // valid to say OLEMISC_ISLINKOBJECT, etc.
  2954. (*pdwStatus) |= OLEMISC_CANTLINKINSIDE | OLEMISC_ISLINKOBJECT;
  2955. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::GetMiscStatus (%lx)[%lx]\n",
  2956. this, hresult, *pdwStatus ));
  2957. return hresult;
  2958. }
  2959. //+-------------------------------------------------------------------------
  2960. //
  2961. // Member: CDefLink::SetColorScheme
  2962. //
  2963. // Synopsis: Sets the palette for the object; unused for links
  2964. //
  2965. // Effects:
  2966. //
  2967. // Arguments: [lpLogpal] -- the palette
  2968. //
  2969. // Requires:
  2970. //
  2971. // Returns: NOERROR
  2972. //
  2973. // Signals:
  2974. //
  2975. // Modifies:
  2976. //
  2977. // Derivation: IOleObject
  2978. //
  2979. // Algorithm:
  2980. //
  2981. // History: dd-mmm-yy Author Comment
  2982. // 21-Nov-94 alexgo memory optimization
  2983. // 19-Nov-93 alexgo 32bit port
  2984. //
  2985. // Notes:
  2986. //
  2987. //--------------------------------------------------------------------------
  2988. STDMETHODIMP CDefLink::SetColorScheme(LPLOGPALETTE lpLogpal)
  2989. {
  2990. VDATEHEAP();
  2991. VDATETHREAD(this);
  2992. // we ignore this always
  2993. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::SetColor"
  2994. "Scheme ( %p )\n", this, lpLogpal));
  2995. LEDebugOut((DEB_WARN, "Link IOO:SetColorScheme called on a link\n"));
  2996. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::SetColor"
  2997. "Scheme ( %lx )\n", this, NOERROR));
  2998. return NOERROR;
  2999. }
  3000. /*
  3001. * IMPLEMENTATION of CLinkImpl methods
  3002. *
  3003. */
  3004. //+-------------------------------------------------------------------------
  3005. //
  3006. // Member: CDefLink::BeginUpdates
  3007. //
  3008. // Synopsis: Private method to update the caches and then set the update
  3009. // times
  3010. //
  3011. // Effects:
  3012. //
  3013. // Arguments: void
  3014. //
  3015. // Requires:
  3016. //
  3017. // Returns: void
  3018. //
  3019. // Signals:
  3020. //
  3021. // Modifies:
  3022. //
  3023. // Derivation:
  3024. //
  3025. // Algorithm:
  3026. //
  3027. // History: dd-mmm-yy Author Comment
  3028. // 21-Nov-94 alexgo memory optimization
  3029. // 19-Nov-93 alexgo 32bit port
  3030. //
  3031. // Notes:
  3032. //
  3033. //--------------------------------------------------------------------------
  3034. INTERNAL_(void) CDefLink::BeginUpdates(void)
  3035. {
  3036. VDATEHEAP();
  3037. LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::BeginUpdates ( )\n", this));
  3038. IDataObject FAR* pDataDelegate;
  3039. if( pDataDelegate = GetDataDelegate() )
  3040. {
  3041. // inform cache that we are running
  3042. Assert(m_pCOleCache != NULL);
  3043. m_pCOleCache->OnRun(pDataDelegate);
  3044. // update only the automatic local caches from the newly
  3045. // running src
  3046. m_pCOleCache->UpdateCache(pDataDelegate, UPDFCACHE_NORMALCACHE,
  3047. NULL);
  3048. // we are an automatic link which is now up to date
  3049. SetUpdateTimes();
  3050. }
  3051. LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::BeginUpdates ( )\n", this ));
  3052. }
  3053. //+-------------------------------------------------------------------------
  3054. //
  3055. // Member: CDefLink::EndUpdates
  3056. //
  3057. // Synopsis: Calls OnStop on the cache
  3058. //
  3059. // Effects:
  3060. //
  3061. // Arguments: void
  3062. //
  3063. // Requires:
  3064. //
  3065. // Returns: void
  3066. //
  3067. // Signals:
  3068. //
  3069. // Modifies:
  3070. //
  3071. // Derivation:
  3072. //
  3073. // Algorithm:
  3074. //
  3075. // History: dd-mmm-yy Author Comment
  3076. // 21-Nov-94 alexgo memory optimization
  3077. // 19-Nov-93 alexgo 32bit port
  3078. //
  3079. // Notes:
  3080. //
  3081. //--------------------------------------------------------------------------
  3082. INTERNAL_(void) CDefLink::EndUpdates(void)
  3083. {
  3084. VDATEHEAP();
  3085. LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::EndUpdates ( )\n", this));
  3086. Assert(m_pCOleCache != NULL);
  3087. m_pCOleCache->OnStop();
  3088. LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::EndUpdates ( )\n", this));
  3089. }
  3090. //+-------------------------------------------------------------------------
  3091. //
  3092. // Member: CDefLink::UpdateAutoOnSave
  3093. //
  3094. // Synopsis: Updates caches that have been set with ADVFCACHE_ONSAVE
  3095. // and sets the update times. Private method
  3096. //
  3097. // Effects:
  3098. //
  3099. // Arguments: void
  3100. //
  3101. // Requires:
  3102. //
  3103. // Returns: void
  3104. //
  3105. // Signals:
  3106. //
  3107. // Modifies:
  3108. //
  3109. // Derivation:
  3110. //
  3111. // Algorithm:
  3112. //
  3113. // History: dd-mmm-yy Author Comment
  3114. // 21-Nov-94 alexgo memory optimization
  3115. // 19-Nov-93 alexgo 32bit port
  3116. //
  3117. // Notes:
  3118. //
  3119. //--------------------------------------------------------------------------
  3120. INTERNAL_(void) CDefLink::UpdateAutoOnSave(void)
  3121. {
  3122. VDATEHEAP();
  3123. LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::UpdateAutoOnSave ( )\n",
  3124. this));
  3125. // if m_pUnkDelegate is non-NULL, assume we are running
  3126. // (we only want to take the hit of the rpc-call IsRunning
  3127. // on external entry points.
  3128. if (m_pUnkDelegate && m_dwUpdateOpt == OLEUPDATE_ALWAYS)
  3129. {
  3130. // update any cache which has ADVFCACHE_ONSAVE
  3131. Assert(m_pCOleCache != NULL);
  3132. //REVIEW32: I think SetUpdateTimes ought to be called
  3133. //*after* the cache has been updated (that's what
  3134. //BeginUpdates does as well)
  3135. SetUpdateTimes();
  3136. m_pCOleCache->UpdateCache(GetDataDelegate(),
  3137. UPDFCACHE_IFBLANKORONSAVECACHE, NULL);
  3138. }
  3139. LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::UpdateAutoOnSaves ( )\n",
  3140. this));
  3141. }
  3142. //+-------------------------------------------------------------------------
  3143. //
  3144. // Member: CDefLink::UpdateRelMkFromAbsMk (private)
  3145. //
  3146. // Synopsis: Creates a new relative moniker from the absolute moniker
  3147. //
  3148. // Effects:
  3149. //
  3150. // Arguments: [pmkContainer] -- the moniker to the container (may be NULL)
  3151. //
  3152. // Requires:
  3153. //
  3154. // Returns: void
  3155. //
  3156. // Signals:
  3157. //
  3158. // Modifies:
  3159. //
  3160. // Derivation:
  3161. //
  3162. // Algorithm:
  3163. //
  3164. // History: dd-mmm-yy Author Comment
  3165. // 21-Nov-94 alexgo memory optimization
  3166. // 03-Feb-94 alexgo check for NULL before SendOnLinkSrcChange
  3167. // 19-Nov-93 alexgo 32bit port
  3168. //
  3169. // Notes:
  3170. //
  3171. // update relative moniker from abs; always release relative moniker;
  3172. // may leave relative moniker NULL; doesn't return an error (because
  3173. // no caller wanted it); dirties the link when we get rid of an
  3174. // existing relative moniker or get a new one.
  3175. //
  3176. //--------------------------------------------------------------------------
  3177. INTERNAL_(void) CDefLink::UpdateRelMkFromAbsMk(IMoniker *pmkContainer)
  3178. {
  3179. LPMONIKER pmkTemp = NULL;
  3180. BOOL fNeedToAdvise = FALSE;
  3181. HRESULT hresult;
  3182. VDATEHEAP();
  3183. LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::UpdateRelMkFromAbsMk ( %p )\n",
  3184. this, pmkContainer ));
  3185. if (m_pMonikerRel)
  3186. {
  3187. m_pMonikerRel->Release();
  3188. m_pMonikerRel = NULL;
  3189. m_flags |= DL_DIRTY_LINK; // got rid on an existing moniker, now dirty
  3190. fNeedToAdvise = TRUE;
  3191. }
  3192. // NOTE: m_pMonikerRel is now NULL and only set when if we get a
  3193. // new one
  3194. if (m_pMonikerAbs == NULL)
  3195. {
  3196. // no abs mk thus no relative one
  3197. goto errRtn;
  3198. }
  3199. if (pmkContainer)
  3200. {
  3201. pmkTemp = pmkContainer;
  3202. }
  3203. else
  3204. {
  3205. hresult = GetMoniker( OLEGETMONIKER_ONLYIFTHERE, // it will be
  3206. OLEWHICHMK_CONTAINER, &pmkTemp );
  3207. AssertOutPtrIface(hresult, pmkTemp);
  3208. if (hresult != NOERROR)
  3209. {
  3210. // no container moniker, thus no relative one to it
  3211. goto errRtn;
  3212. }
  3213. Assert(pmkTemp != NULL);
  3214. }
  3215. hresult = pmkTemp->RelativePathTo(m_pMonikerAbs, &m_pMonikerRel);
  3216. AssertOutPtrIface(hresult, m_pMonikerRel);
  3217. if (hresult != NOERROR)
  3218. {
  3219. // no relationship between container and absolute, thus no
  3220. // relative
  3221. if (m_pMonikerRel)
  3222. {
  3223. m_pMonikerRel->Release();
  3224. m_pMonikerRel = NULL;
  3225. }
  3226. }
  3227. if (pmkContainer == NULL)
  3228. {
  3229. // new moniker was allocated and needs to be released
  3230. pmkTemp->Release();
  3231. }
  3232. if (m_pMonikerRel != NULL)
  3233. {
  3234. m_flags |= DL_DIRTY_LINK; // have new relative moniker; dirty
  3235. fNeedToAdvise = TRUE;
  3236. }
  3237. // if there's an advise holder and we need to advise, send out
  3238. // the change notification.
  3239. if (fNeedToAdvise && m_pCOAHolder)
  3240. {
  3241. m_pCOAHolder->SendOnLinkSrcChange(m_pMonikerAbs);
  3242. }
  3243. errRtn:
  3244. LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::UpdateRelMkFromAbsMk ( %p )\n",
  3245. this, pmkContainer ));
  3246. }
  3247. //+-------------------------------------------------------------------------
  3248. //
  3249. // Member: CDefLink::UpdateMksFromAbs
  3250. //
  3251. // Synopsis: make a reasonable attempt to get valid rel && absolute
  3252. // monikers
  3253. //
  3254. // Effects:
  3255. //
  3256. // Arguments: [pmkContainer] -- the moniker to the container
  3257. // [pmkAbs] -- 'good' absolute moniker
  3258. //
  3259. // Requires:
  3260. //
  3261. // Returns: S_OK
  3262. //
  3263. // Signals:
  3264. //
  3265. // Modifies:
  3266. //
  3267. // Derivation:
  3268. //
  3269. // Algorithm:
  3270. //
  3271. // History: dd-mmm-yy Author Comment
  3272. // 09-Jan-95 alexgo author
  3273. //
  3274. // Notes: This function should only be used when we aren't 100% sure
  3275. // of the validity of the moniker (i.e. after an IMoniker::
  3276. // TimeOfLastChange call). We do not do any error
  3277. // recovery. Basically, the idea is 'try' to put us in a
  3278. // more consistent state, but it that fails, it's OK (because
  3279. // we'd basically have OLE 16bit behaviour).
  3280. //
  3281. //--------------------------------------------------------------------------
  3282. INTERNAL CDefLink::UpdateMksFromAbs( IMoniker *pmkContainer, IMoniker *pmkAbs )
  3283. {
  3284. HRESULT hresult;
  3285. IMoniker *pmktempRel;
  3286. BOOL fNeedToUpdate = FALSE;
  3287. VDATEHEAP();
  3288. LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::UpdateMksFromAbs ( %p , %p )\n",
  3289. this, pmkContainer, pmkAbs));
  3290. // try updating the relative moniker (if one exists). Basically, we
  3291. // see if the relative moniker between pmkContainer and pmkAbs is
  3292. // any different than the moniker we currently have.
  3293. if( m_pMonikerRel )
  3294. {
  3295. hresult = pmkContainer->RelativePathTo(pmkAbs, &pmktempRel);
  3296. if( hresult == NOERROR )
  3297. {
  3298. if( pmktempRel->IsEqual(m_pMonikerRel) == S_FALSE )
  3299. {
  3300. // need to update the relative moniker.
  3301. m_pMonikerRel->Release();
  3302. m_pMonikerRel = pmktempRel;
  3303. m_pMonikerRel->AddRef();
  3304. // updated relative moniker, now dirty
  3305. m_flags |= DL_DIRTY_LINK;
  3306. fNeedToUpdate = TRUE;
  3307. }
  3308. }
  3309. }
  3310. // it is also possible that the absolute moniker is now bad. Use the
  3311. // known 'good' one.
  3312. if( m_pMonikerAbs && m_pMonikerAbs->IsEqual(pmkAbs) == S_FALSE )
  3313. {
  3314. m_pMonikerAbs->Release();
  3315. m_pMonikerAbs = pmkAbs;
  3316. m_pMonikerAbs->AddRef();
  3317. #ifdef _TRACKLINK_
  3318. EnableTracking(m_pMonikerAbs, OT_READTRACKINGINFO);
  3319. #endif
  3320. m_flags |= DL_DIRTY_LINK;
  3321. fNeedToUpdate = TRUE;
  3322. }
  3323. // send out an advise to any interested parties if we changed our
  3324. // monikers. Note that we do this even if just the relative moniker
  3325. // changed because the moniker we give apps via GetSourceMoniker is
  3326. // computed from the relative.
  3327. if( fNeedToUpdate && m_pCOAHolder )
  3328. {
  3329. m_pCOAHolder->SendOnLinkSrcChange(m_pMonikerAbs);
  3330. }
  3331. hresult = NOERROR;
  3332. LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::UpdateMksFromAbs ( %lx )\n",
  3333. this, hresult));
  3334. return hresult;
  3335. }
  3336. //+-------------------------------------------------------------------------
  3337. //
  3338. // Member: CDefLink::GetAbsMkFromRel (private)
  3339. //
  3340. // Synopsis: Gets the absolute moniker from the relative moniker
  3341. // stored in the link
  3342. //
  3343. // Effects:
  3344. //
  3345. // Arguments: [ppmkAbs] -- where to put the pointer to the moniker
  3346. // [ppmkCont] -- where to put the container moniker
  3347. // (may be NULL)
  3348. //
  3349. // Requires:
  3350. //
  3351. // Returns: HRESULT
  3352. //
  3353. // Signals:
  3354. //
  3355. // Modifies:
  3356. //
  3357. // Derivation:
  3358. //
  3359. // Algorithm: calls IMoniker->ComposeWith on the moniker to the container
  3360. //
  3361. // History: dd-mmm-yy Author Comment
  3362. // 09-Jan-95 alexgo added ppmkCont parameter
  3363. // 21-Nov-94 alexgo memory optimization
  3364. // 19-Nov-93 alexgo 32bit port
  3365. //
  3366. // Notes:
  3367. //
  3368. //--------------------------------------------------------------------------
  3369. INTERNAL CDefLink::GetAbsMkFromRel(IMoniker **ppmkAbs, IMoniker **ppmkCont )
  3370. {
  3371. LPMONIKER pmkContainer = NULL;
  3372. HRESULT hresult;
  3373. VDATEHEAP();
  3374. VDATETHREAD(this);
  3375. LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::GetAbsMkFromRel ( %p , %p )\n",
  3376. this, ppmkAbs, ppmkCont));
  3377. *ppmkAbs = NULL;
  3378. if (m_pMonikerRel == NULL)
  3379. {
  3380. hresult = E_FAIL;
  3381. goto errRtn;
  3382. }
  3383. hresult = GetMoniker( OLEGETMONIKER_ONLYIFTHERE,
  3384. OLEWHICHMK_CONTAINER, &pmkContainer );
  3385. AssertOutPtrIface(hresult, pmkContainer);
  3386. if (hresult != NOERROR)
  3387. {
  3388. goto errRtn;
  3389. }
  3390. Assert(pmkContainer != NULL);
  3391. hresult = pmkContainer->ComposeWith( m_pMonikerRel, FALSE, ppmkAbs );
  3392. if (pmkContainer)
  3393. {
  3394. if( ppmkCont )
  3395. {
  3396. *ppmkCont = pmkContainer; // no need to AddRef, just implicitly
  3397. // transfer ownership from pmkContainer
  3398. }
  3399. else
  3400. {
  3401. pmkContainer->Release();
  3402. }
  3403. }
  3404. errRtn:
  3405. LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::GetAbsMkFromRel ( %lx ) "
  3406. "[ %p ]\n", this, hresult, *ppmkAbs));
  3407. return hresult;
  3408. }
  3409. //+-------------------------------------------------------------------------
  3410. //
  3411. // Member: CDefLink::SetUpdateOptions
  3412. //
  3413. // Synopsis: Sets the update options for the link (such as always or
  3414. // manual)
  3415. //
  3416. // Effects:
  3417. //
  3418. // Arguments: [dwUpdateOpt] -- update options
  3419. //
  3420. // Requires:
  3421. //
  3422. // Returns: HRESULT
  3423. //
  3424. // Signals:
  3425. //
  3426. // Modifies:
  3427. //
  3428. // Derivation: IOleLink
  3429. //
  3430. // Algorithm: If UPDATE_ALWAYS, then update the caches, otherwise
  3431. // call OnStop (via EndUpdates)
  3432. //
  3433. // History: dd-mmm-yy Author Comment
  3434. // 21-Nov-94 alexgo memory optimization
  3435. // 03-Aug-94 alexgo stabilized and handle zombie case
  3436. // 19-Nov-93 alexgo 32bit port
  3437. //
  3438. // Notes:
  3439. //
  3440. //--------------------------------------------------------------------------
  3441. STDMETHODIMP CDefLink::SetUpdateOptions(DWORD dwUpdateOpt)
  3442. {
  3443. HRESULT hresult;
  3444. VDATEHEAP();
  3445. VDATETHREAD(this);
  3446. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::SetUpdateOptions "
  3447. "( %lx )\n", this, dwUpdateOpt));
  3448. CRefStabilize stabilize(this);
  3449. if( IsZombie() )
  3450. {
  3451. hresult = CO_E_RELEASED;
  3452. goto errRtn;
  3453. }
  3454. switch (dwUpdateOpt)
  3455. {
  3456. case OLEUPDATE_ALWAYS:
  3457. // make sure we are connected if running
  3458. BindIfRunning();
  3459. // if we've already are in UPDATE_ALWAYS mode,
  3460. // we don't need to reenter
  3461. if (m_pUnkDelegate &&
  3462. m_dwUpdateOpt != OLEUPDATE_ALWAYS)
  3463. {
  3464. BeginUpdates();
  3465. }
  3466. break;
  3467. case OLEUPDATE_ONCALL:
  3468. // if we aren't already in UPDATE_ONCALL mode, then
  3469. // enter it.
  3470. if (m_dwUpdateOpt != OLEUPDATE_ONCALL)
  3471. {
  3472. // inform cache that we are not running
  3473. // (even if not running)
  3474. EndUpdates();
  3475. }
  3476. break;
  3477. default:
  3478. hresult = E_INVALIDARG;
  3479. goto errRtn;
  3480. }
  3481. m_dwUpdateOpt = dwUpdateOpt;
  3482. m_flags |= DL_DIRTY_LINK;
  3483. hresult = NOERROR;
  3484. errRtn:
  3485. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::SetUpdateOptions "
  3486. "( %lx )\n", this, hresult));
  3487. return hresult;
  3488. }
  3489. //+-------------------------------------------------------------------------
  3490. //
  3491. // Member: CDefLink::GetUpdateOptions
  3492. //
  3493. // Synopsis: Retrieves the current update mode for the link
  3494. //
  3495. // Effects:
  3496. //
  3497. // Arguments: [pdwUpdateOpt] -- wehre to put the update options
  3498. //
  3499. // Requires:
  3500. //
  3501. // Returns: HRESULT
  3502. //
  3503. // Signals:
  3504. //
  3505. // Modifies:
  3506. //
  3507. // Derivation: IOleLink
  3508. //
  3509. // Algorithm:
  3510. //
  3511. // History: dd-mmm-yy Author Comment
  3512. // 21-Nov-94 alexgo memory optimization
  3513. // 19-Nov-93 alexgo 32bit port
  3514. //
  3515. // Notes:
  3516. //
  3517. //--------------------------------------------------------------------------
  3518. STDMETHODIMP CDefLink::GetUpdateOptions(LPDWORD pdwUpdateOpt)
  3519. {
  3520. VDATEHEAP();
  3521. VDATETHREAD(this);
  3522. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::GetUpdateOptions "
  3523. "( %p )\n", this, pdwUpdateOpt));
  3524. *pdwUpdateOpt = m_dwUpdateOpt;
  3525. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::GetUpdateOptions "
  3526. "( %lx ) [ %lx ]\n", this, NOERROR, *pdwUpdateOpt));
  3527. return NOERROR;
  3528. }
  3529. //+-------------------------------------------------------------------------
  3530. //
  3531. // Member: CDefLink::SetSourceMoniker
  3532. //
  3533. // Synopsis: Sets the link source moniker
  3534. //
  3535. // Effects:
  3536. //
  3537. // Arguments: [pmk] -- moniker to the new source (NULL used
  3538. // for CancelLink operations)
  3539. // [rclsid] -- the clsid of the source
  3540. //
  3541. // Requires:
  3542. //
  3543. // Returns: HRESULT
  3544. //
  3545. // Signals:
  3546. //
  3547. // Modifies:
  3548. //
  3549. // Derivation: IOleLink
  3550. //
  3551. // Algorithm: Stores the new absolute moniker and creates a new relative
  3552. // moniker from the absolute moniker
  3553. //
  3554. // History: dd-mmm-yy Author Comment
  3555. // 09-Jan-95 alexgo added call to SetUpdateTimes to keep
  3556. // internal state consistent
  3557. // 21-Nov-94 alexgo memory optimization
  3558. /// 03-Aug-94 alexgo stabilized and handle zombie case
  3559. // 19-Nov-93 alexgo 32bit port
  3560. //
  3561. // Notes:
  3562. //
  3563. //--------------------------------------------------------------------------
  3564. STDMETHODIMP CDefLink::SetSourceMoniker( LPMONIKER pmk, REFCLSID clsid )
  3565. {
  3566. HRESULT hresult = NOERROR;
  3567. VDATEHEAP();
  3568. VDATETHREAD(this);
  3569. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::SetSourceMoniker "
  3570. "( %p , %p )\n", this, pmk, clsid));
  3571. CRefStabilize stabilize(this);
  3572. if( IsZombie() )
  3573. {
  3574. hresult = CO_E_RELEASED;
  3575. goto errRtn;
  3576. }
  3577. if (pmk)
  3578. {
  3579. VDATEIFACE(pmk);
  3580. }
  3581. UnbindSource();
  3582. // REVIEW: the following code appears in several places and should
  3583. // be put in a separate routine:
  3584. // SetBothMk(pmkSrcAbs, <calculated from abs>,
  3585. // TRUE/*fBind*/);
  3586. if (m_pMonikerAbs)
  3587. {
  3588. m_pMonikerAbs->Release();
  3589. }
  3590. if ((m_pMonikerAbs = pmk) != NULL)
  3591. {
  3592. pmk->AddRef();
  3593. //
  3594. // TRACKLINK
  3595. //
  3596. // -- use ITrackingMoniker to convert file moniker to
  3597. // be tracking.
  3598. //
  3599. #ifdef _TRACKLINK_
  3600. EnableTracking(pmk, OT_READTRACKINGINFO);
  3601. #endif
  3602. }
  3603. UpdateRelMkFromAbsMk(NULL);
  3604. // to prevent error in BindToSource when clsid is different; i.e., we
  3605. // shouldn't fail to connect (or require OLELINKBIND_EVENIFCLASSDIFF)
  3606. // when the moniker is changed; i.e., we expect the class to change
  3607. // so don't bother the programmer.
  3608. m_clsid = CLSID_NULL;
  3609. if (BindIfRunning() != NOERROR)
  3610. {
  3611. // server not running -> use clsid given (even if CLSID_NULL
  3612. // and even
  3613. // if no moniker)
  3614. m_clsid = clsid;
  3615. }
  3616. errRtn:
  3617. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::SetSourceMoniker "
  3618. "( %lx )\n", this, hresult ));
  3619. return hresult;
  3620. }
  3621. //+-------------------------------------------------------------------------
  3622. //
  3623. // Member: CDefLink::GetSourceMoniker
  3624. //
  3625. // Synopsis: Gets the moniker to the source
  3626. //
  3627. // Effects:
  3628. //
  3629. // Arguments: [ppmk] -- where to put the moniker
  3630. //
  3631. // Requires:
  3632. //
  3633. // Returns: HRESULT
  3634. //
  3635. // Signals:
  3636. //
  3637. // Modifies:
  3638. //
  3639. // Derivation: IOleLink
  3640. //
  3641. // Algorithm: We first try to build a new absolute moniker from the
  3642. // relative one, if that fails then we return the currently
  3643. // stored absolute moniker.
  3644. //
  3645. // History: dd-mmm-yy Author Comment
  3646. // 21-Nov-94 alexgo memory optimization
  3647. // 03-Aug-94 alexgo stabilized
  3648. // 19-Nov-93 alexgo 32bit port
  3649. //
  3650. // Notes:
  3651. //
  3652. //--------------------------------------------------------------------------
  3653. STDMETHODIMP CDefLink::GetSourceMoniker(LPMONIKER *ppmk)
  3654. {
  3655. LPMONIKER pmkAbs = NULL;
  3656. // the absolute moniker constructed from the rel
  3657. HRESULT hresult = NOERROR;
  3658. VDATEHEAP();
  3659. VDATETHREAD(this);
  3660. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::GetSourceMoniker "
  3661. "( %p )\n", this, ppmk));
  3662. CRefStabilize stabilize(this);
  3663. GetAbsMkFromRel(&pmkAbs, NULL);
  3664. if (pmkAbs)
  3665. {
  3666. *ppmk = pmkAbs; // no addref
  3667. }
  3668. else if (*ppmk = m_pMonikerAbs)
  3669. {
  3670. // we've been asked to give the pointer so we should AddRef()
  3671. m_pMonikerAbs->AddRef();
  3672. }
  3673. else
  3674. {
  3675. hresult = MK_E_UNAVAILABLE;
  3676. }
  3677. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::GetSourceMoniker "
  3678. "( %lx ) [ %p ]\n", this, hresult, *ppmk));
  3679. return hresult;
  3680. }
  3681. //+-------------------------------------------------------------------------
  3682. //
  3683. // Member: CDefLink::SetSourceDisplayName
  3684. //
  3685. // Synopsis: Creates a moniker from the display name and calls
  3686. // SetSourceMoniker, thus setting the moniker to the source
  3687. //
  3688. // Effects:
  3689. //
  3690. // Arguments: [lpszStatusText] -- the display name
  3691. //
  3692. // Requires:
  3693. //
  3694. // Returns: HRESULT
  3695. //
  3696. // Signals:
  3697. //
  3698. // Modifies:
  3699. //
  3700. // Derivation: IOleLink
  3701. //
  3702. // Algorithm:
  3703. //
  3704. // History: dd-mmm-yy Author Comment
  3705. // 21-Nov-94 alexgo memory optimization
  3706. // 03-Aug-94 alexgo stabilized and handle the zombie case
  3707. // 19-Nov-93 alexgo 32bit port
  3708. //
  3709. // Notes:
  3710. //
  3711. //--------------------------------------------------------------------------
  3712. STDMETHODIMP CDefLink::SetSourceDisplayName(
  3713. LPCOLESTR lpszStatusText)
  3714. {
  3715. HRESULT error;
  3716. IBindCtx FAR* pbc;
  3717. ULONG cchEaten;
  3718. IMoniker FAR* pmk;
  3719. VDATEHEAP();
  3720. VDATETHREAD(this);
  3721. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::SetSourceDisplay"
  3722. "Name ( %p )\n", this, lpszStatusText));
  3723. CRefStabilize stabilize(this);
  3724. if( IsZombie() )
  3725. {
  3726. error = CO_E_RELEASED;
  3727. goto errRtn;
  3728. }
  3729. if (error = CreateBindCtx(0,&pbc))
  3730. {
  3731. goto errRtn;
  3732. }
  3733. error = MkParseDisplayName(pbc, (LPOLESTR)lpszStatusText, &cchEaten,
  3734. &pmk);
  3735. // In Daytona, we release the hidden server
  3736. // must release this now so the (possibly) hidden server goes away.
  3737. Verify(pbc->Release() == 0);
  3738. if (error != NOERROR)
  3739. {
  3740. goto errRtn;
  3741. }
  3742. error = SetSourceMoniker(pmk, CLSID_NULL);
  3743. pmk->Release();
  3744. // NOTE: we don't bind to the link source now since that would leave
  3745. // the server running, but hidden. If the caller want to not start
  3746. // the server twice it should parse the moniker itself, call
  3747. // SetSourceMoniker and then BindToSource with the bind context of
  3748. // the parse.
  3749. errRtn:
  3750. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::SetSourceDisplay"
  3751. "Name ( %lx )\n", this, error ));
  3752. return error;
  3753. }
  3754. //+-------------------------------------------------------------------------
  3755. //
  3756. // Member: CDefLink::GetSourceDisplayName
  3757. //
  3758. // Synopsis: Retrieves the source display name (such as that set with
  3759. // SetSourceDisplayName)
  3760. //
  3761. // Effects:
  3762. //
  3763. // Arguments: [lplpszDisplayName] -- where to put a pointer to the
  3764. // display name
  3765. //
  3766. // Requires:
  3767. //
  3768. // Returns: HRESULT
  3769. //
  3770. // Signals:
  3771. //
  3772. // Modifies:
  3773. //
  3774. // Derivation: IOleLink
  3775. //
  3776. // Algorithm: Gets the absolute moniker and asks it for the display name
  3777. //
  3778. // History: dd-mmm-yy Author Comment
  3779. // 21-Nov-94 alexgo memory optimization
  3780. // 03-Aug-94 alexgo stabilized
  3781. // 19-Nov-93 alexgo 32bit port
  3782. //
  3783. // Notes:
  3784. //
  3785. //--------------------------------------------------------------------------
  3786. STDMETHODIMP CDefLink::GetSourceDisplayName( LPOLESTR *lplpszDisplayName )
  3787. {
  3788. HRESULT hresult;
  3789. IBindCtx FAR* pbc;
  3790. LPMONIKER pmk = NULL;
  3791. VDATEHEAP();
  3792. VDATETHREAD(this);
  3793. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::GetSourceDisplay"
  3794. "Name ( %p )\n", this, lplpszDisplayName));
  3795. CRefStabilize stabilize(this);
  3796. *lplpszDisplayName = NULL;
  3797. GetSourceMoniker(&pmk);
  3798. if (pmk == NULL)
  3799. {
  3800. hresult = E_FAIL;
  3801. goto errRtn;
  3802. }
  3803. if (hresult = CreateBindCtx(0,&pbc))
  3804. {
  3805. goto errRtn;
  3806. }
  3807. hresult = pmk->GetDisplayName(pbc, NULL,lplpszDisplayName);
  3808. AssertOutPtrParam(hresult, *lplpszDisplayName);
  3809. Verify(pbc->Release() == 0);
  3810. errRtn:
  3811. if (pmk)
  3812. {
  3813. pmk->Release();
  3814. }
  3815. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::GetSourceDisplay"
  3816. "Name ( %lx ) [ %p ]\n", this, hresult,
  3817. *lplpszDisplayName));
  3818. return hresult;
  3819. }
  3820. //+-------------------------------------------------------------------------
  3821. //
  3822. // Member: CDefLink::BindToSource
  3823. //
  3824. // Synopsis: Binds to the link source
  3825. //
  3826. // Effects:
  3827. //
  3828. // Arguments: [bindflags] -- controls the binding (such as binding
  3829. // even if the class ID is different)
  3830. // [pbc] -- the bind context
  3831. //
  3832. // Requires:
  3833. //
  3834. // Returns: HRESULT
  3835. //
  3836. // Signals:
  3837. //
  3838. // Modifies:
  3839. //
  3840. // Derivation: IOleLink
  3841. //
  3842. // Algorithm: First try binding with the relative moniker, failing that
  3843. // then try the absolute moniker. Once bound, we set up
  3844. // the advises and cache.
  3845. //
  3846. // History: dd-mmm-yy Author Comment
  3847. // 21-Nov-94 alexgo memory optimization
  3848. // 03-Aug-94 alexgo stabilize and check for zombie case
  3849. // 03-Feb-94 alexgo check for NULL before SendOnLinkSrcChange
  3850. // 11-Jan-94 alexgo cast -1's to DWORD to fix compile
  3851. // warning
  3852. // 19-Nov-93 alexgo 32bit port
  3853. //
  3854. // Notes:
  3855. //
  3856. //--------------------------------------------------------------------------
  3857. STDMETHODIMP CDefLink::BindToSource(DWORD bindflags, LPBINDCTX pbc)
  3858. {
  3859. HRESULT error = S_OK;
  3860. IOleObject FAR* pOleDelegate;
  3861. IDataObject FAR* pDataDelegate;
  3862. IBindCtx FAR* pBcUse;
  3863. CLSID clsid;
  3864. LPMONIKER pmkAbs = NULL;
  3865. LPMONIKER pmkHold = NULL;
  3866. LPRUNNABLEOBJECT pRODelegate;
  3867. LPOLEITEMCONTAINER pOleCont;
  3868. BOOL fLockedContainer;
  3869. VDATEHEAP();
  3870. VDATETHREAD(this);
  3871. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::BindToSource "
  3872. "( %lx , %p )\n", this, bindflags, pbc));
  3873. CRefStabilize stabilize(this);
  3874. // if we're zombied (e.g. in the middle of our destructor), we
  3875. // don't really want to bind the source again ;-)
  3876. if( IsZombie() )
  3877. {
  3878. error = CO_E_RELEASED;
  3879. goto logRtn;
  3880. }
  3881. // if we're running, then we're already bound
  3882. if (IsReallyRunning())
  3883. {
  3884. error = NOERROR;
  3885. goto logRtn;
  3886. }
  3887. // nobody to bind to
  3888. if (m_pMonikerAbs == NULL)
  3889. {
  3890. error = E_UNSPEC;
  3891. goto logRtn;
  3892. }
  3893. if ((pBcUse = pbc) == NULL && (error = CreateBindCtx(0,&pBcUse))
  3894. != NOERROR)
  3895. {
  3896. goto errRtn;
  3897. }
  3898. {
  3899. //
  3900. // Rewritten BillMo 30 Jan 1995.
  3901. //
  3902. // Enumeration which is used to keep track of what stage of resolution
  3903. // we were successful in.
  3904. //
  3905. enum
  3906. {
  3907. None, Relative, Ids, Absolute
  3908. } ResolveSuccess = { None };
  3909. if (m_pMonikerRel != NULL)
  3910. {
  3911. error = GetAbsMkFromRel(&pmkAbs, NULL);
  3912. if (error == NOERROR)
  3913. {
  3914. error = pmkAbs->BindToObject(pBcUse,
  3915. NULL,
  3916. IID_IUnknown,
  3917. (LPVOID FAR *) &m_pUnkDelegate);
  3918. if (error == NOERROR)
  3919. {
  3920. ResolveSuccess = Relative;
  3921. }
  3922. else
  3923. {
  3924. pmkAbs->Release();
  3925. pmkAbs = NULL;
  3926. }
  3927. }
  3928. }
  3929. if (ResolveSuccess == None && error != RPC_E_CALL_REJECTED)
  3930. {
  3931. error = m_pMonikerAbs->BindToObject(pBcUse,
  3932. NULL,
  3933. IID_IUnknown,
  3934. (LPVOID FAR *)&m_pUnkDelegate);
  3935. if (error == NOERROR)
  3936. {
  3937. ResolveSuccess = Absolute;
  3938. (pmkAbs = m_pMonikerAbs)->AddRef();
  3939. }
  3940. }
  3941. #ifdef _TRACKLINK_
  3942. if (ResolveSuccess == None && error != RPC_E_CALL_REJECTED)
  3943. {
  3944. HRESULT error2;
  3945. Assert(pmkAbs == NULL);
  3946. EnableTracking(m_pMonikerAbs, OT_ENABLEREDUCE);
  3947. error2 = m_pMonikerAbs->Reduce(pBcUse,
  3948. MKRREDUCE_ALL,
  3949. NULL,
  3950. &pmkAbs);
  3951. EnableTracking(m_pMonikerAbs, OT_DISABLEREDUCE);
  3952. if (error2 == NOERROR)
  3953. {
  3954. if (pmkAbs != NULL)
  3955. {
  3956. error2 = pmkAbs->BindToObject(pBcUse,
  3957. NULL,
  3958. IID_IUnknown,
  3959. (LPVOID FAR *)&m_pUnkDelegate);
  3960. if (error2 == NOERROR)
  3961. {
  3962. ResolveSuccess = Ids;
  3963. error = NOERROR;
  3964. }
  3965. else
  3966. {
  3967. pmkAbs->Release();
  3968. pmkAbs=NULL;
  3969. }
  3970. }
  3971. // else error contains error from m_pMonikerAbs->BindToObject
  3972. }
  3973. else
  3974. if (error2 == MK_S_REDUCED_TO_SELF)
  3975. {
  3976. if (pmkAbs != NULL)
  3977. {
  3978. pmkAbs->Release();
  3979. pmkAbs=NULL;
  3980. }
  3981. }
  3982. // else error contains error from m_pMonikerAbs->BindToObject
  3983. }
  3984. #endif
  3985. //
  3986. // Update the link state
  3987. //
  3988. if (ResolveSuccess == None)
  3989. goto errRtn;
  3990. // Update the absolute moniker and send OnLinkSrcChange
  3991. // (may update relative if this was an Ids resolve)
  3992. if (ResolveSuccess == Relative || ResolveSuccess == Ids)
  3993. {
  3994. // binding succeeded with relative moniker or ids
  3995. // Update the absolute one.
  3996. // hold on to old absolute one
  3997. pmkHold = m_pMonikerAbs;
  3998. if (pmkHold)
  3999. {
  4000. pmkHold->AddRef();
  4001. }
  4002. if (m_pMonikerAbs)
  4003. {
  4004. m_pMonikerAbs->Release();
  4005. m_pMonikerAbs = NULL;
  4006. }
  4007. if (ResolveSuccess == Relative)
  4008. {
  4009. GetAbsMkFromRel(&m_pMonikerAbs, NULL);
  4010. }
  4011. else
  4012. {
  4013. // Ids
  4014. m_pMonikerAbs = pmkAbs;
  4015. pmkAbs = NULL;
  4016. UpdateRelMkFromAbsMk(NULL);
  4017. }
  4018. //
  4019. // test to see if we had no abs moniker before OR the
  4020. // one we had is different to the new one.
  4021. //
  4022. if (pmkHold == NULL ||
  4023. pmkHold->IsEqual(m_pMonikerAbs)
  4024. != NOERROR )
  4025. {
  4026. m_flags |= DL_DIRTY_LINK;
  4027. // send change notification if the advise
  4028. // holder present.
  4029. if( m_pCOAHolder)
  4030. {
  4031. m_pCOAHolder->SendOnLinkSrcChange(
  4032. m_pMonikerAbs);
  4033. }
  4034. }
  4035. // have new absolute moniker; dirty
  4036. if (pmkHold)
  4037. {
  4038. pmkHold->Release();
  4039. }
  4040. }
  4041. // Update the relative
  4042. if (ResolveSuccess == Absolute)
  4043. {
  4044. UpdateRelMkFromAbsMk(NULL);
  4045. }
  4046. }
  4047. #ifdef _TRACKLINK_
  4048. EnableTracking(m_pMonikerAbs, OT_READTRACKINGINFO);
  4049. if (m_pMonikerAbs->IsDirty())
  4050. m_flags |= DL_DIRTY_LINK;
  4051. #endif
  4052. // NOTE: don't need to update the relative moniker when there isn't
  4053. // one because we will do that at save time.
  4054. // Successfully bound, Lock the Object.
  4055. if ((pRODelegate = GetRODelegate()) != NULL)
  4056. {
  4057. // lock so invisible link source does not goes away.
  4058. Assert(0 == (m_flags & DL_LOCKED_RUNNABLEOBJECT));
  4059. if (NOERROR == pRODelegate->LockRunning(TRUE, FALSE))
  4060. {
  4061. m_flags |= DL_LOCKED_RUNNABLEOBJECT;
  4062. }
  4063. }
  4064. else if( (pOleCont = GetOleItemContainerDelegate()) != NULL)
  4065. {
  4066. // have container in same process or handler which doesn't
  4067. // support IRunnableObject.
  4068. Assert(0 == (m_flags & DL_LOCKED_OLEITEMCONTAINER));
  4069. if (NOERROR == pOleCont->LockContainer(TRUE))
  4070. {
  4071. m_flags |= DL_LOCKED_OLEITEMCONTAINER;
  4072. }
  4073. }
  4074. // Lock the container
  4075. fLockedContainer = m_flags & DL_LOCKED_CONTAINER;
  4076. DuLockContainer(m_pAppClientSite, TRUE, &fLockedContainer );
  4077. if(fLockedContainer)
  4078. {
  4079. m_flags |= DL_LOCKED_CONTAINER;
  4080. }
  4081. else
  4082. {
  4083. m_flags &= ~DL_LOCKED_CONTAINER;
  4084. }
  4085. // By this point, we have successfully bound to the server. Now
  4086. // we take care of misc administrative tasks.
  4087. Assert(m_pUnkDelegate != NULL &&
  4088. "CDefLink::BindToSource expected valid m_pUnkDelegate");
  4089. // get class of link source; use NULL if it doesn't support IOleObject
  4090. // or IOleObject::GetUserClassID returns an error.
  4091. if ((pOleDelegate = GetOleDelegate()) == NULL ||
  4092. pOleDelegate->GetUserClassID(&clsid) != NOERROR)
  4093. {
  4094. clsid = CLSID_NULL;
  4095. }
  4096. // if different and no flag, release and return error.
  4097. if ( IsEqualCLSID(m_clsid,CLSID_NULL))
  4098. {
  4099. // m_clsid now NULL; link becomes dirty
  4100. m_flags |= DL_DIRTY_LINK;
  4101. }
  4102. else if ( !IsEqualCLSID(clsid, m_clsid) )
  4103. {
  4104. if ((bindflags & OLELINKBIND_EVENIFCLASSDIFF) == 0)
  4105. {
  4106. CLSID TreatAsCLSID;
  4107. // Initialize error
  4108. error = OLE_E_CLASSDIFF;
  4109. // Check for TreatAs case
  4110. if(CoGetTreatAsClass(m_clsid, &TreatAsCLSID) == S_OK) {
  4111. // Check if the server clsid is same as TreatAs clsid
  4112. if(IsEqualCLSID(clsid, TreatAsCLSID))
  4113. error = NOERROR;
  4114. }
  4115. if(error == OLE_E_CLASSDIFF)
  4116. goto errRtn;
  4117. }
  4118. // clsid's do no match; link becomes dirty
  4119. m_flags |= DL_DIRTY_LINK;
  4120. }
  4121. // use new class (even if null); dirty flag set above
  4122. m_clsid = clsid;
  4123. // it is possible that a re-entrant call unbound our source
  4124. // thus making pOleDelegate invalid (since it's a local on
  4125. // the stack
  4126. LEWARN(pOleDelegate != m_pOleDelegate,
  4127. "Unbind during IOL::BindToSource");
  4128. // we fetched m_pOleDelegate in the call to GetOleDelegate above.
  4129. if( m_pOleDelegate != NULL)
  4130. {
  4131. // set single ole advise (we multiplex)
  4132. if ((error = m_pOleDelegate->Advise(
  4133. &m_AdviseSink,
  4134. &m_dwConnOle)) != NOERROR)
  4135. {
  4136. goto errRtn;
  4137. }
  4138. }
  4139. // Set up advise connections for data changes
  4140. if( pDataDelegate = GetDataDelegate() )
  4141. {
  4142. // setup wild card advise to get time change
  4143. FORMATETC fetc;
  4144. fetc.cfFormat = NULL;
  4145. fetc.ptd = NULL;
  4146. fetc.dwAspect = (DWORD)-1L;
  4147. fetc.lindex = -1;
  4148. fetc.tymed = (DWORD)-1L;
  4149. if ((error = pDataDelegate->DAdvise(&fetc, ADVF_NODATA,
  4150. &m_AdviseSink,
  4151. &m_dwConnTime)) != NOERROR)
  4152. {
  4153. LEDebugOut((DEB_WARN, "WARNING: server does not "
  4154. "support wild card advises\n"));
  4155. goto errRtn;
  4156. }
  4157. // it is possible that a re-entrant call unbound our
  4158. // link server, so we need to fetch the data object
  4159. // pointer again
  4160. LEWARN(pDataDelegate != m_pDataDelegate,
  4161. "Unbind during IOL::BindToSource");
  4162. // this will set up data advise connections with
  4163. // everybody in our data advise holder
  4164. // (see dacache.cpp)
  4165. error = m_pDataAdvCache->EnumAndAdvise(
  4166. m_pDataDelegate, TRUE);
  4167. if( error != NOERROR )
  4168. {
  4169. goto errRtn;
  4170. }
  4171. }
  4172. if (m_dwUpdateOpt == OLEUPDATE_ALWAYS)
  4173. {
  4174. // we inform the cache that we are running only if auto
  4175. // update; otherwise, we are a manual link and will call
  4176. // Update directly (which doesn't require OnRun to be called).
  4177. BeginUpdates();
  4178. }
  4179. // Our m_pUnkDelegate may have been released by an
  4180. // OnClose advise that came in while we were setting up Advise
  4181. // sinks.
  4182. if (NULL == m_pUnkDelegate)
  4183. {
  4184. LEDebugOut((DEB_WARN,
  4185. "CDefLink::BindToSource - "
  4186. "m_pUnkDelegate was released "
  4187. "(probably due to OnClose)"));
  4188. error = MK_E_NOOBJECT;
  4189. }
  4190. errRtn:
  4191. // free used resources
  4192. if (pmkAbs)
  4193. {
  4194. pmkAbs->Release();
  4195. }
  4196. if (error == NOERROR) {
  4197. m_ContentSRVMSBits = 0;
  4198. m_ContentSRVMSHResult = 0xFFFFFFFF;
  4199. }
  4200. else {
  4201. UnbindSource(); // ClientSite will be unlocked in UnBindSource
  4202. }
  4203. if (pbc == NULL && pBcUse != NULL)
  4204. {
  4205. // created bind ctx locally
  4206. Verify(pBcUse->Release() == 0);
  4207. }
  4208. #if DBG == 1
  4209. if( m_pUnkDelegate )
  4210. {
  4211. Assert(error == NOERROR );
  4212. }
  4213. else
  4214. {
  4215. Assert(error != NOERROR );
  4216. }
  4217. #endif
  4218. AssertOutPtrIface(error, m_pUnkDelegate);
  4219. logRtn:
  4220. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::BindToSource "
  4221. "( %lx )\n", this, error ));
  4222. return error;
  4223. }
  4224. //+-------------------------------------------------------------------------
  4225. //
  4226. // Member: CDefLink::BindIfRunning
  4227. //
  4228. // Synopsis: Binds to the source server only if it is currently running
  4229. //
  4230. // Effects:
  4231. //
  4232. // Arguments: void
  4233. //
  4234. // Requires:
  4235. //
  4236. // Returns: HRESULT (NOERROR if connected)
  4237. //
  4238. // Signals:
  4239. //
  4240. // Modifies:
  4241. //
  4242. // Derivation: IOleLink
  4243. //
  4244. // Algorithm: Gets a good moniker to the source (first tries relative,
  4245. // then tries absolute), ask it if the server is running, if
  4246. // yes, then bind to it.
  4247. //
  4248. // History: dd-mmm-yy Author Comment
  4249. // 21-Nov-94 alexgo memory optimization
  4250. // 03-Aug-94 alexgo stabilize and handle the zombie case
  4251. // 19-Nov-93 alexgo 32bit port
  4252. //
  4253. // Notes: We may return NOERROR (connected) even if the server has
  4254. // crashed unexpectedly
  4255. //
  4256. //--------------------------------------------------------------------------
  4257. STDMETHODIMP CDefLink::BindIfRunning(void)
  4258. {
  4259. HRESULT error;
  4260. LPBC pbc;
  4261. LPMONIKER pmkAbs = NULL;
  4262. VDATEHEAP();
  4263. VDATETHREAD(this);
  4264. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::BindIfRunning "
  4265. "( )\n", this ));
  4266. CRefStabilize stabilize(this);
  4267. // if we're zombied (e.g. in our destructor), then we don't want
  4268. // to bind to the server!
  4269. if( IsZombie() )
  4270. {
  4271. error = CO_E_RELEASED;
  4272. goto errRtn;
  4273. }
  4274. if (IsReallyRunning())
  4275. {
  4276. error = NOERROR;
  4277. goto errRtn;
  4278. }
  4279. // try getting an absolute moniker from the relative moniker first
  4280. if (GetAbsMkFromRel(&pmkAbs, NULL) != NOERROR)
  4281. {
  4282. // can't get relative moniker; use abs if available
  4283. if ((pmkAbs = m_pMonikerAbs) == NULL)
  4284. {
  4285. error = E_FAIL;
  4286. goto errRtn;
  4287. }
  4288. pmkAbs->AddRef();
  4289. }
  4290. // NOTE: we used to try both monikers, but this caused problems if
  4291. // both would bind and the absolute one was running: we would bind
  4292. // to the wrong one or force the relative one to be running. Now,
  4293. // if we have a relative moniker, we try that one only; if we only
  4294. // have an absolute moniker, we try that one; otherwise we fail.
  4295. error = CreateBindCtx( 0, &pbc );
  4296. if (error != NOERROR)
  4297. {
  4298. goto errRtn;
  4299. }
  4300. if ((error = pmkAbs->IsRunning(pbc, NULL, NULL)) == NOERROR)
  4301. {
  4302. // abs is running, but rel is not; force BindToSource to use
  4303. // the absolute moniker
  4304. error = BindToSource(0, pbc);
  4305. }
  4306. // else return last error (from pmkAbs->IsRunning)
  4307. pbc->Release();
  4308. errRtn:
  4309. if (pmkAbs)
  4310. {
  4311. pmkAbs->Release();
  4312. }
  4313. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::BindIfRunning "
  4314. "( %lx )\n", this, error ));
  4315. return error;
  4316. }
  4317. //+-------------------------------------------------------------------------
  4318. //
  4319. // Member: CDefLink::GetBoundSource
  4320. //
  4321. // Synopsis: Returns a pointer to the server delegate
  4322. //
  4323. // Effects:
  4324. //
  4325. // Arguments: [ppUnk] -- where to put the pointer to the server
  4326. //
  4327. // Requires:
  4328. //
  4329. // Returns: HRESULT
  4330. //
  4331. // Signals:
  4332. //
  4333. // Modifies:
  4334. //
  4335. // Derivation: IOleLink
  4336. //
  4337. // Algorithm:
  4338. //
  4339. // History: dd-mmm-yy Author Comment
  4340. // 21-Nov-94 alexgo memory optimization
  4341. // 03-Aug-94 alexgo stabilized
  4342. // 19-Nov-93 alexgo 32bit port
  4343. //
  4344. // Notes:
  4345. //
  4346. //--------------------------------------------------------------------------
  4347. STDMETHODIMP CDefLink::GetBoundSource(LPUNKNOWN *ppUnk)
  4348. {
  4349. HRESULT hresult;
  4350. VDATEHEAP();
  4351. VDATETHREAD(this);
  4352. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::GetBoundSource "
  4353. "( %p )\n", this, ppUnk));
  4354. CRefStabilize stabilize(this);
  4355. if (!IsReallyRunning())
  4356. {
  4357. *ppUnk = NULL;
  4358. hresult = E_FAIL;
  4359. }
  4360. else
  4361. {
  4362. (*ppUnk = m_pUnkDelegate)->AddRef();
  4363. hresult = NOERROR;
  4364. }
  4365. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::GetBoundSource "
  4366. "( %lx ) [ %p ]\n", this, hresult, *ppUnk));
  4367. return hresult;
  4368. }
  4369. //+-------------------------------------------------------------------------
  4370. //
  4371. // Member: CDefLink::UnbindSource
  4372. //
  4373. // Synopsis: Unbinds the connection to the link source server
  4374. //
  4375. // Effects:
  4376. //
  4377. // Arguments: void
  4378. //
  4379. // Requires:
  4380. //
  4381. // Returns: HRESULT
  4382. //
  4383. // Signals:
  4384. //
  4385. // Modifies:
  4386. //
  4387. // Derivation: IOleLink
  4388. //
  4389. // Algorithm: First unadvise all advise connections and then tickle
  4390. // the container by lock/unlocking (to handle the silent
  4391. // update case). Finally, we release all pointers to the
  4392. // server. If we were the only folks connected, the server
  4393. // will go away
  4394. //
  4395. // History: dd-mmm-yy Author Comment
  4396. // 21-Nov-94 alexgo memory optimization
  4397. // 03-Aug-94 alexgo stabilized
  4398. // 19-Nov-93 alexgo 32bit port
  4399. //
  4400. // Notes:
  4401. //
  4402. //--------------------------------------------------------------------------
  4403. STDMETHODIMP CDefLink::UnbindSource(void)
  4404. {
  4405. LPDATAOBJECT pDataDelegate;
  4406. LPOLEOBJECT pOleDelegate;
  4407. LPRUNNABLEOBJECT pRODelegate;
  4408. LPOLEITEMCONTAINER pOleCont;
  4409. HRESULT hresult = NOERROR;
  4410. IUnknown * pUnkDelegate;
  4411. BOOL fLockedContainer;
  4412. VDATEHEAP();
  4413. VDATETHREAD(this);
  4414. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::UnbindSource "
  4415. "( )\n", this ));
  4416. CRefStabilize stabilize(this);
  4417. if (!m_pUnkDelegate)
  4418. {
  4419. // hresult == NOERROR
  4420. goto errRtn;
  4421. }
  4422. // unadvise so if delegate stays around, we get the correct results
  4423. if ((pOleDelegate = GetOleDelegate()) != NULL &&
  4424. m_dwConnOle != 0)
  4425. {
  4426. pOleDelegate->Unadvise(m_dwConnOle);
  4427. m_dwConnOle = 0;
  4428. }
  4429. if( pDataDelegate = GetDataDelegate() )
  4430. {
  4431. if (m_dwConnTime)
  4432. {
  4433. pDataDelegate->DUnadvise(m_dwConnTime);
  4434. m_dwConnTime = 0;
  4435. }
  4436. // we can actually be re-entered here, so refetch the
  4437. // IDO pointer from the server (if it's still around)
  4438. LEWARN(pDataDelegate != m_pDataDelegate,
  4439. "Unbind called within IOL::UnbindSource!");
  4440. // pDataDelegate should still be good, since we still have
  4441. // an AddRef on it. Go through and do the unadvises again
  4442. // anyway.
  4443. // this will unadvise everybody registered in the data
  4444. // advise holder
  4445. m_pDataAdvCache->EnumAndAdvise(
  4446. pDataDelegate, FALSE);
  4447. }
  4448. // inform cache that we are not running (even if OnRun was not called)
  4449. EndUpdates();
  4450. if ( (m_flags & DL_LOCKED_RUNNABLEOBJECT) &&
  4451. ((pRODelegate = GetRODelegate()) != NULL) )
  4452. {
  4453. // unlock so invisible link source goes away.
  4454. // do it just before release delegates so above unadvises go
  4455. m_flags &= ~DL_LOCKED_RUNNABLEOBJECT;
  4456. pRODelegate->LockRunning(FALSE, TRUE);
  4457. }
  4458. if( (m_flags & DL_LOCKED_OLEITEMCONTAINER) &&
  4459. ((pOleCont = GetOleItemContainerDelegate()) != NULL) )
  4460. {
  4461. // have container in same process or handler
  4462. // Unlock to shutdown.
  4463. m_flags &= ~DL_LOCKED_OLEITEMCONTAINER;
  4464. pOleCont->LockContainer(FALSE);
  4465. }
  4466. Assert(0 == (m_flags & (DL_LOCKED_OLEITEMCONTAINER | DL_LOCKED_RUNNABLEOBJECT)));
  4467. // release all of our pointers.
  4468. ReleaseOleDelegate();
  4469. ReleaseDataDelegate();
  4470. ReleaseRODelegate();
  4471. ReleaseOleItemContainerDelegate();
  4472. // if we are the only consumer of this data, the following will stop
  4473. // the server; set member to NULL first since release may cause this
  4474. // object to be accessed again.
  4475. pUnkDelegate = m_pUnkDelegate;
  4476. LEWARN(pUnkDelegate == NULL, "Unbind called within IOL::UnbindSource");
  4477. m_pUnkDelegate = NULL;
  4478. if( pUnkDelegate )
  4479. {
  4480. pUnkDelegate->Release();
  4481. }
  4482. // make sure unlocked if we locked it
  4483. fLockedContainer = m_flags & DL_LOCKED_CONTAINER;
  4484. m_flags &= ~DL_LOCKED_CONTAINER;
  4485. DuLockContainer(m_pAppClientSite, FALSE, &fLockedContainer);
  4486. AssertSz( hresult == NOERROR, "Bogus code modification, check error "
  4487. "paths");
  4488. errRtn:
  4489. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::UnbindSource "
  4490. "( %lx )\n", this, hresult));
  4491. return hresult;
  4492. }
  4493. //+-------------------------------------------------------------------------
  4494. //
  4495. // Member: CDefLink::Update
  4496. //
  4497. // Synopsis: Updates the link (fills cache, etc).
  4498. //
  4499. // Effects:
  4500. //
  4501. // Arguments: [pbc] -- the bind context
  4502. //
  4503. // Requires:
  4504. //
  4505. // Returns: HRESULT
  4506. //
  4507. // Signals:
  4508. //
  4509. // Modifies:
  4510. //
  4511. // Derivation: IOleLink
  4512. //
  4513. // Algorithm: Bind to the server, then update the caches
  4514. //
  4515. // History: dd-mmm-yy Author Comment
  4516. // 21-Nov-94 alexgo memory optimization
  4517. // 03-Aug-94 alexgo stabilized
  4518. // 19-Nov-93 alexgo 32bit port
  4519. //
  4520. // Notes:
  4521. // As in IOO::DoVerb, we try to "fix" crashed servers by
  4522. // staying bound to them if we rebind due to a crash. See
  4523. // the Notes in IOO::DoVerb for more info.
  4524. //
  4525. //--------------------------------------------------------------------------
  4526. STDMETHODIMP CDefLink::Update(LPBINDCTX pbc)
  4527. {
  4528. HRESULT error = NOERROR;
  4529. BOOL bStartedNow = !m_pUnkDelegate;
  4530. LPBINDCTX pBcUse;
  4531. VDATEHEAP();
  4532. VDATETHREAD(this);
  4533. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::Update ( %p )\n",
  4534. this, pbc));
  4535. CRefStabilize stabilize(this);
  4536. if (pbc)
  4537. {
  4538. pBcUse = pbc;
  4539. }
  4540. else
  4541. {
  4542. if (FAILED(error = CreateBindCtx( 0, &pBcUse )))
  4543. goto errBndCtx;
  4544. }
  4545. if (FAILED(error = BindToSource(0,pBcUse)))
  4546. {
  4547. goto errRtn;
  4548. }
  4549. // store the pUnk there to allow for
  4550. // better optimization (if we didn't, file based link sources would
  4551. // be launched multiple times since the moniker code does not put
  4552. // them in the bind ctx (and probably shouldn't)).
  4553. pBcUse->RegisterObjectBound(m_pUnkDelegate);
  4554. SetUpdateTimes(); // ignore error.
  4555. if (bStartedNow && (m_dwUpdateOpt == OLEUPDATE_ALWAYS))
  4556. {
  4557. // if this is an auto-link and we ran it now, then all the
  4558. // automatic caches would have been updated during the
  4559. // running process. So, here we have to update only the
  4560. // ADVFCACHE_ONSAVE caches.
  4561. error= m_pCOleCache->UpdateCache(
  4562. GetDataDelegate(),
  4563. UPDFCACHE_IFBLANKORONSAVECACHE, NULL);
  4564. }
  4565. else
  4566. {
  4567. // This is a manual-link or it is an auto-link then it is
  4568. // already running. In all these cases, all the caches need
  4569. // to be updated.
  4570. // (See bug 1616, to find out why we also have to update
  4571. // the autmatic caches of auto-links).
  4572. error= m_pCOleCache->UpdateCache(
  4573. GetDataDelegate(),
  4574. UPDFCACHE_ALLBUTNODATACACHE, NULL);
  4575. }
  4576. if (bStartedNow)
  4577. {
  4578. UnbindSource();
  4579. }
  4580. errRtn:
  4581. // if we created a bind context release it.
  4582. if ( (NULL == pbc) && pBcUse)
  4583. {
  4584. pBcUse->Release();
  4585. }
  4586. errBndCtx:
  4587. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::Update ( %lx )\n",
  4588. this, error ));
  4589. return error;
  4590. }
  4591. //+-------------------------------------------------------------------------
  4592. //
  4593. // Member: CDefLink::EnableTracking
  4594. //
  4595. // Synopsis: Calls ITrackingMoniker::EnableTracking on the passed moniker.
  4596. //
  4597. // Arguments: [pmk] -- moniker
  4598. //
  4599. // [ulFlags]
  4600. // OT_READTRACKINGINFO -- read tracking info from source
  4601. // OT_ENABLESAVE -- enable save of tracking info
  4602. // OT_DISABLESAVE -- disable save of tracking info
  4603. //
  4604. // Algorithm: QI to ITrackingMoniker and call EnableTracking
  4605. //
  4606. //
  4607. //--------------------------------------------------------------------------
  4608. #ifdef _TRACKLINK_
  4609. INTERNAL CDefLink::EnableTracking(IMoniker *pmk, ULONG ulFlags)
  4610. {
  4611. ITrackingMoniker *ptm = NULL;
  4612. HRESULT hr = E_FAIL;
  4613. if (pmk != NULL)
  4614. {
  4615. hr = pmk->QueryInterface(IID_ITrackingMoniker, (void**)&ptm);
  4616. if (hr == S_OK)
  4617. {
  4618. hr = ptm->EnableTracking(NULL, ulFlags);
  4619. LEDebugOut((DEB_TRACK,
  4620. "CDefLink(%08X)::EnableTracking -- ptm->EnableTracking() = %08X\n",
  4621. this, hr));
  4622. ptm->Release();
  4623. }
  4624. else
  4625. {
  4626. LEDebugOut((DEB_TRACK,
  4627. "CDefLink(%08X)::EnableTracking -- pmk->QI failed (%08X)\n",
  4628. this, hr));
  4629. }
  4630. }
  4631. else
  4632. {
  4633. LEDebugOut((DEB_TRACK,
  4634. "CDefLink(%08X)::EnableTracking -- pmk is NULL\n",
  4635. this));
  4636. }
  4637. return(hr);
  4638. }
  4639. #endif
  4640. /*
  4641. * IMPLEMENTATION of CROImpl methods
  4642. */
  4643. //+-------------------------------------------------------------------------
  4644. //
  4645. // Member: CDefLink::GetRODelegate (private)
  4646. //
  4647. // Synopsis: gets the IRunnableObject from the interface
  4648. //
  4649. // Effects:
  4650. //
  4651. // Arguments: void
  4652. //
  4653. // Requires:
  4654. //
  4655. // Returns: IRunnableObject *
  4656. //
  4657. // Signals:
  4658. //
  4659. // Modifies:
  4660. //
  4661. // Derivation:
  4662. //
  4663. // Algorithm:
  4664. //
  4665. // History: dd-mmm-yy Author Comment
  4666. // 21-Nov-94 alexgo memory optimization
  4667. // 03-Aug-94 alexgo stabilized and handle the zombie case
  4668. // 19-Nov-93 alexgo 32bit port
  4669. //
  4670. // Notes:
  4671. // This function may return misleading information if the
  4672. // server has died (i.e., you'll return a pointer to a cached
  4673. // interface proxy). It is the responsibility of the caller
  4674. // to handler server crashes.
  4675. //
  4676. //--------------------------------------------------------------------------
  4677. INTERNAL_(IRunnableObject *) CDefLink::GetRODelegate(void)
  4678. {
  4679. IRunnableObject *pRODelegate;
  4680. VDATEHEAP();
  4681. LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::GetRODelegate "
  4682. "( )\n", this ));
  4683. // if we're zombied, then we don't want to QI for a new interface!!
  4684. if( !IsZombie() )
  4685. {
  4686. DuCacheDelegate(&(m_pUnkDelegate),
  4687. IID_IRunnableObject, (LPLPVOID)&m_pRODelegate, NULL);
  4688. pRODelegate = m_pRODelegate;
  4689. #if DBG == 1
  4690. if( m_pRODelegate )
  4691. {
  4692. Assert(m_pUnkDelegate);
  4693. }
  4694. #endif // DBG == 1
  4695. }
  4696. else
  4697. {
  4698. pRODelegate = NULL;
  4699. }
  4700. LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::GetRODelegate "
  4701. "( %p )\n", this, pRODelegate));
  4702. return pRODelegate;
  4703. }
  4704. //+-------------------------------------------------------------------------
  4705. //
  4706. // Member: CDefLink::ReleaseRODelegate (private)
  4707. //
  4708. // Synopsis: Releases the IRO pointer to the server
  4709. //
  4710. // Effects:
  4711. //
  4712. // Arguments: void
  4713. //
  4714. // Requires:
  4715. //
  4716. // Returns: void
  4717. //
  4718. // Signals:
  4719. //
  4720. // Modifies:
  4721. //
  4722. // Derivation:
  4723. //
  4724. // Algorithm:
  4725. //
  4726. // History: dd-mmm-yy Author Comment
  4727. // 21-Nov-94 alexgo memory optimization
  4728. // 19-Nov-93 alexgo 32bit port
  4729. //
  4730. // Notes:
  4731. //
  4732. //--------------------------------------------------------------------------
  4733. INTERNAL_(void) CDefLink::ReleaseRODelegate(void)
  4734. {
  4735. VDATEHEAP();
  4736. LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::ReleaseRODelegate "
  4737. "( )\n", this ));
  4738. if (m_pRODelegate)
  4739. {
  4740. SafeReleaseAndNULL((IUnknown **)&m_pRODelegate);
  4741. }
  4742. LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::ReleaseRODelegate "
  4743. "( )\n", this ));
  4744. }
  4745. //+-------------------------------------------------------------------------
  4746. //
  4747. // Member: CDefLink::GetRunningClass
  4748. //
  4749. // Synopsis: retrieves the class of the the default link
  4750. //
  4751. // Effects:
  4752. //
  4753. // Arguments: [lpClsid] -- where to put the class id
  4754. //
  4755. // Requires:
  4756. //
  4757. // Returns: NOERROR
  4758. //
  4759. // Signals:
  4760. //
  4761. // Modifies:
  4762. //
  4763. // Derivation: IRunnableObject
  4764. //
  4765. // Algorithm:
  4766. //
  4767. // History: dd-mmm-yy Author Comment
  4768. // 21-Nov-94 alexgo memory optimization
  4769. // 19-Nov-93 alexgo 32bit port
  4770. //
  4771. // Notes:
  4772. //
  4773. //--------------------------------------------------------------------------
  4774. STDMETHODIMP CDefLink::GetRunningClass(LPCLSID lpClsid)
  4775. {
  4776. VDATEHEAP();
  4777. VDATETHREAD(this);
  4778. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::GetRunningClass "
  4779. "( %p )\n", this, lpClsid));
  4780. VDATEPTROUT(lpClsid, CLSID);
  4781. *lpClsid = CLSID_StdOleLink;
  4782. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::GetRunningClass "
  4783. "( %lx )\n", this, NOERROR));
  4784. return NOERROR;
  4785. }
  4786. //+-------------------------------------------------------------------------
  4787. //
  4788. // Member: CDefLink::Run
  4789. //
  4790. // Synopsis: Runs the object (binds to the server)
  4791. //
  4792. // Effects:
  4793. //
  4794. // Arguments: [pbc] -- the bind context
  4795. //
  4796. // Requires:
  4797. //
  4798. // Returns: HRESULT
  4799. //
  4800. // Signals:
  4801. //
  4802. // Modifies:
  4803. //
  4804. // Derivation: IRunnableObject
  4805. //
  4806. // Algorithm:
  4807. //
  4808. // History: dd-mmm-yy Author Comment
  4809. // 21-Nov-94 alexgo memory optimization
  4810. // 03-Aug-94 alexgo stabilized
  4811. // 19-Nov-93 alexgo 32bit port
  4812. //
  4813. // Notes:
  4814. //
  4815. //--------------------------------------------------------------------------
  4816. STDMETHODIMP CDefLink::Run (LPBINDCTX pbc)
  4817. {
  4818. HRESULT hresult;
  4819. VDATEHEAP();
  4820. VDATETHREAD(this);
  4821. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::Run ( %p )\n",
  4822. this, pbc ));
  4823. CRefStabilize stabilize(this);
  4824. hresult = BindToSource(0, pbc);
  4825. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::Run ( %lx )\n",
  4826. this, hresult));
  4827. return hresult;
  4828. }
  4829. //+-------------------------------------------------------------------------
  4830. //
  4831. // Member: CDefLink::IsRunning
  4832. //
  4833. // Synopsis: returns whether or not we've bound to the link server
  4834. //
  4835. // Effects:
  4836. //
  4837. // Arguments: none
  4838. //
  4839. // Requires:
  4840. //
  4841. // Returns: TRUE/FALSE
  4842. //
  4843. // Signals:
  4844. //
  4845. // Modifies:
  4846. //
  4847. // Derivation: IRunnableObject
  4848. //
  4849. // Algorithm:
  4850. //
  4851. // History: dd-mmm-yy Author Comment
  4852. // 21-Nov-94 alexgo memory optimization
  4853. // 27-Aug-94 alexgo author
  4854. //
  4855. // Notes: 16bit OLE only ever implemented this function. We
  4856. // implement IsReallyRunning to allow links to recover
  4857. // from a crashed server.
  4858. // Unfortunately, we can't just move the IsReallyRunning
  4859. // implementation into IsRunning. Many apps (like Project)
  4860. // sit and spin calling OleIsRunning. IsReallyRunning also
  4861. // will sometimes make outgoing RPC calls; with Project,
  4862. // this causes a really cool infinite feedback loop. (the
  4863. // outgoing call resets some state in Project and they decide
  4864. // to call OleIsRunning again ;-)
  4865. //
  4866. //--------------------------------------------------------------------------
  4867. STDMETHODIMP_(BOOL) CDefLink::IsRunning (void)
  4868. {
  4869. BOOL fRet;
  4870. VDATEHEAP();
  4871. VDATETHREAD(this);
  4872. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::IsRunning ( )\n",
  4873. this ));
  4874. if( m_pUnkDelegate )
  4875. {
  4876. fRet = TRUE;
  4877. }
  4878. else
  4879. {
  4880. fRet = FALSE;
  4881. }
  4882. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::IsRunning ( %d )\n",
  4883. this, fRet));
  4884. return fRet;
  4885. }
  4886. //+-------------------------------------------------------------------------
  4887. //
  4888. // Member: CDefLink::IsReallyRunning
  4889. //
  4890. // Synopsis: Returns whether or not the link server is running
  4891. //
  4892. // Effects:
  4893. //
  4894. // Arguments: void
  4895. //
  4896. // Requires:
  4897. //
  4898. // Returns: BOOL -- TRUE == is running
  4899. //
  4900. // Signals:
  4901. //
  4902. // Modifies:
  4903. //
  4904. // Derivation:
  4905. //
  4906. // Algorithm: If we have not yet bound to the link server, then we
  4907. // are not running. If we have, we would like to verify
  4908. // that the server is still running (i.e. it hasn't crashed).
  4909. // Thus, we ask the absolute moniker if we are still running.
  4910. // (it will ping the rot, which will ping the server).
  4911. //
  4912. // History: dd-mmm-yy Author Comment
  4913. // 21-Nov-94 alexgo memory optimization
  4914. // 03-Aug-94 alexgo stabilized
  4915. // 06-May-94 alexgo now calls IMoniker::IsRunning
  4916. // 19-Nov-93 alexgo 32bit port
  4917. //
  4918. // Notes:
  4919. //
  4920. //
  4921. //--------------------------------------------------------------------------
  4922. STDMETHODIMP_(BOOL) CDefLink::IsReallyRunning (void)
  4923. {
  4924. BOOL fRet = FALSE;
  4925. LPBC pbc;
  4926. HRESULT hresult;
  4927. VDATEHEAP();
  4928. VDATETHREAD(this);
  4929. LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::IsReallyRunning "
  4930. "( )\n", this));
  4931. CRefStabilize stabilize(this);
  4932. if( m_pUnkDelegate != NULL )
  4933. {
  4934. if( CreateBindCtx( 0, &pbc ) != NOERROR )
  4935. {
  4936. // this is a bit counter-intuitive. Basically,
  4937. // the only error we'll get is OutOfMemory, but
  4938. // we have no way of returning that error.
  4939. // In order to mimimize the amount of work we need
  4940. // to do (since we are in a low-mem state), just
  4941. // return the current Running state (in this,
  4942. // TRUE, since m_pUnkDelegate is not NULL
  4943. fRet = TRUE;
  4944. goto errRtn;
  4945. }
  4946. if( m_pMonikerAbs )
  4947. {
  4948. hresult = m_pMonikerAbs->IsRunning(pbc,
  4949. NULL, NULL);
  4950. if( hresult != NOERROR )
  4951. {
  4952. LEDebugOut((DEB_WARN, "WARNING: link server "
  4953. "crashed or exited inappropriately "
  4954. "( %lx ). Recovering...\n", hresult));
  4955. // wowsers, the server has crashed or gone
  4956. // away even though we were bound to it.
  4957. // let's go ahead and unbind.
  4958. // don't worry about errors here; we're
  4959. // just trying to cleanup as best we can
  4960. UnbindSource();
  4961. }
  4962. if( hresult == NOERROR )
  4963. {
  4964. fRet = TRUE;
  4965. }
  4966. #if DBG == 1
  4967. else
  4968. {
  4969. Assert(fRet == FALSE);
  4970. }
  4971. #endif // DBG == 1
  4972. }
  4973. #if DBG == 1
  4974. else
  4975. {
  4976. // we cannot have a pointer to the link server
  4977. // if we don't have a moniker to it. If we get
  4978. // to this state, something is hosed.
  4979. AssertSz(0,
  4980. "Pointer to link server without a moniker");
  4981. }
  4982. #endif // DBG == 1
  4983. pbc->Release();
  4984. }
  4985. errRtn:
  4986. // do some checking here. If we say we're running, then
  4987. // we should have a valid pUnkDelegate. Otherwise, it should
  4988. // be NULL. Note, however, that is *is* possible for us
  4989. // to unbind during this call even if we think we're running
  4990. //
  4991. // This occurs if during the call to IMoniker::IsRunning, we
  4992. // get another call in which does an UnbindSource; thus
  4993. // we'll think we're really running (from IMoniker::IsRunning),
  4994. // but we've really unbound.
  4995. //
  4996. // We'll check for that condition here
  4997. if( fRet == TRUE )
  4998. {
  4999. if( m_pUnkDelegate == NULL )
  5000. {
  5001. fRet = FALSE;
  5002. LEDebugOut((DEB_WARN, "WARNING: Re-entrant Unbind"
  5003. " during IsReallyRunning, should be OK\n"));
  5004. }
  5005. }
  5006. #if DBG == 1
  5007. if( fRet == TRUE )
  5008. {
  5009. Assert(m_pUnkDelegate != NULL);
  5010. }
  5011. else
  5012. {
  5013. Assert(m_pUnkDelegate == NULL);
  5014. }
  5015. #endif // DBG == 1
  5016. LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::IsReallyRunning"
  5017. "( %lu )\n", this, fRet));
  5018. return fRet;
  5019. }
  5020. //+-------------------------------------------------------------------------
  5021. //
  5022. // Member: CDefLink::SetContainedObject
  5023. //
  5024. // Synopsis: Sets the object as an embedding, not relevant for links
  5025. //
  5026. // Effects:
  5027. //
  5028. // Arguments: [fContained] -- flag to toggle embedding status
  5029. //
  5030. // Requires:
  5031. //
  5032. // Returns: HRESULT (NOERROR)
  5033. //
  5034. // Signals:
  5035. //
  5036. // Modifies:
  5037. //
  5038. // Derivation: IRunnableObject
  5039. //
  5040. // Algorithm:
  5041. //
  5042. // History: dd-mmm-yy Author Comment
  5043. // 21-Nov-94 alexgo memory optimization
  5044. // 19-Nov-93 alexgo 32bit port
  5045. //
  5046. // Notes:
  5047. //
  5048. // note contained object; links don't care at present
  5049. //
  5050. //--------------------------------------------------------------------------
  5051. STDMETHODIMP CDefLink::SetContainedObject(BOOL fContained)
  5052. {
  5053. VDATEHEAP();
  5054. VDATETHREAD(this);
  5055. return NOERROR;
  5056. }
  5057. //+-------------------------------------------------------------------------
  5058. //
  5059. // Member: CDefLink::LockRunning
  5060. //
  5061. // Synopsis: Lock/Unlock the connection to the server. Does nothing
  5062. // for links.
  5063. //
  5064. // Effects:
  5065. //
  5066. // Arguments: [fLock] -- flag to lock/unlock
  5067. // [fLastUnlockCloses] -- close if its the last unlock
  5068. //
  5069. // Requires:
  5070. //
  5071. // Returns: NOERROR
  5072. //
  5073. // Signals:
  5074. //
  5075. // Modifies:
  5076. //
  5077. // Derivation: IRunnableObject
  5078. //
  5079. // Algorithm:
  5080. //
  5081. // History: dd-mmm-yy Author Comment
  5082. // 21-Nov-94 alexgo memory optimization
  5083. // 19-Nov-93 alexgo 32bit port
  5084. //
  5085. // Notes:
  5086. // Links have different liveness characteristics than embeddings.
  5087. // We do not need to do anything for LockRunning for links.
  5088. //
  5089. //--------------------------------------------------------------------------
  5090. STDMETHODIMP CDefLink::LockRunning(BOOL fLock, BOOL fLastUnlockCloses)
  5091. {
  5092. VDATEHEAP();
  5093. VDATETHREAD(this);
  5094. return NOERROR;
  5095. }
  5096. /*
  5097. * IMPLEMENTATION of CPersistStgImpl methods
  5098. */
  5099. //+-------------------------------------------------------------------------
  5100. //
  5101. // Member: CDefLink::GetClassID
  5102. //
  5103. // Synopsis: Retrieves the class id of the default link
  5104. //
  5105. // Effects:
  5106. //
  5107. // Arguments: [pClassID] -- where to put the class ID
  5108. //
  5109. // Requires:
  5110. //
  5111. // Returns: HRESULT
  5112. //
  5113. // Signals:
  5114. //
  5115. // Modifies:
  5116. //
  5117. // Derivation: IPersistStorage
  5118. //
  5119. // Algorithm:
  5120. //
  5121. // History: dd-mmm-yy Author Comment
  5122. // 21-Nov-94 alexgo memory optimization
  5123. // 19-Nov-93 alexgo 32bit port
  5124. //
  5125. // Notes:
  5126. //
  5127. //--------------------------------------------------------------------------
  5128. STDMETHODIMP CDefLink::GetClassID (CLSID *pClassID)
  5129. {
  5130. VDATEHEAP();
  5131. VDATETHREAD(this);
  5132. *pClassID = CLSID_StdOleLink;
  5133. return NOERROR;
  5134. }
  5135. //+-------------------------------------------------------------------------
  5136. //
  5137. // Member: CDefLink::IsDirty
  5138. //
  5139. // Synopsis: Returns TRUE if the linked object has changed
  5140. //
  5141. // Effects:
  5142. //
  5143. // Arguments: void
  5144. //
  5145. // Requires:
  5146. //
  5147. // Returns: NOERROR if dirty
  5148. //
  5149. // Signals:
  5150. //
  5151. // Modifies:
  5152. //
  5153. // Derivation: IPersistStorage
  5154. //
  5155. // Algorithm:
  5156. //
  5157. // History: dd-mmm-yy Author Comment
  5158. // 21-Nov-94 alexgo memory optimization
  5159. // 19-Nov-93 alexgo 32bit port
  5160. //
  5161. // Notes:
  5162. //
  5163. //--------------------------------------------------------------------------
  5164. STDMETHODIMP CDefLink::IsDirty(void)
  5165. {
  5166. HRESULT hresult;
  5167. VDATEHEAP();
  5168. VDATETHREAD(this);
  5169. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::IsDirty"
  5170. " ( )\n", this));
  5171. if( (m_flags & DL_DIRTY_LINK) )
  5172. {
  5173. hresult = NOERROR;
  5174. }
  5175. else
  5176. {
  5177. Assert(m_pCOleCache != NULL);
  5178. hresult = m_pCOleCache->IsDirty();
  5179. }
  5180. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::IsDirty "
  5181. "( %lx )\n", this, hresult));
  5182. return hresult;
  5183. }
  5184. //+-------------------------------------------------------------------------
  5185. //
  5186. // Member: CDefLink::InitNew
  5187. //
  5188. // Synopsis: Initialize a new link object from the given storage
  5189. //
  5190. // Effects:
  5191. //
  5192. // Arguments: [pstg] -- the new storage for the link
  5193. //
  5194. // Requires:
  5195. //
  5196. // Returns: HRESULT
  5197. //
  5198. // Signals:
  5199. //
  5200. // Modifies:
  5201. //
  5202. // Derivation: IPersistStorage
  5203. //
  5204. // Algorithm: Delegates to the cache
  5205. //
  5206. // History: dd-mmm-yy Author Comment
  5207. // 21-Nov-94 alexgo memory optimization
  5208. // 03-Aug-94 alexgo stabilized and handle the zombie case
  5209. // 19-Nov-93 alexgo 32bit port
  5210. //
  5211. // Notes:
  5212. //
  5213. //--------------------------------------------------------------------------
  5214. STDMETHODIMP CDefLink::InitNew( IStorage *pstg)
  5215. {
  5216. HRESULT error;
  5217. VDATEHEAP();
  5218. VDATETHREAD(this);
  5219. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::InitNew "
  5220. "( %p )\n", this, pstg));
  5221. VDATEIFACE(pstg);
  5222. CRefStabilize stabilize(this);
  5223. if( IsZombie() )
  5224. {
  5225. error = CO_E_RELEASED;
  5226. }
  5227. else if (m_pStg == NULL)
  5228. {
  5229. Assert(m_pCOleCache != NULL);
  5230. if ((error = m_pCOleCache->InitNew(pstg)) == NOERROR)
  5231. {
  5232. m_flags |= DL_DIRTY_LINK;
  5233. (m_pStg = pstg)->AddRef();
  5234. }
  5235. }
  5236. else
  5237. {
  5238. error = CO_E_ALREADYINITIALIZED;
  5239. }
  5240. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::InitNew "
  5241. "( %lx )\n", this, error ));
  5242. return error;
  5243. }
  5244. //+-------------------------------------------------------------------------
  5245. //
  5246. // Member: CDefLink::Load
  5247. //
  5248. // Synopsis: Initializes a link from data stored in the storage
  5249. //
  5250. // Effects:
  5251. //
  5252. // Arguments: [pstg] -- the storage with link data
  5253. //
  5254. // Requires:
  5255. //
  5256. // Returns: HRESULT
  5257. //
  5258. // Signals:
  5259. //
  5260. // Modifies:
  5261. //
  5262. // Derivation: IPersistStorage
  5263. //
  5264. // Algorithm: Read ole private data and set internal link information.
  5265. // Then delegate to the cache to load presentation data, etc.
  5266. //
  5267. // History: dd-mmm-yy Author Comment
  5268. // 20-Feb-94 KentCe Buffer internal stream i/o.
  5269. // 21-Nov-94 alexgo memory optimization
  5270. // 03-Aug-94 alexgo stabilized and handle zombie case
  5271. // 19-Nov-93 alexgo 32bit port
  5272. //
  5273. //--------------------------------------------------------------------------
  5274. STDMETHODIMP CDefLink::Load(IStorage *pstg)
  5275. {
  5276. HRESULT error;
  5277. LPMONIKER pmk = NULL;
  5278. LPMONIKER pmkSrcAbs = NULL;
  5279. LPMONIKER pmkSrcRel = NULL;
  5280. CLSID clsid;
  5281. DWORD dwOptUpdate;
  5282. LPSTREAM pstm = NULL;
  5283. DWORD dummy;
  5284. ULONG cbRead;
  5285. CStmBufRead StmRead;
  5286. VDATEHEAP();
  5287. VDATETHREAD(this);
  5288. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::CPeristStgImpl::Load "
  5289. "( %p )\n", this, pstg ));
  5290. VDATEIFACE(pstg);
  5291. CRefStabilize stabilize(this);
  5292. // if we're in a zombie state, we don't want to be reloading
  5293. // our object!!
  5294. if( IsZombie() )
  5295. {
  5296. error = CO_E_RELEASED;
  5297. goto logRtn;
  5298. }
  5299. if (m_pStg)
  5300. {
  5301. error = CO_E_ALREADYINITIALIZED;
  5302. goto logRtn;
  5303. }
  5304. //read link data from the storage
  5305. error = ReadOleStg (pstg, &m_dwObjFlags, &dwOptUpdate, NULL, &pmk, &pstm);
  5306. if (error == NOERROR)
  5307. {
  5308. // set the update options.
  5309. SetUpdateOptions (dwOptUpdate);
  5310. // we can get the moniker from container, so no need to
  5311. // remeber this
  5312. if (pmk)
  5313. {
  5314. pmk->Release();
  5315. }
  5316. Assert (pstm != NULL);
  5317. // Read relative source moniker. Write NULL for the time being
  5318. if ((error = ReadMonikerStm (pstm, &pmkSrcRel)) != NOERROR)
  5319. {
  5320. goto errRtn;
  5321. }
  5322. // Read absolute source moniker; stored in link below
  5323. if ((error = ReadMonikerStm (pstm, &pmkSrcAbs)) != NOERROR)
  5324. {
  5325. goto errRtn;
  5326. }
  5327. //
  5328. // Buffer the read i/o from the stream.
  5329. //
  5330. StmRead.Init(pstm);
  5331. // Read -1 followed by the last class name
  5332. if ((error = ReadM1ClassStmBuf(StmRead, &clsid)) != NOERROR)
  5333. {
  5334. goto errRtn;
  5335. }
  5336. // Read the last display name
  5337. // Right now, this is always an empty string
  5338. LPOLESTR pstr = NULL;
  5339. if ((error = ReadStringStream (StmRead, &pstr)) != NOERROR)
  5340. {
  5341. goto errRtn;
  5342. }
  5343. if (pstr)
  5344. {
  5345. LEDebugOut((DEB_ERROR, "ERROR!: Link user type "
  5346. "string found, unexpected\n"));
  5347. PubMemFree(pstr);
  5348. }
  5349. if ((error = StmRead.Read(&dummy, sizeof(DWORD)))
  5350. != NOERROR)
  5351. {
  5352. goto errRtn;
  5353. }
  5354. if ((error = StmRead.Read(&(m_ltChangeOfUpdate),
  5355. sizeof(FILETIME))) != NOERROR)
  5356. {
  5357. goto errRtn;
  5358. }
  5359. if ((error = StmRead.Read(&(m_ltKnownUpToDate),
  5360. sizeof(FILETIME))) != NOERROR)
  5361. {
  5362. goto errRtn;
  5363. }
  5364. if ((error = StmRead.Read(&(m_rtUpdate),
  5365. sizeof(FILETIME))) != NOERROR)
  5366. {
  5367. goto errRtn;
  5368. }
  5369. //
  5370. // TRACKLINK
  5371. //
  5372. // - tell the absolute moniker to convert itself
  5373. // into a tracking moniker using ITrackingMoniker::
  5374. // EnableTracking. (The composite
  5375. // moniker should pass this on to each of
  5376. // its contained monikers.)
  5377. // - if the moniker is already a tracking file moniker
  5378. // ignore the request.
  5379. //
  5380. #ifdef _TRACKLINK_
  5381. EnableTracking(pmkSrcAbs, OT_READTRACKINGINFO);
  5382. #endif
  5383. m_pMonikerRel = pmkSrcRel;
  5384. if (pmkSrcRel)
  5385. {
  5386. pmkSrcRel->AddRef();
  5387. }
  5388. m_pMonikerAbs = pmkSrcAbs;
  5389. if (pmkSrcAbs)
  5390. {
  5391. pmkSrcAbs->AddRef();
  5392. }
  5393. m_clsid = clsid;
  5394. // just loaded; thus not dirty
  5395. m_flags &= ~(DL_DIRTY_LINK);
  5396. }
  5397. else if( error == STG_E_FILENOTFOUND)
  5398. {
  5399. // It's OK if the Ole stream doesn't exist.
  5400. error = NOERROR;
  5401. }
  5402. else
  5403. {
  5404. return error;
  5405. }
  5406. // now load cache from pstg
  5407. Assert(m_pCOleCache != NULL);
  5408. if(m_dwObjFlags & OBJFLAGS_CACHEEMPTY) {
  5409. error = m_pCOleCache->Load(pstg, TRUE);
  5410. if(error != NOERROR)
  5411. goto errRtn;
  5412. }
  5413. else {
  5414. error = m_pCOleCache->Load(pstg);
  5415. if(error != NOERROR)
  5416. goto errRtn;
  5417. }
  5418. (m_pStg = pstg)->AddRef();
  5419. errRtn:
  5420. StmRead.Release();
  5421. if (pmkSrcAbs)
  5422. {
  5423. pmkSrcAbs->Release();
  5424. }
  5425. if (pmkSrcRel)
  5426. {
  5427. pmkSrcRel->Release();
  5428. }
  5429. if (pstm)
  5430. {
  5431. pstm->Release();
  5432. }
  5433. #ifdef REVIEW
  5434. if (error == NOERROR && m_pAppClientSite)
  5435. {
  5436. BindIfRunning();
  5437. }
  5438. #endif
  5439. logRtn:
  5440. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::Load "
  5441. "( %lx )\n", this, error ));
  5442. return error;
  5443. }
  5444. //+-------------------------------------------------------------------------
  5445. //
  5446. // Member: CDefLink::Save
  5447. //
  5448. // Synopsis: Saves the link the given storage
  5449. //
  5450. // Effects:
  5451. //
  5452. // Arguments: [pstgSave] -- the storage to save into
  5453. // [fSameAsLoad] -- FALSE indicates SaveAs operation
  5454. //
  5455. // Requires:
  5456. //
  5457. // Returns: HRESULT
  5458. //
  5459. // Signals:
  5460. //
  5461. // Modifies:
  5462. //
  5463. // Derivation: IPersistStorage
  5464. //
  5465. // Algorithm: Writes private ole data (such as the clsid, monikers,
  5466. // and update times) and the presentations stored in the
  5467. // cache to the given storage
  5468. //
  5469. // History: dd-mmm-yy Author Comment
  5470. // 21-Nov-94 alexgo memory optimization
  5471. // 03-Aug-94 alexgo stabilized
  5472. // 19-Nov-93 alexgo 32bit port
  5473. //
  5474. // Notes:
  5475. //
  5476. //--------------------------------------------------------------------------
  5477. STDMETHODIMP CDefLink::Save( IStorage *pstgSave, BOOL fSameAsLoad)
  5478. {
  5479. HRESULT error = NOERROR;
  5480. LPSTREAM pstm = NULL;
  5481. DWORD cbWritten;
  5482. CStmBufWrite StmWrite;
  5483. DWORD ObjFlags = 0;
  5484. VDATEHEAP();
  5485. VDATETHREAD(this);
  5486. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::CPeristStgImpl::Save "
  5487. "( %p , %lu )\n", this, pstgSave, fSameAsLoad ));
  5488. VDATEIFACE(pstgSave);
  5489. CRefStabilize stabilize(this);
  5490. // update any cache which has ADVFCACHE_ONSAVE
  5491. UpdateAutoOnSave();
  5492. if(fSameAsLoad && !(m_flags & DL_DIRTY_LINK) &&
  5493. (!!(m_dwObjFlags & OBJFLAGS_CACHEEMPTY)==m_pCOleCache->IsEmpty())) {
  5494. // The storage is not a new one (so we don't need to
  5495. // initialize our private data) and the link is not
  5496. // dirty, so we just need to delegate to the cache
  5497. goto LSaveCache;
  5498. }
  5499. // Obtain cache status
  5500. if(m_pCOleCache->IsEmpty())
  5501. ObjFlags |= OBJFLAGS_CACHEEMPTY;
  5502. // assign object moniker (used by WriteOleStg); we don't save this
  5503. // moniker since WriteOleStg gets it again; we also don't care if
  5504. // this failes as we don't want a failure here to prevent the link
  5505. // from being saved; the assignment might fail if some container has
  5506. // yet to be saved to a file. REIVEW PERF: we could pass this mk to
  5507. // WriteOleStg. We don't get the moniker for !fSameAsLoad since the
  5508. // relative moniker is not correct for the new stg and it causes the
  5509. // container to do work in a case for which it might not be prepared.
  5510. IMoniker * pMkObjRel;
  5511. if (fSameAsLoad && GetMoniker(
  5512. OLEGETMONIKER_FORCEASSIGN,
  5513. OLEWHICHMK_OBJREL, &pMkObjRel) == NOERROR)
  5514. {
  5515. pMkObjRel->Release();
  5516. }
  5517. if ((error = WriteOleStgEx(pstgSave,(IOleObject *)this, NULL, ObjFlags,
  5518. &pstm)) != NOERROR)
  5519. {
  5520. goto logRtn;
  5521. }
  5522. Assert(pstm != NULL);
  5523. // Write relative source moniker.
  5524. // if it is NULL, try to compute it now. We may be saving a file for
  5525. // the first time, so the container now has a moniker for the first
  5526. // time.
  5527. if (m_pMonikerRel == NULL || m_pUnkDelegate)
  5528. {
  5529. // if the link is connected, we know that the absolute
  5530. // moniker is correct -- it was updated at bind time if
  5531. // necessary. If the link container moniker has changed
  5532. // (file/saveas) then we can exploit this opportunity to
  5533. // straighten things out and improve our link tracking
  5534. // since we know which of the two monikers is correct.
  5535. UpdateRelMkFromAbsMk(NULL);
  5536. }
  5537. if ((error = WriteMonikerStm (pstm, m_pMonikerRel))
  5538. != NOERROR)
  5539. {
  5540. goto errRtn;
  5541. }
  5542. #ifdef _TRACKLINK_
  5543. EnableTracking(m_pMonikerAbs, OT_ENABLESAVE);
  5544. #endif
  5545. // Write absolute source moniker.
  5546. error = WriteMonikerStm (pstm, m_pMonikerAbs);
  5547. #ifdef _TRACKLINK_
  5548. EnableTracking(m_pMonikerAbs, OT_DISABLESAVE);
  5549. #endif
  5550. if (error != NOERROR)
  5551. goto errRtn;
  5552. //
  5553. //
  5554. //
  5555. StmWrite.Init(pstm);
  5556. // write last class name
  5557. UpdateUserClassID();
  5558. if ((error = WriteM1ClassStmBuf(StmWrite, m_clsid)) != NOERROR)
  5559. {
  5560. goto errRtn;
  5561. }
  5562. // write last display name, should be NULL if the moniker's are
  5563. // non-NULL. For the time being this is always NULL.
  5564. if ((error = StmWrite.WriteLong(0))
  5565. != NOERROR)
  5566. {
  5567. goto errRtn;
  5568. }
  5569. // write -1 as the end marker, so that if we want to extend
  5570. // the file formats (ex: adding network name) it will be easier.
  5571. if ((error = StmWrite.WriteLong(-1))
  5572. != NOERROR)
  5573. {
  5574. goto errRtn;
  5575. }
  5576. if ((error = StmWrite.Write(&(m_ltChangeOfUpdate),
  5577. sizeof(FILETIME))) != NOERROR)
  5578. {
  5579. goto errRtn;
  5580. }
  5581. if ((error = StmWrite.Write(&(m_ltKnownUpToDate),
  5582. sizeof(FILETIME))) != NOERROR)
  5583. {
  5584. goto errRtn;
  5585. }
  5586. if ((error = StmWrite.Write(&(m_rtUpdate),
  5587. sizeof(FILETIME))) != NOERROR)
  5588. {
  5589. goto errRtn;
  5590. }
  5591. if ((error = StmWrite.Flush()) != NOERROR)
  5592. {
  5593. goto errRtn;
  5594. }
  5595. if (!fSameAsLoad)
  5596. {
  5597. // Copy link tracking info
  5598. static const LPOLESTR lpszLinkTracker = OLESTR("\1OleLink");
  5599. pstgSave->DestroyElement(lpszLinkTracker);
  5600. if (m_pStg)
  5601. {
  5602. // copy link tracking info, if one existed,
  5603. // ignore error
  5604. m_pStg->MoveElementTo(lpszLinkTracker,
  5605. pstgSave, lpszLinkTracker,
  5606. STGMOVE_COPY);
  5607. }
  5608. }
  5609. LSaveCache:
  5610. // last, save cache
  5611. Assert(m_pCOleCache != NULL);
  5612. error = m_pCOleCache->Save(pstgSave, fSameAsLoad);
  5613. errRtn:
  5614. StmWrite.Release();
  5615. if (pstm)
  5616. {
  5617. pstm->Release();
  5618. }
  5619. if (error == NOERROR)
  5620. {
  5621. m_flags |= DL_NO_SCRIBBLE_MODE;
  5622. if( fSameAsLoad )
  5623. {
  5624. m_flags |= DL_SAME_AS_LOAD;
  5625. m_dwObjFlags |= ObjFlags;
  5626. }
  5627. else
  5628. {
  5629. m_flags &= ~(DL_SAME_AS_LOAD);
  5630. }
  5631. }
  5632. logRtn:
  5633. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::Save "
  5634. "( %lx )\n", this, error ));
  5635. return error;
  5636. }
  5637. //+-------------------------------------------------------------------------
  5638. //
  5639. // Member: CDefLink::SaveCompleted
  5640. //
  5641. // Synopsis: Called once the save is completed (for all objects in the
  5642. // container). Clear the dirty flag and update the storage
  5643. // that we hand onto.
  5644. //
  5645. // Effects:
  5646. //
  5647. // Arguments: [pstgNew] -- the new default storage for the object
  5648. //
  5649. // Requires:
  5650. //
  5651. // Returns: HRESULT
  5652. //
  5653. // Signals:
  5654. //
  5655. // Modifies:
  5656. //
  5657. // Derivation: IPersistStorage
  5658. //
  5659. // Algorithm:
  5660. //
  5661. // History: dd-mmm-yy Author Comment
  5662. // 21-Nov-94 alexgo memory optimization
  5663. // 03-Aug-94 alexgo stabilized and handle zombie case
  5664. // 20-Nov-93 alexgo 32bit port
  5665. //
  5666. // Notes:
  5667. //
  5668. //--------------------------------------------------------------------------
  5669. STDMETHODIMP CDefLink::SaveCompleted( IStorage *pstgNew)
  5670. {
  5671. VDATEHEAP();
  5672. VDATETHREAD(this);
  5673. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::Save"
  5674. "Completed ( %p )\n", this, pstgNew ));
  5675. if (pstgNew)
  5676. {
  5677. VDATEIFACE(pstgNew);
  5678. }
  5679. // don't hang on to the new storage if we're in a zombie state!
  5680. if (pstgNew && !IsZombie() )
  5681. {
  5682. if (m_pStg)
  5683. {
  5684. m_pStg->Release();
  5685. }
  5686. m_pStg = pstgNew;
  5687. pstgNew->AddRef();
  5688. }
  5689. // REVIEW: do we send on save???
  5690. if( (m_flags & DL_SAME_AS_LOAD) || pstgNew)
  5691. {
  5692. if( (m_flags & DL_NO_SCRIBBLE_MODE) )
  5693. {
  5694. m_flags &= ~(DL_DIRTY_LINK);
  5695. }
  5696. m_flags &= ~(DL_SAME_AS_LOAD);
  5697. }
  5698. // let the cache know that the save is completed, so that it can clear
  5699. // its dirty flag in Save or SaveAs situation, as well as remember the
  5700. // new storage pointer if a new one is given
  5701. Assert(m_pCOleCache != NULL);
  5702. m_pCOleCache->SaveCompleted(pstgNew);
  5703. m_flags &= ~(DL_NO_SCRIBBLE_MODE);
  5704. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::Save"
  5705. "Completed ( %lx )\n", this, NOERROR ));
  5706. return NOERROR;
  5707. }
  5708. //+-------------------------------------------------------------------------
  5709. //
  5710. // Member: CDefLink::HandsOffStorage
  5711. //
  5712. // Synopsis: Releases all pointers to the storage (useful for low-mem
  5713. // situations)
  5714. //
  5715. // Effects:
  5716. //
  5717. // Arguments: void
  5718. //
  5719. // Requires:
  5720. //
  5721. // Returns: HRESULT (NOERROR)
  5722. //
  5723. // Signals:
  5724. //
  5725. // Modifies:
  5726. //
  5727. // Derivation: IPersistStorage
  5728. //
  5729. // Algorithm:
  5730. //
  5731. // History: dd-mmm-yy Author Comment
  5732. // 21-Nov-94 alexgo memory optimization
  5733. // 20-Nov-93 alexgo 32bit port
  5734. //
  5735. // Notes:
  5736. //
  5737. //--------------------------------------------------------------------------
  5738. STDMETHODIMP CDefLink::HandsOffStorage(void)
  5739. {
  5740. VDATEHEAP();
  5741. VDATETHREAD(this);
  5742. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::HandsOff"
  5743. "Storage ( )\n", this ));
  5744. if (m_pStg)
  5745. {
  5746. m_pStg->Release();
  5747. m_pStg = NULL;
  5748. }
  5749. Assert(m_pCOleCache != NULL);
  5750. m_pCOleCache->HandsOffStorage();
  5751. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::HandsOff"
  5752. "Storage ( %lx )\n", this, NOERROR));
  5753. return NOERROR;
  5754. }
  5755. /*
  5756. *
  5757. * IMPLEMENTATION of CAdvSinkImpl methods
  5758. *
  5759. */
  5760. //
  5761. // NOTE: Advise Sink is a nested object of Default Link that is exported
  5762. // for achieving some of its functionality. This introduces some lifetime
  5763. // complications. Can its lifetime be controlled by the server object to
  5764. // which it exported its Advise Sink? Ideally, only its client should
  5765. // control its lifetime alone, but it should also honor the ref counts
  5766. // placed on it by the server object by entering into a zombie state
  5767. // to prevent AV's on the incoming calls to the Advise Sink. All needed
  5768. // logic is coded into the new class "CRefExportCount" which manages
  5769. // the ref and export counts in a thread safe manner and invokes
  5770. // appropriate methods during the object's lifetime. Any server objects
  5771. // that export nested objects to other server objects should derive from
  5772. // "CRefExportCount" class and call its methods to manage their lifetime
  5773. // as exemplified in this Default Link implementation.
  5774. //
  5775. // Gopalk Jan 28, 97
  5776. //
  5777. //+-------------------------------------------------------------------------
  5778. //
  5779. // Member: CDefLink::CAdvSinkImpl::QueryInterface
  5780. //
  5781. // Synopsis: Only supports IUnknown and IAdviseSink
  5782. //
  5783. // Arguments: [iid] -- Interface requested
  5784. // [ppvObj] -- pointer to hold returned interface
  5785. //
  5786. // Returns: HRESULT
  5787. //
  5788. // History: dd-mmm-yy Author Comment
  5789. // 10-Jan-96 Gopalk Rewritten
  5790. //--------------------------------------------------------------------------
  5791. STDMETHODIMP CDefLink::CAdvSinkImpl::QueryInterface(REFIID iid, void **ppv)
  5792. {
  5793. LEDebugOut((DEB_TRACE,"%p _IN CDefLink::CAdvSinkImpl::QueryInterface()\n",
  5794. this));
  5795. // Validation check
  5796. VDATEHEAP();
  5797. // Local variables
  5798. HRESULT hresult = NOERROR;
  5799. if(IsValidPtrOut(ppv, sizeof(void *))) {
  5800. if(IsEqualIID(iid, IID_IUnknown)) {
  5801. *ppv = (void *)(IUnknown *) this;
  5802. }
  5803. else if(IsEqualIID(iid, IID_IAdviseSink)) {
  5804. *ppv = (void *)(IAdviseSink *) this;
  5805. }
  5806. else {
  5807. *ppv = NULL;
  5808. hresult = E_NOINTERFACE;
  5809. }
  5810. }
  5811. else
  5812. hresult = E_INVALIDARG;
  5813. if(hresult == NOERROR)
  5814. ((IUnknown *) *ppv)->AddRef();
  5815. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::CAdvSinkImpl::QueryInterface(%lx)\n",
  5816. this, hresult));
  5817. return hresult;
  5818. }
  5819. //+-------------------------------------------------------------------------
  5820. //
  5821. // Member: CDefLink::CAdvSinkImpl::AddRef
  5822. //
  5823. // Synopsis: Increments export count
  5824. //
  5825. // Returns: ULONG; New export count
  5826. //
  5827. // History: dd-mmm-yy Author Comment
  5828. // 10-Jan-96 Gopalk Rewritten
  5829. //--------------------------------------------------------------------------
  5830. STDMETHODIMP_(ULONG) CDefLink::CAdvSinkImpl::AddRef( void )
  5831. {
  5832. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::CAdvSinkImpl::AddRef()\n",
  5833. this));
  5834. // Validation check
  5835. VDATEHEAP();
  5836. // Local variables
  5837. CDefLink *pDefLink = GETPPARENT(this, CDefLink, m_AdviseSink);
  5838. ULONG cExportCount;
  5839. // Increment export count
  5840. cExportCount = pDefLink->IncrementExportCount();
  5841. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::CAdvSinkImpl::AddRef(%ld)\n",
  5842. this, cExportCount));
  5843. return cExportCount;
  5844. }
  5845. //+-------------------------------------------------------------------------
  5846. //
  5847. // Member: CDefLink::CAdvSinkImpl::Release
  5848. //
  5849. // Synopsis: Decerement export count and potentially destroy the Link
  5850. //
  5851. // Returns: ULONG; New export count
  5852. //
  5853. // History: dd-mmm-yy Author Comment
  5854. // 10-Jan-96 Gopalk Rewritten
  5855. //--------------------------------------------------------------------------
  5856. STDMETHODIMP_(ULONG) CDefLink::CAdvSinkImpl::Release ( void )
  5857. {
  5858. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::CAdvSinkImpl::Release()\n",
  5859. this));
  5860. // Validation check
  5861. VDATEHEAP();
  5862. // Local variables
  5863. CDefLink *pDefLink = GETPPARENT(this, CDefLink, m_AdviseSink);
  5864. ULONG cExportCount;
  5865. // Decrement export count.
  5866. cExportCount = pDefLink->DecrementExportCount();
  5867. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::CAdvSinkImpl::Release(%ld)\n",
  5868. this, cExportCount));
  5869. return cExportCount;
  5870. }
  5871. //+-------------------------------------------------------------------------
  5872. //
  5873. // Member: CDefLink::CAdvSinkImpl::OnDataChange
  5874. //
  5875. // Synopsis: Updates time of change
  5876. //
  5877. // Arguments: [pFormatetc] -- Data format that changed
  5878. // [pStgmed] -- New data
  5879. //
  5880. // Returns: void
  5881. //
  5882. // History: dd-mmm-yy Author Comment
  5883. // 28-Jan-96 Gopalk Rewritten
  5884. //--------------------------------------------------------------------------
  5885. STDMETHODIMP_(void) CDefLink::CAdvSinkImpl::OnDataChange(FORMATETC *pFormatetc,
  5886. STGMEDIUM *pStgmed)
  5887. {
  5888. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::CAdvSinkImpl::OnDataChange(%p, %p)\n",
  5889. this, pFormatetc, pStgmed));
  5890. // Validation checks
  5891. VDATEHEAP();
  5892. // Local variable
  5893. CDefLink *pDefLink = GETPPARENT(this, CDefLink, m_AdviseSink);
  5894. // Assert that the wild card advise prompted this notification
  5895. Win4Assert(pFormatetc->cfFormat == NULL && pFormatetc->ptd == NULL &&
  5896. pFormatetc->dwAspect == -1 && pFormatetc->tymed == -1);
  5897. Win4Assert(pStgmed->tymed == TYMED_NULL);
  5898. // Update time of change for automatic links
  5899. if(!pDefLink->IsZombie() && pDefLink->m_dwUpdateOpt==OLEUPDATE_ALWAYS) {
  5900. // Stabilize
  5901. CRefStabilize stabilize(pDefLink);
  5902. pDefLink->SetUpdateTimes();
  5903. }
  5904. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::CAdvSinkImpl::OnDataChange()\n",
  5905. this));
  5906. return;
  5907. }
  5908. //+-------------------------------------------------------------------------
  5909. //
  5910. // Member: CDefLink::CAdvSinkImpl::OnViewChange
  5911. //
  5912. // Synopsis: Called when the view changes; should never be called for
  5913. // links
  5914. //
  5915. // Effects:
  5916. //
  5917. // Arguments: [aspects] -- drawing aspect
  5918. // [lindex] -- unused
  5919. //
  5920. // Requires:
  5921. //
  5922. // Returns: void
  5923. //
  5924. // Signals:
  5925. //
  5926. // Modifies:
  5927. //
  5928. // Derivation: IAdviseSink
  5929. //
  5930. // Algorithm:
  5931. //
  5932. // History: dd-mmm-yy Author Comment
  5933. // 21-Nov-94 alexgo memory optimization
  5934. // 20-Nov-93 alexgo 32bit port
  5935. //
  5936. // Notes:
  5937. //
  5938. //--------------------------------------------------------------------------
  5939. STDMETHODIMP_(void) CDefLink::CAdvSinkImpl::OnViewChange
  5940. (DWORD aspects, LONG lindex)
  5941. {
  5942. VDATEHEAP();
  5943. Assert(FALSE); // never received
  5944. }
  5945. //+-------------------------------------------------------------------------
  5946. //
  5947. // Member: CDefLink::CAdvSinkImpl::OnRename
  5948. //
  5949. // Synopsis: Updates internal monikers to the source object. Turns around
  5950. // and informs its advise sinks
  5951. //
  5952. // Arguments: [pmk] -- New moniker name
  5953. //
  5954. // Returns: void
  5955. //
  5956. // History: dd-mmm-yy Author Comment
  5957. // 28-Jan-96 Gopalk Rewritten
  5958. //--------------------------------------------------------------------------
  5959. STDMETHODIMP_(void) CDefLink::CAdvSinkImpl::OnRename(IMoniker *pmk)
  5960. {
  5961. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::CAdvSinkImpl::OnRename(%p)\n",
  5962. this, pmk));
  5963. // Validation check
  5964. VDATEHEAP();
  5965. // Local variable
  5966. CDefLink *pDefLink = GETPPARENT(this, CDefLink, m_AdviseSink);
  5967. if(!pDefLink->IsZombie()) {
  5968. CRefStabilize stabilize(pDefLink);
  5969. // Release old absolute moniker
  5970. if(pDefLink->m_pMonikerAbs)
  5971. pDefLink->m_pMonikerAbs->Release();
  5972. // Remember the new moniker
  5973. pDefLink->m_pMonikerAbs = pmk;
  5974. if(pmk) {
  5975. // AddRef the new moniker
  5976. pmk->AddRef();
  5977. //
  5978. // Enable tracking on the new moniker
  5979. // (this will get a new shellink if neccessary.)
  5980. //
  5981. #ifdef _TRACKLINK_
  5982. pDefLink->EnableTracking(pmk, OT_READTRACKINGINFO);
  5983. #endif
  5984. }
  5985. // Update relative moniker from the new absolute moniker
  5986. pDefLink->UpdateRelMkFromAbsMk(NULL);
  5987. // Name of the link source changed. This has no bearing on the
  5988. // name of the link object itself.
  5989. if(pDefLink->m_pCOAHolder)
  5990. pDefLink->m_pCOAHolder->SendOnLinkSrcChange(pmk);
  5991. }
  5992. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::CAdvSinkImpl::OnRename()\n",
  5993. this));
  5994. return;
  5995. }
  5996. //+-------------------------------------------------------------------------
  5997. //
  5998. // Member: CDefLink::CAdvSinkImpl::OnSave
  5999. //
  6000. // Synopsis: Updates cache and turns around and informs its advise sinks
  6001. //
  6002. // Arguments: None
  6003. //
  6004. // Returns: void
  6005. //
  6006. // History: dd-mmm-yy Author Comment
  6007. // 28-Jan-96 Gopalk Rewritten
  6008. //--------------------------------------------------------------------------
  6009. STDMETHODIMP_(void) CDefLink::CAdvSinkImpl::OnSave()
  6010. {
  6011. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::CAdvSinkImpl::OnSave()\n",
  6012. this));
  6013. // Validation check
  6014. VDATEHEAP();
  6015. // Local variable
  6016. CDefLink *pDefLink = GETPPARENT(this, CDefLink, m_AdviseSink);
  6017. if(!pDefLink->IsZombie()) {
  6018. // Stabilize
  6019. CRefStabilize stabilize(pDefLink);
  6020. // Turn around and send notification
  6021. if(pDefLink->m_pCOAHolder)
  6022. pDefLink->m_pCOAHolder->SendOnSave();
  6023. // Update presentations cached with ADVFCACHE_ONSAVE
  6024. pDefLink->UpdateAutoOnSave();
  6025. // Update clsid
  6026. pDefLink->UpdateUserClassID();
  6027. }
  6028. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::CAdvSinkImpl::OnSave()\n",
  6029. this));
  6030. return;
  6031. }
  6032. //+-------------------------------------------------------------------------
  6033. //
  6034. // Member: CDefLink::CAdvSinkImpl::OnClose
  6035. //
  6036. // Synopsis: Updates time of change and turns around and informs its
  6037. // advise sinks.
  6038. //
  6039. // Arguments: void
  6040. //
  6041. // Returns: void
  6042. //
  6043. // History: dd-mmm-yy Author Comment
  6044. // 28-Jan-96 Gopalk Rewritten
  6045. //--------------------------------------------------------------------------
  6046. STDMETHODIMP_(void) CDefLink::CAdvSinkImpl::OnClose(void)
  6047. {
  6048. LEDebugOut((DEB_TRACE, "%p _IN CDefLink::CAdvSinkImpl::OnClose()\n",
  6049. this));
  6050. // Validation check
  6051. VDATEHEAP();
  6052. // Local variable
  6053. CDefLink *pDefLink = GETPPARENT(this, CDefLink, m_AdviseSink);
  6054. if(!pDefLink->IsZombie()) {
  6055. // Stabilize
  6056. CRefStabilize stabilize(pDefLink);
  6057. // Update time of change
  6058. if(pDefLink->m_dwUpdateOpt == OLEUPDATE_ALWAYS )
  6059. pDefLink->SetUpdateTimes();
  6060. // Turn around and send notification
  6061. if(pDefLink->m_pCOAHolder)
  6062. pDefLink->m_pCOAHolder->SendOnClose();
  6063. // To be safe, unbind source
  6064. pDefLink->UnbindSource();
  6065. }
  6066. LEDebugOut((DEB_TRACE, "%p OUT CDefLink::CAdvSinkImpl::OnClose()\n",
  6067. this));
  6068. return;
  6069. }
  6070. /*
  6071. * IMPLEMENTATION of OleItemContainer methods
  6072. */
  6073. //+-------------------------------------------------------------------------
  6074. //
  6075. // Member: CDefLink::GetOleItemContainerDelegate (private)
  6076. //
  6077. // Synopsis: gets the IOleItemContainer from the interface
  6078. //
  6079. // Effects:
  6080. //
  6081. // Arguments: void
  6082. //
  6083. // Requires:
  6084. //
  6085. // Returns: IOleItemContainer *
  6086. //
  6087. // Signals:
  6088. //
  6089. // Modifies:
  6090. //
  6091. // Derivation:
  6092. //
  6093. // Algorithm:
  6094. //
  6095. // History: dd-mmm-yy Author Comment
  6096. //
  6097. // Notes:
  6098. // This function may return misleading information if the
  6099. // server has died (i.e., you'll return a pointer to a cached
  6100. // interface proxy). It is the responsibility of the caller
  6101. // to handler server crashes.
  6102. //
  6103. //--------------------------------------------------------------------------
  6104. INTERNAL_(IOleItemContainer *) CDefLink::GetOleItemContainerDelegate(void)
  6105. {
  6106. IOleItemContainer *pOleItemContainerDelegate;
  6107. VDATEHEAP();
  6108. LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::GetOleItemContainerDelegate "
  6109. "( )\n", this ));
  6110. // if we're zombied, then we don't want to QI for a new interface!!
  6111. if(!IsZombie())
  6112. {
  6113. DuCacheDelegate(&(m_pUnkDelegate),
  6114. IID_IOleItemContainer, (LPLPVOID)&m_pOleItemContainerDelegate, NULL);
  6115. pOleItemContainerDelegate = m_pOleItemContainerDelegate;
  6116. #if DBG == 1
  6117. if( m_pOleItemContainerDelegate )
  6118. {
  6119. Assert(m_pUnkDelegate);
  6120. }
  6121. #endif // DBG == 1
  6122. }
  6123. else
  6124. {
  6125. m_pOleItemContainerDelegate = NULL;
  6126. }
  6127. LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::GetOleItemContainerDelegate "
  6128. "( %p )\n", this, pOleItemContainerDelegate));
  6129. return m_pOleItemContainerDelegate;
  6130. }
  6131. //+-------------------------------------------------------------------------
  6132. //
  6133. // Member: CDefLink::ReleaseOleItemContainerDelegate (private)
  6134. //
  6135. // Synopsis: Releases the OleItemContainer pointer to the server
  6136. //
  6137. // Effects:
  6138. //
  6139. // Arguments: void
  6140. //
  6141. // Requires:
  6142. //
  6143. // Returns: void
  6144. //
  6145. // Signals:
  6146. //
  6147. // Modifies:
  6148. //
  6149. // Derivation:
  6150. //
  6151. // Algorithm:
  6152. //
  6153. // History: dd-mmm-yy Author Comment
  6154. //
  6155. // Notes:
  6156. //
  6157. //--------------------------------------------------------------------------
  6158. INTERNAL_(void) CDefLink::ReleaseOleItemContainerDelegate(void)
  6159. {
  6160. VDATEHEAP();
  6161. LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::ReleaseOleItemContainerDelegate "
  6162. "( )\n", this ));
  6163. if (m_pOleItemContainerDelegate)
  6164. {
  6165. SafeReleaseAndNULL((IUnknown **)&m_pOleItemContainerDelegate);
  6166. }
  6167. LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::ReleaseOleItemContainerDelegate "
  6168. "( )\n", this ));
  6169. }
  6170. //+-------------------------------------------------------------------------
  6171. //
  6172. // Member: CDefLink::Dump, public (_DEBUG only)
  6173. //
  6174. // Synopsis: return a string containing the contents of the data members
  6175. //
  6176. // Effects:
  6177. //
  6178. // Arguments: [ppszDump] - an out pointer to a null terminated character array
  6179. // [ulFlag] - flag determining prefix of all newlines of the
  6180. // out character array (default is 0 - no prefix)
  6181. // [nIndentLevel] - will add a indent prefix after the other prefix
  6182. // for ALL newlines (including those with no prefix)
  6183. //
  6184. // Requires:
  6185. //
  6186. // Returns: HRESULT
  6187. //
  6188. // Signals:
  6189. //
  6190. // Modifies: [ppszDump] - argument
  6191. //
  6192. // Derivation:
  6193. //
  6194. // Algorithm: use dbgstream to create a string containing information on the
  6195. // content of data structures
  6196. //
  6197. // History: dd-mmm-yy Author Comment
  6198. // 01-Feb-95 t-ScottH author
  6199. //
  6200. // Notes:
  6201. //
  6202. //--------------------------------------------------------------------------
  6203. #ifdef _DEBUG
  6204. HRESULT CDefLink::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
  6205. {
  6206. int i;
  6207. char *pszPrefix;
  6208. char *pszCSafeRefCount;
  6209. char *pszCThreadCheck;
  6210. char *pszCLSID;
  6211. char *pszCOleCache;
  6212. char *pszCOAHolder;
  6213. char *pszDAC;
  6214. char *pszFILETIME;
  6215. char *pszMonikerDisplayName;
  6216. dbgstream dstrPrefix;
  6217. dbgstream dstrDump(5000);
  6218. // determine prefix of newlines
  6219. if ( ulFlag & DEB_VERBOSE )
  6220. {
  6221. dstrPrefix << this << " _VB ";
  6222. }
  6223. // determine indentation prefix for all newlines
  6224. for (i = 0; i < nIndentLevel; i++)
  6225. {
  6226. dstrPrefix << DUMPTAB;
  6227. }
  6228. pszPrefix = dstrPrefix.str();
  6229. // put data members in stream
  6230. pszCThreadCheck = DumpCThreadCheck((CThreadCheck *)this, ulFlag, nIndentLevel + 1);
  6231. dstrDump << pszPrefix << "CThreadCheck:" << endl;
  6232. dstrDump << pszCThreadCheck;
  6233. CoTaskMemFree(pszCThreadCheck);
  6234. // only vtable pointers (plus we don't get the right address in debugger extensions)
  6235. // dstrDump << pszPrefix << "&IUnknown = " << &m_Unknown << endl;
  6236. // dstrDump << pszPrefix << "&IAdviseSink = " << &m_AdviseSink << endl;
  6237. dstrDump << pszPrefix << "Link flags = ";
  6238. if (m_flags & DL_SAME_AS_LOAD)
  6239. {
  6240. dstrDump << "DL_SAME_AS_LOAD ";
  6241. }
  6242. if (m_flags & DL_NO_SCRIBBLE_MODE)
  6243. {
  6244. dstrDump << "DL_NO_SCRIBBLE_MODE ";
  6245. }
  6246. if (m_flags & DL_DIRTY_LINK)
  6247. {
  6248. dstrDump << "DL_DIRTY_LINK ";
  6249. }
  6250. if (m_flags & DL_LOCKED_CONTAINER)
  6251. {
  6252. dstrDump << "DL_LOCKED_CONTAINER ";
  6253. }
  6254. // if none of the flags are set...
  6255. if ( !( (m_flags & DL_SAME_AS_LOAD) |
  6256. (m_flags & DL_LOCKED_CONTAINER) |
  6257. (m_flags & DL_NO_SCRIBBLE_MODE) |
  6258. (m_flags & DL_DIRTY_LINK)))
  6259. {
  6260. dstrDump << "No FLAGS SET!";
  6261. }
  6262. dstrDump << "(" << LongToPtr(m_flags) << ")" << endl;
  6263. dstrDump << pszPrefix << "pIOleObject Delegate = " << m_pOleDelegate << endl;
  6264. dstrDump << pszPrefix << "pIDataObject Delegate = " << m_pDataDelegate << endl;
  6265. dstrDump << pszPrefix << "pIRunnableObject Delegate = " << m_pRODelegate << endl;
  6266. dstrDump << pszPrefix << "No. of Refs. on Link = " << m_cRefsOnLink << endl;
  6267. dstrDump << pszPrefix << "pIUnknown pUnkOuter = ";
  6268. if (m_flags & DL_AGGREGATED)
  6269. {
  6270. dstrDump << "AGGREGATED (" << m_pUnkOuter << ")" << endl;
  6271. }
  6272. else
  6273. {
  6274. dstrDump << "NO AGGREGATION (" << m_pUnkOuter << ")" << endl;
  6275. }
  6276. dstrDump << pszPrefix << "pIMoniker Absolute = " << m_pMonikerAbs << endl;
  6277. if (m_pMonikerAbs != NULL)
  6278. {
  6279. pszMonikerDisplayName = DumpMonikerDisplayName(m_pMonikerAbs);
  6280. dstrDump << pszPrefix << "pIMoniker Absolute = ";
  6281. dstrDump << pszMonikerDisplayName;
  6282. dstrDump << "( " << m_pMonikerAbs << " )" << endl;
  6283. CoTaskMemFree(pszMonikerDisplayName);
  6284. }
  6285. else
  6286. {
  6287. dstrDump << pszPrefix << "pIMoniker Absolute = NULL or unable to resolve" << endl;
  6288. }
  6289. if (m_pMonikerRel != NULL)
  6290. {
  6291. pszMonikerDisplayName = DumpMonikerDisplayName(m_pMonikerRel);
  6292. dstrDump << pszPrefix << "pIMoniker Relative = ";
  6293. dstrDump << pszMonikerDisplayName;
  6294. dstrDump << "( " << m_pMonikerRel << " )" << endl;
  6295. CoTaskMemFree(pszMonikerDisplayName);
  6296. }
  6297. else
  6298. {
  6299. dstrDump << pszPrefix << "pIMoniker Absolute = NULL or unable to resolve" << endl;
  6300. }
  6301. dstrDump << pszPrefix << "pIUnknown Delegate = " << m_pUnkDelegate << endl;
  6302. dstrDump << pszPrefix << "OLEUPDATE flags = ";
  6303. if (m_dwUpdateOpt & OLEUPDATE_ALWAYS)
  6304. {
  6305. dstrDump << "OLEUPDATE_ALWAYS ";
  6306. }
  6307. else if (m_dwUpdateOpt & OLEUPDATE_ONCALL)
  6308. {
  6309. dstrDump << "OLEUPDATE_ONCALL ";
  6310. }
  6311. else
  6312. {
  6313. dstrDump << "No FLAGS SET!";
  6314. }
  6315. dstrDump << "(" << LongToPtr(m_flags) << ")" << endl;
  6316. pszCLSID = DumpCLSID(m_clsid);
  6317. dstrDump << pszPrefix << "Last known CLSID of link = " << pszCLSID << endl;
  6318. CoTaskMemFree(pszCLSID);
  6319. dstrDump << pszPrefix << "pIStorage = " << m_pStg << endl;
  6320. if (m_pCOleCache != NULL)
  6321. {
  6322. // pszCOleCache = DumpCOleCache(m_pCOleCache, ulFlag, nIndentLevel + 1);
  6323. dstrDump << pszPrefix << "COleCache: " << endl;
  6324. // dstrDump << pszCOleCache;
  6325. // CoTaskMemFree(pszCOleCache);
  6326. }
  6327. else
  6328. {
  6329. dstrDump << pszPrefix << "pCOleCache = " << m_pCOleCache << endl;
  6330. }
  6331. if (m_pCOAHolder != NULL)
  6332. {
  6333. pszCOAHolder = DumpCOAHolder(m_pCOAHolder, ulFlag, nIndentLevel + 1);
  6334. dstrDump << pszPrefix << "COAHolder: " << endl;
  6335. dstrDump << pszCOAHolder;
  6336. CoTaskMemFree(pszCOAHolder);
  6337. }
  6338. else
  6339. {
  6340. dstrDump << pszPrefix << "pCOAHolder = " << m_pCOAHolder << endl;
  6341. }
  6342. dstrDump << pszPrefix << "OLE Connection Advise ID = " << m_dwConnOle << endl;
  6343. if (m_pDataAdvCache != NULL)
  6344. {
  6345. pszDAC = DumpCDataAdviseCache(m_pDataAdvCache, ulFlag, nIndentLevel + 1);
  6346. dstrDump << pszPrefix << "CDataAdviseCache: " << endl;
  6347. dstrDump << pszDAC;
  6348. CoTaskMemFree(pszDAC);
  6349. }
  6350. else
  6351. {
  6352. dstrDump << pszPrefix << "pCDataAdviseCache = " << m_pDataAdvCache << endl;
  6353. }
  6354. dstrDump << pszPrefix << "pIOleClientSite = " << m_pAppClientSite << endl;
  6355. dstrDump << pszPrefix << "Connection for time = " << m_dwConnTime << endl;
  6356. pszFILETIME = DumpFILETIME(&m_ltChangeOfUpdate);
  6357. dstrDump << pszPrefix << "Change of update filetime = " << pszFILETIME << endl;
  6358. CoTaskMemFree(pszFILETIME);
  6359. pszFILETIME = DumpFILETIME(&m_ltKnownUpToDate);
  6360. dstrDump << pszPrefix << "Known up to date filetime = " << pszFILETIME << endl;
  6361. CoTaskMemFree(pszFILETIME);
  6362. pszFILETIME = DumpFILETIME(&m_rtUpdate);
  6363. dstrDump << pszPrefix << "Update filetime = " << pszFILETIME << endl;
  6364. CoTaskMemFree(pszFILETIME);
  6365. // cleanup and provide pointer to character array
  6366. *ppszDump = dstrDump.str();
  6367. if (*ppszDump == NULL)
  6368. {
  6369. *ppszDump = UtDupStringA(szDumpErrorMessage);
  6370. }
  6371. CoTaskMemFree(pszPrefix);
  6372. return NOERROR;
  6373. }
  6374. #endif // _DEBUG
  6375. //+-------------------------------------------------------------------------
  6376. //
  6377. // Function: DumpCDefLink, public (_DEBUG only)
  6378. //
  6379. // Synopsis: calls the CDefLink::Dump method, takes care of errors and
  6380. // returns the zero terminated string
  6381. //
  6382. // Effects:
  6383. //
  6384. // Arguments: [pDL] - pointer to CDefLink
  6385. // [ulFlag] - flag determining prefix of all newlines of the
  6386. // out character array (default is 0 - no prefix)
  6387. // [nIndentLevel] - will add a indent prefix after the other prefix
  6388. // for ALL newlines (including those with no prefix)
  6389. //
  6390. // Requires:
  6391. //
  6392. // Returns: character array of structure dump or error (null terminated)
  6393. //
  6394. // Signals:
  6395. //
  6396. // Modifies:
  6397. //
  6398. // Algorithm:
  6399. //
  6400. // History: dd-mmm-yy Author Comment
  6401. // 01-Feb-95 t-ScottH author
  6402. //
  6403. // Notes:
  6404. //
  6405. //--------------------------------------------------------------------------
  6406. #ifdef _DEBUG
  6407. char *DumpCDefLink(CDefLink *pDL, ULONG ulFlag, int nIndentLevel)
  6408. {
  6409. HRESULT hresult;
  6410. char *pszDump;
  6411. if (pDL == NULL)
  6412. {
  6413. return UtDupStringA(szDumpBadPtr);
  6414. }
  6415. hresult = pDL->Dump(&pszDump, ulFlag, nIndentLevel);
  6416. if (hresult != NOERROR)
  6417. {
  6418. CoTaskMemFree(pszDump);
  6419. return DumpHRESULT(hresult);
  6420. }
  6421. return pszDump;
  6422. }
  6423. #endif // _DEBUG