⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 keyboard.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 2 页
字号:
   return Result;
}

DWORD
STDCALL
NtUserGetKeyboardState(
   LPBYTE lpKeyState)
{
   BOOL Result = TRUE;
   DECLARE_RETURN(DWORD);
   
   DPRINT("Enter NtUserGetKeyboardState\n");
   UserEnterShared();
   
   if (lpKeyState)
   {
      if(!NT_SUCCESS(MmCopyToCaller(lpKeyState, gQueueKeyStateTable, 256)))
         Result = FALSE;
   }

   RETURN(Result);
   
CLEANUP:
   DPRINT("Leave NtUserGetKeyboardState, ret=%i\n",_ret_);
   UserLeave();
   END_CLEANUP;
}

DWORD
STDCALL
NtUserSetKeyboardState(LPBYTE lpKeyState)
{
   BOOL Result = TRUE;
   DECLARE_RETURN(DWORD);
   
   DPRINT("Enter NtUserSetKeyboardState\n");
   UserEnterExclusive();

   if (lpKeyState)
   {
      if(! NT_SUCCESS(MmCopyFromCaller(gQueueKeyStateTable, lpKeyState, 256)))
         Result = FALSE;
   }
   
   RETURN(Result);

CLEANUP:
   DPRINT("Leave NtUserSetKeyboardState, ret=%i\n",_ret_);
   UserLeave();
   END_CLEANUP;
}

static UINT VkToScan( UINT Code, BOOL ExtCode, PKBDTABLES pkKT )
{
   int i;

   for( i = 0; i < pkKT->bMaxVSCtoVK; i++ )
   {
      if( pkKT->pusVSCtoVK[i] == Code )
      {
         return i;
      }
   }

   return 0;
}

UINT ScanToVk( UINT Code, BOOL ExtKey, PKBDTABLES pkKT )
{
   if( !pkKT )
   {
      DPRINT("ScanToVk: No layout\n");
      return 0;
   }

   if( ExtKey )
   {
      int i;

      for( i = 0; pkKT->pVSCtoVK_E0[i].Vsc; i++ )
      {
         if( pkKT->pVSCtoVK_E0[i].Vsc == Code )
            return pkKT->pVSCtoVK_E0[i].Vk & 0xff;
      }
      for( i = 0; pkKT->pVSCtoVK_E1[i].Vsc; i++ )
      {
         if( pkKT->pVSCtoVK_E1[i].Vsc == Code )
            return pkKT->pVSCtoVK_E1[i].Vk & 0xff;
      }

      return 0;
   }
   else
   {
      if( Code >= pkKT->bMaxVSCtoVK )
      {
         return 0;
      }
      return pkKT->pusVSCtoVK[Code] & 0xff;
   }
}

/*
 * Map a virtual key code, or virtual scan code, to a scan code, key code,
 * or unshifted unicode character.
 *
 * Code: See Below
 * Type:
 * 0 -- Code is a virtual key code that is converted into a virtual scan code
 *      that does not distinguish between left and right shift keys.
 * 1 -- Code is a virtual scan code that is converted into a virtual key code
 *      that does not distinguish between left and right shift keys.
 * 2 -- Code is a virtual key code that is converted into an unshifted unicode
 *      character.
 * 3 -- Code is a virtual scan code that is converted into a virtual key code
 *      that distinguishes left and right shift keys.
 * KeyLayout: Keyboard layout handle (currently, unused)
 *
 * @implemented
 */

static UINT IntMapVirtualKeyEx( UINT Code, UINT Type, PKBDTABLES keyLayout )
{
   UINT ret = 0;

   switch( Type )
   {
      case 0:
         if( Code == VK_RSHIFT )
            Code = VK_LSHIFT;
         if( Code == VK_RMENU )
            Code = VK_LMENU;
         if( Code == VK_RCONTROL )
            Code = VK_LCONTROL;
         ret = VkToScan( Code, FALSE, keyLayout );
         break;

      case 1:
         ret =
            DontDistinguishShifts
            (IntMapVirtualKeyEx( Code, 3, keyLayout ) );
         break;

      case 2:
         {
            WCHAR wp[2] = {0};

            ret = VkToScan( Code, FALSE, keyLayout );
            ToUnicodeInner( Code, ret, 0, wp, 2, 0, keyLayout );
            ret = wp[0];
         }
         break;

      case 3:

         ret = ScanToVk( Code, FALSE, keyLayout );
         break;
   }

   return ret;
}

UINT
STDCALL
NtUserMapVirtualKeyEx( UINT Code, UINT Type, DWORD keyboardId, HKL dwhkl )
{
   PKBDTABLES keyLayout;
   DECLARE_RETURN(UINT);
   
   DPRINT("Enter NtUserMapVirtualKeyEx\n");
   UserEnterExclusive();
   
   keyLayout = PsGetCurrentThreadWin32Thread() ? PsGetCurrentThreadWin32Thread()->KeyboardLayout->KBTables : 0;

   if( !keyLayout )
      RETURN(0);

   RETURN(IntMapVirtualKeyEx( Code, Type, keyLayout ));
   
CLEANUP:
   DPRINT("Leave NtUserMapVirtualKeyEx, ret=%i\n",_ret_);
   UserLeave();
   END_CLEANUP;   
}


int
STDCALL
NtUserToUnicodeEx(
   UINT wVirtKey,
   UINT wScanCode,
   PBYTE lpKeyState,
   LPWSTR pwszBuff,
   int cchBuff,
   UINT wFlags,
   HKL dwhkl )
{
   BYTE KeyStateBuf[0x100];
   PWCHAR OutPwszBuff = 0;
   int ret = 0;
   DECLARE_RETURN(int);
   
   DPRINT("Enter NtUserSetKeyboardState\n");
   UserEnterShared();//faxme: this syscall doesnt seem to need any locking...


   if( !NT_SUCCESS(MmCopyFromCaller(KeyStateBuf,
                                    lpKeyState,
                                    sizeof(KeyStateBuf))) )
   {
      DPRINT1( "Couldn't copy key state from caller.\n" );
      RETURN(0);
   }
   OutPwszBuff = ExAllocatePoolWithTag(NonPagedPool,sizeof(WCHAR) * cchBuff, TAG_STRING);
   if( !OutPwszBuff )
   {
      DPRINT1( "ExAllocatePool(%d) failed\n", sizeof(WCHAR) * cchBuff);
      RETURN(0);
   }
   RtlZeroMemory( OutPwszBuff, sizeof( WCHAR ) * cchBuff );

   ret = ToUnicodeEx( wVirtKey,
                      wScanCode,
                      KeyStateBuf,
                      OutPwszBuff,
                      cchBuff,
                      wFlags,
                      dwhkl );

   MmCopyToCaller(pwszBuff,OutPwszBuff,sizeof(WCHAR)*cchBuff);
   ExFreePool(OutPwszBuff);

   RETURN(ret);
   
CLEANUP:
   DPRINT("Leave NtUserSetKeyboardState, ret=%i\n",_ret_);
   UserLeave();
   END_CLEANUP;   
}

static int W32kSimpleToupper( int ch )
{
   if( ch >= 'a' && ch <= 'z' )
      ch = ch - 'a' + 'A';
   return ch;
}

DWORD
STDCALL
NtUserGetKeyNameText( LONG lParam, LPWSTR lpString, int nSize )
{
   int i;
   DWORD ret = 0;
   UINT CareVk = 0;
   UINT VkCode = 0;
   UINT ScanCode = (lParam >> 16) & 0xff;
   BOOL ExtKey = lParam & (1<<24) ? TRUE : FALSE;
   PKBDTABLES keyLayout;
   VSC_LPWSTR *KeyNames;
   DECLARE_RETURN(DWORD);
   
   DPRINT("Enter NtUserGetKeyNameText\n");
   UserEnterShared();
   
   keyLayout = PsGetCurrentThreadWin32Thread() ?
      PsGetCurrentThreadWin32Thread()->KeyboardLayout->KBTables : 0;

   if( !keyLayout || nSize < 1 )
      RETURN(0);

   if( lParam & (1<<25) )
   {
      CareVk = VkCode = ScanToVk( ScanCode, ExtKey, keyLayout );
      if( VkCode == VK_LSHIFT || VkCode == VK_RSHIFT )
         VkCode = VK_LSHIFT;
      if( VkCode == VK_LCONTROL || VkCode == VK_RCONTROL )
         VkCode = VK_LCONTROL;
      if( VkCode == VK_LMENU || VkCode == VK_RMENU )
         VkCode = VK_LMENU;
   }
   else
   {
      VkCode = ScanToVk( ScanCode, ExtKey, keyLayout );
   }

   KeyNames = 0;

   if( CareVk != VkCode )
      ScanCode = VkToScan( VkCode, ExtKey, keyLayout );

   if( ExtKey )
      KeyNames = keyLayout->pKeyNamesExt;
   else
      KeyNames = keyLayout->pKeyNames;

   for( i = 0; KeyNames[i].pwsz; i++ )
   {
      if( KeyNames[i].vsc == ScanCode )
      {
         UINT StrLen = wcslen(KeyNames[i].pwsz);
         UINT StrMax = StrLen > (nSize - 1) ? (nSize - 1) : StrLen;
         WCHAR null_wc = 0;
         if( NT_SUCCESS( MmCopyToCaller( lpString,
                                         KeyNames[i].pwsz,
                                         StrMax * sizeof(WCHAR) ) ) &&
               NT_SUCCESS( MmCopyToCaller( lpString + StrMax,
                                           &null_wc,
                                           sizeof( WCHAR ) ) ) )
         {
            ret = StrMax;
            break;
         }
      }
   }

   if( ret == 0 )
   {
      WCHAR UCName[2];

      UCName[0] = W32kSimpleToupper(IntMapVirtualKeyEx( VkCode, 2, keyLayout ));
      UCName[1] = 0;
      ret = 1;

      if( !NT_SUCCESS(MmCopyToCaller( lpString, UCName, 2 * sizeof(WCHAR) )) )
         RETURN(0);
   }

   RETURN(ret);
   
CLEANUP:
   DPRINT("Leave NtUserGetKeyNameText, ret=%i\n",_ret_);
   UserLeave();
   END_CLEANUP;
}

/*
 * Filter this message according to the current key layout, setting wParam
 * appropriately.
 */

VOID FASTCALL
W32kKeyProcessMessage(LPMSG Msg,
                      PKBDTABLES KeyboardLayout,
                      BYTE Prefix)
{
   DWORD ScanCode = 0, ModifierBits = 0;
   DWORD i = 0;
   DWORD BaseMapping = 0;
   DWORD RawVk = 0;
   static WORD NumpadConversion[][2] =
      { { VK_DELETE, VK_DECIMAL },
        { VK_INSERT, VK_NUMPAD0 },
        { VK_END,    VK_NUMPAD1 },
        { VK_DOWN,   VK_NUMPAD2 },
        { VK_NEXT,   VK_NUMPAD3 },
        { VK_LEFT,   VK_NUMPAD4 },
        { VK_CLEAR,  VK_NUMPAD5 },
        { VK_RIGHT,  VK_NUMPAD6 },
        { VK_HOME,   VK_NUMPAD7 },
        { VK_UP,     VK_NUMPAD8 },
        { VK_PRIOR,  VK_NUMPAD9 },
        { 0,0 } };
   PVSC_VK VscVkTable = NULL; 

   if( !KeyboardLayout || !Msg ||
         (Msg->message != WM_KEYDOWN && Msg->message != WM_SYSKEYDOWN &&
          Msg->message != WM_KEYUP   && Msg->message != WM_SYSKEYUP) )
   {
      return;
   }

   /* arty -- handle numpad -- On real windows, the actual key produced
    * by the messaging layer is different based on the state of numlock. */
   ModifierBits = ModBits(KeyboardLayout,gQueueKeyStateTable);

   /* Get the raw scan code, so we can look up whether the key is a numpad
    * key
    *
    * Shift and the LP_EXT_BIT cancel. */
   ScanCode = (Msg->lParam >> 16) & 0xff;
   BaseMapping = Msg->wParam =
                    IntMapVirtualKeyEx( ScanCode, 1, KeyboardLayout );
   if( Prefix == 0 )
   {
      if( ScanCode >= KeyboardLayout->bMaxVSCtoVK )
         RawVk = 0xff;
      else
         RawVk = KeyboardLayout->pusVSCtoVK[ScanCode];
   }
   else
   {
      if( Prefix == 0xE0 )
      {
         /* ignore shift codes */
         if( ScanCode == 0x2A || ScanCode == 0x36 )
         {
            return;
         }
         VscVkTable = KeyboardLayout->pVSCtoVK_E0;
      }
      else if( Prefix == 0xE1 )
      {
         VscVkTable = KeyboardLayout->pVSCtoVK_E1;
      }

      RawVk = 0xff;
      while (VscVkTable->Vsc)
      {
         if( VscVkTable->Vsc == ScanCode )
         {
            RawVk = VscVkTable->Vk;
         }
         VscVkTable++;
      }
   }

   if ((ModifierBits & NUMLOCK_BIT) &&
         !(ModifierBits & GetShiftBit(KeyboardLayout, VK_SHIFT)) &&
         (RawVk & KNUMP) &&
         !(Msg->lParam & LP_EXT_BIT))
   {
      /* The key in question is a numpad key.  Search for a translation. */
      for (i = 0; NumpadConversion[i][0]; i++)
      {
         if ((BaseMapping & 0xff) == NumpadConversion[i][0]) /* RawVk? */
         {
            Msg->wParam = NumpadConversion[i][1];
            break;
         }
      }
   }

   DPRINT("Key: [%04x -> %04x]\n", BaseMapping, Msg->wParam);

   /* Now that we have the VK, we can set the keymap appropriately
    * This is a better place for this code, as it's guaranteed to be
    * run, unlike translate message. */
   if (Msg->message == WM_KEYDOWN || Msg->message == WM_SYSKEYDOWN)
   {
      SetKeyState( ScanCode, Msg->wParam, Msg->lParam & LP_EXT_BIT,
                   TRUE ); /* Strike key */
   }
   else if (Msg->message == WM_KEYUP || Msg->message == WM_SYSKEYUP)
   {
      SetKeyState( ScanCode, Msg->wParam, Msg->lParam & LP_EXT_BIT,
                   FALSE ); /* Release key */
   }

   /* We need to unset SYSKEYDOWN if the ALT key is an ALT+Gr */
   if( gQueueKeyStateTable[VK_RMENU] & KS_DOWN_BIT )
   {
      if( Msg->message == WM_SYSKEYDOWN )
         Msg->message = WM_KEYDOWN;
      else
         Msg->message = WM_KEYUP;
   }

}



DWORD FASTCALL
UserGetKeyboardType(
   DWORD TypeFlag)
{
   switch(TypeFlag)
   {
      case 0:        /* Keyboard type */
         return 4;    /* AT-101 */
      case 1:        /* Keyboard Subtype */
         return 0;    /* There are no defined subtypes */
      case 2:        /* Number of F-keys */
         return 12;   /* We're doing an 101 for now, so return 12 F-keys */
      default:
         DPRINT1("Unknown type!\n");
         return 0;    /* The book says 0 here, so 0 */
   }
}


/*
    Based on TryToTranslateChar, instead of processing VirtualKey match,
    look for wChar match.
 */
DWORD
STDCALL
NtUserVkKeyScanEx(
   DWORD wChar,
   DWORD KeyboardLayout,
   DWORD Unknown2)
{
/* FAXME: currently, this routine doesnt seem to need any locking */

   PKBDTABLES KeyLayout;
   PVK_TO_WCHAR_TABLE vtwTbl;
   PVK_TO_WCHARS10 vkPtr;
   size_t size_this_entry;
   int nMod;
   DWORD CapsMod = 0, CapsState = 0;

   if(!KeyboardLayout)
      return -1;
   KeyLayout = (PKBDTABLES) KeyboardLayout;

   for (nMod = 0; KeyLayout->pVkToWcharTable[nMod].nModifications; nMod++)
   {
      vtwTbl = &KeyLayout->pVkToWcharTable[nMod];
      size_this_entry = vtwTbl->cbSize;
      vkPtr = (PVK_TO_WCHARS10)((BYTE *)vtwTbl->pVkToWchars);

      while(vkPtr->VirtualKey)
      {
         /*
            0x01 Shift key
            0x02 Ctrl key
            0x04 Alt key
            Should have only 8 valid possibilities. Including zero.
          */
         for(CapsState = 0; CapsState < vtwTbl->nModifications; CapsState++)
         {
            if(vkPtr->wch[CapsState] == wChar)
            {
               CapsMod = KeyLayout->pCharModifiers->ModNumber[CapsState];
               DPRINT("nMod %d wC %04x: CapsMod %08x CapsState %08x MaxModBits %08x\n",
                      nMod, wChar, CapsMod, CapsState, KeyLayout->pCharModifiers->wMaxModBits);
               return ((CapsMod << 8)|(vkPtr->VirtualKey & 0xff));
            }
         }
         vkPtr = (PVK_TO_WCHARS10)(((BYTE *)vkPtr) + size_this_entry);
      }
   }
   return -1;
}


/* EOF */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -