diff --git a/reactos/dll/win32/msctf/compartmentmgr.c b/reactos/dll/win32/msctf/compartmentmgr.c new file mode 100644 index 00000000000..06a691d9967 --- /dev/null +++ b/reactos/dll/win32/msctf/compartmentmgr.c @@ -0,0 +1,660 @@ +/* + * 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 + +#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; +} diff --git a/reactos/dll/win32/msctf/context.c b/reactos/dll/win32/msctf/context.c index 8e14a722552..c13235c7783 100644 --- a/reactos/dll/win32/msctf/context.c +++ b/reactos/dll/win32/msctf/context.c @@ -61,15 +61,20 @@ typedef struct tagContext { /* 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; @@ -107,6 +112,16 @@ static inline Context *impl_from_ITfSourceVtbl(ITfSource *iface) 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); @@ -169,6 +184,7 @@ static void Context_Destructor(Context *This) free_sink(sink); } + CompartmentMgr_Destructor(This->CompartmentMgr); HeapFree(GetProcessHeap(),0,This); } @@ -185,6 +201,18 @@ static HRESULT WINAPI Context_QueryInterface(ITfContext *iface, REFIID iid, LPVO { *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) { @@ -223,7 +251,6 @@ static HRESULT WINAPI Context_RequestEditSession (ITfContext *iface, HRESULT hr; Context *This = (Context *)iface; DWORD dwLockFlags = 0x0; - TS_STATUS status; TRACE("(%p) %i %p %x %p\n",This, tid, pes, dwFlags, phrSession); @@ -248,10 +275,10 @@ static HRESULT WINAPI Context_RequestEditSession (ITfContext *iface, 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; @@ -263,7 +290,6 @@ static HRESULT WINAPI Context_RequestEditSession (ITfContext *iface, return E_INVALIDARG; } - hr = ITextStoreACP_RequestLock(This->pITextStoreACP, dwLockFlags, phrSession); return hr; @@ -341,9 +367,39 @@ static HRESULT WINAPI Context_GetSelection (ITfContext *iface, 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, @@ -419,8 +475,25 @@ static HRESULT WINAPI Context_GetStatus (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, @@ -460,8 +533,18 @@ static HRESULT WINAPI Context_GetDocumentMgr (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, @@ -579,7 +662,130 @@ static const ITfSourceVtbl Context_SourceVtbl = 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; @@ -599,9 +805,14 @@ HRESULT Context_Constructor(TfClientId tidOwner, IUnknown *punk, ITfContext **pp 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; @@ -633,7 +844,7 @@ HRESULT Context_Constructor(TfClientId tidOwner, IUnknown *punk, ITfContext **pp return S_OK; } -HRESULT Context_Initialize(ITfContext *iface) +HRESULT Context_Initialize(ITfContext *iface, ITfDocumentMgr *manager) { Context *This = (Context *)iface; @@ -644,6 +855,7 @@ HRESULT Context_Initialize(ITfContext *iface) (IUnknown*)This->pITextStoreACPSink, TS_AS_ALL_SINKS); } This->connected = TRUE; + This->manager = manager; return S_OK; } @@ -658,6 +870,7 @@ HRESULT Context_Uninitialize(ITfContext *iface) This->pITextStoreACPSink = NULL; } This->connected = FALSE; + This->manager = NULL; return S_OK; } @@ -739,8 +952,28 @@ static HRESULT WINAPI TextStoreACPSink_OnStatusChange(ITextStoreACPSink *iface, 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, @@ -756,27 +989,57 @@ static HRESULT WINAPI TextStoreACPSink_OnLockGranted(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; diff --git a/reactos/dll/win32/msctf/documentmgr.c b/reactos/dll/win32/msctf/documentmgr.c index 7fd354aa1b8..0a25b3d3b67 100644 --- a/reactos/dll/win32/msctf/documentmgr.c +++ b/reactos/dll/win32/msctf/documentmgr.c @@ -45,10 +45,23 @@ typedef struct tagDocumentMgr { 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)); @@ -56,11 +69,17 @@ static inline DocumentMgr *impl_from_ITfSourceVtbl(ITfSource *iface) 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); } @@ -77,6 +96,10 @@ static HRESULT WINAPI DocumentMgr_QueryInterface(ITfDocumentMgr *iface, REFIID i { *ppvOut = &This->SourceVtbl; } + else if (IsEqualIID(iid, &IID_ITfCompartmentMgr)) + { + *ppvOut = This->CompartmentMgr; + } if (*ppvOut) { @@ -115,7 +138,7 @@ static HRESULT WINAPI DocumentMgr_CreateContext(ITfDocumentMgr *iface, { 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) @@ -137,8 +160,8 @@ 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; } @@ -225,8 +248,8 @@ static HRESULT WINAPI DocumentMgr_GetBase(ITfDocumentMgr *iface, ITfContext **pp 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 = @@ -303,7 +326,148 @@ HRESULT DocumentMgr_Constructor(ITfThreadMgrEventSink *ThreadMgrSink, ITfDocumen 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; +} diff --git a/reactos/dll/win32/msctf/inputprocessor.c b/reactos/dll/win32/msctf/inputprocessor.c index a904a68b854..0935c4444e2 100644 --- a/reactos/dll/win32/msctf/inputprocessor.c +++ b/reactos/dll/win32/msctf/inputprocessor.c @@ -43,10 +43,15 @@ 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 { @@ -144,7 +149,7 @@ static void add_userkey( REFCLSID rclsid, LANGID langid, 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) @@ -278,7 +283,7 @@ static HRESULT WINAPI InputProcessorProfiles_AddLanguageProfile( 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); @@ -312,18 +317,91 @@ static HRESULT WINAPI InputProcessorProfiles_GetDefaultLanguageProfile( 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( @@ -413,8 +491,22 @@ static HRESULT WINAPI InputProcessorProfiles_GetCurrentLanguage( 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; } @@ -422,8 +514,11 @@ static HRESULT WINAPI InputProcessorProfiles_GetLanguageList( 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( @@ -456,7 +551,7 @@ static HRESULT WINAPI InputProcessorProfiles_EnableLanguageProfile( 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 @@ -490,7 +585,7 @@ static HRESULT WINAPI InputProcessorProfiles_IsEnabledLanguageProfile( 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); } @@ -501,7 +596,7 @@ static HRESULT WINAPI InputProcessorProfiles_IsEnabledLanguageProfile( 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); } } @@ -533,7 +628,7 @@ static HRESULT WINAPI InputProcessorProfiles_EnableLanguageProfileByDefault( 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 diff --git a/reactos/dll/win32/msctf/msctf.c b/reactos/dll/win32/msctf/msctf.c index 675e4d5954c..82772787e41 100644 --- a/reactos/dll/win32/msctf/msctf.c +++ b/reactos/dll/win32/msctf/msctf.c @@ -33,7 +33,6 @@ #include "shlwapi.h" #include "shlguid.h" #include "comcat.h" -#include "initguid.h" #include "msctf.h" #include "msctf_internal.h" @@ -74,8 +73,10 @@ static UINT activated = 0; 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); @@ -598,3 +599,12 @@ HRESULT WINAPI SetInputScopes(HWND hwnd, const INT *pInputScopes, return S_OK; } + +/*********************************************************************** + * TF_CreateInputProcessorProfiles(MSCTF.@) + */ +HRESULT WINAPI TF_CreateInputProcessorProfiles( + ITfInputProcessorProfiles **ppipr) +{ + return InputProcessorProfiles_Constructor(NULL,(IUnknown**)ppipr); +} diff --git a/reactos/dll/win32/msctf/msctf.rbuild b/reactos/dll/win32/msctf/msctf.rbuild index 44664c7c629..e7cea9ceefb 100644 --- a/reactos/dll/win32/msctf/msctf.rbuild +++ b/reactos/dll/win32/msctf/msctf.rbuild @@ -9,6 +9,7 @@ 0x600 categorymgr.c + compartmentmgr.c context.c documentmgr.c inputprocessor.c @@ -20,12 +21,18 @@ wine uuid ole32 + oleaut32 user32 advapi32 kernel32 + msctf_local_interface + textstor_local_interface ntdll msctf_local.idl + + textstor_local.idl + diff --git a/reactos/dll/win32/msctf/msctf.spec b/reactos/dll/win32/msctf/msctf.spec index 1c8bb37a1b4..f7c35a3a64a 100644 --- a/reactos/dll/win32/msctf/msctf.spec +++ b/reactos/dll/win32/msctf/msctf.spec @@ -11,7 +11,7 @@ @ 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) diff --git a/reactos/dll/win32/msctf/msctf_internal.h b/reactos/dll/win32/msctf/msctf_internal.h index 9181b8c4f41..3bb0baa6ee7 100644 --- a/reactos/dll/win32/msctf/msctf_internal.h +++ b/reactos/dll/win32/msctf/msctf_internal.h @@ -26,19 +26,25 @@ #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); @@ -58,4 +64,5 @@ extern HRESULT get_textservice_sink(TfClientId tid, REFCLSID iid, IUnknown** sin extern HRESULT set_textservice_sink(TfClientId tid, REFCLSID iid, IUnknown* sink); extern const WCHAR szwSystemTIPKey[]; +extern const WCHAR szwSystemCTFKey[]; #endif /* __WINE_MSCTF_I_H */ diff --git a/reactos/dll/win32/msctf/range.c b/reactos/dll/win32/msctf/range.c index 63181afdff2..dc9eae15c60 100644 --- a/reactos/dll/win32/msctf/range.c +++ b/reactos/dll/win32/msctf/range.c @@ -201,8 +201,21 @@ static HRESULT WINAPI Range_Collapse(ITfRange *iface, TfEditCookie ec, 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, @@ -331,3 +344,21 @@ HRESULT Range_Constructor(ITfContext *context, ITextStoreACP *textstore, DWORD l 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; +} diff --git a/reactos/dll/win32/msctf/textstor_local.idl b/reactos/dll/win32/msctf/textstor_local.idl new file mode 100644 index 00000000000..a665b253969 --- /dev/null +++ b/reactos/dll/win32/msctf/textstor_local.idl @@ -0,0 +1,2 @@ + +#include "textstor.idl" diff --git a/reactos/dll/win32/msctf/threadmgr.c b/reactos/dll/win32/msctf/threadmgr.c index 9b887f0a24b..0661fec1bcd 100644 --- a/reactos/dll/win32/msctf/threadmgr.c +++ b/reactos/dll/win32/msctf/threadmgr.c @@ -65,6 +65,19 @@ typedef struct tagPreservedKey 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; @@ -78,6 +91,9 @@ typedef struct tagACLMulti { /* const ITfSourceSingleVtbl *SourceSingleVtbl; */ LONG refCount; + /* Aggregation */ + ITfCompartmentMgr *CompartmentMgr; + const ITfThreadMgrEventSinkVtbl *ThreadMgrEventSinkVtbl; /* internal */ ITfDocumentMgr *focus; @@ -87,6 +103,10 @@ typedef struct tagACLMulti { CLSID forgroundTextService; struct list CurrentPreservedKeys; + struct list CreatedDocumentMgrs; + + struct list AssociatedFocusWindows; + HHOOK focusHook; /* kept as separate lists to reduce unnecessary iterations */ struct list ActiveLanguageProfileNotifySink; @@ -97,6 +117,17 @@ typedef struct tagACLMulti { 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)); @@ -122,6 +153,22 @@ static inline ThreadMgr *impl_from_ITfThreadMgrEventSink(ITfThreadMgrEventSink * 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); @@ -132,6 +179,10 @@ static void ThreadMgr_Destructor(ThreadMgr *This) { struct list *cursor, *cursor2; + /* unhook right away */ + if (This->focusHook) + UnhookWindowsHookEx(This->focusHook); + TlsSetValue(tlsIndex,NULL); TRACE("destroying %p\n", This); if (This->focus) @@ -183,6 +234,23 @@ static void ThreadMgr_Destructor(ThreadMgr *This) 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); } @@ -211,6 +279,10 @@ static HRESULT WINAPI ThreadMgr_QueryInterface(ITfThreadMgr *iface, REFIID iid, { *ppvOut = &This->ClientIdVtbl; } + else if (IsEqualIID(iid, &IID_ITfCompartmentMgr)) + { + *ppvOut = This->CompartmentMgr; + } if (*ppvOut) { @@ -294,16 +366,37 @@ static HRESULT WINAPI ThreadMgr_CreateDocumentMgr( ITfThreadMgr* iface, ITfDocum **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 @@ -334,7 +427,9 @@ static HRESULT WINAPI ThreadMgr_SetFocus( ITfThreadMgr* iface, ITfDocumentMgr *p 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); @@ -349,16 +444,53 @@ static HRESULT WINAPI ThreadMgr_SetFocus( ITfThreadMgr* iface, ITfDocumentMgr *p 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, @@ -381,8 +513,22 @@ static HRESULT WINAPI ThreadMgr_GetGlobalCompartment( ITfThreadMgr* iface, 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 = @@ -1054,7 +1200,11 @@ HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut) 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); @@ -1067,3 +1217,200 @@ HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut) *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); +} diff --git a/reactos/dll/win32/mshtml/dispex.c b/reactos/dll/win32/mshtml/dispex.c index 3dd11b18e4d..b8937e7c29e 100644 --- a/reactos/dll/win32/mshtml/dispex.c +++ b/reactos/dll/win32/mshtml/dispex.c @@ -35,12 +35,14 @@ typedef struct { 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; }; @@ -50,10 +52,20 @@ typedef struct { 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 @@ -188,22 +200,23 @@ void release_typelib(void) 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++; } @@ -237,6 +250,7 @@ static dispex_data_t *preprocess_dispex_data(DispatchEx *This) 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); @@ -251,7 +265,7 @@ static dispex_data_t *preprocess_dispex_data(DispatchEx *This) 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); } @@ -343,55 +357,56 @@ static inline BOOL is_dynamic_dispid(DISPID id) 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; + } + + for(i=0; i < data->prop_cnt; i++) { + if(!strcmpW(data->props[i].name, name)) { + *ret = data->props+i; + return S_OK; } } - if(alloc) { - TRACE("creating dynamic prop %s\n", debugstr_w(name)); + 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; - } + 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; - 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; + new_props = heap_realloc(data->props, sizeof(dynamic_prop_t)*(data->buf_size<<1)); + if(!new_props) + return E_OUTOFMEMORY; - new_props = heap_realloc(data->props, sizeof(dynamic_prop_t)*(data->buf_size<<1)); - if(!new_props) - return E_OUTOFMEMORY; - - data->props = new_props; - data->buf_size <<= 1; - } - - 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) @@ -407,6 +422,191 @@ HRESULT dispex_get_dprop_ref(DispatchEx *This, const WCHAR *name, BOOL alloc, VA 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) @@ -547,15 +747,15 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc 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); @@ -648,21 +848,11 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc 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; - } + 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 = 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; - } - - hres = ITypeInfo_Invoke(ti, unk, id, wFlags, pdp, pvarRes, pei, &argerr); - - IUnknown_Release(unk); return hres; } @@ -756,9 +946,40 @@ BOOL dispex_query_interface(DispatchEx *This, REFIID riid, void **ppv) 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; } diff --git a/reactos/dll/win32/mshtml/htmlcurstyle.c b/reactos/dll/win32/mshtml/htmlcurstyle.c index 5aaaece85c2..d622239816b 100644 --- a/reactos/dll/win32/mshtml/htmlcurstyle.c +++ b/reactos/dll/win32/mshtml/htmlcurstyle.c @@ -90,6 +90,7 @@ static ULONG WINAPI HTMLCurrentStyle_Release(IHTMLCurrentStyle *iface) if(!ref) { if(This->nsstyle) nsIDOMCSSStyleDeclaration_Release(This->nsstyle); + release_dispex(&This->dispex); heap_free(This); } @@ -144,15 +145,15 @@ static HRESULT WINAPI HTMLCurrentStyle_get_styleFloat(IHTMLCurrentStyle *iface, 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) @@ -279,29 +280,29 @@ static HRESULT WINAPI HTMLCurrentStyle_get_borderLeftStyle(IHTMLCurrentStyle *if 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) @@ -386,8 +387,10 @@ static HRESULT WINAPI HTMLCurrentStyle_get_display(IHTMLCurrentStyle *iface, BST 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) @@ -519,8 +522,8 @@ static HRESULT WINAPI HTMLCurrentStyle_get_clipLeft(IHTMLCurrentStyle *iface, VA 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) @@ -723,8 +726,8 @@ static HRESULT WINAPI HTMLCurrentStyle_get_borderColor(IHTMLCurrentStyle *iface, 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) @@ -737,8 +740,8 @@ static HRESULT WINAPI HTMLCurrentStyle_get_padding(IHTMLCurrentStyle *iface, BST 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) diff --git a/reactos/dll/win32/mshtml/htmldoc.c b/reactos/dll/win32/mshtml/htmldoc.c index 0b952293293..d5b6cbe5c8f 100644 --- a/reactos/dll/win32/mshtml/htmldoc.c +++ b/reactos/dll/win32/mshtml/htmldoc.c @@ -215,6 +215,7 @@ static ULONG WINAPI HTMLDocument_Release(IHTMLDocument2 *iface) detach_selection(This); detach_ranges(This); release_nodes(This); + release_dispex(&This->dispex); ConnectionPointContainer_Destroy(&This->cp_container); @@ -900,17 +901,14 @@ static HRESULT WINAPI HTMLDocument_get_nameProp(IHTMLDocument2 *iface, BSTR *p) 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; @@ -929,10 +927,14 @@ static HRESULT WINAPI HTMLDocument_write(IHTMLDocument2 *iface, SAFEARRAY *psarr 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 { @@ -946,11 +948,22 @@ static HRESULT WINAPI HTMLDocument_write(IHTMLDocument2 *iface, SAFEARRAY *psarr 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, diff --git a/reactos/dll/win32/mshtml/htmlelem.c b/reactos/dll/win32/mshtml/htmlelem.c index 170d5a0761a..84f63095497 100644 --- a/reactos/dll/win32/mshtml/htmlelem.c +++ b/reactos/dll/win32/mshtml/htmlelem.c @@ -931,8 +931,26 @@ static HRESULT WINAPI HTMLElement_put_outerHTML(IHTMLElement *iface, BSTR v) 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) diff --git a/reactos/dll/win32/mshtml/htmlelemcol.c b/reactos/dll/win32/mshtml/htmlelemcol.c index 43628907943..63fcb80544a 100644 --- a/reactos/dll/win32/mshtml/htmlelemcol.c +++ b/reactos/dll/win32/mshtml/htmlelemcol.c @@ -132,6 +132,7 @@ static ULONG WINAPI HTMLElementCollection_Release(IHTMLElementCollection *iface) if(!ref) { IUnknown_Release(This->ref_unk); + release_dispex(&This->dispex); heap_free(This->elems); heap_free(This); } @@ -428,6 +429,7 @@ static const IHTMLElementCollectionVtbl HTMLElementCollectionVtbl = { }; static const dispex_static_data_vtbl_t HTMLElementColection_dispex_vtbl = { + NULL, HTMLElementCollection_get_dispid, HTMLElementCollection_invoke }; diff --git a/reactos/dll/win32/mshtml/htmlevent.c b/reactos/dll/win32/mshtml/htmlevent.c index b73f8658b40..ca7166c004f 100644 --- a/reactos/dll/win32/mshtml/htmlevent.c +++ b/reactos/dll/win32/mshtml/htmlevent.c @@ -176,8 +176,10 @@ static ULONG WINAPI HTMLEventObj_Release(IHTMLEventObj *iface) TRACE("(%p) ref=%d\n", This, ref); - if(!ref) + if(!ref) { + release_dispex(&This->dispex); heap_free(This); + } return ref; } diff --git a/reactos/dll/win32/mshtml/htmlinput.c b/reactos/dll/win32/mshtml/htmlinput.c index eaffae5b534..df7cb5fb304 100644 --- a/reactos/dll/win32/mshtml/htmlinput.c +++ b/reactos/dll/win32/mshtml/htmlinput.c @@ -839,7 +839,7 @@ static HRESULT WINAPI HTMLInputTextElement_get_value(IHTMLInputTextElement *ifac 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) diff --git a/reactos/dll/win32/mshtml/htmllocation.c b/reactos/dll/win32/mshtml/htmllocation.c index 35f042a2676..8637838b776 100644 --- a/reactos/dll/win32/mshtml/htmllocation.c +++ b/reactos/dll/win32/mshtml/htmllocation.c @@ -23,7 +23,10 @@ #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" @@ -79,6 +82,7 @@ static ULONG WINAPI HTMLLocation_Release(IHTMLLocation *iface) if(!ref) { if(This->doc && This->doc->location == This) This->doc->location = NULL; + release_dispex(&This->dispex); heap_free(This); } @@ -125,8 +129,20 @@ static HRESULT WINAPI HTMLLocation_put_href(IHTMLLocation *iface, BSTR v) 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) @@ -195,8 +211,41 @@ static HRESULT WINAPI HTMLLocation_put_pathname(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) @@ -255,6 +304,34 @@ static HRESULT WINAPI HTMLLocation_toString(IHTMLLocation *iface, BSTR *String) 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 = { @@ -287,12 +364,18 @@ 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 diff --git a/reactos/dll/win32/mshtml/htmlnode.c b/reactos/dll/win32/mshtml/htmlnode.c index 720bbfef4be..30fdac87162 100644 --- a/reactos/dll/win32/mshtml/htmlnode.c +++ b/reactos/dll/win32/mshtml/htmlnode.c @@ -250,6 +250,7 @@ static const tid_t HTMLDOMChildrenCollection_iface_tids[] = { }; static const dispex_static_data_vtbl_t HTMLDOMChildrenCollection_dispex_vtbl = { + NULL, HTMLDOMChildrenCollection_get_dispid, HTMLDOMChildrenCollection_invoke }; @@ -307,6 +308,7 @@ static ULONG WINAPI HTMLDOMNode_Release(IHTMLDOMNode *iface) if(!ref) { This->vtbl->destructor(This); + release_dispex(&This->dispex); heap_free(This); } diff --git a/reactos/dll/win32/mshtml/htmlstyle.c b/reactos/dll/win32/mshtml/htmlstyle.c index f036077f642..a993702eaea 100644 --- a/reactos/dll/win32/mshtml/htmlstyle.c +++ b/reactos/dll/win32/mshtml/htmlstyle.c @@ -59,6 +59,8 @@ static const WCHAR attrBorderLeft[] = {'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[] = @@ -93,6 +95,8 @@ static const WCHAR attrHeight[] = {'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[] = @@ -119,6 +123,8 @@ static const WCHAR attrVisibility[] = {'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[] = @@ -140,6 +146,7 @@ static const struct{ {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}, @@ -157,6 +164,7 @@ static const struct{ {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}, @@ -170,6 +178,7 @@ static const struct{ {attrVerticalAlign, DISPID_IHTMLSTYLE_VERTICALALIGN}, {attrVisibility, DISPID_IHTMLSTYLE_VISIBILITY}, {attrWidth, DISPID_IHTMLSTYLE_WIDTH}, + {attrWordSpacing, DISPID_IHTMLSTYLE_WORDSPACING}, {attrWordWrap, DISPID_IHTMLSTYLE3_WORDWRAP}, {attrZIndex, DISPID_IHTMLSTYLE_ZINDEX} }; @@ -545,6 +554,7 @@ static ULONG WINAPI HTMLStyle_Release(IHTMLStyle *iface) if(!ref) { if(This->nsstyle) nsIDOMCSSStyleDeclaration_Release(This->nsstyle); + release_dispex(&This->dispex); heap_free(This); } @@ -920,29 +930,29 @@ static HRESULT WINAPI HTMLStyle_get_backgroundPositionY(IHTMLStyle *iface, VARIA 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) @@ -1574,15 +1584,15 @@ static HRESULT WINAPI HTMLStyle_get_borderBottomWidth(IHTMLStyle *iface, VARIANT 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) @@ -2601,6 +2611,7 @@ static const IHTMLStyleVtbl HTMLStyleVtbl = { }; static const dispex_static_data_vtbl_t HTMLStyle_dispex_vtbl = { + NULL, HTMLStyle_get_dispid, NULL }; diff --git a/reactos/dll/win32/mshtml/htmlstyle.h b/reactos/dll/win32/mshtml/htmlstyle.h index 307824e5c5d..b691804cefa 100644 --- a/reactos/dll/win32/mshtml/htmlstyle.h +++ b/reactos/dll/win32/mshtml/htmlstyle.h @@ -47,6 +47,7 @@ typedef enum { 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, @@ -64,6 +65,7 @@ typedef enum { STYLEID_FONT_WEIGHT, STYLEID_HEIGHT, STYLEID_LEFT, + STYLEID_LETTER_SPACING, STYLEID_MARGIN, STYLEID_MARGIN_LEFT, STYLEID_MARGIN_RIGHT, @@ -77,6 +79,7 @@ typedef enum { STYLEID_VERTICAL_ALIGN, STYLEID_VISIBILITY, STYLEID_WIDTH, + STYLEID_WORD_SPACING, STYLEID_WORD_WRAP, STYLEID_Z_INDEX } styleid_t; diff --git a/reactos/dll/win32/mshtml/htmlwindow.c b/reactos/dll/win32/mshtml/htmlwindow.c index a92870941bf..d50eca17758 100644 --- a/reactos/dll/win32/mshtml/htmlwindow.c +++ b/reactos/dll/win32/mshtml/htmlwindow.c @@ -93,6 +93,7 @@ static ULONG WINAPI HTMLWindow2_Release(IHTMLWindow2 *iface) if(!ref) { list_remove(&This->entry); + release_dispex(&This->dispex); heap_free(This); } @@ -745,8 +746,16 @@ static HRESULT WINAPI HTMLWindow2_execScript(IHTMLWindow2 *iface, BSTR scode, BS 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) diff --git a/reactos/dll/win32/mshtml/mshtml.rbuild b/reactos/dll/win32/mshtml/mshtml.rbuild index ead2dcb4deb..ff605823772 100644 --- a/reactos/dll/win32/mshtml/mshtml.rbuild +++ b/reactos/dll/win32/mshtml/mshtml.rbuild @@ -77,6 +77,7 @@ gdi32 advapi32 kernel32 + wininet ntdll mshtml_nsiface_header diff --git a/reactos/dll/win32/mshtml/mshtml_private.h b/reactos/dll/win32/mshtml/mshtml_private.h index 6ab70f2df21..ecae0a55310 100644 --- a/reactos/dll/win32/mshtml/mshtml_private.h +++ b/reactos/dll/win32/mshtml/mshtml_private.h @@ -33,9 +33,6 @@ #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) @@ -44,8 +41,6 @@ #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)) @@ -132,6 +127,7 @@ typedef struct dispex_dynamic_data_t dispex_dynamic_data_t; #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; @@ -153,6 +149,7 @@ typedef struct { } 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**); @@ -363,11 +360,13 @@ struct NSContainer { 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; @@ -377,6 +376,7 @@ typedef struct { nsIURI *original_uri; char *content_type; char *charset; + PRUint32 response_status; } nsChannel; typedef struct { @@ -466,6 +466,7 @@ 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) @@ -559,9 +560,8 @@ void nsAString_SetData(nsAString*,const PRUnichar*); 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); diff --git a/reactos/dll/win32/mshtml/mutation.c b/reactos/dll/win32/mshtml/mutation.c index 6060a8dca94..f161de4eef2 100644 --- a/reactos/dll/win32/mshtml/mutation.c +++ b/reactos/dll/win32/mshtml/mutation.c @@ -461,6 +461,22 @@ static void NSAPI nsDocumentObserver_BeginLoad(nsIDocumentObserver *iface, nsIDo 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, diff --git a/reactos/dll/win32/mshtml/navigate.c b/reactos/dll/win32/mshtml/navigate.c index f882e6c0290..1a0d5eb4024 100644 --- a/reactos/dll/win32/mshtml/navigate.c +++ b/reactos/dll/win32/mshtml/navigate.c @@ -54,10 +54,12 @@ typedef struct { 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 { @@ -75,6 +77,7 @@ struct BSCallback { ULONG post_data_len; ULONG readed; DWORD bindf; + BOOL bindinfo_ready; IMoniker *mon; IBinding *binding; @@ -344,19 +347,23 @@ static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallback *ifac 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, @@ -367,6 +374,16 @@ 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; @@ -469,9 +486,11 @@ static HRESULT WINAPI HttpNegotiate_OnResponse(IHttpNegotiate2 *iface, DWORD dwR 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, @@ -744,6 +763,11 @@ static void BufferBSC_destroy(BSCallback *bsc) heap_free(This); } +static HRESULT BufferBSC_init_bindinfo(BSCallback *bsc) +{ + return S_OK; +} + static HRESULT BufferBSC_start_binding(BSCallback *bsc) { return S_OK; @@ -794,14 +818,21 @@ static HRESULT BufferBSC_on_progress(BSCallback *bsc, ULONG status_code, LPCWSTR 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 }; @@ -848,14 +879,46 @@ struct nsChannelBSC { 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; @@ -869,21 +932,21 @@ static HRESULT read_stream_data(nsChannelBSC *This, IStream *stream) 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) { @@ -901,22 +964,15 @@ static HRESULT read_stream_data(nsChannelBSC *This, IStream *stream) 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; @@ -957,6 +1013,19 @@ static HRESULT nsChannelBSC_start_binding(BSCallback *bsc) 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); @@ -974,23 +1043,6 @@ static HRESULT nsChannelBSC_stop_binding(BSCallback *bsc, HRESULT result) } } - 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; } @@ -1017,14 +1069,24 @@ static HRESULT nsChannelBSC_on_progress(BSCallback *bsc, ULONG status_code, LPCW 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) diff --git a/reactos/dll/win32/mshtml/nsembed.c b/reactos/dll/win32/mshtml/nsembed.c index 0464e0597b0..50001aa72b3 100644 --- a/reactos/dll/win32/mshtml/nsembed.c +++ b/reactos/dll/win32/mshtml/nsembed.c @@ -38,14 +38,10 @@ WINE_DECLARE_DEBUG_CHANNEL(gecko); #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" @@ -296,12 +292,38 @@ static BOOL load_wine_gecko(PRUnichar *gre_path) 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', @@ -321,9 +343,7 @@ static void set_lang(nsIPrefBranch *pref) 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) @@ -333,7 +353,6 @@ 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', @@ -368,30 +387,12 @@ static void set_proxy(nsIPrefBranch *pref) 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); -} + set_string_pref(pref, "network.proxy.http", proxy); + set_string_pref(pref, "network.proxy.ssl", proxy); -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)); + 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) @@ -410,6 +411,7 @@ 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); } @@ -575,32 +577,6 @@ void nsAString_Finish(nsAString *str) 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; @@ -633,7 +609,7 @@ nsresult get_nsinterface(nsISupports *iface, REFIID riid, void **ppv) 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; @@ -645,7 +621,7 @@ static void nsnode_to_nsstring_rec(nsIContentSerializer *serializer, nsIDOMNode nsres = nsIDOMNode_GetNodeType(nsnode, &type); if(NS_FAILED(nsres)) { ERR("GetType failed: %08x\n", nsres); - return; + return E_FAIL; } switch(type) { @@ -676,6 +652,9 @@ static void nsnode_to_nsstring_rec(nsIContentSerializer *serializer, nsIDOMNode nsIDOMDocument_Release(nsdoc); break; } + case DOCUMENT_TYPE_NODE: + WARN("Ignoring DOCUMENT_TYPE_NODE\n"); + break; case DOCUMENT_FRAGMENT_NODE: break; default: @@ -708,35 +687,37 @@ static void nsnode_to_nsstring_rec(nsIContentSerializer *serializer, nsIDOMNode 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) @@ -1179,6 +1160,33 @@ static nsrefcnt NSAPI nsURIContentListener_Release(nsIURIContentListener *iface) 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) { @@ -1222,12 +1230,15 @@ static nsresult NSAPI nsURIContentListener_OnStartURIOpen(nsIURIContentListener 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; } diff --git a/reactos/dll/win32/mshtml/nsevents.c b/reactos/dll/win32/mshtml/nsevents.c index 1933c5788cd..0ba11d2c361 100644 --- a/reactos/dll/win32/mshtml/nsevents.c +++ b/reactos/dll/win32/mshtml/nsevents.c @@ -131,7 +131,6 @@ static nsresult NSAPI handle_load(nsIDOMEventListener *iface, nsIDOMEvent *event { NSContainer *This = NSEVENTLIST_THIS(iface)->This; nsIDOMHTMLElement *nsbody = NULL; - task_t *task; TRACE("(%p)\n", This); @@ -149,18 +148,6 @@ static nsresult NSAPI handle_load(nsIDOMEventListener *iface, nsIDOMEvent *event 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; diff --git a/reactos/dll/win32/mshtml/nsiface.idl b/reactos/dll/win32/mshtml/nsiface.idl index 24c6214ffc2..cb8f76839b4 100644 --- a/reactos/dll/win32/mshtml/nsiface.idl +++ b/reactos/dll/win32/mshtml/nsiface.idl @@ -284,19 +284,6 @@ interface nsIInputStream : nsISupports 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), @@ -333,6 +320,34 @@ interface nsIURI : nsISupports 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), @@ -452,6 +467,24 @@ interface nsIHttpChannel : nsIChannel 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), @@ -2547,7 +2580,7 @@ interface nsIDocumentObserver : nsIMutationObserver local /* INTERNAL */ ] -interface nsIWineURI : nsIURI +interface nsIWineURI : nsIURL { typedef struct NSContainer NSContainer; diff --git a/reactos/dll/win32/mshtml/nsio.c b/reactos/dll/win32/mshtml/nsio.c index 7c402b295a9..12e8520978b 100644 --- a/reactos/dll/win32/mshtml/nsio.c +++ b/reactos/dll/win32/mshtml/nsio.c @@ -57,6 +57,7 @@ typedef struct { LONG ref; nsIURI *uri; + nsIURL *nsurl; NSContainer *container; LPWSTR wine_url; PRBool is_doc_uri; @@ -68,6 +69,14 @@ typedef struct { 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; @@ -167,8 +176,6 @@ static nsresult NSAPI nsChannel_QueryInterface(nsIHttpChannel *iface, nsIIDRef r { nsChannel *This = NSCHANNEL_THIS(iface); - *result = NULL; - if(IsEqualGUID(&IID_nsISupports, riid)) { TRACE("(%p)->(IID_nsISupports %p)\n", This, result); *result = NSCHANNEL(This); @@ -178,12 +185,18 @@ static nsresult NSAPI nsChannel_QueryInterface(nsIHttpChannel *iface, nsIIDRef r }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) { @@ -191,10 +204,6 @@ static nsresult NSAPI nsChannel_QueryInterface(nsIHttpChannel *iface, nsIIDRef r 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; } @@ -219,6 +228,8 @@ static nsrefcnt NSAPI nsChannel_Release(nsIHttpChannel *iface) 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) @@ -606,37 +617,6 @@ static nsresult NSAPI nsChannel_Open(nsIHttpChannel *iface, nsIInputStream **_re 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; @@ -730,8 +710,7 @@ static nsresult async_open_doc_uri(nsChannel *This, NSContainer *container, 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); @@ -762,23 +741,9 @@ static nsresult async_open(nsChannel *This, NSContainer *container, nsIStreamLis { 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; @@ -980,10 +945,15 @@ static nsresult NSAPI nsChannel_GetResponseStatus(nsIHttpChannel *iface, PRUint3 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, @@ -1217,6 +1187,131 @@ static const nsIUploadChannelVtbl nsUploadChannelVtbl = { 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) @@ -1231,6 +1326,9 @@ static nsresult NSAPI nsURI_QueryInterface(nsIWineURI *iface, nsIIDRef riid, nsQ }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); @@ -1265,6 +1363,8 @@ static nsrefcnt NSAPI nsURI_Release(nsIWineURI *iface) 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); @@ -1688,6 +1788,280 @@ static nsresult NSAPI nsURI_GetOriginCharset(nsIWineURI *iface, nsACString *aOri 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); @@ -1813,6 +2187,24 @@ static const nsIWineURIVtbl nsWineURIVtbl = { 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, @@ -1836,6 +2228,11 @@ static nsresult create_uri(nsIURI *uri, NSContainer *container, nsIWineURI **_re 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; @@ -2051,15 +2448,15 @@ static nsresult NSAPI nsIOService_GetProtocolFlags(nsIIOService *iface, const ch 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; - 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); + for(i=0; i < sizeof(special_schemes)/sizeof(*special_schemes); i++) { + if(!strncasecmp(spec, special_schemes[i], strlen(special_schemes[i]))) + return TRUE; + } + + return FALSE; } static nsresult NSAPI nsIOService_NewURI(nsIIOService *iface, const nsACString *aSpec, @@ -2187,6 +2584,7 @@ static nsresult NSAPI nsIOService_NewChannelFromURI(nsIIOService *iface, nsIURI ret->lpHttpChannelVtbl = &nsChannelVtbl; ret->lpUploadChannelVtbl = &nsUploadChannelVtbl; + ret->lpIHttpChannelInternalVtbl = &nsHttpChannelInternalVtbl; ret->ref = 1; ret->channel = channel; ret->uri = wine_uri; @@ -2194,8 +2592,10 @@ static nsresult NSAPI nsIOService_NewChannelFromURI(nsIIOService *iface, nsIURI 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; diff --git a/reactos/dll/win32/mshtml/omnavigator.c b/reactos/dll/win32/mshtml/omnavigator.c index e86537f946d..dc0fb4a8ca4 100644 --- a/reactos/dll/win32/mshtml/omnavigator.c +++ b/reactos/dll/win32/mshtml/omnavigator.c @@ -84,8 +84,10 @@ static ULONG WINAPI OmNavigator_Release(IOmNavigator *iface) TRACE("(%p) ref=%d\n", This, ref); - if(!ref) + if(!ref) { + release_dispex(&This->dispex); heap_free(This); + } return ref; } @@ -139,8 +141,19 @@ static HRESULT WINAPI OmNavigator_get_appCodeName(IOmNavigator *iface, BSTR *p) 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) @@ -166,8 +179,24 @@ 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) @@ -215,8 +244,16 @@ static HRESULT WINAPI OmNavigator_get_opsProfile(IOmNavigator *iface, IHTMLOpsPr 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) diff --git a/reactos/dll/win32/mshtml/persist.c b/reactos/dll/win32/mshtml/persist.c index c8a0c5731b3..6c1a0e5f3b7 100644 --- a/reactos/dll/win32/mshtml/persist.c +++ b/reactos/dll/win32/mshtml/persist.c @@ -39,129 +39,6 @@ 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',':'}; @@ -304,27 +181,15 @@ static HRESULT set_moniker(HTMLDocument *This, IMoniker *mon, IBindCtx *pibc, BO 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; } } @@ -337,7 +202,7 @@ static HRESULT set_moniker(HTMLDocument *This, IMoniker *mon, IBindCtx *pibc, BO 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; @@ -362,9 +227,7 @@ static HRESULT get_doc_string(HTMLDocument *This, char **str, DWORD *len) 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); @@ -583,7 +446,7 @@ static HRESULT WINAPI PersistFile_Save(IPersistFile *iface, LPCOLESTR pszFileNam { HTMLDocument *This = PERSISTFILE_THIS(iface); char *str; - DWORD len, written=0; + DWORD written=0; HANDLE file; HRESULT hres; @@ -596,9 +459,9 @@ static HRESULT WINAPI PersistFile_Save(IPersistFile *iface, LPCOLESTR pszFileNam 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; @@ -698,16 +561,16 @@ static HRESULT WINAPI PersistStreamInit_Save(IPersistStreamInit *iface, LPSTREAM { 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); diff --git a/reactos/dll/win32/mshtml/script.c b/reactos/dll/win32/mshtml/script.c index 55636d2118e..e12588ccd3e 100644 --- a/reactos/dll/win32/mshtml/script.c +++ b/reactos/dll/win32/mshtml/script.c @@ -67,12 +67,30 @@ typedef struct { #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); @@ -104,20 +122,13 @@ static BOOL init_script_engine(ScriptHost *script_host) if(FAILED(hres)) return FALSE; - hres = IActiveScript_QueryInterface(script_host->script, &IID_IActiveScriptProperty, (void**)&property); - if(SUCCEEDED(hres)) { - VARIANT var; + V_VT(&var) = VT_I4; + V_I4(&var) = 1; + set_script_prop(script_host, SCRIPTPROP_INVOKEVERSIONING, &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); - - 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)) { @@ -146,8 +157,13 @@ static BOOL init_script_engine(ScriptHost *script_host) 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); diff --git a/reactos/dll/win32/msxml3/attribute.c b/reactos/dll/win32/msxml3/attribute.c index 9fabc469a7d..2fc32be11d0 100644 --- a/reactos/dll/win32/msxml3/attribute.c +++ b/reactos/dll/win32/msxml3/attribute.c @@ -556,7 +556,7 @@ IUnknown* create_attribute( xmlNodePtr attribute ) 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); diff --git a/reactos/dll/win32/msxml3/cdata.c b/reactos/dll/win32/msxml3/cdata.c index a9b7fee34a0..b0ef3d76595 100644 --- a/reactos/dll/win32/msxml3/cdata.c +++ b/reactos/dll/win32/msxml3/cdata.c @@ -779,7 +779,7 @@ IUnknown* create_cdata( xmlNodePtr text ) 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); diff --git a/reactos/dll/win32/msxml3/comment.c b/reactos/dll/win32/msxml3/comment.c index a8cf528a374..346ad192730 100644 --- a/reactos/dll/win32/msxml3/comment.c +++ b/reactos/dll/win32/msxml3/comment.c @@ -777,7 +777,7 @@ IUnknown* create_comment( xmlNodePtr comment ) 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); diff --git a/reactos/dll/win32/msxml3/dispex.c b/reactos/dll/win32/msxml3/dispex.c index 59d887842a4..529f9a452ee 100644 --- a/reactos/dll/win32/msxml3/dispex.c +++ b/reactos/dll/win32/msxml3/dispex.c @@ -91,6 +91,7 @@ static REFIID tid_ids[] = { &IID_IXMLDOMParseError, &IID_IXMLDOMProcessingInstruction, &IID_IXMLDOMSchemaCollection, + &IID_IXMLDOMSelection, &IID_IXMLDOMText, &IID_IXMLElement, &IID_IXMLDOMDocument, diff --git a/reactos/dll/win32/msxml3/docfrag.c b/reactos/dll/win32/msxml3/docfrag.c index 572d223d44d..1330c196ba0 100644 --- a/reactos/dll/win32/msxml3/docfrag.c +++ b/reactos/dll/win32/msxml3/docfrag.c @@ -529,7 +529,7 @@ IUnknown* create_doc_fragment( xmlNodePtr fragment ) 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); diff --git a/reactos/dll/win32/msxml3/domdoc.c b/reactos/dll/win32/msxml3/domdoc.c index 84bd43c2c88..ad0fe0a49bc 100644 --- a/reactos/dll/win32/msxml3/domdoc.c +++ b/reactos/dll/win32/msxml3/domdoc.c @@ -77,9 +77,6 @@ typedef struct _domdoc /* IObjectSafety */ DWORD safeopt; - - /* IDispatchEx */ - DispatchEx dispex; } domdoc; /* @@ -466,7 +463,7 @@ static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument2 *iface, REFIID rii { *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; } @@ -1043,7 +1040,7 @@ static HRESULT WINAPI domdoc_createElement( 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); @@ -2218,15 +2215,13 @@ HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument2 **docu 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); diff --git a/reactos/dll/win32/msxml3/element.c b/reactos/dll/win32/msxml3/element.c index 33db539457b..6590e5baed5 100644 --- a/reactos/dll/win32/msxml3/element.c +++ b/reactos/dll/win32/msxml3/element.c @@ -41,8 +41,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(msxml); typedef struct _domelem { const struct IXMLDOMElementVtbl *lpVtbl; - const struct IUnknownVtbl *lpInternalUnkVtbl; - IUnknown *pUnkOuter; LONG ref; xmlnode *node; } domelem; @@ -52,11 +50,6 @@ static inline domelem *impl_from_IXMLDOMElement( IXMLDOMElement *iface ) 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; @@ -68,23 +61,54 @@ static HRESULT WINAPI domelem_QueryInterface( 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( @@ -727,66 +751,7 @@ static const struct IXMLDOMElementVtbl domelem_vtbl = 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; @@ -796,21 +761,15 @@ IUnknown* create_element( xmlNodePtr element, IUnknown *pUnkOuter ) 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 diff --git a/reactos/dll/win32/msxml3/entityref.c b/reactos/dll/win32/msxml3/entityref.c index 1726e2f1697..102bf44533b 100644 --- a/reactos/dll/win32/msxml3/entityref.c +++ b/reactos/dll/win32/msxml3/entityref.c @@ -528,7 +528,7 @@ IUnknown* create_doc_entity_ref( xmlNodePtr entity ) 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); diff --git a/reactos/dll/win32/msxml3/msxml_private.h b/reactos/dll/win32/msxml3/msxml_private.h index d09b3801fd5..57dec0f4719 100644 --- a/reactos/dll/win32/msxml3/msxml_private.h +++ b/reactos/dll/win32/msxml3/msxml_private.h @@ -29,117 +29,6 @@ # error You must include config.h to use this header #endif -#ifdef HAVE_LIBXML2 - -#ifdef HAVE_LIBXML_PARSER_H -#include -#endif - -/* constructors */ -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_attribute( xmlNodePtr attribute ); -extern IUnknown *create_text( xmlNodePtr text ); -extern IUnknown *create_pi( xmlNodePtr pi ); -extern IUnknown *create_comment( xmlNodePtr comment ); -extern IUnknown *create_cdata( xmlNodePtr text ); -extern IXMLDOMNodeList *create_children_nodelist( xmlNodePtr ); -extern IXMLDOMNamedNodeMap *create_nodemap( IXMLDOMNode *node ); -extern IUnknown *create_doc_Implementation(); -extern IUnknown *create_doc_fragment( xmlNodePtr fragment ); -extern IUnknown *create_doc_entity_ref( xmlNodePtr entity ); - -extern HRESULT queryresult_create( xmlNodePtr, LPWSTR, IXMLDOMNodeList ** ); - -/* data accessors */ -xmlNodePtr xmlNodePtr_from_domnode( IXMLDOMNode *iface, xmlElementType type ); - -/* helpers */ -extern xmlChar *xmlChar_from_wchar( LPWSTR str ); - -extern LONG xmldoc_add_ref( xmlDocPtr doc ); -extern LONG xmldoc_release( xmlDocPtr doc ); -extern HRESULT xmldoc_add_orphan( xmlDocPtr doc, xmlNodePtr node ); -extern HRESULT xmldoc_remove_orphan( xmlDocPtr doc, xmlNodePtr node ); - -extern HRESULT XMLElement_create( IUnknown *pUnkOuter, xmlNodePtr node, LPVOID *ppObj ); - -extern xmlDocPtr parse_xml(char *ptr, int len); - -/* IXMLDOMNode Internal Structure */ -typedef struct _xmlnode -{ - const struct IXMLDOMNodeVtbl *lpVtbl; - const struct IUnknownVtbl *lpInternalUnkVtbl; - IUnknown *pUnkOuter; - LONG ref; - xmlNodePtr node; -} xmlnode; - -static inline xmlnode *impl_from_IXMLDOMNode( IXMLDOMNode *iface ) -{ - return (xmlnode *)((char*)iface - FIELD_OFFSET(xmlnode, lpVtbl)); -} - -static inline IXMLDOMNode *IXMLDOMNode_from_impl(xmlnode *This) -{ - return (IXMLDOMNode*)&This->lpVtbl; -} - -extern xmlnode *create_basic_node(xmlNodePtr,IUnknown*); - -extern HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument2 **document); - -static inline BSTR bstr_from_xmlChar(const xmlChar *str) -{ - BSTR ret = NULL; - - if(str) { - DWORD len = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)str, -1, NULL, 0); - ret = SysAllocStringLen(NULL, len-1); - if(ret) - MultiByteToWideChar( CP_UTF8, 0, (LPCSTR)str, -1, ret, len); - } - - return ret; -} - -#endif - -void* libxslt_handle; -#ifdef SONAME_LIBXSLT -# ifdef HAVE_LIBXSLT_PATTERN_H -# include -# endif -# ifdef HAVE_LIBXSLT_TRANSFORM_H -# include -# endif -# include -# include - -# define MAKE_FUNCPTR(f) extern typeof(f) * p##f -MAKE_FUNCPTR(xsltApplyStylesheet); -MAKE_FUNCPTR(xsltCleanupGlobals); -MAKE_FUNCPTR(xsltFreeStylesheet); -MAKE_FUNCPTR(xsltParseStylesheetDoc); -# undef MAKE_FUNCPTR -#endif - -extern IXMLDOMParseError *create_parseError( LONG code, BSTR url, BSTR reason, BSTR srcText, - LONG line, LONG linepos, LONG filepos ); -extern HRESULT DOMDocument_create( IUnknown *pUnkOuter, LPVOID *ppObj ); -extern HRESULT SchemaCache_create( IUnknown *pUnkOuter, LPVOID *ppObj ); -extern HRESULT XMLDocument_create( IUnknown *pUnkOuter, LPVOID *ppObj ); -extern HRESULT SAXXMLReader_create(IUnknown *pUnkOuter, LPVOID *ppObj ); -extern HRESULT XMLHTTPRequest_create(IUnknown *pUnkOuter, LPVOID *ppObj); - -typedef struct bsc_t bsc_t; - -HRESULT bind_url(LPCWSTR, HRESULT (*onDataAvailable)(void*,char*,DWORD), void*, bsc_t**); -void detach_bsc(bsc_t*); - /* typelibs */ typedef enum tid_t { IXMLDOMAttribute_tid, @@ -157,6 +46,7 @@ typedef enum tid_t { IXMLDOMParseError_tid, IXMLDOMProcessingInstruction_tid, IXMLDOMSchemaCollection_tid, + IXMLDOMSelection_tid, IXMLDOMText_tid, IXMLElement_tid, IXMLDocument_tid, @@ -210,6 +100,118 @@ typedef struct { void init_dispex(DispatchEx*,IUnknown*,dispex_static_data_t*); BOOL dispex_query_interface(DispatchEx*,REFIID,void**); +#ifdef HAVE_LIBXML2 + +#ifdef HAVE_LIBXML_PARSER_H +#include +#endif + +/* constructors */ +extern IUnknown *create_domdoc( xmlNodePtr document ); +extern IUnknown *create_xmldoc( void ); +extern IXMLDOMNode *create_node( xmlNodePtr node ); +extern IUnknown *create_element( xmlNodePtr element ); +extern IUnknown *create_attribute( xmlNodePtr attribute ); +extern IUnknown *create_text( xmlNodePtr text ); +extern IUnknown *create_pi( xmlNodePtr pi ); +extern IUnknown *create_comment( xmlNodePtr comment ); +extern IUnknown *create_cdata( xmlNodePtr text ); +extern IXMLDOMNodeList *create_children_nodelist( xmlNodePtr ); +extern IXMLDOMNamedNodeMap *create_nodemap( IXMLDOMNode *node ); +extern IUnknown *create_doc_Implementation(); +extern IUnknown *create_doc_fragment( xmlNodePtr fragment ); +extern IUnknown *create_doc_entity_ref( xmlNodePtr entity ); + +extern HRESULT queryresult_create( xmlNodePtr, LPWSTR, IXMLDOMNodeList ** ); + +/* data accessors */ +xmlNodePtr xmlNodePtr_from_domnode( IXMLDOMNode *iface, xmlElementType type ); + +/* helpers */ +extern xmlChar *xmlChar_from_wchar( LPWSTR str ); + +extern LONG xmldoc_add_ref( xmlDocPtr doc ); +extern LONG xmldoc_release( xmlDocPtr doc ); +extern HRESULT xmldoc_add_orphan( xmlDocPtr doc, xmlNodePtr node ); +extern HRESULT xmldoc_remove_orphan( xmlDocPtr doc, xmlNodePtr node ); + +extern HRESULT XMLElement_create( IUnknown *pUnkOuter, xmlNodePtr node, LPVOID *ppObj ); + +extern xmlDocPtr parse_xml(char *ptr, int len); + +/* IXMLDOMNode Internal Structure */ +typedef struct _xmlnode +{ + DispatchEx dispex; + const struct IXMLDOMNodeVtbl *lpVtbl; + const struct IUnknownVtbl *lpInternalUnkVtbl; + IUnknown *pUnkOuter; + LONG ref; + xmlNodePtr node; +} xmlnode; + +static inline xmlnode *impl_from_IXMLDOMNode( IXMLDOMNode *iface ) +{ + return (xmlnode *)((char*)iface - FIELD_OFFSET(xmlnode, lpVtbl)); +} + +static inline IXMLDOMNode *IXMLDOMNode_from_impl(xmlnode *This) +{ + return (IXMLDOMNode*)&This->lpVtbl; +} + +extern xmlnode *create_basic_node(xmlNodePtr,IUnknown*,dispex_static_data_t*); + +extern HRESULT DOMDocument_create_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument2 **document); + +static inline BSTR bstr_from_xmlChar(const xmlChar *str) +{ + BSTR ret = NULL; + + if(str) { + DWORD len = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)str, -1, NULL, 0); + ret = SysAllocStringLen(NULL, len-1); + if(ret) + MultiByteToWideChar( CP_UTF8, 0, (LPCSTR)str, -1, ret, len); + } + + return ret; +} + +#endif + +void* libxslt_handle; +#ifdef SONAME_LIBXSLT +# ifdef HAVE_LIBXSLT_PATTERN_H +# include +# endif +# ifdef HAVE_LIBXSLT_TRANSFORM_H +# include +# endif +# include +# include + +# define MAKE_FUNCPTR(f) extern typeof(f) * p##f +MAKE_FUNCPTR(xsltApplyStylesheet); +MAKE_FUNCPTR(xsltCleanupGlobals); +MAKE_FUNCPTR(xsltFreeStylesheet); +MAKE_FUNCPTR(xsltParseStylesheetDoc); +# undef MAKE_FUNCPTR +#endif + +extern IXMLDOMParseError *create_parseError( LONG code, BSTR url, BSTR reason, BSTR srcText, + LONG line, LONG linepos, LONG filepos ); +extern HRESULT DOMDocument_create( IUnknown *pUnkOuter, LPVOID *ppObj ); +extern HRESULT SchemaCache_create( IUnknown *pUnkOuter, LPVOID *ppObj ); +extern HRESULT XMLDocument_create( IUnknown *pUnkOuter, LPVOID *ppObj ); +extern HRESULT SAXXMLReader_create(IUnknown *pUnkOuter, LPVOID *ppObj ); +extern HRESULT XMLHTTPRequest_create(IUnknown *pUnkOuter, LPVOID *ppObj); + +typedef struct bsc_t bsc_t; + +HRESULT bind_url(LPCWSTR, HRESULT (*onDataAvailable)(void*,char*,DWORD), void*, bsc_t**); +void detach_bsc(bsc_t*); + /* memory allocation functions */ static inline void *heap_alloc(size_t len) diff --git a/reactos/dll/win32/msxml3/node.c b/reactos/dll/win32/msxml3/node.c index 2876ef3a05e..987b07d2d09 100644 --- a/reactos/dll/win32/msxml3/node.c +++ b/reactos/dll/win32/msxml3/node.c @@ -1542,7 +1542,7 @@ static const struct IUnknownVtbl internal_unk_vtbl = 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; @@ -1561,6 +1561,9 @@ xmlnode *create_basic_node( xmlNodePtr node, IUnknown *pUnkOuter ) else This->pUnkOuter = (IUnknown *)&This->lpInternalUnkVtbl; + if(dispex_data) + init_dispex(&This->dispex, This->pUnkOuter, dispex_data); + This->ref = 1; This->node = node; @@ -1580,7 +1583,7 @@ IXMLDOMNode *create_node( xmlNodePtr 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 ); @@ -1599,7 +1602,7 @@ IXMLDOMNode *create_node( xmlNodePtr 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); diff --git a/reactos/dll/win32/msxml3/pi.c b/reactos/dll/win32/msxml3/pi.c index 00a52665088..ddcf68b9415 100644 --- a/reactos/dll/win32/msxml3/pi.c +++ b/reactos/dll/win32/msxml3/pi.c @@ -614,7 +614,7 @@ IUnknown* create_pi( xmlNodePtr pi ) 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); diff --git a/reactos/dll/win32/msxml3/queryresult.c b/reactos/dll/win32/msxml3/queryresult.c index 1cdd9f66f47..50e8b79a83f 100644 --- a/reactos/dll/win32/msxml3/queryresult.c +++ b/reactos/dll/win32/msxml3/queryresult.c @@ -366,7 +366,7 @@ static const tid_t queryresult_iface_tids[] = { }; static dispex_static_data_t queryresult_dispex = { &queryresult_dispex_vtbl, - IXMLDOMNodeList_tid, + IXMLDOMSelection_tid, NULL, queryresult_iface_tids }; diff --git a/reactos/dll/win32/msxml3/text.c b/reactos/dll/win32/msxml3/text.c index 58de405c321..cb1966c03ad 100644 --- a/reactos/dll/win32/msxml3/text.c +++ b/reactos/dll/win32/msxml3/text.c @@ -781,7 +781,7 @@ IUnknown* create_text( xmlNodePtr text ) 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);