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.

1179 lines
38 KiB

  1. /*************************************************************************
  2. **
  3. ** OLE 2 Server Sample Code
  4. **
  5. ** oledoc.c
  6. **
  7. ** This file contains general OleDoc methods and related support
  8. ** functions. OleDoc implementation is used by both the Container
  9. ** versions and the Server (Object) versions of the Outline Sample.
  10. **
  11. ** This file includes general support for the following:
  12. ** 1. show/hide doc window
  13. ** 2. QueryInterface, AddRef, Release
  14. ** 3. document locking (calls CoLockObjectExternal)
  15. ** 4. document shutdown (Close, Destroy)
  16. ** 5. clipboard support
  17. **
  18. ** OleDoc Object
  19. ** exposed interfaces:
  20. ** IUnknown
  21. ** IPersistFile
  22. ** IOleItemContainer
  23. ** IDataObject
  24. **
  25. ** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved
  26. **
  27. *************************************************************************/
  28. #include "outline.h"
  29. OLEDBGDATA
  30. extern LPOUTLINEAPP g_lpApp;
  31. extern IUnknownVtbl g_OleDoc_UnknownVtbl;
  32. extern IPersistFileVtbl g_OleDoc_PersistFileVtbl;
  33. extern IOleItemContainerVtbl g_OleDoc_OleItemContainerVtbl;
  34. extern IExternalConnectionVtbl g_OleDoc_ExternalConnectionVtbl;
  35. extern IDataObjectVtbl g_OleDoc_DataObjectVtbl;
  36. #if defined( USE_DRAGDROP )
  37. extern IDropTargetVtbl g_OleDoc_DropTargetVtbl;
  38. extern IDropSourceVtbl g_OleDoc_DropSourceVtbl;
  39. #endif // USE_DRAGDROP
  40. #if defined( INPLACE_CNTR )
  41. extern BOOL g_fInsideOutContainer;
  42. #endif
  43. /* OleDoc_Init
  44. * -----------
  45. *
  46. * Initialize the fields of a new OleDoc object. The object is initially
  47. * not associated with a file or an (Untitled) document. This function sets
  48. * the docInitType to DOCTYPE_UNKNOWN. After calling this function the
  49. * caller should call:
  50. * 1.) Doc_InitNewFile to set the OleDoc to (Untitled)
  51. * 2.) Doc_LoadFromFile to associate the OleDoc with a file.
  52. * This function creates a new window for the document.
  53. *
  54. * NOTE: the window is initially created with a NIL size. it must be
  55. * sized and positioned by the caller. also the document is initially
  56. * created invisible. the caller must call OutlineDoc_ShowWindow
  57. * after sizing it to make the document window visible.
  58. */
  59. BOOL OleDoc_Init(LPOLEDOC lpOleDoc, BOOL fDataTransferDoc)
  60. {
  61. LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
  62. LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList;
  63. lpOleDoc->m_cRef = 0;
  64. lpOleDoc->m_dwStrongExtConn = 0;
  65. #if defined( _DEBUG )
  66. lpOleDoc->m_cCntrLock = 0;
  67. #endif
  68. lpOleDoc->m_lpStg = NULL;
  69. lpOleDoc->m_lpLLStm = NULL;
  70. lpOleDoc->m_lpNTStm = NULL;
  71. lpOleDoc->m_dwRegROT = 0;
  72. lpOleDoc->m_lpFileMoniker = NULL;
  73. lpOleDoc->m_fLinkSourceAvail = FALSE;
  74. lpOleDoc->m_lpSrcDocOfCopy = NULL;
  75. lpOleDoc->m_fObjIsClosing = FALSE;
  76. lpOleDoc->m_fObjIsDestroying = FALSE;
  77. lpOleDoc->m_fUpdateEditMenu = FALSE;
  78. #if defined( USE_DRAGDROP )
  79. lpOleDoc->m_dwTimeEnterScrollArea = 0L;
  80. lpOleDoc->m_dwNextScrollTime = 0L;
  81. lpOleDoc->m_dwLastScrollDir = SCROLLDIR_NULL;
  82. lpOleDoc->m_fRegDragDrop = FALSE;
  83. lpOleDoc->m_fLocalDrag = FALSE;
  84. lpOleDoc->m_fCanDropCopy = FALSE;
  85. lpOleDoc->m_fCanDropLink = FALSE;
  86. lpOleDoc->m_fLocalDrop = FALSE;
  87. lpOleDoc->m_fDragLeave = FALSE;
  88. lpOleDoc->m_fPendingDrag = FALSE;
  89. #endif
  90. #if defined( INPLACE_SVR ) || defined( INPLACE_CNTR )
  91. lpOleDoc->m_fCSHelpMode = FALSE; // Shift-F1 context
  92. // sensitive help mode
  93. #endif
  94. INIT_INTERFACEIMPL(
  95. &lpOleDoc->m_Unknown,
  96. &g_OleDoc_UnknownVtbl,
  97. lpOleDoc
  98. );
  99. INIT_INTERFACEIMPL(
  100. &lpOleDoc->m_PersistFile,
  101. &g_OleDoc_PersistFileVtbl,
  102. lpOleDoc
  103. );
  104. INIT_INTERFACEIMPL(
  105. &lpOleDoc->m_OleItemContainer,
  106. &g_OleDoc_OleItemContainerVtbl,
  107. lpOleDoc
  108. );
  109. INIT_INTERFACEIMPL(
  110. &lpOleDoc->m_ExternalConnection,
  111. &g_OleDoc_ExternalConnectionVtbl,
  112. lpOleDoc
  113. );
  114. INIT_INTERFACEIMPL(
  115. &lpOleDoc->m_DataObject,
  116. &g_OleDoc_DataObjectVtbl,
  117. lpOleDoc
  118. );
  119. #if defined( USE_DRAGDROP )
  120. INIT_INTERFACEIMPL(
  121. &lpOleDoc->m_DropSource,
  122. &g_OleDoc_DropSourceVtbl,
  123. lpOleDoc
  124. );
  125. INIT_INTERFACEIMPL(
  126. &lpOleDoc->m_DropTarget,
  127. &g_OleDoc_DropTargetVtbl,
  128. lpOleDoc
  129. );
  130. #endif // USE_DRAGDROP
  131. /*
  132. ** OLE2NOTE: each user level document addref's the app object in
  133. ** order to guarentee that the app does not shut down while the
  134. ** doc is still open.
  135. */
  136. // OLE2NOTE: data transfer documents should not hold the app alive
  137. if (! fDataTransferDoc)
  138. OleApp_DocLockApp(lpOleApp);
  139. #if defined( OLE_SERVER )
  140. /* OLE2NOTE: perform initialization specific for an OLE server */
  141. if (! ServerDoc_Init((LPSERVERDOC)lpOleDoc, fDataTransferDoc))
  142. return FALSE;
  143. #endif
  144. #if defined( OLE_CNTR )
  145. /* OLE2NOTE: perform initialization specific for an OLE container */
  146. if (! ContainerDoc_Init((LPCONTAINERDOC)lpOleDoc, fDataTransferDoc))
  147. return FALSE;
  148. #endif
  149. return TRUE;
  150. }
  151. /* OleDoc_InitNewFile
  152. * ------------------
  153. *
  154. * Initialize the document to be a new (Untitled) document.
  155. * This function sets the docInitType to DOCTYPE_NEW.
  156. *
  157. * OLE2NOTE: if this is a visible user document then generate a unique
  158. * untitled name that we can use to register in the RunningObjectTable.
  159. * We need a unique name so that clients can link to data in this document
  160. * even when the document is in the un-saved (untitled) state. it would be
  161. * ambiguous to register two documents titled "Outline1" in the ROT. we
  162. * thus generate the lowest numbered document that is not already
  163. * registered in the ROT.
  164. */
  165. BOOL OleDoc_InitNewFile(LPOLEDOC lpOleDoc)
  166. {
  167. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
  168. static UINT uUnique = 1;
  169. OleDbgAssert(lpOutlineDoc->m_docInitType == DOCTYPE_UNKNOWN);
  170. #if defined( OLE_CNTR )
  171. {
  172. LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOleDoc;
  173. #if defined( _DEBUG )
  174. OleDbgAssertSz(lpOleDoc->m_lpStg == NULL,
  175. "Setting to untitled with current file open"
  176. );
  177. #endif
  178. /* Create a temp, (delete-on-release) file base storage
  179. ** for the untitled document.
  180. */
  181. lpOleDoc->m_lpStg = OleStdCreateRootStorage(
  182. NULL,
  183. STGM_SHARE_EXCLUSIVE
  184. );
  185. if (! lpOleDoc->m_lpStg) return FALSE;
  186. }
  187. #endif
  188. lpOutlineDoc->m_docInitType = DOCTYPE_NEW;
  189. if (! lpOutlineDoc->m_fDataTransferDoc) {
  190. /* OLE2NOTE: choose a unique name for a Moniker so that
  191. ** potential clients can link to our new, untitled document.
  192. ** if links are established (and currently are connected),
  193. ** then they will be notified that we have been renamed when
  194. ** this document is saved to a file.
  195. */
  196. lpOleDoc->m_fLinkSourceAvail = TRUE;
  197. // REVIEW: should load UNTITLED string from string resource
  198. OleStdCreateTempFileMoniker(
  199. UNTITLED,
  200. (UINT FAR*)&uUnique,
  201. lpOutlineDoc->m_szFileName,
  202. &lpOleDoc->m_lpFileMoniker
  203. );
  204. OLEDBG_BEGIN3("OleStdRegisterAsRunning called\r\n")
  205. OleStdRegisterAsRunning(
  206. (LPUNKNOWN)&lpOleDoc->m_PersistFile,
  207. (LPMONIKER)lpOleDoc->m_lpFileMoniker,
  208. &lpOleDoc->m_dwRegROT
  209. );
  210. OLEDBG_END3
  211. lpOutlineDoc->m_lpszDocTitle = lpOutlineDoc->m_szFileName;
  212. OutlineDoc_SetTitle(lpOutlineDoc, FALSE /*fMakeUpperCase*/);
  213. } else {
  214. lstrcpy(lpOutlineDoc->m_szFileName, UNTITLED);
  215. lpOutlineDoc->m_lpszDocTitle = lpOutlineDoc->m_szFileName;
  216. }
  217. return TRUE;
  218. }
  219. /* OleDoc_ShowWindow
  220. * -----------------
  221. *
  222. * Show the window of the document to the user.
  223. * make sure app window is visible and bring the document to the top.
  224. * if the document is a file-based document or a new untitled
  225. * document, give the user the control over the life-time of the doc.
  226. */
  227. void OleDoc_ShowWindow(LPOLEDOC lpOleDoc)
  228. {
  229. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  230. LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
  231. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
  232. LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList;
  233. #if defined( OLE_SERVER )
  234. LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc;
  235. #endif // OLE_SERVER
  236. OLEDBG_BEGIN3("OleDoc_ShowWindow\r\n")
  237. /* OLE2NOTE: while the document is visible, we do NOT want it to be
  238. ** prematurely destroyed when a linking client disconnects. thus
  239. ** we must inform OLE to hold an external lock on our document.
  240. ** this arranges that OLE holds at least 1 reference to our
  241. ** document that will NOT be released until we release this
  242. ** external lock. later, when the document window is hidden, we
  243. ** will release this external lock.
  244. */
  245. if (! IsWindowVisible(lpOutlineDoc->m_hWndDoc))
  246. OleDoc_Lock(lpOleDoc, TRUE /* fLock */, 0 /* not applicable */);
  247. #if defined( USE_DRAGDROP )
  248. /* OLE2NOTE: since our window is now being made visible, we will
  249. ** register our window as a potential drop target. when the
  250. ** window is hidden there is no reason to be registered as a
  251. ** drop target.
  252. */
  253. if (! lpOleDoc->m_fRegDragDrop) {
  254. OLEDBG_BEGIN2("RegisterDragDrop called\r\n")
  255. RegisterDragDrop(
  256. LineList_GetWindow(lpLL),
  257. (LPDROPTARGET)&lpOleDoc->m_DropTarget
  258. );
  259. OLEDBG_END2
  260. lpOleDoc->m_fRegDragDrop = TRUE;
  261. }
  262. #endif // USE_DRAGDROP
  263. #if defined( USE_FRAMETOOLS )
  264. {
  265. /* OLE2NOTE: we need to enable our frame level tools
  266. */
  267. FrameTools_Enable(lpOutlineDoc->m_lpFrameTools, TRUE);
  268. }
  269. #endif // USE_FRAMETOOLS
  270. #if defined( OLE_SERVER )
  271. if (lpOutlineDoc->m_docInitType == DOCTYPE_EMBEDDED &&
  272. lpServerDoc->m_lpOleClientSite != NULL) {
  273. /* OLE2NOTE: we must also ask our container to show itself if
  274. ** it is not already visible and to scroll us into view. we
  275. ** must make sure to call this BEFORE showing our server's
  276. ** window and taking focus. we do not want our container's
  277. ** window to end up on top.
  278. */
  279. OLEDBG_BEGIN2("IOleClientSite::ShowObject called\r\n");
  280. lpServerDoc->m_lpOleClientSite->lpVtbl->ShowObject(
  281. lpServerDoc->m_lpOleClientSite
  282. );
  283. OLEDBG_END2
  284. /* OLE2NOTE: if we are an embedded object and we are not
  285. ** in-place active in our containers window, we must inform our
  286. ** embedding container that our window is opening.
  287. ** the container must now hatch our object.
  288. */
  289. #if defined( INPLACE_SVR )
  290. if (! lpServerDoc->m_fInPlaceActive)
  291. #endif
  292. {
  293. OLEDBG_BEGIN2("IOleClientSite::OnShowWindow(TRUE) called\r\n");
  294. lpServerDoc->m_lpOleClientSite->lpVtbl->OnShowWindow(
  295. lpServerDoc->m_lpOleClientSite,
  296. TRUE
  297. );
  298. OLEDBG_END2
  299. }
  300. /* OLE2NOTE: the life-time of our document is controlled by our
  301. ** client and NOT by the user. we are not an independent
  302. ** file-level object. we simply want to show our window here.
  303. **
  304. ** if we are not in-place active (ie. we are opening
  305. ** our own window), we must make sure our main app window is
  306. ** visible. we do not, however, want to give the user
  307. ** control of the App window; we do not want OleApp_ShowWindow
  308. ** to call OleApp_Lock on behalf of the user.
  309. */
  310. if (! IsWindowVisible(lpOutlineApp->m_hWndApp) ||
  311. IsIconic(lpOutlineApp->m_hWndApp)) {
  312. #if defined( INPLACE_SVR )
  313. if (! ((LPSERVERDOC)lpOleDoc)->m_fInPlaceActive)
  314. #endif
  315. OleApp_ShowWindow(lpOleApp, FALSE /* fGiveUserCtrl */);
  316. SetFocus(lpOutlineDoc->m_hWndDoc);
  317. }
  318. } else
  319. #endif // OLE_SERVER
  320. { // DOCTYPE_NEW || DOCTYPE_FROMFILE
  321. // we must make sure our app window is visible
  322. OleApp_ShowWindow(lpOleApp, TRUE /* fGiveUserCtrl */);
  323. }
  324. // make document window visible and make sure it is not minimized
  325. ShowWindow(lpOutlineDoc->m_hWndDoc, SW_SHOWNORMAL);
  326. SetFocus(lpOutlineDoc->m_hWndDoc);
  327. OLEDBG_END3
  328. }
  329. /* OleDoc_HideWindow
  330. * -----------------
  331. *
  332. * Hide the window of the document from the user.
  333. * take away the control of the document by the user.
  334. */
  335. void OleDoc_HideWindow(LPOLEDOC lpOleDoc, BOOL fShutdown)
  336. {
  337. LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
  338. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
  339. LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList;
  340. if (! IsWindowVisible(lpOutlineDoc->m_hWndDoc))
  341. return; // already visible
  342. OLEDBG_BEGIN3("OleDoc_HideWindow\r\n")
  343. #if defined( USE_DRAGDROP )
  344. // The document's window is being hidden, revoke it as a DropTarget
  345. if (lpOleDoc->m_fRegDragDrop) {
  346. OLEDBG_BEGIN2("RevokeDragDrop called\r\n");
  347. RevokeDragDrop(LineList_GetWindow(lpLL));
  348. OLEDBG_END2
  349. lpOleDoc->m_fRegDragDrop = FALSE ;
  350. }
  351. #endif // USE_DRAGDROP
  352. /* OLE2NOTE: the document is now being hidden, so we must release
  353. ** the external lock made when the document was made visible.
  354. ** if this is a shutdown situation (fShutdown==TRUE), then OLE
  355. ** is instructed to release our document. if this is that last
  356. ** external lock on our document, thus enabling our document to
  357. ** complete its shutdown operation. If This is not a shutdown
  358. ** situation (eg. in-place server hiding its window when
  359. ** UIDeactivating or IOleObject::DoVerb(OLEVERB_HIDE) is called),
  360. ** then OLE is told to NOT immediately release the document.
  361. ** this leaves the document in an unstable state where the next
  362. ** Lock/Unlock sequence will shut the document down (eg. a
  363. ** linking client connecting and disconnecting).
  364. */
  365. if (IsWindowVisible(lpOutlineDoc->m_hWndDoc))
  366. OleDoc_Lock(lpOleDoc, FALSE /* fLock */, fShutdown);
  367. ShowWindow(((LPOUTLINEDOC)lpOleDoc)->m_hWndDoc, SW_HIDE);
  368. #if defined( OLE_SERVER )
  369. {
  370. LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc;
  371. /* OLE2NOTE: if we are an embedded object and we are not
  372. ** in-place active, we must inform our
  373. ** embedding container that our window is hiding (closing
  374. ** from the user's perspective). the container must now
  375. ** un-hatch our object.
  376. */
  377. if (lpServerDoc->m_lpOleClientSite != NULL
  378. #if defined( INPLACE_SVR )
  379. && !lpServerDoc->m_fInPlaceVisible
  380. #endif
  381. ) {
  382. OLEDBG_BEGIN2("IOleClientSite::OnShowWindow(FALSE) called\r\n");
  383. lpServerDoc->m_lpOleClientSite->lpVtbl->OnShowWindow(
  384. lpServerDoc->m_lpOleClientSite,
  385. FALSE
  386. );
  387. OLEDBG_END2
  388. }
  389. }
  390. #endif
  391. /* OLE2NOTE: if there are no more documents visible to the user.
  392. ** and the app itself is not under user control, then
  393. ** it has no reason to stay visible. we thus should hide the
  394. ** app. we can not directly destroy the app, because it may be
  395. ** validly being used programatically by another client
  396. ** application and should remain running. it should simply be
  397. ** hidded from the user.
  398. */
  399. OleApp_HideIfNoReasonToStayVisible(lpOleApp);
  400. OLEDBG_END3
  401. }
  402. /* OleDoc_Lock
  403. ** -----------
  404. ** Lock/Unlock the Doc object. if the last lock is unlocked and
  405. ** fLastUnlockReleases == TRUE, then the Doc object will shut down
  406. ** (ie. it will recieve its final release and its refcnt will go to 0).
  407. */
  408. HRESULT OleDoc_Lock(LPOLEDOC lpOleDoc, BOOL fLock, BOOL fLastUnlockReleases)
  409. {
  410. HRESULT hrErr;
  411. #if defined( _DEBUG )
  412. if (fLock) {
  413. OLEDBG_BEGIN2("CoLockObjectExternal(lpDoc,TRUE) called\r\n")
  414. } else {
  415. if (fLastUnlockReleases)
  416. OLEDBG_BEGIN2("CoLockObjectExternal(lpDoc,FALSE,TRUE) called\r\n")
  417. else
  418. OLEDBG_BEGIN2("CoLockObjectExternal(lpDoc,FALSE,FALSE) called\r\n")
  419. }
  420. #endif // _DEBUG
  421. hrErr = CoLockObjectExternal(
  422. (LPUNKNOWN)&lpOleDoc->m_Unknown, fLock, fLastUnlockReleases);
  423. OLEDBG_END2
  424. return hrErr;
  425. }
  426. /* OleDoc_AddRef
  427. ** -------------
  428. **
  429. ** increment the ref count of the document object.
  430. **
  431. ** Returns the new ref count on the object
  432. */
  433. ULONG OleDoc_AddRef(LPOLEDOC lpOleDoc)
  434. {
  435. ++lpOleDoc->m_cRef;
  436. #if defined( _DEBUG )
  437. OleDbgOutRefCnt4(
  438. "OleDoc_AddRef: cRef++\r\n",
  439. lpOleDoc,
  440. lpOleDoc->m_cRef
  441. );
  442. #endif
  443. return lpOleDoc->m_cRef;
  444. }
  445. /* OleDoc_Release
  446. ** --------------
  447. **
  448. ** decrement the ref count of the document object.
  449. ** if the ref count goes to 0, then the document is destroyed.
  450. **
  451. ** Returns the remaining ref count on the object
  452. */
  453. ULONG OleDoc_Release (LPOLEDOC lpOleDoc)
  454. {
  455. ULONG cRef;
  456. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  457. LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
  458. /*********************************************************************
  459. ** OLE2NOTE: when the obj refcnt == 0, then destroy the object. **
  460. ** otherwise the object is still in use. **
  461. *********************************************************************/
  462. cRef = --lpOleDoc->m_cRef;
  463. #if defined( _DEBUG )
  464. OleDbgAssertSz (lpOleDoc->m_cRef >= 0, "Release called with cRef == 0");
  465. OleDbgOutRefCnt4(
  466. "OleDoc_Release: cRef--\r\n", lpOleDoc, cRef);
  467. #endif
  468. if (cRef == 0)
  469. OutlineDoc_Destroy((LPOUTLINEDOC)lpOleDoc);
  470. return cRef;
  471. }
  472. /* OleDoc_QueryInterface
  473. ** ---------------------
  474. **
  475. ** Retrieve a pointer to an interface on the document object.
  476. **
  477. ** OLE2NOTE: this function will AddRef the ref cnt of the object.
  478. **
  479. ** Returns S_OK if interface is successfully retrieved.
  480. ** E_NOINTERFACE if the interface is not supported
  481. */
  482. HRESULT OleDoc_QueryInterface(
  483. LPOLEDOC lpOleDoc,
  484. REFIID riid,
  485. LPVOID FAR* lplpvObj
  486. )
  487. {
  488. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
  489. SCODE sc = E_NOINTERFACE;
  490. /* OLE2NOTE: we must make sure to set all out ptr parameters to NULL. */
  491. *lplpvObj = NULL;
  492. if (IsEqualIID(riid, &IID_IUnknown)) {
  493. OleDbgOut4("OleDoc_QueryInterface: IUnknown* RETURNED\r\n");
  494. *lplpvObj = (LPVOID) &lpOleDoc->m_Unknown;
  495. OleDoc_AddRef(lpOleDoc);
  496. sc = S_OK;
  497. }
  498. else if(lpOutlineDoc->m_fDataTransferDoc
  499. && IsEqualIID(riid, &IID_IDataObject)) {
  500. OleDbgOut4("OleDoc_QueryInterface: IDataObject* RETURNED\r\n");
  501. *lplpvObj = (LPVOID) &lpOleDoc->m_DataObject;
  502. OleDoc_AddRef(lpOleDoc);
  503. sc = S_OK;
  504. }
  505. /* OLE2NOTE: if this document is a DataTransferDocument used to
  506. ** support a clipboard or drag/drop operation, then it should
  507. ** only expose IUnknown, IDataObject, and IDropSource
  508. ** interfaces. if the document is a normal user document, then
  509. ** we will also continue to consider our other interfaces.
  510. */
  511. if (lpOutlineDoc->m_fDataTransferDoc)
  512. goto done;
  513. if(IsEqualIID(riid,&IID_IPersist) || IsEqualIID(riid,&IID_IPersistFile)) {
  514. OleDbgOut4("OleDoc_QueryInterface: IPersistFile* RETURNED\r\n");
  515. *lplpvObj = (LPVOID) &lpOleDoc->m_PersistFile;
  516. OleDoc_AddRef(lpOleDoc);
  517. sc = S_OK;
  518. }
  519. else if(IsEqualIID(riid, &IID_IOleItemContainer) ||
  520. IsEqualIID(riid, &IID_IOleContainer) ||
  521. IsEqualIID(riid, &IID_IParseDisplayName) ) {
  522. OleDbgOut4("OleDoc_QueryInterface: IOleItemContainer* RETURNED\r\n");
  523. *lplpvObj = (LPVOID) &lpOleDoc->m_OleItemContainer;
  524. OleDoc_AddRef(lpOleDoc);
  525. sc = S_OK;
  526. }
  527. else if(IsEqualIID(riid, &IID_IExternalConnection)) {
  528. OleDbgOut4("OleDoc_QueryInterface: IExternalConnection* RETURNED\r\n");
  529. *lplpvObj = (LPVOID) &lpOleDoc->m_ExternalConnection;
  530. OleDoc_AddRef(lpOleDoc);
  531. sc = S_OK;
  532. }
  533. #if defined( USE_DRAGDROP )
  534. else if(IsEqualIID(riid, &IID_IDropTarget)) {
  535. OleDbgOut4("OleDoc_QueryInterface: IDropTarget* RETURNED\r\n");
  536. *lplpvObj = (LPVOID) &lpOleDoc->m_DropTarget;
  537. OleDoc_AddRef(lpOleDoc);
  538. sc = S_OK;
  539. }
  540. else if(IsEqualIID(riid, &IID_IDropSource)) {
  541. OleDbgOut4("OleDoc_QueryInterface: IDropSource* RETURNED\r\n");
  542. *lplpvObj = (LPVOID) &lpOleDoc->m_DropSource;
  543. OleDoc_AddRef(lpOleDoc);
  544. sc = S_OK;
  545. }
  546. #endif
  547. #if defined( OLE_CNTR )
  548. else if (IsEqualIID(riid, &IID_IOleUILinkContainer)) {
  549. OleDbgOut4("OleDoc_QueryInterface: IOleUILinkContainer* RETURNED\r\n");
  550. *lplpvObj=(LPVOID)&((LPCONTAINERDOC)lpOleDoc)->m_OleUILinkContainer;
  551. OleDoc_AddRef(lpOleDoc);
  552. sc = S_OK;
  553. }
  554. #endif
  555. #if defined( OLE_SERVER )
  556. /* OLE2NOTE: if OLE server version, than also offer the server
  557. ** specific interfaces: IOleObject and IPersistStorage.
  558. */
  559. else if (IsEqualIID(riid, &IID_IOleObject)) {
  560. OleDbgOut4("OleDoc_QueryInterface: IOleObject* RETURNED\r\n");
  561. *lplpvObj = (LPVOID) &((LPSERVERDOC)lpOleDoc)->m_OleObject;
  562. OleDoc_AddRef(lpOleDoc);
  563. sc = S_OK;
  564. }
  565. else if(IsEqualIID(riid, &IID_IPersistStorage)) {
  566. OleDbgOut4("OleDoc_QueryInterface: IPersistStorage* RETURNED\r\n");
  567. *lplpvObj = (LPVOID) &((LPSERVERDOC)lpOleDoc)->m_PersistStorage;
  568. OleDoc_AddRef(lpOleDoc);
  569. sc = S_OK;
  570. }
  571. else if(IsEqualIID(riid, &IID_IDataObject)) {
  572. OleDbgOut4("OleDoc_QueryInterface: IDataObject* RETURNED\r\n");
  573. *lplpvObj = (LPVOID) &lpOleDoc->m_DataObject;
  574. OleDoc_AddRef(lpOleDoc);
  575. sc = S_OK;
  576. }
  577. #if defined( SVR_TREATAS )
  578. else if(IsEqualIID(riid, &IID_IStdMarshalInfo)) {
  579. OleDbgOut4("OleDoc_QueryInterface: IStdMarshalInfo* RETURNED\r\n");
  580. *lplpvObj = (LPVOID) &((LPSERVERDOC)lpOleDoc)->m_StdMarshalInfo;
  581. OleDoc_AddRef(lpOleDoc);
  582. sc = S_OK;
  583. }
  584. #endif // SVR_TREATAS
  585. #if defined( INPLACE_SVR )
  586. else if (IsEqualIID(riid, &IID_IOleWindow) ||
  587. IsEqualIID(riid, &IID_IOleInPlaceObject)) {
  588. OleDbgOut4("OleDoc_QueryInterface: IOleInPlaceObject* RETURNED\r\n");
  589. *lplpvObj = (LPVOID) &((LPSERVERDOC)lpOleDoc)->m_OleInPlaceObject;
  590. OleDoc_AddRef(lpOleDoc);
  591. sc = S_OK;
  592. }
  593. #endif // INPLACE_SVR
  594. #endif // OLE_SERVER
  595. done:
  596. OleDbgQueryInterfaceMethod(*lplpvObj);
  597. return ResultFromScode(sc);
  598. }
  599. /* OleDoc_Close
  600. * ------------
  601. *
  602. * Close the document.
  603. * This functions performs the actions that are in common to all
  604. * document types which derive from OleDoc (eg. ContainerDoc and
  605. * ServerDoc) which are required to close a document.
  606. *
  607. * Returns:
  608. * FALSE -- user canceled the closing of the doc.
  609. * TRUE -- the doc was successfully closed
  610. */
  611. BOOL OleDoc_Close(LPOLEDOC lpOleDoc, DWORD dwSaveOption)
  612. {
  613. LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
  614. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  615. LPOLEDOC lpClipboardDoc;
  616. LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList;
  617. BOOL fAbortIfSaveCanceled = (dwSaveOption == OLECLOSE_PROMPTSAVE);
  618. if (! lpOleDoc)
  619. return TRUE; // active doc's are already destroyed
  620. if (lpOleDoc->m_fObjIsClosing)
  621. return TRUE; // Closing is already in progress
  622. OLEDBG_BEGIN3("OleDoc_Close\r\n")
  623. if (! OutlineDoc_CheckSaveChanges((LPOUTLINEDOC)lpOleDoc,&dwSaveOption)
  624. && fAbortIfSaveCanceled) {
  625. OLEDBG_END3
  626. return FALSE; // cancel closing the doc
  627. }
  628. lpOleDoc->m_fObjIsClosing = TRUE; // guard against recursive call
  629. /* OLE2NOTE: in order to have a stable app and doc during the
  630. ** process of closing, we intially AddRef the App and Doc ref
  631. ** cnts and later Release them. These initial AddRefs are
  632. ** artificial; they simply guarantee that these objects do not
  633. ** get destroyed until the end of this routine.
  634. */
  635. OleApp_AddRef(lpOleApp);
  636. OleDoc_AddRef(lpOleDoc);
  637. #if defined( OLE_CNTR )
  638. {
  639. LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOleDoc;
  640. /* OLE2NOTE: force all OLE objects to close. this forces all
  641. ** OLE object to transition from running to loaded. we can
  642. ** NOT exit if any embeddings are still running.
  643. ** if an object can't be closed and this close operation was
  644. ** started by the user, then we will abort closing our document.
  645. */
  646. if (! ContainerDoc_CloseAllOleObjects(lpContainerDoc, OLECLOSE_NOSAVE)
  647. && fAbortIfSaveCanceled) {
  648. OleDoc_Release(lpOleDoc); // release artificial AddRef above
  649. OleApp_Release(lpOleApp); // release artificial AddRef above
  650. lpOleDoc->m_fObjIsClosing = FALSE; // clear recursion guard
  651. OLEDBG_END3
  652. return FALSE; // Closing is aborted
  653. }
  654. }
  655. #endif
  656. #if defined( INPLACE_SVR )
  657. /* OLE2NOTE: if the server is currently in-place active we must
  658. ** deactivate it now before closing
  659. */
  660. ServerDoc_DoInPlaceDeactivate((LPSERVERDOC)lpOleDoc);
  661. #endif
  662. /* OLE2NOTE: if this document is the source of data for the
  663. ** clipboard, then flush the clipboard. it is important to flush
  664. ** the clipboard BEFORE calling sending any notifications to
  665. ** clients (eg. IOleClientSite::OnShowWindow(FALSE)) which could
  666. ** give them a chance to run and try to get our clipboard data
  667. ** object that we want to destroy. (eg. our app tries to
  668. ** update the paste button of the toolbar when
  669. ** WM_ACTIVATEAPP is received.)
  670. */
  671. lpClipboardDoc = (LPOLEDOC)lpOutlineApp->m_lpClipboardDoc;
  672. if (lpClipboardDoc &&
  673. lpClipboardDoc->m_lpSrcDocOfCopy == lpOleDoc) {
  674. OleApp_FlushClipboard(lpOleApp);
  675. }
  676. /* OLE2NOTE: Revoke the object from the Running Object Table. it is
  677. ** best if the object is revoke prior to calling
  678. ** COLockObjectExternal(FALSE,TRUE) which is called when the
  679. ** document window is hidden from the user.
  680. */
  681. OLEDBG_BEGIN3("OleStdRevokeAsRunning called\r\n")
  682. OleStdRevokeAsRunning(&lpOleDoc->m_dwRegROT);
  683. OLEDBG_END3
  684. /* OLE2NOTE: if the user is in control of the document, the user
  685. ** accounts for one refcnt on the document. Closing the
  686. ** document is achieved by releasing the object on behalf of
  687. ** the user. if the document is not referenced by any other
  688. ** clients, then the document will also be destroyed. if it
  689. ** is referenced by other clients, then it will remain until
  690. ** they release it. it is important to hide the window and call
  691. ** IOleClientSite::OnShowWindow(FALSE) BEFORE sending OnClose
  692. ** notification.
  693. */
  694. OleDoc_HideWindow(lpOleDoc, TRUE);
  695. #if defined( OLE_SERVER )
  696. {
  697. LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc;
  698. LPSERVERNAMETABLE lpServerNameTable =
  699. (LPSERVERNAMETABLE)((LPOUTLINEDOC)lpOleDoc)->m_lpNameTable;
  700. /* OLE2NOTE: force all pseudo objects to close. this informs all
  701. ** linking clients of pseudo objects to release their PseudoObj.
  702. */
  703. ServerNameTable_CloseAllPseudoObjs(lpServerNameTable);
  704. /* OLE2NOTE: send last OnDataChange notification to clients
  705. ** that have registered for data notifications when object
  706. ** stops running (ADVF_DATAONSTOP), if the data in our
  707. ** object has ever changed. it is best to only send this
  708. ** notification if necessary.
  709. */
  710. if (lpServerDoc->m_lpDataAdviseHldr) {
  711. if (lpServerDoc->m_fSendDataOnStop) {
  712. ServerDoc_SendAdvise(
  713. (LPSERVERDOC)lpOleDoc,
  714. OLE_ONDATACHANGE,
  715. NULL, /* lpmkDoc -- not relevant here */
  716. ADVF_DATAONSTOP
  717. );
  718. }
  719. /* OLE2NOTE: we just sent the last data notification that we
  720. ** need to send; release our DataAdviseHolder. we SHOULD be
  721. ** the only one using it.
  722. */
  723. OleStdVerifyRelease(
  724. (LPUNKNOWN)lpServerDoc->m_lpDataAdviseHldr,
  725. "DataAdviseHldr not released properly"
  726. );
  727. lpServerDoc->m_lpDataAdviseHldr = NULL;
  728. }
  729. // OLE2NOTE: inform all of our linking clients that we are closing.
  730. if (lpServerDoc->m_lpOleAdviseHldr) {
  731. ServerDoc_SendAdvise(
  732. (LPSERVERDOC)lpOleDoc,
  733. OLE_ONCLOSE,
  734. NULL, /* lpmkDoc -- not relevant here */
  735. 0 /* advf -- not relevant here */
  736. );
  737. /* OLE2NOTE: OnClose is the last notification that we need to
  738. ** send; release our OleAdviseHolder. we SHOULD be the only
  739. ** one using it. this will make our destructor realize that
  740. ** OnClose notification has already been sent.
  741. */
  742. OleStdVerifyRelease(
  743. (LPUNKNOWN)lpServerDoc->m_lpOleAdviseHldr,
  744. "OleAdviseHldr not released properly"
  745. );
  746. lpServerDoc->m_lpOleAdviseHldr = NULL;
  747. }
  748. /* release our Container's ClientSite. */
  749. if(lpServerDoc->m_lpOleClientSite) {
  750. OleStdRelease((LPUNKNOWN)lpServerDoc->m_lpOleClientSite);
  751. lpServerDoc->m_lpOleClientSite = NULL;
  752. }
  753. }
  754. #endif
  755. if (lpOleDoc->m_lpLLStm) {
  756. /* release our LineList stream. */
  757. OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpLLStm);
  758. lpOleDoc->m_lpLLStm = NULL;
  759. }
  760. if (lpOleDoc->m_lpNTStm) {
  761. /* release our NameTable stream. */
  762. OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpNTStm);
  763. lpOleDoc->m_lpNTStm = NULL;
  764. }
  765. if (lpOleDoc->m_lpStg) {
  766. /* release our doc storage. */
  767. OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpStg);
  768. lpOleDoc->m_lpStg = NULL;
  769. }
  770. if (lpOleDoc->m_lpFileMoniker) {
  771. OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpFileMoniker);
  772. lpOleDoc->m_lpFileMoniker = NULL;
  773. }
  774. /* OLE2NOTE: this call forces all external connections to our
  775. ** object to close down and therefore guarantees that we receive
  776. ** all releases associated with those external connections.
  777. */
  778. OLEDBG_BEGIN2("CoDisconnectObject(lpDoc) called\r\n")
  779. CoDisconnectObject((LPUNKNOWN)&lpOleDoc->m_Unknown, 0);
  780. OLEDBG_END2
  781. OleDoc_Release(lpOleDoc); // release artificial AddRef above
  782. OleApp_Release(lpOleApp); // release artificial AddRef above
  783. OLEDBG_END3
  784. return TRUE;
  785. }
  786. /* OleDoc_Destroy
  787. * --------------
  788. *
  789. * Free all OLE related resources that had been allocated for a document.
  790. */
  791. void OleDoc_Destroy(LPOLEDOC lpOleDoc)
  792. {
  793. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  794. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
  795. if (lpOleDoc->m_fObjIsDestroying)
  796. return; // Doc destruction is already in progress
  797. lpOleDoc->m_fObjIsDestroying = TRUE; // guard against recursive call
  798. #if defined( OLE_SERVER )
  799. /* OLE2NOTE: it is ALWAYS necessary to make sure that the work we
  800. ** do in our OleDoc_Close function is performed before we
  801. ** destroy our document object. this includes revoking from the
  802. ** Running Object Table (ROT), sending OnClose notification,
  803. ** revoking from Drag/Drop, closing all pseudo objects, etc.
  804. ** There are some tricky scenarios involving linking and
  805. ** when IOleObject::Close is called versus when we get our
  806. ** final release causing us to call our OleDoc_Destroy
  807. ** (destructor) function.
  808. **
  809. ** SCENARIO 1 -- closing from server (File.Exit or File.Close)
  810. ** OleDoc_Close function is called directly by the
  811. ** server in response to the menu command
  812. ** (WM_COMMAND processing).
  813. **
  814. ** SCENARIO 2 -- closed by embedding container
  815. ** our embedding container calls IOleObject::Close
  816. ** directly.
  817. **
  818. ** SCENARIO 3 -- silent-update final release
  819. ** THIS IS THE TRICKY ONE!!!
  820. ** in the case that our object is launched because
  821. ** a linking client calls IOleObject::Update on
  822. ** its link, then our object will be run
  823. ** invisibly, typically GetData will be called,
  824. ** and then the connection from the linking client
  825. ** will be released. the release of this last
  826. ** linking connection should cause our object to
  827. ** shut down.
  828. ** there are 2 strategies to deal with this scenario:
  829. **
  830. ** STRATEGY 1 -- implement IExternalConnection.
  831. ** IExternalConnection::AddConnection will be
  832. ** called (by the StubManager) every time that an
  833. ** external (linking) connection is created or
  834. ** CoLockObjectExternal is called. the object
  835. ** should maintain a count of strong connections
  836. ** (m_dwStrongExtConn). IExternalConnection::
  837. ** ReleaseConnection will be called when these
  838. ** connections are released. when the
  839. ** m_dwStrongExtConn transistions to 0, the object
  840. ** should call its IOleObject::Close function.
  841. ** this assumes that CoLockObjectExternal is used
  842. ** to manage locks by the object itself (eg. when
  843. ** the object is visible to the user--fUserCtrl,
  844. ** and when PseudoObjects are created, etc.)
  845. ** this is the strategy implemented by SVROUTL.
  846. **
  847. ** STRATEGY 2 -- guard both the destructor
  848. ** function and the Close function. if the
  849. ** destructor is called directly without Close
  850. ** first being called, then call Close before
  851. ** proceeding with the destruction code.
  852. ** previously SVROUTL was organized in this
  853. ** manner. that old code is conditionaly compiled
  854. ** away with "#ifdef OBSOLETE" below. this
  855. ** method has the disadvantage that external
  856. ** remoting is no longer possible by the time the
  857. ** Close is called making it impossible for
  858. ** the object to ask its container to save the
  859. ** object if the object is dirty. this can result
  860. ** in data loss. thus STRATEGY 1 is safer.
  861. ** consider the scenario where an in-place
  862. ** container UIDeactivates an object but does NOT
  863. ** keep the object locked running (this is
  864. ** required--see CntrLine_IPSite_OnInPlaceActivate
  865. ** in cntrline.c), then, if a linking client binds
  866. ** and unbinds from the object, the object will be
  867. ** destroyed and will NOT have an opportunity to
  868. ** be saved. by implementing IExternalConnection,
  869. ** a server can insulate itself from a poorly
  870. ** written container.
  871. */
  872. #if defined( _DEBUG )
  873. #ifndef WIN32
  874. // this is not a valid assert in Ole32; if file moniker binding
  875. // fails, for example, we will only get releases coming in
  876. // (no external connections are involved because OLE32 does a
  877. // private rpc to the server (us) where the IPersistFile::Load is
  878. // done.
  879. OleDbgAssertSz(
  880. (lpOutlineDoc->m_fDataTransferDoc || lpOleDoc->m_fObjIsClosing),
  881. "Destroy called without Close being called\r\n"
  882. );
  883. #endif //!WIN32
  884. #endif // _DEBUG
  885. #if defined( OBSOLETE )
  886. /* OLE2NOTE: if the document destructor is called directly because
  887. ** the object's refcnt went to 0 (ie. without OleDoc_Close first
  888. ** being called), then we need to make sure that the document is
  889. ** properly closed before destroying the object. this scenario
  890. ** could arise during a silent-update of a link. calling
  891. ** OleDoc_Close here guarantees that the clipboard will be
  892. ** properly flushed, the doc's moniker will be properly revoked,
  893. ** the document will be saved if necessary, etc.
  894. */
  895. if (!lpOutlineDoc->m_fDataTransferDoc && !lpOleDoc->m_fObjIsClosing)
  896. OleDoc_Close(lpOleDoc, OLECLOSE_NOSAVE);
  897. #endif
  898. {
  899. LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc;
  900. /* OLE2NOTE: perform processing specific for an OLE server */
  901. #if defined( SVR_TREATAS )
  902. if (lpServerDoc->m_lpszTreatAsType) {
  903. OleStdFreeString(lpServerDoc->m_lpszTreatAsType, NULL);
  904. lpServerDoc->m_lpszTreatAsType = NULL;
  905. }
  906. #endif // SVR_TREATAS
  907. #if defined( INPLACE_SVR )
  908. if (IsWindow(lpServerDoc->m_hWndHatch))
  909. DestroyWindow(lpServerDoc->m_hWndHatch);
  910. #endif // INPLACE_SVR
  911. }
  912. #endif // OLE_SERVER
  913. if (lpOleDoc->m_lpLLStm) {
  914. /* release our LineList stream. */
  915. OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpLLStm);
  916. lpOleDoc->m_lpLLStm = NULL;
  917. }
  918. if (lpOleDoc->m_lpNTStm) {
  919. /* release our NameTable stream. */
  920. OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpNTStm);
  921. lpOleDoc->m_lpNTStm = NULL;
  922. }
  923. if (lpOleDoc->m_lpStg) {
  924. /* release our doc storage. */
  925. OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpStg);
  926. lpOleDoc->m_lpStg = NULL;
  927. }
  928. if (lpOleDoc->m_lpFileMoniker) {
  929. OleStdRelease((LPUNKNOWN)lpOleDoc->m_lpFileMoniker);
  930. lpOleDoc->m_lpFileMoniker = NULL;
  931. }
  932. /*****************************************************************
  933. ** OLE2NOTE: each document addref's the app object in order to **
  934. ** guarentee that the app does not shut down while the doc **
  935. ** is still open. since this doc is now destroyed, we will **
  936. ** release this refcnt now. if there are now more open **
  937. ** documents AND the app is not under the control of the **
  938. ** user (ie. launched by OLE) then the app will revoke its **
  939. ** ClassFactory. if there are no more references to the **
  940. ** ClassFactory after it is revoked, then the app will shut **
  941. ** down. this whole procedure is triggered by calling **
  942. ** OutlineApp_DocUnlockApp. **
  943. *****************************************************************/
  944. OutlineApp_DocUnlockApp(lpOutlineApp, lpOutlineDoc);
  945. }
  946. /* OleDoc_SetUpdateEditMenuFlag
  947. * ----------------------------
  948. *
  949. * Purpose:
  950. * Set/clear the UpdateEditMenuFlag in OleDoc.
  951. *
  952. * Parameters:
  953. * fUpdate new value of the flag
  954. *
  955. * Returns:
  956. */
  957. void OleDoc_SetUpdateEditMenuFlag(LPOLEDOC lpOleDoc, BOOL fUpdate)
  958. {
  959. if (!lpOleDoc)
  960. return;
  961. lpOleDoc->m_fUpdateEditMenu = fUpdate;
  962. }
  963. /* OleDoc_GetUpdateEditMenuFlag
  964. * ----------------------------
  965. *
  966. * Purpose:
  967. * Get the value of the UpdateEditMenuFlag in OleDoc
  968. *
  969. * Parameters:
  970. *
  971. * Returns:
  972. * value of the flag
  973. */
  974. BOOL OleDoc_GetUpdateEditMenuFlag(LPOLEDOC lpOleDoc)
  975. {
  976. if (!lpOleDoc)
  977. return FALSE;
  978. return lpOleDoc->m_fUpdateEditMenu;
  979. }
  980. /*************************************************************************
  981. ** OleDoc::IUnknown interface implementation
  982. *************************************************************************/
  983. STDMETHODIMP OleDoc_Unk_QueryInterface(
  984. LPUNKNOWN lpThis,
  985. REFIID riid,
  986. LPVOID FAR* lplpvObj
  987. )
  988. {
  989. LPOLEDOC lpOleDoc = ((struct CDocUnknownImpl FAR*)lpThis)->lpOleDoc;
  990. return OleDoc_QueryInterface(lpOleDoc, riid, lplpvObj);
  991. }
  992. STDMETHODIMP_(ULONG) OleDoc_Unk_AddRef(LPUNKNOWN lpThis)
  993. {
  994. LPOLEDOC lpOleDoc = ((struct CDocUnknownImpl FAR*)lpThis)->lpOleDoc;
  995. OleDbgAddRefMethod(lpThis, "IUnknown");
  996. return OleDoc_AddRef(lpOleDoc);
  997. }
  998. STDMETHODIMP_(ULONG) OleDoc_Unk_Release (LPUNKNOWN lpThis)
  999. {
  1000. LPOLEDOC lpOleDoc = ((struct CDocUnknownImpl FAR*)lpThis)->lpOleDoc;
  1001. OleDbgReleaseMethod(lpThis, "IUnknown");
  1002. return OleDoc_Release(lpOleDoc);
  1003. }
  1004.