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.

14744 lines
386 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: ntstubs.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * Kernel-mode stubs
  7. *
  8. * History:
  9. * 03-16-95 JimA Created.
  10. \***************************************************************************/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #include "cscall.h"
  14. #include <dbt.h>
  15. #define PROTOS_ONLY 1
  16. #include "msgdef.h"
  17. #if DBG
  18. UINT gcMaxNestedCalls;
  19. ULONG_PTR gcMaxUsedStack;
  20. #if defined(_IA64_)
  21. ULONG_PTR gcMaxUsedBStore;
  22. #endif // _IA64_
  23. int ThreadLockCount(
  24. BOOL fInc)
  25. {
  26. PTHREADINFO ptiCurrent = PtiCurrentShared();
  27. PTL ptl = ptiCurrent->ptl;
  28. int nLocks = 0;
  29. ULONG_PTR CurrentUsedSize;
  30. if (fInc) {
  31. (ptiCurrent->cNestedCalls)++;
  32. if (GetNestedCallsCounter() > 50) {
  33. RIPMSG1(RIP_WARNING, "ThreadLockCount: This thread did %d nested calls.", GetNestedCallsCounter());
  34. }
  35. if (ptiCurrent->cNestedCalls > gcMaxNestedCalls) {
  36. gcMaxNestedCalls = ptiCurrent->cNestedCalls;
  37. }
  38. } else {
  39. (ptiCurrent->cNestedCalls)--;
  40. }
  41. if (!ISCSRSS()) {
  42. CurrentUsedSize = GET_USED_STACK_SIZE();
  43. if (CurrentUsedSize > gcMaxUsedStack) {
  44. gcMaxUsedStack = CurrentUsedSize;
  45. }
  46. #ifdef _IA64_
  47. CurrentUsedSize = GET_USED_BSTORE_SIZE();
  48. if (CurrentUsedSize > gcMaxUsedBStore) {
  49. gcMaxUsedBStore = CurrentUsedSize;
  50. }
  51. #endif
  52. }
  53. while (ptl != NULL) {
  54. nLocks++;
  55. ptl = ptl->next;
  56. }
  57. ptl = ptiCurrent->ptlW32;
  58. while (ptl != NULL) {
  59. nLocks++;
  60. ptl = ptl->next;
  61. }
  62. return nLocks;
  63. }
  64. VOID ThreadLockCheck(
  65. int nLocks)
  66. {
  67. int nNewCount = ThreadLockCount(FALSE);
  68. if (nLocks != nNewCount) {
  69. RIPMSG2(RIP_ERROR, "ThreadLocks mismatch %d %d", nLocks, nNewCount);
  70. }
  71. }
  72. // The parameter is used to ensure BEGINRECV* matches ENDRECV* in each stub.
  73. #define DBG_THREADLOCK_START(s) { int nLocks ## s = ThreadLockCount(TRUE);
  74. #define DBG_THREADLOCK_END(s) ThreadLockCheck(nLocks ## s); }
  75. #else
  76. #define DBG_THREADLOCK_START(s)
  77. #define DBG_THREADLOCK_END(s)
  78. #endif
  79. /*
  80. * Setup and control macros
  81. */
  82. #define BEGINRECV(type, err) \
  83. type retval; \
  84. type errret = err; \
  85. EnterCrit(); \
  86. DBG_THREADLOCK_START(_)
  87. #define ENDRECV() ENDRECV_(_)
  88. #define BEGINATOMICRECV(type, err) \
  89. type retval; \
  90. type errret = err; \
  91. EnterCrit(); \
  92. DBG_THREADLOCK_START(_) \
  93. BEGINATOMICCHECK()
  94. #define ENDATOMICRECV() ENDATOMICRECV_(_)
  95. #define BEGINRECVCSRSS(type, err) \
  96. type retval; \
  97. type errret = err; \
  98. EnterCrit(); \
  99. DBG_THREADLOCK_START(CSRSS) \
  100. if (!ISCSRSS()) { \
  101. retval = STATUS_ACCESS_DENIED; \
  102. goto errorexit; \
  103. }
  104. #define ENDRECVCSRSS() ENDRECV_(CSRSS)
  105. #define BEGINRECV_SHARED(type, err) \
  106. type retval; \
  107. type errret = err; \
  108. EnterSharedCrit(); \
  109. DBG_THREADLOCK_START(SHARED)
  110. #define ENDRECV_SHARED() ENDRECV_(SHARED)
  111. #define BEGINRECV_NOCRIT(type, err) \
  112. type retval; \
  113. type errret = err;
  114. #define BEGINRECV_VOID() \
  115. EnterCrit(); \
  116. DBG_THREADLOCK_START(_VOID)
  117. #define ENDRECV_VOID() ENDRECV_VOID_(_VOID)
  118. #define BEGINRECV_HWND(type, err, hwnd) \
  119. type retval; \
  120. type errret = err; \
  121. PWND pwnd; \
  122. EnterCrit(); \
  123. DBG_THREADLOCK_START(HWND) \
  124. if ((pwnd = ValidateHwnd((hwnd))) == NULL) { \
  125. retval = errret; \
  126. goto errorexit; \
  127. }
  128. #define ENDRECV_HWND() ENDRECV_HWND_(HWND)
  129. #define BEGINATOMICRECV_HWND(type, err, hwnd) \
  130. type retval; \
  131. type errret = err; \
  132. PWND pwnd; \
  133. EnterCrit(); \
  134. DBG_THREADLOCK_START(HWND) \
  135. BEGINATOMICCHECK() \
  136. if ((pwnd = ValidateHwnd((hwnd))) == NULL) { \
  137. retval = errret; \
  138. goto errorexit; \
  139. }
  140. #define ENDATOMICRECV_HWND() ENDATOMICRECV_HWND_(HWND)
  141. #define BEGINRECV_HWND_VOID(hwnd) \
  142. PWND pwnd; \
  143. EnterCrit(); \
  144. DBG_THREADLOCK_START(HWND_VOID) \
  145. if ((pwnd = ValidateHwnd((hwnd))) == NULL) { \
  146. goto errorexit; \
  147. }
  148. #define ENDRECV_HWND_VOID() ENDRECV_VOID_(HWND_VOID)
  149. #define BEGINRECV_HWND_SHARED(type, err, hwnd) \
  150. type retval; \
  151. type errret = err; \
  152. PWND pwnd; \
  153. EnterSharedCrit(); \
  154. DBG_THREADLOCK_START(HWND_SHARED) \
  155. if ((pwnd = ValidateHwnd((hwnd))) == NULL) { \
  156. retval = errret; \
  157. goto errorexit; \
  158. }
  159. #define ENDRECV_HWND_SHARED() ENDRECV_HWND_(HWND_SHARED)
  160. #define BEGINRECV_HWNDOPT_SHARED(type, err, hwnd) \
  161. type retval; \
  162. type errret = err; \
  163. PWND pwnd; \
  164. EnterSharedCrit(); \
  165. DBG_THREADLOCK_START(HWND_OPT_SHARED) \
  166. if (hwnd) { \
  167. if ((pwnd = ValidateHwnd((hwnd))) == NULL) { \
  168. retval = errret; \
  169. goto errorexit; \
  170. } \
  171. } else { \
  172. pwnd = NULL; \
  173. }
  174. #define ENDRECV_HWNDOPT_SHARED() ENDRECV_HWND_(HWND_OPT_SHARED)
  175. #define BEGINRECV_HWNDLOCK(type, err, hwnd) \
  176. type retval; \
  177. type errret = err; \
  178. PWND pwnd; \
  179. TL tlpwnd; \
  180. PTHREADINFO ptiCurrent; \
  181. EnterCrit(); \
  182. DBG_THREADLOCK_START(HWNDLOCK) \
  183. if ((pwnd = ValidateHwnd((hwnd))) == NULL) { \
  184. retval = errret; \
  185. goto errorexit2; \
  186. } \
  187. ptiCurrent = PtiCurrent(); \
  188. ThreadLockAlwaysWithPti(ptiCurrent, pwnd, &tlpwnd);
  189. #define BEGINRECV_HWNDLOCKFF(type, err, hwnd, xpfnProc) \
  190. type retval; \
  191. type errret = err; \
  192. PWND pwnd; \
  193. TL tlpwnd; \
  194. EnterCrit(); \
  195. DBG_THREADLOCK_START(HWNDLOCK) \
  196. if ((hwnd == HWND_BROADCAST || hwnd == (HWND)-1) && \
  197. (xpfnProc == FNID_SENDNOTIFYMESSAGE || \
  198. xpfnProc == FNID_SENDMESSAGECALLBACK)) { \
  199. \
  200. if (hwnd == (HWND)-1) { \
  201. RIPMSG0(RIP_VERBOSE, \
  202. "Use HWND_BROADCAST, not -1"); \
  203. } \
  204. \
  205. pwnd = PWND_BROADCAST; \
  206. } else if ((pwnd = ValidateHwnd((hwnd))) == NULL) { \
  207. retval = errret; \
  208. goto errorexit2; \
  209. } else { \
  210. PTHREADINFO ptiCurrent = PtiCurrent(); \
  211. ThreadLockAlwaysWithPti(ptiCurrent, pwnd, &tlpwnd); \
  212. }
  213. #define ENDRECV_HWNDLOCK() ENDRECV_HWNDLOCK_(HWNDLOCK)
  214. #define ENDRECV_HWNDLOCKFF() ENDRECV_HWNDLOCK_FF(HWNDLOCK)
  215. #define BEGINRECV_HWNDLOCK_ND(type, err, hwnd) \
  216. type retval; \
  217. type errret = err; \
  218. PWND pwndND; \
  219. TL tlpwnd; \
  220. PTHREADINFO ptiCurrent; \
  221. EnterCrit(); \
  222. DBG_THREADLOCK_START(HWNDLOCK_ND) \
  223. if (((pwndND = ValidateHwnd((hwnd))) == NULL) || \
  224. (GETFNID(pwndND) == FNID_DESKTOP) || \
  225. (GETFNID(pwndND) == FNID_MESSAGEWND)) { \
  226. retval = errret; \
  227. goto errorexit2; \
  228. } \
  229. ptiCurrent = PtiCurrent(); \
  230. ThreadLockAlwaysWithPti(ptiCurrent, pwndND, &tlpwnd);
  231. #define ENDRECV_HWNDLOCK_ND() ENDRECV_HWNDLOCK_(HWNDLOCK_ND)
  232. /*
  233. * This macro performs normal HWNDLOCK stub handling and
  234. * optionally rejects desktop hwnd arguments for certain
  235. * APIs.
  236. */
  237. #define BEGINRECV_HWNDLOCK_COND_ND(type, err, hwnd, xpfnProc) \
  238. type retval; \
  239. type errret = err; \
  240. PWND pwndCondND; \
  241. TL tlpwnd; \
  242. PTHREADINFO ptiCurrent; \
  243. EnterCrit(); \
  244. DBG_THREADLOCK_START(HWNDLOCK_COND_ND) \
  245. if ((pwndCondND = ValidateHwnd(hwnd)) == NULL) { \
  246. retval = errret; \
  247. goto errorexit2; \
  248. } \
  249. switch(xpfnProc) { \
  250. case SFI_XXXDRAWMENUBAR: \
  251. case SFI_XXXENABLEWINDOW: \
  252. if ((GETFNID(pwndCondND) == FNID_DESKTOP) || \
  253. (GETFNID(pwndCondND) == FNID_MESSAGEWND)) { \
  254. retval = errret; \
  255. goto errorexit2; \
  256. } \
  257. break; \
  258. } \
  259. ptiCurrent = PtiCurrent(); \
  260. ThreadLockAlwaysWithPti(ptiCurrent, pwndCondND, &tlpwnd);
  261. #define ENDRECV_HWNDLOCK_COND_ND() ENDRECV_HWNDLOCK_(HWNDLOCK_COND_ND)
  262. #define BEGINRECV_HWNDLOCK_OPT(type, err, hwnd) \
  263. type retval; \
  264. type errret = err; \
  265. PWND pwnd; \
  266. TL tlpwnd; \
  267. PTHREADINFO ptiCurrent; \
  268. EnterCrit(); \
  269. DBG_THREADLOCK_START(HWNDLOCK_OPT) \
  270. if (hwnd) { \
  271. if ((pwnd = ValidateHwnd(hwnd)) == NULL) { \
  272. retval = errret; \
  273. goto errorexit2; \
  274. } \
  275. } else { \
  276. pwnd = NULL; \
  277. } \
  278. ptiCurrent = PtiCurrent(); \
  279. ThreadLockWithPti(ptiCurrent, pwnd, &tlpwnd);
  280. #define ENDRECV_HWNDLOCK_OPT() ENDRECV_HWNDLOCK_(HWNDLOCK_OPT)
  281. #define BEGINRECV_HWNDLOCK_VOID(hwnd) \
  282. PWND pwnd; \
  283. TL tlpwnd; \
  284. PTHREADINFO ptiCurrent; \
  285. EnterCrit(); \
  286. DBG_THREADLOCK_START(HWNDLOCK_VOID) \
  287. if ((pwnd = ValidateHwnd((hwnd))) == NULL) { \
  288. goto errorexit2; \
  289. } \
  290. ptiCurrent = PtiCurrent(); \
  291. ThreadLockAlwaysWithPti(ptiCurrent, pwnd, &tlpwnd);
  292. #define ISXPFNPROCINRANGE(range) \
  293. ((xpfnProc >= SFI_BEGINTRANSLATE ## range) && \
  294. (xpfnProc < SFI_ENDTRANSLATE ## range))
  295. #define VALIDATEXPFNPROC(range) \
  296. UserAssert(SFI_ENDTRANSLATETABLE == ulMaxSimpleCall); \
  297. UserAssert(SFI_ENDTRANSLATE ## range <= ulMaxSimpleCall); \
  298. if (!ISXPFNPROCINRANGE(range)) { \
  299. MSGERROR(0); \
  300. }
  301. #define CLEANUPRECV() \
  302. cleanupexit:
  303. #define ENDRECV_(s) \
  304. goto errorexit; \
  305. errorexit: \
  306. DBG_THREADLOCK_END(s) \
  307. LeaveCrit(); \
  308. return retval;
  309. #define ENDATOMICRECV_(s) \
  310. goto errorexit; \
  311. errorexit: \
  312. ENDATOMICCHECK() \
  313. DBG_THREADLOCK_END(s) \
  314. LeaveCrit(); \
  315. return retval;
  316. #define ENDRECV_NOCRIT() \
  317. goto errorexit; \
  318. errorexit: \
  319. return retval;
  320. #define ENDRECV_VOID_(s) \
  321. goto errorexit; \
  322. errorexit: \
  323. DBG_THREADLOCK_END(s) \
  324. LeaveCrit(); \
  325. return;
  326. #define ENDRECV_HWND_(s) \
  327. goto errorexit; \
  328. errorexit: \
  329. DBG_THREADLOCK_END(s) \
  330. LeaveCrit(); \
  331. return retval;
  332. #define ENDATOMICRECV_HWND_(s) \
  333. goto errorexit; \
  334. errorexit: \
  335. ENDATOMICCHECK() \
  336. DBG_THREADLOCK_END(s) \
  337. LeaveCrit(); \
  338. return retval;
  339. #define ENDRECV_HWNDLOCK_(s) \
  340. goto errorexit; \
  341. errorexit: \
  342. ThreadUnlock(&tlpwnd); \
  343. errorexit2: \
  344. DBG_THREADLOCK_END(s) \
  345. LeaveCrit(); \
  346. return retval;
  347. #define ENDRECV_HWNDLOCK_FF(s) \
  348. goto errorexit; \
  349. errorexit: \
  350. if (pwnd != PWND_BROADCAST) { \
  351. ThreadUnlock(&tlpwnd); \
  352. } \
  353. errorexit2: \
  354. DBG_THREADLOCK_END(s) \
  355. LeaveCrit(); \
  356. return retval;
  357. #define ENDRECV_HWNDLOCK_VOID() \
  358. goto errorexit; \
  359. errorexit: \
  360. ThreadUnlock(&tlpwnd); \
  361. errorexit2: \
  362. DBG_THREADLOCK_END(HWNDLOCK_VOID) \
  363. LeaveCrit(); \
  364. return;
  365. /*
  366. * MSGERROR - exit the stub with an error condition.
  367. * Parameters:
  368. * LastError (OPTIONAL):
  369. * == 0 If LastError is 0, the compiler will optimize away the call to
  370. * UserSetLastError(). The last error will not be set to zero!
  371. * != 0 If you want to SetLastError, provide a non-zero value.
  372. */
  373. #define MSGERROR(LastError) { \
  374. retval = errret; \
  375. if (LastError) { \
  376. UserSetLastError(LastError); \
  377. } \
  378. goto errorexit; }
  379. #define MSGERROR_VOID() { \
  380. goto errorexit; }
  381. /*
  382. * Same as MSGERROR but jumps to cleanup code instead of straight to the return
  383. */
  384. #define MSGERRORCLEANUP(LastError) { \
  385. retval = errret; \
  386. if (LastError) { \
  387. UserSetLastError(LastError); \
  388. } \
  389. goto cleanupexit; }
  390. #define StubExceptionHandler(fSetLastError) W32ExceptionHandler((fSetLastError), RIP_WARNING)
  391. #define TESTFLAGS(flags, mask) \
  392. if (((flags) & ~(mask)) != 0) { \
  393. RIPERR2(ERROR_INVALID_FLAGS, RIP_WARNING, "Invalid flags, %x & ~%x != 0 " #mask, \
  394. flags, mask); \
  395. MSGERROR(0); \
  396. }
  397. #define LIMITVALUE(value, limit, szText) \
  398. if ((UINT)(value) > (UINT)(limit)) { \
  399. RIPERR3(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid parameter, %d > %d in %s", \
  400. value, limit, szText); \
  401. MSGERROR(0); \
  402. }
  403. #define MESSAGECALL(api) \
  404. LRESULT NtUserfn ## api( \
  405. PWND pwnd, \
  406. UINT msg, \
  407. WPARAM wParam, \
  408. LPARAM lParam, \
  409. ULONG_PTR xParam, \
  410. DWORD xpfnProc, \
  411. BOOL bAnsi)
  412. #define BEGINRECV_MESSAGECALL(err) \
  413. LRESULT retval; \
  414. LRESULT errret = err; \
  415. PTHREADINFO ptiCurrent = PtiCurrent(); \
  416. CheckCritIn();
  417. #define ENDRECV_MESSAGECALL() \
  418. goto errorexit; \
  419. errorexit: \
  420. return retval;
  421. #define BEGINRECV_HOOKCALL() \
  422. LRESULT retval; \
  423. LRESULT errret = 0; \
  424. CheckCritIn();
  425. #define ENDRECV_HOOKCALL() \
  426. goto errorexit; \
  427. errorexit: \
  428. return retval;
  429. #define CALLPROC(p) FNID(p)
  430. /*
  431. * Validation macros
  432. */
  433. #define ValidateHWNDNoRIP(p,h) \
  434. if ((p = ValidateHwnd(h)) == NULL) \
  435. MSGERROR(0);
  436. #define ValidateHWND(p,h) \
  437. if ((p = ValidateHwnd(h)) == NULL) \
  438. MSGERROR(0);
  439. #define ValidateHWNDND(p,h) \
  440. if ( ((p = ValidateHwnd(h)) == NULL) || \
  441. (GETFNID(p) == FNID_DESKTOP) || \
  442. (GETFNID(p) == FNID_MESSAGEWND) \
  443. ) \
  444. MSGERROR(0);
  445. #define ValidateHWNDOPT(p,h) \
  446. if (h) { \
  447. if ((p = ValidateHwnd(h)) == NULL) \
  448. MSGERROR(0); \
  449. } else { \
  450. p = NULL; \
  451. }
  452. #define ValidateHWNDIA(p,h) \
  453. if (h != HWND_TOP && \
  454. h != HWND_BOTTOM && \
  455. h != HWND_TOPMOST && \
  456. h != HWND_NOTOPMOST) { \
  457. if ( ((p = ValidateHwnd(h)) == NULL) || \
  458. (GETFNID(p) == FNID_DESKTOP) || \
  459. (GETFNID(p) == FNID_MESSAGEWND) \
  460. ) \
  461. MSGERROR(0); \
  462. } else { \
  463. p = (PWND)h; \
  464. }
  465. #define ValidateHMENUOPT(p,h) \
  466. if (h) { \
  467. if ((p = ValidateHmenu(h)) == NULL) \
  468. MSGERROR(0); \
  469. } else { \
  470. p = NULL; \
  471. }
  472. #define ValidateHMENU(p,h) \
  473. if ((p = ValidateHmenu(h)) == NULL) \
  474. MSGERROR(0);
  475. #define ValidateHMENUMODIFY(p,h) \
  476. if ((p = ValidateHmenu(h)) == NULL) { \
  477. MSGERROR(0); \
  478. } else if (TestMF(p, MFDESKTOP)) { \
  479. RIPMSG1(RIP_WARNING, "ValidateHMENUMODIFY: Attempt to modify desktop menu:%#p", p); \
  480. MSGERROR(0); \
  481. }
  482. #define ValidateHMENUMODIFYCHECKLOCK(p,h) \
  483. if ((p = ValidateHmenu(h)) == NULL) { \
  484. MSGERROR(0); \
  485. } else if (TestMF(p, MFDESKTOP)) { \
  486. RIPMSG1(RIP_WARNING, "ValidateHMENUMODIFYCHECKLOCK: Attempt to modify desktop menu:%#p", p); \
  487. MSGERROR(0); \
  488. } else if (TestMF(p, MFREADONLY)) { \
  489. RIPMSG1(RIP_WARNING, "ValidateHMENUMODIFYCHECKLOCK: Attempt to modify RO menu: %#p", p); \
  490. MSGERROR(0); \
  491. }
  492. #define ValidateHACCEL(p,h) \
  493. if ((p = HMValidateHandle(h, TYPE_ACCELTABLE)) == NULL) \
  494. MSGERROR(0);
  495. #define ValidateHCURSOR(p,h) \
  496. if ((p = HMValidateHandle(h, TYPE_CURSOR)) == NULL) \
  497. MSGERROR(0);
  498. #define ValidateHCURSOROPT(p,h) \
  499. if (h) { \
  500. if ((p = HMValidateHandle(h, TYPE_CURSOR)) == NULL) \
  501. MSGERROR(0); \
  502. } else { \
  503. p = NULL; \
  504. }
  505. #define ValidateHICON(p,h) \
  506. if ((p = HMValidateHandle(h, TYPE_CURSOR)) == NULL) \
  507. MSGERROR(0);
  508. #define ValidateHHOOK(p,h) \
  509. if ((p = HMValidateHandle(h, TYPE_HOOK)) == NULL) \
  510. MSGERROR(0);
  511. #define ValidateHWINEVENTHOOK(p,h) \
  512. if ((p = HMValidateHandle(h, TYPE_WINEVENTHOOK)) == NULL) \
  513. MSGERROR(0);
  514. #define ValidateHDWP(p,h) \
  515. if ((p = HMValidateHandle(h, TYPE_SETWINDOWPOS)) == NULL) \
  516. MSGERROR(0);
  517. #define ValidateHMONITOR(p,h) \
  518. if ((p = ValidateHmonitor(h)) == NULL) \
  519. MSGERROR(0);
  520. #define ValidateHIMC(p,h) \
  521. if ((p = HMValidateHandle((HANDLE)h, TYPE_INPUTCONTEXT)) == NULL) \
  522. MSGERROR(0);
  523. #define ValidateHIMCOPT(p,h) \
  524. if (h) { \
  525. if ((p = HMValidateHandle((HANDLE)h, TYPE_INPUTCONTEXT)) == NULL) \
  526. MSGERROR(0); \
  527. } else { \
  528. p = NULL; \
  529. }
  530. #define ValidateIMMEnabled() \
  531. if (!IS_IME_ENABLED()) { \
  532. RIPERR0(ERROR_CALL_NOT_IMPLEMENTED, RIP_VERBOSE, "IME is disabled in this system."); \
  533. MSGERROR(0); \
  534. }
  535. #define ValidateIMMEnabledVOID() \
  536. if (!IS_IME_ENABLED()) { \
  537. RIPERR0(ERROR_CALL_NOT_IMPLEMENTED, RIP_VERBOSE, "IME is disabled in this system."); \
  538. MSGERROR_VOID(); \
  539. }
  540. #define DOWNCAST(type, value) ((type)(ULONG_PTR)(value))
  541. NTSTATUS
  542. NtUserRemoteConnect(
  543. IN PDOCONNECTDATA pDoConnectData,
  544. IN ULONG cchDisplayDriverNameLength,
  545. IN PWCHAR DisplayDriverName)
  546. {
  547. UINT chMax;
  548. DOCONNECTDATA CapturedDoConnectData;
  549. WCHAR CapturedDriverName[DR_DISPLAY_DRIVER_NAME_LENGTH + 1];
  550. BEGINRECVCSRSS(NTSTATUS, STATUS_UNSUCCESSFUL);
  551. if (!ISTS()) {
  552. errret = STATUS_ACCESS_DENIED;
  553. MSGERROR(0);
  554. }
  555. /*
  556. * Probe all read arguments.
  557. */
  558. try {
  559. CapturedDoConnectData = ProbeAndReadStructure(pDoConnectData, DOCONNECTDATA);
  560. ProbeForRead(DisplayDriverName, cchDisplayDriverNameLength, sizeof(WCHAR));
  561. UserAssert(DR_DISPLAY_DRIVER_NAME_LENGTH + 1 >= cchDisplayDriverNameLength);
  562. chMax = min((sizeof(CapturedDriverName)/sizeof(WCHAR)) - 1, cchDisplayDriverNameLength);
  563. wcsncpycch(CapturedDriverName, DisplayDriverName, chMax);
  564. CapturedDriverName[chMax] = 0;
  565. } except (StubExceptionHandler(FALSE)) {
  566. MSGERROR(0);
  567. }
  568. retval = RemoteConnect(&CapturedDoConnectData,
  569. chMax * sizeof(WCHAR),
  570. CapturedDriverName);
  571. TRACE("NtUserRemoteConnect");
  572. ENDRECVCSRSS();
  573. }
  574. NTSTATUS
  575. NtUserRemoteRedrawRectangle(
  576. IN WORD Left,
  577. IN WORD Top,
  578. IN WORD Right,
  579. IN WORD Bottom)
  580. {
  581. BEGINRECVCSRSS(NTSTATUS, STATUS_UNSUCCESSFUL);
  582. if (!ISTS()) {
  583. errret = STATUS_ACCESS_DENIED;
  584. MSGERROR(0);
  585. }
  586. retval = RemoteRedrawRectangle(Left, Top, Right, Bottom);
  587. TRACE("NtUserRemoteRedrawRectangle");
  588. ENDRECVCSRSS();
  589. }
  590. NTSTATUS
  591. NtUserRemoteRedrawScreen(
  592. VOID)
  593. {
  594. BEGINRECVCSRSS(NTSTATUS, STATUS_UNSUCCESSFUL);
  595. if (!ISTS()) {
  596. errret = STATUS_ACCESS_DENIED;
  597. MSGERROR(0);
  598. }
  599. /*
  600. * If there are any shadow connections, or it's not disconnected.
  601. */
  602. if (gnShadowers > 0 || gbConnected) {
  603. retval = RemoteRedrawScreen();
  604. } else {
  605. retval = STATUS_UNSUCCESSFUL;
  606. }
  607. TRACE("NtUserRemoteRedrawScreen");
  608. ENDRECVCSRSS();
  609. }
  610. NTSTATUS
  611. NtUserRemoteStopScreenUpdates(
  612. VOID)
  613. {
  614. BEGINRECVCSRSS(NTSTATUS, STATUS_UNSUCCESSFUL);
  615. if (!ISTS()) {
  616. errret = STATUS_ACCESS_DENIED;
  617. MSGERROR(0);
  618. }
  619. if (!gfSwitchInProgress) {
  620. retval = xxxRemoteStopScreenUpdates();
  621. } else {
  622. retval = STATUS_UNSUCCESSFUL;
  623. }
  624. TRACE("NtUserRemoteStopScreenUpdates");
  625. ENDRECVCSRSS();
  626. }
  627. NTSTATUS
  628. NtUserCtxDisplayIOCtl(
  629. IN ULONG DisplayIOCtlFlags,
  630. IN PUCHAR pDisplayIOCtlData,
  631. IN ULONG cbDisplayIOCtlData)
  632. {
  633. PUCHAR pCapturedDisplayIOCtlData = NULL;
  634. TL tlBuffer;
  635. PTHREADINFO ptiCurrent;
  636. BEGINRECVCSRSS(NTSTATUS, STATUS_UNSUCCESSFUL);
  637. if (!ISTS()) {
  638. errret = STATUS_ACCESS_DENIED;
  639. MSGERROR(0);
  640. }
  641. ptiCurrent = PtiCurrent();
  642. /*
  643. * Probe all read arguments.
  644. */
  645. try {
  646. ProbeForRead(pDisplayIOCtlData, cbDisplayIOCtlData, sizeof(BYTE));
  647. pCapturedDisplayIOCtlData = UserAllocPoolWithQuota(cbDisplayIOCtlData, TAG_SYSTEM);
  648. if (pCapturedDisplayIOCtlData) {
  649. ThreadLockPool(ptiCurrent, pCapturedDisplayIOCtlData, &tlBuffer);
  650. RtlCopyMemory(pCapturedDisplayIOCtlData, pDisplayIOCtlData, cbDisplayIOCtlData);
  651. } else {
  652. ExRaiseStatus(STATUS_NO_MEMORY);
  653. }
  654. } except (StubExceptionHandler(FALSE)) {
  655. MSGERRORCLEANUP(0);
  656. }
  657. retval = CtxDisplayIOCtl(DisplayIOCtlFlags,
  658. pCapturedDisplayIOCtlData,
  659. cbDisplayIOCtlData);
  660. CLEANUPRECV();
  661. if (pCapturedDisplayIOCtlData) {
  662. ThreadUnlockAndFreePool(ptiCurrent, &tlBuffer);
  663. }
  664. TRACE("NtUserCtxDisplayIOCtl");
  665. ENDRECVCSRSS();
  666. }
  667. UINT NtUserHardErrorControl(
  668. IN HARDERRORCONTROL dwCmd,
  669. IN HANDLE handle,
  670. OUT PDESKRESTOREDATA pdrdRestore OPTIONAL)
  671. {
  672. DESKRESTOREDATA drdRestore;
  673. BEGINRECVCSRSS(BOOL, HEC_ERROR);
  674. /*
  675. * Probe all arguments. Try block necessary even with CSRSS as
  676. * the calling process because it can incurr an in-page exception.
  677. */
  678. try {
  679. if (ARGUMENT_PRESENT(pdrdRestore)) {
  680. ProbeForRead(pdrdRestore, sizeof(DESKRESTOREDATA), sizeof(DWORD));
  681. RtlCopyMemory(&drdRestore, pdrdRestore, sizeof(DESKRESTOREDATA));
  682. }
  683. } except (StubExceptionHandler(FALSE)) {
  684. MSGERROR(0);
  685. }
  686. retval = xxxHardErrorControl(dwCmd, handle, (ARGUMENT_PRESENT(pdrdRestore))? &drdRestore : NULL);
  687. try {
  688. if (ARGUMENT_PRESENT(pdrdRestore)) {
  689. ProbeForWrite(pdrdRestore, sizeof(DESKRESTOREDATA), sizeof(DWORD));
  690. RtlCopyMemory(pdrdRestore, &drdRestore, sizeof(DESKRESTOREDATA));
  691. }
  692. } except (StubExceptionHandler(FALSE)) {
  693. MSGERROR(0);
  694. }
  695. TRACE("NtUserHardErrorControl");
  696. ENDRECVCSRSS();
  697. }
  698. BOOL NtUserGetObjectInformation( // API GetUserObjectInformationA/W
  699. IN HANDLE hObject,
  700. IN int nIndex,
  701. OUT PVOID pvInfo,
  702. IN DWORD nLength,
  703. OUT OPTIONAL LPDWORD pnLengthNeeded)
  704. {
  705. DWORD dwAlign;
  706. DWORD dwLocalLength;
  707. BEGINATOMICRECV(BOOL, FALSE);
  708. /*
  709. * Probe arguments
  710. */
  711. try {
  712. #if defined(_X86_)
  713. dwAlign = sizeof(BYTE);
  714. #else
  715. if (nIndex == UOI_FLAGS) {
  716. dwAlign = sizeof(DWORD);
  717. } else {
  718. dwAlign = sizeof(WCHAR);
  719. }
  720. #endif
  721. ProbeForWrite(pvInfo, nLength, dwAlign);
  722. if (ARGUMENT_PRESENT(pnLengthNeeded))
  723. ProbeForWriteUlong(pnLengthNeeded);
  724. } except (StubExceptionHandler(TRUE)) {
  725. MSGERROR(0);
  726. }
  727. /*
  728. * Make sure the handle doesn't get closed while we're playing with it.
  729. */
  730. SetHandleInUse(hObject);
  731. /*
  732. * pvInfo is client-side. GetUserObjectInformation
  733. * protects use of this pointer with try blocks.
  734. */
  735. retval = _GetUserObjectInformation(hObject,
  736. nIndex, pvInfo,
  737. nLength, &dwLocalLength);
  738. /*
  739. * OK, we're done with the handle.
  740. */
  741. SetHandleInUse(NULL);
  742. if (ARGUMENT_PRESENT(pnLengthNeeded)) {
  743. try {
  744. *pnLengthNeeded = dwLocalLength;
  745. } except (StubExceptionHandler(TRUE)) {
  746. MSGERROR(0);
  747. }
  748. }
  749. TRACE("NtUserGetObjectInformation");
  750. ENDATOMICRECV();
  751. }
  752. BOOL NtUserWin32PoolAllocationStats(
  753. IN LPDWORD parrTags,
  754. IN SIZE_T tagsCount,
  755. OUT SIZE_T* lpdwMaxMem,
  756. OUT SIZE_T* lpdwCrtMem,
  757. OUT LPDWORD lpdwMaxAlloc,
  758. OUT LPDWORD lpdwCrtAlloc)
  759. {
  760. #ifdef POOL_INSTR_API
  761. SIZE_T dwMaxMem, dwCrtMem;
  762. DWORD dwMaxAlloc, dwCrtAlloc;
  763. BEGINRECV(BOOL, FALSE);
  764. retval = _Win32PoolAllocationStats(parrTags,
  765. tagsCount,
  766. &dwMaxMem,
  767. &dwCrtMem,
  768. &dwMaxAlloc,
  769. &dwCrtAlloc);
  770. /*
  771. * Probe and copy
  772. */
  773. try {
  774. if (lpdwMaxMem != NULL) {
  775. ProbeForWrite(lpdwMaxMem, sizeof(SIZE_T), sizeof(DWORD));
  776. *lpdwMaxMem = dwMaxMem;
  777. }
  778. if (lpdwCrtMem != NULL) {
  779. ProbeForWrite(lpdwCrtMem, sizeof(SIZE_T), sizeof(DWORD));
  780. *lpdwCrtMem = dwCrtMem;
  781. }
  782. if (lpdwMaxAlloc != NULL) {
  783. ProbeForWrite(lpdwMaxAlloc, sizeof(DWORD), sizeof(DWORD));
  784. *lpdwMaxAlloc = dwMaxAlloc;
  785. }
  786. if (lpdwCrtAlloc != NULL) {
  787. ProbeForWrite(lpdwCrtAlloc, sizeof(DWORD), sizeof(DWORD));
  788. *lpdwCrtAlloc = dwCrtAlloc;
  789. }
  790. } except (StubExceptionHandler(FALSE)) {
  791. MSGERROR(0);
  792. }
  793. TRACE("NtUserWin32PoolAllocationStats");
  794. ENDRECV();
  795. #else
  796. UNREFERENCED_PARAMETER(parrTags);
  797. UNREFERENCED_PARAMETER(tagsCount);
  798. UNREFERENCED_PARAMETER(lpdwMaxMem);
  799. UNREFERENCED_PARAMETER(lpdwCrtMem);
  800. UNREFERENCED_PARAMETER(lpdwMaxAlloc);
  801. UNREFERENCED_PARAMETER(lpdwCrtAlloc);
  802. return FALSE;
  803. #endif // POOL_INSTR_API
  804. }
  805. #if DBG
  806. VOID NtUserDbgWin32HeapFail( // private DbgWin32HeapFail
  807. IN DWORD dwFlags,
  808. IN BOOL bFail)
  809. {
  810. BEGINRECV_VOID();
  811. if ((dwFlags | WHF_VALID) != WHF_VALID) {
  812. RIPMSG1(RIP_WARNING, "Invalid flags for DbgWin32HeapFail %x", dwFlags);
  813. MSGERROR_VOID();
  814. }
  815. Win32HeapFailAllocations(bFail);
  816. TRACEVOID("NtUserDbgWin32HeapFail");
  817. ENDRECV_VOID();
  818. }
  819. DWORD NtUserDbgWin32HeapStat( // private DbgWin32HeapStat
  820. PDBGHEAPSTAT phs,
  821. DWORD dwLen)
  822. {
  823. extern DWORD Win32HeapStat(PDBGHEAPSTAT phs, DWORD dwLen, BOOL bTagsAreShift);
  824. DBGHEAPSTAT localHS[30];
  825. BEGINRECV(DWORD, 0);
  826. LIMITVALUE(dwLen, sizeof(localHS), "DbgWin32HeapStat");
  827. try{
  828. ProbeForRead(phs, dwLen, CHARALIGN);
  829. RtlCopyMemory(localHS, phs, dwLen);
  830. } except (StubExceptionHandler(FALSE)) {
  831. MSGERROR(0);
  832. }
  833. retval = Win32HeapStat(localHS, dwLen, FALSE);
  834. try {
  835. ProbeForWrite(phs, dwLen, CHARALIGN);
  836. RtlCopyMemory(phs, localHS, dwLen);
  837. } except (StubExceptionHandler(FALSE)) {
  838. }
  839. TRACE("NtUserDbgWin32HeapStat");
  840. ENDRECV();
  841. }
  842. #endif // DBG
  843. BOOL NtUserSetObjectInformation( // API SetUserObjectInformationA/W
  844. IN HANDLE hObject,
  845. IN int nIndex,
  846. IN PVOID pvInfo,
  847. IN DWORD nLength)
  848. {
  849. BEGINATOMICRECV(BOOL, FALSE);
  850. /*
  851. * Probe arguments
  852. */
  853. try {
  854. ProbeForRead(pvInfo, nLength, DATAALIGN);
  855. } except (StubExceptionHandler(TRUE)) {
  856. MSGERROR(0);
  857. }
  858. /*
  859. * Make sure the handle doesn't get closed while we're playing with it.
  860. */
  861. SetHandleInUse(hObject);
  862. /*
  863. * pvInfo is client-side. SetUserObjectInformation
  864. * protects use of this pointer with try blocks.
  865. */
  866. retval = _SetUserObjectInformation(hObject,
  867. nIndex, pvInfo, nLength);
  868. /*
  869. * OK, we're done with the handle.
  870. */
  871. SetHandleInUse(NULL);
  872. TRACE("NtUserSetObjectInformation");
  873. ENDATOMICRECV();
  874. }
  875. NTSTATUS NtUserConsoleControl( // private NtUserConsoleControl
  876. IN CONSOLECONTROL ConsoleCommand,
  877. IN PVOID ConsoleInformation,
  878. IN DWORD ConsoleInformationLength)
  879. {
  880. union {
  881. CONSOLEDESKTOPCONSOLETHREAD DesktopConsole;
  882. ATOM ClassAtom;
  883. CONSOLE_PROCESS_INFO ProcessInfo;
  884. RECT rc;
  885. HPALETTE hPalette;
  886. CONSOLEWINDOWSTATIONPROCESS WindowStationConsole;
  887. CONSOLE_REGISTER_CONSOLEIME IMEConsole;
  888. CONSOLE_FULLSCREEN_SWITCH FullScreenConsole;
  889. CONSOLE_CARET_INFO CaretInfo;
  890. } ConsoleInformationUnion;
  891. PVOID pConsoleInformation = &ConsoleInformationUnion;
  892. BEGINRECVCSRSS(NTSTATUS, STATUS_UNSUCCESSFUL);
  893. if (ConsoleInformationLength > sizeof(ConsoleInformationUnion)) {
  894. FRE_RIPMSG2(
  895. RIP_ERROR,
  896. "ConsoleInformationLength: %x is greater than union size: %x.",
  897. ConsoleInformationLength,
  898. sizeof(ConsoleInformationUnion));
  899. }
  900. /*
  901. * Probe all arguments. Try block necessary even with CSRSS as
  902. * the calling process because it can incurr an in-page exception.
  903. */
  904. try {
  905. if (ARGUMENT_PRESENT(ConsoleInformation)) {
  906. ProbeForRead(ConsoleInformation, ConsoleInformationLength, sizeof(ATOM));
  907. RtlCopyMemory(pConsoleInformation, ConsoleInformation, ConsoleInformationLength);
  908. } else {
  909. pConsoleInformation = NULL;
  910. }
  911. } except (StubExceptionHandler(FALSE)) {
  912. MSGERROR(0);
  913. }
  914. retval = xxxConsoleControl(
  915. ConsoleCommand,
  916. pConsoleInformation,
  917. ConsoleInformationLength);
  918. try {
  919. if (ARGUMENT_PRESENT(ConsoleInformation)) {
  920. ProbeForWrite(ConsoleInformation, ConsoleInformationLength, sizeof(ATOM));
  921. RtlCopyMemory(ConsoleInformation, pConsoleInformation, ConsoleInformationLength);
  922. }
  923. } except (StubExceptionHandler(FALSE)) {
  924. MSGERROR(0);
  925. }
  926. TRACE("NtUserConsoleControl");
  927. ENDRECVCSRSS();
  928. }
  929. HWINSTA NtUserCreateWindowStation( // API CreateWindowStationA/W
  930. IN POBJECT_ATTRIBUTES pObja,
  931. IN ACCESS_MASK amRequest,
  932. IN HANDLE hKbdLayoutFile,
  933. IN DWORD offTable,
  934. IN PKBDTABLE_MULTI_INTERNAL pKbdTableMulti,
  935. IN PUNICODE_STRING pstrKLID,
  936. UINT uKbdInputLocale)
  937. {
  938. NTSTATUS Status;
  939. OBJECT_ATTRIBUTES CapturedAttributes;
  940. SECURITY_QUALITY_OF_SERVICE qosCaptured;
  941. PSECURITY_DESCRIPTOR psdCaptured = NULL;
  942. LUID luidService;
  943. UNICODE_STRING strWinSta;
  944. UNICODE_STRING strKLID;
  945. KBDTABLE_MULTI_INTERNAL kbdTableMulti;
  946. WCHAR awchName[MAX_SESSION_PATH];
  947. WCHAR awchKF[KL_NAMELENGTH];
  948. UINT chMax;
  949. KPROCESSOR_MODE OwnershipMode;
  950. BEGINRECV(HWINSTA, NULL);
  951. /*
  952. * Set status so we can clean up in case of failure
  953. */
  954. Status = STATUS_SUCCESS;
  955. try {
  956. /*
  957. * Probe and capture the ??? string
  958. */
  959. strKLID = ProbeAndReadUnicodeString(pstrKLID);
  960. ProbeForReadUnicodeStringBuffer(strKLID);
  961. chMax = min(sizeof(awchKF) - sizeof(WCHAR), strKLID.Length) / sizeof(WCHAR);
  962. wcsncpycch(awchKF, strKLID.Buffer, chMax);
  963. awchKF[chMax] = 0;
  964. kbdTableMulti = ProbeAndReadStructure(pKbdTableMulti, KBDTABLE_MULTI_INTERNAL);
  965. if (kbdTableMulti.multi.nTables >= KBDTABLE_MULTI_MAX) {
  966. RIPMSG1(RIP_WARNING, "NtUserCreateWindowStation: kbdTableMulti.multi.nTables too big: %x", kbdTableMulti.multi.nTables);
  967. MSGERROR(ERROR_INVALID_PARAMETER);
  968. }
  969. /*
  970. * Probe and capture the object attributes
  971. */
  972. CapturedAttributes = ProbeAndReadStructure(pObja, OBJECT_ATTRIBUTES);
  973. /*
  974. * Probe and capture all other components of the object attributes.
  975. */
  976. if (CapturedAttributes.ObjectName == NULL && CapturedAttributes.RootDirectory == NULL) {
  977. /*
  978. * Use the logon authentication id to form the windowstation
  979. * name.
  980. */
  981. Status = GetProcessLuid(NULL, &luidService);
  982. if (NT_SUCCESS(Status)) {
  983. swprintf(awchName, L"%ws\\Service-0x%x-%x$",
  984. szWindowStationDirectory,
  985. luidService.HighPart, luidService.LowPart);
  986. RtlInitUnicodeString(&strWinSta, awchName);
  987. CapturedAttributes.ObjectName = &strWinSta;
  988. }
  989. OwnershipMode = KernelMode;
  990. } else {
  991. strWinSta = ProbeAndReadUnicodeString(CapturedAttributes.ObjectName);
  992. ProbeForReadUnicodeStringBuffer(strWinSta);
  993. /*
  994. * Use the StaticUnicodeBuffer on the TEB as the buffer for the
  995. * object name. Even if this is client side and we pass
  996. * KernelMode to the Ob call in _OpenWindowStation this is
  997. * safe because the TEB is not going to go away during this
  998. * call. The worst it can happen is to have the buffer in the
  999. * TEB trashed.
  1000. */
  1001. strWinSta.Length = min(strWinSta.Length, STATIC_UNICODE_BUFFER_LENGTH * sizeof(WCHAR));
  1002. RtlCopyMemory(NtCurrentTeb()->StaticUnicodeBuffer,
  1003. strWinSta.Buffer,
  1004. strWinSta.Length);
  1005. strWinSta.Buffer = NtCurrentTeb()->StaticUnicodeBuffer;
  1006. CapturedAttributes.ObjectName = &strWinSta;
  1007. OwnershipMode = UserMode;
  1008. }
  1009. if (CapturedAttributes.SecurityQualityOfService) {
  1010. PSECURITY_QUALITY_OF_SERVICE pqos;
  1011. pqos = CapturedAttributes.SecurityQualityOfService;
  1012. qosCaptured = ProbeAndReadStructure(pqos, SECURITY_QUALITY_OF_SERVICE);
  1013. CapturedAttributes.SecurityQualityOfService = &qosCaptured;
  1014. }
  1015. if (NT_SUCCESS(Status) && CapturedAttributes.SecurityDescriptor != NULL) {
  1016. Status = SeCaptureSecurityDescriptor(
  1017. CapturedAttributes.SecurityDescriptor,
  1018. UserMode,
  1019. PagedPool,
  1020. FALSE,
  1021. &psdCaptured);
  1022. if (!NT_SUCCESS(Status)) {
  1023. psdCaptured = NULL;
  1024. }
  1025. CapturedAttributes.SecurityDescriptor = psdCaptured;
  1026. }
  1027. } except (StubExceptionHandler(FALSE)) {
  1028. Status = GetExceptionCode();
  1029. }
  1030. if (!NT_SUCCESS(Status)) {
  1031. MSGERRORCLEANUP(RtlNtStatusToDosError(Status));
  1032. }
  1033. /*
  1034. * Create the windowstation and return a kernel handle.
  1035. */
  1036. retval = xxxCreateWindowStation(&CapturedAttributes,
  1037. OwnershipMode,
  1038. amRequest,
  1039. hKbdLayoutFile,
  1040. offTable,
  1041. &kbdTableMulti,
  1042. awchKF,
  1043. uKbdInputLocale);
  1044. CLEANUPRECV();
  1045. /*
  1046. * Release captured security descriptor.
  1047. */
  1048. if (psdCaptured != NULL) {
  1049. SeReleaseSecurityDescriptor(psdCaptured, UserMode, FALSE);
  1050. }
  1051. TRACE("NtUserCreateWindowStation");
  1052. ENDRECV();
  1053. }
  1054. HWINSTA NtUserOpenWindowStation(
  1055. IN OUT POBJECT_ATTRIBUTES pObja,
  1056. IN ACCESS_MASK amRequest)
  1057. {
  1058. NTSTATUS Status;
  1059. LUID luidService;
  1060. WCHAR awchName[sizeof(L"Service-0x0000-0000$") / sizeof(WCHAR)];
  1061. OBJECT_ATTRIBUTES Obja;
  1062. UNICODE_STRING ObjectName;
  1063. BEGINRECV(HWINSTA, NULL);
  1064. /*
  1065. * NT Bug 387849: We want to allow the caller to pass in a "template" to
  1066. * be filled in for the Service windowstation. So, we need to walk
  1067. * through the pObja structure and check the string out, replacing it
  1068. * with the real object name if necessary.
  1069. *
  1070. * It is VERY important that we pass the pObja object to the executive
  1071. * (through _OpenWindowStation) and not the Obja object. This is
  1072. * because we will request UserMode for this object, and the executive
  1073. * will check that it is actually getting a user-mode address.
  1074. *
  1075. * We will still make a copy of the structures to manipulate while we
  1076. * are walking everything so that we don't need to worry about the rug
  1077. * being removed from beneath us. The executive will do its own checking.
  1078. */
  1079. try {
  1080. /*
  1081. * Probe the object attributes. We need to be able to read the
  1082. * OBJECT_ATTRIBUTES and to write the ObjectName (UNICODE_STRING).
  1083. */
  1084. Obja = ProbeAndReadStructure(pObja, OBJECT_ATTRIBUTES);
  1085. ProbeForWrite(Obja.ObjectName, sizeof(*(Obja.ObjectName)), DATAALIGN);
  1086. ObjectName = ProbeAndReadUnicodeString(Obja.ObjectName);
  1087. /*
  1088. * If we are trying to open the NULL or "" WindowStation, remap this
  1089. * benign name to Service-0x????-????$.
  1090. */
  1091. if (Obja.RootDirectory != NULL &&
  1092. ObjectName.Buffer != NULL &&
  1093. ObjectName.MaximumLength == sizeof(awchName) &&
  1094. ObjectName.Length == (sizeof(awchName) - sizeof(UNICODE_NULL))) {
  1095. /*
  1096. * Use the logon authentication id to form the windowstation
  1097. * name. Put this in the user's buffer since we were the one
  1098. * who allocated it in _OpenWindowStation.
  1099. */
  1100. ProbeForWrite(ObjectName.Buffer, ObjectName.MaximumLength, CHARALIGN);
  1101. if (!_wcsicmp(ObjectName.Buffer, L"Service-0x0000-0000$")) {
  1102. Status = GetProcessLuid(NULL, &luidService);
  1103. if (NT_SUCCESS(Status)) {
  1104. swprintf(ObjectName.Buffer,
  1105. L"Service-0x%x-%x$",
  1106. luidService.HighPart,
  1107. luidService.LowPart);
  1108. /*
  1109. * We need to re-initialize the string to get the counted
  1110. * length correct. Otherwise the hashing function used
  1111. * by ObpLookupDirectoryEntry will fail.
  1112. */
  1113. RtlInitUnicodeString(Obja.ObjectName, ObjectName.Buffer);
  1114. }
  1115. }
  1116. }
  1117. } except (StubExceptionHandler(TRUE)) {
  1118. MSGERROR(0);
  1119. }
  1120. /*
  1121. * Open the WindowStation.
  1122. */
  1123. retval = _OpenWindowStation(pObja, amRequest, UserMode);
  1124. TRACE("NtUserOpenWindowStation");
  1125. ENDRECV();
  1126. }
  1127. BOOL NtUserCloseWindowStation(
  1128. IN HWINSTA hwinsta)
  1129. {
  1130. PWINDOWSTATION pwinsta;
  1131. NTSTATUS Status;
  1132. BEGINRECV(BOOL, FALSE);
  1133. retval = FALSE;
  1134. Status = ValidateHwinsta(hwinsta, UserMode, 0, &pwinsta);
  1135. if (NT_SUCCESS(Status)) {
  1136. retval = _CloseWindowStation(hwinsta);
  1137. ObDereferenceObject(pwinsta);
  1138. }
  1139. TRACE("NtUserCloseWindowStation");
  1140. ENDRECV();
  1141. }
  1142. BOOL NtUserSetProcessWindowStation(
  1143. IN HWINSTA hwinsta)
  1144. {
  1145. BEGINRECV(BOOL, FALSE);
  1146. retval = NT_SUCCESS(_SetProcessWindowStation(hwinsta, UserMode));
  1147. TRACE("NtUserSetProcessWindowStation");
  1148. ENDRECV();
  1149. }
  1150. HWINSTA NtUserGetProcessWindowStation(
  1151. VOID)
  1152. {
  1153. BEGINRECV_SHARED(HWINSTA, NULL);
  1154. _GetProcessWindowStation(&retval);
  1155. TRACE("NtUserGetProcessWindowStation");
  1156. ENDRECV_SHARED();
  1157. }
  1158. BOOL NtUserLockWorkStation(
  1159. VOID)
  1160. {
  1161. BEGINRECV(BOOL, FALSE);
  1162. retval = _LockWorkStation();
  1163. TRACE("NtUserLockWorkStation");
  1164. ENDRECV();
  1165. }
  1166. HDESK NtUserCreateDesktop( // API CreateDesktopA/W
  1167. IN POBJECT_ATTRIBUTES pObja,
  1168. IN PUNICODE_STRING pstrDevice,
  1169. IN LPDEVMODEW pDevmode,
  1170. IN DWORD dwFlags,
  1171. IN ACCESS_MASK amRequest)
  1172. {
  1173. BEGINRECV(HDESK, NULL);
  1174. /*
  1175. * Fail this call for restricted threads.
  1176. */
  1177. if (IS_CURRENT_THREAD_RESTRICTED(JOB_OBJECT_UILIMIT_DESKTOP)) {
  1178. RIPMSGF0(RIP_WARNING, "Failed for restricted thread");
  1179. MSGERROR(ERROR_ACCESS_DENIED);
  1180. }
  1181. /*
  1182. * Validate the dwFlags parameter. The only externally visible flag is
  1183. * DF_ALLOWOTHERACCOUNTHOOK.
  1184. */
  1185. if (dwFlags && dwFlags != DF_ALLOWOTHERACCOUNTHOOK) {
  1186. RIPMSGF1(RIP_WARNING, "Invalid dwFlags 0x%x", dwFlags);
  1187. MSGERROR(ERROR_INVALID_PARAMETER);
  1188. }
  1189. /*
  1190. * Probe arguments.
  1191. */
  1192. try {
  1193. ProbeForRead(pObja, sizeof(*pObja), sizeof(DWORD));
  1194. } except (StubExceptionHandler(TRUE)) {
  1195. MSGERROR(0);
  1196. }
  1197. /*
  1198. * pObja, pDevmode, and pstrDevice are all client side addresses.
  1199. *
  1200. * pstrDevice and pDevmode are put into the Context info, and they are
  1201. * used by GDI (where thay are captured before use).
  1202. */
  1203. retval = xxxCreateDesktop(pObja,
  1204. UserMode,
  1205. pstrDevice,
  1206. pDevmode,
  1207. dwFlags,
  1208. amRequest);
  1209. TRACE("NtUserCreateDesktop");
  1210. ENDRECV();
  1211. }
  1212. HDESK NtUserOpenDesktop(
  1213. IN POBJECT_ATTRIBUTES pObja,
  1214. IN DWORD dwFlags,
  1215. IN ACCESS_MASK amRequest)
  1216. {
  1217. BOOL bShutDown;
  1218. BEGINRECV(HDESK, NULL);
  1219. retval = _OpenDesktop(pObja, UserMode, dwFlags, amRequest, &bShutDown);
  1220. TRACE("NtUserOpenDesktop");
  1221. ENDRECV();
  1222. }
  1223. HDESK NtUserOpenInputDesktop(
  1224. IN DWORD dwFlags,
  1225. IN BOOL fInherit,
  1226. IN DWORD amRequest)
  1227. {
  1228. HWINSTA hwinsta;
  1229. PWINDOWSTATION pwinsta;
  1230. PDESKTOP pdesk;
  1231. NTSTATUS Status;
  1232. BEGINRECV(HDESK, NULL);
  1233. if (grpdeskRitInput == NULL) {
  1234. MSGERROR(ERROR_OPEN_FAILED);
  1235. } else {
  1236. pwinsta = _GetProcessWindowStation(&hwinsta);
  1237. if (pwinsta == NULL) {
  1238. MSGERROR(ERROR_ACCESS_DENIED);
  1239. }
  1240. if (pwinsta->dwWSF_Flags & WSF_NOIO) {
  1241. MSGERROR(ERROR_INVALID_FUNCTION);
  1242. } else {
  1243. /*
  1244. * We should never return the 'Disconnect' desktop to an app. We
  1245. * should instead return the desktop that we will restore to
  1246. * from the Disconnect desktop.
  1247. */
  1248. pdesk = (gbDesktopLocked ? gspdeskShouldBeForeground : grpdeskRitInput);
  1249. if (pdesk == NULL) {
  1250. MSGERROR(ERROR_OPEN_FAILED);
  1251. }
  1252. /*
  1253. * Require read/write access
  1254. */
  1255. amRequest |= DESKTOP_READOBJECTS | DESKTOP_WRITEOBJECTS;
  1256. Status = ObOpenObjectByPointer(
  1257. pdesk,
  1258. fInherit ? OBJ_INHERIT : 0,
  1259. NULL,
  1260. amRequest,
  1261. *ExDesktopObjectType,
  1262. UserMode,
  1263. &retval);
  1264. if (NT_SUCCESS(Status)) {
  1265. BOOL bShutDown;
  1266. /*
  1267. * Complete the desktop open
  1268. */
  1269. if (!OpenDesktopCompletion(pdesk, retval, dwFlags, &bShutDown)) {
  1270. CloseProtectedHandle(retval);
  1271. retval = NULL;
  1272. } else {
  1273. SetHandleFlag(retval, HF_PROTECTED, TRUE);
  1274. }
  1275. } else {
  1276. MSGERROR(RtlNtStatusToDosError(Status));
  1277. }
  1278. }
  1279. }
  1280. TRACE("NtUserOpenInputDesktop");
  1281. ENDRECV();
  1282. }
  1283. NTSTATUS NtUserResolveDesktopForWOW ( // WOW ResolveDesktopForWOW
  1284. IN OUT PUNICODE_STRING pstrDesktop)
  1285. {
  1286. UNICODE_STRING strDesktop, strDesktop2;
  1287. PTHREADINFO ptiCurrent;
  1288. TL tlBuffer;
  1289. LPWSTR lpBuffer = NULL;
  1290. BOOL fFreeBuffer = FALSE;
  1291. BEGINRECV(NTSTATUS, STATUS_UNSUCCESSFUL);
  1292. retval = STATUS_SUCCESS;
  1293. ptiCurrent = PtiCurrent();
  1294. /*
  1295. * Probe arguments
  1296. */
  1297. try {
  1298. strDesktop = ProbeAndReadUnicodeString(pstrDesktop);
  1299. ProbeForReadUnicodeStringFullBuffer(strDesktop);
  1300. RtlCopyMemory(&strDesktop2, &strDesktop, sizeof(strDesktop));
  1301. if (strDesktop.MaximumLength > 0) {
  1302. PWSTR pszCapture = strDesktop.Buffer;
  1303. strDesktop.Buffer = UserAllocPoolWithQuota(strDesktop.MaximumLength, TAG_TEXT2);
  1304. if (strDesktop.Buffer) {
  1305. fFreeBuffer = TRUE;
  1306. ThreadLockPool(ptiCurrent, strDesktop.Buffer, &tlBuffer);
  1307. RtlCopyMemory(strDesktop.Buffer, pszCapture, strDesktop.Length);
  1308. } else {
  1309. ExRaiseStatus(STATUS_NO_MEMORY);
  1310. }
  1311. } else {
  1312. strDesktop.Buffer = NULL;
  1313. }
  1314. } except (StubExceptionHandler(FALSE)) {
  1315. MSGERRORCLEANUP(0);
  1316. }
  1317. retval = xxxResolveDesktopForWOW(&strDesktop);
  1318. if (NT_SUCCESS(retval)) {
  1319. try {
  1320. /*
  1321. * The string structure at pstrDesktop could have changed
  1322. * so we will ignore it and drop the one we have already
  1323. * probed down on top of it. We have already performed the
  1324. * ResolveDesktopForWOW action, so we should not return an
  1325. * error if this copy fails.
  1326. */
  1327. RtlCopyUnicodeString(&strDesktop2, &strDesktop);
  1328. RtlCopyMemory(pstrDesktop, &strDesktop2, sizeof(strDesktop2));
  1329. } except (StubExceptionHandler(FALSE)) {
  1330. }
  1331. }
  1332. CLEANUPRECV();
  1333. if (fFreeBuffer)
  1334. ThreadUnlockAndFreePool(ptiCurrent, &tlBuffer);
  1335. TRACE("NtUserResolveDesktopForWOW");
  1336. ENDRECV();
  1337. }
  1338. HDESK NtUserResolveDesktop(
  1339. IN HANDLE hProcess,
  1340. IN PUNICODE_STRING pstrDesktop,
  1341. IN BOOL fInherit,
  1342. OUT HWINSTA *phwinsta)
  1343. {
  1344. UNICODE_STRING strDesktop;
  1345. HWINSTA hwinsta = NULL;
  1346. PTHREADINFO pti;
  1347. TL tlBuffer;
  1348. BOOL fFreeBuffer = FALSE;
  1349. BOOL bShutDown = FALSE;
  1350. BEGINRECV(HDESK, NULL);
  1351. pti = PtiCurrent();
  1352. /*
  1353. * Probe and capture desktop path
  1354. */
  1355. try {
  1356. strDesktop = ProbeAndReadUnicodeString(pstrDesktop);
  1357. if (strDesktop.Length > 0) {
  1358. PWSTR pszCapture = strDesktop.Buffer;
  1359. ProbeForReadUnicodeStringBuffer(strDesktop);
  1360. strDesktop.Buffer = UserAllocPoolWithQuota(strDesktop.Length, TAG_TEXT2);
  1361. if (strDesktop.Buffer) {
  1362. fFreeBuffer = TRUE;
  1363. ThreadLockPool(pti, strDesktop.Buffer, &tlBuffer);
  1364. RtlCopyMemory(strDesktop.Buffer, pszCapture, strDesktop.Length);
  1365. } else {
  1366. ExRaiseStatus(STATUS_NO_MEMORY);
  1367. }
  1368. } else {
  1369. strDesktop.Buffer = NULL;
  1370. }
  1371. } except (StubExceptionHandler(TRUE)) {
  1372. MSGERRORCLEANUP(0);
  1373. }
  1374. retval = xxxResolveDesktop(hProcess, &strDesktop, &hwinsta,
  1375. fInherit, &bShutDown);
  1376. CLEANUPRECV();
  1377. if (fFreeBuffer)
  1378. ThreadUnlockAndFreePool(pti, &tlBuffer);
  1379. if (retval != NULL) {
  1380. try {
  1381. ProbeAndWriteHandle((PHANDLE)phwinsta, hwinsta);
  1382. } except (StubExceptionHandler(TRUE)) {
  1383. xxxCloseDesktop(retval, KernelMode);
  1384. if (hwinsta) {
  1385. _CloseWindowStation(hwinsta);
  1386. }
  1387. MSGERROR(0);
  1388. }
  1389. } else {
  1390. UserAssert(hwinsta == NULL);
  1391. }
  1392. TRACE("NtUserResolveDesktop");
  1393. ENDRECV();
  1394. }
  1395. BOOL NtUserCloseDesktop(
  1396. IN HDESK hdesk)
  1397. {
  1398. BEGINRECV(BOOL, FALSE);
  1399. retval = xxxCloseDesktop(hdesk, UserMode);
  1400. TRACE("NtUserCloseDesktop");
  1401. ENDRECV();
  1402. }
  1403. BOOL NtUserSetThreadDesktop(
  1404. IN HDESK hdesk)
  1405. {
  1406. PDESKTOP pdesk = NULL;
  1407. NTSTATUS Status = STATUS_SUCCESS;
  1408. BEGINRECV(BOOL, FALSE);
  1409. Status = ValidateHdesk(hdesk, UserMode, 0, &pdesk);
  1410. if (NT_SUCCESS(Status)) {
  1411. retval = xxxSetThreadDesktop(hdesk, pdesk);
  1412. LogDesktop(pdesk, LD_DEREF_VALIDATE_HDESK1, FALSE, (ULONG_PTR)PtiCurrent());
  1413. ObDereferenceObject(pdesk);
  1414. } else if (hdesk == NULL && PsGetCurrentProcess() == gpepCSRSS) {
  1415. retval = xxxSetThreadDesktop(NULL, NULL);
  1416. } else {
  1417. retval = FALSE;
  1418. }
  1419. TRACE("NtUserSetThreadDesktop");
  1420. ENDRECV();
  1421. }
  1422. HDESK NtUserGetThreadDesktop(
  1423. IN DWORD dwThreadId,
  1424. IN HDESK hdeskConsole)
  1425. {
  1426. BEGINRECV_SHARED(HDESK, NULL);
  1427. retval = xxxGetThreadDesktop(dwThreadId, hdeskConsole, UserMode);
  1428. TRACE("NtUserGetThreadDesktop");
  1429. ENDRECV_SHARED();
  1430. }
  1431. BOOL NtUserSwitchDesktop(
  1432. IN HDESK hdesk)
  1433. {
  1434. PDESKTOP pdesk;
  1435. TL tlpdesk;
  1436. PTHREADINFO ptiCurrent;
  1437. NTSTATUS Status;
  1438. BEGINRECV(BOOL, FALSE);
  1439. ptiCurrent = PtiCurrent();
  1440. /*
  1441. * Fail this call for restricted threads
  1442. */
  1443. if (IS_CURRENT_THREAD_RESTRICTED(JOB_OBJECT_UILIMIT_DESKTOP)) {
  1444. RIPMSG0(RIP_WARNING, "NtUserSwitchDesktop failed for restricted thread");
  1445. MSGERROR(0);
  1446. }
  1447. Status = ValidateHdesk(hdesk, UserMode, DESKTOP_SWITCHDESKTOP, &pdesk);
  1448. if (NT_SUCCESS(Status)) {
  1449. if (pdesk->rpwinstaParent->dwWSF_Flags & WSF_NOIO) {
  1450. LogDesktop(pdesk, LD_DEREF_VALIDATE_HDESK2, FALSE, (ULONG_PTR)PtiCurrent());
  1451. ObDereferenceObject(pdesk);
  1452. RIPERR0(ERROR_ACCESS_DENIED, RIP_VERBOSE, "");
  1453. retval = FALSE;
  1454. } else {
  1455. ThreadLockDesktop(ptiCurrent, pdesk, &tlpdesk, LDLT_FN_NTUSERSWITCHDESKTOP);
  1456. LogDesktop(pdesk, LD_DEREF_VALIDATE_HDESK3, FALSE, (ULONG_PTR)PtiCurrent());
  1457. ObDereferenceObject(pdesk);
  1458. retval = xxxSwitchDesktop(NULL, pdesk, 0);
  1459. ThreadUnlockDesktop(ptiCurrent, &tlpdesk, LDUT_FN_NTUSERSWITCHDESKTOP);
  1460. }
  1461. } else {
  1462. retval = FALSE;
  1463. }
  1464. TRACE("NtUserSwitchDesktop");
  1465. ENDRECV();
  1466. }
  1467. NTSTATUS NtUserInitializeClientPfnArrays( // private
  1468. IN CONST PFNCLIENT *ppfnClientA OPTIONAL,
  1469. IN CONST PFNCLIENT *ppfnClientW OPTIONAL,
  1470. IN CONST PFNCLIENTWORKER *ppfnClientWorker OPTIONAL,
  1471. IN HANDLE hModUser)
  1472. {
  1473. BEGINRECV(NTSTATUS, STATUS_UNSUCCESSFUL);
  1474. /*
  1475. * Probe all read arguments
  1476. */
  1477. try {
  1478. if (ARGUMENT_PRESENT(ppfnClientA)) {
  1479. ProbeForRead(ppfnClientA, sizeof(*ppfnClientA), sizeof(DWORD));
  1480. }
  1481. if (ARGUMENT_PRESENT(ppfnClientW)) {
  1482. ProbeForRead(ppfnClientW, sizeof(*ppfnClientW), sizeof(DWORD));
  1483. }
  1484. if (ARGUMENT_PRESENT(ppfnClientWorker)) {
  1485. ProbeForRead(ppfnClientWorker, sizeof(*ppfnClientWorker), sizeof(DWORD));
  1486. }
  1487. retval = InitializeClientPfnArrays(
  1488. ppfnClientA, ppfnClientW, ppfnClientWorker, hModUser);
  1489. } except (StubExceptionHandler(FALSE)) {
  1490. MSGERROR(0);
  1491. }
  1492. TRACE("NtUserInitializeThreadInfo");
  1493. ENDRECV();
  1494. }
  1495. BOOL NtUserWaitForMsgAndEvent(
  1496. IN HANDLE hevent)
  1497. {
  1498. BEGINRECV(BOOL, FALSE);
  1499. retval = xxxSleepTask(FALSE, hevent);
  1500. TRACE("NtUserWaitForMsgAndEvent");
  1501. ENDRECV();
  1502. }
  1503. DWORD NtUserDragObject(
  1504. IN HWND hwndParent,
  1505. IN HWND hwndFrom,
  1506. IN UINT wFmt,
  1507. IN ULONG_PTR dwData,
  1508. IN HCURSOR hcur)
  1509. {
  1510. PWND pwndFrom;
  1511. PCURSOR pcur;
  1512. TL tlpwndFrom;
  1513. TL tlpcur;
  1514. BEGINRECV_HWNDLOCK(DWORD, 0, hwndParent);
  1515. ValidateHWNDOPT(pwndFrom, hwndFrom);
  1516. ValidateHCURSOROPT(pcur, hcur);
  1517. ThreadLockWithPti(ptiCurrent, pwndFrom, &tlpwndFrom);
  1518. ThreadLockWithPti(ptiCurrent, pcur, &tlpcur);
  1519. retval = xxxDragObject(
  1520. pwnd,
  1521. pwndFrom,
  1522. wFmt,
  1523. dwData,
  1524. pcur);
  1525. ThreadUnlock(&tlpcur);
  1526. ThreadUnlock(&tlpwndFrom);
  1527. TRACE("NtUserDragObject");
  1528. ENDRECV_HWNDLOCK();
  1529. }
  1530. BOOL NtUserGetIconInfo( // API GetIconInfo
  1531. IN HICON hIcon,
  1532. OUT PICONINFO piconinfo,
  1533. IN OUT OPTIONAL PUNICODE_STRING pstrInstanceName,
  1534. IN OUT OPTIONAL PUNICODE_STRING pstrResName,
  1535. OUT LPDWORD pbpp,
  1536. IN BOOL fInternal)
  1537. {
  1538. PICON pIcon;
  1539. UNICODE_STRING strInstanceName, *pstrInstanceLocal;
  1540. UNICODE_STRING strResName, *pstrResLocal;
  1541. BEGINATOMICRECV(BOOL, FALSE);
  1542. /*
  1543. * NOTE -- this can't be _SHARED since it calls Gre code with system HDC's.
  1544. */
  1545. ValidateHCURSOR(pIcon, hIcon);
  1546. /*
  1547. * Probe arguments
  1548. */
  1549. try {
  1550. if (pstrInstanceName != NULL) {
  1551. strInstanceName = ProbeAndReadUnicodeString(pstrInstanceName);
  1552. ProbeForWrite(strInstanceName.Buffer, strInstanceName.MaximumLength, CHARALIGN);
  1553. pstrInstanceLocal = &strInstanceName;
  1554. } else {
  1555. pstrInstanceLocal = NULL;
  1556. }
  1557. if (pstrResName != NULL) {
  1558. strResName = ProbeAndReadUnicodeString(pstrResName);
  1559. ProbeForWrite(strResName.Buffer, strResName.MaximumLength, CHARALIGN);
  1560. pstrResLocal = &strResName;
  1561. } else {
  1562. pstrResLocal = NULL;
  1563. }
  1564. if (pbpp != NULL) {
  1565. ProbeForWrite(pbpp, sizeof(DWORD), sizeof(DWORD));
  1566. }
  1567. ProbeForWrite(piconinfo, sizeof(*piconinfo), DATAALIGN);
  1568. } except (StubExceptionHandler(TRUE)) {
  1569. MSGERROR(0);
  1570. }
  1571. /*
  1572. * All use of client-side pointers in InternalGetIconInfo
  1573. * is protected by try/except.
  1574. */
  1575. retval = _InternalGetIconInfo(
  1576. pIcon,
  1577. piconinfo,
  1578. pstrInstanceLocal,
  1579. pstrResLocal,
  1580. pbpp,
  1581. fInternal);
  1582. try {
  1583. if (pstrInstanceName != NULL) {
  1584. RtlCopyMemory(pstrInstanceName, pstrInstanceLocal, sizeof(UNICODE_STRING));
  1585. }
  1586. if (pstrResName != NULL) {
  1587. RtlCopyMemory(pstrResName, pstrResLocal, sizeof(UNICODE_STRING));
  1588. }
  1589. } except (StubExceptionHandler(TRUE)) {
  1590. MSGERROR(0);
  1591. }
  1592. TRACE("NtUserGetIconInfo");
  1593. ENDATOMICRECV();
  1594. }
  1595. BOOL NtUserGetIconSize( // private
  1596. IN HICON hIcon,
  1597. IN UINT istepIfAniCur,
  1598. OUT int *pcx,
  1599. OUT int *pcy)
  1600. {
  1601. PCURSOR picon;
  1602. BEGINRECV_SHARED(BOOL, FALSE);
  1603. ValidateHICON(picon, hIcon);
  1604. if (picon->CURSORF_flags & CURSORF_ACON) {
  1605. PACON pacon = (PACON)picon;
  1606. if (istepIfAniCur < (UINT)pacon->cpcur) {
  1607. picon = pacon->aspcur[pacon->aicur[istepIfAniCur]];
  1608. } else {
  1609. RIPMSG2(RIP_WARNING, "NtUserGetIconSize: Invalid istepIfAniCur:%#lx. picon:%#p",
  1610. istepIfAniCur, picon);
  1611. MSGERROR(0);
  1612. }
  1613. }
  1614. /*
  1615. * Probe arguments
  1616. */
  1617. try {
  1618. ProbeAndWriteLong(pcx, picon->cx);
  1619. ProbeAndWriteLong(pcy, picon->cy);
  1620. retval = 1;
  1621. } except (StubExceptionHandler(FALSE)) {
  1622. MSGERROR(0);
  1623. }
  1624. TRACE("NtUserGetIconSize");
  1625. ENDRECV_SHARED();
  1626. }
  1627. BOOL NtUserDrawIconEx( // API DrawIconEx
  1628. IN HDC hdc,
  1629. IN int x,
  1630. IN int y,
  1631. IN HICON hicon,
  1632. IN int cx,
  1633. IN int cy,
  1634. IN UINT istepIfAniCur,
  1635. IN HBRUSH hbrush,
  1636. IN UINT diFlags,
  1637. IN BOOL fMeta,
  1638. OUT DRAWICONEXDATA *pdid)
  1639. {
  1640. PCURSOR picon;
  1641. BEGINATOMICRECV(BOOL, FALSE);
  1642. ValidateHICON(picon, hicon);
  1643. if (fMeta) {
  1644. if (picon->CURSORF_flags & CURSORF_ACON)
  1645. picon = ((PACON)picon)->aspcur[((PACON)picon)->aicur[0]];
  1646. /*
  1647. * Probe arguments
  1648. */
  1649. try {
  1650. ProbeForWrite(pdid, sizeof(*pdid), DATAALIGN);
  1651. pdid->hbmMask = picon->hbmMask;
  1652. pdid->hbmColor = picon->hbmColor;
  1653. pdid->hbmUserAlpha = picon->hbmUserAlpha;
  1654. pdid->cx = picon->cx;
  1655. pdid->cy = picon->cy;
  1656. retval = 1;
  1657. } except (StubExceptionHandler(TRUE)) {
  1658. MSGERROR(0);
  1659. }
  1660. } else {
  1661. retval = _DrawIconEx(hdc,
  1662. x,
  1663. y,
  1664. picon,
  1665. cx,
  1666. cy,
  1667. istepIfAniCur,
  1668. hbrush,
  1669. diFlags);
  1670. }
  1671. TRACE("NtUserDrawIconEx");
  1672. ENDATOMICRECV();
  1673. }
  1674. HANDLE NtUserDeferWindowPos(
  1675. IN HDWP hWinPosInfo,
  1676. IN HWND hwnd,
  1677. IN HWND hwndInsertAfter,
  1678. IN int x,
  1679. IN int y,
  1680. IN int cx,
  1681. IN int cy,
  1682. IN UINT wFlags)
  1683. {
  1684. PWND pwnd;
  1685. PWND pwndInsertAfter;
  1686. PSMWP psmwp;
  1687. BEGINATOMICRECV(HANDLE, NULL);
  1688. TESTFLAGS(wFlags, SWP_VALID);
  1689. ValidateHWNDND(pwnd, hwnd);
  1690. ValidateHWNDIA(pwndInsertAfter, hwndInsertAfter);
  1691. ValidateHDWP(psmwp, hWinPosInfo);
  1692. if (wFlags & ~(SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER |
  1693. SWP_NOREDRAW | SWP_NOACTIVATE | SWP_FRAMECHANGED |
  1694. SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOCOPYBITS |
  1695. SWP_NOOWNERZORDER)) {
  1696. RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid flags (0x%lx) passed to DeferWindowPos",
  1697. wFlags);
  1698. MSGERROR(0);
  1699. }
  1700. /*
  1701. * Make sure the window coordinates can fit in WORDs.
  1702. */
  1703. if (!(wFlags & SWP_NOMOVE)) {
  1704. if (x > SHRT_MAX) {
  1705. x = SHRT_MAX;
  1706. } else if (x < SHRT_MIN) {
  1707. x = SHRT_MIN;
  1708. }
  1709. if (y > SHRT_MAX) {
  1710. y = SHRT_MAX;
  1711. } else if (y < SHRT_MIN) {
  1712. y = SHRT_MIN;
  1713. }
  1714. }
  1715. /*
  1716. * Actually, if we were going to be really strict about this we'd
  1717. * make sure that x + cx < SHRT_MAX, etc but since we do maintain
  1718. * signed 32-bit coords internally this case doesn't cause a problem.
  1719. */
  1720. if (!(wFlags & SWP_NOSIZE)) {
  1721. if (cx < 0) {
  1722. cx = 0;
  1723. } else if (cx > SHRT_MAX) {
  1724. cx = SHRT_MAX;
  1725. }
  1726. if (cy < 0) {
  1727. cy = 0;
  1728. } else if (cy > SHRT_MAX) {
  1729. cy = SHRT_MAX;
  1730. }
  1731. }
  1732. #ifdef NEVER
  1733. //
  1734. // do not fail these conditions because real apps use them.
  1735. //
  1736. if (!(wFlags & SWP_NOMOVE) &&
  1737. (x > SHRT_MAX || x < SHRT_MIN ||
  1738. y > SHRT_MAX || y < SHRT_MIN)) {
  1739. RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid coordinate passed to SetWindowPos");
  1740. MSGERROR(0);
  1741. }
  1742. /*
  1743. * Actually, if we were going to be really strict about this we'd
  1744. * make sure that x + cx < SHRT_MAX, etc but since we do maintain
  1745. * signed 32-bit coords internally this case doesn't cause a problem.
  1746. */
  1747. if (!(wFlags & SWP_NOSIZE) &&
  1748. (cx < 0 || cx > SHRT_MAX ||
  1749. cy < 0 || cy > SHRT_MAX)) {
  1750. RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid width/height passed to SetWindowPos");
  1751. MSGERROR(0);
  1752. }
  1753. #endif
  1754. retval = _DeferWindowPos(
  1755. psmwp,
  1756. pwnd,
  1757. pwndInsertAfter,
  1758. x,
  1759. y,
  1760. cx,
  1761. cy,
  1762. wFlags);
  1763. retval = PtoH((PVOID)retval);
  1764. TRACE("NtUserDeferWindowPos");
  1765. ENDATOMICRECV();
  1766. }
  1767. BOOL NtUserEndDeferWindowPosEx(
  1768. IN HDWP hWinPosInfo,
  1769. IN BOOL fAsync)
  1770. {
  1771. PSMWP psmwp;
  1772. TL tlpsmp;
  1773. BEGINRECV(BOOL, FALSE);
  1774. ValidateHDWP(psmwp, hWinPosInfo);
  1775. ThreadLockAlways(psmwp, &tlpsmp);
  1776. retval = xxxEndDeferWindowPosEx(
  1777. psmwp,
  1778. fAsync);
  1779. ThreadUnlock(&tlpsmp);
  1780. TRACE("NtUserEndDeferWindowPosEx");
  1781. ENDRECV();
  1782. }
  1783. BOOL NtUserGetMessage( // API GetMessageA/W
  1784. OUT LPMSG pmsg,
  1785. IN HWND hwnd,
  1786. IN UINT wMsgFilterMin,
  1787. IN UINT wMsgFilterMax)
  1788. {
  1789. MSG msg;
  1790. BEGINRECV(BOOL, FALSE);
  1791. retval = xxxGetMessage(
  1792. &msg,
  1793. hwnd,
  1794. wMsgFilterMin,
  1795. wMsgFilterMax);
  1796. /*
  1797. * Probe arguments
  1798. */
  1799. try {
  1800. ProbeAndWriteStructure(pmsg, msg, MSG);
  1801. } except (StubExceptionHandler(TRUE)) {
  1802. MSGERROR(0);
  1803. }
  1804. TRACE("NtUserGetMessage");
  1805. ENDRECV();
  1806. }
  1807. #ifdef MESSAGE_PUMP_HOOK
  1808. BOOL NtUserRealInternalGetMessage( // API RealInternalGetMessage
  1809. OUT LPMSG pmsg,
  1810. IN HWND hwnd,
  1811. IN UINT wMsgFilterMin,
  1812. IN UINT wMsgFilterMax,
  1813. IN UINT flags,
  1814. BOOL fGetMessage)
  1815. {
  1816. MSG msg;
  1817. BEGINRECV(BOOL, FALSE);
  1818. TESTFLAGS(flags, PM_VALID);
  1819. if (!IsInsideMPH()) {
  1820. RIPMSG0(RIP_WARNING, "NtUserRealInternalGetMessage: Calling MPH function on non-initialized thread");
  1821. }
  1822. retval = xxxRealInternalGetMessage(
  1823. &msg,
  1824. hwnd,
  1825. wMsgFilterMin,
  1826. wMsgFilterMax,
  1827. flags,
  1828. fGetMessage);
  1829. /*
  1830. * Probe arguments
  1831. */
  1832. try {
  1833. ProbeAndWriteStructure(pmsg, msg, MSG);
  1834. } except (StubExceptionHandler(TRUE)) {
  1835. MSGERROR(0);
  1836. }
  1837. TRACE("NtUserRealInternalGetMessage");
  1838. ENDRECV();
  1839. }
  1840. #endif // MESSAGE_PUMP_HOOK
  1841. BOOL NtUserMoveWindow(
  1842. IN HWND hwnd,
  1843. IN int x,
  1844. IN int y,
  1845. IN int cx,
  1846. IN int cy,
  1847. IN BOOL fRepaint)
  1848. {
  1849. BEGINRECV_HWNDLOCK_ND(BOOL, FALSE, hwnd);
  1850. /*
  1851. * Make sure the window coordinates can fit in WORDs.
  1852. */
  1853. if (x > SHRT_MAX) {
  1854. x = SHRT_MAX;
  1855. } else if (x < SHRT_MIN) {
  1856. x = SHRT_MIN;
  1857. }
  1858. if (y > SHRT_MAX) {
  1859. y = SHRT_MAX;
  1860. } else if (y < SHRT_MIN) {
  1861. y = SHRT_MIN;
  1862. }
  1863. /*
  1864. * Actually, if we were going to be really strict about this we'd
  1865. * make sure that x + cx < SHRT_MAX, etc but since we do maintain
  1866. * signed 32-bit coords internally this case doesn't cause a problem.
  1867. */
  1868. if (cx < 0) {
  1869. cx = 0;
  1870. } else if (cx > SHRT_MAX) {
  1871. cx = SHRT_MAX;
  1872. }
  1873. if (cy < 0) {
  1874. cy = 0;
  1875. } else if (cy > SHRT_MAX) {
  1876. cy = SHRT_MAX;
  1877. }
  1878. #ifdef NEVER
  1879. //
  1880. // do not fail these conditions because real apps use them.
  1881. //
  1882. if (x > SHRT_MAX || x < SHRT_MIN ||
  1883. y > SHRT_MAX || y < SHRT_MIN) {
  1884. RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid coordinate passed to MoveWindow");
  1885. MSGERROR(0);
  1886. }
  1887. /*
  1888. * Actually, if we were going to be really strict about this we'd
  1889. * make sure that x + cx < SHRT_MAX, etc but since we do maintain
  1890. * signed 32-bit coords internally this case doesn't cause a problem.
  1891. */
  1892. if (cx < 0 || cx > SHRT_MAX ||
  1893. cy < 0 || cy > SHRT_MAX) {
  1894. RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid width/height passed to MoveWindow");
  1895. MSGERROR(0);
  1896. }
  1897. #endif
  1898. retval = xxxMoveWindow(
  1899. pwndND,
  1900. x,
  1901. y,
  1902. cx,
  1903. cy,
  1904. fRepaint);
  1905. TRACE("NtUserMoveWindow");
  1906. ENDRECV_HWNDLOCK_ND();
  1907. }
  1908. int NtUserTranslateAccelerator( // API TranslateAcceleratorA/W
  1909. IN HWND hwnd,
  1910. IN HACCEL haccel,
  1911. IN LPMSG lpmsg)
  1912. {
  1913. PWND pwnd;
  1914. LPACCELTABLE pat;
  1915. TL tlpwnd;
  1916. TL tlpat;
  1917. PTHREADINFO ptiCurrent;
  1918. MSG msg;
  1919. BEGINRECV(int, 0);
  1920. /*
  1921. * Probe arguments
  1922. */
  1923. try {
  1924. msg = ProbeAndReadMessage(lpmsg);
  1925. } except (StubExceptionHandler(FALSE)) {
  1926. MSGERROR(0);
  1927. }
  1928. /*
  1929. * This is called within a message loop. If the window gets destroyed,
  1930. * there still may be other messages in the queue that get returned
  1931. * after the window is destroyed. The app will call TranslateAccelerator()
  1932. * on every one of these, causing RIPs.... Make it nice so it just
  1933. * returns FALSE.
  1934. */
  1935. ValidateHWNDNoRIP(pwnd, hwnd);
  1936. ValidateHACCEL(pat, haccel);
  1937. ptiCurrent = PtiCurrent();
  1938. ThreadLockAlwaysWithPti(ptiCurrent, pwnd, &tlpwnd);
  1939. ThreadLockAlwaysWithPti(ptiCurrent, pat, &tlpat);
  1940. retval = xxxTranslateAccelerator(
  1941. pwnd,
  1942. pat,
  1943. &msg);
  1944. ThreadUnlock(&tlpat);
  1945. ThreadUnlock(&tlpwnd);
  1946. TRACE("NtUserTranslateAccelerator");
  1947. ENDRECV();
  1948. }
  1949. LONG_PTR NtUserSetClassLongPtr( // API SetClassLongPtrA/W
  1950. IN HWND hwnd,
  1951. IN int nIndex,
  1952. OUT LONG_PTR dwNewLong,
  1953. IN BOOL bAnsi)
  1954. {
  1955. UNICODE_STRING strMenuName;
  1956. CLSMENUNAME cmn, *pcmnSave;
  1957. BEGINRECV_HWNDLOCK(ULONG_PTR, 0, hwnd);
  1958. switch (nIndex) {
  1959. case GCLP_MENUNAME:
  1960. try {
  1961. /*
  1962. * There is no callback from the routine for
  1963. * this value, so we can protect it with a try/except.
  1964. * This is cheaper than capturing the name
  1965. * and copying it back. FritzS
  1966. */
  1967. pcmnSave = (PCLSMENUNAME) dwNewLong;
  1968. cmn = ProbeAndReadStructure(pcmnSave, CLSMENUNAME);
  1969. strMenuName = ProbeAndReadUnicodeString(cmn.pusMenuName);
  1970. ProbeForReadUnicodeStringBufferOrId(strMenuName);
  1971. } except (StubExceptionHandler(TRUE)) {
  1972. MSGERROR(0);
  1973. }
  1974. cmn.pusMenuName = &strMenuName;
  1975. dwNewLong = (ULONG_PTR) &cmn;
  1976. retval = xxxSetClassLongPtr(
  1977. pwnd,
  1978. nIndex,
  1979. dwNewLong,
  1980. bAnsi);
  1981. try {
  1982. ProbeAndWriteStructure(pcmnSave, cmn, CLSMENUNAME);
  1983. } except (StubExceptionHandler(TRUE)) {
  1984. MSGERROR(0);
  1985. }
  1986. break;
  1987. case GCL_STYLE:
  1988. /*
  1989. * I'm not sure how CS_VALID mask will affect existing apps,
  1990. * so leave it for now --- except CS_IME flag, on which the system
  1991. * deeply depends.
  1992. */
  1993. #if DBG
  1994. if (dwNewLong & ~CS_VALID) {
  1995. RIPMSG1(RIP_WARNING, "NtUserSetClassLongPtr: Invalid style (%x) specified.", dwNewLong);
  1996. }
  1997. #endif
  1998. if (dwNewLong & CS_IME) {
  1999. RIPERR1(ERROR_INVALID_DATA, RIP_VERBOSE, "NtUserSetClassLongPtr: CS_IME is specified in new style (%x).", dwNewLong);
  2000. MSGERROR(0);
  2001. }
  2002. default:
  2003. retval = xxxSetClassLongPtr(
  2004. pwnd,
  2005. nIndex,
  2006. dwNewLong,
  2007. bAnsi);
  2008. }
  2009. TRACE("NtUserSetClassLongPtr");
  2010. ENDRECV_HWNDLOCK();
  2011. }
  2012. #ifdef _WIN64
  2013. LONG NtUserSetClassLong(
  2014. IN HWND hwnd,
  2015. IN int nIndex,
  2016. OUT LONG dwNewLong,
  2017. IN BOOL bAnsi)
  2018. {
  2019. BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
  2020. switch (nIndex) {
  2021. case GCL_STYLE:
  2022. /*
  2023. * I'm not sure how CS_VALID mask will affect existing apps,
  2024. * so leave it for now --- except CS_IME flag, on which the system
  2025. * deeply depends.
  2026. */
  2027. #if DBG
  2028. if (dwNewLong & ~CS_VALID) {
  2029. RIPMSG1(RIP_WARNING, "NtUserSetClassLong: Invalid style (%x) specified.", dwNewLong);
  2030. }
  2031. #endif
  2032. if (dwNewLong & CS_IME) {
  2033. RIPERR1(ERROR_INVALID_DATA, RIP_VERBOSE, "NtUserSetClassLong: CS_IME is specified in new style (%x).", dwNewLong);
  2034. MSGERROR(0);
  2035. }
  2036. }
  2037. retval = xxxSetClassLong(
  2038. pwnd,
  2039. nIndex,
  2040. dwNewLong,
  2041. bAnsi);
  2042. TRACE("NtUserSetClassLong");
  2043. ENDRECV_HWNDLOCK();
  2044. }
  2045. #endif
  2046. BOOL NtUserSetKeyboardState( // API SetKeyboardState
  2047. IN CONST BYTE *lpKeyState)
  2048. {
  2049. BEGINRECV(BOOL, FALSE);
  2050. /*
  2051. * Probe arguments
  2052. */
  2053. try {
  2054. ProbeForRead(lpKeyState, 256, sizeof(BYTE));
  2055. retval = _SetKeyboardState(lpKeyState);
  2056. } except (StubExceptionHandler(TRUE)) {
  2057. MSGERROR(0);
  2058. }
  2059. TRACE("NtUserSetKeyboardState");
  2060. ENDRECV();
  2061. }
  2062. BOOL NtUserSetWindowPos(
  2063. IN HWND hwnd,
  2064. IN HWND hwndInsertAfter,
  2065. IN int x,
  2066. IN int y,
  2067. IN int cx,
  2068. IN int cy,
  2069. IN UINT dwFlags)
  2070. {
  2071. PWND pwndT;
  2072. PWND pwndInsertAfter;
  2073. TL tlpwndT;
  2074. BEGINRECV_HWNDLOCK_ND(BOOL, FALSE, hwnd);
  2075. TESTFLAGS(dwFlags, SWP_VALID);
  2076. ValidateHWNDIA(pwndInsertAfter, hwndInsertAfter);
  2077. /*
  2078. * Let's not allow the window to be shown/hidden once we
  2079. * started the destruction of the window.
  2080. */
  2081. if (TestWF(pwndND, WFINDESTROY)) {
  2082. RIPERR1(ERROR_INVALID_PARAMETER,
  2083. RIP_WARNING,
  2084. "SetWindowPos: Window is being destroyed (pwnd == %#p)",
  2085. pwndND);
  2086. MSGERROR(0);
  2087. }
  2088. if (dwFlags & ~SWP_VALID) {
  2089. RIPERR1(ERROR_INVALID_PARAMETER,
  2090. RIP_WARNING,
  2091. "SetWindowPos: Invalid flags passed in (flags == 0x%lx)",
  2092. dwFlags);
  2093. MSGERROR(0);
  2094. }
  2095. /*
  2096. * Make sure the window coordinates can fit in WORDs.
  2097. */
  2098. if (!(dwFlags & SWP_NOMOVE)) {
  2099. if (x > SHRT_MAX) {
  2100. x = SHRT_MAX;
  2101. } else if (x < SHRT_MIN) {
  2102. x = SHRT_MIN;
  2103. }
  2104. if (y > SHRT_MAX) {
  2105. y = SHRT_MAX;
  2106. } else if (y < SHRT_MIN) {
  2107. y = SHRT_MIN;
  2108. }
  2109. }
  2110. /*
  2111. * Actually, if we were going to be really strict about this we'd
  2112. * make sure that x + cx < SHRT_MAX, etc but since we do maintain
  2113. * signed 32-bit coords internally this case doesn't cause a problem.
  2114. */
  2115. if (!(dwFlags & SWP_NOSIZE)) {
  2116. if (cx < 0) {
  2117. cx = 0;
  2118. } else if (cx > SHRT_MAX) {
  2119. cx = SHRT_MAX;
  2120. }
  2121. if (cy < 0) {
  2122. cy = 0;
  2123. } else if (cy > SHRT_MAX) {
  2124. cy = SHRT_MAX;
  2125. }
  2126. }
  2127. #ifdef NEVER
  2128. //
  2129. // do not fail these conditions because real apps use them.
  2130. //
  2131. if (!(dwFlags & SWP_NOMOVE) &&
  2132. (x > SHRT_MAX || x < SHRT_MIN ||
  2133. y > SHRT_MAX || y < SHRT_MIN)) {
  2134. RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid coordinate passed to SetWindowPos");
  2135. MSGERROR(0);
  2136. }
  2137. /*
  2138. * Actually, if we were going to be really strict about this we'd
  2139. * make sure that x + cx < SHRT_MAX, etc but since we do maintain
  2140. * signed 32-bit coords internally this case doesn't cause a problem.
  2141. */
  2142. if (!(dwFlags & SWP_NOSIZE) &&
  2143. (cx < 0 || cx > SHRT_MAX ||
  2144. cy < 0 || cy > SHRT_MAX)) {
  2145. RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid width/height passed to SetWindowPos");
  2146. MSGERROR(0);
  2147. }
  2148. #endif
  2149. switch((ULONG_PTR)pwndInsertAfter) {
  2150. case (ULONG_PTR)HWND_TOPMOST:
  2151. case (ULONG_PTR)HWND_NOTOPMOST:
  2152. case (ULONG_PTR)HWND_TOP:
  2153. case (ULONG_PTR)HWND_BOTTOM:
  2154. pwndT = NULL;
  2155. break;
  2156. default:
  2157. pwndT = pwndInsertAfter;
  2158. break;
  2159. }
  2160. ThreadLockWithPti(ptiCurrent, pwndT, &tlpwndT);
  2161. retval = xxxSetWindowPos(
  2162. pwndND,
  2163. pwndInsertAfter,
  2164. x,
  2165. y,
  2166. cx,
  2167. cy,
  2168. dwFlags);
  2169. ThreadUnlock(&tlpwndT);
  2170. TRACE("NtUserSetWindowPos");
  2171. ENDRECV_HWNDLOCK_ND();
  2172. }
  2173. BOOL NtUserSetShellWindowEx(
  2174. IN HWND hwnd,
  2175. IN HWND hwndBkGnd)
  2176. {
  2177. PWND pwndBkGnd;
  2178. TL tlpwndBkGnd;
  2179. BEGINRECV_HWNDLOCK_ND(BOOL, FALSE, hwnd);
  2180. ValidateHWNDND(pwndBkGnd, hwndBkGnd);
  2181. ThreadLockAlwaysWithPti(ptiCurrent, pwndBkGnd, &tlpwndBkGnd);
  2182. retval = xxxSetShellWindow(pwndND, pwndBkGnd);
  2183. ThreadUnlock(&tlpwndBkGnd);
  2184. TRACE("NtUserSetShellWindowEx");
  2185. ENDRECV_HWNDLOCK_ND();
  2186. }
  2187. DWORD
  2188. NtUserGetGuiResources(
  2189. HANDLE hProcess,
  2190. DWORD dwFlags)
  2191. {
  2192. PEPROCESS Process;
  2193. PW32PROCESS pW32Process;
  2194. BEGINRECV_SHARED(DWORD, 0);
  2195. /*
  2196. * Probe arguments
  2197. */
  2198. if (dwFlags > GR_MAXOBJECT) {
  2199. RIPERR1(ERROR_INVALID_PARAMETER,
  2200. RIP_WARNING,
  2201. "GetGuiResources: Invalid flag bits 0x%x",
  2202. dwFlags);
  2203. MSGERROR(0);
  2204. }
  2205. if (hProcess == NtCurrentProcess()) {
  2206. pW32Process = W32GetCurrentProcess();
  2207. } else {
  2208. NTSTATUS Status;
  2209. Status = ObReferenceObjectByHandle(hProcess,
  2210. PROCESS_QUERY_INFORMATION,
  2211. *PsProcessType,
  2212. UserMode,
  2213. &Process,
  2214. NULL);
  2215. if (!NT_SUCCESS(Status)) {
  2216. RIPERR2(ERROR_INVALID_PARAMETER,
  2217. RIP_WARNING,
  2218. "GetGuiResources: Failed with process 0x%x, Status = 0x%x",
  2219. hProcess,
  2220. Status);
  2221. MSGERROR(0);
  2222. }
  2223. /*
  2224. * Make sure they are from the same session
  2225. */
  2226. if (PsGetProcessSessionId(Process) != gSessionId) {
  2227. RIPERR2(ERROR_INVALID_PARAMETER,
  2228. RIP_VERBOSE,
  2229. "GetGuiResources: Different session. Failed with process 0x%x, Status = 0x%x",
  2230. hProcess,
  2231. Status);
  2232. ObDereferenceObject(Process);
  2233. MSGERROR(0);
  2234. }
  2235. pW32Process = PsGetProcessWin32Process(Process);
  2236. }
  2237. if (pW32Process) {
  2238. switch(dwFlags) {
  2239. case GR_GDIOBJECTS:
  2240. retval = pW32Process->GDIHandleCount;
  2241. break;
  2242. case GR_USEROBJECTS:
  2243. retval = pW32Process->UserHandleCount;
  2244. break;
  2245. }
  2246. } else {
  2247. retval = 0;
  2248. }
  2249. if (hProcess != NtCurrentProcess()) {
  2250. ObDereferenceObject(Process);
  2251. }
  2252. TRACE("NtUserGetGuiResources");
  2253. ENDRECV_SHARED();
  2254. }
  2255. BOOL NtUserSystemParametersInfo( // API SystemParametersInfoA/W
  2256. IN UINT wFlag,
  2257. IN DWORD wParam,
  2258. IN OUT LPVOID lpData,
  2259. IN UINT flags)
  2260. {
  2261. UNICODE_STRING strData;
  2262. ULONG ulLength, ulLength2;
  2263. LPVOID lpDataSave;
  2264. union {
  2265. INT MouseData[3];
  2266. LOGFONTW LogFont;
  2267. MOUSEKEYS MouseKeys;
  2268. FILTERKEYS FilterKeys;
  2269. STICKYKEYS StickyKeys;
  2270. TOGGLEKEYS ToggleKeys;
  2271. SOUNDSENTRY SoundSentry;
  2272. ACCESSTIMEOUT AccessTimeout;
  2273. RECT Rect;
  2274. ANIMATIONINFO AnimationInfo;
  2275. NONCLIENTMETRICS NonClientMetrics;
  2276. MINIMIZEDMETRICS MinimizedMetrics;
  2277. ICONMETRICS IconMetrics;
  2278. HKL hkl;
  2279. INTERNALSETHIGHCONTRAST ihc;
  2280. HIGHCONTRAST hc;
  2281. WCHAR szTemp[MAX_PATH];
  2282. } CaptureBuffer;
  2283. PTHREADINFO pti;
  2284. TL tlBuffer;
  2285. BOOL fFreeBuffer = FALSE;
  2286. BOOL fWrite = FALSE;
  2287. BEGINRECV(BOOL, FALSE);
  2288. /*
  2289. * Prevent restricted processes from setting system
  2290. * parameters.
  2291. *
  2292. * clupu: this is ineficient and temporary. I'll change this
  2293. * soon !!!
  2294. */
  2295. if (IS_CURRENT_THREAD_RESTRICTED(JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS)) {
  2296. switch (wFlag) {
  2297. case SPI_SETBEEP:
  2298. case SPI_SETMOUSE:
  2299. case SPI_SETBORDER:
  2300. case SPI_SETKEYBOARDSPEED:
  2301. case SPI_ICONHORIZONTALSPACING:
  2302. case SPI_SETSCREENSAVETIMEOUT:
  2303. case SPI_SETBLOCKSENDINPUTRESETS:
  2304. case SPI_SETSCREENSAVEACTIVE:
  2305. case SPI_SETGRIDGRANULARITY:
  2306. case SPI_SETDESKWALLPAPER:
  2307. case SPI_SETDESKPATTERN:
  2308. case SPI_SETKEYBOARDDELAY:
  2309. case SPI_ICONVERTICALSPACING:
  2310. case SPI_SETICONTITLEWRAP:
  2311. case SPI_SETMENUDROPALIGNMENT:
  2312. case SPI_SETDOUBLECLKWIDTH:
  2313. case SPI_SETDOUBLECLKHEIGHT:
  2314. case SPI_SETDOUBLECLICKTIME:
  2315. case SPI_SETMOUSEBUTTONSWAP:
  2316. case SPI_SETICONTITLELOGFONT:
  2317. case SPI_SETFASTTASKSWITCH:
  2318. case SPI_SETDRAGFULLWINDOWS:
  2319. case SPI_SETNONCLIENTMETRICS:
  2320. case SPI_SETMINIMIZEDMETRICS:
  2321. case SPI_SETICONMETRICS:
  2322. case SPI_SETWORKAREA:
  2323. case SPI_SETPENWINDOWS:
  2324. case SPI_SETHIGHCONTRAST:
  2325. case SPI_SETKEYBOARDPREF:
  2326. case SPI_SETSCREENREADER:
  2327. case SPI_SETANIMATION:
  2328. case SPI_SETFONTSMOOTHING:
  2329. case SPI_SETDRAGWIDTH:
  2330. case SPI_SETDRAGHEIGHT:
  2331. case SPI_SETHANDHELD:
  2332. case SPI_SETLOWPOWERTIMEOUT:
  2333. case SPI_SETPOWEROFFTIMEOUT:
  2334. case SPI_SETLOWPOWERACTIVE:
  2335. case SPI_SETPOWEROFFACTIVE:
  2336. case SPI_SETCURSORS:
  2337. case SPI_SETICONS:
  2338. case SPI_SETDEFAULTINPUTLANG:
  2339. case SPI_SETLANGTOGGLE:
  2340. case SPI_SETMOUSETRAILS:
  2341. case SPI_SETSCREENSAVERRUNNING:
  2342. case SPI_SETFILTERKEYS:
  2343. case SPI_SETTOGGLEKEYS:
  2344. case SPI_SETMOUSEKEYS:
  2345. case SPI_SETSHOWSOUNDS:
  2346. case SPI_SETSTICKYKEYS:
  2347. case SPI_SETACCESSTIMEOUT:
  2348. case SPI_SETSOUNDSENTRY:
  2349. case SPI_SETSNAPTODEFBUTTON:
  2350. case SPI_SETMOUSEHOVERWIDTH:
  2351. case SPI_SETMOUSEHOVERHEIGHT:
  2352. case SPI_SETMOUSEHOVERTIME:
  2353. case SPI_SETWHEELSCROLLLINES:
  2354. case SPI_SETMENUSHOWDELAY:
  2355. case SPI_SETSHOWIMEUI:
  2356. case SPI_SETMOUSESPEED:
  2357. case SPI_SETACTIVEWINDOWTRACKING:
  2358. case SPI_SETMENUANIMATION:
  2359. case SPI_SETCOMBOBOXANIMATION:
  2360. case SPI_SETLISTBOXSMOOTHSCROLLING:
  2361. case SPI_SETGRADIENTCAPTIONS:
  2362. case SPI_SETKEYBOARDCUES:
  2363. case SPI_SETACTIVEWNDTRKZORDER:
  2364. case SPI_SETHOTTRACKING:
  2365. case SPI_SETMENUFADE:
  2366. case SPI_SETSELECTIONFADE:
  2367. case SPI_SETTOOLTIPANIMATION:
  2368. case SPI_SETTOOLTIPFADE:
  2369. #ifdef MOUSE_IP
  2370. case SPI_SETMOUSESONAR:
  2371. case SPI_SETMOUSECLICKLOCK:
  2372. #endif
  2373. case SPI_SETFOREGROUNDLOCKTIMEOUT:
  2374. case SPI_SETACTIVEWNDTRKTIMEOUT:
  2375. case SPI_SETFOREGROUNDFLASHCOUNT:
  2376. case SPI_SETMOUSECLICKLOCKTIME:
  2377. case SPI_SETFOCUSBORDERWIDTH:
  2378. case SPI_SETFOCUSBORDERHEIGHT:
  2379. MSGERROR(0);
  2380. break;
  2381. }
  2382. }
  2383. try {
  2384. switch(wFlag) {
  2385. case SPI_SETDESKPATTERN:
  2386. /*
  2387. * If wParam is -1, that means read the new wallpaper from
  2388. * win.ini. If wParam is not -1, lParam points to the wallpaper
  2389. * string.
  2390. */
  2391. if (wParam == (WPARAM)-1) {
  2392. break;
  2393. }
  2394. /*
  2395. * SetDeskPattern may take a string in lpData; if lpData
  2396. * is one of the magic values it obviously is not a string
  2397. */
  2398. if (lpData == IntToPtr(0xFFFFFFFF) || lpData == NULL) {
  2399. /*
  2400. * These are not really magic values, but in order not to break
  2401. * apps we have to keep them valid. wParam == -1 will make
  2402. * lParam be ignored.
  2403. */
  2404. wParam = -1;
  2405. break;
  2406. }
  2407. goto ProbeString;
  2408. case SPI_SETDESKWALLPAPER:
  2409. /*
  2410. * If the caller passed in (-1) in the wParam, then the
  2411. * wallpaper name is to be loaded later. Otherwise,
  2412. * they passed in a unicode string in the lParam.
  2413. */
  2414. if (wParam == (WPARAM)-1) {
  2415. break;
  2416. }
  2417. if (((LPWSTR)lpData == NULL) ||
  2418. ((LPWSTR)lpData == SETWALLPAPER_METRICS) ||
  2419. ((LPWSTR)lpData == SETWALLPAPER_DEFAULT)) {
  2420. break;
  2421. }
  2422. ProbeString:
  2423. /*
  2424. * Probe and capture the string. Capture is necessary to
  2425. * the pointer to be passed directly to the registry routines
  2426. * which cannot cleanly handle exceptions.
  2427. */
  2428. strData = ProbeAndReadUnicodeString((PUNICODE_STRING)lpData);
  2429. #if defined(_X86_)
  2430. ProbeForRead(strData.Buffer, strData.Length, sizeof(BYTE));
  2431. #else
  2432. ProbeForRead(strData.Buffer, strData.Length, sizeof(WCHAR));
  2433. #endif
  2434. lpData = UserAllocPoolWithQuota(strData.Length + sizeof(WCHAR), TAG_TEXT2);
  2435. if (lpData == NULL) {
  2436. ExRaiseStatus(STATUS_NO_MEMORY);
  2437. }
  2438. pti = PtiCurrent();
  2439. ThreadLockPool(pti, lpData, &tlBuffer);
  2440. fFreeBuffer = TRUE;
  2441. RtlCopyMemory(lpData,
  2442. strData.Buffer,
  2443. strData.Length);
  2444. ((PWSTR)lpData)[strData.Length / sizeof(WCHAR)] = 0;
  2445. break;
  2446. case SPI_SETBLOCKSENDINPUTRESETS:
  2447. /*
  2448. * This must be done a we must allow our value to be passed in wparam
  2449. * to be consistent with xxxUpdatePerUserSystemParameters(). If we allow
  2450. * This to fall through the default it will assert on us and the value will
  2451. * not get set properly.
  2452. */
  2453. break;
  2454. case SPI_SETMOUSE:
  2455. ulLength = sizeof(INT) * 3;
  2456. goto ProbeRead;
  2457. case SPI_SETICONTITLELOGFONT:
  2458. if (!ARGUMENT_PRESENT(lpData))
  2459. break;
  2460. ulLength = sizeof(LOGFONTW);
  2461. goto ProbeRead;
  2462. case SPI_SETMOUSEKEYS:
  2463. ulLength = sizeof(MOUSEKEYS);
  2464. goto ProbeRead;
  2465. case SPI_SETFILTERKEYS:
  2466. ulLength = sizeof(FILTERKEYS);
  2467. goto ProbeRead;
  2468. case SPI_SETSTICKYKEYS:
  2469. ulLength = sizeof(STICKYKEYS);
  2470. goto ProbeRead;
  2471. case SPI_SETTOGGLEKEYS:
  2472. ulLength = sizeof(TOGGLEKEYS);
  2473. goto ProbeRead;
  2474. case SPI_SETSOUNDSENTRY:
  2475. ulLength = sizeof(SOUNDSENTRY);
  2476. goto ProbeRead;
  2477. case SPI_SETACCESSTIMEOUT:
  2478. ulLength = sizeof(ACCESSTIMEOUT);
  2479. goto ProbeRead;
  2480. case SPI_SETWORKAREA:
  2481. ulLength = sizeof(RECT);
  2482. goto ProbeRead;
  2483. case SPI_SETANIMATION:
  2484. ulLength = sizeof(ANIMATIONINFO);
  2485. goto ProbeRead;
  2486. case SPI_SETNONCLIENTMETRICS:
  2487. ulLength = sizeof(NONCLIENTMETRICS);
  2488. goto ProbeRead;
  2489. case SPI_SETMINIMIZEDMETRICS:
  2490. ulLength = sizeof(MINIMIZEDMETRICS);
  2491. goto ProbeRead;
  2492. case SPI_SETICONMETRICS:
  2493. ulLength = sizeof(ICONMETRICS);
  2494. goto ProbeRead;
  2495. case SPI_SETDEFAULTINPUTLANG:
  2496. ulLength = sizeof(HKL);
  2497. goto ProbeRead;
  2498. case SPI_SETHIGHCONTRAST:
  2499. CaptureBuffer.ihc = ProbeAndReadStructure((INTERNALSETHIGHCONTRAST *)lpData, INTERNALSETHIGHCONTRAST);
  2500. lpData = &CaptureBuffer.ihc;
  2501. /*
  2502. * Now probe High Contrast string -- note that we send a client-side
  2503. * buffer pointer to the routine.
  2504. */
  2505. ProbeForReadUnicodeStringBuffer(CaptureBuffer.ihc.usDefaultScheme);
  2506. if (CaptureBuffer.ihc.usDefaultScheme.Length == 0) {
  2507. CaptureBuffer.ihc.usDefaultScheme.Buffer = NULL;
  2508. }
  2509. break;
  2510. /*
  2511. * Probe and capture the data. Capture is necessary to
  2512. * allow the pointer to be passed to the worker routines
  2513. * where exceptions cannot be cleanly handled.
  2514. */
  2515. ProbeRead:
  2516. #if defined(_X86_)
  2517. ProbeForRead(lpData, ulLength, sizeof(BYTE));
  2518. #else
  2519. ProbeForRead(lpData, ulLength, sizeof(DWORD));
  2520. #endif
  2521. RtlCopyMemory(&CaptureBuffer, lpData, ulLength);
  2522. lpData = &CaptureBuffer;
  2523. break;
  2524. case SPI_ICONHORIZONTALSPACING: // returns INT
  2525. case SPI_ICONVERTICALSPACING: // returns INT
  2526. if (!IS_PTR(lpData))
  2527. break;
  2528. /*
  2529. * Fall through and probe the data
  2530. */
  2531. case SPI_GETBEEP: // returns BOOL
  2532. case SPI_GETBORDER: // returns INT
  2533. case SPI_GETKEYBOARDSPEED: // returns DWORD
  2534. case SPI_GETKEYBOARDDELAY: // returns INT
  2535. case SPI_GETSCREENSAVETIMEOUT: // returns INT
  2536. case SPI_GETLOWPOWERTIMEOUT: // returns INT
  2537. case SPI_GETPOWEROFFTIMEOUT: // returns INT
  2538. case SPI_GETSCREENSAVEACTIVE: // returns BOOL
  2539. case SPI_GETBLOCKSENDINPUTRESETS: // returns BOOL
  2540. case SPI_GETLOWPOWERACTIVE: // returns BOOL
  2541. case SPI_GETPOWEROFFACTIVE: // returns BOOL
  2542. case SPI_GETGRIDGRANULARITY: // returns INT
  2543. case SPI_GETICONTITLEWRAP: // returns BOOL
  2544. case SPI_GETMENUDROPALIGNMENT: // returns BOOL
  2545. case SPI_GETFASTTASKSWITCH: // returns BOOL
  2546. case SPI_GETDRAGFULLWINDOWS: // returns INT
  2547. case SPI_GETSHOWSOUNDS: // returns BOOL
  2548. case SPI_GETFONTSMOOTHING: // returns INT
  2549. case SPI_GETSNAPTODEFBUTTON: // returns BOOL
  2550. case SPI_GETKEYBOARDPREF: // returns BOOL
  2551. case SPI_GETSCREENREADER: // returns BOOL
  2552. case SPI_GETMOUSEHOVERWIDTH:
  2553. case SPI_GETMOUSEHOVERHEIGHT:
  2554. case SPI_GETMOUSEHOVERTIME:
  2555. case SPI_GETWHEELSCROLLLINES:
  2556. case SPI_GETMENUSHOWDELAY:
  2557. case SPI_GETMOUSESPEED:
  2558. case SPI_GETMOUSETRAILS: // returns int
  2559. case SPI_GETSCREENSAVERRUNNING:
  2560. case SPI_GETSHOWIMEUI:
  2561. goto ProbeWriteUlong;
  2562. case SPI_GETDEFAULTINPUTLANG: // returns HKL
  2563. ulLength = sizeof(HKL);
  2564. goto ProbeWrite;
  2565. case SPI_GETICONTITLELOGFONT: // returns LOGFONT
  2566. ulLength = sizeof(LOGFONT);
  2567. goto ProbeWrite;
  2568. case SPI_GETMOUSE: // returns 3 INTs
  2569. ulLength = sizeof(INT) * 3;
  2570. goto ProbeWrite;
  2571. case SPI_GETFILTERKEYS: // returns FILTERKEYS
  2572. ulLength = sizeof(FILTERKEYS);
  2573. goto ProbeWrite;
  2574. case SPI_GETSTICKYKEYS: // returns STICKYKEYS
  2575. ulLength = sizeof(STICKYKEYS);
  2576. goto ProbeWrite;
  2577. case SPI_GETMOUSEKEYS: // returns MOUSEKEYS
  2578. ulLength = sizeof(MOUSEKEYS);
  2579. goto ProbeWrite;
  2580. case SPI_GETTOGGLEKEYS: // returns TOGGLEKEYS
  2581. ulLength = sizeof(TOGGLEKEYS);
  2582. goto ProbeWrite;
  2583. case SPI_GETSOUNDSENTRY: // returns SOUNDSENTRY
  2584. ulLength = sizeof(SOUNDSENTRY);
  2585. goto ProbeWrite;
  2586. case SPI_GETACCESSTIMEOUT: // returns ACCESSTIMEOUT
  2587. ulLength = sizeof(ACCESSTIMEOUT);
  2588. goto ProbeWrite;
  2589. case SPI_GETANIMATION: // returns ANIMATIONINFO
  2590. ulLength = sizeof(ANIMATIONINFO);
  2591. goto ProbeWrite;
  2592. case SPI_GETNONCLIENTMETRICS: // returns NONCLIENTMETRICS
  2593. ulLength = sizeof(NONCLIENTMETRICS);
  2594. goto ProbeWrite;
  2595. case SPI_GETMINIMIZEDMETRICS: // returns MINIMIZEDMETRICS
  2596. ulLength = sizeof(MINIMIZEDMETRICS);
  2597. goto ProbeWrite;
  2598. case SPI_GETICONMETRICS: // returns ICONMETRICS
  2599. ulLength = sizeof(ICONMETRICS);
  2600. goto ProbeWrite;
  2601. case SPI_GETHIGHCONTRAST: // returns HIGHCONTRAST
  2602. ulLength = sizeof(HIGHCONTRASTW);
  2603. ProbeForWrite(lpData, ulLength, DATAALIGN);
  2604. lpDataSave = lpData;
  2605. CaptureBuffer.hc = *((LPHIGHCONTRAST)lpData);
  2606. lpData = &CaptureBuffer.hc;
  2607. /*
  2608. * now probe string address
  2609. */
  2610. ulLength2 = MAX_SCHEME_NAME_SIZE * sizeof(WCHAR);
  2611. ProbeForWrite(((LPHIGHCONTRAST)lpData)->lpszDefaultScheme, ulLength2, CHARALIGN);
  2612. fWrite = TRUE;
  2613. break;
  2614. case SPI_GETWORKAREA: // returns RECT
  2615. ulLength = sizeof(RECT);
  2616. goto ProbeWrite;
  2617. case SPI_GETDESKWALLPAPER:
  2618. lpDataSave = lpData;
  2619. lpData = CaptureBuffer.szTemp;
  2620. ProbeForWriteBuffer((PWSTR)lpDataSave, wParam, CHARALIGN);
  2621. wParam = (wParam < MAX_PATH) ? wParam : MAX_PATH;
  2622. ulLength = wParam * sizeof(WCHAR);
  2623. fWrite = TRUE;
  2624. break;
  2625. default:
  2626. if (wFlag < SPI_MAX) {
  2627. break;
  2628. } else if (!UPIsBOOLRange(wFlag)
  2629. && !UPIsDWORDRange(wFlag)) {
  2630. RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "NtUserSystemParametersInfo: Invalid SPI_:%#lx", wFlag);
  2631. MSGERRORCLEANUP(0);
  2632. }
  2633. /*
  2634. * Let's enforce this or this parameter is gone for good.
  2635. */
  2636. if (wParam != 0) {
  2637. /*
  2638. * Too late, Winstone98 is alreay using it (incorrectly).
  2639. * Bummer, this has never been shipped and it's hacked already
  2640. * Allow a special case to go through
  2641. */
  2642. if (LOWORD((PtiCurrent()->dwExpWinVer) > VER40)
  2643. || (wFlag != SPI_SETUIEFFECTS)
  2644. || (wParam != 1)) {
  2645. RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "NtUserSystemParametersInfo: uiParam must be zero for SPI %#lx", wFlag);
  2646. MSGERRORCLEANUP(0);
  2647. }
  2648. }
  2649. UserAssert(wFlag & SPIF_RANGETYPEMASK);
  2650. if (wFlag & SPIF_SET) {
  2651. /*
  2652. * If your dword data needs to be validated (i.e, range, value),
  2653. * switch here on wFlag and do it here
  2654. */
  2655. switch (wFlag) {
  2656. case SPI_SETFOREGROUNDLOCKTIMEOUT:
  2657. if (!CanForceForeground(PpiCurrent() FG_HOOKLOCK_PARAM(PtiCurrent()))) {
  2658. RIPERR0(ERROR_ACCESS_DENIED, RIP_VERBOSE, "");
  2659. MSGERRORCLEANUP(0);
  2660. }
  2661. break;
  2662. case SPI_SETFONTSMOOTHINGTYPE:
  2663. if (PtrToInt(lpData) & ~FE_FONTSMOOTHINGTYPE_VALID) {
  2664. RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "");
  2665. MSGERRORCLEANUP(0);
  2666. }
  2667. break;
  2668. case SPI_SETFONTSMOOTHINGORIENTATION:
  2669. if (PtrToInt(lpData) & ~FE_FONTSMOOTHINGORIENTATION_VALID) {
  2670. RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "");
  2671. MSGERRORCLEANUP(0);
  2672. }
  2673. break;
  2674. }
  2675. } else {
  2676. ProbeWriteUlong:
  2677. ulLength = sizeof(ULONG);
  2678. lpDataSave = lpData;
  2679. lpData = &CaptureBuffer;
  2680. ProbeForWriteUlong((PULONG)lpDataSave);
  2681. fWrite = TRUE;
  2682. }
  2683. break;
  2684. /*
  2685. * Probe the data. wParam contains the length.
  2686. */
  2687. ProbeWrite:
  2688. lpDataSave = lpData;
  2689. lpData = &CaptureBuffer;
  2690. ProbeForWrite(lpDataSave, ulLength, DATAALIGN);
  2691. fWrite = TRUE;
  2692. /*
  2693. * Copy the first DWORD of the buffer. This will make sure that
  2694. * the cbSize parameter of some structures gets copied.
  2695. */
  2696. UserAssert(ulLength >= sizeof(DWORD));
  2697. *(LPDWORD)lpData=*(LPDWORD)lpDataSave;
  2698. }
  2699. } except (StubExceptionHandler(TRUE)) {
  2700. MSGERRORCLEANUP(0);
  2701. }
  2702. retval = xxxSystemParametersInfo(wFlag, wParam, lpData, flags);
  2703. /*
  2704. * Copy out any data we need to.
  2705. */
  2706. if (fWrite) {
  2707. try {
  2708. RtlCopyMemory(lpDataSave, lpData, ulLength);
  2709. } except (StubExceptionHandler(TRUE)) {
  2710. MSGERRORCLEANUP(0);
  2711. }
  2712. }
  2713. CLEANUPRECV();
  2714. if (fFreeBuffer)
  2715. ThreadUnlockAndFreePool(pti, &tlBuffer);
  2716. TRACE("NtUserSystemParametersInfo");
  2717. ENDRECV();
  2718. }
  2719. BOOL NtUserUpdatePerUserSystemParameters(
  2720. IN HANDLE hToken,
  2721. IN DWORD dwFlags)
  2722. {
  2723. BEGINRECV(BOOL, FALSE);
  2724. UNREFERENCED_PARAMETER(hToken);
  2725. retval = xxxUpdatePerUserSystemParameters(dwFlags);
  2726. TRACE("NtUserUpdatePerUserSystemParameters");
  2727. ENDRECV();
  2728. }
  2729. DWORD NtUserDdeInitialize( // API DdeInitializeA/W
  2730. OUT PHANDLE phInst,
  2731. OUT HWND *phwnd,
  2732. OUT LPDWORD pMonFlags,
  2733. IN DWORD afCmd,
  2734. IN PVOID pcii)
  2735. {
  2736. HANDLE hInst;
  2737. HWND hwnd;
  2738. DWORD MonFlags;
  2739. BEGINRECV(DWORD, DMLERR_INVALIDPARAMETER);
  2740. /*
  2741. * NOTE -- pcii is a value that is passed back to the client side
  2742. * for event callbacks. It is not probed because it is not used
  2743. * on the kernel side.
  2744. */
  2745. retval = xxxCsDdeInitialize(&hInst, &hwnd,
  2746. &MonFlags, afCmd, pcii);
  2747. /*
  2748. * Probe arguments. pcii is not dereferenced in the kernel so probing
  2749. * is not needed.
  2750. */
  2751. if (retval == DMLERR_NO_ERROR) {
  2752. try {
  2753. ProbeAndWriteHandle(phInst, hInst);
  2754. ProbeAndWriteHandle((PHANDLE)phwnd, hwnd);
  2755. ProbeAndWriteUlong(pMonFlags, MonFlags);
  2756. } except (StubExceptionHandler(TRUE)) {
  2757. xxxDestroyThreadDDEObject(PtiCurrent(), HtoP(hInst));
  2758. MSGERROR(0);
  2759. }
  2760. }
  2761. TRACE("NtUserDdeInitialize");
  2762. ENDRECV();
  2763. }
  2764. DWORD NtUserUpdateInstance( // private, but pMonFlags from API DdeInitializeA/W
  2765. IN HANDLE hInst,
  2766. OUT LPDWORD pMonFlags,
  2767. IN DWORD afCmd)
  2768. {
  2769. DWORD MonFlags;
  2770. BEGINRECV(DWORD, DMLERR_INVALIDPARAMETER);
  2771. /*
  2772. * Probe arguments
  2773. */
  2774. try {
  2775. ProbeForWriteUlong(pMonFlags);
  2776. } except (StubExceptionHandler(FALSE)) {
  2777. MSGERROR(0);
  2778. }
  2779. retval = _CsUpdateInstance(hInst, &MonFlags, afCmd);
  2780. try {
  2781. *pMonFlags = MonFlags;
  2782. } except (StubExceptionHandler(TRUE)) {
  2783. MSGERROR(0);
  2784. }
  2785. TRACE("NtUserUpdateInstance");
  2786. ENDRECV();
  2787. }
  2788. DWORD NtUserEvent( // private
  2789. IN PEVENT_PACKET pep)
  2790. {
  2791. WORD cbEventData;
  2792. BEGINRECV(DWORD, 0);
  2793. /*
  2794. * Probe arguments
  2795. */
  2796. try {
  2797. ProbeForRead(pep, sizeof(*pep), DATAALIGN);
  2798. /*
  2799. * capture so that another thread can't change it after the probe.
  2800. */
  2801. cbEventData = pep->cbEventData;
  2802. ProbeForRead(&pep->Data, cbEventData, DATAALIGN);
  2803. } except (StubExceptionHandler(FALSE)) {
  2804. MSGERROR(0);
  2805. }
  2806. /*
  2807. * The buffer is captured within a try/except in xxxCsEvent.
  2808. */
  2809. retval = xxxCsEvent((PEVENT_PACKET)pep, cbEventData);
  2810. TRACE("NtUserEvent");
  2811. ENDRECV();
  2812. }
  2813. BOOL NtUserFillWindow(
  2814. IN HWND hwndBrush,
  2815. IN HWND hwndPaint,
  2816. IN HDC hdc,
  2817. IN HBRUSH hbr)
  2818. {
  2819. PWND pwndBrush;
  2820. TL tlpwndBrush;
  2821. BEGINRECV_HWNDLOCK(DWORD, 0, hwndPaint);
  2822. if (hdc == NULL)
  2823. MSGERROR(0);
  2824. ValidateHWNDOPT(pwndBrush, hwndBrush);
  2825. ThreadLockWithPti(ptiCurrent, pwndBrush, &tlpwndBrush);
  2826. retval = xxxFillWindow(
  2827. pwndBrush,
  2828. pwnd,
  2829. hdc,
  2830. hbr);
  2831. ThreadUnlock(&tlpwndBrush);
  2832. TRACE("NtUserFillWindow");
  2833. ENDRECV_HWNDLOCK();
  2834. }
  2835. PCLS NtUserGetWOWClass( // wow
  2836. IN HINSTANCE hInstance,
  2837. IN PUNICODE_STRING pString)
  2838. {
  2839. UNICODE_STRING strClassName;
  2840. BEGINRECV_SHARED(PCLS, NULL);
  2841. /*
  2842. * Probe arguments
  2843. */
  2844. try {
  2845. strClassName = ProbeAndReadUnicodeString(pString);
  2846. ProbeForReadUnicodeStringBuffer(strClassName);
  2847. } except (StubExceptionHandler(FALSE)) {
  2848. MSGERROR(0);
  2849. }
  2850. retval = _GetWOWClass(
  2851. hInstance,
  2852. strClassName.Buffer);
  2853. TRACE("NtUserGetWOWClass");
  2854. ENDRECV_SHARED();
  2855. }
  2856. UINT NtUserGetInternalWindowPos( // private
  2857. IN HWND hwnd,
  2858. OUT LPRECT lpRect OPTIONAL,
  2859. OUT LPPOINT lpPoint OPTIONAL)
  2860. {
  2861. WINDOWPLACEMENT wp;
  2862. BEGINRECV_HWND_SHARED(DWORD, 0, hwnd);
  2863. /*
  2864. * Probe arguments
  2865. */
  2866. try {
  2867. if (ARGUMENT_PRESENT(lpRect)) {
  2868. ProbeForWriteRect(lpRect);
  2869. }
  2870. if (ARGUMENT_PRESENT(lpPoint)) {
  2871. ProbeForWritePoint(lpPoint);
  2872. }
  2873. } except (StubExceptionHandler(FALSE)) {
  2874. MSGERROR(0);
  2875. }
  2876. wp.length = sizeof(WINDOWPLACEMENT);
  2877. _GetWindowPlacement(pwnd, &wp);
  2878. retval = wp.showCmd;
  2879. try {
  2880. if (ARGUMENT_PRESENT(lpRect)) {
  2881. RtlCopyMemory(lpRect, &wp.rcNormalPosition, sizeof(RECT));
  2882. }
  2883. if (ARGUMENT_PRESENT(lpPoint)) {
  2884. RtlCopyMemory(lpPoint, &wp.ptMinPosition, sizeof(POINT));
  2885. }
  2886. } except (StubExceptionHandler(FALSE)) {
  2887. }
  2888. TRACE("NtUserGetInternalWindowPos");
  2889. ENDRECV_HWND_SHARED();
  2890. }
  2891. NTSTATUS NtUserInitTask( // wow
  2892. IN UINT dwExpWinVer,
  2893. IN DWORD dwAppCompatFlags,
  2894. IN DWORD dwUserWOWCompatFlags,
  2895. IN PUNICODE_STRING pstrModName,
  2896. IN PUNICODE_STRING pstrBaseFileName,
  2897. IN DWORD hTaskWow,
  2898. IN DWORD dwHotkey,
  2899. IN DWORD idTask,
  2900. IN DWORD dwX,
  2901. IN DWORD dwY,
  2902. IN DWORD dwXSize,
  2903. IN DWORD dwYSize)
  2904. {
  2905. UNICODE_STRING strModName;
  2906. UNICODE_STRING strBaseFileName;
  2907. BEGINRECV(NTSTATUS, STATUS_UNSUCCESSFUL);
  2908. /*
  2909. * Make sure this is really a WOW process.
  2910. */
  2911. if (PpiCurrent()->pwpi == NULL) {
  2912. MSGERROR(0);
  2913. }
  2914. /*
  2915. * Probe arguments
  2916. */
  2917. try {
  2918. strModName = ProbeAndReadUnicodeString(pstrModName);
  2919. /*
  2920. * pstrModName->Buffer has a UNICODE_NULL that's not counted in
  2921. * the length, but we want to include it for convenience. The
  2922. * probe routine does this.
  2923. */
  2924. ProbeForReadUnicodeStringBuffer(strModName);
  2925. if (pstrBaseFileName) {
  2926. strBaseFileName = ProbeAndReadUnicodeString(pstrBaseFileName);
  2927. ProbeForReadUnicodeStringBuffer(strBaseFileName);
  2928. }
  2929. } except (StubExceptionHandler(FALSE)) {
  2930. MSGERROR(0);
  2931. }
  2932. retval = zzzInitTask(
  2933. dwExpWinVer,
  2934. dwAppCompatFlags,
  2935. dwUserWOWCompatFlags,
  2936. &strModName,
  2937. pstrBaseFileName ? &strBaseFileName : NULL,
  2938. hTaskWow,
  2939. dwHotkey,
  2940. idTask,
  2941. dwX,
  2942. dwY,
  2943. dwXSize,
  2944. dwYSize);
  2945. TRACE("NtUserInitTask");
  2946. ENDRECV();
  2947. }
  2948. BOOL NtUserPostThreadMessage(
  2949. IN DWORD id,
  2950. IN UINT msg,
  2951. IN WPARAM wParam,
  2952. IN LPARAM lParam)
  2953. {
  2954. PTHREADINFO ptiCurrent, pti;
  2955. BEGINRECV(BOOL, FALSE);
  2956. /*
  2957. * Prevent apps from setting hi 16 bits so we can use them internally.
  2958. */
  2959. if (msg & MSGFLAG_MASK) {
  2960. RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid message");
  2961. MSGERROR(0);
  2962. }
  2963. pti = PtiFromThreadId(id);
  2964. if (pti == NULL) {
  2965. struct tagWOWPROCESSINFO *pwpi;
  2966. PTDB ptdb;
  2967. for (pwpi=gpwpiFirstWow; pwpi; pwpi=pwpi->pwpiNext) {
  2968. for (ptdb=pwpi->ptdbHead; ptdb; ptdb=ptdb->ptdbNext) {
  2969. if (ptdb->hTaskWow == id) {
  2970. pti=ptdb->pti;
  2971. goto PTM_DoIt;
  2972. }
  2973. }
  2974. }
  2975. RIPERR0(ERROR_INVALID_THREAD_ID, RIP_VERBOSE, "");
  2976. MSGERROR(0);
  2977. }
  2978. PTM_DoIt:
  2979. /*
  2980. * Should be OK if any of the following are true
  2981. * threads are running on the same desktop
  2982. * request is on behalf of a system process
  2983. * this process owns the desktop the thread is running in
  2984. * the LUIDs match
  2985. */
  2986. ptiCurrent = PtiCurrent();
  2987. if ( !(ptiCurrent->rpdesk == pti->rpdesk) &&
  2988. !(ptiCurrent->TIF_flags & TIF_CSRSSTHREAD) &&
  2989. !(GetDesktopView(ptiCurrent->ppi, pti->rpdesk))) {
  2990. LUID luidCurrent, luidTo;
  2991. if (!NT_SUCCESS(GetProcessLuid(ptiCurrent->pEThread, &luidCurrent)) ||
  2992. !NT_SUCCESS(GetProcessLuid(pti->pEThread, &luidTo)) ||
  2993. !RtlEqualLuid(&luidCurrent, &luidTo)) {
  2994. RIPERR3(ERROR_INVALID_THREAD_ID,
  2995. RIP_WARNING,
  2996. "NtUserPostThreadMessage failed LUID check: msg(%lx), t1(%#p) -> t2(%#p)",
  2997. msg, ptiCurrent, pti);
  2998. MSGERROR(0);
  2999. }
  3000. }
  3001. retval = _PostThreadMessage(
  3002. pti,
  3003. msg,
  3004. wParam,
  3005. lParam);
  3006. TRACE("NtUserPostThreadMessage");
  3007. ENDRECV();
  3008. }
  3009. BOOL NtUserRegisterTasklist(
  3010. IN HWND hwnd)
  3011. {
  3012. BEGINRECV_HWND(DWORD, 0, hwnd);
  3013. retval = _RegisterTasklist(
  3014. pwnd);
  3015. TRACE("NtUserRegisterTasklist");
  3016. ENDRECV_HWND();
  3017. }
  3018. BOOL NtUserCloseClipboard(
  3019. VOID)
  3020. {
  3021. BEGINRECV(BOOL, FALSE);
  3022. retval = xxxCloseClipboard(NULL);
  3023. TRACE("NtUserCloseClipboard");
  3024. ENDRECV();
  3025. }
  3026. BOOL NtUserEmptyClipboard(
  3027. VOID)
  3028. {
  3029. BEGINRECV(BOOL, FALSE);
  3030. retval = xxxEmptyClipboard(NULL);
  3031. TRACE("NtUserEmptyClipboard");
  3032. ENDRECV();
  3033. }
  3034. BOOL NtUserSetClipboardData( // API SetClipboardData
  3035. IN UINT fmt,
  3036. IN HANDLE hData,
  3037. IN PSETCLIPBDATA pscd)
  3038. {
  3039. SETCLIPBDATA scd;
  3040. BEGINRECV(BOOL, FALSE);
  3041. /*
  3042. * Check for jobs with JOB_OBJECT_UILIMIT_WRITECLIPBOARD
  3043. */
  3044. if (IS_CURRENT_THREAD_RESTRICTED(JOB_OBJECT_UILIMIT_WRITECLIPBOARD)) {
  3045. RIPMSG0(RIP_WARNING, "NtUserSetClipboardData failed for restricted thread");
  3046. MSGERROR(0);
  3047. }
  3048. /*
  3049. * Probe arguments
  3050. */
  3051. try {
  3052. scd = ProbeAndReadSetClipBData(pscd);
  3053. } except (StubExceptionHandler(TRUE)) {
  3054. MSGERROR(0);
  3055. }
  3056. retval = _SetClipboardData(
  3057. fmt,
  3058. hData,
  3059. scd.fGlobalHandle,
  3060. scd.fIncSerialNumber);
  3061. TRACE("NtUserSetClipboardData");
  3062. ENDRECV();
  3063. }
  3064. HANDLE NtUserConvertMemHandle( // worker routine, lpData not from API
  3065. IN LPBYTE lpData,
  3066. IN UINT cbData)
  3067. {
  3068. BEGINRECV(HANDLE, NULL);
  3069. /*
  3070. * Probe arguments
  3071. */
  3072. try {
  3073. ProbeForRead(lpData, cbData, sizeof(BYTE));
  3074. } except (StubExceptionHandler(FALSE)) {
  3075. MSGERROR(0);
  3076. }
  3077. /*
  3078. * lpData is client-side.
  3079. */
  3080. retval = _ConvertMemHandle(lpData, cbData);
  3081. TRACE("NtUserConvertMemHandle");
  3082. ENDRECV();
  3083. }
  3084. NTSTATUS NtUserCreateLocalMemHandle( // helper routine
  3085. IN HANDLE hMem,
  3086. OUT LPBYTE lpData OPTIONAL,
  3087. IN UINT cbData,
  3088. OUT PUINT lpcbNeeded OPTIONAL)
  3089. {
  3090. PCLIPDATA pClipData;
  3091. BEGINRECV(NTSTATUS, STATUS_INVALID_HANDLE);
  3092. pClipData = HMValidateHandle(hMem, TYPE_CLIPDATA);
  3093. if (pClipData == NULL)
  3094. MSGERROR(0);
  3095. /*
  3096. * Probe arguments
  3097. */
  3098. try {
  3099. if (ARGUMENT_PRESENT(lpData)) {
  3100. ProbeForWrite(lpData, cbData, sizeof(BYTE));
  3101. }
  3102. if (ARGUMENT_PRESENT(lpcbNeeded)) {
  3103. ProbeAndWriteUlong(lpcbNeeded, pClipData->cbData);
  3104. }
  3105. if (!ARGUMENT_PRESENT(lpData) || cbData < pClipData->cbData) {
  3106. retval = STATUS_BUFFER_TOO_SMALL;
  3107. } else {
  3108. RtlCopyMemory(lpData, &pClipData->abData, pClipData->cbData);
  3109. retval = STATUS_SUCCESS;
  3110. }
  3111. } except (StubExceptionHandler(FALSE)) {
  3112. MSGERROR(0);
  3113. }
  3114. TRACE("NtUserCreateLocalMemHandle");
  3115. ENDRECV();
  3116. }
  3117. HHOOK NtUserSetWindowsHookEx(
  3118. IN HANDLE hmod,
  3119. IN PUNICODE_STRING pstrLib OPTIONAL,
  3120. IN DWORD idThread,
  3121. IN int nFilterType,
  3122. IN PROC pfnFilterProc,
  3123. IN DWORD dwFlags)
  3124. {
  3125. PTHREADINFO ptiThread;
  3126. BEGINRECV(HHOOK, NULL);
  3127. if (idThread != 0) {
  3128. ptiThread = PtiFromThreadId(idThread);
  3129. if (ptiThread == NULL) {
  3130. RIPERR0(ERROR_INVALID_PARAMETER, RIP_VERBOSE, "");
  3131. MSGERROR(0);
  3132. }
  3133. } else {
  3134. ptiThread = NULL;
  3135. }
  3136. /*
  3137. * Probe pstrLib in GetHmodTableIndex().
  3138. */
  3139. retval = (HHOOK)zzzSetWindowsHookEx(
  3140. hmod,
  3141. pstrLib,
  3142. ptiThread,
  3143. nFilterType,
  3144. pfnFilterProc,
  3145. dwFlags);
  3146. retval = PtoH((PVOID)retval);
  3147. TRACE("NtUserSetWindowsHookEx");
  3148. ENDRECV();
  3149. }
  3150. HWINEVENTHOOK NtUserSetWinEventHook(
  3151. IN DWORD eventMin,
  3152. IN DWORD eventMax,
  3153. IN HMODULE hmodWinEventProc,
  3154. IN PUNICODE_STRING pstrLib OPTIONAL,
  3155. IN WINEVENTPROC pfnWinEventProc,
  3156. IN DWORD idEventProcess,
  3157. IN DWORD idEventThread,
  3158. IN DWORD dwFlags)
  3159. {
  3160. BEGINRECV(HWINEVENTHOOK, NULL);
  3161. TESTFLAGS(dwFlags, WINEVENT_VALID);
  3162. /*
  3163. * Probe pstrLib in GetHmodTableIndex().
  3164. */
  3165. retval = (HWINEVENTHOOK)_SetWinEventHook(
  3166. eventMin,
  3167. eventMax,
  3168. hmodWinEventProc,
  3169. pstrLib,
  3170. pfnWinEventProc,
  3171. LongToHandle(idEventProcess),
  3172. idEventThread,
  3173. dwFlags);
  3174. retval = PtoH((PVOID)retval);
  3175. TRACE("NtUserSetWinEventHook");
  3176. ENDRECV();
  3177. }
  3178. BOOL NtUserUnhookWinEvent(
  3179. IN HWINEVENTHOOK hWinEventUnhook)
  3180. {
  3181. PEVENTHOOK peh;
  3182. BEGINATOMICRECV(BOOL, FALSE);
  3183. ValidateHWINEVENTHOOK(peh, hWinEventUnhook);
  3184. retval = _UnhookWinEvent(peh);
  3185. TRACE("NtUserUnhookWinEvent");
  3186. ENDATOMICRECV();
  3187. }
  3188. VOID NtUserNotifyWinEvent(
  3189. IN DWORD event,
  3190. IN HWND hwnd,
  3191. IN LONG idObject,
  3192. IN LONG idChild)
  3193. {
  3194. BEGINRECV_HWNDLOCK_VOID(hwnd);
  3195. xxxWindowEvent(event, pwnd, idObject, idChild, WEF_USEPWNDTHREAD);
  3196. TRACEVOID("NtUserNotifyWinEvent");
  3197. ENDRECV_HWNDLOCK_VOID();
  3198. }
  3199. BOOL NtUserRegisterUserApiHook(
  3200. IN PUNICODE_STRING pstrLib,
  3201. IN ULONG_PTR offPfnInitUserApiHook)
  3202. {
  3203. BEGINATOMICRECV(BOOL, FALSE);
  3204. /*
  3205. * Probe pstrLib in GetHmodTableIndex().
  3206. */
  3207. retval = _RegisterUserApiHook(
  3208. pstrLib,
  3209. offPfnInitUserApiHook);
  3210. TRACE("NtUserRegisterUserApiHook");
  3211. ENDATOMICRECV();
  3212. }
  3213. BOOL NtUserUnregisterUserApiHook(VOID)
  3214. {
  3215. BEGINATOMICRECV(BOOL, FALSE);
  3216. retval = _UnregisterUserApiHook();
  3217. TRACE("NtUserUnregisterUserApiHook");
  3218. ENDATOMICRECV();
  3219. }
  3220. BOOL NtUserGetGUIThreadInfo( // API GetGUIThreadInfo
  3221. IN DWORD idThread,
  3222. IN OUT PGUITHREADINFO pgui)
  3223. {
  3224. PTHREADINFO ptiThread;
  3225. GUITHREADINFO gui;
  3226. BEGINRECV_SHARED(BOOL, FALSE);
  3227. if (idThread) {
  3228. ptiThread = PtiFromThreadId(idThread);
  3229. if (ptiThread == NULL) {
  3230. RIPERR0(ERROR_INVALID_PARAMETER, RIP_VERBOSE, "Bad thread id");
  3231. MSGERROR(0);
  3232. }
  3233. } else {
  3234. ptiThread = NULL;
  3235. }
  3236. /*
  3237. * Probe arguments and copy results
  3238. * C2: test pti & current thread on same desktop within _GetGUIThreadInfo
  3239. */
  3240. try {
  3241. ProbeForWrite(pgui, sizeof(*pgui), DATAALIGN);
  3242. gui.cbSize = pgui->cbSize;
  3243. } except (StubExceptionHandler(TRUE)) {
  3244. MSGERROR(0);
  3245. }
  3246. retval = _GetGUIThreadInfo(ptiThread, &gui);
  3247. if (retval) {
  3248. try {
  3249. *pgui = gui;
  3250. } except (StubExceptionHandler(TRUE)) {
  3251. MSGERROR(0);
  3252. }
  3253. }
  3254. TRACE("NtUserGetGUIThreadInfo");
  3255. ENDRECV_SHARED();
  3256. }
  3257. /*****************************************************************************\
  3258. * GetTitleBarInfo
  3259. *
  3260. * Gets information about the title bar
  3261. \*****************************************************************************/
  3262. BOOL NtUserGetTitleBarInfo(IN HWND hwnd, IN OUT PTITLEBARINFO ptbi)
  3263. {
  3264. TITLEBARINFO tbi;
  3265. BEGINRECV_HWNDLOCK(BOOL, FALSE, hwnd);
  3266. /*
  3267. * Probe arguments and copy out results
  3268. */
  3269. try {
  3270. ProbeForWrite(ptbi, sizeof(*ptbi), DATAALIGN);
  3271. tbi.cbSize = ptbi->cbSize;
  3272. } except (StubExceptionHandler(TRUE)) {
  3273. MSGERROR(0);
  3274. }
  3275. /*
  3276. * Get the titlebar info
  3277. */
  3278. retval = xxxGetTitleBarInfo(pwnd, &tbi);
  3279. if (retval) {
  3280. try {
  3281. *ptbi = tbi;
  3282. } except (StubExceptionHandler(TRUE)) {
  3283. MSGERROR(0);
  3284. }
  3285. }
  3286. TRACE("NtUserGetTitleBarInfo");
  3287. ENDRECV_HWNDLOCK();
  3288. }
  3289. /*****************************************************************************\
  3290. * NtUserGetComboBoxInfo
  3291. *
  3292. * Gets information about the combo box
  3293. \*****************************************************************************/
  3294. BOOL NtUserGetComboBoxInfo(IN HWND hwnd, IN OUT PCOMBOBOXINFO pcbi)
  3295. {
  3296. COMBOBOXINFO cbi;
  3297. BEGINRECV_HWNDLOCK(BOOL, FALSE, hwnd);
  3298. /*
  3299. * Probe arguments and copy out results
  3300. */
  3301. try {
  3302. ProbeForWrite(pcbi, sizeof(*pcbi), DATAALIGN);
  3303. cbi.cbSize = pcbi->cbSize;
  3304. } except (StubExceptionHandler(TRUE)) {
  3305. MSGERROR(0);
  3306. }
  3307. /*
  3308. * Get the combobox info
  3309. */
  3310. retval = xxxGetComboBoxInfo(pwnd, &cbi);
  3311. if (retval) {
  3312. try {
  3313. *pcbi = cbi;
  3314. } except (StubExceptionHandler(TRUE)) {
  3315. MSGERROR(0);
  3316. }
  3317. }
  3318. TRACE("NtUserGetComboBoxInfo");
  3319. ENDRECV_HWNDLOCK();
  3320. }
  3321. /*****************************************************************************\
  3322. * NtUserGetListBoxInfo
  3323. *
  3324. * Gets information about the list box
  3325. \*****************************************************************************/
  3326. DWORD NtUserGetListBoxInfo(IN HWND hwnd)
  3327. {
  3328. BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
  3329. /*
  3330. * Get the listbox info
  3331. */
  3332. retval = xxxGetListBoxInfo(pwnd);
  3333. TRACE("NtUserGetListBoxInfo");
  3334. ENDRECV_HWNDLOCK();
  3335. }
  3336. /*****************************************************************************\
  3337. * GetCursorInfo
  3338. *
  3339. * Gets information about the global cursor
  3340. \*****************************************************************************/
  3341. BOOL NtUserGetCursorInfo(IN OUT PCURSORINFO pci)
  3342. {
  3343. CURSORINFO ci = {0};
  3344. BEGINRECV_SHARED(BOOL, FALSE);
  3345. ci.ptScreenPos = gpsi->ptCursor;
  3346. ci.flags = 0;
  3347. if (gpcurPhysCurrent)
  3348. ci.flags |= CURSOR_SHOWING;
  3349. /*
  3350. * Get the current LOGICAL cursor (the one apps actually see from LoadCursor())
  3351. */
  3352. ci.hCursor = (HCURSOR)PtoH(gpcurLogCurrent);
  3353. retval = TRUE;
  3354. /*
  3355. * Probe arguments and copy out result
  3356. */
  3357. try {
  3358. ProbeForWrite(pci, sizeof(*pci), DATAALIGN);
  3359. if (pci->cbSize != sizeof(CURSORINFO)) {
  3360. RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "CURSORINFO.cbSize %d is wrong", pci->cbSize);
  3361. retval = FALSE;
  3362. } else {
  3363. *pci = ci;
  3364. }
  3365. } except (StubExceptionHandler(TRUE)) {
  3366. MSGERROR(0);
  3367. }
  3368. TRACE("NtUserGetCursorInfo");
  3369. ENDRECV_SHARED();
  3370. }
  3371. /*****************************************************************************\
  3372. * GetScrollBarInfo
  3373. *
  3374. * Gets information about the scroll bar
  3375. \*****************************************************************************/
  3376. BOOL NtUserGetScrollBarInfo(IN HWND hwnd, IN LONG idObject, IN OUT PSCROLLBARINFO psbi)
  3377. {
  3378. SCROLLBARINFO sbi;
  3379. BEGINRECV_HWNDLOCK(BOOL, FALSE, hwnd);
  3380. /*
  3381. * Probe arguments and copy out results
  3382. */
  3383. try {
  3384. ProbeForWrite(psbi, sizeof(*psbi), DATAALIGN);
  3385. sbi.cbSize = psbi->cbSize;
  3386. } except (StubExceptionHandler(TRUE)) {
  3387. MSGERROR(0);
  3388. }
  3389. /*
  3390. * Get the scrollbar info
  3391. */
  3392. retval = xxxGetScrollBarInfo(pwnd, idObject, &sbi);
  3393. if (retval) {
  3394. try {
  3395. *psbi = sbi;
  3396. } except (StubExceptionHandler(TRUE)) {
  3397. MSGERROR(0);
  3398. }
  3399. }
  3400. TRACE("NtUserGetScrollBarInfo");
  3401. ENDRECV_HWNDLOCK();
  3402. }
  3403. HWND NtUserGetAncestor(IN HWND hwndChild, IN UINT gaFlags)
  3404. {
  3405. BEGINRECV_HWND_SHARED(HWND, NULL, hwndChild);
  3406. if ((gaFlags < GA_MIN) || (gaFlags > GA_MAX)) {
  3407. RIPERR3(ERROR_INVALID_PARAMETER, RIP_WARNING,
  3408. "NtUserGetAncestor: Invalid gaFlags parameter %d, not %d - %d",
  3409. gaFlags, GA_MIN, GA_MAX);
  3410. MSGERROR(0);
  3411. }
  3412. retval = (HWND)_GetAncestor(pwnd, gaFlags);
  3413. retval = PtoH((PVOID)retval);
  3414. TRACE("NtUserGetAncestor");
  3415. ENDRECV_HWND_SHARED();
  3416. }
  3417. HWND NtUserRealChildWindowFromPoint(IN HWND hwndParent, IN POINT pt)
  3418. {
  3419. BEGINRECV_HWND_SHARED(HWND, NULL, hwndParent);
  3420. retval = (HWND)_RealChildWindowFromPoint(pwnd, pt);
  3421. retval = PtoH((PVOID)retval);
  3422. TRACE("NtUserRealChildWindowFromPoint");
  3423. ENDRECV_HWND_SHARED();
  3424. }
  3425. BOOL NtUserGetAltTabInfo(
  3426. IN HWND hwnd,
  3427. IN int iItem,
  3428. IN OUT PALTTABINFO pati,
  3429. OUT LPWSTR lpszItemText,
  3430. IN UINT cchItemText OPTIONAL,
  3431. BOOL bAnsi)
  3432. {
  3433. ALTTABINFO ati;
  3434. BEGINRECV_HWNDOPT_SHARED(BOOL, FALSE, hwnd);
  3435. /*
  3436. * If the specified window is not a switch window, then fail the call.
  3437. * It's a dumb API we got from Windows 95, I am hereby allowing NULL hwnd.
  3438. */
  3439. if (pwnd && (pwnd != gspwndAltTab)) {
  3440. MSGERROR(ERROR_INVALID_WINDOW_HANDLE);
  3441. }
  3442. /*
  3443. * Probe arguments
  3444. */
  3445. try {
  3446. ProbeForWrite(pati, sizeof(*pati), DATAALIGN);
  3447. if (bAnsi) {
  3448. ProbeForWriteBuffer((LPSTR)lpszItemText, cchItemText, CHARALIGN);
  3449. } else {
  3450. ProbeForWriteBuffer(lpszItemText, cchItemText, CHARALIGN);
  3451. }
  3452. /*
  3453. * Validate AltTabInfo structure
  3454. */
  3455. if (pati->cbSize != sizeof(ALTTABINFO)) {
  3456. RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "ALTTABINFO.cbSize %d is wrong", pati->cbSize);
  3457. MSGERROR(0);
  3458. }
  3459. } except (StubExceptionHandler(TRUE)) {
  3460. MSGERROR(0);
  3461. }
  3462. /*
  3463. * Get the alt tab info
  3464. */
  3465. ati.cbSize = sizeof(ALTTABINFO);
  3466. retval = _GetAltTabInfo(iItem, &ati, lpszItemText, cchItemText, bAnsi);
  3467. if (retval) {
  3468. try {
  3469. *pati = ati;
  3470. } except (StubExceptionHandler(TRUE)) {
  3471. MSGERROR(0);
  3472. }
  3473. }
  3474. TRACE("NtUserGetAltTabInfo");
  3475. ENDRECV_HWNDOPT_SHARED();
  3476. }
  3477. BOOL NtUserGetMenuBarInfo(
  3478. IN HWND hwnd,
  3479. IN long idObject,
  3480. IN long idItem,
  3481. IN OUT PMENUBARINFO pmbi)
  3482. {
  3483. MENUBARINFO mbi;
  3484. BEGINRECV_HWNDLOCK(BOOL, FALSE, hwnd);
  3485. /*
  3486. * Probe arguments
  3487. */
  3488. try {
  3489. #if defined(_X86_)
  3490. ProbeForWrite(pmbi, sizeof(*pmbi), sizeof(BYTE));
  3491. #else
  3492. ProbeForWrite(pmbi, sizeof(*pmbi), sizeof(DWORD));
  3493. #endif
  3494. mbi.cbSize = pmbi->cbSize;
  3495. } except (StubExceptionHandler(TRUE)) {
  3496. MSGERROR(0);
  3497. }
  3498. /*
  3499. * Get the menubar info
  3500. */
  3501. retval = xxxGetMenuBarInfo(pwnd, idObject, idItem, &mbi);
  3502. if (retval) {
  3503. try {
  3504. *pmbi = mbi;
  3505. } except (StubExceptionHandler(TRUE)) {
  3506. MSGERROR(0);
  3507. }
  3508. }
  3509. TRACE("NtUserGetMenuBarInfo");
  3510. ENDRECV_HWNDLOCK();
  3511. }
  3512. BOOL NtUserSetInternalWindowPos( // private SetInternalWindowPos
  3513. IN HWND hwnd,
  3514. IN UINT cmdShow,
  3515. IN CONST RECT *lpRect,
  3516. IN CONST POINT *lpPoint)
  3517. {
  3518. RECT rc;
  3519. POINT pt;
  3520. BEGINRECV_HWNDLOCK_ND(BOOL, FALSE, hwnd);
  3521. /*
  3522. * Probe arguments
  3523. */
  3524. try {
  3525. rc = ProbeAndReadRect(lpRect);
  3526. pt = ProbeAndReadPoint(lpPoint);
  3527. } except (StubExceptionHandler(FALSE)) {
  3528. MSGERROR(0);
  3529. }
  3530. retval = xxxSetInternalWindowPos(
  3531. pwndND,
  3532. cmdShow,
  3533. &rc,
  3534. &pt);
  3535. TRACE("NtUserSetInternalWindowPos");
  3536. ENDRECV_HWNDLOCK_ND();
  3537. }
  3538. BOOL NtUserChangeClipboardChain(
  3539. IN HWND hwndRemove,
  3540. IN HWND hwndNewNext)
  3541. {
  3542. PWND pwndNewNext;
  3543. TL tlpwndNewNext;
  3544. BEGINRECV_HWNDLOCK(DWORD, 0, hwndRemove);
  3545. ValidateHWNDOPT(pwndNewNext, hwndNewNext);
  3546. ThreadLockWithPti(ptiCurrent, pwndNewNext, &tlpwndNewNext);
  3547. retval = xxxChangeClipboardChain(
  3548. pwnd,
  3549. pwndNewNext);
  3550. ThreadUnlock(&tlpwndNewNext);
  3551. TRACE("NtUserChangeClipboardChain");
  3552. ENDRECV_HWNDLOCK();
  3553. }
  3554. DWORD NtUserCheckMenuItem(
  3555. IN HMENU hmenu,
  3556. IN UINT wIDCheckItem,
  3557. IN UINT wCheck)
  3558. {
  3559. PMENU pmenu;
  3560. BEGINATOMICRECV(DWORD, (DWORD)-1);
  3561. TESTFLAGS(wCheck, MF_VALID);
  3562. ValidateHMENUMODIFY(pmenu, hmenu);
  3563. retval = _CheckMenuItem(
  3564. pmenu,
  3565. wIDCheckItem,
  3566. wCheck);
  3567. TRACE("NtUserCheckMenuItem");
  3568. ENDATOMICRECV();
  3569. }
  3570. HWND NtUserChildWindowFromPointEx(
  3571. IN HWND hwndParent,
  3572. IN POINT point,
  3573. IN UINT flags)
  3574. {
  3575. BEGINRECV_HWND(HWND, NULL, hwndParent);
  3576. retval = (HWND)_ChildWindowFromPointEx(pwnd, point, flags);
  3577. retval = PtoH((PVOID)retval);
  3578. TRACE("NtUserChildWindowFromPointEx");
  3579. ENDRECV_HWND();
  3580. }
  3581. BOOL NtUserClipCursor( // API ClipCursor
  3582. IN CONST RECT *lpRect OPTIONAL)
  3583. {
  3584. RECT rc;
  3585. BEGINRECV(BOOL, FALSE);
  3586. /*
  3587. * Probe arguments
  3588. */
  3589. if (ARGUMENT_PRESENT(lpRect)) {
  3590. try {
  3591. rc = ProbeAndReadRect(lpRect);
  3592. lpRect = &rc;
  3593. } except (StubExceptionHandler(TRUE)) {
  3594. MSGERROR(0);
  3595. }
  3596. }
  3597. retval = zzzClipCursor(lpRect);
  3598. TRACE("NtUserClipCursor");
  3599. ENDRECV();
  3600. }
  3601. HACCEL NtUserCreateAcceleratorTable( // API CreateAcceleratorTableA/W
  3602. IN LPACCEL paccel,
  3603. IN INT cAccel)
  3604. {
  3605. BEGINRECV(HACCEL, NULL);
  3606. if (cAccel <= 0) {
  3607. MSGERROR(0);
  3608. }
  3609. /*
  3610. * Probe arguments
  3611. */
  3612. try {
  3613. ProbeForReadBuffer(paccel, cAccel, DATAALIGN);
  3614. } except (StubExceptionHandler(TRUE)) {
  3615. MSGERROR(0);
  3616. }
  3617. retval = (HACCEL)_CreateAcceleratorTable(
  3618. paccel,
  3619. cAccel * sizeof(ACCEL));
  3620. retval = PtoH((PVOID)retval);
  3621. TRACE("NtUserCreateAcceleratorTable");
  3622. ENDRECV();
  3623. }
  3624. BOOL NtUserDeleteMenu(
  3625. IN HMENU hmenu,
  3626. IN UINT nPosition,
  3627. IN UINT dwFlags)
  3628. {
  3629. PMENU pmenu;
  3630. TL tlpMenu;
  3631. BEGINRECV(BOOL, FALSE);
  3632. TESTFLAGS(dwFlags, MF_VALID);
  3633. ValidateHMENUMODIFYCHECKLOCK(pmenu, hmenu);
  3634. ThreadLock(pmenu, &tlpMenu);
  3635. retval = xxxDeleteMenu(
  3636. pmenu,
  3637. nPosition,
  3638. dwFlags);
  3639. ThreadUnlock(&tlpMenu);
  3640. TRACE("NtUserDeleteMenu");
  3641. ENDRECV();
  3642. }
  3643. BOOL NtUserDestroyAcceleratorTable(
  3644. IN HACCEL hAccel)
  3645. {
  3646. LPACCELTABLE pat;
  3647. BEGINRECV(BOOL, FALSE);
  3648. ValidateHACCEL(pat, hAccel);
  3649. /*
  3650. * Mark the object for destruction - if it says it's ok to free,
  3651. * then free it.
  3652. */
  3653. if (HMMarkObjectDestroy(pat)) {
  3654. HMFreeObject(pat);
  3655. }
  3656. retval = TRUE;
  3657. TRACE("NtUserDestroyAcceleratorTable");
  3658. ENDRECV();
  3659. }
  3660. BOOL NtUserDestroyCursor(
  3661. IN HCURSOR hcurs,
  3662. IN DWORD cmd)
  3663. {
  3664. PCURSOR pcurs;
  3665. BEGINATOMICRECV(BOOL, FALSE);
  3666. ValidateHCURSOR(pcurs, hcurs);
  3667. retval = _DestroyCursor(pcurs, cmd);
  3668. TRACE("NtUserDestroyCursor");
  3669. ENDATOMICRECV();
  3670. }
  3671. HANDLE NtUserGetClipboardData( // API GetClipboardData
  3672. IN UINT fmt,
  3673. OUT PGETCLIPBDATA pgcd)
  3674. {
  3675. PTHREADINFO ptiCurrent;
  3676. TL tlpwinsta;
  3677. PWINDOWSTATION pwinsta;
  3678. GETCLIPBDATA gcd;
  3679. BEGINRECV(HANDLE, NULL);
  3680. ptiCurrent = PtiCurrent();
  3681. if ((pwinsta = CheckClipboardAccess()) == NULL) {
  3682. MSGERROR(0);
  3683. }
  3684. /*
  3685. * Check for jobs with JOB_OBJECT_UILIMIT_READCLIPBOARD
  3686. */
  3687. if (IS_THREAD_RESTRICTED(ptiCurrent, JOB_OBJECT_UILIMIT_READCLIPBOARD)) {
  3688. RIPERR0(ERROR_ACCESS_DENIED, RIP_WARNING, "NtUserGetClipboardData failed for restricted thread");
  3689. MSGERROR(0);
  3690. }
  3691. ThreadLockWinSta(ptiCurrent, pwinsta, &tlpwinsta);
  3692. /*
  3693. * Start out assuming the format requested
  3694. * will be the format returned.
  3695. */
  3696. gcd.uFmtRet = fmt;
  3697. retval = xxxGetClipboardData(pwinsta, fmt, &gcd);
  3698. /*
  3699. * Probe arguments
  3700. */
  3701. try {
  3702. ProbeAndWriteStructure(pgcd, gcd, GETCLIPBDATA);
  3703. } except (StubExceptionHandler(TRUE)) {
  3704. MSGERRORCLEANUP(0);
  3705. }
  3706. CLEANUPRECV();
  3707. ThreadUnlockWinSta(ptiCurrent, &tlpwinsta);
  3708. TRACE("NtUserGetClipboardData");
  3709. ENDRECV();
  3710. }
  3711. BOOL NtUserDestroyMenu(
  3712. IN HMENU hmenu)
  3713. {
  3714. PMENU pmenu;
  3715. BEGINATOMICRECV(BOOL, FALSE);
  3716. ValidateHMENUMODIFY(pmenu, hmenu);
  3717. retval = _DestroyMenu(pmenu);
  3718. TRACE("NtUserDestroyMenu");
  3719. ENDATOMICRECV();
  3720. }
  3721. BOOL NtUserDestroyWindow(
  3722. IN HWND hwnd)
  3723. {
  3724. BEGINRECV_HWND(DWORD, 0, hwnd);
  3725. retval = xxxDestroyWindow(pwnd);
  3726. TRACE("NtUserDestroyWindow");
  3727. ENDRECV_HWND();
  3728. }
  3729. LRESULT NtUserDispatchMessage( // API DispatchMessageA/W
  3730. IN CONST MSG *pmsg)
  3731. {
  3732. MSG msg;
  3733. BEGINRECV(LRESULT, 0);
  3734. /*
  3735. * Probe arguments
  3736. */
  3737. try {
  3738. msg = ProbeAndReadMessage(pmsg);
  3739. } except (StubExceptionHandler(TRUE)) {
  3740. MSGERROR(0);
  3741. }
  3742. retval = xxxDispatchMessage(&msg);
  3743. TRACE("NtUserDispatchMessage");
  3744. ENDRECV();
  3745. }
  3746. BOOL NtUserEnableMenuItem(
  3747. IN HMENU hMenu,
  3748. IN UINT wIDEnableItem,
  3749. IN UINT wEnable)
  3750. {
  3751. PMENU pmenu;
  3752. TL tlpMenu;
  3753. BEGINRECV(BOOL, -1);
  3754. TESTFLAGS(wEnable, MF_VALID);
  3755. ValidateHMENUMODIFY(pmenu, hMenu);
  3756. ThreadLockAlways(pmenu, &tlpMenu);
  3757. retval = xxxEnableMenuItem(
  3758. pmenu,
  3759. wIDEnableItem,
  3760. wEnable);
  3761. ThreadUnlock(&tlpMenu);
  3762. TRACE("NtUserEnableMenuItem");
  3763. ENDRECV();
  3764. }
  3765. BOOL NtUserAttachThreadInput(
  3766. IN DWORD idAttach,
  3767. IN DWORD idAttachTo,
  3768. IN BOOL fAttach)
  3769. {
  3770. PTHREADINFO ptiAttach;
  3771. PTHREADINFO ptiAttachTo;
  3772. BEGINRECV(BOOL, FALSE);
  3773. /*
  3774. * Always must attach or detach from a real thread id.
  3775. */
  3776. if ((ptiAttach = PtiFromThreadId(idAttach)) == NULL) {
  3777. MSGERROR(0);
  3778. }
  3779. if ((ptiAttachTo = PtiFromThreadId(idAttachTo)) == NULL) {
  3780. MSGERROR(0);
  3781. }
  3782. retval = zzzAttachThreadInput(
  3783. ptiAttach,
  3784. ptiAttachTo,
  3785. fAttach);
  3786. TRACE("NtUserAttachThreadInput");
  3787. ENDRECV();
  3788. }
  3789. BOOL NtUserGetWindowPlacement( // API GetWindowPlacement
  3790. IN HWND hwnd,
  3791. OUT PWINDOWPLACEMENT pwp)
  3792. {
  3793. WINDOWPLACEMENT wp;
  3794. BEGINRECV_HWND(DWORD, 0, hwnd);
  3795. /*
  3796. * Probe arguments
  3797. */
  3798. try {
  3799. ProbeForWriteWindowPlacement(pwp);
  3800. wp.length = pwp->length;
  3801. #ifdef LATER
  3802. if (pwp->length != sizeof(WINDOWPLACEMENT)) {
  3803. if (TestWF(pwnd, WFWIN40COMPAT)) {
  3804. RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "GetWindowPlacement: invalid length %lX", pwp->length);
  3805. MSGERROR(0);
  3806. } else {
  3807. RIPMSG1(RIP_WARNING, "GetWindowPlacement: invalid length %lX", pwp->length);
  3808. pwp->length = sizeof(WINDOWPLACEMENT);
  3809. }
  3810. }
  3811. #endif
  3812. } except (StubExceptionHandler(TRUE)) {
  3813. MSGERROR(0);
  3814. }
  3815. retval = _GetWindowPlacement(pwnd, &wp);
  3816. try {
  3817. RtlCopyMemory(pwp, &wp, sizeof(WINDOWPLACEMENT));
  3818. } except (StubExceptionHandler(TRUE)) {
  3819. MSGERROR(0);
  3820. }
  3821. TRACE("NtUserGetWindowPlacement");
  3822. ENDRECV_HWND();
  3823. }
  3824. BOOL NtUserSetWindowPlacement( // API SetWindowPlacement
  3825. IN HWND hwnd,
  3826. IN CONST WINDOWPLACEMENT *pwp)
  3827. {
  3828. WINDOWPLACEMENT wp;
  3829. BEGINRECV_HWNDLOCK_ND(BOOL, FALSE, hwnd);
  3830. /*
  3831. * Probe arguments
  3832. */
  3833. try {
  3834. wp = ProbeAndReadWindowPlacement(pwp);
  3835. } except (StubExceptionHandler(TRUE)) {
  3836. MSGERROR(0);
  3837. }
  3838. if (wp.length != sizeof(WINDOWPLACEMENT)) {
  3839. if (Is400Compat(ptiCurrent->dwExpWinVer)) {
  3840. RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "SetWindowPlacement: invalid length %lX", pwp->length);
  3841. MSGERROR(0);
  3842. } else {
  3843. RIPMSG1(RIP_WARNING, "SetWindowPlacement: invalid length %lX", pwp->length);
  3844. }
  3845. }
  3846. retval = xxxSetWindowPlacement(pwndND, &wp);
  3847. TRACE("NtUserSetWindowPlacement");
  3848. ENDRECV_HWNDLOCK_ND();
  3849. }
  3850. BOOL NtUserLockWindowUpdate( // API LockWindowUpdate
  3851. IN HWND hwnd)
  3852. {
  3853. PWND pwnd;
  3854. BEGINATOMICRECV(BOOL, FALSE);
  3855. ValidateHWNDOPT(pwnd, hwnd);
  3856. retval = LockWindowUpdate2(pwnd, FALSE);
  3857. TRACE("NtUserLockWindowUpdate");
  3858. ENDATOMICRECV();
  3859. }
  3860. BOOL NtUserGetClipCursor( // API GetClipCursor
  3861. OUT LPRECT lpRect)
  3862. {
  3863. /*
  3864. * Check if the caller has the proper access rights: if not, this will
  3865. * SetLastError to ERROR_ACCESS_DENIED and return FALSE. Do this *before*
  3866. * BEGINRECV_SHARED, else we must use MSGERROR to release the critsect!
  3867. */
  3868. RETURN_IF_ACCESS_DENIED(PpiCurrent()->amwinsta,
  3869. WINSTA_READATTRIBUTES,
  3870. FALSE);
  3871. {
  3872. BEGINRECV_SHARED(BOOL, FALSE);
  3873. /*
  3874. * Probe arguments
  3875. */
  3876. try {
  3877. ProbeForWriteRect(lpRect);
  3878. *lpRect = grcCursorClip;
  3879. retval = TRUE;
  3880. } except (StubExceptionHandler(TRUE)) {
  3881. MSGERROR(0);
  3882. }
  3883. TRACE("NtUserGetClipCursor");
  3884. ENDRECV_SHARED();
  3885. }
  3886. }
  3887. BOOL NtUserEnableScrollBar(
  3888. IN HWND hwnd,
  3889. IN UINT wSBflags,
  3890. IN UINT wArrows)
  3891. {
  3892. BEGINRECV_HWNDLOCK_ND(BOOL, FALSE, hwnd);
  3893. LIMITVALUE(wSBflags, SB_MAX, "EnableScrollBar");
  3894. retval = xxxEnableScrollBar(
  3895. pwndND,
  3896. wSBflags,
  3897. wArrows);
  3898. TRACE("NtUserEnableScrollBar");
  3899. ENDRECV_HWNDLOCK_ND();
  3900. }
  3901. BOOL NtUserDdeSetQualityOfService( // API DdeSetQualityOfService
  3902. IN HWND hwndClient,
  3903. IN CONST SECURITY_QUALITY_OF_SERVICE *pqosNew,
  3904. OUT PSECURITY_QUALITY_OF_SERVICE pqosPrev OPTIONAL)
  3905. {
  3906. SECURITY_QUALITY_OF_SERVICE qosNew, qosPrev;
  3907. BEGINRECV_HWND(BOOL, FALSE, hwndClient);
  3908. if (GETPTI(pwnd) != PtiCurrent()) {
  3909. MSGERROR(0);
  3910. }
  3911. /*
  3912. * Probe arguments
  3913. */
  3914. try {
  3915. qosNew = ProbeAndReadStructure(pqosNew, SECURITY_QUALITY_OF_SERVICE);
  3916. if (ARGUMENT_PRESENT(pqosPrev))
  3917. ProbeForWrite(pqosPrev, sizeof(*pqosPrev), sizeof(DWORD));
  3918. } except (StubExceptionHandler(TRUE)) {
  3919. MSGERROR(0);
  3920. }
  3921. retval = _DdeSetQualityOfService(
  3922. pwnd,
  3923. &qosNew,
  3924. &qosPrev);
  3925. try {
  3926. if (ARGUMENT_PRESENT(pqosPrev))
  3927. *pqosPrev = qosPrev;
  3928. } except (StubExceptionHandler(TRUE)) {
  3929. MSGERROR(0);
  3930. }
  3931. TRACE("NtUserDdeSetQualityOfService");
  3932. ENDRECV_HWND();
  3933. }
  3934. BOOL NtUserDdeGetQualityOfService( // private DdeGetQualityOfService
  3935. IN HWND hwndClient,
  3936. IN HWND hwndServer,
  3937. OUT PSECURITY_QUALITY_OF_SERVICE pqos)
  3938. {
  3939. PWND pwndServer;
  3940. PTHREADINFO ptiCurrent;
  3941. SECURITY_QUALITY_OF_SERVICE qos;
  3942. BEGINATOMICRECV_HWND(BOOL, FALSE, hwndClient);
  3943. ValidateHWNDOPT(pwndServer, hwndServer);
  3944. ptiCurrent = PtiCurrent();
  3945. if (GETPTI(pwnd) != ptiCurrent && pwndServer != NULL &&
  3946. GETPTI(pwndServer) != ptiCurrent) {
  3947. MSGERROR(0);
  3948. }
  3949. /*
  3950. * Probe arguments
  3951. */
  3952. try {
  3953. ProbeForWrite(pqos, sizeof(*pqos), DATAALIGN);
  3954. } except (StubExceptionHandler(FALSE)) {
  3955. MSGERROR(0);
  3956. }
  3957. retval = _DdeGetQualityOfService(
  3958. pwnd,
  3959. pwndServer,
  3960. &qos);
  3961. try {
  3962. RtlCopyMemory(pqos, &qos, sizeof (SECURITY_QUALITY_OF_SERVICE));
  3963. } except (StubExceptionHandler(FALSE)) {
  3964. MSGERROR(0);
  3965. }
  3966. TRACE("NtUserDdeGetQualityOfService");
  3967. ENDATOMICRECV_HWND();
  3968. }
  3969. DWORD NtUserGetMenuIndex(
  3970. IN HMENU hMenu,
  3971. IN HMENU hSubMenu)
  3972. {
  3973. PMENU pmenu;
  3974. PMENU psubmenu;
  3975. DWORD idx;
  3976. BEGINRECV_SHARED(DWORD, 0);
  3977. ValidateHMENU(pmenu, hMenu);
  3978. ValidateHMENU(psubmenu, hSubMenu);
  3979. retval = (DWORD)-1;
  3980. if (pmenu && psubmenu) {
  3981. for (idx=0; idx<pmenu->cItems; idx++)
  3982. if ((pmenu->rgItems[idx].spSubMenu == psubmenu)) {
  3983. retval = idx;
  3984. break;
  3985. }
  3986. }
  3987. TRACE("NtUserGetMenuIndex");
  3988. ENDRECV_SHARED();
  3989. }
  3990. #if DBG
  3991. VOID NtUserSetRipFlags(
  3992. DWORD dwRipFlags)
  3993. {
  3994. BEGINRECV_VOID();
  3995. SetRipFlags(dwRipFlags);
  3996. TRACEVOID("NtUserSetRipFlags");
  3997. ENDRECV_VOID();
  3998. }
  3999. VOID NtUserSetDbgTag(
  4000. int tag,
  4001. DWORD dwBitFlags)
  4002. {
  4003. BEGINRECV_VOID();
  4004. SetDbgTag(tag, dwBitFlags);
  4005. TRACEVOID("NtUserSetDbgTag");
  4006. ENDRECV_VOID();
  4007. }
  4008. VOID NtUserSetDbgTagCount(
  4009. DWORD dwTagCount)
  4010. {
  4011. BEGINRECV_VOID();
  4012. SetDbgTagCount(dwTagCount);
  4013. TRACEVOID("NtUserSetDbgTagCount");
  4014. ENDRECV_VOID();
  4015. }
  4016. #endif
  4017. ULONG_PTR NtUserCallNoParam(
  4018. IN DWORD xpfnProc)
  4019. {
  4020. BEGINRECV(ULONG_PTR, 0);
  4021. /*
  4022. * C4296: (...) : expression is always true/false
  4023. * The first comparison in ISXPFNPROCINRANGE is always true for
  4024. * SFI_BEGINTRANSLATENOPARAMXXX, so we explicitly disable the warning.
  4025. */
  4026. #pragma warning(disable:4296)
  4027. VALIDATEXPFNPROC(NOPARAM);
  4028. retval = (apfnSimpleCall[xpfnProc]());
  4029. if (ISXPFNPROCINRANGE(NOPARAMANDRETURNHANDLE)) {
  4030. retval = (ULONG_PTR)PtoH((PVOID)retval);
  4031. }
  4032. #pragma warning(default:4296)
  4033. TRACE(apszSimpleCallNames[xpfnProc]);
  4034. ENDRECV();
  4035. }
  4036. ULONG_PTR NtUserCallOneParam(
  4037. IN ULONG_PTR dwParam,
  4038. IN DWORD xpfnProc)
  4039. {
  4040. BEGINRECV(ULONG_PTR, 0);
  4041. VALIDATEXPFNPROC(ONEPARAM);
  4042. retval = (apfnSimpleCall[xpfnProc](dwParam));
  4043. if (ISXPFNPROCINRANGE(ONEPARAMANDRETURNHANDLE)) {
  4044. retval = (ULONG_PTR)PtoH((PVOID)retval);
  4045. }
  4046. TRACE(apszSimpleCallNames[xpfnProc]);
  4047. ENDRECV();
  4048. }
  4049. ULONG_PTR NtUserCallHwnd(
  4050. IN HWND hwnd,
  4051. IN DWORD xpfnProc)
  4052. {
  4053. BEGINRECV_HWNDLOCK(ULONG_PTR, 0, hwnd);
  4054. VALIDATEXPFNPROC(HWND);
  4055. retval = (apfnSimpleCall[xpfnProc](pwnd));
  4056. TRACE(apszSimpleCallNames[xpfnProc]);
  4057. ENDRECV_HWNDLOCK();
  4058. }
  4059. ULONG_PTR NtUserCallHwndLock(
  4060. IN HWND hwnd,
  4061. IN DWORD xpfnProc)
  4062. {
  4063. BEGINRECV_HWNDLOCK_COND_ND(ULONG_PTR, 0, hwnd, xpfnProc);
  4064. VALIDATEXPFNPROC(HWNDLOCK);
  4065. retval = apfnSimpleCall[xpfnProc](pwndCondND);
  4066. TRACE(apszSimpleCallNames[xpfnProc]);
  4067. ENDRECV_HWNDLOCK_COND_ND();
  4068. }
  4069. ULONG_PTR NtUserCallHwndOpt(
  4070. IN HWND hwnd,
  4071. IN DWORD xpfnProc)
  4072. {
  4073. PWND pwnd;
  4074. BEGINATOMICRECV(ULONG_PTR, 0);
  4075. ValidateHWNDOPT(pwnd, hwnd);
  4076. VALIDATEXPFNPROC(HWNDOPT);
  4077. retval = (apfnSimpleCall[xpfnProc](pwnd));
  4078. TRACE(apszSimpleCallNames[xpfnProc]);
  4079. ENDATOMICRECV();
  4080. }
  4081. ULONG_PTR NtUserCallHwndParam(
  4082. IN HWND hwnd,
  4083. IN ULONG_PTR dwParam,
  4084. IN DWORD xpfnProc)
  4085. {
  4086. BEGINRECV_HWNDLOCK(ULONG_PTR, 0, hwnd);
  4087. VALIDATEXPFNPROC(HWNDPARAM);
  4088. retval = (apfnSimpleCall[xpfnProc](pwnd, dwParam));
  4089. if (ISXPFNPROCINRANGE(HWNDPARAMANDRETURNHANDLE)) {
  4090. retval = (ULONG_PTR)PtoH((PVOID)retval);
  4091. }
  4092. TRACE(apszSimpleCallNames[xpfnProc]);
  4093. ENDRECV_HWNDLOCK();
  4094. }
  4095. ULONG_PTR NtUserCallHwndParamLock(
  4096. IN HWND hwnd,
  4097. IN ULONG_PTR dwParam,
  4098. IN DWORD xpfnProc)
  4099. {
  4100. BEGINRECV_HWNDLOCK_COND_ND(ULONG_PTR, 0, hwnd, xpfnProc);
  4101. VALIDATEXPFNPROC(HWNDPARAMLOCK);
  4102. retval = apfnSimpleCall[xpfnProc](pwndCondND, dwParam);
  4103. TRACE(apszSimpleCallNames[xpfnProc]);
  4104. ENDRECV_HWNDLOCK_COND_ND();
  4105. }
  4106. ULONG_PTR NtUserCallTwoParam(
  4107. ULONG_PTR dwParam1,
  4108. ULONG_PTR dwParam2,
  4109. IN DWORD xpfnProc)
  4110. {
  4111. BEGINRECV(ULONG_PTR, 0);
  4112. VALIDATEXPFNPROC(TWOPARAM);
  4113. retval = (apfnSimpleCall[xpfnProc](dwParam1, dwParam2));
  4114. TRACE(apszSimpleCallNames[xpfnProc]);
  4115. ENDRECV();
  4116. }
  4117. BOOL NtUserThunkedMenuItemInfo( // worker for various menu APIs
  4118. IN HMENU hMenu,
  4119. IN UINT nPosition,
  4120. IN BOOL fByPosition,
  4121. IN BOOL fInsert,
  4122. IN LPMENUITEMINFOW lpmii,
  4123. IN PUNICODE_STRING pstrItem OPTIONAL)
  4124. {
  4125. PMENU pmenu;
  4126. MENUITEMINFO mii;
  4127. UNICODE_STRING strItem;
  4128. TL tlpMenu;
  4129. BEGINRECV(BOOL, FALSE);
  4130. /*
  4131. * Probe arguments
  4132. * No need to SetLastError because lpmii is always the address of
  4133. * a local stack structure in USER code, not an application address.
  4134. */
  4135. try {
  4136. mii = ProbeAndReadMenuItem(lpmii);
  4137. if (ARGUMENT_PRESENT(pstrItem)) {
  4138. strItem = ProbeAndReadUnicodeString(pstrItem);
  4139. ProbeForReadUnicodeStringBuffer(strItem);
  4140. } else {
  4141. RtlInitUnicodeString(&strItem, NULL);
  4142. }
  4143. } except (StubExceptionHandler(FALSE)) {
  4144. MSGERROR(0);
  4145. }
  4146. if (fInsert) {
  4147. ValidateHMENUMODIFYCHECKLOCK(pmenu, hMenu);
  4148. } else {
  4149. ValidateHMENUMODIFY(pmenu, hMenu);
  4150. }
  4151. ThreadLock(pmenu, &tlpMenu);
  4152. /*
  4153. * These routines only use the buffer in a try/except (actually in
  4154. * xxxSetLPITEMInfo).
  4155. */
  4156. if (fInsert) {
  4157. retval = xxxInsertMenuItem(
  4158. pmenu,
  4159. nPosition,
  4160. fByPosition,
  4161. &mii,
  4162. &strItem);
  4163. } else {
  4164. retval = xxxSetMenuItemInfo(
  4165. pmenu,
  4166. nPosition,
  4167. fByPosition,
  4168. &mii,
  4169. &strItem);
  4170. }
  4171. ThreadUnlock(&tlpMenu);
  4172. TRACE("NtUserThunkedMenuItemInfo");
  4173. ENDRECV();
  4174. }
  4175. /***************************************************************************\
  4176. * NtUserThunkedMenuInfo
  4177. *
  4178. * History:
  4179. * 07-23-96 GerardoB - Added header & fixed up for 5.0
  4180. \***************************************************************************/
  4181. BOOL NtUserThunkedMenuInfo( // API SetMenuInfo
  4182. IN HMENU hMenu,
  4183. IN LPCMENUINFO lpmi)
  4184. {
  4185. PMENU pmenu;
  4186. MENUINFO mi;
  4187. TL tlpMenu;
  4188. BEGINRECV(BOOL, FALSE);
  4189. /*
  4190. * Probe arguments
  4191. */
  4192. try {
  4193. mi = ProbeAndReadMenuInfo(lpmi);
  4194. } except (StubExceptionHandler(TRUE)) {
  4195. MSGERROR(0);
  4196. }
  4197. ValidateHMENUMODIFY(pmenu, hMenu);
  4198. ThreadLock(pmenu, &tlpMenu);
  4199. retval = xxxSetMenuInfo(pmenu, &mi);
  4200. ThreadUnlock(&tlpMenu);
  4201. TRACE("NtUserThunkedMenuInfo");
  4202. ENDRECV();
  4203. }
  4204. BOOL NtUserSetMenuDefaultItem(
  4205. IN HMENU hMenu,
  4206. IN UINT wID,
  4207. IN UINT fByPosition)
  4208. {
  4209. PMENU pmenu;
  4210. BEGINATOMICRECV(BOOL, FALSE);
  4211. ValidateHMENUMODIFY(pmenu, hMenu);
  4212. retval = _SetMenuDefaultItem(
  4213. pmenu,
  4214. wID,
  4215. fByPosition);
  4216. TRACE("NtUserSetMenuDefaultItem");
  4217. ENDATOMICRECV();
  4218. }
  4219. BOOL NtUserSetMenuContextHelpId(
  4220. IN HMENU hMenu,
  4221. IN DWORD dwContextHelpId)
  4222. {
  4223. PMENU pmenu;
  4224. BEGINATOMICRECV(BOOL, FALSE);
  4225. ValidateHMENUMODIFY(pmenu, hMenu);
  4226. retval = _SetMenuContextHelpId(
  4227. pmenu,
  4228. dwContextHelpId);
  4229. TRACE("NtUserSetMenuContextHelpId");
  4230. ENDATOMICRECV();
  4231. }
  4232. BOOL NtUserSetMenuFlagRtoL(
  4233. IN HMENU hMenu)
  4234. {
  4235. PMENU pmenu;
  4236. BEGINATOMICRECV(BOOL, FALSE);
  4237. ValidateHMENU(pmenu, hMenu);
  4238. retval = _SetMenuFlagRtoL(pmenu);
  4239. TRACE("NtUserSetMenuFlagRtoL");
  4240. ENDATOMICRECV();
  4241. }
  4242. BOOL NtUserDrawAnimatedRects( // API DrawAnimatedRects
  4243. IN HWND hwnd,
  4244. IN int idAni,
  4245. IN CONST RECT *lprcFrom,
  4246. IN CONST RECT *lprcTo)
  4247. {
  4248. PWND pwnd;
  4249. TL tlpwnd;
  4250. RECT rcFrom;
  4251. RECT rcTo;
  4252. BEGINRECV(BOOL, FALSE);
  4253. ValidateHWNDOPT(pwnd, hwnd);
  4254. /*
  4255. * Probe arguments
  4256. */
  4257. try {
  4258. rcFrom = ProbeAndReadRect(lprcFrom);
  4259. rcTo = ProbeAndReadRect(lprcTo);
  4260. } except (StubExceptionHandler(TRUE)) {
  4261. MSGERROR(0);
  4262. }
  4263. ThreadLock(pwnd, &tlpwnd);
  4264. retval = xxxDrawAnimatedRects(
  4265. pwnd,
  4266. idAni,
  4267. &rcFrom,
  4268. &rcTo);
  4269. ThreadUnlock(&tlpwnd);
  4270. TRACE("NtUserDrawAnimatedRects");
  4271. ENDRECV();
  4272. }
  4273. BOOL NtUserDrawCaption( // API DrawCaption
  4274. IN HWND hwnd,
  4275. IN HDC hdc,
  4276. IN CONST RECT *lprc,
  4277. IN UINT flags)
  4278. {
  4279. RECT rc;
  4280. BEGINRECV_HWNDLOCK(DWORD, FALSE, hwnd);
  4281. /*
  4282. * Probe arguments
  4283. */
  4284. try {
  4285. rc = ProbeAndReadRect(lprc);
  4286. } except (StubExceptionHandler(TRUE)) {
  4287. MSGERROR(0);
  4288. }
  4289. retval = xxxDrawCaptionTemp(pwnd, hdc, &rc, NULL, NULL, NULL, flags);
  4290. TRACE("NtUserDrawCaption");
  4291. ENDRECV_HWNDLOCK();
  4292. }
  4293. BOOL NtUserPaintDesktop(
  4294. IN HDC hdc)
  4295. {
  4296. PTHREADINFO ptiCurrent;
  4297. PWND pwndDesk;
  4298. TL tlpwndDesk;
  4299. BEGINRECV(BOOL, FALSE);
  4300. ptiCurrent = PtiCurrent();
  4301. if (ptiCurrent->rpdesk != NULL) {
  4302. pwndDesk = ptiCurrent->rpdesk->pDeskInfo->spwnd;
  4303. ThreadLockWithPti(ptiCurrent, pwndDesk, &tlpwndDesk);
  4304. retval = xxxInternalPaintDesktop(pwndDesk, hdc, TRUE);
  4305. ThreadUnlock(&tlpwndDesk);
  4306. } else {
  4307. MSGERROR(0);
  4308. }
  4309. TRACE("NtUserPaintDesktop");
  4310. ENDRECV();
  4311. }
  4312. SHORT NtUserGetAsyncKeyState(
  4313. IN int vKey)
  4314. {
  4315. PTHREADINFO ptiCurrent;
  4316. BEGINRECV_SHARED(SHORT, 0);
  4317. ptiCurrent = PtiCurrentShared();
  4318. UserAssert(ptiCurrent);
  4319. /*
  4320. * Don't allow other processes to spy on other deskops or a process
  4321. * to spy on the foreground if the desktop does not allow input spying
  4322. */
  4323. if ((ptiCurrent->rpdesk != grpdeskRitInput) ||
  4324. ( ((gptiForeground == NULL) || (PpiCurrent() != gptiForeground->ppi)) &&
  4325. !RtlAreAnyAccessesGranted(ptiCurrent->amdesk, (DESKTOP_HOOKCONTROL | DESKTOP_JOURNALRECORD)))) {
  4326. RIPERR0(ERROR_ACCESS_DENIED, RIP_VERBOSE, "GetAysncKeyState: not"
  4327. " foreground desktop or no desktop hooking (input spying)");
  4328. MSGERROR(0);
  4329. }
  4330. UserAssert(!(ptiCurrent->rpdesk->rpwinstaParent->dwWSF_Flags & WSF_NOIO));
  4331. retval = _GetAsyncKeyState(vKey);
  4332. /*
  4333. * Update the client side key state cache.
  4334. */
  4335. try {
  4336. ptiCurrent->pClientInfo->dwAsyncKeyCache = gpsi->dwAsyncKeyCache;
  4337. RtlCopyMemory(ptiCurrent->pClientInfo->afAsyncKeyState,
  4338. gafAsyncKeyState,
  4339. CBASYNCKEYCACHE);
  4340. RtlCopyMemory(ptiCurrent->pClientInfo->afAsyncKeyStateRecentDown,
  4341. gafAsyncKeyStateRecentDown,
  4342. CBASYNCKEYCACHE);
  4343. } except (StubExceptionHandler(TRUE)) {
  4344. retval = 0;
  4345. }
  4346. TRACE("NtUserGetAsyncKeyState");
  4347. ENDRECV_SHARED();
  4348. }
  4349. HBRUSH NtUserGetControlBrush(
  4350. IN HWND hwnd,
  4351. IN HDC hdc,
  4352. IN UINT msg)
  4353. {
  4354. BEGINRECV_HWNDLOCK(HBRUSH, NULL, hwnd);
  4355. if (hdc == NULL || !InMsgRange(msg, WM_CTLCOLORFIRST, WM_CTLCOLORLAST)) {
  4356. MSGERROR(0);
  4357. }
  4358. retval = xxxGetControlBrush(
  4359. pwnd,
  4360. hdc,
  4361. msg);
  4362. TRACE("NtUserGetControlBrush");
  4363. ENDRECV_HWNDLOCK();
  4364. }
  4365. HBRUSH NtUserGetControlColor(
  4366. IN HWND hwndParent,
  4367. IN HWND hwndCtl,
  4368. IN HDC hdc,
  4369. IN UINT msg)
  4370. {
  4371. PWND pwndCtl;
  4372. TL tlpwndCtl;
  4373. BEGINRECV_HWNDLOCK(HBRUSH, NULL, hwndParent);
  4374. ValidateHWND(pwndCtl, hwndCtl);
  4375. if (hdc == NULL || !InMsgRange(msg, WM_CTLCOLORFIRST, WM_CTLCOLORLAST)) {
  4376. MSGERROR(0);
  4377. }
  4378. ThreadLockAlwaysWithPti(ptiCurrent, pwndCtl, &tlpwndCtl);
  4379. retval = xxxGetControlColor(
  4380. pwnd,
  4381. pwndCtl,
  4382. hdc,
  4383. msg);
  4384. ThreadUnlock(&tlpwndCtl);
  4385. TRACE("NtUserGetControlColor");
  4386. ENDRECV_HWNDLOCK();
  4387. }
  4388. BOOL NtUserEndMenu(VOID)
  4389. {
  4390. PTHREADINFO ptiCurrent;
  4391. PWND pwnd;
  4392. BEGINRECV(BOOL, FALSE);
  4393. ptiCurrent = PtiCurrent();
  4394. /*
  4395. * The menu might be in the middle of some callback, so calling xxxEndMenu
  4396. * directly might mess things up. So we post it a message to signal it to
  4397. * go away at a good moment
  4398. */
  4399. if (ptiCurrent->pMenuState != NULL) {
  4400. pwnd = GetMenuStateWindow(ptiCurrent->pMenuState);
  4401. if (pwnd != NULL) {
  4402. _PostMessage(pwnd, MN_ENDMENU, 0, 0);
  4403. } else {
  4404. /*
  4405. * Is this menu messed up?
  4406. */
  4407. UserAssert(pwnd != NULL);
  4408. ptiCurrent->pMenuState->fInsideMenuLoop = FALSE;
  4409. }
  4410. }
  4411. retval = TRUE;
  4412. TRACEVOID("NtUserEndMenu");
  4413. ENDRECV();
  4414. }
  4415. int NtUserCountClipboardFormats(
  4416. VOID)
  4417. {
  4418. PWINDOWSTATION pwinsta;
  4419. BEGINRECV_SHARED(int, 0);
  4420. /*
  4421. * Blow it off if the caller doesn't have the proper access rights
  4422. */
  4423. if ((pwinsta = CheckClipboardAccess()) == NULL) {
  4424. MSGERROR(0);
  4425. }
  4426. retval = pwinsta->cNumClipFormats;
  4427. TRACE("NtUserCountClipboardFormats");
  4428. ENDRECV_SHARED();
  4429. }
  4430. DWORD NtUserGetClipboardSequenceNumber(
  4431. VOID)
  4432. {
  4433. PWINDOWSTATION pwinsta;
  4434. BEGINRECV_SHARED(DWORD, 0);
  4435. /*
  4436. * Blow it off if the caller doesn't have the proper access rights
  4437. */
  4438. if ((pwinsta = CheckClipboardAccess()) == NULL) {
  4439. MSGERROR(0);
  4440. }
  4441. retval = pwinsta->iClipSequenceNumber;
  4442. TRACE("NtUserGetClipboardSequenceNumber");
  4443. ENDRECV_SHARED();
  4444. }
  4445. UINT NtUserGetCaretBlinkTime(VOID)
  4446. {
  4447. BEGINRECV_SHARED(UINT, 0);
  4448. /*
  4449. * Blow it off if the caller doesn't have the proper access rights. However,
  4450. * allow CSRSS to use this value internally to the server. Note that if the
  4451. * client tries to retrieve this value itself, the access check will
  4452. * function normally.
  4453. */
  4454. if ((PpiCurrent()->Process != gpepCSRSS) &&
  4455. (!CheckGrantedAccess(PpiCurrent()->amwinsta, WINSTA_READATTRIBUTES))) {
  4456. MSGERROR(0);
  4457. }
  4458. retval = gpsi->dtCaretBlink;
  4459. TRACE("NtUserGetCaretBlinkTime");
  4460. ENDRECV_SHARED();
  4461. }
  4462. HWND NtUserGetClipboardOwner(
  4463. VOID)
  4464. {
  4465. PWINDOWSTATION pwinsta;
  4466. BEGINRECV_SHARED(HWND, NULL);
  4467. /*
  4468. * Blow it off if the caller doesn't have the proper access rights
  4469. */
  4470. if ((pwinsta = CheckClipboardAccess()) == NULL) {
  4471. MSGERROR(0);
  4472. }
  4473. retval = PtoH(pwinsta->spwndClipOwner);
  4474. TRACE("NtUserGetClipboardOwner");
  4475. ENDRECV_SHARED();
  4476. }
  4477. HWND NtUserGetClipboardViewer(
  4478. VOID)
  4479. {
  4480. PWINDOWSTATION pwinsta;
  4481. BEGINRECV_SHARED(HWND, NULL);
  4482. /*
  4483. * Blow it off if the caller doesn't have the proper access rights
  4484. */
  4485. if ((pwinsta = CheckClipboardAccess()) == NULL) {
  4486. MSGERROR(0);
  4487. }
  4488. retval = PtoH(pwinsta->spwndClipViewer);
  4489. TRACE("NtUserGetClipboardViewer");
  4490. ENDRECV_SHARED();
  4491. }
  4492. UINT NtUserGetDoubleClickTime(
  4493. VOID)
  4494. {
  4495. BEGINRECV_SHARED(UINT, 0);
  4496. /*
  4497. * Blow it off if the caller doesn't have the proper access rights. However,
  4498. * allow CSRSS to use this value internally to the server. Note that if the
  4499. * client tries to retrieve this value itself, the access check will
  4500. * function normally.
  4501. */
  4502. if ((PpiCurrent()->Process != gpepCSRSS) &&
  4503. (!CheckGrantedAccess(PpiCurrent()->amwinsta, WINSTA_READATTRIBUTES))) {
  4504. MSGERROR(0);
  4505. }
  4506. retval = gdtDblClk;
  4507. TRACE("NtUserGetDoubleClickTime");
  4508. ENDRECV_SHARED();
  4509. }
  4510. HWND NtUserGetForegroundWindow(
  4511. VOID)
  4512. {
  4513. BEGINRECV_SHARED(HWND, NULL);
  4514. /*
  4515. * Only return a window if there is a foreground queue and the
  4516. * caller has access to the current desktop.
  4517. */
  4518. if (gpqForeground == NULL || gpqForeground->spwndActive == NULL ||
  4519. PtiCurrentShared()->rpdesk != gpqForeground->spwndActive->head.rpdesk) {
  4520. MSGERROR(0);
  4521. }
  4522. retval = PtoHq(gpqForeground->spwndActive);
  4523. TRACE("NtUserGetForegroundWindow");
  4524. ENDRECV_SHARED();
  4525. }
  4526. HWND NtUserGetOpenClipboardWindow(
  4527. VOID)
  4528. {
  4529. PWINDOWSTATION pwinsta;
  4530. BEGINRECV_SHARED(HWND, NULL);
  4531. /*
  4532. * Blow it off if the caller doesn't have the proper access rights
  4533. */
  4534. if ((pwinsta = CheckClipboardAccess()) == NULL) {
  4535. MSGERROR(0);
  4536. }
  4537. retval = PtoH(pwinsta->spwndClipOpen);
  4538. TRACE("NtUserGetOpenClipboardWindow");
  4539. ENDRECV_SHARED();
  4540. }
  4541. int NtUserGetPriorityClipboardFormat( // API GetPriorityClipboardFormat
  4542. IN UINT *paFormatPriorityList,
  4543. IN int cFormats)
  4544. {
  4545. BEGINRECV_SHARED(int, 0);
  4546. /*
  4547. * Probe arguments
  4548. */
  4549. try {
  4550. ProbeForReadBuffer(paFormatPriorityList, cFormats, DATAALIGN);
  4551. retval = _GetPriorityClipboardFormat(
  4552. paFormatPriorityList,
  4553. cFormats);
  4554. } except (StubExceptionHandler(TRUE)) {
  4555. MSGERROR(0);
  4556. }
  4557. TRACE("NtUserGetPriorityClipboardFormat");
  4558. ENDRECV_SHARED();
  4559. }
  4560. HMENU NtUserGetSystemMenu(
  4561. IN HWND hwnd,
  4562. IN BOOL bRevert)
  4563. {
  4564. BEGINRECV_HWNDLOCK(HMENU, NULL, hwnd);
  4565. retval = (HMENU)xxxGetSystemMenu(pwnd, bRevert);
  4566. retval = PtoH((PVOID)retval);
  4567. TRACE("NtUserGetSystemMenu");
  4568. ENDRECV_HWNDLOCK();
  4569. }
  4570. BOOL NtUserGetUpdateRect( // API GetUpdateRect
  4571. IN HWND hwnd,
  4572. IN LPRECT prect OPTIONAL,
  4573. IN BOOL bErase)
  4574. {
  4575. RECT rect2;
  4576. BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
  4577. retval = xxxGetUpdateRect(
  4578. pwnd,
  4579. prect? &rect2:NULL,
  4580. bErase);
  4581. /*
  4582. * Probe arguments
  4583. */
  4584. if (ARGUMENT_PRESENT(prect)) {
  4585. try {
  4586. ProbeAndWriteStructure(prect, rect2, RECT);
  4587. } except (StubExceptionHandler(TRUE)) {
  4588. MSGERROR(0);
  4589. }
  4590. }
  4591. TRACE("NtUserGetUpdateRect");
  4592. ENDRECV_HWNDLOCK();
  4593. }
  4594. BOOL NtUserHideCaret(
  4595. IN HWND hwnd)
  4596. {
  4597. PWND pwnd;
  4598. BEGINRECV(BOOL, FALSE);
  4599. ValidateHWNDOPT(pwnd, hwnd);
  4600. retval = zzzHideCaret(pwnd);
  4601. TRACE("NtUserHideCaret");
  4602. ENDRECV();
  4603. }
  4604. BOOL NtUserHiliteMenuItem(
  4605. IN HWND hwnd,
  4606. IN HMENU hMenu,
  4607. IN UINT uIDHiliteItem,
  4608. IN UINT uHilite)
  4609. {
  4610. PMENU pmenu;
  4611. TL tlpMenu;
  4612. BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
  4613. TESTFLAGS(uHilite, MF_VALID);
  4614. ValidateHMENUMODIFY(pmenu, hMenu);
  4615. ThreadLockAlwaysWithPti(ptiCurrent, pmenu, &tlpMenu);
  4616. retval = xxxHiliteMenuItem(
  4617. pwnd,
  4618. pmenu,
  4619. uIDHiliteItem,
  4620. uHilite);
  4621. ThreadUnlock(&tlpMenu);
  4622. TRACE("NtUserHiliteMenuItem");
  4623. ENDRECV_HWNDLOCK();
  4624. }
  4625. BOOL NtUserInvalidateRect( // API InvalidateRect
  4626. IN HWND hwnd,
  4627. IN CONST RECT *prect OPTIONAL,
  4628. IN BOOL bErase)
  4629. {
  4630. PWND pwnd;
  4631. TL tlpwnd;
  4632. RECT rc;
  4633. BEGINRECV(BOOL, FALSE);
  4634. ValidateHWNDOPT(pwnd, hwnd);
  4635. /*
  4636. * Probe arguments
  4637. */
  4638. if (ARGUMENT_PRESENT(prect)) {
  4639. try {
  4640. rc = ProbeAndReadRect(prect);
  4641. prect = &rc;
  4642. } except (StubExceptionHandler(TRUE)) {
  4643. MSGERROR(0);
  4644. }
  4645. }
  4646. ThreadLock(pwnd, &tlpwnd);
  4647. retval = xxxInvalidateRect(
  4648. pwnd,
  4649. (PRECT)prect,
  4650. bErase);
  4651. ThreadUnlock(&tlpwnd);
  4652. TRACE("NtUserInvalidateRect");
  4653. ENDRECV();
  4654. }
  4655. BOOL NtUserIsClipboardFormatAvailable(
  4656. IN UINT nFormat)
  4657. {
  4658. PWINDOWSTATION pwinsta;
  4659. BEGINRECV_SHARED(BOOL, FALSE);
  4660. /*
  4661. * Blow it off if the caller doesn't have the proper access rights
  4662. */
  4663. if ((pwinsta = CheckClipboardAccess()) == NULL) {
  4664. MSGERROR(0);
  4665. }
  4666. retval = (FindClipFormat(pwinsta, nFormat) != NULL);
  4667. TRACE("NtUserIsClipboardFormatAvailable");
  4668. ENDRECV_SHARED();
  4669. }
  4670. BOOL NtUserKillTimer(
  4671. IN HWND hwnd,
  4672. IN UINT_PTR nIDEvent)
  4673. {
  4674. PWND pwnd;
  4675. BEGINATOMICRECV(BOOL, FALSE);
  4676. ValidateHWNDOPT(pwnd, hwnd);
  4677. retval = _KillTimer(
  4678. pwnd,
  4679. nIDEvent);
  4680. TRACE("NtUserKillTimer");
  4681. ENDATOMICRECV();
  4682. }
  4683. HWND NtUserMinMaximize(
  4684. IN HWND hwnd,
  4685. IN UINT nCmdShow,
  4686. IN BOOL fKeepHidden)
  4687. {
  4688. BEGINRECV_HWNDLOCK_ND(HWND, NULL, hwnd);
  4689. retval = (HWND)xxxMinMaximize(
  4690. pwndND,
  4691. nCmdShow,
  4692. ((fKeepHidden) ? MINMAX_KEEPHIDDEN : 0) | TEST_PUDF(PUDF_ANIMATE));
  4693. retval = PtoH((PVOID)retval);
  4694. TRACE("NtUserMinMaximize");
  4695. ENDRECV_HWNDLOCK_ND();
  4696. }
  4697. /**************************************************************************\
  4698. * NtUserMNDragOver
  4699. *
  4700. * Called from the IDropTarget interface to let menus update the selection
  4701. * given the mouse position. It also returns the handle of the menu the
  4702. * the index of the item the point is on.
  4703. *
  4704. * 10/28/96 GerardoB Created
  4705. \**************************************************************************/
  4706. BOOL NtUserMNDragOver( // worker for menu drag & drop
  4707. IN POINT * ppt,
  4708. OUT PMNDRAGOVERINFO pmndoi)
  4709. {
  4710. POINT pt;
  4711. MNDRAGOVERINFO mndoi;
  4712. BEGINRECV(BOOL, FALSE);
  4713. /*
  4714. * No need to SetLastError since ppt and pmndoi are always addresses of
  4715. * local stack variables in USER, not addresses from an application
  4716. */
  4717. try {
  4718. pt = ProbeAndReadPoint(ppt);
  4719. } except (StubExceptionHandler(FALSE)) {
  4720. RIPMSG1(RIP_WARNING, "NtUserMNDragOver: Exception:%#lx", GetExceptionCode());
  4721. MSGERROR(0);
  4722. }
  4723. retval = xxxMNDragOver(&pt, &mndoi);
  4724. if (retval) {
  4725. try {
  4726. ProbeAndWriteStructure(pmndoi, mndoi, MNDRAGOVERINFO);
  4727. } except (StubExceptionHandler(FALSE)) {
  4728. RIPMSG1(RIP_WARNING, "NtUserMNDragOver: Exception:%#lx", GetExceptionCode());
  4729. MSGERROR(0);
  4730. }
  4731. }
  4732. TRACE("NtUserMNDragOver");
  4733. ENDRECV();
  4734. }
  4735. /**************************************************************************\
  4736. * NtUserMNDragLeave
  4737. *
  4738. * Called from the IDropTarget interface to let the menu clean up
  4739. *
  4740. * 10/28/96 GerardoB Created
  4741. \**************************************************************************/
  4742. BOOL NtUserMNDragLeave(VOID)
  4743. {
  4744. BEGINRECV(BOOL, FALSE);
  4745. retval = xxxMNDragLeave();
  4746. TRACE("NtUserMNDragLeave");
  4747. ENDRECV();
  4748. }
  4749. BOOL NtUserOpenClipboard( // API OpenClipboard
  4750. IN HWND hwnd,
  4751. OUT PBOOL pfEmptyClient)
  4752. {
  4753. PWND pwnd;
  4754. TL tlpwnd;
  4755. BOOL fEmptyClient;
  4756. BEGINRECV(BOOL, FALSE);
  4757. ValidateHWNDOPT(pwnd, hwnd);
  4758. ThreadLock(pwnd, &tlpwnd);
  4759. retval = _OpenClipboard(pwnd, &fEmptyClient);
  4760. ThreadUnlock(&tlpwnd);
  4761. /*
  4762. * Probe arguments
  4763. * No need to SetLastError since pfEmptyClient is the address of a local
  4764. * variable in USER client code, not an application address.
  4765. */
  4766. try {
  4767. ProbeAndWriteUlong(pfEmptyClient, fEmptyClient);
  4768. } except (StubExceptionHandler(FALSE)) {
  4769. MSGERROR(0);
  4770. }
  4771. TRACE("NtUserOpenClipboard");
  4772. ENDRECV();
  4773. }
  4774. BOOL NtUserPeekMessage(
  4775. OUT LPMSG pmsg,
  4776. IN HWND hwnd,
  4777. IN UINT wMsgFilterMin,
  4778. IN UINT wMsgFilterMax,
  4779. IN UINT wRemoveMsg)
  4780. {
  4781. MSG msg;
  4782. BEGINRECV(BOOL, FALSE);
  4783. TESTFLAGS(wRemoveMsg, PM_VALID);
  4784. retval = xxxPeekMessage(
  4785. &msg,
  4786. hwnd,
  4787. wMsgFilterMin,
  4788. wMsgFilterMax,
  4789. wRemoveMsg);
  4790. /*
  4791. * Probe and write arguments only if PeekMessage suceeds otherwise
  4792. * we want to leave MSG undisturbed (bug 16224) to be compatible.
  4793. */
  4794. if (retval) {
  4795. try {
  4796. ProbeAndWriteStructure(pmsg, msg, MSG);
  4797. } except (StubExceptionHandler(TRUE)) {
  4798. MSGERROR(0);
  4799. }
  4800. }
  4801. TRACE("NtUserPeekMessage");
  4802. ENDRECV();
  4803. }
  4804. BOOL NtUserPostMessage(
  4805. IN HWND hwnd,
  4806. IN UINT msg,
  4807. IN WPARAM wParam,
  4808. IN LPARAM lParam)
  4809. {
  4810. PWND pwnd;
  4811. BEGINRECV(BOOL, FALSE);
  4812. /*
  4813. * Prevent apps from setting hi 16 bits so we can use them internally.
  4814. */
  4815. if (msg & MSGFLAG_MASK) {
  4816. RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid message");
  4817. MSGERROR(0);
  4818. }
  4819. switch ((ULONG_PTR)hwnd) {
  4820. case -1:
  4821. case 0x0000FFFF:
  4822. pwnd = PWND_BROADCAST;
  4823. break;
  4824. case 0:
  4825. pwnd = NULL;
  4826. break;
  4827. default:
  4828. if ((pwnd = ValidateHwnd(hwnd)) == NULL) {
  4829. /*
  4830. * We fake terminates to dead windows! (SAS)
  4831. */
  4832. errret = (msg == WM_DDE_TERMINATE);
  4833. MSGERROR(0);
  4834. }
  4835. break;
  4836. }
  4837. retval = _PostMessage(
  4838. pwnd,
  4839. msg,
  4840. wParam,
  4841. lParam);
  4842. TRACE("NtUserPostMessage");
  4843. ENDRECV();
  4844. }
  4845. BOOL NtUserRegisterHotKey(
  4846. IN HWND hwnd,
  4847. IN int id,
  4848. IN UINT fsModifiers,
  4849. IN UINT vk)
  4850. {
  4851. PWND pwnd;
  4852. BEGINATOMICRECV(BOOL, FALSE);
  4853. TESTFLAGS(fsModifiers, MOD_VALID);
  4854. ValidateHWNDOPT(pwnd, hwnd);
  4855. retval = _RegisterHotKey(pwnd, id, fsModifiers, vk);
  4856. TRACE("NtUserRegisterHotKey");
  4857. ENDATOMICRECV();
  4858. }
  4859. BOOL NtUserRemoveMenu(
  4860. IN HMENU hmenu,
  4861. IN UINT nPosition,
  4862. IN UINT dwFlags)
  4863. {
  4864. PMENU pmenu;
  4865. TL tlpMenu;
  4866. BEGINRECV(BOOL, FALSE);
  4867. TESTFLAGS(dwFlags, MF_VALID);
  4868. ValidateHMENUMODIFYCHECKLOCK(pmenu, hmenu);
  4869. ThreadLock(pmenu, &tlpMenu);
  4870. retval = xxxRemoveMenu(pmenu, nPosition, dwFlags);
  4871. ThreadUnlock(&tlpMenu);
  4872. TRACE("NtUserRemoveMenu");
  4873. ENDRECV();
  4874. }
  4875. BOOL NtUserScrollWindowEx( // API ScrollWindowEx
  4876. IN HWND hwnd,
  4877. IN int dx,
  4878. IN int dy,
  4879. IN CONST RECT *prcScroll OPTIONAL,
  4880. IN CONST RECT *prcClip OPTIONAL,
  4881. IN HRGN hrgnUpdate,
  4882. OUT LPRECT prcUpdate OPTIONAL,
  4883. IN UINT flags)
  4884. {
  4885. RECT rcScroll;
  4886. RECT rcClip;
  4887. RECT rcUpdate;
  4888. BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
  4889. /*
  4890. * Probe arguments
  4891. */
  4892. try {
  4893. if (ARGUMENT_PRESENT(prcScroll)) {
  4894. rcScroll = ProbeAndReadRect(prcScroll);
  4895. prcScroll = &rcScroll;
  4896. }
  4897. if (ARGUMENT_PRESENT(prcClip)) {
  4898. rcClip = ProbeAndReadRect(prcClip);
  4899. prcClip = &rcClip;
  4900. }
  4901. } except (StubExceptionHandler(TRUE)) {
  4902. MSGERROR(0);
  4903. }
  4904. retval = xxxScrollWindowEx(
  4905. pwnd,
  4906. dx,
  4907. dy,
  4908. (PRECT)prcScroll,
  4909. (PRECT)prcClip,
  4910. hrgnUpdate,
  4911. prcUpdate ? &rcUpdate : NULL,
  4912. flags);
  4913. if (ARGUMENT_PRESENT(prcUpdate)) {
  4914. try {
  4915. ProbeAndWriteStructure(prcUpdate, rcUpdate, RECT);
  4916. } except (StubExceptionHandler(TRUE)) {
  4917. MSGERROR(0);
  4918. }
  4919. }
  4920. TRACE("NtUserScrollWindow");
  4921. ENDRECV_HWNDLOCK();
  4922. }
  4923. HWND NtUserSetActiveWindow(
  4924. IN HWND hwnd)
  4925. {
  4926. PWND pwnd;
  4927. TL tlpwnd;
  4928. BEGINRECV(HWND, NULL);
  4929. ValidateHWNDOPT(pwnd, hwnd);
  4930. ThreadLock(pwnd, &tlpwnd);
  4931. retval = (HWND)xxxSetActiveWindow(pwnd);
  4932. retval = PtoH((PVOID)retval);
  4933. ThreadUnlock(&tlpwnd);
  4934. TRACE("NtUserSetActiveWindow");
  4935. ENDRECV();
  4936. }
  4937. HWND NtUserSetCapture(
  4938. IN HWND hwnd)
  4939. {
  4940. PWND pwnd;
  4941. TL tlpwnd;
  4942. BEGINRECV(HWND, NULL);
  4943. ValidateHWNDOPT(pwnd, hwnd);
  4944. ThreadLock(pwnd, &tlpwnd);
  4945. retval = (HWND)xxxSetCapture(pwnd);
  4946. retval = PtoH((PVOID)retval);
  4947. ThreadUnlock(&tlpwnd);
  4948. TRACE("NtUserSetCapture");
  4949. ENDRECV();
  4950. }
  4951. WORD NtUserSetClassWord(
  4952. IN HWND hwnd,
  4953. IN int nIndex,
  4954. IN WORD wNewWord)
  4955. {
  4956. BEGINRECV_HWND(WORD, 0, hwnd);
  4957. retval = _SetClassWord(
  4958. pwnd,
  4959. nIndex,
  4960. wNewWord);
  4961. TRACE("NtUserSetClassWord");
  4962. ENDRECV_HWND();
  4963. }
  4964. HWND NtUserSetClipboardViewer(
  4965. IN HWND hwnd)
  4966. {
  4967. PWND pwnd;
  4968. TL tlpwnd;
  4969. BEGINRECV(HWND, NULL);
  4970. ValidateHWNDOPT(pwnd, hwnd);
  4971. ThreadLock(pwnd, &tlpwnd);
  4972. retval = (HWND)xxxSetClipboardViewer(pwnd);
  4973. retval = PtoH((PVOID)retval);
  4974. ThreadUnlock(&tlpwnd);
  4975. TRACE("NtUserSetClipboardViewer");
  4976. ENDRECV();
  4977. }
  4978. HCURSOR NtUserSetCursor(
  4979. IN HCURSOR hCursor)
  4980. {
  4981. PCURSOR pCursor;
  4982. BEGINRECV(HCURSOR, NULL);
  4983. ValidateHCURSOROPT(pCursor, hCursor);
  4984. retval = (HCURSOR)zzzSetCursor(pCursor);
  4985. retval = PtoH((PVOID)retval);
  4986. TRACE("NtUserSetCursor");
  4987. ENDRECV();
  4988. }
  4989. HWND NtUserSetFocus(
  4990. IN HWND hwnd)
  4991. {
  4992. PWND pwnd;
  4993. TL tlpwnd;
  4994. BEGINRECV(HWND, NULL);
  4995. ValidateHWNDOPT(pwnd, hwnd);
  4996. ThreadLock(pwnd, &tlpwnd);
  4997. retval = (HWND)xxxSetFocus(pwnd);
  4998. retval = PtoH((PVOID)retval);
  4999. ThreadUnlock(&tlpwnd);
  5000. TRACE("NtUserSetFocus");
  5001. ENDRECV();
  5002. }
  5003. BOOL NtUserSetMenu(
  5004. IN HWND hwnd,
  5005. IN HMENU hmenu,
  5006. IN BOOL fRedraw)
  5007. {
  5008. PMENU pmenu;
  5009. TL tlpMenu;
  5010. BEGINRECV_HWNDLOCK_ND(DWORD, 0, hwnd);
  5011. ValidateHMENUOPT(pmenu, hmenu);
  5012. ThreadLockWithPti(ptiCurrent, pmenu, &tlpMenu);
  5013. retval = xxxSetMenu(pwndND, pmenu, fRedraw);
  5014. ThreadUnlock(&tlpMenu);
  5015. TRACE("NtUserSetMenu");
  5016. ENDRECV_HWNDLOCK_ND();
  5017. }
  5018. HWND NtUserSetParent(
  5019. IN HWND hwndChild,
  5020. IN HWND hwndNewParent)
  5021. {
  5022. PWND pwndNewParent;
  5023. TL tlpwndNewParent;
  5024. BEGINRECV_HWNDLOCK_ND(HWND, NULL, hwndChild);
  5025. if (hwndNewParent == NULL) {
  5026. pwndNewParent = _GetDesktopWindow();
  5027. } else if (hwndNewParent == HWND_MESSAGE) {
  5028. pwndNewParent = _GetMessageWindow();
  5029. } else {
  5030. ValidateHWND(pwndNewParent, hwndNewParent);
  5031. }
  5032. ThreadLockWithPti(ptiCurrent, pwndNewParent, &tlpwndNewParent);
  5033. retval = (HWND)xxxSetParent(
  5034. pwndND,
  5035. pwndNewParent);
  5036. retval = PtoH((PVOID)retval);
  5037. ThreadUnlock(&tlpwndNewParent);
  5038. TRACE("NtUserSetParent");
  5039. ENDRECV_HWNDLOCK_ND();
  5040. }
  5041. int NtUserSetScrollInfo( // API SetScrollInfo
  5042. IN HWND hwnd,
  5043. IN int nBar,
  5044. IN LPCSCROLLINFO pInfo,
  5045. IN BOOL fRedraw)
  5046. {
  5047. SCROLLINFO si;
  5048. BEGINRECV_HWNDLOCK_ND(DWORD, 0, hwnd);
  5049. LIMITVALUE(nBar, SB_MAX, "SetScrollInfo");
  5050. /*
  5051. * Probe arguments
  5052. */
  5053. try {
  5054. si = ProbeAndReadScrollInfo(pInfo);
  5055. } except (StubExceptionHandler(TRUE)) {
  5056. MSGERROR(0);
  5057. }
  5058. retval = xxxSetScrollBar(pwndND, nBar, &si, fRedraw);
  5059. TRACE("NtUserSetScrollInfo");
  5060. ENDRECV_HWNDLOCK_ND();
  5061. }
  5062. BOOL NtUserSetSysColors( // API SetSysColors
  5063. IN int nCount,
  5064. IN CONST INT *pSysColor,
  5065. IN CONST COLORREF *pColorValues,
  5066. IN UINT uOptions)
  5067. {
  5068. LPINT lpSysColors = NULL;
  5069. LPDWORD lpSysColorValues = NULL;
  5070. TL tlName, tlSysColors, tlSysColorValues;
  5071. PUNICODE_STRING pProfileUserName = NULL;
  5072. PTHREADINFO ptiCurrent;
  5073. BEGINRECV(BOOL, FALSE);
  5074. ptiCurrent = PtiCurrent();
  5075. /*
  5076. * Prevent restricted threads from changing global stuff
  5077. */
  5078. if (IS_THREAD_RESTRICTED(ptiCurrent, JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS)) {
  5079. MSGERROR(0);
  5080. }
  5081. /*
  5082. * Probe arguments
  5083. */
  5084. if (nCount) {
  5085. try {
  5086. ProbeForReadBuffer(pSysColor, nCount, DATAALIGN);
  5087. ProbeForReadBuffer(pColorValues, nCount, DATAALIGN);
  5088. lpSysColors = UserAllocPoolWithQuota(nCount * sizeof(*pSysColor), TAG_COLORS);
  5089. if (lpSysColors == NULL) {
  5090. ExRaiseStatus(STATUS_NO_MEMORY);
  5091. }
  5092. RtlCopyMemory(lpSysColors, pSysColor, nCount * sizeof(*pSysColor));
  5093. lpSysColorValues = UserAllocPoolWithQuota(nCount * sizeof(*pColorValues), TAG_COLORVALUES);
  5094. if (lpSysColorValues == NULL) {
  5095. ExRaiseStatus(STATUS_NO_MEMORY);
  5096. }
  5097. RtlCopyMemory(lpSysColorValues, pColorValues, nCount * sizeof(*pColorValues));
  5098. } except (StubExceptionHandler(TRUE)) {
  5099. MSGERRORCLEANUP(0);
  5100. }
  5101. }
  5102. ThreadLockPool(ptiCurrent, lpSysColors, &tlSysColors);
  5103. ThreadLockPool(ptiCurrent, lpSysColorValues, &tlSysColorValues);
  5104. pProfileUserName = CreateProfileUserName(&tlName);
  5105. retval = xxxSetSysColors(pProfileUserName,
  5106. nCount,
  5107. lpSysColors,
  5108. lpSysColorValues,
  5109. uOptions);
  5110. FreeProfileUserName(pProfileUserName, &tlName);
  5111. ThreadUnlockPool(ptiCurrent, &tlSysColorValues);
  5112. ThreadUnlockPool(ptiCurrent, &tlSysColors);
  5113. CLEANUPRECV();
  5114. if (lpSysColors) {
  5115. UserFreePool(lpSysColors);
  5116. }
  5117. if (lpSysColorValues) {
  5118. UserFreePool(lpSysColorValues);
  5119. }
  5120. TRACE("NtUserSetSysColors");
  5121. ENDRECV();
  5122. }
  5123. UINT_PTR NtUserSetTimer(
  5124. IN HWND hwnd,
  5125. IN UINT_PTR nIDEvent,
  5126. IN UINT wElapse,
  5127. IN TIMERPROC pTimerFunc)
  5128. {
  5129. PWND pwnd;
  5130. BEGINATOMICRECV(UINT_PTR, 0);
  5131. ValidateHWNDOPT(pwnd, hwnd);
  5132. /*
  5133. * We have code on the client side that assumes no CSRSS code creates
  5134. * a timer with a timer proc, so assert that that's the case.
  5135. */
  5136. UserAssert(PsGetCurrentProcess() != gpepCSRSS || pTimerFunc == NULL);
  5137. /*
  5138. * If we let apps set a timer granularity less then 10 the app
  5139. * spends too long processing timer messages. Some WOW apps like
  5140. * Paradox in WinStone use zero to effectively get the minimal
  5141. * timer value which was ~55ms in Win 3.1. We also step this
  5142. * value up for 32 bit apps because the NT timer resolution
  5143. * can very depending if the multimedia timers have turned up
  5144. * the resolution. If they have NT apps that specify a low value
  5145. * will not work properly because they will eat the CPU processing
  5146. * WM_TIMER messages.
  5147. */
  5148. if (wElapse < 10) {
  5149. wElapse = 10;
  5150. }
  5151. retval = _SetTimer(
  5152. pwnd,
  5153. nIDEvent,
  5154. wElapse,
  5155. (TIMERPROC_PWND)pTimerFunc);
  5156. TRACE("NtUserSetTimer");
  5157. ENDATOMICRECV();
  5158. }
  5159. LONG_PTR NtUserSetWindowLongPtr(
  5160. IN HWND hwnd,
  5161. IN int nIndex,
  5162. IN LONG_PTR dwNewLong,
  5163. IN BOOL bAnsi)
  5164. {
  5165. BEGINRECV_HWNDLOCK(ULONG_PTR, 0, hwnd);
  5166. retval = xxxSetWindowLongPtr(pwnd, nIndex, dwNewLong, bAnsi);
  5167. TRACE("NtUserSetWindowLongPtr");
  5168. ENDRECV_HWNDLOCK();
  5169. }
  5170. #ifdef _WIN64
  5171. LONG NtUserSetWindowLong(
  5172. IN HWND hwnd,
  5173. IN int nIndex,
  5174. IN LONG dwNewLong,
  5175. IN BOOL bAnsi)
  5176. {
  5177. BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
  5178. retval = xxxSetWindowLong(pwnd, nIndex, dwNewLong, bAnsi);
  5179. TRACE("NtUserSetWindowLong");
  5180. ENDRECV_HWNDLOCK();
  5181. }
  5182. #endif
  5183. WORD NtUserSetWindowWord(
  5184. IN HWND hwnd,
  5185. IN int nIndex,
  5186. IN WORD wNewWord)
  5187. {
  5188. BEGINRECV_HWND(WORD, 0, hwnd);
  5189. retval = _SetWindowWord(pwnd, nIndex, wNewWord);
  5190. TRACE("NtUserSetWindowWord");
  5191. ENDRECV_HWND();
  5192. }
  5193. HHOOK NtUserSetWindowsHookAW(
  5194. IN int nFilterType,
  5195. IN HOOKPROC pfnFilterProc,
  5196. IN DWORD dwFlags)
  5197. {
  5198. BEGINRECV(HHOOK, NULL);
  5199. retval = (HHOOK)zzzSetWindowsHookAW(nFilterType, (PROC)pfnFilterProc, dwFlags);
  5200. TRACE("NtUserSetWindowsHookAW");
  5201. ENDRECV();
  5202. }
  5203. BOOL NtUserShowCaret(
  5204. IN HWND hwnd)
  5205. {
  5206. PWND pwnd;
  5207. BEGINRECV(BOOL, FALSE);
  5208. ValidateHWNDOPT(pwnd, hwnd);
  5209. retval = zzzShowCaret(pwnd);
  5210. TRACE("NtUserShowCaret");
  5211. ENDRECV();
  5212. }
  5213. BOOL NtUserShowScrollBar(
  5214. IN HWND hwnd,
  5215. IN int iBar,
  5216. IN BOOL fShow)
  5217. {
  5218. BEGINRECV_HWNDLOCK_ND(DWORD, 0, hwnd);
  5219. LIMITVALUE(iBar, SB_MAX, "ShowScrollBar");
  5220. retval = xxxShowScrollBar(pwndND, iBar, fShow);
  5221. TRACE("NtUserShowScrollBar");
  5222. ENDRECV_HWNDLOCK_ND();
  5223. }
  5224. BOOL NtUserShowWindowAsync(
  5225. IN HWND hwnd,
  5226. IN int nCmdShow)
  5227. {
  5228. BEGINRECV_HWNDLOCK_ND(BOOL, FALSE, hwnd);
  5229. LIMITVALUE(nCmdShow, SW_MAX, "ShowWindowAsync");
  5230. retval = _ShowWindowAsync(pwndND, nCmdShow, 0);
  5231. TRACE("NtUserShowWindowAsync");
  5232. ENDRECV_HWNDLOCK_ND();
  5233. }
  5234. BOOL NtUserShowWindow(
  5235. IN HWND hwnd,
  5236. IN int nCmdShow)
  5237. {
  5238. BEGINRECV_HWNDLOCK_ND(BOOL, FALSE, hwnd);
  5239. LIMITVALUE(nCmdShow, SW_MAX, "ShowWindow");
  5240. /*
  5241. * Let's not allow the window to be shown/hidden once we
  5242. * started the destruction of the window.
  5243. */
  5244. if (TestWF(pwndND, WFINDESTROY)) {
  5245. RIPERR1(ERROR_INVALID_PARAMETER,
  5246. RIP_WARNING,
  5247. "ShowWindow: Window is being destroyed (%#p)",
  5248. pwndND);
  5249. MSGERROR(0);
  5250. }
  5251. retval = xxxShowWindow(pwndND, nCmdShow | TEST_PUDF(PUDF_ANIMATE));
  5252. TRACE("NtUserShowWindow");
  5253. ENDRECV_HWNDLOCK_ND();
  5254. }
  5255. BOOL NtUserTrackMouseEvent( // API TrackMouseEvent
  5256. IN OUT LPTRACKMOUSEEVENT lpTME)
  5257. {
  5258. TRACKMOUSEEVENT tme;
  5259. BEGINRECV(BOOL, FALSE);
  5260. /*
  5261. * Probe arguments
  5262. */
  5263. try {
  5264. tme = ProbeAndReadTrackMouseEvent(lpTME);
  5265. if (tme.cbSize != sizeof(tme)) {
  5266. RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "TrackMouseEvent: invalid size %lX", tme.cbSize);
  5267. MSGERROR(0);
  5268. }
  5269. TESTFLAGS(tme.dwFlags, TME_VALID);
  5270. } except (StubExceptionHandler(TRUE)) {
  5271. MSGERROR(0);
  5272. }
  5273. if (tme.dwFlags & TME_QUERY) {
  5274. retval = QueryTrackMouseEvent(&tme);
  5275. try {
  5276. RtlCopyMemory(lpTME, &tme, sizeof(tme));
  5277. } except (StubExceptionHandler(TRUE)) {
  5278. MSGERROR(0);
  5279. }
  5280. } else {
  5281. retval = TrackMouseEvent(&tme);
  5282. }
  5283. TRACE("NtUserTrackMouseEvent");
  5284. ENDRECV();
  5285. }
  5286. BOOL NtUserTrackPopupMenuEx( // API TrackPopupMenuEx
  5287. IN HMENU hMenu,
  5288. IN UINT uFlags,
  5289. IN int x,
  5290. IN int y,
  5291. IN HWND hwnd,
  5292. IN CONST TPMPARAMS *pparamst OPTIONAL)
  5293. {
  5294. PWND pwnd;
  5295. PMENU pmenu;
  5296. TL tlpwnd;
  5297. TL tlpMenu;
  5298. PTHREADINFO ptiCurrent;
  5299. TPMPARAMS paramst;
  5300. BEGINRECV(BOOL, FALSE);
  5301. TESTFLAGS(uFlags, TPM_VALID);
  5302. ValidateHMENU(pmenu, hMenu);
  5303. ValidateHWND(pwnd, hwnd);
  5304. ptiCurrent = PtiCurrent();
  5305. ThreadLockAlwaysWithPti(ptiCurrent, pwnd, &tlpwnd);
  5306. ThreadLockAlwaysWithPti(ptiCurrent, pmenu, &tlpMenu);
  5307. /*
  5308. * Probe arguments
  5309. */
  5310. try {
  5311. if (ARGUMENT_PRESENT(pparamst)) {
  5312. paramst = ProbeAndReadPopupParams(pparamst);
  5313. pparamst = &paramst;
  5314. }
  5315. } except (StubExceptionHandler(TRUE)) {
  5316. MSGERRORCLEANUP(0);
  5317. }
  5318. retval = xxxTrackPopupMenuEx(
  5319. pmenu,
  5320. uFlags,
  5321. x,
  5322. y,
  5323. pwnd,
  5324. pparamst);
  5325. CLEANUPRECV();
  5326. ThreadUnlock(&tlpMenu);
  5327. ThreadUnlock(&tlpwnd);
  5328. TRACE("NtUserTrackPopupMenuEx");
  5329. ENDRECV();
  5330. }
  5331. UINT NtUserPaintMenuBar(
  5332. IN HWND hwnd,
  5333. IN HDC hdc,
  5334. IN int iLeftOffset,
  5335. IN int iRightOffset,
  5336. IN int iTopOffset,
  5337. IN DWORD dwFlags)
  5338. {
  5339. BEGINRECV_HWNDLOCK(UINT, 0, hwnd);
  5340. /*
  5341. * This routine should only be called for top-level windows.
  5342. */
  5343. if (TestwndChild(pwnd)) {
  5344. MSGERROR(ERROR_INVALID_PARAMETER);
  5345. }
  5346. TESTFLAGS(dwFlags, PMB_VALID);
  5347. if (iLeftOffset < 0 || iRightOffset < 0 || iTopOffset < 0) {
  5348. MSGERROR(ERROR_INVALID_PARAMETER);
  5349. }
  5350. retval = xxxPaintMenuBar(pwnd, hdc, iLeftOffset, iRightOffset, iTopOffset, dwFlags);
  5351. TRACE("NtUserPaintMenuBar");
  5352. ENDRECV_HWNDLOCK();
  5353. }
  5354. UINT NtUserCalcMenuBar(
  5355. IN HWND hwnd,
  5356. IN int iLeftOffset,
  5357. IN int iRightOffset,
  5358. IN int iTopOffset,
  5359. IN LPCRECT prcWnd)
  5360. {
  5361. RECT rcWnd;
  5362. BEGINRECV_HWNDLOCK(UINT, 0, hwnd);
  5363. if (iLeftOffset < 0 || iRightOffset < 0 || iTopOffset < 0) {
  5364. MSGERROR(ERROR_INVALID_PARAMETER);
  5365. }
  5366. try {
  5367. if (ARGUMENT_PRESENT(prcWnd)) {
  5368. rcWnd = ProbeAndReadRect(prcWnd);
  5369. } else {
  5370. CopyRect(&rcWnd, &pwnd->rcWindow);
  5371. }
  5372. } except (StubExceptionHandler(FALSE)) {
  5373. MSGERROR(0);
  5374. }
  5375. retval = xxxCalcMenuBar(pwnd, iLeftOffset, iRightOffset, iTopOffset, &rcWnd);
  5376. TRACE("NtUserCalcMenuBar");
  5377. ENDRECV_HWNDLOCK();
  5378. }
  5379. BOOL NtUserTranslateMessage( // API TranslateMessage
  5380. IN CONST MSG *lpMsg,
  5381. IN UINT flags)
  5382. {
  5383. MSG msg;
  5384. BEGINRECV(BOOL, FALSE);
  5385. /*
  5386. * Probe arguments
  5387. */
  5388. try {
  5389. msg = ProbeAndReadMessage(lpMsg);
  5390. } except (StubExceptionHandler(TRUE)) {
  5391. MSGERROR(0);
  5392. }
  5393. if (ValidateHwnd(msg.hwnd) == NULL) {
  5394. MSGERROR(0);
  5395. }
  5396. retval = xxxTranslateMessage(
  5397. &msg,
  5398. flags);
  5399. TRACE("NtUserTranslateMessage");
  5400. ENDRECV();
  5401. }
  5402. BOOL NtUserUnhookWindowsHookEx(
  5403. IN HHOOK hhk)
  5404. {
  5405. PHOOK phk;
  5406. BEGINRECV(BOOL, FALSE);
  5407. ValidateHHOOK(phk, hhk);
  5408. retval = zzzUnhookWindowsHookEx(
  5409. phk);
  5410. TRACE("NtUserUnhookWindowsHookEx");
  5411. ENDRECV();
  5412. }
  5413. BOOL NtUserUnregisterHotKey(
  5414. IN HWND hwnd,
  5415. IN int id)
  5416. {
  5417. PWND pwnd;
  5418. BEGINATOMICRECV(BOOL, FALSE);
  5419. ValidateHWNDOPT(pwnd, hwnd);
  5420. retval = _UnregisterHotKey(
  5421. pwnd,
  5422. id);
  5423. TRACE("NtUserUnregisterHotKey");
  5424. ENDATOMICRECV();
  5425. }
  5426. BOOL NtUserValidateRect( // API ValidateRect
  5427. IN HWND hwnd,
  5428. IN CONST RECT *lpRect OPTIONAL)
  5429. {
  5430. PWND pwnd;
  5431. TL tlpwnd;
  5432. RECT rc;
  5433. BEGINRECV(BOOL, FALSE);
  5434. /*
  5435. * Probe arguments
  5436. */
  5437. if (ARGUMENT_PRESENT(lpRect)) {
  5438. try {
  5439. rc = ProbeAndReadRect(lpRect);
  5440. lpRect = &rc;
  5441. } except (StubExceptionHandler(TRUE)) {
  5442. MSGERROR(0);
  5443. }
  5444. }
  5445. ValidateHWNDOPT(pwnd, hwnd);
  5446. ThreadLock(pwnd, &tlpwnd);
  5447. retval = xxxValidateRect(pwnd, (PRECT)lpRect);
  5448. ThreadUnlock(&tlpwnd);
  5449. TRACE("NtUserValidateRect");
  5450. ENDRECV();
  5451. }
  5452. DWORD NtUserWaitForInputIdle(
  5453. IN ULONG_PTR idProcess,
  5454. IN DWORD dwMilliseconds,
  5455. IN BOOL fSharedWow)
  5456. {
  5457. BEGINRECV(DWORD, (DWORD)-1);
  5458. retval = xxxWaitForInputIdle(
  5459. idProcess,
  5460. dwMilliseconds,
  5461. fSharedWow);
  5462. TRACE("NtUserWaitForInputIdle");
  5463. ENDRECV();
  5464. }
  5465. HWND NtUserWindowFromPoint(
  5466. IN POINT Point)
  5467. {
  5468. BEGINRECV(HWND, NULL);
  5469. retval = (HWND)xxxWindowFromPoint(
  5470. Point);
  5471. retval = PtoH((PVOID)retval);
  5472. TRACE("NtUserWindowFromPoint");
  5473. ENDRECV();
  5474. }
  5475. HDC NtUserBeginPaint( // API BeginPaint
  5476. IN HWND hwnd,
  5477. OUT LPPAINTSTRUCT lpPaint)
  5478. {
  5479. PAINTSTRUCT ps;
  5480. BEGINRECV_HWNDLOCK(HDC, NULL, hwnd);
  5481. retval = xxxBeginPaint(pwnd, &ps);
  5482. /*
  5483. * Probe arguments
  5484. */
  5485. try {
  5486. ProbeAndWriteStructure(lpPaint, ps, PAINTSTRUCT);
  5487. } except (StubExceptionHandler(TRUE)) {
  5488. xxxEndPaint(pwnd, &ps);
  5489. MSGERROR(0);
  5490. }
  5491. TRACE("NtUserBeginPaint");
  5492. ENDRECV_HWNDLOCK();
  5493. }
  5494. BOOL NtUserCreateCaret(
  5495. IN HWND hwnd,
  5496. IN HBITMAP hBitmap,
  5497. IN int nWidth,
  5498. IN int nHeight)
  5499. {
  5500. BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
  5501. retval = xxxCreateCaret(pwnd, hBitmap, nWidth, nHeight);
  5502. TRACE("NtUserCreateCaret");
  5503. ENDRECV_HWNDLOCK();
  5504. }
  5505. BOOL NtUserEndPaint( // API EndPaint
  5506. IN HWND hwnd,
  5507. IN CONST PAINTSTRUCT *lpPaint)
  5508. {
  5509. PAINTSTRUCT ps;
  5510. BEGINRECV_HWNDLOCK(BOOL, FALSE, hwnd);
  5511. /*
  5512. * Probe arguments
  5513. */
  5514. try {
  5515. ps = ProbeAndReadPaintStruct(lpPaint);
  5516. } except (StubExceptionHandler(TRUE)) {
  5517. MSGERROR(0);
  5518. }
  5519. retval = xxxEndPaint(pwnd, &ps);
  5520. TRACE("NtUserEndPaint");
  5521. ENDRECV_HWNDLOCK();
  5522. }
  5523. int NtUserExcludeUpdateRgn(
  5524. IN HDC hdc,
  5525. IN HWND hwnd)
  5526. {
  5527. BEGINRECV_HWND(int, ERROR, hwnd);
  5528. if (hdc == NULL)
  5529. MSGERROR(0);
  5530. retval = _ExcludeUpdateRgn(hdc, pwnd);
  5531. TRACE("NtUserExcludeUpdateRgn");
  5532. ENDRECV_HWND();
  5533. }
  5534. HDC NtUserGetDC(
  5535. IN HWND hwnd)
  5536. {
  5537. PWND pwnd;
  5538. BOOL bValid = TRUE;
  5539. BEGINATOMICRECV(HDC, NULL);
  5540. ValidateHWNDOPT(pwnd, hwnd);
  5541. if (IS_CURRENT_THREAD_RESTRICTED(JOB_OBJECT_UILIMIT_HANDLES) && pwnd == NULL) {
  5542. PDESKTOP pdesk = PtiCurrent()->rpdesk;
  5543. /*
  5544. * Make sure it has access to the desktop window.
  5545. */
  5546. if (!ValidateHwnd(PtoH(pdesk->pDeskInfo->spwnd))) {
  5547. bValid = FALSE;
  5548. }
  5549. }
  5550. retval = _GetDC(pwnd);
  5551. if (!bValid) {
  5552. HRGN hrgn = CreateEmptyRgn();
  5553. /*
  5554. * Select a NULL visible region on this DC so that restricted
  5555. * processes don't mess with GetDC(NULL).
  5556. */
  5557. GreSelectVisRgn(retval, hrgn, SVR_DELETEOLD);
  5558. }
  5559. TRACE("NtUserGetDC");
  5560. ENDATOMICRECV();
  5561. }
  5562. HDC NtUserGetDCEx(
  5563. IN HWND hwnd,
  5564. IN HRGN hrgnClip,
  5565. IN DWORD flags)
  5566. {
  5567. PWND pwnd;
  5568. BEGINATOMICRECV(HDC, NULL);
  5569. if ((hrgnClip && !GreIsValidRegion(hrgnClip)) || flags & ~DCX_MASK) {
  5570. RIPMSG0(RIP_ERROR, "NtUserGetDCEx passed invalid parameter");
  5571. MSGERROR(ERROR_INVALID_PARAMETER);
  5572. }
  5573. ValidateHWNDOPT(pwnd, hwnd);
  5574. if (pwnd == NULL) {
  5575. pwnd = PtiCurrent()->rpdesk->pDeskInfo->spwnd;
  5576. if (IS_CURRENT_THREAD_RESTRICTED(JOB_OBJECT_UILIMIT_HANDLES)) {
  5577. /*
  5578. * Make sure it has access to the desktop window.
  5579. */
  5580. if (!ValidateHwnd(PtoH(pwnd))) {
  5581. RIPMSG0(RIP_WARNING,
  5582. "NtUserGetDCEx fails desktop window validation");
  5583. MSGERROR(0);
  5584. }
  5585. }
  5586. }
  5587. retval = _GetDCEx(pwnd, hrgnClip, flags);
  5588. TRACE("NtUserGetDCEx");
  5589. ENDATOMICRECV();
  5590. }
  5591. HDC NtUserGetWindowDC(
  5592. IN HWND hwnd)
  5593. {
  5594. PWND pwnd;
  5595. BEGINATOMICRECV(HDC, NULL);
  5596. ValidateHWNDOPT(pwnd, hwnd);
  5597. retval = _GetWindowDC(pwnd);
  5598. TRACE("NtUserGetWindowDC");
  5599. ENDATOMICRECV();
  5600. }
  5601. int NtUserGetUpdateRgn(
  5602. IN HWND hwnd,
  5603. IN HRGN hrgn,
  5604. IN BOOL bErase)
  5605. {
  5606. BEGINRECV_HWNDLOCK(int, ERROR, hwnd);
  5607. retval = xxxGetUpdateRgn(
  5608. pwnd,
  5609. hrgn,
  5610. bErase);
  5611. TRACE("NtUserGetUpdateRgn");
  5612. ENDRECV_HWNDLOCK();
  5613. }
  5614. BOOL NtUserRedrawWindow( // API RedrawWindow
  5615. IN HWND hwnd,
  5616. IN CONST RECT *lprcUpdate OPTIONAL,
  5617. IN HRGN hrgnUpdate,
  5618. IN UINT flags)
  5619. {
  5620. RECT rc;
  5621. BEGINRECV_HWNDLOCK_OPT(BOOL, FALSE, hwnd);
  5622. /*
  5623. * Probe arguments
  5624. */
  5625. if (ARGUMENT_PRESENT(lprcUpdate)) {
  5626. try {
  5627. rc = ProbeAndReadRect(lprcUpdate);
  5628. lprcUpdate = &rc;
  5629. } except (StubExceptionHandler(TRUE)) {
  5630. MSGERROR(0);
  5631. }
  5632. }
  5633. TESTFLAGS(flags, RDW_VALIDMASK);
  5634. retval = xxxRedrawWindow(
  5635. pwnd,
  5636. (PRECT)lprcUpdate,
  5637. hrgnUpdate,
  5638. flags);
  5639. TRACE("NtUserRedrawWindow");
  5640. ENDRECV_HWNDLOCK_OPT();
  5641. }
  5642. BOOL NtUserInvalidateRgn(
  5643. IN HWND hwnd,
  5644. IN HRGN hrgn,
  5645. IN BOOL bErase)
  5646. {
  5647. BEGINRECV_HWNDLOCK(BOOL, FALSE, hwnd);
  5648. retval = xxxInvalidateRgn(
  5649. pwnd,
  5650. hrgn,
  5651. bErase);
  5652. TRACE("NtUserInvalidateRgn");
  5653. ENDRECV_HWNDLOCK();
  5654. }
  5655. int NtUserSetWindowRgn(
  5656. IN HWND hwnd,
  5657. IN HRGN hrgn,
  5658. IN BOOL bRedraw)
  5659. {
  5660. BEGINRECV_HWNDLOCK_ND(int, 0, hwnd);
  5661. retval = xxxSetWindowRgn(
  5662. pwndND,
  5663. hrgn,
  5664. bRedraw);
  5665. TRACE("NtUserSetWindowRgn");
  5666. ENDRECV_HWNDLOCK_ND();
  5667. }
  5668. BOOL NtUserScrollDC( // API ScrollDC
  5669. IN HDC hdc,
  5670. IN int dx,
  5671. IN int dy,
  5672. IN CONST RECT *prcScroll OPTIONAL,
  5673. IN CONST RECT *prcClip OPTIONAL,
  5674. IN HRGN hrgnUpdate,
  5675. OUT LPRECT prcUpdate OPTIONAL)
  5676. {
  5677. RECT rcScroll;
  5678. RECT rcClip;
  5679. RECT rcUpdate;
  5680. BEGINRECV(BOOL, FALSE);
  5681. /*
  5682. * Probe arguments
  5683. */
  5684. try {
  5685. if (ARGUMENT_PRESENT(prcScroll)) {
  5686. rcScroll = ProbeAndReadRect(prcScroll);
  5687. prcScroll = &rcScroll;
  5688. }
  5689. if (ARGUMENT_PRESENT(prcClip)) {
  5690. rcClip = ProbeAndReadRect(prcClip);
  5691. prcClip = &rcClip;
  5692. }
  5693. } except (StubExceptionHandler(TRUE)) {
  5694. MSGERROR(0);
  5695. }
  5696. retval = _ScrollDC(
  5697. hdc,
  5698. dx,
  5699. dy,
  5700. (PRECT)prcScroll,
  5701. (PRECT)prcClip,
  5702. hrgnUpdate,
  5703. prcUpdate ? &rcUpdate : NULL);
  5704. if (ARGUMENT_PRESENT(prcUpdate)) {
  5705. try {
  5706. ProbeAndWriteStructure(prcUpdate, rcUpdate, RECT);
  5707. } except (StubExceptionHandler(TRUE)) {
  5708. MSGERROR(0);
  5709. }
  5710. }
  5711. ENDRECV();
  5712. }
  5713. int NtUserInternalGetWindowText( // private InternalGetWindowText
  5714. IN HWND hwnd,
  5715. OUT LPWSTR lpString,
  5716. IN int nMaxCount)
  5717. {
  5718. BEGINRECV_HWND_SHARED(DWORD, 0, hwnd);
  5719. if (nMaxCount) {
  5720. /*
  5721. * Probe arguments
  5722. */
  5723. try {
  5724. ProbeForWriteBuffer(lpString, nMaxCount, CHARALIGN);
  5725. /*
  5726. * Initialize string empty.
  5727. */
  5728. *lpString = TEXT('\0');
  5729. if (pwnd->strName.Length) {
  5730. retval = TextCopy(&pwnd->strName, lpString, nMaxCount);
  5731. } else {
  5732. retval = 0;
  5733. }
  5734. } except (StubExceptionHandler(FALSE)) {
  5735. MSGERROR(0); // private API, don't SetLastError
  5736. }
  5737. } else {
  5738. MSGERROR(0);
  5739. }
  5740. TRACE("NtUserInternalGetWindowText");
  5741. ENDRECV_HWND_SHARED();
  5742. }
  5743. int NtUserGetMouseMovePointsEx( // API GetMouseMovePointsEx
  5744. IN UINT cbSize,
  5745. IN CONST MOUSEMOVEPOINT *lppt,
  5746. OUT MOUSEMOVEPOINT *lpptBuf,
  5747. IN UINT nBufPoints,
  5748. IN DWORD resolution)
  5749. {
  5750. MOUSEMOVEPOINT mmp;
  5751. BEGINRECV(int, -1);
  5752. if (cbSize != sizeof(MOUSEMOVEPOINT) || nBufPoints > MAX_MOUSEPOINTS) {
  5753. RIPERR2(ERROR_INVALID_PARAMETER, RIP_VERBOSE,
  5754. "GetMouseMovePointsEx: invalid cbSize %d or nBufPoints %d",
  5755. cbSize, nBufPoints);
  5756. MSGERROR(0);
  5757. }
  5758. /*
  5759. * Probe arguments
  5760. */
  5761. try {
  5762. mmp = ProbeAndReadStructure(lppt, MOUSEMOVEPOINT);
  5763. ProbeForWriteBuffer(lpptBuf, nBufPoints, DATAALIGN);
  5764. } except (StubExceptionHandler(TRUE)) {
  5765. MSGERROR(0);
  5766. }
  5767. /*
  5768. * GetMouseMovePointsEx protects itself with a try block.
  5769. * No it doesn't!
  5770. */
  5771. retval = _GetMouseMovePointsEx(&mmp, lpptBuf, nBufPoints, resolution);
  5772. TRACE("NtUserGetMouseMovePointsEx");
  5773. ENDRECV();
  5774. }
  5775. int NtUserToUnicodeEx( // API ToUnicode/ToUnicodeEx/ToAscii/ToAsciiEx
  5776. IN UINT wVirtKey,
  5777. IN UINT wScanCode,
  5778. IN CONST BYTE *lpKeyState,
  5779. OUT LPWSTR pwszBuff,
  5780. IN int cchBuff,
  5781. IN UINT wFlags,
  5782. IN HKL hKeyboardLayout)
  5783. {
  5784. BYTE KeyState[256];
  5785. WCHAR wcBuff[4];
  5786. LPWSTR pwszBuffK;
  5787. BOOL bAlloc = FALSE;
  5788. PTHREADINFO ptiCurrent;
  5789. TL tlInput;
  5790. BEGINRECV(int, 0);
  5791. if (cchBuff <= 0) {
  5792. MSGERROR(ERROR_INVALID_PARAMETER);
  5793. }
  5794. /*
  5795. * Probe arguments
  5796. */
  5797. try {
  5798. ProbeForRead(lpKeyState, 256, sizeof(BYTE));
  5799. RtlCopyMemory(KeyState, lpKeyState, 256);
  5800. ProbeForWriteBuffer(pwszBuff, cchBuff, CHARALIGN);
  5801. if (cchBuff < 4) {
  5802. pwszBuffK = wcBuff;
  5803. }else {
  5804. pwszBuffK = UserAllocPoolWithQuota(cchBuff * sizeof(WCHAR), TAG_UNICODEBUFFER);
  5805. if (pwszBuffK == NULL) {
  5806. ExRaiseStatus(STATUS_NO_MEMORY);
  5807. }
  5808. bAlloc = TRUE;
  5809. ptiCurrent = PtiCurrent();
  5810. ThreadLockPool(ptiCurrent, pwszBuffK, &tlInput);
  5811. }
  5812. } except (StubExceptionHandler(TRUE)) {
  5813. MSGERROR(0);
  5814. }
  5815. retval = xxxToUnicodeEx(
  5816. wVirtKey,
  5817. wScanCode,
  5818. KeyState,
  5819. pwszBuffK,
  5820. cchBuff,
  5821. wFlags,
  5822. hKeyboardLayout);
  5823. try {
  5824. RtlCopyMemory(pwszBuff, pwszBuffK, cchBuff*sizeof(WCHAR));
  5825. } except (StubExceptionHandler(TRUE)) {
  5826. MSGERRORCLEANUP(0);
  5827. }
  5828. CLEANUPRECV();
  5829. if (bAlloc) {
  5830. ThreadUnlockAndFreePool(ptiCurrent, &tlInput);
  5831. }
  5832. TRACE("NtUserToUnicodeEx");
  5833. ENDRECV();
  5834. }
  5835. BOOL NtUserYieldTask(
  5836. VOID)
  5837. {
  5838. PTHREADINFO ptiCurrent;
  5839. BOOL bBackground;
  5840. BEGINRECV(BOOL, FALSE);
  5841. /*
  5842. * Make sure this process is running in the background if it is just
  5843. * spinning.
  5844. */
  5845. ptiCurrent = PtiCurrent();
  5846. try {
  5847. ptiCurrent->pClientInfo->cSpins++;
  5848. bBackground = ptiCurrent->pClientInfo->cSpins >= CSPINBACKGROUND;
  5849. } except (StubExceptionHandler(TRUE)) {
  5850. MSGERROR(0);
  5851. }
  5852. /*
  5853. * CheckProcessBackground see input.c for comments
  5854. */
  5855. if (bBackground) {
  5856. try {
  5857. ptiCurrent->pClientInfo->cSpins = 0;
  5858. ptiCurrent->pClientInfo->dwTIFlags |= TIF_SPINNING;
  5859. } except (StubExceptionHandler(TRUE)) {
  5860. MSGERROR(0);
  5861. }
  5862. ptiCurrent->TIF_flags |= TIF_SPINNING;
  5863. if (!(ptiCurrent->ppi->W32PF_Flags & W32PF_FORCEBACKGROUNDPRIORITY)) {
  5864. ptiCurrent->ppi->W32PF_Flags |= W32PF_FORCEBACKGROUNDPRIORITY;
  5865. if (ptiCurrent->ppi == gppiWantForegroundPriority) {
  5866. SetForegroundPriority(ptiCurrent, FALSE);
  5867. }
  5868. }
  5869. }
  5870. retval = xxxUserYield(ptiCurrent);
  5871. TRACE("NtUserYieldTask");
  5872. ENDRECV();
  5873. }
  5874. BOOL NtUserWaitMessage(
  5875. VOID)
  5876. {
  5877. BEGINRECV(BOOL, FALSE);
  5878. retval = xxxWaitMessage();
  5879. TRACE("NtUserWaitMessage");
  5880. ENDRECV();
  5881. }
  5882. #ifdef MESSAGE_PUMP_HOOK
  5883. BOOL NtUserRealWaitMessageEx(
  5884. IN UINT fsWakeMask,
  5885. IN DWORD Timeout)
  5886. {
  5887. BEGINRECV(BOOL, FALSE);
  5888. TESTFLAGS(fsWakeMask, QS_VALID);
  5889. if (!IsInsideMPH()) {
  5890. RIPMSG0(RIP_WARNING, "NtUserRealWaitMessageEx: Calling MPH function on non-initialized thread");
  5891. }
  5892. retval = xxxRealWaitMessageEx(fsWakeMask, Timeout);
  5893. TRACE("NtUserRealWaitMessage");
  5894. ENDRECV();
  5895. }
  5896. #endif // MESSAGE_PUMP_HOOK
  5897. UINT NtUserLockWindowStation(
  5898. IN HWINSTA hwinsta)
  5899. {
  5900. PWINDOWSTATION pwinsta;
  5901. NTSTATUS Status;
  5902. BEGINRECV(UINT, 0);
  5903. Status = ValidateHwinsta(hwinsta, UserMode, 0, &pwinsta);
  5904. if (!NT_SUCCESS(Status))
  5905. MSGERROR(0);
  5906. retval = _LockWindowStation(pwinsta);
  5907. ObDereferenceObject(pwinsta);
  5908. TRACE("NtUserLockWindowStation");
  5909. ENDRECV();
  5910. }
  5911. BOOL NtUserUnlockWindowStation(
  5912. IN HWINSTA hwinsta)
  5913. {
  5914. PWINDOWSTATION pwinsta;
  5915. NTSTATUS Status;
  5916. BEGINRECV(BOOL, FALSE);
  5917. Status = ValidateHwinsta(hwinsta, UserMode, 0, &pwinsta);
  5918. if (!NT_SUCCESS(Status))
  5919. MSGERROR(0);
  5920. retval = _UnlockWindowStation(pwinsta);
  5921. ObDereferenceObject(pwinsta);
  5922. TRACE("NtUserUnlockWindowStation");
  5923. ENDRECV();
  5924. }
  5925. UINT NtUserSetWindowStationUser( // private SetWindowStationUser
  5926. IN HWINSTA hwinsta,
  5927. IN PLUID pLuidUser,
  5928. IN PSID pSidUser OPTIONAL,
  5929. IN DWORD cbSidUser)
  5930. {
  5931. PWINDOWSTATION pwinsta;
  5932. NTSTATUS Status;
  5933. LUID luid;
  5934. BEGINATOMICRECV(UINT, FALSE);
  5935. Status = ValidateHwinsta(hwinsta, UserMode, 0, &pwinsta);
  5936. if (!NT_SUCCESS(Status))
  5937. MSGERROR(0);
  5938. try {
  5939. ProbeForRead(pLuidUser, sizeof(*pLuidUser), sizeof(DWORD));
  5940. luid = *pLuidUser;
  5941. if (ARGUMENT_PRESENT(pSidUser)) {
  5942. ProbeForRead(pSidUser, cbSidUser, sizeof(DWORD));
  5943. }
  5944. } except (StubExceptionHandler(FALSE)) {
  5945. MSGERRORCLEANUP(0); // don't SetLastError for private API
  5946. }
  5947. /*
  5948. * SetWindowStationUser uses pSidUser in a try block.
  5949. */
  5950. retval = _SetWindowStationUser(pwinsta, &luid, pSidUser, cbSidUser);
  5951. CLEANUPRECV();
  5952. ObDereferenceObject(pwinsta);
  5953. TRACE("NtUserSetWindowStationUser");
  5954. ENDATOMICRECV();
  5955. }
  5956. BOOL NtUserSetLogonNotifyWindow(
  5957. IN HWND hwnd)
  5958. {
  5959. BEGINRECV_HWND(BOOL, FALSE, hwnd);
  5960. retval = _SetLogonNotifyWindow(pwnd);
  5961. TRACE("NtUserSetLogonNotifyWindow");
  5962. ENDRECV_HWND();
  5963. }
  5964. BOOL NtUserSetSystemCursor(
  5965. IN HCURSOR hcur,
  5966. IN DWORD id)
  5967. {
  5968. PCURSOR pcur;
  5969. BEGINRECV(BOOL, FALSE);
  5970. ValidateHCURSOR(pcur, hcur);
  5971. retval = zzzSetSystemCursor(pcur, id);
  5972. TRACE("NtUserSetSystemCursor");
  5973. ENDRECV();
  5974. }
  5975. HCURSOR NtUserGetCursorFrameInfo( // private GetCursorFrameInfo (Obsolete? - IanJa)
  5976. IN HCURSOR hcur,
  5977. IN int iFrame,
  5978. OUT LPDWORD pjifRate,
  5979. OUT LPINT pccur)
  5980. {
  5981. PCURSOR pcur, pcurRet;
  5982. DWORD jifRate;
  5983. INT ccur;
  5984. BEGINRECV_SHARED(HCURSOR, NULL);
  5985. ValidateHCURSOR(pcur, hcur);
  5986. /*
  5987. * Probe arguments
  5988. */
  5989. try {
  5990. ProbeForWriteUlong(pjifRate);
  5991. ProbeForWriteLong(pccur);
  5992. } except (StubExceptionHandler(FALSE)) {
  5993. MSGERROR(0); // don't SetLastError for private API
  5994. }
  5995. pcurRet = _GetCursorFrameInfo(
  5996. pcur,
  5997. iFrame,
  5998. &jifRate,
  5999. &ccur);
  6000. if (pcurRet != NULL) {
  6001. retval = PtoH(pcurRet);
  6002. try {
  6003. *pjifRate = jifRate;
  6004. *pccur = ccur;
  6005. } except (StubExceptionHandler(FALSE)) {
  6006. MSGERROR(0); // don't SetLastError for private API
  6007. }
  6008. } else {
  6009. retval = NULL;
  6010. }
  6011. TRACE("NtUserGetCursorFrameInfo");
  6012. ENDRECV_SHARED();
  6013. }
  6014. BOOL NtUserSetCursorContents(
  6015. IN HCURSOR hCursor,
  6016. IN HCURSOR hCursorNew)
  6017. {
  6018. PCURSOR pCursor;
  6019. PCURSOR pCursorNew;
  6020. BEGINATOMICRECV(BOOL, FALSE);
  6021. ValidateHCURSOR(pCursor, hCursor);
  6022. ValidateHCURSOR(pCursorNew, hCursorNew);
  6023. retval = _SetCursorContents(pCursor, pCursorNew);
  6024. TRACE("NtUserSetCursorContents");
  6025. ENDATOMICRECV();
  6026. }
  6027. HCURSOR NtUserFindExistingCursorIcon( // Various Icon/Cursor APIs
  6028. IN PUNICODE_STRING pstrModName,
  6029. IN PUNICODE_STRING pstrResName,
  6030. IN PCURSORFIND pcfSearch)
  6031. {
  6032. ATOM atomModName;
  6033. UNICODE_STRING strModName;
  6034. UNICODE_STRING strResName;
  6035. PCURSOR pcurSrc;
  6036. CURSORFIND cfSearch;
  6037. BEGINRECV_SHARED(HCURSOR, NULL);
  6038. /*
  6039. * Probe arguments
  6040. */
  6041. try {
  6042. cfSearch = ProbeAndReadCursorFind(pcfSearch);
  6043. ValidateHCURSOROPT(pcurSrc, cfSearch.hcur);
  6044. strModName = ProbeAndReadUnicodeString(pstrModName);
  6045. ProbeForReadUnicodeStringBuffer(strModName);
  6046. strResName = ProbeAndReadUnicodeString(pstrResName);
  6047. ProbeForReadUnicodeStringBufferOrId(strResName);
  6048. } except (StubExceptionHandler(TRUE)) {
  6049. MSGERROR(0);
  6050. }
  6051. /*
  6052. * The ModName buffer is client-side, but UserFindAtom protects
  6053. * access.
  6054. */
  6055. atomModName = UserFindAtom(strModName.Buffer);
  6056. if (atomModName) {
  6057. /*
  6058. * The ResName buffer is client-side. FindExistincCursorIcon
  6059. * protects access.
  6060. */
  6061. retval = (HCURSOR)_FindExistingCursorIcon(atomModName,
  6062. &strResName,
  6063. pcurSrc,
  6064. &cfSearch);
  6065. retval = (HCURSOR)PtoH((PCURSOR)retval);
  6066. } else {
  6067. retval = 0;
  6068. }
  6069. TRACE("NtUserFindExistingCursorIcon");
  6070. ENDRECV_SHARED();
  6071. }
  6072. BOOL NtUserSetCursorIconData( // worker called by CreateIcon, CreateCursor etc.
  6073. IN HCURSOR hCursor,
  6074. IN PUNICODE_STRING pstrModName,
  6075. IN PUNICODE_STRING pstrResName,
  6076. IN PCURSORDATA pData)
  6077. {
  6078. UNICODE_STRING strModName;
  6079. UNICODE_STRING strResName;
  6080. PCURSOR pCursor;
  6081. CURSORDATA curData;
  6082. DWORD cbData;
  6083. BEGINATOMICRECV(BOOL, FALSE);
  6084. ValidateHCURSOR(pCursor, hCursor);
  6085. /*
  6086. * Probe arguments
  6087. */
  6088. try {
  6089. strModName = ProbeAndReadUnicodeString(pstrModName);
  6090. strResName = ProbeAndReadUnicodeString(pstrResName);
  6091. ProbeForReadUnicodeStringBuffer(strModName);
  6092. ProbeForReadUnicodeStringBufferOrId(strResName);
  6093. curData = ProbeAndReadCursorData(pData);
  6094. if (curData.CURSORF_flags & CURSORF_ACON) {
  6095. /*
  6096. * Avoid overflow here, or we might end up probing less.
  6097. * MCostea #199188
  6098. */
  6099. if (HIWORD(curData.cpcur) | HIWORD(curData.cicur)) {
  6100. MSGERROR(0);
  6101. }
  6102. /*
  6103. * The code assumes that the memory was allocated in one chunk
  6104. * as in CreateAniIcon(). To prevent evil apps, do this check.
  6105. */
  6106. if ((INT_PTR)curData.ajifRate != curData.cpcur * (INT_PTR) sizeof(HCURSOR) ||
  6107. (INT_PTR)curData.aicur != (INT_PTR)curData.ajifRate + curData.cicur * (INT_PTR) sizeof(JIF)) {
  6108. MSGERROR(0);
  6109. }
  6110. cbData = (curData.cpcur * sizeof(HCURSOR)) +
  6111. (curData.cicur * sizeof(JIF)) +
  6112. (curData.cicur * sizeof(DWORD));
  6113. } else {
  6114. cbData = 0;
  6115. }
  6116. ProbeForRead(curData.aspcur, cbData, sizeof(DWORD));
  6117. } except (StubExceptionHandler(FALSE)) {
  6118. /*
  6119. * Probed parameters are USER stack variables, not supplied by the
  6120. * application itself, so don't bother to SetLastError.
  6121. */
  6122. MSGERROR(0);
  6123. }
  6124. /*
  6125. * SetCursorIconData guards use of the buffer addresses with try clauses.
  6126. */
  6127. retval = _SetCursorIconData(pCursor,
  6128. &strModName,
  6129. &strResName,
  6130. &curData,
  6131. cbData);
  6132. TRACE("NtUserSetCursorIconData");
  6133. ENDATOMICRECV();
  6134. }
  6135. BOOL NtUserGetMenuItemRect( // API GetMenuItemRect
  6136. IN HWND hwnd,
  6137. IN HMENU hMenu,
  6138. IN UINT uItem,
  6139. OUT LPRECT lprcItem)
  6140. {
  6141. PMENU pmenu;
  6142. TL tlpMenu;
  6143. RECT rcItem;
  6144. BEGINRECV_HWNDLOCK_OPT(DWORD, 0, hwnd);
  6145. ValidateHMENU(pmenu, hMenu);
  6146. ThreadLockAlwaysWithPti(ptiCurrent, pmenu, &tlpMenu);
  6147. retval = xxxGetMenuItemRect(
  6148. pwnd,
  6149. pmenu,
  6150. uItem,
  6151. &rcItem);
  6152. /*
  6153. * Probe arguments
  6154. */
  6155. try {
  6156. ProbeAndWriteStructure(lprcItem, rcItem, RECT);
  6157. } except (StubExceptionHandler(TRUE)) {
  6158. MSGERRORCLEANUP(0);
  6159. }
  6160. CLEANUPRECV();
  6161. ThreadUnlock(&tlpMenu);
  6162. TRACE("NtUserGetMenuItemRect");
  6163. ENDRECV_HWNDLOCK_OPT();
  6164. }
  6165. int NtUserMenuItemFromPoint( // API MenuItemFromPoint
  6166. IN HWND hwnd,
  6167. IN HMENU hMenu,
  6168. IN POINT ptScreen)
  6169. {
  6170. PMENU pmenu;
  6171. TL tlpMenu;
  6172. BEGINRECV_HWNDLOCK_OPT(DWORD, -1, hwnd);
  6173. ValidateHMENU(pmenu, hMenu);
  6174. ThreadLockAlwaysWithPti(ptiCurrent, pmenu, &tlpMenu);
  6175. retval = xxxMenuItemFromPoint(
  6176. pwnd,
  6177. pmenu,
  6178. ptScreen);
  6179. ThreadUnlock(&tlpMenu);
  6180. TRACE("NtUserMenuItemFromPoint");
  6181. ENDRECV_HWNDLOCK_OPT();
  6182. }
  6183. BOOL NtUserGetCaretPos( // API GetCaretPos
  6184. OUT LPPOINT lpPoint)
  6185. {
  6186. PTHREADINFO pti;
  6187. PQ pq;
  6188. BEGINRECV_SHARED(BOOL, FALSE);
  6189. /*
  6190. * Probe arguments
  6191. */
  6192. try {
  6193. ProbeForWritePoint(lpPoint);
  6194. pti = PtiCurrentShared();
  6195. pq = pti->pq;
  6196. lpPoint->x = pq->caret.x;
  6197. lpPoint->y = pq->caret.y;
  6198. retval = TRUE;
  6199. } except (StubExceptionHandler(TRUE)) {
  6200. MSGERROR(0);
  6201. }
  6202. TRACE("NtUserGetCaretPos");
  6203. ENDRECV_SHARED();
  6204. }
  6205. BOOL NtUserDefSetText(
  6206. IN HWND hwnd,
  6207. IN PLARGE_STRING pstrText OPTIONAL)
  6208. {
  6209. LARGE_STRING strText;
  6210. BEGINRECV_HWND(DWORD, 0, hwnd);
  6211. /*
  6212. * Probe arguments
  6213. */
  6214. if (ARGUMENT_PRESENT(pstrText)) {
  6215. try {
  6216. strText = ProbeAndReadLargeString(pstrText);
  6217. #if defined(_X86_)
  6218. ProbeForRead(strText.Buffer, strText.Length, sizeof(BYTE));
  6219. #else
  6220. ProbeForRead(strText.Buffer, strText.Length,
  6221. strText.bAnsi ? sizeof(BYTE) : sizeof(WORD));
  6222. #endif
  6223. pstrText = &strText;
  6224. } except (StubExceptionHandler(TRUE)) {
  6225. MSGERROR(0); // WM_SETTEXT lParam
  6226. }
  6227. }
  6228. /*
  6229. * pstrText buffer is client side. DefSetText protects uses of the buffer.
  6230. */
  6231. retval = DefSetText(
  6232. pwnd,
  6233. pstrText);
  6234. TRACE("NtUserDefSetText");
  6235. ENDRECV_HWND();
  6236. }
  6237. NTSTATUS NtUserQueryInformationThread(
  6238. IN HANDLE hThread,
  6239. IN USERTHREADINFOCLASS ThreadInfoClass,
  6240. IN OUT PVOID ThreadInformation,
  6241. IN ULONG ThreadInformationLength,
  6242. IN OUT PULONG ReturnLength OPTIONAL)
  6243. {
  6244. ULONG uReturnLength;
  6245. TL tlBuffer;
  6246. PTHREADINFO ptiCurrent;
  6247. union {
  6248. USERTHREAD_SHUTDOWN_INFORMATION ThreadShutdownInformation;
  6249. DWORD dwThreadInfo;
  6250. WCHAR szThreadTaskName[32];
  6251. USERTHREAD_WOW_INFORMATION UserThreadWowInformation;
  6252. } ThreadInformationUnion;
  6253. PVOID pThreadInformation = NULL;
  6254. BEGINRECVCSRSS(NTSTATUS, STATUS_UNSUCCESSFUL);
  6255. ptiCurrent = PtiCurrent();
  6256. /*
  6257. * Probe all arguments. Try block necessary even with CSRSS as
  6258. * the calling process because it can incurr an in-page exception.
  6259. */
  6260. try {
  6261. if (ARGUMENT_PRESENT(ThreadInformation)) {
  6262. ProbeForRead(ThreadInformation, ThreadInformationLength, sizeof(WCHAR));
  6263. if (ThreadInformationLength > sizeof(ThreadInformationUnion)) {
  6264. pThreadInformation = UserAllocPoolWithQuota(ThreadInformationLength, TAG_SYSTEM);
  6265. if (pThreadInformation) {
  6266. ThreadLockPool(ptiCurrent, pThreadInformation, &tlBuffer);
  6267. } else {
  6268. ExRaiseStatus(STATUS_NO_MEMORY);
  6269. }
  6270. } else {
  6271. pThreadInformation = &ThreadInformationUnion;
  6272. }
  6273. RtlCopyMemory(pThreadInformation, ThreadInformation, ThreadInformationLength);
  6274. } else {
  6275. pThreadInformation = NULL;
  6276. }
  6277. } except (StubExceptionHandler(FALSE)) {
  6278. MSGERRORCLEANUP(0);
  6279. }
  6280. retval = xxxQueryInformationThread(
  6281. hThread,
  6282. ThreadInfoClass,
  6283. pThreadInformation,
  6284. ThreadInformationLength,
  6285. (ARGUMENT_PRESENT(ReturnLength))? &uReturnLength: NULL);
  6286. try {
  6287. if (ARGUMENT_PRESENT(ThreadInformation)) {
  6288. ProbeForWrite(ThreadInformation, ThreadInformationLength, sizeof(WCHAR));
  6289. RtlCopyMemory(ThreadInformation, pThreadInformation, ThreadInformationLength);
  6290. }
  6291. if (ARGUMENT_PRESENT(ReturnLength)) {
  6292. ProbeForWrite(ReturnLength, sizeof(ULONG), sizeof(ULONG));
  6293. RtlCopyMemory(ReturnLength, &uReturnLength, sizeof(ULONG));
  6294. }
  6295. } except (StubExceptionHandler(FALSE)) {
  6296. MSGERRORCLEANUP(0);
  6297. }
  6298. CLEANUPRECV();
  6299. if ((pThreadInformation != &ThreadInformationUnion) && pThreadInformation) {
  6300. ASSERT(ThreadInformationLength > sizeof(ThreadInformationUnion));
  6301. ThreadUnlockAndFreePool(ptiCurrent, &tlBuffer);
  6302. }
  6303. TRACE("NtUserQueryInformationThread");
  6304. ENDRECVCSRSS();
  6305. }
  6306. NTSTATUS NtUserSetInformationThread(
  6307. IN HANDLE hThread,
  6308. IN USERTHREADINFOCLASS ThreadInfoClass,
  6309. IN PVOID ThreadInformation,
  6310. IN ULONG ThreadInformationLength)
  6311. {
  6312. union {
  6313. USERTHREAD_FLAGS UserThread_Flags;
  6314. DWORD dwThreadInfo;
  6315. NTSTATUS Status;
  6316. USERTHREAD_USEDESKTOPINFO UserThreadDesktopInfo;
  6317. HANDLE handle;
  6318. } ThreadInformationUnion;
  6319. PVOID pThreadInformation = &ThreadInformationUnion;
  6320. BEGINRECVCSRSS(NTSTATUS, STATUS_UNSUCCESSFUL);
  6321. if (ThreadInformationLength > sizeof(ThreadInformationUnion)) {
  6322. FRE_RIPMSG2(
  6323. RIP_ERROR,
  6324. "ThreadInformationLength: %x is greater than union size: %x.",
  6325. ThreadInformationLength,
  6326. sizeof(ThreadInformationUnion));
  6327. }
  6328. /*
  6329. * Probe read arguments. Try block necessary even with CSRSS as
  6330. * the calling process because it can incurr an in-page exception.
  6331. */
  6332. try {
  6333. if (ARGUMENT_PRESENT(ThreadInformation)) {
  6334. ProbeForRead(ThreadInformation, ThreadInformationLength, sizeof(DWORD));
  6335. RtlCopyMemory(pThreadInformation, ThreadInformation, ThreadInformationLength);
  6336. } else {
  6337. pThreadInformation = NULL;
  6338. }
  6339. } except (StubExceptionHandler(FALSE)) {
  6340. MSGERROR(0);
  6341. }
  6342. retval = xxxSetInformationThread(
  6343. hThread,
  6344. ThreadInfoClass,
  6345. pThreadInformation,
  6346. ThreadInformationLength);
  6347. try {
  6348. if (ARGUMENT_PRESENT(ThreadInformation)) {
  6349. ProbeForWrite(ThreadInformation, ThreadInformationLength, sizeof(DWORD));
  6350. RtlCopyMemory(ThreadInformation, pThreadInformation, ThreadInformationLength);
  6351. }
  6352. } except (StubExceptionHandler(FALSE)) {
  6353. MSGERROR(0);
  6354. }
  6355. TRACE("NtUserSetInformationThread");
  6356. ENDRECVCSRSS();
  6357. }
  6358. NTSTATUS NtUserSetInformationProcess(
  6359. IN HANDLE hProcess,
  6360. IN USERPROCESSINFOCLASS ProcessInfoClass,
  6361. IN PVOID pProcessInformation,
  6362. IN ULONG ProcessInformationLength)
  6363. {
  6364. USERTHREAD_FLAGS ProcessInformation;
  6365. BEGINRECVCSRSS(NTSTATUS, STATUS_UNSUCCESSFUL);
  6366. /*
  6367. * Probe read arguments. Try block necessary even with CSRSS as
  6368. * the calling process because it can incurr an in-page exception.
  6369. */
  6370. try {
  6371. if (ARGUMENT_PRESENT(pProcessInformation)) {
  6372. ProbeForRead(pProcessInformation, ProcessInformationLength, sizeof(DWORD));
  6373. RtlCopyMemory(&ProcessInformation, pProcessInformation, ProcessInformationLength);
  6374. }
  6375. } except (StubExceptionHandler(FALSE)) {
  6376. MSGERROR(0);
  6377. }
  6378. retval = SetInformationProcess(
  6379. hProcess,
  6380. ProcessInfoClass,
  6381. ARGUMENT_PRESENT(pProcessInformation) ? &ProcessInformation : NULL,
  6382. ProcessInformationLength);
  6383. TRACE("NtUserSetInformationProcess");
  6384. ENDRECVCSRSS();
  6385. }
  6386. BOOL NtUserNotifyProcessCreate(
  6387. IN DWORD dwProcessId,
  6388. IN DWORD dwParentThreadId,
  6389. IN ULONG_PTR dwData,
  6390. IN DWORD dwFlags)
  6391. {
  6392. extern BOOL xxxUserNotifyProcessCreate(
  6393. DWORD idProcess,
  6394. DWORD idParentThread,
  6395. ULONG_PTR dwData,
  6396. DWORD dwFlags);
  6397. BEGINRECVCSRSS(BOOL, FALSE);
  6398. retval = xxxUserNotifyProcessCreate(
  6399. dwProcessId,
  6400. dwParentThreadId,
  6401. dwData, // Static value not a ptr. No probing needed.
  6402. dwFlags);
  6403. TRACE("NtUserNotifyProcessCreate");
  6404. ENDRECVCSRSS();
  6405. }
  6406. NTSTATUS NtUserSoundSentry(VOID)
  6407. {
  6408. BEGINRECV(NTSTATUS, STATUS_UNSUCCESSFUL);
  6409. retval = (_UserSoundSentryWorker() ?
  6410. STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
  6411. TRACE("NtUserSoundSentry");
  6412. ENDRECV();
  6413. }
  6414. NTSTATUS NtUserTestForInteractiveUser( // private _UserTestTokenForInteractive
  6415. IN PLUID pluidCaller)
  6416. {
  6417. LUID luidCaller;
  6418. BEGINRECV_SHARED(NTSTATUS, STATUS_UNSUCCESSFUL);
  6419. /*
  6420. * Probe arguments
  6421. */
  6422. try {
  6423. luidCaller = ProbeAndReadStructure(pluidCaller, LUID);
  6424. } except (StubExceptionHandler(FALSE)) {
  6425. MSGERROR(0);
  6426. }
  6427. retval = TestForInteractiveUser(&luidCaller);
  6428. TRACE("NtUserTestForInteractiveUser");
  6429. ENDRECV_SHARED();
  6430. }
  6431. BOOL NtUserSetConsoleReserveKeys(
  6432. IN HWND hwnd,
  6433. IN DWORD fsReserveKeys)
  6434. {
  6435. BOOL _SetConsoleReserveKeys(PWND, DWORD);
  6436. BEGINRECV_HWND(BOOL, FALSE, hwnd);
  6437. retval = _SetConsoleReserveKeys(pwnd, fsReserveKeys);
  6438. TRACE("NtUserSetConsoleReserveKeys");
  6439. ENDRECV_HWND();
  6440. }
  6441. VOID NtUserModifyUserStartupInfoFlags(
  6442. IN DWORD dwMask,
  6443. IN DWORD dwFlags)
  6444. {
  6445. BEGINRECV_VOID();
  6446. PpiCurrent()->usi.dwFlags = (PpiCurrent()->usi.dwFlags & ~dwMask) | (dwFlags & dwMask);
  6447. TRACEVOID("NtUserModifyUserStartupInfoFlags");
  6448. ENDRECV_VOID();
  6449. }
  6450. BOOL NtUserSetWindowFNID(
  6451. IN HWND hwnd,
  6452. IN WORD fnid)
  6453. {
  6454. BEGINRECV_HWND(BOOL, FALSE, hwnd);
  6455. /*
  6456. * Don't let apps mess with windows on other processes.
  6457. */
  6458. if (GETPTI(pwnd)->ppi != PpiCurrent()) {
  6459. MSGERROR(0);
  6460. }
  6461. /*
  6462. * Make sure the fnid is in the correct range.
  6463. */
  6464. if (fnid != FNID_CLEANEDUP_BIT) {
  6465. if ((fnid < FNID_CONTROLSTART) || (fnid > FNID_CONTROLEND) || (GETFNID(pwnd) != 0)) {
  6466. MSGERROR(0);
  6467. }
  6468. }
  6469. /*
  6470. * Remember what window class this window belongs to. Can't use
  6471. * the real class because any app can call CallWindowProc()
  6472. * directly no matter what the class is!
  6473. */
  6474. pwnd->fnid |= fnid;
  6475. retval = TRUE;
  6476. TRACE("NtUserSetWindowFNID");
  6477. ENDRECV_HWND();
  6478. }
  6479. #define AWS_MASK (BS_TYPEMASK | BS_RIGHT | BS_RIGHTBUTTON | \
  6480. WS_HSCROLL | WS_VSCROLL | SS_TYPEMASK)
  6481. VOID NtUserAlterWindowStyle(
  6482. IN HWND hwnd,
  6483. IN DWORD mask,
  6484. IN DWORD flags)
  6485. {
  6486. BEGINRECV_HWND_VOID(hwnd);
  6487. if (GETPTI(pwnd)->ppi == PpiCurrent()) {
  6488. if (mask & ~AWS_MASK) {
  6489. RIPMSGF1(RIP_WARNING, "Bad mask 0x%x", mask);
  6490. }
  6491. mask &= AWS_MASK;
  6492. pwnd->style = (pwnd->style & (~mask)) | (flags & mask);
  6493. } else {
  6494. RIPMSGF1(RIP_WARNING, "Current ppi doesn't own pwnd 0x%p", pwnd);
  6495. }
  6496. TRACEVOID("NtUserAlterWindowStyle");
  6497. ENDRECV_HWND_VOID();
  6498. }
  6499. VOID NtUserSetThreadState(
  6500. IN DWORD dwFlags,
  6501. IN DWORD dwMask)
  6502. {
  6503. PTHREADINFO ptiCurrent;
  6504. DWORD dwOldFlags;
  6505. if (dwFlags & ~(QF_DIALOGACTIVE)) {
  6506. return;
  6507. }
  6508. BEGINRECV_VOID();
  6509. ptiCurrent = PtiCurrent();
  6510. dwOldFlags = ptiCurrent->pq->QF_flags;
  6511. ptiCurrent->pq->QF_flags ^= ((dwOldFlags ^ dwFlags) & dwMask);
  6512. TRACEVOID("NtUserSetThreadState");
  6513. ENDRECV_VOID();
  6514. }
  6515. ULONG_PTR NtUserGetThreadState(
  6516. IN USERTHREADSTATECLASS ThreadState)
  6517. {
  6518. PTHREADINFO ptiCurrent = PtiCurrentShared();
  6519. BEGINRECV_SHARED(ULONG_PTR, 0);
  6520. switch (ThreadState) {
  6521. case UserThreadStateFocusWindow:
  6522. retval = (ULONG_PTR)HW(ptiCurrent->pq->spwndFocus);
  6523. break;
  6524. case UserThreadStateActiveWindow:
  6525. retval = (ULONG_PTR)HW(ptiCurrent->pq->spwndActive);
  6526. break;
  6527. case UserThreadStateCaptureWindow:
  6528. retval = (ULONG_PTR)HW(ptiCurrent->pq->spwndCapture);
  6529. break;
  6530. case UserThreadStateDefaultImeWindow:
  6531. retval = (ULONG_PTR)HW(ptiCurrent->spwndDefaultIme);
  6532. break;
  6533. case UserThreadStateDefaultInputContext:
  6534. retval = (ULONG_PTR)PtoH(ptiCurrent->spDefaultImc);
  6535. break;
  6536. case UserThreadStateImeCompatFlags:
  6537. UserAssert(ptiCurrent->ppi != NULL);
  6538. retval = (DWORD)(ptiCurrent->ppi->dwImeCompatFlags);
  6539. break;
  6540. case UserThreadStatePreviousKeyboardLayout:
  6541. retval = (ULONG_PTR)(ptiCurrent->hklPrev);
  6542. break;
  6543. #ifdef OBSOLETE
  6544. case UserThreadStateIsWinlogonThread:
  6545. /*
  6546. * This is no longer supported, for the securty breach bug.
  6547. * The enum value is kept for the Wow16 compatibility.
  6548. */
  6549. #endif
  6550. case UserThreadStateNeedsSecurity:
  6551. /*
  6552. * Client IMM checks if the process is winlogon to prevent switching
  6553. * dictionaries, etc. Also, we need to check the secure desktop, for
  6554. * some accessibility applications run on the secure desktop.
  6555. */
  6556. retval = (PsGetCurrentProcessId() == gpidLogon) || (ptiCurrent->rpdesk == grpdeskLogon);
  6557. if (ptiCurrent->rpdesk == grpdeskLogon) {
  6558. RIPMSG2(RIP_WARNING,
  6559. "Thread 0x%p is running on the secure desktop %p",
  6560. ptiCurrent,
  6561. grpdeskLogon);
  6562. }
  6563. break;
  6564. case UserThreadStateIsConImeThread:
  6565. UserAssert(ptiCurrent->rpdesk != NULL);
  6566. retval = (DWORD)(PtiFromThreadId(ptiCurrent->rpdesk->dwConsoleIMEThreadId) == ptiCurrent);
  6567. break;
  6568. case UserThreadStateInputState:
  6569. retval = (DWORD)_GetInputState();
  6570. break;
  6571. case UserThreadStateCursor:
  6572. retval = (ULONG_PTR)PtoH(ptiCurrent->pq->spcurCurrent);
  6573. break;
  6574. case UserThreadStateChangeBits:
  6575. retval = ptiCurrent->pcti->fsChangeBits;
  6576. break;
  6577. case UserThreadStatePeekMessage:
  6578. /*
  6579. * Update the last read time so that hung app painting won't occur.
  6580. */
  6581. SET_TIME_LAST_READ(ptiCurrent);
  6582. retval = (DWORD)FALSE;
  6583. break;
  6584. case UserThreadStateExtraInfo:
  6585. retval = ptiCurrent->pq->ExtraInfo;
  6586. break;
  6587. case UserThreadStateInSendMessage:
  6588. if (ptiCurrent->psmsCurrent != NULL) {
  6589. if (ptiCurrent->psmsCurrent->ptiSender != NULL) {
  6590. retval = ISMEX_SEND;
  6591. } else if (ptiCurrent->psmsCurrent->flags & (SMF_CB_REQUEST | SMF_CB_REPLY)) {
  6592. retval = ISMEX_CALLBACK;
  6593. } else {
  6594. retval = ISMEX_NOTIFY;
  6595. }
  6596. if (ptiCurrent->psmsCurrent->flags & SMF_REPLY) {
  6597. retval |= ISMEX_REPLIED;
  6598. }
  6599. } else {
  6600. retval = ISMEX_NOSEND;
  6601. }
  6602. break;
  6603. case UserThreadStateMessageTime:
  6604. retval = ptiCurrent->timeLast;
  6605. break;
  6606. case UserThreadStateIsForeground:
  6607. retval = (ptiCurrent->pq == gpqForeground);
  6608. break;
  6609. case UserThreadConnect:
  6610. retval = TRUE;
  6611. break;
  6612. default:
  6613. RIPMSG1(RIP_WARNING, "NtUserGetThreadState invalid ThreadState:%#x", ThreadState);
  6614. MSGERROR(0);
  6615. }
  6616. ENDRECV_SHARED();
  6617. }
  6618. BOOL NtUserValidateHandleSecure(
  6619. IN HANDLE h)
  6620. {
  6621. BEGINRECV(BOOL, FALSE);
  6622. retval = ValidateHandleSecure(h);
  6623. TRACE("NtUserValidateHandleSecure");
  6624. ENDRECV();
  6625. }
  6626. BOOL NtUserUserHandleGrantAccess( // API UserHandleGrantAccess
  6627. IN HANDLE hUserHandle,
  6628. IN HANDLE hJob,
  6629. IN BOOL bGrant)
  6630. {
  6631. NTSTATUS Status;
  6632. PEJOB Job;
  6633. PW32JOB pW32Job;
  6634. DWORD dw;
  6635. PHE phe;
  6636. PULONG_PTR pgh;
  6637. BOOL retval;
  6638. BOOL errret = FALSE;
  6639. Status = ObReferenceObjectByHandle(
  6640. hJob,
  6641. JOB_OBJECT_SET_ATTRIBUTES,
  6642. *PsJobType,
  6643. UserMode,
  6644. (PVOID*)&Job,
  6645. NULL);
  6646. if (!NT_SUCCESS(Status)) {
  6647. RIPERR1(ERROR_INVALID_PARAMETER,
  6648. RIP_WARNING,
  6649. "UserHandleGrantAccess: Invalid job handle 0x%p",
  6650. hJob);
  6651. return FALSE;
  6652. }
  6653. /*
  6654. * Acquire the job's lock and enter the user critical section.
  6655. */
  6656. KeEnterCriticalRegion();
  6657. ExAcquireResourceExclusiveLite(PsGetJobLock(Job), TRUE);
  6658. EnterCrit();
  6659. /*
  6660. * Bail out if it doesn't have UI restrictions.
  6661. */
  6662. if (PsGetJobUIRestrictionsClass(Job) == 0) {
  6663. RIPERR1(ERROR_INVALID_PARAMETER,
  6664. RIP_WARNING,
  6665. "UserHandleGrantAccess: job 0x%p doesn't have UI restrictions",
  6666. hJob);
  6667. MSGERRORCLEANUP(0);
  6668. }
  6669. /*
  6670. * see if we have a W32JOB structure created for this job
  6671. */
  6672. pW32Job = gpJobsList;
  6673. while (pW32Job) {
  6674. if (pW32Job->Job == Job) {
  6675. break;
  6676. }
  6677. pW32Job = pW32Job->pNext;
  6678. }
  6679. UserAssert(pW32Job != NULL);
  6680. try {
  6681. /*
  6682. * Now, validate the 'unsecure' handle.
  6683. */
  6684. if (HMValidateHandle(hUserHandle, TYPE_GENERIC) == NULL) {
  6685. RIPERR1(ERROR_INVALID_PARAMETER,
  6686. RIP_WARNING,
  6687. "UserHandleGrantAccess: invalid handle 0x%p",
  6688. hUserHandle);
  6689. MSGERRORCLEANUP(0);
  6690. }
  6691. dw = HMIndexFromHandle(hUserHandle);
  6692. phe = &gSharedInfo.aheList[dw];
  6693. phe->bFlags |= HANDLEF_GRANTED;
  6694. pgh = pW32Job->pgh;
  6695. if (bGrant) {
  6696. /*
  6697. * Add the handle to the process' list
  6698. */
  6699. if (pW32Job->ughCrt == pW32Job->ughMax) {
  6700. if (pW32Job->ughCrt == 0) {
  6701. pgh = UserAllocPool(GH_SIZE * sizeof(*pgh), TAG_GRANTEDHANDLES);
  6702. } else {
  6703. /*
  6704. * we need to grow the array
  6705. */
  6706. DWORD uBytes = (pW32Job->ughMax) * sizeof(*pgh);
  6707. pgh = UserReAllocPool(pgh,
  6708. uBytes,
  6709. uBytes + GH_SIZE * sizeof(*pgh),
  6710. TAG_GRANTEDHANDLES);
  6711. }
  6712. if (pgh == NULL) {
  6713. MSGERRORCLEANUP(ERROR_NOT_ENOUGH_MEMORY);
  6714. }
  6715. pW32Job->pgh = pgh;
  6716. pW32Job->ughMax += GH_SIZE;
  6717. }
  6718. UserAssert(pW32Job->ughCrt < pW32Job->ughMax);
  6719. /*
  6720. * see if the handle is not already granted to this process
  6721. */
  6722. for (dw = 0; dw < pW32Job->ughCrt; dw++) {
  6723. if (*(pgh + dw) == (ULONG_PTR)hUserHandle) {
  6724. break;
  6725. }
  6726. }
  6727. if (dw >= pW32Job->ughCrt) {
  6728. /*
  6729. * add the handle to the granted handles table
  6730. */
  6731. *(pgh + pW32Job->ughCrt) = (ULONG_PTR)hUserHandle;
  6732. (pW32Job->ughCrt)++;
  6733. }
  6734. } else {
  6735. /*
  6736. * Remove the handle from the granted list
  6737. */
  6738. /*
  6739. * search for the handle in the array.
  6740. */
  6741. for (dw = 0; dw < pW32Job->ughCrt; dw++) {
  6742. if (*(pgh + dw) == (ULONG_PTR)hUserHandle) {
  6743. /*
  6744. * found the handle granted to this process
  6745. */
  6746. RtlMoveMemory(pgh + dw,
  6747. pgh + dw + 1,
  6748. (pW32Job->ughCrt - dw - 1) * sizeof(*pgh));
  6749. (pW32Job->ughCrt)--;
  6750. break;
  6751. }
  6752. }
  6753. #if DBG
  6754. if (dw >= pW32Job->ughCrt) {
  6755. RIPERR1(ERROR_INVALID_HANDLE, RIP_WARNING,
  6756. "UserHandleGrantAccess(FALSE): handle not found %#p",
  6757. hUserHandle);
  6758. }
  6759. #endif // DBG
  6760. }
  6761. retval = TRUE;
  6762. } except (StubExceptionHandler(TRUE)) {
  6763. MSGERRORCLEANUP(0);
  6764. }
  6765. CLEANUPRECV();
  6766. LeaveCrit();
  6767. ExReleaseResourceLite(PsGetJobLock(Job));
  6768. KeLeaveCriticalRegion();
  6769. ObDereferenceObject(Job);
  6770. TRACE("NtUserUserHandleGrantAccess");
  6771. return retval;
  6772. }
  6773. HWND NtUserCreateWindowEx(
  6774. IN DWORD dwExStyle,
  6775. IN PLARGE_STRING pstrNVClassName,
  6776. IN PLARGE_STRING pstrClassName,
  6777. IN PLARGE_STRING pstrWindowName OPTIONAL,
  6778. IN DWORD dwStyle,
  6779. IN int x,
  6780. IN int y,
  6781. IN int nWidth,
  6782. IN int nHeight,
  6783. IN HWND hwndParent,
  6784. IN HMENU hmenu,
  6785. IN HANDLE hModule,
  6786. IN LPVOID pParam,
  6787. IN DWORD dwFlags,
  6788. IN PACTIVATION_CONTEXT pActCtx)
  6789. {
  6790. LARGE_STRING strNVClassName;
  6791. LARGE_STRING strClassName;
  6792. LARGE_STRING strWindowName;
  6793. PWND pwndParent;
  6794. PMENU pmenu;
  6795. TL tlpwndParent;
  6796. TL tlpMenu;
  6797. BOOL fLockMenu = FALSE;
  6798. PTHREADINFO ptiCurrent;
  6799. BEGINRECV(HWND, NULL);
  6800. if (hwndParent != HWND_MESSAGE) {
  6801. ValidateHWNDOPT(pwndParent, hwndParent);
  6802. } else {
  6803. pwndParent = _GetMessageWindow();
  6804. }
  6805. /*
  6806. * Win3.1 only checks for WS_CHILD before treating pmenu as an id. This
  6807. * is a bug, because throughout the code, the real check is TestwndChild(),
  6808. * which checks (style & (WS_CHILD | WS_POPUP)) == WS_CHILD. This is
  6809. * because old style "iconic popup" is WS_CHILD | WS_POPUP. So... if on
  6810. * win3.1 an app used ws_iconicpopup, menu validation would not occur
  6811. * (could crash if hmenu != NULL). On Win32, check for the real thing -
  6812. * but allow NULL!
  6813. */
  6814. ptiCurrent = PtiCurrent();
  6815. if (((dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) &&
  6816. (hmenu != NULL)) {
  6817. ValidateHMENU(pmenu, hmenu);
  6818. ThreadLockAlwaysWithPti(ptiCurrent, pmenu, &tlpMenu);
  6819. fLockMenu = TRUE;
  6820. } else {
  6821. pmenu = (PMENU)hmenu;
  6822. }
  6823. /*
  6824. * Mask out the new 5.0 extended style bits for apps
  6825. * that would try to use them and we'll fail in xxxCreateWindowEx
  6826. */
  6827. if (GetAppCompatFlags2(VER40) & GACF2_NO50EXSTYLEBITSCW) {
  6828. #if DBG
  6829. if (dwExStyle & ~(WS_EX_VALID40 | WS_EX_INTERNAL)) {
  6830. RIPMSG0(RIP_WARNING, "CreateWindowEx: appcompat removed 5.0 EX bits");
  6831. }
  6832. #endif
  6833. dwExStyle &= (WS_EX_VALID40 | WS_EX_INTERNAL);
  6834. }
  6835. if ((dwExStyle & (WS_EX_ALLVALID | WS_EX_INTERNAL)) != dwExStyle) {
  6836. RIPMSG0(RIP_WARNING, "CreateWindowEx: enforced not using private bits");
  6837. /*
  6838. * NOTE: Because WS_EX_ANSICREATOR is a reused bit, we actually need to
  6839. * check for valid | internal instead of turning off the private bits.
  6840. *
  6841. * It is very important for us to do this because we need to ensure that
  6842. * certain bits are not set, such as WS_EXP_COMPOSITING or
  6843. * WS_EXP_REDIRECTED because we can fault if this bits were set without
  6844. * properly setting up their accompanying data.
  6845. */
  6846. dwExStyle &= WS_EX_ALLVALID | WS_EX_INTERNAL;
  6847. }
  6848. /*
  6849. * Probe arguments
  6850. */
  6851. try {
  6852. #if defined(_X86_)
  6853. if (IS_PTR(pstrNVClassName)) {
  6854. strNVClassName = ProbeAndReadLargeString(pstrNVClassName);
  6855. ProbeForRead(strNVClassName.Buffer, strNVClassName.Length,
  6856. sizeof(BYTE));
  6857. pstrNVClassName = &strNVClassName;
  6858. }
  6859. if (IS_PTR(pstrClassName)) {
  6860. strClassName = ProbeAndReadLargeString(pstrClassName);
  6861. ProbeForRead(strClassName.Buffer, strClassName.Length,
  6862. sizeof(BYTE));
  6863. pstrClassName = &strClassName;
  6864. }
  6865. if (ARGUMENT_PRESENT(pstrWindowName)) {
  6866. strWindowName = ProbeAndReadLargeString(pstrWindowName);
  6867. ProbeForRead(strWindowName.Buffer, strWindowName.Length,
  6868. sizeof(BYTE));
  6869. pstrWindowName = &strWindowName;
  6870. }
  6871. #else
  6872. if (IS_PTR(pstrNVClassName)) {
  6873. strNVClassName = ProbeAndReadLargeString(pstrNVClassName);
  6874. ProbeForRead(strNVClassName.Buffer, strNVClassName.Length,
  6875. sizeof(WORD));
  6876. pstrNVClassName = &strNVClassName;
  6877. }
  6878. if (IS_PTR(pstrClassName)) {
  6879. strClassName = ProbeAndReadLargeString(pstrClassName);
  6880. ProbeForRead(strClassName.Buffer, strClassName.Length,
  6881. sizeof(WORD));
  6882. pstrClassName = &strClassName;
  6883. }
  6884. if (ARGUMENT_PRESENT(pstrWindowName)) {
  6885. strWindowName = ProbeAndReadLargeString(pstrWindowName);
  6886. ProbeForRead(strWindowName.Buffer, strWindowName.Length,
  6887. (strWindowName.bAnsi ? sizeof(BYTE) : sizeof(WORD)));
  6888. pstrWindowName = &strWindowName;
  6889. }
  6890. #endif
  6891. } except (StubExceptionHandler(TRUE)) {
  6892. MSGERRORCLEANUP(0);
  6893. }
  6894. ThreadLockWithPti(ptiCurrent, pwndParent, &tlpwndParent);
  6895. /*
  6896. * The buffers for ClassName and WindowName are still in client space.
  6897. */
  6898. retval = (HWND)xxxCreateWindowEx(
  6899. dwExStyle,
  6900. pstrNVClassName,
  6901. pstrClassName,
  6902. pstrWindowName,
  6903. dwStyle,
  6904. x,
  6905. y,
  6906. nWidth,
  6907. nHeight,
  6908. pwndParent,
  6909. pmenu,
  6910. hModule,
  6911. pParam,
  6912. dwFlags,
  6913. pActCtx);
  6914. retval = PtoH((PVOID)retval);
  6915. ThreadUnlock(&tlpwndParent);
  6916. CLEANUPRECV();
  6917. if (fLockMenu)
  6918. ThreadUnlock(&tlpMenu);
  6919. TRACE("NtUserCreateWindowEx");
  6920. ENDRECV();
  6921. }
  6922. NTSTATUS NtUserBuildHwndList( // worker for EnumWindows, EnumThreadWindows etc.
  6923. IN HDESK hdesk,
  6924. IN HWND hwndNext,
  6925. IN BOOL fEnumChildren,
  6926. IN DWORD idThread,
  6927. IN UINT cHwndMax,
  6928. OUT HWND *phwndFirst,
  6929. OUT PUINT pcHwndNeeded)
  6930. {
  6931. PWND pwndNext;
  6932. PDESKTOP pdesk;
  6933. PBWL pbwl;
  6934. PTHREADINFO pti;
  6935. UINT cHwndNeeded;
  6936. UINT wFlags = BWL_ENUMLIST;
  6937. WIN32_OPENMETHOD_PARAMETERS OpenParams;
  6938. BEGINATOMICRECV(NTSTATUS, STATUS_INVALID_HANDLE);
  6939. if (IS_IME_ENABLED()) {
  6940. // special treatment of IME Window
  6941. wFlags |= BWL_ENUMIMELAST;
  6942. }
  6943. /*
  6944. * Validate prior to referencing the desktop
  6945. */
  6946. ValidateHWNDOPT(pwndNext, hwndNext);
  6947. if (idThread) {
  6948. pti = PtiFromThreadId(idThread);
  6949. if (pti == NULL || pti->rpdesk == NULL) {
  6950. MSGERROR(ERROR_INVALID_PARAMETER);
  6951. }
  6952. pwndNext = pti->rpdesk->pDeskInfo->spwnd->spwndChild;
  6953. } else {
  6954. pti = NULL;
  6955. }
  6956. if (hdesk) {
  6957. retval = ValidateHdesk(hdesk, UserMode, DESKTOP_READOBJECTS, &pdesk);
  6958. if (!NT_SUCCESS(retval)) {
  6959. MSGERROR(ERROR_INVALID_HANDLE);
  6960. }
  6961. OpenParams.GrantedAccess = 0;
  6962. OpenParams.HandleCount = 0;
  6963. OpenParams.Object = pdesk;
  6964. OpenParams.OpenReason = ObOpenHandle;
  6965. OpenParams.Process = PsGetCurrentProcess();
  6966. retval = MapDesktop(&OpenParams);
  6967. if (!NT_SUCCESS(retval)) {
  6968. errret = retval;
  6969. MSGERROR(ERROR_INVALID_HANDLE);
  6970. }
  6971. pwndNext = pdesk->pDeskInfo->spwnd->spwndChild;
  6972. } else {
  6973. pdesk = NULL;
  6974. }
  6975. if (pwndNext == NULL) {
  6976. /*
  6977. * Windows NT Bug #262004.
  6978. * If we have a valid desk (just no windows on it), then we need to
  6979. * fall through. Otherwise, we'll just grab the current desktop and
  6980. * enum its windows!
  6981. */
  6982. if (pdesk == NULL) {
  6983. if (pti != NULL) {
  6984. pwndNext = pti->rpdesk->pDeskInfo->spwnd->spwndChild;
  6985. } else {
  6986. pwndNext = _GetDesktopWindow()->spwndChild;
  6987. }
  6988. }
  6989. } else {
  6990. if (fEnumChildren) {
  6991. wFlags |= BWL_ENUMCHILDREN;
  6992. pwndNext = pwndNext->spwndChild;
  6993. }
  6994. }
  6995. if ((pbwl = BuildHwndList(pwndNext, wFlags, pti)) == NULL) {
  6996. MSGERRORCLEANUP(ERROR_NOT_ENOUGH_MEMORY);
  6997. }
  6998. cHwndNeeded = (UINT)(pbwl->phwndNext - pbwl->rghwnd) + 1;
  6999. /*
  7000. * Probe arguments
  7001. */
  7002. try {
  7003. ProbeForWriteBuffer(phwndFirst, cHwndMax, sizeof(DWORD));
  7004. ProbeForWriteUlong(pcHwndNeeded);
  7005. /*
  7006. * If we have enough space, copy out list of hwnds to user mode buffer.
  7007. */
  7008. if (cHwndNeeded <= cHwndMax) {
  7009. RtlCopyMemory(phwndFirst, pbwl->rghwnd, cHwndNeeded * sizeof(HWND));
  7010. retval = STATUS_SUCCESS;
  7011. } else {
  7012. retval = STATUS_BUFFER_TOO_SMALL;
  7013. }
  7014. *pcHwndNeeded = cHwndNeeded;
  7015. } except (StubExceptionHandler(TRUE)) {
  7016. MSGERRORCLEANUP(0); // phwndFirst/pcHwndNeeded are USER's, not app's
  7017. }
  7018. CLEANUPRECV();
  7019. if (pbwl != NULL) {
  7020. FreeHwndList(pbwl);
  7021. }
  7022. if (pdesk != NULL) {
  7023. LogDesktop(pdesk, LD_DEREF_VALIDATE_HDESK4, FALSE, (ULONG_PTR)PtiCurrent());
  7024. ObDereferenceObject(pdesk);
  7025. }
  7026. TRACE("NtUserBuildHwndList");
  7027. ENDATOMICRECV();
  7028. }
  7029. NTSTATUS NtUserBuildPropList( // worker for EnumProps etc.
  7030. IN HWND hwnd,
  7031. IN UINT cPropMax,
  7032. OUT PPROPSET pPropSet,
  7033. OUT PUINT pcPropNeeded)
  7034. {
  7035. BEGINRECV_HWNDLOCK(NTSTATUS, STATUS_INVALID_HANDLE, hwnd);
  7036. if (cPropMax == 0) {
  7037. MSGERROR(0);
  7038. }
  7039. /*
  7040. * Probe arguments
  7041. */
  7042. try {
  7043. ProbeForWriteBuffer(pPropSet, cPropMax, sizeof(DWORD));
  7044. ProbeForWriteUlong(pcPropNeeded);
  7045. retval = _BuildPropList(
  7046. pwnd,
  7047. pPropSet,
  7048. cPropMax,
  7049. pcPropNeeded);
  7050. } except (StubExceptionHandler(FALSE)) {
  7051. MSGERROR(0); // pPropSet/pcPropNeed are USER's, not app's
  7052. }
  7053. TRACE("NtUserBuildPropList");
  7054. ENDRECV_HWNDLOCK();
  7055. }
  7056. NTSTATUS NtUserBuildNameList( // worker for EnumWindowStations/EnumDesktops
  7057. IN HWINSTA hwinsta,
  7058. IN UINT cbNameList,
  7059. OUT PNAMELIST ccxpNameList,
  7060. OUT PUINT pcbNeeded)
  7061. {
  7062. UINT cbNeeded;
  7063. PWINDOWSTATION pwinsta;
  7064. BEGINRECV_SHARED(NTSTATUS, STATUS_INVALID_HANDLE);
  7065. if (cbNameList < sizeof(NAMELIST)) {
  7066. MSGERROR(0);
  7067. }
  7068. try {
  7069. ProbeForWriteUlong(pcbNeeded);
  7070. ProbeForWrite(ccxpNameList, cbNameList, sizeof(DWORD));
  7071. } except (StubExceptionHandler(FALSE)) {
  7072. MSGERROR(0);
  7073. }
  7074. if (hwinsta != NULL) {
  7075. retval = ValidateHwinsta(hwinsta, UserMode, WINSTA_ENUMDESKTOPS, &pwinsta);
  7076. } else {
  7077. retval = STATUS_SUCCESS;
  7078. pwinsta = NULL;
  7079. }
  7080. if (!NT_SUCCESS(retval)) {
  7081. try {
  7082. *ccxpNameList->awchNames = 0;
  7083. ccxpNameList->cb = 1;
  7084. } except (StubExceptionHandler(FALSE)) {
  7085. MSGERROR(0);
  7086. }
  7087. } else {
  7088. retval = _BuildNameList(pwinsta, ccxpNameList, cbNameList, &cbNeeded);
  7089. try {
  7090. *pcbNeeded = cbNeeded;
  7091. } except (StubExceptionHandler(FALSE)) {
  7092. retval = STATUS_ACCESS_VIOLATION;
  7093. }
  7094. if (pwinsta != NULL) {
  7095. ObDereferenceObject(pwinsta);
  7096. }
  7097. }
  7098. TRACE("NtUserBuildNameList");
  7099. ENDRECV_SHARED();
  7100. }
  7101. HKL NtUserActivateKeyboardLayout(
  7102. IN HKL hkl,
  7103. IN UINT Flags)
  7104. {
  7105. BEGINRECV(HKL, NULL);
  7106. /*
  7107. * Prevent restricted threads from setting the keyboard layout
  7108. * for the entire system.
  7109. */
  7110. if (IS_CURRENT_THREAD_RESTRICTED(JOB_OBJECT_UILIMIT_HANDLES)) {
  7111. MSGERROR(0);
  7112. }
  7113. retval = xxxActivateKeyboardLayout(_GetProcessWindowStation(NULL),
  7114. hkl,
  7115. Flags,
  7116. NULL);
  7117. TRACE("NtUserActivateKeyboardLayout");
  7118. ENDRECV();
  7119. }
  7120. NTSTATUS GetSymbolicLink(
  7121. OUT PUNICODE_STRING pLinkTarget,
  7122. IN PCWSTR pSymbolicLink)
  7123. {
  7124. NTSTATUS Status;
  7125. HANDLE hLinkHandle;
  7126. OBJECT_ATTRIBUTES oa;
  7127. UNICODE_STRING RootString;
  7128. UNICODE_STRING RootValue;
  7129. PVOID pRootValueBuffer = UserAllocPool(MAX_PATH * sizeof(WCHAR), TAG_KBDLAYOUT);
  7130. if (pRootValueBuffer == NULL) {
  7131. return STATUS_NO_MEMORY;
  7132. }
  7133. RtlInitUnicodeString(&RootString,
  7134. pSymbolicLink);
  7135. InitializeObjectAttributes(&oa,
  7136. &RootString,
  7137. OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
  7138. NULL,
  7139. NULL);
  7140. Status = ZwOpenSymbolicLinkObject(&hLinkHandle,
  7141. GENERIC_READ,
  7142. &oa);
  7143. if (!NT_SUCCESS(Status)) {
  7144. RIPMSG1(RIP_WARNING,
  7145. "GetSymbolicLink: Failed to open symbolic link. Got status=%x.",
  7146. Status);
  7147. goto exit;
  7148. }
  7149. RootValue.Buffer = pRootValueBuffer;
  7150. RootValue.Length = 0;
  7151. RootValue.MaximumLength = (USHORT)MAX_PATH * sizeof(WCHAR);
  7152. Status = ZwQuerySymbolicLinkObject(hLinkHandle, &RootValue, NULL);
  7153. ZwClose(hLinkHandle);
  7154. if (!NT_SUCCESS(Status)) {
  7155. RIPMSG1(RIP_WARNING,
  7156. "GetSymbolicLink: Failed to query symbolic link. Got status=%x.",
  7157. Status);
  7158. goto exit;
  7159. }
  7160. RtlCopyUnicodeString(pLinkTarget, &RootValue);
  7161. exit:
  7162. if (pRootValueBuffer) {
  7163. UserFreePool(pRootValueBuffer);
  7164. }
  7165. return Status;
  7166. }
  7167. NTSTATUS GetWindowsDirectoryDevicePath(
  7168. OUT PUNICODE_STRING pWindir)
  7169. {
  7170. NTSTATUS Status;
  7171. PWCHAR pSlash = NULL, pFixUp;
  7172. UNICODE_STRING RootValue;
  7173. UNICODE_STRING PathValue;
  7174. PVOID pRootValueBuffer = UserAllocPool(MAX_PATH * sizeof(WCHAR), TAG_KBDLAYOUT);
  7175. PVOID pPathValueBuffer = UserAllocPool(MAX_PATH * sizeof(WCHAR), TAG_KBDLAYOUT);
  7176. if ((pRootValueBuffer == NULL) || (pPathValueBuffer == NULL)) {
  7177. Status = STATUS_NO_MEMORY;
  7178. RIPMSGF1(RIP_WARNING,
  7179. "Failed to allocate memory. Got status=%x.",
  7180. Status);
  7181. goto exit;
  7182. }
  7183. RootValue.Buffer = pRootValueBuffer;
  7184. RootValue.Length = 0;
  7185. RootValue.MaximumLength = (USHORT)MAX_PATH * sizeof(WCHAR);
  7186. /*
  7187. * \SystemRoot is a SymbolicLink that will get us the name of the
  7188. * windows install directory. Much like %systemroot%\%windir% does.
  7189. */
  7190. Status = GetSymbolicLink(&RootValue, L"\\SystemRoot");
  7191. if (!NT_SUCCESS(Status)) {
  7192. RIPMSGF1(RIP_WARNING,
  7193. "Failed to query \\SystemRoot. Got status=%x.",
  7194. Status);
  7195. goto exit;
  7196. }
  7197. /*
  7198. * \SystemRoot returns in the form "\Device\Harddisk1\Partition1\WINDOWS".
  7199. * We need to convert to \Device\HarddiskVolume3\WINDOWS form by converting
  7200. * the "\Device\Harddisk1\Partition1" SymbolicLink to the needed form so we
  7201. * can do our comparisons.
  7202. * We will walk the string backwards masking out a slash at a time as it is
  7203. * possible the windows directory is \WINDOWS\foo\xyz or anything the user
  7204. * has decided to make it. It is not always 1 level deep.
  7205. */
  7206. PathValue.Buffer = pPathValueBuffer;
  7207. PathValue.Length = 0;
  7208. PathValue.MaximumLength = (USHORT)MAX_PATH * sizeof(WCHAR);
  7209. do {
  7210. pFixUp = pSlash;
  7211. pSlash = wcsrchr(RootValue.Buffer, L'\\');
  7212. if (pFixUp != NULL) {
  7213. pFixUp[0] = L'\\';
  7214. }
  7215. if (pSlash) {
  7216. pSlash[0] = L'\0';
  7217. Status = GetSymbolicLink(&PathValue, RootValue.Buffer);
  7218. if (NT_SUCCESS(Status)) {
  7219. pSlash[0] = L'\\';
  7220. RtlAppendUnicodeToString(&PathValue, pSlash);
  7221. RtlCopyUnicodeString(pWindir, &PathValue);
  7222. goto exit;
  7223. }
  7224. }
  7225. } while (pSlash != NULL);
  7226. exit:
  7227. if (pRootValueBuffer) {
  7228. UserFreePool(pRootValueBuffer);
  7229. }
  7230. if (pPathValueBuffer) {
  7231. UserFreePool(pPathValueBuffer);
  7232. }
  7233. return Status;
  7234. }
  7235. HANDLE ConvertHandleAndVerifyLoc(
  7236. HANDLE hFile)
  7237. {
  7238. HANDLE hSafeFile = NULL;
  7239. NTSTATUS Status;
  7240. PFILE_OBJECT pFileObject = NULL;
  7241. ULONG ulRetNameLength;
  7242. BYTE bNameBuffer[(MAX_PATH * sizeof(WCHAR)) + sizeof(OBJECT_NAME_INFORMATION)];
  7243. POBJECT_NAME_INFORMATION pFileNameInfo = (POBJECT_NAME_INFORMATION)bNameBuffer;
  7244. PUNICODE_STRING pNameBuffer = (PUNICODE_STRING)&bNameBuffer;
  7245. UNICODE_STRING LinkValue;
  7246. PVOID pLinkValueBuffer = UserAllocPool(MAX_PATH * sizeof(WCHAR), TAG_KBDLAYOUT);
  7247. if (pLinkValueBuffer == NULL) {
  7248. Status = STATUS_NO_MEMORY;
  7249. goto exit;
  7250. }
  7251. if (hFile) {
  7252. /*
  7253. * This will get a pointer to the object, Verify that the user has
  7254. * read access and that the object is a file handle.
  7255. */
  7256. Status = ObReferenceObjectByHandle(hFile,
  7257. FILE_READ_DATA,
  7258. *IoFileObjectType,
  7259. UserMode,
  7260. &pFileObject,
  7261. NULL);
  7262. if (!NT_SUCCESS(Status)) {
  7263. RIPMSGF2(RIP_WARNING,
  7264. "Failed to convert handle %x. Got status=%x.",
  7265. hFile,
  7266. Status);
  7267. goto exit;
  7268. }
  7269. /*
  7270. * Lets get the name of the file. The value returned is of the form
  7271. * "\Device\HarddiskVolume3\WINDOWS\system32\kbdus.dll"
  7272. */
  7273. Status = ObQueryNameString(pFileObject,
  7274. pFileNameInfo,
  7275. sizeof(bNameBuffer),
  7276. &ulRetNameLength);
  7277. if (!NT_SUCCESS(Status)) {
  7278. RIPMSGF2(RIP_WARNING,
  7279. "Failed to query info for %p. Got status=%x.",
  7280. pFileObject,
  7281. Status);
  7282. goto exit;
  7283. }
  7284. LinkValue.Buffer = pLinkValueBuffer;
  7285. LinkValue.Length = 0;
  7286. LinkValue.MaximumLength = (USHORT)MAX_PATH * sizeof(WCHAR);
  7287. /*
  7288. * Now lets get the windows directory path so we can match this
  7289. * with pFileNameInfo's value and make sure we are in the windows
  7290. * directory.
  7291. */
  7292. Status = GetWindowsDirectoryDevicePath(&LinkValue);
  7293. if (!NT_SUCCESS(Status)) {
  7294. RIPMSGF1(RIP_WARNING,
  7295. "Failed to query \\SystemRoot. Got status=%x.",
  7296. Status);
  7297. goto exit;
  7298. }
  7299. #if defined(_WIN64)
  7300. if (PtiCurrent()->TIF_flags & TIF_WOW64) {
  7301. RtlAppendUnicodeToString(&LinkValue, L"\\SysWOW64");
  7302. } else
  7303. #endif
  7304. {
  7305. RtlAppendUnicodeToString(&LinkValue, L"\\system32");
  7306. }
  7307. if (_wcsnicmp(pFileNameInfo->Name.Buffer, LinkValue.Buffer, LinkValue.Length / sizeof(WCHAR))) {
  7308. RIPMSGF1(RIP_WARNING,
  7309. "Specifed hFile %S is not in a secure location.",
  7310. pFileNameInfo->Name.Buffer);
  7311. Status = STATUS_INVALID_PARAMETER_1;
  7312. goto exit;
  7313. }
  7314. /*
  7315. * We have passed the location check so lets go ahead and open a
  7316. * kernel handle that we can use later to map the view.
  7317. */
  7318. Status = ObOpenObjectByPointer(pFileObject,
  7319. OBJ_KERNEL_HANDLE,
  7320. NULL,
  7321. FILE_READ_DATA,
  7322. *IoFileObjectType,
  7323. KernelMode,
  7324. &hSafeFile);
  7325. if (!NT_SUCCESS(Status)) {
  7326. RIPMSGF2(RIP_WARNING,
  7327. "Failed to get handle for %p. Got status=%x.",
  7328. pFileObject,
  7329. Status);
  7330. goto exit;
  7331. }
  7332. }
  7333. goto exit;
  7334. exit:
  7335. if (pLinkValueBuffer != NULL) {
  7336. UserFreePool(pLinkValueBuffer);
  7337. }
  7338. if (pFileObject) {
  7339. ObDereferenceObject(pFileObject);
  7340. }
  7341. return hSafeFile;
  7342. }
  7343. HKL NtUserLoadKeyboardLayoutEx(
  7344. IN HANDLE hFile,
  7345. IN DWORD offTable,
  7346. IN PKBDTABLE_MULTI_INTERNAL pKbdTableMulti,
  7347. IN HKL hkl,
  7348. IN PUNICODE_STRING pstrKLID,
  7349. IN UINT KbdInputLocale,
  7350. IN UINT Flags)
  7351. {
  7352. UNICODE_STRING strKLID;
  7353. PWINDOWSTATION pwinsta;
  7354. WCHAR awchKF[KL_NAMELENGTH];
  7355. UINT chMax;
  7356. KBDTABLE_MULTI_INTERNAL kbdTableMulti;
  7357. HANDLE hSafeFile = NULL;
  7358. UINT i;
  7359. BEGINRECV(HKL, NULL);
  7360. TESTFLAGS(Flags, KLF_VALID);
  7361. RtlZeroMemory(&kbdTableMulti, sizeof(KBDTABLE_MULTI_INTERNAL));
  7362. pwinsta = _GetProcessWindowStation(NULL);
  7363. /*
  7364. * Probe arguments
  7365. */
  7366. try {
  7367. strKLID = ProbeAndReadUnicodeString(pstrKLID);
  7368. ProbeForRead(strKLID.Buffer, strKLID.Length, CHARALIGN);
  7369. chMax = min(sizeof(awchKF) - sizeof(WCHAR), strKLID.Length) / sizeof(WCHAR);
  7370. wcsncpy(awchKF, strKLID.Buffer, chMax);
  7371. awchKF[chMax] = 0;
  7372. if (pKbdTableMulti) {
  7373. kbdTableMulti = ProbeAndReadStructure(pKbdTableMulti, KBDTABLE_MULTI_INTERNAL);
  7374. }
  7375. } except (StubExceptionHandler(TRUE)) {
  7376. MSGERRORCLEANUP(0);
  7377. }
  7378. hSafeFile = ConvertHandleAndVerifyLoc(hFile);
  7379. if (pKbdTableMulti && hSafeFile != NULL) {
  7380. if (kbdTableMulti.multi.nTables >= KBDTABLE_MULTI_MAX) {
  7381. RIPMSGF1(RIP_WARNING,
  7382. "pKbdTableMulti.multi.nTables too large: %x",
  7383. kbdTableMulti.multi.nTables);
  7384. kbdTableMulti.multi.nTables = 0;
  7385. MSGERRORCLEANUP(ERROR_INVALID_PARAMETER);
  7386. } else if (kbdTableMulti.multi.nTables > 0) {
  7387. for (i = 0; i < kbdTableMulti.multi.nTables; i++) {
  7388. kbdTableMulti.files[i].hFile = ConvertHandleAndVerifyLoc(kbdTableMulti.files[i].hFile);
  7389. if (kbdTableMulti.files[i].hFile == NULL) {
  7390. RIPMSGF2(RIP_WARNING,
  7391. "Failed to Convert KbdTableMulti[%x].hFile and nTables is %x.",
  7392. i,
  7393. kbdTableMulti.multi.nTables);
  7394. break;
  7395. }
  7396. }
  7397. kbdTableMulti.multi.nTables = i;
  7398. }
  7399. }
  7400. pKbdTableMulti = &kbdTableMulti;
  7401. retval = xxxLoadKeyboardLayoutEx(pwinsta,
  7402. hSafeFile,
  7403. hkl,
  7404. offTable,
  7405. pKbdTableMulti,
  7406. awchKF,
  7407. KbdInputLocale,
  7408. Flags);
  7409. CLEANUPRECV();
  7410. if (hSafeFile != NULL) {
  7411. ZwClose(hSafeFile);
  7412. for (i = 0; i < kbdTableMulti.multi.nTables; i++) {
  7413. if (kbdTableMulti.files[i].hFile != NULL) {
  7414. ZwClose(kbdTableMulti.files[i].hFile);
  7415. }
  7416. }
  7417. }
  7418. TRACE("NtUserLoadKeyboardLayoutEx");
  7419. ENDRECV();
  7420. }
  7421. BOOL NtUserUnloadKeyboardLayout(
  7422. IN HKL hkl)
  7423. {
  7424. BEGINRECV(BOOL, FALSE);
  7425. retval = xxxUnloadKeyboardLayout(
  7426. _GetProcessWindowStation(NULL),
  7427. hkl);
  7428. TRACE("NtUserUnloadKeyboardLayout");
  7429. ENDRECV();
  7430. }
  7431. BOOL NtUserSetSystemMenu(
  7432. IN HWND hwnd,
  7433. IN HMENU hmenu)
  7434. {
  7435. PMENU pmenu;
  7436. TL tlpMenu;
  7437. BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
  7438. ValidateHMENU(pmenu, hmenu);
  7439. ThreadLockAlwaysWithPti(ptiCurrent, pmenu, &tlpMenu);
  7440. retval = xxxSetSystemMenu(pwnd, pmenu);
  7441. ThreadUnlock(&tlpMenu);
  7442. TRACE("NtUserSetSystemMenu");
  7443. ENDRECV_HWNDLOCK();
  7444. }
  7445. BOOL NtUserDragDetect(
  7446. IN HWND hwnd,
  7447. IN POINT pt)
  7448. {
  7449. BEGINRECV_HWNDLOCK(DWORD, 0, hwnd);
  7450. retval = xxxDragDetect(pwnd, pt);
  7451. TRACE("NtUserDragDetect");
  7452. ENDRECV_HWNDLOCK();
  7453. }
  7454. UINT_PTR NtUserSetSystemTimer(
  7455. IN HWND hwnd,
  7456. IN UINT_PTR nIDEvent,
  7457. IN DWORD dwElapse,
  7458. IN WNDPROC pTimerFunc)
  7459. {
  7460. BEGINRECV_HWND(UINT_PTR, 0, hwnd);
  7461. UNREFERENCED_PARAMETER(pTimerFunc);
  7462. retval = _SetSystemTimer(pwnd,
  7463. nIDEvent,
  7464. dwElapse,
  7465. NULL);
  7466. TRACE("NtUserSetSystemTimer");
  7467. ENDRECV_HWND();
  7468. }
  7469. BOOL NtUserQuerySendMessage( // private QuerySendMessage
  7470. OUT PMSG pmsg OPTIONAL)
  7471. {
  7472. PSMS psms;
  7473. BEGINRECV_SHARED(BOOL, FALSE);
  7474. if ((psms = PtiCurrentShared()->psmsCurrent) == NULL) {
  7475. MSGERROR(0);
  7476. }
  7477. retval = TRUE;
  7478. if (ARGUMENT_PRESENT(pmsg)) {
  7479. try {
  7480. ProbeForWriteMessage(pmsg);
  7481. pmsg->hwnd = HW(psms->spwnd);
  7482. pmsg->message = psms->message;
  7483. pmsg->wParam = psms->wParam;
  7484. pmsg->lParam = psms->lParam;
  7485. pmsg->time = psms->tSent;
  7486. pmsg->pt.x = 0;
  7487. pmsg->pt.y = 0;
  7488. } except (StubExceptionHandler(FALSE)) {
  7489. MSGERROR(0);
  7490. }
  7491. }
  7492. TRACE("NtUserQuerySendMessage");
  7493. ENDRECV_SHARED();
  7494. }
  7495. UINT NtUserSendInput(
  7496. IN UINT cInputs,
  7497. IN CONST INPUT *pInputs,
  7498. IN int cbSize)
  7499. {
  7500. LPINPUT pInput2 = NULL;
  7501. PTHREADINFO ptiCurrent;
  7502. TL tlInput;
  7503. BEGINRECV(UINT, 0);
  7504. if (sizeof(INPUT) != cbSize || cInputs == 0) {
  7505. MSGERROR(ERROR_INVALID_PARAMETER);
  7506. }
  7507. ptiCurrent = PtiCurrent();
  7508. /*
  7509. * Probe arguments
  7510. */
  7511. try {
  7512. ProbeForReadBuffer(pInputs, cInputs, DATAALIGN);
  7513. pInput2 = UserAllocPoolWithQuota(cInputs * sizeof(*pInputs), TAG_SENDINPUT);
  7514. if (pInput2 == NULL) {
  7515. ExRaiseStatus(STATUS_NO_MEMORY);
  7516. }
  7517. RtlCopyMemory(pInput2, pInputs, cInputs * sizeof(*pInputs));
  7518. } except (StubExceptionHandler(TRUE)) {
  7519. MSGERRORCLEANUP(0);
  7520. }
  7521. ThreadLockPool(ptiCurrent, pInput2, &tlInput);
  7522. retval = xxxSendInput(cInputs, pInput2);
  7523. ThreadUnlockPool(ptiCurrent, &tlInput);
  7524. CLEANUPRECV();
  7525. if (pInput2) {
  7526. UserFreePool(pInput2);
  7527. }
  7528. TRACE("NtUserSendInput");
  7529. ENDRECV();
  7530. }
  7531. UINT NtUserBlockInput(
  7532. IN BOOL fBlockIt)
  7533. {
  7534. BEGINATOMICRECV(BOOL, FALSE);
  7535. retval = _BlockInput(fBlockIt);
  7536. TRACE("NtUserBlockInput");
  7537. ENDATOMICRECV();
  7538. }
  7539. BOOL NtUserImpersonateDdeClientWindow(
  7540. IN HWND hwndClient,
  7541. IN HWND hwndServer)
  7542. {
  7543. PWND pwndServer;
  7544. BEGINATOMICRECV_HWND(BOOL, FALSE, hwndClient);
  7545. ValidateHWND(pwndServer, hwndServer);
  7546. if (GETPTI(pwndServer) != PtiCurrent()) {
  7547. RIPERR0(ERROR_INVALID_PARAMETER, RIP_VERBOSE, "");
  7548. MSGERROR(0);
  7549. }
  7550. if (GETPWNDPPI(pwnd) == GETPWNDPPI(pwndServer)) {
  7551. retval = TRUE; // impersonating self is a NOOP
  7552. } else {
  7553. retval = _ImpersonateDdeClientWindow(pwnd, pwndServer);
  7554. }
  7555. TRACE("NtUserImpersonateDdeClientWindow");
  7556. ENDATOMICRECV_HWND();
  7557. }
  7558. ULONG_PTR NtUserGetCPD(
  7559. IN HWND hwnd,
  7560. IN DWORD options,
  7561. IN ULONG_PTR dwData)
  7562. {
  7563. BEGINRECV_HWND(ULONG_PTR, 0, hwnd);
  7564. switch (options & ~CPD_TRANSITION_TYPES) {
  7565. case CPD_WND:
  7566. case CPD_DIALOG:
  7567. case CPD_WNDTOCLS:
  7568. break;
  7569. default:
  7570. RIPMSG1(RIP_WARNING, "GetCPD: Invalid options %x", options);
  7571. MSGERROR(0);
  7572. }
  7573. retval = GetCPD(pwnd, options, dwData);
  7574. TRACE("NtUserGetCPD");
  7575. ENDRECV_HWND();
  7576. }
  7577. int NtUserCopyAcceleratorTable( // API CopyAcceleratorTableA/W
  7578. IN HACCEL hAccelSrc,
  7579. IN OUT LPACCEL lpAccelDst OPTIONAL,
  7580. IN int cAccel)
  7581. {
  7582. LPACCELTABLE pat;
  7583. int i;
  7584. BEGINATOMICRECV(int, 0);
  7585. ValidateHACCEL(pat, hAccelSrc);
  7586. if (lpAccelDst == NULL) {
  7587. retval = pat->cAccel;
  7588. } else {
  7589. /*
  7590. * Probe arguments
  7591. */
  7592. try {
  7593. ProbeForWriteBuffer(lpAccelDst, cAccel, DATAALIGN);
  7594. if (cAccel > (int)pat->cAccel)
  7595. cAccel = pat->cAccel;
  7596. retval = cAccel;
  7597. for (i = 0; i < cAccel; i++) {
  7598. RtlCopyMemory(&lpAccelDst[i], &pat->accel[i], sizeof(ACCEL));
  7599. lpAccelDst[i].fVirt &= ~FLASTKEY;
  7600. }
  7601. } except (StubExceptionHandler(TRUE)) {
  7602. MSGERROR(0);
  7603. }
  7604. }
  7605. TRACE("NtUserCopyAcceleratorTable");
  7606. ENDATOMICRECV();
  7607. }
  7608. HWND NtUserFindWindowEx( // API FindWindowA/W, FindWindowExA/W
  7609. IN HWND hwndParent,
  7610. IN HWND hwndChild,
  7611. IN PUNICODE_STRING pstrClassName,
  7612. IN PUNICODE_STRING pstrWindowName,
  7613. DWORD dwType)
  7614. {
  7615. UNICODE_STRING strClassName;
  7616. UNICODE_STRING strWindowName;
  7617. PWND pwndParent, pwndChild;
  7618. BEGINATOMICRECV(HWND, NULL);
  7619. if (hwndParent != HWND_MESSAGE) {
  7620. ValidateHWNDOPT(pwndParent, hwndParent);
  7621. } else {
  7622. pwndParent = _GetMessageWindow();
  7623. }
  7624. ValidateHWNDOPT(pwndChild, hwndChild);
  7625. /*
  7626. * Probe arguments
  7627. */
  7628. try {
  7629. strClassName = ProbeAndReadUnicodeString(pstrClassName);
  7630. strWindowName = ProbeAndReadUnicodeString(pstrWindowName);
  7631. ProbeForReadUnicodeStringBufferOrId(strClassName);
  7632. ProbeForReadUnicodeStringBuffer(strWindowName);
  7633. } except (StubExceptionHandler(TRUE)) {
  7634. MSGERRORCLEANUP(0);
  7635. }
  7636. /*
  7637. * Use of both buffers is protected by try/except clauses in the code.
  7638. */
  7639. retval = (HWND)_FindWindowEx(
  7640. pwndParent,
  7641. pwndChild,
  7642. strClassName.Buffer,
  7643. strWindowName.Buffer,
  7644. dwType);
  7645. retval = PtoH((PVOID)retval);
  7646. CLEANUPRECV();
  7647. TRACE("NtUserFindWindowEx");
  7648. ENDATOMICRECV();
  7649. }
  7650. BOOL NtUserGetClassInfoEx( // API GetClassInfoA/W
  7651. IN HINSTANCE hInstance OPTIONAL,
  7652. IN PUNICODE_STRING pstrClassName,
  7653. IN OUT LPWNDCLASSEXW lpWndClass,
  7654. OUT LPWSTR *ppszMenuName,
  7655. IN BOOL bAnsi)
  7656. {
  7657. UNICODE_STRING strClassName;
  7658. LPWSTR pszMenuName;
  7659. WNDCLASSEXW wc;
  7660. BEGINRECV(BOOL, FALSE);
  7661. #ifdef LAZY_CLASS_INIT
  7662. if ((PtiCurrent()->ppi->W32PF_Flags & W32PF_CLASSESREGISTERED) == 0) {
  7663. if (!LW_RegisterWindows()) {
  7664. MSGERROR(ERROR_INVALID_PARAMETER);
  7665. }
  7666. }
  7667. #endif
  7668. /*
  7669. * Probe arguments
  7670. */
  7671. try {
  7672. strClassName = ProbeAndReadUnicodeString(pstrClassName);
  7673. /*
  7674. * The class name may either be a string or an atom. Only
  7675. * probe strings.
  7676. */
  7677. ProbeForReadUnicodeStringBufferOrId(strClassName);
  7678. ProbeForWrite(lpWndClass, sizeof(*lpWndClass), DATAALIGN);
  7679. ProbeForWriteUlong((PULONG)ppszMenuName);
  7680. RtlCopyMemory(&wc, lpWndClass, sizeof(WNDCLASSEXW));
  7681. } except (StubExceptionHandler(TRUE)) {
  7682. MSGERROR(0);
  7683. }
  7684. /*
  7685. * The class name buffer is client-side.
  7686. */
  7687. retval = _GetClassInfoEx(hInstance,
  7688. (LPTSTR)strClassName.Buffer,
  7689. &wc,
  7690. &pszMenuName,
  7691. bAnsi);
  7692. if (retval) {
  7693. try {
  7694. RtlCopyMemory(lpWndClass, &wc, sizeof(WNDCLASSEXW));
  7695. *ppszMenuName = pszMenuName;
  7696. } except (StubExceptionHandler(TRUE)) {
  7697. MSGERROR(0);
  7698. }
  7699. }
  7700. TRACE("NtUserGetClassInfo");
  7701. ENDRECV();
  7702. }
  7703. /*
  7704. * gaFNIDtoICLS is used only in NtUserGetClassName and should be in sync with
  7705. * the values from user.h
  7706. * ICLS_MAX is an unused value
  7707. */
  7708. CONST BYTE gaFNIDtoICLS[] = {
  7709. // FNID-START
  7710. ICLS_SCROLLBAR, // FNID_SCROLLBAR
  7711. ICLS_ICONTITLE, // FNID_ICONTITLE
  7712. ICLS_MENU, // FNID_MENU
  7713. ICLS_DESKTOP, // FNID_DESKTOP
  7714. ICLS_MAX, // FNID_DEFWINDOWPROC
  7715. ICLS_MAX, // FNID_MESSAGE
  7716. ICLS_SWITCH, // FNID_SWITCH
  7717. ICLS_BUTTON, // FNID_BUTTON
  7718. ICLS_COMBOBOX, // FNID_COMBOBOX
  7719. ICLS_COMBOLISTBOX, // FNID_COMBOLISTBOX
  7720. ICLS_DIALOG, // FNID_DIALOG
  7721. ICLS_EDIT, // FNID_EDIT
  7722. ICLS_LISTBOX, // FNID_LISTBOX
  7723. ICLS_MDICLIENT, // FNID_MDICLIENT
  7724. ICLS_STATIC, // FNID_STATIC
  7725. ICLS_IME, // FNID_IME
  7726. ICLS_MAX, // FNID_HKINLPCWPEXSTRUCT
  7727. ICLS_MAX, // FNID_HKINLPCWPRETEXSTRUCT
  7728. ICLS_MAX, // FNID_DEFFRAMEPROC
  7729. ICLS_MAX, // FNID_DEFMDICHILDPROC
  7730. ICLS_MAX, // FNID_MB_DLGPROC
  7731. ICLS_MAX, // FNID_MDIACTIVATEDLGPROC
  7732. ICLS_MAX, // FNID_SENDMESSAGE
  7733. ICLS_MAX, // FNID_SENDMESSAGEFF
  7734. ICLS_MAX, // FNID_SENDMESSAGEEX
  7735. ICLS_MAX, // FNID_CALLWINDOWPROC
  7736. ICLS_MAX, // FNID_SENDMESSAGEBSM
  7737. ICLS_TOOLTIP, // FNID_TOOLTIP
  7738. ICLS_GHOST, // FNID_GHOST
  7739. ICLS_MAX, // FNID_SENDNOTIFYMESSAGE
  7740. ICLS_MAX // FNID_SENDMESSAGECALLBACK
  7741. }; // FNID_END
  7742. int NtUserGetClassName( // API GetClassNameA/W
  7743. IN HWND hwnd,
  7744. IN BOOL bReal,
  7745. IN OUT PUNICODE_STRING pstrClassName)
  7746. {
  7747. UNICODE_STRING strClassName;
  7748. ATOM atom;
  7749. BEGINRECV_HWND_SHARED(DWORD, 0, hwnd);
  7750. /*
  7751. * Probe arguments
  7752. */
  7753. try {
  7754. strClassName = ProbeAndReadUnicodeString(pstrClassName);
  7755. #if defined(_X86_)
  7756. ProbeForWrite(strClassName.Buffer, strClassName.MaximumLength,
  7757. sizeof(BYTE));
  7758. #else
  7759. ProbeForWrite(strClassName.Buffer, strClassName.MaximumLength,
  7760. sizeof(WCHAR));
  7761. #endif
  7762. atom = pwnd->pcls->atomNVClassName;
  7763. UserAssert(ARRAY_SIZE(gaFNIDtoICLS) == FNID_END - FNID_START + 1);
  7764. if (bReal) {
  7765. DWORD dwFnid;
  7766. DWORD dwClass;
  7767. dwFnid = GETFNID(pwnd);
  7768. if (dwFnid) {
  7769. dwFnid -= FNID_START;
  7770. if (dwFnid < ARRAY_SIZE(gaFNIDtoICLS)) {
  7771. dwClass = gaFNIDtoICLS[dwFnid];
  7772. if (dwClass != ICLS_MAX) {
  7773. atom = gpsi->atomSysClass[dwClass];
  7774. }
  7775. }
  7776. }
  7777. }
  7778. retval = UserGetAtomName(
  7779. atom,
  7780. strClassName.Buffer,
  7781. strClassName.MaximumLength / sizeof(WCHAR));
  7782. } except (StubExceptionHandler(TRUE)) {
  7783. MSGERROR(0);
  7784. }
  7785. TRACE("NtUserGetClassName");
  7786. ENDRECV_HWND_SHARED();
  7787. }
  7788. UINT NtUserGetAtomName(
  7789. IN ATOM atom,
  7790. IN OUT PUNICODE_STRING pstrAtomName)
  7791. {
  7792. UNICODE_STRING strAtomName;
  7793. BEGINRECV_SHARED(UINT, 0);
  7794. /*
  7795. * Probe arguments
  7796. */
  7797. try {
  7798. strAtomName = ProbeAndReadUnicodeString(pstrAtomName);
  7799. #if defined(_X86_)
  7800. ProbeForWrite(strAtomName.Buffer, strAtomName.MaximumLength,
  7801. sizeof(BYTE));
  7802. #else
  7803. ProbeForWrite(strAtomName.Buffer, strAtomName.MaximumLength,
  7804. sizeof(WCHAR));
  7805. #endif
  7806. } except (StubExceptionHandler(TRUE)) {
  7807. MSGERROR(0);
  7808. }
  7809. retval = UserGetAtomName(
  7810. atom,
  7811. strAtomName.Buffer,
  7812. strAtomName.MaximumLength / sizeof(WCHAR));
  7813. TRACE("NtUserGetAtomName");
  7814. ENDRECV_SHARED();
  7815. }
  7816. int NtUserGetClipboardFormatName( // API GetclipboardFormatNameA/W
  7817. IN UINT format,
  7818. OUT LPWSTR lpszFormatName,
  7819. IN UINT chMax)
  7820. {
  7821. BEGINRECV_NOCRIT(int, 0);
  7822. /*
  7823. * Probe arguments
  7824. */
  7825. try {
  7826. ProbeForWriteBuffer(lpszFormatName, chMax, CHARALIGN);
  7827. } except (StubExceptionHandler(TRUE)) {
  7828. MSGERROR(0);
  7829. }
  7830. if ((ATOM)format < MAXINTATOM) {
  7831. MSGERROR(ERROR_INVALID_PARAMETER);
  7832. } else {
  7833. /*
  7834. * UserGetAtomName (actually RtlQueryAtomInAtomTable) protects access
  7835. * within a try block, and sets last error appropriately.
  7836. */
  7837. retval = UserGetAtomName((ATOM)format, lpszFormatName, chMax);
  7838. }
  7839. TRACE("NtUserGetClipboardFormatName");
  7840. ENDRECV_NOCRIT();
  7841. }
  7842. int NtUserGetKeyNameText(
  7843. IN LONG lParam,
  7844. OUT LPWSTR lpszKeyName,
  7845. IN UINT chMax)
  7846. {
  7847. BEGINRECV_SHARED(int, 0);
  7848. /*
  7849. * Probe arguments
  7850. */
  7851. try {
  7852. ProbeForWriteBuffer(lpszKeyName, chMax, CHARALIGN);
  7853. } except (StubExceptionHandler(TRUE)) {
  7854. MSGERROR(0);
  7855. }
  7856. /*
  7857. * Note -- lpszKeyName is a client-side address. GetKeyNameText
  7858. * protects uses with try blocks, and sets last error accordingly.
  7859. */
  7860. retval = _GetKeyNameText(
  7861. lParam,
  7862. lpszKeyName,
  7863. chMax);
  7864. TRACE("NtUserGetKeyNameText");
  7865. ENDRECV_SHARED();
  7866. }
  7867. BOOL NtUserGetKeyboardLayoutName(
  7868. IN OUT PUNICODE_STRING pstrKLID)
  7869. {
  7870. PTHREADINFO ptiCurrent;
  7871. PKL pklActive;
  7872. UNICODE_STRING strKLID;
  7873. BEGINRECV_SHARED(BOOL, FALSE);
  7874. ptiCurrent = PtiCurrentShared();
  7875. pklActive = ptiCurrent->spklActive;
  7876. if (pklActive == NULL) {
  7877. MSGERROR(0);
  7878. }
  7879. /*
  7880. * Probe arguments
  7881. */
  7882. try {
  7883. strKLID = ProbeAndReadUnicodeString(pstrKLID);
  7884. ProbeForWrite(strKLID.Buffer, strKLID.MaximumLength, CHARALIGN);
  7885. if (IS_IME_KBDLAYOUT(pklActive->hkl)) {
  7886. /*
  7887. * IME KL may have different KL name for the same layout file.
  7888. * Their KL name are really equivalent to HKL.
  7889. */
  7890. RtlIntegerToUnicodeString(DOWNCAST(ULONG, pklActive->hkl), 0x10, &strKLID);
  7891. } else {
  7892. #if (KL_NAMELENGTH != 8 + 1)
  7893. #error unexpected KL_NAMELENGTH
  7894. #endif
  7895. if (strKLID.MaximumLength < KL_NAMELENGTH * sizeof(WCHAR) ||
  7896. !NT_SUCCESS(RtlIntegerToUnicode(pklActive->dwKLID, 0x10, -(KL_NAMELENGTH - 1), strKLID.Buffer))) {
  7897. MSGERROR(ERROR_INVALID_PARAMETER);
  7898. }
  7899. strKLID.Length = (KL_NAMELENGTH - 1) * sizeof(WCHAR);
  7900. /*
  7901. * Make it NULL terminated.
  7902. */
  7903. strKLID.Buffer[KL_NAMELENGTH - 1] = L'\0';
  7904. }
  7905. retval = TRUE;
  7906. } except (StubExceptionHandler(TRUE)) {
  7907. MSGERROR(0);
  7908. }
  7909. TRACE("NtUserGetKeyboardLayoutName");
  7910. ENDRECV_SHARED();
  7911. }
  7912. UINT NtUserGetKeyboardLayoutList(
  7913. IN UINT nItems,
  7914. OUT HKL *lpBuff)
  7915. {
  7916. PWINDOWSTATION pwinsta;
  7917. BEGINRECV_SHARED(UINT, 0);
  7918. /*
  7919. * Probe arguments
  7920. */
  7921. try {
  7922. if (!lpBuff) {
  7923. nItems = 0;
  7924. }
  7925. ProbeForWriteBuffer(lpBuff, nItems, DATAALIGN);
  7926. pwinsta = _GetProcessWindowStation(NULL);
  7927. } except (StubExceptionHandler(TRUE)) {
  7928. MSGERROR(0);
  7929. }
  7930. /*
  7931. * Access to the client-side buffer lpBuff is protected by try/except
  7932. * inside _GetKeyboardLayoutList()
  7933. */
  7934. retval = (DWORD)_GetKeyboardLayoutList(pwinsta, nItems, lpBuff);
  7935. TRACE("NtUserGetKeyboardLayoutList");
  7936. ENDRECV_SHARED();
  7937. }
  7938. UINT NtUserMapVirtualKeyEx(
  7939. IN UINT uCode,
  7940. IN UINT uMapType,
  7941. IN ULONG_PTR dwHKLorPKL,
  7942. IN BOOL bHKL)
  7943. {
  7944. PKL pkl;
  7945. BEGINRECV_SHARED(UINT, 0);
  7946. /*
  7947. * See if we need to convert an HKL to a PKL. MapVirtualKey passes a PKL and
  7948. * MapVirtualKeyEx passes an HKL. The conversion must be done in the kernel.
  7949. */
  7950. if (bHKL) {
  7951. pkl = HKLtoPKL(PtiCurrentShared(), (HKL)dwHKLorPKL);
  7952. } else {
  7953. pkl = PtiCurrentShared()->spklActive;
  7954. }
  7955. if (pkl == NULL) {
  7956. retval = 0;
  7957. } else {
  7958. retval = InternalMapVirtualKeyEx(uCode, uMapType, pkl->spkf->pKbdTbl);
  7959. }
  7960. TRACE("NtUserMapVirtualKeyEx");
  7961. ENDRECV_SHARED();
  7962. }
  7963. ATOM NtUserRegisterClassExWOW(
  7964. IN WNDCLASSEX *lpWndClass,
  7965. IN PUNICODE_STRING pstrClassName,
  7966. IN PUNICODE_STRING pstrClassNameVer,
  7967. IN PCLSMENUNAME pcmn,
  7968. IN WORD fnid,
  7969. IN DWORD dwFlags,
  7970. IN LPDWORD pdwWOWstuff OPTIONAL)
  7971. {
  7972. UNICODE_STRING strClassName;
  7973. UNICODE_STRING strClassNameVer;
  7974. UNICODE_STRING strMenuName;
  7975. WNDCLASSVEREX WndClass;
  7976. WC WowCls;
  7977. CLSMENUNAME cmn;
  7978. BEGINRECV(ATOM, 0);
  7979. TESTFLAGS(dwFlags, CSF_VALID);
  7980. #ifdef LAZY_CLASS_INIT
  7981. if ((PtiCurrent()->ppi->W32PF_Flags & W32PF_CLASSESREGISTERED) == 0) {
  7982. if (!LW_RegisterWindows()) {
  7983. MSGERROR(ERROR_INVALID_PARAMETER);
  7984. }
  7985. }
  7986. #endif
  7987. /*
  7988. * Probe arguments
  7989. */
  7990. try {
  7991. strClassName = ProbeAndReadUnicodeString(pstrClassName);
  7992. strClassNameVer = ProbeAndReadUnicodeString(pstrClassNameVer);
  7993. cmn = ProbeAndReadStructure(pcmn, CLSMENUNAME);
  7994. strMenuName = ProbeAndReadUnicodeString(cmn.pusMenuName);
  7995. *((LPWNDCLASSEX)(&WndClass)) = ProbeAndReadStructure(lpWndClass, WNDCLASSEX);
  7996. ProbeForReadUnicodeStringBufferOrId(strClassName);
  7997. ProbeForReadUnicodeStringBufferOrId(strClassNameVer);
  7998. ProbeForReadUnicodeStringBufferOrId(strMenuName);
  7999. if (ARGUMENT_PRESENT(pdwWOWstuff)) {
  8000. ProbeForRead(pdwWOWstuff, sizeof(WC), sizeof(BYTE));
  8001. RtlCopyMemory(&WowCls, pdwWOWstuff, sizeof(WC));
  8002. pdwWOWstuff = (PDWORD)&WowCls;
  8003. }
  8004. WndClass.lpszClassName = strClassName.Buffer;
  8005. WndClass.lpszClassNameVer = strClassNameVer.Buffer;
  8006. WndClass.lpszMenuName = strMenuName.Buffer;
  8007. } except (StubExceptionHandler(TRUE)) {
  8008. MSGERROR(0);
  8009. }
  8010. if (WndClass.cbClsExtra < 0 || WndClass.cbWndExtra < 0 || WndClass.cbSize != sizeof(WNDCLASSEX)) {
  8011. MSGERROR(ERROR_INVALID_PARAMETER);
  8012. }
  8013. /*
  8014. * ClassName and MenuName in WndClass are client-side pointers.
  8015. */
  8016. retval = _RegisterClassEx(&WndClass,
  8017. &cmn,
  8018. fnid,
  8019. dwFlags,
  8020. pdwWOWstuff);
  8021. TRACE("NtUserRegisterClassExWOW");
  8022. ENDRECV();
  8023. }
  8024. UINT NtUserRegisterWindowMessage(
  8025. IN PUNICODE_STRING pstrMessage)
  8026. {
  8027. UNICODE_STRING strMessage;
  8028. BEGINRECV_NOCRIT(UINT, 0);
  8029. /*
  8030. * Probe arguments
  8031. */
  8032. try {
  8033. strMessage = ProbeAndReadUnicodeString(pstrMessage);
  8034. ProbeForReadUnicodeStringBuffer(strMessage);
  8035. } except (StubExceptionHandler(TRUE)) {
  8036. MSGERROR(0);
  8037. }
  8038. /*
  8039. * The buffer is in client-side memory.
  8040. * Rtl atom routines protect accesses to strings with their
  8041. * own try/except blocks, UserAddAtom sets last error accordingly.
  8042. */
  8043. retval = UserAddAtom(
  8044. strMessage.Buffer, FALSE);
  8045. TRACE("NtUserRegisterWindowMessage");
  8046. ENDRECV_NOCRIT();
  8047. }
  8048. HANDLE NtUserRemoveProp(
  8049. IN HWND hwnd,
  8050. IN DWORD dwProp)
  8051. {
  8052. BEGINRECV_HWND(HANDLE, NULL, hwnd);
  8053. retval = InternalRemoveProp(pwnd, (LPWSTR)LOWORD(dwProp), FALSE);
  8054. TRACE("NtUserRemoveProp");
  8055. ENDRECV_HWND();
  8056. }
  8057. BOOL NtUserSetProp(
  8058. IN HWND hwnd,
  8059. IN DWORD dwProp,
  8060. IN HANDLE hData)
  8061. {
  8062. BEGINRECV_HWND(DWORD, 0, hwnd);
  8063. retval = InternalSetProp(pwnd,
  8064. (LPTSTR)LOWORD(dwProp),
  8065. hData,
  8066. HIWORD(dwProp) ? PROPF_STRING : 0);
  8067. TRACE("NtUserSetProp");
  8068. ENDRECV_HWND();
  8069. }
  8070. BOOL NtUserUnregisterClass( // API UnregisterClass
  8071. IN PUNICODE_STRING pstrClassName,
  8072. IN HINSTANCE hInstance,
  8073. OUT PCLSMENUNAME pcmn)
  8074. {
  8075. UNICODE_STRING strClassName;
  8076. CLSMENUNAME cmn;
  8077. BEGINRECV(BOOL, FALSE);
  8078. /*
  8079. * Probe arguments
  8080. */
  8081. try {
  8082. strClassName = ProbeAndReadUnicodeString(pstrClassName);
  8083. ProbeForReadUnicodeStringBufferOrId(strClassName);
  8084. } except (StubExceptionHandler(TRUE)) {
  8085. MSGERROR(0);
  8086. }
  8087. /*
  8088. * The buffer is in client-side memory.
  8089. */
  8090. retval = _UnregisterClass(
  8091. strClassName.Buffer,
  8092. hInstance,
  8093. &cmn);
  8094. try {
  8095. ProbeAndWriteStructure(pcmn, cmn, CLSMENUNAME);
  8096. } except (StubExceptionHandler(FALSE)) {
  8097. // no SetLastError, since pcmn is a USER address, not the application's
  8098. }
  8099. TRACE("NtUserUnregisterClass");
  8100. ENDRECV();
  8101. }
  8102. SHORT NtUserVkKeyScanEx(
  8103. IN WCHAR cChar,
  8104. IN ULONG_PTR dwHKLorPKL,
  8105. IN BOOL bHKL)
  8106. {
  8107. PKL pkl;
  8108. BEGINRECV_SHARED(SHORT, -1);
  8109. /*
  8110. * See if we need to convert an HKL to a PKL. VkKeyScan passes a PKL and
  8111. * VkKeyScanEx passes an HKL. The conversion must be done on the server side.
  8112. */
  8113. if (bHKL) {
  8114. pkl = HKLtoPKL(PtiCurrentShared(), (HKL)dwHKLorPKL);
  8115. } else {
  8116. pkl = PtiCurrentShared()->spklActive;
  8117. }
  8118. if (pkl == NULL) {
  8119. retval = (SHORT)-1;
  8120. } else {
  8121. retval = InternalVkKeyScanEx(cChar, pkl->spkf->pKbdTbl);
  8122. }
  8123. TRACE("NtUserVkKeyScanEx");
  8124. ENDRECV_SHARED();
  8125. }
  8126. NTSTATUS
  8127. NtUserEnumDisplayDevices(
  8128. IN PUNICODE_STRING pstrDeviceName,
  8129. IN DWORD iDevNum,
  8130. IN OUT LPDISPLAY_DEVICEW lpDisplayDevice,
  8131. IN DWORD dwFlags)
  8132. {
  8133. BEGINRECV(NTSTATUS, STATUS_UNSUCCESSFUL);
  8134. /*
  8135. * We need to syncrhonize with session switching from local to remote or
  8136. * remote to local while enumerating display settings. Use
  8137. * UserSessionSwitchEnterCrit() to ensure mutual exclusion with session
  8138. * switch code, but first leave the User critical section as
  8139. * UserSessionSwitchEnterCrit() does not expect to be held by the caller.
  8140. * On return from UserSessionSwitchEnterCrit() the critical section will be
  8141. * held.
  8142. */
  8143. LeaveCrit();
  8144. retval = UserSessionSwitchEnterCrit();
  8145. if (retval != STATUS_SUCCESS) {
  8146. goto exit_api;
  8147. }
  8148. /*
  8149. * Update the list of devices. Do this only if connected to local console.
  8150. * If the function returns FALSE (retry update), then we must
  8151. * disable the current hdev, call back, and reanable the hdev.
  8152. */
  8153. if (!IsRemoteConnection()) {
  8154. if (DrvUpdateGraphicsDeviceList(FALSE, FALSE, TRUE) == FALSE) {
  8155. if (SafeDisableMDEV()) {
  8156. DrvUpdateGraphicsDeviceList(TRUE, FALSE, TRUE);
  8157. SafeEnableMDEV();
  8158. /*
  8159. * Repaint the screen
  8160. */
  8161. xxxUserResetDisplayDevice();
  8162. /*
  8163. * xxxUserResetDisplayDevice may have released and reaquiered the user critical section.
  8164. * We need to make sure again that no session switch has started during that window.
  8165. */
  8166. LeaveCrit();
  8167. retval = UserSessionSwitchEnterCrit();
  8168. if (retval != STATUS_SUCCESS) {
  8169. goto exit_api;
  8170. }
  8171. }
  8172. }
  8173. }
  8174. /*
  8175. * Address checking, etc., occurs in GRE.
  8176. */
  8177. retval = DrvEnumDisplayDevices(pstrDeviceName,
  8178. gpDispInfo->pMonitorPrimary->hDev,
  8179. iDevNum,
  8180. lpDisplayDevice,
  8181. dwFlags,
  8182. UserMode);
  8183. UserSessionSwitchLeaveCrit();
  8184. exit_api:
  8185. EnterCrit();
  8186. TRACE("NtUserEnumDisplayDevices");
  8187. ENDRECV();
  8188. }
  8189. NTSTATUS
  8190. NtUserEnumDisplaySettings(
  8191. IN PUNICODE_STRING pstrDeviceName,
  8192. IN DWORD iModeNum,
  8193. OUT LPDEVMODEW lpDevMode,
  8194. IN DWORD dwFlags)
  8195. {
  8196. BEGINRECV(NTSTATUS, STATUS_UNSUCCESSFUL);
  8197. /*
  8198. * We need to synchronize with session switching from local to remote or
  8199. * remote to local while enumerating display settings. Use
  8200. * UserSessionSwitchEnterCrit() to ensure mutual exclusion with session
  8201. * switch code, but first leave the User critical section as
  8202. * UserSessionSwitchEnterCrit() does not expect to be held by the caller.
  8203. * On return from UserSessionSwitchEnterCrit() the critical section will be
  8204. * held.
  8205. *
  8206. * Address checking, etc., occurs in GRE.
  8207. */
  8208. LeaveCrit();
  8209. retval = UserSessionSwitchEnterCrit();
  8210. if (retval != STATUS_SUCCESS) {
  8211. goto exit_api;
  8212. }
  8213. retval = DrvEnumDisplaySettings(pstrDeviceName,
  8214. gpDispInfo->pMonitorPrimary->hDev,
  8215. iModeNum,
  8216. lpDevMode,
  8217. dwFlags);
  8218. UserSessionSwitchLeaveCrit();
  8219. exit_api:
  8220. EnterCrit();
  8221. TRACE("NtUserEnumDisplaySettings");
  8222. ENDRECV();
  8223. }
  8224. #ifdef PRERELEASE
  8225. PTHREADINFO gptiLastChangedDisplaySettings;
  8226. #endif
  8227. LONG
  8228. NtUserChangeDisplaySettings(
  8229. IN PUNICODE_STRING pstrDeviceName,
  8230. IN LPDEVMODEW pDevMode,
  8231. IN DWORD dwFlags,
  8232. IN PVOID lParam)
  8233. {
  8234. BEGINRECV(LONG, DISP_CHANGE_FAILED);
  8235. /*
  8236. * Prevent restricted threads from changing display settings.
  8237. */
  8238. if (IS_CURRENT_THREAD_RESTRICTED(JOB_OBJECT_UILIMIT_DISPLAYSETTINGS)) {
  8239. MSGERROR(0);
  8240. }
  8241. #ifdef PRERELEASE
  8242. /*
  8243. * Remember the last guy who tried to change the display settings
  8244. * (per the request from the shell team).
  8245. * N.b. it doesn't care if the call was succeeded or not.
  8246. */
  8247. gptiLastChangedDisplaySettings = PtiCurrent();
  8248. #endif
  8249. /*
  8250. * Address checking, etc., occurs in GRE.
  8251. */
  8252. retval = xxxUserChangeDisplaySettings(pstrDeviceName,
  8253. pDevMode,
  8254. NULL,
  8255. dwFlags,
  8256. lParam,
  8257. UserMode);
  8258. TRACE("NtUserChangeDisplaySettings");
  8259. ENDRECV();
  8260. }
  8261. BOOL NtUserCallMsgFilter( // API CallMsgFilterA/W
  8262. IN OUT LPMSG lpMsg,
  8263. IN int nCode)
  8264. {
  8265. MSG msg;
  8266. BEGINRECV(BOOL, FALSE);
  8267. /*
  8268. * Probe arguments
  8269. */
  8270. try {
  8271. ProbeForWriteMessage(lpMsg);
  8272. msg = *lpMsg;
  8273. } except (StubExceptionHandler(TRUE)) {
  8274. MSGERROR(0);
  8275. }
  8276. retval = _CallMsgFilter(
  8277. &msg,
  8278. nCode);
  8279. try {
  8280. *lpMsg = msg;
  8281. } except (StubExceptionHandler(TRUE)) {
  8282. MSGERROR(0);
  8283. }
  8284. TRACE("NtUserCallMsgFilter");
  8285. ENDRECV();
  8286. }
  8287. int NtUserDrawMenuBarTemp( // private DrawMenuBarTemp
  8288. IN HWND hwnd,
  8289. IN HDC hdc,
  8290. IN LPCRECT lprc,
  8291. IN HMENU hMenu,
  8292. IN HFONT hFont)
  8293. {
  8294. PMENU pMenu;
  8295. TL tlpMenu;
  8296. RECT rc;
  8297. BEGINRECV_HWNDLOCK(int, 0, hwnd);
  8298. /*
  8299. * Probe and capture arguments.
  8300. */
  8301. try {
  8302. rc = ProbeAndReadRect(lprc);
  8303. } except (StubExceptionHandler(FALSE)) {
  8304. MSGERROR(0);
  8305. }
  8306. ValidateHMENU(pMenu, hMenu);
  8307. ThreadLockAlwaysWithPti(ptiCurrent, pMenu, &tlpMenu);
  8308. retval = xxxDrawMenuBarTemp(
  8309. pwnd,
  8310. hdc,
  8311. &rc,
  8312. pMenu,
  8313. hFont);
  8314. ThreadUnlock(&tlpMenu);
  8315. TRACE("NtUserDrawMenuBarTemp");
  8316. ENDRECV_HWNDLOCK();
  8317. }
  8318. BOOL NtUserDrawCaptionTemp( // private DrawCaptionTempA/W
  8319. IN HWND hwnd,
  8320. IN HDC hdc,
  8321. IN LPCRECT lprc,
  8322. IN HFONT hFont,
  8323. IN HICON hIcon,
  8324. IN PUNICODE_STRING pstrText,
  8325. IN UINT flags)
  8326. {
  8327. PCURSOR pcur;
  8328. TL tlpcur;
  8329. RECT rc;
  8330. UNICODE_STRING strCapture;
  8331. PWND pwnd;
  8332. TL tlpwnd;
  8333. PTHREADINFO ptiCurrent;
  8334. TL tlBuffer;
  8335. BOOL fFreeBuffer = FALSE;
  8336. BEGINRECV(DWORD, FALSE);
  8337. ptiCurrent = PtiCurrent();
  8338. ValidateHWNDOPT(pwnd, hwnd);
  8339. ValidateHCURSOROPT(pcur, hIcon);
  8340. /*
  8341. * Probe and capture arguments. Capturing the text is ugly,
  8342. * but must be done because it is passed to GDI.
  8343. */
  8344. try {
  8345. rc = ProbeAndReadRect(lprc);
  8346. strCapture = ProbeAndReadUnicodeString(pstrText);
  8347. if (strCapture.Buffer != NULL) {
  8348. PWSTR pszCapture = strCapture.Buffer;
  8349. ProbeForRead(strCapture.Buffer, strCapture.Length, CHARALIGN);
  8350. strCapture.Buffer = UserAllocPoolWithQuota(strCapture.Length+sizeof(UNICODE_NULL), TAG_TEXT);
  8351. if (strCapture.Buffer != NULL) {
  8352. fFreeBuffer = TRUE;
  8353. ThreadLockPool(ptiCurrent, strCapture.Buffer, &tlBuffer);
  8354. RtlCopyMemory(strCapture.Buffer, pszCapture, strCapture.Length);
  8355. strCapture.Buffer[strCapture.Length/sizeof(WCHAR)]=0; // null-terminate string
  8356. strCapture.MaximumLength = strCapture.Length+sizeof(UNICODE_NULL);
  8357. pstrText = &strCapture;
  8358. } else {
  8359. ExRaiseStatus(STATUS_NO_MEMORY);
  8360. }
  8361. }
  8362. } except (StubExceptionHandler(FALSE)) {
  8363. MSGERRORCLEANUP(0);
  8364. }
  8365. ThreadLockWithPti(ptiCurrent, pwnd, &tlpwnd);
  8366. ThreadLockWithPti(ptiCurrent, pcur, &tlpcur);
  8367. retval = xxxDrawCaptionTemp(
  8368. pwnd,
  8369. hdc,
  8370. &rc,
  8371. hFont,
  8372. pcur,
  8373. strCapture.Buffer ? &strCapture : NULL,
  8374. flags);
  8375. ThreadUnlock(&tlpcur);
  8376. ThreadUnlock(&tlpwnd);
  8377. CLEANUPRECV();
  8378. if (fFreeBuffer)
  8379. ThreadUnlockAndFreePool(ptiCurrent, &tlBuffer);
  8380. TRACE("NtUserDrawCaptionTemp");
  8381. ENDRECV();
  8382. }
  8383. BOOL NtUserGetKeyboardState( // API GetKeyboardState
  8384. OUT PBYTE pb)
  8385. {
  8386. int i;
  8387. PQ pq;
  8388. BEGINRECV_SHARED(SHORT, 0)
  8389. /*
  8390. * Probe arguments
  8391. */
  8392. try {
  8393. ProbeForWrite(pb, 256, sizeof(BYTE));
  8394. pq = PtiCurrentShared()->pq;
  8395. for (i = 0; i < 256; i++, pb++) {
  8396. *pb = 0;
  8397. if (TestKeyStateDown(pq, i))
  8398. *pb |= 0x80;
  8399. if (TestKeyStateToggle(pq, i))
  8400. *pb |= 0x01;
  8401. }
  8402. retval = TRUE;
  8403. } except (StubExceptionHandler(TRUE)) {
  8404. MSGERROR(0);
  8405. }
  8406. ENDRECV_SHARED();
  8407. }
  8408. SHORT NtUserGetKeyState(
  8409. IN int vk)
  8410. {
  8411. PTHREADINFO ptiCurrent;
  8412. BEGINRECV_SHARED(SHORT, 0)
  8413. ptiCurrent = PtiCurrentShared();
  8414. if (ptiCurrent->pq->QF_flags & QF_UPDATEKEYSTATE) {
  8415. /*
  8416. * We are going to change the system state, so we
  8417. * must have an exclusive lock
  8418. */
  8419. ChangeAcquireResourceType();
  8420. /*
  8421. * If this thread needs a key state event, give one to it. There are
  8422. * cases where any app may be looping looking at GetKeyState(), plus
  8423. * calling PeekMessage(). Key state events don't get created unless
  8424. * new hardware input comes along. If the app isn't receiving hardware
  8425. * input, it won't get the new key state. So ResyncKeyState() will
  8426. * ensure that if the app is looping on GetKeyState(), it'll get the
  8427. * right key state.
  8428. */
  8429. if (ptiCurrent->pq->QF_flags & QF_UPDATEKEYSTATE) {
  8430. PostUpdateKeyStateEvent(ptiCurrent->pq);
  8431. }
  8432. }
  8433. retval = _GetKeyState(vk);
  8434. /*
  8435. * Update the client side key state cache.
  8436. */
  8437. try {
  8438. ptiCurrent->pClientInfo->dwKeyCache = gpsi->dwKeyCache;
  8439. RtlCopyMemory(ptiCurrent->pClientInfo->afKeyState,
  8440. ptiCurrent->pq->afKeyState,
  8441. CBKEYCACHE);
  8442. } except (StubExceptionHandler(TRUE)) {
  8443. MSGERROR(0);
  8444. }
  8445. ENDRECV_SHARED();
  8446. }
  8447. /**************************************************************************\
  8448. * NtUserQueryWindow
  8449. *
  8450. * 03-18-95 JimA Created.
  8451. \**************************************************************************/
  8452. HANDLE NtUserQueryWindow(
  8453. IN HWND hwnd,
  8454. IN WINDOWINFOCLASS WindowInfo)
  8455. {
  8456. PTHREADINFO ptiWnd;
  8457. BEGINRECV_HWND_SHARED(HANDLE, NULL, hwnd);
  8458. ptiWnd = GETPTI(pwnd);
  8459. switch (WindowInfo) {
  8460. case WindowProcess:
  8461. /*
  8462. * Special case console windows
  8463. */
  8464. if (ptiWnd->TIF_flags & TIF_CSRSSTHREAD &&
  8465. pwnd->pcls->atomClassName == gatomConsoleClass) {
  8466. retval = LongToHandle(_GetWindowLong(pwnd, 0));
  8467. } else {
  8468. retval = PsGetThreadProcessId(ptiWnd->pEThread);
  8469. }
  8470. break;
  8471. case WindowThread:
  8472. /*
  8473. * Special case console windows
  8474. */
  8475. if (ptiWnd->TIF_flags & TIF_CSRSSTHREAD &&
  8476. pwnd->pcls->atomClassName == gatomConsoleClass) {
  8477. retval = LongToHandle(_GetWindowLong(pwnd, 4));
  8478. } else {
  8479. retval = GETPTIID(ptiWnd);
  8480. }
  8481. break;
  8482. case WindowActiveWindow:
  8483. retval = (HANDLE)HW(ptiWnd->pq->spwndActive);
  8484. break;
  8485. case WindowFocusWindow:
  8486. retval = (HANDLE)HW(ptiWnd->pq->spwndFocus);
  8487. break;
  8488. case WindowIsHung:
  8489. /*
  8490. * If the window is a ghost window, report that the window is hung.
  8491. */
  8492. if ((GETFNID(pwnd) == FNID_GHOST)) {
  8493. retval = LongToHandle(TRUE);
  8494. } else {
  8495. retval = LongToHandle(FHungApp(ptiWnd, CMSHUNGAPPTIMEOUT));
  8496. }
  8497. break;
  8498. case WindowIsForegroundThread:
  8499. retval = LongToHandle(ptiWnd->pq == gpqForeground);
  8500. break;
  8501. case WindowDefaultImeWindow:
  8502. retval = HW(ptiWnd->spwndDefaultIme);
  8503. break;
  8504. case WindowDefaultInputContext:
  8505. retval = PtoH(ptiWnd->spDefaultImc);
  8506. break;
  8507. default:
  8508. RIPMSG1(RIP_WARNING,
  8509. "QueryWindow called with invalid index 0x%x",
  8510. WindowInfo);
  8511. retval = (HANDLE)NULL;
  8512. break;
  8513. }
  8514. ENDRECV_HWND_SHARED();
  8515. }
  8516. BOOL NtUserSBGetParms( // API GetScrollInfo, SBM_GETSCROLLINFO
  8517. IN HWND hwnd,
  8518. IN int code,
  8519. IN PSBDATA pw,
  8520. IN OUT LPSCROLLINFO lpsi)
  8521. {
  8522. SBDATA sbd;
  8523. SCROLLINFO si;
  8524. BEGINRECV_HWND_SHARED(BOOL, FALSE, hwnd);
  8525. /*
  8526. * Probe arguments
  8527. */
  8528. try {
  8529. ProbeForWriteScrollInfo(lpsi);
  8530. /*
  8531. * Probe the 4 DWORDS (MIN, MAX, PAGE, POS)
  8532. */
  8533. ProbeForRead(pw, sizeof(SBDATA), sizeof(DWORD));
  8534. RtlCopyMemory(&sbd, pw, sizeof(sbd));
  8535. RtlCopyMemory(&si, lpsi, sizeof(SCROLLINFO));
  8536. } except (StubExceptionHandler(TRUE)) {
  8537. MSGERROR(0);
  8538. }
  8539. retval = _SBGetParms(pwnd, code, &sbd, &si);
  8540. try {
  8541. RtlCopyMemory(lpsi, &si, sizeof(SCROLLINFO));
  8542. } except (StubExceptionHandler(TRUE)) {
  8543. MSGERROR(0);
  8544. }
  8545. ENDRECV_HWND_SHARED();
  8546. }
  8547. BOOL NtUserBitBltSysBmp(
  8548. IN HDC hdc,
  8549. IN int xDest,
  8550. IN int yDest,
  8551. IN int cxDest,
  8552. IN int cyDest,
  8553. IN int xSrc,
  8554. IN int ySrc,
  8555. IN DWORD dwRop)
  8556. {
  8557. BEGINRECV(BOOL, FALSE);
  8558. /*
  8559. * Note: This interface requires exclusive ownership of the User crit
  8560. * sect in order to serialize use of HDCBITS. Only one thread at a time
  8561. * may use a DC.
  8562. */
  8563. retval = GreBitBlt(hdc,
  8564. xDest,
  8565. yDest,
  8566. cxDest,
  8567. cyDest,
  8568. HDCBITS(),
  8569. xSrc,
  8570. ySrc,
  8571. dwRop,
  8572. 0);
  8573. ENDRECV();
  8574. }
  8575. HPALETTE NtUserSelectPalette(
  8576. IN HDC hdc,
  8577. IN HPALETTE hpalette,
  8578. IN BOOL fForceBackground)
  8579. {
  8580. BEGINRECV(HPALETTE, NULL)
  8581. retval = _SelectPalette(hdc, hpalette, fForceBackground);
  8582. ENDRECV();
  8583. }
  8584. /*
  8585. * Message thunks
  8586. */
  8587. LRESULT NtUserMessageCall(
  8588. IN HWND hwnd,
  8589. IN UINT msg,
  8590. IN WPARAM wParam,
  8591. IN LPARAM lParam,
  8592. IN ULONG_PTR xParam,
  8593. IN DWORD xpfnProc,
  8594. IN BOOL bAnsi)
  8595. {
  8596. BEGINRECV_HWNDLOCKFF(LRESULT, 0, hwnd, xpfnProc);
  8597. if ((msg & ~MSGFLAG_MASK) >= WM_USER) {
  8598. retval = CALLPROC(xpfnProc)(
  8599. pwnd,
  8600. msg,
  8601. wParam,
  8602. lParam,
  8603. xParam);
  8604. } else {
  8605. retval = gapfnMessageCall[MessageTable[(msg & ~MSGFLAG_MASK)].iFunction](
  8606. pwnd,
  8607. msg,
  8608. wParam,
  8609. lParam,
  8610. xParam,
  8611. xpfnProc,
  8612. bAnsi);
  8613. }
  8614. TRACE("NtUserMessageCall");
  8615. ENDRECV_HWNDLOCKFF();
  8616. }
  8617. MESSAGECALL(DWORD)
  8618. {
  8619. BEGINRECV_MESSAGECALL(0);
  8620. TRACETHUNK("fnDWORD");
  8621. UNREFERENCED_PARAMETER(bAnsi);
  8622. retval = CALLPROC(xpfnProc)(
  8623. pwnd,
  8624. msg,
  8625. wParam,
  8626. lParam,
  8627. xParam);
  8628. TRACE("fnDWORD");
  8629. ENDRECV_MESSAGECALL();
  8630. }
  8631. MESSAGECALL(NCDESTROY)
  8632. {
  8633. BEGINRECV_MESSAGECALL(0);
  8634. TRACETHUNK("fnNCDESTROY");
  8635. UNREFERENCED_PARAMETER(bAnsi);
  8636. retval = CALLPROC(xpfnProc)(
  8637. pwnd,
  8638. msg,
  8639. wParam,
  8640. lParam,
  8641. xParam);
  8642. TRACE("fnNCDESTROY");
  8643. ENDRECV_MESSAGECALL();
  8644. }
  8645. MESSAGECALL(OPTOUTLPDWORDOPTOUTLPDWORD)
  8646. {
  8647. DWORD dwwParam, dwlParam;
  8648. BEGINRECV_MESSAGECALL(0);
  8649. TRACETHUNK("fnOPTOUTLPDWORDOPTOUTLPDWORD");
  8650. UNREFERENCED_PARAMETER(bAnsi);
  8651. retval = CALLPROC(xpfnProc)(
  8652. pwnd,
  8653. msg,
  8654. (WPARAM)&dwwParam,
  8655. (LPARAM)&dwlParam,
  8656. xParam);
  8657. /*
  8658. * Probe arguments
  8659. */
  8660. try {
  8661. if (ARGUMENT_PRESENT(wParam)) {
  8662. ProbeAndWriteUlong((PULONG)wParam, dwwParam);
  8663. }
  8664. if (ARGUMENT_PRESENT(lParam)) {
  8665. ProbeAndWriteUlong((PULONG)lParam, dwlParam);
  8666. }
  8667. } except (StubExceptionHandler(TRUE)) {
  8668. MSGERROR(0); // should messages with bad wParam/lParam SetLastError?
  8669. }
  8670. TRACE("fnOPTOUTLPDWORDOPTOUTLPDWORD");
  8671. ENDRECV_MESSAGECALL();
  8672. }
  8673. MESSAGECALL(INOUTNEXTMENU)
  8674. {
  8675. MDINEXTMENU mnm;
  8676. BEGINRECV_MESSAGECALL(0);
  8677. TRACETHUNK("fnINOUTNEXTMENU");
  8678. UNREFERENCED_PARAMETER(bAnsi);
  8679. /*
  8680. * Probe arguments
  8681. */
  8682. try {
  8683. ProbeForWriteMDINextMenu((PMDINEXTMENU)lParam);
  8684. mnm = *(PMDINEXTMENU)lParam;
  8685. } except (StubExceptionHandler(FALSE)) {
  8686. MSGERROR(0);
  8687. }
  8688. retval = CALLPROC(xpfnProc)(
  8689. pwnd,
  8690. msg,
  8691. wParam,
  8692. (LPARAM)&mnm,
  8693. xParam);
  8694. try {
  8695. *(PMDINEXTMENU)lParam = mnm;
  8696. } except (StubExceptionHandler(FALSE)) {
  8697. }
  8698. TRACE("fnINOUTNEXTMENU");
  8699. ENDRECV_MESSAGECALL();
  8700. }
  8701. MESSAGECALL(DWORDOPTINLPMSG)
  8702. {
  8703. MSG msgstruct;
  8704. BEGINRECV_MESSAGECALL(0);
  8705. TRACETHUNK("fnDWORDOPTINLPMSG");
  8706. UNREFERENCED_PARAMETER(bAnsi);
  8707. /*
  8708. * Probe arguments
  8709. */
  8710. try {
  8711. if (ARGUMENT_PRESENT(lParam)) {
  8712. msgstruct = ProbeAndReadMessage((LPMSG)lParam);
  8713. lParam = (LPARAM)&msgstruct;
  8714. }
  8715. } except (StubExceptionHandler(FALSE)) {
  8716. MSGERROR(0);
  8717. }
  8718. retval = CALLPROC(xpfnProc)(
  8719. pwnd,
  8720. msg,
  8721. wParam,
  8722. lParam,
  8723. xParam);
  8724. TRACE("fnDWORDOPTINLPMSG");
  8725. ENDRECV_MESSAGECALL();
  8726. }
  8727. MESSAGECALL(COPYGLOBALDATA)
  8728. {
  8729. BEGINRECV_MESSAGECALL(0);
  8730. TRACETHUNK("fnCOPYGLOBALDATA");
  8731. UNREFERENCED_PARAMETER(bAnsi);
  8732. /*
  8733. * Probe arguments
  8734. */
  8735. try {
  8736. ProbeForRead((PVOID)lParam, wParam, sizeof(BYTE));
  8737. } except (StubExceptionHandler(FALSE)) {
  8738. MSGERROR(0);
  8739. }
  8740. /*
  8741. * !!! Data pointed to by lParam must be captured
  8742. * in xxxInterSendMsgEx
  8743. */
  8744. retval = CALLPROC(xpfnProc)(
  8745. pwnd,
  8746. msg,
  8747. wParam,
  8748. lParam,
  8749. xParam);
  8750. TRACE("fnCOPYGLOBALDATA");
  8751. ENDRECV_MESSAGECALL();
  8752. }
  8753. MESSAGECALL(COPYDATA)
  8754. {
  8755. COPYDATASTRUCT cds;
  8756. BEGINRECV_MESSAGECALL(0);
  8757. TRACETHUNK("fnCOPYDATA");
  8758. UNREFERENCED_PARAMETER(bAnsi);
  8759. /*
  8760. * Probe arguments
  8761. */
  8762. try {
  8763. if (ARGUMENT_PRESENT(lParam)) {
  8764. cds = ProbeAndReadCopyDataStruct((PCOPYDATASTRUCT)lParam);
  8765. if (cds.lpData)
  8766. ProbeForRead(cds.lpData, cds.cbData, sizeof(BYTE));
  8767. lParam = (LPARAM)&cds;
  8768. }
  8769. } except (StubExceptionHandler(FALSE)) {
  8770. MSGERROR(0);
  8771. }
  8772. /*
  8773. * !!! Data pointed to by cds.lpData must be captured
  8774. * in xxxInterSendMsgEx
  8775. */
  8776. retval = CALLPROC(xpfnProc)(
  8777. pwnd,
  8778. msg,
  8779. wParam,
  8780. lParam,
  8781. xParam);
  8782. TRACE("fnCOPYDATA");
  8783. ENDRECV_MESSAGECALL();
  8784. }
  8785. MESSAGECALL(SENTDDEMSG)
  8786. {
  8787. BEGINRECV_MESSAGECALL(0);
  8788. TRACETHUNK("fnSENTDDEMSG");
  8789. UNREFERENCED_PARAMETER(bAnsi);
  8790. if (xpfnProc == FNID_CALLWINDOWPROC) {
  8791. retval = CALLPROC(xpfnProc)(pwnd,
  8792. msg | MSGFLAG_DDE_SPECIAL_SEND,
  8793. wParam, lParam, xParam);
  8794. } else if ((ptiCurrent->TIF_flags & TIF_16BIT) &&
  8795. (ptiCurrent->ptdb) &&
  8796. (ptiCurrent->ptdb->hTaskWow)) {
  8797. /*
  8798. * Note that this function may modify msg by ORing in a bit in the
  8799. * high word. This bit is ignored when thunking messages.
  8800. * This allows the DdeTrackSendMessage() hook to be skipped - which
  8801. * would cause an error - and instead allows this thunk to carry
  8802. * the message all the way across.
  8803. */
  8804. retval = xxxDDETrackPostHook(&msg, pwnd, wParam, &lParam, TRUE);
  8805. switch (retval) {
  8806. case DO_POST:
  8807. /*
  8808. * Or in the MSGFLAG_DDE_SPECIAL_SEND so that
  8809. * xxxSendMessageTimeout() will not pass this on to
  8810. * xxxDdeTrackSendMsg() which would think it was evil.
  8811. *
  8812. * Since the SendMessage() thunks ignore the reserved bits
  8813. * it will still get maped to the fnSENTDDEMSG callback thunk.
  8814. */
  8815. retval = CALLPROC(xpfnProc)(pwnd,
  8816. msg | MSGFLAG_DDE_SPECIAL_SEND,
  8817. wParam, lParam, xParam);
  8818. break;
  8819. case FAKE_POST:
  8820. case FAIL_POST:
  8821. retval = 0;
  8822. }
  8823. } else {
  8824. MSGERROR(0);
  8825. }
  8826. TRACE("fnSENTDDEMSG");
  8827. ENDRECV_MESSAGECALL();
  8828. }
  8829. MESSAGECALL(DDEINIT)
  8830. {
  8831. PWND pwndFrom;
  8832. TL tlpwndFrom;
  8833. PDDEIMP pddei;
  8834. PSECURITY_QUALITY_OF_SERVICE pqos;
  8835. NTSTATUS Status;
  8836. BEGINRECV_MESSAGECALL(0);
  8837. TRACETHUNK("fnDDEINIT");
  8838. UNREFERENCED_PARAMETER(bAnsi);
  8839. ValidateHWND(pwndFrom, (HWND)wParam);
  8840. ThreadLockAlwaysWithPti(ptiCurrent, pwndFrom, &tlpwndFrom);
  8841. /*
  8842. * Create temporary DDEIMP property for client window - this stays around
  8843. * only during the initiate phase.
  8844. */
  8845. if ((pddei = (PDDEIMP)_GetProp(pwndFrom, PROP_DDEIMP, TRUE))
  8846. == NULL) {
  8847. pddei = (PDDEIMP)UserAllocPoolWithQuota(sizeof(DDEIMP), TAG_DDEd);
  8848. if (pddei == NULL) {
  8849. RIPERR0(ERROR_NOT_ENOUGH_MEMORY, RIP_WARNING, "fnDDEINIT: LocalAlloc failed.");
  8850. MSGERRORCLEANUP(0);
  8851. }
  8852. pqos = (PSECURITY_QUALITY_OF_SERVICE)_GetProp(pwndFrom, PROP_QOS, TRUE);
  8853. if (pqos == NULL) {
  8854. pqos = &gqosDefault;
  8855. }
  8856. pddei->qos = *pqos;
  8857. Status = SeCreateClientSecurity(PsGetCurrentThread(),
  8858. pqos, FALSE, &pddei->ClientContext);
  8859. if (!NT_SUCCESS(Status)) {
  8860. RIPMSG0(RIP_WARNING, "SeCreateClientContext failed.");
  8861. UserFreePool(pddei);
  8862. MSGERRORCLEANUP(0);
  8863. }
  8864. pddei->cRefInit = 1;
  8865. pddei->cRefConv = 0;
  8866. InternalSetProp(pwndFrom, PROP_DDEIMP, pddei, PROPF_INTERNAL);
  8867. } else {
  8868. pddei->cRefInit++; // cover broadcast case!
  8869. }
  8870. retval = CALLPROC(xpfnProc)(
  8871. pwnd,
  8872. msg,
  8873. wParam,
  8874. lParam,
  8875. xParam);
  8876. /*
  8877. * Reaquire pddei incase pwndFrom was destroyed.
  8878. */
  8879. pddei = (PDDEIMP)_GetProp(pwndFrom, PROP_DDEIMP, TRUE);
  8880. if (pddei != NULL) {
  8881. /*
  8882. * Decrement reference count from DDEImpersonate property and remove property.
  8883. */
  8884. pddei->cRefInit--;
  8885. if (pddei->cRefInit == 0) {
  8886. InternalRemoveProp(pwndFrom, PROP_DDEIMP, TRUE);
  8887. if (pddei->cRefConv == 0) {
  8888. SeDeleteClientSecurity(&pddei->ClientContext);
  8889. UserFreePool(pddei);
  8890. }
  8891. }
  8892. }
  8893. CLEANUPRECV();
  8894. ThreadUnlock(&tlpwndFrom);
  8895. TRACE("fnDDEINIT");
  8896. ENDRECV_MESSAGECALL();
  8897. }
  8898. MESSAGECALL(INPAINTCLIPBRD)
  8899. {
  8900. PAINTSTRUCT ps;
  8901. BEGINRECV_MESSAGECALL(0);
  8902. TRACETHUNK("fnINPAINTCLIPBRD");
  8903. UNREFERENCED_PARAMETER(bAnsi);
  8904. /*
  8905. * Probe arguments
  8906. */
  8907. try {
  8908. ps = ProbeAndReadPaintStruct((PPAINTSTRUCT)lParam);
  8909. } except (StubExceptionHandler(FALSE)) {
  8910. MSGERROR(0);
  8911. }
  8912. retval = CALLPROC(xpfnProc)(
  8913. pwnd,
  8914. msg,
  8915. wParam,
  8916. (LPARAM)&ps,
  8917. xParam);
  8918. TRACE("fnINPAINTCLIPBRD");
  8919. ENDRECV_MESSAGECALL();
  8920. }
  8921. MESSAGECALL(INSIZECLIPBRD)
  8922. {
  8923. RECT rc;
  8924. BEGINRECV_MESSAGECALL(0);
  8925. TRACETHUNK("fnINSIZECLIPBRD");
  8926. UNREFERENCED_PARAMETER(bAnsi);
  8927. /*
  8928. * Probe arguments
  8929. */
  8930. try {
  8931. rc = ProbeAndReadRect((PRECT)lParam);
  8932. } except (StubExceptionHandler(FALSE)) {
  8933. MSGERROR(0);
  8934. }
  8935. retval = CALLPROC(xpfnProc)(
  8936. pwnd,
  8937. msg,
  8938. wParam,
  8939. (LPARAM)&rc,
  8940. xParam);
  8941. TRACE("fnINSIZECLIPBRD");
  8942. ENDRECV_MESSAGECALL();
  8943. }
  8944. MESSAGECALL(INOUTDRAG)
  8945. {
  8946. DROPSTRUCT ds;
  8947. BEGINRECV_MESSAGECALL(0);
  8948. TRACETHUNK("fnINOUTDRAG");
  8949. UNREFERENCED_PARAMETER(bAnsi);
  8950. /*
  8951. * Probe arguments
  8952. */
  8953. try {
  8954. ProbeForWriteDropStruct((PDROPSTRUCT)lParam);
  8955. ds = *(PDROPSTRUCT)lParam;
  8956. } except (StubExceptionHandler(FALSE)) {
  8957. MSGERROR(0);
  8958. }
  8959. retval = CALLPROC(xpfnProc)(
  8960. pwnd,
  8961. msg,
  8962. wParam,
  8963. (LPARAM)&ds,
  8964. xParam);
  8965. try {
  8966. *(PDROPSTRUCT)lParam = ds;
  8967. } except (StubExceptionHandler(FALSE)) {
  8968. }
  8969. TRACE("fnINOUTDRAG");
  8970. ENDRECV_MESSAGECALL();
  8971. }
  8972. MESSAGECALL(GETDBCSTEXTLENGTHS)
  8973. {
  8974. BEGINRECV_MESSAGECALL(0);
  8975. TRACETHUNK("fnGETDBCSTEXTLENGTHS");
  8976. UNREFERENCED_PARAMETER(lParam);
  8977. /*
  8978. * This is used by L/CB_GETTEXTLEN which should return -1 (L/CB_ERR)
  8979. * on error. If any error code path is introduced here, make sure we return the
  8980. * proper value.This is also used by WM_GETTEXTLEN.
  8981. */
  8982. retval = CALLPROC(xpfnProc)(
  8983. pwnd,
  8984. msg,
  8985. wParam,
  8986. bAnsi,
  8987. xParam);
  8988. TRACE("fnGETDBCSTEXTLENGTHS");
  8989. ENDRECV_MESSAGECALL();
  8990. }
  8991. MESSAGECALL(INLPCREATESTRUCT)
  8992. {
  8993. CREATESTRUCTEX csex;
  8994. BEGINRECV_MESSAGECALL(0);
  8995. TRACETHUNK("fnINLPCREATESTRUCT");
  8996. if (ARGUMENT_PRESENT(lParam)) {
  8997. try {
  8998. csex.cs = ProbeAndReadCreateStruct((LPCREATESTRUCTW)lParam);
  8999. if (bAnsi) {
  9000. ProbeForRead(csex.cs.lpszName, sizeof(CHAR), sizeof(CHAR));
  9001. RtlInitLargeAnsiString((PLARGE_ANSI_STRING)&csex.strName,
  9002. (LPSTR)csex.cs.lpszName, (UINT)-1);
  9003. if (IS_PTR(csex.cs.lpszClass)) {
  9004. ProbeForRead(csex.cs.lpszClass, sizeof(CHAR), sizeof(CHAR));
  9005. RtlInitLargeAnsiString((PLARGE_ANSI_STRING)&csex.strClass,
  9006. (LPSTR)csex.cs.lpszClass, (UINT)-1);
  9007. }
  9008. } else {
  9009. ProbeForRead(csex.cs.lpszName, sizeof(WCHAR), CHARALIGN);
  9010. RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)&csex.strName,
  9011. csex.cs.lpszName, (UINT)-1);
  9012. if (IS_PTR(csex.cs.lpszClass)) {
  9013. ProbeForRead(csex.cs.lpszClass, sizeof(WCHAR), CHARALIGN);
  9014. RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)&csex.strClass,
  9015. csex.cs.lpszClass, (UINT)-1);
  9016. }
  9017. }
  9018. } except (StubExceptionHandler(FALSE)) {
  9019. MSGERROR(0);
  9020. }
  9021. }
  9022. /*
  9023. * Per Win95, do not allow NULL lpcreatestructs for WM_NCCREATE [51986]
  9024. * Allowed for WM_CREATE in Win95 for ObjectVision
  9025. */
  9026. else if (msg == WM_NCCREATE) {
  9027. MSGERROR(0) ;
  9028. }
  9029. /*
  9030. * !!! Strings pointed to by cs.cs must be captured in xxxInterSendMsgEx
  9031. */
  9032. retval = CALLPROC(xpfnProc)(
  9033. pwnd,
  9034. msg,
  9035. wParam,
  9036. lParam ? (LPARAM)&csex : 0,
  9037. xParam);
  9038. TRACE("fnINLPCREATESTRUCT");
  9039. ENDRECV_MESSAGECALL();
  9040. }
  9041. MESSAGECALL(INLPMDICREATESTRUCT)
  9042. {
  9043. MDICREATESTRUCTEX mdics;
  9044. BEGINRECV_MESSAGECALL(0);
  9045. TRACETHUNK("fnINLPMDICREATESTRUCT");
  9046. /*
  9047. * Probe arguments
  9048. */
  9049. try {
  9050. mdics.mdics = ProbeAndReadMDICreateStruct((LPMDICREATESTRUCTW)lParam);
  9051. if (bAnsi) {
  9052. ProbeForRead(mdics.mdics.szTitle, sizeof(CHAR), sizeof(CHAR));
  9053. RtlInitLargeAnsiString((PLARGE_ANSI_STRING)&mdics.strTitle,
  9054. (LPSTR)mdics.mdics.szTitle, (UINT)-1);
  9055. if (IS_PTR(mdics.mdics.szClass)) {
  9056. ProbeForRead(mdics.mdics.szClass, sizeof(CHAR), sizeof(CHAR));
  9057. RtlInitLargeAnsiString((PLARGE_ANSI_STRING)&mdics.strClass,
  9058. (LPSTR)mdics.mdics.szClass, (UINT)-1);
  9059. } else {
  9060. /*
  9061. * mdics.mdics.szClass may be Atom.
  9062. */
  9063. RtlInitLargeAnsiString((PLARGE_ANSI_STRING)&mdics.strClass,
  9064. NULL, 0);
  9065. }
  9066. } else {
  9067. ProbeForRead(mdics.mdics.szTitle, sizeof(WCHAR), CHARALIGN);
  9068. RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)&mdics.strTitle,
  9069. mdics.mdics.szTitle, (UINT)-1);
  9070. if (IS_PTR(mdics.mdics.szClass)) {
  9071. ProbeForRead(mdics.mdics.szClass, sizeof(WCHAR), CHARALIGN);
  9072. RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)&mdics.strClass,
  9073. mdics.mdics.szClass, (UINT)-1);
  9074. } else {
  9075. /*
  9076. * mdics.mdics.szClass may be Atom.
  9077. */
  9078. RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)&mdics.strClass,
  9079. NULL, 0);
  9080. }
  9081. }
  9082. } except (StubExceptionHandler(FALSE)) {
  9083. MSGERROR(0);
  9084. }
  9085. /*
  9086. * !!! Strings pointed to by mdics must be captured in xxxInterSendMsgEx
  9087. */
  9088. retval = CALLPROC(xpfnProc)(
  9089. pwnd,
  9090. msg,
  9091. wParam,
  9092. (LPARAM)&mdics,
  9093. xParam);
  9094. TRACE("fnINLPMDICREATESTRUCT");
  9095. ENDRECV_MESSAGECALL();
  9096. }
  9097. MESSAGECALL(INOUTLPSCROLLINFO)
  9098. {
  9099. SCROLLINFO scrollinfo;
  9100. BEGINRECV_MESSAGECALL(0);
  9101. TRACETHUNK("fnINOUTLPSCROLLINFO");
  9102. UNREFERENCED_PARAMETER(bAnsi);
  9103. /*
  9104. * Probe arguments
  9105. */
  9106. try {
  9107. ProbeForWriteScrollInfo((LPSCROLLINFO)lParam);
  9108. scrollinfo = *(LPSCROLLINFO)lParam;
  9109. } except (StubExceptionHandler(FALSE)) {
  9110. MSGERROR(0);
  9111. }
  9112. retval = CALLPROC(xpfnProc)(
  9113. pwnd,
  9114. msg,
  9115. wParam,
  9116. (LPARAM)&scrollinfo,
  9117. xParam);
  9118. try {
  9119. *(LPSCROLLINFO)lParam = scrollinfo;
  9120. } except (StubExceptionHandler(FALSE)) {
  9121. }
  9122. TRACE("fnINOUTLPSCROLLINFO");
  9123. ENDRECV_MESSAGECALL();
  9124. }
  9125. MESSAGECALL(INOUTLPPOINT5)
  9126. {
  9127. POINT5 pt5;
  9128. BEGINRECV_MESSAGECALL(0);
  9129. TRACETHUNK("fnINOUTLPPOINT5");
  9130. UNREFERENCED_PARAMETER(bAnsi);
  9131. /*
  9132. * Probe arguments
  9133. */
  9134. try {
  9135. ProbeForWritePoint5((LPPOINT5)lParam);
  9136. pt5 = *(LPPOINT5)lParam;
  9137. } except (StubExceptionHandler(FALSE)) {
  9138. MSGERROR(0);
  9139. }
  9140. retval = CALLPROC(xpfnProc)(
  9141. pwnd,
  9142. msg,
  9143. wParam,
  9144. (LPARAM)&pt5,
  9145. xParam);
  9146. try {
  9147. *(LPPOINT5)lParam = pt5;
  9148. } except (StubExceptionHandler(FALSE)) {
  9149. }
  9150. TRACE("fnINOUTLPPOINT5");
  9151. ENDRECV_MESSAGECALL();
  9152. }
  9153. MESSAGECALL(INSTRING)
  9154. {
  9155. LARGE_STRING str;
  9156. BEGINRECV_MESSAGECALL(0);
  9157. TRACETHUNK("fnINSTRING");
  9158. /*
  9159. * Don't allow any app to send a LB_DIR or CB_DIR with the postmsgs bit
  9160. * set (ObjectVision does this). This is because there is actually a legal
  9161. * case that we need to thunk of user posting a LB_DIR or CB_DIR
  9162. * (DlgDirListHelper()). In the post case, we thunk the lParam (pointer
  9163. * to a string) differently, and we track that post case with the
  9164. * DDL_POSTMSGS bit. If an app sends a message with this bit, then our
  9165. * thunking gets confused, so clear it here. Let's hope that no app
  9166. * depends on this bit set when either of these messages are sent.
  9167. *
  9168. * These messages should return -1 on failure
  9169. */
  9170. switch (msg) {
  9171. case LB_DIR:
  9172. case CB_DIR:
  9173. wParam &= ~DDL_POSTMSGS;
  9174. /* Fall through */
  9175. case LB_ADDFILE:
  9176. #if (LB_ERR != CB_ERR)
  9177. #error LB_ERR/CB_ERR conflict
  9178. #endif
  9179. errret = LB_ERR;
  9180. break;
  9181. }
  9182. /*
  9183. * Probe arguments
  9184. */
  9185. try {
  9186. if (bAnsi) {
  9187. ProbeForRead((LPSTR)lParam, sizeof(CHAR), sizeof(CHAR));
  9188. RtlInitLargeAnsiString((PLARGE_ANSI_STRING)&str,
  9189. (LPSTR)lParam, (UINT)-1);
  9190. } else {
  9191. ProbeForRead((LPWSTR)lParam, sizeof(WCHAR), CHARALIGN);
  9192. RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)&str,
  9193. (LPWSTR)lParam, (UINT)-1);
  9194. }
  9195. } except (StubExceptionHandler(FALSE)) {
  9196. MSGERROR(0);
  9197. }
  9198. /*
  9199. * !!! str.Buffer must be captured in xxxInterSendMsgEx
  9200. */
  9201. retval = CALLPROC(xpfnProc)(
  9202. pwnd,
  9203. msg,
  9204. wParam,
  9205. (LPARAM)&str,
  9206. xParam);
  9207. TRACE("fnINSTRING");
  9208. ENDRECV_MESSAGECALL();
  9209. }
  9210. MESSAGECALL(INSTRINGNULL)
  9211. {
  9212. LARGE_STRING str;
  9213. BEGINRECV_MESSAGECALL(0);
  9214. TRACETHUNK("fnINSTRINGNULL");
  9215. /*
  9216. * Probe arguments
  9217. */
  9218. if (ARGUMENT_PRESENT(lParam)) {
  9219. try {
  9220. if (bAnsi) {
  9221. ProbeForRead((LPSTR)lParam, sizeof(CHAR), sizeof(CHAR));
  9222. RtlInitLargeAnsiString((PLARGE_ANSI_STRING)&str,
  9223. (LPSTR)lParam, (UINT)-1);
  9224. } else {
  9225. ProbeForRead((LPWSTR)lParam, sizeof(WCHAR), CHARALIGN);
  9226. RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)&str,
  9227. (LPWSTR)lParam, (UINT)-1);
  9228. }
  9229. lParam = (LPARAM)&str;
  9230. } except (StubExceptionHandler(FALSE)) {
  9231. MSGERROR(0);
  9232. }
  9233. }
  9234. /*
  9235. * !!! str.Buffer must be captured in xxxInterSendMsgEx
  9236. */
  9237. retval = CALLPROC(xpfnProc)(
  9238. pwnd,
  9239. msg,
  9240. wParam,
  9241. lParam,
  9242. xParam);
  9243. TRACE("fnINSTRINGNULL");
  9244. ENDRECV_MESSAGECALL();
  9245. }
  9246. MESSAGECALL(INDEVICECHANGE)
  9247. {
  9248. BOOL fPtr = (BOOL)((wParam & 0x8000) == 0x8000);
  9249. DWORD cbSize;
  9250. PBYTE bfr = NULL;
  9251. TL tlBuffer;
  9252. BEGINRECV_MESSAGECALL(0);
  9253. TRACETHUNK("fnINDEVICECHANGE");
  9254. UNREFERENCED_PARAMETER(bAnsi);
  9255. /*
  9256. * Probe arguments
  9257. */
  9258. if (fPtr && lParam) {
  9259. struct _DEV_BROADCAST_HEADER *pHdr;
  9260. PDEV_BROADCAST_DEVICEINTERFACE_W pInterfaceW;
  9261. PDEV_BROADCAST_PORT_W pPortW;
  9262. PDEV_BROADCAST_HANDLE pHandleW;
  9263. try {
  9264. pHdr = (struct _DEV_BROADCAST_HEADER *)lParam;
  9265. cbSize = ProbeAndReadUlong(&(pHdr->dbcd_size));
  9266. if (cbSize < sizeof(*pHdr)) {
  9267. MSGERROR(ERROR_INVALID_PARAMETER);
  9268. }
  9269. ProbeForRead(pHdr, cbSize, sizeof(BYTE));
  9270. bfr = UserAllocPoolWithQuota(cbSize+2, TAG_DEVICECHANGE); // add space for trailing NULL for test
  9271. if (bfr == NULL) {
  9272. RIPERR0(ERROR_NOT_ENOUGH_MEMORY, RIP_WARNING, "fnINDEVICECHANGE: LocalAlloc failed.");
  9273. MSGERRORCLEANUP(0);
  9274. }
  9275. ThreadLockPool(ptiCurrent, bfr, &tlBuffer);
  9276. RtlCopyMemory(bfr, (PBYTE)lParam,
  9277. cbSize);
  9278. ((PWSTR)bfr)[cbSize/sizeof(WCHAR)] = 0; // trailing null to halt wcslen scan
  9279. lParam = (LPARAM)bfr;
  9280. pHdr = (struct _DEV_BROADCAST_HEADER *)lParam;
  9281. if (pHdr->dbcd_size != cbSize) {
  9282. MSGERRORCLEANUP(0);
  9283. }
  9284. switch(pHdr->dbcd_devicetype) {
  9285. case DBT_DEVTYP_PORT:
  9286. pPortW = (PDEV_BROADCAST_PORT_W)lParam;
  9287. if ((1+wcslen(pPortW->dbcp_name))*sizeof(WCHAR) + FIELD_OFFSET(DEV_BROADCAST_PORT_W, dbcp_name) > cbSize) {
  9288. MSGERRORCLEANUP(0);
  9289. }
  9290. break;
  9291. case DBT_DEVTYP_DEVICEINTERFACE:
  9292. pInterfaceW = (PDEV_BROADCAST_DEVICEINTERFACE_W)lParam;
  9293. if ((1+wcslen(pInterfaceW->dbcc_name))*sizeof(WCHAR) + FIELD_OFFSET(DEV_BROADCAST_DEVICEINTERFACE_W, dbcc_name) > cbSize) {
  9294. MSGERRORCLEANUP(0);
  9295. }
  9296. break;
  9297. case DBT_DEVTYP_HANDLE:
  9298. pHandleW = (PDEV_BROADCAST_HANDLE)lParam;
  9299. /*
  9300. * Check if there is any text.
  9301. */
  9302. if (wParam != DBT_CUSTOMEVENT) {
  9303. if (FIELD_OFFSET(DEV_BROADCAST_HANDLE, dbch_eventguid) > cbSize) {
  9304. MSGERRORCLEANUP(0);
  9305. }
  9306. break;
  9307. }
  9308. if (pHandleW->dbch_nameoffset < 0) {
  9309. if (FIELD_OFFSET(DEV_BROADCAST_HANDLE, dbch_data) > cbSize) {
  9310. MSGERRORCLEANUP(0);
  9311. }
  9312. break;
  9313. }
  9314. if (pHandleW->dbch_nameoffset & (CHARALIGN - 1)) {
  9315. ExRaiseDatatypeMisalignment(); \
  9316. }
  9317. if ((DWORD)(FIELD_OFFSET(DEV_BROADCAST_HANDLE, dbch_data) + pHandleW->dbch_nameoffset) > cbSize) {
  9318. MSGERRORCLEANUP(0);
  9319. }
  9320. if (FIELD_OFFSET(DEV_BROADCAST_HANDLE, dbch_data) + pHandleW->dbch_nameoffset +
  9321. (1+wcslen((LPWSTR)(pHandleW->dbch_data+pHandleW->dbch_nameoffset)))*sizeof(WCHAR) >
  9322. cbSize) {
  9323. MSGERRORCLEANUP(0);
  9324. }
  9325. break;
  9326. }
  9327. } except (StubExceptionHandler(FALSE)) {
  9328. MSGERRORCLEANUP(0);
  9329. }
  9330. }
  9331. retval = CALLPROC(xpfnProc)(
  9332. pwnd,
  9333. msg,
  9334. wParam,
  9335. lParam,
  9336. xParam);
  9337. CLEANUPRECV();
  9338. if (bfr)
  9339. ThreadUnlockAndFreePool(ptiCurrent, &tlBuffer);
  9340. TRACE("fnINDEVICECHANGE");
  9341. ENDRECV_MESSAGECALL();
  9342. }
  9343. MESSAGECALL(INOUTNCCALCSIZE)
  9344. {
  9345. NCCALCSIZE_PARAMS params;
  9346. WINDOWPOS pos;
  9347. PWINDOWPOS pposClient;
  9348. RECT rc;
  9349. LPARAM lParamLocal;
  9350. BEGINRECV_MESSAGECALL(0);
  9351. TRACETHUNK("fnINOUTNCCALCSIZE");
  9352. UNREFERENCED_PARAMETER(bAnsi);
  9353. /*
  9354. * Probe arguments
  9355. */
  9356. try {
  9357. if (wParam != 0) {
  9358. ProbeForWriteNCCalcSize((LPNCCALCSIZE_PARAMS)lParam);
  9359. params = *(LPNCCALCSIZE_PARAMS)lParam;
  9360. ProbeForWriteWindowPos(params.lppos);
  9361. pposClient = params.lppos;
  9362. pos = *params.lppos;
  9363. params.lppos = &pos;
  9364. lParamLocal = (LPARAM)&params;
  9365. } else {
  9366. ProbeForWriteRect((LPRECT)lParam);
  9367. rc = *(LPRECT)lParam;
  9368. lParamLocal = (LPARAM)&rc;
  9369. }
  9370. } except (StubExceptionHandler(FALSE)) {
  9371. MSGERROR(0);
  9372. }
  9373. retval = CALLPROC(xpfnProc)(
  9374. pwnd,
  9375. msg,
  9376. wParam,
  9377. lParamLocal,
  9378. xParam);
  9379. try {
  9380. if (wParam != 0) {
  9381. *(LPNCCALCSIZE_PARAMS)lParam = params;
  9382. ((LPNCCALCSIZE_PARAMS)lParam)->lppos = pposClient;
  9383. *pposClient = pos;
  9384. } else {
  9385. *(LPRECT)lParam = rc;
  9386. }
  9387. } except (StubExceptionHandler(FALSE)) {
  9388. }
  9389. TRACE("fnINOUTNCCALCSIZE");
  9390. ENDRECV_MESSAGECALL();
  9391. }
  9392. MESSAGECALL(INOUTSTYLECHANGE)
  9393. {
  9394. STYLESTRUCT ss;
  9395. BEGINRECV_MESSAGECALL(0);
  9396. TRACETHUNK("fnINOUTSTYLECHANGE");
  9397. UNREFERENCED_PARAMETER(bAnsi);
  9398. /*
  9399. * Probe arguments
  9400. */
  9401. try {
  9402. ProbeForWriteStyleStruct((LPSTYLESTRUCT)lParam);
  9403. ss = *(LPSTYLESTRUCT)lParam;
  9404. } except (StubExceptionHandler(FALSE)) {
  9405. MSGERROR(0);
  9406. }
  9407. retval = CALLPROC(xpfnProc)(
  9408. pwnd,
  9409. msg,
  9410. wParam,
  9411. (LPARAM)&ss,
  9412. xParam);
  9413. try {
  9414. *(LPSTYLESTRUCT)lParam = ss;
  9415. } except (StubExceptionHandler(FALSE)) {
  9416. }
  9417. TRACE("fnINOUTSTYLECHANGE");
  9418. ENDRECV_MESSAGECALL();
  9419. }
  9420. MESSAGECALL(INOUTLPRECT)
  9421. {
  9422. RECT rc;
  9423. BEGINRECV_MESSAGECALL((msg == LB_GETITEMRECT ? LB_ERR : 0));
  9424. TRACETHUNK("fnINOUTLPRECT");
  9425. UNREFERENCED_PARAMETER(bAnsi);
  9426. /*
  9427. * Probe arguments
  9428. */
  9429. try {
  9430. ProbeForWriteRect((PRECT)lParam);
  9431. rc = *(PRECT)lParam;
  9432. } except (StubExceptionHandler(FALSE)) {
  9433. MSGERROR(0);
  9434. }
  9435. retval = CALLPROC(xpfnProc)(
  9436. pwnd,
  9437. msg,
  9438. wParam,
  9439. (LPARAM)&rc,
  9440. xParam);
  9441. try {
  9442. *(PRECT)lParam = rc;
  9443. } except (StubExceptionHandler(FALSE)) {
  9444. }
  9445. TRACE("fnINOUTLPRECT");
  9446. ENDRECV_MESSAGECALL();
  9447. }
  9448. MESSAGECALL(OUTLPSCROLLINFO)
  9449. {
  9450. SCROLLINFO scrollinfo;
  9451. BEGINRECV_MESSAGECALL(0);
  9452. TRACETHUNK("fnOUTLPSCROLLINFO");
  9453. UNREFERENCED_PARAMETER(bAnsi);
  9454. retval = CALLPROC(xpfnProc)(
  9455. pwnd,
  9456. msg,
  9457. wParam,
  9458. (LPARAM)&scrollinfo,
  9459. xParam);
  9460. /*
  9461. * Probe arguments
  9462. */
  9463. try {
  9464. ProbeAndWriteStructure((LPSCROLLINFO)lParam, scrollinfo, SCROLLINFO);
  9465. } except (StubExceptionHandler(FALSE)) {
  9466. MSGERROR(0);
  9467. }
  9468. TRACE("fnOUTLPSCROLLINFO");
  9469. ENDRECV_MESSAGECALL();
  9470. }
  9471. MESSAGECALL(OUTLPRECT)
  9472. {
  9473. RECT rc;
  9474. BEGINRECV_MESSAGECALL(0);
  9475. TRACETHUNK("fnOUTLPRECT");
  9476. UNREFERENCED_PARAMETER(bAnsi);
  9477. retval = CALLPROC(xpfnProc)(
  9478. pwnd,
  9479. msg,
  9480. wParam,
  9481. (LPARAM)&rc,
  9482. xParam);
  9483. /*
  9484. * Probe arguments
  9485. */
  9486. try {
  9487. ProbeAndWriteStructure((PRECT)lParam, rc, RECT);
  9488. } except (StubExceptionHandler(FALSE)) {
  9489. MSGERROR(0);
  9490. }
  9491. TRACE("fnOUTLPRECT");
  9492. ENDRECV_MESSAGECALL();
  9493. }
  9494. MESSAGECALL(INLPCOMPAREITEMSTRUCT)
  9495. {
  9496. COMPAREITEMSTRUCT compareitemstruct;
  9497. BEGINRECV_MESSAGECALL(0);
  9498. TRACETHUNK("fnINLPCOMPAREITEMSTRUCT");
  9499. UNREFERENCED_PARAMETER(bAnsi);
  9500. /*
  9501. * Probe arguments
  9502. */
  9503. try {
  9504. compareitemstruct = ProbeAndReadCompareItemStruct((PCOMPAREITEMSTRUCT)lParam);
  9505. } except (StubExceptionHandler(FALSE)) {
  9506. MSGERROR(0);
  9507. }
  9508. retval = CALLPROC(xpfnProc)(
  9509. pwnd,
  9510. msg,
  9511. wParam,
  9512. (LPARAM)&compareitemstruct,
  9513. xParam);
  9514. TRACE("fnINLPCOMPAREITEMSTRUCT");
  9515. ENDRECV_MESSAGECALL();
  9516. }
  9517. MESSAGECALL(INLPDELETEITEMSTRUCT)
  9518. {
  9519. DELETEITEMSTRUCT deleteitemstruct;
  9520. BEGINRECV_MESSAGECALL(0);
  9521. TRACETHUNK("fnINLPDELETEITEMSTRUCT");
  9522. UNREFERENCED_PARAMETER(bAnsi);
  9523. /*
  9524. * Probe arguments
  9525. */
  9526. try {
  9527. deleteitemstruct = ProbeAndReadDeleteItemStruct((PDELETEITEMSTRUCT)lParam);
  9528. } except (StubExceptionHandler(FALSE)) {
  9529. MSGERROR(0);
  9530. }
  9531. retval = CALLPROC(xpfnProc)(
  9532. pwnd,
  9533. msg,
  9534. wParam,
  9535. (LPARAM)&deleteitemstruct,
  9536. xParam);
  9537. TRACE("fnINLPDELETEITEMSTRUCT");
  9538. ENDRECV_MESSAGECALL();
  9539. }
  9540. MESSAGECALL(INLPHLPSTRUCT)
  9541. {
  9542. HLP hlp;
  9543. LPHLP phlp = NULL;
  9544. TL tlBuffer;
  9545. BEGINRECV_MESSAGECALL(0);
  9546. TRACETHUNK("fnINLPHLPSTRUCT");
  9547. UNREFERENCED_PARAMETER(bAnsi);
  9548. /*
  9549. * Probe arguments
  9550. */
  9551. try {
  9552. hlp = ProbeAndReadHelp((LPHLP)lParam);
  9553. if (hlp.cbData < sizeof(HLP)) {
  9554. MSGERROR(0);
  9555. }
  9556. phlp = UserAllocPoolWithQuota(hlp.cbData, TAG_SYSTEM);
  9557. if (phlp == NULL) {
  9558. ExRaiseStatus(STATUS_NO_MEMORY);
  9559. }
  9560. ThreadLockPool(ptiCurrent, phlp, &tlBuffer);
  9561. RtlCopyMemory(phlp, (PVOID)lParam, hlp.cbData);
  9562. } except (StubExceptionHandler(FALSE)) {
  9563. MSGERRORCLEANUP(0);
  9564. }
  9565. retval = CALLPROC(xpfnProc)(
  9566. pwnd,
  9567. msg,
  9568. wParam,
  9569. (LPARAM)phlp,
  9570. xParam);
  9571. CLEANUPRECV();
  9572. if (phlp) {
  9573. ThreadUnlockAndFreePool(ptiCurrent, &tlBuffer);
  9574. }
  9575. TRACE("fnINLPHLPSTRUCT");
  9576. ENDRECV_MESSAGECALL();
  9577. }
  9578. MESSAGECALL(INLPHELPINFOSTRUCT)
  9579. {
  9580. HELPINFO helpinfo;
  9581. BEGINRECV_MESSAGECALL(0);
  9582. TRACETHUNK("fnINLPHELPINFOSTRUCT");
  9583. UNREFERENCED_PARAMETER(bAnsi);
  9584. /*
  9585. * Probe arguments
  9586. */
  9587. try {
  9588. helpinfo = ProbeAndReadHelpInfo((LPHELPINFO)lParam);
  9589. if (helpinfo.cbSize != sizeof(HELPINFO)) {
  9590. RIPMSG1(RIP_WARNING, "HELPINFO.cbSize %d is wrong", helpinfo.cbSize);
  9591. MSGERROR(ERROR_INVALID_PARAMETER);
  9592. }
  9593. } except (StubExceptionHandler(FALSE)) {
  9594. MSGERROR(0);
  9595. }
  9596. retval = CALLPROC(xpfnProc)(
  9597. pwnd,
  9598. msg,
  9599. wParam,
  9600. (LPARAM)&helpinfo,
  9601. xParam);
  9602. TRACE("fnINLPHELPINFOSTRUCT");
  9603. ENDRECV_MESSAGECALL();
  9604. }
  9605. MESSAGECALL(INLPDRAWITEMSTRUCT)
  9606. {
  9607. DRAWITEMSTRUCT drawitemstruct;
  9608. BEGINRECV_MESSAGECALL(0);
  9609. TRACETHUNK("fnINLPDRAWITEMSTRUCT");
  9610. UNREFERENCED_PARAMETER(bAnsi);
  9611. /*
  9612. * Probe arguments
  9613. */
  9614. try {
  9615. drawitemstruct = ProbeAndReadDrawItemStruct((PDRAWITEMSTRUCT)lParam);
  9616. } except (StubExceptionHandler(FALSE)) {
  9617. MSGERROR(0);
  9618. }
  9619. retval = CALLPROC(xpfnProc)(
  9620. pwnd,
  9621. msg,
  9622. wParam,
  9623. (LPARAM)&drawitemstruct,
  9624. xParam);
  9625. TRACE("fnINLPDRAWITEMSTRUCT");
  9626. ENDRECV_MESSAGECALL();
  9627. }
  9628. MESSAGECALL(INOUTLPMEASUREITEMSTRUCT)
  9629. {
  9630. MEASUREITEMSTRUCT measureitemstruct;
  9631. BEGINRECV_MESSAGECALL(0);
  9632. TRACETHUNK("fnINOUTLPMEASUREITEMSTRUCT");
  9633. UNREFERENCED_PARAMETER(bAnsi);
  9634. /*
  9635. * Probe arguments
  9636. */
  9637. try {
  9638. ProbeForWriteMeasureItemStruct((PMEASUREITEMSTRUCT)lParam);
  9639. measureitemstruct = *(PMEASUREITEMSTRUCT)lParam;
  9640. } except (StubExceptionHandler(FALSE)) {
  9641. MSGERROR(0);
  9642. }
  9643. retval = CALLPROC(xpfnProc)(
  9644. pwnd,
  9645. msg,
  9646. wParam,
  9647. (LPARAM)&measureitemstruct,
  9648. xParam);
  9649. try {
  9650. *(PMEASUREITEMSTRUCT)lParam = measureitemstruct;
  9651. } except (StubExceptionHandler(FALSE)) {
  9652. }
  9653. TRACE("fnINOUTLPMEASUREITEMSTRUCT");
  9654. ENDRECV_MESSAGECALL();
  9655. }
  9656. MESSAGECALL(OUTSTRING)
  9657. {
  9658. LARGE_STRING str;
  9659. BEGINRECV_MESSAGECALL(0);
  9660. TRACETHUNK("fnOUTSTRING");
  9661. /*
  9662. * Probe all arguments
  9663. */
  9664. try {
  9665. str.bAnsi = bAnsi;
  9666. str.MaximumLength = (ULONG)wParam;
  9667. if (!bAnsi) {
  9668. str.MaximumLength *= sizeof(WCHAR);
  9669. }
  9670. str.Length = 0;
  9671. str.Buffer = (PVOID)lParam;
  9672. #if defined(_X86_)
  9673. ProbeForWrite((PVOID)str.Buffer, str.MaximumLength, sizeof(BYTE));
  9674. #else
  9675. ProbeForWrite((PVOID)str.Buffer, str.MaximumLength,
  9676. str.bAnsi ? sizeof(BYTE) : sizeof(WORD));
  9677. #endif
  9678. } except (StubExceptionHandler(FALSE)) {
  9679. MSGERROR(0);
  9680. }
  9681. /*
  9682. * !!! String buffer must be created in xxxInterSendMsgEx and
  9683. * lParam probed for write again upon return.
  9684. */
  9685. retval = CALLPROC(xpfnProc)(
  9686. pwnd,
  9687. msg,
  9688. wParam,
  9689. (LPARAM)&str,
  9690. xParam);
  9691. /*
  9692. * A dialog function returning FALSE means no text to copy out,
  9693. * but an empty string also has retval == 0: put a null char in
  9694. * pstr for the latter case.
  9695. */
  9696. if (!retval && wParam != 0) {
  9697. try {
  9698. NullTerminateString((PVOID)lParam, bAnsi);
  9699. } except (StubExceptionHandler(FALSE)) {
  9700. MSGERROR(0);
  9701. }
  9702. }
  9703. TRACE("fnOUTSTRING");
  9704. ENDRECV_MESSAGECALL();
  9705. }
  9706. MESSAGECALL(OUTDWORDINDWORD)
  9707. {
  9708. DWORD dw;
  9709. BEGINRECV_MESSAGECALL(0);
  9710. TRACETHUNK("fnOUTDWORDINDWORD");
  9711. UNREFERENCED_PARAMETER(bAnsi);
  9712. retval = CALLPROC(xpfnProc)(
  9713. pwnd,
  9714. msg,
  9715. (WPARAM)&dw,
  9716. lParam,
  9717. xParam);
  9718. /*
  9719. * Probe wParam
  9720. */
  9721. try {
  9722. ProbeAndWriteUlong((PULONG)wParam, dw);
  9723. } except (StubExceptionHandler(FALSE)) {
  9724. MSGERROR(0);
  9725. }
  9726. TRACE("fnOUTDWORDINDWORD");
  9727. ENDRECV_MESSAGECALL();
  9728. }
  9729. MESSAGECALL(INCNTOUTSTRING)
  9730. {
  9731. LARGE_STRING str;
  9732. BEGINRECV_MESSAGECALL(0);
  9733. TRACETHUNK("fnINCNTOUTSTRING");
  9734. /*
  9735. * Probe arguments
  9736. */
  9737. try {
  9738. str.bAnsi = bAnsi;
  9739. str.MaximumLength = ProbeAndReadUshort((LPWORD)lParam);
  9740. if (!bAnsi) {
  9741. str.MaximumLength *= sizeof(WCHAR);
  9742. }
  9743. if (str.MaximumLength < sizeof(WORD)) {
  9744. RIPMSG0(RIP_WARNING, "fnINCNTOUTSTRING buffer is too small");
  9745. MSGERROR(0);
  9746. }
  9747. str.Length = 0;
  9748. str.Buffer = (LPBYTE)lParam;
  9749. #if defined(_X86_)
  9750. ProbeForWrite((PVOID)str.Buffer, str.MaximumLength, sizeof(BYTE));
  9751. #else
  9752. ProbeForWrite((PVOID)str.Buffer, str.MaximumLength,
  9753. str.bAnsi ? sizeof(BYTE) : sizeof(WORD));
  9754. #endif
  9755. } except (StubExceptionHandler(FALSE)) {
  9756. MSGERROR(0);
  9757. }
  9758. /*
  9759. * !!! String buffer must be created in xxxInterSendMsgEx and
  9760. * lParam probed for write again upon return.
  9761. */
  9762. retval = CALLPROC(xpfnProc)(
  9763. pwnd,
  9764. msg,
  9765. wParam,
  9766. (LPARAM)&str,
  9767. xParam);
  9768. /*
  9769. * A dialog function returning FALSE means no text to copy out,
  9770. * but an empty string also has retval == 0: put a null char in
  9771. * pstr for the latter case.
  9772. */
  9773. if (!retval) {
  9774. try {
  9775. NullTerminateString((PVOID)lParam, bAnsi);
  9776. } except (StubExceptionHandler(FALSE)) {
  9777. MSGERROR(0);
  9778. }
  9779. }
  9780. TRACE("fnINCNTOUTSTRING");
  9781. ENDRECV_MESSAGECALL();
  9782. }
  9783. MESSAGECALL(INCNTOUTSTRINGNULL)
  9784. {
  9785. LARGE_STRING str;
  9786. BEGINRECV_MESSAGECALL(0);
  9787. TRACETHUNK("fnINCNTOUTSTRINGNULL");
  9788. /*
  9789. * Probe arguments
  9790. */
  9791. try {
  9792. if (wParam < 2) { // This prevents a possible GP
  9793. MSGERROR(0);
  9794. }
  9795. str.bAnsi = bAnsi;
  9796. str.MaximumLength = (ULONG)wParam;
  9797. if (!bAnsi) {
  9798. str.MaximumLength *= sizeof(WCHAR);
  9799. }
  9800. str.Length = 0;
  9801. str.Buffer = (LPBYTE)lParam;
  9802. #if defined(_X86_)
  9803. ProbeForWrite((PVOID)str.Buffer, str.MaximumLength, sizeof(BYTE));
  9804. #else
  9805. ProbeForWrite((PVOID)str.Buffer, str.MaximumLength,
  9806. str.bAnsi ? sizeof(BYTE) : sizeof(WORD));
  9807. #endif
  9808. *((LPWSTR)str.Buffer) = 0; // mark incase message is not handled
  9809. } except (StubExceptionHandler(FALSE)) {
  9810. MSGERROR(0);
  9811. }
  9812. /*
  9813. * !!! String buffer must be created in xxxInterSendMsgEx and
  9814. * lParam probed for write again upon return.
  9815. */
  9816. retval = CALLPROC(xpfnProc)(
  9817. pwnd,
  9818. msg,
  9819. wParam,
  9820. (LPARAM)&str,
  9821. xParam);
  9822. TRACE("fnINCNTOUTSTRINGNULL");
  9823. ENDRECV_MESSAGECALL();
  9824. }
  9825. MESSAGECALL(POUTLPINT)
  9826. {
  9827. BEGINRECV_MESSAGECALL(LB_ERR);
  9828. /*
  9829. * If we use this for other messages, then that return value might not be appropriate.
  9830. */
  9831. UserAssert(msg == LB_GETSELITEMS);
  9832. TRACETHUNK("fnPOUTLPINT");
  9833. UNREFERENCED_PARAMETER(bAnsi);
  9834. /*
  9835. * Probe arguments
  9836. */
  9837. try {
  9838. #if defined(_X86_)
  9839. ProbeForWriteBuffer((LPINT)lParam, wParam, sizeof(BYTE));
  9840. #else
  9841. ProbeForWriteBuffer((LPINT)lParam, wParam, sizeof(INT));
  9842. #endif
  9843. } except (StubExceptionHandler(FALSE)) {
  9844. MSGERROR(0);
  9845. }
  9846. /*
  9847. * !!! Buffer must be created in xxxInterSendMsgEx and
  9848. * lParam probed for write again upon return.
  9849. */
  9850. retval = CALLPROC(xpfnProc)(
  9851. pwnd,
  9852. msg,
  9853. wParam,
  9854. lParam,
  9855. xParam);
  9856. TRACE("fnPOUTLPINT");
  9857. ENDRECV_MESSAGECALL();
  9858. }
  9859. MESSAGECALL(POPTINLPUINT)
  9860. {
  9861. BEGINRECV_MESSAGECALL(0);
  9862. TRACETHUNK("fnPOPTINLPUINT");
  9863. UNREFERENCED_PARAMETER(bAnsi);
  9864. /*
  9865. * Probe arguments
  9866. */
  9867. try {
  9868. #if defined(_X86_)
  9869. if (lParam)
  9870. ProbeForReadBuffer((LPUINT)lParam, wParam, sizeof(BYTE));
  9871. #else
  9872. if (lParam)
  9873. ProbeForReadBuffer((LPUINT)lParam, wParam, sizeof(DWORD));
  9874. #endif
  9875. } except (StubExceptionHandler(FALSE)) {
  9876. MSGERROR(0);
  9877. }
  9878. /*
  9879. * !!! Data pointed to by lParam must be captured in xxxInterSendMsgEx
  9880. */
  9881. retval = CALLPROC(xpfnProc)(
  9882. pwnd,
  9883. msg,
  9884. wParam,
  9885. lParam,
  9886. xParam);
  9887. TRACE("fnPOPTINLPUINT");
  9888. ENDRECV_MESSAGECALL();
  9889. }
  9890. MESSAGECALL(INOUTLPWINDOWPOS)
  9891. {
  9892. WINDOWPOS pos;
  9893. BEGINRECV_MESSAGECALL(0);
  9894. TRACETHUNK("fnINOUTLPWINDOWPOS");
  9895. UNREFERENCED_PARAMETER(bAnsi);
  9896. /*
  9897. * Probe arguments
  9898. */
  9899. try {
  9900. ProbeForWriteWindowPos((PWINDOWPOS)lParam);
  9901. pos = *(PWINDOWPOS)lParam;
  9902. } except (StubExceptionHandler(FALSE)) {
  9903. MSGERROR(0);
  9904. }
  9905. retval = CALLPROC(xpfnProc)(
  9906. pwnd,
  9907. msg,
  9908. wParam,
  9909. (LPARAM)&pos,
  9910. xParam);
  9911. try {
  9912. *(PWINDOWPOS)lParam = pos;
  9913. } except (StubExceptionHandler(FALSE)) {
  9914. }
  9915. TRACE("fnINOUTLPWINDOWPOS");
  9916. ENDRECV_MESSAGECALL();
  9917. }
  9918. MESSAGECALL(INLPWINDOWPOS)
  9919. {
  9920. WINDOWPOS pos;
  9921. BEGINRECV_MESSAGECALL(0);
  9922. TRACETHUNK("fnINLPWINDOWPOS");
  9923. UNREFERENCED_PARAMETER(bAnsi);
  9924. /*
  9925. * Probe arguments
  9926. */
  9927. try {
  9928. pos = ProbeAndReadWindowPos((PWINDOWPOS)lParam);
  9929. } except (StubExceptionHandler(FALSE)) {
  9930. MSGERROR(0);
  9931. }
  9932. retval = CALLPROC(xpfnProc)(
  9933. pwnd,
  9934. msg,
  9935. wParam,
  9936. (LPARAM)&pos,
  9937. xParam);
  9938. TRACE("fnINLPWINDOWPOS");
  9939. ENDRECV_MESSAGECALL();
  9940. }
  9941. MESSAGECALL(INLBOXSTRING)
  9942. {
  9943. BEGINRECV_MESSAGECALL(LB_ERR);
  9944. TRACETHUNK("fnINLBOXSTRING");
  9945. if (!(pwnd->style & LBS_HASSTRINGS) &&
  9946. (pwnd->style & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE))) {
  9947. retval = CALLPROC(xpfnProc)(
  9948. pwnd,
  9949. msg,
  9950. wParam,
  9951. lParam,
  9952. xParam);
  9953. } else if (msg == LB_FINDSTRING) {
  9954. retval = NtUserfnINSTRINGNULL(
  9955. pwnd,
  9956. msg,
  9957. wParam,
  9958. lParam,
  9959. xParam,
  9960. xpfnProc,
  9961. bAnsi);
  9962. } else {
  9963. retval = NtUserfnINSTRING(
  9964. pwnd,
  9965. msg,
  9966. wParam,
  9967. lParam,
  9968. xParam,
  9969. xpfnProc,
  9970. bAnsi);
  9971. }
  9972. TRACE("fnINLBOXSTRING");
  9973. ENDRECV_MESSAGECALL();
  9974. }
  9975. MESSAGECALL(OUTLBOXSTRING)
  9976. {
  9977. LARGE_STRING str;
  9978. BEGINRECV_MESSAGECALL(LB_ERR);
  9979. TRACETHUNK("fnOUTLBOXSTRING");
  9980. /*
  9981. * Need to get the string length ahead of time. This isn't passed in
  9982. * with this message. Code assumes app already knows the size of
  9983. * the string and has passed a pointer to a buffer of adequate size.
  9984. * To do client/server copying of this string, we need to ahead of
  9985. * time the Unicode size of this string. We add one character because
  9986. * GETTEXTLEN excludes the null terminator.
  9987. */
  9988. retval = NtUserfnGETDBCSTEXTLENGTHS(
  9989. pwnd,
  9990. LB_GETTEXTLEN,
  9991. wParam,
  9992. lParam,
  9993. xParam,
  9994. xpfnProc,
  9995. /*IS_DBCS_ENABLED() &&*/ bAnsi); // HiroYama: LATER
  9996. if (retval == LB_ERR)
  9997. MSGERROR(0);
  9998. retval++;
  9999. /*
  10000. * Probe all arguments
  10001. */
  10002. try {
  10003. str.bAnsi = bAnsi;
  10004. if (bAnsi) {
  10005. str.MaximumLength = (ULONG)retval;
  10006. } else {
  10007. str.MaximumLength = (ULONG)retval * sizeof(WCHAR);
  10008. }
  10009. str.Length = 0;
  10010. str.Buffer = (PVOID)lParam;
  10011. #if defined(_X86_)
  10012. ProbeForWrite((PVOID)str.Buffer, str.MaximumLength, sizeof(BYTE));
  10013. #else
  10014. ProbeForWrite((PVOID)str.Buffer, str.MaximumLength,
  10015. str.bAnsi ? sizeof(BYTE) : sizeof(WORD));
  10016. #endif
  10017. } except (StubExceptionHandler(FALSE)) {
  10018. MSGERROR(0);
  10019. }
  10020. retval = CALLPROC(xpfnProc)(
  10021. pwnd,
  10022. msg,
  10023. wParam,
  10024. (LPARAM)&str,
  10025. xParam);
  10026. /*
  10027. * If the control is ownerdraw and does not have the LBS_HASSTRINGS
  10028. * style, then a 32-bits of application data has been obtained,
  10029. * not a string.
  10030. */
  10031. if (!(pwnd->style & LBS_HASSTRINGS) &&
  10032. (pwnd->style & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE))) {
  10033. if (bAnsi) {
  10034. retval = sizeof(ULONG_PTR)/sizeof(CHAR); // 4 CHARs just like win3.1
  10035. } else {
  10036. retval = sizeof(ULONG_PTR)/sizeof(WCHAR); // 2 WCHARs
  10037. }
  10038. }
  10039. TRACE("fnOUTLBOXSTRING");
  10040. ENDRECV_MESSAGECALL();
  10041. }
  10042. MESSAGECALL(INCBOXSTRING)
  10043. {
  10044. BEGINRECV_MESSAGECALL(CB_ERR);
  10045. TRACETHUNK("fnINCBOXSTRING");
  10046. if (!(pwnd->style & CBS_HASSTRINGS) &&
  10047. (pwnd->style & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE))) {
  10048. retval = CALLPROC(xpfnProc)(
  10049. pwnd,
  10050. msg,
  10051. wParam,
  10052. lParam,
  10053. xParam);
  10054. } else if (msg == CB_FINDSTRING) {
  10055. retval = NtUserfnINSTRINGNULL(
  10056. pwnd,
  10057. msg,
  10058. wParam,
  10059. lParam,
  10060. xParam,
  10061. xpfnProc,
  10062. bAnsi);
  10063. } else {
  10064. retval = NtUserfnINSTRING(
  10065. pwnd,
  10066. msg,
  10067. wParam,
  10068. lParam,
  10069. xParam,
  10070. xpfnProc,
  10071. bAnsi);
  10072. }
  10073. TRACE("fnINCBOXSTRING");
  10074. ENDRECV_MESSAGECALL();
  10075. }
  10076. MESSAGECALL(OUTCBOXSTRING)
  10077. {
  10078. LARGE_STRING str;
  10079. BEGINRECV_MESSAGECALL(CB_ERR);
  10080. TRACETHUNK("fnOUTCBOXSTRING");
  10081. /*
  10082. * Need to get the string length ahead of time. This isn't passed in
  10083. * with this message. Code assumes app already knows the size of
  10084. * the string and has passed a pointer to a buffer of adequate size.
  10085. * To do client/server copying of this string, we need to ahead of
  10086. * time the size of this string. We add one character because
  10087. * GETTEXTLEN excludes the null terminator.
  10088. */
  10089. retval = NtUserfnGETDBCSTEXTLENGTHS(
  10090. pwnd,
  10091. CB_GETLBTEXTLEN,
  10092. wParam,
  10093. lParam,
  10094. xParam,
  10095. xpfnProc,
  10096. /*IS_DBCS_ENABLED() &&*/ bAnsi); // HiroYama: LATER
  10097. if (retval == CB_ERR)
  10098. MSGERROR(0);
  10099. retval++;
  10100. /*
  10101. * Probe all arguments
  10102. */
  10103. try {
  10104. str.bAnsi = bAnsi;
  10105. if (bAnsi) {
  10106. str.MaximumLength = (ULONG)retval;
  10107. } else {
  10108. str.MaximumLength = (ULONG)retval * sizeof(WCHAR);
  10109. }
  10110. str.Length = 0;
  10111. str.Buffer = (PVOID)lParam;
  10112. #if defined(_X86_)
  10113. ProbeForWrite((PVOID)str.Buffer, str.MaximumLength, sizeof(BYTE));
  10114. #else
  10115. ProbeForWrite((PVOID)str.Buffer, str.MaximumLength,
  10116. str.bAnsi ? sizeof(BYTE) : sizeof(WORD));
  10117. #endif
  10118. } except (StubExceptionHandler(FALSE)) {
  10119. MSGERROR(0);
  10120. }
  10121. retval = CALLPROC(xpfnProc)(
  10122. pwnd,
  10123. msg,
  10124. wParam,
  10125. (LPARAM)&str,
  10126. xParam);
  10127. /*
  10128. * If the control is ownerdraw and does not have the CBS_HASSTRINGS
  10129. * style, then a 32-bits of application data has been obtained,
  10130. * not a string.
  10131. */
  10132. if (!(pwnd->style & CBS_HASSTRINGS) &&
  10133. (pwnd->style & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE))) {
  10134. if (bAnsi) {
  10135. retval = sizeof(ULONG_PTR)/sizeof(CHAR); // 4 CHARs just like win3.1
  10136. } else {
  10137. retval = sizeof(ULONG_PTR)/sizeof(WCHAR); // 2 WCHARs
  10138. }
  10139. }
  10140. TRACE("fnOUTCBOXSTRING");
  10141. ENDRECV_MESSAGECALL();
  10142. }
  10143. MESSAGECALL(INWPARAMCHAR)
  10144. {
  10145. BEGINRECV_MESSAGECALL(0);
  10146. TRACETHUNK("fnINWPARAMCHAR");
  10147. /*
  10148. * The server always expects the characters to be unicode so
  10149. * if this was generated from an ANSI routine convert it to Unicode
  10150. */
  10151. if (bAnsi) {
  10152. if (msg == WM_CHARTOITEM || msg == WM_MENUCHAR) {
  10153. WPARAM dwT = wParam & 0xFFFF; // mask of caret pos
  10154. RtlMBMessageWParamCharToWCS(msg, &dwT); // convert key portion
  10155. wParam = MAKELONG(LOWORD(dwT),HIWORD(wParam)); // rebuild pos & key wParam
  10156. } else {
  10157. RtlMBMessageWParamCharToWCS(msg, &wParam);
  10158. }
  10159. }
  10160. retval = CALLPROC(xpfnProc)(
  10161. pwnd,
  10162. msg,
  10163. wParam,
  10164. lParam,
  10165. xParam);
  10166. TRACE("fnINWPARAMCHAR");
  10167. ENDRECV_MESSAGECALL();
  10168. }
  10169. MESSAGECALL(KERNELONLY)
  10170. {
  10171. BEGINRECV_MESSAGECALL(0);
  10172. TRACETHUNK("fnKERNELONLY");
  10173. UNREFERENCED_PARAMETER(pwnd);
  10174. UNREFERENCED_PARAMETER(msg);
  10175. UNREFERENCED_PARAMETER(wParam);
  10176. UNREFERENCED_PARAMETER(lParam);
  10177. UNREFERENCED_PARAMETER(xParam);
  10178. UNREFERENCED_PARAMETER(xpfnProc);
  10179. UNREFERENCED_PARAMETER(bAnsi);
  10180. RIPMSG0(RIP_WARNING,
  10181. "Message sent from client to kernel for a process which has only kernel side");
  10182. retval = 0;
  10183. TRACE("fnKERNELONLY");
  10184. ENDRECV_MESSAGECALL();
  10185. }
  10186. MESSAGECALL(IMECONTROL)
  10187. {
  10188. CANDIDATEFORM CandForm;
  10189. COMPOSITIONFORM CompForm;
  10190. LOGFONTW LogFontW;
  10191. LPARAM lData = lParam;
  10192. PSOFTKBDDATA pSoftKbdData = NULL;
  10193. BEGINRECV_MESSAGECALL(0);
  10194. TRACETHUNK("fnIMECONTROL");
  10195. UNREFERENCED_PARAMETER(bAnsi);
  10196. /*
  10197. * wParam range validation:
  10198. * No need to check lower limit, 'cause we assume IMC_FIRST == 0
  10199. * and wParam is unsigned.
  10200. */
  10201. #if (IMC_FIRST != 0)
  10202. #error IMC_FIRST: unexpected value
  10203. #endif
  10204. if (msg != WM_IME_CONTROL || wParam > IMC_LAST) {
  10205. MSGERROR(0);
  10206. }
  10207. /*
  10208. * Probe arguments
  10209. */
  10210. try {
  10211. switch (wParam) {
  10212. case IMC_GETCANDIDATEPOS:
  10213. ProbeForWriteCandidateForm((PCANDIDATEFORM)lParam);
  10214. break;
  10215. case IMC_GETCOMPOSITIONWINDOW:
  10216. ProbeForWriteCompositionForm((PCOMPOSITIONFORM)lParam);
  10217. break;
  10218. case IMC_GETCOMPOSITIONFONT:
  10219. case IMC_GETSOFTKBDFONT:
  10220. ProbeForWriteLogFontW((PLOGFONTW)lParam);
  10221. break;
  10222. case IMC_SETCANDIDATEPOS:
  10223. CandForm = ProbeAndReadCandidateForm((PCANDIDATEFORM)lParam);
  10224. lData = (LPARAM)&CandForm;
  10225. break;
  10226. case IMC_SETCOMPOSITIONWINDOW:
  10227. CompForm = ProbeAndReadCompositionForm((PCOMPOSITIONFORM)lParam);
  10228. lData = (LPARAM)&CompForm;
  10229. break;
  10230. case IMC_SETCOMPOSITIONFONT:
  10231. LogFontW = ProbeAndReadLogFontW((PLOGFONTW)lParam);
  10232. lData = (LPARAM)&LogFontW;
  10233. break;
  10234. case IMC_SETSOFTKBDDATA:
  10235. pSoftKbdData = ProbeAndCaptureSoftKbdData((PSOFTKBDDATA)lParam);
  10236. if (pSoftKbdData == NULL)
  10237. MSGERROR(0);
  10238. lData = (LPARAM)pSoftKbdData;
  10239. break;
  10240. default:
  10241. break;
  10242. }
  10243. } except (StubExceptionHandler(FALSE)) {
  10244. MSGERRORCLEANUP(0);
  10245. }
  10246. retval = CALLPROC(xpfnProc)(
  10247. pwnd,
  10248. msg,
  10249. wParam,
  10250. lData,
  10251. xParam);
  10252. CLEANUPRECV();
  10253. if (pSoftKbdData != NULL) {
  10254. UserFreePool(pSoftKbdData);
  10255. }
  10256. TRACE("fnIMECONTROL");
  10257. ENDRECV_MESSAGECALL();
  10258. }
  10259. #ifdef LATER
  10260. MESSAGECALL(IMEREQUEST)
  10261. {
  10262. LPARAM lData = lParam;
  10263. BEGINRECV_MESSAGECALL(0);
  10264. TRACETHUNK("fnIMEREQUEST");
  10265. UNREFERENCED_PARAMETER(bAnsi);
  10266. if (GETPTI(pwnd) != PtiCurrent()) {
  10267. /*
  10268. * Does not allow to send WM_IME_REQUEST to
  10269. * the different thread.
  10270. */
  10271. MSGERROR(ERROR_WINDOW_OF_OTHER_THREAD);
  10272. }
  10273. /*
  10274. * Probe arguments
  10275. */
  10276. try {
  10277. switch (wParam) {
  10278. case IMR_COMPOSITIONWINDOW:
  10279. ProbeForWriteCompositionForm((PCOMPOSITIONFORM)lParam);
  10280. break;
  10281. case IMR_CANDIDATEWINDOW:
  10282. ProbeForWriteCandidateForm((PCANDIDATEFORM)lParam);
  10283. break;
  10284. case IMR_COMPOSITIONFONT:
  10285. ProbeForWriteLogFontW((PLOGFONTW)lParam);
  10286. break;
  10287. case IMR_RECONVERTSTRING:
  10288. case IMR_DOCUMENTFEED:
  10289. if (lParam) {
  10290. ProbeForWriteReconvertString((LPRECONVERTSTRING)lParam);
  10291. }
  10292. break;
  10293. case IMR_CONFIRMRECONVERTSTRING:
  10294. //ProbeAndCaptureReconvertString((LPRECONVERTSTRING)lParam);
  10295. //ProbeForWriteReconvertString((LPRECONVERTSTRING)lParam);
  10296. ProbeForReadReconvertString((LPRECONVERTSTRING)lParam);
  10297. break;
  10298. case IMR_QUERYCHARPOSITION:
  10299. ProbeForWriteImeCharPosition((LPPrivateIMECHARPOSITION)lParam);
  10300. break;
  10301. default:
  10302. MSGERROR(0);
  10303. }
  10304. } except (StubExceptionHandler(FALSE)) {
  10305. MSGERRORCLEANUP(0);
  10306. }
  10307. retval = CALLPROC(xpfnProc)(
  10308. pwnd,
  10309. msg,
  10310. wParam,
  10311. lData,
  10312. xParam);
  10313. CLEANUPRECV();
  10314. TRACE("fnIMEREQUEST");
  10315. ENDRECV_MESSAGECALL();
  10316. }
  10317. #endif
  10318. /*
  10319. * Hook stubs
  10320. */
  10321. LRESULT NtUserfnHkINLPCBTCREATESTRUCT(
  10322. IN UINT msg,
  10323. IN WPARAM wParam,
  10324. IN LPCBT_CREATEWND pcbt,
  10325. IN BOOL bAnsi)
  10326. {
  10327. CBT_CREATEWND cbt;
  10328. CREATESTRUCTEX csex;
  10329. LPCREATESTRUCT lpcsSave;
  10330. BEGINRECV_HOOKCALL();
  10331. /*
  10332. * Probe arguments
  10333. */
  10334. try {
  10335. cbt = ProbeAndReadCBTCreateStruct(pcbt);
  10336. ProbeForWriteCreateStruct(cbt.lpcs);
  10337. lpcsSave = cbt.lpcs;
  10338. csex.cs = *cbt.lpcs;
  10339. cbt.lpcs = (LPCREATESTRUCT)&csex;
  10340. if (bAnsi) {
  10341. ProbeForRead(csex.cs.lpszName, sizeof(CHAR), sizeof(CHAR));
  10342. RtlInitLargeAnsiString((PLARGE_ANSI_STRING)&csex.strName,
  10343. (LPSTR)csex.cs.lpszName, (UINT)-1);
  10344. if (IS_PTR(csex.cs.lpszClass)) {
  10345. ProbeForRead(csex.cs.lpszClass, sizeof(CHAR), sizeof(CHAR));
  10346. RtlInitLargeAnsiString((PLARGE_ANSI_STRING)&csex.strClass,
  10347. (LPSTR)csex.cs.lpszClass, (UINT)-1);
  10348. }
  10349. } else {
  10350. ProbeForRead(csex.cs.lpszName, sizeof(WCHAR), CHARALIGN);
  10351. RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)&csex.strName,
  10352. csex.cs.lpszName, (UINT)-1);
  10353. if (IS_PTR(csex.cs.lpszClass)) {
  10354. ProbeForRead(csex.cs.lpszClass, sizeof(WCHAR), CHARALIGN);
  10355. RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)&csex.strClass,
  10356. csex.cs.lpszClass, (UINT)-1);
  10357. }
  10358. }
  10359. } except (StubExceptionHandler(FALSE)) {
  10360. MSGERROR(0);
  10361. }
  10362. retval = xxxCallNextHookEx(
  10363. msg,
  10364. wParam,
  10365. (LPARAM)&cbt);
  10366. try {
  10367. pcbt->hwndInsertAfter = cbt.hwndInsertAfter;
  10368. lpcsSave->x = cbt.lpcs->x;
  10369. lpcsSave->y = cbt.lpcs->y;
  10370. lpcsSave->cx = cbt.lpcs->cx;
  10371. lpcsSave->cy = cbt.lpcs->cy;
  10372. } except (StubExceptionHandler(FALSE)) {
  10373. MSGERROR(0);
  10374. }
  10375. TRACE("NtUserfnHkINLPCBTCREATESTRUCT");
  10376. ENDRECV_HOOKCALL();
  10377. }
  10378. LRESULT NtUserfnHkINLPRECT(
  10379. IN DWORD nCode,
  10380. IN WPARAM wParam,
  10381. IN LPRECT lParam)
  10382. {
  10383. RECT rc;
  10384. BEGINRECV_HOOKCALL();
  10385. /*
  10386. * Probe arguments
  10387. */
  10388. try {
  10389. rc = ProbeAndReadRect((PRECT)lParam);
  10390. } except (StubExceptionHandler(FALSE)) {
  10391. MSGERROR(0);
  10392. }
  10393. retval = xxxCallNextHookEx(
  10394. nCode,
  10395. wParam,
  10396. (LPARAM)&rc);
  10397. TRACE("NtUserfnHkINLPRECT");
  10398. ENDRECV_HOOKCALL();
  10399. }
  10400. #ifdef REDIRECTION
  10401. LRESULT NtUserfnHkINLPPOINT(
  10402. IN DWORD nCode,
  10403. IN WPARAM wParam,
  10404. IN LPPOINT lParam)
  10405. {
  10406. POINT pt;
  10407. BEGINRECV_HOOKCALL();
  10408. /*
  10409. * Probe arguments
  10410. */
  10411. try {
  10412. pt = ProbeAndReadPoint((LPPOINT)lParam);
  10413. } except (StubExceptionHandler(FALSE)) {
  10414. MSGERROR(0);
  10415. }
  10416. retval = xxxCallNextHookEx(
  10417. nCode,
  10418. wParam,
  10419. (LPARAM)&pt);
  10420. TRACE("NtUserfnHkINLPPOINT");
  10421. ENDRECV_HOOKCALL();
  10422. }
  10423. /**************************************************************************\
  10424. * NtUserGetProcessRedirectionMode
  10425. *
  10426. * 04-06-01 MSadek Created.
  10427. \**************************************************************************/
  10428. BOOL
  10429. NtUserGetProcessRedirectionMode(
  10430. HANDLE hProcess,
  10431. PBOOL pbRedirectionMode)
  10432. {
  10433. PEPROCESS Process;
  10434. PPROCESSINFO ppi;
  10435. BEGINRECV(BOOL, FALSE);
  10436. if (hProcess == NtCurrentProcess()) {
  10437. ppi = PpiCurrent();
  10438. } else {
  10439. NTSTATUS Status;
  10440. Status = ObReferenceObjectByHandle(hProcess,
  10441. PROCESS_QUERY_INFORMATION,
  10442. *PsProcessType,
  10443. UserMode,
  10444. &Process,
  10445. NULL);
  10446. if (!NT_SUCCESS(Status)) {
  10447. RIPERR2(ERROR_INVALID_PARAMETER, RIP_WARNING, "NtUserGetProcessRedirectionMode: Failed with Process handle == %X, Status = %x",
  10448. hProcess, Status);
  10449. MSGERROR(0);
  10450. }
  10451. /*
  10452. * Make sure they are from the same session.
  10453. */
  10454. if (PsGetProcessSessionId(Process) != gSessionId) {
  10455. RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "NtUserGetProcessRedirectionMode: Different session. Failed with Process handle == %X", hProcess);
  10456. ObDereferenceObject(Process);
  10457. MSGERROR(0);
  10458. }
  10459. ppi = PpiFromProcess(Process);
  10460. if (ppi == NULL) {
  10461. RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "NtUserGetProcessRedirectionMode: Non GUI process. Process handle == %X", hProcess);
  10462. ObDereferenceObject(Process);
  10463. MSGERROR(0);
  10464. }
  10465. try {
  10466. ProbeAndWriteLong(pbRedirectionMode, ppi->dwRedirection & PF_REDIRECTED);
  10467. ObDereferenceObject(Process);
  10468. } except (StubExceptionHandler(TRUE)) {
  10469. ObDereferenceObject(Process);
  10470. MSGERROR(0);
  10471. }
  10472. retval = TRUE;
  10473. }
  10474. TRACE("NtUserGetProcessRedirectionMode");
  10475. ENDRECV();
  10476. }
  10477. /**************************************************************************\
  10478. * NtUserSetProcessRedirectionMode
  10479. *
  10480. * 04-06-01 MSadek Created.
  10481. \**************************************************************************/
  10482. BOOL
  10483. NtUserSetProcessRedirectionMode(
  10484. HANDLE hProcess,
  10485. BOOL bRedirectionMode)
  10486. {
  10487. PEPROCESS Process;
  10488. PPROCESSINFO ppi;
  10489. BEGINRECV(BOOL, FALSE);
  10490. /*
  10491. * A host process can not redirect itself.
  10492. */
  10493. if (hProcess == NtCurrentProcess()) {
  10494. RIPERR0(ERROR_INVALID_PARAMETER,
  10495. RIP_WARNING,
  10496. "NtUserSetProcessRedirectionMode: A process tried to change redirection mode for itself.");
  10497. MSGERROR(0);
  10498. } else {
  10499. NTSTATUS Status;
  10500. Status = ObReferenceObjectByHandle(hProcess,
  10501. PROCESS_SET_INFORMATION,
  10502. *PsProcessType,
  10503. UserMode,
  10504. &Process,
  10505. NULL);
  10506. if (!NT_SUCCESS(Status)) {
  10507. RIPERR2(ERROR_INVALID_PARAMETER,
  10508. RIP_WARNING,
  10509. "NtUserSetProcessRedirectionMode: Failed with Process handle == 0x%x, Status = 0x%x",
  10510. hProcess,
  10511. Status);
  10512. MSGERROR(0);
  10513. }
  10514. /*
  10515. * Cannot allow CSRSS to be redirected.
  10516. */
  10517. if (Process == gpepCSRSS) {
  10518. ObDereferenceObject(Process);
  10519. MSGERROR(ERROR_ACCESS_DENIED);
  10520. }
  10521. /*
  10522. * Make sure they are from the same session.
  10523. */
  10524. if (PsGetProcessSessionId(Process) != gSessionId) {
  10525. RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "NtUserSetProcessRedirectionMode: Different session. Failed with Process handle == %X", hProcess);
  10526. ObDereferenceObject(Process);
  10527. MSGERROR(0);
  10528. }
  10529. ppi = PpiFromProcess(Process);
  10530. if (ppi == NULL) {
  10531. RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "NtUserSetProcessRedirectionMode: Non GUI process. Process handle == %X", hProcess);
  10532. ObDereferenceObject(Process);
  10533. MSGERROR(0);
  10534. }
  10535. /*
  10536. * Fail if the target process is a redirection host.
  10537. */
  10538. if (ppi-> dwRedirection & PF_REDIRECTIONHOST) {
  10539. RIPERR2(ERROR_INVALID_PARAMETER, RIP_WARNING, "NtUserSetProcessRedirectionMode: trying to redirect a host process == %X, Status = %x",
  10540. hProcess, Status);
  10541. ObDereferenceObject(Process);
  10542. MSGERROR(0);
  10543. }
  10544. PpiCurrent()->dwRedirection = PF_REDIRECTIONHOST;
  10545. if (bRedirectionMode) {
  10546. ppi->dwRedirection |= PF_REDIRECTED;
  10547. } else {
  10548. ppi->dwRedirection &= ~PF_REDIRECTED;
  10549. }
  10550. xxxSetProcessRedirectionMode(bRedirectionMode, ppi);
  10551. ObDereferenceObject(Process);
  10552. retval = TRUE;
  10553. }
  10554. TRACE("NtUserSetProcessRedirectionMode");
  10555. ENDRECV();
  10556. }
  10557. /**************************************************************************\
  10558. * NtUserGetDesktopRedirectionMode
  10559. *
  10560. * 04-06-01 MSadek Created.
  10561. \**************************************************************************/
  10562. BOOL
  10563. NtUserGetDesktopRedirectionMode(
  10564. HDESK hDesk,
  10565. PBOOL pbRedirectionMode)
  10566. {
  10567. PDESKTOP pDesk;
  10568. NTSTATUS Status;
  10569. BEGINRECV(BOOL, FALSE);
  10570. Status = ValidateHdesk(hDesk, UserMode, DESKTOP_QUERY_INFORMATION, &pDesk);
  10571. if (!NT_SUCCESS(Status)) {
  10572. RIPERR2(ERROR_INVALID_PARAMETER, RIP_WARNING, "NtUserGetDesktopRedirectionMode: Failed with Desktop handle == %X, Status = %x",
  10573. hDesk, Status);
  10574. MSGERROR(0);
  10575. }
  10576. try {
  10577. ProbeAndWriteLong(pbRedirectionMode, pDesk->dwDTFlags & DF_REDIRECTED);
  10578. ObDereferenceObject(pDesk);
  10579. } except (StubExceptionHandler(TRUE)) {
  10580. ObDereferenceObject(pDesk);
  10581. MSGERROR(0);
  10582. }
  10583. retval = TRUE;
  10584. TRACE("NtUserGetDesktopRedirectionMode");
  10585. ENDRECV();
  10586. }
  10587. /**************************************************************************\
  10588. * NtUserSetDesktopRedirectionMode
  10589. *
  10590. * 04-06-01 MSadek Created.
  10591. \**************************************************************************/
  10592. BOOL
  10593. NtUserSetDesktopRedirectionMode(
  10594. HDESK hDesk,
  10595. BOOL bRedirectionMode)
  10596. {
  10597. PDESKTOP pDesk;
  10598. NTSTATUS Status;
  10599. BEGINRECV(BOOL, FALSE);
  10600. Status = ValidateHdesk(hDesk, UserMode, DESKTOP_REDIRECT, &pDesk);
  10601. if (!NT_SUCCESS(Status)) {
  10602. RIPERR2(ERROR_INVALID_PARAMETER, RIP_WARNING, "NtUserGetDesktopRedirectionMode: Failed with Desktop handle == %X, Status = %x",
  10603. hDesk, Status);
  10604. MSGERROR(0);
  10605. }
  10606. PpiCurrent()->dwRedirection = PF_REDIRECTIONHOST;
  10607. if (bRedirectionMode) {
  10608. pDesk->dwDTFlags |= DF_REDIRECTED;
  10609. } else {
  10610. pDesk->dwDTFlags &= ~DF_REDIRECTED;
  10611. }
  10612. xxxSetDesktopRedirectionMode(bRedirectionMode, pDesk, PpiCurrent());
  10613. ObDereferenceObject(pDesk);
  10614. retval = TRUE;
  10615. TRACE("NtUserSetDesktopRedirectionMode");
  10616. ENDRECV();
  10617. }
  10618. #endif // REDIRECTION
  10619. LRESULT NtUserfnHkINLPMSG(
  10620. IN int iHook,
  10621. IN DWORD nCode,
  10622. IN WPARAM wParam,
  10623. IN LPMSG lParam)
  10624. {
  10625. MSG msg;
  10626. BEGINRECV_HOOKCALL();
  10627. /*
  10628. * Probe arguments
  10629. */
  10630. try {
  10631. msg = ProbeAndReadMessage((PMSG)lParam);
  10632. } except (StubExceptionHandler(FALSE)) {
  10633. MSGERROR(0);
  10634. }
  10635. retval = xxxCallNextHookEx(
  10636. nCode,
  10637. wParam,
  10638. (LPARAM)&msg);
  10639. /*
  10640. * If this is GetMessageHook, the hook should be
  10641. * able to change the message, as stated in SDK document.
  10642. */
  10643. if (iHook == WH_GETMESSAGE) {
  10644. try {
  10645. *(PMSG)lParam = msg;
  10646. } except (StubExceptionHandler(FALSE)) {
  10647. MSGERROR(0);
  10648. }
  10649. }
  10650. TRACE("NtUserfnHkINLPMSG");
  10651. ENDRECV_HOOKCALL();
  10652. }
  10653. LRESULT NtUserfnHkINLPDEBUGHOOKSTRUCT(
  10654. IN DWORD nCode,
  10655. IN WPARAM wParam,
  10656. IN LPDEBUGHOOKINFO lParam)
  10657. {
  10658. DEBUGHOOKINFO hookinfo;
  10659. DWORD cbDbgLParam;
  10660. BEGINRECV_HOOKCALL();
  10661. /*
  10662. * Probe arguments
  10663. */
  10664. try {
  10665. hookinfo = ProbeAndReadHookInfo((PDEBUGHOOKINFO)lParam);
  10666. cbDbgLParam = GetDebugHookLParamSize(wParam, &hookinfo);
  10667. ProbeForRead(hookinfo.lParam, cbDbgLParam, DATAALIGN);
  10668. } except (StubExceptionHandler(FALSE)) {
  10669. MSGERROR(0);
  10670. }
  10671. retval = xxxCallNextHookEx(
  10672. nCode,
  10673. wParam,
  10674. (LPARAM)&hookinfo);
  10675. TRACE("NtUserfnHkINLPDEBUGHOOKSTRUCT");
  10676. ENDRECV_HOOKCALL();
  10677. }
  10678. LRESULT NtUserfnHkOPTINLPEVENTMSG(
  10679. IN DWORD nCode,
  10680. IN WPARAM wParam,
  10681. IN OUT LPEVENTMSGMSG lParam OPTIONAL)
  10682. {
  10683. EVENTMSG event;
  10684. BEGINRECV_HOOKCALL();
  10685. /*
  10686. * Probe arguments
  10687. */
  10688. if (ARGUMENT_PRESENT(lParam)) {
  10689. try {
  10690. ProbeForWriteEvent((LPEVENTMSGMSG)lParam);
  10691. event = *(LPEVENTMSGMSG)lParam;
  10692. } except (StubExceptionHandler(FALSE)) {
  10693. MSGERROR(0);
  10694. }
  10695. }
  10696. retval = xxxCallNextHookEx(
  10697. nCode,
  10698. wParam,
  10699. (LPARAM)(lParam ? &event : NULL));
  10700. if (ARGUMENT_PRESENT(lParam)) {
  10701. try {
  10702. *(LPEVENTMSGMSG)lParam = event;
  10703. } except (StubExceptionHandler(FALSE)) {
  10704. MSGERROR(0);
  10705. }
  10706. }
  10707. TRACE("NtUserfnHkINLPEVENTMSG");
  10708. ENDRECV_HOOKCALL();
  10709. }
  10710. LRESULT NtUserfnHkINLPMOUSEHOOKSTRUCTEX(
  10711. IN DWORD nCode,
  10712. IN WPARAM wParam,
  10713. IN LPMOUSEHOOKSTRUCTEX lParam)
  10714. {
  10715. MOUSEHOOKSTRUCTEX mousehook;
  10716. BEGINRECV_HOOKCALL();
  10717. /*
  10718. * Probe arguments
  10719. */
  10720. try {
  10721. mousehook = ProbeAndReadMouseHook((PMOUSEHOOKSTRUCTEX)lParam);
  10722. } except (StubExceptionHandler(FALSE)) {
  10723. MSGERROR(0);
  10724. }
  10725. retval = xxxCallNextHookEx(
  10726. nCode,
  10727. wParam,
  10728. (LPARAM)&mousehook);
  10729. TRACE("NtUserfnHkINLPMOUSEHOOKSTRUCTEX");
  10730. ENDRECV_HOOKCALL();
  10731. }
  10732. LRESULT NtUserfnHkINLPKBDLLHOOKSTRUCT(
  10733. IN DWORD nCode,
  10734. IN WPARAM wParam,
  10735. IN LPKBDLLHOOKSTRUCT lParam)
  10736. {
  10737. KBDLLHOOKSTRUCT kbdhook;
  10738. BEGINRECV_HOOKCALL();
  10739. /*
  10740. * Probe arguments
  10741. */
  10742. try {
  10743. kbdhook = ProbeAndReadKbdHook((PKBDLLHOOKSTRUCT)lParam);
  10744. } except (StubExceptionHandler(FALSE)) {
  10745. MSGERROR(0);
  10746. }
  10747. retval = xxxCallNextHookEx(
  10748. nCode,
  10749. wParam,
  10750. (LPARAM)&kbdhook);
  10751. TRACE("NtUserfnHkINLPKBDLLHOOKSTRUCT");
  10752. ENDRECV_HOOKCALL();
  10753. }
  10754. LRESULT NtUserfnHkINLPMSLLHOOKSTRUCT(
  10755. IN DWORD nCode,
  10756. IN WPARAM wParam,
  10757. IN LPMSLLHOOKSTRUCT lParam)
  10758. {
  10759. MSLLHOOKSTRUCT msllhook;
  10760. BEGINRECV_HOOKCALL();
  10761. /*
  10762. * Probe arguments
  10763. */
  10764. try {
  10765. msllhook = ProbeAndReadMsllHook((PMSLLHOOKSTRUCT)lParam);
  10766. } except (StubExceptionHandler(FALSE)) {
  10767. MSGERROR(0);
  10768. }
  10769. retval = xxxCallNextHookEx(
  10770. nCode,
  10771. wParam,
  10772. (LPARAM)&msllhook);
  10773. TRACE("NtUserfnHkINLPMSLLHOOKSTRUCT");
  10774. ENDRECV_HOOKCALL();
  10775. }
  10776. #ifdef REDIRECTION
  10777. LRESULT NtUserfnHkINLPHTHOOKSTRUCT(
  10778. IN DWORD nCode,
  10779. IN WPARAM wParam,
  10780. IN LPHTHOOKSTRUCT lParam)
  10781. {
  10782. HTHOOKSTRUCT hthook;
  10783. BEGINRECV_HOOKCALL();
  10784. /*
  10785. * Probe arguments
  10786. */
  10787. try {
  10788. hthook = ProbeAndReadHTHook((PHTHOOKSTRUCT)lParam);
  10789. } except (StubExceptionHandler(FALSE)) {
  10790. MSGERROR(0);
  10791. }
  10792. retval = xxxCallNextHookEx(
  10793. nCode,
  10794. wParam,
  10795. (LPARAM)&hthook);
  10796. TRACE("NtUserfnHkINLPHTHOOKSTRUCT");
  10797. ENDRECV_HOOKCALL();
  10798. }
  10799. #endif // REDIRECTION
  10800. LRESULT NtUserfnHkINLPCBTACTIVATESTRUCT(
  10801. IN DWORD nCode,
  10802. IN WPARAM wParam,
  10803. IN LPCBTACTIVATESTRUCT lParam)
  10804. {
  10805. CBTACTIVATESTRUCT cbtactivate;
  10806. BEGINRECV_HOOKCALL();
  10807. /*
  10808. * Probe arguments
  10809. */
  10810. try {
  10811. cbtactivate = ProbeAndReadCBTActivateStruct((LPCBTACTIVATESTRUCT)lParam);
  10812. } except (StubExceptionHandler(FALSE)) {
  10813. MSGERROR(0);
  10814. }
  10815. retval = xxxCallNextHookEx(
  10816. nCode,
  10817. wParam,
  10818. (LPARAM)&cbtactivate);
  10819. TRACE("NtUserfnHkINLPCBTACTIVATESTRUCT");
  10820. ENDRECV_HOOKCALL();
  10821. }
  10822. LRESULT NtUserCallNextHookEx(
  10823. int nCode,
  10824. WPARAM wParam,
  10825. LPARAM lParam,
  10826. BOOL bAnsi)
  10827. {
  10828. BEGINRECV(LRESULT, 0);
  10829. if (PtiCurrent()->sphkCurrent == NULL) {
  10830. MSGERROR(0);
  10831. }
  10832. switch (PtiCurrent()->sphkCurrent->iHook) {
  10833. case WH_CBT:
  10834. /*
  10835. * There are many different types of CBT hooks!
  10836. */
  10837. switch (nCode) {
  10838. case HCBT_CLICKSKIPPED:
  10839. goto MouseHook;
  10840. break;
  10841. case HCBT_CREATEWND:
  10842. /*
  10843. * This hook type points to a CREATESTRUCT, so we need to
  10844. * be fancy it's thunking, because a CREATESTRUCT contains
  10845. * a pointer to CREATEPARAMS which can be anything... so
  10846. * funnel this through our message thunks.
  10847. */
  10848. retval = NtUserfnHkINLPCBTCREATESTRUCT(
  10849. nCode,
  10850. wParam,
  10851. (LPCBT_CREATEWND)lParam,
  10852. bAnsi);
  10853. break;
  10854. #ifdef REDIRECTION
  10855. case HCBT_GETCURSORPOS:
  10856. /*
  10857. * This hook type points to a POINT structure.
  10858. */
  10859. retval = NtUserfnHkINLPPOINT(nCode, wParam, (LPPOINT)lParam);
  10860. break;
  10861. #endif // REDIRECTION
  10862. case HCBT_MOVESIZE:
  10863. /*
  10864. * This hook type points to a RECT structure.
  10865. */
  10866. retval = NtUserfnHkINLPRECT(nCode, wParam, (LPRECT)lParam);
  10867. break;
  10868. case HCBT_ACTIVATE:
  10869. /*
  10870. * This hook type points to a CBTACTIVATESTRUCT
  10871. */
  10872. retval = NtUserfnHkINLPCBTACTIVATESTRUCT(nCode, wParam,
  10873. (LPCBTACTIVATESTRUCT)lParam);
  10874. break;
  10875. default:
  10876. /*
  10877. * The rest of the cbt hooks are all dword parameters.
  10878. */
  10879. retval = xxxCallNextHookEx(
  10880. nCode,
  10881. wParam,
  10882. lParam);
  10883. break;
  10884. }
  10885. break;
  10886. case WH_FOREGROUNDIDLE:
  10887. case WH_KEYBOARD:
  10888. case WH_SHELL:
  10889. /*
  10890. * These are dword parameters and are therefore real easy.
  10891. */
  10892. retval = xxxCallNextHookEx(
  10893. nCode,
  10894. wParam,
  10895. lParam);
  10896. break;
  10897. case WH_MSGFILTER:
  10898. case WH_SYSMSGFILTER:
  10899. case WH_GETMESSAGE:
  10900. /*
  10901. * These take an lpMsg as their last parameter. Since these are
  10902. * exclusively posted parameters, and since nowhere on the server
  10903. * do we post a message with a pointer to some other structure in
  10904. * it, the lpMsg structure contents can all be treated verbatim.
  10905. */
  10906. retval = NtUserfnHkINLPMSG(PtiCurrent()->sphkCurrent->iHook, nCode, wParam, (LPMSG)lParam);
  10907. break;
  10908. case WH_JOURNALPLAYBACK:
  10909. case WH_JOURNALRECORD:
  10910. /*
  10911. * These take an OPTIONAL lpEventMsg.
  10912. */
  10913. retval = NtUserfnHkOPTINLPEVENTMSG(nCode, wParam, (LPEVENTMSGMSG)lParam);
  10914. break;
  10915. case WH_DEBUG:
  10916. /*
  10917. * This takes an lpDebugHookStruct.
  10918. */
  10919. retval = NtUserfnHkINLPDEBUGHOOKSTRUCT(nCode, wParam, (LPDEBUGHOOKINFO)lParam);
  10920. break;
  10921. case WH_KEYBOARD_LL:
  10922. /*
  10923. * This takes an lpKbdllHookStruct.
  10924. */
  10925. retval = NtUserfnHkINLPKBDLLHOOKSTRUCT(nCode, wParam, (LPKBDLLHOOKSTRUCT)lParam);
  10926. break;
  10927. case WH_MOUSE_LL:
  10928. /*
  10929. * This takes an lpMsllHookStruct.
  10930. */
  10931. retval = NtUserfnHkINLPMSLLHOOKSTRUCT(nCode, wParam, (LPMSLLHOOKSTRUCT)lParam);
  10932. break;
  10933. case WH_MOUSE:
  10934. /*
  10935. * This takes an lpMouseHookStructEx.
  10936. */
  10937. MouseHook:
  10938. retval = NtUserfnHkINLPMOUSEHOOKSTRUCTEX(nCode, wParam, (LPMOUSEHOOKSTRUCTEX)lParam);
  10939. break;
  10940. #ifdef REDIRECTION
  10941. case WH_HITTEST:
  10942. /*
  10943. * This takes an lpHTHookStruct.
  10944. */
  10945. retval = NtUserfnHkINLPHTHOOKSTRUCT(nCode, wParam, (LPHTHOOKSTRUCT)lParam);
  10946. break;
  10947. #endif // REDIRECTION
  10948. default:
  10949. RIPMSG1(RIP_WARNING, "NtUserCallNextHookEx: Invalid hook type %x",
  10950. PtiCurrent()->sphkCurrent->iHook);
  10951. MSGERROR(0);
  10952. }
  10953. TRACE("NtUserCallNextHookEx");
  10954. ENDRECV();
  10955. }
  10956. HIMC NtUserCreateInputContext(
  10957. IN ULONG_PTR dwClientImcData)
  10958. {
  10959. BEGINRECV(HIMC, (HIMC)NULL);
  10960. ValidateIMMEnabled();
  10961. if (dwClientImcData == 0) {
  10962. RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid hMemClientIC parameter");
  10963. MSGERROR(0);
  10964. }
  10965. retval = (HIMC)CreateInputContext(dwClientImcData);
  10966. retval = (HIMC)PtoH((PVOID)retval);
  10967. TRACE("NtUserCreateInputContext");
  10968. ENDRECV();
  10969. }
  10970. BOOL NtUserDestroyInputContext(
  10971. IN HIMC hImc)
  10972. {
  10973. PIMC pImc;
  10974. BEGINATOMICRECV(BOOL, FALSE);
  10975. ValidateIMMEnabled();
  10976. ValidateHIMC(pImc, hImc);
  10977. retval = DestroyInputContext(pImc);
  10978. TRACE("NtUserDestroyInputContext");
  10979. ENDATOMICRECV();
  10980. }
  10981. AIC_STATUS NtUserAssociateInputContext(
  10982. IN HWND hwnd,
  10983. IN HIMC hImc,
  10984. IN DWORD dwFlag)
  10985. {
  10986. PIMC pImc;
  10987. BEGINATOMICRECV_HWND(AIC_STATUS, AIC_ERROR, hwnd);
  10988. ValidateIMMEnabled();
  10989. ValidateHIMCOPT(pImc, hImc);
  10990. retval = AssociateInputContextEx(pwnd, pImc, dwFlag);
  10991. TRACE("NtUserAssociateInputContext");
  10992. ENDATOMICRECV_HWND();
  10993. }
  10994. BOOL NtUserUpdateInputContext(
  10995. IN HIMC hImc,
  10996. IN UPDATEINPUTCONTEXTCLASS UpdateType,
  10997. IN ULONG_PTR UpdateValue)
  10998. {
  10999. PIMC pImc;
  11000. BEGINATOMICRECV(BOOL, FALSE);
  11001. ValidateIMMEnabled();
  11002. ValidateHIMC(pImc, hImc);
  11003. retval = UpdateInputContext(pImc, UpdateType, UpdateValue);
  11004. TRACE("NtUserUpdateInputContext");
  11005. ENDATOMICRECV();
  11006. }
  11007. ULONG_PTR NtUserQueryInputContext(
  11008. IN HIMC hImc,
  11009. IN INPUTCONTEXTINFOCLASS InputContextInfo)
  11010. {
  11011. PTHREADINFO ptiImc;
  11012. PIMC pImc;
  11013. BEGINRECV_SHARED(ULONG_PTR, 0);
  11014. ValidateIMMEnabled();
  11015. ValidateHIMC(pImc, hImc);
  11016. ptiImc = GETPTI(pImc);
  11017. switch (InputContextInfo) {
  11018. case InputContextProcess:
  11019. retval = (ULONG_PTR)PsGetThreadProcessId(ptiImc->pEThread);
  11020. break;
  11021. case InputContextThread:
  11022. retval = (ULONG_PTR)GETPTIID(ptiImc);
  11023. break;
  11024. case InputContextDefaultImeWindow:
  11025. retval = (ULONG_PTR)HW(ptiImc->spwndDefaultIme);
  11026. break;
  11027. case InputContextDefaultInputContext:
  11028. retval = (ULONG_PTR)PtoH(ptiImc->spDefaultImc);
  11029. break;
  11030. }
  11031. ENDRECV_SHARED();
  11032. }
  11033. NTSTATUS NtUserBuildHimcList( // private IMM BuildHimcList
  11034. IN DWORD idThread,
  11035. IN UINT cHimcMax,
  11036. OUT HIMC *phimcFirst,
  11037. OUT PUINT pcHimcNeeded)
  11038. {
  11039. PTHREADINFO pti;
  11040. UINT cHimcNeeded;
  11041. BEGINATOMICRECV(NTSTATUS, STATUS_UNSUCCESSFUL);
  11042. ValidateIMMEnabled();
  11043. switch (idThread) {
  11044. case 0:
  11045. pti = PtiCurrent();
  11046. break;
  11047. case (DWORD)-1:
  11048. pti = NULL;
  11049. break;
  11050. default:
  11051. pti = PtiFromThreadId(idThread);
  11052. if (pti == NULL || pti->rpdesk == NULL) {
  11053. MSGERROR(0);
  11054. }
  11055. break;
  11056. }
  11057. /*
  11058. * Probe arguments
  11059. */
  11060. try {
  11061. ProbeForWriteBuffer(phimcFirst, cHimcMax, sizeof(DWORD));
  11062. ProbeForWriteUlong(pcHimcNeeded);
  11063. } except (StubExceptionHandler(FALSE)) {
  11064. MSGERROR(0);
  11065. }
  11066. /*
  11067. * phimcFirst is client-side.
  11068. */
  11069. cHimcNeeded = BuildHimcList(pti, cHimcMax, phimcFirst);
  11070. if (cHimcNeeded <= cHimcMax) {
  11071. retval = STATUS_SUCCESS;
  11072. } else {
  11073. retval = STATUS_BUFFER_TOO_SMALL;
  11074. }
  11075. try {
  11076. *pcHimcNeeded = cHimcNeeded;
  11077. } except (StubExceptionHandler(FALSE)) {
  11078. }
  11079. TRACE("NtUserBuildHimcList");
  11080. ENDATOMICRECV();
  11081. }
  11082. BOOL NtUserGetImeInfoEx( // private ImmGetImeInfoEx
  11083. IN OUT PIMEINFOEX piiex,
  11084. IN IMEINFOEXCLASS SearchType)
  11085. {
  11086. IMEINFOEX iiex;
  11087. BEGINRECV_SHARED(BOOL, FALSE);
  11088. ValidateIMMEnabled();
  11089. try {
  11090. ProbeForWrite(piiex, sizeof(*piiex), sizeof(BYTE));
  11091. RtlCopyMemory(&iiex, piiex, sizeof(IMEINFOEX));
  11092. } except (StubExceptionHandler(FALSE)) {
  11093. MSGERROR(0);
  11094. }
  11095. retval = GetImeInfoEx(
  11096. _GetProcessWindowStation(NULL),
  11097. &iiex,
  11098. SearchType);
  11099. try {
  11100. RtlCopyMemory(piiex, &iiex, sizeof(IMEINFOEX));
  11101. } except (StubExceptionHandler(FALSE)) {
  11102. }
  11103. TRACE("NtUserGetImeInfoEx");
  11104. ENDRECV_SHARED();
  11105. }
  11106. BOOL NtUserSetImeInfoEx(
  11107. IN PIMEINFOEX piiex)
  11108. {
  11109. IMEINFOEX iiex;
  11110. BEGINRECV(BOOL, FALSE);
  11111. ValidateIMMEnabled();
  11112. /*
  11113. * Probe arguments
  11114. */
  11115. try {
  11116. ProbeForRead(piiex, sizeof(*piiex), sizeof(BYTE));
  11117. RtlCopyMemory(&iiex, piiex, sizeof(IMEINFOEX));
  11118. } except (StubExceptionHandler(FALSE)) {
  11119. MSGERROR(0);
  11120. }
  11121. retval = SetImeInfoEx(
  11122. _GetProcessWindowStation(NULL),
  11123. &iiex);
  11124. TRACE("NtUserSetImeInfoEx");
  11125. ENDRECV();
  11126. }
  11127. BOOL NtUserGetImeHotKey(
  11128. IN DWORD dwID,
  11129. OUT PUINT puModifiers,
  11130. OUT PUINT puVKey,
  11131. OUT LPHKL phkl)
  11132. {
  11133. UINT uModifiers;
  11134. UINT uVKey;
  11135. HKL hkl;
  11136. LPHKL phklIn = NULL;
  11137. BEGINRECV(BOOL, FALSE);
  11138. try {
  11139. ProbeForWriteUlong(((PULONG)puModifiers));
  11140. ProbeForWriteUlong(((PULONG)puVKey));
  11141. if (ARGUMENT_PRESENT(phkl)) {
  11142. ProbeForWriteHandle((PHANDLE)phkl);
  11143. phklIn = &hkl;
  11144. }
  11145. } except (StubExceptionHandler(FALSE)) {
  11146. MSGERROR(0);
  11147. }
  11148. retval = GetImeHotKey( dwID, &uModifiers, &uVKey, phklIn);
  11149. if (retval) {
  11150. try {
  11151. *puModifiers = uModifiers;
  11152. *puVKey = uVKey;
  11153. if (ARGUMENT_PRESENT(phkl)) {
  11154. *phkl = *phklIn;
  11155. }
  11156. } except (StubExceptionHandler(FALSE)) {
  11157. MSGERROR(0);
  11158. }
  11159. }
  11160. TRACE("NtUserGetImeHotKey");
  11161. ENDRECV();
  11162. }
  11163. BOOL NtUserSetImeHotKey(
  11164. IN DWORD dwID,
  11165. IN UINT uModifiers,
  11166. IN UINT uVKey,
  11167. IN HKL hkl,
  11168. IN DWORD dwFlags)
  11169. {
  11170. BEGINRECV(BOOL, FALSE);
  11171. retval = SetImeHotKey( dwID, uModifiers, uVKey, hkl, dwFlags );
  11172. TRACE("NtUserSetImeHotKey");
  11173. ENDRECV();
  11174. }
  11175. /*
  11176. * Set per-window application level for IME control.
  11177. * Used only for Korean 3.x ( both 16 bit and 32 bit)
  11178. * applications.
  11179. *
  11180. * return value
  11181. *
  11182. * TRUE : success
  11183. * FALSE: error
  11184. */
  11185. BOOL NtUserSetAppImeLevel(
  11186. IN HWND hwnd,
  11187. IN DWORD dwLevel)
  11188. {
  11189. BEGINRECV_HWND(BOOL, FALSE, hwnd);
  11190. ValidateIMMEnabled();
  11191. if ( GETPTI(pwnd)->ppi == PpiCurrent() ) {
  11192. InternalSetProp(pwnd, PROP_IMELEVEL, LongToHandle(dwLevel), PROPF_INTERNAL | PROPF_NOPOOL);
  11193. retval = TRUE;
  11194. } else {
  11195. MSGERROR(0);
  11196. }
  11197. TRACE("NtUserSetAppImeLevel");
  11198. ENDRECV_HWND();
  11199. }
  11200. /*
  11201. * Get per-window application level for IME control.
  11202. * Used only for Korean 3.x ( both 16 bit and 32 bit)
  11203. * applications.
  11204. *
  11205. * return value
  11206. *
  11207. * 0 : error
  11208. * non zero value : level
  11209. */
  11210. DWORD NtUserGetAppImeLevel(
  11211. IN HWND hwnd)
  11212. {
  11213. BEGINRECV_HWND_SHARED(DWORD, 0, hwnd);
  11214. ValidateIMMEnabled();
  11215. if ( GETPTI(pwnd)->ppi == PtiCurrentShared()->ppi ) {
  11216. retval = (DWORD)(ULONG_PTR)_GetProp(pwnd, PROP_IMELEVEL, TRUE);
  11217. } else {
  11218. MSGERROR(0);
  11219. }
  11220. TRACE("NtUserGetAppImeLevel");
  11221. ENDRECV_HWND_SHARED();
  11222. }
  11223. DWORD NtUserCheckImeHotKey(
  11224. UINT uVKey,
  11225. LPARAM lParam)
  11226. {
  11227. PIMEHOTKEYOBJ pImeHotKeyObj;
  11228. BEGINRECV(DWORD, IME_INVALID_HOTKEY);
  11229. if (gpqForeground == NULL)
  11230. MSGERROR(0);
  11231. ValidateIMMEnabled();
  11232. pImeHotKeyObj = CheckImeHotKey(gpqForeground, uVKey, lParam);
  11233. if (pImeHotKeyObj) {
  11234. retval = pImeHotKeyObj->hk.dwHotKeyID;
  11235. } else {
  11236. retval = IME_INVALID_HOTKEY;
  11237. }
  11238. TRACE("NtUserCheckImeHotKey");
  11239. ENDRECV();
  11240. }
  11241. /**************************************************************************\
  11242. * NtUserSetImeOwnerWindow
  11243. *
  11244. * History:
  11245. * 17-July-2001 Mohamed Removed re-ownership code and created
  11246. ImeSetOwnerWindow. Added this call for ownership
  11247. assignment of spwndActive to avoid cyclic
  11248. ownership.
  11249. \**************************************************************************/
  11250. BOOL NtUserSetImeOwnerWindow(
  11251. IN HWND hwndIme,
  11252. IN HWND hwndFocus)
  11253. {
  11254. PWND pwndFocus;
  11255. BEGINATOMICRECV_HWND(BOOL, FALSE, hwndIme);
  11256. ValidateIMMEnabled();
  11257. /*
  11258. * Make sure this really is an IME window.
  11259. */
  11260. if (GETFNID(pwnd) != FNID_IME)
  11261. MSGERROR(0);
  11262. ValidateHWNDOPT(pwndFocus, hwndFocus);
  11263. if (pwndFocus != NULL) {
  11264. ImeSetOwnerWindow(pwnd, pwndFocus);
  11265. ImeCheckTopmost(pwnd);
  11266. } else {
  11267. PTHREADINFO ptiImeWnd = GETPTI(pwnd);
  11268. PWND pwndActive = ptiImeWnd->pq->spwndActive;
  11269. /*
  11270. * If pwndFocus == NULL, active window in the queue should become the
  11271. * owner window of the IME window, except: if IME related windows
  11272. * somehow got a focus, or the active window belongs to the other thread.
  11273. */
  11274. if (pwndActive == NULL || pwndActive != pwnd->spwndOwner) {
  11275. if (pwndActive == NULL || IsWndImeRelated(pwndActive) || ptiImeWnd != GETPTI(pwndActive)) {
  11276. /*
  11277. * We should avoid improper window to be an owner of IME window.
  11278. */
  11279. ImeSetFutureOwner(pwnd, pwnd->spwndOwner);
  11280. } else {
  11281. ImeSetOwnerWindow(pwnd, pwndActive);
  11282. }
  11283. ImeCheckTopmost(pwnd);
  11284. }
  11285. }
  11286. retval = TRUE;
  11287. TRACE("NtUserSetImeNewOwner");
  11288. ENDATOMICRECV_HWND();
  11289. }
  11290. VOID NtUserSetThreadLayoutHandles(
  11291. IN HKL hklNew,
  11292. IN HKL hklOld)
  11293. {
  11294. PTHREADINFO ptiCurrent;
  11295. PKL pklNew;
  11296. BEGINRECV_VOID();
  11297. ptiCurrent = PtiCurrent();
  11298. if (ptiCurrent->spklActive != NULL && ptiCurrent->spklActive->hkl != hklOld)
  11299. MSGERROR_VOID();
  11300. if ((pklNew = HKLtoPKL(ptiCurrent, hklNew)) == NULL)
  11301. MSGERROR_VOID();
  11302. /*
  11303. * hklPrev is only used for IME, non-IME toggle hotkey.
  11304. * The purpose we remember hklPrev is to jump from
  11305. * non-IME keyboard layout to the most recently used
  11306. * IME layout, or to jump from an IME layout to
  11307. * the most recently used non-IME layout. Therefore
  11308. * piti->hklPrev is updated only when [ IME -> non-IME ]
  11309. * or [ non-IME -> IME ] transition is happened.
  11310. */
  11311. if (IS_IME_KBDLAYOUT(hklNew) ^ IS_IME_KBDLAYOUT(hklOld))
  11312. ptiCurrent->hklPrev = hklOld;
  11313. Lock(&ptiCurrent->spklActive, pklNew);
  11314. TRACEVOID("NtUserSetThreadLayoutHandles");
  11315. ENDRECV_VOID();
  11316. }
  11317. VOID NtUserNotifyIMEStatus(
  11318. IN HWND hwnd,
  11319. IN DWORD dwOpen,
  11320. IN DWORD dwConversion)
  11321. {
  11322. BEGINRECV_HWNDLOCK_VOID(hwnd);
  11323. ValidateIMMEnabledVOID();
  11324. xxxNotifyIMEStatus( pwnd, dwOpen, dwConversion );
  11325. TRACEVOID("NtUserNotifyIMEStatus");
  11326. ENDRECV_HWNDLOCK_VOID()
  11327. }
  11328. BOOL NtUserDisableThreadIme(
  11329. IN DWORD dwThreadId)
  11330. {
  11331. PTHREADINFO ptiCurrent, pti;
  11332. BEGINRECV(BOOL, FALSE);
  11333. ValidateIMMEnabled();
  11334. ptiCurrent = PtiCurrent();
  11335. if (dwThreadId == -1) {
  11336. // IME processing is disabled for all the thread in the current process
  11337. ptiCurrent->ppi->W32PF_Flags |= W32PF_DISABLEIME;
  11338. // destory IME stuff
  11339. pti = ptiCurrent->ppi->ptiList;
  11340. while (pti) {
  11341. pti->TIF_flags |= TIF_DISABLEIME;
  11342. if (pti->spwndDefaultIme != NULL) {
  11343. xxxDestroyWindow(pti->spwndDefaultIme);
  11344. // Start the search over from beginning
  11345. // Since the ptilist may be updated
  11346. pti = ptiCurrent->ppi->ptiList;
  11347. continue;
  11348. }
  11349. pti = pti->ptiSibling;
  11350. }
  11351. } else {
  11352. if (dwThreadId == 0) {
  11353. pti = ptiCurrent;
  11354. } else {
  11355. pti = PtiFromThreadId(dwThreadId);
  11356. if (pti == NULL || pti->ppi != ptiCurrent->ppi)
  11357. MSGERROR(0);
  11358. }
  11359. pti->TIF_flags |= TIF_DISABLEIME;
  11360. if (pti->spwndDefaultIme != NULL) {
  11361. xxxDestroyWindow(pti->spwndDefaultIme);
  11362. }
  11363. }
  11364. retval = TRUE;
  11365. TRACE("NtUserDisableThreadIme");
  11366. ENDRECV();
  11367. }
  11368. BOOL
  11369. NtUserEnumDisplayMonitors( // API EnumDisplayMonitors
  11370. IN HDC hdc,
  11371. IN LPCRECT lprcClip,
  11372. IN MONITORENUMPROC lpfnEnum,
  11373. IN LPARAM dwData)
  11374. {
  11375. RECT rc;
  11376. LPRECT lprc = (LPRECT) lprcClip;
  11377. BEGINRECV(BOOL, FALSE);
  11378. /*
  11379. * Probe arguments
  11380. */
  11381. if (ARGUMENT_PRESENT(lprc)) {
  11382. try {
  11383. rc = ProbeAndReadRect(lprc);
  11384. lprc = &rc;
  11385. } except (StubExceptionHandler(TRUE)) {
  11386. MSGERROR(0);
  11387. }
  11388. }
  11389. retval = xxxEnumDisplayMonitors(
  11390. hdc,
  11391. lprc,
  11392. lpfnEnum,
  11393. dwData,
  11394. FALSE);
  11395. TRACE("NtUserEnumDisplayMonitors");
  11396. ENDRECV();
  11397. }
  11398. #ifdef PRERELEASE
  11399. /*
  11400. * NtUserQueryUserCounters() retrieves statistics on win32k
  11401. *
  11402. * QUERYUSER_TYPE_USER retrieves the handle counters
  11403. *
  11404. * QUERYUSER_TYPE_CS will fill the result buffer with USER critical section
  11405. * usage data.
  11406. */
  11407. BOOL NtUserQueryUserCounters( // private QueryUserCounters
  11408. IN DWORD dwQueryType,
  11409. IN LPVOID pvIn,
  11410. IN DWORD dwInSize,
  11411. OUT LPVOID pvResult,
  11412. IN DWORD dwOutSize)
  11413. {
  11414. PDWORD pdwInternalIn = NULL;
  11415. PDWORD pdwInternalResult = NULL;
  11416. BEGINRECV(BOOL, FALSE);
  11417. #if defined (USER_PERFORMANCE)
  11418. if (dwQueryType == QUERYUSER_CS) {
  11419. CSSTATISTICS* pcsData;
  11420. if (dwOutSize != sizeof(CSSTATISTICS)) {
  11421. MSGERROR(0);
  11422. }
  11423. try {
  11424. ProbeForWrite((PDWORD)pvResult, dwOutSize, sizeof(DWORD));
  11425. /*
  11426. * Checking for overflow on these counters is caller responsability
  11427. */
  11428. pcsData = (CSSTATISTICS*)pvResult;
  11429. pcsData->cExclusive = gCSStatistics.cExclusive;
  11430. pcsData->cShared = gCSStatistics.cShared;
  11431. pcsData->i64TimeExclusive = gCSStatistics.i64TimeExclusive;
  11432. } except (StubExceptionHandler(FALSE)) {
  11433. MSGERROR(0);
  11434. }
  11435. retval = TRUE;
  11436. MSGERROR_VOID();
  11437. } else
  11438. #endif // USER_PERFORMANCE
  11439. if (dwQueryType == QUERYUSER_HANDLES) {
  11440. /*
  11441. * Probe arguments, dwInSize should be multiple of 4
  11442. */
  11443. if (dwInSize & (sizeof(DWORD)-1) ||
  11444. dwOutSize != TYPE_CTYPES*dwInSize) {
  11445. MSGERROR(0)
  11446. }
  11447. try {
  11448. ProbeForRead((PDWORD)pvIn, dwInSize, sizeof(DWORD));
  11449. pdwInternalIn = UserAllocPoolWithQuota(dwInSize, TAG_SYSTEM);
  11450. if (!pdwInternalIn) {
  11451. ExRaiseStatus(STATUS_NO_MEMORY);
  11452. }
  11453. RtlCopyMemory(pdwInternalIn, pvIn, dwInSize);
  11454. ProbeForWrite(pvResult, dwOutSize, sizeof(DWORD));
  11455. pdwInternalResult = UserAllocPoolWithQuota(dwOutSize, TAG_SYSTEM);
  11456. if (!pdwInternalResult) {
  11457. ExRaiseStatus(STATUS_NO_MEMORY);
  11458. }
  11459. } except (StubExceptionHandler(FALSE)) {
  11460. MSGERRORCLEANUP(0);
  11461. }
  11462. _QueryUserHandles(pdwInternalIn,
  11463. dwInSize/sizeof(DWORD),
  11464. (DWORD (*)[TYPE_CTYPES])pdwInternalResult);
  11465. retval = TRUE;
  11466. try {
  11467. RtlCopyMemory(pvResult, pdwInternalResult, dwOutSize);
  11468. } except (StubExceptionHandler(FALSE)) {
  11469. MSGERRORCLEANUP(0);
  11470. }
  11471. } else {
  11472. MSGERROR(0);
  11473. }
  11474. CLEANUPRECV();
  11475. if (pdwInternalIn) {
  11476. UserFreePool(pdwInternalIn);
  11477. }
  11478. if (pdwInternalResult) {
  11479. UserFreePool(pdwInternalResult);
  11480. }
  11481. TRACE("NtUserQueryCounters");
  11482. ENDRECV();
  11483. }
  11484. #endif
  11485. /***************************************************************************\
  11486. * NtUserINOUTGETMENUINFO
  11487. *
  11488. * History:
  11489. * 11-12-96 GerardoB - Created
  11490. \***************************************************************************/
  11491. MESSAGECALL(INOUTMENUGETOBJECT)
  11492. {
  11493. MENUGETOBJECTINFO mgoi;
  11494. BEGINRECV_MESSAGECALL(0);
  11495. TRACETHUNK("fnINOUTMENUGETOBJECT");
  11496. UNREFERENCED_PARAMETER(bAnsi);
  11497. try {
  11498. /*
  11499. * Capture now so xxxInterSendMsgEx won't have to.
  11500. */
  11501. mgoi = ProbeAndReadMenuGetObjectInfo((PMENUGETOBJECTINFO)lParam);
  11502. } except (StubExceptionHandler(FALSE)) {
  11503. MSGERROR(0);
  11504. }
  11505. retval = CALLPROC(xpfnProc)(
  11506. pwnd,
  11507. msg,
  11508. wParam,
  11509. (LPARAM)&mgoi,
  11510. xParam);
  11511. try {
  11512. *((PMENUGETOBJECTINFO)lParam) = mgoi;
  11513. } except (StubExceptionHandler(FALSE)) {
  11514. }
  11515. TRACE("fnINOUTMENUGETOBJECT");
  11516. ENDRECV_MESSAGECALL();
  11517. }
  11518. MESSAGECALL(OUTLPCOMBOBOXINFO)
  11519. {
  11520. COMBOBOXINFO cbinfo;
  11521. BEGINRECV_MESSAGECALL(0);
  11522. TRACETHUNK("fnOUTLPCOMBOBOXINFO");
  11523. UNREFERENCED_PARAMETER(bAnsi);
  11524. /*
  11525. * Probe arguments
  11526. */
  11527. try {
  11528. ProbeForWriteComboBoxInfo((PCOMBOBOXINFO)lParam);
  11529. cbinfo = *(PCOMBOBOXINFO)lParam;
  11530. } except (StubExceptionHandler(FALSE)) {
  11531. MSGERROR(0);
  11532. }
  11533. retval = CALLPROC(xpfnProc)(
  11534. pwnd,
  11535. msg,
  11536. wParam,
  11537. (LPARAM)&cbinfo,
  11538. xParam);
  11539. try {
  11540. *(PCOMBOBOXINFO)lParam = cbinfo;
  11541. } except (StubExceptionHandler(FALSE)) {
  11542. }
  11543. TRACE("fnOUTLPCOMBOBOXINFO");
  11544. ENDRECV_MESSAGECALL();
  11545. }
  11546. MESSAGECALL(OUTLPSCROLLBARINFO)
  11547. {
  11548. SCROLLBARINFO sbinfo;
  11549. BEGINRECV_MESSAGECALL(0);
  11550. TRACETHUNK("fnOUTLPSCROLLBARINFO");
  11551. UNREFERENCED_PARAMETER(bAnsi);
  11552. /*
  11553. * Probe arguments
  11554. */
  11555. try {
  11556. ProbeForWriteScrollBarInfo((PSCROLLBARINFO)lParam);
  11557. sbinfo = *(PSCROLLBARINFO)lParam;
  11558. } except (StubExceptionHandler(FALSE)) {
  11559. MSGERROR(0);
  11560. }
  11561. retval = CALLPROC(xpfnProc)(
  11562. pwnd,
  11563. msg,
  11564. wParam,
  11565. (LPARAM)&sbinfo,
  11566. xParam);
  11567. try {
  11568. *(PSCROLLBARINFO)lParam = sbinfo;
  11569. } except (StubExceptionHandler(FALSE)) {
  11570. }
  11571. TRACE("fnOUTLPSCROLLBARINFO");
  11572. ENDRECV_MESSAGECALL();
  11573. }
  11574. /***************************************************************************\
  11575. * NtUserFlashWindowEx
  11576. *
  11577. * History:
  11578. * 11-16-96 MCostea - Created
  11579. \***************************************************************************/
  11580. BOOL
  11581. NtUserFlashWindowEx( // API FlashWindowEx
  11582. IN PFLASHWINFO pfwi)
  11583. {
  11584. FLASHWINFO fwiInternal;
  11585. TL tlpwnd;
  11586. PWND pwnd;
  11587. BEGINRECV(BOOL, FALSE);
  11588. DBG_THREADLOCK_START(FlashWindowEx);
  11589. /*
  11590. * Probe arguments
  11591. */
  11592. try {
  11593. fwiInternal = ProbeAndReadStructure(pfwi, FLASHWINFO);
  11594. } except (StubExceptionHandler(TRUE)) {
  11595. MSGERROR(0);
  11596. }
  11597. if ((pwnd = ValidateHwnd(fwiInternal.hwnd)) == NULL ||
  11598. fwiInternal.cbSize != sizeof(FLASHWINFO) ||
  11599. fwiInternal.dwFlags & ~FLASHW_VALID) {
  11600. RIPMSG0(RIP_WARNING, "NtUserFlashWindowEx: Invalid Parameter");
  11601. MSGERROR(ERROR_INVALID_PARAMETER);
  11602. }
  11603. else {
  11604. ThreadLockAlwaysWithPti(PtiCurrent(), pwnd, &tlpwnd);
  11605. retval = xxxFlashWindow(pwnd,
  11606. MAKELONG(fwiInternal.dwFlags, fwiInternal.uCount),
  11607. fwiInternal.dwTimeout);
  11608. ThreadUnlock(&tlpwnd);
  11609. }
  11610. DBG_THREADLOCK_END(FlashWindowEx);
  11611. TRACE("NtUserFlashWindowEx");
  11612. ENDRECV();
  11613. }
  11614. BOOL NtUserUpdateLayeredWindow( // API UpdateLayeredWindow
  11615. IN HWND hwnd,
  11616. IN HDC hdcDst,
  11617. IN POINT *pptDst,
  11618. IN SIZE *psize,
  11619. IN HDC hdcSrc,
  11620. IN POINT *pptSrc,
  11621. IN COLORREF crKey,
  11622. IN BLENDFUNCTION *pblend,
  11623. IN DWORD dwFlags)
  11624. {
  11625. PWND pwnd;
  11626. POINT ptSrc;
  11627. SIZE size;
  11628. POINT ptDst;
  11629. BLENDFUNCTION blend;
  11630. BEGINATOMICRECV(BOOL, FALSE);
  11631. ValidateHWND(pwnd, hwnd);
  11632. /*
  11633. * Probe and validate arguments.
  11634. */
  11635. try {
  11636. if (ARGUMENT_PRESENT(pptSrc)) {
  11637. ptSrc = ProbeAndReadPoint(pptSrc);
  11638. pptSrc = &ptSrc;
  11639. }
  11640. if (ARGUMENT_PRESENT(psize)) {
  11641. size = ProbeAndReadSize(psize);
  11642. psize = &size;
  11643. if (psize->cx < 0 || psize->cy < 0) {
  11644. MSGERROR(ERROR_INVALID_PARAMETER); // this is a jump out of try!
  11645. }
  11646. }
  11647. if (ARGUMENT_PRESENT(pptDst)) {
  11648. ptDst = ProbeAndReadPoint(pptDst);
  11649. pptDst = &ptDst;
  11650. }
  11651. if (ARGUMENT_PRESENT(pblend)) {
  11652. blend = ProbeAndReadBlendfunction(pblend);
  11653. pblend = &blend;
  11654. }
  11655. } except (StubExceptionHandler(TRUE)) {
  11656. MSGERROR(0);
  11657. }
  11658. if (dwFlags & ~ULW_VALID) {
  11659. RIPMSG0(RIP_WARNING, "UpdateLayeredWindow: Invalid Parameter");
  11660. MSGERROR(ERROR_INVALID_PARAMETER);
  11661. } else {
  11662. retval = _UpdateLayeredWindow(
  11663. pwnd,
  11664. hdcDst,
  11665. pptDst,
  11666. psize,
  11667. hdcSrc,
  11668. pptSrc,
  11669. crKey,
  11670. pblend,
  11671. dwFlags);
  11672. }
  11673. TRACE("NtUserUpdateLayeredWindow");
  11674. ENDATOMICRECV();
  11675. }
  11676. BOOL NtUserGetLayeredWindowAttributes(
  11677. IN HWND hwnd,
  11678. OUT OPTIONAL COLORREF *pcrKey,
  11679. OUT OPTIONAL BYTE *pbAlpha,
  11680. OUT OPTIONAL DWORD *pdwFlags)
  11681. {
  11682. PWND pwnd;
  11683. COLORREF crKey;
  11684. BYTE bAlpha;
  11685. DWORD dwFlags;
  11686. BEGINATOMICRECV(BOOL, FALSE);
  11687. ValidateHWND(pwnd, hwnd);
  11688. retval = _GetLayeredWindowAttributes(pwnd, &crKey, &bAlpha, &dwFlags);
  11689. if (retval) {
  11690. try {
  11691. if (ARGUMENT_PRESENT(pcrKey)) {
  11692. ProbeForWrite(pcrKey, sizeof(COLORREF), sizeof(COLORREF));
  11693. *pcrKey = crKey;
  11694. }
  11695. if (ARGUMENT_PRESENT(pbAlpha)) {
  11696. ProbeForWrite(pbAlpha, sizeof(BYTE), sizeof(BYTE));
  11697. *pbAlpha = bAlpha;
  11698. }
  11699. if (ARGUMENT_PRESENT(pdwFlags)) {
  11700. ProbeForWrite(pdwFlags, sizeof(DWORD), sizeof(DWORD));
  11701. *pdwFlags = dwFlags & ULW_VALID;
  11702. }
  11703. } except (StubExceptionHandler(TRUE)) {
  11704. MSGERROR(0);
  11705. }
  11706. }
  11707. TRACE("NtUserGetLayeredWindowAttributes");
  11708. ENDATOMICRECV();
  11709. }
  11710. BOOL NtUserSetLayeredWindowAttributes(
  11711. IN HWND hwnd,
  11712. IN COLORREF crKey,
  11713. IN BYTE bAlpha,
  11714. IN DWORD dwFlags)
  11715. {
  11716. PWND pwnd;
  11717. BEGINATOMICRECV(BOOL, FALSE);
  11718. ValidateHWND(pwnd, hwnd);
  11719. if (dwFlags & ~LWA_VALID) {
  11720. RIPMSG0(RIP_WARNING, "SetLayeredWindowAttributes: Invalid Parameter");
  11721. MSGERROR(ERROR_INVALID_PARAMETER);
  11722. } else {
  11723. retval = _SetLayeredWindowAttributes(pwnd, crKey, bAlpha, dwFlags);
  11724. }
  11725. TRACE("NtUserSetLayeredWindowAttributes");
  11726. ENDATOMICRECV();
  11727. }
  11728. BOOL NtUserPrintWindow(
  11729. IN HWND hwnd,
  11730. IN HDC hdcBlt,
  11731. IN UINT nFlags)
  11732. {
  11733. BEGINRECV_HWNDLOCK_ND(BOOL, FALSE, hwnd);
  11734. if ((nFlags & PW_VALID) != nFlags) {
  11735. RIPMSG2(RIP_WARNING, "PrintWindow: Invalid Parameter nFlags=%d on HWND=0x%p", nFlags, hwnd);
  11736. MSGERROR(ERROR_INVALID_PARAMETER);
  11737. } else {
  11738. retval = xxxPrintWindow(pwndND, hdcBlt, nFlags);
  11739. }
  11740. TRACE("NtUserPrintWindow");
  11741. ENDRECV_HWNDLOCK_ND();
  11742. }
  11743. /***************************************************************************\
  11744. * GetHDevName
  11745. * Called by NtUserCallTwoParam in GetMonitorInfo to query
  11746. * gre about the HDev name
  11747. *
  11748. * 1-July-1998 MCostea created
  11749. \***************************************************************************/
  11750. BOOL GetHDevName(HMONITOR hMon, PWCHAR pName)
  11751. {
  11752. PMONITOR pMonitor;
  11753. WCHAR wszName[CCHDEVICENAME];
  11754. BOOL fResult = FALSE;
  11755. CheckCritIn();
  11756. pMonitor = ValidateHmonitor(hMon);
  11757. if (!pMonitor) {
  11758. return FALSE;
  11759. }
  11760. if (DrvGetHdevName(pMonitor->hDev, wszName)) {
  11761. /*
  11762. * Make sure it's NULL terminated.
  11763. */
  11764. wszName[CCHDEVICENAME - 1] = 0;
  11765. try {
  11766. ProbeForWrite(pName, CCHDEVICENAME * sizeof(WCHAR), sizeof(DWORD));
  11767. RtlCopyMemory(pName, wszName, CCHDEVICENAME * sizeof(WCHAR));
  11768. } except (StubExceptionHandler(TRUE)) {
  11769. goto _exit;
  11770. }
  11771. fResult = TRUE;
  11772. }
  11773. _exit:
  11774. return fResult;
  11775. }
  11776. #ifdef GENERIC_INPUT
  11777. /***************************************************************************\
  11778. * NtUserGetRawInputData
  11779. * Gets the HIDDATA structure from its HRAWINPUT handle.
  11780. *
  11781. * Returns the number of bytes written to pRawInput. On error, it returns -1 and zero
  11782. * in *pcbSize. If pRawInput is NULL, it returns zero and the number of bytes need to
  11783. * receive the data in pcbSize.
  11784. *
  11785. * If pRawInput is not big enough, it return -1 and the number of bytes needed to
  11786. * receive the data in pcbSize.
  11787. *
  11788. * 25-February-2000 JasonSch created
  11789. \***************************************************************************/
  11790. UINT NtUserGetRawInputData(
  11791. HRAWINPUT hRawInput,
  11792. UINT uiCommand,
  11793. LPVOID pData,
  11794. PUINT pcbSize,
  11795. UINT cbSizeHeader)
  11796. {
  11797. PHIDDATA pHidData;
  11798. UINT cbOutSize, cbBufferSize;
  11799. BEGINATOMICRECV(UINT, (UINT)-1);
  11800. if (cbSizeHeader != sizeof(RAWINPUTHEADER)) {
  11801. MSGERROR(ERROR_INVALID_PARAMETER);
  11802. }
  11803. /*
  11804. * Get the report data contents.
  11805. */
  11806. pHidData = HMValidateHandle(hRawInput, TYPE_HIDDATA);
  11807. if (pHidData == NULL) {
  11808. RIPERR1(ERROR_INVALID_HANDLE, RIP_WARNING, "NtUserGetRawInputData: invalid handle %p", hRawInput);
  11809. MSGERROR(0);
  11810. }
  11811. /*
  11812. * Check the type of the raw input data.
  11813. */
  11814. switch (pHidData->rid.header.dwType) {
  11815. case RIM_TYPEMOUSE:
  11816. case RIM_TYPEKEYBOARD:
  11817. case RIM_TYPEHID:
  11818. break;
  11819. default:
  11820. /*
  11821. * The handle is valid, but the internal state of the object is
  11822. * weird.
  11823. */
  11824. RIPERR2(ERROR_INVALID_HANDLE,
  11825. RIP_ERROR,
  11826. "Invalid type 0x%x in pHidData %p",
  11827. pHidData->rid.header.dwType,
  11828. pHidData);
  11829. MSGERROR(0);
  11830. }
  11831. /*
  11832. * Calculate the size of the data
  11833. */
  11834. switch (uiCommand) {
  11835. case RID_INPUT:
  11836. cbOutSize = pHidData->rid.header.dwSize;
  11837. break;
  11838. case RID_HEADER:
  11839. cbOutSize = sizeof pHidData->rid.header;
  11840. break;
  11841. default:
  11842. MSGERROR(ERROR_INVALID_PARAMETER);
  11843. break;
  11844. }
  11845. #if DBG
  11846. if (pHidData->rid.header.dwType == RIM_TYPEHID && uiCommand == RID_INPUT) {
  11847. /*
  11848. * TYPEHID has variable length array of report data.
  11849. */
  11850. TAGMSG3(DBGTAG_PNP, "NtUserGetRawInputData: pHidData=%p, dwOutSize=%x, calc'ed=%x",
  11851. pHidData,
  11852. cbOutSize, FIELD_OFFSET(RAWINPUT, data.hid.bRawData) + pHidData->rid.data.hid.dwSizeHid * pHidData->rid.data.hid.dwCount);
  11853. UserAssert(cbOutSize == FIELD_OFFSET(RAWINPUT, data.hid.bRawData) + pHidData->rid.data.hid.dwSizeHid * pHidData->rid.data.hid.dwCount);
  11854. }
  11855. #endif
  11856. if (pData == NULL) {
  11857. /*
  11858. * The caller wants to get the required size of the buffer.
  11859. */
  11860. try {
  11861. ProbeForWrite(pcbSize, sizeof(UINT), sizeof(DWORD));
  11862. *pcbSize = cbOutSize;
  11863. } except (StubExceptionHandler(TRUE)) {
  11864. MSGERROR(0);
  11865. }
  11866. retval = 0;
  11867. } else {
  11868. try {
  11869. ProbeForRead(pcbSize, sizeof(UINT), sizeof(DWORD));
  11870. cbBufferSize = *pcbSize;
  11871. } except (StubExceptionHandler(TRUE)) {
  11872. MSGERROR(0);
  11873. }
  11874. if (cbBufferSize >= cbOutSize) {
  11875. try {
  11876. switch (uiCommand) {
  11877. case RID_INPUT:
  11878. ProbeForWrite(pData, cbOutSize, sizeof(DWORD));
  11879. RtlCopyMemory(pData, &pHidData->rid, cbOutSize);
  11880. break;
  11881. case RID_HEADER:
  11882. {
  11883. PRAWINPUTHEADER pHeader = (PRAWINPUTHEADER)pData;
  11884. UserAssert(cbOutSize == sizeof(RAWINPUTHEADER));
  11885. ProbeAndWriteStructure(pHeader, pHidData->rid.header, RAWINPUTHEADER);
  11886. }
  11887. break;
  11888. default:
  11889. UserAssert(FALSE);
  11890. break;
  11891. }
  11892. } except (StubExceptionHandler(TRUE)) {
  11893. MSGERROR(0);
  11894. }
  11895. retval = cbOutSize;
  11896. } else {
  11897. retval = errret;
  11898. try {
  11899. ProbeForWrite(pcbSize, sizeof(UINT), sizeof(DWORD));
  11900. *pcbSize = cbBufferSize;
  11901. UserSetLastError(ERROR_INSUFFICIENT_BUFFER);
  11902. } except(StubExceptionHandler(TRUE)) {
  11903. MSGERROR(0);
  11904. }
  11905. }
  11906. }
  11907. TRACE("NtUserGetRawInputData");
  11908. ENDATOMICRECV();
  11909. }
  11910. UINT NtUserGetRawInputDeviceInfo(
  11911. HANDLE hDevice,
  11912. UINT uiCommand,
  11913. LPVOID pData,
  11914. PUINT pcbSize)
  11915. {
  11916. PDEVICEINFO pDeviceInfo;
  11917. UINT cbOutSize = 0;
  11918. UINT cbBufferSize;
  11919. BEGINATOMICRECV(DWORD, (UINT)-1);
  11920. try {
  11921. ProbeForRead(pcbSize, sizeof(UINT), sizeof(DWORD));
  11922. cbBufferSize = *pcbSize;
  11923. } except (StubExceptionHandler(TRUE)) {
  11924. MSGERROR(0);
  11925. }
  11926. EnterDeviceInfoListCrit();
  11927. pDeviceInfo = HMValidateHandle(hDevice, TYPE_DEVICEINFO);
  11928. if (pDeviceInfo == NULL) {
  11929. RIPERR1(ERROR_INVALID_HANDLE, RIP_WARNING, "NtUserGetRawInputDeviceInfo: invalid handle=%p", hDevice);
  11930. MSGERRORCLEANUP(0);
  11931. }
  11932. /*
  11933. * Compute the size of the output and evaluate the uiCommand.
  11934. */
  11935. switch (uiCommand) {
  11936. case RIDI_PREPARSEDDATA:
  11937. if (pDeviceInfo->type == DEVICE_TYPE_HID) {
  11938. cbOutSize = pDeviceInfo->hid.pHidDesc->hidCollectionInfo.DescriptorSize;
  11939. } else {
  11940. cbOutSize = 0;
  11941. }
  11942. break;
  11943. case RIDI_DEVICENAME:
  11944. /*
  11945. * N.b. UNICODE_STRING counts the length by the BYTE count, not by the character count.
  11946. * Our APIs always treat the strings by the character count. Thus, for RIDI_DEVICNAME
  11947. * only, cbOutSize holds the character count, not the byte count, in spite of its
  11948. * name. Confusing, but cch is the way to be consistent.
  11949. */
  11950. cbOutSize = pDeviceInfo->ustrName.Length / sizeof(WCHAR) + 1; // for Null terminator
  11951. break;
  11952. case RIDI_DEVICEINFO:
  11953. cbOutSize = sizeof(RID_DEVICE_INFO);
  11954. break;
  11955. default:
  11956. RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "NtUserGetRawInputDeviceInfo: invalid uiCommand=%x", uiCommand);
  11957. MSGERRORCLEANUP(0);
  11958. break;
  11959. }
  11960. if (pData == NULL) {
  11961. /*
  11962. * The app wants to get the required size.
  11963. */
  11964. try {
  11965. ProbeForWrite(pcbSize, sizeof(UINT), sizeof(DWORD));
  11966. *pcbSize = cbOutSize;
  11967. } except (StubExceptionHandler(TRUE)) {
  11968. MSGERRORCLEANUP(0);
  11969. }
  11970. retval = 0;
  11971. } else {
  11972. if (cbBufferSize >= cbOutSize) {
  11973. try {
  11974. ProbeForWrite(pData, cbBufferSize, sizeof(DWORD));
  11975. switch (uiCommand) {
  11976. case RIDI_PREPARSEDDATA:
  11977. if (pDeviceInfo->type == DEVICE_TYPE_HID) {
  11978. RtlCopyMemory(pData, pDeviceInfo->hid.pHidDesc->pPreparsedData, cbOutSize);
  11979. } else {
  11980. UserAssert(cbOutSize == 0);
  11981. }
  11982. break;
  11983. case RIDI_DEVICENAME:
  11984. UserAssert((cbOutSize -1) * sizeof(WCHAR) == pDeviceInfo->ustrName.Length);
  11985. RtlCopyMemory(pData, pDeviceInfo->ustrName.Buffer, pDeviceInfo->ustrName.Length);
  11986. ((WCHAR*)pData)[cbOutSize - 1] = 0; // make it null terminated
  11987. break;
  11988. case RIDI_DEVICEINFO:
  11989. {
  11990. PRID_DEVICE_INFO prdi = (PRID_DEVICE_INFO)pData;
  11991. ProbeForRead(prdi, sizeof(UINT), sizeof(DWORD));
  11992. if (prdi->cbSize != cbOutSize) {
  11993. MSGERRORCLEANUP(ERROR_INVALID_PARAMETER);
  11994. }
  11995. ProbeForWrite(prdi, sizeof(RID_DEVICE_INFO), sizeof(DWORD));
  11996. RtlZeroMemory(prdi, sizeof(RID_DEVICE_INFO));
  11997. prdi->cbSize = cbOutSize;
  11998. switch (pDeviceInfo->type) {
  11999. case DEVICE_TYPE_HID:
  12000. prdi->dwType = RIM_TYPEHID;
  12001. prdi->hid.dwVendorId = pDeviceInfo->hid.pHidDesc->hidCollectionInfo.VendorID;
  12002. prdi->hid.dwProductId = pDeviceInfo->hid.pHidDesc->hidCollectionInfo.ProductID;
  12003. prdi->hid.dwVersionNumber = pDeviceInfo->hid.pHidDesc->hidCollectionInfo.VersionNumber;
  12004. prdi->hid.usUsagePage = pDeviceInfo->hid.pHidDesc->hidpCaps.UsagePage;
  12005. prdi->hid.usUsage = pDeviceInfo->hid.pHidDesc->hidpCaps.Usage;
  12006. break;
  12007. case DEVICE_TYPE_MOUSE:
  12008. prdi->dwType = RIM_TYPEMOUSE;
  12009. prdi->mouse.dwId = pDeviceInfo->mouse.Attr.MouseIdentifier;
  12010. prdi->mouse.dwNumberOfButtons = pDeviceInfo->mouse.Attr.NumberOfButtons;
  12011. prdi->mouse.dwSampleRate = pDeviceInfo->mouse.Attr.SampleRate;
  12012. break;
  12013. case DEVICE_TYPE_KEYBOARD:
  12014. prdi->dwType = RIM_TYPEKEYBOARD;
  12015. prdi->keyboard.dwType = GET_KEYBOARD_DEVINFO_TYPE(pDeviceInfo);
  12016. prdi->keyboard.dwSubType = GET_KEYBOARD_DEVINFO_SUBTYPE(pDeviceInfo);
  12017. prdi->keyboard.dwKeyboardMode = pDeviceInfo->keyboard.Attr.KeyboardMode;
  12018. prdi->keyboard.dwNumberOfFunctionKeys = pDeviceInfo->keyboard.Attr.NumberOfFunctionKeys;
  12019. prdi->keyboard.dwNumberOfIndicators = pDeviceInfo->keyboard.Attr.NumberOfIndicators;
  12020. prdi->keyboard.dwNumberOfKeysTotal = pDeviceInfo->keyboard.Attr.NumberOfKeysTotal;
  12021. break;
  12022. }
  12023. }
  12024. break;
  12025. default:
  12026. UserAssert(FALSE);
  12027. break;
  12028. }
  12029. } except (StubExceptionHandler(TRUE)) {
  12030. MSGERRORCLEANUP(0);
  12031. }
  12032. retval = cbOutSize;
  12033. } else {
  12034. /*
  12035. * The buffer size is too small.
  12036. * Returns error, storing the required size in *pcbSize.
  12037. */
  12038. retval = errret;
  12039. try {
  12040. ProbeForWrite(pcbSize, sizeof(UINT), sizeof(DWORD));
  12041. *pcbSize = cbOutSize;
  12042. UserSetLastError(ERROR_INSUFFICIENT_BUFFER);
  12043. } except (StubExceptionHandler(TRUE)) {
  12044. MSGERRORCLEANUP(0);
  12045. }
  12046. }
  12047. }
  12048. CLEANUPRECV();
  12049. LeaveDeviceInfoListCrit();
  12050. TRACE("NtUserGetRawInputDeviceInfo");
  12051. ENDATOMICRECV();
  12052. }
  12053. UINT NtUserGetRawInputDeviceList(
  12054. PRAWINPUTDEVICELIST pRawInputDeviceList,
  12055. PUINT puiNumDevices,
  12056. UINT cbSize)
  12057. {
  12058. UINT nDevices = 0;
  12059. PDEVICEINFO pDeviceInfo;
  12060. BEGINATOMICRECV(DWORD, (UINT)-1);
  12061. if (cbSize != sizeof(RAWINPUTDEVICELIST)) {
  12062. MSGERROR(ERROR_INVALID_PARAMETER);
  12063. }
  12064. EnterDeviceInfoListCrit();
  12065. /*
  12066. * Firstly, count up the number of devices
  12067. * attached to the system.
  12068. */
  12069. for (pDeviceInfo = gpDeviceInfoList; pDeviceInfo; pDeviceInfo = pDeviceInfo->pNext) {
  12070. ++nDevices;
  12071. }
  12072. if (pRawInputDeviceList == NULL) {
  12073. /*
  12074. * Application simply wants the number of devices.
  12075. */
  12076. try {
  12077. /*
  12078. * Store number of devices.
  12079. */
  12080. ProbeForWrite(puiNumDevices, sizeof(UINT), sizeof(DWORD));
  12081. *puiNumDevices = nDevices;
  12082. /*
  12083. * Set retval as 0, to indicate the API succeeded.
  12084. */
  12085. retval = 0;
  12086. } except (StubExceptionHandler(TRUE)) {
  12087. MSGERRORCLEANUP(0);
  12088. }
  12089. } else {
  12090. /*
  12091. * Write out the device info list.
  12092. */
  12093. try {
  12094. UINT i;
  12095. ProbeForRead(puiNumDevices, sizeof(UINT), sizeof(DWORD));
  12096. if (*puiNumDevices < nDevices) {
  12097. /*
  12098. * If the buffer size is not sufficient, set the required
  12099. * number of buffers, then return error.
  12100. */
  12101. ProbeForWrite(puiNumDevices, sizeof(UINT), sizeof(DWORD));
  12102. *puiNumDevices = nDevices;
  12103. MSGERRORCLEANUP(ERROR_INSUFFICIENT_BUFFER);
  12104. }
  12105. ProbeForWrite(pRawInputDeviceList, sizeof(RAWINPUTDEVICELIST) * nDevices, sizeof(HANDLE));
  12106. for (i = 0, pDeviceInfo = gpDeviceInfoList; pDeviceInfo; pDeviceInfo = pDeviceInfo->pNext, ++i) {
  12107. UserAssert(i < nDevices);
  12108. pRawInputDeviceList[i].hDevice = PtoHq(pDeviceInfo);
  12109. pRawInputDeviceList[i].dwType = pDeviceInfo->type;
  12110. }
  12111. UserAssert(i == nDevices);
  12112. retval = i;
  12113. } except (StubExceptionHandler(TRUE)) {
  12114. MSGERRORCLEANUP(0);
  12115. }
  12116. }
  12117. CLEANUPRECV();
  12118. LeaveDeviceInfoListCrit();
  12119. TRACE("NtUserGetRawInputDeviceList");
  12120. ENDATOMICRECV();
  12121. }
  12122. BOOL NtUserRegisterRawInputDevices(
  12123. PRAWINPUTDEVICE pRawInputDevices,
  12124. UINT uiNumDevices,
  12125. UINT cbSize)
  12126. {
  12127. PVOID pLocalRawInputDevices = NULL;
  12128. TL tlBuffer;
  12129. PTHREADINFO ptiCurrent;
  12130. BEGINATOMICRECV(BOOL, FALSE);
  12131. ptiCurrent = PtiCurrent();
  12132. if (pRawInputDevices == NULL || uiNumDevices == 0 || cbSize != sizeof(RAWINPUTDEVICE)) {
  12133. /*
  12134. * TBD:
  12135. * What should we do if pRawInputDevices is NULL?
  12136. * Perhaps should start receiving all HID input?
  12137. */
  12138. MSGERROR(ERROR_INVALID_PARAMETER);
  12139. }
  12140. try {
  12141. ProbeForReadBuffer(pRawInputDevices, uiNumDevices, sizeof(PRAWINPUTDEVICE));
  12142. pLocalRawInputDevices = UserAllocPoolWithQuota(uiNumDevices * cbSize, TAG_SYSTEM);
  12143. if (pLocalRawInputDevices) {
  12144. ThreadLockPool(ptiCurrent, pLocalRawInputDevices, &tlBuffer);
  12145. RtlCopyMemory(pLocalRawInputDevices, pRawInputDevices, uiNumDevices * cbSize);
  12146. } else {
  12147. ExRaiseStatus(STATUS_NO_MEMORY);
  12148. }
  12149. } except (StubExceptionHandler(TRUE)) {
  12150. MSGERRORCLEANUP(0);
  12151. }
  12152. retval = _RegisterRawInputDevices(pLocalRawInputDevices, uiNumDevices);
  12153. CLEANUPRECV();
  12154. if (pLocalRawInputDevices) {
  12155. ThreadUnlockAndFreePool(ptiCurrent, &tlBuffer);
  12156. }
  12157. TRACE("NtUserSetRawInputDevices");
  12158. ENDATOMICRECV();
  12159. }
  12160. UINT NtUserGetRegisteredRawInputDevices(
  12161. PRAWINPUTDEVICE pRawInputDevices,
  12162. PUINT puiNumDevices,
  12163. UINT cbSize)
  12164. {
  12165. BEGINATOMICRECV(DWORD, (UINT)-1);
  12166. if (cbSize != sizeof(RAWINPUTDEVICE)) {
  12167. MSGERROR(ERROR_INVALID_PARAMETER);
  12168. }
  12169. retval = _GetRegisteredRawInputDevices(pRawInputDevices, puiNumDevices);
  12170. ENDATOMICRECV();
  12171. }
  12172. #ifdef _WIN64
  12173. # ifndef QWORD_ALIGN
  12174. # define QWORD_ALIGN(x) (((x) + 7) & ~7)
  12175. # endif
  12176. #define RI_ALIGN(x) QWORD_ALIGN(x)
  12177. #else
  12178. #define RI_ALIGN(x) DWORD_ALIGN(x)
  12179. #endif // _Win64
  12180. UINT NtUserGetRawInputBuffer(
  12181. PRAWINPUT pData,
  12182. PUINT pcbSize,
  12183. #ifdef LATER
  12184. DWORD dwFlags,
  12185. #endif
  12186. UINT cbSizeHeader)
  12187. {
  12188. UINT cbBytes = 0; /* # of bytes written to the buffer */
  12189. UINT cbWriteSize = 0; /* the # of bytes to write into pData */
  12190. PQMSG pqmsg;
  12191. PTHREADINFO ptiCurrent;
  12192. PQ pq;
  12193. PHIDDATA pHidData;
  12194. UINT cbBufferSize; /* the size of the passed in buffer */
  12195. UINT cRICount = 0; /* # of RAWINPUT structures written to the buffer */
  12196. BEGINATOMICRECV(UINT, -1);
  12197. #ifdef LATER
  12198. if (dwFlags != 0) {
  12199. MSGERROR(ERROR_INVALID_PARAMETER);
  12200. }
  12201. #endif
  12202. if (cbSizeHeader != sizeof(RAWINPUTHEADER)) {
  12203. MSGERROR(ERROR_INVALID_PARAMETER);
  12204. }
  12205. try {
  12206. ProbeForRead(pcbSize, sizeof(UINT), sizeof(DWORD));
  12207. cbBufferSize = *pcbSize;
  12208. } except (StubExceptionHandler(TRUE)) {
  12209. MSGERROR(0);
  12210. }
  12211. ptiCurrent = PtiCurrent();
  12212. pq = ptiCurrent->pq;
  12213. pqmsg = pq->mlInput.pqmsgRead;
  12214. while (pqmsg) {
  12215. // Remember the next pqmsg, for the current pqmsg may be freed in this loop
  12216. PQMSG pqmsgNext = pqmsg->pqmsgNext;
  12217. if (pqmsg->msg.message == WM_INPUT) {
  12218. pHidData = HMValidateHandle((HRAWINPUT)pqmsg->msg.lParam, TYPE_HIDDATA);
  12219. UserAssert(pHidData != NULL);
  12220. cbWriteSize = RI_ALIGN(pHidData->rid.header.dwSize);
  12221. if (pData == NULL || (cbBytes + cbWriteSize) > cbBufferSize) {
  12222. break;
  12223. }
  12224. try {
  12225. ProbeForWrite(pData, cbWriteSize, sizeof(DWORD));
  12226. RtlCopyMemory(pData, &pHidData->rid, pHidData->rid.header.dwSize);
  12227. ++cRICount;
  12228. (PBYTE)pData += cbWriteSize;
  12229. cbBytes += cbWriteSize;
  12230. } except (StubExceptionHandler(TRUE)) {
  12231. RIPMSG3(RIP_WARNING, "NtUserGetRawInputBuffer: exception: src=%p target=%p %x bytes",
  12232. &pHidData->rid, pData, pHidData->rid.header.dwSize);
  12233. MSGERROR(0);
  12234. }
  12235. // Update the time of the messages
  12236. ptiCurrent->timeLast = pqmsg->msg.time;
  12237. // Remove this msg from the queue
  12238. DelQEntry(&pq->mlInput, pqmsg);
  12239. FreeHidData(pHidData);
  12240. }
  12241. pqmsg = pqmsgNext;
  12242. }
  12243. /*
  12244. * If pqmsg is NULL then we went through the entire MLIST. This will
  12245. * only happen if we have copied all of the WM_INPUTs into the buffer or
  12246. * there were none to begin with. Either way, there are none left. So
  12247. * turn off QS_RAWINPUT.
  12248. */
  12249. if (pqmsg == NULL && pData != NULL) {
  12250. ClearWakeBit(ptiCurrent, QS_RAWINPUT, FALSE);
  12251. }
  12252. if (cbBufferSize <= cbWriteSize || pData == NULL) {
  12253. if (pData == NULL) {
  12254. retval = 0;
  12255. } else {
  12256. retval = errret;
  12257. UserSetLastError(ERROR_INSUFFICIENT_BUFFER);
  12258. }
  12259. try {
  12260. ProbeForWrite(pcbSize, sizeof(UINT), sizeof(DWORD));
  12261. *pcbSize = cbWriteSize;
  12262. } except(StubExceptionHandler(TRUE)) {
  12263. MSGERROR(0);
  12264. }
  12265. } else {
  12266. // Update the last time read
  12267. SET_TIME_LAST_READ(ptiCurrent);
  12268. retval = cRICount;
  12269. }
  12270. TRACE("NtUserGetRawInputBuffer");
  12271. ENDATOMICRECV();
  12272. }
  12273. #undef RI_ALIGN
  12274. #endif
  12275. BOOL NtUserValidateTimerCallback(
  12276. IN ULONG_PTR pfnCallback)
  12277. {
  12278. BEGINRECV_SHARED(BOOL, FALSE);
  12279. retval = ValidateTimerCallback(PtiCurrentShared(), pfnCallback);
  12280. ENDRECV_SHARED();
  12281. }