Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

getsetc.c

Go to the documentation of this file.
00001 /****************************** Module Header ******************************\ 00002 * Module Name: getsetc.c 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * This module contains window manager information routines 00007 * 00008 * History: 00009 * 10-Mar-1993 JerrySh Pulled functions from user\server. 00010 \***************************************************************************/ 00011 00012 #include "precomp.h" 00013 #pragma hdrstop 00014 00015 /***************************************************************************\ 00016 * _GetWindowWord (supports the GetWindowWord API) 00017 * 00018 * Return a window word. Positive index values return application window words 00019 * while negative index values return system window words. The negative 00020 * indices are published in WINDOWS.H. 00021 * 00022 * History: 00023 * 11-26-90 darrinm Wrote. 00024 \***************************************************************************/ 00025 00026 WORD _GetWindowWord( 00027 PWND pwnd, 00028 int index) 00029 { 00030 if (GETFNID(pwnd) != 0) { 00031 if ((index >= 0) && (index < 00032 (int)(CBFNID(pwnd->fnid)-sizeof(WND)))) { 00033 00034 switch (GETFNID(pwnd)) { 00035 case FNID_MDICLIENT: 00036 if (index == 0) 00037 break; 00038 goto DoDefault; 00039 00040 case FNID_BUTTON: 00041 /* 00042 * CorelDraw does a get/set on the first button window word. 00043 * Allow it to. 00044 */ 00045 if (index == 0) { 00046 /* 00047 * Since we now use a lookaside buffer for the control's 00048 * private data, we need to indirect into this structure. 00049 */ 00050 PBUTN pbutn = ((PBUTNWND)pwnd)->pbutn; 00051 if (!pbutn || (LONG_PTR)pbutn == (LONG_PTR)-1) { 00052 return 0; 00053 } else { 00054 return (WORD)(pbutn->buttonState); 00055 } 00056 } 00057 goto DoDefault; 00058 00059 case FNID_DIALOG: 00060 if (index == DWLP_USER) 00061 return LOWORD(((PDIALOG)pwnd)->unused); 00062 if (index == DWLP_USER+2) 00063 return HIWORD(((PDIALOG)pwnd)->unused); 00064 goto DoDefault; 00065 00066 default: 00067 DoDefault: 00068 RIPERR3(ERROR_INVALID_INDEX, 00069 RIP_WARNING, 00070 "GetWindowWord: Trying to read private server data pwnd=(%#p) index=(%ld) fnid=(%lX)", 00071 pwnd, index, (DWORD)pwnd->fnid); 00072 return 0; 00073 break; 00074 } 00075 } 00076 } 00077 00078 if (index == GWLP_USERDATA) 00079 return (WORD)pwnd->dwUserData; 00080 00081 if ((index < 0) || ((UINT)index + sizeof(WORD) > (UINT)pwnd->cbwndExtra)) { 00082 RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE, ""); 00083 return 0; 00084 } else { 00085 return *((WORD UNALIGNED *)((BYTE *)(pwnd + 1) + index)); 00086 } 00087 } 00088 00089 ULONG_PTR GetWindowData(PWND pwnd, int index, BOOL bAnsi); 00090 00091 /***************************************************************************\ 00092 * _GetWindowLong (supports GetWindowLongA/W API) 00093 * 00094 * Return a window long. Positive index values return application window longs 00095 * while negative index values return system window longs. The negative 00096 * indices are published in WINDOWS.H. 00097 * 00098 * History: 00099 * 11-26-90 darrinm Wrote. 00100 \***************************************************************************/ 00101 00102 ULONG_PTR _GetWindowLongPtr( 00103 PWND pwnd, 00104 int index, 00105 BOOL bAnsi) 00106 { 00107 ULONG_PTR dwProc; 00108 DWORD dwCPDType = 0; 00109 ULONG_PTR UNALIGNED *pudw; 00110 00111 /* 00112 * If it's a dialog window, only a few indices are permitted. 00113 */ 00114 if (GETFNID(pwnd) != 0) { 00115 if (TestWF(pwnd, WFDIALOGWINDOW)) { 00116 switch (index) { 00117 case DWLP_DLGPROC: // See similar case GWLP_WNDGPROC 00118 00119 /* 00120 * Hide the window proc from other processes 00121 */ 00122 if (!TestWindowProcess(pwnd)) { 00123 RIPERR1(ERROR_ACCESS_DENIED, 00124 RIP_WARNING, 00125 "Access denied to \"pwnd\" (%#p) in _GetWindowLong", 00126 pwnd); 00127 00128 return 0; 00129 } 00130 00131 dwProc = (ULONG_PTR)PDLG(pwnd)->lpfnDlg; 00132 00133 /* 00134 * If a proc exists check it to see if we need a translation 00135 */ 00136 if (dwProc) { 00137 00138 /* 00139 * May need to return a CallProc handle if there is an 00140 * Ansi/Unicode transition 00141 */ 00142 if (bAnsi != ((PDLG(pwnd)->flags & DLGF_ANSI) ? TRUE : FALSE)) { 00143 dwCPDType |= bAnsi ? CPD_ANSI_TO_UNICODE : CPD_UNICODE_TO_ANSI; 00144 } 00145 00146 if (dwCPDType) { 00147 ULONG_PTR cpd; 00148 00149 cpd = GetCPD(pwnd, dwCPDType | CPD_DIALOG, dwProc); 00150 00151 if (cpd) { 00152 dwProc = cpd; 00153 } else { 00154 RIPMSG0(RIP_WARNING, "GetWindowLong unable to alloc CPD returning handle\n"); 00155 } 00156 } 00157 } 00158 00159 /* 00160 * return proc (or CPD handle) 00161 */ 00162 return dwProc; 00163 00164 case DWLP_MSGRESULT: 00165 return (ULONG_PTR)((PDIALOG)pwnd)->resultWP; 00166 00167 case DWLP_USER: 00168 return (ULONG_PTR)((PDIALOG)pwnd)->unused; 00169 00170 default: 00171 if (index >= 0 && index < DLGWINDOWEXTRA) { 00172 RIPERR0(ERROR_PRIVATE_DIALOG_INDEX, RIP_VERBOSE, ""); 00173 return 0; 00174 } 00175 } 00176 } else { 00177 if (index >= 0 && 00178 (index < (int)(CBFNID(pwnd->fnid)-sizeof(WND)))) { 00179 switch (GETFNID(pwnd)) { 00180 case FNID_MDICLIENT: 00181 /* 00182 * Allow the 0 index (which is reserved) to be set/get. 00183 * Quattro Pro 1.0 uses this index! 00184 */ 00185 if (index != 0) 00186 break; 00187 00188 goto GetData; 00189 break; 00190 00191 case FNID_EDIT: 00192 00193 if (index != 0) 00194 break; 00195 00196 /* 00197 * If we get to this point we need to return the first 00198 * entry in the lookaside. This will provide backward 00199 * compatibilty for 3.51 that allowed edit-controls to 00200 * do this. PeachTree is one app which required this. 00201 */ 00202 pudw = (ULONG_PTR UNALIGNED *)((BYTE *)(pwnd + 1)); 00203 00204 /* 00205 * Do not dereference the pointer if we are not in 00206 * the proper address space. Apps like Spyxx like to 00207 * do this on other process' windows 00208 */ 00209 return (TestWindowProcess(pwnd) ? *(ULONG_PTR UNALIGNED *)*pudw : (ULONG_PTR)pudw); 00210 00211 } 00212 00213 RIPERR3(ERROR_INVALID_INDEX, 00214 RIP_WARNING, 00215 "GetWindowLong: Trying to read private server data pwnd=(%#p) index=(%ld) fnid (%lX)", 00216 pwnd, index, (DWORD)pwnd->fnid); 00217 return 0; 00218 } 00219 } 00220 } 00221 00222 if (index < 0) { 00223 return GetWindowData(pwnd, index, bAnsi); 00224 } else { 00225 if ((UINT)index + sizeof(ULONG_PTR) > (UINT)pwnd->cbwndExtra) { 00226 RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE, ""); 00227 return 0; 00228 } else { 00229 00230 GetData: 00231 pudw = (ULONG_PTR UNALIGNED *)((BYTE *)(pwnd + 1) + index); 00232 return *pudw; 00233 } 00234 } 00235 } 00236 00237 00238 #ifdef _WIN64 00239 DWORD _GetWindowLong( 00240 PWND pwnd, 00241 int index, 00242 BOOL bAnsi) 00243 { 00244 DWORD UNALIGNED *pudw; 00245 00246 /* 00247 * If it's a dialog window, only a few indices are permitted. 00248 */ 00249 if (GETFNID(pwnd) != 0) { 00250 if (TestWF(pwnd, WFDIALOGWINDOW)) { 00251 switch (index) { 00252 case DWLP_DLGPROC: // See similar case GWLP_WNDPROC 00253 RIPERR1(ERROR_INVALID_INDEX, RIP_WARNING, "GetWindowLong: invalid index %d", index); 00254 return 0; 00255 00256 case DWLP_MSGRESULT: 00257 return (DWORD)((PDIALOG)pwnd)->resultWP; 00258 00259 case DWLP_USER: 00260 return (DWORD)((PDIALOG)pwnd)->unused; 00261 00262 default: 00263 if (index >= 0 && index < DLGWINDOWEXTRA) { 00264 RIPERR0(ERROR_PRIVATE_DIALOG_INDEX, RIP_VERBOSE, ""); 00265 return 0; 00266 } 00267 } 00268 } else { 00269 if (index >= 0 && 00270 (index < (int)(CBFNID(pwnd->fnid)-sizeof(WND)))) { 00271 switch (GETFNID(pwnd)) { 00272 case FNID_MDICLIENT: 00273 /* 00274 * Allow the 0 index (which is reserved) to be set/get. 00275 * Quattro Pro 1.0 uses this index! 00276 */ 00277 if (index != 0) 00278 break; 00279 00280 goto GetData; 00281 break; 00282 00283 case FNID_EDIT: 00284 00285 if (index != 0) 00286 break; 00287 00288 /* 00289 * If we get to this point we need to return the first 00290 * entry in the lookaside. This will provide backward 00291 * compatibilty for 3.51 that allowed edit-controls to 00292 * do this. PeachTree is one app which required this. 00293 */ 00294 pudw = (DWORD UNALIGNED *)((BYTE *)(pwnd + 1)); 00295 00296 /* 00297 * Do not dereference the pointer if we are not in 00298 * the proper address space. Apps like Spyxx like to 00299 * do this on other process' windows 00300 */ 00301 return (TestWindowProcess(pwnd) ? *(DWORD UNALIGNED *)*(ULONG_PTR UNALIGNED *)pudw : PtrToUlong(pudw)); 00302 00303 00304 } 00305 00306 RIPERR3(ERROR_INVALID_INDEX, 00307 RIP_WARNING, 00308 "GetWindowLong: Trying to read private server data pwnd=(%#p) index=(%ld) fnid (%lX)", 00309 pwnd, index, (DWORD)pwnd->fnid); 00310 return 0; 00311 } 00312 } 00313 } 00314 00315 if (index < 0) { 00316 if ((index != GWL_STYLE) && (index != GWL_EXSTYLE) && (index != GWL_ID) && (index != GWLP_USERDATA)) { 00317 RIPERR1(ERROR_INVALID_INDEX, RIP_WARNING, "GetWindowLong: invalid index %d", index); 00318 return 0; 00319 } 00320 return (DWORD)GetWindowData(pwnd, index, bAnsi); 00321 } else { 00322 if ((UINT)index + sizeof(DWORD) > (UINT)pwnd->cbwndExtra) { 00323 RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE, ""); 00324 return 0; 00325 } else { 00326 00327 GetData: 00328 pudw = (DWORD UNALIGNED *)((BYTE *)(pwnd + 1) + index); 00329 return *pudw; 00330 } 00331 } 00332 } 00333 #endif 00334 00335 00336 /***************************************************************************\ 00337 * GetWindowData 00338 * 00339 * History: 00340 * 11-26-90 darrinm Wrote. 00341 \***************************************************************************/ 00342 00343 ULONG_PTR GetWindowData( 00344 PWND pwnd, 00345 int index, 00346 BOOL bAnsi) 00347 { 00348 KERNEL_ULONG_PTR dwProc; 00349 DWORD dwCPDType = 0; 00350 PWND pwndParent; 00351 00352 switch (index) { 00353 case GWLP_USERDATA: 00354 return KERNEL_ULONG_PTR_TO_ULONG_PTR(pwnd->dwUserData); 00355 00356 case GWL_EXSTYLE: 00357 /* 00358 * Apps should not mess with unused bits. We use them privately 00359 */ 00360 return pwnd->ExStyle & WS_EX_ALLVALID; 00361 00362 case GWL_STYLE: 00363 return pwnd->style; 00364 00365 case GWLP_ID: 00366 if (TestwndChild(pwnd)) { 00367 return (ULONG_PTR)pwnd->spmenu; 00368 } else if (pwnd->spmenu != NULL) { 00369 PMENU pmenu; 00370 00371 pmenu = REBASEALWAYS(pwnd, spmenu); 00372 return (ULONG_PTR)PtoH(pmenu); 00373 } 00374 return 0; 00375 00376 case GWLP_HINSTANCE: 00377 return (ULONG_PTR)pwnd->hModule; 00378 00379 case GWLP_WNDPROC: // See similar case DWLP_DLGPROC 00380 /* 00381 * Hide the window proc from other processes 00382 */ 00383 if (!TestWindowProcess(pwnd)) { 00384 RIPERR1(ERROR_ACCESS_DENIED, RIP_WARNING, "Can not subclass another process's window %#p", pwnd); 00385 return 0; 00386 } 00387 00388 /* 00389 * If the client queries a server-side winproc we return the 00390 * address of the client-side winproc (expecting ANSI or Unicode 00391 * depending on bAnsi) 00392 */ 00393 if (TestWF(pwnd, WFSERVERSIDEPROC)) { 00394 dwProc = MapServerToClientPfn((KERNEL_ULONG_PTR)pwnd->lpfnWndProc, bAnsi); 00395 if (dwProc == 0) 00396 RIPMSG1(RIP_WARNING, "GetWindowLong: GWL_WNDPROC: Kernel-side wndproc can't be mapped for pwnd=%#p", pwnd); 00397 } else { 00398 00399 /* 00400 * Keep edit control behavior compatible with NT 3.51. 00401 */ 00402 if (GETFNID(pwnd) == FNID_EDIT) { 00403 dwProc = (ULONG_PTR)MapKernelClientFnToClientFn(pwnd->lpfnWndProc); 00404 goto CheckAnsiUnicodeMismatch; 00405 } else { 00406 PCLS pcls = REBASEALWAYS(pwnd, pcls); 00407 dwProc = MapClientNeuterToClientPfn(pcls, (KERNEL_ULONG_PTR)pwnd->lpfnWndProc, bAnsi); 00408 } 00409 00410 /* 00411 * If the client mapping didn't change the window proc then see if 00412 * we need a callproc handle. 00413 */ 00414 if (dwProc == (KERNEL_ULONG_PTR)pwnd->lpfnWndProc) { 00415 CheckAnsiUnicodeMismatch: 00416 /* 00417 * Need to return a CallProc handle if there is an Ansi/Unicode mismatch 00418 */ 00419 if (bAnsi != (TestWF(pwnd, WFANSIPROC) ? TRUE : FALSE)) { 00420 dwCPDType |= bAnsi ? CPD_ANSI_TO_UNICODE : CPD_UNICODE_TO_ANSI; 00421 } 00422 } 00423 00424 if (dwCPDType) { 00425 ULONG_PTR cpd; 00426 00427 cpd = GetCPD(pwnd, dwCPDType | CPD_WND, KERNEL_ULONG_PTR_TO_ULONG_PTR(dwProc)); 00428 00429 if (cpd) { 00430 dwProc = cpd; 00431 } else { 00432 RIPMSG0(RIP_WARNING, "GetWindowLong unable to alloc CPD returning handle\n"); 00433 } 00434 } 00435 } 00436 00437 /* 00438 * return proc (or CPD handle) 00439 */ 00440 return KERNEL_ULONG_PTR_TO_ULONG_PTR(dwProc); 00441 00442 case GWLP_HWNDPARENT: 00443 00444 /* 00445 * If the window is the desktop window, return 00446 * NULL to keep it compatible with Win31 and 00447 * to prevent any access to the desktop owner 00448 * window. 00449 */ 00450 if (GETFNID(pwnd) == FNID_DESKTOP) { 00451 return 0; 00452 } 00453 00454 /* 00455 * Special case for pre-1.1 versions of Windows 00456 * Set/GetWindowWord(GWL_HWNDPARENT) needs to be mapped 00457 * to the hwndOwner for top level windows. 00458 * 00459 * Note that we find the desktop window through the 00460 * pti because the PWNDDESKTOP macro only works in 00461 * the server. 00462 */ 00463 00464 /* 00465 * Remove this test when we later add a test for WFDESTROYED 00466 * in Client handle validation. 00467 */ 00468 if (pwnd->spwndParent == NULL) { 00469 return 0; 00470 } 00471 pwndParent = REBASEALWAYS(pwnd, spwndParent); 00472 if (GETFNID(pwndParent) == FNID_DESKTOP) { 00473 pwnd = REBASEPWND(pwnd, spwndOwner); 00474 return (ULONG_PTR)HW(pwnd); 00475 } 00476 00477 return (ULONG_PTR)HW(pwndParent); 00478 00479 /* 00480 * WOW uses a pointer straight into the window structure. 00481 */ 00482 case GWLP_WOWWORDS: 00483 return (ULONG_PTR) &pwnd->state; 00484 00485 } 00486 00487 RIPERR0(ERROR_INVALID_INDEX, RIP_VERBOSE, ""); 00488 return 0; 00489 }

Generated on Sat May 15 19:40:13 2004 for test by doxygen 1.3.7