[NTUSER] KLF_UNLOAD flag of NtUserGetKeyboardLayoutList (#4592)
authorKatayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
Wed, 3 Aug 2022 03:45:10 +0000 (12:45 +0900)
committerGitHub <noreply@github.com>
Wed, 3 Aug 2022 03:45:10 +0000 (12:45 +0900)
This implementation enables KLF_UNLOAD flag awareness on listing the KLs.
CORE-11700

win32ss/user/ntuser/kbdlayout.c
win32ss/user/ntuser/winsta.c
win32ss/user/ntuser/winsta.h

index 82767e7..bca41fa 100644 (file)
@@ -6,6 +6,7 @@
  * COPYRIGHT:       Copyright 2007 Saveliy Tretiakov
  *                  Copyright 2008 Colin Finck
  *                  Copyright 2011 Rafal Harabien
+ *                  Copyright 2022 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
  */
 
 #include <win32k.h>
 
 DBG_DEFAULT_CHANNEL(UserKbdLayout);
 
-PKL gspklBaseLayout = NULL;
+PKL gspklBaseLayout = NULL; /* FIXME: Please move this to pWinSta->spklList */
 PKBDFILE gpkfList = NULL;
 DWORD gSystemFS = 0;
 UINT gSystemCPCharSet = 0;
 
 typedef PVOID (*PFN_KBDLAYERDESCRIPTOR)(VOID);
 
-
 /* PRIVATE FUNCTIONS ******************************************************/
 
+// Win: _GetKeyboardLayoutList
+static UINT APIENTRY
+IntGetKeyboardLayoutList(
+    _Inout_ PWINSTATION_OBJECT pWinSta,
+    _In_ ULONG nBuff,
+    _Out_ HKL *pHklBuff)
+{
+    UINT ret = 0;
+    PKL pKL, pFirstKL;
+
+    pFirstKL = gspklBaseLayout; /* FIXME: Use pWinSta->spklList instead */
+    if (!pWinSta || !pFirstKL)
+        return 0;
+
+    pKL = pFirstKL;
+
+    if (nBuff == 0)
+    {
+        /* Count the effective PKLs */
+        do
+        {
+            if (!(pKL->dwKL_Flags & KLF_UNLOAD))
+                ++ret;
+            pKL = pKL->pklNext;
+        } while (pKL != pFirstKL);
+    }
+    else
+    {
+        /* Copy the effective HKLs to pHklBuff */
+        do
+        {
+            if (!(pKL->dwKL_Flags & KLF_UNLOAD))
+            {
+                *pHklBuff = pKL->hkl;
+                ++pHklBuff;
+                ++ret;
+                --nBuff;
+
+                if (nBuff == 0)
+                    break;
+            }
+            pKL = pKL->pklNext;
+        } while (pKL != pFirstKL);
+    }
+
+    return ret;
+}
+
 #if 0 && DBG
 
 static VOID
@@ -550,54 +598,47 @@ NtUserGetKeyboardLayoutList(
     ULONG nBuff,
     HKL *pHklBuff)
 {
-    UINT uRet = 0;
-    PKL pKl;
+    UINT ret = 0;
+    PWINSTATION_OBJECT pWinSta;
 
     if (!pHklBuff)
         nBuff = 0;
 
     UserEnterShared();
 
-    if (!gspklBaseLayout)
+    if (nBuff > MAXULONG / sizeof(HKL))
     {
-        UserLeave();
-        return 0;
+        SetLastNtError(ERROR_INVALID_PARAMETER);
+        goto Quit;
     }
-    pKl = gspklBaseLayout;
 
-    if (nBuff == 0)
+    _SEH2_TRY
     {
-        do
-        {
-            uRet++;
-            pKl = pKl->pklNext;
-        } while (pKl != gspklBaseLayout);
+        ProbeForWrite(pHklBuff, nBuff * sizeof(HKL), 1);
     }
-    else
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
-        _SEH2_TRY
-        {
-            ProbeForWrite(pHklBuff, nBuff*sizeof(HKL), 4);
+        SetLastNtError(_SEH2_GetExceptionCode());
+        goto Quit;
+    }
+    _SEH2_END;
 
-            while (uRet < nBuff)
-            {
-                pHklBuff[uRet] = pKl->hkl;
-                uRet++;
-                pKl = pKl->pklNext;
-                if (pKl == gspklBaseLayout)
-                    break;
-            }
-        }
-        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-        {
-            SetLastNtError(_SEH2_GetExceptionCode());
-            uRet = 0;
-        }
-        _SEH2_END;
+    pWinSta = IntGetProcessWindowStation(NULL);
+
+    _SEH2_TRY
+    {
+        ret = IntGetKeyboardLayoutList(pWinSta, nBuff, pHklBuff);
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        SetLastNtError(_SEH2_GetExceptionCode());
+        goto Quit;
     }
+    _SEH2_END;
 
+Quit:
     UserLeave();
-    return uRet;
+    return ret;
 }
 
 /*
index 4c91558..b4c31dc 100644 (file)
@@ -395,6 +395,18 @@ CheckWinstaAttributeAccess(ACCESS_MASK DesiredAccess)
     return TRUE;
 }
 
+// Win: _GetProcessWindowStation
+PWINSTATION_OBJECT FASTCALL
+IntGetProcessWindowStation(HWINSTA *phWinSta OPTIONAL)
+{
+    PWINSTATION_OBJECT pWinSta;
+    PPROCESSINFO ppi = GetW32ProcessInfo();
+    HWINSTA hWinSta = ppi->hwinsta;
+    if (phWinSta)
+        *phWinSta = hWinSta;
+    IntValidateWindowStationHandle(hWinSta, UserMode, 0, &pWinSta, 0);
+    return pWinSta;
+}
 
 /* PUBLIC FUNCTIONS ***********************************************************/
 
index 2918ca5..e755dad 100644 (file)
@@ -106,6 +106,7 @@ IntCreateWindowStation(
     DWORD Unknown5,
     DWORD Unknown6);
 
+PWINSTATION_OBJECT FASTCALL IntGetProcessWindowStation(HWINSTA *phWinSta OPTIONAL);
 BOOL FASTCALL UserSetProcessWindowStation(HWINSTA hWindowStation);
 
 BOOL FASTCALL co_IntInitializeDesktopGraphics(VOID);