--- /dev/null
+/*
+ * ITfCompartmentMgr 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 "oleauto.h"
+#include "olectl.h"
+
+#include "wine/unicode.h"
+#include "wine/list.h"
+
+#include "msctf.h"
+#include "msctf_internal.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(msctf);
+
+typedef struct tagCompartmentValue {
+ struct list entry;
+ GUID guid;
+ TfClientId owner;
+ ITfCompartment *compartment;
+} CompartmentValue;
+
+typedef struct tagCompartmentMgr {
+ const ITfCompartmentMgrVtbl *CompartmentMgrVtbl;
+ LONG refCount;
+
+ IUnknown *pUnkOuter;
+
+ struct list values;
+} CompartmentMgr;
+
+typedef struct tagCompartmentEnumGuid {
+ const IEnumGUIDVtbl *Vtbl;
+ LONG refCount;
+
+ struct list *values;
+ struct list *cursor;
+} CompartmentEnumGuid;
+
+
+typedef struct tagCompartmentSink {
+ struct list entry;
+ union {
+ IUnknown *pIUnknown;
+ ITfCompartmentEventSink *pITfCompartmentEventSink;
+ } interfaces;
+} CompartmentSink;
+
+typedef struct tagCompartment {
+ const ITfCompartmentVtbl *Vtbl;
+ const ITfSourceVtbl *SourceVtbl;
+ LONG refCount;
+
+ /* Only VT_I4, VT_UNKNOWN and VT_BSTR data types are allowed */
+ VARIANT variant;
+ CompartmentValue *valueData;
+ struct list CompartmentEventSink;
+} Compartment;
+
+static HRESULT CompartmentEnumGuid_Constructor(struct list* values, IEnumGUID **ppOut);
+static HRESULT Compartment_Constructor(CompartmentValue *value, ITfCompartment **ppOut);
+
+static inline Compartment *impl_from_ITfSourceVtbl(ITfSource *iface)
+{
+ return (Compartment *)((char *)iface - FIELD_OFFSET(Compartment,SourceVtbl));
+}
+
+HRESULT CompartmentMgr_Destructor(ITfCompartmentMgr *iface)
+{
+ CompartmentMgr *This = (CompartmentMgr *)iface;
+ struct list *cursor, *cursor2;
+
+ LIST_FOR_EACH_SAFE(cursor, cursor2, &This->values)
+ {
+ CompartmentValue* value = LIST_ENTRY(cursor,CompartmentValue,entry);
+ list_remove(cursor);
+ ITfCompartment_Release(value->compartment);
+ HeapFree(GetProcessHeap(),0,value);
+ }
+
+ HeapFree(GetProcessHeap(),0,This);
+ return S_OK;
+}
+
+/*****************************************************
+ * ITfCompartmentMgr functions
+ *****************************************************/
+static HRESULT WINAPI CompartmentMgr_QueryInterface(ITfCompartmentMgr *iface, REFIID iid, LPVOID *ppvOut)
+{
+ CompartmentMgr *This = (CompartmentMgr *)iface;
+ if (This->pUnkOuter)
+ return IUnknown_QueryInterface(This->pUnkOuter, iid, *ppvOut);
+ else
+ {
+ *ppvOut = NULL;
+
+ if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfCompartmentMgr))
+ {
+ *ppvOut = This;
+ }
+
+ if (*ppvOut)
+ {
+ IUnknown_AddRef(iface);
+ return S_OK;
+ }
+
+ WARN("unsupported interface: %s\n", debugstr_guid(iid));
+ return E_NOINTERFACE;
+ }
+}
+
+static ULONG WINAPI CompartmentMgr_AddRef(ITfCompartmentMgr *iface)
+{
+ CompartmentMgr *This = (CompartmentMgr *)iface;
+ if (This->pUnkOuter)
+ return IUnknown_AddRef(This->pUnkOuter);
+ else
+ return InterlockedIncrement(&This->refCount);
+}
+
+static ULONG WINAPI CompartmentMgr_Release(ITfCompartmentMgr *iface)
+{
+ CompartmentMgr *This = (CompartmentMgr *)iface;
+ if (This->pUnkOuter)
+ return IUnknown_Release(This->pUnkOuter);
+ else
+ {
+ ULONG ret;
+
+ ret = InterlockedDecrement(&This->refCount);
+ if (ret == 0)
+ CompartmentMgr_Destructor(iface);
+ return ret;
+ }
+}
+
+static HRESULT WINAPI CompartmentMgr_GetCompartment(ITfCompartmentMgr *iface,
+ REFGUID rguid, ITfCompartment **ppcomp)
+{
+ CompartmentMgr *This = (CompartmentMgr *)iface;
+ CompartmentValue* value;
+ struct list *cursor;
+ HRESULT hr;
+
+ TRACE("(%p) %s %p\n",This,debugstr_guid(rguid),ppcomp);
+
+ LIST_FOR_EACH(cursor, &This->values)
+ {
+ value = LIST_ENTRY(cursor,CompartmentValue,entry);
+ if (IsEqualGUID(rguid,&value->guid))
+ {
+ ITfCompartment_AddRef(value->compartment);
+ *ppcomp = value->compartment;
+ return S_OK;
+ }
+ }
+
+ value = HeapAlloc(GetProcessHeap(),0,sizeof(CompartmentValue));
+ value->guid = *rguid;
+ value->owner = 0;
+ hr = Compartment_Constructor(value,&value->compartment);
+ if (SUCCEEDED(hr))
+ {
+ list_add_head(&This->values,&value->entry);
+ ITfCompartment_AddRef(value->compartment);
+ *ppcomp = value->compartment;
+ }
+ else
+ {
+ HeapFree(GetProcessHeap(),0,value);
+ *ppcomp = NULL;
+ }
+ return hr;
+}
+
+static HRESULT WINAPI CompartmentMgr_ClearCompartment(ITfCompartmentMgr *iface,
+ TfClientId tid, REFGUID rguid)
+{
+ struct list *cursor;
+ CompartmentMgr *This = (CompartmentMgr *)iface;
+ TRACE("(%p) %i %s\n",This,tid,debugstr_guid(rguid));
+
+ LIST_FOR_EACH(cursor, &This->values)
+ {
+ CompartmentValue* value = LIST_ENTRY(cursor,CompartmentValue,entry);
+ if (IsEqualGUID(rguid,&value->guid))
+ {
+ if (value->owner && tid != value->owner)
+ return E_UNEXPECTED;
+ list_remove(cursor);
+ ITfCompartment_Release(value->compartment);
+ HeapFree(GetProcessHeap(),0,value);
+ return S_OK;
+ }
+ }
+
+ return CONNECT_E_NOCONNECTION;
+}
+
+static HRESULT WINAPI CompartmentMgr_EnumCompartments(ITfCompartmentMgr *iface,
+ IEnumGUID **ppEnum)
+{
+ CompartmentMgr *This = (CompartmentMgr *)iface;
+ TRACE("(%p) %p\n",This,ppEnum);
+ if (!ppEnum)
+ return E_INVALIDARG;
+ return CompartmentEnumGuid_Constructor(&This->values, ppEnum);
+}
+
+static const ITfCompartmentMgrVtbl CompartmentMgr_CompartmentMgrVtbl =
+{
+ CompartmentMgr_QueryInterface,
+ CompartmentMgr_AddRef,
+ CompartmentMgr_Release,
+
+ CompartmentMgr_GetCompartment,
+ CompartmentMgr_ClearCompartment,
+ CompartmentMgr_EnumCompartments
+};
+
+HRESULT CompartmentMgr_Constructor(IUnknown *pUnkOuter, REFIID riid, IUnknown **ppOut)
+{
+ CompartmentMgr *This;
+
+ if (!ppOut)
+ return E_POINTER;
+
+ if (pUnkOuter && !IsEqualIID (riid, &IID_IUnknown))
+ return CLASS_E_NOAGGREGATION;
+
+ This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(CompartmentMgr));
+ if (This == NULL)
+ return E_OUTOFMEMORY;
+
+ This->CompartmentMgrVtbl = &CompartmentMgr_CompartmentMgrVtbl;
+ This->pUnkOuter = pUnkOuter;
+ list_init(&This->values);
+
+ if (pUnkOuter)
+ {
+ TRACE("returning %p\n", This);
+ *ppOut = (IUnknown*)This;
+ return S_OK;
+ }
+ else
+ {
+ HRESULT hr;
+ hr = IUnknown_QueryInterface((IUnknown*)This, riid, (LPVOID*)ppOut);
+ if (FAILED(hr))
+ HeapFree(GetProcessHeap(),0,This);
+ return hr;
+ }
+}
+
+/**************************************************
+ * IEnumGUID implementaion for ITfCompartmentMgr::EnumCompartments
+ **************************************************/
+static void CompartmentEnumGuid_Destructor(CompartmentEnumGuid *This)
+{
+ TRACE("destroying %p\n", This);
+ HeapFree(GetProcessHeap(),0,This);
+}
+
+static HRESULT WINAPI CompartmentEnumGuid_QueryInterface(IEnumGUID *iface, REFIID iid, LPVOID *ppvOut)
+{
+ CompartmentEnumGuid *This = (CompartmentEnumGuid *)iface;
+ *ppvOut = NULL;
+
+ if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumGUID))
+ {
+ *ppvOut = This;
+ }
+
+ if (*ppvOut)
+ {
+ IUnknown_AddRef(iface);
+ return S_OK;
+ }
+
+ WARN("unsupported interface: %s\n", debugstr_guid(iid));
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI CompartmentEnumGuid_AddRef(IEnumGUID *iface)
+{
+ CompartmentEnumGuid *This = (CompartmentEnumGuid*)iface;
+ return InterlockedIncrement(&This->refCount);
+}
+
+static ULONG WINAPI CompartmentEnumGuid_Release(IEnumGUID *iface)
+{
+ CompartmentEnumGuid *This = (CompartmentEnumGuid *)iface;
+ ULONG ret;
+
+ ret = InterlockedDecrement(&This->refCount);
+ if (ret == 0)
+ CompartmentEnumGuid_Destructor(This);
+ return ret;
+}
+
+/*****************************************************
+ * IEnumGuid functions
+ *****************************************************/
+static HRESULT WINAPI CompartmentEnumGuid_Next( LPENUMGUID iface,
+ ULONG celt, GUID *rgelt, ULONG *pceltFetched)
+{
+ CompartmentEnumGuid *This = (CompartmentEnumGuid *)iface;
+ ULONG fetched = 0;
+
+ TRACE("(%p)\n",This);
+
+ if (rgelt == NULL) return E_POINTER;
+
+ while (fetched < celt && This->cursor)
+ {
+ CompartmentValue* value = LIST_ENTRY(This->cursor,CompartmentValue,entry);
+ if (!value)
+ break;
+
+ This->cursor = list_next(This->values,This->cursor);
+ *rgelt = value->guid;
+
+ ++fetched;
+ ++rgelt;
+ }
+
+ if (pceltFetched) *pceltFetched = fetched;
+ return fetched == celt ? S_OK : S_FALSE;
+}
+
+static HRESULT WINAPI CompartmentEnumGuid_Skip( LPENUMGUID iface, ULONG celt)
+{
+ CompartmentEnumGuid *This = (CompartmentEnumGuid *)iface;
+ TRACE("(%p)\n",This);
+
+ This->cursor = list_next(This->values,This->cursor);
+ return S_OK;
+}
+
+static HRESULT WINAPI CompartmentEnumGuid_Reset( LPENUMGUID iface)
+{
+ CompartmentEnumGuid *This = (CompartmentEnumGuid *)iface;
+ TRACE("(%p)\n",This);
+ This->cursor = list_head(This->values);
+ return S_OK;
+}
+
+static HRESULT WINAPI CompartmentEnumGuid_Clone( LPENUMGUID iface,
+ IEnumGUID **ppenum)
+{
+ CompartmentEnumGuid *This = (CompartmentEnumGuid *)iface;
+ HRESULT res;
+
+ TRACE("(%p)\n",This);
+
+ if (ppenum == NULL) return E_POINTER;
+
+ res = CompartmentEnumGuid_Constructor(This->values, ppenum);
+ if (SUCCEEDED(res))
+ {
+ CompartmentEnumGuid *new_This = (CompartmentEnumGuid *)*ppenum;
+ new_This->cursor = This->cursor;
+ }
+ return res;
+}
+
+static const IEnumGUIDVtbl IEnumGUID_Vtbl ={
+ CompartmentEnumGuid_QueryInterface,
+ CompartmentEnumGuid_AddRef,
+ CompartmentEnumGuid_Release,
+
+ CompartmentEnumGuid_Next,
+ CompartmentEnumGuid_Skip,
+ CompartmentEnumGuid_Reset,
+ CompartmentEnumGuid_Clone
+};
+
+static HRESULT CompartmentEnumGuid_Constructor(struct list *values, IEnumGUID **ppOut)
+{
+ CompartmentEnumGuid *This;
+
+ This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(CompartmentEnumGuid));
+ if (This == NULL)
+ return E_OUTOFMEMORY;
+
+ This->Vtbl= &IEnumGUID_Vtbl;
+ This->refCount = 1;
+
+ This->values = values;
+ This->cursor = list_head(values);
+
+ TRACE("returning %p\n", This);
+ *ppOut = (IEnumGUID*)This;
+ return S_OK;
+}
+
+/**************************************************
+ * ITfCompartment
+ **************************************************/
+static void free_sink(CompartmentSink *sink)
+{
+ IUnknown_Release(sink->interfaces.pIUnknown);
+ HeapFree(GetProcessHeap(),0,sink);
+}
+
+static void Compartment_Destructor(Compartment *This)
+{
+ struct list *cursor, *cursor2;
+ TRACE("destroying %p\n", This);
+ VariantClear(&This->variant);
+ LIST_FOR_EACH_SAFE(cursor, cursor2, &This->CompartmentEventSink)
+ {
+ CompartmentSink* sink = LIST_ENTRY(cursor,CompartmentSink,entry);
+ list_remove(cursor);
+ free_sink(sink);
+ }
+ HeapFree(GetProcessHeap(),0,This);
+}
+
+static HRESULT WINAPI Compartment_QueryInterface(ITfCompartment *iface, REFIID iid, LPVOID *ppvOut)
+{
+ Compartment *This = (Compartment *)iface;
+ *ppvOut = NULL;
+
+ if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfCompartment))
+ {
+ *ppvOut = This;
+ }
+ else if (IsEqualIID(iid, &IID_ITfSource))
+ {
+ *ppvOut = &This->SourceVtbl;
+ }
+
+ if (*ppvOut)
+ {
+ IUnknown_AddRef(iface);
+ return S_OK;
+ }
+
+ WARN("unsupported interface: %s\n", debugstr_guid(iid));
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI Compartment_AddRef(ITfCompartment *iface)
+{
+ Compartment *This = (Compartment*)iface;
+ return InterlockedIncrement(&This->refCount);
+}
+
+static ULONG WINAPI Compartment_Release(ITfCompartment *iface)
+{
+ Compartment *This = (Compartment *)iface;
+ ULONG ret;
+
+ ret = InterlockedDecrement(&This->refCount);
+ if (ret == 0)
+ Compartment_Destructor(This);
+ return ret;
+}
+
+static HRESULT WINAPI Compartment_SetValue(ITfCompartment *iface,
+ TfClientId tid, const VARIANT *pvarValue)
+{
+ Compartment *This = (Compartment *)iface;
+ struct list *cursor;
+
+ TRACE("(%p) %i %p\n",This,tid,pvarValue);
+
+ if (!pvarValue)
+ return E_INVALIDARG;
+
+ if (!(V_VT(pvarValue) == VT_BSTR || V_VT(pvarValue) == VT_I4 ||
+ V_VT(pvarValue) == VT_UNKNOWN))
+ return E_INVALIDARG;
+
+ if (!This->valueData->owner)
+ This->valueData->owner = tid;
+
+ VariantClear(&This->variant);
+
+ /* Shallow copy of value and type */
+ This->variant = *pvarValue;
+
+ if (V_VT(pvarValue) == VT_BSTR)
+ V_BSTR(&This->variant) = SysAllocStringByteLen((char*)V_BSTR(pvarValue),
+ SysStringByteLen(V_BSTR(pvarValue)));
+ else if (V_VT(pvarValue) == VT_UNKNOWN)
+ IUnknown_AddRef(V_UNKNOWN(&This->variant));
+
+ LIST_FOR_EACH(cursor, &This->CompartmentEventSink)
+ {
+ CompartmentSink* sink = LIST_ENTRY(cursor,CompartmentSink,entry);
+ ITfCompartmentEventSink_OnChange(sink->interfaces.pITfCompartmentEventSink,&This->valueData->guid);
+ }
+
+ return S_OK;
+}
+
+static HRESULT WINAPI Compartment_GetValue(ITfCompartment *iface,
+ VARIANT *pvarValue)
+{
+ Compartment *This = (Compartment *)iface;
+ TRACE("(%p) %p\n",This, pvarValue);
+
+ if (!pvarValue)
+ return E_INVALIDARG;
+
+ VariantInit(pvarValue);
+ if (V_VT(&This->variant) == VT_EMPTY) return S_FALSE;
+ return VariantCopy(pvarValue,&This->variant);
+}
+
+static const ITfCompartmentVtbl ITfCompartment_Vtbl ={
+ Compartment_QueryInterface,
+ Compartment_AddRef,
+ Compartment_Release,
+
+ Compartment_SetValue,
+ Compartment_GetValue
+};
+
+/*****************************************************
+ * ITfSource functions
+ *****************************************************/
+
+static HRESULT WINAPI Source_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut)
+{
+ Compartment *This = impl_from_ITfSourceVtbl(iface);
+ return Compartment_QueryInterface((ITfCompartment *)This, iid, *ppvOut);
+}
+
+static ULONG WINAPI Source_AddRef(ITfSource *iface)
+{
+ Compartment *This = impl_from_ITfSourceVtbl(iface);
+ return Compartment_AddRef((ITfCompartment*)This);
+}
+
+static ULONG WINAPI Source_Release(ITfSource *iface)
+{
+ Compartment *This = impl_from_ITfSourceVtbl(iface);
+ return Compartment_Release((ITfCompartment *)This);
+}
+
+static WINAPI HRESULT CompartmentSource_AdviseSink(ITfSource *iface,
+ REFIID riid, IUnknown *punk, DWORD *pdwCookie)
+{
+ CompartmentSink *cs;
+ Compartment *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_ITfCompartmentEventSink))
+ {
+ cs = HeapAlloc(GetProcessHeap(),0,sizeof(CompartmentSink));
+ if (!cs)
+ return E_OUTOFMEMORY;
+ if (FAILED(IUnknown_QueryInterface(punk, riid, (LPVOID *)&cs->interfaces.pITfCompartmentEventSink)))
+ {
+ HeapFree(GetProcessHeap(),0,cs);
+ return CONNECT_E_CANNOTCONNECT;
+ }
+ list_add_head(&This->CompartmentEventSink,&cs->entry);
+ *pdwCookie = generate_Cookie(COOKIE_MAGIC_COMPARTMENTSINK , cs);
+ }
+ 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 CompartmentSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie)
+{
+ CompartmentSink *sink;
+ Compartment *This = impl_from_ITfSourceVtbl(iface);
+
+ TRACE("(%p) %x\n",This,pdwCookie);
+
+ if (get_Cookie_magic(pdwCookie)!=COOKIE_MAGIC_COMPARTMENTSINK)
+ return E_INVALIDARG;
+
+ sink = (CompartmentSink*)remove_Cookie(pdwCookie);
+ if (!sink)
+ return CONNECT_E_NOCONNECTION;
+
+ list_remove(&sink->entry);
+ free_sink(sink);
+
+ return S_OK;
+}
+
+static const ITfSourceVtbl Compartment_SourceVtbl =
+{
+ Source_QueryInterface,
+ Source_AddRef,
+ Source_Release,
+
+ CompartmentSource_AdviseSink,
+ CompartmentSource_UnadviseSink,
+};
+
+static HRESULT Compartment_Constructor(CompartmentValue *valueData, ITfCompartment **ppOut)
+{
+ Compartment *This;
+
+ This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Compartment));
+ if (This == NULL)
+ return E_OUTOFMEMORY;
+
+ This->Vtbl= &ITfCompartment_Vtbl;
+ This->SourceVtbl = &Compartment_SourceVtbl;
+ This->refCount = 1;
+
+ This->valueData = valueData;
+ VariantInit(&This->variant);
+
+ list_init(&This->CompartmentEventSink);
+
+ TRACE("returning %p\n", This);
+ *ppOut = (ITfCompartment*)This;
+ return S_OK;
+}
/* const ITfContextCompositionVtbl *ContextCompositionVtbl; */
/* const ITfContextOwnerCompositionServicesVtbl *ContextOwnerCompositionServicesVtbl; */
/* const ITfContextOwnerServicesVtbl *ContextOwnerServicesVtbl; */
- /* const ITfInsertAtSelectionVtbl *InsertAtSelectionVtbl; */
+ const ITfInsertAtSelectionVtbl *InsertAtSelectionVtbl;
/* const ITfMouseTrackerVtbl *MouseTrackerVtbl; */
/* const ITfQueryEmbeddedVtbl *QueryEmbeddedVtbl; */
- /* const ITfSourceSingleVtbl *SourceSingleVtbl; */
+ const ITfSourceSingleVtbl *SourceSingleVtbl;
LONG refCount;
BOOL connected;
+ /* Aggregation */
+ ITfCompartmentMgr *CompartmentMgr;
+
TfClientId tidOwner;
TfEditCookie defaultCookie;
+ TS_STATUS documentStatus;
+ ITfDocumentMgr *manager;
ITextStoreACP *pITextStoreACP;
ITfContextOwnerCompositionSink *pITfContextOwnerCompositionSink;
return (Context *)((char *)iface - FIELD_OFFSET(Context,SourceVtbl));
}
+static inline Context *impl_from_ITfInsertAtSelectionVtbl(ITfInsertAtSelection*iface)
+{
+ return (Context *)((char *)iface - FIELD_OFFSET(Context,InsertAtSelectionVtbl));
+}
+
+static inline Context *impl_from_ITfSourceSingleVtbl(ITfSourceSingle* iface)
+{
+ return (Context *)((char *)iface - FIELD_OFFSET(Context,SourceSingleVtbl));
+}
+
static void free_sink(ContextSink *sink)
{
IUnknown_Release(sink->interfaces.pIUnknown);
free_sink(sink);
}
+ CompartmentMgr_Destructor(This->CompartmentMgr);
HeapFree(GetProcessHeap(),0,This);
}
{
*ppvOut = &This->SourceVtbl;
}
+ else if (IsEqualIID(iid, &IID_ITfInsertAtSelection))
+ {
+ *ppvOut = &This->InsertAtSelectionVtbl;
+ }
+ else if (IsEqualIID(iid, &IID_ITfCompartmentMgr))
+ {
+ *ppvOut = This->CompartmentMgr;
+ }
+ else if (IsEqualIID(iid, &IID_ITfSourceSingle))
+ {
+ *ppvOut = &This->SourceSingleVtbl;
+ }
if (*ppvOut)
{
HRESULT hr;
Context *This = (Context *)iface;
DWORD dwLockFlags = 0x0;
- TS_STATUS status;
TRACE("(%p) %i %p %x %p\n",This, tid, pes, dwFlags, phrSession);
else if (dwFlags & TF_ES_READ)
dwLockFlags |= TS_LF_READ;
- /* TODO: cache this */
- ITextStoreACP_GetStatus(This->pITextStoreACP, &status);
+ if (!This->documentStatus.dwDynamicFlags)
+ ITextStoreACP_GetStatus(This->pITextStoreACP, &This->documentStatus);
- if (((dwFlags & TF_ES_READWRITE) == TF_ES_READWRITE) && (status.dwDynamicFlags & TS_SD_READONLY))
+ if (((dwFlags & TF_ES_READWRITE) == TF_ES_READWRITE) && (This->documentStatus.dwDynamicFlags & TS_SD_READONLY))
{
*phrSession = TS_E_READONLY;
return S_OK;
return E_INVALIDARG;
}
-
hr = ITextStoreACP_RequestLock(This->pITextStoreACP, dwLockFlags, phrSession);
return hr;
static HRESULT WINAPI Context_SetSelection (ITfContext *iface,
TfEditCookie ec, ULONG ulCount, const TF_SELECTION *pSelection)
{
+ TS_SELECTION_ACP *acp;
Context *This = (Context *)iface;
- FIXME("STUB:(%p)\n",This);
- return E_NOTIMPL;
+ INT i;
+ HRESULT hr;
+
+ TRACE("(%p) %i %i %p\n",This,ec,ulCount,pSelection);
+
+ if (!This->pITextStoreACP)
+ {
+ FIXME("Context does not have a ITextStoreACP\n");
+ return E_NOTIMPL;
+ }
+
+ if (get_Cookie_magic(ec)!=COOKIE_MAGIC_EDITCOOKIE)
+ return TF_E_NOLOCK;
+
+ acp = HeapAlloc(GetProcessHeap(), 0, sizeof(TS_SELECTION_ACP) * ulCount);
+ if (!acp)
+ return E_OUTOFMEMORY;
+
+ for (i = 0; i < ulCount; i++)
+ if (FAILED(TF_SELECTION_to_TS_SELECTION_ACP(&pSelection[i], &acp[i])))
+ {
+ TRACE("Selection Conversion Failed\n");
+ HeapFree(GetProcessHeap(), 0 , acp);
+ return E_FAIL;
+ }
+
+ hr = ITextStoreACP_SetSelection(This->pITextStoreACP, ulCount, acp);
+
+ HeapFree(GetProcessHeap(), 0, acp);
+
+ return hr;
}
static HRESULT WINAPI Context_GetStart (ITfContext *iface,
TF_STATUS *pdcs)
{
Context *This = (Context *)iface;
- FIXME("STUB:(%p)\n",This);
- return E_NOTIMPL;
+ TRACE("(%p) %p\n",This,pdcs);
+
+ if (!This->connected)
+ return TF_E_DISCONNECTED;
+
+ if (!pdcs)
+ return E_INVALIDARG;
+
+ if (!This->pITextStoreACP)
+ {
+ FIXME("Context does not have a ITextStoreACP\n");
+ return E_NOTIMPL;
+ }
+
+ ITextStoreACP_GetStatus(This->pITextStoreACP, &This->documentStatus);
+
+ *pdcs = This->documentStatus;
+
+ return S_OK;
}
static HRESULT WINAPI Context_GetProperty (ITfContext *iface,
ITfDocumentMgr **ppDm)
{
Context *This = (Context *)iface;
- FIXME("STUB:(%p)\n",This);
- return E_NOTIMPL;
+ TRACE("(%p) %p\n",This,ppDm);
+
+ if (!ppDm)
+ return E_INVALIDARG;
+
+ *ppDm = This->manager;
+ if (!This->manager)
+ return S_FALSE;
+
+ ITfDocumentMgr_AddRef(This->manager);
+
+ return S_OK;
}
static HRESULT WINAPI Context_CreateRangeBackup (ITfContext *iface,
ContextSource_UnadviseSink,
};
-HRESULT Context_Constructor(TfClientId tidOwner, IUnknown *punk, ITfContext **ppOut, TfEditCookie *pecTextStore)
+/*****************************************************
+ * ITfInsertAtSelection functions
+ *****************************************************/
+static HRESULT WINAPI InsertAtSelection_QueryInterface(ITfInsertAtSelection *iface, REFIID iid, LPVOID *ppvOut)
+{
+ Context *This = impl_from_ITfInsertAtSelectionVtbl(iface);
+ return Context_QueryInterface((ITfContext *)This, iid, *ppvOut);
+}
+
+static ULONG WINAPI InsertAtSelection_AddRef(ITfInsertAtSelection *iface)
+{
+ Context *This = impl_from_ITfInsertAtSelectionVtbl(iface);
+ return Context_AddRef((ITfContext *)This);
+}
+
+static ULONG WINAPI InsertAtSelection_Release(ITfInsertAtSelection *iface)
+{
+ Context *This = impl_from_ITfInsertAtSelectionVtbl(iface);
+ return Context_Release((ITfContext *)This);
+}
+
+static WINAPI HRESULT InsertAtSelection_InsertTextAtSelection(
+ ITfInsertAtSelection *iface, TfEditCookie ec, DWORD dwFlags,
+ const WCHAR *pchText, LONG cch, ITfRange **ppRange)
+{
+ Context *This = impl_from_ITfInsertAtSelectionVtbl(iface);
+ EditCookie *cookie;
+ LONG acpStart, acpEnd;
+ TS_TEXTCHANGE change;
+ HRESULT hr;
+
+ TRACE("(%p) %i %x %s %p\n",This, ec, dwFlags, debugstr_wn(pchText,cch), ppRange);
+
+ if (!This->connected)
+ return TF_E_DISCONNECTED;
+
+ if (get_Cookie_magic(ec)!=COOKIE_MAGIC_EDITCOOKIE)
+ return TF_E_NOLOCK;
+
+ cookie = get_Cookie_data(ec);
+
+ if ((cookie->lockType & TS_LF_READWRITE) != TS_LF_READWRITE )
+ return TS_E_READONLY;
+
+ if (!This->pITextStoreACP)
+ {
+ FIXME("Context does not have a ITextStoreACP\n");
+ return E_NOTIMPL;
+ }
+
+ hr = ITextStoreACP_InsertTextAtSelection(This->pITextStoreACP, dwFlags, pchText, cch, &acpStart, &acpEnd, &change);
+ if (SUCCEEDED(hr))
+ Range_Constructor((ITfContext*)This, This->pITextStoreACP, cookie->lockType, change.acpStart, change.acpNewEnd, ppRange);
+
+ return hr;
+}
+
+static WINAPI HRESULT InsertAtSelection_InsertEmbeddedAtSelection(
+ ITfInsertAtSelection *iface, TfEditCookie ec, DWORD dwFlags,
+ IDataObject *pDataObject, ITfRange **ppRange)
+{
+ Context *This = impl_from_ITfInsertAtSelectionVtbl(iface);
+ FIXME("STUB:(%p)\n",This);
+ return E_NOTIMPL;
+}
+
+static const ITfInsertAtSelectionVtbl Context_InsertAtSelectionVtbl =
+{
+ InsertAtSelection_QueryInterface,
+ InsertAtSelection_AddRef,
+ InsertAtSelection_Release,
+
+ InsertAtSelection_InsertTextAtSelection,
+ InsertAtSelection_InsertEmbeddedAtSelection,
+};
+
+/*****************************************************
+ * ITfSourceSingle functions
+ *****************************************************/
+static HRESULT WINAPI SourceSingle_QueryInterface(ITfSourceSingle *iface, REFIID iid, LPVOID *ppvOut)
+{
+ Context *This = impl_from_ITfSourceSingleVtbl(iface);
+ return Context_QueryInterface((ITfContext *)This, iid, *ppvOut);
+}
+
+static ULONG WINAPI SourceSingle_AddRef(ITfSourceSingle *iface)
+{
+ Context *This = impl_from_ITfSourceSingleVtbl(iface);
+ return Context_AddRef((ITfContext *)This);
+}
+
+static ULONG WINAPI SourceSingle_Release(ITfSourceSingle *iface)
+{
+ Context *This = impl_from_ITfSourceSingleVtbl(iface);
+ return Context_Release((ITfContext *)This);
+}
+
+static WINAPI HRESULT SourceSingle_AdviseSingleSink( ITfSourceSingle *iface,
+ TfClientId tid, REFIID riid, IUnknown *punk)
+{
+ Context *This = impl_from_ITfSourceSingleVtbl(iface);
+ FIXME("STUB:(%p) %i %s %p\n",This, tid, debugstr_guid(riid),punk);
+ return E_NOTIMPL;
+}
+
+static WINAPI HRESULT SourceSingle_UnadviseSingleSink( ITfSourceSingle *iface,
+ TfClientId tid, REFIID riid)
+{
+ Context *This = impl_from_ITfSourceSingleVtbl(iface);
+ FIXME("STUB:(%p) %i %s\n",This, tid, debugstr_guid(riid));
+ return E_NOTIMPL;
+}
+
+static const ITfSourceSingleVtbl Context_SourceSingleVtbl =
+{
+ SourceSingle_QueryInterface,
+ SourceSingle_AddRef,
+ SourceSingle_Release,
+
+ SourceSingle_AdviseSingleSink,
+ SourceSingle_UnadviseSingleSink,
+};
+
+HRESULT Context_Constructor(TfClientId tidOwner, IUnknown *punk, ITfDocumentMgr *mgr, ITfContext **ppOut, TfEditCookie *pecTextStore)
{
Context *This;
EditCookie *cookie;
This->ContextVtbl= &Context_ContextVtbl;
This->SourceVtbl = &Context_SourceVtbl;
+ This->InsertAtSelectionVtbl = &Context_InsertAtSelectionVtbl;
+ This->SourceSingleVtbl = &Context_SourceSingleVtbl;
This->refCount = 1;
This->tidOwner = tidOwner;
This->connected = FALSE;
+ This->manager = mgr;
+
+ CompartmentMgr_Constructor((IUnknown*)This, &IID_IUnknown, (IUnknown**)&This->CompartmentMgr);
cookie->lockType = TF_ES_READ;
cookie->pOwningContext = This;
return S_OK;
}
-HRESULT Context_Initialize(ITfContext *iface)
+HRESULT Context_Initialize(ITfContext *iface, ITfDocumentMgr *manager)
{
Context *This = (Context *)iface;
(IUnknown*)This->pITextStoreACPSink, TS_AS_ALL_SINKS);
}
This->connected = TRUE;
+ This->manager = manager;
return S_OK;
}
This->pITextStoreACPSink = NULL;
}
This->connected = FALSE;
+ This->manager = NULL;
return S_OK;
}
DWORD dwFlags)
{
TextStoreACPSink *This = (TextStoreACPSink *)iface;
- FIXME("STUB:(%p)\n",This);
- return E_NOTIMPL;
+ HRESULT hr, hrSession;
+
+ TRACE("(%p) %x\n",This, dwFlags);
+
+ if (!This->pContext)
+ {
+ ERR("No context?\n");
+ return E_FAIL;
+ }
+
+ if (!This->pContext->pITextStoreACP)
+ {
+ FIXME("Context does not have a ITextStoreACP\n");
+ return E_NOTIMPL;
+ }
+
+ hr = ITextStoreACP_RequestLock(This->pContext->pITextStoreACP, TS_LF_READ, &hrSession);
+
+ if(SUCCEEDED(hr) && SUCCEEDED(hrSession))
+ This->pContext->documentStatus.dwDynamicFlags = dwFlags;
+
+ return S_OK;
}
static HRESULT WINAPI TextStoreACPSink_OnAttrsChange(ITextStoreACPSink *iface,
{
TextStoreACPSink *This = (TextStoreACPSink *)iface;
HRESULT hr;
- EditCookie *cookie;
+ EditCookie *cookie,*sinkcookie;
TfEditCookie ec;
+ struct list *cursor;
TRACE("(%p) %x\n",This, dwLockFlags);
- if (!This->pContext || !This->pContext->currentEditSession)
+ if (!This->pContext)
{
- ERR("OnLockGranted called on a context without a current edit session\n");
+ ERR("OnLockGranted called without a context\n");
return E_FAIL;
}
+ if (!This->pContext->currentEditSession)
+ {
+ FIXME("OnLockGranted called for something other than an EditSession\n");
+ return S_OK;
+ }
+
cookie = HeapAlloc(GetProcessHeap(),0,sizeof(EditCookie));
if (!cookie)
return E_OUTOFMEMORY;
+ sinkcookie = HeapAlloc(GetProcessHeap(),0,sizeof(EditCookie));
+ if (!sinkcookie)
+ return E_OUTOFMEMORY;
+
cookie->lockType = dwLockFlags;
cookie->pOwningContext = This->pContext;
ec = generate_Cookie(COOKIE_MAGIC_EDITCOOKIE, cookie);
hr = ITfEditSession_DoEditSession(This->pContext->currentEditSession, ec);
+ if ((dwLockFlags&TS_LF_READWRITE) == TS_LF_READWRITE)
+ {
+ TfEditCookie sc;
+
+ sinkcookie->lockType = TS_LF_READ;
+ sinkcookie->pOwningContext = This->pContext;
+ sc = generate_Cookie(COOKIE_MAGIC_EDITCOOKIE, sinkcookie);
+
+ /*TODO: implement ITfEditRecord */
+ LIST_FOR_EACH(cursor, &This->pContext->pTextEditSink)
+ {
+ ContextSink* sink = LIST_ENTRY(cursor,ContextSink,entry);
+ ITfTextEditSink_OnEndEdit(sink->interfaces.pITfTextEditSink,
+ (ITfContext*) &This->pContext, sc, NULL);
+ }
+ sinkcookie = remove_Cookie(sc);
+ }
+ HeapFree(GetProcessHeap(),0,sinkcookie);
+
ITfEditSession_Release(This->pContext->currentEditSession);
This->pContext->currentEditSession = NULL;
const ITfSourceVtbl *SourceVtbl;
LONG refCount;
+ /* Aggregation */
+ ITfCompartmentMgr *CompartmentMgr;
+
ITfContext* contextStack[2]; /* limit of 2 contexts */
ITfThreadMgrEventSink* ThreadMgrSink;
} DocumentMgr;
+typedef struct tagEnumTfContext {
+ const IEnumTfContextsVtbl *Vtbl;
+ LONG refCount;
+
+ DWORD index;
+ DocumentMgr *docmgr;
+} EnumTfContext;
+
+static HRESULT EnumTfContext_Constructor(DocumentMgr* mgr, IEnumTfContexts **ppOut);
+
static inline DocumentMgr *impl_from_ITfSourceVtbl(ITfSource *iface)
{
return (DocumentMgr *)((char *)iface - FIELD_OFFSET(DocumentMgr,SourceVtbl));
static void DocumentMgr_Destructor(DocumentMgr *This)
{
+ ITfThreadMgr *tm;
TRACE("destroying %p\n", This);
+
+ TF_GetThreadMgr(&tm);
+ ThreadMgr_OnDocumentMgrDestruction(tm, (ITfDocumentMgr*)This);
+
if (This->contextStack[0])
ITfContext_Release(This->contextStack[0]);
if (This->contextStack[1])
ITfContext_Release(This->contextStack[1]);
+ CompartmentMgr_Destructor(This->CompartmentMgr);
HeapFree(GetProcessHeap(),0,This);
}
{
*ppvOut = &This->SourceVtbl;
}
+ else if (IsEqualIID(iid, &IID_ITfCompartmentMgr))
+ {
+ *ppvOut = This->CompartmentMgr;
+ }
if (*ppvOut)
{
{
DocumentMgr *This = (DocumentMgr *)iface;
TRACE("(%p) 0x%x 0x%x %p %p %p\n",This,tidOwner,dwFlags,punk,ppic,pecTextStore);
- return Context_Constructor(tidOwner, punk, ppic, pecTextStore);
+ return Context_Constructor(tidOwner, punk, iface, ppic, pecTextStore);
}
static HRESULT WINAPI DocumentMgr_Push(ITfDocumentMgr *iface, ITfContext *pic)
This->contextStack[1] = This->contextStack[0];
This->contextStack[0] = check;
+ Context_Initialize(check, iface);
ITfThreadMgrEventSink_OnPushContext(This->ThreadMgrSink,check);
- Context_Initialize(check);
return S_OK;
}
static HRESULT WINAPI DocumentMgr_EnumContexts(ITfDocumentMgr *iface, IEnumTfContexts **ppEnum)
{
DocumentMgr *This = (DocumentMgr *)iface;
- FIXME("STUB:(%p)\n",This);
- return E_NOTIMPL;
+ TRACE("(%p) %p\n",This,ppEnum);
+ return EnumTfContext_Constructor(This, ppEnum);
}
static const ITfDocumentMgrVtbl DocumentMgr_DocumentMgrVtbl =
This->refCount = 1;
This->ThreadMgrSink = ThreadMgrSink;
+ CompartmentMgr_Constructor((IUnknown*)This, &IID_IUnknown, (IUnknown**)&This->CompartmentMgr);
+
TRACE("returning %p\n", This);
*ppOut = (ITfDocumentMgr*)This;
return S_OK;
}
+
+/**************************************************
+ * IEnumTfContexts implementaion
+ **************************************************/
+static void EnumTfContext_Destructor(EnumTfContext *This)
+{
+ TRACE("destroying %p\n", This);
+ HeapFree(GetProcessHeap(),0,This);
+}
+
+static HRESULT WINAPI EnumTfContext_QueryInterface(IEnumTfContexts *iface, REFIID iid, LPVOID *ppvOut)
+{
+ EnumTfContext *This = (EnumTfContext *)iface;
+ *ppvOut = NULL;
+
+ if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumTfContexts))
+ {
+ *ppvOut = This;
+ }
+
+ if (*ppvOut)
+ {
+ IUnknown_AddRef(iface);
+ return S_OK;
+ }
+
+ WARN("unsupported interface: %s\n", debugstr_guid(iid));
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI EnumTfContext_AddRef(IEnumTfContexts *iface)
+{
+ EnumTfContext *This = (EnumTfContext*)iface;
+ return InterlockedIncrement(&This->refCount);
+}
+
+static ULONG WINAPI EnumTfContext_Release(IEnumTfContexts *iface)
+{
+ EnumTfContext *This = (EnumTfContext *)iface;
+ ULONG ret;
+
+ ret = InterlockedDecrement(&This->refCount);
+ if (ret == 0)
+ EnumTfContext_Destructor(This);
+ return ret;
+}
+
+static HRESULT WINAPI EnumTfContext_Next(IEnumTfContexts *iface,
+ ULONG ulCount, ITfContext **rgContext, ULONG *pcFetched)
+{
+ EnumTfContext *This = (EnumTfContext *)iface;
+ ULONG fetched = 0;
+
+ TRACE("(%p)\n",This);
+
+ if (rgContext == NULL) return E_POINTER;
+
+ while (fetched < ulCount)
+ {
+ if (This->index > 1)
+ break;
+
+ if (!This->docmgr->contextStack[This->index])
+ break;
+
+ *rgContext = This->docmgr->contextStack[This->index];
+ ITfContext_AddRef(*rgContext);
+
+ ++This->index;
+ ++fetched;
+ ++rgContext;
+ }
+
+ if (pcFetched) *pcFetched = fetched;
+ return fetched == ulCount ? S_OK : S_FALSE;
+}
+
+static HRESULT WINAPI EnumTfContext_Skip( IEnumTfContexts* iface, ULONG celt)
+{
+ EnumTfContext *This = (EnumTfContext *)iface;
+ TRACE("(%p)\n",This);
+ This->index += celt;
+ return S_OK;
+}
+
+static HRESULT WINAPI EnumTfContext_Reset( IEnumTfContexts* iface)
+{
+ EnumTfContext *This = (EnumTfContext *)iface;
+ TRACE("(%p)\n",This);
+ This->index = 0;
+ return S_OK;
+}
+
+static HRESULT WINAPI EnumTfContext_Clone( IEnumTfContexts *iface,
+ IEnumTfContexts **ppenum)
+{
+ EnumTfContext *This = (EnumTfContext *)iface;
+ HRESULT res;
+
+ TRACE("(%p)\n",This);
+
+ if (ppenum == NULL) return E_POINTER;
+
+ res = EnumTfContext_Constructor(This->docmgr, ppenum);
+ if (SUCCEEDED(res))
+ {
+ EnumTfContext *new_This = (EnumTfContext *)*ppenum;
+ new_This->index = This->index;
+ }
+ return res;
+}
+
+static const IEnumTfContextsVtbl IEnumTfContexts_Vtbl ={
+ EnumTfContext_QueryInterface,
+ EnumTfContext_AddRef,
+ EnumTfContext_Release,
+
+ EnumTfContext_Clone,
+ EnumTfContext_Next,
+ EnumTfContext_Reset,
+ EnumTfContext_Skip
+};
+
+static HRESULT EnumTfContext_Constructor(DocumentMgr *mgr, IEnumTfContexts **ppOut)
+{
+ EnumTfContext *This;
+
+ This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(EnumTfContext));
+ if (This == NULL)
+ return E_OUTOFMEMORY;
+
+ This->Vtbl= &IEnumTfContexts_Vtbl;
+ This->refCount = 1;
+ This->docmgr = mgr;
+
+ TRACE("returning %p\n", This);
+ *ppOut = (IEnumTfContexts*)This;
+ return S_OK;
+}
WINE_DEFAULT_DEBUG_CHANNEL(msctf);
static const WCHAR szwLngp[] = {'L','a','n','g','u','a','g','e','P','r','o','f','i','l','e',0};
-static const WCHAR szwEnabled[] = {'E','n','a','b','l','e','d',0};
+static const WCHAR szwEnable[] = {'E','n','a','b','l','e',0};
static const WCHAR szwTipfmt[] = {'%','s','\\','%','s',0};
static const WCHAR szwFullLangfmt[] = {'%','s','\\','%','s','\\','%','s','\\','0','x','%','0','8','x','\\','%','s',0};
+static const WCHAR szwAssemblies[] = {'A','s','s','e','m','b','l','i','e','s',0};
+static const WCHAR szwDefault[] = {'D','e','f','a','u','l','t',0};
+static const WCHAR szwProfile[] = {'P','r','o','f','i','l','e',0};
+static const WCHAR szwDefaultFmt[] = {'%','s','\\','%','s','\\','0','x','%','0','8','x','\\','%','s',0};
+
typedef struct tagInputProcessorProfilesSink {
struct list entry;
union {
if (!res && disposition == REG_CREATED_NEW_KEY)
{
DWORD zero = 0x0;
- RegSetValueExW(key, szwEnabled, 0, REG_DWORD, (LPBYTE)&zero, sizeof(DWORD));
+ RegSetValueExW(key, szwEnable, 0, REG_DWORD, (LPBYTE)&zero, sizeof(DWORD));
}
if (!res)
RegSetValueExW(fmtkey, icnf, 0, REG_SZ, (LPBYTE)pchIconFile, cchFile * sizeof(WCHAR));
RegSetValueExW(fmtkey, icni, 0, REG_DWORD, (LPBYTE)&uIconIndex, sizeof(DWORD));
if (disposition == REG_CREATED_NEW_KEY)
- RegSetValueExW(fmtkey, szwEnabled, 0, REG_DWORD, (LPBYTE)&zero, sizeof(DWORD));
+ RegSetValueExW(fmtkey, szwEnable, 0, REG_DWORD, (LPBYTE)&zero, sizeof(DWORD));
RegCloseKey(fmtkey);
add_userkey(rclsid, langid, guidProfile);
ITfInputProcessorProfiles *iface, LANGID langid, REFGUID catid,
CLSID *pclsid, GUID *pguidProfile)
{
+ WCHAR fullkey[168];
+ WCHAR buf[39];
+ HKEY hkey;
+ DWORD count;
+ ULONG res;
InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
- FIXME("STUB:(%p)\n",This);
- return E_NOTIMPL;
+
+ TRACE("%p) %x %s %p %p\n",This, langid, debugstr_guid(catid),pclsid,pguidProfile);
+
+ if (!catid || !pclsid || !pguidProfile)
+ return E_INVALIDARG;
+
+ StringFromGUID2(catid, buf, 39);
+ sprintfW(fullkey, szwDefaultFmt, szwSystemCTFKey, szwAssemblies, langid, buf);
+
+ if (RegOpenKeyExW(HKEY_CURRENT_USER, fullkey, 0, KEY_READ | KEY_WRITE,
+ &hkey ) != ERROR_SUCCESS)
+ return S_FALSE;
+
+ count = sizeof(buf);
+ res = RegQueryValueExW(hkey, szwDefault, 0, NULL, (LPBYTE)buf, &count);
+ if (res != ERROR_SUCCESS)
+ {
+ RegCloseKey(hkey);
+ return S_FALSE;
+ }
+ CLSIDFromString(buf,pclsid);
+
+ res = RegQueryValueExW(hkey, szwProfile, 0, NULL, (LPBYTE)buf, &count);
+ if (res == ERROR_SUCCESS)
+ CLSIDFromString(buf,pguidProfile);
+
+ RegCloseKey(hkey);
+
+ return S_OK;
}
static HRESULT WINAPI InputProcessorProfiles_SetDefaultLanguageProfile(
ITfInputProcessorProfiles *iface, LANGID langid, REFCLSID rclsid,
REFGUID guidProfiles)
{
+ WCHAR fullkey[168];
+ WCHAR buf[39];
+ HKEY hkey;
+ GUID catid;
+ HRESULT hr;
+ ITfCategoryMgr *catmgr;
InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
- FIXME("STUB:(%p)\n",This);
- return E_NOTIMPL;
+ static const GUID * tipcats[3] = { &GUID_TFCAT_TIP_KEYBOARD,
+ &GUID_TFCAT_TIP_SPEECH,
+ &GUID_TFCAT_TIP_HANDWRITING };
+
+ TRACE("%p) %x %s %s\n",This, langid, debugstr_guid(rclsid),debugstr_guid(guidProfiles));
+
+ if (!rclsid || !guidProfiles)
+ return E_INVALIDARG;
+
+ hr = CategoryMgr_Constructor(NULL,(IUnknown**)&catmgr);
+
+ if (FAILED(hr))
+ return hr;
+
+ if (ITfCategoryMgr_FindClosestCategory(catmgr, rclsid,
+ &catid, tipcats, 3) != S_OK)
+ hr = ITfCategoryMgr_FindClosestCategory(catmgr, rclsid,
+ &catid, NULL, 0);
+ ITfCategoryMgr_Release(catmgr);
+
+ if (FAILED(hr))
+ return E_FAIL;
+
+ StringFromGUID2(&catid, buf, 39);
+ sprintfW(fullkey, szwDefaultFmt, szwSystemCTFKey, szwAssemblies, langid, buf);
+
+ if (RegCreateKeyExW(HKEY_CURRENT_USER, fullkey, 0, NULL, 0, KEY_READ | KEY_WRITE,
+ NULL, &hkey, NULL ) != ERROR_SUCCESS)
+ return E_FAIL;
+
+ StringFromGUID2(rclsid, buf, 39);
+ RegSetValueExW(hkey, szwDefault, 0, REG_SZ, (LPBYTE)buf, sizeof(buf));
+ StringFromGUID2(guidProfiles, buf, 39);
+ RegSetValueExW(hkey, szwProfile, 0, REG_SZ, (LPBYTE)buf, sizeof(buf));
+ RegCloseKey(hkey);
+
+ return S_OK;
}
static HRESULT WINAPI InputProcessorProfiles_ActivateLanguageProfile(
static HRESULT WINAPI InputProcessorProfiles_ChangeCurrentLanguage(
ITfInputProcessorProfiles *iface, LANGID langid)
{
+ struct list *cursor;
InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
+ BOOL accept;
+
FIXME("STUB:(%p)\n",This);
+
+ LIST_FOR_EACH(cursor, &This->LanguageProfileNotifySink)
+ {
+ InputProcessorProfilesSink* sink = LIST_ENTRY(cursor,InputProcessorProfilesSink,entry);
+ accept = TRUE;
+ ITfLanguageProfileNotifySink_OnLanguageChange(sink->interfaces.pITfLanguageProfileNotifySink, langid, &accept);
+ if (!accept)
+ return E_FAIL;
+ }
+
+ /* TODO: On successful language change call OnLanguageChanged sink */
return E_NOTIMPL;
}
ITfInputProcessorProfiles *iface, LANGID **ppLangId, ULONG *pulCount)
{
InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
- FIXME("STUB:(%p)\n",This);
- return E_NOTIMPL;
+ FIXME("Semi-STUB:(%p)\n",This);
+ *ppLangId = CoTaskMemAlloc(sizeof(LANGID));
+ **ppLangId = This->currentLanguage;
+ *pulCount = 1;
+ return S_OK;
}
static HRESULT WINAPI InputProcessorProfiles_EnumLanguageProfiles(
if (!res)
{
- RegSetValueExW(key, szwEnabled, 0, REG_DWORD, (LPBYTE)&fEnable, sizeof(DWORD));
+ RegSetValueExW(key, szwEnable, 0, REG_DWORD, (LPBYTE)&fEnable, sizeof(DWORD));
RegCloseKey(key);
}
else
if (!res)
{
DWORD count = sizeof(DWORD);
- res = RegQueryValueExW(key, szwEnabled, 0, NULL, (LPBYTE)pfEnable, &count);
+ res = RegQueryValueExW(key, szwEnable, 0, NULL, (LPBYTE)pfEnable, &count);
RegCloseKey(key);
}
if (!res)
{
DWORD count = sizeof(DWORD);
- res = RegQueryValueExW(key, szwEnabled, 0, NULL, (LPBYTE)pfEnable, &count);
+ res = RegQueryValueExW(key, szwEnable, 0, NULL, (LPBYTE)pfEnable, &count);
RegCloseKey(key);
}
}
if (!res)
{
- RegSetValueExW(key, szwEnabled, 0, REG_DWORD, (LPBYTE)&fEnable, sizeof(DWORD));
+ RegSetValueExW(key, szwEnable, 0, REG_DWORD, (LPBYTE)&fEnable, sizeof(DWORD));
RegCloseKey(key);
}
else
#include "shlwapi.h"
#include "shlguid.h"
#include "comcat.h"
-#include "initguid.h"
#include "msctf.h"
#include "msctf_internal.h"
DWORD tlsIndex = 0;
TfClientId processId = 0;
+ITfCompartmentMgr *globalCompartmentMgr = NULL;
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};
+const WCHAR szwSystemCTFKey[] = {'S','O','F','T','W','A','R','E','\\','M','i','c','r','o','s','o','f','t','\\','C','T','F',0};
typedef HRESULT (*LPFNCONSTRUCTOR)(IUnknown *pUnkOuter, IUnknown **ppvOut);
return S_OK;
}
+
+/***********************************************************************
+ * TF_CreateInputProcessorProfiles(MSCTF.@)
+ */
+HRESULT WINAPI TF_CreateInputProcessorProfiles(
+ ITfInputProcessorProfiles **ppipr)
+{
+ return InputProcessorProfiles_Constructor(NULL,(IUnknown**)ppipr);
+}
<define name="__WINESRC__" />
<redefine name="_WIN32_WINNT">0x600</redefine>
<file>categorymgr.c</file>
+ <file>compartmentmgr.c</file>
<file>context.c</file>
<file>documentmgr.c</file>
<file>inputprocessor.c</file>
<library>wine</library>
<library>uuid</library>
<library>ole32</library>
+ <library>oleaut32</library>
<library>user32</library>
<library>advapi32</library>
<library>kernel32</library>
+ <library>msctf_local_interface</library>
+ <library>textstor_local_interface</library>
<library>ntdll</library>
</module>
<module name="msctf_local_interface" type="idlinterface">
<file>msctf_local.idl</file>
</module>
+<module name="textstor_local_interface" type="idlinterface">
+ <file>textstor_local.idl</file>
+</module>
</group>
@ stub TF_CreateCategoryMgr
@ stub TF_CreateCicLoadMutex
@ stub TF_CreateDisplayAttributeMgr
-@ stub TF_CreateInputProcessorProfiles
+@ stdcall TF_CreateInputProcessorProfiles(ptr)
@ stub TF_CreateLangBarItemMgr
@ stub TF_CreateLangBarMgr
@ stdcall TF_CreateThreadMgr(ptr)
#define COOKIE_MAGIC_GUIDATOM 0x0030
#define COOKIE_MAGIC_IPPSINK 0x0040
#define COOKIE_MAGIC_EDITCOOKIE 0x0050
+#define COOKIE_MAGIC_COMPARTMENTSINK 0x0060
extern DWORD tlsIndex;
extern TfClientId processId;
+extern ITfCompartmentMgr *globalCompartmentMgr;
extern HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut);
extern HRESULT DocumentMgr_Constructor(ITfThreadMgrEventSink*, ITfDocumentMgr **ppOut);
-extern HRESULT Context_Constructor(TfClientId tidOwner, IUnknown *punk, ITfContext **ppOut, TfEditCookie *pecTextStore);
+extern HRESULT Context_Constructor(TfClientId tidOwner, IUnknown *punk, ITfDocumentMgr *mgr, 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 CompartmentMgr_Constructor(IUnknown *pUnkOuter, REFIID riid, IUnknown **ppOut);
+extern HRESULT CompartmentMgr_Destructor(ITfCompartmentMgr *This);
-extern HRESULT Context_Initialize(ITfContext *cxt);
+extern HRESULT Context_Initialize(ITfContext *cxt, ITfDocumentMgr *manager);
extern HRESULT Context_Uninitialize(ITfContext *cxt);
+extern void ThreadMgr_OnDocumentMgrDestruction(ITfThreadMgr *tm, ITfDocumentMgr *mgr);
+extern HRESULT TF_SELECTION_to_TS_SELECTION_ACP(const TF_SELECTION *tf, TS_SELECTION_ACP *tsAcp);
/* cookie function */
extern DWORD generate_Cookie(DWORD magic, LPVOID data);
extern HRESULT set_textservice_sink(TfClientId tid, REFCLSID iid, IUnknown* sink);
extern const WCHAR szwSystemTIPKey[];
+extern const WCHAR szwSystemCTFKey[];
#endif /* __WINE_MSCTF_I_H */
TfAnchor aPos)
{
Range *This = (Range *)iface;
- FIXME("STUB:(%p)\n",This);
- return E_NOTIMPL;
+ TRACE("(%p) %i %i\n",This,ec,aPos);
+
+ switch (aPos)
+ {
+ case TF_ANCHOR_START:
+ This->anchorEnd = This->anchorStart;
+ break;
+ case TF_ANCHOR_END:
+ This->anchorStart = This->anchorEnd;
+ break;
+ default:
+ return E_INVALIDARG;
+ }
+
+ return S_OK;
}
static HRESULT WINAPI Range_IsEqualStart(ITfRange *iface, TfEditCookie ec,
return S_OK;
}
+
+/* Internal conversion functions */
+
+HRESULT TF_SELECTION_to_TS_SELECTION_ACP(const TF_SELECTION *tf, TS_SELECTION_ACP *tsAcp)
+{
+ Range *This;
+
+ if (!tf || !tsAcp || !tf->range)
+ return E_INVALIDARG;
+
+ This = (Range *)tf->range;
+
+ tsAcp->acpStart = This->anchorStart;
+ tsAcp->acpEnd = This->anchorEnd;
+ tsAcp->style.ase = tf->style.ase;
+ tsAcp->style.fInterimChar = tf->style.fInterimChar;
+ return S_OK;
+}
--- /dev/null
+
+#include "textstor.idl"
TfClientId tid;
} PreservedKey;
+typedef struct tagDocumentMgrs
+{
+ struct list entry;
+ ITfDocumentMgr *docmgr;
+} DocumentMgrEntry;
+
+typedef struct tagAssociatedWindow
+{
+ struct list entry;
+ HWND hwnd;
+ ITfDocumentMgr *docmgr;
+} AssociatedWindow;
+
typedef struct tagACLMulti {
const ITfThreadMgrVtbl *ThreadMgrVtbl;
const ITfSourceVtbl *SourceVtbl;
/* const ITfSourceSingleVtbl *SourceSingleVtbl; */
LONG refCount;
+ /* Aggregation */
+ ITfCompartmentMgr *CompartmentMgr;
+
const ITfThreadMgrEventSinkVtbl *ThreadMgrEventSinkVtbl; /* internal */
ITfDocumentMgr *focus;
CLSID forgroundTextService;
struct list CurrentPreservedKeys;
+ struct list CreatedDocumentMgrs;
+
+ struct list AssociatedFocusWindows;
+ HHOOK focusHook;
/* kept as separate lists to reduce unnecessary iterations */
struct list ActiveLanguageProfileNotifySink;
struct list ThreadMgrEventSink;
} ThreadMgr;
+typedef struct tagEnumTfDocumentMgr {
+ const IEnumTfDocumentMgrsVtbl *Vtbl;
+ LONG refCount;
+
+ struct list *index;
+ struct list *head;
+} EnumTfDocumentMgr;
+
+static HRESULT EnumTfDocumentMgr_Constructor(struct list* head, IEnumTfDocumentMgrs **ppOut);
+LRESULT CALLBACK ThreadFocusHookProc(int nCode, WPARAM wParam, LPARAM lParam);
+
static inline ThreadMgr *impl_from_ITfSourceVtbl(ITfSource *iface)
{
return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,SourceVtbl));
return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,ThreadMgrEventSinkVtbl));
}
+static HRESULT SetupWindowsHook(ThreadMgr *This)
+{
+ if (!This->focusHook)
+ {
+ This->focusHook = SetWindowsHookExW(WH_CBT, ThreadFocusHookProc, 0,
+ GetCurrentThreadId());
+ if (!This->focusHook)
+ {
+ ERR("Unable to set focus hook\n");
+ return E_FAIL;
+ }
+ return S_OK;
+ }
+ return S_FALSE;
+}
+
static void free_sink(ThreadMgrSink *sink)
{
IUnknown_Release(sink->interfaces.pIUnknown);
{
struct list *cursor, *cursor2;
+ /* unhook right away */
+ if (This->focusHook)
+ UnhookWindowsHookEx(This->focusHook);
+
TlsSetValue(tlsIndex,NULL);
TRACE("destroying %p\n", This);
if (This->focus)
HeapFree(GetProcessHeap(),0,key);
}
+ LIST_FOR_EACH_SAFE(cursor, cursor2, &This->CreatedDocumentMgrs)
+ {
+ DocumentMgrEntry *mgr = LIST_ENTRY(cursor,DocumentMgrEntry,entry);
+ list_remove(cursor);
+ FIXME("Left Over ITfDocumentMgr. Should we do something with it?\n");
+ HeapFree(GetProcessHeap(),0,mgr);
+ }
+
+ LIST_FOR_EACH_SAFE(cursor, cursor2, &This->AssociatedFocusWindows)
+ {
+ AssociatedWindow *wnd = LIST_ENTRY(cursor,AssociatedWindow,entry);
+ list_remove(cursor);
+ HeapFree(GetProcessHeap(),0,wnd);
+ }
+
+ CompartmentMgr_Destructor(This->CompartmentMgr);
+
HeapFree(GetProcessHeap(),0,This);
}
{
*ppvOut = &This->ClientIdVtbl;
}
+ else if (IsEqualIID(iid, &IID_ITfCompartmentMgr))
+ {
+ *ppvOut = This->CompartmentMgr;
+ }
if (*ppvOut)
{
**ppdim)
{
ThreadMgr *This = (ThreadMgr *)iface;
+ DocumentMgrEntry *mgrentry;
+ HRESULT hr;
+
TRACE("(%p)\n",iface);
- return DocumentMgr_Constructor((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, ppdim);
+ mgrentry = HeapAlloc(GetProcessHeap(),0,sizeof(DocumentMgrEntry));
+ if (mgrentry == NULL)
+ return E_OUTOFMEMORY;
+
+ hr = DocumentMgr_Constructor((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, ppdim);
+
+ if (SUCCEEDED(hr))
+ {
+ mgrentry->docmgr = *ppdim;
+ list_add_head(&This->CreatedDocumentMgrs,&mgrentry->entry);
+ }
+ else
+ HeapFree(GetProcessHeap(),0,mgrentry);
+
+ return hr;
}
static HRESULT WINAPI ThreadMgr_EnumDocumentMgrs( ITfThreadMgr* iface, IEnumTfDocumentMgrs
**ppEnum)
{
ThreadMgr *This = (ThreadMgr *)iface;
- FIXME("STUB:(%p)\n",This);
- return E_NOTIMPL;
+ TRACE("(%p) %p\n",This,ppEnum);
+
+ if (!ppEnum)
+ return E_INVALIDARG;
+
+ return EnumTfDocumentMgr_Constructor(&This->CreatedDocumentMgrs, ppEnum);
}
static HRESULT WINAPI ThreadMgr_GetFocus( ITfThreadMgr* iface, ITfDocumentMgr
TRACE("(%p) %p\n",This,pdimFocus);
- if (!pdimFocus || FAILED(IUnknown_QueryInterface(pdimFocus,&IID_ITfDocumentMgr,(LPVOID*) &check)))
+ if (!pdimFocus)
+ check = NULL;
+ else if (FAILED(IUnknown_QueryInterface(pdimFocus,&IID_ITfDocumentMgr,(LPVOID*) &check)))
return E_INVALIDARG;
ITfThreadMgrEventSink_OnSetFocus((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, check, This->focus);
static HRESULT WINAPI ThreadMgr_AssociateFocus( ITfThreadMgr* iface, HWND hwnd,
ITfDocumentMgr *pdimNew, ITfDocumentMgr **ppdimPrev)
{
+ struct list *cursor, *cursor2;
ThreadMgr *This = (ThreadMgr *)iface;
- FIXME("STUB:(%p)\n",This);
- return E_NOTIMPL;
+ AssociatedWindow *wnd;
+
+ TRACE("(%p) %p %p %p\n",This,hwnd,pdimNew,ppdimPrev);
+
+ if (!ppdimPrev)
+ return E_INVALIDARG;
+
+ *ppdimPrev = NULL;
+
+ LIST_FOR_EACH_SAFE(cursor, cursor2, &This->AssociatedFocusWindows)
+ {
+ wnd = LIST_ENTRY(cursor,AssociatedWindow,entry);
+ if (wnd->hwnd == hwnd)
+ {
+ if (wnd->docmgr)
+ ITfDocumentMgr_AddRef(wnd->docmgr);
+ *ppdimPrev = wnd->docmgr;
+ wnd->docmgr = pdimNew;
+ if (GetFocus() == hwnd)
+ ThreadMgr_SetFocus(iface,pdimNew);
+ return S_OK;
+ }
+ }
+
+ wnd = HeapAlloc(GetProcessHeap(),0,sizeof(AssociatedWindow));
+ wnd->hwnd = hwnd;
+ wnd->docmgr = pdimNew;
+ list_add_head(&This->AssociatedFocusWindows,&wnd->entry);
+
+ if (GetFocus() == hwnd)
+ ThreadMgr_SetFocus(iface,pdimNew);
+
+ SetupWindowsHook(This);
+
+ return S_OK;
}
static HRESULT WINAPI ThreadMgr_IsThreadFocus( ITfThreadMgr* iface, BOOL *pfThreadFocus)
{
+ HWND focus;
ThreadMgr *This = (ThreadMgr *)iface;
- FIXME("STUB:(%p)\n",This);
- return E_NOTIMPL;
+ TRACE("(%p) %p\n",This,pfThreadFocus);
+ focus = GetFocus();
+ *pfThreadFocus = (focus == NULL);
+ return S_OK;
}
static HRESULT WINAPI ThreadMgr_GetFunctionProvider( ITfThreadMgr* iface, REFCLSID clsid,
ITfCompartmentMgr **ppCompMgr)
{
ThreadMgr *This = (ThreadMgr *)iface;
- FIXME("STUB:(%p)\n",This);
- return E_NOTIMPL;
+ HRESULT hr;
+ TRACE("(%p) %p\n",This, ppCompMgr);
+
+ if (!ppCompMgr)
+ return E_INVALIDARG;
+
+ if (!globalCompartmentMgr)
+ {
+ hr = CompartmentMgr_Constructor(NULL,&IID_ITfCompartmentMgr,(IUnknown**)&globalCompartmentMgr);
+ if (FAILED(hr))
+ return hr;
+ }
+
+ ITfCompartmentMgr_AddRef(globalCompartmentMgr);
+ *ppCompMgr = globalCompartmentMgr;
+ return S_OK;
}
static const ITfThreadMgrVtbl ThreadMgr_ThreadMgrVtbl =
This->refCount = 1;
TlsSetValue(tlsIndex,This);
+ CompartmentMgr_Constructor((IUnknown*)This, &IID_IUnknown, (IUnknown**)&This->CompartmentMgr);
+
list_init(&This->CurrentPreservedKeys);
+ list_init(&This->CreatedDocumentMgrs);
+ list_init(&This->AssociatedFocusWindows);
list_init(&This->ActiveLanguageProfileNotifySink);
list_init(&This->DisplayAttributeNotifySink);
*ppOut = (IUnknown *)This;
return S_OK;
}
+
+/**************************************************
+ * IEnumTfDocumentMgrs implementaion
+ **************************************************/
+static void EnumTfDocumentMgr_Destructor(EnumTfDocumentMgr *This)
+{
+ TRACE("destroying %p\n", This);
+ HeapFree(GetProcessHeap(),0,This);
+}
+
+static HRESULT WINAPI EnumTfDocumentMgr_QueryInterface(IEnumTfDocumentMgrs *iface, REFIID iid, LPVOID *ppvOut)
+{
+ EnumTfDocumentMgr *This = (EnumTfDocumentMgr *)iface;
+ *ppvOut = NULL;
+
+ if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumTfDocumentMgrs))
+ {
+ *ppvOut = This;
+ }
+
+ if (*ppvOut)
+ {
+ IUnknown_AddRef(iface);
+ return S_OK;
+ }
+
+ WARN("unsupported interface: %s\n", debugstr_guid(iid));
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI EnumTfDocumentMgr_AddRef(IEnumTfDocumentMgrs *iface)
+{
+ EnumTfDocumentMgr *This = (EnumTfDocumentMgr*)iface;
+ return InterlockedIncrement(&This->refCount);
+}
+
+static ULONG WINAPI EnumTfDocumentMgr_Release(IEnumTfDocumentMgrs *iface)
+{
+ EnumTfDocumentMgr *This = (EnumTfDocumentMgr *)iface;
+ ULONG ret;
+
+ ret = InterlockedDecrement(&This->refCount);
+ if (ret == 0)
+ EnumTfDocumentMgr_Destructor(This);
+ return ret;
+}
+
+static HRESULT WINAPI EnumTfDocumentMgr_Next(IEnumTfDocumentMgrs *iface,
+ ULONG ulCount, ITfDocumentMgr **rgDocumentMgr, ULONG *pcFetched)
+{
+ EnumTfDocumentMgr *This = (EnumTfDocumentMgr *)iface;
+ ULONG fetched = 0;
+
+ TRACE("(%p)\n",This);
+
+ if (rgDocumentMgr == NULL) return E_POINTER;
+
+ while (fetched < ulCount)
+ {
+ DocumentMgrEntry *mgrentry;
+ if (This->index == NULL)
+ break;
+
+ mgrentry = LIST_ENTRY(This->index,DocumentMgrEntry,entry);
+ if (mgrentry == NULL)
+ break;
+
+ *rgDocumentMgr = mgrentry->docmgr;
+ ITfDocumentMgr_AddRef(*rgDocumentMgr);
+
+ This->index = list_next(This->head, This->index);
+ ++fetched;
+ ++rgDocumentMgr;
+ }
+
+ if (pcFetched) *pcFetched = fetched;
+ return fetched == ulCount ? S_OK : S_FALSE;
+}
+
+static HRESULT WINAPI EnumTfDocumentMgr_Skip( IEnumTfDocumentMgrs* iface, ULONG celt)
+{
+ INT i;
+ EnumTfDocumentMgr *This = (EnumTfDocumentMgr *)iface;
+ TRACE("(%p)\n",This);
+ for(i = 0; i < celt && This->index != NULL; i++)
+ This->index = list_next(This->head, This->index);
+ return S_OK;
+}
+
+static HRESULT WINAPI EnumTfDocumentMgr_Reset( IEnumTfDocumentMgrs* iface)
+{
+ EnumTfDocumentMgr *This = (EnumTfDocumentMgr *)iface;
+ TRACE("(%p)\n",This);
+ This->index = list_head(This->head);
+ return S_OK;
+}
+
+static HRESULT WINAPI EnumTfDocumentMgr_Clone( IEnumTfDocumentMgrs *iface,
+ IEnumTfDocumentMgrs **ppenum)
+{
+ EnumTfDocumentMgr *This = (EnumTfDocumentMgr *)iface;
+ HRESULT res;
+
+ TRACE("(%p)\n",This);
+
+ if (ppenum == NULL) return E_POINTER;
+
+ res = EnumTfDocumentMgr_Constructor(This->head, ppenum);
+ if (SUCCEEDED(res))
+ {
+ EnumTfDocumentMgr *new_This = (EnumTfDocumentMgr *)*ppenum;
+ new_This->index = This->index;
+ }
+ return res;
+}
+
+static const IEnumTfDocumentMgrsVtbl IEnumTfDocumentMgrs_Vtbl ={
+ EnumTfDocumentMgr_QueryInterface,
+ EnumTfDocumentMgr_AddRef,
+ EnumTfDocumentMgr_Release,
+
+ EnumTfDocumentMgr_Clone,
+ EnumTfDocumentMgr_Next,
+ EnumTfDocumentMgr_Reset,
+ EnumTfDocumentMgr_Skip
+};
+
+static HRESULT EnumTfDocumentMgr_Constructor(struct list* head, IEnumTfDocumentMgrs **ppOut)
+{
+ EnumTfDocumentMgr *This;
+
+ This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(EnumTfDocumentMgr));
+ if (This == NULL)
+ return E_OUTOFMEMORY;
+
+ This->Vtbl= &IEnumTfDocumentMgrs_Vtbl;
+ This->refCount = 1;
+ This->head = head;
+ This->index = list_head(This->head);
+
+ TRACE("returning %p\n", This);
+ *ppOut = (IEnumTfDocumentMgrs*)This;
+ return S_OK;
+}
+
+void ThreadMgr_OnDocumentMgrDestruction(ITfThreadMgr *tm, ITfDocumentMgr *mgr)
+{
+ ThreadMgr *This = (ThreadMgr *)tm;
+ struct list *cursor;
+ LIST_FOR_EACH(cursor, &This->CreatedDocumentMgrs)
+ {
+ DocumentMgrEntry *mgrentry = LIST_ENTRY(cursor,DocumentMgrEntry,entry);
+ if (mgrentry->docmgr == mgr)
+ {
+ list_remove(cursor);
+ HeapFree(GetProcessHeap(),0,mgrentry);
+ return;
+ }
+ }
+ FIXME("ITfDocumenMgr %p not found in this thread\n",mgr);
+}
+
+LRESULT CALLBACK ThreadFocusHookProc(int nCode, WPARAM wParam, LPARAM lParam)
+{
+ ThreadMgr *This;
+
+ This = TlsGetValue(tlsIndex);
+ if (!This)
+ {
+ ERR("Hook proc but no ThreadMgr for this thread. Serious Error\n");
+ return 0;
+ }
+ if (!This->focusHook)
+ {
+ ERR("Hook proc but no ThreadMgr focus Hook. Serious Error\n");
+ return 0;
+ }
+
+ if (nCode == HCBT_SETFOCUS) /* focus change within our thread */
+ {
+ struct list *cursor;
+
+ LIST_FOR_EACH(cursor, &This->AssociatedFocusWindows)
+ {
+ AssociatedWindow *wnd = LIST_ENTRY(cursor,AssociatedWindow,entry);
+ if (wnd->hwnd == (HWND)wParam)
+ {
+ TRACE("Triggering Associated window focus\n");
+ if (This->focus != wnd->docmgr)
+ ThreadMgr_SetFocus((ITfThreadMgr*)This, wnd->docmgr);
+ break;
+ }
+ }
+ }
+
+ return CallNextHookEx(This->focusHook, nCode, wParam, lParam);
+}
DISPID id;
BSTR name;
tid_t tid;
+ int func_disp_idx;
} func_info_t;
struct dispex_data_t {
DWORD func_cnt;
func_info_t *funcs;
func_info_t **name_table;
+ DWORD func_disp_cnt;
struct list entry;
};
LPWSTR name;
} dynamic_prop_t;
+typedef struct {
+ DispatchEx dispex;
+ const IUnknownVtbl *lpIUnknownVtbl;
+ DispatchEx *obj;
+ func_info_t *info;
+} func_disp_t;
+
+#define FUNCUNKNOWN(x) ((IUnknown*) &(x)->lpIUnknownVtbl)
+
struct dispex_dynamic_data_t {
DWORD buf_size;
DWORD prop_cnt;
dynamic_prop_t *props;
+ func_disp_t **func_disps;
};
#define DISPID_DYNPROP_0 0x50000000
ITypeLib_Release(typelib);
}
-static void add_func_info(dispex_data_t *data, DWORD *size, tid_t tid, DISPID id, ITypeInfo *dti)
+static void add_func_info(dispex_data_t *data, DWORD *size, tid_t tid, const FUNCDESC *desc, ITypeInfo *dti)
{
HRESULT hres;
- if(data->func_cnt && data->funcs[data->func_cnt-1].id == id)
+ if(data->func_cnt && data->funcs[data->func_cnt-1].id == desc->memid)
return;
if(data->func_cnt == *size)
data->funcs = heap_realloc(data->funcs, (*size <<= 1)*sizeof(func_info_t));
- hres = ITypeInfo_GetDocumentation(dti, id, &data->funcs[data->func_cnt].name, NULL, NULL, NULL);
+ hres = ITypeInfo_GetDocumentation(dti, desc->memid, &data->funcs[data->func_cnt].name, NULL, NULL, NULL);
if(FAILED(hres))
return;
- data->funcs[data->func_cnt].id = id;
+ data->funcs[data->func_cnt].id = desc->memid;
data->funcs[data->func_cnt].tid = tid;
+ data->funcs[data->func_cnt].func_disp_idx = desc->invkind == INVOKE_FUNC ? data->func_disp_cnt++ : -1;
data->func_cnt++;
}
data = heap_alloc(sizeof(dispex_data_t));
data->func_cnt = 0;
+ data->func_disp_cnt = 0;
data->funcs = heap_alloc(size*sizeof(func_info_t));
list_add_tail(&dispex_data_list, &data->entry);
if(FAILED(hres))
break;
- add_func_info(data, &size, *tid, funcdesc->memid, dti);
+ add_func_info(data, &size, *tid, funcdesc, dti);
ITypeInfo_ReleaseFuncDesc(ti, funcdesc);
}
return DISPID_DYNPROP_0 <= id && id <= DISPID_DYNPROP_MAX;
}
+static inline dispex_dynamic_data_t *get_dynamic_data(DispatchEx *This, BOOL alloc)
+{
+ return !alloc || This->dynamic_data
+ ? This->dynamic_data
+ : (This->dynamic_data = heap_alloc_zero(sizeof(dispex_dynamic_data_t)));
+}
+
static HRESULT get_dynamic_prop(DispatchEx *This, const WCHAR *name, BOOL alloc, dynamic_prop_t **ret)
{
- dispex_dynamic_data_t *data = This->dynamic_data;
+ dispex_dynamic_data_t *data = get_dynamic_data(This, alloc);
+ unsigned i;
- if(data) {
- unsigned i;
+ if(!data) {
+ if(alloc)
+ return E_OUTOFMEMORY;
- for(i=0; i < data->prop_cnt; i++) {
- if(!strcmpW(data->props[i].name, name)) {
- *ret = data->props+i;
- return S_OK;
- }
- }
+ TRACE("not found %s\n", debugstr_w(name));
+ return DISP_E_UNKNOWNNAME;
}
- if(alloc) {
- TRACE("creating dynamic prop %s\n", debugstr_w(name));
-
- if(!data) {
- data = This->dynamic_data = heap_alloc_zero(sizeof(dispex_dynamic_data_t));
- if(!data)
- return E_OUTOFMEMORY;
+ for(i=0; i < data->prop_cnt; i++) {
+ if(!strcmpW(data->props[i].name, name)) {
+ *ret = data->props+i;
+ return S_OK;
}
+ }
- if(!data->buf_size) {
- data->props = heap_alloc(sizeof(dynamic_prop_t)*4);
- if(!data->props)
- return E_OUTOFMEMORY;
- data->buf_size = 4;
- }else if(data->buf_size == data->prop_cnt) {
- dynamic_prop_t *new_props;
+ TRACE("creating dynamic prop %s\n", debugstr_w(name));
- new_props = heap_realloc(data->props, sizeof(dynamic_prop_t)*(data->buf_size<<1));
- if(!new_props)
- return E_OUTOFMEMORY;
+ if(!data->buf_size) {
+ data->props = heap_alloc(sizeof(dynamic_prop_t)*4);
+ if(!data->props)
+ return E_OUTOFMEMORY;
+ data->buf_size = 4;
+ }else if(data->buf_size == data->prop_cnt) {
+ dynamic_prop_t *new_props;
- data->props = new_props;
- data->buf_size <<= 1;
- }
+ new_props = heap_realloc(data->props, sizeof(dynamic_prop_t)*(data->buf_size<<1));
+ if(!new_props)
+ return E_OUTOFMEMORY;
- data->props[data->prop_cnt].name = heap_strdupW(name);
- VariantInit(&data->props[data->prop_cnt].var);
- *ret = data->props + data->prop_cnt++;
-
- return S_OK;
+ data->props = new_props;
+ data->buf_size <<= 1;
}
- TRACE("not found %s\n", debugstr_w(name));
- return DISP_E_UNKNOWNNAME;
+ data->props[data->prop_cnt].name = heap_strdupW(name);
+ VariantInit(&data->props[data->prop_cnt].var);
+ *ret = data->props + data->prop_cnt++;
+
+ return S_OK;
}
HRESULT dispex_get_dprop_ref(DispatchEx *This, const WCHAR *name, BOOL alloc, VARIANT **ret)
return S_OK;
}
+static HRESULT dispex_value(DispatchEx *This, LCID lcid, WORD flags, DISPPARAMS *params,
+ VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
+{
+ static const WCHAR objectW[] = {'[','o','b','j','e','c','t',']',0};
+
+ if(This->data->vtbl && This->data->vtbl->value)
+ return This->data->vtbl->value(This->outer, lcid, flags, params, res, ei, caller);
+
+ switch(flags) {
+ case DISPATCH_PROPERTYGET:
+ V_VT(res) = VT_BSTR;
+ V_BSTR(res) = SysAllocString(objectW);
+ if(!V_BSTR(res))
+ return E_OUTOFMEMORY;
+ break;
+ default:
+ FIXME("Unimplemented flags %x\n", flags);
+ return E_NOTIMPL;
+ }
+
+ return S_OK;
+}
+
+static HRESULT typeinfo_invoke(DispatchEx *This, func_info_t *func, WORD flags, DISPPARAMS *dp, VARIANT *res,
+ EXCEPINFO *ei)
+{
+ ITypeInfo *ti;
+ IUnknown *unk;
+ UINT argerr=0;
+ HRESULT hres;
+
+ hres = get_typeinfo(func->tid, &ti);
+ if(FAILED(hres)) {
+ ERR("Could not get type info: %08x\n", hres);
+ return hres;
+ }
+
+ hres = IUnknown_QueryInterface(This->outer, tid_ids[func->tid], (void**)&unk);
+ if(FAILED(hres)) {
+ ERR("Could not get iface %s: %08x\n", debugstr_guid(tid_ids[func->tid]), hres);
+ return E_FAIL;
+ }
+
+ hres = ITypeInfo_Invoke(ti, unk, func->id, flags, dp, res, ei, &argerr);
+
+ IUnknown_Release(unk);
+ return hres;
+}
+
+#define FUNCTION_THIS(iface) DEFINE_THIS(func_disp_t, IUnknown, iface)
+
+static HRESULT WINAPI Function_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
+{
+ func_disp_t *This = FUNCTION_THIS(iface);
+
+ if(IsEqualGUID(&IID_IUnknown, riid)) {
+ TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
+ *ppv = FUNCUNKNOWN(This);
+ }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
+ return *ppv ? S_OK : E_NOINTERFACE;
+ }else {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI Function_AddRef(IUnknown *iface)
+{
+ func_disp_t *This = FUNCTION_THIS(iface);
+
+ TRACE("(%p)\n", This);
+
+ return IDispatchEx_AddRef(DISPATCHEX(This->obj));
+}
+
+static ULONG WINAPI Function_Release(IUnknown *iface)
+{
+ func_disp_t *This = FUNCTION_THIS(iface);
+
+ TRACE("(%p)\n", This);
+
+ return IDispatchEx_Release(DISPATCHEX(This->obj));
+}
+
+static HRESULT function_value(IUnknown *iface, LCID lcid, WORD flags, DISPPARAMS *params,
+ VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
+{
+ func_disp_t *This = FUNCTION_THIS(iface);
+ HRESULT hres;
+
+ switch(flags) {
+ case DISPATCH_METHOD:
+ hres = typeinfo_invoke(This->obj, This->info, flags, params, res, ei);
+ break;
+ default:
+ FIXME("Unimplemented flags %x\n", flags);
+ hres = E_NOTIMPL;
+ }
+
+ return hres;
+}
+
+#undef FUNCTION_THIS
+
+static const IUnknownVtbl FunctionUnkVtbl = {
+ Function_QueryInterface,
+ Function_AddRef,
+ Function_Release
+};
+
+static const dispex_static_data_vtbl_t function_dispex_vtbl = {
+ function_value,
+ NULL,
+ NULL
+};
+
+static dispex_static_data_t function_dispex = {
+ &function_dispex_vtbl,
+ LAST_tid,
+ NULL,
+ NULL
+};
+
+static func_disp_t *create_func_disp(DispatchEx *obj, func_info_t *info)
+{
+ func_disp_t *ret;
+
+ ret = heap_alloc_zero(sizeof(func_disp_t));
+ if(!ret)
+ return NULL;
+
+ ret->lpIUnknownVtbl = &FunctionUnkVtbl;
+ init_dispex(&ret->dispex, FUNCUNKNOWN(ret), &function_dispex);
+ ret->obj = obj;
+ ret->info = info;
+
+ return ret;
+}
+
+static HRESULT function_invoke(DispatchEx *This, func_info_t *func, WORD flags, DISPPARAMS *dp, VARIANT *res,
+ EXCEPINFO *ei)
+{
+ HRESULT hres;
+
+ switch(flags) {
+ case DISPATCH_METHOD:
+ hres = typeinfo_invoke(This, func, flags, dp, res, ei);
+ break;
+ case DISPATCH_PROPERTYGET: {
+ dispex_dynamic_data_t *dynamic_data;
+
+ dynamic_data = get_dynamic_data(This, TRUE);
+ if(!dynamic_data)
+ return E_OUTOFMEMORY;
+
+ if(!dynamic_data->func_disps) {
+ dynamic_data->func_disps = heap_alloc_zero(This->data->data->func_disp_cnt * sizeof(func_disp_t*));
+ if(!dynamic_data->func_disps)
+ return E_OUTOFMEMORY;
+ }
+
+ if(!dynamic_data->func_disps[func->func_disp_idx]) {
+ dynamic_data->func_disps[func->func_disp_idx] = create_func_disp(This, func);
+ if(!dynamic_data->func_disps[func->func_disp_idx])
+ return E_OUTOFMEMORY;
+ }
+
+ V_VT(res) = VT_DISPATCH;
+ V_DISPATCH(res) = (IDispatch*)DISPATCHEX(&dynamic_data->func_disps[func->func_disp_idx]->dispex);
+ IDispatch_AddRef(V_DISPATCH(res));
+ hres = S_OK;
+ break;
+ }
+ default:
+ FIXME("Unimplemented flags %x\n", flags);
+ case DISPATCH_PROPERTYPUT:
+ hres = E_NOTIMPL;
+ }
+
+ return hres;
+}
+
#define DISPATCHEX_THIS(iface) DEFINE_THIS(DispatchEx, IDispatchEx, iface)
static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv)
VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
{
DispatchEx *This = DISPATCHEX_THIS(iface);
- IUnknown *unk;
- ITypeInfo *ti;
dispex_data_t *data;
- UINT argerr=0;
int min, max, n;
HRESULT hres;
TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
+ if(id == DISPID_VALUE)
+ return dispex_value(This, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
+
if(is_custom_dispid(id) && This->data->vtbl && This->data->vtbl->invoke)
return This->data->vtbl->invoke(This->outer, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
return DISP_E_UNKNOWNNAME;
}
- hres = get_typeinfo(data->funcs[n].tid, &ti);
- if(FAILED(hres)) {
- ERR("Could not get type info: %08x\n", hres);
- return hres;
- }
-
- hres = IUnknown_QueryInterface(This->outer, tid_ids[data->funcs[n].tid], (void**)&unk);
- if(FAILED(hres)) {
- ERR("Could not get iface %s: %08x\n", debugstr_guid(tid_ids[data->funcs[n].tid]), hres);
- return E_FAIL;
- }
+ if(data->funcs[n].func_disp_idx == -1)
+ hres = typeinfo_invoke(This, data->funcs+n, wFlags, pdp, pvarRes, pei);
+ else
+ hres = function_invoke(This, data->funcs+n, wFlags, pdp, pvarRes, pei);
- hres = ITypeInfo_Invoke(ti, unk, id, wFlags, pdp, pvarRes, pei, &argerr);
-
- IUnknown_Release(unk);
return hres;
}
return TRUE;
}
+void release_dispex(DispatchEx *This)
+{
+ dynamic_prop_t *prop;
+
+ if(!This->dynamic_data)
+ return;
+
+ for(prop = This->dynamic_data->props; prop < This->dynamic_data->props + This->dynamic_data->prop_cnt; prop++) {
+ VariantClear(&prop->var);
+ heap_free(prop->name);
+ }
+
+ heap_free(This->dynamic_data->props);
+
+ if(This->dynamic_data->func_disps) {
+ unsigned i;
+
+ for(i=0; i < This->data->data->func_disp_cnt; i++) {
+ if(This->dynamic_data->func_disps[i]) {
+ release_dispex(&This->dynamic_data->func_disps[i]->dispex);
+ heap_free(This->dynamic_data->func_disps[i]);
+ }
+ }
+
+ heap_free(This->dynamic_data->func_disps);
+ }
+
+ heap_free(This->dynamic_data);
+}
+
void init_dispex(DispatchEx *dispex, IUnknown *outer, dispex_static_data_t *data)
{
dispex->lpIDispatchExVtbl = &DispatchExVtbl;
dispex->outer = outer;
dispex->data = data;
+ dispex->dynamic_data = NULL;
}
if(!ref) {
if(This->nsstyle)
nsIDOMCSSStyleDeclaration_Release(This->nsstyle);
+ release_dispex(&This->dispex);
heap_free(This);
}
static HRESULT WINAPI HTMLCurrentStyle_get_color(IHTMLCurrentStyle *iface, VARIANT *p)
{
HTMLCurrentStyle *This = HTMLCURSTYLE_THIS(iface);
- FIXME("(%p)->(%p)\n", This, p);
- return E_NOTIMPL;
+ TRACE("(%p)->(%p)\n", This, p);
+ return get_nsstyle_attr_var(This->nsstyle, STYLEID_COLOR, p, 0);
}
static HRESULT WINAPI HTMLCurrentStyle_get_backgroundColor(IHTMLCurrentStyle *iface, VARIANT *p)
{
HTMLCurrentStyle *This = HTMLCURSTYLE_THIS(iface);
- FIXME("(%p)->(%p)\n", This, p);
- return E_NOTIMPL;
+ TRACE("(%p)->(%p)\n", This, p);
+ return get_nsstyle_attr_var(This->nsstyle, STYLEID_BACKGROUND_COLOR, p, 0);
}
static HRESULT WINAPI HTMLCurrentStyle_get_fontFamily(IHTMLCurrentStyle *iface, BSTR *p)
static HRESULT WINAPI HTMLCurrentStyle_get_borderTopWidth(IHTMLCurrentStyle *iface, VARIANT *p)
{
HTMLCurrentStyle *This = HTMLCURSTYLE_THIS(iface);
- FIXME("(%p)->(%p)\n", This, p);
- return E_NOTIMPL;
+ TRACE("(%p)->(%p)\n", This, p);
+ return get_nsstyle_attr_var(This->nsstyle, STYLEID_BORDER_TOP_WIDTH, p, 0);
}
static HRESULT WINAPI HTMLCurrentStyle_get_borderRightWidth(IHTMLCurrentStyle *iface, VARIANT *p)
{
HTMLCurrentStyle *This = HTMLCURSTYLE_THIS(iface);
- FIXME("(%p)->(%p)\n", This, p);
- return E_NOTIMPL;
+ TRACE("(%p)->(%p)\n", This, p);
+ return get_nsstyle_attr_var(This->nsstyle, STYLEID_BORDER_RIGHT_WIDTH, p, 0);
}
static HRESULT WINAPI HTMLCurrentStyle_get_borderBottomWidth(IHTMLCurrentStyle *iface, VARIANT *p)
{
HTMLCurrentStyle *This = HTMLCURSTYLE_THIS(iface);
- FIXME("(%p)->(%p)\n", This, p);
- return E_NOTIMPL;
+ TRACE("(%p)->(%p)\n", This, p);
+ return get_nsstyle_attr_var(This->nsstyle, STYLEID_BORDER_BOTTOM_WIDTH, p, 0);
}
static HRESULT WINAPI HTMLCurrentStyle_get_borderLeftWidth(IHTMLCurrentStyle *iface, VARIANT *p)
{
HTMLCurrentStyle *This = HTMLCURSTYLE_THIS(iface);
- FIXME("(%p)->(%p)\n", This, p);
- return E_NOTIMPL;
+ TRACE("(%p)->(%p)\n", This, p);
+ return get_nsstyle_attr_var(This->nsstyle, STYLEID_BORDER_LEFT_WIDTH, p, 0);
}
static HRESULT WINAPI HTMLCurrentStyle_get_left(IHTMLCurrentStyle *iface, VARIANT *p)
static HRESULT WINAPI HTMLCurrentStyle_get_visibility(IHTMLCurrentStyle *iface, BSTR *p)
{
HTMLCurrentStyle *This = HTMLCURSTYLE_THIS(iface);
- FIXME("(%p)->(%p)\n", This, p);
- return E_NOTIMPL;
+
+ TRACE("(%p)->(%p)\n", This, p);
+
+ return get_nsstyle_attr(This->nsstyle, STYLEID_VISIBILITY, p);
}
static HRESULT WINAPI HTMLCurrentStyle_get_zIndex(IHTMLCurrentStyle *iface, VARIANT *p)
static HRESULT WINAPI HTMLCurrentStyle_get_overflow(IHTMLCurrentStyle *iface, BSTR *p)
{
HTMLCurrentStyle *This = HTMLCURSTYLE_THIS(iface);
- FIXME("(%p)->(%p)\n", This, p);
- return E_NOTIMPL;
+ TRACE("(%p)->(%p)\n", This, p);
+ return get_nsstyle_attr(This->nsstyle, STYLEID_OVERFLOW, p);
}
static HRESULT WINAPI HTMLCurrentStyle_get_pageBreakBefore(IHTMLCurrentStyle *iface, BSTR *p)
static HRESULT WINAPI HTMLCurrentStyle_get_borderWidth(IHTMLCurrentStyle *iface, BSTR *p)
{
HTMLCurrentStyle *This = HTMLCURSTYLE_THIS(iface);
- FIXME("(%p)->(%p)\n", This, p);
- return E_NOTIMPL;
+ TRACE("(%p)->(%p)\n", This, p);
+ return get_nsstyle_attr(This->nsstyle, STYLEID_BORDER_WIDTH, p);
}
static HRESULT WINAPI HTMLCurrentStyle_get_padding(IHTMLCurrentStyle *iface, BSTR *p)
static HRESULT WINAPI HTMLCurrentStyle_get_margin(IHTMLCurrentStyle *iface, BSTR *p)
{
HTMLCurrentStyle *This = HTMLCURSTYLE_THIS(iface);
- FIXME("(%p)->(%p)\n", This, p);
- return E_NOTIMPL;
+ TRACE("(%p)->(%p)\n", This, p);
+ return get_nsstyle_attr(This->nsstyle, STYLEID_MARGIN, p);
}
static HRESULT WINAPI HTMLCurrentStyle_get_accelerator(IHTMLCurrentStyle *iface, BSTR *p)
detach_selection(This);
detach_ranges(This);
release_nodes(This);
+ release_dispex(&This->dispex);
ConnectionPointContainer_Destroy(&This->cp_container);
return E_NOTIMPL;
}
-static HRESULT WINAPI HTMLDocument_write(IHTMLDocument2 *iface, SAFEARRAY *psarray)
+static HRESULT document_write(HTMLDocument *This, SAFEARRAY *psarray, BOOL ln)
{
- HTMLDocument *This = HTMLDOC_THIS(iface);
nsAString nsstr;
VARIANT *var;
- ULONG i;
+ ULONG i, argc;
nsresult nsres;
HRESULT hres;
- TRACE("(%p)->(%p)\n", iface, psarray);
-
if(!This->nsdoc) {
WARN("NULL nsdoc\n");
return E_UNEXPECTED;
nsAString_Init(&nsstr, NULL);
- for(i=0; i < psarray->rgsabound[0].cElements; i++) {
+ argc = psarray->rgsabound[0].cElements;
+ for(i=0; i < argc; i++) {
if(V_VT(var+i) == VT_BSTR) {
nsAString_SetData(&nsstr, V_BSTR(var+i));
- nsres = nsIDOMHTMLDocument_Write(This->nsdoc, &nsstr);
+ if(!ln || i != argc-1)
+ nsres = nsIDOMHTMLDocument_Write(This->nsdoc, &nsstr);
+ else
+ nsres = nsIDOMHTMLDocument_Writeln(This->nsdoc, &nsstr);
if(NS_FAILED(nsres))
ERR("Write failed: %08x\n", nsres);
}else {
return S_OK;
}
+static HRESULT WINAPI HTMLDocument_write(IHTMLDocument2 *iface, SAFEARRAY *psarray)
+{
+ HTMLDocument *This = HTMLDOC_THIS(iface);
+
+ TRACE("(%p)->(%p)\n", iface, psarray);
+
+ return document_write(This, psarray, FALSE);
+}
+
static HRESULT WINAPI HTMLDocument_writeln(IHTMLDocument2 *iface, SAFEARRAY *psarray)
{
HTMLDocument *This = HTMLDOC_THIS(iface);
- FIXME("(%p)->(%p)\n", This, psarray);
- return E_NOTIMPL;
+
+ TRACE("(%p)->(%p)\n", This, psarray);
+
+ return document_write(This, psarray, TRUE);
}
static HRESULT WINAPI HTMLDocument_open(IHTMLDocument2 *iface, BSTR url, VARIANT name,
static HRESULT WINAPI HTMLElement_get_outerHTML(IHTMLElement *iface, BSTR *p)
{
HTMLElement *This = HTMLELEM_THIS(iface);
- FIXME("(%p)->(%p)\n", This, p);
- return E_NOTIMPL;
+ nsAString html_str;
+ HRESULT hres;
+
+ WARN("(%p)->(%p) semi-stub\n", This, p);
+
+ nsAString_Init(&html_str, NULL);
+ hres = nsnode_to_nsstring(This->node.nsnode, &html_str);
+ if(SUCCEEDED(hres)) {
+ const PRUnichar *html;
+
+ nsAString_GetData(&html_str, &html);
+ *p = SysAllocString(html);
+ if(!*p)
+ hres = E_OUTOFMEMORY;
+ }
+
+ nsAString_Finish(&html_str);
+
+ TRACE("ret %s\n", debugstr_w(*p));
+ return S_OK;
}
static HRESULT WINAPI HTMLElement_put_outerText(IHTMLElement *iface, BSTR v)
if(!ref) {
IUnknown_Release(This->ref_unk);
+ release_dispex(&This->dispex);
heap_free(This->elems);
heap_free(This);
}
};
static const dispex_static_data_vtbl_t HTMLElementColection_dispex_vtbl = {
+ NULL,
HTMLElementCollection_get_dispid,
HTMLElementCollection_invoke
};
TRACE("(%p) ref=%d\n", This, ref);
- if(!ref)
+ if(!ref) {
+ release_dispex(&This->dispex);
heap_free(This);
+ }
return ref;
}
TRACE("(%p)->(%p)\n", This, p);
- return IHTMLInputTextElement_get_value(HTMLINPUT(This), p);
+ return IHTMLInputElement_get_value(HTMLINPUT(This), p);
}
static HRESULT WINAPI HTMLInputTextElement_put_name(IHTMLInputTextElement *iface, BSTR v)
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
+#include "winreg.h"
#include "ole2.h"
+#include "wininet.h"
+#include "shlwapi.h"
#include "wine/debug.h"
if(!ref) {
if(This->doc && This->doc->location == This)
This->doc->location = NULL;
+ release_dispex(&This->dispex);
heap_free(This);
}
static HRESULT WINAPI HTMLLocation_get_href(IHTMLLocation *iface, BSTR *p)
{
HTMLLocation *This = HTMLLOCATION_THIS(iface);
- FIXME("(%p)->(%p)\n", This, p);
- return E_NOTIMPL;
+
+ TRACE("(%p)->(%p)\n", This, p);
+
+ if(!p)
+ return E_POINTER;
+
+ if(!This->doc || !This->doc->url) {
+ FIXME("No current URL\n");
+ return E_NOTIMPL;
+ }
+
+ *p = SysAllocString(This->doc->url);
+
+ return S_OK;
}
static HRESULT WINAPI HTMLLocation_put_protocol(IHTMLLocation *iface, BSTR v)
static HRESULT WINAPI HTMLLocation_get_pathname(IHTMLLocation *iface, BSTR *p)
{
HTMLLocation *This = HTMLLOCATION_THIS(iface);
- FIXME("(%p)->(%p)\n", This, p);
- return E_NOTIMPL;
+ WCHAR buf[INTERNET_MAX_PATH_LENGTH];
+ URL_COMPONENTSW url = {sizeof(url)};
+ DWORD size = 0;
+ HRESULT hres;
+
+ TRACE("(%p)->(%p)\n", This, p);
+
+ if(!This->doc || !This->doc->url) {
+ FIXME("No current URL\n");
+ return E_NOTIMPL;
+ }
+
+ hres = CoInternetParseUrl(This->doc->url, PARSE_PATH_FROM_URL, 0, buf, sizeof(buf), &size, 0);
+ if(SUCCEEDED(hres)) {
+ *p = SysAllocString(buf);
+ if(!*p)
+ return E_OUTOFMEMORY;
+ return S_OK;
+ }
+
+ url.dwUrlPathLength = 1;
+ if(!InternetCrackUrlW(This->doc->url, 0, 0, &url)) {
+ FIXME("InternetCrackUrl failed\n");
+ return E_FAIL;
+ }
+
+ if(!url.dwUrlPathLength) {
+ *p = NULL;
+ return S_OK;
+ }
+
+ *p = SysAllocStringLen(url.lpszUrlPath, url.dwUrlPathLength);
+ if(!*p)
+ return E_OUTOFMEMORY;
+ return S_OK;
}
static HRESULT WINAPI HTMLLocation_put_search(IHTMLLocation *iface, BSTR v)
return E_NOTIMPL;
}
+static HRESULT HTMLLocation_value(IUnknown *iface, LCID lcid, WORD flags, DISPPARAMS *params,
+ VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
+{
+ HTMLLocation *This = HTMLLOCATION_THIS(iface);
+ HRESULT hres;
+
+ TRACE("(%p)\n", This);
+
+ switch(flags) {
+ case DISPATCH_PROPERTYGET: {
+ BSTR str;
+
+ hres = IHTMLLocation_get_href(HTMLLOCATION(This), &str);
+ if(FAILED(hres))
+ return hres;
+
+ V_VT(res) = VT_BSTR;
+ V_BSTR(res) = str;
+ break;
+ }
+ default:
+ FIXME("unimplemented flags %x\n", flags);
+ return E_NOTIMPL;
+ }
+
+ return S_OK;
+}
+
#undef HTMLLOCATION_THIS
static const IHTMLLocationVtbl HTMLLocationVtbl = {
HTMLLocation_toString
};
+static const dispex_static_data_vtbl_t HTMLLocation_dispex_vtbl = {
+ HTMLLocation_value,
+ NULL,
+ NULL
+};
+
static const tid_t HTMLLocation_iface_tids[] = {
IHTMLLocation_tid,
0
};
static dispex_static_data_t HTMLLocation_dispex = {
- NULL,
+ &HTMLLocation_dispex_vtbl,
DispHTMLLocation_tid,
NULL,
HTMLLocation_iface_tids
};
static const dispex_static_data_vtbl_t HTMLDOMChildrenCollection_dispex_vtbl = {
+ NULL,
HTMLDOMChildrenCollection_get_dispid,
HTMLDOMChildrenCollection_invoke
};
if(!ref) {
This->vtbl->destructor(This);
+ release_dispex(&This->dispex);
heap_free(This);
}
{'b','o','r','d','e','r','-','l','e','f','t',0};
static const WCHAR attrBorderLeftStyle[] =
{'b','o','r','d','e','r','-','l','e','f','t','-','s','t','y','l','e',0};
+static const WCHAR attrBorderLeftWidth[] =
+ {'b','o','r','d','e','r','-','l','e','f','t','-','w','i','d','t','h',0};
static const WCHAR attrBorderRightStyle[] =
{'b','o','r','d','e','r','-','r','i','g','h','t','-','s','t','y','l','e',0};
static const WCHAR attrBorderRightWidth[] =
{'h','e','i','g','h','t',0};
static const WCHAR attrLeft[] =
{'l','e','f','t',0};
+static const WCHAR attrLetterSpacing[] =
+ {'l','e','t','t','e','r','-','s','p','a','c','i','n','g',0};
static const WCHAR attrMargin[] =
{'m','a','r','g','i','n',0};
static const WCHAR attrMarginLeft[] =
{'v','i','s','i','b','i','l','i','t','y',0};
static const WCHAR attrWidth[] =
{'w','i','d','t','h',0};
+static const WCHAR attrWordSpacing[] =
+ {'w','o','r','d','-','s','p','a','c','i','n','g',0};
static const WCHAR attrWordWrap[] =
{'w','o','r','d','-','w','r','a','p',0};
static const WCHAR attrZIndex[] =
{attrBorderColor, DISPID_IHTMLSTYLE_BORDERCOLOR},
{attrBorderLeft, DISPID_IHTMLSTYLE_BORDERLEFT},
{attrBorderLeftStyle, DISPID_IHTMLSTYLE_BORDERLEFTSTYLE},
+ {attrBorderLeftWidth, DISPID_IHTMLSTYLE_BORDERLEFTWIDTH},
{attrBorderRightStyle, DISPID_IHTMLSTYLE_BORDERRIGHTSTYLE},
{attrBorderRightWidth, DISPID_IHTMLSTYLE_BORDERRIGHTWIDTH},
{attrBorderStyle, DISPID_IHTMLSTYLE_BORDERSTYLE},
{attrFontWeight, DISPID_IHTMLSTYLE_FONTWEIGHT},
{attrHeight, DISPID_IHTMLSTYLE_HEIGHT},
{attrLeft, DISPID_IHTMLSTYLE_LEFT},
+ {attrLetterSpacing, DISPID_IHTMLSTYLE_LETTERSPACING},
{attrMargin, DISPID_IHTMLSTYLE_MARGIN},
{attrMarginLeft, DISPID_IHTMLSTYLE_MARGINLEFT},
{attrMarginRight, DISPID_IHTMLSTYLE_MARGINRIGHT},
{attrVerticalAlign, DISPID_IHTMLSTYLE_VERTICALALIGN},
{attrVisibility, DISPID_IHTMLSTYLE_VISIBILITY},
{attrWidth, DISPID_IHTMLSTYLE_WIDTH},
+ {attrWordSpacing, DISPID_IHTMLSTYLE_WORDSPACING},
{attrWordWrap, DISPID_IHTMLSTYLE3_WORDWRAP},
{attrZIndex, DISPID_IHTMLSTYLE_ZINDEX}
};
if(!ref) {
if(This->nsstyle)
nsIDOMCSSStyleDeclaration_Release(This->nsstyle);
+ release_dispex(&This->dispex);
heap_free(This);
}
static HRESULT WINAPI HTMLStyle_put_wordSpacing(IHTMLStyle *iface, VARIANT v)
{
HTMLStyle *This = HTMLSTYLE_THIS(iface);
- FIXME("(%p)->(v%d)\n", This, V_VT(&v));
- return E_NOTIMPL;
+ TRACE("(%p)->(v%d)\n", This, V_VT(&v));
+ return set_nsstyle_attr_var(This->nsstyle, STYLEID_WORD_SPACING, &v, 0);
}
static HRESULT WINAPI HTMLStyle_get_wordSpacing(IHTMLStyle *iface, VARIANT *p)
{
HTMLStyle *This = HTMLSTYLE_THIS(iface);
- FIXME("(%p)->(%p)\n", This, p);
- return E_NOTIMPL;
+ TRACE("(%p)->(%p)\n", This, p);
+ return get_nsstyle_attr_var(This->nsstyle, STYLEID_WORD_SPACING, p, 0);
}
static HRESULT WINAPI HTMLStyle_put_letterSpacing(IHTMLStyle *iface, VARIANT v)
{
HTMLStyle *This = HTMLSTYLE_THIS(iface);
- FIXME("(%p)->(v%d)\n", This, V_VT(&v));
- return E_NOTIMPL;
+ TRACE("(%p)->(v%d)\n", This, V_VT(&v));
+ return set_nsstyle_attr_var(This->nsstyle, STYLEID_LETTER_SPACING, &v, 0);
}
static HRESULT WINAPI HTMLStyle_get_letterSpacing(IHTMLStyle *iface, VARIANT *p)
{
HTMLStyle *This = HTMLSTYLE_THIS(iface);
- FIXME("(%p)->(%p)\n", This, p);
- return E_NOTIMPL;
+ TRACE("(%p)->(%p)\n", This, p);
+ return get_nsstyle_attr_var(This->nsstyle, STYLEID_LETTER_SPACING, p, 0);
}
static HRESULT WINAPI HTMLStyle_put_textDecoration(IHTMLStyle *iface, BSTR v)
static HRESULT WINAPI HTMLStyle_put_borderLeftWidth(IHTMLStyle *iface, VARIANT v)
{
HTMLStyle *This = HTMLSTYLE_THIS(iface);
- FIXME("(%p)->(v%d)\n", This, V_VT(&v));
- return E_NOTIMPL;
+ TRACE("(%p)->(v%d)\n", This, V_VT(&v));
+ return set_nsstyle_attr_var(This->nsstyle, STYLEID_BORDER_LEFT_WIDTH, &v, 0);
}
static HRESULT WINAPI HTMLStyle_get_borderLeftWidth(IHTMLStyle *iface, VARIANT *p)
{
HTMLStyle *This = HTMLSTYLE_THIS(iface);
- FIXME("(%p)->(%p)\n", This, p);
- return E_NOTIMPL;
+ TRACE("(%p)->(%p)\n", This, p);
+ return get_nsstyle_attr_var(This->nsstyle, STYLEID_BORDER_LEFT_WIDTH, p, 0);
}
static HRESULT WINAPI HTMLStyle_put_borderStyle(IHTMLStyle *iface, BSTR v)
};
static const dispex_static_data_vtbl_t HTMLStyle_dispex_vtbl = {
+ NULL,
HTMLStyle_get_dispid,
NULL
};
STYLEID_BORDER_COLOR,
STYLEID_BORDER_LEFT,
STYLEID_BORDER_LEFT_STYLE,
+ STYLEID_BORDER_LEFT_WIDTH,
STYLEID_BORDER_RIGHT_STYLE,
STYLEID_BORDER_RIGHT_WIDTH,
STYLEID_BORDER_STYLE,
STYLEID_FONT_WEIGHT,
STYLEID_HEIGHT,
STYLEID_LEFT,
+ STYLEID_LETTER_SPACING,
STYLEID_MARGIN,
STYLEID_MARGIN_LEFT,
STYLEID_MARGIN_RIGHT,
STYLEID_VERTICAL_ALIGN,
STYLEID_VISIBILITY,
STYLEID_WIDTH,
+ STYLEID_WORD_SPACING,
STYLEID_WORD_WRAP,
STYLEID_Z_INDEX
} styleid_t;
if(!ref) {
list_remove(&This->entry);
+ release_dispex(&This->dispex);
heap_free(This);
}
static HRESULT WINAPI HTMLWindow2_toString(IHTMLWindow2 *iface, BSTR *String)
{
HTMLWindow *This = HTMLWINDOW2_THIS(iface);
- FIXME("(%p)->(%p)\n", This, String);
- return E_NOTIMPL;
+
+ static const WCHAR objectW[] = {'[','o','b','j','e','c','t',']',0};
+
+ TRACE("(%p)->(%p)\n", This, String);
+
+ if(!String)
+ return E_INVALIDARG;
+
+ *String = SysAllocString(objectW);
+ return *String ? S_OK : E_OUTOFMEMORY;
}
static HRESULT WINAPI HTMLWindow2_scrollBy(IHTMLWindow2 *iface, LONG x, LONG y)
<library>gdi32</library>
<library>advapi32</library>
<library>kernel32</library>
+ <library>wininet</library>
<library>ntdll</library>
<dependency>mshtml_nsiface_header</dependency>
</module>
#include "nsiface.h"
-#define GENERATE_MSHTML_NS_FAILURE(code) \
- ((nsresult) ((PRUint32)(1<<31) | ((PRUint32)(0x45+6)<<16) | (PRUint32)(code)))
-
#define NS_OK ((nsresult)0x00000000L)
#define NS_ERROR_FAILURE ((nsresult)0x80004005L)
#define NS_NOINTERFACE ((nsresult)0x80004002L)
#define NS_ERROR_UNEXPECTED ((nsresult)0x8000ffffL)
#define NS_ERROR_UNKNOWN_PROTOCOL ((nsresult)0x804b0012L)
-#define WINE_NS_LOAD_FROM_MONIKER GENERATE_MSHTML_NS_FAILURE(0)
-
#define NS_FAILED(res) ((res) & 0x80000000)
#define NS_SUCCEEDED(res) (!NS_FAILED(res))
#define MSHTML_DISPID_CUSTOM_MAX 0x6fffffff
typedef struct {
+ HRESULT (*value)(IUnknown*,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,IServiceProvider*);
HRESULT (*get_dispid)(IUnknown*,BSTR,DWORD,DISPID*);
HRESULT (*invoke)(IUnknown*,DISPID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,IServiceProvider*);
} dispex_static_data_vtbl_t;
} DispatchEx;
void init_dispex(DispatchEx*,IUnknown*,dispex_static_data_t*);
+void release_dispex(DispatchEx*);
BOOL dispex_query_interface(DispatchEx*,REFIID,void**);
HRESULT dispex_get_dprop_ref(DispatchEx*,const WCHAR*,BOOL,VARIANT**);
typedef struct {
const nsIHttpChannelVtbl *lpHttpChannelVtbl;
const nsIUploadChannelVtbl *lpUploadChannelVtbl;
+ const nsIHttpChannelInternalVtbl *lpIHttpChannelInternalVtbl;
LONG ref;
nsIChannel *channel;
nsIHttpChannel *http_channel;
+ nsIHttpChannelInternal *http_channel_internal;
nsIWineURI *uri;
nsIInputStream *post_data_stream;
nsILoadGroup *load_group;
nsIURI *original_uri;
char *content_type;
char *charset;
+ PRUint32 response_status;
} nsChannel;
typedef struct {
#define NSCHANNEL(x) ((nsIChannel*) &(x)->lpHttpChannelVtbl)
#define NSHTTPCHANNEL(x) ((nsIHttpChannel*) &(x)->lpHttpChannelVtbl)
#define NSUPCHANNEL(x) ((nsIUploadChannel*) &(x)->lpUploadChannelVtbl)
+#define NSHTTPINTERNAL(x) ((nsIHttpChannelInternal*) &(x)->lpIHttpChannelInternalVtbl)
#define HTTPNEG(x) ((IHttpNegotiate2*) &(x)->lpHttpNegotiate2Vtbl)
#define STATUSCLB(x) ((IBindStatusCallback*) &(x)->lpBindStatusCallbackVtbl)
PRUint32 nsAString_GetData(const nsAString*,const PRUnichar**);
void nsAString_Finish(nsAString*);
-nsIInputStream *create_nsstream(const char*,PRInt32);
nsICommandParams *create_nscommand_params(void);
-void nsnode_to_nsstring(nsIDOMNode*,nsAString*);
+HRESULT nsnode_to_nsstring(nsIDOMNode*,nsAString*);
void get_editor_controller(NSContainer*);
void init_nsevents(NSContainer*);
void add_nsevent_listener(NSContainer*,LPCWSTR);
static void NSAPI nsDocumentObserver_EndLoad(nsIDocumentObserver *iface, nsIDocument *aDocument)
{
+ NSContainer *This = NSDOCOBS_THIS(iface);
+ task_t *task;
+
+ TRACE("\n");
+
+ task = heap_alloc(sizeof(task_t));
+
+ task->doc = This->doc;
+ task->task_id = TASK_PARSECOMPLETE;
+ task->next = NULL;
+
+ /*
+ * This should be done in the worker thread that parses HTML,
+ * but we don't have such thread (Gecko parses HTML for us).
+ */
+ push_task(task);
}
static void NSAPI nsDocumentObserver_ContentStatesChanged(nsIDocumentObserver *iface, nsIDocument *aDocument,
typedef struct {
void (*destroy)(BSCallback*);
+ HRESULT (*init_bindinfo)(BSCallback*);
HRESULT (*start_binding)(BSCallback*);
HRESULT (*stop_binding)(BSCallback*,HRESULT);
HRESULT (*read_data)(BSCallback*,IStream*);
HRESULT (*on_progress)(BSCallback*,ULONG,LPCWSTR);
+ HRESULT (*on_response)(BSCallback*,DWORD);
} BSCallbackVtbl;
struct BSCallback {
ULONG post_data_len;
ULONG readed;
DWORD bindf;
+ BOOL bindinfo_ready;
IMoniker *mon;
IBinding *binding;
HRESULT hresult, LPCWSTR szError)
{
BSCallback *This = STATUSCLB_THIS(iface);
+ HRESULT hres;
TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError));
/* NOTE: IE7 calls GetBindResult here */
+ hres = This->vtbl->stop_binding(This, hresult);
+
if(This->binding) {
IBinding_Release(This->binding);
This->binding = NULL;
}
list_remove(&This->entry);
+ This->doc = NULL;
- return This->vtbl->stop_binding(This, hresult);
+ return hres;
}
static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallback *iface,
TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
+ if(!This->bindinfo_ready) {
+ HRESULT hres;
+
+ hres = This->vtbl->init_bindinfo(This);
+ if(FAILED(hres))
+ return hres;
+
+ This->bindinfo_ready = TRUE;
+ }
+
*grfBINDF = This->bindf;
size = pbindinfo->cbSize;
LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders)
{
BSCallback *This = HTTPNEG_THIS(iface);
- FIXME("(%p)->(%d %s %s %p)\n", This, dwResponseCode, debugstr_w(szResponseHeaders),
+
+ TRACE("(%p)->(%d %s %s %p)\n", This, dwResponseCode, debugstr_w(szResponseHeaders),
debugstr_w(szRequestHeaders), pszAdditionalRequestHeaders);
- return E_NOTIMPL;
+
+ return This->vtbl->on_response(This, dwResponseCode);
}
static HRESULT WINAPI HttpNegotiate_GetRootSecurityId(IHttpNegotiate2 *iface,
heap_free(This);
}
+static HRESULT BufferBSC_init_bindinfo(BSCallback *bsc)
+{
+ return S_OK;
+}
+
static HRESULT BufferBSC_start_binding(BSCallback *bsc)
{
return S_OK;
return S_OK;
}
+static HRESULT BufferBSC_on_response(BSCallback *bsc, DWORD response_code)
+{
+ return S_OK;
+}
+
#undef BUFFERBSC_THIS
static const BSCallbackVtbl BufferBSCVtbl = {
BufferBSC_destroy,
+ BufferBSC_init_bindinfo,
BufferBSC_start_binding,
BufferBSC_stop_binding,
BufferBSC_read_data,
BufferBSC_on_progress,
+ BufferBSC_on_response
};
nsProtocolStream *nsstream;
};
+static void on_start_nsrequest(nsChannelBSC *This)
+{
+ nsresult nsres;
+
+ /* FIXME: it's needed for http connections from BindToObject. */
+ if(!This->nschannel->response_status)
+ This->nschannel->response_status = 200;
+
+ nsres = nsIStreamListener_OnStartRequest(This->nslistener,
+ (nsIRequest*)NSCHANNEL(This->nschannel), This->nscontext);
+ if(NS_FAILED(nsres))
+ FIXME("OnStartRequest failed: %08x\n", nsres);
+}
+
+static void on_stop_nsrequest(nsChannelBSC *This)
+{
+ nsresult nsres;
+
+ if(!This->nslistener)
+ return;
+
+ if(!This->bsc.readed) {
+ TRACE("No data read! Calling OnStartRequest\n");
+ on_start_nsrequest(This);
+ }
+
+ nsres = nsIStreamListener_OnStopRequest(This->nslistener, (nsIRequest*)NSCHANNEL(This->nschannel),
+ This->nscontext, NS_OK);
+ if(NS_FAILED(nsres))
+ WARN("OnStopRequest failed: %08x\n", nsres);
+}
+
static HRESULT read_stream_data(nsChannelBSC *This, IStream *stream)
{
+ DWORD read;
nsresult nsres;
HRESULT hres;
if(!This->nslistener) {
BYTE buf[1024];
- DWORD read;
do {
read = 0;
This->nsstream = create_nsprotocol_stream();
do {
- hres = IStream_Read(stream, This->nsstream->buf, sizeof(This->nsstream->buf),
- &This->nsstream->buf_size);
- if(!This->nsstream->buf_size)
+ read = 0;
+ hres = IStream_Read(stream, This->nsstream->buf+This->nsstream->buf_size,
+ sizeof(This->nsstream->buf)-This->nsstream->buf_size, &read);
+ if(!read)
break;
- if(!This->bsc.readed && This->nsstream->buf_size >= 2 && *(WORD*)This->nsstream->buf == 0xfeff) {
- This->nschannel->charset = heap_alloc(sizeof(UTF16_STR));
- memcpy(This->nschannel->charset, UTF16_STR, sizeof(UTF16_STR));
- }
+ This->nsstream->buf_size += read;
if(!This->bsc.readed) {
- nsres = nsIStreamListener_OnStartRequest(This->nslistener,
- (nsIRequest*)NSCHANNEL(This->nschannel), This->nscontext);
- if(NS_FAILED(nsres))
- FIXME("OnStartRequest failed: %08x\n", nsres);
+ if(This->nsstream->buf_size >= 2
+ && (BYTE)This->nsstream->buf[0] == 0xff
+ && (BYTE)This->nsstream->buf[1] == 0xfe)
+ This->nschannel->charset = heap_strdupA(UTF16_STR);
+
+ on_start_nsrequest(This);
/* events are reset when a new document URI is loaded, so re-initialise them here */
if(This->bsc.doc && This->bsc.doc->bscallback == This && This->bsc.doc->nscontainer) {
if(NS_FAILED(nsres))
ERR("OnDataAvailable failed: %08x\n", nsres);
- if(This->nsstream->buf_size)
- FIXME("buffer is not empty!\n");
+ if(This->nsstream->buf_size == sizeof(This->nsstream->buf)) {
+ ERR("buffer is full\n");
+ break;
+ }
}while(hres == S_OK);
return S_OK;
}
-static void on_stop_nsrequest(nsChannelBSC *This)
-{
- if(!This->nslistener)
- return;
-
- nsIStreamListener_OnStopRequest(This->nslistener, (nsIRequest*)NSCHANNEL(This->nschannel),
- This->nscontext, NS_OK);
-}
-
static void add_nsrequest(nsChannelBSC *This)
{
nsresult nsres;
return S_OK;
}
+static HRESULT nsChannelBSC_init_bindinfo(BSCallback *bsc)
+{
+ nsChannelBSC *This = NSCHANNELBSC_THIS(bsc);
+
+ if(This->nschannel && This->nschannel->post_data_stream) {
+ parse_post_data(This->nschannel->post_data_stream, &This->bsc.headers, &This->bsc.post_data, &This->bsc.post_data_len);
+ TRACE("headers = %s post_data = %s\n", debugstr_w(This->bsc.headers),
+ debugstr_an(This->bsc.post_data, This->bsc.post_data_len));
+ }
+
+ return S_OK;
+}
+
static HRESULT nsChannelBSC_stop_binding(BSCallback *bsc, HRESULT result)
{
nsChannelBSC *This = NSCHANNELBSC_THIS(bsc);
}
}
- if(FAILED(result))
- return S_OK;
-
- if(This->bsc.doc && This->bsc.doc->bscallback == This && !This->bsc.doc->nscontainer) {
- task_t *task = heap_alloc(sizeof(task_t));
-
- task->doc = This->bsc.doc;
- task->task_id = TASK_PARSECOMPLETE;
- task->next = NULL;
-
- /*
- * This should be done in the worker thread that parses HTML,
- * but we don't have such thread.
- */
- push_task(task);
- }
-
return S_OK;
}
return S_OK;
}
+static HRESULT nsChannelBSC_on_response(BSCallback *bsc, DWORD response_code)
+{
+ nsChannelBSC *This = NSCHANNELBSC_THIS(bsc);
+
+ This->nschannel->response_status = response_code;
+ return S_OK;
+}
+
#undef NSCHANNELBSC_THIS
static const BSCallbackVtbl nsChannelBSCVtbl = {
nsChannelBSC_destroy,
+ nsChannelBSC_init_bindinfo,
nsChannelBSC_start_binding,
nsChannelBSC_stop_binding,
nsChannelBSC_read_data,
nsChannelBSC_on_progress,
+ nsChannelBSC_on_response
};
nsChannelBSC *create_channelbsc(IMoniker *mon)
#define NS_APPSTARTUPNOTIFIER_CONTRACTID "@mozilla.org/embedcomp/appstartup-notifier;1"
#define NS_WEBBROWSER_CONTRACTID "@mozilla.org/embedding/browser/nsWebBrowser;1"
-#define NS_PROFILE_CONTRACTID "@mozilla.org/profile/manager;1"
#define NS_MEMORY_CONTRACTID "@mozilla.org/xpcom/memory-service;1"
-#define NS_STRINGSTREAM_CONTRACTID "@mozilla.org/io/string-input-stream;1"
#define NS_COMMANDPARAMS_CONTRACTID "@mozilla.org/embedcomp/command-params;1"
#define NS_HTMLSERIALIZER_CONTRACTID "@mozilla.org/layout/contentserializer;1?mimetype=text/html"
#define NS_EDITORCONTROLLER_CONTRACTID "@mozilla.org/editor/editorcontroller;1"
-#define NS_ARRAY_CONTRACTID "@mozilla.org/array;1"
-#define NS_VARIANT_CONTRACTID "@mozilla.org/variant;1"
#define NS_PREFERENCES_CONTRACTID "@mozilla.org/preferences;1"
#define APPSTARTUP_TOPIC "app-startup"
return ret;
}
+static void set_bool_pref(nsIPrefBranch *pref, const char *pref_name, BOOL val)
+{
+ nsresult nsres;
+
+ nsres = nsIPrefBranch_SetBoolPref(pref, pref_name, val);
+ if(NS_FAILED(nsres))
+ ERR("Could not set pref %s\n", debugstr_a(pref_name));
+}
+
+static void set_int_pref(nsIPrefBranch *pref, const char *pref_name, int val)
+{
+ nsresult nsres;
+
+ nsres = nsIPrefBranch_SetIntPref(pref, pref_name, val);
+ if(NS_FAILED(nsres))
+ ERR("Could not set pref %s\n", debugstr_a(pref_name));
+}
+
+static void set_string_pref(nsIPrefBranch *pref, const char *pref_name, const char *val)
+{
+ nsresult nsres;
+
+ nsres = nsIPrefBranch_SetCharPref(pref, pref_name, val);
+ if(NS_FAILED(nsres))
+ ERR("Could not set pref %s\n", debugstr_a(pref_name));
+}
+
static void set_lang(nsIPrefBranch *pref)
{
char langs[100];
DWORD res, size, type;
HKEY hkey;
- nsresult nsres;
static const WCHAR international_keyW[] =
{'S','o','f','t','w','a','r','e',
TRACE("Setting lang %s\n", debugstr_a(langs));
- nsres = nsIPrefBranch_SetCharPref(pref, "intl.accept_languages", langs);
- if(NS_FAILED(nsres))
- ERR("SetCharPref failed: %08x\n", nsres);
+ set_string_pref(pref, "intl.accept_languages", langs);
}
static void set_proxy(nsIPrefBranch *pref)
int proxy_port_num;
DWORD enabled = 0, res, size, type;
HKEY hkey;
- nsresult nsres;
static const WCHAR proxy_keyW[] =
{'S','o','f','t','w','a','r','e',
proxy_port_num = atoi(proxy_port + 1);
TRACE("Setting proxy to %s, port %d\n", debugstr_a(proxy), proxy_port_num);
- nsres = nsIPrefBranch_SetIntPref(pref, "network.proxy.type", 1);
- if(NS_FAILED(nsres))
- ERR("SetIntPref network.proxy.type failed: %08x\n", nsres);
- nsres = nsIPrefBranch_SetCharPref(pref, "network.proxy.http", proxy);
- if(NS_FAILED(nsres))
- ERR("SetCharPref network.proxy.http failed: %08x\n", nsres);
- nsres = nsIPrefBranch_SetIntPref(pref, "network.proxy.http_port", proxy_port_num);
- if(NS_FAILED(nsres))
- ERR("SetIntPref network.proxy.http_port failed: %08x\n", nsres);
- nsres = nsIPrefBranch_SetCharPref(pref, "network.proxy.ssl", proxy);
- if(NS_FAILED(nsres))
- ERR("SetCharPref network.proxy.ssl failed: %08x\n", nsres);
- nsres = nsIPrefBranch_SetIntPref(pref, "network.proxy.ssl_port", proxy_port_num);
- if(NS_FAILED(nsres))
- ERR("SetIntPref network.proxy.ssl_port failed: %08x\n", nsres);
-}
-
-static void set_bool_pref(nsIPrefBranch *pref, const char *pref_name, BOOL val)
-{
- nsresult nsres;
+ set_string_pref(pref, "network.proxy.http", proxy);
+ set_string_pref(pref, "network.proxy.ssl", proxy);
- nsres = nsIPrefBranch_SetBoolPref(pref, pref_name, val);
- if(NS_FAILED(nsres))
- ERR("Could not set pref %s\n", debugstr_a(pref_name));
+ set_int_pref(pref, "network.proxy.type", 1);
+ set_int_pref(pref, "network.proxy.http_port", proxy_port_num);
+ set_int_pref(pref, "network.proxy.ssl_port", proxy_port_num);
}
static void set_preferences(void)
set_proxy(pref);
set_bool_pref(pref, "security.warn_entering_secure", FALSE);
set_bool_pref(pref, "security.warn_submit_insecure", FALSE);
+ set_int_pref(pref, "layout.spellcheckDefault", 0);
nsIPrefBranch_Release(pref);
}
NS_StringContainerFinish(str);
}
-nsIInputStream *create_nsstream(const char *data, PRInt32 data_len)
-{
- nsIStringInputStream *ret;
- nsresult nsres;
-
- if(!pCompMgr)
- return NULL;
-
- nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr,
- NS_STRINGSTREAM_CONTRACTID, NULL, &IID_nsIStringInputStream,
- (void**)&ret);
- if(NS_FAILED(nsres)) {
- ERR("Could not get nsIStringInputStream\n");
- return NULL;
- }
-
- nsres = nsIStringInputStream_SetData(ret, data, data_len);
- if(NS_FAILED(nsres)) {
- ERR("AdoptData failed: %08x\n", nsres);
- nsIStringInputStream_Release(ret);
- return NULL;
- }
-
- return (nsIInputStream*)ret;
-}
-
nsICommandParams *create_nscommand_params(void)
{
nsICommandParams *ret = NULL;
return nsres;
}
-static void nsnode_to_nsstring_rec(nsIContentSerializer *serializer, nsIDOMNode *nsnode, nsAString *str)
+static HRESULT nsnode_to_nsstring_rec(nsIContentSerializer *serializer, nsIDOMNode *nsnode, nsAString *str)
{
nsIDOMNodeList *node_list = NULL;
PRBool has_children = FALSE;
nsres = nsIDOMNode_GetNodeType(nsnode, &type);
if(NS_FAILED(nsres)) {
ERR("GetType failed: %08x\n", nsres);
- return;
+ return E_FAIL;
}
switch(type) {
nsIDOMDocument_Release(nsdoc);
break;
}
+ case DOCUMENT_TYPE_NODE:
+ WARN("Ignoring DOCUMENT_TYPE_NODE\n");
+ break;
case DOCUMENT_FRAGMENT_NODE:
break;
default:
nsIContentSerializer_AppendElementEnd(serializer, nselem, str);
nsIDOMElement_Release(nselem);
}
+
+ return S_OK;
}
-void nsnode_to_nsstring(nsIDOMNode *nsdoc, nsAString *str)
+HRESULT nsnode_to_nsstring(nsIDOMNode *nsnode, nsAString *str)
{
nsIContentSerializer *serializer;
- nsIDOMNode *nsnode;
nsresult nsres;
+ HRESULT hres;
nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr,
NS_HTMLSERIALIZER_CONTRACTID, NULL, &IID_nsIContentSerializer,
(void**)&serializer);
if(NS_FAILED(nsres)) {
ERR("Could not get nsIContentSerializer: %08x\n", nsres);
- return;
+ return E_FAIL;
}
nsres = nsIContentSerializer_Init(serializer, 0, 100, NULL, FALSE, FALSE /* FIXME */);
if(NS_FAILED(nsres))
ERR("Init failed: %08x\n", nsres);
- nsIDOMDocument_QueryInterface(nsdoc, &IID_nsIDOMNode, (void**)&nsnode);
- nsnode_to_nsstring_rec(serializer, nsnode, str);
- nsIDOMNode_Release(nsnode);
-
- nsres = nsIContentSerializer_Flush(serializer, str);
- if(NS_FAILED(nsres))
- ERR("Flush failed: %08x\n", nsres);
+ hres = nsnode_to_nsstring_rec(serializer, nsnode, str);
+ if(SUCCEEDED(hres)) {
+ nsres = nsIContentSerializer_Flush(serializer, str);
+ if(NS_FAILED(nsres))
+ ERR("Flush failed: %08x\n", nsres);
+ }
nsIContentSerializer_Release(serializer);
+ return hres;
}
void get_editor_controller(NSContainer *This)
return nsIWebBrowserChrome_Release(NSWBCHROME(This));
}
+static BOOL translate_url(HTMLDocument *doc, nsIWineURI *nsuri)
+{
+ OLECHAR *new_url = NULL, *url;
+ BOOL ret = FALSE;
+ LPCWSTR wine_url;
+ HRESULT hres;
+
+ if(!doc->hostui)
+ return FALSE;
+
+ nsIWineURI_GetWineURL(nsuri, &wine_url);
+
+ url = heap_strdupW(wine_url);
+ hres = IDocHostUIHandler_TranslateUrl(doc->hostui, 0, url, &new_url);
+ heap_free(url);
+ if(hres != S_OK || !new_url)
+ return FALSE;
+
+ if(strcmpW(url, new_url)) {
+ FIXME("TranslateUrl returned new URL %s -> %s\n", debugstr_w(url), debugstr_w(new_url));
+ ret = TRUE;
+ }
+
+ CoTaskMemFree(new_url);
+ return ret;
+}
+
static nsresult NSAPI nsURIContentListener_OnStartURIOpen(nsIURIContentListener *iface,
nsIURI *aURI, PRBool *_retval)
{
IMoniker_Release(mon);
}
+
+ *_retval = FALSE;
+ }else if(This->doc) {
+ *_retval = translate_url(This->doc, wine_uri);
}
nsIWineURI_Release(wine_uri);
- *_retval = FALSE;
- return This->content_listener
+ return !*_retval && This->content_listener
? nsIURIContentListener_OnStartURIOpen(This->content_listener, aURI, _retval)
: NS_OK;
}
{
NSContainer *This = NSEVENTLIST_THIS(iface)->This;
nsIDOMHTMLElement *nsbody = NULL;
- task_t *task;
TRACE("(%p)\n", This);
if(This->doc->usermode == EDITMODE)
handle_edit_load(This->doc);
- task = heap_alloc(sizeof(task_t));
-
- task->doc = This->doc;
- task->task_id = TASK_PARSECOMPLETE;
- task->next = NULL;
-
- /*
- * This should be done in the worker thread that parses HTML,
- * but we don't have such thread (Gecko parses HTML for us).
- */
- push_task(task);
-
if(!This->doc->nsdoc) {
ERR("NULL nsdoc\n");
return NS_ERROR_FAILURE;
nsresult IsNonBlocking(PRBool *_retval);
}
-[
- object,
- uuid(450cd2d4-f0fd-424d-b365-b1251f80fd53),
- local
- /* NOT_FROZEN */
-]
-interface nsIStringInputStream : nsIInputStream
-{
- nsresult SetData(const char *data, PRInt32 dataLen);
- nsresult AdoptData(char *data, PRInt32 dataLen);
- nsresult ShareData(const char *data, PRInt32 dataLen);
-}
-
[
object,
uuid(07a22cc0-0ce5-11d3-9331-00104ba0fd40),
nsresult GetOriginCharset(nsACString *aOriginCharset);
}
+[
+ object,
+ uuid(d6116970-8034-11d3-9399-00104ba0fd40),
+ local
+ /* FROZEN */
+]
+interface nsIURL : nsIURI
+{
+ nsresult GetFilePath(nsACString *aFilePath);
+ nsresult SetFilePath(const nsACString *aFilePath);
+ nsresult GetParam(nsACString *aParam);
+ nsresult SetParam(const nsACString *aParam);
+ nsresult GetQuery(nsACString *aQuery);
+ nsresult SetQuery(const nsACString *aQuery);
+ nsresult GetRef(nsACString *aRef);
+ nsresult SetRef(const nsACString *aRef);
+ nsresult GetDirectory(nsACString *aDirectory);
+ nsresult SetDirectory(const nsACString *aDirectory);
+ nsresult GetFileName(nsACString *aFileName);
+ nsresult SetFileName(const nsACString *aFileName);
+ nsresult GetFileBaseName(nsACString *aFileBaseName);
+ nsresult SetFileBaseName(const nsACString *aFileBaseName);
+ nsresult GetFileExtension(nsACString *aFileExtension);
+ nsresult SetFileExtension(const nsACString *aFileExtension);
+ nsresult GetCommonBaseSpec(nsIURI *aURIToCompare, nsACString *_retval);
+ nsresult GetRelativeSpec(nsIURI *aURIToCompare, nsACString *_retval);
+}
+
[
object,
uuid(ef6bfbd2-fd46-48d8-96b7-9f8f0fd387fe),
nsresult IsNoCacheResponse(PRBool *_retval);
}
+[
+ object,
+ uuid(0eb66361-faaa-4e52-8c7e-6c25f11f8e3c),
+ local
+ /* NOT_FROZEN */
+]
+interface nsIHttpChannelInternal : nsISupports
+{
+ nsresult GetDocumentURI(nsIURI **aDocumentURI);
+ nsresult SetDocumentURI(nsIURI *aDocumentURI);
+ nsresult GetRequestVersion(PRUint32 *major, PRUint32 *minor);
+ nsresult GetResponseVersion(PRUint32 *major, PRUint32 *minor);
+ nsresult SetCookie(const char *aCookieHeader);
+ nsresult SetupFallbackChannel(const char *aFallbackKey);
+ nsresult GetForceAllowThirdPartyCookie(PRBool *aForceAllowThirdPartyCookie);
+ nsresult SetForceAllowThirdPartyCookie(PRBool aForceAllowThirdPartyCookie);
+}
+
[
object,
uuid(ddf633d8-e9a4-439d-ad88-de636fd9bb75),
local
/* INTERNAL */
]
-interface nsIWineURI : nsIURI
+interface nsIWineURI : nsIURL
{
typedef struct NSContainer NSContainer;
LONG ref;
nsIURI *uri;
+ nsIURL *nsurl;
NSContainer *container;
LPWSTR wine_url;
PRBool is_doc_uri;
static nsresult create_uri(nsIURI*,NSContainer*,nsIWineURI**);
+static const char *debugstr_nsacstr(const nsACString *nsstr)
+{
+ const char *data;
+
+ nsACString_GetData(nsstr, &data);
+ return debugstr_a(data);
+}
+
HRESULT nsuri_to_url(LPCWSTR nsuri, BSTR *ret)
{
const WCHAR *ptr = nsuri;
{
nsChannel *This = NSCHANNEL_THIS(iface);
- *result = NULL;
-
if(IsEqualGUID(&IID_nsISupports, riid)) {
TRACE("(%p)->(IID_nsISupports %p)\n", This, result);
*result = NSCHANNEL(This);
}else if(IsEqualGUID(&IID_nsIChannel, riid)) {
TRACE("(%p)->(IID_nsIChannel %p)\n", This, result);
*result = NSCHANNEL(This);
- }else if(This->http_channel && IsEqualGUID(&IID_nsIHttpChannel, riid)) {
+ }else if(IsEqualGUID(&IID_nsIHttpChannel, riid)) {
TRACE("(%p)->(IID_nsIHttpChannel %p)\n", This, result);
- *result = NSHTTPCHANNEL(This);
+ *result = This->http_channel ? NSHTTPCHANNEL(This) : NULL;
}else if(IsEqualGUID(&IID_nsIUploadChannel, riid)) {
TRACE("(%p)->(IID_nsIUploadChannel %p)\n", This, result);
*result = NSUPCHANNEL(This);
+ }else if(IsEqualGUID(&IID_nsIHttpChannelInternal, riid)) {
+ TRACE("(%p)->(IID_nsIHttpChannelInternal %p)\n", This, result);
+ *result = This->http_channel_internal ? NSHTTPINTERNAL(This) : NULL;
+ }else {
+ TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), result);
+ *result = NULL;
}
if(*result) {
return NS_OK;
}
- TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), result);
-
- if(This->channel)
- return nsIChannel_QueryInterface(This->channel, riid, result);
return NS_NOINTERFACE;
}
nsIChannel_Release(This->channel);
if(This->http_channel)
nsIHttpChannel_Release(This->http_channel);
+ if(This->http_channel_internal)
+ nsIHttpChannel_Release(This->http_channel_internal);
if(This->owner)
nsISupports_Release(This->owner);
if(This->post_data_stream)
return NS_ERROR_NOT_IMPLEMENTED;
}
-static BOOL do_load_from_moniker_hack(nsChannel *This)
-{
- nsACString scheme_str;
- nsresult nsres;
- BOOL ret = TRUE;
-
- /*
- * We should always load the page from IMoniker, but Wine is not yet
- * ready for this. This function is a heuristic, that decides which
- * way of loading is better (Gecko implementation or IMoniker). The
- * aim is to always return TRUE.
- */
-
- /* Load from moniker if there is no Gecko channel available */
- if(!This->channel)
- return TRUE;
-
- nsACString_Init(&scheme_str, NULL);
- nsres = nsIWineURI_GetScheme(This->uri, &scheme_str);
-
- if(NS_SUCCEEDED(nsres)) {
- const char *scheme;
-
- nsACString_GetData(&scheme_str, &scheme);
- ret = !strcmp(scheme, "wine") || !strcmp(scheme, "about");
- }
-
- nsACString_Finish(&scheme_str);
- return ret;
-}
-
static HRESULT create_mon_for_nschannel(nsChannel *channel, IMoniker **mon)
{
nsIWineURI *wine_uri;
This->content_type = heap_strdupWtoA(container->doc->mime);
}
- if(do_load_from_moniker_hack(This))
- return WINE_NS_LOAD_FROM_MONIKER;
+ return NS_OK;
}else {
BOOL cont = before_async_open(This, container);
{
nsChannelBSC *bscallback;
IMoniker *mon = NULL;
- nsresult nsres;
task_t *task;
HRESULT hres;
- if(This->channel) {
- nsres = nsIChannel_AsyncOpen(This->channel, listener, context);
-
- if(mon)
- IMoniker_Release(mon);
-
- if(NS_FAILED(nsres) && (This->load_flags & LOAD_INITIAL_DOCUMENT_URI))
- return WINE_NS_LOAD_FROM_MONIKER;
- return nsres;
- }
-
- TRACE("channel == NULL\n");
-
hres = create_mon_for_nschannel(This, &mon);
if(FAILED(hres))
return NS_ERROR_UNEXPECTED;
TRACE("(%p)->(%p)\n", This, aResponseStatus);
+ if(This->response_status) {
+ *aResponseStatus = This->response_status;
+ return NS_OK;
+ }
+
if(This->http_channel)
return nsIHttpChannel_GetResponseStatus(This->http_channel, aResponseStatus);
- return NS_ERROR_NOT_IMPLEMENTED;
+ return NS_ERROR_UNEXPECTED;
}
static nsresult NSAPI nsChannel_GetResponseStatusText(nsIHttpChannel *iface,
nsUploadChannel_GetUploadStream
};
+#define NSHTTPINTERNAL_THIS(iface) DEFINE_THIS(nsChannel, IHttpChannelInternal, iface)
+
+static nsresult NSAPI nsHttpChannelInternal_QueryInterface(nsIHttpChannelInternal *iface, nsIIDRef riid,
+ nsQIResult result)
+{
+ nsChannel *This = NSHTTPINTERNAL_THIS(iface);
+ return nsIChannel_QueryInterface(NSCHANNEL(This), riid, result);
+}
+
+static nsrefcnt NSAPI nsHttpChannelInternal_AddRef(nsIHttpChannelInternal *iface)
+{
+ nsChannel *This = NSHTTPINTERNAL_THIS(iface);
+ return nsIChannel_AddRef(NSCHANNEL(This));
+}
+
+static nsrefcnt NSAPI nsHttpChannelInternal_Release(nsIHttpChannelInternal *iface)
+{
+ nsChannel *This = NSHTTPINTERNAL_THIS(iface);
+ return nsIChannel_Release(NSCHANNEL(This));
+}
+
+static nsresult NSAPI nsHttpChannelInternal_GetDocumentURI(nsIHttpChannelInternal *iface, nsIURI **aDocumentURI)
+{
+ nsChannel *This = NSHTTPINTERNAL_THIS(iface);
+
+ TRACE("(%p)->()\n", This);
+
+ if(This->http_channel_internal)
+ return nsIHttpChannelInternal_GetDocumentURI(This->http_channel_internal, aDocumentURI);
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+static nsresult NSAPI nsHttpChannelInternal_SetDocumentURI(nsIHttpChannelInternal *iface, nsIURI *aDocumentURI)
+{
+ nsChannel *This = NSHTTPINTERNAL_THIS(iface);
+
+ TRACE("(%p)->()\n", This);
+
+ if(This->http_channel_internal)
+ return nsIHttpChannelInternal_SetDocumentURI(This->http_channel_internal, aDocumentURI);
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+static nsresult NSAPI nsHttpChannelInternal_GetRequestVersion(nsIHttpChannelInternal *iface, PRUint32 *major, PRUint32 *minor)
+{
+ nsChannel *This = NSHTTPINTERNAL_THIS(iface);
+
+ TRACE("(%p)->()\n", This);
+
+ if(This->http_channel_internal)
+ return nsIHttpChannelInternal_GetRequestVersion(This->http_channel_internal, major, minor);
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+static nsresult NSAPI nsHttpChannelInternal_GetResponseVersion(nsIHttpChannelInternal *iface, PRUint32 *major, PRUint32 *minor)
+{
+ nsChannel *This = NSHTTPINTERNAL_THIS(iface);
+
+ TRACE("(%p)->()\n", This);
+
+ if(This->http_channel_internal)
+ return nsIHttpChannelInternal_GetResponseVersion(This->http_channel_internal, major, minor);
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+static nsresult NSAPI nsHttpChannelInternal_SetCookie(nsIHttpChannelInternal *iface, const char *aCookieHeader)
+{
+ nsChannel *This = NSHTTPINTERNAL_THIS(iface);
+
+ TRACE("(%p)->()\n", This);
+
+ if(This->http_channel_internal)
+ return nsIHttpChannelInternal_SetCookie(This->http_channel_internal, aCookieHeader);
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+static nsresult NSAPI nsHttpChannelInternal_SetupFallbackChannel(nsIHttpChannelInternal *iface, const char *aFallbackKey)
+{
+ nsChannel *This = NSHTTPINTERNAL_THIS(iface);
+
+ TRACE("(%p)->()\n", This);
+
+ if(This->http_channel_internal)
+ return nsIHttpChannelInternal_SetupFallbackChannel(This->http_channel_internal, aFallbackKey);
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+static nsresult NSAPI nsHttpChannelInternal_GetForceAllowThirdPartyCookie(nsIHttpChannelInternal *iface, PRBool *aForceThirdPartyCookie)
+{
+ nsChannel *This = NSHTTPINTERNAL_THIS(iface);
+
+ TRACE("(%p)->()\n", This);
+
+ if(This->http_channel_internal)
+ return nsIHttpChannelInternal_GetForceAllowThirdPartyCookie(This->http_channel_internal, aForceThirdPartyCookie);
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+static nsresult NSAPI nsHttpChannelInternal_SetForceAllowThirdPartyCookie(nsIHttpChannelInternal *iface, PRBool aForceThirdPartyCookie)
+{
+ nsChannel *This = NSHTTPINTERNAL_THIS(iface);
+
+ TRACE("(%p)->()\n", This);
+
+ if(This->http_channel_internal)
+ return nsIHttpChannelInternal_SetForceAllowThirdPartyCookie(This->http_channel_internal, aForceThirdPartyCookie);
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+#undef NSHTTPINTERNAL_THIS
+
+static const nsIHttpChannelInternalVtbl nsHttpChannelInternalVtbl = {
+ nsHttpChannelInternal_QueryInterface,
+ nsHttpChannelInternal_AddRef,
+ nsHttpChannelInternal_Release,
+ nsHttpChannelInternal_GetDocumentURI,
+ nsHttpChannelInternal_SetDocumentURI,
+ nsHttpChannelInternal_GetRequestVersion,
+ nsHttpChannelInternal_GetResponseVersion,
+ nsHttpChannelInternal_SetCookie,
+ nsHttpChannelInternal_SetupFallbackChannel,
+ nsHttpChannelInternal_GetForceAllowThirdPartyCookie,
+ nsHttpChannelInternal_SetForceAllowThirdPartyCookie
+};
+
#define NSURI_THIS(iface) DEFINE_THIS(nsURI, WineURI, iface)
static nsresult NSAPI nsURI_QueryInterface(nsIWineURI *iface, nsIIDRef riid, nsQIResult result)
}else if(IsEqualGUID(&IID_nsIURI, riid)) {
TRACE("(%p)->(IID_nsIURI %p)\n", This, result);
*result = NSURI(This);
+ }else if(IsEqualGUID(&IID_nsIURL, riid)) {
+ TRACE("(%p)->(IID_nsIURL %p)\n", This, result);
+ *result = NSURI(This);
}else if(IsEqualGUID(&IID_nsIWineURI, riid)) {
TRACE("(%p)->(IID_nsIWineURI %p)\n", This, result);
*result = NSURI(This);
if(!ref) {
if(This->container)
nsIWebBrowserChrome_Release(NSWBCHROME(This->container));
+ if(This->nsurl)
+ nsIURL_Release(This->nsurl);
if(This->uri)
nsIURI_Release(This->uri);
heap_free(This->wine_url);
return NS_ERROR_NOT_IMPLEMENTED;
}
+static nsresult NSAPI nsURL_GetFilePath(nsIWineURI *iface, nsACString *aFilePath)
+{
+ nsURI *This = NSURI_THIS(iface);
+
+ TRACE("(%p)->(%p)\n", This, aFilePath);
+
+ if(This->nsurl)
+ return nsIURL_GetFilePath(This->nsurl, aFilePath);
+
+ FIXME("default action not implemented\n");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+static nsresult NSAPI nsURL_SetFilePath(nsIWineURI *iface, const nsACString *aFilePath)
+{
+ nsURI *This = NSURI_THIS(iface);
+
+ TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aFilePath));
+
+ if(This->nsurl)
+ return nsIURL_SetFilePath(This->nsurl, aFilePath);
+
+ FIXME("default action not implemented\n");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+static nsresult NSAPI nsURL_GetParam(nsIWineURI *iface, nsACString *aParam)
+{
+ nsURI *This = NSURI_THIS(iface);
+
+ TRACE("(%p)->(%p)\n", This, aParam);
+
+ if(This->nsurl)
+ return nsIURL_GetParam(This->nsurl, aParam);
+
+ FIXME("default action not implemented\n");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+static nsresult NSAPI nsURL_SetParam(nsIWineURI *iface, const nsACString *aParam)
+{
+ nsURI *This = NSURI_THIS(iface);
+
+ TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aParam));
+
+ if(This->nsurl)
+ return nsIURL_SetParam(This->nsurl, aParam);
+
+ FIXME("default action not implemented\n");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+static nsresult NSAPI nsURL_GetQuery(nsIWineURI *iface, nsACString *aQuery)
+{
+ nsURI *This = NSURI_THIS(iface);
+
+ TRACE("(%p)->(%p)\n", This, aQuery);
+
+ if(This->nsurl)
+ return nsIURL_GetQuery(This->nsurl, aQuery);
+
+ FIXME("default action not implemented\n");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+static nsresult NSAPI nsURL_SetQuery(nsIWineURI *iface, const nsACString *aQuery)
+{
+ nsURI *This = NSURI_THIS(iface);
+ const WCHAR *ptr1, *ptr2;
+ const char *query;
+ WCHAR *new_url, *ptr;
+ DWORD len, size;
+
+ TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aQuery));
+
+ if(This->nsurl)
+ nsIURL_SetQuery(This->nsurl, aQuery);
+
+ if(!This->wine_url)
+ return NS_OK;
+
+ nsACString_GetData(aQuery, &query);
+ size = len = MultiByteToWideChar(CP_ACP, 0, query, -1, NULL, 0);
+ ptr1 = strchrW(This->wine_url, '?');
+ if(ptr1) {
+ size += ptr1-This->wine_url;
+ ptr2 = strchrW(ptr1, '#');
+ if(ptr2)
+ size += strlenW(ptr2);
+ }else {
+ ptr1 = This->wine_url + strlenW(This->wine_url);
+ ptr2 = NULL;
+ size += strlenW(This->wine_url);
+ }
+
+ if(*query)
+ size++;
+
+ new_url = heap_alloc(size*sizeof(WCHAR));
+ memcpy(new_url, This->wine_url, (ptr1-This->wine_url)*sizeof(WCHAR));
+ ptr = new_url + (ptr1-This->wine_url);
+ if(*query) {
+ *ptr++ = '?';
+ MultiByteToWideChar(CP_ACP, 0, query, -1, ptr, len);
+ ptr += len-1;
+ }
+ if(ptr2)
+ strcpyW(ptr, ptr2);
+ else
+ *ptr = 0;
+
+ TRACE("setting %s\n", debugstr_w(new_url));
+
+ heap_free(This->wine_url);
+ This->wine_url = new_url;
+ return NS_OK;
+}
+
+static nsresult NSAPI nsURL_GetRef(nsIWineURI *iface, nsACString *aRef)
+{
+ nsURI *This = NSURI_THIS(iface);
+
+ TRACE("(%p)->(%p)\n", This, aRef);
+
+ if(This->nsurl)
+ return nsIURL_GetRef(This->nsurl, aRef);
+
+ FIXME("default action not implemented\n");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+static nsresult NSAPI nsURL_SetRef(nsIWineURI *iface, const nsACString *aRef)
+{
+ nsURI *This = NSURI_THIS(iface);
+
+ TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aRef));
+
+ if(This->nsurl)
+ return nsIURL_SetRef(This->nsurl, aRef);
+
+ FIXME("default action not implemented\n");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+static nsresult NSAPI nsURL_GetDirectory(nsIWineURI *iface, nsACString *aDirectory)
+{
+ nsURI *This = NSURI_THIS(iface);
+
+ TRACE("(%p)->(%p)\n", This, aDirectory);
+
+ if(This->nsurl)
+ return nsIURL_GetDirectory(This->nsurl, aDirectory);
+
+ FIXME("default action not implemented\n");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+static nsresult NSAPI nsURL_SetDirectory(nsIWineURI *iface, const nsACString *aDirectory)
+{
+ nsURI *This = NSURI_THIS(iface);
+
+ TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aDirectory));
+
+ if(This->nsurl)
+ return nsIURL_SetDirectory(This->nsurl, aDirectory);
+
+ FIXME("default action not implemented\n");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+static nsresult NSAPI nsURL_GetFileName(nsIWineURI *iface, nsACString *aFileName)
+{
+ nsURI *This = NSURI_THIS(iface);
+
+ TRACE("(%p)->(%p)\n", This, aFileName);
+
+ if(This->nsurl)
+ return nsIURL_GetFileName(This->nsurl, aFileName);
+
+ FIXME("default action not implemented\n");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+static nsresult NSAPI nsURL_SetFileName(nsIWineURI *iface, const nsACString *aFileName)
+{
+ nsURI *This = NSURI_THIS(iface);
+
+ TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aFileName));
+
+ if(This->nsurl)
+ return nsIURL_SetFileName(This->nsurl, aFileName);
+
+ FIXME("default action not implemented\n");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+static nsresult NSAPI nsURL_GetFileBaseName(nsIWineURI *iface, nsACString *aFileBaseName)
+{
+ nsURI *This = NSURI_THIS(iface);
+
+ TRACE("(%p)->(%p)\n", This, aFileBaseName);
+
+ if(This->nsurl)
+ return nsIURL_GetFileBaseName(This->nsurl, aFileBaseName);
+
+ FIXME("default action not implemented\n");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+static nsresult NSAPI nsURL_SetFileBaseName(nsIWineURI *iface, const nsACString *aFileBaseName)
+{
+ nsURI *This = NSURI_THIS(iface);
+
+ TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aFileBaseName));
+
+ if(This->nsurl)
+ return nsIURL_SetFileBaseName(This->nsurl, aFileBaseName);
+
+ FIXME("default action not implemented\n");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+static nsresult NSAPI nsURL_GetFileExtension(nsIWineURI *iface, nsACString *aFileExtension)
+{
+ nsURI *This = NSURI_THIS(iface);
+
+ TRACE("(%p)->(%p)\n", This, aFileExtension);
+
+ if(This->nsurl)
+ return nsIURL_GetFileExtension(This->nsurl, aFileExtension);
+
+ FIXME("default action not implemented\n");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+static nsresult NSAPI nsURL_SetFileExtension(nsIWineURI *iface, const nsACString *aFileExtension)
+{
+ nsURI *This = NSURI_THIS(iface);
+
+ TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aFileExtension));
+
+ if(This->nsurl)
+ return nsIURL_SetFileExtension(This->nsurl, aFileExtension);
+
+ FIXME("default action not implemented\n");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+static nsresult NSAPI nsURL_GetCommonBaseSpec(nsIWineURI *iface, nsIURI *aURIToCompare, nsACString *_retval)
+{
+ nsURI *This = NSURI_THIS(iface);
+
+ TRACE("(%p)->(%p %p)\n", This, aURIToCompare, _retval);
+
+ if(This->nsurl)
+ return nsIURL_GetCommonBaseSpec(This->nsurl, aURIToCompare, _retval);
+
+ FIXME("default action not implemented\n");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+static nsresult NSAPI nsURL_GetRelativeSpec(nsIWineURI *iface, nsIURI *aURIToCompare, nsACString *_retval)
+{
+ nsURI *This = NSURI_THIS(iface);
+
+ TRACE("(%p)->(%p %p)\n", This, aURIToCompare, _retval);
+
+ if(This->nsurl)
+ return nsIURL_GetRelativeSpec(This->nsurl, aURIToCompare, _retval);
+
+ FIXME("default action not implemented\n");
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
static nsresult NSAPI nsURI_GetNSContainer(nsIWineURI *iface, NSContainer **aContainer)
{
nsURI *This = NSURI_THIS(iface);
nsURI_GetAsciiSpec,
nsURI_GetAsciiHost,
nsURI_GetOriginCharset,
+ nsURL_GetFilePath,
+ nsURL_SetFilePath,
+ nsURL_GetParam,
+ nsURL_SetParam,
+ nsURL_GetQuery,
+ nsURL_SetQuery,
+ nsURL_GetRef,
+ nsURL_SetRef,
+ nsURL_GetDirectory,
+ nsURL_SetDirectory,
+ nsURL_GetFileName,
+ nsURL_SetFileName,
+ nsURL_GetFileBaseName,
+ nsURL_SetFileBaseName,
+ nsURL_GetFileExtension,
+ nsURL_SetFileExtension,
+ nsURL_GetCommonBaseSpec,
+ nsURL_GetRelativeSpec,
nsURI_GetNSContainer,
nsURI_SetNSContainer,
nsURI_GetIsDocumentURI,
if(container)
nsIWebBrowserChrome_AddRef(NSWBCHROME(container));
+ if(uri)
+ nsIURI_QueryInterface(uri, &IID_nsIURL, (void**)&ret->nsurl);
+ else
+ ret->nsurl = NULL;
+
TRACE("retval=%p\n", ret);
*_retval = NSWINEURI(ret);
return NS_OK;
static BOOL is_gecko_special_uri(const char *spec)
{
- static const char chromeW[] = "chrome:";
- static const char jarW[] = "jar:";
- static const char resourceW[] = "resource:";
- static const char javascriptW[] = "javascript:";
+ static const char *special_schemes[] = {"chrome:", "jar:", "resource:", "javascript:", "wyciwyg:"};
+ int i;
+
+ for(i=0; i < sizeof(special_schemes)/sizeof(*special_schemes); i++) {
+ if(!strncasecmp(spec, special_schemes[i], strlen(special_schemes[i])))
+ return TRUE;
+ }
- return !strncasecmp(spec, chromeW, sizeof(chromeW)-1)
- || !strncasecmp(spec, resourceW, sizeof(resourceW)-1)
- || !strncasecmp(spec, jarW, sizeof(jarW)-1)
- || !strncasecmp(spec, javascriptW, sizeof(javascriptW)-1);
+ return FALSE;
}
static nsresult NSAPI nsIOService_NewURI(nsIIOService *iface, const nsACString *aSpec,
ret->lpHttpChannelVtbl = &nsChannelVtbl;
ret->lpUploadChannelVtbl = &nsUploadChannelVtbl;
+ ret->lpIHttpChannelInternalVtbl = &nsHttpChannelInternalVtbl;
ret->ref = 1;
ret->channel = channel;
ret->uri = wine_uri;
nsIURI_AddRef(aURI);
ret->original_uri = aURI;
- if(channel)
+ if(channel) {
nsIChannel_QueryInterface(channel, &IID_nsIHttpChannel, (void**)&ret->http_channel);
+ nsIChannel_QueryInterface(channel, &IID_nsIHttpChannelInternal, (void**)&ret->http_channel_internal);
+ }
*_retval = NSCHANNEL(ret);
return NS_OK;
TRACE("(%p) ref=%d\n", This, ref);
- if(!ref)
+ if(!ref) {
+ release_dispex(&This->dispex);
heap_free(This);
+ }
return ref;
}
static HRESULT WINAPI OmNavigator_get_appName(IOmNavigator *iface, BSTR *p)
{
OmNavigator *This = OMNAVIGATOR_THIS(iface);
- FIXME("(%p)->(%p)\n", This, p);
- return E_NOTIMPL;
+
+ static const WCHAR app_nameW[] =
+ {'M','i','c','r','o','s','o','f','t',' ',
+ 'I','n','t','e','r','n','e','t',' ',
+ 'E','x','p','l','o','r','e','r',0};
+
+ TRACE("(%p)->(%p)\n", This, p);
+
+ *p = SysAllocString(app_nameW);
+ if(!*p)
+ return E_OUTOFMEMORY;
+
+ return S_OK;
}
static HRESULT WINAPI OmNavigator_get_appVersion(IOmNavigator *iface, BSTR *p)
static HRESULT WINAPI OmNavigator_get_userAgent(IOmNavigator *iface, BSTR *p)
{
OmNavigator *This = OMNAVIGATOR_THIS(iface);
- FIXME("(%p)->(%p)\n", This, p);
- return E_NOTIMPL;
+ char user_agent[512];
+ DWORD size;
+ HRESULT hres;
+
+ TRACE("(%p)->(%p)\n", This, p);
+
+ size = sizeof(user_agent);
+ hres = ObtainUserAgentString(0, user_agent, &size);
+ if(FAILED(hres))
+ return hres;
+
+ size = MultiByteToWideChar(CP_ACP, 0, user_agent, -1, NULL, 0);
+ *p = SysAllocStringLen(NULL, size-1);
+ if(!*p)
+ return E_OUTOFMEMORY;
+
+ MultiByteToWideChar(CP_ACP, 0, user_agent, -1, *p, size);
+ return S_OK;
}
static HRESULT WINAPI OmNavigator_javaEnabled(IOmNavigator *iface, VARIANT_BOOL *enabled)
static HRESULT WINAPI OmNavigator_toString(IOmNavigator *iface, BSTR *String)
{
OmNavigator *This = OMNAVIGATOR_THIS(iface);
- FIXME("(%p)->(%p)\n", This, String);
- return E_NOTIMPL;
+
+ static const WCHAR objectW[] = {'[','o','b','j','e','c','t',']',0};
+
+ TRACE("(%p)->(%p)\n", This, String);
+
+ if(!String)
+ return E_INVALIDARG;
+
+ *String = SysAllocString(objectW);
+ return *String ? S_OK : E_OUTOFMEMORY;
}
static HRESULT WINAPI OmNavigator_get_cpuClass(IOmNavigator *iface, BSTR *p)
WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
-#define USER_AGENT "User-Agent:"
-#define CONTENT_TYPE "Content-Type:"
-
-static int fix_headers(char *buf, DWORD post_len)
-{
- char *ptr = buf, *ptr2;
-
- while(*ptr && (ptr[0] != '\r' || ptr[1] != '\n')) {
- for(ptr2=ptr+1; *ptr2 && (ptr2[0] != '\r' || ptr2[1] != '\n'); ptr2++);
-
- if(*ptr2)
- ptr2 += 2;
-
- if(!strncasecmp(ptr, USER_AGENT, sizeof(USER_AGENT)-1)) {
- FIXME("Ignoring User-Agent header\n");
- memmove(ptr, ptr2, strlen(ptr2)+1);
- }else if(!post_len && !strncasecmp(ptr, CONTENT_TYPE, sizeof(CONTENT_TYPE)-1)) {
- TRACE("Ignoring Content-Type header\n");
- memmove(ptr, ptr2, strlen(ptr2)+1);
- }else {
- ptr = ptr2;
- }
- }
-
- *ptr = 0;
- return ptr-buf;
-}
-
-static nsIInputStream *get_post_data_stream(IBindCtx *bctx)
-{
- nsIInputStream *ret = NULL;
- IUnknown *unk;
- IBindStatusCallback *callback;
- IServiceProvider *service_provider;
- BINDINFO bindinfo;
- DWORD bindf = 0;
- DWORD post_len = 0, headers_len = 0;
- LPWSTR headers = NULL;
- WCHAR emptystr[] = {0};
- char *data;
- HRESULT hres;
-
- static WCHAR _BSCB_Holder_[] =
- {'_','B','S','C','B','_','H','o','l','d','e','r','_',0};
-
-
- /* FIXME: This should be done in URLMoniker */
- if(!bctx)
- return NULL;
-
- hres = IBindCtx_GetObjectParam(bctx, _BSCB_Holder_, &unk);
- if(FAILED(hres))
- return NULL;
-
- hres = IUnknown_QueryInterface(unk, &IID_IBindStatusCallback, (void**)&callback);
- if(FAILED(hres)) {
- IUnknown_Release(unk);
- return NULL;
- }
-
- hres = IUnknown_QueryInterface(unk, &IID_IServiceProvider, (void**)&service_provider);
- IUnknown_Release(unk);
- if(SUCCEEDED(hres)) {
- IHttpNegotiate *http_negotiate;
-
- hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate, &IID_IHttpNegotiate,
- (void**)&http_negotiate);
- if(SUCCEEDED(hres)) {
- hres = IHttpNegotiate_BeginningTransaction(http_negotiate, emptystr,
- emptystr, 0, &headers);
- IHttpNegotiate_Release(http_negotiate);
-
- if(SUCCEEDED(hres) && headers)
- headers_len = WideCharToMultiByte(CP_ACP, 0, headers, -1, NULL, 0, NULL, NULL);
- }
-
- IServiceProvider_Release(service_provider);
- }
-
- memset(&bindinfo, 0, sizeof(bindinfo));
- bindinfo.cbSize = sizeof(bindinfo);
-
- hres = IBindStatusCallback_GetBindInfo(callback, &bindf, &bindinfo);
-
- if(SUCCEEDED(hres) && bindinfo.dwBindVerb == BINDVERB_POST)
- post_len = bindinfo.cbstgmedData;
-
- if(headers_len || post_len) {
- int len = 0;
-
- static const char content_length[] = "Content-Length: %u\r\n\r\n";
-
- data = heap_alloc(headers_len+post_len+sizeof(content_length)+10);
-
- if(headers_len) {
- WideCharToMultiByte(CP_ACP, 0, headers, -1, data, headers_len, NULL, NULL);
- len = fix_headers(data, post_len);
- if(len >= 2 && (data[len-1] != '\n' || data[len-2] != '\r')) {
- data[len++] = '\r';
- data[len++] = '\n';
- }
- }
-
- if(post_len) {
- sprintf(data+len, content_length, post_len);
- len += strlen(data+len);
-
- memcpy(data+len, bindinfo.stgmedData.u.hGlobal, post_len);
- }
-
- TRACE("data = %s\n", debugstr_an(data, len+post_len));
-
- if(len)
- ret = create_nsstream(data, len+post_len);
- }
-
- CoTaskMemFree(headers);
- ReleaseBindInfo(&bindinfo);
- IBindStatusCallback_Release(callback);
-
- return ret;
-}
-
static BOOL use_gecko_script(LPCWSTR url)
{
static const WCHAR fileW[] = {'f','i','l','e',':'};
push_task(task);
if(This->nscontainer) {
- nsIInputStream *post_data_stream = get_post_data_stream(pibc);
-
This->nscontainer->bscallback = bscallback;
nsres = nsIWebNavigation_LoadURI(This->nscontainer->navigation, url,
- LOAD_FLAGS_NONE, NULL, post_data_stream, NULL);
+ LOAD_FLAGS_NONE, NULL, NULL, NULL);
This->nscontainer->bscallback = NULL;
-
- if(post_data_stream)
- nsIInputStream_Release(post_data_stream);
-
- if(NS_SUCCEEDED(nsres)) {
- /* FIXME: don't return here (URL Moniker needs to be good enough) */
-
+ if(NS_FAILED(nsres)) {
+ WARN("LoadURI failed: %08x\n", nsres);
IUnknown_Release((IUnknown*)bscallback);
CoTaskMemFree(url);
-
- if(bind_complete)
- *bind_complete = TRUE;
- return S_OK;
- }else if(nsres != WINE_NS_LOAD_FROM_MONIKER) {
- WARN("LoadURI failed: %08x\n", nsres);
+ return E_FAIL;
}
}
return S_OK;
}
-static HRESULT get_doc_string(HTMLDocument *This, char **str, DWORD *len)
+static HRESULT get_doc_string(HTMLDocument *This, char **str)
{
nsIDOMNode *nsnode;
LPCWSTR strw;
nsAString_GetData(&nsstr, &strw);
TRACE("%s\n", debugstr_w(strw));
- *len = WideCharToMultiByte(CP_ACP, 0, strw, -1, NULL, 0, NULL, NULL);
- *str = heap_alloc(*len);
- WideCharToMultiByte(CP_ACP, 0, strw, -1, *str, *len, NULL, NULL);
+ *str = heap_strdupWtoA(strw);
nsAString_Finish(&nsstr);
{
HTMLDocument *This = PERSISTFILE_THIS(iface);
char *str;
- DWORD len, written=0;
+ DWORD written=0;
HANDLE file;
HRESULT hres;
return E_FAIL;
}
- hres = get_doc_string(This, &str, &len);
+ hres = get_doc_string(This, &str);
if(SUCCEEDED(hres))
- WriteFile(file, str, len, &written, NULL);
+ WriteFile(file, str, strlen(str), &written, NULL);
CloseHandle(file);
return hres;
{
HTMLDocument *This = PERSTRINIT_THIS(iface);
char *str;
- DWORD len, written=0;
+ DWORD written=0;
HRESULT hres;
TRACE("(%p)->(%p %x)\n", This, pStm, fClearDirty);
- hres = get_doc_string(This, &str, &len);
+ hres = get_doc_string(This, &str);
if(FAILED(hres))
return hres;
- hres = IStream_Write(pStm, str, len, &written);
+ hres = IStream_Write(pStm, str, strlen(str), &written);
if(FAILED(hres))
FIXME("Write failed: %08x\n", hres);
#define ACTSCPWIN(x) (&(x)->lpIActiveScriptSiteWindowVtbl)
#define ACTSCPDBG32(x) (&(x)->lpIActiveScriptSiteDebug32Vtbl)
+static void set_script_prop(ScriptHost *script_host, DWORD property, VARIANT *val)
+{
+ IActiveScriptProperty *script_prop;
+ HRESULT hres;
+
+ hres = IActiveScript_QueryInterface(script_host->script, &IID_IActiveScriptProperty,
+ (void**)&script_prop);
+ if(FAILED(hres)) {
+ WARN("Could not get IActiveScriptProperty iface: %08x\n", hres);
+ return;
+ }
+
+ hres = IActiveScriptProperty_SetProperty(script_prop, property, NULL, val);
+ IActiveScriptProperty_Release(script_prop);
+ if(FAILED(hres))
+ WARN("SetProperty(%x) failed: %08x\n", property, hres);
+}
+
static BOOL init_script_engine(ScriptHost *script_host)
{
- IActiveScriptProperty *property;
IObjectSafety *safety;
SCRIPTSTATE state;
DWORD supported_opts=0, enabled_opts=0;
+ VARIANT var;
HRESULT hres;
hres = IActiveScript_QueryInterface(script_host->script, &IID_IActiveScriptParse, (void**)&script_host->parse);
if(FAILED(hres))
return FALSE;
- hres = IActiveScript_QueryInterface(script_host->script, &IID_IActiveScriptProperty, (void**)&property);
- if(SUCCEEDED(hres)) {
- VARIANT var;
-
- V_VT(&var) = VT_BOOL;
- V_BOOL(&var) = VARIANT_TRUE;
- hres = IActiveScriptProperty_SetProperty(property, SCRIPTPROP_HACK_TRIDENTEVENTSINK, NULL, &var);
- if(FAILED(hres))
- WARN("SetProperty failed: %08x\n", hres);
+ V_VT(&var) = VT_I4;
+ V_I4(&var) = 1;
+ set_script_prop(script_host, SCRIPTPROP_INVOKEVERSIONING, &var);
- IActiveScriptProperty_Release(property);
- }else {
- WARN("Could not get IActiveScriptProperty: %08x\n", hres);
- }
+ V_VT(&var) = VT_BOOL;
+ V_BOOL(&var) = VARIANT_TRUE;
+ set_script_prop(script_host, SCRIPTPROP_HACK_TRIDENTEVENTSINK, &var);
hres = IActiveScriptParse64_InitNew(script_host->parse);
if(FAILED(hres)) {
hres = IActiveScript_AddNamedItem(script_host->script, windowW,
SCRIPTITEM_ISVISIBLE|SCRIPTITEM_ISSOURCE|SCRIPTITEM_GLOBALMEMBERS);
- if(FAILED(hres))
+ if(SUCCEEDED(hres)) {
+ V_VT(&var) = VT_BOOL;
+ V_BOOL(&var) = VARIANT_TRUE;
+ set_script_prop(script_host, SCRIPTPROP_ABBREVIATE_GLOBALNAME_RESOLUTION, &var);
+ }else {
WARN("AddNamedItem failed: %08x\n", hres);
+ }
hres = IActiveScript_QueryInterface(script_host->script, &IID_IActiveScriptParseProcedure2,
(void**)&script_host->parse_proc);
This->lpVtbl = &domattr_vtbl;
This->ref = 1;
- node = create_basic_node( attribute, (IUnknown*)&This->lpVtbl );
+ node = create_basic_node( attribute, (IUnknown*)&This->lpVtbl, NULL );
if(!node)
{
HeapFree(GetProcessHeap(), 0, This);
This->lpVtbl = &domcdata_vtbl;
This->ref = 1;
- node = create_basic_node( text, (IUnknown*)&This->lpVtbl );
+ node = create_basic_node( text, (IUnknown*)&This->lpVtbl, NULL );
if(!node)
{
HeapFree(GetProcessHeap(), 0, This);
This->lpVtbl = &domcomment_vtbl;
This->ref = 1;
- node = create_basic_node( comment, (IUnknown*)&This->lpVtbl );
+ node = create_basic_node( comment, (IUnknown*)&This->lpVtbl, NULL );
if(!node)
{
HeapFree(GetProcessHeap(), 0, This);
&IID_IXMLDOMParseError,
&IID_IXMLDOMProcessingInstruction,
&IID_IXMLDOMSchemaCollection,
+ &IID_IXMLDOMSelection,
&IID_IXMLDOMText,
&IID_IXMLElement,
&IID_IXMLDOMDocument,
This->lpVtbl = &domfrag_vtbl;
This->ref = 1;
- node = create_basic_node( fragment, (IUnknown*)&This->lpVtbl );
+ node = create_basic_node( fragment, (IUnknown*)&This->lpVtbl, NULL );
if(!node)
{
HeapFree(GetProcessHeap(), 0, This);
/* IObjectSafety */
DWORD safeopt;
-
- /* IDispatchEx */
- DispatchEx dispex;
} domdoc;
/*
{
*ppvObject = &This->lpvtblISupportErrorInfo;
}
- else if(dispex_query_interface(&This->dispex, riid, ppvObject))
+ else if(dispex_query_interface(&This->node->dispex, riid, ppvObject))
{
return *ppvObject ? S_OK : E_NOINTERFACE;
}
xmldoc_add_orphan(xmlnode->doc, xmlnode);
TRACE("created xmlptr %p\n", xmlnode);
- elem_unk = create_element(xmlnode, NULL);
+ elem_unk = create_element(xmlnode);
HeapFree(GetProcessHeap(), 0, xml_name);
hr = IUnknown_QueryInterface(elem_unk, &IID_IXMLDOMElement, (void **)element);
doc->safeopt = 0;
doc->bsc = NULL;
- doc->node = create_basic_node( (xmlNodePtr)xmldoc, (IUnknown*)&doc->lpVtbl );
+ doc->node = create_basic_node( (xmlNodePtr)xmldoc, (IUnknown*)&doc->lpVtbl, &domdoc_dispex );
if(!doc->node)
{
HeapFree(GetProcessHeap(), 0, doc);
return E_FAIL;
}
- init_dispex(&doc->dispex, (IUnknown*)&doc->lpVtbl, &domdoc_dispex);
-
*document = (IXMLDOMDocument2*)&doc->lpVtbl;
TRACE("returning iface %p\n", *document);
typedef struct _domelem
{
const struct IXMLDOMElementVtbl *lpVtbl;
- const struct IUnknownVtbl *lpInternalUnkVtbl;
- IUnknown *pUnkOuter;
LONG ref;
xmlnode *node;
} domelem;
return (domelem *)((char*)iface - FIELD_OFFSET(domelem, lpVtbl));
}
-static inline domelem *impl_from_InternalUnknown( IUnknown *iface )
-{
- return (domelem *)((char*)iface - FIELD_OFFSET(domelem, lpInternalUnkVtbl));
-}
-
static inline xmlNodePtr get_element( domelem *This )
{
return This->node->node;
void** ppvObject )
{
domelem *This = impl_from_IXMLDOMElement( iface );
+
TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
- return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObject);
+ if ( IsEqualGUID( riid, &IID_IXMLDOMElement ) ||
+ IsEqualGUID( riid, &IID_IDispatch ) ||
+ IsEqualGUID( riid, &IID_IUnknown ) )
+ {
+ *ppvObject = &This->lpVtbl;
+ }
+ else if ( IsEqualGUID( riid, &IID_IXMLDOMNode ) )
+ {
+ *ppvObject = IXMLDOMNode_from_impl(This->node);
+ }
+ else
+ {
+ FIXME("interface %s not implemented\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef( (IUnknown*)*ppvObject );
+ return S_OK;
}
static ULONG WINAPI domelem_AddRef(
IXMLDOMElement *iface )
{
domelem *This = impl_from_IXMLDOMElement( iface );
- return IUnknown_AddRef(This->pUnkOuter);
+ LONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) ref=%d\n", This, ref);
+
+ return ref;
}
static ULONG WINAPI domelem_Release(
IXMLDOMElement *iface )
{
domelem *This = impl_from_IXMLDOMElement( iface );
- return IUnknown_Release(This->pUnkOuter);
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) ref=%d\n", This, ref);
+
+ if(!ref) {
+ IXMLDOMNode_Release(IXMLDOMNode_from_impl(This->node));
+ heap_free(This);
+ }
+
+ return ref;
}
static HRESULT WINAPI domelem_GetTypeInfoCount(
domelem_normalize,
};
-static HRESULT WINAPI Internal_QueryInterface(
- IUnknown *iface,
- REFIID riid,
- void** ppvObject )
-{
- domelem *This = impl_from_InternalUnknown( iface );
- TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
-
- if ( IsEqualGUID( riid, &IID_IXMLDOMElement ) ||
- IsEqualGUID( riid, &IID_IDispatch ) ||
- IsEqualGUID( riid, &IID_IUnknown ) )
- {
- *ppvObject = &This->lpVtbl;
- }
- else if ( IsEqualGUID( riid, &IID_IXMLDOMNode ) )
- {
- *ppvObject = IXMLDOMNode_from_impl(This->node);
- }
- else
- {
- FIXME("interface %s not implemented\n", debugstr_guid(riid));
- return E_NOINTERFACE;
- }
-
- IUnknown_AddRef( (IUnknown*)*ppvObject );
-
- return S_OK;
-}
-
-static ULONG WINAPI Internal_AddRef(
- IUnknown *iface )
-{
- domelem *This = impl_from_InternalUnknown( iface );
- return InterlockedIncrement( &This->ref );
-}
-
-static ULONG WINAPI Internal_Release(
- IUnknown *iface )
-{
- domelem *This = impl_from_InternalUnknown( iface );
- ULONG ref;
-
- ref = InterlockedDecrement( &This->ref );
- if ( ref == 0 )
- {
- IXMLDOMNode_Release( IXMLDOMNode_from_impl(This->node) );
- HeapFree( GetProcessHeap(), 0, This );
- }
-
- return ref;
-}
-
-static const struct IUnknownVtbl internal_unk_vtbl =
-{
- Internal_QueryInterface,
- Internal_AddRef,
- Internal_Release
-};
-
-IUnknown* create_element( xmlNodePtr element, IUnknown *pUnkOuter )
+IUnknown* create_element( xmlNodePtr element )
{
domelem *This;
This->lpVtbl = &domelem_vtbl;
This->ref = 1;
- This->lpInternalUnkVtbl = &internal_unk_vtbl;
-
- if(pUnkOuter)
- This->pUnkOuter = pUnkOuter; /* Don't take a ref on outer Unknown */
- else
- This->pUnkOuter = (IUnknown *)&This->lpInternalUnkVtbl;
- This->node = create_basic_node( element, (IUnknown*)&This->lpVtbl );
+ This->node = create_basic_node( element, (IUnknown*)&This->lpVtbl, NULL );
if(!This->node)
{
HeapFree(GetProcessHeap(), 0, This);
return NULL;
}
- return (IUnknown*) &This->lpInternalUnkVtbl;
+ return (IUnknown*) &This->lpVtbl;
}
#endif
This->lpVtbl = &entityref_vtbl;
This->ref = 1;
- node = create_basic_node( entity, (IUnknown*)&This->lpVtbl );
+ node = create_basic_node( entity, (IUnknown*)&This->lpVtbl, NULL );
if(!node)
{
HeapFree(GetProcessHeap(), 0, This);
# error You must include config.h to use this header
#endif
+/* typelibs */
+typedef enum tid_t {
+ IXMLDOMAttribute_tid,
+ IXMLDOMCDATASection_tid,
+ IXMLDOMComment_tid,
+ IXMLDOMDocument_tid,
+ IXMLDOMDocument2_tid,
+ IXMLDOMDocumentFragment_tid,
+ IXMLDOMElement_tid,
+ IXMLDOMEntityReference_tid,
+ IXMLDOMImplementation_tid,
+ IXMLDOMNamedNodeMap_tid,
+ IXMLDOMNode_tid,
+ IXMLDOMNodeList_tid,
+ IXMLDOMParseError_tid,
+ IXMLDOMProcessingInstruction_tid,
+ IXMLDOMSchemaCollection_tid,
+ IXMLDOMSelection_tid,
+ IXMLDOMText_tid,
+ IXMLElement_tid,
+ IXMLDocument_tid,
+ IXMLHTTPRequest_tid,
+ IVBSAXAttributes_tid,
+ IVBSAXContentHandler_tid,
+ IVBSAXDeclHandler_tid,
+ IVBSAXDTDHandler_tid,
+ IVBSAXEntityResolver_tid,
+ IVBSAXErrorHandler_tid,
+ IVBSAXLexicalHandler_tid,
+ IVBSAXLocator_tid,
+ IVBSAXXMLFilter_tid,
+ IVBSAXXMLReader_tid,
+ IMXAttributes_tid,
+ IMXReaderControl_tid,
+ IMXWriter_tid,
+ LAST_tid
+} tid_t;
+
+extern HRESULT get_typeinfo(tid_t tid, ITypeInfo **typeinfo);
+extern void release_typelib(void);
+
+typedef struct dispex_data_t dispex_data_t;
+typedef struct dispex_dynamic_data_t dispex_dynamic_data_t;
+
+#define MSXML_DISPID_CUSTOM_MIN 0x60000000
+#define MSXML_DISPID_CUSTOM_MAX 0x6fffffff
+
+typedef struct {
+ HRESULT (*get_dispid)(IUnknown*,BSTR,DWORD,DISPID*);
+ HRESULT (*invoke)(IUnknown*,DISPID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*);
+} dispex_static_data_vtbl_t;
+
+typedef struct {
+ const dispex_static_data_vtbl_t *vtbl;
+ const tid_t disp_tid;
+ dispex_data_t *data;
+ const tid_t* const iface_tids;
+} dispex_static_data_t;
+
+typedef struct {
+ const IDispatchExVtbl *lpIDispatchExVtbl;
+
+ IUnknown *outer;
+
+ dispex_static_data_t *data;
+ dispex_dynamic_data_t *dynamic_data;
+} DispatchEx;
+
+void init_dispex(DispatchEx*,IUnknown*,dispex_static_data_t*);
+BOOL dispex_query_interface(DispatchEx*,REFIID,void**);
+
#ifdef HAVE_LIBXML2
#ifdef HAVE_LIBXML_PARSER_H
extern IUnknown *create_domdoc( xmlNodePtr document );
extern IUnknown *create_xmldoc( void );
extern IXMLDOMNode *create_node( xmlNodePtr node );
-extern IUnknown *create_element( xmlNodePtr element, IUnknown *pUnkOuter );
+extern IUnknown *create_element( xmlNodePtr element );
extern IUnknown *create_attribute( xmlNodePtr attribute );
extern IUnknown *create_text( xmlNodePtr text );
extern IUnknown *create_pi( xmlNodePtr pi );
/* IXMLDOMNode Internal Structure */
typedef struct _xmlnode
{
+ DispatchEx dispex;
const struct IXMLDOMNodeVtbl *lpVtbl;
const struct IUnknownVtbl *lpInternalUnkVtbl;
IUnknown *pUnkOuter;
return (IXMLDOMNode*)&This->lpVtbl;
}
-extern xmlnode *create_basic_node(xmlNodePtr,IUnknown*);
+extern xmlnode *create_basic_node(xmlNodePtr,IUnknown*,dispex_static_data_t*);
extern HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument2 **document);
HRESULT bind_url(LPCWSTR, HRESULT (*onDataAvailable)(void*,char*,DWORD), void*, bsc_t**);
void detach_bsc(bsc_t*);
-/* typelibs */
-typedef enum tid_t {
- IXMLDOMAttribute_tid,
- IXMLDOMCDATASection_tid,
- IXMLDOMComment_tid,
- IXMLDOMDocument_tid,
- IXMLDOMDocument2_tid,
- IXMLDOMDocumentFragment_tid,
- IXMLDOMElement_tid,
- IXMLDOMEntityReference_tid,
- IXMLDOMImplementation_tid,
- IXMLDOMNamedNodeMap_tid,
- IXMLDOMNode_tid,
- IXMLDOMNodeList_tid,
- IXMLDOMParseError_tid,
- IXMLDOMProcessingInstruction_tid,
- IXMLDOMSchemaCollection_tid,
- IXMLDOMText_tid,
- IXMLElement_tid,
- IXMLDocument_tid,
- IXMLHTTPRequest_tid,
- IVBSAXAttributes_tid,
- IVBSAXContentHandler_tid,
- IVBSAXDeclHandler_tid,
- IVBSAXDTDHandler_tid,
- IVBSAXEntityResolver_tid,
- IVBSAXErrorHandler_tid,
- IVBSAXLexicalHandler_tid,
- IVBSAXLocator_tid,
- IVBSAXXMLFilter_tid,
- IVBSAXXMLReader_tid,
- IMXAttributes_tid,
- IMXReaderControl_tid,
- IMXWriter_tid,
- LAST_tid
-} tid_t;
-
-extern HRESULT get_typeinfo(tid_t tid, ITypeInfo **typeinfo);
-extern void release_typelib(void);
-
-typedef struct dispex_data_t dispex_data_t;
-typedef struct dispex_dynamic_data_t dispex_dynamic_data_t;
-
-#define MSXML_DISPID_CUSTOM_MIN 0x60000000
-#define MSXML_DISPID_CUSTOM_MAX 0x6fffffff
-
-typedef struct {
- HRESULT (*get_dispid)(IUnknown*,BSTR,DWORD,DISPID*);
- HRESULT (*invoke)(IUnknown*,DISPID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*);
-} dispex_static_data_vtbl_t;
-
-typedef struct {
- const dispex_static_data_vtbl_t *vtbl;
- const tid_t disp_tid;
- dispex_data_t *data;
- const tid_t* const iface_tids;
-} dispex_static_data_t;
-
-typedef struct {
- const IDispatchExVtbl *lpIDispatchExVtbl;
-
- IUnknown *outer;
-
- dispex_static_data_t *data;
- dispex_dynamic_data_t *dynamic_data;
-} DispatchEx;
-
-void init_dispex(DispatchEx*,IUnknown*,dispex_static_data_t*);
-BOOL dispex_query_interface(DispatchEx*,REFIID,void**);
-
/* memory allocation functions */
static inline void *heap_alloc(size_t len)
Internal_Release
};
-xmlnode *create_basic_node( xmlNodePtr node, IUnknown *pUnkOuter )
+xmlnode *create_basic_node( xmlNodePtr node, IUnknown *pUnkOuter, dispex_static_data_t *dispex_data )
{
xmlnode *This;
else
This->pUnkOuter = (IUnknown *)&This->lpInternalUnkVtbl;
+ if(dispex_data)
+ init_dispex(&This->dispex, This->pUnkOuter, dispex_data);
+
This->ref = 1;
This->node = node;
switch(node->type)
{
case XML_ELEMENT_NODE:
- pUnk = create_element( node, NULL );
+ pUnk = create_element( node );
break;
case XML_ATTRIBUTE_NODE:
pUnk = create_attribute( node );
break;
default:
FIXME("only creating basic node for type %d\n", node->type);
- pUnk = (IUnknown*)&create_basic_node( node, NULL )->lpInternalUnkVtbl;
+ pUnk = (IUnknown*)&create_basic_node( node, NULL, NULL )->lpInternalUnkVtbl;
}
hr = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMNode, (LPVOID*)&ret);
This->lpVtbl = &dom_pi_vtbl;
This->ref = 1;
- node = create_basic_node( pi, (IUnknown*)&This->lpVtbl );
+ node = create_basic_node( pi, (IUnknown*)&This->lpVtbl, NULL );
if(!node)
{
HeapFree(GetProcessHeap(), 0, This);
};
static dispex_static_data_t queryresult_dispex = {
&queryresult_dispex_vtbl,
- IXMLDOMNodeList_tid,
+ IXMLDOMSelection_tid,
NULL,
queryresult_iface_tids
};
This->lpVtbl = &domtext_vtbl;
This->ref = 1;
- node = create_basic_node( text, (IUnknown*)&This->lpVtbl );
+ node = create_basic_node( text, (IUnknown*)&This->lpVtbl, NULL );
if(!node)
{
HeapFree(GetProcessHeap(), 0, This);