ReactOS  0.4.14-dev-49-gfb4591c
imm32.c
Go to the documentation of this file.
1 /*
2  * Unit tests for imm32
3  *
4  * Copyright (c) 2008 Michael Jung
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #include <stdio.h>
22 
23 #include "wine/test.h"
24 #include "winuser.h"
25 #include "wingdi.h"
26 #include "imm.h"
27 #include "ddk/imm.h"
28 
29 static BOOL (WINAPI *pImmAssociateContextEx)(HWND,HIMC,DWORD);
30 static BOOL (WINAPI *pImmIsUIMessageA)(HWND,UINT,WPARAM,LPARAM);
31 static UINT (WINAPI *pSendInput) (UINT, INPUT*, size_t);
32 
33 /*
34  * msgspy - record and analyse message traces sent to a certain window
35  */
36 typedef struct _msgs {
39 } imm_msgs;
40 
41 static struct _msg_spy {
43  HHOOK get_msg_hook;
46  unsigned int i_msg;
47 } msg_spy;
48 
49 typedef struct
50 {
52  union
53  {
57  } u;
58 } TEST_INPUT;
59 
60 typedef struct _tagTRANSMSG {
61  UINT message;
62  WPARAM wParam;
63  LPARAM lParam;
65 
66 static UINT (WINAPI *pSendInput) (UINT, INPUT*, size_t);
67 
69 {
70  if (HC_ACTION == nCode) {
71  MSG *msg = (MSG*)lParam;
72 
73  if ((msg->hwnd == msg_spy.hwnd || msg_spy.hwnd == NULL) &&
74  (msg_spy.i_msg < ARRAY_SIZE(msg_spy.msgs)))
75  {
76  msg_spy.msgs[msg_spy.i_msg].msg.hwnd = msg->hwnd;
77  msg_spy.msgs[msg_spy.i_msg].msg.message = msg->message;
78  msg_spy.msgs[msg_spy.i_msg].msg.wParam = msg->wParam;
79  msg_spy.msgs[msg_spy.i_msg].msg.lParam = msg->lParam;
80  msg_spy.msgs[msg_spy.i_msg].post = TRUE;
81  msg_spy.i_msg++;
82  }
83  }
84 
85  return CallNextHookEx(msg_spy.get_msg_hook, nCode, wParam, lParam);
86 }
87 
89  LPARAM lParam)
90 {
91  if (HC_ACTION == nCode) {
92  CWPSTRUCT *cwp = (CWPSTRUCT*)lParam;
93 
94  if (((cwp->hwnd == msg_spy.hwnd || msg_spy.hwnd == NULL)) &&
95  (msg_spy.i_msg < ARRAY_SIZE(msg_spy.msgs)))
96  {
97  memcpy(&msg_spy.msgs[msg_spy.i_msg].msg, cwp, sizeof(msg_spy.msgs[0].msg));
98  msg_spy.msgs[msg_spy.i_msg].post = FALSE;
99  msg_spy.i_msg++;
100  }
101  }
102 
103  return CallNextHookEx(msg_spy.call_wnd_proc_hook, nCode, wParam, lParam);
104 }
105 
106 static void msg_spy_pump_msg_queue(void) {
107  MSG msg;
108 
109  while(PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) {
112  }
113 
114  return;
115 }
116 
117 static void msg_spy_flush_msgs(void) {
119  msg_spy.i_msg = 0;
120 }
121 
123  UINT i;
124 
126 
127  if (msg_spy.i_msg >= ARRAY_SIZE(msg_spy.msgs))
128  fprintf(stdout, "%s:%d: msg_spy: message buffer overflow!\n",
129  __FILE__, __LINE__);
130 
131  for (i = *start; i < msg_spy.i_msg; i++)
132  if (msg_spy.msgs[i].msg.message == message)
133  {
134  *start = i+1;
135  return &msg_spy.msgs[i];
136  }
137 
138  return NULL;
139 }
140 
142  UINT i = 0;
143 
144  return msg_spy_find_next_msg(message, &i);
145 }
146 
147 static void msg_spy_init(HWND hwnd) {
148  msg_spy.hwnd = hwnd;
149  msg_spy.get_msg_hook =
152  msg_spy.call_wnd_proc_hook =
155  msg_spy.i_msg = 0;
156 
158 }
159 
160 static void msg_spy_cleanup(void) {
161  if (msg_spy.get_msg_hook)
162  UnhookWindowsHookEx(msg_spy.get_msg_hook);
163  if (msg_spy.call_wnd_proc_hook)
164  UnhookWindowsHookEx(msg_spy.call_wnd_proc_hook);
165  memset(&msg_spy, 0, sizeof(msg_spy));
166 }
167 
168 /*
169  * imm32 test cases - Issue some IMM commands on a dummy window and analyse the
170  * messages being sent to this window in response.
171  */
172 static const char wndcls[] = "winetest_imm32_wndcls";
175 static HWND hwnd;
176 
177 static HWND get_ime_window(void);
178 
180 {
181  HWND default_ime_wnd;
182  switch (msg)
183  {
184  case WM_IME_SETCONTEXT:
185  return TRUE;
186  case WM_NCCREATE:
187  default_ime_wnd = get_ime_window();
188  switch(test_phase) {
189  case FIRST_WINDOW:
190  case IME_DISABLED:
191  ok(!default_ime_wnd, "expected no IME windows\n");
192  break;
193  case SECOND_WINDOW:
194  ok(default_ime_wnd != NULL, "expected IME window existence\n");
195  break;
196  default:
197  break; /* do nothing */
198  }
200  return FALSE;
201  return TRUE;
202  case WM_NCCALCSIZE:
203  default_ime_wnd = get_ime_window();
204  switch(test_phase) {
205  case FIRST_WINDOW:
206  case SECOND_WINDOW:
207  case CREATE_CANCEL:
208  ok(default_ime_wnd != NULL, "expected IME window existence\n");
209  break;
210  case IME_DISABLED:
211  ok(!default_ime_wnd, "expected no IME windows\n");
212  break;
213  default:
214  break; /* do nothing */
215  }
216  break;
217  case WM_CREATE:
218  default_ime_wnd = get_ime_window();
219  switch(test_phase) {
220  case FIRST_WINDOW:
221  case SECOND_WINDOW:
222  case CREATE_CANCEL:
223  ok(default_ime_wnd != NULL, "expected IME window existence\n");
224  break;
225  case IME_DISABLED:
226  ok(!default_ime_wnd, "expected no IME windows\n");
227  break;
228  default:
229  break; /* do nothing */
230  }
231  if (test_phase == CREATE_CANCEL)
232  return -1;
233  return TRUE;
234  }
235 
237 }
238 
239 static BOOL init(void) {
240  WNDCLASSEXA wc;
241  HIMC imc;
242  HMODULE hmod,huser;
243 
244  hmod = GetModuleHandleA("imm32.dll");
245  huser = GetModuleHandleA("user32");
246  pImmAssociateContextEx = (void*)GetProcAddress(hmod, "ImmAssociateContextEx");
247  pImmIsUIMessageA = (void*)GetProcAddress(hmod, "ImmIsUIMessageA");
248  pSendInput = (void*)GetProcAddress(huser, "SendInput");
249 
250  wc.cbSize = sizeof(WNDCLASSEXA);
251  wc.style = 0;
252  wc.lpfnWndProc = wndProc;
253  wc.cbClsExtra = 0;
254  wc.cbWndExtra = 0;
258  wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
259  wc.lpszMenuName = NULL;
260  wc.lpszClassName = wndcls;
262 
263  if (!RegisterClassExA(&wc))
264  return FALSE;
265 
266  hwnd = CreateWindowExA(WS_EX_CLIENTEDGE, wndcls, "Wine imm32.dll test",
268  240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL);
269  if (!hwnd)
270  return FALSE;
271 
272  imc = ImmGetContext(hwnd);
273  if (!imc)
274  {
275  win_skip("IME support not implemented\n");
276  return FALSE;
277  }
278  ImmReleaseContext(hwnd, imc);
279 
282 
284 
285  return TRUE;
286 }
287 
288 static void cleanup(void) {
289  msg_spy_cleanup();
290  if (hwnd)
293 }
294 
295 static void test_ImmNotifyIME(void) {
296  static const char string[] = "wine";
297  char resstr[16] = "";
298  HIMC imc;
299  BOOL ret;
300 
301  imc = ImmGetContext(hwnd);
303 
305  ok(broken(!ret) ||
306  ret, /* Vista+ */
307  "Canceling an empty composition string should succeed.\n");
308  ok(!msg_spy_find_msg(WM_IME_COMPOSITION), "Windows does not post "
309  "WM_IME_COMPOSITION in response to NI_COMPOSITIONSTR / CPS_CANCEL, if "
310  "the composition string being canceled is empty.\n");
311 
312  ImmSetCompositionStringA(imc, SCS_SETSTR, string, sizeof(string), NULL, 0);
314 
317 
318  /* behavior differs between win9x and NT */
319  ret = ImmGetCompositionStringA(imc, GCS_COMPSTR, resstr, sizeof(resstr));
320  ok(!ret, "After being cancelled the composition string is empty.\n");
321 
323 
325  ok(broken(!ret) ||
326  ret, /* Vista+ */
327  "Canceling an empty composition string should succeed.\n");
328  ok(!msg_spy_find_msg(WM_IME_COMPOSITION), "Windows does not post "
329  "WM_IME_COMPOSITION in response to NI_COMPOSITIONSTR / CPS_CANCEL, if "
330  "the composition string being canceled is empty.\n");
331 
333  ImmReleaseContext(hwnd, imc);
334 
335  imc = ImmCreateContext();
336  ImmDestroyContext(imc);
337 
338  SetLastError(0xdeadbeef);
339  ret = ImmNotifyIME((HIMC)0xdeadcafe, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
340  ok (ret == 0, "Bad IME should return 0\n");
341  ret = GetLastError();
342  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
343  SetLastError(0xdeadbeef);
344  ret = ImmNotifyIME(0x00000000, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
345  ok (ret == 0, "NULL IME should return 0\n");
346  ret = GetLastError();
347  ok(ret == ERROR_SUCCESS, "wrong last error %08x!\n", ret);
348  SetLastError(0xdeadbeef);
350  ok (ret == 0, "Destroyed IME should return 0\n");
351  ret = GetLastError();
352  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
353 
354 }
355 
356 static struct {
363 
365 {
366  switch (msg)
367  {
368  case WM_IME_COMPOSITION:
369  if ((lParam & GCS_RESULTSTR) && !ime_composition_test.catch_result_str) {
370  HWND hwndIme;
371  WCHAR wstring[20];
372  HIMC imc;
373  LONG size;
374  LRESULT ret;
375 
376  hwndIme = ImmGetDefaultIMEWnd(hWnd);
377  ok(hwndIme != NULL, "expected IME window existence\n");
378 
379  ok(!ime_composition_test.catch_ime_char, "WM_IME_CHAR is sent\n");
381  hWnd, msg, wParam, lParam);
382  ok(ime_composition_test.catch_ime_char, "WM_IME_CHAR isn't sent\n");
383 
384  ime_composition_test.catch_ime_char = FALSE;
385  SendMessageA(hwndIme, msg, wParam, lParam);
386  ok(!ime_composition_test.catch_ime_char, "WM_IME_CHAR is sent\n");
387 
388  imc = ImmGetContext(hWnd);
390  wstring, sizeof(wstring));
391  ok(size > 0, "ImmGetCompositionString(GCS_RESULTSTR) is %d\n", size);
392  ImmReleaseContext(hwnd, imc);
393 
394  ime_composition_test.catch_result_str = TRUE;
395  return ret;
396  }
397  break;
398  case WM_IME_CHAR:
399  if (!ime_composition_test.catch_result_str)
400  ime_composition_test.catch_ime_char = TRUE;
401  break;
402  case WM_TIMER:
403  if (wParam == ime_composition_test.timer_id) {
405  char title[64];
406  int left = 20 - (GetTickCount() - ime_composition_test.start) / 1000;
407  wsprintfA(title, "%sLeft %d sec. - IME composition test",
408  ime_composition_test.catch_result_str ? "[*] " : "", left);
410  if (left <= 0)
412  else
413  SetTimer(hWnd, wParam, 100, NULL);
414  return TRUE;
415  }
416  break;
417  }
418  return CallWindowProcA(ime_composition_test.old_wnd_proc,
419  hWnd, msg, wParam, lParam);
420 }
421 
423 {
424  HIMC imc;
425  static const WCHAR string[] = {'w','i','n','e',0x65e5,0x672c,0x8a9e};
426  char cstring[20];
427  WCHAR wstring[20];
428  LONG len;
429  LONG alen,wlen;
430  BOOL ret;
431  DWORD prop;
432 
433  imc = ImmGetContext(hwnd);
434  ret = ImmSetCompositionStringW(imc, SCS_SETSTR, string, sizeof(string), NULL,0);
435  if (!ret) {
436  win_skip("Composition isn't supported\n");
437  ImmReleaseContext(hwnd, imc);
438  return;
439  }
441 
442  alen = ImmGetCompositionStringA(imc, GCS_COMPSTR, cstring, 20);
443  wlen = ImmGetCompositionStringW(imc, GCS_COMPSTR, wstring, 20);
444  /* windows machines without any IME installed just return 0 above */
445  if( alen && wlen)
446  {
448  ok(len*sizeof(WCHAR)==wlen,"GCS_COMPATTR(W) not returning correct count\n");
450  ok(len==alen,"GCS_COMPATTR(A) not returning correct count\n");
451  }
452  else
453  win_skip("Composition string isn't available\n");
454 
455  ImmReleaseContext(hwnd, imc);
456 
457  /* Test composition results input by IMM API */
459  if (!(prop & SCS_CAP_COMPSTR)) {
460  /* Wine's IME doesn't support SCS_SETSTR in ImmSetCompositionString */
461  skip("This IME doesn't support SCS_SETSTR\n");
462  }
463  else {
464  ime_composition_test.old_wnd_proc =
467  imc = ImmGetContext(hwnd);
469 
471  string, sizeof(string), NULL,0);
472  ok(ret, "ImmSetCompositionStringW failed\n");
474  wstring, sizeof(wstring));
475  if (wlen > 0) {
477  ok(ret, "ImmNotifyIME(CPS_COMPLETE) failed\n");
479  ok(ime_composition_test.catch_result_str,
480  "WM_IME_COMPOSITION(GCS_RESULTSTR) isn't sent\n");
481  }
482  else
483  win_skip("Composition string isn't available\n");
484  ImmReleaseContext(hwnd, imc);
486  (LONG_PTR)ime_composition_test.old_wnd_proc);
488  }
489 
490  /* Test composition results input by hand */
492  if (winetest_interactive) {
493  HWND hwndMain, hwndChild;
494  MSG msg;
495  const DWORD MY_TIMER = 0xcaffe;
496 
498  "IME composition test",
500  CW_USEDEFAULT, CW_USEDEFAULT, 320, 160,
502  hwndChild = CreateWindowExA(0, "static",
503  "Input a DBCS character here using IME.",
505  0, 0, 320, 100, hwndMain, NULL,
507 
508  ime_composition_test.old_wnd_proc =
511 
512  SetFocus(hwndChild);
513 
514  ime_composition_test.timer_id = MY_TIMER;
516  SetTimer(hwndChild, ime_composition_test.timer_id, 100, NULL);
517  while (GetMessageA(&msg, NULL, 0, 0)) {
520  if (!IsWindow(hwndMain))
521  break;
522  }
523  if (!ime_composition_test.catch_result_str)
524  skip("WM_IME_COMPOSITION(GCS_RESULTSTR) isn't tested\n");
526  }
527 }
528 
530 {
531  HIMC imc;
532  BOOL ret;
533 
534  SetLastError(0xdeadbeef);
535  imc = ImmGetContext(hwnd);
536  ok(imc != 0, "ImmGetContext() failed. Last error: %u\n", GetLastError());
537  if (!imc)
538  return;
539 
541  ok(broken(!ret) ||
542  ret, /* Vista+ */
543  "ImmSetCompositionStringW() failed.\n");
544 
546  NULL, 0, NULL, 0);
547  ok(!ret, "ImmSetCompositionStringW() succeeded.\n");
548 
550  NULL, 0, NULL, 0);
551  ok(!ret, "ImmSetCompositionStringW() succeeded.\n");
552 
554  NULL, 0, NULL, 0);
555  ok(!ret, "ImmSetCompositionStringW() succeeded.\n");
556 
558  NULL, 0, NULL, 0);
559  ok(!ret, "ImmSetCompositionStringW() succeeded.\n");
560 
561  ImmReleaseContext(hwnd, imc);
562 }
563 
564 static void test_ImmIME(void)
565 {
566  HIMC imc;
567 
568  imc = ImmGetContext(hwnd);
569  if (imc)
570  {
571  BOOL rc;
573  ok (rc == 0, "ImmConfigureIMEA did not fail\n");
575  ok (rc == 0, "ImmConfigureIMEW did not fail\n");
576  }
577  ImmReleaseContext(hwnd,imc);
578 }
579 
580 static void test_ImmAssociateContextEx(void)
581 {
582  HIMC imc;
583  BOOL rc;
584 
585  if (!pImmAssociateContextEx) return;
586 
587  imc = ImmGetContext(hwnd);
588  if (imc)
589  {
590  HIMC retimc, newimc;
591 
592  newimc = ImmCreateContext();
593  ok(newimc != imc, "handles should not be the same\n");
594  rc = pImmAssociateContextEx(NULL, NULL, 0);
595  ok(!rc, "ImmAssociateContextEx succeeded\n");
596  rc = pImmAssociateContextEx(hwnd, NULL, 0);
597  ok(rc, "ImmAssociateContextEx failed\n");
598  rc = pImmAssociateContextEx(NULL, imc, 0);
599  ok(!rc, "ImmAssociateContextEx succeeded\n");
600 
601  rc = pImmAssociateContextEx(hwnd, imc, 0);
602  ok(rc, "ImmAssociateContextEx failed\n");
603  retimc = ImmGetContext(hwnd);
604  ok(retimc == imc, "handles should be the same\n");
605  ImmReleaseContext(hwnd,retimc);
606 
607  rc = pImmAssociateContextEx(hwnd, newimc, 0);
608  ok(rc, "ImmAssociateContextEx failed\n");
609  retimc = ImmGetContext(hwnd);
610  ok(retimc == newimc, "handles should be the same\n");
611  ImmReleaseContext(hwnd,retimc);
612 
613  rc = pImmAssociateContextEx(hwnd, NULL, IACE_DEFAULT);
614  ok(rc, "ImmAssociateContextEx failed\n");
615  }
616  ImmReleaseContext(hwnd,imc);
617 }
618 
619 typedef struct _igc_threadinfo {
625 
626 
628 {
629  HIMC h1,h2;
630  HWND hwnd2;
632  CANDIDATEFORM cdf;
633  POINT pt;
634  MSG msg;
635 
636  igc_threadinfo *info= (igc_threadinfo*)lpParam;
637  info->hwnd = CreateWindowExA(WS_EX_CLIENTEDGE, wndcls, "Wine imm32.dll test",
639  240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL);
640 
641  h1 = ImmGetContext(hwnd);
642  ok(info->himc == h1, "hwnd context changed in new thread\n");
643  h2 = ImmGetContext(info->hwnd);
644  ok(h2 != h1, "new hwnd in new thread should have different context\n");
645  info->himc = h2;
647 
648  hwnd2 = CreateWindowExA(WS_EX_CLIENTEDGE, wndcls, "Wine imm32.dll test",
650  240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL);
651  h1 = ImmGetContext(hwnd2);
652 
653  ok(h1 == h2, "Windows in same thread should have same default context\n");
654  ImmReleaseContext(hwnd2,h1);
655  ImmReleaseContext(info->hwnd,h2);
656  DestroyWindow(hwnd2);
657 
658  /* priming for later tests */
661  info->u_himc = ImmCreateContext();
662  ImmSetOpenStatus(info->u_himc, TRUE);
663  cdf.dwIndex = 0;
665  cdf.ptCurrentPos.x = 0;
666  cdf.ptCurrentPos.y = 0;
667  ImmSetCandidateWindow(info->u_himc, &cdf);
668 
669  SetEvent(info->event);
670 
671  while(GetMessageW(&msg, 0, 0, 0))
672  {
675  }
676  return 1;
677 }
678 
679 static void test_ImmThreads(void)
680 {
681  HIMC himc, otherHimc, h1;
682  igc_threadinfo threadinfo;
683  HANDLE hThread;
685  BOOL rc;
686  LOGFONTA lf;
688  CANDIDATEFORM cdf;
689  DWORD status, sentence;
690  POINT pt;
691 
692  himc = ImmGetContext(hwnd);
693  threadinfo.event = CreateEventA(NULL, TRUE, FALSE, NULL);
694  threadinfo.himc = himc;
695  hThread = CreateThread(NULL, 0, ImmGetContextThreadFunc, &threadinfo, 0, &dwThreadId );
696  WaitForSingleObject(threadinfo.event, INFINITE);
697 
698  otherHimc = ImmGetContext(threadinfo.hwnd);
699 
700  ok(himc != otherHimc, "Windows from other threads should have different himc\n");
701  ok(otherHimc == threadinfo.himc, "Context from other thread should not change in main thread\n");
702 
703  h1 = ImmAssociateContext(hwnd,otherHimc);
704  ok(h1 == NULL, "Should fail to be able to Associate a default context from a different thread\n");
705  h1 = ImmGetContext(hwnd);
706  ok(h1 == himc, "Context for window should remain unchanged\n");
708 
709  h1 = ImmAssociateContext(hwnd, threadinfo.u_himc);
710  ok (h1 == NULL, "Should fail to associate a context from a different thread\n");
711  h1 = ImmGetContext(hwnd);
712  ok(h1 == himc, "Context for window should remain unchanged\n");
714 
715  h1 = ImmAssociateContext(threadinfo.hwnd, threadinfo.u_himc);
716  ok (h1 == NULL, "Should fail to associate a context from a different thread into a window from that thread.\n");
717  h1 = ImmGetContext(threadinfo.hwnd);
718  ok(h1 == threadinfo.himc, "Context for window should remain unchanged\n");
719  ImmReleaseContext(threadinfo.hwnd,h1);
720 
721  /* OpenStatus */
722  rc = ImmSetOpenStatus(himc, TRUE);
723  ok(rc != 0, "ImmSetOpenStatus failed\n");
724  rc = ImmGetOpenStatus(himc);
725  ok(rc != 0, "ImmGetOpenStatus failed\n");
726  rc = ImmSetOpenStatus(himc, FALSE);
727  ok(rc != 0, "ImmSetOpenStatus failed\n");
728  rc = ImmGetOpenStatus(himc);
729  ok(rc == 0, "ImmGetOpenStatus failed\n");
730 
731  rc = ImmSetOpenStatus(otherHimc, TRUE);
732  ok(rc == 0, "ImmSetOpenStatus should fail\n");
733  rc = ImmSetOpenStatus(threadinfo.u_himc, TRUE);
734  ok(rc == 0, "ImmSetOpenStatus should fail\n");
735  rc = ImmGetOpenStatus(otherHimc);
736  ok(rc == 0, "ImmGetOpenStatus failed\n");
737  rc = ImmGetOpenStatus(threadinfo.u_himc);
738  ok (rc == 1 || broken(rc == 0), "ImmGetOpenStatus should return 1\n");
739  rc = ImmSetOpenStatus(otherHimc, FALSE);
740  ok(rc == 0, "ImmSetOpenStatus should fail\n");
741  rc = ImmGetOpenStatus(otherHimc);
742  ok(rc == 0, "ImmGetOpenStatus failed\n");
743 
744  /* CompositionFont */
745  rc = ImmGetCompositionFontA(himc, &lf);
746  ok(rc != 0, "ImmGetCompositionFont failed\n");
747  rc = ImmSetCompositionFontA(himc, &lf);
748  ok(rc != 0, "ImmSetCompositionFont failed\n");
749 
750  rc = ImmGetCompositionFontA(otherHimc, &lf);
751  ok(rc != 0 || broken(rc == 0), "ImmGetCompositionFont failed\n");
752  rc = ImmGetCompositionFontA(threadinfo.u_himc, &lf);
753  ok(rc != 0 || broken(rc == 0), "ImmGetCompositionFont user himc failed\n");
754  rc = ImmSetCompositionFontA(otherHimc, &lf);
755  ok(rc == 0, "ImmSetCompositionFont should fail\n");
756  rc = ImmSetCompositionFontA(threadinfo.u_himc, &lf);
757  ok(rc == 0, "ImmSetCompositionFont should fail\n");
758 
759  /* CompositionWindow */
760  rc = ImmSetCompositionWindow(himc, &cf);
761  ok(rc != 0, "ImmSetCompositionWindow failed\n");
762  rc = ImmGetCompositionWindow(himc, &cf);
763  ok(rc != 0, "ImmGetCompositionWindow failed\n");
764 
765  rc = ImmSetCompositionWindow(otherHimc, &cf);
766  ok(rc == 0, "ImmSetCompositionWindow should fail\n");
767  rc = ImmSetCompositionWindow(threadinfo.u_himc, &cf);
768  ok(rc == 0, "ImmSetCompositionWindow should fail\n");
769  rc = ImmGetCompositionWindow(otherHimc, &cf);
770  ok(rc != 0 || broken(rc == 0), "ImmGetCompositionWindow failed\n");
771  rc = ImmGetCompositionWindow(threadinfo.u_himc, &cf);
772  ok(rc != 0 || broken(rc == 0), "ImmGetCompositionWindow failed\n");
773 
774  /* ConversionStatus */
775  rc = ImmGetConversionStatus(himc, &status, &sentence);
776  ok(rc != 0, "ImmGetConversionStatus failed\n");
777  rc = ImmSetConversionStatus(himc, status, sentence);
778  ok(rc != 0, "ImmSetConversionStatus failed\n");
779 
780  rc = ImmGetConversionStatus(otherHimc, &status, &sentence);
781  ok(rc != 0 || broken(rc == 0), "ImmGetConversionStatus failed\n");
782  rc = ImmGetConversionStatus(threadinfo.u_himc, &status, &sentence);
783  ok(rc != 0 || broken(rc == 0), "ImmGetConversionStatus failed\n");
784  rc = ImmSetConversionStatus(otherHimc, status, sentence);
785  ok(rc == 0, "ImmSetConversionStatus should fail\n");
786  rc = ImmSetConversionStatus(threadinfo.u_himc, status, sentence);
787  ok(rc == 0, "ImmSetConversionStatus should fail\n");
788 
789  /* StatusWindowPos */
790  rc = ImmSetStatusWindowPos(himc, &pt);
791  ok(rc != 0, "ImmSetStatusWindowPos failed\n");
792  rc = ImmGetStatusWindowPos(himc, &pt);
793  ok(rc != 0, "ImmGetStatusWindowPos failed\n");
794 
795  rc = ImmSetStatusWindowPos(otherHimc, &pt);
796  ok(rc == 0, "ImmSetStatusWindowPos should fail\n");
797  rc = ImmSetStatusWindowPos(threadinfo.u_himc, &pt);
798  ok(rc == 0, "ImmSetStatusWindowPos should fail\n");
799  rc = ImmGetStatusWindowPos(otherHimc, &pt);
800  ok(rc != 0 || broken(rc == 0), "ImmGetStatusWindowPos failed\n");
801  rc = ImmGetStatusWindowPos(threadinfo.u_himc, &pt);
802  ok(rc != 0 || broken(rc == 0), "ImmGetStatusWindowPos failed\n");
803 
804  h1 = ImmAssociateContext(threadinfo.hwnd, NULL);
805  ok (h1 == otherHimc, "ImmAssociateContext cross thread with NULL should work\n");
806  h1 = ImmGetContext(threadinfo.hwnd);
807  ok (h1 == NULL, "CrossThread window context should be NULL\n");
808  h1 = ImmAssociateContext(threadinfo.hwnd, h1);
809  ok (h1 == NULL, "Resetting cross thread context should fail\n");
810  h1 = ImmGetContext(threadinfo.hwnd);
811  ok (h1 == NULL, "CrossThread window context should still be NULL\n");
812 
813  rc = ImmDestroyContext(threadinfo.u_himc);
814  ok (rc == 0, "ImmDestroyContext Cross Thread should fail\n");
815 
816  /* Candidate Window */
817  rc = ImmGetCandidateWindow(himc, 0, &cdf);
818  ok (rc == 0, "ImmGetCandidateWindow should fail\n");
819  cdf.dwIndex = 0;
821  cdf.ptCurrentPos.x = 0;
822  cdf.ptCurrentPos.y = 0;
823  rc = ImmSetCandidateWindow(himc, &cdf);
824  ok (rc == 1, "ImmSetCandidateWindow should succeed\n");
825  rc = ImmGetCandidateWindow(himc, 0, &cdf);
826  ok (rc == 1, "ImmGetCandidateWindow should succeed\n");
827 
828  rc = ImmGetCandidateWindow(otherHimc, 0, &cdf);
829  ok (rc == 0, "ImmGetCandidateWindow should fail\n");
830  rc = ImmSetCandidateWindow(otherHimc, &cdf);
831  ok (rc == 0, "ImmSetCandidateWindow should fail\n");
832  rc = ImmGetCandidateWindow(threadinfo.u_himc, 0, &cdf);
833  ok (rc == 1 || broken( rc == 0), "ImmGetCandidateWindow should succeed\n");
834  rc = ImmSetCandidateWindow(threadinfo.u_himc, &cdf);
835  ok (rc == 0, "ImmSetCandidateWindow should fail\n");
836 
837  ImmReleaseContext(threadinfo.hwnd,otherHimc);
838  ImmReleaseContext(hwnd,himc);
839 
840  SendMessageA(threadinfo.hwnd, WM_CLOSE, 0, 0);
842  ok(rc == 1, "PostThreadMessage should succeed\n");
845 
847  ok(himc == NULL, "Should not be able to get himc from other process window\n");
848 }
849 
850 static void test_ImmIsUIMessage(void)
851 {
852  struct test
853  {
854  UINT msg;
855  BOOL ret;
856  };
857 
858  static const struct test tests[] =
859  {
860  { WM_MOUSEMOVE, FALSE },
861  { WM_IME_STARTCOMPOSITION, TRUE },
862  { WM_IME_ENDCOMPOSITION, TRUE },
863  { WM_IME_COMPOSITION, TRUE },
864  { WM_IME_SETCONTEXT, TRUE },
865  { WM_IME_NOTIFY, TRUE },
866  { WM_IME_CONTROL, FALSE },
868  { WM_IME_SELECT, TRUE },
869  { WM_IME_CHAR, FALSE },
870  { 0x287 /* FIXME */, TRUE },
871  { WM_IME_REQUEST, FALSE },
872  { WM_IME_KEYDOWN, FALSE },
873  { WM_IME_KEYUP, FALSE },
874  { 0, FALSE } /* mark the end */
875  };
876 
877  UINT WM_MSIME_SERVICE = RegisterWindowMessageA("MSIMEService");
878  UINT WM_MSIME_RECONVERTOPTIONS = RegisterWindowMessageA("MSIMEReconvertOptions");
879  UINT WM_MSIME_MOUSE = RegisterWindowMessageA("MSIMEMouseOperation");
880  UINT WM_MSIME_RECONVERTREQUEST = RegisterWindowMessageA("MSIMEReconvertRequest");
881  UINT WM_MSIME_RECONVERT = RegisterWindowMessageA("MSIMEReconvert");
882  UINT WM_MSIME_QUERYPOSITION = RegisterWindowMessageA("MSIMEQueryPosition");
883  UINT WM_MSIME_DOCUMENTFEED = RegisterWindowMessageA("MSIMEDocumentFeed");
884 
885  const struct test *test;
886  BOOL ret;
887 
888  if (!pImmIsUIMessageA) return;
889 
890  for (test = tests; test->msg; test++)
891  {
893  ret = pImmIsUIMessageA(NULL, test->msg, 0, 0);
894  ok(ret == test->ret, "ImmIsUIMessageA returned %x for %x\n", ret, test->msg);
895  ok(!msg_spy_find_msg(test->msg), "Windows does not send 0x%x for NULL hwnd\n", test->msg);
896 
897  ret = pImmIsUIMessageA(hwnd, test->msg, 0, 0);
898  ok(ret == test->ret, "ImmIsUIMessageA returned %x for %x\n", ret, test->msg);
899  if (ret)
900  ok(msg_spy_find_msg(test->msg) != NULL, "Windows does send 0x%x\n", test->msg);
901  else
902  ok(!msg_spy_find_msg(test->msg), "Windows does not send 0x%x\n", test->msg);
903  }
904 
905  ret = pImmIsUIMessageA(NULL, WM_MSIME_SERVICE, 0, 0);
906  ok(!ret, "ImmIsUIMessageA returned TRUE for WM_MSIME_SERVICE\n");
907  ret = pImmIsUIMessageA(NULL, WM_MSIME_RECONVERTOPTIONS, 0, 0);
908  ok(!ret, "ImmIsUIMessageA returned TRUE for WM_MSIME_RECONVERTOPTIONS\n");
909  ret = pImmIsUIMessageA(NULL, WM_MSIME_MOUSE, 0, 0);
910  ok(!ret, "ImmIsUIMessageA returned TRUE for WM_MSIME_MOUSE\n");
911  ret = pImmIsUIMessageA(NULL, WM_MSIME_RECONVERTREQUEST, 0, 0);
912  ok(!ret, "ImmIsUIMessageA returned TRUE for WM_MSIME_RECONVERTREQUEST\n");
913  ret = pImmIsUIMessageA(NULL, WM_MSIME_RECONVERT, 0, 0);
914  ok(!ret, "ImmIsUIMessageA returned TRUE for WM_MSIME_RECONVERT\n");
915  ret = pImmIsUIMessageA(NULL, WM_MSIME_QUERYPOSITION, 0, 0);
916  ok(!ret, "ImmIsUIMessageA returned TRUE for WM_MSIME_QUERYPOSITION\n");
917  ret = pImmIsUIMessageA(NULL, WM_MSIME_DOCUMENTFEED, 0, 0);
918  ok(!ret, "ImmIsUIMessageA returned TRUE for WM_MSIME_DOCUMENTFEED\n");
919 }
920 
921 static void test_ImmGetContext(void)
922 {
923  HIMC himc;
924  DWORD err;
925 
926  SetLastError(0xdeadbeef);
927  himc = ImmGetContext((HWND)0xffffffff);
928  err = GetLastError();
929  ok(himc == NULL, "ImmGetContext succeeded\n");
930  ok(err == ERROR_INVALID_WINDOW_HANDLE, "got %u\n", err);
931 
932  himc = ImmGetContext(hwnd);
933  ok(himc != NULL, "ImmGetContext failed\n");
934  ok(ImmReleaseContext(hwnd, himc), "ImmReleaseContext failed\n");
935 }
936 
937 static void test_ImmGetDescription(void)
938 {
939  HKL hkl;
940  WCHAR descW[100];
941  CHAR descA[100];
942  UINT ret, lret;
943 
944  /* FIXME: invalid keyboard layouts should not pass */
946  ok(!ret, "ImmGetDescriptionW failed, expected 0 received %d.\n", ret);
948  ok(!ret, "ImmGetDescriptionA failed, expected 0 received %d.\n", ret);
949 
950  /* load a language with valid IMM descriptions */
951  hkl = GetKeyboardLayout(0);
952  ok(hkl != 0, "GetKeyboardLayout failed, expected != 0.\n");
953 
955  if(!ret)
956  {
957  win_skip("ImmGetDescriptionW is not working for current loaded keyboard.\n");
958  return;
959  }
960 
961  SetLastError(0xdeadcafe);
962  ret = ImmGetDescriptionW(0, NULL, 100);
963  ok (ret == 0, "ImmGetDescriptionW with 0 hkl should return 0\n");
964  ret = GetLastError();
965  ok (ret == 0xdeadcafe, "Last Error should remain unchanged\n");
966 
967  ret = ImmGetDescriptionW(hkl, descW, 0);
968  ok(ret, "ImmGetDescriptionW failed, expected != 0 received 0.\n");
969 
970  lret = ImmGetDescriptionW(hkl, descW, ret + 1);
971  ok(lret, "ImmGetDescriptionW failed, expected != 0 received 0.\n");
972  ok(lret == ret, "ImmGetDescriptionW failed to return the correct amount of data. Expected %d, got %d.\n", ret, lret);
973 
974  lret = ImmGetDescriptionA(hkl, descA, ret + 1);
975  ok(lret, "ImmGetDescriptionA failed, expected != 0 received 0.\n");
976  ok(lret == ret, "ImmGetDescriptionA failed to return the correct amount of data. Expected %d, got %d.\n", ret, lret);
977 
978  ret /= 2; /* try to copy partially */
979  lret = ImmGetDescriptionW(hkl, descW, ret + 1);
980  ok(lret, "ImmGetDescriptionW failed, expected != 0 received 0.\n");
981  ok(lret == ret, "ImmGetDescriptionW failed to return the correct amount of data. Expected %d, got %d.\n", ret, lret);
982 
983  lret = ImmGetDescriptionA(hkl, descA, ret + 1);
984  ok(!lret, "ImmGetDescriptionA should fail\n");
985 
986  ret = ImmGetDescriptionW(hkl, descW, 1);
987  ok(!ret, "ImmGetDescriptionW failed, expected 0 received %d.\n", ret);
988 
990 }
991 
992 static LRESULT (WINAPI *old_imm_wnd_proc)(HWND, UINT, WPARAM, LPARAM);
994 {
995  ok(msg != WM_DESTROY, "got WM_DESTROY message\n");
996  return old_imm_wnd_proc(hwnd, msg, wparam, lparam);
997 }
998 
1001 {
1002  CreateWindowA("static", "static", WS_POPUP, 0, 0, 1, 1, NULL, NULL, NULL, NULL);
1003 
1005  ok(thread_ime_wnd != 0, "ImmGetDefaultIMEWnd returned NULL\n");
1006  old_imm_wnd_proc = (void*)SetWindowLongPtrW(thread_ime_wnd, GWLP_WNDPROC, (LONG_PTR)imm_wnd_proc);
1007  return 0;
1008 }
1009 
1010 static void test_ImmDefaultHwnd(void)
1011 {
1012  HIMC imc1, imc2, imc3;
1013  HWND def1, def3;
1014  HANDLE thread;
1015  HWND hwnd;
1016  char title[16];
1017  LONG style;
1018 
1019  hwnd = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "Wine imm32.dll test",
1021  240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL);
1022 
1024 
1025  imc1 = ImmGetContext(hwnd);
1026  if (!imc1)
1027  {
1028  win_skip("IME support not implemented\n");
1029  return;
1030  }
1031 
1032  def1 = ImmGetDefaultIMEWnd(hwnd);
1033 
1034  GetWindowTextA(def1, title, sizeof(title));
1035  ok(!strcmp(title, "Default IME"), "got %s\n", title);
1036  style = GetWindowLongA(def1, GWL_STYLE);
1037  ok(style == (WS_DISABLED | WS_POPUP | WS_CLIPSIBLINGS), "got %08x\n", style);
1038  style = GetWindowLongA(def1, GWL_EXSTYLE);
1039  ok(style == 0, "got %08x\n", style);
1040 
1041  imc2 = ImmCreateContext();
1042  ImmSetOpenStatus(imc2, TRUE);
1043 
1044  imc3 = ImmGetContext(hwnd);
1045  def3 = ImmGetDefaultIMEWnd(hwnd);
1046 
1047  ok(def3 == def1, "Default IME window should not change\n");
1048  ok(imc1 == imc3, "IME context should not change\n");
1049  ImmSetOpenStatus(imc2, FALSE);
1050 
1053  ok(thread_ime_wnd != def1, "thread_ime_wnd == def1\n");
1054  ok(!IsWindow(thread_ime_wnd), "thread_ime_wnd was not destroyed\n");
1056 
1057  ImmReleaseContext(hwnd, imc1);
1058  ImmReleaseContext(hwnd, imc3);
1059  ImmDestroyContext(imc2);
1061 }
1062 
1064 {
1065  static const WCHAR imeW[] = {'I','M','E',0};
1066  WCHAR class_nameW[16];
1067  HWND *ime_window = (HWND *)param;
1068  if (GetClassNameW(hWnd, class_nameW, ARRAY_SIZE(class_nameW)) && !lstrcmpW(class_nameW, imeW))
1069  {
1070  *ime_window = hWnd;
1071  return FALSE;
1072  }
1073  return TRUE;
1074 }
1075 
1076 static HWND get_ime_window(void)
1077 {
1078  HWND ime_window = NULL;
1080  return ime_window;
1081 }
1082 
1086 };
1087 
1089 {
1090  struct testcase_ime_window *testcase = (struct testcase_ime_window *)arg;
1091  DWORD visible = testcase->visible ? WS_VISIBLE : 0;
1092  HWND hwnd1, hwnd2, default_ime_wnd, ime_wnd;
1093 
1094  ok(!get_ime_window(), "Expected no IME windows\n");
1095  if (testcase->top_level_window) {
1097  hwnd1 = CreateWindowExA(WS_EX_CLIENTEDGE, wndcls, "Wine imm32.dll test",
1100  240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL);
1101  }
1102  else {
1103  hwnd1 = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "Wine imm32.dll test",
1104  WS_CHILD | visible,
1106  240, 24, hwnd, NULL, GetModuleHandleW(NULL), NULL);
1107  }
1108  ime_wnd = get_ime_window();
1109  ok(ime_wnd != NULL, "Expected IME window existence\n");
1110  default_ime_wnd = ImmGetDefaultIMEWnd(hwnd1);
1111  ok(ime_wnd == default_ime_wnd, "Expected %p, got %p\n", ime_wnd, default_ime_wnd);
1112 
1114  hwnd2 = CreateWindowExA(WS_EX_CLIENTEDGE, wndcls, "Wine imm32.dll test",
1117  240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL);
1118  DestroyWindow(hwnd2);
1119  ok(IsWindow(ime_wnd) ||
1120  broken(!testcase->visible /* Vista */) ||
1121  broken(!testcase->top_level_window /* Vista */) ,
1122  "Expected IME window existence\n");
1123  DestroyWindow(hwnd1);
1124  ok(!IsWindow(ime_wnd), "Expected no IME windows\n");
1125  return 1;
1126 }
1127 
1129 {
1130  struct testcase_ime_window *testcase = (struct testcase_ime_window *)arg;
1131  DWORD visible = testcase->visible ? WS_VISIBLE : 0;
1132  HWND hwnd1, hwnd2, default_ime_wnd, ime_wnd;
1133 
1134  ok(!get_ime_window(), "Expected no IME windows\n");
1136  hwnd1 = CreateWindowExA(WS_EX_CLIENTEDGE, wndcls, "Wine imm32.dll test",
1139  240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL);
1140  ok(hwnd1 == NULL, "creation succeeded, got %p\n", hwnd1);
1141  ok(!get_ime_window(), "Expected no IME windows\n");
1142 
1144  hwnd1 = CreateWindowExA(WS_EX_CLIENTEDGE, wndcls, "Wine imm32.dll test",
1147  240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL);
1148  ok(hwnd1 == NULL, "creation succeeded, got %p\n", hwnd1);
1149  ok(!get_ime_window(), "Expected no IME windows\n");
1150 
1152  hwnd2 = CreateWindowExA(WS_EX_CLIENTEDGE, wndcls, "Wine imm32.dll test",
1155  240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL);
1156  ime_wnd = get_ime_window();
1157  ok(ime_wnd != NULL, "Expected IME window existence\n");
1158  default_ime_wnd = ImmGetDefaultIMEWnd(hwnd2);
1159  ok(ime_wnd == default_ime_wnd, "Expected %p, got %p\n", ime_wnd, default_ime_wnd);
1160 
1161  DestroyWindow(hwnd2);
1162  ok(!IsWindow(ime_wnd), "Expected no IME windows\n");
1163  return 1;
1164 }
1165 
1167 {
1168  HWND hWnd, default_ime_wnd;
1169 
1170  ok(!get_ime_window(), "Expected no IME windows\n");
1173  hWnd = CreateWindowExA(WS_EX_CLIENTEDGE, wndcls, "Wine imm32.dll test",
1176  240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL);
1177  default_ime_wnd = ImmGetDefaultIMEWnd(hWnd);
1178  ok(!default_ime_wnd, "Expected no IME windows\n");
1180  return 1;
1181 }
1182 
1184 {
1185  HWND hwnd1, hwnd2, default_ime_wnd;
1186 
1188  hwnd1 = CreateWindowA(wndcls, "Wine imm32.dll test",
1191  240, 120, HWND_MESSAGE, NULL, GetModuleHandleW(NULL), NULL);
1192  default_ime_wnd = ImmGetDefaultIMEWnd(hwnd1);
1193  ok(!IsWindow(default_ime_wnd), "Expected no IME windows, got %p\n", default_ime_wnd);
1194 
1195  hwnd2 = CreateWindowA(wndcls, "Wine imm32.dll test",
1198  240, 120, hwnd1, NULL, GetModuleHandleW(NULL), NULL);
1199  default_ime_wnd = ImmGetDefaultIMEWnd(hwnd2);
1200  ok(IsWindow(default_ime_wnd), "Expected IME window existence\n");
1201 
1202  DestroyWindow(hwnd2);
1203  DestroyWindow(hwnd1);
1204 
1205  hwnd1 = CreateWindowA(wndcls, "Wine imm32.dll test",
1208  240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL);
1209  default_ime_wnd = ImmGetDefaultIMEWnd(hwnd1);
1210  ok(IsWindow(default_ime_wnd), "Expected IME window existence\n");
1211  SetParent(hwnd1, HWND_MESSAGE);
1212  default_ime_wnd = ImmGetDefaultIMEWnd(hwnd1);
1213  ok(IsWindow(default_ime_wnd), "Expected IME window existence\n");
1214  DestroyWindow(hwnd1);
1215  return 1;
1216 }
1217 
1219 {
1220  HANDLE thread;
1221  size_t i;
1222  struct testcase_ime_window testcases[] = {
1223  /* visible, top-level window */
1224  { TRUE, TRUE },
1225  { FALSE, TRUE },
1226  { TRUE, FALSE },
1227  { FALSE, FALSE }
1228  };
1229 
1230  for (i = 0; i < ARRAY_SIZE(testcases); i++)
1231  {
1232  thread = CreateThread(NULL, 0, test_default_ime_window_cb, &testcases[i], 0, NULL);
1233  ok(thread != NULL, "CreateThread failed with error %u\n", GetLastError());
1235  {
1236  MSG msg;
1237  while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
1238  {
1241  }
1242  }
1244 
1245  if (testcases[i].top_level_window)
1246  {
1248  ok(thread != NULL, "CreateThread failed with error %u\n", GetLastError());
1251  }
1252  }
1253 
1257 
1261 
1263 }
1264 
1265 static void test_ImmGetIMCLockCount(void)
1266 {
1267  HIMC imc;
1268  DWORD count, ret, i;
1269  INPUTCONTEXT *ic;
1270 
1271  imc = ImmCreateContext();
1272  ImmDestroyContext(imc);
1273  SetLastError(0xdeadbeef);
1274  count = ImmGetIMCLockCount((HIMC)0xdeadcafe);
1275  ok(count == 0, "Invalid IMC should return 0\n");
1276  ret = GetLastError();
1277  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1278  SetLastError(0xdeadbeef);
1279  count = ImmGetIMCLockCount(0x00000000);
1280  ok(count == 0, "NULL IMC should return 0\n");
1281  ret = GetLastError();
1282  ok(ret == 0xdeadbeef, "Last Error should remain unchanged: %08x\n",ret);
1283  count = ImmGetIMCLockCount(imc);
1284  ok(count == 0, "Destroyed IMC should return 0\n");
1285  ret = GetLastError();
1286  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1287 
1288  imc = ImmCreateContext();
1289  count = ImmGetIMCLockCount(imc);
1290  ok(count == 0, "expect 0, returned %d\n", count);
1291  ic = ImmLockIMC(imc);
1292  ok(ic != NULL, "ImmLockIMC failed!\n");
1293  count = ImmGetIMCLockCount(imc);
1294  ok(count == 1, "expect 1, returned %d\n", count);
1295  ret = ImmUnlockIMC(imc);
1296  ok(ret == TRUE, "expect TRUE, ret %d\n", ret);
1297  count = ImmGetIMCLockCount(imc);
1298  ok(count == 0, "expect 0, returned %d\n", count);
1299  ret = ImmUnlockIMC(imc);
1300  ok(ret == TRUE, "expect TRUE, ret %d\n", ret);
1301  count = ImmGetIMCLockCount(imc);
1302  ok(count == 0, "expect 0, returned %d\n", count);
1303 
1304  for (i = 0; i < GMEM_LOCKCOUNT * 2; i++)
1305  {
1306  ic = ImmLockIMC(imc);
1307  ok(ic != NULL, "ImmLockIMC failed!\n");
1308  }
1309  count = ImmGetIMCLockCount(imc);
1310  todo_wine ok(count == GMEM_LOCKCOUNT, "expect GMEM_LOCKCOUNT, returned %d\n", count);
1311 
1312  for (i = 0; i < GMEM_LOCKCOUNT - 1; i++)
1313  ImmUnlockIMC(imc);
1314  count = ImmGetIMCLockCount(imc);
1315  todo_wine ok(count == 1, "expect 1, returned %d\n", count);
1316  ImmUnlockIMC(imc);
1317  count = ImmGetIMCLockCount(imc);
1318  todo_wine ok(count == 0, "expect 0, returned %d\n", count);
1319 
1320  ImmDestroyContext(imc);
1321 }
1322 
1323 static void test_ImmGetIMCCLockCount(void)
1324 {
1325  HIMCC imcc;
1326  DWORD count, g_count, i;
1327  BOOL ret;
1328  VOID *p;
1329 
1330  imcc = ImmCreateIMCC(sizeof(CANDIDATEINFO));
1331  count = ImmGetIMCCLockCount(imcc);
1332  ok(count == 0, "expect 0, returned %d\n", count);
1333  ImmLockIMCC(imcc);
1334  count = ImmGetIMCCLockCount(imcc);
1335  ok(count == 1, "expect 1, returned %d\n", count);
1336  ret = ImmUnlockIMCC(imcc);
1337  ok(ret == FALSE, "expect FALSE, ret %d\n", ret);
1338  count = ImmGetIMCCLockCount(imcc);
1339  ok(count == 0, "expect 0, returned %d\n", count);
1340  ret = ImmUnlockIMCC(imcc);
1341  ok(ret == FALSE, "expect FALSE, ret %d\n", ret);
1342  count = ImmGetIMCCLockCount(imcc);
1343  ok(count == 0, "expect 0, returned %d\n", count);
1344 
1345  p = ImmLockIMCC(imcc);
1346  ok(GlobalHandle(p) == imcc, "expect %p, returned %p\n", imcc, GlobalHandle(p));
1347 
1348  for (i = 0; i < GMEM_LOCKCOUNT * 2; i++)
1349  {
1350  ImmLockIMCC(imcc);
1351  count = ImmGetIMCCLockCount(imcc);
1352  g_count = GlobalFlags(imcc) & GMEM_LOCKCOUNT;
1353  ok(count == g_count, "count %d, g_count %d\n", count, g_count);
1354  }
1355  count = ImmGetIMCCLockCount(imcc);
1356  ok(count == GMEM_LOCKCOUNT, "expect GMEM_LOCKCOUNT, returned %d\n", count);
1357 
1358  for (i = 0; i < GMEM_LOCKCOUNT - 1; i++)
1359  GlobalUnlock(imcc);
1360  count = ImmGetIMCCLockCount(imcc);
1361  ok(count == 1, "expect 1, returned %d\n", count);
1362  GlobalUnlock(imcc);
1363  count = ImmGetIMCCLockCount(imcc);
1364  ok(count == 0, "expect 0, returned %d\n", count);
1365 
1366  ImmDestroyIMCC(imcc);
1367 }
1368 
1369 static void test_ImmDestroyContext(void)
1370 {
1371  HIMC imc;
1372  DWORD ret, count;
1373  INPUTCONTEXT *ic;
1374 
1375  imc = ImmCreateContext();
1376  count = ImmGetIMCLockCount(imc);
1377  ok(count == 0, "expect 0, returned %d\n", count);
1378  ic = ImmLockIMC(imc);
1379  ok(ic != NULL, "ImmLockIMC failed!\n");
1380  count = ImmGetIMCLockCount(imc);
1381  ok(count == 1, "expect 1, returned %d\n", count);
1382  ret = ImmDestroyContext(imc);
1383  ok(ret == TRUE, "Destroy a locked IMC should success!\n");
1384  ic = ImmLockIMC(imc);
1385  ok(ic == NULL, "Lock a destroyed IMC should fail!\n");
1386  ret = ImmUnlockIMC(imc);
1387  ok(ret == FALSE, "Unlock a destroyed IMC should fail!\n");
1388  count = ImmGetIMCLockCount(imc);
1389  ok(count == 0, "Get lock count of a destroyed IMC should return 0!\n");
1390  SetLastError(0xdeadbeef);
1391  ret = ImmDestroyContext(imc);
1392  ok(ret == FALSE, "Destroy a destroyed IMC should fail!\n");
1393  ret = GetLastError();
1394  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1395 }
1396 
1397 static void test_ImmDestroyIMCC(void)
1398 {
1399  HIMCC imcc;
1400  DWORD ret, count, size;
1401  VOID *p;
1402 
1403  imcc = ImmCreateIMCC(sizeof(CANDIDATEINFO));
1404  count = ImmGetIMCCLockCount(imcc);
1405  ok(count == 0, "expect 0, returned %d\n", count);
1406  p = ImmLockIMCC(imcc);
1407  ok(p != NULL, "ImmLockIMCC failed!\n");
1408  count = ImmGetIMCCLockCount(imcc);
1409  ok(count == 1, "expect 1, returned %d\n", count);
1410  size = ImmGetIMCCSize(imcc);
1411  ok(size == sizeof(CANDIDATEINFO), "returned %d\n", size);
1412  p = ImmDestroyIMCC(imcc);
1413  ok(p == NULL, "Destroy a locked IMCC should success!\n");
1414  p = ImmLockIMCC(imcc);
1415  ok(p == NULL, "Lock a destroyed IMCC should fail!\n");
1416  ret = ImmUnlockIMCC(imcc);
1417  ok(ret == FALSE, "Unlock a destroyed IMCC should return FALSE!\n");
1418  count = ImmGetIMCCLockCount(imcc);
1419  ok(count == 0, "Get lock count of a destroyed IMCC should return 0!\n");
1420  size = ImmGetIMCCSize(imcc);
1421  ok(size == 0, "Get size of a destroyed IMCC should return 0!\n");
1422  SetLastError(0xdeadbeef);
1423  p = ImmDestroyIMCC(imcc);
1424  ok(p != NULL, "returned NULL\n");
1425  ret = GetLastError();
1426  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1427 }
1428 
1429 static void test_ImmMessages(void)
1430 {
1431  CANDIDATEFORM cf;
1432  imm_msgs *msg;
1433  HWND defwnd;
1434  HIMC imc;
1435  UINT idx = 0;
1436 
1437  LPINPUTCONTEXT lpIMC;
1438  LPTRANSMSG lpTransMsg;
1439 
1440  HWND hwnd = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "Wine imm32.dll test",
1442  240, 120, NULL, NULL, GetModuleHandleA(NULL), NULL);
1443 
1445  defwnd = ImmGetDefaultIMEWnd(hwnd);
1446  imc = ImmGetContext(hwnd);
1447 
1448  ImmSetOpenStatus(imc, TRUE);
1451  do
1452  {
1454  if (msg) ok(!msg->post, "Message should not be posted\n");
1455  } while (msg);
1457 
1458  lpIMC = ImmLockIMC(imc);
1459  lpIMC->hMsgBuf = ImmReSizeIMCC(lpIMC->hMsgBuf, (lpIMC->dwNumMsgBuf + 1) * sizeof(TRANSMSG));
1460  lpTransMsg = ImmLockIMCC(lpIMC->hMsgBuf);
1461  lpTransMsg += lpIMC->dwNumMsgBuf;
1462  lpTransMsg->message = WM_IME_STARTCOMPOSITION;
1463  lpTransMsg->wParam = 0;
1464  lpTransMsg->lParam = 0;
1465  ImmUnlockIMCC(lpIMC->hMsgBuf);
1466  lpIMC->dwNumMsgBuf++;
1467  ImmUnlockIMC(imc);
1468  ImmGenerateMessage(imc);
1469  idx = 0;
1470  do
1471  {
1472  msg = msg_spy_find_next_msg(WM_IME_STARTCOMPOSITION, &idx);
1473  if (msg) ok(!msg->post, "Message should not be posted\n");
1474  } while (msg);
1476 
1477  lpIMC = ImmLockIMC(imc);
1478  lpIMC->hMsgBuf = ImmReSizeIMCC(lpIMC->hMsgBuf, (lpIMC->dwNumMsgBuf + 1) * sizeof(TRANSMSG));
1479  lpTransMsg = ImmLockIMCC(lpIMC->hMsgBuf);
1480  lpTransMsg += lpIMC->dwNumMsgBuf;
1481  lpTransMsg->message = WM_IME_COMPOSITION;
1482  lpTransMsg->wParam = 0;
1483  lpTransMsg->lParam = 0;
1484  ImmUnlockIMCC(lpIMC->hMsgBuf);
1485  lpIMC->dwNumMsgBuf++;
1486  ImmUnlockIMC(imc);
1487  ImmGenerateMessage(imc);
1488  idx = 0;
1489  do
1490  {
1491  msg = msg_spy_find_next_msg(WM_IME_COMPOSITION, &idx);
1492  if (msg) ok(!msg->post, "Message should not be posted\n");
1493  } while (msg);
1495 
1496  lpIMC = ImmLockIMC(imc);
1497  lpIMC->hMsgBuf = ImmReSizeIMCC(lpIMC->hMsgBuf, (lpIMC->dwNumMsgBuf + 1) * sizeof(TRANSMSG));
1498  lpTransMsg = ImmLockIMCC(lpIMC->hMsgBuf);
1499  lpTransMsg += lpIMC->dwNumMsgBuf;
1500  lpTransMsg->message = WM_IME_ENDCOMPOSITION;
1501  lpTransMsg->wParam = 0;
1502  lpTransMsg->lParam = 0;
1503  ImmUnlockIMCC(lpIMC->hMsgBuf);
1504  lpIMC->dwNumMsgBuf++;
1505  ImmUnlockIMC(imc);
1506  ImmGenerateMessage(imc);
1507  idx = 0;
1508  do
1509  {
1510  msg = msg_spy_find_next_msg(WM_IME_ENDCOMPOSITION, &idx);
1511  if (msg) ok(!msg->post, "Message should not be posted\n");
1512  } while (msg);
1514 
1515  ImmSetOpenStatus(imc, FALSE);
1516  ImmReleaseContext(hwnd, imc);
1518 }
1519 
1521  LPARAM lParam )
1522 {
1523  return DefWindowProcW(hWnd, msg, wParam, lParam);
1524 }
1525 
1526 static void test_ime_processkey(void)
1527 {
1528  WCHAR classNameW[] = {'P','r','o','c','e','s','s', 'K','e','y','T','e','s','t','C','l','a','s','s',0};
1529  WCHAR windowNameW[] = {'P','r','o','c','e','s','s', 'K','e','y',0};
1530 
1531  MSG msg;
1532  WNDCLASSW wclass;
1534  TEST_INPUT inputs[2];
1535  HIMC imc;
1536  INT rc;
1537  HWND hWndTest;
1538 
1539  wclass.lpszClassName = classNameW;
1540  wclass.style = CS_HREDRAW | CS_VREDRAW;
1542  wclass.hInstance = hInstance;
1543  wclass.hIcon = LoadIconW(0, (LPCWSTR)IDI_APPLICATION);
1544  wclass.hCursor = LoadCursorW( NULL, (LPCWSTR)IDC_ARROW);
1545  wclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
1546  wclass.lpszMenuName = 0;
1547  wclass.cbClsExtra = 0;
1548  wclass.cbWndExtra = 0;
1549  if(!RegisterClassW(&wclass)){
1550  win_skip("Failed to register window.\n");
1551  return;
1552  }
1553 
1554  /* create the test window that will receive the keystrokes */
1555  hWndTest = CreateWindowW(wclass.lpszClassName, windowNameW,
1556  WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 100, 100,
1557  NULL, NULL, hInstance, NULL);
1558 
1563 
1564  imc = ImmGetContext(hWndTest);
1565  if (!imc)
1566  {
1567  win_skip("IME not supported\n");
1569  return;
1570  }
1571 
1572  rc = ImmSetOpenStatus(imc, TRUE);
1573  if (rc != TRUE)
1574  {
1575  win_skip("Unable to open IME\n");
1578  return;
1579  }
1580 
1581  /* flush pending messages */
1582  while (PeekMessageW(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageW(&msg);
1583 
1584  SetFocus(hWndTest);
1585 
1586  /* init input data that never changes */
1587  inputs[1].type = inputs[0].type = INPUT_KEYBOARD;
1588  inputs[1].u.ki.dwExtraInfo = inputs[0].u.ki.dwExtraInfo = 0;
1589  inputs[1].u.ki.time = inputs[0].u.ki.time = 0;
1590 
1591  /* Pressing a key */
1592  inputs[0].u.ki.wVk = 0x41;
1593  inputs[0].u.ki.wScan = 0x1e;
1594  inputs[0].u.ki.dwFlags = 0x0;
1595 
1596  pSendInput(1, (INPUT*)inputs, sizeof(INPUT));
1597 
1598  while(PeekMessageW(&msg, hWndTest, 0, 0, PM_NOREMOVE)) {
1599  if(msg.message != WM_KEYDOWN)
1600  PeekMessageW(&msg, hWndTest, 0, 0, PM_REMOVE);
1601  else
1602  {
1603  ok(msg.wParam != VK_PROCESSKEY,"Incorrect ProcessKey Found\n");
1604  PeekMessageW(&msg, hWndTest, 0, 0, PM_REMOVE);
1605  if(msg.wParam == VK_PROCESSKEY)
1606  trace("ProcessKey was correctly found\n");
1607  }
1610  }
1611 
1612  inputs[0].u.ki.wVk = 0x41;
1613  inputs[0].u.ki.wScan = 0x1e;
1614  inputs[0].u.ki.dwFlags = KEYEVENTF_KEYUP;
1615 
1616  pSendInput(1, (INPUT*)inputs, sizeof(INPUT));
1617 
1618  while(PeekMessageW(&msg, hWndTest, 0, 0, PM_NOREMOVE)) {
1619  if(msg.message != WM_KEYUP)
1620  PeekMessageW(&msg, hWndTest, 0, 0, PM_REMOVE);
1621  else
1622  {
1623  ok(msg.wParam != VK_PROCESSKEY,"Incorrect ProcessKey Found\n");
1624  PeekMessageW(&msg, hWndTest, 0, 0, PM_REMOVE);
1625  ok(msg.wParam != VK_PROCESSKEY,"ProcessKey should still not be Found\n");
1626  }
1629  }
1630 
1632  ImmSetOpenStatus(imc, FALSE);
1634 }
1635 
1636 static void test_InvalidIMC(void)
1637 {
1638  HIMC imc_destroy;
1639  HIMC imc_null = 0x00000000;
1640  HIMC imc_bad = (HIMC)0xdeadcafe;
1641 
1642  HIMC imc1, imc2, oldimc;
1643  DWORD ret;
1644  DWORD count;
1645  CHAR buffer[1000];
1646  INPUTCONTEXT *ic;
1647  LOGFONTA lf;
1648 
1649  memset(&lf, 0, sizeof(lf));
1650 
1651  imc_destroy = ImmCreateContext();
1652  ret = ImmDestroyContext(imc_destroy);
1653  ok(ret == TRUE, "Destroy an IMC should success!\n");
1654 
1655  /* Test associating destroyed imc */
1656  imc1 = ImmGetContext(hwnd);
1657  SetLastError(0xdeadbeef);
1658  oldimc = ImmAssociateContext(hwnd, imc_destroy);
1659  ok(!oldimc, "Associating to a destroyed imc should fail!\n");
1660  ret = GetLastError();
1661  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1662  imc2 = ImmGetContext(hwnd);
1663  ok(imc1 == imc2, "imc should not changed! imc1 %p, imc2 %p\n", imc1, imc2);
1664 
1665  /* Test associating NULL imc, which is different from an invalid imc */
1666  oldimc = ImmAssociateContext(hwnd, imc_null);
1667  ok(oldimc != NULL, "Associating to NULL imc should success!\n");
1668  imc2 = ImmGetContext(hwnd);
1669  ok(!imc2, "expect NULL, returned %p\n", imc2);
1670  oldimc = ImmAssociateContext(hwnd, imc1);
1671  ok(!oldimc, "expect NULL, returned %p\n", oldimc);
1672  imc2 = ImmGetContext(hwnd);
1673  ok(imc2 == imc1, "imc should not changed! imc2 %p, imc1 %p\n", imc2, imc1);
1674 
1675  /* Test associating invalid imc */
1676  imc1 = ImmGetContext(hwnd);
1677  SetLastError(0xdeadbeef);
1678  oldimc = ImmAssociateContext(hwnd, imc_bad);
1679  ok(!oldimc, "Associating to a destroyed imc should fail!\n");
1680  ret = GetLastError();
1681  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1682  imc2 = ImmGetContext(hwnd);
1683  ok(imc1 == imc2, "imc should not changed! imc1 %p, imc2 %p\n", imc1, imc2);
1684 
1685 
1686  /* Test ImmGetCandidateListA */
1687  SetLastError(0xdeadbeef);
1688  ret = ImmGetCandidateListA(imc_bad, 0, NULL, 0);
1689  ok(ret == 0, "Bad IME should return 0\n");
1690  ret = GetLastError();
1691  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1692  SetLastError(0xdeadbeef);
1693  ret = ImmGetCandidateListA(imc_null, 0, NULL, 0);
1694  ok(ret == 0, "NULL IME should return 0\n");
1695  ret = GetLastError();
1696  ok(ret == 0xdeadbeef, "last error should remain unchanged %08x!\n", ret);
1697  SetLastError(0xdeadbeef);
1698  ret = ImmGetCandidateListA(imc_destroy, 0, NULL, 0);
1699  ok(ret == 0, "Destroyed IME should return 0\n");
1700  ret = GetLastError();
1701  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1702 
1703  /* Test ImmGetCandidateListCountA*/
1704  SetLastError(0xdeadbeef);
1705  ret = ImmGetCandidateListCountA(imc_bad,&count);
1706  ok(ret == 0, "Bad IME should return 0\n");
1707  ret = GetLastError();
1708  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1709  SetLastError(0xdeadbeef);
1710  ret = ImmGetCandidateListCountA(imc_null,&count);
1711  ok(ret == 0, "NULL IME should return 0\n");
1712  ret = GetLastError();
1713  ok(ret == 0xdeadbeef, "last error should remain unchanged %08x!\n", ret);
1714  SetLastError(0xdeadbeef);
1715  ret = ImmGetCandidateListCountA(imc_destroy,&count);
1716  ok(ret == 0, "Destroyed IME should return 0\n");
1717  ret = GetLastError();
1718  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1719 
1720  /* Test ImmGetCandidateWindow */
1721  SetLastError(0xdeadbeef);
1723  ok(ret == 0, "Bad IME should return 0\n");
1724  ret = GetLastError();
1725  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1726  SetLastError(0xdeadbeef);
1728  ok(ret == 0, "NULL IME should return 0\n");
1729  ret = GetLastError();
1730  ok(ret == 0xdeadbeef, "last error should remain unchanged %08x!\n", ret);
1731  SetLastError(0xdeadbeef);
1732  ret = ImmGetCandidateWindow(imc_destroy, 0, (LPCANDIDATEFORM)buffer);
1733  ok(ret == 0, "Destroyed IME should return 0\n");
1734  ret = GetLastError();
1735  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1736 
1737  /* Test ImmGetCompositionFontA */
1738  SetLastError(0xdeadbeef);
1740  ok(ret == 0, "Bad IME should return 0\n");
1741  ret = GetLastError();
1742  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1743  SetLastError(0xdeadbeef);
1745  ok(ret == 0, "NULL IME should return 0\n");
1746  ret = GetLastError();
1747  ok(ret == 0xdeadbeef, "last error should remain unchanged %08x!\n", ret);
1748  SetLastError(0xdeadbeef);
1749  ret = ImmGetCompositionFontA(imc_destroy, (LPLOGFONTA)buffer);
1750  ok(ret == 0, "Destroyed IME should return 0\n");
1751  ret = GetLastError();
1752  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1753 
1754  /* Test ImmGetCompositionWindow */
1755  SetLastError(0xdeadbeef);
1757  ok(ret == 0, "Bad IME should return 0\n");
1758  ret = GetLastError();
1759  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1760  SetLastError(0xdeadbeef);
1762  ok(ret == 0, "NULL IME should return 0\n");
1763  ret = GetLastError();
1764  ok(ret == 0xdeadbeef, "last error should remain unchanged %08x!\n", ret);
1765  SetLastError(0xdeadbeef);
1767  ok(ret == 0, "Destroyed IME should return 0\n");
1768  ret = GetLastError();
1769  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1770 
1771  /* Test ImmGetCompositionStringA */
1772  SetLastError(0xdeadbeef);
1773  ret = ImmGetCompositionStringA(imc_bad, GCS_COMPSTR, NULL, 0);
1774  ok(ret == 0, "Bad IME should return 0\n");
1775  ret = GetLastError();
1776  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1777  SetLastError(0xdeadbeef);
1778  ret = ImmGetCompositionStringA(imc_null, GCS_COMPSTR, NULL, 0);
1779  ok(ret == 0, "NULL IME should return 0\n");
1780  ret = GetLastError();
1781  ok(ret == 0xdeadbeef, "last error should remain unchanged %08x!\n", ret);
1782  SetLastError(0xdeadbeef);
1783  ret = ImmGetCompositionStringA(imc_destroy, GCS_COMPSTR, NULL, 0);
1784  ok(ret == 0, "Destroyed IME should return 0\n");
1785  ret = GetLastError();
1786  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1787 
1788  /* Test ImmSetOpenStatus */
1789  SetLastError(0xdeadbeef);
1790  ret = ImmSetOpenStatus(imc_bad, 1);
1791  ok(ret == 0, "Bad IME should return 0\n");
1792  ret = GetLastError();
1793  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1794  SetLastError(0xdeadbeef);
1795  ret = ImmSetOpenStatus(imc_null, 1);
1796  ok(ret == 0, "NULL IME should return 0\n");
1797  ret = GetLastError();
1798  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1799  SetLastError(0xdeadbeef);
1800  ret = ImmSetOpenStatus(imc_destroy, 1);
1801  ok(ret == 0, "Destroyed IME should return 0\n");
1802  ret = GetLastError();
1803  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1804 
1805  /* Test ImmGetOpenStatus */
1806  SetLastError(0xdeadbeef);
1807  ret = ImmGetOpenStatus(imc_bad);
1808  ok(ret == 0, "Bad IME should return 0\n");
1809  ret = GetLastError();
1810  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1811  SetLastError(0xdeadbeef);
1812  ret = ImmGetOpenStatus(imc_null);
1813  ok(ret == 0, "NULL IME should return 0\n");
1814  ret = GetLastError();
1815  ok(ret == 0xdeadbeef, "last error should remain unchanged %08x!\n", ret);
1816  SetLastError(0xdeadbeef);
1817  ret = ImmGetOpenStatus(imc_destroy);
1818  ok(ret == 0, "Destroyed IME should return 0\n");
1819  ret = GetLastError();
1820  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1821 
1822  /* Test ImmGetStatusWindowPos */
1823  SetLastError(0xdeadbeef);
1824  ret = ImmGetStatusWindowPos(imc_bad, NULL);
1825  ok(ret == 0, "Bad IME should return 0\n");
1826  ret = GetLastError();
1827  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1828  SetLastError(0xdeadbeef);
1829  ret = ImmGetStatusWindowPos(imc_null, NULL);
1830  ok(ret == 0, "NULL IME should return 0\n");
1831  ret = GetLastError();
1832  ok(ret == 0xdeadbeef, "last error should remain unchanged %08x!\n", ret);
1833  SetLastError(0xdeadbeef);
1834  ret = ImmGetStatusWindowPos(imc_destroy, NULL);
1835  ok(ret == 0, "Destroyed IME should return 0\n");
1836  ret = GetLastError();
1837  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1838 
1839  /* Test ImmRequestMessageA */
1840  SetLastError(0xdeadbeef);
1841  ret = ImmRequestMessageA(imc_bad, WM_CHAR, 0);
1842  ok(ret == 0, "Bad IME should return 0\n");
1843  ret = GetLastError();
1844  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1845  SetLastError(0xdeadbeef);
1846  ret = ImmRequestMessageA(imc_null, WM_CHAR, 0);
1847  ok(ret == 0, "NULL IME should return 0\n");
1848  ret = GetLastError();
1849  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1850  SetLastError(0xdeadbeef);
1851  ret = ImmRequestMessageA(imc_destroy, WM_CHAR, 0);
1852  ok(ret == 0, "Destroyed IME should return 0\n");
1853  ret = GetLastError();
1854  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1855 
1856  /* Test ImmSetCompositionFontA */
1857  SetLastError(0xdeadbeef);
1858  ret = ImmSetCompositionFontA(imc_bad, &lf);
1859  ok(ret == 0, "Bad IME should return 0\n");
1860  ret = GetLastError();
1861  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1862  SetLastError(0xdeadbeef);
1863  ret = ImmSetCompositionFontA(imc_null, &lf);
1864  ok(ret == 0, "NULL IME should return 0\n");
1865  ret = GetLastError();
1866  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1867  SetLastError(0xdeadbeef);
1868  ret = ImmSetCompositionFontA(imc_destroy, &lf);
1869  ok(ret == 0, "Destroyed IME should return 0\n");
1870  ret = GetLastError();
1871  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1872 
1873  /* Test ImmSetCompositionWindow */
1874  SetLastError(0xdeadbeef);
1875  ret = ImmSetCompositionWindow(imc_bad, NULL);
1876  ok(ret == 0, "Bad IME should return 0\n");
1877  ret = GetLastError();
1878  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1879  SetLastError(0xdeadbeef);
1880  ret = ImmSetCompositionWindow(imc_null, NULL);
1881  ok(ret == 0, "NULL IME should return 0\n");
1882  ret = GetLastError();
1883  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1884  SetLastError(0xdeadbeef);
1885  ret = ImmSetCompositionWindow(imc_destroy, NULL);
1886  ok(ret == 0, "Destroyed IME should return 0\n");
1887  ret = GetLastError();
1888  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1889 
1890  /* Test ImmSetConversionStatus */
1891  SetLastError(0xdeadbeef);
1892  ret = ImmSetConversionStatus(imc_bad, 0, 0);
1893  ok(ret == 0, "Bad IME should return 0\n");
1894  ret = GetLastError();
1895  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1896  SetLastError(0xdeadbeef);
1897  ret = ImmSetConversionStatus(imc_null, 0, 0);
1898  ok(ret == 0, "NULL IME should return 0\n");
1899  ret = GetLastError();
1900  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1901  SetLastError(0xdeadbeef);
1902  ret = ImmSetConversionStatus(imc_destroy, 0, 0);
1903  ok(ret == 0, "Destroyed IME should return 0\n");
1904  ret = GetLastError();
1905  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1906 
1907  /* Test ImmSetStatusWindowPos */
1908  SetLastError(0xdeadbeef);
1909  ret = ImmSetStatusWindowPos(imc_bad, 0);
1910  ok(ret == 0, "Bad IME should return 0\n");
1911  ret = GetLastError();
1912  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1913  SetLastError(0xdeadbeef);
1914  ret = ImmSetStatusWindowPos(imc_null, 0);
1915  ok(ret == 0, "NULL IME should return 0\n");
1916  ret = GetLastError();
1917  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1918  SetLastError(0xdeadbeef);
1919  ret = ImmSetStatusWindowPos(imc_destroy, 0);
1920  ok(ret == 0, "Destroyed IME should return 0\n");
1921  ret = GetLastError();
1922  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1923 
1924  /* Test ImmGetImeMenuItemsA */
1925  SetLastError(0xdeadbeef);
1926  ret = ImmGetImeMenuItemsA(imc_bad, 0, 0, NULL, NULL, 0);
1927  ok(ret == 0, "Bad IME should return 0\n");
1928  ret = GetLastError();
1929  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1930  SetLastError(0xdeadbeef);
1931  ret = ImmGetImeMenuItemsA(imc_null, 0, 0, NULL, NULL, 0);
1932  ok(ret == 0, "NULL IME should return 0\n");
1933  ret = GetLastError();
1934  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1935  SetLastError(0xdeadbeef);
1936  ret = ImmGetImeMenuItemsA(imc_destroy, 0, 0, NULL, NULL, 0);
1937  ok(ret == 0, "Destroyed IME should return 0\n");
1938  ret = GetLastError();
1939  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1940 
1941  /* Test ImmLockIMC */
1942  SetLastError(0xdeadbeef);
1943  ic = ImmLockIMC(imc_bad);
1944  ok(ic == 0, "Bad IME should return 0\n");
1945  ret = GetLastError();
1946  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1947  SetLastError(0xdeadbeef);
1948  ic = ImmLockIMC(imc_null);
1949  ok(ic == 0, "NULL IME should return 0\n");
1950  ret = GetLastError();
1951  ok(ret == 0xdeadbeef, "last error should remain unchanged %08x!\n", ret);
1952  SetLastError(0xdeadbeef);
1953  ic = ImmLockIMC(imc_destroy);
1954  ok(ic == 0, "Destroyed IME should return 0\n");
1955  ret = GetLastError();
1956  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1957 
1958  /* Test ImmUnlockIMC */
1959  SetLastError(0xdeadbeef);
1960  ret = ImmUnlockIMC(imc_bad);
1961  ok(ret == 0, "Bad IME should return 0\n");
1962  ret = GetLastError();
1963  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1964  SetLastError(0xdeadbeef);
1965  ret = ImmUnlockIMC(imc_null);
1966  ok(ret == 0, "NULL IME should return 0\n");
1967  ret = GetLastError();
1968  ok(ret == 0xdeadbeef, "last error should remain unchanged %08x!\n", ret);
1969  SetLastError(0xdeadbeef);
1970  ret = ImmUnlockIMC(imc_destroy);
1971  ok(ret == 0, "Destroyed IME should return 0\n");
1972  ret = GetLastError();
1973  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1974 
1975  /* Test ImmGenerateMessage */
1976  SetLastError(0xdeadbeef);
1977  ret = ImmGenerateMessage(imc_bad);
1978  ok(ret == 0, "Bad IME should return 0\n");
1979  ret = GetLastError();
1980  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1981  SetLastError(0xdeadbeef);
1982  ret = ImmGenerateMessage(imc_null);
1983  ok(ret == 0, "NULL IME should return 0\n");
1984  ret = GetLastError();
1985  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1986  SetLastError(0xdeadbeef);
1987  ret = ImmGenerateMessage(imc_destroy);
1988  ok(ret == 0, "Destroyed IME should return 0\n");
1989  ret = GetLastError();
1990  ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1991 }
1992 
1993 START_TEST(imm32) {
1994  if (init())
1995  {
1999  test_ImmIME();
2001  test_ImmThreads();
2011  test_InvalidIMC();
2012  msg_spy_cleanup();
2013  /* Reinitialize the hooks to capture all windows */
2014  msg_spy_init(NULL);
2015  test_ImmMessages();
2016  msg_spy_cleanup();
2017  if (pSendInput)
2019  else win_skip("SendInput is not available\n");
2020  }
2021  cleanup();
2022 }
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 ImmGetCandidateListCountA(HIMC hIMC, LPDWORD lpdwListCount)
Definition: imm.c:1041
DWORD HIMCC
Definition: dimm.idl:76
#define WS_CLIPSIBLINGS
Definition: pedump.c:618
static IClassFactory * cf
#define IACE_DEFAULT
Definition: imm.h:576
static void test_ImmSetCompositionString(void)
Definition: imm32.c:529
#define IMC_GETCANDIDATEPOS
Definition: imm.h:270
struct _WNDCLASSEXA WNDCLASSEXA
#define WS_DISABLED
Definition: pedump.c:621
#define WM_IME_KEYUP
Definition: winuser.h:1821
static void test_ImmGetIMCLockCount(void)
Definition: imm32.c:1265
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
UINT style
Definition: winuser.h:3176
BOOL catch_result_str
Definition: imm32.c:358
static void msg_spy_init(HWND hwnd)
Definition: imm32.c:147
static void test_ImmAssociateContextEx(void)
Definition: imm32.c:580
#define WM_IME_NOTIFY
Definition: winuser.h:1812
struct param_test tests[]
DWORD type
Definition: imm32.c:51
BOOL WINAPI TranslateMessage(_In_ const MSG *)
LRESULT WINAPI DispatchMessageA(_In_ const MSG *)
Definition: tftpd.h:59
static BOOL init(void)
Definition: imm32.c:239
MOUSEINPUT mi
Definition: imm32.c:54
LPCSTR lpszMenuName
Definition: winuser.h:3184
#define TRUE
Definition: types.h:120
BOOL WINAPI ImmConfigureIMEW(HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
Definition: imm.c:705
#define CloseHandle
Definition: compat.h:398
#define VK_PROCESSKEY
Definition: winuser.h:2302
#define WH_GETMESSAGE
Definition: winuser.h:33
#define WM_IME_KEYDOWN
Definition: winuser.h:1820
int WINAPI GetWindowTextA(HWND hWnd, LPSTR lpString, int nMaxCount)
Definition: window.c:1326
static LRESULT WINAPI imm_wnd_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
Definition: imm32.c:993
long y
Definition: polytest.cpp:48
#define CPS_COMPLETE
Definition: imm.h:304
UINT style
Definition: winuser.h:3150
#define ERROR_SUCCESS
Definition: deptool.c:10
#define WM_CHAR
Definition: winuser.h:1699
#define SCS_SETSTR
Definition: imm.h:447
HCURSOR hCursor
Definition: winuser.h:3182
WNDPROC lpfnWndProc
Definition: winuser.h:3177
LPCWSTR lpszMenuName
Definition: winuser.h:3158
#define WM_IME_CHAR
Definition: winuser.h:1816
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
CWPSTRUCT msg
Definition: imm32.c:37
BOOL WINAPI IsWindow(_In_opt_ HWND)
static DWORD WINAPI ImmGetContextThreadFunc(LPVOID lpParam)
Definition: imm32.c:627
#define KEYEVENTF_KEYUP
Definition: winuser.h:1092
long x
Definition: polytest.cpp:48
HWND hwndMain
Definition: solitaire.cpp:12
static LRESULT WINAPI wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
Definition: imm32.c:179
Definition: imm32.c:41
LPCSTR lpszClassName
Definition: winuser.h:3185
LPARAM lParam
Definition: imm.c:88
#define pt(x, y)
Definition: drawing.c:79
static WPARAM
Definition: imm32.c:30
HWND WINAPI SetParent(_In_ HWND, _In_opt_ HWND)
LRESULT WINAPI SendMessageA(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define SCS_CHANGEATTR
Definition: imm.h:448
LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
Definition: imm.c:2877
HANDLE event
Definition: imm32.c:621
#define WM_NCCALCSIZE
Definition: winuser.h:1667
int WINAPI lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:170
union TEST_INPUT::@1598 u
GLuint GLuint GLsizei count
Definition: gl.h:1545
DWORD timer_id
Definition: imm32.c:361
UINT NTAPI GlobalFlags(HGLOBAL hMem)
Definition: heapmem.c:520
char CHAR
Definition: xmlstorage.h:175
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1827
#define ERROR_INVALID_HANDLE
Definition: compat.h:88
Definition: imm32.c:36
unsigned int i_msg
Definition: imm32.c:46
#define CALLBACK
Definition: compat.h:27
BOOL WINAPI UpdateWindow(_In_ HWND)
HWND hWnd
Definition: settings.c:17
#define WM_QUIT
Definition: winuser.h:1605
DWORD WINAPI GetTickCount(VOID)
Definition: time.c:445
#define WM_IME_SELECT
Definition: winuser.h:1815
HANDLE HWND
Definition: compat.h:13
BOOL WINAPI GetMessageA(_Out_ LPMSG, _In_opt_ HWND, _In_ UINT, _In_ UINT)
HIMCC WINAPI ImmDestroyIMCC(HIMCC block)
Definition: imm.c:2923
BOOL WINAPI EnumThreadWindows(_In_ DWORD, _In_ WNDENUMPROC, _In_ LPARAM)
DWORD time
Definition: winable.h:50
BOOL WINAPI PostThreadMessageA(_In_ DWORD, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
static void msg_spy_pump_msg_queue(void)
Definition: imm32.c:106
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define CS_HREDRAW
Definition: winuser.h:648
#define GWL_EXSTYLE
Definition: winuser.h:845
#define HWND_TOPMOST
Definition: winuser.h:1194
DWORD WINAPI ImmGetIMCCSize(HIMCC imcc)
Definition: imm.c:2963
GLuint buffer
Definition: glext.h:5915
int cbClsExtra
Definition: winuser.h:3152
HWND WINAPI SetFocus(_In_opt_ HWND)
DWORD dwStyle
Definition: dimm.idl:80
static BOOL CALLBACK is_ime_window_proc(HWND hWnd, LPARAM param)
Definition: imm32.c:1063
#define test
Definition: rosglue.h:37
HGLOBAL NTAPI GlobalHandle(LPCVOID pMem)
Definition: heapmem.c:705
#define IDI_APPLICATION
Definition: winuser.h:699
UINT_PTR WPARAM
Definition: windef.h:207
#define WS_CHILD
Definition: pedump.c:617
#define HWND_MESSAGE
Definition: winuser.h:1196
HICON hIconSm
Definition: winuser.h:3186
int winetest_interactive
BOOL WINAPI ShowWindow(_In_ HWND, _In_ int)
static void test_ImmIME(void)
Definition: imm32.c:564
HARDWAREINPUT hi
Definition: imm32.c:56
BOOL WINAPI PeekMessageA(_Out_ LPMSG, _In_opt_ HWND, _In_ UINT, _In_ UINT, _In_ UINT)
BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
Definition: imm.c:1989
UINT message
Definition: imm.c:86
static DWORD WINAPI test_default_ime_disabled_cb(void *arg)
Definition: imm32.c:1166
#define WM_NCCREATE
Definition: winuser.h:1665
BOOL WINAPI DestroyWindow(_In_ HWND)
static void test_ImmGetIMCCLockCount(void)
Definition: imm32.c:1323
#define CreateWindowW(a, b, c, d, e, f, g, h, i, j, k)
Definition: winuser.h:4217
#define COLOR_WINDOW
Definition: winuser.h:908
#define WM_IME_COMPOSITIONFULL
Definition: winuser.h:1814
int32_t INT
Definition: typedefs.h:56
WPARAM wParam
Definition: combotst.c:138
HICON WINAPI LoadIconA(_In_opt_ HINSTANCE, _In_ LPCSTR)
Definition: cursoricon.c:2029
FILE * stdout
LRESULT WINAPI DefWindowProcW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
LONG WINAPI ImmGetCompositionStringA(HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
Definition: imm.c:1459
BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
Definition: imm.c:2610
BOOL WINAPI ImmDestroyContext(HIMC hIMC)
Definition: imm.c:826
static void msg_spy_cleanup(void)
Definition: imm32.c:160
LRESULT WINAPI CallWindowProcA(_In_ WNDPROC, _In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define PM_NOREMOVE
Definition: winuser.h:1181
int WINAPI GetClassNameW(_In_ HWND hWnd, _Out_writes_to_(nMaxCount, return) LPWSTR lpClassName, _In_ int nMaxCount)
#define SCS_CAP_COMPSTR
Definition: imm.h:395
BOOL catch_ime_char
Definition: imm32.c:359
BOOL WINAPI ImmSetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
Definition: imm.c:2492
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
BOOL WINAPI ImmGetConversionStatus(HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence)
Definition: imm.c:1604
ATOM WINAPI RegisterClassW(_In_ CONST WNDCLASSW *)
HWND hwnd
Definition: imm32.c:42
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 const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
HINSTANCE hInstance
Definition: charmap.c:20
HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
Definition: imm.c:1716
#define INPUT_KEYBOARD
Definition: winable.h:10
LPVOID WINAPI ImmLockIMCC(HIMCC imcc)
Definition: imm.c:2931
LONG WINAPI GetWindowLongA(_In_ HWND, _In_ int)
HINSTANCE hInstance
Definition: winuser.h:3180
LRESULT WINAPI DispatchMessageW(_In_ const MSG *)
DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC)
Definition: imm.c:2904
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
static void msg_spy_flush_msgs(void)
Definition: imm32.c:117
static void test_default_ime_window_creation(void)
Definition: imm32.c:1218
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
static enum @1596 test_phase
static UINT WPARAM LPARAM lparam
Definition: combo.c:716
UINT WINAPI ImmGetDescriptionA(HKL hKL, LPSTR lpszDescription, UINT uBufLen)
Definition: imm.c:1731
WNDPROC lpfnWndProc
Definition: winuser.h:3151
static void test_ImmThreads(void)
Definition: imm32.c:679
static DWORD WINAPI test_default_ime_window_cancel_cb(void *arg)
Definition: imm32.c:1128
static const char wndcls[]
Definition: imm32.c:172
static UINT
Definition: imm32.c:30
#define CreateWindowA(a, b, c, d, e, f, g, h, i, j, k)
Definition: winuser.h:4216
unsigned int idx
Definition: utils.c:41
#define CW_USEDEFAULT
Definition: winuser.h:225
static imm_msgs * msg_spy_find_msg(UINT message)
Definition: imm32.c:141
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:136
static const WCHAR imeW[]
Definition: imm.c:309
smooth NULL
Definition: ftsmooth.c:416
HWND WINAPI GetDesktopWindow(void)
Definition: window.c:652
#define GCS_RESULTSTR
Definition: imm.h:366
#define WM_KEYDOWN
Definition: winuser.h:1697
LPCWSTR lpszClassName
Definition: winuser.h:3159
LONG_PTR LPARAM
Definition: windef.h:208
UINT cbSize
Definition: winuser.h:3175
struct _tagTRANSMSG * LPTRANSMSG
static HWND thread_ime_wnd
Definition: imm32.c:999
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventA(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCSTR lpName OPTIONAL)
Definition: synch.c:637
const char * LPCSTR
Definition: xmlstorage.h:183
#define SW_SHOW
Definition: winuser.h:769
#define WM_IME_REQUEST
Definition: winuser.h:1818
DWORD HIMC
Definition: dimm.idl:75
static void test_InvalidIMC(void)
Definition: imm32.c:1636
HIMC WINAPI ImmCreateContext(void)
Definition: imm.c:740
DWORD WINAPI GetCurrentThreadId(VOID)
Definition: thread.c:458
HBRUSH hbrBackground
Definition: winuser.h:3183
UINT_PTR WINAPI SetTimer(_In_opt_ HWND, _In_ UINT_PTR, _In_ UINT, _In_opt_ TIMERPROC)
#define WM_DESTROY
Definition: winuser.h:1591
BOOL WINAPI ImmGetOpenStatus(HIMC hIMC)
Definition: imm.c:1886
static HWND hWndTest
Definition: input.c:68
LRESULT WINAPI ImmRequestMessageA(HIMC hIMC, WPARAM wParam, LPARAM lParam)
Definition: imm.c:2267
DWORD dwFlags
Definition: winable.h:49
#define CS_VREDRAW
Definition: winuser.h:653
static LRESULT CALLBACK processkey_wnd_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
Definition: imm32.c:1520
#define ERROR_INVALID_WINDOW_HANDLE
Definition: winerror.h:881
#define WAIT_OBJECT_0
Definition: winbase.h:387
GLsizeiptr size
Definition: glext.h:5919
#define IGP_SETCOMPSTR
Definition: imm.h:442
#define trace
Definition: atltest.h:70
static LPARAM
Definition: imm32.c:30
struct _igc_threadinfo igc_threadinfo
r parent
Definition: btrfs.c:2897
int cbWndExtra
Definition: winuser.h:3153
static void test_ImmDestroyIMCC(void)
Definition: imm32.c:1397
static struct @1597 ime_composition_test
__wchar_t WCHAR
Definition: xmlstorage.h:180
BOOL WINAPI UnloadKeyboardLayout(_In_ HKL)
BOOL WINAPI SetWindowTextA(_In_ HWND, _In_opt_ LPCSTR)
LONG WINAPI ImmGetCompositionStringW(HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
Definition: imm.c:1469
#define WM_IME_SETCONTEXT
Definition: winuser.h:1811
HIMC WINAPI ImmGetContext(HWND hWnd)
Definition: imm.c:1496
struct _msgs imm_msgs
#define WM_TIMER
Definition: winuser.h:1724
#define WM_IME_CONTROL
Definition: winuser.h:1813
#define WM_CLOSE
Definition: winuser.h:1603
GLfloat param
Definition: glext.h:5796
#define WINAPI
Definition: msvc.h:8
#define WM_KEYUP
Definition: winuser.h:1698
#define CFS_CANDIDATEPOS
Definition: imm.h:467
unsigned long DWORD
Definition: ntddk_ex.h:95
GLint left
Definition: glext.h:7726
HICON hIcon
Definition: winuser.h:3155
static void test_ImmIsUIMessage(void)
Definition: imm32.c:850
BOOL WINAPI ImmSetCompositionStringW(HIMC hIMC, DWORD dwIndex, LPCVOID lpComp, DWORD dwCompLen, LPCVOID lpRead, DWORD dwReadLen)
Definition: imm.c:2433
int cbWndExtra
Definition: winuser.h:3179
HHOOK get_msg_hook
Definition: imm32.c:43
#define SCS_CHANGECLAUSE
Definition: imm.h:449
struct _tagTRANSMSG TRANSMSG
HCURSOR WINAPI LoadCursorW(_In_opt_ HINSTANCE, _In_ LPCWSTR)
Definition: cursoricon.c:2074
#define SetLastError(x)
Definition: compat.h:409
BOOL WINAPI ImmUnlockIMCC(HIMCC imcc)
Definition: imm.c:2939
BOOL top_level_window
Definition: imm32.c:1085
BOOL post
Definition: imm32.c:38
static void test_ImmGetDescription(void)
Definition: imm32.c:937
static DWORD
Definition: imm32.c:29
DWORD WINAPI MsgWaitForMultipleObjects(_In_ DWORD nCount, _In_reads_opt_(nCount) CONST HANDLE *pHandles, _In_ BOOL fWaitAll, _In_ DWORD dwMilliseconds, _In_ DWORD dwWakeMask)
static HANDLE thread
Definition: service.c:33
static LRESULT CALLBACK get_msg_filter(int nCode, WPARAM wParam, LPARAM lParam)
Definition: imm32.c:68
int ret
DWORD dwThreadId
Definition: fdebug.c:31
static LRESULT WINAPI test_ime_wnd_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
Definition: imm32.c:364
HIMCC hMsgBuf
Definition: imm.h:45
static struct _msg_spy msg_spy
HICON hIcon
Definition: winuser.h:3181
DWORD WINAPI ImmGetImeMenuItemsA(HIMC hIMC, DWORD dwFlags, DWORD dwType, LPIMEMENUITEMINFOA lpImeParentMenu, LPIMEMENUITEMINFOA lpImeMenu, DWORD dwSize)
Definition: imm.c:2737
POINT ptCurrentPos
Definition: dimm.idl:81
#define WH_CALLWNDPROC
Definition: winuser.h:34
#define todo_wine
Definition: test.h:154
BOOL WINAPI ImmDisableIME(DWORD idThread)
Definition: imm.c:837
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
#define SetWindowLongPtrA
Definition: winuser.h:5246
#define CPS_CANCEL
Definition: imm.h:307
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:821
#define GCS_COMPATTR
Definition: imm.h:360
#define err(...)
LRESULT WINAPI DefWindowProcA(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
UINT_PTR HKL
Definition: msctf.idl:101
ATOM WINAPI RegisterClassExA(_In_ CONST WNDCLASSEXA *)
HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC)
Definition: imm.c:563
static HIMC
Definition: imm32.c:29
BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
Definition: imm.c:2328
HCURSOR WINAPI LoadCursorA(_In_opt_ HINSTANCE, _In_ LPCSTR)
Definition: cursoricon.c:2059
BOOL WINAPI UnhookWindowsHookEx(_In_ HHOOK)
#define GWLP_WNDPROC
Definition: treelist.c:66
#define broken(x)
Definition: _sntprintf.h:21
static PEXPLICIT_ACCESSW *static HMODULE hmod
Definition: security.c:141
DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex)
Definition: imm.c:1905
BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
Definition: imm.c:2253
#define SWP_NOSIZE
Definition: winuser.h:1230
HCURSOR hCursor
Definition: winuser.h:3156
LRESULT(CALLBACK * WNDPROC)(HWND, UINT, WPARAM, LPARAM)
Definition: winuser.h:2880
#define GWL_STYLE
Definition: winuser.h:846
HWND WINAPI GetParent(_In_ HWND)
LRESULT WINAPI CallNextHookEx(_In_opt_ HHOOK, _In_ int, _In_ WPARAM, _In_ LPARAM)
#define SW_SHOWNORMAL
Definition: winuser.h:764
int cbClsExtra
Definition: winuser.h:3178
static DWORD WINAPI test_default_ime_window_cb(void *arg)
Definition: imm32.c:1088
HKL hkl
Definition: msctf.idl:611
WPARAM wParam
Definition: imm.c:87
static void test_ImmNotifyIME(void)
Definition: imm32.c:295
BOOL WINAPI ImmGenerateMessage(HIMC hIMC)
Definition: imm.c:2971
static LRESULT CALLBACK call_wnd_proc_filter(int nCode, WPARAM wParam, LPARAM lParam)
Definition: imm32.c:88
BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
Definition: imm.c:2571
#define WS_EX_CLIENTEDGE
Definition: winuser.h:384
int WINAPIV wsprintfA(_Out_ LPSTR, _In_ _Printf_format_string_ LPCSTR,...)
BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
Definition: imm.c:1168
WORD wScan
Definition: winable.h:48
UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen)
Definition: imm.c:1767
static imm_msgs * msg_spy_find_next_msg(UINT message, UINT *start)
Definition: imm32.c:122
DWORD dwIndex
Definition: dimm.idl:79
GLuint start
Definition: gl.h:1545
#define ARRAY_SIZE(a)
Definition: main.h:24
#define HC_ACTION
Definition: winuser.h:48
static LRESULT(WINAPI *old_imm_wnd_proc)(HWND
DWORD WINAPI ImmGetCandidateListA(HIMC hIMC, DWORD dwIndex, LPCANDIDATELIST lpCandList, DWORD dwBufLen)
Definition: imm.c:1002
HBRUSH hbrBackground
Definition: winuser.h:3157
#define QS_ALLINPUT
Definition: winuser.h:874
#define ok(value,...)
Definition: atltest.h:57
static INPUT size_t
Definition: imm32.c:31
PKEYBOARD_LAYOUT GetKeyboardLayout()
Definition: utils.c:194
BOOL WINAPI ImmConfigureIMEA(HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
Definition: imm.c:670
DWORD dwNumMsgBuf
Definition: imm.h:44
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
#define IME_CONFIG_REGISTERWORD
Definition: imm.h:547
HIMCC WINAPI ImmCreateIMCC(DWORD size)
Definition: imm.c:2915
#define WS_POPUP
Definition: pedump.c:616
BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
Definition: imm.c:1479
unsigned int UINT
Definition: ndis.h:50
#define WM_MOUSEMOVE
Definition: winuser.h:1757
HHOOK call_wnd_proc_hook
Definition: imm32.c:44
BOOL NTAPI GlobalUnlock(HGLOBAL hMem)
Definition: heapmem.c:1190
static HWND hwnd
Definition: imm32.c:175
DWORD WINAPI ImmGetIMCCLockCount(HIMCC imcc)
Definition: imm.c:2947
BOOL WINAPI GetMessageW(_Out_ LPMSG, _In_opt_ HWND, _In_ UINT, _In_ UINT)
HANDLE hThread
Definition: wizard.c:27
START_TEST(imm32)
Definition: imm32.c:1993
BOOL WINAPI ImmSetCandidateWindow(HIMC hIMC, LPCANDIDATEFORM lpCandidate)
Definition: imm.c:2297
HINSTANCE hInstance
Definition: winuser.h:3154
#define skip(...)
Definition: atltest.h:64
#define msg(x)
Definition: auth_time.c:54
#define IDC_ARROW
Definition: winuser.h:682
BOOL WINAPI ImmSetCompositionStringA(HIMC hIMC, DWORD dwIndex, LPCVOID lpComp, DWORD dwCompLen, LPCVOID lpRead, DWORD dwReadLen)
Definition: imm.c:2378
BOOL WINAPI ImmGetCandidateWindow(HIMC hIMC, DWORD dwIndex, LPCANDIDATEFORM lpCandidate)
Definition: imm.c:1144
WNDPROC old_wnd_proc
Definition: imm32.c:357
HHOOK WINAPI SetWindowsHookExW(_In_ int, _In_ HOOKPROC, _In_opt_ HINSTANCE, _In_ DWORD)
#define WM_CREATE
Definition: winuser.h:1590
static void test_ImmGetContext(void)
Definition: imm32.c:921
HWND WINAPI CreateWindowExA(_In_ DWORD dwExStyle, _In_opt_ LPCSTR lpClassName, _In_opt_ LPCSTR lpWindowName, _In_ DWORD dwStyle, _In_ int X, _In_ int Y, _In_ int nWidth, _In_ int nHeight, _In_opt_ HWND hWndParent, _In_opt_ HMENU hMenu, _In_opt_ HINSTANCE hInstance, _In_opt_ LPVOID lpParam)
HIMCC WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size)
Definition: imm.c:2955
static void cleanup(void)
Definition: imm32.c:288
#define WS_OVERLAPPEDWINDOW
Definition: pedump.c:637
HIMC u_himc
Definition: imm32.c:623
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:847
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
BOOL WINAPI SetForegroundWindow(_In_ HWND)
HICON WINAPI LoadIconW(_In_opt_ HINSTANCE, _In_ LPCWSTR)
Definition: cursoricon.c:2044
BOOL WINAPI ImmSetConversionStatus(HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence)
Definition: imm.c:2533
BOOL WINAPI ImmNotifyIME(HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
Definition: imm.c:2168
ULONG_PTR dwExtraInfo
Definition: winable.h:51
#define GetProcAddress(x, y)
Definition: compat.h:410
#define SWP_NOMOVE
Definition: winuser.h:1229
static void test_ImmDestroyContext(void)
Definition: imm32.c:1369
static HWND get_ime_window(void)
Definition: imm32.c:1076
BOOL WINAPI SetWindowPos(_In_ HWND, _In_opt_ HWND, _In_ int, _In_ int, _In_ int, _In_ int, _In_ UINT)
#define SetWindowLongPtrW
Definition: winuser.h:5247
BOOL WINAPI UnregisterClassA(_In_ LPCSTR, HINSTANCE)
BOOL WINAPI PeekMessageW(_Out_ LPMSG, _In_opt_ HWND, _In_ UINT, _In_ UINT, _In_ UINT)
#define PM_REMOVE
Definition: winuser.h:1182
static void test_ime_processkey(void)
Definition: imm32.c:1526
static BOOL(WINAPI *pImmAssociateContextEx)(HWND
GLfloat GLfloat p
Definition: glext.h:8902
LONG_PTR LRESULT
Definition: windef.h:209
#define INFINITE
Definition: serial.h:102
#define NI_COMPOSITIONSTR
Definition: imm.h:290
static DWORD WINAPI test_default_ime_with_message_only_window_cb(void *arg)
Definition: imm32.c:1183
Arabic default style
Definition: afstyles.h:93
#define WS_VISIBLE
Definition: pedump.c:620
static void test_ImmMessages(void)
Definition: imm32.c:1429
DWORD start
Definition: imm32.c:360
#define memset(x, y, z)
Definition: compat.h:39
KEYBDINPUT ki
Definition: imm32.c:55
#define GCS_COMPSTR
Definition: imm.h:359
static SERVICE_STATUS status
Definition: service.c:31
#define GMEM_LOCKCOUNT
Definition: winbase.h:306
#define win_skip
Definition: test.h:141
BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
Definition: imm.c:2890
LPARAM lParam
Definition: combotst.c:139
static char title[]
Definition: ps.c:92
WORD wVk
Definition: winable.h:47
static DWORD WINAPI test_ImmGetDefaultIMEWnd_thread(void *arg)
Definition: imm32.c:1000
UINT WINAPI RegisterWindowMessageA(_In_ LPCSTR)
KEYBDINPUT ki
Definition: winable.h:62
static UINT WPARAM wparam
Definition: combo.c:716
static void test_ImmGetCompositionString(void)
Definition: imm32.c:422
imm_msgs msgs[64]
Definition: imm32.c:45
Definition: ps.c:97
static void test_ImmDefaultHwnd(void)
Definition: imm32.c:1010