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