2008-04-04 16:43:16 +00:00
|
|
|
/*
|
|
|
|
* Unit tests for imm32
|
|
|
|
*
|
|
|
|
* Copyright (c) 2008 Michael Jung
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include "wine/test.h"
|
|
|
|
#include "winuser.h"
|
2011-12-15 00:39:37 +00:00
|
|
|
#include "wingdi.h"
|
2008-04-04 16:43:16 +00:00
|
|
|
#include "imm.h"
|
2013-12-01 15:57:54 +00:00
|
|
|
#include "ddk/imm.h"
|
2008-04-04 16:43:16 +00:00
|
|
|
|
|
|
|
#define NUMELEMS(array) (sizeof((array))/sizeof((array)[0]))
|
|
|
|
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
static BOOL (WINAPI *pImmAssociateContextEx)(HWND,HIMC,DWORD);
|
2011-12-15 00:39:37 +00:00
|
|
|
static BOOL (WINAPI *pImmIsUIMessageA)(HWND,UINT,WPARAM,LPARAM);
|
2013-12-01 15:57:54 +00:00
|
|
|
static UINT (WINAPI *pSendInput) (UINT, INPUT*, size_t);
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
|
2008-04-04 16:43:16 +00:00
|
|
|
/*
|
|
|
|
* msgspy - record and analyse message traces sent to a certain window
|
|
|
|
*/
|
2013-02-03 20:58:19 +00:00
|
|
|
typedef struct _msgs {
|
|
|
|
CWPSTRUCT msg;
|
|
|
|
BOOL post;
|
|
|
|
} imm_msgs;
|
|
|
|
|
2008-04-04 16:43:16 +00:00
|
|
|
static struct _msg_spy {
|
|
|
|
HWND hwnd;
|
|
|
|
HHOOK get_msg_hook;
|
|
|
|
HHOOK call_wnd_proc_hook;
|
2016-08-18 10:08:05 +00:00
|
|
|
imm_msgs msgs[64];
|
2008-04-04 16:43:16 +00:00
|
|
|
unsigned int i_msg;
|
|
|
|
} msg_spy;
|
|
|
|
|
2013-12-01 15:57:54 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
DWORD type;
|
|
|
|
union
|
|
|
|
{
|
|
|
|
MOUSEINPUT mi;
|
|
|
|
KEYBDINPUT ki;
|
|
|
|
HARDWAREINPUT hi;
|
|
|
|
} u;
|
|
|
|
} TEST_INPUT;
|
|
|
|
|
2016-08-18 10:08:05 +00:00
|
|
|
typedef struct _tagTRANSMSG {
|
|
|
|
UINT message;
|
|
|
|
WPARAM wParam;
|
|
|
|
LPARAM lParam;
|
|
|
|
} TRANSMSG, *LPTRANSMSG;
|
|
|
|
|
2013-12-01 15:57:54 +00:00
|
|
|
static UINT (WINAPI *pSendInput) (UINT, INPUT*, size_t);
|
|
|
|
|
2008-04-04 16:43:16 +00:00
|
|
|
static LRESULT CALLBACK get_msg_filter(int nCode, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
|
|
|
if (HC_ACTION == nCode) {
|
|
|
|
MSG *msg = (MSG*)lParam;
|
|
|
|
|
2013-02-03 20:58:19 +00:00
|
|
|
if ((msg->hwnd == msg_spy.hwnd || msg_spy.hwnd == NULL) &&
|
2008-04-04 16:43:16 +00:00
|
|
|
(msg_spy.i_msg < NUMELEMS(msg_spy.msgs)))
|
|
|
|
{
|
2013-02-03 20:58:19 +00:00
|
|
|
msg_spy.msgs[msg_spy.i_msg].msg.hwnd = msg->hwnd;
|
|
|
|
msg_spy.msgs[msg_spy.i_msg].msg.message = msg->message;
|
|
|
|
msg_spy.msgs[msg_spy.i_msg].msg.wParam = msg->wParam;
|
|
|
|
msg_spy.msgs[msg_spy.i_msg].msg.lParam = msg->lParam;
|
|
|
|
msg_spy.msgs[msg_spy.i_msg].post = TRUE;
|
2008-04-04 16:43:16 +00:00
|
|
|
msg_spy.i_msg++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return CallNextHookEx(msg_spy.get_msg_hook, nCode, wParam, lParam);
|
|
|
|
}
|
|
|
|
|
|
|
|
static LRESULT CALLBACK call_wnd_proc_filter(int nCode, WPARAM wParam,
|
|
|
|
LPARAM lParam)
|
|
|
|
{
|
|
|
|
if (HC_ACTION == nCode) {
|
|
|
|
CWPSTRUCT *cwp = (CWPSTRUCT*)lParam;
|
|
|
|
|
2013-02-03 20:58:19 +00:00
|
|
|
if (((cwp->hwnd == msg_spy.hwnd || msg_spy.hwnd == NULL)) &&
|
2008-04-04 16:43:16 +00:00
|
|
|
(msg_spy.i_msg < NUMELEMS(msg_spy.msgs)))
|
|
|
|
{
|
2013-02-03 20:58:19 +00:00
|
|
|
memcpy(&msg_spy.msgs[msg_spy.i_msg].msg, cwp, sizeof(msg_spy.msgs[0].msg));
|
|
|
|
msg_spy.msgs[msg_spy.i_msg].post = FALSE;
|
2008-04-04 16:43:16 +00:00
|
|
|
msg_spy.i_msg++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return CallNextHookEx(msg_spy.call_wnd_proc_hook, nCode, wParam, lParam);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void msg_spy_pump_msg_queue(void) {
|
|
|
|
MSG msg;
|
|
|
|
|
2014-04-30 12:16:47 +00:00
|
|
|
while(PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) {
|
2008-04-04 16:43:16 +00:00
|
|
|
TranslateMessage(&msg);
|
2014-04-30 12:16:47 +00:00
|
|
|
DispatchMessageW(&msg);
|
2008-04-04 16:43:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void msg_spy_flush_msgs(void) {
|
|
|
|
msg_spy_pump_msg_queue();
|
|
|
|
msg_spy.i_msg = 0;
|
|
|
|
}
|
|
|
|
|
2013-02-03 20:58:19 +00:00
|
|
|
static imm_msgs* msg_spy_find_next_msg(UINT message, UINT *start) {
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
UINT i;
|
2008-04-04 16:43:16 +00:00
|
|
|
|
|
|
|
msg_spy_pump_msg_queue();
|
|
|
|
|
|
|
|
if (msg_spy.i_msg >= NUMELEMS(msg_spy.msgs))
|
|
|
|
fprintf(stdout, "%s:%d: msg_spy: message buffer overflow!\n",
|
|
|
|
__FILE__, __LINE__);
|
|
|
|
|
2013-02-03 20:58:19 +00:00
|
|
|
for (i = *start; i < msg_spy.i_msg; i++)
|
|
|
|
if (msg_spy.msgs[i].msg.message == message)
|
|
|
|
{
|
|
|
|
*start = i+1;
|
2008-04-04 16:43:16 +00:00
|
|
|
return &msg_spy.msgs[i];
|
2013-02-03 20:58:19 +00:00
|
|
|
}
|
2008-04-04 16:43:16 +00:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-02-03 20:58:19 +00:00
|
|
|
static imm_msgs* msg_spy_find_msg(UINT message) {
|
|
|
|
UINT i = 0;
|
|
|
|
|
|
|
|
return msg_spy_find_next_msg(message, &i);
|
|
|
|
}
|
|
|
|
|
2008-04-04 16:43:16 +00:00
|
|
|
static void msg_spy_init(HWND hwnd) {
|
|
|
|
msg_spy.hwnd = hwnd;
|
|
|
|
msg_spy.get_msg_hook =
|
2014-04-30 12:16:47 +00:00
|
|
|
SetWindowsHookExW(WH_GETMESSAGE, get_msg_filter, GetModuleHandleW(NULL),
|
|
|
|
GetCurrentThreadId());
|
2008-04-04 16:43:16 +00:00
|
|
|
msg_spy.call_wnd_proc_hook =
|
2014-04-30 12:16:47 +00:00
|
|
|
SetWindowsHookExW(WH_CALLWNDPROC, call_wnd_proc_filter,
|
|
|
|
GetModuleHandleW(NULL), GetCurrentThreadId());
|
2008-04-04 16:43:16 +00:00
|
|
|
msg_spy.i_msg = 0;
|
|
|
|
|
|
|
|
msg_spy_flush_msgs();
|
|
|
|
}
|
|
|
|
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
static void msg_spy_cleanup(void) {
|
2008-04-04 16:43:16 +00:00
|
|
|
if (msg_spy.get_msg_hook)
|
|
|
|
UnhookWindowsHookEx(msg_spy.get_msg_hook);
|
|
|
|
if (msg_spy.call_wnd_proc_hook)
|
|
|
|
UnhookWindowsHookEx(msg_spy.call_wnd_proc_hook);
|
|
|
|
memset(&msg_spy, 0, sizeof(msg_spy));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* imm32 test cases - Issue some IMM commands on a dummy window and analyse the
|
|
|
|
* messages being sent to this window in response.
|
|
|
|
*/
|
|
|
|
static const char wndcls[] = "winetest_imm32_wndcls";
|
2016-08-18 10:08:05 +00:00
|
|
|
static enum { PHASE_UNKNOWN, FIRST_WINDOW, SECOND_WINDOW,
|
|
|
|
CREATE_CANCEL, NCCREATE_CANCEL, IME_DISABLED } test_phase;
|
2008-04-04 16:43:16 +00:00
|
|
|
static HWND hwnd;
|
|
|
|
|
2016-08-18 10:08:05 +00:00
|
|
|
static HWND get_ime_window(void);
|
|
|
|
|
2011-12-15 00:39:37 +00:00
|
|
|
static LRESULT WINAPI wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
2016-08-18 10:08:05 +00:00
|
|
|
HWND default_ime_wnd;
|
2011-12-15 00:39:37 +00:00
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case WM_IME_SETCONTEXT:
|
2016-08-18 10:08:05 +00:00
|
|
|
return TRUE;
|
2011-12-15 00:39:37 +00:00
|
|
|
case WM_NCCREATE:
|
2016-08-18 10:08:05 +00:00
|
|
|
default_ime_wnd = get_ime_window();
|
|
|
|
switch(test_phase) {
|
|
|
|
case FIRST_WINDOW:
|
|
|
|
case IME_DISABLED:
|
|
|
|
ok(!default_ime_wnd, "expected no IME windows\n");
|
|
|
|
break;
|
|
|
|
case SECOND_WINDOW:
|
|
|
|
ok(default_ime_wnd != NULL, "expected IME window existence\n");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break; /* do nothing */
|
|
|
|
}
|
|
|
|
if (test_phase == NCCREATE_CANCEL)
|
|
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
|
|
case WM_NCCALCSIZE:
|
|
|
|
default_ime_wnd = get_ime_window();
|
|
|
|
switch(test_phase) {
|
|
|
|
case FIRST_WINDOW:
|
|
|
|
case SECOND_WINDOW:
|
|
|
|
case CREATE_CANCEL:
|
|
|
|
ok(default_ime_wnd != NULL, "expected IME window existence\n");
|
|
|
|
break;
|
|
|
|
case IME_DISABLED:
|
|
|
|
ok(!default_ime_wnd, "expected no IME windows\n");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break; /* do nothing */
|
|
|
|
}
|
|
|
|
break;
|
2011-12-15 00:39:37 +00:00
|
|
|
case WM_CREATE:
|
2016-08-18 10:08:05 +00:00
|
|
|
default_ime_wnd = get_ime_window();
|
|
|
|
switch(test_phase) {
|
|
|
|
case FIRST_WINDOW:
|
|
|
|
case SECOND_WINDOW:
|
|
|
|
case CREATE_CANCEL:
|
|
|
|
ok(default_ime_wnd != NULL, "expected IME window existence\n");
|
|
|
|
break;
|
|
|
|
case IME_DISABLED:
|
|
|
|
ok(!default_ime_wnd, "expected no IME windows\n");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break; /* do nothing */
|
|
|
|
}
|
|
|
|
if (test_phase == CREATE_CANCEL)
|
|
|
|
return -1;
|
2011-12-15 00:39:37 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2016-08-18 10:08:05 +00:00
|
|
|
return DefWindowProcA(hWnd,msg,wParam,lParam);
|
2011-12-15 00:39:37 +00:00
|
|
|
}
|
|
|
|
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
static BOOL init(void) {
|
2014-04-30 12:16:47 +00:00
|
|
|
WNDCLASSEXA wc;
|
2009-05-17 07:05:22 +00:00
|
|
|
HIMC imc;
|
2013-12-01 15:57:54 +00:00
|
|
|
HMODULE hmod,huser;
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
|
|
|
|
hmod = GetModuleHandleA("imm32.dll");
|
2013-12-01 15:57:54 +00:00
|
|
|
huser = GetModuleHandleA("user32");
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
pImmAssociateContextEx = (void*)GetProcAddress(hmod, "ImmAssociateContextEx");
|
2011-12-15 00:39:37 +00:00
|
|
|
pImmIsUIMessageA = (void*)GetProcAddress(hmod, "ImmIsUIMessageA");
|
2013-12-01 15:57:54 +00:00
|
|
|
pSendInput = (void*)GetProcAddress(huser, "SendInput");
|
2008-04-04 16:43:16 +00:00
|
|
|
|
2014-04-30 12:16:47 +00:00
|
|
|
wc.cbSize = sizeof(WNDCLASSEXA);
|
2008-04-04 16:43:16 +00:00
|
|
|
wc.style = 0;
|
2011-12-15 00:39:37 +00:00
|
|
|
wc.lpfnWndProc = wndProc;
|
2008-04-04 16:43:16 +00:00
|
|
|
wc.cbClsExtra = 0;
|
|
|
|
wc.cbWndExtra = 0;
|
2014-04-30 12:16:47 +00:00
|
|
|
wc.hInstance = GetModuleHandleA(NULL);
|
|
|
|
wc.hIcon = LoadIconA(NULL, (LPCSTR)IDI_APPLICATION);
|
|
|
|
wc.hCursor = LoadCursorA(NULL, (LPCSTR)IDC_ARROW);
|
2008-04-04 16:43:16 +00:00
|
|
|
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
|
|
|
|
wc.lpszMenuName = NULL;
|
|
|
|
wc.lpszClassName = wndcls;
|
2014-04-30 12:16:47 +00:00
|
|
|
wc.hIconSm = LoadIconA(NULL, (LPCSTR)IDI_APPLICATION);
|
2008-04-04 16:43:16 +00:00
|
|
|
|
|
|
|
if (!RegisterClassExA(&wc))
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
return FALSE;
|
2008-04-04 16:43:16 +00:00
|
|
|
|
2014-04-30 12:16:47 +00:00
|
|
|
hwnd = CreateWindowExA(WS_EX_CLIENTEDGE, wndcls, "Wine imm32.dll test",
|
|
|
|
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
|
|
|
|
240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL);
|
2008-04-04 16:43:16 +00:00
|
|
|
if (!hwnd)
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
return FALSE;
|
2008-04-04 16:43:16 +00:00
|
|
|
|
2009-05-17 07:05:22 +00:00
|
|
|
imc = ImmGetContext(hwnd);
|
|
|
|
if (!imc)
|
|
|
|
{
|
|
|
|
win_skip("IME support not implemented\n");
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
return FALSE;
|
2009-05-17 07:05:22 +00:00
|
|
|
}
|
|
|
|
ImmReleaseContext(hwnd, imc);
|
|
|
|
|
2008-04-04 16:43:16 +00:00
|
|
|
ShowWindow(hwnd, SW_SHOWNORMAL);
|
|
|
|
UpdateWindow(hwnd);
|
|
|
|
|
|
|
|
msg_spy_init(hwnd);
|
|
|
|
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
return TRUE;
|
2008-04-04 16:43:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void cleanup(void) {
|
|
|
|
msg_spy_cleanup();
|
|
|
|
if (hwnd)
|
|
|
|
DestroyWindow(hwnd);
|
2014-04-30 12:16:47 +00:00
|
|
|
UnregisterClassA(wndcls, GetModuleHandleW(NULL));
|
2008-04-04 16:43:16 +00:00
|
|
|
}
|
|
|
|
|
2009-05-17 07:05:22 +00:00
|
|
|
static void test_ImmNotifyIME(void) {
|
2008-04-04 16:43:16 +00:00
|
|
|
static const char string[] = "wine";
|
|
|
|
char resstr[16] = "";
|
|
|
|
HIMC imc;
|
2008-05-09 17:35:45 +00:00
|
|
|
BOOL ret;
|
2008-04-04 16:43:16 +00:00
|
|
|
|
|
|
|
imc = ImmGetContext(hwnd);
|
|
|
|
msg_spy_flush_msgs();
|
|
|
|
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
ret = ImmNotifyIME(imc, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
|
|
|
|
ok(broken(!ret) ||
|
|
|
|
ret, /* Vista+ */
|
|
|
|
"Canceling an empty composition string should succeed.\n");
|
2008-04-04 16:43:16 +00:00
|
|
|
ok(!msg_spy_find_msg(WM_IME_COMPOSITION), "Windows does not post "
|
|
|
|
"WM_IME_COMPOSITION in response to NI_COMPOSITIONSTR / CPS_CANCEL, if "
|
|
|
|
"the composition string being canceled is empty.\n");
|
|
|
|
|
2014-04-30 12:16:47 +00:00
|
|
|
ImmSetCompositionStringA(imc, SCS_SETSTR, string, sizeof(string), NULL, 0);
|
2008-04-04 16:43:16 +00:00
|
|
|
msg_spy_flush_msgs();
|
|
|
|
|
|
|
|
ImmNotifyIME(imc, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
|
2011-12-15 00:39:37 +00:00
|
|
|
msg_spy_flush_msgs();
|
2008-05-09 17:35:45 +00:00
|
|
|
|
|
|
|
/* behavior differs between win9x and NT */
|
2014-04-30 12:16:47 +00:00
|
|
|
ret = ImmGetCompositionStringA(imc, GCS_COMPSTR, resstr, sizeof(resstr));
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
ok(!ret, "After being cancelled the composition string is empty.\n");
|
2008-04-04 16:43:16 +00:00
|
|
|
|
|
|
|
msg_spy_flush_msgs();
|
|
|
|
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
ret = ImmNotifyIME(imc, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
|
|
|
|
ok(broken(!ret) ||
|
|
|
|
ret, /* Vista+ */
|
|
|
|
"Canceling an empty composition string should succeed.\n");
|
2008-04-04 16:43:16 +00:00
|
|
|
ok(!msg_spy_find_msg(WM_IME_COMPOSITION), "Windows does not post "
|
|
|
|
"WM_IME_COMPOSITION in response to NI_COMPOSITIONSTR / CPS_CANCEL, if "
|
|
|
|
"the composition string being canceled is empty.\n");
|
|
|
|
|
|
|
|
msg_spy_flush_msgs();
|
|
|
|
ImmReleaseContext(hwnd, imc);
|
2014-04-30 12:16:47 +00:00
|
|
|
|
|
|
|
imc = ImmCreateContext();
|
|
|
|
ImmDestroyContext(imc);
|
|
|
|
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmNotifyIME((HIMC)0xdeadcafe, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
|
|
|
|
ok (ret == 0, "Bad IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmNotifyIME(0x00000000, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
|
|
|
|
ok (ret == 0, "NULL IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_SUCCESS, "wrong last error %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmNotifyIME(imc, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
|
|
|
|
ok (ret == 0, "Destroyed IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
|
2009-05-17 07:05:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void test_ImmGetCompositionString(void)
|
|
|
|
{
|
|
|
|
HIMC imc;
|
|
|
|
static const WCHAR string[] = {'w','i','n','e',0x65e5,0x672c,0x8a9e};
|
|
|
|
char cstring[20];
|
|
|
|
WCHAR wstring[20];
|
|
|
|
DWORD len;
|
|
|
|
DWORD alen,wlen;
|
|
|
|
|
|
|
|
imc = ImmGetContext(hwnd);
|
|
|
|
ImmSetCompositionStringW(imc, SCS_SETSTR, string, sizeof(string), NULL,0);
|
|
|
|
alen = ImmGetCompositionStringA(imc, GCS_COMPSTR, cstring, 20);
|
|
|
|
wlen = ImmGetCompositionStringW(imc, GCS_COMPSTR, wstring, 20);
|
|
|
|
/* windows machines without any IME installed just return 0 above */
|
|
|
|
if( alen && wlen)
|
|
|
|
{
|
|
|
|
len = ImmGetCompositionStringW(imc, GCS_COMPATTR, NULL, 0);
|
|
|
|
ok(len*sizeof(WCHAR)==wlen,"GCS_COMPATTR(W) not returning correct count\n");
|
|
|
|
len = ImmGetCompositionStringA(imc, GCS_COMPATTR, NULL, 0);
|
|
|
|
ok(len==alen,"GCS_COMPATTR(A) not returning correct count\n");
|
|
|
|
}
|
|
|
|
ImmReleaseContext(hwnd, imc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_ImmSetCompositionString(void)
|
|
|
|
{
|
|
|
|
HIMC imc;
|
|
|
|
BOOL ret;
|
|
|
|
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
imc = ImmGetContext(hwnd);
|
|
|
|
ok(imc != 0, "ImmGetContext() failed. Last error: %u\n", GetLastError());
|
|
|
|
if (!imc)
|
|
|
|
return;
|
|
|
|
|
|
|
|
ret = ImmSetCompositionStringW(imc, SCS_SETSTR, NULL, 0, NULL, 0);
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
ok(broken(!ret) ||
|
|
|
|
ret, /* Vista+ */
|
|
|
|
"ImmSetCompositionStringW() failed.\n");
|
2009-05-17 07:05:22 +00:00
|
|
|
|
|
|
|
ret = ImmSetCompositionStringW(imc, SCS_SETSTR | SCS_CHANGEATTR,
|
|
|
|
NULL, 0, NULL, 0);
|
|
|
|
ok(!ret, "ImmSetCompositionStringW() succeeded.\n");
|
|
|
|
|
|
|
|
ret = ImmSetCompositionStringW(imc, SCS_SETSTR | SCS_CHANGECLAUSE,
|
|
|
|
NULL, 0, NULL, 0);
|
|
|
|
ok(!ret, "ImmSetCompositionStringW() succeeded.\n");
|
|
|
|
|
|
|
|
ret = ImmSetCompositionStringW(imc, SCS_CHANGEATTR | SCS_CHANGECLAUSE,
|
|
|
|
NULL, 0, NULL, 0);
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
ok(!ret, "ImmSetCompositionStringW() succeeded.\n");
|
|
|
|
|
|
|
|
ret = ImmSetCompositionStringW(imc, SCS_SETSTR | SCS_CHANGEATTR | SCS_CHANGECLAUSE,
|
|
|
|
NULL, 0, NULL, 0);
|
2009-05-17 07:05:22 +00:00
|
|
|
ok(!ret, "ImmSetCompositionStringW() succeeded.\n");
|
|
|
|
|
|
|
|
ImmReleaseContext(hwnd, imc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_ImmIME(void)
|
|
|
|
{
|
|
|
|
HIMC imc;
|
2008-04-04 16:43:16 +00:00
|
|
|
|
2009-05-17 07:05:22 +00:00
|
|
|
imc = ImmGetContext(hwnd);
|
|
|
|
if (imc)
|
|
|
|
{
|
|
|
|
BOOL rc;
|
|
|
|
rc = ImmConfigureIMEA(imc, NULL, IME_CONFIG_REGISTERWORD, NULL);
|
|
|
|
ok (rc == 0, "ImmConfigureIMEA did not fail\n");
|
|
|
|
rc = ImmConfigureIMEW(imc, NULL, IME_CONFIG_REGISTERWORD, NULL);
|
|
|
|
ok (rc == 0, "ImmConfigureIMEW did not fail\n");
|
|
|
|
}
|
|
|
|
ImmReleaseContext(hwnd,imc);
|
2008-04-04 16:43:16 +00:00
|
|
|
}
|
|
|
|
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
static void test_ImmAssociateContextEx(void)
|
|
|
|
{
|
|
|
|
HIMC imc;
|
|
|
|
BOOL rc;
|
|
|
|
|
|
|
|
if (!pImmAssociateContextEx) return;
|
|
|
|
|
|
|
|
imc = ImmGetContext(hwnd);
|
|
|
|
if (imc)
|
|
|
|
{
|
|
|
|
HIMC retimc, newimc;
|
|
|
|
|
|
|
|
newimc = ImmCreateContext();
|
|
|
|
ok(newimc != imc, "handles should not be the same\n");
|
|
|
|
rc = pImmAssociateContextEx(NULL, NULL, 0);
|
|
|
|
ok(!rc, "ImmAssociateContextEx succeeded\n");
|
|
|
|
rc = pImmAssociateContextEx(hwnd, NULL, 0);
|
|
|
|
ok(rc, "ImmAssociateContextEx failed\n");
|
|
|
|
rc = pImmAssociateContextEx(NULL, imc, 0);
|
|
|
|
ok(!rc, "ImmAssociateContextEx succeeded\n");
|
|
|
|
|
|
|
|
rc = pImmAssociateContextEx(hwnd, imc, 0);
|
|
|
|
ok(rc, "ImmAssociateContextEx failed\n");
|
|
|
|
retimc = ImmGetContext(hwnd);
|
|
|
|
ok(retimc == imc, "handles should be the same\n");
|
|
|
|
ImmReleaseContext(hwnd,retimc);
|
|
|
|
|
|
|
|
rc = pImmAssociateContextEx(hwnd, newimc, 0);
|
|
|
|
ok(rc, "ImmAssociateContextEx failed\n");
|
|
|
|
retimc = ImmGetContext(hwnd);
|
|
|
|
ok(retimc == newimc, "handles should be the same\n");
|
|
|
|
ImmReleaseContext(hwnd,retimc);
|
|
|
|
|
|
|
|
rc = pImmAssociateContextEx(hwnd, NULL, IACE_DEFAULT);
|
|
|
|
ok(rc, "ImmAssociateContextEx failed\n");
|
|
|
|
}
|
|
|
|
ImmReleaseContext(hwnd,imc);
|
|
|
|
}
|
|
|
|
|
2011-12-15 00:39:37 +00:00
|
|
|
typedef struct _igc_threadinfo {
|
|
|
|
HWND hwnd;
|
|
|
|
HANDLE event;
|
|
|
|
HIMC himc;
|
2016-03-09 08:32:48 +00:00
|
|
|
HIMC u_himc;
|
2011-12-15 00:39:37 +00:00
|
|
|
} igc_threadinfo;
|
|
|
|
|
|
|
|
|
|
|
|
static DWORD WINAPI ImmGetContextThreadFunc( LPVOID lpParam)
|
|
|
|
{
|
|
|
|
HIMC h1,h2;
|
|
|
|
HWND hwnd2;
|
|
|
|
COMPOSITIONFORM cf;
|
2016-03-09 08:32:48 +00:00
|
|
|
CANDIDATEFORM cdf;
|
2011-12-15 00:39:37 +00:00
|
|
|
POINT pt;
|
2016-03-09 08:32:48 +00:00
|
|
|
MSG msg;
|
|
|
|
|
2011-12-15 00:39:37 +00:00
|
|
|
igc_threadinfo *info= (igc_threadinfo*)lpParam;
|
2014-04-30 12:16:47 +00:00
|
|
|
info->hwnd = CreateWindowExA(WS_EX_CLIENTEDGE, wndcls, "Wine imm32.dll test",
|
|
|
|
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
|
|
|
|
240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL);
|
2011-12-15 00:39:37 +00:00
|
|
|
|
|
|
|
h1 = ImmGetContext(hwnd);
|
2016-03-09 08:32:48 +00:00
|
|
|
ok(info->himc == h1, "hwnd context changed in new thread\n");
|
2011-12-15 00:39:37 +00:00
|
|
|
h2 = ImmGetContext(info->hwnd);
|
2016-03-09 08:32:48 +00:00
|
|
|
ok(h2 != h1, "new hwnd in new thread should have different context\n");
|
2011-12-15 00:39:37 +00:00
|
|
|
info->himc = h2;
|
|
|
|
ImmReleaseContext(hwnd,h1);
|
|
|
|
|
2014-04-30 12:16:47 +00:00
|
|
|
hwnd2 = CreateWindowExA(WS_EX_CLIENTEDGE, wndcls, "Wine imm32.dll test",
|
|
|
|
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
|
|
|
|
240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL);
|
2011-12-15 00:39:37 +00:00
|
|
|
h1 = ImmGetContext(hwnd2);
|
|
|
|
|
|
|
|
ok(h1 == h2, "Windows in same thread should have same default context\n");
|
|
|
|
ImmReleaseContext(hwnd2,h1);
|
|
|
|
ImmReleaseContext(info->hwnd,h2);
|
|
|
|
DestroyWindow(hwnd2);
|
|
|
|
|
|
|
|
/* priming for later tests */
|
|
|
|
ImmSetCompositionWindow(h1, &cf);
|
|
|
|
ImmSetStatusWindowPos(h1, &pt);
|
2016-03-09 08:32:48 +00:00
|
|
|
info->u_himc = ImmCreateContext();
|
|
|
|
ImmSetOpenStatus(info->u_himc, TRUE);
|
|
|
|
cdf.dwIndex = 0;
|
|
|
|
cdf.dwStyle = CFS_CANDIDATEPOS;
|
|
|
|
cdf.ptCurrentPos.x = 0;
|
|
|
|
cdf.ptCurrentPos.y = 0;
|
|
|
|
ImmSetCandidateWindow(info->u_himc, &cdf);
|
2011-12-15 00:39:37 +00:00
|
|
|
|
|
|
|
SetEvent(info->event);
|
2016-03-09 08:32:48 +00:00
|
|
|
|
|
|
|
while(GetMessageW(&msg, 0, 0, 0))
|
|
|
|
{
|
|
|
|
TranslateMessage(&msg);
|
|
|
|
DispatchMessageW(&msg);
|
|
|
|
}
|
2011-12-15 00:39:37 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_ImmThreads(void)
|
|
|
|
{
|
|
|
|
HIMC himc, otherHimc, h1;
|
|
|
|
igc_threadinfo threadinfo;
|
|
|
|
HANDLE hThread;
|
|
|
|
DWORD dwThreadId;
|
|
|
|
BOOL rc;
|
2014-04-30 12:16:47 +00:00
|
|
|
LOGFONTA lf;
|
2011-12-15 00:39:37 +00:00
|
|
|
COMPOSITIONFORM cf;
|
2014-04-30 12:16:47 +00:00
|
|
|
CANDIDATEFORM cdf;
|
2011-12-15 00:39:37 +00:00
|
|
|
DWORD status, sentence;
|
|
|
|
POINT pt;
|
|
|
|
|
|
|
|
himc = ImmGetContext(hwnd);
|
2014-04-30 12:16:47 +00:00
|
|
|
threadinfo.event = CreateEventA(NULL, TRUE, FALSE, NULL);
|
2011-12-15 00:39:37 +00:00
|
|
|
threadinfo.himc = himc;
|
|
|
|
hThread = CreateThread(NULL, 0, ImmGetContextThreadFunc, &threadinfo, 0, &dwThreadId );
|
|
|
|
WaitForSingleObject(threadinfo.event, INFINITE);
|
|
|
|
|
|
|
|
otherHimc = ImmGetContext(threadinfo.hwnd);
|
|
|
|
|
2016-03-09 08:32:48 +00:00
|
|
|
ok(himc != otherHimc, "Windows from other threads should have different himc\n");
|
|
|
|
ok(otherHimc == threadinfo.himc, "Context from other thread should not change in main thread\n");
|
2011-12-15 00:39:37 +00:00
|
|
|
|
|
|
|
h1 = ImmAssociateContext(hwnd,otherHimc);
|
|
|
|
ok(h1 == NULL, "Should fail to be able to Associate a default context from a different thread\n");
|
|
|
|
h1 = ImmGetContext(hwnd);
|
|
|
|
ok(h1 == himc, "Context for window should remain unchanged\n");
|
|
|
|
ImmReleaseContext(hwnd,h1);
|
|
|
|
|
2016-03-09 08:32:48 +00:00
|
|
|
h1 = ImmAssociateContext(hwnd, threadinfo.u_himc);
|
|
|
|
ok (h1 == NULL, "Should fail to associate a context from a different thread\n");
|
|
|
|
h1 = ImmGetContext(hwnd);
|
|
|
|
ok(h1 == himc, "Context for window should remain unchanged\n");
|
|
|
|
ImmReleaseContext(hwnd,h1);
|
|
|
|
|
|
|
|
h1 = ImmAssociateContext(threadinfo.hwnd, threadinfo.u_himc);
|
|
|
|
ok (h1 == NULL, "Should fail to associate a context from a different thread into a window from that thread.\n");
|
|
|
|
h1 = ImmGetContext(threadinfo.hwnd);
|
|
|
|
ok(h1 == threadinfo.himc, "Context for window should remain unchanged\n");
|
|
|
|
ImmReleaseContext(threadinfo.hwnd,h1);
|
2011-12-15 00:39:37 +00:00
|
|
|
|
|
|
|
/* OpenStatus */
|
|
|
|
rc = ImmSetOpenStatus(himc, TRUE);
|
|
|
|
ok(rc != 0, "ImmSetOpenStatus failed\n");
|
|
|
|
rc = ImmGetOpenStatus(himc);
|
|
|
|
ok(rc != 0, "ImmGetOpenStatus failed\n");
|
|
|
|
rc = ImmSetOpenStatus(himc, FALSE);
|
|
|
|
ok(rc != 0, "ImmSetOpenStatus failed\n");
|
|
|
|
rc = ImmGetOpenStatus(himc);
|
|
|
|
ok(rc == 0, "ImmGetOpenStatus failed\n");
|
|
|
|
|
|
|
|
rc = ImmSetOpenStatus(otherHimc, TRUE);
|
2016-03-09 08:32:48 +00:00
|
|
|
ok(rc == 0, "ImmSetOpenStatus should fail\n");
|
|
|
|
rc = ImmSetOpenStatus(threadinfo.u_himc, TRUE);
|
|
|
|
ok(rc == 0, "ImmSetOpenStatus should fail\n");
|
2011-12-15 00:39:37 +00:00
|
|
|
rc = ImmGetOpenStatus(otherHimc);
|
2016-03-09 08:32:48 +00:00
|
|
|
ok(rc == 0, "ImmGetOpenStatus failed\n");
|
|
|
|
rc = ImmGetOpenStatus(threadinfo.u_himc);
|
|
|
|
ok (rc == 1 || broken(rc == 0), "ImmGetOpenStatus should return 1\n");
|
2011-12-15 00:39:37 +00:00
|
|
|
rc = ImmSetOpenStatus(otherHimc, FALSE);
|
2016-03-09 08:32:48 +00:00
|
|
|
ok(rc == 0, "ImmSetOpenStatus should fail\n");
|
2011-12-15 00:39:37 +00:00
|
|
|
rc = ImmGetOpenStatus(otherHimc);
|
|
|
|
ok(rc == 0, "ImmGetOpenStatus failed\n");
|
|
|
|
|
|
|
|
/* CompositionFont */
|
2014-04-30 12:16:47 +00:00
|
|
|
rc = ImmGetCompositionFontA(himc, &lf);
|
2011-12-15 00:39:37 +00:00
|
|
|
ok(rc != 0, "ImmGetCompositionFont failed\n");
|
2014-04-30 12:16:47 +00:00
|
|
|
rc = ImmSetCompositionFontA(himc, &lf);
|
2011-12-15 00:39:37 +00:00
|
|
|
ok(rc != 0, "ImmSetCompositionFont failed\n");
|
|
|
|
|
2014-04-30 12:16:47 +00:00
|
|
|
rc = ImmGetCompositionFontA(otherHimc, &lf);
|
2011-12-15 00:39:37 +00:00
|
|
|
ok(rc != 0 || broken(rc == 0), "ImmGetCompositionFont failed\n");
|
2016-03-09 08:32:48 +00:00
|
|
|
rc = ImmGetCompositionFontA(threadinfo.u_himc, &lf);
|
|
|
|
ok(rc != 0 || broken(rc == 0), "ImmGetCompositionFont user himc failed\n");
|
2014-04-30 12:16:47 +00:00
|
|
|
rc = ImmSetCompositionFontA(otherHimc, &lf);
|
2016-03-09 08:32:48 +00:00
|
|
|
ok(rc == 0, "ImmSetCompositionFont should fail\n");
|
|
|
|
rc = ImmSetCompositionFontA(threadinfo.u_himc, &lf);
|
|
|
|
ok(rc == 0, "ImmSetCompositionFont should fail\n");
|
2011-12-15 00:39:37 +00:00
|
|
|
|
|
|
|
/* CompositionWindow */
|
|
|
|
rc = ImmSetCompositionWindow(himc, &cf);
|
|
|
|
ok(rc != 0, "ImmSetCompositionWindow failed\n");
|
|
|
|
rc = ImmGetCompositionWindow(himc, &cf);
|
|
|
|
ok(rc != 0, "ImmGetCompositionWindow failed\n");
|
|
|
|
|
|
|
|
rc = ImmSetCompositionWindow(otherHimc, &cf);
|
2016-03-09 08:32:48 +00:00
|
|
|
ok(rc == 0, "ImmSetCompositionWindow should fail\n");
|
|
|
|
rc = ImmSetCompositionWindow(threadinfo.u_himc, &cf);
|
|
|
|
ok(rc == 0, "ImmSetCompositionWindow should fail\n");
|
2011-12-15 00:39:37 +00:00
|
|
|
rc = ImmGetCompositionWindow(otherHimc, &cf);
|
|
|
|
ok(rc != 0 || broken(rc == 0), "ImmGetCompositionWindow failed\n");
|
2016-03-09 08:32:48 +00:00
|
|
|
rc = ImmGetCompositionWindow(threadinfo.u_himc, &cf);
|
|
|
|
ok(rc != 0 || broken(rc == 0), "ImmGetCompositionWindow failed\n");
|
2011-12-15 00:39:37 +00:00
|
|
|
|
|
|
|
/* ConversionStatus */
|
|
|
|
rc = ImmGetConversionStatus(himc, &status, &sentence);
|
|
|
|
ok(rc != 0, "ImmGetConversionStatus failed\n");
|
|
|
|
rc = ImmSetConversionStatus(himc, status, sentence);
|
|
|
|
ok(rc != 0, "ImmSetConversionStatus failed\n");
|
|
|
|
|
|
|
|
rc = ImmGetConversionStatus(otherHimc, &status, &sentence);
|
|
|
|
ok(rc != 0 || broken(rc == 0), "ImmGetConversionStatus failed\n");
|
2016-03-09 08:32:48 +00:00
|
|
|
rc = ImmGetConversionStatus(threadinfo.u_himc, &status, &sentence);
|
|
|
|
ok(rc != 0 || broken(rc == 0), "ImmGetConversionStatus failed\n");
|
2011-12-15 00:39:37 +00:00
|
|
|
rc = ImmSetConversionStatus(otherHimc, status, sentence);
|
2016-03-09 08:32:48 +00:00
|
|
|
ok(rc == 0, "ImmSetConversionStatus should fail\n");
|
|
|
|
rc = ImmSetConversionStatus(threadinfo.u_himc, status, sentence);
|
|
|
|
ok(rc == 0, "ImmSetConversionStatus should fail\n");
|
2011-12-15 00:39:37 +00:00
|
|
|
|
|
|
|
/* StatusWindowPos */
|
|
|
|
rc = ImmSetStatusWindowPos(himc, &pt);
|
|
|
|
ok(rc != 0, "ImmSetStatusWindowPos failed\n");
|
|
|
|
rc = ImmGetStatusWindowPos(himc, &pt);
|
|
|
|
ok(rc != 0, "ImmGetStatusWindowPos failed\n");
|
|
|
|
|
|
|
|
rc = ImmSetStatusWindowPos(otherHimc, &pt);
|
2016-03-09 08:32:48 +00:00
|
|
|
ok(rc == 0, "ImmSetStatusWindowPos should fail\n");
|
|
|
|
rc = ImmSetStatusWindowPos(threadinfo.u_himc, &pt);
|
|
|
|
ok(rc == 0, "ImmSetStatusWindowPos should fail\n");
|
2011-12-15 00:39:37 +00:00
|
|
|
rc = ImmGetStatusWindowPos(otherHimc, &pt);
|
|
|
|
ok(rc != 0 || broken(rc == 0), "ImmGetStatusWindowPos failed\n");
|
2016-03-09 08:32:48 +00:00
|
|
|
rc = ImmGetStatusWindowPos(threadinfo.u_himc, &pt);
|
|
|
|
ok(rc != 0 || broken(rc == 0), "ImmGetStatusWindowPos failed\n");
|
|
|
|
|
|
|
|
h1 = ImmAssociateContext(threadinfo.hwnd, NULL);
|
|
|
|
ok (h1 == otherHimc, "ImmAssociateContext cross thread with NULL should work\n");
|
|
|
|
h1 = ImmGetContext(threadinfo.hwnd);
|
|
|
|
ok (h1 == NULL, "CrossThread window context should be NULL\n");
|
|
|
|
h1 = ImmAssociateContext(threadinfo.hwnd, h1);
|
|
|
|
ok (h1 == NULL, "Resetting cross thread context should fail\n");
|
|
|
|
h1 = ImmGetContext(threadinfo.hwnd);
|
|
|
|
ok (h1 == NULL, "CrossThread window context should still be NULL\n");
|
|
|
|
|
|
|
|
rc = ImmDestroyContext(threadinfo.u_himc);
|
|
|
|
ok (rc == 0, "ImmDestroyContext Cross Thread should fail\n");
|
2011-12-15 00:39:37 +00:00
|
|
|
|
2014-04-30 12:16:47 +00:00
|
|
|
/* Candidate Window */
|
|
|
|
rc = ImmGetCandidateWindow(himc, 0, &cdf);
|
|
|
|
ok (rc == 0, "ImmGetCandidateWindow should fail\n");
|
|
|
|
cdf.dwIndex = 0;
|
|
|
|
cdf.dwStyle = CFS_CANDIDATEPOS;
|
|
|
|
cdf.ptCurrentPos.x = 0;
|
|
|
|
cdf.ptCurrentPos.y = 0;
|
|
|
|
rc = ImmSetCandidateWindow(himc, &cdf);
|
|
|
|
ok (rc == 1, "ImmSetCandidateWindow should succeed\n");
|
|
|
|
rc = ImmGetCandidateWindow(himc, 0, &cdf);
|
|
|
|
ok (rc == 1, "ImmGetCandidateWindow should succeed\n");
|
|
|
|
|
|
|
|
rc = ImmGetCandidateWindow(otherHimc, 0, &cdf);
|
2016-03-09 08:32:48 +00:00
|
|
|
ok (rc == 0, "ImmGetCandidateWindow should fail\n");
|
2014-04-30 12:16:47 +00:00
|
|
|
rc = ImmSetCandidateWindow(otherHimc, &cdf);
|
2016-03-09 08:32:48 +00:00
|
|
|
ok (rc == 0, "ImmSetCandidateWindow should fail\n");
|
|
|
|
rc = ImmGetCandidateWindow(threadinfo.u_himc, 0, &cdf);
|
|
|
|
ok (rc == 1 || broken( rc == 0), "ImmGetCandidateWindow should succeed\n");
|
|
|
|
rc = ImmSetCandidateWindow(threadinfo.u_himc, &cdf);
|
|
|
|
ok (rc == 0, "ImmSetCandidateWindow should fail\n");
|
2014-04-30 12:16:47 +00:00
|
|
|
|
2011-12-15 00:39:37 +00:00
|
|
|
ImmReleaseContext(threadinfo.hwnd,otherHimc);
|
|
|
|
ImmReleaseContext(hwnd,himc);
|
|
|
|
|
2016-08-18 10:08:05 +00:00
|
|
|
SendMessageA(threadinfo.hwnd, WM_CLOSE, 0, 0);
|
|
|
|
rc = PostThreadMessageA(dwThreadId, WM_QUIT, 1, 0);
|
|
|
|
ok(rc == 1, "PostThreadMessage should succeed\n");
|
|
|
|
WaitForSingleObject(hThread, INFINITE);
|
|
|
|
CloseHandle(hThread);
|
2011-12-15 00:39:37 +00:00
|
|
|
|
|
|
|
himc = ImmGetContext(GetDesktopWindow());
|
2016-03-09 08:32:48 +00:00
|
|
|
ok(himc == NULL, "Should not be able to get himc from other process window\n");
|
2011-12-15 00:39:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void test_ImmIsUIMessage(void)
|
|
|
|
{
|
|
|
|
struct test
|
|
|
|
{
|
|
|
|
UINT msg;
|
|
|
|
BOOL ret;
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct test tests[] =
|
|
|
|
{
|
|
|
|
{ WM_MOUSEMOVE, FALSE },
|
|
|
|
{ WM_IME_STARTCOMPOSITION, TRUE },
|
|
|
|
{ WM_IME_ENDCOMPOSITION, TRUE },
|
|
|
|
{ WM_IME_COMPOSITION, TRUE },
|
|
|
|
{ WM_IME_SETCONTEXT, TRUE },
|
|
|
|
{ WM_IME_NOTIFY, TRUE },
|
|
|
|
{ WM_IME_CONTROL, FALSE },
|
|
|
|
{ WM_IME_COMPOSITIONFULL, TRUE },
|
|
|
|
{ WM_IME_SELECT, TRUE },
|
|
|
|
{ WM_IME_CHAR, FALSE },
|
|
|
|
{ 0x287 /* FIXME */, TRUE },
|
|
|
|
{ WM_IME_REQUEST, FALSE },
|
|
|
|
{ WM_IME_KEYDOWN, FALSE },
|
|
|
|
{ WM_IME_KEYUP, FALSE },
|
|
|
|
{ 0, FALSE } /* mark the end */
|
|
|
|
};
|
|
|
|
|
2016-03-09 08:32:48 +00:00
|
|
|
UINT WM_MSIME_SERVICE = RegisterWindowMessageA("MSIMEService");
|
|
|
|
UINT WM_MSIME_RECONVERTOPTIONS = RegisterWindowMessageA("MSIMEReconvertOptions");
|
|
|
|
UINT WM_MSIME_MOUSE = RegisterWindowMessageA("MSIMEMouseOperation");
|
|
|
|
UINT WM_MSIME_RECONVERTREQUEST = RegisterWindowMessageA("MSIMEReconvertRequest");
|
|
|
|
UINT WM_MSIME_RECONVERT = RegisterWindowMessageA("MSIMEReconvert");
|
|
|
|
UINT WM_MSIME_QUERYPOSITION = RegisterWindowMessageA("MSIMEQueryPosition");
|
|
|
|
UINT WM_MSIME_DOCUMENTFEED = RegisterWindowMessageA("MSIMEDocumentFeed");
|
|
|
|
|
2011-12-15 00:39:37 +00:00
|
|
|
const struct test *test;
|
|
|
|
BOOL ret;
|
|
|
|
|
|
|
|
if (!pImmIsUIMessageA) return;
|
|
|
|
|
|
|
|
for (test = tests; test->msg; test++)
|
|
|
|
{
|
|
|
|
msg_spy_flush_msgs();
|
|
|
|
ret = pImmIsUIMessageA(NULL, test->msg, 0, 0);
|
|
|
|
ok(ret == test->ret, "ImmIsUIMessageA returned %x for %x\n", ret, test->msg);
|
|
|
|
ok(!msg_spy_find_msg(test->msg), "Windows does not send 0x%x for NULL hwnd\n", test->msg);
|
|
|
|
|
|
|
|
ret = pImmIsUIMessageA(hwnd, test->msg, 0, 0);
|
|
|
|
ok(ret == test->ret, "ImmIsUIMessageA returned %x for %x\n", ret, test->msg);
|
|
|
|
if (ret)
|
|
|
|
ok(msg_spy_find_msg(test->msg) != NULL, "Windows does send 0x%x\n", test->msg);
|
|
|
|
else
|
|
|
|
ok(!msg_spy_find_msg(test->msg), "Windows does not send 0x%x\n", test->msg);
|
|
|
|
}
|
2016-03-09 08:32:48 +00:00
|
|
|
|
|
|
|
ret = pImmIsUIMessageA(NULL, WM_MSIME_SERVICE, 0, 0);
|
|
|
|
ok(!ret, "ImmIsUIMessageA returned TRUE for WM_MSIME_SERVICE\n");
|
|
|
|
ret = pImmIsUIMessageA(NULL, WM_MSIME_RECONVERTOPTIONS, 0, 0);
|
|
|
|
ok(!ret, "ImmIsUIMessageA returned TRUE for WM_MSIME_RECONVERTOPTIONS\n");
|
|
|
|
ret = pImmIsUIMessageA(NULL, WM_MSIME_MOUSE, 0, 0);
|
|
|
|
ok(!ret, "ImmIsUIMessageA returned TRUE for WM_MSIME_MOUSE\n");
|
|
|
|
ret = pImmIsUIMessageA(NULL, WM_MSIME_RECONVERTREQUEST, 0, 0);
|
|
|
|
ok(!ret, "ImmIsUIMessageA returned TRUE for WM_MSIME_RECONVERTREQUEST\n");
|
|
|
|
ret = pImmIsUIMessageA(NULL, WM_MSIME_RECONVERT, 0, 0);
|
|
|
|
ok(!ret, "ImmIsUIMessageA returned TRUE for WM_MSIME_RECONVERT\n");
|
|
|
|
ret = pImmIsUIMessageA(NULL, WM_MSIME_QUERYPOSITION, 0, 0);
|
|
|
|
ok(!ret, "ImmIsUIMessageA returned TRUE for WM_MSIME_QUERYPOSITION\n");
|
|
|
|
ret = pImmIsUIMessageA(NULL, WM_MSIME_DOCUMENTFEED, 0, 0);
|
|
|
|
ok(!ret, "ImmIsUIMessageA returned TRUE for WM_MSIME_DOCUMENTFEED\n");
|
2011-12-15 00:39:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void test_ImmGetContext(void)
|
|
|
|
{
|
|
|
|
HIMC himc;
|
|
|
|
DWORD err;
|
|
|
|
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
himc = ImmGetContext((HWND)0xffffffff);
|
|
|
|
err = GetLastError();
|
|
|
|
ok(himc == NULL, "ImmGetContext succeeded\n");
|
|
|
|
ok(err == ERROR_INVALID_WINDOW_HANDLE, "got %u\n", err);
|
|
|
|
|
|
|
|
himc = ImmGetContext(hwnd);
|
|
|
|
ok(himc != NULL, "ImmGetContext failed\n");
|
|
|
|
ok(ImmReleaseContext(hwnd, himc), "ImmReleaseContext failed\n");
|
|
|
|
}
|
|
|
|
|
2012-03-15 21:45:07 +00:00
|
|
|
static void test_ImmGetDescription(void)
|
|
|
|
{
|
|
|
|
HKL hkl;
|
|
|
|
WCHAR descW[100];
|
|
|
|
CHAR descA[100];
|
|
|
|
UINT ret, lret;
|
|
|
|
|
|
|
|
/* FIXME: invalid keyboard layouts should not pass */
|
|
|
|
ret = ImmGetDescriptionW(NULL, NULL, 0);
|
2014-04-30 12:16:47 +00:00
|
|
|
ok(!ret, "ImmGetDescriptionW failed, expected 0 received %d.\n", ret);
|
|
|
|
ret = ImmGetDescriptionA(NULL, NULL, 0);
|
|
|
|
ok(!ret, "ImmGetDescriptionA failed, expected 0 received %d.\n", ret);
|
2012-03-15 21:45:07 +00:00
|
|
|
|
|
|
|
/* load a language with valid IMM descriptions */
|
2014-04-30 12:16:47 +00:00
|
|
|
hkl = GetKeyboardLayout(0);
|
|
|
|
ok(hkl != 0, "GetKeyboardLayout failed, expected != 0.\n");
|
2012-03-15 21:45:07 +00:00
|
|
|
|
|
|
|
ret = ImmGetDescriptionW(hkl, NULL, 0);
|
|
|
|
if(!ret)
|
|
|
|
{
|
|
|
|
win_skip("ImmGetDescriptionW is not working for current loaded keyboard.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-04-30 12:16:47 +00:00
|
|
|
SetLastError(0xdeadcafe);
|
|
|
|
ret = ImmGetDescriptionW(0, NULL, 100);
|
|
|
|
ok (ret == 0, "ImmGetDescriptionW with 0 hkl should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok (ret == 0xdeadcafe, "Last Error should remain unchanged\n");
|
|
|
|
|
2012-03-15 21:45:07 +00:00
|
|
|
ret = ImmGetDescriptionW(hkl, descW, 0);
|
|
|
|
ok(ret, "ImmGetDescriptionW failed, expected != 0 received 0.\n");
|
|
|
|
|
|
|
|
lret = ImmGetDescriptionW(hkl, descW, ret + 1);
|
|
|
|
ok(lret, "ImmGetDescriptionW failed, expected != 0 received 0.\n");
|
|
|
|
ok(lret == ret, "ImmGetDescriptionW failed to return the correct amount of data. Expected %d, got %d.\n", ret, lret);
|
|
|
|
|
|
|
|
lret = ImmGetDescriptionA(hkl, descA, ret + 1);
|
|
|
|
ok(lret, "ImmGetDescriptionA failed, expected != 0 received 0.\n");
|
2014-04-30 12:16:47 +00:00
|
|
|
ok(lret == ret, "ImmGetDescriptionA failed to return the correct amount of data. Expected %d, got %d.\n", ret, lret);
|
2012-03-15 21:45:07 +00:00
|
|
|
|
|
|
|
ret /= 2; /* try to copy partially */
|
|
|
|
lret = ImmGetDescriptionW(hkl, descW, ret + 1);
|
|
|
|
ok(lret, "ImmGetDescriptionW failed, expected != 0 received 0.\n");
|
|
|
|
ok(lret == ret, "ImmGetDescriptionW failed to return the correct amount of data. Expected %d, got %d.\n", ret, lret);
|
|
|
|
|
2014-04-30 12:16:47 +00:00
|
|
|
lret = ImmGetDescriptionA(hkl, descA, ret + 1);
|
|
|
|
ok(!lret, "ImmGetDescriptionA should fail\n");
|
|
|
|
|
2012-03-15 21:45:07 +00:00
|
|
|
ret = ImmGetDescriptionW(hkl, descW, 1);
|
|
|
|
ok(!ret, "ImmGetDescriptionW failed, expected 0 received %d.\n", ret);
|
|
|
|
|
|
|
|
UnloadKeyboardLayout(hkl);
|
|
|
|
}
|
|
|
|
|
2016-03-09 08:32:48 +00:00
|
|
|
static LRESULT (WINAPI *old_imm_wnd_proc)(HWND, UINT, WPARAM, LPARAM);
|
|
|
|
static LRESULT WINAPI imm_wnd_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
|
|
|
|
{
|
|
|
|
ok(msg != WM_DESTROY, "got WM_DESTROY message\n");
|
|
|
|
return old_imm_wnd_proc(hwnd, msg, wparam, lparam);
|
|
|
|
}
|
|
|
|
|
|
|
|
static HWND thread_ime_wnd;
|
|
|
|
static DWORD WINAPI test_ImmGetDefaultIMEWnd_thread(void *arg)
|
|
|
|
{
|
|
|
|
CreateWindowA("static", "static", WS_POPUP, 0, 0, 1, 1, NULL, NULL, NULL, NULL);
|
|
|
|
|
|
|
|
thread_ime_wnd = ImmGetDefaultIMEWnd(0);
|
|
|
|
ok(thread_ime_wnd != 0, "ImmGetDefaultIMEWnd returned NULL\n");
|
|
|
|
old_imm_wnd_proc = (void*)SetWindowLongPtrW(thread_ime_wnd, GWLP_WNDPROC, (LONG_PTR)imm_wnd_proc);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-02-03 20:58:19 +00:00
|
|
|
static void test_ImmDefaultHwnd(void)
|
|
|
|
{
|
|
|
|
HIMC imc1, imc2, imc3;
|
|
|
|
HWND def1, def3;
|
2016-03-09 08:32:48 +00:00
|
|
|
HANDLE thread;
|
2013-02-03 20:58:19 +00:00
|
|
|
HWND hwnd;
|
2016-11-17 23:47:11 +00:00
|
|
|
char title[16];
|
|
|
|
LONG style;
|
2013-02-03 20:58:19 +00:00
|
|
|
|
2014-04-30 12:16:47 +00:00
|
|
|
hwnd = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "Wine imm32.dll test",
|
|
|
|
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
|
|
|
|
240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL);
|
2013-02-03 20:58:19 +00:00
|
|
|
|
|
|
|
ShowWindow(hwnd, SW_SHOWNORMAL);
|
|
|
|
|
|
|
|
imc1 = ImmGetContext(hwnd);
|
|
|
|
if (!imc1)
|
|
|
|
{
|
|
|
|
win_skip("IME support not implemented\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
def1 = ImmGetDefaultIMEWnd(hwnd);
|
|
|
|
|
2016-11-17 23:47:11 +00:00
|
|
|
GetWindowTextA(def1, title, sizeof(title));
|
|
|
|
ok(!strcmp(title, "Default IME"), "got %s\n", title);
|
|
|
|
style = GetWindowLongA(def1, GWL_STYLE);
|
|
|
|
ok(style == (WS_DISABLED | WS_POPUP | WS_CLIPSIBLINGS), "got %08x\n", style);
|
|
|
|
style = GetWindowLongA(def1, GWL_EXSTYLE);
|
|
|
|
ok(style == 0, "got %08x\n", style);
|
|
|
|
|
2013-02-03 20:58:19 +00:00
|
|
|
imc2 = ImmCreateContext();
|
|
|
|
ImmSetOpenStatus(imc2, TRUE);
|
|
|
|
|
|
|
|
imc3 = ImmGetContext(hwnd);
|
|
|
|
def3 = ImmGetDefaultIMEWnd(hwnd);
|
|
|
|
|
|
|
|
ok(def3 == def1, "Default IME window should not change\n");
|
|
|
|
ok(imc1 == imc3, "IME context should not change\n");
|
|
|
|
ImmSetOpenStatus(imc2, FALSE);
|
|
|
|
|
2016-03-09 08:32:48 +00:00
|
|
|
thread = CreateThread(NULL, 0, test_ImmGetDefaultIMEWnd_thread, NULL, 0, NULL);
|
|
|
|
WaitForSingleObject(thread, INFINITE);
|
|
|
|
ok(thread_ime_wnd != def1, "thread_ime_wnd == def1\n");
|
|
|
|
ok(!IsWindow(thread_ime_wnd), "thread_ime_wnd was not destroyed\n");
|
2016-08-18 10:08:05 +00:00
|
|
|
CloseHandle(thread);
|
2016-03-09 08:32:48 +00:00
|
|
|
|
2013-02-03 20:58:19 +00:00
|
|
|
ImmReleaseContext(hwnd, imc1);
|
|
|
|
ImmReleaseContext(hwnd, imc3);
|
|
|
|
ImmDestroyContext(imc2);
|
|
|
|
DestroyWindow(hwnd);
|
|
|
|
}
|
|
|
|
|
2016-08-18 10:08:05 +00:00
|
|
|
static BOOL CALLBACK is_ime_window_proc(HWND hWnd, LPARAM param)
|
|
|
|
{
|
|
|
|
static const WCHAR imeW[] = {'I','M','E',0};
|
|
|
|
WCHAR class_nameW[16];
|
|
|
|
HWND *ime_window = (HWND *)param;
|
|
|
|
if (GetClassNameW(hWnd, class_nameW, sizeof(class_nameW)/sizeof(class_nameW[0])) &&
|
|
|
|
!lstrcmpW(class_nameW, imeW)) {
|
|
|
|
*ime_window = hWnd;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HWND get_ime_window(void)
|
|
|
|
{
|
|
|
|
HWND ime_window = NULL;
|
|
|
|
EnumThreadWindows(GetCurrentThreadId(), is_ime_window_proc, (LPARAM)&ime_window);
|
|
|
|
return ime_window;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct testcase_ime_window {
|
|
|
|
BOOL visible;
|
|
|
|
BOOL top_level_window;
|
|
|
|
};
|
|
|
|
|
|
|
|
static DWORD WINAPI test_default_ime_window_cb(void *arg)
|
|
|
|
{
|
|
|
|
struct testcase_ime_window *testcase = (struct testcase_ime_window *)arg;
|
|
|
|
DWORD visible = testcase->visible ? WS_VISIBLE : 0;
|
|
|
|
HWND hwnd1, hwnd2, default_ime_wnd, ime_wnd;
|
|
|
|
|
|
|
|
ok(!get_ime_window(), "Expected no IME windows\n");
|
|
|
|
if (testcase->top_level_window) {
|
|
|
|
test_phase = FIRST_WINDOW;
|
|
|
|
hwnd1 = CreateWindowExA(WS_EX_CLIENTEDGE, wndcls, "Wine imm32.dll test",
|
|
|
|
WS_OVERLAPPEDWINDOW | visible,
|
|
|
|
CW_USEDEFAULT, CW_USEDEFAULT,
|
|
|
|
240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
hwnd1 = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "Wine imm32.dll test",
|
|
|
|
WS_CHILD | visible,
|
|
|
|
CW_USEDEFAULT, CW_USEDEFAULT,
|
|
|
|
240, 24, hwnd, NULL, GetModuleHandleW(NULL), NULL);
|
|
|
|
}
|
|
|
|
ime_wnd = get_ime_window();
|
2016-11-17 23:47:11 +00:00
|
|
|
ok(ime_wnd != NULL, "Expected IME window existence\n");
|
2016-08-18 10:08:05 +00:00
|
|
|
default_ime_wnd = ImmGetDefaultIMEWnd(hwnd1);
|
2016-11-17 23:47:11 +00:00
|
|
|
ok(ime_wnd == default_ime_wnd, "Expected %p, got %p\n", ime_wnd, default_ime_wnd);
|
2016-08-18 10:08:05 +00:00
|
|
|
|
|
|
|
test_phase = SECOND_WINDOW;
|
|
|
|
hwnd2 = CreateWindowExA(WS_EX_CLIENTEDGE, wndcls, "Wine imm32.dll test",
|
|
|
|
WS_OVERLAPPEDWINDOW | visible,
|
|
|
|
CW_USEDEFAULT, CW_USEDEFAULT,
|
|
|
|
240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL);
|
|
|
|
DestroyWindow(hwnd2);
|
2016-11-17 23:47:11 +00:00
|
|
|
ok(IsWindow(ime_wnd) ||
|
2016-08-18 10:08:05 +00:00
|
|
|
broken(!testcase->visible /* Vista */) ||
|
|
|
|
broken(!testcase->top_level_window /* Vista */) ,
|
|
|
|
"Expected IME window existence\n");
|
|
|
|
DestroyWindow(hwnd1);
|
|
|
|
ok(!IsWindow(ime_wnd), "Expected no IME windows\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static DWORD WINAPI test_default_ime_window_cancel_cb(void *arg)
|
|
|
|
{
|
|
|
|
struct testcase_ime_window *testcase = (struct testcase_ime_window *)arg;
|
|
|
|
DWORD visible = testcase->visible ? WS_VISIBLE : 0;
|
|
|
|
HWND hwnd1, hwnd2, default_ime_wnd, ime_wnd;
|
|
|
|
|
|
|
|
ok(!get_ime_window(), "Expected no IME windows\n");
|
|
|
|
test_phase = NCCREATE_CANCEL;
|
|
|
|
hwnd1 = CreateWindowExA(WS_EX_CLIENTEDGE, wndcls, "Wine imm32.dll test",
|
|
|
|
WS_OVERLAPPEDWINDOW | visible,
|
|
|
|
CW_USEDEFAULT, CW_USEDEFAULT,
|
|
|
|
240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL);
|
|
|
|
ok(hwnd1 == NULL, "creation succeeded, got %p\n", hwnd1);
|
|
|
|
ok(!get_ime_window(), "Expected no IME windows\n");
|
|
|
|
|
|
|
|
test_phase = CREATE_CANCEL;
|
|
|
|
hwnd1 = CreateWindowExA(WS_EX_CLIENTEDGE, wndcls, "Wine imm32.dll test",
|
|
|
|
WS_OVERLAPPEDWINDOW | visible,
|
|
|
|
CW_USEDEFAULT, CW_USEDEFAULT,
|
|
|
|
240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL);
|
|
|
|
ok(hwnd1 == NULL, "creation succeeded, got %p\n", hwnd1);
|
|
|
|
ok(!get_ime_window(), "Expected no IME windows\n");
|
|
|
|
|
|
|
|
test_phase = FIRST_WINDOW;
|
|
|
|
hwnd2 = CreateWindowExA(WS_EX_CLIENTEDGE, wndcls, "Wine imm32.dll test",
|
|
|
|
WS_OVERLAPPEDWINDOW | visible,
|
|
|
|
CW_USEDEFAULT, CW_USEDEFAULT,
|
|
|
|
240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL);
|
|
|
|
ime_wnd = get_ime_window();
|
2016-11-17 23:47:11 +00:00
|
|
|
ok(ime_wnd != NULL, "Expected IME window existence\n");
|
2016-08-18 10:08:05 +00:00
|
|
|
default_ime_wnd = ImmGetDefaultIMEWnd(hwnd2);
|
2016-11-17 23:47:11 +00:00
|
|
|
ok(ime_wnd == default_ime_wnd, "Expected %p, got %p\n", ime_wnd, default_ime_wnd);
|
2016-08-18 10:08:05 +00:00
|
|
|
|
|
|
|
DestroyWindow(hwnd2);
|
|
|
|
ok(!IsWindow(ime_wnd), "Expected no IME windows\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static DWORD WINAPI test_default_ime_disabled_cb(void *arg)
|
|
|
|
{
|
|
|
|
HWND hWnd, default_ime_wnd;
|
|
|
|
|
|
|
|
ok(!get_ime_window(), "Expected no IME windows\n");
|
|
|
|
ImmDisableIME(GetCurrentThreadId());
|
|
|
|
test_phase = IME_DISABLED;
|
|
|
|
hWnd = CreateWindowExA(WS_EX_CLIENTEDGE, wndcls, "Wine imm32.dll test",
|
|
|
|
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
|
|
|
|
CW_USEDEFAULT, CW_USEDEFAULT,
|
|
|
|
240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL);
|
|
|
|
default_ime_wnd = ImmGetDefaultIMEWnd(hWnd);
|
|
|
|
ok(!default_ime_wnd, "Expected no IME windows\n");
|
|
|
|
DestroyWindow(hWnd);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2016-11-17 23:47:11 +00:00
|
|
|
static DWORD WINAPI test_default_ime_with_message_only_window_cb(void *arg)
|
|
|
|
{
|
|
|
|
HWND hwnd1, hwnd2, default_ime_wnd;
|
|
|
|
|
|
|
|
test_phase = PHASE_UNKNOWN;
|
|
|
|
hwnd1 = CreateWindowA(wndcls, "Wine imm32.dll test",
|
|
|
|
WS_OVERLAPPEDWINDOW,
|
|
|
|
CW_USEDEFAULT, CW_USEDEFAULT,
|
|
|
|
240, 120, HWND_MESSAGE, NULL, GetModuleHandleW(NULL), NULL);
|
|
|
|
default_ime_wnd = ImmGetDefaultIMEWnd(hwnd1);
|
|
|
|
ok(!IsWindow(default_ime_wnd), "Expected no IME windows, got %p\n", default_ime_wnd);
|
|
|
|
|
|
|
|
hwnd2 = CreateWindowA(wndcls, "Wine imm32.dll test",
|
|
|
|
WS_OVERLAPPEDWINDOW,
|
|
|
|
CW_USEDEFAULT, CW_USEDEFAULT,
|
|
|
|
240, 120, hwnd1, NULL, GetModuleHandleW(NULL), NULL);
|
|
|
|
default_ime_wnd = ImmGetDefaultIMEWnd(hwnd2);
|
|
|
|
ok(IsWindow(default_ime_wnd), "Expected IME window existance\n");
|
|
|
|
|
|
|
|
DestroyWindow(hwnd2);
|
|
|
|
DestroyWindow(hwnd1);
|
|
|
|
|
|
|
|
hwnd1 = CreateWindowA(wndcls, "Wine imm32.dll test",
|
|
|
|
WS_OVERLAPPEDWINDOW,
|
|
|
|
CW_USEDEFAULT, CW_USEDEFAULT,
|
|
|
|
240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL);
|
|
|
|
default_ime_wnd = ImmGetDefaultIMEWnd(hwnd1);
|
|
|
|
ok(IsWindow(default_ime_wnd), "Expected IME window existence\n");
|
|
|
|
SetParent(hwnd1, HWND_MESSAGE);
|
|
|
|
default_ime_wnd = ImmGetDefaultIMEWnd(hwnd1);
|
|
|
|
ok(IsWindow(default_ime_wnd), "Expected IME window existence\n");
|
|
|
|
DestroyWindow(hwnd1);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2016-08-18 10:08:05 +00:00
|
|
|
static void test_default_ime_window_creation(void)
|
|
|
|
{
|
|
|
|
HANDLE thread;
|
|
|
|
size_t i;
|
|
|
|
struct testcase_ime_window testcases[] = {
|
|
|
|
/* visible, top-level window */
|
|
|
|
{ TRUE, TRUE },
|
|
|
|
{ FALSE, TRUE },
|
|
|
|
{ TRUE, FALSE },
|
|
|
|
{ FALSE, FALSE }
|
|
|
|
};
|
|
|
|
|
|
|
|
for (i = 0; i < sizeof(testcases)/sizeof(testcases[0]); i++)
|
|
|
|
{
|
|
|
|
thread = CreateThread(NULL, 0, test_default_ime_window_cb, &testcases[i], 0, NULL);
|
|
|
|
ok(thread != NULL, "CreateThread failed with error %u\n", GetLastError());
|
|
|
|
while (MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT) == WAIT_OBJECT_0 + 1)
|
|
|
|
{
|
|
|
|
MSG msg;
|
|
|
|
while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
|
|
|
|
{
|
|
|
|
TranslateMessage(&msg);
|
|
|
|
DispatchMessageA(&msg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CloseHandle(thread);
|
|
|
|
|
|
|
|
if (testcases[i].top_level_window)
|
|
|
|
{
|
|
|
|
thread = CreateThread(NULL, 0, test_default_ime_window_cancel_cb, &testcases[i], 0, NULL);
|
|
|
|
ok(thread != NULL, "CreateThread failed with error %u\n", GetLastError());
|
|
|
|
WaitForSingleObject(thread, INFINITE);
|
|
|
|
CloseHandle(thread);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
thread = CreateThread(NULL, 0, test_default_ime_disabled_cb, NULL, 0, NULL);
|
|
|
|
WaitForSingleObject(thread, INFINITE);
|
|
|
|
CloseHandle(thread);
|
|
|
|
|
2016-11-17 23:47:11 +00:00
|
|
|
thread = CreateThread(NULL, 0, test_default_ime_with_message_only_window_cb, NULL, 0, NULL);
|
|
|
|
WaitForSingleObject(thread, INFINITE);
|
|
|
|
CloseHandle(thread);
|
|
|
|
|
2016-08-18 10:08:05 +00:00
|
|
|
test_phase = PHASE_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
2013-12-01 15:57:54 +00:00
|
|
|
static void test_ImmGetIMCLockCount(void)
|
|
|
|
{
|
|
|
|
HIMC imc;
|
|
|
|
DWORD count, ret, i;
|
|
|
|
INPUTCONTEXT *ic;
|
|
|
|
|
2014-04-30 12:16:47 +00:00
|
|
|
imc = ImmCreateContext();
|
|
|
|
ImmDestroyContext(imc);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
count = ImmGetIMCLockCount((HIMC)0xdeadcafe);
|
|
|
|
ok(count == 0, "Invalid IMC should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
count = ImmGetIMCLockCount(0x00000000);
|
|
|
|
ok(count == 0, "NULL IMC should return 0\n");
|
|
|
|
ret = GetLastError();
|
2014-09-28 18:28:09 +00:00
|
|
|
ok(ret == 0xdeadbeef, "Last Error should remain unchanged: %08x\n",ret);
|
2014-04-30 12:16:47 +00:00
|
|
|
count = ImmGetIMCLockCount(imc);
|
|
|
|
ok(count == 0, "Destroyed IMC should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
|
2013-12-01 15:57:54 +00:00
|
|
|
imc = ImmCreateContext();
|
|
|
|
count = ImmGetIMCLockCount(imc);
|
|
|
|
ok(count == 0, "expect 0, returned %d\n", count);
|
|
|
|
ic = ImmLockIMC(imc);
|
|
|
|
ok(ic != NULL, "ImmLockIMC failed!\n");
|
|
|
|
count = ImmGetIMCLockCount(imc);
|
|
|
|
ok(count == 1, "expect 1, returned %d\n", count);
|
|
|
|
ret = ImmUnlockIMC(imc);
|
|
|
|
ok(ret == TRUE, "expect TRUE, ret %d\n", ret);
|
|
|
|
count = ImmGetIMCLockCount(imc);
|
|
|
|
ok(count == 0, "expect 0, returned %d\n", count);
|
|
|
|
ret = ImmUnlockIMC(imc);
|
|
|
|
ok(ret == TRUE, "expect TRUE, ret %d\n", ret);
|
|
|
|
count = ImmGetIMCLockCount(imc);
|
|
|
|
ok(count == 0, "expect 0, returned %d\n", count);
|
|
|
|
|
|
|
|
for (i = 0; i < GMEM_LOCKCOUNT * 2; i++)
|
|
|
|
{
|
|
|
|
ic = ImmLockIMC(imc);
|
|
|
|
ok(ic != NULL, "ImmLockIMC failed!\n");
|
|
|
|
}
|
|
|
|
count = ImmGetIMCLockCount(imc);
|
|
|
|
todo_wine ok(count == GMEM_LOCKCOUNT, "expect GMEM_LOCKCOUNT, returned %d\n", count);
|
|
|
|
|
|
|
|
for (i = 0; i < GMEM_LOCKCOUNT - 1; i++)
|
|
|
|
ImmUnlockIMC(imc);
|
|
|
|
count = ImmGetIMCLockCount(imc);
|
|
|
|
todo_wine ok(count == 1, "expect 1, returned %d\n", count);
|
|
|
|
ImmUnlockIMC(imc);
|
|
|
|
count = ImmGetIMCLockCount(imc);
|
|
|
|
todo_wine ok(count == 0, "expect 0, returned %d\n", count);
|
|
|
|
|
|
|
|
ImmDestroyContext(imc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_ImmGetIMCCLockCount(void)
|
|
|
|
{
|
|
|
|
HIMCC imcc;
|
2014-04-30 12:16:47 +00:00
|
|
|
DWORD count, g_count, i;
|
|
|
|
BOOL ret;
|
2013-12-01 15:57:54 +00:00
|
|
|
VOID *p;
|
|
|
|
|
|
|
|
imcc = ImmCreateIMCC(sizeof(CANDIDATEINFO));
|
|
|
|
count = ImmGetIMCCLockCount(imcc);
|
|
|
|
ok(count == 0, "expect 0, returned %d\n", count);
|
|
|
|
ImmLockIMCC(imcc);
|
|
|
|
count = ImmGetIMCCLockCount(imcc);
|
|
|
|
ok(count == 1, "expect 1, returned %d\n", count);
|
|
|
|
ret = ImmUnlockIMCC(imcc);
|
|
|
|
ok(ret == FALSE, "expect FALSE, ret %d\n", ret);
|
|
|
|
count = ImmGetIMCCLockCount(imcc);
|
|
|
|
ok(count == 0, "expect 0, returned %d\n", count);
|
|
|
|
ret = ImmUnlockIMCC(imcc);
|
|
|
|
ok(ret == FALSE, "expect FALSE, ret %d\n", ret);
|
|
|
|
count = ImmGetIMCCLockCount(imcc);
|
|
|
|
ok(count == 0, "expect 0, returned %d\n", count);
|
|
|
|
|
|
|
|
p = ImmLockIMCC(imcc);
|
|
|
|
ok(GlobalHandle(p) == imcc, "expect %p, returned %p\n", imcc, GlobalHandle(p));
|
|
|
|
|
|
|
|
for (i = 0; i < GMEM_LOCKCOUNT * 2; i++)
|
|
|
|
{
|
|
|
|
ImmLockIMCC(imcc);
|
|
|
|
count = ImmGetIMCCLockCount(imcc);
|
|
|
|
g_count = GlobalFlags(imcc) & GMEM_LOCKCOUNT;
|
|
|
|
ok(count == g_count, "count %d, g_count %d\n", count, g_count);
|
|
|
|
}
|
|
|
|
count = ImmGetIMCCLockCount(imcc);
|
|
|
|
ok(count == GMEM_LOCKCOUNT, "expect GMEM_LOCKCOUNT, returned %d\n", count);
|
|
|
|
|
|
|
|
for (i = 0; i < GMEM_LOCKCOUNT - 1; i++)
|
|
|
|
GlobalUnlock(imcc);
|
|
|
|
count = ImmGetIMCCLockCount(imcc);
|
|
|
|
ok(count == 1, "expect 1, returned %d\n", count);
|
|
|
|
GlobalUnlock(imcc);
|
|
|
|
count = ImmGetIMCCLockCount(imcc);
|
|
|
|
ok(count == 0, "expect 0, returned %d\n", count);
|
|
|
|
|
|
|
|
ImmDestroyIMCC(imcc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_ImmDestroyContext(void)
|
|
|
|
{
|
|
|
|
HIMC imc;
|
|
|
|
DWORD ret, count;
|
|
|
|
INPUTCONTEXT *ic;
|
|
|
|
|
|
|
|
imc = ImmCreateContext();
|
|
|
|
count = ImmGetIMCLockCount(imc);
|
|
|
|
ok(count == 0, "expect 0, returned %d\n", count);
|
|
|
|
ic = ImmLockIMC(imc);
|
|
|
|
ok(ic != NULL, "ImmLockIMC failed!\n");
|
|
|
|
count = ImmGetIMCLockCount(imc);
|
|
|
|
ok(count == 1, "expect 1, returned %d\n", count);
|
|
|
|
ret = ImmDestroyContext(imc);
|
|
|
|
ok(ret == TRUE, "Destroy a locked IMC should success!\n");
|
|
|
|
ic = ImmLockIMC(imc);
|
2014-04-30 12:16:47 +00:00
|
|
|
ok(ic == NULL, "Lock a destroyed IMC should fail!\n");
|
2013-12-01 15:57:54 +00:00
|
|
|
ret = ImmUnlockIMC(imc);
|
2014-04-30 12:16:47 +00:00
|
|
|
ok(ret == FALSE, "Unlock a destroyed IMC should fail!\n");
|
2013-12-01 15:57:54 +00:00
|
|
|
count = ImmGetIMCLockCount(imc);
|
2014-04-30 12:16:47 +00:00
|
|
|
ok(count == 0, "Get lock count of a destroyed IMC should return 0!\n");
|
2013-12-01 15:57:54 +00:00
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmDestroyContext(imc);
|
2014-04-30 12:16:47 +00:00
|
|
|
ok(ret == FALSE, "Destroy a destroyed IMC should fail!\n");
|
2013-12-01 15:57:54 +00:00
|
|
|
ret = GetLastError();
|
2014-04-30 12:16:47 +00:00
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
2013-12-01 15:57:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void test_ImmDestroyIMCC(void)
|
|
|
|
{
|
|
|
|
HIMCC imcc;
|
|
|
|
DWORD ret, count, size;
|
|
|
|
VOID *p;
|
|
|
|
|
|
|
|
imcc = ImmCreateIMCC(sizeof(CANDIDATEINFO));
|
|
|
|
count = ImmGetIMCCLockCount(imcc);
|
|
|
|
ok(count == 0, "expect 0, returned %d\n", count);
|
|
|
|
p = ImmLockIMCC(imcc);
|
|
|
|
ok(p != NULL, "ImmLockIMCC failed!\n");
|
|
|
|
count = ImmGetIMCCLockCount(imcc);
|
|
|
|
ok(count == 1, "expect 1, returned %d\n", count);
|
|
|
|
size = ImmGetIMCCSize(imcc);
|
|
|
|
ok(size == sizeof(CANDIDATEINFO), "returned %d\n", size);
|
|
|
|
p = ImmDestroyIMCC(imcc);
|
|
|
|
ok(p == NULL, "Destroy a locked IMCC should success!\n");
|
|
|
|
p = ImmLockIMCC(imcc);
|
|
|
|
ok(p == NULL, "Lock a destroyed IMCC should fail!\n");
|
|
|
|
ret = ImmUnlockIMCC(imcc);
|
|
|
|
ok(ret == FALSE, "Unlock a destroyed IMCC should return FALSE!\n");
|
|
|
|
count = ImmGetIMCCLockCount(imcc);
|
|
|
|
ok(count == 0, "Get lock count of a destroyed IMCC should return 0!\n");
|
|
|
|
size = ImmGetIMCCSize(imcc);
|
|
|
|
ok(size == 0, "Get size of a destroyed IMCC should return 0!\n");
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
p = ImmDestroyIMCC(imcc);
|
|
|
|
ok(p != NULL, "returned NULL\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
}
|
|
|
|
|
2013-02-03 20:58:19 +00:00
|
|
|
static void test_ImmMessages(void)
|
|
|
|
{
|
|
|
|
CANDIDATEFORM cf;
|
|
|
|
imm_msgs *msg;
|
|
|
|
HWND defwnd;
|
|
|
|
HIMC imc;
|
|
|
|
UINT idx = 0;
|
|
|
|
|
2016-08-18 10:08:05 +00:00
|
|
|
LPINPUTCONTEXT lpIMC;
|
|
|
|
LPTRANSMSG lpTransMsg;
|
|
|
|
|
2014-04-30 12:16:47 +00:00
|
|
|
HWND hwnd = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "Wine imm32.dll test",
|
|
|
|
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
|
|
|
|
240, 120, NULL, NULL, GetModuleHandleA(NULL), NULL);
|
2013-02-03 20:58:19 +00:00
|
|
|
|
|
|
|
ShowWindow(hwnd, SW_SHOWNORMAL);
|
|
|
|
defwnd = ImmGetDefaultIMEWnd(hwnd);
|
|
|
|
imc = ImmGetContext(hwnd);
|
|
|
|
|
|
|
|
ImmSetOpenStatus(imc, TRUE);
|
|
|
|
msg_spy_flush_msgs();
|
2014-04-30 12:16:47 +00:00
|
|
|
SendMessageA(defwnd, WM_IME_CONTROL, IMC_GETCANDIDATEPOS, (LPARAM)&cf );
|
2013-02-03 20:58:19 +00:00
|
|
|
do
|
|
|
|
{
|
|
|
|
msg = msg_spy_find_next_msg(WM_IME_CONTROL,&idx);
|
|
|
|
if (msg) ok(!msg->post, "Message should not be posted\n");
|
|
|
|
} while (msg);
|
|
|
|
msg_spy_flush_msgs();
|
2016-08-18 10:08:05 +00:00
|
|
|
|
|
|
|
lpIMC = ImmLockIMC(imc);
|
|
|
|
lpIMC->hMsgBuf = ImmReSizeIMCC(lpIMC->hMsgBuf, (lpIMC->dwNumMsgBuf + 1) * sizeof(TRANSMSG));
|
|
|
|
lpTransMsg = ImmLockIMCC(lpIMC->hMsgBuf);
|
|
|
|
lpTransMsg += lpIMC->dwNumMsgBuf;
|
|
|
|
lpTransMsg->message = WM_IME_STARTCOMPOSITION;
|
|
|
|
lpTransMsg->wParam = 0;
|
|
|
|
lpTransMsg->lParam = 0;
|
|
|
|
ImmUnlockIMCC(lpIMC->hMsgBuf);
|
|
|
|
lpIMC->dwNumMsgBuf++;
|
|
|
|
ImmUnlockIMC(imc);
|
|
|
|
ImmGenerateMessage(imc);
|
|
|
|
idx = 0;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
msg = msg_spy_find_next_msg(WM_IME_STARTCOMPOSITION, &idx);
|
|
|
|
if (msg) ok(!msg->post, "Message should not be posted\n");
|
|
|
|
} while (msg);
|
|
|
|
msg_spy_flush_msgs();
|
|
|
|
|
|
|
|
lpIMC = ImmLockIMC(imc);
|
|
|
|
lpIMC->hMsgBuf = ImmReSizeIMCC(lpIMC->hMsgBuf, (lpIMC->dwNumMsgBuf + 1) * sizeof(TRANSMSG));
|
|
|
|
lpTransMsg = ImmLockIMCC(lpIMC->hMsgBuf);
|
|
|
|
lpTransMsg += lpIMC->dwNumMsgBuf;
|
|
|
|
lpTransMsg->message = WM_IME_COMPOSITION;
|
|
|
|
lpTransMsg->wParam = 0;
|
|
|
|
lpTransMsg->lParam = 0;
|
|
|
|
ImmUnlockIMCC(lpIMC->hMsgBuf);
|
|
|
|
lpIMC->dwNumMsgBuf++;
|
|
|
|
ImmUnlockIMC(imc);
|
|
|
|
ImmGenerateMessage(imc);
|
|
|
|
idx = 0;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
msg = msg_spy_find_next_msg(WM_IME_COMPOSITION, &idx);
|
|
|
|
if (msg) ok(!msg->post, "Message should not be posted\n");
|
|
|
|
} while (msg);
|
|
|
|
msg_spy_flush_msgs();
|
|
|
|
|
|
|
|
lpIMC = ImmLockIMC(imc);
|
|
|
|
lpIMC->hMsgBuf = ImmReSizeIMCC(lpIMC->hMsgBuf, (lpIMC->dwNumMsgBuf + 1) * sizeof(TRANSMSG));
|
|
|
|
lpTransMsg = ImmLockIMCC(lpIMC->hMsgBuf);
|
|
|
|
lpTransMsg += lpIMC->dwNumMsgBuf;
|
|
|
|
lpTransMsg->message = WM_IME_ENDCOMPOSITION;
|
|
|
|
lpTransMsg->wParam = 0;
|
|
|
|
lpTransMsg->lParam = 0;
|
|
|
|
ImmUnlockIMCC(lpIMC->hMsgBuf);
|
|
|
|
lpIMC->dwNumMsgBuf++;
|
|
|
|
ImmUnlockIMC(imc);
|
|
|
|
ImmGenerateMessage(imc);
|
|
|
|
idx = 0;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
msg = msg_spy_find_next_msg(WM_IME_ENDCOMPOSITION, &idx);
|
|
|
|
if (msg) ok(!msg->post, "Message should not be posted\n");
|
|
|
|
} while (msg);
|
|
|
|
msg_spy_flush_msgs();
|
|
|
|
|
2013-02-03 20:58:19 +00:00
|
|
|
ImmSetOpenStatus(imc, FALSE);
|
|
|
|
ImmReleaseContext(hwnd, imc);
|
|
|
|
DestroyWindow(hwnd);
|
|
|
|
}
|
|
|
|
|
2013-12-01 15:57:54 +00:00
|
|
|
static LRESULT CALLBACK processkey_wnd_proc( HWND hWnd, UINT msg, WPARAM wParam,
|
|
|
|
LPARAM lParam )
|
|
|
|
{
|
|
|
|
return DefWindowProcW(hWnd, msg, wParam, lParam);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_ime_processkey(void)
|
|
|
|
{
|
|
|
|
WCHAR classNameW[] = {'P','r','o','c','e','s','s', 'K','e','y','T','e','s','t','C','l','a','s','s',0};
|
|
|
|
WCHAR windowNameW[] = {'P','r','o','c','e','s','s', 'K','e','y',0};
|
|
|
|
|
|
|
|
MSG msg;
|
|
|
|
WNDCLASSW wclass;
|
|
|
|
HANDLE hInstance = GetModuleHandleW(NULL);
|
|
|
|
TEST_INPUT inputs[2];
|
|
|
|
HIMC imc;
|
|
|
|
INT rc;
|
|
|
|
HWND hWndTest;
|
|
|
|
|
|
|
|
wclass.lpszClassName = classNameW;
|
|
|
|
wclass.style = CS_HREDRAW | CS_VREDRAW;
|
|
|
|
wclass.lpfnWndProc = processkey_wnd_proc;
|
|
|
|
wclass.hInstance = hInstance;
|
2014-04-30 12:16:47 +00:00
|
|
|
wclass.hIcon = LoadIconW(0, (LPCWSTR)IDI_APPLICATION);
|
|
|
|
wclass.hCursor = LoadCursorW( NULL, (LPCWSTR)IDC_ARROW);
|
2013-12-01 15:57:54 +00:00
|
|
|
wclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
|
|
|
|
wclass.lpszMenuName = 0;
|
|
|
|
wclass.cbClsExtra = 0;
|
|
|
|
wclass.cbWndExtra = 0;
|
|
|
|
if(!RegisterClassW(&wclass)){
|
|
|
|
win_skip("Failed to register window.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* create the test window that will receive the keystrokes */
|
|
|
|
hWndTest = CreateWindowW(wclass.lpszClassName, windowNameW,
|
|
|
|
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 100, 100,
|
|
|
|
NULL, NULL, hInstance, NULL);
|
|
|
|
|
|
|
|
ShowWindow(hWndTest, SW_SHOW);
|
|
|
|
SetWindowPos(hWndTest, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
|
|
|
|
SetForegroundWindow(hWndTest);
|
|
|
|
UpdateWindow(hWndTest);
|
|
|
|
|
|
|
|
imc = ImmGetContext(hWndTest);
|
|
|
|
if (!imc)
|
|
|
|
{
|
|
|
|
win_skip("IME not supported\n");
|
|
|
|
DestroyWindow(hWndTest);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = ImmSetOpenStatus(imc, TRUE);
|
|
|
|
if (rc != TRUE)
|
|
|
|
{
|
|
|
|
win_skip("Unable to open IME\n");
|
|
|
|
ImmReleaseContext(hWndTest, imc);
|
|
|
|
DestroyWindow(hWndTest);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* flush pending messages */
|
|
|
|
while (PeekMessageW(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageW(&msg);
|
|
|
|
|
|
|
|
SetFocus(hWndTest);
|
|
|
|
|
|
|
|
/* init input data that never changes */
|
|
|
|
inputs[1].type = inputs[0].type = INPUT_KEYBOARD;
|
|
|
|
inputs[1].u.ki.dwExtraInfo = inputs[0].u.ki.dwExtraInfo = 0;
|
|
|
|
inputs[1].u.ki.time = inputs[0].u.ki.time = 0;
|
|
|
|
|
|
|
|
/* Pressing a key */
|
|
|
|
inputs[0].u.ki.wVk = 0x41;
|
|
|
|
inputs[0].u.ki.wScan = 0x1e;
|
|
|
|
inputs[0].u.ki.dwFlags = 0x0;
|
|
|
|
|
|
|
|
pSendInput(1, (INPUT*)inputs, sizeof(INPUT));
|
|
|
|
|
|
|
|
while(PeekMessageW(&msg, hWndTest, 0, 0, PM_NOREMOVE)) {
|
|
|
|
if(msg.message != WM_KEYDOWN)
|
|
|
|
PeekMessageW(&msg, hWndTest, 0, 0, PM_REMOVE);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ok(msg.wParam != VK_PROCESSKEY,"Incorrect ProcessKey Found\n");
|
|
|
|
PeekMessageW(&msg, hWndTest, 0, 0, PM_REMOVE);
|
|
|
|
if(msg.wParam == VK_PROCESSKEY)
|
|
|
|
trace("ProcessKey was correctly found\n");
|
|
|
|
}
|
|
|
|
TranslateMessage(&msg);
|
|
|
|
DispatchMessageW(&msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
inputs[0].u.ki.wVk = 0x41;
|
|
|
|
inputs[0].u.ki.wScan = 0x1e;
|
|
|
|
inputs[0].u.ki.dwFlags = KEYEVENTF_KEYUP;
|
|
|
|
|
|
|
|
pSendInput(1, (INPUT*)inputs, sizeof(INPUT));
|
|
|
|
|
|
|
|
while(PeekMessageW(&msg, hWndTest, 0, 0, PM_NOREMOVE)) {
|
|
|
|
if(msg.message != WM_KEYUP)
|
|
|
|
PeekMessageW(&msg, hWndTest, 0, 0, PM_REMOVE);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ok(msg.wParam != VK_PROCESSKEY,"Incorrect ProcessKey Found\n");
|
|
|
|
PeekMessageW(&msg, hWndTest, 0, 0, PM_REMOVE);
|
|
|
|
ok(msg.wParam != VK_PROCESSKEY,"ProcessKey should still not be Found\n");
|
|
|
|
}
|
|
|
|
TranslateMessage(&msg);
|
|
|
|
DispatchMessageW(&msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
ImmReleaseContext(hWndTest, imc);
|
|
|
|
ImmSetOpenStatus(imc, FALSE);
|
|
|
|
DestroyWindow(hWndTest);
|
|
|
|
}
|
|
|
|
|
2014-04-30 12:16:47 +00:00
|
|
|
static void test_InvalidIMC(void)
|
|
|
|
{
|
|
|
|
HIMC imc_destroy;
|
|
|
|
HIMC imc_null = 0x00000000;
|
|
|
|
HIMC imc_bad = (HIMC)0xdeadcafe;
|
|
|
|
|
|
|
|
HIMC imc1, imc2, oldimc;
|
|
|
|
DWORD ret;
|
|
|
|
DWORD count;
|
|
|
|
CHAR buffer[1000];
|
|
|
|
INPUTCONTEXT *ic;
|
|
|
|
LOGFONTA lf;
|
|
|
|
|
|
|
|
memset(&lf, 0, sizeof(lf));
|
|
|
|
|
|
|
|
imc_destroy = ImmCreateContext();
|
|
|
|
ret = ImmDestroyContext(imc_destroy);
|
|
|
|
ok(ret == TRUE, "Destroy an IMC should success!\n");
|
|
|
|
|
|
|
|
/* Test associating destroyed imc */
|
|
|
|
imc1 = ImmGetContext(hwnd);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
oldimc = ImmAssociateContext(hwnd, imc_destroy);
|
|
|
|
ok(!oldimc, "Associating to a destroyed imc should fail!\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
imc2 = ImmGetContext(hwnd);
|
|
|
|
ok(imc1 == imc2, "imc should not changed! imc1 %p, imc2 %p\n", imc1, imc2);
|
|
|
|
|
|
|
|
/* Test associating NULL imc, which is different from an invalid imc */
|
|
|
|
oldimc = ImmAssociateContext(hwnd, imc_null);
|
|
|
|
ok(oldimc != NULL, "Associating to NULL imc should success!\n");
|
|
|
|
imc2 = ImmGetContext(hwnd);
|
|
|
|
ok(!imc2, "expect NULL, returned %p\n", imc2);
|
|
|
|
oldimc = ImmAssociateContext(hwnd, imc1);
|
|
|
|
ok(!oldimc, "expect NULL, returned %p\n", oldimc);
|
|
|
|
imc2 = ImmGetContext(hwnd);
|
|
|
|
ok(imc2 == imc1, "imc should not changed! imc2 %p, imc1 %p\n", imc2, imc1);
|
|
|
|
|
|
|
|
/* Test associating invalid imc */
|
|
|
|
imc1 = ImmGetContext(hwnd);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
oldimc = ImmAssociateContext(hwnd, imc_bad);
|
|
|
|
ok(!oldimc, "Associating to a destroyed imc should fail!\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
imc2 = ImmGetContext(hwnd);
|
|
|
|
ok(imc1 == imc2, "imc should not changed! imc1 %p, imc2 %p\n", imc1, imc2);
|
|
|
|
|
|
|
|
|
|
|
|
/* Test ImmGetCandidateListA */
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmGetCandidateListA(imc_bad, 0, NULL, 0);
|
|
|
|
ok(ret == 0, "Bad IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmGetCandidateListA(imc_null, 0, NULL, 0);
|
|
|
|
ok(ret == 0, "NULL IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == 0xdeadbeef, "last error should remain unchanged %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmGetCandidateListA(imc_destroy, 0, NULL, 0);
|
|
|
|
ok(ret == 0, "Destroyed IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
|
|
|
|
/* Test ImmGetCandidateListCountA*/
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmGetCandidateListCountA(imc_bad,&count);
|
|
|
|
ok(ret == 0, "Bad IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmGetCandidateListCountA(imc_null,&count);
|
|
|
|
ok(ret == 0, "NULL IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == 0xdeadbeef, "last error should remain unchanged %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmGetCandidateListCountA(imc_destroy,&count);
|
|
|
|
ok(ret == 0, "Destroyed IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
|
|
|
|
/* Test ImmGetCandidateWindow */
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmGetCandidateWindow(imc_bad, 0, (LPCANDIDATEFORM)buffer);
|
|
|
|
ok(ret == 0, "Bad IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmGetCandidateWindow(imc_null, 0, (LPCANDIDATEFORM)buffer);
|
|
|
|
ok(ret == 0, "NULL IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == 0xdeadbeef, "last error should remain unchanged %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmGetCandidateWindow(imc_destroy, 0, (LPCANDIDATEFORM)buffer);
|
|
|
|
ok(ret == 0, "Destroyed IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
|
|
|
|
/* Test ImmGetCompositionFontA */
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmGetCompositionFontA(imc_bad, (LPLOGFONTA)buffer);
|
|
|
|
ok(ret == 0, "Bad IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmGetCompositionFontA(imc_null, (LPLOGFONTA)buffer);
|
|
|
|
ok(ret == 0, "NULL IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == 0xdeadbeef, "last error should remain unchanged %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmGetCompositionFontA(imc_destroy, (LPLOGFONTA)buffer);
|
|
|
|
ok(ret == 0, "Destroyed IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
|
|
|
|
/* Test ImmGetCompositionWindow */
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmGetCompositionWindow(imc_bad, (LPCOMPOSITIONFORM)buffer);
|
|
|
|
ok(ret == 0, "Bad IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmGetCompositionWindow(imc_null, (LPCOMPOSITIONFORM)buffer);
|
|
|
|
ok(ret == 0, "NULL IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == 0xdeadbeef, "last error should remain unchanged %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmGetCompositionWindow(imc_destroy, (LPCOMPOSITIONFORM)buffer);
|
|
|
|
ok(ret == 0, "Destroyed IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
|
|
|
|
/* Test ImmGetCompositionStringA */
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmGetCompositionStringA(imc_bad, GCS_COMPSTR, NULL, 0);
|
|
|
|
ok(ret == 0, "Bad IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmGetCompositionStringA(imc_null, GCS_COMPSTR, NULL, 0);
|
|
|
|
ok(ret == 0, "NULL IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == 0xdeadbeef, "last error should remain unchanged %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmGetCompositionStringA(imc_destroy, GCS_COMPSTR, NULL, 0);
|
|
|
|
ok(ret == 0, "Destroyed IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
|
|
|
|
/* Test ImmSetOpenStatus */
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmSetOpenStatus(imc_bad, 1);
|
|
|
|
ok(ret == 0, "Bad IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmSetOpenStatus(imc_null, 1);
|
|
|
|
ok(ret == 0, "NULL IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmSetOpenStatus(imc_destroy, 1);
|
|
|
|
ok(ret == 0, "Destroyed IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
|
|
|
|
/* Test ImmGetOpenStatus */
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmGetOpenStatus(imc_bad);
|
|
|
|
ok(ret == 0, "Bad IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmGetOpenStatus(imc_null);
|
|
|
|
ok(ret == 0, "NULL IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == 0xdeadbeef, "last error should remain unchanged %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmGetOpenStatus(imc_destroy);
|
|
|
|
ok(ret == 0, "Destroyed IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
|
|
|
|
/* Test ImmGetStatusWindowPos */
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmGetStatusWindowPos(imc_bad, NULL);
|
|
|
|
ok(ret == 0, "Bad IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmGetStatusWindowPos(imc_null, NULL);
|
|
|
|
ok(ret == 0, "NULL IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == 0xdeadbeef, "last error should remain unchanged %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmGetStatusWindowPos(imc_destroy, NULL);
|
|
|
|
ok(ret == 0, "Destroyed IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
|
|
|
|
/* Test ImmRequestMessageA */
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmRequestMessageA(imc_bad, WM_CHAR, 0);
|
|
|
|
ok(ret == 0, "Bad IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmRequestMessageA(imc_null, WM_CHAR, 0);
|
|
|
|
ok(ret == 0, "NULL IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmRequestMessageA(imc_destroy, WM_CHAR, 0);
|
|
|
|
ok(ret == 0, "Destroyed IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
|
|
|
|
/* Test ImmSetCompositionFontA */
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmSetCompositionFontA(imc_bad, &lf);
|
|
|
|
ok(ret == 0, "Bad IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmSetCompositionFontA(imc_null, &lf);
|
|
|
|
ok(ret == 0, "NULL IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmSetCompositionFontA(imc_destroy, &lf);
|
|
|
|
ok(ret == 0, "Destroyed IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
|
|
|
|
/* Test ImmSetCompositionWindow */
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmSetCompositionWindow(imc_bad, NULL);
|
|
|
|
ok(ret == 0, "Bad IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmSetCompositionWindow(imc_null, NULL);
|
|
|
|
ok(ret == 0, "NULL IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmSetCompositionWindow(imc_destroy, NULL);
|
|
|
|
ok(ret == 0, "Destroyed IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
|
|
|
|
/* Test ImmSetConversionStatus */
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmSetConversionStatus(imc_bad, 0, 0);
|
|
|
|
ok(ret == 0, "Bad IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmSetConversionStatus(imc_null, 0, 0);
|
|
|
|
ok(ret == 0, "NULL IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmSetConversionStatus(imc_destroy, 0, 0);
|
|
|
|
ok(ret == 0, "Destroyed IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
|
|
|
|
/* Test ImmSetStatusWindowPos */
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmSetStatusWindowPos(imc_bad, 0);
|
|
|
|
ok(ret == 0, "Bad IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmSetStatusWindowPos(imc_null, 0);
|
|
|
|
ok(ret == 0, "NULL IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmSetStatusWindowPos(imc_destroy, 0);
|
|
|
|
ok(ret == 0, "Destroyed IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
|
|
|
|
/* Test ImmGetImeMenuItemsA */
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmGetImeMenuItemsA(imc_bad, 0, 0, NULL, NULL, 0);
|
|
|
|
ok(ret == 0, "Bad IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmGetImeMenuItemsA(imc_null, 0, 0, NULL, NULL, 0);
|
|
|
|
ok(ret == 0, "NULL IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmGetImeMenuItemsA(imc_destroy, 0, 0, NULL, NULL, 0);
|
|
|
|
ok(ret == 0, "Destroyed IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
|
|
|
|
/* Test ImmLockIMC */
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ic = ImmLockIMC(imc_bad);
|
|
|
|
ok(ic == 0, "Bad IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ic = ImmLockIMC(imc_null);
|
|
|
|
ok(ic == 0, "NULL IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == 0xdeadbeef, "last error should remain unchanged %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ic = ImmLockIMC(imc_destroy);
|
|
|
|
ok(ic == 0, "Destroyed IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
|
|
|
|
/* Test ImmUnlockIMC */
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmUnlockIMC(imc_bad);
|
|
|
|
ok(ret == 0, "Bad IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmUnlockIMC(imc_null);
|
|
|
|
ok(ret == 0, "NULL IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == 0xdeadbeef, "last error should remain unchanged %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmUnlockIMC(imc_destroy);
|
|
|
|
ok(ret == 0, "Destroyed IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
|
|
|
|
/* Test ImmGenerateMessage */
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmGenerateMessage(imc_bad);
|
|
|
|
ok(ret == 0, "Bad IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmGenerateMessage(imc_null);
|
|
|
|
ok(ret == 0, "NULL IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
ret = ImmGenerateMessage(imc_destroy);
|
|
|
|
ok(ret == 0, "Destroyed IME should return 0\n");
|
|
|
|
ret = GetLastError();
|
|
|
|
ok(ret == ERROR_INVALID_HANDLE, "wrong last error %08x!\n", ret);
|
|
|
|
}
|
|
|
|
|
2008-04-04 16:43:16 +00:00
|
|
|
START_TEST(imm32) {
|
|
|
|
if (init())
|
2009-05-17 07:05:22 +00:00
|
|
|
{
|
2008-04-04 16:43:16 +00:00
|
|
|
test_ImmNotifyIME();
|
2009-05-17 07:05:22 +00:00
|
|
|
test_ImmGetCompositionString();
|
|
|
|
test_ImmSetCompositionString();
|
|
|
|
test_ImmIME();
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
test_ImmAssociateContextEx();
|
2011-12-15 00:39:37 +00:00
|
|
|
test_ImmThreads();
|
|
|
|
test_ImmIsUIMessage();
|
|
|
|
test_ImmGetContext();
|
2012-03-15 21:45:07 +00:00
|
|
|
test_ImmGetDescription();
|
2013-02-03 20:58:19 +00:00
|
|
|
test_ImmDefaultHwnd();
|
2016-08-18 10:08:05 +00:00
|
|
|
test_default_ime_window_creation();
|
2013-12-01 15:57:54 +00:00
|
|
|
test_ImmGetIMCLockCount();
|
|
|
|
test_ImmGetIMCCLockCount();
|
|
|
|
test_ImmDestroyContext();
|
|
|
|
test_ImmDestroyIMCC();
|
2014-04-30 12:16:47 +00:00
|
|
|
test_InvalidIMC();
|
2013-02-03 20:58:19 +00:00
|
|
|
msg_spy_cleanup();
|
|
|
|
/* Reinitialize the hooks to capture all windows */
|
|
|
|
msg_spy_init(NULL);
|
|
|
|
test_ImmMessages();
|
|
|
|
msg_spy_cleanup();
|
2013-12-01 15:57:54 +00:00
|
|
|
if (pSendInput)
|
|
|
|
test_ime_processkey();
|
|
|
|
else win_skip("SendInput is not available\n");
|
2009-05-17 07:05:22 +00:00
|
|
|
}
|
2008-04-04 16:43:16 +00:00
|
|
|
cleanup();
|
|
|
|
}
|