Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4632 lines
147 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 = FALSE;
  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. //+----------------------------------------------------------------------------
  2185. //
  2186. // Member:
  2187. // COleCache::CCacheViewImpl::Draw, public
  2188. //
  2189. // Synopsis:
  2190. // implements IViewObject::Draw
  2191. //
  2192. // Arguments:
  2193. // [dwDrawAspect] -- a value from the DVASPECT_* enumeration
  2194. // [lindex] -- indicates what piece of the object is of
  2195. // interest; legal values vary with dwDrawAspect
  2196. // [pvAspect] -- currently NULL
  2197. // [ptd] -- the target device
  2198. // [hicTargetDev] -- in information context for [ptd]
  2199. // [hdcDraw] -- device context on which drawing is to be done
  2200. // [lprcBounds] -- boundaries of drawing on [hdcDraw]
  2201. // [lprcWBounds] -- if hdcDraw is a meta-file, it's boundaries
  2202. // [pfnContinue] --a callback function that the drawer should call
  2203. // periodically to see if rendering should be aborted.
  2204. // [dwContinue] -- passed on into [pfnContinue]
  2205. //
  2206. // Returns:
  2207. // OLE_E_BLANK, if no presentation object can be found
  2208. // REVIEW, anything from IOlePresObj::Draw
  2209. //
  2210. // Notes:
  2211. // This finds the presentation object in the cache for
  2212. // the requested format, if there is one, and then passes
  2213. // on the call to its Draw method.
  2214. //
  2215. // The use of a callback function as a parameter means that
  2216. // this interface cannot be remoted, unless some custom
  2217. // proxy is built, allowing the function to be called back in its
  2218. // original context; the interface is defined as
  2219. // [local] in common\types
  2220. //
  2221. // History:
  2222. // 01/12/95 - t-ScottH- added VDATETHREAD( GETPPARENT...)
  2223. // 11/11/93 - ChrisWe - file inspection and cleanup
  2224. // 11/30/93 - alexgo - fixed bug with GETPPARENT usage
  2225. //
  2226. //-----------------------------------------------------------------------------
  2227. #pragma SEG(COleCache_CCacheViewImpl_Draw)
  2228. STDMETHODIMP NC(COleCache,CCacheViewImpl)::Draw(
  2229. DWORD dwDrawAspect,
  2230. LONG lindex, void FAR* pvAspect, DVTARGETDEVICE FAR * ptd,
  2231. HDC hicTargetDev, HDC hdcDraw,
  2232. LPCRECTL lprcBounds,
  2233. LPCRECTL lprcWBounds,
  2234. BOOL (CALLBACK * pfnContinue)(ULONG_PTR),
  2235. ULONG_PTR dwContinue)
  2236. {
  2237. // Validation check
  2238. VDATEHEAP();
  2239. // Get the parent object
  2240. COleCache* pOleCache = GETPPARENT(this, COleCache, m_ViewObject);
  2241. VDATETHREAD(pOleCache);
  2242. // Local variables
  2243. BOOL bMetaDC;
  2244. LPCACHENODE lpCacheNode;
  2245. // Validate parameters
  2246. if(ptd)
  2247. VDATEPTRIN(ptd, DVTARGETDEVICE);
  2248. if(lprcBounds) {
  2249. VDATEPTRIN(lprcBounds, RECTL);
  2250. }
  2251. else
  2252. return E_INVALIDARG;
  2253. if(lprcWBounds)
  2254. VDATEPTRIN(lprcWBounds, RECTL);
  2255. if(!hdcDraw)
  2256. return E_INVALIDARG;
  2257. if(!IsValidLINDEX(dwDrawAspect, lindex))
  2258. return(DV_E_LINDEX);
  2259. // Locate the cache node for the given draw parameters
  2260. lpCacheNode = pOleCache->Locate(dwDrawAspect, lindex, ptd);
  2261. // If there is no cache node, we cannot draw
  2262. if(!lpCacheNode)
  2263. return ResultFromScode(OLE_E_BLANK);
  2264. // If the DC is a metafile DC then window bounds must be valid
  2265. if((bMetaDC = OleIsDcMeta(hdcDraw)) && (lprcWBounds == NULL))
  2266. return ResultFromScode(E_INVALIDARG);
  2267. #ifdef MAC_REVIEW
  2268. A RECT value on the MAC contains members which are 'short's'. A RECTL
  2269. uses longs, and in the code below an assumption is explicitely made
  2270. that long member values is directly comp[atible on the MAC. Naturally, this is not
  2271. the case, and the compiler will barf on this.
  2272. #endif
  2273. #ifndef WIN32 // no need to do this on WIN 32 also
  2274. // On Win 16 make sure that the coordinates are valid 16bit quantities.
  2275. RECT rcBounds;
  2276. RECT rcWBounds;
  2277. if (!(IS_SMALL_INT(lprcBounds->left) &&
  2278. IS_SMALL_INT(lprcBounds->right) &&
  2279. IS_SMALL_INT(lprcBounds->top) &&
  2280. IS_SMALL_INT(lprcBounds->bottom)))
  2281. {
  2282. AssertSz(FALSE, "Rect coordinate is not a small int");
  2283. return ReportResult(0, OLE_E_INVALIDRECT, 0, 0);
  2284. }
  2285. else
  2286. {
  2287. rcBounds.left = (int) lprcBounds->left;
  2288. rcBounds.right = (int) lprcBounds->right;
  2289. rcBounds.top = (int) lprcBounds->top;
  2290. rcBounds.bottom = (int) lprcBounds->bottom;
  2291. }
  2292. if (bMetaDC)
  2293. {
  2294. if (!(IS_SMALL_INT(lprcWBounds->left) &&
  2295. IS_SMALL_INT(lprcWBounds->right) &&
  2296. IS_SMALL_INT(lprcWBounds->top) &&
  2297. IS_SMALL_INT(lprcWBounds->bottom)))
  2298. {
  2299. AssertSz(FALSE, "Rect coordinate is not a small int");
  2300. return ReportResult(0, OLE_E_INVALIDRECT, 0, 0);
  2301. }
  2302. else
  2303. {
  2304. rcWBounds.left = (int) lprcWBounds->left;
  2305. rcWBounds.right = (int) lprcWBounds->right;
  2306. rcWBounds.top = (int) lprcWBounds->top;
  2307. rcWBounds.bottom = (int) lprcWBounds->bottom;
  2308. }
  2309. }
  2310. return(lpCacheNode->Draw(pvAspect, hicTargetDev, hdcDraw,
  2311. &rcBounds, &rcWBounds, pfnContinue,
  2312. dwContinue));
  2313. #else
  2314. // on MAC as well as win 32 we can use the same pointer as it is,
  2315. // 'cause rect fields are 32 bit quantities
  2316. return(lpCacheNode->Draw(pvAspect, hicTargetDev, hdcDraw,
  2317. lprcBounds, lprcWBounds, pfnContinue,
  2318. dwContinue));
  2319. #endif
  2320. }
  2321. //+----------------------------------------------------------------------------
  2322. //
  2323. // Member:
  2324. // COleCache::CCacheViewImpl::GetColorSet, public
  2325. //
  2326. // Synopsis:
  2327. // implements IViewObject::GetColorSet
  2328. //
  2329. // Arguments:
  2330. // [dwDrawAspect] -- a value from the DVASPECT_* enumeration
  2331. // [lindex] -- indicates what piece of the object is of
  2332. // interest; legal values vary with dwDrawAspect
  2333. // [pvAspect] -- currently NULL
  2334. // [ptd] -- the target device
  2335. // [hicTargetDev] -- in information context for [ptd]
  2336. // [ppColorSet] -- the color set required for the requested
  2337. // rendering
  2338. //
  2339. // Returns:
  2340. // OLE_E_BLANK, if no presentation object can be found
  2341. // REVIEW, anything from IOlePresObj::Draw
  2342. //
  2343. // Notes:
  2344. // Finds a presentation object in the cache that matches the
  2345. // requested rendering, if there is one, and asks the
  2346. // presentation object for the color set.
  2347. //
  2348. // History:
  2349. // 09/04/96 - Gopalk - Modifications needed for
  2350. // supporting delay loading
  2351. // of cache
  2352. // 01/12/95 - t-ScottH- added VDATETHREAD( GETPPARENT...)
  2353. // 11/11/93 - ChrisWe - file inspection and cleanup
  2354. // 11/30/93 - alexgo - fixed bug with GETPPARENT usage
  2355. //
  2356. //-----------------------------------------------------------------------------
  2357. #pragma SEG(COleCache_CCacheViewImpl_GetColorSet)
  2358. STDMETHODIMP COleCache::CCacheViewImpl::GetColorSet(DWORD dwDrawAspect,
  2359. LONG lindex, void* pvAspect,
  2360. DVTARGETDEVICE* ptd,
  2361. HDC hicTargetDev,
  2362. LPLOGPALETTE* ppColorSet)
  2363. {
  2364. // Validation check
  2365. VDATEHEAP();
  2366. // Get the parent object
  2367. COleCache* pOleCache = GETPPARENT(this, COleCache, m_ViewObject);
  2368. VDATETHREAD(pOleCache);
  2369. // Local variables
  2370. LPCACHENODE lpCacheNode;
  2371. // Initialize color set
  2372. *ppColorSet = NULL;
  2373. // Vaidate the parameters
  2374. if(!IsValidLINDEX(dwDrawAspect, lindex))
  2375. return(DV_E_LINDEX);
  2376. // Locate the cache node for the given draw parameters
  2377. lpCacheNode = pOleCache->Locate(dwDrawAspect, lindex, ptd);
  2378. // If there is no cache node, we cannot draw
  2379. if(!lpCacheNode)
  2380. return ResultFromScode(OLE_E_BLANK);
  2381. return(lpCacheNode->GetColorSet(pvAspect, hicTargetDev, ppColorSet));
  2382. }
  2383. //+----------------------------------------------------------------------------
  2384. //
  2385. // Member:
  2386. // COleCache::CCacheViewImpl, public
  2387. //
  2388. // Synopsis:
  2389. // implements IViewObject::Freeze
  2390. //
  2391. // Arguments:
  2392. // [dwDrawAspect] -- a value from the DVASPECT_* enumeration
  2393. // [lindex] -- indicates what piece of the object is of
  2394. // interest; legal values vary with dwDrawAspect
  2395. // [pvAspect] -- currently NULL
  2396. // [pdwFreeze] -- a token that can later be used to unfreeze
  2397. // this aspects cached presentations
  2398. //
  2399. // Returns:
  2400. // OLE_E_BLANK, if no presentation is found that matches the
  2401. // requested characteristics
  2402. //
  2403. // Notes:
  2404. // The current implementation returns the ASPECT+FREEZE_CONSTANT
  2405. // as the FreezeID. At Unfreeze time we get the ASPECT by doing
  2406. // FreezeID-FREEZE_CONSTANT.
  2407. //
  2408. // REVIEW: In future where we allow lindexes other than DEF_LINDEX,
  2409. // we will have to use some other scheme for generating the
  2410. // FreezeID.
  2411. //
  2412. // History:
  2413. // Gopalk Rewritten Sep 04, 96
  2414. //
  2415. //-----------------------------------------------------------------------------
  2416. #pragma SEG(COleCache_CCacheViewImpl_Freeze)
  2417. STDMETHODIMP COleCache::CCacheViewImpl::Freeze(DWORD dwAspect, LONG lindex,
  2418. LPVOID pvAspect, DWORD* pdwFreeze)
  2419. {
  2420. // Validation check
  2421. VDATEHEAP();
  2422. // Get the parent object
  2423. COleCache* pOleCache = GETPPARENT(this, COleCache, m_ViewObject);
  2424. VDATETHREAD(pOleCache);
  2425. // Local variables
  2426. ULONG index, cntFrozenNodes;
  2427. LPCACHENODE lpCacheNode;
  2428. const FORMATETC* pforetc;
  2429. // Validate parameters
  2430. if(pdwFreeze) {
  2431. VDATEPTROUT(pdwFreeze, DWORD);
  2432. *pdwFreeze = 0;
  2433. }
  2434. VERIFY_ASPECT_SINGLE(dwAspect);
  2435. if(!IsValidLINDEX(dwAspect, lindex))
  2436. return(DV_E_LINDEX);
  2437. // Check if the aspect has already been frozen
  2438. if(pOleCache->m_dwFrozenAspects & dwAspect) {
  2439. // Set the freeze id
  2440. if(pdwFreeze)
  2441. *pdwFreeze = dwAspect + FREEZE_CONSTANT;
  2442. return ResultFromScode(VIEW_S_ALREADY_FROZEN);
  2443. }
  2444. // Freeze the cache nodes including native cache node
  2445. pOleCache->m_pCacheArray->Reset(index);
  2446. cntFrozenNodes = 0;
  2447. for(unsigned long i=0; i<pOleCache->m_pCacheArray->Length(); i++) {
  2448. lpCacheNode = pOleCache->m_pCacheArray->GetNext(index);
  2449. pforetc = lpCacheNode->GetFormatEtc();
  2450. if(pforetc->dwAspect == dwAspect && pforetc->lindex == lindex)
  2451. if(lpCacheNode->Freeze() == NOERROR)
  2452. cntFrozenNodes++;
  2453. }
  2454. // Check if we froze any cache nodes
  2455. if(cntFrozenNodes) {
  2456. // Add this aspect to the frozen aspects.
  2457. pOleCache->m_dwFrozenAspects |= dwAspect;
  2458. // Set the freeze id
  2459. if(pdwFreeze)
  2460. *pdwFreeze = dwAspect + FREEZE_CONSTANT;
  2461. return(NOERROR);
  2462. }
  2463. // No cache node matched the requested characteristics
  2464. return ResultFromScode(OLE_E_BLANK);
  2465. }
  2466. //+----------------------------------------------------------------------------
  2467. //
  2468. // Member:
  2469. // COleCache::CCacheViewImpl::Unfreeze, public
  2470. //
  2471. // Synopsis:
  2472. // implements IViewObject::Unfreeze
  2473. //
  2474. // Arguments:
  2475. // [dwFreezeId] -- the id returned by Freeze() when some aspect
  2476. // was frozen earlier
  2477. //
  2478. // Returns:
  2479. // OLE_E_NOCONNECTION, if dwFreezeId is invalid
  2480. // S_OK, otherwise
  2481. //
  2482. // Notes:
  2483. // See notes for Freeze().
  2484. //
  2485. //
  2486. // History:
  2487. // Gopalk Rewritten Sep 04, 96
  2488. //
  2489. //-----------------------------------------------------------------------------
  2490. #pragma SEG(COleCache_CCacheViewImpl_Unfreeze)
  2491. STDMETHODIMP COleCache::CCacheViewImpl::Unfreeze(DWORD dwFreezeId)
  2492. {
  2493. // Validation check
  2494. VDATEHEAP();
  2495. // Get the parent object
  2496. COleCache* pOleCache = GETPPARENT(this, COleCache, m_ViewObject);
  2497. VDATETHREAD(pOleCache);
  2498. // Local variables
  2499. BOOL fAnyUpdated = FALSE, fUpdated;
  2500. ULONG index, cntUnfrozenNodes;
  2501. DWORD dwAspect = dwFreezeId - FREEZE_CONSTANT;
  2502. LONG lindex = DEF_LINDEX;
  2503. LPCACHENODE lpCacheNode;
  2504. const FORMATETC* pforetc;
  2505. // Atleast one and not more than one bit should be set in dwAspect
  2506. if(!(dwAspect && !(dwAspect & (dwAspect-1)) && (dwAspect <= MAX_VALID_ASPECT)))
  2507. return ResultFromScode(OLE_E_NOCONNECTION);
  2508. // Make sure that this aspect is frozen
  2509. if (!(pOleCache->m_dwFrozenAspects & dwAspect))
  2510. return ResultFromScode(OLE_E_NOCONNECTION);
  2511. // Unfreeze the cache nodes including native cache node
  2512. pOleCache->m_pCacheArray->Reset(index);
  2513. cntUnfrozenNodes = 0;
  2514. for(unsigned long i=0; i<pOleCache->m_pCacheArray->Length(); i++) {
  2515. // Get the next cache node
  2516. lpCacheNode = pOleCache->m_pCacheArray->GetNext(index);
  2517. // lpCacheNode cannot be null
  2518. Win4Assert(lpCacheNode);
  2519. // Get the formatetc of the cache node
  2520. pforetc = lpCacheNode->GetFormatEtc();
  2521. if(pforetc->dwAspect == dwAspect && pforetc->lindex == lindex)
  2522. if(lpCacheNode->Unfreeze(fUpdated) == NOERROR) {
  2523. if(fUpdated)
  2524. fAnyUpdated = TRUE;
  2525. cntUnfrozenNodes++;
  2526. }
  2527. }
  2528. // Check if we unfroze any cache nodes
  2529. if(cntUnfrozenNodes) {
  2530. // Remove this aspect from frozen aspects
  2531. pOleCache->m_dwFrozenAspects &= ~dwAspect;
  2532. }
  2533. // Check if the aspect has changed
  2534. if(fAnyUpdated)
  2535. pOleCache->AspectsUpdated(dwAspect);
  2536. return NOERROR;
  2537. }
  2538. //+----------------------------------------------------------------------------
  2539. //
  2540. // Member:
  2541. // COleCache::CCacheViewImpl::SetAdvise, public
  2542. //
  2543. // Synopsis:
  2544. // implements IViewObject::SetAdvise
  2545. //
  2546. // Arguments:
  2547. // [aspects] -- the aspects the sink would like to be advised of
  2548. // changes to
  2549. // [advf] -- advise control flags from ADVF_*
  2550. // [pAdvSink] -- the advise sink
  2551. //
  2552. // Returns:
  2553. // E_INVALIDARG
  2554. // S_OK
  2555. //
  2556. // Notes:
  2557. // Only one advise sink is allowed at a time. If a second one
  2558. // is registered, the first one is released.
  2559. //
  2560. // History:
  2561. // Gopalk Rewritten Sep 04, 96
  2562. //
  2563. //-----------------------------------------------------------------------------
  2564. #pragma SEG(COleCache_CCacheViewImpl_SetAdvise)
  2565. STDMETHODIMP COleCache::CCacheViewImpl::SetAdvise(DWORD aspects, DWORD advf,
  2566. IAdviseSink* pAdvSink)
  2567. {
  2568. // Validation check
  2569. VDATEHEAP();
  2570. // Get the parent object
  2571. COleCache* pOleCache = GETPPARENT(this, COleCache, m_ViewObject);
  2572. VDATETHREAD(pOleCache);
  2573. // Validate parameters
  2574. if(pAdvSink)
  2575. VDATEIFACE(pAdvSink);
  2576. if(aspects & ~(DVASPECT_CONTENT | DVASPECT_THUMBNAIL |
  2577. DVASPECT_ICON|DVASPECT_DOCPRINT)) {
  2578. Win4Assert(FALSE);
  2579. return ResultFromScode(E_INVALIDARG);
  2580. }
  2581. // ADVF_NODATA is not valid because there is no way to send data
  2582. // using IAdviseSink::OnViewChange
  2583. if(advf & ADVF_NODATA)
  2584. return ResultFromScode(E_INVALIDARG);
  2585. // We allow only one view advise at any given time,
  2586. // so Release the old sink.
  2587. if (pOleCache->m_pViewAdvSink)
  2588. pOleCache->m_pViewAdvSink->Release();
  2589. // Remember the new sink
  2590. if((pOleCache->m_pViewAdvSink = pAdvSink)) {
  2591. // Add ref the new advise sink
  2592. pAdvSink->AddRef();
  2593. // Save the advice flags and aspects
  2594. pOleCache->m_advfView = advf;
  2595. pOleCache->m_aspectsView = aspects;
  2596. // If ADVF_PRIMEFIRST is set, send OnViewChange immediately
  2597. if(advf & ADVF_PRIMEFIRST) {
  2598. pOleCache->m_pViewAdvSink->OnViewChange(aspects, DEF_LINDEX);
  2599. // If ADVF_ONLYONCE is set, free the advise sink
  2600. if (pOleCache->m_advfView & ADVF_ONLYONCE) {
  2601. pOleCache->m_pViewAdvSink->Release();
  2602. pOleCache->m_pViewAdvSink = NULL;
  2603. pOleCache->m_advfView = 0;
  2604. pOleCache->m_aspectsView = 0;
  2605. }
  2606. }
  2607. }
  2608. return NOERROR;
  2609. }
  2610. //+----------------------------------------------------------------------------
  2611. //
  2612. // Member:
  2613. // COleCache::CCacheViewImpl::GetAdvise, public
  2614. //
  2615. // Synopsis:
  2616. // implement IViewObject::GetAdvise
  2617. //
  2618. // Arguments:
  2619. // [pAspects] -- a pointer to where to return the aspects the
  2620. // current advise sink is interested in
  2621. // [pAdvf] -- a pointer to where to return the advise control
  2622. // flags for the current advise sink
  2623. // [ppAdvSink] -- a pointer to where to return a reference to
  2624. // the current advise sink
  2625. //
  2626. // Returns:
  2627. // S_OK
  2628. //
  2629. //
  2630. // History:
  2631. // Gopalk Rewritten Sep 04, 96
  2632. //
  2633. //-----------------------------------------------------------------------------
  2634. #pragma SEG(COleCache_CCacheViewImpl_GetAdvise)
  2635. STDMETHODIMP COleCache::CCacheViewImpl::GetAdvise(DWORD* pAspects, DWORD* pAdvf,
  2636. IAdviseSink** ppAdvSink)
  2637. {
  2638. // Validation check
  2639. VDATEHEAP();
  2640. // Get the parent object
  2641. COleCache* pOleCache = GETPPARENT(this, COleCache, m_ViewObject);
  2642. VDATETHREAD(pOleCache);
  2643. // Validate parameters
  2644. if(ppAdvSink) {
  2645. VDATEPTROUT(ppAdvSink, IAdviseSink*);
  2646. *ppAdvSink = NULL;
  2647. }
  2648. if(pAspects) {
  2649. VDATEPTROUT(pAspects, DWORD);
  2650. *pAspects = 0;
  2651. }
  2652. if(pAdvf) {
  2653. VDATEPTROUT(pAdvf, DWORD);
  2654. *pAdvf = 0;
  2655. }
  2656. // Check if an AdviseSink is registered
  2657. if(pOleCache->m_pViewAdvSink) {
  2658. if(pAspects)
  2659. *pAspects = pOleCache->m_aspectsView;
  2660. if(pAdvf)
  2661. *pAdvf = pOleCache->m_advfView;
  2662. if(ppAdvSink)
  2663. (*ppAdvSink = pOleCache->m_pViewAdvSink)->AddRef();
  2664. }
  2665. return NOERROR;
  2666. }
  2667. //+----------------------------------------------------------------------------
  2668. //
  2669. // Member:
  2670. // COleCache::CCacheViewImpl::GetExtent, public
  2671. //
  2672. // Synopsis:
  2673. // implements IViewObject::GetExtent
  2674. //
  2675. // Arguments:
  2676. // [dwDrawAspect] -- the aspect for which we'd like the extent
  2677. // [lindex] -- the lindex for which we'd like the extent
  2678. // [ptd] -- pointer to the target device descriptor
  2679. // [lpsizel] -- pointer to where to return the extent
  2680. //
  2681. // Returns:
  2682. // OLE_E_BLANK, if no presentation can be found that matches
  2683. // (dwDrawAspect, lindex)
  2684. // History:
  2685. // Gopalk Rewritten Sep 04, 96
  2686. //
  2687. //-----------------------------------------------------------------------------
  2688. #pragma SEG(COleCache_CCacheViewImpl_GetExtent)
  2689. STDMETHODIMP COleCache::CCacheViewImpl::GetExtent(DWORD dwDrawAspect,
  2690. LONG lindex,
  2691. DVTARGETDEVICE* ptd,
  2692. LPSIZEL lpsizel)
  2693. {
  2694. // Validation check
  2695. VDATEHEAP();
  2696. // Get the parent object
  2697. COleCache* pOleCache = GETPPARENT(this, COleCache, m_ViewObject);
  2698. VDATETHREAD(pOleCache);
  2699. // Local variable
  2700. LPCACHENODE lpCacheNode;
  2701. // Validate parameters
  2702. VDATEPTROUT(lpsizel, SIZEL);
  2703. if(!IsValidLINDEX(dwDrawAspect, lindex))
  2704. return(DV_E_LINDEX);
  2705. if(ptd)
  2706. VDATEPTRIN(ptd, DVTARGETDEVICE);
  2707. // Locate the cache node for the given draw parameters
  2708. lpCacheNode = pOleCache->Locate(dwDrawAspect, lindex, ptd);
  2709. // If there is no cache node, we cannot draw
  2710. if(!lpCacheNode)
  2711. return ResultFromScode(OLE_E_BLANK);
  2712. return(lpCacheNode->GetExtent(dwDrawAspect, lpsizel));
  2713. }
  2714. // IPersistStorage implementation
  2715. //+----------------------------------------------------------------------------
  2716. //
  2717. // Member:
  2718. // COleCache::GetClassID, public
  2719. //
  2720. // Synopsis:
  2721. // implements IPersist::GetClassID
  2722. //
  2723. // Arguments:
  2724. // [pClassID] -- pointer to where to return class id
  2725. //
  2726. // History:
  2727. // Gopalk Rewritten Sep 04, 96
  2728. //
  2729. //-----------------------------------------------------------------------------
  2730. #pragma SEG(COleCache_GetClassID)
  2731. STDMETHODIMP COleCache::GetClassID(LPCLSID pClassID)
  2732. {
  2733. // Validation checks
  2734. VDATEHEAP();
  2735. VDATETHREAD(this);
  2736. VDATEPTROUT(pClassID, CLSID);
  2737. *pClassID = m_clsid;
  2738. return NOERROR;
  2739. }
  2740. //+----------------------------------------------------------------------------
  2741. //
  2742. // Member:
  2743. // COleCache::IsDirty, public
  2744. //
  2745. // Synopsis:
  2746. // implements IPersistStorage::IsDirty
  2747. //
  2748. // Arguments:
  2749. // none
  2750. //
  2751. // Returns:
  2752. // S_FALSE, if the object does not need saving
  2753. // S_OK otherwise
  2754. //
  2755. // History:
  2756. // Gopalk Rewritten Sep 04, 96
  2757. //
  2758. //-----------------------------------------------------------------------------
  2759. #pragma SEG(COleCache_IsDirty)
  2760. STDMETHODIMP COleCache::IsDirty(void)
  2761. {
  2762. // Validation check
  2763. VDATEHEAP();
  2764. VDATETHREAD(this);
  2765. // Local variables
  2766. ULONG index;
  2767. LPCACHENODE lpCacheNode;
  2768. // Check if the cache is in loaded state
  2769. if(!(m_ulFlags & COLECACHEF_LOADEDSTATE))
  2770. return(NOERROR);
  2771. // Start the enumeration of the cache nodes at the right start point
  2772. if(m_ulFlags & COLECACHEF_STATIC)
  2773. m_pCacheArray->Reset(index, TRUE);
  2774. else
  2775. m_pCacheArray->Reset(index, FALSE);
  2776. // Enumerate the cache nodes
  2777. while(lpCacheNode = m_pCacheArray->GetNext(index))
  2778. if(!lpCacheNode->InLoadedState()) {
  2779. m_ulFlags &= ~COLECACHEF_LOADEDSTATE;
  2780. return NOERROR;
  2781. }
  2782. // Cache is not dirty
  2783. return S_FALSE;
  2784. }
  2785. //+----------------------------------------------------------------------------
  2786. //
  2787. // Member:
  2788. // COleCache::InitNew, public
  2789. //
  2790. // Synopsis:
  2791. // implements IPersistStorage::InitNew
  2792. //
  2793. // Arguments:
  2794. // [pstg] -- the storage the object can use until saved
  2795. //
  2796. // Returns:
  2797. // S_OK
  2798. //
  2799. // History:
  2800. // Gopalk Rewritten Sep 04, 96
  2801. //
  2802. //-----------------------------------------------------------------------------
  2803. #pragma SEG(COleCache_InitNew)
  2804. STDMETHODIMP COleCache::InitNew(LPSTORAGE pstg)
  2805. {
  2806. // Validation checks
  2807. VDATEHEAP();
  2808. VDATETHREAD(this);
  2809. VDATEIFACE(pstg);
  2810. // Local variable
  2811. LPCACHENODE lpCacheNode;
  2812. // Check if m_pStg is already set
  2813. if(m_pStg)
  2814. return ResultFromScode(CO_E_ALREADYINITIALIZED);
  2815. // Save and add ref the storage
  2816. (m_pStg = pstg)->AddRef();
  2817. // Find the native object format to add native cache node
  2818. FindObjectFormat(pstg);
  2819. // Set the storage on the already cached nodes
  2820. if((!m_pCacheArray->GetItem(1) && m_pCacheArray->Length()) ||
  2821. (m_pCacheArray->GetItem(1) && m_pCacheArray->Length()>1)) {
  2822. ULONG index;
  2823. // Enumerate the cache nodes excluding native cache node
  2824. m_pCacheArray->Reset(index, FALSE);
  2825. while(lpCacheNode = m_pCacheArray->GetNext(index))
  2826. lpCacheNode->SetStg(pstg);
  2827. }
  2828. // Check if the native object has been successfully created
  2829. if(m_ulFlags & COLECACHEF_FORMATKNOWN) {
  2830. // Obtain the native cache node.
  2831. if(!(lpCacheNode = m_pCacheArray->GetItem(1)))
  2832. return ResultFromScode(E_OUTOFMEMORY);
  2833. // Static objects cannot have a server
  2834. if(m_ulFlags & COLECACHEF_STATIC)
  2835. Win4Assert(!m_pDataObject);
  2836. // Check if native cache node has just been created
  2837. if(!lpCacheNode->GetStg()) {
  2838. // Set the storage for the native cache node
  2839. lpCacheNode->SetStg(pstg);
  2840. // Set up the advise connection if the object is already running
  2841. if(m_pDataObject)
  2842. lpCacheNode->SetupAdviseConnection(m_pDataObject,
  2843. (IAdviseSink *) &m_AdviseSink);
  2844. }
  2845. }
  2846. // The spec for InitNew requires that the object should be marked dirty
  2847. // See Nt bug 284729.
  2848. m_ulFlags &= ~COLECACHEF_LOADEDSTATE;
  2849. return NOERROR;
  2850. }
  2851. //+----------------------------------------------------------------------------
  2852. //
  2853. // Member:
  2854. // COleCache::Load, public
  2855. //
  2856. // Synopsis:
  2857. // Called by DefHandler and DefLink when cache is empty
  2858. //
  2859. // Arguments:
  2860. // [pstg] [in] -- the storage to load from
  2861. // [fCacheEmpty] [in] -- Set to TRUE when cache is empty
  2862. //
  2863. // Returns:
  2864. // HRESULT
  2865. //
  2866. // History:
  2867. // Gopalk Creation Oct 24, 96
  2868. //
  2869. //-----------------------------------------------------------------------------
  2870. HRESULT COleCache::Load(LPSTORAGE pstg, BOOL fCacheEmpty)
  2871. {
  2872. // Check if m_pStg is already set
  2873. if(m_pStg)
  2874. return ResultFromScode(CO_E_ALREADYINITIALIZED);
  2875. // If Cache is not empty, follow normal load
  2876. if(!fCacheEmpty)
  2877. return Load(pstg);
  2878. else {
  2879. // Validation checks
  2880. VDATEHEAP();
  2881. VDATETHREAD(this);
  2882. VDATEIFACE(pstg);
  2883. // Save the storage
  2884. (m_pStg = pstg)->AddRef();
  2885. // Assert that there is no native cache node
  2886. Win4Assert(!m_pCacheArray->GetItem(1));
  2887. // Set the storage on the already cached nodes
  2888. if(m_pCacheArray->Length()) {
  2889. ULONG index;
  2890. LPCACHENODE lpCacheNode;
  2891. // Enumerate the cache nodes including native cache node
  2892. m_pCacheArray->Reset(index);
  2893. while(lpCacheNode = m_pCacheArray->GetNext(index))
  2894. lpCacheNode->SetStg(pstg);
  2895. }
  2896. else {
  2897. // Cache is in loaded state
  2898. m_ulFlags |= COLECACHEF_LOADEDSTATE;
  2899. }
  2900. }
  2901. #if DBG==1
  2902. // Ensure that the storage is really empty in Debug builds
  2903. HRESULT error;
  2904. LPSTREAM lpstream;
  2905. error = pstg->OpenStream(OLE_PRESENTATION_STREAM, NULL,
  2906. (STGM_READ | STGM_SHARE_EXCLUSIVE),
  2907. 0, &lpstream);
  2908. Win4Assert(error==STG_E_FILENOTFOUND);
  2909. #endif // DBG==1
  2910. return NOERROR;
  2911. }
  2912. //+----------------------------------------------------------------------------
  2913. //
  2914. // Member:
  2915. // COleCache::Load, public
  2916. //
  2917. // Synopsis:
  2918. // implements IPersistStorage::Load
  2919. //
  2920. // Arguments:
  2921. // [pstg] -- the storage to load from
  2922. //
  2923. // Returns:
  2924. // Various storage errors and S_OK
  2925. //
  2926. // Notes:
  2927. // Presentations are loaded from sequentially numbered
  2928. // streams, stopping at the first one that cannot be found.
  2929. //
  2930. // History:
  2931. // Gopalk Rewritten Sep 04, 96
  2932. //
  2933. //-----------------------------------------------------------------------------
  2934. #pragma SEG(COleCache_Load)
  2935. STDMETHODIMP COleCache::Load(LPSTORAGE pstg)
  2936. {
  2937. // Validation checks
  2938. VDATEHEAP();
  2939. VDATETHREAD(this);
  2940. VDATEIFACE(pstg);
  2941. // Local variables
  2942. CLSID clsid;
  2943. HRESULT error = NOERROR;
  2944. BOOL fCachedBefore = FALSE, fCachesLoaded = FALSE;
  2945. ULONG ulLastIndex = 0;
  2946. LPCACHENODE lpCacheNode;
  2947. // Check if m_pStg is already set
  2948. if(m_pStg)
  2949. return ResultFromScode(CO_E_ALREADYINITIALIZED);
  2950. // Save the storage
  2951. m_pStg = pstg;
  2952. // Find the native object format
  2953. FindObjectFormat(pstg);
  2954. // Set the storage on the already cached nodes
  2955. if((!m_pCacheArray->GetItem(1) && m_pCacheArray->Length()) ||
  2956. (m_pCacheArray->GetItem(1) && m_pCacheArray->Length()>1)) {
  2957. // Presentations were cached before load
  2958. Win4Assert(FALSE);
  2959. fCachedBefore = TRUE;
  2960. // Enumerate the cache nodes excluding native cache node
  2961. m_pCacheArray->Reset(ulLastIndex, FALSE);
  2962. while(lpCacheNode = m_pCacheArray->GetNext(ulLastIndex))
  2963. lpCacheNode->SetStg(pstg);
  2964. }
  2965. // Check if the native object is a static object
  2966. if(m_ulFlags & COLECACHEF_STATIC) {
  2967. UINT uiStatus;
  2968. // Static objects cannot have a server
  2969. Win4Assert(!m_pDataObject);
  2970. // Old static objects wrote data into the OLE_PRESENTATION_STREAM
  2971. // rather than the CONTENTS stream.
  2972. // If we have such a static object, we need to convert it
  2973. error = UtOlePresStmToContentsStm(pstg, OLE_PRESENTATION_STREAM,
  2974. TRUE, &uiStatus);
  2975. Win4Assert(error==NOERROR);
  2976. if(error != NOERROR)
  2977. return error;
  2978. }
  2979. if(m_ulFlags & COLECACHEF_FORMATKNOWN) {
  2980. // Obtain the native cache node.
  2981. if(!(lpCacheNode = m_pCacheArray->GetItem(1)))
  2982. return ResultFromScode(E_OUTOFMEMORY);
  2983. // Check if native cache node has just been created
  2984. if(!lpCacheNode->GetStg()) {
  2985. // Set the storage for the native cache node
  2986. lpCacheNode->SetStg(pstg);
  2987. // Set up the advise connection if the object is already running
  2988. if(m_pDataObject)
  2989. lpCacheNode->SetupAdviseConnection(m_pDataObject,
  2990. (IAdviseSink *) &m_AdviseSink);
  2991. }
  2992. // Ensure that native cache node is not blank before
  2993. // delay loading the presentation from native stream
  2994. if(lpCacheNode->IsBlank())
  2995. lpCacheNode->Load(NULL, OLE_INVALID_STREAMNUM, TRUE);
  2996. }
  2997. if(error == NOERROR) {
  2998. int iPresStreamNum=0;
  2999. ULONG index;
  3000. LPSTREAM lpstream;
  3001. OLECHAR szName[sizeof(OLE_PRESENTATION_STREAM)/sizeof(OLECHAR)];
  3002. CCacheNode BlankCache;
  3003. // Start with presentation stream 0
  3004. lstrcpyW(szName, OLE_PRESENTATION_STREAM);
  3005. // Load the presentation streams
  3006. while(TRUE) {
  3007. // Open the presentation stream
  3008. lpstream = NULL;
  3009. error = pstg->OpenStream(szName, NULL, (STGM_READ | STGM_SHARE_EXCLUSIVE),
  3010. 0, &lpstream);
  3011. if(error != NOERROR) {
  3012. if(GetScode(error) == STG_E_FILENOTFOUND) {
  3013. // Presentation stream does not exist. No error
  3014. error = NOERROR;
  3015. }
  3016. break;
  3017. }
  3018. // Presentation stream exists. Add a blank cache node
  3019. index = m_pCacheArray->AddItem(BlankCache);
  3020. if(!index) {
  3021. error = ResultFromScode(E_OUTOFMEMORY);
  3022. break;
  3023. }
  3024. lpCacheNode = m_pCacheArray->GetItem(index);
  3025. Win4Assert(lpCacheNode);
  3026. // Load the presentation from the stream
  3027. if(!iPresStreamNum) {
  3028. // Do not delay load presentation
  3029. error = lpCacheNode->Load(lpstream, iPresStreamNum, FALSE);
  3030. if(error == NOERROR)
  3031. fCachesLoaded = TRUE;
  3032. }
  3033. else {
  3034. // Delay load the presentation
  3035. error = lpCacheNode->Load(lpstream, iPresStreamNum, TRUE);
  3036. }
  3037. if(error != NOERROR)
  3038. break;
  3039. // Set the storage on the cache node
  3040. lpCacheNode->SetStg(pstg);
  3041. // If the server is runinng, set the advise connection
  3042. // We ignore the errors in setting up advise connection. Gopalk
  3043. if(m_pDataObject)
  3044. lpCacheNode->SetupAdviseConnection(m_pDataObject,
  3045. (IAdviseSink *) &m_AdviseSink);
  3046. // Check if TOC exists at the end of presentation stream 0
  3047. if(!iPresStreamNum)
  3048. if(LoadTOC(lpstream, pstg) == NOERROR)
  3049. break;
  3050. // Release the stream
  3051. lpstream->Release();
  3052. lpstream = NULL;
  3053. // Get the next presentation stream name
  3054. UtGetPresStreamName(szName, ++iPresStreamNum);
  3055. }
  3056. if(lpstream)
  3057. lpstream->Release();
  3058. lpstream = NULL;
  3059. }
  3060. if(error == NOERROR) {
  3061. // Addref the storage
  3062. m_pStg->AddRef();
  3063. // For static object remove all the caches other than those with
  3064. // iconic aspect
  3065. if(m_ulFlags & COLECACHEF_STATIC) {
  3066. ULONG index, indexToUncache = 0;
  3067. const FORMATETC* lpforetc;
  3068. // Start the enumeration after native cache node
  3069. m_pCacheArray->Reset(index, FALSE);
  3070. while(lpCacheNode = m_pCacheArray->GetNext(index)) {
  3071. lpforetc = lpCacheNode->GetFormatEtc();
  3072. if(lpforetc->dwAspect != DVASPECT_ICON) {
  3073. // Uncache any previous index that needs to be uncached
  3074. if(indexToUncache)
  3075. Uncache(indexToUncache);
  3076. // Remember the new index that needs to be uncached
  3077. indexToUncache = index;
  3078. }
  3079. }
  3080. // Uncache any remaining index that needs to be uncached
  3081. if(indexToUncache)
  3082. Uncache(indexToUncache);
  3083. }
  3084. // Check if presentation were cached before load
  3085. if(fCachedBefore) {
  3086. // Check if any presentation were loaded from disk
  3087. if(fCachesLoaded) {
  3088. // Shift the newly cached nodes to the end
  3089. // This is needed to allow presentation
  3090. // streams to be renamed during save
  3091. m_pCacheArray->ShiftToEnd(ulLastIndex);
  3092. }
  3093. }
  3094. else {
  3095. // Cache is in loaded state
  3096. m_ulFlags |= COLECACHEF_LOADEDSTATE;
  3097. }
  3098. }
  3099. else {
  3100. if(m_pDataObject) {
  3101. ULONG index;
  3102. // Tear down the advise connection set up earlier
  3103. m_pCacheArray->Reset(index);
  3104. while(lpCacheNode = m_pCacheArray->GetNext(index))
  3105. lpCacheNode->TearDownAdviseConnection(m_pDataObject);
  3106. }
  3107. // Delete all cache nodes
  3108. m_pCacheArray->DeleteAllItems();
  3109. // Reset the storage
  3110. m_pStg = NULL;
  3111. }
  3112. return error;
  3113. }
  3114. //+----------------------------------------------------------------------------
  3115. //
  3116. // Member:
  3117. // COleCache::Save, public
  3118. //
  3119. // Synopsis:
  3120. // implements IPersistStorage::Save
  3121. //
  3122. // Arguments:
  3123. // [pstgSave] -- the storage to use to save this
  3124. // [fSameAsLoad] -- is this the same storage we loaded from?
  3125. //
  3126. // Returns:
  3127. // Various storage errors
  3128. //
  3129. // Notes:
  3130. // All the caches are saved to streams with sequential numeric
  3131. // names. Also TOC is saved at the end of presentation 0
  3132. //
  3133. //
  3134. // History:
  3135. // Gopalk Rewritten Sep 04, 96
  3136. //
  3137. //-----------------------------------------------------------------------------
  3138. #pragma SEG(COleCache_Save)
  3139. STDMETHODIMP COleCache::Save(LPSTORAGE pstgSave, BOOL fSameAsLoad)
  3140. {
  3141. // Validation checks
  3142. VDATEHEAP();
  3143. VDATETHREAD(this);
  3144. VDATEIFACE(pstgSave);
  3145. // Local variables
  3146. HRESULT error, rerror = NOERROR;
  3147. ULONG index, cntCachesNotSaved;
  3148. int iPresStreamNum;
  3149. LPCACHENODE lpCacheNode;
  3150. // Check if we are in no scribble mode
  3151. // According to spec, SaveCompleted be should after Save to reset
  3152. // NOSCRIBBLEMODE. Insisting on the spec is causing some apps
  3153. // like ClipArt Gallery to break. Turn off the check. Gopalk
  3154. //if(m_ulFlags & COLECACHEF_NOSCRIBBLEMODE)
  3155. // return E_UNEXPECTED;
  3156. // If fSameAsLoad, assert that the current storage is same as given storage
  3157. // Some apps will violate this assert because for SaveAs case, they copy the
  3158. // existing storage to a new storage and call save on the new storage with
  3159. // fSameAsLoad set to TRUE. They subsequently either call SaveCompleted with
  3160. // the new storage or call SaveCompleted with NULL storage, HandsOffStorage,
  3161. // and SaveCompleted with the new storage in sequence. Gopalk
  3162. if(fSameAsLoad)
  3163. Win4Assert(m_pStg==pstgSave);
  3164. // Cache need not be saved if fSameAsLoad and not dirty
  3165. if(!fSameAsLoad || IsDirty()==NOERROR) {
  3166. // Reset the stream number
  3167. iPresStreamNum = 0;
  3168. // Check if the cache is empty
  3169. if(m_pCacheArray->Length()) {
  3170. // Cache is not empty
  3171. // Save the native cache node only if it is a static object
  3172. if(m_ulFlags & COLECACHEF_STATIC) {
  3173. lpCacheNode = m_pCacheArray->GetItem(1);
  3174. Win4Assert(lpCacheNode);
  3175. lpCacheNode->Save(pstgSave, fSameAsLoad, OLE_INVALID_STREAMNUM);
  3176. }
  3177. // Enumerate the cache nodes excluding the native cache node
  3178. m_pCacheArray->Reset(index, FALSE);
  3179. while(lpCacheNode = m_pCacheArray->GetNext(index)) {
  3180. // Save the cache node
  3181. error = lpCacheNode->Save(pstgSave, fSameAsLoad, iPresStreamNum);
  3182. // Update state information
  3183. if(error == NOERROR)
  3184. ++iPresStreamNum;
  3185. else
  3186. rerror = error;
  3187. }
  3188. // Save table of contents at the end of first pres stream
  3189. if(rerror == NOERROR)
  3190. SaveTOC(pstgSave, fSameAsLoad);
  3191. if (m_ulFlags & COLECACHEF_APICREATE) { // NT bug 281051
  3192. DWORD dwFlags;
  3193. if (S_OK == ReadOleStg(pstgSave,&dwFlags,NULL,NULL,NULL,NULL)){
  3194. WriteOleStgEx(pstgSave, NULL, NULL,
  3195. (dwFlags & ~OBJFLAGS_CACHEEMPTY),
  3196. NULL ) ;
  3197. }
  3198. }
  3199. }
  3200. // Remove any extra presentation streams left
  3201. // Due to streams getting renamed above, the streams left behind may not
  3202. // be contiguous in XXXX where XXXX is \2OlePresXXXX. Consequently, we
  3203. // may not get rid of all extra pres streams below. Gopalk
  3204. UtRemoveExtraOlePresStreams(pstgSave, iPresStreamNum);
  3205. }
  3206. // Update flags
  3207. if(rerror == NOERROR) {
  3208. m_ulFlags |= COLECACHEF_NOSCRIBBLEMODE;
  3209. if (fSameAsLoad)
  3210. m_ulFlags |= COLECACHEF_SAMEASLOAD;
  3211. else
  3212. m_ulFlags &= ~COLECACHEF_SAMEASLOAD;
  3213. }
  3214. return rerror;
  3215. }
  3216. //+----------------------------------------------------------------------------
  3217. //
  3218. // Member:
  3219. // COleCache::SaveCompleted, public
  3220. //
  3221. // Synopsis:
  3222. // implements IPersistStorage::SaveCompleted
  3223. //
  3224. // Arguments:
  3225. // [pstgNew] -- NULL, or a pointer to a new storage
  3226. //
  3227. // History:
  3228. // Gopalk Rewritten Sep 04, 96
  3229. //
  3230. //-----------------------------------------------------------------------------
  3231. #pragma SEG(COleCache_SaveCompleted)
  3232. STDMETHODIMP COleCache::SaveCompleted(LPSTORAGE pStgNew)
  3233. {
  3234. // Validation checks
  3235. VDATEHEAP();
  3236. VDATETHREAD(this);
  3237. if(pStgNew)
  3238. VDATEIFACE(pStgNew);
  3239. if(!(m_ulFlags & (COLECACHEF_NOSCRIBBLEMODE | COLECACHEF_HANDSOFSTORAGE)))
  3240. return E_UNEXPECTED;
  3241. if(m_ulFlags & COLECACHEF_HANDSOFSTORAGE && !pStgNew)
  3242. return E_INVALIDARG;
  3243. // Local variables
  3244. ULONG index;
  3245. LPCACHENODE lpCacheNode;
  3246. // Remember the new storage
  3247. if (pStgNew || (m_ulFlags & COLECACHEF_SAMEASLOAD)) {
  3248. m_ulFlags &= ~COLECACHEF_SAMEASLOAD;
  3249. if (pStgNew) {
  3250. if(m_pStg)
  3251. m_pStg->Release();
  3252. m_pStg = pStgNew;
  3253. m_pStg->AddRef();
  3254. }
  3255. if (m_ulFlags & COLECACHEF_NOSCRIBBLEMODE) {
  3256. // Enumerate the cache nodes starting with native cache node
  3257. m_pCacheArray->Reset(index);
  3258. for(unsigned long i=0;i<m_pCacheArray->Length();i++) {
  3259. // Get the next cache node
  3260. lpCacheNode = m_pCacheArray->GetNext(index);
  3261. // pCacheNode cannot be null
  3262. Win4Assert(lpCacheNode);
  3263. // Call savecompleted method of the cache node
  3264. lpCacheNode->SaveCompleted(pStgNew);
  3265. }
  3266. //The next line clears dirty flag effectively.
  3267. //Had to move it here from Save to keep apps from breaking.
  3268. m_ulFlags |= COLECACHEF_LOADEDSTATE;
  3269. }
  3270. }
  3271. // Reset flags
  3272. m_ulFlags &= ~COLECACHEF_NOSCRIBBLEMODE;
  3273. m_ulFlags &= ~COLECACHEF_HANDSOFSTORAGE;
  3274. return NOERROR;
  3275. }
  3276. //+----------------------------------------------------------------------------
  3277. //
  3278. // Member:
  3279. // COleCache::HandsOffStorage, public
  3280. //
  3281. // Synopsis:
  3282. // implements IPersistStorage::HandsOffStorage
  3283. //
  3284. // Arguments:
  3285. // none
  3286. //
  3287. // Returns:
  3288. // S_OK
  3289. //
  3290. //
  3291. // History:
  3292. // Gopalk Rewritten Sep 04, 96
  3293. //
  3294. //-----------------------------------------------------------------------------
  3295. #pragma SEG(COleCache_HandsOffStorage)
  3296. STDMETHODIMP COleCache::HandsOffStorage(void)
  3297. {
  3298. // Validation checks
  3299. VDATEHEAP();
  3300. VDATETHREAD(this);
  3301. if(!m_pStg) {
  3302. // The following Win4Assert is getting fired in Liveness tests
  3303. // Win4Assert(FALSE);
  3304. return E_UNEXPECTED;
  3305. }
  3306. // Local variables
  3307. ULONG index;
  3308. LPCACHENODE lpCacheNode;
  3309. // Enumerate the cache nodes starting with native cache node
  3310. m_pCacheArray->Reset(index);
  3311. for(unsigned long i=0;i<m_pCacheArray->Length();i++) {
  3312. // Get the next cache node
  3313. lpCacheNode = m_pCacheArray->GetNext(index);
  3314. // lpCacheNode cannot be null
  3315. Win4Assert(lpCacheNode);
  3316. // Get the formatetc of the cache node
  3317. lpCacheNode->HandsOffStorage();
  3318. }
  3319. // Release the current storage
  3320. m_pStg->Release();
  3321. m_pStg = NULL;
  3322. // Set COLECACHEF_HANDSOFSTORAGE flag
  3323. m_ulFlags |= COLECACHEF_HANDSOFSTORAGE;
  3324. return NOERROR;
  3325. }
  3326. //+----------------------------------------------------------------------------
  3327. //
  3328. // Member:
  3329. // COleCache::Locate, private
  3330. //
  3331. // Synopsis:
  3332. // Locates the cache node with the given FORMATETC
  3333. //
  3334. // Arguments:
  3335. // [foretc][in] -- FormatEtc of the desired cache node
  3336. // [lpdwCacheId][out] -- CacheId of the found cache node
  3337. //
  3338. //
  3339. // Returns:
  3340. // Pointer to the found cache node on success
  3341. // NULL otherwise
  3342. //
  3343. // History:
  3344. // Gopalk Creation Sep 04, 96
  3345. //
  3346. //-----------------------------------------------------------------------------
  3347. LPCACHENODE COleCache::Locate(LPFORMATETC lpGivenForEtc, DWORD* lpdwCacheId)
  3348. {
  3349. // New data type
  3350. typedef enum tagFormatType {
  3351. // These values are defined in order of least to best preferred, so that
  3352. // numeric comparisons are valid; DO NOT REORDER
  3353. FORMATTYPE_NONE = 0,
  3354. FORMATTYPE_ANY,
  3355. FORMATTYPE_ENHMF,
  3356. FORMATTYPE_DIB,
  3357. FORMATTYPE_MFPICT,
  3358. FORMATTYPE_USER
  3359. } FormatType;
  3360. // Local variables
  3361. ULONG index, savedIndex;
  3362. FormatType CurrFormatType;
  3363. FormatType BestFormatType;
  3364. LPFORMATETC lpCurrentForEtc;
  3365. LPCACHENODE lpCacheNode;
  3366. // Start the enumeration including the native cache
  3367. m_pCacheArray->Reset(index);
  3368. BestFormatType = FORMATTYPE_NONE;
  3369. savedIndex = 0;
  3370. for(unsigned long i=0;i<m_pCacheArray->Length();i++) {
  3371. // Get the next cache node
  3372. lpCacheNode = m_pCacheArray->GetNext(index);
  3373. // pCacheNode cannot be null
  3374. Win4Assert(lpCacheNode);
  3375. // Get the formatetc of the cache node
  3376. lpCurrentForEtc = (FORMATETC *) lpCacheNode->GetFormatEtc();
  3377. // Obtain the Formattype of the current node
  3378. if(lpCurrentForEtc->cfFormat == 0)
  3379. CurrFormatType = FORMATTYPE_ANY;
  3380. else if(lpCurrentForEtc->cfFormat == lpGivenForEtc->cfFormat)
  3381. CurrFormatType = FORMATTYPE_USER;
  3382. else if(lpCurrentForEtc->cfFormat == CF_DIB &&
  3383. lpGivenForEtc->cfFormat == CF_BITMAP)
  3384. CurrFormatType = FORMATTYPE_USER;
  3385. else if(lpCurrentForEtc->cfFormat == CF_ENHMETAFILE)
  3386. CurrFormatType = FORMATTYPE_ENHMF;
  3387. else if(lpCurrentForEtc->cfFormat == CF_DIB)
  3388. CurrFormatType = FORMATTYPE_DIB;
  3389. else if(lpCurrentForEtc->cfFormat == CF_METAFILEPICT)
  3390. CurrFormatType = FORMATTYPE_MFPICT;
  3391. else
  3392. CurrFormatType = FORMATTYPE_NONE;
  3393. // Check if the cache node is better than any we have seen so far
  3394. if(CurrFormatType > BestFormatType)
  3395. if(lpCurrentForEtc->dwAspect == lpGivenForEtc->dwAspect)
  3396. if(lpCurrentForEtc->lindex == lpGivenForEtc->lindex)
  3397. if(lpCurrentForEtc->ptd==lpGivenForEtc->ptd ||
  3398. UtCompareTargetDevice(lpCurrentForEtc->ptd, lpGivenForEtc->ptd)) {
  3399. BestFormatType = CurrFormatType;
  3400. savedIndex = index;
  3401. if(BestFormatType == FORMATTYPE_USER)
  3402. break;
  3403. }
  3404. }
  3405. // Handle the case when there is no matching cache node
  3406. if((lpGivenForEtc->cfFormat && BestFormatType != FORMATTYPE_USER) ||
  3407. (!lpGivenForEtc->cfFormat && BestFormatType == FORMATTYPE_NONE)) {
  3408. if(lpdwCacheId)
  3409. *lpdwCacheId = 0;
  3410. return NULL;
  3411. }
  3412. // There is a matching cache node
  3413. lpCacheNode = m_pCacheArray->GetItem(savedIndex);
  3414. Win4Assert(lpCacheNode);
  3415. if(lpdwCacheId)
  3416. *lpdwCacheId = savedIndex;
  3417. return lpCacheNode;
  3418. }
  3419. //+----------------------------------------------------------------------------
  3420. //
  3421. // Member:
  3422. // COleCache::Locate, private
  3423. //
  3424. // Synopsis:
  3425. // Locates the cache node with the given FORMATETC
  3426. //
  3427. // Arguments:
  3428. // [dwAspect][in] -- Aspect of the desired cache node
  3429. // [lindex] [in] -- Lindex of the desired cache node
  3430. // [ptd] [in] -- Target device of the desired cache node
  3431. //
  3432. // Returns:
  3433. // Pointer to the found cache node on success
  3434. // NULL otherwise
  3435. //
  3436. // History:
  3437. // Gopalk Creation Sep 04, 96
  3438. //
  3439. //-----------------------------------------------------------------------------
  3440. LPCACHENODE COleCache::Locate(DWORD dwAspect, LONG lindex, DVTARGETDEVICE* ptd)
  3441. {
  3442. // New data type
  3443. typedef enum tagFormatType {
  3444. // These values are defined in order of least to best preferred, so that
  3445. // numeric comparisons are valid; DO NOT REORDER
  3446. FORMATTYPE_NONE = 0,
  3447. FORMATTYPE_DIB,
  3448. FORMATTYPE_MFPICT,
  3449. FORMATTYPE_ENHMF
  3450. } FormatType;
  3451. // Local variables
  3452. ULONG index, savedIndex;
  3453. FormatType CurrFormatType;
  3454. FormatType BestFormatType;
  3455. LPFORMATETC lpCurrentForEtc;
  3456. LPCACHENODE lpCacheNode;
  3457. // Start the enumeration including the native cache
  3458. m_pCacheArray->Reset(index);
  3459. BestFormatType = FORMATTYPE_NONE;
  3460. savedIndex = 0;
  3461. for(unsigned long i=0;i<m_pCacheArray->Length();i++) {
  3462. // Get the next cache node
  3463. lpCacheNode = m_pCacheArray->GetNext(index);
  3464. // pCacheNode cannot be null
  3465. Win4Assert(lpCacheNode);
  3466. // Get the formatetc of the cache node
  3467. lpCurrentForEtc = (FORMATETC *) lpCacheNode->GetFormatEtc();
  3468. // Obtain the Formattype of the current node
  3469. if(lpCurrentForEtc->cfFormat == CF_ENHMETAFILE)
  3470. CurrFormatType = FORMATTYPE_ENHMF;
  3471. else if(lpCurrentForEtc->cfFormat == CF_METAFILEPICT)
  3472. CurrFormatType = FORMATTYPE_MFPICT;
  3473. else if(lpCurrentForEtc->cfFormat == CF_DIB)
  3474. CurrFormatType = FORMATTYPE_DIB;
  3475. else
  3476. CurrFormatType = FORMATTYPE_NONE;
  3477. // Check if the cache node is better than any we have seen so far
  3478. if(CurrFormatType > BestFormatType)
  3479. if(lpCurrentForEtc->dwAspect == dwAspect)
  3480. if(lpCurrentForEtc->lindex == lindex)
  3481. if(lpCurrentForEtc->ptd==ptd ||
  3482. UtCompareTargetDevice(lpCurrentForEtc->ptd, ptd)) {
  3483. BestFormatType = CurrFormatType;
  3484. savedIndex = index;
  3485. if(BestFormatType == FORMATTYPE_ENHMF)
  3486. break;
  3487. }
  3488. }
  3489. // Handle the case when there is no matching cache node
  3490. if(BestFormatType == FORMATTYPE_NONE)
  3491. return NULL;
  3492. // There is a matching cache node
  3493. lpCacheNode = m_pCacheArray->GetItem(savedIndex);
  3494. Win4Assert(lpCacheNode);
  3495. return lpCacheNode;
  3496. }
  3497. //+----------------------------------------------------------------------------
  3498. //
  3499. // Member:
  3500. // COleCache::CAdviseSinkImpl::QueryInterface private
  3501. //
  3502. // Synopsis:
  3503. // implements IUnknown::QueryInterface
  3504. //
  3505. // Arguments:
  3506. // [iid] [in] -- IID of the desired interface
  3507. // [ppv] [out] -- pointer to where to return the requested interface
  3508. //
  3509. // Returns:
  3510. // E_NOINTERFACE if the requested interface is not available
  3511. // NOERROR otherwise
  3512. //
  3513. // History:
  3514. // Gopalk Creation Sep 04, 96
  3515. //
  3516. //-----------------------------------------------------------------------------
  3517. STDMETHODIMP COleCache::CAdviseSinkImpl::QueryInterface(REFIID riid, LPVOID* ppv)
  3518. {
  3519. // Validation check
  3520. VDATEHEAP();
  3521. // Get the parent object
  3522. COleCache* pOleCache = GETPPARENT(this, COleCache, m_AdviseSink);
  3523. VDATETHREAD(pOleCache);
  3524. // Get the requested Interface
  3525. if(IsEqualIID(riid, IID_IUnknown))
  3526. *ppv = (void *)(IUnknown *) this;
  3527. else if(IsEqualIID(riid, IID_IAdviseSink))
  3528. *ppv = (void *)(IAdviseSink *) this;
  3529. else {
  3530. *ppv = NULL;
  3531. return ResultFromScode(E_NOINTERFACE);
  3532. }
  3533. // Call addref through the interface being returned
  3534. ((IUnknown *) *ppv)->AddRef();
  3535. return NOERROR;
  3536. }
  3537. //+----------------------------------------------------------------------------
  3538. //
  3539. // Member:
  3540. // COleCache::CAdviseSinkImpl::AddRef, private
  3541. //
  3542. // Synopsis:
  3543. // implements IUnknown::AddRef
  3544. //
  3545. // Arguments:
  3546. // none
  3547. //
  3548. // Returns:
  3549. // the object's reference count
  3550. //
  3551. // History:
  3552. // Gopalk Creation Sep 04, 96
  3553. //
  3554. //-----------------------------------------------------------------------------
  3555. STDMETHODIMP_(ULONG) COleCache::CAdviseSinkImpl::AddRef(void)
  3556. {
  3557. // Validation check
  3558. VDATEHEAP();
  3559. // Get the parent object
  3560. COleCache* pOleCache = GETPPARENT(this, COleCache, m_AdviseSink);
  3561. ULONG cExportCount;
  3562. if(!pOleCache->VerifyThreadId())
  3563. return((ULONG) RPC_E_WRONG_THREAD);
  3564. // Increment export count
  3565. cExportCount = pOleCache->IncrementExportCount();
  3566. // Addref the parent object
  3567. return cExportCount;
  3568. }
  3569. //+----------------------------------------------------------------------------
  3570. //
  3571. // Member:
  3572. // COleCache::CAdviseSinkImpl::Release, private
  3573. //
  3574. // Synopsis:
  3575. // implements IUnknown::Release
  3576. //
  3577. // Arguments:
  3578. // none
  3579. //
  3580. // Returns:
  3581. // the object's reference count
  3582. //
  3583. // History:
  3584. // Gopalk Creation Sep 04, 96
  3585. //
  3586. //-----------------------------------------------------------------------------
  3587. STDMETHODIMP_(ULONG) COleCache::CAdviseSinkImpl::Release(void)
  3588. {
  3589. // Validation check
  3590. VDATEHEAP();
  3591. // Get the parent object
  3592. COleCache* pOleCache = GETPPARENT(this, COleCache, m_AdviseSink);
  3593. ULONG cExportCount;
  3594. if(!pOleCache->VerifyThreadId())
  3595. return((ULONG) RPC_E_WRONG_THREAD);
  3596. // Decrement export count.
  3597. cExportCount = pOleCache->DecrementExportCount();
  3598. return cExportCount;
  3599. }
  3600. //+----------------------------------------------------------------------------
  3601. //
  3602. // Member:
  3603. // COleCache::CAdviseSinkImpl::OnDataChange, private
  3604. //
  3605. // Synopsis:
  3606. // The methods looks up cache node representing the given formatetc
  3607. // calls set data on it.
  3608. //
  3609. // Arguments:
  3610. // [lpForetc] [in] -- the format of the new data
  3611. // [lpStgmed] [in] -- the storage medium of the new data
  3612. //
  3613. // History:
  3614. // Gopalk Creation Sep 04, 96
  3615. //
  3616. //-----------------------------------------------------------------------------
  3617. STDMETHODIMP_(void) COleCache::CAdviseSinkImpl::OnDataChange(LPFORMATETC lpForetc,
  3618. LPSTGMEDIUM lpStgmed)
  3619. {
  3620. // Validation checks
  3621. VDATEHEAP();
  3622. if(!IsValidPtrIn(lpForetc, sizeof(FORMATETC)))
  3623. return;
  3624. if(!IsValidPtrIn(lpStgmed, sizeof(STGMEDIUM)))
  3625. return;
  3626. // Get the parent object
  3627. COleCache* pOleCache = GETPPARENT(this, COleCache, m_AdviseSink);
  3628. if(!pOleCache->VerifyThreadId())
  3629. return;
  3630. if(pOleCache->IsZombie())
  3631. return;
  3632. // Local variables
  3633. LPCACHENODE lpCacheNode;
  3634. BOOL fUpdated;
  3635. HRESULT error;
  3636. // Locate the cache node representing the formatetc
  3637. lpCacheNode = pOleCache->Locate(lpForetc);
  3638. Win4Assert(lpCacheNode);
  3639. if(lpCacheNode && lpStgmed->tymed!=TYMED_NULL) {
  3640. error = lpCacheNode->SetData(lpForetc, lpStgmed, FALSE, fUpdated);
  3641. if(error == NOERROR) {
  3642. // Cache is not in loaded state now
  3643. pOleCache->m_ulFlags &= ~COLECACHEF_LOADEDSTATE;
  3644. // Inform AspectsUpdated about the updated aspect
  3645. if(fUpdated)
  3646. pOleCache->AspectsUpdated(lpForetc->dwAspect);
  3647. }
  3648. }
  3649. return;
  3650. }
  3651. //+----------------------------------------------------------------------------
  3652. //
  3653. // Member:
  3654. // COleCache::CAdviseSinkImpl::OnViewChange, private
  3655. //
  3656. // Synopsis:
  3657. // This function should not get called
  3658. //
  3659. // Arguments:
  3660. // [aspect] [in] -- Aspect whose view has changed
  3661. // [lindex] [in] -- Lindex of the aspect that has changed
  3662. //
  3663. // History:
  3664. // Gopalk Creation Sep 04, 96
  3665. //
  3666. //-----------------------------------------------------------------------------
  3667. STDMETHODIMP_(void) COleCache::CAdviseSinkImpl::OnViewChange(DWORD aspect, LONG lindex)
  3668. {
  3669. // Validation check
  3670. VDATEHEAP();
  3671. // Get the parent object
  3672. COleCache* pOleCache = GETPPARENT(this, COleCache, m_AdviseSink);
  3673. if(!pOleCache->VerifyThreadId())
  3674. return;
  3675. // There function should not get called
  3676. Win4Assert(FALSE);
  3677. return;
  3678. }
  3679. //+----------------------------------------------------------------------------
  3680. //
  3681. // Member:
  3682. // COleCache::CAdviseSinkImpl::OnRename, private
  3683. //
  3684. // Synopsis:
  3685. // This function should not get called
  3686. //
  3687. // Arguments:
  3688. // [pmk] [in] -- New moniker
  3689. //
  3690. // History:
  3691. // Gopalk Creation Sep 04, 96
  3692. //
  3693. //-----------------------------------------------------------------------------
  3694. STDMETHODIMP_(void) COleCache::CAdviseSinkImpl::OnRename(IMoniker* pmk)
  3695. {
  3696. // Validation check
  3697. VDATEHEAP();
  3698. if(!IsValidInterface(pmk))
  3699. return;
  3700. // Get the parent object
  3701. COleCache* pOleCache = GETPPARENT(this, COleCache, m_AdviseSink);
  3702. if(!pOleCache->VerifyThreadId())
  3703. return;
  3704. // There function should not get called
  3705. Win4Assert(FALSE);
  3706. return;
  3707. }
  3708. //+----------------------------------------------------------------------------
  3709. //
  3710. // Member:
  3711. // COleCache::CAdviseSinkImpl::OnSave, private
  3712. //
  3713. // Synopsis:
  3714. // This function should not get called
  3715. //
  3716. // Arguments:
  3717. // NONE
  3718. //
  3719. // History:
  3720. // Gopalk Creation Sep 04, 96
  3721. //
  3722. //-----------------------------------------------------------------------------
  3723. STDMETHODIMP_(void) COleCache::CAdviseSinkImpl::OnSave()
  3724. {
  3725. // Validation check
  3726. VDATEHEAP();
  3727. // Get the parent object
  3728. COleCache* pOleCache = GETPPARENT(this, COleCache, m_AdviseSink);
  3729. if(!pOleCache->VerifyThreadId())
  3730. return;
  3731. // There function should not get called
  3732. Win4Assert(FALSE);
  3733. return;
  3734. }
  3735. //+----------------------------------------------------------------------------
  3736. //
  3737. // Member:
  3738. // COleCache::CAdviseSinkImpl::OnClose, private
  3739. //
  3740. // Synopsis:
  3741. // This function should not get called
  3742. //
  3743. // Arguments:
  3744. // NONE
  3745. //
  3746. // History:
  3747. // Gopalk Creation Sep 04, 96
  3748. //
  3749. //-----------------------------------------------------------------------------
  3750. STDMETHODIMP_(void) COleCache::CAdviseSinkImpl::OnClose()
  3751. {
  3752. // Validation check
  3753. VDATEHEAP();
  3754. // Get the parent object
  3755. COleCache* pOleCache = GETPPARENT(this, COleCache, m_AdviseSink);
  3756. if(!pOleCache->VerifyThreadId())
  3757. return;
  3758. // There function should not get called
  3759. Win4Assert(FALSE);
  3760. return;
  3761. }
  3762. //+----------------------------------------------------------------------------
  3763. //
  3764. // Member:
  3765. // COleCache::LoadTOC, private
  3766. //
  3767. // Synopsis:
  3768. // Loads the Table Of Contents from the given stream
  3769. //
  3770. // Arguments:
  3771. // lpStream [in] - Stream from which TOC is to be loaded
  3772. // lpZeroCache [in] - CacheNode representing presentation stream 0
  3773. //
  3774. // Returns:
  3775. // NOERROR if TOC was found and successfully loaded
  3776. // else appropriate error
  3777. //
  3778. // History:
  3779. // Gopalk Creation Sep 04, 96
  3780. //
  3781. //-----------------------------------------------------------------------------
  3782. HRESULT COleCache::LoadTOC(LPSTREAM lpStream, LPSTORAGE pStg)
  3783. {
  3784. // Local variables
  3785. HRESULT error;
  3786. int iPresStm=1;
  3787. DWORD dwBuf[2];
  3788. ULONG ulBytesRead, *TOCIndex, NumTOCAdded;
  3789. LPCACHENODE lpNativeCache, lpCacheNode;
  3790. CLIPFORMAT cfFormat;
  3791. // Read TOC header
  3792. error = lpStream->Read(dwBuf, sizeof(dwBuf), &ulBytesRead);
  3793. if(ulBytesRead==sizeof(dwBuf) && dwBuf[0]==TOCSIGNATURE) {
  3794. // TOC exists in presentation stream 0
  3795. // Initialize
  3796. error = NOERROR;
  3797. NumTOCAdded = 0;
  3798. if(dwBuf[1]) {
  3799. CCacheNode BlankCache;
  3800. TOCIndex = new unsigned long[dwBuf[1]];
  3801. if(TOCIndex) {
  3802. // Load TOC entries into new cache nodes
  3803. while(NumTOCAdded < dwBuf[1]) {
  3804. // Add a blank cache node
  3805. TOCIndex[NumTOCAdded] = m_pCacheArray->AddItem(BlankCache);
  3806. if(!TOCIndex[NumTOCAdded]) {
  3807. error = ResultFromScode(E_OUTOFMEMORY);
  3808. break;
  3809. }
  3810. lpCacheNode = m_pCacheArray->GetItem(TOCIndex[NumTOCAdded]);
  3811. Win4Assert(lpCacheNode);
  3812. ++NumTOCAdded;
  3813. // Load TOC entry from the stream
  3814. error = lpCacheNode->LoadTOCEntry(lpStream, iPresStm);
  3815. if(error != NOERROR)
  3816. break;
  3817. // Check if this is the first native TOC
  3818. if(NumTOCAdded == 1 && lpCacheNode->IsNativeCache()) {
  3819. cfFormat = lpCacheNode->GetFormatEtc()->cfFormat;
  3820. lpNativeCache = m_pCacheArray->GetItem(1);
  3821. if(lpNativeCache && (cfFormat==m_cfFormat)) {
  3822. // Both native cfFormats match.
  3823. // Delete the new native cache node
  3824. m_pCacheArray->DeleteItem(TOCIndex[NumTOCAdded-1]);
  3825. continue;
  3826. }
  3827. else {
  3828. // Either native cache does not exist or cfFormats
  3829. // do not match. This could be an auto convert case.
  3830. // Try to recover old native data
  3831. if(lpCacheNode->LoadNativeData()!=NOERROR) {
  3832. // Native data could not be loaded. May be the data has
  3833. // already been converted
  3834. m_pCacheArray->DeleteItem(TOCIndex[NumTOCAdded-1]);
  3835. continue;
  3836. }
  3837. // Old Native data successfully loaded.
  3838. // Update state on the new cache
  3839. lpCacheNode->MakeNormalCache();
  3840. lpCacheNode->SetClsid(CLSID_NULL);
  3841. }
  3842. }
  3843. // Set the storage on the cache node
  3844. lpCacheNode->SetStg(pStg);
  3845. // If the server is runinng, set the advise connection
  3846. if(m_pDataObject)
  3847. lpCacheNode->SetupAdviseConnection(m_pDataObject,
  3848. (IAdviseSink *) &m_AdviseSink);
  3849. }
  3850. // Check if TOC entries have been successfully loaded
  3851. if(error != NOERROR) {
  3852. // Something has gone wrong while loading TOC.
  3853. // Delete all newly added cache nodes
  3854. while(NumTOCAdded) {
  3855. lpCacheNode = m_pCacheArray->GetItem(TOCIndex[NumTOCAdded-1]);
  3856. Win4Assert(lpCacheNode);
  3857. if(m_pDataObject)
  3858. lpCacheNode->TearDownAdviseConnection(m_pDataObject);
  3859. m_pCacheArray->DeleteItem(TOCIndex[NumTOCAdded-1]);
  3860. --NumTOCAdded;
  3861. }
  3862. }
  3863. // Delete the TOCIndex array
  3864. delete[] TOCIndex;
  3865. }
  3866. else
  3867. error = ResultFromScode(E_OUTOFMEMORY);
  3868. }
  3869. }
  3870. else
  3871. error = ResultFromScode(E_FAIL);
  3872. return error;
  3873. }
  3874. //+----------------------------------------------------------------------------
  3875. //
  3876. // Member:
  3877. // COleCache::SaveTOC, private
  3878. //
  3879. // Synopsis:
  3880. // Saves the Table Of Contents in the given stream
  3881. //
  3882. // Arguments:
  3883. // pStg [in] - Storage in which TOC is to be saved
  3884. //
  3885. // Returns:
  3886. // NOERROR if TOC was successfully saved
  3887. // else appropriate error
  3888. //
  3889. // History:
  3890. // Gopalk Creation Sep 04, 96
  3891. //
  3892. //-----------------------------------------------------------------------------
  3893. HRESULT COleCache::SaveTOC(LPSTORAGE pStg, BOOL fSameAsLoad)
  3894. {
  3895. // Local variables
  3896. HRESULT error;
  3897. DWORD dwBuf[2];
  3898. ULONG NumTOCEntries, index;
  3899. LPSTREAM lpStream;
  3900. LPCACHENODE lpCacheNode;
  3901. LARGE_INTEGER largeInt;
  3902. ULARGE_INTEGER ulargeInt;
  3903. // There should be atleast one cached presentation for saving TOC
  3904. if(!m_pCacheArray->Length() ||
  3905. (m_pCacheArray->Length()==1 && (m_pCacheArray->GetItem(1))))
  3906. return NOERROR;
  3907. // Open presentation stream 0
  3908. error = pStg->OpenStream(OLE_PRESENTATION_STREAM, NULL,
  3909. (STGM_READWRITE | STGM_SHARE_EXCLUSIVE),
  3910. 0, &lpStream);
  3911. if(error == NOERROR) {
  3912. // Presentation stream exists. Seek to its end
  3913. LISet32(largeInt, 0);
  3914. error = lpStream->Seek(largeInt, STREAM_SEEK_END, &ulargeInt);
  3915. if(error == NOERROR) {
  3916. // Save TOC header
  3917. NumTOCEntries = m_pCacheArray->Length()-1;
  3918. dwBuf[0] = TOCSIGNATURE;
  3919. dwBuf[1] = NumTOCEntries;
  3920. error = lpStream->Write(dwBuf, sizeof(dwBuf), NULL);
  3921. if(error==NOERROR && NumTOCEntries) {
  3922. // If native cache node exists, save its TOC entry first
  3923. if(lpCacheNode = m_pCacheArray->GetItem(1)) {
  3924. error = lpCacheNode->SaveTOCEntry(lpStream, fSameAsLoad);
  3925. --NumTOCEntries;
  3926. }
  3927. if(error == NOERROR && NumTOCEntries) {
  3928. // Skip the first cached presentation
  3929. m_pCacheArray->Reset(index, FALSE);
  3930. lpCacheNode = m_pCacheArray->GetNext(index);
  3931. Win4Assert(lpCacheNode);
  3932. // Save the TOC entries of the remaining presentations
  3933. while(error==NOERROR && (lpCacheNode = m_pCacheArray->GetNext(index))) {
  3934. error = lpCacheNode->SaveTOCEntry(lpStream, fSameAsLoad);
  3935. --NumTOCEntries;
  3936. }
  3937. }
  3938. }
  3939. // Check if the TOC has been successfully saved
  3940. if(error == NOERROR)
  3941. Win4Assert(!NumTOCEntries);
  3942. else {
  3943. // Something has gone wrong while writting TOC.
  3944. // Revert presentation stream to its original length
  3945. lpStream->SetSize(ulargeInt);
  3946. }
  3947. }
  3948. // Release the stream
  3949. lpStream->Release();
  3950. }
  3951. return error;
  3952. }
  3953. //+----------------------------------------------------------------------------
  3954. //
  3955. // Member:
  3956. // COleCache::AspectsUpdated, private
  3957. //
  3958. // Synopsis:
  3959. // Notifies the container advise sink of view change if the aspect
  3960. // is one of those in which it expressed interest
  3961. //
  3962. // Arguments:
  3963. // dwAspect [in] - Aspect that changed
  3964. //
  3965. // History:
  3966. // Gopalk Creation Sep 04, 96
  3967. //
  3968. //-----------------------------------------------------------------------------
  3969. void COleCache::AspectsUpdated(DWORD dwAspects)
  3970. {
  3971. DWORD dwKnownAspects;
  3972. // Aspects known to us
  3973. dwKnownAspects = DVASPECT_CONTENT | DVASPECT_THUMBNAIL |
  3974. DVASPECT_ICON | DVASPECT_DOCPRINT;
  3975. // Ensure that we were given known aspects
  3976. if(dwAspects & ~dwKnownAspects) {
  3977. Win4Assert(FALSE);
  3978. dwAspects &= dwKnownAspects;
  3979. }
  3980. // Check if the client registered advise on any of the changed aspects.
  3981. if(m_pViewAdvSink) {
  3982. // Ensure that container requested advise on valid aspects
  3983. if(m_aspectsView & ~dwKnownAspects) {
  3984. Win4Assert(FALSE);
  3985. m_aspectsView &= dwKnownAspects;
  3986. }
  3987. // As cache is always loaded inproc, the advise to ViewAdvSink
  3988. // does not violate ASYNC call convention of not being allowed
  3989. // to call outside the current apartment
  3990. while(m_aspectsView & dwAspects) {
  3991. if(dwAspects & DVASPECT_CONTENT) {
  3992. dwAspects &= ~DVASPECT_CONTENT;
  3993. if(!(m_aspectsView & DVASPECT_CONTENT))
  3994. continue;
  3995. m_pViewAdvSink->OnViewChange(DVASPECT_CONTENT, DEF_LINDEX);
  3996. }
  3997. else if(dwAspects & DVASPECT_THUMBNAIL) {
  3998. dwAspects &= ~DVASPECT_THUMBNAIL;
  3999. if(!(m_aspectsView & DVASPECT_THUMBNAIL))
  4000. continue;
  4001. m_pViewAdvSink->OnViewChange(DVASPECT_THUMBNAIL, DEF_LINDEX);
  4002. }
  4003. else if(dwAspects & DVASPECT_ICON) {
  4004. dwAspects &= ~DVASPECT_ICON;
  4005. if(!(m_aspectsView & DVASPECT_ICON))
  4006. continue;
  4007. m_pViewAdvSink->OnViewChange(DVASPECT_ICON, DEF_LINDEX);
  4008. }
  4009. else if(dwAspects & DVASPECT_DOCPRINT) {
  4010. dwAspects &= ~DVASPECT_DOCPRINT;
  4011. if(!(m_aspectsView & DVASPECT_DOCPRINT))
  4012. continue;
  4013. m_pViewAdvSink->OnViewChange(DVASPECT_DOCPRINT, DEF_LINDEX);
  4014. }
  4015. // If client only wanted notification once, free the advise sink
  4016. if(m_advfView & ADVF_ONLYONCE) {
  4017. m_pViewAdvSink->Release();
  4018. m_pViewAdvSink = NULL;
  4019. m_advfView = 0;
  4020. m_aspectsView = 0;
  4021. }
  4022. }
  4023. }
  4024. return;
  4025. }