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.

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