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

1068 lines
29 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. hwndSrvr = GetParent (hwndDoc);
  141. lpsrvr = (LPSRVR) GetWindowLongPtr (hwndSrvr, 0);
  142. // delete all the items(objects) for this doc
  143. DeleteAllItems (lpdoc->hwnd);
  144. // we are terminating.
  145. lpdoc->bTerminate = TRUE;
  146. lpdoc->termNo = 0;
  147. // send ack if Revoke is done as a result of StdClose
  148. if (lpdoc->fAckClose) { // Post the acknowledge to the client
  149. LPARAM lparamNew = MAKE_DDE_LPARAM(WM_DDE_ACK, 0x8000, lpdoc->hDataClose);
  150. if (!PostMessageToClient (lpdoc->hwndClose, WM_DDE_ACK, (WPARAM)lpdoc->hwnd,lparamNew))
  151. {
  152. // if the window died or post failed, delete the atom.
  153. GlobalFree (lpdoc->hDataClose);
  154. DDEFREE(WM_DDE_ACK,lparamNew);
  155. }
  156. }
  157. // Post termination for each of the doc clients.
  158. EnumProps(hwndDoc, (PROPENUMPROC)lpTerminateDocClients);
  159. // post all the messages with yield which have been collected in enum
  160. // UnblockPostMsgs (hwndDoc, TRUE);
  161. #ifdef WAIT_DDE
  162. if (lpdoc->termNo)
  163. WaitForTerminate((LPSRVR)lpdoc);
  164. #endif
  165. return ReleaseDoc (lpdoc);
  166. }
  167. /***************************** Public Function ****************************\
  168. * OLESTATUS FAR PASCAL OleRenameServerDoc (lhdoc, lpNewName)
  169. *
  170. * OleRenameServerDoc: Changes the name of the document
  171. *
  172. * Parameters:
  173. * 1. DLL Doc handle.
  174. * 2. New name for document
  175. *
  176. * return values:
  177. * returns OLE_OK if the document is successfully renamed
  178. *
  179. * History:
  180. * Srinik: Wrote it,
  181. \***************************************************************************/
  182. OLESTATUS FAR PASCAL OleRenameServerDoc (
  183. LHDOC lhdoc,
  184. LPCSTR lpNewName
  185. ){
  186. LPDOC lpdoc;
  187. OLESTATUS retVal = OLE_OK;
  188. HANDLE hdata;
  189. HWND hStdWnd;
  190. if (!CheckServerDoc (lpdoc = (LPDOC)lhdoc))
  191. return OLE_ERROR_HANDLE;
  192. PROBE_READ(lpNewName);
  193. if (!(hdata = MakeGlobal (lpNewName)))
  194. return OLE_ERROR_MEMORY;
  195. if (lpdoc->aDoc)
  196. GlobalDeleteAtom (lpdoc->aDoc);
  197. lpdoc->aDoc = GlobalAddAtom (lpNewName);
  198. // if StdDocName item is present send rename to relevant clients
  199. if (hStdWnd = SearchItem (lpdoc, (LPSTR) MAKEINTATOM(aStdDocName))) {
  200. if (!MakeDDEData (hdata, cfBinary, (LPHANDLE)&hddeRename,FALSE))
  201. retVal = OLE_ERROR_MEMORY;
  202. else {
  203. EnumProps(hStdWnd, (PROPENUMPROC)lpSendRenameMsg);
  204. // post all the messages with yield which have been collected in enum
  205. // UnblockPostMsgs (hStdWnd, FALSE);
  206. GlobalFree (hddeRename);
  207. }
  208. }
  209. hwndRename = hStdWnd;
  210. // Post termination for each of the doc clients.
  211. EnumProps(lpdoc->hwnd, (PROPENUMPROC)lpEnumForTerminate);
  212. // post all the messages with yield which have been collected in enum
  213. // UnblockPostMsgs (lpdoc->hwnd, TRUE);
  214. // If it was an embedded object, from now on it won't be
  215. lpdoc->fEmbed = FALSE;
  216. if (!hStdWnd || retVal != OLE_OK)
  217. GlobalFree(hdata);
  218. // Do link manager stuff
  219. return retVal;
  220. }
  221. /***************************** Public Function ****************************\
  222. * OLESTATUS FAR PASCAL OleSavedServerDoc (lhdoc)
  223. *
  224. * OleSavedServerDoc: Changes the name of the document
  225. *
  226. * Parameters:
  227. * 1. DLL Doc handle.
  228. *
  229. * return values:
  230. * returns OLE_OK if the link manager is successfully notified
  231. *
  232. * History:
  233. * Srinik: Wrote it,
  234. \***************************************************************************/
  235. OLESTATUS FAR PASCAL OleSavedServerDoc (
  236. LHDOC lhdoc
  237. ){
  238. LPDOC lpdoc;
  239. if (!CheckServerDoc (lpdoc = (LPDOC)lhdoc))
  240. return OLE_ERROR_HANDLE;
  241. fAdviseSaveDoc = TRUE;
  242. EnumChildWindows (lpdoc->hwnd, (WNDENUMPROC)lpFindItemWnd,
  243. MAKELONG (NULL, ITEM_SAVED));
  244. if (lpdoc->fEmbed && !fAdviseSaveDoc)
  245. return OLE_ERROR_CANT_UPDATE_CLIENT;
  246. return OLE_OK;
  247. }
  248. /***************************** Public Function ****************************\
  249. * OLESTATUS FAR PASCAL OleRevertServerDoc (lhdoc)
  250. *
  251. * OleRevertServerDoc: Changes the name of the document
  252. *
  253. * Parameters:
  254. * 1. DLL Doc handle.
  255. *
  256. * return values:
  257. * returns OLE_OK if the link manager has been successfully informed
  258. *
  259. * History:
  260. * Srinik: Wrote it,
  261. \***************************************************************************/
  262. OLESTATUS FAR PASCAL OleRevertServerDoc (
  263. LHDOC lhdoc
  264. ){
  265. LPDOC lpdoc;
  266. if (!CheckServerDoc (lpdoc = (LPDOC)lhdoc))
  267. return OLE_ERROR_HANDLE;
  268. return OLE_OK;
  269. }
  270. // TerminateDocClients: Call back for the document window for
  271. // enumerating all the clients. Posts terminate for each of
  272. // the clients.
  273. BOOL FAR PASCAL TerminateDocClients (
  274. HWND hwnd,
  275. LPSTR lpstr,
  276. HANDLE hdata
  277. ){
  278. LPDOC lpdoc;
  279. UNREFERENCED_PARAMETER(lpstr);
  280. lpdoc = (LPDOC)GetWindowLongPtr (hwnd, 0);
  281. if (IsWindowValid ((HWND)hdata)){
  282. lpdoc->termNo++;
  283. // irrespective of the post, incremet the count, so
  284. // that client does not die.
  285. PostMessageToClientWithBlock ((HWND)hdata, WM_DDE_TERMINATE, (WPARAM)hwnd, (LPARAM)0);
  286. }
  287. else
  288. ASSERT(FALSE, "TERMINATE: Client's Doc channel is missing");
  289. return TRUE;
  290. }
  291. // ReleaseDoc: If there are no more matching terminates pending
  292. // Call the server for its release. (Server might be waiting for the
  293. // docs to be terminated. Called thru OleRevokeServer).
  294. int INTERNAL ReleaseDoc (
  295. LPDOC lpdoc
  296. ){
  297. HWND hwndSrvr;
  298. HANDLE hdoc;
  299. LPSRVR lpsrvr;
  300. // release srvr is called only when everything is
  301. // cleaned and srvr app can post WM_QUIT.
  302. if (lpdoc->bTerminate && lpdoc->termNo)
  303. return OLE_WAIT_FOR_RELEASE;
  304. // Call Release for the app to release its space.
  305. if (lpdoc->lpoledoc){
  306. (*lpdoc->lpoledoc->lpvtbl->Release) (lpdoc->lpoledoc);
  307. }
  308. if (lpdoc->aDoc) {
  309. GlobalDeleteAtom (lpdoc->aDoc);
  310. lpdoc->aDoc = (ATOM)0;
  311. }
  312. hwndSrvr = GetParent (lpdoc->hwnd);
  313. DestroyWindow (lpdoc->hwnd);
  314. lpsrvr = (LPSRVR)GetWindowLongPtr (hwndSrvr, 0);
  315. // if the server is waiting for us, inform the server
  316. // we are done
  317. if (!lpsrvr->bTerminate) {
  318. // if we are not in terminate mode, then send advise to the server
  319. // if server can be revoked. raor (04/09)
  320. if (QueryRelease (lpsrvr)){
  321. (*lpsrvr->lpolesrvr->lpvtbl->Release) (lpsrvr->lpolesrvr);
  322. }
  323. } else
  324. ReleaseSrvr (lpsrvr);
  325. GlobalUnlock (hdoc = lpdoc->hdoc);
  326. GlobalFree (hdoc);
  327. return OLE_OK;
  328. }
  329. //RevokeAllDocs : revokes all the documents attached to a given
  330. //server.
  331. int INTERNAL RevokeAllDocs (
  332. LPSRVR lpsrvr
  333. ){
  334. HWND hwnd;
  335. HWND hwndnext;
  336. hwnd = GetWindow (lpsrvr->hwnd, GW_CHILD);
  337. // Go thru each of the child windows and revoke the corresponding
  338. // document. Doc windows are child windows for the server window.
  339. while (hwnd){
  340. // sequence is important
  341. hwndnext = GetWindow (hwnd, GW_HWNDNEXT);
  342. OleRevokeServerDoc ((LHDOC)GetWindowLongPtr (hwnd, 0));
  343. hwnd = hwndnext;
  344. }
  345. return OLE_OK;
  346. }
  347. // FindDoc: Given a document, searches for the document
  348. // in the given server document tree. returns true if the
  349. // document is available.
  350. LPDOC INTERNAL FindDoc (
  351. LPSRVR lpsrvr,
  352. LPSTR lpdocname
  353. ){
  354. ATOM aDoc;
  355. HWND hwnd;
  356. LPDOC lpdoc;
  357. aDoc = (ATOM)GlobalFindAtom (lpdocname);
  358. hwnd = GetWindow (lpsrvr->hwnd, GW_CHILD);
  359. while (hwnd){
  360. lpdoc = (LPDOC)GetWindowLongPtr (hwnd, 0);
  361. if (lpdoc->aDoc == aDoc)
  362. return lpdoc;
  363. hwnd = GetWindow (hwnd, GW_HWNDNEXT);
  364. }
  365. return NULL;
  366. }
  367. // DocWndProc: document window procedure.
  368. // ### We might be able to merge this code with
  369. // the server window proc.
  370. LRESULT FAR PASCAL DocWndProc (
  371. HWND hwnd,
  372. UINT msg,
  373. WPARAM wParam,
  374. LPARAM lParam
  375. ){
  376. LPDOC lpdoc;
  377. WORD status = 0;
  378. BOOL fack;
  379. HANDLE hdata = NULL;
  380. OLESTATUS retval;
  381. LPSRVR lpsrvr;
  382. if (AddMessage (hwnd, msg, wParam, lParam, (int)WT_DOC))
  383. return 0L;
  384. lpdoc = (LPDOC)GetWindowLongPtr (hwnd, 0);
  385. switch (msg){
  386. case WM_CREATE:
  387. DEBUG_OUT ("doc create window", 0)
  388. break;
  389. case WM_DDE_INITIATE:
  390. DEBUG_OUT ("doc: DDE init",0);
  391. if (lpdoc->bTerminate){
  392. DEBUG_OUT ("doc: No action due to termination process",0)
  393. break;
  394. }
  395. // if we are the documnet then respond.
  396. if (! (lpdoc->aDoc == (ATOM)(HIWORD(lParam))))
  397. break;
  398. // We can enterain this client. Put this window in the client list
  399. // and acknowledge the initiate.
  400. if (!AddClient (hwnd, (HWND)wParam, (HWND)wParam))
  401. break;
  402. lpdoc->cClients++;
  403. lpsrvr = (LPSRVR) GetWindowLongPtr (GetParent(lpdoc->hwnd), 0);
  404. lpsrvr->bnoRelease = FALSE;
  405. // post the acknowledge
  406. DuplicateAtom (LOWORD(lParam));
  407. DuplicateAtom (HIWORD(lParam));
  408. SendMessage ((HWND)wParam, WM_DDE_ACK, (WPARAM)hwnd, lParam);
  409. break;
  410. case WM_DDE_EXECUTE: {
  411. HANDLE hData = GET_WM_DDE_EXECUTE_HDATA(wParam,lParam);
  412. DEBUG_OUT ("doc: execute", 0)
  413. // Are we terminating
  414. if (lpdoc->bTerminate || !IsWindowValid ((HWND)wParam)) {
  415. DEBUG_OUT ("doc: execute after terminate posted",0)
  416. // !!! are we supposed to free the data
  417. GlobalFree (hData);
  418. break;
  419. }
  420. retval = DocExecute (hwnd, hData, (HWND)wParam);
  421. SET_MSG_STATUS (retval, status);
  422. #ifdef OLD
  423. // if we posted the terminate because of execute, do not send
  424. // ack.
  425. if (lpdoc->bTerminate) {
  426. // !!! We got close but, we are posting the
  427. // the terminate. Excel does not complain about
  428. // this. But powerpoint complains.
  429. #ifdef POWERPNT_BUG
  430. GlobalFree (hData);
  431. #endif
  432. break;
  433. }
  434. #endif
  435. if (!lpdoc->bTerminate) { // Post the acknowledge to the client
  436. LPARAM lparamNew = MAKE_DDE_LPARAM(WM_DDE_ACK, status, hData);
  437. if (!PostMessageToClient ((HWND)wParam, WM_DDE_ACK, (WPARAM)hwnd, lparamNew)){
  438. // the window either died or post failed, delete the data
  439. GlobalFree (hData);
  440. DDEFREE(WM_DDE_ACK,lparamNew);
  441. }
  442. }
  443. break;
  444. }
  445. case WM_DDE_TERMINATE:
  446. DEBUG_OUT ("doc: DDE terminate",0)
  447. // We do not need this client any more. Delete him from the
  448. // client list.
  449. DeleteClient (lpdoc->hwnd, (HWND)wParam);
  450. lpdoc->cClients--;
  451. if (lpdoc->bTerminate){
  452. lpsrvr = (LPSRVR) GetWindowLongPtr (GetParent(lpdoc->hwnd), 0);
  453. if (!--lpdoc->termNo)
  454. // Release this Doc and may be the server also
  455. // if the server is waiting to be released also.
  456. ReleaseDoc (lpdoc);
  457. } else {
  458. if (lpdoc->termNo == 0){
  459. // If client intiated the terminate. Post matching terminate
  460. PostMessageToClient ((HWND)wParam, WM_DDE_TERMINATE,
  461. (WPARAM)hwnd, (LPARAM)0);
  462. } else
  463. lpdoc->termNo--;
  464. //Client initiated the termination. So, we shoudl take him
  465. // out from any of our items client lists.
  466. DeleteFromItemsList (lpdoc->hwnd, (HWND)wParam);
  467. lpsrvr = (LPSRVR)GetWindowLongPtr (GetParent (lpdoc->hwnd), 0);
  468. if (QueryRelease (lpsrvr)){
  469. (*lpsrvr->lpolesrvr->lpvtbl->Release) (lpsrvr->lpolesrvr);
  470. }
  471. }
  472. break;
  473. case WM_DESTROY:
  474. DEBUG_OUT ("doc: Destroy window",0)
  475. break;
  476. case WM_DDE_POKE: {
  477. int iStdItem;
  478. LPARAM lparamNew;
  479. ATOM aItem = GET_WM_DDE_POKE_ITEM(wParam,lParam);
  480. HANDLE hData = GET_WM_DDE_POKE_HDATA(wParam,lParam);
  481. DEBUG_OUT ("doc: Poke", 0)
  482. if (lpdoc->bTerminate || !IsWindowValid ((HWND) wParam)) {
  483. // we are getting pke message after we have posted the
  484. // the termination or the client got deleted.
  485. /*
  486. * This path is valid for POKE, DATA, and ADVISE transactions
  487. * only!
  488. */
  489. FreePokeData (GET_WM_DDE_POKE_HDATA(wParam,lParam));
  490. #ifdef OLD
  491. GlobalFree (GET_WM_DDE_POKE_HDATA(wParam,lParam));
  492. #endif
  493. // !!! Are we supposed to delete the atoms also.
  494. PokeErr1:
  495. /*
  496. * This path is valid for POKE, DATA, ADVISE and
  497. * ACK transactions only!
  498. */
  499. if (GET_WM_DDE_POKE_ITEM(wParam,lParam))
  500. GlobalDeleteAtom (GET_WM_DDE_POKE_ITEM(wParam,lParam));
  501. DDEFREE(msg,lParam);
  502. break;
  503. }
  504. if (iStdItem = GetStdItemIndex (aItem))
  505. retval = PokeStdItems (lpdoc, (HWND)wParam, hData, iStdItem);
  506. else
  507. retval = PokeData (lpdoc, (HWND)wParam, lParam);
  508. SET_MSG_STATUS (retval, status);
  509. // !!! If the fRelease is false and the post fails
  510. // then we are not freeing the hdata. Are we supposed to
  511. lparamNew = MAKE_DDE_LPARAM(WM_DDE_ACK,status,aItem);
  512. if (!PostMessageToClient ((HWND)wParam, WM_DDE_ACK, (WPARAM)hwnd,lparamNew))
  513. {
  514. DDEFREE(WM_DDE_ACK,lparamNew);
  515. goto PokeErr1;
  516. }
  517. break;
  518. }
  519. case WM_DDE_ADVISE: {
  520. ATOM aItem = GET_WM_DDE_ADVISE_ITEM(wParam, lParam);
  521. DEBUG_OUT ("doc: Advise", 0)
  522. fack = TRUE;
  523. if (lpdoc->bTerminate || !IsWindowValid ((HWND)wParam))
  524. goto PokeErr1;
  525. if (IsAdviseStdItems (aItem))
  526. retval = AdviseStdItems (lpdoc, (HWND)wParam, lParam, (BOOL FAR *)&fack);
  527. else
  528. // advise data will not have any OLE_BUSY
  529. retval = AdviseData (lpdoc, (HWND)wParam, lParam, (BOOL FAR *)&fack);
  530. SET_MSG_STATUS (retval, status);
  531. if (fack) {
  532. LPARAM lparamNew = MAKE_DDE_LPARAM(WM_DDE_ACK,status,aItem);
  533. if (!PostMessageToClient ((HWND)wParam, WM_DDE_ACK, (WPARAM)hwnd, lparamNew))
  534. {
  535. DDEFREE(WM_DDE_ACK,lparamNew);
  536. goto PokeErr1;
  537. }
  538. }
  539. else if ((ATOM)(HIWORD (lParam)))
  540. GlobalDeleteAtom (aItem);
  541. break;
  542. }
  543. case WM_DDE_UNADVISE: {
  544. LPARAM lparamNew;
  545. ATOM aItem = GET_WM_DDE_UNADVISE_ITEM(wParam, lParam);
  546. DEBUG_OUT ("doc: Unadvise", 0)
  547. if (lpdoc->bTerminate || !IsWindowValid ((HWND)wParam)) {
  548. goto PokeErr1;
  549. }
  550. retval = UnAdviseData (lpdoc, (HWND)wParam, lParam);
  551. SET_MSG_STATUS (retval, status);
  552. lparamNew = MAKE_DDE_LPARAM(WM_DDE_ACK,status, aItem);
  553. if (!PostMessageToClient ((HWND)wParam, WM_DDE_ACK, (WPARAM)hwnd,lparamNew))
  554. {
  555. DDEFREE(WM_DDE_ACK,lparamNew);
  556. UnadviseErr:
  557. /*
  558. * This path is valid for UNADVISE and REQUEST transaction only!
  559. */
  560. if (GET_WM_DDE_UNADVISE_ITEM(wParam,lParam))
  561. GlobalDeleteAtom (GET_WM_DDE_UNADVISE_ITEM(wParam,lParam));
  562. DDEFREE(msg,lParam);
  563. break;
  564. }
  565. break;
  566. }
  567. case WM_DDE_REQUEST: {
  568. LPARAM lparamNew;
  569. ATOM aItem = GET_WM_DDE_REQUEST_ITEM(wParam,lParam);
  570. DEBUG_OUT ("doc: Request", 0)
  571. if (lpdoc->bTerminate || !IsWindowValid ((HWND) wParam))
  572. goto UnadviseErr;
  573. retval = RequestData (lpdoc, (HWND)wParam, lParam, (HANDLE FAR *)&hdata);
  574. if(retval == OLE_OK) { // post the data message and we are not asking for any
  575. // acknowledge.
  576. lparamNew = MAKE_DDE_LPARAM(WM_DDE_DATA,hdata,aItem);
  577. if (!PostMessageToClient ((HWND)wParam, WM_DDE_DATA, (WPARAM)hwnd,
  578. lparamNew)) {
  579. GlobalFree (hdata);
  580. DDEFREE(WM_DDE_DATA,lparamNew);
  581. goto UnadviseErr;
  582. }
  583. break;
  584. }
  585. if (retval == OLE_BUSY)
  586. status = 0x4000;
  587. else
  588. status = 0;
  589. lparamNew = MAKE_DDE_LPARAM(WM_DDE_ACK,status,aItem);
  590. // if request failed, then acknowledge with error.
  591. if (!PostMessageToClient ((HWND)wParam, WM_DDE_ACK, (WPARAM)hwnd, lparamNew))
  592. {
  593. DDEFREE(WM_DDE_ACK,lparamNew);
  594. goto UnadviseErr;
  595. }
  596. break;
  597. }
  598. default:
  599. DEBUG_OUT("doc: Default message",0)
  600. return DefWindowProc (hwnd, msg, wParam, lParam);
  601. }
  602. return 0L;
  603. }
  604. //DocExecute: Interprets the execute command for the
  605. //document conversation.
  606. OLESTATUS INTERNAL DocExecute(
  607. HWND hwnd,
  608. HANDLE hdata,
  609. HWND hwndClient
  610. ){
  611. ATOM acmd;
  612. BOOL fShow;
  613. BOOL fActivate;
  614. HANDLE hdup = NULL;
  615. int retval = OLE_ERROR_MEMORY;
  616. LPDOC lpdoc;
  617. LPOLESERVERDOC lpoledoc;
  618. LPCLIENT lpclient = NULL;
  619. LPSTR lpitemname;
  620. LPSTR lpopt;
  621. LPSTR lpnextarg;
  622. LPSTR lpdata = NULL;
  623. LPSTR lpverb = NULL;
  624. UINT verb;
  625. WORD wCmdType;
  626. // !!!Can we modify the string which has been passed to us
  627. // rather than duplicating the data. This will get some speed
  628. // and save some space.
  629. if(!(hdup = DuplicateData(hdata)))
  630. goto errRtn;
  631. if (!(lpdata = GlobalLock (hdup)))
  632. goto errRtn;
  633. DEBUG_OUT (lpdata, 0)
  634. lpdoc = (LPDOC)GetWindowLongPtr (hwnd, 0);
  635. lpoledoc = lpdoc->lpoledoc;
  636. retval = OLE_ERROR_SYNTAX;
  637. if(*lpdata++ != '[') // commands start with the left sqaure bracket
  638. goto errRtn;
  639. // scan the command and scan upto the first arg.
  640. if (!(wCmdType = ScanCommand(lpdata, WT_DOC, &lpnextarg, &acmd)))
  641. goto errRtn;
  642. if (wCmdType == NON_OLE_COMMAND) {
  643. LPSRVR lpsrvr;
  644. if (lpsrvr = (LPSRVR) GetWindowLongPtr (GetParent (hwnd), 0)) {
  645. if (!UtilQueryProtocol (lpsrvr->aClass, PROTOCOL_EXECUTE))
  646. retval = OLE_ERROR_PROTOCOL;
  647. else {
  648. retval = (*lpoledoc->lpvtbl->Execute) (lpoledoc, hdata);
  649. }
  650. }
  651. goto errRtn;
  652. }
  653. //////////////////////////////////////////////////////////////////////////
  654. //
  655. // [StdCloseDocument]
  656. //
  657. //////////////////////////////////////////////////////////////////////////
  658. if (acmd == aStdClose){
  659. // if not terminated by NULL error
  660. if (*lpnextarg)
  661. goto errRtn;
  662. lpdoc->fAckClose = TRUE;
  663. lpdoc->hwndClose = hwndClient;
  664. lpdoc->hDataClose = hdata;
  665. retval = (*lpoledoc->lpvtbl->Close) (lpoledoc);
  666. lpdoc->fAckClose = FALSE;
  667. goto end;
  668. }
  669. //////////////////////////////////////////////////////////////////////////
  670. //
  671. // [StdDoVerbItem("itemname", verb, BOOL, BOOL]
  672. //
  673. //////////////////////////////////////////////////////////////////////////
  674. if (acmd == aStdDoVerbItem){
  675. lpitemname = lpnextarg;
  676. if(!(lpverb = ScanArg(lpnextarg)))
  677. goto errRtn;
  678. if(!(lpnextarg = ScanNumArg(lpverb, (LPINT)&verb)))
  679. goto errRtn;
  680. // now scan the show BOOL
  681. if (!(lpnextarg = ScanBoolArg (lpnextarg, (BOOL FAR *)&fShow)))
  682. goto errRtn;
  683. fActivate = FALSE;
  684. // if activate BOOL is present, scan it.
  685. if (*lpnextarg) {
  686. if (!(lpnextarg = ScanBoolArg (lpnextarg, (BOOL FAR *)&fActivate)))
  687. goto errRtn;
  688. }
  689. if (*lpnextarg)
  690. goto errRtn;
  691. retval = DocDoVerbItem (lpdoc, lpitemname, verb, fShow, !fActivate);
  692. goto end;
  693. }
  694. //////////////////////////////////////////////////////////////////////////
  695. //
  696. // [StdShowItem("itemname"[, "true"])]
  697. //
  698. //////////////////////////////////////////////////////////////////////////
  699. if (acmd != aStdShowItem)
  700. goto errRtn;
  701. lpitemname = lpnextarg;
  702. if(!(lpopt = ScanArg(lpitemname)))
  703. goto errRtn;
  704. // Now scan for optional parameter.
  705. fActivate = FALSE;
  706. if (*lpopt) {
  707. if(!(lpnextarg = ScanBoolArg (lpopt, (BOOL FAR *)&fActivate)))
  708. goto errRtn;
  709. if (*lpnextarg)
  710. goto errRtn;
  711. }
  712. retval = DocShowItem (lpdoc, lpitemname, !fActivate);
  713. end:
  714. errRtn:
  715. if (lpdata)
  716. GlobalUnlock (hdup);
  717. if (hdup)
  718. GlobalFree (hdup);
  719. return retval;
  720. }
  721. int INTERNAL DocShowItem (
  722. LPDOC lpdoc,
  723. LPSTR lpitemname,
  724. BOOL fAct
  725. ){
  726. LPCLIENT lpclient;
  727. int retval;
  728. if ((retval = FindItem (lpdoc, lpitemname, (LPCLIENT FAR *)&lpclient))
  729. != OLE_OK)
  730. return retval;
  731. // protocol sends false for activating and TRUE for not activating.
  732. // for api send TRUE for avtivating and FALSE for not activating.
  733. return (*lpclient->lpoleobject->lpvtbl->Show)(lpclient->lpoleobject, fAct);
  734. }
  735. int INTERNAL DocDoVerbItem (
  736. LPDOC lpdoc,
  737. LPSTR lpitemname,
  738. UINT verb,
  739. BOOL fShow,
  740. BOOL fAct
  741. ){
  742. LPCLIENT lpclient;
  743. int retval = OLE_ERROR_PROTOCOL;
  744. if ((retval = FindItem (lpdoc, lpitemname, (LPCLIENT FAR *)&lpclient))
  745. != OLE_OK)
  746. return retval;
  747. // pass TRUE to activate and False not to activate. Differnt from
  748. // protocol.
  749. retval = (*lpclient->lpoleobject->lpvtbl->DoVerb)(lpclient->lpoleobject, verb, fShow, fAct);
  750. return retval;
  751. }
  752. // FreePokeData: Frees the poked dats.
  753. void INTERNAL FreePokeData (
  754. HANDLE hdde
  755. ){
  756. DDEPOKE FAR * lpdde;
  757. if (hdde) {
  758. if (lpdde = (DDEPOKE FAR *) GlobalLock (hdde)) {
  759. if (lpdde->cfFormat == CF_METAFILEPICT)
  760. #ifdef _WIN64
  761. FreeGDIdata (*(void* _unaligned*)lpdde->Value, lpdde->cfFormat);
  762. #else
  763. FreeGDIdata (*(LPHANDLE)lpdde->Value, lpdde->cfFormat);
  764. #endif
  765. else
  766. FreeGDIdata (LongToHandle(*(LONG*)lpdde->Value), lpdde->cfFormat);
  767. GlobalUnlock (hdde);
  768. }
  769. GlobalFree (hdde);
  770. }
  771. }
  772. // Returns TRUE if GDI format else returns FALSE
  773. BOOL INTERNAL FreeGDIdata (
  774. HANDLE hData,
  775. OLECLIPFORMAT cfFormat
  776. ){
  777. if (cfFormat == CF_METAFILEPICT) {
  778. LPMETAFILEPICT lpMfp;
  779. if (lpMfp = (LPMETAFILEPICT) GlobalLock (hData)) {
  780. GlobalUnlock (hData);
  781. DeleteMetaFile (lpMfp->hMF);
  782. }
  783. GlobalFree (hData);
  784. }
  785. else if (cfFormat == CF_BITMAP)
  786. DeleteObject (hData);
  787. else if (cfFormat == CF_DIB)
  788. GlobalFree (hData);
  789. else if (cfFormat == CF_ENHMETAFILE)
  790. DeleteEnhMetaFile(hData);
  791. else
  792. return FALSE;
  793. return TRUE;
  794. }