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.

515 lines
17 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: getsetc.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * This module contains window manager information routines
  7. *
  8. * History:
  9. * 10-Mar-1993 JerrySh Pulled functions from user\server.
  10. \***************************************************************************/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. /***************************************************************************\
  14. * _GetWindowWord (supports the GetWindowWord API)
  15. *
  16. * Return a window word. Positive index values return application window words
  17. * while negative index values return system window words. The negative
  18. * indices are published in WINDOWS.H.
  19. *
  20. * History:
  21. * 11-26-90 darrinm Wrote.
  22. \***************************************************************************/
  23. WORD _GetWindowWord(
  24. PWND pwnd,
  25. int index)
  26. {
  27. if (GETFNID(pwnd) != 0) {
  28. if ((index >= 0) && (index <
  29. (int)(CBFNID(pwnd->fnid)-sizeof(WND)))) {
  30. switch (GETFNID(pwnd)) {
  31. case FNID_MDICLIENT:
  32. if (index == 0)
  33. break;
  34. goto DoDefault;
  35. case FNID_BUTTON:
  36. /*
  37. * CorelDraw does a get/set on the first button window word.
  38. * Allow it to.
  39. */
  40. if (index == 0) {
  41. /*
  42. * Since we now use a lookaside buffer for the control's
  43. * private data, we need to indirect into this structure.
  44. */
  45. PBUTN pbutn = ((PBUTNWND)pwnd)->pbutn;
  46. if (!pbutn || (LONG_PTR)pbutn == (LONG_PTR)-1) {
  47. return 0;
  48. } else {
  49. return (WORD)(pbutn->buttonState);
  50. }
  51. }
  52. goto DoDefault;
  53. case FNID_DIALOG:
  54. if (index == DWLP_USER)
  55. return LOWORD(((PDIALOG)pwnd)->unused);
  56. if (index == DWLP_USER+2)
  57. return HIWORD(((PDIALOG)pwnd)->unused);
  58. goto DoDefault;
  59. default:
  60. DoDefault:
  61. RIPERR3(ERROR_INVALID_INDEX,
  62. RIP_WARNING,
  63. "GetWindowWord: Trying to read private server data pwnd=(%#p) index=(%ld) fnid=(%lX)",
  64. pwnd, index, (DWORD)pwnd->fnid);
  65. return 0;
  66. break;
  67. }
  68. }
  69. }
  70. if (index == GWLP_USERDATA)
  71. return (WORD)pwnd->dwUserData;
  72. if ((index < 0) || ((UINT)index + sizeof(WORD) > (UINT)pwnd->cbwndExtra)) {
  73. RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE, "");
  74. return 0;
  75. } else {
  76. return *((WORD UNALIGNED * KPTR_MODIFIER)((KPBYTE)(pwnd + 1) + index));
  77. }
  78. }
  79. ULONG_PTR GetWindowData(PWND pwnd, int index, BOOL bAnsi);
  80. /***************************************************************************\
  81. * _GetWindowLong (supports GetWindowLongA/W API)
  82. *
  83. * Return a window long. Positive index values return application window longs
  84. * while negative index values return system window longs. The negative
  85. * indices are published in WINDOWS.H.
  86. *
  87. * History:
  88. * 11-26-90 darrinm Wrote.
  89. \***************************************************************************/
  90. ULONG_PTR _GetWindowLongPtr(
  91. PWND pwnd,
  92. int index,
  93. BOOL bAnsi)
  94. {
  95. ULONG_PTR dwProc;
  96. DWORD dwCPDType = 0;
  97. ULONG_PTR UNALIGNED * KPTR_MODIFIER pudw;
  98. /*
  99. * If it's a dialog window, only a few indices are permitted.
  100. */
  101. if (GETFNID(pwnd) != 0) {
  102. if (TestWF(pwnd, WFDIALOGWINDOW)) {
  103. switch (index) {
  104. case DWLP_DLGPROC: // See similar case GWLP_WNDGPROC
  105. /*
  106. * Hide the window proc from other processes
  107. */
  108. if (!TestWindowProcess(pwnd)) {
  109. RIPERR1(ERROR_ACCESS_DENIED,
  110. RIP_WARNING,
  111. "Access denied to \"pwnd\" (%#p) in _GetWindowLong",
  112. pwnd);
  113. return 0;
  114. }
  115. dwProc = (ULONG_PTR)PDLG(pwnd)->lpfnDlg;
  116. /*
  117. * If a proc exists check it to see if we need a translation
  118. */
  119. if (dwProc) {
  120. /*
  121. * May need to return a CallProc handle if there is an
  122. * Ansi/Unicode transition
  123. */
  124. if (bAnsi != ((PDLG(pwnd)->flags & DLGF_ANSI) ? TRUE : FALSE)) {
  125. dwCPDType |= bAnsi ? CPD_ANSI_TO_UNICODE : CPD_UNICODE_TO_ANSI;
  126. }
  127. if (dwCPDType) {
  128. ULONG_PTR cpd;
  129. cpd = GetCPD(pwnd, dwCPDType | CPD_DIALOG, dwProc);
  130. if (cpd) {
  131. dwProc = cpd;
  132. } else {
  133. RIPMSG0(RIP_WARNING, "GetWindowLong unable to alloc CPD returning handle\n");
  134. }
  135. }
  136. }
  137. /*
  138. * return proc (or CPD handle)
  139. */
  140. return dwProc;
  141. case DWLP_MSGRESULT:
  142. return (ULONG_PTR)((PDIALOG)pwnd)->resultWP;
  143. case DWLP_USER:
  144. return (ULONG_PTR)((PDIALOG)pwnd)->unused;
  145. default:
  146. if (index >= 0 && index < DLGWINDOWEXTRA) {
  147. RIPERR0(ERROR_PRIVATE_DIALOG_INDEX, RIP_VERBOSE, "");
  148. return 0;
  149. }
  150. }
  151. } else {
  152. if (index >= 0 &&
  153. (index < (int)(CBFNID(pwnd->fnid)-sizeof(WND)))) {
  154. switch (GETFNID(pwnd)) {
  155. case FNID_MDICLIENT:
  156. /*
  157. * Allow the 0 index (which is reserved) to be set/get.
  158. * Quattro Pro 1.0 uses this index!
  159. */
  160. if (index != 0)
  161. break;
  162. goto GetData;
  163. break;
  164. case FNID_EDIT:
  165. if (index != 0)
  166. break;
  167. /*
  168. * If we get to this point we need to return the first
  169. * entry in the lookaside. This will provide backward
  170. * compatibilty for 3.51 that allowed edit-controls to
  171. * do this. PeachTree is one app which required this.
  172. */
  173. pudw = (ULONG_PTR UNALIGNED * KPTR_MODIFIER)((KPBYTE)(pwnd + 1));
  174. /*
  175. * Do not dereference the pointer if we are not in
  176. * the proper address space. Apps like Spyxx like to
  177. * do this on other process' windows
  178. */
  179. return (TestWindowProcess(pwnd) ? *(ULONG_PTR UNALIGNED *)*pudw : (ULONG_PTR)pudw);
  180. }
  181. RIPERR3(ERROR_INVALID_INDEX,
  182. RIP_WARNING,
  183. "GetWindowLong: Trying to read private server data pwnd=(%#p) index=(%ld) fnid (%lX)",
  184. pwnd, index, (DWORD)pwnd->fnid);
  185. return 0;
  186. }
  187. }
  188. }
  189. if (index < 0) {
  190. return GetWindowData(pwnd, index, bAnsi);
  191. } else {
  192. if ((UINT)index + sizeof(ULONG_PTR) > (UINT)pwnd->cbwndExtra) {
  193. RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE, "");
  194. return 0;
  195. } else {
  196. GetData:
  197. pudw = (ULONG_PTR UNALIGNED * KPTR_MODIFIER)((KPBYTE)(pwnd + 1) + index);
  198. return *pudw;
  199. }
  200. }
  201. }
  202. #ifdef _WIN64
  203. DWORD _GetWindowLong(
  204. PWND pwnd,
  205. int index,
  206. BOOL bAnsi)
  207. {
  208. DWORD UNALIGNED * KPTR_MODIFIER pudw;
  209. /*
  210. * If it's a dialog window, only a few indices are permitted.
  211. */
  212. if (GETFNID(pwnd) != 0) {
  213. if (TestWF(pwnd, WFDIALOGWINDOW)) {
  214. switch (index) {
  215. case DWLP_DLGPROC: // See similar case GWLP_WNDPROC
  216. RIPERR1(ERROR_INVALID_INDEX, RIP_WARNING, "GetWindowLong: invalid index %d", index);
  217. return 0;
  218. case DWLP_MSGRESULT:
  219. return (DWORD)((PDIALOG)pwnd)->resultWP;
  220. case DWLP_USER:
  221. return (DWORD)((PDIALOG)pwnd)->unused;
  222. default:
  223. if (index >= 0 && index < DLGWINDOWEXTRA) {
  224. RIPERR0(ERROR_PRIVATE_DIALOG_INDEX, RIP_VERBOSE, "");
  225. return 0;
  226. }
  227. }
  228. } else {
  229. if (index >= 0 &&
  230. (index < (int)(CBFNID(pwnd->fnid)-sizeof(WND)))) {
  231. switch (GETFNID(pwnd)) {
  232. case FNID_MDICLIENT:
  233. /*
  234. * Allow the 0 index (which is reserved) to be set/get.
  235. * Quattro Pro 1.0 uses this index!
  236. */
  237. if (index != 0)
  238. break;
  239. goto GetData;
  240. break;
  241. case FNID_EDIT:
  242. if (index != 0)
  243. break;
  244. /*
  245. * If we get to this point we need to return the first
  246. * entry in the lookaside. This will provide backward
  247. * compatibilty for 3.51 that allowed edit-controls to
  248. * do this. PeachTree is one app which required this.
  249. */
  250. pudw = (DWORD UNALIGNED * KPTR_MODIFIER)((KPBYTE)(pwnd + 1));
  251. /*
  252. * Do not dereference the pointer if we are not in
  253. * the proper address space. Apps like Spyxx like to
  254. * do this on other process' windows
  255. */
  256. return (TestWindowProcess(pwnd) ? *(DWORD UNALIGNED *)*(ULONG_PTR UNALIGNED *)pudw : PtrToUlong(pudw));
  257. }
  258. RIPERR3(ERROR_INVALID_INDEX,
  259. RIP_WARNING,
  260. "GetWindowLong: Trying to read private server data pwnd=(%#p) index=(%ld) fnid (%lX)",
  261. pwnd, index, (DWORD)pwnd->fnid);
  262. return 0;
  263. }
  264. }
  265. }
  266. if (index < 0) {
  267. if ((index != GWL_STYLE) && (index != GWL_EXSTYLE) && (index != GWL_ID) && (index != GWLP_USERDATA)) {
  268. RIPERR1(ERROR_INVALID_INDEX, RIP_WARNING, "GetWindowLong: invalid index %d", index);
  269. return 0;
  270. }
  271. return (DWORD)GetWindowData(pwnd, index, bAnsi);
  272. } else {
  273. if ((UINT)index + sizeof(DWORD) > (UINT)pwnd->cbwndExtra) {
  274. RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE, "");
  275. return 0;
  276. } else {
  277. GetData:
  278. pudw = (DWORD UNALIGNED * KPTR_MODIFIER)((KPBYTE)(pwnd + 1) + index);
  279. return *pudw;
  280. }
  281. }
  282. }
  283. #endif
  284. /***************************************************************************\
  285. * GetWindowData
  286. *
  287. * History:
  288. * 11-26-90 darrinm Wrote.
  289. \***************************************************************************/
  290. ULONG_PTR GetWindowData(
  291. PWND pwnd,
  292. int index,
  293. BOOL bAnsi)
  294. {
  295. KERNEL_ULONG_PTR dwProc;
  296. DWORD dwCPDType = 0;
  297. PWND pwndParent;
  298. switch (index) {
  299. case GWLP_USERDATA:
  300. return KERNEL_ULONG_PTR_TO_ULONG_PTR(pwnd->dwUserData);
  301. case GWL_EXSTYLE:
  302. /*
  303. * Apps should not mess with unused bits. We use them privately
  304. */
  305. return pwnd->ExStyle & WS_EX_ALLVALID;
  306. case GWL_STYLE:
  307. return pwnd->style;
  308. case GWLP_ID:
  309. if (TestwndChild(pwnd)) {
  310. return (ULONG_PTR)pwnd->spmenu;
  311. } else if (pwnd->spmenu != NULL) {
  312. PMENU pmenu;
  313. pmenu = REBASEALWAYS(pwnd, spmenu);
  314. return (ULONG_PTR)PtoH(pmenu);
  315. }
  316. return 0;
  317. case GWLP_HINSTANCE:
  318. return (ULONG_PTR)pwnd->hModule;
  319. case GWLP_WNDPROC: // See similar case DWLP_DLGPROC
  320. /*
  321. * Hide the window proc from other processes
  322. */
  323. if (!TestWindowProcess(pwnd)) {
  324. RIPERR1(ERROR_ACCESS_DENIED, RIP_WARNING, "Can not subclass another process's window %#p", pwnd);
  325. return 0;
  326. }
  327. /*
  328. * If the client queries a server-side winproc we return the
  329. * address of the client-side winproc (expecting ANSI or Unicode
  330. * depending on bAnsi)
  331. */
  332. if (TestWF(pwnd, WFSERVERSIDEPROC)) {
  333. dwProc = MapServerToClientPfn((KERNEL_ULONG_PTR)pwnd->lpfnWndProc, bAnsi);
  334. if (dwProc == 0)
  335. RIPMSG1(RIP_WARNING, "GetWindowLong: GWL_WNDPROC: Kernel-side wndproc can't be mapped for pwnd=%#p", pwnd);
  336. } else {
  337. /*
  338. * Keep edit control behavior compatible with NT 3.51.
  339. */
  340. if (GETFNID(pwnd) == FNID_EDIT) {
  341. dwProc = (ULONG_PTR)MapKernelClientFnToClientFn(pwnd->lpfnWndProc);
  342. goto CheckAnsiUnicodeMismatch;
  343. } else {
  344. PCLS pcls = REBASEALWAYS(pwnd, pcls);
  345. dwProc = MapClientNeuterToClientPfn(pcls, (KERNEL_ULONG_PTR)pwnd->lpfnWndProc, bAnsi);
  346. }
  347. /*
  348. * If the client mapping didn't change the window proc then see if
  349. * we need a callproc handle.
  350. */
  351. if (dwProc == (KERNEL_ULONG_PTR)pwnd->lpfnWndProc) {
  352. CheckAnsiUnicodeMismatch:
  353. /*
  354. * Need to return a CallProc handle if there is an Ansi/Unicode mismatch
  355. */
  356. if (bAnsi != (TestWF(pwnd, WFANSIPROC) ? TRUE : FALSE)) {
  357. dwCPDType |= bAnsi ? CPD_ANSI_TO_UNICODE : CPD_UNICODE_TO_ANSI;
  358. }
  359. }
  360. if (dwCPDType) {
  361. ULONG_PTR cpd;
  362. cpd = GetCPD(pwnd, dwCPDType | CPD_WND, KERNEL_ULONG_PTR_TO_ULONG_PTR(dwProc));
  363. if (cpd) {
  364. dwProc = cpd;
  365. } else {
  366. RIPMSG0(RIP_WARNING, "GetWindowLong unable to alloc CPD returning handle\n");
  367. }
  368. }
  369. }
  370. /*
  371. * return proc (or CPD handle)
  372. */
  373. return KERNEL_ULONG_PTR_TO_ULONG_PTR(dwProc);
  374. case GWLP_HWNDPARENT:
  375. /*
  376. * If the window is the desktop window, return
  377. * NULL to keep it compatible with Win31 and
  378. * to prevent any access to the desktop owner
  379. * window.
  380. */
  381. if (GETFNID(pwnd) == FNID_DESKTOP) {
  382. return 0;
  383. }
  384. /*
  385. * Special case for pre-1.1 versions of Windows
  386. * Set/GetWindowWord(GWL_HWNDPARENT) needs to be mapped
  387. * to the hwndOwner for top level windows.
  388. *
  389. * Note that we find the desktop window through the
  390. * pti because the PWNDDESKTOP macro only works in
  391. * the server.
  392. */
  393. /*
  394. * Remove this test when we later add a test for WFDESTROYED
  395. * in Client handle validation.
  396. */
  397. if (pwnd->spwndParent == NULL) {
  398. return 0;
  399. }
  400. pwndParent = REBASEALWAYS(pwnd, spwndParent);
  401. if (GETFNID(pwndParent) == FNID_DESKTOP) {
  402. pwnd = REBASEPWND(pwnd, spwndOwner);
  403. return (ULONG_PTR)HW(pwnd);
  404. }
  405. return (ULONG_PTR)HW(pwndParent);
  406. /*
  407. * WOW uses a pointer straight into the window structure.
  408. */
  409. case GWLP_WOWWORDS:
  410. return (ULONG_PTR) &pwnd->state;
  411. }
  412. RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE, "");
  413. return 0;
  414. }
  415. #ifdef GENERIC_INPUT
  416. FUNCLOG3(LOG_GENERAL, UINT, DUMMYCALLINGTYPE, GetRawInputBuffer, PRAWINPUT, pData, PUINT, pcbSize, UINT, cbSizeHeader)
  417. UINT GetRawInputBuffer(PRAWINPUT pData, PUINT pcbSize, UINT cbSizeHeader)
  418. {
  419. CLIENTTHREADINFO *pcti;
  420. pcti = GETCLIENTTHREADINFO();
  421. // Validate parameters
  422. if (pcbSize == NULL || cbSizeHeader != sizeof(RAWINPUTHEADER)) {
  423. RIPERR0(ERROR_INVALID_PARAMETER, RIP_VERBOSE, "");
  424. return -1;
  425. }
  426. // Don't even go into the kernel if there's no reason to
  427. if (pcti == NULL || (pcti->fsWakeBits & QS_RAWINPUT) == 0) {
  428. *pcbSize = 0;
  429. return 0;
  430. }
  431. return NtUserGetRawInputBuffer(pData, pcbSize, cbSizeHeader);
  432. }
  433. #endif // GENERIC_INPUT