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
);