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

1538 lines
41 KiB

  1. /*************************************************************************
  2. **
  3. ** OLE 2 Server Sample Code
  4. **
  5. ** svrpsobj.c
  6. **
  7. ** This file contains all PseudoObj methods and related support
  8. ** functions.
  9. **
  10. ** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved
  11. **
  12. *************************************************************************/
  13. #include "outline.h"
  14. OLEDBGDATA
  15. extern LPOUTLINEAPP g_lpApp;
  16. extern IUnknownVtbl g_PseudoObj_UnknownVtbl;
  17. extern IOleObjectVtbl g_PseudoObj_OleObjectVtbl;
  18. extern IDataObjectVtbl g_PseudoObj_DataObjectVtbl;
  19. /* PseudoObj_Init
  20. ** --------------
  21. ** Initialize fields in a newly constructed PseudoObj.
  22. ** NOTE: ref cnt of PseudoObj initialized to 0
  23. */
  24. void PseudoObj_Init(
  25. LPPSEUDOOBJ lpPseudoObj,
  26. LPSERVERNAME lpServerName,
  27. LPSERVERDOC lpServerDoc
  28. )
  29. {
  30. OleDbgOut2("++PseudoObj Created\r\n");
  31. lpPseudoObj->m_cRef = 0;
  32. lpPseudoObj->m_lpName = lpServerName;
  33. lpPseudoObj->m_lpDoc = lpServerDoc;
  34. lpPseudoObj->m_lpOleAdviseHldr = NULL;
  35. lpPseudoObj->m_lpDataAdviseHldr = NULL;
  36. lpPseudoObj->m_fObjIsClosing = FALSE;
  37. INIT_INTERFACEIMPL(
  38. &lpPseudoObj->m_Unknown,
  39. &g_PseudoObj_UnknownVtbl,
  40. lpPseudoObj
  41. );
  42. INIT_INTERFACEIMPL(
  43. &lpPseudoObj->m_OleObject,
  44. &g_PseudoObj_OleObjectVtbl,
  45. lpPseudoObj
  46. );
  47. INIT_INTERFACEIMPL(
  48. &lpPseudoObj->m_DataObject,
  49. &g_PseudoObj_DataObjectVtbl,
  50. lpPseudoObj
  51. );
  52. /* OLE2NOTE: Increment the refcnt of the Doc on behalf of the
  53. ** PseudoObj. the Document should not shut down unless all
  54. ** pseudo objects are closed. when a pseudo object is destroyed,
  55. ** it calls ServerDoc_PseudoObjUnlockDoc to release this hold on
  56. ** the document.
  57. */
  58. ServerDoc_PseudoObjLockDoc(lpServerDoc);
  59. }
  60. /* PseudoObj_AddRef
  61. ** ----------------
  62. **
  63. ** increment the ref count of the PseudoObj object.
  64. **
  65. ** Returns the new ref count on the object
  66. */
  67. ULONG PseudoObj_AddRef(LPPSEUDOOBJ lpPseudoObj)
  68. {
  69. ++lpPseudoObj->m_cRef;
  70. #if defined( _DEBUG )
  71. OleDbgOutRefCnt4(
  72. "PseudoObj_AddRef: cRef++\r\n",
  73. lpPseudoObj,
  74. lpPseudoObj->m_cRef
  75. );
  76. #endif
  77. return lpPseudoObj->m_cRef;
  78. }
  79. /* PseudoObj_Release
  80. ** -----------------
  81. **
  82. ** decrement the ref count of the PseudoObj object.
  83. ** if the ref count goes to 0, then the PseudoObj is destroyed.
  84. **
  85. ** Returns the remaining ref count on the object
  86. */
  87. ULONG PseudoObj_Release(LPPSEUDOOBJ lpPseudoObj)
  88. {
  89. ULONG cRef;
  90. /*********************************************************************
  91. ** OLE2NOTE: when the obj refcnt == 0, then destroy the object. **
  92. ** otherwise the object is still in use. **
  93. *********************************************************************/
  94. cRef = --lpPseudoObj->m_cRef;
  95. #if defined( _DEBUG )
  96. OleDbgAssertSz(lpPseudoObj->m_cRef >= 0,"Release called with cRef == 0");
  97. OleDbgOutRefCnt4(
  98. "PseudoObj_Release: cRef--\r\n", lpPseudoObj,cRef);
  99. #endif
  100. if (cRef == 0)
  101. PseudoObj_Destroy(lpPseudoObj);
  102. return cRef;
  103. }
  104. /* PseudoObj_QueryInterface
  105. ** ------------------------
  106. **
  107. ** Retrieve a pointer to an interface on the PseudoObj object.
  108. **
  109. ** Returns S_OK if interface is successfully retrieved.
  110. ** E_NOINTERFACE if the interface is not supported
  111. */
  112. HRESULT PseudoObj_QueryInterface(
  113. LPPSEUDOOBJ lpPseudoObj,
  114. REFIID riid,
  115. LPVOID FAR* lplpvObj
  116. )
  117. {
  118. SCODE sc = E_NOINTERFACE;
  119. /* OLE2NOTE: we must make sure to set all out ptr parameters to NULL. */
  120. *lplpvObj = NULL;
  121. if (IsEqualIID(riid, &IID_IUnknown)) {
  122. OleDbgOut4("PseudoObj_QueryInterface: IUnknown* RETURNED\r\n");
  123. *lplpvObj = (LPVOID) &lpPseudoObj->m_Unknown;
  124. PseudoObj_AddRef(lpPseudoObj);
  125. sc = S_OK;
  126. }
  127. else if (IsEqualIID(riid, &IID_IOleObject)) {
  128. OleDbgOut4("PseudoObj_QueryInterface: IOleObject* RETURNED\r\n");
  129. *lplpvObj = (LPVOID) &lpPseudoObj->m_OleObject;
  130. PseudoObj_AddRef(lpPseudoObj);
  131. sc = S_OK;
  132. }
  133. else if (IsEqualIID(riid, &IID_IDataObject)) {
  134. OleDbgOut4("PseudoObj_QueryInterface: IDataObject* RETURNED\r\n");
  135. *lplpvObj = (LPVOID) &lpPseudoObj->m_DataObject;
  136. PseudoObj_AddRef(lpPseudoObj);
  137. sc = S_OK;
  138. }
  139. OleDbgQueryInterfaceMethod(*lplpvObj);
  140. return ResultFromScode(sc);
  141. }
  142. /* PseudoObj_Close
  143. * ---------------
  144. *
  145. * Close the pseudo object. Force all external connections to close
  146. * down. This causes link clients to release this PseudoObj. when
  147. * the refcount actually reaches 0, then the PseudoObj will be
  148. * destroyed.
  149. *
  150. * Returns:
  151. * FALSE -- user canceled the closing of the doc.
  152. * TRUE -- the doc was successfully closed
  153. */
  154. BOOL PseudoObj_Close(LPPSEUDOOBJ lpPseudoObj)
  155. {
  156. LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpPseudoObj->m_lpDoc;
  157. LPSERVERNAME lpServerName = (LPSERVERNAME)lpPseudoObj->m_lpName;
  158. LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
  159. LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc;
  160. BOOL fStatus = TRUE;
  161. if (lpPseudoObj->m_fObjIsClosing)
  162. return TRUE; // Closing is already in progress
  163. lpPseudoObj->m_fObjIsClosing = TRUE; // guard against recursive call
  164. OLEDBG_BEGIN3("PseudoObj_Close\r\n")
  165. /* OLE2NOTE: in order to have a stable App, Doc, AND pseudo object
  166. ** during the process of closing, we intially AddRef the App,
  167. ** Doc, and PseudoObj ref counts and later Release them. These
  168. ** initial AddRefs are artificial; they are simply done to
  169. ** guarantee that these objects do not get destroyed until the
  170. ** end of this routine.
  171. */
  172. OleApp_AddRef(lpOleApp);
  173. OleDoc_AddRef(lpOleDoc);
  174. PseudoObj_AddRef(lpPseudoObj);
  175. if (lpPseudoObj->m_lpDataAdviseHldr) {
  176. /* OLE2NOTE: send last OnDataChange notification to clients
  177. ** that have registered for data notifications when object
  178. ** stops running (ADVF_DATAONSTOP)
  179. */
  180. PseudoObj_SendAdvise(
  181. lpPseudoObj,
  182. OLE_ONDATACHANGE,
  183. NULL, /* lpmkObj -- not relevant here */
  184. ADVF_DATAONSTOP
  185. );
  186. /* OLE2NOTE: we just sent the last data notification that we
  187. ** need to send; release our DataAdviseHolder. we SHOULD be
  188. ** the only one using it.
  189. */
  190. OleStdVerifyRelease(
  191. (LPUNKNOWN)lpPseudoObj->m_lpDataAdviseHldr,
  192. "DataAdviseHldr not released properly"
  193. );
  194. lpPseudoObj->m_lpDataAdviseHldr = NULL;
  195. }
  196. if (lpPseudoObj->m_lpOleAdviseHldr) {
  197. // OLE2NOTE: inform all of our linking clients that we are closing.
  198. PseudoObj_SendAdvise(
  199. lpPseudoObj,
  200. OLE_ONCLOSE,
  201. NULL, /* lpmkObj -- not relevant here */
  202. 0 /* advf -- not relevant here */
  203. );
  204. /* OLE2NOTE: OnClose is the last notification that we need to
  205. ** send; release our OleAdviseHolder. we SHOULD be the only
  206. ** one using it. this will make our destructor realize that
  207. ** OnClose notification has already been sent.
  208. */
  209. OleStdVerifyRelease(
  210. (LPUNKNOWN)lpPseudoObj->m_lpOleAdviseHldr,
  211. "OleAdviseHldr not released properly"
  212. );
  213. lpPseudoObj->m_lpOleAdviseHldr = NULL;
  214. }
  215. /* OLE2NOTE: this call forces all external connections to our
  216. ** object to close down and therefore guarantees that we receive
  217. ** all releases associated with those external connections.
  218. */
  219. OLEDBG_BEGIN2("CoDisconnectObject called\r\n")
  220. CoDisconnectObject((LPUNKNOWN)&lpPseudoObj->m_Unknown, 0);
  221. OLEDBG_END2
  222. PseudoObj_Release(lpPseudoObj); // release artificial AddRef above
  223. OleDoc_Release(lpOleDoc); // release artificial AddRef above
  224. OleApp_Release(lpOleApp); // release artificial AddRef above
  225. OLEDBG_END3
  226. return fStatus;
  227. }
  228. /* PseudoObj_Destroy
  229. ** -----------------
  230. ** Destroy (Free) the memory used by a PseudoObj structure.
  231. ** This function is called when the ref count of the PseudoObj goes
  232. ** to zero. the ref cnt goes to zero after PseudoObj_Delete forces
  233. ** the OleObject to unload and release its pointers to the
  234. ** PseudoObj IOleClientSite and IAdviseSink interfaces.
  235. */
  236. void PseudoObj_Destroy(LPPSEUDOOBJ lpPseudoObj)
  237. {
  238. LPSERVERDOC lpServerDoc = lpPseudoObj->m_lpDoc;
  239. LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
  240. LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc;
  241. OLEDBG_BEGIN3("PseudoObj_Destroy\r\n")
  242. /* OLE2NOTE: in order to have a stable App, Doc, AND pseudo object
  243. ** during the process of closing, we intially AddRef the App,
  244. ** Doc ref counts and later Release them. These
  245. ** initial AddRefs are artificial; they are simply done to
  246. ** guarantee that these objects do not get destroyed until the
  247. ** end of this routine.
  248. */
  249. OleApp_AddRef(lpOleApp);
  250. OleDoc_AddRef(lpOleDoc);
  251. /******************************************************************
  252. ** OLE2NOTE: we no longer need the advise and enum holder objects,
  253. ** so release them.
  254. ******************************************************************/
  255. if (lpPseudoObj->m_lpDataAdviseHldr) {
  256. /* release DataAdviseHldr; we SHOULD be the only one using it. */
  257. OleStdVerifyRelease(
  258. (LPUNKNOWN)lpPseudoObj->m_lpDataAdviseHldr,
  259. "DataAdviseHldr not released properly"
  260. );
  261. lpPseudoObj->m_lpDataAdviseHldr = NULL;
  262. }
  263. if (lpPseudoObj->m_lpOleAdviseHldr) {
  264. /* release OleAdviseHldr; we SHOULD be the only one using it. */
  265. OleStdVerifyRelease(
  266. (LPUNKNOWN)lpPseudoObj->m_lpOleAdviseHldr,
  267. "OleAdviseHldr not released properly"
  268. );
  269. lpPseudoObj->m_lpOleAdviseHldr = NULL;
  270. }
  271. /* forget the pointer to destroyed PseudoObj in NameTable */
  272. if (lpPseudoObj->m_lpName)
  273. lpPseudoObj->m_lpName->m_lpPseudoObj = NULL;
  274. /* OLE2NOTE: release the lock on the Doc held on behalf of the
  275. ** PseudoObj. the Document should not shut down unless all
  276. ** pseudo objects are closed. when a pseudo object is first
  277. ** created, it calls ServerDoc_PseudoObjLockDoc to guarantee
  278. ** that the document stays alive (called from PseudoObj_Init).
  279. */
  280. ServerDoc_PseudoObjUnlockDoc(lpServerDoc, lpPseudoObj);
  281. Delete(lpPseudoObj); // Free the memory for the structure itself
  282. OleDoc_Release(lpOleDoc); // release artificial AddRef above
  283. OleApp_Release(lpOleApp); // release artificial AddRef above
  284. OLEDBG_END3
  285. }
  286. /* PseudoObj_GetSel
  287. ** ----------------
  288. ** Return the line range for the pseudo object
  289. */
  290. void PseudoObj_GetSel(LPPSEUDOOBJ lpPseudoObj, LPLINERANGE lplrSel)
  291. {
  292. LPOUTLINENAME lpOutlineName = (LPOUTLINENAME)lpPseudoObj->m_lpName;
  293. lplrSel->m_nStartLine = lpOutlineName->m_nStartLine;
  294. lplrSel->m_nEndLine = lpOutlineName->m_nEndLine;
  295. }
  296. /* PseudoObj_GetExtent
  297. * -------------------
  298. *
  299. * Get the extent (width, height) of the entire document.
  300. */
  301. void PseudoObj_GetExtent(LPPSEUDOOBJ lpPseudoObj, LPSIZEL lpsizel)
  302. {
  303. LPOLEDOC lpOleDoc = (LPOLEDOC)lpPseudoObj->m_lpDoc;
  304. LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList;
  305. LINERANGE lrSel;
  306. PseudoObj_GetSel(lpPseudoObj, (LPLINERANGE)&lrSel);
  307. LineList_CalcSelExtentInHimetric(lpLL, (LPLINERANGE)&lrSel, lpsizel);
  308. }
  309. /* PseudoObj_SendAdvise
  310. * --------------------
  311. *
  312. * This function sends an advise notification on behalf of a specific
  313. * doc object to all its clients.
  314. */
  315. void PseudoObj_SendAdvise(
  316. LPPSEUDOOBJ lpPseudoObj,
  317. WORD wAdvise,
  318. LPMONIKER lpmkObj,
  319. DWORD dwAdvf
  320. )
  321. {
  322. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpPseudoObj->m_lpDoc;
  323. switch (wAdvise) {
  324. case OLE_ONDATACHANGE:
  325. // inform clients that the data of the object has changed
  326. if (lpOutlineDoc->m_nDisableDraw == 0) {
  327. /* drawing is currently enabled. inform clients that
  328. ** the data of the object has changed
  329. */
  330. lpPseudoObj->m_fDataChanged = FALSE;
  331. if (lpPseudoObj->m_lpDataAdviseHldr) {
  332. OLEDBG_BEGIN2("IDataAdviseHolder::SendOnDataChange called\r\n");
  333. lpPseudoObj->m_lpDataAdviseHldr->lpVtbl->SendOnDataChange(
  334. lpPseudoObj->m_lpDataAdviseHldr,
  335. (LPDATAOBJECT)&lpPseudoObj->m_DataObject,
  336. 0,
  337. dwAdvf
  338. );
  339. OLEDBG_END2
  340. }
  341. } else {
  342. /* drawing is currently disabled. do not send
  343. ** notifications until drawing is re-enabled.
  344. */
  345. lpPseudoObj->m_fDataChanged = TRUE;
  346. }
  347. break;
  348. case OLE_ONCLOSE:
  349. // inform clients that the object is shutting down
  350. if (lpPseudoObj->m_lpOleAdviseHldr) {
  351. OLEDBG_BEGIN2("IOleAdviseHolder::SendOnClose called\r\n");
  352. lpPseudoObj->m_lpOleAdviseHldr->lpVtbl->SendOnClose(
  353. lpPseudoObj->m_lpOleAdviseHldr
  354. );
  355. OLEDBG_END2
  356. }
  357. break;
  358. case OLE_ONSAVE:
  359. // inform clients that the object has been saved
  360. if (lpPseudoObj->m_lpOleAdviseHldr) {
  361. OLEDBG_BEGIN2("IOleAdviseHolder::SendOnClose called\r\n");
  362. lpPseudoObj->m_lpOleAdviseHldr->lpVtbl->SendOnSave(
  363. lpPseudoObj->m_lpOleAdviseHldr
  364. );
  365. OLEDBG_END2
  366. }
  367. break;
  368. case OLE_ONRENAME:
  369. // inform clients that the object's name has changed
  370. if (lpmkObj && lpPseudoObj->m_lpOleAdviseHldr) {
  371. OLEDBG_BEGIN2("IOleAdviseHolder::SendOnRename called\r\n");
  372. if (lpPseudoObj->m_lpOleAdviseHldr)
  373. lpPseudoObj->m_lpOleAdviseHldr->lpVtbl->SendOnRename(
  374. lpPseudoObj->m_lpOleAdviseHldr,
  375. lpmkObj
  376. );
  377. OLEDBG_END2
  378. }
  379. break;
  380. }
  381. }
  382. /* PseudoObj_GetFullMoniker
  383. * ------------------------
  384. *
  385. * Returns the Full, absolute Moniker which identifies this pseudo object.
  386. */
  387. LPMONIKER PseudoObj_GetFullMoniker(LPPSEUDOOBJ lpPseudoObj, LPMONIKER lpmkDoc)
  388. {
  389. LPOUTLINENAME lpOutlineName = (LPOUTLINENAME)lpPseudoObj->m_lpName;
  390. LPMONIKER lpmkItem = NULL;
  391. LPMONIKER lpmkPseudoObj = NULL;
  392. if (lpmkDoc != NULL) {
  393. CreateItemMonikerA(OLESTDDELIM,lpOutlineName->m_szName,&lpmkItem);
  394. /* OLE2NOTE: create an absolute moniker which identifies the
  395. ** pseudo object. this moniker is created as a composite of
  396. ** the absolute moniker for the entire document appended
  397. ** with an item moniker which identifies the selection of
  398. ** the pseudo object relative to the document.
  399. */
  400. CreateGenericComposite(lpmkDoc, lpmkItem, &lpmkPseudoObj);
  401. if (lpmkItem)
  402. OleStdRelease((LPUNKNOWN)lpmkItem);
  403. return lpmkPseudoObj;
  404. } else {
  405. return NULL;
  406. }
  407. }
  408. /*************************************************************************
  409. ** PseudoObj::IUnknown interface implementation
  410. *************************************************************************/
  411. STDMETHODIMP PseudoObj_Unk_QueryInterface(
  412. LPUNKNOWN lpThis,
  413. REFIID riid,
  414. LPVOID FAR* lplpvObj
  415. )
  416. {
  417. LPPSEUDOOBJ lpPseudoObj =
  418. ((struct CPseudoObjUnknownImpl FAR*)lpThis)->lpPseudoObj;
  419. return PseudoObj_QueryInterface(lpPseudoObj, riid, lplpvObj);
  420. }
  421. STDMETHODIMP_(ULONG) PseudoObj_Unk_AddRef(LPUNKNOWN lpThis)
  422. {
  423. LPPSEUDOOBJ lpPseudoObj =
  424. ((struct CPseudoObjUnknownImpl FAR*)lpThis)->lpPseudoObj;
  425. OleDbgAddRefMethod(lpThis, "IUnknown");
  426. return PseudoObj_AddRef(lpPseudoObj);
  427. }
  428. STDMETHODIMP_(ULONG) PseudoObj_Unk_Release (LPUNKNOWN lpThis)
  429. {
  430. LPPSEUDOOBJ lpPseudoObj =
  431. ((struct CPseudoObjUnknownImpl FAR*)lpThis)->lpPseudoObj;
  432. OleDbgReleaseMethod(lpThis, "IUnknown");
  433. return PseudoObj_Release(lpPseudoObj);
  434. }
  435. /*************************************************************************
  436. ** PseudoObj::IOleObject interface implementation
  437. *************************************************************************/
  438. STDMETHODIMP PseudoObj_OleObj_QueryInterface(
  439. LPOLEOBJECT lpThis,
  440. REFIID riid,
  441. LPVOID FAR* lplpvObj
  442. )
  443. {
  444. LPPSEUDOOBJ lpPseudoObj =
  445. ((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj;
  446. return PseudoObj_QueryInterface(lpPseudoObj, riid, lplpvObj);
  447. }
  448. STDMETHODIMP_(ULONG) PseudoObj_OleObj_AddRef(LPOLEOBJECT lpThis)
  449. {
  450. LPPSEUDOOBJ lpPseudoObj =
  451. ((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj;
  452. OleDbgAddRefMethod(lpThis, "IOleObject");
  453. return PseudoObj_AddRef((LPPSEUDOOBJ)lpPseudoObj);
  454. }
  455. STDMETHODIMP_(ULONG) PseudoObj_OleObj_Release(LPOLEOBJECT lpThis)
  456. {
  457. LPPSEUDOOBJ lpPseudoObj =
  458. ((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj;
  459. OleDbgReleaseMethod(lpThis, "IOleObject");
  460. return PseudoObj_Release((LPPSEUDOOBJ)lpPseudoObj);
  461. }
  462. STDMETHODIMP PseudoObj_OleObj_SetClientSite(
  463. LPOLEOBJECT lpThis,
  464. LPOLECLIENTSITE lpClientSite
  465. )
  466. {
  467. OleDbgOut2("PseudoObj_OleObj_SetClientSite\r\n");
  468. // OLE2NOTE: a pseudo object does NOT support SetExtent
  469. return ResultFromScode(E_FAIL);
  470. }
  471. STDMETHODIMP PseudoObj_OleObj_GetClientSite(
  472. LPOLEOBJECT lpThis,
  473. LPOLECLIENTSITE FAR* lplpClientSite
  474. )
  475. {
  476. OleDbgOut2("PseudoObj_OleObj_GetClientSite\r\n");
  477. *lplpClientSite = NULL;
  478. // OLE2NOTE: a pseudo object does NOT support SetExtent
  479. return ResultFromScode(E_FAIL);
  480. }
  481. STDMETHODIMP PseudoObj_OleObj_SetHostNamesA(
  482. LPOLEOBJECT lpThis,
  483. LPCSTR szContainerApp,
  484. LPCSTR szContainerObj
  485. )
  486. {
  487. OleDbgOut2("PseudoObj_OleObj_SetHostNamesA\r\n");
  488. // OLE2NOTE: a pseudo object does NOT support SetExtent
  489. return ResultFromScode(E_FAIL);
  490. }
  491. STDMETHODIMP PseudoObj_OleObj_SetHostNames(
  492. LPOLEOBJECT lpThis,
  493. LPCOLESTR szContainerApp,
  494. LPCOLESTR szContainerObj
  495. )
  496. {
  497. OleDbgOut2("PseudoObj_OleObj_SetHostNames\r\n");
  498. // OLE2NOTE: a pseudo object does NOT support SetExtent
  499. return ResultFromScode(E_FAIL);
  500. }
  501. STDMETHODIMP PseudoObj_OleObj_Close(
  502. LPOLEOBJECT lpThis,
  503. DWORD dwSaveOption
  504. )
  505. {
  506. LPPSEUDOOBJ lpPseudoObj =
  507. ((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj;
  508. BOOL fStatus;
  509. OLEDBG_BEGIN2("PseudoObj_OleObj_Close\r\n")
  510. /* OLE2NOTE: a pseudo object's implementation of IOleObject::Close
  511. ** should ignore the dwSaveOption parameter. it is NOT
  512. ** applicable to pseudo objects.
  513. */
  514. fStatus = PseudoObj_Close(lpPseudoObj);
  515. OleDbgAssertSz(fStatus == TRUE, "PseudoObj_OleObj_Close failed\r\n");
  516. OLEDBG_END2
  517. return NOERROR;
  518. }
  519. STDMETHODIMP PseudoObj_OleObj_SetMoniker(
  520. LPOLEOBJECT lpThis,
  521. DWORD dwWhichMoniker,
  522. LPMONIKER lpmk
  523. )
  524. {
  525. OleDbgOut2("PseudoObj_OleObj_SetMoniker\r\n");
  526. // OLE2NOTE: a pseudo object does NOT support SetMoniker
  527. return ResultFromScode(E_FAIL);
  528. }
  529. STDMETHODIMP PseudoObj_OleObj_GetMoniker(
  530. LPOLEOBJECT lpThis,
  531. DWORD dwAssign,
  532. DWORD dwWhichMoniker,
  533. LPMONIKER FAR* lplpmk
  534. )
  535. {
  536. LPPSEUDOOBJ lpPseudoObj =
  537. ((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj;
  538. LPOLEDOC lpOleDoc = (LPOLEDOC)lpPseudoObj->m_lpDoc;
  539. LPMONIKER lpmkDoc;
  540. OLEDBG_BEGIN2("PseudoObj_OleObj_GetMoniker\r\n")
  541. lpmkDoc = OleDoc_GetFullMoniker(lpOleDoc, GETMONIKER_ONLYIFTHERE);
  542. *lplpmk = PseudoObj_GetFullMoniker(lpPseudoObj, lpmkDoc);
  543. OLEDBG_END2
  544. if (*lplpmk != NULL)
  545. return NOERROR;
  546. else
  547. return ResultFromScode(E_FAIL);
  548. }
  549. STDMETHODIMP PseudoObj_OleObj_InitFromData(
  550. LPOLEOBJECT lpThis,
  551. LPDATAOBJECT lpDataObject,
  552. BOOL fCreation,
  553. DWORD reserved
  554. )
  555. {
  556. LPPSEUDOOBJ lpPseudoObj =
  557. ((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj;
  558. OleDbgOut2("PseudoObj_OleObj_InitFromData\r\n");
  559. // REVIEW: NOT YET IMPLEMENTED
  560. return ResultFromScode(E_NOTIMPL);
  561. }
  562. STDMETHODIMP PseudoObj_OleObj_GetClipboardData(
  563. LPOLEOBJECT lpThis,
  564. DWORD reserved,
  565. LPDATAOBJECT FAR* lplpDataObject
  566. )
  567. {
  568. LPPSEUDOOBJ lpPseudoObj =
  569. ((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj;
  570. OleDbgOut2("PseudoObj_OleObj_GetClipboardData\r\n");
  571. // REVIEW: NOT YET IMPLEMENTED
  572. return ResultFromScode(E_NOTIMPL);
  573. }
  574. STDMETHODIMP PseudoObj_OleObj_DoVerb(
  575. LPOLEOBJECT lpThis,
  576. LONG lVerb,
  577. LPMSG lpmsg,
  578. LPOLECLIENTSITE lpActiveSite,
  579. LONG lindex,
  580. HWND hwndParent,
  581. LPCRECT lprcPosRect
  582. )
  583. {
  584. LPPSEUDOOBJ lpPseudoObj =
  585. ((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj;
  586. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpPseudoObj->m_lpDoc;
  587. LPSERVERDOC lpServerDoc = lpPseudoObj->m_lpDoc;
  588. LINERANGE lrSel;
  589. HRESULT hrErr;
  590. OLEDBG_BEGIN2("PseudoObj_OleObj_DoVerb\r\n");
  591. /* OLE2NOTE: we must first ask our Document to perform the same
  592. ** verb. then if the verb is NOT OLEIVERB_HIDE we should also
  593. ** select the range of our pseudo object.
  594. ** however, we must give our document its own embedding site as
  595. ** its active site.
  596. */
  597. hrErr = SvrDoc_OleObj_DoVerb(
  598. (LPOLEOBJECT)&lpServerDoc->m_OleObject,
  599. lVerb,
  600. lpmsg,
  601. lpServerDoc->m_lpOleClientSite,
  602. lindex,
  603. NULL, /* we have no hwndParent to give */
  604. NULL /* we have no lprcPosRect to give */
  605. );
  606. if (FAILED(hrErr)) {
  607. OLEDBG_END2
  608. return hrErr;
  609. }
  610. if (lVerb != OLEIVERB_HIDE) {
  611. PseudoObj_GetSel(lpPseudoObj, &lrSel);
  612. OutlineDoc_SetSel(lpOutlineDoc, &lrSel);
  613. }
  614. OLEDBG_END2
  615. return NOERROR;
  616. }
  617. STDMETHODIMP PseudoObj_OleObj_EnumVerbs(
  618. LPOLEOBJECT lpThis,
  619. LPENUMOLEVERB FAR* lplpenumOleVerb
  620. )
  621. {
  622. OleDbgOut2("PseudoObj_OleObj_EnumVerbs\r\n");
  623. /* OLE2NOTE: we must make sure to set all out parameters to NULL. */
  624. *lplpenumOleVerb = NULL;
  625. /* A pseudo object may NOT return OLE_S_USEREG; they must call the
  626. ** OleReg* API or provide their own implementation. Because this
  627. ** pseudo object does NOT implement IPersist, simply a low-level
  628. ** remoting handler (ProxyManager) object as opposed to a
  629. ** DefHandler object is used as the handler for the pseudo
  630. ** object in a clients process space. The ProxyManager does NOT
  631. ** handle the OLE_S_USEREG return values.
  632. */
  633. return OleRegEnumVerbs((REFCLSID)&CLSID_APP, lplpenumOleVerb);
  634. }
  635. STDMETHODIMP PseudoObj_OleObj_Update(LPOLEOBJECT lpThis)
  636. {
  637. OleDbgOut2("PseudoObj_OleObj_Update\r\n");
  638. /* OLE2NOTE: a server-only app is always "up-to-date".
  639. ** a container-app which contains links where the link source
  640. ** has changed since the last update of the link would be
  641. ** considered "out-of-date". the "Update" method instructs the
  642. ** object to get an update from any out-of-date links.
  643. */
  644. return NOERROR;
  645. }
  646. STDMETHODIMP PseudoObj_OleObj_IsUpToDate(LPOLEOBJECT lpThis)
  647. {
  648. LPPSEUDOOBJ lpPseudoObj =
  649. ((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj;
  650. OleDbgOut2("PseudoObj_OleObj_IsUpToDate\r\n");
  651. /* OLE2NOTE: a server-only app is always "up-to-date".
  652. ** a container-app which contains links where the link source
  653. ** has changed since the last update of the link would be
  654. ** considered "out-of-date".
  655. */
  656. return NOERROR;
  657. }
  658. STDMETHODIMP PseudoObj_OleObj_GetUserClassID(
  659. LPOLEOBJECT lpThis,
  660. LPCLSID lpclsid
  661. )
  662. {
  663. LPPSEUDOOBJ lpPseudoObj =
  664. ((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj;
  665. LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpPseudoObj->m_lpDoc;
  666. OleDbgOut2("PseudoObj_OleObj_GetUserClassID\r\n");
  667. /* OLE2NOTE: we must be carefull to return the correct CLSID here.
  668. ** if we are currently preforming a "TreatAs (aka. ActivateAs)"
  669. ** operation then we need to return the class of the object
  670. ** written in the storage of the object. otherwise we would
  671. ** return our own class id.
  672. */
  673. return ServerDoc_GetClassID(lpServerDoc, lpclsid);
  674. }
  675. STDMETHODIMP PseudoObj_OleObj_GetUserTypeA(
  676. LPOLEOBJECT lpThis,
  677. DWORD dwFormOfType,
  678. LPSTR FAR* lpszUserType
  679. )
  680. {
  681. LPPSEUDOOBJ lpPseudoObj =
  682. ((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj;
  683. LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpPseudoObj->m_lpDoc;
  684. OleDbgOut2("PseudoObj_OleObj_GetUserType\r\n");
  685. /* OLE2NOTE: we must make sure to set all out parameters to NULL. */
  686. *lpszUserType = NULL;
  687. /* OLE2NOTE: we must be carefull to return the correct user type here.
  688. ** if we are currently preforming a "TreatAs (aka. ActivateAs)"
  689. ** operation then we need to return the user type name that
  690. ** corresponds to the class of the object we are currently
  691. ** emmulating. otherwise we should return our normal user type
  692. ** name corresponding to our own class. This routine determines
  693. ** the current clsid in effect.
  694. **
  695. ** A pseudo object may NOT return OLE_S_USEREG; they must call the
  696. ** OleReg* API or provide their own implementation. Because this
  697. ** pseudo object does NOT implement IPersist, simply a low-level
  698. ** remoting handler (ProxyManager) object as opposed to a
  699. ** DefHandler object is used as the handler for the pseudo
  700. ** object in a clients process space. The ProxyManager does NOT
  701. ** handle the OLE_S_USEREG return values.
  702. */
  703. #if defined( SVR_TREATAS )
  704. if (! IsEqualCLSID(&lpServerDoc->m_clsidTreatAs, &CLSID_NULL) )
  705. return OleRegGetUserTypeA(
  706. &lpServerDoc->m_clsidTreatAs,dwFormOfType,lpszUserType);
  707. else
  708. #endif // SVR_TREATAS
  709. return OleRegGetUserTypeA(&CLSID_APP, dwFormOfType, lpszUserType);
  710. }
  711. STDMETHODIMP PseudoObj_OleObj_GetUserType(
  712. LPOLEOBJECT lpThis,
  713. DWORD dwFormOfType,
  714. LPOLESTR FAR* lpszUserType
  715. )
  716. {
  717. LPSTR pstr;
  718. HRESULT hr = PseudoObj_OleObj_GetUserTypeA(lpThis, dwFormOfType, &pstr);
  719. CopyAndFreeSTR(pstr, lpszUserType);
  720. return hr;
  721. }
  722. STDMETHODIMP PseudoObj_OleObj_SetExtent(
  723. LPOLEOBJECT lpThis,
  724. DWORD dwDrawAspect,
  725. LPSIZEL lplgrc
  726. )
  727. {
  728. OleDbgOut2("PseudoObj_OleObj_SetExtent\r\n");
  729. // OLE2NOTE: a pseudo object does NOT support SetExtent
  730. return ResultFromScode(E_FAIL);
  731. }
  732. STDMETHODIMP PseudoObj_OleObj_GetExtent(
  733. LPOLEOBJECT lpThis,
  734. DWORD dwDrawAspect,
  735. LPSIZEL lpsizel
  736. )
  737. {
  738. LPPSEUDOOBJ lpPseudoObj =
  739. ((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj;
  740. OleDbgOut2("PseudoObj_OleObj_GetExtent\r\n");
  741. /* OLE2NOTE: it is VERY important to check which aspect the caller
  742. ** is asking about. an object implemented by a server EXE MAY
  743. ** fail to return extents when asked for DVASPECT_ICON.
  744. */
  745. if (dwDrawAspect == DVASPECT_CONTENT) {
  746. PseudoObj_GetExtent(lpPseudoObj, lpsizel);
  747. return NOERROR;
  748. }
  749. else
  750. {
  751. return ResultFromScode(E_FAIL);
  752. }
  753. }
  754. STDMETHODIMP PseudoObj_OleObj_Advise(
  755. LPOLEOBJECT lpThis,
  756. LPADVISESINK lpAdvSink,
  757. LPDWORD lpdwConnection
  758. )
  759. {
  760. LPPSEUDOOBJ lpPseudoObj =
  761. ((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj;
  762. HRESULT hrErr;
  763. SCODE sc;
  764. OLEDBG_BEGIN2("PseudoObj_OleObj_Advise\r\n");
  765. if (lpPseudoObj->m_lpOleAdviseHldr == NULL &&
  766. CreateOleAdviseHolder(&lpPseudoObj->m_lpOleAdviseHldr) != NOERROR) {
  767. sc = E_OUTOFMEMORY;
  768. goto error;
  769. }
  770. OLEDBG_BEGIN2("IOleAdviseHolder::Advise called\r\n")
  771. hrErr = lpPseudoObj->m_lpOleAdviseHldr->lpVtbl->Advise(
  772. lpPseudoObj->m_lpOleAdviseHldr,
  773. lpAdvSink,
  774. lpdwConnection
  775. );
  776. OLEDBG_END2
  777. OLEDBG_END2
  778. return hrErr;
  779. error:
  780. OLEDBG_END2
  781. return ResultFromScode(sc);
  782. }
  783. STDMETHODIMP PseudoObj_OleObj_Unadvise(LPOLEOBJECT lpThis, DWORD dwConnection)
  784. {
  785. LPPSEUDOOBJ lpPseudoObj =
  786. ((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj;
  787. HRESULT hrErr;
  788. SCODE sc;
  789. OLEDBG_BEGIN2("PseudoObj_OleObj_Unadvise\r\n");
  790. if (lpPseudoObj->m_lpOleAdviseHldr == NULL) {
  791. sc = E_FAIL;
  792. goto error;
  793. }
  794. OLEDBG_BEGIN2("IOleAdviseHolder::Unadvise called\r\n")
  795. hrErr = lpPseudoObj->m_lpOleAdviseHldr->lpVtbl->Unadvise(
  796. lpPseudoObj->m_lpOleAdviseHldr,
  797. dwConnection
  798. );
  799. OLEDBG_END2
  800. OLEDBG_END2
  801. return hrErr;
  802. error:
  803. OLEDBG_END2
  804. return ResultFromScode(sc);
  805. }
  806. STDMETHODIMP PseudoObj_OleObj_EnumAdvise(
  807. LPOLEOBJECT lpThis,
  808. LPENUMSTATDATA FAR* lplpenumAdvise
  809. )
  810. {
  811. LPPSEUDOOBJ lpPseudoObj =
  812. ((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj;
  813. HRESULT hrErr;
  814. SCODE sc;
  815. OLEDBG_BEGIN2("PseudoObj_OleObj_EnumAdvise\r\n");
  816. /* OLE2NOTE: we must make sure to set all out parameters to NULL. */
  817. *lplpenumAdvise = NULL;
  818. if (lpPseudoObj->m_lpOleAdviseHldr == NULL) {
  819. sc = E_FAIL;
  820. goto error;
  821. }
  822. OLEDBG_BEGIN2("IOleAdviseHolder::EnumAdvise called\r\n")
  823. hrErr = lpPseudoObj->m_lpOleAdviseHldr->lpVtbl->EnumAdvise(
  824. lpPseudoObj->m_lpOleAdviseHldr,
  825. lplpenumAdvise
  826. );
  827. OLEDBG_END2
  828. OLEDBG_END2
  829. return hrErr;
  830. error:
  831. OLEDBG_END2
  832. return ResultFromScode(sc);
  833. }
  834. STDMETHODIMP PseudoObj_OleObj_GetMiscStatus(
  835. LPOLEOBJECT lpThis,
  836. DWORD dwAspect,
  837. DWORD FAR* lpdwStatus
  838. )
  839. {
  840. LPPSEUDOOBJ lpPseudoObj =
  841. ((struct CPseudoObjOleObjectImpl FAR*)lpThis)->lpPseudoObj;
  842. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpPseudoObj->m_lpDoc;
  843. OleDbgOut2("PseudoObj_OleObj_GetMiscStatus\r\n");
  844. /* Get our default MiscStatus for the given Aspect. this
  845. ** information is registered in the RegDB. We query the RegDB
  846. ** here to guarantee that the value returned from this method
  847. ** agrees with the values in RegDB. in this way we only have to
  848. ** maintain the info in one place (in the RegDB). Alternatively
  849. ** we could have the values hard coded here.
  850. **
  851. ** OLE2NOTE: A pseudo object may NOT return OLE_S_USEREG; they must
  852. ** call the
  853. ** OleReg* API or provide their own implementation. Because this
  854. ** pseudo object does NOT implement IPersist, simply a low-level
  855. ** remoting handler (ProxyManager) object as opposed to a
  856. ** DefHandler object is used as the handler for the pseudo
  857. ** object in a clients process space. The ProxyManager does NOT
  858. ** handle the OLE_S_USEREG return values.
  859. */
  860. OleRegGetMiscStatus((REFCLSID)&CLSID_APP, dwAspect, lpdwStatus);
  861. /* OLE2NOTE: check if the pseudo object is compatible to be
  862. ** linked by an OLE 1.0 container. it is compatible if
  863. ** either the pseudo object is an untitled document or a
  864. ** file-based document. if the pseudo object is part of
  865. ** an embedded object, then it is NOT compatible to be
  866. ** linked by an OLE 1.0 container. if it is compatible then
  867. ** we should include OLEMISC_CANLINKBYOLE1 as part of the
  868. ** dwStatus flags.
  869. */
  870. if (lpOutlineDoc->m_docInitType == DOCTYPE_NEW ||
  871. lpOutlineDoc->m_docInitType == DOCTYPE_FROMFILE)
  872. *lpdwStatus |= OLEMISC_CANLINKBYOLE1;
  873. return NOERROR;
  874. }
  875. STDMETHODIMP PseudoObj_OleObj_SetColorScheme(
  876. LPOLEOBJECT lpThis,
  877. LPLOGPALETTE lpLogpal
  878. )
  879. {
  880. OleDbgOut2("PseudoObj_OleObj_SetColorScheme\r\n");
  881. // REVIEW: NOT YET IMPLEMENTED
  882. return ResultFromScode(E_NOTIMPL);
  883. }
  884. /*************************************************************************
  885. ** PseudoObj::IDataObject interface implementation
  886. *************************************************************************/
  887. STDMETHODIMP PseudoObj_DataObj_QueryInterface (
  888. LPDATAOBJECT lpThis,
  889. REFIID riid,
  890. LPVOID FAR* lplpvObj
  891. )
  892. {
  893. LPPSEUDOOBJ lpPseudoObj =
  894. ((struct CPseudoObjDataObjectImpl FAR*)lpThis)->lpPseudoObj;
  895. return PseudoObj_QueryInterface(lpPseudoObj, riid, lplpvObj);
  896. }
  897. STDMETHODIMP_(ULONG) PseudoObj_DataObj_AddRef(LPDATAOBJECT lpThis)
  898. {
  899. LPPSEUDOOBJ lpPseudoObj =
  900. ((struct CPseudoObjDataObjectImpl FAR*)lpThis)->lpPseudoObj;
  901. OleDbgAddRefMethod(lpThis, "IDataObject");
  902. return PseudoObj_AddRef((LPPSEUDOOBJ)lpPseudoObj);
  903. }
  904. STDMETHODIMP_(ULONG) PseudoObj_DataObj_Release (LPDATAOBJECT lpThis)
  905. {
  906. LPPSEUDOOBJ lpPseudoObj =
  907. ((struct CPseudoObjDataObjectImpl FAR*)lpThis)->lpPseudoObj;
  908. OleDbgReleaseMethod(lpThis, "IDataObject");
  909. return PseudoObj_Release((LPPSEUDOOBJ)lpPseudoObj);
  910. }
  911. STDMETHODIMP PseudoObj_DataObj_GetData (
  912. LPDATAOBJECT lpThis,
  913. LPFORMATETC lpformatetc,
  914. LPSTGMEDIUM lpMedium
  915. )
  916. {
  917. LPPSEUDOOBJ lpPseudoObj =
  918. ((struct CPseudoObjDataObjectImpl FAR*)lpThis)->lpPseudoObj;
  919. LPSERVERDOC lpServerDoc = lpPseudoObj->m_lpDoc;
  920. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc;
  921. LPSERVERAPP lpServerApp = (LPSERVERAPP)g_lpApp;
  922. LPOLEAPP lpOleApp = (LPOLEAPP)lpServerApp;
  923. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpServerApp;
  924. LINERANGE lrSel;
  925. SCODE sc = S_OK;
  926. OLEDBG_BEGIN2("PseudoObj_DataObj_GetData\r\n")
  927. PseudoObj_GetSel(lpPseudoObj, &lrSel);
  928. /* OLE2NOTE: we must make sure to set all out parameters to NULL. */
  929. lpMedium->tymed = TYMED_NULL;
  930. lpMedium->pUnkForRelease = NULL; // we transfer ownership to caller
  931. lpMedium->hGlobal = NULL;
  932. if (lpformatetc->cfFormat == lpOutlineApp->m_cfOutline) {
  933. // Verify caller asked for correct medium
  934. if (!(lpformatetc->tymed & TYMED_HGLOBAL)) {
  935. sc = DATA_E_FORMATETC;
  936. goto error;
  937. }
  938. lpMedium->hGlobal = OutlineDoc_GetOutlineData (lpOutlineDoc,&lrSel);
  939. if (! lpMedium->hGlobal) return ResultFromScode(E_OUTOFMEMORY);
  940. lpMedium->tymed = TYMED_HGLOBAL;
  941. OleDbgOut3("PseudoObj_DataObj_GetData: rendered CF_OUTLINE\r\n");
  942. } else if(lpformatetc->cfFormat == CF_METAFILEPICT &&
  943. (lpformatetc->dwAspect & DVASPECT_CONTENT) ) {
  944. // Verify caller asked for correct medium
  945. if (!(lpformatetc->tymed & TYMED_MFPICT)) {
  946. sc = DATA_E_FORMATETC;
  947. goto error;
  948. }
  949. lpMedium->hGlobal=ServerDoc_GetMetafilePictData(lpServerDoc,&lrSel);
  950. if (! lpMedium->hGlobal) {
  951. sc = E_OUTOFMEMORY;
  952. goto error;
  953. }
  954. lpMedium->tymed = TYMED_MFPICT;
  955. OleDbgOut3("PseudoObj_DataObj_GetData: rendered CF_METAFILEPICT\r\n");
  956. } else if (lpformatetc->cfFormat == CF_METAFILEPICT &&
  957. (lpformatetc->dwAspect & DVASPECT_ICON) ) {
  958. CLSID clsid;
  959. // Verify caller asked for correct medium
  960. if (!(lpformatetc->tymed & TYMED_MFPICT)) {
  961. sc = DATA_E_FORMATETC;
  962. goto error;
  963. }
  964. /* OLE2NOTE: we should return the default icon for our class.
  965. ** we must be carefull to use the correct CLSID here.
  966. ** if we are currently preforming a "TreatAs (aka. ActivateAs)"
  967. ** operation then we need to use the class of the object
  968. ** written in the storage of the object. otherwise we would
  969. ** use our own class id.
  970. */
  971. if (ServerDoc_GetClassID(lpServerDoc, (LPCLSID)&clsid) != NOERROR) {
  972. sc = DATA_E_FORMATETC;
  973. goto error;
  974. }
  975. lpMedium->hGlobal=GetIconOfClass(
  976. g_lpApp->m_hInst,(REFCLSID)&clsid, NULL, FALSE);
  977. if (! lpMedium->hGlobal) {
  978. sc = E_OUTOFMEMORY;
  979. goto error;
  980. }
  981. lpMedium->tymed = TYMED_MFPICT;
  982. OleDbgOut3("PseudoObj_DataObj_GetData: rendered CF_METAFILEPICT (icon)\r\n");
  983. return NOERROR;
  984. } else if (lpformatetc->cfFormat == CF_TEXT) {
  985. // Verify caller asked for correct medium
  986. if (!(lpformatetc->tymed & TYMED_HGLOBAL)) {
  987. sc = DATA_E_FORMATETC;
  988. goto error;
  989. }
  990. lpMedium->hGlobal = OutlineDoc_GetTextData (lpOutlineDoc, &lrSel);
  991. if (! lpMedium->hGlobal) {
  992. sc = E_OUTOFMEMORY;
  993. goto error;
  994. }
  995. lpMedium->tymed = TYMED_HGLOBAL;
  996. OleDbgOut3("PseudoObj_DataObj_GetData: rendered CF_TEXT\r\n");
  997. } else {
  998. sc = DATA_E_FORMATETC;
  999. goto error;
  1000. }
  1001. OLEDBG_END2
  1002. return NOERROR;
  1003. error:
  1004. OLEDBG_END2
  1005. return ResultFromScode(sc);
  1006. }
  1007. STDMETHODIMP PseudoObj_DataObj_GetDataHere (
  1008. LPDATAOBJECT lpThis,
  1009. LPFORMATETC lpformatetc,
  1010. LPSTGMEDIUM lpMedium
  1011. )
  1012. {
  1013. LPPSEUDOOBJ lpPseudoObj =
  1014. ((struct CPseudoObjDataObjectImpl FAR*)lpThis)->lpPseudoObj;
  1015. LPSERVERDOC lpServerDoc = lpPseudoObj->m_lpDoc;
  1016. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc;
  1017. LPSERVERAPP lpServerApp = (LPSERVERAPP)g_lpApp;
  1018. LPOLEAPP lpOleApp = (LPOLEAPP)lpServerApp;
  1019. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpServerApp;
  1020. OleDbgOut("PseudoObj_DataObj_GetDataHere\r\n");
  1021. /* Caller is requesting data to be returned in Caller allocated
  1022. ** medium, but we do NOT support this. we only support
  1023. ** global memory blocks that WE allocate for the caller.
  1024. */
  1025. return ResultFromScode(DATA_E_FORMATETC);
  1026. }
  1027. STDMETHODIMP PseudoObj_DataObj_QueryGetData (
  1028. LPDATAOBJECT lpThis,
  1029. LPFORMATETC lpformatetc
  1030. )
  1031. {
  1032. LPPSEUDOOBJ lpPseudoObj =
  1033. ((struct CPseudoObjDataObjectImpl FAR*)lpThis)->lpPseudoObj;
  1034. LPSERVERDOC lpServerDoc = lpPseudoObj->m_lpDoc;
  1035. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc;
  1036. LPSERVERAPP lpServerApp = (LPSERVERAPP)g_lpApp;
  1037. LPOLEAPP lpOleApp = (LPOLEAPP)lpServerApp;
  1038. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpServerApp;
  1039. OleDbgOut2("PseudoObj_DataObj_QueryGetData\r\n");
  1040. /* Caller is querying if we support certain format but does not
  1041. ** want any data actually returned.
  1042. */
  1043. if (lpformatetc->cfFormat == CF_METAFILEPICT &&
  1044. (lpformatetc->dwAspect & (DVASPECT_CONTENT | DVASPECT_ICON)) ) {
  1045. return OleStdQueryFormatMedium(lpformatetc, TYMED_MFPICT);
  1046. } else if (lpformatetc->cfFormat == (lpOutlineApp)->m_cfOutline ||
  1047. lpformatetc->cfFormat == CF_TEXT) {
  1048. return OleStdQueryFormatMedium(lpformatetc, TYMED_HGLOBAL);
  1049. }
  1050. return ResultFromScode(DATA_E_FORMATETC);
  1051. }
  1052. STDMETHODIMP PseudoObj_DataObj_GetCanonicalFormatEtc(
  1053. LPDATAOBJECT lpThis,
  1054. LPFORMATETC lpformatetc,
  1055. LPFORMATETC lpformatetcOut
  1056. )
  1057. {
  1058. HRESULT hrErr;
  1059. OleDbgOut2("PseudoObj_DataObj_GetCanonicalFormatEtc\r\n");
  1060. if (!lpformatetcOut)
  1061. return ResultFromScode(E_INVALIDARG);
  1062. /* OLE2NOTE: we must make sure to set all out parameters to NULL. */
  1063. lpformatetcOut->ptd = NULL;
  1064. if (!lpformatetc)
  1065. return ResultFromScode(E_INVALIDARG);
  1066. // OLE2NOTE: we must validate that the format requested is supported
  1067. if ((hrErr=lpThis->lpVtbl->QueryGetData(lpThis,lpformatetc)) != NOERROR)
  1068. return hrErr;
  1069. /* OLE2NOTE: an app that is insensitive to target device (as the
  1070. ** Outline Sample is) should fill in the lpformatOut parameter
  1071. ** but NULL out the "ptd" field; it should return NOERROR if the
  1072. ** input formatetc->ptd what non-NULL. this tells the caller
  1073. ** that it is NOT necessary to maintain a separate screen
  1074. ** rendering and printer rendering. if should return
  1075. ** DATA_S_SAMEFORMATETC if the input and output formatetc's are
  1076. ** identical.
  1077. */
  1078. *lpformatetcOut = *lpformatetc;
  1079. if (lpformatetc->ptd == NULL)
  1080. return ResultFromScode(DATA_S_SAMEFORMATETC);
  1081. else {
  1082. lpformatetcOut->ptd = NULL;
  1083. return NOERROR;
  1084. }
  1085. }
  1086. STDMETHODIMP PseudoObj_DataObj_SetData (
  1087. LPDATAOBJECT lpThis,
  1088. LPFORMATETC lpformatetc,
  1089. LPSTGMEDIUM lpmedium,
  1090. BOOL fRelease
  1091. )
  1092. {
  1093. LPPSEUDOOBJ lpPseudoObj =
  1094. ((struct CPseudoObjDataObjectImpl FAR*)lpThis)->lpPseudoObj;
  1095. LPSERVERDOC lpServerDoc = lpPseudoObj->m_lpDoc;
  1096. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc;
  1097. LPSERVERAPP lpServerApp = (LPSERVERAPP)g_lpApp;
  1098. OleDbgOut2("PseudoObj_DataObj_SetData\r\n");
  1099. // REVIEW: NOT-YET-IMPLEMENTED
  1100. return ResultFromScode(E_NOTIMPL);
  1101. }
  1102. STDMETHODIMP PseudoObj_DataObj_EnumFormatEtc(
  1103. LPDATAOBJECT lpThis,
  1104. DWORD dwDirection,
  1105. LPENUMFORMATETC FAR* lplpenumFormatEtc
  1106. )
  1107. {
  1108. SCODE sc;
  1109. OleDbgOut2("PseudoObj_DataObj_EnumFormatEtc\r\n");
  1110. /* OLE2NOTE: a pseudo object only needs to enumerate the static list
  1111. ** of formats that are registered for our app in the
  1112. ** registration database. it is NOT
  1113. ** required that a pseudo object (ie. non-DataTransferDoc)
  1114. ** enumerate the OLE formats: CF_LINKSOURCE, CF_EMBEDSOURCE, or
  1115. ** CF_EMBEDDEDOBJECT. we do NOT use pseudo objects for data
  1116. ** transfers.
  1117. **
  1118. ** A pseudo object may NOT return OLE_S_USEREG; they must call the
  1119. ** OleReg* API or provide their own implementation. Because this
  1120. ** pseudo object does NOT implement IPersist, simply a low-level
  1121. ** remoting handler (ProxyManager) object as opposed to a
  1122. ** DefHandler object is used as the handler for the pseudo
  1123. ** object in a clients process space. The ProxyManager does NOT
  1124. ** handle the OLE_S_USEREG return values.
  1125. */
  1126. if (dwDirection == DATADIR_GET)
  1127. return OleRegEnumFormatEtc(
  1128. (REFCLSID)&CLSID_APP, dwDirection, lplpenumFormatEtc);
  1129. else if (dwDirection == DATADIR_SET)
  1130. sc = E_NOTIMPL;
  1131. else
  1132. sc = E_INVALIDARG;
  1133. return ResultFromScode(sc);
  1134. }
  1135. STDMETHODIMP PseudoObj_DataObj_DAdvise(
  1136. LPDATAOBJECT lpThis,
  1137. FORMATETC FAR* lpFormatetc,
  1138. DWORD advf,
  1139. LPADVISESINK lpAdvSink,
  1140. DWORD FAR* lpdwConnection
  1141. )
  1142. {
  1143. LPPSEUDOOBJ lpPseudoObj =
  1144. ((struct CPseudoObjDataObjectImpl FAR*)lpThis)->lpPseudoObj;
  1145. HRESULT hrErr;
  1146. SCODE sc;
  1147. OLEDBG_BEGIN2("PseudoObj_DataObj_DAdvise\r\n")
  1148. /* OLE2NOTE: we must make sure to set all out parameters to NULL. */
  1149. *lpdwConnection = 0;
  1150. /* OLE2NOTE: we should validate if the caller is setting up an
  1151. ** Advise for a data type that we support. we must
  1152. ** explicitly allow an advise for the "wildcard" advise.
  1153. */
  1154. if ( !( lpFormatetc->cfFormat == 0 &&
  1155. lpFormatetc->ptd == NULL &&
  1156. lpFormatetc->dwAspect == -1L &&
  1157. lpFormatetc->lindex == -1L &&
  1158. lpFormatetc->tymed == -1L) &&
  1159. (hrErr = PseudoObj_DataObj_QueryGetData(lpThis, lpFormatetc))
  1160. != NOERROR) {
  1161. sc = GetScode(hrErr);
  1162. goto error;
  1163. }
  1164. if (lpPseudoObj->m_lpDataAdviseHldr == NULL &&
  1165. CreateDataAdviseHolder(&lpPseudoObj->m_lpDataAdviseHldr) != NOERROR) {
  1166. sc = E_OUTOFMEMORY;
  1167. goto error;
  1168. }
  1169. OLEDBG_BEGIN2("IOleAdviseHolder::Advise called\r\n")
  1170. hrErr = lpPseudoObj->m_lpDataAdviseHldr->lpVtbl->Advise(
  1171. lpPseudoObj->m_lpDataAdviseHldr,
  1172. (LPDATAOBJECT)&lpPseudoObj->m_DataObject,
  1173. lpFormatetc,
  1174. advf,
  1175. lpAdvSink,
  1176. lpdwConnection
  1177. );
  1178. OLEDBG_END2
  1179. OLEDBG_END2
  1180. return hrErr;
  1181. error:
  1182. OLEDBG_END2
  1183. return ResultFromScode(sc);
  1184. }
  1185. STDMETHODIMP PseudoObj_DataObj_DUnadvise(LPDATAOBJECT lpThis, DWORD dwConnection)
  1186. {
  1187. LPPSEUDOOBJ lpPseudoObj =
  1188. ((struct CPseudoObjDataObjectImpl FAR*)lpThis)->lpPseudoObj;
  1189. HRESULT hrErr;
  1190. SCODE sc;
  1191. OLEDBG_BEGIN2("PseudoObj_DataObj_Unadvise\r\n");
  1192. // no one registered
  1193. if (lpPseudoObj->m_lpDataAdviseHldr == NULL) {
  1194. sc = E_FAIL;
  1195. goto error;
  1196. }
  1197. OLEDBG_BEGIN2("IOleAdviseHolder::DUnadvise called\r\n")
  1198. hrErr = lpPseudoObj->m_lpDataAdviseHldr->lpVtbl->Unadvise(
  1199. lpPseudoObj->m_lpDataAdviseHldr,
  1200. dwConnection
  1201. );
  1202. OLEDBG_END2
  1203. OLEDBG_END2
  1204. return hrErr;
  1205. error:
  1206. OLEDBG_END2
  1207. return ResultFromScode(sc);
  1208. }
  1209. STDMETHODIMP PseudoObj_DataObj_EnumAdvise(
  1210. LPDATAOBJECT lpThis,
  1211. LPENUMSTATDATA FAR* lplpenumAdvise
  1212. )
  1213. {
  1214. LPPSEUDOOBJ lpPseudoObj =
  1215. ((struct CPseudoObjDataObjectImpl FAR*)lpThis)->lpPseudoObj;
  1216. HRESULT hrErr;
  1217. SCODE sc;
  1218. OLEDBG_BEGIN2("PseudoObj_DataObj_EnumAdvise\r\n");
  1219. /* OLE2NOTE: we must make sure to set all out parameters to NULL. */
  1220. *lplpenumAdvise = NULL;
  1221. if (lpPseudoObj->m_lpDataAdviseHldr == NULL) {
  1222. sc = E_FAIL;
  1223. goto error;
  1224. }
  1225. OLEDBG_BEGIN2("IOleAdviseHolder::EnumAdvise called\r\n")
  1226. hrErr = lpPseudoObj->m_lpDataAdviseHldr->lpVtbl->EnumAdvise(
  1227. lpPseudoObj->m_lpDataAdviseHldr,
  1228. lplpenumAdvise
  1229. );
  1230. OLEDBG_END2
  1231. OLEDBG_END2
  1232. return hrErr;
  1233. error:
  1234. OLEDBG_END2
  1235. return ResultFromScode(sc);
  1236. }