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.

2650 lines
87 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: ClMsg.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * Includes the mapping table for messages when calling the server.
  7. *
  8. * 04-11-91 ScottLu Created.
  9. \***************************************************************************/
  10. #include "precomp.h"
  11. #pragma hdrstop
  12. #define fnINDESTROYCLIPBRD fnDWORD
  13. #define fnOUTDWORDDWORD fnDWORD
  14. #define fnPOWERBROADCAST fnDWORD
  15. #define fnLOGONNOTIFY fnKERNELONLY
  16. #define fnINLPKDRAWSWITCHWND fnKERNELONLY
  17. #define MSGFN(func) fn ## func
  18. #define FNSCSENDMESSAGE CFNSCSENDMESSAGE
  19. #include "messages.h"
  20. #if DBG
  21. BOOL gfTurboDWP = TRUE;
  22. #endif
  23. #define BEGIN_CALLWINPROC(fInsideHook, lRet) \
  24. PCLIENTTHREADINFO pcti = GetClientInfo()->pClientThreadInfo; \
  25. BOOL fCallBack = ((pcti!=NULL) && \
  26. TEST_BOOL_FLAG(pcti->CTIF_flags, CTIF_INCALLBACKMESSAGE)); \
  27. RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME ActivationFrame \
  28. = { \
  29. sizeof(ActivationFrame), \
  30. RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER \
  31. }; \
  32. fInsideHook = FALSE; \
  33. \
  34. if (!fCallBack) { \
  35. RtlActivateActivationContextUnsafeFast( \
  36. &ActivationFrame, \
  37. pActCtx); \
  38. \
  39. fInsideHook = _BeginIfHookedUserApiHook(); \
  40. } \
  41. \
  42. __try { \
  43. #define END_CALLWINPROC(fInsideHook) \
  44. } __finally { \
  45. if (!fCallBack) { \
  46. if (fInsideHook) { \
  47. _EndUserApiHook(); \
  48. } \
  49. RtlDeactivateActivationContextUnsafeFast( \
  50. &ActivationFrame); \
  51. } \
  52. }
  53. /***************************************************************************\
  54. * UserCallWinProc
  55. *
  56. * Setups everything to finally call a Win32 WNDPROC
  57. *
  58. * History:
  59. * 27-Apr-2000 jstall Rewrote to support "lightweight hooks"
  60. \***************************************************************************/
  61. LRESULT
  62. UserCallWinProc(
  63. PACTIVATION_CONTEXT pActCtx,
  64. WNDPROC pfn,
  65. HWND hwnd,
  66. UINT msg,
  67. WPARAM wParam,
  68. LPARAM lParam)
  69. {
  70. BOOL fInsideHook;
  71. LRESULT lRet = 0;
  72. BEGIN_CALLWINPROC(fInsideHook, lRet)
  73. BOOL fOverride = fInsideHook && IsMsgOverride(msg, &guah.uoiWnd.mm);
  74. pfn = MapKernelClientFnToClientFn(pfn);
  75. if (fOverride) {
  76. /*
  77. * NOTE: It is important that the same lRet is passed to all three
  78. * calls, allowing the Before and After OWP's to examine the value.
  79. */
  80. PVOID pvCookie = NULL;
  81. if (!guah.uoiWnd.pfnBeforeOWP(hwnd, msg, wParam, lParam, &lRet, &pvCookie)) {
  82. lRet = InternalCallWinProc((WNDPROC)KPVOID_TO_PVOID(pfn),
  83. hwnd,
  84. msg,
  85. wParam,
  86. lParam);
  87. guah.uoiWnd.pfnAfterOWP(hwnd, msg, wParam, lParam, &lRet, &pvCookie);
  88. }
  89. } else {
  90. lRet = InternalCallWinProc((WNDPROC)KPVOID_TO_PVOID(pfn),
  91. hwnd,
  92. msg,
  93. wParam,
  94. lParam);
  95. }
  96. END_CALLWINPROC(fInsideHook)
  97. return lRet;
  98. }
  99. /***************************************************************************\
  100. * UserCallWinProcCheckWow
  101. *
  102. * Sets up everything to finally call a Win32 or WOW WNDPROC.
  103. *
  104. * History:
  105. * 27-Apr-2000 jstall Rewrote to support "lightweight hooks"
  106. \***************************************************************************/
  107. LRESULT
  108. UserCallWinProcCheckWow(
  109. PACTIVATION_CONTEXT pActCtx,
  110. WNDPROC pfn,
  111. HWND hwnd,
  112. UINT msg,
  113. WPARAM wParam,
  114. LPARAM lParam,
  115. PVOID pww,
  116. BOOL fEnableLiteHooks)
  117. {
  118. BOOL fInsideHook;
  119. LRESULT lRet = 0;
  120. BEGIN_CALLWINPROC(fInsideHook, lRet)
  121. BOOL fOverride = fInsideHook && fEnableLiteHooks && IsMsgOverride(msg, &guah.uoiWnd.mm);
  122. pfn = MapKernelClientFnToClientFn(pfn);
  123. if (fOverride) {
  124. /*
  125. * NOTE: It is important that the same lRet is passed to all three
  126. * calls, allowing the Before and After OWP's to examine the value.
  127. */
  128. void * pvCookie = NULL;
  129. if (guah.uoiWnd.pfnBeforeOWP(hwnd, msg, wParam, lParam, &lRet, &pvCookie)) {
  130. goto DoneCalls;
  131. }
  132. lRet = (IsWOWProc(pfn) ? (*pfnWowWndProcEx)(hwnd, msg, wParam, lParam, PtrToUlong(pfn), KPVOID_TO_PVOID(pww)) :
  133. InternalCallWinProc((WNDPROC)KPVOID_TO_PVOID(pfn), hwnd, msg, wParam, lParam));
  134. if (guah.uoiWnd.pfnAfterOWP(hwnd, msg, wParam, lParam, &lRet, &pvCookie)) {
  135. // Fall through and exit normally
  136. }
  137. DoneCalls:
  138. ;
  139. } else {
  140. lRet = (IsWOWProc(pfn) ? (*pfnWowWndProcEx)(hwnd, msg, wParam, lParam, PtrToUlong(pfn), KPVOID_TO_PVOID(pww)) :
  141. InternalCallWinProc((WNDPROC)KPVOID_TO_PVOID(pfn), hwnd, msg, wParam, lParam));
  142. }
  143. END_CALLWINPROC(fInsideHook)
  144. return lRet;
  145. #ifdef _WIN64
  146. UNREFERENCED_PARAMETER(pww);
  147. #endif // _WIN64
  148. }
  149. /***************************************************************************\
  150. * UserCallDlgProcCheckWow
  151. *
  152. * Setups everything to finally call a Win32 or WOW DLGPROC
  153. *
  154. * History:
  155. * 27-Apr-2000 jstall Rewrote to support "lightweight hooks"
  156. \***************************************************************************/
  157. BOOL
  158. UserCallDlgProcCheckWow(
  159. PACTIVATION_CONTEXT pActCtx,
  160. DLGPROC pfn,
  161. HWND hwnd,
  162. UINT msg,
  163. WPARAM wParam,
  164. LPARAM lParam,
  165. PVOID pww,
  166. INT_PTR * pret)
  167. {
  168. BOOL fInsideHook;
  169. INT_PTR fRet = 0;
  170. BOOL fHandled = FALSE;
  171. BEGIN_CALLWINPROC(fInsideHook, fRet)
  172. BOOL fOverride = fInsideHook && IsMsgOverride(msg, &guah.uoiDlg.mm);
  173. pfn = MapKernelClientFnToClientFn(pfn);
  174. if (fOverride) {
  175. /*
  176. * NOTE: It is important that the same lRet is passed to all three
  177. * calls, allowing the Before and After OWP's to examine the value.
  178. */
  179. void * pvCookie = NULL;
  180. if (guah.uoiDlg.pfnBeforeOWP(hwnd, msg, wParam, lParam, (LRESULT*) &fRet, &pvCookie)) {
  181. fHandled = TRUE;
  182. goto DoneCalls;
  183. }
  184. fRet = (IsWOWProc(pfn) ? (*pfnWowDlgProcEx)(hwnd, msg, wParam, lParam, PtrToUlong(pfn), KPVOID_TO_PVOID(pww)) :
  185. InternalCallWinProc((WNDPROC)KPVOID_TO_PVOID(pfn), hwnd, msg, wParam, lParam));
  186. if (guah.uoiDlg.pfnAfterOWP(hwnd, msg, wParam, lParam, (LRESULT*) &fRet, &pvCookie)) {
  187. fHandled = TRUE;
  188. // Fall through and exit normally
  189. }
  190. DoneCalls:
  191. ;
  192. } else {
  193. fRet = (IsWOWProc(pfn) ? (*pfnWowDlgProcEx)(hwnd, msg, wParam, lParam, PtrToUlong(pfn), KPVOID_TO_PVOID(pww)) :
  194. InternalCallWinProc((WNDPROC)KPVOID_TO_PVOID(pfn), hwnd, msg, wParam, lParam));
  195. }
  196. END_CALLWINPROC(fInsideHook)
  197. *pret = fRet;
  198. return fHandled;
  199. #ifdef _WIN64
  200. UNREFERENCED_PARAMETER(pww);
  201. #endif // _WIN64
  202. }
  203. /***************************************************************************\
  204. * GetMouseKeyState
  205. *
  206. * Returns the state of mouse and keyboard keys that are sent
  207. * in a mouse message.
  208. *
  209. * History:
  210. * 12-Nov-1998 adams Created.
  211. \***************************************************************************/
  212. WORD
  213. GetMouseKeyState(void)
  214. {
  215. WORD keystate;
  216. /*
  217. * Note that it is more efficient to call GetKeyState for each
  218. * key than to call GetKeyboardState, since the keys we are testing
  219. * are cached and don't require a trip to the kernel to fetch.
  220. */
  221. #define TESTANDSETKEYSTATE(x) \
  222. if (GetKeyState(VK_##x) & 0x8000) { \
  223. keystate |= MK_##x; \
  224. }
  225. keystate = 0;
  226. TESTANDSETKEYSTATE(LBUTTON)
  227. TESTANDSETKEYSTATE(RBUTTON)
  228. TESTANDSETKEYSTATE(MBUTTON)
  229. TESTANDSETKEYSTATE(XBUTTON1)
  230. TESTANDSETKEYSTATE(XBUTTON2)
  231. TESTANDSETKEYSTATE(SHIFT)
  232. TESTANDSETKEYSTATE(CONTROL)
  233. return keystate;
  234. }
  235. /***************************************************************************\
  236. * These are client side thunks for server side window procs. This is being
  237. * done so that when an app gets a wndproc via GetWindowLong, GetClassLong,
  238. * or GetClassInfo, it gets a real callable address - some apps don't call
  239. * CallWindowProc, but call the return ed address directly.
  240. *
  241. * 01-13-92 ScottLu Created.
  242. * 03-Dec-1993 mikeke added client side handling of some messages
  243. \***************************************************************************/
  244. LRESULT WINAPI DesktopWndProcWorker(
  245. HWND hwnd,
  246. UINT message,
  247. WPARAM wParam,
  248. LPARAM lParam,
  249. BOOL fAnsi)
  250. {
  251. PWND pwnd;
  252. if (FWINDOWMSG(message, FNID_DESKTOP)) {
  253. return CsSendMessage(hwnd, message, wParam, lParam,
  254. 0L, FNID_DESKTOP, fAnsi);
  255. }
  256. if ((pwnd = ValidateHwnd(hwnd)) == NULL)
  257. return 0;
  258. return DefWindowProcWorker(pwnd, message, wParam, lParam, fAnsi);
  259. }
  260. LRESULT WINAPI DesktopWndProcA(
  261. HWND hwnd,
  262. UINT message,
  263. WPARAM wParam,
  264. LPARAM lParam)
  265. {
  266. return DesktopWndProcWorker(hwnd, message, wParam, lParam, TRUE);
  267. }
  268. LRESULT WINAPI DesktopWndProcW(
  269. HWND hwnd,
  270. UINT message,
  271. WPARAM wParam,
  272. LPARAM lParam)
  273. {
  274. return DesktopWndProcWorker(hwnd, message, wParam, lParam, FALSE);
  275. }
  276. /***************************************************************************\
  277. * These are client side thunks for server side window procs. This is being
  278. * done so that when an app gets a wndproc via GetWindowLong, GetClassLong,
  279. * or GetClassInfo, it gets a real callable address - some apps don't call
  280. * CallWindowProc, but call the return ed address directly.
  281. *
  282. * 01-13-92 ScottLu Created.
  283. * 03-Dec-1993 mikeke added client side handling of some messages
  284. \***************************************************************************/
  285. LRESULT WINAPI MenuWndProcWorker(
  286. HWND hwnd,
  287. UINT message,
  288. WPARAM wParam,
  289. LPARAM lParam,
  290. BOOL fAnsi)
  291. {
  292. PWND pwnd;
  293. if (FWINDOWMSG(message, FNID_MENU)) {
  294. return CsSendMessage(hwnd, message, wParam, lParam,
  295. 0L, FNID_MENU, fAnsi);
  296. }
  297. if ((pwnd = ValidateHwnd(hwnd)) == NULL)
  298. return 0;
  299. switch (message) {
  300. case WM_LBUTTONDBLCLK:
  301. case WM_NCLBUTTONDBLCLK:
  302. case WM_RBUTTONDBLCLK:
  303. case WM_NCRBUTTONDBLCLK:
  304. /*
  305. * Ignore double clicks on these windows.
  306. */
  307. break;
  308. case WM_DESTROY:
  309. break;
  310. default:
  311. return DefWindowProcWorker(pwnd, message, wParam, lParam, fAnsi);
  312. }
  313. return 0;
  314. }
  315. LRESULT WINAPI MenuWndProcA(
  316. HWND hwnd,
  317. UINT message,
  318. WPARAM wParam,
  319. LPARAM lParam)
  320. {
  321. return MenuWndProcWorker(hwnd, message, wParam, lParam, TRUE);
  322. }
  323. LRESULT WINAPI MenuWndProcW(
  324. HWND hwnd,
  325. UINT message,
  326. WPARAM wParam,
  327. LPARAM lParam)
  328. {
  329. return MenuWndProcWorker(hwnd, message, wParam, lParam, FALSE);
  330. }
  331. /***************************************************************************\
  332. \***************************************************************************/
  333. LRESULT WINAPI ScrollBarWndProcWorker(
  334. HWND hwnd,
  335. UINT message,
  336. WPARAM wParam,
  337. LPARAM lParam,
  338. BOOL fAnsi)
  339. {
  340. PSBWND psbwnd;
  341. LPSCROLLINFO lpsi;
  342. PSBDATA pw;
  343. if (FWINDOWMSG(message, FNID_SCROLLBAR)) {
  344. return CsSendMessage(hwnd, message, wParam, lParam,
  345. 0L, FNID_SCROLLBAR, fAnsi);
  346. }
  347. if ((psbwnd = (PSBWND)ValidateHwnd(hwnd)) == NULL)
  348. return 0;
  349. switch (message) {
  350. case WM_GETDLGCODE:
  351. return DLGC_WANTARROWS;
  352. case SBM_GETPOS:
  353. return (LONG)psbwnd->SBCalc.pos;
  354. case SBM_GETRANGE:
  355. *((LPINT)wParam) = psbwnd->SBCalc.posMin;
  356. *((LPINT)lParam) = psbwnd->SBCalc.posMax;
  357. return 0;
  358. case SBM_GETSCROLLINFO:
  359. lpsi = (LPSCROLLINFO)lParam;
  360. if ((lpsi->cbSize != sizeof(SCROLLINFO)) &&
  361. (lpsi->cbSize != sizeof(SCROLLINFO) - 4)) {
  362. RIPMSG0(RIP_ERROR, "SCROLLINFO: invalid cbSize");
  363. return FALSE;
  364. }
  365. if (lpsi->fMask & ~SIF_MASK)
  366. {
  367. RIPMSG0(RIP_ERROR, "SCROLLINFO: Invalid fMask");
  368. return FALSE;
  369. }
  370. pw = (PSBDATA)KPSBDATA_TO_PSBDATA(&(psbwnd->SBCalc));
  371. return(NtUserSBGetParms(hwnd, SB_CTL, pw, lpsi));
  372. case SBM_GETSCROLLBARINFO:
  373. return NtUserGetScrollBarInfo(hwnd, OBJID_CLIENT, (PSCROLLBARINFO)lParam);
  374. default:
  375. return DefWindowProcWorker((PWND)psbwnd, message,
  376. wParam, lParam, fAnsi);
  377. }
  378. }
  379. LRESULT WINAPI ScrollBarWndProcA(
  380. HWND hwnd,
  381. UINT message,
  382. WPARAM wParam,
  383. LPARAM lParam)
  384. {
  385. return ScrollBarWndProcWorker(hwnd, message, wParam, lParam, TRUE);
  386. }
  387. LRESULT WINAPI ScrollBarWndProcW(
  388. HWND hwnd,
  389. UINT message,
  390. WPARAM wParam,
  391. LPARAM lParam)
  392. {
  393. return ScrollBarWndProcWorker(hwnd, message, wParam, lParam, FALSE);
  394. }
  395. /***************************************************************************\
  396. * SendMessage
  397. *
  398. * Translates the message, calls SendMessage on server side.
  399. *
  400. * 04-11-91 ScottLu Created.
  401. * 04-27-92 DarrinM Added code to support client-to-client SendMessages.
  402. \***************************************************************************/
  403. LRESULT SendMessageWorker(
  404. PWND pwnd,
  405. UINT message,
  406. WPARAM wParam,
  407. LPARAM lParam,
  408. BOOL fAnsi)
  409. {
  410. HWND hwnd = HWq(pwnd);
  411. PCLIENTINFO pci;
  412. PCLS pcls;
  413. BOOLEAN fAnsiRecv;
  414. BOOLEAN fNeedTranslation = FALSE;
  415. BOOLEAN bDoDbcsMessaging = FALSE;
  416. LRESULT lRet;
  417. UserAssert(pwnd);
  418. /*
  419. * Pass DDE messages to the server.
  420. */
  421. if (message >= WM_DDE_FIRST && message <= WM_DDE_LAST)
  422. goto lbServerSendMessage;
  423. /*
  424. * Server must handle inter-thread SendMessages and SendMessages
  425. * to server-side procs.
  426. */
  427. if ((PtiCurrent() != GETPTI(pwnd)) || TestWF(pwnd, WFSERVERSIDEPROC))
  428. goto lbServerSendMessage;
  429. /*
  430. * Server must handle hooks (at least for now).
  431. */
  432. pci = GetClientInfo();
  433. if (IsHooked(pci, (WHF_CALLWNDPROC | WHF_CALLWNDPROCRET))) {
  434. lbServerSendMessage:
  435. return CsSendMessage(hwnd, message, wParam, lParam, 0L,
  436. FNID_SENDMESSAGE, fAnsi);
  437. }
  438. /*
  439. * If the sender and the receiver are both ANSI or both UNICODE
  440. * then no message translation is necessary.
  441. *
  442. * EditWndProc may need to go to the server for translation if we
  443. * are calling vanilla EditWndProc from SendMessageA and the edit
  444. * control is currently subclassed Ansi but the edit control is
  445. * stored Unicode.
  446. */
  447. fAnsiRecv = !!(TestWF(pwnd, WFANSIPROC));
  448. if (!fAnsi != !fAnsiRecv) {
  449. /*
  450. * Translation might be necessary between sender and receiver,
  451. * check to see if this is one of the messages we translate.
  452. */
  453. switch (message) {
  454. case WM_CHARTOITEM:
  455. case EM_SETPASSWORDCHAR:
  456. case WM_CHAR:
  457. case WM_DEADCHAR:
  458. case WM_SYSCHAR:
  459. case WM_SYSDEADCHAR:
  460. case WM_MENUCHAR:
  461. case WM_IME_CHAR:
  462. case WM_IME_COMPOSITION:
  463. if (fAnsi) {
  464. /*
  465. * Setup DBCS Messaging for WM_CHAR...
  466. */
  467. BUILD_DBCS_MESSAGE_TO_CLIENTW_FROM_CLIENTA(message,wParam,TRUE);
  468. /*
  469. * Convert wParam to Unicode...
  470. */
  471. RtlMBMessageWParamCharToWCS(message, &wParam);
  472. /*
  473. * The message has been converted to Unicode.
  474. */
  475. fAnsi = FALSE;
  476. } else {
  477. POINT ptZero = {0,0};
  478. /*
  479. * Convert wParam to ANSI...
  480. */
  481. RtlWCSMessageWParamCharToMB(message, &wParam);
  482. /*
  483. * Let's DBCS messaging for WM_CHAR....
  484. */
  485. BUILD_DBCS_MESSAGE_TO_CLIENTA_FROM_CLIENTW(
  486. hwnd,message,wParam,lParam,0,ptZero,bDoDbcsMessaging);
  487. /*
  488. * The message has been converted to ANSI.
  489. */
  490. fAnsi = TRUE;
  491. }
  492. break;
  493. case EM_SETSEL:
  494. case EM_GETSEL:
  495. case CB_GETEDITSEL:
  496. if (IS_DBCS_ENABLED()) {
  497. RIPERR1(ERROR_INVALID_PARAMETER,
  498. RIP_WARNING,
  499. "Invalid DBCS message (%x) to SendMessageWorker",message);
  500. }
  501. //
  502. // Fall down...
  503. default:
  504. if ((message < WM_USER) && MessageTable[message].bThunkMessage) {
  505. fNeedTranslation = TRUE;
  506. }
  507. }
  508. }
  509. #ifndef LATER
  510. /*
  511. * If the window has a client side worker proc and has
  512. * not been subclassed, dispatch the message directly
  513. * to the worker proc. Otherwise, dispatch it normally.
  514. */
  515. pcls = REBASEALWAYS(pwnd, pcls);
  516. if ((!IsInsideUserApiHook()) &&
  517. (pcls->fnid >= FNID_CONTROLSTART && pcls->fnid <= FNID_CONTROLEND) &&
  518. ((KERNEL_ULONG_PTR)pwnd->lpfnWndProc == FNID_TO_CLIENT_PFNW_KERNEL(pcls->fnid) ||
  519. (KERNEL_ULONG_PTR)pwnd->lpfnWndProc == FNID_TO_CLIENT_PFNA_KERNEL(pcls->fnid))) {
  520. PWNDMSG pwm = &gSharedInfo.awmControl[pcls->fnid - FNID_START];
  521. /*
  522. * If this message is not processed by the control, call
  523. * xxxDefWindowProc
  524. */
  525. if (pwm->abMsgs && ((message > pwm->maxMsgs) ||
  526. !((pwm->abMsgs)[message / 8] & (1 << (message & 7))))) {
  527. /*
  528. * Special case dialogs so that we can ignore unimportant
  529. * messages during dialog creation.
  530. */
  531. if (pcls->fnid == FNID_DIALOG &&
  532. PDLG(pwnd) && PDLG(pwnd)->lpfnDlg != NULL) {
  533. /*
  534. * If A/W translation are needed for Dialog,
  535. * it should go to kernel side to perform proper message.
  536. * DefDlgProcWorker will call aplication's DlgProc directly
  537. * without A/W conversion.
  538. */
  539. if (fNeedTranslation) {
  540. goto lbServerSendMessage;
  541. }
  542. /*
  543. * Call woker procudure.
  544. */
  545. SendMessageToWorker1Again:
  546. lRet = ((PROC)(FNID_TO_CLIENT_PFNWORKER(pcls->fnid)))(pwnd, message, wParam, lParam, fAnsi);
  547. /*
  548. * if we have DBCS TrailingByte that should be sent, send it here..
  549. */
  550. DISPATCH_DBCS_MESSAGE_IF_EXIST(message,wParam,bDoDbcsMessaging,SendMessageToWorker1);
  551. return lRet;
  552. } else {
  553. /*
  554. * Call worker procedure.
  555. */
  556. SendMessageToDefWindowAgain:
  557. lRet = DefWindowProcWorker(pwnd, message, wParam, lParam, fAnsi);
  558. /*
  559. * if we have DBCS TrailingByte that should be sent, send it here..
  560. */
  561. DISPATCH_DBCS_MESSAGE_IF_EXIST(message,wParam,bDoDbcsMessaging,SendMessageToDefWindow);
  562. return lRet;
  563. }
  564. } else {
  565. /*
  566. * Call woker procudure.
  567. */
  568. SendMessageToWorker2Again:
  569. lRet = ((PROC)(FNID_TO_CLIENT_PFNWORKER(pcls->fnid)))(pwnd, message, wParam, lParam, fAnsi);
  570. /*
  571. * if we have DBCS TrailingByte that should be sent, send it here..
  572. */
  573. DISPATCH_DBCS_MESSAGE_IF_EXIST(message,wParam,bDoDbcsMessaging,SendMessageToWorker2);
  574. return lRet;
  575. }
  576. }
  577. #endif
  578. /*
  579. * If this message needs to be translated, go through the kernel.
  580. */
  581. if (fNeedTranslation) {
  582. goto lbServerSendMessage;
  583. }
  584. /*
  585. * Call Client Windows procudure.
  586. */
  587. SendMessageToWndProcAgain:
  588. lRet = UserCallWinProcCheckWow(pwnd->pActCtx, (WNDPROC)pwnd->lpfnWndProc, hwnd, message, wParam, lParam, &(pwnd->state), TRUE);
  589. /*
  590. * if we have DBCS TrailingByte that should be sent, send it here..
  591. */
  592. DISPATCH_DBCS_MESSAGE_IF_EXIST(message,wParam,bDoDbcsMessaging,SendMessageToWndProc);
  593. return lRet;
  594. }
  595. // LATER!!! can this somehow be combined or subroutinized with SendMessageWork
  596. // so we don't have to copies of 95% identical code.
  597. /***************************************************************************\
  598. * SendMessageTimeoutWorker
  599. *
  600. * Translates the message, calls SendMessageTimeout on server side.
  601. *
  602. * 07-21-92 ChrisBB Created/modified SendMessageWorkder
  603. \***************************************************************************/
  604. LRESULT SendMessageTimeoutWorker(
  605. HWND hwnd,
  606. UINT message,
  607. WPARAM wParam,
  608. LPARAM lParam,
  609. UINT fuFlags,
  610. UINT uTimeout,
  611. PULONG_PTR lpdwResult,
  612. BOOL fAnsi)
  613. {
  614. SNDMSGTIMEOUT smto;
  615. /*
  616. * Prevent apps from setting hi 16 bits so we can use them internally.
  617. */
  618. if (message & RESERVED_MSG_BITS) {
  619. RIPERR1(ERROR_INVALID_PARAMETER,
  620. RIP_WARNING,
  621. "Invalid parameter \"message\" (%ld) to SendMessageTimeoutWorker",
  622. message);
  623. return(0);
  624. }
  625. if (fuFlags & ~SMTO_VALID) {
  626. RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "invalid dwFlags (%x) for SendMessageTimeout\n", fuFlags);
  627. return(0);
  628. }
  629. if (lpdwResult != NULL)
  630. *lpdwResult = 0L;
  631. /*
  632. * Always send broadcast requests straight to the server.
  633. * Note: the xParam is used to id if it's from timeout or
  634. * from an normal sendmessage.
  635. */
  636. smto.fuFlags = fuFlags;
  637. smto.uTimeout = uTimeout;
  638. smto.lSMTOReturn = 0;
  639. smto.lSMTOResult = 0;
  640. /*
  641. * Thunk through a special sendmessage for -1 hwnd's so that the general
  642. * purpose thunks don't allow -1 hwnd's.
  643. */
  644. if (hwnd == (HWND)-1 || hwnd == (HWND)0x0000FFFF) {
  645. /*
  646. * Get a real hwnd so the thunks will validation ok. Note that since
  647. * -1 hwnd is really rare, calling GetDesktopWindow() here is not a
  648. * big deal.
  649. */
  650. hwnd = GetDesktopWindow();
  651. CsSendMessage(hwnd, message, wParam, lParam,
  652. (ULONG_PTR)&smto, FNID_SENDMESSAGEFF, fAnsi);
  653. } else {
  654. CsSendMessage(hwnd, message, wParam, lParam,
  655. (ULONG_PTR)&smto, FNID_SENDMESSAGEEX, fAnsi);
  656. }
  657. if (lpdwResult != NULL)
  658. *lpdwResult = smto.lSMTOResult;
  659. return smto.lSMTOReturn;
  660. }
  661. #ifdef LAME_BUTTON
  662. PLAMEBTNPROC gpfnCommentReport;
  663. VOID LoadCommentReportIfNeeded(
  664. VOID)
  665. {
  666. if (gpfnCommentReport == NULL) {
  667. HMODULE hmod = LoadLibrary(L"LAMEBTN.DLL");
  668. if (hmod != NULL) {
  669. gpfnCommentReport = (PLAMEBTNPROC)GetProcAddress(hmod, "CommentReport");
  670. if (gpfnCommentReport == NULL) {
  671. FreeLibrary(hmod);
  672. }
  673. }
  674. }
  675. }
  676. VOID CallLameButtonHandler(
  677. PWND pwnd,
  678. HWND hwnd)
  679. {
  680. UNREFERENCED_PARAMETER(pwnd);
  681. UserAssert(TestWF(pwnd, WEFLAMEBUTTON));
  682. LoadCommentReportIfNeeded();
  683. if (gpfnCommentReport != NULL) {
  684. (*gpfnCommentReport)(hwnd, GetProp(hwnd, MAKEINTATOM(gatomLameButton)));
  685. }
  686. }
  687. #endif // LAME_BUTTON
  688. VOID CopyMsgMask(
  689. MSGMASK * pDest,
  690. MSGMASK * pSrc,
  691. BYTE * rgbLocal,
  692. DWORD cbMax)
  693. {
  694. if ((pSrc->rgb != NULL) && (pSrc->cb > 0)) {
  695. pDest->rgb = rgbLocal;
  696. pDest->cb = min(cbMax, pSrc->cb);
  697. CopyMemory(pDest->rgb, pSrc->rgb, pDest->cb);
  698. } else {
  699. pDest->rgb = NULL;
  700. pDest->cb = 0;
  701. }
  702. }
  703. /***************************************************************************\
  704. * InitUserApiHook
  705. *
  706. * This function gets called when the module that contains the UserApiHook's
  707. * gets loaded. The UserApiHook is installed by calling
  708. * RegisterUserApiHook and is loaded on demand by xxxCreateWindowEx and/or
  709. * xxxDefWindowProc. The loading/unloading is controlled through the library
  710. * management routines. The function calls the initialization function in the
  711. * module and then sets up our global variables.
  712. *
  713. * We keep 2 reference counts. One counts calls to LoadLibrary/FreeLibrary. When
  714. * this goes to zero, we can stop calling out to the substitute UserApiHook's.
  715. * The other gets incremented when we do an actual callout to the substitute
  716. * UserApiHook and decremented on return. We can't actually unload the module
  717. * until this count goes to zero too (i.e. we aren't in a callout).
  718. *
  719. * History:
  720. * 10-Mar-2000 JerrySh Created.
  721. * 16-May-2000 JStall Changed to support uninitialize callback
  722. * 12-Feb-2001 Mohamed Added the check for read-only on reset ptr.
  723. \***************************************************************************/
  724. BOOL InitUserApiHook(
  725. HMODULE hmod,
  726. ULONG_PTR offPfnInitUserApiHook)
  727. {
  728. INITUSERAPIHOOK pfnInitUserApi = NULL;
  729. USERAPIHOOK uahTemp;
  730. BOOL bUpdate= FALSE;
  731. BOOL retval = FALSE;
  732. /*
  733. * If we're loading for the first time, call the initialization routine.
  734. */
  735. ResetUserApiHook(&uahTemp);
  736. pfnInitUserApi = (INITUSERAPIHOOK)((ULONG_PTR)hmod + offPfnInitUserApiHook);
  737. bUpdate = pfnInitUserApi(UIAH_INITIALIZE, &uahTemp);
  738. /*
  739. * Check that the value of pfnForceResetUserApiHook hasn't been changed
  740. * by client since this should be treated as read-only.
  741. */
  742. if ((!bUpdate) || (uahTemp.cbSize <= 0) || (uahTemp.pfnForceResetUserApiHook != ForceResetUserApiHook)) {
  743. return FALSE;
  744. }
  745. RtlEnterCriticalSection(&gcsUserApiHook);
  746. /*
  747. * Need to check this again inside critical section.
  748. */
  749. if (ghmodUserApiHook == NULL) {
  750. UserAssertMsg0(gpfnInitUserApi == NULL, "Ensure gpfnInitUserApi not set");
  751. /*
  752. * Save the global state if the init routine succeeded.
  753. * Copy the hooked functions
  754. */
  755. UserAssert(gcLoadUserApiHook == 0);
  756. gcLoadUserApiHook = 1;
  757. gfUserApiHook = TRUE; // Turn calling the hooks on
  758. ghmodUserApiHook = hmod;
  759. gpfnInitUserApi = pfnInitUserApi;
  760. CopyMemory(&guah, &uahTemp, uahTemp.cbSize);
  761. /*
  762. * Copy the message-filter bit-mask
  763. */
  764. CopyMsgMask(&guah.mmDWP, &uahTemp.mmDWP, grgbDwpLiteHookMsg, sizeof(grgbDwpLiteHookMsg));
  765. CopyMsgMask(&guah.uoiWnd.mm, &uahTemp.uoiWnd.mm, grgbWndLiteHookMsg, sizeof(grgbWndLiteHookMsg));
  766. CopyMsgMask(&guah.uoiDlg.mm, &uahTemp.uoiDlg.mm, grgbDlgLiteHookMsg, sizeof(grgbDlgLiteHookMsg));
  767. retval = TRUE;
  768. } else if (ghmodUserApiHook == hmod) {
  769. /*
  770. * This is the UserApiHook module, so bump up the reference count.
  771. */
  772. UserAssert(gcLoadUserApiHook < MAXLONG);
  773. UserAssertMsg0(gpfnInitUserApi == pfnInitUserApi, "Need to match from before");
  774. ++gcLoadUserApiHook;
  775. retval = TRUE;
  776. }
  777. RtlLeaveCriticalSection(&gcsUserApiHook);
  778. if (!retval) {
  779. /*
  780. * Initialization failed, so ClientLoadLibrary() is going to
  781. * FreeLibrary(). Notify before we do this.
  782. */
  783. RIPMSG2(RIP_WARNING, "Uninit from Init Load %lx Call %lx", gcLoadUserApiHook, gcCallUserApiHook);
  784. pfnInitUserApi(UIAH_UNINITIALIZE, NULL);
  785. }
  786. return retval;
  787. }
  788. /***************************************************************************\
  789. * ClearUserApiHook
  790. *
  791. * This function gets called when the module that contains the UserApiHook
  792. * is about to get unloaded. The unload happens when UnregisterUserApiHook
  793. * is called or the process that registered it exits. If this is the last unload,
  794. * we'll clear the globals containing the UserApiHook function addresses so we
  795. * don't do any more callouts. If we're not currently doing a callout, we'll
  796. * indicate that it's OK to unload the module. Otherwise, it'll get unloaded
  797. * when the last callout completes.
  798. *
  799. * History:
  800. * 10-Mar-2000 JerrySh Created.
  801. * 16-May-2000 JStall Changed to support uninitialize callback
  802. * 03-Apr-2001 Mohamed Added support for UIAH_UNHOOK logic.
  803. \***************************************************************************/
  804. BOOL ClearUserApiHook(
  805. HMODULE hmod)
  806. {
  807. INITUSERAPIHOOK pfnInitUserApi = NULL;
  808. INITUSERAPIHOOK pfnSignalInitUserApi = NULL;
  809. /*
  810. * If this is the last reference to the UserApiHook module, clear the
  811. * global state.
  812. */
  813. RtlEnterCriticalSection(&gcsUserApiHook);
  814. if (ghmodUserApiHook == hmod) {
  815. UserAssert(gcLoadUserApiHook > 0);
  816. UserAssertMsg0(gpfnInitUserApi != NULL, "Ensure gpfnInitUserApi properly set");
  817. UserAssertMsg0(ghmodUserApiHook != NULL, "Should still have valid ghmodUserApiHook");
  818. pfnInitUserApi = gpfnInitUserApi;
  819. if (--gcLoadUserApiHook == 0) {
  820. /*
  821. * Use the internal functions, so turn calling the hooks off. It is
  822. * very important to set gfUserApiHook FALSE here so that new calls
  823. * do not increment gcCallUserApiHook and keep the DLL from being
  824. * unloaded.
  825. */
  826. gfUserApiHook = FALSE;
  827. ResetUserApiHook(&guah);
  828. if (gcCallUserApiHook == 0) {
  829. /*
  830. * We're not calling into it, we can free the module.
  831. *
  832. * FreeLibrary() will be called on this DLL in
  833. * ClientFreeLibrary() when this function returns.
  834. */
  835. hmod = ghmodUserApiHook;
  836. ghmodUserApiHook = NULL;
  837. gpfnInitUserApi = NULL;
  838. } else {
  839. /*
  840. * We're still calling into the module, so we can't free it yet.
  841. * This means we have to delay the last callback with UIAH_UNINITIALIZE
  842. * until we actually free the library. This will occur in
  843. * _EndUserApiHook(). However, we set pfnSignalInitUserApi to initiate
  844. * a callback with UIAH_UNHOOK to alert the module to this fact.
  845. */
  846. hmod = NULL;
  847. pfnInitUserApi = NULL;
  848. pfnSignalInitUserApi = gpfnInitUserApi;
  849. ++gcLoadUserApiHook;
  850. }
  851. } else {
  852. /*
  853. * This part of code should never be executed since we guard against
  854. * multiple loads of same DLL in xxxLoadUserApiHook. However, since
  855. * this is a load count and could conceivably be greater than 1,
  856. * this warning message is inserted to signal such an event.
  857. */
  858. RIPMSG1(RIP_WARNING, " gcLoadUserApiHook: %lx > 1 in Clear Load", gcLoadUserApiHook);
  859. }
  860. }
  861. RtlLeaveCriticalSection(&gcsUserApiHook);
  862. /*
  863. * Signal that hooks have been uninitialized but DLL can't be unloaded due to outstanding calls.
  864. */
  865. if (pfnSignalInitUserApi != NULL) {
  866. RIPMSG2(RIP_WARNING, "Unhook from Clear Load %lx Call %lx", gcLoadUserApiHook, gcCallUserApiHook);
  867. pfnSignalInitUserApi(UIAH_UNHOOK, NULL);
  868. /*
  869. * After having returned from the DLL, we revalidate the state of the hooking world again.
  870. * The outstanding call that we were deferring in favor of, could have completed by now
  871. * and finding the load count greater than zero, it ignored completing the deferred cleanup
  872. * which we must now do at this point.
  873. */
  874. RtlEnterCriticalSection(&gcsUserApiHook);
  875. UserAssert(gcLoadUserApiHook > 0);
  876. UserAssertMsg0(gpfnInitUserApi != NULL, "Ensure gpfnInitUserApi properly set");
  877. UserAssertMsg0(ghmodUserApiHook != NULL, "Should still have valid ghmodUserApiHook");
  878. pfnInitUserApi = gpfnInitUserApi;
  879. if (--gcLoadUserApiHook == 0) {
  880. if (gcCallUserApiHook == 0) {
  881. /*
  882. * The outstanding call has completed while we were
  883. * calling back and we can now safely clean up.
  884. * FreeLibrary() will be called on this DLL in
  885. * ClientFreeLibrary() when this function returns.
  886. */
  887. hmod = ghmodUserApiHook;
  888. ghmodUserApiHook = NULL;
  889. gpfnInitUserApi = NULL;
  890. } else {
  891. /*
  892. * The outstanding call into the DLL hasn't returned. However, we are done
  893. * from this point. The DLL has been notified of UNHOOK situation and the
  894. * rest of the cleanup will be done in _EndUserApiHook when the last call
  895. * into the DLL returns.
  896. */
  897. hmod = NULL;
  898. pfnInitUserApi = NULL;
  899. }
  900. } else {
  901. /*
  902. * This part of code should never be executed since we guard against
  903. * multiple loads of same DLL in xxxLoadUserApiHook. However, since
  904. * this is a load count and could conceivably be greater than 1,
  905. * this warning message is inserted to signal such an event.
  906. */
  907. RIPMSG1(RIP_WARNING, " gcLoadUserApiHook: %lx > 1 in Clear Load", gcLoadUserApiHook);
  908. }
  909. RtlLeaveCriticalSection(&gcsUserApiHook);
  910. }
  911. /*
  912. * This is called in the case where the outstanding call into the DLL was completed in between
  913. * the two critical sections and we have completed the full cleanup at this end.
  914. */
  915. if (pfnInitUserApi != NULL) {
  916. RIPMSG2(RIP_WARNING, "Uninit from Clear Load %lx Call %lx", gcLoadUserApiHook, gcCallUserApiHook);
  917. pfnInitUserApi(UIAH_UNINITIALIZE, NULL);
  918. }
  919. return (hmod != NULL);
  920. }
  921. /***************************************************************************\
  922. * DefaultOWP
  923. *
  924. * This function provides an empty OWP implementation that can be safely
  925. * called while the UserApiHook DLL is being unloaded and we are resetting
  926. * the states.
  927. *
  928. * History:
  929. * 27-Apr-2000 JStall Created.
  930. \***************************************************************************/
  931. BOOL CALLBACK DefaultOWP(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT * pr, void ** pvCookie)
  932. {
  933. UNREFERENCED_PARAMETER(hwnd);
  934. UNREFERENCED_PARAMETER(message);
  935. UNREFERENCED_PARAMETER(wParam);
  936. UNREFERENCED_PARAMETER(lParam);
  937. UNREFERENCED_PARAMETER(pr);
  938. UNREFERENCED_PARAMETER(pvCookie);
  939. return FALSE;
  940. }
  941. /***************************************************************************\
  942. * MDIRedrawFrame
  943. *
  944. *
  945. * History:
  946. * 20-Apr-2001 Mohamed Created.
  947. \***************************************************************************/
  948. void MDIRedrawFrame(
  949. HWND hwndChild,
  950. BOOL fAdd)
  951. {
  952. BEGIN_USERAPIHOOK()
  953. guah.pfnMDIRedrawFrame(hwndChild, fAdd);
  954. END_USERAPIHOOK()
  955. }
  956. void RealMDIRedrawFrame(
  957. HWND hwndChild,
  958. BOOL fAdd)
  959. {
  960. UNREFERENCED_PARAMETER(fAdd);
  961. NtUserRedrawFrame(hwndChild);
  962. }
  963. /***************************************************************************\
  964. * ResetUserApiHook
  965. *
  966. * This function gets called to reset the UserApiHook function pointers to
  967. * the internal (default) implementations of the functions. This is done
  968. * when any installed UserApiHook is being removed by calling
  969. * UnregisterUserApiHook().
  970. *
  971. * History:
  972. * 28-Mar-2000 JStall Created.
  973. * 28-Oct-2000 mohamed Added GetSystemMetrics and SystemParametersInfo hooks.
  974. \***************************************************************************/
  975. void ResetUserApiHook(USERAPIHOOK * puah)
  976. {
  977. puah->cbSize = sizeof(USERAPIHOOK);
  978. puah->pfnDefWindowProcA = RealDefWindowProcA;
  979. puah->pfnDefWindowProcW = RealDefWindowProcW;
  980. puah->mmDWP.rgb = NULL;
  981. puah->mmDWP.cb = 0;
  982. puah->pfnGetScrollInfo = RealGetScrollInfo;
  983. puah->pfnSetScrollInfo = RealSetScrollInfo;
  984. puah->pfnEnableScrollBar = RealEnableScrollBar;
  985. puah->pfnAdjustWindowRectEx = RealAdjustWindowRectEx;
  986. puah->pfnSetWindowRgn = RealSetWindowRgn;
  987. puah->uoiWnd.pfnBeforeOWP = DefaultOWP;
  988. puah->uoiWnd.pfnAfterOWP = DefaultOWP;
  989. puah->uoiWnd.mm.rgb = NULL;
  990. puah->uoiWnd.mm.cb = 0;
  991. puah->uoiDlg.pfnBeforeOWP = DefaultOWP;
  992. puah->uoiDlg.pfnAfterOWP = DefaultOWP;
  993. puah->uoiDlg.mm.rgb = NULL;
  994. puah->uoiDlg.mm.cb = 0;
  995. puah->pfnGetSystemMetrics = RealGetSystemMetrics;
  996. puah->pfnSystemParametersInfoA = RealSystemParametersInfoA;
  997. puah->pfnSystemParametersInfoW = RealSystemParametersInfoW;
  998. puah->pfnForceResetUserApiHook = ForceResetUserApiHook;
  999. puah->pfnDrawFrameControl = RealDrawFrameControl;
  1000. puah->pfnDrawCaption = RealDrawCaption;
  1001. puah->pfnMDIRedrawFrame = RealMDIRedrawFrame;
  1002. }
  1003. /***************************************************************************\
  1004. * ForceResetUserApiHook
  1005. *
  1006. * NOTE : This is an API function that is called by external clients.
  1007. *
  1008. * This function gets called to force a reset of the UserApiHook function
  1009. * pointers. This is done usually by the hooked DLL in the case when it is
  1010. * about to be unloaded by anyone other than WindowManager and is done to
  1011. * prevent future calls into that DLL. It is to be noted however, that
  1012. * WindowManger still believes that it is hooked
  1013. *
  1014. * Note:
  1015. * 1- This function is meant to be called only by hooking dll inside
  1016. * DllMain when recieving a DLL_PROCESS_DETACH message. A check is
  1017. * made on the LoaderLock to verify.
  1018. * 2- No serialization is done based on the assumption that the call
  1019. * is made during DLL_PROCESS_DETACH and hence there is only the
  1020. * main thread.
  1021. *
  1022. * History:
  1023. * 02-Feb-2001 mohamed Created.
  1024. \***************************************************************************/
  1025. BOOL
  1026. ForceResetUserApiHook(
  1027. HMODULE hmod)
  1028. {
  1029. /*
  1030. * Verify that the calling module is indeed the same hooking module and that
  1031. * we are indeed being called from DllMain by verifying that we are inside
  1032. * the loader lock.
  1033. */
  1034. if (ghmodUserApiHook != hmod || !RtlIsThreadWithinLoaderCallout()){
  1035. return FALSE;
  1036. }
  1037. /*
  1038. * Reset the function pointers back to Window Manager native functions and
  1039. * reset the global dll initialization function pointer to prevent calls
  1040. * into hooked dll with un\initialization messages.
  1041. */
  1042. ResetUserApiHook(&guah);
  1043. gpfnInitUserApi = NULL;
  1044. return TRUE;
  1045. }
  1046. /***************************************************************************\
  1047. * _EndUserApiHook
  1048. *
  1049. * This function gets called after each hooked API function call from
  1050. * END_USERAPIHOOK(). This provides a common place to clean up resources
  1051. * that were delayed because they were in use during the hooked function
  1052. * call.
  1053. *
  1054. * History:
  1055. * 28-Mar-2000 JStall Created.
  1056. * 16-May-2000 JStall Changed to support uninitialize callback
  1057. \***************************************************************************/
  1058. void _EndUserApiHook()
  1059. {
  1060. UserAssert(gcCallUserApiHook > 0);
  1061. if (InterlockedDecrement(&gcCallUserApiHook) == 0) {
  1062. /*
  1063. * If the load count went to zero, free the library.
  1064. */
  1065. if (gcLoadUserApiHook == 0) {
  1066. HMODULE hmod = NULL;
  1067. INITUSERAPIHOOK pfnInitUserApi = NULL;
  1068. RtlEnterCriticalSection(&gcsUserApiHook);
  1069. if (gcLoadUserApiHook == 0) {
  1070. UserAssertMsg0(ghmodUserApiHook != NULL, "Should still have valid ghmodUserApiHook");
  1071. UserAssertMsg0(gpfnInitUserApi != NULL, "Should still have valid gpfnInitUserApi");
  1072. hmod = ghmodUserApiHook;
  1073. pfnInitUserApi = gpfnInitUserApi;
  1074. ghmodUserApiHook = NULL;
  1075. gpfnInitUserApi = NULL;
  1076. }
  1077. RtlLeaveCriticalSection(&gcsUserApiHook);
  1078. /*
  1079. * Make the callback that we delayed from ClearUserApiHook()
  1080. * because there was still an outstanding API call.
  1081. */
  1082. if (pfnInitUserApi != NULL) {
  1083. RIPMSG2(RIP_WARNING, "Uninit from End Load %lx Call %lx", gcLoadUserApiHook, gcCallUserApiHook);
  1084. pfnInitUserApi(UIAH_UNINITIALIZE, NULL);
  1085. }
  1086. if (hmod != NULL) {
  1087. FreeLibrary(hmod);
  1088. }
  1089. }
  1090. }
  1091. }
  1092. /***************************************************************************\
  1093. * DefWindowProcWorker
  1094. *
  1095. * Handles any messages that can be dealt with wholly on the client and
  1096. * passes the rest to the server.
  1097. *
  1098. * 03-31-92 DarrinM Created.
  1099. \***************************************************************************/
  1100. LRESULT DefWindowProcWorker(
  1101. PWND pwnd,
  1102. UINT message,
  1103. WPARAM wParam,
  1104. LPARAM lParam,
  1105. DWORD fAnsi)
  1106. {
  1107. if (ghmodUserApiHook) {
  1108. if (fAnsi) {
  1109. return DefWindowProcA(HWq(pwnd), message, wParam, lParam);
  1110. } else {
  1111. return DefWindowProcW(HWq(pwnd), message, wParam, lParam);
  1112. }
  1113. }
  1114. return RealDefWindowProcWorker(pwnd, message, wParam, lParam, fAnsi);
  1115. }
  1116. LRESULT RealDefWindowProcWorker(
  1117. PWND pwnd,
  1118. UINT message,
  1119. WPARAM wParam,
  1120. LPARAM lParam,
  1121. DWORD fAnsi)
  1122. {
  1123. HWND hwnd = HWq(pwnd);
  1124. int icolBack;
  1125. int icolFore;
  1126. PWND pwndParent;
  1127. HWND hwndDefIme;
  1128. PWND pwndDefIme;
  1129. PIMEUI pimeui;
  1130. #if DBG
  1131. if (!gfTurboDWP) {
  1132. return CsSendMessage(hwnd, message, wParam, lParam, 0L,
  1133. FNID_DEFWINDOWPROC, fAnsi);
  1134. } else {
  1135. #endif
  1136. if (FDEFWINDOWMSG(message, DefWindowMsgs)) {
  1137. return CsSendMessage(hwnd, message, wParam, lParam, 0L,
  1138. FNID_DEFWINDOWPROC, fAnsi);
  1139. } else if (!FDEFWINDOWMSG(message, DefWindowSpecMsgs)) {
  1140. return 0;
  1141. }
  1142. /*
  1143. * Important: If you add cases to the switch statement below,
  1144. * add the messages to server.c's gawDefWindowSpecMsgs.
  1145. * Similarly if you add cases to dwp.c's DefWindowProc
  1146. * which can come from the client, add the messages
  1147. * to gawDefWindowMsgs.
  1148. */
  1149. switch (message) {
  1150. #ifdef LAME_BUTTON
  1151. case WM_NCLBUTTONDOWN:
  1152. if (wParam == HTLAMEBUTTON && TestWF(pwnd, WEFLAMEBUTTON)) {
  1153. CallLameButtonHandler(pwnd, hwnd);
  1154. }
  1155. return CsSendMessage(hwnd, message, wParam, lParam, 0L,
  1156. FNID_DEFWINDOWPROC, fAnsi);
  1157. case WM_SYSCHAR:
  1158. if (wParam == LAMEBUTTONHOTKEY && (HIWORD(lParam) & SYS_ALTERNATE) &&
  1159. TestWF(pwnd, WEFLAMEBUTTON)) {
  1160. CallLameButtonHandler(pwnd, hwnd);
  1161. }
  1162. return CsSendMessage(hwnd, message, wParam, lParam, 0L,
  1163. FNID_DEFWINDOWPROC, fAnsi);
  1164. case WM_SYSCOMMAND:
  1165. if (wParam == SC_LAMEBUTTON && TestWF(pwnd, WEFLAMEBUTTON)) {
  1166. CallLameButtonHandler(pwnd, hwnd);
  1167. }
  1168. return CsSendMessage(hwnd, message, wParam, lParam, 0L,
  1169. FNID_DEFWINDOWPROC, fAnsi);
  1170. #endif // LAME_BUTTON
  1171. case WM_HELP:
  1172. {
  1173. PWND pwndDest;
  1174. /*
  1175. * If this window is a child window, Help message must be passed on
  1176. * to it's parent; Else, this must be passed on to the owner window.
  1177. */
  1178. pwndDest = (TestwndChild(pwnd) ? pwnd->spwndParent : pwnd->spwndOwner);
  1179. if (pwndDest) {
  1180. pwndDest = REBASEPTR(pwnd, pwndDest);
  1181. if (pwndDest != _GetDesktopWindow())
  1182. return SendMessageW(HWq(pwndDest), WM_HELP, wParam, lParam);;
  1183. }
  1184. return(0L);
  1185. }
  1186. case WM_MOUSEWHEEL:
  1187. if (TestwndChild(pwnd)) {
  1188. pwndParent = REBASEPWND(pwnd, spwndParent);
  1189. SendMessageW(HW(pwndParent), WM_MOUSEWHEEL, wParam, lParam);
  1190. }
  1191. break;
  1192. case WM_CONTEXTMENU:
  1193. if (TestwndChild(pwnd)) {
  1194. pwndParent = REBASEPWND(pwnd, spwndParent);
  1195. SendMessageW(HW(pwndParent), WM_CONTEXTMENU,
  1196. (WPARAM)hwnd, lParam);
  1197. }
  1198. break;
  1199. /*
  1200. * Default handling for WM_CONTEXTMENU support
  1201. */
  1202. case WM_RBUTTONUP:
  1203. if (TestWF(pwnd, WEFLAYOUTRTL)) {
  1204. lParam = MAKELONG(pwnd->rcClient.right - GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) + pwnd->rcClient.top);
  1205. } else {
  1206. lParam = MAKELONG(GET_X_LPARAM(lParam) + pwnd->rcClient.left, GET_Y_LPARAM(lParam) + pwnd->rcClient.top);
  1207. }
  1208. SendMessageWorker(pwnd, WM_CONTEXTMENU, (WPARAM)hwnd, lParam, fAnsi);
  1209. break;
  1210. case WM_APPCOMMAND:
  1211. if (TestwndChild(pwnd)) {
  1212. /*
  1213. * Bubble the message to the parent
  1214. */
  1215. pwndParent = REBASEPWND(pwnd, spwndParent);
  1216. return SendMessageW(HW(pwndParent), WM_APPCOMMAND, wParam, lParam);
  1217. } else {
  1218. /*
  1219. * Call the server side to send the shell hook HSHELL_APPCOMMAND
  1220. */
  1221. return CsSendMessage(hwnd, WM_APPCOMMAND, wParam, lParam, 0L, FNID_DEFWINDOWPROC, fAnsi);
  1222. }
  1223. break;
  1224. /*
  1225. * Default handling for WM_APPCOMMAND support
  1226. */
  1227. case WM_NCXBUTTONUP:
  1228. case WM_XBUTTONUP:
  1229. {
  1230. WORD cmd;
  1231. WORD keystate;
  1232. LPARAM lParamAppCommand;
  1233. switch (GET_XBUTTON_WPARAM(wParam)) {
  1234. case XBUTTON1:
  1235. cmd = APPCOMMAND_BROWSER_BACKWARD;
  1236. break;
  1237. case XBUTTON2:
  1238. cmd = APPCOMMAND_BROWSER_FORWARD;
  1239. break;
  1240. default:
  1241. cmd = 0;
  1242. break;
  1243. }
  1244. if (cmd == 0) {
  1245. break;
  1246. }
  1247. cmd |= FAPPCOMMAND_MOUSE;
  1248. if (message == WM_XBUTTONUP) {
  1249. keystate = GET_KEYSTATE_WPARAM(wParam);
  1250. } else {
  1251. keystate = GetMouseKeyState();
  1252. }
  1253. lParamAppCommand = MAKELPARAM(keystate, cmd);
  1254. SendMessageWorker(pwnd, WM_APPCOMMAND, (WPARAM)hwnd, lParamAppCommand, fAnsi);
  1255. break;
  1256. }
  1257. case WM_WINDOWPOSCHANGED: {
  1258. PWINDOWPOS ppos = (PWINDOWPOS)lParam;
  1259. if (!(ppos->flags & SWP_NOCLIENTMOVE)) {
  1260. POINT pt = {pwnd->rcClient.left, pwnd->rcClient.top};
  1261. pwndParent = REBASEPWND(pwnd, spwndParent);
  1262. if (pwndParent != _GetDesktopWindow()) {
  1263. pt.x -= pwndParent->rcClient.left;
  1264. pt.y -= pwndParent->rcClient.top;
  1265. }
  1266. SendMessageWorker(pwnd, WM_MOVE, FALSE, MAKELPARAM(pt.x, pt.y), fAnsi);
  1267. }
  1268. if ((ppos->flags & SWP_STATECHANGE) || !(ppos->flags & SWP_NOCLIENTSIZE)) {
  1269. UINT cmd;
  1270. RECT rc;
  1271. if (TestWF(pwnd, WFMINIMIZED))
  1272. cmd = SIZEICONIC;
  1273. else if (TestWF(pwnd, WFMAXIMIZED))
  1274. cmd = SIZEFULLSCREEN;
  1275. else
  1276. cmd = SIZENORMAL;
  1277. /*
  1278. * HACK ALERT:
  1279. * If the window is minimized then the real client width and height are
  1280. * zero. But, in win3.1 they were non-zero. Under Chicago, PrintShop
  1281. * Deluxe ver 1.2 hits a divide by zero. To fix this we fake the width
  1282. * and height for old apps to be non-zero values.
  1283. * GetClientRect does that job for us.
  1284. */
  1285. _GetClientRect(pwnd, &rc);
  1286. SendMessageWorker(pwnd, WM_SIZE, cmd,
  1287. MAKELONG(rc.right - rc.left,
  1288. rc.bottom - rc.top), fAnsi);
  1289. }
  1290. return 0;
  1291. }
  1292. case WM_MOUSEACTIVATE: {
  1293. PWND pwndT;
  1294. LRESULT lt;
  1295. /*
  1296. * GetChildParent returns either a kernel pointer or NULL.
  1297. */
  1298. pwndT = GetChildParent(pwnd);
  1299. if (pwndT != NULL) {
  1300. pwndT = REBASEPTR(pwnd, pwndT);
  1301. lt = SendMessageWorker(pwndT, WM_MOUSEACTIVATE, wParam, lParam, fAnsi);
  1302. if (lt != 0)
  1303. return lt;
  1304. }
  1305. /*
  1306. * Moving, sizing or minimizing? Activate AFTER we take action.
  1307. */
  1308. return ((LOWORD(lParam) == HTCAPTION) && (HIWORD(lParam) == WM_LBUTTONDOWN )) ?
  1309. (LONG)MA_NOACTIVATE : (LONG)MA_ACTIVATE;
  1310. }
  1311. case WM_CTLCOLORSCROLLBAR:
  1312. if ((gpsi->BitCount < 8) ||
  1313. (SYSRGB(3DHILIGHT) != SYSRGB(SCROLLBAR)) ||
  1314. (SYSRGB(3DHILIGHT) == SYSRGB(WINDOW)))
  1315. {
  1316. /*
  1317. * Remove call to UnrealizeObject(). GDI Handles this for
  1318. * brushes on NT.
  1319. *
  1320. * UnrealizeObject(ghbrGray);
  1321. */
  1322. SetBkColor((HDC)wParam, SYSRGB(3DHILIGHT));
  1323. SetTextColor((HDC)wParam, SYSRGB(3DFACE));
  1324. return((LRESULT)gpsi->hbrGray);
  1325. }
  1326. icolBack = COLOR_3DHILIGHT;
  1327. icolFore = COLOR_BTNTEXT;
  1328. goto SetColor;
  1329. case WM_CTLCOLORBTN:
  1330. if (pwnd == NULL)
  1331. goto ColorDefault;
  1332. if (TestWF(pwnd, WFWIN40COMPAT)) {
  1333. icolBack = COLOR_3DFACE;
  1334. icolFore = COLOR_BTNTEXT;
  1335. } else {
  1336. goto ColorDefault;
  1337. }
  1338. goto SetColor;
  1339. case WM_CTLCOLORSTATIC:
  1340. case WM_CTLCOLORDLG:
  1341. case WM_CTLCOLORMSGBOX:
  1342. // We want static controls in dialogs to have the 3D
  1343. // background color, but statics in windows to inherit
  1344. // their parents' background.
  1345. if (pwnd == NULL)
  1346. goto ColorDefault;
  1347. if (TestWF(pwnd, WFWIN40COMPAT)) {
  1348. icolBack = COLOR_3DFACE;
  1349. icolFore = COLOR_WINDOWTEXT;
  1350. goto SetColor;
  1351. }
  1352. // ELSE FALL THRU...
  1353. case WM_CTLCOLOR: // here for WOW only
  1354. case WM_CTLCOLORLISTBOX:
  1355. case WM_CTLCOLOREDIT:
  1356. ColorDefault:
  1357. icolBack = COLOR_WINDOW;
  1358. icolFore = COLOR_WINDOWTEXT;
  1359. SetColor:
  1360. {
  1361. SetBkColor((HDC)wParam, gpsi->argbSystem[icolBack]);
  1362. SetTextColor((HDC)wParam, gpsi->argbSystem[icolFore]);
  1363. return (LRESULT)(SYSHBRUSH(icolBack));
  1364. }
  1365. case WM_NCHITTEST:
  1366. return FindNCHit(pwnd, (LONG)lParam);
  1367. case WM_GETTEXT:
  1368. if (wParam != 0) {
  1369. LPWSTR lpszText;
  1370. UINT cchSrc;
  1371. if (pwnd->strName.Length) {
  1372. lpszText = REBASE(pwnd, strName.Buffer);
  1373. cchSrc = (UINT)pwnd->strName.Length / sizeof(WCHAR);
  1374. if (fAnsi) {
  1375. LPSTR lpName = (LPSTR)lParam;
  1376. /*
  1377. * Non-zero retval means some text to copy out. Do not
  1378. * copy out more than the requested byte count
  1379. * 'chMaxCount'.
  1380. */
  1381. cchSrc = WCSToMB(lpszText,
  1382. cchSrc,
  1383. (LPSTR *)&lpName,
  1384. (UINT)(wParam - 1),
  1385. FALSE);
  1386. lpName[cchSrc] = '\0';
  1387. } else {
  1388. LPWSTR lpwName = (LPWSTR)lParam;
  1389. cchSrc = min(cchSrc, (UINT)(wParam - 1));
  1390. RtlCopyMemory(lpwName, lpszText, cchSrc * sizeof(WCHAR));
  1391. lpwName[cchSrc] = 0;
  1392. }
  1393. return cchSrc;
  1394. }
  1395. /*
  1396. * else Null terminate the text buffer since there is no text.
  1397. */
  1398. if (fAnsi) {
  1399. ((LPSTR)lParam)[0] = 0;
  1400. } else {
  1401. ((LPWSTR)lParam)[0] = 0;
  1402. }
  1403. }
  1404. return 0;
  1405. case WM_GETTEXTLENGTH:
  1406. if (pwnd->strName.Length) {
  1407. UINT cch;
  1408. if (fAnsi) {
  1409. RtlUnicodeToMultiByteSize(&cch,
  1410. REBASE(pwnd, strName.Buffer),
  1411. pwnd->strName.Length);
  1412. } else {
  1413. cch = pwnd->strName.Length / sizeof(WCHAR);
  1414. }
  1415. return cch;
  1416. }
  1417. return 0L;
  1418. case WM_QUERYDRAGICON:
  1419. /*
  1420. * If the window is WIN40COMPAT or has a kernel side procedure
  1421. * do not attempt to look into the instance module
  1422. */
  1423. if (TestWF(pwnd, WFWIN40COMPAT) || TestWF(pwnd, WFSERVERSIDEPROC)) {
  1424. return 0;
  1425. }
  1426. /*
  1427. * For old apps, like the VB3 ones, try to load the icon from resources
  1428. * This is how Win95 does.
  1429. */
  1430. return (LRESULT)LoadIconW(KHANDLE_TO_HANDLE(pwnd->hModule), MAKEINTRESOURCE(1));
  1431. case WM_QUERYOPEN:
  1432. case WM_QUERYENDSESSION:
  1433. case WM_DEVICECHANGE:
  1434. case WM_POWERBROADCAST:
  1435. return TRUE;
  1436. case WM_KEYDOWN:
  1437. if (wParam == VK_F10) {
  1438. return CsSendMessage(hwnd, message, wParam, lParam, 0L,
  1439. FNID_DEFWINDOWPROC, fAnsi);
  1440. }
  1441. break;
  1442. case WM_SYSKEYDOWN:
  1443. if ((HIWORD(lParam) & SYS_ALTERNATE) || (wParam == VK_F10) ||
  1444. (wParam == VK_ESCAPE))
  1445. return CsSendMessage(hwnd, message, wParam, lParam, 0L,
  1446. FNID_DEFWINDOWPROC, fAnsi);
  1447. break;
  1448. case WM_UNICHAR:
  1449. if (wParam == UNICODE_NOCHAR) {
  1450. return FALSE;
  1451. }
  1452. break;
  1453. case WM_CHARTOITEM:
  1454. case WM_VKEYTOITEM:
  1455. /*
  1456. * Do default processing for keystrokes into owner draw listboxes.
  1457. */
  1458. return -1;
  1459. case WM_ACTIVATE:
  1460. if (LOWORD(wParam))
  1461. return CsSendMessage(hwnd, message, wParam, lParam, 0L,
  1462. FNID_DEFWINDOWPROC, fAnsi);
  1463. break;
  1464. case WM_SHOWWINDOW:
  1465. if (lParam != 0)
  1466. return CsSendMessage(hwnd, message, wParam, lParam, 0L,
  1467. FNID_DEFWINDOWPROC, fAnsi);
  1468. break;
  1469. case WM_DROPOBJECT:
  1470. return DO_DROPFILE;
  1471. case WM_WINDOWPOSCHANGING:
  1472. /*
  1473. * If the window's size is changing, adjust the passed-in size
  1474. */
  1475. #define ppos ((WINDOWPOS *)lParam)
  1476. if (!(ppos->flags & SWP_NOSIZE))
  1477. return CsSendMessage(hwnd, message, wParam, lParam, 0L,
  1478. FNID_DEFWINDOWPROC, fAnsi);
  1479. #undef ppos
  1480. break;
  1481. case WM_KLUDGEMINRECT:
  1482. {
  1483. SHELLHOOKINFO shi;
  1484. LPRECT lprc = (LPRECT)lParam;
  1485. shi.hwnd = (HWND)wParam;
  1486. shi.rc.left = MAKELONG(lprc->left, lprc->top);
  1487. shi.rc.top = MAKELONG(lprc->right, lprc->bottom);
  1488. if (gpsi->uiShellMsg == 0)
  1489. SetTaskmanWindow(NULL);
  1490. if (SendMessageWorker(pwnd, gpsi->uiShellMsg, HSHELL_GETMINRECT,
  1491. (LPARAM)&shi, fAnsi)) {
  1492. //
  1493. // Now convert the RECT back from two POINTS structures into two POINT
  1494. // structures.
  1495. //
  1496. lprc->left = (SHORT)LOWORD(shi.rc.left); // Sign extend
  1497. lprc->top = (SHORT)HIWORD(shi.rc.left); // Sign extend
  1498. lprc->right = (SHORT)LOWORD(shi.rc.top); // Sign extend
  1499. lprc->bottom = (SHORT)HIWORD(shi.rc.top); // Sign extend
  1500. }
  1501. break;
  1502. }
  1503. case WM_NOTIFYFORMAT:
  1504. if (lParam == NF_QUERY)
  1505. return(TestWF(pwnd, WFANSICREATOR) ? NFR_ANSI : NFR_UNICODE);
  1506. break;
  1507. case WM_IME_KEYDOWN:
  1508. if (fAnsi)
  1509. PostMessageA(hwnd, WM_KEYDOWN, wParam, lParam);
  1510. else
  1511. PostMessageW(hwnd, WM_KEYDOWN, wParam, lParam);
  1512. break;
  1513. case WM_IME_KEYUP:
  1514. if (fAnsi)
  1515. PostMessageA(hwnd, WM_KEYUP, wParam, lParam);
  1516. else
  1517. PostMessageW(hwnd, WM_KEYUP, wParam, lParam);
  1518. break;
  1519. case WM_IME_CHAR:
  1520. //if (TestCF(pwnd, CFIME))
  1521. // break;
  1522. if ( fAnsi ) {
  1523. if( IsDBCSLeadByteEx(THREAD_CODEPAGE(),(BYTE)(wParam >> 8)) ) {
  1524. PostMessageA(hwnd,
  1525. WM_CHAR,
  1526. (WPARAM)((BYTE)(wParam >> 8)), // leading byte
  1527. 1L);
  1528. PostMessageA(hwnd,
  1529. WM_CHAR,
  1530. (WPARAM)((BYTE)wParam), // trailing byte
  1531. 1L);
  1532. }
  1533. else
  1534. PostMessageA(hwnd,
  1535. WM_CHAR,
  1536. (WPARAM)(wParam),
  1537. 1L);
  1538. } else {
  1539. PostMessageW(hwnd, WM_CHAR, wParam, 1L);
  1540. }
  1541. break;
  1542. case WM_IME_COMPOSITION:
  1543. //if (TestCF(pwnd, CFIME))
  1544. // break;
  1545. if (lParam & GCS_RESULTSTR) {
  1546. HIMC hImc;
  1547. DWORD cbLen;
  1548. if ((hImc = fpImmGetContext(hwnd)) == NULL_HIMC)
  1549. goto dwpime_ToIMEWnd_withchk;
  1550. if (fAnsi) {
  1551. LPSTR pszBuffer, psz;
  1552. /*
  1553. * ImmGetComposition returns the size of buffer needed in byte.
  1554. */
  1555. if (!(cbLen = fpImmGetCompositionStringA(hImc, GCS_RESULTSTR, NULL, 0))) {
  1556. fpImmReleaseContext(hwnd, hImc);
  1557. goto dwpime_ToIMEWnd_withchk;
  1558. }
  1559. pszBuffer = psz = (LPSTR)UserLocalAlloc(HEAP_ZERO_MEMORY,
  1560. cbLen + sizeof(CHAR));
  1561. if (pszBuffer == NULL) {
  1562. fpImmReleaseContext(hwnd, hImc);
  1563. goto dwpime_ToIMEWnd_withchk;
  1564. }
  1565. fpImmGetCompositionStringA(hImc, GCS_RESULTSTR, psz, cbLen);
  1566. while (*psz) {
  1567. if (IsDBCSLeadByteEx(THREAD_CODEPAGE(),*psz)) {
  1568. if (*(psz+1)) {
  1569. SendMessageA( hwnd,
  1570. WM_IME_CHAR,
  1571. MAKEWPARAM(MAKEWORD(*(psz+1), *psz), 0),
  1572. 1L );
  1573. psz++;
  1574. }
  1575. psz++;
  1576. }
  1577. else
  1578. SendMessageA( hwnd,
  1579. WM_IME_CHAR,
  1580. MAKEWPARAM(MAKEWORD(*(psz++), 0), 0),
  1581. 1L );
  1582. }
  1583. UserLocalFree(pszBuffer);
  1584. fpImmReleaseContext(hwnd, hImc);
  1585. }
  1586. else {
  1587. LPWSTR pwszBuffer, pwsz;
  1588. /*
  1589. * ImmGetComposition returns the size of buffer needed in byte
  1590. */
  1591. if (!(cbLen = fpImmGetCompositionStringW(hImc, GCS_RESULTSTR, NULL, 0))) {
  1592. fpImmReleaseContext(hwnd, hImc);
  1593. goto dwpime_ToIMEWnd_withchk;
  1594. }
  1595. pwszBuffer = pwsz = (LPWSTR)UserLocalAlloc(HEAP_ZERO_MEMORY,
  1596. cbLen + sizeof(WCHAR));
  1597. if (pwszBuffer == NULL) {
  1598. fpImmReleaseContext(hwnd, hImc);
  1599. goto dwpime_ToIMEWnd_withchk;
  1600. }
  1601. fpImmGetCompositionStringW(hImc, GCS_RESULTSTR, pwsz, cbLen);
  1602. while (*pwsz)
  1603. SendMessageW(hwnd, WM_IME_CHAR, MAKEWPARAM(*pwsz++, 0), 1L);
  1604. UserLocalFree(pwszBuffer);
  1605. fpImmReleaseContext(hwnd, hImc);
  1606. }
  1607. }
  1608. /*
  1609. * Fall through to send to Default IME Window with checking
  1610. * activated hIMC.
  1611. */
  1612. case WM_IME_STARTCOMPOSITION:
  1613. case WM_IME_ENDCOMPOSITION:
  1614. dwpime_ToIMEWnd_withchk:
  1615. //if (TestCF(pwnd, CFIME))
  1616. // break;
  1617. if (GetClientInfo()->dwTIFlags & TIF_DISABLEIME) {
  1618. break;
  1619. }
  1620. /*
  1621. * We assume this Wnd uses DefaultIMEWindow.
  1622. * If this window has its own IME window, it have to call
  1623. * ImmIsUIMessage()....
  1624. */
  1625. hwndDefIme = fpImmGetDefaultIMEWnd(hwnd);
  1626. if (hwndDefIme == hwnd) {
  1627. /*
  1628. * VC++ 1.51 TLW0NCL.DLL subclass IME class window
  1629. * and pass IME messages to DefWindowProc().
  1630. */
  1631. RIPMSG1(RIP_WARNING,
  1632. "IME Class window is hooked and IME message [%X] are sent to DefWindowProc",
  1633. message);
  1634. ImeWndProcWorker(pwnd, message, wParam, lParam, fAnsi);
  1635. break;
  1636. }
  1637. if ((pwndDefIme = ValidateHwndNoRip(hwndDefIme)) != NULL) {
  1638. /*
  1639. * If hImc of this window is not activated for IME window,
  1640. * we don't send WM_IME_NOTIFY.
  1641. */
  1642. pimeui = ((PIMEWND)pwndDefIme)->pimeui;
  1643. if (pimeui->hIMC == fpImmGetContext(hwnd))
  1644. return SendMessageWorker(pwndDefIme, message, wParam, lParam, fAnsi);
  1645. else
  1646. RIPMSG1(RIP_WARNING,
  1647. "DefWindowProc can not send WM_IME_message [%X] now",
  1648. message);
  1649. }
  1650. break;
  1651. dwpime_ToTopLevel_withchk:
  1652. //if (TestCF(pwnd, CFIME))
  1653. // break;
  1654. /*
  1655. * We assume this Wnd uses DefaultIMEWindow.
  1656. * If this window has its own IME window, it have to call
  1657. * ImmIsUIMessage()....
  1658. */
  1659. hwndDefIme = fpImmGetDefaultIMEWnd(hwnd);
  1660. if (hwndDefIme == hwnd) {
  1661. /*
  1662. * VC++ 1.51 TLW0NCL.DLL subclass IME class window
  1663. * and pass IME messages to DefWindowProc().
  1664. */
  1665. RIPMSG1(RIP_WARNING,
  1666. "IME Class window is hooked and IME message [%X] are sent to DefWindowProc",
  1667. message);
  1668. ImeWndProcWorker(pwnd, message, wParam, lParam, fAnsi);
  1669. break;
  1670. }
  1671. pwndDefIme = ValidateHwndNoRip(hwndDefIme);
  1672. if ((pwndDefIme = ValidateHwndNoRip(hwndDefIme)) != NULL) {
  1673. PWND pwndT, pwndParent;
  1674. pwndT = pwnd;
  1675. while (TestwndChild(pwndT)) {
  1676. pwndParent = REBASEPWND(pwndT, spwndParent);
  1677. if (GETPTI(pwndParent) != GETPTI(pwnd))
  1678. break;
  1679. pwndT = pwndParent;
  1680. }
  1681. /*
  1682. * If hImc of this window is not activated for IME window,
  1683. * we don't send WM_IME_NOTIFY.
  1684. */
  1685. if (pwndT != pwnd) {
  1686. pimeui = ((PIMEWND)pwndDefIme)->pimeui;
  1687. if (pimeui->hIMC == fpImmGetContext(hwnd))
  1688. return SendMessageWorker(pwndT, message, wParam, lParam, fAnsi);
  1689. else
  1690. RIPMSG1(RIP_WARNING,
  1691. "DefWindowProc can not send WM_IME_message [%X] now",
  1692. message);
  1693. }
  1694. else {
  1695. /*
  1696. * Review !!
  1697. * If this is the toplevel window, we pass messages to
  1698. * the default IME window...
  1699. */
  1700. return SendMessageWorker(pwndDefIme, message, wParam, lParam, fAnsi);
  1701. }
  1702. }
  1703. break;
  1704. case WM_IME_NOTIFY:
  1705. switch (wParam) {
  1706. case IMN_OPENSTATUSWINDOW:
  1707. case IMN_CLOSESTATUSWINDOW:
  1708. #ifndef WKWOK_DEBUG
  1709. goto dwpime_ToIMEWnd_withchk;
  1710. #endif
  1711. goto dwpime_ToTopLevel_withchk;
  1712. default:
  1713. goto dwpime_ToIMEWnd_withchk;
  1714. }
  1715. break;
  1716. case WM_IME_REQUEST:
  1717. switch (wParam) {
  1718. case IMR_QUERYCHARPOSITION:
  1719. goto dwpime_ToIMEWnd_withchk;
  1720. default:
  1721. break;
  1722. }
  1723. break;
  1724. case WM_IME_SYSTEM:
  1725. if (wParam == IMS_SETACTIVECONTEXT) {
  1726. RIPMSG0(RIP_WARNING, "DefWindowProc received unexpected WM_IME_SYSTEM");
  1727. break;
  1728. }
  1729. /*
  1730. * IMS_SETOPENSTATUS is depended on the activated input context.
  1731. * It needs to be sent to only the activated system window.
  1732. */
  1733. if (wParam == IMS_SETOPENSTATUS)
  1734. goto dwpime_ToIMEWnd_withchk;
  1735. /*
  1736. * Fall through to send to Default IME Window.
  1737. */
  1738. case WM_IME_SETCONTEXT:
  1739. //if (TestCF(pwnd, CFIME))
  1740. // break;
  1741. hwndDefIme = fpImmGetDefaultIMEWnd(hwnd);
  1742. if (hwndDefIme == hwnd) {
  1743. /*
  1744. * VC++ 1.51 TLW0NCL.DLL subclass IME class window
  1745. * and pass IME messages to DefWindowProc().
  1746. */
  1747. RIPMSG1(RIP_WARNING,
  1748. "IME Class window is hooked and IME message [%X] are sent to DefWindowProc",
  1749. message);
  1750. ImeWndProcWorker(pwnd, message, wParam, lParam, fAnsi);
  1751. break;
  1752. }
  1753. if ((pwndDefIme = ValidateHwndNoRip(hwndDefIme)) != NULL)
  1754. return SendMessageWorker(pwndDefIme, message, wParam, lParam, fAnsi);
  1755. break;
  1756. case WM_IME_SELECT:
  1757. RIPMSG0(RIP_WARNING, "DefWindowProc should not receive WM_IME_SELECT");
  1758. break;
  1759. case WM_IME_COMPOSITIONFULL:
  1760. //if (TestCF(pwnd, CFIME))
  1761. // break;
  1762. if (GETAPPVER() < VER40) {
  1763. /*
  1764. * This is a temporary solution for win31app.
  1765. * FEREVIEW: For M5 this will call WINNLS message mapping logic
  1766. * -yutakan
  1767. */
  1768. return SendMessageWorker(pwnd, WM_IME_REPORT,
  1769. IR_FULLCONVERT, (LPARAM)0L, fAnsi);
  1770. }
  1771. break;
  1772. case WM_CHANGEUISTATE:
  1773. {
  1774. WORD wAction = LOWORD(wParam);
  1775. WORD wFlags = HIWORD(wParam);
  1776. BOOL bRealChange = FALSE;
  1777. /*
  1778. * Validate parameters and determine the flags that should actually be changed.
  1779. */
  1780. if ((wFlags & ~UISF_VALID) || (wAction > UIS_LASTVALID) || lParam) {
  1781. return 0;
  1782. }
  1783. if (wAction == UIS_INITIALIZE) {
  1784. wFlags = 0;
  1785. if (TEST_KbdCuesPUSIF) {
  1786. if (TEST_SRVIF(SRVIF_LASTRITWASKEYBOARD)) {
  1787. wAction = UIS_CLEAR;
  1788. } else {
  1789. wAction = UIS_SET;
  1790. }
  1791. wFlags = UISF_HIDEFOCUS | UISF_HIDEACCEL;
  1792. wParam = MAKEWPARAM(wAction, wFlags);
  1793. }
  1794. } else if (!TEST_KbdCuesPUSIF) {
  1795. wFlags &= ~(UISF_HIDEFOCUS | UISF_HIDEACCEL);
  1796. }
  1797. if (wFlags == 0) {
  1798. return 0;
  1799. }
  1800. UserAssert(wAction == UIS_SET || wAction == UIS_CLEAR);
  1801. /*
  1802. * If the state is not going to change, there's nothing to do here
  1803. */
  1804. if (wFlags & UISF_HIDEFOCUS) {
  1805. bRealChange = (!!TestWF(pwnd, WEFPUIFOCUSHIDDEN)) ^ (wAction == UIS_SET);
  1806. }
  1807. if (wFlags & UISF_HIDEACCEL) {
  1808. bRealChange |= (!!TestWF(pwnd, WEFPUIACCELHIDDEN)) ^ (wAction == UIS_SET);
  1809. }
  1810. if (wFlags & UISF_ACTIVE) {
  1811. bRealChange |= (!!TestWF(pwnd, WEFPUIACTIVE)) ^ (wAction == UIS_SET);
  1812. }
  1813. if (!bRealChange) {
  1814. break;
  1815. }
  1816. /*
  1817. * Children pass this message up
  1818. * Top level windows update send down to themselves WM_UPDATEUISTATE.
  1819. * WM_UPDATEUISTATE will change the state bits and broadcast down the message
  1820. */
  1821. if (TestwndChild(pwnd)) {
  1822. return SendMessageWorker(REBASEPWND(pwnd, spwndParent), WM_CHANGEUISTATE,
  1823. wParam, lParam, fAnsi);
  1824. } else {
  1825. return SendMessageWorker(pwnd, WM_UPDATEUISTATE, wParam, lParam, fAnsi);
  1826. }
  1827. }
  1828. break;
  1829. case WM_QUERYUISTATE:
  1830. return (TestWF(pwnd, WEFPUIFOCUSHIDDEN) ? UISF_HIDEFOCUS : 0) |
  1831. (TestWF(pwnd, WEFPUIACCELHIDDEN) ? UISF_HIDEACCEL : 0) |
  1832. (TestWF(pwnd, WEFPUIACTIVE) ? UISF_ACTIVE : 0);
  1833. break;
  1834. }
  1835. return 0;
  1836. #if DBG
  1837. } // gfTurboDWP
  1838. #endif
  1839. }
  1840. /***************************************************************************\
  1841. * CallWindowProc
  1842. *
  1843. * Calls pfn with the passed message parameters. If pfn is a server-side
  1844. * window proc the server is called to deliver the message to the window.
  1845. * Currently we have the following restrictions:
  1846. *
  1847. * 04-17-91 DarrinM Created.
  1848. \***************************************************************************/
  1849. LRESULT WINAPI CallWindowProcAorW(
  1850. WNDPROC pfn,
  1851. HWND hwnd,
  1852. UINT message,
  1853. WPARAM wParam,
  1854. LPARAM lParam,
  1855. BOOL bAnsi) // Denotes if input is Ansi or Unicode
  1856. {
  1857. PCALLPROCDATA pCPD;
  1858. PWND pwnd;
  1859. /*
  1860. * Raid# 78954: SPY++
  1861. *
  1862. * Under FE NT4.0 or NT5.0, the sytem sends WM_GETTEXTLENGTH
  1863. * corresponding to WM_xxxGETTEXT to optimize buffer allocation.
  1864. * This is really needed to avoid the buffer size inflation.
  1865. * For some reasons, Spy++ passes NULL as pfn to CallWindowProc
  1866. *
  1867. */
  1868. if (pfn == NULL) {
  1869. RIPMSG0(RIP_WARNING, "CallWidowProcAorW(): pfn == NULL!");
  1870. return 0L;
  1871. }
  1872. // OPT!! check an ANSI\UNICODE table rather than fnDWORD
  1873. // OPT!! convert WM_CHAR family messages in line
  1874. /*
  1875. * Check if pfn is really a CallProcData Handle
  1876. * if it is and there is no ANSI data then convert the handle
  1877. * into an address; otherwise call the server for translation
  1878. */
  1879. if (ISCPDTAG(pfn)) {
  1880. if (pCPD = HMValidateHandleNoRip((HANDLE)pfn, TYPE_CALLPROC)) {
  1881. if ((message >= WM_USER) || !MessageTable[message].bThunkMessage) {
  1882. pfn = (WNDPROC)pCPD->pfnClientPrevious;
  1883. } else {
  1884. return CsSendMessage(hwnd, message, wParam, lParam, (ULONG_PTR)pfn,
  1885. FNID_CALLWINDOWPROC, bAnsi);
  1886. }
  1887. } else {
  1888. RIPMSG1(RIP_WARNING, "CallWindowProc tried using a deleted CPD %#p\n", pfn);
  1889. return 0;
  1890. }
  1891. }
  1892. pwnd = ValidateHwnd(hwnd);
  1893. return UserCallWinProcCheckWow(PACTCTXT(pwnd), pfn, hwnd, message, wParam, lParam, NULL, FALSE);
  1894. }
  1895. FUNCLOG5(LOG_GENERAL, LRESULT, WINAPI, CallWindowProcA, WNDPROC, pfn, HWND, hwnd, UINT, message, WPARAM, wParam, LPARAM, lParam)
  1896. LRESULT WINAPI CallWindowProcA(
  1897. WNDPROC pfn,
  1898. HWND hwnd,
  1899. UINT message,
  1900. WPARAM wParam,
  1901. LPARAM lParam)
  1902. {
  1903. return CallWindowProcAorW(pfn, hwnd, message, wParam, lParam, TRUE);
  1904. }
  1905. FUNCLOG5(LOG_GENERAL, LRESULT, WINAPI, CallWindowProcW, WNDPROC, pfn, HWND, hwnd, UINT, message, WPARAM, wParam, LPARAM, lParam)
  1906. LRESULT WINAPI CallWindowProcW(
  1907. WNDPROC pfn,
  1908. HWND hwnd,
  1909. UINT message,
  1910. WPARAM wParam,
  1911. LPARAM lParam)
  1912. {
  1913. return CallWindowProcAorW(pfn, hwnd, message, wParam, lParam, FALSE);
  1914. }
  1915. /***************************************************************************\
  1916. * MenuWindowProc
  1917. *
  1918. * Calls the sever-side function xxxMenuWindowProc
  1919. *
  1920. * 07-27-92 Mikehar Created.
  1921. \***************************************************************************/
  1922. FUNCLOG5(LOG_GENERAL, LRESULT, WINAPI, MenuWindowProcW, HWND, hwnd, HWND, hwndMDIClient, UINT, message, WPARAM, wParam, LPARAM, lParam)
  1923. LRESULT WINAPI MenuWindowProcW(
  1924. HWND hwnd,
  1925. HWND hwndMDIClient,
  1926. UINT message,
  1927. WPARAM wParam,
  1928. LPARAM lParam)
  1929. {
  1930. return CsSendMessage(hwnd, message, wParam, lParam,
  1931. (ULONG_PTR)hwndMDIClient, FNID_MENU, FALSE);
  1932. }
  1933. FUNCLOG5(LOG_GENERAL, LRESULT, WINAPI, MenuWindowProcA, HWND, hwnd, HWND, hwndMDIClient, UINT, message, WPARAM, wParam, LPARAM, lParam)
  1934. LRESULT WINAPI MenuWindowProcA(
  1935. HWND hwnd,
  1936. HWND hwndMDIClient,
  1937. UINT message,
  1938. WPARAM wParam,
  1939. LPARAM lParam)
  1940. {
  1941. return CsSendMessage(hwnd, message, wParam, lParam,
  1942. (ULONG_PTR)hwndMDIClient, FNID_MENU, TRUE);
  1943. }
  1944. /***************************************************************************\
  1945. * _ClientGetListboxString
  1946. *
  1947. * This special function exists because LB_GETTEXT and CB_GETLBTEXT don't have
  1948. * buffer counts in them anywhere. Because there is no buffer count we have
  1949. * no idea how much room to reserved in the shared memory stack for this
  1950. * string to be copied into. The solution is to get the string length ahead
  1951. * of time, and send the message with this buffer length. Since this buffer
  1952. * length isn't a part of the original message, this routine is used for
  1953. * just this purpose.
  1954. *
  1955. * This routine gets called from the server.
  1956. *
  1957. * 04-13-91 ScottLu Created.
  1958. \***************************************************************************/
  1959. DWORD WINAPI _ClientGetListboxString(
  1960. PWND pwnd,
  1961. UINT msg,
  1962. WPARAM wParam,
  1963. LPSTR lParam, // May be a unicode or ANSI string
  1964. ULONG_PTR xParam,
  1965. PROC xpfn)
  1966. {
  1967. return ((DWORD)((GENERICPROC)xpfn)(pwnd, msg, wParam, (LPARAM)lParam, xParam));
  1968. }
  1969. /***************************************************************************\
  1970. * DispatchMessageWorker
  1971. *
  1972. * Handles any messages that can be dealt with wholly on the client and
  1973. * passes the rest to the server.
  1974. *
  1975. * 04-24-92 DarrinM Created.
  1976. \***************************************************************************/
  1977. LRESULT DispatchMessageWorker(
  1978. MSG *pmsg,
  1979. BOOL fAnsi)
  1980. {
  1981. PWND pwnd;
  1982. WPARAM wParamSaved;
  1983. LRESULT lRet;
  1984. BOOL bDoDbcsMessaging = FALSE;
  1985. /*
  1986. * Prevent apps from setting hi 16 bits so we can use them internally.
  1987. */
  1988. if (pmsg->message & RESERVED_MSG_BITS) {
  1989. RIPERR1(ERROR_INVALID_PARAMETER,
  1990. RIP_WARNING,
  1991. "Invalid parameter \"pmsg->message\" (%ld) to DispatchMessageWorker",
  1992. pmsg->message);
  1993. return 0;
  1994. }
  1995. if (pmsg->hwnd != NULL) {
  1996. pwnd = ValidateHwnd(pmsg->hwnd);
  1997. if (pwnd == NULL) {
  1998. return 0;
  1999. }
  2000. pmsg->hwnd = HWq(pwnd); // get full 32-bit HWND in case this came from WoW
  2001. } else {
  2002. pwnd = NULL;
  2003. }
  2004. /*
  2005. * If this is a synchronous-only message (takes a pointer in wParam or
  2006. * lParam), then don't allow this message to go through since those
  2007. * parameters have not been thunked, and are pointing into outer-space
  2008. * (which would case exceptions to occur).
  2009. *
  2010. * (This api is only called in the context of a message loop, and you
  2011. * don't get synchronous-only messages in a message loop).
  2012. */
  2013. if (TESTSYNCONLYMESSAGE(pmsg->message, pmsg->wParam)) {
  2014. /*
  2015. * Fail if 32 bit app is calling.
  2016. */
  2017. if (!(GetClientInfo()->dwTIFlags & TIF_16BIT)) {
  2018. RIPERR0(ERROR_MESSAGE_SYNC_ONLY, RIP_WARNING, "DispatchMessageWorker: must be sync only");
  2019. return FALSE;
  2020. }
  2021. /*
  2022. * For wow apps, allow it to go through (for compatibility). Change
  2023. * the message id so our code doesn't understand the message - wow
  2024. * will get the message and strip out this bit before dispatching
  2025. * the message to the application.
  2026. */
  2027. pmsg->message |= MSGFLAG_WOW_RESERVED;
  2028. }
  2029. /*
  2030. * Timer callbacks that don't go through window procs are sent with
  2031. * the callback address in lParam. Identify and dispatch those timers.
  2032. */
  2033. if ((pmsg->message == WM_TIMER) || (pmsg->message == WM_SYSTIMER)) {
  2034. /*
  2035. * Console windows use WM_TIMER for the caret. However, they don't
  2036. * use a timer callback, so if this is CSRSS and there's a WM_TIMER
  2037. * for us, the only way lParam would be non-zero is if someone's trying
  2038. * to make us fault. No, this isn't a nice thing to do, but there
  2039. * are bad, bad people out there. Windows Bug #361246.
  2040. */
  2041. if (pmsg->lParam != 0) {
  2042. /*
  2043. * System timers must be executed on the server's context.
  2044. */
  2045. if (pmsg->message == WM_SYSTIMER) {
  2046. return NtUserDispatchMessage(pmsg);
  2047. } else if (!gfServerProcess) {
  2048. /*
  2049. * WM_TIMER with lParam could be an attack from
  2050. * malicious apps. To make sure the call is legitimate,
  2051. * let the kernel side validates it.
  2052. */
  2053. if (!NtUserValidateTimerCallback(pmsg->lParam)) {
  2054. RIPMSGF3(RIP_WARNING, "invalid timer: hwnd=%p, wParam=%p, lParam=%p", pmsg->hwnd, pmsg->wParam, pmsg->lParam);
  2055. return 0;
  2056. }
  2057. /*
  2058. * We can't really trust what's in lParam, so make sure we
  2059. * handle any exceptions that occur during this call.
  2060. */
  2061. try {
  2062. /*
  2063. * Windows NT Bug #234292.
  2064. * Since the called window/dialog proc may have a different
  2065. * calling convention, we must wrap the call and, check esp
  2066. * and replace with a good esp when the call returns. This
  2067. * is what UserCallWinProc* does.
  2068. */
  2069. lRet = UserCallWinProc(PACTCTXT(pwnd),
  2070. (WNDPROC)pmsg->lParam,
  2071. pmsg->hwnd,
  2072. pmsg->message,
  2073. pmsg->wParam,
  2074. NtGetTickCount());
  2075. } except ((GetAppCompatFlags2(VER40) & GACF2_NO_TRYEXCEPT_CALLWNDPROC) ?
  2076. EXCEPTION_CONTINUE_SEARCH : W32ExceptionHandler(FALSE, RIP_WARNING)) {
  2077. /*
  2078. * Windows NT Bug #359866.
  2079. * Some applications like Hagaki Studio 2000 need to handle
  2080. * the exception in WndProc in their handler, even though it
  2081. * skips the API calls. For those apps, we have to honor the
  2082. * behavior of NT4, with no protection.
  2083. */
  2084. lRet = 0;
  2085. }
  2086. return lRet;
  2087. }
  2088. }
  2089. }
  2090. if (pwnd == NULL) {
  2091. return 0;
  2092. }
  2093. /*
  2094. * To be safe (in case some bizarre app wants to look at the message
  2095. * again after dispatching it) save wParam so it can be restored after
  2096. * RtlMBMessageWParamCharToWCS() or RtlWCSMessageToMB() mangle it.
  2097. */
  2098. wParamSaved = pmsg->wParam;
  2099. /*
  2100. * Pass messages intended for server-side windows over to the server.
  2101. * WM_PAINTs are passed over so the WFPAINTNOTPROCESSED code can be
  2102. * executed.
  2103. */
  2104. if (TestWF(pwnd, WFSERVERSIDEPROC) || (pmsg->message == WM_PAINT)) {
  2105. if (fAnsi) {
  2106. /*
  2107. * Setup DBCS Messaging for WM_CHAR...
  2108. */
  2109. BUILD_DBCS_MESSAGE_TO_SERVER_FROM_CLIENTA(pmsg->message,pmsg->wParam,TRUE);
  2110. /*
  2111. * Convert wParam to Unicode, if nessesary.
  2112. */
  2113. RtlMBMessageWParamCharToWCS(pmsg->message, &pmsg->wParam);
  2114. }
  2115. lRet = NtUserDispatchMessage(pmsg);
  2116. pmsg->wParam = wParamSaved;
  2117. return lRet;
  2118. }
  2119. /*
  2120. * If the dispatcher and the receiver are both ANSI or both UNICODE
  2121. * then no message translation is necessary. NOTE: this test
  2122. * assumes that fAnsi is FALSE or TRUE, not just zero or non-zero.
  2123. */
  2124. if (!fAnsi != !TestWF(pwnd, WFANSIPROC)) {
  2125. // before: if (fAnsi != ((TestWF(pwnd, WFANSIPROC)) ? TRUE : FALSE)) {
  2126. if (PtiCurrent() != GETPTI(pwnd)) {
  2127. RIPMSG0(RIP_WARNING, "message belongs to a different Q");
  2128. return 0;
  2129. }
  2130. if (fAnsi) {
  2131. /*
  2132. * Setup DBCS Messaging for WM_CHAR...
  2133. */
  2134. BUILD_DBCS_MESSAGE_TO_CLIENTW_FROM_CLIENTA(pmsg->message,pmsg->wParam,TRUE);
  2135. /*
  2136. * Convert wParam to Unicode, if nessesary.
  2137. */
  2138. RtlMBMessageWParamCharToWCS(pmsg->message, &pmsg->wParam);
  2139. } else {
  2140. /*
  2141. * Convert wParam to ANSI...
  2142. */
  2143. RtlWCSMessageWParamCharToMB(pmsg->message, &pmsg->wParam);
  2144. /*
  2145. * Let's DBCS messaging for WM_CHAR....
  2146. */
  2147. BUILD_DBCS_MESSAGE_TO_CLIENTA_FROM_CLIENTW(
  2148. pmsg->hwnd,pmsg->message,pmsg->wParam,pmsg->lParam,
  2149. pmsg->time,pmsg->pt,bDoDbcsMessaging);
  2150. }
  2151. }
  2152. DispatchMessageAgain:
  2153. lRet = UserCallWinProcCheckWow(pwnd->pActCtx, (WNDPROC)pwnd->lpfnWndProc, pmsg->hwnd, pmsg->message,
  2154. pmsg->wParam, pmsg->lParam, &(pwnd->state), TRUE);
  2155. /*
  2156. * if we have DBCS TrailingByte that should be sent, send it here..
  2157. */
  2158. DISPATCH_DBCS_MESSAGE_IF_EXIST(pmsg->message,pmsg->wParam,bDoDbcsMessaging,DispatchMessage);
  2159. pmsg->wParam = wParamSaved;
  2160. return lRet;
  2161. }
  2162. /***************************************************************************\
  2163. * GetMessageTime (API)
  2164. *
  2165. * This API returns the time when the last message was read from
  2166. * the current message queue.
  2167. *
  2168. * History:
  2169. * 11-19-90 DavidPe Created.
  2170. \***************************************************************************/
  2171. LONG GetMessageTime(VOID)
  2172. {
  2173. return (LONG)NtUserGetThreadState(UserThreadStateMessageTime);
  2174. }
  2175. /***************************************************************************\
  2176. * GetMessageExtraInfo (API)
  2177. *
  2178. * History:
  2179. * 28-May-1991 mikeke
  2180. \***************************************************************************/
  2181. LPARAM GetMessageExtraInfo(VOID)
  2182. {
  2183. return (LPARAM)NtUserGetThreadState(UserThreadStateExtraInfo);
  2184. }
  2185. FUNCLOG1(LOG_GENERAL, LPARAM, DUMMYCALLINGTYPE, SetMessageExtraInfo, LPARAM, lParam)
  2186. LPARAM SetMessageExtraInfo(LPARAM lParam)
  2187. {
  2188. return (LPARAM)NtUserCallOneParam(lParam, SFI__SETMESSAGEEXTRAINFO);
  2189. }
  2190. /***********************************************************************\
  2191. * InSendMessage (API)
  2192. *
  2193. * This function determines if the current thread is preocessing a message
  2194. * from another application.
  2195. *
  2196. * History:
  2197. * 01-13-91 DavidPe Ported.
  2198. \***********************************************************************/
  2199. BOOL InSendMessage(VOID)
  2200. {
  2201. PCLIENTTHREADINFO pcti = GetClientInfo()->pClientThreadInfo;
  2202. if (pcti) {
  2203. return TEST_BOOL_FLAG(pcti->CTIF_flags, CTIF_INSENDMESSAGE);
  2204. }
  2205. return NtUserGetThreadState(UserThreadStateInSendMessage) != ISMEX_NOSEND;
  2206. }
  2207. /***********************************************************************\
  2208. * InSendMessageEx (API)
  2209. *
  2210. * This function tells you what type of send message is being processed
  2211. * by the application, if any
  2212. *
  2213. * History:
  2214. * 01/22/97 GerardoB Created
  2215. \***********************************************************************/
  2216. FUNCLOG1(LOG_GENERAL, DWORD, DUMMYCALLINGTYPE, InSendMessageEx, LPVOID, lpReserved)
  2217. DWORD InSendMessageEx(LPVOID lpReserved)
  2218. {
  2219. PCLIENTTHREADINFO pcti = GetClientInfo()->pClientThreadInfo;
  2220. UNREFERENCED_PARAMETER(lpReserved);
  2221. if (pcti && !TEST_FLAG(pcti->CTIF_flags, CTIF_INSENDMESSAGE)) {
  2222. return ISMEX_NOSEND;
  2223. }
  2224. return (DWORD)NtUserGetThreadState(UserThreadStateInSendMessage);
  2225. }
  2226. /***********************************************************************\
  2227. * GetCPD
  2228. *
  2229. * This function calls the server to allocate a CPD structure.
  2230. *
  2231. * History:
  2232. * 11-15-94 JimA Created.
  2233. \***********************************************************************/
  2234. ULONG_PTR GetCPD(
  2235. KERNEL_PVOID pWndOrCls,
  2236. DWORD options,
  2237. ULONG_PTR dwData)
  2238. {
  2239. return NtUserGetCPD(HW(pWndOrCls), options, dwData);
  2240. }
  2241. #ifdef BUILD_WOW6432
  2242. /***********************************************************************\
  2243. * MapKernelClientFnToClientFn
  2244. *
  2245. * Maps a function pointer from what the kernel expects to what the
  2246. * client(user-mode) expects.
  2247. *
  2248. * History:
  2249. * 11-15-98 PeterHal Created.
  2250. \***********************************************************************/
  2251. WNDPROC_PWND
  2252. MapKernelClientFnToClientFn(
  2253. WNDPROC_PWND lpfnWndProc
  2254. )
  2255. {
  2256. KPKERNEL_ULONG_PTR pp;
  2257. for (pp = (KPKERNEL_ULONG_PTR)&gpsi->apfnClientA; pp < (KPKERNEL_ULONG_PTR) (&gpsi->apfnClientA+1); pp ++) {
  2258. if ((KERNEL_ULONG_PTR)lpfnWndProc == *pp) {
  2259. return (WNDPROC_PWND)((KERNEL_ULONG_PTR*) &pfnClientA) [ (pp - (KPKERNEL_ULONG_PTR)&gpsi->apfnClientA) ];
  2260. }
  2261. }
  2262. for (pp = (KPKERNEL_ULONG_PTR)&gpsi->apfnClientW; pp < (KPKERNEL_ULONG_PTR) (&gpsi->apfnClientW+1); pp ++) {
  2263. if ((KERNEL_ULONG_PTR)lpfnWndProc == *pp) {
  2264. return (WNDPROC_PWND)((KERNEL_ULONG_PTR*) &pfnClientW) [ (pp - (KPKERNEL_ULONG_PTR)&gpsi->apfnClientW) ];
  2265. }
  2266. }
  2267. return lpfnWndProc;
  2268. }
  2269. #endif
  2270. #ifdef GENERIC_INPUT
  2271. LRESULT
  2272. APIENTRY
  2273. DefRawInputProc(
  2274. PRAWINPUT* paRawInput,
  2275. INT nInput,
  2276. UINT cbSizeHeader)
  2277. {
  2278. UNREFERENCED_PARAMETER(paRawInput);
  2279. UNREFERENCED_PARAMETER(nInput);
  2280. if (cbSizeHeader != sizeof(RAWINPUTHEADER)) {
  2281. return (LRESULT)-1;
  2282. }
  2283. return 0;
  2284. }
  2285. #endif