4 * Copyright 2000 Hidenori Takeshima
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(imm);
36 #include "imm_private.h"
38 static const char IMM32_szRegKL[] =
39 "System\\CurrentControlSet\\Control\\keyboard layouts";
40 static const char IMM32_szIME_File[] = "IME file";
41 static const char IMM32_szLayout_File[] = "layout file";
43 static IMM32_IMEKL* IMM32_pklFirst = NULL;
46 static LONG IMM32_RegOpenKey( HKL hkl, PHKEY phkRet )
48 CHAR szRegPath[ sizeof(IMM32_szRegKL)+16 ];
50 wsprintfA( szRegPath, "%s\\%08x", IMM32_szRegKL, (unsigned)hkl );
51 return RegOpenKeyExA( HKEY_LOCAL_MACHINE, szRegPath,
52 0, KEY_READ, phkRet );
55 static LONG IMM32_RegCreateKey( HKL hkl, PHKEY phkRet,
56 LPDWORD lpdwDisposition )
58 CHAR szRegPath[ sizeof(IMM32_szRegKL)+16 ];
60 wsprintfA( szRegPath, "%s\\%08x", IMM32_szRegKL, (unsigned)hkl );
61 return RegCreateKeyExA( HKEY_LOCAL_MACHINE, szRegPath,
63 REG_OPTION_NON_VOLATILE,
65 phkRet, lpdwDisposition );
68 static DWORD IMM32_GetIMEFileName( HKL hkl, LPSTR lpBuf, INT nBufLen )
74 CHAR szValueName[ sizeof(IMM32_szIME_File) ];
76 TRACE( "hkl = %08x\n", (unsigned)hkl );
78 nError = IMM32_RegOpenKey( hkl, &hkey );
79 if ( nError != ERROR_SUCCESS )
81 SetLastError( nError );
84 memcpy( szValueName, IMM32_szIME_File, sizeof(IMM32_szIME_File) );
86 nError = RegQueryValueExA( hkey, szValueName, NULL,
87 &dwType, NULL, &cbData );
88 if ( nError == ERROR_SUCCESS && dwType != REG_SZ )
89 nError = ERROR_FILE_NOT_FOUND; /* FIXME? */
90 if ( nError == ERROR_SUCCESS && lpBuf != NULL && nBufLen != 0 )
92 if ( nBufLen < (INT)cbData )
93 nError = ERROR_INSUFFICIENT_BUFFER;
95 nError = RegQueryValueExA( hkey, szValueName, NULL,
96 &dwType, lpBuf, &cbData );
101 if ( nError != ERROR_SUCCESS )
103 SetLastError( nError );
112 BOOL IMM32_GetIMEHandlersA( HINSTANCE hInstIME,
113 struct IMM32_IME_EXPORTED_HANDLERS* phandlers )
118 phandlers->p##name = (IMM32_p##name) \
119 GetProcAddress(hInstIME,#name); \
120 if ( phandlers->p##name == NULL ) fError = TRUE;
122 phandlers->p##name.A = (IMM32_p##name##A) \
123 GetProcAddress(hInstIME,#name); \
124 if ( phandlers->p##name.A == NULL ) fError = TRUE;
130 FE_(ImeConversionList)
132 FE_(ImeEnumRegisterWord)
133 FE_(ImeGetRegisterWordStyle)
138 FE(ImeSetActiveContext)
139 FE_(ImeSetCompositionString)
141 FE_(ImeUnregisterWord)
147 FE_(ImeGetImeMenuItems)
156 BOOL IMM32_GetIMEHandlersW( HINSTANCE hInstIME,
157 struct IMM32_IME_EXPORTED_HANDLERS* phandlers )
162 phandlers->p##name = (IMM32_p##name) \
163 GetProcAddress(hInstIME,#name); \
164 if ( phandlers->p##name == NULL ) fError = TRUE;
166 phandlers->p##name.W = (IMM32_p##name##W) \
167 GetProcAddress(hInstIME,#name); \
168 if ( phandlers->p##name.W == NULL ) fError = TRUE;
174 FE_(ImeConversionList)
176 FE_(ImeEnumRegisterWord)
177 FE_(ImeGetRegisterWordStyle)
182 FE(ImeSetActiveContext)
183 FE_(ImeSetCompositionString)
185 FE_(ImeUnregisterWord)
191 FE_(ImeGetImeMenuItems)
200 static IMM32_IMEKL* IMM32_LoadIME( HKL hkl )
202 IMM32_IMEKL* pkl = NULL;
203 BOOL fInitialized = FALSE;
204 CHAR* pszFileName = NULL;
206 IMM32_pImeInquireA pImeInquire;
207 IMM32_pImeDestroy pImeDestroy = NULL;
208 CHAR szUIClassName[ (IMM32_UICLASSNAME_MAX+1)*sizeof(WCHAR) ];
210 dwBufLen = IMM32_GetIMEFileName( hkl, NULL, 0 );
213 pszFileName = (CHAR*)IMM32_HeapAlloc( 0, sizeof(CHAR)*(dwBufLen+1) );
214 if ( pszFileName == NULL )
216 SetLastError( ERROR_OUTOFMEMORY );
219 if ( !IMM32_GetIMEFileName( hkl, pszFileName, dwBufLen + 1 ) )
223 IMM32_HeapAlloc( HEAP_ZERO_MEMORY, sizeof(IMM32_IMEKL) );
226 SetLastError( ERROR_OUTOFMEMORY );
232 pkl->hInstIME = LoadLibraryA( pszFileName );
233 if ( pkl->hInstIME == (HINSTANCE)NULL )
236 pImeInquire = (IMM32_pImeInquireA)GetProcAddress
237 ( pkl->hInstIME, "ImeInquire" );
238 pImeDestroy = (IMM32_pImeDestroy)GetProcAddress
239 ( pkl->hInstIME, "ImeDestroy" );
240 if ( pImeInquire == NULL || pImeDestroy == NULL )
243 if ( !pImeInquire( &(pkl->imeinfo), szUIClassName, NULL ) )
245 SetLastError( ERROR_DLL_INIT_FAILED ); /* FIXME? */
250 /* FIXME: Is this correct??? */
251 if ( pkl->imeinfo.fdwProperty & IME_PROP_UNICODE )
252 pkl->fUnicode = TRUE;
254 pkl->fUnicode = FALSE;
258 if ( !IMM32_GetIMEHandlersW( pkl->hInstIME, &pkl->handlers ) )
260 memcpy( pkl->UIClassName.W, szUIClassName,
261 IMM32_UICLASSNAME_MAX*sizeof(WCHAR) );
262 TRACE( "UI class name(Unicode): %s\n",
263 debugstr_w(pkl->UIClassName.W) );
267 if ( !IMM32_GetIMEHandlersA( pkl->hInstIME, &pkl->handlers ) )
269 memcpy( pkl->UIClassName.A, szUIClassName,
270 IMM32_UICLASSNAME_MAX*sizeof(CHAR) );
271 TRACE( "UI class name(ASCII): %s\n",
272 debugstr_a(pkl->UIClassName.A) );
275 /* The IME is loaded successfully. */
276 pkl->pszIMEFileName = pszFileName; pszFileName = NULL;
280 IMM32_HeapFree( pszFileName );
283 if ( pkl->hInstIME != (HINSTANCE)NULL )
286 (void)pImeDestroy(0);
287 FreeLibrary( pkl->hInstIME );
289 IMM32_HeapFree( pkl );
296 const IMM32_IMEKL* IMM32_GetIME( HKL hkl )
302 pkl = IMM32_pklFirst;
303 while ( pkl != NULL )
305 if ( pkl->hkl == hkl )
310 pkl = IMM32_LoadIME( hkl );
313 pkl->pNext = IMM32_pklFirst;
314 IMM32_pklFirst = pkl;
323 void IMM32_UnloadAllIMEs( void )
326 IMM32_IMEKL* pklNext;
330 pkl = IMM32_pklFirst;
331 while ( pkl != NULL )
333 TRACE( "hkl = %08x\n", (unsigned)pkl->hkl );
335 pklNext = pkl->pNext;
336 (void)pkl->handlers.pImeDestroy(0);
337 FreeLibrary( pkl->hInstIME );
338 IMM32_HeapFree( pkl->pszIMEFileName );
339 IMM32_HeapFree( pkl );
342 IMM32_pklFirst = NULL;
349 /***********************************************************************
350 * ImmInstallIMEA (IMM32.@)
352 HKL WINAPI ImmInstallIMEA(
353 LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
362 CHAR szValueName[ sizeof(IMM32_szIME_File) ];
365 debugstr_a(lpszIMEFileName), debugstr_a(lpszLayoutText) );
367 dwLCID = (DWORD)GetThreadLocale();
370 FIXME( "IMEs don't work correctly now since\n"
371 "wine/windows/input.c doesn't handle HKL correctly.\n" );
375 hkl = (HKL)(((0xe000|dwTryCount)<<16) | (dwLCID));
377 nError = IMM32_RegCreateKey( hkl, &hkey, &dwDisposition );
378 if ( nError != ERROR_SUCCESS )
381 memcpy( szValueName, IMM32_szIME_File,
382 sizeof(IMM32_szIME_File) );
384 nError = RegQueryValueExA( hkey, szValueName, NULL,
385 NULL, NULL, &cbData );
386 if ( nError == ERROR_SUCCESS && cbData > 0 )
390 /* try to assign an other HKL. */
392 if ( dwTryCount >= 0x100 )
394 nError = ERROR_ACCESS_DENIED; /* FIXME */
400 nError = RegSetValueExA( hkey, IMM32_szIME_File, 0,
401 REG_SZ, lpszIMEFileName,
402 strlen(lpszIMEFileName)+1 );
403 if ( nError == ERROR_SUCCESS )
404 nError = RegSetValueExA( hkey, IMM32_szLayout_File, 0,
405 REG_SZ, lpszLayoutText,
406 strlen(lpszLayoutText)+1 );
411 if ( nError != ERROR_SUCCESS )
413 SetLastError( nError );
420 /***********************************************************************
421 * ImmInstallIMEW (IMM32.@)
423 HKL WINAPI ImmInstallIMEW(
424 LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
431 debugstr_w(lpszIMEFileName), debugstr_w(lpszLayoutText) );
433 lpszParam1 = IMM32_strdupWtoA( lpszIMEFileName );
434 lpszParam2 = IMM32_strdupWtoA( lpszLayoutText );
435 if ( ( lpszParam1 == NULL ) || ( lpszParam2 == NULL ) )
437 SetLastError( ERROR_OUTOFMEMORY );
442 hkl = ImmInstallIMEA( lpszParam1, lpszParam2 );
444 IMM32_HeapFree( lpszParam1 );
445 IMM32_HeapFree( lpszParam2 );
451 /***********************************************************************
454 BOOL WINAPI ImmIsIME(HKL hkl)
456 const IMM32_IMEKL* pkl;
458 TRACE("(0x%08x)\n", hkl);
460 pkl = IMM32_GetIME( hkl );
468 /***********************************************************************
469 * ImmGetIMEFileNameA (IMM32.@)
471 UINT WINAPI ImmGetIMEFileNameA(HKL hkl, LPSTR lpszFileName, UINT uBufLen)
473 const IMM32_IMEKL* pkl;
474 UINT uIMEFileNameLen;
476 TRACE("(%08x,%p,%u)\n",hkl,lpszFileName,uBufLen);
478 pkl = IMM32_GetIME( hkl );
482 uIMEFileNameLen = strlen(pkl->pszIMEFileName);
484 return uIMEFileNameLen;
485 if ( uBufLen <= uIMEFileNameLen )
487 SetLastError(ERROR_INSUFFICIENT_BUFFER);
490 memcpy( lpszFileName, pkl->pszIMEFileName,
491 sizeof(CHAR)*(uIMEFileNameLen+1) );
493 return uIMEFileNameLen;
496 /***********************************************************************
497 * ImmGetIMEFileNameW (IMM32.@)
499 UINT WINAPI ImmGetIMEFileNameW(HKL hkl, LPWSTR lpszFileName, UINT uBufLen)
501 const IMM32_IMEKL* pkl;
502 UINT uIMEFileNameLen;
504 TRACE("(%08x,%p,%u)\n",hkl,lpszFileName,uBufLen);
506 pkl = IMM32_GetIME( hkl );
510 uIMEFileNameLen = IMM32_strlenAtoW(pkl->pszIMEFileName);
512 return uIMEFileNameLen;
513 if ( uBufLen <= uIMEFileNameLen )
515 SetLastError(ERROR_INSUFFICIENT_BUFFER);
518 IMM32_strncpyAtoW( lpszFileName, pkl->pszIMEFileName, uBufLen );
520 return uIMEFileNameLen;
523 /***********************************************************************
524 * ImmGetProperty (IMM32.@)
526 DWORD WINAPI ImmGetProperty(HKL hkl, DWORD fdwIndex)
528 const IMM32_IMEKL* pkl;
531 TRACE("(0x%08x, %ld)\n", hkl, fdwIndex);
533 pkl = IMM32_GetIME( hkl );
539 case IGP_GETIMEVERSION:
543 dwRet = pkl->imeinfo.fdwProperty;
546 dwRet = pkl->imeinfo.fdwConversionCaps;
549 dwRet = pkl->imeinfo.fdwSentenceCaps;
552 dwRet = pkl->imeinfo.fdwUICaps;
555 dwRet = pkl->imeinfo.fdwSCSCaps;
558 dwRet = pkl->imeinfo.fdwSelectCaps;
561 FIXME("(0x%08x, %ld): invalid/unknown property.\n",
563 SetLastError( ERROR_INVALID_PARAMETER );
571 /***********************************************************************
572 * ImmEnumRegisterWordA (IMM32.@)
574 UINT WINAPI ImmEnumRegisterWordA(
575 HKL hkl, REGISTERWORDENUMPROCA lpfnEnumProc,
576 LPCSTR lpszReading, DWORD dwStyle,
577 LPCSTR lpszRegister, LPVOID lpData)
579 const IMM32_IMEKL* pkl;
581 TRACE("(0x%08x, %p, %s, %ld, %s, %p)\n",
583 debugstr_a(lpszReading), dwStyle,
584 debugstr_a(lpszRegister), lpData);
586 pkl = IMM32_GetIME( hkl );
592 FIXME( "please implement UNICODE->ANSI\n" );
593 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
598 return pkl->handlers.pImeEnumRegisterWord.A
599 ( lpfnEnumProc, lpszReading, dwStyle,
600 lpszRegister, lpData );
604 /***********************************************************************
605 * ImmEnumRegisterWordW (IMM32.@)
607 UINT WINAPI ImmEnumRegisterWordW(
608 HKL hkl, REGISTERWORDENUMPROCW lpfnEnumProc,
609 LPCWSTR lpszReading, DWORD dwStyle,
610 LPCWSTR lpszRegister, LPVOID lpData)
612 const IMM32_IMEKL* pkl;
614 TRACE("(0x%08x, %p, %s, %ld, %s, %p): stub\n",
616 debugstr_w(lpszReading), dwStyle,
617 debugstr_w(lpszRegister), lpData);
619 pkl = IMM32_GetIME( hkl );
625 return pkl->handlers.pImeEnumRegisterWord.W
626 ( lpfnEnumProc, lpszReading, dwStyle,
627 lpszRegister, lpData );
631 FIXME( "please implement ANSI->UNICODE\n" );
632 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
638 /***********************************************************************
639 * ImmGetRegisterWordStyleA (IMM32.@)
641 UINT WINAPI ImmGetRegisterWordStyleA(
642 HKL hkl, UINT nItem, LPSTYLEBUFA lpStyleBuf)
644 const IMM32_IMEKL* pkl;
646 TRACE("(0x%08x, %d, %p)\n", hkl, nItem, lpStyleBuf);
648 pkl = IMM32_GetIME( hkl );
654 FIXME( "please implement UNICODE->ANSI\n" );
655 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
660 return pkl->handlers.pImeGetRegisterWordStyle.A
661 ( nItem, lpStyleBuf );
665 /***********************************************************************
666 * ImmGetRegisterWordStyleW (IMM32.@)
668 UINT WINAPI ImmGetRegisterWordStyleW(
669 HKL hkl, UINT nItem, LPSTYLEBUFW lpStyleBuf)
671 const IMM32_IMEKL* pkl;
673 TRACE("(0x%08x, %d, %p)\n", hkl, nItem, lpStyleBuf);
675 pkl = IMM32_GetIME( hkl );
681 return pkl->handlers.pImeGetRegisterWordStyle.W
682 ( nItem, lpStyleBuf );
686 FIXME( "please implement ANSI->UNICODE\n" );
687 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);