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.

1160 lines
32 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: Doc.c Document Main module
  3. *
  4. * Purpose: Includes All the document communication related routines.
  5. *
  6. * Created: Oct 1990.
  7. *
  8. * Copyright (c) 1990, 1991 Microsoft Corporation
  9. *
  10. * History:
  11. * Raor (../10/1990) Designed, coded
  12. * curts created portable version for WIN16/32
  13. *
  14. \***************************************************************************/
  15. #include "windows.h"
  16. #include "cmacs.h"
  17. #include "ole.h"
  18. #include "dde.h"
  19. #include "srvr.h"
  20. extern ATOM cfBinary;
  21. extern ATOM aStdClose;
  22. extern ATOM aStdShowItem;
  23. extern ATOM aStdDoVerbItem;
  24. extern ATOM aStdDocName;
  25. extern ATOM aTrue;
  26. extern ATOM aFalse;
  27. extern FARPROC lpTerminateDocClients;
  28. extern FARPROC lpSendRenameMsg;
  29. extern FARPROC lpFindItemWnd;
  30. extern FARPROC lpEnumForTerminate;
  31. extern HANDLE hdllInst;
  32. extern HANDLE hddeRename;
  33. extern HWND hwndRename;
  34. extern BOOL fAdviseSaveDoc;
  35. // ### Do we have to create a seperate window for each doc conversation.
  36. // EDF thinks so.
  37. /***************************** Public Function ****************************\
  38. *
  39. * OLESTATUS FAR PASCAL OleRegisterServerDoc (lhsrvr, lpdocname, lpoledoc, lplhdoc)
  40. *
  41. * OleRegisterServerDoc: Registers the Document with the server lib.
  42. *
  43. * Parameters:
  44. * 1. Server long handle(server with which the document should
  45. * be registered)
  46. * 2. Document name.
  47. * 3. Handle to the doc of the server app (private to the server app).
  48. * 4. Ptr for returning the Doc handle of the lib (private to the lib).
  49. *
  50. * return values:
  51. * returns OLE_OK if the server is successfully registered .
  52. * else returns the corresponding error.
  53. *
  54. * History:
  55. * Raor: Wrote it,
  56. \***************************************************************************/
  57. OLESTATUS FAR PASCAL OleRegisterServerDoc (
  58. LHSRVR lhsrvr, // handle we passed back as part of registration.
  59. LPCSTR lpdocname, // document name
  60. LPOLESERVERDOC lpoledoc, // Private doc handle of the server app.
  61. LHDOC FAR * lplhdoc // where we will be passing our doc private handle
  62. ){
  63. LPSRVR lpsrvr = NULL;
  64. LPDOC lpdoc = NULL;
  65. HANDLE hdoc = NULL;
  66. Puts ("OleRegisterServerDoc");
  67. if (!CheckServer (lpsrvr = (LPSRVR)lhsrvr))
  68. return OLE_ERROR_HANDLE;
  69. // server's termination has already started.
  70. if (lpsrvr->bTerminate)
  71. return OLE_ERROR_TERMINATE;
  72. PROBE_READ(lpdocname);
  73. PROBE_WRITE(lplhdoc);
  74. // we are using the null from inside the server lib
  75. if (lpoledoc)
  76. PROBE_WRITE(lpoledoc);
  77. hdoc = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT | GMEM_DDESHARE, sizeof (DOC));
  78. if (!(hdoc && (lpdoc = (LPDOC)GlobalLock (hdoc))))
  79. goto errReturn;
  80. // set the signature, handle and the doc atom.
  81. lpdoc->sig[0] = 'S';
  82. lpdoc->sig[1] = 'D';
  83. lpdoc->hdoc = hdoc;
  84. lpdoc->aDoc = GlobalAddAtom (lpdocname);
  85. lpdoc->lpoledoc = lpoledoc;
  86. if (!(lpdoc->hwnd = CreateWindow ("DocWndClass", "Doc",
  87. WS_CHILD,0,0,0,0,lpsrvr->hwnd,NULL, hdllInst, NULL)))
  88. goto errReturn;
  89. // save the ptr to the struct in the window.
  90. SetWindowLongPtr (lpdoc->hwnd, 0, (LONG_PTR)lpdoc);
  91. SetWindowWord (lpdoc->hwnd, WW_LE, WC_LE);
  92. SetWindowLongPtr (lpdoc->hwnd, WW_HANDLE, GetWindowLongPtr(lpsrvr->hwnd, WW_HANDLE));
  93. *lplhdoc = (LONG_PTR)lpdoc;
  94. return OLE_OK;
  95. errReturn:
  96. if (lpdoc){
  97. if (lpdoc->hwnd)
  98. DestroyWindow (lpsrvr->hwnd);
  99. if (lpdoc->aDoc)
  100. GlobalDeleteAtom (lpdoc->aDoc);
  101. GlobalUnlock(hdoc);
  102. }
  103. if (hdoc)
  104. GlobalFree (hdoc);
  105. return OLE_ERROR_MEMORY;
  106. }
  107. /***************************** Public Function ****************************\
  108. * OLESTATUS FAR PASCAL OleRevokeServerDoc (lhdoc)
  109. *
  110. * OleRevokeServerDoc: Unregisters the document which has been registered.
  111. *
  112. * Parameters:
  113. * 1. DLL Doc handle.
  114. *
  115. * return values:
  116. * returns OLE_OK if the document is successfully unregisterd.
  117. * ( It is Ok for the app to free the associated space).
  118. * If the unregistration is intiated, returns OLE_STARTED.
  119. * Calls the Doc class release entry point when the doc
  120. * can be released. App should wait till the Release is called
  121. *
  122. * History:
  123. * Raor: Wrote it,
  124. \***************************************************************************/
  125. OLESTATUS FAR PASCAL OleRevokeServerDoc (
  126. LHDOC lhdoc
  127. ){
  128. HWND hwndSrvr;
  129. LPSRVR lpsrvr;
  130. HWND hwndDoc;
  131. LPDOC lpdoc;
  132. Puts ("OleRevokeServerDoc");
  133. if (!CheckServerDoc (lpdoc = (LPDOC)lhdoc))
  134. return OLE_ERROR_HANDLE;
  135. if (lpdoc->bTerminate && lpdoc->termNo)
  136. return OLE_WAIT_FOR_RELEASE;
  137. // ### this code is very similar to the srvr code.
  138. // we should optimize.
  139. hwndDoc = lpdoc->hwnd;
  140. #ifdef FIREWALLS
  141. ASSERT (hwndDoc, "No doc window")
  142. #endif
  143. hwndSrvr = GetParent (hwndDoc);
  144. lpsrvr = (LPSRVR) GetWindowLongPtr (hwndSrvr, 0);
  145. #ifdef FIREWALLS
  146. ASSERT (hwndSrvr, "No srvr window")
  147. ASSERT (lpsrvr, "No srvr structure")
  148. #endif
  149. // delete all the items(objects) for this doc
  150. DeleteAllItems (lpdoc->hwnd);
  151. // we are terminating.
  152. lpdoc->bTerminate = TRUE;
  153. lpdoc->termNo = 0;
  154. // send ack if Revoke is done as a result of StdClose
  155. if (lpdoc->fAckClose) { // Post the acknowledge to the client
  156. LPARAM lparamNew = MAKE_DDE_LPARAM(WM_DDE_ACK, 0x8000, lpdoc->hDataClose);
  157. if (!PostMessageToClient (lpdoc->hwndClose, WM_DDE_ACK, (WPARAM)lpdoc->hwnd,lparamNew))
  158. {
  159. // if the window died or post failed, delete the atom.
  160. GlobalFree (lpdoc->hDataClose);
  161. DDEFREE(WM_DDE_ACK,lparamNew);
  162. }
  163. }
  164. // Post termination for each of the doc clients.
  165. EnumProps(hwndDoc, (PROPENUMPROC)lpTerminateDocClients);
  166. // post all the messages with yield which have been collected in enum
  167. // UnblockPostMsgs (hwndDoc, TRUE);
  168. #ifdef WAIT_DDE
  169. if (lpdoc->termNo)
  170. WaitForTerminate((LPSRVR)lpdoc);
  171. #endif
  172. return ReleaseDoc (lpdoc);
  173. }
  174. /***************************** Public Function ****************************\
  175. * OLESTATUS FAR PASCAL OleRenameServerDoc (lhdoc, lpNewName)
  176. *
  177. * OleRenameServerDoc: Changes the name of the document
  178. *
  179. * Parameters:
  180. * 1. DLL Doc handle.
  181. * 2. New name for document
  182. *
  183. * return values:
  184. * returns OLE_OK if the document is successfully renamed
  185. *
  186. * History:
  187. * Srinik: Wrote it,
  188. \***************************************************************************/
  189. OLESTATUS FAR PASCAL OleRenameServerDoc (
  190. LHDOC lhdoc,
  191. LPCSTR lpNewName
  192. ){
  193. LPDOC lpdoc;
  194. OLESTATUS retVal = OLE_OK;
  195. HANDLE hdata;
  196. HWND hStdWnd;
  197. if (!CheckServerDoc (lpdoc = (LPDOC)lhdoc))
  198. return OLE_ERROR_HANDLE;
  199. PROBE_READ(lpNewName);
  200. if (!(hdata = MakeGlobal (lpNewName)))
  201. return OLE_ERROR_MEMORY;
  202. if (lpdoc->aDoc)
  203. GlobalDeleteAtom (lpdoc->aDoc);
  204. lpdoc->aDoc = GlobalAddAtom (lpNewName);
  205. // if StdDocName item is present send rename to relevant clients
  206. if (hStdWnd = SearchItem (lpdoc, (LPSTR) MAKEINTATOM(aStdDocName))) {
  207. if (!MakeDDEData (hdata, cfBinary, (LPHANDLE)&hddeRename,FALSE))
  208. retVal = OLE_ERROR_MEMORY;
  209. else {
  210. EnumProps(hStdWnd, (PROPENUMPROC)lpSendRenameMsg);
  211. // post all the messages with yield which have been collected in enum
  212. // UnblockPostMsgs (hStdWnd, FALSE);
  213. GlobalFree (hddeRename);
  214. }
  215. }
  216. hwndRename = hStdWnd;
  217. // Post termination for each of the doc clients.
  218. EnumProps(lpdoc->hwnd, (PROPENUMPROC)lpEnumForTerminate);
  219. // post all the messages with yield which have been collected in enum
  220. // UnblockPostMsgs (lpdoc->hwnd, TRUE);
  221. // If it was an embedded object, from now on it won't be
  222. lpdoc->fEmbed = FALSE;
  223. if (!hStdWnd || retVal != OLE_OK)
  224. GlobalFree(hdata);
  225. // Do link manager stuff
  226. return retVal;
  227. }
  228. /***************************** Public Function ****************************\
  229. * OLESTATUS FAR PASCAL OleSavedServerDoc (lhdoc)
  230. *
  231. * OleSavedServerDoc: Changes the name of the document
  232. *
  233. * Parameters:
  234. * 1. DLL Doc handle.
  235. *
  236. * return values:
  237. * returns OLE_OK if the link manager is successfully notified
  238. *
  239. * History:
  240. * Srinik: Wrote it,
  241. \***************************************************************************/
  242. OLESTATUS FAR PASCAL OleSavedServerDoc (
  243. LHDOC lhdoc
  244. ){
  245. LPDOC lpdoc;
  246. if (!CheckServerDoc (lpdoc = (LPDOC)lhdoc))
  247. return OLE_ERROR_HANDLE;
  248. fAdviseSaveDoc = TRUE;
  249. EnumChildWindows (lpdoc->hwnd, (WNDENUMPROC)lpFindItemWnd,
  250. MAKELONG (NULL, ITEM_SAVED));
  251. if (lpdoc->fEmbed && !fAdviseSaveDoc)
  252. return OLE_ERROR_CANT_UPDATE_CLIENT;
  253. return OLE_OK;
  254. }
  255. /***************************** Public Function ****************************\
  256. * OLESTATUS FAR PASCAL OleRevertServerDoc (lhdoc)
  257. *
  258. * OleRevertServerDoc: Changes the name of the document
  259. *
  260. * Parameters:
  261. * 1. DLL Doc handle.
  262. *
  263. * return values:
  264. * returns OLE_OK if the link manager has been successfully informed
  265. *
  266. * History:
  267. * Srinik: Wrote it,
  268. \***************************************************************************/
  269. OLESTATUS FAR PASCAL OleRevertServerDoc (
  270. LHDOC lhdoc
  271. ){
  272. LPDOC lpdoc;
  273. if (!CheckServerDoc (lpdoc = (LPDOC)lhdoc))
  274. return OLE_ERROR_HANDLE;
  275. return OLE_OK;
  276. }
  277. // TerminateDocClients: Call back for the document window for
  278. // enumerating all the clients. Posts terminate for each of
  279. // the clients.
  280. BOOL FAR PASCAL TerminateDocClients (
  281. HWND hwnd,
  282. LPSTR lpstr,
  283. HANDLE hdata
  284. ){
  285. LPDOC lpdoc;
  286. UNREFERENCED_PARAMETER(lpstr);
  287. lpdoc = (LPDOC)GetWindowLongPtr (hwnd, 0);
  288. if (IsWindowValid ((HWND)hdata)){
  289. lpdoc->termNo++;
  290. // irrespective of the post, incremet the count, so
  291. // that client does not die.
  292. PostMessageToClientWithBlock ((HWND)hdata, WM_DDE_TERMINATE, (WPARAM)hwnd, (LPARAM)0);
  293. }
  294. else
  295. ASSERT(FALSE, "TERMINATE: Client's Doc channel is missing");
  296. return TRUE;
  297. }
  298. // ReleaseDoc: If there are no more matching terminates pending
  299. // Call the server for its release. (Server might be waiting for the
  300. // docs to be terminated. Called thru OleRevokeServer).
  301. int INTERNAL ReleaseDoc (
  302. LPDOC lpdoc
  303. ){
  304. HWND hwndSrvr;
  305. HANDLE hdoc;
  306. LPSRVR lpsrvr;
  307. // release srvr is called only when everything is
  308. // cleaned and srvr app can post WM_QUIT.
  309. if (lpdoc->bTerminate && lpdoc->termNo)
  310. return OLE_WAIT_FOR_RELEASE;
  311. // Call Release for the app to release its space.
  312. if (lpdoc->lpoledoc){
  313. #ifdef FIREWALLS
  314. if (!CheckPointer (lpdoc->lpoledoc, WRITE_ACCESS))
  315. ASSERT (0, "Invalid LPOLESERVERDOC")
  316. else if (!CheckPointer (lpdoc->lpoledoc->lpvtbl, WRITE_ACCESS))
  317. ASSERT (0, "Invalid LPOLESERVERDOCVTBL")
  318. else
  319. ASSERT (lpdoc->lpoledoc->lpvtbl->Release,
  320. "Invalid pointer to Release method")
  321. #endif
  322. (*lpdoc->lpoledoc->lpvtbl->Release) (lpdoc->lpoledoc);
  323. }
  324. if (lpdoc->aDoc) {
  325. GlobalDeleteAtom (lpdoc->aDoc);
  326. lpdoc->aDoc = (ATOM)0;
  327. }
  328. hwndSrvr = GetParent (lpdoc->hwnd);
  329. DestroyWindow (lpdoc->hwnd);
  330. lpsrvr = (LPSRVR)GetWindowLongPtr (hwndSrvr, 0);
  331. // if the server is waiting for us, inform the server
  332. // we are done
  333. if (!lpsrvr->bTerminate) {
  334. // if we are not in terminate mode, then send advise to the server
  335. // if server can be revoked. raor (04/09)
  336. if (QueryRelease (lpsrvr)){
  337. #ifdef FIREWALLS
  338. if (!CheckPointer (lpsrvr->lpolesrvr, WRITE_ACCESS))
  339. ASSERT (0, "Invalid LPOLESERVER")
  340. else if (!CheckPointer (lpsrvr->lpolesrvr->lpvtbl,
  341. WRITE_ACCESS))
  342. ASSERT (0, "Invalid LPOLESERVERVTBL")
  343. else
  344. ASSERT (lpsrvr->lpolesrvr->lpvtbl->Release,
  345. "Invalid pointer to Release method")
  346. #endif
  347. (*lpsrvr->lpolesrvr->lpvtbl->Release) (lpsrvr->lpolesrvr);
  348. }
  349. } else
  350. ReleaseSrvr (lpsrvr);
  351. GlobalUnlock (hdoc = lpdoc->hdoc);
  352. GlobalFree (hdoc);
  353. return OLE_OK;
  354. }
  355. //RevokeAllDocs : revokes all the documents attached to a given
  356. //server.
  357. int INTERNAL RevokeAllDocs (
  358. LPSRVR lpsrvr
  359. ){
  360. HWND hwnd;
  361. HWND hwndnext;
  362. hwnd = GetWindow (lpsrvr->hwnd, GW_CHILD);
  363. // Go thru each of the child windows and revoke the corresponding
  364. // document. Doc windows are child windows for the server window.
  365. while (hwnd){
  366. // sequence is important
  367. hwndnext = GetWindow (hwnd, GW_HWNDNEXT);
  368. OleRevokeServerDoc ((LHDOC)GetWindowLongPtr (hwnd, 0));
  369. hwnd = hwndnext;
  370. }
  371. return OLE_OK;
  372. }
  373. // FindDoc: Given a document, searches for the document
  374. // in the given server document tree. returns true if the
  375. // document is available.
  376. LPDOC INTERNAL FindDoc (
  377. LPSRVR lpsrvr,
  378. LPSTR lpdocname
  379. ){
  380. ATOM aDoc;
  381. HWND hwnd;
  382. LPDOC lpdoc;
  383. aDoc = (ATOM)GlobalFindAtom (lpdocname);
  384. hwnd = GetWindow (lpsrvr->hwnd, GW_CHILD);
  385. while (hwnd){
  386. lpdoc = (LPDOC)GetWindowLongPtr (hwnd, 0);
  387. if (lpdoc->aDoc == aDoc)
  388. return lpdoc;
  389. hwnd = GetWindow (hwnd, GW_HWNDNEXT);
  390. }
  391. return NULL;
  392. }
  393. // DocWndProc: document window procedure.
  394. // ### We might be able to merge this code with
  395. // the server window proc.
  396. LRESULT FAR PASCAL DocWndProc (
  397. HWND hwnd,
  398. UINT msg,
  399. WPARAM wParam,
  400. LPARAM lParam
  401. ){
  402. LPDOC lpdoc;
  403. WORD status = 0;
  404. BOOL fack;
  405. HANDLE hdata = NULL;
  406. OLESTATUS retval;
  407. LPSRVR lpsrvr;
  408. #ifdef FIREWALLS
  409. HWND hwndClient;
  410. #endif
  411. if (AddMessage (hwnd, msg, wParam, lParam, (int)WT_DOC))
  412. return 0L;
  413. lpdoc = (LPDOC)GetWindowLongPtr (hwnd, 0);
  414. switch (msg){
  415. case WM_CREATE:
  416. DEBUG_OUT ("doc create window", 0)
  417. break;
  418. case WM_DDE_INITIATE:
  419. DEBUG_OUT ("doc: DDE init",0);
  420. if (lpdoc->bTerminate){
  421. DEBUG_OUT ("doc: No action due to termination process",0)
  422. break;
  423. }
  424. // if we are the documnet then respond.
  425. if (! (lpdoc->aDoc == (ATOM)(HIWORD(lParam))))
  426. break;
  427. // We can enterain this client. Put this window in the client list
  428. // and acknowledge the initiate.
  429. if (!AddClient (hwnd, (HWND)wParam, (HWND)wParam))
  430. break;
  431. lpdoc->cClients++;
  432. lpsrvr = (LPSRVR) GetWindowLongPtr (GetParent(lpdoc->hwnd), 0);
  433. lpsrvr->bnoRelease = FALSE;
  434. // post the acknowledge
  435. DuplicateAtom (LOWORD(lParam));
  436. DuplicateAtom (HIWORD(lParam));
  437. SendMessage ((HWND)wParam, WM_DDE_ACK, (WPARAM)hwnd, lParam);
  438. break;
  439. case WM_DDE_EXECUTE: {
  440. HANDLE hData = GET_WM_DDE_EXECUTE_HDATA(wParam,lParam);
  441. DEBUG_OUT ("doc: execute", 0)
  442. #ifdef FIREWALLS
  443. // find the client in the client list.
  444. hwndClient = FindClient (lpdoc->hwnd, (HWND)wParam);
  445. ASSERT (hwndClient, "Client is missing from the server")
  446. #endif
  447. // Are we terminating
  448. if (lpdoc->bTerminate || !IsWindowValid ((HWND)wParam)) {
  449. DEBUG_OUT ("doc: execute after terminate posted",0)
  450. // !!! are we supposed to free the data
  451. GlobalFree (hData);
  452. break;
  453. }
  454. retval = DocExecute (hwnd, hData, (HWND)wParam);
  455. SET_MSG_STATUS (retval, status);
  456. #ifdef OLD
  457. // if we posted the terminate because of execute, do not send
  458. // ack.
  459. if (lpdoc->bTerminate) {
  460. // !!! We got close but, we are posting the
  461. // the terminate. Excel does not complain about
  462. // this. But powerpoint complains.
  463. #ifdef POWERPNT_BUG
  464. GlobalFree (hData);
  465. #endif
  466. break;
  467. }
  468. #endif
  469. if (!lpdoc->bTerminate) { // Post the acknowledge to the client
  470. LPARAM lparamNew = MAKE_DDE_LPARAM(WM_DDE_ACK, status, hData);
  471. if (!PostMessageToClient ((HWND)wParam, WM_DDE_ACK, (WPARAM)hwnd, lparamNew)){
  472. // the window either died or post failed, delete the data
  473. GlobalFree (hData);
  474. DDEFREE(WM_DDE_ACK,lparamNew);
  475. }
  476. }
  477. break;
  478. }
  479. case WM_DDE_TERMINATE:
  480. DEBUG_OUT ("doc: DDE terminate",0)
  481. #ifdef FIREWALLS
  482. // find the client in the client list.
  483. hwndClient = FindClient (lpdoc->hwnd,(HWND)wParam);
  484. ASSERT(hwndClient || lpdoc->termNo, "Client is missing from the server")
  485. #endif
  486. // We do not need this client any more. Delete him from the
  487. // client list.
  488. DeleteClient (lpdoc->hwnd, (HWND)wParam);
  489. lpdoc->cClients--;
  490. if (lpdoc->bTerminate){
  491. lpsrvr = (LPSRVR) GetWindowLongPtr (GetParent(lpdoc->hwnd), 0);
  492. if (!--lpdoc->termNo)
  493. // Release this Doc and may be the server also
  494. // if the server is waiting to be released also.
  495. ReleaseDoc (lpdoc);
  496. } else {
  497. if (lpdoc->termNo == 0){
  498. // If client intiated the terminate. Post matching terminate
  499. PostMessageToClient ((HWND)wParam, WM_DDE_TERMINATE,
  500. (WPARAM)hwnd, (LPARAM)0);
  501. } else
  502. lpdoc->termNo--;
  503. //Client initiated the termination. So, we shoudl take him
  504. // out from any of our items client lists.
  505. DeleteFromItemsList (lpdoc->hwnd, (HWND)wParam);
  506. lpsrvr = (LPSRVR)GetWindowLongPtr (GetParent (lpdoc->hwnd), 0);
  507. if (QueryRelease (lpsrvr)){
  508. #ifdef FIREWALLS
  509. if (!CheckPointer (lpsrvr->lpolesrvr, WRITE_ACCESS))
  510. ASSERT (0, "Invalid LPOLESERVER")
  511. else if (!CheckPointer (lpsrvr->lpolesrvr->lpvtbl,
  512. WRITE_ACCESS))
  513. ASSERT (0, "Invalid LPOLESERVERVTBL")
  514. else
  515. ASSERT (lpsrvr->lpolesrvr->lpvtbl->Release,
  516. "Invalid pointer to Release method")
  517. #endif
  518. (*lpsrvr->lpolesrvr->lpvtbl->Release) (lpsrvr->lpolesrvr);
  519. }
  520. }
  521. break;
  522. case WM_DESTROY:
  523. DEBUG_OUT ("doc: Destroy window",0)
  524. break;
  525. case WM_DDE_POKE: {
  526. int iStdItem;
  527. LPARAM lparamNew;
  528. ATOM aItem = GET_WM_DDE_POKE_ITEM(wParam,lParam);
  529. HANDLE hData = GET_WM_DDE_POKE_HDATA(wParam,lParam);
  530. DEBUG_OUT ("doc: Poke", 0)
  531. if (lpdoc->bTerminate || !IsWindowValid ((HWND) wParam)) {
  532. // we are getting pke message after we have posted the
  533. // the termination or the client got deleted.
  534. /*
  535. * This path is valid for POKE, DATA, and ADVISE transactions
  536. * only!
  537. */
  538. FreePokeData (GET_WM_DDE_POKE_HDATA(wParam,lParam));
  539. #ifdef OLD
  540. GlobalFree (GET_WM_DDE_POKE_HDATA(wParam,lParam));
  541. #endif
  542. // !!! Are we supposed to delete the atoms also.
  543. PokeErr1:
  544. /*
  545. * This path is valid for POKE, DATA, ADVISE and
  546. * ACK transactions only!
  547. */
  548. if (GET_WM_DDE_POKE_ITEM(wParam,lParam))
  549. GlobalDeleteAtom (GET_WM_DDE_POKE_ITEM(wParam,lParam));
  550. DDEFREE(msg,lParam);
  551. break;
  552. }
  553. if (iStdItem = GetStdItemIndex (aItem))
  554. retval = PokeStdItems (lpdoc, (HWND)wParam, hData, iStdItem);
  555. else
  556. retval = PokeData (lpdoc, (HWND)wParam, lParam);
  557. SET_MSG_STATUS (retval, status);
  558. // !!! If the fRelease is false and the post fails
  559. // then we are not freeing the hdata. Are we supposed to
  560. lparamNew = MAKE_DDE_LPARAM(WM_DDE_ACK,status,aItem);
  561. if (!PostMessageToClient ((HWND)wParam, WM_DDE_ACK, (WPARAM)hwnd,lparamNew))
  562. {
  563. DDEFREE(WM_DDE_ACK,lparamNew);
  564. goto PokeErr1;
  565. }
  566. break;
  567. }
  568. case WM_DDE_ADVISE: {
  569. ATOM aItem = GET_WM_DDE_ADVISE_ITEM(wParam, lParam);
  570. DEBUG_OUT ("doc: Advise", 0)
  571. fack = TRUE;
  572. if (lpdoc->bTerminate || !IsWindowValid ((HWND)wParam))
  573. goto PokeErr1;
  574. if (IsAdviseStdItems (aItem))
  575. retval = AdviseStdItems (lpdoc, (HWND)wParam, lParam, (BOOL FAR *)&fack);
  576. else
  577. // advise data will not have any OLE_BUSY
  578. retval = AdviseData (lpdoc, (HWND)wParam, lParam, (BOOL FAR *)&fack);
  579. SET_MSG_STATUS (retval, status);
  580. if (fack) {
  581. LPARAM lparamNew = MAKE_DDE_LPARAM(WM_DDE_ACK,status,aItem);
  582. if (!PostMessageToClient ((HWND)wParam, WM_DDE_ACK, (WPARAM)hwnd, lparamNew))
  583. {
  584. DDEFREE(WM_DDE_ACK,lparamNew);
  585. goto PokeErr1;
  586. }
  587. }
  588. else if ((ATOM)(HIWORD (lParam)))
  589. GlobalDeleteAtom (aItem);
  590. break;
  591. }
  592. case WM_DDE_UNADVISE: {
  593. LPARAM lparamNew;
  594. ATOM aItem = GET_WM_DDE_UNADVISE_ITEM(wParam, lParam);
  595. DEBUG_OUT ("doc: Unadvise", 0)
  596. if (lpdoc->bTerminate || !IsWindowValid ((HWND)wParam)) {
  597. goto PokeErr1;
  598. }
  599. retval = UnAdviseData (lpdoc, (HWND)wParam, lParam);
  600. SET_MSG_STATUS (retval, status);
  601. lparamNew = MAKE_DDE_LPARAM(WM_DDE_ACK,status, aItem);
  602. if (!PostMessageToClient ((HWND)wParam, WM_DDE_ACK, (WPARAM)hwnd,lparamNew))
  603. {
  604. DDEFREE(WM_DDE_ACK,lparamNew);
  605. UnadviseErr:
  606. /*
  607. * This path is valid for UNADVISE and REQUEST transaction only!
  608. */
  609. if (GET_WM_DDE_UNADVISE_ITEM(wParam,lParam))
  610. GlobalDeleteAtom (GET_WM_DDE_UNADVISE_ITEM(wParam,lParam));
  611. DDEFREE(msg,lParam);
  612. break;
  613. }
  614. break;
  615. }
  616. case WM_DDE_REQUEST: {
  617. LPARAM lparamNew;
  618. ATOM aItem = GET_WM_DDE_REQUEST_ITEM(wParam,lParam);
  619. DEBUG_OUT ("doc: Request", 0)
  620. if (lpdoc->bTerminate || !IsWindowValid ((HWND) wParam))
  621. goto UnadviseErr;
  622. retval = RequestData (lpdoc, (HWND)wParam, lParam, (HANDLE FAR *)&hdata);
  623. if(retval == OLE_OK) { // post the data message and we are not asking for any
  624. // acknowledge.
  625. lparamNew = MAKE_DDE_LPARAM(WM_DDE_DATA,hdata,aItem);
  626. if (!PostMessageToClient ((HWND)wParam, WM_DDE_DATA, (WPARAM)hwnd,
  627. lparamNew)) {
  628. GlobalFree (hdata);
  629. DDEFREE(WM_DDE_DATA,lparamNew);
  630. goto UnadviseErr;
  631. }
  632. break;
  633. }
  634. if (retval == OLE_BUSY)
  635. status = 0x4000;
  636. else
  637. status = 0;
  638. lparamNew = MAKE_DDE_LPARAM(WM_DDE_ACK,status,aItem);
  639. // if request failed, then acknowledge with error.
  640. if (!PostMessageToClient ((HWND)wParam, WM_DDE_ACK, (WPARAM)hwnd, lparamNew))
  641. {
  642. DDEFREE(WM_DDE_ACK,lparamNew);
  643. goto UnadviseErr;
  644. }
  645. break;
  646. }
  647. default:
  648. DEBUG_OUT("doc: Default message",0)
  649. return DefWindowProc (hwnd, msg, wParam, lParam);
  650. }
  651. return 0L;
  652. }
  653. //DocExecute: Interprets the execute command for the
  654. //document conversation.
  655. OLESTATUS INTERNAL DocExecute(
  656. HWND hwnd,
  657. HANDLE hdata,
  658. HWND hwndClient
  659. ){
  660. ATOM acmd;
  661. BOOL fShow;
  662. BOOL fActivate;
  663. HANDLE hdup = NULL;
  664. int retval = OLE_ERROR_MEMORY;
  665. LPDOC lpdoc;
  666. LPOLESERVERDOC lpoledoc;
  667. LPCLIENT lpclient = NULL;
  668. LPSTR lpitemname;
  669. LPSTR lpopt;
  670. LPSTR lpnextarg;
  671. LPSTR lpdata = NULL;
  672. LPSTR lpverb = NULL;
  673. UINT verb;
  674. WORD wCmdType;
  675. // !!!Can we modify the string which has been passed to us
  676. // rather than duplicating the data. This will get some speed
  677. // and save some space.
  678. if(!(hdup = DuplicateData(hdata)))
  679. goto errRtn;
  680. if (!(lpdata = GlobalLock (hdup)))
  681. goto errRtn;
  682. DEBUG_OUT (lpdata, 0)
  683. lpdoc = (LPDOC)GetWindowLongPtr (hwnd, 0);
  684. #ifdef FIREWALLS
  685. ASSERT (lpdoc, "doc: doc does not exist");
  686. #endif
  687. lpoledoc = lpdoc->lpoledoc;
  688. retval = OLE_ERROR_SYNTAX;
  689. if(*lpdata++ != '[') // commands start with the left sqaure bracket
  690. goto errRtn;
  691. // scan the command and scan upto the first arg.
  692. if (!(wCmdType = ScanCommand(lpdata, WT_DOC, &lpnextarg, &acmd)))
  693. goto errRtn;
  694. if (wCmdType == NON_OLE_COMMAND) {
  695. LPSRVR lpsrvr;
  696. if (lpsrvr = (LPSRVR) GetWindowLongPtr (GetParent (hwnd), 0)) {
  697. if (!UtilQueryProtocol (lpsrvr->aClass, PROTOCOL_EXECUTE))
  698. retval = OLE_ERROR_PROTOCOL;
  699. else {
  700. #ifdef FIREWALLS
  701. if (!CheckPointer (lpoledoc, WRITE_ACCESS))
  702. ASSERT (0, "Invalid LPOLESERVERDOC")
  703. else if (!CheckPointer (lpoledoc->lpvtbl, WRITE_ACCESS))
  704. ASSERT (0, "Invalid LPOLESERVERDOCVTBL")
  705. else
  706. ASSERT (lpoledoc->lpvtbl->Execute,
  707. "Invalid pointer to Execute method")
  708. #endif
  709. retval = (*lpoledoc->lpvtbl->Execute) (lpoledoc, hdata);
  710. }
  711. }
  712. goto errRtn;
  713. }
  714. //////////////////////////////////////////////////////////////////////////
  715. //
  716. // [StdCloseDocument]
  717. //
  718. //////////////////////////////////////////////////////////////////////////
  719. if (acmd == aStdClose){
  720. // if not terminated by NULL error
  721. if (*lpnextarg)
  722. goto errRtn;
  723. #ifdef FIREWALLS
  724. if (!CheckPointer (lpoledoc, WRITE_ACCESS))
  725. ASSERT (0, "Invalid LPOLESERVERDOC")
  726. else if (!CheckPointer (lpoledoc->lpvtbl, WRITE_ACCESS))
  727. ASSERT (0, "Invalid LPOLESERVERDOCVTBL")
  728. else
  729. ASSERT (lpoledoc->lpvtbl->Close,"Invalid pointer to Close method")
  730. #endif
  731. lpdoc->fAckClose = TRUE;
  732. lpdoc->hwndClose = hwndClient;
  733. lpdoc->hDataClose = hdata;
  734. retval = (*lpoledoc->lpvtbl->Close) (lpoledoc);
  735. lpdoc->fAckClose = FALSE;
  736. goto end;
  737. }
  738. //////////////////////////////////////////////////////////////////////////
  739. //
  740. // [StdDoVerbItem("itemname", verb, BOOL, BOOL]
  741. //
  742. //////////////////////////////////////////////////////////////////////////
  743. if (acmd == aStdDoVerbItem){
  744. lpitemname = lpnextarg;
  745. if(!(lpverb = ScanArg(lpnextarg)))
  746. goto errRtn;
  747. if(!(lpnextarg = ScanNumArg(lpverb, (LPINT)&verb)))
  748. goto errRtn;
  749. #ifdef FIREWALLS
  750. ASSERT (verb < 9 , "Unexpected verb number");
  751. #endif
  752. // now scan the show BOOL
  753. if (!(lpnextarg = ScanBoolArg (lpnextarg, (BOOL FAR *)&fShow)))
  754. goto errRtn;
  755. fActivate = FALSE;
  756. // if activate BOOL is present, scan it.
  757. if (*lpnextarg) {
  758. if (!(lpnextarg = ScanBoolArg (lpnextarg, (BOOL FAR *)&fActivate)))
  759. goto errRtn;
  760. }
  761. if (*lpnextarg)
  762. goto errRtn;
  763. retval = DocDoVerbItem (lpdoc, lpitemname, verb, fShow, !fActivate);
  764. goto end;
  765. }
  766. //////////////////////////////////////////////////////////////////////////
  767. //
  768. // [StdShowItem("itemname"[, "true"])]
  769. //
  770. //////////////////////////////////////////////////////////////////////////
  771. if (acmd != aStdShowItem)
  772. goto errRtn;
  773. lpitemname = lpnextarg;
  774. if(!(lpopt = ScanArg(lpitemname)))
  775. goto errRtn;
  776. // Now scan for optional parameter.
  777. fActivate = FALSE;
  778. if (*lpopt) {
  779. if(!(lpnextarg = ScanBoolArg (lpopt, (BOOL FAR *)&fActivate)))
  780. goto errRtn;
  781. if (*lpnextarg)
  782. goto errRtn;
  783. }
  784. retval = DocShowItem (lpdoc, lpitemname, !fActivate);
  785. end:
  786. errRtn:
  787. if (lpdata)
  788. GlobalUnlock (hdup);
  789. if (hdup)
  790. GlobalFree (hdup);
  791. return retval;
  792. }
  793. int INTERNAL DocShowItem (
  794. LPDOC lpdoc,
  795. LPSTR lpitemname,
  796. BOOL fAct
  797. ){
  798. LPCLIENT lpclient;
  799. int retval;
  800. if ((retval = FindItem (lpdoc, lpitemname, (LPCLIENT FAR *)&lpclient))
  801. != OLE_OK)
  802. return retval;
  803. #ifdef FIREWALLS
  804. if (!CheckPointer (lpclient->lpoleobject->lpvtbl, WRITE_ACCESS))
  805. ASSERT (0, "Invalid LPOLEOBJECTVTBL")
  806. else
  807. ASSERT (lpclient->lpoleobject->lpvtbl->Show,
  808. "Invalid pointer to Show method")
  809. #endif
  810. // protocol sends false for activating and TRUE for not activating.
  811. // for api send TRUE for avtivating and FALSE for not activating.
  812. return (*lpclient->lpoleobject->lpvtbl->Show)(lpclient->lpoleobject, fAct);
  813. }
  814. int INTERNAL DocDoVerbItem (
  815. LPDOC lpdoc,
  816. LPSTR lpitemname,
  817. UINT verb,
  818. BOOL fShow,
  819. BOOL fAct
  820. ){
  821. LPCLIENT lpclient;
  822. int retval = OLE_ERROR_PROTOCOL;
  823. if ((retval = FindItem (lpdoc, lpitemname, (LPCLIENT FAR *)&lpclient))
  824. != OLE_OK)
  825. return retval;
  826. #ifdef FIREWALLS
  827. if (!CheckPointer (lpclient->lpoleobject->lpvtbl, WRITE_ACCESS))
  828. ASSERT (0, "Invalid LPOLEOBJECTVTBL")
  829. else
  830. ASSERT (lpclient->lpoleobject->lpvtbl->DoVerb,
  831. "Invalid pointer to Run method")
  832. #endif
  833. // pass TRUE to activate and False not to activate. Differnt from
  834. // protocol.
  835. retval = (*lpclient->lpoleobject->lpvtbl->DoVerb)(lpclient->lpoleobject, verb, fShow, fAct);
  836. return retval;
  837. }
  838. // FreePokeData: Frees the poked dats.
  839. void INTERNAL FreePokeData (
  840. HANDLE hdde
  841. ){
  842. DDEPOKE FAR * lpdde;
  843. if (hdde) {
  844. if (lpdde = (DDEPOKE FAR *) GlobalLock (hdde)) {
  845. if (lpdde->cfFormat == CF_METAFILEPICT)
  846. #ifdef _WIN64
  847. FreeGDIdata (*(void* _unaligned*)lpdde->Value, lpdde->cfFormat);
  848. #else
  849. FreeGDIdata (*(LPHANDLE)lpdde->Value, lpdde->cfFormat);
  850. #endif
  851. else
  852. FreeGDIdata (LongToHandle(*(LONG*)lpdde->Value), lpdde->cfFormat);
  853. GlobalUnlock (hdde);
  854. }
  855. GlobalFree (hdde);
  856. }
  857. }
  858. // Returns TRUE if GDI format else returns FALSE
  859. BOOL INTERNAL FreeGDIdata (
  860. HANDLE hData,
  861. OLECLIPFORMAT cfFormat
  862. ){
  863. if (cfFormat == CF_METAFILEPICT) {
  864. LPMETAFILEPICT lpMfp;
  865. if (lpMfp = (LPMETAFILEPICT) GlobalLock (hData)) {
  866. GlobalUnlock (hData);
  867. DeleteMetaFile (lpMfp->hMF);
  868. }
  869. GlobalFree (hData);
  870. }
  871. else if (cfFormat == CF_BITMAP)
  872. DeleteObject (hData);
  873. else if (cfFormat == CF_DIB)
  874. GlobalFree (hData);
  875. else if (cfFormat == CF_ENHMETAFILE)
  876. DeleteEnhMetaFile(hData);
  877. else
  878. return FALSE;
  879. return TRUE;
  880. }