4 * Copyright 2000 Hidenori Takeshima
18 #include "debugtools.h"
19 DEFAULT_DEBUG_CHANNEL(imm);
21 #include "imm_private.h"
23 static const char IMM32_szRegKL[] =
24 "System\\CurrentControlSet\\Control\\keyboard layouts";
25 static const char IMM32_szIME_File[] = "IME file";
26 static const char IMM32_szLayout_File[] = "layout file";
28 static IMM32_IMEKL* IMM32_pklFirst = NULL;
31 static LONG IMM32_RegOpenKey( HKL hkl, PHKEY phkRet )
33 CHAR szRegPath[ sizeof(IMM32_szRegKL)+16 ];
35 wsprintfA( szRegPath, "%s\\%08x", IMM32_szRegKL, (unsigned)hkl );
36 return RegOpenKeyExA( HKEY_LOCAL_MACHINE, szRegPath,
37 0, KEY_READ, phkRet );
40 static LONG IMM32_RegCreateKey( HKL hkl, PHKEY phkRet,
41 LPDWORD lpdwDisposition )
43 CHAR szRegPath[ sizeof(IMM32_szRegKL)+16 ];
45 wsprintfA( szRegPath, "%s\\%08x", IMM32_szRegKL, (unsigned)hkl );
46 return RegCreateKeyExA( HKEY_LOCAL_MACHINE, szRegPath,
48 REG_OPTION_NON_VOLATILE,
50 phkRet, lpdwDisposition );
53 static DWORD IMM32_GetIMEFileName( HKL hkl, LPSTR lpBuf, INT nBufLen )
59 CHAR szValueName[ sizeof(IMM32_szIME_File) ];
61 TRACE( "hkl = %08x\n", (unsigned)hkl );
63 nError = IMM32_RegOpenKey( hkl, &hkey );
64 if ( nError != ERROR_SUCCESS )
66 SetLastError( nError );
69 memcpy( szValueName, IMM32_szIME_File, sizeof(IMM32_szIME_File) );
71 nError = RegQueryValueExA( hkey, szValueName, NULL,
72 &dwType, NULL, &cbData );
73 if ( nError == ERROR_SUCCESS && dwType != REG_SZ )
74 nError = ERROR_FILE_NOT_FOUND; /* FIXME? */
75 if ( nError == ERROR_SUCCESS && lpBuf != NULL && nBufLen != 0 )
77 if ( nBufLen < (INT)cbData )
78 nError = ERROR_INSUFFICIENT_BUFFER;
80 nError = RegQueryValueExA( hkey, szValueName, NULL,
81 &dwType, lpBuf, &cbData );
86 if ( nError != ERROR_SUCCESS )
88 SetLastError( nError );
97 BOOL IMM32_GetIMEHandlersA( HINSTANCE hInstIME,
98 struct IMM32_IME_EXPORTED_HANDLERS* phandlers )
103 phandlers->p##name = (IMM32_p##name) \
104 GetProcAddress(hInstIME,#name); \
105 if ( phandlers->p##name == NULL ) fError = TRUE;
107 phandlers->p##name.A = (IMM32_p##name##A) \
108 GetProcAddress(hInstIME,#name); \
109 if ( phandlers->p##name.A == NULL ) fError = TRUE;
115 FE_(ImeConversionList)
117 FE_(ImeEnumRegisterWord)
118 FE_(ImeGetRegisterWordStyle)
123 FE(ImeSetActiveContext)
124 FE_(ImeSetCompositionString)
126 FE_(ImeUnregisterWord)
132 FE_(ImeGetImeMenuItems)
141 BOOL IMM32_GetIMEHandlersW( HINSTANCE hInstIME,
142 struct IMM32_IME_EXPORTED_HANDLERS* phandlers )
147 phandlers->p##name = (IMM32_p##name) \
148 GetProcAddress(hInstIME,#name); \
149 if ( phandlers->p##name == NULL ) fError = TRUE;
151 phandlers->p##name.W = (IMM32_p##name##W) \
152 GetProcAddress(hInstIME,#name); \
153 if ( phandlers->p##name.W == NULL ) fError = TRUE;
159 FE_(ImeConversionList)
161 FE_(ImeEnumRegisterWord)
162 FE_(ImeGetRegisterWordStyle)
167 FE(ImeSetActiveContext)
168 FE_(ImeSetCompositionString)
170 FE_(ImeUnregisterWord)
176 FE_(ImeGetImeMenuItems)
185 static IMM32_IMEKL* IMM32_LoadIME( HKL hkl )
187 IMM32_IMEKL* pkl = NULL;
188 BOOL fInitialized = FALSE;
189 CHAR* pszFileName = NULL;
191 IMM32_pImeInquireA pImeInquire;
192 IMM32_pImeDestroy pImeDestroy = NULL;
193 CHAR szUIClassName[ (IMM32_UICLASSNAME_MAX+1)*sizeof(WCHAR) ];
195 dwBufLen = IMM32_GetIMEFileName( hkl, NULL, 0 );
198 pszFileName = (CHAR*)IMM32_HeapAlloc( 0, sizeof(CHAR)*(dwBufLen+1) );
199 if ( pszFileName == NULL )
201 SetLastError( ERROR_OUTOFMEMORY );
204 if ( !IMM32_GetIMEFileName( hkl, pszFileName, dwBufLen + 1 ) )
208 IMM32_HeapAlloc( HEAP_ZERO_MEMORY, sizeof(IMM32_IMEKL) );
211 SetLastError( ERROR_OUTOFMEMORY );
217 pkl->hInstIME = LoadLibraryA( pszFileName );
218 if ( pkl->hInstIME == (HINSTANCE)NULL )
221 pImeInquire = (IMM32_pImeInquireA)GetProcAddress
222 ( pkl->hInstIME, "ImeInquire" );
223 pImeDestroy = (IMM32_pImeDestroy)GetProcAddress
224 ( pkl->hInstIME, "ImeDestroy" );
225 if ( pImeInquire == NULL || pImeDestroy == NULL )
228 if ( !pImeInquire( &(pkl->imeinfo), szUIClassName, NULL ) )
230 SetLastError( ERROR_DLL_INIT_FAILED ); /* FIXME? */
235 /* FIXME: Is this correct??? */
236 if ( pkl->imeinfo.fdwProperty & IME_PROP_UNICODE )
237 pkl->fUnicode = TRUE;
239 pkl->fUnicode = FALSE;
243 if ( !IMM32_GetIMEHandlersW( pkl->hInstIME, &pkl->handlers ) )
245 memcpy( pkl->UIClassName.W, szUIClassName,
246 IMM32_UICLASSNAME_MAX*sizeof(WCHAR) );
247 TRACE( "UI class name(Unicode): %s\n",
248 debugstr_w(pkl->UIClassName.W) );
252 if ( !IMM32_GetIMEHandlersA( pkl->hInstIME, &pkl->handlers ) )
254 memcpy( pkl->UIClassName.A, szUIClassName,
255 IMM32_UICLASSNAME_MAX*sizeof(CHAR) );
256 TRACE( "UI class name(ASCII): %s\n",
257 debugstr_a(pkl->UIClassName.A) );
260 /* The IME is loaded successfully. */
261 pkl->pszIMEFileName = pszFileName; pszFileName = NULL;
265 IMM32_HeapFree( pszFileName );
268 if ( pkl->hInstIME != (HINSTANCE)NULL )
271 (void)pImeDestroy(0);
272 FreeLibrary( pkl->hInstIME );
274 IMM32_HeapFree( pkl );
281 const IMM32_IMEKL* IMM32_GetIME( HKL hkl )
287 pkl = IMM32_pklFirst;
288 while ( pkl != NULL )
290 if ( pkl->hkl == hkl )
295 pkl = IMM32_LoadIME( hkl );
298 pkl->pNext = IMM32_pklFirst;
299 IMM32_pklFirst = pkl;
308 void IMM32_UnloadAllIMEs( void )
311 IMM32_IMEKL* pklNext;
315 pkl = IMM32_pklFirst;
316 while ( pkl != NULL )
318 TRACE( "hkl = %08x\n", (unsigned)pkl->hkl );
320 pklNext = pkl->pNext;
321 (void)pkl->handlers.pImeDestroy(0);
322 FreeLibrary( pkl->hInstIME );
323 IMM32_HeapFree( pkl->pszIMEFileName );
324 IMM32_HeapFree( pkl );
327 IMM32_pklFirst = NULL;
334 /***********************************************************************
335 * ImmInstallIMEA (IMM32.@)
337 HKL WINAPI ImmInstallIMEA(
338 LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
347 CHAR szValueName[ sizeof(IMM32_szIME_File) ];
350 debugstr_a(lpszIMEFileName), debugstr_a(lpszLayoutText) );
352 dwLCID = (DWORD)GetThreadLocale();
355 FIXME( "IMEs don't work correctly now since\n"
356 "wine/windows/input.c doesn't handle HKL correctly.\n" );
360 hkl = (HKL)(((0xe000|dwTryCount)<<16) | (dwLCID));
362 nError = IMM32_RegCreateKey( hkl, &hkey, &dwDisposition );
363 if ( nError != ERROR_SUCCESS )
366 memcpy( szValueName, IMM32_szIME_File,
367 sizeof(IMM32_szIME_File) );
369 nError = RegQueryValueExA( hkey, szValueName, NULL,
370 NULL, NULL, &cbData );
371 if ( nError == ERROR_SUCCESS && cbData > 0 )
375 /* try to assign an other HKL. */
377 if ( dwTryCount >= 0x100 )
379 nError = ERROR_ACCESS_DENIED; /* FIXME */
385 nError = RegSetValueExA( hkey, IMM32_szIME_File, 0,
386 REG_SZ, lpszIMEFileName,
387 strlen(lpszIMEFileName)+1 );
388 if ( nError == ERROR_SUCCESS )
389 nError = RegSetValueExA( hkey, IMM32_szLayout_File, 0,
390 REG_SZ, lpszLayoutText,
391 strlen(lpszLayoutText)+1 );
396 if ( nError != ERROR_SUCCESS )
398 SetLastError( nError );
405 /***********************************************************************
406 * ImmInstallIMEW (IMM32.@)
408 HKL WINAPI ImmInstallIMEW(
409 LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
416 debugstr_w(lpszIMEFileName), debugstr_w(lpszLayoutText) );
418 lpszParam1 = IMM32_strdupWtoA( lpszIMEFileName );
419 lpszParam2 = IMM32_strdupWtoA( lpszLayoutText );
420 if ( ( lpszParam1 == NULL ) || ( lpszParam2 == NULL ) )
422 SetLastError( ERROR_OUTOFMEMORY );
427 hkl = ImmInstallIMEA( lpszParam1, lpszParam2 );
429 IMM32_HeapFree( lpszParam1 );
430 IMM32_HeapFree( lpszParam2 );
436 /***********************************************************************
439 BOOL WINAPI ImmIsIME(HKL hkl)
441 const IMM32_IMEKL* pkl;
443 TRACE("(0x%08x)\n", hkl);
445 pkl = IMM32_GetIME( hkl );
453 /***********************************************************************
454 * ImmGetIMEFileNameA (IMM32.@)
456 UINT WINAPI ImmGetIMEFileNameA(HKL hkl, LPSTR lpszFileName, UINT uBufLen)
458 const IMM32_IMEKL* pkl;
459 UINT uIMEFileNameLen;
461 TRACE("(%08x,%p,%u)\n",hkl,lpszFileName,uBufLen);
463 pkl = IMM32_GetIME( hkl );
467 uIMEFileNameLen = strlen(pkl->pszIMEFileName);
469 return uIMEFileNameLen;
470 if ( uBufLen <= uIMEFileNameLen )
472 SetLastError(ERROR_INSUFFICIENT_BUFFER);
475 memcpy( lpszFileName, pkl->pszIMEFileName,
476 sizeof(CHAR)*(uIMEFileNameLen+1) );
478 return uIMEFileNameLen;
481 /***********************************************************************
482 * ImmGetIMEFileNameW (IMM32.@)
484 UINT WINAPI ImmGetIMEFileNameW(HKL hkl, LPWSTR lpszFileName, UINT uBufLen)
486 const IMM32_IMEKL* pkl;
487 UINT uIMEFileNameLen;
489 TRACE("(%08x,%p,%u)\n",hkl,lpszFileName,uBufLen);
491 pkl = IMM32_GetIME( hkl );
495 uIMEFileNameLen = IMM32_strlenAtoW(pkl->pszIMEFileName);
497 return uIMEFileNameLen;
498 if ( uBufLen <= uIMEFileNameLen )
500 SetLastError(ERROR_INSUFFICIENT_BUFFER);
503 IMM32_strncpyAtoW( lpszFileName, pkl->pszIMEFileName, uBufLen );
505 return uIMEFileNameLen;
508 /***********************************************************************
509 * ImmGetProperty (IMM32.@)
511 DWORD WINAPI ImmGetProperty(HKL hkl, DWORD fdwIndex)
513 const IMM32_IMEKL* pkl;
516 TRACE("(0x%08x, %ld)\n", hkl, fdwIndex);
518 pkl = IMM32_GetIME( hkl );
524 case IGP_GETIMEVERSION:
528 dwRet = pkl->imeinfo.fdwProperty;
531 dwRet = pkl->imeinfo.fdwConversionCaps;
534 dwRet = pkl->imeinfo.fdwSentenceCaps;
537 dwRet = pkl->imeinfo.fdwUICaps;
540 dwRet = pkl->imeinfo.fdwSCSCaps;
543 dwRet = pkl->imeinfo.fdwSelectCaps;
546 FIXME("(0x%08x, %ld): invalid/unknown property.\n",
548 SetLastError( ERROR_INVALID_PARAMETER );
556 /***********************************************************************
557 * ImmEnumRegisterWordA (IMM32.@)
559 UINT WINAPI ImmEnumRegisterWordA(
560 HKL hkl, REGISTERWORDENUMPROCA lpfnEnumProc,
561 LPCSTR lpszReading, DWORD dwStyle,
562 LPCSTR lpszRegister, LPVOID lpData)
564 const IMM32_IMEKL* pkl;
566 TRACE("(0x%08x, %p, %s, %ld, %s, %p)\n",
568 debugstr_a(lpszReading), dwStyle,
569 debugstr_a(lpszRegister), lpData);
571 pkl = IMM32_GetIME( hkl );
577 FIXME( "please implement UNICODE->ANSI\n" );
578 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
583 return pkl->handlers.pImeEnumRegisterWord.A
584 ( lpfnEnumProc, lpszReading, dwStyle,
585 lpszRegister, lpData );
589 /***********************************************************************
590 * ImmEnumRegisterWordW (IMM32.@)
592 UINT WINAPI ImmEnumRegisterWordW(
593 HKL hkl, REGISTERWORDENUMPROCW lpfnEnumProc,
594 LPCWSTR lpszReading, DWORD dwStyle,
595 LPCWSTR lpszRegister, LPVOID lpData)
597 const IMM32_IMEKL* pkl;
599 TRACE("(0x%08x, %p, %s, %ld, %s, %p): stub\n",
601 debugstr_w(lpszReading), dwStyle,
602 debugstr_w(lpszRegister), lpData);
604 pkl = IMM32_GetIME( hkl );
610 return pkl->handlers.pImeEnumRegisterWord.W
611 ( lpfnEnumProc, lpszReading, dwStyle,
612 lpszRegister, lpData );
616 FIXME( "please implement ANSI->UNICODE\n" );
617 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
623 /***********************************************************************
624 * ImmGetRegisterWordStyleA (IMM32.@)
626 UINT WINAPI ImmGetRegisterWordStyleA(
627 HKL hkl, UINT nItem, LPSTYLEBUFA lpStyleBuf)
629 const IMM32_IMEKL* pkl;
631 TRACE("(0x%08x, %d, %p)\n", hkl, nItem, lpStyleBuf);
633 pkl = IMM32_GetIME( hkl );
639 FIXME( "please implement UNICODE->ANSI\n" );
640 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
645 return pkl->handlers.pImeGetRegisterWordStyle.A
646 ( nItem, lpStyleBuf );
650 /***********************************************************************
651 * ImmGetRegisterWordStyleW (IMM32.@)
653 UINT WINAPI ImmGetRegisterWordStyleW(
654 HKL hkl, UINT nItem, LPSTYLEBUFW lpStyleBuf)
656 const IMM32_IMEKL* pkl;
658 TRACE("(0x%08x, %d, %p)\n", hkl, nItem, lpStyleBuf);
660 pkl = IMM32_GetIME( hkl );
666 return pkl->handlers.pImeGetRegisterWordStyle.W
667 ( nItem, lpStyleBuf );
671 FIXME( "please implement ANSI->UNICODE\n" );
672 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);