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.

817 lines
19 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: wow.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * This module contains shared code between USER32 and USER16
  7. * No New CODE should be added to this file, unless its shared
  8. * with USER16.
  9. *
  10. * History:
  11. * 29-DEC-93 NanduriR shared user32/user16 code.
  12. \***************************************************************************/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. /***************************************************************************\
  16. * ValidateHwnd
  17. *
  18. * Verify that the handle is valid. If the handle is invalid or access
  19. * cannot be granted fail.
  20. *
  21. * History:
  22. * 03-18-92 DarrinM Created from pieces of misc server-side funcs.
  23. \***************************************************************************/
  24. PWND FASTCALL ValidateHwnd(
  25. HWND hwnd)
  26. {
  27. PCLIENTINFO pci = GetClientInfo();
  28. /*
  29. * Attempt fast window validation.
  30. */
  31. if (hwnd != NULL && hwnd == pci->CallbackWnd.hwnd) {
  32. return pci->CallbackWnd.pwnd;
  33. }
  34. /*
  35. * Validate that the handle is of the proper type.
  36. */
  37. return HMValidateHandle(hwnd, TYPE_WINDOW);
  38. }
  39. PWND FASTCALL ValidateHwndNoRip(
  40. HWND hwnd)
  41. {
  42. PCLIENTINFO pci = GetClientInfo();
  43. /*
  44. * Attempt fast window validation.
  45. */
  46. if (hwnd != NULL && hwnd == pci->CallbackWnd.hwnd) {
  47. return pci->CallbackWnd.pwnd;
  48. }
  49. /*
  50. * Validate the handle is of the proper type.
  51. */
  52. return HMValidateHandleNoRip(hwnd, TYPE_WINDOW);
  53. }
  54. FUNCLOG3(LOG_GENERAL, int, WINAPI, GetClassNameA, HWND, hwnd, LPSTR, lpClassName, int, nMaxCount)
  55. int WINAPI GetClassNameA(
  56. HWND hwnd,
  57. LPSTR lpClassName,
  58. int nMaxCount)
  59. {
  60. PCLS pcls;
  61. LPSTR lpszClassNameSrc;
  62. PWND pwnd;
  63. int cchSrc;
  64. pwnd = ValidateHwnd(hwnd);
  65. if (pwnd == NULL)
  66. return FALSE;
  67. try {
  68. if (nMaxCount != 0) {
  69. pcls = (PCLS)REBASEALWAYS(pwnd, pcls);
  70. lpszClassNameSrc = REBASEPTR(pwnd, pcls->lpszAnsiClassName);
  71. cchSrc = lstrlenA(lpszClassNameSrc);
  72. nMaxCount = min(cchSrc, nMaxCount - 1);
  73. RtlCopyMemory(lpClassName, lpszClassNameSrc, nMaxCount);
  74. lpClassName[nMaxCount] = '\0';
  75. }
  76. } except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
  77. nMaxCount = 0;
  78. }
  79. return nMaxCount;
  80. }
  81. /***************************************************************************\
  82. * _GetDesktopWindow (API)
  83. *
  84. * History:
  85. * 11-07-90 darrinm Implemented.
  86. \***************************************************************************/
  87. PWND _GetDesktopWindow(
  88. VOID)
  89. {
  90. PCLIENTINFO pci;
  91. ConnectIfNecessary(0);
  92. pci = GetClientInfo();
  93. return (PWND)((KERNEL_ULONG_PTR)pci->pDeskInfo->spwnd - pci->ulClientDelta);
  94. }
  95. HWND GetDesktopWindow(
  96. VOID)
  97. {
  98. PWND pwnd = _GetDesktopWindow();
  99. PCLIENTINFO pci = GetClientInfo();
  100. /*
  101. * Validate the parent window's handle if a restricted process.
  102. */
  103. if (pci && (pci->dwTIFlags & TIF_RESTRICTED)) {
  104. if (ValidateHwnd(HW(pwnd)) == NULL) {
  105. return NULL;
  106. }
  107. }
  108. return HW(pwnd);
  109. }
  110. PWND _GetDlgItem(
  111. PWND pwnd,
  112. int id)
  113. {
  114. if (pwnd != NULL) {
  115. pwnd = REBASEPWND(pwnd, spwndChild);
  116. while (pwnd != NULL) {
  117. if (PtrToLong(pwnd->spmenu) == id) {
  118. break;
  119. }
  120. pwnd = REBASEPWND(pwnd, spwndNext);
  121. }
  122. }
  123. return pwnd;
  124. }
  125. FUNCLOG2(LOG_GENERAL, HWND, DUMMYCALLINGTYPE, GetDlgItem, HWND, hwnd, int, id)
  126. HWND GetDlgItem(
  127. HWND hwnd,
  128. int id)
  129. {
  130. PWND pwnd;
  131. HWND hwndRet;
  132. pwnd = ValidateHwnd(hwnd);
  133. if (pwnd == NULL) {
  134. return NULL;
  135. }
  136. pwnd = _GetDlgItem(pwnd, id);
  137. hwndRet = HW(pwnd);
  138. if (hwndRet == (HWND)0) {
  139. RIPERR0(ERROR_CONTROL_ID_NOT_FOUND, RIP_VERBOSE, "");
  140. }
  141. return hwndRet;
  142. }
  143. FUNCLOG1(LOG_GENERAL, HMENU, DUMMYCALLINGTYPE, GetMenu, HWND, hwnd)
  144. HMENU GetMenu(
  145. HWND hwnd)
  146. {
  147. PWND pwnd;
  148. PMENU pmenu;
  149. pwnd = ValidateHwnd(hwnd);
  150. if (pwnd == NULL) {
  151. return 0;
  152. }
  153. /*
  154. * Some ill-behaved apps use GetMenu to get the child id, so
  155. * only map to the handle for non-child windows.
  156. */
  157. if (!TestwndChild(pwnd)) {
  158. pmenu = REBASE(pwnd, spmenu);
  159. return (HMENU)PtoH(pmenu);
  160. } else {
  161. return (HMENU)KPVOID_TO_PVOID(pwnd->spmenu);
  162. }
  163. }
  164. /***************************************************************************\
  165. * GetMenuItemCount
  166. *
  167. * Returns a count of the number of items in the menu. Returns -1 if
  168. * invalid menu.
  169. *
  170. * History:
  171. \***************************************************************************/
  172. FUNCLOG1(LOG_GENERAL, int, DUMMYCALLINGTYPE, GetMenuItemCount, HMENU, hMenu)
  173. int GetMenuItemCount(
  174. HMENU hMenu)
  175. {
  176. PMENU pMenu;
  177. pMenu = VALIDATEHMENU(hMenu);
  178. if (pMenu == NULL) {
  179. return -1;
  180. }
  181. return pMenu->cItems;
  182. }
  183. /***************************************************************************\
  184. * GetMenuItemID
  185. *
  186. * Return the ID of a menu item at the specified position.
  187. *
  188. * History:
  189. \***************************************************************************/
  190. FUNCLOG2(LOG_GENERAL, UINT, DUMMYCALLINGTYPE, GetMenuItemID, HMENU, hMenu, int, nPos)
  191. UINT GetMenuItemID(
  192. HMENU hMenu,
  193. int nPos)
  194. {
  195. PMENU pMenu;
  196. PITEM pItem;
  197. pMenu = VALIDATEHMENU(hMenu);
  198. if (pMenu == NULL) {
  199. return (UINT)-1;
  200. }
  201. /*
  202. * If the position is valid and the item is not a popup, get the ID
  203. * Don't allow negative indexes, because that'll cause an access violation.
  204. */
  205. if (nPos < (int)pMenu->cItems && nPos >= 0) {
  206. pItem = &((PITEM)REBASEALWAYS(pMenu, rgItems))[nPos];
  207. if (pItem->spSubMenu == NULL) {
  208. return pItem->wID;
  209. }
  210. }
  211. return (UINT)-1;
  212. }
  213. FUNCLOG3(LOG_GENERAL, UINT, DUMMYCALLINGTYPE, GetMenuState, HMENU, hMenu, UINT, uId, UINT, uFlags)
  214. UINT GetMenuState(
  215. HMENU hMenu,
  216. UINT uId,
  217. UINT uFlags)
  218. {
  219. PMENU pMenu;
  220. pMenu = VALIDATEHMENU(hMenu);
  221. if (pMenu == NULL || (uFlags & ~MF_VALID) != 0) {
  222. return (UINT)-1;
  223. }
  224. return _GetMenuState(pMenu, uId, uFlags);
  225. }
  226. FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, IsWindow, HWND, hwnd)
  227. BOOL IsWindow(
  228. HWND hwnd)
  229. {
  230. PWND pwnd;
  231. /*
  232. * Validate the handle is of type window
  233. */
  234. pwnd = ValidateHwndNoRip(hwnd);
  235. /*
  236. * And validate this handle is valid for this desktop by trying to read it
  237. */
  238. if (pwnd != NULL) {
  239. try {
  240. if (pwnd->fnid & FNID_DELETED_BIT) {
  241. pwnd = 0;
  242. }
  243. } except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
  244. RIPMSG1(RIP_WARNING, "IsWindow: Window %#p not of this desktop",
  245. pwnd);
  246. pwnd = 0;
  247. }
  248. }
  249. return !!pwnd;
  250. }
  251. FUNCLOG2(LOG_GENERAL, HWND, DUMMYCALLINGTYPE, GetWindow, HWND, hwnd, UINT, wCmd)
  252. HWND GetWindow(
  253. HWND hwnd,
  254. UINT wCmd)
  255. {
  256. PWND pwnd;
  257. pwnd = ValidateHwnd(hwnd);
  258. if (pwnd == NULL) {
  259. return NULL;
  260. }
  261. pwnd = _GetWindow(pwnd, wCmd);
  262. return HW(pwnd);
  263. }
  264. FUNCLOG1(LOG_GENERAL, HWND, DUMMYCALLINGTYPE, GetParent, HWND, hwnd)
  265. HWND GetParent(
  266. HWND hwnd)
  267. {
  268. PWND pwnd;
  269. PCLIENTINFO pci;
  270. pwnd = ValidateHwnd(hwnd);
  271. if (pwnd == NULL) {
  272. return NULL;
  273. }
  274. try {
  275. pwnd = _GetParent(pwnd);
  276. hwnd = HW(pwnd);
  277. } except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
  278. hwnd = NULL;
  279. }
  280. pci = GetClientInfo();
  281. /*
  282. * validate the parent window's handle if a restricted process
  283. */
  284. if (pci && (pci->dwTIFlags & TIF_RESTRICTED)) {
  285. if (ValidateHwnd(hwnd) == NULL) {
  286. return NULL;
  287. }
  288. }
  289. return hwnd;
  290. }
  291. FUNCLOG2(LOG_GENERAL, HMENU, DUMMYCALLINGTYPE, GetSubMenu, HMENU, hMenu, int, nPos)
  292. HMENU GetSubMenu(
  293. HMENU hMenu,
  294. int nPos)
  295. {
  296. PMENU pMenu;
  297. pMenu = VALIDATEHMENU(hMenu);
  298. if (pMenu == NULL) {
  299. return 0;
  300. }
  301. pMenu = _GetSubMenu(pMenu, nPos);
  302. return (HMENU)PtoH(pMenu);
  303. }
  304. FUNCLOG1(LOG_GENERAL, DWORD, DUMMYCALLINGTYPE, GetSysColor, int, nIndex)
  305. DWORD GetSysColor(
  306. int nIndex)
  307. {
  308. /*
  309. * Return 0 if the index is out of range.
  310. */
  311. if (nIndex < 0 || nIndex >= COLOR_MAX) {
  312. RIPERR1(ERROR_INVALID_PARAMETER,
  313. RIP_WARNING,
  314. "Invalid parameter \"nIndex\" (%ld) to GetSysColor",
  315. nIndex);
  316. return 0;
  317. }
  318. return gpsi->argbSystem[nIndex];
  319. }
  320. FUNCLOG1(LOG_GENERAL, int, DUMMYCALLINGTYPE, GetSystemMetrics, int, index)
  321. int GetSystemMetrics(
  322. int index)
  323. {
  324. int ret;
  325. BEGIN_USERAPIHOOK()
  326. ret = guah.pfnGetSystemMetrics(index);
  327. END_USERAPIHOOK()
  328. return ret;
  329. }
  330. int RealGetSystemMetrics(
  331. int index)
  332. {
  333. ConnectIfNecessary(0);
  334. /*
  335. * First check for values that aren't in the aiSysMet array.
  336. */
  337. switch (index) {
  338. case SM_REMOTESESSION:
  339. return ISREMOTESESSION();
  340. }
  341. /*
  342. * If it's in the BOOLEAN system metric range then do our magic.
  343. */
  344. if (index >= SM_STARTBOOLRANGE && index <= SM_ENDBOOLRANGE) {
  345. return SYSMETBOOL2(index);
  346. }
  347. if (index < 0 || index >= SM_CMETRICS) {
  348. return 0;
  349. }
  350. switch (index) {
  351. case SM_DBCSENABLED:
  352. #ifdef FE_SB
  353. return TEST_SRVIF(SRVIF_DBCS);
  354. #else
  355. return FALSE;
  356. #endif
  357. case SM_IMMENABLED:
  358. #ifdef FE_IME
  359. return TEST_SRVIF(SRVIF_IME);
  360. #else
  361. return FALSE;
  362. #endif
  363. case SM_MIDEASTENABLED:
  364. return TEST_SRVIF(SRVIF_MIDEAST);
  365. }
  366. if (!Is400Compat(GetClientInfo()->dwExpWinVer)) {
  367. /*
  368. * SCROLL BAR
  369. * before 4.0, the scroll bars and the border overlapped by a pixel. Many apps
  370. * rely on this overlap when they compute dimensions. Now, in 4.0, this pixel
  371. * overlap is no longer there. So for old apps, we lie and pretend the overlap
  372. * is there by making the scroll bar widths one bigger.
  373. *
  374. * DLGFRAME
  375. * In Win3.1, SM_CXDLGFRAME & SM_CYDLGFRAME were border space MINUS 1
  376. * In Win4.0, they are border space
  377. *
  378. * CAPTION
  379. * In Win3.1, SM_CYCAPTION was the caption height PLUS 1
  380. * In Win4.0, SM_CYCAPTION is the caption height
  381. *
  382. * MENU
  383. * In Win3.1, SM_CYMENU was the menu height MINUS 1
  384. * In Win4.0, SM_CYMENU is the menu height
  385. */
  386. switch (index) {
  387. case SM_CXDLGFRAME:
  388. case SM_CYDLGFRAME:
  389. case SM_CYMENU:
  390. case SM_CYFULLSCREEN:
  391. return gpsi->aiSysMet[index] - 1;
  392. case SM_CYCAPTION:
  393. case SM_CXVSCROLL:
  394. case SM_CYHSCROLL:
  395. return gpsi->aiSysMet[index] + 1;
  396. }
  397. }
  398. return gpsi->aiSysMet[index];
  399. }
  400. /***************************************************************************\
  401. * GetTopWindow (API)
  402. *
  403. * This poorly named API should really be called 'GetFirstChild', which is
  404. * what it does.
  405. *
  406. * History:
  407. * 11-12-90 darrinm Ported.
  408. * 02-19-91 JimA Added enum access check
  409. * 05-04-02 DarrinM Removed enum access check and moved to USERRTL.DLL
  410. \***************************************************************************/
  411. FUNCLOG1(LOG_GENERAL, HWND, DUMMYCALLINGTYPE, GetTopWindow, HWND, hwnd)
  412. HWND GetTopWindow(
  413. HWND hwnd)
  414. {
  415. PWND pwnd;
  416. /*
  417. * Allow a NULL hwnd to go through here.
  418. */
  419. if (hwnd == NULL) {
  420. pwnd = _GetDesktopWindow();
  421. } else {
  422. pwnd = ValidateHwnd(hwnd);
  423. }
  424. if (pwnd == NULL) {
  425. return NULL;
  426. }
  427. pwnd = REBASEPWND(pwnd, spwndChild);
  428. return HW(pwnd);
  429. }
  430. FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, IsChild, HWND, hwndParent, HWND, hwnd)
  431. BOOL IsChild(
  432. HWND hwndParent,
  433. HWND hwnd)
  434. {
  435. PWND pwnd, pwndParent;
  436. pwnd = ValidateHwnd(hwnd);
  437. if (pwnd == NULL) {
  438. return FALSE;
  439. }
  440. pwndParent = ValidateHwnd(hwndParent);
  441. if (pwndParent == NULL) {
  442. return FALSE;
  443. }
  444. return _IsChild(pwndParent, pwnd);
  445. }
  446. FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, IsIconic, HWND, hwnd)
  447. BOOL IsIconic(
  448. HWND hwnd)
  449. {
  450. PWND pwnd;
  451. pwnd = ValidateHwnd(hwnd);
  452. if (pwnd == NULL) {
  453. return FALSE;
  454. }
  455. return _IsIconic(pwnd);
  456. }
  457. FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, IsWindowEnabled, HWND, hwnd)
  458. BOOL IsWindowEnabled(
  459. HWND hwnd)
  460. {
  461. PWND pwnd;
  462. pwnd = ValidateHwnd(hwnd);
  463. if (pwnd == NULL) {
  464. return FALSE;
  465. }
  466. return _IsWindowEnabled(pwnd);
  467. }
  468. FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, IsWindowVisible, HWND, hwnd)
  469. BOOL IsWindowVisible(
  470. HWND hwnd)
  471. {
  472. PWND pwnd;
  473. BOOL bRet;
  474. pwnd = ValidateHwnd(hwnd);
  475. if (pwnd == NULL) {
  476. bRet = FALSE;
  477. } else {
  478. try {
  479. bRet = _IsWindowVisible(pwnd);
  480. } except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
  481. bRet = FALSE;
  482. }
  483. }
  484. return bRet;
  485. }
  486. FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, IsZoomed, HWND, hwnd)
  487. BOOL IsZoomed(
  488. HWND hwnd)
  489. {
  490. PWND pwnd;
  491. pwnd = ValidateHwnd(hwnd);
  492. if (pwnd == NULL) {
  493. return FALSE;
  494. }
  495. return _IsZoomed(pwnd);
  496. }
  497. FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, ClientToScreen, HWND, hwnd, LPPOINT, ppoint)
  498. BOOL ClientToScreen(
  499. HWND hwnd,
  500. LPPOINT ppoint)
  501. {
  502. PWND pwnd;
  503. pwnd = ValidateHwnd(hwnd);
  504. if (pwnd == NULL) {
  505. return FALSE;
  506. }
  507. _ClientToScreen(pwnd, ppoint);
  508. return TRUE;
  509. }
  510. FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, GetClientRect, HWND, hwnd, LPRECT, prect)
  511. BOOL GetClientRect(
  512. HWND hwnd,
  513. LPRECT prect)
  514. {
  515. PWND pwnd;
  516. pwnd = ValidateHwnd(hwnd);
  517. if (pwnd == NULL) {
  518. return FALSE;
  519. }
  520. _GetClientRect(pwnd, prect);
  521. return TRUE;
  522. }
  523. FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, GetCursorPos, LPPOINT, lpPoint)
  524. BOOL GetCursorPos(
  525. LPPOINT lpPoint)
  526. {
  527. return (BOOL)NtUserCallOneParam((ULONG_PTR)lpPoint, SFI_XXXGETCURSORPOS);
  528. }
  529. FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, GetWindowRect, HWND, hwnd, LPRECT, prect)
  530. BOOL GetWindowRect(
  531. HWND hwnd,
  532. LPRECT prect)
  533. {
  534. PWND pwnd;
  535. pwnd = ValidateHwnd(hwnd);
  536. if (pwnd == NULL) {
  537. return FALSE;
  538. }
  539. _GetWindowRect(pwnd, prect);
  540. return TRUE;
  541. }
  542. FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, ScreenToClient, HWND, hwnd, LPPOINT, ppoint)
  543. BOOL ScreenToClient(
  544. HWND hwnd,
  545. LPPOINT ppoint)
  546. {
  547. PWND pwnd;
  548. pwnd = ValidateHwnd(hwnd);
  549. if (pwnd == NULL) {
  550. return FALSE;
  551. }
  552. _ScreenToClient(pwnd, ppoint);
  553. return TRUE;
  554. }
  555. FUNCLOG3(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, EnableMenuItem, HMENU, hMenu, UINT, uIDEnableItem, UINT, uEnable)
  556. BOOL EnableMenuItem(
  557. HMENU hMenu,
  558. UINT uIDEnableItem,
  559. UINT uEnable)
  560. {
  561. PMENU pMenu;
  562. PITEM pItem;
  563. pMenu = VALIDATEHMENU(hMenu);
  564. if (pMenu == NULL) {
  565. return (BOOL)-1;
  566. }
  567. /*
  568. * Get a pointer the the menu item.
  569. */
  570. if ((pItem = MNLookUpItem(pMenu, uIDEnableItem, (BOOL) (uEnable & MF_BYPOSITION), NULL)) == NULL) {
  571. return (DWORD)-1;
  572. }
  573. /*
  574. * If the item is already in the state we're
  575. * trying to set, just return.
  576. */
  577. if ((pItem->fState & MFS_GRAYED) == (uEnable & MFS_GRAYED)) {
  578. return pItem->fState & MFS_GRAYED;
  579. }
  580. return NtUserEnableMenuItem(hMenu, uIDEnableItem, uEnable);
  581. }
  582. /***************************************************************************\
  583. * CallNextHookEx
  584. *
  585. * This routine is called to call the next hook in the hook chain.
  586. *
  587. * 05-09-91 ScottLu Created.
  588. \***************************************************************************/
  589. FUNCLOG4(LOG_GENERAL, LRESULT, WINAPI, CallNextHookEx, HHOOK, hhk, int, nCode, WPARAM, wParam, LPARAM, lParam)
  590. LRESULT WINAPI CallNextHookEx(
  591. HHOOK hhk,
  592. int nCode,
  593. WPARAM wParam,
  594. LPARAM lParam)
  595. {
  596. LRESULT nRet;
  597. BOOL bAnsi;
  598. DWORD dwHookCurrent;
  599. PCLIENTINFO pci;
  600. ULONG_PTR dwHookData;
  601. ULONG_PTR dwFlags;
  602. UNREFERENCED_PARAMETER(hhk);
  603. ConnectIfNecessary(0);
  604. pci = GetClientInfo();
  605. dwHookCurrent = pci->dwHookCurrent;
  606. bAnsi = LOWORD(dwHookCurrent);
  607. /*
  608. * If this is the last hook in the hook chain then return 0; we're done.
  609. */
  610. if (PhkNextValid((PHOOK)((KERNEL_ULONG_PTR)pci->phkCurrent - pci->ulClientDelta)) == NULL) {
  611. return 0;
  612. }
  613. switch ((INT)(SHORT)HIWORD(dwHookCurrent)) {
  614. case WH_CALLWNDPROC:
  615. case WH_CALLWNDPROCRET:
  616. /*
  617. * This is the hardest of the hooks because we need to thunk through
  618. * the message hooks in order to deal with synchronously sent messages
  619. * that point to structures - to get the structures passed across
  620. * alright, etc.
  621. *
  622. * This will call a special kernel-side routine that'll rebundle the
  623. * arguments and call the hook in the right format.
  624. *
  625. * Currently, the message thunk callbacks to the client-side don't take
  626. * enough parameters to pass wParam (which == fInterThread send msg).
  627. * To do this, save the state of wParam in the CLIENTINFO structure.
  628. */
  629. dwFlags = KERNEL_ULONG_PTR_TO_ULONG_PTR(pci->CI_flags) & CI_INTERTHREAD_HOOK;
  630. dwHookData = KERNEL_ULONG_PTR_TO_ULONG_PTR(pci->dwHookData);
  631. if (wParam) {
  632. pci->CI_flags |= CI_INTERTHREAD_HOOK;
  633. } else {
  634. pci->CI_flags &= ~CI_INTERTHREAD_HOOK;
  635. }
  636. if ((INT)(SHORT)HIWORD(dwHookCurrent) == WH_CALLWNDPROC) {
  637. nRet = CsSendMessage(
  638. ((LPCWPSTRUCT)lParam)->hwnd,
  639. ((LPCWPSTRUCT)lParam)->message,
  640. ((LPCWPSTRUCT)lParam)->wParam,
  641. ((LPCWPSTRUCT)lParam)->lParam,
  642. 0, FNID_HKINLPCWPEXSTRUCT, bAnsi);
  643. } else {
  644. pci->dwHookData = ((LPCWPRETSTRUCT)lParam)->lResult;
  645. nRet = CsSendMessage(
  646. ((LPCWPRETSTRUCT)lParam)->hwnd,
  647. ((LPCWPRETSTRUCT)lParam)->message,
  648. ((LPCWPRETSTRUCT)lParam)->wParam,
  649. ((LPCWPRETSTRUCT)lParam)->lParam,
  650. 0, FNID_HKINLPCWPRETEXSTRUCT, bAnsi);
  651. }
  652. /*
  653. * Restore previous hook state.
  654. */
  655. pci->CI_flags ^= ((pci->CI_flags ^ dwFlags) & CI_INTERTHREAD_HOOK);
  656. pci->dwHookData = dwHookData;
  657. break;
  658. default:
  659. nRet = NtUserCallNextHookEx(nCode, wParam, lParam, bAnsi);
  660. }
  661. return nRet;
  662. }