Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmsctf.c
Go to the documentation of this file.
00001 /* 00002 * MSCTF Server DLL 00003 * 00004 * Copyright 2008 Aric Stewart, CodeWeavers 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 */ 00020 00021 #include "config.h" 00022 00023 #include <stdarg.h> 00024 #include <stdio.h> 00025 00026 #define COBJMACROS 00027 00028 #include "wine/debug.h" 00029 #include "wine/list.h" 00030 #include "windef.h" 00031 #include "winbase.h" 00032 #include "winreg.h" 00033 #include "shlwapi.h" 00034 #include "shlguid.h" 00035 #include "comcat.h" 00036 #include "rpcproxy.h" 00037 #include "msctf.h" 00038 00039 #include "msctf_internal.h" 00040 00041 WINE_DEFAULT_DEBUG_CHANNEL(msctf); 00042 00043 static LONG MSCTF_refCount; 00044 00045 static HINSTANCE MSCTF_hinstance; 00046 00047 typedef struct 00048 { 00049 DWORD id; 00050 DWORD magic; 00051 LPVOID data; 00052 } CookieInternal; 00053 00054 typedef struct { 00055 TF_LANGUAGEPROFILE LanguageProfile; 00056 ITfTextInputProcessor *pITfTextInputProcessor; 00057 ITfThreadMgr *pITfThreadMgr; 00058 ITfKeyEventSink *pITfKeyEventSink; 00059 TfClientId tid; 00060 } ActivatedTextService; 00061 00062 typedef struct 00063 { 00064 struct list entry; 00065 ActivatedTextService *ats; 00066 } AtsEntry; 00067 00068 static CookieInternal *cookies; 00069 static UINT id_last; 00070 static UINT array_size; 00071 00072 static struct list AtsList = LIST_INIT(AtsList); 00073 static UINT activated = 0; 00074 00075 DWORD tlsIndex = 0; 00076 TfClientId processId = 0; 00077 ITfCompartmentMgr *globalCompartmentMgr = NULL; 00078 00079 const WCHAR szwSystemTIPKey[] = {'S','O','F','T','W','A','R','E','\\','M','i','c','r','o','s','o','f','t','\\','C','T','F','\\','T','I','P',0}; 00080 const WCHAR szwSystemCTFKey[] = {'S','O','F','T','W','A','R','E','\\','M','i','c','r','o','s','o','f','t','\\','C','T','F',0}; 00081 00082 typedef HRESULT (*LPFNCONSTRUCTOR)(IUnknown *pUnkOuter, IUnknown **ppvOut); 00083 00084 static const struct { 00085 REFCLSID clsid; 00086 LPFNCONSTRUCTOR ctor; 00087 } ClassesTable[] = { 00088 {&CLSID_TF_ThreadMgr, ThreadMgr_Constructor}, 00089 {&CLSID_TF_InputProcessorProfiles, InputProcessorProfiles_Constructor}, 00090 {&CLSID_TF_CategoryMgr, CategoryMgr_Constructor}, 00091 {&CLSID_TF_LangBarMgr, LangBarMgr_Constructor}, 00092 {&CLSID_TF_DisplayAttributeMgr, DisplayAttributeMgr_Constructor}, 00093 {NULL, NULL} 00094 }; 00095 00096 typedef struct tagClassFactory 00097 { 00098 IClassFactory IClassFactory_iface; 00099 LONG ref; 00100 LPFNCONSTRUCTOR ctor; 00101 } ClassFactory; 00102 00103 static inline ClassFactory *impl_from_IClassFactory(IClassFactory *iface) 00104 { 00105 return CONTAINING_RECORD(iface, ClassFactory, IClassFactory_iface); 00106 } 00107 00108 static void ClassFactory_Destructor(ClassFactory *This) 00109 { 00110 TRACE("Destroying class factory %p\n", This); 00111 HeapFree(GetProcessHeap(),0,This); 00112 MSCTF_refCount--; 00113 } 00114 00115 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *ppvOut) 00116 { 00117 *ppvOut = NULL; 00118 if (IsEqualIID(riid, &IID_IClassFactory) || IsEqualIID(riid, &IID_IUnknown)) { 00119 IClassFactory_AddRef(iface); 00120 *ppvOut = iface; 00121 return S_OK; 00122 } 00123 00124 WARN("Unknown interface %s\n", debugstr_guid(riid)); 00125 return E_NOINTERFACE; 00126 } 00127 00128 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface) 00129 { 00130 ClassFactory *This = impl_from_IClassFactory(iface); 00131 return InterlockedIncrement(&This->ref); 00132 } 00133 00134 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface) 00135 { 00136 ClassFactory *This = impl_from_IClassFactory(iface); 00137 ULONG ret = InterlockedDecrement(&This->ref); 00138 00139 if (ret == 0) 00140 ClassFactory_Destructor(This); 00141 return ret; 00142 } 00143 00144 static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *punkOuter, REFIID iid, LPVOID *ppvOut) 00145 { 00146 ClassFactory *This = impl_from_IClassFactory(iface); 00147 HRESULT ret; 00148 IUnknown *obj; 00149 00150 TRACE("(%p, %p, %s, %p)\n", iface, punkOuter, debugstr_guid(iid), ppvOut); 00151 ret = This->ctor(punkOuter, &obj); 00152 if (FAILED(ret)) 00153 return ret; 00154 ret = IUnknown_QueryInterface(obj, iid, ppvOut); 00155 IUnknown_Release(obj); 00156 return ret; 00157 } 00158 00159 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL fLock) 00160 { 00161 ClassFactory *This = impl_from_IClassFactory(iface); 00162 00163 TRACE("(%p)->(%x)\n", This, fLock); 00164 00165 if(fLock) 00166 InterlockedIncrement(&MSCTF_refCount); 00167 else 00168 InterlockedDecrement(&MSCTF_refCount); 00169 00170 return S_OK; 00171 } 00172 00173 static const IClassFactoryVtbl ClassFactoryVtbl = { 00174 /* IUnknown */ 00175 ClassFactory_QueryInterface, 00176 ClassFactory_AddRef, 00177 ClassFactory_Release, 00178 00179 /* IClassFactory*/ 00180 ClassFactory_CreateInstance, 00181 ClassFactory_LockServer 00182 }; 00183 00184 static HRESULT ClassFactory_Constructor(LPFNCONSTRUCTOR ctor, LPVOID *ppvOut) 00185 { 00186 ClassFactory *This = HeapAlloc(GetProcessHeap(),0,sizeof(ClassFactory)); 00187 This->IClassFactory_iface.lpVtbl = &ClassFactoryVtbl; 00188 This->ref = 1; 00189 This->ctor = ctor; 00190 *ppvOut = This; 00191 TRACE("Created class factory %p\n", This); 00192 MSCTF_refCount++; 00193 return S_OK; 00194 } 00195 00196 /************************************************************************* 00197 * DWORD Cookie Management 00198 */ 00199 DWORD generate_Cookie(DWORD magic, LPVOID data) 00200 { 00201 int i; 00202 00203 /* try to reuse IDs if possible */ 00204 for (i = 0; i < id_last; i++) 00205 if (cookies[i].id == 0) break; 00206 00207 if (i == array_size) 00208 { 00209 if (!array_size) 00210 { 00211 cookies = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(CookieInternal) * 10); 00212 if (!cookies) 00213 { 00214 ERR("Out of memory, Unable to alloc cookies array\n"); 00215 return 0; 00216 } 00217 array_size = 10; 00218 } 00219 else 00220 { 00221 CookieInternal *new_cookies = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cookies, 00222 sizeof(CookieInternal) * (array_size * 2)); 00223 if (!new_cookies) 00224 { 00225 ERR("Out of memory, Unable to realloc cookies array\n"); 00226 return 0; 00227 } 00228 cookies = new_cookies; 00229 array_size *= 2; 00230 } 00231 } 00232 00233 cookies[i].id = i + 1; /* a return of 0 is used for failure */ 00234 cookies[i].magic = magic; 00235 cookies[i].data = data; 00236 00237 if (i == id_last) 00238 id_last++; 00239 00240 return cookies[i].id; 00241 } 00242 00243 DWORD get_Cookie_magic(DWORD id) 00244 { 00245 UINT index = id - 1; 00246 00247 if (index >= id_last) 00248 return 0; 00249 00250 if (cookies[index].id == 0) 00251 return 0; 00252 00253 return cookies[index].magic; 00254 } 00255 00256 LPVOID get_Cookie_data(DWORD id) 00257 { 00258 UINT index = id - 1; 00259 00260 if (index >= id_last) 00261 return NULL; 00262 00263 if (cookies[index].id == 0) 00264 return NULL; 00265 00266 return cookies[index].data; 00267 } 00268 00269 LPVOID remove_Cookie(DWORD id) 00270 { 00271 UINT index = id - 1; 00272 00273 if (index >= id_last) 00274 return NULL; 00275 00276 if (cookies[index].id == 0) 00277 return NULL; 00278 00279 cookies[index].id = 0; 00280 return cookies[index].data; 00281 } 00282 00283 DWORD enumerate_Cookie(DWORD magic, DWORD *index) 00284 { 00285 int i; 00286 for (i = *index; i < id_last; i++) 00287 if (cookies[i].id != 0 && cookies[i].magic == magic) 00288 { 00289 *index = (i+1); 00290 return cookies[i].id; 00291 } 00292 return 0x0; 00293 } 00294 00295 /***************************************************************************** 00296 * Active Text Service Management 00297 *****************************************************************************/ 00298 static HRESULT activate_given_ts(ActivatedTextService *actsvr, ITfThreadMgr* tm) 00299 { 00300 HRESULT hr; 00301 00302 /* Already Active? */ 00303 if (actsvr->pITfTextInputProcessor) 00304 return S_OK; 00305 00306 hr = CoCreateInstance (&actsvr->LanguageProfile.clsid, NULL, CLSCTX_INPROC_SERVER, 00307 &IID_ITfTextInputProcessor, (void**)&actsvr->pITfTextInputProcessor); 00308 if (FAILED(hr)) return hr; 00309 00310 hr = ITfTextInputProcessor_Activate(actsvr->pITfTextInputProcessor, tm, actsvr->tid); 00311 if (FAILED(hr)) 00312 { 00313 ITfTextInputProcessor_Release(actsvr->pITfTextInputProcessor); 00314 actsvr->pITfTextInputProcessor = NULL; 00315 return hr; 00316 } 00317 00318 actsvr->pITfThreadMgr = tm; 00319 ITfThreadMgr_AddRef(tm); 00320 return hr; 00321 } 00322 00323 static HRESULT deactivate_given_ts(ActivatedTextService *actsvr) 00324 { 00325 HRESULT hr = S_OK; 00326 00327 if (actsvr->pITfTextInputProcessor) 00328 { 00329 hr = ITfTextInputProcessor_Deactivate(actsvr->pITfTextInputProcessor); 00330 ITfTextInputProcessor_Release(actsvr->pITfTextInputProcessor); 00331 ITfThreadMgr_Release(actsvr->pITfThreadMgr); 00332 actsvr->pITfTextInputProcessor = NULL; 00333 actsvr->pITfThreadMgr = NULL; 00334 } 00335 00336 return hr; 00337 } 00338 00339 static void deactivate_remove_conflicting_ts(REFCLSID catid) 00340 { 00341 AtsEntry *ats, *cursor2; 00342 00343 LIST_FOR_EACH_ENTRY_SAFE(ats, cursor2, &AtsList, AtsEntry, entry) 00344 { 00345 if (IsEqualCLSID(catid,&ats->ats->LanguageProfile.catid)) 00346 { 00347 deactivate_given_ts(ats->ats); 00348 list_remove(&ats->entry); 00349 HeapFree(GetProcessHeap(),0,ats->ats); 00350 HeapFree(GetProcessHeap(),0,ats); 00351 /* we are guarenteeing there is only 1 */ 00352 break; 00353 } 00354 } 00355 } 00356 00357 HRESULT add_active_textservice(TF_LANGUAGEPROFILE *lp) 00358 { 00359 ActivatedTextService *actsvr; 00360 ITfCategoryMgr *catmgr; 00361 AtsEntry *entry; 00362 ITfThreadMgr *tm = TlsGetValue(tlsIndex); 00363 ITfClientId *clientid; 00364 00365 if (!tm) return E_UNEXPECTED; 00366 00367 actsvr = HeapAlloc(GetProcessHeap(),0,sizeof(ActivatedTextService)); 00368 if (!actsvr) return E_OUTOFMEMORY; 00369 00370 ITfThreadMgr_QueryInterface(tm,&IID_ITfClientId,(LPVOID)&clientid); 00371 ITfClientId_GetClientId(clientid, &lp->clsid, &actsvr->tid); 00372 ITfClientId_Release(clientid); 00373 00374 if (!actsvr->tid) 00375 { 00376 HeapFree(GetProcessHeap(),0,actsvr); 00377 return E_OUTOFMEMORY; 00378 } 00379 00380 actsvr->pITfTextInputProcessor = NULL; 00381 actsvr->LanguageProfile = *lp; 00382 actsvr->LanguageProfile.fActive = TRUE; 00383 actsvr->pITfKeyEventSink = NULL; 00384 00385 /* get TIP category */ 00386 if (SUCCEEDED(CategoryMgr_Constructor(NULL,(IUnknown**)&catmgr))) 00387 { 00388 static const GUID *list[3] = {&GUID_TFCAT_TIP_SPEECH, &GUID_TFCAT_TIP_KEYBOARD, &GUID_TFCAT_TIP_HANDWRITING}; 00389 00390 ITfCategoryMgr_FindClosestCategory(catmgr, 00391 &actsvr->LanguageProfile.clsid, &actsvr->LanguageProfile.catid, 00392 list, 3); 00393 00394 ITfCategoryMgr_Release(catmgr); 00395 } 00396 else 00397 { 00398 ERR("CategoryMgr construction failed\n"); 00399 actsvr->LanguageProfile.catid = GUID_NULL; 00400 } 00401 00402 if (!IsEqualGUID(&actsvr->LanguageProfile.catid,&GUID_NULL)) 00403 deactivate_remove_conflicting_ts(&actsvr->LanguageProfile.catid); 00404 00405 if (activated > 0) 00406 activate_given_ts(actsvr, tm); 00407 00408 entry = HeapAlloc(GetProcessHeap(),0,sizeof(AtsEntry)); 00409 00410 if (!entry) 00411 { 00412 HeapFree(GetProcessHeap(),0,actsvr); 00413 return E_OUTOFMEMORY; 00414 } 00415 00416 entry->ats = actsvr; 00417 list_add_head(&AtsList, &entry->entry); 00418 00419 return S_OK; 00420 } 00421 00422 BOOL get_active_textservice(REFCLSID rclsid, TF_LANGUAGEPROFILE *profile) 00423 { 00424 AtsEntry *ats; 00425 00426 LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry) 00427 { 00428 if (IsEqualCLSID(rclsid,&ats->ats->LanguageProfile.clsid)) 00429 { 00430 if (profile) 00431 *profile = ats->ats->LanguageProfile; 00432 return TRUE; 00433 } 00434 } 00435 return FALSE; 00436 } 00437 00438 HRESULT activate_textservices(ITfThreadMgr *tm) 00439 { 00440 HRESULT hr = S_OK; 00441 AtsEntry *ats; 00442 00443 activated ++; 00444 if (activated > 1) 00445 return S_OK; 00446 00447 LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry) 00448 { 00449 hr = activate_given_ts(ats->ats, tm); 00450 if (FAILED(hr)) 00451 FIXME("Failed to activate text service\n"); 00452 } 00453 return hr; 00454 } 00455 00456 HRESULT deactivate_textservices(void) 00457 { 00458 AtsEntry *ats; 00459 00460 if (activated > 0) 00461 activated --; 00462 00463 if (activated == 0) 00464 LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry) 00465 deactivate_given_ts(ats->ats); 00466 00467 return S_OK; 00468 } 00469 00470 CLSID get_textservice_clsid(TfClientId tid) 00471 { 00472 AtsEntry *ats; 00473 00474 LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry) 00475 if (ats->ats->tid == tid) 00476 return ats->ats->LanguageProfile.clsid; 00477 return GUID_NULL; 00478 } 00479 00480 HRESULT get_textservice_sink(TfClientId tid, REFCLSID iid, IUnknown **sink) 00481 { 00482 AtsEntry *ats; 00483 00484 if (!IsEqualCLSID(iid,&IID_ITfKeyEventSink)) 00485 return E_NOINTERFACE; 00486 00487 LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry) 00488 if (ats->ats->tid == tid) 00489 { 00490 *sink = (IUnknown*)ats->ats->pITfKeyEventSink; 00491 return S_OK; 00492 } 00493 00494 return E_FAIL; 00495 } 00496 00497 HRESULT set_textservice_sink(TfClientId tid, REFCLSID iid, IUnknown* sink) 00498 { 00499 AtsEntry *ats; 00500 00501 if (!IsEqualCLSID(iid,&IID_ITfKeyEventSink)) 00502 return E_NOINTERFACE; 00503 00504 LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry) 00505 if (ats->ats->tid == tid) 00506 { 00507 ats->ats->pITfKeyEventSink = (ITfKeyEventSink*)sink; 00508 return S_OK; 00509 } 00510 00511 return E_FAIL; 00512 } 00513 00514 /************************************************************************* 00515 * MSCTF DllMain 00516 */ 00517 BOOL WINAPI DllMain(HINSTANCE hinst, DWORD fdwReason, LPVOID fImpLoad) 00518 { 00519 TRACE("%p 0x%x %p\n", hinst, fdwReason, fImpLoad); 00520 switch (fdwReason) 00521 { 00522 case DLL_WINE_PREATTACH: 00523 return FALSE; /* prefer native version */ 00524 case DLL_PROCESS_ATTACH: 00525 MSCTF_hinstance = hinst; 00526 tlsIndex = TlsAlloc(); 00527 break; 00528 case DLL_PROCESS_DETACH: 00529 TlsFree(tlsIndex); 00530 break; 00531 } 00532 return TRUE; 00533 } 00534 00535 /************************************************************************* 00536 * DllCanUnloadNow (MSCTF.@) 00537 */ 00538 HRESULT WINAPI DllCanUnloadNow(void) 00539 { 00540 return MSCTF_refCount ? S_FALSE : S_OK; 00541 } 00542 00543 /*********************************************************************** 00544 * DllGetClassObject (MSCTF.@) 00545 */ 00546 HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID iid, LPVOID *ppvOut) 00547 { 00548 int i; 00549 00550 *ppvOut = NULL; 00551 if (!IsEqualIID(iid, &IID_IUnknown) && !IsEqualIID(iid, &IID_IClassFactory)) 00552 return E_NOINTERFACE; 00553 00554 for (i = 0; ClassesTable[i].clsid != NULL; i++) 00555 if (IsEqualCLSID(ClassesTable[i].clsid, clsid)) { 00556 return ClassFactory_Constructor(ClassesTable[i].ctor, ppvOut); 00557 } 00558 FIXME("CLSID %s not supported\n", debugstr_guid(clsid)); 00559 return CLASS_E_CLASSNOTAVAILABLE; 00560 } 00561 00562 /*********************************************************************** 00563 * DllRegisterServer (MSCTF.@) 00564 */ 00565 HRESULT WINAPI DllRegisterServer(void) 00566 { 00567 return __wine_register_resources( MSCTF_hinstance ); 00568 } 00569 00570 /*********************************************************************** 00571 * DllUnregisterServer (MSCTF.@) 00572 */ 00573 HRESULT WINAPI DllUnregisterServer(void) 00574 { 00575 return __wine_unregister_resources( MSCTF_hinstance ); 00576 } 00577 00578 /*********************************************************************** 00579 * TF_CreateThreadMgr (MSCTF.@) 00580 */ 00581 HRESULT WINAPI TF_CreateThreadMgr(ITfThreadMgr **pptim) 00582 { 00583 TRACE("\n"); 00584 return ThreadMgr_Constructor(NULL,(IUnknown**)pptim); 00585 } 00586 00587 /*********************************************************************** 00588 * TF_GetThreadMgr (MSCTF.@) 00589 */ 00590 HRESULT WINAPI TF_GetThreadMgr(ITfThreadMgr **pptim) 00591 { 00592 TRACE("\n"); 00593 *pptim = TlsGetValue(tlsIndex); 00594 00595 if (*pptim) 00596 ITfThreadMgr_AddRef(*pptim); 00597 00598 return S_OK; 00599 } 00600 00601 /*********************************************************************** 00602 * SetInputScope(MSCTF.@) 00603 */ 00604 HRESULT WINAPI SetInputScope(HWND hwnd, INT inputscope) 00605 { 00606 FIXME("STUB: %p %i\n",hwnd,inputscope); 00607 return S_OK; 00608 } 00609 00610 /*********************************************************************** 00611 * SetInputScopes(MSCTF.@) 00612 */ 00613 HRESULT WINAPI SetInputScopes(HWND hwnd, const INT *pInputScopes, 00614 UINT cInputScopes, WCHAR **ppszPhraseList, 00615 UINT cPhrases, WCHAR *pszRegExp, WCHAR *pszSRGS) 00616 { 00617 int i; 00618 FIXME("STUB: %p ... %s %s\n",hwnd, debugstr_w(pszRegExp), debugstr_w(pszSRGS)); 00619 for (i = 0; i < cInputScopes; i++) 00620 TRACE("\tScope[%i] = %i\n",i,pInputScopes[i]); 00621 for (i = 0; i < cPhrases; i++) 00622 TRACE("\tPhrase[%i] = %s\n",i,debugstr_w(ppszPhraseList[i])); 00623 00624 return S_OK; 00625 } 00626 00627 /*********************************************************************** 00628 * TF_CreateInputProcessorProfiles(MSCTF.@) 00629 */ 00630 HRESULT WINAPI TF_CreateInputProcessorProfiles( 00631 ITfInputProcessorProfiles **ppipr) 00632 { 00633 return InputProcessorProfiles_Constructor(NULL,(IUnknown**)ppipr); 00634 } 00635 00636 /*********************************************************************** 00637 * TF_InvalidAssemblyListCacheIfExist(MSCTF.@) 00638 */ 00639 HRESULT WINAPI TF_InvalidAssemblyListCacheIfExist(void) 00640 { 00641 FIXME("Stub\n"); 00642 return S_OK; 00643 } 00644 00645 /*********************************************************************** 00646 * TF_CreateLangBarMgr (MSCTF.@) 00647 */ 00648 HRESULT WINAPI TF_CreateLangBarMgr(ITfLangBarMgr **pppbm) 00649 { 00650 TRACE("\n"); 00651 return LangBarMgr_Constructor(NULL,(IUnknown**)pppbm); 00652 } Generated on Sun May 27 2012 04:24:50 for ReactOS by
1.7.6.1
|