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.

2157 lines
58 KiB

  1. /*************************************************************************
  2. **
  3. ** OLE 2 Sample Code
  4. **
  5. ** linking.c
  6. **
  7. ** This file contains the major interfaces, methods and related support
  8. ** functions for implementing linking to items. The code
  9. ** contained in this file is used by BOTH the Container and Server
  10. ** (Object) versions of the Outline sample code.
  11. **
  12. ** As a server SVROUTL supports linking to the whole document object
  13. ** (either a file-based document or as an embedded object). It also
  14. ** supports linking to ranges (or PseudoObjects).
  15. **
  16. ** As a container CNTROUTL supports linking to embedded objects.
  17. ** (see file svrpsobj.c for Pseudo Object implementation)
  18. **
  19. ** OleDoc Object
  20. ** exposed interfaces:
  21. ** IPersistFile
  22. ** IOleItemContainer
  23. ** IExternalConnection
  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. STDMETHODIMP OleDoc_ItemCont_GetObjectA(
  32. LPOLEITEMCONTAINER lpThis,
  33. LPSTR lpszItem,
  34. DWORD dwSpeedNeeded,
  35. LPBINDCTX lpbc,
  36. REFIID riid,
  37. LPVOID FAR*lplpvObject
  38. );
  39. STDMETHODIMP OleDoc_ItemCont_GetObjectStorageA(
  40. LPOLEITEMCONTAINER lpThis,
  41. LPSTR lpszItem,
  42. LPBINDCTX lpbc,
  43. REFIID riid,
  44. LPVOID FAR*lplpvStorage
  45. );
  46. #if defined(OLE_CNTR)
  47. STDMETHODIMP OleDoc_ItemCont_IsRunningA(
  48. LPOLEITEMCONTAINER lpThis,
  49. LPSTR lpszItem
  50. );
  51. HRESULT ContainerDoc_IsRunningA(
  52. LPCONTAINERDOC lpContainerDoc,
  53. LPSTR lpszItem);
  54. HRESULT ContainerDoc_GetObjectA(
  55. LPCONTAINERDOC lpContainerDoc,
  56. LPSTR lpszItem,
  57. DWORD dwSpeedNeeded,
  58. REFIID riid,
  59. LPVOID FAR*lplpvObject
  60. );
  61. HRESULT ContainerDoc_GetObjectStorageA(
  62. LPCONTAINERDOC lpContainerDoc,
  63. LPSTR lpszItem,
  64. LPSTORAGE FAR*lplpStg);
  65. #endif // OLE_CNTR
  66. #if defined(OLE_SERVER)
  67. HRESULT ServerDoc_IsRunningA(LPSERVERDOC lpServerDoc, LPSTR lpszItem);
  68. HRESULT ServerDoc_GetObjectA(
  69. LPSERVERDOC lpServerDoc,
  70. LPSTR lpszItem,
  71. REFIID riid,
  72. LPVOID FAR*lplpvObject);
  73. #endif // OLE_SERVER
  74. /*************************************************************************
  75. ** OleDoc::IPersistFile interface implementation
  76. *************************************************************************/
  77. // IPersistFile::QueryInterface
  78. STDMETHODIMP OleDoc_PFile_QueryInterface(
  79. LPPERSISTFILE lpThis,
  80. REFIID riid,
  81. LPVOID FAR* lplpvObj
  82. )
  83. {
  84. LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc;
  85. return OleDoc_QueryInterface(lpOleDoc, riid, lplpvObj);
  86. }
  87. // IPersistFile::AddRef
  88. STDMETHODIMP_(ULONG) OleDoc_PFile_AddRef(LPPERSISTFILE lpThis)
  89. {
  90. LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc;
  91. OleDbgAddRefMethod(lpThis, "IPersistFile");
  92. return OleDoc_AddRef(lpOleDoc);
  93. }
  94. // IPersistFile::Release
  95. STDMETHODIMP_(ULONG) OleDoc_PFile_Release (LPPERSISTFILE lpThis)
  96. {
  97. LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc;
  98. OleDbgReleaseMethod(lpThis, "IPersistFile");
  99. return OleDoc_Release(lpOleDoc);
  100. }
  101. // IPersistFile::GetClassID
  102. STDMETHODIMP OleDoc_PFile_GetClassID (
  103. LPPERSISTFILE lpThis,
  104. CLSID FAR* lpclsid
  105. )
  106. {
  107. LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc;
  108. LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp;
  109. OleDbgOut2("OleDoc_PFile_GetClassID\r\n");
  110. #if defined( OLE_SERVER ) && defined( SVR_TREATAS )
  111. /* OLE2NOTE: we must be carefull to return the correct CLSID here.
  112. ** if we are currently preforming a "TreatAs (aka. ActivateAs)"
  113. ** operation then we need to return the class of the object
  114. ** written in the storage of the object. otherwise we would
  115. ** return our own class id.
  116. */
  117. return ServerDoc_GetClassID((LPSERVERDOC)lpOleDoc, lpclsid);
  118. #else
  119. *lpclsid = CLSID_APP;
  120. #endif
  121. return NOERROR;
  122. }
  123. // IPersistFile::IsDirty
  124. STDMETHODIMP OleDoc_PFile_IsDirty(LPPERSISTFILE lpThis)
  125. {
  126. LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc;
  127. OleDbgOut2("OleDoc_PFile_IsDirty\r\n");
  128. if (OutlineDoc_IsModified((LPOUTLINEDOC)lpOleDoc))
  129. return NOERROR;
  130. else
  131. return ResultFromScode(S_FALSE);
  132. }
  133. // IPersistFile::Load
  134. STDMETHODIMP OleDoc_PFile_LoadA(
  135. LPPERSISTFILE lpThis,
  136. LPCSTR lpszFileName,
  137. DWORD grfMode
  138. )
  139. {
  140. LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc;
  141. SCODE sc;
  142. OLEDBG_BEGIN2("OleDoc_PFile_Load\r\n")
  143. /* OLE2NOTE: grfMode passed from the caller indicates if the caller
  144. ** needs Read or ReadWrite permissions. if appropriate the
  145. ** callee should open the file with the requested permissions.
  146. ** the caller will normally not impose sharing permissions.
  147. **
  148. ** the sample code currently always opens its file ReadWrite.
  149. */
  150. if (OutlineDoc_LoadFromFile((LPOUTLINEDOC)lpOleDoc, (LPSTR)lpszFileName))
  151. sc = S_OK;
  152. else
  153. sc = E_FAIL;
  154. OLEDBG_END2
  155. return ResultFromScode(sc);
  156. }
  157. // IPersistFile::Load
  158. STDMETHODIMP OleDoc_PFile_Load (
  159. LPPERSISTFILE lpThis,
  160. LPCOLESTR lpszFileName,
  161. DWORD grfMode
  162. )
  163. {
  164. CREATESTR(lpsz, lpszFileName)
  165. HRESULT hr = OleDoc_PFile_LoadA(lpThis, lpsz, grfMode);
  166. FREESTR(lpsz)
  167. return hr;
  168. }
  169. // IPersistFile::Save
  170. STDMETHODIMP OleDoc_PFile_SaveA (
  171. LPPERSISTFILE lpThis,
  172. LPCSTR lpszFileName,
  173. BOOL fRemember
  174. )
  175. {
  176. LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc;
  177. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
  178. SCODE sc;
  179. OLEDBG_BEGIN2("OleDoc_PFile_Save\r\n")
  180. /* OLE2NOTE: it is only legal to perform a Save or SaveAs operation
  181. ** on a file-based document. if the document is an embedded
  182. ** object then we can not be changed to a file-base object.
  183. **
  184. ** fRemember lpszFileName Type of Save
  185. ** ----------------------------------------------
  186. ** TRUE NULL SAVE
  187. ** TRUE ! NULL SAVE AS
  188. ** FALSE ! NULL SAVE COPY AS
  189. ** FALSE NULL ***error***
  190. */
  191. if ( (lpszFileName==NULL || (lpszFileName != NULL && fRemember))
  192. && ((lpOutlineDoc->m_docInitType != DOCTYPE_FROMFILE
  193. && lpOutlineDoc->m_docInitType != DOCTYPE_NEW)) ) {
  194. OLEDBG_END2
  195. return ResultFromScode(E_INVALIDARG);
  196. }
  197. if (OutlineDoc_SaveToFile(
  198. (LPOUTLINEDOC)lpOleDoc,
  199. lpszFileName,
  200. lpOutlineDoc->m_cfSaveFormat,
  201. fRemember)) {
  202. sc = S_OK;
  203. } else
  204. sc = E_FAIL;
  205. OLEDBG_END2
  206. return ResultFromScode(sc);
  207. }
  208. // IPersistFile::Save
  209. STDMETHODIMP OleDoc_PFile_Save(
  210. LPPERSISTFILE lpThis,
  211. LPCOLESTR lpszFileName,
  212. BOOL fRemember
  213. )
  214. {
  215. CREATESTR(lpsz, lpszFileName)
  216. HRESULT hr = OleDoc_PFile_SaveA(lpThis, lpsz, fRemember);
  217. FREESTR(lpsz)
  218. return hr;
  219. }
  220. // IPersistFile::SaveCompleted
  221. STDMETHODIMP OleDoc_PFile_SaveCompletedA (
  222. LPPERSISTFILE lpThis,
  223. LPCSTR lpszFileName
  224. )
  225. {
  226. LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc;
  227. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
  228. OleDbgOut2("OleDoc_PFile_SaveCompleted\r\n");
  229. /* This method is called after IPersistFile::Save is called. during
  230. ** the period between Save and SaveCompleted the object must
  231. ** consider itself in NOSCRIBBLE mode (ie. it is NOT allowed to
  232. ** write to its file. here the object can clear its NOSCRIBBLE
  233. ** mode flag. the outline app never scribbles to its storage, so
  234. ** we have nothing to do.
  235. */
  236. return NOERROR;
  237. }
  238. STDMETHODIMP OleDoc_PFile_SaveCompleted (
  239. LPPERSISTFILE lpThis,
  240. LPCOLESTR lpszFileName
  241. )
  242. {
  243. CREATESTR(lpsz, lpszFileName)
  244. HRESULT hr = OleDoc_PFile_SaveCompletedA(lpThis, lpsz);
  245. FREESTR(lpsz)
  246. return hr;
  247. }
  248. // IPersistFile::GetCurFile
  249. STDMETHODIMP OleDoc_PFile_GetCurFileA (
  250. LPPERSISTFILE lpThis,
  251. LPSTR FAR* lplpszFileName
  252. )
  253. {
  254. LPOLEDOC lpOleDoc = ((struct CDocPersistFileImpl FAR*)lpThis)->lpOleDoc;
  255. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
  256. LPMALLOC lpMalloc;
  257. LPSTR lpsz;
  258. SCODE sc;
  259. OleDbgOut2("OleDoc_PFile_GetCurFile\r\n");
  260. /* OLE2NOTE: we must make sure to set all out ptr parameters to NULL. */
  261. *lplpszFileName = NULL;
  262. /*********************************************************************
  263. ** OLE2NOTE: memory returned for the lplpszFileName must be
  264. ** allocated appropriately using the current registered IMalloc
  265. ** interface. the allows the ownership of the memory to be
  266. ** passed to the caller (even if in another process).
  267. *********************************************************************/
  268. CoGetMalloc(MEMCTX_TASK, &lpMalloc);
  269. if (! lpMalloc) {
  270. return ResultFromScode(E_FAIL);
  271. }
  272. if (lpOutlineDoc->m_docInitType == DOCTYPE_FROMFILE) {
  273. /* valid filename associated; return file name */
  274. lpsz = (LPSTR)lpMalloc->lpVtbl->Alloc(
  275. lpMalloc,
  276. lstrlen((LPSTR)lpOutlineDoc->m_szFileName)+1
  277. );
  278. if (! lpsz) {
  279. sc = E_OUTOFMEMORY;
  280. goto error;
  281. }
  282. lstrcpy(lpsz, (LPSTR)lpOutlineDoc->m_szFileName);
  283. sc = S_OK;
  284. } else {
  285. /* no file associated; return default file name prompt */
  286. lpsz=(LPSTR)lpMalloc->lpVtbl->Alloc(lpMalloc, sizeof(DEFEXTENSION)+3);
  287. wsprintf(lpsz, "*.%s", DEFEXTENSION);
  288. sc = S_FALSE;
  289. }
  290. error:
  291. OleStdRelease((LPUNKNOWN)lpMalloc);
  292. *lplpszFileName = lpsz;
  293. return ResultFromScode(sc);
  294. }
  295. STDMETHODIMP OleDoc_PFile_GetCurFile (
  296. LPPERSISTFILE lpThis,
  297. LPOLESTR FAR* lplpszFileName
  298. )
  299. {
  300. LPSTR lpsz;
  301. HRESULT hr = OleDoc_PFile_GetCurFileA(lpThis, &lpsz);
  302. CopyAndFreeSTR(lpsz, lplpszFileName);
  303. return hr;
  304. }
  305. /*************************************************************************
  306. ** OleDoc::IOleItemContainer interface implementation
  307. *************************************************************************/
  308. // IOleItemContainer::QueryInterface
  309. STDMETHODIMP OleDoc_ItemCont_QueryInterface(
  310. LPOLEITEMCONTAINER lpThis,
  311. REFIID riid,
  312. LPVOID FAR* lplpvObj
  313. )
  314. {
  315. LPOLEDOC lpOleDoc =
  316. ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc;
  317. return OleDoc_QueryInterface(lpOleDoc, riid, lplpvObj);
  318. }
  319. // IOleItemContainer::AddRef
  320. STDMETHODIMP_(ULONG) OleDoc_ItemCont_AddRef(LPOLEITEMCONTAINER lpThis)
  321. {
  322. LPOLEDOC lpOleDoc =
  323. ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc;
  324. OleDbgAddRefMethod(lpThis, "IOleItemContainer");
  325. return OleDoc_AddRef((LPOLEDOC)lpOleDoc);
  326. }
  327. // IOleItemContainer::Release
  328. STDMETHODIMP_(ULONG) OleDoc_ItemCont_Release(LPOLEITEMCONTAINER lpThis)
  329. {
  330. LPOLEDOC lpOleDoc =
  331. ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc;
  332. OleDbgReleaseMethod(lpThis, "IOleItemContainer");
  333. return OleDoc_Release((LPOLEDOC)lpOleDoc);
  334. }
  335. // IOleItemContainer::ParseDisplayName
  336. STDMETHODIMP OleDoc_ItemCont_ParseDisplayNameA(
  337. LPOLEITEMCONTAINER lpThis,
  338. LPBC lpbc,
  339. LPSTR lpszDisplayName,
  340. ULONG FAR* lpchEaten,
  341. LPMONIKER FAR* lplpmkOut
  342. )
  343. {
  344. LPOLEDOC lpOleDoc =
  345. ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc;
  346. char szItemName[MAXNAMESIZE];
  347. LPUNKNOWN lpUnk;
  348. HRESULT hrErr;
  349. OleDbgOut2("OleDoc_ItemCont_ParseDisplayName\r\n");
  350. /* OLE2NOTE: we must make sure to set all out ptr parameters to NULL. */
  351. *lplpmkOut = NULL;
  352. *lpchEaten = OleStdGetItemToken(
  353. lpszDisplayName,
  354. szItemName,
  355. sizeof(szItemName)
  356. );
  357. /* OLE2NOTE: get a pointer to a running instance of the object. we
  358. ** should force the object to go running if necessary (even if
  359. ** this means launching its server EXE). this is the meaining of
  360. ** BINDSPEED_INDEFINITE. Parsing a Moniker is known to be an
  361. ** "EXPENSIVE" operation.
  362. */
  363. hrErr = OleDoc_ItemCont_GetObjectA(
  364. lpThis,
  365. szItemName,
  366. BINDSPEED_INDEFINITE,
  367. lpbc,
  368. &IID_IUnknown,
  369. (LPVOID FAR*)&lpUnk
  370. );
  371. if (hrErr == NOERROR) {
  372. OleStdRelease(lpUnk); // item name FOUND; don't need obj ptr.
  373. CreateItemMonikerA(OLESTDDELIM, szItemName, lplpmkOut);
  374. } else
  375. *lpchEaten = 0; // item name is NOT valid
  376. return hrErr;
  377. }
  378. STDMETHODIMP OleDoc_ItemCont_ParseDisplayName(
  379. LPOLEITEMCONTAINER lpThis,
  380. LPBC lpbc,
  381. LPOLESTR lpszDisplayName,
  382. ULONG FAR* lpchEaten,
  383. LPMONIKER FAR* lplpmkOut
  384. )
  385. {
  386. CREATESTR(lpsz, lpszDisplayName)
  387. HRESULT hr = OleDoc_ItemCont_ParseDisplayNameA(lpThis, lpbc,
  388. lpsz, lpchEaten, lplpmkOut);
  389. FREESTR(lpsz);
  390. return hr;
  391. }
  392. // IOleItemContainer::EnumObjects
  393. STDMETHODIMP OleDoc_ItemCont_EnumObjects(
  394. LPOLEITEMCONTAINER lpThis,
  395. DWORD grfFlags,
  396. LPENUMUNKNOWN FAR* lplpenumUnknown
  397. )
  398. {
  399. LPOLEDOC lpOleDoc =
  400. ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc;
  401. OLEDBG_BEGIN2("OleDoc_ItemCont_EnumObjects\r\n")
  402. /* OLE2NOTE: we must make sure to set all out ptr parameters to NULL. */
  403. *lplpenumUnknown = NULL;
  404. /* OLE2NOTE: this method should be implemented to allow programatic
  405. ** clients the ability to what elements the container holds.
  406. ** this method is NOT called in the standard linking scenarios.
  407. **
  408. ** grfFlags can be one of the following:
  409. ** OLECONTF_EMBEDDINGS -- enumerate embedded objects
  410. ** OLECONTF_LINKS -- enumerate linked objects
  411. ** OLECONTF_OTHERS -- enumerate non-OLE compound doc objs
  412. ** OLECONTF_ONLYUSER -- enumerate only objs named by user
  413. ** OLECONTF_ONLYIFRUNNING-- enumerate only objs in running state
  414. */
  415. OleDbgAssertSz(0, "NOT YET IMPLEMENTED!");
  416. OLEDBG_END2
  417. return ResultFromScode(E_NOTIMPL);
  418. }
  419. // IOleItemContainer::LockContainer
  420. STDMETHODIMP OleDoc_ItemCont_LockContainer(
  421. LPOLEITEMCONTAINER lpThis,
  422. BOOL fLock
  423. )
  424. {
  425. LPOLEDOC lpOleDoc =
  426. ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc;
  427. HRESULT hrErr;
  428. OLEDBG_BEGIN2("OleDoc_ItemCont_LockContainer\r\n")
  429. #if defined( _DEBUG )
  430. if (fLock) {
  431. ++lpOleDoc->m_cCntrLock;
  432. OleDbgOutRefCnt3(
  433. "OleDoc_ItemCont_LockContainer: cLock++\r\n",
  434. lpOleDoc,
  435. lpOleDoc->m_cCntrLock
  436. );
  437. } else {
  438. /* OLE2NOTE: when there are no open documents and the app is not
  439. ** under the control of the user and there are no outstanding
  440. ** locks on the app, then revoke our ClassFactory to enable the
  441. ** app to shut down.
  442. */
  443. --lpOleDoc->m_cCntrLock;
  444. OleDbgAssertSz (
  445. lpOleDoc->m_cCntrLock >= 0,
  446. "OleDoc_ItemCont_LockContainer(FALSE) called with cLock == 0"
  447. );
  448. if (lpOleDoc->m_cCntrLock == 0) {
  449. OleDbgOutRefCnt2(
  450. "OleDoc_ItemCont_LockContainer: UNLOCKED\r\n",
  451. lpOleDoc, lpOleDoc->m_cCntrLock);
  452. } else {
  453. OleDbgOutRefCnt3(
  454. "OleDoc_ItemCont_LockContainer: cLock--\r\n",
  455. lpOleDoc, lpOleDoc->m_cCntrLock);
  456. }
  457. }
  458. #endif // _DEBUG
  459. /* OLE2NOTE: in order to hold the document alive we call
  460. ** CoLockObjectExternal to add a strong reference to our Doc
  461. ** object. this will keep the Doc alive when all other external
  462. ** references release us. whenever an embedded object goes
  463. ** running a LockContainer(TRUE) is called. when the embedded
  464. ** object shuts down (ie. transitions from running to loaded)
  465. ** LockContainer(FALSE) is called. if the user issues File.Close
  466. ** the document will shut down in any case ignoring any
  467. ** outstanding LockContainer locks because CoDisconnectObject is
  468. ** called in OleDoc_Close. this will forceably break any
  469. ** existing strong reference counts including counts that we add
  470. ** ourselves by calling CoLockObjectExternal and guarantee that
  471. ** the Doc object gets its final release (ie. cRefs goes to 0).
  472. */
  473. hrErr = OleDoc_Lock(lpOleDoc, fLock, TRUE /* fLastUnlockReleases */);
  474. OLEDBG_END2
  475. return hrErr;
  476. }
  477. // IOleItemContainer::GetObject
  478. STDMETHODIMP OleDoc_ItemCont_GetObjectA(
  479. LPOLEITEMCONTAINER lpThis,
  480. LPSTR lpszItem,
  481. DWORD dwSpeedNeeded,
  482. LPBINDCTX lpbc,
  483. REFIID riid,
  484. LPVOID FAR* lplpvObject
  485. )
  486. {
  487. LPOLEDOC lpOleDoc =
  488. ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc;
  489. HRESULT hrErr;
  490. OLEDBG_BEGIN2("OleDoc_ItemCont_GetObject\r\n")
  491. /* OLE2NOTE: we must make sure to set all out ptr parameters to NULL. */
  492. *lplpvObject = NULL;
  493. #if defined( OLE_SERVER )
  494. /* OLE2NOTE: SERVER ONLY version should return PseudoObjects with
  495. ** BINDSPEED_IMMEDIATE, thus the dwSpeedNeeded is not important
  496. ** in the case of a pure server.
  497. */
  498. hrErr = ServerDoc_GetObjectA(
  499. (LPSERVERDOC)lpOleDoc, lpszItem,riid,lplpvObject);
  500. #endif
  501. #if defined( OLE_CNTR )
  502. /* OLE2NOTE: dwSpeedNeeded indicates how long the caller is willing
  503. ** to wait for us to get the object:
  504. ** BINDSPEED_IMMEDIATE -- only if obj already loaded && IsRunning
  505. ** BINDSPEED_MODERATE -- load obj if necessary && if IsRunning
  506. ** BINDSPEED_INDEFINITE-- force obj to load and run if necessary
  507. */
  508. hrErr = ContainerDoc_GetObjectA(
  509. (LPCONTAINERDOC)lpOleDoc,lpszItem,dwSpeedNeeded,riid,lplpvObject);
  510. #endif
  511. OLEDBG_END2
  512. return hrErr;
  513. }
  514. STDMETHODIMP OleDoc_ItemCont_GetObject(
  515. LPOLEITEMCONTAINER lpThis,
  516. LPOLESTR lpszItem,
  517. DWORD dwSpeedNeeded,
  518. LPBINDCTX lpbc,
  519. REFIID riid,
  520. LPVOID FAR* lplpvObject
  521. )
  522. {
  523. CREATESTR(lpsz, lpszItem)
  524. HRESULT hr = OleDoc_ItemCont_GetObjectA(lpThis, lpsz, dwSpeedNeeded, lpbc,
  525. riid, lplpvObject);
  526. FREESTR(lpsz)
  527. return hr;
  528. }
  529. // IOleItemContainer::GetObjectStorage
  530. STDMETHODIMP OleDoc_ItemCont_GetObjectStorageA(
  531. LPOLEITEMCONTAINER lpThis,
  532. LPSTR lpszItem,
  533. LPBINDCTX lpbc,
  534. REFIID riid,
  535. LPVOID FAR* lplpvStorage
  536. )
  537. {
  538. LPOLEDOC lpOleDoc =
  539. ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc;
  540. OleDbgOut2("OleDoc_ItemCont_GetObjectStorage\r\n");
  541. /* OLE2NOTE: we must make sure to set all out ptr parameters to NULL. */
  542. *lplpvStorage = NULL;
  543. #if defined( OLE_SERVER )
  544. /* OLE2NOTE: in the SERVER ONLY version, item names identify pseudo
  545. ** objects. pseudo objects, do NOT have identifiable storage.
  546. */
  547. return ResultFromScode(E_FAIL);
  548. #endif
  549. #if defined( OLE_CNTR )
  550. // We can only return an IStorage* type pointer
  551. if (! IsEqualIID(riid, &IID_IStorage))
  552. return ResultFromScode(E_FAIL);
  553. return ContainerDoc_GetObjectStorageA(
  554. (LPCONTAINERDOC)lpOleDoc,
  555. lpszItem,
  556. (LPSTORAGE FAR*)lplpvStorage
  557. );
  558. #endif
  559. }
  560. STDMETHODIMP OleDoc_ItemCont_GetObjectStorage(
  561. LPOLEITEMCONTAINER lpThis,
  562. LPOLESTR lpszItem,
  563. LPBINDCTX lpbc,
  564. REFIID riid,
  565. LPVOID FAR* lplpvStorage
  566. )
  567. {
  568. CREATESTR(lpsz, lpszItem)
  569. HRESULT hr = OleDoc_ItemCont_GetObjectStorageA(lpThis, lpsz, lpbc,
  570. riid, lplpvStorage);
  571. FREESTR(lpsz)
  572. return hr;
  573. }
  574. // IOleItemContainer::IsRunning
  575. STDMETHODIMP OleDoc_ItemCont_IsRunningA(
  576. LPOLEITEMCONTAINER lpThis,
  577. LPSTR lpszItem
  578. )
  579. {
  580. LPOLEDOC lpOleDoc =
  581. ((struct CDocOleItemContainerImpl FAR*)lpThis)->lpOleDoc;
  582. HRESULT hrErr;
  583. OLEDBG_BEGIN2("OleDoc_ItemCont_IsRunning\r\n")
  584. /* OLE2NOTE: Check if item name is valid. if so then return if
  585. ** Object is running. PseudoObjects in the Server version are
  586. ** always considered running. Ole objects in the container must
  587. ** be checked if they are running.
  588. */
  589. #if defined( OLE_SERVER )
  590. hrErr = ServerDoc_IsRunningA((LPSERVERDOC)lpOleDoc, lpszItem);
  591. #endif
  592. #if defined( OLE_CNTR )
  593. hrErr = ContainerDoc_IsRunningA((LPCONTAINERDOC)lpOleDoc, lpszItem);
  594. #endif
  595. OLEDBG_END2
  596. return hrErr;
  597. }
  598. STDMETHODIMP OleDoc_ItemCont_IsRunning(
  599. LPOLEITEMCONTAINER lpThis,
  600. LPOLESTR lpszItem
  601. )
  602. {
  603. CREATESTR(lpsz, lpszItem)
  604. HRESULT hr = OleDoc_ItemCont_IsRunningA(lpThis,lpsz);
  605. FREESTR(lpsz)
  606. return hr;
  607. }
  608. /*************************************************************************
  609. ** OleDoc::IExternalConnection interface implementation
  610. *************************************************************************/
  611. // IExternalConnection::QueryInterface
  612. STDMETHODIMP OleDoc_ExtConn_QueryInterface(
  613. LPEXTERNALCONNECTION lpThis,
  614. REFIID riid,
  615. LPVOID FAR* lplpvObj
  616. )
  617. {
  618. LPOLEDOC lpOleDoc =
  619. ((struct CDocExternalConnectionImpl FAR*)lpThis)->lpOleDoc;
  620. return OleDoc_QueryInterface(lpOleDoc, riid, lplpvObj);
  621. }
  622. // IExternalConnection::AddRef
  623. STDMETHODIMP_(ULONG) OleDoc_ExtConn_AddRef(LPEXTERNALCONNECTION lpThis)
  624. {
  625. LPOLEDOC lpOleDoc =
  626. ((struct CDocExternalConnectionImpl FAR*)lpThis)->lpOleDoc;
  627. OleDbgAddRefMethod(lpThis, "IExternalConnection");
  628. return OleDoc_AddRef(lpOleDoc);
  629. }
  630. // IExternalConnection::Release
  631. STDMETHODIMP_(ULONG) OleDoc_ExtConn_Release (LPEXTERNALCONNECTION lpThis)
  632. {
  633. LPOLEDOC lpOleDoc =
  634. ((struct CDocExternalConnectionImpl FAR*)lpThis)->lpOleDoc;
  635. OleDbgReleaseMethod(lpThis, "IExternalConnection");
  636. return OleDoc_Release(lpOleDoc);
  637. }
  638. // IExternalConnection::AddConnection
  639. STDMETHODIMP_(DWORD) OleDoc_ExtConn_AddConnection(
  640. LPEXTERNALCONNECTION lpThis,
  641. DWORD extconn,
  642. DWORD reserved
  643. )
  644. {
  645. LPOLEDOC lpOleDoc =
  646. ((struct CDocExternalConnectionImpl FAR*)lpThis)->lpOleDoc;
  647. if( extconn & EXTCONN_STRONG ) {
  648. #if defined( _DEBUG )
  649. OleDbgOutRefCnt3(
  650. "OleDoc_ExtConn_AddConnection: dwStrongExtConn++\r\n",
  651. lpOleDoc,
  652. lpOleDoc->m_dwStrongExtConn + 1
  653. );
  654. #endif
  655. return ++(lpOleDoc->m_dwStrongExtConn);
  656. } else
  657. return 0;
  658. }
  659. // IExternalConnection::ReleaseConnection
  660. STDMETHODIMP_(DWORD) OleDoc_ExtConn_ReleaseConnection(
  661. LPEXTERNALCONNECTION lpThis,
  662. DWORD extconn,
  663. DWORD reserved,
  664. BOOL fLastReleaseCloses
  665. )
  666. {
  667. LPOLEDOC lpOleDoc =
  668. ((struct CDocExternalConnectionImpl FAR*)lpThis)->lpOleDoc;
  669. if( extconn & EXTCONN_STRONG ){
  670. DWORD dwSave = --(lpOleDoc->m_dwStrongExtConn);
  671. #if defined( _DEBUG )
  672. OLEDBG_BEGIN2( (fLastReleaseCloses ?
  673. "OleDoc_ExtConn_ReleaseConnection(TRUE)\r\n" :
  674. "OleDoc_ExtConn_ReleaseConnection(FALSE)\r\n") )
  675. OleDbgOutRefCnt3(
  676. "OleDoc_ExtConn_ReleaseConnection: dwStrongExtConn--\r\n",
  677. lpOleDoc,
  678. lpOleDoc->m_dwStrongExtConn
  679. );
  680. OleDbgAssertSz (
  681. lpOleDoc->m_dwStrongExtConn >= 0,
  682. "OleDoc_ExtConn_ReleaseConnection called with dwStrong == 0"
  683. );
  684. #endif // _DEBUG
  685. if( lpOleDoc->m_dwStrongExtConn == 0 && fLastReleaseCloses )
  686. OleDoc_Close(lpOleDoc, OLECLOSE_SAVEIFDIRTY);
  687. OLEDBG_END2
  688. return dwSave;
  689. } else
  690. return 0;
  691. }
  692. /*************************************************************************
  693. ** OleDoc Common Support Functions
  694. *************************************************************************/
  695. /* OleDoc_GetFullMoniker
  696. ** ---------------------
  697. ** Return the full, absolute moniker of the document.
  698. **
  699. ** NOTE: the caller must release the pointer returned when done.
  700. */
  701. LPMONIKER OleDoc_GetFullMoniker(LPOLEDOC lpOleDoc, DWORD dwAssign)
  702. {
  703. LPMONIKER lpMoniker = NULL;
  704. OLEDBG_BEGIN3("OleDoc_GetFullMoniker\r\n")
  705. if (lpOleDoc->m_lpSrcDocOfCopy) {
  706. /* CASE I: this document was created for a copy or drag/drop
  707. ** operation. generate the moniker which identifies the
  708. ** source document of the original copy.
  709. */
  710. if (! lpOleDoc->m_fLinkSourceAvail)
  711. goto done; // we already know a moniker is not available
  712. lpMoniker=OleDoc_GetFullMoniker(lpOleDoc->m_lpSrcDocOfCopy, dwAssign);
  713. }
  714. else if (lpOleDoc->m_lpFileMoniker) {
  715. /* CASE II: this document is a top-level user document (either
  716. ** file-based or untitled). return the FileMoniker stored
  717. ** with the document; it uniquely identifies the document.
  718. */
  719. // we must AddRef the moniker to pass out a ptr
  720. lpOleDoc->m_lpFileMoniker->lpVtbl->AddRef(lpOleDoc->m_lpFileMoniker);
  721. lpMoniker = lpOleDoc->m_lpFileMoniker;
  722. }
  723. #if defined( OLE_SERVER )
  724. else if (((LPSERVERDOC)lpOleDoc)->m_lpOleClientSite) {
  725. /* CASE III: this document is an embedded object, ask our
  726. ** container for our moniker.
  727. */
  728. OLEDBG_BEGIN2("IOleClientSite::GetMoniker called\r\n");
  729. ((LPSERVERDOC)lpOleDoc)->m_lpOleClientSite->lpVtbl->GetMoniker(
  730. ((LPSERVERDOC)lpOleDoc)->m_lpOleClientSite,
  731. dwAssign,
  732. OLEWHICHMK_OBJFULL,
  733. &lpMoniker
  734. );
  735. OLEDBG_END2
  736. }
  737. #endif
  738. else {
  739. lpMoniker = NULL;
  740. }
  741. done:
  742. OLEDBG_END3
  743. return lpMoniker;
  744. }
  745. /* OleDoc_DocRenamedUpdate
  746. ** -----------------------
  747. ** Update the documents registration in the running object table (ROT).
  748. ** Also inform all embedded OLE objects (container only) and/or psedudo
  749. ** objects (server only) that the name of the document has changed.
  750. */
  751. void OleDoc_DocRenamedUpdate(LPOLEDOC lpOleDoc, LPMONIKER lpmkDoc)
  752. {
  753. OLEDBG_BEGIN3("OleDoc_DocRenamedUpdate\r\n")
  754. OleDoc_AddRef(lpOleDoc);
  755. /* OLE2NOTE: we must re-register ourselves as running when we
  756. ** get a new moniker assigned (ie. when we are renamed).
  757. */
  758. OLEDBG_BEGIN3("OleStdRegisterAsRunning called\r\n")
  759. OleStdRegisterAsRunning(
  760. (LPUNKNOWN)&lpOleDoc->m_Unknown,
  761. lpmkDoc,
  762. &lpOleDoc->m_dwRegROT
  763. );
  764. OLEDBG_END3
  765. #if defined( OLE_SERVER )
  766. {
  767. LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc;
  768. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc;
  769. /* OLE2NOTE: inform any linking clients that the document has been
  770. ** renamed.
  771. */
  772. ServerDoc_SendAdvise (
  773. lpServerDoc,
  774. OLE_ONRENAME,
  775. lpmkDoc,
  776. 0 /* advf -- not relevant here */
  777. );
  778. /* OLE2NOTE: inform any clients of pseudo objects
  779. ** within our document, that our document's
  780. ** Moniker has changed.
  781. */
  782. ServerNameTable_InformAllPseudoObjectsDocRenamed(
  783. (LPSERVERNAMETABLE)lpOutlineDoc->m_lpNameTable, lpmkDoc);
  784. }
  785. #endif
  786. #if defined( OLE_CNTR )
  787. {
  788. LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOleDoc;
  789. /* OLE2NOTE: must tell all OLE objects that our container
  790. ** moniker changed.
  791. */
  792. ContainerDoc_InformAllOleObjectsDocRenamed(
  793. lpContainerDoc,
  794. lpmkDoc
  795. );
  796. }
  797. #endif
  798. OleDoc_Release(lpOleDoc); // release artificial AddRef above
  799. OLEDBG_END3
  800. }
  801. #if defined( OLE_SERVER )
  802. /*************************************************************************
  803. ** ServerDoc Supprt Functions Used by Server versions
  804. *************************************************************************/
  805. /* ServerDoc_PseudoObjLockDoc
  806. ** --------------------------
  807. ** Add a lock on the Doc on behalf of the PseudoObject. the Doc may not
  808. ** close while the Doc exists.
  809. **
  810. ** when a pseudo object is first created, it calls this method to
  811. ** guarantee that the document stays alive (PseudoObj_Init).
  812. ** when a pseudo object is destroyed, it call
  813. ** ServerDoc_PseudoObjUnlockDoc to release this hold on the document.
  814. */
  815. void ServerDoc_PseudoObjLockDoc(LPSERVERDOC lpServerDoc)
  816. {
  817. LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc;
  818. ULONG cPseudoObj;
  819. cPseudoObj = ++lpServerDoc->m_cPseudoObj;
  820. #if defined( _DEBUG )
  821. OleDbgOutRefCnt3(
  822. "ServerDoc_PseudoObjLockDoc: cPseudoObj++\r\n",
  823. lpServerDoc,
  824. cPseudoObj
  825. );
  826. #endif
  827. OleDoc_Lock(lpOleDoc, TRUE /* fLock */, 0 /* not applicable */);
  828. return;
  829. }
  830. /* ServerDoc_PseudoObjUnlockDoc
  831. ** ----------------------------
  832. ** Release the lock on the Doc on behalf of the PseudoObject. if this was
  833. ** the last lock on the Doc, then it will shutdown.
  834. */
  835. void ServerDoc_PseudoObjUnlockDoc(
  836. LPSERVERDOC lpServerDoc,
  837. LPPSEUDOOBJ lpPseudoObj
  838. )
  839. {
  840. ULONG cPseudoObj;
  841. LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc;
  842. OLEDBG_BEGIN3("ServerDoc_PseudoObjUnlockDoc\r\n")
  843. /* OLE2NOTE: when there are no active pseudo objects in the Doc and
  844. ** the Doc is not visible, and if there are no outstanding locks
  845. ** on the Doc, then this is a "silent update"
  846. ** situation. our Doc is being used programatically by some
  847. ** client; it is NOT accessible to the user because it is
  848. ** NOT visible. thus since all Locks have been released, we
  849. ** will close the document. if the app is only running due
  850. ** to the presence of this document, then the app will now
  851. ** also shut down.
  852. */
  853. cPseudoObj = --lpServerDoc->m_cPseudoObj;
  854. #if defined( _DEBUG )
  855. OleDbgAssertSz (
  856. lpServerDoc->m_cPseudoObj >= 0,
  857. "PseudoObjUnlockDoc called with cPseudoObj == 0"
  858. );
  859. OleDbgOutRefCnt3(
  860. "ServerDoc_PseudoObjUnlockDoc: cPseudoObj--\r\n",
  861. lpServerDoc,
  862. cPseudoObj
  863. );
  864. #endif
  865. OleDoc_Lock(lpOleDoc, FALSE /* fLock */, TRUE /* fLastUnlockReleases */);
  866. OLEDBG_END3
  867. return;
  868. }
  869. /* ServerDoc_GetObject
  870. ** -------------------
  871. **
  872. ** Return a pointer to an object identified by an item string
  873. ** (lpszItem). For a server-only app, the object returned will be a
  874. ** pseudo object.
  875. */
  876. HRESULT ServerDoc_GetObjectA(
  877. LPSERVERDOC lpServerDoc,
  878. LPSTR lpszItem,
  879. REFIID riid,
  880. LPVOID FAR* lplpvObject
  881. )
  882. {
  883. LPPSEUDOOBJ lpPseudoObj;
  884. LPSERVERNAMETABLE lpServerNameTable =
  885. (LPSERVERNAMETABLE)((LPOUTLINEDOC)lpServerDoc)->m_lpNameTable;
  886. *lplpvObject = NULL;
  887. /* Get the PseudoObj which corresponds to an item name. if the item
  888. ** name does NOT exist in the name table then NO object is
  889. ** returned. the ServerNameTable_GetPseudoObj routine finds a
  890. ** name entry corresponding to the item name, it then checks if
  891. ** a PseudoObj has already been allocated. if so, it returns the
  892. ** existing object, otherwise it allocates a new PseudoObj.
  893. */
  894. lpPseudoObj = ServerNameTable_GetPseudoObj(
  895. lpServerNameTable,
  896. lpszItem,
  897. lpServerDoc
  898. );
  899. if (! lpPseudoObj) {
  900. *lplpvObject = NULL;
  901. return ResultFromScode(MK_E_NOOBJECT);
  902. }
  903. // return the desired interface pointer of the pseudo object.
  904. return PseudoObj_QueryInterface(lpPseudoObj, riid, lplpvObject);
  905. }
  906. HRESULT ServerDoc_GetObject(
  907. LPSERVERDOC lpServerDoc,
  908. LPOLESTR lpszItem,
  909. REFIID riid,
  910. LPVOID FAR* lplpvObject
  911. )
  912. {
  913. CREATESTR(pstr, lpszItem)
  914. HRESULT hr = ServerDoc_GetObjectA(lpServerDoc, pstr, riid, lplpvObject);
  915. FREESTR(pstr)
  916. return hr;
  917. }
  918. /* ServerDoc_IsRunning
  919. ** -------------------
  920. **
  921. ** Check if the object identified by an item string (lpszItem) is in
  922. ** the running state. For a server-only app, if the item name exists in
  923. ** in the NameTable then the item name is considered running.
  924. ** IOleItemContainer::GetObject would succeed.
  925. */
  926. HRESULT ServerDoc_IsRunningA(LPSERVERDOC lpServerDoc, LPSTR lpszItem)
  927. {
  928. LPOUTLINENAMETABLE lpOutlineNameTable =
  929. ((LPOUTLINEDOC)lpServerDoc)->m_lpNameTable;
  930. LPSERVERNAME lpServerName;
  931. lpServerName = (LPSERVERNAME)OutlineNameTable_FindName(
  932. lpOutlineNameTable,
  933. lpszItem
  934. );
  935. if (lpServerName)
  936. return NOERROR;
  937. else
  938. return ResultFromScode(MK_E_NOOBJECT);
  939. }
  940. /* ServerDoc_GetSelRelMoniker
  941. ** --------------------------
  942. ** Retrieve the relative item moniker which identifies the given
  943. ** selection (lplrSel).
  944. **
  945. ** Returns NULL if a moniker can NOT be created.
  946. */
  947. LPMONIKER ServerDoc_GetSelRelMoniker(
  948. LPSERVERDOC lpServerDoc,
  949. LPLINERANGE lplrSel,
  950. DWORD dwAssign
  951. )
  952. {
  953. LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp;
  954. LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc;
  955. LPSERVERNAMETABLE lpServerNameTable =
  956. (LPSERVERNAMETABLE)lpOutlineDoc->m_lpNameTable;
  957. LPOUTLINENAMETABLE lpOutlineNameTable =
  958. (LPOUTLINENAMETABLE)lpServerNameTable;
  959. LPOUTLINENAME lpOutlineName;
  960. LPMONIKER lpmk;
  961. lpOutlineName=OutlineNameTable_FindNamedRange(lpOutlineNameTable,lplrSel);
  962. if (lpOutlineName) {
  963. /* the selection range already has a name assigned */
  964. CreateItemMonikerA(OLESTDDELIM, lpOutlineName->m_szName, &lpmk);
  965. } else {
  966. char szbuf[MAXNAMESIZE];
  967. switch (dwAssign) {
  968. case GETMONIKER_FORCEASSIGN:
  969. /* Force the assignment of the name. This is called when a
  970. ** Paste Link actually occurs. At this point we want to
  971. ** create a Name and add it to the NameTable in order to
  972. ** track the source of the link. This name (as all
  973. ** names) will be updated upon editing of the document.
  974. */
  975. wsprintf(
  976. szbuf,
  977. "%s %ld",
  978. (LPSTR)DEFRANGENAMEPREFIX,
  979. ++(lpServerDoc->m_nNextRangeNo)
  980. );
  981. lpOutlineName = OutlineApp_CreateName(lpOutlineApp);
  982. if (lpOutlineName) {
  983. lstrcpy(lpOutlineName->m_szName, szbuf);
  984. lpOutlineName->m_nStartLine = lplrSel->m_nStartLine;
  985. lpOutlineName->m_nEndLine = lplrSel->m_nEndLine;
  986. OutlineDoc_AddName(lpOutlineDoc, lpOutlineName);
  987. } else {
  988. // REVIEW: do we need "Out-of-Memory" error message here?
  989. }
  990. break;
  991. case GETMONIKER_TEMPFORUSER:
  992. /* Create a name to show to the user in the Paste
  993. ** Special dialog but do NOT yet incur the overhead
  994. ** of adding a Name to the NameTable. The Moniker
  995. ** generated should be useful to display to the user
  996. ** to indicate the source of the copy, but will NOT
  997. ** be used to create a link directly (the caller
  998. ** should ask again for a moniker specifying FORCEASSIGN).
  999. ** we will generate the name that would be the next
  1000. ** auto-generated range name, BUT will NOT actually
  1001. ** increment the range counter.
  1002. */
  1003. wsprintf(
  1004. szbuf,
  1005. "%s %ld",
  1006. (LPSTR)DEFRANGENAMEPREFIX,
  1007. (lpServerDoc->m_nNextRangeNo)+1
  1008. );
  1009. break;
  1010. case GETMONIKER_ONLYIFTHERE:
  1011. /* the caller only wants a name if one has already been
  1012. ** assigned. we have already above checked if the
  1013. ** current selection has a name, so we will simply
  1014. ** return NULL here.
  1015. */
  1016. return NULL; // no moniker is assigned
  1017. default:
  1018. return NULL; // unknown flag given
  1019. }
  1020. CreateItemMonikerA(OLESTDDELIM, szbuf, &lpmk);
  1021. }
  1022. return lpmk;
  1023. }
  1024. /* ServerDoc_GetSelFullMoniker
  1025. ** ---------------------------
  1026. ** Retrieve the full absolute moniker which identifies the given
  1027. ** selection (lplrSel).
  1028. ** this moniker is created as a composite of the absolute moniker for
  1029. ** the entire document appended with an item moniker which identifies
  1030. ** the selection relative to the document.
  1031. ** Returns NULL if a moniker can NOT be created.
  1032. */
  1033. LPMONIKER ServerDoc_GetSelFullMoniker(
  1034. LPSERVERDOC lpServerDoc,
  1035. LPLINERANGE lplrSel,
  1036. DWORD dwAssign
  1037. )
  1038. {
  1039. LPMONIKER lpmkDoc = NULL;
  1040. LPMONIKER lpmkItem = NULL;
  1041. LPMONIKER lpmkFull = NULL;
  1042. lpmkDoc = OleDoc_GetFullMoniker(
  1043. (LPOLEDOC)lpServerDoc,
  1044. dwAssign
  1045. );
  1046. if (! lpmkDoc) return NULL;
  1047. lpmkItem = ServerDoc_GetSelRelMoniker(
  1048. lpServerDoc,
  1049. lplrSel,
  1050. dwAssign
  1051. );
  1052. if (lpmkItem) {
  1053. CreateGenericComposite(lpmkDoc, lpmkItem, (LPMONIKER FAR*)&lpmkFull);
  1054. OleStdRelease((LPUNKNOWN)lpmkItem);
  1055. }
  1056. if (lpmkDoc)
  1057. OleStdRelease((LPUNKNOWN)lpmkDoc);
  1058. return lpmkFull;
  1059. }
  1060. /* ServerNameTable_EditLineUpdate
  1061. * -------------------------------
  1062. *
  1063. * Update the table when a line at nEditIndex is edited.
  1064. */
  1065. void ServerNameTable_EditLineUpdate(
  1066. LPSERVERNAMETABLE lpServerNameTable,
  1067. int nEditIndex
  1068. )
  1069. {
  1070. LPOUTLINENAMETABLE lpOutlineNameTable =
  1071. (LPOUTLINENAMETABLE)lpServerNameTable;
  1072. LPOUTLINENAME lpOutlineName;
  1073. LINERANGE lrSel;
  1074. LPPSEUDOOBJ lpPseudoObj;
  1075. int i;
  1076. for(i = 0; i < lpOutlineNameTable->m_nCount; i++) {
  1077. lpOutlineName=OutlineNameTable_GetName(lpOutlineNameTable, i);
  1078. lpPseudoObj = ((LPSERVERNAME)lpOutlineName)->m_lpPseudoObj;
  1079. /* if there is a pseudo object associated with this name, then
  1080. ** check if the line that was modified is included within
  1081. ** the named range.
  1082. */
  1083. if (lpPseudoObj) {
  1084. OutlineName_GetSel(lpOutlineName, &lrSel);
  1085. if(((int)lrSel.m_nStartLine <= nEditIndex) &&
  1086. ((int)lrSel.m_nEndLine >= nEditIndex)) {
  1087. // inform linking clients data has changed
  1088. PseudoObj_SendAdvise(
  1089. lpPseudoObj,
  1090. OLE_ONDATACHANGE,
  1091. NULL, /* lpmkDoc -- not relevant here */
  1092. 0 /* advf -- no flags necessary */
  1093. );
  1094. }
  1095. }
  1096. }
  1097. }
  1098. /* ServerNameTable_InformAllPseudoObjectsDocRenamed
  1099. * ------------------------------------------------
  1100. *
  1101. * Inform all pseudo object clients that the name of the pseudo
  1102. * object has changed.
  1103. */
  1104. void ServerNameTable_InformAllPseudoObjectsDocRenamed(
  1105. LPSERVERNAMETABLE lpServerNameTable,
  1106. LPMONIKER lpmkDoc
  1107. )
  1108. {
  1109. LPOUTLINENAMETABLE lpOutlineNameTable =
  1110. (LPOUTLINENAMETABLE)lpServerNameTable;
  1111. LPOUTLINENAME lpOutlineName;
  1112. LPPSEUDOOBJ lpPseudoObj;
  1113. LPMONIKER lpmkObj;
  1114. int i;
  1115. OLEDBG_BEGIN2("ServerNameTable_InformAllPseudoObjectsDocRenamed\r\n");
  1116. for(i = 0; i < lpOutlineNameTable->m_nCount; i++) {
  1117. lpOutlineName=OutlineNameTable_GetName(lpOutlineNameTable, i);
  1118. lpPseudoObj = ((LPSERVERNAME)lpOutlineName)->m_lpPseudoObj;
  1119. /* if there is a pseudo object associated with this name, then
  1120. ** send OnRename advise to its linking clients.
  1121. */
  1122. if (lpPseudoObj &&
  1123. ((lpmkObj=PseudoObj_GetFullMoniker(lpPseudoObj,lpmkDoc))!=NULL)) {
  1124. // inform the clients that the name has changed
  1125. PseudoObj_SendAdvise (
  1126. lpPseudoObj,
  1127. OLE_ONRENAME,
  1128. lpmkObj,
  1129. 0 /* advf -- not relevant here */
  1130. );
  1131. }
  1132. }
  1133. OLEDBG_END2
  1134. }
  1135. /* ServerNameTable_InformAllPseudoObjectsDocSaved
  1136. * ------------------------------------------------
  1137. *
  1138. * Inform all pseudo object clients that the name of the pseudo
  1139. * object has changed.
  1140. */
  1141. void ServerNameTable_InformAllPseudoObjectsDocSaved(
  1142. LPSERVERNAMETABLE lpServerNameTable,
  1143. LPMONIKER lpmkDoc
  1144. )
  1145. {
  1146. LPOUTLINENAMETABLE lpOutlineNameTable =
  1147. (LPOUTLINENAMETABLE)lpServerNameTable;
  1148. LPOUTLINENAME lpOutlineName;
  1149. LPPSEUDOOBJ lpPseudoObj;
  1150. LPMONIKER lpmkObj;
  1151. int i;
  1152. OLEDBG_BEGIN2("ServerNameTable_InformAllPseudoObjectsDocSaved\r\n");
  1153. for(i = 0; i < lpOutlineNameTable->m_nCount; i++) {
  1154. lpOutlineName=OutlineNameTable_GetName(lpOutlineNameTable, i);
  1155. lpPseudoObj = ((LPSERVERNAME)lpOutlineName)->m_lpPseudoObj;
  1156. /* if there is a pseudo object associated with this name, then
  1157. ** send OnSave advise to its linking clients.
  1158. */
  1159. if (lpPseudoObj &&
  1160. ((lpmkObj=PseudoObj_GetFullMoniker(lpPseudoObj,lpmkDoc))!=NULL)) {
  1161. // inform the clients that the name has been saved
  1162. PseudoObj_SendAdvise (
  1163. lpPseudoObj,
  1164. OLE_ONSAVE,
  1165. NULL, /* lpmkDoc -- not relevant here */
  1166. 0 /* advf -- not relevant here */
  1167. );
  1168. }
  1169. }
  1170. OLEDBG_END2
  1171. }
  1172. /* ServerNameTable_SendPendingAdvises
  1173. * ----------------------------------
  1174. *
  1175. * Send any pending change notifications for pseudo objects.
  1176. * while ReDraw is diabled on the ServerDoc, then change advise
  1177. * notifications are not sent to pseudo object clients.
  1178. */
  1179. void ServerNameTable_SendPendingAdvises(LPSERVERNAMETABLE lpServerNameTable)
  1180. {
  1181. LPOUTLINENAMETABLE lpOutlineNameTable =
  1182. (LPOUTLINENAMETABLE)lpServerNameTable;
  1183. LPSERVERNAME lpServerName;
  1184. int i;
  1185. for(i = 0; i < lpOutlineNameTable->m_nCount; i++) {
  1186. lpServerName = (LPSERVERNAME)OutlineNameTable_GetName(
  1187. lpOutlineNameTable,
  1188. i
  1189. );
  1190. ServerName_SendPendingAdvises(lpServerName);
  1191. }
  1192. }
  1193. /* ServerNameTable_GetPseudoObj
  1194. ** ----------------------------
  1195. **
  1196. ** Return a pointer to a pseudo object identified by an item string
  1197. ** (lpszItem). if the pseudo object already exists, then return the
  1198. ** existing object, otherwise allocate a new pseudo object.
  1199. */
  1200. LPPSEUDOOBJ ServerNameTable_GetPseudoObj(
  1201. LPSERVERNAMETABLE lpServerNameTable,
  1202. LPSTR lpszItem,
  1203. LPSERVERDOC lpServerDoc
  1204. )
  1205. {
  1206. LPSERVERNAME lpServerName;
  1207. lpServerName = (LPSERVERNAME)OutlineNameTable_FindName(
  1208. (LPOUTLINENAMETABLE)lpServerNameTable,
  1209. lpszItem
  1210. );
  1211. if (lpServerName)
  1212. return ServerName_GetPseudoObj(lpServerName, lpServerDoc);
  1213. else
  1214. return NULL;
  1215. }
  1216. /* ServerNameTable_CloseAllPseudoObjs
  1217. * ----------------------------------
  1218. *
  1219. * Force all pseudo objects to close. this results in sending OnClose
  1220. * notification to each pseudo object's linking clients.
  1221. */
  1222. void ServerNameTable_CloseAllPseudoObjs(LPSERVERNAMETABLE lpServerNameTable)
  1223. {
  1224. LPOUTLINENAMETABLE lpOutlineNameTable =
  1225. (LPOUTLINENAMETABLE)lpServerNameTable;
  1226. LPSERVERNAME lpServerName;
  1227. int i;
  1228. OLEDBG_BEGIN3("ServerNameTable_CloseAllPseudoObjs\r\n")
  1229. for(i = 0; i < lpOutlineNameTable->m_nCount; i++) {
  1230. lpServerName = (LPSERVERNAME)OutlineNameTable_GetName(
  1231. lpOutlineNameTable,
  1232. i
  1233. );
  1234. ServerName_ClosePseudoObj(lpServerName);
  1235. }
  1236. OLEDBG_END3
  1237. }
  1238. /* ServerName_SetSel
  1239. * -----------------
  1240. *
  1241. * Change the line range of a name.
  1242. */
  1243. void ServerName_SetSel(
  1244. LPSERVERNAME lpServerName,
  1245. LPLINERANGE lplrSel,
  1246. BOOL fRangeModified
  1247. )
  1248. {
  1249. LPOUTLINENAME lpOutlineName = (LPOUTLINENAME)lpServerName;
  1250. BOOL fPseudoObjChanged = fRangeModified;
  1251. if (lpOutlineName->m_nStartLine != lplrSel->m_nStartLine) {
  1252. lpOutlineName->m_nStartLine = lplrSel->m_nStartLine;
  1253. fPseudoObjChanged = TRUE;
  1254. }
  1255. if (lpOutlineName->m_nEndLine != lplrSel->m_nEndLine) {
  1256. lpOutlineName->m_nEndLine = lplrSel->m_nEndLine;
  1257. fPseudoObjChanged = TRUE;
  1258. }
  1259. /* OLE2NOTE: if the range of an active pseudo object has
  1260. ** changed, then inform any linking clients that the object
  1261. ** has changed.
  1262. */
  1263. if (lpServerName->m_lpPseudoObj && fPseudoObjChanged) {
  1264. PseudoObj_SendAdvise(
  1265. lpServerName->m_lpPseudoObj,
  1266. OLE_ONDATACHANGE,
  1267. NULL, /* lpmkDoc -- not relevant here */
  1268. 0 /* advf -- no flags necessary */
  1269. );
  1270. }
  1271. }
  1272. /* ServerName_SendPendingAdvises
  1273. * -----------------------------
  1274. *
  1275. * Send any pending change notifications for the associated
  1276. * pseudo objects for this name (if one exists).
  1277. * while ReDraw is diabled on the ServerDoc, then change advise
  1278. * notifications are not sent to pseudo object clients.
  1279. */
  1280. void ServerName_SendPendingAdvises(LPSERVERNAME lpServerName)
  1281. {
  1282. if (! lpServerName->m_lpPseudoObj)
  1283. return; // no associated pseudo object
  1284. if (lpServerName->m_lpPseudoObj->m_fDataChanged)
  1285. PseudoObj_SendAdvise(
  1286. lpServerName->m_lpPseudoObj,
  1287. OLE_ONDATACHANGE,
  1288. NULL, /* lpmkDoc -- not relevant here */
  1289. 0 /* advf -- no flags necessary */
  1290. );
  1291. }
  1292. /* ServerName_GetPseudoObj
  1293. ** -----------------------
  1294. **
  1295. ** Return a pointer to a pseudo object associated to a ServerName.
  1296. ** if the pseudo object already exists, then return the
  1297. ** existing object, otherwise allocate a new pseudo object.
  1298. **
  1299. ** NOTE: the PseudoObj is returned with a 0 refcnt if first created,
  1300. ** else the existing refcnt is unchanged.
  1301. */
  1302. LPPSEUDOOBJ ServerName_GetPseudoObj(
  1303. LPSERVERNAME lpServerName,
  1304. LPSERVERDOC lpServerDoc
  1305. )
  1306. {
  1307. // Check if a PseudoObj already exists
  1308. if (lpServerName->m_lpPseudoObj)
  1309. return lpServerName->m_lpPseudoObj;
  1310. // A PseudoObj does NOT already exist, allocate a new one.
  1311. lpServerName->m_lpPseudoObj=(LPPSEUDOOBJ) New((DWORD)sizeof(PSEUDOOBJ));
  1312. if (lpServerName->m_lpPseudoObj == NULL) {
  1313. OleDbgAssertSz(lpServerName->m_lpPseudoObj != NULL, "Error allocating PseudoObj");
  1314. return NULL;
  1315. }
  1316. PseudoObj_Init(lpServerName->m_lpPseudoObj, lpServerName, lpServerDoc);
  1317. return lpServerName->m_lpPseudoObj;
  1318. }
  1319. /* ServerName_ClosePseudoObj
  1320. * -------------------------
  1321. *
  1322. * if there is an associated pseudo objects for this name (if one
  1323. * exists), then close it. this results in sending OnClose
  1324. * notification to the pseudo object's linking clients.
  1325. */
  1326. void ServerName_ClosePseudoObj(LPSERVERNAME lpServerName)
  1327. {
  1328. if (!lpServerName || !lpServerName->m_lpPseudoObj)
  1329. return; // no associated pseudo object
  1330. PseudoObj_Close(lpServerName->m_lpPseudoObj);
  1331. }
  1332. #endif // OLE_SERVER
  1333. #if defined( OLE_CNTR )
  1334. /*************************************************************************
  1335. ** ContainerDoc Supprt Functions Used by Container versions
  1336. *************************************************************************/
  1337. /* ContainerLine_GetRelMoniker
  1338. ** ---------------------------
  1339. ** Retrieve the relative item moniker which identifies the OLE object
  1340. ** relative to the container document.
  1341. **
  1342. ** Returns NULL if a moniker can NOT be created.
  1343. */
  1344. LPMONIKER ContainerLine_GetRelMoniker(
  1345. LPCONTAINERLINE lpContainerLine,
  1346. DWORD dwAssign
  1347. )
  1348. {
  1349. LPMONIKER lpmk = NULL;
  1350. /* OLE2NOTE: we should only give out a moniker for the OLE object
  1351. ** if the object is allowed to be linked to from the inside. if
  1352. ** so we are allowed to give out a moniker which binds to the
  1353. ** running OLE object). if the object is an OLE 2.0 embedded
  1354. ** object then it is allowed to be linked to from the inside. if
  1355. ** the object is either an OleLink or an OLE 1.0 embedding
  1356. ** then it can not be linked to from the inside.
  1357. ** if we were a container/server app then we could offer linking
  1358. ** to the outside of the object (ie. a pseudo object within our
  1359. ** document). we are a container only app that does not support
  1360. ** linking to ranges of its data.
  1361. */
  1362. switch (dwAssign) {
  1363. case GETMONIKER_FORCEASSIGN:
  1364. /* Force the assignment of the name. This is called when a
  1365. ** Paste Link actually occurs. From now on we want
  1366. ** to inform the OLE object that its moniker is
  1367. ** assigned and is thus necessary to register itself
  1368. ** in the RunningObjectTable.
  1369. */
  1370. CreateItemMonikerA(
  1371. OLESTDDELIM, lpContainerLine->m_szStgName, &lpmk);
  1372. /* OLE2NOTE: if the OLE object is already loaded and it
  1373. ** is being assigned a moniker for the first time,
  1374. ** then we need to inform it that it now has a moniker
  1375. ** assigned by calling IOleObject::SetMoniker. this
  1376. ** will force the OLE object to register in the
  1377. ** RunningObjectTable when it enters the running
  1378. ** state. if the object is not currently loaded,
  1379. ** SetMoniker will be called automatically later when
  1380. ** the object is loaded by the function
  1381. ** ContainerLine_LoadOleObject.
  1382. */
  1383. if (! lpContainerLine->m_fMonikerAssigned) {
  1384. /* we must remember forever more that this object has a
  1385. ** moniker assigned.
  1386. */
  1387. lpContainerLine->m_fMonikerAssigned = TRUE;
  1388. // we are now dirty and must be saved
  1389. OutlineDoc_SetModified(
  1390. (LPOUTLINEDOC)lpContainerLine->m_lpDoc,
  1391. TRUE, /* fModified */
  1392. FALSE, /* fDataChanged--N/A for container ver. */
  1393. FALSE /* fSizeChanged--N/A for container ver. */
  1394. );
  1395. if (lpContainerLine->m_lpOleObj) {
  1396. OLEDBG_BEGIN2("IOleObject::SetMoniker called\r\n")
  1397. lpContainerLine->m_lpOleObj->lpVtbl->SetMoniker(
  1398. lpContainerLine->m_lpOleObj,
  1399. OLEWHICHMK_OBJREL,
  1400. lpmk
  1401. );
  1402. OLEDBG_END2
  1403. }
  1404. }
  1405. break;
  1406. case GETMONIKER_ONLYIFTHERE:
  1407. /* If the OLE object currently has a moniker assigned,
  1408. ** then return it.
  1409. */
  1410. if (lpContainerLine->m_fMonikerAssigned) {
  1411. CreateItemMonikerA(
  1412. OLESTDDELIM,
  1413. lpContainerLine->m_szStgName,
  1414. &lpmk
  1415. );
  1416. }
  1417. break;
  1418. case GETMONIKER_TEMPFORUSER:
  1419. /* Return the moniker that would be used for the OLE
  1420. ** object but do NOT force moniker assignment at
  1421. ** this point. Since our strategy is to use the
  1422. ** storage name of the object as its item name, we
  1423. ** can simply create the corresponding ItemMoniker
  1424. ** (indepenedent of whether the moniker is currently
  1425. ** assigned or not).
  1426. */
  1427. CreateItemMonikerA(
  1428. OLESTDDELIM,
  1429. lpContainerLine->m_szStgName,
  1430. &lpmk
  1431. );
  1432. break;
  1433. case GETMONIKER_UNASSIGN:
  1434. lpContainerLine->m_fMonikerAssigned = FALSE;
  1435. break;
  1436. }
  1437. return lpmk;
  1438. }
  1439. /* ContainerLine_GetFullMoniker
  1440. ** ----------------------------
  1441. ** Retrieve the full absolute moniker which identifies the OLE object
  1442. ** in the container document.
  1443. ** this moniker is created as a composite of the absolute moniker for
  1444. ** the entire document appended with an item moniker which identifies
  1445. ** the OLE object relative to the document.
  1446. ** Returns NULL if a moniker can NOT be created.
  1447. */
  1448. LPMONIKER ContainerLine_GetFullMoniker(
  1449. LPCONTAINERLINE lpContainerLine,
  1450. DWORD dwAssign
  1451. )
  1452. {
  1453. LPMONIKER lpmkDoc = NULL;
  1454. LPMONIKER lpmkItem = NULL;
  1455. LPMONIKER lpmkFull = NULL;
  1456. lpmkDoc = OleDoc_GetFullMoniker(
  1457. (LPOLEDOC)lpContainerLine->m_lpDoc,
  1458. dwAssign
  1459. );
  1460. if (! lpmkDoc) return NULL;
  1461. lpmkItem = ContainerLine_GetRelMoniker(lpContainerLine, dwAssign);
  1462. if (lpmkItem) {
  1463. CreateGenericComposite(lpmkDoc, lpmkItem, (LPMONIKER FAR*)&lpmkFull);
  1464. OleStdRelease((LPUNKNOWN)lpmkItem);
  1465. }
  1466. if (lpmkDoc)
  1467. OleStdRelease((LPUNKNOWN)lpmkDoc);
  1468. return lpmkFull;
  1469. }
  1470. /* ContainerDoc_InformAllOleObjectsDocRenamed
  1471. ** ------------------------------------------
  1472. ** Inform all OLE objects that the name of the ContainerDoc has changed.
  1473. */
  1474. void ContainerDoc_InformAllOleObjectsDocRenamed(
  1475. LPCONTAINERDOC lpContainerDoc,
  1476. LPMONIKER lpmkDoc
  1477. )
  1478. {
  1479. LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
  1480. int i;
  1481. LPLINE lpLine;
  1482. for (i = 0; i < lpLL->m_nNumLines; i++) {
  1483. lpLine=LineList_GetLine(lpLL, i);
  1484. if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) {
  1485. LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine;
  1486. /* OLE2NOTE: if the OLE object is already loaded AND the
  1487. ** object already has a moniker assigned, then we need
  1488. ** to inform it that the moniker of the ContainerDoc has
  1489. ** changed. of course, this means the full moniker of
  1490. ** the object has changed. to do this we call
  1491. ** IOleObject::SetMoniker. this will force the OLE
  1492. ** object to re-register in the RunningObjectTable if it
  1493. ** is currently in the running state. it is not in the
  1494. ** running state, the object handler can make not that
  1495. ** the object has a new moniker. if the object is not
  1496. ** currently loaded, SetMoniker will be called
  1497. ** automatically later when the object is loaded by the
  1498. ** function ContainerLine_LoadOleObject.
  1499. ** also if the object is a linked object, we always want
  1500. ** to call SetMoniker on the link so that in case the
  1501. ** link source is contained within our same container,
  1502. ** the link source will be tracked. the link rebuilds
  1503. ** its absolute moniker if it has a relative moniker.
  1504. */
  1505. if (lpContainerLine->m_lpOleObj) {
  1506. if (lpContainerLine->m_fMonikerAssigned ||
  1507. lpContainerLine->m_dwLinkType != 0) {
  1508. OLEDBG_BEGIN2("IOleObject::SetMoniker called\r\n")
  1509. lpContainerLine->m_lpOleObj->lpVtbl->SetMoniker(
  1510. lpContainerLine->m_lpOleObj,
  1511. OLEWHICHMK_CONTAINER,
  1512. lpmkDoc
  1513. );
  1514. OLEDBG_END2
  1515. }
  1516. /* OLE2NOTE: we must call IOleObject::SetHostNames so
  1517. ** any open objects can update their window titles.
  1518. */
  1519. OLEDBG_BEGIN2("IOleObject::SetHostNames called\r\n")
  1520. CallIOleObjectSetHostNamesA(
  1521. lpContainerLine->m_lpOleObj,
  1522. APPNAME,
  1523. ((LPOUTLINEDOC)lpContainerDoc)->m_lpszDocTitle
  1524. );
  1525. OLEDBG_END2
  1526. }
  1527. }
  1528. }
  1529. }
  1530. /* ContainerDoc_GetObject
  1531. ** ----------------------
  1532. ** Return a pointer to the desired interface of an object identified
  1533. ** by an item string (lpszItem). the object returned will be an OLE
  1534. ** object (either link or embedding).
  1535. **
  1536. ** OLE2NOTE: we must force the object to run because we are
  1537. ** REQUIRED to return a pointer the OLE object in the
  1538. ** RUNNING state.
  1539. **
  1540. ** dwSpeedNeeded indicates how long the caller is willing
  1541. ** to wait for us to get the object:
  1542. ** BINDSPEED_IMMEDIATE -- only if obj already loaded && IsRunning
  1543. ** BINDSPEED_MODERATE -- load obj if necessary && if IsRunning
  1544. ** BINDSPEED_INDEFINITE-- force obj to load and run if necessary
  1545. */
  1546. HRESULT ContainerDoc_GetObjectA(
  1547. LPCONTAINERDOC lpContainerDoc,
  1548. LPSTR lpszItem,
  1549. DWORD dwSpeedNeeded,
  1550. REFIID riid,
  1551. LPVOID FAR* lplpvObject
  1552. )
  1553. {
  1554. LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
  1555. int i;
  1556. LPLINE lpLine;
  1557. BOOL fMatchFound = FALSE;
  1558. DWORD dwStatus;
  1559. HRESULT hrErr;
  1560. *lplpvObject = NULL;
  1561. for (i = 0; i < lpLL->m_nNumLines; i++) {
  1562. lpLine=LineList_GetLine(lpLL, i);
  1563. if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) {
  1564. LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine;
  1565. if (lstrcmp(lpContainerLine->m_szStgName, lpszItem) == 0) {
  1566. fMatchFound = TRUE; // valid item name
  1567. // check if object is loaded.
  1568. if (lpContainerLine->m_lpOleObj == NULL) {
  1569. // if BINDSPEED_IMMEDIATE is requested, object must
  1570. // ALREADY be loadded.
  1571. if (dwSpeedNeeded == BINDSPEED_IMMEDIATE)
  1572. return ResultFromScode(MK_E_EXCEEDEDDEADLINE);
  1573. ContainerLine_LoadOleObject(lpContainerLine);
  1574. if (! lpContainerLine->m_lpOleObj)
  1575. return ResultFromScode(E_OUTOFMEMORY);
  1576. }
  1577. /* OLE2NOTE: check if the object is allowed to be linked
  1578. ** to from the inside (ie. we are allowed to
  1579. ** give out a moniker which binds to the running
  1580. ** OLE object). if the object is an OLE
  1581. ** 2.0 embedded object then it is allowed to be
  1582. ** linked to from the inside. if the object is
  1583. ** either an OleLink or an OLE 1.0 embedding
  1584. ** then it can not be linked to from the inside.
  1585. ** if we were a container/server app then we
  1586. ** could offer linking to the outside of the
  1587. ** object (ie. a pseudo object within our
  1588. ** document). we are a container only app that
  1589. ** does not support linking to ranges of its data.
  1590. */
  1591. OLEDBG_BEGIN2("IOleObject::GetMiscStatus called\r\n");
  1592. lpContainerLine->m_lpOleObj->lpVtbl->GetMiscStatus(
  1593. lpContainerLine->m_lpOleObj,
  1594. DVASPECT_CONTENT, /* aspect is not important */
  1595. (LPDWORD)&dwStatus
  1596. );
  1597. OLEDBG_END2
  1598. if (dwStatus & OLEMISC_CANTLINKINSIDE)
  1599. return ResultFromScode(MK_E_NOOBJECT);
  1600. // check if object is running.
  1601. if (! OleIsRunning(lpContainerLine->m_lpOleObj)) {
  1602. // if BINDSPEED_MODERATE is requested, object must
  1603. // ALREADY be running.
  1604. if (dwSpeedNeeded == BINDSPEED_MODERATE)
  1605. return ResultFromScode(MK_E_EXCEEDEDDEADLINE);
  1606. /* OLE2NOTE: we have found a match for the item name.
  1607. ** now we must return a pointer to the desired
  1608. ** interface on the RUNNING object. we must
  1609. ** carefully load the object and initially ask for
  1610. ** an interface that we are sure the loaded form of
  1611. ** the object supports. if we immediately ask the
  1612. ** loaded object for the desired interface, the
  1613. ** QueryInterface call might fail if it is an
  1614. ** interface that is supported only when the object
  1615. ** is running. thus we force the object to load and
  1616. ** return its IUnknown*. then we force the object to
  1617. ** run, and then finally, we can ask for the
  1618. ** actually requested interface.
  1619. */
  1620. hrErr = ContainerLine_RunOleObject(lpContainerLine);
  1621. if (hrErr != NOERROR) {
  1622. return hrErr;
  1623. }
  1624. }
  1625. // Retrieve the requested interface
  1626. *lplpvObject = OleStdQueryInterface(
  1627. (LPUNKNOWN)lpContainerLine->m_lpOleObj, riid);
  1628. break; // Match FOUND!
  1629. }
  1630. }
  1631. }
  1632. if (*lplpvObject != NULL) {
  1633. return NOERROR;
  1634. } else
  1635. return (fMatchFound ? ResultFromScode(E_NOINTERFACE)
  1636. : ResultFromScode(MK_E_NOOBJECT));
  1637. }
  1638. HRESULT ContainerDoc_GetObject(
  1639. LPCONTAINERDOC lpContainerDoc,
  1640. LPOLESTR lpszItem,
  1641. DWORD dwSpeedNeeded,
  1642. REFIID riid,
  1643. LPVOID FAR* lplpvObject
  1644. )
  1645. {
  1646. CREATESTR(lpsz, lpszItem)
  1647. HRESULT hr = ContainerDoc_GetObjectA(lpContainerDoc, lpsz, dwSpeedNeeded,
  1648. riid, lplpvObject);
  1649. FREESTR(lpsz)
  1650. return hr;
  1651. }
  1652. /* ContainerDoc_GetObjectStorage
  1653. ** -----------------------------
  1654. ** Return a pointer to the IStorage* used by the object identified
  1655. ** by an item string (lpszItem). the object identified could be either
  1656. ** an OLE object (either link or embedding).
  1657. */
  1658. HRESULT ContainerDoc_GetObjectStorageA(
  1659. LPCONTAINERDOC lpContainerDoc,
  1660. LPSTR lpszItem,
  1661. LPSTORAGE FAR* lplpStg
  1662. )
  1663. {
  1664. LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
  1665. int i;
  1666. LPLINE lpLine;
  1667. *lplpStg = NULL;
  1668. for (i = 0; i < lpLL->m_nNumLines; i++) {
  1669. lpLine=LineList_GetLine(lpLL, i);
  1670. if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) {
  1671. LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine;
  1672. if (lstrcmp(lpContainerLine->m_szStgName, lpszItem) == 0) {
  1673. *lplpStg = lpContainerLine->m_lpStg;
  1674. break; // Match FOUND!
  1675. }
  1676. }
  1677. }
  1678. if (*lplpStg != NULL) {
  1679. return NOERROR;
  1680. } else
  1681. return ResultFromScode(MK_E_NOOBJECT);
  1682. }
  1683. HRESULT ContainerDoc_GetObjectStorage(
  1684. LPCONTAINERDOC lpContainerDoc,
  1685. LPOLESTR lpszItem,
  1686. LPSTORAGE FAR* lplpStg
  1687. )
  1688. {
  1689. CREATESTR(lpsz, lpszItem)
  1690. HRESULT hr = ContainerDoc_GetObjectStorageA(lpContainerDoc, lpsz, lplpStg);
  1691. FREESTR(lpsz)
  1692. return hr;
  1693. }
  1694. /* ContainerDoc_IsRunning
  1695. ** ----------------------
  1696. ** Check if the object identified by an item string (lpszItem) is in
  1697. ** the running state.
  1698. ** For a container-only app, a check is made if the OLE object
  1699. ** associated with the item name is running.
  1700. */
  1701. HRESULT ContainerDoc_IsRunningA(LPCONTAINERDOC lpContainerDoc, LPSTR lpszItem)
  1702. {
  1703. LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList;
  1704. int i;
  1705. LPLINE lpLine;
  1706. DWORD dwStatus;
  1707. for (i = 0; i < lpLL->m_nNumLines; i++) {
  1708. lpLine=LineList_GetLine(lpLL, i);
  1709. if (lpLine && (Line_GetLineType(lpLine)==CONTAINERLINETYPE)) {
  1710. LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine;
  1711. if (lstrcmp(lpContainerLine->m_szStgName, lpszItem) == 0) {
  1712. /* OLE2NOTE: we have found a match for the item name.
  1713. ** now we must check if the OLE object is running.
  1714. ** we will load the object if not already loaded.
  1715. */
  1716. if (! lpContainerLine->m_lpOleObj) {
  1717. ContainerLine_LoadOleObject(lpContainerLine);
  1718. if (! lpContainerLine->m_lpOleObj)
  1719. return ResultFromScode(E_OUTOFMEMORY);
  1720. }
  1721. /* OLE2NOTE: check if the object is allowed to be linked
  1722. ** to from the inside (ie. we are allowed to
  1723. ** give out a moniker which binds to the running
  1724. ** OLE object). if the object is an OLE
  1725. ** 2.0 embedded object then it is allowed to be
  1726. ** linked to from the inside. if the object is
  1727. ** either an OleLink or an OLE 1.0 embedding
  1728. ** then it can not be linked to from the inside.
  1729. ** if we were a container/server app then we
  1730. ** could offer linking to the outside of the
  1731. ** object (ie. a pseudo object within our
  1732. ** document). we are a container only app that
  1733. ** does not support linking to ranges of its data.
  1734. */
  1735. OLEDBG_BEGIN2("IOleObject::GetMiscStatus called\r\n")
  1736. lpContainerLine->m_lpOleObj->lpVtbl->GetMiscStatus(
  1737. lpContainerLine->m_lpOleObj,
  1738. DVASPECT_CONTENT, /* aspect is not important */
  1739. (LPDWORD)&dwStatus
  1740. );
  1741. OLEDBG_END2
  1742. if (dwStatus & OLEMISC_CANTLINKINSIDE)
  1743. return ResultFromScode(MK_E_NOOBJECT);
  1744. if (OleIsRunning(lpContainerLine->m_lpOleObj))
  1745. return NOERROR;
  1746. else
  1747. return ResultFromScode(S_FALSE);
  1748. }
  1749. }
  1750. }
  1751. // no object was found corresponding to the item name
  1752. return ResultFromScode(MK_E_NOOBJECT);
  1753. }
  1754. HRESULT ContainerDoc_IsRunning(LPCONTAINERDOC lpContainerDoc, LPOLESTR lpszItem)
  1755. {
  1756. CREATESTR(lpsz, lpszItem)
  1757. HRESULT hr = ContainerDoc_IsRunningA(lpContainerDoc, lpsz);
  1758. FREESTR(lpsz)
  1759. return hr;
  1760. }
  1761. #endif // OLE_CNTR