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.

2349 lines
64 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: le.c
  3. *
  4. * Purpose: Handles all API routines for the dde L&E sub-dll of the ole dll.
  5. *
  6. * Created: 1990
  7. *
  8. * Copyright (c) 1990, 1991 Microsoft Corporation
  9. *
  10. * History:
  11. * Raor, srinik (../../1990,91) Designed and coded
  12. * curts created portable version for win16/32
  13. *
  14. \***************************************************************************/
  15. #include <windows.h>
  16. #include "dll.h"
  17. #define EMB_ID_INDEX 3 // index of ones digit in #000
  18. char embStr[] = "#000";
  19. extern HANDLE hInfo;
  20. extern OLECLIPFORMAT cfNetworkName;
  21. HANDLE GetNetNameHandle (LPOBJECT_LE);
  22. BOOL AreTopicsEqual (LPOBJECT_LE, LPOBJECT_LE);
  23. ATOM FARINTERNAL wAtomCat (ATOM, ATOM);
  24. #ifdef WIN16
  25. #pragma alloc_text(_RARETEXT, LeObjectLong, LeQueryProtocol, LeEqual, AreTopicsEqual, LeObjectConvert, wAtomCat)
  26. #pragma alloc_text(_DDETEXT, LeRequestData, RequestData, LeChangeData, ContextCallBack, DeleteExtraData, NextAsyncCmd, InitAsyncCmd, FarInitAsyncCmd, EndAsyncCmd, ProcessErr, ScheduleAsyncCmd, LeQueryReleaseStatus, EmbLnkDelete, LeRelease, DeleteObjectAto
  27. ms, QueryClose, SendStdClose, TermDocConv, DeleteDocEdit, QueryUnlaunch, SendStdExit, QueryOpen, GetPictType, RequestOn, DocShow, EmbLnkClose, LnkSetUpdateOptions, LnkChangeLnk, TermSrvrConv, DeleteSrvrEdit, LeCopyFromLink)
  28. #endif
  29. OLEOBJECTVTBL vtblLE = {
  30. LeQueryProtocol, // check whether the speced protocol is supported
  31. LeRelease, // release
  32. LeShow, // Show
  33. LeDoVerb, // run
  34. LeGetData,
  35. LeSetData,
  36. LeSetTargetDevice, //
  37. LeSetBounds, // set viewport bounds
  38. LeEnumFormat, // returns format
  39. LeSetColorScheme, // set color scheme
  40. LeRelease, // delete
  41. LeSetHostNames, //
  42. LeSaveToStream, // write to file
  43. LeClone, // clone object
  44. LeCopyFromLink, // Create embedded from Link
  45. LeEqual, // test whether the object data is similar
  46. LeCopy, // copy to clip
  47. LeDraw, // draw the object
  48. LeActivate, // activate
  49. LeExecute, // excute the given commands
  50. LeClose, // stop
  51. LeUpdate, // Update
  52. LeReconnect, // Reconnect
  53. LeObjectConvert, // convert object to specified type
  54. LeGetUpdateOptions, // Get Link Update options
  55. LeSetUpdateOptions, // Set Link Update options
  56. ObjRename, // Change Object name
  57. ObjQueryName, // Get current object name
  58. LeQueryType, // object Type
  59. LeQueryBounds, // QueryBounds
  60. ObjQuerySize, // Find the size of the object
  61. LeQueryOpen, // Query open
  62. LeQueryOutOfDate, // query whether object is current
  63. LeQueryReleaseStatus, // returns release status
  64. LeQueryReleaseError, // assynchronusrelease error
  65. LeQueryReleaseMethod, // the method/proc which is in assynchronus
  66. // operation.
  67. LeRequestData, // requestdata
  68. LeObjectLong, // objectLong
  69. LeChangeData // change native data of existing object
  70. };
  71. //////////////////////////////////////////////////////////////////////////////
  72. //
  73. // OLESTATUS FAR PASCAL LeObjectLong (lpoleobj, wFlags, lpData)
  74. //
  75. //
  76. // Returns whether a given object is still processing a previous
  77. // asynchronous command. returns OLE_BUSY if the object is still
  78. // processing the previous command
  79. //
  80. // Arguments:
  81. //
  82. // lpoleobj - ole object pointer
  83. // wFlags - get, set flags
  84. // lpData - long pointer to data
  85. //
  86. // Returns:
  87. //
  88. // OLE_OK
  89. // OLE_ERROR_OBJECT
  90. //
  91. // Effects:
  92. //
  93. //////////////////////////////////////////////////////////////////////////////
  94. OLESTATUS FARINTERNAL LeObjectLong (
  95. LPOLEOBJECT lpoleobj,
  96. UINT wFlags,
  97. LPLONG lpData
  98. ){
  99. LPOBJECT_LE lpobj = (LPOBJECT_LE)lpoleobj;
  100. LONG lData;
  101. Puts("LeObjectLong");
  102. if (!FarCheckObject((LPOLEOBJECT) lpobj))
  103. return OLE_ERROR_OBJECT;
  104. if ((lpobj->head.ctype != CT_EMBEDDED) && (lpobj->head.ctype != CT_LINK))
  105. return OLE_ERROR_OBJECT;
  106. if (wFlags & OF_HANDLER) {
  107. lData = lpobj->lHandlerData;
  108. if (wFlags & OF_SET)
  109. lpobj->lHandlerData = *lpData;
  110. if (wFlags & OF_GET)
  111. *lpData = lData;
  112. }
  113. else {
  114. lData = lpobj->lAppData;
  115. if (wFlags & OF_SET)
  116. lpobj->lAppData = *lpData;
  117. if (wFlags & OF_GET)
  118. *lpData = lData;
  119. }
  120. return OLE_OK;
  121. }
  122. //////////////////////////////////////////////////////////////////////////////
  123. //
  124. // OLESTATUS FAR PASCAL LeQueryReleaseStatus (lpoleobj)
  125. //
  126. //
  127. // Returns whether a given object is still processing a previous
  128. // asynchronous command. returns OLE_BUSY if the object is still
  129. // processing the previous command
  130. //
  131. // Arguments:
  132. //
  133. // lpoleobj - ole object pointer
  134. //
  135. // Returns:
  136. //
  137. // OLE_BUSY - object is busy
  138. // OLE_OK - not busy
  139. //
  140. // Effects:
  141. //
  142. //////////////////////////////////////////////////////////////////////////////
  143. OLESTATUS FAR PASCAL LeQueryReleaseStatus (LPOLEOBJECT lpoleobj)
  144. {
  145. LPOBJECT_LE lpobj = (LPOBJECT_LE)lpoleobj;
  146. // probe async will clean up the channels
  147. // if the server died.
  148. PROBE_ASYNC (lpobj);
  149. return OLE_OK;
  150. }
  151. //////////////////////////////////////////////////////////////////////////////
  152. //
  153. // OLESTATUS FAR PASCAL LeQueryReleaseError (lpoleobj)
  154. //
  155. // returns the errors of an asynchronous command.
  156. //
  157. // Arguments:
  158. //
  159. // lpoleobj - ole object pointer
  160. //
  161. // Returns:
  162. //
  163. // OLE_ERROR_.. - if there is any error
  164. // OLE_OK - no error
  165. //
  166. // Note: This api is typically valid only during the callback of
  167. // OLE_RELEASE.
  168. //
  169. //////////////////////////////////////////////////////////////////////////////
  170. OLESTATUS FAR PASCAL LeQueryReleaseError (LPOLEOBJECT lpoleobj)
  171. {
  172. LPOBJECT_LE lpobj = (LPOBJECT_LE)lpoleobj;
  173. return lpobj->mainErr;
  174. }
  175. //////////////////////////////////////////////////////////////////////////////
  176. //
  177. // OLE_RELEASE_METHOD FAR PASCAL LeQueryReleaseMethod (lpoleobj)
  178. //
  179. // returns the method/command of the asynchronous command which
  180. // resulted in the OLE_RELEASE call back.
  181. //
  182. // Arguments:
  183. //
  184. // lpoleobj - ole object pointer
  185. //
  186. // Returns:
  187. // OLE_RELEASE_METHOD
  188. //
  189. // Note: This api is typically valid only during the callback of
  190. // OLE_RELEASE. Using this api, clients can decide which previous
  191. // asynchronous command resulted in OLE_RELEASE.
  192. //
  193. //////////////////////////////////////////////////////////////////////////////
  194. OLE_RELEASE_METHOD FAR PASCAL LeQueryReleaseMethod (LPOLEOBJECT lpoleobj)
  195. {
  196. LPOBJECT_LE lpobj = (LPOBJECT_LE)lpoleobj;
  197. return lpobj->oldasyncCmd;
  198. }
  199. //////////////////////////////////////////////////////////////////////////////
  200. //
  201. // LPVOID FARINTERNAL LeQueryProtocol (lpoleobj, lpprotocol)
  202. //
  203. // Given an oject, returns the new object handle for the new protocol.
  204. // Does the conversion of objects from one protocol to another one.
  205. //
  206. // Arguments:
  207. //
  208. // lpoleobj - ole object pointer
  209. // lpprotocol - ptr to new protocol string
  210. //
  211. // Returns:
  212. // lpobj - New object handle
  213. // null - if the protocol is not supported.
  214. //
  215. //
  216. //////////////////////////////////////////////////////////////////////////////
  217. LPVOID FARINTERNAL LeQueryProtocol (
  218. LPOLEOBJECT lpoleobj,
  219. OLE_LPCSTR lpprotocol
  220. ){
  221. LPOBJECT_LE lpobj = (LPOBJECT_LE)lpoleobj;
  222. if (lpobj->bOldLink)
  223. return NULL;
  224. if (!lstrcmp (lpprotocol, PROTOCOL_EDIT))
  225. return lpobj;
  226. if (!lstrcmp (lpprotocol, PROTOCOL_EXECUTE)) {
  227. if (UtilQueryProtocol (lpobj, lpprotocol))
  228. return lpobj;
  229. return NULL;
  230. }
  231. return NULL;
  232. }
  233. //////////////////////////////////////////////////////////////////////////////
  234. //
  235. // OLESTATUS EmbLnkDelete (lpoleobj)
  236. //
  237. // Routine for the object termination/deletion. Schedules differnt
  238. // asynchronous commands depending on different conditions.
  239. // Arguments:
  240. //
  241. // Sends "StdClose" only if it is Ok to close the document. Sends
  242. // "StdExit" only if the server has to be unlaunched. Deletes the object
  243. // only if the original command is OLE_DELETE. No need to call back the
  244. // client if the deletion is internal.
  245. //
  246. // While delete, this routine is entered several times. EAIT_FOR_ASYNC_MSG
  247. // results in going back to from where it is called and the next DDE message
  248. // brings back the control to this routine.
  249. //
  250. // Arguments:
  251. //
  252. // lpobj - object pointer
  253. //
  254. // Returns:
  255. //
  256. //
  257. //////////////////////////////////////////////////////////////////////////////
  258. OLESTATUS FARINTERNAL EmbLnkDelete (LPOBJECT_LE lpobj)
  259. {
  260. HOBJECT hobj;
  261. switch (lpobj->subRtn) {
  262. case 0:
  263. SKIP_TO (!QueryClose (lpobj), step1);
  264. // Send "StdCloseDocument"
  265. SendStdClose (lpobj);
  266. WAIT_FOR_ASYNC_MSG (lpobj);
  267. case 1:
  268. step1:
  269. SETSTEP (lpobj, 1);
  270. // End the doc conversation
  271. TermDocConv (lpobj);
  272. WAIT_FOR_ASYNC_MSG (lpobj);
  273. case 2:
  274. // delete the doc edit block. It is Ok even if the object
  275. // is not actually getting deleted.
  276. DeleteDocEdit (lpobj);
  277. // if need to unluanch the app, send stdexit.
  278. SKIP_TO (!QueryUnlaunch (lpobj), step3);
  279. SendStdExit (lpobj);
  280. WAIT_FOR_ASYNC_MSG (lpobj);
  281. case 3:
  282. step3:
  283. SETSTEP (lpobj, 3);
  284. // Do not set any errors.
  285. // Terminate the server conversation.
  286. TermSrvrConv (lpobj);
  287. WAIT_FOR_ASYNC_MSG (lpobj);
  288. case 4:
  289. // delete the server edit block
  290. DeleteSrvrEdit (lpobj);
  291. if (lpobj->asyncCmd != OLE_DELETE) {
  292. // if this delete is called because of unlauncinh of
  293. // object because of some error, no need to
  294. // call end asynchronous. It should have been already
  295. // called from somewhere else.
  296. if (lpobj->asyncCmd == OLE_SERVERUNLAUNCH){
  297. // send the async cmd;
  298. CLEARASYNCCMD (lpobj);
  299. } else
  300. EndAsyncCmd (lpobj);
  301. return OLE_OK;
  302. }
  303. // for real delete delete the atoms and space.
  304. DeleteObjectAtoms (lpobj);
  305. if (lpobj->lpobjPict)
  306. (*lpobj->lpobjPict->lpvtbl->Delete) (lpobj->lpobjPict);
  307. if (lpobj->hnative)
  308. GlobalFree (lpobj->hnative);
  309. if (lpobj->hLink)
  310. GlobalFree (lpobj->hLink);
  311. if (lpobj->hhostNames)
  312. GlobalFree (lpobj->hhostNames);
  313. if (lpobj->htargetDevice)
  314. GlobalFree (lpobj->htargetDevice);
  315. if (lpobj->hdocDimensions)
  316. GlobalFree (lpobj->hdocDimensions);
  317. DeleteExtraData (lpobj);
  318. DocDeleteObject ((LPOLEOBJECT) lpobj);
  319. // send the async cmd;
  320. EndAsyncCmd (lpobj);
  321. if (lpobj->head.iTable != INVALID_INDEX)
  322. DecreaseHandlerObjCount (lpobj->head.iTable);
  323. hobj = lpobj->head.hobj;
  324. ASSERT (hobj, "Object handle NULL in delete")
  325. GlobalUnlock (hobj);
  326. GlobalFree (hobj);
  327. return OLE_OK;
  328. }
  329. return OLE_ERROR_GENERIC;
  330. }
  331. //////////////////////////////////////////////////////////////////////////////
  332. //
  333. // OLESTATUS FARINTERNAL LeRelease (lpoleobj)
  334. //
  335. // Deletes the given object. This is can be asynchronous operation.
  336. //
  337. // Arguments:
  338. //
  339. // lpoleobj - ole object pointer
  340. //
  341. // Returns:
  342. //
  343. // OLE_WAIT_FOR_RELASE: If any DDE_TRANSACTIONS have been queued
  344. // OLE_OK : If deletion successfully
  345. // OLE_ERROR_... : If any error
  346. //
  347. //////////////////////////////////////////////////////////////////////////////
  348. OLESTATUS FARINTERNAL LeRelease (LPOLEOBJECT lpoleobj)
  349. {
  350. LPOBJECT_LE lpobj = (LPOBJECT_LE) lpoleobj;
  351. // For delete allow if the object has been aborted.
  352. PROBE_ASYNC (lpobj);
  353. // reset the flags so that we do not delete the object based on the old
  354. // flags
  355. lpobj->fCmd = 0;
  356. InitAsyncCmd (lpobj, OLE_DELETE, EMBLNKDELETE);
  357. return EmbLnkDelete (lpobj);
  358. }
  359. //////////////////////////////////////////////////////////////////////////////
  360. //
  361. // OLESTATUS FARINTERNAL LeClone (lpoleobjsrc, lpclient, lhclientdoc, lpobjname, lplpobj)
  362. //
  363. // Clones a given object.
  364. //
  365. // Arguments:
  366. //
  367. // lpoleobjsrc: ptr to the src object.
  368. // lpclient: client callback handle
  369. // lhclientdoc: doc handle
  370. // lpobjname: object name
  371. // lplpobj: holder for returning object.
  372. //
  373. // Returns:
  374. // OLE_OK : successful
  375. // OLE_ERROR_... : error
  376. //
  377. // Note: If the object being cloned is connected to the server, then
  378. // the cloned object is not connected to the server. For linked
  379. // objects, OleConnect has to be called.
  380. //
  381. //
  382. //////////////////////////////////////////////////////////////////////////////
  383. OLESTATUS FARINTERNAL LeClone (
  384. LPOLEOBJECT lpoleobjsrc,
  385. LPOLECLIENT lpclient,
  386. LHCLIENTDOC lhclientdoc,
  387. OLE_LPCSTR lpobjname,
  388. LPOLEOBJECT FAR * lplpoleobj
  389. ){
  390. LPOBJECT_LE lpobjsrc = (LPOBJECT_LE) lpoleobjsrc;
  391. LPOBJECT_LE lpobj = (LPOBJECT_LE) NULL;
  392. int retval = OLE_ERROR_MEMORY;
  393. // Assumes all the creates are in order
  394. // PROBE_OBJECT_BLANK(lpobjsrc);
  395. PROBE_CREATE_ASYNC(lpobjsrc);
  396. if (!(lpobj = LeCreateBlank(lhclientdoc, (LPSTR)lpobjname,
  397. lpobjsrc->head.ctype)))
  398. goto errRtn;
  399. lpobj->head.lpclient = lpclient;
  400. lpobj->head.iTable = lpobjsrc->head.iTable; //!!! dll loading
  401. lpobj->head.lpvtbl = lpobjsrc->head.lpvtbl;
  402. // set the atoms.
  403. lpobj->app = DuplicateAtom (lpobjsrc->app);
  404. lpobj->topic = DuplicateAtom (lpobjsrc->topic);
  405. lpobj->item = DuplicateAtom (lpobjsrc->item);
  406. lpobj->aServer = DuplicateAtom (lpobjsrc->aServer);
  407. lpobj->bOleServer = lpobjsrc->bOleServer;
  408. lpobj->verb = lpobjsrc->verb;
  409. lpobj->fCmd = lpobjsrc->fCmd;
  410. lpobj->aNetName = DuplicateAtom (lpobjsrc->aNetName);
  411. lpobj->cDrive = lpobjsrc->cDrive;
  412. lpobj->dwNetInfo = lpobjsrc->dwNetInfo;
  413. if (lpobjsrc->htargetDevice)
  414. lpobj->htargetDevice = DuplicateGlobal (lpobjsrc->htargetDevice,
  415. GMEM_MOVEABLE);
  416. if (lpobjsrc->head.ctype == CT_EMBEDDED) {
  417. if (lpobjsrc->hnative) {
  418. if (!(lpobj->hnative = DuplicateGlobal (lpobjsrc->hnative,
  419. GMEM_MOVEABLE)))
  420. goto errRtn;
  421. }
  422. if (lpobjsrc->hdocDimensions)
  423. lpobj->hdocDimensions = DuplicateGlobal (lpobjsrc->hdocDimensions,
  424. GMEM_MOVEABLE);
  425. if (lpobjsrc->hlogpal)
  426. lpobj->hlogpal = DuplicateGlobal (lpobjsrc->hlogpal,
  427. GMEM_MOVEABLE);
  428. SetEmbeddedTopic (lpobj);
  429. }
  430. else {
  431. lpobj->bOldLink = lpobjsrc->bOldLink;
  432. lpobj->optUpdate = lpobjsrc->optUpdate;
  433. }
  434. retval = OLE_OK;
  435. // if picture is needed clone the picture object.
  436. if ((!lpobjsrc->lpobjPict) ||
  437. ((retval = (*lpobjsrc->lpobjPict->lpvtbl->Clone)(lpobjsrc->lpobjPict,
  438. lpclient, lhclientdoc, lpobjname,
  439. (LPOLEOBJECT FAR *)&lpobj->lpobjPict))
  440. == OLE_OK)) {
  441. SetExtents (lpobj);
  442. *lplpoleobj = (LPOLEOBJECT)lpobj;
  443. if (lpobj->lpobjPict)
  444. lpobj->lpobjPict->lpParent = (LPOLEOBJECT) lpobj;
  445. }
  446. return retval;
  447. errRtn:
  448. // This oledelete should not result in any async communication.
  449. if (lpobj)
  450. OleDelete ((LPOLEOBJECT)lpobj);
  451. return retval;
  452. }
  453. //////////////////////////////////////////////////////////////////////////////
  454. //
  455. // OLESTATUS FARINTERNAL LeCopyFromLink (lpoleobjsrc, lpclient, lhclientdoc, lpobjname, lplpobj)
  456. //
  457. // Creates an embedded object from a lonked object. If the linked object
  458. // is not activated, then launches the server, gets the native data and
  459. // unlaunches the server. All these operations are done silently.
  460. //
  461. // Arguments:
  462. //
  463. // lpoleobjsrc: ptr to the src object.
  464. // lpclient: client callback handle
  465. // lhclientdoc: doc handle
  466. // lpobjname: object name
  467. // lplpobj: holder for returning object.
  468. //
  469. // Returns:
  470. // OLE_OK : successful
  471. // OLE_ERROR_... : error
  472. // OLE_WAITF_FOR_RELEASE : if DDE transcation is queued
  473. //
  474. // Note: Could result in asynchronous operation if there is any
  475. // DDE operaion involved in getting any data from the server.
  476. //
  477. // Also, If there is any error in getting the native data, the
  478. // client is expected delete the object after the OLE_RELEASE
  479. // call back
  480. //
  481. //////////////////////////////////////////////////////////////////////////////
  482. OLESTATUS FARINTERNAL LeCopyFromLink (
  483. LPOLEOBJECT lpoleobjsrc,
  484. LPOLECLIENT lpclient,
  485. LHCLIENTDOC lhclientdoc,
  486. OLE_LPCSTR lpobjname,
  487. LPOLEOBJECT FAR * lplpoleobj
  488. ){
  489. LPOBJECT_LE lpobjsrc = (LPOBJECT_LE)lpoleobjsrc;
  490. LPOBJECT_LE lpobj;
  491. int retval;
  492. *lplpoleobj = (LPOLEOBJECT)NULL;
  493. PROBE_OLDLINK (lpobjsrc);
  494. if (lpobjsrc->head.ctype != CT_LINK)
  495. return OLE_ERROR_NOT_LINK;
  496. PROBE_ASYNC (lpobjsrc);
  497. PROBE_SVRCLOSING(lpobjsrc);
  498. if ((retval = LeClone ((LPOLEOBJECT)lpobjsrc, lpclient, lhclientdoc, lpobjname,
  499. (LPOLEOBJECT FAR *)&lpobj)) != OLE_OK)
  500. return retval;
  501. // we successfully cloned the object. if picture object has native data
  502. // then grab it and put it in LE object. otherwise activate and get native
  503. // data also.
  504. if (lpobj->lpobjPict
  505. && (*lpobj->lpobjPict->lpvtbl->EnumFormats)
  506. (lpobj->lpobjPict, 0) == cfNative){
  507. // Now we know that the picture object is of native format, and it
  508. // means that it is a generic object. So grab the handle to native
  509. // data and put it in LE object.
  510. lpobj->hnative = ((LPOBJECT_GEN) (lpobj->lpobjPict))->hData;
  511. ((LPOBJECT_GEN) (lpobj->lpobjPict))->hData = (HANDLE)NULL;
  512. (*lpobj->lpobjPict->lpvtbl->Delete) (lpobj->lpobjPict);
  513. lpobj->lpobjPict = (LPOLEOBJECT)NULL;
  514. SetEmbeddedTopic (lpobj);
  515. *lplpoleobj = (LPOLEOBJECT)lpobj;
  516. return OLE_OK;
  517. } else {
  518. // if necessary launch, get native data and unlaunch the app.
  519. lpobj->fCmd = LN_LNKACT | ACT_REQUEST | ACT_NATIVE | (QueryOpen(lpobjsrc) ? ACT_TERMDOC : ACT_UNLAUNCH);
  520. InitAsyncCmd (lpobj, OLE_COPYFROMLNK, LNKOPENUPDATE);
  521. if ((retval = LnkOpenUpdate (lpobj)) > OLE_WAIT_FOR_RELEASE)
  522. LeRelease ((LPOLEOBJECT)lpobj);
  523. else
  524. *lplpoleobj = (LPOLEOBJECT)lpobj;
  525. return retval;
  526. // we will be changing the topic in end conversation.
  527. }
  528. }
  529. //////////////////////////////////////////////////////////////////////////////
  530. //
  531. // OLESTATUS FARINTERNAL LeEqual (lpoleobj1, lpoleobj2)
  532. //
  533. // Checks whethere two objects are equal. Checks for equality
  534. // of links, native data and picture data.
  535. //
  536. // Arguments:
  537. //
  538. // lpoleobj1: first object
  539. // lpoleobj2: second object
  540. //
  541. // Returns:
  542. // OLE_OK : equal
  543. // OLE_ERROR_NOT_EQUAL : if not equal
  544. // OLE_ERROR_..... : any errors
  545. //
  546. // Note: If any of the objects are connectd to the servers, leequal operaion
  547. // may not make much sense because the data might be changing from the
  548. // the server
  549. //
  550. //////////////////////////////////////////////////////////////////////////////
  551. OLESTATUS FARINTERNAL LeEqual (
  552. LPOLEOBJECT lpoleobj1,
  553. LPOLEOBJECT lpoleobj2
  554. ){
  555. LPOBJECT_LE lpobj1 = (LPOBJECT_LE)lpoleobj1;
  556. LPOBJECT_LE lpobj2 = (LPOBJECT_LE)lpoleobj2;
  557. if (lpobj1->app != lpobj2->app)
  558. return OLE_ERROR_NOT_EQUAL;
  559. // type of the objects is same. Otherwise this routine won't be called
  560. if (lpobj1->head.ctype == CT_LINK) {
  561. if (AreTopicsEqual (lpobj1, lpobj2) && (lpobj1->item == lpobj2->item))
  562. return OLE_OK;
  563. return OLE_ERROR_NOT_EQUAL;
  564. }
  565. else {
  566. ASSERT (lpobj1->head.ctype == CT_EMBEDDED, "Invalid ctype in LeEqual")
  567. if (lpobj1->item != lpobj2->item)
  568. return OLE_ERROR_NOT_EQUAL;
  569. if (CmpGlobals (lpobj1->hnative, lpobj2->hnative))
  570. return OLE_OK;
  571. else
  572. return OLE_ERROR_NOT_EQUAL;
  573. }
  574. //### we may have to compare the picture data also
  575. }
  576. //////////////////////////////////////////////////////////////////////////////
  577. //
  578. // OLESTATUS FARINTERNAL LeCopy (lpoleobj)
  579. //
  580. // Copies the object to the clipboard. Even for linked objects
  581. // we do not render the objectlink. It is up to the client app
  582. // to render object link
  583. //
  584. // Arguments:
  585. //
  586. // lpoleobj: object handle
  587. //
  588. // Returns:
  589. // OLE_OK : successful
  590. // OLE_ERROR_..... : any errors
  591. //
  592. // Note: Library does not open the clipboard. Client is supposed to
  593. // open the librray before this call is made
  594. //
  595. //////////////////////////////////////////////////////////////////////////////
  596. OLESTATUS FARINTERNAL LeCopy (LPOLEOBJECT lpoleobj)
  597. {
  598. LPOBJECT_LE lpobj = (LPOBJECT_LE)lpoleobj;
  599. HANDLE hlink = (HANDLE)NULL;
  600. HANDLE hnative = (HANDLE)NULL;
  601. PROBE_OLDLINK (lpobj);
  602. // Assumes all the creates are in order
  603. // PROBE_OBJECT_BLANK(lpobj);
  604. PROBE_CREATE_ASYNC(lpobj);
  605. if (lpobj->head.ctype == CT_EMBEDDED){
  606. if (!(hnative = DuplicateGlobal (lpobj->hnative, GMEM_MOVEABLE)))
  607. return OLE_ERROR_MEMORY;
  608. SetClipboardData (cfNative, hnative);
  609. }
  610. hlink = GetLink (lpobj);
  611. if (!(hlink = DuplicateGlobal (hlink, GMEM_MOVEABLE)))
  612. return OLE_ERROR_MEMORY;
  613. SetClipboardData (cfOwnerLink, hlink);
  614. // copy network name if it exists
  615. if (lpobj->head.ctype == CT_LINK && lpobj->aNetName) {
  616. HANDLE hNetName;
  617. if (hNetName = GetNetNameHandle (lpobj))
  618. SetClipboardData (cfNetworkName, hNetName);
  619. }
  620. if (lpobj->lpobjPict)
  621. return (*lpobj->lpobjPict->lpvtbl->CopyToClipboard)(lpobj->lpobjPict);
  622. return OLE_OK;
  623. }
  624. //////////////////////////////////////////////////////////////////////////////
  625. //
  626. // OLESTATUS FARINTERNAL LeQueryBounds (lpoleobj, lpRc)
  627. //
  628. // Returns the bounding rectangle of the object. Returns topleft
  629. // as zero always and the units are himetric units.
  630. //
  631. // Arguments:
  632. //
  633. // lpoleobj: object handle
  634. //
  635. // Returns:
  636. // OLE_OK : successful
  637. // OLE_ERROR_..... : any errors
  638. //
  639. // Note: Library does not open the clipboard. Client is supposed to
  640. // open the librray before this call is made
  641. //
  642. //////////////////////////////////////////////////////////////////////////////
  643. OLESTATUS FARINTERNAL LeQueryBounds (
  644. LPOLEOBJECT lpoleobj,
  645. LPRECT lpRc
  646. ){
  647. LPOBJECT_LE lpobj = (LPOBJECT_LE)lpoleobj;
  648. Puts("LeQueryBounds");
  649. // MM_HIMETRIC units
  650. lpRc->left = 0;
  651. lpRc->top = 0;
  652. lpRc->right = (int) lpobj->head.cx;
  653. lpRc->bottom = (int) lpobj->head.cy;
  654. if (lpRc->right || lpRc->bottom)
  655. return OLE_OK;
  656. if (!lpobj->lpobjPict)
  657. return OLE_ERROR_BLANK;
  658. return (*lpobj->lpobjPict->lpvtbl->QueryBounds) (lpobj->lpobjPict, lpRc);
  659. }
  660. //////////////////////////////////////////////////////////////////////////////
  661. //
  662. // OLESTATUS FARINTERNAL LeDraw (lpoleobj, hdc, lprc, lpWrc, hdcTarget)
  663. //
  664. // Draws the object. Calls the picture object for drawing the object
  665. //
  666. //
  667. // Arguments:
  668. //
  669. // lpoleobj: source object
  670. // hdc: handle to dest dc. Could be metafile dc
  671. // lprc: rectangle into which the object should be drawn
  672. // should be in himetric units and topleft
  673. // could be nonzero.
  674. // hdctarget: Target dc for which the object should be drawn
  675. // (Ex: Draw metafile on the dest dc using the attributes
  676. // of traget dc).
  677. //
  678. // Returns:
  679. // OLE_OK : successful
  680. // OLE_ERROR_BLANK : no picture
  681. //
  682. //
  683. //////////////////////////////////////////////////////////////////////////////
  684. OLESTATUS FARINTERNAL LeDraw (
  685. LPOLEOBJECT lpoleobj,
  686. HDC hdc,
  687. OLE_CONST RECT FAR* lprc,
  688. OLE_CONST RECT FAR* lpWrc,
  689. HDC hdcTarget
  690. ){
  691. LPOBJECT_LE lpobj = (LPOBJECT_LE)lpoleobj;
  692. if (lpobj->lpobjPict)
  693. return (*lpobj->lpobjPict->lpvtbl->Draw) (lpobj->lpobjPict,
  694. hdc, lprc, lpWrc, hdcTarget);
  695. return OLE_ERROR_BLANK;
  696. }
  697. //////////////////////////////////////////////////////////////////////////////
  698. //
  699. // OLECLIPFORMAT FARINTERNAL LeEnumFormat (lpoleobj, cfFormat)
  700. //
  701. // Enumerates the object formats.
  702. //
  703. //
  704. // Arguments:
  705. //
  706. // lpoleobj : source object
  707. // cfFormat : ref fprmat
  708. //
  709. // Returns:
  710. // NULL : no more formats or if we do not understand the
  711. // given format.
  712. //
  713. // Note: Even if the object is connected, we do not enumerate all the formats
  714. // the server can render. Server protocol can render the format list
  715. // only on system channel. Object can be connected only on the doc
  716. // channel
  717. //
  718. //////////////////////////////////////////////////////////////////////////////
  719. OLECLIPFORMAT FARINTERNAL LeEnumFormat (
  720. LPOLEOBJECT lpoleobj,
  721. OLECLIPFORMAT cfFormat
  722. ){
  723. LPOBJECT_LE lpobj = (LPOBJECT_LE)lpoleobj;
  724. Puts("LeEnumFormat");
  725. ASSERT((lpobj->head.ctype == CT_LINK)||(lpobj->head.ctype == CT_EMBEDDED),
  726. "Invalid Object Type");
  727. // switch is not used because case won't take variable argument
  728. if (cfFormat == (OLECLIPFORMAT)NULL) {
  729. if (lpobj->head.ctype == CT_EMBEDDED)
  730. return cfNative;
  731. else
  732. return (lpobj->bOldLink ? cfLink : cfObjectLink);
  733. }
  734. if (cfFormat == cfNative) {
  735. if (lpobj->head.ctype == CT_EMBEDDED)
  736. return cfOwnerLink;
  737. else
  738. return 0;
  739. }
  740. if (cfFormat == cfObjectLink) {
  741. if (lpobj->aNetName)
  742. return cfNetworkName;
  743. else
  744. cfFormat = (OLECLIPFORMAT)NULL;
  745. }
  746. else if (cfFormat == cfOwnerLink || cfFormat == cfLink
  747. || cfFormat == cfNetworkName)
  748. cfFormat = (OLECLIPFORMAT)NULL;
  749. if (lpobj->lpobjPict)
  750. return (*lpobj->lpobjPict->lpvtbl->EnumFormats) (lpobj->lpobjPict, cfFormat);
  751. return 0;
  752. }
  753. ////////////////////////////////////////////////////////////////////////////////
  754. //
  755. //
  756. // OLESTATUS FARINTERNAL LeRequestData (lpoleobj, cfFormat)
  757. //
  758. // Requests data from the server for a given format, if the server
  759. // is connected. If the server is not connected returns error.
  760. //
  761. //
  762. // Arguments:
  763. //
  764. // lpoleobj: source object
  765. // cfFormat: ref fprmat
  766. //
  767. // Returns:
  768. // OLE_WAIT_FOR_RELEASE : If the data request data is sent to
  769. // the server.
  770. // OLE_ERROR_NOT_OPEN : Server is not open for data
  771. //
  772. // Note: If the server is ready, sends request to the server. When the
  773. // the data comes back from the server OLE_DATA_READY is sent in
  774. // the callback and the client can use Getdata to get the data.
  775. //
  776. //
  777. //////////////////////////////////////////////////////////////////////////////
  778. OLESTATUS FARINTERNAL LeRequestData (
  779. LPOLEOBJECT lpoleobj,
  780. OLECLIPFORMAT cfFormat
  781. ){
  782. LPOBJECT_LE lpobj = (LPOBJECT_LE)lpoleobj;
  783. // Assumes all the creates are in order
  784. PROBE_ASYNC(lpobj);
  785. PROBE_SVRCLOSING(lpobj);
  786. if (!QueryOpen (lpobj))
  787. return OLE_ERROR_NOT_OPEN;
  788. if (cfFormat == cfOwnerLink || cfFormat == cfObjectLink)
  789. return OLE_ERROR_FORMAT;
  790. if (!(cfFormat == cfNative && lpobj->head.ctype == CT_EMBEDDED)
  791. && (cfFormat != (OLECLIPFORMAT) GetPictType (lpobj))) {
  792. DeleteExtraData (lpobj);
  793. lpobj->cfExtra = cfFormat;
  794. }
  795. InitAsyncCmd (lpobj, OLE_REQUESTDATA, REQUESTDATA);
  796. lpobj->pDocEdit->bCallLater = FALSE;
  797. return RequestData(lpobj, cfFormat);
  798. }
  799. OLESTATUS RequestData (
  800. LPOBJECT_LE lpobj,
  801. OLECLIPFORMAT cfFormat
  802. ){
  803. switch (lpobj->subRtn) {
  804. case 0:
  805. RequestOn (lpobj, cfFormat);
  806. WAIT_FOR_ASYNC_MSG (lpobj);
  807. case 1:
  808. ProcessErr (lpobj);
  809. return EndAsyncCmd (lpobj);
  810. default:
  811. ASSERT (TRUE, "unexpected step in Requestdata");
  812. return OLE_ERROR_GENERIC;
  813. }
  814. }
  815. ////////////////////////////////////////////////////////////////////////////////
  816. //
  817. //
  818. // OLESTATUS FARINTERNAL LeGetData (lpoleobj, cfFormat, lphandle)
  819. //
  820. // Returns the data handle for a given format
  821. //
  822. // Arguments:
  823. //
  824. // lpoleobj: source object
  825. // cfFormat: ref fprmat
  826. // lphandle: handle return
  827. //
  828. // Returns:
  829. // NULL : no more formats or if we do not understand the
  830. // given format.
  831. //
  832. // Note: Even if the object is connected, we do not get the data from the
  833. // server. Getdata can not be used for getting data in any other
  834. // format other than the formats available with the object on
  835. // the client side.
  836. //
  837. //////////////////////////////////////////////////////////////////////////////
  838. OLESTATUS FARINTERNAL LeGetData (
  839. LPOLEOBJECT lpoleobj,
  840. OLECLIPFORMAT cfFormat,
  841. LPHANDLE lphandle
  842. ){
  843. LPOBJECT_LE lpobj = (LPOBJECT_LE)lpoleobj;
  844. // Assumes all the creates are in order
  845. // PROBE_OBJECT_BLANK(lpobj);
  846. PROBE_CREATE_ASYNC(lpobj);
  847. *lphandle = (HANDLE)NULL;
  848. // The assumption made here is that the native data can be in either
  849. // LE object or picture object.
  850. if ((cfFormat == cfNative) && (lpobj->hnative)) {
  851. ASSERT ((lpobj->head.ctype == CT_EMBEDDED) || (!lpobj->lpobjPict) ||
  852. ((*lpobj->lpobjPict->lpvtbl->EnumFormats) (lpobj->lpobjPict, NULL)
  853. != cfNative), "Native data at wrong Place");
  854. *lphandle = lpobj->hnative;
  855. return OLE_OK;
  856. }
  857. if (cfFormat == cfOwnerLink && lpobj->head.ctype == CT_EMBEDDED) {
  858. if (*lphandle = GetLink (lpobj))
  859. return OLE_OK;
  860. return OLE_ERROR_BLANK;
  861. }
  862. if ((cfFormat == cfObjectLink || cfFormat == cfLink) &&
  863. lpobj->head.ctype == CT_LINK) {
  864. if (*lphandle = GetLink (lpobj))
  865. return OLE_OK;
  866. return OLE_ERROR_BLANK;
  867. }
  868. if (cfFormat == cfNetworkName) {
  869. if (lpobj->aNetName && (*lphandle = GetNetNameHandle (lpobj)))
  870. return OLE_WARN_DELETE_DATA;
  871. return OLE_ERROR_BLANK;
  872. }
  873. if (cfFormat == (OLECLIPFORMAT)lpobj->cfExtra) {
  874. if (*lphandle = lpobj->hextraData)
  875. return OLE_OK;
  876. return OLE_ERROR_BLANK;
  877. }
  878. if (!lpobj->lpobjPict && cfFormat)
  879. return OLE_ERROR_FORMAT;
  880. return (*lpobj->lpobjPict->lpvtbl->GetData) (lpobj->lpobjPict, cfFormat, lphandle);
  881. }
  882. OLESTATUS FARINTERNAL LeQueryOutOfDate (LPOLEOBJECT lpoleobj)
  883. {
  884. UNREFERENCED_PARAMETER(lpoleobj);
  885. return OLE_OK;
  886. }
  887. ////////////////////////////////////////////////////////////////////////////////
  888. //
  889. // OLESTATUS FARINTERNAL LeObjectConvert (lpoleobj, lpprotocol, lpclient, lhclientdoc, lpobjname, lplpobj)
  890. //
  891. // Converts a given linked/embedded object to static object.
  892. //
  893. // Arguments:
  894. // lpoleobj : source object
  895. // lpprotocol : protocol
  896. // lpclient : client callback for the new object
  897. // lhclientdoc: client doc
  898. // lpobjname : object name
  899. // lplpoleobj : object return
  900. //
  901. //
  902. // Returns:
  903. // OLE_OK : successful
  904. // OLE_ERROR_.... : any errors
  905. //
  906. //////////////////////////////////////////////////////////////////////////////
  907. OLESTATUS FARINTERNAL LeObjectConvert (
  908. LPOLEOBJECT lpoleobj,
  909. LPCSTR lpprotocol,
  910. LPOLECLIENT lpclient,
  911. LHCLIENTDOC lhclientdoc,
  912. LPCSTR lpobjname,
  913. LPOLEOBJECT FAR * lplpoleobj
  914. ){
  915. LPOBJECT_LE lpobj = (LPOBJECT_LE)lpoleobj;
  916. OLESTATUS retVal;
  917. PROBE_ASYNC (lpobj);
  918. *lplpoleobj = (LPOLEOBJECT)NULL;
  919. if (lstrcmp (lpprotocol, PROTOCOL_STATIC))
  920. return OLE_ERROR_PROTOCOL;
  921. if (!lpobj->lpobjPict ||
  922. ((*lpobj->lpobjPict->lpvtbl->QueryType) (lpobj->lpobjPict, NULL)
  923. == OLE_ERROR_GENERIC)) {
  924. // Either no picture object or non-standard picture object.
  925. // Create a metafile Object.
  926. HDC hMetaDC;
  927. RECT rc;
  928. HANDLE hMF = (HANDLE)NULL, hmfp = (HANDLE)NULL;
  929. LPMETAFILEPICT lpmfp;
  930. OleQueryBounds ((LPOLEOBJECT) lpobj, &rc);
  931. if (!(hMetaDC = CreateMetaFile (NULL)))
  932. goto Cleanup;
  933. MSetWindowOrg (hMetaDC, rc.left, rc.top);
  934. MSetWindowExt (hMetaDC, rc.right - rc.left, rc.bottom - rc.top);
  935. retVal = OleDraw ((LPOLEOBJECT) lpobj, hMetaDC, &rc, &rc, NULL);
  936. hMF = CloseMetaFile (hMetaDC);
  937. if ((retVal != OLE_OK) || !hMF)
  938. goto Cleanup;
  939. if (!(hmfp = GlobalAlloc (GMEM_MOVEABLE, sizeof (METAFILEPICT))))
  940. goto Cleanup;
  941. if (!(lpmfp = (LPMETAFILEPICT) GlobalLock (hmfp)))
  942. goto Cleanup;
  943. lpmfp->hMF = hMF;
  944. lpmfp->mm = MM_ANISOTROPIC;
  945. lpmfp->xExt = rc.right - rc.left;
  946. lpmfp->yExt = rc.top - rc.bottom;
  947. GlobalUnlock (hmfp);
  948. if (*lplpoleobj = (LPOLEOBJECT) MfCreateObject (hmfp, lpclient, TRUE,
  949. lhclientdoc, lpobjname, CT_STATIC))
  950. return OLE_OK;
  951. Cleanup:
  952. if (hMF)
  953. DeleteMetaFile (hMF);
  954. if (hmfp)
  955. GlobalFree (hmfp);
  956. return OLE_ERROR_MEMORY;
  957. }
  958. // Picture object is one of the standard objects
  959. if ((retVal = (*lpobj->lpobjPict->lpvtbl->Clone) (lpobj->lpobjPict,
  960. lpclient, lhclientdoc,
  961. lpobjname, lplpoleobj)) == OLE_OK) {
  962. (*lplpoleobj)->ctype = CT_STATIC;
  963. DocAddObject ((LPCLIENTDOC) lhclientdoc, *lplpoleobj, lpobjname);
  964. }
  965. return retVal;
  966. }
  967. // internal method used for changing picture/native data
  968. OLESTATUS FARINTERNAL LeChangeData (
  969. LPOLEOBJECT lpoleobj,
  970. HANDLE hnative,
  971. LPOLECLIENT lpoleclient,
  972. BOOL fDelete
  973. ){
  974. LPOBJECT_LE lpobj = (LPOBJECT_LE)lpoleobj;
  975. UNREFERENCED_PARAMETER(lpoleclient);
  976. if (!fDelete) {
  977. if (!(hnative = DuplicateGlobal (hnative, GMEM_MOVEABLE)))
  978. return OLE_ERROR_MEMORY;
  979. }
  980. // In case of a CopyFromLink, eventhough the object type is CT_LINK, the
  981. // native data should go to LE object rather than the picture object, as
  982. // we are going to change the object type to embedded after the required
  983. // data is recieved.
  984. if ((lpobj->head.ctype == CT_LINK)
  985. && (lpobj->asyncCmd != OLE_COPYFROMLNK)
  986. && (lpobj->asyncCmd != OLE_CREATEFROMFILE)) {
  987. if (lpobj->lpobjPict)
  988. return (*lpobj->lpobjPict->lpvtbl->SetData)
  989. (lpobj->lpobjPict, cfNative, hnative);
  990. }
  991. else { // It must be embedded.
  992. if (lpobj->hnative)
  993. GlobalFree (lpobj->hnative);
  994. lpobj->hnative = hnative;
  995. return OLE_OK;
  996. }
  997. GlobalFree(hnative);
  998. return OLE_ERROR_BLANK;
  999. }
  1000. ////////////////////////////////////////////////////////////////////////////////
  1001. //
  1002. // LPOBJECT_LE FARINTERNAL LeCreateBlank (lhclientdoc, lpobjname, ctype)
  1003. //
  1004. // Create a blank object. Global block is used for the object and it is
  1005. // locked once sucessful. Unlocking is done only while deletion. Object
  1006. // is added to the corresponding doc.
  1007. //
  1008. // 'LE' signature is used for object validation.
  1009. //
  1010. // Arguments:
  1011. // lhclientdoc : client doc handle
  1012. // lpobjname : object name
  1013. // ctype : type of object to be created
  1014. //
  1015. // Returns:
  1016. // LPOBJECT : successful
  1017. // NULL : any errors
  1018. //
  1019. //////////////////////////////////////////////////////////////////////////////
  1020. LPOBJECT_LE FARINTERNAL LeCreateBlank (
  1021. LHCLIENTDOC lhclientdoc,
  1022. LPSTR lpobjname,
  1023. LONG ctype
  1024. ){
  1025. HOBJECT hobj;
  1026. LPOBJECT_LE lpobj;
  1027. if (!(ctype == CT_LINK || ctype == CT_EMBEDDED || ctype == CT_OLDLINK))
  1028. return NULL;
  1029. if (!(hobj = GlobalAlloc (GMEM_MOVEABLE|GMEM_ZEROINIT,
  1030. sizeof (OBJECT_LE))))
  1031. return NULL;
  1032. if (!(lpobj = (LPOBJECT_LE) GlobalLock (hobj))) {
  1033. GlobalFree (hobj);
  1034. return NULL;
  1035. }
  1036. if (ctype == CT_OLDLINK) {
  1037. ctype = CT_LINK;
  1038. lpobj->bOldLink = TRUE;
  1039. }
  1040. lpobj->head.objId[0] = 'L';
  1041. lpobj->head.objId[1] = 'E';
  1042. lpobj->head.ctype = ctype;
  1043. lpobj->head.iTable = INVALID_INDEX;
  1044. lpobj->head.lpvtbl = (LPOLEOBJECTVTBL)&vtblLE;
  1045. if (ctype == CT_LINK){
  1046. lpobj->optUpdate = oleupdate_always;
  1047. }else {
  1048. lpobj->optUpdate = oleupdate_onclose;
  1049. }
  1050. lpobj->head.hobj = hobj;
  1051. DocAddObject ((LPCLIENTDOC) lhclientdoc, (LPOLEOBJECT) lpobj, lpobjname);
  1052. return lpobj;
  1053. }
  1054. void FARINTERNAL SetExtents (LPOBJECT_LE lpobj)
  1055. {
  1056. RECT rc = {0, 0, 0, 0};
  1057. if (lpobj->lpobjPict) {
  1058. if ((*lpobj->lpobjPict->lpvtbl->QueryBounds) (lpobj->lpobjPict,
  1059. (LPRECT)&rc) == OLE_OK) {
  1060. // Bounds are in MM_HIMETRIC units
  1061. lpobj->head.cx = (LONG) (rc.right - rc.left);
  1062. lpobj->head.cy = (LONG) (rc.bottom - rc.top);
  1063. }
  1064. return;
  1065. }
  1066. }
  1067. ////////////////////////////////////////////////////////////////////////////////
  1068. //
  1069. // OLESTATUS FARINTERNAL LeSaveToStream (lpoleobj, lpstream)
  1070. //
  1071. // Save the object to the stream. Uses the stream functions provided
  1072. // in the lpclient.
  1073. //
  1074. // Format: (!!! Document the fomrat here).
  1075. //
  1076. //
  1077. //
  1078. // Arguments:
  1079. // lpoleobj - pointer to ole object
  1080. // lpstream - pointer to stream
  1081. //
  1082. // Returns:
  1083. // LPOBJECT : successful
  1084. // NULL : any errors
  1085. //
  1086. //////////////////////////////////////////////////////////////////////////////
  1087. OLESTATUS FARINTERNAL LeSaveToStream (
  1088. LPOLEOBJECT lpoleobj,
  1089. LPOLESTREAM lpstream
  1090. ){
  1091. DWORD dwFileVer = GetFileVersion(lpoleobj);
  1092. LPOBJECT_LE lpobj = (LPOBJECT_LE)lpoleobj;
  1093. // PROBE_OBJECT_BLANK(lpobj);
  1094. PROBE_CREATE_ASYNC(lpobj);
  1095. if (lpobj->head.ctype == CT_LINK && lpobj->bOldLink)
  1096. lpobj->head.ctype = CT_OLDLINK;
  1097. if (PutBytes (lpstream, (LPSTR) &dwFileVer, sizeof(LONG)))
  1098. return OLE_ERROR_STREAM;
  1099. if (PutBytes (lpstream, (LPSTR) &lpobj->head.ctype, sizeof(LONG)))
  1100. return OLE_ERROR_STREAM;
  1101. if (lpobj->bOldLink)
  1102. lpobj->head.ctype = CT_OLDLINK;
  1103. return LeStreamWrite (lpstream, lpobj);
  1104. }
  1105. ////////////////////////////////////////////////////////////////////////////////
  1106. //
  1107. // OLESTATUS FARINTERNAL LeLoadFromStream (lpstream, lpclient, lhclientdoc, lpobjname, lplpoleobject, ctype, aClass, cfFormat)
  1108. //
  1109. // Create an object, loading the object from the stream.
  1110. //
  1111. // Arguments:
  1112. // lpstream : stream table
  1113. // lpclient : client callback table
  1114. // lhclientdoc : Doc handle foe which the object should be created
  1115. // lpobjname : Object name
  1116. // lplpoleobject : object return
  1117. // ctype : Type of object
  1118. // aClass : class atom
  1119. // cfFormat : render format
  1120. //
  1121. // Returns:
  1122. // LPOBJECT : successful
  1123. // NULL : any errors
  1124. //
  1125. //////////////////////////////////////////////////////////////////////////////
  1126. OLESTATUS FARINTERNAL LeLoadFromStream (
  1127. LPOLESTREAM lpstream,
  1128. LPOLECLIENT lpclient,
  1129. LHCLIENTDOC lhclientdoc,
  1130. LPSTR lpobjname,
  1131. LPOLEOBJECT FAR * lplpoleobject,
  1132. LONG ctype,
  1133. ATOM aClass,
  1134. OLECLIPFORMAT cfFormat
  1135. ){
  1136. LPOBJECT_LE lpobj = (LPOBJECT_LE)NULL;
  1137. OLESTATUS retval = OLE_ERROR_STREAM;
  1138. LONG type; // this not same as ctype
  1139. char chVerb [80];
  1140. *lplpoleobject = (LPOLEOBJECT)NULL;
  1141. if (!(lpobj = LeCreateBlank (lhclientdoc, lpobjname, ctype)))
  1142. return OLE_ERROR_MEMORY;
  1143. lpobj->head.lpclient = lpclient;
  1144. lpobj->app = aClass;
  1145. // if the entry is present, then it is
  1146. lpobj->bOleServer = QueryVerb (lpobj, 0, (LPSTR)&chVerb, 80);
  1147. if (LeStreamRead (lpstream, lpobj) == OLE_OK) {
  1148. // Get exe name from aClass and set it as aServer
  1149. SetExeAtom (lpobj);
  1150. if (!GetBytes (lpstream, (LPSTR) &dwVerFromFile, sizeof(LONG))) {
  1151. if (!GetBytes (lpstream, (LPSTR) &type, sizeof(LONG))) {
  1152. if (type == CT_NULL)
  1153. retval = OLE_OK;
  1154. else if (aClass = GetAtomFromStream (lpstream)) {
  1155. retval = DefLoadFromStream (lpstream, NULL, lpclient,
  1156. lhclientdoc, lpobjname,
  1157. (LPOLEOBJECT FAR *)&lpobj->lpobjPict,
  1158. CT_PICTURE, aClass, cfFormat);
  1159. }
  1160. }
  1161. }
  1162. if (retval == OLE_OK) {
  1163. SetExtents (lpobj);
  1164. *lplpoleobject = (LPOLEOBJECT) lpobj;
  1165. if (lpobj->lpobjPict)
  1166. lpobj->lpobjPict->lpParent = (LPOLEOBJECT) lpobj;
  1167. if ((lpobj->head.ctype != CT_LINK)
  1168. || (!InitDocConv (lpobj, !POPUP_NETDLG))
  1169. || (lpobj->optUpdate >= oleupdate_oncall))
  1170. return OLE_OK;
  1171. lpobj->fCmd = ACT_ADVISE;
  1172. // If it's auto update, then get the latest data.
  1173. if (lpobj->optUpdate == oleupdate_always)
  1174. lpobj->fCmd |= ACT_REQUEST;
  1175. FarInitAsyncCmd (lpobj, OLE_LOADFROMSTREAM, LNKOPENUPDATE);
  1176. return LnkOpenUpdate (lpobj);
  1177. }
  1178. }
  1179. // This delete will not run into async command. We did not even
  1180. // even connect.
  1181. OleDelete ((LPOLEOBJECT) lpobj);
  1182. return OLE_ERROR_STREAM;
  1183. }
  1184. //
  1185. OLESTATUS INTERNAL LeStreamRead (
  1186. LPOLESTREAM lpstream,
  1187. LPOBJECT_LE lpobj
  1188. ){
  1189. DWORD dwBytes;
  1190. LPSTR lpstr;
  1191. OLESTATUS retval = OLE_OK;
  1192. if (!(lpobj->topic = GetAtomFromStream(lpstream))
  1193. && (lpobj->head.ctype != CT_EMBEDDED))
  1194. return OLE_ERROR_STREAM;
  1195. // !!! This atom could be NULL. How do we distinguish the
  1196. // error case
  1197. lpobj->item = GetAtomFromStream(lpstream);
  1198. if (lpobj->head.ctype == CT_EMBEDDED) {
  1199. if (GetBytes (lpstream, (LPSTR) &dwBytes, sizeof(LONG)))
  1200. return OLE_ERROR_STREAM;
  1201. if (!(lpobj->hnative = GlobalAlloc (GMEM_MOVEABLE, dwBytes)))
  1202. return OLE_ERROR_MEMORY;
  1203. else if (!(lpstr = GlobalLock (lpobj->hnative))) {
  1204. GlobalFree (lpobj->hnative);
  1205. return OLE_ERROR_MEMORY;
  1206. }
  1207. else {
  1208. if (GetBytes(lpstream, lpstr, dwBytes))
  1209. retval = OLE_ERROR_STREAM;
  1210. GlobalUnlock (lpobj->hnative);
  1211. }
  1212. if (retval == OLE_OK)
  1213. SetEmbeddedTopic (lpobj);
  1214. }
  1215. else {
  1216. if (lpobj->aNetName = GetAtomFromStream (lpstream)) {
  1217. if (HIWORD(dwVerFromFile) == OS_MAC) {
  1218. // if it is a mac file this field will have "ZONE:MACHINE:"
  1219. // string. Lets prepend this to the topic, so that server
  1220. // app or user can fix the string
  1221. ATOM aTemp;
  1222. aTemp = wAtomCat (lpobj->aNetName, lpobj->topic);
  1223. GlobalDeleteAtom (lpobj->aNetName);
  1224. lpobj->aNetName = (ATOM)0;
  1225. GlobalDeleteAtom (lpobj->topic);
  1226. lpobj->topic = aTemp;
  1227. }
  1228. else
  1229. SetNetDrive (lpobj);
  1230. }
  1231. if (HIWORD(dwVerFromFile) != OS_MAC) {
  1232. if (GetBytes (lpstream, (LPSTR) &lpobj->dwNetInfo, sizeof(LONG)))
  1233. return OLE_ERROR_STREAM;
  1234. }
  1235. if (GetBytes (lpstream, (LPSTR) &lpobj->optUpdate, sizeof(LONG)))
  1236. return OLE_ERROR_STREAM;
  1237. }
  1238. return retval;
  1239. }
  1240. OLESTATUS INTERNAL LeStreamWrite (
  1241. LPOLESTREAM lpstream,
  1242. LPOBJECT_LE lpobj
  1243. ){
  1244. DWORD dwFileVer = GetFileVersion((LPOLEOBJECT)lpobj);
  1245. LPSTR lpstr;
  1246. DWORD dwBytes = 0L;
  1247. LONG nullType = CT_NULL;
  1248. int error;
  1249. if (PutAtomIntoStream(lpstream, lpobj->app))
  1250. return OLE_ERROR_STREAM;
  1251. if (lpobj->head.ctype == CT_EMBEDDED) {
  1252. // we set the topic at load time, no point in saving it
  1253. if (PutBytes (lpstream, (LPSTR) &dwBytes, sizeof(LONG)))
  1254. return OLE_ERROR_STREAM;
  1255. }
  1256. else {
  1257. if (PutAtomIntoStream(lpstream, lpobj->topic))
  1258. return OLE_ERROR_STREAM;
  1259. }
  1260. #ifdef OLD
  1261. if (PutAtomIntoStream(lpstream, lpobj->topic))
  1262. return OLE_ERROR_STREAM;
  1263. #endif
  1264. if (PutAtomIntoStream(lpstream, lpobj->item))
  1265. return OLE_ERROR_STREAM;
  1266. // !!! deal with objects > 64k
  1267. if (lpobj->head.ctype == CT_EMBEDDED) {
  1268. if (!lpobj->hnative)
  1269. return OLE_ERROR_BLANK;
  1270. // assumption low bytes are first
  1271. dwBytes = (DWORD)GlobalSize (lpobj->hnative);
  1272. if (PutBytes (lpstream, (LPSTR)&dwBytes, sizeof(LONG)))
  1273. return OLE_ERROR_STREAM;
  1274. if (!(lpstr = GlobalLock (lpobj->hnative)))
  1275. return OLE_ERROR_MEMORY;
  1276. error = PutBytes (lpstream, lpstr, dwBytes);
  1277. GlobalUnlock (lpobj->hnative);
  1278. if (error)
  1279. return OLE_ERROR_STREAM;
  1280. }
  1281. else {
  1282. if (PutAtomIntoStream(lpstream, lpobj->aNetName))
  1283. return OLE_ERROR_STREAM;
  1284. if (PutBytes (lpstream, (LPSTR) &lpobj->dwNetInfo, sizeof(LONG)))
  1285. return OLE_ERROR_STREAM;
  1286. if (PutBytes (lpstream, (LPSTR) &lpobj->optUpdate, sizeof(LONG)))
  1287. return OLE_ERROR_STREAM;
  1288. }
  1289. if (lpobj->lpobjPict)
  1290. return (*lpobj->lpobjPict->lpvtbl->SaveToStream) (lpobj->lpobjPict,
  1291. lpstream);
  1292. if (PutBytes (lpstream, (LPSTR) &dwFileVer, sizeof(LONG)))
  1293. return OLE_ERROR_STREAM;
  1294. if (PutBytes (lpstream, (LPSTR) &nullType, sizeof(LONG)))
  1295. return OLE_ERROR_STREAM;
  1296. return OLE_OK;
  1297. }
  1298. /***************************** Public Function ****************************\
  1299. * OLESTATUS FARINTERNAL LeQueryType (lpobj, lptype)
  1300. *
  1301. * Effects:
  1302. *
  1303. * History:
  1304. * Wrote it.
  1305. \***************************************************************************/
  1306. OLESTATUS FARINTERNAL LeQueryType (
  1307. LPOLEOBJECT lpoleobj,
  1308. LPLONG lptype
  1309. ){
  1310. LPOBJECT_LE lpobj = (LPOBJECT_LE)lpoleobj;
  1311. Puts("LeQueryType");
  1312. if ((lpobj->head.ctype == CT_EMBEDDED)
  1313. || (lpobj->asyncCmd == OLE_COPYFROMLNK)
  1314. || (lpobj->asyncCmd == OLE_CREATEFROMFILE))
  1315. *lptype = CT_EMBEDDED;
  1316. else if ((lpobj->head.ctype == CT_LINK)
  1317. || (lpobj->head.ctype == CT_OLDLINK))
  1318. *lptype = CT_LINK;
  1319. else
  1320. return OLE_ERROR_OBJECT;
  1321. return OLE_OK;
  1322. }
  1323. // ContextCallBack: internal function. Calls callback function of <hobj>
  1324. // with flags.
  1325. int FARINTERNAL ContextCallBack (
  1326. LPOLEOBJECT lpobj,
  1327. OLE_NOTIFICATION flags
  1328. ){
  1329. LPOLECLIENT lpclient;
  1330. Puts("ContextCallBack");
  1331. if (!FarCheckObject(lpobj))
  1332. return FALSE;
  1333. if (!(lpclient = lpobj->lpclient))
  1334. return FALSE;
  1335. ASSERT (lpclient->lpvtbl->CallBack, "Client Callback ptr is NULL");
  1336. return ((*lpclient->lpvtbl->CallBack) (lpclient, flags, lpobj));
  1337. }
  1338. void FARINTERNAL DeleteExtraData (LPOBJECT_LE lpobj)
  1339. {
  1340. if (lpobj->hextraData == (HANDLE)NULL)
  1341. return;
  1342. switch (lpobj->cfExtra) {
  1343. case CF_BITMAP:
  1344. DeleteObject (lpobj->hextraData);
  1345. break;
  1346. case CF_METAFILEPICT:
  1347. {
  1348. LPMETAFILEPICT lpmfp;
  1349. if (!(lpmfp = (LPMETAFILEPICT) GlobalLock (lpobj->hextraData)))
  1350. break;
  1351. DeleteMetaFile (lpmfp->hMF);
  1352. GlobalUnlock (lpobj->hextraData);
  1353. GlobalFree (lpobj->hextraData);
  1354. break;
  1355. }
  1356. default:
  1357. GlobalFree (lpobj->hextraData);
  1358. }
  1359. lpobj->hextraData = (HANDLE)NULL;
  1360. }
  1361. void INTERNAL DeleteObjectAtoms(LPOBJECT_LE lpobj)
  1362. {
  1363. if (lpobj->app) {
  1364. GlobalDeleteAtom (lpobj->app);
  1365. lpobj->app = (ATOM)0;
  1366. }
  1367. if (lpobj->topic) {
  1368. GlobalDeleteAtom (lpobj->topic);
  1369. lpobj->topic = (ATOM)0;
  1370. }
  1371. if (lpobj->item) {
  1372. GlobalDeleteAtom (lpobj->item);
  1373. lpobj->item = (ATOM)0;
  1374. }
  1375. if (lpobj->aServer) {
  1376. GlobalDeleteAtom (lpobj->aServer);
  1377. lpobj->aServer = (ATOM)0;
  1378. }
  1379. if (lpobj->aNetName) {
  1380. GlobalDeleteAtom (lpobj->aNetName);
  1381. lpobj->aNetName = (ATOM)0;
  1382. }
  1383. }
  1384. // LeGetUpdateOptions: Gets the update options.
  1385. OLESTATUS FARINTERNAL LeGetUpdateOptions (
  1386. LPOLEOBJECT lpoleobj,
  1387. OLEOPT_UPDATE FAR *lpOptions
  1388. ){
  1389. LPOBJECT_LE lpobj = (LPOBJECT_LE)lpoleobj;
  1390. if (lpobj->head.ctype != CT_LINK)
  1391. return OLE_ERROR_OBJECT;
  1392. *lpOptions = lpobj->optUpdate;
  1393. return OLE_OK;
  1394. }
  1395. OLESTATUS FARINTERNAL LnkPaste (
  1396. LPOLECLIENT lpclient,
  1397. LHCLIENTDOC lhclientdoc,
  1398. LPSTR lpobjname,
  1399. LPOLEOBJECT FAR * lplpoleobject,
  1400. OLEOPT_RENDER optRender,
  1401. OLECLIPFORMAT cfFormat,
  1402. OLECLIPFORMAT sfFormat
  1403. ){
  1404. LPOBJECT_LE lpobj = NULL;
  1405. OLESTATUS retval = OLE_ERROR_MEMORY;
  1406. LPSTR lpClass = NULL;
  1407. if (!(lpobj = LeCreateBlank (lhclientdoc, lpobjname, CT_LINK)))
  1408. goto errRtn;
  1409. lpobj->head.lpclient = lpclient;
  1410. #ifdef OLD
  1411. if (!bWLO) {
  1412. // we are not running under WLO
  1413. if (!(hInfo = GetClipboardData (sfFormat))) {
  1414. if (hInfo = GetClipboardData (cfLink))
  1415. lpobj->bOldLink = TRUE;
  1416. }
  1417. }
  1418. #endif
  1419. if (!hInfo)
  1420. goto errRtn;
  1421. if (!IsClipboardFormatAvailable (sfFormat))
  1422. lpobj->bOldLink = TRUE;
  1423. if (!SetLink (lpobj, hInfo, &lpClass))
  1424. goto errRtn;
  1425. if ((retval = SetNetName(lpobj)) != OLE_OK) {
  1426. // see whether network name is on the clipboard and try to use it
  1427. HANDLE hNetName;
  1428. LPSTR lpNetName;
  1429. if (!IsClipboardFormatAvailable (cfNetworkName))
  1430. goto errRtn;
  1431. if (!(hNetName = GetClipboardData (cfNetworkName)))
  1432. goto errRtn;
  1433. if (!(lpNetName = GlobalLock (hNetName)))
  1434. goto errRtn;
  1435. GlobalUnlock (hNetName);
  1436. if (!(lpobj->aNetName = GlobalAddAtom (lpNetName)))
  1437. goto errRtn;
  1438. SetNetDrive (lpobj);
  1439. }
  1440. retval = CreatePictFromClip (lpclient, lhclientdoc, lpobjname,
  1441. (LPOLEOBJECT FAR *)&lpobj->lpobjPict, optRender,
  1442. cfFormat, lpClass, CT_PICTURE);
  1443. if (retval == OLE_OK) {
  1444. SetExtents (lpobj);
  1445. // why do we have to update the link, do we show it?
  1446. // Reconnect if we could and advise for updates
  1447. *lplpoleobject = (LPOLEOBJECT)lpobj;
  1448. if (lpobj->lpobjPict)
  1449. lpobj->lpobjPict->lpParent = (LPOLEOBJECT) lpobj;
  1450. if (!InitDocConv (lpobj, !POPUP_NETDLG))
  1451. return OLE_OK; // document is not loaded , it is OK.
  1452. lpobj->fCmd = ACT_ADVISE | ACT_REQUEST;
  1453. FarInitAsyncCmd (lpobj, OLE_LNKPASTE, LNKOPENUPDATE);
  1454. return LnkOpenUpdate (lpobj);
  1455. }
  1456. else {
  1457. errRtn:
  1458. if (lpobj)
  1459. OleDelete ((LPOLEOBJECT)lpobj);
  1460. }
  1461. return retval;
  1462. }
  1463. // !!! EmbPaste and LnkPaste Can be combined
  1464. OLESTATUS FARINTERNAL EmbPaste (
  1465. LPOLECLIENT lpclient,
  1466. LHCLIENTDOC lhclientdoc,
  1467. LPSTR lpobjname,
  1468. LPOLEOBJECT FAR * lplpoleobject,
  1469. OLEOPT_RENDER optRender,
  1470. OLECLIPFORMAT cfFormat
  1471. ){
  1472. LPOBJECT_LE lpobj = NULL;
  1473. HANDLE hnative;
  1474. OLESTATUS retval = OLE_ERROR_MEMORY;
  1475. LPSTR lpClass = NULL;
  1476. if (!IsClipboardFormatAvailable (cfOwnerLink))
  1477. return OLE_ERROR_CLIPBOARD;
  1478. if (!(lpobj = LeCreateBlank (lhclientdoc, lpobjname, CT_EMBEDDED)))
  1479. goto errRtn;
  1480. lpobj->head.lpclient = lpclient;
  1481. #ifdef OLD
  1482. if (!bWLO) {
  1483. // we are not running under WLO
  1484. hInfo = GetClipboardData (cfOwnerLink);
  1485. }
  1486. #endif
  1487. if (!hInfo)
  1488. goto errRtn;
  1489. if (!SetLink (lpobj, hInfo, &lpClass))
  1490. goto errRtn;
  1491. SetEmbeddedTopic (lpobj);
  1492. hnative = GetClipboardData (cfNative);
  1493. if (!(lpobj->hnative = DuplicateGlobal (hnative, GMEM_MOVEABLE)))
  1494. goto errRtn;
  1495. retval = CreatePictFromClip (lpclient, lhclientdoc, lpobjname,
  1496. (LPOLEOBJECT FAR *)&lpobj->lpobjPict, optRender,
  1497. cfFormat, lpClass, CT_PICTURE);
  1498. if (retval == OLE_OK) {
  1499. SetExtents (lpobj);
  1500. *lplpoleobject = (LPOLEOBJECT) lpobj;
  1501. if (lpobj->lpobjPict)
  1502. lpobj->lpobjPict->lpParent = (LPOLEOBJECT) lpobj;
  1503. }
  1504. else {
  1505. errRtn:
  1506. // Note: This oledelete should not result in any async commands.
  1507. if (lpobj)
  1508. OleDelete ((LPOLEOBJECT)lpobj);
  1509. }
  1510. #ifdef EXCEL_BUG
  1511. // Some server apps (ex: Excel) copy picture (to clipboard) which is
  1512. // formatted for printer DC. So, we want to update the picture if the
  1513. // server app is running, and the it's a old server
  1514. if ((retval == OLE_OK) && (!lpobj->bOleServer)) {
  1515. lpobj->fCmd = LN_EMBACT | ACT_NOLAUNCH | ACT_REQUEST | ACT_UNLAUNCH;
  1516. FarInitAsyncCmd (lpobj, OLE_EMBPASTE, EMBOPENUPDATE);
  1517. if ((retval = EmbOpenUpdate (lpobj)) > OLE_WAIT_FOR_RELEASE)
  1518. return OLE_OK;
  1519. }
  1520. #endif
  1521. return retval;
  1522. }
  1523. BOOL INTERNAL SetLink (
  1524. LPOBJECT_LE lpobj,
  1525. HANDLE hinfo,
  1526. LPSTR FAR * lpLpClass
  1527. ){
  1528. LPSTR lpinfo;
  1529. char chVerb[80];
  1530. // If there exits a conversation, then terminate it.
  1531. if (!(lpinfo = GlobalLock (hinfo)))
  1532. return FALSE;
  1533. *lpLpClass = lpinfo;
  1534. #if FIREWALLS
  1535. if (lpobj->pDocEdit)
  1536. ASSERT (!lpobj->pDocEdit->hClient, "unexpected client conv exists");
  1537. #endif
  1538. lpobj->app = GlobalAddAtom (lpinfo);
  1539. SetExeAtom (lpobj);
  1540. lpobj->bOleServer = QueryVerb (lpobj, 0, (LPSTR)&chVerb, 80);
  1541. // lpobj->aServer = GetAppAtom (lpinfo);
  1542. lpinfo += lstrlen (lpinfo) + 1;
  1543. lpobj->topic = GlobalAddAtom (lpinfo);
  1544. lpinfo += lstrlen (lpinfo) + 1;
  1545. if (*lpinfo)
  1546. lpobj->item = GlobalAddAtom (lpinfo);
  1547. else
  1548. lpobj->item = (ATOM)0;
  1549. if (lpobj->hLink) { // As the atoms have already changed,
  1550. GlobalFree (lpobj->hLink); // lpobj->hLink becomes irrelevant.
  1551. lpobj->hLink = NULL;
  1552. }
  1553. if (lpinfo)
  1554. GlobalUnlock(hinfo);
  1555. if (!lpobj->app)
  1556. return FALSE;
  1557. if (!lpobj->topic && (lpobj->head.ctype == CT_LINK))
  1558. return FALSE;
  1559. lpobj->hLink = DuplicateGlobal (hinfo, GMEM_MOVEABLE);
  1560. return TRUE;
  1561. }
  1562. HANDLE INTERNAL GetLink (LPOBJECT_LE lpobj)
  1563. {
  1564. HANDLE hLink = NULL;
  1565. LPSTR lpLink;
  1566. int len;
  1567. WORD size;
  1568. if (lpobj->hLink)
  1569. return lpobj->hLink;
  1570. size = 4; // three nulls and one null at the end
  1571. size += (WORD)GlobalGetAtomLen (lpobj->app);
  1572. size += (WORD)GlobalGetAtomLen (lpobj->topic);
  1573. size += (WORD)GlobalGetAtomLen (lpobj->item);
  1574. if (!(hLink = GlobalAlloc (GMEM_MOVEABLE, (DWORD) size)))
  1575. return NULL;
  1576. if (!(lpLink = GlobalLock (hLink))) {
  1577. GlobalFree (hLink);
  1578. return NULL;
  1579. }
  1580. len = (int) GlobalGetAtomName (lpobj->app, lpLink, size);
  1581. lpLink += ++len;
  1582. len = (int) GlobalGetAtomName (lpobj->topic, lpLink, (size -= (WORD)len));
  1583. lpLink += ++len;
  1584. if (!lpobj->item)
  1585. *lpLink = '\0';
  1586. else {
  1587. len = (int) GlobalGetAtomName (lpobj->item, lpLink, size - len);
  1588. lpLink += len;
  1589. }
  1590. *++lpLink = '\0'; // put another null the end
  1591. GlobalUnlock (hLink);
  1592. return (lpobj->hLink = hLink);
  1593. }
  1594. void FARINTERNAL SetEmbeddedTopic (LPOBJECT_LE lpobj)
  1595. {
  1596. LPCLIENTDOC lpdoc;
  1597. char buf[MAX_STR];
  1598. char buf1[MAX_STR];
  1599. LPSTR lpstr, lptmp;
  1600. int len;
  1601. if (lpobj->topic)
  1602. GlobalDeleteAtom (lpobj->topic);
  1603. if (lpobj->aNetName) {
  1604. GlobalDeleteAtom (lpobj->aNetName);
  1605. lpobj->aNetName = (ATOM)0;
  1606. }
  1607. lpobj->cDrive = '\0';
  1608. lpobj->dwNetInfo = 0;
  1609. lpobj->head.ctype = CT_EMBEDDED;
  1610. lpdoc = (LPCLIENTDOC) lpobj->head.lhclientdoc;
  1611. lpstr = (LPSTR) buf;
  1612. lptmp = (LPSTR) buf1;
  1613. ASSERT(lpdoc->aDoc, "lpdoc->aDoc is null");
  1614. GlobalGetAtomName (lpdoc->aDoc, lpstr, sizeof(buf));
  1615. // strip the path
  1616. lpstr += (len = lstrlen(lpstr));
  1617. while (--lpstr != (LPSTR) buf) {
  1618. if ((*lpstr == '\\') || (*lpstr == ':')) {
  1619. lpstr++;
  1620. break;
  1621. }
  1622. }
  1623. GlobalGetAtomName (lpdoc->aClass, lptmp, sizeof(buf1));
  1624. lstrcat (lptmp, "%");
  1625. lstrcat (lptmp, lpstr);
  1626. lstrcat (lptmp, "%");
  1627. lpstr = lptmp;
  1628. lptmp += lstrlen (lptmp);
  1629. if (lpobj->head.aObjName) {
  1630. GlobalGetAtomName (lpobj->head.aObjName, lptmp, sizeof(buf)-(len+1));
  1631. }
  1632. if ((embStr[EMB_ID_INDEX] += 1) > '9') {
  1633. embStr[EMB_ID_INDEX] = '0';
  1634. if ((embStr[EMB_ID_INDEX - 1] += 1) > '9') {
  1635. embStr[EMB_ID_INDEX - 1] = '0';
  1636. if ((embStr[EMB_ID_INDEX - 2] += 1) > '9')
  1637. embStr[EMB_ID_INDEX - 2] = '0';
  1638. }
  1639. }
  1640. lstrcat (lptmp, embStr);
  1641. lpobj->topic = GlobalAddAtom (lpstr);
  1642. // Topic, item have changed, lpobj->hLink is out of date.
  1643. if (lpobj->hLink) {
  1644. GlobalFree (lpobj->hLink);
  1645. lpobj->hLink = NULL;
  1646. }
  1647. }
  1648. /////////////////////////////////////////////////////////////////////
  1649. // //
  1650. // Routines related to the asynchronous processing. //
  1651. // //
  1652. /////////////////////////////////////////////////////////////////////
  1653. void NextAsyncCmd (
  1654. LPOBJECT_LE lpobj,
  1655. UINT mainRtn
  1656. ){
  1657. lpobj->mainRtn = mainRtn;
  1658. lpobj->subRtn = 0;
  1659. }
  1660. void InitAsyncCmd (
  1661. LPOBJECT_LE lpobj,
  1662. UINT cmd,
  1663. UINT mainRtn
  1664. ){
  1665. lpobj->asyncCmd = cmd;
  1666. lpobj->mainErr = OLE_OK;
  1667. lpobj->mainRtn = mainRtn;
  1668. lpobj->subRtn = 0;
  1669. lpobj->subErr = 0;
  1670. lpobj->bAsync = 0;
  1671. lpobj->endAsync = 0;
  1672. lpobj->errHint = 0;
  1673. }
  1674. #ifdef WIN16
  1675. void FARINTERNAL FarInitAsyncCmd (
  1676. LPOBJECT_LE lpobj,
  1677. UINT cmd,
  1678. UINT mainRtn
  1679. ){
  1680. return (InitAsyncCmd(lpobj, cmd, mainRtn));
  1681. }
  1682. #endif
  1683. OLESTATUS EndAsyncCmd (LPOBJECT_LE lpobj)
  1684. {
  1685. OLESTATUS olderr;
  1686. if (!lpobj->endAsync) {
  1687. lpobj->asyncCmd = OLE_NONE;
  1688. return OLE_OK;
  1689. }
  1690. // this is an asynchronous operation. Send callback with or without
  1691. // error.
  1692. switch (lpobj->asyncCmd) {
  1693. case OLE_DELETE:
  1694. break;
  1695. case OLE_COPYFROMLNK:
  1696. case OLE_CREATEFROMFILE:
  1697. // change the topic name to embedded.
  1698. SetEmbeddedTopic (lpobj);
  1699. break;
  1700. case OLE_LOADFROMSTREAM:
  1701. case OLE_LNKPASTE:
  1702. case OLE_RUN:
  1703. case OLE_SHOW:
  1704. case OLE_ACTIVATE:
  1705. case OLE_UPDATE:
  1706. case OLE_CLOSE:
  1707. case OLE_RECONNECT:
  1708. case OLE_CREATELINKFROMFILE:
  1709. case OLE_CREATEINVISIBLE:
  1710. case OLE_CREATE:
  1711. case OLE_CREATEFROMTEMPLATE:
  1712. case OLE_SETUPDATEOPTIONS:
  1713. case OLE_SERVERUNLAUNCH:
  1714. case OLE_SETDATA:
  1715. case OLE_REQUESTDATA:
  1716. case OLE_OTHER:
  1717. break;
  1718. case OLE_EMBPASTE:
  1719. lpobj->mainErr = OLE_OK;
  1720. break;
  1721. default:
  1722. DEBUG_OUT ("unexpected maincmd", 0);
  1723. break;
  1724. }
  1725. lpobj->bAsync = FALSE;
  1726. lpobj->endAsync = FALSE;
  1727. lpobj->oldasyncCmd = lpobj->asyncCmd;
  1728. olderr = lpobj->mainErr;
  1729. lpobj->asyncCmd = OLE_NONE; // no async command in progress.
  1730. if (lpobj->head.lpclient)
  1731. ContextCallBack ((LPOLEOBJECT)lpobj, OLE_RELEASE);
  1732. lpobj->mainErr = OLE_OK;
  1733. return olderr;
  1734. }
  1735. BOOL ProcessErr (LPOBJECT_LE lpobj)
  1736. {
  1737. if (lpobj->subErr == OLE_OK)
  1738. return FALSE;
  1739. if (lpobj->mainErr == OLE_OK)
  1740. lpobj->mainErr = lpobj->subErr;
  1741. lpobj->subErr = OLE_OK;
  1742. return TRUE;
  1743. }
  1744. void ScheduleAsyncCmd (LPOBJECT_LE lpobj)
  1745. {
  1746. // replacs this with direct proc jump later on.
  1747. #ifdef FIREWALLS
  1748. ASSERT (lpobj->bAsync, "Not an asynchronous command");
  1749. #endif
  1750. lpobj->bAsync = FALSE;
  1751. // if the object is active and we do pokes we go thru this path
  1752. // !!! We may have to go thru the endasynccmd.
  1753. if ((lpobj->asyncCmd == OLE_OTHER)
  1754. || ((lpobj->asyncCmd == OLE_SETDATA) && !lpobj->mainRtn)) {
  1755. lpobj->endAsync = TRUE;
  1756. lpobj->mainErr = lpobj->subErr;
  1757. EndAsyncCmd (lpobj);
  1758. if (lpobj->bUnlaunchLater) {
  1759. lpobj->bUnlaunchLater = FALSE;
  1760. CallEmbLnkDelete(lpobj);
  1761. }
  1762. return;
  1763. }
  1764. switch (lpobj->mainRtn) {
  1765. case EMBLNKDELETE:
  1766. EmbLnkDelete (lpobj);
  1767. break;
  1768. case LNKOPENUPDATE:
  1769. LnkOpenUpdate (lpobj);
  1770. break;
  1771. case DOCSHOW:
  1772. DocShow (lpobj);
  1773. break;
  1774. case EMBOPENUPDATE:
  1775. EmbOpenUpdate (lpobj);
  1776. break;
  1777. case EMBLNKCLOSE:
  1778. EmbLnkClose (lpobj);
  1779. break;
  1780. case LNKSETUPDATEOPTIONS:
  1781. LnkSetUpdateOptions (lpobj);
  1782. break;
  1783. case LNKCHANGELNK:
  1784. LnkChangeLnk (lpobj);
  1785. break;
  1786. case REQUESTDATA:
  1787. RequestData (lpobj, 0);
  1788. break;
  1789. default:
  1790. DEBUG_OUT ("Unexpected asyn command", 0);
  1791. break;
  1792. }
  1793. return;
  1794. }
  1795. void SetNetDrive (LPOBJECT_LE lpobj)
  1796. {
  1797. char buf[MAX_STR];
  1798. if (GlobalGetAtomName (lpobj->topic, buf, sizeof(buf))
  1799. && (buf[1] == ':')) {
  1800. AnsiUpperBuff ((LPSTR) buf, 1);
  1801. lpobj->cDrive = buf[0];
  1802. }
  1803. }
  1804. HANDLE GetNetNameHandle (LPOBJECT_LE lpobj)
  1805. {
  1806. HANDLE hNetName;
  1807. LPSTR lpNetName;
  1808. int size;
  1809. if (!(size = GlobalGetAtomLen (lpobj->aNetName)))
  1810. return NULL;
  1811. size++;
  1812. if (!(hNetName = GlobalAlloc (GMEM_MOVEABLE, (DWORD) size)))
  1813. return NULL;
  1814. if (lpNetName = GlobalLock (hNetName)) {
  1815. GlobalUnlock (hNetName);
  1816. if (GlobalGetAtomName(lpobj->aNetName, lpNetName, size))
  1817. return hNetName;
  1818. }
  1819. // error case
  1820. GlobalFree (hNetName);
  1821. return NULL;
  1822. }
  1823. BOOL AreTopicsEqual (
  1824. LPOBJECT_LE lpobj1,
  1825. LPOBJECT_LE lpobj2
  1826. ){
  1827. char buf1[MAX_STR];
  1828. char buf2[MAX_STR];
  1829. if (lpobj1->aNetName != lpobj2->aNetName)
  1830. return FALSE;
  1831. if (!lpobj1->aNetName) {
  1832. if (lpobj1->topic == lpobj2->topic)
  1833. return TRUE;
  1834. return FALSE;
  1835. }
  1836. if (!GlobalGetAtomName (lpobj1->topic, buf1, MAX_STR))
  1837. return FALSE;
  1838. if (!GlobalGetAtomName (lpobj2->topic, buf2, MAX_STR))
  1839. return FALSE;
  1840. if (!lstrcmpi (&buf1[1], &buf2[1]))
  1841. return TRUE;
  1842. return FALSE;
  1843. }
  1844. ATOM FARINTERNAL wAtomCat (
  1845. ATOM a1,
  1846. ATOM a2
  1847. ){
  1848. char buf[MAX_STR+MAX_STR];
  1849. LPSTR lpBuf = (LPSTR)buf;
  1850. if (!GlobalGetAtomName (a1, lpBuf, MAX_STR+MAX_STR))
  1851. return (ATOM)0;
  1852. lpBuf += lstrlen(lpBuf);
  1853. if (!GlobalGetAtomName(a2, lpBuf, MAX_STR))
  1854. return (ATOM)0;
  1855. return GlobalAddAtom ((LPSTR) buf);
  1856. }