imm32: Return FALSE on WM_MSIME_* messages in ImmIsUIMessage.
[wine.git] / dlls / imm32 / tests / imm32.c
blobd43464870cee7c5b9fef2e981412d9c77b8f850a
1 /*
2 * Unit tests for imm32
4 * Copyright (c) 2008 Michael Jung
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.
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.
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
21 #include <stdio.h>
23 #include "wine/test.h"
24 #include "winuser.h"
25 #include "wingdi.h"
26 #include "imm.h"
27 #include "ddk/imm.h"
29 #define NUMELEMS(array) (sizeof((array))/sizeof((array)[0]))
31 static BOOL (WINAPI *pImmAssociateContextEx)(HWND,HIMC,DWORD);
32 static BOOL (WINAPI *pImmIsUIMessageA)(HWND,UINT,WPARAM,LPARAM);
33 static UINT (WINAPI *pSendInput) (UINT, INPUT*, size_t);
36 * msgspy - record and analyse message traces sent to a certain window
38 typedef struct _msgs {
39 CWPSTRUCT msg;
40 BOOL post;
41 } imm_msgs;
43 static struct _msg_spy {
44 HWND hwnd;
45 HHOOK get_msg_hook;
46 HHOOK call_wnd_proc_hook;
47 imm_msgs msgs[32];
48 unsigned int i_msg;
49 } msg_spy;
51 typedef struct
53 DWORD type;
54 union
56 MOUSEINPUT mi;
57 KEYBDINPUT ki;
58 HARDWAREINPUT hi;
59 } u;
60 } TEST_INPUT;
62 static UINT (WINAPI *pSendInput) (UINT, INPUT*, size_t);
64 static LRESULT CALLBACK get_msg_filter(int nCode, WPARAM wParam, LPARAM lParam)
66 if (HC_ACTION == nCode) {
67 MSG *msg = (MSG*)lParam;
69 if ((msg->hwnd == msg_spy.hwnd || msg_spy.hwnd == NULL) &&
70 (msg_spy.i_msg < NUMELEMS(msg_spy.msgs)))
72 msg_spy.msgs[msg_spy.i_msg].msg.hwnd = msg->hwnd;
73 msg_spy.msgs[msg_spy.i_msg].msg.message = msg->message;
74 msg_spy.msgs[msg_spy.i_msg].msg.wParam = msg->wParam;
75 msg_spy.msgs[msg_spy.i_msg].msg.lParam = msg->lParam;
76 msg_spy.msgs[msg_spy.i_msg].post = TRUE;
77 msg_spy.i_msg++;
81 return CallNextHookEx(msg_spy.get_msg_hook, nCode, wParam, lParam);
84 static LRESULT CALLBACK call_wnd_proc_filter(int nCode, WPARAM wParam,
85 LPARAM lParam)
87 if (HC_ACTION == nCode) {
88 CWPSTRUCT *cwp = (CWPSTRUCT*)lParam;
90 if (((cwp->hwnd == msg_spy.hwnd || msg_spy.hwnd == NULL)) &&
91 (msg_spy.i_msg < NUMELEMS(msg_spy.msgs)))
93 memcpy(&msg_spy.msgs[msg_spy.i_msg].msg, cwp, sizeof(msg_spy.msgs[0].msg));
94 msg_spy.msgs[msg_spy.i_msg].post = FALSE;
95 msg_spy.i_msg++;
99 return CallNextHookEx(msg_spy.call_wnd_proc_hook, nCode, wParam, lParam);
102 static void msg_spy_pump_msg_queue(void) {
103 MSG msg;
105 while(PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) {
106 TranslateMessage(&msg);
107 DispatchMessageW(&msg);
110 return;
113 static void msg_spy_flush_msgs(void) {
114 msg_spy_pump_msg_queue();
115 msg_spy.i_msg = 0;
118 static imm_msgs* msg_spy_find_next_msg(UINT message, UINT *start) {
119 UINT i;
121 msg_spy_pump_msg_queue();
123 if (msg_spy.i_msg >= NUMELEMS(msg_spy.msgs))
124 fprintf(stdout, "%s:%d: msg_spy: message buffer overflow!\n",
125 __FILE__, __LINE__);
127 for (i = *start; i < msg_spy.i_msg; i++)
128 if (msg_spy.msgs[i].msg.message == message)
130 *start = i+1;
131 return &msg_spy.msgs[i];
134 return NULL;
137 static imm_msgs* msg_spy_find_msg(UINT message) {
138 UINT i = 0;
140 return msg_spy_find_next_msg(message, &i);
143 static void msg_spy_init(HWND hwnd) {
144 msg_spy.hwnd = hwnd;
145 msg_spy.get_msg_hook =
146 SetWindowsHookExW(WH_GETMESSAGE, get_msg_filter, GetModuleHandleW(NULL),
147 GetCurrentThreadId());
148 msg_spy.call_wnd_proc_hook =
149 SetWindowsHookExW(WH_CALLWNDPROC, call_wnd_proc_filter,
150 GetModuleHandleW(NULL), GetCurrentThreadId());
151 msg_spy.i_msg = 0;
153 msg_spy_flush_msgs();
156 static void msg_spy_cleanup(void) {
157 if (msg_spy.get_msg_hook)
158 UnhookWindowsHookEx(msg_spy.get_msg_hook);
159 if (msg_spy.call_wnd_proc_hook)
160 UnhookWindowsHookEx(msg_spy.call_wnd_proc_hook);
161 memset(&msg_spy, 0, sizeof(msg_spy));
165 * imm32 test cases - Issue some IMM commands on a dummy window and analyse the
166 * messages being sent to this window in response.
168 static const char wndcls[] = "winetest_imm32_wndcls";
169 static HWND hwnd;
171 static LRESULT WINAPI wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
173 switch (msg)
175 case WM_IME_SETCONTEXT:
176 case WM_NCCREATE:
177 case WM_CREATE:
178 return TRUE;
181 return DefWindowProcA(hwnd,msg,wParam,lParam);
184 static BOOL init(void) {
185 WNDCLASSEXA wc;
186 HIMC imc;
187 HMODULE hmod,huser;
189 hmod = GetModuleHandleA("imm32.dll");
190 huser = GetModuleHandleA("user32");
191 pImmAssociateContextEx = (void*)GetProcAddress(hmod, "ImmAssociateContextEx");
192 pImmIsUIMessageA = (void*)GetProcAddress(hmod, "ImmIsUIMessageA");
193 pSendInput = (void*)GetProcAddress(huser, "SendInput");
195 wc.cbSize = sizeof(WNDCLASSEXA);
196 wc.style = 0;
197 wc.lpfnWndProc = wndProc;
198 wc.cbClsExtra = 0;
199 wc.cbWndExtra = 0;
200 wc.hInstance = GetModuleHandleA(NULL);
201 wc.hIcon = LoadIconA(NULL, (LPCSTR)IDI_APPLICATION);
202 wc.hCursor = LoadCursorA(NULL, (LPCSTR)IDC_ARROW);
203 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
204 wc.lpszMenuName = NULL;
205 wc.lpszClassName = wndcls;
206 wc.hIconSm = LoadIconA(NULL, (LPCSTR)IDI_APPLICATION);
208 if (!RegisterClassExA(&wc))
209 return FALSE;
211 hwnd = CreateWindowExA(WS_EX_CLIENTEDGE, wndcls, "Wine imm32.dll test",
212 WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
213 240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL);
214 if (!hwnd)
215 return FALSE;
217 imc = ImmGetContext(hwnd);
218 if (!imc)
220 win_skip("IME support not implemented\n");
221 return FALSE;
223 ImmReleaseContext(hwnd, imc);
225 ShowWindow(hwnd, SW_SHOWNORMAL);
226 UpdateWindow(hwnd);
228 msg_spy_init(hwnd);
230 return TRUE;
233 static void cleanup(void) {
234 msg_spy_cleanup();
235 if (hwnd)
236 DestroyWindow(hwnd);
237 UnregisterClassA(wndcls, GetModuleHandleW(NULL));
240 static void test_ImmNotifyIME(void) {
241 static const char string[] = "wine";
242 char resstr[16] = "";
243 HIMC imc;
244 BOOL ret;
246 imc = ImmGetContext(hwnd);
247 msg_spy_flush_msgs();
249 ret = ImmNotifyIME(imc, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
250 ok(broken(!ret) ||
251 ret, /* Vista+ */
252 "Canceling an empty composition string should succeed.\n");
253 ok(!msg_spy_find_msg(WM_IME_COMPOSITION), "Windows does not post "
254 "WM_IME_COMPOSITION in response to NI_COMPOSITIONSTR / CPS_CANCEL, if "
255 "the composition string being canceled is empty.\n");
257 ImmSetCompositionStringA(imc, SCS_SETSTR, string, sizeof(string), NULL, 0);
258 msg_spy_flush_msgs();
260 ImmNotifyIME(imc, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
261 msg_spy_flush_msgs();
263 /* behavior differs between win9x and NT */
264 ret = ImmGetCompositionStringA(imc, GCS_COMPSTR, resstr, sizeof(resstr));
265 ok(!ret, "After being cancelled the composition string is empty.\n");
267 msg_spy_flush_msgs();
269 ret = ImmNotifyIME(imc, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
270 ok(broken(!ret) ||
271 ret, /* Vista+ */
272 "Canceling an empty composition string should succeed.\n");
273 ok(!msg_spy_find_msg(WM_IME_COMPOSITION), "Windows does not post "
274 "WM_IME_COMPOSITION in response to NI_COMPOSITIONSTR / CPS_CANCEL, if "
275 "the composition string being canceled is empty.\n");
277 msg_spy_flush_msgs();
278 ImmReleaseContext(hwnd, imc);
280 imc = ImmCreateContext();
281 ImmDestroyContext(imc);
283 SetLastError(0xdeadbeef);
284 ret = ImmNotifyIME((HIMC)0xdeadcafe, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
285 ok (ret == 0, "Bad IME should return 0\n");
286 ret = GetLastError();
287 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
288 SetLastError(0xdeadbeef);
289 ret = ImmNotifyIME(0x00000000, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
290 ok (ret == 0, "NULL IME should return 0\n");
291 ret = GetLastError();
292 ok(ret == ERROR_SUCCESS, "wrong last error %08x!\n", ret);
293 SetLastError(0xdeadbeef);
294 ret = ImmNotifyIME(imc, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
295 ok (ret == 0, "Destroyed IME should return 0\n");
296 ret = GetLastError();
297 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
301 static void test_ImmGetCompositionString(void)
303 HIMC imc;
304 static const WCHAR string[] = {'w','i','n','e',0x65e5,0x672c,0x8a9e};
305 char cstring[20];
306 WCHAR wstring[20];
307 DWORD len;
308 DWORD alen,wlen;
310 imc = ImmGetContext(hwnd);
311 ImmSetCompositionStringW(imc, SCS_SETSTR, string, sizeof(string), NULL,0);
312 alen = ImmGetCompositionStringA(imc, GCS_COMPSTR, cstring, 20);
313 wlen = ImmGetCompositionStringW(imc, GCS_COMPSTR, wstring, 20);
314 /* windows machines without any IME installed just return 0 above */
315 if( alen && wlen)
317 len = ImmGetCompositionStringW(imc, GCS_COMPATTR, NULL, 0);
318 ok(len*sizeof(WCHAR)==wlen,"GCS_COMPATTR(W) not returning correct count\n");
319 len = ImmGetCompositionStringA(imc, GCS_COMPATTR, NULL, 0);
320 ok(len==alen,"GCS_COMPATTR(A) not returning correct count\n");
322 ImmReleaseContext(hwnd, imc);
325 static void test_ImmSetCompositionString(void)
327 HIMC imc;
328 BOOL ret;
330 SetLastError(0xdeadbeef);
331 imc = ImmGetContext(hwnd);
332 ok(imc != 0, "ImmGetContext() failed. Last error: %u\n", GetLastError());
333 if (!imc)
334 return;
336 ret = ImmSetCompositionStringW(imc, SCS_SETSTR, NULL, 0, NULL, 0);
337 ok(broken(!ret) ||
338 ret, /* Vista+ */
339 "ImmSetCompositionStringW() failed.\n");
341 ret = ImmSetCompositionStringW(imc, SCS_SETSTR | SCS_CHANGEATTR,
342 NULL, 0, NULL, 0);
343 ok(!ret, "ImmSetCompositionStringW() succeeded.\n");
345 ret = ImmSetCompositionStringW(imc, SCS_SETSTR | SCS_CHANGECLAUSE,
346 NULL, 0, NULL, 0);
347 ok(!ret, "ImmSetCompositionStringW() succeeded.\n");
349 ret = ImmSetCompositionStringW(imc, SCS_CHANGEATTR | SCS_CHANGECLAUSE,
350 NULL, 0, NULL, 0);
351 ok(!ret, "ImmSetCompositionStringW() succeeded.\n");
353 ret = ImmSetCompositionStringW(imc, SCS_SETSTR | SCS_CHANGEATTR | SCS_CHANGECLAUSE,
354 NULL, 0, NULL, 0);
355 ok(!ret, "ImmSetCompositionStringW() succeeded.\n");
357 ImmReleaseContext(hwnd, imc);
360 static void test_ImmIME(void)
362 HIMC imc;
364 imc = ImmGetContext(hwnd);
365 if (imc)
367 BOOL rc;
368 rc = ImmConfigureIMEA(imc, NULL, IME_CONFIG_REGISTERWORD, NULL);
369 ok (rc == 0, "ImmConfigureIMEA did not fail\n");
370 rc = ImmConfigureIMEW(imc, NULL, IME_CONFIG_REGISTERWORD, NULL);
371 ok (rc == 0, "ImmConfigureIMEW did not fail\n");
373 ImmReleaseContext(hwnd,imc);
376 static void test_ImmAssociateContextEx(void)
378 HIMC imc;
379 BOOL rc;
381 if (!pImmAssociateContextEx) return;
383 imc = ImmGetContext(hwnd);
384 if (imc)
386 HIMC retimc, newimc;
388 newimc = ImmCreateContext();
389 ok(newimc != imc, "handles should not be the same\n");
390 rc = pImmAssociateContextEx(NULL, NULL, 0);
391 ok(!rc, "ImmAssociateContextEx succeeded\n");
392 rc = pImmAssociateContextEx(hwnd, NULL, 0);
393 ok(rc, "ImmAssociateContextEx failed\n");
394 rc = pImmAssociateContextEx(NULL, imc, 0);
395 ok(!rc, "ImmAssociateContextEx succeeded\n");
397 rc = pImmAssociateContextEx(hwnd, imc, 0);
398 ok(rc, "ImmAssociateContextEx failed\n");
399 retimc = ImmGetContext(hwnd);
400 ok(retimc == imc, "handles should be the same\n");
401 ImmReleaseContext(hwnd,retimc);
403 rc = pImmAssociateContextEx(hwnd, newimc, 0);
404 ok(rc, "ImmAssociateContextEx failed\n");
405 retimc = ImmGetContext(hwnd);
406 ok(retimc == newimc, "handles should be the same\n");
407 ImmReleaseContext(hwnd,retimc);
409 rc = pImmAssociateContextEx(hwnd, NULL, IACE_DEFAULT);
410 ok(rc, "ImmAssociateContextEx failed\n");
412 ImmReleaseContext(hwnd,imc);
415 typedef struct _igc_threadinfo {
416 HWND hwnd;
417 HANDLE event;
418 HIMC himc;
419 } igc_threadinfo;
422 static DWORD WINAPI ImmGetContextThreadFunc( LPVOID lpParam)
424 HIMC h1,h2;
425 HWND hwnd2;
426 COMPOSITIONFORM cf;
427 POINT pt;
428 igc_threadinfo *info= (igc_threadinfo*)lpParam;
429 info->hwnd = CreateWindowExA(WS_EX_CLIENTEDGE, wndcls, "Wine imm32.dll test",
430 WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
431 240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL);
433 h1 = ImmGetContext(hwnd);
434 todo_wine ok(info->himc == h1, "hwnd context changed in new thread\n");
435 h2 = ImmGetContext(info->hwnd);
436 todo_wine ok(h2 != h1, "new hwnd in new thread should have different context\n");
437 info->himc = h2;
438 ImmReleaseContext(hwnd,h1);
440 hwnd2 = CreateWindowExA(WS_EX_CLIENTEDGE, wndcls, "Wine imm32.dll test",
441 WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
442 240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL);
443 h1 = ImmGetContext(hwnd2);
445 ok(h1 == h2, "Windows in same thread should have same default context\n");
446 ImmReleaseContext(hwnd2,h1);
447 ImmReleaseContext(info->hwnd,h2);
448 DestroyWindow(hwnd2);
450 /* priming for later tests */
451 ImmSetCompositionWindow(h1, &cf);
452 ImmSetStatusWindowPos(h1, &pt);
454 SetEvent(info->event);
455 Sleep(INFINITE);
456 return 1;
459 static void test_ImmThreads(void)
461 HIMC himc, otherHimc, h1;
462 igc_threadinfo threadinfo;
463 HANDLE hThread;
464 DWORD dwThreadId;
465 BOOL rc;
466 LOGFONTA lf;
467 COMPOSITIONFORM cf;
468 CANDIDATEFORM cdf;
469 DWORD status, sentence;
470 POINT pt;
472 himc = ImmGetContext(hwnd);
473 threadinfo.event = CreateEventA(NULL, TRUE, FALSE, NULL);
474 threadinfo.himc = himc;
475 hThread = CreateThread(NULL, 0, ImmGetContextThreadFunc, &threadinfo, 0, &dwThreadId );
476 WaitForSingleObject(threadinfo.event, INFINITE);
478 otherHimc = ImmGetContext(threadinfo.hwnd);
480 todo_wine ok(himc != otherHimc, "Windows from other threads should have different himc\n");
481 todo_wine ok(otherHimc == threadinfo.himc, "Context from other thread should not change in main thread\n");
483 if (0) /* FIXME: Causes wine to hang */
485 h1 = ImmAssociateContext(hwnd,otherHimc);
486 ok(h1 == NULL, "Should fail to be able to Associate a default context from a different thread\n");
487 h1 = ImmGetContext(hwnd);
488 ok(h1 == himc, "Context for window should remain unchanged\n");
489 ImmReleaseContext(hwnd,h1);
493 /* OpenStatus */
494 rc = ImmSetOpenStatus(himc, TRUE);
495 ok(rc != 0, "ImmSetOpenStatus failed\n");
496 rc = ImmGetOpenStatus(himc);
497 ok(rc != 0, "ImmGetOpenStatus failed\n");
498 rc = ImmSetOpenStatus(himc, FALSE);
499 ok(rc != 0, "ImmSetOpenStatus failed\n");
500 rc = ImmGetOpenStatus(himc);
501 ok(rc == 0, "ImmGetOpenStatus failed\n");
503 rc = ImmSetOpenStatus(otherHimc, TRUE);
504 todo_wine ok(rc == 0, "ImmSetOpenStatus should fail\n");
505 rc = ImmGetOpenStatus(otherHimc);
506 todo_wine ok(rc == 0, "ImmGetOpenStatus failed\n");
507 rc = ImmSetOpenStatus(otherHimc, FALSE);
508 todo_wine ok(rc == 0, "ImmSetOpenStatus should fail\n");
509 rc = ImmGetOpenStatus(otherHimc);
510 ok(rc == 0, "ImmGetOpenStatus failed\n");
512 /* CompositionFont */
513 rc = ImmGetCompositionFontA(himc, &lf);
514 ok(rc != 0, "ImmGetCompositionFont failed\n");
515 rc = ImmSetCompositionFontA(himc, &lf);
516 ok(rc != 0, "ImmSetCompositionFont failed\n");
518 rc = ImmGetCompositionFontA(otherHimc, &lf);
519 ok(rc != 0 || broken(rc == 0), "ImmGetCompositionFont failed\n");
520 rc = ImmSetCompositionFontA(otherHimc, &lf);
521 todo_wine ok(rc == 0, "ImmSetCompositionFont should fail\n");
523 /* CompositionWindow */
524 rc = ImmSetCompositionWindow(himc, &cf);
525 ok(rc != 0, "ImmSetCompositionWindow failed\n");
526 rc = ImmGetCompositionWindow(himc, &cf);
527 ok(rc != 0, "ImmGetCompositionWindow failed\n");
529 rc = ImmSetCompositionWindow(otherHimc, &cf);
530 todo_wine ok(rc == 0, "ImmSetCompositionWindow should fail\n");
531 rc = ImmGetCompositionWindow(otherHimc, &cf);
532 ok(rc != 0 || broken(rc == 0), "ImmGetCompositionWindow failed\n");
534 /* ConversionStatus */
535 rc = ImmGetConversionStatus(himc, &status, &sentence);
536 ok(rc != 0, "ImmGetConversionStatus failed\n");
537 rc = ImmSetConversionStatus(himc, status, sentence);
538 ok(rc != 0, "ImmSetConversionStatus failed\n");
540 rc = ImmGetConversionStatus(otherHimc, &status, &sentence);
541 ok(rc != 0 || broken(rc == 0), "ImmGetConversionStatus failed\n");
542 rc = ImmSetConversionStatus(otherHimc, status, sentence);
543 todo_wine ok(rc == 0, "ImmSetConversionStatus should fail\n");
545 /* StatusWindowPos */
546 rc = ImmSetStatusWindowPos(himc, &pt);
547 ok(rc != 0, "ImmSetStatusWindowPos failed\n");
548 rc = ImmGetStatusWindowPos(himc, &pt);
549 ok(rc != 0, "ImmGetStatusWindowPos failed\n");
551 rc = ImmSetStatusWindowPos(otherHimc, &pt);
552 todo_wine ok(rc == 0, "ImmSetStatusWindowPos should fail\n");
553 rc = ImmGetStatusWindowPos(otherHimc, &pt);
554 ok(rc != 0 || broken(rc == 0), "ImmGetStatusWindowPos failed\n");
556 /* Candidate Window */
557 rc = ImmGetCandidateWindow(himc, 0, &cdf);
558 ok (rc == 0, "ImmGetCandidateWindow should fail\n");
559 cdf.dwIndex = 0;
560 cdf.dwStyle = CFS_CANDIDATEPOS;
561 cdf.ptCurrentPos.x = 0;
562 cdf.ptCurrentPos.y = 0;
563 rc = ImmSetCandidateWindow(himc, &cdf);
564 ok (rc == 1, "ImmSetCandidateWindow should succeed\n");
565 rc = ImmGetCandidateWindow(himc, 0, &cdf);
566 ok (rc == 1, "ImmGetCandidateWindow should succeed\n");
568 rc = ImmGetCandidateWindow(otherHimc, 0, &cdf);
569 todo_wine ok (rc == 0, "ImmGetCandidateWindow should fail\n");
570 rc = ImmSetCandidateWindow(otherHimc, &cdf);
571 todo_wine ok (rc == 0, "ImmSetCandidateWindow should fail\n");
573 ImmReleaseContext(threadinfo.hwnd,otherHimc);
574 ImmReleaseContext(hwnd,himc);
576 DestroyWindow(threadinfo.hwnd);
577 TerminateThread(hThread, 1);
579 himc = ImmGetContext(GetDesktopWindow());
580 todo_wine ok(himc == NULL, "Should not be able to get himc from other process window\n");
583 static void test_ImmIsUIMessage(void)
585 struct test
587 UINT msg;
588 BOOL ret;
591 static const struct test tests[] =
593 { WM_MOUSEMOVE, FALSE },
594 { WM_IME_STARTCOMPOSITION, TRUE },
595 { WM_IME_ENDCOMPOSITION, TRUE },
596 { WM_IME_COMPOSITION, TRUE },
597 { WM_IME_SETCONTEXT, TRUE },
598 { WM_IME_NOTIFY, TRUE },
599 { WM_IME_CONTROL, FALSE },
600 { WM_IME_COMPOSITIONFULL, TRUE },
601 { WM_IME_SELECT, TRUE },
602 { WM_IME_CHAR, FALSE },
603 { 0x287 /* FIXME */, TRUE },
604 { WM_IME_REQUEST, FALSE },
605 { WM_IME_KEYDOWN, FALSE },
606 { WM_IME_KEYUP, FALSE },
607 { 0, FALSE } /* mark the end */
610 UINT WM_MSIME_SERVICE = RegisterWindowMessageA("MSIMEService");
611 UINT WM_MSIME_RECONVERTOPTIONS = RegisterWindowMessageA("MSIMEReconvertOptions");
612 UINT WM_MSIME_MOUSE = RegisterWindowMessageA("MSIMEMouseOperation");
613 UINT WM_MSIME_RECONVERTREQUEST = RegisterWindowMessageA("MSIMEReconvertRequest");
614 UINT WM_MSIME_RECONVERT = RegisterWindowMessageA("MSIMEReconvert");
615 UINT WM_MSIME_QUERYPOSITION = RegisterWindowMessageA("MSIMEQueryPosition");
616 UINT WM_MSIME_DOCUMENTFEED = RegisterWindowMessageA("MSIMEDocumentFeed");
618 const struct test *test;
619 BOOL ret;
621 if (!pImmIsUIMessageA) return;
623 for (test = tests; test->msg; test++)
625 msg_spy_flush_msgs();
626 ret = pImmIsUIMessageA(NULL, test->msg, 0, 0);
627 ok(ret == test->ret, "ImmIsUIMessageA returned %x for %x\n", ret, test->msg);
628 ok(!msg_spy_find_msg(test->msg), "Windows does not send 0x%x for NULL hwnd\n", test->msg);
630 ret = pImmIsUIMessageA(hwnd, test->msg, 0, 0);
631 ok(ret == test->ret, "ImmIsUIMessageA returned %x for %x\n", ret, test->msg);
632 if (ret)
633 ok(msg_spy_find_msg(test->msg) != NULL, "Windows does send 0x%x\n", test->msg);
634 else
635 ok(!msg_spy_find_msg(test->msg), "Windows does not send 0x%x\n", test->msg);
638 ret = pImmIsUIMessageA(NULL, WM_MSIME_SERVICE, 0, 0);
639 ok(!ret, "ImmIsUIMessageA returned TRUE for WM_MSIME_SERVICE\n");
640 ret = pImmIsUIMessageA(NULL, WM_MSIME_RECONVERTOPTIONS, 0, 0);
641 ok(!ret, "ImmIsUIMessageA returned TRUE for WM_MSIME_RECONVERTOPTIONS\n");
642 ret = pImmIsUIMessageA(NULL, WM_MSIME_MOUSE, 0, 0);
643 ok(!ret, "ImmIsUIMessageA returned TRUE for WM_MSIME_MOUSE\n");
644 ret = pImmIsUIMessageA(NULL, WM_MSIME_RECONVERTREQUEST, 0, 0);
645 ok(!ret, "ImmIsUIMessageA returned TRUE for WM_MSIME_RECONVERTREQUEST\n");
646 ret = pImmIsUIMessageA(NULL, WM_MSIME_RECONVERT, 0, 0);
647 ok(!ret, "ImmIsUIMessageA returned TRUE for WM_MSIME_RECONVERT\n");
648 ret = pImmIsUIMessageA(NULL, WM_MSIME_QUERYPOSITION, 0, 0);
649 ok(!ret, "ImmIsUIMessageA returned TRUE for WM_MSIME_QUERYPOSITION\n");
650 ret = pImmIsUIMessageA(NULL, WM_MSIME_DOCUMENTFEED, 0, 0);
651 ok(!ret, "ImmIsUIMessageA returned TRUE for WM_MSIME_DOCUMENTFEED\n");
654 static void test_ImmGetContext(void)
656 HIMC himc;
657 DWORD err;
659 SetLastError(0xdeadbeef);
660 himc = ImmGetContext((HWND)0xffffffff);
661 err = GetLastError();
662 ok(himc == NULL, "ImmGetContext succeeded\n");
663 ok(err == ERROR_INVALID_WINDOW_HANDLE, "got %u\n", err);
665 himc = ImmGetContext(hwnd);
666 ok(himc != NULL, "ImmGetContext failed\n");
667 ok(ImmReleaseContext(hwnd, himc), "ImmReleaseContext failed\n");
670 static void test_ImmGetDescription(void)
672 HKL hkl;
673 WCHAR descW[100];
674 CHAR descA[100];
675 UINT ret, lret;
677 /* FIXME: invalid keyboard layouts should not pass */
678 ret = ImmGetDescriptionW(NULL, NULL, 0);
679 ok(!ret, "ImmGetDescriptionW failed, expected 0 received %d.\n", ret);
680 ret = ImmGetDescriptionA(NULL, NULL, 0);
681 ok(!ret, "ImmGetDescriptionA failed, expected 0 received %d.\n", ret);
683 /* load a language with valid IMM descriptions */
684 hkl = GetKeyboardLayout(0);
685 ok(hkl != 0, "GetKeyboardLayout failed, expected != 0.\n");
687 ret = ImmGetDescriptionW(hkl, NULL, 0);
688 if(!ret)
690 win_skip("ImmGetDescriptionW is not working for current loaded keyboard.\n");
691 return;
694 SetLastError(0xdeadcafe);
695 ret = ImmGetDescriptionW(0, NULL, 100);
696 ok (ret == 0, "ImmGetDescriptionW with 0 hkl should return 0\n");
697 ret = GetLastError();
698 ok (ret == 0xdeadcafe, "Last Error should remain unchanged\n");
700 ret = ImmGetDescriptionW(hkl, descW, 0);
701 ok(ret, "ImmGetDescriptionW failed, expected != 0 received 0.\n");
703 lret = ImmGetDescriptionW(hkl, descW, ret + 1);
704 ok(lret, "ImmGetDescriptionW failed, expected != 0 received 0.\n");
705 ok(lret == ret, "ImmGetDescriptionW failed to return the correct amount of data. Expected %d, got %d.\n", ret, lret);
707 lret = ImmGetDescriptionA(hkl, descA, ret + 1);
708 ok(lret, "ImmGetDescriptionA failed, expected != 0 received 0.\n");
709 ok(lret == ret, "ImmGetDescriptionA failed to return the correct amount of data. Expected %d, got %d.\n", ret, lret);
711 ret /= 2; /* try to copy partially */
712 lret = ImmGetDescriptionW(hkl, descW, ret + 1);
713 ok(lret, "ImmGetDescriptionW failed, expected != 0 received 0.\n");
714 ok(lret == ret, "ImmGetDescriptionW failed to return the correct amount of data. Expected %d, got %d.\n", ret, lret);
716 lret = ImmGetDescriptionA(hkl, descA, ret + 1);
717 ok(!lret, "ImmGetDescriptionA should fail\n");
719 ret = ImmGetDescriptionW(hkl, descW, 1);
720 ok(!ret, "ImmGetDescriptionW failed, expected 0 received %d.\n", ret);
722 UnloadKeyboardLayout(hkl);
725 static void test_ImmDefaultHwnd(void)
727 HIMC imc1, imc2, imc3;
728 HWND def1, def3;
729 HWND hwnd;
731 hwnd = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "Wine imm32.dll test",
732 WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
733 240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL);
735 ShowWindow(hwnd, SW_SHOWNORMAL);
737 imc1 = ImmGetContext(hwnd);
738 if (!imc1)
740 win_skip("IME support not implemented\n");
741 return;
744 def1 = ImmGetDefaultIMEWnd(hwnd);
746 imc2 = ImmCreateContext();
747 ImmSetOpenStatus(imc2, TRUE);
749 imc3 = ImmGetContext(hwnd);
750 def3 = ImmGetDefaultIMEWnd(hwnd);
752 ok(def3 == def1, "Default IME window should not change\n");
753 ok(imc1 == imc3, "IME context should not change\n");
754 ImmSetOpenStatus(imc2, FALSE);
756 ImmReleaseContext(hwnd, imc1);
757 ImmReleaseContext(hwnd, imc3);
758 ImmDestroyContext(imc2);
759 DestroyWindow(hwnd);
762 static void test_ImmGetIMCLockCount(void)
764 HIMC imc;
765 DWORD count, ret, i;
766 INPUTCONTEXT *ic;
768 imc = ImmCreateContext();
769 ImmDestroyContext(imc);
770 SetLastError(0xdeadbeef);
771 count = ImmGetIMCLockCount((HIMC)0xdeadcafe);
772 ok(count == 0, "Invalid IMC should return 0\n");
773 ret = GetLastError();
774 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
775 SetLastError(0xdeadbeef);
776 count = ImmGetIMCLockCount(0x00000000);
777 ok(count == 0, "NULL IMC should return 0\n");
778 ret = GetLastError();
779 ok(ret == 0xdeadbeef, "Last Error should remain unchanged: %08x\n",ret);
780 count = ImmGetIMCLockCount(imc);
781 ok(count == 0, "Destroyed IMC should return 0\n");
782 ret = GetLastError();
783 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
785 imc = ImmCreateContext();
786 count = ImmGetIMCLockCount(imc);
787 ok(count == 0, "expect 0, returned %d\n", count);
788 ic = ImmLockIMC(imc);
789 ok(ic != NULL, "ImmLockIMC failed!\n");
790 count = ImmGetIMCLockCount(imc);
791 ok(count == 1, "expect 1, returned %d\n", count);
792 ret = ImmUnlockIMC(imc);
793 ok(ret == TRUE, "expect TRUE, ret %d\n", ret);
794 count = ImmGetIMCLockCount(imc);
795 ok(count == 0, "expect 0, returned %d\n", count);
796 ret = ImmUnlockIMC(imc);
797 ok(ret == TRUE, "expect TRUE, ret %d\n", ret);
798 count = ImmGetIMCLockCount(imc);
799 ok(count == 0, "expect 0, returned %d\n", count);
801 for (i = 0; i < GMEM_LOCKCOUNT * 2; i++)
803 ic = ImmLockIMC(imc);
804 ok(ic != NULL, "ImmLockIMC failed!\n");
806 count = ImmGetIMCLockCount(imc);
807 todo_wine ok(count == GMEM_LOCKCOUNT, "expect GMEM_LOCKCOUNT, returned %d\n", count);
809 for (i = 0; i < GMEM_LOCKCOUNT - 1; i++)
810 ImmUnlockIMC(imc);
811 count = ImmGetIMCLockCount(imc);
812 todo_wine ok(count == 1, "expect 1, returned %d\n", count);
813 ImmUnlockIMC(imc);
814 count = ImmGetIMCLockCount(imc);
815 todo_wine ok(count == 0, "expect 0, returned %d\n", count);
817 ImmDestroyContext(imc);
820 static void test_ImmGetIMCCLockCount(void)
822 HIMCC imcc;
823 DWORD count, g_count, i;
824 BOOL ret;
825 VOID *p;
827 imcc = ImmCreateIMCC(sizeof(CANDIDATEINFO));
828 count = ImmGetIMCCLockCount(imcc);
829 ok(count == 0, "expect 0, returned %d\n", count);
830 ImmLockIMCC(imcc);
831 count = ImmGetIMCCLockCount(imcc);
832 ok(count == 1, "expect 1, returned %d\n", count);
833 ret = ImmUnlockIMCC(imcc);
834 ok(ret == FALSE, "expect FALSE, ret %d\n", ret);
835 count = ImmGetIMCCLockCount(imcc);
836 ok(count == 0, "expect 0, returned %d\n", count);
837 ret = ImmUnlockIMCC(imcc);
838 ok(ret == FALSE, "expect FALSE, ret %d\n", ret);
839 count = ImmGetIMCCLockCount(imcc);
840 ok(count == 0, "expect 0, returned %d\n", count);
842 p = ImmLockIMCC(imcc);
843 ok(GlobalHandle(p) == imcc, "expect %p, returned %p\n", imcc, GlobalHandle(p));
845 for (i = 0; i < GMEM_LOCKCOUNT * 2; i++)
847 ImmLockIMCC(imcc);
848 count = ImmGetIMCCLockCount(imcc);
849 g_count = GlobalFlags(imcc) & GMEM_LOCKCOUNT;
850 ok(count == g_count, "count %d, g_count %d\n", count, g_count);
852 count = ImmGetIMCCLockCount(imcc);
853 ok(count == GMEM_LOCKCOUNT, "expect GMEM_LOCKCOUNT, returned %d\n", count);
855 for (i = 0; i < GMEM_LOCKCOUNT - 1; i++)
856 GlobalUnlock(imcc);
857 count = ImmGetIMCCLockCount(imcc);
858 ok(count == 1, "expect 1, returned %d\n", count);
859 GlobalUnlock(imcc);
860 count = ImmGetIMCCLockCount(imcc);
861 ok(count == 0, "expect 0, returned %d\n", count);
863 ImmDestroyIMCC(imcc);
866 static void test_ImmDestroyContext(void)
868 HIMC imc;
869 DWORD ret, count;
870 INPUTCONTEXT *ic;
872 imc = ImmCreateContext();
873 count = ImmGetIMCLockCount(imc);
874 ok(count == 0, "expect 0, returned %d\n", count);
875 ic = ImmLockIMC(imc);
876 ok(ic != NULL, "ImmLockIMC failed!\n");
877 count = ImmGetIMCLockCount(imc);
878 ok(count == 1, "expect 1, returned %d\n", count);
879 ret = ImmDestroyContext(imc);
880 ok(ret == TRUE, "Destroy a locked IMC should success!\n");
881 ic = ImmLockIMC(imc);
882 ok(ic == NULL, "Lock a destroyed IMC should fail!\n");
883 ret = ImmUnlockIMC(imc);
884 ok(ret == FALSE, "Unlock a destroyed IMC should fail!\n");
885 count = ImmGetIMCLockCount(imc);
886 ok(count == 0, "Get lock count of a destroyed IMC should return 0!\n");
887 SetLastError(0xdeadbeef);
888 ret = ImmDestroyContext(imc);
889 ok(ret == FALSE, "Destroy a destroyed IMC should fail!\n");
890 ret = GetLastError();
891 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
894 static void test_ImmDestroyIMCC(void)
896 HIMCC imcc;
897 DWORD ret, count, size;
898 VOID *p;
900 imcc = ImmCreateIMCC(sizeof(CANDIDATEINFO));
901 count = ImmGetIMCCLockCount(imcc);
902 ok(count == 0, "expect 0, returned %d\n", count);
903 p = ImmLockIMCC(imcc);
904 ok(p != NULL, "ImmLockIMCC failed!\n");
905 count = ImmGetIMCCLockCount(imcc);
906 ok(count == 1, "expect 1, returned %d\n", count);
907 size = ImmGetIMCCSize(imcc);
908 ok(size == sizeof(CANDIDATEINFO), "returned %d\n", size);
909 p = ImmDestroyIMCC(imcc);
910 ok(p == NULL, "Destroy a locked IMCC should success!\n");
911 p = ImmLockIMCC(imcc);
912 ok(p == NULL, "Lock a destroyed IMCC should fail!\n");
913 ret = ImmUnlockIMCC(imcc);
914 ok(ret == FALSE, "Unlock a destroyed IMCC should return FALSE!\n");
915 count = ImmGetIMCCLockCount(imcc);
916 ok(count == 0, "Get lock count of a destroyed IMCC should return 0!\n");
917 size = ImmGetIMCCSize(imcc);
918 ok(size == 0, "Get size of a destroyed IMCC should return 0!\n");
919 SetLastError(0xdeadbeef);
920 p = ImmDestroyIMCC(imcc);
921 ok(p != NULL, "returned NULL\n");
922 ret = GetLastError();
923 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
926 static void test_ImmMessages(void)
928 CANDIDATEFORM cf;
929 imm_msgs *msg;
930 HWND defwnd;
931 HIMC imc;
932 UINT idx = 0;
934 HWND hwnd = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "Wine imm32.dll test",
935 WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
936 240, 120, NULL, NULL, GetModuleHandleA(NULL), NULL);
938 ShowWindow(hwnd, SW_SHOWNORMAL);
939 defwnd = ImmGetDefaultIMEWnd(hwnd);
940 imc = ImmGetContext(hwnd);
942 ImmSetOpenStatus(imc, TRUE);
943 msg_spy_flush_msgs();
944 SendMessageA(defwnd, WM_IME_CONTROL, IMC_GETCANDIDATEPOS, (LPARAM)&cf );
947 msg = msg_spy_find_next_msg(WM_IME_CONTROL,&idx);
948 if (msg) ok(!msg->post, "Message should not be posted\n");
949 } while (msg);
950 msg_spy_flush_msgs();
951 ImmSetOpenStatus(imc, FALSE);
952 ImmReleaseContext(hwnd, imc);
953 DestroyWindow(hwnd);
956 static LRESULT CALLBACK processkey_wnd_proc( HWND hWnd, UINT msg, WPARAM wParam,
957 LPARAM lParam )
959 return DefWindowProcW(hWnd, msg, wParam, lParam);
962 static void test_ime_processkey(void)
964 WCHAR classNameW[] = {'P','r','o','c','e','s','s', 'K','e','y','T','e','s','t','C','l','a','s','s',0};
965 WCHAR windowNameW[] = {'P','r','o','c','e','s','s', 'K','e','y',0};
967 MSG msg;
968 WNDCLASSW wclass;
969 HANDLE hInstance = GetModuleHandleW(NULL);
970 TEST_INPUT inputs[2];
971 HIMC imc;
972 INT rc;
973 HWND hWndTest;
975 wclass.lpszClassName = classNameW;
976 wclass.style = CS_HREDRAW | CS_VREDRAW;
977 wclass.lpfnWndProc = processkey_wnd_proc;
978 wclass.hInstance = hInstance;
979 wclass.hIcon = LoadIconW(0, (LPCWSTR)IDI_APPLICATION);
980 wclass.hCursor = LoadCursorW( NULL, (LPCWSTR)IDC_ARROW);
981 wclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
982 wclass.lpszMenuName = 0;
983 wclass.cbClsExtra = 0;
984 wclass.cbWndExtra = 0;
985 if(!RegisterClassW(&wclass)){
986 win_skip("Failed to register window.\n");
987 return;
990 /* create the test window that will receive the keystrokes */
991 hWndTest = CreateWindowW(wclass.lpszClassName, windowNameW,
992 WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 100, 100,
993 NULL, NULL, hInstance, NULL);
995 ShowWindow(hWndTest, SW_SHOW);
996 SetWindowPos(hWndTest, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
997 SetForegroundWindow(hWndTest);
998 UpdateWindow(hWndTest);
1000 imc = ImmGetContext(hWndTest);
1001 if (!imc)
1003 win_skip("IME not supported\n");
1004 DestroyWindow(hWndTest);
1005 return;
1008 rc = ImmSetOpenStatus(imc, TRUE);
1009 if (rc != TRUE)
1011 win_skip("Unable to open IME\n");
1012 ImmReleaseContext(hWndTest, imc);
1013 DestroyWindow(hWndTest);
1014 return;
1017 /* flush pending messages */
1018 while (PeekMessageW(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageW(&msg);
1020 SetFocus(hWndTest);
1022 /* init input data that never changes */
1023 inputs[1].type = inputs[0].type = INPUT_KEYBOARD;
1024 inputs[1].u.ki.dwExtraInfo = inputs[0].u.ki.dwExtraInfo = 0;
1025 inputs[1].u.ki.time = inputs[0].u.ki.time = 0;
1027 /* Pressing a key */
1028 inputs[0].u.ki.wVk = 0x41;
1029 inputs[0].u.ki.wScan = 0x1e;
1030 inputs[0].u.ki.dwFlags = 0x0;
1032 pSendInput(1, (INPUT*)inputs, sizeof(INPUT));
1034 while(PeekMessageW(&msg, hWndTest, 0, 0, PM_NOREMOVE)) {
1035 if(msg.message != WM_KEYDOWN)
1036 PeekMessageW(&msg, hWndTest, 0, 0, PM_REMOVE);
1037 else
1039 ok(msg.wParam != VK_PROCESSKEY,"Incorrect ProcessKey Found\n");
1040 PeekMessageW(&msg, hWndTest, 0, 0, PM_REMOVE);
1041 if(msg.wParam == VK_PROCESSKEY)
1042 trace("ProcessKey was correctly found\n");
1044 TranslateMessage(&msg);
1045 DispatchMessageW(&msg);
1048 inputs[0].u.ki.wVk = 0x41;
1049 inputs[0].u.ki.wScan = 0x1e;
1050 inputs[0].u.ki.dwFlags = KEYEVENTF_KEYUP;
1052 pSendInput(1, (INPUT*)inputs, sizeof(INPUT));
1054 while(PeekMessageW(&msg, hWndTest, 0, 0, PM_NOREMOVE)) {
1055 if(msg.message != WM_KEYUP)
1056 PeekMessageW(&msg, hWndTest, 0, 0, PM_REMOVE);
1057 else
1059 ok(msg.wParam != VK_PROCESSKEY,"Incorrect ProcessKey Found\n");
1060 PeekMessageW(&msg, hWndTest, 0, 0, PM_REMOVE);
1061 ok(msg.wParam != VK_PROCESSKEY,"ProcessKey should still not be Found\n");
1063 TranslateMessage(&msg);
1064 DispatchMessageW(&msg);
1067 ImmReleaseContext(hWndTest, imc);
1068 ImmSetOpenStatus(imc, FALSE);
1069 DestroyWindow(hWndTest);
1072 static void test_InvalidIMC(void)
1074 HIMC imc_destroy;
1075 HIMC imc_null = 0x00000000;
1076 HIMC imc_bad = (HIMC)0xdeadcafe;
1078 HIMC imc1, imc2, oldimc;
1079 DWORD ret;
1080 DWORD count;
1081 CHAR buffer[1000];
1082 INPUTCONTEXT *ic;
1083 LOGFONTA lf;
1085 memset(&lf, 0, sizeof(lf));
1087 imc_destroy = ImmCreateContext();
1088 ret = ImmDestroyContext(imc_destroy);
1089 ok(ret == TRUE, "Destroy an IMC should success!\n");
1091 /* Test associating destroyed imc */
1092 imc1 = ImmGetContext(hwnd);
1093 SetLastError(0xdeadbeef);
1094 oldimc = ImmAssociateContext(hwnd, imc_destroy);
1095 ok(!oldimc, "Associating to a destroyed imc should fail!\n");
1096 ret = GetLastError();
1097 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1098 imc2 = ImmGetContext(hwnd);
1099 ok(imc1 == imc2, "imc should not changed! imc1 %p, imc2 %p\n", imc1, imc2);
1101 /* Test associating NULL imc, which is different from an invalid imc */
1102 oldimc = ImmAssociateContext(hwnd, imc_null);
1103 ok(oldimc != NULL, "Associating to NULL imc should success!\n");
1104 imc2 = ImmGetContext(hwnd);
1105 ok(!imc2, "expect NULL, returned %p\n", imc2);
1106 oldimc = ImmAssociateContext(hwnd, imc1);
1107 ok(!oldimc, "expect NULL, returned %p\n", oldimc);
1108 imc2 = ImmGetContext(hwnd);
1109 ok(imc2 == imc1, "imc should not changed! imc2 %p, imc1 %p\n", imc2, imc1);
1111 /* Test associating invalid imc */
1112 imc1 = ImmGetContext(hwnd);
1113 SetLastError(0xdeadbeef);
1114 oldimc = ImmAssociateContext(hwnd, imc_bad);
1115 ok(!oldimc, "Associating to a destroyed imc should fail!\n");
1116 ret = GetLastError();
1117 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1118 imc2 = ImmGetContext(hwnd);
1119 ok(imc1 == imc2, "imc should not changed! imc1 %p, imc2 %p\n", imc1, imc2);
1122 /* Test ImmGetCandidateListA */
1123 SetLastError(0xdeadbeef);
1124 ret = ImmGetCandidateListA(imc_bad, 0, NULL, 0);
1125 ok(ret == 0, "Bad IME should return 0\n");
1126 ret = GetLastError();
1127 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1128 SetLastError(0xdeadbeef);
1129 ret = ImmGetCandidateListA(imc_null, 0, NULL, 0);
1130 ok(ret == 0, "NULL IME should return 0\n");
1131 ret = GetLastError();
1132 ok(ret == 0xdeadbeef, "last error should remain unchanged %08x!\n", ret);
1133 SetLastError(0xdeadbeef);
1134 ret = ImmGetCandidateListA(imc_destroy, 0, NULL, 0);
1135 ok(ret == 0, "Destroyed IME should return 0\n");
1136 ret = GetLastError();
1137 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1139 /* Test ImmGetCandidateListCountA*/
1140 SetLastError(0xdeadbeef);
1141 ret = ImmGetCandidateListCountA(imc_bad,&count);
1142 ok(ret == 0, "Bad IME should return 0\n");
1143 ret = GetLastError();
1144 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1145 SetLastError(0xdeadbeef);
1146 ret = ImmGetCandidateListCountA(imc_null,&count);
1147 ok(ret == 0, "NULL IME should return 0\n");
1148 ret = GetLastError();
1149 ok(ret == 0xdeadbeef, "last error should remain unchanged %08x!\n", ret);
1150 SetLastError(0xdeadbeef);
1151 ret = ImmGetCandidateListCountA(imc_destroy,&count);
1152 ok(ret == 0, "Destroyed IME should return 0\n");
1153 ret = GetLastError();
1154 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1156 /* Test ImmGetCandidateWindow */
1157 SetLastError(0xdeadbeef);
1158 ret = ImmGetCandidateWindow(imc_bad, 0, (LPCANDIDATEFORM)buffer);
1159 ok(ret == 0, "Bad IME should return 0\n");
1160 ret = GetLastError();
1161 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1162 SetLastError(0xdeadbeef);
1163 ret = ImmGetCandidateWindow(imc_null, 0, (LPCANDIDATEFORM)buffer);
1164 ok(ret == 0, "NULL IME should return 0\n");
1165 ret = GetLastError();
1166 ok(ret == 0xdeadbeef, "last error should remain unchanged %08x!\n", ret);
1167 SetLastError(0xdeadbeef);
1168 ret = ImmGetCandidateWindow(imc_destroy, 0, (LPCANDIDATEFORM)buffer);
1169 ok(ret == 0, "Destroyed IME should return 0\n");
1170 ret = GetLastError();
1171 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1173 /* Test ImmGetCompositionFontA */
1174 SetLastError(0xdeadbeef);
1175 ret = ImmGetCompositionFontA(imc_bad, (LPLOGFONTA)buffer);
1176 ok(ret == 0, "Bad IME should return 0\n");
1177 ret = GetLastError();
1178 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1179 SetLastError(0xdeadbeef);
1180 ret = ImmGetCompositionFontA(imc_null, (LPLOGFONTA)buffer);
1181 ok(ret == 0, "NULL IME should return 0\n");
1182 ret = GetLastError();
1183 ok(ret == 0xdeadbeef, "last error should remain unchanged %08x!\n", ret);
1184 SetLastError(0xdeadbeef);
1185 ret = ImmGetCompositionFontA(imc_destroy, (LPLOGFONTA)buffer);
1186 ok(ret == 0, "Destroyed IME should return 0\n");
1187 ret = GetLastError();
1188 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1190 /* Test ImmGetCompositionWindow */
1191 SetLastError(0xdeadbeef);
1192 ret = ImmGetCompositionWindow(imc_bad, (LPCOMPOSITIONFORM)buffer);
1193 ok(ret == 0, "Bad IME should return 0\n");
1194 ret = GetLastError();
1195 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1196 SetLastError(0xdeadbeef);
1197 ret = ImmGetCompositionWindow(imc_null, (LPCOMPOSITIONFORM)buffer);
1198 ok(ret == 0, "NULL IME should return 0\n");
1199 ret = GetLastError();
1200 ok(ret == 0xdeadbeef, "last error should remain unchanged %08x!\n", ret);
1201 SetLastError(0xdeadbeef);
1202 ret = ImmGetCompositionWindow(imc_destroy, (LPCOMPOSITIONFORM)buffer);
1203 ok(ret == 0, "Destroyed IME should return 0\n");
1204 ret = GetLastError();
1205 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1207 /* Test ImmGetCompositionStringA */
1208 SetLastError(0xdeadbeef);
1209 ret = ImmGetCompositionStringA(imc_bad, GCS_COMPSTR, NULL, 0);
1210 ok(ret == 0, "Bad IME should return 0\n");
1211 ret = GetLastError();
1212 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1213 SetLastError(0xdeadbeef);
1214 ret = ImmGetCompositionStringA(imc_null, GCS_COMPSTR, NULL, 0);
1215 ok(ret == 0, "NULL IME should return 0\n");
1216 ret = GetLastError();
1217 ok(ret == 0xdeadbeef, "last error should remain unchanged %08x!\n", ret);
1218 SetLastError(0xdeadbeef);
1219 ret = ImmGetCompositionStringA(imc_destroy, GCS_COMPSTR, NULL, 0);
1220 ok(ret == 0, "Destroyed IME should return 0\n");
1221 ret = GetLastError();
1222 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1224 /* Test ImmSetOpenStatus */
1225 SetLastError(0xdeadbeef);
1226 ret = ImmSetOpenStatus(imc_bad, 1);
1227 ok(ret == 0, "Bad IME should return 0\n");
1228 ret = GetLastError();
1229 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1230 SetLastError(0xdeadbeef);
1231 ret = ImmSetOpenStatus(imc_null, 1);
1232 ok(ret == 0, "NULL IME should return 0\n");
1233 ret = GetLastError();
1234 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1235 SetLastError(0xdeadbeef);
1236 ret = ImmSetOpenStatus(imc_destroy, 1);
1237 ok(ret == 0, "Destroyed IME should return 0\n");
1238 ret = GetLastError();
1239 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1241 /* Test ImmGetOpenStatus */
1242 SetLastError(0xdeadbeef);
1243 ret = ImmGetOpenStatus(imc_bad);
1244 ok(ret == 0, "Bad IME should return 0\n");
1245 ret = GetLastError();
1246 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1247 SetLastError(0xdeadbeef);
1248 ret = ImmGetOpenStatus(imc_null);
1249 ok(ret == 0, "NULL IME should return 0\n");
1250 ret = GetLastError();
1251 ok(ret == 0xdeadbeef, "last error should remain unchanged %08x!\n", ret);
1252 SetLastError(0xdeadbeef);
1253 ret = ImmGetOpenStatus(imc_destroy);
1254 ok(ret == 0, "Destroyed IME should return 0\n");
1255 ret = GetLastError();
1256 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1258 /* Test ImmGetStatusWindowPos */
1259 SetLastError(0xdeadbeef);
1260 ret = ImmGetStatusWindowPos(imc_bad, NULL);
1261 ok(ret == 0, "Bad IME should return 0\n");
1262 ret = GetLastError();
1263 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1264 SetLastError(0xdeadbeef);
1265 ret = ImmGetStatusWindowPos(imc_null, NULL);
1266 ok(ret == 0, "NULL IME should return 0\n");
1267 ret = GetLastError();
1268 ok(ret == 0xdeadbeef, "last error should remain unchanged %08x!\n", ret);
1269 SetLastError(0xdeadbeef);
1270 ret = ImmGetStatusWindowPos(imc_destroy, NULL);
1271 ok(ret == 0, "Destroyed IME should return 0\n");
1272 ret = GetLastError();
1273 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1275 /* Test ImmRequestMessageA */
1276 SetLastError(0xdeadbeef);
1277 ret = ImmRequestMessageA(imc_bad, WM_CHAR, 0);
1278 ok(ret == 0, "Bad IME should return 0\n");
1279 ret = GetLastError();
1280 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1281 SetLastError(0xdeadbeef);
1282 ret = ImmRequestMessageA(imc_null, WM_CHAR, 0);
1283 ok(ret == 0, "NULL IME should return 0\n");
1284 ret = GetLastError();
1285 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1286 SetLastError(0xdeadbeef);
1287 ret = ImmRequestMessageA(imc_destroy, WM_CHAR, 0);
1288 ok(ret == 0, "Destroyed IME should return 0\n");
1289 ret = GetLastError();
1290 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1292 /* Test ImmSetCompositionFontA */
1293 SetLastError(0xdeadbeef);
1294 ret = ImmSetCompositionFontA(imc_bad, &lf);
1295 ok(ret == 0, "Bad IME should return 0\n");
1296 ret = GetLastError();
1297 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1298 SetLastError(0xdeadbeef);
1299 ret = ImmSetCompositionFontA(imc_null, &lf);
1300 ok(ret == 0, "NULL IME should return 0\n");
1301 ret = GetLastError();
1302 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1303 SetLastError(0xdeadbeef);
1304 ret = ImmSetCompositionFontA(imc_destroy, &lf);
1305 ok(ret == 0, "Destroyed IME should return 0\n");
1306 ret = GetLastError();
1307 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1309 /* Test ImmSetCompositionWindow */
1310 SetLastError(0xdeadbeef);
1311 ret = ImmSetCompositionWindow(imc_bad, NULL);
1312 ok(ret == 0, "Bad IME should return 0\n");
1313 ret = GetLastError();
1314 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1315 SetLastError(0xdeadbeef);
1316 ret = ImmSetCompositionWindow(imc_null, NULL);
1317 ok(ret == 0, "NULL IME should return 0\n");
1318 ret = GetLastError();
1319 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1320 SetLastError(0xdeadbeef);
1321 ret = ImmSetCompositionWindow(imc_destroy, NULL);
1322 ok(ret == 0, "Destroyed IME should return 0\n");
1323 ret = GetLastError();
1324 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1326 /* Test ImmSetConversionStatus */
1327 SetLastError(0xdeadbeef);
1328 ret = ImmSetConversionStatus(imc_bad, 0, 0);
1329 ok(ret == 0, "Bad IME should return 0\n");
1330 ret = GetLastError();
1331 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1332 SetLastError(0xdeadbeef);
1333 ret = ImmSetConversionStatus(imc_null, 0, 0);
1334 ok(ret == 0, "NULL IME should return 0\n");
1335 ret = GetLastError();
1336 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1337 SetLastError(0xdeadbeef);
1338 ret = ImmSetConversionStatus(imc_destroy, 0, 0);
1339 ok(ret == 0, "Destroyed IME should return 0\n");
1340 ret = GetLastError();
1341 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1343 /* Test ImmSetStatusWindowPos */
1344 SetLastError(0xdeadbeef);
1345 ret = ImmSetStatusWindowPos(imc_bad, 0);
1346 ok(ret == 0, "Bad IME should return 0\n");
1347 ret = GetLastError();
1348 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1349 SetLastError(0xdeadbeef);
1350 ret = ImmSetStatusWindowPos(imc_null, 0);
1351 ok(ret == 0, "NULL IME should return 0\n");
1352 ret = GetLastError();
1353 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1354 SetLastError(0xdeadbeef);
1355 ret = ImmSetStatusWindowPos(imc_destroy, 0);
1356 ok(ret == 0, "Destroyed IME should return 0\n");
1357 ret = GetLastError();
1358 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1360 /* Test ImmGetImeMenuItemsA */
1361 SetLastError(0xdeadbeef);
1362 ret = ImmGetImeMenuItemsA(imc_bad, 0, 0, NULL, NULL, 0);
1363 ok(ret == 0, "Bad IME should return 0\n");
1364 ret = GetLastError();
1365 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1366 SetLastError(0xdeadbeef);
1367 ret = ImmGetImeMenuItemsA(imc_null, 0, 0, NULL, NULL, 0);
1368 ok(ret == 0, "NULL IME should return 0\n");
1369 ret = GetLastError();
1370 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1371 SetLastError(0xdeadbeef);
1372 ret = ImmGetImeMenuItemsA(imc_destroy, 0, 0, NULL, NULL, 0);
1373 ok(ret == 0, "Destroyed IME should return 0\n");
1374 ret = GetLastError();
1375 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1377 /* Test ImmLockIMC */
1378 SetLastError(0xdeadbeef);
1379 ic = ImmLockIMC(imc_bad);
1380 ok(ic == 0, "Bad IME should return 0\n");
1381 ret = GetLastError();
1382 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1383 SetLastError(0xdeadbeef);
1384 ic = ImmLockIMC(imc_null);
1385 ok(ic == 0, "NULL IME should return 0\n");
1386 ret = GetLastError();
1387 ok(ret == 0xdeadbeef, "last error should remain unchanged %08x!\n", ret);
1388 SetLastError(0xdeadbeef);
1389 ic = ImmLockIMC(imc_destroy);
1390 ok(ic == 0, "Destroyed IME should return 0\n");
1391 ret = GetLastError();
1392 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1394 /* Test ImmUnlockIMC */
1395 SetLastError(0xdeadbeef);
1396 ret = ImmUnlockIMC(imc_bad);
1397 ok(ret == 0, "Bad IME should return 0\n");
1398 ret = GetLastError();
1399 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1400 SetLastError(0xdeadbeef);
1401 ret = ImmUnlockIMC(imc_null);
1402 ok(ret == 0, "NULL IME should return 0\n");
1403 ret = GetLastError();
1404 ok(ret == 0xdeadbeef, "last error should remain unchanged %08x!\n", ret);
1405 SetLastError(0xdeadbeef);
1406 ret = ImmUnlockIMC(imc_destroy);
1407 ok(ret == 0, "Destroyed IME should return 0\n");
1408 ret = GetLastError();
1409 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1411 /* Test ImmGenerateMessage */
1412 SetLastError(0xdeadbeef);
1413 ret = ImmGenerateMessage(imc_bad);
1414 ok(ret == 0, "Bad IME should return 0\n");
1415 ret = GetLastError();
1416 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1417 SetLastError(0xdeadbeef);
1418 ret = ImmGenerateMessage(imc_null);
1419 ok(ret == 0, "NULL IME should return 0\n");
1420 ret = GetLastError();
1421 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1422 SetLastError(0xdeadbeef);
1423 ret = ImmGenerateMessage(imc_destroy);
1424 ok(ret == 0, "Destroyed IME should return 0\n");
1425 ret = GetLastError();
1426 ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
1429 START_TEST(imm32) {
1430 if (init())
1432 test_ImmNotifyIME();
1433 test_ImmGetCompositionString();
1434 test_ImmSetCompositionString();
1435 test_ImmIME();
1436 test_ImmAssociateContextEx();
1437 test_ImmThreads();
1438 test_ImmIsUIMessage();
1439 test_ImmGetContext();
1440 test_ImmGetDescription();
1441 test_ImmDefaultHwnd();
1442 test_ImmGetIMCLockCount();
1443 test_ImmGetIMCCLockCount();
1444 test_ImmDestroyContext();
1445 test_ImmDestroyIMCC();
1446 test_InvalidIMC();
1447 msg_spy_cleanup();
1448 /* Reinitialize the hooks to capture all windows */
1449 msg_spy_init(NULL);
1450 test_ImmMessages();
1451 msg_spy_cleanup();
1452 if (pSendInput)
1453 test_ime_processkey();
1454 else win_skip("SendInput is not available\n");
1456 cleanup();