diff --git a/reactos/include/reactos/win32k/ntuser.h b/reactos/include/reactos/win32k/ntuser.h index a7f00c11bf5..dec3284547e 100644 --- a/reactos/include/reactos/win32k/ntuser.h +++ b/reactos/include/reactos/win32k/ntuser.h @@ -1923,10 +1923,10 @@ NTAPI NtUserUnhookWinEvent( DWORD Unknown0); -DWORD +BOOL NTAPI NtUserUnloadKeyboardLayout( - DWORD Unknown0); + HKL hKl); BOOL NTAPI diff --git a/reactos/subsystems/win32/win32k/include/input.h b/reactos/subsystems/win32/win32k/include/input.h index 20c9487a6f1..c03bc0250d3 100644 --- a/reactos/subsystems/win32/win32k/include/input.h +++ b/reactos/subsystems/win32/win32k/include/input.h @@ -15,8 +15,9 @@ typedef struct _KBL DWORD klid; // Low word - language id. High word - device id. } KBL, *PKBL; -#define KBL_UNLOADED 0x20000000 -#define KBL_RESET 0x40000000 +#define KBL_UNLOAD 1 +#define KBL_PRELOAD 2 +#define KBL_RESET 4 NTSTATUS FASTCALL InitInputImpl(VOID); diff --git a/reactos/subsystems/win32/win32k/ntuser/kbdlayout.c b/reactos/subsystems/win32/win32k/ntuser/kbdlayout.c index 564f79f5d22..07cd5ac3c24 100644 --- a/reactos/subsystems/win32/win32k/ntuser/kbdlayout.c +++ b/reactos/subsystems/win32/win32k/ntuser/kbdlayout.c @@ -156,7 +156,7 @@ static BOOL UserLoadKbdDll(WCHAR *wsKLID, RtlFreeUnicodeString(&LayoutFile); *phModule = EngLoadImage(FullLayoutPath.Buffer); - + if(*phModule) { DPRINT("Loaded %wZ\n", &FullLayoutPath); @@ -262,6 +262,8 @@ BOOL UserInitDefaultKeyboardLayout() } } + KBLList->Flags |= KBL_PRELOAD; + InitializeListHead(&KBLList->List); return TRUE; } @@ -318,17 +320,56 @@ static PKBL UserHklToKbl(HKL hKl) return NULL; } -static PKBL co_UserActivateKbl(PW32THREAD Thread, PKBL pKbl) +BOOL UserUnloadKbl(PKBL pKbl) +{ + /* According to msdn, UnloadKeyboardLayout can fail + if the keyboard layout identifier was preloaded. */ + + if(pKbl->Flags & KBL_PRELOAD) + { + DPRINT1("Attempted to unload preloaded keyboard layout.\n"); + return FALSE; + } + + if(pKbl->RefCount > 0) + { + /* Layout is used by other threads. + Mark it as unloaded and don't do anything else. */ + pKbl->Flags |= KBL_UNLOAD; + } + else + { + //Unload the layout + EngUnloadImage(pKbl->hModule); + RemoveEntryList(&pKbl->List); + ExFreePool(pKbl); + } + + return TRUE; +} + +static PKBL co_UserActivateKbl(PW32THREAD w32Thread, PKBL pKbl, UINT Flags) { PKBL Prev; - Prev = Thread->KeyboardLayout; + Prev = w32Thread->KeyboardLayout; Prev->RefCount--; - Thread->KeyboardLayout = pKbl; + w32Thread->KeyboardLayout = pKbl; pKbl->RefCount++; + if(Flags & KLF_SETFORPROCESS) + { + //FIXME + + } + + if(Prev->Flags & KBL_UNLOAD && Prev->RefCount == 0) + { + UserUnloadKbl(Prev); + } + // Send WM_INPUTLANGCHANGE to thread's focus window - co_IntSendMessage(Thread->MessageQueue->FocusWindow, + co_IntSendMessage(w32Thread->MessageQueue->FocusWindow, WM_INPUTLANGCHANGE, 0, // FIXME: put charset here (what is this?) (LPARAM)pKbl->hkl); //klid @@ -394,10 +435,13 @@ NtUserGetKeyboardLayoutList( while(Ret < nItems) { - pHklBuff[Ret] = pKbl->hkl; - Ret++; - pKbl = (PKBL) pKbl->List.Flink; - if(pKbl == KBLList) break; + if(!(pKbl->Flags & KBL_UNLOAD)) + { + pHklBuff[Ret] = pKbl->hkl; + Ret++; + pKbl = (PKBL) pKbl->List.Flink; + if(pKbl == KBLList) break; + } } } @@ -457,18 +501,21 @@ NtUserLoadKeyboardLayoutEx( UserEnterExclusive(); + //Let's see if layout was already loaded. Cur = KBLList; do { if(Cur->klid == dwKLID) { pKbl = Cur; + pKbl->Flags &= ~KBL_UNLOAD; break; } Cur = (PKBL) Cur->List.Flink; } while(Cur != KBLList); + //It wasn't, so load it. if(!pKbl) { pKbl = UserLoadDllAndCreateKbl(dwKLID); @@ -485,14 +532,14 @@ NtUserLoadKeyboardLayoutEx( if(Flags & KLF_ACTIVATE) { - co_UserActivateKbl(PsGetCurrentThreadWin32Thread(), pKbl); + co_UserActivateKbl(PsGetCurrentThreadWin32Thread(), pKbl, Flags); } Ret = pKbl->hkl; - //FIXME: Respect Flags! - // KLF_NOTELLSHELL KLF_SETFORPROCESS - // KLF_REPLACELANG KLF_SUBSTITUTE_OK + //FIXME: KLF_NOTELLSHELL + // KLF_REPLACELANG + // KLF_SUBSTITUTE_OK the_end: UserLeave(); @@ -530,7 +577,6 @@ NtUserActivateKeyboardLayout( else pKbl = UserHklToKbl(hKl); //FIXME: KLF_RESET, KLF_SHIFTLOCK - //FIXME: KLF_SETFORPROCESS if(pKbl) { @@ -543,15 +589,41 @@ NtUserActivateKeyboardLayout( } else { - pKbl = co_UserActivateKbl(pWThread, pKbl); + pKbl = co_UserActivateKbl(pWThread, pKbl, Flags); Ret = pKbl->hkl; } } + else + { + DPRINT1("%s: Invalid HKL %x!\n", __FUNCTION__, hKl); + } the_end: UserLeave(); return Ret; } +BOOL +STDCALL +NtUserUnloadKeyboardLayout( + HKL hKl) +{ + PKBL pKbl; + BOOL Ret = FALSE; + + UserEnterExclusive(); + + if((pKbl = UserHklToKbl(hKl))) + { + Ret = UserUnloadKbl(pKbl); + } + else + { + DPRINT1("%s: Invalid HKL %x!\n", __FUNCTION__, hKl); + } + + UserLeave(); + return Ret; +} /* EOF */ diff --git a/reactos/subsystems/win32/win32k/ntuser/ntstubs.c b/reactos/subsystems/win32/win32k/ntuser/ntstubs.c index f0858e12edc..71fbe2718ab 100644 --- a/reactos/subsystems/win32/win32k/ntuser/ntstubs.c +++ b/reactos/subsystems/win32/win32k/ntuser/ntstubs.c @@ -616,16 +616,6 @@ NtUserTrackMouseEvent( return 0; } -DWORD -STDCALL -NtUserUnloadKeyboardLayout( - DWORD Unknown0) -{ - UNIMPLEMENTED - - return 0; -} - DWORD STDCALL