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.

2187 lines
66 KiB

  1. /*++
  2. *
  3. * WOW v1.0
  4. *
  5. * Copyright (c) 1991, Microsoft Corporation
  6. *
  7. * WUMSG.C
  8. * WOW32 16-bit User Message API support
  9. *
  10. * History:
  11. * Created 07-Mar-1991 by Jeff Parsons (jeffpar)
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. MODNAME(wumsg.c);
  16. extern HANDLE hmodWOW32;
  17. // SendDlgItemMessage cache
  18. HWND hdlgSDIMCached = NULL ;
  19. BOOL fWhoCalled = FALSE;
  20. // DDE bit used in GetMessage and PeekMessage
  21. #define fAckReq 0x8000
  22. #define fRelease 0x2000
  23. /*++
  24. BOOL CallMsgFilter(<lpMsg>, <nCode>)
  25. LPMSG <lpMsg>;
  26. int <nCode>;
  27. The %CallMsgFilter% function passes the given message and code to the
  28. current message filter function. The message filter function is an
  29. application-specified function that examines and modifies all messages. An
  30. application specifies the function by using the %SetWindowsHook% function.
  31. <lpMsg>
  32. Points to an %MSG% structure that contains the message to be
  33. filtered.
  34. <nCode>
  35. Specifies a code used by the filter function to determine how to
  36. process the message.
  37. The return value specifies the state of message processing. It is FALSE if
  38. the message should be processed. It is TRUE if the message should not be
  39. processed further.
  40. The %CallMsgFilter% function is usually called by Windows to let
  41. applications examine and control the flow of messages during internal
  42. processing in menus and scroll bars or when moving or sizing a window.
  43. Values given for the <nCode> parameter must not conflict with any of the
  44. MSGF_ and HC_ values passed by Windows to the message filter function.
  45. --*/
  46. ULONG FASTCALL WU32CallMsgFilter(PVDMFRAME pFrame)
  47. {
  48. INT f2;
  49. ULONG ul;
  50. MSG t1;
  51. VPMSG16 vpf1;
  52. register PCALLMSGFILTER16 parg16;
  53. MSGPARAMEX mpex;
  54. GETARGPTR(pFrame, sizeof(CALLMSGFILTER16), parg16);
  55. vpf1 = (VPMSG16)(parg16->f1);
  56. f2 = INT32(parg16->f2);
  57. getmsg16(vpf1, &t1, &mpex);
  58. // Note: getmsg16 may have caused 16-bit memory movement
  59. FREEARGPTR(pFrame);
  60. FREEARGPTR(parg16);
  61. BlockWOWIdle(TRUE);
  62. ul = GETBOOL16(CallMsgFilter(&t1, f2));
  63. // Note: Call to CallMsgFilter may have caused 16-bit memory to move
  64. BlockWOWIdle(FALSE);
  65. // we need to free the struct ret'd by PackDDElParam in the getmsg16 call
  66. // (actually the call is made in ThunkWMMsg16() which is called by getmsg16)
  67. if((t1.message >= WM_DDE_FIRST) && (t1.message <= WM_DDE_LAST)) {
  68. if(t1.message == WM_DDE_ACK ||
  69. t1.message == WM_DDE_DATA ||
  70. t1.message == WM_DDE_POKE ||
  71. t1.message == WM_DDE_ADVISE ) {
  72. // make sure this isn't in response to an initiate message
  73. if(!WI32DDEInitiate((HWND16) mpex.Parm16.WndProc.hwnd)) {
  74. FreeDDElParam(t1.message, t1.lParam);
  75. }
  76. }
  77. }
  78. FREEMSG16(vpf1, &t1);
  79. FREEARGPTR(parg16);
  80. RETURN(ul);
  81. }
  82. /*++
  83. LONG CallWindowProc(<lpPrevWndFunc>, <hwnd>, <wMsg>, <wParam>, <lParam>)
  84. FARPROC <lpPrevWndFunc>;
  85. HWND <hwnd>;
  86. WORD <wMsg>;
  87. WORD <wParam>;
  88. DWORD <lParam>;
  89. The %CallWindowProc% function passes message information to the function
  90. specified by the <lpPrevWndFunc> parameter. The %CallWindowProc% function is
  91. used for window subclassing. Normally, all windows with the same class share
  92. the same window function. A subclass is a window or set of windows belonging
  93. to the same window class whose messages are intercepted and processed by
  94. another function (or functions) before being passed to the window function
  95. of that class.
  96. The %SetWindowLong% function creates the subclass by changing the window
  97. function associated with a particular window, causing Windows to call the
  98. new window function instead of the previous one. Any messages not processed
  99. by the new window function must be passed to the previous window function by
  100. calling %CallWindowProc%. This allows a chain of window functions to be
  101. created.
  102. <lpPrevWndFunc>
  103. Is the procedure-instance address of the previous window function.
  104. <hwnd>
  105. Identifies the window that receives the message.
  106. <wMsg>
  107. Specifies the message number.
  108. <wParam>
  109. Specifies additional message-dependent information.
  110. <lParam>
  111. Specifies additional message-dependent information.
  112. The return value specifies the result of the message processing. The
  113. possible return values depend on the message sent.
  114. --*/
  115. ULONG FASTCALL WU32CallWindowProc(PVDMFRAME pFrame)
  116. {
  117. ULONG ul;
  118. PARM16 Parm16;
  119. register PCALLWINDOWPROC16 parg16;
  120. WORD f2, f3, f4;
  121. LONG f5;
  122. DWORD Proc16;
  123. DWORD Proc32;
  124. INT iMsgThunkClass = 0;
  125. ul = FALSE;
  126. GETARGPTR(pFrame, sizeof(CALLWINDOWPROC16), parg16);
  127. Proc16 = DWORD32(parg16->f1);
  128. f2 = parg16->f2;
  129. f3 = WORD32(parg16->f3);
  130. f4 = WORD32(parg16->f4);
  131. f5 = LONG32(parg16->f5);
  132. Proc32 = IsThunkWindowProc(Proc16, &iMsgThunkClass);
  133. // Note: IsThunkWindowProc may have caused 16-bit memory movement
  134. FREEARGPTR(pFrame);
  135. FREEARGPTR(parg16);
  136. if (Proc32) {
  137. HWND hwnd;
  138. UINT uMsgNew;
  139. UINT uParamNew;
  140. LONG lParamNew;
  141. MSGPARAMEX mpex;
  142. mpex.Parm16.WndProc.hwnd = f2;
  143. mpex.Parm16.WndProc.wMsg = f3;
  144. mpex.Parm16.WndProc.wParam = f4;
  145. mpex.Parm16.WndProc.lParam = f5;
  146. mpex.iMsgThunkClass = iMsgThunkClass;
  147. if (hwnd = ThunkMsg16(&mpex)) {
  148. // Note: ThunkMsg16 may have caused 16-bit memory movement
  149. // But: we haven't refreshed them since freeing after IsThunkWindowProc above.
  150. // FREEARGPTR(pFrame);
  151. // FREEARGPTR(parg16);
  152. uMsgNew = mpex.uMsg;
  153. uParamNew = mpex.uParam;
  154. lParamNew = mpex.lParam;
  155. //
  156. // see comment in IsMDIChild()
  157. //
  158. if ((uMsgNew == WM_CREATE || uMsgNew == WM_NCCREATE) && iMsgThunkClass == WOWCLASS_MDICLIENT) {
  159. FinishThunkingWMCreateMDI16(lParamNew,
  160. (LPCLIENTCREATESTRUCT)((LPCREATESTRUCT)lParamNew + 1));
  161. }
  162. BlockWOWIdle(TRUE);
  163. ul = CallWindowProc((WNDPROC)Proc32, hwnd, uMsgNew,
  164. uParamNew, lParamNew);
  165. BlockWOWIdle(FALSE);
  166. if ((uMsgNew == WM_CREATE || uMsgNew == WM_NCCREATE) && iMsgThunkClass == WOWCLASS_MDICLIENT) {
  167. StartUnThunkingWMCreateMDI16(lParamNew); // does nothing
  168. }
  169. if (MSG16NEEDSTHUNKING(&mpex)) {
  170. mpex.lReturn = ul;
  171. (mpex.lpfnUnThunk16)(&mpex);
  172. ul = mpex.lReturn;
  173. }
  174. }
  175. }
  176. else {
  177. Parm16.WndProc.hwnd = f2;
  178. Parm16.WndProc.wMsg = f3;
  179. Parm16.WndProc.wParam = f4;
  180. Parm16.WndProc.lParam = f5;
  181. Parm16.WndProc.hInst = (WORD)GetWindowLong(HWND32(f2), GWL_HINSTANCE);
  182. CallBack16(RET_WNDPROC, &Parm16, VPFN32(Proc16), (PVPVOID)&ul);
  183. }
  184. FREEARGPTR(parg16);
  185. RETURN(ul);
  186. }
  187. /*++
  188. LONG DefDlgProc(<hDlg>, <wMsg>, <wParam>, <lParam>)
  189. HWND <hDlg>;
  190. WORD <wMsg>;
  191. WORD <wParam>;
  192. DWORD <lParam>;
  193. The %DefDlgProc% function provides default processing for any Windows
  194. messages that a dialog box with a private window class does not process.
  195. All window messages that are not explicitly processed by the window function
  196. must be passed to the %DefDlgProc% function, not the %DefWindowProc%
  197. function. This ensures that all messages not handled by their private window
  198. procedure will be handled properly.
  199. <hDlg>
  200. Identifies the dialog box.
  201. <wMsg>
  202. Specifies the message number.
  203. <wParam>
  204. Specifies 16 bits of additional message-dependent information.
  205. <lParam>
  206. Specifies 32 bits of additional message-dependent information.
  207. The return value specifies the result of the message processing and depends
  208. on the actual message sent.
  209. The source code for the %DefDlgProc% function is provided on the SDK disks.
  210. An application creates a dialog box by calling one of the following
  211. functions:
  212. %CreateDialog%
  213. Creates a modeless dialog box.
  214. %CreateDialogIndirect%
  215. Creates a modeless dialog box.
  216. %CreateDialogIndirectParam%
  217. Creates a modeless dialog box and passes data to it when it is created.
  218. %CreateDialogParam%
  219. Creates a modeless dialog box and passes data to it when it is created.
  220. %DialogBox%
  221. Creates a modal dialog box.
  222. %DialogBoxIndirect%
  223. Creates a modal dialog box.
  224. %DialogBoxIndirectParam%
  225. Creates a modal dialog box and passes data to it when it is created.
  226. %DialogBoxParam%
  227. Creates a modal dialog box and passes data to it when it is created.
  228. --*/
  229. ULONG FASTCALL WU32DefDlgProc(PVDMFRAME pFrame)
  230. {
  231. HWND hdlg;
  232. MSGPARAMEX mpex;
  233. register PDEFDLGPROC16 parg16;
  234. GETARGPTR(pFrame, sizeof(DEFDLGPROC16), parg16);
  235. mpex.lReturn = 0;
  236. mpex.Parm16.WndProc.hwnd = parg16->f1;
  237. mpex.Parm16.WndProc.wMsg = WORD32(parg16->f2);
  238. mpex.Parm16.WndProc.wParam = WORD32(parg16->f3);
  239. mpex.Parm16.WndProc.lParam = LONG32(parg16->f4);
  240. mpex.iMsgThunkClass = 0;
  241. if (hdlg = ThunkMsg16(&mpex)) {
  242. // Note: ThunkMsg16 may have caused 16-bit memory movement
  243. FREEARGPTR(pFrame);
  244. FREEARGPTR(parg16);
  245. BlockWOWIdle(TRUE);
  246. mpex.lReturn = DefDlgProc(hdlg, mpex.uMsg, mpex.uParam, mpex.lParam);
  247. BlockWOWIdle(FALSE);
  248. if (MSG16NEEDSTHUNKING(&mpex)) {
  249. (mpex.lpfnUnThunk16)(&mpex);
  250. }
  251. }
  252. FREEARGPTR(parg16);
  253. RETURN((ULONG)mpex.lReturn);
  254. }
  255. /*++
  256. LONG DefFrameProc(<hwnd>, <hwndMDIClient>, <wMsg>, <wParam>, <lParam>)
  257. HWND <hwnd>;
  258. HWND <hwndMDIClient>;
  259. WORD <wMsg>;
  260. WORD <wParam>;
  261. DWORD <lParam>;
  262. The %DefFrameProc% function provides default processing for any Windows
  263. messages that the window function of a multiple document interface (MDI)
  264. frame window does not process. All window messages that are not explicitly
  265. processed by the window function must be passed to the %DefFrameProc%
  266. function, not the %DefWindowProc% function.
  267. <hwnd>
  268. Identifies the MDI frame window.
  269. <hwndMDIClient>
  270. Identifies the MDI client window.
  271. <wMsg>
  272. Specifies the message number.
  273. <wParam>
  274. Specifies 16 bits of additional message-dependent information.
  275. <lParam>
  276. Specifies 32 bits of additional message-dependent information.
  277. The return value specifies the result of the message processing and depends
  278. on the actual message sent. If the <hwndMDIClient> parameter is NULL, the
  279. return value is the same as for the %DefWindowProc% function.
  280. Normally, when an application's window procedure does not handle a message,
  281. it passes the message to the %DefWindowProc% function, which processes the
  282. message. MDI applications use the %fDefFrameProc% and %DefMDIChildProc%
  283. functions instead of %DefWindowProc% to provide default message processing.
  284. All messages that an application would normally pass to %DefWindowProc%
  285. (such as nonclient messages and WM_SETTEXT) should be passed to
  286. %DefFrameProc% instead. In addition to these, %DefFrameProc% also handles
  287. the following messages:
  288. WM_COMMAND
  289. The frame window of an MDI application receives the WM_COMMAND message
  290. to activate a particular MDI child window. The window ID accompanying
  291. this message will be the ID of the MDI child window assigned by Windows,
  292. starting with the first ID specified by the application when it created
  293. the MDI client window. This value of the first ID must not conflict with
  294. menu-item IDs.
  295. WM_MENUCHAR
  296. When the ^ALTHYPHEN^ key is pressed, the control menu of the active MDI
  297. child window will be selected.
  298. WM_SETFOCUS
  299. %DefFrameProc% passes focus on to the MDI client, which in turn passes
  300. the focus on to the active MDI child window.
  301. WM_SIZE
  302. If the frame window procedure passes this message to %DefFrameProc%, the
  303. MDI client window will be resized to fit in the new client area. If the
  304. frame window procedure sizes the MDI client to a different size, it
  305. should not pass the message to %DefWindowProc%.
  306. --*/
  307. ULONG FASTCALL WU32DefFrameProc(PVDMFRAME pFrame)
  308. {
  309. HWND hwnd, hwnd2;
  310. MSGPARAMEX mpex;
  311. register PDEFFRAMEPROC16 parg16;
  312. GETARGPTR(pFrame, sizeof(DEFFRAMEPROC16), parg16);
  313. mpex.lReturn = 0;
  314. mpex.Parm16.WndProc.hwnd = parg16->f1;
  315. mpex.Parm16.WndProc.wMsg = WORD32(parg16->f3);
  316. mpex.Parm16.WndProc.wParam = WORD32(parg16->f4);
  317. mpex.Parm16.WndProc.lParam = LONG32(parg16->f5);
  318. mpex.iMsgThunkClass = 0;
  319. hwnd2 = HWND32(parg16->f2);
  320. if (hwnd = ThunkMsg16(&mpex)) {
  321. // Note: ThunkMsg16 may have caused 16-bit memory movement
  322. FREEARGPTR(pFrame);
  323. FREEARGPTR(parg16);
  324. if (mpex.uMsg == WM_CLIENTSHUTDOWN &&
  325. CURRENTPTD()->dwWOWCompatFlagsEx & WOWCFEX_IGNORECLIENTSHUTDOWN) {
  326. //
  327. // TurboCAD picks up an uninitialized stack variable as the
  328. // message number to pass to DefFrameProc. In NT 3.51 it
  329. // got 0x907 so the call was a NOP. In NT 4.0, because we
  330. // now save FS and GS in wow16call, they pick up the x86
  331. // flat FS, 0x3b, which also happens to be WM_CLIENTSHUTDOWN
  332. // on NT and Win95, an undocumented message. DefFrameProc
  333. // passes the message to DefWindowProc, which does some
  334. // shutdown related processing which causes TurboCAD to fault
  335. // soon thereafter.
  336. //
  337. // We considered renumbering WM_CLIENTSHUTDOWN, but Win95 uses
  338. // it as well and some apps may have reverse-engineered the
  339. // value 3b and depend on seeing the message.
  340. //
  341. // So instead we eat the call to DefFrameProc here under
  342. // a compatibility bit.
  343. // -- DaveHart 31-May-96
  344. //
  345. mpex.lReturn = 0;
  346. } else {
  347. BlockWOWIdle(TRUE);
  348. mpex.lReturn = DefFrameProc(hwnd, hwnd2,
  349. mpex.uMsg, mpex.uParam, mpex.lParam);
  350. BlockWOWIdle(FALSE);
  351. }
  352. if (MSG16NEEDSTHUNKING(&mpex)) {
  353. (mpex.lpfnUnThunk16)(&mpex);
  354. }
  355. }
  356. FREEARGPTR(parg16);
  357. RETURN((ULONG)mpex.lReturn);
  358. }
  359. /*++
  360. LONG DefMDIChildProc(<hwnd>, <wMsg>, <wParam>, <lParam>)
  361. HWND <hwnd>;
  362. WORD <wMsg>;
  363. WORD <wParam>;
  364. DWORD <lParam>;
  365. The %DefMDIChildProc% function provides default processing for any Windows
  366. messages that the window function of a multiple document interface (MDI)
  367. child window does not process. All window messages that are not explicitly
  368. processed by the window function must be passed to the %DefMDIChildProc%
  369. function, not the %DefWindowProc% function.
  370. <hwnd>
  371. Identifies the MDI child window.
  372. <wMsg>
  373. Specifies the message number.
  374. <wParam>
  375. Specifies 16 bits of additional message-dependent information.
  376. <lParam>
  377. Specifies 32 bits of additional message-dependent information.
  378. The return value specifies the result of the message processing and depends
  379. on the actual message sent.
  380. This function assumes that the parent of the window identified by the <hwnd>
  381. parameter was created with the MDICLIENT class.
  382. Normally, when an application's window procedure does not handle a message,
  383. it passes the message to the %DefWindowProc% function, which processes the
  384. message. MDI applications use the %DefFrameProc% and %DefMDIChildProc%
  385. functions instead of %DefWindowProc% to provide default message processing.
  386. All messages that an application would normally pass to %DefWindowProc%
  387. (such as nonclient messages and WM_SETTEXT) should be passed to
  388. %DefMDIChildProc% instead. In addition to these, %DefMDIChildProc% also
  389. handles the following messages:
  390. WM_CHILDACTIVATE
  391. Performs activation processing when child windows are sized, moved, or
  392. shown. This message must be passed.
  393. WM_GETMINMAXINFO
  394. Calculates the size of a maximized MDI child window based on the current
  395. size of the MDI client window.
  396. WM_MENUCHAR
  397. Sends the key to the frame window.
  398. WM_MOVE
  399. Recalculates MDI client scroll bars, if they are present.
  400. WM_SETFOCUS
  401. Activates the child window if it is not the active MDI child.
  402. WM_SIZE
  403. Performs necessary operations when changing the size of a window,
  404. especially when maximizing or restoring an MDI child window. Failing to
  405. pass this message to %DefMDIChildProc% will produce highly undesirable
  406. results.
  407. WM_SYSCOMMAND
  408. Also handles the next window command.
  409. --*/
  410. ULONG FASTCALL WU32DefMDIChildProc(PVDMFRAME pFrame)
  411. {
  412. HWND hwnd;
  413. register PDEFMDICHILDPROC16 parg16;
  414. MSGPARAMEX mpex;
  415. GETARGPTR(pFrame, sizeof(DEFMDICHILDPROC16), parg16);
  416. mpex.lReturn = 0;
  417. mpex.Parm16.WndProc.hwnd = parg16->f1;
  418. mpex.Parm16.WndProc.wMsg = WORD32(parg16->f2);
  419. mpex.Parm16.WndProc.wParam = WORD32(parg16->f3);
  420. mpex.Parm16.WndProc.lParam = LONG32(parg16->f4);
  421. mpex.iMsgThunkClass = 0;
  422. if (hwnd = ThunkMsg16(&mpex)) {
  423. // Note: ThunkMsg16 may have caused 16-bit memory movement
  424. FREEARGPTR(pFrame);
  425. FREEARGPTR(parg16);
  426. BlockWOWIdle(TRUE);
  427. mpex.lReturn = DefMDIChildProc(hwnd, mpex.uMsg, mpex.uParam,
  428. mpex.lParam);
  429. BlockWOWIdle(FALSE);
  430. if (MSG16NEEDSTHUNKING(&mpex)) {
  431. (mpex.lpfnUnThunk16)(&mpex);
  432. }
  433. }
  434. FREEARGPTR(parg16);
  435. RETURN((ULONG)mpex.lReturn);
  436. }
  437. /*++
  438. LONG DefWindowProc(<hwnd>, <wMsg>, <wParam>, <lParam>)
  439. HWND <hwnd>;
  440. WORD <wMsg>;
  441. WORD <wParam>;
  442. DWORD <lParam>;
  443. The %DefWindowProc% function calls the default window procedure. The
  444. default window procedure provides default processing for any window messages
  445. that an application does not process. This function is used to ensure that
  446. every message is processed. It should be called with the same parameters as
  447. those received by the window procedure.
  448. <hwnd>
  449. Identifies the window that received the message.
  450. <wMsg>
  451. Specifies the message.
  452. <wParam>
  453. Specifies 16 bits of additional message-dependent information.
  454. <lParam>
  455. Specifies 32 bits of additional message-dependent information.
  456. The return value is dependent on the message that was passed to this
  457. function.
  458. --*/
  459. ULONG FASTCALL WU32DefWindowProc(PVDMFRAME pFrame)
  460. {
  461. HWND hwnd;
  462. register PDEFWINDOWPROC16 parg16;
  463. MSGPARAMEX mpex;
  464. GETARGPTR(pFrame, sizeof(DEFWINDOWPROC16), parg16);
  465. mpex.lReturn = 0;
  466. mpex.Parm16.WndProc.hwnd = parg16->hwnd;
  467. mpex.Parm16.WndProc.wMsg = WORD32(parg16->wMsg);
  468. mpex.Parm16.WndProc.wParam = WORD32(parg16->wParam);
  469. mpex.Parm16.WndProc.lParam = LONG32(parg16->lParam);
  470. mpex.iMsgThunkClass = 0;
  471. if (hwnd = ThunkMsg16(&mpex)) {
  472. // Note: ThunkMsg16 may have caused 16-bit memory movement
  473. FREEARGPTR(pFrame);
  474. FREEARGPTR(parg16);
  475. BlockWOWIdle(TRUE);
  476. mpex.lReturn = DefWindowProc(hwnd, mpex.uMsg, mpex.uParam, mpex.lParam);
  477. BlockWOWIdle(FALSE);
  478. if (MSG16NEEDSTHUNKING(&mpex)) {
  479. (mpex.lpfnUnThunk16)(&mpex);
  480. }
  481. }
  482. FREEARGPTR(parg16);
  483. RETURN((ULONG)mpex.lReturn);
  484. }
  485. /*++
  486. LONG DispatchMessage(<lpMsg>)
  487. LPMSG <lpMsg>;
  488. The %DispatchMessage% function passes the message in the %MSG% structure
  489. pointed to by the <lpMsg> parameter to the window function of the specified
  490. window.
  491. <lpMsg>
  492. Points to an %MSG% structure that contains message information from
  493. the Windows application queue.
  494. The structure must contain valid message values. If <lpMsg> points to a
  495. WM_TIMER message and the <lParam> parameter of the WM_TIMER message is
  496. not NULL, then the <lParam> parameter is the address of a function that
  497. is called instead of the window function.
  498. The return value specifies the value returned by the window function. Its
  499. meaning depends on the message being dispatched, but generally the return
  500. value is ignored.
  501. --*/
  502. ULONG FASTCALL WU32DispatchMessage(PVDMFRAME pFrame)
  503. {
  504. ULONG ul;
  505. WORD wTDB;
  506. MSG t1;
  507. register PDISPATCHMESSAGE16 parg16;
  508. MSGPARAMEX mpex;
  509. GETARGPTR(pFrame, sizeof(DISPATCHMESSAGE16), parg16);
  510. wTDB = pFrame->wTDB;
  511. getmsg16(parg16->f1, &t1, &mpex);
  512. // Note: getmsg16 may have caused 16-bit memory movement
  513. FREEARGPTR(pFrame);
  514. FREEARGPTR(parg16);
  515. if (CACHENOTEMPTY() && !(CURRENTPTD()->dwWOWCompatFlags & WOWCF_DONTRELEASECACHEDDC)) {
  516. ReleaseCachedDCs(wTDB, 0, 0, 0, SRCHDC_TASK16);
  517. }
  518. BlockWOWIdle(TRUE);
  519. ul = GETLONG16(DispatchMessage(&t1));
  520. BlockWOWIdle(FALSE);
  521. // WARNING Don't rely on any 32 bit flat pointers to 16 bit memory
  522. // After the dispatchmessage call.
  523. FREEARGPTR(parg16);
  524. RETURN(ul);
  525. }
  526. /*++
  527. BOOL GetMessage(<lpMsg>, <hwnd>, <wMsgFilterMin>, <wMsgFilterMax>)
  528. LPMSG <lpMsg>;
  529. HWND <hwnd>;
  530. WORD <wMsgFilterMin>;
  531. WORD <wMsgFilterMax>;
  532. The %GetMessage% function retrieves a message from the application queue and
  533. places the message in the structure pointed to by the <lpMsg> parameter. If
  534. no message is available, the %GetMessage% function yields control to other
  535. applications until a message becomes available.
  536. %GetMessage% retrieves only messages associated with the window specified by
  537. the <hwnd> parameter and within the range of message values given by the
  538. <wMsgFilterMin> and <wMsgFilterMax> parameters. If <hwnd> is NULL,
  539. %GetMessage% retrieves messages for any window that belongs to the
  540. application making the call. (The %GetMessage% function does not retrieve
  541. messages for windows that belong to other applications.) If <wMsgFilterMin>
  542. and <wMsgFilterMax> are both zero, %GetMessage% returns all available
  543. messages (no filtering is performed).
  544. The constants WM_KEYFIRST and WM_KEYLAST can be used as filter values to
  545. retrieve all messages related to keyboard input; the constants WM_MOUSEFIRST
  546. and WM_MOUSELAST can be used to retrieve all mouse-related messages.
  547. <lpMsg>
  548. Points to an %MSG% structure that contains message information from
  549. the Windows application queue.
  550. <hwnd>
  551. Identifies the window whose messages are to be examined. If
  552. <hwnd> is NULL, %GetMessage% retrieves messages for any window that
  553. belongs to the application making the call.
  554. <wMsgFilterMin>
  555. Specifies the integer value of the lowest message value to be
  556. retrieved.
  557. <wMsgFilterMax>
  558. Specifies the integer value of the highest message value to be
  559. retrieved.
  560. The return value is TRUE if a message other than WM_QUIT is retrieved. It is
  561. FALSE if the WM_QUIT message is retrieved.
  562. The return value is usually used to decide whether to terminate the
  563. application's main loop and exit the program.
  564. In addition to yielding control to other applications when no messages are
  565. available, the %GetMessage% and %PeekMessage% functions also yield control
  566. when WM_PAINT or WM_TIMER messages for other tasks are available.
  567. The %GetMessage%, %PeekMessage%, and %WaitMessage% functions are the only
  568. ways to let other applications run. If your application does not call any of
  569. these functions for long periods of time, other applications cannot run.
  570. When %GetMessage%, %PeekMessage%, and %WaitMessage% yield control to other
  571. applications, the stack and data segments of the application calling the
  572. function may move in memory to accommodate the changing memory requirements
  573. of other applications. If the application has stored long pointers to
  574. objects in the data or stack segment (that is, global or local variables),
  575. these pointers can become invalid after a call to %GetMessage%,
  576. %PeekMessage%, or %WaitMessage%. The <lpMsg> parameter of the called
  577. function remains valid in any case.
  578. --*/
  579. ULONG FASTCALL WU32GetMessage(PVDMFRAME pFrame)
  580. {
  581. ULONG ul;
  582. MSG t1;
  583. VPMSG16 vpMsg;
  584. register PGETMESSAGE16 parg16;
  585. ULONG ulReturn;
  586. BlockWOWIdle(TRUE);
  587. // NOTE: pFrame needs to be restored on all GOTO's to get_next_dde_message
  588. get_next_dde_message:
  589. GETARGPTR(pFrame, sizeof(GETMESSAGE16), parg16);
  590. vpMsg = parg16->vpMsg;
  591. ul = GETBOOL16(GetMessage(&t1,
  592. HWND32(parg16->hwnd),
  593. WORD32(parg16->wMin),
  594. WORD32(parg16->wMax)));
  595. // There Could have been a Task Switch Before GetMessage Returned so
  596. // Don't Trust any 32 bit flat pointers we have, memory could've been
  597. // compacted or moved.
  598. FREEARGPTR(parg16);
  599. FREEVDMPTR(pFrame);
  600. #ifdef DEBUG
  601. if (t1.message == WM_TIMER) {
  602. WOW32ASSERT(HIWORD(t1.wParam) == 0);
  603. }
  604. #endif
  605. ulReturn = putmsg16(vpMsg, &t1);
  606. // NOTE: Call to putmsg16 could've caused 16-bit memory movement
  607. if (((t1.message == WM_DDE_DATA) || (t1.message == WM_DDE_POKE)) && (!ulReturn)) {
  608. register PMSG16 pmsg16;
  609. DDEDATA *lpMem32;
  610. WORD Status;
  611. UINT dd;
  612. WORD ww;
  613. char szMsgBoxText[1024];
  614. char szCaption[256];
  615. GETVDMPTR(vpMsg, sizeof(MSG16), pmsg16);
  616. dd = FETCHDWORD(pmsg16->lParam);
  617. ww = FETCHWORD(pmsg16->wParam);
  618. lpMem32 = GlobalLock((HGLOBAL)dd);
  619. Status = (*((PWORD) lpMem32));
  620. GlobalUnlock((HGLOBAL)dd);
  621. (pfnOut.pfnFreeDDEData)((HANDLE)dd, TRUE, TRUE);
  622. GlobalDeleteAtom (ww);
  623. if ((Status & fAckReq) || (t1.message == WM_DDE_POKE)) {
  624. LoadString(hmodWOW32, iszOLEMemAllocFailedFatal, szMsgBoxText, sizeof szMsgBoxText);
  625. LoadString(hmodWOW32, iszSystemError, szCaption, sizeof szCaption);
  626. MessageBox(t1.hwnd, (LPCTSTR) szMsgBoxText, szCaption, MB_OK | MB_SETFOREGROUND | MB_TOPMOST);
  627. PostMessage((HWND) t1.wParam, WM_DDE_TERMINATE, (WPARAM)FULLHWND32((WORD)t1.hwnd), (LPARAM)0l);
  628. }
  629. else {
  630. LoadString(hmodWOW32, iszOLEMemAllocFailed, szMsgBoxText, sizeof szMsgBoxText);
  631. LoadString(hmodWOW32, iszSystemError, szCaption, sizeof szCaption);
  632. MessageBox(t1.hwnd, (LPCTSTR) szMsgBoxText, szCaption, MB_OK | MB_SETFOREGROUND | MB_TOPMOST);
  633. }
  634. FREEVDMPTR(pmsg16);
  635. // restore the frame ptr due to possible 16-bit memory movement
  636. GETFRAMEPTR(((PTD)CURRENTPTD())->vpStack, pFrame);
  637. goto get_next_dde_message;
  638. }
  639. BlockWOWIdle(FALSE);
  640. FREEARGPTR(parg16);
  641. FREEVDMPTR(pFrame);
  642. RETURN(ul);
  643. }
  644. /*++
  645. DWORD GetMessagePos(VOID)
  646. The %GetMessagePos% function returns a long value that represents the cursor
  647. position (in screen coordinates) when the last message obtained by the
  648. %GetMessage% function occurred.
  649. This function has no parameters.
  650. The return value specifies the <x>- and <y>-coordinates of the cursor
  651. position. The <x>-coordinate is in the low-order word, and the
  652. <y>-coordinate is in the high-order word. If the return value is assigned to
  653. a variable, the %MAKEPOINT% macro can be used to obtain a %POINT% structure
  654. from the return value; the %LOWORD% or %HIWORD% macro can be used to extract
  655. the <x>- or the <y>-coordinate.
  656. To obtain the current position of the cursor instead of the position when
  657. the last message occurred, use the %GetCursorPos% function.
  658. --*/
  659. ULONG FASTCALL WU32GetMessagePos(PVDMFRAME pFrame)
  660. {
  661. ULONG ul;
  662. UNREFERENCED_PARAMETER(pFrame);
  663. ul = GETDWORD16(GetMessagePos());
  664. RETURN(ul);
  665. }
  666. /*++
  667. DWORD GetMessageTime(VOID)
  668. The %GetMessageTime% function returns the message time for the last message
  669. retrieved by the %GetMessage% function. The time is a long integer that
  670. specifies the elapsed time (in milliseconds) from the time the system was
  671. booted to the time the message was created (placed in the application
  672. queue).
  673. This function has no parameters.
  674. The return value specifies the message time.
  675. Do not assume that the return value is always increasing. The return value
  676. will wrap around to zero if the timer count exceeds the maximum value for
  677. long integers.
  678. To calculate time delays between messages, subtract the time of the second
  679. message from the time of the first message.
  680. --*/
  681. ULONG FASTCALL WU32GetMessageTime(PVDMFRAME pFrame)
  682. {
  683. ULONG ul;
  684. UNREFERENCED_PARAMETER(pFrame);
  685. ul = GETLONG16(GetMessageTime());
  686. RETURN(ul);
  687. }
  688. /*++
  689. BOOL InSendMessage(VOID)
  690. The %InSendMessage% function specifies whether the current window function
  691. is processing a message that is passed to it through a call to the
  692. %SendMessage% function.
  693. This function has no parameters.
  694. The return value specifies the outcome of the function. It is TRUE if the
  695. window function is processing a message sent to it with %SendMessage%.
  696. Otherwise, it is FALSE.
  697. Applications use the %InSendMessage% function to determine how to handle
  698. errors that occur when an inactive window processes messages. For example,
  699. if the active window uses %SendMessage% to send a request for information to
  700. another window, the other window cannot become active until it returns
  701. control from the %SendMessage% call. The only method an inactive window has
  702. to inform the user of an error is to create a message box.
  703. --*/
  704. ULONG FASTCALL WU32InSendMessage(PVDMFRAME pFrame)
  705. {
  706. ULONG ul;
  707. UNREFERENCED_PARAMETER(pFrame);
  708. ul = GETBOOL16(InSendMessage());
  709. RETURN(ul);
  710. }
  711. /*++
  712. BOOL PeekMessage(<lpMsg>, <hwnd>, <wMsgFilterMin>, <wMsgFilterMax>,
  713. <wRemoveMsg>)
  714. LPMSG <lpMsg>;
  715. HWND <hwnd>;
  716. WORD <wMsgFilterMin>;
  717. WORD <wMsgFilterMax>;
  718. WORD <wRemoveMsg>;
  719. The %PeekMessage% function checks the application queue for a message and
  720. places the message (if any) in the structure pointed to by the <lpMsg>
  721. parameter. Unlike the %GetMessage% function, the %PeekMessage% function does
  722. not wait for a message to be placed in the queue before returning. It does,
  723. however, yield control (if the PM_NOYIELD flag isn't set) and does not
  724. return control after the yield until Windows returns control to the
  725. application.
  726. %PeekMessage% retrieves only messages associated with the window specified
  727. by the <hwnd> parameter, or any of its children as specified by the
  728. %IsChild% function, and within the range of message values given by the
  729. <wMsgFilterMin> and <wMsgFilterMax> parameters. If <hwnd> is NULL,
  730. %PeekMessage% retrieves messages for any window that belongs to the
  731. application making the call. (The %PeekMessage% function does not retrieve
  732. messages for windows that belong to other applications.) If <hwnd> is -1,
  733. %PeekMessage% returns only messages with a <hwnd> of NULL as posted by the
  734. %PostAppMessage% function. If <wMsgFilterMin> and <wMsgFilterMax> are both
  735. zero, %PeekMessage% returns all available messages (no range filtering is
  736. performed).
  737. The WM_KEYFIRST and WM_KEYLAST flags can be used as filter values to
  738. retrieve all key messages; the WM_MOUSEFIRST and WM_MOUSELAST flags can be
  739. used to retrieve all mouse messages.
  740. <lpMsg>
  741. Points to an %MSG% structure that contains message information from
  742. the Windows application queue.
  743. <hwnd>
  744. Identifies the window whose messages are to be examined.
  745. <wMsgFilterMin>
  746. Specifies the value of the lowest message position to be
  747. examined.
  748. <wMsgFilterMax>
  749. Specifies the value of the highest message position to be
  750. examined.
  751. <wRemoveMsg>
  752. Specifies a combination of the flags described in the following
  753. list. PM_NOYIELD can be combined with either PM_NOREMOVE or PM_REMOVE:
  754. PM_NOREMOVE
  755. Messages are not removed from the queue after processing by
  756. PeekMessage.
  757. PM_NOYIELD
  758. Prevents the current task from halting and yielding system resources to
  759. another task.
  760. PM_REMOVE
  761. Messages are removed from the queue after processing by %PeekMessage%.
  762. The return value specifies whether or not a message is found. It is TRUE if
  763. a message is available. Otherwise, it is FALSE.
  764. %PeekMessage% does not remove WM_PAINT messages from the queue. The messages
  765. remain in the queue until processed. The %GetMessage%, %PeekMessage%, and
  766. %WaitMessage% functions yield control to other applications. These calls are
  767. the only way to let other applications run. If your application does not
  768. call any of these functions for long periods of time, other applications
  769. cannot run.
  770. When %GetMessage%, %PeekMessage%, and %WaitMessage% yield control to other
  771. applications, the stack and data segments of the application calling the
  772. function may move in memory to accommodate the changing memory requirements
  773. of other applications.
  774. If the application has stored long pointers to objects in the data or stack
  775. segment (global or local variables), and if they are unlocked, these
  776. pointers can become invalid after a call to %GetMessage%, %PeekMessage%, or
  777. %WaitMessage%. The <lpMsg> parameter of the called function remains valid in
  778. any case.
  779. --*/
  780. ULONG FASTCALL WU32PeekMessage(PVDMFRAME pFrame)
  781. {
  782. ULONG ul;
  783. VPMSG16 vpf1;
  784. HANDLE f2;
  785. WORD f3, f4, f5;
  786. MSG t1;
  787. register PPEEKMESSAGE16 parg16;
  788. BOOL fNoYield;
  789. BlockWOWIdle(TRUE);
  790. // NOTE: pFrame needs to be restored on all GOTO's to get_next_dde_message
  791. get_next_dde_message:
  792. GETARGPTR(pFrame, sizeof(PEEKMESSAGE16), parg16);
  793. vpf1 = parg16->f1;
  794. f2 = HWND32(parg16->f2);
  795. f3 = WORD32(parg16->f3);
  796. f4 = WORD32(parg16->f4);
  797. f5 = parg16->f5;
  798. fNoYield = f5 & PM_NOYIELD;
  799. ul = GETBOOL16(PeekMessage(&t1, f2, f3, f4, f5));
  800. // There could've been a task switch before peekmessage returned
  801. // so Don't trust any 32 bit flat pointers we have, memory could
  802. // have been compacted or moved.
  803. FREEARGPTR(parg16);
  804. FREEVDMPTR(pFrame);
  805. #ifdef DEBUG
  806. if (ul && t1.message == WM_TIMER) {
  807. WOW32ASSERT(HIWORD(t1.wParam) == 0);
  808. }
  809. #endif
  810. // If PeekMessage returned NULL don't bother to copy anything back
  811. if (ul) {
  812. ULONG ulReturn;
  813. //
  814. // We need to set/reset fThunkDDEmsg (based on PM_REMOVE flag)
  815. // so that we know whether to call FreeDDElParam or not while
  816. // thunking 32 bit message to 16 bit message.
  817. //
  818. fThunkDDEmsg = (BOOL) (f5 & PM_REMOVE);
  819. ulReturn = putmsg16(vpf1, &t1);
  820. // There Could've been a Task Switch Before putmsg16 Returned so Don't
  821. // Trust any 32 bit flat pointers we have, memory could have been
  822. // compacted or moved.
  823. FREEARGPTR(parg16);
  824. FREEVDMPTR(pFrame);
  825. fThunkDDEmsg = TRUE;
  826. if (((t1.message == WM_DDE_DATA) || (t1.message == WM_DDE_POKE)) && (!ulReturn)) {
  827. register PMSG16 pmsg16;
  828. DDEDATA *lpMem32;
  829. WORD Status;
  830. UINT dd;
  831. WORD ww;
  832. char szMsgBoxText[1024];
  833. char szCaption[256];
  834. GETVDMPTR(vpf1, sizeof(MSG16), pmsg16);
  835. dd = FETCHDWORD(pmsg16->lParam);
  836. ww = FETCHWORD(pmsg16->wParam);
  837. lpMem32 = GlobalLock((HGLOBAL)dd);
  838. Status = (*((PWORD) lpMem32));
  839. GlobalUnlock((HGLOBAL)dd);
  840. (pfnOut.pfnFreeDDEData)((HANDLE)dd, TRUE, TRUE);
  841. GlobalDeleteAtom (ww);
  842. if (!(f5 & PM_REMOVE)) {
  843. ul = GETBOOL16(PeekMessage(&t1, f2, f3, f4, f5 | PM_REMOVE));
  844. // There could've been a task switch before peekmessage returned
  845. // so Don't trust any 32 bit flat pointers we have, memory could
  846. // have been compacted or moved.
  847. FREEARGPTR(parg16);
  848. FREEVDMPTR(pFrame);
  849. FREEVDMPTR(pmsg16);
  850. // uncomment if parg16 is ref'd before goto get_next_dde_message
  851. //GETFRAMEPTR(((PTD)CURRENTPTD())->vpStack, pFrame);
  852. //GETARGPTR(pFrame, sizeof(PEEKMESSAGE16), parg16);
  853. // uncomment if pmsg16 is ref'd before goto get_next_dde_message
  854. //GETVDMPTR(vpf1, sizeof(MSG16), pmsg16);
  855. }
  856. if ((Status & fAckReq) || (t1.message == WM_DDE_POKE)) {
  857. LoadString(hmodWOW32, iszOLEMemAllocFailedFatal, szMsgBoxText, sizeof szMsgBoxText);
  858. LoadString(hmodWOW32, iszSystemError, szCaption, sizeof szCaption);
  859. MessageBox(t1.hwnd, (LPCTSTR) szMsgBoxText, szCaption, MB_OK);
  860. PostMessage ((HWND) t1.wParam, WM_DDE_TERMINATE, (WPARAM)FULLHWND32((WORD)t1.hwnd), (LPARAM)0l);
  861. }
  862. else {
  863. LoadString(hmodWOW32, iszOLEMemAllocFailed, szMsgBoxText, sizeof szMsgBoxText);
  864. LoadString(hmodWOW32, iszSystemError, szCaption, sizeof szCaption);
  865. MessageBox(t1.hwnd, (LPCTSTR) szMsgBoxText, szCaption, MB_OK);
  866. }
  867. FREEVDMPTR(pmsg16);
  868. // restore the frame ptr due to possible 16-bit memory movement
  869. GETFRAMEPTR(((PTD)CURRENTPTD())->vpStack, pFrame);
  870. goto get_next_dde_message;
  871. }
  872. }
  873. else if (fNoYield && (CURRENTPTD()->dwWOWCompatFlags & WOWCF_SETNULLMESSAGE)) {
  874. // winproj (help.tutorial) calls peekmessage with PM_REMOVE and
  875. // PM_NOYIELD and an lpmsg whose contents are uninitialized. However
  876. // even if peekmessage returns false, it checks if lpmsg->message is
  877. // WM_QUIT and if true exits. In WOW by pure coincidence the
  878. // unintialized lpmsg->message happens to be value 0x12, which is
  879. // WM_QUIT and thus the tutorial always exits after initialization.
  880. //
  881. // So we reset lpmsg->message to zero, if it was called with PM_NOYIELD
  882. // and if it happens to be WM_QUIT and if peekmessage returns zero.
  883. //
  884. // - nanduri
  885. // we don't need to reinitialize pFrame etc. 'cause peekmessage was
  886. // called with PM_NOYIELD and thus the 16bit memory couldn't have moved
  887. register PMSG16 pmsg16;
  888. GETVDMPTR(vpf1, sizeof(MSG16), pmsg16);
  889. if (pmsg16 && (pmsg16->message == WM_QUIT)) {
  890. pmsg16->message = 0;
  891. }
  892. FREEVDMPTR(pmsg16);
  893. }
  894. BlockWOWIdle(FALSE);
  895. FREEARGPTR(parg16);
  896. FREEVDMPTR(pFrame);
  897. RETURN(ul);
  898. }
  899. /*++
  900. BOOL PostAppMessage(<hTask>, <wMsg>, <wParam>, <lParam>)
  901. HANDLE <hTask>;
  902. WORD <wMsg>;
  903. WORD <wParam>;
  904. DWORD <lParam>;
  905. The %PostAppMessage% function posts a message to an application identified
  906. by a task handle, and then returns without waiting for the application to
  907. process the message. The application receiving the message obtains the
  908. message by calling the %GetMessage% or %PeekMessage% function. The <hwnd>
  909. parameter of the returned %MSG% structure is NULL.
  910. <hTask>
  911. Identifies the task that is to receive the message. The
  912. %GetCurrentTask% function returns this handle.
  913. <wMsg>
  914. Specifies the type of message posted.
  915. <wParam>
  916. Specifies additional message information.
  917. <lParam>
  918. Specifies additional message information.
  919. The return value specifies whether or not the message is posted. It is
  920. TRUE if the message is posted. Otherwise, it is FALSE.
  921. --*/
  922. ULONG FASTCALL WU32PostAppMessage(PVDMFRAME pFrame)
  923. {
  924. register PPOSTAPPMESSAGE16 parg16;
  925. DWORD f1;
  926. MSGPARAMEX mpex;
  927. GETARGPTR(pFrame, sizeof(POSTAPPMESSAGE16), parg16);
  928. mpex.lReturn = 0;
  929. mpex.Parm16.WndProc.hwnd = 0;
  930. mpex.Parm16.WndProc.wMsg = WORD32(parg16->f2);
  931. mpex.Parm16.WndProc.wParam = WORD32(parg16->f3);
  932. mpex.Parm16.WndProc.lParam = LONG32(parg16->f4);
  933. mpex.iMsgThunkClass = 0;
  934. f1 = THREADID32(parg16->f1);
  935. ThunkMsg16(&mpex);
  936. // Note: ThunkMsg16 may have caused 16-bit memory movement
  937. FREEARGPTR(pFrame);
  938. FREEARGPTR(parg16);
  939. mpex.lReturn = PostThreadMessage(f1, mpex.uMsg, mpex.uParam, mpex.lParam);
  940. if (MSG16NEEDSTHUNKING(&mpex)) {
  941. (mpex.lpfnUnThunk16)(&mpex);
  942. }
  943. FREEARGPTR(parg16);
  944. RETURN((ULONG)mpex.lReturn);
  945. }
  946. /*++
  947. BOOL PostMessage(<hwnd>, <msg>, <wParam>, <lParam>)
  948. HWND <hwnd>;
  949. WORD <msg>;
  950. WORD <wParam>;
  951. LONG <lParam>;
  952. The %PostMessage% function places a message in a window's application queue,
  953. and then returns without waiting for the corresponding window to process the
  954. message. Messages in a message queue are retrieved by calls to the
  955. %GetMessage% or %PeekMessage% function.
  956. .*
  957. .* DA's: the following parameters section should be identical to the
  958. .* parameters section in the sdmsg.ref file. If there is a change
  959. .* to this section, the identical change should be made in the other
  960. .* file.
  961. .*
  962. <hwnd>
  963. Identifies the window that is to receive the message. If this parameter
  964. is 0xFFFF (-1), the message is sent to all top-level windows.
  965. <msg>
  966. Specifies the message to be sent.
  967. <wParam>
  968. Specifies additional message information. The contents of this
  969. parameter depends on the message being sent.
  970. <lParam>
  971. Specifies additional message information. The contents of this
  972. parameter depends on the message being sent.
  973. The return value is TRUE if the message is posted, or FALSE if it is not.
  974. An application should never use the %PostMessage% function to send a message
  975. to a control.
  976. .cmt
  977. 27-Oct-1990 [ralphw]
  978. The following is a rewording of the previous documentation. However, it
  979. needs confirmation from development as to its technical accuracy before it
  980. can be released for public consumption.
  981. If the message is being sent to another application, and the <wParam> or
  982. <lParam> parameters are used to pass a handle or pointer to global memory,
  983. the memory should be allocated by the %GlobalAlloc% function using the
  984. GMEM_NOT_BANKED flag. In a system using expanded memory (EMS), this ensures
  985. that the memory is not in in a different bank of memory from the application
  986. using the memory.
  987. .endcmt
  988. --*/
  989. ULONG FASTCALL WU32PostMessage(PVDMFRAME pFrame)
  990. {
  991. LONG l;
  992. UINT f2;
  993. WPARAM f3;
  994. LPARAM f4;
  995. HWND hwnd;
  996. register PPOSTMESSAGE16 parg16;
  997. MSGPARAMEX mpex;
  998. DWORD err = NO_ERROR;
  999. GETARGPTR(pFrame, sizeof(POSTMESSAGE16), parg16);
  1000. // Apps should never use PostMessage to post messages that have
  1001. // pointers to structures, because those messages will show up in
  1002. // GetMessage, and if GetMessage tries to thunk them (ie, tries to
  1003. // call back to the 16-bit kernel to allocate some 16-bit memory to
  1004. // copy the converted 32-bit structure into), we have no way of
  1005. // knowing when to free that 16-bit memory.
  1006. //
  1007. // BUGBUG 22-Aug-91 JeffPar: a flag should be added to ThunkMsg16
  1008. // indicating whether or not such allocations are permissible; this
  1009. // flag should be passed on to all the ThunkXXMsg16 subfunctions,
  1010. // and each of those subfunctions should assert the flag is false
  1011. // whenever allocating 16-bit memory.
  1012. //
  1013. // Used by 16->32 DDE thunkers.
  1014. //
  1015. WOW32ASSERT(fWhoCalled == FALSE);
  1016. fWhoCalled = WOWDDE_POSTMESSAGE;
  1017. f2 = (UINT)WORD32(parg16->f2);
  1018. f3 = (WPARAM)(WORD32(parg16->f3));
  1019. f4 = (LPARAM)(LONG32(parg16->f4));
  1020. mpex.lReturn = 0;
  1021. mpex.Parm16.WndProc.hwnd = parg16->f1;
  1022. mpex.Parm16.WndProc.wMsg = (WORD)f2;
  1023. mpex.Parm16.WndProc.wParam = (WORD)f3;
  1024. mpex.Parm16.WndProc.lParam = f4;
  1025. mpex.iMsgThunkClass = 0;
  1026. // The Reader.exe shipped with Lotus 123MM version has a message
  1027. // synchronization problem. Force proper synchronization by
  1028. // converting this PostMessage call to a SendMessage().
  1029. if ((f2 == WM_VSCROLL) &&
  1030. ((f3 == SB_THUMBTRACK) || (f3 == SB_THUMBPOSITION)) &&
  1031. (CURRENTPTD()->dwWOWCompatFlagsEx & WOWCFEX_SENDPOSTEDMSG) ) {
  1032. l = (LONG)WU32SendMessage(pFrame);
  1033. FREEARGPTR(parg16);
  1034. RETURN((ULONG) l);
  1035. }
  1036. hwnd = ThunkMsg16(&mpex);
  1037. // Note: ThunkMsg16 may have caused 16-bit memory movement
  1038. FREEARGPTR(pFrame);
  1039. FREEARGPTR(parg16);
  1040. WOW32ASSERT(fWhoCalled == WOWDDE_POSTMESSAGE);
  1041. fWhoCalled = FALSE;
  1042. if (hwnd) {
  1043. l = PostMessage(hwnd, mpex.uMsg, mpex.uParam, mpex.lParam);
  1044. if (!l)
  1045. err = GetLastError();
  1046. mpex.lReturn = l;
  1047. if (MSG16NEEDSTHUNKING(&mpex)) {
  1048. (mpex.lpfnUnThunk16)(&mpex);
  1049. }
  1050. // If the post message failed, then the message was probably one
  1051. // that has pointers and therefore can not be posted. (MetaDesign
  1052. // tries to post these kind of messages.) If the destination was a
  1053. // WOW app, then make it into a private message, and try the post
  1054. // again. We don't have to worry about thunking since both the source
  1055. // and destination are in the WOW address space.
  1056. if (err == ERROR_INVALID_PARAMETER) {
  1057. PWW pww;
  1058. DWORD dwpid;
  1059. pww = FindPWW(hwnd);
  1060. // was added for WM_DRAWITEM messages which are probably intended
  1061. // for owner drawn std-type classes. see bug #2047 NTBUG4
  1062. if (pww != NULL && GETICLASS(pww, hwnd) != WOWCLASS_WIN16) {
  1063. // make sure we're in the same vdm process
  1064. if (!(GetWindowThreadProcessId(hwnd, &dwpid) &&
  1065. (dwpid == GetCurrentProcessId()))) {
  1066. return 0;
  1067. }
  1068. mpex.lReturn = PostMessage(hwnd, f2 | WOWPRIVATEMSG, f3, f4);
  1069. }
  1070. }
  1071. }
  1072. FREEARGPTR(parg16);
  1073. RETURN((ULONG)mpex.lReturn);
  1074. }
  1075. /*++
  1076. void PostQuitMessage(<nExitCode>)
  1077. int <nExitCode>;
  1078. The %PostQuitMessage% function informs Windows that the application wishes
  1079. to terminate execution. It is typically used in response to a WM_DESTROY
  1080. message.
  1081. The %PostQuitMessage% function posts a WM_QUIT message to the application
  1082. and returns immediately; the function merely informs the system that the
  1083. application wants to quit sometime in the future.
  1084. When the application receives the WM_QUIT message, it should exit the
  1085. message loop in the main function and return control to Windows. The exit
  1086. code returned to Windows must be the <wParam> parameter of the WM_QUIT
  1087. message.
  1088. <nExitCode>
  1089. Specifies an application exit code. It is used as the wParam parameter
  1090. of the WM_QUIT message.
  1091. This function does not return a value.
  1092. --*/
  1093. ULONG FASTCALL WU32PostQuitMessage(PVDMFRAME pFrame)
  1094. {
  1095. register PPOSTQUITMESSAGE16 parg16;
  1096. GETARGPTR(pFrame, sizeof(POSTQUITMESSAGE16), parg16);
  1097. PostQuitMessage(INT32(parg16->wExitCode));
  1098. FREEARGPTR(parg16);
  1099. RETURN(0);
  1100. }
  1101. /*++
  1102. WORD RegisterWindowMessage(<lpString>)
  1103. LPSTR <lpString>;
  1104. This function defines a new window message that is guaranteed to be unique
  1105. throughout the system. The returned message value can be used when calling
  1106. the %SendMessage% or %PostMessage% function.
  1107. %RegisterWindowMessage% is typically used for communication between two
  1108. cooperating applications.
  1109. If the same message string is registered by two different applications, the
  1110. same message value is returned. The message remains registered until the
  1111. user ends the Windows session.
  1112. <lpString>
  1113. Points to the message string to be registered.
  1114. The return value specifies the outcome of the function. It is an unsigned
  1115. short integer within the range 0xC000 to 0xFFFF if the message is
  1116. successfully registered. Otherwise, it is zero.
  1117. Use the %RegisterWindowMessage% function only when the same message must be
  1118. understood by more than one application. For sending private messages within
  1119. an application, an application can use any integer within the range WM_USER
  1120. to 0xBFFF.
  1121. --*/
  1122. ULONG FASTCALL WU32RegisterWindowMessage(PVDMFRAME pFrame)
  1123. {
  1124. ULONG ul;
  1125. PSZ psz1;
  1126. register PREGISTERWINDOWMESSAGE16 parg16;
  1127. GETARGPTR(pFrame, sizeof(REGISTERWINDOWMESSAGE16), parg16);
  1128. GETPSZPTR(parg16->f1, psz1);
  1129. ul = GETWORD16(RegisterWindowMessage(psz1));
  1130. FREEPSZPTR(psz1);
  1131. FREEARGPTR(parg16);
  1132. RETURN(ul);
  1133. }
  1134. /*++
  1135. void ReplyMessage(<lReply>)
  1136. LONG <lReply>;
  1137. The %ReplyMessage% function is used to reply to a message sent through the
  1138. %SendMessage% function without returning control to the function that called
  1139. %SendMessage.%
  1140. By calling this function, the window function that receives the message
  1141. allows the task that called %SendMessage% to continue to execute as though
  1142. the task that received the message had returned control. The task that calls
  1143. %ReplyMessage% also continues to execute.
  1144. Normally a task that calls %SendMessage% to send a message to another task
  1145. will not continue executing until the window procedure that Windows calls to
  1146. receive the message returns. However, if a task that is called to receive a
  1147. message needs to perform some type of operation that might yield control
  1148. (such as calling the %MessageBox% or %DialogBox% functions), Windows could
  1149. be placed in a deadlock situation where the sending task needs to execute
  1150. and process messages but cannot because it is waiting for %SendMessage% to
  1151. return. An application can avoid this problem if the task receiving the
  1152. message calls %ReplyMessage% before performing any operation that could
  1153. cause the task to yield.
  1154. The %ReplyMessage% function has no effect if the message was not sent
  1155. through the %SendMessage% function or if the message was sent by the same
  1156. task.
  1157. <lReply>
  1158. Specifies the result of the message processing. The possible values
  1159. depend on the actual message sent.
  1160. This function does not return a value.
  1161. --*/
  1162. ULONG FASTCALL WU32ReplyMessage(PVDMFRAME pFrame)
  1163. {
  1164. register PREPLYMESSAGE16 parg16;
  1165. GETARGPTR(pFrame, sizeof(REPLYMESSAGE16), parg16);
  1166. ReplyMessage(LONG32(parg16->f1));
  1167. // WARNING - Don't use any 32 bit flat pointers after call to ReplyMessage,
  1168. // other tasks might have run and made the pointers invalid.
  1169. FREEARGPTR(parg16);
  1170. RETURN(0);
  1171. }
  1172. /*++
  1173. DWORD SendDlgItemMessage(<hDlg>, <nIDDlgItem>, <wMsg>, <wParam>, <lParam>)
  1174. HWND <hDlg>;
  1175. int <nIDDlgItem>;
  1176. WORD <wMsg>;
  1177. WORD <wParam>;
  1178. DWORD <lParam>;
  1179. The %SendDlgItemMessage% function sends a message to the control specified
  1180. by the <nIDDlgItem> parameter within the dialog box specified by the <hDlg>
  1181. parameter. The %SendDlgItemMessage% function does not return until the
  1182. message has been processed.
  1183. <hDlg>
  1184. Identifies the dialog box that contains the control.
  1185. <nIDDlgItem>
  1186. Specifies the integer identifier of the dialog item that is to
  1187. receive the message.
  1188. <wMsg>
  1189. Specifies the message value.
  1190. <wParam>
  1191. Specifies additional message information.
  1192. <lParam>
  1193. Specifies additional message information.
  1194. The return value specifies the outcome of the function. It is the value
  1195. returned by the control's window function, or zero if the control identifier
  1196. is not valid.
  1197. Using %SendDlgItemMessage% is identical to obtaining a handle to the given
  1198. control and calling the %SendMessage% function.
  1199. --*/
  1200. #define W31EM_GETRECT (WM_USER+2) // w31 EM_GETRECT != NT EM_GETRECT
  1201. ULONG FASTCALL WU32SendDlgItemMessage(PVDMFRAME pFrame)
  1202. {
  1203. HWND hdlg, hwndItem, hwnd;
  1204. register PSENDDLGITEMMESSAGE16 parg16;
  1205. MSGPARAMEX mpex;
  1206. static HWND hwndCached = NULL ;
  1207. static DWORD dwCachedItem = 0L ;
  1208. GETARGPTR(pFrame, sizeof(SENDDLGITEMMESSAGE16), parg16);
  1209. // QuarkExpress v3.31 passes a hard coded 7fff:0000 as the pointer to the
  1210. // RECT struct for EM_GETRECT message - W3.1 rejects it in validation layer
  1211. if( (DWORD32(parg16->f5) == 0x7FFF0000) &&
  1212. (WORD32(parg16->f3) == W31EM_GETRECT) &&
  1213. (CURRENTPTD()->dwWOWCompatFlagsEx & WOWCFEX_BOGUSPOINTER) ) {
  1214. FREEARGPTR(parg16);
  1215. RETURN((ULONG)0);
  1216. }
  1217. // Need unique handle
  1218. hdlg = (HWND)FULLHWND32(parg16->f1);
  1219. //
  1220. // Caching the hwnd for the dialog item because EForm will
  1221. // call SendDlgItemMessage in a tight loop.
  1222. //
  1223. if ( hdlg == hdlgSDIMCached && WORD32(parg16->f2) == dwCachedItem ) {
  1224. // Set from cached
  1225. hwndItem = hwndCached ;
  1226. }
  1227. else {
  1228. if ( hwndItem = GetDlgItem(hdlg, WORD32(parg16->f2)) ) {
  1229. // and cache needed information
  1230. hdlgSDIMCached = hdlg ;
  1231. hwndCached = hwndItem ;
  1232. dwCachedItem = WORD32(parg16->f2) ;
  1233. }
  1234. else {
  1235. FREEARGPTR(parg16);
  1236. RETURN((ULONG)0);
  1237. }
  1238. }
  1239. mpex.lReturn = 0;
  1240. if (hwndItem) {
  1241. mpex.Parm16.WndProc.hwnd = GETHWND16(hwndItem);
  1242. mpex.Parm16.WndProc.wMsg = WORD32(parg16->f3);
  1243. mpex.Parm16.WndProc.wParam = WORD32(parg16->f4);
  1244. mpex.Parm16.WndProc.lParam = LONG32(parg16->f5);
  1245. mpex.iMsgThunkClass = 0;
  1246. if (hwnd = ThunkMsg16(&mpex)) {
  1247. // Note: ThunkMsg16 may have caused memory movement
  1248. FREEARGPTR(pFrame);
  1249. FREEARGPTR(parg16);
  1250. /*
  1251. ** Since we already know which window the message is going to
  1252. ** don't make USER32 look it up again. - MarkRi
  1253. */
  1254. mpex.lReturn = SendMessage(hwndItem, mpex.uMsg, mpex.uParam,
  1255. mpex.lParam);
  1256. // to keep common dialog structs in sync (see wcommdlg.c)
  1257. Check_ComDlg_pszptr(CURRENTPTD()->CommDlgTd,
  1258. (VPVOID)mpex.Parm16.WndProc.lParam);
  1259. if (MSG16NEEDSTHUNKING(&mpex)) {
  1260. (mpex.lpfnUnThunk16)(&mpex);
  1261. }
  1262. }
  1263. }
  1264. FREEARGPTR(parg16);
  1265. RETURN((ULONG)mpex.lReturn);
  1266. }
  1267. /*++
  1268. DWORD SendMessage(<hwnd>, <msg>, <wParam>, <lParam>)
  1269. HWND <hwnd>;
  1270. WORD <msg>;
  1271. WORD <wParam>;
  1272. LONG <lParam>;
  1273. The %SendMessage% function sends a message to a window or windows. The
  1274. %SendMessage% function calls the window procedure for the specified window,
  1275. and does not return until that window procedure has processed the message.
  1276. This is in contrast to the %PostMessage% function which places the message
  1277. into the specified window's message queue and returns immediately.
  1278. <hwnd>
  1279. Identifies the window that is to receive the message. If this parameter
  1280. is 0xFFFF (-1), the message is sent to all top-level windows.
  1281. <msg>
  1282. Specifies the message to be sent.
  1283. <wParam>
  1284. Specifies additional message information. The contents of this
  1285. parameter depends on the message being sent.
  1286. <lParam>
  1287. Specifies additional message information. The contents of this
  1288. parameter depends on the message being sent.
  1289. The return value is the result returned by the invoked window procedure; its
  1290. value depends on the message being sent.
  1291. --*/
  1292. ULONG FASTCALL WU32SendMessage(PVDMFRAME pFrame)
  1293. {
  1294. // NOTE: This can be called directly by WU32PostMessage!!!
  1295. HWND hwnd;
  1296. register PSENDMESSAGE16 parg16;
  1297. MSGPARAMEX mpex;
  1298. HWND16 hwndOld;
  1299. UINT uMsgOld;
  1300. UINT uParamOld;
  1301. LONG lParamOld;
  1302. #ifdef DBCS
  1303. HMEM16 hMem16;
  1304. LPSZ lpBuf16,lpBuf32;
  1305. #endif // DBCS
  1306. GETARGPTR(pFrame, sizeof(SENDMESSAGE16), parg16);
  1307. hwndOld = parg16->f1;
  1308. uMsgOld = WORD32(parg16->f2);
  1309. uParamOld = WORD32(parg16->f3);
  1310. lParamOld = LONG32(parg16->f4);
  1311. //
  1312. // Check for funky apps sending WM_SYSCOMMAND - SC_CLOSE to progman
  1313. //
  1314. if ( uMsgOld == WM_SYSCOMMAND && uParamOld == SC_CLOSE ) {
  1315. if ( hwndOld == GETHWND16(hwndProgman) && hwndProgman != (HWND)0 ) {
  1316. //
  1317. // Now if shift key is down, they must be trying to save
  1318. // settings in progman.
  1319. //
  1320. if ( GetKeyState( VK_SHIFT ) < 0 ) {
  1321. uMsgOld = RegisterWindowMessage("SaveSettings");
  1322. }
  1323. }
  1324. }
  1325. //
  1326. // This is for the apps that use DDE protocol wrongly, like AmiPro.
  1327. //
  1328. WOW32ASSERT(fWhoCalled == FALSE);
  1329. fWhoCalled = WOWDDE_POSTMESSAGE;
  1330. mpex.lReturn = 0;
  1331. mpex.Parm16.WndProc.hwnd = hwndOld;
  1332. mpex.Parm16.WndProc.wMsg = (WORD)uMsgOld;
  1333. #ifdef DBCS
  1334. //
  1335. // For WIN3.1J's BUG ?
  1336. // SendMessage( hwnd, WM_GETTEXT, 2, lpBuffer )
  1337. // if string is DBCS, return is DBCS-leadbyte.
  1338. // KKSUZUKA:#1731
  1339. // 1994.8.8 add by V-HIDEKK
  1340. //
  1341. if( uMsgOld == WM_GETTEXT && uParamOld == 2 ){
  1342. mpex.Parm16.WndProc.wParam = (WORD)(uParamOld + 1);
  1343. mpex.Parm16.WndProc.lParam = GlobalAllocLock16( GMEM_SHARE | GMEM_MOVEABLE, uParamOld +1, &hMem16 );
  1344. }
  1345. else {
  1346. mpex.Parm16.WndProc.wParam = (WORD)uParamOld;
  1347. mpex.Parm16.WndProc.lParam = lParamOld;
  1348. }
  1349. #else // !DBCS
  1350. mpex.Parm16.WndProc.wParam = (WORD)uParamOld;
  1351. mpex.Parm16.WndProc.lParam = lParamOld;
  1352. #endif // !DBCS
  1353. mpex.iMsgThunkClass = 0;
  1354. hwnd = ThunkMsg16(&mpex);
  1355. // Note: ThunkMsg16 may have caused memory movement
  1356. FREEARGPTR(pFrame);
  1357. FREEARGPTR(parg16);
  1358. WOW32ASSERT(fWhoCalled == WOWDDE_POSTMESSAGE);
  1359. fWhoCalled = FALSE;
  1360. if (hwnd) {
  1361. BlockWOWIdle(TRUE);
  1362. #ifdef DEBUG
  1363. if ( WM_DDE_EXECUTE == mpex.uMsg ) {
  1364. // comes handy when debugging shell shortcut problems
  1365. LOGDEBUG(1,("dest %x, src%x, msg %s\n",hwnd,mpex.uParam,mpex.lParam));
  1366. }
  1367. #endif
  1368. mpex.lReturn = SendMessage(hwnd, mpex.uMsg, mpex.uParam, mpex.lParam);
  1369. BlockWOWIdle(FALSE);
  1370. #ifdef DBCS
  1371. //
  1372. // For WIN3.1J's BUG ?
  1373. // SendMessage( hwnd, WM_GETTEXT, 2, lpBuffer )
  1374. // if string is DBCS, return is DBCSLeadbyte.
  1375. // KKSUZUKA:#1731
  1376. // 1994.8.8 add by V-HIDEKK
  1377. //
  1378. if( uMsgOld == WM_GETTEXT && uParamOld == 2 ){
  1379. GETVDMPTR(mpex.Parm16.WndProc.lParam,mpex.Parm16.WndProc.wParam,lpBuf32);
  1380. GETVDMPTR(lParamOld,uParamOld,lpBuf16);
  1381. lpBuf16[0] = lpBuf32[0];
  1382. if( mpex.lReturn == 2 ){
  1383. lpBuf16[1] = 0;
  1384. mpex.lReturn = 1;
  1385. }
  1386. else {
  1387. lpBuf16[1] = lpBuf32[1];
  1388. }
  1389. FREEVDMPTR(lpBuf16);
  1390. FREEVDMPTR(lpBuf32);
  1391. GlobalUnlockFree16( mpex.Parm16.WndProc.lParam );
  1392. mpex.Parm16.WndProc.wParam = (WORD)uParamOld;
  1393. mpex.Parm16.WndProc.lParam = lParamOld;
  1394. }
  1395. #endif // DBCS
  1396. WOW32ASSERT(fWhoCalled == FALSE);
  1397. fWhoCalled = WOWDDE_POSTMESSAGE;
  1398. if (MSG16NEEDSTHUNKING(&mpex)) {
  1399. (mpex.lpfnUnThunk16)(&mpex);
  1400. }
  1401. WOW32ASSERT(fWhoCalled == WOWDDE_POSTMESSAGE);
  1402. fWhoCalled = FALSE;
  1403. }
  1404. FREEARGPTR(parg16);
  1405. RETURN((ULONG)mpex.lReturn);
  1406. }
  1407. /*++
  1408. int TranslateAccelerator(<hwnd>, <hAccTable>, <lpMsg>)
  1409. The %TranslateAccelerator% function processes keyboard accelerators for menu
  1410. commands. The %TranslateAccelerator% function translates WM_KEYUP and
  1411. WM_KEYDOWN messages to WM_COMMAND or WM_SYSCOMMAND messages, if there is an
  1412. entry for the key in the application's accelerator table. The high-order
  1413. word of the <lParam> parameter of the WM_COMMAND or WM_SYSCOMMAND message
  1414. contains the value 1 to differentiate the message from messages sent by
  1415. menus or controls.
  1416. WM_COMMAND or WM_SYSCOMMAND messages are sent directly to the window, rather
  1417. than being posted to the application queue. The %TranslateAccelerator%
  1418. function does not return until the message is processed.
  1419. Accelerator key strokes that are defined to select items from the system
  1420. menu are translated into WM_SYSCOMMAND messages; all other accelerators are
  1421. translated into WM_COMMAND messages.
  1422. <hwnd>
  1423. Identifies the window whose messages are to be translated.
  1424. <hAccTable>
  1425. %HANDLE% Identifies an accelerator table (loaded by using the
  1426. %LoadAccelerators% function).
  1427. <lpMsg>
  1428. Points to a message retrieved by using the %GetMessage% or
  1429. %PeekMessage% function. The message must be an %MSG% structure and
  1430. contain message information from the Windows application queue.
  1431. .cmt
  1432. 19-Sep-1990 [johnca]
  1433. Doesn't this function really return a BOOL?
  1434. .endcmt
  1435. The return value specifies the outcome of the function. It is nonzero if
  1436. translation occurs. Otherwise, it is zero.
  1437. When %TranslateAccelerator% returns nonzero (meaning that the message is
  1438. translated), the application should <not> process the message again by using
  1439. the %TranslateMessage% function.
  1440. Commands in accelerator tables do not have to correspond to menu items.
  1441. If the accelerator command does correspond to a menu item, the application
  1442. is sent WM_INITMENU and WM_INITMENUPOPUP messages, just as if the user were
  1443. trying to display the menu. However, these messages are not sent if any of
  1444. the following conditions are present:
  1445. o The window is disabled.
  1446. o The menu item is disabled.
  1447. o The command is not in the System menu and the window is minimized.
  1448. o A mouse capture is in effect (for more information, see the %SetCapture%
  1449. function, earlier in this chapter).
  1450. If the window is the active window and there is no keyboard focus (generally
  1451. true if the window is minimized), then WM_SYSKEYUP and WM_SYSKEYDOWN
  1452. messages are translated instead of WM_KEYUP and WM_KEYDOWN messages.
  1453. If an accelerator key stroke that corresponds to a menu item occurs when the
  1454. window that owns the menu is iconic, no WM_COMMAND message is sent. However,
  1455. if an accelerator key stroke that does not match any of the items on the
  1456. window's menu or the System menu occurs, a WM_COMMAND message is sent, even
  1457. if the window is iconic.
  1458. --*/
  1459. ULONG FASTCALL WU32TranslateAccelerator(PVDMFRAME pFrame)
  1460. {
  1461. ULONG ul;
  1462. MSG t3;
  1463. register PTRANSLATEACCELERATOR16 parg16;
  1464. GETARGPTR(pFrame, sizeof(TRANSLATEACCELERATOR16), parg16);
  1465. W32CopyMsgStruct(parg16->f3, &t3, TRUE);
  1466. ul = GETINT16(TranslateAccelerator(HWND32(parg16->f1),
  1467. HACCEL32(parg16->f2), &t3 ));
  1468. FREEARGPTR(parg16);
  1469. RETURN(ul);
  1470. }
  1471. /*++
  1472. BOOL TranslateMDISysAccel(<hwndClient>, <lpMsg>)
  1473. The %TranslateMDISysAccel% function processes keyboard accelerators for
  1474. multiple document interface (MDI) child window System-menu commands. The
  1475. %TranslateMDISysAccel% function translates WM_KEYUP and WM_KEYDOWN messages
  1476. to WM_SYSCOMMAND messages. The high-order word of the <lParam> parameter of
  1477. the WM_SYSCOMMAND message contains the value 1 to differentiate the message
  1478. from messages sent by menus or controls.
  1479. <hwndClient>
  1480. Identifies the parent MDI client window.
  1481. <lpMsg>
  1482. Points to a message retrieved by using the %GetMessage% or
  1483. %PeekMessage% function. The message must be an %MSG% structure and
  1484. contain message information from the Windows application queue.
  1485. The return value is TRUE if the function translated a message into a system
  1486. command. Otherwise, it is FALSE.
  1487. --*/
  1488. ULONG FASTCALL WU32TranslateMDISysAccel(PVDMFRAME pFrame)
  1489. {
  1490. ULONG ul;
  1491. MSG t2;
  1492. register PTRANSLATEMDISYSACCEL16 parg16;
  1493. GETARGPTR(pFrame, sizeof(TRANSLATEMDISYSACCEL16), parg16);
  1494. W32CopyMsgStruct(parg16->f2, &t2, TRUE);
  1495. ul = GETBOOL16(TranslateMDISysAccel(HWND32(parg16->f1), &t2));
  1496. FREEARGPTR(parg16);
  1497. RETURN(ul);
  1498. }
  1499. /*++
  1500. BOOL TranslateMessage(<lpMsg>)
  1501. The %TranslateMessage% function translates virtual-key messages into
  1502. character messages, as follows:
  1503. o WM_KEYDOWN/WM_KEYUP combinations produce a WM_CHAR or a WM_DEADCHAR
  1504. message.
  1505. o WM_SYSKEYDOWN/WM_SYSKEYUP combinations produce a WM_SYSCHAR or a
  1506. WM_SYSDEADCHAR message.
  1507. The character messages are posted to the application queue, to be read the
  1508. next time the application calls the %GetMessage% or %PeekMessage% function.
  1509. <lpMsg>
  1510. Points to a %MSG% structure retrieved through the GetMessage or
  1511. PeekMessage function. The structure contains message information from
  1512. the Windows application queue.
  1513. The return value specifies the outcome of the function. It is TRUE if the
  1514. message is translated (that is, character messages are posted to the
  1515. application queue). Otherwise, it is FALSE.
  1516. The %TranslateMessage% function does not modify the message given by the
  1517. <lpMsg> parameter.
  1518. %TranslateMessage% produces WM_CHAR messages only for keys which are mapped
  1519. to ASCII characters by the keyboard driver.
  1520. An application should not call %TranslateMessage% if the application
  1521. processes virtual-key messages for some other purpose. For instance, an
  1522. application should not call the %TranslateMessage% function if the
  1523. %TranslateAccelerator% function returns TRUE.
  1524. --*/
  1525. ULONG FASTCALL WU32TranslateMessage(PVDMFRAME pFrame)
  1526. {
  1527. ULONG ul;
  1528. MSG t1;
  1529. register PTRANSLATEMESSAGE16 parg16;
  1530. GETARGPTR(pFrame, sizeof(TRANSLATEMESSAGE16), parg16);
  1531. W32CopyMsgStruct(parg16->f1, &t1, TRUE);
  1532. ul = GETBOOL16(TranslateMessage( &t1 ));
  1533. FREEARGPTR(parg16);
  1534. RETURN(ul);
  1535. }
  1536. /*++
  1537. void WaitMessage(VOID)
  1538. The %WaitMessage% function yields control to other applications when an
  1539. application has no other tasks to perform. The %WaitMessage% function
  1540. suspends the application and does not return until a new message is placed
  1541. in the application's queue.
  1542. This function has no parameters.
  1543. This function does not return a value.
  1544. The %GetMessage%, %PeekMessage%, and %WaitMessage% functions yield control
  1545. to other applications. These calls are the only way to let other
  1546. applications run. If your application does not call any of these functions
  1547. for long periods of time, other applications cannot run.
  1548. When %GetMessage%, %PeekMessage%, and %WaitMessage% yield control to other
  1549. applications, the stack and data segments of the application calling the
  1550. function may move in memory to accommodate the changing memory requirements
  1551. of other applications. If the application has stored long pointers to
  1552. objects in the data or stack segment (that is, global or local variables),
  1553. these pointers can become invalid after a call to %GetMessage%,
  1554. %PeekMessage%, or %WaitMessage%.
  1555. --*/
  1556. ULONG FASTCALL WU32WaitMessage(PVDMFRAME pFrame)
  1557. {
  1558. UNREFERENCED_PARAMETER(pFrame);
  1559. BlockWOWIdle(TRUE);
  1560. WaitMessage();
  1561. BlockWOWIdle(FALSE);
  1562. RETURN(0);
  1563. }