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 #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
{
43 static struct _msg_spy
{
46 HHOOK call_wnd_proc_hook
;
62 typedef struct _tagTRANSMSG
{
66 } TRANSMSG
, *LPTRANSMSG
;
68 static UINT (WINAPI
*pSendInput
) (UINT
, INPUT
*, size_t);
70 static LRESULT CALLBACK
get_msg_filter(int nCode
, WPARAM wParam
, LPARAM lParam
)
72 if (HC_ACTION
== nCode
) {
73 MSG
*msg
= (MSG
*)lParam
;
75 if ((msg
->hwnd
== msg_spy
.hwnd
|| msg_spy
.hwnd
== NULL
) &&
76 (msg_spy
.i_msg
< NUMELEMS(msg_spy
.msgs
)))
78 msg_spy
.msgs
[msg_spy
.i_msg
].msg
.hwnd
= msg
->hwnd
;
79 msg_spy
.msgs
[msg_spy
.i_msg
].msg
.message
= msg
->message
;
80 msg_spy
.msgs
[msg_spy
.i_msg
].msg
.wParam
= msg
->wParam
;
81 msg_spy
.msgs
[msg_spy
.i_msg
].msg
.lParam
= msg
->lParam
;
82 msg_spy
.msgs
[msg_spy
.i_msg
].post
= TRUE
;
87 return CallNextHookEx(msg_spy
.get_msg_hook
, nCode
, wParam
, lParam
);
90 static LRESULT CALLBACK
call_wnd_proc_filter(int nCode
, WPARAM wParam
,
93 if (HC_ACTION
== nCode
) {
94 CWPSTRUCT
*cwp
= (CWPSTRUCT
*)lParam
;
96 if (((cwp
->hwnd
== msg_spy
.hwnd
|| msg_spy
.hwnd
== NULL
)) &&
97 (msg_spy
.i_msg
< NUMELEMS(msg_spy
.msgs
)))
99 memcpy(&msg_spy
.msgs
[msg_spy
.i_msg
].msg
, cwp
, sizeof(msg_spy
.msgs
[0].msg
));
100 msg_spy
.msgs
[msg_spy
.i_msg
].post
= FALSE
;
105 return CallNextHookEx(msg_spy
.call_wnd_proc_hook
, nCode
, wParam
, lParam
);
108 static void msg_spy_pump_msg_queue(void) {
111 while(PeekMessageW(&msg
, NULL
, 0, 0, PM_REMOVE
)) {
112 TranslateMessage(&msg
);
113 DispatchMessageW(&msg
);
119 static void msg_spy_flush_msgs(void) {
120 msg_spy_pump_msg_queue();
124 static imm_msgs
* msg_spy_find_next_msg(UINT message
, UINT
*start
) {
127 msg_spy_pump_msg_queue();
129 if (msg_spy
.i_msg
>= NUMELEMS(msg_spy
.msgs
))
130 fprintf(stdout
, "%s:%d: msg_spy: message buffer overflow!\n",
133 for (i
= *start
; i
< msg_spy
.i_msg
; i
++)
134 if (msg_spy
.msgs
[i
].msg
.message
== message
)
137 return &msg_spy
.msgs
[i
];
143 static imm_msgs
* msg_spy_find_msg(UINT message
) {
146 return msg_spy_find_next_msg(message
, &i
);
149 static void msg_spy_init(HWND hwnd
) {
151 msg_spy
.get_msg_hook
=
152 SetWindowsHookExW(WH_GETMESSAGE
, get_msg_filter
, GetModuleHandleW(NULL
),
153 GetCurrentThreadId());
154 msg_spy
.call_wnd_proc_hook
=
155 SetWindowsHookExW(WH_CALLWNDPROC
, call_wnd_proc_filter
,
156 GetModuleHandleW(NULL
), GetCurrentThreadId());
159 msg_spy_flush_msgs();
162 static void msg_spy_cleanup(void) {
163 if (msg_spy
.get_msg_hook
)
164 UnhookWindowsHookEx(msg_spy
.get_msg_hook
);
165 if (msg_spy
.call_wnd_proc_hook
)
166 UnhookWindowsHookEx(msg_spy
.call_wnd_proc_hook
);
167 memset(&msg_spy
, 0, sizeof(msg_spy
));
171 * imm32 test cases - Issue some IMM commands on a dummy window and analyse the
172 * messages being sent to this window in response.
174 static const char wndcls
[] = "winetest_imm32_wndcls";
175 static enum { PHASE_UNKNOWN
, FIRST_WINDOW
, SECOND_WINDOW
,
176 CREATE_CANCEL
, NCCREATE_CANCEL
, IME_DISABLED
} test_phase
;
179 static HWND
get_ime_window(void);
181 static LRESULT WINAPI
wndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
183 HWND default_ime_wnd
;
186 case WM_IME_SETCONTEXT
:
189 default_ime_wnd
= get_ime_window();
193 ok(!default_ime_wnd
, "expected no IME windows\n");
196 ok(default_ime_wnd
!= NULL
, "expected IME window existence\n");
199 break; /* do nothing */
201 if (test_phase
== NCCREATE_CANCEL
)
205 default_ime_wnd
= get_ime_window();
210 ok(default_ime_wnd
!= NULL
, "expected IME window existence\n");
213 ok(!default_ime_wnd
, "expected no IME windows\n");
216 break; /* do nothing */
220 default_ime_wnd
= get_ime_window();
225 ok(default_ime_wnd
!= NULL
, "expected IME window existence\n");
228 ok(!default_ime_wnd
, "expected no IME windows\n");
231 break; /* do nothing */
233 if (test_phase
== CREATE_CANCEL
)
238 return DefWindowProcA(hWnd
,msg
,wParam
,lParam
);
241 static BOOL
init(void) {
246 hmod
= GetModuleHandleA("imm32.dll");
247 huser
= GetModuleHandleA("user32");
248 pImmAssociateContextEx
= (void*)GetProcAddress(hmod
, "ImmAssociateContextEx");
249 pImmIsUIMessageA
= (void*)GetProcAddress(hmod
, "ImmIsUIMessageA");
250 pSendInput
= (void*)GetProcAddress(huser
, "SendInput");
252 wc
.cbSize
= sizeof(WNDCLASSEXA
);
254 wc
.lpfnWndProc
= wndProc
;
257 wc
.hInstance
= GetModuleHandleA(NULL
);
258 wc
.hIcon
= LoadIconA(NULL
, (LPCSTR
)IDI_APPLICATION
);
259 wc
.hCursor
= LoadCursorA(NULL
, (LPCSTR
)IDC_ARROW
);
260 wc
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+1);
261 wc
.lpszMenuName
= NULL
;
262 wc
.lpszClassName
= wndcls
;
263 wc
.hIconSm
= LoadIconA(NULL
, (LPCSTR
)IDI_APPLICATION
);
265 if (!RegisterClassExA(&wc
))
268 hwnd
= CreateWindowExA(WS_EX_CLIENTEDGE
, wndcls
, "Wine imm32.dll test",
269 WS_OVERLAPPEDWINDOW
, CW_USEDEFAULT
, CW_USEDEFAULT
,
270 240, 120, NULL
, NULL
, GetModuleHandleW(NULL
), NULL
);
274 imc
= ImmGetContext(hwnd
);
277 win_skip("IME support not implemented\n");
280 ImmReleaseContext(hwnd
, imc
);
282 ShowWindow(hwnd
, SW_SHOWNORMAL
);
290 static void cleanup(void) {
294 UnregisterClassA(wndcls
, GetModuleHandleW(NULL
));
297 static void test_ImmNotifyIME(void) {
298 static const char string
[] = "wine";
299 char resstr
[16] = "";
303 imc
= ImmGetContext(hwnd
);
304 msg_spy_flush_msgs();
306 ret
= ImmNotifyIME(imc
, NI_COMPOSITIONSTR
, CPS_CANCEL
, 0);
309 "Canceling an empty composition string should succeed.\n");
310 ok(!msg_spy_find_msg(WM_IME_COMPOSITION
), "Windows does not post "
311 "WM_IME_COMPOSITION in response to NI_COMPOSITIONSTR / CPS_CANCEL, if "
312 "the composition string being canceled is empty.\n");
314 ImmSetCompositionStringA(imc
, SCS_SETSTR
, string
, sizeof(string
), NULL
, 0);
315 msg_spy_flush_msgs();
317 ImmNotifyIME(imc
, NI_COMPOSITIONSTR
, CPS_CANCEL
, 0);
318 msg_spy_flush_msgs();
320 /* behavior differs between win9x and NT */
321 ret
= ImmGetCompositionStringA(imc
, GCS_COMPSTR
, resstr
, sizeof(resstr
));
322 ok(!ret
, "After being cancelled the composition string is empty.\n");
324 msg_spy_flush_msgs();
326 ret
= ImmNotifyIME(imc
, NI_COMPOSITIONSTR
, CPS_CANCEL
, 0);
329 "Canceling an empty composition string should succeed.\n");
330 ok(!msg_spy_find_msg(WM_IME_COMPOSITION
), "Windows does not post "
331 "WM_IME_COMPOSITION in response to NI_COMPOSITIONSTR / CPS_CANCEL, if "
332 "the composition string being canceled is empty.\n");
334 msg_spy_flush_msgs();
335 ImmReleaseContext(hwnd
, imc
);
337 imc
= ImmCreateContext();
338 ImmDestroyContext(imc
);
340 SetLastError(0xdeadbeef);
341 ret
= ImmNotifyIME((HIMC
)0xdeadcafe, NI_COMPOSITIONSTR
, CPS_CANCEL
, 0);
342 ok (ret
== 0, "Bad IME should return 0\n");
343 ret
= GetLastError();
344 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
345 SetLastError(0xdeadbeef);
346 ret
= ImmNotifyIME(0x00000000, NI_COMPOSITIONSTR
, CPS_CANCEL
, 0);
347 ok (ret
== 0, "NULL IME should return 0\n");
348 ret
= GetLastError();
349 ok(ret
== ERROR_SUCCESS
, "wrong last error %08x!\n", ret
);
350 SetLastError(0xdeadbeef);
351 ret
= ImmNotifyIME(imc
, NI_COMPOSITIONSTR
, CPS_CANCEL
, 0);
352 ok (ret
== 0, "Destroyed IME should return 0\n");
353 ret
= GetLastError();
354 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
358 static void test_ImmGetCompositionString(void)
361 static const WCHAR string
[] = {'w','i','n','e',0x65e5,0x672c,0x8a9e};
367 imc
= ImmGetContext(hwnd
);
368 ImmSetCompositionStringW(imc
, SCS_SETSTR
, string
, sizeof(string
), NULL
,0);
369 alen
= ImmGetCompositionStringA(imc
, GCS_COMPSTR
, cstring
, 20);
370 wlen
= ImmGetCompositionStringW(imc
, GCS_COMPSTR
, wstring
, 20);
371 /* windows machines without any IME installed just return 0 above */
374 len
= ImmGetCompositionStringW(imc
, GCS_COMPATTR
, NULL
, 0);
375 ok(len
*sizeof(WCHAR
)==wlen
,"GCS_COMPATTR(W) not returning correct count\n");
376 len
= ImmGetCompositionStringA(imc
, GCS_COMPATTR
, NULL
, 0);
377 ok(len
==alen
,"GCS_COMPATTR(A) not returning correct count\n");
379 ImmReleaseContext(hwnd
, imc
);
382 static void test_ImmSetCompositionString(void)
387 SetLastError(0xdeadbeef);
388 imc
= ImmGetContext(hwnd
);
389 ok(imc
!= 0, "ImmGetContext() failed. Last error: %u\n", GetLastError());
393 ret
= ImmSetCompositionStringW(imc
, SCS_SETSTR
, NULL
, 0, NULL
, 0);
396 "ImmSetCompositionStringW() failed.\n");
398 ret
= ImmSetCompositionStringW(imc
, SCS_SETSTR
| SCS_CHANGEATTR
,
400 ok(!ret
, "ImmSetCompositionStringW() succeeded.\n");
402 ret
= ImmSetCompositionStringW(imc
, SCS_SETSTR
| SCS_CHANGECLAUSE
,
404 ok(!ret
, "ImmSetCompositionStringW() succeeded.\n");
406 ret
= ImmSetCompositionStringW(imc
, SCS_CHANGEATTR
| SCS_CHANGECLAUSE
,
408 ok(!ret
, "ImmSetCompositionStringW() succeeded.\n");
410 ret
= ImmSetCompositionStringW(imc
, SCS_SETSTR
| SCS_CHANGEATTR
| SCS_CHANGECLAUSE
,
412 ok(!ret
, "ImmSetCompositionStringW() succeeded.\n");
414 ImmReleaseContext(hwnd
, imc
);
417 static void test_ImmIME(void)
421 imc
= ImmGetContext(hwnd
);
425 rc
= ImmConfigureIMEA(imc
, NULL
, IME_CONFIG_REGISTERWORD
, NULL
);
426 ok (rc
== 0, "ImmConfigureIMEA did not fail\n");
427 rc
= ImmConfigureIMEW(imc
, NULL
, IME_CONFIG_REGISTERWORD
, NULL
);
428 ok (rc
== 0, "ImmConfigureIMEW did not fail\n");
430 ImmReleaseContext(hwnd
,imc
);
433 static void test_ImmAssociateContextEx(void)
438 if (!pImmAssociateContextEx
) return;
440 imc
= ImmGetContext(hwnd
);
445 newimc
= ImmCreateContext();
446 ok(newimc
!= imc
, "handles should not be the same\n");
447 rc
= pImmAssociateContextEx(NULL
, NULL
, 0);
448 ok(!rc
, "ImmAssociateContextEx succeeded\n");
449 rc
= pImmAssociateContextEx(hwnd
, NULL
, 0);
450 ok(rc
, "ImmAssociateContextEx failed\n");
451 rc
= pImmAssociateContextEx(NULL
, imc
, 0);
452 ok(!rc
, "ImmAssociateContextEx succeeded\n");
454 rc
= pImmAssociateContextEx(hwnd
, imc
, 0);
455 ok(rc
, "ImmAssociateContextEx failed\n");
456 retimc
= ImmGetContext(hwnd
);
457 ok(retimc
== imc
, "handles should be the same\n");
458 ImmReleaseContext(hwnd
,retimc
);
460 rc
= pImmAssociateContextEx(hwnd
, newimc
, 0);
461 ok(rc
, "ImmAssociateContextEx failed\n");
462 retimc
= ImmGetContext(hwnd
);
463 ok(retimc
== newimc
, "handles should be the same\n");
464 ImmReleaseContext(hwnd
,retimc
);
466 rc
= pImmAssociateContextEx(hwnd
, NULL
, IACE_DEFAULT
);
467 ok(rc
, "ImmAssociateContextEx failed\n");
469 ImmReleaseContext(hwnd
,imc
);
472 typedef struct _igc_threadinfo
{
480 static DWORD WINAPI
ImmGetContextThreadFunc( LPVOID lpParam
)
489 igc_threadinfo
*info
= (igc_threadinfo
*)lpParam
;
490 info
->hwnd
= CreateWindowExA(WS_EX_CLIENTEDGE
, wndcls
, "Wine imm32.dll test",
491 WS_OVERLAPPEDWINDOW
, CW_USEDEFAULT
, CW_USEDEFAULT
,
492 240, 120, NULL
, NULL
, GetModuleHandleW(NULL
), NULL
);
494 h1
= ImmGetContext(hwnd
);
495 ok(info
->himc
== h1
, "hwnd context changed in new thread\n");
496 h2
= ImmGetContext(info
->hwnd
);
497 ok(h2
!= h1
, "new hwnd in new thread should have different context\n");
499 ImmReleaseContext(hwnd
,h1
);
501 hwnd2
= CreateWindowExA(WS_EX_CLIENTEDGE
, wndcls
, "Wine imm32.dll test",
502 WS_OVERLAPPEDWINDOW
, CW_USEDEFAULT
, CW_USEDEFAULT
,
503 240, 120, NULL
, NULL
, GetModuleHandleW(NULL
), NULL
);
504 h1
= ImmGetContext(hwnd2
);
506 ok(h1
== h2
, "Windows in same thread should have same default context\n");
507 ImmReleaseContext(hwnd2
,h1
);
508 ImmReleaseContext(info
->hwnd
,h2
);
509 DestroyWindow(hwnd2
);
511 /* priming for later tests */
512 ImmSetCompositionWindow(h1
, &cf
);
513 ImmSetStatusWindowPos(h1
, &pt
);
514 info
->u_himc
= ImmCreateContext();
515 ImmSetOpenStatus(info
->u_himc
, TRUE
);
517 cdf
.dwStyle
= CFS_CANDIDATEPOS
;
518 cdf
.ptCurrentPos
.x
= 0;
519 cdf
.ptCurrentPos
.y
= 0;
520 ImmSetCandidateWindow(info
->u_himc
, &cdf
);
522 SetEvent(info
->event
);
524 while(GetMessageW(&msg
, 0, 0, 0))
526 TranslateMessage(&msg
);
527 DispatchMessageW(&msg
);
532 static void test_ImmThreads(void)
534 HIMC himc
, otherHimc
, h1
;
535 igc_threadinfo threadinfo
;
542 DWORD status
, sentence
;
545 himc
= ImmGetContext(hwnd
);
546 threadinfo
.event
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
547 threadinfo
.himc
= himc
;
548 hThread
= CreateThread(NULL
, 0, ImmGetContextThreadFunc
, &threadinfo
, 0, &dwThreadId
);
549 WaitForSingleObject(threadinfo
.event
, INFINITE
);
551 otherHimc
= ImmGetContext(threadinfo
.hwnd
);
553 ok(himc
!= otherHimc
, "Windows from other threads should have different himc\n");
554 ok(otherHimc
== threadinfo
.himc
, "Context from other thread should not change in main thread\n");
556 h1
= ImmAssociateContext(hwnd
,otherHimc
);
557 ok(h1
== NULL
, "Should fail to be able to Associate a default context from a different thread\n");
558 h1
= ImmGetContext(hwnd
);
559 ok(h1
== himc
, "Context for window should remain unchanged\n");
560 ImmReleaseContext(hwnd
,h1
);
562 h1
= ImmAssociateContext(hwnd
, threadinfo
.u_himc
);
563 ok (h1
== NULL
, "Should fail to associate a context from a different thread\n");
564 h1
= ImmGetContext(hwnd
);
565 ok(h1
== himc
, "Context for window should remain unchanged\n");
566 ImmReleaseContext(hwnd
,h1
);
568 h1
= ImmAssociateContext(threadinfo
.hwnd
, threadinfo
.u_himc
);
569 ok (h1
== NULL
, "Should fail to associate a context from a different thread into a window from that thread.\n");
570 h1
= ImmGetContext(threadinfo
.hwnd
);
571 ok(h1
== threadinfo
.himc
, "Context for window should remain unchanged\n");
572 ImmReleaseContext(threadinfo
.hwnd
,h1
);
575 rc
= ImmSetOpenStatus(himc
, TRUE
);
576 ok(rc
!= 0, "ImmSetOpenStatus failed\n");
577 rc
= ImmGetOpenStatus(himc
);
578 ok(rc
!= 0, "ImmGetOpenStatus failed\n");
579 rc
= ImmSetOpenStatus(himc
, FALSE
);
580 ok(rc
!= 0, "ImmSetOpenStatus failed\n");
581 rc
= ImmGetOpenStatus(himc
);
582 ok(rc
== 0, "ImmGetOpenStatus failed\n");
584 rc
= ImmSetOpenStatus(otherHimc
, TRUE
);
585 ok(rc
== 0, "ImmSetOpenStatus should fail\n");
586 rc
= ImmSetOpenStatus(threadinfo
.u_himc
, TRUE
);
587 ok(rc
== 0, "ImmSetOpenStatus should fail\n");
588 rc
= ImmGetOpenStatus(otherHimc
);
589 ok(rc
== 0, "ImmGetOpenStatus failed\n");
590 rc
= ImmGetOpenStatus(threadinfo
.u_himc
);
591 ok (rc
== 1 || broken(rc
== 0), "ImmGetOpenStatus should return 1\n");
592 rc
= ImmSetOpenStatus(otherHimc
, FALSE
);
593 ok(rc
== 0, "ImmSetOpenStatus should fail\n");
594 rc
= ImmGetOpenStatus(otherHimc
);
595 ok(rc
== 0, "ImmGetOpenStatus failed\n");
597 /* CompositionFont */
598 rc
= ImmGetCompositionFontA(himc
, &lf
);
599 ok(rc
!= 0, "ImmGetCompositionFont failed\n");
600 rc
= ImmSetCompositionFontA(himc
, &lf
);
601 ok(rc
!= 0, "ImmSetCompositionFont failed\n");
603 rc
= ImmGetCompositionFontA(otherHimc
, &lf
);
604 ok(rc
!= 0 || broken(rc
== 0), "ImmGetCompositionFont failed\n");
605 rc
= ImmGetCompositionFontA(threadinfo
.u_himc
, &lf
);
606 ok(rc
!= 0 || broken(rc
== 0), "ImmGetCompositionFont user himc failed\n");
607 rc
= ImmSetCompositionFontA(otherHimc
, &lf
);
608 ok(rc
== 0, "ImmSetCompositionFont should fail\n");
609 rc
= ImmSetCompositionFontA(threadinfo
.u_himc
, &lf
);
610 ok(rc
== 0, "ImmSetCompositionFont should fail\n");
612 /* CompositionWindow */
613 rc
= ImmSetCompositionWindow(himc
, &cf
);
614 ok(rc
!= 0, "ImmSetCompositionWindow failed\n");
615 rc
= ImmGetCompositionWindow(himc
, &cf
);
616 ok(rc
!= 0, "ImmGetCompositionWindow failed\n");
618 rc
= ImmSetCompositionWindow(otherHimc
, &cf
);
619 ok(rc
== 0, "ImmSetCompositionWindow should fail\n");
620 rc
= ImmSetCompositionWindow(threadinfo
.u_himc
, &cf
);
621 ok(rc
== 0, "ImmSetCompositionWindow should fail\n");
622 rc
= ImmGetCompositionWindow(otherHimc
, &cf
);
623 ok(rc
!= 0 || broken(rc
== 0), "ImmGetCompositionWindow failed\n");
624 rc
= ImmGetCompositionWindow(threadinfo
.u_himc
, &cf
);
625 ok(rc
!= 0 || broken(rc
== 0), "ImmGetCompositionWindow failed\n");
627 /* ConversionStatus */
628 rc
= ImmGetConversionStatus(himc
, &status
, &sentence
);
629 ok(rc
!= 0, "ImmGetConversionStatus failed\n");
630 rc
= ImmSetConversionStatus(himc
, status
, sentence
);
631 ok(rc
!= 0, "ImmSetConversionStatus failed\n");
633 rc
= ImmGetConversionStatus(otherHimc
, &status
, &sentence
);
634 ok(rc
!= 0 || broken(rc
== 0), "ImmGetConversionStatus failed\n");
635 rc
= ImmGetConversionStatus(threadinfo
.u_himc
, &status
, &sentence
);
636 ok(rc
!= 0 || broken(rc
== 0), "ImmGetConversionStatus failed\n");
637 rc
= ImmSetConversionStatus(otherHimc
, status
, sentence
);
638 ok(rc
== 0, "ImmSetConversionStatus should fail\n");
639 rc
= ImmSetConversionStatus(threadinfo
.u_himc
, status
, sentence
);
640 ok(rc
== 0, "ImmSetConversionStatus should fail\n");
642 /* StatusWindowPos */
643 rc
= ImmSetStatusWindowPos(himc
, &pt
);
644 ok(rc
!= 0, "ImmSetStatusWindowPos failed\n");
645 rc
= ImmGetStatusWindowPos(himc
, &pt
);
646 ok(rc
!= 0, "ImmGetStatusWindowPos failed\n");
648 rc
= ImmSetStatusWindowPos(otherHimc
, &pt
);
649 ok(rc
== 0, "ImmSetStatusWindowPos should fail\n");
650 rc
= ImmSetStatusWindowPos(threadinfo
.u_himc
, &pt
);
651 ok(rc
== 0, "ImmSetStatusWindowPos should fail\n");
652 rc
= ImmGetStatusWindowPos(otherHimc
, &pt
);
653 ok(rc
!= 0 || broken(rc
== 0), "ImmGetStatusWindowPos failed\n");
654 rc
= ImmGetStatusWindowPos(threadinfo
.u_himc
, &pt
);
655 ok(rc
!= 0 || broken(rc
== 0), "ImmGetStatusWindowPos failed\n");
657 h1
= ImmAssociateContext(threadinfo
.hwnd
, NULL
);
658 ok (h1
== otherHimc
, "ImmAssociateContext cross thread with NULL should work\n");
659 h1
= ImmGetContext(threadinfo
.hwnd
);
660 ok (h1
== NULL
, "CrossThread window context should be NULL\n");
661 h1
= ImmAssociateContext(threadinfo
.hwnd
, h1
);
662 ok (h1
== NULL
, "Resetting cross thread context should fail\n");
663 h1
= ImmGetContext(threadinfo
.hwnd
);
664 ok (h1
== NULL
, "CrossThread window context should still be NULL\n");
666 rc
= ImmDestroyContext(threadinfo
.u_himc
);
667 ok (rc
== 0, "ImmDestroyContext Cross Thread should fail\n");
669 /* Candidate Window */
670 rc
= ImmGetCandidateWindow(himc
, 0, &cdf
);
671 ok (rc
== 0, "ImmGetCandidateWindow should fail\n");
673 cdf
.dwStyle
= CFS_CANDIDATEPOS
;
674 cdf
.ptCurrentPos
.x
= 0;
675 cdf
.ptCurrentPos
.y
= 0;
676 rc
= ImmSetCandidateWindow(himc
, &cdf
);
677 ok (rc
== 1, "ImmSetCandidateWindow should succeed\n");
678 rc
= ImmGetCandidateWindow(himc
, 0, &cdf
);
679 ok (rc
== 1, "ImmGetCandidateWindow should succeed\n");
681 rc
= ImmGetCandidateWindow(otherHimc
, 0, &cdf
);
682 ok (rc
== 0, "ImmGetCandidateWindow should fail\n");
683 rc
= ImmSetCandidateWindow(otherHimc
, &cdf
);
684 ok (rc
== 0, "ImmSetCandidateWindow should fail\n");
685 rc
= ImmGetCandidateWindow(threadinfo
.u_himc
, 0, &cdf
);
686 ok (rc
== 1 || broken( rc
== 0), "ImmGetCandidateWindow should succeed\n");
687 rc
= ImmSetCandidateWindow(threadinfo
.u_himc
, &cdf
);
688 ok (rc
== 0, "ImmSetCandidateWindow should fail\n");
690 ImmReleaseContext(threadinfo
.hwnd
,otherHimc
);
691 ImmReleaseContext(hwnd
,himc
);
693 SendMessageA(threadinfo
.hwnd
, WM_CLOSE
, 0, 0);
694 rc
= PostThreadMessageA(dwThreadId
, WM_QUIT
, 1, 0);
695 ok(rc
== 1, "PostThreadMessage should succeed\n");
696 WaitForSingleObject(hThread
, INFINITE
);
697 CloseHandle(hThread
);
699 himc
= ImmGetContext(GetDesktopWindow());
700 ok(himc
== NULL
, "Should not be able to get himc from other process window\n");
703 static void test_ImmIsUIMessage(void)
711 static const struct test tests
[] =
713 { WM_MOUSEMOVE
, FALSE
},
714 { WM_IME_STARTCOMPOSITION
, TRUE
},
715 { WM_IME_ENDCOMPOSITION
, TRUE
},
716 { WM_IME_COMPOSITION
, TRUE
},
717 { WM_IME_SETCONTEXT
, TRUE
},
718 { WM_IME_NOTIFY
, TRUE
},
719 { WM_IME_CONTROL
, FALSE
},
720 { WM_IME_COMPOSITIONFULL
, TRUE
},
721 { WM_IME_SELECT
, TRUE
},
722 { WM_IME_CHAR
, FALSE
},
723 { 0x287 /* FIXME */, TRUE
},
724 { WM_IME_REQUEST
, FALSE
},
725 { WM_IME_KEYDOWN
, FALSE
},
726 { WM_IME_KEYUP
, FALSE
},
727 { 0, FALSE
} /* mark the end */
730 UINT WM_MSIME_SERVICE
= RegisterWindowMessageA("MSIMEService");
731 UINT WM_MSIME_RECONVERTOPTIONS
= RegisterWindowMessageA("MSIMEReconvertOptions");
732 UINT WM_MSIME_MOUSE
= RegisterWindowMessageA("MSIMEMouseOperation");
733 UINT WM_MSIME_RECONVERTREQUEST
= RegisterWindowMessageA("MSIMEReconvertRequest");
734 UINT WM_MSIME_RECONVERT
= RegisterWindowMessageA("MSIMEReconvert");
735 UINT WM_MSIME_QUERYPOSITION
= RegisterWindowMessageA("MSIMEQueryPosition");
736 UINT WM_MSIME_DOCUMENTFEED
= RegisterWindowMessageA("MSIMEDocumentFeed");
738 const struct test
*test
;
741 if (!pImmIsUIMessageA
) return;
743 for (test
= tests
; test
->msg
; test
++)
745 msg_spy_flush_msgs();
746 ret
= pImmIsUIMessageA(NULL
, test
->msg
, 0, 0);
747 ok(ret
== test
->ret
, "ImmIsUIMessageA returned %x for %x\n", ret
, test
->msg
);
748 ok(!msg_spy_find_msg(test
->msg
), "Windows does not send 0x%x for NULL hwnd\n", test
->msg
);
750 ret
= pImmIsUIMessageA(hwnd
, test
->msg
, 0, 0);
751 ok(ret
== test
->ret
, "ImmIsUIMessageA returned %x for %x\n", ret
, test
->msg
);
753 ok(msg_spy_find_msg(test
->msg
) != NULL
, "Windows does send 0x%x\n", test
->msg
);
755 ok(!msg_spy_find_msg(test
->msg
), "Windows does not send 0x%x\n", test
->msg
);
758 ret
= pImmIsUIMessageA(NULL
, WM_MSIME_SERVICE
, 0, 0);
759 ok(!ret
, "ImmIsUIMessageA returned TRUE for WM_MSIME_SERVICE\n");
760 ret
= pImmIsUIMessageA(NULL
, WM_MSIME_RECONVERTOPTIONS
, 0, 0);
761 ok(!ret
, "ImmIsUIMessageA returned TRUE for WM_MSIME_RECONVERTOPTIONS\n");
762 ret
= pImmIsUIMessageA(NULL
, WM_MSIME_MOUSE
, 0, 0);
763 ok(!ret
, "ImmIsUIMessageA returned TRUE for WM_MSIME_MOUSE\n");
764 ret
= pImmIsUIMessageA(NULL
, WM_MSIME_RECONVERTREQUEST
, 0, 0);
765 ok(!ret
, "ImmIsUIMessageA returned TRUE for WM_MSIME_RECONVERTREQUEST\n");
766 ret
= pImmIsUIMessageA(NULL
, WM_MSIME_RECONVERT
, 0, 0);
767 ok(!ret
, "ImmIsUIMessageA returned TRUE for WM_MSIME_RECONVERT\n");
768 ret
= pImmIsUIMessageA(NULL
, WM_MSIME_QUERYPOSITION
, 0, 0);
769 ok(!ret
, "ImmIsUIMessageA returned TRUE for WM_MSIME_QUERYPOSITION\n");
770 ret
= pImmIsUIMessageA(NULL
, WM_MSIME_DOCUMENTFEED
, 0, 0);
771 ok(!ret
, "ImmIsUIMessageA returned TRUE for WM_MSIME_DOCUMENTFEED\n");
774 static void test_ImmGetContext(void)
779 SetLastError(0xdeadbeef);
780 himc
= ImmGetContext((HWND
)0xffffffff);
781 err
= GetLastError();
782 ok(himc
== NULL
, "ImmGetContext succeeded\n");
783 ok(err
== ERROR_INVALID_WINDOW_HANDLE
, "got %u\n", err
);
785 himc
= ImmGetContext(hwnd
);
786 ok(himc
!= NULL
, "ImmGetContext failed\n");
787 ok(ImmReleaseContext(hwnd
, himc
), "ImmReleaseContext failed\n");
790 static void test_ImmGetDescription(void)
797 /* FIXME: invalid keyboard layouts should not pass */
798 ret
= ImmGetDescriptionW(NULL
, NULL
, 0);
799 ok(!ret
, "ImmGetDescriptionW failed, expected 0 received %d.\n", ret
);
800 ret
= ImmGetDescriptionA(NULL
, NULL
, 0);
801 ok(!ret
, "ImmGetDescriptionA failed, expected 0 received %d.\n", ret
);
803 /* load a language with valid IMM descriptions */
804 hkl
= GetKeyboardLayout(0);
805 ok(hkl
!= 0, "GetKeyboardLayout failed, expected != 0.\n");
807 ret
= ImmGetDescriptionW(hkl
, NULL
, 0);
810 win_skip("ImmGetDescriptionW is not working for current loaded keyboard.\n");
814 SetLastError(0xdeadcafe);
815 ret
= ImmGetDescriptionW(0, NULL
, 100);
816 ok (ret
== 0, "ImmGetDescriptionW with 0 hkl should return 0\n");
817 ret
= GetLastError();
818 ok (ret
== 0xdeadcafe, "Last Error should remain unchanged\n");
820 ret
= ImmGetDescriptionW(hkl
, descW
, 0);
821 ok(ret
, "ImmGetDescriptionW failed, expected != 0 received 0.\n");
823 lret
= ImmGetDescriptionW(hkl
, descW
, ret
+ 1);
824 ok(lret
, "ImmGetDescriptionW failed, expected != 0 received 0.\n");
825 ok(lret
== ret
, "ImmGetDescriptionW failed to return the correct amount of data. Expected %d, got %d.\n", ret
, lret
);
827 lret
= ImmGetDescriptionA(hkl
, descA
, ret
+ 1);
828 ok(lret
, "ImmGetDescriptionA failed, expected != 0 received 0.\n");
829 ok(lret
== ret
, "ImmGetDescriptionA failed to return the correct amount of data. Expected %d, got %d.\n", ret
, lret
);
831 ret
/= 2; /* try to copy partially */
832 lret
= ImmGetDescriptionW(hkl
, descW
, ret
+ 1);
833 ok(lret
, "ImmGetDescriptionW failed, expected != 0 received 0.\n");
834 ok(lret
== ret
, "ImmGetDescriptionW failed to return the correct amount of data. Expected %d, got %d.\n", ret
, lret
);
836 lret
= ImmGetDescriptionA(hkl
, descA
, ret
+ 1);
837 ok(!lret
, "ImmGetDescriptionA should fail\n");
839 ret
= ImmGetDescriptionW(hkl
, descW
, 1);
840 ok(!ret
, "ImmGetDescriptionW failed, expected 0 received %d.\n", ret
);
842 UnloadKeyboardLayout(hkl
);
845 static LRESULT (WINAPI
*old_imm_wnd_proc
)(HWND
, UINT
, WPARAM
, LPARAM
);
846 static LRESULT WINAPI
imm_wnd_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
848 ok(msg
!= WM_DESTROY
, "got WM_DESTROY message\n");
849 return old_imm_wnd_proc(hwnd
, msg
, wparam
, lparam
);
852 static HWND thread_ime_wnd
;
853 static DWORD WINAPI
test_ImmGetDefaultIMEWnd_thread(void *arg
)
855 CreateWindowA("static", "static", WS_POPUP
, 0, 0, 1, 1, NULL
, NULL
, NULL
, NULL
);
857 thread_ime_wnd
= ImmGetDefaultIMEWnd(0);
858 ok(thread_ime_wnd
!= 0, "ImmGetDefaultIMEWnd returned NULL\n");
859 old_imm_wnd_proc
= (void*)SetWindowLongPtrW(thread_ime_wnd
, GWLP_WNDPROC
, (LONG_PTR
)imm_wnd_proc
);
863 static void test_ImmDefaultHwnd(void)
865 HIMC imc1
, imc2
, imc3
;
872 hwnd
= CreateWindowExA(WS_EX_CLIENTEDGE
, "EDIT", "Wine imm32.dll test",
873 WS_OVERLAPPEDWINDOW
, CW_USEDEFAULT
, CW_USEDEFAULT
,
874 240, 120, NULL
, NULL
, GetModuleHandleW(NULL
), NULL
);
876 ShowWindow(hwnd
, SW_SHOWNORMAL
);
878 imc1
= ImmGetContext(hwnd
);
881 win_skip("IME support not implemented\n");
885 def1
= ImmGetDefaultIMEWnd(hwnd
);
887 GetWindowTextA(def1
, title
, sizeof(title
));
888 ok(!strcmp(title
, "Default IME"), "got %s\n", title
);
889 style
= GetWindowLongA(def1
, GWL_STYLE
);
890 ok(style
== (WS_DISABLED
| WS_POPUP
| WS_CLIPSIBLINGS
), "got %08x\n", style
);
891 style
= GetWindowLongA(def1
, GWL_EXSTYLE
);
892 ok(style
== 0, "got %08x\n", style
);
894 imc2
= ImmCreateContext();
895 ImmSetOpenStatus(imc2
, TRUE
);
897 imc3
= ImmGetContext(hwnd
);
898 def3
= ImmGetDefaultIMEWnd(hwnd
);
900 ok(def3
== def1
, "Default IME window should not change\n");
901 ok(imc1
== imc3
, "IME context should not change\n");
902 ImmSetOpenStatus(imc2
, FALSE
);
904 thread
= CreateThread(NULL
, 0, test_ImmGetDefaultIMEWnd_thread
, NULL
, 0, NULL
);
905 WaitForSingleObject(thread
, INFINITE
);
906 ok(thread_ime_wnd
!= def1
, "thread_ime_wnd == def1\n");
907 ok(!IsWindow(thread_ime_wnd
), "thread_ime_wnd was not destroyed\n");
910 ImmReleaseContext(hwnd
, imc1
);
911 ImmReleaseContext(hwnd
, imc3
);
912 ImmDestroyContext(imc2
);
916 static BOOL CALLBACK
is_ime_window_proc(HWND hWnd
, LPARAM param
)
918 static const WCHAR imeW
[] = {'I','M','E',0};
919 WCHAR class_nameW
[16];
920 HWND
*ime_window
= (HWND
*)param
;
921 if (GetClassNameW(hWnd
, class_nameW
, sizeof(class_nameW
)/sizeof(class_nameW
[0])) &&
922 !lstrcmpW(class_nameW
, imeW
)) {
929 static HWND
get_ime_window(void)
931 HWND ime_window
= NULL
;
932 EnumThreadWindows(GetCurrentThreadId(), is_ime_window_proc
, (LPARAM
)&ime_window
);
936 struct testcase_ime_window
{
938 BOOL top_level_window
;
941 static DWORD WINAPI
test_default_ime_window_cb(void *arg
)
943 struct testcase_ime_window
*testcase
= (struct testcase_ime_window
*)arg
;
944 DWORD visible
= testcase
->visible
? WS_VISIBLE
: 0;
945 HWND hwnd1
, hwnd2
, default_ime_wnd
, ime_wnd
;
947 ok(!get_ime_window(), "Expected no IME windows\n");
948 if (testcase
->top_level_window
) {
949 test_phase
= FIRST_WINDOW
;
950 hwnd1
= CreateWindowExA(WS_EX_CLIENTEDGE
, wndcls
, "Wine imm32.dll test",
951 WS_OVERLAPPEDWINDOW
| visible
,
952 CW_USEDEFAULT
, CW_USEDEFAULT
,
953 240, 120, NULL
, NULL
, GetModuleHandleW(NULL
), NULL
);
956 hwnd1
= CreateWindowExA(WS_EX_CLIENTEDGE
, "EDIT", "Wine imm32.dll test",
958 CW_USEDEFAULT
, CW_USEDEFAULT
,
959 240, 24, hwnd
, NULL
, GetModuleHandleW(NULL
), NULL
);
961 ime_wnd
= get_ime_window();
962 ok(ime_wnd
!= NULL
, "Expected IME window existence\n");
963 default_ime_wnd
= ImmGetDefaultIMEWnd(hwnd1
);
964 ok(ime_wnd
== default_ime_wnd
, "Expected %p, got %p\n", ime_wnd
, default_ime_wnd
);
966 test_phase
= SECOND_WINDOW
;
967 hwnd2
= CreateWindowExA(WS_EX_CLIENTEDGE
, wndcls
, "Wine imm32.dll test",
968 WS_OVERLAPPEDWINDOW
| visible
,
969 CW_USEDEFAULT
, CW_USEDEFAULT
,
970 240, 120, NULL
, NULL
, GetModuleHandleW(NULL
), NULL
);
971 DestroyWindow(hwnd2
);
972 ok(IsWindow(ime_wnd
) ||
973 broken(!testcase
->visible
/* Vista */) ||
974 broken(!testcase
->top_level_window
/* Vista */) ,
975 "Expected IME window existence\n");
976 DestroyWindow(hwnd1
);
977 ok(!IsWindow(ime_wnd
), "Expected no IME windows\n");
981 static DWORD WINAPI
test_default_ime_window_cancel_cb(void *arg
)
983 struct testcase_ime_window
*testcase
= (struct testcase_ime_window
*)arg
;
984 DWORD visible
= testcase
->visible
? WS_VISIBLE
: 0;
985 HWND hwnd1
, hwnd2
, default_ime_wnd
, ime_wnd
;
987 ok(!get_ime_window(), "Expected no IME windows\n");
988 test_phase
= NCCREATE_CANCEL
;
989 hwnd1
= CreateWindowExA(WS_EX_CLIENTEDGE
, wndcls
, "Wine imm32.dll test",
990 WS_OVERLAPPEDWINDOW
| visible
,
991 CW_USEDEFAULT
, CW_USEDEFAULT
,
992 240, 120, NULL
, NULL
, GetModuleHandleW(NULL
), NULL
);
993 ok(hwnd1
== NULL
, "creation succeeded, got %p\n", hwnd1
);
994 ok(!get_ime_window(), "Expected no IME windows\n");
996 test_phase
= CREATE_CANCEL
;
997 hwnd1
= CreateWindowExA(WS_EX_CLIENTEDGE
, wndcls
, "Wine imm32.dll test",
998 WS_OVERLAPPEDWINDOW
| visible
,
999 CW_USEDEFAULT
, CW_USEDEFAULT
,
1000 240, 120, NULL
, NULL
, GetModuleHandleW(NULL
), NULL
);
1001 ok(hwnd1
== NULL
, "creation succeeded, got %p\n", hwnd1
);
1002 ok(!get_ime_window(), "Expected no IME windows\n");
1004 test_phase
= FIRST_WINDOW
;
1005 hwnd2
= CreateWindowExA(WS_EX_CLIENTEDGE
, wndcls
, "Wine imm32.dll test",
1006 WS_OVERLAPPEDWINDOW
| visible
,
1007 CW_USEDEFAULT
, CW_USEDEFAULT
,
1008 240, 120, NULL
, NULL
, GetModuleHandleW(NULL
), NULL
);
1009 ime_wnd
= get_ime_window();
1010 ok(ime_wnd
!= NULL
, "Expected IME window existence\n");
1011 default_ime_wnd
= ImmGetDefaultIMEWnd(hwnd2
);
1012 ok(ime_wnd
== default_ime_wnd
, "Expected %p, got %p\n", ime_wnd
, default_ime_wnd
);
1014 DestroyWindow(hwnd2
);
1015 ok(!IsWindow(ime_wnd
), "Expected no IME windows\n");
1019 static DWORD WINAPI
test_default_ime_disabled_cb(void *arg
)
1021 HWND hWnd
, default_ime_wnd
;
1023 ok(!get_ime_window(), "Expected no IME windows\n");
1024 ImmDisableIME(GetCurrentThreadId());
1025 test_phase
= IME_DISABLED
;
1026 hWnd
= CreateWindowExA(WS_EX_CLIENTEDGE
, wndcls
, "Wine imm32.dll test",
1027 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
1028 CW_USEDEFAULT
, CW_USEDEFAULT
,
1029 240, 120, NULL
, NULL
, GetModuleHandleW(NULL
), NULL
);
1030 default_ime_wnd
= ImmGetDefaultIMEWnd(hWnd
);
1031 ok(!default_ime_wnd
, "Expected no IME windows\n");
1032 DestroyWindow(hWnd
);
1036 static DWORD WINAPI
test_default_ime_with_message_only_window_cb(void *arg
)
1038 HWND hwnd1
, hwnd2
, default_ime_wnd
;
1040 test_phase
= PHASE_UNKNOWN
;
1041 hwnd1
= CreateWindowA(wndcls
, "Wine imm32.dll test",
1042 WS_OVERLAPPEDWINDOW
,
1043 CW_USEDEFAULT
, CW_USEDEFAULT
,
1044 240, 120, HWND_MESSAGE
, NULL
, GetModuleHandleW(NULL
), NULL
);
1045 default_ime_wnd
= ImmGetDefaultIMEWnd(hwnd1
);
1046 ok(!IsWindow(default_ime_wnd
), "Expected no IME windows, got %p\n", default_ime_wnd
);
1048 hwnd2
= CreateWindowA(wndcls
, "Wine imm32.dll test",
1049 WS_OVERLAPPEDWINDOW
,
1050 CW_USEDEFAULT
, CW_USEDEFAULT
,
1051 240, 120, hwnd1
, NULL
, GetModuleHandleW(NULL
), NULL
);
1052 default_ime_wnd
= ImmGetDefaultIMEWnd(hwnd2
);
1053 ok(IsWindow(default_ime_wnd
), "Expected IME window existance\n");
1055 DestroyWindow(hwnd2
);
1056 DestroyWindow(hwnd1
);
1058 hwnd1
= CreateWindowA(wndcls
, "Wine imm32.dll test",
1059 WS_OVERLAPPEDWINDOW
,
1060 CW_USEDEFAULT
, CW_USEDEFAULT
,
1061 240, 120, NULL
, NULL
, GetModuleHandleW(NULL
), NULL
);
1062 default_ime_wnd
= ImmGetDefaultIMEWnd(hwnd1
);
1063 ok(IsWindow(default_ime_wnd
), "Expected IME window existence\n");
1064 SetParent(hwnd1
, HWND_MESSAGE
);
1065 default_ime_wnd
= ImmGetDefaultIMEWnd(hwnd1
);
1066 ok(IsWindow(default_ime_wnd
), "Expected IME window existence\n");
1067 DestroyWindow(hwnd1
);
1071 static void test_default_ime_window_creation(void)
1075 struct testcase_ime_window testcases
[] = {
1076 /* visible, top-level window */
1083 for (i
= 0; i
< sizeof(testcases
)/sizeof(testcases
[0]); i
++)
1085 thread
= CreateThread(NULL
, 0, test_default_ime_window_cb
, &testcases
[i
], 0, NULL
);
1086 ok(thread
!= NULL
, "CreateThread failed with error %u\n", GetLastError());
1087 while (MsgWaitForMultipleObjects(1, &thread
, FALSE
, INFINITE
, QS_ALLINPUT
) == WAIT_OBJECT_0
+ 1)
1090 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
1092 TranslateMessage(&msg
);
1093 DispatchMessageA(&msg
);
1096 CloseHandle(thread
);
1098 if (testcases
[i
].top_level_window
)
1100 thread
= CreateThread(NULL
, 0, test_default_ime_window_cancel_cb
, &testcases
[i
], 0, NULL
);
1101 ok(thread
!= NULL
, "CreateThread failed with error %u\n", GetLastError());
1102 WaitForSingleObject(thread
, INFINITE
);
1103 CloseHandle(thread
);
1107 thread
= CreateThread(NULL
, 0, test_default_ime_disabled_cb
, NULL
, 0, NULL
);
1108 WaitForSingleObject(thread
, INFINITE
);
1109 CloseHandle(thread
);
1111 thread
= CreateThread(NULL
, 0, test_default_ime_with_message_only_window_cb
, NULL
, 0, NULL
);
1112 WaitForSingleObject(thread
, INFINITE
);
1113 CloseHandle(thread
);
1115 test_phase
= PHASE_UNKNOWN
;
1118 static void test_ImmGetIMCLockCount(void)
1121 DWORD count
, ret
, i
;
1124 imc
= ImmCreateContext();
1125 ImmDestroyContext(imc
);
1126 SetLastError(0xdeadbeef);
1127 count
= ImmGetIMCLockCount((HIMC
)0xdeadcafe);
1128 ok(count
== 0, "Invalid IMC should return 0\n");
1129 ret
= GetLastError();
1130 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1131 SetLastError(0xdeadbeef);
1132 count
= ImmGetIMCLockCount(0x00000000);
1133 ok(count
== 0, "NULL IMC should return 0\n");
1134 ret
= GetLastError();
1135 ok(ret
== 0xdeadbeef, "Last Error should remain unchanged: %08x\n",ret
);
1136 count
= ImmGetIMCLockCount(imc
);
1137 ok(count
== 0, "Destroyed IMC should return 0\n");
1138 ret
= GetLastError();
1139 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1141 imc
= ImmCreateContext();
1142 count
= ImmGetIMCLockCount(imc
);
1143 ok(count
== 0, "expect 0, returned %d\n", count
);
1144 ic
= ImmLockIMC(imc
);
1145 ok(ic
!= NULL
, "ImmLockIMC failed!\n");
1146 count
= ImmGetIMCLockCount(imc
);
1147 ok(count
== 1, "expect 1, returned %d\n", count
);
1148 ret
= ImmUnlockIMC(imc
);
1149 ok(ret
== TRUE
, "expect TRUE, ret %d\n", ret
);
1150 count
= ImmGetIMCLockCount(imc
);
1151 ok(count
== 0, "expect 0, returned %d\n", count
);
1152 ret
= ImmUnlockIMC(imc
);
1153 ok(ret
== TRUE
, "expect TRUE, ret %d\n", ret
);
1154 count
= ImmGetIMCLockCount(imc
);
1155 ok(count
== 0, "expect 0, returned %d\n", count
);
1157 for (i
= 0; i
< GMEM_LOCKCOUNT
* 2; i
++)
1159 ic
= ImmLockIMC(imc
);
1160 ok(ic
!= NULL
, "ImmLockIMC failed!\n");
1162 count
= ImmGetIMCLockCount(imc
);
1163 todo_wine
ok(count
== GMEM_LOCKCOUNT
, "expect GMEM_LOCKCOUNT, returned %d\n", count
);
1165 for (i
= 0; i
< GMEM_LOCKCOUNT
- 1; i
++)
1167 count
= ImmGetIMCLockCount(imc
);
1168 todo_wine
ok(count
== 1, "expect 1, returned %d\n", count
);
1170 count
= ImmGetIMCLockCount(imc
);
1171 todo_wine
ok(count
== 0, "expect 0, returned %d\n", count
);
1173 ImmDestroyContext(imc
);
1176 static void test_ImmGetIMCCLockCount(void)
1179 DWORD count
, g_count
, i
;
1183 imcc
= ImmCreateIMCC(sizeof(CANDIDATEINFO
));
1184 count
= ImmGetIMCCLockCount(imcc
);
1185 ok(count
== 0, "expect 0, returned %d\n", count
);
1187 count
= ImmGetIMCCLockCount(imcc
);
1188 ok(count
== 1, "expect 1, returned %d\n", count
);
1189 ret
= ImmUnlockIMCC(imcc
);
1190 ok(ret
== FALSE
, "expect FALSE, ret %d\n", ret
);
1191 count
= ImmGetIMCCLockCount(imcc
);
1192 ok(count
== 0, "expect 0, returned %d\n", count
);
1193 ret
= ImmUnlockIMCC(imcc
);
1194 ok(ret
== FALSE
, "expect FALSE, ret %d\n", ret
);
1195 count
= ImmGetIMCCLockCount(imcc
);
1196 ok(count
== 0, "expect 0, returned %d\n", count
);
1198 p
= ImmLockIMCC(imcc
);
1199 ok(GlobalHandle(p
) == imcc
, "expect %p, returned %p\n", imcc
, GlobalHandle(p
));
1201 for (i
= 0; i
< GMEM_LOCKCOUNT
* 2; i
++)
1204 count
= ImmGetIMCCLockCount(imcc
);
1205 g_count
= GlobalFlags(imcc
) & GMEM_LOCKCOUNT
;
1206 ok(count
== g_count
, "count %d, g_count %d\n", count
, g_count
);
1208 count
= ImmGetIMCCLockCount(imcc
);
1209 ok(count
== GMEM_LOCKCOUNT
, "expect GMEM_LOCKCOUNT, returned %d\n", count
);
1211 for (i
= 0; i
< GMEM_LOCKCOUNT
- 1; i
++)
1213 count
= ImmGetIMCCLockCount(imcc
);
1214 ok(count
== 1, "expect 1, returned %d\n", count
);
1216 count
= ImmGetIMCCLockCount(imcc
);
1217 ok(count
== 0, "expect 0, returned %d\n", count
);
1219 ImmDestroyIMCC(imcc
);
1222 static void test_ImmDestroyContext(void)
1228 imc
= ImmCreateContext();
1229 count
= ImmGetIMCLockCount(imc
);
1230 ok(count
== 0, "expect 0, returned %d\n", count
);
1231 ic
= ImmLockIMC(imc
);
1232 ok(ic
!= NULL
, "ImmLockIMC failed!\n");
1233 count
= ImmGetIMCLockCount(imc
);
1234 ok(count
== 1, "expect 1, returned %d\n", count
);
1235 ret
= ImmDestroyContext(imc
);
1236 ok(ret
== TRUE
, "Destroy a locked IMC should success!\n");
1237 ic
= ImmLockIMC(imc
);
1238 ok(ic
== NULL
, "Lock a destroyed IMC should fail!\n");
1239 ret
= ImmUnlockIMC(imc
);
1240 ok(ret
== FALSE
, "Unlock a destroyed IMC should fail!\n");
1241 count
= ImmGetIMCLockCount(imc
);
1242 ok(count
== 0, "Get lock count of a destroyed IMC should return 0!\n");
1243 SetLastError(0xdeadbeef);
1244 ret
= ImmDestroyContext(imc
);
1245 ok(ret
== FALSE
, "Destroy a destroyed IMC should fail!\n");
1246 ret
= GetLastError();
1247 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1250 static void test_ImmDestroyIMCC(void)
1253 DWORD ret
, count
, size
;
1256 imcc
= ImmCreateIMCC(sizeof(CANDIDATEINFO
));
1257 count
= ImmGetIMCCLockCount(imcc
);
1258 ok(count
== 0, "expect 0, returned %d\n", count
);
1259 p
= ImmLockIMCC(imcc
);
1260 ok(p
!= NULL
, "ImmLockIMCC failed!\n");
1261 count
= ImmGetIMCCLockCount(imcc
);
1262 ok(count
== 1, "expect 1, returned %d\n", count
);
1263 size
= ImmGetIMCCSize(imcc
);
1264 ok(size
== sizeof(CANDIDATEINFO
), "returned %d\n", size
);
1265 p
= ImmDestroyIMCC(imcc
);
1266 ok(p
== NULL
, "Destroy a locked IMCC should success!\n");
1267 p
= ImmLockIMCC(imcc
);
1268 ok(p
== NULL
, "Lock a destroyed IMCC should fail!\n");
1269 ret
= ImmUnlockIMCC(imcc
);
1270 ok(ret
== FALSE
, "Unlock a destroyed IMCC should return FALSE!\n");
1271 count
= ImmGetIMCCLockCount(imcc
);
1272 ok(count
== 0, "Get lock count of a destroyed IMCC should return 0!\n");
1273 size
= ImmGetIMCCSize(imcc
);
1274 ok(size
== 0, "Get size of a destroyed IMCC should return 0!\n");
1275 SetLastError(0xdeadbeef);
1276 p
= ImmDestroyIMCC(imcc
);
1277 ok(p
!= NULL
, "returned NULL\n");
1278 ret
= GetLastError();
1279 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1282 static void test_ImmMessages(void)
1290 LPINPUTCONTEXT lpIMC
;
1291 LPTRANSMSG lpTransMsg
;
1293 HWND hwnd
= CreateWindowExA(WS_EX_CLIENTEDGE
, "EDIT", "Wine imm32.dll test",
1294 WS_OVERLAPPEDWINDOW
, CW_USEDEFAULT
, CW_USEDEFAULT
,
1295 240, 120, NULL
, NULL
, GetModuleHandleA(NULL
), NULL
);
1297 ShowWindow(hwnd
, SW_SHOWNORMAL
);
1298 defwnd
= ImmGetDefaultIMEWnd(hwnd
);
1299 imc
= ImmGetContext(hwnd
);
1301 ImmSetOpenStatus(imc
, TRUE
);
1302 msg_spy_flush_msgs();
1303 SendMessageA(defwnd
, WM_IME_CONTROL
, IMC_GETCANDIDATEPOS
, (LPARAM
)&cf
);
1306 msg
= msg_spy_find_next_msg(WM_IME_CONTROL
,&idx
);
1307 if (msg
) ok(!msg
->post
, "Message should not be posted\n");
1309 msg_spy_flush_msgs();
1311 lpIMC
= ImmLockIMC(imc
);
1312 lpIMC
->hMsgBuf
= ImmReSizeIMCC(lpIMC
->hMsgBuf
, (lpIMC
->dwNumMsgBuf
+ 1) * sizeof(TRANSMSG
));
1313 lpTransMsg
= ImmLockIMCC(lpIMC
->hMsgBuf
);
1314 lpTransMsg
+= lpIMC
->dwNumMsgBuf
;
1315 lpTransMsg
->message
= WM_IME_STARTCOMPOSITION
;
1316 lpTransMsg
->wParam
= 0;
1317 lpTransMsg
->lParam
= 0;
1318 ImmUnlockIMCC(lpIMC
->hMsgBuf
);
1319 lpIMC
->dwNumMsgBuf
++;
1321 ImmGenerateMessage(imc
);
1325 msg
= msg_spy_find_next_msg(WM_IME_STARTCOMPOSITION
, &idx
);
1326 if (msg
) ok(!msg
->post
, "Message should not be posted\n");
1328 msg_spy_flush_msgs();
1330 lpIMC
= ImmLockIMC(imc
);
1331 lpIMC
->hMsgBuf
= ImmReSizeIMCC(lpIMC
->hMsgBuf
, (lpIMC
->dwNumMsgBuf
+ 1) * sizeof(TRANSMSG
));
1332 lpTransMsg
= ImmLockIMCC(lpIMC
->hMsgBuf
);
1333 lpTransMsg
+= lpIMC
->dwNumMsgBuf
;
1334 lpTransMsg
->message
= WM_IME_COMPOSITION
;
1335 lpTransMsg
->wParam
= 0;
1336 lpTransMsg
->lParam
= 0;
1337 ImmUnlockIMCC(lpIMC
->hMsgBuf
);
1338 lpIMC
->dwNumMsgBuf
++;
1340 ImmGenerateMessage(imc
);
1344 msg
= msg_spy_find_next_msg(WM_IME_COMPOSITION
, &idx
);
1345 if (msg
) ok(!msg
->post
, "Message should not be posted\n");
1347 msg_spy_flush_msgs();
1349 lpIMC
= ImmLockIMC(imc
);
1350 lpIMC
->hMsgBuf
= ImmReSizeIMCC(lpIMC
->hMsgBuf
, (lpIMC
->dwNumMsgBuf
+ 1) * sizeof(TRANSMSG
));
1351 lpTransMsg
= ImmLockIMCC(lpIMC
->hMsgBuf
);
1352 lpTransMsg
+= lpIMC
->dwNumMsgBuf
;
1353 lpTransMsg
->message
= WM_IME_ENDCOMPOSITION
;
1354 lpTransMsg
->wParam
= 0;
1355 lpTransMsg
->lParam
= 0;
1356 ImmUnlockIMCC(lpIMC
->hMsgBuf
);
1357 lpIMC
->dwNumMsgBuf
++;
1359 ImmGenerateMessage(imc
);
1363 msg
= msg_spy_find_next_msg(WM_IME_ENDCOMPOSITION
, &idx
);
1364 if (msg
) ok(!msg
->post
, "Message should not be posted\n");
1366 msg_spy_flush_msgs();
1368 ImmSetOpenStatus(imc
, FALSE
);
1369 ImmReleaseContext(hwnd
, imc
);
1370 DestroyWindow(hwnd
);
1373 static LRESULT CALLBACK
processkey_wnd_proc( HWND hWnd
, UINT msg
, WPARAM wParam
,
1376 return DefWindowProcW(hWnd
, msg
, wParam
, lParam
);
1379 static void test_ime_processkey(void)
1381 WCHAR classNameW
[] = {'P','r','o','c','e','s','s', 'K','e','y','T','e','s','t','C','l','a','s','s',0};
1382 WCHAR windowNameW
[] = {'P','r','o','c','e','s','s', 'K','e','y',0};
1386 HANDLE hInstance
= GetModuleHandleW(NULL
);
1387 TEST_INPUT inputs
[2];
1392 wclass
.lpszClassName
= classNameW
;
1393 wclass
.style
= CS_HREDRAW
| CS_VREDRAW
;
1394 wclass
.lpfnWndProc
= processkey_wnd_proc
;
1395 wclass
.hInstance
= hInstance
;
1396 wclass
.hIcon
= LoadIconW(0, (LPCWSTR
)IDI_APPLICATION
);
1397 wclass
.hCursor
= LoadCursorW( NULL
, (LPCWSTR
)IDC_ARROW
);
1398 wclass
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
1399 wclass
.lpszMenuName
= 0;
1400 wclass
.cbClsExtra
= 0;
1401 wclass
.cbWndExtra
= 0;
1402 if(!RegisterClassW(&wclass
)){
1403 win_skip("Failed to register window.\n");
1407 /* create the test window that will receive the keystrokes */
1408 hWndTest
= CreateWindowW(wclass
.lpszClassName
, windowNameW
,
1409 WS_OVERLAPPEDWINDOW
, CW_USEDEFAULT
, 0, 100, 100,
1410 NULL
, NULL
, hInstance
, NULL
);
1412 ShowWindow(hWndTest
, SW_SHOW
);
1413 SetWindowPos(hWndTest
, HWND_TOPMOST
, 0, 0, 0, 0, SWP_NOSIZE
|SWP_NOMOVE
);
1414 SetForegroundWindow(hWndTest
);
1415 UpdateWindow(hWndTest
);
1417 imc
= ImmGetContext(hWndTest
);
1420 win_skip("IME not supported\n");
1421 DestroyWindow(hWndTest
);
1425 rc
= ImmSetOpenStatus(imc
, TRUE
);
1428 win_skip("Unable to open IME\n");
1429 ImmReleaseContext(hWndTest
, imc
);
1430 DestroyWindow(hWndTest
);
1434 /* flush pending messages */
1435 while (PeekMessageW(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW(&msg
);
1439 /* init input data that never changes */
1440 inputs
[1].type
= inputs
[0].type
= INPUT_KEYBOARD
;
1441 inputs
[1].u
.ki
.dwExtraInfo
= inputs
[0].u
.ki
.dwExtraInfo
= 0;
1442 inputs
[1].u
.ki
.time
= inputs
[0].u
.ki
.time
= 0;
1444 /* Pressing a key */
1445 inputs
[0].u
.ki
.wVk
= 0x41;
1446 inputs
[0].u
.ki
.wScan
= 0x1e;
1447 inputs
[0].u
.ki
.dwFlags
= 0x0;
1449 pSendInput(1, (INPUT
*)inputs
, sizeof(INPUT
));
1451 while(PeekMessageW(&msg
, hWndTest
, 0, 0, PM_NOREMOVE
)) {
1452 if(msg
.message
!= WM_KEYDOWN
)
1453 PeekMessageW(&msg
, hWndTest
, 0, 0, PM_REMOVE
);
1456 ok(msg
.wParam
!= VK_PROCESSKEY
,"Incorrect ProcessKey Found\n");
1457 PeekMessageW(&msg
, hWndTest
, 0, 0, PM_REMOVE
);
1458 if(msg
.wParam
== VK_PROCESSKEY
)
1459 trace("ProcessKey was correctly found\n");
1461 TranslateMessage(&msg
);
1462 DispatchMessageW(&msg
);
1465 inputs
[0].u
.ki
.wVk
= 0x41;
1466 inputs
[0].u
.ki
.wScan
= 0x1e;
1467 inputs
[0].u
.ki
.dwFlags
= KEYEVENTF_KEYUP
;
1469 pSendInput(1, (INPUT
*)inputs
, sizeof(INPUT
));
1471 while(PeekMessageW(&msg
, hWndTest
, 0, 0, PM_NOREMOVE
)) {
1472 if(msg
.message
!= WM_KEYUP
)
1473 PeekMessageW(&msg
, hWndTest
, 0, 0, PM_REMOVE
);
1476 ok(msg
.wParam
!= VK_PROCESSKEY
,"Incorrect ProcessKey Found\n");
1477 PeekMessageW(&msg
, hWndTest
, 0, 0, PM_REMOVE
);
1478 ok(msg
.wParam
!= VK_PROCESSKEY
,"ProcessKey should still not be Found\n");
1480 TranslateMessage(&msg
);
1481 DispatchMessageW(&msg
);
1484 ImmReleaseContext(hWndTest
, imc
);
1485 ImmSetOpenStatus(imc
, FALSE
);
1486 DestroyWindow(hWndTest
);
1489 static void test_InvalidIMC(void)
1492 HIMC imc_null
= 0x00000000;
1493 HIMC imc_bad
= (HIMC
)0xdeadcafe;
1495 HIMC imc1
, imc2
, oldimc
;
1502 memset(&lf
, 0, sizeof(lf
));
1504 imc_destroy
= ImmCreateContext();
1505 ret
= ImmDestroyContext(imc_destroy
);
1506 ok(ret
== TRUE
, "Destroy an IMC should success!\n");
1508 /* Test associating destroyed imc */
1509 imc1
= ImmGetContext(hwnd
);
1510 SetLastError(0xdeadbeef);
1511 oldimc
= ImmAssociateContext(hwnd
, imc_destroy
);
1512 ok(!oldimc
, "Associating to a destroyed imc should fail!\n");
1513 ret
= GetLastError();
1514 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1515 imc2
= ImmGetContext(hwnd
);
1516 ok(imc1
== imc2
, "imc should not changed! imc1 %p, imc2 %p\n", imc1
, imc2
);
1518 /* Test associating NULL imc, which is different from an invalid imc */
1519 oldimc
= ImmAssociateContext(hwnd
, imc_null
);
1520 ok(oldimc
!= NULL
, "Associating to NULL imc should success!\n");
1521 imc2
= ImmGetContext(hwnd
);
1522 ok(!imc2
, "expect NULL, returned %p\n", imc2
);
1523 oldimc
= ImmAssociateContext(hwnd
, imc1
);
1524 ok(!oldimc
, "expect NULL, returned %p\n", oldimc
);
1525 imc2
= ImmGetContext(hwnd
);
1526 ok(imc2
== imc1
, "imc should not changed! imc2 %p, imc1 %p\n", imc2
, imc1
);
1528 /* Test associating invalid imc */
1529 imc1
= ImmGetContext(hwnd
);
1530 SetLastError(0xdeadbeef);
1531 oldimc
= ImmAssociateContext(hwnd
, imc_bad
);
1532 ok(!oldimc
, "Associating to a destroyed imc should fail!\n");
1533 ret
= GetLastError();
1534 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1535 imc2
= ImmGetContext(hwnd
);
1536 ok(imc1
== imc2
, "imc should not changed! imc1 %p, imc2 %p\n", imc1
, imc2
);
1539 /* Test ImmGetCandidateListA */
1540 SetLastError(0xdeadbeef);
1541 ret
= ImmGetCandidateListA(imc_bad
, 0, NULL
, 0);
1542 ok(ret
== 0, "Bad IME should return 0\n");
1543 ret
= GetLastError();
1544 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1545 SetLastError(0xdeadbeef);
1546 ret
= ImmGetCandidateListA(imc_null
, 0, NULL
, 0);
1547 ok(ret
== 0, "NULL IME should return 0\n");
1548 ret
= GetLastError();
1549 ok(ret
== 0xdeadbeef, "last error should remain unchanged %08x!\n", ret
);
1550 SetLastError(0xdeadbeef);
1551 ret
= ImmGetCandidateListA(imc_destroy
, 0, NULL
, 0);
1552 ok(ret
== 0, "Destroyed IME should return 0\n");
1553 ret
= GetLastError();
1554 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1556 /* Test ImmGetCandidateListCountA*/
1557 SetLastError(0xdeadbeef);
1558 ret
= ImmGetCandidateListCountA(imc_bad
,&count
);
1559 ok(ret
== 0, "Bad IME should return 0\n");
1560 ret
= GetLastError();
1561 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1562 SetLastError(0xdeadbeef);
1563 ret
= ImmGetCandidateListCountA(imc_null
,&count
);
1564 ok(ret
== 0, "NULL IME should return 0\n");
1565 ret
= GetLastError();
1566 ok(ret
== 0xdeadbeef, "last error should remain unchanged %08x!\n", ret
);
1567 SetLastError(0xdeadbeef);
1568 ret
= ImmGetCandidateListCountA(imc_destroy
,&count
);
1569 ok(ret
== 0, "Destroyed IME should return 0\n");
1570 ret
= GetLastError();
1571 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1573 /* Test ImmGetCandidateWindow */
1574 SetLastError(0xdeadbeef);
1575 ret
= ImmGetCandidateWindow(imc_bad
, 0, (LPCANDIDATEFORM
)buffer
);
1576 ok(ret
== 0, "Bad IME should return 0\n");
1577 ret
= GetLastError();
1578 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1579 SetLastError(0xdeadbeef);
1580 ret
= ImmGetCandidateWindow(imc_null
, 0, (LPCANDIDATEFORM
)buffer
);
1581 ok(ret
== 0, "NULL IME should return 0\n");
1582 ret
= GetLastError();
1583 ok(ret
== 0xdeadbeef, "last error should remain unchanged %08x!\n", ret
);
1584 SetLastError(0xdeadbeef);
1585 ret
= ImmGetCandidateWindow(imc_destroy
, 0, (LPCANDIDATEFORM
)buffer
);
1586 ok(ret
== 0, "Destroyed IME should return 0\n");
1587 ret
= GetLastError();
1588 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1590 /* Test ImmGetCompositionFontA */
1591 SetLastError(0xdeadbeef);
1592 ret
= ImmGetCompositionFontA(imc_bad
, (LPLOGFONTA
)buffer
);
1593 ok(ret
== 0, "Bad IME should return 0\n");
1594 ret
= GetLastError();
1595 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1596 SetLastError(0xdeadbeef);
1597 ret
= ImmGetCompositionFontA(imc_null
, (LPLOGFONTA
)buffer
);
1598 ok(ret
== 0, "NULL IME should return 0\n");
1599 ret
= GetLastError();
1600 ok(ret
== 0xdeadbeef, "last error should remain unchanged %08x!\n", ret
);
1601 SetLastError(0xdeadbeef);
1602 ret
= ImmGetCompositionFontA(imc_destroy
, (LPLOGFONTA
)buffer
);
1603 ok(ret
== 0, "Destroyed IME should return 0\n");
1604 ret
= GetLastError();
1605 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1607 /* Test ImmGetCompositionWindow */
1608 SetLastError(0xdeadbeef);
1609 ret
= ImmGetCompositionWindow(imc_bad
, (LPCOMPOSITIONFORM
)buffer
);
1610 ok(ret
== 0, "Bad IME should return 0\n");
1611 ret
= GetLastError();
1612 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1613 SetLastError(0xdeadbeef);
1614 ret
= ImmGetCompositionWindow(imc_null
, (LPCOMPOSITIONFORM
)buffer
);
1615 ok(ret
== 0, "NULL IME should return 0\n");
1616 ret
= GetLastError();
1617 ok(ret
== 0xdeadbeef, "last error should remain unchanged %08x!\n", ret
);
1618 SetLastError(0xdeadbeef);
1619 ret
= ImmGetCompositionWindow(imc_destroy
, (LPCOMPOSITIONFORM
)buffer
);
1620 ok(ret
== 0, "Destroyed IME should return 0\n");
1621 ret
= GetLastError();
1622 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1624 /* Test ImmGetCompositionStringA */
1625 SetLastError(0xdeadbeef);
1626 ret
= ImmGetCompositionStringA(imc_bad
, GCS_COMPSTR
, NULL
, 0);
1627 ok(ret
== 0, "Bad IME should return 0\n");
1628 ret
= GetLastError();
1629 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1630 SetLastError(0xdeadbeef);
1631 ret
= ImmGetCompositionStringA(imc_null
, GCS_COMPSTR
, NULL
, 0);
1632 ok(ret
== 0, "NULL IME should return 0\n");
1633 ret
= GetLastError();
1634 ok(ret
== 0xdeadbeef, "last error should remain unchanged %08x!\n", ret
);
1635 SetLastError(0xdeadbeef);
1636 ret
= ImmGetCompositionStringA(imc_destroy
, GCS_COMPSTR
, NULL
, 0);
1637 ok(ret
== 0, "Destroyed IME should return 0\n");
1638 ret
= GetLastError();
1639 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1641 /* Test ImmSetOpenStatus */
1642 SetLastError(0xdeadbeef);
1643 ret
= ImmSetOpenStatus(imc_bad
, 1);
1644 ok(ret
== 0, "Bad IME should return 0\n");
1645 ret
= GetLastError();
1646 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1647 SetLastError(0xdeadbeef);
1648 ret
= ImmSetOpenStatus(imc_null
, 1);
1649 ok(ret
== 0, "NULL IME should return 0\n");
1650 ret
= GetLastError();
1651 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1652 SetLastError(0xdeadbeef);
1653 ret
= ImmSetOpenStatus(imc_destroy
, 1);
1654 ok(ret
== 0, "Destroyed IME should return 0\n");
1655 ret
= GetLastError();
1656 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1658 /* Test ImmGetOpenStatus */
1659 SetLastError(0xdeadbeef);
1660 ret
= ImmGetOpenStatus(imc_bad
);
1661 ok(ret
== 0, "Bad IME should return 0\n");
1662 ret
= GetLastError();
1663 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1664 SetLastError(0xdeadbeef);
1665 ret
= ImmGetOpenStatus(imc_null
);
1666 ok(ret
== 0, "NULL IME should return 0\n");
1667 ret
= GetLastError();
1668 ok(ret
== 0xdeadbeef, "last error should remain unchanged %08x!\n", ret
);
1669 SetLastError(0xdeadbeef);
1670 ret
= ImmGetOpenStatus(imc_destroy
);
1671 ok(ret
== 0, "Destroyed IME should return 0\n");
1672 ret
= GetLastError();
1673 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1675 /* Test ImmGetStatusWindowPos */
1676 SetLastError(0xdeadbeef);
1677 ret
= ImmGetStatusWindowPos(imc_bad
, NULL
);
1678 ok(ret
== 0, "Bad IME should return 0\n");
1679 ret
= GetLastError();
1680 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1681 SetLastError(0xdeadbeef);
1682 ret
= ImmGetStatusWindowPos(imc_null
, NULL
);
1683 ok(ret
== 0, "NULL IME should return 0\n");
1684 ret
= GetLastError();
1685 ok(ret
== 0xdeadbeef, "last error should remain unchanged %08x!\n", ret
);
1686 SetLastError(0xdeadbeef);
1687 ret
= ImmGetStatusWindowPos(imc_destroy
, NULL
);
1688 ok(ret
== 0, "Destroyed IME should return 0\n");
1689 ret
= GetLastError();
1690 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1692 /* Test ImmRequestMessageA */
1693 SetLastError(0xdeadbeef);
1694 ret
= ImmRequestMessageA(imc_bad
, WM_CHAR
, 0);
1695 ok(ret
== 0, "Bad IME should return 0\n");
1696 ret
= GetLastError();
1697 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1698 SetLastError(0xdeadbeef);
1699 ret
= ImmRequestMessageA(imc_null
, WM_CHAR
, 0);
1700 ok(ret
== 0, "NULL IME should return 0\n");
1701 ret
= GetLastError();
1702 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1703 SetLastError(0xdeadbeef);
1704 ret
= ImmRequestMessageA(imc_destroy
, WM_CHAR
, 0);
1705 ok(ret
== 0, "Destroyed IME should return 0\n");
1706 ret
= GetLastError();
1707 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1709 /* Test ImmSetCompositionFontA */
1710 SetLastError(0xdeadbeef);
1711 ret
= ImmSetCompositionFontA(imc_bad
, &lf
);
1712 ok(ret
== 0, "Bad IME should return 0\n");
1713 ret
= GetLastError();
1714 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1715 SetLastError(0xdeadbeef);
1716 ret
= ImmSetCompositionFontA(imc_null
, &lf
);
1717 ok(ret
== 0, "NULL IME should return 0\n");
1718 ret
= GetLastError();
1719 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1720 SetLastError(0xdeadbeef);
1721 ret
= ImmSetCompositionFontA(imc_destroy
, &lf
);
1722 ok(ret
== 0, "Destroyed IME should return 0\n");
1723 ret
= GetLastError();
1724 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1726 /* Test ImmSetCompositionWindow */
1727 SetLastError(0xdeadbeef);
1728 ret
= ImmSetCompositionWindow(imc_bad
, NULL
);
1729 ok(ret
== 0, "Bad IME should return 0\n");
1730 ret
= GetLastError();
1731 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1732 SetLastError(0xdeadbeef);
1733 ret
= ImmSetCompositionWindow(imc_null
, NULL
);
1734 ok(ret
== 0, "NULL IME should return 0\n");
1735 ret
= GetLastError();
1736 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1737 SetLastError(0xdeadbeef);
1738 ret
= ImmSetCompositionWindow(imc_destroy
, NULL
);
1739 ok(ret
== 0, "Destroyed IME should return 0\n");
1740 ret
= GetLastError();
1741 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1743 /* Test ImmSetConversionStatus */
1744 SetLastError(0xdeadbeef);
1745 ret
= ImmSetConversionStatus(imc_bad
, 0, 0);
1746 ok(ret
== 0, "Bad IME should return 0\n");
1747 ret
= GetLastError();
1748 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1749 SetLastError(0xdeadbeef);
1750 ret
= ImmSetConversionStatus(imc_null
, 0, 0);
1751 ok(ret
== 0, "NULL IME should return 0\n");
1752 ret
= GetLastError();
1753 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1754 SetLastError(0xdeadbeef);
1755 ret
= ImmSetConversionStatus(imc_destroy
, 0, 0);
1756 ok(ret
== 0, "Destroyed IME should return 0\n");
1757 ret
= GetLastError();
1758 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1760 /* Test ImmSetStatusWindowPos */
1761 SetLastError(0xdeadbeef);
1762 ret
= ImmSetStatusWindowPos(imc_bad
, 0);
1763 ok(ret
== 0, "Bad IME should return 0\n");
1764 ret
= GetLastError();
1765 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1766 SetLastError(0xdeadbeef);
1767 ret
= ImmSetStatusWindowPos(imc_null
, 0);
1768 ok(ret
== 0, "NULL IME should return 0\n");
1769 ret
= GetLastError();
1770 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1771 SetLastError(0xdeadbeef);
1772 ret
= ImmSetStatusWindowPos(imc_destroy
, 0);
1773 ok(ret
== 0, "Destroyed IME should return 0\n");
1774 ret
= GetLastError();
1775 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1777 /* Test ImmGetImeMenuItemsA */
1778 SetLastError(0xdeadbeef);
1779 ret
= ImmGetImeMenuItemsA(imc_bad
, 0, 0, NULL
, NULL
, 0);
1780 ok(ret
== 0, "Bad IME should return 0\n");
1781 ret
= GetLastError();
1782 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1783 SetLastError(0xdeadbeef);
1784 ret
= ImmGetImeMenuItemsA(imc_null
, 0, 0, NULL
, NULL
, 0);
1785 ok(ret
== 0, "NULL IME should return 0\n");
1786 ret
= GetLastError();
1787 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1788 SetLastError(0xdeadbeef);
1789 ret
= ImmGetImeMenuItemsA(imc_destroy
, 0, 0, NULL
, NULL
, 0);
1790 ok(ret
== 0, "Destroyed IME should return 0\n");
1791 ret
= GetLastError();
1792 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1794 /* Test ImmLockIMC */
1795 SetLastError(0xdeadbeef);
1796 ic
= ImmLockIMC(imc_bad
);
1797 ok(ic
== 0, "Bad IME should return 0\n");
1798 ret
= GetLastError();
1799 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1800 SetLastError(0xdeadbeef);
1801 ic
= ImmLockIMC(imc_null
);
1802 ok(ic
== 0, "NULL IME should return 0\n");
1803 ret
= GetLastError();
1804 ok(ret
== 0xdeadbeef, "last error should remain unchanged %08x!\n", ret
);
1805 SetLastError(0xdeadbeef);
1806 ic
= ImmLockIMC(imc_destroy
);
1807 ok(ic
== 0, "Destroyed IME should return 0\n");
1808 ret
= GetLastError();
1809 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1811 /* Test ImmUnlockIMC */
1812 SetLastError(0xdeadbeef);
1813 ret
= ImmUnlockIMC(imc_bad
);
1814 ok(ret
== 0, "Bad IME should return 0\n");
1815 ret
= GetLastError();
1816 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1817 SetLastError(0xdeadbeef);
1818 ret
= ImmUnlockIMC(imc_null
);
1819 ok(ret
== 0, "NULL IME should return 0\n");
1820 ret
= GetLastError();
1821 ok(ret
== 0xdeadbeef, "last error should remain unchanged %08x!\n", ret
);
1822 SetLastError(0xdeadbeef);
1823 ret
= ImmUnlockIMC(imc_destroy
);
1824 ok(ret
== 0, "Destroyed IME should return 0\n");
1825 ret
= GetLastError();
1826 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1828 /* Test ImmGenerateMessage */
1829 SetLastError(0xdeadbeef);
1830 ret
= ImmGenerateMessage(imc_bad
);
1831 ok(ret
== 0, "Bad IME should return 0\n");
1832 ret
= GetLastError();
1833 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1834 SetLastError(0xdeadbeef);
1835 ret
= ImmGenerateMessage(imc_null
);
1836 ok(ret
== 0, "NULL IME should return 0\n");
1837 ret
= GetLastError();
1838 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1839 SetLastError(0xdeadbeef);
1840 ret
= ImmGenerateMessage(imc_destroy
);
1841 ok(ret
== 0, "Destroyed IME should return 0\n");
1842 ret
= GetLastError();
1843 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1849 test_ImmNotifyIME();
1850 test_ImmGetCompositionString();
1851 test_ImmSetCompositionString();
1853 test_ImmAssociateContextEx();
1855 test_ImmIsUIMessage();
1856 test_ImmGetContext();
1857 test_ImmGetDescription();
1858 test_ImmDefaultHwnd();
1859 test_default_ime_window_creation();
1860 test_ImmGetIMCLockCount();
1861 test_ImmGetIMCCLockCount();
1862 test_ImmDestroyContext();
1863 test_ImmDestroyIMCC();
1866 /* Reinitialize the hooks to capture all windows */
1871 test_ime_processkey();
1872 else win_skip("SendInput is not available\n");