ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

msctf.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.