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";
177 static LRESULT WINAPI
wndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
181 case WM_IME_SETCONTEXT
:
187 return DefWindowProcA(hWnd
,msg
,wParam
,lParam
);
190 static BOOL
init(void) {
195 hmod
= GetModuleHandleA("imm32.dll");
196 huser
= GetModuleHandleA("user32");
197 pImmAssociateContextEx
= (void*)GetProcAddress(hmod
, "ImmAssociateContextEx");
198 pImmIsUIMessageA
= (void*)GetProcAddress(hmod
, "ImmIsUIMessageA");
199 pSendInput
= (void*)GetProcAddress(huser
, "SendInput");
201 wc
.cbSize
= sizeof(WNDCLASSEXA
);
203 wc
.lpfnWndProc
= wndProc
;
206 wc
.hInstance
= GetModuleHandleA(NULL
);
207 wc
.hIcon
= LoadIconA(NULL
, (LPCSTR
)IDI_APPLICATION
);
208 wc
.hCursor
= LoadCursorA(NULL
, (LPCSTR
)IDC_ARROW
);
209 wc
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+1);
210 wc
.lpszMenuName
= NULL
;
211 wc
.lpszClassName
= wndcls
;
212 wc
.hIconSm
= LoadIconA(NULL
, (LPCSTR
)IDI_APPLICATION
);
214 if (!RegisterClassExA(&wc
))
217 hwnd
= CreateWindowExA(WS_EX_CLIENTEDGE
, wndcls
, "Wine imm32.dll test",
218 WS_OVERLAPPEDWINDOW
, CW_USEDEFAULT
, CW_USEDEFAULT
,
219 240, 120, NULL
, NULL
, GetModuleHandleW(NULL
), NULL
);
223 imc
= ImmGetContext(hwnd
);
226 win_skip("IME support not implemented\n");
229 ImmReleaseContext(hwnd
, imc
);
231 ShowWindow(hwnd
, SW_SHOWNORMAL
);
239 static void cleanup(void) {
243 UnregisterClassA(wndcls
, GetModuleHandleW(NULL
));
246 static void test_ImmNotifyIME(void) {
247 static const char string
[] = "wine";
248 char resstr
[16] = "";
252 imc
= ImmGetContext(hwnd
);
253 msg_spy_flush_msgs();
255 ret
= ImmNotifyIME(imc
, NI_COMPOSITIONSTR
, CPS_CANCEL
, 0);
258 "Canceling an empty composition string should succeed.\n");
259 ok(!msg_spy_find_msg(WM_IME_COMPOSITION
), "Windows does not post "
260 "WM_IME_COMPOSITION in response to NI_COMPOSITIONSTR / CPS_CANCEL, if "
261 "the composition string being canceled is empty.\n");
263 ImmSetCompositionStringA(imc
, SCS_SETSTR
, string
, sizeof(string
), NULL
, 0);
264 msg_spy_flush_msgs();
266 ImmNotifyIME(imc
, NI_COMPOSITIONSTR
, CPS_CANCEL
, 0);
267 msg_spy_flush_msgs();
269 /* behavior differs between win9x and NT */
270 ret
= ImmGetCompositionStringA(imc
, GCS_COMPSTR
, resstr
, sizeof(resstr
));
271 ok(!ret
, "After being cancelled the composition string is empty.\n");
273 msg_spy_flush_msgs();
275 ret
= ImmNotifyIME(imc
, NI_COMPOSITIONSTR
, CPS_CANCEL
, 0);
278 "Canceling an empty composition string should succeed.\n");
279 ok(!msg_spy_find_msg(WM_IME_COMPOSITION
), "Windows does not post "
280 "WM_IME_COMPOSITION in response to NI_COMPOSITIONSTR / CPS_CANCEL, if "
281 "the composition string being canceled is empty.\n");
283 msg_spy_flush_msgs();
284 ImmReleaseContext(hwnd
, imc
);
286 imc
= ImmCreateContext();
287 ImmDestroyContext(imc
);
289 SetLastError(0xdeadbeef);
290 ret
= ImmNotifyIME((HIMC
)0xdeadcafe, NI_COMPOSITIONSTR
, CPS_CANCEL
, 0);
291 ok (ret
== 0, "Bad IME should return 0\n");
292 ret
= GetLastError();
293 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
294 SetLastError(0xdeadbeef);
295 ret
= ImmNotifyIME(0x00000000, NI_COMPOSITIONSTR
, CPS_CANCEL
, 0);
296 ok (ret
== 0, "NULL IME should return 0\n");
297 ret
= GetLastError();
298 ok(ret
== ERROR_SUCCESS
, "wrong last error %08x!\n", ret
);
299 SetLastError(0xdeadbeef);
300 ret
= ImmNotifyIME(imc
, NI_COMPOSITIONSTR
, CPS_CANCEL
, 0);
301 ok (ret
== 0, "Destroyed IME should return 0\n");
302 ret
= GetLastError();
303 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
307 static void test_ImmGetCompositionString(void)
310 static const WCHAR string
[] = {'w','i','n','e',0x65e5,0x672c,0x8a9e};
316 imc
= ImmGetContext(hwnd
);
317 ImmSetCompositionStringW(imc
, SCS_SETSTR
, string
, sizeof(string
), NULL
,0);
318 alen
= ImmGetCompositionStringA(imc
, GCS_COMPSTR
, cstring
, 20);
319 wlen
= ImmGetCompositionStringW(imc
, GCS_COMPSTR
, wstring
, 20);
320 /* windows machines without any IME installed just return 0 above */
323 len
= ImmGetCompositionStringW(imc
, GCS_COMPATTR
, NULL
, 0);
324 ok(len
*sizeof(WCHAR
)==wlen
,"GCS_COMPATTR(W) not returning correct count\n");
325 len
= ImmGetCompositionStringA(imc
, GCS_COMPATTR
, NULL
, 0);
326 ok(len
==alen
,"GCS_COMPATTR(A) not returning correct count\n");
328 ImmReleaseContext(hwnd
, imc
);
331 static void test_ImmSetCompositionString(void)
336 SetLastError(0xdeadbeef);
337 imc
= ImmGetContext(hwnd
);
338 ok(imc
!= 0, "ImmGetContext() failed. Last error: %u\n", GetLastError());
342 ret
= ImmSetCompositionStringW(imc
, SCS_SETSTR
, NULL
, 0, NULL
, 0);
345 "ImmSetCompositionStringW() failed.\n");
347 ret
= ImmSetCompositionStringW(imc
, SCS_SETSTR
| SCS_CHANGEATTR
,
349 ok(!ret
, "ImmSetCompositionStringW() succeeded.\n");
351 ret
= ImmSetCompositionStringW(imc
, SCS_SETSTR
| SCS_CHANGECLAUSE
,
353 ok(!ret
, "ImmSetCompositionStringW() succeeded.\n");
355 ret
= ImmSetCompositionStringW(imc
, SCS_CHANGEATTR
| SCS_CHANGECLAUSE
,
357 ok(!ret
, "ImmSetCompositionStringW() succeeded.\n");
359 ret
= ImmSetCompositionStringW(imc
, SCS_SETSTR
| SCS_CHANGEATTR
| SCS_CHANGECLAUSE
,
361 ok(!ret
, "ImmSetCompositionStringW() succeeded.\n");
363 ImmReleaseContext(hwnd
, imc
);
366 static void test_ImmIME(void)
370 imc
= ImmGetContext(hwnd
);
374 rc
= ImmConfigureIMEA(imc
, NULL
, IME_CONFIG_REGISTERWORD
, NULL
);
375 ok (rc
== 0, "ImmConfigureIMEA did not fail\n");
376 rc
= ImmConfigureIMEW(imc
, NULL
, IME_CONFIG_REGISTERWORD
, NULL
);
377 ok (rc
== 0, "ImmConfigureIMEW did not fail\n");
379 ImmReleaseContext(hwnd
,imc
);
382 static void test_ImmAssociateContextEx(void)
387 if (!pImmAssociateContextEx
) return;
389 imc
= ImmGetContext(hwnd
);
394 newimc
= ImmCreateContext();
395 ok(newimc
!= imc
, "handles should not be the same\n");
396 rc
= pImmAssociateContextEx(NULL
, NULL
, 0);
397 ok(!rc
, "ImmAssociateContextEx succeeded\n");
398 rc
= pImmAssociateContextEx(hwnd
, NULL
, 0);
399 ok(rc
, "ImmAssociateContextEx failed\n");
400 rc
= pImmAssociateContextEx(NULL
, imc
, 0);
401 ok(!rc
, "ImmAssociateContextEx succeeded\n");
403 rc
= pImmAssociateContextEx(hwnd
, imc
, 0);
404 ok(rc
, "ImmAssociateContextEx failed\n");
405 retimc
= ImmGetContext(hwnd
);
406 ok(retimc
== imc
, "handles should be the same\n");
407 ImmReleaseContext(hwnd
,retimc
);
409 rc
= pImmAssociateContextEx(hwnd
, newimc
, 0);
410 ok(rc
, "ImmAssociateContextEx failed\n");
411 retimc
= ImmGetContext(hwnd
);
412 ok(retimc
== newimc
, "handles should be the same\n");
413 ImmReleaseContext(hwnd
,retimc
);
415 rc
= pImmAssociateContextEx(hwnd
, NULL
, IACE_DEFAULT
);
416 ok(rc
, "ImmAssociateContextEx failed\n");
418 ImmReleaseContext(hwnd
,imc
);
421 typedef struct _igc_threadinfo
{
429 static DWORD WINAPI
ImmGetContextThreadFunc( LPVOID lpParam
)
438 igc_threadinfo
*info
= (igc_threadinfo
*)lpParam
;
439 info
->hwnd
= CreateWindowExA(WS_EX_CLIENTEDGE
, wndcls
, "Wine imm32.dll test",
440 WS_OVERLAPPEDWINDOW
, CW_USEDEFAULT
, CW_USEDEFAULT
,
441 240, 120, NULL
, NULL
, GetModuleHandleW(NULL
), NULL
);
443 h1
= ImmGetContext(hwnd
);
444 ok(info
->himc
== h1
, "hwnd context changed in new thread\n");
445 h2
= ImmGetContext(info
->hwnd
);
446 ok(h2
!= h1
, "new hwnd in new thread should have different context\n");
448 ImmReleaseContext(hwnd
,h1
);
450 hwnd2
= CreateWindowExA(WS_EX_CLIENTEDGE
, wndcls
, "Wine imm32.dll test",
451 WS_OVERLAPPEDWINDOW
, CW_USEDEFAULT
, CW_USEDEFAULT
,
452 240, 120, NULL
, NULL
, GetModuleHandleW(NULL
), NULL
);
453 h1
= ImmGetContext(hwnd2
);
455 ok(h1
== h2
, "Windows in same thread should have same default context\n");
456 ImmReleaseContext(hwnd2
,h1
);
457 ImmReleaseContext(info
->hwnd
,h2
);
458 DestroyWindow(hwnd2
);
460 /* priming for later tests */
461 ImmSetCompositionWindow(h1
, &cf
);
462 ImmSetStatusWindowPos(h1
, &pt
);
463 info
->u_himc
= ImmCreateContext();
464 ImmSetOpenStatus(info
->u_himc
, TRUE
);
466 cdf
.dwStyle
= CFS_CANDIDATEPOS
;
467 cdf
.ptCurrentPos
.x
= 0;
468 cdf
.ptCurrentPos
.y
= 0;
469 ImmSetCandidateWindow(info
->u_himc
, &cdf
);
471 SetEvent(info
->event
);
473 while(GetMessageW(&msg
, 0, 0, 0))
475 TranslateMessage(&msg
);
476 DispatchMessageW(&msg
);
481 static void test_ImmThreads(void)
483 HIMC himc
, otherHimc
, h1
;
484 igc_threadinfo threadinfo
;
491 DWORD status
, sentence
;
494 himc
= ImmGetContext(hwnd
);
495 threadinfo
.event
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
496 threadinfo
.himc
= himc
;
497 hThread
= CreateThread(NULL
, 0, ImmGetContextThreadFunc
, &threadinfo
, 0, &dwThreadId
);
498 WaitForSingleObject(threadinfo
.event
, INFINITE
);
500 otherHimc
= ImmGetContext(threadinfo
.hwnd
);
502 ok(himc
!= otherHimc
, "Windows from other threads should have different himc\n");
503 ok(otherHimc
== threadinfo
.himc
, "Context from other thread should not change in main thread\n");
505 h1
= ImmAssociateContext(hwnd
,otherHimc
);
506 ok(h1
== NULL
, "Should fail to be able to Associate a default context from a different thread\n");
507 h1
= ImmGetContext(hwnd
);
508 ok(h1
== himc
, "Context for window should remain unchanged\n");
509 ImmReleaseContext(hwnd
,h1
);
511 h1
= ImmAssociateContext(hwnd
, threadinfo
.u_himc
);
512 ok (h1
== NULL
, "Should fail to associate a context from a different thread\n");
513 h1
= ImmGetContext(hwnd
);
514 ok(h1
== himc
, "Context for window should remain unchanged\n");
515 ImmReleaseContext(hwnd
,h1
);
517 h1
= ImmAssociateContext(threadinfo
.hwnd
, threadinfo
.u_himc
);
518 ok (h1
== NULL
, "Should fail to associate a context from a different thread into a window from that thread.\n");
519 h1
= ImmGetContext(threadinfo
.hwnd
);
520 ok(h1
== threadinfo
.himc
, "Context for window should remain unchanged\n");
521 ImmReleaseContext(threadinfo
.hwnd
,h1
);
524 rc
= ImmSetOpenStatus(himc
, TRUE
);
525 ok(rc
!= 0, "ImmSetOpenStatus failed\n");
526 rc
= ImmGetOpenStatus(himc
);
527 ok(rc
!= 0, "ImmGetOpenStatus failed\n");
528 rc
= ImmSetOpenStatus(himc
, FALSE
);
529 ok(rc
!= 0, "ImmSetOpenStatus failed\n");
530 rc
= ImmGetOpenStatus(himc
);
531 ok(rc
== 0, "ImmGetOpenStatus failed\n");
533 rc
= ImmSetOpenStatus(otherHimc
, TRUE
);
534 ok(rc
== 0, "ImmSetOpenStatus should fail\n");
535 rc
= ImmSetOpenStatus(threadinfo
.u_himc
, TRUE
);
536 ok(rc
== 0, "ImmSetOpenStatus should fail\n");
537 rc
= ImmGetOpenStatus(otherHimc
);
538 ok(rc
== 0, "ImmGetOpenStatus failed\n");
539 rc
= ImmGetOpenStatus(threadinfo
.u_himc
);
540 ok (rc
== 1 || broken(rc
== 0), "ImmGetOpenStatus should return 1\n");
541 rc
= ImmSetOpenStatus(otherHimc
, FALSE
);
542 ok(rc
== 0, "ImmSetOpenStatus should fail\n");
543 rc
= ImmGetOpenStatus(otherHimc
);
544 ok(rc
== 0, "ImmGetOpenStatus failed\n");
546 /* CompositionFont */
547 rc
= ImmGetCompositionFontA(himc
, &lf
);
548 ok(rc
!= 0, "ImmGetCompositionFont failed\n");
549 rc
= ImmSetCompositionFontA(himc
, &lf
);
550 ok(rc
!= 0, "ImmSetCompositionFont failed\n");
552 rc
= ImmGetCompositionFontA(otherHimc
, &lf
);
553 ok(rc
!= 0 || broken(rc
== 0), "ImmGetCompositionFont failed\n");
554 rc
= ImmGetCompositionFontA(threadinfo
.u_himc
, &lf
);
555 ok(rc
!= 0 || broken(rc
== 0), "ImmGetCompositionFont user himc failed\n");
556 rc
= ImmSetCompositionFontA(otherHimc
, &lf
);
557 ok(rc
== 0, "ImmSetCompositionFont should fail\n");
558 rc
= ImmSetCompositionFontA(threadinfo
.u_himc
, &lf
);
559 ok(rc
== 0, "ImmSetCompositionFont should fail\n");
561 /* CompositionWindow */
562 rc
= ImmSetCompositionWindow(himc
, &cf
);
563 ok(rc
!= 0, "ImmSetCompositionWindow failed\n");
564 rc
= ImmGetCompositionWindow(himc
, &cf
);
565 ok(rc
!= 0, "ImmGetCompositionWindow failed\n");
567 rc
= ImmSetCompositionWindow(otherHimc
, &cf
);
568 ok(rc
== 0, "ImmSetCompositionWindow should fail\n");
569 rc
= ImmSetCompositionWindow(threadinfo
.u_himc
, &cf
);
570 ok(rc
== 0, "ImmSetCompositionWindow should fail\n");
571 rc
= ImmGetCompositionWindow(otherHimc
, &cf
);
572 ok(rc
!= 0 || broken(rc
== 0), "ImmGetCompositionWindow failed\n");
573 rc
= ImmGetCompositionWindow(threadinfo
.u_himc
, &cf
);
574 ok(rc
!= 0 || broken(rc
== 0), "ImmGetCompositionWindow failed\n");
576 /* ConversionStatus */
577 rc
= ImmGetConversionStatus(himc
, &status
, &sentence
);
578 ok(rc
!= 0, "ImmGetConversionStatus failed\n");
579 rc
= ImmSetConversionStatus(himc
, status
, sentence
);
580 ok(rc
!= 0, "ImmSetConversionStatus failed\n");
582 rc
= ImmGetConversionStatus(otherHimc
, &status
, &sentence
);
583 ok(rc
!= 0 || broken(rc
== 0), "ImmGetConversionStatus failed\n");
584 rc
= ImmGetConversionStatus(threadinfo
.u_himc
, &status
, &sentence
);
585 ok(rc
!= 0 || broken(rc
== 0), "ImmGetConversionStatus failed\n");
586 rc
= ImmSetConversionStatus(otherHimc
, status
, sentence
);
587 ok(rc
== 0, "ImmSetConversionStatus should fail\n");
588 rc
= ImmSetConversionStatus(threadinfo
.u_himc
, status
, sentence
);
589 ok(rc
== 0, "ImmSetConversionStatus should fail\n");
591 /* StatusWindowPos */
592 rc
= ImmSetStatusWindowPos(himc
, &pt
);
593 ok(rc
!= 0, "ImmSetStatusWindowPos failed\n");
594 rc
= ImmGetStatusWindowPos(himc
, &pt
);
595 ok(rc
!= 0, "ImmGetStatusWindowPos failed\n");
597 rc
= ImmSetStatusWindowPos(otherHimc
, &pt
);
598 ok(rc
== 0, "ImmSetStatusWindowPos should fail\n");
599 rc
= ImmSetStatusWindowPos(threadinfo
.u_himc
, &pt
);
600 ok(rc
== 0, "ImmSetStatusWindowPos should fail\n");
601 rc
= ImmGetStatusWindowPos(otherHimc
, &pt
);
602 ok(rc
!= 0 || broken(rc
== 0), "ImmGetStatusWindowPos failed\n");
603 rc
= ImmGetStatusWindowPos(threadinfo
.u_himc
, &pt
);
604 ok(rc
!= 0 || broken(rc
== 0), "ImmGetStatusWindowPos failed\n");
606 h1
= ImmAssociateContext(threadinfo
.hwnd
, NULL
);
607 ok (h1
== otherHimc
, "ImmAssociateContext cross thread with NULL should work\n");
608 h1
= ImmGetContext(threadinfo
.hwnd
);
609 ok (h1
== NULL
, "CrossThread window context should be NULL\n");
610 h1
= ImmAssociateContext(threadinfo
.hwnd
, h1
);
611 ok (h1
== NULL
, "Resetting cross thread context should fail\n");
612 h1
= ImmGetContext(threadinfo
.hwnd
);
613 ok (h1
== NULL
, "CrossThread window context should still be NULL\n");
615 rc
= ImmDestroyContext(threadinfo
.u_himc
);
616 ok (rc
== 0, "ImmDestroyContext Cross Thread should fail\n");
618 /* Candidate Window */
619 rc
= ImmGetCandidateWindow(himc
, 0, &cdf
);
620 ok (rc
== 0, "ImmGetCandidateWindow should fail\n");
622 cdf
.dwStyle
= CFS_CANDIDATEPOS
;
623 cdf
.ptCurrentPos
.x
= 0;
624 cdf
.ptCurrentPos
.y
= 0;
625 rc
= ImmSetCandidateWindow(himc
, &cdf
);
626 ok (rc
== 1, "ImmSetCandidateWindow should succeed\n");
627 rc
= ImmGetCandidateWindow(himc
, 0, &cdf
);
628 ok (rc
== 1, "ImmGetCandidateWindow should succeed\n");
630 rc
= ImmGetCandidateWindow(otherHimc
, 0, &cdf
);
631 ok (rc
== 0, "ImmGetCandidateWindow should fail\n");
632 rc
= ImmSetCandidateWindow(otherHimc
, &cdf
);
633 ok (rc
== 0, "ImmSetCandidateWindow should fail\n");
634 rc
= ImmGetCandidateWindow(threadinfo
.u_himc
, 0, &cdf
);
635 ok (rc
== 1 || broken( rc
== 0), "ImmGetCandidateWindow should succeed\n");
636 rc
= ImmSetCandidateWindow(threadinfo
.u_himc
, &cdf
);
637 ok (rc
== 0, "ImmSetCandidateWindow should fail\n");
639 ImmReleaseContext(threadinfo
.hwnd
,otherHimc
);
640 ImmReleaseContext(hwnd
,himc
);
642 SendMessageA(threadinfo
.hwnd
, WM_CLOSE
, 0, 0);
643 rc
= PostThreadMessageA(dwThreadId
, WM_QUIT
, 1, 0);
644 ok(rc
== 1, "PostThreadMessage should succeed\n");
645 WaitForSingleObject(hThread
, INFINITE
);
646 CloseHandle(hThread
);
648 himc
= ImmGetContext(GetDesktopWindow());
649 ok(himc
== NULL
, "Should not be able to get himc from other process window\n");
652 static void test_ImmIsUIMessage(void)
660 static const struct test tests
[] =
662 { WM_MOUSEMOVE
, FALSE
},
663 { WM_IME_STARTCOMPOSITION
, TRUE
},
664 { WM_IME_ENDCOMPOSITION
, TRUE
},
665 { WM_IME_COMPOSITION
, TRUE
},
666 { WM_IME_SETCONTEXT
, TRUE
},
667 { WM_IME_NOTIFY
, TRUE
},
668 { WM_IME_CONTROL
, FALSE
},
669 { WM_IME_COMPOSITIONFULL
, TRUE
},
670 { WM_IME_SELECT
, TRUE
},
671 { WM_IME_CHAR
, FALSE
},
672 { 0x287 /* FIXME */, TRUE
},
673 { WM_IME_REQUEST
, FALSE
},
674 { WM_IME_KEYDOWN
, FALSE
},
675 { WM_IME_KEYUP
, FALSE
},
676 { 0, FALSE
} /* mark the end */
679 UINT WM_MSIME_SERVICE
= RegisterWindowMessageA("MSIMEService");
680 UINT WM_MSIME_RECONVERTOPTIONS
= RegisterWindowMessageA("MSIMEReconvertOptions");
681 UINT WM_MSIME_MOUSE
= RegisterWindowMessageA("MSIMEMouseOperation");
682 UINT WM_MSIME_RECONVERTREQUEST
= RegisterWindowMessageA("MSIMEReconvertRequest");
683 UINT WM_MSIME_RECONVERT
= RegisterWindowMessageA("MSIMEReconvert");
684 UINT WM_MSIME_QUERYPOSITION
= RegisterWindowMessageA("MSIMEQueryPosition");
685 UINT WM_MSIME_DOCUMENTFEED
= RegisterWindowMessageA("MSIMEDocumentFeed");
687 const struct test
*test
;
690 if (!pImmIsUIMessageA
) return;
692 for (test
= tests
; test
->msg
; test
++)
694 msg_spy_flush_msgs();
695 ret
= pImmIsUIMessageA(NULL
, test
->msg
, 0, 0);
696 ok(ret
== test
->ret
, "ImmIsUIMessageA returned %x for %x\n", ret
, test
->msg
);
697 ok(!msg_spy_find_msg(test
->msg
), "Windows does not send 0x%x for NULL hwnd\n", test
->msg
);
699 ret
= pImmIsUIMessageA(hwnd
, test
->msg
, 0, 0);
700 ok(ret
== test
->ret
, "ImmIsUIMessageA returned %x for %x\n", ret
, test
->msg
);
702 ok(msg_spy_find_msg(test
->msg
) != NULL
, "Windows does send 0x%x\n", test
->msg
);
704 ok(!msg_spy_find_msg(test
->msg
), "Windows does not send 0x%x\n", test
->msg
);
707 ret
= pImmIsUIMessageA(NULL
, WM_MSIME_SERVICE
, 0, 0);
708 ok(!ret
, "ImmIsUIMessageA returned TRUE for WM_MSIME_SERVICE\n");
709 ret
= pImmIsUIMessageA(NULL
, WM_MSIME_RECONVERTOPTIONS
, 0, 0);
710 ok(!ret
, "ImmIsUIMessageA returned TRUE for WM_MSIME_RECONVERTOPTIONS\n");
711 ret
= pImmIsUIMessageA(NULL
, WM_MSIME_MOUSE
, 0, 0);
712 ok(!ret
, "ImmIsUIMessageA returned TRUE for WM_MSIME_MOUSE\n");
713 ret
= pImmIsUIMessageA(NULL
, WM_MSIME_RECONVERTREQUEST
, 0, 0);
714 ok(!ret
, "ImmIsUIMessageA returned TRUE for WM_MSIME_RECONVERTREQUEST\n");
715 ret
= pImmIsUIMessageA(NULL
, WM_MSIME_RECONVERT
, 0, 0);
716 ok(!ret
, "ImmIsUIMessageA returned TRUE for WM_MSIME_RECONVERT\n");
717 ret
= pImmIsUIMessageA(NULL
, WM_MSIME_QUERYPOSITION
, 0, 0);
718 ok(!ret
, "ImmIsUIMessageA returned TRUE for WM_MSIME_QUERYPOSITION\n");
719 ret
= pImmIsUIMessageA(NULL
, WM_MSIME_DOCUMENTFEED
, 0, 0);
720 ok(!ret
, "ImmIsUIMessageA returned TRUE for WM_MSIME_DOCUMENTFEED\n");
723 static void test_ImmGetContext(void)
728 SetLastError(0xdeadbeef);
729 himc
= ImmGetContext((HWND
)0xffffffff);
730 err
= GetLastError();
731 ok(himc
== NULL
, "ImmGetContext succeeded\n");
732 ok(err
== ERROR_INVALID_WINDOW_HANDLE
, "got %u\n", err
);
734 himc
= ImmGetContext(hwnd
);
735 ok(himc
!= NULL
, "ImmGetContext failed\n");
736 ok(ImmReleaseContext(hwnd
, himc
), "ImmReleaseContext failed\n");
739 static void test_ImmGetDescription(void)
746 /* FIXME: invalid keyboard layouts should not pass */
747 ret
= ImmGetDescriptionW(NULL
, NULL
, 0);
748 ok(!ret
, "ImmGetDescriptionW failed, expected 0 received %d.\n", ret
);
749 ret
= ImmGetDescriptionA(NULL
, NULL
, 0);
750 ok(!ret
, "ImmGetDescriptionA failed, expected 0 received %d.\n", ret
);
752 /* load a language with valid IMM descriptions */
753 hkl
= GetKeyboardLayout(0);
754 ok(hkl
!= 0, "GetKeyboardLayout failed, expected != 0.\n");
756 ret
= ImmGetDescriptionW(hkl
, NULL
, 0);
759 win_skip("ImmGetDescriptionW is not working for current loaded keyboard.\n");
763 SetLastError(0xdeadcafe);
764 ret
= ImmGetDescriptionW(0, NULL
, 100);
765 ok (ret
== 0, "ImmGetDescriptionW with 0 hkl should return 0\n");
766 ret
= GetLastError();
767 ok (ret
== 0xdeadcafe, "Last Error should remain unchanged\n");
769 ret
= ImmGetDescriptionW(hkl
, descW
, 0);
770 ok(ret
, "ImmGetDescriptionW failed, expected != 0 received 0.\n");
772 lret
= ImmGetDescriptionW(hkl
, descW
, ret
+ 1);
773 ok(lret
, "ImmGetDescriptionW failed, expected != 0 received 0.\n");
774 ok(lret
== ret
, "ImmGetDescriptionW failed to return the correct amount of data. Expected %d, got %d.\n", ret
, lret
);
776 lret
= ImmGetDescriptionA(hkl
, descA
, ret
+ 1);
777 ok(lret
, "ImmGetDescriptionA failed, expected != 0 received 0.\n");
778 ok(lret
== ret
, "ImmGetDescriptionA failed to return the correct amount of data. Expected %d, got %d.\n", ret
, lret
);
780 ret
/= 2; /* try to copy partially */
781 lret
= ImmGetDescriptionW(hkl
, descW
, ret
+ 1);
782 ok(lret
, "ImmGetDescriptionW failed, expected != 0 received 0.\n");
783 ok(lret
== ret
, "ImmGetDescriptionW failed to return the correct amount of data. Expected %d, got %d.\n", ret
, lret
);
785 lret
= ImmGetDescriptionA(hkl
, descA
, ret
+ 1);
786 ok(!lret
, "ImmGetDescriptionA should fail\n");
788 ret
= ImmGetDescriptionW(hkl
, descW
, 1);
789 ok(!ret
, "ImmGetDescriptionW failed, expected 0 received %d.\n", ret
);
791 UnloadKeyboardLayout(hkl
);
794 static LRESULT (WINAPI
*old_imm_wnd_proc
)(HWND
, UINT
, WPARAM
, LPARAM
);
795 static LRESULT WINAPI
imm_wnd_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
797 ok(msg
!= WM_DESTROY
, "got WM_DESTROY message\n");
798 return old_imm_wnd_proc(hwnd
, msg
, wparam
, lparam
);
801 static HWND thread_ime_wnd
;
802 static DWORD WINAPI
test_ImmGetDefaultIMEWnd_thread(void *arg
)
804 CreateWindowA("static", "static", WS_POPUP
, 0, 0, 1, 1, NULL
, NULL
, NULL
, NULL
);
806 thread_ime_wnd
= ImmGetDefaultIMEWnd(0);
807 ok(thread_ime_wnd
!= 0, "ImmGetDefaultIMEWnd returned NULL\n");
808 old_imm_wnd_proc
= (void*)SetWindowLongPtrW(thread_ime_wnd
, GWLP_WNDPROC
, (LONG_PTR
)imm_wnd_proc
);
812 static void test_ImmDefaultHwnd(void)
814 HIMC imc1
, imc2
, imc3
;
819 hwnd
= CreateWindowExA(WS_EX_CLIENTEDGE
, "EDIT", "Wine imm32.dll test",
820 WS_OVERLAPPEDWINDOW
, CW_USEDEFAULT
, CW_USEDEFAULT
,
821 240, 120, NULL
, NULL
, GetModuleHandleW(NULL
), NULL
);
823 ShowWindow(hwnd
, SW_SHOWNORMAL
);
825 imc1
= ImmGetContext(hwnd
);
828 win_skip("IME support not implemented\n");
832 def1
= ImmGetDefaultIMEWnd(hwnd
);
834 imc2
= ImmCreateContext();
835 ImmSetOpenStatus(imc2
, TRUE
);
837 imc3
= ImmGetContext(hwnd
);
838 def3
= ImmGetDefaultIMEWnd(hwnd
);
840 ok(def3
== def1
, "Default IME window should not change\n");
841 ok(imc1
== imc3
, "IME context should not change\n");
842 ImmSetOpenStatus(imc2
, FALSE
);
844 thread
= CreateThread(NULL
, 0, test_ImmGetDefaultIMEWnd_thread
, NULL
, 0, NULL
);
845 WaitForSingleObject(thread
, INFINITE
);
846 ok(thread_ime_wnd
!= def1
, "thread_ime_wnd == def1\n");
847 ok(!IsWindow(thread_ime_wnd
), "thread_ime_wnd was not destroyed\n");
850 ImmReleaseContext(hwnd
, imc1
);
851 ImmReleaseContext(hwnd
, imc3
);
852 ImmDestroyContext(imc2
);
856 static void test_ImmGetIMCLockCount(void)
862 imc
= ImmCreateContext();
863 ImmDestroyContext(imc
);
864 SetLastError(0xdeadbeef);
865 count
= ImmGetIMCLockCount((HIMC
)0xdeadcafe);
866 ok(count
== 0, "Invalid IMC should return 0\n");
867 ret
= GetLastError();
868 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
869 SetLastError(0xdeadbeef);
870 count
= ImmGetIMCLockCount(0x00000000);
871 ok(count
== 0, "NULL IMC should return 0\n");
872 ret
= GetLastError();
873 ok(ret
== 0xdeadbeef, "Last Error should remain unchanged: %08x\n",ret
);
874 count
= ImmGetIMCLockCount(imc
);
875 ok(count
== 0, "Destroyed IMC should return 0\n");
876 ret
= GetLastError();
877 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
879 imc
= ImmCreateContext();
880 count
= ImmGetIMCLockCount(imc
);
881 ok(count
== 0, "expect 0, returned %d\n", count
);
882 ic
= ImmLockIMC(imc
);
883 ok(ic
!= NULL
, "ImmLockIMC failed!\n");
884 count
= ImmGetIMCLockCount(imc
);
885 ok(count
== 1, "expect 1, returned %d\n", count
);
886 ret
= ImmUnlockIMC(imc
);
887 ok(ret
== TRUE
, "expect TRUE, ret %d\n", ret
);
888 count
= ImmGetIMCLockCount(imc
);
889 ok(count
== 0, "expect 0, returned %d\n", count
);
890 ret
= ImmUnlockIMC(imc
);
891 ok(ret
== TRUE
, "expect TRUE, ret %d\n", ret
);
892 count
= ImmGetIMCLockCount(imc
);
893 ok(count
== 0, "expect 0, returned %d\n", count
);
895 for (i
= 0; i
< GMEM_LOCKCOUNT
* 2; i
++)
897 ic
= ImmLockIMC(imc
);
898 ok(ic
!= NULL
, "ImmLockIMC failed!\n");
900 count
= ImmGetIMCLockCount(imc
);
901 todo_wine
ok(count
== GMEM_LOCKCOUNT
, "expect GMEM_LOCKCOUNT, returned %d\n", count
);
903 for (i
= 0; i
< GMEM_LOCKCOUNT
- 1; i
++)
905 count
= ImmGetIMCLockCount(imc
);
906 todo_wine
ok(count
== 1, "expect 1, returned %d\n", count
);
908 count
= ImmGetIMCLockCount(imc
);
909 todo_wine
ok(count
== 0, "expect 0, returned %d\n", count
);
911 ImmDestroyContext(imc
);
914 static void test_ImmGetIMCCLockCount(void)
917 DWORD count
, g_count
, i
;
921 imcc
= ImmCreateIMCC(sizeof(CANDIDATEINFO
));
922 count
= ImmGetIMCCLockCount(imcc
);
923 ok(count
== 0, "expect 0, returned %d\n", count
);
925 count
= ImmGetIMCCLockCount(imcc
);
926 ok(count
== 1, "expect 1, returned %d\n", count
);
927 ret
= ImmUnlockIMCC(imcc
);
928 ok(ret
== FALSE
, "expect FALSE, ret %d\n", ret
);
929 count
= ImmGetIMCCLockCount(imcc
);
930 ok(count
== 0, "expect 0, returned %d\n", count
);
931 ret
= ImmUnlockIMCC(imcc
);
932 ok(ret
== FALSE
, "expect FALSE, ret %d\n", ret
);
933 count
= ImmGetIMCCLockCount(imcc
);
934 ok(count
== 0, "expect 0, returned %d\n", count
);
936 p
= ImmLockIMCC(imcc
);
937 ok(GlobalHandle(p
) == imcc
, "expect %p, returned %p\n", imcc
, GlobalHandle(p
));
939 for (i
= 0; i
< GMEM_LOCKCOUNT
* 2; i
++)
942 count
= ImmGetIMCCLockCount(imcc
);
943 g_count
= GlobalFlags(imcc
) & GMEM_LOCKCOUNT
;
944 ok(count
== g_count
, "count %d, g_count %d\n", count
, g_count
);
946 count
= ImmGetIMCCLockCount(imcc
);
947 ok(count
== GMEM_LOCKCOUNT
, "expect GMEM_LOCKCOUNT, returned %d\n", count
);
949 for (i
= 0; i
< GMEM_LOCKCOUNT
- 1; i
++)
951 count
= ImmGetIMCCLockCount(imcc
);
952 ok(count
== 1, "expect 1, returned %d\n", count
);
954 count
= ImmGetIMCCLockCount(imcc
);
955 ok(count
== 0, "expect 0, returned %d\n", count
);
957 ImmDestroyIMCC(imcc
);
960 static void test_ImmDestroyContext(void)
966 imc
= ImmCreateContext();
967 count
= ImmGetIMCLockCount(imc
);
968 ok(count
== 0, "expect 0, returned %d\n", count
);
969 ic
= ImmLockIMC(imc
);
970 ok(ic
!= NULL
, "ImmLockIMC failed!\n");
971 count
= ImmGetIMCLockCount(imc
);
972 ok(count
== 1, "expect 1, returned %d\n", count
);
973 ret
= ImmDestroyContext(imc
);
974 ok(ret
== TRUE
, "Destroy a locked IMC should success!\n");
975 ic
= ImmLockIMC(imc
);
976 ok(ic
== NULL
, "Lock a destroyed IMC should fail!\n");
977 ret
= ImmUnlockIMC(imc
);
978 ok(ret
== FALSE
, "Unlock a destroyed IMC should fail!\n");
979 count
= ImmGetIMCLockCount(imc
);
980 ok(count
== 0, "Get lock count of a destroyed IMC should return 0!\n");
981 SetLastError(0xdeadbeef);
982 ret
= ImmDestroyContext(imc
);
983 ok(ret
== FALSE
, "Destroy a destroyed IMC should fail!\n");
984 ret
= GetLastError();
985 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
988 static void test_ImmDestroyIMCC(void)
991 DWORD ret
, count
, size
;
994 imcc
= ImmCreateIMCC(sizeof(CANDIDATEINFO
));
995 count
= ImmGetIMCCLockCount(imcc
);
996 ok(count
== 0, "expect 0, returned %d\n", count
);
997 p
= ImmLockIMCC(imcc
);
998 ok(p
!= NULL
, "ImmLockIMCC failed!\n");
999 count
= ImmGetIMCCLockCount(imcc
);
1000 ok(count
== 1, "expect 1, returned %d\n", count
);
1001 size
= ImmGetIMCCSize(imcc
);
1002 ok(size
== sizeof(CANDIDATEINFO
), "returned %d\n", size
);
1003 p
= ImmDestroyIMCC(imcc
);
1004 ok(p
== NULL
, "Destroy a locked IMCC should success!\n");
1005 p
= ImmLockIMCC(imcc
);
1006 ok(p
== NULL
, "Lock a destroyed IMCC should fail!\n");
1007 ret
= ImmUnlockIMCC(imcc
);
1008 ok(ret
== FALSE
, "Unlock a destroyed IMCC should return FALSE!\n");
1009 count
= ImmGetIMCCLockCount(imcc
);
1010 ok(count
== 0, "Get lock count of a destroyed IMCC should return 0!\n");
1011 size
= ImmGetIMCCSize(imcc
);
1012 ok(size
== 0, "Get size of a destroyed IMCC should return 0!\n");
1013 SetLastError(0xdeadbeef);
1014 p
= ImmDestroyIMCC(imcc
);
1015 ok(p
!= NULL
, "returned NULL\n");
1016 ret
= GetLastError();
1017 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1020 static void test_ImmMessages(void)
1028 LPINPUTCONTEXT lpIMC
;
1029 LPTRANSMSG lpTransMsg
;
1031 HWND hwnd
= CreateWindowExA(WS_EX_CLIENTEDGE
, "EDIT", "Wine imm32.dll test",
1032 WS_OVERLAPPEDWINDOW
, CW_USEDEFAULT
, CW_USEDEFAULT
,
1033 240, 120, NULL
, NULL
, GetModuleHandleA(NULL
), NULL
);
1035 ShowWindow(hwnd
, SW_SHOWNORMAL
);
1036 defwnd
= ImmGetDefaultIMEWnd(hwnd
);
1037 imc
= ImmGetContext(hwnd
);
1039 ImmSetOpenStatus(imc
, TRUE
);
1040 msg_spy_flush_msgs();
1041 SendMessageA(defwnd
, WM_IME_CONTROL
, IMC_GETCANDIDATEPOS
, (LPARAM
)&cf
);
1044 msg
= msg_spy_find_next_msg(WM_IME_CONTROL
,&idx
);
1045 if (msg
) ok(!msg
->post
, "Message should not be posted\n");
1047 msg_spy_flush_msgs();
1049 lpIMC
= ImmLockIMC(imc
);
1050 lpIMC
->hMsgBuf
= ImmReSizeIMCC(lpIMC
->hMsgBuf
, (lpIMC
->dwNumMsgBuf
+ 1) * sizeof(TRANSMSG
));
1051 lpTransMsg
= ImmLockIMCC(lpIMC
->hMsgBuf
);
1052 lpTransMsg
+= lpIMC
->dwNumMsgBuf
;
1053 lpTransMsg
->message
= WM_IME_STARTCOMPOSITION
;
1054 lpTransMsg
->wParam
= 0;
1055 lpTransMsg
->lParam
= 0;
1056 ImmUnlockIMCC(lpIMC
->hMsgBuf
);
1057 lpIMC
->dwNumMsgBuf
++;
1059 ImmGenerateMessage(imc
);
1063 msg
= msg_spy_find_next_msg(WM_IME_STARTCOMPOSITION
, &idx
);
1064 if (msg
) ok(!msg
->post
, "Message should not be posted\n");
1066 msg_spy_flush_msgs();
1068 lpIMC
= ImmLockIMC(imc
);
1069 lpIMC
->hMsgBuf
= ImmReSizeIMCC(lpIMC
->hMsgBuf
, (lpIMC
->dwNumMsgBuf
+ 1) * sizeof(TRANSMSG
));
1070 lpTransMsg
= ImmLockIMCC(lpIMC
->hMsgBuf
);
1071 lpTransMsg
+= lpIMC
->dwNumMsgBuf
;
1072 lpTransMsg
->message
= WM_IME_COMPOSITION
;
1073 lpTransMsg
->wParam
= 0;
1074 lpTransMsg
->lParam
= 0;
1075 ImmUnlockIMCC(lpIMC
->hMsgBuf
);
1076 lpIMC
->dwNumMsgBuf
++;
1078 ImmGenerateMessage(imc
);
1082 msg
= msg_spy_find_next_msg(WM_IME_COMPOSITION
, &idx
);
1083 if (msg
) ok(!msg
->post
, "Message should not be posted\n");
1085 msg_spy_flush_msgs();
1087 lpIMC
= ImmLockIMC(imc
);
1088 lpIMC
->hMsgBuf
= ImmReSizeIMCC(lpIMC
->hMsgBuf
, (lpIMC
->dwNumMsgBuf
+ 1) * sizeof(TRANSMSG
));
1089 lpTransMsg
= ImmLockIMCC(lpIMC
->hMsgBuf
);
1090 lpTransMsg
+= lpIMC
->dwNumMsgBuf
;
1091 lpTransMsg
->message
= WM_IME_ENDCOMPOSITION
;
1092 lpTransMsg
->wParam
= 0;
1093 lpTransMsg
->lParam
= 0;
1094 ImmUnlockIMCC(lpIMC
->hMsgBuf
);
1095 lpIMC
->dwNumMsgBuf
++;
1097 ImmGenerateMessage(imc
);
1101 msg
= msg_spy_find_next_msg(WM_IME_ENDCOMPOSITION
, &idx
);
1102 if (msg
) ok(!msg
->post
, "Message should not be posted\n");
1104 msg_spy_flush_msgs();
1106 ImmSetOpenStatus(imc
, FALSE
);
1107 ImmReleaseContext(hwnd
, imc
);
1108 DestroyWindow(hwnd
);
1111 static LRESULT CALLBACK
processkey_wnd_proc( HWND hWnd
, UINT msg
, WPARAM wParam
,
1114 return DefWindowProcW(hWnd
, msg
, wParam
, lParam
);
1117 static void test_ime_processkey(void)
1119 WCHAR classNameW
[] = {'P','r','o','c','e','s','s', 'K','e','y','T','e','s','t','C','l','a','s','s',0};
1120 WCHAR windowNameW
[] = {'P','r','o','c','e','s','s', 'K','e','y',0};
1124 HANDLE hInstance
= GetModuleHandleW(NULL
);
1125 TEST_INPUT inputs
[2];
1130 wclass
.lpszClassName
= classNameW
;
1131 wclass
.style
= CS_HREDRAW
| CS_VREDRAW
;
1132 wclass
.lpfnWndProc
= processkey_wnd_proc
;
1133 wclass
.hInstance
= hInstance
;
1134 wclass
.hIcon
= LoadIconW(0, (LPCWSTR
)IDI_APPLICATION
);
1135 wclass
.hCursor
= LoadCursorW( NULL
, (LPCWSTR
)IDC_ARROW
);
1136 wclass
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
1137 wclass
.lpszMenuName
= 0;
1138 wclass
.cbClsExtra
= 0;
1139 wclass
.cbWndExtra
= 0;
1140 if(!RegisterClassW(&wclass
)){
1141 win_skip("Failed to register window.\n");
1145 /* create the test window that will receive the keystrokes */
1146 hWndTest
= CreateWindowW(wclass
.lpszClassName
, windowNameW
,
1147 WS_OVERLAPPEDWINDOW
, CW_USEDEFAULT
, 0, 100, 100,
1148 NULL
, NULL
, hInstance
, NULL
);
1150 ShowWindow(hWndTest
, SW_SHOW
);
1151 SetWindowPos(hWndTest
, HWND_TOPMOST
, 0, 0, 0, 0, SWP_NOSIZE
|SWP_NOMOVE
);
1152 SetForegroundWindow(hWndTest
);
1153 UpdateWindow(hWndTest
);
1155 imc
= ImmGetContext(hWndTest
);
1158 win_skip("IME not supported\n");
1159 DestroyWindow(hWndTest
);
1163 rc
= ImmSetOpenStatus(imc
, TRUE
);
1166 win_skip("Unable to open IME\n");
1167 ImmReleaseContext(hWndTest
, imc
);
1168 DestroyWindow(hWndTest
);
1172 /* flush pending messages */
1173 while (PeekMessageW(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageW(&msg
);
1177 /* init input data that never changes */
1178 inputs
[1].type
= inputs
[0].type
= INPUT_KEYBOARD
;
1179 inputs
[1].u
.ki
.dwExtraInfo
= inputs
[0].u
.ki
.dwExtraInfo
= 0;
1180 inputs
[1].u
.ki
.time
= inputs
[0].u
.ki
.time
= 0;
1182 /* Pressing a key */
1183 inputs
[0].u
.ki
.wVk
= 0x41;
1184 inputs
[0].u
.ki
.wScan
= 0x1e;
1185 inputs
[0].u
.ki
.dwFlags
= 0x0;
1187 pSendInput(1, (INPUT
*)inputs
, sizeof(INPUT
));
1189 while(PeekMessageW(&msg
, hWndTest
, 0, 0, PM_NOREMOVE
)) {
1190 if(msg
.message
!= WM_KEYDOWN
)
1191 PeekMessageW(&msg
, hWndTest
, 0, 0, PM_REMOVE
);
1194 ok(msg
.wParam
!= VK_PROCESSKEY
,"Incorrect ProcessKey Found\n");
1195 PeekMessageW(&msg
, hWndTest
, 0, 0, PM_REMOVE
);
1196 if(msg
.wParam
== VK_PROCESSKEY
)
1197 trace("ProcessKey was correctly found\n");
1199 TranslateMessage(&msg
);
1200 DispatchMessageW(&msg
);
1203 inputs
[0].u
.ki
.wVk
= 0x41;
1204 inputs
[0].u
.ki
.wScan
= 0x1e;
1205 inputs
[0].u
.ki
.dwFlags
= KEYEVENTF_KEYUP
;
1207 pSendInput(1, (INPUT
*)inputs
, sizeof(INPUT
));
1209 while(PeekMessageW(&msg
, hWndTest
, 0, 0, PM_NOREMOVE
)) {
1210 if(msg
.message
!= WM_KEYUP
)
1211 PeekMessageW(&msg
, hWndTest
, 0, 0, PM_REMOVE
);
1214 ok(msg
.wParam
!= VK_PROCESSKEY
,"Incorrect ProcessKey Found\n");
1215 PeekMessageW(&msg
, hWndTest
, 0, 0, PM_REMOVE
);
1216 ok(msg
.wParam
!= VK_PROCESSKEY
,"ProcessKey should still not be Found\n");
1218 TranslateMessage(&msg
);
1219 DispatchMessageW(&msg
);
1222 ImmReleaseContext(hWndTest
, imc
);
1223 ImmSetOpenStatus(imc
, FALSE
);
1224 DestroyWindow(hWndTest
);
1227 static void test_InvalidIMC(void)
1230 HIMC imc_null
= 0x00000000;
1231 HIMC imc_bad
= (HIMC
)0xdeadcafe;
1233 HIMC imc1
, imc2
, oldimc
;
1240 memset(&lf
, 0, sizeof(lf
));
1242 imc_destroy
= ImmCreateContext();
1243 ret
= ImmDestroyContext(imc_destroy
);
1244 ok(ret
== TRUE
, "Destroy an IMC should success!\n");
1246 /* Test associating destroyed imc */
1247 imc1
= ImmGetContext(hwnd
);
1248 SetLastError(0xdeadbeef);
1249 oldimc
= ImmAssociateContext(hwnd
, imc_destroy
);
1250 ok(!oldimc
, "Associating to a destroyed imc should fail!\n");
1251 ret
= GetLastError();
1252 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1253 imc2
= ImmGetContext(hwnd
);
1254 ok(imc1
== imc2
, "imc should not changed! imc1 %p, imc2 %p\n", imc1
, imc2
);
1256 /* Test associating NULL imc, which is different from an invalid imc */
1257 oldimc
= ImmAssociateContext(hwnd
, imc_null
);
1258 ok(oldimc
!= NULL
, "Associating to NULL imc should success!\n");
1259 imc2
= ImmGetContext(hwnd
);
1260 ok(!imc2
, "expect NULL, returned %p\n", imc2
);
1261 oldimc
= ImmAssociateContext(hwnd
, imc1
);
1262 ok(!oldimc
, "expect NULL, returned %p\n", oldimc
);
1263 imc2
= ImmGetContext(hwnd
);
1264 ok(imc2
== imc1
, "imc should not changed! imc2 %p, imc1 %p\n", imc2
, imc1
);
1266 /* Test associating invalid imc */
1267 imc1
= ImmGetContext(hwnd
);
1268 SetLastError(0xdeadbeef);
1269 oldimc
= ImmAssociateContext(hwnd
, imc_bad
);
1270 ok(!oldimc
, "Associating to a destroyed imc should fail!\n");
1271 ret
= GetLastError();
1272 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1273 imc2
= ImmGetContext(hwnd
);
1274 ok(imc1
== imc2
, "imc should not changed! imc1 %p, imc2 %p\n", imc1
, imc2
);
1277 /* Test ImmGetCandidateListA */
1278 SetLastError(0xdeadbeef);
1279 ret
= ImmGetCandidateListA(imc_bad
, 0, NULL
, 0);
1280 ok(ret
== 0, "Bad IME should return 0\n");
1281 ret
= GetLastError();
1282 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1283 SetLastError(0xdeadbeef);
1284 ret
= ImmGetCandidateListA(imc_null
, 0, NULL
, 0);
1285 ok(ret
== 0, "NULL IME should return 0\n");
1286 ret
= GetLastError();
1287 ok(ret
== 0xdeadbeef, "last error should remain unchanged %08x!\n", ret
);
1288 SetLastError(0xdeadbeef);
1289 ret
= ImmGetCandidateListA(imc_destroy
, 0, NULL
, 0);
1290 ok(ret
== 0, "Destroyed IME should return 0\n");
1291 ret
= GetLastError();
1292 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1294 /* Test ImmGetCandidateListCountA*/
1295 SetLastError(0xdeadbeef);
1296 ret
= ImmGetCandidateListCountA(imc_bad
,&count
);
1297 ok(ret
== 0, "Bad IME should return 0\n");
1298 ret
= GetLastError();
1299 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1300 SetLastError(0xdeadbeef);
1301 ret
= ImmGetCandidateListCountA(imc_null
,&count
);
1302 ok(ret
== 0, "NULL IME should return 0\n");
1303 ret
= GetLastError();
1304 ok(ret
== 0xdeadbeef, "last error should remain unchanged %08x!\n", ret
);
1305 SetLastError(0xdeadbeef);
1306 ret
= ImmGetCandidateListCountA(imc_destroy
,&count
);
1307 ok(ret
== 0, "Destroyed IME should return 0\n");
1308 ret
= GetLastError();
1309 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1311 /* Test ImmGetCandidateWindow */
1312 SetLastError(0xdeadbeef);
1313 ret
= ImmGetCandidateWindow(imc_bad
, 0, (LPCANDIDATEFORM
)buffer
);
1314 ok(ret
== 0, "Bad IME should return 0\n");
1315 ret
= GetLastError();
1316 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1317 SetLastError(0xdeadbeef);
1318 ret
= ImmGetCandidateWindow(imc_null
, 0, (LPCANDIDATEFORM
)buffer
);
1319 ok(ret
== 0, "NULL IME should return 0\n");
1320 ret
= GetLastError();
1321 ok(ret
== 0xdeadbeef, "last error should remain unchanged %08x!\n", ret
);
1322 SetLastError(0xdeadbeef);
1323 ret
= ImmGetCandidateWindow(imc_destroy
, 0, (LPCANDIDATEFORM
)buffer
);
1324 ok(ret
== 0, "Destroyed IME should return 0\n");
1325 ret
= GetLastError();
1326 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1328 /* Test ImmGetCompositionFontA */
1329 SetLastError(0xdeadbeef);
1330 ret
= ImmGetCompositionFontA(imc_bad
, (LPLOGFONTA
)buffer
);
1331 ok(ret
== 0, "Bad IME should return 0\n");
1332 ret
= GetLastError();
1333 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1334 SetLastError(0xdeadbeef);
1335 ret
= ImmGetCompositionFontA(imc_null
, (LPLOGFONTA
)buffer
);
1336 ok(ret
== 0, "NULL IME should return 0\n");
1337 ret
= GetLastError();
1338 ok(ret
== 0xdeadbeef, "last error should remain unchanged %08x!\n", ret
);
1339 SetLastError(0xdeadbeef);
1340 ret
= ImmGetCompositionFontA(imc_destroy
, (LPLOGFONTA
)buffer
);
1341 ok(ret
== 0, "Destroyed IME should return 0\n");
1342 ret
= GetLastError();
1343 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1345 /* Test ImmGetCompositionWindow */
1346 SetLastError(0xdeadbeef);
1347 ret
= ImmGetCompositionWindow(imc_bad
, (LPCOMPOSITIONFORM
)buffer
);
1348 ok(ret
== 0, "Bad IME should return 0\n");
1349 ret
= GetLastError();
1350 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1351 SetLastError(0xdeadbeef);
1352 ret
= ImmGetCompositionWindow(imc_null
, (LPCOMPOSITIONFORM
)buffer
);
1353 ok(ret
== 0, "NULL IME should return 0\n");
1354 ret
= GetLastError();
1355 ok(ret
== 0xdeadbeef, "last error should remain unchanged %08x!\n", ret
);
1356 SetLastError(0xdeadbeef);
1357 ret
= ImmGetCompositionWindow(imc_destroy
, (LPCOMPOSITIONFORM
)buffer
);
1358 ok(ret
== 0, "Destroyed IME should return 0\n");
1359 ret
= GetLastError();
1360 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1362 /* Test ImmGetCompositionStringA */
1363 SetLastError(0xdeadbeef);
1364 ret
= ImmGetCompositionStringA(imc_bad
, GCS_COMPSTR
, NULL
, 0);
1365 ok(ret
== 0, "Bad IME should return 0\n");
1366 ret
= GetLastError();
1367 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1368 SetLastError(0xdeadbeef);
1369 ret
= ImmGetCompositionStringA(imc_null
, GCS_COMPSTR
, NULL
, 0);
1370 ok(ret
== 0, "NULL IME should return 0\n");
1371 ret
= GetLastError();
1372 ok(ret
== 0xdeadbeef, "last error should remain unchanged %08x!\n", ret
);
1373 SetLastError(0xdeadbeef);
1374 ret
= ImmGetCompositionStringA(imc_destroy
, GCS_COMPSTR
, NULL
, 0);
1375 ok(ret
== 0, "Destroyed IME should return 0\n");
1376 ret
= GetLastError();
1377 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1379 /* Test ImmSetOpenStatus */
1380 SetLastError(0xdeadbeef);
1381 ret
= ImmSetOpenStatus(imc_bad
, 1);
1382 ok(ret
== 0, "Bad IME should return 0\n");
1383 ret
= GetLastError();
1384 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1385 SetLastError(0xdeadbeef);
1386 ret
= ImmSetOpenStatus(imc_null
, 1);
1387 ok(ret
== 0, "NULL IME should return 0\n");
1388 ret
= GetLastError();
1389 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1390 SetLastError(0xdeadbeef);
1391 ret
= ImmSetOpenStatus(imc_destroy
, 1);
1392 ok(ret
== 0, "Destroyed IME should return 0\n");
1393 ret
= GetLastError();
1394 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1396 /* Test ImmGetOpenStatus */
1397 SetLastError(0xdeadbeef);
1398 ret
= ImmGetOpenStatus(imc_bad
);
1399 ok(ret
== 0, "Bad IME should return 0\n");
1400 ret
= GetLastError();
1401 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1402 SetLastError(0xdeadbeef);
1403 ret
= ImmGetOpenStatus(imc_null
);
1404 ok(ret
== 0, "NULL IME should return 0\n");
1405 ret
= GetLastError();
1406 ok(ret
== 0xdeadbeef, "last error should remain unchanged %08x!\n", ret
);
1407 SetLastError(0xdeadbeef);
1408 ret
= ImmGetOpenStatus(imc_destroy
);
1409 ok(ret
== 0, "Destroyed IME should return 0\n");
1410 ret
= GetLastError();
1411 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1413 /* Test ImmGetStatusWindowPos */
1414 SetLastError(0xdeadbeef);
1415 ret
= ImmGetStatusWindowPos(imc_bad
, NULL
);
1416 ok(ret
== 0, "Bad IME should return 0\n");
1417 ret
= GetLastError();
1418 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1419 SetLastError(0xdeadbeef);
1420 ret
= ImmGetStatusWindowPos(imc_null
, NULL
);
1421 ok(ret
== 0, "NULL IME should return 0\n");
1422 ret
= GetLastError();
1423 ok(ret
== 0xdeadbeef, "last error should remain unchanged %08x!\n", ret
);
1424 SetLastError(0xdeadbeef);
1425 ret
= ImmGetStatusWindowPos(imc_destroy
, NULL
);
1426 ok(ret
== 0, "Destroyed IME should return 0\n");
1427 ret
= GetLastError();
1428 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1430 /* Test ImmRequestMessageA */
1431 SetLastError(0xdeadbeef);
1432 ret
= ImmRequestMessageA(imc_bad
, WM_CHAR
, 0);
1433 ok(ret
== 0, "Bad IME should return 0\n");
1434 ret
= GetLastError();
1435 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1436 SetLastError(0xdeadbeef);
1437 ret
= ImmRequestMessageA(imc_null
, WM_CHAR
, 0);
1438 ok(ret
== 0, "NULL IME should return 0\n");
1439 ret
= GetLastError();
1440 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1441 SetLastError(0xdeadbeef);
1442 ret
= ImmRequestMessageA(imc_destroy
, WM_CHAR
, 0);
1443 ok(ret
== 0, "Destroyed IME should return 0\n");
1444 ret
= GetLastError();
1445 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1447 /* Test ImmSetCompositionFontA */
1448 SetLastError(0xdeadbeef);
1449 ret
= ImmSetCompositionFontA(imc_bad
, &lf
);
1450 ok(ret
== 0, "Bad IME should return 0\n");
1451 ret
= GetLastError();
1452 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1453 SetLastError(0xdeadbeef);
1454 ret
= ImmSetCompositionFontA(imc_null
, &lf
);
1455 ok(ret
== 0, "NULL IME should return 0\n");
1456 ret
= GetLastError();
1457 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1458 SetLastError(0xdeadbeef);
1459 ret
= ImmSetCompositionFontA(imc_destroy
, &lf
);
1460 ok(ret
== 0, "Destroyed IME should return 0\n");
1461 ret
= GetLastError();
1462 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1464 /* Test ImmSetCompositionWindow */
1465 SetLastError(0xdeadbeef);
1466 ret
= ImmSetCompositionWindow(imc_bad
, NULL
);
1467 ok(ret
== 0, "Bad IME should return 0\n");
1468 ret
= GetLastError();
1469 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1470 SetLastError(0xdeadbeef);
1471 ret
= ImmSetCompositionWindow(imc_null
, NULL
);
1472 ok(ret
== 0, "NULL IME should return 0\n");
1473 ret
= GetLastError();
1474 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1475 SetLastError(0xdeadbeef);
1476 ret
= ImmSetCompositionWindow(imc_destroy
, NULL
);
1477 ok(ret
== 0, "Destroyed IME should return 0\n");
1478 ret
= GetLastError();
1479 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1481 /* Test ImmSetConversionStatus */
1482 SetLastError(0xdeadbeef);
1483 ret
= ImmSetConversionStatus(imc_bad
, 0, 0);
1484 ok(ret
== 0, "Bad IME should return 0\n");
1485 ret
= GetLastError();
1486 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1487 SetLastError(0xdeadbeef);
1488 ret
= ImmSetConversionStatus(imc_null
, 0, 0);
1489 ok(ret
== 0, "NULL IME should return 0\n");
1490 ret
= GetLastError();
1491 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1492 SetLastError(0xdeadbeef);
1493 ret
= ImmSetConversionStatus(imc_destroy
, 0, 0);
1494 ok(ret
== 0, "Destroyed IME should return 0\n");
1495 ret
= GetLastError();
1496 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1498 /* Test ImmSetStatusWindowPos */
1499 SetLastError(0xdeadbeef);
1500 ret
= ImmSetStatusWindowPos(imc_bad
, 0);
1501 ok(ret
== 0, "Bad IME should return 0\n");
1502 ret
= GetLastError();
1503 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1504 SetLastError(0xdeadbeef);
1505 ret
= ImmSetStatusWindowPos(imc_null
, 0);
1506 ok(ret
== 0, "NULL IME should return 0\n");
1507 ret
= GetLastError();
1508 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1509 SetLastError(0xdeadbeef);
1510 ret
= ImmSetStatusWindowPos(imc_destroy
, 0);
1511 ok(ret
== 0, "Destroyed IME should return 0\n");
1512 ret
= GetLastError();
1513 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1515 /* Test ImmGetImeMenuItemsA */
1516 SetLastError(0xdeadbeef);
1517 ret
= ImmGetImeMenuItemsA(imc_bad
, 0, 0, NULL
, NULL
, 0);
1518 ok(ret
== 0, "Bad IME should return 0\n");
1519 ret
= GetLastError();
1520 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1521 SetLastError(0xdeadbeef);
1522 ret
= ImmGetImeMenuItemsA(imc_null
, 0, 0, NULL
, NULL
, 0);
1523 ok(ret
== 0, "NULL IME should return 0\n");
1524 ret
= GetLastError();
1525 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1526 SetLastError(0xdeadbeef);
1527 ret
= ImmGetImeMenuItemsA(imc_destroy
, 0, 0, NULL
, NULL
, 0);
1528 ok(ret
== 0, "Destroyed IME should return 0\n");
1529 ret
= GetLastError();
1530 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1532 /* Test ImmLockIMC */
1533 SetLastError(0xdeadbeef);
1534 ic
= ImmLockIMC(imc_bad
);
1535 ok(ic
== 0, "Bad IME should return 0\n");
1536 ret
= GetLastError();
1537 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1538 SetLastError(0xdeadbeef);
1539 ic
= ImmLockIMC(imc_null
);
1540 ok(ic
== 0, "NULL IME should return 0\n");
1541 ret
= GetLastError();
1542 ok(ret
== 0xdeadbeef, "last error should remain unchanged %08x!\n", ret
);
1543 SetLastError(0xdeadbeef);
1544 ic
= ImmLockIMC(imc_destroy
);
1545 ok(ic
== 0, "Destroyed IME should return 0\n");
1546 ret
= GetLastError();
1547 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1549 /* Test ImmUnlockIMC */
1550 SetLastError(0xdeadbeef);
1551 ret
= ImmUnlockIMC(imc_bad
);
1552 ok(ret
== 0, "Bad IME should return 0\n");
1553 ret
= GetLastError();
1554 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1555 SetLastError(0xdeadbeef);
1556 ret
= ImmUnlockIMC(imc_null
);
1557 ok(ret
== 0, "NULL IME should return 0\n");
1558 ret
= GetLastError();
1559 ok(ret
== 0xdeadbeef, "last error should remain unchanged %08x!\n", ret
);
1560 SetLastError(0xdeadbeef);
1561 ret
= ImmUnlockIMC(imc_destroy
);
1562 ok(ret
== 0, "Destroyed IME should return 0\n");
1563 ret
= GetLastError();
1564 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1566 /* Test ImmGenerateMessage */
1567 SetLastError(0xdeadbeef);
1568 ret
= ImmGenerateMessage(imc_bad
);
1569 ok(ret
== 0, "Bad IME should return 0\n");
1570 ret
= GetLastError();
1571 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1572 SetLastError(0xdeadbeef);
1573 ret
= ImmGenerateMessage(imc_null
);
1574 ok(ret
== 0, "NULL IME should return 0\n");
1575 ret
= GetLastError();
1576 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1577 SetLastError(0xdeadbeef);
1578 ret
= ImmGenerateMessage(imc_destroy
);
1579 ok(ret
== 0, "Destroyed IME should return 0\n");
1580 ret
= GetLastError();
1581 ok(ret
== ERROR_INVALID_HANDLE
, "wrong last error %08x!\n", ret
);
1587 test_ImmNotifyIME();
1588 test_ImmGetCompositionString();
1589 test_ImmSetCompositionString();
1591 test_ImmAssociateContextEx();
1593 test_ImmIsUIMessage();
1594 test_ImmGetContext();
1595 test_ImmGetDescription();
1596 test_ImmDefaultHwnd();
1597 test_ImmGetIMCLockCount();
1598 test_ImmGetIMCCLockCount();
1599 test_ImmDestroyContext();
1600 test_ImmDestroyIMCC();
1603 /* Reinitialize the hooks to capture all windows */
1608 test_ime_processkey();
1609 else win_skip("SendInput is not available\n");