/* Name: calldll Copyright: Copyright (C) SIL International. Documentation: Description: Create Date: 11 Mar 2009 Modified Date: 13 Oct 2014 Authors: mcdurdin Related Files: Dependencies: Bugs: Todo: Notes: History: 11 Mar 2009 - mcdurdin - I1894 - Fix threading bugs introduced in I1888 11 Dec 2009 - mcdurdin - I934 - x64 - Initial version 12 Mar 2010 - mcdurdin - I934 - x64 - Complete 12 Mar 2010 - mcdurdin - I2229 - Remove hints and warnings 04 May 2010 - mcdurdin - I2351 - Robustness - verify _td return value 03 Oct 2011 - mcdurdin - I3094 - IMX DLLs do not support x64 03 Oct 2011 - mcdurdin - I3091 - KMGetContext crashes with assertion failure due to buffer size mismatch 24 Jan 2012 - mcdurdin - I3173 - Keyman Developer crash when unloading forced keyboard in rare cases 04 Nov 2012 - mcdurdin - I3525 - V9.0 - Merge of I3173 - Keyman can crash when Keyman_StopForcingKeyboard called and keyboard is not already forced 05 Nov 2012 - mcdurdin - I3547 - V9.0 Use _countof to tidyup code 13 Oct 2014 - mcdurdin - I4452 - V9.0 - Chinese keyboard is not working correctly */ #include "pch.h" typedef BOOL (WINAPI *InitDllFunction)(PSTR name); /* Add a dll to the list of dlls associated with the keyboard */ // core processor implmentation also uses the static LPIMDLL AddIMDLL(LPINTKEYBOARDINFO lpkbi, LPSTR kbdpath, LPSTR dllfilename) { SendDebugMessageFormat(0, sdmKeyboard, 0, "AddIMDLL: Enter"); DWORD j; for(j = 0; j < lpkbi->nIMDLLs; j++) if(!_stricmp(lpkbi->IMDLLs[j].Filename, dllfilename)) break; if(j < lpkbi->nIMDLLs) return &lpkbi->IMDLLs[j]; char drive[_MAX_DRIVE], dir[_MAX_DIR], fullname[_MAX_PATH], newdllname[_MAX_FNAME]; strcpy_s(fullname, _countof(fullname), kbdpath); _splitpath_s(fullname, drive, _countof(drive), dir, _countof(dir), NULL, 0, NULL, 0); // I3547 #ifdef _WIN64 char dllname[_MAX_FNAME], dllext[_MAX_EXT], newdllext[_MAX_EXT]; // I3094 _splitpath_s(dllfilename, NULL, 0, NULL, 0, dllname, _countof(dllname), dllext, _countof(dllext)); // I3547 strcpy_s(newdllext, _countof(newdllext), ".x64"); // I3547 strcat_s(newdllext, _countof(newdllext), dllext); // I3547 _makepath_s(fullname, _countof(fullname), drive, dir, dllname, newdllext); // I3547 _makepath_s(newdllname, _countof(newdllname), NULL, NULL, dllname, newdllext); // I3547 #else _makepath_s(fullname, _countof(fullname), drive, dir, dllfilename, NULL); // I3547 strcpy_s(newdllname, _countof(newdllname), dllfilename); // I3094 // I3547 #endif /* Load the DLL */ HINSTANCE hModule = LoadLibrary(fullname); // Try keyboard dir first if(!hModule) hModule = LoadLibrary(newdllname); // Try anywhere on the path -- LIBRARY_NAME dir first // I3094 if (!hModule) { SendDebugMessageFormat(0, sdmKeyboard, 0, "AddIMDLL: hModule not loadded fullname[%s] newdllname[%s]", fullname, newdllname); return NULL; } /* Initialise the DLL */ InitDllFunction idf = (InitDllFunction) GetProcAddress(hModule, "KeymanIMInit"); if(idf && !(*idf)(lpkbi->Name)) { FreeLibrary(hModule); return NULL; } /* Add the DLL to the list of DLLs */ SendDebugMessageFormat( 0, sdmKeyboard, 0, "AddIMDLL: add new function"); LPIMDLL imd = new IMDLL[lpkbi->nIMDLLs + 1]; if(lpkbi->nIMDLLs > 0) { memcpy(imd, lpkbi->IMDLLs, sizeof(IMDLL) * lpkbi->nIMDLLs); delete lpkbi->IMDLLs; } lpkbi->IMDLLs = imd; strncpy(imd->Filename, dllfilename, 255); imd->Filename[255] = 0; imd->nHooks = 0; imd->Hooks = NULL; imd->hModule = hModule; lpkbi->nIMDLLs++; SendDebugMessageFormat(0, sdmKeyboard, 0, "AddIMDLL: Exit"); return imd; } /* Add a dll hook function to the list of hook functions associated with a single dll */ static BOOL AddIMDLLHook(LPIMDLL imd, LPSTR funcname, DWORD storeno, PWCHAR *dpString) { SendDebugMessageFormat(0, sdmKeyboard, 0, "AddIMDLLHook: Enter"); /* Get the procedure address for the function */ IMDLLHOOKProc dhp = (IMDLLHOOKProc) GetProcAddress(imd->hModule, funcname); if(!dhp) return FALSE; /* Add the function to the list of functions in the DLL */ LPIMDLLHOOK hooks = new IMDLLHOOK[imd->nHooks+1]; if(imd->nHooks > 0) { memcpy(hooks, imd->Hooks, sizeof(IMDLLHOOK) * imd->nHooks); delete imd->Hooks; } imd->Hooks = hooks; strncpy(imd->Hooks[imd->nHooks].name, funcname, 31); imd->Hooks[imd->nHooks].name[31] = 0; imd->Hooks[imd->nHooks].storeno = storeno; imd->Hooks[imd->nHooks].function = dhp; *dpString = (PWCHAR) &imd->Hooks[imd->nHooks++]; SendDebugMessageFormat(0, sdmKeyboard, 0, "AddIMDLLHook: Exit"); return TRUE; } static km_kbp_action_item* kmnToCoreActionItem(int ItemType, DWORD dwData) { //km_kbp_action_item *actionItem = nullptr; km_kbp_action_item *actionItems = new km_kbp_action_item[2]; actionItems[0].type = KM_KBP_IT_END; actionItems[1].type = KM_KBP_IT_END; switch (ItemType) { case QIT_CHAR: //actionItem = new km_kbp_action_item { // KM_KBP_CT_CHAR, // { // 0, // }, // {dwData}}; actionItems[0].type = KM_KBP_IT_CHAR; actionItems[0].character = dwData; break; case QIT_DEADKEY: /*actionItem = new km_kbp_action_item { KM_KBP_IT_MARKER, { 0, }, {dwData}};*/ actionItems[0].type = KM_KBP_IT_MARKER; actionItems[0].marker = dwData; break; case QIT_BELL: /*actionItem = new km_kbp_action_item { KM_KBP_IT_ALERT, { 0, }, {0}};*/ actionItems[0].type = KM_KBP_IT_ALERT; break; case QIT_BACK: switch (dwData) { case BK_DEFAULT: /*actionItem = new km_kbp_action_item{ KM_KBP_IT_BACK, { 0, }, {0}}; actionItem->backspace.expected_type = KM_KBP_BT_CHAR;*/ actionItems[0].type = KM_KBP_IT_BACK; actionItems[0].backspace.expected_type = KM_KBP_BT_CHAR; break; case BK_DEADKEY: /*actionItem = new km_kbp_action_item{ KM_KBP_IT_BACK, { 0, }, {0}}; actionItem->backspace.expected_type = KM_KBP_BT_MARKER;*/ actionItems[0].type = KM_KBP_IT_BACK; actionItems[0].backspace.expected_type = KM_KBP_BT_MARKER; break; } break; case QIT_CAPSLOCK: case QIT_VKEYDOWN: case QIT_VKEYUP: case QIT_VSHIFTDOWN: case QIT_VSHIFTUP: // Not handled TODO Log a message? //actionItem = new km_kbp_action_item {KM_KBP_IT_END, {0,}, {0}}; actionItems[0].type = KM_KBP_IT_END; break; case QIT_INVALIDATECONTEXT: //actionItem = new km_kbp_action_item {KM_KBP_IT_INVALIDATE_CONTEXT, {0,}, {0}}; actionItems[0].type = KM_KBP_IT_INVALIDATE_CONTEXT; break; } //if (!actionItem) { // actionItem = new km_kbp_action_item {KM_KBP_IT_END, {0,}, {0}}; // return actionItem; // } //else //km_kbp_action_item *actionItems[2]; // actionItems[0] = actionItem; // actionItems[1] = new km_kbp_action_item {KM_KBP_IT_END, {0,}, {0}}; return actionItems; } // For debuging allow printing of the intermediate context static BOOL LogIntermediateContext(km_kbp_state *lpCoreKeyboardState) { if (!lpCoreKeyboardState) { return FALSE; } km_kbp_context_item *citems = nullptr; if (KM_KBP_STATUS_OK != (km_kbp_status_codes)kbp_state_get_intermediate_context(lpCoreKeyboardState, &citems)) { km_kbp_context_items_dispose(citems); return FALSE; } DWORD context_length = (DWORD)km_kbp_context_item_list_size(citems); WCHAR *buf = new WCHAR[(context_length * 3) +1 ]; // *3 if every context item was a deadkey if (!ContextItemToAppContext(citems, buf, context_length)) { km_kbp_context_items_dispose(citems); delete[] buf; return FALSE; } km_kbp_context_items_dispose(citems); SendDebugMessageFormat(0, sdmKeyboard, 0, "LogIntermediateContext: intermediate_context [%s]", Debug_UnicodeString(buf)); delete[] buf; return TRUE; } // For debuging static BOOL LogCoreContext(km_kbp_state *lpCoreKeyboardState) { if (!lpCoreKeyboardState) { return FALSE; } km_kbp_context_item *citems = nullptr; if (KM_KBP_STATUS_OK != (km_kbp_status_codes)km_kbp_context_get(km_kbp_state_context(lpCoreKeyboardState), &citems)) { km_kbp_context_items_dispose(citems); return FALSE; } DWORD context_length = (DWORD)km_kbp_context_item_list_size(citems); WCHAR *buf = new WCHAR[(context_length * 3) + 1]; // *3 if every context item was a deadkey if (!ContextItemToAppContext(citems, buf, MAXCONTEXT)) { km_kbp_context_items_dispose(citems); delete[] buf; return FALSE; } km_kbp_context_items_dispose(citems); SendDebugMessageFormat(0, sdmKeyboard, 0, "LogCoreContext: core context [%s]", Debug_UnicodeString(buf)); delete[] buf; return TRUE; } /// /* Call a DLL callback for all DLLs loaded with a given keyboard */ BOOL CallbackDLLs(LPINTKEYBOARDINFO lpkbi, PSTR cmd) { //SendDebugMessageFormat(0, sdmKeyboard, 0, "ActivateDLLs: Enter"); for(DWORD i = 0; i < lpkbi->nIMDLLs; i++) { InitDllFunction idf = (InitDllFunction) GetProcAddress(lpkbi->IMDLLs[i].hModule, cmd); if(idf) (*idf)(lpkbi->Name); } return TRUE; } /* Load the dlls associated with a keyboard */ BOOL LoadDLLs(LPINTKEYBOARDINFO lpkbi) { char fullname[_MAX_PATH]; SendDebugMessageFormat(0, sdmKeyboard, 0, "LoadDLLs: Enter"); if(lpkbi->nIMDLLs > 0) if(!UnloadDLLs(lpkbi)) return FALSE; if (!GetKeyboardFileName(lpkbi->Name, fullname, _MAX_PATH)) { SendDebugMessageFormat(0, sdmKeyboard, 0, "LoadDLLs: Filename not found[%s]", lpkbi->Name); return FALSE; } if (!lpkbi->Keyboard) { SendDebugMessageFormat(0, sdmKeyboard, 0, "LoadDLLs: Keyboard is null"); return FALSE; } for(DWORD i = 0; i < lpkbi->Keyboard->cxStoreArray; i++) { LPSTORE s = &lpkbi->Keyboard->dpStoreArray[i]; if(s->dwSystemID == TSS_CALLDEFINITION) { /* Break the store string into components */ PCHAR p = wstrtostr(s->dpString), q, r, context; q = strtok_s(p, ":", &context); r = strtok_s(NULL, ":", &context); if(!q || !r) { s->dwSystemID = TSS_CALLDEFINITION_LOADFAILED; delete[] p; continue; } LPIMDLL imd = AddIMDLL(lpkbi, fullname, q); if(imd && AddIMDLLHook(imd, r, i, &s->dpString)) s->dwSystemID = TSS_CALLDEFINITION; else s->dwSystemID = TSS_CALLDEFINITION_LOADFAILED; delete[] p; } } SendDebugMessageFormat(0, sdmKeyboard, 0, "LoadDLLs: Exit"); return TRUE; } // Both Core and Window keyboard processor can use this function BOOL UnloadDLLs(LPINTKEYBOARDINFO lpkbi) { SendDebugMessageFormat(0, sdmKeyboard, 0, "UnloadDLLs: Enter"); if(!lpkbi) { SetLastError(ERROR_INVALID_PARAMETER); // I3173 // I3525 return FALSE; } CallbackDLLs(lpkbi, "KeymanIMDestroy"); for(DWORD i = 0; i < lpkbi->nIMDLLs; i++) { FreeLibrary(lpkbi->IMDLLs[i].hModule); if(lpkbi->IMDLLs[i].Hooks) delete lpkbi->IMDLLs[i].Hooks; } delete lpkbi->IMDLLs; lpkbi->IMDLLs = NULL; lpkbi->nIMDLLs = 0; if (Globals::get_CoreIntegration() && lpkbi->lpCoreKeyboardState) { SendDebugMessageFormat(0, sdmKeyboard, 0, "UnloadDLLs: deregister core callback"); km_kbp_state_imx_deregister_callback(lpkbi->lpCoreKeyboardState); } SendDebugMessageFormat(0, sdmKeyboard, 0, "UnloadDLLs: Exit"); return TRUE; } BOOL ActivateDLLs(LPINTKEYBOARDINFO lpkbi) { if(!lpkbi) { SetLastError(ERROR_INVALID_PARAMETER); // I3173 - not actually used by this issue but added for completeness // I3525 return FALSE; } CallbackDLLs(lpkbi, "KeymanIMActivate"); return TRUE; } BOOL DeactivateDLLs(LPINTKEYBOARDINFO lpkbi) { if(!lpkbi) { SetLastError(ERROR_INVALID_PARAMETER); // I3173 // I3525 return FALSE; } CallbackDLLs(lpkbi, "KeymanIMDeactivate"); return TRUE; } void CallDLL(LPINTKEYBOARDINFO lpkbi, DWORD storenum) { SendDebugMessageFormat(0, sdmKeyboard, 0, "CallDll: Enter"); if (!lpkbi->Keyboard) return; if(storenum >= lpkbi->Keyboard->cxStoreArray) return; LPSTORE s = &lpkbi->Keyboard->dpStoreArray[storenum]; if(s->dwSystemID != TSS_CALLDEFINITION) return; if(s->dpString == NULL) return; LPIMDLLHOOK imdh = (LPIMDLLHOOK) s->dpString; PKEYMAN64THREADDATA _td = ThreadGlobals(); if(!_td) return; if(_td->TIPFUpdateable) { // I4452 (*imdh->function)(_td->state.msg.hwnd, _td->state.vkey, _td->state.charCode, Globals::get_ShiftState()); } SendDebugMessageFormat(0, sdmKeyboard, 0, "CallDll: Exit"); } // The callback function from core //typedef KMN_API uint8_t (*km_kbp_keyboard_imx_platform)(km_kbp_state *, uint32_t); // TODO need to update this to have LPINTKEYBOARDINFO lpkbi in the callback. So the callback will store the object. // will not need km_state anymore extern "C" uint8_t IM_CallBackCore(km_kbp_state *km_state, uint32_t UniqueStoreNo, void *callbackObject) { SendDebugMessageFormat(0, sdmKeyboard, 0, "IM_CallBackCore: Enter"); if (callbackObject == NULL) { return FALSE; } if (km_state == NULL) { return FALSE; } LPINTKEYBOARDINFO lpkbi = (LPINTKEYBOARDINFO)(callbackObject); if (!lpkbi->lpCoreKeyboard) return 0; // False // Iterate through hooks to find the call back BOOL found = FALSE; DWORD n = 0; LPIMDLLHOOK imdh = nullptr; SendDebugMessageFormat(0, sdmKeyboard, 0, "IM_CallBackCore: nIMDLL count [%lu] hook count [%lu], storeno [%lu]", lpkbi->nIMDLLs, lpkbi->nIMDLLHooks, UniqueStoreNo); for (DWORD i = 0; i < lpkbi->nIMDLLs; i++) { for (DWORD j = 0; j < lpkbi->IMDLLs[i].nHooks; j++) { if (lpkbi->IMDLLs[i].Hooks[j].storeno == UniqueStoreNo) { found = TRUE; imdh = &lpkbi->IMDLLs[i].Hooks[j]; break; } n++; } } if (!found) { return FALSE; } SendDebugMessageFormat( 0, sdmKeyboard, 0, "IM_CallBackCore: found:[%lu]", found); //LPIMDLLHOOK imdh = lpkbi->lpIMDLLHooks[n]; PKEYMAN64THREADDATA _td = ThreadGlobals(); if (!_td) return FALSE; SendDebugMessageFormat( 0, sdmKeyboard, 0, "IM_CallBackCore: td loadeded"); if (_td->TIPFUpdateable) { // I4452 SendDebugMessageFormat(0, sdmKeyboard, 0, "IM_CallBackCore: td TIPFUpdatable about to call function [%s]", imdh->name); SendDebugMessageFormat(0, sdmKeyboard, 0, "IM_CallBackCore context"); LogCoreContext(_td->lpActiveKeyboard->lpCoreKeyboardState); LogIntermediateContext(_td->lpActiveKeyboard->lpCoreKeyboardState); SendDebugMessageFormat( 0, sdmKeyboard, 0, "IM_CallBackCore: td->state.vkey:[%lu] td->state.charCode [%lu]", _td->state.vkey, _td->state.charCode); (*imdh->function)(_td->state.msg.hwnd, _td->state.vkey, _td->state.charCode, Globals::get_ShiftState()); } SendDebugMessageFormat(0, sdmKeyboard, 0, "IM_CallBackCore: Exit"); return TRUE; } extern "C" BOOL _declspec(dllexport) WINAPI KMSetOutput(PWSTR buf, DWORD backlen) { SendDebugMessageFormat(0, sdmKeyboard, 0, "KMSetOutput: Enter"); PKEYMAN64THREADDATA _td = ThreadGlobals(); if (!_td) return FALSE; if (!_td->app) return FALSE; if (!Globals::get_CoreIntegration()) { // TODO: 5442 Remove If and fix indent while (backlen-- > 0) _td->app->QueueAction(QIT_BACK, 0); while (*buf) _td->app->QueueAction(QIT_CHAR, *buf++); SendDebugMessageFormat(0, sdmKeyboard, 0, "KMSetOutput: Exit"); return TRUE; } else { if (!_td->lpActiveKeyboard->lpCoreKeyboardState) { SendDebugMessageFormat(0, sdmKeyboard, 0, "KMSetOutputCore: no active state"); return FALSE; } DWORD numActions = backlen + (DWORD)wcslen(buf); DWORD idx = 0; km_kbp_action_item *actionItems = new km_kbp_action_item[numActions + 1]; // The actions sent to the core processor need to set the expected_type // correctly. To do this need to check the context as we process the // backspaces. // hmmm I think we may need the use the get intermediate context for this SendDebugMessageFormat(0, sdmKeyboard, 0, "KMSetOutputCoreStep1"); LogCoreContext(_td->lpActiveKeyboard->lpCoreKeyboardState); LogIntermediateContext(_td->lpActiveKeyboard->lpCoreKeyboardState); km_kbp_context_item *citems = nullptr; if (KM_KBP_STATUS_OK != (km_kbp_status_codes)kbp_state_get_intermediate_context(_td->lpActiveKeyboard->lpCoreKeyboardState, &citems)) { km_kbp_context_items_dispose(citems); return FALSE; } WCHAR *contextString = new WCHAR[MAXCONTEXT]; // *3 if every context item was a deadkey if (!ContextItemToAppContext(citems, contextString, MAXCONTEXT)) { km_kbp_context_items_dispose(citems); delete[] contextString; return FALSE; } km_kbp_context_items_dispose(citems); AppContext context; context.Set(contextString); delete[] contextString; //AppContext context; //_td->app->CopyContext(&context); SendDebugMessageFormat(0, sdmKeyboard, 0, "KMSetOutputCore: backlen[%lu],buflen[%lu]", backlen, (DWORD)wcslen(buf)); while (backlen-- > 0) { actionItems[idx].type = KM_KBP_IT_BACK; WCHAR *CodeUnitPtr; const int DeadKeyLength = 3; const int SurrogateLength = 2; const int SingleCharLength = 1; if (context.CharIsDeadkey()) { CodeUnitPtr = context.BufMax(DeadKeyLength); CodeUnitPtr += 2; actionItems[idx].backspace.expected_type = KM_KBP_BT_MARKER; actionItems[idx].backspace.expected_value = (uintptr_t)*CodeUnitPtr; } else if (context.CharIsSurrogatePair()) { CodeUnitPtr = context.BufMax(SurrogateLength); actionItems[idx].backspace.expected_type = KM_KBP_BT_CHAR; actionItems[idx].backspace.expected_value = (DWORD)Uni_SurrogateToUTF32(*CodeUnitPtr, *(CodeUnitPtr + 1)); } else { CodeUnitPtr = context.BufMax(SingleCharLength); actionItems[idx].backspace.expected_type = KM_KBP_BT_CHAR; actionItems[idx].backspace.expected_value = (DWORD)*CodeUnitPtr; } context.Delete(); SendDebugMessageFormat(0, sdmKeyboard, 0, "KMSetOutputCore: ContextDelete"); idx++; } // Need to set the app with the updated context //_td->app->RestoreContextOnly(&context); SendDebugMessageFormat(0, sdmKeyboard, 0, "KMSetOutputCore: buf is [%s]", Debug_UnicodeString(buf)); while (*buf) { actionItems[idx].type = KM_KBP_IT_CHAR; if (Uni_IsSurrogate1(*buf) && Uni_IsSurrogate2(*(buf + 1))) { actionItems[idx].character = Uni_SurrogateToUTF32(*buf, *(buf + 1)); buf++; } else { actionItems[idx].character = (DWORD)(*buf); } buf++; idx++; } actionItems[idx].type = KM_KBP_IT_END; // for debugging km_kbp_action_item *actionItem_iter = actionItems; for (; actionItem_iter->type != KM_KBP_IT_END; ++actionItem_iter) { if (actionItem_iter->type >= KM_KBP_IT_MAX_TYPE_ID) { SendDebugMessageFormat(0, sdmKeyboard, 0, "KMSetOutputCore: KM_KBP_STATUS_INVALID_ARGUMENT"); } SendDebugMessageFormat(0, sdmKeyboard, 0, "KMSetOutputCore: type[%lu]", actionItem_iter->type); } // for debugging SendDebugMessageFormat(0, sdmKeyboard, 0, "KMSetOutputCoreStep2"); LogCoreContext(_td->lpActiveKeyboard->lpCoreKeyboardState); LogIntermediateContext(_td->lpActiveKeyboard->lpCoreKeyboardState); if (KM_KBP_STATUS_OK != (km_kbp_status_codes)km_kbp_state_queue_action_items(_td->lpActiveKeyboard->lpCoreKeyboardState, actionItems)) { delete[] actionItems; return FALSE; } delete[] actionItems; SendDebugMessageFormat(0, sdmKeyboard, 0, "KMSetOutputCore: queue_action_items"); LogCoreContext(_td->lpActiveKeyboard->lpCoreKeyboardState); LogIntermediateContext(_td->lpActiveKeyboard->lpCoreKeyboardState); SendDebugMessageFormat(0, sdmKeyboard, 0, "KMSetOutputCore: Exit"); return TRUE; } } extern "C" BOOL _declspec(dllexport) WINAPI KMQueueAction(int ItemType, DWORD dwData) { SendDebugMessageFormat(0, sdmKeyboard, 0, "KMQueueAction: Enter Item type[%lu]",ItemType); PKEYMAN64THREADDATA _td = ThreadGlobals(); if (!_td) return FALSE; if (!_td->app) return FALSE; if (!Globals::get_CoreIntegration()) { SendDebugMessageFormat(0, sdmKeyboard, 0, "KMQueueAction: Exit"); return _td->app->QueueAction(ItemType, dwData); // TODO: 5442 Remove } else { if (!_td->lpActiveKeyboard->lpCoreKeyboardState) { SendDebugMessageFormat(0, sdmKeyboard, 0, "KMQueueAction: Exit - no active state Return False"); return FALSE; } km_kbp_action_item *actionItem = kmnToCoreActionItem(ItemType, dwData); // for debuging SendDebugMessageFormat(0, sdmKeyboard, 0, "KMQueueAction: before queue_action_items"); LogCoreContext(_td->lpActiveKeyboard->lpCoreKeyboardState); LogIntermediateContext(_td->lpActiveKeyboard->lpCoreKeyboardState); km_kbp_action_item *actionItem_iter = actionItem; for (; actionItem_iter->type != KM_KBP_IT_END; ++actionItem_iter) { if (actionItem_iter->type >= KM_KBP_IT_MAX_TYPE_ID) { SendDebugMessageFormat(0, sdmKeyboard, 0, "KMQueueAction: KM_KBP_STATUS_INVALID_ARGUMENT"); } SendDebugMessageFormat(0, sdmKeyboard, 0, "KMQueueAction: type[%lu]", actionItem_iter->type); } // if (KM_KBP_STATUS_OK != // (km_kbp_status_codes)km_kbp_state_queue_action_items(_td->lpActiveKeyboard->lpCoreKeyboardState, actionItem)) km_kbp_status_codes error_status = (km_kbp_status_codes)km_kbp_state_queue_action_items(_td->lpActiveKeyboard->lpCoreKeyboardState, actionItem); if (error_status != KM_KBP_STATUS_OK) { delete[] actionItem; SendDebugMessageFormat(0, sdmKeyboard, 0, "KMQueueAction: Exit - core queue Return [%lu]",error_status); return FALSE; } delete[] actionItem; SendDebugMessageFormat(0, sdmKeyboard, 0, "KMQueueAction: After queue_action_items"); LogCoreContext(_td->lpActiveKeyboard->lpCoreKeyboardState); LogIntermediateContext(_td->lpActiveKeyboard->lpCoreKeyboardState); SendDebugMessageFormat(0, sdmKeyboard, 0, "KMQueueActionCore: Exit"); return TRUE; } } extern "C" BOOL _declspec(dllexport) WINAPI KMGetContext(PWSTR buf, DWORD len) { SendDebugMessageFormat(0, sdmKeyboard, 0, "KMGetContext: Enter"); PKEYMAN64THREADDATA _td = ThreadGlobals(); if(!_td) return FALSE; if(!_td->app) return FALSE; // TODO: 5442 KMGetContext is already public call (even though it is pointer) Rather then making a new KMGetContextCore // This has been modified to check for core processor once we move to core processor the old Windows Platmform calling of // ContextBuff can be removed // if(!Globals::get_CoreIntegration()){ PWSTR q = _td->app->ContextBufMax(len); if (!q) return FALSE; // context buf does not exist wcscpy_s(buf, len + 1, q); // I3091 SendDebugMessageFormat(0, sdmKeyboard, 0, "KMGetContextEngine: [%s]", Debug_UnicodeString(buf)); return TRUE; } else { if (!_td->lpActiveKeyboard->lpCoreKeyboardState) { return FALSE; } km_kbp_context_item *citems = nullptr; if (KM_KBP_STATUS_OK != (km_kbp_status_codes)kbp_state_get_intermediate_context(_td->lpActiveKeyboard->lpCoreKeyboardState, &citems)){ km_kbp_context_items_dispose(citems); return FALSE; } if (!ContextItemToAppContext(citems, buf, len)) { km_kbp_context_items_dispose(citems); return FALSE; } km_kbp_context_items_dispose(citems); // Do we need to updated the windows engine context at this point? SendDebugMessageFormat(0, sdmKeyboard, 0, "KMGetContextCore: intermediate_context [%s]", Debug_UnicodeString(buf)); SendDebugMessageFormat(0, sdmKeyboard, 0, "KMGetContext: Exit"); return TRUE; } } extern "C" BOOL _declspec(dllexport) WINAPI KMDisplayIM(HWND hwnd, BOOL FShowAlways) { SendDebugMessageFormat(0, sdmKeyboard, 0, "KMDisplayIM: Enter"); if(hwnd == 0) return KMHideIM(); HWND hwndFocus = GetFocus(); if(hwndFocus == 0) return FALSE; if(*Globals::hwndIM() == hwnd) { *Globals::hwndIMAlways() = FShowAlways; return TRUE; } *Globals::hwndIM() = hwnd; *Globals::hwndIMAlways() = FShowAlways; POINT pt; RECT r; GetCaretPos(&pt); int n; //if(pt.x == 0 && pt.y == 0) n = SWP_NOMOVE; //else n = 0; ClientToScreen(hwndFocus, &pt); GetWindowRect(hwnd, &r); if(pt.x + r.right - r.left >= GetSystemMetrics(SM_CXSCREEN)) pt.x = GetSystemMetrics(SM_CXSCREEN) - (r.right - r.left); if(pt.y - (r.bottom-r.top) > 0) pt.y -= (r.bottom-r.top); else pt.y += 32; // guessing... SetWindowPos(hwnd, HWND_TOPMOST, pt.x,pt.y,0,0, n|SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE); SendDebugMessageFormat(0, sdmKeyboard, 0, "KMDisplayIM: Exit"); return TRUE; } extern "C" BOOL _declspec(dllexport) WINAPI KMHideIM() { SendDebugMessageFormat(0, sdmKeyboard, 0, "KMHideIM: Enter"); if(*Globals::hwndIM() != 0) { ShowWindow(*Globals::hwndIM(), SW_HIDE); //PostMessage(hwndIM, WM_USER+2134, (WPARAM) hwndIMOldFocus, 0); *Globals::hwndIM() = 0; *Globals::hwndIMAlways() = FALSE; } SendDebugMessageFormat(0, sdmKeyboard, 0, "KMHideIM: Exit"); return TRUE; } extern "C" BOOL _declspec(dllexport) WINAPI KMGetActiveKeyboard(PSTR buf, int nbuf) { SendDebugMessageFormat(0, sdmKeyboard, 0, "KMGetActiveKeyboard: Enter"); PKEYMAN64THREADDATA _td = ThreadGlobals(); if(!_td) return FALSE; if(!_td->lpActiveKeyboard) return FALSE; strncpy_s(buf, nbuf, _td->lpActiveKeyboard->Name, nbuf-1); buf[nbuf-1] = 0; SendDebugMessageFormat(0, sdmKeyboard, 0, "KMGetActiveKeyboard: Exit"); return TRUE; } extern "C" BOOL _declspec(dllexport) WINAPI KMGetKeyboardPath(PSTR keyboardname, PSTR buf, int nbuf) { SendDebugMessageFormat(0, sdmKeyboard, 0, "KMGetKeyboardPath: Enter&Exit"); return GetKeyboardFileName(keyboardname, buf, nbuf); } void KMUpdateIM() { SendDebugMessageFormat(0, sdmKeyboard, 0, "KMUpdateIM: Enter"); if(*Globals::hwndIM() != 0) { ShowWindow(*Globals::hwndIM(), SW_HIDE); //PostMessage(hwndIM, WM_USER+2134, (WPARAM) hwndIMOldFocus, 0); *Globals::hwndIM() = 0; *Globals::hwndIMAlways() = FALSE; } SendDebugMessageFormat(0, sdmKeyboard, 0, "KMUpdateIM: Exit"); } BOOL IsIMWindow(HWND hwnd) { if(hwnd == *Globals::hwndIM()) return TRUE; if(!*Globals::hwndIM()) return FALSE; return IsChild(*Globals::hwndIM(), hwnd); } //------- All the functions bellow are used for interaction with the core processor. /* Add a dll hook function to the list of hook functions associated with a single dll */ static BOOL AddIMDLLHookCore(LPIMDLL imd, LPSTR funcname, DWORD storeno) { /* Get the procedure address for the function */ SendDebugMessageFormat(0, sdmKeyboard, 0, "AddIMDLLHookCore: Enter"); IMDLLHOOKProc dhp = (IMDLLHOOKProc)GetProcAddress(imd->hModule, funcname); if (!dhp) return FALSE; /* Add the function to the list of functions in the DLL */ LPIMDLLHOOK hooks = new IMDLLHOOK[imd->nHooks + 1]; if (imd->nHooks > 0) { memcpy(hooks, imd->Hooks, sizeof(IMDLLHOOK) * imd->nHooks); delete imd->Hooks; } imd->Hooks = hooks; strncpy(imd->Hooks[imd->nHooks].name, funcname, 31); imd->Hooks[imd->nHooks].name[31] = 0; imd->Hooks[imd->nHooks].storeno = storeno; imd->Hooks[imd->nHooks].function = dhp; imd->nHooks++; SendDebugMessageFormat( 0, sdmKeyboard, 0, "AddIMDLLHookCore: nHooks count [%lu] unique [%lu]", imd->nHooks, imd->Hooks[imd->nHooks-1].storeno); SendDebugMessageFormat(0, sdmKeyboard, 0, "AddIMDLLHookCore: Exit"); return TRUE; } /* Load the dlls associated with a keyboard */ BOOL LoadDLLsCore(LPINTKEYBOARDINFO lpkbi) { char fullname[_MAX_PATH]; SendDebugMessageFormat(0, sdmKeyboard, 0, "LoadDLLsCore: Enter"); if (lpkbi->nIMDLLs > 0) if (!UnloadDLLs(lpkbi)) return FALSE; if (!GetKeyboardFileName(lpkbi->Name, fullname, _MAX_PATH)) return FALSE; if ((!lpkbi->lpCoreKeyboard) || (!lpkbi->lpCoreKeyboard)){ return FALSE; } km_kbp_keyboard_imx *imx_list = lpkbi->lpIMXList; BOOL result = false; for (; imx_list->library_name; ++imx_list) { // maybe need to check if copy string SendDebugMessageFormat(0, sdmKeyboard, 0, "LoadDLLsCore: Library name %s", wstrtostr(reinterpret_cast(imx_list->library_name))); SendDebugMessageFormat(0, sdmKeyboard, 0, "LoadDLLsCore: Function name %s", wstrtostr(reinterpret_cast(imx_list->function_name))); // dummy line LPIMDLL imd = AddIMDLL(lpkbi, fullname, wstrtostr(reinterpret_cast(imx_list->library_name))); if (imd && AddIMDLLHookCore(imd, wstrtostr(reinterpret_cast(imx_list->function_name)), imx_list->store_no)) { result = TRUE; } // log ok //else // log error } // If result is true register a callback with the core if (result) { SendDebugMessageFormat(0, sdmKeyboard, 0, "LoadDLLsCore: register core callback"); //int *test_array = new int[20]; //test_array[1] = 60; //test_array[8] = 80; km_kbp_state_imx_register_callback(lpkbi->lpCoreKeyboardState, IM_CallBackCore, (void *)lpkbi); //km_kbp_state_imx_register_callback(lpkbi->lpCoreKeyboardState, IM_CallBackCore, (void *)&test_array); } SendDebugMessageFormat(0, sdmKeyboard, 0, "LoadDLLsCore: Exit"); return TRUE; }