📄 keybdmdd.cpp
字号:
{
vkUp = v_BackVKeySent;
v_BackVKeySent = 0;
if ( v_fLShiftDown )
{
vkDown = VK_LSHIFT;
}
else if ( v_fRShiftDown )
{
vkDown = VK_RSHIFT;
}
}
else if ( vkOnly == VK_COMMA )
{
vkUp = v_CommaVKeySent;
v_CommaVKeySent = 0;
if ( ANY_ALT_DOWN() )
{
vkDown = VK_MENU;
}
}
else if ( vkOnly == VK_PERIOD )
{
vkUp = v_PeriodVKeySent;
v_PeriodVKeySent = 0;
if ( ANY_ALT_DOWN() )
{
vkDown = VK_MENU;
}
}
else if ( vkOnly == VK_RIGHT )
{
vkUp = v_RightVKeySent;
v_RightVKeySent = 0;
if ( ANY_ALT_DOWN() )
{
vkDown = VK_MENU;
}
}
else if ( vkOnly == VK_LEFT )
{
vkUp = v_LeftVKeySent;
v_LeftVKeySent = 0;
if ( ANY_ALT_DOWN() )
{
vkDown = VK_MENU;
}
}
else if ( vkOnly == VK_UP )
{
vkUp = v_UpVKeySent;
v_UpVKeySent = 0;
if ( ANY_ALT_DOWN() )
{
vkDown = VK_MENU;
}
}
else if ( vkOnly == VK_DOWN )
{
vkUp = v_DownVKeySent;
v_DownVKeySent = 0;
if ( ANY_ALT_DOWN() )
{
vkDown = VK_MENU;
}
}
else if ( vkOnly == VK_LMENU )
{
v_fLAltDown = FALSE;
// If we already sent out that the Alt key went up, don't send it again.
if ( v_fLPseudoAltDown )
{
v_fLPseudoAltDown = FALSE;
}
else
{
fSendUp = FALSE;
}
}
else if ( vkOnly == VK_RMENU )
{
v_fRAltDown = FALSE;
// If we already sent out that the Alt key went up, don't send it again.
if ( v_fRPseudoAltDown )
{
v_fRPseudoAltDown = FALSE;
}
else
{
fSendUp = FALSE;
}
}
else if ( vkOnly == VK_LCONTROL )
{
v_fLCtrlDown = FALSE;
}
else if ( vkOnly == VK_RCONTROL )
{
v_fRCtrlDown = FALSE;
}
if ( fSendUp )
{
/* If we are about to release the alt key and the last key down we sent
was pseudo-alt, send a null character through to keep menus from
activating. */
if ( v_fLastKeyDownWasPseudoAlt &&
( ( vkUp == VK_LMENU ) || ( vkUp == VK_RMENU ) ) )
{
(*v_pfnKeybdEventCallback)(
KEYBD_DEVICE_SILENT | vkOther, // Virtual key == 0 down.
KeyStateDownFlag);
(*v_pfnKeybdEventCallback)(vkOther, 0); // Virtual key == 0 up.
}
// Send the virtual key up.
(*v_pfnKeybdEventCallback)(vkUp|vkOther, KeyStateFlags);
}
// Make it look like the modifier(s) went down.
if ( vkDown )
{
if ( vkDown == VK_MENU )
{
if ( v_fLAltDown )
{
(*v_pfnKeybdEventCallback)(VK_LMENU | vkOther | KEYBD_DEVICE_SILENT, KeyStateDownFlag);
v_fLPseudoAltDown = TRUE;
}
if ( v_fRAltDown )
{
(*v_pfnKeybdEventCallback)(VK_RMENU | vkOther | KEYBD_DEVICE_SILENT, KeyStateDownFlag);
v_fRPseudoAltDown = TRUE;
}
v_fLastKeyDownWasPseudoAlt = TRUE;
}
else
{
(*v_pfnKeybdEventCallback)(vkDown | vkOther | KEYBD_DEVICE_SILENT, KeyStateDownFlag);
v_fLastKeyDownWasPseudoAlt = FALSE;
}
}
return;
}
/*++
KeybdDriverThread:
Keyboard driver interrupt service thread.
Return Value:
Never returns.
--*/
DWORD
KeybdDriverThread(
PVOID pArg
)
{
HANDLE hKeyIntr;
UINT32 VirtualKey[16]; // hardcoded w/ PDD
KEY_STATE_FLAGS KeyStateFlags[16]; // hardcoded w/ PDD
INT nKeys;
DWORD AutoRepeatKeysPerSec;
long AutoRepeatTimeout;
BOOL fSendAutoRepeatKey;
DWORD MRKeyTimeForPolling = 0; // Get rid of compiler uninitialized variable warning.
hKeyIntr = CreateEvent(
NULL, // No Security
FALSE, // Not manual reset
FALSE, // Not initially signalled
NULL // No name
);
if ( !hKeyIntr )
{
ERRORMSG(1,
(TEXT("Could not create event handle for keyboard interrupt!!!\r\n")));
goto exit;
}
// Turn on the interrupt.
if ( !InterruptInitialize(gIntrKeyboard, hKeyIntr, 0, 0) )
{
ERRORMSG(1,
(TEXT("InterruptInitialize(gIntrKeyboard - %d) failed!!!\r\n"),
gIntrKeyboard));
goto exit;
}
AutoRepeatTimeout = INFINITE;
wait_for_keybd_interrupt:
fSendAutoRepeatKey = FALSE;
// Grab a copy once w/o critical section.
AutoRepeatKeysPerSec = v_AutoRepeatKeysPerSec;
// 0 keys per second => auto repeat disabled.
if ( AutoRepeatKeysPerSec == 0 )
v_AutoRepeatState = AR_WAIT_FOR_ANY;
if ( v_AutoRepeatState == AR_WAIT_FOR_ANY )
{
AutoRepeatTimeout = INFINITE;
}
else if ( v_AutoRepeatState == AR_INITIAL_DELAY )
{
AutoRepeatTimeout = v_AutoRepeatInitialDelay;
}
else
{
AutoRepeatTimeout = 1000/AutoRepeatKeysPerSec;
}
if ( WaitForSingleObject(hKeyIntr, AutoRepeatTimeout) == WAIT_TIMEOUT )
{
/* On power off, the v_AutoRepeatState is set to AR_WAIT_FOR_ANY, but we
cannot reset the WaitForSingleObject timeout value. This means that when
we power on, we could (and probably will) come back from the wait with a
wait timeout status. In this case, we do nothing and come back around to
wait again with the proper timeout. */
if ( v_AutoRepeatState == AR_WAIT_FOR_ANY )
; // do nothing
else if ( v_AutoRepeatState == AR_INITIAL_DELAY )
{
fSendAutoRepeatKey = TRUE;
v_AutoRepeatState = AR_AUTOREPEATING;
}
else
{
fSendAutoRepeatKey = TRUE;
}
}
else
{
// We got a keyboard interrupt but there may or may not be keys.
if ( nKeys = KeybdPdd_GetEvent(VirtualKey, KeyStateFlags) ) // Assignment in if
{
int i;
for ( i = 0; i < nKeys; i++ )
{
if ( KeyStateIsDown(KeyStateFlags[i]) )
{
MRKeyTimeForPolling = GetTickCount();
v_AutoRepeatState = AR_INITIAL_DELAY;
v_AutoRepeatVKey = VirtualKey[i];
v_AutoRepeatFlags = KeyStateFlags[i];
KeybdSendKeyDownToUser(VirtualKey[i], KeyStateFlags[i]);
}
else
{
v_AutoRepeatState = AR_WAIT_FOR_ANY;
KeybdSendKeyUpToUser(VirtualKey[i], KeyStateFlags[i]);
}
}
}
else
{
// We did not get a timeout from the wait or key events. We must be periodically polling.
// This means that we will need to do the timing here.
if ( ( v_AutoRepeatState == AR_INITIAL_DELAY ) ||
( v_AutoRepeatState == AR_AUTOREPEATING ) )
{
DWORD TimeNow = GetTickCount();
if ( TimeNow > (MRKeyTimeForPolling + AutoRepeatTimeout) )
{
fSendAutoRepeatKey = TRUE;
MRKeyTimeForPolling = TimeNow;
v_AutoRepeatState = AR_AUTOREPEATING;
}
}
}
// Ack the interrupt.
InterruptDone(gIntrKeyboard);
}
if ( fSendAutoRepeatKey )
{
KeybdSendKeyDownToUser(v_AutoRepeatVKey, v_AutoRepeatFlags);
}
goto wait_for_keybd_interrupt;
exit:
ERRORMSG(1, (TEXT("Keyboard driver thread terminating.\r\n")));
return 0;
}
#define DEFAULT_THREAD_PRIORITY 145
#define KEYNAME_KEYBD_DRIVER TEXT("\\Drivers\\BuiltIn\\KeyBd")
#define VALNAME_THREAD_PRIO TEXT("Priority256")
/*++
Autodoc Information:
@func DWORD | KeybdDriverpGetPriority |
This routine reads the KeybdDriverThread thread priority from the registry.
@rdesc
Returns thread priority read from registry or the default priority if not
in the registry.
--*/
static DWORD KeybdDriverpGetPriority(void)
{
HKEY hKey;
DWORD dwType;
DWORD dwVal;
DWORD dwSize;
DWORD dwStatus;
dwStatus = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
KEYNAME_KEYBD_DRIVER,
0,
0,
&hKey
);
if (dwStatus)
{
DEBUGMSG(ZONE_INIT | ZONE_WARN,
(TEXT("KEYBDDR:KeybdDriverpGetPriority - RegOpenKeyEx(%s) failed %d, using default thread priority\n"),
KEYNAME_KEYBD_DRIVER, dwStatus));
return DEFAULT_THREAD_PRIORITY;
}
dwSize = sizeof(DWORD);
dwStatus = RegQueryValueEx(
hKey,
VALNAME_THREAD_PRIO,
0,
&dwType,
(PUCHAR)&dwVal,
&dwSize
);
if (dwStatus)
{
DEBUGMSG(ZONE_INIT | ZONE_WARN,
(TEXT("KEYBDDR:KeybdDriverpGetPriority - Failed to get %s value, defaulting to %d\r\n"),
VALNAME_THREAD_PRIO, DEFAULT_THREAD_PRIORITY));
dwVal = DEFAULT_THREAD_PRIORITY;
}
RegCloseKey(hKey);
return dwVal;
} // KeybdDriverpGetPriority
extern "C"
/*++
@doc EXTERNAL DRIVERS
@func
System power state change notification.
@comm This routine is called in a kernel context and may not make any
system calls whatsoever. It may read and write its own memory and that's
about it.
@comm Resets the auto-repeat state and calls the <f KeybdPdd_PowerHandler> routine.
--*/
void KeybdDriverPowerHandler(
BOOL bOff // @parm TRUE, the system is powering off; FALSE, the system is powering up.
)
{
v_AutoRepeatState = AR_WAIT_FOR_ANY;
KeybdPdd_PowerHandler(bOff);
return;
}
#ifdef DEBUG
PFN_KEYBD_DRIVER_POWER_HANDLER v_pfnPowerHandler = KeybdDriverPowerHandler;
#endif
extern "C"
// @doc EXTERNAL DRIVERS
/* @func Do one time only keyboard driver initialization.
@rdesc If the function succeeds the return value is TRUE, otherwise, it is
FALSE. Extended error information is available via the GetLastError
function.
@comm Calls <f KeybdPdd_InitializeDriver> then starts driver interrupt
service thread.
--*/
void KeybdDriverInitialize(
PFN_KEYBD_EVENT_CALLBACK pfnKeybdEventCallback // @parm The callback into the input system.
)
{
HANDLE hNewThread;
DWORD IDThread;
v_pfnKeybdEventCallback = pfnKeybdEventCallback;
KeybdPdd_InitializeDriver(pfnKeybdEventCallback);
hNewThread = CreateThread(
0, // Security Attributes
0, // Stack Size
(LPTHREAD_START_ROUTINE)KeybdDriverThread,
0, // Thread Param
0, // Creation Flags
&IDThread
);
if ( hNewThread == NULL )
{
ERRORMSG(1, (TEXT("Could not start keybd driver thread.\r\n")));
return;
}
// Get thread priority from registry and set
CeSetThreadPriority(hNewThread, KeybdDriverpGetPriority( ));
return;
}
#ifdef DEBUG
PFN_KEYBD_DRIVER_INITIALIZE v_pfnDriverInitializeTest = KeybdDriverInitialize;
#endif
BOOL
WINAPI
DllEntry(
HANDLE hinstDLL,
DWORD Op,
LPVOID lpvReserved
)
{
if ( !KeybdPdd_DllEntry(hinstDLL, Op, lpvReserved) )
return FALSE;
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -