2 * PROJECT: ReactOS IMM32
3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4 * PURPOSE: Implementing IME manipulation of IMM32
5 * COPYRIGHT: Copyright 1998 Patrik Stridvall
6 * Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart
7 * Copyright 2017 James Tabor <james.tabor@reactos.org>
8 * Copyright 2018 Amine Khaldi <amine.khaldi@reactos.org>
9 * Copyright 2020-2022 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
14 WINE_DEFAULT_DEBUG_CHANNEL(imm
);
16 RTL_CRITICAL_SECTION gcsImeDpi
; // Win: gcsImeDpi
17 PIMEDPI gpImeDpiList
= NULL
; // Win: gpImeDpi
20 PIMEDPI APIENTRY
Imm32FindImeDpi(HKL hKL
)
24 RtlEnterCriticalSection(&gcsImeDpi
);
25 for (pImeDpi
= gpImeDpiList
; pImeDpi
!= NULL
; pImeDpi
= pImeDpi
->pNext
)
27 if (pImeDpi
->hKL
== hKL
)
30 RtlLeaveCriticalSection(&gcsImeDpi
);
36 VOID APIENTRY
Imm32FreeIME(PIMEDPI pImeDpi
, BOOL bDestroy
)
38 if (pImeDpi
->hInst
== NULL
)
41 pImeDpi
->ImeDestroy(0);
42 FreeLibrary(pImeDpi
->hInst
);
43 pImeDpi
->hInst
= NULL
;
47 BOOL APIENTRY
Imm32InquireIme(PIMEDPI pImeDpi
)
51 DWORD dwSysInfoFlags
= 0;
52 LPIMEINFO pImeInfo
= &pImeDpi
->ImeInfo
;
54 if (NtUserGetThreadState(THREADSTATE_ISWINLOGON2
))
55 dwSysInfoFlags
|= IME_SYSINFO_WINLOGON
;
57 if (GetWin32ClientInfo()->dwTIFlags
& TIF_16BIT
)
58 dwSysInfoFlags
|= IME_SYSINFO_WOW16
;
60 if (IS_IME_HKL(pImeDpi
->hKL
))
62 if (!pImeDpi
->ImeInquire(pImeInfo
, szUIClass
, dwSysInfoFlags
))
68 else if (IS_CICERO_MODE() && !IS_16BIT_MODE())
70 if (pImeDpi
->CtfImeInquireExW(pImeInfo
, szUIClass
, dwSysInfoFlags
, pImeDpi
->hKL
) != S_OK
)
82 szUIClass
[_countof(szUIClass
) - 1] = UNICODE_NULL
; /* Avoid buffer overrun */
84 if (pImeInfo
->dwPrivateDataSize
< sizeof(DWORD
))
85 pImeInfo
->dwPrivateDataSize
= sizeof(DWORD
);
87 #define VALID_IME_PROP (IME_PROP_AT_CARET | \
88 IME_PROP_SPECIAL_UI | \
89 IME_PROP_CANDLIST_START_FROM_1 | \
91 IME_PROP_COMPLETE_ON_UNSELECT | \
92 IME_PROP_END_UNLOAD | \
93 IME_PROP_KBD_CHAR_FIRST | \
94 IME_PROP_IGNORE_UPKEYS | \
95 IME_PROP_NEED_ALTKEY | \
96 IME_PROP_NO_KEYS_ON_CLOSE | \
97 IME_PROP_ACCEPT_WIDE_VKEY)
98 #define VALID_CMODE_CAPS (IME_CMODE_ALPHANUMERIC | \
100 IME_CMODE_KATAKANA | \
101 IME_CMODE_LANGUAGE | \
102 IME_CMODE_FULLSHAPE | \
104 IME_CMODE_CHARCODE | \
105 IME_CMODE_HANJACONVERT | \
106 IME_CMODE_SOFTKBD | \
107 IME_CMODE_NOCONVERSION | \
111 #define VALID_SMODE_CAPS (IME_SMODE_NONE | \
112 IME_SMODE_PLAURALCLAUSE | \
113 IME_SMODE_SINGLECONVERT | \
114 IME_SMODE_AUTOMATIC | \
115 IME_SMODE_PHRASEPREDICT | \
116 IME_SMODE_CONVERSATION)
117 #define VALID_UI_CAPS (UI_CAP_2700 | \
121 #define VALID_SCS_CAPS (SCS_CAP_COMPSTR | \
123 SCS_CAP_SETRECONVERTSTRING)
124 #define VALID_SELECT_CAPS (SELECT_CAP_CONVERSION | SELECT_CAP_SENTENCE)
126 if (pImeInfo
->fdwProperty
& ~VALID_IME_PROP
)
131 if (pImeInfo
->fdwConversionCaps
& ~VALID_CMODE_CAPS
)
136 if (pImeInfo
->fdwSentenceCaps
& ~VALID_SMODE_CAPS
)
141 if (pImeInfo
->fdwUICaps
& ~VALID_UI_CAPS
)
146 if (pImeInfo
->fdwSCSCaps
& ~VALID_SCS_CAPS
)
151 if (pImeInfo
->fdwSelectCaps
& ~VALID_SELECT_CAPS
)
157 #undef VALID_IME_PROP
158 #undef VALID_CMODE_CAPS
159 #undef VALID_SMODE_CAPS
161 #undef VALID_SCS_CAPS
162 #undef VALID_SELECT_CAPS
164 if (pImeInfo
->fdwProperty
& IME_PROP_UNICODE
)
166 StringCchCopyW(pImeDpi
->szUIClass
, _countof(pImeDpi
->szUIClass
), szUIClass
);
170 if (pImeDpi
->uCodePage
!= GetACP() && pImeDpi
->uCodePage
!= CP_ACP
)
173 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, (LPSTR
)szUIClass
, -1,
174 pImeDpi
->szUIClass
, _countof(pImeDpi
->szUIClass
));
176 pImeDpi
->szUIClass
[_countof(pImeDpi
->szUIClass
) - 1] = UNICODE_NULL
;
179 if (!GetClassInfoW(pImeDpi
->hInst
, pImeDpi
->szUIClass
, &wcW
))
188 /* Define stub IME functions */
189 #define DEFINE_IME_ENTRY(type, name, params, optional) \
190 type APIENTRY Stub##name params { \
191 FIXME("%s: Why stub called?\n", #name); \
194 #include <imetable.h>
195 #undef DEFINE_IME_ENTRY
198 BOOL APIENTRY
Imm32LoadIME(PIMEINFOEX pImeInfoEx
, PIMEDPI pImeDpi
)
200 WCHAR szPath
[MAX_PATH
];
205 if (!Imm32GetSystemLibraryPath(szPath
, _countof(szPath
), pImeInfoEx
->wszImeFile
))
208 pImeDpi
->hInst
= hIME
= LoadLibraryW(szPath
);
211 ERR("LoadLibraryW(%s) failed\n", debugstr_w(szPath
));
215 /* Populate the table by stub IME functions */
216 #define DEFINE_IME_ENTRY(type, name, params, optional) pImeDpi->name = Stub##name;
217 #include <imetable.h>
218 #undef DEFINE_IME_ENTRY
220 /* Populate the table by real IME functions */
221 #define DEFINE_IME_ENTRY(type, name, params, optional) \
223 fn = GetProcAddress(hIME, #name); \
224 if (fn) pImeDpi->name = (FN_##name)fn; \
225 else if (!(optional)) { \
226 ERR("'%s' not found in IME module '%s'.\n", #name, debugstr_w(szPath)); \
230 #include <imetable.h>
231 #undef DEFINE_IME_ENTRY
233 if (Imm32InquireIme(pImeDpi
))
241 FreeLibrary(pImeDpi
->hInst
);
242 pImeDpi
->hInst
= NULL
;
245 if (pImeInfoEx
->fLoadFlag
== 0)
249 C_ASSERT(sizeof(pImeInfoEx
->wszUIClass
) == sizeof(pImeDpi
->szUIClass
));
250 pImeInfoEx
->ImeInfo
= pImeDpi
->ImeInfo
;
251 RtlCopyMemory(pImeInfoEx
->wszUIClass
, pImeDpi
->szUIClass
,
252 sizeof(pImeInfoEx
->wszUIClass
));
253 pImeInfoEx
->fLoadFlag
= 2;
257 pImeInfoEx
->fLoadFlag
= 1;
260 NtUserSetImeInfoEx(pImeInfoEx
);
267 PIMEDPI APIENTRY
Imm32LoadImeDpi(HKL hKL
, BOOL bLock
)
271 PIMEDPI pImeDpiNew
, pImeDpiFound
;
275 if (!IS_IME_HKL(hKL
))
281 if (!ImmGetImeInfoEx(&ImeInfoEx
, ImeInfoExKeyboardLayout
, &hKL
))
287 if (ImeInfoEx
.fLoadFlag
== 1)
293 pImeDpiNew
= ImmLocalAlloc(HEAP_ZERO_MEMORY
, sizeof(IMEDPI
));
294 if (IS_NULL_UNEXPECTEDLY(pImeDpiNew
))
297 pImeDpiNew
->hKL
= hKL
;
300 if (TranslateCharsetInfo((LPDWORD
)(DWORD_PTR
)lcid
, &ci
, TCI_SRCLOCALE
))
301 uCodePage
= ci
.ciACP
;
304 pImeDpiNew
->uCodePage
= uCodePage
;
306 if (!Imm32LoadIME(&ImeInfoEx
, pImeDpiNew
))
309 ImmLocalFree(pImeDpiNew
);
313 RtlEnterCriticalSection(&gcsImeDpi
);
315 pImeDpiFound
= Imm32FindImeDpi(hKL
);
319 pImeDpiFound
->dwFlags
&= ~IMEDPI_FLAG_LOCKED
;
321 RtlLeaveCriticalSection(&gcsImeDpi
);
322 Imm32FreeIME(pImeDpiNew
, FALSE
);
323 ImmLocalFree(pImeDpiNew
);
330 pImeDpiNew
->dwFlags
|= IMEDPI_FLAG_LOCKED
;
331 pImeDpiNew
->cLockObj
= 1;
334 pImeDpiNew
->pNext
= gpImeDpiList
;
335 gpImeDpiList
= pImeDpiNew
;
337 RtlLeaveCriticalSection(&gcsImeDpi
);
342 // Win: FindOrLoadImeDpi
343 PIMEDPI APIENTRY
Imm32FindOrLoadImeDpi(HKL hKL
)
347 if (!IS_IME_HKL(hKL
) && (!IS_CICERO_MODE() || IS_16BIT_MODE()))
353 pImeDpi
= ImmLockImeDpi(hKL
);
355 pImeDpi
= Imm32LoadImeDpi(hKL
, TRUE
);
359 static LRESULT APIENTRY
360 ImeDpi_Escape(PIMEDPI pImeDpi
, HIMC hIMC
, UINT uSubFunc
, LPVOID lpData
, HKL hKL
)
363 return pImeDpi
->ImeEscape(hIMC
, uSubFunc
, lpData
);
364 if (IS_CICERO_MODE() && !IS_16BIT_MODE())
365 return pImeDpi
->CtfImeEscapeEx(hIMC
, uSubFunc
, lpData
, hKL
);
371 BOOL APIENTRY
Imm32ReleaseIME(HKL hKL
)
374 PIMEDPI pImeDpi0
, pImeDpi1
;
376 RtlEnterCriticalSection(&gcsImeDpi
);
378 for (pImeDpi0
= gpImeDpiList
; pImeDpi0
; pImeDpi0
= pImeDpi0
->pNext
)
380 if (pImeDpi0
->hKL
== hKL
)
387 if (pImeDpi0
->cLockObj
)
389 pImeDpi0
->dwFlags
|= IMEDPI_FLAG_UNLOADED
;
394 if (gpImeDpiList
== pImeDpi0
)
396 gpImeDpiList
= pImeDpi0
->pNext
;
398 else if (gpImeDpiList
)
400 for (pImeDpi1
= gpImeDpiList
; pImeDpi1
; pImeDpi1
= pImeDpi1
->pNext
)
402 if (pImeDpi1
->pNext
== pImeDpi0
)
404 pImeDpi1
->pNext
= pImeDpi0
->pNext
;
410 Imm32FreeIME(pImeDpi0
, TRUE
);
411 ImmLocalFree(pImeDpi0
);
414 RtlLeaveCriticalSection(&gcsImeDpi
);
418 // We will transport the IME menu items by using a flat memory block via
419 // a file mapping object beyond the boundary of a process.
421 #define MAX_IMEMENU_BITMAP_BYTES 0xF00
423 typedef struct tagIMEMENUITEM
425 IMEMENUITEMINFOW Info
;
426 BYTE abChecked
[MAX_IMEMENU_BITMAP_BYTES
];
427 BYTE abUnchecked
[MAX_IMEMENU_BITMAP_BYTES
];
428 BYTE abItem
[MAX_IMEMENU_BITMAP_BYTES
];
429 } IMEMENUITEM
, *PIMEMENUITEM
;
431 typedef struct tagIMEMENU
437 IMEMENUITEMINFOW Parent
;
438 IMEMENUITEM Items
[ANYSIZE_ARRAY
];
439 } IMEMENU
, *PIMEMENU
;
441 /***********************************************************************
442 * ImmPutImeMenuItemsIntoMappedFile (IMM32.@)
444 * Called from user32.dll to transport the IME menu items by using a
445 * file mapping object. This function is provided for WM_IME_SYSTEM:IMS_GETIMEMENU
448 LRESULT WINAPI
ImmPutImeMenuItemsIntoMappedFile(HIMC hIMC
)
453 LPIMEMENUITEMINFOW pParent
= NULL
, pItems
= NULL
;
454 DWORD i
, cItems
, cbItems
= 0;
456 hMapping
= OpenFileMappingW(FILE_MAP_ALL_ACCESS
, FALSE
, L
"ImmMenuInfo");
457 pView
= MapViewOfFile(hMapping
, FILE_MAP_ALL_ACCESS
, 0, 0, 0);
458 if (IS_NULL_UNEXPECTEDLY(pView
))
461 if (pView
->dwVersion
!= 1)
467 if (pView
->Parent
.cbSize
> 0)
468 pParent
= &pView
->Parent
;
470 if (pView
->dwItemCount
> 0)
472 cbItems
= pView
->dwItemCount
* sizeof(IMEMENUITEMINFOW
);
473 pItems
= ImmLocalAlloc(HEAP_ZERO_MEMORY
, cbItems
);
474 if (IS_NULL_UNEXPECTEDLY(pItems
))
478 cItems
= ImmGetImeMenuItemsW(hIMC
, pView
->dwFlags
, pView
->dwType
, pParent
, pItems
, cbItems
);
479 pView
->dwItemCount
= cItems
;
480 if (IS_ZERO_UNEXPECTEDLY(cItems
))
485 for (i
= 0; i
< cItems
; ++i
)
487 pView
->Items
[i
].Info
= pItems
[i
];
489 // store bitmaps to bytes
490 if (pItems
[i
].hbmpChecked
)
492 Imm32StoreBitmapToBytes(pItems
[i
].hbmpChecked
, pView
->Items
[i
].abChecked
,
493 MAX_IMEMENU_BITMAP_BYTES
);
494 DeleteObject(pItems
[i
].hbmpChecked
);
496 if (pItems
[i
].hbmpUnchecked
)
498 Imm32StoreBitmapToBytes(pItems
[i
].hbmpUnchecked
, pView
->Items
[i
].abUnchecked
,
499 MAX_IMEMENU_BITMAP_BYTES
);
500 DeleteObject(pItems
[i
].hbmpUnchecked
);
502 if (pItems
[i
].hbmpItem
)
504 Imm32StoreBitmapToBytes(pItems
[i
].hbmpItem
, pView
->Items
[i
].abItem
,
505 MAX_IMEMENU_BITMAP_BYTES
);
506 DeleteObject(pItems
[i
].hbmpItem
);
515 ImmLocalFree(pItems
);
517 UnmapViewOfFile(pView
);
519 CloseHandle(hMapping
);
523 // Win: ImmGetImeMenuItemsInterProcess
525 Imm32GetImeMenuItemWInterProcess(HIMC hIMC
, DWORD dwFlags
, DWORD dwType
, LPVOID lpImeParentMenu
,
526 LPVOID lpImeMenu
, DWORD dwSize
)
530 DWORD i
, cbView
, dwItemCount
, ret
= 0;
532 PIMEMENUITEM pGotItem
;
533 LPIMEMENUITEMINFOW pSetInfo
;
535 hImeWnd
= (HWND
)NtUserQueryInputContext(hIMC
, QIC_DEFAULTWINDOWIME
);
536 if (!hImeWnd
|| !IsWindow(hImeWnd
))
542 dwItemCount
= (lpImeMenu
? (dwSize
/ sizeof(IMEMENUITEMINFOW
)) : 0);
543 cbView
= sizeof(IMEMENU
) + ((size_t)dwItemCount
- 1) * sizeof(IMEMENUITEM
);
545 RtlEnterCriticalSection(&gcsImeDpi
);
547 // create a file mapping
548 hMapping
= CreateFileMappingW(INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
,
549 0, cbView
, L
"ImmMenuInfo");
550 pView
= MapViewOfFile(hMapping
, FILE_MAP_READ
| FILE_MAP_WRITE
, 0, 0, 0);
551 if (IS_NULL_UNEXPECTEDLY(pView
))
554 ZeroMemory(pView
, cbView
);
555 pView
->dwVersion
= 1;
556 pView
->dwFlags
= dwFlags
;
557 pView
->dwType
= dwType
;
558 pView
->dwItemCount
= dwItemCount
;
561 pView
->Parent
= *(LPIMEMENUITEMINFOW
)lpImeParentMenu
;
562 pView
->Parent
.cbSize
= sizeof(IMEMENUITEMINFOW
);
565 if (!SendMessageW(hImeWnd
, WM_IME_SYSTEM
, IMS_GETIMEMENU
, (LPARAM
)hIMC
))
571 ret
= pView
->dwItemCount
;
576 for (i
= 0; i
< ret
; ++i
)
578 pGotItem
= &(pView
->Items
[i
]);
579 pSetInfo
= &((LPIMEMENUITEMINFOW
)lpImeMenu
)[i
];
581 *pSetInfo
= pGotItem
->Info
;
583 // load bitmaps from bytes
584 if (pSetInfo
->hbmpChecked
)
586 pSetInfo
->hbmpChecked
= Imm32LoadBitmapFromBytes(pGotItem
->abChecked
);
588 if (pSetInfo
->hbmpUnchecked
)
590 pSetInfo
->hbmpUnchecked
= Imm32LoadBitmapFromBytes(pGotItem
->abUnchecked
);
592 if (pSetInfo
->hbmpItem
)
594 pSetInfo
->hbmpItem
= Imm32LoadBitmapFromBytes(pGotItem
->abItem
);
599 RtlLeaveCriticalSection(&gcsImeDpi
);
601 UnmapViewOfFile(pView
);
603 CloseHandle(hMapping
);
607 // Win: ImmGetImeMenuItemsWorker
609 ImmGetImeMenuItemsAW(HIMC hIMC
, DWORD dwFlags
, DWORD dwType
, LPVOID lpImeParentMenu
,
610 LPVOID lpImeMenu
, DWORD dwSize
, BOOL bTargetIsAnsi
)
612 DWORD ret
= 0, cbTotal
, dwProcessId
, dwThreadId
, iItem
;
614 PIMEDPI pImeDpi
= NULL
;
615 IMEMENUITEMINFOA ParentA
;
616 IMEMENUITEMINFOW ParentW
;
617 LPIMEMENUITEMINFOA pItemA
;
618 LPIMEMENUITEMINFOW pItemW
;
619 LPVOID pNewItems
= NULL
, pNewParent
= NULL
;
623 if (IS_NULL_UNEXPECTEDLY(hIMC
))
626 dwProcessId
= (DWORD
)NtUserQueryInputContext(hIMC
, QIC_INPUTPROCESSID
);
627 if (IS_ZERO_UNEXPECTEDLY(dwProcessId
))
630 if (dwProcessId
!= GetCurrentProcessId())
634 return Imm32GetImeMenuItemWInterProcess(hIMC
, dwFlags
, dwType
, lpImeParentMenu
,
638 pIC
= ImmLockIMC(hIMC
);
639 if (IS_NULL_UNEXPECTEDLY(pIC
))
642 dwThreadId
= (DWORD
)NtUserQueryInputContext(hIMC
, QIC_INPUTTHREADID
);
643 if (IS_ZERO_UNEXPECTEDLY(dwThreadId
))
649 hKL
= GetKeyboardLayout(dwThreadId
);
650 pImeDpi
= ImmLockImeDpi(hKL
);
651 if (IS_NULL_UNEXPECTEDLY(pImeDpi
))
657 bImcIsAnsi
= Imm32IsImcAnsi(hIMC
);
659 if (bImcIsAnsi
!= bTargetIsAnsi
)
664 pNewParent
= &ParentW
;
668 cbTotal
= ((dwSize
/ sizeof(IMEMENUITEMINFOA
)) * sizeof(IMEMENUITEMINFOW
));
669 pNewItems
= ImmLocalAlloc(0, cbTotal
);
670 if (IS_NULL_UNEXPECTEDLY(pNewItems
))
677 pNewParent
= &ParentA
;
681 cbTotal
= ((dwSize
/ sizeof(IMEMENUITEMINFOW
)) * sizeof(IMEMENUITEMINFOA
));
682 pNewItems
= ImmLocalAlloc(0, cbTotal
);
683 if (IS_NULL_UNEXPECTEDLY(pNewItems
))
690 pNewItems
= lpImeMenu
;
691 pNewParent
= lpImeParentMenu
;
694 ret
= pImeDpi
->ImeGetImeMenuItems(hIMC
, dwFlags
, dwType
, pNewParent
, pNewItems
, dwSize
);
695 if (IS_ZERO_UNEXPECTEDLY(ret
) || !lpImeMenu
)
698 if (bImcIsAnsi
!= bTargetIsAnsi
)
703 Imm32ImeMenuWideToAnsi(pNewParent
, lpImeParentMenu
, pImeDpi
->uCodePage
);
707 for (iItem
= 0; iItem
< ret
; ++iItem
, ++pItemW
, ++pItemA
)
709 if (!Imm32ImeMenuWideToAnsi(pItemW
, pItemA
, pImeDpi
->uCodePage
))
720 Imm32ImeMenuAnsiToWide(pNewParent
, lpImeParentMenu
, pImeDpi
->uCodePage
, TRUE
);
724 for (iItem
= 0; iItem
< dwSize
; ++iItem
, ++pItemA
, ++pItemW
)
726 if (!Imm32ImeMenuAnsiToWide(pItemA
, pItemW
, pImeDpi
->uCodePage
, TRUE
))
737 if (pNewItems
!= lpImeMenu
)
738 ImmLocalFree(pNewItems
);
739 ImmUnlockImeDpi(pImeDpi
);
741 TRACE("ret: 0x%X\n", ret
);
745 /***********************************************************************
746 * ImmInstallIMEA (IMM32.@)
748 HKL WINAPI
ImmInstallIMEA(LPCSTR lpszIMEFileName
, LPCSTR lpszLayoutText
)
751 LPWSTR pszFileNameW
= NULL
, pszLayoutTextW
= NULL
;
753 TRACE("(%s, %s)\n", debugstr_a(lpszIMEFileName
), debugstr_a(lpszLayoutText
));
755 pszFileNameW
= Imm32WideFromAnsi(CP_ACP
, lpszIMEFileName
);
756 if (IS_NULL_UNEXPECTEDLY(pszFileNameW
))
759 pszLayoutTextW
= Imm32WideFromAnsi(CP_ACP
, lpszLayoutText
);
760 if (IS_NULL_UNEXPECTEDLY(pszLayoutTextW
))
763 hKL
= ImmInstallIMEW(pszFileNameW
, pszLayoutTextW
);
766 ImmLocalFree(pszFileNameW
);
767 ImmLocalFree(pszLayoutTextW
);
771 /***********************************************************************
772 * ImmInstallIMEW (IMM32.@)
774 HKL WINAPI
ImmInstallIMEW(LPCWSTR lpszIMEFileName
, LPCWSTR lpszLayoutText
)
776 WCHAR szImeFileName
[MAX_PATH
], szImeDestPath
[MAX_PATH
], szImeKey
[20];
779 UINT iLayout
, cLayouts
;
782 PREG_IME pLayouts
= NULL
;
784 TRACE("(%s, %s)\n", debugstr_w(lpszIMEFileName
), debugstr_w(lpszLayoutText
));
786 GetFullPathNameW(lpszIMEFileName
, _countof(szImeFileName
), szImeFileName
, &pchFilePart
);
787 CharUpperW(szImeFileName
);
788 if (IS_NULL_UNEXPECTEDLY(pchFilePart
))
791 /* Load the IME version info */
792 InfoEx
.hkl
= hNewKL
= NULL
;
793 StringCchCopyW(InfoEx
.wszImeFile
, _countof(InfoEx
.wszImeFile
), pchFilePart
);
794 if (!Imm32LoadImeVerInfo(&InfoEx
) || !InfoEx
.hkl
)
799 wLangID
= LOWORD(InfoEx
.hkl
);
801 /* Get the IME layouts from registry */
802 cLayouts
= Imm32GetImeLayout(NULL
, 0);
805 pLayouts
= ImmLocalAlloc(0, cLayouts
* sizeof(REG_IME
));
806 if (IS_NULL_UNEXPECTEDLY(pLayouts
))
809 if (!Imm32GetImeLayout(pLayouts
, cLayouts
))
812 ImmLocalFree(pLayouts
);
816 for (iLayout
= 0; iLayout
< cLayouts
; ++iLayout
)
818 if (lstrcmpiW(pLayouts
[iLayout
].szFileName
, pchFilePart
) == 0)
820 if (wLangID
!= LOWORD(pLayouts
[iLayout
].hKL
))
823 goto Quit
; /* The language is different */
826 hNewKL
= pLayouts
[iLayout
].hKL
; /* Found */
832 /* If the IME for the specified filename is valid, then unload it now */
833 if (ImmGetImeInfoEx(&InfoEx
, ImeInfoExImeFileName
, pchFilePart
) &&
834 !UnloadKeyboardLayout(InfoEx
.hkl
))
841 Imm32GetSystemLibraryPath(szImeDestPath
, _countof(szImeDestPath
), pchFilePart
);
842 CharUpperW(szImeDestPath
);
844 /* If the source and the destination pathnames were different, then copy the IME file */
845 if (lstrcmpiW(szImeFileName
, szImeDestPath
) != 0 &&
846 !Imm32CopyImeFile(szImeFileName
, szImeDestPath
))
854 hNewKL
= Imm32AssignNewLayout(cLayouts
, pLayouts
, wLangID
);
858 /* Write the IME layout to registry */
859 if (Imm32WriteImeLayout(hNewKL
, pchFilePart
, lpszLayoutText
))
861 /* Load the keyboard layout */
862 StringCchPrintfW(szImeKey
, _countof(szImeKey
), L
"%08X", (DWORD
)(DWORD_PTR
)hNewKL
);
863 hNewKL
= LoadKeyboardLayoutW(szImeKey
, KLF_REPLACELANG
);
873 ImmLocalFree(pLayouts
);
877 /***********************************************************************
880 BOOL WINAPI
ImmIsIME(HKL hKL
)
883 TRACE("(%p)\n", hKL
);
884 return !!ImmGetImeInfoEx(&info
, ImeInfoExKeyboardLayoutTFS
, &hKL
);
887 /***********************************************************************
888 * ImmGetDefaultIMEWnd (IMM32.@)
890 HWND WINAPI
ImmGetDefaultIMEWnd(HWND hWnd
)
899 return (HWND
)NtUserGetThreadState(THREADSTATE_DEFAULTIMEWINDOW
);
901 return (HWND
)NtUserQueryWindow(hWnd
, QUERY_WINDOW_DEFAULT_IME
);
904 /***********************************************************************
905 * ImmNotifyIME (IMM32.@)
907 BOOL WINAPI
ImmNotifyIME(HIMC hIMC
, DWORD dwAction
, DWORD dwIndex
, DWORD_PTR dwValue
)
913 TRACE("(%p, %lu, %lu, %lu)\n", hIMC
, dwAction
, dwIndex
, dwValue
);
915 if (hIMC
&& IS_CROSS_THREAD_HIMC(hIMC
))
918 hKL
= GetKeyboardLayout(0);
919 pImeDpi
= ImmLockImeDpi(hKL
);
920 if (IS_NULL_UNEXPECTEDLY(pImeDpi
))
923 ret
= pImeDpi
->NotifyIME(hIMC
, dwAction
, dwIndex
, dwValue
);
924 ImmUnlockImeDpi(pImeDpi
);
928 /***********************************************************************
929 * ImmGetImeInfoEx (IMM32.@)
932 ImmGetImeInfoEx(PIMEINFOEX pImeInfoEx
, IMEINFOEXCLASS SearchType
, PVOID pvSearchKey
)
935 if (SearchType
== ImeInfoExKeyboardLayout
|| SearchType
== ImeInfoExKeyboardLayoutTFS
)
937 hKL
= *(HKL
*)pvSearchKey
;
938 pImeInfoEx
->hkl
= hKL
;
940 if (SearchType
== ImeInfoExKeyboardLayoutTFS
)
942 if (!IS_IME_HKL(hKL
))
944 if (CtfImmIsTextFrameServiceDisabled() || !IS_CICERO_MODE() || IS_16BIT_MODE())
951 SearchType
= ImeInfoExKeyboardLayout
;
955 if (!IS_IME_HKL(hKL
))
962 else if (SearchType
== ImeInfoExImeFileName
)
964 StringCchCopyW(pImeInfoEx
->wszImeFile
, _countof(pImeInfoEx
->wszImeFile
),
972 return NtUserGetImeInfoEx(pImeInfoEx
, SearchType
);
975 /***********************************************************************
976 * ImmLockImeDpi (IMM32.@)
978 PIMEDPI WINAPI
ImmLockImeDpi(HKL hKL
)
980 PIMEDPI pImeDpi
= NULL
;
982 TRACE("(%p)\n", hKL
);
984 RtlEnterCriticalSection(&gcsImeDpi
);
987 for (pImeDpi
= gpImeDpiList
; pImeDpi
; pImeDpi
= pImeDpi
->pNext
)
989 if (pImeDpi
->hKL
== hKL
) /* found */
991 /* lock if possible */
992 if (pImeDpi
->dwFlags
& IMEDPI_FLAG_UNLOADED
)
995 ++(pImeDpi
->cLockObj
);
1000 RtlLeaveCriticalSection(&gcsImeDpi
);
1004 /***********************************************************************
1005 * ImmUnlockImeDpi (IMM32.@)
1007 VOID WINAPI
ImmUnlockImeDpi(PIMEDPI pImeDpi
)
1011 TRACE("(%p)\n", pImeDpi
);
1013 if (pImeDpi
== NULL
)
1016 RtlEnterCriticalSection(&gcsImeDpi
);
1019 --(pImeDpi
->cLockObj
);
1020 if (pImeDpi
->cLockObj
!= 0)
1022 RtlLeaveCriticalSection(&gcsImeDpi
);
1026 if ((pImeDpi
->dwFlags
& IMEDPI_FLAG_UNLOADED
) == 0)
1028 if ((pImeDpi
->dwFlags
& IMEDPI_FLAG_LOCKED
) == 0 ||
1029 (pImeDpi
->ImeInfo
.fdwProperty
& IME_PROP_END_UNLOAD
) == 0)
1031 RtlLeaveCriticalSection(&gcsImeDpi
);
1036 /* Remove from list */
1037 for (ppEntry
= &gpImeDpiList
; *ppEntry
; ppEntry
= &((*ppEntry
)->pNext
))
1039 if (*ppEntry
== pImeDpi
) /* found */
1041 *ppEntry
= pImeDpi
->pNext
;
1046 Imm32FreeIME(pImeDpi
, TRUE
);
1047 ImmLocalFree(pImeDpi
);
1049 RtlLeaveCriticalSection(&gcsImeDpi
);
1052 /***********************************************************************
1053 * ImmLoadIME (IMM32.@)
1055 BOOL WINAPI
ImmLoadIME(HKL hKL
)
1059 if (!IS_IME_HKL(hKL
) && (!IS_CICERO_MODE() || IS_16BIT_MODE()))
1065 pImeDpi
= Imm32FindImeDpi(hKL
);
1066 if (pImeDpi
== NULL
)
1067 pImeDpi
= Imm32LoadImeDpi(hKL
, FALSE
);
1068 return (pImeDpi
!= NULL
);
1071 /***********************************************************************
1072 * ImmDisableIME (IMM32.@)
1074 BOOL WINAPI
ImmDisableIME(DWORD dwThreadId
)
1076 return NtUserDisableThreadIme(dwThreadId
);
1079 /***********************************************************************
1080 * ImmGetDescriptionA (IMM32.@)
1082 UINT WINAPI
ImmGetDescriptionA(HKL hKL
, LPSTR lpszDescription
, UINT uBufLen
)
1087 TRACE("(%p,%p,%d)\n", hKL
, lpszDescription
, uBufLen
);
1089 if (!IS_IME_HKL(hKL
))
1095 if (!ImmGetImeInfoEx(&info
, ImeInfoExKeyboardLayout
, &hKL
))
1101 StringCchLengthW(info
.wszImeDescription
, _countof(info
.wszImeDescription
), &cch
);
1102 cch
= WideCharToMultiByte(CP_ACP
, 0, info
.wszImeDescription
, (INT
)cch
,
1103 lpszDescription
, uBufLen
, NULL
, NULL
);
1105 lpszDescription
[cch
] = 0;
1109 /***********************************************************************
1110 * ImmGetDescriptionW (IMM32.@)
1112 UINT WINAPI
ImmGetDescriptionW(HKL hKL
, LPWSTR lpszDescription
, UINT uBufLen
)
1117 TRACE("(%p, %p, %d)\n", hKL
, lpszDescription
, uBufLen
);
1119 if (!IS_IME_HKL(hKL
))
1125 if (!ImmGetImeInfoEx(&info
, ImeInfoExKeyboardLayout
, &hKL
))
1132 StringCchCopyW(lpszDescription
, uBufLen
, info
.wszImeDescription
);
1134 StringCchLengthW(info
.wszImeDescription
, _countof(info
.wszImeDescription
), &cch
);
1138 /***********************************************************************
1139 * ImmGetIMEFileNameA (IMM32.@)
1141 UINT WINAPI
ImmGetIMEFileNameA( HKL hKL
, LPSTR lpszFileName
, UINT uBufLen
)
1147 TRACE("(%p, %p, %u)\n", hKL
, lpszFileName
, uBufLen
);
1149 if (!IS_IME_HKL(hKL
))
1153 lpszFileName
[0] = 0;
1157 if (!ImmGetImeInfoEx(&info
, ImeInfoExKeyboardLayout
, &hKL
))
1161 lpszFileName
[0] = 0;
1165 StringCchLengthW(info
.wszImeFile
, _countof(info
.wszImeFile
), &cch
);
1167 cch
= WideCharToMultiByte(CP_ACP
, 0, info
.wszImeFile
, (INT
)cch
,
1168 lpszFileName
, uBufLen
, NULL
, &bDefUsed
);
1172 if (cch
> uBufLen
- 1)
1175 lpszFileName
[cch
] = 0;
1179 /***********************************************************************
1180 * ImmGetIMEFileNameW (IMM32.@)
1182 UINT WINAPI
ImmGetIMEFileNameW(HKL hKL
, LPWSTR lpszFileName
, UINT uBufLen
)
1187 TRACE("(%p, %p, %u)\n", hKL
, lpszFileName
, uBufLen
);
1189 if (!IS_IME_HKL(hKL
))
1193 lpszFileName
[0] = 0;
1197 if (!ImmGetImeInfoEx(&info
, ImeInfoExKeyboardLayout
, &hKL
))
1201 lpszFileName
[0] = 0;
1205 StringCchLengthW(info
.wszImeFile
, _countof(info
.wszImeFile
), &cch
);
1209 StringCchCopyNW(lpszFileName
, uBufLen
, info
.wszImeFile
, cch
);
1211 if (cch
> uBufLen
- 1)
1214 lpszFileName
[cch
] = 0;
1218 /***********************************************************************
1219 * ImmGetProperty (IMM32.@)
1221 DWORD WINAPI
ImmGetProperty(HKL hKL
, DWORD fdwIndex
)
1223 IMEINFOEX ImeInfoEx
;
1226 PIMEDPI pImeDpi
= NULL
;
1228 TRACE("(%p, %lu)\n", hKL
, fdwIndex
);
1230 if (!IS_IME_HKL(hKL
))
1236 if (!ImmGetImeInfoEx(&ImeInfoEx
, ImeInfoExKeyboardLayout
, &hKL
))
1242 if (fdwIndex
== IGP_GETIMEVERSION
)
1243 return ImeInfoEx
.dwImeWinVersion
;
1245 if (ImeInfoEx
.fLoadFlag
!= 2)
1247 pImeDpi
= Imm32FindOrLoadImeDpi(hKL
);
1248 if (IS_NULL_UNEXPECTEDLY(pImeDpi
))
1251 pImeInfo
= &pImeDpi
->ImeInfo
;
1255 pImeInfo
= &ImeInfoEx
.ImeInfo
;
1260 case IGP_PROPERTY
: dwValue
= pImeInfo
->fdwProperty
; break;
1261 case IGP_CONVERSION
: dwValue
= pImeInfo
->fdwConversionCaps
; break;
1262 case IGP_SENTENCE
: dwValue
= pImeInfo
->fdwSentenceCaps
; break;
1263 case IGP_UI
: dwValue
= pImeInfo
->fdwUICaps
; break;
1264 case IGP_SETCOMPSTR
: dwValue
= pImeInfo
->fdwSCSCaps
; break;
1265 case IGP_SELECT
: dwValue
= pImeInfo
->fdwSelectCaps
; break;
1266 default: dwValue
= 0; break;
1270 ImmUnlockImeDpi(pImeDpi
);
1274 /***********************************************************************
1275 * ImmEscapeA (IMM32.@)
1277 LRESULT WINAPI
ImmEscapeA(HKL hKL
, HIMC hIMC
, UINT uSubFunc
, LPVOID lpData
)
1282 CHAR szA
[MAX_IMM_FILENAME
];
1283 WCHAR szW
[MAX_IMM_FILENAME
];
1285 TRACE("(%p, %p, %u, %p)\n", hKL
, hIMC
, uSubFunc
, lpData
);
1287 pImeDpi
= Imm32FindOrLoadImeDpi(hKL
);
1288 if (IS_NULL_UNEXPECTEDLY(pImeDpi
))
1291 if (!ImeDpi_IsUnicode(pImeDpi
) || !lpData
) /* No conversion needed */
1293 ret
= ImeDpi_Escape(pImeDpi
, hIMC
, uSubFunc
, lpData
, hKL
);
1294 ImmUnlockImeDpi(pImeDpi
);
1300 case IME_ESC_SEQUENCE_TO_INTERNAL
:
1301 ret
= ImeDpi_Escape(pImeDpi
, hIMC
, uSubFunc
, lpData
, hKL
);
1305 szW
[cch
++] = HIWORD(ret
);
1307 szW
[cch
++] = LOWORD(ret
);
1309 cch
= WideCharToMultiByte(pImeDpi
->uCodePage
, 0, szW
, cch
, szA
, _countof(szA
),
1314 ret
= MAKEWORD(szA
[0], 0);
1317 ret
= MAKEWORD(szA
[1], szA
[0]);
1320 ret
= MAKELONG(MAKEWORD(szA
[2], szA
[1]), MAKEWORD(szA
[0], 0));
1323 ret
= MAKELONG(MAKEWORD(szA
[3], szA
[2]), MAKEWORD(szA
[1], szA
[0]));
1331 case IME_ESC_GET_EUDC_DICTIONARY
:
1332 case IME_ESC_IME_NAME
:
1333 case IME_ESC_GETHELPFILENAME
:
1334 ret
= ImeDpi_Escape(pImeDpi
, hIMC
, uSubFunc
, szW
, hKL
);
1337 szW
[_countof(szW
) - 1] = UNICODE_NULL
; /* Avoid buffer overrun */
1338 WideCharToMultiByte(pImeDpi
->uCodePage
, 0, szW
, -1,
1339 lpData
, MAX_IMM_FILENAME
, NULL
, NULL
);
1340 ((LPSTR
)lpData
)[MAX_IMM_FILENAME
- 1] = 0;
1344 case IME_ESC_SET_EUDC_DICTIONARY
:
1345 case IME_ESC_HANJA_MODE
:
1346 MultiByteToWideChar(pImeDpi
->uCodePage
, MB_PRECOMPOSED
,
1347 lpData
, -1, szW
, _countof(szW
));
1348 szW
[_countof(szW
) - 1] = UNICODE_NULL
; /* Avoid buffer overrun */
1349 ret
= ImeDpi_Escape(pImeDpi
, hIMC
, uSubFunc
, szW
, hKL
);
1353 ret
= ImeDpi_Escape(pImeDpi
, hIMC
, uSubFunc
, lpData
, hKL
);
1357 ImmUnlockImeDpi(pImeDpi
);
1358 TRACE("ret: %p\n", ret
);
1362 /***********************************************************************
1363 * ImmEscapeW (IMM32.@)
1365 LRESULT WINAPI
ImmEscapeW(HKL hKL
, HIMC hIMC
, UINT uSubFunc
, LPVOID lpData
)
1370 CHAR szA
[MAX_IMM_FILENAME
];
1371 WCHAR szW
[MAX_IMM_FILENAME
];
1374 TRACE("(%p, %p, %u, %p)\n", hKL
, hIMC
, uSubFunc
, lpData
);
1376 pImeDpi
= Imm32FindOrLoadImeDpi(hKL
);
1377 if (IS_NULL_UNEXPECTEDLY(pImeDpi
))
1380 if (ImeDpi_IsUnicode(pImeDpi
) || !lpData
) /* No conversion needed */
1382 ret
= ImeDpi_Escape(pImeDpi
, hIMC
, uSubFunc
, lpData
, hKL
);
1383 ImmUnlockImeDpi(pImeDpi
);
1389 case IME_ESC_SEQUENCE_TO_INTERNAL
:
1390 ret
= ImeDpi_Escape(pImeDpi
, hIMC
, uSubFunc
, lpData
, hKL
);
1395 szA
[cch
++] = HIBYTE(word
);
1397 szA
[cch
++] = LOBYTE(word
);
1399 cch
= MultiByteToWideChar(pImeDpi
->uCodePage
, MB_PRECOMPOSED
,
1400 szA
, cch
, szW
, _countof(szW
));
1403 case 1: ret
= szW
[0]; break;
1404 case 2: ret
= MAKELONG(szW
[1], szW
[0]); break;
1405 default: ret
= 0; break;
1409 case IME_ESC_GET_EUDC_DICTIONARY
:
1410 case IME_ESC_IME_NAME
:
1411 case IME_ESC_GETHELPFILENAME
:
1412 ret
= ImeDpi_Escape(pImeDpi
, hIMC
, uSubFunc
, szA
, hKL
);
1415 szA
[_countof(szA
) - 1] = 0;
1416 MultiByteToWideChar(pImeDpi
->uCodePage
, MB_PRECOMPOSED
,
1417 szA
, -1, lpData
, MAX_IMM_FILENAME
);
1418 ((LPWSTR
)lpData
)[MAX_IMM_FILENAME
- 1] = UNICODE_NULL
; /* Avoid buffer overrun */
1422 case IME_ESC_SET_EUDC_DICTIONARY
:
1423 case IME_ESC_HANJA_MODE
:
1424 WideCharToMultiByte(pImeDpi
->uCodePage
, 0,
1425 lpData
, -1, szA
, _countof(szA
), NULL
, NULL
);
1426 szA
[_countof(szA
) - 1] = 0;
1427 ret
= ImeDpi_Escape(pImeDpi
, hIMC
, uSubFunc
, szA
, hKL
);
1431 ret
= ImeDpi_Escape(pImeDpi
, hIMC
, uSubFunc
, lpData
, hKL
);
1435 ImmUnlockImeDpi(pImeDpi
);
1436 TRACE("ret: %p\n", ret
);
1440 /***********************************************************************
1441 * ImmGetOpenStatus (IMM32.@)
1443 BOOL WINAPI
ImmGetOpenStatus(HIMC hIMC
)
1448 TRACE("(%p)\n", hIMC
);
1450 if (IS_NULL_UNEXPECTEDLY(hIMC
))
1453 pIC
= ImmLockIMC(hIMC
);
1454 if (IS_NULL_UNEXPECTEDLY(pIC
))
1459 TRACE("ret: %d\n", ret
);
1463 /***********************************************************************
1464 * ImmSetOpenStatus (IMM32.@)
1466 BOOL WINAPI
ImmSetOpenStatus(HIMC hIMC
, BOOL fOpen
)
1471 BOOL bHasChange
= FALSE
;
1473 TRACE("(%p, %d)\n", hIMC
, fOpen
);
1475 if (IS_CROSS_THREAD_HIMC(hIMC
))
1478 pIC
= ImmLockIMC(hIMC
);
1479 if (IS_NULL_UNEXPECTEDLY(pIC
))
1482 if (pIC
->fOpen
!= fOpen
)
1486 dwConversion
= pIC
->fdwConversion
;
1494 Imm32MakeIMENotify(hIMC
, hWnd
, NI_CONTEXTUPDATED
, 0,
1495 IMC_SETOPENSTATUS
, IMN_SETOPENSTATUS
, 0);
1496 NtUserNotifyIMEStatus(hWnd
, fOpen
, dwConversion
);
1500 TRACE("No change.\n");
1506 /***********************************************************************
1507 * ImmGetStatusWindowPos (IMM32.@)
1509 BOOL WINAPI
ImmGetStatusWindowPos(HIMC hIMC
, LPPOINT lpptPos
)
1514 TRACE("(%p, %p)\n", hIMC
, lpptPos
);
1516 pIC
= ImmLockIMC(hIMC
);
1517 if (IS_NULL_UNEXPECTEDLY(pIC
))
1520 ret
= !!(pIC
->fdwInit
& INIT_STATUSWNDPOS
);
1522 *lpptPos
= pIC
->ptStatusWndPos
;
1528 /***********************************************************************
1529 * ImmSetStatusWindowPos (IMM32.@)
1531 BOOL WINAPI
ImmSetStatusWindowPos(HIMC hIMC
, LPPOINT lpptPos
)
1536 TRACE("(%p, {%ld, %ld})\n", hIMC
, lpptPos
->x
, lpptPos
->y
);
1538 if (IS_CROSS_THREAD_HIMC(hIMC
))
1541 pIC
= ImmLockIMC(hIMC
);
1542 if (IS_NULL_UNEXPECTEDLY(pIC
))
1546 pIC
->ptStatusWndPos
= *lpptPos
;
1547 pIC
->fdwInit
|= INIT_STATUSWNDPOS
;
1551 Imm32MakeIMENotify(hIMC
, hWnd
, NI_CONTEXTUPDATED
, 0,
1552 IMC_SETSTATUSWINDOWPOS
, IMN_SETSTATUSWINDOWPOS
, 0);
1556 /***********************************************************************
1557 * ImmGetCompositionWindow (IMM32.@)
1559 BOOL WINAPI
ImmGetCompositionWindow(HIMC hIMC
, LPCOMPOSITIONFORM lpCompForm
)
1564 TRACE("(%p, %p)\n", hIMC
, lpCompForm
);
1566 pIC
= ImmLockIMC(hIMC
);
1567 if (IS_NULL_UNEXPECTEDLY(pIC
))
1570 if (pIC
->fdwInit
& INIT_COMPFORM
)
1572 *lpCompForm
= pIC
->cfCompForm
;
1580 /***********************************************************************
1581 * ImmSetCompositionWindow (IMM32.@)
1583 BOOL WINAPI
ImmSetCompositionWindow(HIMC hIMC
, LPCOMPOSITIONFORM lpCompForm
)
1585 LPINPUTCONTEXTDX pIC
;
1588 if (IS_CROSS_THREAD_HIMC(hIMC
))
1591 pIC
= (LPINPUTCONTEXTDX
)ImmLockIMC(hIMC
);
1592 if (IS_NULL_UNEXPECTEDLY(pIC
))
1595 pIC
->cfCompForm
= *lpCompForm
;
1596 pIC
->fdwInit
|= INIT_COMPFORM
;
1598 if (pIC
->dwUIFlags
& 0x8)
1599 pIC
->dwUIFlags
&= ~0x8;
1601 pIC
->dwUIFlags
&= ~0x2;
1607 Imm32MakeIMENotify(hIMC
, hWnd
, NI_CONTEXTUPDATED
, 0,
1608 IMC_SETCOMPOSITIONWINDOW
, IMN_SETCOMPOSITIONWINDOW
, 0);
1612 /***********************************************************************
1613 * ImmGetCompositionFontA (IMM32.@)
1615 BOOL WINAPI
ImmGetCompositionFontA(HIMC hIMC
, LPLOGFONTA lplf
)
1617 PCLIENTIMC pClientImc
;
1618 BOOL ret
= FALSE
, bWide
;
1621 TRACE("(%p, %p)\n", hIMC
, lplf
);
1623 pClientImc
= ImmLockClientImc(hIMC
);
1624 if (IS_NULL_UNEXPECTEDLY(pClientImc
))
1627 bWide
= (pClientImc
->dwFlags
& CLIENTIMC_WIDE
);
1628 ImmUnlockClientImc(pClientImc
);
1630 pIC
= ImmLockIMC(hIMC
);
1631 if (IS_NULL_UNEXPECTEDLY(pIC
))
1634 if (pIC
->fdwInit
& INIT_LOGFONT
)
1637 LogFontWideToAnsi(&pIC
->lfFont
.W
, lplf
);
1639 *lplf
= pIC
->lfFont
.A
;
1648 /***********************************************************************
1649 * ImmGetCompositionFontW (IMM32.@)
1651 BOOL WINAPI
ImmGetCompositionFontW(HIMC hIMC
, LPLOGFONTW lplf
)
1653 PCLIENTIMC pClientImc
;
1658 TRACE("(%p, %p)\n", hIMC
, lplf
);
1660 pClientImc
= ImmLockClientImc(hIMC
);
1661 if (IS_NULL_UNEXPECTEDLY(pClientImc
))
1664 bWide
= (pClientImc
->dwFlags
& CLIENTIMC_WIDE
);
1665 ImmUnlockClientImc(pClientImc
);
1667 pIC
= ImmLockIMC(hIMC
);
1668 if (IS_NULL_UNEXPECTEDLY(pIC
))
1671 if (pIC
->fdwInit
& INIT_LOGFONT
)
1674 *lplf
= pIC
->lfFont
.W
;
1676 LogFontAnsiToWide(&pIC
->lfFont
.A
, lplf
);
1685 /***********************************************************************
1686 * ImmSetCompositionFontA (IMM32.@)
1688 BOOL WINAPI
ImmSetCompositionFontA(HIMC hIMC
, LPLOGFONTA lplf
)
1691 PCLIENTIMC pClientImc
;
1693 LPINPUTCONTEXTDX pIC
;
1697 TRACE("(%p, %p)\n", hIMC
, lplf
);
1699 if (IS_CROSS_THREAD_HIMC(hIMC
))
1702 pClientImc
= ImmLockClientImc(hIMC
);
1703 if (IS_NULL_UNEXPECTEDLY(pClientImc
))
1706 bWide
= (pClientImc
->dwFlags
& CLIENTIMC_WIDE
);
1707 ImmUnlockClientImc(pClientImc
);
1711 LogFontAnsiToWide(lplf
, &lfW
);
1712 return ImmSetCompositionFontW(hIMC
, &lfW
);
1715 pIC
= (LPINPUTCONTEXTDX
)ImmLockIMC(hIMC
);
1716 if (IS_NULL_UNEXPECTEDLY(pIC
))
1719 if (GetWin32ClientInfo()->dwExpWinVer
< _WIN32_WINNT_NT4
) /* old version (3.x)? */
1721 LangID
= LANGIDFROMLCID(GetSystemDefaultLCID());
1722 if (PRIMARYLANGID(LangID
) == LANG_JAPANESE
&&
1723 !(pIC
->dwUIFlags
& 2) &&
1724 pIC
->cfCompForm
.dwStyle
!= CFS_DEFAULT
)
1726 PostMessageA(pIC
->hWnd
, WM_IME_REPORT
, IR_CHANGECONVERT
, 0);
1730 pIC
->lfFont
.A
= *lplf
;
1731 pIC
->fdwInit
|= INIT_LOGFONT
;
1736 Imm32MakeIMENotify(hIMC
, hWnd
, NI_CONTEXTUPDATED
, 0, IMC_SETCOMPOSITIONFONT
,
1737 IMN_SETCOMPOSITIONFONT
, 0);
1741 /***********************************************************************
1742 * ImmSetCompositionFontW (IMM32.@)
1744 BOOL WINAPI
ImmSetCompositionFontW(HIMC hIMC
, LPLOGFONTW lplf
)
1747 PCLIENTIMC pClientImc
;
1750 LPINPUTCONTEXTDX pIC
;
1753 TRACE("(%p, %p)\n", hIMC
, lplf
);
1755 if (IS_CROSS_THREAD_HIMC(hIMC
))
1758 pClientImc
= ImmLockClientImc(hIMC
);
1759 if (IS_NULL_UNEXPECTEDLY(pClientImc
))
1762 bWide
= (pClientImc
->dwFlags
& CLIENTIMC_WIDE
);
1763 ImmUnlockClientImc(pClientImc
);
1767 LogFontWideToAnsi(lplf
, &lfA
);
1768 return ImmSetCompositionFontA(hIMC
, &lfA
);
1771 pIC
= (LPINPUTCONTEXTDX
)ImmLockIMC(hIMC
);
1772 if (IS_NULL_UNEXPECTEDLY(pIC
))
1775 if (GetWin32ClientInfo()->dwExpWinVer
< _WIN32_WINNT_NT4
) /* old version (3.x)? */
1777 LangID
= LANGIDFROMLCID(GetSystemDefaultLCID());
1778 if (PRIMARYLANGID(LangID
) == LANG_JAPANESE
&&
1779 !(pIC
->dwUIFlags
& 2) &&
1780 pIC
->cfCompForm
.dwStyle
!= CFS_DEFAULT
)
1782 PostMessageW(pIC
->hWnd
, WM_IME_REPORT
, IR_CHANGECONVERT
, 0);
1786 pIC
->lfFont
.W
= *lplf
;
1787 pIC
->fdwInit
|= INIT_LOGFONT
;
1792 Imm32MakeIMENotify(hIMC
, hWnd
, NI_CONTEXTUPDATED
, 0, IMC_SETCOMPOSITIONFONT
,
1793 IMN_SETCOMPOSITIONFONT
, 0);
1797 /***********************************************************************
1798 * ImmGetConversionListA (IMM32.@)
1801 ImmGetConversionListA(HKL hKL
, HIMC hIMC
, LPCSTR pSrc
, LPCANDIDATELIST lpDst
,
1802 DWORD dwBufLen
, UINT uFlag
)
1806 LPWSTR pszSrcW
= NULL
;
1807 LPCANDIDATELIST pCL
= NULL
;
1810 TRACE("(%p, %p, %s, %p, %lu, 0x%lX)\n", hKL
, hIMC
, debugstr_a(pSrc
),
1811 lpDst
, dwBufLen
, uFlag
);
1813 pImeDpi
= Imm32FindOrLoadImeDpi(hKL
);
1814 if (IS_NULL_UNEXPECTEDLY(pImeDpi
))
1817 if (!ImeDpi_IsUnicode(pImeDpi
)) /* No conversion needed */
1819 ret
= pImeDpi
->ImeConversionList(hIMC
, pSrc
, lpDst
, dwBufLen
, uFlag
);
1820 ImmUnlockImeDpi(pImeDpi
);
1826 pszSrcW
= Imm32WideFromAnsi(pImeDpi
->uCodePage
, pSrc
);
1827 if (IS_NULL_UNEXPECTEDLY(pszSrcW
))
1831 cb
= pImeDpi
->ImeConversionList(hIMC
, pszSrcW
, NULL
, 0, uFlag
);
1832 if (IS_ZERO_UNEXPECTEDLY(cb
))
1835 pCL
= ImmLocalAlloc(0, cb
);
1836 if (IS_NULL_UNEXPECTEDLY(pCL
))
1839 cb
= pImeDpi
->ImeConversionList(hIMC
, pszSrcW
, pCL
, cb
, uFlag
);
1840 if (IS_ZERO_UNEXPECTEDLY(cb
))
1843 ret
= CandidateListWideToAnsi(pCL
, lpDst
, dwBufLen
, pImeDpi
->uCodePage
);
1846 ImmLocalFree(pszSrcW
);
1848 ImmUnlockImeDpi(pImeDpi
);
1849 TRACE("ret: 0x%X\n", ret
);
1853 /***********************************************************************
1854 * ImmGetConversionListW (IMM32.@)
1857 ImmGetConversionListW(HKL hKL
, HIMC hIMC
, LPCWSTR pSrc
, LPCANDIDATELIST lpDst
,
1858 DWORD dwBufLen
, UINT uFlag
)
1863 LPCANDIDATELIST pCL
= NULL
;
1864 LPSTR pszSrcA
= NULL
;
1866 TRACE("(%p, %p, %s, %p, %lu, 0x%lX)\n", hKL
, hIMC
, debugstr_w(pSrc
),
1867 lpDst
, dwBufLen
, uFlag
);
1869 pImeDpi
= Imm32FindOrLoadImeDpi(hKL
);
1870 if (IS_NULL_UNEXPECTEDLY(pImeDpi
))
1873 if (ImeDpi_IsUnicode(pImeDpi
)) /* No conversion needed */
1875 ret
= pImeDpi
->ImeConversionList(hIMC
, pSrc
, lpDst
, dwBufLen
, uFlag
);
1876 ImmUnlockImeDpi(pImeDpi
);
1882 pszSrcA
= Imm32AnsiFromWide(pImeDpi
->uCodePage
, pSrc
);
1883 if (IS_NULL_UNEXPECTEDLY(pszSrcA
))
1887 cb
= pImeDpi
->ImeConversionList(hIMC
, pszSrcA
, NULL
, 0, uFlag
);
1888 if (IS_ZERO_UNEXPECTEDLY(cb
))
1891 pCL
= ImmLocalAlloc(0, cb
);
1892 if (IS_NULL_UNEXPECTEDLY(pCL
))
1895 cb
= pImeDpi
->ImeConversionList(hIMC
, pszSrcA
, pCL
, cb
, uFlag
);
1896 if (IS_ZERO_UNEXPECTEDLY(cb
))
1899 ret
= CandidateListAnsiToWide(pCL
, lpDst
, dwBufLen
, pImeDpi
->uCodePage
);
1902 ImmLocalFree(pszSrcA
);
1904 ImmUnlockImeDpi(pImeDpi
);
1905 TRACE("ret: 0x%X\n", ret
);
1909 /***********************************************************************
1910 * ImmGetConversionStatus (IMM32.@)
1912 BOOL WINAPI
ImmGetConversionStatus(HIMC hIMC
, LPDWORD lpfdwConversion
, LPDWORD lpfdwSentence
)
1916 TRACE("(%p %p %p)\n", hIMC
, lpfdwConversion
, lpfdwSentence
);
1918 pIC
= ImmLockIMC(hIMC
);
1919 if (IS_NULL_UNEXPECTEDLY(pIC
))
1922 if (lpfdwConversion
)
1924 *lpfdwConversion
= pIC
->fdwConversion
;
1925 TRACE("0x%X\n", *lpfdwConversion
);
1930 *lpfdwSentence
= pIC
->fdwSentence
;
1931 TRACE("0x%X\n", *lpfdwSentence
);
1938 /***********************************************************************
1939 * ImmSetConversionStatus (IMM32.@)
1941 BOOL WINAPI
ImmSetConversionStatus(HIMC hIMC
, DWORD fdwConversion
, DWORD fdwSentence
)
1945 DWORD dwOldConversion
, dwOldSentence
;
1946 BOOL fOpen
= FALSE
, fConversionChange
= FALSE
, fSentenceChange
= FALSE
, fUseCicero
= FALSE
;
1949 TRACE("(%p, 0x%lX, 0x%lX)\n", hIMC
, fdwConversion
, fdwSentence
);
1951 hKL
= GetKeyboardLayout(0);
1952 if (!IS_IME_HKL(hKL
) && IS_CICERO_MODE() && !IS_16BIT_MODE())
1955 if (IS_CROSS_THREAD_HIMC(hIMC
))
1958 pIC
= ImmLockIMC(hIMC
);
1959 if (IS_NULL_UNEXPECTEDLY(pIC
))
1962 if (pIC
->fdwConversion
!= fdwConversion
)
1964 dwOldConversion
= pIC
->fdwConversion
;
1965 pIC
->fdwConversion
= fdwConversion
;
1966 fConversionChange
= TRUE
;
1969 if (pIC
->fdwSentence
!= fdwSentence
)
1971 dwOldSentence
= pIC
->fdwSentence
;
1972 pIC
->fdwSentence
= fdwSentence
;
1973 fSentenceChange
= TRUE
;
1980 if (fConversionChange
|| fUseCicero
)
1982 Imm32MakeIMENotify(hIMC
, hWnd
, NI_CONTEXTUPDATED
, dwOldConversion
,
1983 IMC_SETCONVERSIONMODE
, IMN_SETCONVERSIONMODE
, 0);
1984 if (fConversionChange
)
1985 NtUserNotifyIMEStatus(hWnd
, fOpen
, fdwConversion
);
1988 if (fSentenceChange
|| fUseCicero
)
1990 Imm32MakeIMENotify(hIMC
, hWnd
, NI_CONTEXTUPDATED
, dwOldSentence
,
1991 IMC_SETSENTENCEMODE
, IMN_SETSENTENCEMODE
, 0);
1997 /***********************************************************************
1998 * ImmConfigureIMEA (IMM32.@)
2000 BOOL WINAPI
ImmConfigureIMEA(HKL hKL
, HWND hWnd
, DWORD dwMode
, LPVOID lpData
)
2004 REGISTERWORDW RegWordW
;
2005 LPREGISTERWORDA pRegWordA
;
2007 TRACE("(%p, %p, 0x%lX, %p)\n", hKL
, hWnd
, dwMode
, lpData
);
2009 if (IS_NULL_UNEXPECTEDLY(ValidateHwnd(hWnd
)) || IS_CROSS_PROCESS_HWND(hWnd
))
2012 pImeDpi
= Imm32FindOrLoadImeDpi(hKL
);
2013 if (IS_NULL_UNEXPECTEDLY(pImeDpi
))
2016 RtlZeroMemory(&RegWordW
, sizeof(RegWordW
));
2018 if (!ImeDpi_IsUnicode(pImeDpi
) || !lpData
|| dwMode
!= IME_CONFIG_REGISTERWORD
)
2019 goto DoIt
; /* No conversion needed */
2023 if (pRegWordA
->lpReading
)
2025 RegWordW
.lpReading
= Imm32WideFromAnsi(pImeDpi
->uCodePage
, pRegWordA
->lpReading
);
2026 if (IS_NULL_UNEXPECTEDLY(RegWordW
.lpReading
))
2030 if (pRegWordA
->lpWord
)
2032 RegWordW
.lpWord
= Imm32WideFromAnsi(pImeDpi
->uCodePage
, pRegWordA
->lpWord
);
2033 if (IS_NULL_UNEXPECTEDLY(RegWordW
.lpWord
))
2040 SendMessageW(hWnd
, WM_IME_SYSTEM
, 0x1B, 0);
2041 ret
= pImeDpi
->ImeConfigure(hKL
, hWnd
, dwMode
, lpData
);
2042 SendMessageW(hWnd
, WM_IME_SYSTEM
, 0x1A, 0);
2045 ImmLocalFree(RegWordW
.lpReading
);
2046 ImmLocalFree(RegWordW
.lpWord
);
2047 ImmUnlockImeDpi(pImeDpi
);
2048 TRACE("ret: %d\n", ret
);
2052 /***********************************************************************
2053 * ImmConfigureIMEW (IMM32.@)
2055 BOOL WINAPI
ImmConfigureIMEW(HKL hKL
, HWND hWnd
, DWORD dwMode
, LPVOID lpData
)
2059 REGISTERWORDA RegWordA
;
2060 LPREGISTERWORDW pRegWordW
;
2062 TRACE("(%p, %p, 0x%lX, %p)\n", hKL
, hWnd
, dwMode
, lpData
);
2064 if (IS_NULL_UNEXPECTEDLY(ValidateHwnd(hWnd
)) || IS_CROSS_PROCESS_HWND(hWnd
))
2067 pImeDpi
= Imm32FindOrLoadImeDpi(hKL
);
2068 if (IS_NULL_UNEXPECTEDLY(pImeDpi
))
2071 RtlZeroMemory(&RegWordA
, sizeof(RegWordA
));
2073 if (ImeDpi_IsUnicode(pImeDpi
) || !lpData
|| dwMode
!= IME_CONFIG_REGISTERWORD
)
2074 goto DoIt
; /* No conversion needed */
2078 if (pRegWordW
->lpReading
)
2080 RegWordA
.lpReading
= Imm32AnsiFromWide(pImeDpi
->uCodePage
, pRegWordW
->lpReading
);
2081 if (IS_NULL_UNEXPECTEDLY(RegWordA
.lpReading
))
2085 if (pRegWordW
->lpWord
)
2087 RegWordA
.lpWord
= Imm32AnsiFromWide(pImeDpi
->uCodePage
, pRegWordW
->lpWord
);
2088 if (IS_NULL_UNEXPECTEDLY(RegWordA
.lpWord
))
2095 SendMessageW(hWnd
, WM_IME_SYSTEM
, 0x1B, 0);
2096 ret
= pImeDpi
->ImeConfigure(hKL
, hWnd
, dwMode
, lpData
);
2097 SendMessageW(hWnd
, WM_IME_SYSTEM
, 0x1A, 0);
2100 ImmLocalFree(RegWordA
.lpReading
);
2101 ImmLocalFree(RegWordA
.lpWord
);
2102 ImmUnlockImeDpi(pImeDpi
);
2103 TRACE("ret: %d\n", ret
);
2107 /***********************************************************************
2108 * ImmGetImeMenuItemsA (IMM32.@)
2111 ImmGetImeMenuItemsA(HIMC hIMC
, DWORD dwFlags
, DWORD dwType
,
2112 LPIMEMENUITEMINFOA lpImeParentMenu
,
2113 LPIMEMENUITEMINFOA lpImeMenu
, DWORD dwSize
)
2115 TRACE("(%p, 0x%lX, 0x%lX, %p, %p, 0x%lX)\n",
2116 hIMC
, dwFlags
, dwType
, lpImeParentMenu
, lpImeMenu
, dwSize
);
2117 return ImmGetImeMenuItemsAW(hIMC
, dwFlags
, dwType
, lpImeParentMenu
, lpImeMenu
, dwSize
, TRUE
);
2120 /***********************************************************************
2121 * ImmGetImeMenuItemsW (IMM32.@)
2124 ImmGetImeMenuItemsW(HIMC hIMC
, DWORD dwFlags
, DWORD dwType
,
2125 LPIMEMENUITEMINFOW lpImeParentMenu
,
2126 LPIMEMENUITEMINFOW lpImeMenu
, DWORD dwSize
)
2128 TRACE("(%p, 0x%lX, 0x%lX, %p, %p, 0x%lX)\n",
2129 hIMC
, dwFlags
, dwType
, lpImeParentMenu
, lpImeMenu
, dwSize
);
2130 return ImmGetImeMenuItemsAW(hIMC
, dwFlags
, dwType
, lpImeParentMenu
, lpImeMenu
, dwSize
, FALSE
);
2133 /***********************************************************************
2134 * ImmWINNLSEnableIME (IMM32.@)
2136 BOOL WINAPI
ImmWINNLSEnableIME(HWND hWnd
, BOOL enable
)
2139 PCLIENTIMC pClientImc
;
2143 TRACE("(%p, %d)\n", hWnd
, enable
);
2145 if (!Imm32IsSystemJapaneseOrKorean())
2147 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2151 hIMC
= (HIMC
)NtUserGetThreadState(THREADSTATE_DEFAULTINPUTCONTEXT
);
2152 if (IS_NULL_UNEXPECTEDLY(hIMC
))
2155 pClientImc
= ImmLockClientImc(hIMC
);
2156 if (IS_NULL_UNEXPECTEDLY(pClientImc
))
2159 ret
= !(pClientImc
->dwFlags
& CLIENTIMC_DISABLEIME
);
2160 if (!!enable
== ret
)
2163 ImmUnlockClientImc(pClientImc
);
2167 if (!IsWindow(hWnd
))
2170 hImeWnd
= ImmGetDefaultIMEWnd(hWnd
);
2171 bImeWnd
= IsWindow(hImeWnd
);
2173 ImmSetActiveContext(hWnd
, (enable
? NULL
: hIMC
), FALSE
);
2176 pClientImc
->dwFlags
&= ~CLIENTIMC_DISABLEIME
;
2178 pClientImc
->dwFlags
|= CLIENTIMC_DISABLEIME
;
2180 ImmUnlockClientImc(pClientImc
);
2183 ImmSetActiveContext(hWnd
, (enable
? hIMC
: NULL
), TRUE
);