#include <winnls.h>
#include <winreg.h>
#include <wine/list.h>
+#include <wine/unicode.h>
WINE_DEFAULT_DEBUG_CHANNEL(imm);
ImmHkl *immKbd;
UINT lastVK;
+ DWORD magic;
} InputContextData;
+#define WINE_IMC_VALID_MAGIC 0x56434D49
+
typedef struct _tagTRANSMSG {
UINT message;
WPARAM wParam;
}
}
-static HMODULE LoadDefaultWineIME(void)
+static HMODULE load_graphics_driver(void)
{
- char buffer[MAX_PATH], libname[32], *name, *next;
- HMODULE module = 0;
- HKEY hkey;
-
- TRACE("Attempting to fall back to wine default IME\n");
-
- strcpy( buffer, "x11" ); /* default value */
- /* @@ Wine registry key: HKCU\Software\Wine\Drivers */
- if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Drivers", &hkey ))
- {
- DWORD type, count = sizeof(buffer);
- RegQueryValueExA( hkey, "Ime", 0, &type, (LPBYTE) buffer, &count );
- RegCloseKey( hkey );
- }
-
- name = buffer;
- while (name)
- {
- next = strchr( name, ',' );
- if (next) *next++ = 0;
+ static const WCHAR display_device_guid_propW[] = {
+ '_','_','w','i','n','e','_','d','i','s','p','l','a','y','_',
+ 'd','e','v','i','c','e','_','g','u','i','d',0 };
+ static const WCHAR key_pathW[] = {
+ 'S','y','s','t','e','m','\\',
+ 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
+ 'C','o','n','t','r','o','l','\\',
+ 'V','i','d','e','o','\\','{',0};
+ static const WCHAR displayW[] = {'}','\\','0','0','0','0',0};
+ static const WCHAR driverW[] = {'G','r','a','p','h','i','c','s','D','r','i','v','e','r',0};
- snprintf( libname, sizeof(libname), "wine%s.drv", name );
- if ((module = LoadLibraryA( libname )) != 0) break;
- name = next;
- }
-
- return module;
+ HMODULE ret = 0;
+ HKEY hkey;
+ DWORD size;
+ WCHAR path[MAX_PATH];
+ WCHAR key[(sizeof(key_pathW) + sizeof(displayW)) / sizeof(WCHAR) + 40];
+ UINT guid_atom = HandleToULong( GetPropW( GetDesktopWindow(), display_device_guid_propW ));
+
+ if (!guid_atom) return 0;
+ memcpy( key, key_pathW, sizeof(key_pathW) );
+ if (!GlobalGetAtomNameW( guid_atom, key + strlenW(key), 40 )) return 0;
+ strcatW( key, displayW );
+ if (RegOpenKeyW( HKEY_LOCAL_MACHINE, key, &hkey )) return 0;
+ size = sizeof(path);
+ if (!RegQueryValueExW( hkey, driverW, NULL, NULL, (BYTE *)path, &size )) ret = LoadLibraryW( path );
+ RegCloseKey( hkey );
+ TRACE( "%s %p\n", debugstr_w(path), ret );
+ return ret;
}
/* ImmHkl loading and freeing */
ptr->hkl = hkl;
if (ImmGetIMEFileNameW(hkl, filename, MAX_PATH)) ptr->hIME = LoadLibraryW(filename);
- if (!ptr->hIME)
- ptr->hIME = LoadDefaultWineIME();
+ if (!ptr->hIME) ptr->hIME = load_graphics_driver();
if (ptr->hIME)
{
LOAD_FUNCPTR(ImeInquire);
return rc;
}
+static InputContextData* get_imc_data(HIMC hIMC)
+{
+ InputContextData *data = hIMC;
+
+ if (hIMC == NULL)
+ return NULL;
+
+ if(IsBadReadPtr(data, sizeof(InputContextData)) || data->magic != WINE_IMC_VALID_MAGIC)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return NULL;
+ }
+ return data;
+}
+
/***********************************************************************
* ImmAssociateContext (IMM32.@)
*/
HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC)
{
HIMC old = NULL;
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("(%p, %p):\n", hWnd, hIMC);
+ if(hIMC && !data)
+ return NULL;
+
if (!IMM_GetThreadData()->defaultContext)
IMM_GetThreadData()->defaultContext = ImmCreateContext();
InputContextData *new_context;
LPGUIDELINE gl;
LPCANDIDATEINFO ci;
+ int i;
new_context = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputContextData));
gl->dwSize = sizeof(GUIDELINE);
ImmUnlockIMCC(new_context->IMC.hGuideLine);
+ for (i = 0; i < sizeof(new_context->IMC.cfCandForm) / sizeof(CANDIDATEFORM); i++)
+ new_context->IMC.cfCandForm[i].dwIndex = ~0u;
+
/* Initialize the IME Private */
new_context->IMC.hPrivate = ImmCreateIMCC(new_context->immKbd->imeInfo.dwPrivateDataSize);
+ new_context->IMC.fdwConversion = new_context->immKbd->imeInfo.fdwConversionCaps;
+ new_context->IMC.fdwSentence = new_context->immKbd->imeInfo.fdwSentenceCaps;
+
if (!new_context->immKbd->pImeSelect(new_context, TRUE))
{
TRACE("Selection of IME failed\n");
new_context->immKbd->uSelected++;
TRACE("Created context %p\n",new_context);
+ new_context->magic = WINE_IMC_VALID_MAGIC;
return new_context;
}
static BOOL IMM_DestroyContext(HIMC hIMC)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("Destroying %p\n",hIMC);
- if (hIMC)
- {
- data->immKbd->uSelected --;
- data->immKbd->pImeSelect(hIMC, FALSE);
- SendMessageW(data->IMC.hWnd, WM_IME_SELECT, FALSE, (LPARAM)GetKeyboardLayout(0));
+ if (!data)
+ return FALSE;
- ImmDestroyIMCC(data->IMC.hCompStr);
- ImmDestroyIMCC(data->IMC.hCandInfo);
- ImmDestroyIMCC(data->IMC.hGuideLine);
- ImmDestroyIMCC(data->IMC.hPrivate);
- ImmDestroyIMCC(data->IMC.hMsgBuf);
+ data->immKbd->uSelected --;
+ data->immKbd->pImeSelect(hIMC, FALSE);
+ SendMessageW(data->IMC.hWnd, WM_IME_SELECT, FALSE, (LPARAM)GetKeyboardLayout(0));
+
+ ImmDestroyIMCC(data->IMC.hCompStr);
+ ImmDestroyIMCC(data->IMC.hCandInfo);
+ ImmDestroyIMCC(data->IMC.hGuideLine);
+ ImmDestroyIMCC(data->IMC.hPrivate);
+ ImmDestroyIMCC(data->IMC.hMsgBuf);
+
+ data->magic = 0;
+ HeapFree(GetProcessHeap(),0,data);
- HeapFree(GetProcessHeap(),0,data);
- }
return TRUE;
}
HIMC hIMC, DWORD dwIndex,
LPCANDIDATELIST lpCandList, DWORD dwBufLen)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
LPCANDIDATEINFO candinfo;
LPCANDIDATELIST candlist;
DWORD ret = 0;
DWORD WINAPI ImmGetCandidateListCountA(
HIMC hIMC, LPDWORD lpdwListCount)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
LPCANDIDATEINFO candinfo;
DWORD ret, count;
DWORD WINAPI ImmGetCandidateListCountW(
HIMC hIMC, LPDWORD lpdwListCount)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
LPCANDIDATEINFO candinfo;
DWORD ret, count;
HIMC hIMC, DWORD dwIndex,
LPCANDIDATELIST lpCandList, DWORD dwBufLen)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
LPCANDIDATEINFO candinfo;
LPCANDIDATELIST candlist;
DWORD ret = 0;
BOOL WINAPI ImmGetCandidateWindow(
HIMC hIMC, DWORD dwIndex, LPCANDIDATEFORM lpCandidate)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("%p, %d, %p\n", hIMC, dwIndex, lpCandidate);
if ( dwIndex >= (sizeof(data->IMC.cfCandForm) / sizeof(CANDIDATEFORM)) )
return FALSE;
+ if (data->IMC.cfCandForm[dwIndex].dwIndex != dwIndex)
+ return FALSE;
+
*lpCandidate = data->IMC.cfCandForm[dwIndex];
return TRUE;
*/
BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("(%p, %p):\n", hIMC, lplf);
DWORD dwBufLen, BOOL unicode)
{
LONG rc = 0;
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
LPCOMPOSITIONSTRING compstr;
LPBYTE compdata;
*/
BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("(%p, %p)\n", hIMC, lpCompForm);
return FALSE;
*lpCompForm = data->IMC.cfCompForm;
- return 1;
+ return TRUE;
}
/***********************************************************************
BOOL WINAPI ImmGetConversionStatus(
HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("%p %p %p\n", hIMC, lpfdwConversion, lpfdwSentence);
/* find out how many characters in the unicode buffer */
len = ImmGetDescriptionW( hKL, NULL, 0 );
+ if (!len)
+ return 0;
/* allocate a buffer of that size */
buf = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof (WCHAR) );
HeapFree( GetProcessHeap(), 0, buf );
- return len;
+ if (len == 0)
+ return 0;
+
+ return len - 1;
}
/***********************************************************************
FIXME("(%p, %p, %d): semi stub\n", hKL, lpszDescription, uBufLen);
+ if (!hKL) return 0;
if (!uBufLen) return lstrlenW( name );
lstrcpynW( lpszDescription, name, uBufLen );
return lstrlenW( lpszDescription );
*/
BOOL WINAPI ImmGetOpenStatus(HIMC hIMC)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
static int i;
if (!data)
*/
BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("(%p, %p)\n", hIMC, lpptPos);
BOOL WINAPI ImmNotifyIME(
HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("(%p, %d, %d, %d)\n",
hIMC, dwAction, dwIndex, dwValue);
+ if (hIMC == NULL)
+ {
+ SetLastError(ERROR_SUCCESS);
+ return FALSE;
+ }
+
if (!data || ! data->immKbd->pNotifyIME)
+ {
return FALSE;
+ }
return data->immKbd->pNotifyIME(hIMC,dwAction,dwIndex,dwValue);
}
*/
BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
{
- static int shown = 0;
+ static BOOL shown = FALSE;
if (!shown) {
FIXME("(%p, %p): stub\n", hWnd, hIMC);
- shown = 1;
+ shown = TRUE;
}
return TRUE;
}
*/
LRESULT WINAPI ImmRequestMessageA(HIMC hIMC, WPARAM wParam, LPARAM lParam)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
+ if (!data)
+ SetLastError(ERROR_INVALID_HANDLE);
if (data && IsWindow(data->IMC.hWnd))
return SendMessageA(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
*/
LRESULT WINAPI ImmRequestMessageW(HIMC hIMC, WPARAM wParam, LPARAM lParam)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
+ if (!data)
+ SetLastError(ERROR_INVALID_HANDLE);
+
if (data && IsWindow(data->IMC.hWnd))
return SendMessageW(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
BOOL WINAPI ImmSetCandidateWindow(
HIMC hIMC, LPCANDIDATEFORM lpCandidate)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("(%p, %p)\n", hIMC, lpCandidate);
*/
BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("(%p, %p)\n", hIMC, lplf);
if (!data || !lplf)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
+ }
memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTA));
MultiByteToWideChar(CP_ACP, 0, lplf->lfFaceName, -1, data->IMC.lfFont.W.lfFaceName,
*/
BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("(%p, %p)\n", hIMC, lplf);
if (!data || !lplf)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
+ }
data->IMC.lfFont.W = *lplf;
ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT);
WCHAR *CompBuffer = NULL;
WCHAR *ReadBuffer = NULL;
BOOL rc;
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("(%p, %d, %p, %d, %p, %d):\n",
hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
CHAR *CompBuffer = NULL;
CHAR *ReadBuffer = NULL;
BOOL rc;
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("(%p, %d, %p, %d, %p, %d):\n",
hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
{
BOOL reshow = FALSE;
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("(%p, %p)\n", hIMC, lpCompForm);
TRACE("\t%x, (%i,%i), (%i,%i - %i,%i)\n",lpCompForm->dwStyle,
lpCompForm->rcArea.left, lpCompForm->rcArea.bottom, lpCompForm->rcArea.right);
if (!data)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
+ }
data->IMC.cfCompForm = *lpCompForm;
HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence)
{
DWORD oldConversion, oldSentence;
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("%p %d %d\n", hIMC, fdwConversion, fdwSentence);
if (!data)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
+ }
if ( fdwConversion != data->IMC.fdwConversion )
{
*/
BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("%p %d\n", hIMC, fOpen);
if (!data)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
+ }
if (data->immKbd->UIWnd == NULL)
{
*/
BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("(%p, %p)\n", hIMC, lpptPos);
if (!data || !lpptPos)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
+ }
TRACE("\t(%i,%i)\n", lpptPos->x, lpptPos->y);
LPIMEMENUITEMINFOA lpImeParentMenu, LPIMEMENUITEMINFOA lpImeMenu,
DWORD dwSize)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
lpImeParentMenu, lpImeMenu, dwSize);
+
+ if (!data)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return 0;
+ }
+
if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
{
if (!is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu,
DWORD dwSize)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
lpImeParentMenu, lpImeMenu, dwSize);
+
+ if (!data)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return 0;
+ }
+
if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
{
if (is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
*/
LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
if (!data)
return NULL;
*/
BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
+
+ if (!data)
+ return FALSE;
if (data->dwLock)
data->dwLock--;
return TRUE;
*/
DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
+ if (!data)
+ return 0;
return data->dwLock;
}
*/
BOOL WINAPI ImmGenerateMessage(HIMC hIMC)
{
- InputContextData *data = hIMC;
+ InputContextData *data = get_imc_data(hIMC);
+
+ if (!data)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
TRACE("%i messages queued\n",data->IMC.dwNumMsgBuf);
if (data->IMC.dwNumMsgBuf > 0)