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.

4738 lines
146 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File:
  4. // olecache.cpp
  5. //
  6. // Contents:
  7. // Ole default presentation cache implementation
  8. //
  9. // Classes:
  10. // COleCache - ole multiple presentation cache
  11. // CCacheEnum - enumerator for COleCache
  12. //
  13. // Functions:
  14. // CreateDataCache
  15. //
  16. // History:
  17. // 04-Sep-96 Gopalk Completly rewritten to delay load cache using
  18. // Table of Contents written at the end of
  19. // Presentation steam 0
  20. // 31-Jan-95 t-ScottH add Dump methods to COleCache
  21. // CCacheEnum
  22. // CCacheEnumFormatEtc
  23. // add the following APIs: DumpCOleCache
  24. // DumpCCacheEnum
  25. // DumpCCacheEnumFormatEtc
  26. // moved CCacheEnumFormatEtc def'n to header file
  27. // added flag to COLECACHEFLAGS to indicate aggregation
  28. // (_DEBUG only)
  29. // 01/09/95 - t-ScottH - change VDATETHREAD to accept a this
  30. // pointer, and added VDATETHREAD to IViewObject:: methods
  31. // (COleCache::CCacheViewImpl:: )
  32. // 03/01/94 - AlexGo - Added call tracing to AddRef/Release
  33. // implementations
  34. // 02/08/94 - ChrisWe - 7297: need implementation of
  35. // FORMATETC enumerator
  36. // 01/24/94 alexgo first pass at converting to Cairo-style
  37. // memory allocation
  38. // 01/11/94 - AlexGo - added VDATEHEAP macros to every function
  39. // and method.
  40. // 12/10/93 - AlexT - header file clean up, include ole1cls.h
  41. // 12/09/93 - ChrisWe - incremented pointer in COleCache::GetNext()
  42. // 11/30/93 - alexgo - fixed bugs with GETPPARENT usage
  43. // 11/23/93 - ChrisWe - introduce use of CACHEID_NATIVE,
  44. // CACHEID_GETNEXT_GETALL, CACHEID_GETNEXT_GETALLBUTNATIVE
  45. // for documentary purposes
  46. // 11/22/93 - ChrisWe - replace overloaded ==, != with
  47. // IsEqualIID and IsEqualCLSID
  48. // 07/04/93 - SriniK - Added the support for reading PBrush,
  49. // MSDraw native objects, hence avoid creating
  50. // presentation cache/stream. Also started writing static
  51. // object data into "OLE_CONTENTS" stream in placeable
  52. // metafile format for static metafile and DIB File
  53. // format for static dibs. This enabled me to provide
  54. // support for converting static objects. Also added code
  55. // to support converting static metafile to MSDraw object
  56. // and static DIB to PBrush object.
  57. // 06/04/93 - SriniK - Added the support for demand loading and
  58. // discarding the caches.
  59. // 11/12/92 - SriniK - created
  60. //
  61. //-----------------------------------------------------------------------------
  62. #include <le2int.h>
  63. #include <olepres.h>
  64. #include <ole1cls.h>
  65. #include <olecache.h>
  66. #include "enumtors.h"
  67. #ifndef WIN32
  68. #ifndef _MAC
  69. const LONG lMaxSmallInt = 32767;
  70. const LONG lMinSmallInt = -32768;
  71. #else
  72. #ifdef MAC_REVIEW
  73. Review IS_SMALL_INT.
  74. #endif
  75. #include <limits.h>
  76. #define lMaxSmallInt SHRT_MAX
  77. #define lMinSmallInt SHRT_MIN
  78. #endif
  79. #define IS_SMALL_INT(lVal) \
  80. ((HIWORD(lVal) && ((lVal > lMaxSmallInt) || (lVal < lMinSmallInt))) \
  81. ? FALSE : TRUE)
  82. #endif // WIN32
  83. #define FREEZE_CONSTANT 143 // Used by Freeze() and Unfreeze()
  84. // This was the original code...
  85. /*
  86. #define VERIFY_TYMED_SINGLE_VALID_FOR_CLIPFORMAT(pfetc) {\
  87. if ((pfetc->cfFormat==CF_METAFILEPICT && pfetc->tymed!=TYMED_MFPICT)\
  88. || ( (pfetc->cfFormat==CF_BITMAP || \
  89. pfetc->cfFormat == CF_DIB ) \
  90. && pfetc->tymed!=TYMED_GDI)\
  91. || (pfetc->cfFormat!=CF_METAFILEPICT && \
  92. pfetc->cfFormat!=CF_BITMAP && \
  93. pfetc->cfFormat!=CF_DIB && \
  94. pfetc->tymed!=TYMED_HGLOBAL)) \
  95. return ResultFromScode(DV_E_TYMED); \
  96. }
  97. */
  98. //+----------------------------------------------------------------------------
  99. //
  100. // Function:
  101. // CheckTymedCFCombination (Internal)
  102. //
  103. // Synopsis:
  104. // Verifies that the combination of clipformat and tymed is
  105. // valid to the cache.
  106. //
  107. // Arguments:
  108. // [pfetc] -- The candidate FORMATETC
  109. //
  110. // Returns:
  111. // S_OK For a valid combination
  112. // CACHE_S_FORMATETC_NOTSUPPORTED For a combination which can be
  113. // cached, but not drawn by the cache
  114. // DV_E_TYMED For all other combinations
  115. //
  116. // Rules:
  117. //
  118. // 1> (CMF && TMF) || (CEM && TEM) || (CB && TG) || (CD && TH) => S_OK
  119. // (TH && ~CD) => CACHE_S_FORMATETC_NOTSUPPORTED
  120. //
  121. // 2> (~S_OK && ~CACHE_S_FORMATETC_NOTSUPPORTED) => DV_E_TYMED
  122. //
  123. // Where: CMF == CF_METAFILEPICT
  124. // CEM == CF_ENHMETAFILE
  125. // CB == CF_BITMAP
  126. // CD == CF_FIB
  127. // TMF == TYMED_MFPICT
  128. // TEM == TYMED_ENHMETAFILE
  129. // TG == TYMED_GDI
  130. // TH == TYMED_HGLOBAL
  131. //
  132. // Notes:
  133. // Since CACHE_S_FORMATETC_NOTSUPPORTED was never implemented in
  134. // 16-bit, we return S_OK in its place if we are in the WOW.
  135. //
  136. // History:
  137. // 01/07/94 DavePl Created
  138. //
  139. //-----------------------------------------------------------------------------
  140. INTERNAL_(HRESULT) CheckTymedCFCombination(LPFORMATETC pfetc)
  141. {
  142. HRESULT hr;
  143. // CF_METAFILEPICT on TYMED_MFPICT is a valid combination
  144. if (pfetc->cfFormat == CF_METAFILEPICT && pfetc->tymed == TYMED_MFPICT)
  145. {
  146. hr = S_OK;
  147. }
  148. // CF_ENHMETAFILE on TYMED_ENHMF is a valid combination
  149. else if (pfetc->cfFormat == CF_ENHMETAFILE && pfetc->tymed == TYMED_ENHMF)
  150. {
  151. hr = S_OK;
  152. }
  153. // CF_BITMAP on TYMED_GDI is a valid combination
  154. else if (pfetc->cfFormat == CF_BITMAP && pfetc->tymed == TYMED_GDI)
  155. {
  156. hr = S_OK;
  157. }
  158. // CF_DIB on TYMED_HGLOBAL is a valid combination
  159. else if (pfetc->cfFormat == CF_DIB && pfetc->tymed == TYMED_HGLOBAL)
  160. {
  161. hr = S_OK;
  162. }
  163. // Anything else on TYMED_HGLOBAL is valid, but we cannot draw it
  164. else if (pfetc->tymed == TYMED_HGLOBAL)
  165. {
  166. hr = IsWOWThread() ? S_OK : CACHE_S_FORMATETC_NOTSUPPORTED;
  167. }
  168. // Any other combination is invalid
  169. else
  170. {
  171. hr = DV_E_TYMED;
  172. }
  173. return hr;
  174. }
  175. //+----------------------------------------------------------------------------
  176. //
  177. // Function:
  178. // IsSameAsObjectFormatEtc, internal
  179. //
  180. // Synopsis:
  181. // REVIEW, checks to see if [lpforetc] is compatible with
  182. // [cfFormat]. If [lpforetc] doesn't have a format set,
  183. // sets it to cfFormat, which is then assumed to be
  184. // one of CF_METAFILEPICT, or CF_DIB.
  185. //
  186. // Arguments:
  187. // [lpforetc] -- a pointer to a FORMATETC
  188. // [cfFormat] -- a clipboard format
  189. //
  190. // Returns:
  191. // DV_E_ASPECT, if the aspect isn't DVASPECT_CONTENT
  192. // DV_E_LINDEX, DV_E_CLIPFORMAT if the lindex or clipboard
  193. // formats don't match
  194. // S_OK
  195. //
  196. // Notes:
  197. //
  198. // History:
  199. // 11/28/93 - ChrisWe - file inspection and cleanup
  200. //
  201. //-----------------------------------------------------------------------------
  202. INTERNAL IsSameAsObjectFormatEtc(LPFORMATETC lpforetc, CLIPFORMAT cfFormat)
  203. {
  204. VDATEHEAP();
  205. // this function only checks for DVASPECT_CONTENT
  206. if (lpforetc->dwAspect != DVASPECT_CONTENT)
  207. return ResultFromScode(DV_E_DVASPECT);
  208. // is the lindex right?
  209. if (lpforetc->lindex != DEF_LINDEX)
  210. return ResultFromScode(DV_E_LINDEX);
  211. // if there's no format, set it to CF_METAFILEPICT or CF_DIB
  212. if(lpforetc->cfFormat == NULL) {
  213. lpforetc->cfFormat = cfFormat;
  214. if(lpforetc->cfFormat == CF_METAFILEPICT) {
  215. lpforetc->tymed = TYMED_MFPICT;
  216. }
  217. #ifdef FULL_EMF_SUPPORT
  218. else if (lpforetc->cfFormat == CF_ENHMETAFILE) {
  219. lpforetc->tymed = TYMED_ENHMF;
  220. }
  221. #endif
  222. else {
  223. lpforetc->tymed = TYMED_HGLOBAL;
  224. }
  225. }
  226. else
  227. {
  228. // if it's CF_BITMAP, change it to CF_DIB
  229. BITMAP_TO_DIB((*lpforetc));
  230. // compare the two formats
  231. if (lpforetc->cfFormat != cfFormat)
  232. return ResultFromScode(DV_E_CLIPFORMAT);
  233. }
  234. // if we got here, the two formats are [interchangeable?]
  235. return NOERROR;
  236. }
  237. //+----------------------------------------------------------------------------
  238. //
  239. // Function:
  240. // CreateDataCache, public
  241. //
  242. // Synopsis:
  243. // Creates an instance of the default presentation cache used by Ole.
  244. //
  245. // Arguments:
  246. // [pUnkOuter] [in] -- pointer to outer unknown, if this is being
  247. // aggregated
  248. // [rclsid] [in] -- the class that the cache should assume
  249. // [iid] [in] -- the interface the user would like returned
  250. // [ppv] [out] -- pointer to return the requested interface
  251. //
  252. // Returns:
  253. // E_OUTOFMEMORY, S_OK
  254. //
  255. // History:
  256. // Gopalk Rewritten Sep 04, 96
  257. //
  258. //-----------------------------------------------------------------------------
  259. #pragma SEG(CreateDataCache)
  260. STDAPI CreateDataCache(IUnknown* pUnkOuter, REFCLSID rclsid, REFIID iid,
  261. LPVOID* ppv)
  262. {
  263. OLETRACEIN((API_CreateDataCache,
  264. PARAMFMT("pUnkOuter= %p, rclsid= %I, iid= %I, ppv= %p"),
  265. pUnkOuter, &rclsid, &iid, ppv));
  266. VDATEHEAP();
  267. // Local variables
  268. HRESULT error = NOERROR;
  269. COleCache* pOleCache = NULL;
  270. // Check if being aggregated
  271. if(pUnkOuter) {
  272. // Validate the interface and IID requested
  273. if(!IsValidInterface(pUnkOuter) || !IsEqualIID(iid, IID_IUnknown))
  274. error = ResultFromScode(E_INVALIDARG);
  275. }
  276. // Check that a valid out pointer has been passed
  277. if(!IsValidPtrOut(ppv, sizeof(LPVOID)))
  278. error = ResultFromScode(E_INVALIDARG);
  279. if(error == NOERROR) {
  280. // Create new cache
  281. pOleCache = (COleCache *) new COleCache(pUnkOuter,
  282. rclsid,
  283. COLECACHEF_APICREATE);
  284. if(pOleCache && !pOleCache->IsOutOfMemory()) {
  285. if(pUnkOuter) {
  286. // We're being aggregated, return private IUnknown
  287. *ppv = (void *)(IUnknown *)&pOleCache->m_UnkPrivate;
  288. }
  289. else {
  290. // Get requested interface on cache
  291. error = pOleCache->QueryInterface(iid, ppv);
  292. // Release the local pointer because the
  293. // refcount is currently 2
  294. if(error == NOERROR)
  295. pOleCache->Release();
  296. }
  297. }
  298. else
  299. error = ResultFromScode(E_OUTOFMEMORY);
  300. }
  301. // If something has gone wrong, clean up
  302. if(error != NOERROR) {
  303. if(pOleCache)
  304. pOleCache->Release();
  305. }
  306. OLETRACEOUT((API_CreateDataCache, error));
  307. return error;
  308. }
  309. //+----------------------------------------------------------------------------
  310. //
  311. // Member:
  312. // COleCache::COleCache, public
  313. //
  314. // Synopsis:
  315. // Constructor
  316. //
  317. // Arguments:
  318. // [pUnkOuter] [in] -- outer unknown, if being aggregated
  319. // [rclsid] [in] -- the class id the cache should assume
  320. //
  321. // Notes:
  322. // Constructs an instance of presentation cache
  323. //
  324. // History:
  325. // Gopalk Rewritten Sep 04, 96
  326. //
  327. //-----------------------------------------------------------------------------
  328. #pragma SEG(COleCache_ctor)
  329. COleCache::COleCache(IUnknown* pUnkOuter, REFCLSID rclsid, DWORD dwCreateFlag) :
  330. CRefExportCount(pUnkOuter)
  331. {
  332. // Set reference count for return from constructor
  333. SafeAddRef();
  334. // Initialize flags
  335. Win4Assert(dwCreateFlag==0 || dwCreateFlag==COLECACHEF_APICREATE);
  336. m_ulFlags = COLECACHEF_LOADEDSTATE | dwCreateFlag; //fresh cache!
  337. // Set m_pUnkOuter appropriately
  338. if(pUnkOuter) {
  339. m_pUnkOuter = pUnkOuter;
  340. // This is for the debugger extensions
  341. // (since we cannot compare m_pUnkOuter to m_pUnkPrivate with copied mem)
  342. // it is only used in the ::Dump method
  343. #ifdef _DEBUG
  344. m_ulFlags |= COLECACHEF_AGGREGATED;
  345. #endif // _DEBUG
  346. }
  347. else {
  348. m_pUnkOuter = &m_UnkPrivate;
  349. }
  350. // Create the CacheNode Array object
  351. m_pCacheArray = CArray<CCacheNode>::CreateArray(5,1);
  352. if(!m_pCacheArray) {
  353. m_ulFlags |= COLECACHEF_OUTOFMEMORY;
  354. return;
  355. }
  356. // Initialize storage
  357. m_pStg = NULL;
  358. // Initialize IViewObject advise sink
  359. m_pViewAdvSink = NULL;
  360. m_advfView = 0;
  361. m_aspectsView = 0;
  362. // Initialize frozen aspects
  363. m_dwFrozenAspects = NULL;
  364. // Initialize data object
  365. m_pDataObject = NULL;
  366. // Initialize CLSID and cfFormat
  367. m_clsid = rclsid;
  368. m_cfFormat = NULL;
  369. // Update flags based on the clsid
  370. if(IsEqualCLSID(m_clsid, CLSID_StaticMetafile)) {
  371. m_cfFormat = CF_METAFILEPICT;
  372. m_ulFlags |= COLECACHEF_STATIC | COLECACHEF_FORMATKNOWN;
  373. }
  374. else if(IsEqualCLSID(m_clsid, CLSID_StaticDib)) {
  375. m_cfFormat = CF_DIB;
  376. m_ulFlags |= COLECACHEF_STATIC | COLECACHEF_FORMATKNOWN;
  377. }
  378. else if(IsEqualCLSID(m_clsid, CLSID_PBrush)) {
  379. m_cfFormat = CF_DIB;
  380. m_ulFlags |= COLECACHEF_PBRUSHORMSDRAW | COLECACHEF_FORMATKNOWN;
  381. }
  382. else if(IsEqualCLSID(m_clsid, CLSID_MSDraw)) {
  383. m_cfFormat = CF_METAFILEPICT;
  384. m_ulFlags |= COLECACHEF_PBRUSHORMSDRAW | COLECACHEF_FORMATKNOWN;
  385. }
  386. else if(IsEqualCLSID(m_clsid, CLSID_Picture_EnhMetafile)) {
  387. m_cfFormat = CF_ENHMETAFILE;
  388. m_ulFlags |= COLECACHEF_STATIC | COLECACHEF_FORMATKNOWN;
  389. }
  390. else
  391. m_cfFormat = NULL;
  392. // If we can render native format of the cache, add native cache node
  393. if(m_cfFormat) {
  394. if (!UpdateCacheNodeForNative())
  395. m_ulFlags |= COLECACHEF_OUTOFMEMORY;
  396. else
  397. m_ulFlags &= ~COLECACHEF_LOADEDSTATE; // Native node has been added.
  398. }
  399. }
  400. //+----------------------------------------------------------------------------
  401. //
  402. // Member:
  403. // COleCache::~COleCache, public
  404. //
  405. // Synopsis:
  406. // Destructor
  407. //
  408. // Notes:
  409. // Destroys the presentation cache
  410. //
  411. // History:
  412. // Gopalk Rewritten Sep 04, 96
  413. //
  414. //-----------------------------------------------------------------------------
  415. #pragma SEG(COleCache_dtor)
  416. COleCache::~COleCache(void)
  417. {
  418. Win4Assert(m_ulFlags & COLECACHEF_CLEANEDUP);
  419. }
  420. //+----------------------------------------------------------------------------
  421. //
  422. // Member:
  423. // COleCache::CleanupFn, private
  424. //
  425. // Synopsis:
  426. // Cleanup function called before destruction
  427. //
  428. // Notes:
  429. // Performs necessary cleanup
  430. //
  431. // History:
  432. // Gopalk Creation Jan 21, 97
  433. //
  434. //-----------------------------------------------------------------------------
  435. void COleCache::CleanupFn(void)
  436. {
  437. // Release the cache array object
  438. if(m_pCacheArray) {
  439. if(m_pDataObject) {
  440. ULONG index;
  441. LPCACHENODE lpCacheNode;
  442. // This indicates that cache client has bad release logic
  443. Win4Assert(!"Ole Cache released while the server is running");
  444. // Tear down existing advise connections
  445. m_pCacheArray->Reset(index);
  446. while(lpCacheNode = m_pCacheArray->GetNext(index))
  447. lpCacheNode->TearDownAdviseConnection(m_pDataObject);
  448. }
  449. m_pCacheArray->Release();
  450. }
  451. // Release storage
  452. if (m_pStg)
  453. m_pStg->Release();
  454. // Release IViewObject advise sink
  455. if (m_pViewAdvSink) {
  456. m_pViewAdvSink->Release();
  457. m_pViewAdvSink = NULL;
  458. }
  459. // Set COLECACHEF_CLEANEDUP flag
  460. m_ulFlags |= COLECACHEF_CLEANEDUP;
  461. }
  462. //+----------------------------------------------------------------------------
  463. //
  464. // Member:
  465. // COleCache::QueryInterface, public
  466. //
  467. // Synopsis:
  468. // implements IUnknown::QueryInterface
  469. //
  470. // Arguments:
  471. // [iid] [in] -- IID of the desired interface
  472. // [ppv] [out] -- pointer to return the requested interface
  473. //
  474. // Returns:
  475. // E_NOINTERFACE if the requested interface is not available
  476. // otherwise S_OK
  477. //
  478. //
  479. // History:
  480. // Gopalk Rewritten Sep 04, 96
  481. //
  482. //-----------------------------------------------------------------------------
  483. #pragma SEG(COleCache_QueryInterface)
  484. STDMETHODIMP COleCache::QueryInterface(REFIID iid, LPVOID* ppv)
  485. {
  486. // Validation checks
  487. VDATEHEAP();
  488. VDATETHREAD(this);
  489. return(m_pUnkOuter->QueryInterface(iid, ppv));
  490. }
  491. //+----------------------------------------------------------------------------
  492. //
  493. // Member:
  494. // COleCache::AddRef, public
  495. //
  496. // Synopsis:
  497. // implements IUnknown::AddRef
  498. //
  499. // Arguments:
  500. // none
  501. //
  502. // Returns:
  503. // the object's reference count
  504. //
  505. // History:
  506. // Gopalk Rewritten Sep 04, 96
  507. //
  508. //-----------------------------------------------------------------------------
  509. #pragma SEG(COleCache_AddRef)
  510. STDMETHODIMP_(ULONG) COleCache::AddRef(void)
  511. {
  512. // Validation checks
  513. VDATEHEAP();
  514. if(!VerifyThreadId())
  515. return((ULONG) RPC_E_WRONG_THREAD);
  516. return(m_pUnkOuter->AddRef());
  517. }
  518. //+----------------------------------------------------------------------------
  519. //
  520. // Member:
  521. // COleCache::Release, public
  522. //
  523. // Synopsis:
  524. // implements IUnknown::Release
  525. //
  526. // Arguments:
  527. // none
  528. //
  529. // Returns:
  530. // the object's reference count
  531. //
  532. // History:
  533. // Gopalk Rewritten Sep 04, 96
  534. //
  535. //-----------------------------------------------------------------------------
  536. #pragma SEG(COleCache_Release)
  537. STDMETHODIMP_(ULONG) COleCache::Release(void)
  538. {
  539. // Validation checks
  540. VDATEHEAP();
  541. if(!VerifyThreadId())
  542. return((ULONG) RPC_E_WRONG_THREAD);
  543. return(m_pUnkOuter->Release());
  544. }
  545. //+----------------------------------------------------------------------------
  546. //
  547. // Member:
  548. // COleCache::GetExtent, public
  549. //
  550. // Synopsis:
  551. // Gets the size of the cached presentation for [dwAspect]. If
  552. // there are several, because of varied advise control flags,
  553. // such as ADVF_NODATA, ADVF_ONSTOP, ADVF_ONSAVE, etc., gets the
  554. // most up to date one
  555. //
  556. // Arguments:
  557. // [dwAspect] [in] -- the aspect for which the extents are needed
  558. // [lpsizel] [out] -- pointer to return the width and height
  559. //
  560. // Returns:
  561. // OLE_E_BLANK if the aspect is not found
  562. // otherwise S_OK
  563. //
  564. // History:
  565. // Gopalk Rewritten Sep 04, 96
  566. //
  567. //-----------------------------------------------------------------------------
  568. #pragma SEG(COleCache_GetExtent)
  569. INTERNAL COleCache::GetExtent(DWORD dwAspect, LPSIZEL lpsizel)
  570. {
  571. // Validation check
  572. VDATEHEAP();
  573. // New data type
  574. typedef enum tagCacheType {
  575. // These values are defined in order of least to best preferred, so that
  576. // numeric comparisons are valid; DO NOT REORDER
  577. CACHETYPE_NONE = 0,
  578. CACHETYPE_NODATA,
  579. CACHETYPE_ONSTOP,
  580. CACHETYPE_ONSAVE,
  581. CACHETYPE_NORMAL
  582. } CacheType;
  583. // local variables
  584. CCacheNode* pCacheNode; // pointer to cache node being examined
  585. CacheType iCacheType; // cache type of cache node being examined
  586. CacheType iCacheTypeSoFar; // best cache type so far
  587. const FORMATETC* pforetc; // format information for current node
  588. DWORD grfAdvf; // advise flags for current node
  589. SIZEL sizelTmp; // temp Sizel struct
  590. unsigned long index; // index used for enumerating m_pCacheArray
  591. // Initialize the sizel struct
  592. lpsizel->cx = 0;
  593. lpsizel->cy = 0;
  594. // Check to see if any cache nodes exist
  595. if (!m_pCacheArray->Length())
  596. return ResultFromScode(OLE_E_BLANK);
  597. // We want to return the extents of the cache node that has NORMAL
  598. // advise flags. If we don't find such a node then we will take the next
  599. // best available.
  600. m_pCacheArray->Reset(index);
  601. iCacheTypeSoFar = CACHETYPE_NONE;
  602. for(unsigned long i=0;i<m_pCacheArray->Length();i++) {
  603. // Get the next cache node
  604. pCacheNode = m_pCacheArray->GetNext(index);
  605. // pCacheNode cannot be null
  606. Win4Assert(pCacheNode);
  607. // Get the formatetc of the cache node
  608. pforetc = pCacheNode->GetFormatEtc();
  609. // Restrict cfFormat to those that cache can draw
  610. if((pforetc->cfFormat == CF_METAFILEPICT) ||
  611. (pforetc->cfFormat == CF_DIB) ||
  612. (pforetc->cfFormat == CF_ENHMETAFILE)) {
  613. // Obtain the advise flags
  614. grfAdvf = pCacheNode->GetAdvf();
  615. // Obtain the cachetype
  616. if(grfAdvf & ADVFCACHE_ONSAVE)
  617. iCacheType = CACHETYPE_ONSAVE;
  618. else if(grfAdvf & ADVF_NODATA)
  619. iCacheType = CACHETYPE_NODATA;
  620. else if(grfAdvf & ADVF_DATAONSTOP)
  621. iCacheType = CACHETYPE_ONSTOP;
  622. else
  623. iCacheType = CACHETYPE_NORMAL;
  624. if (iCacheType > iCacheTypeSoFar) {
  625. // Get the extents from the presentation object
  626. if((pCacheNode->GetExtent(dwAspect, &sizelTmp)) == NOERROR) {
  627. if(!(sizelTmp.cx == 0 && sizelTmp.cy == 0)) {
  628. // Update extents
  629. *lpsizel = sizelTmp;
  630. iCacheTypeSoFar = iCacheType;
  631. // If we have normal cache, break
  632. if(iCacheType == CACHETYPE_NORMAL)
  633. break;
  634. }
  635. }
  636. }
  637. }
  638. }
  639. if(lpsizel->cx == 0 || lpsizel->cy == 0)
  640. return ResultFromScode(OLE_E_BLANK);
  641. return NOERROR;
  642. }
  643. // Private methods of COleCache
  644. //+----------------------------------------------------------------------------
  645. //
  646. // Member:
  647. // COleCache::UpdateCacheNodeForNative, private
  648. //
  649. // Synopsis:
  650. // If a native cache node of different format already exists,
  651. // changes that node to a normal cache node and adds a native
  652. // cache node if cache can render the new native format
  653. //
  654. // Arguments:
  655. // none
  656. //
  657. // Returns:
  658. // pointer to the found, or newly created cache node. Will
  659. // return NULL if out of memory
  660. //
  661. // History:
  662. // Gopalk Creation Sep 04, 96
  663. //
  664. //-----------------------------------------------------------------------------
  665. INTERNAL_(LPCACHENODE)COleCache::UpdateCacheNodeForNative(void)
  666. {
  667. // Local variable
  668. ULONG index;
  669. LPCACHENODE lpCacheNode;
  670. FORMATETC foretc;
  671. // Check if a native cache has already been created
  672. lpCacheNode = m_pCacheArray->GetItem(1);
  673. if(lpCacheNode) {
  674. // Assert that we have storage now
  675. Win4Assert(m_pStg);
  676. Win4Assert(!lpCacheNode->GetStg());
  677. if(lpCacheNode->GetFormatEtc()->cfFormat != m_cfFormat) {
  678. // The native format has changed
  679. // Add the old native cache as a normal cache
  680. index = m_pCacheArray->AddItem(*lpCacheNode);
  681. if(index) {
  682. // Clear the advise connection of the old native cache
  683. if(m_pDataObject)
  684. lpCacheNode->ClearAdviseConnection();
  685. // Update the state on the new cache
  686. lpCacheNode = m_pCacheArray->GetItem(index);
  687. Win4Assert(lpCacheNode);
  688. lpCacheNode->MakeNormalCache();
  689. lpCacheNode->SetClsid(CLSID_NULL);
  690. }
  691. else {
  692. // We are out of memory
  693. if(m_pDataObject)
  694. lpCacheNode->TearDownAdviseConnection(m_pDataObject);
  695. }
  696. // Delete the old native cache
  697. m_pCacheArray->DeleteItem(1);
  698. lpCacheNode = NULL;
  699. }
  700. else {
  701. // Set the storage on the native cache node
  702. lpCacheNode->SetStg(m_pStg);
  703. }
  704. }
  705. if(!lpCacheNode) {
  706. // Add a new native cache if we can render the format
  707. if(m_cfFormat==CF_METAFILEPICT ||
  708. m_cfFormat==CF_DIB ||
  709. m_cfFormat==CF_ENHMETAFILE) {
  710. // Initialize the FormatEtc
  711. INIT_FORETC(foretc);
  712. foretc.cfFormat = m_cfFormat;
  713. if (foretc.cfFormat == CF_METAFILEPICT)
  714. foretc.tymed = TYMED_MFPICT;
  715. else if (foretc.cfFormat == CF_ENHMETAFILE)
  716. foretc.tymed = TYMED_ENHMF;
  717. else
  718. foretc.tymed = TYMED_HGLOBAL;
  719. // Create the native cache node
  720. CCacheNode CacheNode(&foretc, 0, NULL);
  721. if(m_pCacheArray->AddReservedItem(CacheNode, 1)) {
  722. lpCacheNode = m_pCacheArray->GetItem(1);
  723. // Update state on the native cache node
  724. lpCacheNode->MakeNativeCache();
  725. lpCacheNode->SetClsid(m_clsid);
  726. }
  727. }
  728. }
  729. return lpCacheNode;
  730. }
  731. //+----------------------------------------------------------------------------
  732. //
  733. // Member:
  734. // COleObject::FindObjectFormat, private
  735. //
  736. // Synopsis:
  737. // Determines the object's clipboard format from the storage
  738. // and updates native cache node
  739. //
  740. // Arguments:
  741. // [pstg] [in] -- pointer to storage
  742. //
  743. // History:
  744. // Gopalk Creation Sep 04, 96
  745. //
  746. //-----------------------------------------------------------------------------
  747. INTERNAL_(void) COleCache::FindObjectFormat(LPSTORAGE pstg)
  748. {
  749. // Local variables
  750. CLIPFORMAT cfFormat;
  751. CLSID clsid;
  752. ULONG ulFlags;
  753. // Intialize CLSID, clipboard format and cache flags
  754. cfFormat = NULL;
  755. ulFlags = 0;
  756. clsid = CLSID_NULL;
  757. // Determine the CLSID of the object that owns the storage
  758. if(SUCCEEDED(ReadClassStg(pstg, &clsid))) {
  759. // Update clipboard format and cache flags based on the clsid
  760. if(IsEqualCLSID(clsid, CLSID_StaticMetafile)) {
  761. cfFormat = CF_METAFILEPICT;
  762. ulFlags |= (COLECACHEF_STATIC | COLECACHEF_FORMATKNOWN);
  763. }
  764. else if(IsEqualCLSID(clsid, CLSID_StaticDib)) {
  765. cfFormat = CF_DIB;
  766. ulFlags |= (COLECACHEF_STATIC | COLECACHEF_FORMATKNOWN);
  767. }
  768. else if(IsEqualCLSID(clsid, CLSID_PBrush)) {
  769. cfFormat = CF_DIB;
  770. ulFlags |= (COLECACHEF_PBRUSHORMSDRAW | COLECACHEF_FORMATKNOWN);
  771. }
  772. else if(IsEqualCLSID(clsid, CLSID_MSDraw)) {
  773. cfFormat = CF_METAFILEPICT;
  774. ulFlags |= (COLECACHEF_PBRUSHORMSDRAW | COLECACHEF_FORMATKNOWN);
  775. }
  776. else if(IsEqualCLSID(clsid, CLSID_Picture_EnhMetafile)) {
  777. cfFormat = CF_ENHMETAFILE;
  778. ulFlags |= (COLECACHEF_STATIC | COLECACHEF_FORMATKNOWN);
  779. }
  780. }
  781. // Though we do not know the CLSID of the object that owns the storage,
  782. // we might understand its native format
  783. if(!cfFormat) {
  784. if(SUCCEEDED(ReadFmtUserTypeStg(pstg, &cfFormat, NULL))) {
  785. if(cfFormat==CF_METAFILEPICT || cfFormat==CF_DIB ||
  786. cfFormat==CF_ENHMETAFILE)
  787. ulFlags |= COLECACHEF_FORMATKNOWN;
  788. }
  789. else
  790. cfFormat = NULL;
  791. }
  792. // Update the native cache node
  793. if(cfFormat || m_cfFormat) {
  794. m_cfFormat = cfFormat;
  795. m_clsid = clsid;
  796. m_ulFlags &= ~COLECACHEF_NATIVEFLAGS;
  797. m_ulFlags |= ulFlags;
  798. UpdateCacheNodeForNative();
  799. }
  800. return;
  801. }
  802. // IOleCacheControl implementation
  803. //+----------------------------------------------------------------------------
  804. //
  805. // Member:
  806. // COleCache::OnRun, public
  807. //
  808. // Synopsis:
  809. // implements IOleCacheControl::OnRun
  810. //
  811. // Sets up advisory connections with the running object for
  812. // dynamically updating cached presentations
  813. //
  814. // Arguments:
  815. // [pDataObj] [in] -- IDataObject interface on the running object
  816. //
  817. // Returns:
  818. // S_OK or appropriate error code
  819. //
  820. // History:
  821. // Gopalk Rewritten Sep 04, 96
  822. //
  823. //-----------------------------------------------------------------------------
  824. #pragma SEG(COleCache_OnRun)
  825. STDMETHODIMP COleCache::OnRun(IDataObject* pDataObj)
  826. {
  827. // Validatation checks
  828. VDATEHEAP();
  829. VDATETHREAD(this);
  830. VDATEIFACE(pDataObj);
  831. // Local variables
  832. HRESULT rerror, error;
  833. PCACHENODE pCacheNode;
  834. unsigned long index;
  835. // Static objects cannot have a server
  836. Win4Assert(!(m_ulFlags & COLECACHEF_STATIC));
  837. // OnRun should be called after Load or InitNew
  838. if(!m_pStg) {
  839. LEDebugOut((DEB_WARN, "OnRun called without storage\n"));
  840. }
  841. // If we already have the data object, nothing more to do
  842. if(m_pDataObject) {
  843. Win4Assert(m_pDataObject==pDataObj);
  844. return NOERROR;
  845. }
  846. // Save the data object without ref counting
  847. m_pDataObject = pDataObj;
  848. // Set up advise connections on the data object for each
  849. // cached presentation including native cache. Gopalk
  850. m_pCacheArray->Reset(index);
  851. rerror = NOERROR;
  852. for(unsigned long i=0;i<m_pCacheArray->Length();i++) {
  853. // Get the next cache node
  854. pCacheNode = m_pCacheArray->GetNext(index);
  855. // pCacheNode cannot be null
  856. Win4Assert(pCacheNode);
  857. // Ask the cache node to set up the advise connection
  858. error = pCacheNode->SetupAdviseConnection(m_pDataObject,
  859. (IAdviseSink *) &m_AdviseSink);
  860. if(error != NOERROR)
  861. rerror = error;
  862. }
  863. return rerror;
  864. }
  865. //+----------------------------------------------------------------------------
  866. //
  867. // Member:
  868. // COleCache::OnStop, public
  869. //
  870. // Synopsis:
  871. // implements IOleCacheControl::OnStop
  872. //
  873. // Tears down the advisory connections set up running object
  874. //
  875. // Arguments:
  876. // none
  877. //
  878. // Returns:
  879. // S_OK or appropriate error code
  880. //
  881. // History:
  882. // Gopalk Rewritten Sep 04, 96
  883. //
  884. //-----------------------------------------------------------------------------
  885. #pragma SEG(COleCache_OnStop)
  886. STDMETHODIMP COleCache::OnStop()
  887. {
  888. // Validatation checks
  889. VDATEHEAP();
  890. VDATETHREAD(this);
  891. // Local variables
  892. HRESULT rerror, error;
  893. PCACHENODE pCacheNode;
  894. unsigned long index;
  895. // OnRun should have been called before OnStop
  896. if(!m_pDataObject)
  897. return E_UNEXPECTED;
  898. // Delete the advise connections on the data object for
  899. // each cached presentation established earlier. Gopalk
  900. m_pCacheArray->Reset(index);
  901. rerror = NOERROR;
  902. for(unsigned long i=0;i<m_pCacheArray->Length();i++) {
  903. // Get the next cache node
  904. pCacheNode = m_pCacheArray->GetNext(index);
  905. // pCacheNode cannot be null
  906. Win4Assert(pCacheNode);
  907. // Ask the cache node to tear down the advise connection
  908. error = pCacheNode->TearDownAdviseConnection(m_pDataObject);
  909. if(error != NOERROR)
  910. rerror = error;
  911. }
  912. // Reset m_pDataObject
  913. m_pDataObject = NULL;
  914. // Assert that the advise sink ref count has gone to zero
  915. // Win4Assert(!GetExportCount());
  916. return rerror;
  917. }
  918. //+----------------------------------------------------------------------------
  919. //
  920. // Member:
  921. // COleCache::OnCrash, public
  922. //
  923. // Synopsis:
  924. // Called by the default handler when the local server crashes or
  925. // disconnects with remote objects
  926. //
  927. // Arguments:
  928. // none
  929. //
  930. // Returns:
  931. // S_OK or appropriate error code
  932. //
  933. // History:
  934. // Gopalk Created Dec 07, 96
  935. //
  936. //-----------------------------------------------------------------------------
  937. HRESULT COleCache::OnCrash()
  938. {
  939. // Validatation checks
  940. VDATEHEAP();
  941. VDATETHREAD(this);
  942. // Local variables
  943. HRESULT rerror, error;
  944. PCACHENODE pCacheNode;
  945. unsigned long index;
  946. // OnRun should have been called before OnCrash
  947. if(!m_pDataObject)
  948. return E_UNEXPECTED;
  949. // Reset the advise connections on the data object for
  950. // each cached presentation established earlier. Gopalk
  951. m_pCacheArray->Reset(index);
  952. rerror = NOERROR;
  953. for(unsigned long i=0;i<m_pCacheArray->Length();i++) {
  954. // Get the next cache node
  955. pCacheNode = m_pCacheArray->GetNext(index);
  956. // pCacheNode cannot be null
  957. Win4Assert(pCacheNode);
  958. // Ask the cache node to reset the advise connection
  959. error = pCacheNode->TearDownAdviseConnection(NULL);
  960. if(error != NOERROR)
  961. rerror = error;
  962. }
  963. // Reset m_pDataObject
  964. m_pDataObject = NULL;
  965. // Discard cache
  966. DiscardCache(DISCARDCACHE_NOSAVE);
  967. // Server crashed or disconnected. Recover the references
  968. // placed by the server on the cache advise sink
  969. CoDisconnectObject((IUnknown *) &m_AdviseSink, 0);
  970. // Assert that the advise sink ref count has gone to zero
  971. // Win4Assert(!GetExportCount());
  972. return rerror;
  973. }
  974. // IOleCache implementation
  975. //+----------------------------------------------------------------------------
  976. //
  977. // Member:
  978. // COleCache::Cache, public
  979. //
  980. // Synopsis:
  981. // implementation of IOleCache::Cache
  982. //
  983. // The specified presentation is cached
  984. //
  985. // Arguments:
  986. // [lpforetcIn] [in] -- the presentation format to cache
  987. // [advf] [in] -- the advise control flags
  988. // [lpdwCacheId] [out] -- pointer to return the cache node id
  989. //
  990. // Returns:
  991. // HRESULT
  992. //
  993. // History:
  994. // Gopalk Rewritten Sep 04, 96
  995. //
  996. //-----------------------------------------------------------------------------
  997. #pragma SEG(COleCache_Cache)
  998. STDMETHODIMP COleCache::Cache(LPFORMATETC lpforetcIn, DWORD advf,
  999. LPDWORD lpdwCacheId)
  1000. {
  1001. // Validation checks
  1002. VDATEHEAP();
  1003. VDATETHREAD(this);
  1004. VDATEREADPTRIN(lpforetcIn, FORMATETC);
  1005. if(lpdwCacheId)
  1006. VDATEPTROUT(lpdwCacheId, DWORD);
  1007. // Local variables
  1008. HRESULT error = NOERROR;
  1009. FORMATETC foretc;
  1010. LPCACHENODE lpCacheNode = NULL;
  1011. DWORD dwDummyCacheId;
  1012. // Validate parameters
  1013. if(!HasValidLINDEX(lpforetcIn))
  1014. return(DV_E_LINDEX);
  1015. VERIFY_ASPECT_SINGLE(lpforetcIn->dwAspect);
  1016. if(lpforetcIn->cfFormat)
  1017. if(FAILED(error = CheckTymedCFCombination(lpforetcIn)))
  1018. return error;
  1019. if(lpforetcIn->ptd) {
  1020. VDATEREADPTRIN(lpforetcIn->ptd, DVTARGETDEVICE);
  1021. if(!IsValidReadPtrIn(lpforetcIn->ptd, lpforetcIn->ptd->tdSize))
  1022. return ResultFromScode(E_INVALIDARG);
  1023. }
  1024. // Initialize cache id
  1025. if(lpdwCacheId)
  1026. *lpdwCacheId = 0;
  1027. else
  1028. lpdwCacheId = &dwDummyCacheId;
  1029. // If this aspect is frozen, don't allow creation of the cache
  1030. if (m_dwFrozenAspects & lpforetcIn->dwAspect)
  1031. return ResultFromScode(E_FAIL);
  1032. // Ensure that storage has been initialized
  1033. if(!m_pStg) {
  1034. LEDebugOut((DEB_WARN, "Presentation being cached without storage\n"));
  1035. }
  1036. // Copy the FORMATETC
  1037. foretc = *lpforetcIn;
  1038. lpCacheNode = NULL;
  1039. if(foretc.dwAspect != DVASPECT_ICON) {
  1040. HRESULT hresult;
  1041. // Convert Bitmap to DIB
  1042. BITMAP_TO_DIB(foretc);
  1043. if(m_ulFlags & COLECACHEF_FORMATKNOWN) {
  1044. // We can render the native format of the cache
  1045. hresult = IsSameAsObjectFormatEtc(&foretc, m_cfFormat);
  1046. if(hresult == NOERROR) {
  1047. // New format is compatible with native format. Check Ptd
  1048. if(foretc.ptd == NULL) {
  1049. // We can render this format from native format
  1050. // Locate the native cache node
  1051. lpCacheNode = Locate(&foretc, lpdwCacheId);
  1052. // Assert that we could locate the cache node
  1053. Win4Assert(lpCacheNode);
  1054. }
  1055. else if(m_ulFlags & COLECACHEF_STATIC) {
  1056. // Static objects cannot have NON-NULL target device
  1057. return ResultFromScode(DV_E_DVTARGETDEVICE);
  1058. }
  1059. }
  1060. else if(m_ulFlags & COLECACHEF_STATIC) {
  1061. // Static objects can only cache icon aspect
  1062. return hresult;
  1063. }
  1064. }
  1065. }
  1066. if(!lpCacheNode) {
  1067. // The CfFormat is different from native format or Ptd is NON-NULL
  1068. // Check if the format has already been cached
  1069. lpCacheNode = Locate(&foretc, lpdwCacheId);
  1070. }
  1071. // Check if we succeeded in locating an existing cache node
  1072. if(lpCacheNode) {
  1073. // Update advise control flags
  1074. if(lpCacheNode->GetAdvf() != advf) {
  1075. // Static objects cannot have a server
  1076. Win4Assert(!(m_ulFlags & COLECACHEF_STATIC) || !m_pDataObject);
  1077. // If the object is running, tear down advise connection
  1078. if(m_pDataObject)
  1079. lpCacheNode->TearDownAdviseConnection(m_pDataObject);
  1080. // Set the new advise flags
  1081. lpCacheNode->SetAdvf(advf);
  1082. //If the object is running, set up advise connection
  1083. if(m_pDataObject)
  1084. lpCacheNode->SetupAdviseConnection(m_pDataObject,
  1085. (IAdviseSink *) &m_AdviseSink);
  1086. // Cache is not in loaded state now
  1087. m_ulFlags &= ~COLECACHEF_LOADEDSTATE;
  1088. }
  1089. return ResultFromScode(CACHE_S_SAMECACHE);
  1090. }
  1091. // The CfFormat is different from native format or Ptd is NON-NULL
  1092. // and there is no existing cache node for the given formatetc
  1093. // ICON aspect should specify CF_METAFILEPICT CfFormat
  1094. if(foretc.dwAspect == DVASPECT_ICON) {
  1095. // If the format is not set, set it
  1096. if (foretc.cfFormat == NULL) {
  1097. foretc.cfFormat = CF_METAFILEPICT;
  1098. foretc.tymed = TYMED_MFPICT;
  1099. }
  1100. else if(foretc.cfFormat != CF_METAFILEPICT)
  1101. return ResultFromScode(DV_E_FORMATETC);
  1102. }
  1103. // Add cache node for this formatetc
  1104. CCacheNode CacheNode(&foretc, advf, m_pStg);
  1105. *lpdwCacheId = m_pCacheArray->AddItem(CacheNode);
  1106. if(!(*lpdwCacheId))
  1107. return ResultFromScode(E_OUTOFMEMORY);
  1108. lpCacheNode = m_pCacheArray->GetItem(*lpdwCacheId);
  1109. Win4Assert(lpCacheNode);
  1110. if(lpCacheNode->IsOutOfMemory())
  1111. return ResultFromScode(E_OUTOFMEMORY);
  1112. // Static objects cannot have a server
  1113. Win4Assert(!(m_ulFlags & COLECACHEF_STATIC) || !m_pDataObject);
  1114. // If the object is running, set up advise connection so that cache
  1115. // gets updated. Note that we might have data in the cache at the end
  1116. // of this remote call and call on OnDataChange might occur before the
  1117. // call completes
  1118. if(m_pDataObject)
  1119. lpCacheNode->SetupAdviseConnection(m_pDataObject,
  1120. (IAdviseSink *) &m_AdviseSink);
  1121. // Cache is not in loaded state now
  1122. m_ulFlags &= ~COLECACHEF_LOADEDSTATE;
  1123. // Do the special handling for icon here.
  1124. // We prerender iconic aspect by getting icon data from registration
  1125. // data base. Note that this is extra work that can be delayed till GetData
  1126. // or GetDataHere or Draw or Save so that the running object is given a chance
  1127. // to render icon through the advise sink. Gopalk
  1128. if(foretc.dwAspect == DVASPECT_ICON && lpCacheNode->IsBlank() &&
  1129. (!IsEqualCLSID(m_clsid, CLSID_NULL) || m_pDataObject)) {
  1130. STGMEDIUM stgmed;
  1131. BOOL fUpdated;
  1132. // Get icon data
  1133. if(UtGetIconData(m_pDataObject, m_clsid, &foretc, &stgmed) == NOERROR) {
  1134. // Set the data on the cache
  1135. if(lpCacheNode->SetData(&foretc, &stgmed, TRUE, fUpdated) == NOERROR) {
  1136. // Check if aspect has been updated
  1137. if(fUpdated)
  1138. AspectsUpdated(DVASPECT_ICON);
  1139. }
  1140. else {
  1141. // Set data did not release the stgmedium. Release it
  1142. ReleaseStgMedium(&stgmed);
  1143. }
  1144. }
  1145. }
  1146. return(error);
  1147. }
  1148. //+----------------------------------------------------------------------------
  1149. //
  1150. // Member:
  1151. // COleCache::Uncache, public
  1152. //
  1153. // Synopsis:
  1154. // implements IOleCache::Uncache
  1155. //
  1156. // The specified presenation is uncached
  1157. //
  1158. // Arguments:
  1159. // [dwCacheId] [in] -- the cache node id to be deleted
  1160. //
  1161. // Returns:
  1162. // OLE_E_NOCONNECTION, if dwCacheId is invalid
  1163. // S_OK
  1164. //
  1165. // Notes:
  1166. // The native cache is never deleted
  1167. //
  1168. // History:
  1169. // Gopalk Rewritten Sep 04, 96
  1170. //
  1171. //-----------------------------------------------------------------------------
  1172. #pragma SEG(COleCache_Uncache)
  1173. STDMETHODIMP COleCache::Uncache(DWORD dwCacheId)
  1174. {
  1175. // Validation checks
  1176. VDATEHEAP();
  1177. VDATETHREAD(this);
  1178. // Local variable
  1179. LPCACHENODE lpCacheNode = NULL;
  1180. // Delete the cache node
  1181. if(dwCacheId) {
  1182. lpCacheNode = m_pCacheArray->GetItem(dwCacheId);
  1183. if(lpCacheNode && !(lpCacheNode->IsNativeCache())) {
  1184. // If the object is running, tear down advise connection
  1185. if(m_pDataObject)
  1186. lpCacheNode->TearDownAdviseConnection(m_pDataObject);
  1187. // Delete the cache node
  1188. m_pCacheArray->DeleteItem(dwCacheId);
  1189. // Cache is not in loaded state now
  1190. m_ulFlags &= ~COLECACHEF_LOADEDSTATE;
  1191. return NOERROR;
  1192. }
  1193. }
  1194. // No cache node with dwCacheId or Native Cache
  1195. return ResultFromScode(OLE_E_NOCONNECTION);
  1196. }
  1197. //+----------------------------------------------------------------------------
  1198. //
  1199. // Member:
  1200. // COleCache::EnumCache, public
  1201. //
  1202. // Synopsis:
  1203. // implements IOleCache::EnumCache
  1204. //
  1205. // returns cache enumerator
  1206. //
  1207. // Arguments:
  1208. // [ppenum] [out] -- a pointer to return the pointer to the
  1209. // enumerator
  1210. //
  1211. // Returns:
  1212. // E_OUTOFMEMORY, S_OK
  1213. //
  1214. // History:
  1215. // Gopalk Rewritten Sep 04, 96
  1216. //
  1217. //-----------------------------------------------------------------------------
  1218. #pragma SEG(COleCache_EnumCache)
  1219. STDMETHODIMP COleCache::EnumCache(LPENUMSTATDATA* ppenum)
  1220. {
  1221. // Validation checks
  1222. VDATEHEAP();
  1223. VDATETHREAD(this);
  1224. VDATEPTROUT(ppenum, LPENUMSTATDATA*);
  1225. // Initialize
  1226. *ppenum = NULL;
  1227. // Check if the cache is empty
  1228. //if(m_pCacheArray->Length()) {
  1229. *ppenum = CEnumStatData::CreateEnumStatData(m_pCacheArray);
  1230. if(!(*ppenum))
  1231. return ResultFromScode(E_OUTOFMEMORY);
  1232. //}
  1233. return NOERROR;
  1234. }
  1235. //+----------------------------------------------------------------------------
  1236. //
  1237. // Member:
  1238. // COleCache::InitCache, public
  1239. //
  1240. // Synopsis:
  1241. // implements IOleCache::InitCache
  1242. //
  1243. // initializes all cache nodes with the given data object.
  1244. // Calls IOleCache2::UpdateCache
  1245. //
  1246. // Arguments:
  1247. // [lpSrcDataObj] [in] -- pointer to the source data object
  1248. //
  1249. // Returns:
  1250. // E_INVALIDARG, if [lpSrcDataObj] is NULL
  1251. //
  1252. // History:
  1253. // Gopalk Rewritten Sep 04, 96
  1254. //
  1255. //-----------------------------------------------------------------------------
  1256. #pragma SEG(COleCache_InitCache)
  1257. STDMETHODIMP COleCache::InitCache(LPDATAOBJECT lpSrcDataObj)
  1258. {
  1259. // Validataion checks
  1260. VDATEHEAP();
  1261. VDATETHREAD(this);
  1262. VDATEIFACE(lpSrcDataObj);
  1263. // Initialize the cache by calling update cache
  1264. return UpdateCache(lpSrcDataObj, UPDFCACHE_ALLBUTNODATACACHE, NULL);
  1265. }
  1266. //+----------------------------------------------------------------------------
  1267. //
  1268. // Member:
  1269. // COleCache::SetData, public
  1270. //
  1271. // Synopsis:
  1272. // implements IOleCache::SetData
  1273. //
  1274. // stores data into the cache node which matches the given
  1275. // FORMATETC
  1276. //
  1277. // Arguments:
  1278. // [pformatetc] [in] -- the format the data is in
  1279. // [pmedium] [in] -- the storage medium for the new data
  1280. // [fRelease] [in] -- indicates whether to release the storage
  1281. // after the data is examined
  1282. //
  1283. // Returns:
  1284. // HRESULT
  1285. //
  1286. // History:
  1287. // Gopalk Rewritten Sep 04, 96
  1288. //
  1289. //-----------------------------------------------------------------------------
  1290. #pragma SEG(COleCache_SetData)
  1291. STDMETHODIMP COleCache::SetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium,
  1292. BOOL fRelease)
  1293. {
  1294. // Validation checks
  1295. VDATEHEAP();
  1296. VDATETHREAD(this);
  1297. VDATEREADPTRIN(pformatetc, FORMATETC);
  1298. VDATEREADPTRIN(pmedium, STGMEDIUM);
  1299. VERIFY_TYMED_SINGLE_VALID_FOR_CLIPFORMAT(pformatetc);
  1300. if(pformatetc->ptd) {
  1301. VDATEREADPTRIN(pformatetc->ptd, DVTARGETDEVICE);
  1302. if(!IsValidReadPtrIn(pformatetc->ptd, pformatetc->ptd->tdSize))
  1303. return ResultFromScode(E_INVALIDARG);
  1304. }
  1305. // Local variables
  1306. LPCACHENODE lpCacheNode;
  1307. CLIPFORMAT cfFormat;
  1308. HRESULT error;
  1309. FORMATETC foretc;
  1310. BOOL fUpdated;
  1311. // Check if the object is static
  1312. if((m_ulFlags & COLECACHEF_STATIC) && (pformatetc->dwAspect != DVASPECT_ICON)) {
  1313. // Copy the FormatEtc
  1314. foretc = *pformatetc;
  1315. // The given format should be same as native format
  1316. error = IsSameAsObjectFormatEtc(&foretc, m_cfFormat);
  1317. if(error != NOERROR)
  1318. return error;
  1319. // The Ptd has to be null. This prevents client from storing the data
  1320. // in the cache that has been created for NON-NULL Ptd in
  1321. // COleCache::Cache(). Gopalk
  1322. if(foretc.ptd)
  1323. return ResultFromScode(DV_E_DVTARGETDEVICE);
  1324. // Obtain the native cache node.
  1325. if(!(lpCacheNode = m_pCacheArray->GetItem(1)))
  1326. return ResultFromScode(E_OUTOFMEMORY);
  1327. // Set data on the cache node. The native stream gets saved in
  1328. // COleCache::Save(). Gopalk
  1329. error = lpCacheNode->SetData(pformatetc, pmedium, fRelease, fUpdated);
  1330. if(SUCCEEDED(error) && m_pStg)
  1331. error = Save(m_pStg, TRUE); // save changes
  1332. }
  1333. else {
  1334. // The obejct is either not a static object or the aspect is ICON
  1335. lpCacheNode = Locate(pformatetc);
  1336. // Set data on the cache node
  1337. if(lpCacheNode)
  1338. error = lpCacheNode->SetData(pformatetc, pmedium, fRelease, fUpdated);
  1339. else
  1340. error = ResultFromScode(OLE_E_BLANK);
  1341. }
  1342. if(error==NOERROR) {
  1343. // Cache is not in loaded state now
  1344. m_ulFlags &= ~COLECACHEF_LOADEDSTATE;
  1345. // Inform AspectsUpdated about the updated aspect
  1346. if(fUpdated)
  1347. AspectsUpdated(pformatetc->dwAspect);
  1348. }
  1349. return error;
  1350. }
  1351. // IOleCache2 implementation
  1352. //+----------------------------------------------------------------------------
  1353. //
  1354. // Member:
  1355. // COleCache::UpdateCache, public
  1356. //
  1357. // Synopsis:
  1358. // implements IOleCache2::UpdateCache
  1359. //
  1360. // Updates cache entries that match the given criteria with the
  1361. // given data object. If no data object is given, it uses the
  1362. // existing running data object.
  1363. //
  1364. // Arguments:
  1365. // [pDataObjIn] [in] -- data object to get data from. Can be NULL
  1366. // [grfUpdf] [in] -- update control flags
  1367. // [pReserved] [in] -- must be NULL
  1368. //
  1369. // Returns:
  1370. // HRESULT
  1371. //
  1372. // History:
  1373. // Gopalk Rewritten Sep 04, 96
  1374. //
  1375. //-----------------------------------------------------------------------------
  1376. #pragma SEG(COleCache_UpdateCache)
  1377. STDMETHODIMP COleCache::UpdateCache(LPDATAOBJECT pDataObjIn, DWORD grfUpdf,
  1378. LPVOID pReserved)
  1379. {
  1380. // Validation checks
  1381. VDATEHEAP();
  1382. VDATETHREAD(this);
  1383. if(pDataObjIn) {
  1384. VDATEIFACE(pDataObjIn);
  1385. }
  1386. else if(!m_pDataObject)
  1387. return ResultFromScode(OLE_E_NOTRUNNING);
  1388. Win4Assert(!pReserved);
  1389. // Local variables
  1390. LPDATAOBJECT pDataObject;
  1391. ULONG cntUpdatedNodes, cntTotalNodes;
  1392. ULONG index, i;
  1393. BOOL fUpdated;
  1394. DWORD dwUpdatedAspects, dwAspect;
  1395. LPCACHENODE lpCacheNode;
  1396. HRESULT error;
  1397. // Set the data object for use in update
  1398. if(pDataObjIn)
  1399. pDataObject = pDataObjIn;
  1400. else
  1401. pDataObject = m_pDataObject;
  1402. // Check if the cache is empty
  1403. cntTotalNodes = m_pCacheArray->Length();
  1404. if(!cntTotalNodes)
  1405. return NOERROR;
  1406. // Update the cache nodes including native cache. Gopalk
  1407. m_pCacheArray->Reset(index);
  1408. cntUpdatedNodes = 0;
  1409. dwUpdatedAspects = 0;
  1410. for(i=0; i<cntTotalNodes; i++) {
  1411. // Get the next cache node
  1412. lpCacheNode = m_pCacheArray->GetNext(index);
  1413. // lpCacheNode cannot be null
  1414. Win4Assert(lpCacheNode);
  1415. // Update the cache node
  1416. error = lpCacheNode->Update(pDataObject, grfUpdf, fUpdated);
  1417. if(error == NOERROR) {
  1418. cntUpdatedNodes++;
  1419. // Cache is not in loaded state now
  1420. m_ulFlags &= ~COLECACHEF_LOADEDSTATE;
  1421. // Check if a new aspect has been updated
  1422. dwAspect = lpCacheNode->GetFormatEtc()->dwAspect;
  1423. if(fUpdated && !(dwUpdatedAspects & dwAspect))
  1424. dwUpdatedAspects |= dwAspect;
  1425. }
  1426. else if(error == ResultFromScode(CACHE_S_SAMECACHE))
  1427. cntUpdatedNodes++;
  1428. }
  1429. // Inform AspectsUpdated about the updated aspects
  1430. if(dwUpdatedAspects)
  1431. AspectsUpdated(dwUpdatedAspects);
  1432. // It is OK to have zero nodes and zero updates
  1433. // Return appropriate error code
  1434. if(!cntUpdatedNodes && cntTotalNodes)
  1435. return ResultFromScode(CACHE_E_NOCACHE_UPDATED);
  1436. else if(cntUpdatedNodes < cntTotalNodes)
  1437. // return ResultFromScode(CACHE_S_SOMECACHES_NOTUPDATED);
  1438. return(NOERROR);
  1439. return NOERROR;
  1440. }
  1441. //+----------------------------------------------------------------------------
  1442. //
  1443. // Member:
  1444. // COleCache::DiscardCache, public
  1445. //
  1446. // Synopsis:
  1447. // implements IOleCache2::DiscardCache
  1448. //
  1449. // Instructs the cache that its contents should be discarded;
  1450. // the contents are optionally saved to disk before discarding.
  1451. //
  1452. // Arguments:
  1453. // [dwDiscardOpt] -- discard option from DISCARDCACHE_*
  1454. //
  1455. // Returns:
  1456. // HRESULT
  1457. //
  1458. // History:
  1459. // Gopalk Rewritten Sep 04, 96
  1460. //
  1461. //-----------------------------------------------------------------------------
  1462. STDMETHODIMP COleCache::DiscardCache(DWORD dwDiscardOpt)
  1463. {
  1464. // Validation checks
  1465. VDATEHEAP();
  1466. VDATETHREAD(this);
  1467. if(dwDiscardOpt != DISCARDCACHE_SAVEIFDIRTY &&
  1468. dwDiscardOpt != DISCARDCACHE_NOSAVE)
  1469. return ResultFromScode(E_INVALIDARG);
  1470. // Local variable
  1471. HRESULT error;
  1472. ULONG index;
  1473. LPCACHENODE lpCacheNode;
  1474. if(dwDiscardOpt == DISCARDCACHE_SAVEIFDIRTY) {
  1475. // There has to be a storage for saving
  1476. if(m_pStg == NULL)
  1477. return ResultFromScode(OLE_E_NOSTORAGE);
  1478. // Save the cache
  1479. error = Save(m_pStg, TRUE /* fSameAsLoad */);
  1480. if(FAILED(error))
  1481. return error;
  1482. // Call save completed
  1483. SaveCompleted(NULL);
  1484. }
  1485. // Discard cache nodes including the native cache node
  1486. // What about the uncached presentations. Should they
  1487. // be loaded from the disk. Gopalk
  1488. m_pCacheArray->Reset(index);
  1489. for(unsigned long i=0; i<m_pCacheArray->Length(); i++) {
  1490. // Get the next cache node
  1491. lpCacheNode = m_pCacheArray->GetNext(index);
  1492. // lpCacheNode cannot be null
  1493. Win4Assert(lpCacheNode);
  1494. // Discard the presentation of the cache node
  1495. lpCacheNode->DiscardPresentation();
  1496. }
  1497. // We make a safe assumption that the cache is in loaded state
  1498. m_ulFlags |= COLECACHEF_LOADEDSTATE;
  1499. return NOERROR;
  1500. }
  1501. // private IUnknown implementation
  1502. //+----------------------------------------------------------------------------
  1503. //
  1504. // Member:
  1505. // COleCache::CCacheUnkImpl::QueryInterface, public
  1506. //
  1507. // Synopsis:
  1508. // implements IUnknown::QueryInterface
  1509. //
  1510. // This provides the private IUnknown implementation when
  1511. // COleCache is aggregated
  1512. //
  1513. // Arguments:
  1514. // [iid] [in] -- IID of the desired interface
  1515. // [ppv] [out] -- pointer to where to return the requested interface
  1516. //
  1517. // Returns:
  1518. // E_NOINTERFACE, if the requested interface is not available
  1519. // S_OK
  1520. //
  1521. // History:
  1522. // Gopalk Rewritten Sep 04, 96
  1523. //
  1524. //-----------------------------------------------------------------------------
  1525. #pragma SEG(COleCache_CCacheUnkImpl_QueryInterface)
  1526. STDMETHODIMP COleCache::CCacheUnkImpl::QueryInterface(REFIID iid, LPVOID* ppv)
  1527. {
  1528. // Validation checks
  1529. VDATEHEAP();
  1530. VDATEPTROUT(ppv, LPVOID);
  1531. // Get the parent object
  1532. COleCache* pOleCache = GETPPARENT(this, COleCache, m_UnkPrivate);
  1533. VDATETHREAD(pOleCache);
  1534. // Get the requested Interface
  1535. if(IsEqualIID(iid, IID_IUnknown) ||
  1536. IsEqualIID(iid, IID_IOleCache) || IsEqualIID(iid, IID_IOleCache2))
  1537. *ppv = (void *)(IOleCache2 *) pOleCache;
  1538. else if(IsEqualIID(iid, IID_IDataObject))
  1539. *ppv = (void *)(IDataObject *) &pOleCache->m_Data;
  1540. else if(IsEqualIID(iid, IID_IViewObject) || IsEqualIID(iid, IID_IViewObject2))
  1541. *ppv = (void *)(IViewObject2 *) &pOleCache->m_ViewObject;
  1542. else if(IsEqualIID(iid, IID_IPersist) || IsEqualIID(iid, IID_IPersistStorage))
  1543. *ppv = (void *)(IPersistStorage *) pOleCache;
  1544. else if(IsEqualIID(iid, IID_IOleCacheControl))
  1545. *ppv = (void *)(IOleCacheControl *) pOleCache;
  1546. else {
  1547. *ppv = NULL;
  1548. return ResultFromScode(E_NOINTERFACE);
  1549. }
  1550. // Call addref through the interface being returned
  1551. ((IUnknown *) *ppv)->AddRef();
  1552. return NOERROR;
  1553. }
  1554. //+----------------------------------------------------------------------------
  1555. //
  1556. // Member:
  1557. // COleCache::CCacheUnkImpl::AddRef, public
  1558. //
  1559. // Synopsis:
  1560. // implements IUnknown::AddRef
  1561. //
  1562. // This is part of the private IUnknown implementation of
  1563. // COleCache used when COleCache is aggregated
  1564. //
  1565. // Arguments:
  1566. // none
  1567. //
  1568. // Returns:
  1569. // the object's reference count
  1570. //
  1571. // History:
  1572. // Gopalk Rewritten Sep 04, 96
  1573. //
  1574. //-----------------------------------------------------------------------------
  1575. #pragma SEG(COleCache_CCacheUnkImpl_AddRef)
  1576. STDMETHODIMP_(ULONG) COleCache::CCacheUnkImpl::AddRef(void)
  1577. {
  1578. // Validation check
  1579. VDATEHEAP();
  1580. // Get the parent object
  1581. COleCache* pOleCache = GETPPARENT(this, COleCache, m_UnkPrivate);
  1582. ULONG cRefs;
  1583. if(!pOleCache->VerifyThreadId())
  1584. return((ULONG) RPC_E_WRONG_THREAD);
  1585. // AddRef parent object
  1586. cRefs = pOleCache->SafeAddRef();
  1587. return cRefs;
  1588. }
  1589. //+----------------------------------------------------------------------------
  1590. //
  1591. // Member:
  1592. // COleCache::CCacheUnkImpl::Release, public
  1593. //
  1594. // Synopsis:
  1595. // implements IUnknown::Release
  1596. //
  1597. // This is part of the private IUnknown implementation of
  1598. // COleCache used when COleCache is aggregated
  1599. //
  1600. // Arguments:
  1601. // none
  1602. //
  1603. // Returns:
  1604. // the object's reference count
  1605. //
  1606. // History:
  1607. // Gopalk Rewritten Sep 04, 96
  1608. //
  1609. //-----------------------------------------------------------------------------
  1610. #pragma SEG(COleCache_CCacheUnkImpl_Release)
  1611. STDMETHODIMP_(ULONG) COleCache::CCacheUnkImpl::Release(void)
  1612. {
  1613. // Validation check
  1614. VDATEHEAP();
  1615. // Get the parent object
  1616. COleCache* pOleCache = GETPPARENT(this, COleCache, m_UnkPrivate);
  1617. ULONG cRefs;
  1618. if(!pOleCache->VerifyThreadId())
  1619. return((ULONG) RPC_E_WRONG_THREAD);
  1620. // Release parent object
  1621. cRefs = pOleCache->SafeRelease();
  1622. return cRefs;
  1623. }
  1624. // IDataObject implementation
  1625. //+----------------------------------------------------------------------------
  1626. //
  1627. // Member:
  1628. // COleCache::CCacheDataImpl::QueryInterface, public
  1629. //
  1630. // Synopsis:
  1631. // implements IUnknown::QueryInterface
  1632. //
  1633. // Arguments:
  1634. // [iid] [in] -- IID of the desired interface
  1635. // [ppv] [out] -- pointer to where to return the requested interface
  1636. //
  1637. // Returns:
  1638. // E_NOINTERFACE, if the requested interface is not available
  1639. // S_OK
  1640. //
  1641. // History:
  1642. // Gopalk Rewritten Sep 04, 96
  1643. //
  1644. //-----------------------------------------------------------------------------
  1645. #pragma SEG(COleCache_CCacheDataImpl_QueryInterface)
  1646. STDMETHODIMP COleCache::CCacheDataImpl::QueryInterface(REFIID riid, LPVOID* ppv)
  1647. {
  1648. // Validation check
  1649. VDATEHEAP();
  1650. // Get the parent object
  1651. COleCache* pOleCache = GETPPARENT(this, COleCache, m_Data);
  1652. VDATETHREAD(pOleCache);
  1653. // Delegate to the outer unknown
  1654. return pOleCache->m_pUnkOuter->QueryInterface(riid, ppv);
  1655. }
  1656. //+----------------------------------------------------------------------------
  1657. //
  1658. // Member:
  1659. // COleCache::CCacheDataImpl::AddRef, public
  1660. //
  1661. // Synopsis:
  1662. // implements IUnknown::AddRef
  1663. //
  1664. // Arguments:
  1665. // none
  1666. //
  1667. // Returns:
  1668. // the object's reference count
  1669. //
  1670. // History:
  1671. // Gopalk Rewritten Sep 04, 96
  1672. //
  1673. //-----------------------------------------------------------------------------
  1674. #pragma SEG(COleCache_CCacheDataImpl_AddRef)
  1675. STDMETHODIMP_(ULONG) COleCache::CCacheDataImpl::AddRef (void)
  1676. {
  1677. // Validation check
  1678. VDATEHEAP();
  1679. // Get the parent object
  1680. COleCache* pOleCache = GETPPARENT(this, COleCache, m_Data);
  1681. if(!pOleCache->VerifyThreadId())
  1682. return((ULONG) RPC_E_WRONG_THREAD);
  1683. // Delegate to the outer unknown
  1684. return pOleCache->m_pUnkOuter->AddRef();
  1685. }
  1686. //+----------------------------------------------------------------------------
  1687. //
  1688. // Member:
  1689. // COleCache::CCacheDataImpl::Release, public
  1690. //
  1691. // Synopsis:
  1692. // implements IUnknown::Release
  1693. //
  1694. // Arguments:
  1695. // none
  1696. //
  1697. // Returns:
  1698. // the object's reference count
  1699. //
  1700. // History:
  1701. // Gopalk Rewritten Sep 04, 96
  1702. //
  1703. //-----------------------------------------------------------------------------
  1704. #pragma SEG(COleCache_CCacheDataImpl_Release)
  1705. STDMETHODIMP_(ULONG) COleCache::CCacheDataImpl::Release (void)
  1706. {
  1707. // Validation check
  1708. VDATEHEAP();
  1709. // Get the parent object
  1710. COleCache* pOleCache = GETPPARENT(this, COleCache, m_Data);
  1711. if(!pOleCache->VerifyThreadId())
  1712. return((ULONG) RPC_E_WRONG_THREAD);
  1713. // Delegate to the outer unknown
  1714. return pOleCache->m_pUnkOuter->Release();
  1715. }
  1716. //+----------------------------------------------------------------------------
  1717. //
  1718. // Member:
  1719. // COleCache::CCacheDataImpl::GetData, public
  1720. //
  1721. // Synopsis:
  1722. // implements IDataObject::GetData
  1723. //
  1724. // Arguments:
  1725. // [pforetc] [in] -- the format the requestor would like the data in
  1726. // [pmedium] [out] -- where to return the storage medium to the caller
  1727. //
  1728. // Returns:
  1729. // OLE_E_BLANK, if the cache is empty
  1730. //
  1731. // History:
  1732. // Gopalk Rewritten Sep 04, 96
  1733. //
  1734. //-----------------------------------------------------------------------------
  1735. #pragma SEG(COleCache_CCacheDataImpl_GetData)
  1736. STDMETHODIMP COleCache::CCacheDataImpl::GetData(LPFORMATETC pforetc,
  1737. LPSTGMEDIUM pmedium)
  1738. {
  1739. // Validation checks
  1740. VDATEHEAP();
  1741. VDATEREADPTRIN(pforetc, FORMATETC);
  1742. VERIFY_ASPECT_SINGLE(pforetc->dwAspect);
  1743. if(pforetc->ptd) {
  1744. VDATEREADPTRIN(pforetc->ptd, DVTARGETDEVICE);
  1745. if(!IsValidReadPtrIn(pforetc->ptd, pforetc->ptd->tdSize))
  1746. return ResultFromScode(E_INVALIDARG);
  1747. }
  1748. VDATEPTROUT(pmedium, STGMEDIUM);
  1749. // Get the parent object
  1750. COleCache* pOleCache = GETPPARENT(this, COleCache, m_Data);
  1751. VDATETHREAD(pOleCache);
  1752. // Local variable
  1753. LPCACHENODE lpCacheNode;
  1754. // Check if cache is empty
  1755. if(!pOleCache->m_pCacheArray->Length())
  1756. return ResultFromScode(OLE_E_BLANK);
  1757. // Initialize storage medium
  1758. pmedium->tymed = TYMED_NULL;
  1759. pmedium->pUnkForRelease = NULL;
  1760. // Locate the cache node for the given formatetc
  1761. lpCacheNode = pOleCache->Locate(pforetc);
  1762. // If there is no cache node, we cannot furnish the data
  1763. if(!lpCacheNode)
  1764. return ResultFromScode(OLE_E_BLANK);
  1765. // Get the data from the cache node
  1766. return(lpCacheNode->GetData(pforetc, pmedium));
  1767. }
  1768. //+----------------------------------------------------------------------------
  1769. //
  1770. // Member:
  1771. // COleCache::CCacheDataImpl::GetDataHere, public
  1772. //
  1773. // Synopsis:
  1774. // implements IDataObject::GetDataHere
  1775. //
  1776. // Arguments:
  1777. // [pforetc] [in] -- the format the requestor would like the data in
  1778. // [pmedium] [in/out] -- where to return the storage medium to the caller
  1779. //
  1780. // Returns:
  1781. // OLE_E_BLANK, if the cache is empty
  1782. //
  1783. // History:
  1784. // Gopalk Rewritten Sep 04, 96
  1785. //
  1786. //-----------------------------------------------------------------------------
  1787. #pragma SEG(COleCache_CCacheDataImpl_GetDataHere)
  1788. STDMETHODIMP COleCache::CCacheDataImpl::GetDataHere(LPFORMATETC pforetc,
  1789. LPSTGMEDIUM pmedium)
  1790. {
  1791. // Validation checks
  1792. VDATEHEAP();
  1793. VDATEREADPTRIN(pforetc, FORMATETC);
  1794. VERIFY_ASPECT_SINGLE(pforetc->dwAspect);
  1795. VERIFY_TYMED_SINGLE(pforetc->tymed);
  1796. if(pforetc->ptd) {
  1797. VDATEREADPTRIN(pforetc->ptd, DVTARGETDEVICE);
  1798. if(!IsValidReadPtrIn(pforetc->ptd, pforetc->ptd->tdSize))
  1799. return ResultFromScode(E_INVALIDARG);
  1800. }
  1801. VDATEPTROUT(pmedium, STGMEDIUM);
  1802. // TYMED_MFPICT, TYMED_GDI are not allowed
  1803. if ((pforetc->tymed == TYMED_MFPICT) || (pforetc->tymed == TYMED_GDI)
  1804. || (pmedium->tymed != pforetc->tymed))
  1805. return ResultFromScode(DV_E_TYMED);
  1806. // Get the parent object
  1807. COleCache* pOleCache = GETPPARENT(this, COleCache, m_Data);
  1808. VDATETHREAD(pOleCache);
  1809. // Local variable
  1810. LPCACHENODE lpCacheNode;
  1811. // Check if cache is empty
  1812. if(!pOleCache->m_pCacheArray->Length())
  1813. return ResultFromScode(OLE_E_BLANK);
  1814. // Locate the cache node for the given formatetc
  1815. lpCacheNode = pOleCache->Locate(pforetc);
  1816. // If there is no cache node, we cannot furnish the data
  1817. if(!lpCacheNode)
  1818. return ResultFromScode(OLE_E_BLANK);
  1819. // Get the data from the cache node
  1820. return(lpCacheNode->GetDataHere(pforetc, pmedium));
  1821. }
  1822. //+----------------------------------------------------------------------------
  1823. //
  1824. // Member:
  1825. // COleCache::CCacheDataImpl::QueryGetData, public
  1826. //
  1827. // Synopsis:
  1828. // implements IDataObject::QueryGetData
  1829. //
  1830. // Arguments:
  1831. // [pforetc] [in] -- the format to check for
  1832. //
  1833. // Returns:
  1834. // S_FALSE, if data is not available in the requested format
  1835. // S_OK otherwise
  1836. //
  1837. // History:
  1838. // Gopalk Rewritten Sep 04, 96
  1839. //
  1840. //-----------------------------------------------------------------------------
  1841. #pragma SEG(COleCache_CCacheDataImpl_QueryGetData)
  1842. STDMETHODIMP COleCache::CCacheDataImpl::QueryGetData(LPFORMATETC pforetc)
  1843. {
  1844. // Validation checks
  1845. VDATEHEAP();
  1846. VDATEREADPTRIN(pforetc, FORMATETC);
  1847. VERIFY_TYMED_VALID_FOR_CLIPFORMAT(pforetc);
  1848. if(pforetc->ptd) {
  1849. VDATEREADPTRIN(pforetc->ptd, DVTARGETDEVICE);
  1850. if(!IsValidReadPtrIn(pforetc->ptd, pforetc->ptd->tdSize))
  1851. return ResultFromScode(E_INVALIDARG);
  1852. }
  1853. // Get the parent object
  1854. COleCache* pOleCache = GETPPARENT(this, COleCache, m_Data);
  1855. VDATETHREAD(pOleCache);
  1856. // Local variable
  1857. LPCACHENODE lpCacheNode;
  1858. // Check if cache is empty
  1859. if(!pOleCache->m_pCacheArray->Length())
  1860. return ResultFromScode(S_FALSE);
  1861. // Locate the cache node for the given formatetc
  1862. lpCacheNode = pOleCache->Locate(pforetc);
  1863. // If there is no cache node or if it is blank,
  1864. // we cannot furnish the data
  1865. if(!lpCacheNode || lpCacheNode->IsBlank())
  1866. return ResultFromScode(S_FALSE);
  1867. return NOERROR;
  1868. }
  1869. //+----------------------------------------------------------------------------
  1870. //
  1871. // Member:
  1872. // COleCache::CCacheDataImpl::GetCanonicalFormatEtc, public
  1873. //
  1874. // Synopsis:
  1875. // implements IDataObject::GetCanonicalFormatEtc
  1876. //
  1877. // Arguments:
  1878. // [pformatetc] --
  1879. // [pformatetcOut] --
  1880. //
  1881. // Returns:
  1882. // E_NOTIMPL
  1883. //
  1884. // History:
  1885. // 11/10/93 - ChrisWe - file inspection and cleanup
  1886. //
  1887. //-----------------------------------------------------------------------------
  1888. #pragma SEG(COleCache_CCacheDataImpl_GetCanonicalFormatEtc)
  1889. STDMETHODIMP COleCache::CCacheDataImpl::GetCanonicalFormatEtc(LPFORMATETC pforetcIn,
  1890. LPFORMATETC pforetcOut)
  1891. {
  1892. // Validation check
  1893. VDATEHEAP();
  1894. // Get the parent object
  1895. COleCache* pOleCache = GETPPARENT(this, COleCache, m_Data);
  1896. VDATETHREAD(pOleCache);
  1897. // Not implemented
  1898. return ResultFromScode(E_NOTIMPL);
  1899. }
  1900. //+----------------------------------------------------------------------------
  1901. //
  1902. // Member:
  1903. // COleCache::CCacheDataImpl::SetData, public
  1904. //
  1905. // Synopsis:
  1906. // implements IDataObject::SetData
  1907. //
  1908. // Arguments:
  1909. // [pformatetc] [in] -- the format the data is in
  1910. // [pmedium] [in] -- the storage medium the data is on
  1911. // [fRelease] [in] -- release storage medium after data is copied
  1912. //
  1913. // Returns:
  1914. // HRESULT
  1915. //
  1916. // History:
  1917. // Gopalk Rewritten Sep 04, 96
  1918. //
  1919. //-----------------------------------------------------------------------------
  1920. #pragma SEG(COleCache_CCacheDataImpl_SetData)
  1921. STDMETHODIMP COleCache::CCacheDataImpl::SetData(LPFORMATETC pformatetc,
  1922. LPSTGMEDIUM pmedium,
  1923. BOOL fRelease)
  1924. {
  1925. // Validation check
  1926. VDATEHEAP();
  1927. // Get the parent object
  1928. COleCache* pOleCache = GETPPARENT(this, COleCache, m_Data);
  1929. VDATETHREAD(pOleCache);
  1930. // Call COleCache::SetData. It validates the parameters
  1931. return pOleCache->SetData(pformatetc, pmedium, fRelease);
  1932. }
  1933. //+----------------------------------------------------------------------------
  1934. //
  1935. // Member:
  1936. // COleCache::CCacheDataImpl::EnumFormatEtc, public
  1937. //
  1938. // Synopsis:
  1939. // implements IDataObject::EnumFormatEtc
  1940. //
  1941. // Arguments:
  1942. // [dwDirection] [in] -- which way to run the enumerator
  1943. // [ppenumFormatEtc] [out] -- pointer to where the enumerator
  1944. // is returned
  1945. //
  1946. // Returns:
  1947. // E_OUTOFMEMORY, S_OK
  1948. //
  1949. // History:
  1950. // Gopalk Rewritten Sep 04, 96
  1951. //
  1952. //-----------------------------------------------------------------------------
  1953. #pragma SEG(COleCache_CCacheDataImpl_EnumFormatEtc)
  1954. STDMETHODIMP COleCache::CCacheDataImpl::EnumFormatEtc(DWORD dwDirection,
  1955. LPENUMFORMATETC* ppenum)
  1956. {
  1957. // Validation checks
  1958. VDATEHEAP();
  1959. VDATEPTROUT(ppenum, LPENUMFORMATETC);
  1960. // Get the parent object
  1961. COleCache* pOleCache = GETPPARENT(this, COleCache, m_Data);
  1962. VDATETHREAD(pOleCache);
  1963. // Enumeration for only DATADIR_GET is implemented
  1964. if ((dwDirection | DATADIR_GET) != DATADIR_GET)
  1965. return ResultFromScode(E_NOTIMPL);
  1966. // Initialize
  1967. //*ppenum = NULL;
  1968. // Check if the cache is empty
  1969. //if(pOleCache->m_pCacheArray->Length()) {
  1970. *ppenum = CEnumFormatEtc::CreateEnumFormatEtc(pOleCache->m_pCacheArray);
  1971. if(!(*ppenum))
  1972. return ResultFromScode(E_OUTOFMEMORY);
  1973. //}
  1974. return NOERROR;
  1975. }
  1976. //+----------------------------------------------------------------------------
  1977. //
  1978. // Member:
  1979. // COleCache::CCacheDataImpl::DAdvise, public
  1980. //
  1981. // Synopsis:
  1982. // implements IDataObject::DAdvise
  1983. //
  1984. // Arguments:
  1985. // [pforetc] -- the data format the advise sink is interested in
  1986. // [advf] -- advise control flags from ADVF_*
  1987. // [pAdvSink] -- the advise sink
  1988. // [pdwConnection] -- pointer to where to return the connection id
  1989. //
  1990. // Returns:
  1991. // OLE_E_ADVISENOTSUPPORTED
  1992. //
  1993. // Notes:
  1994. // Defhndlr and deflink never call the following three methods. Even for App
  1995. // handlers which make use our cache implementation this is not necessary. So,
  1996. // I am making it return error.
  1997. //
  1998. // History:
  1999. // 11/10/93 - ChrisWe - set returned connection id to 0
  2000. // 11/10/93 - ChrisWe - file inspection and cleanup
  2001. //
  2002. //-----------------------------------------------------------------------------
  2003. #pragma SEG(COleCache_CCacheDataImpl_DAdvise)
  2004. STDMETHODIMP COleCache::CCacheDataImpl::DAdvise(LPFORMATETC pforetc, DWORD advf,
  2005. IAdviseSink* pAdvSink,
  2006. DWORD* pdwConnection)
  2007. {
  2008. // Validation Check
  2009. VDATEHEAP();
  2010. // Reset connection ID
  2011. *pdwConnection = 0;
  2012. // Not implemeted
  2013. return ResultFromScode(OLE_E_ADVISENOTSUPPORTED);
  2014. }
  2015. //+----------------------------------------------------------------------------
  2016. //
  2017. // Member:
  2018. // COleCache::CCacheDataImpl::DUnadvise, public
  2019. //
  2020. // Synopsis:
  2021. // implements IDataObject::DUnadvise
  2022. //
  2023. // Arguments:
  2024. // [dwConnection] -- the connection id
  2025. //
  2026. // Returns:
  2027. // OLE_E_NOCONNECTION
  2028. //
  2029. // Notes:
  2030. // See COleCache::CCacheDataImpl::DAdvise
  2031. //
  2032. // History:
  2033. // 11/10/93 - ChrisWe - file inspection and cleanup
  2034. //
  2035. //-----------------------------------------------------------------------------
  2036. #pragma SEG(COleCache_CCacheDataImpl_DUnadvise)
  2037. STDMETHODIMP COleCache::CCacheDataImpl::DUnadvise(DWORD dwConnection)
  2038. {
  2039. // Validation check
  2040. VDATEHEAP();
  2041. // Not implemented
  2042. return ResultFromScode(OLE_E_NOCONNECTION);
  2043. }
  2044. //+----------------------------------------------------------------------------
  2045. //
  2046. // Member:
  2047. // COleCache::CCacheDataImpl::EnumDAdvise, public
  2048. //
  2049. // Synopsis:
  2050. // implements IDataObject::EnumDAdvise
  2051. //
  2052. // Arguments:
  2053. // [ppenumDAdvise] -- pointer to where to return the enumerator
  2054. //
  2055. // Returns:
  2056. // OLE_E_ADVISENOTSUPPORTED
  2057. //
  2058. // Notes:
  2059. // See COleCache::CCacheDataImpl::DAdvise
  2060. //
  2061. // History:
  2062. // 11/10/93 - ChrisWe - set returned enumerator pointer to 0
  2063. // 11/10/93 - ChrisWe - file inspection and cleanup
  2064. //
  2065. //-----------------------------------------------------------------------------
  2066. #pragma SEG(COleCache_CCacheDataImpl_EnumDAdvise)
  2067. STDMETHODIMP COleCache::CCacheDataImpl::EnumDAdvise(LPENUMSTATDATA* ppenumDAdvise)
  2068. {
  2069. // Validation check
  2070. VDATEHEAP();
  2071. // Reset the enumerator
  2072. *ppenumDAdvise = NULL;
  2073. // Not implemented
  2074. return ResultFromScode(OLE_E_ADVISENOTSUPPORTED);
  2075. }
  2076. // IViewObject implementation
  2077. //+----------------------------------------------------------------------------
  2078. //
  2079. // Member:
  2080. // COleCache::CCacheViewImpl::QueryInterface, public
  2081. //
  2082. // Synopsis:
  2083. // implements IUnknown::QueryInterface
  2084. //
  2085. // Arguments:
  2086. // [iid] -- IID of the desired interface
  2087. // [ppv] -- pointer where the requested interface is returned
  2088. //
  2089. // Returns:
  2090. // E_NOINTERFACE, if the requested interface is not available
  2091. // S_OK, otherwise
  2092. //
  2093. //
  2094. // History:
  2095. // Gopalk Rewritten Sep 04, 96
  2096. //
  2097. //-----------------------------------------------------------------------------
  2098. #pragma SEG(COleCache_CCacheViewImpl_QueryInterface)
  2099. STDMETHODIMP COleCache::CCacheViewImpl::QueryInterface(REFIID riid, LPVOID* ppv)
  2100. {
  2101. // Validation check
  2102. VDATEHEAP();
  2103. // Get the parent object
  2104. COleCache* pOleCache = GETPPARENT(this, COleCache, m_ViewObject);
  2105. VDATETHREAD(pOleCache);
  2106. // Delegate to contolling unknown
  2107. return pOleCache->m_pUnkOuter->QueryInterface(riid, ppv);
  2108. }
  2109. //+----------------------------------------------------------------------------
  2110. //
  2111. // Member:
  2112. // COleCache::CCacheViewImpl::AddRef, public
  2113. //
  2114. // Synopsis:
  2115. // implements IUnknown::AddRef
  2116. //
  2117. // Arguments:
  2118. // none
  2119. //
  2120. // Returns:
  2121. // the object's reference count
  2122. //
  2123. //
  2124. // History:
  2125. // Gopalk Rewritten Sep 04, 96
  2126. //
  2127. //-----------------------------------------------------------------------------
  2128. #pragma SEG(COleCache_CCacheViewImpl_AddRef)
  2129. STDMETHODIMP_(ULONG) COleCache::CCacheViewImpl::AddRef(void)
  2130. {
  2131. // Validation check
  2132. VDATEHEAP();
  2133. // Get the parent object
  2134. COleCache* pOleCache = GETPPARENT(this, COleCache, m_ViewObject);
  2135. // VDATETHREAD contains a 'return HRESULT' but this procedure expects to
  2136. // return a ULONG. Disable the warning
  2137. #if ( _MSC_VER >= 800 )
  2138. #pragma warning( disable : 4245 )
  2139. #endif
  2140. VDATETHREAD(pOleCache);
  2141. #if ( _MSC_VER >= 800 )
  2142. #pragma warning( default: 4245 )
  2143. #endif
  2144. // Delegate to contolling unknown
  2145. return pOleCache->m_pUnkOuter->AddRef();
  2146. }
  2147. //+----------------------------------------------------------------------------
  2148. //
  2149. // Member:
  2150. // COleCache::CCacheViewImpl::Release, public
  2151. //
  2152. // Synopsis:
  2153. // implements IUnknown::Release
  2154. //
  2155. // Arguments:
  2156. // none
  2157. //
  2158. // Returns:
  2159. // the object's reference count
  2160. //
  2161. // History:
  2162. // Gopalk Rewritten Sep 04, 96
  2163. //
  2164. //-----------------------------------------------------------------------------
  2165. #pragma SEG(COleCache_CCacheViewImpl_Release)
  2166. STDMETHODIMP_(ULONG) COleCache::CCacheViewImpl::Release(void)
  2167. {
  2168. // Validation check
  2169. VDATEHEAP();
  2170. // Get the parent object
  2171. COleCache* pOleCache = GETPPARENT(this, COleCache, m_ViewObject);
  2172. // VDATETHREAD contains a 'return HRESULT' but this procedure expects to
  2173. // return a ULONG. Disable the warning
  2174. #if ( _MSC_VER >= 800 )
  2175. #pragma warning( disable : 4245 )
  2176. #endif
  2177. VDATETHREAD(pOleCache);
  2178. #if ( _MSC_VER >= 800 )
  2179. #pragma warning( default : 4245 )
  2180. #endif
  2181. // Delegate to contolling unknown
  2182. return pOleCache->m_pUnkOuter->Release();
  2183. }
  2184. #ifdef _CHICAGO_
  2185. //+---------------------------------------------------------------------------
  2186. //
  2187. // Method: static COleCache::DrawStackSwitch
  2188. //
  2189. // Synopsis: needed for stack switching
  2190. //
  2191. // Arguments: [pCV] --
  2192. // [dwDrawAspect] --
  2193. // [lindex] --
  2194. // [pvAspect] --
  2195. // [ptd] --
  2196. // [hicTargetDev] --
  2197. // [hdcDraw] --
  2198. // [lprcBounds] --
  2199. // [lprcWBounds] --
  2200. // [pfnContinue] --
  2201. // [DWORD] --
  2202. // [DWORD] --
  2203. // [dwContinue] --
  2204. //
  2205. // Returns:
  2206. //
  2207. // History: 5-25-95 JohannP (Johann Posch) Created
  2208. //
  2209. // Notes:
  2210. //
  2211. //----------------------------------------------------------------------------
  2212. INTERNAL COleCache::DrawStackSwitch(
  2213. LPVOID *pCV,
  2214. DWORD dwDrawAspect,
  2215. LONG lindex, void FAR* pvAspect, DVTARGETDEVICE FAR * ptd,
  2216. HDC hicTargetDev, HDC hdcDraw,
  2217. LPCRECTL lprcBounds,
  2218. LPCRECTL lprcWBounds,
  2219. BOOL (CALLBACK * pfnContinue)(ULONG_PTR),
  2220. ULONG_PTR dwContinue)
  2221. {
  2222. HRESULT hres = NOERROR;
  2223. StackDebugOut((DEB_STCKSWTCH, "COleCache::DrawStackSwitch 32->16 : pCV(%x)n", pCV));
  2224. hres = ((CCacheViewImpl *)pCV)->SSDraw(dwDrawAspect, lindex, pvAspect, ptd, hicTargetDev, hdcDraw,
  2225. lprcBounds, lprcWBounds, pfnContinue, dwContinue);
  2226. StackDebugOut((DEB_STCKSWTCH, "COleCache::DrawStackSwitch 32<-16 back; hres:%ld\n", hres));
  2227. return hres;
  2228. }
  2229. #endif // _CHICAGO_
  2230. //+----------------------------------------------------------------------------
  2231. //
  2232. // Member:
  2233. // COleCache::CCacheViewImpl::Draw, public
  2234. //
  2235. // Synopsis:
  2236. // implements IViewObject::Draw
  2237. //
  2238. // Arguments:
  2239. // [dwDrawAspect] -- a value from the DVASPECT_* enumeration
  2240. // [lindex] -- indicates what piece of the object is of
  2241. // interest; legal values vary with dwDrawAspect
  2242. // [pvAspect] -- currently NULL
  2243. // [ptd] -- the target device
  2244. // [hicTargetDev] -- in information context for [ptd]
  2245. // [hdcDraw] -- device context on which drawing is to be done
  2246. // [lprcBounds] -- boundaries of drawing on [hdcDraw]
  2247. // [lprcWBounds] -- if hdcDraw is a meta-file, it's boundaries
  2248. // [pfnContinue] --a callback function that the drawer should call
  2249. // periodically to see if rendering should be aborted.
  2250. // [dwContinue] -- passed on into [pfnContinue]
  2251. //
  2252. // Returns:
  2253. // OLE_E_BLANK, if no presentation object can be found
  2254. // REVIEW, anything from IOlePresObj::Draw
  2255. //
  2256. // Notes:
  2257. // This finds the presentation object in the cache for
  2258. // the requested format, if there is one, and then passes
  2259. // on the call to its Draw method.
  2260. //
  2261. // The use of a callback function as a parameter means that
  2262. // this interface cannot be remoted, unless some custom
  2263. // proxy is built, allowing the function to be called back in its
  2264. // original context; the interface is defined as
  2265. // [local] in common\types
  2266. //
  2267. // History:
  2268. // 01/12/95 - t-ScottH- added VDATETHREAD( GETPPARENT...)
  2269. // 11/11/93 - ChrisWe - file inspection and cleanup
  2270. // 11/30/93 - alexgo - fixed bug with GETPPARENT usage
  2271. //
  2272. //-----------------------------------------------------------------------------
  2273. #pragma SEG(COleCache_CCacheViewImpl_Draw)
  2274. STDMETHODIMP NC(COleCache,CCacheViewImpl)::Draw(
  2275. DWORD dwDrawAspect,
  2276. LONG lindex, void FAR* pvAspect, DVTARGETDEVICE FAR * ptd,
  2277. HDC hicTargetDev, HDC hdcDraw,
  2278. LPCRECTL lprcBounds,
  2279. LPCRECTL lprcWBounds,
  2280. BOOL (CALLBACK * pfnContinue)(ULONG_PTR),
  2281. ULONG_PTR dwContinue)
  2282. #ifdef _CHICAGO_
  2283. {
  2284. HRESULT hres;
  2285. // Note: Switch to the 16 bit stack under WIN95.
  2286. if (SSONBIGSTACK())
  2287. {
  2288. LEDebugOut((DEB_TRACE, "COleCache::DrawStackSwitch 32->16; this(%x)n", this));
  2289. hres = SSCall(44, SSF_SmallStack, (LPVOID)DrawStackSwitch, (DWORD) this,
  2290. (DWORD)dwDrawAspect, (DWORD)lindex,(DWORD) pvAspect, (DWORD)ptd, (DWORD)hicTargetDev,
  2291. (DWORD)hdcDraw, (DWORD)lprcBounds, (DWORD)lprcWBounds, (DWORD)pfnContinue, (DWORD)dwContinue);
  2292. }
  2293. else
  2294. hres = SSDraw(dwDrawAspect, lindex, pvAspect, ptd, hicTargetDev, hdcDraw,
  2295. lprcBounds, lprcWBounds, pfnContinue, dwContinue);
  2296. return hres;
  2297. }
  2298. //+---------------------------------------------------------------------------
  2299. //
  2300. // Method: SSDraw
  2301. //
  2302. // Synopsis: Called by Draw after switching to 16 bit stack
  2303. //
  2304. // Arguments: [dwDrawAspect] --
  2305. // [lindex] --
  2306. // [pvAspect] --
  2307. // [ptd] --
  2308. // [hicTargetDev] --
  2309. // [hdcDraw] --
  2310. // [lprcBounds] --
  2311. // [lprcWBounds] --
  2312. // [pfnContinue] --
  2313. // [DWORD] --
  2314. // [DWORD] --
  2315. // [dwContinue] --
  2316. //
  2317. // Returns:
  2318. //
  2319. // History: 5-25-95 JohannP (Johann Posch) Created
  2320. // 9-04-96 Gopalk Modifications needed for
  2321. // supporting delay loading
  2322. // of cache
  2323. // Notes:
  2324. //
  2325. //----------------------------------------------------------------------------
  2326. #pragma SEG(COleCache_CCacheViewImpl_SSDraw)
  2327. STDMETHODIMP COleCache::CCacheViewImpl::SSDraw(DWORD dwDrawAspect, LONG lindex,
  2328. void* pvAspect, DVTARGETDEVICE* ptd,
  2329. HDC hicTargetDev, HDC hdcDraw,
  2330. LPCRECTL lprcBounds,
  2331. LPCRECTL lprcWBounds,
  2332. BOOL (CALLBACK * pfnContinue)(ULONG_PTR),
  2333. ULONG_PTR dwContinue)
  2334. #endif // _CHICAGO_
  2335. {
  2336. // Validation check
  2337. VDATEHEAP();
  2338. // Get the parent object
  2339. COleCache* pOleCache = GETPPARENT(this, COleCache, m_ViewObject);
  2340. VDATETHREAD(pOleCache);
  2341. // Local variables
  2342. BOOL bMetaDC;
  2343. LPCACHENODE lpCacheNode;
  2344. // Validate parameters
  2345. if(ptd)
  2346. VDATEPTRIN(ptd, DVTARGETDEVICE);
  2347. if(lprcBounds) {
  2348. VDATEPTRIN(lprcBounds, RECTL);
  2349. }
  2350. else
  2351. return E_INVALIDARG;
  2352. if(lprcWBounds)
  2353. VDATEPTRIN(lprcWBounds, RECTL);
  2354. if(!hdcDraw)
  2355. return E_INVALIDARG;
  2356. if(!IsValidLINDEX(dwDrawAspect, lindex))
  2357. return(DV_E_LINDEX);
  2358. // Locate the cache node for the given draw parameters
  2359. lpCacheNode = pOleCache->Locate(dwDrawAspect, lindex, ptd);
  2360. // If there is no cache node, we cannot draw
  2361. if(!lpCacheNode)
  2362. return ResultFromScode(OLE_E_BLANK);
  2363. // If the DC is a metafile DC then window bounds must be valid
  2364. if((bMetaDC = OleIsDcMeta(hdcDraw)) && (lprcWBounds == NULL))
  2365. return ResultFromScode(E_INVALIDARG);
  2366. #ifdef MAC_REVIEW
  2367. A RECT value on the MAC contains members which are 'short's'. A RECTL
  2368. uses longs, and in the code below an assumption is explicitely made
  2369. that long member values is directly comp[atible on the MAC. Naturally, this is not
  2370. the case, and the compiler will barf on this.
  2371. #endif
  2372. #ifndef WIN32 // no need to do this on WIN 32 also
  2373. // On Win 16 make sure that the coordinates are valid 16bit quantities.
  2374. RECT rcBounds;
  2375. RECT rcWBounds;
  2376. if (!(IS_SMALL_INT(lprcBounds->left) &&
  2377. IS_SMALL_INT(lprcBounds->right) &&
  2378. IS_SMALL_INT(lprcBounds->top) &&
  2379. IS_SMALL_INT(lprcBounds->bottom)))
  2380. {
  2381. AssertSz(FALSE, "Rect coordinate is not a small int");
  2382. return ReportResult(0, OLE_E_INVALIDRECT, 0, 0);
  2383. }
  2384. else
  2385. {
  2386. rcBounds.left = (int) lprcBounds->left;
  2387. rcBounds.right = (int) lprcBounds->right;
  2388. rcBounds.top = (int) lprcBounds->top;
  2389. rcBounds.bottom = (int) lprcBounds->bottom;
  2390. }
  2391. if (bMetaDC)
  2392. {
  2393. if (!(IS_SMALL_INT(lprcWBounds->left) &&
  2394. IS_SMALL_INT(lprcWBounds->right) &&
  2395. IS_SMALL_INT(lprcWBounds->top) &&
  2396. IS_SMALL_INT(lprcWBounds->bottom)))
  2397. {
  2398. AssertSz(FALSE, "Rect coordinate is not a small int");
  2399. return ReportResult(0, OLE_E_INVALIDRECT, 0, 0);
  2400. }
  2401. else
  2402. {
  2403. rcWBounds.left = (int) lprcWBounds->left;
  2404. rcWBounds.right = (int) lprcWBounds->right;
  2405. rcWBounds.top = (int) lprcWBounds->top;
  2406. rcWBounds.bottom = (int) lprcWBounds->bottom;
  2407. }
  2408. }
  2409. return(lpCacheNode->Draw(pvAspect, hicTargetDev, hdcDraw,
  2410. &rcBounds, &rcWBounds, pfnContinue,
  2411. dwContinue));
  2412. #else
  2413. // on MAC as well as win 32 we can use the same pointer as it is,
  2414. // 'cause rect fields are 32 bit quantities
  2415. return(lpCacheNode->Draw(pvAspect, hicTargetDev, hdcDraw,
  2416. lprcBounds, lprcWBounds, pfnContinue,
  2417. dwContinue));
  2418. #endif
  2419. }
  2420. //+----------------------------------------------------------------------------
  2421. //
  2422. // Member:
  2423. // COleCache::CCacheViewImpl::GetColorSet, public
  2424. //
  2425. // Synopsis:
  2426. // implements IViewObject::GetColorSet
  2427. //
  2428. // Arguments:
  2429. // [dwDrawAspect] -- a value from the DVASPECT_* enumeration
  2430. // [lindex] -- indicates what piece of the object is of
  2431. // interest; legal values vary with dwDrawAspect
  2432. // [pvAspect] -- currently NULL
  2433. // [ptd] -- the target device
  2434. // [hicTargetDev] -- in information context for [ptd]
  2435. // [ppColorSet] -- the color set required for the requested
  2436. // rendering
  2437. //
  2438. // Returns:
  2439. // OLE_E_BLANK, if no presentation object can be found
  2440. // REVIEW, anything from IOlePresObj::Draw
  2441. //
  2442. // Notes:
  2443. // Finds a presentation object in the cache that matches the
  2444. // requested rendering, if there is one, and asks the
  2445. // presentation object for the color set.
  2446. //
  2447. // History:
  2448. // 09/04/96 - Gopalk - Modifications needed for
  2449. // supporting delay loading
  2450. // of cache
  2451. // 01/12/95 - t-ScottH- added VDATETHREAD( GETPPARENT...)
  2452. // 11/11/93 - ChrisWe - file inspection and cleanup
  2453. // 11/30/93 - alexgo - fixed bug with GETPPARENT usage
  2454. //
  2455. //-----------------------------------------------------------------------------
  2456. #pragma SEG(COleCache_CCacheViewImpl_GetColorSet)
  2457. STDMETHODIMP COleCache::CCacheViewImpl::GetColorSet(DWORD dwDrawAspect,
  2458. LONG lindex, void* pvAspect,
  2459. DVTARGETDEVICE* ptd,
  2460. HDC hicTargetDev,
  2461. LPLOGPALETTE* ppColorSet)
  2462. {
  2463. // Validation check
  2464. VDATEHEAP();
  2465. // Get the parent object
  2466. COleCache* pOleCache = GETPPARENT(this, COleCache, m_ViewObject);
  2467. VDATETHREAD(pOleCache);
  2468. // Local variables
  2469. LPCACHENODE lpCacheNode;
  2470. // Initialize color set
  2471. *ppColorSet = NULL;
  2472. // Vaidate the parameters
  2473. if(!IsValidLINDEX(dwDrawAspect, lindex))
  2474. return(DV_E_LINDEX);
  2475. // Locate the cache node for the given draw parameters
  2476. lpCacheNode = pOleCache->Locate(dwDrawAspect, lindex, ptd);
  2477. // If there is no cache node, we cannot draw
  2478. if(!lpCacheNode)
  2479. return ResultFromScode(OLE_E_BLANK);
  2480. return(lpCacheNode->GetColorSet(pvAspect, hicTargetDev, ppColorSet));
  2481. }
  2482. //+----------------------------------------------------------------------------
  2483. //
  2484. // Member:
  2485. // COleCache::CCacheViewImpl, public
  2486. //
  2487. // Synopsis:
  2488. // implements IViewObject::Freeze
  2489. //
  2490. // Arguments:
  2491. // [dwDrawAspect] -- a value from the DVASPECT_* enumeration
  2492. // [lindex] -- indicates what piece of the object is of
  2493. // interest; legal values vary with dwDrawAspect
  2494. // [pvAspect] -- currently NULL
  2495. // [pdwFreeze] -- a token that can later be used to unfreeze
  2496. // this aspects cached presentations
  2497. //
  2498. // Returns:
  2499. // OLE_E_BLANK, if no presentation is found that matches the
  2500. // requested characteristics
  2501. //
  2502. // Notes:
  2503. // The current implementation returns the ASPECT+FREEZE_CONSTANT
  2504. // as the FreezeID. At Unfreeze time we get the ASPECT by doing
  2505. // FreezeID-FREEZE_CONSTANT.
  2506. //
  2507. // REVIEW: In future where we allow lindexes other than DEF_LINDEX,
  2508. // we will have to use some other scheme for generating the
  2509. // FreezeID.
  2510. //
  2511. // History:
  2512. // Gopalk Rewritten Sep 04, 96
  2513. //
  2514. //-----------------------------------------------------------------------------
  2515. #pragma SEG(COleCache_CCacheViewImpl_Freeze)
  2516. STDMETHODIMP COleCache::CCacheViewImpl::Freeze(DWORD dwAspect, LONG lindex,
  2517. LPVOID pvAspect, DWORD* pdwFreeze)
  2518. {
  2519. // Validation check
  2520. VDATEHEAP();
  2521. // Get the parent object
  2522. COleCache* pOleCache = GETPPARENT(this, COleCache, m_ViewObject);
  2523. VDATETHREAD(pOleCache);
  2524. // Local variables
  2525. ULONG index, cntFrozenNodes;
  2526. LPCACHENODE lpCacheNode;
  2527. const FORMATETC* pforetc;
  2528. // Validate parameters
  2529. if(pdwFreeze) {
  2530. VDATEPTROUT(pdwFreeze, DWORD);
  2531. *pdwFreeze = 0;
  2532. }
  2533. VERIFY_ASPECT_SINGLE(dwAspect);
  2534. if(!IsValidLINDEX(dwAspect, lindex))
  2535. return(DV_E_LINDEX);
  2536. // Check if the aspect has already been frozen
  2537. if(pOleCache->m_dwFrozenAspects & dwAspect) {
  2538. // Set the freeze id
  2539. if(pdwFreeze)
  2540. *pdwFreeze = dwAspect + FREEZE_CONSTANT;
  2541. return ResultFromScode(VIEW_S_ALREADY_FROZEN);
  2542. }
  2543. // Freeze the cache nodes including native cache node
  2544. pOleCache->m_pCacheArray->Reset(index);
  2545. cntFrozenNodes = 0;
  2546. for(unsigned long i=0; i<pOleCache->m_pCacheArray->Length(); i++) {
  2547. lpCacheNode = pOleCache->m_pCacheArray->GetNext(index);
  2548. pforetc = lpCacheNode->GetFormatEtc();
  2549. if(pforetc->dwAspect == dwAspect && pforetc->lindex == lindex)
  2550. if(lpCacheNode->Freeze() == NOERROR)
  2551. cntFrozenNodes++;
  2552. }
  2553. // Check if we froze any cache nodes
  2554. if(cntFrozenNodes) {
  2555. // Add this aspect to the frozen aspects.
  2556. pOleCache->m_dwFrozenAspects |= dwAspect;
  2557. // Set the freeze id
  2558. if(pdwFreeze)
  2559. *pdwFreeze = dwAspect + FREEZE_CONSTANT;
  2560. return(NOERROR);
  2561. }
  2562. // No cache node matched the requested characteristics
  2563. return ResultFromScode(OLE_E_BLANK);
  2564. }
  2565. //+----------------------------------------------------------------------------
  2566. //
  2567. // Member:
  2568. // COleCache::CCacheViewImpl::Unfreeze, public
  2569. //
  2570. // Synopsis:
  2571. // implements IViewObject::Unfreeze
  2572. //
  2573. // Arguments:
  2574. // [dwFreezeId] -- the id returned by Freeze() when some aspect
  2575. // was frozen earlier
  2576. //
  2577. // Returns:
  2578. // OLE_E_NOCONNECTION, if dwFreezeId is invalid
  2579. // S_OK, otherwise
  2580. //
  2581. // Notes:
  2582. // See notes for Freeze().
  2583. //
  2584. //
  2585. // History:
  2586. // Gopalk Rewritten Sep 04, 96
  2587. //
  2588. //-----------------------------------------------------------------------------
  2589. #pragma SEG(COleCache_CCacheViewImpl_Unfreeze)
  2590. STDMETHODIMP COleCache::CCacheViewImpl::Unfreeze(DWORD dwFreezeId)
  2591. {
  2592. // Validation check
  2593. VDATEHEAP();
  2594. // Get the parent object
  2595. COleCache* pOleCache = GETPPARENT(this, COleCache, m_ViewObject);
  2596. VDATETHREAD(pOleCache);
  2597. // Local variables
  2598. BOOL fAnyUpdated = FALSE, fUpdated;
  2599. ULONG index, cntUnfrozenNodes;
  2600. DWORD dwAspect = dwFreezeId - FREEZE_CONSTANT;
  2601. LONG lindex = DEF_LINDEX;
  2602. LPCACHENODE lpCacheNode;
  2603. const FORMATETC* pforetc;
  2604. // Atleast one and not more than one bit should be set in dwAspect
  2605. if(!(dwAspect && !(dwAspect & (dwAspect-1)) && (dwAspect <= MAX_VALID_ASPECT)))
  2606. return ResultFromScode(OLE_E_NOCONNECTION);
  2607. // Make sure that this aspect is frozen
  2608. if (!(pOleCache->m_dwFrozenAspects & dwAspect))
  2609. return ResultFromScode(OLE_E_NOCONNECTION);
  2610. // Unfreeze the cache nodes including native cache node
  2611. pOleCache->m_pCacheArray->Reset(index);
  2612. cntUnfrozenNodes = 0;
  2613. for(unsigned long i=0; i<pOleCache->m_pCacheArray->Length(); i++) {
  2614. // Get the next cache node
  2615. lpCacheNode = pOleCache->m_pCacheArray->GetNext(index);
  2616. // lpCacheNode cannot be null
  2617. Win4Assert(lpCacheNode);
  2618. // Get the formatetc of the cache node
  2619. pforetc = lpCacheNode->GetFormatEtc();
  2620. if(pforetc->dwAspect == dwAspect && pforetc->lindex == lindex)
  2621. if(lpCacheNode->Unfreeze(fUpdated) == NOERROR) {
  2622. if(fUpdated)
  2623. fAnyUpdated = TRUE;
  2624. cntUnfrozenNodes++;
  2625. }
  2626. }
  2627. // Check if we unfroze any cache nodes
  2628. if(cntUnfrozenNodes) {
  2629. // Remove this aspect from frozen aspects
  2630. pOleCache->m_dwFrozenAspects &= ~dwAspect;
  2631. }
  2632. // Check if the aspect has changed
  2633. if(fAnyUpdated)
  2634. pOleCache->AspectsUpdated(dwAspect);
  2635. return NOERROR;
  2636. }
  2637. //+----------------------------------------------------------------------------
  2638. //
  2639. // Member:
  2640. // COleCache::CCacheViewImpl::SetAdvise, public
  2641. //
  2642. // Synopsis:
  2643. // implements IViewObject::SetAdvise
  2644. //
  2645. // Arguments:
  2646. // [aspects] -- the aspects the sink would like to be advised of
  2647. // changes to
  2648. // [advf] -- advise control flags from ADVF_*
  2649. // [pAdvSink] -- the advise sink
  2650. //
  2651. // Returns:
  2652. // E_INVALIDARG
  2653. // S_OK
  2654. //
  2655. // Notes:
  2656. // Only one advise sink is allowed at a time. If a second one
  2657. // is registered, the first one is released.
  2658. //
  2659. // History:
  2660. // Gopalk Rewritten Sep 04, 96
  2661. //
  2662. //-----------------------------------------------------------------------------
  2663. #pragma SEG(COleCache_CCacheViewImpl_SetAdvise)
  2664. STDMETHODIMP COleCache::CCacheViewImpl::SetAdvise(DWORD aspects, DWORD advf,
  2665. IAdviseSink* pAdvSink)
  2666. {
  2667. // Validation check
  2668. VDATEHEAP();
  2669. // Get the parent object
  2670. COleCache* pOleCache = GETPPARENT(this, COleCache, m_ViewObject);
  2671. VDATETHREAD(pOleCache);
  2672. // Validate parameters
  2673. if(pAdvSink)
  2674. VDATEIFACE(pAdvSink);
  2675. if(aspects & ~(DVASPECT_CONTENT | DVASPECT_THUMBNAIL |
  2676. DVASPECT_ICON|DVASPECT_DOCPRINT)) {
  2677. Win4Assert(FALSE);
  2678. return ResultFromScode(E_INVALIDARG);
  2679. }
  2680. // ADVF_NODATA is not valid because there is no way to send data
  2681. // using IAdviseSink::OnViewChange
  2682. if(advf & ADVF_NODATA)
  2683. return ResultFromScode(E_INVALIDARG);
  2684. // We allow only one view advise at any given time,
  2685. // so Release the old sink.
  2686. if (pOleCache->m_pViewAdvSink)
  2687. pOleCache->m_pViewAdvSink->Release();
  2688. // Remember the new sink
  2689. if((pOleCache->m_pViewAdvSink = pAdvSink)) {
  2690. // Add ref the new advise sink
  2691. pAdvSink->AddRef();
  2692. // Save the advice flags and aspects
  2693. pOleCache->m_advfView = advf;
  2694. pOleCache->m_aspectsView = aspects;
  2695. // If ADVF_PRIMEFIRST is set, send OnViewChange immediately
  2696. if(advf & ADVF_PRIMEFIRST) {
  2697. pOleCache->m_pViewAdvSink->OnViewChange(aspects, DEF_LINDEX);
  2698. // If ADVF_ONLYONCE is set, free the advise sink
  2699. if (pOleCache->m_advfView & ADVF_ONLYONCE) {
  2700. pOleCache->m_pViewAdvSink->Release();
  2701. pOleCache->m_pViewAdvSink = NULL;
  2702. pOleCache->m_advfView = 0;
  2703. pOleCache->m_aspectsView = 0;
  2704. }
  2705. }
  2706. }
  2707. return NOERROR;
  2708. }
  2709. //+----------------------------------------------------------------------------
  2710. //
  2711. // Member:
  2712. // COleCache::CCacheViewImpl::GetAdvise, public
  2713. //
  2714. // Synopsis:
  2715. // implement IViewObject::GetAdvise
  2716. //
  2717. // Arguments:
  2718. // [pAspects] -- a pointer to where to return the aspects the
  2719. // current advise sink is interested in
  2720. // [pAdvf] -- a pointer to where to return the advise control
  2721. // flags for the current advise sink
  2722. // [ppAdvSink] -- a pointer to where to return a reference to
  2723. // the current advise sink
  2724. //
  2725. // Returns:
  2726. // S_OK
  2727. //
  2728. //
  2729. // History:
  2730. // Gopalk Rewritten Sep 04, 96
  2731. //
  2732. //-----------------------------------------------------------------------------
  2733. #pragma SEG(COleCache_CCacheViewImpl_GetAdvise)
  2734. STDMETHODIMP COleCache::CCacheViewImpl::GetAdvise(DWORD* pAspects, DWORD* pAdvf,
  2735. IAdviseSink** ppAdvSink)
  2736. {
  2737. // Validation check
  2738. VDATEHEAP();
  2739. // Get the parent object
  2740. COleCache* pOleCache = GETPPARENT(this, COleCache, m_ViewObject);
  2741. VDATETHREAD(pOleCache);
  2742. // Validate parameters
  2743. if(ppAdvSink) {
  2744. VDATEPTROUT(ppAdvSink, IAdviseSink*);
  2745. *ppAdvSink = NULL;
  2746. }
  2747. if(pAspects) {
  2748. VDATEPTROUT(pAspects, DWORD);
  2749. *pAspects = 0;
  2750. }
  2751. if(pAdvf) {
  2752. VDATEPTROUT(pAdvf, DWORD);
  2753. *pAdvf = 0;
  2754. }
  2755. // Check if an AdviseSink is registered
  2756. if(pOleCache->m_pViewAdvSink) {
  2757. if(pAspects)
  2758. *pAspects = pOleCache->m_aspectsView;
  2759. if(pAdvf)
  2760. *pAdvf = pOleCache->m_advfView;
  2761. if(ppAdvSink)
  2762. (*ppAdvSink = pOleCache->m_pViewAdvSink)->AddRef();
  2763. }
  2764. return NOERROR;
  2765. }
  2766. //+----------------------------------------------------------------------------
  2767. //
  2768. // Member:
  2769. // COleCache::CCacheViewImpl::GetExtent, public
  2770. //
  2771. // Synopsis:
  2772. // implements IViewObject::GetExtent
  2773. //
  2774. // Arguments:
  2775. // [dwDrawAspect] -- the aspect for which we'd like the extent
  2776. // [lindex] -- the lindex for which we'd like the extent
  2777. // [ptd] -- pointer to the target device descriptor
  2778. // [lpsizel] -- pointer to where to return the extent
  2779. //
  2780. // Returns:
  2781. // OLE_E_BLANK, if no presentation can be found that matches
  2782. // (dwDrawAspect, lindex)
  2783. // History:
  2784. // Gopalk Rewritten Sep 04, 96
  2785. //
  2786. //-----------------------------------------------------------------------------
  2787. #pragma SEG(COleCache_CCacheViewImpl_GetExtent)
  2788. STDMETHODIMP COleCache::CCacheViewImpl::GetExtent(DWORD dwDrawAspect,
  2789. LONG lindex,
  2790. DVTARGETDEVICE* ptd,
  2791. LPSIZEL lpsizel)
  2792. {
  2793. // Validation check
  2794. VDATEHEAP();
  2795. // Get the parent object
  2796. COleCache* pOleCache = GETPPARENT(this, COleCache, m_ViewObject);
  2797. VDATETHREAD(pOleCache);
  2798. // Local variable
  2799. LPCACHENODE lpCacheNode;
  2800. // Validate parameters
  2801. VDATEPTROUT(lpsizel, SIZEL);
  2802. if(!IsValidLINDEX(dwDrawAspect, lindex))
  2803. return(DV_E_LINDEX);
  2804. if(ptd)
  2805. VDATEPTRIN(ptd, DVTARGETDEVICE);
  2806. // Locate the cache node for the given draw parameters
  2807. lpCacheNode = pOleCache->Locate(dwDrawAspect, lindex, ptd);
  2808. // If there is no cache node, we cannot draw
  2809. if(!lpCacheNode)
  2810. return ResultFromScode(OLE_E_BLANK);
  2811. return(lpCacheNode->GetExtent(dwDrawAspect, lpsizel));
  2812. }
  2813. // IPersistStorage implementation
  2814. //+----------------------------------------------------------------------------
  2815. //
  2816. // Member:
  2817. // COleCache::GetClassID, public
  2818. //
  2819. // Synopsis:
  2820. // implements IPersist::GetClassID
  2821. //
  2822. // Arguments:
  2823. // [pClassID] -- pointer to where to return class id
  2824. //
  2825. // History:
  2826. // Gopalk Rewritten Sep 04, 96
  2827. //
  2828. //-----------------------------------------------------------------------------
  2829. #pragma SEG(COleCache_GetClassID)
  2830. STDMETHODIMP COleCache::GetClassID(LPCLSID pClassID)
  2831. {
  2832. // Validation checks
  2833. VDATEHEAP();
  2834. VDATETHREAD(this);
  2835. VDATEPTROUT(pClassID, CLSID);
  2836. *pClassID = m_clsid;
  2837. return NOERROR;
  2838. }
  2839. //+----------------------------------------------------------------------------
  2840. //
  2841. // Member:
  2842. // COleCache::IsDirty, public
  2843. //
  2844. // Synopsis:
  2845. // implements IPersistStorage::IsDirty
  2846. //
  2847. // Arguments:
  2848. // none
  2849. //
  2850. // Returns:
  2851. // S_FALSE, if the object does not need saving
  2852. // S_OK otherwise
  2853. //
  2854. // History:
  2855. // Gopalk Rewritten Sep 04, 96
  2856. //
  2857. //-----------------------------------------------------------------------------
  2858. #pragma SEG(COleCache_IsDirty)
  2859. STDMETHODIMP COleCache::IsDirty(void)
  2860. {
  2861. // Validation check
  2862. VDATEHEAP();
  2863. VDATETHREAD(this);
  2864. // Local variables
  2865. ULONG index;
  2866. LPCACHENODE lpCacheNode;
  2867. // Check if the cache is in loaded state
  2868. if(!(m_ulFlags & COLECACHEF_LOADEDSTATE))
  2869. return(NOERROR);
  2870. // Start the enumeration of the cache nodes at the right start point
  2871. if(m_ulFlags & COLECACHEF_STATIC)
  2872. m_pCacheArray->Reset(index, TRUE);
  2873. else
  2874. m_pCacheArray->Reset(index, FALSE);
  2875. // Enumerate the cache nodes
  2876. while(lpCacheNode = m_pCacheArray->GetNext(index))
  2877. if(!lpCacheNode->InLoadedState()) {
  2878. m_ulFlags &= ~COLECACHEF_LOADEDSTATE;
  2879. return NOERROR;
  2880. }
  2881. // Cache is not dirty
  2882. return S_FALSE;
  2883. }
  2884. //+----------------------------------------------------------------------------
  2885. //
  2886. // Member:
  2887. // COleCache::InitNew, public
  2888. //
  2889. // Synopsis:
  2890. // implements IPersistStorage::InitNew
  2891. //
  2892. // Arguments:
  2893. // [pstg] -- the storage the object can use until saved
  2894. //
  2895. // Returns:
  2896. // S_OK
  2897. //
  2898. // History:
  2899. // Gopalk Rewritten Sep 04, 96
  2900. //
  2901. //-----------------------------------------------------------------------------
  2902. #pragma SEG(COleCache_InitNew)
  2903. STDMETHODIMP COleCache::InitNew(LPSTORAGE pstg)
  2904. {
  2905. // Validation checks
  2906. VDATEHEAP();
  2907. VDATETHREAD(this);
  2908. VDATEIFACE(pstg);
  2909. // Local variable
  2910. LPCACHENODE lpCacheNode;
  2911. // Check if m_pStg is already set
  2912. if(m_pStg)
  2913. return ResultFromScode(CO_E_ALREADYINITIALIZED);
  2914. // Save and add ref the storage
  2915. (m_pStg = pstg)->AddRef();
  2916. // Find the native object format to add native cache node
  2917. FindObjectFormat(pstg);
  2918. // Set the storage on the already cached nodes
  2919. if((!m_pCacheArray->GetItem(1) && m_pCacheArray->Length()) ||
  2920. (m_pCacheArray->GetItem(1) && m_pCacheArray->Length()>1)) {
  2921. ULONG index;
  2922. // Enumerate the cache nodes excluding native cache node
  2923. m_pCacheArray->Reset(index, FALSE);
  2924. while(lpCacheNode = m_pCacheArray->GetNext(index))
  2925. lpCacheNode->SetStg(pstg);
  2926. }
  2927. // Check if the native object has been successfully created
  2928. if(m_ulFlags & COLECACHEF_FORMATKNOWN) {
  2929. // Obtain the native cache node.
  2930. if(!(lpCacheNode = m_pCacheArray->GetItem(1)))
  2931. return ResultFromScode(E_OUTOFMEMORY);
  2932. // Static objects cannot have a server
  2933. if(m_ulFlags & COLECACHEF_STATIC)
  2934. Win4Assert(!m_pDataObject);
  2935. // Check if native cache node has just been created
  2936. if(!lpCacheNode->GetStg()) {
  2937. // Set the storage for the native cache node
  2938. lpCacheNode->SetStg(pstg);
  2939. // Set up the advise connection if the object is already running
  2940. if(m_pDataObject)
  2941. lpCacheNode->SetupAdviseConnection(m_pDataObject,
  2942. (IAdviseSink *) &m_AdviseSink);
  2943. }
  2944. }
  2945. // The spec for InitNew requires that the object should be marked dirty
  2946. // See Nt bug 284729.
  2947. m_ulFlags &= ~COLECACHEF_LOADEDSTATE;
  2948. return NOERROR;
  2949. }
  2950. //+----------------------------------------------------------------------------
  2951. //
  2952. // Member:
  2953. // COleCache::Load, public
  2954. //
  2955. // Synopsis:
  2956. // Called by DefHandler and DefLink when cache is empty
  2957. //
  2958. // Arguments:
  2959. // [pstg] [in] -- the storage to load from
  2960. // [fCacheEmpty] [in] -- Set to TRUE when cache is empty
  2961. //
  2962. // Returns:
  2963. // HRESULT
  2964. //
  2965. // History:
  2966. // Gopalk Creation Oct 24, 96
  2967. //
  2968. //-----------------------------------------------------------------------------
  2969. HRESULT COleCache::Load(LPSTORAGE pstg, BOOL fCacheEmpty)
  2970. {
  2971. // Check if m_pStg is already set
  2972. if(m_pStg)
  2973. return ResultFromScode(CO_E_ALREADYINITIALIZED);
  2974. // If Cache is not empty, follow normal load
  2975. if(!fCacheEmpty)
  2976. return Load(pstg);
  2977. else {
  2978. // Validation checks
  2979. VDATEHEAP();
  2980. VDATETHREAD(this);
  2981. VDATEIFACE(pstg);
  2982. // Save the storage
  2983. (m_pStg = pstg)->AddRef();
  2984. // Assert that there is no native cache node
  2985. Win4Assert(!m_pCacheArray->GetItem(1));
  2986. // Set the storage on the already cached nodes
  2987. if(m_pCacheArray->Length()) {
  2988. ULONG index;
  2989. LPCACHENODE lpCacheNode;
  2990. // Enumerate the cache nodes including native cache node
  2991. m_pCacheArray->Reset(index);
  2992. while(lpCacheNode = m_pCacheArray->GetNext(index))
  2993. lpCacheNode->SetStg(pstg);
  2994. }
  2995. else {
  2996. // Cache is in loaded state
  2997. m_ulFlags |= COLECACHEF_LOADEDSTATE;
  2998. }
  2999. }
  3000. #if DBG==1
  3001. // Ensure that the storage is really empty in Debug builds
  3002. HRESULT error;
  3003. LPSTREAM lpstream;
  3004. error = pstg->OpenStream(OLE_PRESENTATION_STREAM, NULL,
  3005. (STGM_READ | STGM_SHARE_EXCLUSIVE),
  3006. 0, &lpstream);
  3007. Win4Assert(error==STG_E_FILENOTFOUND);
  3008. #endif // DBG==1
  3009. return NOERROR;
  3010. }
  3011. //+----------------------------------------------------------------------------
  3012. //
  3013. // Member:
  3014. // COleCache::Load, public
  3015. //
  3016. // Synopsis:
  3017. // implements IPersistStorage::Load
  3018. //
  3019. // Arguments:
  3020. // [pstg] -- the storage to load from
  3021. //
  3022. // Returns:
  3023. // Various storage errors and S_OK
  3024. //
  3025. // Notes:
  3026. // Presentations are loaded from sequentially numbered
  3027. // streams, stopping at the first one that cannot be found.
  3028. //
  3029. // History:
  3030. // Gopalk Rewritten Sep 04, 96
  3031. //
  3032. //-----------------------------------------------------------------------------
  3033. #pragma SEG(COleCache_Load)
  3034. STDMETHODIMP COleCache::Load(LPSTORAGE pstg)
  3035. {
  3036. // Validation checks
  3037. VDATEHEAP();
  3038. VDATETHREAD(this);
  3039. VDATEIFACE(pstg);
  3040. // Local variables
  3041. CLSID clsid;
  3042. HRESULT error = NOERROR;
  3043. BOOL fCachedBefore = FALSE, fCachesLoaded = FALSE;
  3044. ULONG ulLastIndex;
  3045. LPCACHENODE lpCacheNode;
  3046. // Check if m_pStg is already set
  3047. if(m_pStg)
  3048. return ResultFromScode(CO_E_ALREADYINITIALIZED);
  3049. // Save the storage
  3050. m_pStg = pstg;
  3051. // Find the native object format
  3052. FindObjectFormat(pstg);
  3053. // Set the storage on the already cached nodes
  3054. if((!m_pCacheArray->GetItem(1) && m_pCacheArray->Length()) ||
  3055. (m_pCacheArray->GetItem(1) && m_pCacheArray->Length()>1)) {
  3056. // Presentations were cached before load
  3057. Win4Assert(FALSE);
  3058. fCachedBefore = TRUE;
  3059. // Enumerate the cache nodes excluding native cache node
  3060. m_pCacheArray->Reset(ulLastIndex, FALSE);
  3061. while(lpCacheNode = m_pCacheArray->GetNext(ulLastIndex))
  3062. lpCacheNode->SetStg(pstg);
  3063. }
  3064. // Check if the native object is a static object
  3065. if(m_ulFlags & COLECACHEF_STATIC) {
  3066. UINT uiStatus;
  3067. // Static objects cannot have a server
  3068. Win4Assert(!m_pDataObject);
  3069. // Old static objects wrote data into the OLE_PRESENTATION_STREAM
  3070. // rather than the CONTENTS stream.
  3071. // If we have such a static object, we need to convert it
  3072. error = UtOlePresStmToContentsStm(pstg, OLE_PRESENTATION_STREAM,
  3073. TRUE, &uiStatus);
  3074. Win4Assert(error==NOERROR);
  3075. if(error != NOERROR)
  3076. return error;
  3077. }
  3078. if(m_ulFlags & COLECACHEF_FORMATKNOWN) {
  3079. // Obtain the native cache node.
  3080. if(!(lpCacheNode = m_pCacheArray->GetItem(1)))
  3081. return ResultFromScode(E_OUTOFMEMORY);
  3082. // Check if native cache node has just been created
  3083. if(!lpCacheNode->GetStg()) {
  3084. // Set the storage for the native cache node
  3085. lpCacheNode->SetStg(pstg);
  3086. // Set up the advise connection if the object is already running
  3087. if(m_pDataObject)
  3088. lpCacheNode->SetupAdviseConnection(m_pDataObject,
  3089. (IAdviseSink *) &m_AdviseSink);
  3090. }
  3091. // Ensure that native cache node is not blank before
  3092. // delay loading the presentation from native stream
  3093. if(lpCacheNode->IsBlank())
  3094. lpCacheNode->Load(NULL, OLE_INVALID_STREAMNUM, TRUE);
  3095. }
  3096. if(error == NOERROR) {
  3097. int iPresStreamNum=0;
  3098. ULONG index;
  3099. LPSTREAM lpstream;
  3100. OLECHAR szName[sizeof(OLE_PRESENTATION_STREAM)/sizeof(OLECHAR)];
  3101. CCacheNode BlankCache;
  3102. // Start with presentation stream 0
  3103. lstrcpyW(szName, OLE_PRESENTATION_STREAM);
  3104. // Load the presentation streams
  3105. while(TRUE) {
  3106. // Open the presentation stream
  3107. lpstream = NULL;
  3108. error = pstg->OpenStream(szName, NULL, (STGM_READ | STGM_SHARE_EXCLUSIVE),
  3109. 0, &lpstream);
  3110. if(error != NOERROR) {
  3111. if(GetScode(error) == STG_E_FILENOTFOUND) {
  3112. // Presentation stream does not exist. No error
  3113. error = NOERROR;
  3114. }
  3115. break;
  3116. }
  3117. // Presentation stream exists. Add a blank cache node
  3118. index = m_pCacheArray->AddItem(BlankCache);
  3119. if(!index) {
  3120. error = ResultFromScode(E_OUTOFMEMORY);
  3121. break;
  3122. }
  3123. lpCacheNode = m_pCacheArray->GetItem(index);
  3124. Win4Assert(lpCacheNode);
  3125. // Load the presentation from the stream
  3126. if(!iPresStreamNum) {
  3127. // Do not delay load presentation
  3128. error = lpCacheNode->Load(lpstream, iPresStreamNum, FALSE);
  3129. if(error == NOERROR)
  3130. fCachesLoaded = TRUE;
  3131. }
  3132. else {
  3133. // Delay load the presentation
  3134. error = lpCacheNode->Load(lpstream, iPresStreamNum, TRUE);
  3135. }
  3136. if(error != NOERROR)
  3137. break;
  3138. // Set the storage on the cache node
  3139. lpCacheNode->SetStg(pstg);
  3140. // If the server is runinng, set the advise connection
  3141. // We ignore the errors in setting up advise connection. Gopalk
  3142. if(m_pDataObject)
  3143. lpCacheNode->SetupAdviseConnection(m_pDataObject,
  3144. (IAdviseSink *) &m_AdviseSink);
  3145. // Check if TOC exists at the end of presentation stream 0
  3146. if(!iPresStreamNum)
  3147. if(LoadTOC(lpstream, pstg) == NOERROR)
  3148. break;
  3149. // Release the stream
  3150. lpstream->Release();
  3151. lpstream = NULL;
  3152. // Get the next presentation stream name
  3153. UtGetPresStreamName(szName, ++iPresStreamNum);
  3154. }
  3155. if(lpstream)
  3156. lpstream->Release();
  3157. lpstream = NULL;
  3158. }
  3159. if(error == NOERROR) {
  3160. // Addref the storage
  3161. m_pStg->AddRef();
  3162. // For static object remove all the caches other than those with
  3163. // iconic aspect
  3164. if(m_ulFlags & COLECACHEF_STATIC) {
  3165. ULONG index, indexToUncache = 0;
  3166. const FORMATETC* lpforetc;
  3167. // Start the enumeration after native cache node
  3168. m_pCacheArray->Reset(index, FALSE);
  3169. while(lpCacheNode = m_pCacheArray->GetNext(index)) {
  3170. lpforetc = lpCacheNode->GetFormatEtc();
  3171. if(lpforetc->dwAspect != DVASPECT_ICON) {
  3172. // Uncache any previous index that needs to be uncached
  3173. if(indexToUncache)
  3174. Uncache(indexToUncache);
  3175. // Remember the new index that needs to be uncached
  3176. indexToUncache = index;
  3177. }
  3178. }
  3179. // Uncache any remaining index that needs to be uncached
  3180. if(indexToUncache)
  3181. Uncache(indexToUncache);
  3182. }
  3183. // Check if presentation were cached before load
  3184. if(fCachedBefore) {
  3185. // Check if any presentation were loaded from disk
  3186. if(fCachesLoaded) {
  3187. // Shift the newly cached nodes to the end
  3188. // This is needed to allow presentation
  3189. // streams to be renamed during save
  3190. m_pCacheArray->ShiftToEnd(ulLastIndex);
  3191. }
  3192. }
  3193. else {
  3194. // Cache is in loaded state
  3195. m_ulFlags |= COLECACHEF_LOADEDSTATE;
  3196. }
  3197. }
  3198. else {
  3199. if(m_pDataObject) {
  3200. ULONG index;
  3201. // Tear down the advise connection set up earlier
  3202. m_pCacheArray->Reset(index);
  3203. while(lpCacheNode = m_pCacheArray->GetNext(index))
  3204. lpCacheNode->TearDownAdviseConnection(m_pDataObject);
  3205. }
  3206. // Delete all cache nodes
  3207. m_pCacheArray->DeleteAllItems();
  3208. // Reset the storage
  3209. m_pStg = NULL;
  3210. }
  3211. return error;
  3212. }
  3213. //+----------------------------------------------------------------------------
  3214. //
  3215. // Member:
  3216. // COleCache::Save, public
  3217. //
  3218. // Synopsis:
  3219. // implements IPersistStorage::Save
  3220. //
  3221. // Arguments:
  3222. // [pstgSave] -- the storage to use to save this
  3223. // [fSameAsLoad] -- is this the same storage we loaded from?
  3224. //
  3225. // Returns:
  3226. // Various storage errors
  3227. //
  3228. // Notes:
  3229. // All the caches are saved to streams with sequential numeric
  3230. // names. Also TOC is saved at the end of presentation 0
  3231. //
  3232. //
  3233. // History:
  3234. // Gopalk Rewritten Sep 04, 96
  3235. //
  3236. //-----------------------------------------------------------------------------
  3237. #pragma SEG(COleCache_Save)
  3238. STDMETHODIMP COleCache::Save(LPSTORAGE pstgSave, BOOL fSameAsLoad)
  3239. {
  3240. // Validation checks
  3241. VDATEHEAP();
  3242. VDATETHREAD(this);
  3243. VDATEIFACE(pstgSave);
  3244. // Local variables
  3245. HRESULT error, rerror = NOERROR;
  3246. ULONG index, cntCachesNotSaved;
  3247. int iPresStreamNum;
  3248. LPCACHENODE lpCacheNode;
  3249. // Check if we are in no scribble mode
  3250. // According to spec, SaveCompleted be should after Save to reset
  3251. // NOSCRIBBLEMODE. Insisting on the spec is causing some apps
  3252. // like ClipArt Gallery to break. Turn off the check. Gopalk
  3253. //if(m_ulFlags & COLECACHEF_NOSCRIBBLEMODE)
  3254. // return E_UNEXPECTED;
  3255. // If fSameAsLoad, assert that the current storage is same as given storage
  3256. // Some apps will violate this assert because for SaveAs case, they copy the
  3257. // existing storage to a new storage and call save on the new storage with
  3258. // fSameAsLoad set to TRUE. They subsequently either call SaveCompleted with
  3259. // the new storage or call SaveCompleted with NULL storage, HandsOffStorage,
  3260. // and SaveCompleted with the new storage in sequence. Gopalk
  3261. if(fSameAsLoad)
  3262. Win4Assert(m_pStg==pstgSave);
  3263. // Cache need not be saved if fSameAsLoad and not dirty
  3264. if(!fSameAsLoad || IsDirty()==NOERROR) {
  3265. // Reset the stream number
  3266. iPresStreamNum = 0;
  3267. // Check if the cache is empty
  3268. if(m_pCacheArray->Length()) {
  3269. // Cache is not empty
  3270. // Save the native cache node only if it is a static object
  3271. if(m_ulFlags & COLECACHEF_STATIC) {
  3272. lpCacheNode = m_pCacheArray->GetItem(1);
  3273. Win4Assert(lpCacheNode);
  3274. lpCacheNode->Save(pstgSave, fSameAsLoad, OLE_INVALID_STREAMNUM);
  3275. }
  3276. // Enumerate the cache nodes excluding the native cache node
  3277. m_pCacheArray->Reset(index, FALSE);
  3278. while(lpCacheNode = m_pCacheArray->GetNext(index)) {
  3279. // Save the cache node
  3280. error = lpCacheNode->Save(pstgSave, fSameAsLoad, iPresStreamNum);
  3281. // Update state information
  3282. if(error == NOERROR)
  3283. ++iPresStreamNum;
  3284. else
  3285. rerror = error;
  3286. }
  3287. // Save table of contents at the end of first pres stream
  3288. if(rerror == NOERROR)
  3289. SaveTOC(pstgSave, fSameAsLoad);
  3290. if (m_ulFlags & COLECACHEF_APICREATE) { // NT bug 281051
  3291. DWORD dwFlags;
  3292. if (S_OK == ReadOleStg(pstgSave,&dwFlags,NULL,NULL,NULL,NULL)){
  3293. WriteOleStgEx(pstgSave, NULL, NULL,
  3294. (dwFlags & ~OBJFLAGS_CACHEEMPTY),
  3295. NULL ) ;
  3296. }
  3297. }
  3298. }
  3299. // Remove any extra presentation streams left
  3300. // Due to streams getting renamed above, the streams left behind may not
  3301. // be contiguous in XXXX where XXXX is \2OlePresXXXX. Consequently, we
  3302. // may not get rid of all extra pres streams below. Gopalk
  3303. UtRemoveExtraOlePresStreams(pstgSave, iPresStreamNum);
  3304. }
  3305. // Update flags
  3306. if(rerror == NOERROR) {
  3307. m_ulFlags |= COLECACHEF_NOSCRIBBLEMODE;
  3308. if (fSameAsLoad)
  3309. m_ulFlags |= COLECACHEF_SAMEASLOAD;
  3310. else
  3311. m_ulFlags &= ~COLECACHEF_SAMEASLOAD;
  3312. }
  3313. return rerror;
  3314. }
  3315. //+----------------------------------------------------------------------------
  3316. //
  3317. // Member:
  3318. // COleCache::SaveCompleted, public
  3319. //
  3320. // Synopsis:
  3321. // implements IPersistStorage::SaveCompleted
  3322. //
  3323. // Arguments:
  3324. // [pstgNew] -- NULL, or a pointer to a new storage
  3325. //
  3326. // History:
  3327. // Gopalk Rewritten Sep 04, 96
  3328. //
  3329. //-----------------------------------------------------------------------------
  3330. #pragma SEG(COleCache_SaveCompleted)
  3331. STDMETHODIMP COleCache::SaveCompleted(LPSTORAGE pStgNew)
  3332. {
  3333. // Validation checks
  3334. VDATEHEAP();
  3335. VDATETHREAD(this);
  3336. if(pStgNew)
  3337. VDATEIFACE(pStgNew);
  3338. if(!(m_ulFlags & (COLECACHEF_NOSCRIBBLEMODE | COLECACHEF_HANDSOFSTORAGE)))
  3339. return E_UNEXPECTED;
  3340. if(m_ulFlags & COLECACHEF_HANDSOFSTORAGE && !pStgNew)
  3341. return E_INVALIDARG;
  3342. // Local variables
  3343. ULONG index;
  3344. LPCACHENODE lpCacheNode;
  3345. // Remember the new storage
  3346. if (pStgNew || (m_ulFlags & COLECACHEF_SAMEASLOAD)) {
  3347. m_ulFlags &= ~COLECACHEF_SAMEASLOAD;
  3348. if (pStgNew) {
  3349. if(m_pStg)
  3350. m_pStg->Release();
  3351. m_pStg = pStgNew;
  3352. m_pStg->AddRef();
  3353. }
  3354. if (m_ulFlags & COLECACHEF_NOSCRIBBLEMODE) {
  3355. // Enumerate the cache nodes starting with native cache node
  3356. m_pCacheArray->Reset(index);
  3357. for(unsigned long i=0;i<m_pCacheArray->Length();i++) {
  3358. // Get the next cache node
  3359. lpCacheNode = m_pCacheArray->GetNext(index);
  3360. // pCacheNode cannot be null
  3361. Win4Assert(lpCacheNode);
  3362. // Call savecompleted method of the cache node
  3363. lpCacheNode->SaveCompleted(pStgNew);
  3364. }
  3365. //The next line clears dirty flag effectively.
  3366. //Had to move it here from Save to keep apps from breaking.
  3367. m_ulFlags |= COLECACHEF_LOADEDSTATE;
  3368. }
  3369. }
  3370. // Reset flags
  3371. m_ulFlags &= ~COLECACHEF_NOSCRIBBLEMODE;
  3372. m_ulFlags &= ~COLECACHEF_HANDSOFSTORAGE;
  3373. return NOERROR;
  3374. }
  3375. //+----------------------------------------------------------------------------
  3376. //
  3377. // Member:
  3378. // COleCache::HandsOffStorage, public
  3379. //
  3380. // Synopsis:
  3381. // implements IPersistStorage::HandsOffStorage
  3382. //
  3383. // Arguments:
  3384. // none
  3385. //
  3386. // Returns:
  3387. // S_OK
  3388. //
  3389. //
  3390. // History:
  3391. // Gopalk Rewritten Sep 04, 96
  3392. //
  3393. //-----------------------------------------------------------------------------
  3394. #pragma SEG(COleCache_HandsOffStorage)
  3395. STDMETHODIMP COleCache::HandsOffStorage(void)
  3396. {
  3397. // Validation checks
  3398. VDATEHEAP();
  3399. VDATETHREAD(this);
  3400. if(!m_pStg) {
  3401. // The following Win4Assert is getting fired in Liveness tests
  3402. // Win4Assert(FALSE);
  3403. return E_UNEXPECTED;
  3404. }
  3405. // Local variables
  3406. ULONG index;
  3407. LPCACHENODE lpCacheNode;
  3408. // Enumerate the cache nodes starting with native cache node
  3409. m_pCacheArray->Reset(index);
  3410. for(unsigned long i=0;i<m_pCacheArray->Length();i++) {
  3411. // Get the next cache node
  3412. lpCacheNode = m_pCacheArray->GetNext(index);
  3413. // lpCacheNode cannot be null
  3414. Win4Assert(lpCacheNode);
  3415. // Get the formatetc of the cache node
  3416. lpCacheNode->HandsOffStorage();
  3417. }
  3418. // Release the current storage
  3419. m_pStg->Release();
  3420. m_pStg = NULL;
  3421. // Set COLECACHEF_HANDSOFSTORAGE flag
  3422. m_ulFlags |= COLECACHEF_HANDSOFSTORAGE;
  3423. return NOERROR;
  3424. }
  3425. //+----------------------------------------------------------------------------
  3426. //
  3427. // Member:
  3428. // COleCache::Locate, private
  3429. //
  3430. // Synopsis:
  3431. // Locates the cache node with the given FORMATETC
  3432. //
  3433. // Arguments:
  3434. // [foretc][in] -- FormatEtc of the desired cache node
  3435. // [lpdwCacheId][out] -- CacheId of the found cache node
  3436. //
  3437. //
  3438. // Returns:
  3439. // Pointer to the found cache node on success
  3440. // NULL otherwise
  3441. //
  3442. // History:
  3443. // Gopalk Creation Sep 04, 96
  3444. //
  3445. //-----------------------------------------------------------------------------
  3446. LPCACHENODE COleCache::Locate(LPFORMATETC lpGivenForEtc, DWORD* lpdwCacheId)
  3447. {
  3448. // New data type
  3449. typedef enum tagFormatType {
  3450. // These values are defined in order of least to best preferred, so that
  3451. // numeric comparisons are valid; DO NOT REORDER
  3452. FORMATTYPE_NONE = 0,
  3453. FORMATTYPE_ANY,
  3454. FORMATTYPE_ENHMF,
  3455. FORMATTYPE_DIB,
  3456. FORMATTYPE_MFPICT,
  3457. FORMATTYPE_USER
  3458. } FormatType;
  3459. // Local variables
  3460. ULONG index, savedIndex;
  3461. FormatType CurrFormatType;
  3462. FormatType BestFormatType;
  3463. LPFORMATETC lpCurrentForEtc;
  3464. LPCACHENODE lpCacheNode;
  3465. // Start the enumeration including the native cache
  3466. m_pCacheArray->Reset(index);
  3467. BestFormatType = FORMATTYPE_NONE;
  3468. savedIndex = 0;
  3469. for(unsigned long i=0;i<m_pCacheArray->Length();i++) {
  3470. // Get the next cache node
  3471. lpCacheNode = m_pCacheArray->GetNext(index);
  3472. // pCacheNode cannot be null
  3473. Win4Assert(lpCacheNode);
  3474. // Get the formatetc of the cache node
  3475. lpCurrentForEtc = (FORMATETC *) lpCacheNode->GetFormatEtc();
  3476. // Obtain the Formattype of the current node
  3477. if(lpCurrentForEtc->cfFormat == 0)
  3478. CurrFormatType = FORMATTYPE_ANY;
  3479. else if(lpCurrentForEtc->cfFormat == lpGivenForEtc->cfFormat)
  3480. CurrFormatType = FORMATTYPE_USER;
  3481. else if(lpCurrentForEtc->cfFormat == CF_DIB &&
  3482. lpGivenForEtc->cfFormat == CF_BITMAP)
  3483. CurrFormatType = FORMATTYPE_USER;
  3484. else if(lpCurrentForEtc->cfFormat == CF_ENHMETAFILE)
  3485. CurrFormatType = FORMATTYPE_ENHMF;
  3486. else if(lpCurrentForEtc->cfFormat == CF_DIB)
  3487. CurrFormatType = FORMATTYPE_DIB;
  3488. else if(lpCurrentForEtc->cfFormat == CF_METAFILEPICT)
  3489. CurrFormatType = FORMATTYPE_MFPICT;
  3490. else
  3491. CurrFormatType = FORMATTYPE_NONE;
  3492. // Check if the cache node is better than any we have seen so far
  3493. if(CurrFormatType > BestFormatType)
  3494. if(lpCurrentForEtc->dwAspect == lpGivenForEtc->dwAspect)
  3495. if(lpCurrentForEtc->lindex == lpGivenForEtc->lindex)
  3496. if(lpCurrentForEtc->ptd==lpGivenForEtc->ptd ||
  3497. UtCompareTargetDevice(lpCurrentForEtc->ptd, lpGivenForEtc->ptd)) {
  3498. BestFormatType = CurrFormatType;
  3499. savedIndex = index;
  3500. if(BestFormatType == FORMATTYPE_USER)
  3501. break;
  3502. }
  3503. }
  3504. // Handle the case when there is no matching cache node
  3505. if((lpGivenForEtc->cfFormat && BestFormatType != FORMATTYPE_USER) ||
  3506. (!lpGivenForEtc->cfFormat && BestFormatType == FORMATTYPE_NONE)) {
  3507. if(lpdwCacheId)
  3508. *lpdwCacheId = 0;
  3509. return NULL;
  3510. }
  3511. // There is a matching cache node
  3512. lpCacheNode = m_pCacheArray->GetItem(savedIndex);
  3513. Win4Assert(lpCacheNode);
  3514. if(lpdwCacheId)
  3515. *lpdwCacheId = savedIndex;
  3516. return lpCacheNode;
  3517. }
  3518. //+----------------------------------------------------------------------------
  3519. //
  3520. // Member:
  3521. // COleCache::Locate, private
  3522. //
  3523. // Synopsis:
  3524. // Locates the cache node with the given FORMATETC
  3525. //
  3526. // Arguments:
  3527. // [dwAspect][in] -- Aspect of the desired cache node
  3528. // [lindex] [in] -- Lindex of the desired cache node
  3529. // [ptd] [in] -- Target device of the desired cache node
  3530. //
  3531. // Returns:
  3532. // Pointer to the found cache node on success
  3533. // NULL otherwise
  3534. //
  3535. // History:
  3536. // Gopalk Creation Sep 04, 96
  3537. //
  3538. //-----------------------------------------------------------------------------
  3539. LPCACHENODE COleCache::Locate(DWORD dwAspect, LONG lindex, DVTARGETDEVICE* ptd)
  3540. {
  3541. // New data type
  3542. typedef enum tagFormatType {
  3543. // These values are defined in order of least to best preferred, so that
  3544. // numeric comparisons are valid; DO NOT REORDER
  3545. FORMATTYPE_NONE = 0,
  3546. FORMATTYPE_DIB,
  3547. FORMATTYPE_MFPICT,
  3548. FORMATTYPE_ENHMF
  3549. } FormatType;
  3550. // Local variables
  3551. ULONG index, savedIndex;
  3552. FormatType CurrFormatType;
  3553. FormatType BestFormatType;
  3554. LPFORMATETC lpCurrentForEtc;
  3555. LPCACHENODE lpCacheNode;
  3556. // Start the enumeration including the native cache
  3557. m_pCacheArray->Reset(index);
  3558. BestFormatType = FORMATTYPE_NONE;
  3559. savedIndex = 0;
  3560. for(unsigned long i=0;i<m_pCacheArray->Length();i++) {
  3561. // Get the next cache node
  3562. lpCacheNode = m_pCacheArray->GetNext(index);
  3563. // pCacheNode cannot be null
  3564. Win4Assert(lpCacheNode);
  3565. // Get the formatetc of the cache node
  3566. lpCurrentForEtc = (FORMATETC *) lpCacheNode->GetFormatEtc();
  3567. // Obtain the Formattype of the current node
  3568. if(lpCurrentForEtc->cfFormat == CF_ENHMETAFILE)
  3569. CurrFormatType = FORMATTYPE_ENHMF;
  3570. else if(lpCurrentForEtc->cfFormat == CF_METAFILEPICT)
  3571. CurrFormatType = FORMATTYPE_MFPICT;
  3572. else if(lpCurrentForEtc->cfFormat == CF_DIB)
  3573. CurrFormatType = FORMATTYPE_DIB;
  3574. else
  3575. CurrFormatType = FORMATTYPE_NONE;
  3576. // Check if the cache node is better than any we have seen so far
  3577. if(CurrFormatType > BestFormatType)
  3578. if(lpCurrentForEtc->dwAspect == dwAspect)
  3579. if(lpCurrentForEtc->lindex == lindex)
  3580. if(lpCurrentForEtc->ptd==ptd ||
  3581. UtCompareTargetDevice(lpCurrentForEtc->ptd, ptd)) {
  3582. BestFormatType = CurrFormatType;
  3583. savedIndex = index;
  3584. if(BestFormatType == FORMATTYPE_ENHMF)
  3585. break;
  3586. }
  3587. }
  3588. // Handle the case when there is no matching cache node
  3589. if(BestFormatType == FORMATTYPE_NONE)
  3590. return NULL;
  3591. // There is a matching cache node
  3592. lpCacheNode = m_pCacheArray->GetItem(savedIndex);
  3593. Win4Assert(lpCacheNode);
  3594. return lpCacheNode;
  3595. }
  3596. //+----------------------------------------------------------------------------
  3597. //
  3598. // Member:
  3599. // COleCache::CAdviseSinkImpl::QueryInterface private
  3600. //
  3601. // Synopsis:
  3602. // implements IUnknown::QueryInterface
  3603. //
  3604. // Arguments:
  3605. // [iid] [in] -- IID of the desired interface
  3606. // [ppv] [out] -- pointer to where to return the requested interface
  3607. //
  3608. // Returns:
  3609. // E_NOINTERFACE if the requested interface is not available
  3610. // NOERROR otherwise
  3611. //
  3612. // History:
  3613. // Gopalk Creation Sep 04, 96
  3614. //
  3615. //-----------------------------------------------------------------------------
  3616. STDMETHODIMP COleCache::CAdviseSinkImpl::QueryInterface(REFIID riid, LPVOID* ppv)
  3617. {
  3618. // Validation check
  3619. VDATEHEAP();
  3620. // Get the parent object
  3621. COleCache* pOleCache = GETPPARENT(this, COleCache, m_AdviseSink);
  3622. VDATETHREAD(pOleCache);
  3623. // Get the requested Interface
  3624. if(IsEqualIID(riid, IID_IUnknown))
  3625. *ppv = (void *)(IUnknown *) this;
  3626. else if(IsEqualIID(riid, IID_IAdviseSink))
  3627. *ppv = (void *)(IAdviseSink *) this;
  3628. else {
  3629. *ppv = NULL;
  3630. return ResultFromScode(E_NOINTERFACE);
  3631. }
  3632. // Call addref through the interface being returned
  3633. ((IUnknown *) *ppv)->AddRef();
  3634. return NOERROR;
  3635. }
  3636. //+----------------------------------------------------------------------------
  3637. //
  3638. // Member:
  3639. // COleCache::CAdviseSinkImpl::AddRef, private
  3640. //
  3641. // Synopsis:
  3642. // implements IUnknown::AddRef
  3643. //
  3644. // Arguments:
  3645. // none
  3646. //
  3647. // Returns:
  3648. // the object's reference count
  3649. //
  3650. // History:
  3651. // Gopalk Creation Sep 04, 96
  3652. //
  3653. //-----------------------------------------------------------------------------
  3654. STDMETHODIMP_(ULONG) COleCache::CAdviseSinkImpl::AddRef(void)
  3655. {
  3656. // Validation check
  3657. VDATEHEAP();
  3658. // Get the parent object
  3659. COleCache* pOleCache = GETPPARENT(this, COleCache, m_AdviseSink);
  3660. ULONG cExportCount;
  3661. if(!pOleCache->VerifyThreadId())
  3662. return((ULONG) RPC_E_WRONG_THREAD);
  3663. // Increment export count
  3664. cExportCount = pOleCache->IncrementExportCount();
  3665. // Addref the parent object
  3666. return cExportCount;
  3667. }
  3668. //+----------------------------------------------------------------------------
  3669. //
  3670. // Member:
  3671. // COleCache::CAdviseSinkImpl::Release, private
  3672. //
  3673. // Synopsis:
  3674. // implements IUnknown::Release
  3675. //
  3676. // Arguments:
  3677. // none
  3678. //
  3679. // Returns:
  3680. // the object's reference count
  3681. //
  3682. // History:
  3683. // Gopalk Creation Sep 04, 96
  3684. //
  3685. //-----------------------------------------------------------------------------
  3686. STDMETHODIMP_(ULONG) COleCache::CAdviseSinkImpl::Release(void)
  3687. {
  3688. // Validation check
  3689. VDATEHEAP();
  3690. // Get the parent object
  3691. COleCache* pOleCache = GETPPARENT(this, COleCache, m_AdviseSink);
  3692. ULONG cExportCount;
  3693. if(!pOleCache->VerifyThreadId())
  3694. return((ULONG) RPC_E_WRONG_THREAD);
  3695. // Decrement export count.
  3696. cExportCount = pOleCache->DecrementExportCount();
  3697. return cExportCount;
  3698. }
  3699. //+----------------------------------------------------------------------------
  3700. //
  3701. // Member:
  3702. // COleCache::CAdviseSinkImpl::OnDataChange, private
  3703. //
  3704. // Synopsis:
  3705. // The methods looks up cache node representing the given formatetc
  3706. // calls set data on it.
  3707. //
  3708. // Arguments:
  3709. // [lpForetc] [in] -- the format of the new data
  3710. // [lpStgmed] [in] -- the storage medium of the new data
  3711. //
  3712. // History:
  3713. // Gopalk Creation Sep 04, 96
  3714. //
  3715. //-----------------------------------------------------------------------------
  3716. STDMETHODIMP_(void) COleCache::CAdviseSinkImpl::OnDataChange(LPFORMATETC lpForetc,
  3717. LPSTGMEDIUM lpStgmed)
  3718. {
  3719. // Validation checks
  3720. VDATEHEAP();
  3721. if(!IsValidPtrIn(lpForetc, sizeof(FORMATETC)))
  3722. return;
  3723. if(!IsValidPtrIn(lpStgmed, sizeof(STGMEDIUM)))
  3724. return;
  3725. // Get the parent object
  3726. COleCache* pOleCache = GETPPARENT(this, COleCache, m_AdviseSink);
  3727. if(!pOleCache->VerifyThreadId())
  3728. return;
  3729. if(pOleCache->IsZombie())
  3730. return;
  3731. // Local variables
  3732. LPCACHENODE lpCacheNode;
  3733. BOOL fUpdated;
  3734. HRESULT error;
  3735. // Locate the cache node representing the formatetc
  3736. lpCacheNode = pOleCache->Locate(lpForetc);
  3737. Win4Assert(lpCacheNode);
  3738. if(lpCacheNode && lpStgmed->tymed!=TYMED_NULL) {
  3739. error = lpCacheNode->SetData(lpForetc, lpStgmed, FALSE, fUpdated);
  3740. if(error == NOERROR) {
  3741. // Cache is not in loaded state now
  3742. pOleCache->m_ulFlags &= ~COLECACHEF_LOADEDSTATE;
  3743. // Inform AspectsUpdated about the updated aspect
  3744. if(fUpdated)
  3745. pOleCache->AspectsUpdated(lpForetc->dwAspect);
  3746. }
  3747. }
  3748. return;
  3749. }
  3750. //+----------------------------------------------------------------------------
  3751. //
  3752. // Member:
  3753. // COleCache::CAdviseSinkImpl::OnViewChange, private
  3754. //
  3755. // Synopsis:
  3756. // This function should not get called
  3757. //
  3758. // Arguments:
  3759. // [aspect] [in] -- Aspect whose view has changed
  3760. // [lindex] [in] -- Lindex of the aspect that has changed
  3761. //
  3762. // History:
  3763. // Gopalk Creation Sep 04, 96
  3764. //
  3765. //-----------------------------------------------------------------------------
  3766. STDMETHODIMP_(void) COleCache::CAdviseSinkImpl::OnViewChange(DWORD aspect, LONG lindex)
  3767. {
  3768. // Validation check
  3769. VDATEHEAP();
  3770. // Get the parent object
  3771. COleCache* pOleCache = GETPPARENT(this, COleCache, m_AdviseSink);
  3772. if(!pOleCache->VerifyThreadId())
  3773. return;
  3774. // There function should not get called
  3775. Win4Assert(FALSE);
  3776. return;
  3777. }
  3778. //+----------------------------------------------------------------------------
  3779. //
  3780. // Member:
  3781. // COleCache::CAdviseSinkImpl::OnRename, private
  3782. //
  3783. // Synopsis:
  3784. // This function should not get called
  3785. //
  3786. // Arguments:
  3787. // [pmk] [in] -- New moniker
  3788. //
  3789. // History:
  3790. // Gopalk Creation Sep 04, 96
  3791. //
  3792. //-----------------------------------------------------------------------------
  3793. STDMETHODIMP_(void) COleCache::CAdviseSinkImpl::OnRename(IMoniker* pmk)
  3794. {
  3795. // Validation check
  3796. VDATEHEAP();
  3797. if(!IsValidInterface(pmk))
  3798. return;
  3799. // Get the parent object
  3800. COleCache* pOleCache = GETPPARENT(this, COleCache, m_AdviseSink);
  3801. if(!pOleCache->VerifyThreadId())
  3802. return;
  3803. // There function should not get called
  3804. Win4Assert(FALSE);
  3805. return;
  3806. }
  3807. //+----------------------------------------------------------------------------
  3808. //
  3809. // Member:
  3810. // COleCache::CAdviseSinkImpl::OnSave, private
  3811. //
  3812. // Synopsis:
  3813. // This function should not get called
  3814. //
  3815. // Arguments:
  3816. // NONE
  3817. //
  3818. // History:
  3819. // Gopalk Creation Sep 04, 96
  3820. //
  3821. //-----------------------------------------------------------------------------
  3822. STDMETHODIMP_(void) COleCache::CAdviseSinkImpl::OnSave()
  3823. {
  3824. // Validation check
  3825. VDATEHEAP();
  3826. // Get the parent object
  3827. COleCache* pOleCache = GETPPARENT(this, COleCache, m_AdviseSink);
  3828. if(!pOleCache->VerifyThreadId())
  3829. return;
  3830. // There function should not get called
  3831. Win4Assert(FALSE);
  3832. return;
  3833. }
  3834. //+----------------------------------------------------------------------------
  3835. //
  3836. // Member:
  3837. // COleCache::CAdviseSinkImpl::OnClose, private
  3838. //
  3839. // Synopsis:
  3840. // This function should not get called
  3841. //
  3842. // Arguments:
  3843. // NONE
  3844. //
  3845. // History:
  3846. // Gopalk Creation Sep 04, 96
  3847. //
  3848. //-----------------------------------------------------------------------------
  3849. STDMETHODIMP_(void) COleCache::CAdviseSinkImpl::OnClose()
  3850. {
  3851. // Validation check
  3852. VDATEHEAP();
  3853. // Get the parent object
  3854. COleCache* pOleCache = GETPPARENT(this, COleCache, m_AdviseSink);
  3855. if(!pOleCache->VerifyThreadId())
  3856. return;
  3857. // There function should not get called
  3858. Win4Assert(FALSE);
  3859. return;
  3860. }
  3861. //+----------------------------------------------------------------------------
  3862. //
  3863. // Member:
  3864. // COleCache::LoadTOC, private
  3865. //
  3866. // Synopsis:
  3867. // Loads the Table Of Contents from the given stream
  3868. //
  3869. // Arguments:
  3870. // lpStream [in] - Stream from which TOC is to be loaded
  3871. // lpZeroCache [in] - CacheNode representing presentation stream 0
  3872. //
  3873. // Returns:
  3874. // NOERROR if TOC was found and successfully loaded
  3875. // else appropriate error
  3876. //
  3877. // History:
  3878. // Gopalk Creation Sep 04, 96
  3879. //
  3880. //-----------------------------------------------------------------------------
  3881. HRESULT COleCache::LoadTOC(LPSTREAM lpStream, LPSTORAGE pStg)
  3882. {
  3883. // Local variables
  3884. HRESULT error;
  3885. int iPresStm=1;
  3886. DWORD dwBuf[2];
  3887. ULONG ulBytesRead, *TOCIndex, NumTOCAdded;
  3888. LPCACHENODE lpNativeCache, lpCacheNode;
  3889. CLIPFORMAT cfFormat;
  3890. // Read TOC header
  3891. error = lpStream->Read(dwBuf, sizeof(dwBuf), &ulBytesRead);
  3892. if(ulBytesRead==sizeof(dwBuf) && dwBuf[0]==TOCSIGNATURE) {
  3893. // TOC exists in presentation stream 0
  3894. // Initialize
  3895. error = NOERROR;
  3896. NumTOCAdded = 0;
  3897. if(dwBuf[1]) {
  3898. CCacheNode BlankCache;
  3899. TOCIndex = new unsigned long[dwBuf[1]];
  3900. if(TOCIndex) {
  3901. // Load TOC entries into new cache nodes
  3902. while(NumTOCAdded < dwBuf[1]) {
  3903. // Add a blank cache node
  3904. TOCIndex[NumTOCAdded] = m_pCacheArray->AddItem(BlankCache);
  3905. if(!TOCIndex[NumTOCAdded]) {
  3906. error = ResultFromScode(E_OUTOFMEMORY);
  3907. break;
  3908. }
  3909. lpCacheNode = m_pCacheArray->GetItem(TOCIndex[NumTOCAdded]);
  3910. Win4Assert(lpCacheNode);
  3911. ++NumTOCAdded;
  3912. // Load TOC entry from the stream
  3913. error = lpCacheNode->LoadTOCEntry(lpStream, iPresStm);
  3914. if(error != NOERROR)
  3915. break;
  3916. // Check if this is the first native TOC
  3917. if(NumTOCAdded == 1 && lpCacheNode->IsNativeCache()) {
  3918. cfFormat = lpCacheNode->GetFormatEtc()->cfFormat;
  3919. lpNativeCache = m_pCacheArray->GetItem(1);
  3920. if(lpNativeCache && (cfFormat==m_cfFormat)) {
  3921. // Both native cfFormats match.
  3922. // Delete the new native cache node
  3923. m_pCacheArray->DeleteItem(TOCIndex[NumTOCAdded-1]);
  3924. continue;
  3925. }
  3926. else {
  3927. // Either native cache does not exist or cfFormats
  3928. // do not match. This could be an auto convert case.
  3929. // Try to recover old native data
  3930. if(lpCacheNode->LoadNativeData()!=NOERROR) {
  3931. // Native data could not be loaded. May be the data has
  3932. // already been converted
  3933. m_pCacheArray->DeleteItem(TOCIndex[NumTOCAdded-1]);
  3934. continue;
  3935. }
  3936. // Old Native data successfully loaded.
  3937. // Update state on the new cache
  3938. lpCacheNode->MakeNormalCache();
  3939. lpCacheNode->SetClsid(CLSID_NULL);
  3940. }
  3941. }
  3942. // Set the storage on the cache node
  3943. lpCacheNode->SetStg(pStg);
  3944. // If the server is runinng, set the advise connection
  3945. if(m_pDataObject)
  3946. lpCacheNode->SetupAdviseConnection(m_pDataObject,
  3947. (IAdviseSink *) &m_AdviseSink);
  3948. }
  3949. // Check if TOC entries have been successfully loaded
  3950. if(error != NOERROR) {
  3951. // Something has gone wrong while loading TOC.
  3952. // Delete all newly added cache nodes
  3953. while(NumTOCAdded) {
  3954. lpCacheNode = m_pCacheArray->GetItem(TOCIndex[NumTOCAdded-1]);
  3955. Win4Assert(lpCacheNode);
  3956. if(m_pDataObject)
  3957. lpCacheNode->TearDownAdviseConnection(m_pDataObject);
  3958. m_pCacheArray->DeleteItem(TOCIndex[NumTOCAdded-1]);
  3959. --NumTOCAdded;
  3960. }
  3961. }
  3962. // Delete the TOCIndex array
  3963. delete[] TOCIndex;
  3964. }
  3965. else
  3966. error = ResultFromScode(E_OUTOFMEMORY);
  3967. }
  3968. }
  3969. else
  3970. error = ResultFromScode(E_FAIL);
  3971. return error;
  3972. }
  3973. //+----------------------------------------------------------------------------
  3974. //
  3975. // Member:
  3976. // COleCache::SaveTOC, private
  3977. //
  3978. // Synopsis:
  3979. // Saves the Table Of Contents in the given stream
  3980. //
  3981. // Arguments:
  3982. // pStg [in] - Storage in which TOC is to be saved
  3983. //
  3984. // Returns:
  3985. // NOERROR if TOC was successfully saved
  3986. // else appropriate error
  3987. //
  3988. // History:
  3989. // Gopalk Creation Sep 04, 96
  3990. //
  3991. //-----------------------------------------------------------------------------
  3992. HRESULT COleCache::SaveTOC(LPSTORAGE pStg, BOOL fSameAsLoad)
  3993. {
  3994. // Local variables
  3995. HRESULT error;
  3996. DWORD dwBuf[2];
  3997. ULONG NumTOCEntries, index;
  3998. LPSTREAM lpStream;
  3999. LPCACHENODE lpCacheNode;
  4000. LARGE_INTEGER largeInt;
  4001. ULARGE_INTEGER ulargeInt;
  4002. // There should be atleast one cached presentation for saving TOC
  4003. if(!m_pCacheArray->Length() ||
  4004. (m_pCacheArray->Length()==1 && (m_pCacheArray->GetItem(1))))
  4005. return NOERROR;
  4006. // Open presentation stream 0
  4007. error = pStg->OpenStream(OLE_PRESENTATION_STREAM, NULL,
  4008. (STGM_READWRITE | STGM_SHARE_EXCLUSIVE),
  4009. 0, &lpStream);
  4010. if(error == NOERROR) {
  4011. // Presentation stream exists. Seek to its end
  4012. LISet32(largeInt, 0);
  4013. error = lpStream->Seek(largeInt, STREAM_SEEK_END, &ulargeInt);
  4014. if(error == NOERROR) {
  4015. // Save TOC header
  4016. NumTOCEntries = m_pCacheArray->Length()-1;
  4017. dwBuf[0] = TOCSIGNATURE;
  4018. dwBuf[1] = NumTOCEntries;
  4019. error = lpStream->Write(dwBuf, sizeof(dwBuf), NULL);
  4020. if(error==NOERROR && NumTOCEntries) {
  4021. // If native cache node exists, save its TOC entry first
  4022. if(lpCacheNode = m_pCacheArray->GetItem(1)) {
  4023. error = lpCacheNode->SaveTOCEntry(lpStream, fSameAsLoad);
  4024. --NumTOCEntries;
  4025. }
  4026. if(error == NOERROR && NumTOCEntries) {
  4027. // Skip the first cached presentation
  4028. m_pCacheArray->Reset(index, FALSE);
  4029. lpCacheNode = m_pCacheArray->GetNext(index);
  4030. Win4Assert(lpCacheNode);
  4031. // Save the TOC entries of the remaining presentations
  4032. while(error==NOERROR && (lpCacheNode = m_pCacheArray->GetNext(index))) {
  4033. error = lpCacheNode->SaveTOCEntry(lpStream, fSameAsLoad);
  4034. --NumTOCEntries;
  4035. }
  4036. }
  4037. }
  4038. // Check if the TOC has been successfully saved
  4039. if(error == NOERROR)
  4040. Win4Assert(!NumTOCEntries);
  4041. else {
  4042. // Something has gone wrong while writting TOC.
  4043. // Revert presentation stream to its original length
  4044. lpStream->SetSize(ulargeInt);
  4045. }
  4046. }
  4047. // Release the stream
  4048. lpStream->Release();
  4049. }
  4050. return error;
  4051. }
  4052. //+----------------------------------------------------------------------------
  4053. //
  4054. // Member:
  4055. // COleCache::AspectsUpdated, private
  4056. //
  4057. // Synopsis:
  4058. // Notifies the container advise sink of view change if the aspect
  4059. // is one of those in which it expressed interest
  4060. //
  4061. // Arguments:
  4062. // dwAspect [in] - Aspect that changed
  4063. //
  4064. // History:
  4065. // Gopalk Creation Sep 04, 96
  4066. //
  4067. //-----------------------------------------------------------------------------
  4068. void COleCache::AspectsUpdated(DWORD dwAspects)
  4069. {
  4070. DWORD dwKnownAspects;
  4071. // Aspects known to us
  4072. dwKnownAspects = DVASPECT_CONTENT | DVASPECT_THUMBNAIL |
  4073. DVASPECT_ICON | DVASPECT_DOCPRINT;
  4074. // Ensure that we were given known aspects
  4075. if(dwAspects & ~dwKnownAspects) {
  4076. Win4Assert(FALSE);
  4077. dwAspects &= dwKnownAspects;
  4078. }
  4079. // Check if the client registered advise on any of the changed aspects.
  4080. if(m_pViewAdvSink) {
  4081. // Ensure that container requested advise on valid aspects
  4082. if(m_aspectsView & ~dwKnownAspects) {
  4083. Win4Assert(FALSE);
  4084. m_aspectsView &= dwKnownAspects;
  4085. }
  4086. // As cache is always loaded inproc, the advise to ViewAdvSink
  4087. // does not violate ASYNC call convention of not being allowed
  4088. // to call outside the current apartment
  4089. while(m_aspectsView & dwAspects) {
  4090. if(dwAspects & DVASPECT_CONTENT) {
  4091. dwAspects &= ~DVASPECT_CONTENT;
  4092. if(!(m_aspectsView & DVASPECT_CONTENT))
  4093. continue;
  4094. m_pViewAdvSink->OnViewChange(DVASPECT_CONTENT, DEF_LINDEX);
  4095. }
  4096. else if(dwAspects & DVASPECT_THUMBNAIL) {
  4097. dwAspects &= ~DVASPECT_THUMBNAIL;
  4098. if(!(m_aspectsView & DVASPECT_THUMBNAIL))
  4099. continue;
  4100. m_pViewAdvSink->OnViewChange(DVASPECT_THUMBNAIL, DEF_LINDEX);
  4101. }
  4102. else if(dwAspects & DVASPECT_ICON) {
  4103. dwAspects &= ~DVASPECT_ICON;
  4104. if(!(m_aspectsView & DVASPECT_ICON))
  4105. continue;
  4106. m_pViewAdvSink->OnViewChange(DVASPECT_ICON, DEF_LINDEX);
  4107. }
  4108. else if(dwAspects & DVASPECT_DOCPRINT) {
  4109. dwAspects &= ~DVASPECT_DOCPRINT;
  4110. if(!(m_aspectsView & DVASPECT_DOCPRINT))
  4111. continue;
  4112. m_pViewAdvSink->OnViewChange(DVASPECT_DOCPRINT, DEF_LINDEX);
  4113. }
  4114. // If client only wanted notification once, free the advise sink
  4115. if(m_advfView & ADVF_ONLYONCE) {
  4116. m_pViewAdvSink->Release();
  4117. m_pViewAdvSink = NULL;
  4118. m_advfView = 0;
  4119. m_aspectsView = 0;
  4120. }
  4121. }
  4122. }
  4123. return;
  4124. }