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

📄 keyboard.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 3 页
字号:
      return STATUS_NO_MEMORY;
   }
   memcpy( new_string, ResultFirst->Buffer,
           ResultFirst->Length );
   memcpy( new_string + ResultFirst->Length / sizeof(WCHAR),
           Second->Buffer,
           Second->Length );
   if( Deallocate )
      RtlFreeUnicodeString(ResultFirst);
   ResultFirst->Length += Second->Length;
   ResultFirst->MaximumLength = ResultFirst->Length;
   new_string[ResultFirst->Length / sizeof(WCHAR)] = 0;
   Status = RtlCreateUnicodeString(ResultFirst,new_string) ?
            STATUS_SUCCESS : STATUS_NO_MEMORY;
   ExFreePool(new_string);
   return Status;
}

/*
 * Utility function to read a value from the registry more easily.
 *
 * IN  PUNICODE_STRING KeyName       -> Name of key to open
 * IN  PUNICODE_STRING ValueName     -> Name of value to open
 * OUT PUNICODE_STRING ReturnedValue -> String contained in registry
 *
 * Returns NTSTATUS
 */

static NTSTATUS NTAPI ReadRegistryValue( PUNICODE_STRING KeyName,
      PUNICODE_STRING ValueName,
      PUNICODE_STRING ReturnedValue )
{
   NTSTATUS Status;
   HANDLE KeyHandle;
   OBJECT_ATTRIBUTES KeyAttributes;
   PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo;
   ULONG Length = 0;
   ULONG ResLength = 0;
   UNICODE_STRING Temp;

   InitializeObjectAttributes(&KeyAttributes, KeyName, OBJ_CASE_INSENSITIVE,
                              NULL, NULL);
   Status = ZwOpenKey(&KeyHandle, KEY_ALL_ACCESS, &KeyAttributes);
   if( !NT_SUCCESS(Status) )
   {
      return Status;
   }

   Status = ZwQueryValueKey(KeyHandle, ValueName, KeyValuePartialInformation,
                            0,
                            0,
                            &ResLength);

   if( Status != STATUS_BUFFER_TOO_SMALL )
   {
      NtClose(KeyHandle);
      return Status;
   }

   ResLength += sizeof( *KeyValuePartialInfo );
   KeyValuePartialInfo =
      ExAllocatePoolWithTag(PagedPool, ResLength, TAG_STRING);
   Length = ResLength;

   if( !KeyValuePartialInfo )
   {
      NtClose(KeyHandle);
      return STATUS_NO_MEMORY;
   }

   Status = ZwQueryValueKey(KeyHandle, ValueName, KeyValuePartialInformation,
                            (PVOID)KeyValuePartialInfo,
                            Length,
                            &ResLength);

   if( !NT_SUCCESS(Status) )
   {
      NtClose(KeyHandle);
      ExFreePool(KeyValuePartialInfo);
      return Status;
   }

   Temp.Length = Temp.MaximumLength = KeyValuePartialInfo->DataLength;
   Temp.Buffer = (PWCHAR)KeyValuePartialInfo->Data;

   /* At this point, KeyValuePartialInfo->Data contains the key data */
   RtlInitUnicodeString(ReturnedValue,L"");
   AppendUnicodeString(ReturnedValue,&Temp,FALSE);

   ExFreePool(KeyValuePartialInfo);
   NtClose(KeyHandle);

   return Status;
}

typedef PVOID (*KbdLayerDescriptor)(VOID);
NTSTATUS STDCALL LdrGetProcedureAddress(PVOID module,
                                        PANSI_STRING import_name,
                                        DWORD flags,
                                        PVOID *func_addr);

void InitKbdLayout( PVOID *pkKeyboardLayout )
{
   WCHAR LocaleBuffer[16];
   UNICODE_STRING LayoutKeyName;
   UNICODE_STRING LayoutValueName;
   UNICODE_STRING DefaultLocale;
   UNICODE_STRING LayoutFile;
   UNICODE_STRING FullLayoutPath;
   LCID LocaleId;
   PWCHAR KeyboardLayoutWSTR;
   HMODULE kbModule = 0;
   NTSTATUS Status;
   ANSI_STRING kbdProcedureName;
   KbdLayerDescriptor layerDescGetFn;

#define XX_STATUS(x) if (!NT_SUCCESS(Status = (x))) continue;

   do
   {
      Status = ZwQueryDefaultLocale(FALSE, &LocaleId);
      if (!NT_SUCCESS(Status))
      {
         DPRINT1("Could not get default locale (%08lx).\n", Status);
      }
      else
      {
         DPRINT("DefaultLocale = %lx\n", LocaleId);
         swprintf(LocaleBuffer, L"%08lx", LocaleId);
         DPRINT("DefaultLocale = %S\n", LocaleBuffer);
         RtlInitUnicodeString(&DefaultLocale, LocaleBuffer);

         RtlInitUnicodeString(&LayoutKeyName,
                              L"\\REGISTRY\\Machine\\SYSTEM\\CurrentControlSet"
                              L"\\Control\\KeyboardLayouts\\");

         AppendUnicodeString(&LayoutKeyName,&DefaultLocale,FALSE);

         RtlInitUnicodeString(&LayoutValueName,L"Layout File");

         Status = ReadRegistryValue(&LayoutKeyName,&LayoutValueName,&LayoutFile);

         RtlFreeUnicodeString(&LayoutKeyName);

         if( !NT_SUCCESS(Status) )
         {
            DPRINT1("Got default locale but not layout file. (%08lx)\n",
                    Status);
         }
         else
         {
            DPRINT("Read registry and got %wZ\n", &LayoutFile);


            RtlInitUnicodeString(&FullLayoutPath,SYSTEMROOT_DIR);
            AppendUnicodeString(&FullLayoutPath,&LayoutFile,FALSE);

            DPRINT("Loading Keyboard DLL %wZ\n", &FullLayoutPath);

            RtlFreeUnicodeString(&LayoutFile);

            KeyboardLayoutWSTR =
               ExAllocatePoolWithTag(PagedPool,
                                     FullLayoutPath.Length + sizeof(WCHAR),
                                     TAG_STRING);

            if( !KeyboardLayoutWSTR )
            {
               DPRINT1("Couldn't allocate a string for the keyboard layout name.\n");
               RtlFreeUnicodeString(&FullLayoutPath);
               return;
            }
            memcpy(KeyboardLayoutWSTR,FullLayoutPath.Buffer,
                   FullLayoutPath.Length);
            KeyboardLayoutWSTR[FullLayoutPath.Length / sizeof(WCHAR)] = 0;

            kbModule = EngLoadImage(KeyboardLayoutWSTR);
            DPRINT( "Load Keyboard Layout: %S\n", KeyboardLayoutWSTR );

            if( !kbModule )
               DPRINT1( "Load Keyboard Layout: No %wZ\n", &FullLayoutPath );

            ExFreePool(KeyboardLayoutWSTR);
            RtlFreeUnicodeString(&FullLayoutPath);
         }
      }

      if( !kbModule )
      {
         DPRINT1("Trying to load US Keyboard Layout\n");
         kbModule = EngLoadImage(L"\\SystemRoot\\system32\\kbdus.dll");

         if (!kbModule)
         {
            DPRINT1("Failed to load any Keyboard Layout\n");
            return;
         }
      }

      RtlInitAnsiString( &kbdProcedureName, "KbdLayerDescriptor" );

      LdrGetProcedureAddress((PVOID)kbModule,
                             &kbdProcedureName,
                             0,
                             (PVOID*)&layerDescGetFn);

      if( layerDescGetFn )
      {
         *pkKeyboardLayout = layerDescGetFn();
      }
   }
   while (FALSE);

   if( !*pkKeyboardLayout )
   {
      DPRINT1("Failed to load the keyboard layout.\n");
   }

#undef XX_STATUS
}

PKBDTABLES W32kGetDefaultKeyLayout(VOID)
{
   PKBDTABLES pkKeyboardLayout = 0;
   InitKbdLayout( (PVOID) &pkKeyboardLayout );
   return pkKeyboardLayout;
}

BOOL FASTCALL
IntTranslateKbdMessage(LPMSG lpMsg,
                       HKL dwhkl)
{
   static INT dead_char = 0;
   LONG UState = 0;
   WCHAR wp[2] = { 0 };
   MSG NewMsg = { 0 };
   PKBDTABLES keyLayout;
   BOOL Result = FALSE;
   DWORD ScanCode = 0;


   keyLayout = PsGetCurrentThreadWin32Thread()->KeyboardLayout;
   if( !keyLayout )
      return FALSE;

   if (lpMsg->message != WM_KEYDOWN && lpMsg->message != WM_SYSKEYDOWN)
      return FALSE;

   ScanCode = (lpMsg->lParam >> 16) & 0xff;

   /* All messages have to contain the cursor point. */
   IntGetCursorLocation(PsGetCurrentThreadWin32Thread()->Desktop->WindowStation,
                        &NewMsg.pt);

   UState = ToUnicodeInner(lpMsg->wParam, HIWORD(lpMsg->lParam) & 0xff,
                           gQueueKeyStateTable, wp, 2, 0,
                           keyLayout );

   if (UState == 1)
   {
      NewMsg.message = (lpMsg->message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR;
      if (dead_char)
      {
         ULONG i;
         WCHAR first, second;
         DPRINT("PREVIOUS DEAD CHAR: %c\n", dead_char);

         for( i = 0; keyLayout->pDeadKey[i].dwBoth; i++ )
         {
            first = keyLayout->pDeadKey[i].dwBoth >> 16;
            second = keyLayout->pDeadKey[i].dwBoth;
            if (first == dead_char && second == wp[0])
            {
               wp[0] = keyLayout->pDeadKey[i].wchComposed;
               dead_char = 0;
               break;
            }
         }

         DPRINT("FINAL CHAR: %c\n", wp[0]);
      }

      if (dead_char)
      {
         NewMsg.hwnd = lpMsg->hwnd;
         NewMsg.wParam = dead_char;
         NewMsg.lParam = lpMsg->lParam;
         dead_char = 0;
         MsqPostMessage(PsGetCurrentThreadWin32Thread()->MessageQueue, &NewMsg, FALSE, QS_KEY);
      }

      NewMsg.hwnd = lpMsg->hwnd;
      NewMsg.wParam = wp[0];
      NewMsg.lParam = lpMsg->lParam;
      DPRINT( "CHAR='%c' %04x %08x\n", wp[0], wp[0], lpMsg->lParam );
      MsqPostMessage(PsGetCurrentThreadWin32Thread()->MessageQueue, &NewMsg, FALSE, QS_KEY);
      Result = TRUE;
   }
   else if (UState == -1)
   {
      NewMsg.message =
         (lpMsg->message == WM_KEYDOWN) ? WM_DEADCHAR : WM_SYSDEADCHAR;
      NewMsg.hwnd = lpMsg->hwnd;
      NewMsg.wParam = wp[0];
      NewMsg.lParam = lpMsg->lParam;
      dead_char = wp[0];
      MsqPostMessage(PsGetCurrentThreadWin32Thread()->MessageQueue, &NewMsg, FALSE, QS_KEY);
      Result = TRUE;
   }

   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");

⌨️ 快捷键说明

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