Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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