Implement NtUserUnloadKeyboardLayout()

svn path=/trunk/; revision=26233
This commit is contained in:
Saveliy Tretiakov 2007-04-01 17:30:44 +00:00
parent 36af38d7dd
commit 9e8d69fa5d
4 changed files with 92 additions and 29 deletions

View file

@ -1923,10 +1923,10 @@ NTAPI
NtUserUnhookWinEvent( NtUserUnhookWinEvent(
DWORD Unknown0); DWORD Unknown0);
DWORD BOOL
NTAPI NTAPI
NtUserUnloadKeyboardLayout( NtUserUnloadKeyboardLayout(
DWORD Unknown0); HKL hKl);
BOOL BOOL
NTAPI NTAPI

View file

@ -15,8 +15,9 @@ typedef struct _KBL
DWORD klid; // Low word - language id. High word - device id. DWORD klid; // Low word - language id. High word - device id.
} KBL, *PKBL; } KBL, *PKBL;
#define KBL_UNLOADED 0x20000000 #define KBL_UNLOAD 1
#define KBL_RESET 0x40000000 #define KBL_PRELOAD 2
#define KBL_RESET 4
NTSTATUS FASTCALL NTSTATUS FASTCALL
InitInputImpl(VOID); InitInputImpl(VOID);

View file

@ -262,6 +262,8 @@ BOOL UserInitDefaultKeyboardLayout()
} }
} }
KBLList->Flags |= KBL_PRELOAD;
InitializeListHead(&KBLList->List); InitializeListHead(&KBLList->List);
return TRUE; return TRUE;
} }
@ -318,17 +320,56 @@ static PKBL UserHklToKbl(HKL hKl)
return NULL; 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; PKBL Prev;
Prev = Thread->KeyboardLayout; Prev = w32Thread->KeyboardLayout;
Prev->RefCount--; Prev->RefCount--;
Thread->KeyboardLayout = pKbl; w32Thread->KeyboardLayout = pKbl;
pKbl->RefCount++; 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 // Send WM_INPUTLANGCHANGE to thread's focus window
co_IntSendMessage(Thread->MessageQueue->FocusWindow, co_IntSendMessage(w32Thread->MessageQueue->FocusWindow,
WM_INPUTLANGCHANGE, WM_INPUTLANGCHANGE,
0, // FIXME: put charset here (what is this?) 0, // FIXME: put charset here (what is this?)
(LPARAM)pKbl->hkl); //klid (LPARAM)pKbl->hkl); //klid
@ -394,10 +435,13 @@ NtUserGetKeyboardLayoutList(
while(Ret < nItems) while(Ret < nItems)
{ {
pHklBuff[Ret] = pKbl->hkl; if(!(pKbl->Flags & KBL_UNLOAD))
Ret++; {
pKbl = (PKBL) pKbl->List.Flink; pHklBuff[Ret] = pKbl->hkl;
if(pKbl == KBLList) break; Ret++;
pKbl = (PKBL) pKbl->List.Flink;
if(pKbl == KBLList) break;
}
} }
} }
@ -457,18 +501,21 @@ NtUserLoadKeyboardLayoutEx(
UserEnterExclusive(); UserEnterExclusive();
//Let's see if layout was already loaded.
Cur = KBLList; Cur = KBLList;
do do
{ {
if(Cur->klid == dwKLID) if(Cur->klid == dwKLID)
{ {
pKbl = Cur; pKbl = Cur;
pKbl->Flags &= ~KBL_UNLOAD;
break; break;
} }
Cur = (PKBL) Cur->List.Flink; Cur = (PKBL) Cur->List.Flink;
} while(Cur != KBLList); } while(Cur != KBLList);
//It wasn't, so load it.
if(!pKbl) if(!pKbl)
{ {
pKbl = UserLoadDllAndCreateKbl(dwKLID); pKbl = UserLoadDllAndCreateKbl(dwKLID);
@ -485,14 +532,14 @@ NtUserLoadKeyboardLayoutEx(
if(Flags & KLF_ACTIVATE) if(Flags & KLF_ACTIVATE)
{ {
co_UserActivateKbl(PsGetCurrentThreadWin32Thread(), pKbl); co_UserActivateKbl(PsGetCurrentThreadWin32Thread(), pKbl, Flags);
} }
Ret = pKbl->hkl; Ret = pKbl->hkl;
//FIXME: Respect Flags! //FIXME: KLF_NOTELLSHELL
// KLF_NOTELLSHELL KLF_SETFORPROCESS // KLF_REPLACELANG
// KLF_REPLACELANG KLF_SUBSTITUTE_OK // KLF_SUBSTITUTE_OK
the_end: the_end:
UserLeave(); UserLeave();
@ -530,7 +577,6 @@ NtUserActivateKeyboardLayout(
else pKbl = UserHklToKbl(hKl); else pKbl = UserHklToKbl(hKl);
//FIXME: KLF_RESET, KLF_SHIFTLOCK //FIXME: KLF_RESET, KLF_SHIFTLOCK
//FIXME: KLF_SETFORPROCESS
if(pKbl) if(pKbl)
{ {
@ -543,15 +589,41 @@ NtUserActivateKeyboardLayout(
} }
else else
{ {
pKbl = co_UserActivateKbl(pWThread, pKbl); pKbl = co_UserActivateKbl(pWThread, pKbl, Flags);
Ret = pKbl->hkl; Ret = pKbl->hkl;
} }
} }
else
{
DPRINT1("%s: Invalid HKL %x!\n", __FUNCTION__, hKl);
}
the_end: the_end:
UserLeave(); UserLeave();
return Ret; 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 */ /* EOF */

View file

@ -616,16 +616,6 @@ NtUserTrackMouseEvent(
return 0; return 0;
} }
DWORD
STDCALL
NtUserUnloadKeyboardLayout(
DWORD Unknown0)
{
UNIMPLEMENTED
return 0;
}
DWORD DWORD
STDCALL STDCALL