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

hotkeys.c

Go to the documentation of this file.
00001 /****************************** Module Header ******************************\ 00002 * Module Name: hotkeys.c 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * This module contains the core functions of hotkey processing. 00007 * 00008 * History: 00009 * 12-04-90 DavidPe Created. 00010 * 02-12-91 JimA Added access checks 00011 * 13-Feb-1991 mikeke Added Revalidation code (None) 00012 \***************************************************************************/ 00013 00014 #include "precomp.h" 00015 #pragma hdrstop 00016 00017 /***************************************************************************\ 00018 * InitSystemHotKeys 00019 * 00020 * Called from InitWindows(), this routine registers the default system 00021 * hotkeys. 00022 * 00023 * History: 00024 * 12-04-90 DavidPe Created. 00025 \***************************************************************************/ 00026 VOID SetDebugHotKeys() 00027 { 00028 UINT VkDebug; 00029 00030 VkDebug = FastGetProfileDwordW(NULL, PMAP_AEDEBUG, L"UserDebuggerHotkey", 0); 00031 if (VkDebug == 0) { 00032 if (ENHANCED_KEYBOARD(gKeyboardInfo.KeyboardIdentifier)) { 00033 VkDebug = VK_F12; 00034 } else { 00035 VkDebug = VK_SUBTRACT; 00036 } 00037 } else { 00038 UserAssert((0xFFFFFF00 & VkDebug) == 0); 00039 } 00040 00041 _UnregisterHotKey(PWND_INPUTOWNER, IDHOT_DEBUG); 00042 _UnregisterHotKey(PWND_INPUTOWNER, IDHOT_DEBUGSERVER); 00043 00044 _RegisterHotKey(PWND_INPUTOWNER, IDHOT_DEBUG, 0, VkDebug); 00045 _RegisterHotKey(PWND_INPUTOWNER, IDHOT_DEBUGSERVER, MOD_SHIFT, VkDebug); 00046 } 00047 00048 00049 /***************************************************************************\ 00050 * DestroyThreadsHotKeys 00051 * 00052 * History: 00053 * 26-Feb-1991 mikeke Created. 00054 \***************************************************************************/ 00055 00056 VOID DestroyThreadsHotKeys() 00057 { 00058 PHOTKEY *pphk; 00059 PHOTKEY phk; 00060 PTHREADINFO ptiCurrent = PtiCurrent(); 00061 pphk = &gphkFirst; 00062 while (*pphk) { 00063 if ((*pphk)->pti == ptiCurrent) { 00064 phk = *pphk; 00065 *pphk = (*pphk)->phkNext; 00066 00067 /* 00068 * Unlock the object stored here. 00069 */ 00070 if ((phk->spwnd != PWND_FOCUS) && (phk->spwnd != PWND_INPUTOWNER)) { 00071 Unlock(&phk->spwnd); 00072 } 00073 00074 UserFreePool(phk); 00075 } else { 00076 pphk = &((*pphk)->phkNext); 00077 } 00078 } 00079 } 00080 00081 00082 /***************************************************************************\ 00083 * DestroyWindowsHotKeys 00084 * 00085 * Called from xxxFreeWindow. 00086 * Hotkeys not unregistered properly by the app must be destroyed when the 00087 * window is destroyed. Keeps things clean (problems with bad apps #5553) 00088 * 00089 * History: 00090 * 23-Sep-1992 IanJa Created. 00091 \***************************************************************************/ 00092 00093 VOID DestroyWindowsHotKeys( 00094 PWND pwnd) 00095 { 00096 PHOTKEY *pphk; 00097 PHOTKEY phk; 00098 pphk = &gphkFirst; 00099 while (*pphk) { 00100 if ((*pphk)->spwnd == pwnd) { 00101 phk = *pphk; 00102 *pphk = (*pphk)->phkNext; 00103 00104 Unlock(&phk->spwnd); 00105 UserFreePool(phk); 00106 } else { 00107 pphk = &((*pphk)->phkNext); 00108 } 00109 } 00110 } 00111 00112 00113 /***************************************************************************\ 00114 * _RegisterHotKey (API) 00115 * 00116 * This API registers the hotkey specified. If the specified key sequence 00117 * has already been registered we return FALSE. If the specified hwnd 00118 * and id have already been registered, fsModifiers and vk are reset for 00119 * the HOTKEY structure. 00120 * 00121 * History: 00122 * 12-04-90 DavidPe Created. 00123 * 02-12-91 JimA Added access check 00124 \***************************************************************************/ 00125 BOOL _RegisterHotKey( 00126 PWND pwnd, 00127 int id, 00128 UINT fsModifiers, 00129 UINT vk) 00130 { 00131 PHOTKEY phk; 00132 BOOL fKeysExist; 00133 PTHREADINFO ptiCurrent; 00134 BOOL bSAS = FALSE; 00135 WORD wFlags; 00136 00137 wFlags = fsModifiers & MOD_SAS; 00138 fsModifiers &= ~MOD_SAS; 00139 00140 ptiCurrent = PtiCurrent(); 00141 00142 /* 00143 * Blow it off if the caller is not the windowstation init thread 00144 * and doesn't have the proper access rights 00145 */ 00146 if (PsGetCurrentProcess() != gpepCSRSS) { 00147 if (grpWinStaList && !CheckWinstaWriteAttributesAccess()) { 00148 return FALSE; 00149 } 00150 } 00151 00152 /* 00153 * If VK_PACKET is specified, just bail out, since VK_PACKET is 00154 * not a real keyboard input. 00155 */ 00156 if (vk == VK_PACKET) { 00157 return FALSE; 00158 } 00159 00160 /* 00161 * If this is the SAS check that winlogon is the one registering it. 00162 */ 00163 if (wFlags & MOD_SAS) { 00164 if (PsGetCurrentProcess()->UniqueProcessId == gpidLogon) { 00165 bSAS = TRUE; 00166 } 00167 } 00168 00169 /* 00170 * Can't register hotkey for a window of another queue. 00171 * Return FALSE in this case. 00172 */ 00173 if ((pwnd != PWND_FOCUS) && (pwnd != PWND_INPUTOWNER)) { 00174 if (GETPTI(pwnd) != ptiCurrent) { 00175 RIPERR0(ERROR_WINDOW_OF_OTHER_THREAD, RIP_VERBOSE, ""); 00176 return FALSE; 00177 } 00178 } 00179 00180 phk = FindHotKey(ptiCurrent, pwnd, id, fsModifiers, vk, FALSE, &fKeysExist); 00181 00182 /* 00183 * If the keys have already been registered, return FALSE. 00184 */ 00185 if (fKeysExist) { 00186 RIPERR0(ERROR_HOTKEY_ALREADY_REGISTERED, RIP_WARNING, "Hotkey already exists"); 00187 return FALSE; 00188 } 00189 00190 if (phk == NULL) { 00191 /* 00192 * This hotkey doesn't exist yet. 00193 */ 00194 phk = (PHOTKEY)UserAllocPool(sizeof(HOTKEY), TAG_HOTKEY); 00195 00196 /* 00197 * If the allocation failed, bail out. 00198 */ 00199 if (phk == NULL) { 00200 return FALSE; 00201 } 00202 00203 phk->pti = ptiCurrent; 00204 00205 if ((pwnd != PWND_FOCUS) && (pwnd != PWND_INPUTOWNER)) { 00206 phk->spwnd = NULL; 00207 Lock(&phk->spwnd, pwnd); 00208 } else { 00209 phk->spwnd = pwnd; 00210 } 00211 phk->fsModifiers = (WORD)fsModifiers; 00212 phk->wFlags = wFlags; 00213 00214 phk->vk = vk; 00215 phk->id = id; 00216 00217 /* 00218 * Link the new hotkey to the front of the list. 00219 */ 00220 phk->phkNext = gphkFirst; 00221 gphkFirst = phk; 00222 00223 } else { 00224 00225 /* 00226 * Hotkey already exists, reset the keys. 00227 */ 00228 phk->fsModifiers = (WORD)fsModifiers; 00229 phk->wFlags = wFlags; 00230 phk->vk = vk; 00231 } 00232 00233 if (bSAS) { 00234 /* 00235 * store the SAS on the terminal. 00236 */ 00237 gvkSAS = vk; 00238 gfsSASModifiers = fsModifiers; 00239 } 00240 00241 return TRUE; 00242 } 00243 00244 00245 /***************************************************************************\ 00246 * _UnregisterHotKey (API) 00247 * 00248 * This API will 'unregister' the specified hwnd/id hotkey so that the 00249 * WM_HOTKEY message will not be generated for it. 00250 * 00251 * History: 00252 * 12-04-90 DavidPe Created. 00253 \***************************************************************************/ 00254 00255 BOOL _UnregisterHotKey( 00256 PWND pwnd, 00257 int id) 00258 { 00259 PHOTKEY phk; 00260 BOOL fKeysExist; 00261 PTHREADINFO ptiCurrent = PtiCurrent(); 00262 phk = FindHotKey(ptiCurrent, pwnd, id, 0, 0, TRUE, &fKeysExist); 00263 00264 /* 00265 * No hotkey to unregister, return FALSE. 00266 */ 00267 if (phk == NULL) { 00268 RIPERR0(ERROR_HOTKEY_NOT_REGISTERED, RIP_VERBOSE, ""); 00269 return FALSE; 00270 } 00271 00272 return TRUE; 00273 } 00274 00275 00276 /***************************************************************************\ 00277 * FindHotKey 00278 * 00279 * Both RegisterHotKey() and UnregisterHotKey() call this function to search 00280 * for hotkeys that already exist. If a HOTKEY is found that matches 00281 * fsModifiers and vk, *pfKeysExist is set to TRUE. If a HOTKEY is found that 00282 * matches pwnd and id, a pointer to it is returned. 00283 * 00284 * If fUnregister is TRUE, we remove the HOTKEY from the list if we find 00285 * one that matches pwnd and id and return (PHOTKEY)1. 00286 * 00287 * History: 00288 * 12-04-90 DavidPe Created. 00289 \***************************************************************************/ 00290 PHOTKEY FindHotKey( 00291 PTHREADINFO ptiCurrent, 00292 PWND pwnd, 00293 int id, 00294 UINT fsModifiers, 00295 UINT vk, 00296 BOOL fUnregister, 00297 PBOOL pfKeysExist) 00298 { 00299 PHOTKEY phk, phkRet, phkPrev; 00300 00301 /* 00302 * Initialize out 'return' values. 00303 */ 00304 *pfKeysExist = FALSE; 00305 phkRet = NULL; 00306 00307 phk = gphkFirst; 00308 00309 while (phk) { 00310 00311 /* 00312 * If all this matches up then we've found it. 00313 */ 00314 if ((phk->pti == ptiCurrent) && (phk->spwnd == pwnd) && (phk->id == id)) { 00315 if (fUnregister) { 00316 00317 /* 00318 * Unlink the HOTKEY from the list. 00319 */ 00320 if (phk == gphkFirst) { 00321 gphkFirst = phk->phkNext; 00322 } else { 00323 phkPrev->phkNext = phk->phkNext; 00324 } 00325 00326 if ((pwnd != PWND_FOCUS) && (pwnd != PWND_INPUTOWNER)) { 00327 Unlock(&phk->spwnd); 00328 } 00329 UserFreePool((PVOID)phk); 00330 00331 return((PHOTKEY)1); 00332 } 00333 phkRet = phk; 00334 } 00335 00336 /* 00337 * If the key is already registered, set the exists flag so 00338 * the app knows it can't use this hotkey sequence. 00339 */ 00340 if ((phk->fsModifiers == (WORD)fsModifiers) && (phk->vk == vk)) { 00341 00342 /* 00343 * In the case of PWND_FOCUS, we need to check that the queues 00344 * are the same since PWND_FOCUS is local to the queue it was 00345 * registered under. 00346 */ 00347 if (phk->spwnd == PWND_FOCUS) { 00348 if (phk->pti == ptiCurrent) { 00349 *pfKeysExist = TRUE; 00350 } 00351 } else { 00352 *pfKeysExist = TRUE; 00353 } 00354 } 00355 00356 phkPrev = phk; 00357 phk = phk->phkNext; 00358 } 00359 00360 return phkRet; 00361 } 00362 00363 00364 /***************************************************************************\ 00365 * IsSAS 00366 * 00367 * Checks the physical state of keyboard modifiers that would effect SAS 00368 * 00369 * 00370 \***************************************************************************/ 00371 00372 BOOL IsSAS( 00373 BYTE vk, 00374 UINT* pfsModifiers) 00375 { 00376 UINT fsDown = 0; 00377 00378 CheckCritIn(); 00379 00380 if (gvkSAS != vk) { 00381 return FALSE; 00382 } 00383 00384 /* 00385 * Special case for SAS - examine real physical modifier-key state! 00386 * 00387 * An evil daemon process can fool convincingly pretend to be winlogon 00388 * by registering Alt+Del as a hotkey, and spinning another thread that 00389 * continually calls keybd_event() to send the Ctrl key up: when the 00390 * user types Ctrl+Alt+Del, only Alt+Del will be seen by the system, 00391 * the evil daemon will get woken by WM_HOTKEY and can pretend to be 00392 * winlogon. So look at gfsSASModifiersDown in this case, to see what keys 00393 * were physically pressed. 00394 * NOTE: If hotkeys are ever made to work under journal playback, make 00395 * sure they don't affect the gfsSASModifiersDown! - IanJa. 00396 */ 00397 if (gfsSASModifiersDown == gfsSASModifiers) { 00398 *pfsModifiers = gfsSASModifiersDown; 00399 return TRUE; 00400 } 00401 00402 return FALSE; 00403 } 00404 00405 00406 /***************************************************************************\ 00407 * xxxDoHotKeyStuff 00408 * 00409 * This function gets called for every key event from low-level input 00410 * processing. It keeps track of the current state of modifier keys 00411 * and when fsModifiers and vk match up with one of the registered 00412 * hotkeys, a WM_HOTKEY message is generated. DoHotKeyStuff() will 00413 * tell the input system to eat both the make and break for the 'vk' 00414 * event. This prevents apps from getting input that wasn't really 00415 * intended for them. DoHotKeyStuff() returns TRUE if it wants to 'eat' 00416 * the event, FALSE if the system can pass on the event like it normally 00417 * would. 00418 * 00419 * A Note on Modifier-Only Hotkeys 00420 * Some hotkeys involve VK_SHIFT, VK_CONTROL, VK_MENU and/or VK_WINDOWS only. 00421 * These are called Modifier-Only hotkeys. 00422 * In order to distinguish hotkeys such as Alt-Shift-S and and Alt-Shift alone, 00423 * modifier-only hotkeys must operate on a break, not a make. 00424 * In order to prevent Alt-Shift-S from activating the Alt-Shift hotkey when 00425 * the keys are released, modifier-only hotkeys are only activated when a 00426 * modifier keyup (break) was immediately preceded by a modifier keydown (break) 00427 * This also lets Alt-Shift,Shift,Shift activate the Alt-Shift hotkey 3 times. 00428 * 00429 * History: 00430 * 12-05-90 DavidPe Created. 00431 * 4-15-93 Sanfords Added code to return TRUE for Ctrl-Alt-Del events. 00432 \***************************************************************************/ 00433 00434 BOOL xxxDoHotKeyStuff( 00435 UINT vk, 00436 BOOL fBreak, 00437 DWORD fsReserveKeys) 00438 { 00439 static UINT fsModifiers = 0; 00440 static UINT fsModOnlyCandidate = 0; 00441 UINT fsModOnlyHotkey; 00442 UINT fs; 00443 PHOTKEY phk; 00444 BOOL fCancel; 00445 BOOL fEatDebugKeyBreak = FALSE; 00446 PWND pwnd; 00447 BOOL bSAS; 00448 00449 CheckCritIn(); 00450 UserAssert(IsWinEventNotifyDeferredOK()); 00451 00452 if (gfInNumpadHexInput & NUMPAD_HEXMODE_LL) { 00453 RIPMSG0(RIP_VERBOSE, "xxxDoHotKeyStuff: Since we're in gfInNumpadHexInput, just bail out."); 00454 return FALSE; 00455 } 00456 00457 /* 00458 * Update fsModifiers. 00459 */ 00460 fs = 0; 00461 fsModOnlyHotkey = 0; 00462 00463 switch (vk) { 00464 case VK_SHIFT: 00465 fs = MOD_SHIFT; 00466 break; 00467 00468 case VK_CONTROL: 00469 fs = MOD_CONTROL; 00470 break; 00471 00472 case VK_MENU: 00473 fs = MOD_ALT; 00474 break; 00475 00476 case VK_LWIN: 00477 case VK_RWIN: 00478 fs = MOD_WIN; 00479 break; 00480 00481 default: 00482 /* 00483 * A non-modifier key rules out Modifier-Only hotkeys 00484 */ 00485 fsModOnlyCandidate = 0; 00486 break; 00487 } 00488 00489 if (fBreak) { 00490 fsModifiers &= ~fs; 00491 /* 00492 * If a modifier key is coming up, the current modifier only hotkey 00493 * candidate must be tested to see if it is a hotkey. Store this 00494 * in fsModOnlyHotkey, and prevent the next key release from 00495 * being a candidate by clearing fsModOnlyCandidate. 00496 */ 00497 if (fs != 0) { 00498 fsModOnlyHotkey = fsModOnlyCandidate; 00499 fsModOnlyCandidate = 0; 00500 } 00501 } else { 00502 fsModifiers |= fs; 00503 /* 00504 * If a modifier key is going down, we have a modifier-only hotkey 00505 * candidate. Save current modifier state until the following break. 00506 */ 00507 if (fs != 0) { 00508 fsModOnlyCandidate = fsModifiers; 00509 } 00510 } 00511 00512 /* 00513 * We look at the physical state for the modifiers because they can not be 00514 * manipulated and this prevents someone from writing a trojan winlogon look alike. 00515 * (See comment in AreModifiersIndicatingSAS) 00516 */ 00517 bSAS = IsSAS((BYTE)vk, &fsModifiers); 00518 00519 /* 00520 * If the key is not a hotkey then we're done but first check if the 00521 * key is an Alt-Escape if so we need to cancel journalling. 00522 * 00523 * NOTE: Support for Alt+Esc to cancel journalling dropped in NT 4.0 00524 */ 00525 if (fsModOnlyHotkey && fBreak) { 00526 /* 00527 * A hotkey involving only VK_SHIFT, VK_CONTROL, VK_MENU or VK_WINDOWS 00528 * must only operate on a key release. 00529 */ 00530 if ((phk = IsHotKey(fsModOnlyHotkey, VK_NONE)) == NULL) { 00531 return FALSE; 00532 } 00533 } else if ((phk = IsHotKey(fsModifiers, vk)) == NULL) { 00534 return FALSE; 00535 } 00536 00537 /* 00538 * If we tripped a SAS hotkey, but it's not really the SAS, don't do it. 00539 */ 00540 if ((phk->wFlags & MOD_SAS) && !bSAS) { 00541 return FALSE; 00542 00543 } 00544 if (phk->id == IDHOT_WINDOWS) { 00545 pwnd = GETDESKINFO(PtiCurrent())->spwndShell; 00546 if (pwnd != NULL) { 00547 fsModOnlyCandidate = 0; /* Make it return TRUE */ 00548 goto PostTaskListSysCmd; 00549 } 00550 } 00551 00552 if ((phk->id == IDHOT_DEBUG) || (phk->id == IDHOT_DEBUGSERVER)) { 00553 00554 if (!fBreak) { 00555 /* 00556 * The DEBUG key has been pressed. Break the appropriate 00557 * thread into the debugger. Won't need phk after this callback 00558 * because we return immediately. 00559 */ 00560 fEatDebugKeyBreak = xxxActivateDebugger(phk->fsModifiers); 00561 } 00562 00563 /* 00564 * This'll eat the debug key down and break if we broke into 00565 * the debugger on the server only on the down. 00566 */ 00567 return fEatDebugKeyBreak; 00568 } 00569 00570 /* 00571 * don't allow hotkeys(except for ones owned by the logon process) 00572 * if the window station is locked. 00573 */ 00574 00575 if (((grpdeskRitInput->rpwinstaParent->dwWSF_Flags & WSF_SWITCHLOCK) != 0) && 00576 (phk->pti->pEThread->Cid.UniqueProcess != gpidLogon)) { 00577 RIPMSG0(RIP_WARNING, "Ignoring hotkey because Workstation locked"); 00578 return FALSE; 00579 } 00580 00581 if ((fsModOnlyHotkey == 0) && fBreak) { 00582 /* 00583 * Do Modifier-Only hotkeys on break events, else return here. 00584 */ 00585 return FALSE; 00586 } 00587 00588 /* 00589 * Unhook hooks if a control-escape, alt-escape, or control-alt-del 00590 * comes through, so the user can cancel if the system seems hung. 00591 * 00592 * Note the hook may be locked so even if the unhook succeeds it 00593 * won't remove the hook from the global asphkStart array. So 00594 * we have to walk the list manually. This code works because 00595 * we are in the critical section and we know other hooks won't 00596 * be deleted. 00597 * 00598 * Once we've unhooked, post a WM_CANCELJOURNAL message to the app 00599 * that set the hook so it knows we did this. 00600 * 00601 * NOTE: Support for Alt+Esc to cancel journalling dropped in NT 4.0 00602 */ 00603 fCancel = FALSE; 00604 if (vk == VK_ESCAPE && (fsModifiers == MOD_CONTROL)) { 00605 fCancel = TRUE; 00606 } 00607 00608 if (bSAS) { 00609 fCancel = TRUE; 00610 } 00611 00612 if (fCancel) 00613 zzzCancelJournalling(); // BUG BUG phk might go away IANJA 00614 00615 /* 00616 * See if the key is reserved by a console window. If it is, 00617 * return FALSE so the key will be passed to the console. 00618 */ 00619 if (fsReserveKeys != 0) { 00620 switch (vk) { 00621 case VK_TAB: 00622 if ((fsReserveKeys & CONSOLE_ALTTAB) && 00623 ((fsModifiers & (MOD_CONTROL | MOD_ALT)) == MOD_ALT)) { 00624 return FALSE; 00625 } 00626 break; 00627 case VK_ESCAPE: 00628 if ((fsReserveKeys & CONSOLE_ALTESC) && 00629 ((fsModifiers & (MOD_CONTROL | MOD_ALT)) == MOD_ALT)) { 00630 return FALSE; 00631 } 00632 if ((fsReserveKeys & CONSOLE_CTRLESC) && 00633 ((fsModifiers & (MOD_CONTROL | MOD_ALT)) == MOD_CONTROL)) { 00634 return FALSE; 00635 } 00636 break; 00637 case VK_RETURN: 00638 if ((fsReserveKeys & CONSOLE_ALTENTER) && 00639 ((fsModifiers & (MOD_CONTROL | MOD_ALT)) == MOD_ALT)) { 00640 return FALSE; 00641 } 00642 break; 00643 case VK_SNAPSHOT: 00644 if ((fsReserveKeys & CONSOLE_PRTSC) && 00645 ((fsModifiers & (MOD_CONTROL | MOD_ALT)) == 0)) { 00646 return FALSE; 00647 } 00648 if ((fsReserveKeys & CONSOLE_ALTPRTSC) && 00649 ((fsModifiers & (MOD_CONTROL | MOD_ALT)) == MOD_ALT)) { 00650 return FALSE; 00651 } 00652 break; 00653 case VK_SPACE: 00654 if ((fsReserveKeys & CONSOLE_ALTSPACE) && 00655 ((fsModifiers & (MOD_CONTROL | MOD_ALT)) == MOD_ALT)) { 00656 return FALSE; 00657 } 00658 break; 00659 } 00660 } 00661 00662 /* 00663 * If this is the task-list hotkey, go ahead and set foreground 00664 * status to the task-list queue right now. This prevents problems 00665 * where the user hits ctrl-esc and types-ahead before the task-list 00666 * processes the hotkey and brings up the task-list window. 00667 */ 00668 if ((fsModifiers == MOD_CONTROL) && (vk == VK_ESCAPE) && !fBreak) { 00669 PWND pwndSwitch; 00670 TL tlpwndSwitch; 00671 00672 if (ghwndSwitch != NULL) { 00673 pwndSwitch = PW(ghwndSwitch); 00674 ThreadLock(pwndSwitch, &tlpwndSwitch); 00675 xxxSetForegroundWindow2(pwndSwitch, NULL, 0); // BUG BUG phk might go away IANJA 00676 ThreadUnlock(&tlpwndSwitch); 00677 } 00678 } 00679 00680 /* 00681 * Get the hot key contents. 00682 */ 00683 if (phk->spwnd == NULL) { 00684 _PostThreadMessage( 00685 phk->pti, WM_HOTKEY, phk->id, 00686 MAKELONG(fsModifiers, vk)); 00687 /* 00688 * Since this hotkey is for this guy, he owns the last input. 00689 */ 00690 glinp.ptiLastWoken = phk->pti; 00691 00692 } else { 00693 if (phk->spwnd == PWND_INPUTOWNER) { 00694 if (gpqForeground != NULL) { 00695 pwnd = gpqForeground->spwndFocus; 00696 } else { 00697 return FALSE; 00698 } 00699 } else { 00700 pwnd = phk->spwnd; 00701 } 00702 00703 if (pwnd) { 00704 if (pwnd == pwnd->head.rpdesk->pDeskInfo->spwndShell && phk->id == SC_TASKLIST) { 00705 PostTaskListSysCmd: 00706 _PostMessage(pwnd, WM_SYSCOMMAND, SC_TASKLIST, 0); 00707 } else { 00708 _PostMessage(pwnd, WM_HOTKEY, phk->id, MAKELONG(fsModifiers, vk)); 00709 } 00710 00711 /* 00712 * Since this hotkey is for this guy, he owns the last input. 00713 */ 00714 glinp.ptiLastWoken = GETPTI(pwnd); 00715 } 00716 } 00717 00718 /* 00719 * If this is a Modifier-Only hotkey, let the modifier break through 00720 * by returning FALSE, otherwise we will have modifier keys stuck down. 00721 */ 00722 return (fsModOnlyHotkey == 0); 00723 00724 } 00725 00726 00727 /***************************************************************************\ 00728 * IsHotKey 00729 * 00730 * 00731 * History: 00732 * 03-10-91 DavidPe Created. 00733 \***************************************************************************/ 00734 00735 PHOTKEY IsHotKey( 00736 UINT fsModifiers, 00737 UINT vk) 00738 { 00739 PHOTKEY phk; 00740 00741 CheckCritIn(); 00742 00743 phk = gphkFirst; 00744 00745 while (phk != NULL) { 00746 00747 /* 00748 * Do the modifiers and vk for this hotkey match the current state? 00749 */ 00750 if ((phk->fsModifiers == fsModifiers) && (phk->vk == vk)) { 00751 return phk; 00752 } 00753 00754 phk = phk->phkNext; 00755 } 00756 00757 return NULL; 00758 }

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