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

clmsg.c

Go to the documentation of this file.
00001 /****************************** Module Header ******************************\ 00002 * Module Name: ClMsg.c 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * Includes the mapping table for messages when calling the server. 00007 * 00008 * 04-11-91 ScottLu Created. 00009 \***************************************************************************/ 00010 00011 #include "precomp.h" 00012 #pragma hdrstop 00013 00014 00015 #define fnINDESTROYCLIPBRD fnDWORD 00016 #define fnOUTDWORDDWORD fnDWORD 00017 #define fnPOWERBROADCAST fnDWORD 00018 #define fnLOGONNOTIFY fnKERNELONLY 00019 #define fnINLPKDRAWSWITCHWND fnKERNELONLY 00020 00021 #define MSGFN(func) fn ## func 00022 #define FNSCSENDMESSAGE CFNSCSENDMESSAGE 00023 00024 #include "messages.h" 00025 00026 #if DBG 00027 BOOL gfTurboDWP = TRUE; 00028 #endif 00029 00030 /***************************************************************************\ 00031 * GetMouseKeyState 00032 * 00033 * Returns the state of mouse and keyboard keys that are sent 00034 * in a mouse message. 00035 * 00036 * History: 00037 * 12-Nov-1998 adams Created. 00038 \***************************************************************************/ 00039 00040 WORD 00041 GetMouseKeyState(void) 00042 { 00043 WORD keystate; 00044 00045 /* 00046 * Note that it is more efficient to call GetKeyState for each 00047 * key than to call GetKeyboardState, since the keys we are testing 00048 * are cached and don't require a trip to the kernel to fetch. 00049 */ 00050 00051 #define TESTANDSETKEYSTATE(x) \ 00052 if (GetKeyState(VK_##x) & 0x8000) { \ 00053 keystate |= MK_##x; \ 00054 } 00055 00056 keystate = 0; 00057 TESTANDSETKEYSTATE(LBUTTON) 00058 TESTANDSETKEYSTATE(RBUTTON) 00059 TESTANDSETKEYSTATE(MBUTTON) 00060 TESTANDSETKEYSTATE(XBUTTON1) 00061 TESTANDSETKEYSTATE(XBUTTON2) 00062 TESTANDSETKEYSTATE(SHIFT) 00063 TESTANDSETKEYSTATE(CONTROL) 00064 00065 return keystate; 00066 } 00067 00068 /***************************************************************************\ 00069 * These are client side thunks for server side window procs. This is being 00070 * done so that when an app gets a wndproc via GetWindowLong, GetClassLong, 00071 * or GetClassInfo, it gets a real callable address - some apps don't call 00072 * CallWindowProc, but call the return ed address directly. 00073 * 00074 * 01-13-92 ScottLu Created. 00075 * 03-Dec-1993 mikeke added client side handling of some messages 00076 \***************************************************************************/ 00077 00078 LRESULT WINAPI DesktopWndProcWorker( 00079 HWND hwnd, 00080 UINT message, 00081 WPARAM wParam, 00082 LPARAM lParam, 00083 BOOL fAnsi) 00084 { 00085 PWND pwnd; 00086 00087 if (FWINDOWMSG(message, FNID_DESKTOP)) { 00088 return CsSendMessage(hwnd, message, wParam, lParam, 00089 0L, FNID_DESKTOP, fAnsi); 00090 } 00091 00092 if ((pwnd = ValidateHwnd(hwnd)) == NULL) 00093 return 0; 00094 00095 return DefWindowProcWorker(pwnd, message, wParam, lParam, fAnsi); 00096 00097 } 00098 00099 LRESULT WINAPI DesktopWndProcA( 00100 HWND hwnd, 00101 UINT message, 00102 WPARAM wParam, 00103 LPARAM lParam) 00104 { 00105 return DesktopWndProcWorker(hwnd, message, wParam, lParam, TRUE); 00106 } 00107 00108 LRESULT WINAPI DesktopWndProcW( 00109 HWND hwnd, 00110 UINT message, 00111 WPARAM wParam, 00112 LPARAM lParam) 00113 { 00114 return DesktopWndProcWorker(hwnd, message, wParam, lParam, FALSE); 00115 } 00116 00117 /***************************************************************************\ 00118 * These are client side thunks for server side window procs. This is being 00119 * done so that when an app gets a wndproc via GetWindowLong, GetClassLong, 00120 * or GetClassInfo, it gets a real callable address - some apps don't call 00121 * CallWindowProc, but call the return ed address directly. 00122 * 00123 * 01-13-92 ScottLu Created. 00124 * 03-Dec-1993 mikeke added client side handling of some messages 00125 \***************************************************************************/ 00126 00127 LRESULT WINAPI MenuWndProcWorker( 00128 HWND hwnd, 00129 UINT message, 00130 WPARAM wParam, 00131 LPARAM lParam, 00132 BOOL fAnsi) 00133 { 00134 PWND pwnd; 00135 00136 if (FWINDOWMSG(message, FNID_MENU)) { 00137 return CsSendMessage(hwnd, message, wParam, lParam, 00138 0L, FNID_MENU, fAnsi); 00139 } 00140 00141 if ((pwnd = ValidateHwnd(hwnd)) == NULL) 00142 return 0; 00143 00144 switch (message) { 00145 case WM_LBUTTONDBLCLK: 00146 case WM_NCLBUTTONDBLCLK: 00147 case WM_RBUTTONDBLCLK: 00148 case WM_NCRBUTTONDBLCLK: 00149 00150 /* 00151 * Ignore double clicks on these windows. 00152 */ 00153 break; 00154 00155 case WM_DESTROY: 00156 break; 00157 00158 default: 00159 return DefWindowProcWorker(pwnd, message, wParam, lParam, fAnsi); 00160 } 00161 00162 return 0; 00163 } 00164 00165 LRESULT WINAPI MenuWndProcA( 00166 HWND hwnd, 00167 UINT message, 00168 WPARAM wParam, 00169 LPARAM lParam) 00170 { 00171 return MenuWndProcWorker(hwnd, message, wParam, lParam, TRUE); 00172 } 00173 00174 LRESULT WINAPI MenuWndProcW( 00175 HWND hwnd, 00176 UINT message, 00177 WPARAM wParam, 00178 LPARAM lParam) 00179 { 00180 return MenuWndProcWorker(hwnd, message, wParam, lParam, FALSE); 00181 } 00182 00183 /***************************************************************************\ 00184 \***************************************************************************/ 00185 00186 00187 LRESULT WINAPI ScrollBarWndProcWorker( 00188 HWND hwnd, 00189 UINT message, 00190 WPARAM wParam, 00191 LPARAM lParam, 00192 BOOL fAnsi) 00193 { 00194 PSBWND psbwnd; 00195 LPSCROLLINFO lpsi; 00196 PSBDATA pw; 00197 00198 if (FWINDOWMSG(message, FNID_SCROLLBAR)) { 00199 return CsSendMessage(hwnd, message, wParam, lParam, 00200 0L, FNID_SCROLLBAR, fAnsi); 00201 } 00202 00203 if ((psbwnd = (PSBWND)ValidateHwnd(hwnd)) == NULL) 00204 return 0; 00205 00206 switch (message) { 00207 case WM_GETDLGCODE: 00208 return DLGC_WANTARROWS; 00209 00210 case SBM_GETPOS: 00211 return (LONG)psbwnd->SBCalc.pos; 00212 00213 case SBM_GETRANGE: 00214 *((LPINT)wParam) = psbwnd->SBCalc.posMin; 00215 *((LPINT)lParam) = psbwnd->SBCalc.posMax; 00216 return 0; 00217 00218 case SBM_GETSCROLLINFO: 00219 lpsi = (LPSCROLLINFO)lParam; 00220 if ((lpsi->cbSize != sizeof(SCROLLINFO)) && 00221 (lpsi->cbSize != sizeof(SCROLLINFO) - 4)) { 00222 RIPMSG0(RIP_ERROR, "SCROLLINFO: invalid cbSize"); 00223 return FALSE; 00224 } 00225 00226 if (lpsi->fMask & ~SIF_MASK) 00227 { 00228 RIPMSG0(RIP_ERROR, "SCROLLINFO: Invalid fMask"); 00229 return FALSE; 00230 } 00231 00232 pw = (PSBDATA)&(psbwnd->SBCalc); 00233 return(NtUserSBGetParms(hwnd, SB_CTL, pw, lpsi)); 00234 00235 default: 00236 return DefWindowProcWorker((PWND)psbwnd, message, 00237 wParam, lParam, fAnsi); 00238 } 00239 } 00240 00241 00242 LRESULT WINAPI ScrollBarWndProcA( 00243 HWND hwnd, 00244 UINT message, 00245 WPARAM wParam, 00246 LPARAM lParam) 00247 { 00248 return ScrollBarWndProcWorker(hwnd, message, wParam, lParam, TRUE); 00249 } 00250 00251 LRESULT WINAPI ScrollBarWndProcW( 00252 HWND hwnd, 00253 UINT message, 00254 WPARAM wParam, 00255 LPARAM lParam) 00256 { 00257 return ScrollBarWndProcWorker(hwnd, message, wParam, lParam, FALSE); 00258 } 00259 00260 00261 /***************************************************************************\ 00262 * SendMessage 00263 * 00264 * Translates the message, calls SendMessage on server side. 00265 * 00266 * 04-11-91 ScottLu Created. 00267 * 04-27-92 DarrinM Added code to support client-to-client SendMessages. 00268 \***************************************************************************/ 00269 00270 LRESULT SendMessageWorker( 00271 PWND pwnd, 00272 UINT message, 00273 WPARAM wParam, 00274 LPARAM lParam, 00275 BOOL fAnsi) 00276 { 00277 HWND hwnd = HWq(pwnd); 00278 PCLIENTINFO pci; 00279 PCLS pcls; 00280 BOOLEAN fAnsiRecv; 00281 BOOLEAN fNeedTranslation = FALSE; 00282 BOOLEAN bDoDbcsMessaging = FALSE; 00283 LRESULT lRet; 00284 00285 UserAssert(pwnd); 00286 00287 /* 00288 * Pass DDE messages to the server. 00289 */ 00290 if (message >= WM_DDE_FIRST && message <= WM_DDE_LAST) 00291 goto lbServerSendMessage; 00292 00293 /* 00294 * Server must handle inter-thread SendMessages and SendMessages 00295 * to server-side procs. 00296 */ 00297 if ((PtiCurrent() != GETPTI(pwnd)) || TestWF(pwnd, WFSERVERSIDEPROC)) 00298 goto lbServerSendMessage; 00299 00300 /* 00301 * Server must handle hooks (at least for now). 00302 */ 00303 pci = GetClientInfo(); 00304 if (IsHooked(pci, (WHF_CALLWNDPROC | WHF_CALLWNDPROCRET))) { 00305 lbServerSendMessage: 00306 return CsSendMessage(hwnd, message, wParam, lParam, 0L, 00307 FNID_SENDMESSAGE, fAnsi); 00308 } 00309 00310 /* 00311 * If the sender and the receiver are both ANSI or both UNICODE 00312 * then no message translation is necessary. 00313 * 00314 * EditWndProc may need to go to the server for translation if we 00315 * are calling vanilla EditWndProc from SendMessageA and the edit 00316 * control is currently subclassed Ansi but the edit control is 00317 * stored Unicode. 00318 */ 00319 fAnsiRecv = !!(TestWF(pwnd, WFANSIPROC)); 00320 if (!fAnsi != !fAnsiRecv) { 00321 00322 /* 00323 * Translation might be necessary between sender and receiver, 00324 * check to see if this is one of the messages we translate. 00325 */ 00326 switch (message) { 00327 case WM_CHARTOITEM: 00328 case EM_SETPASSWORDCHAR: 00329 case WM_CHAR: 00330 case WM_DEADCHAR: 00331 case WM_SYSCHAR: 00332 case WM_SYSDEADCHAR: 00333 case WM_MENUCHAR: 00334 case WM_IME_CHAR: 00335 case WM_IME_COMPOSITION: 00336 if (fAnsi) { 00337 /* 00338 * Setup DBCS Messaging for WM_CHAR... 00339 */ 00340 BUILD_DBCS_MESSAGE_TO_CLIENTW_FROM_CLIENTA(message,wParam,TRUE); 00341 00342 /* 00343 * Convert wParam to Unicode... 00344 */ 00345 RtlMBMessageWParamCharToWCS(message, &wParam); 00346 00347 /* 00348 * The message has been converted to Unicode. 00349 */ 00350 fAnsi = FALSE; 00351 } else { 00352 POINT ptZero = {0,0}; 00353 /* 00354 * Convert wParam to ANSI... 00355 */ 00356 RtlWCSMessageWParamCharToMB(message, &wParam); 00357 00358 /* 00359 * Let's DBCS messaging for WM_CHAR.... 00360 */ 00361 BUILD_DBCS_MESSAGE_TO_CLIENTA_FROM_CLIENTW( 00362 hwnd,message,wParam,lParam,0,ptZero,bDoDbcsMessaging); 00363 00364 /* 00365 * The message has been converted to ANSI. 00366 */ 00367 fAnsi = TRUE; 00368 } 00369 break; 00370 00371 case EM_SETSEL: 00372 case EM_GETSEL: 00373 case CB_GETEDITSEL: 00374 if (IS_DBCS_ENABLED()) { 00375 RIPERR1(ERROR_INVALID_PARAMETER, 00376 RIP_WARNING, 00377 "Invalid DBCS message (%x) to SendMessageWorker",message); 00378 } 00379 // 00380 // Fall down... 00381 00382 default: 00383 if ((message < WM_USER) && MessageTable[message].bThunkMessage) { 00384 fNeedTranslation = TRUE; 00385 } 00386 } 00387 } 00388 00389 #ifndef LATER 00390 /* 00391 * If the window has a client side worker proc and has 00392 * not been subclassed, dispatch the message directly 00393 * to the worker proc. Otherwise, dispatch it normally. 00394 */ 00395 pcls = REBASEALWAYS(pwnd, pcls); 00396 00397 if ((pcls->fnid >= FNID_CONTROLSTART && pcls->fnid <= FNID_CONTROLEND) && 00398 ((KERNEL_ULONG_PTR)pwnd->lpfnWndProc == FNID_TO_CLIENT_PFNW_KERNEL(pcls->fnid) || 00399 (KERNEL_ULONG_PTR)pwnd->lpfnWndProc == FNID_TO_CLIENT_PFNA_KERNEL(pcls->fnid))) { 00400 PWNDMSG pwm = &gSharedInfo.awmControl[pcls->fnid - FNID_START]; 00401 00402 /* 00403 * If this message is not processed by the control, call 00404 * xxxDefWindowProc 00405 */ 00406 if (pwm->abMsgs && ((message > pwm->maxMsgs) || 00407 !((pwm->abMsgs)[message / 8] & (1 << (message & 7))))) { 00408 00409 /* 00410 * Special case dialogs so that we can ignore unimportant 00411 * messages during dialog creation. 00412 */ 00413 if (pcls->fnid == FNID_DIALOG && 00414 PDLG(pwnd) && PDLG(pwnd)->lpfnDlg != NULL) { 00415 /* 00416 * If A/W translation are needed for Dialog, 00417 * it should go to kernel side to perform proper message. 00418 * DefDlgProcWorker will call aplication's DlgProc directly 00419 * without A/W conversion. 00420 */ 00421 if (fNeedTranslation) { 00422 goto lbServerSendMessage; 00423 } 00424 /* 00425 * Call woker procudure. 00426 */ 00427 SendMessageToWorker1Again: 00428 lRet = ((PROC)(FNID_TO_CLIENT_PFNWORKER(pcls->fnid)))(pwnd, message, wParam, lParam, fAnsi); 00429 /* 00430 * if we have DBCS TrailingByte that should be sent, send it here.. 00431 */ 00432 DISPATCH_DBCS_MESSAGE_IF_EXIST(message,wParam,bDoDbcsMessaging,SendMessageToWorker1); 00433 00434 return lRet; 00435 } else { 00436 /* 00437 * Call worker procedure. 00438 */ 00439 SendMessageToDefWindowAgain: 00440 lRet = DefWindowProcWorker(pwnd, message, wParam, lParam, fAnsi); 00441 /* 00442 * if we have DBCS TrailingByte that should be sent, send it here.. 00443 */ 00444 DISPATCH_DBCS_MESSAGE_IF_EXIST(message,wParam,bDoDbcsMessaging,SendMessageToDefWindow); 00445 00446 return lRet; 00447 } 00448 } else { 00449 /* 00450 * Call woker procudure. 00451 */ 00452 SendMessageToWorker2Again: 00453 lRet = ((PROC)(FNID_TO_CLIENT_PFNWORKER(pcls->fnid)))(pwnd, message, wParam, lParam, fAnsi); 00454 00455 /* 00456 * if we have DBCS TrailingByte that should be sent, send it here.. 00457 */ 00458 DISPATCH_DBCS_MESSAGE_IF_EXIST(message,wParam,bDoDbcsMessaging,SendMessageToWorker2); 00459 00460 return lRet; 00461 } 00462 } 00463 #endif 00464 00465 /* 00466 * If this message needs to be translated, go through the kernel. 00467 */ 00468 if (fNeedTranslation) { 00469 goto lbServerSendMessage; 00470 } 00471 00472 /* 00473 * Call Client Windows procudure. 00474 */ 00475 SendMessageToWndProcAgain: 00476 00477 lRet = CALLPROC_WOWCHECKPWW(MapKernelClientFnToClientFn(pwnd->lpfnWndProc), hwnd, message, wParam, lParam, &(pwnd->state)); 00478 00479 /* 00480 * if we have DBCS TrailingByte that should be sent, send it here.. 00481 */ 00482 DISPATCH_DBCS_MESSAGE_IF_EXIST(message,wParam,bDoDbcsMessaging,SendMessageToWndProc); 00483 00484 return lRet; 00485 } 00486 00487 // LATER!!! can this somehow be combined or subroutinized with SendMessageWork 00488 // so we don't have to copies of 95% identical code. 00489 00490 /***************************************************************************\ 00491 * SendMessageTimeoutWorker 00492 * 00493 * Translates the message, calls SendMessageTimeout on server side. 00494 * 00495 * 07-21-92 ChrisBB Created/modified SendMessageWorkder 00496 \***************************************************************************/ 00497 00498 LRESULT SendMessageTimeoutWorker( 00499 HWND hwnd, 00500 UINT message, 00501 WPARAM wParam, 00502 LPARAM lParam, 00503 UINT fuFlags, 00504 UINT uTimeout, 00505 PULONG_PTR lpdwResult, 00506 BOOL fAnsi) 00507 { 00508 SNDMSGTIMEOUT smto; 00509 00510 /* 00511 * Prevent apps from setting hi 16 bits so we can use them internally. 00512 */ 00513 if (message & RESERVED_MSG_BITS) { 00514 RIPERR1(ERROR_INVALID_PARAMETER, 00515 RIP_WARNING, 00516 "Invalid parameter \"message\" (%ld) to SendMessageTimeoutWorker", 00517 message); 00518 00519 return(0); 00520 } 00521 00522 if (fuFlags & ~SMTO_VALID) { 00523 RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "invalid dwFlags (%x) for SendMessageTimeout\n", fuFlags); 00524 return(0); 00525 } 00526 00527 if (lpdwResult != NULL) 00528 *lpdwResult = 0L; 00529 00530 /* 00531 * Always send broadcast requests straight to the server. 00532 * Note: the xParam is used to id if it's from timeout or 00533 * from an normal sendmessage. 00534 */ 00535 smto.fuFlags = fuFlags; 00536 smto.uTimeout = uTimeout; 00537 smto.lSMTOReturn = 0; 00538 smto.lSMTOResult = 0; 00539 00540 /* 00541 * Thunk through a special sendmessage for -1 hwnd's so that the general 00542 * purpose thunks don't allow -1 hwnd's. 00543 */ 00544 if (hwnd == (HWND)-1 || hwnd == (HWND)0x0000FFFF) { 00545 /* 00546 * Get a real hwnd so the thunks will validation ok. Note that since 00547 * -1 hwnd is really rare, calling GetDesktopWindow() here is not a 00548 * big deal. 00549 */ 00550 hwnd = GetDesktopWindow(); 00551 00552 CsSendMessage(hwnd, message, wParam, lParam, 00553 (ULONG_PTR)&smto, FNID_SENDMESSAGEFF, fAnsi); 00554 } else { 00555 CsSendMessage(hwnd, message, wParam, lParam, 00556 (ULONG_PTR)&smto, FNID_SENDMESSAGEEX, fAnsi); 00557 } 00558 00559 if (lpdwResult != NULL) 00560 *lpdwResult = smto.lSMTOResult; 00561 00562 return smto.lSMTOReturn; 00563 } 00564 00565 /***************************************************************************\ 00566 * DefWindowProcWorker 00567 * 00568 * Handles any messages that can be dealt with wholly on the client and 00569 * passes the rest to the server. 00570 * 00571 * 03-31-92 DarrinM Created. 00572 \***************************************************************************/ 00573 00574 LRESULT DefWindowProcWorker( 00575 PWND pwnd, 00576 UINT message, 00577 WPARAM wParam, 00578 LPARAM lParam, 00579 DWORD fAnsi) 00580 { 00581 HWND hwnd = HWq(pwnd); 00582 int icolBack; 00583 int icolFore; 00584 PWND pwndParent; 00585 HWND hwndDefIme; 00586 PWND pwndDefIme; 00587 PIMEUI pimeui; 00588 00589 #if DBG 00590 if (!gfTurboDWP) { 00591 return CsSendMessage(hwnd, message, wParam, lParam, 0L, 00592 FNID_DEFWINDOWPROC, fAnsi); 00593 } else { 00594 #endif 00595 00596 00597 if (FDEFWINDOWMSG(message, DefWindowMsgs)) { 00598 return CsSendMessage(hwnd, message, wParam, lParam, 0L, 00599 FNID_DEFWINDOWPROC, fAnsi); 00600 } else if (!FDEFWINDOWMSG(message, DefWindowSpecMsgs)) { 00601 return 0; 00602 } 00603 00604 /* 00605 * Important: If you add cases to the switch statement below, 00606 * add the messages to server.c's gawDefWindowSpecMsgs. 00607 * Similarly if you add cases to dwp.c's DefWindowProc 00608 * which can come from the client, add the messages 00609 * to gawDefWindowMsgs. 00610 */ 00611 00612 switch (message) { 00613 00614 case WM_HELP: 00615 { 00616 PWND pwndDest; 00617 00618 /* 00619 * If this window is a child window, Help message must be passed on 00620 * to it's parent; Else, this must be passed on to the owner window. 00621 */ 00622 pwndDest = (TestwndChild(pwnd) ? pwnd->spwndParent : pwnd->spwndOwner); 00623 if (pwndDest) { 00624 pwndDest = REBASEPTR(pwnd, pwndDest); 00625 if (pwndDest != _GetDesktopWindow()) 00626 return SendMessageW(HWq(pwndDest), WM_HELP, wParam, lParam);; 00627 } 00628 return(0L); 00629 } 00630 00631 case WM_MOUSEWHEEL: 00632 if (TestwndChild(pwnd)) { 00633 pwndParent = REBASEPWND(pwnd, spwndParent); 00634 SendMessageW(HW(pwndParent), WM_MOUSEWHEEL, wParam, lParam); 00635 } 00636 break; 00637 00638 case WM_CONTEXTMENU: 00639 if (TestwndChild(pwnd)) { 00640 pwndParent = REBASEPWND(pwnd, spwndParent); 00641 SendMessageW(HW(pwndParent), WM_CONTEXTMENU, 00642 (WPARAM)hwnd, lParam); 00643 } 00644 break; 00645 00646 /* 00647 * Default handling for WM_CONTEXTMENU support 00648 */ 00649 case WM_RBUTTONUP: 00650 #ifdef USE_MIRRORING 00651 if (TestWF(pwnd, WEFLAYOUTRTL)) { 00652 lParam = MAKELONG(pwnd->rcClient.right - GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) + pwnd->rcClient.top); 00653 } else 00654 #endif 00655 { 00656 lParam = MAKELONG(GET_X_LPARAM(lParam) + pwnd->rcClient.left, GET_Y_LPARAM(lParam) + pwnd->rcClient.top); 00657 } 00658 SendMessageWorker(pwnd, WM_CONTEXTMENU, (WPARAM)hwnd, lParam, fAnsi); 00659 break; 00660 00661 case WM_APPCOMMAND: 00662 if (TestwndChild(pwnd)) { 00663 /* 00664 * Bubble the message to the parent 00665 */ 00666 pwndParent = REBASEPWND(pwnd, spwndParent); 00667 return SendMessageW(HW(pwndParent), WM_APPCOMMAND, wParam, lParam); 00668 } else { 00669 /* 00670 * Call the server side to send the shell hook HSHELL_APPCOMMAND 00671 */ 00672 return CsSendMessage(hwnd, WM_APPCOMMAND, wParam, lParam, 0L, FNID_DEFWINDOWPROC, fAnsi); 00673 } 00674 break; 00675 00676 /* 00677 * Default handling for WM_APPCOMMAND support 00678 */ 00679 case WM_NCXBUTTONUP: 00680 case WM_XBUTTONUP: 00681 { 00682 WORD cmd; 00683 WORD keystate; 00684 LPARAM lParamAppCommand; 00685 00686 switch (GET_XBUTTON_WPARAM(wParam)) { 00687 case XBUTTON1: 00688 cmd = APPCOMMAND_BROWSER_BACKWARD; 00689 break; 00690 00691 case XBUTTON2: 00692 cmd = APPCOMMAND_BROWSER_FORWARD; 00693 break; 00694 00695 default: 00696 cmd = 0; 00697 break; 00698 } 00699 00700 if (cmd == 0) { 00701 break; 00702 } 00703 00704 cmd |= FAPPCOMMAND_MOUSE; 00705 if (message == WM_XBUTTONUP) { 00706 keystate = GET_KEYSTATE_WPARAM(wParam); 00707 } else { 00708 keystate = GetMouseKeyState(); 00709 } 00710 00711 lParamAppCommand = MAKELPARAM(keystate, cmd); 00712 SendMessageWorker(pwnd, WM_APPCOMMAND, (WPARAM)hwnd, lParamAppCommand, fAnsi); 00713 break; 00714 } 00715 00716 case WM_WINDOWPOSCHANGED: { 00717 PWINDOWPOS ppos = (PWINDOWPOS)lParam; 00718 00719 if (!(ppos->flags & SWP_NOCLIENTMOVE)) { 00720 POINT pt = {pwnd->rcClient.left, pwnd->rcClient.top}; 00721 pwndParent = REBASEPWND(pwnd, spwndParent); 00722 00723 if (pwndParent != _GetDesktopWindow()) { 00724 pt.x -= pwndParent->rcClient.left; 00725 pt.y -= pwndParent->rcClient.top; 00726 } 00727 00728 SendMessageWorker(pwnd, WM_MOVE, FALSE, MAKELPARAM(pt.x, pt.y), fAnsi); 00729 } 00730 00731 if ((ppos->flags & SWP_STATECHANGE) || !(ppos->flags & SWP_NOCLIENTSIZE)) { 00732 UINT cmd; 00733 RECT rc; 00734 00735 if (TestWF(pwnd, WFMINIMIZED)) 00736 cmd = SIZEICONIC; 00737 else if (TestWF(pwnd, WFMAXIMIZED)) 00738 cmd = SIZEFULLSCREEN; 00739 else 00740 cmd = SIZENORMAL; 00741 00742 /* 00743 * HACK ALERT: 00744 * If the window is minimized then the real client width and height are 00745 * zero. But, in win3.1 they were non-zero. Under Chicago, PrintShop 00746 * Deluxe ver 1.2 hits a divide by zero. To fix this we fake the width 00747 * and height for old apps to be non-zero values. 00748 * GetClientRect does that job for us. 00749 */ 00750 _GetClientRect(pwnd, &rc); 00751 SendMessageWorker(pwnd, WM_SIZE, cmd, 00752 MAKELONG(rc.right - rc.left, 00753 rc.bottom - rc.top), fAnsi); 00754 } 00755 return 0; 00756 } 00757 00758 case WM_MOUSEACTIVATE: { 00759 PWND pwndT; 00760 LRESULT lt; 00761 00762 /* 00763 * GetChildParent returns either a kernel pointer or NULL. 00764 */ 00765 pwndT = GetChildParent(pwnd); 00766 if (pwndT != NULL) { 00767 pwndT = REBASEPTR(pwnd, pwndT); 00768 lt = SendMessageWorker(pwndT, WM_MOUSEACTIVATE, wParam, lParam, fAnsi); 00769 if (lt != 0) 00770 return lt; 00771 } 00772 00773 /* 00774 * Moving, sizing or minimizing? Activate AFTER we take action. 00775 */ 00776 return ((LOWORD(lParam) == HTCAPTION) && (HIWORD(lParam) == WM_LBUTTONDOWN )) ? 00777 (LONG)MA_NOACTIVATE : (LONG)MA_ACTIVATE; 00778 } 00779 00780 case WM_CTLCOLORSCROLLBAR: 00781 if ((gpsi->BitCount < 8) || 00782 (SYSRGB(3DHILIGHT) != SYSRGB(SCROLLBAR)) || 00783 (SYSRGB(3DHILIGHT) == SYSRGB(WINDOW))) 00784 { 00785 /* 00786 * Remove call to UnrealizeObject(). GDI Handles this for 00787 * brushes on NT. 00788 * 00789 * UnrealizeObject(ghbrGray); 00790 */ 00791 00792 SetBkColor((HDC)wParam, SYSRGB(3DHILIGHT)); 00793 SetTextColor((HDC)wParam, SYSRGB(3DFACE)); 00794 return((LRESULT)gpsi->hbrGray); 00795 } 00796 00797 icolBack = COLOR_3DHILIGHT; 00798 icolFore = COLOR_BTNTEXT; 00799 goto SetColor; 00800 00801 case WM_CTLCOLORBTN: 00802 if (pwnd == NULL) 00803 goto ColorDefault; 00804 00805 if (TestWF(pwnd, WFWIN40COMPAT)) { 00806 icolBack = COLOR_3DFACE; 00807 icolFore = COLOR_BTNTEXT; 00808 } else { 00809 goto ColorDefault; 00810 } 00811 goto SetColor; 00812 00813 case WM_CTLCOLORSTATIC: 00814 case WM_CTLCOLORDLG: 00815 case WM_CTLCOLORMSGBOX: 00816 // We want static controls in dialogs to have the 3D 00817 // background color, but statics in windows to inherit 00818 // their parents' background. 00819 00820 if (pwnd == NULL) 00821 goto ColorDefault; 00822 00823 if (TestWF(pwnd, WFWIN40COMPAT)) { 00824 icolBack = COLOR_3DFACE; 00825 icolFore = COLOR_WINDOWTEXT; 00826 goto SetColor; 00827 } 00828 // ELSE FALL THRU... 00829 00830 case WM_CTLCOLOR: // here for WOW only 00831 case WM_CTLCOLORLISTBOX: 00832 case WM_CTLCOLOREDIT: 00833 ColorDefault: 00834 icolBack = COLOR_WINDOW; 00835 icolFore = COLOR_WINDOWTEXT; 00836 00837 SetColor: 00838 { 00839 SetBkColor((HDC)wParam, gpsi->argbSystem[icolBack]); 00840 SetTextColor((HDC)wParam, gpsi->argbSystem[icolFore]); 00841 return (LRESULT)(SYSHBRUSH(icolBack)); 00842 } 00843 00844 case WM_NCHITTEST: 00845 return FindNCHit(pwnd, (LONG)lParam); 00846 00847 case WM_GETTEXT: 00848 if (wParam != 0) { 00849 00850 LPWSTR lpszText; 00851 UINT cchSrc; 00852 00853 if (pwnd->strName.Length) { 00854 00855 lpszText = REBASE(pwnd, strName.Buffer); 00856 cchSrc = (UINT)pwnd->strName.Length / sizeof(WCHAR); 00857 00858 if (fAnsi) { 00859 00860 LPSTR lpName = (LPSTR)lParam; 00861 00862 /* 00863 * Non-zero retval means some text to copy out. Do not 00864 * copy out more than the requested byte count 00865 * 'chMaxCount'. 00866 */ 00867 cchSrc = WCSToMB(lpszText, 00868 cchSrc, 00869 (LPSTR *)&lpName, 00870 (UINT)(wParam - 1), 00871 FALSE); 00872 00873 lpName[cchSrc] = '\0'; 00874 00875 } else { 00876 00877 LPWSTR lpwName = (LPWSTR)lParam; 00878 00879 cchSrc = min(cchSrc, (UINT)(wParam - 1)); 00880 RtlCopyMemory(lpwName, lpszText, cchSrc * sizeof(WCHAR)); 00881 lpwName[cchSrc] = 0; 00882 } 00883 00884 return cchSrc; 00885 } 00886 00887 /* 00888 * else Null terminate the text buffer since there is no text. 00889 */ 00890 if (fAnsi) { 00891 ((LPSTR)lParam)[0] = 0; 00892 } else { 00893 ((LPWSTR)lParam)[0] = 0; 00894 } 00895 } 00896 00897 return 0; 00898 00899 case WM_GETTEXTLENGTH: 00900 if (pwnd->strName.Length) { 00901 UINT cch; 00902 if (fAnsi) { 00903 RtlUnicodeToMultiByteSize(&cch, 00904 REBASE(pwnd, strName.Buffer), 00905 pwnd->strName.Length); 00906 } else { 00907 cch = pwnd->strName.Length / sizeof(WCHAR); 00908 } 00909 return cch; 00910 } 00911 return 0L; 00912 00913 case WM_QUERYDRAGICON: 00914 /* 00915 * If the window is WIN40COMPAT or has a kernel side procedure 00916 * do not attempt to look into the instance module 00917 */ 00918 if (TestWF(pwnd, WFWIN40COMPAT) || TestWF(pwnd, WFSERVERSIDEPROC)) { 00919 return 0; 00920 } 00921 /* 00922 * For old apps, like the VB3 ones, try to load the icon from resources 00923 * This is how Win95 does. 00924 */ 00925 return (LRESULT)LoadIconW(pwnd->hModule, MAKEINTRESOURCE(1)); 00926 00927 case WM_QUERYOPEN: 00928 case WM_QUERYENDSESSION: 00929 case WM_DEVICECHANGE: 00930 case WM_POWERBROADCAST: 00931 return TRUE; 00932 00933 case WM_KEYDOWN: 00934 if (wParam == VK_F10) { 00935 return CsSendMessage(hwnd, message, wParam, lParam, 0L, 00936 FNID_DEFWINDOWPROC, fAnsi); 00937 } 00938 break; 00939 00940 case WM_SYSKEYDOWN: 00941 if ((HIWORD(lParam) & SYS_ALTERNATE) || (wParam == VK_F10) || 00942 (wParam == VK_ESCAPE)) 00943 return CsSendMessage(hwnd, message, wParam, lParam, 0L, 00944 FNID_DEFWINDOWPROC, fAnsi); 00945 break; 00946 00947 case WM_CHARTOITEM: 00948 case WM_VKEYTOITEM: 00949 /* 00950 * Do default processing for keystrokes into owner draw listboxes. 00951 */ 00952 return -1; 00953 00954 case WM_ACTIVATE: 00955 if (LOWORD(wParam)) 00956 return CsSendMessage(hwnd, message, wParam, lParam, 0L, 00957 FNID_DEFWINDOWPROC, fAnsi); 00958 break; 00959 00960 case WM_SHOWWINDOW: 00961 if (lParam != 0) 00962 return CsSendMessage(hwnd, message, wParam, lParam, 0L, 00963 FNID_DEFWINDOWPROC, fAnsi); 00964 break; 00965 00966 case WM_DROPOBJECT: 00967 return DO_DROPFILE; 00968 00969 case WM_WINDOWPOSCHANGING: 00970 /* 00971 * If the window's size is changing, adjust the passed-in size 00972 */ 00973 #define ppos ((WINDOWPOS *)lParam) 00974 if (!(ppos->flags & SWP_NOSIZE)) 00975 return CsSendMessage(hwnd, message, wParam, lParam, 0L, 00976 FNID_DEFWINDOWPROC, fAnsi); 00977 #undef ppos 00978 break; 00979 00980 case WM_KLUDGEMINRECT: 00981 { 00982 SHELLHOOKINFO shi; 00983 LPRECT lprc = (LPRECT)lParam; 00984 00985 shi.hwnd = (HWND)wParam; 00986 shi.rc.left = MAKELONG(lprc->left, lprc->top); 00987 shi.rc.top = MAKELONG(lprc->right, lprc->bottom); 00988 00989 if (gpsi->uiShellMsg == 0) 00990 SetTaskmanWindow(NULL); 00991 if (SendMessageWorker(pwnd, gpsi->uiShellMsg, HSHELL_GETMINRECT, 00992 (LPARAM)&shi, fAnsi)) { 00993 // 00994 // Now convert the RECT back from two POINTS structures into two POINT 00995 // structures. 00996 // 00997 lprc->left = (SHORT)LOWORD(shi.rc.left); // Sign extend 00998 lprc->top = (SHORT)HIWORD(shi.rc.left); // Sign extend 00999 lprc->right = (SHORT)LOWORD(shi.rc.top); // Sign extend 01000 lprc->bottom = (SHORT)HIWORD(shi.rc.top); // Sign extend 01001 } 01002 break; 01003 } 01004 01005 case WM_NOTIFYFORMAT: 01006 if (lParam == NF_QUERY) 01007 return(TestWF(pwnd, WFANSICREATOR) ? NFR_ANSI : NFR_UNICODE); 01008 break; 01009 01010 case WM_IME_KEYDOWN: 01011 if (fAnsi) 01012 PostMessageA(hwnd, WM_KEYDOWN, wParam, lParam); 01013 else 01014 PostMessageW(hwnd, WM_KEYDOWN, wParam, lParam); 01015 break; 01016 01017 case WM_IME_KEYUP: 01018 if (fAnsi) 01019 PostMessageA(hwnd, WM_KEYUP, wParam, lParam); 01020 else 01021 PostMessageW(hwnd, WM_KEYUP, wParam, lParam); 01022 break; 01023 01024 case WM_IME_CHAR: 01025 //if (TestCF(pwnd, CFIME)) 01026 // break; 01027 01028 if ( fAnsi ) { 01029 if( IsDBCSLeadByteEx(THREAD_CODEPAGE(),(BYTE)(wParam >> 8)) ) { 01030 PostMessageA(hwnd, 01031 WM_CHAR, 01032 (WPARAM)((BYTE)(wParam >> 8)), // leading byte 01033 1L); 01034 PostMessageA(hwnd, 01035 WM_CHAR, 01036 (WPARAM)((BYTE)wParam), // trailing byte 01037 1L); 01038 } 01039 else 01040 PostMessageA(hwnd, 01041 WM_CHAR, 01042 (WPARAM)(wParam), 01043 1L); 01044 } else { 01045 PostMessageW(hwnd, WM_CHAR, wParam, 1L); 01046 } 01047 break; 01048 01049 case WM_IME_COMPOSITION: 01050 //if (TestCF(pwnd, CFIME)) 01051 // break; 01052 01053 if (lParam & GCS_RESULTSTR) { 01054 HIMC hImc; 01055 DWORD cbLen; 01056 01057 if ((hImc = fpImmGetContext(hwnd)) == NULL_HIMC) 01058 goto dwpime_ToIMEWnd_withchk; 01059 01060 if (fAnsi) { 01061 LPSTR pszBuffer, psz; 01062 01063 /* 01064 * ImmGetComposition returns the size of buffer needed in byte. 01065 */ 01066 if (!(cbLen = fpImmGetCompositionStringA(hImc, GCS_RESULTSTR, NULL, 0))) { 01067 fpImmReleaseContext(hwnd, hImc); 01068 goto dwpime_ToIMEWnd_withchk; 01069 } 01070 01071 pszBuffer = psz = (LPSTR)UserLocalAlloc(HEAP_ZERO_MEMORY, 01072 cbLen + sizeof(CHAR)); 01073 01074 if (pszBuffer == NULL) { 01075 fpImmReleaseContext(hwnd, hImc); 01076 goto dwpime_ToIMEWnd_withchk; 01077 } 01078 01079 fpImmGetCompositionStringA(hImc, GCS_RESULTSTR, psz, cbLen); 01080 01081 while (*psz) { 01082 if (IsDBCSLeadByteEx(THREAD_CODEPAGE(),*psz)) { 01083 if (*(psz+1)) { 01084 SendMessageA( hwnd, 01085 WM_IME_CHAR, 01086 MAKEWPARAM(MAKEWORD(*(psz+1), *psz), 0), 01087 1L ); 01088 psz++; 01089 } 01090 psz++; 01091 } 01092 else 01093 SendMessageA( hwnd, 01094 WM_IME_CHAR, 01095 MAKEWPARAM(MAKEWORD(*(psz++), 0), 0), 01096 1L ); 01097 } 01098 01099 UserLocalFree(pszBuffer); 01100 01101 fpImmReleaseContext(hwnd, hImc); 01102 } 01103 else { 01104 LPWSTR pwszBuffer, pwsz; 01105 01106 /* 01107 * ImmGetComposition returns the size of buffer needed in byte 01108 */ 01109 if (!(cbLen = fpImmGetCompositionStringW(hImc, GCS_RESULTSTR, NULL, 0))) { 01110 fpImmReleaseContext(hwnd, hImc); 01111 goto dwpime_ToIMEWnd_withchk; 01112 } 01113 01114 pwszBuffer = pwsz = (LPWSTR)UserLocalAlloc(HEAP_ZERO_MEMORY, 01115 cbLen + sizeof(WCHAR)); 01116 01117 if (pwszBuffer == NULL) { 01118 fpImmReleaseContext(hwnd, hImc); 01119 goto dwpime_ToIMEWnd_withchk; 01120 } 01121 01122 fpImmGetCompositionStringW(hImc, GCS_RESULTSTR, pwsz, cbLen); 01123 01124 while (*pwsz) 01125 SendMessageW(hwnd, WM_IME_CHAR, MAKEWPARAM(*pwsz++, 0), 1L); 01126 01127 UserLocalFree(pwszBuffer); 01128 01129 fpImmReleaseContext(hwnd, hImc); 01130 } 01131 } 01132 01133 /* 01134 * Fall through to send to Default IME Window with checking 01135 * activated hIMC. 01136 */ 01137 01138 case WM_IME_STARTCOMPOSITION: 01139 case WM_IME_ENDCOMPOSITION: 01140 dwpime_ToIMEWnd_withchk: 01141 //if (TestCF(pwnd, CFIME)) 01142 // break; 01143 01144 if (GetClientInfo()->dwTIFlags & TIF_DISABLEIME) { 01145 break; 01146 } 01147 /* 01148 * We assume this Wnd uses DefaultIMEWindow. 01149 * If this window has its own IME window, it have to call 01150 * ImmIsUIMessage().... 01151 */ 01152 hwndDefIme = fpImmGetDefaultIMEWnd(hwnd); 01153 01154 if (hwndDefIme == hwnd) { 01155 /* 01156 * VC++ 1.51 TLW0NCL.DLL subclass IME class window 01157 * and pass IME messages to DefWindowProc(). 01158 */ 01159 RIPMSG1(RIP_WARNING, 01160 "IME Class window is hooked and IME message [%X] are sent to DefWindowProc", 01161 message); 01162 ImeWndProcWorker(pwnd, message, wParam, lParam, fAnsi); 01163 break; 01164 } 01165 01166 if ((pwndDefIme = ValidateHwndNoRip(hwndDefIme)) != NULL) { 01167 /* 01168 * If hImc of this window is not activated for IME window, 01169 * we don't send WM_IME_NOTIFY. 01170 */ 01171 pimeui = ((PIMEWND)pwndDefIme)->pimeui; 01172 if (pimeui->hIMC == fpImmGetContext(hwnd)) 01173 return SendMessageWorker(pwndDefIme, message, wParam, lParam, fAnsi); 01174 else 01175 RIPMSG1(RIP_WARNING, 01176 "DefWindowProc can not send WM_IME_message [%X] now", 01177 message); 01178 } 01179 break; 01180 01181 dwpime_ToTopLevel_withchk: 01182 //if (TestCF(pwnd, CFIME)) 01183 // break; 01184 01185 /* 01186 * We assume this Wnd uses DefaultIMEWindow. 01187 * If this window has its own IME window, it have to call 01188 * ImmIsUIMessage().... 01189 */ 01190 hwndDefIme = fpImmGetDefaultIMEWnd(hwnd); 01191 01192 if (hwndDefIme == hwnd) { 01193 /* 01194 * VC++ 1.51 TLW0NCL.DLL subclass IME class window 01195 * and pass IME messages to DefWindowProc(). 01196 */ 01197 RIPMSG1(RIP_WARNING, 01198 "IME Class window is hooked and IME message [%X] are sent to DefWindowProc", 01199 message); 01200 ImeWndProcWorker(pwnd, message, wParam, lParam, fAnsi); 01201 break; 01202 } 01203 01204 pwndDefIme = ValidateHwndNoRip(hwndDefIme); 01205 01206 if ((pwndDefIme = ValidateHwndNoRip(hwndDefIme)) != NULL) { 01207 PWND pwndT, pwndParent; 01208 01209 pwndT = pwnd; 01210 01211 while (TestwndChild(pwndT)) { 01212 pwndParent = REBASEPWND(pwndT, spwndParent); 01213 if (GETPTI(pwndParent) != GETPTI(pwnd)) 01214 break; 01215 pwndT = pwndParent; 01216 } 01217 01218 /* 01219 * If hImc of this window is not activated for IME window, 01220 * we don't send WM_IME_NOTIFY. 01221 */ 01222 if (pwndT != pwnd) { 01223 pimeui = ((PIMEWND)pwndDefIme)->pimeui; 01224 if (pimeui->hIMC == fpImmGetContext(hwnd)) 01225 return SendMessageWorker(pwndT, message, wParam, lParam, fAnsi); 01226 else 01227 RIPMSG1(RIP_WARNING, 01228 "DefWindowProc can not send WM_IME_message [%X] now", 01229 message); 01230 } 01231 else { 01232 /* 01233 * Review !! 01234 * If this is the toplevel window, we pass messages to 01235 * the default IME window... 01236 */ 01237 return SendMessageWorker(pwndDefIme, message, wParam, lParam, fAnsi); 01238 } 01239 } 01240 break; 01241 01242 case WM_IME_NOTIFY: 01243 switch (wParam) { 01244 case IMN_OPENSTATUSWINDOW: 01245 case IMN_CLOSESTATUSWINDOW: 01246 #ifndef WKWOK_DEBUG 01247 goto dwpime_ToIMEWnd_withchk; 01248 #endif 01249 goto dwpime_ToTopLevel_withchk; 01250 01251 default: 01252 goto dwpime_ToIMEWnd_withchk; 01253 } 01254 break; 01255 01256 case WM_IME_REQUEST: 01257 switch (wParam) { 01258 case IMR_QUERYCHARPOSITION: 01259 goto dwpime_ToIMEWnd_withchk; 01260 default: 01261 break; 01262 } 01263 break; 01264 01265 case WM_IME_SYSTEM: 01266 if (wParam == IMS_SETACTIVECONTEXT) { 01267 RIPMSG0(RIP_WARNING, "DefWindowProc received unexpected WM_IME_SYSTEM"); 01268 break; 01269 } 01270 01271 /* 01272 * IMS_SETOPENSTATUS is depended on the activated input context. 01273 * It needs to be sent to only the activated system window. 01274 */ 01275 if (wParam == IMS_SETOPENSTATUS) 01276 goto dwpime_ToIMEWnd_withchk; 01277 01278 /* 01279 * Fall through to send to Default IME Window. 01280 */ 01281 01282 case WM_IME_SETCONTEXT: 01283 //if (TestCF(pwnd, CFIME)) 01284 // break; 01285 01286 hwndDefIme = fpImmGetDefaultIMEWnd(hwnd); 01287 01288 if (hwndDefIme == hwnd) { 01289 /* 01290 * VC++ 1.51 TLW0NCL.DLL subclass IME class window 01291 * and pass IME messages to DefWindowProc(). 01292 */ 01293 RIPMSG1(RIP_WARNING, 01294 "IME Class window is hooked and IME message [%X] are sent to DefWindowProc", 01295 message); 01296 ImeWndProcWorker(pwnd, message, wParam, lParam, fAnsi); 01297 break; 01298 } 01299 01300 if ((pwndDefIme = ValidateHwndNoRip(hwndDefIme)) != NULL) 01301 return SendMessageWorker(pwndDefIme, message, wParam, lParam, fAnsi); 01302 01303 break; 01304 01305 case WM_IME_SELECT: 01306 RIPMSG0(RIP_WARNING, "DefWindowProc should not receive WM_IME_SELECT"); 01307 break; 01308 01309 case WM_IME_COMPOSITIONFULL: 01310 //if (TestCF(pwnd, CFIME)) 01311 // break; 01312 01313 if (GETAPPVER() < VER40) { 01314 /* 01315 * This is a temporary solution for win31app. 01316 * FEREVIEW: For M5 this will call WINNLS message mapping logic 01317 * -yutakan 01318 */ 01319 return SendMessageWorker(pwnd, WM_IME_REPORT, 01320 IR_FULLCONVERT, (LPARAM)0L, fAnsi); 01321 } 01322 break; 01323 01324 case WM_CHANGEUISTATE: 01325 { 01326 WORD wAction = LOWORD(wParam); 01327 WORD wFlags = HIWORD(wParam); 01328 BOOL bRealChange = FALSE; 01329 01330 if (wFlags & ~UISF_VALID || wAction > UIS_LASTVALID || 01331 lParam || !TEST_KbdCuesPUSIF) { 01332 return 0; 01333 } 01334 01335 if (wAction == UIS_INITIALIZE) { 01336 if (gpsi->bLastRITWasKeyboard) { 01337 wAction = UIS_CLEAR; 01338 } else { 01339 wAction = UIS_SET; 01340 } 01341 wFlags = UISF_HIDEFOCUS | UISF_HIDEACCEL; 01342 wParam = MAKEWPARAM(wAction, wFlags); 01343 } 01344 01345 UserAssert(wAction == UIS_SET || wAction == UIS_CLEAR); 01346 /* 01347 * If the state is not going to change, there's nothing to do here 01348 */ 01349 if (wFlags & UISF_HIDEFOCUS) { 01350 bRealChange = (!!TestWF(pwnd, WEFPUIFOCUSHIDDEN)) ^ (wAction == UIS_SET); 01351 } 01352 if (wFlags & UISF_HIDEACCEL) { 01353 bRealChange |= (!!TestWF(pwnd, WEFPUIACCELHIDDEN)) ^ (wAction == UIS_SET); 01354 } 01355 01356 if (!bRealChange) { 01357 break; 01358 } 01359 /* 01360 * Children pass this message up 01361 * Top level windows update send down to themselves WM_UPDATEUISTATE. 01362 * WM_UPDATEUISTATE will change the state bits and broadcast down the message 01363 */ 01364 if (TestwndChild(pwnd)) { 01365 01366 return SendMessageWorker(REBASEPWND(pwnd, spwndParent), WM_CHANGEUISTATE, 01367 wParam, lParam, fAnsi); 01368 } else { 01369 return SendMessageWorker(pwnd, WM_UPDATEUISTATE, wParam, lParam, fAnsi); 01370 } 01371 01372 } 01373 break; 01374 01375 case WM_QUERYUISTATE: 01376 return (TestWF(pwnd, WEFPUIFOCUSHIDDEN) ? UISF_HIDEFOCUS : 0) | 01377 (TestWF(pwnd, WEFPUIACCELHIDDEN) ? UISF_HIDEACCEL : 0); 01378 break; 01379 } 01380 01381 return 0; 01382 01383 #if DBG 01384 } // gfTurboDWP 01385 #endif 01386 } 01387 01388 01389 /***************************************************************************\ 01390 * CallWindowProc 01391 * 01392 * Calls pfn with the passed message parameters. If pfn is a server-side 01393 * window proc the server is called to deliver the message to the window. 01394 * Currently we have the following restrictions: 01395 * 01396 * 04-17-91 DarrinM Created. 01397 \***************************************************************************/ 01398 01399 LRESULT WINAPI CallWindowProcAorW( 01400 WNDPROC pfn, 01401 HWND hwnd, 01402 UINT message, 01403 WPARAM wParam, 01404 LPARAM lParam, 01405 BOOL bAnsi) // Denotes if input is Ansi or Unicode 01406 { 01407 PCALLPROCDATA pCPD; 01408 01409 /* 01410 * Raid# 78954: SPY++ 01411 * 01412 * Under FE NT4.0 or NT5.0, the sytem sends WM_GETTEXTLENGTH 01413 * corresponding to WM_xxxGETTEXT to optimize buffer allocation. 01414 * This is really needed to avoid the buffer size inflation. 01415 * For some reasons, Spy++ passes NULL as pfn to CallWindowProc 01416 * 01417 */ 01418 if (pfn == NULL) { 01419 RIPMSG0(RIP_WARNING, "CallWidowProcAorW(): pfn == NULL!"); 01420 return 0L; 01421 } 01422 01423 // OPT!! check an ANSI\UNICODE table rather than fnDWORD 01424 // OPT!! convert WM_CHAR family messages in line 01425 01426 /* 01427 * Check if pfn is really a CallProcData Handle 01428 * if it is and there is no ANSI data then convert the handle 01429 * into an address; otherwise call the server for translation 01430 */ 01431 if (ISCPDTAG(pfn)) { 01432 if (pCPD = HMValidateHandleNoRip((HANDLE)pfn, TYPE_CALLPROC)) { 01433 if ((message >= WM_USER) || !MessageTable[message].bThunkMessage) { 01434 pfn = (WNDPROC)pCPD->pfnClientPrevious; 01435 } else { 01436 return CsSendMessage(hwnd, message, wParam, lParam, (ULONG_PTR)pfn, 01437 FNID_CALLWINDOWPROC, bAnsi); 01438 } 01439 } else { 01440 RIPMSG1(RIP_WARNING, "CallWindowProc tried using a deleted CPD %#p\n", pfn); 01441 return 0; 01442 } 01443 } 01444 01445 return CALLPROC_WOWCHECK(pfn, hwnd, message, wParam, lParam); 01446 } 01447 01448 LRESULT WINAPI CallWindowProcA( 01449 WNDPROC pfn, 01450 HWND hwnd, 01451 UINT message, 01452 WPARAM wParam, 01453 LPARAM lParam) 01454 { 01455 return CallWindowProcAorW(pfn, hwnd, message, wParam, lParam, TRUE); 01456 } 01457 LRESULT WINAPI CallWindowProcW( 01458 WNDPROC pfn, 01459 HWND hwnd, 01460 UINT message, 01461 WPARAM wParam, 01462 LPARAM lParam) 01463 { 01464 return CallWindowProcAorW(pfn, hwnd, message, wParam, lParam, FALSE); 01465 } 01466 01467 /***************************************************************************\ 01468 * MenuWindowProc 01469 * 01470 * Calls the sever-side function xxxMenuWindowProc 01471 * 01472 * 07-27-92 Mikehar Created. 01473 \***************************************************************************/ 01474 01475 LRESULT WINAPI MenuWindowProcW( 01476 HWND hwnd, 01477 HWND hwndMDIClient, 01478 UINT message, 01479 WPARAM wParam, 01480 LPARAM lParam) 01481 { 01482 return CsSendMessage(hwnd, message, wParam, lParam, 01483 (ULONG_PTR)hwndMDIClient, FNID_MENU, FALSE); 01484 } 01485 01486 LRESULT WINAPI MenuWindowProcA( 01487 HWND hwnd, 01488 HWND hwndMDIClient, 01489 UINT message, 01490 WPARAM wParam, 01491 LPARAM lParam) 01492 { 01493 return CsSendMessage(hwnd, message, wParam, lParam, 01494 (ULONG_PTR)hwndMDIClient, FNID_MENU, TRUE); 01495 } 01496 01497 /***************************************************************************\ 01498 * _ClientGetListboxString 01499 * 01500 * This special function exists because LB_GETTEXT and CB_GETLBTEXT don't have 01501 * buffer counts in them anywhere. Because there is no buffer count we have 01502 * no idea how much room to reserved in the shared memory stack for this 01503 * string to be copied into. The solution is to get the string length ahead 01504 * of time, and send the message with this buffer length. Since this buffer 01505 * length isn't a part of the original message, this routine is used for 01506 * just this purpose. 01507 * 01508 * This routine gets called from the server. 01509 * 01510 * 04-13-91 ScottLu Created. 01511 \***************************************************************************/ 01512 01513 DWORD WINAPI _ClientGetListboxString( 01514 PWND pwnd, 01515 UINT msg, 01516 WPARAM wParam, 01517 LPSTR lParam, // May be a unicode or ANSI string 01518 ULONG_PTR xParam, 01519 PROC xpfn) 01520 { 01521 return ((GENERICPROC)xpfn)(pwnd, msg, wParam, (LPARAM)lParam, xParam); 01522 } 01523 01524 /***************************************************************************\ 01525 * DispatchMessageWorker 01526 * 01527 * Handles any messages that can be dealt with wholly on the client and 01528 * passes the rest to the server. 01529 * 01530 * 04-24-92 DarrinM Created. 01531 \***************************************************************************/ 01532 01533 LRESULT DispatchMessageWorker( 01534 MSG *pmsg, 01535 BOOL fAnsi) 01536 { 01537 PWND pwnd; 01538 WPARAM wParamSaved; 01539 LRESULT lRet; 01540 BOOL bDoDbcsMessaging = FALSE; 01541 01542 /* 01543 * Prevent apps from setting hi 16 bits so we can use them internally. 01544 */ 01545 if (pmsg->message & RESERVED_MSG_BITS) { 01546 RIPERR1(ERROR_INVALID_PARAMETER, 01547 RIP_WARNING, 01548 "Invalid parameter \"pmsg->message\" (%ld) to DispatchMessageWorker", 01549 pmsg->message); 01550 01551 return 0; 01552 } 01553 01554 if (pmsg->hwnd != NULL) { 01555 pwnd = ValidateHwnd(pmsg->hwnd); 01556 if (pwnd == NULL) 01557 return 0; 01558 pmsg->hwnd = HWq(pwnd); // get full 32-bit HWND in case this came from WoW 01559 } else { 01560 pwnd = NULL; 01561 } 01562 01563 /* 01564 * If this is a synchronous-only message (takes a pointer in wParam or 01565 * lParam), then don't allow this message to go through since those 01566 * parameters have not been thunked, and are pointing into outer-space 01567 * (which would case exceptions to occur). 01568 * 01569 * (This api is only called in the context of a message loop, and you 01570 * don't get synchronous-only messages in a message loop). 01571 */ 01572 if (TESTSYNCONLYMESSAGE(pmsg->message, pmsg->wParam)) { 01573 /* 01574 * Fail if 32 bit app is calling. 01575 */ 01576 if (!(GetClientInfo()->dwTIFlags & TIF_16BIT)) { 01577 RIPERR0(ERROR_MESSAGE_SYNC_ONLY, RIP_WARNING, "DispatchMessageWorker: must be sync only"); 01578 return FALSE; 01579 } 01580 01581 /* 01582 * For wow apps, allow it to go through (for compatibility). Change 01583 * the message id so our code doesn't understand the message - wow 01584 * will get the message and strip out this bit before dispatching 01585 * the message to the application. 01586 */ 01587 pmsg->message |= MSGFLAG_WOW_RESERVED; 01588 } 01589 01590 /* 01591 * Timer callbacks that don't go through window procs are sent with 01592 * the callback address in lParam. Identify and dispatch those timers. 01593 */ 01594 if ((pmsg->message == WM_TIMER) || (pmsg->message == WM_SYSTIMER)) { 01595 if (pmsg->lParam != 0) { 01596 /* 01597 * System timers must be executed on the server's context. 01598 */ 01599 if (pmsg->message == WM_SYSTIMER) { 01600 return NtUserDispatchMessage(pmsg); 01601 } else { 01602 /* 01603 * We can't really trust what's in lParam, so make sure we 01604 * handle any exceptions that occur during this call. 01605 */ 01606 try { 01607 /* Bug 234292 - joejo 01608 * Since the called window/dialog proc may have a different calling 01609 * convention, we must wrap the call and, check esp and replace with 01610 * a good esp when the call returns. This is what UserCallWinProc* does. 01611 */ 01612 lRet = UserCallWinProc((WNDPROC)pmsg->lParam, pmsg->hwnd, pmsg->message, 01613 pmsg->wParam, NtGetTickCount()); 01614 } except ((GetAppCompatFlags2(VER40) & GACF2_NO_TRYEXCEPT_CALLWNDPROC) ? 01615 EXCEPTION_CONTINUE_SEARCH : W32ExceptionHandler(FALSE, RIP_WARNING)) { 01616 /* #359866 01617 * Some applications like Hagaki Studio 2000 need to handle the exception 01618 * in WndProc in their handler, even though it skips the API calls. 01619 * For those apps, we have to honor the behavior of NT4, with no protection. 01620 */ 01621 lRet = 0; 01622 } 01623 return lRet; 01624 } 01625 } 01626 } 01627 01628 if (pwnd == NULL) 01629 return 0; 01630 01631 /* 01632 * To be safe (in case some bizarre app wants to look at the message 01633 * again after dispatching it) save wParam so it can be restored after 01634 * RtlMBMessageWParamCharToWCS() or RtlWCSMessageToMB() mangle it. 01635 */ 01636 wParamSaved = pmsg->wParam; 01637 01638 /* 01639 * Pass messages intended for server-side windows over to the server. 01640 * WM_PAINTs are passed over so the WFPAINTNOTPROCESSED code can be 01641 * executed. 01642 */ 01643 if (TestWF(pwnd, WFSERVERSIDEPROC) || (pmsg->message == WM_PAINT)) { 01644 if (fAnsi) { 01645 /* 01646 * Setup DBCS Messaging for WM_CHAR... 01647 */ 01648 BUILD_DBCS_MESSAGE_TO_SERVER_FROM_CLIENTA(pmsg->message,pmsg->wParam,TRUE); 01649 01650 /* 01651 * Convert wParam to Unicode, if nessesary. 01652 */ 01653 RtlMBMessageWParamCharToWCS(pmsg->message, &pmsg->wParam); 01654 } 01655 lRet = NtUserDispatchMessage(pmsg); 01656 pmsg->wParam = wParamSaved; 01657 return lRet; 01658 } 01659 01660 /* 01661 * If the dispatcher and the receiver are both ANSI or both UNICODE 01662 * then no message translation is necessary. NOTE: this test 01663 * assumes that fAnsi is FALSE or TRUE, not just zero or non-zero. 01664 */ 01665 if (!fAnsi != !TestWF(pwnd, WFANSIPROC)) { 01666 // before: if (fAnsi != ((TestWF(pwnd, WFANSIPROC)) ? TRUE : FALSE)) { 01667 UserAssert(PtiCurrent() == GETPTI(pwnd)); // use receiver's codepage 01668 if (fAnsi) { 01669 /* 01670 * Setup DBCS Messaging for WM_CHAR... 01671 */ 01672 BUILD_DBCS_MESSAGE_TO_CLIENTW_FROM_CLIENTA(pmsg->message,pmsg->wParam,TRUE); 01673 01674 /* 01675 * Convert wParam to Unicode, if nessesary. 01676 */ 01677 RtlMBMessageWParamCharToWCS(pmsg->message, &pmsg->wParam); 01678 } else { 01679 /* 01680 * Convert wParam to ANSI... 01681 */ 01682 RtlWCSMessageWParamCharToMB(pmsg->message, &pmsg->wParam); 01683 01684 /* 01685 * Let's DBCS messaging for WM_CHAR.... 01686 */ 01687 BUILD_DBCS_MESSAGE_TO_CLIENTA_FROM_CLIENTW( 01688 pmsg->hwnd,pmsg->message,pmsg->wParam,pmsg->lParam, 01689 pmsg->time,pmsg->pt,bDoDbcsMessaging); 01690 } 01691 } 01692 01693 DispatchMessageAgain: 01694 lRet = CALLPROC_WOWCHECKPWW(MapKernelClientFnToClientFn(pwnd->lpfnWndProc), pmsg->hwnd, pmsg->message, 01695 pmsg->wParam, pmsg->lParam, &(pwnd->state)); 01696 01697 /* 01698 * if we have DBCS TrailingByte that should be sent, send it here.. 01699 */ 01700 DISPATCH_DBCS_MESSAGE_IF_EXIST(pmsg->message,pmsg->wParam,bDoDbcsMessaging,DispatchMessage); 01701 01702 pmsg->wParam = wParamSaved; 01703 return lRet; 01704 } 01705 01706 /***************************************************************************\ 01707 * GetMessageTime (API) 01708 * 01709 * This API returns the time when the last message was read from 01710 * the current message queue. 01711 * 01712 * History: 01713 * 11-19-90 DavidPe Created. 01714 \***************************************************************************/ 01715 01716 LONG GetMessageTime(VOID) 01717 { 01718 return (LONG)NtUserGetThreadState(UserThreadStateMessageTime); 01719 } 01720 01721 /***************************************************************************\ 01722 * GetMessageExtraInfo (API) 01723 * 01724 * History: 01725 * 28-May-1991 mikeke 01726 \***************************************************************************/ 01727 01728 LPARAM GetMessageExtraInfo(VOID) 01729 { 01730 return (LPARAM)NtUserGetThreadState(UserThreadStateExtraInfo); 01731 } 01732 01733 LPARAM SetMessageExtraInfo(LPARAM lParam) 01734 { 01735 return (LPARAM)NtUserCallOneParam(lParam, SFI__SETMESSAGEEXTRAINFO); 01736 } 01737 01738 01739 01740 /***********************************************************************\ 01741 * InSendMessage (API) 01742 * 01743 * This function determines if the current thread is preocessing a message 01744 * from another application. 01745 * 01746 * History: 01747 * 01-13-91 DavidPe Ported. 01748 \***********************************************************************/ 01749 01750 BOOL InSendMessage(VOID) 01751 { 01752 PCLIENTTHREADINFO pcti = GetClientInfo()->pClientThreadInfo; 01753 01754 if (pcti) { 01755 return TEST_BOOL_FLAG(pcti->CTIF_flags, CTIF_INSENDMESSAGE); 01756 } 01757 return NtUserGetThreadState(UserThreadStateInSendMessage) != ISMEX_NOSEND; 01758 } 01759 /***********************************************************************\ 01760 * InSendMessageEx (API) 01761 * 01762 * This function tells you what type of send message is being processed 01763 * by the application, if any 01764 * 01765 * History: 01766 * 01/22/97 GerardoB Created 01767 \***********************************************************************/ 01768 01769 DWORD InSendMessageEx(LPVOID lpReserved) 01770 { 01771 PCLIENTTHREADINFO pcti = GetClientInfo()->pClientThreadInfo; 01772 UNREFERENCED_PARAMETER(lpReserved); 01773 01774 if (pcti && !TEST_FLAG(pcti->CTIF_flags, CTIF_INSENDMESSAGE)) { 01775 return ISMEX_NOSEND; 01776 } 01777 return (DWORD)NtUserGetThreadState(UserThreadStateInSendMessage); 01778 } 01779 01780 /***********************************************************************\ 01781 * GetCPD 01782 * 01783 * This function calls the server to allocate a CPD structure. 01784 * 01785 * History: 01786 * 11-15-94 JimA Created. 01787 \***********************************************************************/ 01788 01789 ULONG_PTR GetCPD( 01790 PVOID pWndOrCls, 01791 DWORD options, 01792 ULONG_PTR dwData) 01793 { 01794 return NtUserGetCPD(HW(pWndOrCls), options, dwData); 01795 } 01796 01797 #ifdef BUILD_WOW6432 01798 /***********************************************************************\ 01799 * MapKernelClientFnToClientFn 01800 * 01801 * Maps a function pointer from what the kernel expects to what the 01802 * client(user-mode) expects. 01803 * 01804 * History: 01805 * 11-15-98 PeterHal Created. 01806 \***********************************************************************/ 01807 WNDPROC_PWND 01808 MapKernelClientFnToClientFn( 01809 WNDPROC_PWND lpfnWndProc 01810 ) 01811 { 01812 KERNEL_ULONG_PTR *pp; 01813 01814 for (pp = (KERNEL_ULONG_PTR*)&gpsi->apfnClientA; pp < (KERNEL_ULONG_PTR*) (&gpsi->apfnClientA+1); pp ++) { 01815 if ((KERNEL_ULONG_PTR)lpfnWndProc == *pp) { 01816 return (WNDPROC_PWND)((KERNEL_ULONG_PTR*) &pfnClientA) [ (pp - (KERNEL_ULONG_PTR*)&gpsi->apfnClientA) ]; 01817 } 01818 } 01819 01820 for (pp = (KERNEL_ULONG_PTR*)&gpsi->apfnClientW; pp < (KERNEL_ULONG_PTR*) (&gpsi->apfnClientW+1); pp ++) { 01821 if ((KERNEL_ULONG_PTR)lpfnWndProc == *pp) { 01822 return (WNDPROC_PWND)((KERNEL_ULONG_PTR*) &pfnClientW) [ (pp - (KERNEL_ULONG_PTR*)&gpsi->apfnClientW) ]; 01823 } 01824 } 01825 01826 return lpfnWndProc; 01827 } 01828 #endif

Generated on Sat May 15 19:39:25 2004 for test by doxygen 1.3.7