4 * Copyright 2000 Hidenori Takeshima
19 #include "debugtools.h"
20 DEFAULT_DEBUG_CHANNEL(imm);
22 #include "imm_private.h"
24 static const char IMM32_szRegKL[] =
25 "System\\CurrentControlSet\\Control\\keyboard layouts";
26 static const char IMM32_szIME_File[] = "IME file";
27 static const char IMM32_szLayout_File[] = "layout file";
29 static IMM32_IMEKL* IMM32_pklFirst = NULL;
32 static LONG IMM32_RegOpenKey( HKL hkl, PHKEY phkRet )
34 CHAR szRegPath[ sizeof(IMM32_szRegKL)+16 ];
36 wsprintfA( szRegPath, "%s\\%08x", IMM32_szRegKL, (unsigned)hkl );
37 return RegOpenKeyExA( HKEY_LOCAL_MACHINE, szRegPath,
38 0, KEY_READ, phkRet );
41 static LONG IMM32_RegCreateKey( HKL hkl, PHKEY phkRet,
42 LPDWORD lpdwDisposition )
44 CHAR szRegPath[ sizeof(IMM32_szRegKL)+16 ];
46 wsprintfA( szRegPath, "%s\\%08x", IMM32_szRegKL, (unsigned)hkl );
47 return RegCreateKeyExA( HKEY_LOCAL_MACHINE, szRegPath,
49 REG_OPTION_NON_VOLATILE,
51 phkRet, lpdwDisposition );
54 static DWORD IMM32_GetIMEFileName( HKL hkl, LPSTR lpBuf, INT nBufLen )
60 CHAR szValueName[ sizeof(IMM32_szIME_File) ];
62 TRACE( "hkl = %08x\n", (unsigned)hkl );
64 nError = IMM32_RegOpenKey( hkl, &hkey );
65 if ( nError != ERROR_SUCCESS )
67 SetLastError( nError );
70 memcpy( szValueName, IMM32_szIME_File, sizeof(IMM32_szIME_File) );
72 nError = RegQueryValueExA( hkey, szValueName, NULL,
73 &dwType, NULL, &cbData );
74 if ( nError == ERROR_SUCCESS && dwType != REG_SZ )
75 nError = ERROR_FILE_NOT_FOUND; /* FIXME? */
76 if ( nError == ERROR_SUCCESS && lpBuf != NULL && nBufLen != 0 )
78 if ( nBufLen < (INT)cbData )
79 nError = ERROR_INSUFFICIENT_BUFFER;
81 nError = RegQueryValueExA( hkey, szValueName, NULL,
82 &dwType, lpBuf, &cbData );
87 if ( nError != ERROR_SUCCESS )
89 SetLastError( nError );
98 BOOL IMM32_GetIMEHandlersA( HINSTANCE hInstIME,
99 struct IMM32_IME_EXPORTED_HANDLERS* phandlers )
104 phandlers->p##name = (IMM32_p##name) \
105 GetProcAddress(hInstIME,#name); \
106 if ( phandlers->p##name == NULL ) fError = TRUE;
108 phandlers->p##name.A = (IMM32_p##name##A) \
109 GetProcAddress(hInstIME,#name); \
110 if ( phandlers->p##name.A == NULL ) fError = TRUE;
116 FE_(ImeConversionList)
118 FE_(ImeEnumRegisterWord)
119 FE_(ImeGetRegisterWordStyle)
124 FE(ImeSetActiveContext)
125 FE_(ImeSetCompositionString)
127 FE_(ImeUnregisterWord)
133 FE_(ImeGetImeMenuItems)
142 BOOL IMM32_GetIMEHandlersW( HINSTANCE hInstIME,
143 struct IMM32_IME_EXPORTED_HANDLERS* phandlers )
148 phandlers->p##name = (IMM32_p##name) \
149 GetProcAddress(hInstIME,#name); \
150 if ( phandlers->p##name == NULL ) fError = TRUE;
152 phandlers->p##name.W = (IMM32_p##name##W) \
153 GetProcAddress(hInstIME,#name); \
154 if ( phandlers->p##name.W == NULL ) fError = TRUE;
160 FE_(ImeConversionList)
162 FE_(ImeEnumRegisterWord)
163 FE_(ImeGetRegisterWordStyle)
168 FE(ImeSetActiveContext)
169 FE_(ImeSetCompositionString)
171 FE_(ImeUnregisterWord)
177 FE_(ImeGetImeMenuItems)
186 static IMM32_IMEKL* IMM32_LoadIME( HKL hkl )
188 IMM32_IMEKL* pkl = NULL;
189 BOOL fInitialized = FALSE;
190 CHAR* pszFileName = NULL;
192 IMM32_pImeInquireA pImeInquire;
193 IMM32_pImeDestroy pImeDestroy = NULL;
194 CHAR szUIClassName[ (IMM32_UICLASSNAME_MAX+1)*sizeof(WCHAR) ];
196 dwBufLen = IMM32_GetIMEFileName( hkl, NULL, 0 );
199 pszFileName = (CHAR*)IMM32_HeapAlloc( 0, sizeof(CHAR)*(dwBufLen+1) );
200 if ( pszFileName == NULL )
202 SetLastError( ERROR_OUTOFMEMORY );
205 if ( !IMM32_GetIMEFileName( hkl, pszFileName, dwBufLen + 1 ) )
209 IMM32_HeapAlloc( HEAP_ZERO_MEMORY, sizeof(IMM32_IMEKL) );
212 SetLastError( ERROR_OUTOFMEMORY );
218 pkl->hInstIME = LoadLibraryA( pszFileName );
219 if ( pkl->hInstIME == (HINSTANCE)NULL )
222 pImeInquire = (IMM32_pImeInquireA)GetProcAddress
223 ( pkl->hInstIME, "ImeInquire" );
224 pImeDestroy = (IMM32_pImeDestroy)GetProcAddress
225 ( pkl->hInstIME, "ImeDestroy" );
226 if ( pImeInquire == NULL || pImeDestroy == NULL )
229 if ( !pImeInquire( &(pkl->imeinfo), szUIClassName, NULL ) )
231 SetLastError( ERROR_DLL_INIT_FAILED ); /* FIXME? */
236 /* FIXME: Is this correct??? */
237 if ( pkl->imeinfo.fdwProperty & IME_PROP_UNICODE )
238 pkl->fUnicode = TRUE;
240 pkl->fUnicode = FALSE;
244 if ( !IMM32_GetIMEHandlersW( pkl->hInstIME, &pkl->handlers ) )
246 memcpy( pkl->UIClassName.W, szUIClassName,
247 IMM32_UICLASSNAME_MAX*sizeof(WCHAR) );
248 TRACE( "UI class name(Unicode): %s\n",
249 debugstr_w(pkl->UIClassName.W) );
253 if ( !IMM32_GetIMEHandlersA( pkl->hInstIME, &pkl->handlers ) )
255 memcpy( pkl->UIClassName.A, szUIClassName,
256 IMM32_UICLASSNAME_MAX*sizeof(CHAR) );
257 TRACE( "UI class name(ASCII): %s\n",
258 debugstr_a(pkl->UIClassName.A) );
261 /* The IME is loaded successfully. */
262 pkl->pszIMEFileName = pszFileName; pszFileName = NULL;
266 IMM32_HeapFree( pszFileName );
269 if ( pkl->hInstIME != (HINSTANCE)NULL )
272 (void)pImeDestroy(0);
273 FreeLibrary( pkl->hInstIME );
275 IMM32_HeapFree( pkl );
282 const IMM32_IMEKL* IMM32_GetIME( HKL hkl )
288 pkl = IMM32_pklFirst;
289 while ( pkl != NULL )
291 if ( pkl->hkl == hkl )
296 pkl = IMM32_LoadIME( hkl );
299 pkl->pNext = IMM32_pklFirst;
300 IMM32_pklFirst = pkl;
309 void IMM32_UnloadAllIMEs( void )
312 IMM32_IMEKL* pklNext;
316 pkl = IMM32_pklFirst;
317 while ( pkl != NULL )
319 TRACE( "hkl = %08x\n", (unsigned)pkl->hkl );
321 pklNext = pkl->pNext;
322 (void)pkl->handlers.pImeDestroy(0);
323 FreeLibrary( pkl->hInstIME );
324 IMM32_HeapFree( pkl->pszIMEFileName );
325 IMM32_HeapFree( pkl );
328 IMM32_pklFirst = NULL;
335 /***********************************************************************
336 * ImmInstallIMEA (IMM32.@)
338 HKL WINAPI ImmInstallIMEA(
339 LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
348 CHAR szValueName[ sizeof(IMM32_szIME_File) ];
351 debugstr_a(lpszIMEFileName), debugstr_a(lpszLayoutText) );
353 dwLCID = (DWORD)GetThreadLocale();
356 FIXME( "IMEs don't work correctly now since\n"
357 "wine/windows/input.c doesn't handle HKL correctly.\n" );
361 hkl = (HKL)(((0xe000|dwTryCount)<<16) | (dwLCID));
363 nError = IMM32_RegCreateKey( hkl, &hkey, &dwDisposition );
364 if ( nError != ERROR_SUCCESS )
367 memcpy( szValueName, IMM32_szIME_File,
368 sizeof(IMM32_szIME_File) );
370 nError = RegQueryValueExA( hkey, szValueName, NULL,
371 NULL, NULL, &cbData );
372 if ( nError == ERROR_SUCCESS && cbData > 0 )
376 /* try to assign an other HKL. */
378 if ( dwTryCount >= 0x100 )
380 nError = ERROR_ACCESS_DENIED; /* FIXME */
386 nError = RegSetValueExA( hkey, IMM32_szIME_File, 0,
387 REG_SZ, lpszIMEFileName,
388 strlen(lpszIMEFileName)+1 );
389 if ( nError == ERROR_SUCCESS )
390 nError = RegSetValueExA( hkey, IMM32_szLayout_File, 0,
391 REG_SZ, lpszLayoutText,
392 strlen(lpszLayoutText)+1 );
397 if ( nError != ERROR_SUCCESS )
399 SetLastError( nError );
406 /***********************************************************************
407 * ImmInstallIMEW (IMM32.@)
409 HKL WINAPI ImmInstallIMEW(
410 LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
417 debugstr_w(lpszIMEFileName), debugstr_w(lpszLayoutText) );
419 lpszParam1 = IMM32_strdupWtoA( lpszIMEFileName );
420 lpszParam2 = IMM32_strdupWtoA( lpszLayoutText );
421 if ( ( lpszParam1 == NULL ) || ( lpszParam2 == NULL ) )
423 SetLastError( ERROR_OUTOFMEMORY );
428 hkl = ImmInstallIMEA( lpszParam1, lpszParam2 );
430 IMM32_HeapFree( lpszParam1 );
431 IMM32_HeapFree( lpszParam2 );
437 /***********************************************************************
440 BOOL WINAPI ImmIsIME(HKL hkl)
442 const IMM32_IMEKL* pkl;
444 TRACE("(0x%08x)\n", hkl);
446 pkl = IMM32_GetIME( hkl );
454 /***********************************************************************
455 * ImmGetIMEFileNameA (IMM32.@)
457 UINT WINAPI ImmGetIMEFileNameA(HKL hkl, LPSTR lpszFileName, UINT uBufLen)
459 const IMM32_IMEKL* pkl;
460 UINT uIMEFileNameLen;
462 TRACE("(%08x,%p,%u)\n",hkl,lpszFileName,uBufLen);
464 pkl = IMM32_GetIME( hkl );
468 uIMEFileNameLen = strlen(pkl->pszIMEFileName);
470 return uIMEFileNameLen;
471 if ( uBufLen <= uIMEFileNameLen )
473 SetLastError(ERROR_INSUFFICIENT_BUFFER);
476 memcpy( lpszFileName, pkl->pszIMEFileName,
477 sizeof(CHAR)*(uIMEFileNameLen+1) );
479 return uIMEFileNameLen;
482 /***********************************************************************
483 * ImmGetIMEFileNameW (IMM32.@)
485 UINT WINAPI ImmGetIMEFileNameW(HKL hkl, LPWSTR lpszFileName, UINT uBufLen)
487 const IMM32_IMEKL* pkl;
488 UINT uIMEFileNameLen;
490 TRACE("(%08x,%p,%u)\n",hkl,lpszFileName,uBufLen);
492 pkl = IMM32_GetIME( hkl );
496 uIMEFileNameLen = IMM32_strlenAtoW(pkl->pszIMEFileName);
498 return uIMEFileNameLen;
499 if ( uBufLen <= uIMEFileNameLen )
501 SetLastError(ERROR_INSUFFICIENT_BUFFER);
504 IMM32_strncpyAtoW( lpszFileName, pkl->pszIMEFileName, uBufLen );
506 return uIMEFileNameLen;
509 /***********************************************************************
510 * ImmGetProperty (IMM32.@)
512 DWORD WINAPI ImmGetProperty(HKL hkl, DWORD fdwIndex)
514 const IMM32_IMEKL* pkl;
517 TRACE("(0x%08x, %ld)\n", hkl, fdwIndex);
519 pkl = IMM32_GetIME( hkl );
525 case IGP_GETIMEVERSION:
529 dwRet = pkl->imeinfo.fdwProperty;
532 dwRet = pkl->imeinfo.fdwConversionCaps;
535 dwRet = pkl->imeinfo.fdwSentenceCaps;
538 dwRet = pkl->imeinfo.fdwUICaps;
541 dwRet = pkl->imeinfo.fdwSCSCaps;
544 dwRet = pkl->imeinfo.fdwSelectCaps;
547 FIXME("(0x%08x, %ld): invalid/unknown property.\n",
549 SetLastError( ERROR_INVALID_PARAMETER );
557 /***********************************************************************
558 * ImmEnumRegisterWordA (IMM32.@)
560 UINT WINAPI ImmEnumRegisterWordA(
561 HKL hkl, REGISTERWORDENUMPROCA lpfnEnumProc,
562 LPCSTR lpszReading, DWORD dwStyle,
563 LPCSTR lpszRegister, LPVOID lpData)
565 const IMM32_IMEKL* pkl;
567 TRACE("(0x%08x, %p, %s, %ld, %s, %p)\n",
569 debugstr_a(lpszReading), dwStyle,
570 debugstr_a(lpszRegister), lpData);
572 pkl = IMM32_GetIME( hkl );
578 FIXME( "please implement UNICODE->ANSI\n" );
579 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
584 return pkl->handlers.pImeEnumRegisterWord.A
585 ( lpfnEnumProc, lpszReading, dwStyle,
586 lpszRegister, lpData );
590 /***********************************************************************
591 * ImmEnumRegisterWordW (IMM32.@)
593 UINT WINAPI ImmEnumRegisterWordW(
594 HKL hkl, REGISTERWORDENUMPROCW lpfnEnumProc,
595 LPCWSTR lpszReading, DWORD dwStyle,
596 LPCWSTR lpszRegister, LPVOID lpData)
598 const IMM32_IMEKL* pkl;
600 TRACE("(0x%08x, %p, %s, %ld, %s, %p): stub\n",
602 debugstr_w(lpszReading), dwStyle,
603 debugstr_w(lpszRegister), lpData);
605 pkl = IMM32_GetIME( hkl );
611 return pkl->handlers.pImeEnumRegisterWord.W
612 ( lpfnEnumProc, lpszReading, dwStyle,
613 lpszRegister, lpData );
617 FIXME( "please implement ANSI->UNICODE\n" );
618 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
624 /***********************************************************************
625 * ImmGetRegisterWordStyleA (IMM32.@)
627 UINT WINAPI ImmGetRegisterWordStyleA(
628 HKL hkl, UINT nItem, LPSTYLEBUFA lpStyleBuf)
630 const IMM32_IMEKL* pkl;
632 TRACE("(0x%08x, %d, %p)\n", hkl, nItem, lpStyleBuf);
634 pkl = IMM32_GetIME( hkl );
640 FIXME( "please implement UNICODE->ANSI\n" );
641 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
646 return pkl->handlers.pImeGetRegisterWordStyle.A
647 ( nItem, lpStyleBuf );
651 /***********************************************************************
652 * ImmGetRegisterWordStyleW (IMM32.@)
654 UINT WINAPI ImmGetRegisterWordStyleW(
655 HKL hkl, UINT nItem, LPSTYLEBUFW lpStyleBuf)
657 const IMM32_IMEKL* pkl;
659 TRACE("(0x%08x, %d, %p)\n", hkl, nItem, lpStyleBuf);
661 pkl = IMM32_GetIME( hkl );
667 return pkl->handlers.pImeGetRegisterWordStyle.W
668 ( nItem, lpStyleBuf );
672 FIXME( "please implement ANSI->UNICODE\n" );
673 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);