BOOL NotifyLogon( PWINDOWSTATION pwinsta, PLUID pluidCaller, DWORD dwFlags) { BOOL fNotified = FALSE; PWND pwndWinlogon; if (dwFlags & EWX_SHUTDOWN) { for (pwinsta = grpwinstaList; pwinsta != NULL; pwinsta = pwinsta->rpwinstaNext) { pwndWinlogon = pwinsta->spwndLogonNotify; if (pwndWinlogon != NULL) { _PostMessage(pwndWinlogon, WM_LOGONNOTIFY, LOGON_LOGOFF, (LONG)dwFlags); fNotified = TRUE; } } } else { LUID luidSystem = SYSTEM_LUID; pwndWinlogon = pwinsta->spwndLogonNotify; if (pwndWinlogon != NULL && (RtlEqualLuid(&pwinsta->luidUser, pluidCaller) || RtlEqualLuid(&luidSystem, pluidCaller))) { _PostMessage(pwndWinlogon, WM_LOGONNOTIFY, LOGON_LOGOFF, (LONG)dwFlags); fNotified = TRUE; } } return fNotified; }
/***************************************************************************\ * xxxCancelMouseMoveTracking * * History * 12/07/96 GerardoB Created \***************************************************************************/ void xxxCancelMouseMoveTracking (DWORD dwDTFlags, PWND pwndTrack, int htEx, DWORD dwDTCancel) { CheckLock(pwndTrack); /* * Hottracking */ if ((dwDTFlags & DF_HOTTRACKING) && (dwDTCancel & DF_HOTTRACKING)) { /* * The current state must be owned by the current queue. * Otherwise, we're about to do an inter-queue cancelation. */ UserAssert(PtiCurrent()->pq == GETPTI(pwndTrack)->pq); xxxHotTrack(pwndTrack, htEx, FALSE); } /* * Tooltips */ if ((dwDTFlags & DF_TOOLTIPSHOWING) && (dwDTCancel & DF_TOOLTIP)) { PTOOLTIPWND pttwnd = (PTOOLTIPWND)PWNDTOOLTIP(pwndTrack); TL tlpwnd; ThreadLockAlways(pttwnd, &tlpwnd); xxxResetTooltip(pttwnd); ThreadUnlock(&tlpwnd); } /* * Mouse Leave */ if ((dwDTFlags & DF_TRACKMOUSELEAVE) && (dwDTCancel & DF_TRACKMOUSELEAVE)) { _PostMessage(pwndTrack, ((htEx == HTCLIENT) ? WM_MOUSELEAVE : WM_NCMOUSELEAVE), 0, 0); } /* * Mouse Hover */ if ((dwDTFlags & DF_TRACKMOUSEHOVER) && (dwDTCancel & DF_TRACKMOUSEHOVER)) { _KillSystemTimer(pwndTrack, IDSYS_MOUSEHOVER); } }
BOOL _TranslateMessage( LPMSG pmsg, UINT flags) { PTHREADINFO pti; UINT wMsgType; WORD *pwParam; int cChar; BOOL fSysKey = FALSE; BOOL bBreak; LPARAM lParam; switch (pmsg->message) { default: return FALSE; case WM_SYSKEYDOWN: /* * HACK carried over from Win3 code: system messages * only get posted during KEYDOWN processing - so * set fSysKey only for WM_SYSKEYDOWN. */ fSysKey = TRUE; /* * Fall thru... */ case WM_SYSKEYUP: case WM_KEYDOWN: case WM_KEYUP: pti = PtiCurrent(); if ((pti->pMenuState != NULL) && (HW(pti->pMenuState->pGlobalPopupMenu->spwndPopupMenu) == pmsg->hwnd)) { flags |= 1; } else { flags &= ~1; } /* * Don't change the contents of the passed in structure. */ lParam = pmsg->lParam; cChar = InternalToUnicode(LOWORD(pmsg->wParam), // virtual key code HIWORD(lParam), // scan code, make/break bit pti->pq->afKeyState, pState, 16, // see init.c flags, &bBreak); /* * LATER 12/7/90 - GregoryW * Note: Win3.x TranslateMessage returns TRUE if ToAscii is called. * Proper behavior is to return TRUE if any translation is * performed by ToAscii. If we have to remain compatible * (even though apps clearly don't currently care about the * return value) then the following return should be changed * to TRUE. If we want the new 32-bit apps to have a meaningful * return value we should leave this as FALSE. * * If console is calling us with the TM_POSTCHARBREAKS flag then we * return FALSE if no char was actually posted * * !!! LATER get console to change so it does not need private API * TranslateMessageEx */ if (!cChar) { if (flags & TM_POSTCHARBREAKS) return FALSE; else return TRUE; } /* * Some translation performed. Figure out what type of * message to post. * */ if (cChar > 0) wMsgType = (fSysKey) ? (UINT)WM_SYSCHAR : (UINT)WM_CHAR; else { wMsgType = (fSysKey) ? (UINT)WM_SYSDEADCHAR : (UINT)WM_DEADCHAR; cChar = -cChar; // want positive value } if (bBreak) { lParam |= 0x80000000; } else { lParam &= ~0x80000000; } pwParam = (WORD *)pState; for ( ; cChar > 0; cChar--) { /* * If this is a multi-character posting, all but the last one * should be marked as fake keystrokes for Console/VDM. */ _PostMessage(PW(pmsg->hwnd), wMsgType, (DWORD)*pwParam, lParam | (cChar > 1 ? FAKE_KEYSTROKE : 0)); *pwParam = 0; // zero out old character pwParam += 1; } return TRUE; } }
BOOL xxxDoHotKeyStuff( UINT vk, BOOL fBreak, DWORD fsReserveKeys) { #ifdef WINDOWS_NOT_HOT static BOOL fOnlyWinKey = FALSE; #endif static UINT fsModifiers = 0; static UINT fsModOnlyCandidate = 0; UINT fsModOnlyHotkey; UINT fs; PHOTKEY phk; PWND pwnd; BOOL fCancel; BOOL fEatDebugKeyBreak = FALSE; CheckCritIn(); /* * Update fsModifiers. */ fs = 0; fsModOnlyHotkey = 0; switch (vk) { case VK_RSHIFT: fs = MOD_RSHIFT; case VK_LSHIFT: case VK_SHIFT: vk = VK_SHIFT; fs |= MOD_SHIFT; break; case VK_RCONTROL: fs = MOD_RCONTROL; case VK_LCONTROL: vk = VK_CONTROL; case VK_CONTROL: fs |= MOD_CONTROL; break; case VK_RMENU: fs = MOD_RALT; case VK_LMENU: vk = VK_MENU; case VK_MENU: fs |= MOD_ALT; break; case VK_LWIN: case VK_RWIN: fs = MOD_WIN; break; default: /* * A non-modifier key rules out Modifier-Only hotkeys */ fsModOnlyCandidate = 0; break; } if (fBreak) { fsModifiers &= ~fs; /* * If a modifier key is coming up, the current modifier only hotkey * candidate must be tested to see if it is a hotkey. Store this * in fsModOnlyHotkey, and prevent the next key release from * being a candidate by clearing fsModOnlyCandidate. */ if (fs != 0) { fsModOnlyHotkey = fsModOnlyCandidate; fsModOnlyCandidate = 0; } } else { fsModifiers |= fs; /* * If a modifier key is going down, we have a modifier-only hotkey * candidate. Save current modifier state until the following break. */ if (fs != 0) { fsModOnlyCandidate = fsModifiers; } } if (vk == VK_DELETE) { /* * Special case for SAS (Ctrl+Alt+Del) - examine physical key state! * * An evil daemon process can fool convincingly pretend to be winlogon * by registering Alt+Del as a hotkey, and spinning another thread that * continually calls keybd_event() to send the Ctrl key up: when the * user types Ctrl+Alt+Del, only Alt+Del will be seen by the system, * the evil daemon will get woken by WM_HOTKEY and can pretend to be * winlogon. So look at gafPhysKeyState in this case, to see what keys * were physically pressed. * NOTE: If hotkeys are ever made to work under journal playback, make * sure they don't affect the gafPhysKeyState! - IanJa. */ UINT fPhysMods = (TestKeyDownBit(gafPhysKeyState, VK_MENU) ? MOD_ALT : 0) | (TestKeyDownBit(gafPhysKeyState, VK_SHIFT) ? MOD_SHIFT : 0) | (TestKeyDownBit(gafPhysKeyState, VK_CONTROL) ? MOD_CONTROL : 0); if ((fPhysMods & (MOD_CONTROL|MOD_ALT)) == MOD_CONTROL|MOD_ALT) { /* * Use physical modifiers keys */ fsModifiers = fPhysMods; } } #ifdef WINDOWS_NOT_HOT /* * track whether any key has been pressed since a Windows key went down */ if (vk == VK_LWIN || vk == VK_RWIN) { if (!fBreak) { fOnlyWinKey = TRUE; } else if (fOnlyWinKey) { fOnlyWinKey = FALSE; CancelJournalling(); pwnd = GETDESKINFO(PtiCurrent())->spwndShell; if (pwnd != NULL) { _PostMessage(pwnd, WM_SYSCOMMAND, SC_TASKLIST, 0); return TRUE; } } } else { fOnlyWinKey = FALSE; } #endif /* * If the key is not a hotkey then we're done but first check if the * key is an Alt-Escape if so we need to cancel journalling. * * NOTE: Support for Alt+Esc to cancel journalling dropped in NT 4.0 */ if (fsModOnlyHotkey && fBreak) { /* * A hotkey involving only VK_SHIFT, VK_CONTROL, VK_MENU or VK_WINDOWS * must only operate on a key release. */ if ((phk = IsHotKey(LOWORD(fsModOnlyHotkey), VK_NONE)) == NULL) { return FALSE; } } else if ((phk = IsHotKey(LOWORD(fsModifiers), vk)) == NULL) { return FALSE; } if (phk->id == IDHOT_WINDOWS) { pwnd = GETDESKINFO(PtiCurrent())->spwndShell; if (pwnd != NULL) { _PostMessage(pwnd, WM_SYSCOMMAND, SC_TASKLIST, 0); return TRUE; } } if ((phk->id == IDHOT_DEBUG) || (phk->id == IDHOT_DEBUGSERVER)) { if (!fBreak) { /* * The DEBUG key has been pressed. Break the appropriate * thread into the debugger. */ fEatDebugKeyBreak = xxxActivateDebugger(phk->fsModifiers); } /* * This'll eat the debug key down and break if we broke into * the debugger on the server only on the down. */ return fEatDebugKeyBreak; } /* * don't allow hotkeys(except for ones owned by the logon process) * if the window station is locked. */ if (((grpdeskRitInput->rpwinstaParent->dwFlags & WSF_SWITCHLOCK) != 0) && (phk->pti->Thread->Cid.UniqueProcess != gpidLogon)) { return FALSE; } if ((fsModOnlyHotkey == 0) && fBreak) { /* * Do Modifier-Only hotkeys on break events, else return here. */ return FALSE; } /* * Unhook hooks if a control-escape, alt-escape, or control-alt-del * comes through, so the user can cancel if the system seems hung. * * Note the hook may be locked so even if the unhook succeeds it * won't remove the hook from the global asphkStart array. So * we have to walk the list manually. This code works because * we are in the critical section and we know other hooks won't * be deleted. * * Once we've unhooked, post a WM_CANCELJOURNAL message to the app * that set the hook so it knows we did this. * * NOTE: Support for Alt+Esc to cancel journalling dropped in NT 4.0 */ fCancel = FALSE; if (vk == VK_ESCAPE && LOWORD(fsModifiers) == MOD_CONTROL) { fCancel = TRUE; } if (vk == VK_DELETE && (fsModifiers & (MOD_CONTROL | MOD_ALT)) == (MOD_CONTROL | MOD_ALT)) { fCancel = TRUE; } if (fCancel) CancelJournalling(); /* * See if the key is reserved by a console window. If it is, * return FALSE so the key will be passed to the console. */ if (fsReserveKeys != 0) { switch (vk) { case VK_TAB: if ((fsReserveKeys & CONSOLE_ALTTAB) && ((fsModifiers & (MOD_CONTROL | MOD_ALT)) == MOD_ALT)) { return FALSE; } break; case VK_ESCAPE: if ((fsReserveKeys & CONSOLE_ALTESC) && ((fsModifiers & (MOD_CONTROL | MOD_ALT)) == MOD_ALT)) { return FALSE; } if ((fsReserveKeys & CONSOLE_CTRLESC) && ((fsModifiers & (MOD_CONTROL | MOD_ALT)) == MOD_CONTROL)) { return FALSE; } break; case VK_RETURN: if ((fsReserveKeys & CONSOLE_ALTENTER) && ((fsModifiers & (MOD_CONTROL | MOD_ALT)) == MOD_ALT)) { return FALSE; } break; case VK_SNAPSHOT: if ((fsReserveKeys & CONSOLE_PRTSC) && ((fsModifiers & (MOD_CONTROL | MOD_ALT)) == 0)) { return FALSE; } if ((fsReserveKeys & CONSOLE_ALTPRTSC) && ((fsModifiers & (MOD_CONTROL | MOD_ALT)) == MOD_ALT)) { return FALSE; } break; case VK_SPACE: if ((fsReserveKeys & CONSOLE_ALTSPACE) && ((fsModifiers & (MOD_CONTROL | MOD_ALT)) == MOD_ALT)) { return FALSE; } break; } } /* * If this is the task-list hotkey, go ahead and set foreground * status to the task-list queue right now. This prevents problems * where the user hits ctrl-esc and types-ahead before the task-list * processes the hotkey and brings up the task-list window. */ if ((LOWORD(fsModifiers) == MOD_CONTROL) && (vk == VK_ESCAPE) && !fBreak) { PWND pwndSwitch; TL tlpwndSwitch; if (ghwndSwitch != NULL) { pwndSwitch = PW(ghwndSwitch); ThreadLock(pwndSwitch, &tlpwndSwitch); xxxSetForegroundWindow2(pwndSwitch, NULL, 0); ThreadUnlock(&tlpwndSwitch); } } /* * Get the hot key contents. */ if (phk->spwnd == NULL) { _PostThreadMessage( phk->pti, WM_HOTKEY, phk->id, MAKELONG(LOWORD(fsModifiers), vk)); } else { if (phk->spwnd == PWND_INPUTOWNER) { if (gpqForeground != NULL) { pwnd = gpqForeground->spwndFocus; } else { return FALSE; } } else { pwnd = phk->spwnd; } if (pwnd) { if (pwnd == pwnd->head.rpdesk->pDeskInfo->spwndShell && phk->id == SC_TASKLIST) { _PostMessage(pwnd, WM_SYSCOMMAND, SC_TASKLIST, 0); } else { _PostMessage(pwnd, WM_HOTKEY, phk->id, MAKELONG(LOWORD(fsModifiers), vk)); } } } /* * If this is a Modifier-Only hotkey, let the modifier break through * by returning FALSE, otherwise we will have modifier keys stuck down. */ return (fsModOnlyHotkey == 0); }
void PostMessageWait(dword dwProcID, dword dwEvent, byte *pBuff, int nLength) { while (!_PostMessage(dwProcID, dwEvent, pBuff, nLength)) ::Sleep(110); }