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
23 #include "wine/test.h"
29 BOOL WINAPI
ImmSetActiveContext(HWND
, HIMC
, BOOL
);
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);
35 #define DEFINE_EXPECT(func) \
36 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE, enabled_ ## func = FALSE
38 #define SET_EXPECT(func) \
39 expect_ ## func = TRUE
41 #define CHECK_EXPECT2(func) \
43 if (enabled_ ## func) {\
44 ok(expect_ ##func, "unexpected call " #func "\n"); \
45 called_ ## func = TRUE; \
49 #define CHECK_EXPECT(func) \
51 CHECK_EXPECT2(func); \
52 expect_ ## func = FALSE; \
55 #define CHECK_CALLED(func) \
57 ok(called_ ## func, "expected " #func "\n"); \
58 expect_ ## func = called_ ## func = FALSE; \
61 #define SET_ENABLE(func, val) \
62 enabled_ ## func = (val)
64 DEFINE_EXPECT(WM_IME_SETCONTEXT_DEACTIVATE
);
65 DEFINE_EXPECT(WM_IME_SETCONTEXT_ACTIVATE
);
68 * msgspy - record and analyse message traces sent to a certain window
70 typedef struct _msgs
{
75 static struct _msg_spy
{
78 HHOOK call_wnd_proc_hook
;
94 typedef struct _tagTRANSMSG
{
98 } TRANSMSG
, *LPTRANSMSG
;
100 static UINT (WINAPI
*pSendInput
) (UINT
, INPUT
*, size_t);
102 static LRESULT CALLBACK
get_msg_filter(int nCode
, WPARAM wParam
, LPARAM lParam
)
104 if (HC_ACTION
== nCode
) {
105 MSG
*msg
= (MSG
*)lParam
;
107 if ((msg
->hwnd
== msg_spy
.hwnd
|| msg_spy
.hwnd
== NULL
) &&
108 (msg_spy
.i_msg
< ARRAY_SIZE(msg_spy
.msgs
)))
110 msg_spy
.msgs
[msg_spy
.i_msg
].msg
.hwnd
= msg
->hwnd
;
111 msg_spy
.msgs
[msg_spy
.i_msg
].msg
.message
= msg
->message
;
112 msg_spy
.msgs
[msg_spy
.i_msg
].msg
.wParam
= msg
->wParam
;
113 msg_spy
.msgs
[msg_spy
.i_msg
].msg
.lParam
= msg
->lParam
;
114 msg_spy
.msgs
[msg_spy
.i_msg
].post
= TRUE
;
119 return CallNextHookEx(msg_spy
.get_msg_hook
, nCode
, wParam
, lParam
);
122 static LRESULT CALLBACK
call_wnd_proc_filter(int nCode
, WPARAM wParam
,
125 if (HC_ACTION
== nCode
) {
126 CWPSTRUCT
*cwp
= (CWPSTRUCT
*)lParam
;
128 if (((cwp
->hwnd
== msg_spy
.hwnd
|| msg_spy
.hwnd
== NULL
)) &&
129 (msg_spy
.i_msg
< ARRAY_SIZE(msg_spy
.msgs
)))
131 memcpy(&msg_spy
.msgs
[msg_spy
.i_msg
].msg
, cwp
, sizeof(msg_spy
.msgs
[0].msg
));
132 msg_spy
.msgs
[msg_spy
.i_msg
].post
= FALSE
;
137 return CallNextHookEx(msg_spy
.call_wnd_proc_hook
, nCode
, wParam
, lParam
);
140 static void msg_spy_pump_msg_queue(void) {
143 while(PeekMessageW(&msg
, NULL
, 0, 0, PM_REMOVE
)) {
144 TranslateMessage(&msg
);
145 DispatchMessageW(&msg
);
151 static void msg_spy_flush_msgs(void) {
152 msg_spy_pump_msg_queue();
156 static imm_msgs
* msg_spy_find_next_msg(UINT message
, UINT
*start
) {
159 msg_spy_pump_msg_queue();
161 if (msg_spy
.i_msg
>= ARRAY_SIZE(msg_spy
.msgs
))
162 fprintf(stdout
, "%s:%d: msg_spy: message buffer overflow!\n",
165 for (i
= *start
; i
< msg_spy
.i_msg
; i
++)
166 if (msg_spy
.msgs
[i
].msg
.message
== message
)
169 return &msg_spy
.msgs
[i
];
175 static imm_msgs
* msg_spy_find_msg(UINT message
) {
178 return msg_spy_find_next_msg(message
, &i
);
181 static void msg_spy_init(HWND hwnd
) {
183 msg_spy
.get_msg_hook
=
184 SetWindowsHookExW(WH_GETMESSAGE
, get_msg_filter
, GetModuleHandleW(NULL
),
185 GetCurrentThreadId());
186 msg_spy
.call_wnd_proc_hook
=
187 SetWindowsHookExW(WH_CALLWNDPROC
, call_wnd_proc_filter
,
188 GetModuleHandleW(NULL
), GetCurrentThreadId());
191 msg_spy_flush_msgs();
194 static void msg_spy_cleanup(void) {
195 if (msg_spy
.get_msg_hook
)
196 UnhookWindowsHookEx(msg_spy
.get_msg_hook
);
197 if (msg_spy
.call_wnd_proc_hook
)
198 UnhookWindowsHookEx(msg_spy
.call_wnd_proc_hook
);
199 memset(&msg_spy
, 0, sizeof(msg_spy
));
203 * imm32 test cases - Issue some IMM commands on a dummy window and analyse the
204 * messages being sent to this window in response.
206 static const char wndcls
[] = "winetest_imm32_wndcls";
207 static enum { PHASE_UNKNOWN
, FIRST_WINDOW
, SECOND_WINDOW
,
208 CREATE_CANCEL
, NCCREATE_CANCEL
, IME_DISABLED
} test_phase
;
211 static HWND
get_ime_window(void);
213 static LRESULT WINAPI
wndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
215 HWND default_ime_wnd
;
218 case WM_IME_SETCONTEXT
:
219 if (wParam
) CHECK_EXPECT(WM_IME_SETCONTEXT_ACTIVATE
);
220 else CHECK_EXPECT(WM_IME_SETCONTEXT_DEACTIVATE
);
221 ok(lParam
== ISC_SHOWUIALL
|| !lParam
, "lParam = %lx\n", lParam
);
224 default_ime_wnd
= get_ime_window();
228 ok(!default_ime_wnd
, "expected no IME windows\n");
231 ok(default_ime_wnd
!= NULL
, "expected IME window existence\n");
234 break; /* do nothing */
236 if (test_phase
== NCCREATE_CANCEL
)
240 default_ime_wnd
= get_ime_window();
245 ok(default_ime_wnd
!= NULL
, "expected IME window existence\n");
248 ok(!default_ime_wnd
, "expected no IME windows\n");
251 break; /* do nothing */
255 default_ime_wnd
= get_ime_window();
260 ok(default_ime_wnd
!= NULL
, "expected IME window existence\n");
263 ok(!default_ime_wnd
, "expected no IME windows\n");
266 break; /* do nothing */
268 if (test_phase
== CREATE_CANCEL
)
273 return DefWindowProcA(hWnd
,msg
,wParam
,lParam
);
276 static BOOL
init(void) {
281 hmod
= GetModuleHandleA("imm32.dll");
282 huser
= GetModuleHandleA("user32");
283 pImmAssociateContextEx
= (void*)GetProcAddress(hmod
, "ImmAssociateContextEx");
284 pImmIsUIMessageA
= (void*)GetProcAddress(hmod
, "ImmIsUIMessageA");
285 pSendInput
= (void*)GetProcAddress(huser
, "SendInput");
287 wc
.cbSize
= sizeof(WNDCLASSEXA
);
289 wc
.lpfnWndProc
= wndProc
;
292 wc
.hInstance
= GetModuleHandleA(NULL
);
293 wc
.hIcon
= LoadIconA(NULL
, (LPCSTR
)IDI_APPLICATION
);
294 wc
.hCursor
= LoadCursorA(NULL
, (LPCSTR
)IDC_ARROW
);
295 wc
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+1);
296 wc
.lpszMenuName
= NULL
;
297 wc
.lpszClassName
= wndcls
;
298 wc
.hIconSm
= LoadIconA(NULL
, (LPCSTR
)IDI_APPLICATION
);
300 if (!RegisterClassExA(&wc
))
303 hwnd
= CreateWindowExA(WS_EX_CLIENTEDGE
, wndcls
, "Wine imm32.dll test",
304 WS_OVERLAPPEDWINDOW
, CW_USEDEFAULT
, CW_USEDEFAULT
,
305 240, 120, NULL
, NULL
, GetModuleHandleW(NULL
), NULL
);
309 imc
= ImmGetContext(hwnd
);
312 win_skip("IME support not implemented\n");
315 ImmReleaseContext(hwnd
, imc
);
317 ShowWindow(hwnd
, SW_SHOWNORMAL
);
325 static void cleanup(void) {
329 UnregisterClassA(wndcls
, GetModuleHandleW(NULL
));
332 static void test_ImmNotifyIME(void) {
333 static const char string
[] = "wine";
334 char resstr
[16] = "";
338 imc
= ImmGetContext(hwnd
);
339 msg_spy_flush_msgs();
341 ret
= ImmNotifyIME(imc
, NI_COMPOSITIONSTR
, CPS_CANCEL
, 0);
344 "Canceling an empty composition string should succeed.\n");
345 ok(!msg_spy_find_msg(WM_IME_COMPOSITION
), "Windows does not post "
346 "WM_IME_COMPOSITION in response to NI_COMPOSITIONSTR / CPS_CANCEL, if "
347 "the composition string being canceled is empty.\n");
349 ImmSetCompositionStringA(imc
, SCS_SETSTR
, string
, sizeof(string
), NULL
, 0);
350 msg_spy_flush_msgs();
352 ImmNotifyIME(imc
, NI_COMPOSITIONSTR
, CPS_CANCEL
, 0);
353 msg_spy_flush_msgs();
355 /* behavior differs between win9x and NT */
356 ret
= ImmGetCompositionStringA(imc
, GCS_COMPSTR
, resstr
, sizeof(resstr
));
357 ok(!ret
, "After being cancelled the composition string is empty.\n");
359 msg_spy_flush_msgs();
361 ret
= ImmNotifyIME(imc
, NI_COMPOSITIONSTR
, CPS_CANCEL
, 0);
364 "Canceling an empty composition string should succeed.\n");
365 ok(!msg_spy_find_msg(WM_IME_COMPOSITION
), "Windows does not post "
366 "WM_IME_COMPOSITION in response to NI_COMPOSITIONSTR / CPS_CANCEL, if "
367 "the composition string being canceled is empty.\n");
369 msg_spy_flush_msgs();
370 ImmReleaseContext(hwnd
, imc
);
372 imc
= ImmCreateContext();
373 ImmDestroyContext(imc
);
375 SetLastError(0xdeadbeef);
376 ret
= ImmNotifyIME((HIMC
)0xdeadcafe, NI_COMPOSITIONSTR
, CPS_CANCEL
, 0);
377 ok (ret
== 0, "Bad IME should return 0\n");
378 ret
= GetLastError();
379 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
380 SetLastError(0xdeadbeef);
381 ret
= ImmNotifyIME(0x00000000, NI_COMPOSITIONSTR
, CPS_CANCEL
, 0);
382 ok (ret
== 0, "NULL IME should return 0\n");
383 ret
= GetLastError();
384 ok(ret
== ERROR_SUCCESS
, "wrong last error %08x!\n", ret
);
385 SetLastError(0xdeadbeef);
386 ret
= ImmNotifyIME(imc
, NI_COMPOSITIONSTR
, CPS_CANCEL
, 0);
387 ok (ret
== 0, "Destroyed IME should return 0\n");
388 ret
= GetLastError();
389 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
394 WNDPROC old_wnd_proc
;
395 BOOL catch_result_str
;
399 } ime_composition_test
;
401 static LRESULT WINAPI
test_ime_wnd_proc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
405 case WM_IME_COMPOSITION
:
406 if ((lParam
& GCS_RESULTSTR
) && !ime_composition_test
.catch_result_str
) {
413 hwndIme
= ImmGetDefaultIMEWnd(hWnd
);
414 ok(hwndIme
!= NULL
, "expected IME window existence\n");
416 ok(!ime_composition_test
.catch_ime_char
, "WM_IME_CHAR is sent\n");
417 ret
= CallWindowProcA(ime_composition_test
.old_wnd_proc
,
418 hWnd
, msg
, wParam
, lParam
);
419 ok(ime_composition_test
.catch_ime_char
, "WM_IME_CHAR isn't sent\n");
421 ime_composition_test
.catch_ime_char
= FALSE
;
422 SendMessageA(hwndIme
, msg
, wParam
, lParam
);
423 ok(!ime_composition_test
.catch_ime_char
, "WM_IME_CHAR is sent\n");
425 imc
= ImmGetContext(hWnd
);
426 size
= ImmGetCompositionStringW(imc
, GCS_RESULTSTR
,
427 wstring
, sizeof(wstring
));
428 ok(size
> 0, "ImmGetCompositionString(GCS_RESULTSTR) is %d\n", size
);
429 ImmReleaseContext(hwnd
, imc
);
431 ime_composition_test
.catch_result_str
= TRUE
;
436 if (!ime_composition_test
.catch_result_str
)
437 ime_composition_test
.catch_ime_char
= TRUE
;
440 if (wParam
== ime_composition_test
.timer_id
) {
441 HWND parent
= GetParent(hWnd
);
443 int left
= 20 - (GetTickCount() - ime_composition_test
.start
) / 1000;
444 wsprintfA(title
, "%sLeft %d sec. - IME composition test",
445 ime_composition_test
.catch_result_str
? "[*] " : "", left
);
446 SetWindowTextA(parent
, title
);
448 DestroyWindow(parent
);
450 SetTimer(hWnd
, wParam
, 100, NULL
);
455 return CallWindowProcA(ime_composition_test
.old_wnd_proc
,
456 hWnd
, msg
, wParam
, lParam
);
459 static void test_ImmGetCompositionString(void)
462 static const WCHAR string
[] = {'w','i','n','e',0x65e5,0x672c,0x8a9e};
470 imc
= ImmGetContext(hwnd
);
471 ret
= ImmSetCompositionStringW(imc
, SCS_SETSTR
, string
, sizeof(string
), NULL
,0);
473 win_skip("Composition isn't supported\n");
474 ImmReleaseContext(hwnd
, imc
);
477 msg_spy_flush_msgs();
479 alen
= ImmGetCompositionStringA(imc
, GCS_COMPSTR
, cstring
, 20);
480 wlen
= ImmGetCompositionStringW(imc
, GCS_COMPSTR
, wstring
, 20);
481 /* windows machines without any IME installed just return 0 above */
484 len
= ImmGetCompositionStringW(imc
, GCS_COMPATTR
, NULL
, 0);
485 ok(len
*sizeof(WCHAR
)==wlen
,"GCS_COMPATTR(W) not returning correct count\n");
486 len
= ImmGetCompositionStringA(imc
, GCS_COMPATTR
, NULL
, 0);
487 ok(len
==alen
,"GCS_COMPATTR(A) not returning correct count\n");
489 /* Get strings with exactly matching buffer sizes. */
490 memset(wstring
, 0x1a, sizeof(wstring
));
491 memset(cstring
, 0x1a, sizeof(cstring
));
493 len
= ImmGetCompositionStringA(imc
, GCS_COMPSTR
, cstring
, alen
);
494 ok(len
== alen
, "Unexpected length %d.\n", len
);
495 ok(cstring
[alen
] == 0x1a, "Unexpected buffer contents.\n");
497 len
= ImmGetCompositionStringW(imc
, GCS_COMPSTR
, wstring
, wlen
);
498 ok(len
== wlen
, "Unexpected length %d.\n", len
);
499 ok(wstring
[wlen
/sizeof(WCHAR
)] == 0x1a1a, "Unexpected buffer contents.\n");
501 /* Get strings with exactly smaller buffer sizes. */
502 memset(wstring
, 0x1a, sizeof(wstring
));
503 memset(cstring
, 0x1a, sizeof(cstring
));
505 /* Returns 0 but still fills buffer. */
506 len
= ImmGetCompositionStringA(imc
, GCS_COMPSTR
, cstring
, alen
- 1);
507 ok(!len
, "Unexpected length %d.\n", len
);
508 ok(cstring
[0] == 'w', "Unexpected buffer contents %s.\n", cstring
);
510 len
= ImmGetCompositionStringW(imc
, GCS_COMPSTR
, wstring
, wlen
- 1);
511 ok(len
== wlen
- 1, "Unexpected length %d.\n", len
);
512 ok(!memcmp(wstring
, string
, wlen
- 1), "Unexpected buffer contents.\n");
514 /* Get the size of the required output buffer. */
515 memset(wstring
, 0x1a, sizeof(wstring
));
516 memset(cstring
, 0x1a, sizeof(cstring
));
518 len
= ImmGetCompositionStringA(imc
, GCS_COMPSTR
, cstring
, 0);
519 ok(len
== alen
, "Unexpected length %d.\n", len
);
520 ok(cstring
[0] == 0x1a, "Unexpected buffer contents %s.\n", cstring
);
522 len
= ImmGetCompositionStringW(imc
, GCS_COMPSTR
, wstring
, 0);
523 ok(len
== wlen
, "Unexpected length %d.\n", len
);
524 ok(wstring
[0] == 0x1a1a, "Unexpected buffer contents.\n");
527 win_skip("Composition string isn't available\n");
529 ImmReleaseContext(hwnd
, imc
);
531 /* Test composition results input by IMM API */
532 prop
= ImmGetProperty(GetKeyboardLayout(0), IGP_SETCOMPSTR
);
533 if (!(prop
& SCS_CAP_COMPSTR
)) {
534 /* Wine's IME doesn't support SCS_SETSTR in ImmSetCompositionString */
535 skip("This IME doesn't support SCS_SETSTR\n");
538 ime_composition_test
.old_wnd_proc
=
539 (WNDPROC
)SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
,
540 (LONG_PTR
)test_ime_wnd_proc
);
541 imc
= ImmGetContext(hwnd
);
542 msg_spy_flush_msgs();
544 ret
= ImmSetCompositionStringW(imc
, SCS_SETSTR
,
545 string
, sizeof(string
), NULL
,0);
546 ok(ret
, "ImmSetCompositionStringW failed\n");
547 wlen
= ImmGetCompositionStringW(imc
, GCS_COMPSTR
,
548 wstring
, sizeof(wstring
));
550 ret
= ImmNotifyIME(imc
, NI_COMPOSITIONSTR
, CPS_COMPLETE
, 0);
551 ok(ret
, "ImmNotifyIME(CPS_COMPLETE) failed\n");
552 msg_spy_flush_msgs();
553 ok(ime_composition_test
.catch_result_str
,
554 "WM_IME_COMPOSITION(GCS_RESULTSTR) isn't sent\n");
557 win_skip("Composition string isn't available\n");
558 ImmReleaseContext(hwnd
, imc
);
559 SetWindowLongPtrA(hwnd
, GWLP_WNDPROC
,
560 (LONG_PTR
)ime_composition_test
.old_wnd_proc
);
561 msg_spy_flush_msgs();
564 /* Test composition results input by hand */
565 memset(&ime_composition_test
, 0, sizeof(ime_composition_test
));
566 if (winetest_interactive
) {
567 HWND hwndMain
, hwndChild
;
569 const DWORD MY_TIMER
= 0xcaffe;
571 hwndMain
= CreateWindowExA(WS_EX_CLIENTEDGE
, wndcls
,
572 "IME composition test",
573 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
574 CW_USEDEFAULT
, CW_USEDEFAULT
, 320, 160,
575 NULL
, NULL
, GetModuleHandleA(NULL
), NULL
);
576 hwndChild
= CreateWindowExA(0, "static",
577 "Input a DBCS character here using IME.",
578 WS_CHILD
| WS_VISIBLE
,
579 0, 0, 320, 100, hwndMain
, NULL
,
580 GetModuleHandleA(NULL
), NULL
);
582 ime_composition_test
.old_wnd_proc
=
583 (WNDPROC
)SetWindowLongPtrA(hwndChild
, GWLP_WNDPROC
,
584 (LONG_PTR
)test_ime_wnd_proc
);
588 ime_composition_test
.timer_id
= MY_TIMER
;
589 ime_composition_test
.start
= GetTickCount();
590 SetTimer(hwndChild
, ime_composition_test
.timer_id
, 100, NULL
);
591 while (GetMessageA(&msg
, NULL
, 0, 0)) {
592 TranslateMessage(&msg
);
593 DispatchMessageA(&msg
);
594 if (!IsWindow(hwndMain
))
597 if (!ime_composition_test
.catch_result_str
)
598 skip("WM_IME_COMPOSITION(GCS_RESULTSTR) isn't tested\n");
599 msg_spy_flush_msgs();
603 static void test_ImmSetCompositionString(void)
608 SetLastError(0xdeadbeef);
609 imc
= ImmGetContext(hwnd
);
610 ok(imc
!= 0, "ImmGetContext() failed. Last error: %u\n", GetLastError());
614 ret
= ImmSetCompositionStringW(imc
, SCS_SETSTR
, NULL
, 0, NULL
, 0);
617 "ImmSetCompositionStringW() failed.\n");
619 ret
= ImmSetCompositionStringW(imc
, SCS_SETSTR
| SCS_CHANGEATTR
,
621 ok(!ret
, "ImmSetCompositionStringW() succeeded.\n");
623 ret
= ImmSetCompositionStringW(imc
, SCS_SETSTR
| SCS_CHANGECLAUSE
,
625 ok(!ret
, "ImmSetCompositionStringW() succeeded.\n");
627 ret
= ImmSetCompositionStringW(imc
, SCS_CHANGEATTR
| SCS_CHANGECLAUSE
,
629 ok(!ret
, "ImmSetCompositionStringW() succeeded.\n");
631 ret
= ImmSetCompositionStringW(imc
, SCS_SETSTR
| SCS_CHANGEATTR
| SCS_CHANGECLAUSE
,
633 ok(!ret
, "ImmSetCompositionStringW() succeeded.\n");
635 ImmReleaseContext(hwnd
, imc
);
638 static void test_ImmIME(void)
642 imc
= ImmGetContext(hwnd
);
646 rc
= ImmConfigureIMEA(imc
, NULL
, IME_CONFIG_REGISTERWORD
, NULL
);
647 ok (rc
== 0, "ImmConfigureIMEA did not fail\n");
648 rc
= ImmConfigureIMEW(imc
, NULL
, IME_CONFIG_REGISTERWORD
, NULL
);
649 ok (rc
== 0, "ImmConfigureIMEW did not fail\n");
651 ImmReleaseContext(hwnd
,imc
);
654 static void test_ImmAssociateContextEx(void)
659 if (!pImmAssociateContextEx
) return;
661 imc
= ImmGetContext(hwnd
);
666 newimc
= ImmCreateContext();
667 ok(newimc
!= imc
, "handles should not be the same\n");
668 rc
= pImmAssociateContextEx(NULL
, NULL
, 0);
669 ok(!rc
, "ImmAssociateContextEx succeeded\n");
670 rc
= pImmAssociateContextEx(hwnd
, NULL
, 0);
671 ok(rc
, "ImmAssociateContextEx failed\n");
672 rc
= pImmAssociateContextEx(NULL
, imc
, 0);
673 ok(!rc
, "ImmAssociateContextEx succeeded\n");
675 rc
= pImmAssociateContextEx(hwnd
, imc
, 0);
676 ok(rc
, "ImmAssociateContextEx failed\n");
677 retimc
= ImmGetContext(hwnd
);
678 ok(retimc
== imc
, "handles should be the same\n");
679 ImmReleaseContext(hwnd
,retimc
);
681 rc
= pImmAssociateContextEx(hwnd
, newimc
, 0);
682 ok(rc
, "ImmAssociateContextEx failed\n");
683 retimc
= ImmGetContext(hwnd
);
684 ok(retimc
== newimc
, "handles should be the same\n");
685 ImmReleaseContext(hwnd
,retimc
);
687 rc
= pImmAssociateContextEx(hwnd
, NULL
, IACE_DEFAULT
);
688 ok(rc
, "ImmAssociateContextEx failed\n");
690 ImmReleaseContext(hwnd
,imc
);
693 typedef struct _igc_threadinfo
{
701 static DWORD WINAPI
ImmGetContextThreadFunc( LPVOID lpParam
)
710 igc_threadinfo
*info
= (igc_threadinfo
*)lpParam
;
711 info
->hwnd
= CreateWindowExA(WS_EX_CLIENTEDGE
, wndcls
, "Wine imm32.dll test",
712 WS_OVERLAPPEDWINDOW
, CW_USEDEFAULT
, CW_USEDEFAULT
,
713 240, 120, NULL
, NULL
, GetModuleHandleW(NULL
), NULL
);
715 h1
= ImmGetContext(hwnd
);
716 ok(info
->himc
== h1
, "hwnd context changed in new thread\n");
717 h2
= ImmGetContext(info
->hwnd
);
718 ok(h2
!= h1
, "new hwnd in new thread should have different context\n");
720 ImmReleaseContext(hwnd
,h1
);
722 hwnd2
= CreateWindowExA(WS_EX_CLIENTEDGE
, wndcls
, "Wine imm32.dll test",
723 WS_OVERLAPPEDWINDOW
, CW_USEDEFAULT
, CW_USEDEFAULT
,
724 240, 120, NULL
, NULL
, GetModuleHandleW(NULL
), NULL
);
725 h1
= ImmGetContext(hwnd2
);
727 ok(h1
== h2
, "Windows in same thread should have same default context\n");
728 ImmReleaseContext(hwnd2
,h1
);
729 ImmReleaseContext(info
->hwnd
,h2
);
730 DestroyWindow(hwnd2
);
732 /* priming for later tests */
733 ImmSetCompositionWindow(h1
, &cf
);
734 ImmSetStatusWindowPos(h1
, &pt
);
735 info
->u_himc
= ImmCreateContext();
736 ImmSetOpenStatus(info
->u_himc
, TRUE
);
738 cdf
.dwStyle
= CFS_CANDIDATEPOS
;
739 cdf
.ptCurrentPos
.x
= 0;
740 cdf
.ptCurrentPos
.y
= 0;
741 ImmSetCandidateWindow(info
->u_himc
, &cdf
);
743 SetEvent(info
->event
);
745 while(GetMessageW(&msg
, 0, 0, 0))
747 TranslateMessage(&msg
);
748 DispatchMessageW(&msg
);
753 static void test_ImmThreads(void)
755 HIMC himc
, otherHimc
, h1
;
756 igc_threadinfo threadinfo
;
763 DWORD status
, sentence
;
766 himc
= ImmGetContext(hwnd
);
767 threadinfo
.event
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
768 threadinfo
.himc
= himc
;
769 hThread
= CreateThread(NULL
, 0, ImmGetContextThreadFunc
, &threadinfo
, 0, &dwThreadId
);
770 WaitForSingleObject(threadinfo
.event
, INFINITE
);
772 otherHimc
= ImmGetContext(threadinfo
.hwnd
);
774 ok(himc
!= otherHimc
, "Windows from other threads should have different himc\n");
775 ok(otherHimc
== threadinfo
.himc
, "Context from other thread should not change in main thread\n");
777 SET_ENABLE(WM_IME_SETCONTEXT_DEACTIVATE
, TRUE
);
778 SET_ENABLE(WM_IME_SETCONTEXT_ACTIVATE
, TRUE
);
779 SET_EXPECT(WM_IME_SETCONTEXT_ACTIVATE
);
780 rc
= ImmSetActiveContext(hwnd
, otherHimc
, TRUE
);
781 ok(rc
, "ImmSetActiveContext failed\n");
782 CHECK_CALLED(WM_IME_SETCONTEXT_ACTIVATE
);
783 SET_EXPECT(WM_IME_SETCONTEXT_DEACTIVATE
);
784 rc
= ImmSetActiveContext(hwnd
, otherHimc
, FALSE
);
785 ok(rc
, "ImmSetActiveContext failed\n");
786 CHECK_CALLED(WM_IME_SETCONTEXT_DEACTIVATE
);
787 SET_ENABLE(WM_IME_SETCONTEXT_DEACTIVATE
, FALSE
);
788 SET_ENABLE(WM_IME_SETCONTEXT_ACTIVATE
, FALSE
);
790 h1
= ImmAssociateContext(hwnd
,otherHimc
);
791 ok(h1
== NULL
, "Should fail to be able to Associate a default context from a different thread\n");
792 h1
= ImmGetContext(hwnd
);
793 ok(h1
== himc
, "Context for window should remain unchanged\n");
794 ImmReleaseContext(hwnd
,h1
);
796 h1
= ImmAssociateContext(hwnd
, threadinfo
.u_himc
);
797 ok (h1
== NULL
, "Should fail to associate a context from a different thread\n");
798 h1
= ImmGetContext(hwnd
);
799 ok(h1
== himc
, "Context for window should remain unchanged\n");
800 ImmReleaseContext(hwnd
,h1
);
802 h1
= ImmAssociateContext(threadinfo
.hwnd
, threadinfo
.u_himc
);
803 ok (h1
== NULL
, "Should fail to associate a context from a different thread into a window from that thread.\n");
804 h1
= ImmGetContext(threadinfo
.hwnd
);
805 ok(h1
== threadinfo
.himc
, "Context for window should remain unchanged\n");
806 ImmReleaseContext(threadinfo
.hwnd
,h1
);
809 rc
= ImmSetOpenStatus(himc
, TRUE
);
810 ok(rc
!= 0, "ImmSetOpenStatus failed\n");
811 rc
= ImmGetOpenStatus(himc
);
812 ok(rc
!= 0, "ImmGetOpenStatus failed\n");
813 rc
= ImmSetOpenStatus(himc
, FALSE
);
814 ok(rc
!= 0, "ImmSetOpenStatus failed\n");
815 rc
= ImmGetOpenStatus(himc
);
816 ok(rc
== 0, "ImmGetOpenStatus failed\n");
818 rc
= ImmSetOpenStatus(otherHimc
, TRUE
);
819 ok(rc
== 0, "ImmSetOpenStatus should fail\n");
820 rc
= ImmSetOpenStatus(threadinfo
.u_himc
, TRUE
);
821 ok(rc
== 0, "ImmSetOpenStatus should fail\n");
822 rc
= ImmGetOpenStatus(otherHimc
);
823 ok(rc
== 0, "ImmGetOpenStatus failed\n");
824 rc
= ImmGetOpenStatus(threadinfo
.u_himc
);
825 ok (rc
== 1 || broken(rc
== 0), "ImmGetOpenStatus should return 1\n");
826 rc
= ImmSetOpenStatus(otherHimc
, FALSE
);
827 ok(rc
== 0, "ImmSetOpenStatus should fail\n");
828 rc
= ImmGetOpenStatus(otherHimc
);
829 ok(rc
== 0, "ImmGetOpenStatus failed\n");
831 /* CompositionFont */
832 rc
= ImmGetCompositionFontA(himc
, &lf
);
833 ok(rc
!= 0, "ImmGetCompositionFont failed\n");
834 rc
= ImmSetCompositionFontA(himc
, &lf
);
835 ok(rc
!= 0, "ImmSetCompositionFont failed\n");
837 rc
= ImmGetCompositionFontA(otherHimc
, &lf
);
838 ok(rc
!= 0 || broken(rc
== 0), "ImmGetCompositionFont failed\n");
839 rc
= ImmGetCompositionFontA(threadinfo
.u_himc
, &lf
);
840 ok(rc
!= 0 || broken(rc
== 0), "ImmGetCompositionFont user himc failed\n");
841 rc
= ImmSetCompositionFontA(otherHimc
, &lf
);
842 ok(rc
== 0, "ImmSetCompositionFont should fail\n");
843 rc
= ImmSetCompositionFontA(threadinfo
.u_himc
, &lf
);
844 ok(rc
== 0, "ImmSetCompositionFont should fail\n");
846 /* CompositionWindow */
847 rc
= ImmSetCompositionWindow(himc
, &cf
);
848 ok(rc
!= 0, "ImmSetCompositionWindow failed\n");
849 rc
= ImmGetCompositionWindow(himc
, &cf
);
850 ok(rc
!= 0, "ImmGetCompositionWindow failed\n");
852 rc
= ImmSetCompositionWindow(otherHimc
, &cf
);
853 ok(rc
== 0, "ImmSetCompositionWindow should fail\n");
854 rc
= ImmSetCompositionWindow(threadinfo
.u_himc
, &cf
);
855 ok(rc
== 0, "ImmSetCompositionWindow should fail\n");
856 rc
= ImmGetCompositionWindow(otherHimc
, &cf
);
857 ok(rc
!= 0 || broken(rc
== 0), "ImmGetCompositionWindow failed\n");
858 rc
= ImmGetCompositionWindow(threadinfo
.u_himc
, &cf
);
859 ok(rc
!= 0 || broken(rc
== 0), "ImmGetCompositionWindow failed\n");
861 /* ConversionStatus */
862 rc
= ImmGetConversionStatus(himc
, &status
, &sentence
);
863 ok(rc
!= 0, "ImmGetConversionStatus failed\n");
864 rc
= ImmSetConversionStatus(himc
, status
, sentence
);
865 ok(rc
!= 0, "ImmSetConversionStatus failed\n");
867 rc
= ImmGetConversionStatus(otherHimc
, &status
, &sentence
);
868 ok(rc
!= 0 || broken(rc
== 0), "ImmGetConversionStatus failed\n");
869 rc
= ImmGetConversionStatus(threadinfo
.u_himc
, &status
, &sentence
);
870 ok(rc
!= 0 || broken(rc
== 0), "ImmGetConversionStatus failed\n");
871 rc
= ImmSetConversionStatus(otherHimc
, status
, sentence
);
872 ok(rc
== 0, "ImmSetConversionStatus should fail\n");
873 rc
= ImmSetConversionStatus(threadinfo
.u_himc
, status
, sentence
);
874 ok(rc
== 0, "ImmSetConversionStatus should fail\n");
876 /* StatusWindowPos */
877 rc
= ImmSetStatusWindowPos(himc
, &pt
);
878 ok(rc
!= 0, "ImmSetStatusWindowPos failed\n");
879 rc
= ImmGetStatusWindowPos(himc
, &pt
);
880 ok(rc
!= 0, "ImmGetStatusWindowPos failed\n");
882 rc
= ImmSetStatusWindowPos(otherHimc
, &pt
);
883 ok(rc
== 0, "ImmSetStatusWindowPos should fail\n");
884 rc
= ImmSetStatusWindowPos(threadinfo
.u_himc
, &pt
);
885 ok(rc
== 0, "ImmSetStatusWindowPos should fail\n");
886 rc
= ImmGetStatusWindowPos(otherHimc
, &pt
);
887 ok(rc
!= 0 || broken(rc
== 0), "ImmGetStatusWindowPos failed\n");
888 rc
= ImmGetStatusWindowPos(threadinfo
.u_himc
, &pt
);
889 ok(rc
!= 0 || broken(rc
== 0), "ImmGetStatusWindowPos failed\n");
891 h1
= ImmAssociateContext(threadinfo
.hwnd
, NULL
);
892 ok (h1
== otherHimc
, "ImmAssociateContext cross thread with NULL should work\n");
893 h1
= ImmGetContext(threadinfo
.hwnd
);
894 ok (h1
== NULL
, "CrossThread window context should be NULL\n");
895 h1
= ImmAssociateContext(threadinfo
.hwnd
, h1
);
896 ok (h1
== NULL
, "Resetting cross thread context should fail\n");
897 h1
= ImmGetContext(threadinfo
.hwnd
);
898 ok (h1
== NULL
, "CrossThread window context should still be NULL\n");
900 rc
= ImmDestroyContext(threadinfo
.u_himc
);
901 ok (rc
== 0, "ImmDestroyContext Cross Thread should fail\n");
903 /* Candidate Window */
904 rc
= ImmGetCandidateWindow(himc
, 0, &cdf
);
905 ok (rc
== 0, "ImmGetCandidateWindow should fail\n");
907 cdf
.dwStyle
= CFS_CANDIDATEPOS
;
908 cdf
.ptCurrentPos
.x
= 0;
909 cdf
.ptCurrentPos
.y
= 0;
910 rc
= ImmSetCandidateWindow(himc
, &cdf
);
911 ok (rc
== 1, "ImmSetCandidateWindow should succeed\n");
912 rc
= ImmGetCandidateWindow(himc
, 0, &cdf
);
913 ok (rc
== 1, "ImmGetCandidateWindow should succeed\n");
915 rc
= ImmGetCandidateWindow(otherHimc
, 0, &cdf
);
916 ok (rc
== 0, "ImmGetCandidateWindow should fail\n");
917 rc
= ImmSetCandidateWindow(otherHimc
, &cdf
);
918 ok (rc
== 0, "ImmSetCandidateWindow should fail\n");
919 rc
= ImmGetCandidateWindow(threadinfo
.u_himc
, 0, &cdf
);
920 ok (rc
== 1 || broken( rc
== 0), "ImmGetCandidateWindow should succeed\n");
921 rc
= ImmSetCandidateWindow(threadinfo
.u_himc
, &cdf
);
922 ok (rc
== 0, "ImmSetCandidateWindow should fail\n");
924 ImmReleaseContext(threadinfo
.hwnd
,otherHimc
);
925 ImmReleaseContext(hwnd
,himc
);
927 SendMessageA(threadinfo
.hwnd
, WM_CLOSE
, 0, 0);
928 rc
= PostThreadMessageA(dwThreadId
, WM_QUIT
, 1, 0);
929 ok(rc
== 1, "PostThreadMessage should succeed\n");
930 WaitForSingleObject(hThread
, INFINITE
);
931 CloseHandle(hThread
);
933 himc
= ImmGetContext(GetDesktopWindow());
934 ok(himc
== NULL
, "Should not be able to get himc from other process window\n");
937 static void test_ImmIsUIMessage(void)
945 static const struct test tests
[] =
947 { WM_MOUSEMOVE
, FALSE
},
948 { WM_IME_STARTCOMPOSITION
, TRUE
},
949 { WM_IME_ENDCOMPOSITION
, TRUE
},
950 { WM_IME_COMPOSITION
, TRUE
},
951 { WM_IME_SETCONTEXT
, TRUE
},
952 { WM_IME_NOTIFY
, TRUE
},
953 { WM_IME_CONTROL
, FALSE
},
954 { WM_IME_COMPOSITIONFULL
, TRUE
},
955 { WM_IME_SELECT
, TRUE
},
956 { WM_IME_CHAR
, FALSE
},
957 { 0x287 /* FIXME */, TRUE
},
958 { WM_IME_REQUEST
, FALSE
},
959 { WM_IME_KEYDOWN
, FALSE
},
960 { WM_IME_KEYUP
, FALSE
},
961 { 0, FALSE
} /* mark the end */
964 UINT WM_MSIME_SERVICE
= RegisterWindowMessageA("MSIMEService");
965 UINT WM_MSIME_RECONVERTOPTIONS
= RegisterWindowMessageA("MSIMEReconvertOptions");
966 UINT WM_MSIME_MOUSE
= RegisterWindowMessageA("MSIMEMouseOperation");
967 UINT WM_MSIME_RECONVERTREQUEST
= RegisterWindowMessageA("MSIMEReconvertRequest");
968 UINT WM_MSIME_RECONVERT
= RegisterWindowMessageA("MSIMEReconvert");
969 UINT WM_MSIME_QUERYPOSITION
= RegisterWindowMessageA("MSIMEQueryPosition");
970 UINT WM_MSIME_DOCUMENTFEED
= RegisterWindowMessageA("MSIMEDocumentFeed");
972 const struct test
*test
;
975 if (!pImmIsUIMessageA
) return;
977 for (test
= tests
; test
->msg
; test
++)
979 msg_spy_flush_msgs();
980 ret
= pImmIsUIMessageA(NULL
, test
->msg
, 0, 0);
981 ok(ret
== test
->ret
, "ImmIsUIMessageA returned %x for %x\n", ret
, test
->msg
);
982 ok(!msg_spy_find_msg(test
->msg
), "Windows does not send 0x%x for NULL hwnd\n", test
->msg
);
984 ret
= pImmIsUIMessageA(hwnd
, test
->msg
, 0, 0);
985 ok(ret
== test
->ret
, "ImmIsUIMessageA returned %x for %x\n", ret
, test
->msg
);
987 ok(msg_spy_find_msg(test
->msg
) != NULL
, "Windows does send 0x%x\n", test
->msg
);
989 ok(!msg_spy_find_msg(test
->msg
), "Windows does not send 0x%x\n", test
->msg
);
992 ret
= pImmIsUIMessageA(NULL
, WM_MSIME_SERVICE
, 0, 0);
993 ok(!ret
, "ImmIsUIMessageA returned TRUE for WM_MSIME_SERVICE\n");
994 ret
= pImmIsUIMessageA(NULL
, WM_MSIME_RECONVERTOPTIONS
, 0, 0);
995 ok(!ret
, "ImmIsUIMessageA returned TRUE for WM_MSIME_RECONVERTOPTIONS\n");
996 ret
= pImmIsUIMessageA(NULL
, WM_MSIME_MOUSE
, 0, 0);
997 ok(!ret
, "ImmIsUIMessageA returned TRUE for WM_MSIME_MOUSE\n");
998 ret
= pImmIsUIMessageA(NULL
, WM_MSIME_RECONVERTREQUEST
, 0, 0);
999 ok(!ret
, "ImmIsUIMessageA returned TRUE for WM_MSIME_RECONVERTREQUEST\n");
1000 ret
= pImmIsUIMessageA(NULL
, WM_MSIME_RECONVERT
, 0, 0);
1001 ok(!ret
, "ImmIsUIMessageA returned TRUE for WM_MSIME_RECONVERT\n");
1002 ret
= pImmIsUIMessageA(NULL
, WM_MSIME_QUERYPOSITION
, 0, 0);
1003 ok(!ret
, "ImmIsUIMessageA returned TRUE for WM_MSIME_QUERYPOSITION\n");
1004 ret
= pImmIsUIMessageA(NULL
, WM_MSIME_DOCUMENTFEED
, 0, 0);
1005 ok(!ret
, "ImmIsUIMessageA returned TRUE for WM_MSIME_DOCUMENTFEED\n");
1008 static void test_ImmGetContext(void)
1013 SetLastError(0xdeadbeef);
1014 himc
= ImmGetContext((HWND
)0xffffffff);
1015 err
= GetLastError();
1016 ok(himc
== NULL
, "ImmGetContext succeeded\n");
1017 ok(err
== ERROR_INVALID_WINDOW_HANDLE
, "got %u\n", err
);
1019 himc
= ImmGetContext(hwnd
);
1020 ok(himc
!= NULL
, "ImmGetContext failed\n");
1021 ok(ImmReleaseContext(hwnd
, himc
), "ImmReleaseContext failed\n");
1024 static void test_ImmGetDescription(void)
1031 /* FIXME: invalid keyboard layouts should not pass */
1032 ret
= ImmGetDescriptionW(NULL
, NULL
, 0);
1033 ok(!ret
, "ImmGetDescriptionW failed, expected 0 received %d.\n", ret
);
1034 ret
= ImmGetDescriptionA(NULL
, NULL
, 0);
1035 ok(!ret
, "ImmGetDescriptionA failed, expected 0 received %d.\n", ret
);
1037 /* load a language with valid IMM descriptions */
1038 hkl
= GetKeyboardLayout(0);
1039 ok(hkl
!= 0, "GetKeyboardLayout failed, expected != 0.\n");
1041 ret
= ImmGetDescriptionW(hkl
, NULL
, 0);
1044 win_skip("ImmGetDescriptionW is not working for current loaded keyboard.\n");
1048 SetLastError(0xdeadcafe);
1049 ret
= ImmGetDescriptionW(0, NULL
, 100);
1050 ok (ret
== 0, "ImmGetDescriptionW with 0 hkl should return 0\n");
1051 ret
= GetLastError();
1052 ok (ret
== 0xdeadcafe, "Last Error should remain unchanged\n");
1054 ret
= ImmGetDescriptionW(hkl
, descW
, 0);
1055 ok(ret
, "ImmGetDescriptionW failed, expected != 0 received 0.\n");
1057 lret
= ImmGetDescriptionW(hkl
, descW
, ret
+ 1);
1058 ok(lret
, "ImmGetDescriptionW failed, expected != 0 received 0.\n");
1059 ok(lret
== ret
, "ImmGetDescriptionW failed to return the correct amount of data. Expected %d, got %d.\n", ret
, lret
);
1061 lret
= ImmGetDescriptionA(hkl
, descA
, ret
+ 1);
1062 ok(lret
, "ImmGetDescriptionA failed, expected != 0 received 0.\n");
1063 ok(lret
== ret
, "ImmGetDescriptionA failed to return the correct amount of data. Expected %d, got %d.\n", ret
, lret
);
1065 ret
/= 2; /* try to copy partially */
1066 lret
= ImmGetDescriptionW(hkl
, descW
, ret
+ 1);
1067 ok(lret
, "ImmGetDescriptionW failed, expected != 0 received 0.\n");
1068 ok(lret
== ret
, "ImmGetDescriptionW failed to return the correct amount of data. Expected %d, got %d.\n", ret
, lret
);
1070 lret
= ImmGetDescriptionA(hkl
, descA
, ret
+ 1);
1071 ok(!lret
, "ImmGetDescriptionA should fail\n");
1073 ret
= ImmGetDescriptionW(hkl
, descW
, 1);
1074 ok(!ret
, "ImmGetDescriptionW failed, expected 0 received %d.\n", ret
);
1076 UnloadKeyboardLayout(hkl
);
1079 static LRESULT (WINAPI
*old_imm_wnd_proc
)(HWND
, UINT
, WPARAM
, LPARAM
);
1080 static LRESULT WINAPI
imm_wnd_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1082 ok(msg
!= WM_DESTROY
, "got WM_DESTROY message\n");
1083 return old_imm_wnd_proc(hwnd
, msg
, wparam
, lparam
);
1086 static HWND thread_ime_wnd
;
1087 static DWORD WINAPI
test_ImmGetDefaultIMEWnd_thread(void *arg
)
1089 CreateWindowA("static", "static", WS_POPUP
, 0, 0, 1, 1, NULL
, NULL
, NULL
, NULL
);
1091 thread_ime_wnd
= ImmGetDefaultIMEWnd(0);
1092 ok(thread_ime_wnd
!= 0, "ImmGetDefaultIMEWnd returned NULL\n");
1093 old_imm_wnd_proc
= (void*)SetWindowLongPtrW(thread_ime_wnd
, GWLP_WNDPROC
, (LONG_PTR
)imm_wnd_proc
);
1097 static void test_ImmDefaultHwnd(void)
1099 HIMC imc1
, imc2
, imc3
;
1106 hwnd
= CreateWindowExA(WS_EX_CLIENTEDGE
, "EDIT", "Wine imm32.dll test",
1107 WS_OVERLAPPEDWINDOW
, CW_USEDEFAULT
, CW_USEDEFAULT
,
1108 240, 120, NULL
, NULL
, GetModuleHandleW(NULL
), NULL
);
1110 ShowWindow(hwnd
, SW_SHOWNORMAL
);
1112 imc1
= ImmGetContext(hwnd
);
1115 win_skip("IME support not implemented\n");
1119 def1
= ImmGetDefaultIMEWnd(hwnd
);
1121 GetWindowTextA(def1
, title
, sizeof(title
));
1122 ok(!strcmp(title
, "Default IME"), "got %s\n", title
);
1123 style
= GetWindowLongA(def1
, GWL_STYLE
);
1124 ok(style
== (WS_DISABLED
| WS_POPUP
| WS_CLIPSIBLINGS
), "got %08x\n", style
);
1125 style
= GetWindowLongA(def1
, GWL_EXSTYLE
);
1126 ok(style
== 0, "got %08x\n", style
);
1128 imc2
= ImmCreateContext();
1129 ImmSetOpenStatus(imc2
, TRUE
);
1131 imc3
= ImmGetContext(hwnd
);
1132 def3
= ImmGetDefaultIMEWnd(hwnd
);
1134 ok(def3
== def1
, "Default IME window should not change\n");
1135 ok(imc1
== imc3
, "IME context should not change\n");
1136 ImmSetOpenStatus(imc2
, FALSE
);
1138 thread
= CreateThread(NULL
, 0, test_ImmGetDefaultIMEWnd_thread
, NULL
, 0, NULL
);
1139 WaitForSingleObject(thread
, INFINITE
);
1140 ok(thread_ime_wnd
!= def1
, "thread_ime_wnd == def1\n");
1141 ok(!IsWindow(thread_ime_wnd
), "thread_ime_wnd was not destroyed\n");
1142 CloseHandle(thread
);
1144 ImmReleaseContext(hwnd
, imc1
);
1145 ImmReleaseContext(hwnd
, imc3
);
1146 ImmDestroyContext(imc2
);
1147 DestroyWindow(hwnd
);
1150 static BOOL CALLBACK
is_ime_window_proc(HWND hWnd
, LPARAM param
)
1152 WCHAR class_nameW
[16];
1153 HWND
*ime_window
= (HWND
*)param
;
1154 if (GetClassNameW(hWnd
, class_nameW
, ARRAY_SIZE(class_nameW
)) && !lstrcmpW(class_nameW
, L
"IME"))
1162 static HWND
get_ime_window(void)
1164 HWND ime_window
= NULL
;
1165 EnumThreadWindows(GetCurrentThreadId(), is_ime_window_proc
, (LPARAM
)&ime_window
);
1169 struct testcase_ime_window
{
1171 BOOL top_level_window
;
1174 static DWORD WINAPI
test_default_ime_window_cb(void *arg
)
1176 struct testcase_ime_window
*testcase
= (struct testcase_ime_window
*)arg
;
1177 DWORD visible
= testcase
->visible
? WS_VISIBLE
: 0;
1178 HWND hwnd1
, hwnd2
, default_ime_wnd
, ime_wnd
;
1180 ok(!get_ime_window(), "Expected no IME windows\n");
1181 if (testcase
->top_level_window
) {
1182 test_phase
= FIRST_WINDOW
;
1183 hwnd1
= CreateWindowExA(WS_EX_CLIENTEDGE
, wndcls
, "Wine imm32.dll test",
1184 WS_OVERLAPPEDWINDOW
| visible
,
1185 CW_USEDEFAULT
, CW_USEDEFAULT
,
1186 240, 120, NULL
, NULL
, GetModuleHandleW(NULL
), NULL
);
1189 hwnd1
= CreateWindowExA(WS_EX_CLIENTEDGE
, "EDIT", "Wine imm32.dll test",
1191 CW_USEDEFAULT
, CW_USEDEFAULT
,
1192 240, 24, hwnd
, NULL
, GetModuleHandleW(NULL
), NULL
);
1194 ime_wnd
= get_ime_window();
1195 ok(ime_wnd
!= NULL
, "Expected IME window existence\n");
1196 default_ime_wnd
= ImmGetDefaultIMEWnd(hwnd1
);
1197 ok(ime_wnd
== default_ime_wnd
, "Expected %p, got %p\n", ime_wnd
, default_ime_wnd
);
1199 test_phase
= SECOND_WINDOW
;
1200 hwnd2
= CreateWindowExA(WS_EX_CLIENTEDGE
, wndcls
, "Wine imm32.dll test",
1201 WS_OVERLAPPEDWINDOW
| visible
,
1202 CW_USEDEFAULT
, CW_USEDEFAULT
,
1203 240, 120, NULL
, NULL
, GetModuleHandleW(NULL
), NULL
);
1204 DestroyWindow(hwnd2
);
1205 ok(IsWindow(ime_wnd
) ||
1206 broken(!testcase
->visible
/* Vista */) ||
1207 broken(!testcase
->top_level_window
/* Vista */) ,
1208 "Expected IME window existence\n");
1209 DestroyWindow(hwnd1
);
1210 ok(!IsWindow(ime_wnd
), "Expected no IME windows\n");
1214 static DWORD WINAPI
test_default_ime_window_cancel_cb(void *arg
)
1216 struct testcase_ime_window
*testcase
= (struct testcase_ime_window
*)arg
;
1217 DWORD visible
= testcase
->visible
? WS_VISIBLE
: 0;
1218 HWND hwnd1
, hwnd2
, default_ime_wnd
, ime_wnd
;
1220 ok(!get_ime_window(), "Expected no IME windows\n");
1221 test_phase
= NCCREATE_CANCEL
;
1222 hwnd1
= CreateWindowExA(WS_EX_CLIENTEDGE
, wndcls
, "Wine imm32.dll test",
1223 WS_OVERLAPPEDWINDOW
| visible
,
1224 CW_USEDEFAULT
, CW_USEDEFAULT
,
1225 240, 120, NULL
, NULL
, GetModuleHandleW(NULL
), NULL
);
1226 ok(hwnd1
== NULL
, "creation succeeded, got %p\n", hwnd1
);
1227 ok(!get_ime_window(), "Expected no IME windows\n");
1229 test_phase
= CREATE_CANCEL
;
1230 hwnd1
= CreateWindowExA(WS_EX_CLIENTEDGE
, wndcls
, "Wine imm32.dll test",
1231 WS_OVERLAPPEDWINDOW
| visible
,
1232 CW_USEDEFAULT
, CW_USEDEFAULT
,
1233 240, 120, NULL
, NULL
, GetModuleHandleW(NULL
), NULL
);
1234 ok(hwnd1
== NULL
, "creation succeeded, got %p\n", hwnd1
);
1235 ok(!get_ime_window(), "Expected no IME windows\n");
1237 test_phase
= FIRST_WINDOW
;
1238 hwnd2
= CreateWindowExA(WS_EX_CLIENTEDGE
, wndcls
, "Wine imm32.dll test",
1239 WS_OVERLAPPEDWINDOW
| visible
,
1240 CW_USEDEFAULT
, CW_USEDEFAULT
,
1241 240, 120, NULL
, NULL
, GetModuleHandleW(NULL
), NULL
);
1242 ime_wnd
= get_ime_window();
1243 ok(ime_wnd
!= NULL
, "Expected IME window existence\n");
1244 default_ime_wnd
= ImmGetDefaultIMEWnd(hwnd2
);
1245 ok(ime_wnd
== default_ime_wnd
, "Expected %p, got %p\n", ime_wnd
, default_ime_wnd
);
1247 DestroyWindow(hwnd2
);
1248 ok(!IsWindow(ime_wnd
), "Expected no IME windows\n");
1252 static DWORD WINAPI
test_default_ime_disabled_cb(void *arg
)
1254 HWND hWnd
, default_ime_wnd
;
1256 ok(!get_ime_window(), "Expected no IME windows\n");
1257 ImmDisableIME(GetCurrentThreadId());
1258 test_phase
= IME_DISABLED
;
1259 hWnd
= CreateWindowExA(WS_EX_CLIENTEDGE
, wndcls
, "Wine imm32.dll test",
1260 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
1261 CW_USEDEFAULT
, CW_USEDEFAULT
,
1262 240, 120, NULL
, NULL
, GetModuleHandleW(NULL
), NULL
);
1263 default_ime_wnd
= ImmGetDefaultIMEWnd(hWnd
);
1264 ok(!default_ime_wnd
, "Expected no IME windows\n");
1265 DestroyWindow(hWnd
);
1269 static DWORD WINAPI
test_default_ime_with_message_only_window_cb(void *arg
)
1271 HWND hwnd1
, hwnd2
, default_ime_wnd
;
1273 test_phase
= PHASE_UNKNOWN
;
1274 hwnd1
= CreateWindowA(wndcls
, "Wine imm32.dll test",
1275 WS_OVERLAPPEDWINDOW
,
1276 CW_USEDEFAULT
, CW_USEDEFAULT
,
1277 240, 120, HWND_MESSAGE
, NULL
, GetModuleHandleW(NULL
), NULL
);
1278 default_ime_wnd
= ImmGetDefaultIMEWnd(hwnd1
);
1279 ok(!IsWindow(default_ime_wnd
), "Expected no IME windows, got %p\n", default_ime_wnd
);
1281 hwnd2
= CreateWindowA(wndcls
, "Wine imm32.dll test",
1282 WS_OVERLAPPEDWINDOW
,
1283 CW_USEDEFAULT
, CW_USEDEFAULT
,
1284 240, 120, hwnd1
, NULL
, GetModuleHandleW(NULL
), NULL
);
1285 default_ime_wnd
= ImmGetDefaultIMEWnd(hwnd2
);
1286 ok(IsWindow(default_ime_wnd
), "Expected IME window existence\n");
1288 DestroyWindow(hwnd2
);
1289 DestroyWindow(hwnd1
);
1291 hwnd1
= CreateWindowA(wndcls
, "Wine imm32.dll test",
1292 WS_OVERLAPPEDWINDOW
,
1293 CW_USEDEFAULT
, CW_USEDEFAULT
,
1294 240, 120, NULL
, NULL
, GetModuleHandleW(NULL
), NULL
);
1295 default_ime_wnd
= ImmGetDefaultIMEWnd(hwnd1
);
1296 ok(IsWindow(default_ime_wnd
), "Expected IME window existence\n");
1297 SetParent(hwnd1
, HWND_MESSAGE
);
1298 default_ime_wnd
= ImmGetDefaultIMEWnd(hwnd1
);
1299 ok(IsWindow(default_ime_wnd
), "Expected IME window existence\n");
1300 DestroyWindow(hwnd1
);
1304 static void test_default_ime_window_creation(void)
1308 struct testcase_ime_window testcases
[] = {
1309 /* visible, top-level window */
1316 for (i
= 0; i
< ARRAY_SIZE(testcases
); i
++)
1318 thread
= CreateThread(NULL
, 0, test_default_ime_window_cb
, &testcases
[i
], 0, NULL
);
1319 ok(thread
!= NULL
, "CreateThread failed with error %u\n", GetLastError());
1320 while (MsgWaitForMultipleObjects(1, &thread
, FALSE
, INFINITE
, QS_ALLINPUT
) == WAIT_OBJECT_0
+ 1)
1323 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
1325 TranslateMessage(&msg
);
1326 DispatchMessageA(&msg
);
1329 CloseHandle(thread
);
1331 if (testcases
[i
].top_level_window
)
1333 thread
= CreateThread(NULL
, 0, test_default_ime_window_cancel_cb
, &testcases
[i
], 0, NULL
);
1334 ok(thread
!= NULL
, "CreateThread failed with error %u\n", GetLastError());
1335 WaitForSingleObject(thread
, INFINITE
);
1336 CloseHandle(thread
);
1340 thread
= CreateThread(NULL
, 0, test_default_ime_disabled_cb
, NULL
, 0, NULL
);
1341 WaitForSingleObject(thread
, INFINITE
);
1342 CloseHandle(thread
);
1344 thread
= CreateThread(NULL
, 0, test_default_ime_with_message_only_window_cb
, NULL
, 0, NULL
);
1345 WaitForSingleObject(thread
, INFINITE
);
1346 CloseHandle(thread
);
1348 test_phase
= PHASE_UNKNOWN
;
1351 static void test_ImmGetIMCLockCount(void)
1354 DWORD count
, ret
, i
;
1357 imc
= ImmCreateContext();
1358 ImmDestroyContext(imc
);
1359 SetLastError(0xdeadbeef);
1360 count
= ImmGetIMCLockCount((HIMC
)0xdeadcafe);
1361 ok(count
== 0, "Invalid IMC should return 0\n");
1362 ret
= GetLastError();
1363 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1364 SetLastError(0xdeadbeef);
1365 count
= ImmGetIMCLockCount(0x00000000);
1366 ok(count
== 0, "NULL IMC should return 0\n");
1367 ret
= GetLastError();
1368 ok(ret
== 0xdeadbeef, "Last Error should remain unchanged: %08x\n",ret
);
1369 count
= ImmGetIMCLockCount(imc
);
1370 ok(count
== 0, "Destroyed IMC should return 0\n");
1371 ret
= GetLastError();
1372 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1374 imc
= ImmCreateContext();
1375 count
= ImmGetIMCLockCount(imc
);
1376 ok(count
== 0, "expect 0, returned %d\n", count
);
1377 ic
= ImmLockIMC(imc
);
1378 ok(ic
!= NULL
, "ImmLockIMC failed!\n");
1379 count
= ImmGetIMCLockCount(imc
);
1380 ok(count
== 1, "expect 1, returned %d\n", count
);
1381 ret
= ImmUnlockIMC(imc
);
1382 ok(ret
== TRUE
, "expect TRUE, ret %d\n", ret
);
1383 count
= ImmGetIMCLockCount(imc
);
1384 ok(count
== 0, "expect 0, returned %d\n", count
);
1385 ret
= ImmUnlockIMC(imc
);
1386 ok(ret
== TRUE
, "expect TRUE, ret %d\n", ret
);
1387 count
= ImmGetIMCLockCount(imc
);
1388 ok(count
== 0, "expect 0, returned %d\n", count
);
1390 for (i
= 0; i
< GMEM_LOCKCOUNT
* 2; i
++)
1392 ic
= ImmLockIMC(imc
);
1393 ok(ic
!= NULL
, "ImmLockIMC failed!\n");
1395 count
= ImmGetIMCLockCount(imc
);
1396 todo_wine
ok(count
== GMEM_LOCKCOUNT
, "expect GMEM_LOCKCOUNT, returned %d\n", count
);
1398 for (i
= 0; i
< GMEM_LOCKCOUNT
- 1; i
++)
1400 count
= ImmGetIMCLockCount(imc
);
1401 todo_wine
ok(count
== 1, "expect 1, returned %d\n", count
);
1403 count
= ImmGetIMCLockCount(imc
);
1404 todo_wine
ok(count
== 0, "expect 0, returned %d\n", count
);
1406 ImmDestroyContext(imc
);
1409 static void test_ImmGetIMCCLockCount(void)
1412 DWORD count
, g_count
, i
;
1416 imcc
= ImmCreateIMCC(sizeof(CANDIDATEINFO
));
1417 count
= ImmGetIMCCLockCount(imcc
);
1418 ok(count
== 0, "expect 0, returned %d\n", count
);
1420 count
= ImmGetIMCCLockCount(imcc
);
1421 ok(count
== 1, "expect 1, returned %d\n", count
);
1422 ret
= ImmUnlockIMCC(imcc
);
1423 ok(ret
== FALSE
, "expect FALSE, ret %d\n", ret
);
1424 count
= ImmGetIMCCLockCount(imcc
);
1425 ok(count
== 0, "expect 0, returned %d\n", count
);
1426 ret
= ImmUnlockIMCC(imcc
);
1427 ok(ret
== FALSE
, "expect FALSE, ret %d\n", ret
);
1428 count
= ImmGetIMCCLockCount(imcc
);
1429 ok(count
== 0, "expect 0, returned %d\n", count
);
1431 p
= ImmLockIMCC(imcc
);
1432 ok(GlobalHandle(p
) == imcc
, "expect %p, returned %p\n", imcc
, GlobalHandle(p
));
1434 for (i
= 0; i
< GMEM_LOCKCOUNT
* 2; i
++)
1437 count
= ImmGetIMCCLockCount(imcc
);
1438 g_count
= GlobalFlags(imcc
) & GMEM_LOCKCOUNT
;
1439 ok(count
== g_count
, "count %d, g_count %d\n", count
, g_count
);
1441 count
= ImmGetIMCCLockCount(imcc
);
1442 ok(count
== GMEM_LOCKCOUNT
, "expect GMEM_LOCKCOUNT, returned %d\n", count
);
1444 for (i
= 0; i
< GMEM_LOCKCOUNT
- 1; i
++)
1446 count
= ImmGetIMCCLockCount(imcc
);
1447 ok(count
== 1, "expect 1, returned %d\n", count
);
1449 count
= ImmGetIMCCLockCount(imcc
);
1450 ok(count
== 0, "expect 0, returned %d\n", count
);
1452 ImmDestroyIMCC(imcc
);
1455 static void test_ImmDestroyContext(void)
1461 imc
= ImmCreateContext();
1462 count
= ImmGetIMCLockCount(imc
);
1463 ok(count
== 0, "expect 0, returned %d\n", count
);
1464 ic
= ImmLockIMC(imc
);
1465 ok(ic
!= NULL
, "ImmLockIMC failed!\n");
1466 count
= ImmGetIMCLockCount(imc
);
1467 ok(count
== 1, "expect 1, returned %d\n", count
);
1468 ret
= ImmDestroyContext(imc
);
1469 ok(ret
== TRUE
, "Destroy a locked IMC should success!\n");
1470 ic
= ImmLockIMC(imc
);
1471 ok(ic
== NULL
, "Lock a destroyed IMC should fail!\n");
1472 ret
= ImmUnlockIMC(imc
);
1473 ok(ret
== FALSE
, "Unlock a destroyed IMC should fail!\n");
1474 count
= ImmGetIMCLockCount(imc
);
1475 ok(count
== 0, "Get lock count of a destroyed IMC should return 0!\n");
1476 SetLastError(0xdeadbeef);
1477 ret
= ImmDestroyContext(imc
);
1478 ok(ret
== FALSE
, "Destroy a destroyed IMC should fail!\n");
1479 ret
= GetLastError();
1480 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1483 static void test_ImmDestroyIMCC(void)
1486 DWORD ret
, count
, size
;
1489 imcc
= ImmCreateIMCC(sizeof(CANDIDATEINFO
));
1490 count
= ImmGetIMCCLockCount(imcc
);
1491 ok(count
== 0, "expect 0, returned %d\n", count
);
1492 p
= ImmLockIMCC(imcc
);
1493 ok(p
!= NULL
, "ImmLockIMCC failed!\n");
1494 count
= ImmGetIMCCLockCount(imcc
);
1495 ok(count
== 1, "expect 1, returned %d\n", count
);
1496 size
= ImmGetIMCCSize(imcc
);
1497 ok(size
== sizeof(CANDIDATEINFO
), "returned %d\n", size
);
1498 p
= ImmDestroyIMCC(imcc
);
1499 ok(p
== NULL
, "Destroy a locked IMCC should success!\n");
1500 p
= ImmLockIMCC(imcc
);
1501 ok(p
== NULL
, "Lock a destroyed IMCC should fail!\n");
1502 ret
= ImmUnlockIMCC(imcc
);
1503 ok(ret
== FALSE
, "Unlock a destroyed IMCC should return FALSE!\n");
1504 count
= ImmGetIMCCLockCount(imcc
);
1505 ok(count
== 0, "Get lock count of a destroyed IMCC should return 0!\n");
1506 size
= ImmGetIMCCSize(imcc
);
1507 ok(size
== 0, "Get size of a destroyed IMCC should return 0!\n");
1508 SetLastError(0xdeadbeef);
1509 p
= ImmDestroyIMCC(imcc
);
1510 ok(p
!= NULL
, "returned NULL\n");
1511 ret
= GetLastError();
1512 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1515 static void test_ImmMessages(void)
1523 LPINPUTCONTEXT lpIMC
;
1524 LPTRANSMSG lpTransMsg
;
1526 HWND hwnd
= CreateWindowExA(WS_EX_CLIENTEDGE
, "EDIT", "Wine imm32.dll test",
1527 WS_OVERLAPPEDWINDOW
, CW_USEDEFAULT
, CW_USEDEFAULT
,
1528 240, 120, NULL
, NULL
, GetModuleHandleA(NULL
), NULL
);
1530 ShowWindow(hwnd
, SW_SHOWNORMAL
);
1531 defwnd
= ImmGetDefaultIMEWnd(hwnd
);
1532 imc
= ImmGetContext(hwnd
);
1534 ImmSetOpenStatus(imc
, TRUE
);
1535 msg_spy_flush_msgs();
1536 SendMessageA(defwnd
, WM_IME_CONTROL
, IMC_GETCANDIDATEPOS
, (LPARAM
)&cf
);
1539 msg
= msg_spy_find_next_msg(WM_IME_CONTROL
,&idx
);
1540 if (msg
) ok(!msg
->post
, "Message should not be posted\n");
1542 msg_spy_flush_msgs();
1544 lpIMC
= ImmLockIMC(imc
);
1545 lpIMC
->hMsgBuf
= ImmReSizeIMCC(lpIMC
->hMsgBuf
, (lpIMC
->dwNumMsgBuf
+ 1) * sizeof(TRANSMSG
));
1546 lpTransMsg
= ImmLockIMCC(lpIMC
->hMsgBuf
);
1547 lpTransMsg
+= lpIMC
->dwNumMsgBuf
;
1548 lpTransMsg
->message
= WM_IME_STARTCOMPOSITION
;
1549 lpTransMsg
->wParam
= 0;
1550 lpTransMsg
->lParam
= 0;
1551 ImmUnlockIMCC(lpIMC
->hMsgBuf
);
1552 lpIMC
->dwNumMsgBuf
++;
1554 ImmGenerateMessage(imc
);
1558 msg
= msg_spy_find_next_msg(WM_IME_STARTCOMPOSITION
, &idx
);
1559 if (msg
) ok(!msg
->post
, "Message should not be posted\n");
1561 msg_spy_flush_msgs();
1563 lpIMC
= ImmLockIMC(imc
);
1564 lpIMC
->hMsgBuf
= ImmReSizeIMCC(lpIMC
->hMsgBuf
, (lpIMC
->dwNumMsgBuf
+ 1) * sizeof(TRANSMSG
));
1565 lpTransMsg
= ImmLockIMCC(lpIMC
->hMsgBuf
);
1566 lpTransMsg
+= lpIMC
->dwNumMsgBuf
;
1567 lpTransMsg
->message
= WM_IME_COMPOSITION
;
1568 lpTransMsg
->wParam
= 0;
1569 lpTransMsg
->lParam
= 0;
1570 ImmUnlockIMCC(lpIMC
->hMsgBuf
);
1571 lpIMC
->dwNumMsgBuf
++;
1573 ImmGenerateMessage(imc
);
1577 msg
= msg_spy_find_next_msg(WM_IME_COMPOSITION
, &idx
);
1578 if (msg
) ok(!msg
->post
, "Message should not be posted\n");
1580 msg_spy_flush_msgs();
1582 lpIMC
= ImmLockIMC(imc
);
1583 lpIMC
->hMsgBuf
= ImmReSizeIMCC(lpIMC
->hMsgBuf
, (lpIMC
->dwNumMsgBuf
+ 1) * sizeof(TRANSMSG
));
1584 lpTransMsg
= ImmLockIMCC(lpIMC
->hMsgBuf
);
1585 lpTransMsg
+= lpIMC
->dwNumMsgBuf
;
1586 lpTransMsg
->message
= WM_IME_ENDCOMPOSITION
;
1587 lpTransMsg
->wParam
= 0;
1588 lpTransMsg
->lParam
= 0;
1589 ImmUnlockIMCC(lpIMC
->hMsgBuf
);
1590 lpIMC
->dwNumMsgBuf
++;
1592 ImmGenerateMessage(imc
);
1596 msg
= msg_spy_find_next_msg(WM_IME_ENDCOMPOSITION
, &idx
);
1597 if (msg
) ok(!msg
->post
, "Message should not be posted\n");
1599 msg_spy_flush_msgs();
1601 ImmSetOpenStatus(imc
, FALSE
);
1602 ImmReleaseContext(hwnd
, imc
);
1603 DestroyWindow(hwnd
);
1606 static LRESULT CALLBACK
processkey_wnd_proc( HWND hWnd
, UINT msg
, WPARAM wParam
,
1609 return DefWindowProcW(hWnd
, msg
, wParam
, lParam
);
1612 static void test_ime_processkey(void)
1616 HANDLE hInstance
= GetModuleHandleW(NULL
);
1617 TEST_INPUT inputs
[2];
1622 wclass
.lpszClassName
= L
"ProcessKeyTestClass";
1623 wclass
.style
= CS_HREDRAW
| CS_VREDRAW
;
1624 wclass
.lpfnWndProc
= processkey_wnd_proc
;
1625 wclass
.hInstance
= hInstance
;
1626 wclass
.hIcon
= LoadIconW(0, (LPCWSTR
)IDI_APPLICATION
);
1627 wclass
.hCursor
= LoadCursorW( NULL
, (LPCWSTR
)IDC_ARROW
);
1628 wclass
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
1629 wclass
.lpszMenuName
= 0;
1630 wclass
.cbClsExtra
= 0;
1631 wclass
.cbWndExtra
= 0;
1632 if(!RegisterClassW(&wclass
)){
1633 win_skip("Failed to register window.\n");
1637 /* create the test window that will receive the keystrokes */
1638 hWndTest
= CreateWindowW(wclass
.lpszClassName
, L
"ProcessKey",
1639 WS_OVERLAPPEDWINDOW
, CW_USEDEFAULT
, 0, 100, 100,
1640 NULL
, NULL
, hInstance
, NULL
);
1642 ShowWindow(hWndTest
, SW_SHOW
);
1643 SetWindowPos(hWndTest
, HWND_TOPMOST
, 0, 0, 0, 0, SWP_NOSIZE
|SWP_NOMOVE
);
1644 SetForegroundWindow(hWndTest
);
1645 UpdateWindow(hWndTest
);
1647 imc
= ImmGetContext(hWndTest
);
1650 win_skip("IME not supported\n");
1651 DestroyWindow(hWndTest
);
1655 rc
= ImmSetOpenStatus(imc
, TRUE
);
1658 win_skip("Unable to open IME\n");
1659 ImmReleaseContext(hWndTest
, imc
);
1660 DestroyWindow(hWndTest
);
1664 /* flush pending messages */
1665 while (PeekMessageW(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW(&msg
);
1669 /* init input data that never changes */
1670 inputs
[1].type
= inputs
[0].type
= INPUT_KEYBOARD
;
1671 inputs
[1].u
.ki
.dwExtraInfo
= inputs
[0].u
.ki
.dwExtraInfo
= 0;
1672 inputs
[1].u
.ki
.time
= inputs
[0].u
.ki
.time
= 0;
1674 /* Pressing a key */
1675 inputs
[0].u
.ki
.wVk
= 0x41;
1676 inputs
[0].u
.ki
.wScan
= 0x1e;
1677 inputs
[0].u
.ki
.dwFlags
= 0x0;
1679 pSendInput(1, (INPUT
*)inputs
, sizeof(INPUT
));
1681 while(PeekMessageW(&msg
, hWndTest
, 0, 0, PM_NOREMOVE
)) {
1682 if(msg
.message
!= WM_KEYDOWN
)
1683 PeekMessageW(&msg
, hWndTest
, 0, 0, PM_REMOVE
);
1686 ok(msg
.wParam
!= VK_PROCESSKEY
,"Incorrect ProcessKey Found\n");
1687 PeekMessageW(&msg
, hWndTest
, 0, 0, PM_REMOVE
);
1688 if(msg
.wParam
== VK_PROCESSKEY
)
1689 trace("ProcessKey was correctly found\n");
1691 TranslateMessage(&msg
);
1692 /* test calling TranslateMessage multiple times */
1693 TranslateMessage(&msg
);
1694 DispatchMessageW(&msg
);
1697 inputs
[0].u
.ki
.wVk
= 0x41;
1698 inputs
[0].u
.ki
.wScan
= 0x1e;
1699 inputs
[0].u
.ki
.dwFlags
= KEYEVENTF_KEYUP
;
1701 pSendInput(1, (INPUT
*)inputs
, sizeof(INPUT
));
1703 while(PeekMessageW(&msg
, hWndTest
, 0, 0, PM_NOREMOVE
)) {
1704 if(msg
.message
!= WM_KEYUP
)
1705 PeekMessageW(&msg
, hWndTest
, 0, 0, PM_REMOVE
);
1708 ok(msg
.wParam
!= VK_PROCESSKEY
,"Incorrect ProcessKey Found\n");
1709 PeekMessageW(&msg
, hWndTest
, 0, 0, PM_REMOVE
);
1710 ok(msg
.wParam
!= VK_PROCESSKEY
,"ProcessKey should still not be Found\n");
1712 TranslateMessage(&msg
);
1713 DispatchMessageW(&msg
);
1716 ImmReleaseContext(hWndTest
, imc
);
1717 ImmSetOpenStatus(imc
, FALSE
);
1718 DestroyWindow(hWndTest
);
1721 static void test_InvalidIMC(void)
1724 HIMC imc_null
= 0x00000000;
1725 HIMC imc_bad
= (HIMC
)0xdeadcafe;
1727 HIMC imc1
, imc2
, oldimc
;
1735 memset(&lf
, 0, sizeof(lf
));
1737 imc_destroy
= ImmCreateContext();
1738 ret
= ImmDestroyContext(imc_destroy
);
1739 ok(ret
== TRUE
, "Destroy an IMC should success!\n");
1741 /* Test associating destroyed imc */
1742 imc1
= ImmGetContext(hwnd
);
1743 SetLastError(0xdeadbeef);
1744 oldimc
= ImmAssociateContext(hwnd
, imc_destroy
);
1745 ok(!oldimc
, "Associating to a destroyed imc should fail!\n");
1746 ret
= GetLastError();
1747 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1748 imc2
= ImmGetContext(hwnd
);
1749 ok(imc1
== imc2
, "imc should not changed! imc1 %p, imc2 %p\n", imc1
, imc2
);
1751 SET_ENABLE(WM_IME_SETCONTEXT_DEACTIVATE
, TRUE
);
1752 SET_ENABLE(WM_IME_SETCONTEXT_ACTIVATE
, TRUE
);
1753 r
= ImmSetActiveContext(hwnd
, imc_destroy
, TRUE
);
1754 ok(!r
, "ImmSetActiveContext succeeded\n");
1755 SET_EXPECT(WM_IME_SETCONTEXT_DEACTIVATE
);
1756 r
= ImmSetActiveContext(hwnd
, imc_destroy
, FALSE
);
1757 ok(r
, "ImmSetActiveContext failed\n");
1758 CHECK_CALLED(WM_IME_SETCONTEXT_DEACTIVATE
);
1759 SET_ENABLE(WM_IME_SETCONTEXT_ACTIVATE
, FALSE
);
1760 SET_ENABLE(WM_IME_SETCONTEXT_DEACTIVATE
, FALSE
);
1762 /* Test associating NULL imc, which is different from an invalid imc */
1763 oldimc
= ImmAssociateContext(hwnd
, imc_null
);
1764 ok(oldimc
!= NULL
, "Associating to NULL imc should success!\n");
1765 imc2
= ImmGetContext(hwnd
);
1766 ok(!imc2
, "expect NULL, returned %p\n", imc2
);
1767 oldimc
= ImmAssociateContext(hwnd
, imc1
);
1768 ok(!oldimc
, "expect NULL, returned %p\n", oldimc
);
1769 imc2
= ImmGetContext(hwnd
);
1770 ok(imc2
== imc1
, "imc should not changed! imc2 %p, imc1 %p\n", imc2
, imc1
);
1772 /* Test associating invalid imc */
1773 imc1
= ImmGetContext(hwnd
);
1774 SetLastError(0xdeadbeef);
1775 oldimc
= ImmAssociateContext(hwnd
, imc_bad
);
1776 ok(!oldimc
, "Associating to a destroyed imc should fail!\n");
1777 ret
= GetLastError();
1778 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1779 imc2
= ImmGetContext(hwnd
);
1780 ok(imc1
== imc2
, "imc should not changed! imc1 %p, imc2 %p\n", imc1
, imc2
);
1783 /* Test ImmGetCandidateListA */
1784 SetLastError(0xdeadbeef);
1785 ret
= ImmGetCandidateListA(imc_bad
, 0, NULL
, 0);
1786 ok(ret
== 0, "Bad IME should return 0\n");
1787 ret
= GetLastError();
1788 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1789 SetLastError(0xdeadbeef);
1790 ret
= ImmGetCandidateListA(imc_null
, 0, NULL
, 0);
1791 ok(ret
== 0, "NULL IME should return 0\n");
1792 ret
= GetLastError();
1793 ok(ret
== 0xdeadbeef, "last error should remain unchanged %08x!\n", ret
);
1794 SetLastError(0xdeadbeef);
1795 ret
= ImmGetCandidateListA(imc_destroy
, 0, NULL
, 0);
1796 ok(ret
== 0, "Destroyed IME should return 0\n");
1797 ret
= GetLastError();
1798 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1800 /* Test ImmGetCandidateListCountA*/
1801 SetLastError(0xdeadbeef);
1802 ret
= ImmGetCandidateListCountA(imc_bad
,&count
);
1803 ok(ret
== 0, "Bad IME should return 0\n");
1804 ret
= GetLastError();
1805 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1806 SetLastError(0xdeadbeef);
1807 ret
= ImmGetCandidateListCountA(imc_null
,&count
);
1808 ok(ret
== 0, "NULL IME should return 0\n");
1809 ret
= GetLastError();
1810 ok(ret
== 0xdeadbeef, "last error should remain unchanged %08x!\n", ret
);
1811 SetLastError(0xdeadbeef);
1812 ret
= ImmGetCandidateListCountA(imc_destroy
,&count
);
1813 ok(ret
== 0, "Destroyed IME should return 0\n");
1814 ret
= GetLastError();
1815 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1817 /* Test ImmGetCandidateWindow */
1818 SetLastError(0xdeadbeef);
1819 ret
= ImmGetCandidateWindow(imc_bad
, 0, (LPCANDIDATEFORM
)buffer
);
1820 ok(ret
== 0, "Bad IME should return 0\n");
1821 ret
= GetLastError();
1822 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1823 SetLastError(0xdeadbeef);
1824 ret
= ImmGetCandidateWindow(imc_null
, 0, (LPCANDIDATEFORM
)buffer
);
1825 ok(ret
== 0, "NULL IME should return 0\n");
1826 ret
= GetLastError();
1827 ok(ret
== 0xdeadbeef, "last error should remain unchanged %08x!\n", ret
);
1828 SetLastError(0xdeadbeef);
1829 ret
= ImmGetCandidateWindow(imc_destroy
, 0, (LPCANDIDATEFORM
)buffer
);
1830 ok(ret
== 0, "Destroyed IME should return 0\n");
1831 ret
= GetLastError();
1832 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1834 /* Test ImmGetCompositionFontA */
1835 SetLastError(0xdeadbeef);
1836 ret
= ImmGetCompositionFontA(imc_bad
, (LPLOGFONTA
)buffer
);
1837 ok(ret
== 0, "Bad IME should return 0\n");
1838 ret
= GetLastError();
1839 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1840 SetLastError(0xdeadbeef);
1841 ret
= ImmGetCompositionFontA(imc_null
, (LPLOGFONTA
)buffer
);
1842 ok(ret
== 0, "NULL IME should return 0\n");
1843 ret
= GetLastError();
1844 ok(ret
== 0xdeadbeef, "last error should remain unchanged %08x!\n", ret
);
1845 SetLastError(0xdeadbeef);
1846 ret
= ImmGetCompositionFontA(imc_destroy
, (LPLOGFONTA
)buffer
);
1847 ok(ret
== 0, "Destroyed IME should return 0\n");
1848 ret
= GetLastError();
1849 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1851 /* Test ImmGetCompositionWindow */
1852 SetLastError(0xdeadbeef);
1853 ret
= ImmGetCompositionWindow(imc_bad
, (LPCOMPOSITIONFORM
)buffer
);
1854 ok(ret
== 0, "Bad IME should return 0\n");
1855 ret
= GetLastError();
1856 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1857 SetLastError(0xdeadbeef);
1858 ret
= ImmGetCompositionWindow(imc_null
, (LPCOMPOSITIONFORM
)buffer
);
1859 ok(ret
== 0, "NULL IME should return 0\n");
1860 ret
= GetLastError();
1861 ok(ret
== 0xdeadbeef, "last error should remain unchanged %08x!\n", ret
);
1862 SetLastError(0xdeadbeef);
1863 ret
= ImmGetCompositionWindow(imc_destroy
, (LPCOMPOSITIONFORM
)buffer
);
1864 ok(ret
== 0, "Destroyed IME should return 0\n");
1865 ret
= GetLastError();
1866 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1868 /* Test ImmGetCompositionStringA */
1869 SetLastError(0xdeadbeef);
1870 ret
= ImmGetCompositionStringA(imc_bad
, GCS_COMPSTR
, NULL
, 0);
1871 ok(ret
== 0, "Bad IME should return 0\n");
1872 ret
= GetLastError();
1873 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1874 SetLastError(0xdeadbeef);
1875 ret
= ImmGetCompositionStringA(imc_null
, GCS_COMPSTR
, NULL
, 0);
1876 ok(ret
== 0, "NULL IME should return 0\n");
1877 ret
= GetLastError();
1878 ok(ret
== 0xdeadbeef, "last error should remain unchanged %08x!\n", ret
);
1879 SetLastError(0xdeadbeef);
1880 ret
= ImmGetCompositionStringA(imc_destroy
, GCS_COMPSTR
, NULL
, 0);
1881 ok(ret
== 0, "Destroyed IME should return 0\n");
1882 ret
= GetLastError();
1883 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1885 /* Test ImmSetOpenStatus */
1886 SetLastError(0xdeadbeef);
1887 ret
= ImmSetOpenStatus(imc_bad
, 1);
1888 ok(ret
== 0, "Bad IME should return 0\n");
1889 ret
= GetLastError();
1890 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1891 SetLastError(0xdeadbeef);
1892 ret
= ImmSetOpenStatus(imc_null
, 1);
1893 ok(ret
== 0, "NULL 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
= ImmSetOpenStatus(imc_destroy
, 1);
1898 ok(ret
== 0, "Destroyed IME should return 0\n");
1899 ret
= GetLastError();
1900 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1902 /* Test ImmGetOpenStatus */
1903 SetLastError(0xdeadbeef);
1904 ret
= ImmGetOpenStatus(imc_bad
);
1905 ok(ret
== 0, "Bad IME should return 0\n");
1906 ret
= GetLastError();
1907 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1908 SetLastError(0xdeadbeef);
1909 ret
= ImmGetOpenStatus(imc_null
);
1910 ok(ret
== 0, "NULL IME should return 0\n");
1911 ret
= GetLastError();
1912 ok(ret
== 0xdeadbeef, "last error should remain unchanged %08x!\n", ret
);
1913 SetLastError(0xdeadbeef);
1914 ret
= ImmGetOpenStatus(imc_destroy
);
1915 ok(ret
== 0, "Destroyed IME should return 0\n");
1916 ret
= GetLastError();
1917 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1919 /* Test ImmGetStatusWindowPos */
1920 SetLastError(0xdeadbeef);
1921 ret
= ImmGetStatusWindowPos(imc_bad
, NULL
);
1922 ok(ret
== 0, "Bad IME should return 0\n");
1923 ret
= GetLastError();
1924 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1925 SetLastError(0xdeadbeef);
1926 ret
= ImmGetStatusWindowPos(imc_null
, NULL
);
1927 ok(ret
== 0, "NULL IME should return 0\n");
1928 ret
= GetLastError();
1929 ok(ret
== 0xdeadbeef, "last error should remain unchanged %08x!\n", ret
);
1930 SetLastError(0xdeadbeef);
1931 ret
= ImmGetStatusWindowPos(imc_destroy
, NULL
);
1932 ok(ret
== 0, "Destroyed IME should return 0\n");
1933 ret
= GetLastError();
1934 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1936 /* Test ImmRequestMessageA */
1937 SetLastError(0xdeadbeef);
1938 ret
= ImmRequestMessageA(imc_bad
, WM_CHAR
, 0);
1939 ok(ret
== 0, "Bad IME should return 0\n");
1940 ret
= GetLastError();
1941 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1942 SetLastError(0xdeadbeef);
1943 ret
= ImmRequestMessageA(imc_null
, WM_CHAR
, 0);
1944 ok(ret
== 0, "NULL IME should return 0\n");
1945 ret
= GetLastError();
1946 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1947 SetLastError(0xdeadbeef);
1948 ret
= ImmRequestMessageA(imc_destroy
, WM_CHAR
, 0);
1949 ok(ret
== 0, "Destroyed IME should return 0\n");
1950 ret
= GetLastError();
1951 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1953 /* Test ImmSetCompositionFontA */
1954 SetLastError(0xdeadbeef);
1955 ret
= ImmSetCompositionFontA(imc_bad
, &lf
);
1956 ok(ret
== 0, "Bad IME should return 0\n");
1957 ret
= GetLastError();
1958 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1959 SetLastError(0xdeadbeef);
1960 ret
= ImmSetCompositionFontA(imc_null
, &lf
);
1961 ok(ret
== 0, "NULL 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
= ImmSetCompositionFontA(imc_destroy
, &lf
);
1966 ok(ret
== 0, "Destroyed IME should return 0\n");
1967 ret
= GetLastError();
1968 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1970 /* Test ImmSetCompositionWindow */
1971 SetLastError(0xdeadbeef);
1972 ret
= ImmSetCompositionWindow(imc_bad
, NULL
);
1973 ok(ret
== 0, "Bad IME should return 0\n");
1974 ret
= GetLastError();
1975 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1976 SetLastError(0xdeadbeef);
1977 ret
= ImmSetCompositionWindow(imc_null
, NULL
);
1978 ok(ret
== 0, "NULL 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
= ImmSetCompositionWindow(imc_destroy
, NULL
);
1983 ok(ret
== 0, "Destroyed IME should return 0\n");
1984 ret
= GetLastError();
1985 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1987 /* Test ImmSetConversionStatus */
1988 SetLastError(0xdeadbeef);
1989 ret
= ImmSetConversionStatus(imc_bad
, 0, 0);
1990 ok(ret
== 0, "Bad IME should return 0\n");
1991 ret
= GetLastError();
1992 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1993 SetLastError(0xdeadbeef);
1994 ret
= ImmSetConversionStatus(imc_null
, 0, 0);
1995 ok(ret
== 0, "NULL IME should return 0\n");
1996 ret
= GetLastError();
1997 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1998 SetLastError(0xdeadbeef);
1999 ret
= ImmSetConversionStatus(imc_destroy
, 0, 0);
2000 ok(ret
== 0, "Destroyed IME should return 0\n");
2001 ret
= GetLastError();
2002 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
2004 /* Test ImmSetStatusWindowPos */
2005 SetLastError(0xdeadbeef);
2006 ret
= ImmSetStatusWindowPos(imc_bad
, 0);
2007 ok(ret
== 0, "Bad IME should return 0\n");
2008 ret
= GetLastError();
2009 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
2010 SetLastError(0xdeadbeef);
2011 ret
= ImmSetStatusWindowPos(imc_null
, 0);
2012 ok(ret
== 0, "NULL IME should return 0\n");
2013 ret
= GetLastError();
2014 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
2015 SetLastError(0xdeadbeef);
2016 ret
= ImmSetStatusWindowPos(imc_destroy
, 0);
2017 ok(ret
== 0, "Destroyed IME should return 0\n");
2018 ret
= GetLastError();
2019 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
2021 /* Test ImmGetImeMenuItemsA */
2022 SetLastError(0xdeadbeef);
2023 ret
= ImmGetImeMenuItemsA(imc_bad
, 0, 0, NULL
, NULL
, 0);
2024 ok(ret
== 0, "Bad IME should return 0\n");
2025 ret
= GetLastError();
2026 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
2027 SetLastError(0xdeadbeef);
2028 ret
= ImmGetImeMenuItemsA(imc_null
, 0, 0, NULL
, NULL
, 0);
2029 ok(ret
== 0, "NULL IME should return 0\n");
2030 ret
= GetLastError();
2031 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
2032 SetLastError(0xdeadbeef);
2033 ret
= ImmGetImeMenuItemsA(imc_destroy
, 0, 0, NULL
, NULL
, 0);
2034 ok(ret
== 0, "Destroyed IME should return 0\n");
2035 ret
= GetLastError();
2036 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
2038 /* Test ImmLockIMC */
2039 SetLastError(0xdeadbeef);
2040 ic
= ImmLockIMC(imc_bad
);
2041 ok(ic
== 0, "Bad IME should return 0\n");
2042 ret
= GetLastError();
2043 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
2044 SetLastError(0xdeadbeef);
2045 ic
= ImmLockIMC(imc_null
);
2046 ok(ic
== 0, "NULL IME should return 0\n");
2047 ret
= GetLastError();
2048 ok(ret
== 0xdeadbeef, "last error should remain unchanged %08x!\n", ret
);
2049 SetLastError(0xdeadbeef);
2050 ic
= ImmLockIMC(imc_destroy
);
2051 ok(ic
== 0, "Destroyed IME should return 0\n");
2052 ret
= GetLastError();
2053 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
2055 /* Test ImmUnlockIMC */
2056 SetLastError(0xdeadbeef);
2057 ret
= ImmUnlockIMC(imc_bad
);
2058 ok(ret
== 0, "Bad IME should return 0\n");
2059 ret
= GetLastError();
2060 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
2061 SetLastError(0xdeadbeef);
2062 ret
= ImmUnlockIMC(imc_null
);
2063 ok(ret
== 0, "NULL IME should return 0\n");
2064 ret
= GetLastError();
2065 ok(ret
== 0xdeadbeef, "last error should remain unchanged %08x!\n", ret
);
2066 SetLastError(0xdeadbeef);
2067 ret
= ImmUnlockIMC(imc_destroy
);
2068 ok(ret
== 0, "Destroyed IME should return 0\n");
2069 ret
= GetLastError();
2070 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
2072 /* Test ImmGenerateMessage */
2073 SetLastError(0xdeadbeef);
2074 ret
= ImmGenerateMessage(imc_bad
);
2075 ok(ret
== 0, "Bad IME should return 0\n");
2076 ret
= GetLastError();
2077 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
2078 SetLastError(0xdeadbeef);
2079 ret
= ImmGenerateMessage(imc_null
);
2080 ok(ret
== 0, "NULL IME should return 0\n");
2081 ret
= GetLastError();
2082 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
2083 SetLastError(0xdeadbeef);
2084 ret
= ImmGenerateMessage(imc_destroy
);
2085 ok(ret
== 0, "Destroyed IME should return 0\n");
2086 ret
= GetLastError();
2087 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
2093 test_ImmNotifyIME();
2094 test_ImmGetCompositionString();
2095 test_ImmSetCompositionString();
2097 test_ImmAssociateContextEx();
2099 test_ImmIsUIMessage();
2100 test_ImmGetContext();
2101 test_ImmGetDescription();
2102 test_ImmDefaultHwnd();
2103 test_default_ime_window_creation();
2104 test_ImmGetIMCLockCount();
2105 test_ImmGetIMCCLockCount();
2106 test_ImmDestroyContext();
2107 test_ImmDestroyIMCC();
2110 /* Reinitialize the hooks to capture all windows */
2115 test_ime_processkey();
2116 else win_skip("SendInput is not available\n");