Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2844 lines
70 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: LEDDE.C
  3. *
  4. * Purpose: ?????
  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 "dde.h"
  17. #include "dll.h"
  18. #include "pict.h"
  19. #define LN_FUDGE 16 // [],(), 3 * 3 (2 double quotes and comma)
  20. #define RUNITEM
  21. #define OLEVERB_CONNECT 0xFFFF
  22. // Definitions for sending the server sys command.
  23. char *srvrSysCmd[] = {"StdNewFromTemplate",
  24. "StdNewDocument",
  25. "StdEditDocument",
  26. "StdOpenDocument"
  27. };
  28. #define EMB_ID_INDEX 11 // index of ones digit in #00
  29. extern char embStr[];
  30. extern BOOL gbCreateInvisible;
  31. extern BOOL gbLaunchServer;
  32. extern ATOM aMSDraw;
  33. extern BOOL (FAR PASCAL *lpfnIsTask) (HANDLE);
  34. // !!! set error hints
  35. OLESTATUS FARINTERNAL LeDoVerb (
  36. LPOLEOBJECT lpoleobj,
  37. UINT verb,
  38. BOOL fShow,
  39. BOOL fActivate
  40. ){
  41. LPOBJECT_LE lpobj = (LPOBJECT_LE)lpoleobj;
  42. PROBE_ASYNC (lpobj);
  43. PROBE_SVRCLOSING(lpobj);
  44. if (!QueryOpen(lpobj))
  45. return OLE_OK;
  46. lpobj->verb = verb;
  47. lpobj->fCmd = ACT_DOVERB;
  48. if (fActivate)
  49. lpobj->fCmd |= ACT_ACTIVATE;
  50. if (fShow)
  51. lpobj->fCmd |= ACT_SHOW;
  52. InitAsyncCmd (lpobj, OLE_RUN, DOCSHOW);
  53. return DocShow (lpobj);
  54. }
  55. OLESTATUS FARINTERNAL LeShow (
  56. LPOLEOBJECT lpoleobj,
  57. BOOL fActivate
  58. ){
  59. LPOBJECT_LE lpobj = (LPOBJECT_LE)lpoleobj;
  60. UNREFERENCED_PARAMETER(fActivate);
  61. PROBE_ASYNC (lpobj);
  62. PROBE_SVRCLOSING(lpobj);
  63. if (!QueryOpen(lpobj))
  64. return OLE_OK;
  65. lpobj->fCmd = ACT_SHOW;
  66. InitAsyncCmd (lpobj, OLE_SHOW, DOCSHOW);
  67. return DocShow (lpobj);
  68. }
  69. // DocShow : If the server is connected, show the item
  70. // for editing. For embedded objects us NULL Item.
  71. OLESTATUS DocShow (LPOBJECT_LE lpobj)
  72. {
  73. switch (lpobj->subRtn) {
  74. case 0:
  75. SendStdShow (lpobj);
  76. WAIT_FOR_ASYNC_MSG (lpobj);
  77. case 1:
  78. ProcessErr (lpobj);
  79. return EndAsyncCmd (lpobj);
  80. default:
  81. DEBUG_OUT ("Unexpected subroutine", 0);
  82. return OLE_ERROR_GENERIC;
  83. }
  84. }
  85. void SendStdShow (LPOBJECT_LE lpobj)
  86. {
  87. UINT len;
  88. UINT size;
  89. LPSTR lpdata = NULL;
  90. HANDLE hdata = NULL;
  91. BOOL bShow;
  92. lpobj->subErr = OLE_OK;
  93. if (lpobj->verb == OLEVERB_CONNECT) {
  94. lpobj->verb = 0;
  95. return;
  96. }
  97. if (!(lpobj->fCmd & (ACT_SHOW | ACT_DOVERB)))
  98. return;
  99. if (bShow = (!lpobj->bOleServer || !(lpobj->fCmd & ACT_DOVERB))) {
  100. // show is off, do not show the server.
  101. if (!(lpobj->fCmd & ACT_SHOW))
  102. return;
  103. SETERRHINT(lpobj, OLE_ERROR_SHOW);
  104. // and 18 "[StdShowItem(\"")for 5 extra for ",FALSE
  105. len = 18 + 7;
  106. } else {
  107. // 19 for the string [StdDoVerbItem(\"") and
  108. // 18 extra is for ",000,FALSE,FALSE
  109. SETERRHINT(lpobj, OLE_ERROR_DOVERB);
  110. len = 19 + 18;
  111. }
  112. len += GlobalGetAtomLen (lpobj->item);
  113. len += 4; // ")]" + NULL
  114. hdata = GlobalAlloc (GMEM_DDESHARE, size = len);
  115. if (hdata == NULL || (lpdata = (LPSTR)GlobalLock (hdata)) == NULL)
  116. goto errRtn;
  117. if (bShow)
  118. lstrcpy (lpdata, "[StdShowItem(\"");
  119. else
  120. lstrcpy (lpdata, "[StdDoVerbItem(\"");
  121. len = lstrlen (lpdata);
  122. if (lpobj->item)
  123. GlobalGetAtomName (lpobj->item , lpdata + len, size - len);
  124. if (!bShow) {
  125. lstrcat (lpdata, (LPSTR)"\",");
  126. // assume that the number of verbs are < 10
  127. len = lstrlen (lpdata);
  128. #ifdef FIREWALLS
  129. ASSERT ( (lpobj->verb & 0x000f) < 9 , "Verb value more than 9");
  130. #endif
  131. lpdata += len;
  132. *lpdata++ = (char)((lpobj->verb & 0x000f) + '0');
  133. *lpdata = 0;
  134. if (lpobj->fCmd & ACT_SHOW)
  135. lstrcat (lpdata, (LPSTR) ",TRUE");
  136. else
  137. lstrcat (lpdata, (LPSTR) ",FALSE");
  138. // StdVerbItem (item, verb, TRUE
  139. // add TRUE/FALSE constant for the activate
  140. if (!(lpobj->fCmd & ACT_ACTIVATE))
  141. lstrcat (lpdata, (LPSTR) ",TRUE)]");
  142. else
  143. lstrcat (lpdata, (LPSTR) ",FALSE)]");
  144. // [StdDoVerb ("item", verb, FALSE, FALSE)]
  145. } else
  146. lstrcat (lpdata, (LPSTR)"\")]");
  147. // apps like excel and wingraph do not suuport activate at
  148. // item level.
  149. GlobalUnlock (hdata);
  150. DocExecute (lpobj, hdata);
  151. return;
  152. errRtn:
  153. if (lpdata)
  154. GlobalUnlock (hdata);
  155. if (hdata)
  156. GlobalFree (hdata);
  157. lpobj->subErr = OLE_ERROR_MEMORY;
  158. return;
  159. }
  160. OLESTATUS FARINTERNAL LeQueryOpen (LPOLEOBJECT lpoleobj)
  161. {
  162. LPOBJECT_LE lpobj = (LPOBJECT_LE)lpoleobj;
  163. if (QueryOpen(lpobj))
  164. return OLE_OK;
  165. else
  166. return OLE_ERROR_NOT_OPEN;
  167. }
  168. BOOL INTERNAL QueryOpen (LPOBJECT_LE lpobj)
  169. {
  170. if (lpobj->pDocEdit && lpobj->pDocEdit->hClient) {
  171. if (IsServerValid (lpobj))
  172. return TRUE;
  173. // destroy the windows and pretend as if the server was never
  174. // connected.
  175. DestroyWindow (lpobj->pDocEdit->hClient);
  176. if (lpobj->pSysEdit && lpobj->pSysEdit->hClient)
  177. DestroyWindow (lpobj->pSysEdit->hClient);
  178. }
  179. return FALSE;
  180. }
  181. OLESTATUS FARINTERNAL LeActivate (
  182. LPOLEOBJECT lpoleobj,
  183. UINT verb,
  184. BOOL fShow,
  185. BOOL fActivate,
  186. HWND hWnd,
  187. OLE_CONST RECT FAR* lprc
  188. ){
  189. LPOBJECT_LE lpobj = (LPOBJECT_LE)lpoleobj;
  190. lpobj->verb = verb;
  191. if (lpobj->head.ctype == CT_EMBEDDED)
  192. return EmbOpen (lpobj, fShow, fActivate, hWnd, (LPRECT)lprc);
  193. #ifdef FIREWALLS
  194. ASSERT (lpobj->head.ctype == CT_LINK, "unknown object");
  195. #endif
  196. return LnkOpen (lpobj, fShow, fActivate, hWnd, (LPRECT)lprc);
  197. }
  198. OLESTATUS FARINTERNAL LeUpdate (
  199. LPOLEOBJECT lpoleobj
  200. ){
  201. LPOBJECT_LE lpobj = (LPOBJECT_LE)lpoleobj;
  202. if (lpobj->head.ctype == CT_EMBEDDED)
  203. return EmbUpdate (lpobj);
  204. #ifdef FIREWALLS
  205. ASSERT (lpobj->head.ctype == CT_LINK, "unknown object");
  206. #endif
  207. return LnkUpdate (lpobj);
  208. }
  209. OLESTATUS FARINTERNAL EmbOpen (
  210. LPOBJECT_LE lpobj,
  211. BOOL fShow,
  212. BOOL fActivate,
  213. HWND hWnd,
  214. LPRECT lprc
  215. ){
  216. UNREFERENCED_PARAMETER(hWnd);
  217. UNREFERENCED_PARAMETER(lprc);
  218. PROBE_ASYNC (lpobj);
  219. PROBE_SVRCLOSING(lpobj);
  220. if(QueryOpen (lpobj))
  221. return LeDoVerb ((LPOLEOBJECT)lpobj, lpobj->verb, fShow, fActivate);
  222. // show the window
  223. // advise for data only on close
  224. // and shut down the conv after the advises.
  225. lpobj->fCmd = LN_EMBACT | ACT_DOVERB | ACT_ADVISE | ACT_CLOSE;
  226. if (fActivate)
  227. lpobj->fCmd |= ACT_ACTIVATE;
  228. if (fShow)
  229. lpobj->fCmd |= ACT_SHOW;
  230. InitAsyncCmd (lpobj, OLE_ACTIVATE, EMBOPENUPDATE);
  231. return EmbOpenUpdate (lpobj);
  232. }
  233. /***************************** Public Function ****************************\
  234. * OLESTATUS FARINTERNAL EmbUpdate (lpobj)
  235. *
  236. * This function updates an EMB object. If the server is connected
  237. * simply send a request for the native as well as the display formats.
  238. * If the server is connected, then tries to start the conversationa and
  239. * get the data. If the conversation fails, then load the server and
  240. * start the conversation. The embeded objects may have links in it.
  241. *
  242. * Effects:
  243. *
  244. * History:
  245. * Wrote it.
  246. \***************************************************************************/
  247. OLESTATUS FARINTERNAL EmbUpdate (LPOBJECT_LE lpobj)
  248. {
  249. // if we are loading the server, then definitly unload.
  250. // if the connection is established, then unload if it is
  251. // to be unloaded, when all the previous requests are satisfied.
  252. PROBE_ASYNC (lpobj);
  253. PROBE_SVRCLOSING(lpobj);
  254. lpobj->fCmd = LN_EMBACT | ACT_REQUEST | (QueryOpen(lpobj) ? 0 : ACT_UNLAUNCH);
  255. InitAsyncCmd (lpobj, OLE_UPDATE, EMBOPENUPDATE);
  256. return EmbOpenUpdate (lpobj);
  257. }
  258. OLESTATUS FARINTERNAL EmbOpenUpdate (LPOBJECT_LE lpobj)
  259. {
  260. switch (lpobj->subRtn) {
  261. case 0:
  262. SKIP_TO (QueryOpen(lpobj), step6);
  263. SendSrvrMainCmd (lpobj, lpobj->lptemplate);
  264. lpobj->lptemplate = NULL;
  265. WAIT_FOR_ASYNC_MSG (lpobj);
  266. case 1:
  267. if (ProcessErr (lpobj))
  268. goto errRtn;
  269. // Init doc conversation should set the failure error
  270. if (!InitDocConv (lpobj, !POPUP_NETDLG))
  271. goto errRtn;
  272. // If there is no native data, do not do any poke.
  273. // creates will not have any poke data to start with
  274. SKIP_TO (!(lpobj->hnative), step6);
  275. PokeNativeData (lpobj);
  276. WAIT_FOR_ASYNC_MSG (lpobj);
  277. case 2:
  278. if (ProcessErr (lpobj))
  279. goto errRtn;
  280. // Now poke the hostnames etc stuff.
  281. PokeHostNames (lpobj);
  282. WAIT_FOR_ASYNC_MSG (lpobj);
  283. case 3:
  284. // do not worry about the poke hostname errors
  285. PokeTargetDeviceInfo (lpobj);
  286. WAIT_FOR_ASYNC_MSG (lpobj);
  287. case 4:
  288. PokeDocDimensions (lpobj);
  289. WAIT_FOR_ASYNC_MSG (lpobj);
  290. case 5:
  291. PokeColorScheme (lpobj);
  292. WAIT_FOR_ASYNC_MSG (lpobj);
  293. case 6:
  294. step6:
  295. // wingraph does not accept the doc dimensions
  296. // after sttedit.
  297. CLEAR_STEP_ERROR (lpobj);
  298. SETSTEP (lpobj, 6);
  299. STEP_NOP (lpobj);
  300. // step_nop simply increments the step numebr
  301. // merge the steps later on
  302. case 7:
  303. if (ProcessErr (lpobj))
  304. goto errRtn;
  305. SKIP_TO (!(lpobj->fCmd & ACT_ADVISE), step13);
  306. lpobj->optUpdate = oleupdate_onsave;
  307. lpobj->pDocEdit->nAdviseSave = 0;
  308. AdviseOn (lpobj, cfNative, aSave);
  309. WAIT_FOR_ASYNC_MSG (lpobj);
  310. case 8:
  311. // do not go for errors on /save. Some servers may not support
  312. // this.
  313. CLEAR_STEP_ERROR (lpobj);
  314. AdvisePict (lpobj, aSave);
  315. WAIT_FOR_ASYNC_MSG (lpobj);
  316. case 9:
  317. // see if server will positive ack a metafile advise if enhmetafile
  318. // advise failed
  319. if (ChangeEMFtoMFneeded(lpobj,aSave))
  320. WAIT_FOR_ASYNC_MSG (lpobj);
  321. case 10:
  322. if (!lpobj->subErr && lpobj->bNewPict)
  323. if (!ChangeEMFtoMF(lpobj))
  324. goto errRtn;
  325. // do not worry about the error case for save. Ignore them
  326. CLEAR_STEP_ERROR (lpobj);
  327. lpobj->optUpdate = oleupdate_onclose;
  328. lpobj->pDocEdit->nAdviseClose = 0;
  329. AdviseOn (lpobj, cfNative, aClose);
  330. WAIT_FOR_ASYNC_MSG (lpobj);
  331. case 11:
  332. if (ProcessErr(lpobj))
  333. goto errRtn;
  334. AdvisePict (lpobj, aClose);
  335. WAIT_FOR_ASYNC_MSG (lpobj);
  336. case 12:
  337. if (ChangeEMFtoMFneeded(lpobj,aClose))
  338. WAIT_FOR_ASYNC_MSG (lpobj);
  339. case 13:
  340. step13:
  341. SETSTEP (lpobj, 13);
  342. if (ProcessErr(lpobj))
  343. goto errRtn;
  344. if (lpobj->bNewPict && !ChangeEMFtoMF(lpobj))
  345. goto errRtn;
  346. SKIP_TO (!(lpobj->fCmd & ACT_REQUEST), step15);
  347. // we don't want to send OLE_CHANGED when we get this data, if we
  348. // are going to request for picture data also.
  349. lpobj->pDocEdit->bCallLater = ((lpobj->lpobjPict) ? TRUE: FALSE);
  350. RequestOn (lpobj, cfNative);
  351. WAIT_FOR_ASYNC_MSG (lpobj);
  352. // If request pict fails, then native and pict are
  353. // not in sync.
  354. case 14:
  355. if (ProcessErr(lpobj))
  356. goto errRtn;
  357. lpobj->pDocEdit->bCallLater = FALSE;
  358. RequestPict (lpobj);
  359. WAIT_FOR_ASYNC_MSG (lpobj);
  360. case 15:
  361. step15:
  362. SETSTEP(lpobj, 15);
  363. if (ProcessErr(lpobj))
  364. goto errRtn;
  365. SendStdShow (lpobj);
  366. WAIT_FOR_ASYNC_MSG (lpobj);
  367. case 16:
  368. if (ProcessErr(lpobj))
  369. goto errRtn;
  370. SKIP_TO ((lpobj->fCmd & ACT_UNLAUNCH), step17);
  371. return EndAsyncCmd (lpobj);
  372. case 17:
  373. errRtn:
  374. step17:
  375. ProcessErr (lpobj);
  376. if ((lpobj->asyncCmd == OLE_UPDATE)
  377. && (!(lpobj->fCmd & ACT_UNLAUNCH)))
  378. return EndAsyncCmd (lpobj);
  379. // if we launched and error, unlaunch (send stdexit)
  380. NextAsyncCmd (lpobj, EMBLNKDELETE);
  381. lpobj->fCmd |= ACT_UNLAUNCH;
  382. EmbLnkDelete (lpobj);
  383. return lpobj->mainErr;
  384. default:
  385. DEBUG_OUT ("Unexpected subroutine", 0);
  386. return OLE_ERROR_GENERIC;
  387. }
  388. }
  389. OLESTATUS FARINTERNAL LnkOpen (
  390. LPOBJECT_LE lpobj,
  391. BOOL fShow,
  392. BOOL fActivate,
  393. HWND hWnd,
  394. LPRECT lprc
  395. ){
  396. UNREFERENCED_PARAMETER(hWnd);
  397. UNREFERENCED_PARAMETER(lprc);
  398. PROBE_ASYNC (lpobj);
  399. PROBE_SVRCLOSING(lpobj);
  400. if(QueryOpen (lpobj))
  401. return LeDoVerb ((LPOLEOBJECT)lpobj, lpobj->verb, fShow, fActivate);
  402. // Just end the system conversation. we are not unloading
  403. // this instance at all.
  404. lpobj->fCmd = LN_LNKACT | ACT_DOVERB;
  405. if (lpobj->optUpdate == oleupdate_always)
  406. lpobj->fCmd |= ACT_ADVISE | ACT_REQUEST;
  407. else if (lpobj->optUpdate == oleupdate_onsave)
  408. lpobj->fCmd |= ACT_ADVISE;
  409. if (fActivate)
  410. lpobj->fCmd |= ACT_ACTIVATE;
  411. if (fShow)
  412. lpobj->fCmd |= ACT_SHOW;
  413. InitAsyncCmd (lpobj, OLE_ACTIVATE, LNKOPENUPDATE);
  414. return LnkOpenUpdate (lpobj);
  415. }
  416. OLESTATUS FARINTERNAL LnkUpdate (LPOBJECT_LE lpobj)
  417. {
  418. // if we are loading the server, then definitly unload.
  419. // if the connection is established, then unload if it is
  420. // to be unloaded, when all the previous requests are satisfied.
  421. PROBE_ASYNC (lpobj);
  422. PROBE_SVRCLOSING(lpobj);
  423. lpobj->fCmd = LN_LNKACT | ACT_REQUEST | (QueryOpen (lpobj) ? 0 : ACT_UNLAUNCH);
  424. InitAsyncCmd (lpobj, OLE_UPDATE, LNKOPENUPDATE);
  425. return LnkOpenUpdate (lpobj);
  426. }
  427. OLESTATUS FARINTERNAL LnkOpenUpdate (LPOBJECT_LE lpobj)
  428. {
  429. switch (lpobj->subRtn) {
  430. case 0:
  431. SKIP_TO (QueryOpen(lpobj), step2);
  432. InitDocConv (lpobj, !POPUP_NETDLG);
  433. if (QueryOpen(lpobj)) {
  434. if (lpobj->app == aPackage)
  435. RemoveLinkStringFromTopic (lpobj);
  436. goto step2;
  437. }
  438. SendSrvrMainCmd (lpobj, NULL);
  439. WAIT_FOR_ASYNC_MSG (lpobj);
  440. case 1:
  441. if (ProcessErr (lpobj))
  442. goto errRtn;
  443. if (lpobj->app == aPackage)
  444. RemoveLinkStringFromTopic (lpobj);
  445. if (!InitDocConv (lpobj, POPUP_NETDLG)) {
  446. lpobj->subErr = OLE_ERROR_OPEN;
  447. goto errRtn;
  448. }
  449. case 2:
  450. step2:
  451. SETSTEP (lpobj, 2);
  452. PokeTargetDeviceInfo (lpobj);
  453. WAIT_FOR_ASYNC_MSG (lpobj);
  454. case 3:
  455. if (ProcessErr (lpobj))
  456. goto errRtn;
  457. SKIP_TO (!(lpobj->fCmd & ACT_ADVISE), step7);
  458. SKIP_TO (!(lpobj->fCmd & ACT_NATIVE), step4);
  459. AdviseOn (lpobj, cfNative, (ATOM)0);
  460. WAIT_FOR_ASYNC_MSG (lpobj);
  461. case 4:
  462. step4:
  463. SETSTEP (lpobj, 4);
  464. if (ProcessErr (lpobj))
  465. goto errRtn;
  466. AdvisePict (lpobj, (ATOM)0);
  467. WAIT_FOR_ASYNC_MSG (lpobj);
  468. case 5:
  469. // see if server will positive ack a metafile advise if enhmetafile
  470. // advise failed
  471. if (ChangeEMFtoMFneeded(lpobj,(ATOM)0))
  472. WAIT_FOR_ASYNC_MSG (lpobj);
  473. case 6:
  474. if (ProcessErr (lpobj))
  475. goto errRtn;
  476. if (lpobj->bNewPict && !ChangeEMFtoMF(lpobj))
  477. goto errRtn;
  478. // Now send advise for renaming the documnet.
  479. AdviseOn (lpobj, cfBinary, aStdDocName);
  480. WAIT_FOR_ASYNC_MSG (lpobj);
  481. case 7:
  482. step7:
  483. // if name advise fails ignore it
  484. SETSTEP (lpobj, 7);
  485. CLEAR_STEP_ERROR (lpobj);
  486. SKIP_TO (!(lpobj->fCmd & ACT_REQUEST), step9);
  487. SKIP_TO (!(lpobj->fCmd & ACT_NATIVE), step8);
  488. // we don't want to send OLE_CHANGED when we get this data, if we
  489. // are going to request for picture data also.
  490. lpobj->pDocEdit->bCallLater = ((lpobj->lpobjPict) ? TRUE: FALSE);
  491. RequestOn (lpobj, cfNative);
  492. WAIT_FOR_ASYNC_MSG (lpobj);
  493. case 8:
  494. step8:
  495. SETSTEP (lpobj, 8);
  496. if (ProcessErr (lpobj))
  497. goto errRtn;
  498. lpobj->pDocEdit->bCallLater = FALSE;
  499. RequestPict (lpobj);
  500. WAIT_FOR_ASYNC_MSG (lpobj);
  501. case 9:
  502. step9:
  503. if (lpobj->subErr && CF_ENHMETAFILE == GetPictType(lpobj)) {
  504. CLEAR_STEP_ERROR (lpobj);
  505. if (!ChangeEMFtoMF(lpobj))
  506. goto errRtn;
  507. RequestPict (lpobj);
  508. WAIT_FOR_ASYNC_MSG (lpobj);
  509. }
  510. else if (ProcessErr (lpobj))
  511. goto errRtn;
  512. SETSTEP (lpobj, 9);
  513. SKIP_TO (!(lpobj->fCmd & ACT_TERMDOC), step11);
  514. // terminate the document conversataion.
  515. TermDocConv (lpobj);
  516. WAIT_FOR_ASYNC_MSG (lpobj);
  517. case 10:
  518. if (ProcessErr (lpobj))
  519. goto errRtn;
  520. // delete the server edit block
  521. DeleteDocEdit (lpobj);
  522. SKIP_TO ((lpobj->fCmd & ACT_UNLAUNCH), step15);
  523. return EndAsyncCmd (lpobj);
  524. case 11:
  525. step11:
  526. SETSTEP (lpobj, 11);
  527. if (ProcessErr (lpobj))
  528. goto errRtn;
  529. SKIP_TO (!(lpobj->fCmd & ACT_TERMSRVR), step13);
  530. // terminate the server conversataion.
  531. TermSrvrConv (lpobj);
  532. WAIT_FOR_ASYNC_MSG (lpobj);
  533. case 12:
  534. if (ProcessErr (lpobj))
  535. goto errRtn;
  536. // delete the server edit block
  537. DeleteSrvrEdit (lpobj);
  538. return EndAsyncCmd (lpobj);
  539. case 13:
  540. step13:
  541. SETSTEP (lpobj, 13);
  542. if (ProcessErr (lpobj))
  543. goto errRtn;
  544. SendStdShow (lpobj);
  545. WAIT_FOR_ASYNC_MSG (lpobj);
  546. case 14:
  547. if (ProcessErr (lpobj))
  548. goto errRtn;
  549. SKIP_TO ((lpobj->fCmd & ACT_UNLAUNCH), step15);
  550. return EndAsyncCmd (lpobj);
  551. case 15:
  552. errRtn:
  553. step15:
  554. ProcessErr (lpobj);
  555. if ((lpobj->asyncCmd == OLE_UPDATE)
  556. && (!(lpobj->fCmd & ACT_UNLAUNCH)))
  557. return EndAsyncCmd (lpobj);
  558. // if we launched and error, unlaunch (send stdexit)
  559. NextAsyncCmd (lpobj, EMBLNKDELETE);
  560. lpobj->fCmd |= ACT_UNLAUNCH;
  561. EmbLnkDelete (lpobj);
  562. return lpobj->mainErr;
  563. default:
  564. DEBUG_OUT ("Unexpected subroutine", 0);
  565. return OLE_ERROR_GENERIC;
  566. }
  567. }
  568. OLESTATUS EmbLnkClose (LPOBJECT_LE lpobj)
  569. {
  570. switch (lpobj->subRtn) {
  571. case 0:
  572. TermDocConv (lpobj);
  573. WAIT_FOR_ASYNC_MSG (lpobj);
  574. case 1:
  575. // delete the edit block
  576. DeleteDocEdit (lpobj);
  577. TermSrvrConv (lpobj);
  578. WAIT_FOR_ASYNC_MSG (lpobj);
  579. case 2:
  580. // Do not set any errors, just delete the object.
  581. // delete the server edit block
  582. DeleteSrvrEdit (lpobj);
  583. return EndAsyncCmd (lpobj);
  584. default:
  585. DEBUG_OUT ("Unexpected subroutine", 0);
  586. return OLE_ERROR_GENERIC;
  587. }
  588. }
  589. OLESTATUS FARINTERNAL LeClose (
  590. LPOLEOBJECT lpoleobj
  591. ){
  592. LPOBJECT_LE lpobj = (LPOBJECT_LE)lpoleobj;
  593. PROBE_ASYNC (lpobj);
  594. if (IS_SVRCLOSING(lpobj))
  595. return OLE_OK;
  596. lpobj->fCmd = 0;
  597. if (lpobj->head.ctype == CT_EMBEDDED) {
  598. InitAsyncCmd (lpobj, OLE_CLOSE, EMBLNKDELETE);
  599. return EmbLnkDelete (lpobj);
  600. }
  601. else {
  602. InitAsyncCmd (lpobj, OLE_CLOSE, EMBLNKCLOSE);
  603. return EmbLnkClose (lpobj);
  604. }
  605. }
  606. OLESTATUS FARINTERNAL LeReconnect (LPOLEOBJECT lpoleobj)
  607. {
  608. LPOBJECT_LE lpobj = (LPOBJECT_LE)lpoleobj;
  609. // check for the existing conversation.
  610. // if the client window is non-null, then
  611. // connection exits.
  612. if (lpobj->head.ctype != CT_LINK)
  613. return OLE_ERROR_NOT_LINK; // allow only for linked
  614. PROBE_ASYNC (lpobj);
  615. PROBE_SVRCLOSING(lpobj);
  616. if (QueryOpen (lpobj))
  617. return OLE_OK;
  618. // start just the conversation. Do not load
  619. // the app.
  620. if (!InitDocConv (lpobj, !POPUP_NETDLG))
  621. return OLE_OK; // document is not loaded , it is OK.
  622. lpobj->fCmd = LN_LNKACT;
  623. if (lpobj->optUpdate == oleupdate_always)
  624. lpobj->fCmd |= ACT_ADVISE | ACT_REQUEST;
  625. InitAsyncCmd (lpobj, OLE_RECONNECT, LNKOPENUPDATE);
  626. return LnkOpenUpdate (lpobj);
  627. }
  628. OLESTATUS INTERNAL PokeNativeData (LPOBJECT_LE lpobj)
  629. {
  630. SETERRHINT(lpobj, OLE_ERROR_POKE_NATIVE);
  631. return SendPokeData (
  632. lpobj,
  633. lpobj->item,
  634. lpobj->hnative,
  635. cfNative
  636. );
  637. }
  638. BOOL INTERNAL PostMessageToServer (
  639. PEDIT_DDE pedit,
  640. UINT msg,
  641. LPARAM lparam
  642. ){
  643. #ifdef FIREWALLS
  644. ASSERT (pedit, "Dde edit block is NULL");
  645. #endif
  646. // save the lparam and msg fpr possible reposting incase of error.
  647. // we are in abort state. no messages except for terminate.
  648. if (pedit->bAbort && msg != WM_DDE_TERMINATE)
  649. return FALSE;
  650. pedit->lParam = lparam;
  651. pedit->msg = msg;
  652. if (pedit->hClient && pedit->hServer) {
  653. while (TRUE){
  654. if (!IsWindowValid (pedit->hServer))
  655. return FALSE;
  656. if (PostMessage (pedit->hServer, msg, (WPARAM)pedit->hClient, lparam) == FALSE)
  657. Yield ();
  658. else
  659. return TRUE;
  660. }
  661. }
  662. return FALSE;
  663. }
  664. OLESTATUS FARINTERNAL LeCreateFromTemplate (
  665. LPOLECLIENT lpclient,
  666. LPSTR lptemplate,
  667. LHCLIENTDOC lhclientdoc,
  668. LPSTR lpobjname,
  669. LPOLEOBJECT FAR * lplpoleobject,
  670. OLEOPT_RENDER optRender,
  671. OLECLIPFORMAT cfFormat
  672. ){
  673. char buf[MAX_STR];
  674. if (!MapExtToClass (lptemplate, (LPSTR)buf, MAX_STR))
  675. return OLE_ERROR_CLASS;
  676. return CreateFromClassOrTemplate (lpclient, (LPSTR) buf, lplpoleobject,
  677. optRender, cfFormat, LN_TEMPLATE, lptemplate,
  678. lhclientdoc, lpobjname);
  679. }
  680. OLESTATUS FARINTERNAL LeCreate (
  681. LPOLECLIENT lpclient,
  682. LPSTR lpclass,
  683. LHCLIENTDOC lhclientdoc,
  684. LPSTR lpobjname,
  685. LPOLEOBJECT FAR * lplpoleobject,
  686. OLEOPT_RENDER optRender,
  687. OLECLIPFORMAT cfFormat
  688. ){
  689. if (gbCreateInvisible) {
  690. // this is in fact a call for invisible create
  691. return LeCreateInvisible (lpclient, lpclass, lhclientdoc, lpobjname,
  692. lplpoleobject, optRender, cfFormat, gbLaunchServer);
  693. }
  694. return CreateFromClassOrTemplate (lpclient, lpclass, lplpoleobject,
  695. optRender, cfFormat, LN_NEW, NULL,
  696. lhclientdoc, lpobjname);
  697. }
  698. OLESTATUS FARINTERNAL CreateFromClassOrTemplate (
  699. LPOLECLIENT lpclient,
  700. LPSTR lpclass,
  701. LPOLEOBJECT FAR * lplpoleobject,
  702. OLEOPT_RENDER optRender,
  703. OLECLIPFORMAT cfFormat,
  704. UINT lnType,
  705. LPSTR lptemplate,
  706. LHCLIENTDOC lhclientdoc,
  707. LPSTR lpobjname
  708. ){
  709. OLESTATUS retval = OLE_ERROR_MEMORY;
  710. LPOBJECT_LE lpobj = NULL;
  711. ATOM aServer;
  712. char chVerb [32];
  713. if (!(aServer = GetAppAtom (lpclass)))
  714. return OLE_ERROR_CLASS;
  715. if(!(lpobj = LeCreateBlank (lhclientdoc, lpobjname, CT_EMBEDDED))) {
  716. GlobalDeleteAtom (aServer);
  717. goto errRtn;
  718. }
  719. // Now set the server.
  720. lpobj->head.lpclient = lpclient;
  721. lpobj->app = GlobalAddAtom (lpclass);
  722. SetEmbeddedTopic (lpobj);
  723. lpobj->item = (ATOM)0;
  724. lpobj->bOleServer = QueryVerb (lpobj, 0, (LPSTR)&chVerb, 32);
  725. lpobj->aServer = aServer;
  726. // launch the app and start the system conversation.
  727. if (!CreatePictObject (lhclientdoc, lpobjname, lpobj,
  728. optRender, cfFormat, lpclass))
  729. goto errRtn;
  730. // show the window. Advise for data and close on receiving data
  731. lpobj->fCmd = (UINT)(lnType | ACT_SHOW | ACT_ADVISE | ACT_CLOSE);
  732. InitAsyncCmd (lpobj, lptemplate? OLE_CREATEFROMTEMPLATE : OLE_CREATE, EMBOPENUPDATE);
  733. *lplpoleobject = (LPOLEOBJECT)lpobj;
  734. lpobj->lptemplate = lptemplate;
  735. if ((retval = EmbOpenUpdate (lpobj)) <= OLE_WAIT_FOR_RELEASE)
  736. return retval;
  737. // If there is error afterwards, then the client app should call
  738. // to delete the object.
  739. errRtn:
  740. // for error termination OleDelete will terminate any conversation
  741. // in action.
  742. if (lpobj) {
  743. // This oledelete will not result in asynchronous command.
  744. OleDelete ((LPOLEOBJECT)lpobj);
  745. *lplpoleobject = NULL;
  746. }
  747. return retval;
  748. }
  749. OLESTATUS FARINTERNAL CreateEmbLnkFromFile (
  750. LPOLECLIENT lpclient,
  751. LPCSTR lpclass,
  752. LPSTR lpfile,
  753. LPSTR lpitem,
  754. LHCLIENTDOC lhclientdoc,
  755. LPSTR lpobjname,
  756. LPOLEOBJECT FAR * lplpoleobject,
  757. OLEOPT_RENDER optRender,
  758. OLECLIPFORMAT cfFormat,
  759. LONG objType
  760. ){
  761. OLESTATUS retval = OLE_ERROR_MEMORY;
  762. LPOBJECT_LE lpobj = NULL;
  763. ATOM aServer;
  764. char buf[MAX_STR];
  765. OLE_RELEASE_METHOD releaseMethod;
  766. UINT wFlags = 0;
  767. char chVerb[32];
  768. if (!lpclass && (lpclass = (LPSTR) buf)
  769. && !MapExtToClass (lpfile, (LPSTR)buf, MAX_STR))
  770. return OLE_ERROR_CLASS;
  771. if (!(aServer = GetAppAtom (lpclass)))
  772. return OLE_ERROR_CLASS;
  773. if (!(lpobj = LeCreateBlank (lhclientdoc, lpobjname, CT_LINK))) {
  774. GlobalDeleteAtom (aServer);
  775. goto errFileCreate;
  776. }
  777. lpobj->head.lpclient = lpclient;
  778. lpobj->app = GlobalAddAtom (lpclass);
  779. lpobj->topic = GlobalAddAtom (lpfile);
  780. lpobj->aServer = aServer;
  781. lpobj->bOleServer = QueryVerb (lpobj, 0, (LPSTR)&chVerb, 32);
  782. if ((retval = SetNetName (lpobj)) != OLE_OK)
  783. goto errFileCreate;
  784. if (lpitem)
  785. lpobj->item = GlobalAddAtom (lpitem);
  786. if (!CreatePictObject (lhclientdoc, lpobjname, lpobj,
  787. optRender, cfFormat, lpclass)) {
  788. retval = OLE_ERROR_MEMORY;
  789. goto errFileCreate;
  790. }
  791. *lplpoleobject = (LPOLEOBJECT) lpobj;
  792. if (objType == CT_EMBEDDED) {
  793. releaseMethod = OLE_CREATEFROMFILE;
  794. if ((optRender == olerender_format) && (cfFormat == cfNative))
  795. wFlags = 0;
  796. else
  797. wFlags = ACT_NATIVE;
  798. }
  799. else {
  800. // caller wants linked object to be created
  801. // if no presentation data is requested and the link is to the whole
  802. // file, then there is no need to launch the server.
  803. if ((optRender == olerender_none) && !lpobj->item)
  804. return FileExists (lpobj);
  805. // we want to establish hot link
  806. wFlags = ACT_ADVISE;
  807. releaseMethod = OLE_CREATELINKFROMFILE;
  808. }
  809. lpobj->fCmd = (UINT)(LN_LNKACT | ACT_REQUEST | ACT_UNLAUNCH | wFlags);
  810. InitAsyncCmd (lpobj, releaseMethod , LNKOPENUPDATE);
  811. if ((retval = LnkOpenUpdate (lpobj)) <= OLE_WAIT_FOR_RELEASE)
  812. return retval;
  813. // If there is error afterwards, then the client app should call
  814. // to delete the object.
  815. errFileCreate:
  816. if (lpobj) {
  817. // This oledelete will not result in asynchronous command.
  818. OleDelete ((LPOLEOBJECT)lpobj);
  819. *lplpoleobject = NULL;
  820. }
  821. return retval;
  822. }
  823. //////////////////////////////////////////////////////////////////////////////
  824. //
  825. // OLESTATUS FARINTERNAL LeCreateInvisible (lpclient, lpclass, lhclientdoc, lpobjname, lplpoleobject, optRender, cfFormat, bActivate)
  826. //
  827. // Arguments:
  828. //
  829. // lpclient -
  830. // lpclass -
  831. // lhclientdoc -
  832. // lpobjname -
  833. // lplpoleobject -
  834. // optRender -
  835. // cfFormat -
  836. // fActivate -
  837. //
  838. // Returns:
  839. //
  840. // OLE_ERROR_CLASS -
  841. // OLE_OK -
  842. // EmbOpenUpdate (lpobj) -
  843. // retval -
  844. //
  845. // Effects:
  846. //
  847. //////////////////////////////////////////////////////////////////////////////
  848. OLESTATUS FARINTERNAL LeCreateInvisible (
  849. LPOLECLIENT lpclient,
  850. LPSTR lpclass,
  851. LHCLIENTDOC lhclientdoc,
  852. LPSTR lpobjname,
  853. LPOLEOBJECT FAR * lplpoleobject,
  854. OLEOPT_RENDER optRender,
  855. OLECLIPFORMAT cfFormat,
  856. BOOL fActivate
  857. ){
  858. OLESTATUS retval = OLE_ERROR_MEMORY;
  859. LPOBJECT_LE lpobj = NULL;
  860. ATOM aServer;
  861. char chVerb [32];
  862. if (!(aServer = GetAppAtom (lpclass)))
  863. return OLE_ERROR_CLASS;
  864. if(!(lpobj = LeCreateBlank (lhclientdoc, lpobjname, CT_EMBEDDED))) {
  865. GlobalDeleteAtom (aServer);
  866. goto errRtn;
  867. }
  868. // Now set the server.
  869. lpobj->head.lpclient = lpclient;
  870. lpobj->app = GlobalAddAtom (lpclass);
  871. lpobj->item = (ATOM)0;
  872. lpobj->bOleServer = QueryVerb (lpobj, 0, (LPSTR)&chVerb, 32);
  873. lpobj->aServer = aServer;
  874. lpobj->lptemplate = NULL;
  875. SetEmbeddedTopic (lpobj);
  876. if (!CreatePictObject (lhclientdoc, lpobjname, lpobj,
  877. optRender, cfFormat, lpclass))
  878. goto errRtn;
  879. *lplpoleobject = (LPOLEOBJECT)lpobj;
  880. if (!fActivate)
  881. return OLE_OK;
  882. // show the window. Advise for data and close on receiving data
  883. lpobj->fCmd = LN_NEW | ACT_ADVISE | ACT_CLOSE;
  884. InitAsyncCmd (lpobj, OLE_CREATEINVISIBLE, EMBOPENUPDATE);
  885. // launch the app and start the system conversation.
  886. if ((retval = EmbOpenUpdate (lpobj)) <= OLE_WAIT_FOR_RELEASE)
  887. return retval;
  888. // If there is error afterwards, then the client app should call
  889. // to delete the object.
  890. errRtn:
  891. // for error termination OleDelete will terminate any conversation
  892. // in action.
  893. if (lpobj) {
  894. // This oledelete will not result in asynchronous command.
  895. OleDelete ((LPOLEOBJECT)lpobj);
  896. *lplpoleobject = NULL;
  897. }
  898. return retval;
  899. }
  900. // LeSetUpdateOptions: sets the update options. If the server
  901. // is connectd then it unadvises for the current options and
  902. // advises for the new options.
  903. OLESTATUS FARINTERNAL LeSetUpdateOptions (
  904. LPOLEOBJECT lpoleobj,
  905. OLEOPT_UPDATE options
  906. ){
  907. LPOBJECT_LE lpobj = (LPOBJECT_LE)lpoleobj;
  908. PROBE_OLDLINK (lpobj);
  909. PROBE_ASYNC (lpobj);
  910. //!!! make sure the options are within range.
  911. if (lpobj->head.ctype != CT_LINK)
  912. return (OLE_ERROR_OBJECT);
  913. if (options > oleupdate_oncall)
  914. return OLE_ERROR_OPTION;
  915. if (lpobj->optUpdate == options)
  916. return OLE_OK;
  917. if (!QueryOpen (lpobj) || IS_SVRCLOSING(lpobj)) {
  918. lpobj->optUpdate = options;
  919. return OLE_OK;
  920. }
  921. lpobj->optNew = options;
  922. lpobj->fCmd = 0;
  923. InitAsyncCmd (lpobj, OLE_SETUPDATEOPTIONS, LNKSETUPDATEOPTIONS);
  924. return LnkSetUpdateOptions (lpobj);
  925. }
  926. OLESTATUS LnkSetUpdateOptions (LPOBJECT_LE lpobj)
  927. {
  928. switch (lpobj->subRtn) {
  929. case 0:
  930. if (lpobj->optUpdate == oleupdate_oncall)
  931. goto step1;
  932. // If the server is active then unadvise for old
  933. // options.
  934. UnAdvisePict (lpobj);
  935. WAIT_FOR_ASYNC_MSG (lpobj);
  936. case 1:
  937. step1:
  938. SETSTEP (lpobj, 1);
  939. ProcessErr (lpobj);
  940. lpobj->optUpdate = lpobj->optNew;
  941. if (lpobj->optUpdate == oleupdate_oncall)
  942. goto step3;
  943. AdvisePict (lpobj, (ATOM)0);
  944. WAIT_FOR_ASYNC_MSG (lpobj);
  945. case 2:
  946. SETSTEP (lpobj, 2);
  947. if (ProcessErr (lpobj))
  948. goto errRtn;
  949. if (lpobj->optUpdate == oleupdate_onsave)
  950. goto step3;
  951. RequestPict (lpobj);
  952. WAIT_FOR_ASYNC_MSG (lpobj);
  953. case 3:
  954. errRtn:
  955. step3:
  956. ProcessErr (lpobj);
  957. return EndAsyncCmd (lpobj);
  958. default:
  959. DEBUG_OUT ("Unexpected subroutine", 0);
  960. return OLE_ERROR_GENERIC;
  961. }
  962. }
  963. //AdvisePict: Sends advise for pict data
  964. void INTERNAL AdvisePict (
  965. LPOBJECT_LE lpobj,
  966. ATOM aAdvItem
  967. ){
  968. int cftype;
  969. if (cftype = GetPictType (lpobj))
  970. AdviseOn (lpobj, cftype, aAdvItem);
  971. }
  972. //UnAdvisePict: Sends unadvise for pict data
  973. void INTERNAL UnAdvisePict (LPOBJECT_LE lpobj)
  974. {
  975. int cftype;
  976. SETERRHINT (lpobj, OLE_ERROR_ADVISE_PICT);
  977. if (cftype = GetPictType (lpobj))
  978. UnAdviseOn (lpobj, cftype);
  979. }
  980. // GetPictType: Given the object, returns the pict type.
  981. int INTERNAL GetPictType (LPOBJECT_LE lpobj)
  982. {
  983. if (lpobj->lpobjPict)
  984. return (int)(*lpobj->lpobjPict->lpvtbl->EnumFormats)
  985. (lpobj->lpobjPict, 0);
  986. return 0;
  987. }
  988. // AdviseOn : Sends advise for a given picture type
  989. // Send advise only if the advise options is not on call.
  990. void INTERNAL AdviseOn (
  991. LPOBJECT_LE lpobj,
  992. int cftype,
  993. ATOM advItem
  994. ){
  995. HANDLE hopt = NULL;
  996. DDEADVISE FAR *lpopt = NULL;
  997. ATOM item = (ATOM)0;
  998. PEDIT_DDE pedit;
  999. OLESTATUS retval= OLE_ERROR_MEMORY;
  1000. LPARAM lParamNew;
  1001. if (cftype == (int)cfNative)
  1002. SETERRHINT (lpobj, OLE_ERROR_ADVISE_NATIVE);
  1003. else {
  1004. if (cftype == (int)cfBinary)
  1005. SETERRHINT (lpobj, OLE_ERROR_ADVISE_RENAME);
  1006. else
  1007. SETERRHINT (lpobj, OLE_ERROR_ADVISE_PICT);
  1008. }
  1009. if (lpobj->optUpdate == oleupdate_oncall)
  1010. return;
  1011. if(!(hopt = GlobalAlloc (GMEM_DDESHARE | GMEM_ZEROINIT, sizeof(DDEADVISE))))
  1012. goto errRtn;
  1013. retval = OLE_ERROR_MEMORY;
  1014. if(!(lpopt = (DDEADVISE FAR *) GlobalLock (hopt)))
  1015. goto errRtn;
  1016. pedit = lpobj->pDocEdit;
  1017. lpopt->fAckReq = TRUE;
  1018. // get data always. Currently there is no way for the
  1019. // deferred updates.
  1020. lpopt->fDeferUpd = 0;
  1021. lpopt->cfFormat = (WORD)cftype;
  1022. GlobalUnlock (hopt);
  1023. pedit->hopt = hopt;
  1024. if (advItem == aStdDocName)
  1025. item = DuplicateAtom (advItem);
  1026. else
  1027. item = ExtendAtom (lpobj, lpobj->item);
  1028. retval = OLE_ERROR_COMM;
  1029. if (!PostMessageToServer(pedit, WM_DDE_ADVISE,
  1030. lParamNew = MAKE_DDE_LPARAM(WM_DDE_ADVISE, (UINT_PTR)hopt, item)))
  1031. {
  1032. DDEFREE(WM_DDE_ADVISE,lParamNew);
  1033. goto errRtn;
  1034. }
  1035. #ifdef FIREWALLS
  1036. ASSERT (!pedit->bTerminating, "trying to post while termination")
  1037. ASSERT (pedit->awaitAck == NULL, "Trying to Post msg while waiting for ack")
  1038. #endif
  1039. pedit->awaitAck = AA_ADVISE;
  1040. lpobj->bAsync = TRUE;
  1041. if (advItem == aClose)
  1042. lpobj->pDocEdit->nAdviseClose++;
  1043. else if (advItem == aSave)
  1044. lpobj->pDocEdit->nAdviseSave++;
  1045. return;
  1046. errRtn:
  1047. if (item)
  1048. GlobalDeleteAtom (item);
  1049. if (lpopt)
  1050. GlobalUnlock (hopt);
  1051. if (hopt)
  1052. GlobalFree (hopt);
  1053. lpobj->subErr = retval;
  1054. return ;
  1055. }
  1056. //UnAdviseOn: Sends unadvise for an item.
  1057. void INTERNAL UnAdviseOn (
  1058. LPOBJECT_LE lpobj,
  1059. int cftype
  1060. ){
  1061. ATOM item;
  1062. PEDIT_DDE pedit;
  1063. UNREFERENCED_PARAMETER(cftype);
  1064. pedit = lpobj->pDocEdit;
  1065. item = ExtendAtom (lpobj, lpobj->item);
  1066. if (!PostMessageToServer(pedit, WM_DDE_UNADVISE, MAKELONG (NULL, item)))
  1067. lpobj->subErr = OLE_ERROR_COMM;
  1068. else {
  1069. #ifdef FIREWALLS
  1070. ASSERT (!pedit->bTerminating, "trying to post while termination")
  1071. ASSERT (pedit->awaitAck == NULL, "Trying to Post msg while waiting for ack")
  1072. #endif
  1073. lpobj->bAsync = TRUE;
  1074. pedit->awaitAck = AA_UNADVISE;
  1075. }
  1076. }
  1077. // RequestOn: Semd WM_DDE_REQUEST for the item of the
  1078. // for a given type;
  1079. void INTERNAL RequestOn (
  1080. LPOBJECT_LE lpobj,
  1081. int cftype
  1082. ){
  1083. ATOM item = (ATOM)0;
  1084. PEDIT_DDE pedit;
  1085. OLESTATUS retval = OLE_ERROR_COMM;
  1086. if (cftype == (int)cfNative)
  1087. SETERRHINT (lpobj, OLE_ERROR_REQUEST_NATIVE);
  1088. else
  1089. SETERRHINT (lpobj, OLE_ERROR_REQUEST_PICT);
  1090. pedit = lpobj->pDocEdit;
  1091. item = DuplicateAtom (lpobj->item);
  1092. if (!PostMessageToServer (pedit, WM_DDE_REQUEST, MAKELONG (cftype, item)))
  1093. goto errRtn;
  1094. #ifdef FIREWALLS
  1095. ASSERT (!pedit->bTerminating, "trying to post while termination")
  1096. ASSERT (pedit->awaitAck == NULL, "Trying to Post msg while waiting for ack")
  1097. #endif
  1098. lpobj->bAsync = TRUE;
  1099. pedit->awaitAck = AA_REQUEST;
  1100. return;
  1101. errRtn:
  1102. if (item)
  1103. GlobalDeleteAtom (item);
  1104. return ;
  1105. }
  1106. //RequestPict: Sends request for apicture type.
  1107. void INTERNAL RequestPict (LPOBJECT_LE lpobj)
  1108. {
  1109. int cftype;
  1110. if (cftype = GetPictType (lpobj))
  1111. RequestOn (lpobj, cftype);
  1112. }
  1113. // LeSetHostNames: Sets the host names. If the server is connected
  1114. // send the host names to the server.
  1115. OLESTATUS FARINTERNAL LeSetHostNames (
  1116. LPOLEOBJECT lpoleobj,
  1117. OLE_LPCSTR lpclientName,
  1118. OLE_LPCSTR lpdocName
  1119. ){
  1120. LPOBJECT_LE lpobj = (LPOBJECT_LE)lpoleobj;
  1121. OLESTATUS retval = OLE_ERROR_MEMORY;
  1122. if (lpobj->head.ctype != CT_EMBEDDED)
  1123. return OLE_ERROR_OBJECT;
  1124. PROBE_ASYNC (lpobj);
  1125. if ((retval = SetHostNamesHandle (lpobj, (LPSTR)lpclientName, (LPSTR)lpdocName))
  1126. != OLE_OK)
  1127. return retval;
  1128. // If the server is connected poke the hostnames
  1129. InitAsyncCmd (lpobj, OLE_OTHER, 0);
  1130. if ((retval = PokeHostNames (lpobj)) != OLE_WAIT_FOR_RELEASE)
  1131. CLEARASYNCCMD(lpobj);
  1132. return retval;
  1133. }
  1134. OLESTATUS FARINTERNAL LeSetTargetDevice (
  1135. LPOLEOBJECT lpoleobj,
  1136. HANDLE hdata
  1137. ){
  1138. LPOBJECT_LE lpobj = (LPOBJECT_LE)lpoleobj;
  1139. HANDLE hdup = NULL;
  1140. OLESTATUS retval;
  1141. PROBE_ASYNC (lpobj);
  1142. if(!(hdup = DuplicateGlobal (hdata, GMEM_MOVEABLE)))
  1143. return OLE_ERROR_MEMORY;
  1144. if (lpobj->htargetDevice)
  1145. GlobalFree (lpobj->htargetDevice);
  1146. lpobj->htargetDevice = hdup;
  1147. InitAsyncCmd (lpobj, OLE_OTHER, 0);
  1148. if ((retval = PokeTargetDeviceInfo (lpobj)) != OLE_WAIT_FOR_RELEASE)
  1149. CLEARASYNCCMD(lpobj);
  1150. return retval;
  1151. }
  1152. OLESTATUS FARINTERNAL LeSetBounds(
  1153. LPOLEOBJECT lpoleobj,
  1154. OLE_CONST RECT FAR* lprcBounds
  1155. ){
  1156. LPOBJECT_LE lpobj = (LPOBJECT_LE)lpoleobj;
  1157. OLESTATUS retval = OLE_ERROR_MEMORY;
  1158. HANDLE hdata = NULL;
  1159. LPBOUNDSRECT lprc = NULL;
  1160. PROBE_ASYNC (lpobj);
  1161. if (lpobj->head.ctype != CT_EMBEDDED)
  1162. return OLE_ERROR_OBJECT;
  1163. if(!(hdata = GlobalAlloc (GMEM_MOVEABLE, (UINT)sizeof (BOUNDSRECT))))
  1164. return OLE_ERROR_MEMORY;
  1165. if (!(lprc = (LPBOUNDSRECT)GlobalLock (hdata)))
  1166. goto errrtn;
  1167. //
  1168. // Now set the data
  1169. //
  1170. // Note: The 16-bit implementations are expecting USHORT sized values
  1171. // Actually, they are expected a 16-bit RECT which is 4 ints. Why we
  1172. // are sending a LPBOUNDSRECT instead of a 16-bit RECT is a mystery,
  1173. // but thats the backward compatible story.
  1174. //
  1175. lprc->defaultWidth = (USHORT) (lprcBounds->right - lprcBounds->left);
  1176. lprc->defaultHeight = (USHORT) -(lprcBounds->bottom - lprcBounds->top);
  1177. lprc->maxWidth = (USHORT) (lprcBounds->right - lprcBounds->left);
  1178. lprc->maxHeight = (USHORT) -(lprcBounds->bottom - lprcBounds->top);
  1179. GlobalUnlock (hdata);
  1180. if (lpobj->hdocDimensions)
  1181. GlobalFree (lpobj->hdocDimensions);
  1182. lpobj->hdocDimensions = hdata;
  1183. InitAsyncCmd (lpobj, OLE_OTHER, 0);
  1184. if ((retval = PokeDocDimensions (lpobj)) != OLE_WAIT_FOR_RELEASE)
  1185. CLEARASYNCCMD(lpobj);
  1186. return retval;
  1187. errrtn:
  1188. if (lprc)
  1189. GlobalUnlock (hdata);
  1190. if (hdata)
  1191. GlobalFree (hdata);
  1192. return retval;
  1193. }
  1194. OLESTATUS FARINTERNAL LeSetData (
  1195. LPOLEOBJECT lpoleobj,
  1196. OLECLIPFORMAT cfFormat,
  1197. HANDLE hData
  1198. ){
  1199. LPOBJECT_LE lpobj = (LPOBJECT_LE)lpoleobj;
  1200. OLESTATUS retVal = OLE_OK;
  1201. BOOL fKnown = FALSE;
  1202. PROBE_ASYNC (lpobj);
  1203. if ((cfFormat == cfObjectLink) || (cfFormat == cfOwnerLink))
  1204. return ChangeDocAndItem (lpobj, hData);
  1205. if (fKnown = (cfFormat && (cfFormat == (OLECLIPFORMAT)GetPictType (lpobj)))) {
  1206. retVal = (*lpobj->lpobjPict->lpvtbl->ChangeData) (lpobj->lpobjPict,
  1207. hData, lpobj->head.lpclient, FALSE);
  1208. (*lpobj->lpobjPict->lpvtbl->GetData) (lpobj->lpobjPict,
  1209. cfFormat, &hData);
  1210. }
  1211. else if (fKnown = (cfFormat == cfNative)) {
  1212. retVal = LeChangeData (lpoleobj, hData, lpobj->head.lpclient, FALSE);
  1213. hData = lpobj->hnative;
  1214. }
  1215. if (retVal != OLE_OK)
  1216. return retVal;
  1217. if (fKnown)
  1218. ContextCallBack ((LPOLEOBJECT)lpobj, OLE_CHANGED);
  1219. if (!QueryOpen (lpobj) || IS_SVRCLOSING(lpobj)) {
  1220. if (!fKnown)
  1221. return OLE_ERROR_NOT_OPEN;
  1222. return OLE_OK;
  1223. }
  1224. // except for the following formats all the other data will be copied
  1225. // into DDEPOKE block. So there is no need to duplicate the data of the
  1226. // other formats
  1227. if ( cfFormat == CF_METAFILEPICT
  1228. || cfFormat == CF_ENHMETAFILE
  1229. || cfFormat == CF_BITMAP
  1230. || cfFormat == CF_DIB)
  1231. {
  1232. if (!(hData = DuplicateGDIdata (hData, cfFormat)))
  1233. return OLE_ERROR_MEMORY;
  1234. }
  1235. // *** The last parameter must be NULL, don't change it ***
  1236. InitAsyncCmd (lpobj, OLE_SETDATA, 0);
  1237. if ((retVal = SendPokeData (lpobj, lpobj->item, hData, cfFormat))
  1238. != OLE_WAIT_FOR_RELEASE)
  1239. CLEARASYNCCMD(lpobj);
  1240. return retVal;
  1241. }
  1242. OLESTATUS FARINTERNAL LeSetColorScheme (
  1243. LPOLEOBJECT lpoleobj,
  1244. OLE_CONST LOGPALETTE FAR* lplogpal
  1245. ){
  1246. LPOBJECT_LE lpobj = (LPOBJECT_LE)lpoleobj;
  1247. HANDLE hdup = NULL;
  1248. DWORD cblogpal;
  1249. OLESTATUS retval;
  1250. LPBYTE lptemp;
  1251. lptemp = (LPBYTE) lplogpal;
  1252. if (lpobj->head.ctype != CT_EMBEDDED)
  1253. return OLE_ERROR_OBJECT;
  1254. PROBE_ASYNC (lpobj);
  1255. FARPROBE_READ(lptemp + (cblogpal = 2*sizeof(UINT)));
  1256. cblogpal += ((sizeof(PALETTEENTRY) * lplogpal->palNumEntries) -1);
  1257. if (!FarCheckPointer (lptemp + cblogpal, READ_ACCESS))
  1258. return OLE_ERROR_PALETTE;
  1259. if (!(hdup = CopyData ((LPSTR) lplogpal, cblogpal)))
  1260. return OLE_ERROR_MEMORY;
  1261. if (lpobj->hlogpal)
  1262. GlobalFree (lpobj->hlogpal);
  1263. lpobj->hlogpal = hdup;
  1264. InitAsyncCmd (lpobj, OLE_OTHER, 0);
  1265. if ((retval = PokeColorScheme (lpobj)) != OLE_WAIT_FOR_RELEASE)
  1266. CLEARASYNCCMD(lpobj);
  1267. return retval;
  1268. }
  1269. //PokeHostNames: Pokes hostname data to the server
  1270. OLESTATUS INTERNAL PokeHostNames (LPOBJECT_LE lpobj)
  1271. {
  1272. OLESTATUS retVal = OLE_ERROR_MEMORY;
  1273. // if the server is connectd then poke the host names
  1274. if (!QueryOpen (lpobj) || IS_SVRCLOSING(lpobj))
  1275. return OLE_OK;
  1276. if (!lpobj->hhostNames)
  1277. return OLE_OK;
  1278. aStdHostNames = GlobalAddAtom ("StdHostNames");
  1279. return SendPokeData (lpobj,aStdHostNames,lpobj->hhostNames,cfBinary);
  1280. }
  1281. OLESTATUS INTERNAL PokeTargetDeviceInfo (LPOBJECT_LE lpobj)
  1282. {
  1283. // if the server is connectd then poke the host names
  1284. if (!QueryOpen (lpobj) || IS_SVRCLOSING(lpobj))
  1285. return OLE_OK;
  1286. if (!lpobj->htargetDevice)
  1287. return OLE_OK;
  1288. aStdTargetDevice = GlobalAddAtom ("StdTargetDevice");
  1289. return SendPokeData (lpobj, aStdTargetDevice,
  1290. lpobj->htargetDevice,
  1291. cfBinary);
  1292. }
  1293. OLESTATUS INTERNAL PokeDocDimensions (LPOBJECT_LE lpobj)
  1294. {
  1295. // if the server is connectd then poke the host names
  1296. if (!QueryOpen (lpobj) || IS_SVRCLOSING(lpobj))
  1297. return OLE_OK;
  1298. if (!lpobj->hdocDimensions)
  1299. return OLE_OK;
  1300. aStdDocDimensions = GlobalAddAtom ("StdDocDimensions");
  1301. return SendPokeData (lpobj, aStdDocDimensions,
  1302. lpobj->hdocDimensions,
  1303. cfBinary);
  1304. }
  1305. OLESTATUS INTERNAL PokeColorScheme (LPOBJECT_LE lpobj)
  1306. {
  1307. // if the server is connected then poke the palette info
  1308. if (!QueryOpen (lpobj) || IS_SVRCLOSING(lpobj))
  1309. return OLE_OK;
  1310. if (!lpobj->hlogpal)
  1311. return OLE_OK;
  1312. aStdColorScheme = GlobalAddAtom ("StdColorScheme");
  1313. return SendPokeData (lpobj, aStdColorScheme,
  1314. lpobj->hlogpal,
  1315. cfBinary);
  1316. }
  1317. OLESTATUS INTERNAL SendPokeData (
  1318. LPOBJECT_LE lpobj,
  1319. ATOM aItem,
  1320. HANDLE hdata,
  1321. OLECLIPFORMAT cfFormat
  1322. ){
  1323. HANDLE hdde = NULL;
  1324. DDEPOKE FAR * lpdde = NULL;
  1325. LPSTR lpdst = NULL;
  1326. LPSTR lpsrc = NULL;
  1327. OLESTATUS retval = OLE_ERROR_MEMORY;
  1328. DWORD dwSize = 0;
  1329. PEDIT_DDE pedit;
  1330. BOOL bGDIdata = FALSE;
  1331. LPARAM lParamNew;
  1332. pedit = lpobj->pDocEdit;
  1333. // If it is GDI data then we can stuff the handle into POKE block.
  1334. // Otherwise we have to copy the data into DDE data block. There
  1335. // is a special case with old MSDraw, that will be handled by
  1336. // the routine CanPutHandleInPokeBlock()
  1337. if (!(bGDIdata = CanPutHandleInPokeBlock (lpobj, cfFormat))) {
  1338. if (!(dwSize = (DWORD)GlobalSize (hdata)))
  1339. return OLE_ERROR_MEMORY;
  1340. if (!(lpsrc = (LPSTR) GlobalLock (hdata)))
  1341. return OLE_ERROR_MEMORY;
  1342. GlobalUnlock (hdata);
  1343. }
  1344. // Now allocate the DDE data block
  1345. if (!(hdde = GlobalAlloc (GMEM_DDESHARE | GMEM_ZEROINIT,
  1346. (dwSize + sizeof(DDEPOKE) - sizeof(BYTE) + sizeof(HANDLE)))))
  1347. goto errRtn;
  1348. if (!(lpdde = (DDEPOKE FAR *)GlobalLock (hdde)))
  1349. goto errRtn;
  1350. GlobalUnlock (hdde);
  1351. // !!! We may want to set it TRUE, for performance reasons. But it
  1352. // will require some rework on the server side
  1353. lpdde->fRelease = 0;
  1354. lpdde->cfFormat = (WORD)cfFormat;
  1355. if (bGDIdata) {
  1356. #ifdef _WIN64
  1357. if (lpdde->cfFormat == CF_METAFILEPICT)
  1358. *(void* _unaligned*)lpdde->Value = hdata;
  1359. else
  1360. #endif
  1361. *(LONG*)lpdde->Value = HandleToLong(hdata);
  1362. } else {
  1363. lpdst = (LPSTR)lpdde->Value;
  1364. UtilMemCpy (lpdst, lpsrc, dwSize);
  1365. // For the CF_METAFILEPICT format, we would come here only if we are
  1366. // dealing with the old version of MSDraw. In that case we want to
  1367. // free the handle to METAFILEPICT strcuture, because we've already
  1368. // copied its contents to DDEPOKE structure.
  1369. // Note that that the old MSDraw expects the contents of METAFILEPICT
  1370. // structure to be part of DDEPOKE, rather than the handle to it.
  1371. if (cfFormat == CF_METAFILEPICT) {
  1372. GlobalFree (hdata);
  1373. hdata = NULL;
  1374. }
  1375. }
  1376. // *** From here onwards if there is an error call FreePokeData(), don't
  1377. // jump to errRtn
  1378. aItem = DuplicateAtom (aItem);
  1379. ASSERT(pedit->hData == NULL, "Poke data is not null");
  1380. pedit->hData = hdde;
  1381. if (!PostMessageToServer (pedit, WM_DDE_POKE,
  1382. lParamNew = MAKE_DDE_LPARAM(WM_DDE_POKE, (UINT_PTR)hdde, aItem)))
  1383. {
  1384. if (aItem)
  1385. GlobalDeleteAtom (aItem);
  1386. FreePokeData (lpobj, pedit);
  1387. DDEFREE(WM_DDE_POKE,lParamNew);
  1388. return (lpobj->subErr = OLE_ERROR_COMM);
  1389. }
  1390. #ifdef FIREWALLS
  1391. ASSERT (!pedit->bTerminating, "trying to post while termination")
  1392. ASSERT (pedit->awaitAck == NULL, "Trying to Post msg while waiting for ack")
  1393. #endif
  1394. if (lpobj->asyncCmd == OLE_NONE)
  1395. lpobj->asyncCmd = OLE_OTHER;
  1396. lpobj->bAsync = TRUE;
  1397. pedit->awaitAck = AA_POKE;
  1398. // !!! after poke of the hostnames etc. we are not processing error.,
  1399. // Data is freed after the Poke is acknowledged. OLE_RELEASE will be sent
  1400. // to when ACK comes.
  1401. return OLE_WAIT_FOR_RELEASE;
  1402. errRtn:
  1403. if (hdata)
  1404. FreeGDIdata (hdata, cfFormat);
  1405. if (hdde)
  1406. GlobalFree (hdde);
  1407. pedit->hData = NULL;
  1408. return (lpobj->subErr = retval);
  1409. }
  1410. // FreePokeData: Frees the poked data.
  1411. void INTERNAL FreePokeData (
  1412. LPOBJECT_LE lpobj,
  1413. PEDIT_DDE pedit
  1414. ){
  1415. DDEPOKE FAR * lpdde;
  1416. #ifdef FIREWALLS
  1417. ASSERT (pedit->hData, "Poke data handle is null");
  1418. #endif
  1419. if (lpdde = (DDEPOKE FAR *) GlobalLock (pedit->hData)) {
  1420. GlobalUnlock (pedit->hData);
  1421. // The old version of MSDraw expects the contents of METAFILEPICT
  1422. // structure to be part of DDEPOKE, rather than the handle to it.
  1423. if (!lpobj->bOleServer && (lpobj->app == aMSDraw)
  1424. && (lpdde->cfFormat == CF_METAFILEPICT)) {
  1425. DeleteMetaFile (((LPMETAFILEPICT) ((LPSTR) &lpdde->Value))->hMF);
  1426. }
  1427. else {
  1428. #ifdef _WIN64
  1429. if (lpdde->cfFormat == CF_METAFILEPICT)
  1430. FreeGDIdata(*(void* _unaligned*)lpdde->Value, lpdde->cfFormat);
  1431. else
  1432. #endif
  1433. FreeGDIdata (LongToHandle(*(LONG*)lpdde->Value), lpdde->cfFormat);
  1434. }
  1435. }
  1436. GlobalFree (pedit->hData);
  1437. pedit->hData = NULL;
  1438. }
  1439. BOOL INTERNAL SendSrvrMainCmd (
  1440. LPOBJECT_LE lpobj,
  1441. LPSTR lptemplate
  1442. ){
  1443. UINT size;
  1444. UINT len;
  1445. OLESTATUS retval = OLE_ERROR_COMM;
  1446. int cmd = 0;
  1447. HANDLE hInst = NULL;
  1448. LPSTR lpdata= NULL;
  1449. HANDLE hdata = NULL;
  1450. BOOL bLaunch = TRUE;
  1451. Puts("Launch App and Send Sys command");
  1452. #ifdef FIREWALLS
  1453. ASSERT (lpobj->aServer, "Serevr is NULL");
  1454. #endif
  1455. if (!lpobj->aServer) {
  1456. retval = OLE_ERROR_REGISTRATION;
  1457. goto errRtn;
  1458. }
  1459. if (!lpobj->bOldLink) {
  1460. bLaunch = !(lpobj->fCmd & ACT_NOLAUNCH);
  1461. cmd = lpobj->fCmd & LN_MASK;
  1462. }
  1463. if (cmd == LN_LNKACT) {
  1464. // take care of network based document
  1465. char cDrive = lpobj->cDrive;
  1466. if ((retval = CheckNetDrive (lpobj, POPUP_NETDLG)) != OLE_OK) {
  1467. lpobj->cDrive = cDrive;
  1468. goto errRtn;
  1469. }
  1470. if (cDrive != lpobj->cDrive)
  1471. ContextCallBack ((LPOLEOBJECT)lpobj, OLE_RENAMED);
  1472. }
  1473. if (!InitSrvrConv (lpobj, hInst)) {
  1474. if (!bLaunch)
  1475. goto errRtn;
  1476. if (!(hInst = LeLaunchApp (lpobj))) {
  1477. // We failed to launch the app. If it is a linked object, see
  1478. // whether the docname is valid for new servers. We wouldn't
  1479. // have given the doc name on the command line for the old
  1480. // servers. So, there is no point in checking for file existance
  1481. // in that case.
  1482. if (lpobj->bOleServer && (lpobj->bOldLink || (cmd == LN_LNKACT))){
  1483. if ((retval = FileExists (lpobj)) != OLE_OK)
  1484. goto errRtn;
  1485. }
  1486. retval = OLE_ERROR_LAUNCH;
  1487. goto errRtn;
  1488. }
  1489. if (lpobj->bOldLink)
  1490. return TRUE;
  1491. if (lpobj->bOleServer && (cmd == LN_LNKACT)) {
  1492. // We are not using any data blocks if the object is old link.
  1493. // we launched with docname, and don't have to establish system
  1494. // level and also we don't have to send exec strings.
  1495. // for non-ole servers like excel, we do want to connect at
  1496. // the system level, so that we can send "StdOpen". We also
  1497. // have to send "StdExit" for the server to exit in the
  1498. // invisible launch case.
  1499. return TRUE;
  1500. }
  1501. retval = OLE_ERROR_COMM;
  1502. if(!InitSrvrConv (lpobj, hInst))
  1503. goto errRtn;
  1504. #ifdef OLD
  1505. if (!lpobj->bOleServer && (cmd == LN_LNKACT))
  1506. return TRUE;
  1507. #endif
  1508. }
  1509. if (!lpobj->bOldLink) {
  1510. cmd = lpobj->fCmd & LN_MASK;
  1511. len = lstrlen (srvrSysCmd[cmd >> LN_SHIFT]);
  1512. // for template and new, add the class name also
  1513. if (cmd == LN_NEW || cmd == LN_TEMPLATE)
  1514. len += GlobalGetAtomLen (lpobj->app);
  1515. // Now add the document length.
  1516. len += GlobalGetAtomLen (lpobj->topic);
  1517. // add the length of the template name
  1518. if (lptemplate)
  1519. len += lstrlen (lptemplate);
  1520. // now add the fudge factor for the Quotes etc.
  1521. len += LN_FUDGE;
  1522. // allocate the buffer and set the command.
  1523. hdata = GlobalAlloc (GMEM_DDESHARE, size = len);
  1524. retval = OLE_ERROR_MEMORY;
  1525. SETERRHINT(lpobj, OLE_ERROR_MEMORY);
  1526. if (hdata == NULL || (lpdata = (LPSTR)GlobalLock (hdata)) == NULL)
  1527. goto errRtn;
  1528. }
  1529. lstrcpy (lpdata, (LPSTR)"["); // [
  1530. lstrcat (lpdata, srvrSysCmd[cmd >> LN_SHIFT]); // [Std....
  1531. lstrcat (lpdata, "(\""); // [std...("
  1532. if (cmd == LN_NEW || cmd == LN_TEMPLATE) {
  1533. len = lstrlen (lpdata);
  1534. GlobalGetAtomName (lpobj->app, (LPSTR)lpdata + len, size - len);
  1535. // [std...("class
  1536. lstrcat (lpdata, "\",\""); // [std...("class", "
  1537. }
  1538. len = lstrlen (lpdata);
  1539. // now get the topic name.
  1540. GlobalGetAtomName (lpobj->topic, lpdata + len, (UINT)size - len);
  1541. // [std...("class","doc
  1542. if (lptemplate) {
  1543. lstrcat (lpdata, "\",\""); // [std...("class","doc","
  1544. lstrcat (lpdata, lptemplate); // [std...("class","doc","temp
  1545. }
  1546. lstrcat (lpdata, "\")]"); // [std...("class","doc","temp")]
  1547. GlobalUnlock (hdata);
  1548. // !!!optimize with mapping.
  1549. SETERRHINT(lpobj, (OLE_ERROR_TEMPLATE + (cmd >> LN_SHIFT)));
  1550. return SrvrExecute (lpobj, hdata);
  1551. errRtn:
  1552. if (lpdata)
  1553. GlobalUnlock (hdata);
  1554. if (hdata)
  1555. GlobalFree (hdata);
  1556. lpobj->subErr = retval;
  1557. return FALSE;
  1558. }
  1559. // ExtendAtom: Create a new atom, which is the old one plus extension
  1560. ATOM INTERNAL ExtendAtom (
  1561. LPOBJECT_LE lpobj,
  1562. ATOM item
  1563. ){
  1564. char buffer[MAX_ATOM+1];
  1565. LPSTR lpext;
  1566. Puts("ExtendAtom");
  1567. buffer[0] = 0;
  1568. if (item)
  1569. GlobalGetAtomName (item, buffer, MAX_ATOM);
  1570. switch (lpobj->optUpdate) {
  1571. case oleupdate_always:
  1572. lpext = (LPSTR)"";
  1573. break;
  1574. case oleupdate_onsave:
  1575. lpext = (LPSTR)"/Save";
  1576. break;
  1577. case oleupdate_onclose:
  1578. lpext = (LPSTR)"/Close";
  1579. break;
  1580. default:
  1581. ASSERT (FALSE, "on call options not expected here");
  1582. break;
  1583. }
  1584. lstrcat (buffer, lpext);
  1585. if (buffer[0])
  1586. return GlobalAddAtom (buffer);
  1587. else
  1588. return (ATOM)0;
  1589. }
  1590. BOOL INTERNAL CreatePictObject (
  1591. LHCLIENTDOC lhclientdoc,
  1592. LPSTR lpobjname,
  1593. LPOBJECT_LE lpobj,
  1594. OLEOPT_RENDER optRender,
  1595. OLECLIPFORMAT cfFormat,
  1596. LPCSTR lpclass
  1597. ){
  1598. LPOLEOBJECT lpPictObj = NULL;
  1599. ATOM aClass;
  1600. lpobj->lpobjPict = NULL;
  1601. if (optRender == olerender_format) {
  1602. switch (cfFormat) {
  1603. case 0:
  1604. return FALSE;
  1605. case CF_ENHMETAFILE:
  1606. if (!(lpPictObj = (LPOLEOBJECT) EmfCreateBlank (lhclientdoc,
  1607. lpobjname, CT_PICTURE)))
  1608. return FALSE;
  1609. case CF_METAFILEPICT:
  1610. if (!(lpPictObj = (LPOLEOBJECT) MfCreateBlank (lhclientdoc,
  1611. lpobjname, CT_PICTURE)))
  1612. return FALSE;
  1613. break;
  1614. case CF_DIB:
  1615. if (!(lpPictObj = (LPOLEOBJECT) DibCreateBlank (lhclientdoc,
  1616. lpobjname, CT_PICTURE)))
  1617. return FALSE;
  1618. break;
  1619. case CF_BITMAP:
  1620. if (!(lpPictObj = (LPOLEOBJECT) BmCreateBlank (lhclientdoc,
  1621. lpobjname, CT_PICTURE)))
  1622. return FALSE;
  1623. break;
  1624. default:
  1625. aClass = GlobalAddAtom (lpclass);
  1626. if (!(lpPictObj = (LPOLEOBJECT) GenCreateBlank (lhclientdoc,
  1627. lpobjname, CT_PICTURE, aClass)))
  1628. return FALSE;
  1629. ((LPOBJECT_GEN)lpPictObj)->cfFormat = cfFormat;
  1630. break;
  1631. }
  1632. }
  1633. else if (optRender == olerender_draw) {
  1634. #ifdef WIN32HACK
  1635. if (!(lpPictObj = (LPOLEOBJECT) BmCreateBlank (lhclientdoc,
  1636. lpobjname, CT_PICTURE)))
  1637. return FALSE;
  1638. #else
  1639. if (!(lpPictObj = (LPOLEOBJECT) EmfCreateBlank (lhclientdoc,
  1640. lpobjname, CT_PICTURE)))
  1641. return FALSE;
  1642. #endif
  1643. #ifdef LATER
  1644. if (AdviseOn (lpobj, (cfFormat = CF_METAFILEPICT), NULL))
  1645. lpPictObj = (LPOLEOBJECT) MfCreateBlank (lhclientdoc,
  1646. lpobjname, CT_PICTURE);
  1647. // !!! for the time being take assume we need to get metafile.
  1648. else if (AdviseOn (lpobj, (cfFormat = CF_DIB), NULL))
  1649. lpPictObj = (LPOLEOBJECT) DibCreateBlank (lhclientdoc,
  1650. lpobjname, CT_PICTURE);
  1651. else if (AdviseOn (lpobj, (cfFormat = CF_BITMAP), NULL))
  1652. lpPictObj = (LPOLEOBJECT) BmCreateBlank (lhclientdoc,
  1653. lpobjname, CT_PICTURE);
  1654. else
  1655. goto errPict;
  1656. #endif
  1657. }
  1658. else
  1659. return (optRender == olerender_none);
  1660. if (lpobj->lpobjPict = lpPictObj)
  1661. lpobj->lpobjPict->lpParent = (LPOLEOBJECT) lpobj;
  1662. return TRUE;
  1663. }
  1664. OLESTATUS LnkChangeLnk (LPOBJECT_LE lpobj)
  1665. {
  1666. switch (lpobj->subRtn) {
  1667. case 0:
  1668. TermDocConv (lpobj);
  1669. WAIT_FOR_ASYNC_MSG (lpobj);
  1670. case 1:
  1671. // delete the edit block
  1672. DeleteDocEdit (lpobj);
  1673. TermSrvrConv (lpobj);
  1674. WAIT_FOR_ASYNC_MSG (lpobj);
  1675. case 2:
  1676. // Do not set any errors, just delete the object.
  1677. // delete the server edit block
  1678. DeleteSrvrEdit (lpobj);
  1679. // now try to activate the new link.
  1680. SKIP_TO (!InitDocConv (lpobj, !POPUP_NETDLG), step3);
  1681. lpobj->fCmd = LN_LNKACT | ACT_ADVISE | ACT_REQUEST;
  1682. InitAsyncCmd (lpobj, OLE_SETDATA, LNKOPENUPDATE);
  1683. return LnkOpenUpdate (lpobj);
  1684. case 3:
  1685. step3:
  1686. return EndAsyncCmd (lpobj);
  1687. default:
  1688. DEBUG_OUT ("Unexpected subroutine", 0);
  1689. return OLE_ERROR_GENERIC;
  1690. }
  1691. }
  1692. OLESTATUS INTERNAL ChangeDocAndItem (
  1693. LPOBJECT_LE lpobj,
  1694. HANDLE hinfo
  1695. ){
  1696. LPSTR lpinfo;
  1697. ATOM aNewTopic, aNewItem = (ATOM)0, aOldTopic;
  1698. OLESTATUS retVal = OLE_ERROR_BLANK;
  1699. PROBE_SVRCLOSING(lpobj);
  1700. if (!(lpinfo = GlobalLock (hinfo)))
  1701. return OLE_ERROR_MEMORY;
  1702. lpinfo += lstrlen (lpinfo) + 1;
  1703. aNewTopic = GlobalAddAtom (lpinfo);
  1704. lpinfo += lstrlen (lpinfo) + 1;
  1705. if (*lpinfo)
  1706. aNewItem = GlobalAddAtom (lpinfo);
  1707. if (!aNewTopic && (lpobj->head.ctype == CT_LINK))
  1708. goto errRtn;
  1709. aOldTopic = lpobj->topic;
  1710. lpobj->topic = aNewTopic;
  1711. if ((retVal = SetNetName (lpobj)) != OLE_OK) {
  1712. if (lpobj->topic)
  1713. GlobalDeleteAtom (lpobj->topic);
  1714. lpobj->topic = aOldTopic;
  1715. goto errRtn;
  1716. }
  1717. if (aOldTopic)
  1718. GlobalDeleteAtom (aOldTopic);
  1719. if (lpobj->item)
  1720. GlobalDeleteAtom (lpobj->item);
  1721. lpobj->item = aNewItem;
  1722. // As the atoms have already changed, lpobj->hLink becomes irrelevant.
  1723. if (lpobj->hLink) {
  1724. GlobalFree (lpobj->hLink);
  1725. lpobj->hLink = NULL;
  1726. }
  1727. GlobalUnlock(hinfo);
  1728. // Now disconnect the old link and try to connect to the new one.
  1729. lpobj->fCmd = 0;
  1730. InitAsyncCmd (lpobj, OLE_SETDATA, LNKCHANGELNK);
  1731. return LnkChangeLnk (lpobj);
  1732. errRtn:
  1733. if (aNewItem)
  1734. GlobalDeleteAtom (aNewItem);
  1735. GlobalUnlock (hinfo);
  1736. return retVal;
  1737. }
  1738. BOOL QueryUnlaunch (LPOBJECT_LE lpobj)
  1739. {
  1740. if (!(lpobj->fCmd & ACT_UNLAUNCH))
  1741. return FALSE;
  1742. // only if we loaded the app
  1743. if (lpobj->pSysEdit && lpobj->pSysEdit->hClient && lpobj->pSysEdit->hInst)
  1744. return TRUE;
  1745. return FALSE;
  1746. }
  1747. BOOL QueryClose (LPOBJECT_LE lpobj)
  1748. {
  1749. if (!((lpobj->fCmd & ACT_UNLAUNCH) ||
  1750. (lpobj->head.ctype == CT_EMBEDDED)))
  1751. return FALSE;
  1752. // only if we loaded the documnet
  1753. if (lpobj->pSysEdit && lpobj->pSysEdit->hClient)
  1754. return TRUE;
  1755. return FALSE;
  1756. }
  1757. OLESTATUS INTERNAL SetHostNamesHandle (
  1758. LPOBJECT_LE lpobj,
  1759. LPSTR lpclientName,
  1760. LPSTR lpdocName
  1761. ){
  1762. UINT cbClient;
  1763. UINT size;
  1764. HANDLE hhostNames = NULL;
  1765. LPHOSTNAMES lphostNames = NULL;
  1766. LPSTR lpdata;
  1767. // 4 bytes is for the two offsets
  1768. size = (cbClient = lstrlen(lpclientName)+1) + (lstrlen(lpdocName)+1) + 2*sizeof(UINT);
  1769. if ((hhostNames = GlobalAlloc (GMEM_MOVEABLE, (DWORD) size))
  1770. == NULL)
  1771. goto errRtn;
  1772. if ((lphostNames = (LPHOSTNAMES)GlobalLock (hhostNames)) == NULL)
  1773. goto errRtn;
  1774. lphostNames->clientNameOffset = 0;
  1775. lphostNames->documentNameOffset = (WORD)cbClient;
  1776. lpdata = (LPSTR)lphostNames->data;
  1777. lstrcpy (lpdata, lpclientName);
  1778. lstrcpy (lpdata + cbClient, lpdocName);
  1779. if (lpobj->hhostNames)
  1780. GlobalFree ( lpobj->hhostNames);
  1781. GlobalUnlock (hhostNames);
  1782. lpobj->hhostNames = hhostNames;
  1783. return OLE_OK;
  1784. errRtn:
  1785. if (lphostNames)
  1786. GlobalUnlock (hhostNames);
  1787. if (hhostNames)
  1788. GlobalFree (hhostNames);
  1789. return OLE_ERROR_MEMORY;
  1790. }
  1791. #if 0
  1792. OLESTATUS FARINTERNAL LeAbort (LPOBJECT_LE lpobj)
  1793. {
  1794. BOOL bAbort = FALSE;
  1795. PEDIT_DDE pedit;
  1796. // check whether the any transaction pending for
  1797. // the document level.
  1798. // channel open
  1799. // any transaction pending.
  1800. // and we are not in terminate mode.
  1801. if ((pedit = lpobj->pDocEdit) && pedit->hServer &&
  1802. pedit->awaitAck && !pedit->bTerminating) {
  1803. pedit->bAbort = bAbort = TRUE;
  1804. // delete any data we need to delete. Ricght now
  1805. // we kill only the timer. We can not delete any
  1806. // since the server could potentially look at the data.
  1807. DeleteAbortData (lpobj, pedit);
  1808. }
  1809. if ((pedit = lpobj->pSysEdit) && pedit->hServer &&
  1810. pedit->awaitAck && !pedit->bTerminating) {
  1811. pedit->bAbort = bAbort = TRUE;
  1812. DeleteAbortData (lpobj, pedit);
  1813. }
  1814. if (!bAbort)
  1815. return OLE_OK;
  1816. // Now send the EndAsync
  1817. lpobj->mainErr = OLE_ERROR_ABORT;
  1818. EndAsyncCmd (lpobj);
  1819. return OLE_OK;
  1820. }
  1821. #endif
  1822. OLESTATUS FARINTERNAL ProbeAsync(LPOBJECT_LE lpobj)
  1823. {
  1824. if (lpobj->asyncCmd == OLE_NONE)
  1825. return OLE_OK;
  1826. if (!IsServerValid (lpobj)) {
  1827. // Now send the EndAsync
  1828. lpobj->mainErr = OLE_ERROR_TASK;
  1829. EndAsyncCmd (lpobj);
  1830. return OLE_OK;
  1831. }
  1832. return OLE_BUSY;
  1833. }
  1834. BOOL INTERNAL IsWindowValid (HWND hwnd)
  1835. {
  1836. #define TASK_OFFSET 0x00FA
  1837. HANDLE htask;
  1838. if (!IsWindow (hwnd))
  1839. return FALSE;
  1840. // now get the task handle and find out it is valid.
  1841. htask = GetWindowTask (hwnd);
  1842. #ifdef WIN16
  1843. {
  1844. LPSTR lptask;
  1845. if (bWLO)
  1846. return TRUE;
  1847. if ((wWinVer == 0x0003) || !lpfnIsTask) {
  1848. lptask = (LPSTR)(MAKELONG (TASK_OFFSET, htask));
  1849. if (!FarCheckPointer(lptask, READ_ACCESS))
  1850. return FALSE;
  1851. // now check for the signature bytes of task block in kernel
  1852. if (*lptask++ == 'T' && *lptask == 'D')
  1853. return TRUE;
  1854. }
  1855. else {
  1856. // From win31 onwards the API IsTask can be used for task validation
  1857. if ((*lpfnIsTask)(htask))
  1858. return TRUE;
  1859. }
  1860. }
  1861. #endif
  1862. #ifdef WIN32
  1863. // if (IsTask(htask))
  1864. return TRUE;
  1865. #endif
  1866. return FALSE;
  1867. }
  1868. BOOL INTERNAL IsServerValid (LPOBJECT_LE lpobj)
  1869. {
  1870. MSG msg;
  1871. BOOL retval = FALSE;
  1872. if (lpobj->pDocEdit && lpobj->pDocEdit->hServer) {
  1873. retval = TRUE;
  1874. if (!IsWindowValid (lpobj->pDocEdit->hServer)) {
  1875. if (!PeekMessage ((LPMSG)&msg, lpobj->pDocEdit->hClient, WM_DDE_TERMINATE, WM_DDE_TERMINATE,
  1876. PM_NOREMOVE | PM_NOYIELD)){
  1877. #ifdef FIREWALLS
  1878. ASSERT (FALSE, "Server truely died");
  1879. #endif
  1880. return FALSE;
  1881. }
  1882. }
  1883. }
  1884. if (lpobj->pSysEdit && lpobj->pSysEdit->hServer) {
  1885. retval = TRUE;
  1886. if (!IsWindowValid (lpobj->pSysEdit->hServer)) {
  1887. if (!PeekMessage ((LPMSG)&msg, lpobj->pSysEdit->hClient, WM_DDE_TERMINATE, WM_DDE_TERMINATE,
  1888. PM_NOREMOVE | PM_NOYIELD)){
  1889. #ifdef FIREWALLS
  1890. ASSERT (FALSE, "Server truely died");
  1891. #endif
  1892. return FALSE;
  1893. }
  1894. }
  1895. }
  1896. return retval;
  1897. }
  1898. OLESTATUS FARINTERNAL LeExecute (
  1899. LPOLEOBJECT lpoleobj,
  1900. HANDLE hCmds,
  1901. UINT wReserve
  1902. ){
  1903. LPOBJECT_LE lpobj = (LPOBJECT_LE)lpoleobj;
  1904. UNREFERENCED_PARAMETER(wReserve);
  1905. // Assumes all the creates are in order
  1906. PROBE_CREATE_ASYNC(lpobj);
  1907. PROBE_SVRCLOSING(lpobj);
  1908. if (!(lpobj = (*lpobj->head.lpvtbl->QueryProtocol) (lpoleobj,
  1909. PROTOCOL_EXECUTE)))
  1910. return OLE_ERROR_PROTOCOL;
  1911. if (!QueryOpen (lpobj))
  1912. return OLE_ERROR_NOT_OPEN;
  1913. if (!(hCmds = DuplicateGlobal (hCmds, GMEM_MOVEABLE|GMEM_DDESHARE)))
  1914. return OLE_ERROR_MEMORY;
  1915. InitAsyncCmd (lpobj, OLE_OTHER, 0);
  1916. SETERRHINT(lpobj, OLE_ERROR_COMMAND);
  1917. if (DocExecute(lpobj, hCmds))
  1918. return OLE_WAIT_FOR_RELEASE;
  1919. else
  1920. return OLE_ERROR_COMMAND;
  1921. }
  1922. void INTERNAL FreeGDIdata (
  1923. HANDLE hData,
  1924. OLECLIPFORMAT cfFormat
  1925. ){
  1926. if (cfFormat == CF_METAFILEPICT) {
  1927. LPMETAFILEPICT lpMfp;
  1928. if (lpMfp = (LPMETAFILEPICT) GlobalLock (hData)) {
  1929. GlobalUnlock (hData);
  1930. DeleteMetaFile (lpMfp->hMF);
  1931. }
  1932. GlobalFree (hData);
  1933. }
  1934. else if (cfFormat == CF_BITMAP)
  1935. DeleteObject (hData);
  1936. else if (cfFormat == CF_DIB)
  1937. GlobalFree (hData);
  1938. else if (cfFormat == CF_ENHMETAFILE)
  1939. DeleteEnhMetaFile(hData);
  1940. }
  1941. // This routine figures out whether the handle to data block can be copied
  1942. // to DDEPOKE block rather than the contents of the handle
  1943. BOOL INTERNAL CanPutHandleInPokeBlock (
  1944. LPOBJECT_LE lpobj,
  1945. OLECLIPFORMAT cfFormat
  1946. ){
  1947. if (cfFormat == CF_BITMAP || cfFormat == CF_DIB || cfFormat == CF_ENHMETAFILE)
  1948. return TRUE;
  1949. if (cfFormat == CF_METAFILEPICT) {
  1950. // The old version of MSDraw expects the contents of METAFILEPICT
  1951. // structure to be part of DDEPOKE, rather than the handle to it.
  1952. if (!lpobj->bOleServer && lpobj->app == aMSDraw)
  1953. return FALSE;
  1954. return TRUE;
  1955. }
  1956. return FALSE;
  1957. }
  1958. // MakeMFfromEMF()
  1959. // make a metafile from and enhanced metafile
  1960. HMETAFILE MakeMFfromEMF (
  1961. HENHMETAFILE hemf
  1962. ){
  1963. HANDLE hBytes;
  1964. LPBYTE lpBytes = NULL;
  1965. LONG lSizeBytes;
  1966. HDC hdc = GetDC(NULL);
  1967. HMETAFILE hmf = NULL;
  1968. if (!(lSizeBytes = GetWinMetaFileBits((HENHMETAFILE)hemf, 0, NULL, MM_ANISOTROPIC, hdc)) ) {
  1969. if (hdc) ReleaseDC(NULL, hdc);
  1970. return NULL;
  1971. }
  1972. if (!(hBytes = GlobalAlloc(GHND, lSizeBytes)) )
  1973. goto error;
  1974. if (!(lpBytes = (LPBYTE)GlobalLock(hBytes)) )
  1975. goto error;
  1976. GetWinMetaFileBits((HENHMETAFILE)hemf, lSizeBytes, lpBytes, MM_ANISOTROPIC, hdc);
  1977. #ifdef NOBUGS
  1978. if (GetWinMetaFileBits(((LPOBJECT_EMF)(lpobj->lpobjPict))->hemf, lSizeBytes, lpBytes, MM_ANISOTROPIC, hdc) != lSizeBytes) {
  1979. retval = OLE_ERROR_METAFILE;
  1980. goto error;
  1981. }
  1982. #endif
  1983. (HMETAFILE)hmf = SetMetaFileBitsEx(lSizeBytes,lpBytes);
  1984. error:
  1985. if (lpBytes)
  1986. GlobalUnlock(hBytes);
  1987. if (hBytes)
  1988. GlobalFree(hBytes);
  1989. if (hdc)
  1990. ReleaseDC(NULL, hdc);
  1991. return hmf;
  1992. }
  1993. // MakeMFPfromEMF()
  1994. // make a metafile picture structure from an enhanced metafile
  1995. HANDLE MakeMFPfromEMF (
  1996. HENHMETAFILE hemf,
  1997. HANDLE hmf
  1998. ){
  1999. HANDLE hmfp;
  2000. LPMETAFILEPICT lpmfp = NULL;
  2001. ENHMETAHEADER enhmetaheader;
  2002. if (GetEnhMetaFileHeader((HENHMETAFILE)hemf, sizeof(enhmetaheader), &enhmetaheader) == GDI_ERROR)
  2003. goto error;
  2004. if (!(hmfp = GlobalAlloc(GHND, sizeof(METAFILEPICT))) )
  2005. goto error;
  2006. if (!(lpmfp = (LPMETAFILEPICT)GlobalLock(hmfp)) )
  2007. goto error;
  2008. lpmfp->xExt = enhmetaheader.rclFrame.right - enhmetaheader.rclFrame.left;
  2009. lpmfp->yExt = enhmetaheader.rclFrame.bottom - enhmetaheader.rclFrame.top;
  2010. lpmfp->mm = MM_ANISOTROPIC;
  2011. lpmfp->hMF = hmf;
  2012. GlobalUnlock(hmfp);
  2013. return hmfp;
  2014. error:
  2015. if (lpmfp)
  2016. GlobalUnlock(hmfp);
  2017. if (hmfp)
  2018. GlobalFree(hmfp);
  2019. return NULL;
  2020. }
  2021. // ChangeEMFtoMF
  2022. // Change and enhanced metafile object to a metafile object
  2023. BOOL INTERNAL ChangeEMFtoMF(
  2024. LPOBJECT_LE lpobj
  2025. ){
  2026. HMETAFILE hmf;
  2027. HANDLE hmfp = NULL;
  2028. LPOBJECT_MF lpobjMF;
  2029. char szobjname[MAX_ATOM];
  2030. DWORD dwSize = MAX_ATOM;
  2031. // the blank picture case
  2032. if (!((LPOBJECT_EMF)(lpobj->lpobjPict))->hemf) {
  2033. GlobalGetAtomName(lpobj->head.aObjName, (LPSTR)szobjname, dwSize);
  2034. if (!(lpobjMF = MfCreateBlank (lpobj->head.lhclientdoc, (LPSTR)szobjname, CT_PICTURE)))
  2035. return FALSE;
  2036. EmfRelease(lpobj->lpobjPict);
  2037. lpobj->lpobjPict = (LPOLEOBJECT)lpobjMF;
  2038. return TRUE;
  2039. }
  2040. // the normal case
  2041. if (!(hmf = MakeMFfromEMF(((LPOBJECT_EMF)(lpobj->lpobjPict))->hemf)) )
  2042. goto error;
  2043. if (!(hmfp = MakeMFPfromEMF(((LPOBJECT_EMF)(lpobj->lpobjPict))->hemf, hmf)) )
  2044. goto error;
  2045. GlobalGetAtomName(lpobj->head.aObjName, (LPSTR)szobjname, dwSize);
  2046. if (!(lpobjMF = MfCreateObject(
  2047. hmfp,
  2048. lpobj->head.lpclient,
  2049. TRUE,
  2050. lpobj->head.lhclientdoc,
  2051. szobjname,
  2052. CT_PICTURE
  2053. ))) goto error;
  2054. EmfRelease(lpobj->lpobjPict);
  2055. lpobj->lpobjPict = (LPOLEOBJECT)lpobjMF;
  2056. return TRUE;
  2057. error:
  2058. if (hmf)
  2059. DeleteMetaFile((HMETAFILE)hmf);
  2060. if (hmfp)
  2061. GlobalFree(hmfp);
  2062. return FALSE;
  2063. }
  2064. BOOL INTERNAL ChangeEMFtoMFneeded(LPOBJECT_LE lpobj, ATOM advItem)
  2065. {
  2066. lpobj->bNewPict = FALSE;
  2067. if (lpobj->subErr && CF_ENHMETAFILE == GetPictType(lpobj)) {
  2068. CLEAR_STEP_ERROR (lpobj);
  2069. if (advItem == aClose)
  2070. lpobj->pDocEdit->nAdviseClose--;
  2071. else if (advItem == aSave)
  2072. lpobj->pDocEdit->nAdviseSave--;
  2073. AdviseOn (lpobj, CF_METAFILEPICT, advItem);
  2074. lpobj->bNewPict = TRUE;
  2075. return TRUE;
  2076. }
  2077. else
  2078. {
  2079. lpobj->subRtn++;
  2080. return FALSE;
  2081. }
  2082. }