ReactOS  0.4.15-dev-2979-gfd8baca
imm.c
Go to the documentation of this file.
1 /*
2  * IMM32 library
3  *
4  * Copyright 1998 Patrik Stridvall
5  * Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21 
22 #include <stdarg.h>
23 #include <stdio.h>
24 
25 #define WIN32_NO_STATUS
26 #include <windef.h>
27 #include <winbase.h>
28 #include <wingdi.h>
29 #include <winuser.h>
30 #include <winerror.h>
31 #include <wine/debug.h>
32 #include <imm.h>
33 #include <ddk/imm.h>
34 #include <winnls.h>
35 #include <winreg.h>
36 #include <wine/list.h>
37 #include <stdlib.h>
38 #include <ndk/umtypes.h>
39 #include <ndk/pstypes.h>
40 #include <ndk/rtlfuncs.h>
41 #include "../../../win32ss/include/ntuser.h"
42 #include "../../../win32ss/include/ntwin32.h"
43 #include <imm32_undoc.h>
44 #include <strsafe.h>
45 
47 
48 #define IMM_INIT_MAGIC 0x19650412
49 #define IMM_INVALID_CANDFORM ULONG_MAX
50 
51 #define REGKEY_KEYBOARD_LAYOUTS \
52  L"System\\CurrentControlSet\\Control\\Keyboard Layouts"
53 #define REGKEY_IMM \
54  L"Software\\Microsoft\\Windows NT\\CurrentVersion\\IMM"
55 
59 
61 
63 {
64  return NtUserQueryInputContext(hIMC, dwUnknown2);
65 }
66 
67 static DWORD APIENTRY Imm32NotifyIMEStatus(HWND hwnd, HIMC hIMC, DWORD dwConversion)
68 {
69  return NtUserNotifyIMEStatus(hwnd, hIMC, dwConversion);
70 }
71 
72 static VOID APIENTRY Imm32FreeImeDpi(PIMEDPI pImeDpi, BOOL bDestroy)
73 {
74  if (pImeDpi->hInst == NULL)
75  return;
76  if (bDestroy)
77  pImeDpi->ImeDestroy(0);
78  FreeLibrary(pImeDpi->hInst);
79  pImeDpi->hInst = NULL;
80 }
81 
82 static BOOL APIENTRY
83 Imm32NotifyAction(HIMC hIMC, HWND hwnd, DWORD dwAction, DWORD_PTR dwIndex, DWORD_PTR dwValue,
84  DWORD_PTR dwCommand, DWORD_PTR dwData)
85 {
86  DWORD dwLayout;
87  HKL hKL;
88  PIMEDPI pImeDpi;
89 
90  if (dwAction)
91  {
92  dwLayout = Imm32QueryInputContext(hIMC, 1);
93  if (dwLayout)
94  {
95  /* find keyboard layout and lock it */
96  hKL = GetKeyboardLayout(dwLayout);
97  pImeDpi = ImmLockImeDpi(hKL);
98  if (pImeDpi)
99  {
100  /* do notify */
101  pImeDpi->NotifyIME(hIMC, dwAction, dwIndex, dwValue);
102 
103  ImmUnlockImeDpi(pImeDpi); /* unlock */
104  }
105  }
106  }
107 
108  if (hwnd && dwCommand)
109  SendMessageW(hwnd, WM_IME_NOTIFY, dwCommand, dwData);
110 
111  return TRUE;
112 }
113 
115 {
116  DWORD cbData;
118  HKEY hLayoutKey = NULL, hLayoutsKey = NULL;
119  LONG error;
121  WCHAR szLayout[MAX_PATH];
122 
123  TRACE("ImmLoadLayout(%p, %p)\n", hKL, pImeInfoEx);
124 
125  if (IS_IME_HKL(hKL) ||
126  !g_psi || (g_psi->dwSRVIFlags & SRVINFO_METRICS) == 0 ||
127  ((PW32CLIENTINFO)NtCurrentTeb()->Win32ClientInfo)->W32ClientInfo[0] & 2)
128  {
129  UnicodeString.Buffer = szLayout;
130  UnicodeString.MaximumLength = sizeof(szLayout);
132  if (!NT_SUCCESS(Status))
133  return NULL;
134 
136  if (error)
137  return NULL;
138 
139  error = RegOpenKeyW(hLayoutsKey, szLayout, &hLayoutKey);
140  }
141  else
142  {
144  }
145 
146  if (error)
147  {
148  ERR("RegOpenKeyW error: 0x%08lX\n", error);
149  hKL = NULL;
150  }
151  else
152  {
153  cbData = sizeof(pImeInfoEx->wszImeFile);
154  error = RegQueryValueExW(hLayoutKey, L"Ime File", 0, 0,
155  (LPBYTE)pImeInfoEx->wszImeFile, &cbData);
156  if (error)
157  hKL = NULL;
158  }
159 
160  RegCloseKey(hLayoutKey);
161  if (hLayoutsKey)
162  RegCloseKey(hLayoutsKey);
163  return hKL;
164 }
165 
166 typedef struct _tagImmHkl{
167  struct list entry;
171  WCHAR imeClassName[17]; /* 16 character max */
174 
175  /* Function Pointers */
176  BOOL (WINAPI *pImeInquire)(IMEINFO *, WCHAR *, const WCHAR *);
177  BOOL (WINAPI *pImeConfigure)(HKL, HWND, DWORD, void *);
178  BOOL (WINAPI *pImeDestroy)(UINT);
179  LRESULT (WINAPI *pImeEscape)(HIMC, UINT, void *);
180  BOOL (WINAPI *pImeSelect)(HIMC, BOOL);
181  BOOL (WINAPI *pImeSetActiveContext)(HIMC, BOOL);
182  UINT (WINAPI *pImeToAsciiEx)(UINT, UINT, const BYTE *, DWORD *, UINT, HIMC);
183  BOOL (WINAPI *pNotifyIME)(HIMC, DWORD, DWORD, DWORD);
184  BOOL (WINAPI *pImeRegisterWord)(const WCHAR *, DWORD, const WCHAR *);
185  BOOL (WINAPI *pImeUnregisterWord)(const WCHAR *, DWORD, const WCHAR *);
186  UINT (WINAPI *pImeEnumRegisterWord)(REGISTERWORDENUMPROCW, const WCHAR *, DWORD, const WCHAR *, void *);
187  BOOL (WINAPI *pImeSetCompositionString)(HIMC, DWORD, const void *, DWORD, const void *, DWORD);
188  DWORD (WINAPI *pImeConversionList)(HIMC, const WCHAR *, CANDIDATELIST *, DWORD, UINT);
189  BOOL (WINAPI *pImeProcessKey)(HIMC, UINT, LPARAM, const BYTE *);
190  UINT (WINAPI *pImeGetRegisterWordStyle)(UINT, STYLEBUFW *);
191  DWORD (WINAPI *pImeGetImeMenuItems)(HIMC, DWORD, DWORD, IMEMENUITEMINFOW *, IMEMENUITEMINFOW *, DWORD);
192 } ImmHkl;
193 
194 typedef struct tagInputContextData
195 {
199 
205 
206 #define WINE_IMC_VALID_MAGIC 0x56434D49
207 
208 typedef struct _tagTRANSMSG {
212 } TRANSMSG, *LPTRANSMSG;
213 
214 typedef struct _tagIMMThreadData {
215  struct list entry;
221 } IMMThreadData;
222 
225 
226 static const WCHAR szwWineIMCProperty[] = {'W','i','n','e','I','m','m','H','I','M','C','P','r','o','p','e','r','t','y',0};
227 
228 static const WCHAR szImeFileW[] = {'I','m','e',' ','F','i','l','e',0};
229 static const WCHAR szLayoutTextW[] = {'L','a','y','o','u','t',' ','T','e','x','t',0};
230 static const WCHAR szImeRegFmt[] = {'S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','K','e','y','b','o','a','r','d',' ','L','a','y','o','u','t','s','\\','%','0','8','l','x',0};
231 
232 static const WCHAR szwIME[] = {'I','M','E',0};
233 static const WCHAR szwDefaultIME[] = {'D','e','f','a','u','l','t',' ','I','M','E',0};
234 
237 {
238  0, 0, &threaddata_cs,
240  0, 0, { (DWORD_PTR)(__FILE__ ": threaddata_cs") }
241 };
242 static CRITICAL_SECTION threaddata_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
244 
246 {
247  return !!(data->immKbd->imeInfo.fdwProperty & IME_PROP_UNICODE);
248 }
249 
250 static inline BOOL is_kbd_ime_unicode(const ImmHkl *hkl)
251 {
252  return !!(hkl->imeInfo.fdwProperty & IME_PROP_UNICODE);
253 }
254 
255 static BOOL IMM_DestroyContext(HIMC hIMC);
256 static InputContextData* get_imc_data(HIMC hIMC);
257 
258 static inline WCHAR *strdupAtoW( const char *str )
259 {
260  WCHAR *ret = NULL;
261  if (str)
262  {
263  DWORD len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
264  if ((ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
265  MultiByteToWideChar( CP_ACP, 0, str, -1, ret, len );
266  }
267  return ret;
268 }
269 
270 static inline CHAR *strdupWtoA( const WCHAR *str )
271 {
272  CHAR *ret = NULL;
273  if (str)
274  {
275  DWORD len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
276  if ((ret = HeapAlloc( GetProcessHeap(), 0, len )))
277  WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL );
278  }
279  return ret;
280 }
281 
284 {
285  DWORD ret, i, len;
286 
288  if ( lpDst && dwBufLen > 0 )
289  {
290  *lpDst = *lpSrc;
291  lpDst->dwOffset[0] = ret;
292  }
293 
294  for ( i = 0; i < lpSrc->dwCount; i++)
295  {
296  LPBYTE src = (LPBYTE)lpSrc + lpSrc->dwOffset[i];
297 
298  if ( lpDst && dwBufLen > 0 )
299  {
300  LPBYTE dest = (LPBYTE)lpDst + lpDst->dwOffset[i];
301 
303  (LPSTR)dest, dwBufLen, NULL, NULL);
304 
305  if ( i + 1 < lpSrc->dwCount )
306  lpDst->dwOffset[i+1] = lpDst->dwOffset[i] + len * sizeof(char);
307  dwBufLen -= len * sizeof(char);
308  }
309  else
311 
312  ret += len * sizeof(char);
313  }
314 
315  if ( lpDst )
316  lpDst->dwSize = ret;
317 
318  return ret;
319 }
320 
323 {
324  DWORD ret, i, len;
325 
327  if ( lpDst && dwBufLen > 0 )
328  {
329  *lpDst = *lpSrc;
330  lpDst->dwOffset[0] = ret;
331  }
332 
333  for ( i = 0; i < lpSrc->dwCount; i++)
334  {
335  LPBYTE src = (LPBYTE)lpSrc + lpSrc->dwOffset[i];
336 
337  if ( lpDst && dwBufLen > 0 )
338  {
339  LPBYTE dest = (LPBYTE)lpDst + lpDst->dwOffset[i];
340 
342  (LPWSTR)dest, dwBufLen);
343 
344  if ( i + 1 < lpSrc->dwCount )
345  lpDst->dwOffset[i+1] = lpDst->dwOffset[i] + len * sizeof(WCHAR);
346  dwBufLen -= len * sizeof(WCHAR);
347  }
348  else
349  len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)src, -1, NULL, 0);
350 
351  ret += len * sizeof(WCHAR);
352  }
353 
354  if ( lpDst )
355  lpDst->dwSize = ret;
356 
357  return ret;
358 }
359 
361 {
363  DWORD process;
364 
365  if (hwnd)
366  {
367  if (!(thread = GetWindowThreadProcessId(hwnd, &process))) return NULL;
368  if (process != GetCurrentProcessId()) return NULL;
369  }
370  else if (thread)
371  {
373  if (!h) return NULL;
375  CloseHandle(h);
376  if (process != GetCurrentProcessId()) return NULL;
377  }
378  else
380 
383  if (data->threadID == thread) return data;
384 
386  data->threadID = thread;
388  TRACE("Thread Data Created (%x)\n",thread);
389  return data;
390 }
391 
393 {
395 
396  if (!data)
397  return FALSE;
398 
399  return data->threadDefault;
400 }
401 
402 static void IMM_FreeThreadData(void)
403 {
405 
408  {
409  if (data->threadID == GetCurrentThreadId())
410  {
411  list_remove(&data->entry);
413  IMM_DestroyContext(data->defaultContext);
415  TRACE("Thread Data Destroyed\n");
416  return;
417  }
418  }
420 }
421 
423 {
424  static const WCHAR display_device_guid_propW[] = {
425  '_','_','w','i','n','e','_','d','i','s','p','l','a','y','_',
426  'd','e','v','i','c','e','_','g','u','i','d',0 };
427  static const WCHAR key_pathW[] = {
428  'S','y','s','t','e','m','\\',
429  'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
430  'C','o','n','t','r','o','l','\\',
431  'V','i','d','e','o','\\','{',0};
432  static const WCHAR displayW[] = {'}','\\','0','0','0','0',0};
433  static const WCHAR driverW[] = {'G','r','a','p','h','i','c','s','D','r','i','v','e','r',0};
434 
435  HMODULE ret = 0;
436  HKEY hkey;
437  DWORD size;
439  WCHAR key[ARRAY_SIZE( key_pathW ) + ARRAY_SIZE( displayW ) + 40];
440  UINT guid_atom = HandleToULong( GetPropW( GetDesktopWindow(), display_device_guid_propW ));
441 
442  if (!guid_atom) return 0;
443  memcpy( key, key_pathW, sizeof(key_pathW) );
444  if (!GlobalGetAtomNameW( guid_atom, key + lstrlenW(key), 40 )) return 0;
445  lstrcatW( key, displayW );
446  if (RegOpenKeyW( HKEY_LOCAL_MACHINE, key, &hkey )) return 0;
447  size = sizeof(path);
448  if (!RegQueryValueExW( hkey, driverW, NULL, NULL, (BYTE *)path, &size )) ret = LoadLibraryW( path );
449  RegCloseKey( hkey );
450  TRACE( "%s %p\n", debugstr_w(path), ret );
451  return ret;
452 }
453 
454 /* ImmHkl loading and freeing */
455 #define LOAD_FUNCPTR(f) if((ptr->p##f = (LPVOID)GetProcAddress(ptr->hIME, #f)) == NULL){WARN("Can't find function %s in ime\n", #f);}
457 {
458  ImmHkl *ptr;
460 
461  TRACE("Seeking ime for keyboard %p\n",hkl);
462 
464  {
465  if (ptr->hkl == hkl)
466  return ptr;
467  }
468  /* not found... create it */
469 
471 
472  ptr->hkl = hkl;
474  if (!ptr->hIME) ptr->hIME = load_graphics_driver();
475  if (ptr->hIME)
476  {
478  if (!ptr->pImeInquire || !ptr->pImeInquire(&ptr->imeInfo, ptr->imeClassName, NULL))
479  {
480  FreeLibrary(ptr->hIME);
481  ptr->hIME = NULL;
482  }
483  else
484  {
487  if (!ptr->pImeSelect || !ptr->pImeDestroy)
488  {
489  FreeLibrary(ptr->hIME);
490  ptr->hIME = NULL;
491  }
492  else
493  {
507  /* make sure our classname is WCHAR */
508  if (!is_kbd_ime_unicode(ptr))
509  {
510  WCHAR bufW[17];
511  MultiByteToWideChar(CP_ACP, 0, (LPSTR)ptr->imeClassName,
512  -1, bufW, 17);
513  lstrcpyW(ptr->imeClassName, bufW);
514  }
515  }
516  }
517  }
518  list_add_head(&ImmHklList,&ptr->entry);
519 
520  return ptr;
521 }
522 #undef LOAD_FUNCPTR
523 
525 {
526  ImmHkl *immHkl = IMM_GetImmHkl(hkl);
527  return immHkl->UIWnd;
528 }
529 
530 static void IMM_FreeAllImmHkl(void)
531 {
532  ImmHkl *ptr,*cursor2;
533 
535  {
536  list_remove(&ptr->entry);
537  if (ptr->hIME)
538  {
539  ptr->pImeDestroy(1);
540  FreeLibrary(ptr->hIME);
541  }
542  if (ptr->UIWnd)
543  DestroyWindow(ptr->UIWnd);
545  }
546 }
547 
548 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
549 {
550  TRACE("%p, %x, %p\n",hInstDLL,fdwReason,lpReserved);
551  switch (fdwReason)
552  {
553  case DLL_PROCESS_ATTACH:
555  {
556  return FALSE;
557  }
558  break;
559  case DLL_THREAD_ATTACH:
560  break;
561  case DLL_THREAD_DETACH:
563  break;
564  case DLL_PROCESS_DETACH:
565  if (lpReserved) break;
568  break;
569  }
570  return TRUE;
571 }
572 
573 /* for posting messages as the IME */
575 {
576  HWND target = GetFocus();
577  if (!target)
578  PostMessageW(data->IMC.hWnd,msg,wParam,lParam);
579  else
581 }
582 
583 /* for sending messages as the IME */
585 {
586  HWND target = GetFocus();
587  if (!target)
588  SendMessageW(data->IMC.hWnd,msg,wParam,lParam);
589  else
591 }
592 
594 {
595  HWND target;
596 
597  target = data->IMC.hWnd;
598  if (!target) target = GetFocus();
599 
600  if (target)
602 
603  return 0;
604 }
605 
607 {
608  HIMCC rc;
610  rc = ImmCreateIMCC(sizeof(COMPOSITIONSTRING));
611  ptr = ImmLockIMCC(rc);
612  memset(ptr,0,sizeof(COMPOSITIONSTRING));
613  ptr->dwSize = sizeof(COMPOSITIONSTRING);
614  ImmUnlockIMCC(rc);
615  return rc;
616 }
617 
619 {
620  InputContextData *data = hIMC;
621 
622  if (hIMC == NULL)
623  return NULL;
624 
625  if(IsBadReadPtr(data, sizeof(InputContextData)) || data->magic != WINE_IMC_VALID_MAGIC)
626  {
628  return NULL;
629  }
630  return data;
631 }
632 
634 {
635  HIMC ret;
637 
638  if (!thread_data) return 0;
639 
640  if (thread_data->defaultContext)
641  {
642  ret = thread_data->defaultContext;
644  return ret;
645  }
646 
647  /* can't create a default context in another thread */
648  if (thread_data->threadID != GetCurrentThreadId())
649  {
651  return 0;
652  }
653 
655 
656  ret = ImmCreateContext();
657  if (!ret) return 0;
658  ((InputContextData*)ret)->threadDefault = TRUE;
659 
660  /* thread_data is in the current thread so we can assume it's still valid */
662 
663  if (thread_data->defaultContext) /* someone beat us */
664  {
666  ret = thread_data->defaultContext;
667  }
668  else thread_data->defaultContext = ret;
669 
671  return ret;
672 }
673 
675 {
677 
678  if (hWnd)
679  {
681  if (thread != GetCurrentThreadId()) return TRUE;
682  }
683  data = get_imc_data(hIMC);
684  if (data && data->threadID != GetCurrentThreadId())
685  return TRUE;
686 
687  return FALSE;
688 }
689 
690 /***********************************************************************
691  * ImmAssociateContext (IMM32.@)
692  */
694 {
695  HIMC old = NULL;
697 
698  TRACE("(%p, %p):\n", hWnd, hIMC);
699 
700  if(hIMC && !data)
701  return NULL;
702 
703  /*
704  * If already associated just return
705  */
706  if (hIMC && data->IMC.hWnd == hWnd)
707  return hIMC;
708 
709  if (hIMC && IMM_IsCrossThreadAccess(hWnd, hIMC))
710  return NULL;
711 
712  if (hWnd)
713  {
714  HIMC defaultContext = get_default_context( hWnd );
716 
717  if (old == NULL)
718  old = defaultContext;
719  else if (old == (HIMC)-1)
720  old = NULL;
721 
722  if (hIMC != defaultContext)
723  {
724  if (hIMC == NULL) /* Meaning disable imm for that window*/
726  else
728  }
729 
730  if (old)
731  {
732  InputContextData *old_data = old;
733  if (old_data->IMC.hWnd == hWnd)
734  old_data->IMC.hWnd = NULL;
735  }
736  }
737 
738  if (!hIMC)
739  return old;
740 
741  if(GetActiveWindow() == data->IMC.hWnd)
742  {
744  data->IMC.hWnd = hWnd;
746  }
747 
748  return old;
749 }
750 
751 
752 /*
753  * Helper function for ImmAssociateContextEx
754  */
756 {
757  HIMC hImc = (HIMC)lParam;
759  return TRUE;
760 }
761 
762 /***********************************************************************
763  * ImmAssociateContextEx (IMM32.@)
764  */
766 {
767  TRACE("(%p, %p, 0x%x):\n", hWnd, hIMC, dwFlags);
768 
769  if (!hWnd)
770  return FALSE;
771 
772  switch (dwFlags)
773  {
774  case 0:
776  return TRUE;
777  case IACE_DEFAULT:
778  {
779  HIMC defaultContext = get_default_context( hWnd );
780  if (!defaultContext) return FALSE;
781  ImmAssociateContext(hWnd,defaultContext);
782  return TRUE;
783  }
787  return TRUE;
788  case IACE_CHILDREN:
790  return TRUE;
791  default:
792  FIXME("Unknown dwFlags 0x%x\n",dwFlags);
793  return FALSE;
794  }
795 }
796 
797 /***********************************************************************
798  * ImmConfigureIMEA (IMM32.@)
799  */
801  HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
802 {
803  ImmHkl *immHkl = IMM_GetImmHkl(hKL);
804 
805  TRACE("(%p, %p, %d, %p):\n", hKL, hWnd, dwMode, lpData);
806 
807  if (dwMode == IME_CONFIG_REGISTERWORD && !lpData)
808  return FALSE;
809 
810  if (immHkl->hIME && immHkl->pImeConfigure)
811  {
812  if (dwMode != IME_CONFIG_REGISTERWORD || !is_kbd_ime_unicode(immHkl))
813  return immHkl->pImeConfigure(hKL,hWnd,dwMode,lpData);
814  else
815  {
816  REGISTERWORDW rww;
817  REGISTERWORDA *rwa = lpData;
818  BOOL rc;
819 
820  rww.lpReading = strdupAtoW(rwa->lpReading);
821  rww.lpWord = strdupAtoW(rwa->lpWord);
822  rc = immHkl->pImeConfigure(hKL,hWnd,dwMode,&rww);
824  HeapFree(GetProcessHeap(),0,rww.lpWord);
825  return rc;
826  }
827  }
828  else
829  return FALSE;
830 }
831 
832 /***********************************************************************
833  * ImmConfigureIMEW (IMM32.@)
834  */
836  HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
837 {
838  ImmHkl *immHkl = IMM_GetImmHkl(hKL);
839 
840  TRACE("(%p, %p, %d, %p):\n", hKL, hWnd, dwMode, lpData);
841 
842  if (dwMode == IME_CONFIG_REGISTERWORD && !lpData)
843  return FALSE;
844 
845  if (immHkl->hIME && immHkl->pImeConfigure)
846  {
847  if (dwMode != IME_CONFIG_REGISTERWORD || is_kbd_ime_unicode(immHkl))
848  return immHkl->pImeConfigure(hKL,hWnd,dwMode,lpData);
849  else
850  {
851  REGISTERWORDW *rww = lpData;
852  REGISTERWORDA rwa;
853  BOOL rc;
854 
855  rwa.lpReading = strdupWtoA(rww->lpReading);
856  rwa.lpWord = strdupWtoA(rww->lpWord);
857  rc = immHkl->pImeConfigure(hKL,hWnd,dwMode,&rwa);
859  HeapFree(GetProcessHeap(),0,rwa.lpWord);
860  return rc;
861  }
862  }
863  else
864  return FALSE;
865 }
866 
867 /***********************************************************************
868  * ImmCreateContext (IMM32.@)
869  */
871 {
872  InputContextData *new_context;
873  LPGUIDELINE gl;
874  LPCANDIDATEINFO ci;
875  int i;
876 
878 
879  /* Load the IME */
880  new_context->immKbd = IMM_GetImmHkl(GetKeyboardLayout(0));
881 
882  if (!new_context->immKbd->hIME)
883  {
884  TRACE("IME dll could not be loaded\n");
885  HeapFree(GetProcessHeap(),0,new_context);
886  return 0;
887  }
888 
889  /* the HIMCCs are never NULL */
890  new_context->IMC.hCompStr = ImmCreateBlankCompStr();
891  new_context->IMC.hMsgBuf = ImmCreateIMCC(0);
892  new_context->IMC.hCandInfo = ImmCreateIMCC(sizeof(CANDIDATEINFO));
893  ci = ImmLockIMCC(new_context->IMC.hCandInfo);
894  memset(ci,0,sizeof(CANDIDATEINFO));
895  ci->dwSize = sizeof(CANDIDATEINFO);
896  ImmUnlockIMCC(new_context->IMC.hCandInfo);
897  new_context->IMC.hGuideLine = ImmCreateIMCC(sizeof(GUIDELINE));
898  gl = ImmLockIMCC(new_context->IMC.hGuideLine);
899  memset(gl,0,sizeof(GUIDELINE));
900  gl->dwSize = sizeof(GUIDELINE);
901  ImmUnlockIMCC(new_context->IMC.hGuideLine);
902 
903  for (i = 0; i < ARRAY_SIZE(new_context->IMC.cfCandForm); i++)
904  new_context->IMC.cfCandForm[i].dwIndex = ~0u;
905 
906  /* Initialize the IME Private */
907  new_context->IMC.hPrivate = ImmCreateIMCC(new_context->immKbd->imeInfo.dwPrivateDataSize);
908 
909  new_context->IMC.fdwConversion = new_context->immKbd->imeInfo.fdwConversionCaps;
910  new_context->IMC.fdwSentence = new_context->immKbd->imeInfo.fdwSentenceCaps;
911 
912  if (!new_context->immKbd->pImeSelect(new_context, TRUE))
913  {
914  TRACE("Selection of IME failed\n");
915  IMM_DestroyContext(new_context);
916  return 0;
917  }
918  new_context->threadID = GetCurrentThreadId();
919  SendMessageW(GetFocus(), WM_IME_SELECT, TRUE, (LPARAM)new_context->immKbd);
920 
921  new_context->immKbd->uSelected++;
922  TRACE("Created context %p\n",new_context);
923 
924  new_context->magic = WINE_IMC_VALID_MAGIC;
925  return new_context;
926 }
927 
929 {
931 
932  TRACE("Destroying %p\n",hIMC);
933 
934  if (!data)
935  return FALSE;
936 
937  data->immKbd->uSelected --;
938  data->immKbd->pImeSelect(hIMC, FALSE);
939  SendMessageW(data->IMC.hWnd, WM_IME_SELECT, FALSE, (LPARAM)data->immKbd);
940 
941  ImmDestroyIMCC(data->IMC.hCompStr);
942  ImmDestroyIMCC(data->IMC.hCandInfo);
943  ImmDestroyIMCC(data->IMC.hGuideLine);
944  ImmDestroyIMCC(data->IMC.hPrivate);
945  ImmDestroyIMCC(data->IMC.hMsgBuf);
946 
947  data->magic = 0;
949 
950  return TRUE;
951 }
952 
953 /***********************************************************************
954  * ImmDestroyContext (IMM32.@)
955  */
957 {
958  if (!IMM_IsDefaultContext(hIMC) && !IMM_IsCrossThreadAccess(NULL, hIMC))
959  return IMM_DestroyContext(hIMC);
960  else
961  return FALSE;
962 }
963 
964 /***********************************************************************
965  * ImmDisableIME (IMM32.@)
966  */
968 {
970 }
971 
972 /***********************************************************************
973  * ImmEnumRegisterWordA (IMM32.@)
974  */
976  HKL hKL, REGISTERWORDENUMPROCA lpfnEnumProc,
977  LPCSTR lpszReading, DWORD dwStyle,
978  LPCSTR lpszRegister, LPVOID lpData)
979 {
980  ImmHkl *immHkl = IMM_GetImmHkl(hKL);
981  TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL, lpfnEnumProc,
982  debugstr_a(lpszReading), dwStyle, debugstr_a(lpszRegister), lpData);
983  if (immHkl->hIME && immHkl->pImeEnumRegisterWord)
984  {
985  if (!is_kbd_ime_unicode(immHkl))
986  return immHkl->pImeEnumRegisterWord((REGISTERWORDENUMPROCW)lpfnEnumProc,
987  (LPCWSTR)lpszReading, dwStyle, (LPCWSTR)lpszRegister, lpData);
988  else
989  {
990  LPWSTR lpszwReading = strdupAtoW(lpszReading);
991  LPWSTR lpszwRegister = strdupAtoW(lpszRegister);
992  BOOL rc;
993 
994  rc = immHkl->pImeEnumRegisterWord((REGISTERWORDENUMPROCW)lpfnEnumProc,
995  lpszwReading, dwStyle, lpszwRegister,
996  lpData);
997 
998  HeapFree(GetProcessHeap(),0,lpszwReading);
999  HeapFree(GetProcessHeap(),0,lpszwRegister);
1000  return rc;
1001  }
1002  }
1003  else
1004  return 0;
1005 }
1006 
1007 /***********************************************************************
1008  * ImmEnumRegisterWordW (IMM32.@)
1009  */
1011  HKL hKL, REGISTERWORDENUMPROCW lpfnEnumProc,
1012  LPCWSTR lpszReading, DWORD dwStyle,
1013  LPCWSTR lpszRegister, LPVOID lpData)
1014 {
1015  ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1016  TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL, lpfnEnumProc,
1017  debugstr_w(lpszReading), dwStyle, debugstr_w(lpszRegister), lpData);
1018  if (immHkl->hIME && immHkl->pImeEnumRegisterWord)
1019  {
1020  if (is_kbd_ime_unicode(immHkl))
1021  return immHkl->pImeEnumRegisterWord(lpfnEnumProc, lpszReading, dwStyle,
1022  lpszRegister, lpData);
1023  else
1024  {
1025  LPSTR lpszaReading = strdupWtoA(lpszReading);
1026  LPSTR lpszaRegister = strdupWtoA(lpszRegister);
1027  BOOL rc;
1028 
1029  rc = immHkl->pImeEnumRegisterWord(lpfnEnumProc, (LPCWSTR)lpszaReading,
1030  dwStyle, (LPCWSTR)lpszaRegister, lpData);
1031 
1032  HeapFree(GetProcessHeap(),0,lpszaReading);
1033  HeapFree(GetProcessHeap(),0,lpszaRegister);
1034  return rc;
1035  }
1036  }
1037  else
1038  return 0;
1039 }
1040 
1041 static inline BOOL EscapeRequiresWA(UINT uEscape)
1042 {
1043  if (uEscape == IME_ESC_GET_EUDC_DICTIONARY ||
1044  uEscape == IME_ESC_SET_EUDC_DICTIONARY ||
1045  uEscape == IME_ESC_IME_NAME ||
1046  uEscape == IME_ESC_GETHELPFILENAME)
1047  return TRUE;
1048  return FALSE;
1049 }
1050 
1051 /***********************************************************************
1052  * ImmEscapeA (IMM32.@)
1053  */
1055  HKL hKL, HIMC hIMC,
1056  UINT uEscape, LPVOID lpData)
1057 {
1058  ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1059  TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData);
1060 
1061  if (immHkl->hIME && immHkl->pImeEscape)
1062  {
1063  if (!EscapeRequiresWA(uEscape) || !is_kbd_ime_unicode(immHkl))
1064  return immHkl->pImeEscape(hIMC,uEscape,lpData);
1065  else
1066  {
1067  WCHAR buffer[81]; /* largest required buffer should be 80 */
1068  LRESULT rc;
1069  if (uEscape == IME_ESC_SET_EUDC_DICTIONARY)
1070  {
1071  MultiByteToWideChar(CP_ACP,0,lpData,-1,buffer,81);
1072  rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
1073  }
1074  else
1075  {
1076  rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
1077  WideCharToMultiByte(CP_ACP,0,buffer,-1,lpData,80, NULL, NULL);
1078  }
1079  return rc;
1080  }
1081  }
1082  else
1083  return 0;
1084 }
1085 
1086 /***********************************************************************
1087  * ImmEscapeW (IMM32.@)
1088  */
1090  HKL hKL, HIMC hIMC,
1091  UINT uEscape, LPVOID lpData)
1092 {
1093  ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1094  TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData);
1095 
1096  if (immHkl->hIME && immHkl->pImeEscape)
1097  {
1098  if (!EscapeRequiresWA(uEscape) || is_kbd_ime_unicode(immHkl))
1099  return immHkl->pImeEscape(hIMC,uEscape,lpData);
1100  else
1101  {
1102  CHAR buffer[81]; /* largest required buffer should be 80 */
1103  LRESULT rc;
1104  if (uEscape == IME_ESC_SET_EUDC_DICTIONARY)
1105  {
1106  WideCharToMultiByte(CP_ACP,0,lpData,-1,buffer,81, NULL, NULL);
1107  rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
1108  }
1109  else
1110  {
1111  rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
1112  MultiByteToWideChar(CP_ACP,0,buffer,-1,lpData,80);
1113  }
1114  return rc;
1115  }
1116  }
1117  else
1118  return 0;
1119 }
1120 
1121 #define ROUNDUP4(n) (((n) + 3) & ~3) /* DWORD alignment */
1122 
1125 
1126 /* flags for g_dwImm32Flags */
1127 #define IMM32_FLAG_UNKNOWN 0x4
1128 #define IMM32_FLAG_CICERO_ENABLED 0x20
1129 
1131 {
1132  if (!g_hImm32Heap)
1133  {
1134  g_hImm32Heap = RtlGetProcessHeap();
1135  if (g_hImm32Heap == NULL)
1136  return NULL;
1137  }
1138  return HeapAlloc(g_hImm32Heap, dwFlags, dwBytes);
1139 }
1140 
1141 static DWORD_PTR APIENTRY
1143 {
1144  return NtUserGetThreadState(Routine);
1145 }
1146 
1148 {
1149  return NtUserQueryWindow(hWnd, Index);
1150 }
1151 
1152 static DWORD APIENTRY
1153 Imm32UpdateInputContext(HIMC hIMC, DWORD Unknown1, PCLIENTIMC pClientImc)
1154 {
1155  return NtUserUpdateInputContext(hIMC, Unknown1, pClientImc);
1156 }
1157 
1159 {
1160  // FIXME: Do something properly here
1161  return NULL;
1162 }
1163 
1165 {
1166  PCLIENTIMC pClientImc;
1167 
1168  TRACE("ImmLockClientImc(%p)\n", hImc);
1169 
1170  if (hImc == NULL)
1171  return NULL;
1172 
1173  pClientImc = Imm32GetClientImcCache();
1174  if (!pClientImc)
1175  {
1176  pClientImc = Imm32HeapAlloc(HEAP_ZERO_MEMORY, sizeof(CLIENTIMC));
1177  if (!pClientImc)
1178  return NULL;
1179 
1180  RtlInitializeCriticalSection(&pClientImc->cs);
1182 
1183  if (!Imm32UpdateInputContext(hImc, 0, pClientImc))
1184  {
1185  HeapFree(g_hImm32Heap, 0, pClientImc);
1186  return NULL;
1187  }
1188 
1189  pClientImc->dwFlags |= CLIENTIMC_UNKNOWN2;
1190  }
1191  else
1192  {
1193  if (pClientImc->dwFlags & CLIENTIMC_UNKNOWN1)
1194  return NULL;
1195  }
1196 
1197  InterlockedIncrement(&pClientImc->cLockObj);
1198  return pClientImc;
1199 }
1200 
1202 {
1203  LONG cLocks;
1204  HIMC hImc;
1205 
1206  TRACE("ImmUnlockClientImc(%p)\n", pClientImc);
1207 
1208  cLocks = InterlockedDecrement(&pClientImc->cLockObj);
1209  if (cLocks != 0 || !(pClientImc->dwFlags & CLIENTIMC_UNKNOWN1))
1210  return;
1211 
1212  hImc = pClientImc->hImc;
1213  if (hImc)
1214  LocalFree(hImc);
1215 
1216  RtlDeleteCriticalSection(&pClientImc->cs);
1217  HeapFree(g_hImm32Heap, 0, pClientImc);
1218 }
1219 
1220 static DWORD APIENTRY
1222  UINT uCodePage)
1223 {
1224  BOOL bUsedDefault;
1225  DWORD dwSize, dwIndex, cbGot, cbLeft;
1226  const BYTE *pbWide;
1227  LPBYTE pbAnsi;
1228  LPDWORD pibOffsets;
1229 
1230  /* calculate total ansi size */
1231  if (pWideCL->dwCount > 0)
1232  {
1233  dwSize = sizeof(CANDIDATELIST) + ((pWideCL->dwCount - 1) * sizeof(DWORD));
1234  for (dwIndex = 0; dwIndex < pWideCL->dwCount; ++dwIndex)
1235  {
1236  pbWide = (const BYTE *)pWideCL + pWideCL->dwOffset[dwIndex];
1237  cbGot = WideCharToMultiByte(uCodePage, 0, (LPCWSTR)pbWide, -1, NULL, 0,
1238  NULL, &bUsedDefault);
1239  dwSize += cbGot;
1240  }
1241  }
1242  else
1243  {
1244  dwSize = sizeof(CANDIDATELIST);
1245  }
1246 
1247  dwSize = ROUNDUP4(dwSize);
1248  if (dwBufLen == 0)
1249  return dwSize;
1250  if (dwBufLen < dwSize)
1251  return 0;
1252 
1253  /* store to ansi */
1254  pAnsiCL->dwSize = dwBufLen;
1255  pAnsiCL->dwStyle = pWideCL->dwStyle;
1256  pAnsiCL->dwCount = pWideCL->dwCount;
1257  pAnsiCL->dwSelection = pWideCL->dwSelection;
1258  pAnsiCL->dwPageStart = pWideCL->dwPageStart;
1259  pAnsiCL->dwPageSize = pWideCL->dwPageSize;
1260 
1261  pibOffsets = pAnsiCL->dwOffset;
1262  if (pWideCL->dwCount > 0)
1263  {
1264  pibOffsets[0] = sizeof(CANDIDATELIST) + ((pWideCL->dwCount - 1) * sizeof(DWORD));
1265  cbLeft = dwBufLen - pibOffsets[0];
1266 
1267  for (dwIndex = 0; dwIndex < pWideCL->dwCount; ++dwIndex)
1268  {
1269  pbWide = (const BYTE *)pWideCL + pWideCL->dwOffset[dwIndex];
1270  pbAnsi = (LPBYTE)pAnsiCL + pibOffsets[dwIndex];
1271 
1272  /* convert to ansi */
1273  cbGot = WideCharToMultiByte(uCodePage, 0, (LPCWSTR)pbWide, -1,
1274  (LPSTR)pbAnsi, cbLeft, NULL, &bUsedDefault);
1275  cbLeft -= cbGot;
1276 
1277  if (dwIndex < pWideCL->dwCount - 1)
1278  pibOffsets[dwIndex + 1] = pibOffsets[dwIndex] + cbGot;
1279  }
1280  }
1281  else
1282  {
1283  pibOffsets[0] = sizeof(CANDIDATELIST);
1284  }
1285 
1286  return dwBufLen;
1287 }
1288 
1289 static DWORD APIENTRY
1291  UINT uCodePage)
1292 {
1293  DWORD dwSize, dwIndex, cchGot, cbGot, cbLeft;
1294  const BYTE *pbAnsi;
1295  LPBYTE pbWide;
1296  LPDWORD pibOffsets;
1297 
1298  /* calculate total wide size */
1299  if (pAnsiCL->dwCount > 0)
1300  {
1301  dwSize = sizeof(CANDIDATELIST) + ((pAnsiCL->dwCount - 1) * sizeof(DWORD));
1302  for (dwIndex = 0; dwIndex < pAnsiCL->dwCount; ++dwIndex)
1303  {
1304  pbAnsi = (const BYTE *)pAnsiCL + pAnsiCL->dwOffset[dwIndex];
1305  cchGot = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED, (LPCSTR)pbAnsi, -1, NULL, 0);
1306  dwSize += cchGot * sizeof(WCHAR);
1307  }
1308  }
1309  else
1310  {
1311  dwSize = sizeof(CANDIDATELIST);
1312  }
1313 
1314  dwSize = ROUNDUP4(dwSize);
1315  if (dwBufLen == 0)
1316  return dwSize;
1317  if (dwBufLen < dwSize)
1318  return 0;
1319 
1320  /* store to wide */
1321  pWideCL->dwSize = dwBufLen;
1322  pWideCL->dwStyle = pAnsiCL->dwStyle;
1323  pWideCL->dwCount = pAnsiCL->dwCount;
1324  pWideCL->dwSelection = pAnsiCL->dwSelection;
1325  pWideCL->dwPageStart = pAnsiCL->dwPageStart;
1326  pWideCL->dwPageSize = pAnsiCL->dwPageSize;
1327 
1328  pibOffsets = pWideCL->dwOffset;
1329  if (pAnsiCL->dwCount > 0)
1330  {
1331  pibOffsets[0] = sizeof(CANDIDATELIST) + ((pWideCL->dwCount - 1) * sizeof(DWORD));
1332  cbLeft = dwBufLen - pibOffsets[0];
1333 
1334  for (dwIndex = 0; dwIndex < pAnsiCL->dwCount; ++dwIndex)
1335  {
1336  pbAnsi = (const BYTE *)pAnsiCL + pAnsiCL->dwOffset[dwIndex];
1337  pbWide = (LPBYTE)pWideCL + pibOffsets[dwIndex];
1338 
1339  /* convert to wide */
1340  cchGot = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED, (LPCSTR)pbAnsi, -1,
1341  (LPWSTR)pbWide, cbLeft / sizeof(WCHAR));
1342  cbGot = cchGot * sizeof(WCHAR);
1343  cbLeft -= cbGot;
1344 
1345  if (dwIndex + 1 < pAnsiCL->dwCount)
1346  pibOffsets[dwIndex + 1] = pibOffsets[dwIndex] + cbGot;
1347  }
1348  }
1349  else
1350  {
1351  pibOffsets[0] = sizeof(CANDIDATELIST);
1352  }
1353 
1354  return dwBufLen;
1355 }
1356 
1357 static DWORD APIENTRY
1359  BOOL bAnsi)
1360 {
1361  DWORD ret = 0;
1362  LPINPUTCONTEXT pIC;
1363  PCLIENTIMC pClientImc;
1364  LPCANDIDATEINFO pCI;
1365  LPCANDIDATELIST pCL;
1366  DWORD dwSize;
1367 
1368  pClientImc = ImmLockClientImc(hIMC);
1369  if (!pClientImc)
1370  return 0;
1371 
1372  pIC = ImmLockIMC(hIMC);
1373  if (pIC == NULL)
1374  {
1375  ImmUnlockClientImc(pClientImc);
1376  return 0;
1377  }
1378 
1379  pCI = ImmLockIMCC(pIC->hCandInfo);
1380  if (pCI == NULL)
1381  {
1382  ImmUnlockIMC(hIMC);
1383  ImmUnlockClientImc(pClientImc);
1384  return 0;
1385  }
1386 
1387  if (pCI->dwSize < sizeof(CANDIDATEINFO) || pCI->dwCount <= dwIndex)
1388  goto Quit;
1389 
1390  /* get required size */
1391  pCL = (LPCANDIDATELIST)((LPBYTE)pCI + pCI->dwOffset[dwIndex]);
1392  if (bAnsi)
1393  {
1394  if (pClientImc->dwFlags & CLIENTIMC_WIDE)
1396  else
1397  dwSize = pCL->dwSize;
1398  }
1399  else
1400  {
1401  if (pClientImc->dwFlags & CLIENTIMC_WIDE)
1402  dwSize = pCL->dwSize;
1403  else
1405  }
1406 
1407  if (dwBufLen != 0 && dwSize != 0)
1408  {
1409  if (lpCandList == NULL || dwBufLen < dwSize)
1410  goto Quit;
1411 
1412  /* store */
1413  if (bAnsi)
1414  {
1415  if (pClientImc->dwFlags & CLIENTIMC_WIDE)
1416  CandidateListAnsiToWide(pCL, lpCandList, dwSize, CP_ACP);
1417  else
1418  RtlCopyMemory(lpCandList, pCL, dwSize);
1419  }
1420  else
1421  {
1422  if (pClientImc->dwFlags & CLIENTIMC_WIDE)
1423  RtlCopyMemory(lpCandList, pCL, dwSize);
1424  else
1425  CandidateListWideToAnsi(pCL, lpCandList, dwSize, CP_ACP);
1426  }
1427  }
1428 
1429  ret = dwSize;
1430 
1431 Quit:
1432  ImmUnlockIMCC(pIC->hCandInfo);
1433  ImmUnlockIMC(hIMC);
1434  ImmUnlockClientImc(pClientImc);
1435  return ret;
1436 }
1437 
1439 {
1440  DWORD ret = 0, cbGot, dwIndex;
1441  PCLIENTIMC pClientImc;
1442  LPINPUTCONTEXT pIC;
1443  const CANDIDATEINFO *pCI;
1444  const BYTE *pb;
1445  const CANDIDATELIST *pCL;
1446  const DWORD *pdwOffsets;
1447 
1448  if (lpdwListCount == NULL)
1449  return 0;
1450 
1451  *lpdwListCount = 0;
1452 
1453  pClientImc = ImmLockClientImc(hIMC);
1454  if (pClientImc == NULL)
1455  return 0;
1456 
1457  pIC = ImmLockIMC(hIMC);
1458  if (pIC == NULL)
1459  {
1460  ImmUnlockClientImc(pClientImc);
1461  return 0;
1462  }
1463 
1464  pCI = ImmLockIMCC(pIC->hCandInfo);
1465  if (pCI == NULL)
1466  {
1467  ImmUnlockIMC(hIMC);
1468  ImmUnlockClientImc(pClientImc);
1469  return 0;
1470  }
1471 
1472  if (pCI->dwSize < sizeof(CANDIDATEINFO))
1473  goto Quit;
1474 
1475  *lpdwListCount = pCI->dwCount; /* the number of candidate lists */
1476 
1477  /* calculate total size of candidate lists */
1478  if (bAnsi)
1479  {
1480  if (pClientImc->dwFlags & CLIENTIMC_WIDE)
1481  {
1482  ret = ROUNDUP4(pCI->dwPrivateSize);
1483  pdwOffsets = pCI->dwOffset;
1484  for (dwIndex = 0; dwIndex < pCI->dwCount; ++dwIndex)
1485  {
1486  pb = (const BYTE *)pCI + pdwOffsets[dwIndex];
1487  pCL = (const CANDIDATELIST *)pb;
1488  cbGot = CandidateListWideToAnsi(pCL, NULL, 0, CP_ACP);
1489  ret += cbGot;
1490  }
1491  }
1492  else
1493  {
1494  ret = pCI->dwSize;
1495  }
1496  }
1497  else
1498  {
1499  if (pClientImc->dwFlags & CLIENTIMC_WIDE)
1500  {
1501  ret = pCI->dwSize;
1502  }
1503  else
1504  {
1505  ret = ROUNDUP4(pCI->dwPrivateSize);
1506  pdwOffsets = pCI->dwOffset;
1507  for (dwIndex = 0; dwIndex < pCI->dwCount; ++dwIndex)
1508  {
1509  pb = (const BYTE *)pCI + pdwOffsets[dwIndex];
1510  pCL = (const CANDIDATELIST *)pb;
1511  cbGot = CandidateListAnsiToWide(pCL, NULL, 0, CP_ACP);
1512  ret += cbGot;
1513  }
1514  }
1515  }
1516 
1517 Quit:
1518  ImmUnlockIMCC(pIC->hCandInfo);
1519  ImmUnlockIMC(hIMC);
1520  ImmUnlockClientImc(pClientImc);
1521  return ret;
1522 }
1523 
1524 /***********************************************************************
1525  * ImmGetCandidateListA (IMM32.@)
1526  */
1528  HIMC hIMC, DWORD dwIndex,
1529  LPCANDIDATELIST lpCandList, DWORD dwBufLen)
1530 {
1531  return ImmGetCandidateListAW(hIMC, dwIndex, lpCandList, dwBufLen, TRUE);
1532 }
1533 
1534 /***********************************************************************
1535  * ImmGetCandidateListCountA (IMM32.@)
1536  */
1538  HIMC hIMC, LPDWORD lpdwListCount)
1539 {
1540  return ImmGetCandidateListCountAW(hIMC, lpdwListCount, TRUE);
1541 }
1542 
1543 /***********************************************************************
1544  * ImmGetCandidateListCountW (IMM32.@)
1545  */
1547  HIMC hIMC, LPDWORD lpdwListCount)
1548 {
1549  return ImmGetCandidateListCountAW(hIMC, lpdwListCount, FALSE);
1550 }
1551 
1552 /***********************************************************************
1553  * ImmGetCandidateListW (IMM32.@)
1554  */
1556  HIMC hIMC, DWORD dwIndex,
1557  LPCANDIDATELIST lpCandList, DWORD dwBufLen)
1558 {
1559  return ImmGetCandidateListAW(hIMC, dwIndex, lpCandList, dwBufLen, FALSE);
1560 }
1561 
1562 /***********************************************************************
1563  * ImmGetCandidateWindow (IMM32.@)
1564  */
1566  HIMC hIMC, DWORD dwIndex, LPCANDIDATEFORM lpCandidate)
1567 {
1568  BOOL ret = FALSE;
1569  LPINPUTCONTEXT pIC;
1570  LPCANDIDATEFORM pCF;
1571 
1572  TRACE("ImmGetCandidateWindow(%p, %lu, %p)\n", hIMC, dwIndex, lpCandidate);
1573 
1574  pIC = ImmLockIMC(hIMC);
1575  if (pIC == NULL)
1576  return FALSE;
1577 
1578  pCF = &pIC->cfCandForm[dwIndex];
1579  if (pCF->dwIndex != IMM_INVALID_CANDFORM)
1580  {
1581  *lpCandidate = *pCF;
1582  ret = TRUE;
1583  }
1584 
1585  ImmUnlockIMC(hIMC);
1586  return ret;
1587 }
1588 
1590 {
1591  size_t cch;
1592  RtlCopyMemory(plfW, plfA, offsetof(LOGFONTA, lfFaceName));
1595  plfW->lfFaceName, _countof(plfW->lfFaceName));
1596  if (cch > _countof(plfW->lfFaceName) - 1)
1597  cch = _countof(plfW->lfFaceName) - 1;
1598  plfW->lfFaceName[cch] = 0;
1599 }
1600 
1602 {
1603  size_t cch;
1604  RtlCopyMemory(plfA, plfW, offsetof(LOGFONTW, lfFaceName));
1607  plfA->lfFaceName, _countof(plfA->lfFaceName), NULL, NULL);
1608  if (cch > _countof(plfA->lfFaceName) - 1)
1609  cch = _countof(plfA->lfFaceName) - 1;
1610  plfA->lfFaceName[cch] = 0;
1611 }
1612 
1613 /***********************************************************************
1614  * ImmGetCompositionFontA (IMM32.@)
1615  */
1617 {
1618  PCLIENTIMC pClientImc;
1619  BOOL ret = FALSE, bWide;
1620  LPINPUTCONTEXT pIC;
1621 
1622  TRACE("ImmGetCompositionFontA(%p, %p)\n", hIMC, lplf);
1623 
1624  pClientImc = ImmLockClientImc(hIMC);
1625  if (pClientImc == NULL)
1626  return FALSE;
1627 
1628  bWide = (pClientImc->dwFlags & CLIENTIMC_WIDE);
1629  ImmUnlockClientImc(pClientImc);
1630 
1631  pIC = ImmLockIMC(hIMC);
1632  if (pIC == NULL)
1633  return FALSE;
1634 
1635  if (pIC->fdwInit & INIT_LOGFONT)
1636  {
1637  if (bWide)
1638  LogFontWideToAnsi(&pIC->lfFont.W, lplf);
1639  else
1640  *lplf = pIC->lfFont.A;
1641 
1642  ret = TRUE;
1643  }
1644 
1645  ImmUnlockIMC(hIMC);
1646  return ret;
1647 }
1648 
1649 /***********************************************************************
1650  * ImmGetCompositionFontW (IMM32.@)
1651  */
1653 {
1654  PCLIENTIMC pClientImc;
1655  BOOL bWide;
1656  LPINPUTCONTEXT pIC;
1657  BOOL ret = FALSE;
1658 
1659  TRACE("ImmGetCompositionFontW(%p, %p)\n", hIMC, lplf);
1660 
1661  pClientImc = ImmLockClientImc(hIMC);
1662  if (pClientImc == NULL)
1663  return FALSE;
1664 
1665  bWide = (pClientImc->dwFlags & CLIENTIMC_WIDE);
1666  ImmUnlockClientImc(pClientImc);
1667 
1668  pIC = ImmLockIMC(hIMC);
1669  if (pIC == NULL)
1670  return FALSE;
1671 
1672  if (pIC->fdwInit & INIT_LOGFONT)
1673  {
1674  if (bWide)
1675  *lplf = pIC->lfFont.W;
1676  else
1677  LogFontAnsiToWide(&pIC->lfFont.A, lplf);
1678 
1679  ret = TRUE;
1680  }
1681 
1682  ImmUnlockIMC(hIMC);
1683  return ret;
1684 }
1685 
1686 
1687 /* Helpers for the GetCompositionString functions */
1688 
1689 /* Source encoding is defined by context, source length is always given in respective characters. Destination buffer
1690  length is always in bytes. */
1691 static INT CopyCompStringIMEtoClient(const InputContextData *data, const void *src, INT src_len, void *dst,
1692  INT dst_len, BOOL unicode)
1693 {
1694  int char_size = unicode ? sizeof(WCHAR) : sizeof(char);
1695  INT ret;
1696 
1697  if (is_himc_ime_unicode(data) ^ unicode)
1698  {
1699  if (unicode)
1700  ret = MultiByteToWideChar(CP_ACP, 0, src, src_len, dst, dst_len / sizeof(WCHAR));
1701  else
1702  ret = WideCharToMultiByte(CP_ACP, 0, src, src_len, dst, dst_len, NULL, NULL);
1703  ret *= char_size;
1704  }
1705  else
1706  {
1707  if (dst_len)
1708  {
1709  ret = min(src_len * char_size, dst_len);
1710  memcpy(dst, src, ret);
1711  }
1712  else
1713  ret = src_len * char_size;
1714  }
1715 
1716  return ret;
1717 }
1718 
1719 /* Composition string encoding is defined by context, returned attributes correspond to string, converted according to
1720  passed mode. String length is in characters, attributes are in byte arrays. */
1721 static INT CopyCompAttrIMEtoClient(const InputContextData *data, const BYTE *src, INT src_len, const void *comp_string,
1722  INT str_len, BYTE *dst, INT dst_len, BOOL unicode)
1723 {
1724  union
1725  {
1726  const void *str;
1727  const WCHAR *strW;
1728  const char *strA;
1729  } string;
1730  INT rc;
1731 
1732  string.str = comp_string;
1733 
1734  if (is_himc_ime_unicode(data) && !unicode)
1735  {
1736  rc = WideCharToMultiByte(CP_ACP, 0, string.strW, str_len, NULL, 0, NULL, NULL);
1737  if (dst_len)
1738  {
1739  int i, j = 0, k = 0;
1740 
1741  if (rc < dst_len)
1742  dst_len = rc;
1743  for (i = 0; i < str_len; ++i)
1744  {
1745  int len;
1746 
1747  len = WideCharToMultiByte(CP_ACP, 0, string.strW + i, 1, NULL, 0, NULL, NULL);
1748  for (; len > 0; --len)
1749  {
1750  dst[j++] = src[k];
1751 
1752  if (j >= dst_len)
1753  goto end;
1754  }
1755  ++k;
1756  }
1757  end:
1758  rc = j;
1759  }
1760  }
1761  else if (!is_himc_ime_unicode(data) && unicode)
1762  {
1763  rc = MultiByteToWideChar(CP_ACP, 0, string.strA, str_len, NULL, 0);
1764  if (dst_len)
1765  {
1766  int i, j = 0;
1767 
1768  if (rc < dst_len)
1769  dst_len = rc;
1770  for (i = 0; i < str_len; ++i)
1771  {
1772  if (IsDBCSLeadByte(string.strA[i]))
1773  continue;
1774 
1775  dst[j++] = src[i];
1776 
1777  if (j >= dst_len)
1778  break;
1779  }
1780  rc = j;
1781  }
1782  }
1783  else
1784  {
1785  memcpy(dst, src, min(src_len, dst_len));
1786  rc = src_len;
1787  }
1788 
1789  return rc;
1790 }
1791 
1793  LPBYTE target, INT tlen, BOOL unicode )
1794 {
1795  INT rc;
1796 
1797  if (is_himc_ime_unicode(data) && !unicode)
1798  {
1799  if (tlen)
1800  {
1801  int i;
1802 
1803  if (slen < tlen)
1804  tlen = slen;
1805  tlen /= sizeof (DWORD);
1806  for (i = 0; i < tlen; ++i)
1807  {
1808  ((DWORD *)target)[i] = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource,
1809  ((DWORD *)source)[i],
1810  NULL, 0,
1811  NULL, NULL);
1812  }
1813  rc = sizeof (DWORD) * i;
1814  }
1815  else
1816  rc = slen;
1817  }
1818  else if (!is_himc_ime_unicode(data) && unicode)
1819  {
1820  if (tlen)
1821  {
1822  int i;
1823 
1824  if (slen < tlen)
1825  tlen = slen;
1826  tlen /= sizeof (DWORD);
1827  for (i = 0; i < tlen; ++i)
1828  {
1829  ((DWORD *)target)[i] = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource,
1830  ((DWORD *)source)[i],
1831  NULL, 0);
1832  }
1833  rc = sizeof (DWORD) * i;
1834  }
1835  else
1836  rc = slen;
1837  }
1838  else
1839  {
1840  memcpy( target, source, min(slen,tlen));
1841  rc = slen;
1842  }
1843 
1844  return rc;
1845 }
1846 
1848 {
1849  int rc;
1850 
1851  if (is_himc_ime_unicode(data) && !unicode)
1852  {
1853  rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, offset, NULL, 0, NULL, NULL);
1854  }
1855  else if (!is_himc_ime_unicode(data) && unicode)
1856  {
1857  rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, offset, NULL, 0);
1858  }
1859  else
1860  rc = offset;
1861 
1862  return rc;
1863 }
1864 
1865 static LONG ImmGetCompositionStringT( HIMC hIMC, DWORD dwIndex, LPVOID lpBuf,
1866  DWORD dwBufLen, BOOL unicode)
1867 {
1868  LONG rc = 0;
1870  LPCOMPOSITIONSTRING compstr;
1871  LPBYTE compdata;
1872 
1873  TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
1874 
1875  if (!data)
1876  return FALSE;
1877 
1878  if (!data->IMC.hCompStr)
1879  return FALSE;
1880 
1881  compdata = ImmLockIMCC(data->IMC.hCompStr);
1882  compstr = (LPCOMPOSITIONSTRING)compdata;
1883 
1884  switch (dwIndex)
1885  {
1886  case GCS_RESULTSTR:
1887  TRACE("GCS_RESULTSTR\n");
1888  rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultStrOffset, compstr->dwResultStrLen, lpBuf, dwBufLen, unicode);
1889  break;
1890  case GCS_COMPSTR:
1891  TRACE("GCS_COMPSTR\n");
1892  rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen, lpBuf, dwBufLen, unicode);
1893  break;
1894  case GCS_COMPATTR:
1895  TRACE("GCS_COMPATTR\n");
1896  rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompAttrOffset, compstr->dwCompAttrLen,
1897  compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen,
1898  lpBuf, dwBufLen, unicode);
1899  break;
1900  case GCS_COMPCLAUSE:
1901  TRACE("GCS_COMPCLAUSE\n");
1902  rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompClauseOffset,compstr->dwCompClauseLen,
1903  compdata + compstr->dwCompStrOffset,
1904  lpBuf, dwBufLen, unicode);
1905  break;
1906  case GCS_RESULTCLAUSE:
1907  TRACE("GCS_RESULTCLAUSE\n");
1908  rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultClauseOffset,compstr->dwResultClauseLen,
1909  compdata + compstr->dwResultStrOffset,
1910  lpBuf, dwBufLen, unicode);
1911  break;
1912  case GCS_RESULTREADSTR:
1913  TRACE("GCS_RESULTREADSTR\n");
1914  rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultReadStrOffset, compstr->dwResultReadStrLen, lpBuf, dwBufLen, unicode);
1915  break;
1916  case GCS_RESULTREADCLAUSE:
1917  TRACE("GCS_RESULTREADCLAUSE\n");
1919  compdata + compstr->dwResultStrOffset,
1920  lpBuf, dwBufLen, unicode);
1921  break;
1922  case GCS_COMPREADSTR:
1923  TRACE("GCS_COMPREADSTR\n");
1924  rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen, lpBuf, dwBufLen, unicode);
1925  break;
1926  case GCS_COMPREADATTR:
1927  TRACE("GCS_COMPREADATTR\n");
1928  rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompReadAttrOffset, compstr->dwCompReadAttrLen,
1929  compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen,
1930  lpBuf, dwBufLen, unicode);
1931  break;
1932  case GCS_COMPREADCLAUSE:
1933  TRACE("GCS_COMPREADCLAUSE\n");
1934  rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompReadClauseOffset,compstr->dwCompReadClauseLen,
1935  compdata + compstr->dwCompStrOffset,
1936  lpBuf, dwBufLen, unicode);
1937  break;
1938  case GCS_CURSORPOS:
1939  TRACE("GCS_CURSORPOS\n");
1940  rc = CopyCompOffsetIMEtoClient(data, compstr->dwCursorPos, compdata + compstr->dwCompStrOffset, unicode);
1941  break;
1942  case GCS_DELTASTART:
1943  TRACE("GCS_DELTASTART\n");
1944  rc = CopyCompOffsetIMEtoClient(data, compstr->dwDeltaStart, compdata + compstr->dwCompStrOffset, unicode);
1945  break;
1946  default:
1947  FIXME("Unhandled index 0x%x\n",dwIndex);
1948  break;
1949  }
1950 
1951  ImmUnlockIMCC(data->IMC.hCompStr);
1952 
1953  return rc;
1954 }
1955 
1956 /***********************************************************************
1957  * ImmGetCompositionStringA (IMM32.@)
1958  */
1960  HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
1961 {
1962  return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, FALSE);
1963 }
1964 
1965 
1966 /***********************************************************************
1967  * ImmGetCompositionStringW (IMM32.@)
1968  */
1970  HIMC hIMC, DWORD dwIndex,
1971  LPVOID lpBuf, DWORD dwBufLen)
1972 {
1973  return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, TRUE);
1974 }
1975 
1976 /***********************************************************************
1977  * ImmGetCompositionWindow (IMM32.@)
1978  */
1980 {
1981  LPINPUTCONTEXT pIC;
1982  BOOL ret = FALSE;
1983 
1984  TRACE("ImmGetCompositionWindow(%p, %p)\n", hIMC, lpCompForm);
1985 
1986  pIC = ImmLockIMC(hIMC);
1987  if (!pIC)
1988  return FALSE;
1989 
1990  if (pIC->fdwInit & INIT_COMPFORM)
1991  {
1992  *lpCompForm = pIC->cfCompForm;
1993  ret = TRUE;
1994  }
1995 
1996  ImmUnlockIMC(hIMC);
1997  return ret;
1998 }
1999 
2000 /***********************************************************************
2001  * ImmGetContext (IMM32.@)
2002  *
2003  */
2005 {
2006  HIMC rc;
2007 
2008  TRACE("%p\n", hWnd);
2009 
2010  if (!IsWindow(hWnd))
2011  {
2013  return NULL;
2014  }
2015 
2017  if (rc == (HIMC)-1)
2018  rc = NULL;
2019  else if (rc == NULL)
2020  rc = get_default_context( hWnd );
2021 
2022  if (rc)
2023  {
2024  InputContextData *data = rc;
2025  data->IMC.hWnd = hWnd;
2026  }
2027 
2028  TRACE("returning %p\n", rc);
2029 
2030  return rc;
2031 }
2032 
2033 /***********************************************************************
2034  * ImmGetConversionListA (IMM32.@)
2035  */
2037  HKL hKL, HIMC hIMC,
2038  LPCSTR pSrc, LPCANDIDATELIST lpDst,
2039  DWORD dwBufLen, UINT uFlag)
2040 {
2041  ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2042  TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL, hIMC, debugstr_a(pSrc), lpDst,
2043  dwBufLen, uFlag);
2044  if (immHkl->hIME && immHkl->pImeConversionList)
2045  {
2046  if (!is_kbd_ime_unicode(immHkl))
2047  return immHkl->pImeConversionList(hIMC,(LPCWSTR)pSrc,lpDst,dwBufLen,uFlag);
2048  else
2049  {
2050  LPCANDIDATELIST lpwDst;
2051  DWORD ret = 0, len;
2052  LPWSTR pwSrc = strdupAtoW(pSrc);
2053 
2054  len = immHkl->pImeConversionList(hIMC, pwSrc, NULL, 0, uFlag);
2055  lpwDst = HeapAlloc(GetProcessHeap(), 0, len);
2056  if ( lpwDst )
2057  {
2058  immHkl->pImeConversionList(hIMC, pwSrc, lpwDst, len, uFlag);
2059  ret = convert_candidatelist_WtoA( lpwDst, lpDst, dwBufLen);
2060  HeapFree(GetProcessHeap(), 0, lpwDst);
2061  }
2062  HeapFree(GetProcessHeap(), 0, pwSrc);
2063 
2064  return ret;
2065  }
2066  }
2067  else
2068  return 0;
2069 }
2070 
2071 /***********************************************************************
2072  * ImmGetConversionListW (IMM32.@)
2073  */
2075  HKL hKL, HIMC hIMC,
2076  LPCWSTR pSrc, LPCANDIDATELIST lpDst,
2077  DWORD dwBufLen, UINT uFlag)
2078 {
2079  ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2080  TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL, hIMC, debugstr_w(pSrc), lpDst,
2081  dwBufLen, uFlag);
2082  if (immHkl->hIME && immHkl->pImeConversionList)
2083  {
2084  if (is_kbd_ime_unicode(immHkl))
2085  return immHkl->pImeConversionList(hIMC,pSrc,lpDst,dwBufLen,uFlag);
2086  else
2087  {
2088  LPCANDIDATELIST lpaDst;
2089  DWORD ret = 0, len;
2090  LPSTR paSrc = strdupWtoA(pSrc);
2091 
2092  len = immHkl->pImeConversionList(hIMC, (LPCWSTR)paSrc, NULL, 0, uFlag);
2093  lpaDst = HeapAlloc(GetProcessHeap(), 0, len);
2094  if ( lpaDst )
2095  {
2096  immHkl->pImeConversionList(hIMC, (LPCWSTR)paSrc, lpaDst, len, uFlag);
2097  ret = convert_candidatelist_AtoW( lpaDst, lpDst, dwBufLen);
2098  HeapFree(GetProcessHeap(), 0, lpaDst);
2099  }
2100  HeapFree(GetProcessHeap(), 0, paSrc);
2101 
2102  return ret;
2103  }
2104  }
2105  else
2106  return 0;
2107 }
2108 
2109 /***********************************************************************
2110  * ImmGetConversionStatus (IMM32.@)
2111  */
2113  HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence)
2114 {
2115  LPINPUTCONTEXT pIC;
2116 
2117  TRACE("ImmGetConversionStatus(%p %p %p)\n", hIMC, lpfdwConversion, lpfdwSentence);
2118 
2119  pIC = ImmLockIMC(hIMC);
2120  if (!pIC)
2121  return FALSE;
2122 
2123  if (lpfdwConversion)
2124  *lpfdwConversion = pIC->fdwConversion;
2125  if (lpfdwSentence)
2126  *lpfdwSentence = pIC->fdwSentence;
2127 
2128  ImmUnlockIMC(hIMC);
2129  return TRUE;
2130 }
2131 
2133 {
2134  WCHAR classW[8];
2135 
2137  return FALSE;
2138  if (GetClassLongPtrW(hwnd, GCL_STYLE) & CS_IME) return FALSE;
2139 
2140  return TRUE;
2141 }
2142 
2143 /***********************************************************************
2144  * __wine_register_window (IMM32.@)
2145  */
2147 {
2148  HWND new = NULL;
2150  TRACE("(%p)\n", hwnd);
2151 
2152  if (!needs_ime_window(hwnd))
2153  return FALSE;
2154 
2156  if (!thread_data)
2157  return FALSE;
2158 
2159  if (thread_data->disableIME || disable_ime)
2160  {
2161  TRACE("IME for this thread is disabled\n");
2163  return FALSE;
2164  }
2165  thread_data->windowRefs++;
2166  TRACE("windowRefs=%u, hwndDefault=%p\n",
2167  thread_data->windowRefs, thread_data->hwndDefault);
2168 
2169  /* Create default IME window */
2170  if (thread_data->windowRefs == 1)
2171  {
2172  /* Do not create the window inside of a critical section */
2176  0, 0, 1, 1, 0, 0, 0, 0);
2177  /* thread_data is in the current thread so we can assume it's still valid */
2179  /* See if anyone beat us */
2180  if (thread_data->hwndDefault == NULL)
2181  {
2182  thread_data->hwndDefault = new;
2183  new = NULL;
2184  TRACE("Default is %p\n", thread_data->hwndDefault);
2185  }
2186  }
2187 
2189 
2190  /* Clean up an unused new window outside of the critical section */
2191  if (new != NULL)
2192  DestroyWindow(new);
2193  return TRUE;
2194 }
2195 
2196 /***********************************************************************
2197  * __wine_unregister_window (IMM32.@)
2198  */
2200 {
2201  HWND to_destroy = 0;
2203  TRACE("(%p)\n", hwnd);
2204 
2206  if (!thread_data) return;
2207 
2208  thread_data->windowRefs--;
2209  TRACE("windowRefs=%u, hwndDefault=%p\n",
2210  thread_data->windowRefs, thread_data->hwndDefault);
2211 
2212  /* Destroy default IME window */
2213  if (thread_data->windowRefs == 0 && thread_data->hwndDefault)
2214  {
2215  to_destroy = thread_data->hwndDefault;
2216  thread_data->hwndDefault = NULL;
2217  }
2219 
2220  if (to_destroy) DestroyWindow( to_destroy );
2221 }
2222 
2223 /***********************************************************************
2224  * ImmGetDefaultIMEWnd (IMM32.@)
2225  */
2227 {
2229  return NULL;
2230 
2231  if (hWnd == NULL)
2233 
2235 }
2236 
2237 /***********************************************************************
2238  * CtfImmIsCiceroEnabled (IMM32.@)
2239  */
2241 {
2243 }
2244 
2245 /***********************************************************************
2246  * ImmGetDescriptionA (IMM32.@)
2247  */
2249  HKL hKL, LPSTR lpszDescription, UINT uBufLen)
2250 {
2251  IMEINFOEX info;
2252  size_t cch;
2253 
2254  TRACE("ImmGetDescriptionA(%p,%p,%d)\n", hKL, lpszDescription, uBufLen);
2255 
2256  if (!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayout, &hKL) || !IS_IME_HKL(hKL))
2257  return 0;
2258 
2259  StringCchLengthW(info.wszImeDescription, _countof(info.wszImeDescription), &cch);
2260  cch = WideCharToMultiByte(CP_ACP, 0, info.wszImeDescription, (INT)cch,
2261  lpszDescription, uBufLen, NULL, NULL);
2262  if (uBufLen)
2263  lpszDescription[cch] = 0;
2264  return cch;
2265 }
2266 
2267 /***********************************************************************
2268  * ImmGetDescriptionW (IMM32.@)
2269  */
2270 UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen)
2271 {
2272  IMEINFOEX info;
2273  size_t cch;
2274 
2275  TRACE("ImmGetDescriptionW(%p, %p, %d)\n", hKL, lpszDescription, uBufLen);
2276 
2277  if (!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayout, &hKL) || !IS_IME_HKL(hKL))
2278  return 0;
2279 
2280  if (uBufLen != 0)
2281  StringCchCopyW(lpszDescription, uBufLen, info.wszImeDescription);
2282 
2283  StringCchLengthW(info.wszImeDescription, _countof(info.wszImeDescription), &cch);
2284  return (UINT)cch;
2285 }
2286 
2287 /***********************************************************************
2288  * ImmGetGuideLineA (IMM32.@)
2289  */
2291  HIMC hIMC, DWORD dwIndex, LPSTR lpBuf, DWORD dwBufLen)
2292 {
2293  FIXME("(%p, %d, %s, %d): stub\n",
2294  hIMC, dwIndex, debugstr_a(lpBuf), dwBufLen
2295  );
2297  return 0;
2298 }
2299 
2300 /***********************************************************************
2301  * ImmGetGuideLineW (IMM32.@)
2302  */
2304 {
2305  FIXME("(%p, %d, %s, %d): stub\n",
2306  hIMC, dwIndex, debugstr_w(lpBuf), dwBufLen
2307  );
2309  return 0;
2310 }
2311 
2312 /***********************************************************************
2313  * ImmGetIMEFileNameA (IMM32.@)
2314  */
2315 UINT WINAPI ImmGetIMEFileNameA( HKL hKL, LPSTR lpszFileName, UINT uBufLen)
2316 {
2317  BOOL bDefUsed;
2318  IMEINFOEX info;
2319  size_t cch;
2320 
2321  TRACE("ImmGetIMEFileNameA(%p, %p, %u)\n", hKL, lpszFileName, uBufLen);
2322 
2323  if (!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayout, &hKL) || !IS_IME_HKL(hKL))
2324  {
2325  if (uBufLen > 0)
2326  lpszFileName[0] = 0;
2327  return 0;
2328  }
2329 
2330  StringCchLengthW(info.wszImeFile, _countof(info.wszImeFile), &cch);
2331 
2332  cch = WideCharToMultiByte(CP_ACP, 0, info.wszImeFile, (INT)cch,
2333  lpszFileName, uBufLen, NULL, &bDefUsed);
2334  if (uBufLen == 0)
2335  return (UINT)cch;
2336 
2337  if (cch > uBufLen - 1)
2338  cch = uBufLen - 1;
2339 
2340  lpszFileName[cch] = 0;
2341  return (UINT)cch;
2342 }
2343 
2344 /***********************************************************************
2345  * ImmGetIMEFileNameW (IMM32.@)
2346  */
2347 UINT WINAPI ImmGetIMEFileNameW(HKL hKL, LPWSTR lpszFileName, UINT uBufLen)
2348 {
2349  IMEINFOEX info;
2350  size_t cch;
2351 
2352  TRACE("ImmGetIMEFileNameW(%p, %p, %u)\n", hKL, lpszFileName, uBufLen);
2353 
2354  if (!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayout, &hKL) || !IS_IME_HKL(hKL))
2355  {
2356  if (uBufLen > 0)
2357  lpszFileName[0] = 0;
2358  return 0;
2359  }
2360 
2361  StringCchLengthW(info.wszImeFile, _countof(info.wszImeFile), &cch);
2362  if (uBufLen == 0)
2363  return (UINT)cch;
2364 
2365  StringCchCopyNW(lpszFileName, uBufLen, info.wszImeFile, cch);
2366 
2367  if (cch > uBufLen - 1)
2368  cch = uBufLen - 1;
2369 
2370  lpszFileName[cch] = 0;
2371  return (UINT)cch;
2372 }
2373 
2374 /***********************************************************************
2375  * ImmGetOpenStatus (IMM32.@)
2376  */
2378 {
2379  BOOL ret;
2380  LPINPUTCONTEXT pIC;
2381 
2382  TRACE("ImmGetOpenStatus(%p)\n", hIMC);
2383 
2384  if (!hIMC)
2385  return FALSE;
2386 
2387  pIC = ImmLockIMC(hIMC);
2388  if (!pIC)
2389  return FALSE;
2390 
2391  ret = pIC->fOpen;
2392 
2393  ImmUnlockIMC(hIMC);
2394  return ret;
2395 }
2396 
2397 /***********************************************************************
2398  * ImmGetProperty (IMM32.@)
2399  */
2401 {
2402  DWORD rc = 0;
2403  ImmHkl *kbd;
2404 
2405  TRACE("(%p, %d)\n", hKL, fdwIndex);
2406  kbd = IMM_GetImmHkl(hKL);
2407 
2408  if (kbd && kbd->hIME)
2409  {
2410  switch (fdwIndex)
2411  {
2412  case IGP_PROPERTY: rc = kbd->imeInfo.fdwProperty; break;
2413  case IGP_CONVERSION: rc = kbd->imeInfo.fdwConversionCaps; break;
2414  case IGP_SENTENCE: rc = kbd->imeInfo.fdwSentenceCaps; break;
2415  case IGP_SETCOMPSTR: rc = kbd->imeInfo.fdwSCSCaps; break;
2416  case IGP_SELECT: rc = kbd->imeInfo.fdwSelectCaps; break;
2417  case IGP_GETIMEVERSION: rc = IMEVER_0400; break;
2418  case IGP_UI: rc = 0; break;
2419  default: rc = 0;
2420  }
2421  }
2422  return rc;
2423 }
2424 
2425 /***********************************************************************
2426  * ImmGetRegisterWordStyleA (IMM32.@)
2427  */
2429  HKL hKL, UINT nItem, LPSTYLEBUFA lpStyleBuf)
2430 {
2431  ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2432  TRACE("(%p, %d, %p):\n", hKL, nItem, lpStyleBuf);
2433  if (immHkl->hIME && immHkl->pImeGetRegisterWordStyle)
2434  {
2435  if (!is_kbd_ime_unicode(immHkl))
2436  return immHkl->pImeGetRegisterWordStyle(nItem,(LPSTYLEBUFW)lpStyleBuf);
2437  else
2438  {
2439  STYLEBUFW sbw;
2440  UINT rc;
2441 
2442  rc = immHkl->pImeGetRegisterWordStyle(nItem,&sbw);
2444  lpStyleBuf->szDescription, 32, NULL, NULL);
2445  lpStyleBuf->dwStyle = sbw.dwStyle;
2446  return rc;
2447  }
2448  }
2449  else
2450  return 0;
2451 }
2452 
2453 /***********************************************************************
2454  * ImmGetRegisterWordStyleW (IMM32.@)
2455  */
2457  HKL hKL, UINT nItem, LPSTYLEBUFW lpStyleBuf)
2458 {
2459  ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2460  TRACE("(%p, %d, %p):\n", hKL, nItem, lpStyleBuf);
2461  if (immHkl->hIME && immHkl->pImeGetRegisterWordStyle)
2462  {
2463  if (is_kbd_ime_unicode(immHkl))
2464  return immHkl->pImeGetRegisterWordStyle(nItem,lpStyleBuf);
2465  else
2466  {
2467  STYLEBUFA sba;
2468  UINT rc;
2469 
2470  rc = immHkl->pImeGetRegisterWordStyle(nItem,(LPSTYLEBUFW)&sba);
2472  lpStyleBuf->szDescription, 32);
2473  lpStyleBuf->dwStyle = sba.dwStyle;
2474  return rc;
2475  }
2476  }
2477  else
2478  return 0;
2479 }
2480 
2481 /***********************************************************************
2482  * ImmGetStatusWindowPos (IMM32.@)
2483  */
2485 {
2486  LPINPUTCONTEXT pIC;
2487  BOOL ret;
2488 
2489  TRACE("ImmGetStatusWindowPos(%p, %p)\n", hIMC, lpptPos);
2490 
2491  pIC = ImmLockIMC(hIMC);
2492  if (pIC == NULL)
2493  return FALSE;
2494 
2495  ret = !!(pIC->fdwInit & INIT_STATUSWNDPOS);
2496  if (ret)
2497  *lpptPos = pIC->ptStatusWndPos;
2498 
2499  ImmUnlockIMC(hIMC);
2500  return ret;
2501 }
2502 
2503 /***********************************************************************
2504  * ImmGetVirtualKey (IMM32.@)
2505  */
2507 {
2510  TRACE("%p\n", hWnd);
2511 
2512  if ( data )
2513  return data->lastVK;
2514 
2515  version.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
2516  GetVersionExA( &version );
2517  switch(version.dwPlatformId)
2518  {
2520  return VK_PROCESSKEY;
2521  case VER_PLATFORM_WIN32_NT:
2522  return 0;
2523  default:
2524  FIXME("%d not supported\n",version.dwPlatformId);
2525  return VK_PROCESSKEY;
2526  }
2527 }
2528 
2529 /***********************************************************************
2530  * ImmInstallIMEA (IMM32.@)
2531  */
2533  LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
2534 {
2535  LPWSTR lpszwIMEFileName;
2536  LPWSTR lpszwLayoutText;
2537  HKL hkl;
2538 
2539  TRACE ("(%s, %s)\n", debugstr_a(lpszIMEFileName),
2540  debugstr_a(lpszLayoutText));
2541 
2542  lpszwIMEFileName = strdupAtoW(lpszIMEFileName);
2543  lpszwLayoutText = strdupAtoW(lpszLayoutText);
2544 
2545  hkl = ImmInstallIMEW(lpszwIMEFileName, lpszwLayoutText);
2546 
2547  HeapFree(GetProcessHeap(),0,lpszwIMEFileName);
2548  HeapFree(GetProcessHeap(),0,lpszwLayoutText);
2549  return hkl;
2550 }
2551 
2552 /***********************************************************************
2553  * ImmInstallIMEW (IMM32.@)
2554  */
2556  LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
2557 {
2558  INT lcid = GetUserDefaultLCID();
2559  INT count;
2560  HKL hkl;
2561  DWORD rc;
2562  HKEY hkey;
2563  WCHAR regKey[ARRAY_SIZE(szImeRegFmt)+8];
2564 
2565  TRACE ("(%s, %s):\n", debugstr_w(lpszIMEFileName),
2566  debugstr_w(lpszLayoutText));
2567 
2568  /* Start with 2. e001 will be blank and so default to the wine internal IME */
2569  count = 2;
2570 
2571  while (count < 0xfff)
2572  {
2573  DWORD disposition = 0;
2574 
2575  hkl = (HKL)MAKELPARAM( lcid, 0xe000 | count );
2576  wsprintfW( regKey, szImeRegFmt, (ULONG_PTR)hkl);
2577 
2578  rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, regKey, 0, NULL, 0, KEY_WRITE, NULL, &hkey, &disposition);
2579  if (rc == ERROR_SUCCESS && disposition == REG_CREATED_NEW_KEY)
2580  break;
2581  else if (rc == ERROR_SUCCESS)
2582  RegCloseKey(hkey);
2583 
2584  count++;
2585  }
2586 
2587  if (count == 0xfff)
2588  {
2589  WARN("Unable to find slot to install IME\n");
2590  return 0;
2591  }
2592 
2593  if (rc == ERROR_SUCCESS)
2594  {
2595  rc = RegSetValueExW(hkey, szImeFileW, 0, REG_SZ, (const BYTE*)lpszIMEFileName,
2596  (lstrlenW(lpszIMEFileName) + 1) * sizeof(WCHAR));
2597  if (rc == ERROR_SUCCESS)
2598  rc = RegSetValueExW(hkey, szLayoutTextW, 0, REG_SZ, (const BYTE*)lpszLayoutText,
2599  (lstrlenW(lpszLayoutText) + 1) * sizeof(WCHAR));
2600  RegCloseKey(hkey);
2601  return hkl;
2602  }
2603  else
2604  {
2605  WARN("Unable to set IME registry values\n");
2606  return 0;
2607  }
2608 }
2609 
2610 /***********************************************************************
2611  * ImmIsIME (IMM32.@)
2612  */
2614 {
2615  IMEINFOEX info;
2616  TRACE("ImmIsIME(%p)\n", hKL);
2617  return !!ImmGetImeInfoEx(&info, ImeInfoExImeWindow, &hKL);
2618 }
2619 
2620 /***********************************************************************
2621  * ImmIsUIMessageA (IMM32.@)
2622  */
2624  HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
2625 {
2626  TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam);
2627  if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
2628  (msg == WM_IME_SETCONTEXT) ||
2629  (msg == WM_IME_NOTIFY) ||
2630  (msg == WM_IME_COMPOSITIONFULL) ||
2631  (msg == WM_IME_SELECT) ||
2632  (msg == 0x287 /* FIXME: WM_IME_SYSTEM */))
2633  {
2634  if (hWndIME)
2635  SendMessageA(hWndIME, msg, wParam, lParam);
2636 
2637  return TRUE;
2638  }
2639  return FALSE;
2640 }
2641 
2642 /***********************************************************************
2643  * ImmIsUIMessageW (IMM32.@)
2644  */
2646  HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
2647 {
2648  TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam);
2649  if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
2650  (msg == WM_IME_SETCONTEXT) ||
2651  (msg == WM_IME_NOTIFY) ||
2652  (msg == WM_IME_COMPOSITIONFULL) ||
2653  (msg == WM_IME_SELECT) ||
2654  (msg == 0x287 /* FIXME: WM_IME_SYSTEM */))
2655  {
2656  if (hWndIME)
2657  SendMessageW(hWndIME, msg, wParam, lParam);
2658 
2659  return TRUE;
2660  }
2661  return FALSE;
2662 }
2663 
2664 /***********************************************************************
2665  * ImmNotifyIME (IMM32.@)
2666  */
2668  HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
2669 {
2670  DWORD dwImeThreadId, dwThreadId;
2671  HKL hKL;
2672  PIMEDPI pImeDpi;
2673  BOOL ret;
2674 
2675  TRACE("ImmNotifyIME(%p, %lu, %lu, %lu)\n", hIMC, dwAction, dwIndex, dwValue);
2676 
2677  if (hIMC)
2678  {
2679  dwImeThreadId = Imm32QueryWindow(hIMC, QUERY_WINDOW_UNIQUE_THREAD_ID);
2681  if (dwImeThreadId != dwThreadId)
2682  return FALSE;
2683  }
2684 
2685  hKL = GetKeyboardLayout(0);
2686  pImeDpi = ImmLockImeDpi(hKL);
2687  if (pImeDpi == NULL)
2688  return FALSE;
2689 
2690  ret = pImeDpi->NotifyIME(hIMC, dwAction, dwIndex, dwValue);
2691  ImmUnlockImeDpi(pImeDpi);
2692  return ret;
2693 }
2694 
2695 /***********************************************************************
2696  * ImmRegisterWordA (IMM32.@)
2697  */
2699  HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszRegister)
2700 {
2701  ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2702  TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_a(lpszReading), dwStyle,
2703  debugstr_a(lpszRegister));
2704  if (immHkl->hIME && immHkl->pImeRegisterWord)
2705  {
2706  if (!is_kbd_ime_unicode(immHkl))
2707  return immHkl->pImeRegisterWord((LPCWSTR)lpszReading,dwStyle,
2708  (LPCWSTR)lpszRegister);
2709  else
2710  {
2711  LPWSTR lpszwReading = strdupAtoW(lpszReading);
2712  LPWSTR lpszwRegister = strdupAtoW(lpszRegister);
2713  BOOL rc;
2714 
2715  rc = immHkl->pImeRegisterWord(lpszwReading,dwStyle,lpszwRegister);
2716  HeapFree(GetProcessHeap(),0,lpszwReading);
2717  HeapFree(GetProcessHeap(),0,lpszwRegister);
2718  return rc;
2719  }
2720  }
2721  else
2722  return FALSE;
2723 }
2724 
2725 /***********************************************************************
2726  * ImmRegisterWordW (IMM32.@)
2727  */
2729  HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszRegister)
2730 {
2731  ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2732  TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_w(lpszReading), dwStyle,
2733  debugstr_w(lpszRegister));
2734  if (immHkl->hIME && immHkl->pImeRegisterWord)
2735  {
2736  if (is_kbd_ime_unicode(immHkl))
2737  return immHkl->pImeRegisterWord(lpszReading,dwStyle,lpszRegister);
2738  else
2739  {
2740  LPSTR lpszaReading = strdupWtoA(lpszReading);
2741  LPSTR lpszaRegister = strdupWtoA(lpszRegister);
2742  BOOL rc;
2743 
2744  rc = immHkl->pImeRegisterWord((LPCWSTR)lpszaReading,dwStyle,
2745  (LPCWSTR)lpszaRegister);
2746  HeapFree(GetProcessHeap(),0,lpszaReading);
2747  HeapFree(GetProcessHeap(),0,lpszaRegister);
2748  return rc;
2749  }
2750  }
2751  else
2752  return FALSE;
2753 }
2754 
2755 /***********************************************************************
2756  * ImmReleaseContext (IMM32.@)
2757  */
2759 {
2760  static BOOL shown = FALSE;
2761 
2762  if (!shown) {
2763  FIXME("(%p, %p): stub\n", hWnd, hIMC);
2764  shown = TRUE;
2765  }
2766  return TRUE;
2767 }
2768 
2769 /***********************************************************************
2770 * ImmRequestMessageA(IMM32.@)
2771 */
2773 {
2775 
2776  TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
2777 
2778  if (data) return SendMessageA(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
2779 
2781  return 0;
2782 }
2783 
2784 /***********************************************************************
2785 * ImmRequestMessageW(IMM32.@)
2786 */
2788 {
2790 
2791  TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
2792 
2793  if (data) return SendMessageW(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
2794 
2796  return 0;
2797 }
2798 
2799 /***********************************************************************
2800  * ImmSetCandidateWindow (IMM32.@)
2801  */
2803  HIMC hIMC, LPCANDIDATEFORM lpCandidate)
2804 {
2806 
2807  TRACE("(%p, %p)\n", hIMC, lpCandidate);
2808 
2809  if (!data || !lpCandidate)
2810  return FALSE;
2811 
2812  if (IMM_IsCrossThreadAccess(NULL, hIMC))
2813  return FALSE;
2814 
2815  TRACE("\t%x, %x, %s, %s\n",
2816  lpCandidate->dwIndex, lpCandidate->dwStyle,
2817  wine_dbgstr_point(&lpCandidate->ptCurrentPos),
2818  wine_dbgstr_rect(&lpCandidate->rcArea));
2819 
2820  if (lpCandidate->dwIndex >= ARRAY_SIZE(data->IMC.cfCandForm))
2821  return FALSE;
2822 
2823  data->IMC.cfCandForm[lpCandidate->dwIndex] = *lpCandidate;
2826 
2827  return TRUE;
2828 }
2829 
2830 /***********************************************************************
2831  * ImmSetCompositionFontA (IMM32.@)
2832  */
2834 {
2836  TRACE("(%p, %p)\n", hIMC, lplf);
2837 
2838  if (!data || !lplf)
2839  {
2841  return FALSE;
2842  }
2843 
2844  if (IMM_IsCrossThreadAccess(NULL, hIMC))
2845  return FALSE;
2846 
2847  memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTA));
2848  MultiByteToWideChar(CP_ACP, 0, lplf->lfFaceName, -1, data->IMC.lfFont.W.lfFaceName,
2849  LF_FACESIZE);
2852 
2853  return TRUE;
2854 }
2855 
2856 /***********************************************************************
2857  * ImmSetCompositionFontW (IMM32.@)
2858  */
2860 {
2862  TRACE("(%p, %p)\n", hIMC, lplf);
2863 
2864  if (!data || !lplf)
2865  {
2867  return FALSE;
2868  }
2869 
2870  if (IMM_IsCrossThreadAccess(NULL, hIMC))
2871  return FALSE;
2872 
2873  data->IMC.lfFont.W = *lplf;
2876 
2877  return TRUE;
2878 }
2879 
2880 /***********************************************************************
2881  * ImmSetCompositionStringA (IMM32.@)
2882  */
2884  HIMC hIMC, DWORD dwIndex,
2885  LPCVOID lpComp, DWORD dwCompLen,
2886  LPCVOID lpRead, DWORD dwReadLen)
2887 {
2888  DWORD comp_len;
2889  DWORD read_len;
2890  WCHAR *CompBuffer = NULL;
2891  WCHAR *ReadBuffer = NULL;
2892  BOOL rc;
2894 
2895  TRACE("(%p, %d, %p, %d, %p, %d):\n",
2896  hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
2897 
2898  if (!data)
2899  return FALSE;
2900 
2901  if (!(dwIndex == SCS_SETSTR ||
2902  dwIndex == SCS_CHANGEATTR ||
2903  dwIndex == SCS_CHANGECLAUSE ||
2904  dwIndex == SCS_SETRECONVERTSTRING ||
2905  dwIndex == SCS_QUERYRECONVERTSTRING))
2906  return FALSE;
2907 
2908  if (!is_himc_ime_unicode(data))
2909  return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp,
2910  dwCompLen, lpRead, dwReadLen);
2911 
2912  comp_len = MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, NULL, 0);
2913  if (comp_len)
2914  {
2915  CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len * sizeof(WCHAR));
2916  MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len);
2917  }
2918 
2919  read_len = MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, NULL, 0);
2920  if (read_len)
2921  {
2922  ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len * sizeof(WCHAR));
2923  MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len);
2924  }
2925 
2926  rc = ImmSetCompositionStringW(hIMC, dwIndex, CompBuffer, comp_len,
2927  ReadBuffer, read_len);
2928 
2929  HeapFree(GetProcessHeap(), 0, CompBuffer);
2931 
2932  return rc;
2933 }
2934 
2935 /***********************************************************************
2936  * ImmSetCompositionStringW (IMM32.@)
2937  */
2939  HIMC hIMC, DWORD dwIndex,
2940  LPCVOID lpComp, DWORD dwCompLen,
2941  LPCVOID lpRead, DWORD dwReadLen)
2942 {
2943  DWORD comp_len;
2944  DWORD read_len;
2945  CHAR *CompBuffer = NULL;
2946  CHAR *ReadBuffer = NULL;
2947  BOOL rc;
2949 
2950  TRACE("(%p, %d, %p, %d, %p, %d):\n",
2951  hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
2952 
2953  if (!data)
2954  return FALSE;
2955 
2956  if (!(dwIndex == SCS_SETSTR ||
2957  dwIndex == SCS_CHANGEATTR ||
2958  dwIndex == SCS_CHANGECLAUSE ||
2959  dwIndex == SCS_SETRECONVERTSTRING ||
2960  dwIndex == SCS_QUERYRECONVERTSTRING))
2961  return FALSE;
2962 
2964  return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp,
2965  dwCompLen, lpRead, dwReadLen);
2966 
2967  comp_len = WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, NULL, 0, NULL,
2968  NULL);
2969  if (comp_len)
2970  {
2971  CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len);
2972  WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len,
2973  NULL, NULL);
2974  }
2975 
2976  read_len = WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, NULL, 0, NULL,
2977  NULL);
2978  if (read_len)
2979  {
2980  ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len);
2981  WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len,
2982  NULL, NULL);
2983  }
2984 
2985  rc = ImmSetCompositionStringA(hIMC, dwIndex, CompBuffer, comp_len,
2986  ReadBuffer, read_len);
2987 
2988  HeapFree(GetProcessHeap(), 0, CompBuffer);
2990 
2991  return rc;
2992 }
2993 
2994 /***********************************************************************
2995  * ImmSetCompositionWindow (IMM32.@)
2996  */
2998  HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
2999 {
3000  DWORD dwImeThreadId, dwThreadId;
3001  LPINPUTCONTEXT pIC;
3002  HWND hWnd;
3003 
3004  dwImeThreadId = NtUserQueryInputContext(hIMC, 1);
3006  if (dwImeThreadId != dwThreadId)
3007  return FALSE;
3008 
3009  pIC = ImmLockIMC(hIMC);
3010  if (pIC == NULL)
3011  return FALSE;
3012 
3013  pIC->cfCompForm = *lpCompForm;
3014  pIC->fdwInit |= INIT_COMPFORM;
3015 
3016  hWnd = pIC->hWnd;
3017 
3018  ImmUnlockIMC(hIMC);
3019 
3022  return TRUE;
3023 }
3024 
3025 /***********************************************************************
3026  * ImmSetConversionStatus (IMM32.@)
3027  */
3029  HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence)
3030 {
3031  DWORD oldConversion, oldSentence;
3033 
3034  TRACE("%p %d %d\n", hIMC, fdwConversion, fdwSentence);
3035 
3036  if (!data)
3037  {
3039  return FALSE;
3040  }
3041 
3042  if (IMM_IsCrossThreadAccess(NULL, hIMC))
3043  return FALSE;
3044 
3045  if ( fdwConversion != data->IMC.fdwConversion )
3046  {
3047  oldConversion = data->IMC.fdwConversion;
3048  data->IMC.fdwConversion = fdwConversion;
3049  ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, oldConversion, IMC_SETCONVERSIONMODE);
3051  }
3052  if ( fdwSentence != data->IMC.fdwSentence )
3053  {
3054  oldSentence = data->IMC.fdwSentence;
3055  data->IMC.fdwSentence = fdwSentence;
3056  ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, oldSentence, IMC_SETSENTENCEMODE);
3058  }
3059 
3060  return TRUE;
3061 }
3062 
3063 /***********************************************************************
3064  * ImmLockImeDpi (IMM32.@)
3065  */
3067 {
3068  PIMEDPI pImeDpi = NULL;
3069 
3070  TRACE("ImmLockImeDpi(%p)\n", hKL);
3071 
3073 
3074  /* Find by hKL */
3075  for (pImeDpi = g_pImeDpiList; pImeDpi; pImeDpi = pImeDpi->pNext)
3076  {
3077  if (pImeDpi->hKL == hKL) /* found */
3078  {
3079  /* lock if possible */
3080  if (pImeDpi->dwFlags & IMEDPI_FLAG_UNKNOWN)
3081  pImeDpi = NULL;
3082  else
3083  ++(pImeDpi->cLockObj);
3084  break;
3085  }
3086  }
3087 
3089  return pImeDpi;
3090 }
3091 
3092 /***********************************************************************
3093  * ImmUnlockImeDpi (IMM32.@)
3094  */
3096 {
3097  PIMEDPI *ppEntry;
3098 
3099  TRACE("ImmUnlockImeDpi(%p)\n", pImeDpi);
3100 
3101  if (pImeDpi == NULL)
3102  return;
3103 
3105 
3106  /* unlock */
3107  --(pImeDpi->cLockObj);
3108  if (pImeDpi->cLockObj != 0)
3109  {
3111  return;
3112  }
3113 
3114  if ((pImeDpi->dwFlags & IMEDPI_FLAG_UNKNOWN) == 0)
3115  {
3116  if ((pImeDpi->dwFlags & IMEDPI_FLAG_UNKNOWN2) == 0 ||
3117  (pImeDpi->dwUnknown1 & 1) == 0)
3118  {
3120  return;
3121  }
3122  }
3123 
3124  /* Remove from list */
3125  for (ppEntry = &g_pImeDpiList; *ppEntry; ppEntry = &((*ppEntry)->pNext))
3126  {
3127  if (*ppEntry == pImeDpi) /* found */
3128  {
3129  *ppEntry = pImeDpi->pNext;
3130  break;
3131  }
3132  }
3133 
3134  Imm32FreeImeDpi(pImeDpi, TRUE);
3135  HeapFree(g_hImm32Heap, 0, pImeDpi);
3136 
3138 }
3139 
3140 /***********************************************************************
3141  * ImmSetOpenStatus (IMM32.@)
3142  */
3144 {
3145  DWORD dwImeThreadId, dwThreadId, dwConversion;
3146  LPINPUTCONTEXT pIC;
3147  HWND hWnd;
3148  BOOL bHasChange = FALSE;
3149 
3150  TRACE("ImmSetOpenStatus(%p, %d)\n", hIMC, fOpen);
3151 
3152  dwImeThreadId = Imm32QueryInputContext(hIMC, 1);
3154  if (dwImeThreadId != dwThreadId)
3155  return FALSE;
3156 
3157  pIC = ImmLockIMC(hIMC);
3158  if (pIC == NULL)
3159  return FALSE;
3160 
3161  if (pIC->fOpen != fOpen)
3162  {
3163  pIC->fOpen = fOpen;
3164  hWnd = pIC->hWnd;
3165  dwConversion = pIC->fdwConversion;
3166  bHasChange = TRUE;
3167  }
3168 
3169  ImmUnlockIMC(hIMC);
3170 
3171  if (bHasChange)
3172  {
3175  Imm32NotifyIMEStatus(hWnd, hIMC, dwConversion);
3176  }
3177 
3178  return TRUE;
3179 }
3180 
3181 /***********************************************************************
3182  * ImmSetStatusWindowPos (IMM32.@)
3183  */
3185 {
3186  LPINPUTCONTEXT pIC;
3187  HWND hWnd;
3188  DWORD dwImeThreadId, dwThreadId;
3189 
3190  TRACE("ImmSetStatusWindowPos(%p, {%ld, %ld})\n", hIMC, lpptPos->x, lpptPos->y);
3191 
3192  dwImeThreadId = Imm32QueryInputContext(hIMC, 1);
3194  if (dwImeThreadId != dwThreadId)
3195  return FALSE;
3196 
3197  pIC = ImmLockIMC(hIMC);
3198  if (!pIC)
3199  return FALSE;
3200 
3201  hWnd = pIC->hWnd;
3202  pIC->ptStatusWndPos = *lpptPos;
3203  pIC->fdwInit |= INIT_STATUSWNDPOS;
3204 
3205  ImmUnlockIMC(hIMC);
3206 
3209  return TRUE;
3210 }
3211 
3212 /***********************************************************************
3213  * ImmCreateSoftKeyboard(IMM32.@)
3214  */
3215 HWND WINAPI ImmCreateSoftKeyboard(UINT uType, UINT hOwner, int x, int y)
3216 {
3217  FIXME("(%d, %d, %d, %d): stub\n", uType, hOwner, x, y);
3219  return 0;
3220 }
3221 
3222 /***********************************************************************
3223  * ImmDestroySoftKeyboard(IMM32.@)
3224  */
3226 {
3227  TRACE("(%p)\n", hSoftWnd);
3228  return DestroyWindow(hSoftWnd);
3229 }
3230 
3231 /***********************************************************************
3232  * ImmShowSoftKeyboard(IMM32.@)
3233  */
3234 BOOL WINAPI ImmShowSoftKeyboard(HWND hSoftWnd, int nCmdShow)
3235 {
3236  TRACE("(%p, %d)\n", hSoftWnd, nCmdShow);
3237  if (hSoftWnd)
3238  return ShowWindow(hSoftWnd, nCmdShow);
3239  return FALSE;
3240 }
3241 
3242 /***********************************************************************
3243  * ImmSimulateHotKey (IMM32.@)
3244  */
3246 {
3247  FIXME("(%p, %d): stub\n", hWnd, dwHotKeyID);
3249  return FALSE;
3250 }
3251 
3252 /***********************************************************************
3253  * ImmUnregisterWordA (IMM32.@)
3254  */
3256  HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszUnregister)
3257 {
3258  ImmHkl *immHkl = IMM_GetImmHkl(hKL);
3259  TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_a(lpszReading), dwStyle,
3260  debugstr_a(lpszUnregister));
3261  if (immHkl->hIME && immHkl->pImeUnregisterWord)
3262  {
3263  if (!is_kbd_ime_unicode(immHkl))
3264  return immHkl->pImeUnregisterWord((LPCWSTR)lpszReading,dwStyle,
3265  (LPCWSTR)lpszUnregister);
3266  else
3267  {
3268  LPWSTR lpszwReading = strdupAtoW(lpszReading);
3269  LPWSTR lpszwUnregister = strdupAtoW(lpszUnregister);
3270  BOOL rc;
3271 
3272  rc = immHkl->pImeUnregisterWord(lpszwReading,dwStyle,lpszwUnregister);
3273  HeapFree(GetProcessHeap(),0,lpszwReading);
3274  HeapFree(GetProcessHeap(),0,lpszwUnregister);
3275  return rc;
3276  }
3277  }
3278  else
3279  return FALSE;
3280 }
3281 
3282 /***********************************************************************
3283  * ImmUnregisterWordW (IMM32.@)
3284  */
3286  HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszUnregister)
3287 {
3288  ImmHkl *immHkl = IMM_GetImmHkl(hKL);
3289  TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_w(lpszReading), dwStyle,
3290  debugstr_w(lpszUnregister));
3291  if (immHkl->hIME && immHkl->pImeUnregisterWord)
3292  {
3293  if (is_kbd_ime_unicode(immHkl))
3294  return immHkl->pImeUnregisterWord(lpszReading,dwStyle,lpszUnregister);
3295  else
3296  {
3297  LPSTR lpszaReading = strdupWtoA(lpszReading);
3298  LPSTR lpszaUnregister = strdupWtoA(lpszUnregister);
3299  BOOL rc;
3300 
3301  rc = immHkl->pImeUnregisterWord((LPCWSTR)lpszaReading,dwStyle,
3302  (LPCWSTR)lpszaUnregister);
3303  HeapFree(GetProcessHeap(),0,lpszaReading);
3304  HeapFree(GetProcessHeap(),0,lpszaUnregister);
3305  return rc;
3306  }
3307  }
3308  else
3309  return FALSE;
3310 }
3311 
3312 /***********************************************************************
3313  * ImmGetImeMenuItemsA (IMM32.@)
3314  */
3316  LPIMEMENUITEMINFOA lpImeParentMenu, LPIMEMENUITEMINFOA lpImeMenu,
3317  DWORD dwSize)
3318 {
3320  TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
3321  lpImeParentMenu, lpImeMenu, dwSize);
3322 
3323  if (!data)
3324  {
3326  return 0;
3327  }
3328 
3329  if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
3330  {
3331  if (!is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
3332  return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
3333  (IMEMENUITEMINFOW*)lpImeParentMenu,
3334  (IMEMENUITEMINFOW*)lpImeMenu, dwSize);
3335  else
3336  {
3337  IMEMENUITEMINFOW lpImeParentMenuW;
3338  IMEMENUITEMINFOW *lpImeMenuW, *parent = NULL;
3339  DWORD rc;
3340 
3341  if (lpImeParentMenu)
3342  parent = &lpImeParentMenuW;
3343  if (lpImeMenu)
3344  {
3345  int count = dwSize / sizeof(LPIMEMENUITEMINFOA);
3346  dwSize = count * sizeof(IMEMENUITEMINFOW);
3347  lpImeMenuW = HeapAlloc(GetProcessHeap(), 0, dwSize);
3348  }
3349  else
3350  lpImeMenuW = NULL;
3351 
3352  rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
3353  parent, lpImeMenuW, dwSize);
3354 
3355  if (lpImeParentMenu)
3356  {
3357  memcpy(lpImeParentMenu,&lpImeParentMenuW,sizeof(IMEMENUITEMINFOA));
3358  lpImeParentMenu->hbmpItem = lpImeParentMenuW.hbmpItem;
3359  WideCharToMultiByte(CP_ACP, 0, lpImeParentMenuW.szString,
3360  -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE,
3361  NULL, NULL);
3362  }
3363  if (lpImeMenu && rc)
3364  {
3365  unsigned int i;
3366  for (i = 0; i < rc; i++)
3367  {
3368  memcpy(&lpImeMenu[i],&lpImeMenuW[1],sizeof(IMEMENUITEMINFOA));
3369  lpImeMenu[i].hbmpItem = lpImeMenuW[i].hbmpItem;
3370  WideCharToMultiByte(CP_ACP, 0, lpImeMenuW[i].szString,
3371  -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE,
3372  NULL, NULL);
3373  }
3374  }
3375  HeapFree(GetProcessHeap(),0,lpImeMenuW);
3376  return rc;
3377  }
3378  }
3379  else
3380  return 0;
3381 }
3382 
3383 /***********************************************************************
3384 * ImmGetImeMenuItemsW (IMM32.@)
3385 */
3387  LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu,
3388  DWORD dwSize)
3389 {
3391  TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
3392  lpImeParentMenu, lpImeMenu, dwSize);
3393 
3394  if (!data)
3395  {
3397  return 0;
3398  }
3399 
3400  if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
3401  {
3402  if (is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
3403  return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
3404  lpImeParentMenu, lpImeMenu, dwSize);
3405  else
3406  {
3407  IMEMENUITEMINFOA lpImeParentMenuA;
3408  IMEMENUITEMINFOA *lpImeMenuA, *parent = NULL;
3409  DWORD rc;
3410 
3411  if (lpImeParentMenu)
3412  parent = &lpImeParentMenuA;
3413  if (lpImeMenu)
3414  {
3415  int count = dwSize / sizeof(LPIMEMENUITEMINFOW);
3416  dwSize = count * sizeof(IMEMENUITEMINFOA);
3417  lpImeMenuA = HeapAlloc(GetProcessHeap(), 0, dwSize);
3418  }
3419  else
3420  lpImeMenuA = NULL;
3421 
3422  rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
3424  (IMEMENUITEMINFOW*)lpImeMenuA, dwSize);
3425 
3426  if (lpImeParentMenu)
3427  {
3428  memcpy(lpImeParentMenu,&lpImeParentMenuA,sizeof(IMEMENUITEMINFOA));
3429  lpImeParentMenu->hbmpItem = lpImeParentMenuA.hbmpItem;
3430  MultiByteToWideChar(CP_ACP, 0, lpImeParentMenuA.szString,
3431  -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE);
3432  }
3433  if (lpImeMenu && rc)
3434  {
3435  unsigned int i;
3436  for (i = 0; i < rc; i++)
3437  {
3438  memcpy(&lpImeMenu[i],&lpImeMenuA[1],sizeof(IMEMENUITEMINFOA));
3439  lpImeMenu[i].hbmpItem = lpImeMenuA[i].hbmpItem;
3440  MultiByteToWideChar(CP_ACP, 0, lpImeMenuA[i].szString,
3441  -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE);
3442  }
3443  }
3444  HeapFree(GetProcessHeap(),0,lpImeMenuA);
3445  return rc;
3446  }
3447  }
3448  else
3449  return 0;
3450 }
3451 
3452 /***********************************************************************
3453 * ImmLockIMC(IMM32.@)
3454 */
3456 {
3458 
3459  if (!data)
3460  return NULL;
3461  data->dwLock++;
3462  return &data->IMC;
3463 }
3464 
3465 /***********************************************************************
3466 * ImmUnlockIMC(IMM32.@)
3467 */
3469 {
3470  PCLIENTIMC pClientImc;
3471  HIMC hClientImc;
3472 
3473  pClientImc = ImmLockClientImc(hIMC);
3474  if (pClientImc == NULL)
3475  return FALSE;
3476 
3477  hClientImc = pClientImc->hImc;
3478  if (hClientImc)
3479  LocalUnlock(hClientImc);
3480 
3481  InterlockedDecrement(&pClientImc->cLockObj);
3482  ImmUnlockClientImc(pClientImc);
3483  return TRUE;
3484 }
3485 
3486 /***********************************************************************
3487 * ImmGetIMCLockCount(IMM32.@)
3488 */
3490 {
3491  DWORD ret;
3492  HIMC hClientImc;
3493  PCLIENTIMC pClientImc;
3494 
3495  pClientImc = ImmLockClientImc(hIMC);
3496  if (pClientImc == NULL)
3497  return 0;
3498 
3499  ret = 0;
3500  hClientImc = pClientImc->hImc;
3501  if (hClientImc)
3502  ret = (LocalFlags(hClientImc) & LMEM_LOCKCOUNT);
3503 
3504  ImmUnlockClientImc(pClientImc);
3505  return ret;
3506 }
3507 
3508 /***********************************************************************
3509 * ImmCreateIMCC(IMM32.@)
3510 */
3512 {
3513  if (size < 4)
3514  size = 4;
3515  return LocalAlloc(LHND, size);
3516 }
3517 
3518 /***********************************************************************
3519 * ImmDestroyIMCC(IMM32.@)
3520 */
3522 {
3523  if (block)
3524  return LocalFree(block);
3525  return NULL;
3526 }
3527 
3528 /***********************************************************************
3529 * ImmLockIMCC(IMM32.@)
3530 */
3532 {
3533  if (imcc)
3534  return LocalLock(imcc);
3535  return NULL;
3536 }
3537 
3538 /***********************************************************************
3539 * ImmUnlockIMCC(IMM32.@)
3540 */
3542 {
3543  if (imcc)
3544  return LocalUnlock(imcc);
3545  return FALSE;
3546 }
3547 
3548 /***********************************************************************
3549 * ImmGetIMCCLockCount(IMM32.@)
3550 */
3552 {
3553  return LocalFlags(imcc) & LMEM_LOCKCOUNT;
3554 }
3555 
3556 /***********************************************************************
3557 * ImmReSizeIMCC(IMM32.@)
3558 */
3560 {
3561  if (!imcc)
3562  return NULL;
3563  return LocalReAlloc(imcc, size, LHND);
3564 }
3565 
3566 /***********************************************************************
3567 * ImmGetIMCCSize(IMM32.@)
3568 */
3570 {
3571  if (imcc)
3572  return LocalSize(imcc);
3573  return 0;
3574 }
3575 
3576 /***********************************************************************
3577 * ImmGenerateMessage(IMM32.@)
3578 */
3580 {
3582 
3583  if (!data)
3584  {
3586  return FALSE;
3587  }
3588 
3589  TRACE("%i messages queued\n",data->IMC.dwNumMsgBuf);
3590  if (data->IMC.dwNumMsgBuf > 0)
3591  {
3592  LPTRANSMSG lpTransMsg;
3593  HIMCC hMsgBuf;
3594  DWORD i, dwNumMsgBuf;
3595 
3596  /* We are going to detach our hMsgBuff so that if processing messages
3597  generates new messages they go into a new buffer */
3598  hMsgBuf = data->IMC.hMsgBuf;
3599  dwNumMsgBuf = data->IMC.dwNumMsgBuf;
3600 
3601  data->IMC.hMsgBuf = ImmCreateIMCC(0);
3602  data->IMC.dwNumMsgBuf = 0;
3603 
3604  lpTransMsg = ImmLockIMCC(hMsgBuf);
3605  for (i = 0; i < dwNumMsgBuf; i++)
3606  ImmInternalSendIMEMessage(data, lpTransMsg[i].message, lpTransMsg[i].wParam, lpTransMsg[i].lParam);
3607 
3608  ImmUnlockIMCC(hMsgBuf);
3609  ImmDestroyIMCC(hMsgBuf);
3610  }
3611 
3612  return TRUE;
3613 }
3614 
3615 /***********************************************************************
3616 * ImmTranslateMessage(IMM32.@)
3617 * ( Undocumented, call internally and from user32.dll )
3618 */
3620 {
3622  HIMC imc = ImmGetContext(hwnd);
3623  BYTE state[256];
3624  UINT scancode;
3625  LPVOID list = 0;
3626  UINT msg_count;
3627  UINT uVirtKey;
3628  static const DWORD list_count = 10;
3629 
3630  TRACE("%p %x %x %x\n",hwnd, msg, (UINT)wParam, (UINT)lKeyData);
3631 
3632  if (imc)
3633  data = imc;
3634  else
3635  return FALSE;
3636 
3637  if (!data->immKbd->hIME || !data->immKbd->pImeToAsciiEx)
3638  return FALSE;
3639 
3641  scancode = lKeyData >> 0x10 & 0xff;
3642 
3644  ((DWORD*)list)[0] = list_count;
3645 
3646  if (data->immKbd->imeInfo.fdwProperty & IME_PROP_KBD_CHAR_FIRST)
3647  {
3648  WCHAR chr;
3649 
3650  if (!is_himc_ime_unicode(data))
3651  ToAscii(data->lastVK, scancode, state, &chr, 0);
3652  else
3653  ToUnicodeEx(data->lastVK, scancode, state, &chr, 1, 0, GetKeyboardLayout(0));
3654  uVirtKey = MAKELONG(data->lastVK,chr);
3655  }
3656  else
3657  uVirtKey = data->lastVK;
3658 
3659  msg_count = data->immKbd->pImeToAsciiEx(uVirtKey, scancode, state, list, 0, imc);
3660  TRACE("%i messages generated\n",msg_count);
3661  if (msg_count && msg_count <= list_count)
3662  {
3663  UINT i;
3664  LPTRANSMSG msgs = (LPTRANSMSG)((LPBYTE)list + sizeof(DWORD));
3665 
3666  for (i = 0; i < msg_count; i++)
3667  ImmInternalPostIMEMessage(data, msgs[i].message, msgs[i].wParam, msgs[i].lParam);
3668  }
3669  else if (msg_count > list_count)
3670  ImmGenerateMessage(imc);
3671 
3673 
3674  data->lastVK = VK_PROCESSKEY;
3675 
3676  return (msg_count > 0);
3677 }
3678 
3679 /***********************************************************************
3680 * ImmProcessKey(IMM32.@)
3681 * ( Undocumented, called from user32.dll )
3682 */
3684 {
3686  HIMC imc = ImmGetContext(hwnd);
3687  BYTE state[256];
3688 
3689  TRACE("%p %p %x %x %x\n",hwnd, hKL, vKey, (UINT)lKeyData, unknown);
3690 
3691  if (imc)
3692  data = imc;
3693  else
3694  return FALSE;
3695 
3696  /* Make sure we are inputting to the correct keyboard */
3697  if (data->immKbd->hkl != hKL)
3698  {
3699  ImmHkl *new_hkl = IMM_GetImmHkl(hKL);
3700  if (new_hkl)
3701  {
3702  data->immKbd->pImeSelect(imc, FALSE);
3703  data->immKbd->uSelected--;
3704  data->immKbd = new_hkl;
3705  data->immKbd->pImeSelect(imc, TRUE);
3706  data->immKbd->uSelected++;
3707  }
3708  else
3709  return FALSE;
3710  }
3711 
3712  if (!data->immKbd->hIME || !data->immKbd->pImeProcessKey)
3713  return FALSE;
3714 
3716  if (data->immKbd->pImeProcessKey(imc, vKey, lKeyData, state))
3717  {
3718  data->lastVK = vKey;
3719  return TRUE;
3720  }
3721 
3722  data->lastVK = VK_PROCESSKEY;
3723  return FALSE;
3724 }
3725 
3726 /***********************************************************************
3727 * ImmDisableTextFrameService(IMM32.@)
3728 */
3730 {
3731  FIXME("Stub\n");
3732  return FALSE;
3733 }
3734 
3735 /***********************************************************************
3736  * ImmEnumInputContext(IMM32.@)
3737  */
3738 
3740 {
3741  FIXME("Stub\n");
3742  return FALSE;
3743 }
3744 
3745 /***********************************************************************
3746  * ImmGetHotKey(IMM32.@)
3747  */
3748 
3749 BOOL WINAPI
3751  OUT LPUINT lpuModifiers,
3752  OUT LPUINT lpuVKey,
3753  OUT LPHKL lphKL)
3754 {
3755  TRACE("%lx, %p, %p, %p\n", dwHotKey, lpuModifiers, lpuVKey, lphKL);
3756  if (lpuModifiers && lpuVKey)
3757  return NtUserGetImeHotKey(dwHotKey, lpuModifiers, lpuVKey, lphKL);
3758  return FALSE;
3759 }
3760 
3761 /***********************************************************************
3762  * ImmDisableLegacyIME(IMM32.@)
3763  */
3765 {
3766  FIXME("stub\n");
3767  return TRUE;
3768 }
3769 
3770 /***********************************************************************
3771  * ImmSetActiveContext(IMM32.@)
3772  */
3774 {
3775  FIXME("(%p, %p, %d): stub\n", hwnd, hIMC, fFlag);
3776  return FALSE;
3777 }
3778 
3779 /***********************************************************************
3780  * ImmSetActiveContextConsoleIME(IMM32.@)
3781  */
3783 {
3784  HIMC hIMC;
3785  TRACE("(%p, %d)\n", hwnd, fFlag);
3786 
3787  hIMC = ImmGetContext(hwnd);
3788  if (hIMC)
3789  return ImmSetActiveContext(hwnd, hIMC, fFlag);
3790  return FALSE;
3791 }
3792 
3793 /***********************************************************************
3794 * ImmRegisterClient(IMM32.@)
3795 * ( Undocumented, called from user32.dll )
3796 */
3797 BOOL WINAPI ImmRegisterClient(PVOID ptr, /* FIXME: should point to SHAREDINFO structure */
3798  HINSTANCE hMod)
3799 {
3800  FIXME("Stub\n");
3801  return TRUE;
3802 }
3803 
3804 /***********************************************************************
3805  * CtfImmIsTextFrameServiceDisabled(IMM32.@)
3806  */
3808 {
3809  PTEB pTeb = NtCurrentTeb();
3810  if (((PW32CLIENTINFO)pTeb->Win32ClientInfo)->CI_flags & CI_TFSDISABLED)
3811  return TRUE;
3812  return FALSE;
3813 }
3814 
3815 /***********************************************************************
3816  * ImmGetImeInfoEx (IMM32.@)
3817  */
3818 
3820 {
3821  return NtUserGetImeInfoEx(pImeInfoEx, SearchType);
3822 }
3823 
3824 BOOL WINAPI
3826  IMEINFOEXCLASS SearchType,
3827  PVOID pvSearchKey)
3828 {
3829  BOOL bDisabled = FALSE;
3830  HKL hKL;
3831  PTEB pTeb;
3832 
3833  switch (SearchType)
3834  {
3836  break;
3837 
3838  case ImeInfoExImeWindow:
3839  bDisabled = CtfImmIsTextFrameServiceDisabled();
3840  SearchType = ImeInfoExKeyboardLayout;
3841  break;
3842 
3843  case ImeInfoExImeFileName:
3844  StringCchCopyW(pImeInfoEx->wszImeFile, _countof(pImeInfoEx->wszImeFile),
3845  pvSearchKey);
3846  goto Quit;
3847  }
3848 
3849  hKL = *(HKL*)pvSearchKey;
3850  pImeInfoEx->hkl = hKL;
3851 
3852  if (!IS_IME_HKL(hKL))
3853  {
3855  {
3856  pTeb = NtCurrentTeb();
3857  if (((PW32CLIENTINFO)pTeb->Win32ClientInfo)->W32ClientInfo[0] & 2)
3858  return FALSE;
3859  if (!bDisabled)
3860  goto Quit;
3861  }
3862  return FALSE;
3863  }
3864 
3865 Quit:
3866  return Imm32GetImeInfoEx(pImeInfoEx, SearchType);
3867 }
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
DWORD WINAPI ImmGetCandidateListCountW(HIMC hIMC, LPDWORD lpdwListCount)
Definition: imm.c:1546
int WINAPIV wsprintfW(_Out_ LPWSTR, _In_ _Printf_format_string_ LPCWSTR,...)
static unsigned int block
Definition: xmlmemory.c:118
DWORD WINAPI ImmGetCandidateListCountA(HIMC hIMC, LPDWORD lpdwListCount)
Definition: imm.c:1537
DWORD HIMCC
Definition: dimm.idl:76
static VOID APIENTRY LogFontWideToAnsi(const LOGFONTW *plfW, LPLOGFONTA plfA)
Definition: imm.c:1601
#define WS_CLIPSIBLINGS
Definition: pedump.c:618
LOGFONTA A
Definition: imm.h:35
static WCHAR * strdupAtoW(const char *str)
Definition: imm.c:258
static CHAR * strdupWtoA(const WCHAR *str)
Definition: imm.c:270
BOOL WINAPI EnumChildWindows(_In_opt_ HWND, _In_ WNDENUMPROC, _In_ LPARAM)
#define IACE_DEFAULT
Definition: imm.h:579
static const WCHAR classW[]
Definition: lex.c:40
#define IME_PROP_KBD_CHAR_FIRST
Definition: imm.h:214
#define LOAD_FUNCPTR(f)
Definition: imm.c:455
struct _tagTRANSMSG * LPTRANSMSG
#define WS_DISABLED
Definition: pedump.c:621
BOOL WINAPI ImmEnumInputContext(DWORD dwThreadId, IMCENUMPROC lpfn, LPARAM lParam)
Definition: imm.c:3739
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
static INT CopyCompClauseIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource, LPBYTE target, INT tlen, BOOL unicode)
Definition: imm.c:1792
char strA[12]
Definition: clipboard.c:2028
#define GCS_RESULTREADSTR
Definition: imm.h:367
#define WM_IME_NOTIFY
Definition: winuser.h:1812
#define IN
Definition: typedefs.h:39
BOOL WINAPI ImeConfigure(HKL, HWND, DWORD, LPVOID)
STRSAFEAPI StringCchCopyNW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc, size_t cchToCopy)
Definition: strsafe.h:236
static INT CopyCompAttrIMEtoClient(const InputContextData *data, const BYTE *src, INT src_len, const void *comp_string, INT str_len, BYTE *dst, INT dst_len, BOOL unicode)
Definition: imm.c:1721
#define VER_PLATFORM_WIN32_NT
Definition: rtltypes.h:236
ULONG Win32ClientInfo[31]
Definition: compat.h:706
Definition: tftpd.h:59
BOOL WINAPI ImmUnregisterWordW(HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszUnregister)
Definition: imm.c:3285
#define IMN_SETCONVERSIONMODE
Definition: imm.h:522
DWORD dwStyle
Definition: imm.h:85
#define QUERY_WINDOW_UNIQUE_THREAD_ID
Definition: ntuser.h:2842
#define IACE_IGNORENOCONTEXT
Definition: imm.h:580
PIMEDPI g_pImeDpiList
Definition: imm.c:57
BOOL disableIME
Definition: imm.c:219
static IMMThreadData * IMM_GetThreadData(HWND hwnd, DWORD thread)
Definition: imm.c:360
BOOL WINAPI ImmConfigureIMEW(HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
Definition: imm.c:835
DWORD dwStyle
Definition: dimm.idl:109
BOOL WINAPI ImmDisableTextFrameService(DWORD dwThreadId)
Definition: imm.c:3729
#define CloseHandle
Definition: compat.h:598
#define VK_PROCESSKEY
Definition: winuser.h:2302
struct tagCOMPOSITIONSTRING * LPCOMPOSITIONSTRING
#define LF_FACESIZE
Definition: dimm.idl:39
#define NI_CONTEXTUPDATED
Definition: imm.h:225
DWORD dwCompAttrLen
Definition: imm.h:171
HMODULE hIME
Definition: imm.c:169
BOOL NTAPI LocalUnlock(HLOCAL hMem)
Definition: heapmem.c:1788
DWORD_PTR NTAPI NtUserGetThreadState(DWORD Routine)
Definition: misc.c:231
LPARAM
Definition: imm.c:189
long y
Definition: polytest.cpp:48
DWORD dwCount
Definition: dimm.idl:94
DWORD dwPageSize
Definition: dimm.idl:97
#define ERROR_SUCCESS
Definition: deptool.c:10
BOOL WINAPI CtfImmIsCiceroEnabled(VOID)
Definition: imm.c:2240
BOOL WINAPI ImmDisableLegacyIME(void)
Definition: imm.c:3764
const WCHAR const WCHAR const WCHAR DWORD
Definition: imm.c:186
#define CS_IME
Definition: winuser.h:654
static HIMC get_default_context(HWND hwnd)
Definition: imm.c:633
#define IMC_SETSENTENCEMODE
Definition: imm.h:221
#define SCS_SETSTR
Definition: imm.h:450
#define DWORD_PTR
Definition: treelist.c:76
#define ROUNDUP4(n)
Definition: imm.c:1121
#define WideCharToMultiByte
Definition: compat.h:111
#define error(str)
Definition: mkdosfs.c:1605
#define IMC_SETCOMPOSITIONWINDOW
Definition: imm.h:278
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
BOOL WINAPI IsWindow(_In_opt_ HWND)
DWORD threadID
Definition: imm.c:198
PSERVERINFO g_psi
Definition: imm.c:58
DWORD dwCompReadClauseOffset
Definition: imm.h:168
LRESULT(WINAPI *pImeEscape)(HIMC
long x
Definition: polytest.cpp:48
POINT ptCurrentPos
Definition: imm.h:62
LPVOID APIENTRY Imm32HeapAlloc(DWORD dwFlags, DWORD dwBytes)
Definition: imm.c:1130
BOOL WINAPI ImeProcessKey(HIMC, UINT, LPARAM, CONST LPBYTE)
LPARAM lParam
Definition: imm.c:211
DWORD dwCompStrLen
Definition: imm.h:175
#define IMN_SETOPENSTATUS
Definition: imm.h:524
#define TRUE
Definition: types.h:120
GLsizei const GLchar ** path
Definition: glext.h:7234
#define DLL_THREAD_ATTACH
Definition: compat.h:132
DWORD WINAPI ImmGetImeMenuItemsW(HIMC hIMC, DWORD dwFlags, DWORD dwType, LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu, DWORD dwSize)
Definition: imm.c:3386
UINT WINAPI ImeToAsciiEx(UINT, UINT, CONST LPBYTE, LPDWORD, UINT, HIMC)
LRESULT WINAPI SendMessageA(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define SCS_CHANGEATTR
Definition: imm.h:451
int(CALLBACK * REGISTERWORDENUMPROCW)(_In_ LPCWSTR, _In_ DWORD, _In_ LPCWSTR, _In_ LPVOID)
Definition: imm.h:52
LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
Definition: imm.c:3455
#define LMEM_LOCKCOUNT
Definition: winbase.h:376
#define CP_ACP
Definition: compat.h:109
int WINAPI lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:170
HKL WINAPI ImmInstallIMEW(LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
Definition: imm.c:2555
GLuint GLuint GLsizei count
Definition: gl.h:1545
PIMEDPI WINAPI ImmLockImeDpi(HKL hKL)
Definition: imm.c:3066
DWORD dwCompReadClauseLen
Definition: imm.h:167
char CHAR
Definition: xmlstorage.h:175
#define IGP_PROPERTY
Definition: imm.h:441
struct list entry
Definition: imm.c:167
DWORD dwCompAttrOffset
Definition: imm.h:172
CANDIDATEFORM cfCandForm[4]
Definition: imm.h:39
static void ImmInternalPostIMEMessage(InputContextData *data, UINT msg, WPARAM wParam, LPARAM lParam)
Definition: imm.c:574
#define WARN(fmt,...)
Definition: debug.h:112
int notify
Definition: msacm.c:1365
#define MAKELPARAM(l, h)
Definition: winuser.h:3983
#define ERROR_INVALID_HANDLE
Definition: compat.h:98
DWORD dwCount
Definition: imm.h:203
LONG NTSTATUS
Definition: precomp.h:26
#define IME_ESC_GETHELPFILENAME
Definition: imm.h:568
HKL hkl
Definition: imm.c:168
#define MB_PRECOMPOSED
Definition: winnls.h:281
DWORD WINAPI ImeGetImeMenuItems(HIMC, DWORD, DWORD, LPIMEMENUITEMINFOW, LPIMEMENUITEMINFOW, DWORD)
DWORD dwStyle
Definition: imm.h:61
#define ReadBuffer(BaseIoAddress, Buffer, Count)
Definition: atapi.h:339
LRESULT WINAPI ImeEscape(HIMC, UINT, LPVOID)
#define str_len
Definition: treelist.c:89
#define CALLBACK
Definition: compat.h:35
DWORD WINAPI ImmGetCandidateListW(HIMC hIMC, DWORD dwIndex, LPCANDIDATELIST lpCandList, DWORD dwBufLen)
Definition: imm.c:1555
__WINE_SERVER_LIST_INLINE void list_add_head(struct list *list, struct list *elem)
Definition: list.h:96
HWND hWnd
Definition: settings.c:17
static BOOL CALLBACK _ImmAssociateContextExEnumProc(HWND hwnd, LPARAM lParam)
Definition: imm.c:755
#define WM_IME_SELECT
Definition: winuser.h:1815
#define GCS_RESULTREADCLAUSE
Definition: imm.h:368
DWORD dwResultReadStrOffset
Definition: imm.h:182
HIMCC WINAPI ImmDestroyIMCC(HIMCC block)
Definition: imm.c:3521
BOOL WINAPI ImmAssociateContextEx(HWND hWnd, HIMC hIMC, DWORD dwFlags)
Definition: imm.c:765
void BOOL
Definition: imm.c:180
static HANDLE process
Definition: process.c:76
NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
static HANDLE ULONG_PTR dwData
Definition: file.c:35
DWORD threadID
Definition: imm.c:216
LRESULT WINAPI ImmRequestMessageW(HIMC hIMC, WPARAM wParam, LPARAM lParam)
Definition: imm.c:2787
#define IMN_SETCOMPOSITIONFONT
Definition: imm.h:526
const BYTE STYLEBUFW IMEMENUITEMINFOW IMEMENUITEMINFOW DWORD
Definition: imm.c:191
#define HandleToULong(h)
Definition: basetsd.h:95
DWORD WINAPI ImmGetIMCCSize(HIMCC imcc)
Definition: imm.c:3569
static LONG cLocks
Definition: compobj.c:119
GLuint buffer
Definition: glext.h:5915
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
UINT WINAPI ImmEnumRegisterWordA(HKL hKL, REGISTERWORDENUMPROCA lpfnEnumProc, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszRegister, LPVOID lpData)
Definition: imm.c:975
static DWORD APIENTRY Imm32QueryInputContext(HIMC hIMC, DWORD dwUnknown2)
Definition: imm.c:62
#define IMN_SETCOMPOSITIONWINDOW
Definition: imm.h:527
uint32_t * LPUINT
Definition: typedefs.h:59
#define DLL_PROCESS_ATTACH
Definition: compat.h:131
#define IMM_INVALID_CANDFORM
Definition: imm.c:49
INPUTCONTEXT IMC
Definition: imm.c:197
UINT_PTR WPARAM
Definition: windef.h:207
LCID WINAPI GetUserDefaultLCID(void)
Definition: lang.c:768
SIZE_T NTAPI LocalSize(HLOCAL hMem)
Definition: heapmem.c:1777
WDF_EXTERN_C_START typedef _Must_inspect_result_ _In_opt_ PCUNICODE_STRING UnicodeString
Definition: wdfstring.h:64
DWORD fdwConversion
Definition: imm.h:32
static BOOL is_kbd_ime_unicode(const ImmHkl *hkl)
Definition: imm.c:250
BOOL WINAPI ShowWindow(_In_ HWND, _In_ int)
HIMCC hPrivate
Definition: imm.h:43
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
BOOL fOpen
Definition: imm.h:29
DWORD dwSize
Definition: imm.h:202
if(dx==0 &&dy==0)
Definition: linetemp.h:174
BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
Definition: imm.c:2484
char * LPSTR
Definition: xmlstorage.h:182
const char * filename
Definition: ioapi.h:135
UINT WINAPI ImmEnumRegisterWordW(HKL hKL, REGISTERWORDENUMPROCW lpfnEnumProc, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszRegister, LPVOID lpData)
Definition: imm.c:1010
_In_ HCRYPTHASH _In_ BOOL _In_ DWORD _Inout_ DWORD _In_ DWORD dwBufLen
Definition: wincrypt.h:4245
UINT message
Definition: imm.c:209
int(CALLBACK * REGISTERWORDENUMPROCA)(_In_ LPCSTR, _In_ DWORD, _In_ LPCSTR, _In_ LPVOID)
Definition: imm.h:45
#define lstrlenW
Definition: compat.h:609
const WCHAR CANDIDATELIST UINT
Definition: imm.c:188
BOOL WINAPI DestroyWindow(_In_ HWND)
#define DWORD
Definition: nt_native.h:44
#define IMM32_FLAG_UNKNOWN
Definition: imm.c:1127
#define WM_IME_COMPOSITIONFULL
Definition: winuser.h:1814
int32_t INT
Definition: typedefs.h:58
HWND UIWnd
Definition: imm.c:173
#define GCS_CURSORPOS
Definition: imm.h:365
WPARAM wParam
Definition: combotst.c:138
#define IMN_SETSENTENCEMODE
Definition: imm.h:523
#define DLL_THREAD_DETACH
Definition: compat.h:133
#define WINE_IMC_VALID_MAGIC
Definition: imm.c:206
HANDLE WINAPI RemovePropW(_In_ HWND, _In_ LPCWSTR)
CHAR lfFaceName[LF_FACESIZE]
Definition: wingdi.h:1893
LONG WINAPI RegCreateKeyExW(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey, _In_ DWORD Reserved, _In_opt_ LPWSTR lpClass, _In_ DWORD dwOptions, _In_ REGSAM samDesired, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, _Out_ PHKEY phkResult, _Out_opt_ LPDWORD lpdwDisposition)
Definition: reg.c:1091
DWORD dwCursorPos
Definition: imm.h:177
#define SCS_SETRECONVERTSTRING
Definition: imm.h:453
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
LONG WINAPI ImmGetCompositionStringA(HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
Definition: imm.c:1959
static BOOL disable_ime
Definition: imm.c:243
BOOL WINAPI __wine_register_window(HWND hwnd)
Definition: imm.c:2146
DWORD dwCompReadStrLen
Definition: imm.h:169
BOOL WINAPI ImmGetHotKey(IN DWORD dwHotKey, OUT LPUINT lpuModifiers, OUT LPUINT lpuVKey, OUT LPHKL lphKL)
Definition: imm.c:3750
BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
Definition: imm.c:3184
BOOL WINAPI ImmDestroyContext(HIMC hIMC)
Definition: imm.c:956
_In_ DWORD _In_ DWORD dwOffset
Definition: ntgdi.h:2032
static DWORD APIENTRY Imm32NotifyIMEStatus(HWND hwnd, HIMC hIMC, DWORD dwConversion)
Definition: imm.c:67
WCHAR szString[IMEMENUITEM_STRING_SIZE]
Definition: imm.h:129
uint32_t ULONG_PTR
Definition: typedefs.h:65
int WINAPI GetClassNameW(_In_ HWND hWnd, _Out_writes_to_(nMaxCount, return) LPWSTR lpClassName, _In_ int nMaxCount)
DWORD dwPageSize
Definition: imm.h:73
BOOL WINAPI ImmIsIME(HKL hKL)
Definition: imm.c:2613
static INT CopyCompOffsetIMEtoClient(InputContextData *data, DWORD offset, LPBYTE ssource, BOOL unicode)
Definition: imm.c:1847
DWORD_PTR NTAPI NtUserQueryWindow(HWND hWnd, DWORD Index)
Definition: window.c:3929
static INT CopyCompStringIMEtoClient(const InputContextData *data, const void *src, INT src_len, void *dst, INT dst_len, BOOL unicode)
Definition: imm.c:1691
DWORD NTAPI NtUserNotifyIMEStatus(HWND hwnd, HIMC hIMC, DWORD dwConversion)
Definition: ime.c:52
BOOL WINAPI ImmSetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
Definition: imm.c:2997
#define GCL_STYLE
Definition: winuser.h:665
BOOL WINAPI ImeUnregisterWord(LPCWSTR, DWORD, LPCWSTR)
BOOL WINAPI ImmGetConversionStatus(HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence)
Definition: imm.c:2112
BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
Definition: imm.c:548
BOOL WINAPI ImeRegisterWord(LPCWSTR, DWORD, LPCWSTR)
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
Definition: imm.c:2226
static HIMCC ImmCreateBlankCompStr(void)
Definition: imm.c:606
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
BOOL WINAPI CtfImmIsTextFrameServiceDisabled(VOID)
Definition: imm.c:3807
unsigned char * LPBYTE
Definition: typedefs.h:53
#define INIT_LOGFONT
Definition: imm.h:94
LRESULT WINAPI ImmEscapeW(HKL hKL, HIMC hIMC, UINT uEscape, LPVOID lpData)
Definition: imm.c:1089
#define IGP_SELECT
Definition: imm.h:446
DWORD unknown
Definition: imm32_undoc.h:16
LPVOID WINAPI ImmLockIMCC(HIMCC imcc)
Definition: imm.c:3531
#define FALSE
Definition: types.h:117
LPWSTR lpReading
Definition: dimm.idl:35
DWORD dwPrivateSize
Definition: imm.h:205
DWORD dwSRVIFlags
Definition: ntuser.h:1007
DWORD dwPageStart
Definition: imm.h:72
HINSTANCE hInst
Definition: ntuser.h:1221
static BOOL needs_ime_window(HWND hwnd)
Definition: imm.c:2132
#define IMN_SETCANDIDATEPOS
Definition: imm.h:525
HIMCC hCandInfo
Definition: imm.h:41
DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC)
Definition: imm.c:3489
static const WCHAR driverW[]
unsigned int BOOL
Definition: ntddk_ex.h:94
WCHAR strW[12]
Definition: clipboard.c:2029
DWORD dwSize
Definition: imm.h:68
__WINE_SERVER_LIST_INLINE unsigned int list_count(const struct list *list)
Definition: list.h:155
long LONG
Definition: pedump.c:60
LPSTR lpWord
Definition: dimm.idl:31
NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
FN_ImeDestroy ImeDestroy
Definition: ntuser.h:1229
HANDLE g_hImm32Heap
Definition: imm.c:1123
DWORD windowRefs
Definition: imm.c:220
LPSTR lpReading
Definition: dimm.idl:30
LONG WINAPI RegOpenKeyW(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:3296
STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:149
UINT WINAPI ImmGetDescriptionA(HKL hKL, LPSTR lpszDescription, UINT uBufLen)
Definition: imm.c:2248
#define debugstr_w
Definition: kernel32.h:32
DWORD WINAPI ImmGetConversionListA(HKL hKL, HIMC hIMC, LPCSTR pSrc, LPCANDIDATELIST lpDst, DWORD dwBufLen, UINT uFlag)
Definition: imm.c:2036
DWORD dwOffset[1]
Definition: dimm.idl:98
#define FIXME(fmt,...)
Definition: debug.h:111
static PVOID ptr
Definition: dispmode.c:27
DWORD dwOffset[1]
Definition: imm.h:74
DWORD APIENTRY ImmGetCandidateListCountAW(HIMC hIMC, LPDWORD lpdwListCount, BOOL bAnsi)
Definition: imm.c:1438
static InputContextData * get_imc_data(HIMC hIMC)
Definition: imm.c:618
BOOL WINAPI ImmSetActiveContextConsoleIME(HWND hwnd, BOOL fFlag)
Definition: imm.c:3782
DWORD WINAPI GetWindowThreadProcessId(HWND, PDWORD)
const WCHAR * str
HKL WINAPI ImmInstallIMEA(LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
Definition: imm.c:2532
#define MAKELONG(a, b)
Definition: typedefs.h:249
BOOL WINAPI ImmDisableIME(DWORD dwThreadId)
Definition: imm.c:967
#define LoadLibraryW(x)
Definition: compat.h:606
BOOL WINAPI User32InitializeImmEntryTable(DWORD)
Definition: imm.c:97
static const WCHAR version[]
Definition: asmname.c:66
HWND WINAPI GetDesktopWindow(void)
Definition: window.c:656
POINT ptStatusWndPos
Definition: imm.h:30
#define offsetof(TYPE, MEMBER)
unsigned char
Definition: typeof.h:29
BOOL WINAPI ImeSetActiveContext(HIMC, BOOL)
WCHAR szDescription[STYLE_DESCRIPTION_SIZE]
Definition: dimm.idl:110
#define GCS_RESULTSTR
Definition: imm.h:369
BOOL WINAPI IsDBCSLeadByte(BYTE TestByte)
Definition: nls.c:2232
DWORD cLockObj
Definition: ntuser.h:1226
static DWORD_PTR APIENTRY Imm32GetThreadState(DWORD Routine)
Definition: imm.c:1142
LONG_PTR LPARAM
Definition: windef.h:208
struct list entry
Definition: imm.c:215
#define IS_IME_HKL(hkl)
Definition: ntuser.h:1187
const WCHAR const WCHAR const WCHAR const WCHAR void const void const void DWORD
Definition: imm.c:187
PCLIENTIMC WINAPI ImmLockClientImc(HIMC hImc)
Definition: imm.c:1164
struct tagIMEMENUITEMINFOA IMEMENUITEMINFOA