olecli3.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649
  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10. #include "stdafx.h"
  11. #ifdef AFX_OLE_SEG
  12. #pragma code_seg(AFX_OLE_SEG)
  13. #endif
  14. #ifdef _DEBUG
  15. #undef THIS_FILE
  16. static char THIS_FILE[] = __FILE__;
  17. #endif
  18. #define new DEBUG_NEW
  19. /////////////////////////////////////////////////////////////////////////////
  20. // COleClientItem activation
  21. // helper to get client site -- this is called from a number of places
  22. LPOLECLIENTSITE COleClientItem::GetClientSite()
  23. {
  24. ASSERT_VALID(this);
  25. LPOLECLIENTSITE lpClientSite =
  26. (LPOLECLIENTSITE)GetInterface(&IID_IOleClientSite);
  27. ASSERT(lpClientSite != NULL);
  28. return lpClientSite;
  29. }
  30. void COleClientItem::Activate(LONG nVerb, CView* pView, LPMSG lpMsg)
  31. {
  32. ASSERT_VALID(this);
  33. ASSERT(m_lpObject != NULL);
  34. if (pView != NULL)
  35. ASSERT_VALID(pView);
  36. if (lpMsg != NULL)
  37. ASSERT(AfxIsValidAddress(lpMsg, sizeof(MSG), FALSE));
  38. // store the container HWND for in place activation then do the verb
  39. if (m_pView == NULL)
  40. m_pView = pView;
  41. _AFX_OLE_STATE* pOleState = _afxOleState;
  42. CView* pViewSave = pOleState->m_pActivateView;
  43. pOleState->m_pActivateView = NULL;
  44. // get item rectangle for in-place players
  45. // (that may not support in-place activation)
  46. LPCRECT lpPosRect = NULL;
  47. CRect rectPos;
  48. if (pView != NULL)
  49. {
  50. ASSERT_VALID(pView);
  51. rectPos.SetRectEmpty();
  52. OnGetItemPosition(rectPos);
  53. if (!rectPos.IsRectEmpty())
  54. {
  55. lpPosRect = &rectPos;
  56. pOleState->m_pActivateView = pView;
  57. }
  58. }
  59. // prepare DoVerb parameters and call into the server
  60. LPOLECLIENTSITE lpClientSite = GetClientSite();
  61. HWND hWnd = pView->GetSafeHwnd();
  62. SCODE sc = m_lpObject->DoVerb(nVerb, lpMsg, lpClientSite, -1,
  63. hWnd, lpPosRect);
  64. pOleState->m_pActivateView = pViewSave;
  65. // clear out m_pView in case in-place activation only partially worked
  66. if (!IsInPlaceActive())
  67. m_pView = NULL;
  68. // update available status based on the results of DoVerb
  69. // (this is used in the links dialog).
  70. m_bLinkUnavail = (BYTE)FAILED(sc);
  71. CheckGeneral(sc);
  72. }
  73. //////////////////////////////////////////////////////////////////////////////
  74. // Create error handling
  75. void COleClientItem::CheckGeneral(SCODE sc)
  76. // set 'm_scLast'
  77. // throw exception if not ok to continue
  78. {
  79. ASSERT_VALID(this);
  80. m_scLast = S_OK; // assume things are ok
  81. // then, check for error
  82. if (sc != S_OK)
  83. {
  84. m_scLast = sc;
  85. if (!FAILED(sc))
  86. {
  87. #ifdef _DEBUG
  88. // warn about non-NULL success codes
  89. TRACE1("Warning: operation returned scode = %s.\n",
  90. AfxGetFullScodeString(m_scLast));
  91. #endif
  92. return;
  93. }
  94. // this error wasn't expected, so throw an exception
  95. AfxThrowOleException(sc);
  96. }
  97. }
  98. /////////////////////////////////////////////////////////////////////////////
  99. // COleClientItem clipboard support
  100. void COleClientItem::CopyToClipboard(BOOL bIncludeLink)
  101. {
  102. ASSERT_VALID(this);
  103. ASSERT(m_lpObject != NULL);
  104. // get clipboard data for this item
  105. COleDataSource* pDataSource = OnGetClipboardData(bIncludeLink, NULL, NULL);
  106. TRY
  107. {
  108. // put it on the clipboard
  109. pDataSource->SetClipboard();
  110. }
  111. CATCH_ALL(e)
  112. {
  113. delete pDataSource;
  114. THROW_LAST();
  115. }
  116. END_CATCH_ALL
  117. }
  118. COleDataSource* COleClientItem::OnGetClipboardData(
  119. BOOL bIncludeLink, LPPOINT lpOffset, LPSIZE lpSize)
  120. {
  121. ASSERT_VALID(this);
  122. COleDataSource* pDataSource = new COleDataSource;
  123. TRY
  124. {
  125. GetClipboardData(pDataSource, bIncludeLink, lpOffset, lpSize);
  126. }
  127. CATCH_ALL(e)
  128. {
  129. delete pDataSource;
  130. THROW_LAST();
  131. }
  132. END_CATCH_ALL
  133. ASSERT_VALID(pDataSource);
  134. return pDataSource;
  135. }
  136. DROPEFFECT COleClientItem::DoDragDrop(LPCRECT lpItemRect, CPoint ptOffset,
  137. BOOL bIncludeLink, DWORD dwEffects, LPCRECT lpRectStartDrag)
  138. {
  139. ASSERT(AfxIsValidAddress(lpItemRect, sizeof(RECT)));
  140. ASSERT_VALID(this);
  141. ASSERT(m_lpObject != NULL);
  142. DROPEFFECT dropEffect = DROPEFFECT_NONE;
  143. COleDataSource *pDataSource = NULL;
  144. TRY
  145. {
  146. // get clipboard data object for the item
  147. CSize sizeItem(
  148. lpItemRect->right - lpItemRect->left,
  149. lpItemRect->bottom - lpItemRect->top);
  150. pDataSource = OnGetClipboardData(bIncludeLink, &ptOffset, &sizeItem);
  151. // add DROPEFFECT_LINK only if link source is available
  152. LPDATAOBJECT lpDataObject = (LPDATAOBJECT)
  153. pDataSource->GetInterface(&IID_IDataObject);
  154. ASSERT(lpDataObject != NULL);
  155. FORMATETC formatEtc;
  156. formatEtc.cfFormat = (CLIPFORMAT)_oleData.cfLinkSource;
  157. formatEtc.ptd = NULL;
  158. formatEtc.dwAspect = DVASPECT_CONTENT;
  159. formatEtc.lindex = -1;
  160. formatEtc.tymed = (DWORD) -1;
  161. if (lpDataObject->QueryGetData(&formatEtc) == S_OK)
  162. dwEffects |= DROPEFFECT_LINK;
  163. // calculate default sensitivity rectangle
  164. CRect rectDrag;
  165. if (lpRectStartDrag == NULL)
  166. {
  167. rectDrag.SetRect(lpItemRect->left, lpItemRect->bottom,
  168. lpItemRect->left, lpItemRect->bottom);
  169. lpRectStartDrag = &rectDrag;
  170. }
  171. // do drag drop operation
  172. dropEffect = pDataSource->DoDragDrop(dwEffects, lpRectStartDrag);
  173. pDataSource->InternalRelease();
  174. }
  175. CATCH_ALL(e)
  176. {
  177. if (pDataSource != NULL)
  178. pDataSource->InternalRelease();
  179. THROW_LAST();
  180. }
  181. END_CATCH_ALL
  182. return dropEffect;
  183. }
  184. void COleClientItem::GetClipboardData(COleDataSource* pDataSource,
  185. BOOL bIncludeLink, LPPOINT lpOffset, LPSIZE lpSize)
  186. {
  187. ASSERT_VALID(this);
  188. ASSERT(m_lpObject != NULL);
  189. ASSERT_VALID(pDataSource);
  190. // add CF_EMBEDDEDOBJECT by creating memory storage copy of the object
  191. STGMEDIUM stgMedium;
  192. GetEmbeddedItemData(&stgMedium);
  193. pDataSource->CacheData((CLIPFORMAT)_oleData.cfEmbeddedObject, &stgMedium);
  194. // add CF_OBJECTDESCRIPTOR
  195. GetObjectDescriptorData(lpOffset, lpSize, &stgMedium);
  196. pDataSource->CacheData((CLIPFORMAT)_oleData.cfObjectDescriptor,
  197. &stgMedium);
  198. // add any presentation entries in the object's cache
  199. AddCachedData(pDataSource);
  200. // add CF_LINKSOURCE if supporting links to embeddings
  201. if (bIncludeLink && GetLinkSourceData(&stgMedium))
  202. {
  203. pDataSource->CacheData((CLIPFORMAT)_oleData.cfLinkSource, &stgMedium);
  204. // add CF_LINKSOURCEDESCRIPTOR
  205. GetObjectDescriptorData(lpOffset, lpSize, &stgMedium);
  206. pDataSource->CacheData((CLIPFORMAT)_oleData.cfLinkSourceDescriptor,
  207. &stgMedium);
  208. }
  209. }
  210. BOOL PASCAL COleClientItem::CanPaste()
  211. {
  212. // it is faster and more reliable to use the Windows clipboard
  213. // APIs instead of OleQueryCreateFromData.
  214. return IsClipboardFormatAvailable(_oleData.cfEmbedSource) ||
  215. IsClipboardFormatAvailable(_oleData.cfEmbeddedObject) ||
  216. IsClipboardFormatAvailable(_oleData.cfFileName) ||
  217. IsClipboardFormatAvailable(_oleData.cfFileNameW) ||
  218. IsClipboardFormatAvailable(CF_METAFILEPICT) ||
  219. IsClipboardFormatAvailable(CF_DIB) ||
  220. IsClipboardFormatAvailable(CF_BITMAP) ||
  221. (IsClipboardFormatAvailable(_oleData.cfOwnerLink) &&
  222. IsClipboardFormatAvailable(_oleData.cfNative));
  223. }
  224. BOOL PASCAL COleClientItem::CanPasteLink()
  225. {
  226. // it is faster and more reliable to use the Windows clipboard
  227. // APIs instead of OleQueryCreateFromData.
  228. return IsClipboardFormatAvailable(_oleData.cfLinkSource) ||
  229. IsClipboardFormatAvailable(_oleData.cfFileName) ||
  230. IsClipboardFormatAvailable(_oleData.cfFileNameW) ||
  231. IsClipboardFormatAvailable(_oleData.cfObjectLink);
  232. }
  233. BOOL PASCAL
  234. COleClientItem::CanCreateFromData(const COleDataObject* pDataObject)
  235. {
  236. if (pDataObject->m_bClipboard)
  237. return COleClientItem::CanPaste();
  238. ((COleDataObject*)pDataObject)->EnsureClipboardObject();
  239. if (pDataObject->m_lpDataObject == NULL)
  240. return FALSE;
  241. SCODE sc = ::OleQueryCreateFromData(pDataObject->m_lpDataObject);
  242. return !FAILED(sc) && sc != S_FALSE;
  243. }
  244. BOOL PASCAL
  245. COleClientItem::CanCreateLinkFromData(const COleDataObject* pDataObject)
  246. {
  247. if (pDataObject->m_bClipboard)
  248. return COleClientItem::CanPasteLink();
  249. ((COleDataObject*)pDataObject)->EnsureClipboardObject();
  250. if (pDataObject->m_lpDataObject == NULL)
  251. return FALSE;
  252. SCODE sc = ::OleQueryLinkFromData(pDataObject->m_lpDataObject);
  253. return !FAILED(sc) && sc != S_FALSE;
  254. }
  255. /////////////////////////////////////////////////////////////////////////////
  256. // Conversion & Activate As support
  257. BOOL COleClientItem::ConvertTo(REFCLSID clsidNew)
  258. {
  259. ASSERT_VALID(this);
  260. ASSERT(m_lpObject != NULL);
  261. // first, close the object
  262. Close();
  263. // convert it
  264. m_scLast = _AfxOleDoConvert(m_lpStorage, clsidNew);
  265. if (FAILED(m_scLast))
  266. return FALSE;
  267. // save IOleObject and IViewObject2 pointers
  268. LPOLEOBJECT lpObject = m_lpObject;
  269. LPVIEWOBJECT2 lpViewObject = m_lpViewObject;
  270. DWORD dwConnection = m_dwConnection;
  271. // NULL out IOleObject and IViewObject2 cached pointers
  272. m_lpObject = NULL;
  273. m_lpViewObject = NULL;
  274. m_dwConnection = 0;
  275. // then load the new object from the new storage
  276. BOOL bResult = FinishCreate(::OleLoad(m_lpStorage, IID_IUnknown,
  277. NULL, (LPLP)&m_lpObject));
  278. if (bResult)
  279. {
  280. RELEASE(lpObject);
  281. RELEASE(lpViewObject);
  282. }
  283. else
  284. {
  285. m_lpObject = lpObject;
  286. m_lpViewObject = lpViewObject;
  287. m_dwConnection = dwConnection;
  288. UpdateItemType();
  289. }
  290. ASSERT_VALID(this);
  291. return bResult;
  292. }
  293. BOOL COleClientItem::Reload()
  294. {
  295. // first, close the object
  296. Close();
  297. // release any pointers we have to the object
  298. RELEASE(m_lpObject);
  299. RELEASE(m_lpViewObject);
  300. // then reload the object with OleLoad and finish creation process
  301. BOOL bResult = FinishCreate(::OleLoad(m_lpStorage, IID_IUnknown,
  302. NULL, (LPLP)&m_lpObject));
  303. ASSERT_VALID(this);
  304. return bResult;
  305. }
  306. BOOL COleClientItem::ActivateAs(LPCTSTR lpszUserType,
  307. REFCLSID clsidOld, REFCLSID clsidNew)
  308. {
  309. ASSERT_VALID(this);
  310. ASSERT(lpszUserType == NULL || AfxIsValidString(lpszUserType));
  311. ASSERT(m_lpObject != NULL);
  312. // enable activate as
  313. m_scLast = _AfxOleDoTreatAsClass(lpszUserType, clsidOld, clsidNew);
  314. if (FAILED(m_scLast))
  315. return FALSE;
  316. // reload all items in this doucment
  317. COleDocument* pDoc = GetDocument();
  318. ASSERT_VALID(pDoc);
  319. POSITION pos = pDoc->GetStartPosition();
  320. COleClientItem* pItem;
  321. while ((pItem = pDoc->GetNextClientItem(pos)) != NULL)
  322. {
  323. // reload it, so activate as works as appropriate
  324. pItem->Reload();
  325. }
  326. ASSERT_VALID(this);
  327. return TRUE;
  328. }
  329. /////////////////////////////////////////////////////////////////////////////
  330. // COleClientItem printing support
  331. BOOL COleClientItem::SetPrintDevice(const DVTARGETDEVICE* ptd)
  332. {
  333. ASSERT(ptd == NULL ||
  334. AfxIsValidAddress(ptd, sizeof(DVTARGETDEVICE), FALSE));
  335. // get printer device information from cache
  336. LPOLECACHE lpOleCache;
  337. DVTARGETDEVICE* ptdCur = NULL;
  338. DWORD dwConnection;
  339. if (!GetPrintDeviceInfo(&lpOleCache, &ptdCur, &dwConnection))
  340. {
  341. lpOleCache = QUERYINTERFACE(m_lpObject, IOleCache);
  342. if (lpOleCache == NULL)
  343. return FALSE; // no print device info available
  344. }
  345. ASSERT(lpOleCache != NULL);
  346. // both may have no target device (considered equal)
  347. if (ptd == NULL && ptdCur == NULL)
  348. {
  349. lpOleCache->Release();
  350. CoTaskMemFree(ptdCur);
  351. return TRUE;
  352. }
  353. if (ptd != NULL && ptdCur != NULL)
  354. {
  355. // should be non-NULL and valid addresses
  356. ASSERT(AfxIsValidAddress(ptd, (size_t)ptd->tdSize));
  357. ASSERT(AfxIsValidAddress(ptdCur, (size_t)ptdCur->tdSize));
  358. // see if they compare equal
  359. if (ptdCur->tdSize == ptd->tdSize &&
  360. memcmp(ptdCur, ptd, (size_t)ptd->tdSize) == 0)
  361. {
  362. lpOleCache->Release();
  363. CoTaskMemFree(ptdCur);
  364. return TRUE;
  365. }
  366. }
  367. // calling this with NULL will just remove the prevous printer cache
  368. if (ptd != NULL)
  369. {
  370. // new cache is for CF_METAFILEPICT, DVASPECT_CONTENT
  371. FORMATETC formatEtc;
  372. formatEtc.cfFormat = CF_METAFILEPICT;
  373. formatEtc.ptd = (DVTARGETDEVICE*)ptd;
  374. formatEtc.dwAspect = DVASPECT_CONTENT;
  375. formatEtc.lindex = -1;
  376. formatEtc.tymed = TYMED_MFPICT;
  377. // attempt to cache new format
  378. DWORD dwNewConnection;
  379. if (lpOleCache->Cache(&formatEtc, ADVFCACHE_ONSAVE,
  380. &dwNewConnection) != S_OK)
  381. {
  382. lpOleCache->Release();
  383. CoTaskMemFree(ptdCur);
  384. return FALSE;
  385. }
  386. }
  387. // new format is cached successfully, uncache old format
  388. if (ptdCur != NULL)
  389. {
  390. lpOleCache->Uncache(dwConnection);
  391. CoTaskMemFree(ptdCur);
  392. }
  393. // cleanup & return
  394. lpOleCache->Release();
  395. return TRUE;
  396. }
  397. BOOL COleClientItem::SetPrintDevice(const PRINTDLG* ppd)
  398. {
  399. ASSERT(ppd == NULL || AfxIsValidAddress(ppd, sizeof(*ppd), FALSE));
  400. DVTARGETDEVICE* ptd = NULL;
  401. if (ppd != NULL)
  402. ptd = _AfxOleCreateTargetDevice((PRINTDLG*)ppd);
  403. BOOL bResult = SetPrintDevice(ptd);
  404. CoTaskMemFree(ptd);
  405. return bResult;
  406. }
  407. /////////////////////////////////////////////////////////////////////////////
  408. // other advanced COleClientItem support
  409. void COleClientItem::GetUserType(
  410. USERCLASSTYPE nUserClassType, CString& rString)
  411. {
  412. ASSERT_VALID(this);
  413. ASSERT(m_lpObject != NULL);
  414. LPOLESTR lpszUserType;
  415. CheckGeneral(m_lpObject->GetUserType(nUserClassType, &lpszUserType));
  416. ASSERT(lpszUserType != NULL);
  417. ASSERT(AfxIsValidString(lpszUserType));
  418. rString = lpszUserType;
  419. CoTaskMemFree(lpszUserType);
  420. }
  421. void COleClientItem::Run()
  422. {
  423. ASSERT_VALID(this);
  424. ASSERT(m_lpObject != NULL);
  425. // is object already in running state?
  426. if (::OleIsRunning(m_lpObject))
  427. return;
  428. // run the object -- throw exception on errors
  429. SCODE sc = ::OleRun(m_lpObject);
  430. CheckGeneral(sc);
  431. // should be running now
  432. ASSERT(::OleIsRunning(m_lpObject));
  433. }
  434. /////////////////////////////////////////////////////////////////////////////
  435. // Linked COleClientItem operations
  436. BOOL COleClientItem::UpdateLink()
  437. {
  438. ASSERT_VALID(this);
  439. ASSERT(m_lpObject != NULL);
  440. m_scLast = S_OK;
  441. if (!IsLinkUpToDate())
  442. {
  443. m_scLast = m_lpObject->Update();
  444. ASSERT_VALID(m_pDocument);
  445. m_pDocument->SetModifiedFlag();
  446. }
  447. return m_scLast == S_OK;
  448. }
  449. BOOL COleClientItem::FreezeLink()
  450. {
  451. ASSERT_VALID(this);
  452. ASSERT(m_lpObject != NULL);
  453. ASSERT(m_pDocument != NULL);
  454. ASSERT(GetType() == OT_LINK);
  455. // first save & close the item
  456. Close();
  457. // get IDataObject interface
  458. LPDATAOBJECT lpDataObject = QUERYINTERFACE(m_lpObject, IDataObject);
  459. ASSERT(lpDataObject != NULL);
  460. COleDataObject dataObject;
  461. dataObject.Attach(lpDataObject, TRUE);
  462. // save important state of original item
  463. LPOLEOBJECT lpObject = m_lpObject;
  464. LPSTORAGE lpStorage = m_lpStorage;
  465. LPLOCKBYTES lpLockBytes = m_lpLockBytes;
  466. LPVIEWOBJECT2 lpViewObject = m_lpViewObject;
  467. DWORD dwConnection = m_dwConnection;
  468. DWORD dwItemNumber = m_dwItemNumber;
  469. m_lpObject = NULL;
  470. m_lpStorage = NULL;
  471. m_lpLockBytes = NULL;
  472. m_lpViewObject = NULL;
  473. m_dwConnection = 0;
  474. // attempt to create new object from data
  475. if (!CreateStaticFromData(&dataObject))
  476. {
  477. m_lpObject = lpObject;
  478. m_lpStorage = lpStorage;
  479. m_lpLockBytes = lpLockBytes;
  480. m_lpViewObject = lpViewObject;
  481. m_dwConnection = dwConnection;
  482. return FALSE;
  483. }
  484. #ifdef _DEBUG
  485. UpdateItemType();
  486. ASSERT(GetType() == OT_STATIC);
  487. #endif
  488. // save new state of that item
  489. LPOLEOBJECT lpNewObject = m_lpObject;
  490. LPSTORAGE lpNewStorage = m_lpStorage;
  491. LPLOCKBYTES lpNewLockBytes = m_lpLockBytes;
  492. LPVIEWOBJECT2 lpNewViewObject = m_lpViewObject;
  493. DWORD dwNewConnection = m_dwConnection;
  494. DWORD dwNewItemNumber = m_dwItemNumber;
  495. // shut down old item
  496. m_lpObject = lpObject;
  497. m_lpStorage = lpStorage;
  498. m_lpLockBytes = lpLockBytes;
  499. m_lpViewObject = lpViewObject;
  500. m_dwConnection = dwConnection;
  501. m_dwItemNumber = dwItemNumber;
  502. #ifdef _DEBUG
  503. UpdateItemType();
  504. ASSERT(GetType() == OT_LINK);
  505. #endif
  506. Delete(FALSE); // revokes item & removes storage
  507. // switch to new item
  508. m_lpObject = lpNewObject;
  509. m_lpStorage = lpNewStorage;
  510. m_lpLockBytes = lpNewLockBytes;
  511. m_lpViewObject = lpNewViewObject;
  512. m_dwConnection = dwNewConnection;
  513. m_dwItemNumber = dwNewItemNumber;
  514. UpdateItemType();
  515. ASSERT(GetType() == OT_STATIC);
  516. // send an on changed with same state to invalidate the item
  517. OnChange(OLE_CHANGED_STATE, (DWORD)GetItemState());
  518. ASSERT_VALID(m_pDocument);
  519. m_pDocument->SetModifiedFlag();
  520. return TRUE;
  521. }
  522. /////////////////////////////////////////////////////////////////////////////
  523. // Special link attributes
  524. OLEUPDATE COleClientItem::GetLinkUpdateOptions()
  525. {
  526. ASSERT_VALID(this);
  527. ASSERT(m_lpObject != NULL);
  528. LPOLELINK lpOleLink = QUERYINTERFACE(m_lpObject, IOleLink);
  529. ASSERT(lpOleLink != NULL); // perhaps not a link?
  530. DWORD dwUpdateOpt;
  531. SCODE sc = lpOleLink->GetUpdateOptions(&dwUpdateOpt);
  532. lpOleLink->Release();
  533. CheckGeneral(sc); // may throw an exception
  534. return (OLEUPDATE)dwUpdateOpt;
  535. }
  536. void COleClientItem::SetLinkUpdateOptions(OLEUPDATE dwUpdateOpt)
  537. {
  538. ASSERT_VALID(this);
  539. ASSERT(m_lpObject != NULL);
  540. LPOLELINK lpOleLink = QUERYINTERFACE(m_lpObject, IOleLink);
  541. ASSERT(lpOleLink != NULL); // perhaps not a link?
  542. SCODE sc = lpOleLink->SetUpdateOptions(dwUpdateOpt);
  543. lpOleLink->Release();
  544. CheckGeneral(sc);
  545. }
  546. /////////////////////////////////////////////////////////////////////////////