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

📄 keyboard.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 3 页
字号:
   UserEnterExclusive();
   
   keyLayout = PsGetCurrentThreadWin32Thread() ? PsGetCurrentThreadWin32Thread()->KeyboardLayout : 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 : 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
STDCALL
NtUserGetKeyboardLayoutList(
   DWORD Items,
   DWORD pHklBuff)
{
   UNIMPLEMENTED

   return 0;
}

BOOL
STDCALL
NtUserGetKeyboardLayoutName(
   LPWSTR lpszName)
{
  BOOL ret = FALSE;
  LCID LocaleId;
  WCHAR LocaleBuffer[16];
  NTSTATUS Status;


  UserEnterExclusive();

   DPRINT("Enter NtUserGetKeyboardLayoutName\n");

   Status = ZwQueryDefaultLocale(FALSE, &LocaleId);
   if (NT_SUCCESS(Status))
   {
        swprintf(LocaleBuffer, L"%08lx", LocaleId);
        DPRINT("LocaleId : %08lx\n",LocaleId);
        _SEH_TRY
        {
           ProbeForWrite(lpszName, 16, 1);
           RtlCopyMemory(lpszName,LocaleBuffer,16);
            ret = TRUE;
        }
        _SEH_HANDLE
        {
            SetLastNtError(_SEH_GetExceptionCode());
            ret = FALSE;
        }
        _SEH_END;
   }
   UserLeave();
   return ret;
}


HKL FASTCALL
UserGetKeyboardLayout(
   DWORD dwThreadId)
{
   NTSTATUS Status;
   PETHREAD Thread;
   PW32THREAD W32Thread;
   PKBDTABLES layout;

   if (!dwThreadId)
      W32Thread = PsGetCurrentThreadWin32Thread();
   else
   {
      Status = PsLookupThreadByThreadId((HANDLE)dwThreadId, &Thread);//fixme: deref thread
      if(!NT_SUCCESS(Status))
      {
         SetLastWin32Error(ERROR_INVALID_PARAMETER);
         return 0;
      }
      W32Thread = Thread->Tcb.Win32Thread; /* Wrong, but returning the pointer to
                                              the table. */
   }
   layout = W32Thread->KeyboardLayout;
   if(!layout)
      return 0;
   return (HKL)layout;
}


HKL
STDCALL
NtUserGetKeyboardLayout(
   DWORD dwThreadId)
{
   DECLARE_RETURN(HKL);

   UserEnterShared();
   DPRINT("Enter NtUserGetKeyboardLayout\n");

   RETURN( UserGetKeyboardLayout(dwThreadId));

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


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 */
   }
}


HKL
STDCALL
NtUserLoadKeyboardLayoutEx( 
   IN HANDLE Handle,
   IN DWORD offTable,
   IN HKL hKL,
   IN PUNICODE_STRING puszKLID,
   IN UINT KLayoutLangID,
   IN UINT Flags)
{
   UNIMPLEMENTED

   return 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 + -