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.

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