- Sync msctf, mlang, inetmib1, inetcomm with Wine 1.1.22

svn path=/trunk/; revision=41065
This commit is contained in:
Dmitry Chapyshev 2009-05-23 10:31:01 +00:00
parent 05625d8565
commit 2607d66f40
11 changed files with 934 additions and 56 deletions

View File

@ -732,7 +732,7 @@ static HRESULT WINAPI SMTPTransport_CommandMAIL(ISMTPTransport2 *iface, LPSTR ps
SMTPTransport *This = (SMTPTransport *)iface;
const char szCommandFormat[] = "MAIL FROM: <%s>\n";
char *szCommand;
int len = sizeof(szCommandFormat) - 2 /* "%s" */ + strlen(pszEmailFrom);
int len;
HRESULT hr;
TRACE("(%s)\n", debugstr_a(pszEmailFrom));
@ -740,6 +740,7 @@ static HRESULT WINAPI SMTPTransport_CommandMAIL(ISMTPTransport2 *iface, LPSTR ps
if (!pszEmailFrom)
return E_INVALIDARG;
len = sizeof(szCommandFormat) - 2 /* "%s" */ + strlen(pszEmailFrom);
szCommand = HeapAlloc(GetProcessHeap(), 0, len);
if (!szCommand)
return E_OUTOFMEMORY;
@ -758,7 +759,7 @@ static HRESULT WINAPI SMTPTransport_CommandRCPT(ISMTPTransport2 *iface, LPSTR ps
SMTPTransport *This = (SMTPTransport *)iface;
const char szCommandFormat[] = "RCPT TO: <%s>\n";
char *szCommand;
int len = sizeof(szCommandFormat) - 2 /* "%s" */ + strlen(pszEmailTo);
int len;
HRESULT hr;
TRACE("(%s)\n", debugstr_a(pszEmailTo));
@ -766,6 +767,7 @@ static HRESULT WINAPI SMTPTransport_CommandRCPT(ISMTPTransport2 *iface, LPSTR ps
if (!pszEmailTo)
return E_INVALIDARG;
len = sizeof(szCommandFormat) - 2 /* "%s" */ + strlen(pszEmailTo);
szCommand = HeapAlloc(GetProcessHeap(), 0, len);
if (!szCommand)
return E_OUTOFMEMORY;
@ -833,7 +835,7 @@ static HRESULT WINAPI SMTPTransport_CommandAUTH(ISMTPTransport2 *iface,
SMTPTransport *This = (SMTPTransport *)iface;
const char szCommandFormat[] = "AUTH %s\n";
char *szCommand;
int len = sizeof(szCommandFormat) - 2 /* "%s" */ + strlen(pszAuthType);
int len;
HRESULT hr;
TRACE("(%s)\n", debugstr_a(pszAuthType));
@ -841,6 +843,7 @@ static HRESULT WINAPI SMTPTransport_CommandAUTH(ISMTPTransport2 *iface,
if (!pszAuthType)
return E_INVALIDARG;
len = sizeof(szCommandFormat) - 2 /* "%s" */ + strlen(pszAuthType);
szCommand = HeapAlloc(GetProcessHeap(), 0, len);
if (!szCommand)
return E_OUTOFMEMORY;

View File

@ -143,7 +143,10 @@ static BOOL mib2IfNumberQuery(BYTE bPduType, SnmpVarBind *pVarBind,
copyInt(&pVarBind->value, &numIfs);
if (bPduType == SNMP_PDU_GETNEXT)
{
SnmpUtilOidFree(&pVarBind->name);
SnmpUtilOidCpy(&pVarBind->name, &numberOid);
}
*pErrorStatus = SNMP_ERRORSTATUS_NOERROR;
}
else
@ -320,7 +323,27 @@ static DWORD oidToIpAddr(AsnObjectIdentifier *oid)
typedef void (*oidToKeyFunc)(AsnObjectIdentifier *oid, void *dst);
typedef int (*compareFunc)(const void *key, const void *value);
static UINT findValueInTable(AsnObjectIdentifier *oid,
/* Finds the first value in the table that matches key. Returns its 1-based
* index if found, or 0 if not found.
*/
static UINT findValueInTable(const void *key,
struct GenericTable *table, size_t tableEntrySize, compareFunc compare)
{
UINT index = 0;
void *value;
value = bsearch(key, table->entries, table->numEntries, tableEntrySize,
compare);
if (value)
index = ((BYTE *)value - (BYTE *)table->entries) / tableEntrySize + 1;
return index;
}
/* Finds the first value in the table that matches oid, using makeKey to
* convert the oid to a key for comparison. Returns the value's 1-based
* index if found, or 0 if not found.
*/
static UINT findOidInTable(AsnObjectIdentifier *oid,
struct GenericTable *table, size_t tableEntrySize, oidToKeyFunc makeKey,
compareFunc compare)
{
@ -329,14 +352,50 @@ static UINT findValueInTable(AsnObjectIdentifier *oid,
if (key)
{
void *value;
makeKey(oid, key);
value = bsearch(key, table->entries, table->numEntries, tableEntrySize,
compare);
if (value)
index = ((BYTE *)value - (BYTE *)table->entries) / tableEntrySize
+ 1;
index = findValueInTable(key, table, tableEntrySize, compare);
HeapFree(GetProcessHeap(), 0, key);
}
return index;
}
/* Finds the first successor to the value in the table that does matches oid,
* using makeKey to convert the oid to a key for comparison. A successor is
* a value that does not match oid, so if multiple entries match an oid, only
* the first will ever be returned using this method.
* Returns the successor's 1-based index if found, or 0 if not found.
*/
static UINT findNextOidInTable(AsnObjectIdentifier *oid,
struct GenericTable *table, size_t tableEntrySize, oidToKeyFunc makeKey,
compareFunc compare)
{
UINT index = 0;
void *key = HeapAlloc(GetProcessHeap(), 0, tableEntrySize);
if (key)
{
makeKey(oid, key);
index = findValueInTable(key, table, tableEntrySize, compare);
if (index == 0)
{
/* Not found in table. If it's less than the first entry, return
* the first index. Otherwise just return 0 and let the caller
* handle finding the successor.
*/
if (compare(key, table->entries) < 0)
index = 1;
}
else
{
/* Skip any entries that match the same key. This enumeration will
* be incomplete, but it's what Windows appears to do if there are
* multiple entries with the same index in a table, and it avoids
* an infinite loop.
*/
for (++index; index <= table->numEntries && compare(key,
&table->entries[tableEntrySize * index]) == 0; ++index)
;
}
HeapFree(GetProcessHeap(), 0, key);
}
return index;
@ -397,12 +456,12 @@ static AsnInteger32 getItemAndInstanceFromTable(AsnObjectIdentifier *oid,
}
else
{
AsnObjectIdentifier ipOid = { instanceLen,
AsnObjectIdentifier instanceOid = { instanceLen,
oid->ids + base->idLength + 1 };
*instance = findValueInTable(&ipOid, table, tableEntrySize,
makeKey, compare) + 1;
if (*instance > table->numEntries)
*instance = findNextOidInTable(&instanceOid, table,
tableEntrySize, makeKey, compare);
if (!*instance || *instance > table->numEntries)
ret = SNMP_ERRORSTATUS_NOSUCHNAME;
}
}
@ -418,10 +477,10 @@ static AsnInteger32 getItemAndInstanceFromTable(AsnObjectIdentifier *oid,
ret = SNMP_ERRORSTATUS_NOSUCHNAME;
else
{
AsnObjectIdentifier ipOid = { instanceLen,
AsnObjectIdentifier instanceOid = { instanceLen,
oid->ids + base->idLength + 1 };
*instance = findValueInTable(&ipOid, table, tableEntrySize,
*instance = findOidInTable(&instanceOid, table, tableEntrySize,
makeKey, compare);
if (!*instance)
ret = SNMP_ERRORSTATUS_NOSUCHNAME;
@ -440,6 +499,7 @@ static INT setOidWithItem(AsnObjectIdentifier *dst, AsnObjectIdentifier *base,
AsnObjectIdentifier oid;
INT ret;
SnmpUtilOidFree(dst);
ret = SnmpUtilOidCpy(dst, base);
if (ret)
{
@ -1311,7 +1371,7 @@ BOOL WINAPI SnmpExtensionQuery(BYTE bPduType, SnmpVarBindList *pVarBindList,
* so we have to continue until an implementation handles the
* query or we exhaust the table of supported OIDs.
*/
for (; error == SNMP_ERRORSTATUS_NOSUCHNAME &&
for (matchingIndex++; error == SNMP_ERRORSTATUS_NOSUCHNAME &&
matchingIndex < DEFINE_SIZEOF(supportedIDs);
matchingIndex++)
{

View File

@ -1939,7 +1939,7 @@ static HRESULT WINAPI fnIMLangFontLink_GetStrCodePages(
}
if (pdwCodePages) *pdwCodePages = cps;
if (pcchCodePages) *pcchCodePages = i;
if (pcchCodePages) *pcchCodePages = min( i + 1, cchSrc );
return S_OK;
}

View File

@ -58,14 +58,24 @@ typedef struct tagContextSink {
typedef struct tagContext {
const ITfContextVtbl *ContextVtbl;
const ITfSourceVtbl *SourceVtbl;
/* const ITfContextCompositionVtbl *ContextCompositionVtbl; */
/* const ITfContextOwnerCompositionServicesVtbl *ContextOwnerCompositionServicesVtbl; */
/* const ITfContextOwnerServicesVtbl *ContextOwnerServicesVtbl; */
/* const ITfInsertAtSelectionVtbl *InsertAtSelectionVtbl; */
/* const ITfMouseTrackerVtbl *MouseTrackerVtbl; */
/* const ITfQueryEmbeddedVtbl *QueryEmbeddedVtbl; */
/* const ITfSourceSingleVtbl *SourceSingleVtbl; */
LONG refCount;
BOOL connected;
TfClientId tidOwner;
TfEditCookie defaultCookie;
ITextStoreACP *pITextStoreACP;
ITfContextOwnerCompositionSink *pITfContextOwnerCompositionSink;
ITextStoreACPSink *pITextStoreACPSink;
ITfEditSession* currentEditSession;
/* kept as separate lists to reduce unnecessary iterations */
struct list pContextKeyEventSink;
@ -76,9 +86,14 @@ typedef struct tagContext {
} Context;
typedef struct tagEditCookie {
DWORD lockType;
Context *pOwningContext;
} EditCookie;
typedef struct tagTextStoreACPSink {
const ITextStoreACPSinkVtbl *TextStoreACPSinkVtbl;
/* const ITextStoreACPServicesVtbl *TextStoreACPServicesVtbl; */
LONG refCount;
Context *pContext;
@ -101,6 +116,7 @@ static void free_sink(ContextSink *sink)
static void Context_Destructor(Context *This)
{
struct list *cursor, *cursor2;
EditCookie *cookie;
TRACE("destroying %p\n", This);
if (This->pITextStoreACPSink)
@ -115,6 +131,13 @@ static void Context_Destructor(Context *This)
if (This->pITfContextOwnerCompositionSink)
ITextStoreACPSink_Release(This->pITfContextOwnerCompositionSink);
if (This->defaultCookie)
{
cookie = remove_Cookie(This->defaultCookie);
HeapFree(GetProcessHeap(),0,cookie);
This->defaultCookie = 0;
}
LIST_FOR_EACH_SAFE(cursor, cursor2, &This->pContextKeyEventSink)
{
ContextSink* sink = LIST_ENTRY(cursor,ContextSink,entry);
@ -197,9 +220,53 @@ static HRESULT WINAPI Context_RequestEditSession (ITfContext *iface,
TfClientId tid, ITfEditSession *pes, DWORD dwFlags,
HRESULT *phrSession)
{
HRESULT hr;
Context *This = (Context *)iface;
FIXME("STUB:(%p)\n",This);
return E_NOTIMPL;
DWORD dwLockFlags = 0x0;
TS_STATUS status;
TRACE("(%p) %i %p %x %p\n",This, tid, pes, dwFlags, phrSession);
if (!(dwFlags & TF_ES_READ) && !(dwFlags & TF_ES_READWRITE))
{
*phrSession = E_FAIL;
return E_INVALIDARG;
}
if (!This->pITextStoreACP)
{
FIXME("No ITextStoreACP avaliable\n");
*phrSession = E_FAIL;
return E_FAIL;
}
if (!(dwFlags & TF_ES_ASYNC))
dwLockFlags |= TS_LF_SYNC;
if ((dwFlags & TF_ES_READWRITE) == TF_ES_READWRITE)
dwLockFlags |= TS_LF_READWRITE;
else if (dwFlags & TF_ES_READ)
dwLockFlags |= TS_LF_READ;
/* TODO: cache this */
ITextStoreACP_GetStatus(This->pITextStoreACP, &status);
if (((dwFlags & TF_ES_READWRITE) == TF_ES_READWRITE) && (status.dwDynamicFlags & TS_SD_READONLY))
{
*phrSession = TS_E_READONLY;
return S_OK;
}
if (FAILED (ITfEditSession_QueryInterface(pes, &IID_ITfEditSession, (LPVOID*)&This->currentEditSession)))
{
*phrSession = E_FAIL;
return E_INVALIDARG;
}
hr = ITextStoreACP_RequestLock(This->pITextStoreACP, dwLockFlags, phrSession);
return hr;
}
static HRESULT WINAPI Context_InWriteSession (ITfContext *iface,
@ -216,8 +283,59 @@ static HRESULT WINAPI Context_GetSelection (ITfContext *iface,
TF_SELECTION *pSelection, ULONG *pcFetched)
{
Context *This = (Context *)iface;
FIXME("STUB:(%p)\n",This);
return E_NOTIMPL;
EditCookie *cookie;
ULONG count, i;
ULONG totalFetched = 0;
HRESULT hr = S_OK;
if (!pSelection || !pcFetched)
return E_INVALIDARG;
*pcFetched = 0;
if (!This->connected)
return TF_E_DISCONNECTED;
if (get_Cookie_magic(ec)!=COOKIE_MAGIC_EDITCOOKIE)
return TF_E_NOLOCK;
if (!This->pITextStoreACP)
{
FIXME("Context does not have a ITextStoreACP\n");
return E_NOTIMPL;
}
cookie = get_Cookie_data(ec);
if (ulIndex == TF_DEFAULT_SELECTION)
count = 1;
else
count = ulCount;
for (i = 0; i < count; i++)
{
DWORD fetched;
TS_SELECTION_ACP acps;
hr = ITextStoreACP_GetSelection(This->pITextStoreACP, ulIndex + i,
1, &acps, &fetched);
if (hr == TS_E_NOLOCK)
return TF_E_NOLOCK;
else if (SUCCEEDED(hr))
{
pSelection[totalFetched].style.ase = acps.style.ase;
pSelection[totalFetched].style.fInterimChar = acps.style.fInterimChar;
Range_Constructor(iface, This->pITextStoreACP, cookie->lockType, acps.acpStart, acps.acpEnd, &pSelection[totalFetched].range);
totalFetched ++;
}
else
break;
}
*pcFetched = totalFetched;
return hr;
}
static HRESULT WINAPI Context_SetSelection (ITfContext *iface,
@ -232,16 +350,53 @@ static HRESULT WINAPI Context_GetStart (ITfContext *iface,
TfEditCookie ec, ITfRange **ppStart)
{
Context *This = (Context *)iface;
FIXME("STUB:(%p)\n",This);
return E_NOTIMPL;
EditCookie *cookie;
TRACE("(%p) %i %p\n",This,ec,ppStart);
if (!ppStart)
return E_INVALIDARG;
*ppStart = NULL;
if (!This->connected)
return TF_E_DISCONNECTED;
if (get_Cookie_magic(ec)!=COOKIE_MAGIC_EDITCOOKIE)
return TF_E_NOLOCK;
cookie = get_Cookie_data(ec);
return Range_Constructor(iface, This->pITextStoreACP, cookie->lockType, 0, 0, ppStart);
}
static HRESULT WINAPI Context_GetEnd (ITfContext *iface,
TfEditCookie ec, ITfRange **ppEnd)
{
Context *This = (Context *)iface;
FIXME("STUB:(%p)\n",This);
return E_NOTIMPL;
EditCookie *cookie;
LONG end;
TRACE("(%p) %i %p\n",This,ec,ppEnd);
if (!ppEnd)
return E_INVALIDARG;
*ppEnd = NULL;
if (!This->connected)
return TF_E_DISCONNECTED;
if (get_Cookie_magic(ec)!=COOKIE_MAGIC_EDITCOOKIE)
return TF_E_NOLOCK;
if (!This->pITextStoreACP)
{
FIXME("Context does not have a ITextStoreACP\n");
return E_NOTIMPL;
}
cookie = get_Cookie_data(ec);
ITextStoreACP_GetEndACP(This->pITextStoreACP,&end);
return Range_Constructor(iface, This->pITextStoreACP, cookie->lockType, end, end, ppEnd);
}
static HRESULT WINAPI Context_GetActiveView (ITfContext *iface,
@ -376,7 +531,7 @@ static WINAPI HRESULT ContextSource_AdviseSink(ITfSource *iface,
es = HeapAlloc(GetProcessHeap(),0,sizeof(ContextSink));
if (!es)
return E_OUTOFMEMORY;
if (!SUCCEEDED(IUnknown_QueryInterface(punk, riid, (LPVOID*)&es->interfaces.pITfTextEditSink)))
if (FAILED(IUnknown_QueryInterface(punk, riid, (LPVOID *)&es->interfaces.pITfTextEditSink)))
{
HeapFree(GetProcessHeap(),0,es);
return CONNECT_E_CANNOTCONNECT;
@ -427,27 +582,34 @@ static const ITfSourceVtbl Context_SourceVtbl =
HRESULT Context_Constructor(TfClientId tidOwner, IUnknown *punk, ITfContext **ppOut, TfEditCookie *pecTextStore)
{
Context *This;
EditCookie *cookie;
This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Context));
if (This == NULL)
return E_OUTOFMEMORY;
cookie = HeapAlloc(GetProcessHeap(),0,sizeof(EditCookie));
if (cookie == NULL)
{
HeapFree(GetProcessHeap(),0,This);
return E_OUTOFMEMORY;
}
TRACE("(%p) %x %p %p %p\n",This, tidOwner, punk, ppOut, pecTextStore);
This->ContextVtbl= &Context_ContextVtbl;
This->SourceVtbl = &Context_SourceVtbl;
This->refCount = 1;
This->tidOwner = tidOwner;
This->connected = FALSE;
cookie->lockType = TF_ES_READ;
cookie->pOwningContext = This;
if (punk)
{
if (SUCCEEDED(IUnknown_QueryInterface(punk, &IID_ITextStoreACP,
(LPVOID*)&This->pITextStoreACP)))
{
if (SUCCEEDED(TextStoreACPSink_Constructor(&This->pITextStoreACPSink, This)))
ITextStoreACP_AdviseSink(This->pITextStoreACP, &IID_ITextStoreACPSink,
(IUnknown*)This->pITextStoreACPSink, TS_AS_ALL_SINKS);
}
IUnknown_QueryInterface(punk, &IID_ITextStoreACP,
(LPVOID*)&This->pITextStoreACP);
IUnknown_QueryInterface(punk, &IID_ITfContextOwnerCompositionSink,
(LPVOID*)&This->pITfContextOwnerCompositionSink);
@ -456,10 +618,8 @@ HRESULT Context_Constructor(TfClientId tidOwner, IUnknown *punk, ITfContext **pp
FIXME("Unhandled pUnk\n");
}
TRACE("returning %p\n", This);
*ppOut = (ITfContext*)This;
/* FIXME */
*pecTextStore = 0xdeaddead;
This->defaultCookie = generate_Cookie(COOKIE_MAGIC_EDITCOOKIE,cookie);
*pecTextStore = This->defaultCookie;
list_init(&This->pContextKeyEventSink);
list_init(&This->pEditTransactionSink);
@ -467,6 +627,37 @@ HRESULT Context_Constructor(TfClientId tidOwner, IUnknown *punk, ITfContext **pp
list_init(&This->pTextEditSink);
list_init(&This->pTextLayoutSink);
*ppOut = (ITfContext*)This;
TRACE("returning %p\n", This);
return S_OK;
}
HRESULT Context_Initialize(ITfContext *iface)
{
Context *This = (Context *)iface;
if (This->pITextStoreACP)
{
if (SUCCEEDED(TextStoreACPSink_Constructor(&This->pITextStoreACPSink, This)))
ITextStoreACP_AdviseSink(This->pITextStoreACP, &IID_ITextStoreACPSink,
(IUnknown*)This->pITextStoreACPSink, TS_AS_ALL_SINKS);
}
This->connected = TRUE;
return S_OK;
}
HRESULT Context_Uninitialize(ITfContext *iface)
{
Context *This = (Context *)iface;
if (This->pITextStoreACPSink)
{
ITextStoreACP_UnadviseSink(This->pITextStoreACP, (IUnknown*)This->pITextStoreACPSink);
if (ITextStoreACPSink_Release(This->pITextStoreACPSink) == 0)
This->pITextStoreACPSink = NULL;
}
This->connected = FALSE;
return S_OK;
}
@ -564,8 +755,36 @@ static HRESULT WINAPI TextStoreACPSink_OnLockGranted(ITextStoreACPSink *iface,
DWORD dwLockFlags)
{
TextStoreACPSink *This = (TextStoreACPSink *)iface;
FIXME("STUB:(%p)\n",This);
return E_NOTIMPL;
HRESULT hr;
EditCookie *cookie;
TfEditCookie ec;
TRACE("(%p) %x\n",This, dwLockFlags);
if (!This->pContext || !This->pContext->currentEditSession)
{
ERR("OnLockGranted called on a context without a current edit session\n");
return E_FAIL;
}
cookie = HeapAlloc(GetProcessHeap(),0,sizeof(EditCookie));
if (!cookie)
return E_OUTOFMEMORY;
cookie->lockType = dwLockFlags;
cookie->pOwningContext = This->pContext;
ec = generate_Cookie(COOKIE_MAGIC_EDITCOOKIE, cookie);
hr = ITfEditSession_DoEditSession(This->pContext->currentEditSession, ec);
ITfEditSession_Release(This->pContext->currentEditSession);
This->pContext->currentEditSession = NULL;
/* Edit Cookie is only valid during the edit session */
cookie = remove_Cookie(ec);
HeapFree(GetProcessHeap(),0,cookie);
return hr;
}
static HRESULT WINAPI TextStoreACPSink_OnStartEditTransaction(ITextStoreACPSink *iface)

View File

@ -138,6 +138,7 @@ static HRESULT WINAPI DocumentMgr_Push(ITfDocumentMgr *iface, ITfContext *pic)
This->contextStack[0] = check;
ITfThreadMgrEventSink_OnPushContext(This->ThreadMgrSink,check);
Context_Initialize(check);
return S_OK;
}
@ -153,11 +154,13 @@ static HRESULT WINAPI DocumentMgr_Pop(ITfDocumentMgr *iface, DWORD dwFlags)
{
ITfThreadMgrEventSink_OnPopContext(This->ThreadMgrSink,This->contextStack[0]);
ITfContext_Release(This->contextStack[0]);
Context_Uninitialize(This->contextStack[0]);
}
if (This->contextStack[1])
{
ITfThreadMgrEventSink_OnPopContext(This->ThreadMgrSink,This->contextStack[1]);
ITfContext_Release(This->contextStack[1]);
Context_Uninitialize(This->contextStack[1]);
}
This->contextStack[0] = This->contextStack[1] = NULL;
ITfThreadMgrEventSink_OnUninitDocumentMgr(This->ThreadMgrSink, iface);
@ -172,6 +175,7 @@ static HRESULT WINAPI DocumentMgr_Pop(ITfDocumentMgr *iface, DWORD dwFlags)
ITfThreadMgrEventSink_OnPopContext(This->ThreadMgrSink,This->contextStack[0]);
ITfContext_Release(This->contextStack[0]);
Context_Uninitialize(This->contextStack[0]);
This->contextStack[0] = This->contextStack[1];
This->contextStack[1] = NULL;

View File

@ -32,8 +32,10 @@
#include "shlwapi.h"
#include "winerror.h"
#include "objbase.h"
#include "olectl.h"
#include "wine/unicode.h"
#include "wine/list.h"
#include "msctf.h"
#include "msctf_internal.h"
@ -45,11 +47,26 @@ static const WCHAR szwEnabled[] = {'E','n','a','b','l','e','d',0};
static const WCHAR szwTipfmt[] = {'%','s','\\','%','s',0};
static const WCHAR szwFullLangfmt[] = {'%','s','\\','%','s','\\','%','s','\\','0','x','%','0','8','x','\\','%','s',0};
typedef struct tagInputProcessorProfilesSink {
struct list entry;
union {
/* InputProcessorProfile Sinks */
IUnknown *pIUnknown;
ITfLanguageProfileNotifySink *pITfLanguageProfileNotifySink;
} interfaces;
} InputProcessorProfilesSink;
typedef struct tagInputProcessorProfiles {
const ITfInputProcessorProfilesVtbl *InputProcessorProfilesVtbl;
const ITfSourceVtbl *SourceVtbl;
/* const ITfInputProcessorProfileMgrVtbl *InputProcessorProfileMgrVtbl; */
/* const ITfInputProcessorProfilesExVtbl *InputProcessorProfilesExVtbl; */
/* const ITfInputProcessorProfileSubstituteLayoutVtbl *InputProcessorProfileSubstituteLayoutVtbl; */
LONG refCount;
LANGID currentLanguage;
struct list LanguageProfileNotifySink;
} InputProcessorProfiles;
typedef struct tagProfilesEnumGuid {
@ -78,9 +95,30 @@ typedef struct tagEnumTfLanguageProfiles {
static HRESULT ProfilesEnumGuid_Constructor(IEnumGUID **ppOut);
static HRESULT EnumTfLanguageProfiles_Constructor(LANGID langid, IEnumTfLanguageProfiles **ppOut);
static inline InputProcessorProfiles *impl_from_ITfSourceVtbl(ITfSource *iface)
{
return (InputProcessorProfiles *)((char *)iface - FIELD_OFFSET(InputProcessorProfiles,SourceVtbl));
}
static void free_sink(InputProcessorProfilesSink *sink)
{
IUnknown_Release(sink->interfaces.pIUnknown);
HeapFree(GetProcessHeap(),0,sink);
}
static void InputProcessorProfiles_Destructor(InputProcessorProfiles *This)
{
struct list *cursor, *cursor2;
TRACE("destroying %p\n", This);
/* free sinks */
LIST_FOR_EACH_SAFE(cursor, cursor2, &This->LanguageProfileNotifySink)
{
InputProcessorProfilesSink* sink = LIST_ENTRY(cursor,InputProcessorProfilesSink,entry);
list_remove(cursor);
free_sink(sink);
}
HeapFree(GetProcessHeap(),0,This);
}
@ -122,6 +160,10 @@ static HRESULT WINAPI InputProcessorProfiles_QueryInterface(ITfInputProcessorPro
{
*ppvOut = This;
}
else if (IsEqualIID(iid, &IID_ITfSource))
{
*ppvOut = &This->SourceVtbl;
}
if (*ppvOut)
{
@ -536,6 +578,92 @@ static const ITfInputProcessorProfilesVtbl InputProcessorProfiles_InputProcessor
InputProcessorProfiles_SubstituteKeyboardLayout
};
/*****************************************************
* ITfSource functions
*****************************************************/
static HRESULT WINAPI IPPSource_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut)
{
InputProcessorProfiles *This = impl_from_ITfSourceVtbl(iface);
return InputProcessorProfiles_QueryInterface((ITfInputProcessorProfiles *)This, iid, *ppvOut);
}
static ULONG WINAPI IPPSource_AddRef(ITfSource *iface)
{
InputProcessorProfiles *This = impl_from_ITfSourceVtbl(iface);
return InputProcessorProfiles_AddRef((ITfInputProcessorProfiles*)This);
}
static ULONG WINAPI IPPSource_Release(ITfSource *iface)
{
InputProcessorProfiles *This = impl_from_ITfSourceVtbl(iface);
return InputProcessorProfiles_Release((ITfInputProcessorProfiles *)This);
}
static WINAPI HRESULT IPPSource_AdviseSink(ITfSource *iface,
REFIID riid, IUnknown *punk, DWORD *pdwCookie)
{
InputProcessorProfilesSink *ipps;
InputProcessorProfiles *This = impl_from_ITfSourceVtbl(iface);
TRACE("(%p) %s %p %p\n",This,debugstr_guid(riid),punk,pdwCookie);
if (!riid || !punk || !pdwCookie)
return E_INVALIDARG;
if (IsEqualIID(riid, &IID_ITfLanguageProfileNotifySink))
{
ipps = HeapAlloc(GetProcessHeap(),0,sizeof(InputProcessorProfilesSink));
if (!ipps)
return E_OUTOFMEMORY;
if (FAILED(IUnknown_QueryInterface(punk, riid, (LPVOID *)&ipps->interfaces.pITfLanguageProfileNotifySink)))
{
HeapFree(GetProcessHeap(),0,ipps);
return CONNECT_E_CANNOTCONNECT;
}
list_add_head(&This->LanguageProfileNotifySink,&ipps->entry);
*pdwCookie = generate_Cookie(COOKIE_MAGIC_IPPSINK, ipps);
}
else
{
FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid));
return E_NOTIMPL;
}
TRACE("cookie %x\n",*pdwCookie);
return S_OK;
}
static WINAPI HRESULT IPPSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie)
{
InputProcessorProfilesSink *sink;
InputProcessorProfiles *This = impl_from_ITfSourceVtbl(iface);
TRACE("(%p) %x\n",This,pdwCookie);
if (get_Cookie_magic(pdwCookie)!=COOKIE_MAGIC_IPPSINK)
return E_INVALIDARG;
sink = (InputProcessorProfilesSink*)remove_Cookie(pdwCookie);
if (!sink)
return CONNECT_E_NOCONNECTION;
list_remove(&sink->entry);
free_sink(sink);
return S_OK;
}
static const ITfSourceVtbl InputProcessorProfiles_SourceVtbl =
{
IPPSource_QueryInterface,
IPPSource_AddRef,
IPPSource_Release,
IPPSource_AdviseSink,
IPPSource_UnadviseSink,
};
HRESULT InputProcessorProfiles_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut)
{
InputProcessorProfiles *This;
@ -547,9 +675,12 @@ HRESULT InputProcessorProfiles_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut
return E_OUTOFMEMORY;
This->InputProcessorProfilesVtbl= &InputProcessorProfiles_InputProcessorProfilesVtbl;
This->SourceVtbl = &InputProcessorProfiles_SourceVtbl;
This->refCount = 1;
This->currentLanguage = GetUserDefaultLCID();
list_init(&This->LanguageProfileNotifySink);
TRACE("returning %p\n", This);
*ppOut = (IUnknown *)This;
return S_OK;

View File

@ -55,6 +55,7 @@ typedef struct {
TF_LANGUAGEPROFILE LanguageProfile;
ITfTextInputProcessor *pITfTextInputProcessor;
ITfThreadMgr *pITfThreadMgr;
ITfKeyEventSink *pITfKeyEventSink;
TfClientId tid;
} ActivatedTextService;
@ -357,14 +358,6 @@ HRESULT add_active_textservice(TF_LANGUAGEPROFILE *lp)
actsvr = HeapAlloc(GetProcessHeap(),0,sizeof(ActivatedTextService));
if (!actsvr) return E_OUTOFMEMORY;
entry = HeapAlloc(GetProcessHeap(),0,sizeof(AtsEntry));
if (!entry)
{
HeapFree(GetProcessHeap(),0,actsvr);
return E_OUTOFMEMORY;
}
ITfThreadMgr_QueryInterface(tm,&IID_ITfClientId,(LPVOID)&clientid);
ITfClientId_GetClientId(clientid, &lp->clsid, &actsvr->tid);
ITfClientId_Release(clientid);
@ -378,6 +371,7 @@ HRESULT add_active_textservice(TF_LANGUAGEPROFILE *lp)
actsvr->pITfTextInputProcessor = NULL;
actsvr->LanguageProfile = *lp;
actsvr->LanguageProfile.fActive = TRUE;
actsvr->pITfKeyEventSink = NULL;
/* get TIP category */
if (SUCCEEDED(CategoryMgr_Constructor(NULL,(IUnknown**)&catmgr)))
@ -402,6 +396,14 @@ HRESULT add_active_textservice(TF_LANGUAGEPROFILE *lp)
if (activated > 0)
activate_given_ts(actsvr, tm);
entry = HeapAlloc(GetProcessHeap(),0,sizeof(AtsEntry));
if (!entry)
{
HeapFree(GetProcessHeap(),0,actsvr);
return E_OUTOFMEMORY;
}
entry->ats = actsvr;
list_add_head(&AtsList, &entry->entry);
@ -456,6 +458,50 @@ HRESULT deactivate_textservices(void)
return S_OK;
}
CLSID get_textservice_clsid(TfClientId tid)
{
AtsEntry *ats;
LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry)
if (ats->ats->tid == tid)
return ats->ats->LanguageProfile.clsid;
return GUID_NULL;
}
HRESULT get_textservice_sink(TfClientId tid, REFCLSID iid, IUnknown **sink)
{
AtsEntry *ats;
if (!IsEqualCLSID(iid,&IID_ITfKeyEventSink))
return E_NOINTERFACE;
LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry)
if (ats->ats->tid == tid)
{
*sink = (IUnknown*)ats->ats->pITfKeyEventSink;
return S_OK;
}
return E_FAIL;
}
HRESULT set_textservice_sink(TfClientId tid, REFCLSID iid, IUnknown* sink)
{
AtsEntry *ats;
if (!IsEqualCLSID(iid,&IID_ITfKeyEventSink))
return E_NOINTERFACE;
LIST_FOR_EACH_ENTRY(ats, &AtsList, AtsEntry, entry)
if (ats->ats->tid == tid)
{
ats->ats->pITfKeyEventSink = (ITfKeyEventSink*)sink;
return S_OK;
}
return E_FAIL;
}
/*************************************************************************
* MSCTF DllMain
*/

View File

@ -13,6 +13,7 @@
<file>documentmgr.c</file>
<file>inputprocessor.c</file>
<file>msctf.c</file>
<file>range.c</file>
<file>regsvr.c</file>
<file>threadmgr.c</file>
<file>version.rc</file>

View File

@ -24,6 +24,8 @@
#define COOKIE_MAGIC_TMSINK 0x0010
#define COOKIE_MAGIC_CONTEXTSINK 0x0020
#define COOKIE_MAGIC_GUIDATOM 0x0030
#define COOKIE_MAGIC_IPPSINK 0x0040
#define COOKIE_MAGIC_EDITCOOKIE 0x0050
extern DWORD tlsIndex;
extern TfClientId processId;
@ -33,6 +35,10 @@ extern HRESULT DocumentMgr_Constructor(ITfThreadMgrEventSink*, ITfDocumentMgr **
extern HRESULT Context_Constructor(TfClientId tidOwner, IUnknown *punk, ITfContext **ppOut, TfEditCookie *pecTextStore);
extern HRESULT InputProcessorProfiles_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut);
extern HRESULT CategoryMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut);
extern HRESULT Range_Constructor(ITfContext *context, ITextStoreACP *textstore, DWORD lockType, DWORD anchorStart, DWORD anchorEnd, ITfRange **ppOut);
extern HRESULT Context_Initialize(ITfContext *cxt);
extern HRESULT Context_Uninitialize(ITfContext *cxt);
/* cookie function */
extern DWORD generate_Cookie(DWORD magic, LPVOID data);
@ -47,5 +53,9 @@ extern BOOL get_active_textservice(REFCLSID rclsid, TF_LANGUAGEPROFILE *lp);
extern HRESULT activate_textservices(ITfThreadMgr *tm);
extern HRESULT deactivate_textservices(void);
extern CLSID get_textservice_clsid(TfClientId tid);
extern HRESULT get_textservice_sink(TfClientId tid, REFCLSID iid, IUnknown** sink);
extern HRESULT set_textservice_sink(TfClientId tid, REFCLSID iid, IUnknown* sink);
extern const WCHAR szwSystemTIPKey[];
#endif /* __WINE_MSCTF_I_H */

View File

@ -0,0 +1,333 @@
/*
* ITfRange implementation
*
* Copyright 2009 Aric Stewart, CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "config.h"
#include <stdarg.h>
#define COBJMACROS
#include "wine/debug.h"
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "winuser.h"
#include "shlwapi.h"
#include "winerror.h"
#include "objbase.h"
#include "wine/unicode.h"
#include "msctf.h"
#include "msctf_internal.h"
WINE_DEFAULT_DEBUG_CHANNEL(msctf);
typedef struct tagRange {
const ITfRangeVtbl *RangeVtbl;
/* const ITfRangeACPVtb *RangeACPVtbl; */
LONG refCount;
ITextStoreACP *pITextStoreACP;
ITfContext *pITfContext;
DWORD lockType;
TfGravity gravityStart, gravityEnd;
DWORD anchorStart, anchorEnd;
} Range;
static void Range_Destructor(Range *This)
{
TRACE("destroying %p\n", This);
HeapFree(GetProcessHeap(),0,This);
}
static HRESULT WINAPI Range_QueryInterface(ITfRange *iface, REFIID iid, LPVOID *ppvOut)
{
Range *This = (Range*)iface;
*ppvOut = NULL;
if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfRange))
{
*ppvOut = This;
}
if (*ppvOut)
{
IUnknown_AddRef(iface);
return S_OK;
}
WARN("unsupported interface: %s\n", debugstr_guid(iid));
return E_NOINTERFACE;
}
static ULONG WINAPI Range_AddRef(ITfRange *iface)
{
Range *This = (Range *)iface;
return InterlockedIncrement(&This->refCount);
}
static ULONG WINAPI Range_Release(ITfRange *iface)
{
Range *This = (Range *)iface;
ULONG ret;
ret = InterlockedDecrement(&This->refCount);
if (ret == 0)
Range_Destructor(This);
return ret;
}
/*****************************************************
* ITfRange functions
*****************************************************/
static HRESULT WINAPI Range_GetText(ITfRange *iface, TfEditCookie ec,
DWORD dwFlags, WCHAR *pchText, ULONG cchMax, ULONG *pcch)
{
Range *This = (Range *)iface;
FIXME("STUB:(%p)\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI Range_SetText(ITfRange *iface, TfEditCookie ec,
DWORD dwFlags, const WCHAR *pchText, LONG cch)
{
Range *This = (Range *)iface;
FIXME("STUB:(%p)\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI Range_GetFormattedText(ITfRange *iface, TfEditCookie ec,
IDataObject **ppDataObject)
{
Range *This = (Range *)iface;
FIXME("STUB:(%p)\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI Range_GetEmbedded(ITfRange *iface, TfEditCookie ec,
REFGUID rguidService, REFIID riid, IUnknown **ppunk)
{
Range *This = (Range *)iface;
FIXME("STUB:(%p)\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI Range_InsertEmbedded(ITfRange *iface, TfEditCookie ec,
DWORD dwFlags, IDataObject *pDataObject)
{
Range *This = (Range *)iface;
FIXME("STUB:(%p)\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI Range_ShiftStart(ITfRange *iface, TfEditCookie ec,
LONG cchReq, LONG *pcch, const TF_HALTCOND *pHalt)
{
Range *This = (Range *)iface;
FIXME("STUB:(%p)\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI Range_ShiftEnd(ITfRange *iface, TfEditCookie ec,
LONG cchReq, LONG *pcch, const TF_HALTCOND *pHalt)
{
Range *This = (Range *)iface;
FIXME("STUB:(%p)\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI Range_ShiftStartToRange(ITfRange *iface, TfEditCookie ec,
ITfRange *pRange, TfAnchor aPos)
{
Range *This = (Range *)iface;
FIXME("STUB:(%p)\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI Range_ShiftEndToRange(ITfRange *iface, TfEditCookie ec,
ITfRange *pRange, TfAnchor aPos)
{
Range *This = (Range *)iface;
FIXME("STUB:(%p)\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI Range_ShiftStartRegion(ITfRange *iface, TfEditCookie ec,
TfShiftDir dir, BOOL *pfNoRegion)
{
Range *This = (Range *)iface;
FIXME("STUB:(%p)\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI Range_ShiftEndRegion(ITfRange *iface, TfEditCookie ec,
TfShiftDir dir, BOOL *pfNoRegion)
{
Range *This = (Range *)iface;
FIXME("STUB:(%p)\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI Range_IsEmpty(ITfRange *iface, TfEditCookie ec,
BOOL *pfEmpty)
{
Range *This = (Range *)iface;
FIXME("STUB:(%p)\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI Range_Collapse(ITfRange *iface, TfEditCookie ec,
TfAnchor aPos)
{
Range *This = (Range *)iface;
FIXME("STUB:(%p)\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI Range_IsEqualStart(ITfRange *iface, TfEditCookie ec,
ITfRange *pWith, TfAnchor aPos, BOOL *pfEqual)
{
Range *This = (Range *)iface;
FIXME("STUB:(%p)\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI Range_IsEqualEnd(ITfRange *iface, TfEditCookie ec,
ITfRange *pWith, TfAnchor aPos, BOOL *pfEqual)
{
Range *This = (Range *)iface;
FIXME("STUB:(%p)\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI Range_CompareStart(ITfRange *iface, TfEditCookie ec,
ITfRange *pWith, TfAnchor aPos, LONG *plResult)
{
Range *This = (Range *)iface;
FIXME("STUB:(%p)\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI Range_CompareEnd(ITfRange *iface, TfEditCookie ec,
ITfRange *pWith, TfAnchor aPos, LONG *plResult)
{
Range *This = (Range *)iface;
FIXME("STUB:(%p)\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI Range_AdjustForInsert(ITfRange *iface, TfEditCookie ec,
ULONG cchInsert, BOOL *pfInsertOk)
{
Range *This = (Range *)iface;
FIXME("STUB:(%p)\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI Range_GetGravity(ITfRange *iface,
TfGravity *pgStart, TfGravity *pgEnd)
{
Range *This = (Range *)iface;
FIXME("STUB:(%p)\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI Range_SetGravity(ITfRange *iface, TfEditCookie ec,
TfGravity gStart, TfGravity gEnd)
{
Range *This = (Range *)iface;
FIXME("STUB:(%p)\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI Range_Clone(ITfRange *iface, ITfRange **ppClone)
{
Range *This = (Range *)iface;
FIXME("STUB:(%p)\n",This);
return E_NOTIMPL;
}
static HRESULT WINAPI Range_GetContext(ITfRange *iface, ITfContext **ppContext)
{
Range *This = (Range *)iface;
TRACE("(%p)\n",This);
if (!ppContext)
return E_INVALIDARG;
*ppContext = This->pITfContext;
return S_OK;
}
static const ITfRangeVtbl Range_RangeVtbl =
{
Range_QueryInterface,
Range_AddRef,
Range_Release,
Range_GetText,
Range_SetText,
Range_GetFormattedText,
Range_GetEmbedded,
Range_InsertEmbedded,
Range_ShiftStart,
Range_ShiftEnd,
Range_ShiftStartToRange,
Range_ShiftEndToRange,
Range_ShiftStartRegion,
Range_ShiftEndRegion,
Range_IsEmpty,
Range_Collapse,
Range_IsEqualStart,
Range_IsEqualEnd,
Range_CompareStart,
Range_CompareEnd,
Range_AdjustForInsert,
Range_GetGravity,
Range_SetGravity,
Range_Clone,
Range_GetContext
};
HRESULT Range_Constructor(ITfContext *context, ITextStoreACP *textstore, DWORD lockType, DWORD anchorStart, DWORD anchorEnd, ITfRange **ppOut)
{
Range *This;
This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Range));
if (This == NULL)
return E_OUTOFMEMORY;
TRACE("(%p) %p %p\n",This, context, textstore);
This->RangeVtbl= &Range_RangeVtbl;
This->refCount = 1;
This->pITfContext = context;
This->pITextStoreACP = textstore;
This->lockType = lockType;
This->anchorStart = anchorStart;
This->anchorEnd = anchorEnd;
*ppOut = (ITfRange*)This;
TRACE("returning %p\n", This);
return S_OK;
}

View File

@ -71,6 +71,11 @@ typedef struct tagACLMulti {
const ITfKeystrokeMgrVtbl *KeystrokeMgrVtbl;
const ITfMessagePumpVtbl *MessagePumpVtbl;
const ITfClientIdVtbl *ClientIdVtbl;
/* const ITfThreadMgrExVtbl *ThreadMgrExVtbl; */
/* const ITfConfigureSystemKeystrokeFeedVtbl *ConfigureSystemKeystrokeFeedVtbl; */
/* const ITfLangBarItemMgrVtbl *LangBarItemMgrVtbl; */
/* const ITfUIElementMgrVtbl *UIElementMgrVtbl; */
/* const ITfSourceSingleVtbl *SourceSingleVtbl; */
LONG refCount;
const ITfThreadMgrEventSinkVtbl *ThreadMgrEventSinkVtbl; /* internal */
@ -78,6 +83,9 @@ typedef struct tagACLMulti {
ITfDocumentMgr *focus;
LONG activationCount;
ITfKeyEventSink *forgroundKeyEventSink;
CLSID forgroundTextService;
struct list CurrentPreservedKeys;
/* kept as separate lists to reduce unnecessary iterations */
@ -434,7 +442,7 @@ static WINAPI HRESULT ThreadMgrSource_AdviseSink(ITfSource *iface,
tms = HeapAlloc(GetProcessHeap(),0,sizeof(ThreadMgrSink));
if (!tms)
return E_OUTOFMEMORY;
if (!SUCCEEDED(IUnknown_QueryInterface(punk, riid, (LPVOID*)&tms->interfaces.pITfThreadMgrEventSink)))
if (FAILED(IUnknown_QueryInterface(punk, riid, (LPVOID *)&tms->interfaces.pITfThreadMgrEventSink)))
{
HeapFree(GetProcessHeap(),0,tms);
return CONNECT_E_CANNOTCONNECT;
@ -509,24 +517,87 @@ static HRESULT WINAPI KeystrokeMgr_AdviseKeyEventSink(ITfKeystrokeMgr *iface,
TfClientId tid, ITfKeyEventSink *pSink, BOOL fForeground)
{
ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
FIXME("STUB:(%p)\n",This);
return E_NOTIMPL;
CLSID textservice;
ITfKeyEventSink *check = NULL;
TRACE("(%p) %x %p %i\n",This,tid,pSink,fForeground);
if (!tid || !pSink)
return E_INVALIDARG;
textservice = get_textservice_clsid(tid);
if (IsEqualCLSID(&GUID_NULL,&textservice))
return E_INVALIDARG;
get_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown**)&check);
if (check != NULL)
return CONNECT_E_ADVISELIMIT;
if (FAILED(IUnknown_QueryInterface(pSink,&IID_ITfKeyEventSink,(LPVOID*) &check)))
return E_INVALIDARG;
set_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown*)check);
if (fForeground)
{
if (This->forgroundKeyEventSink)
{
ITfKeyEventSink_OnSetFocus(This->forgroundKeyEventSink, FALSE);
ITfKeyEventSink_Release(This->forgroundKeyEventSink);
}
ITfKeyEventSink_AddRef(check);
ITfKeyEventSink_OnSetFocus(check, TRUE);
This->forgroundKeyEventSink = check;
This->forgroundTextService = textservice;
}
return S_OK;
}
static HRESULT WINAPI KeystrokeMgr_UnadviseKeyEventSink(ITfKeystrokeMgr *iface,
TfClientId tid)
{
ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
FIXME("STUB:(%p)\n",This);
return E_NOTIMPL;
CLSID textservice;
ITfKeyEventSink *check = NULL;
TRACE("(%p) %x\n",This,tid);
if (!tid)
return E_INVALIDARG;
textservice = get_textservice_clsid(tid);
if (IsEqualCLSID(&GUID_NULL,&textservice))
return E_INVALIDARG;
get_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown**)&check);
if (!check)
return CONNECT_E_NOCONNECTION;
set_textservice_sink(tid, &IID_ITfKeyEventSink, NULL);
ITfKeyEventSink_Release(check);
if (This->forgroundKeyEventSink == check)
{
ITfKeyEventSink_Release(This->forgroundKeyEventSink);
This->forgroundKeyEventSink = NULL;
This->forgroundTextService = GUID_NULL;
}
return S_OK;
}
static HRESULT WINAPI KeystrokeMgr_GetForeground(ITfKeystrokeMgr *iface,
CLSID *pclsid)
{
ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
FIXME("STUB:(%p)\n",This);
return E_NOTIMPL;
TRACE("(%p) %p\n",This,pclsid);
if (!pclsid)
return E_INVALIDARG;
if (IsEqualCLSID(&This->forgroundTextService,&GUID_NULL))
return S_FALSE;
*pclsid = This->forgroundTextService;
return S_OK;
}
static HRESULT WINAPI KeystrokeMgr_TestKeyDown(ITfKeystrokeMgr *iface,