-- v4: mshtml: Handle cNames > 1 in GetIDsOfNames properly. mshtml: Forward IDispatchEx to the document node. mshtml: Forward toString to the document node. mshtml: Expose IEventTarget on HTMLDocumentObj and forward it to the doc node. mshtml/tests: Implement IServiceProvider and few other interfaces needed
From: Gabriel Ivăncescu gabrielopcode@gmail.com
This is to allow to test events and things related to navigating to a new page. Otherwise, native IE will open a new IE process with the destination.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/tests/events.c | 964 +++++++++++++++++++++++++++++++++++++ 1 file changed, 964 insertions(+)
diff --git a/dlls/mshtml/tests/events.c b/dlls/mshtml/tests/events.c index 8175205b830..209552d17d6 100644 --- a/dlls/mshtml/tests/events.c +++ b/dlls/mshtml/tests/events.c @@ -28,8 +28,10 @@ #include "ole2.h" #include "mshtml.h" #include "mshtmdid.h" +#include "mshtmhst.h" #include "docobj.h" #include "hlink.h" +#include "shdeprecated.h" #include "dispex.h"
#define DEFINE_EXPECT(func) \ @@ -2996,6 +2998,8 @@ static HRESULT WINAPI window2_onstorage(IDispatchEx *iface, DISPID id, LCID lcid EVENT_HANDLER_FUNC_OBJ(window2_onstorage);
static HRESULT QueryInterface(REFIID,void**); +static HRESULT browserservice_qi(REFIID,void**); +static HRESULT wb_qi(REFIID,void**);
static HRESULT WINAPI InPlaceFrame_QueryInterface(IOleInPlaceFrame *iface, REFIID riid, void **ppv) { @@ -3349,6 +3353,964 @@ static const IOleDocumentSiteVtbl DocumentSiteVtbl = {
static IOleDocumentSite DocumentSite = { &DocumentSiteVtbl };
+static HRESULT WINAPI TravelLog_QueryInterface(ITravelLog *iface, REFIID riid, void **ppv) +{ + if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_ITravelLog, riid)) + *ppv = iface; + else { + *ppv = NULL; + return E_NOINTERFACE; + } + return S_OK; +} + +static ULONG WINAPI TravelLog_AddRef(ITravelLog *iface) +{ + return 2; +} + +static ULONG WINAPI TravelLog_Release(ITravelLog *iface) +{ + return 1; +} + +static HRESULT WINAPI TravelLog_AddEntry(ITravelLog *iface, IUnknown *punk, BOOL fIsLocalAnchor) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI TravelLog_UpdateEntry(ITravelLog *iface, IUnknown *punk, BOOL fIsLocalAnchor) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI TravelLog_UpdateExternal(ITravelLog *iface, IUnknown *punk, IUnknown *punkHLBrowseContext) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI TravelLog_Travel(ITravelLog *iface, IUnknown *punk, int iOffset) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI TravelLog_GetTravelEntry(ITravelLog *iface, IUnknown *punk, int iOffset, ITravelEntry **ppte) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI TravelLog_FindTravelEntry(ITravelLog *iface, IUnknown *punk, LPCITEMIDLIST pidl, ITravelEntry **ppte) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI TravelLog_GetTooltipText(ITravelLog *iface, IUnknown *punk, int iOffset, int idsTemplate, LPWSTR pwzText, DWORD cchText) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI TravelLog_InsertMenuEntries(ITravelLog *iface, IUnknown *punk, HMENU hmenu, int nPos, int idFirst, int idLast, DWORD dwFlags) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI TravelLog_Clone(ITravelLog *iface, ITravelLog **pptl) +{ + return E_NOTIMPL; +} + +static DWORD WINAPI TravelLog_CountEntries(ITravelLog *iface, IUnknown *punk) +{ + return 0; +} + +static HRESULT WINAPI TravelLog_Revert(ITravelLog *iface) +{ + return E_NOTIMPL; +} + +static const ITravelLogVtbl TravelLogVtbl = { + TravelLog_QueryInterface, + TravelLog_AddRef, + TravelLog_Release, + TravelLog_AddEntry, + TravelLog_UpdateEntry, + TravelLog_UpdateExternal, + TravelLog_Travel, + TravelLog_GetTravelEntry, + TravelLog_FindTravelEntry, + TravelLog_GetTooltipText, + TravelLog_InsertMenuEntries, + TravelLog_Clone, + TravelLog_CountEntries, + TravelLog_Revert +}; + +static ITravelLog TravelLog = { &TravelLogVtbl }; + +static HRESULT WINAPI BrowserService_QueryInterface(IBrowserService *iface, REFIID riid, void **ppv) +{ + return browserservice_qi(riid, ppv); +} + +static ULONG WINAPI BrowserService_AddRef(IBrowserService* This) +{ + return 2; +} + +static ULONG WINAPI BrowserService_Release(IBrowserService* This) +{ + return 1; +} + +static HRESULT WINAPI BrowserService_GetParentSite(IBrowserService* This, IOleInPlaceSite **ppipsite) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_SetTitle(IBrowserService* This, IShellView *psv, LPCWSTR pszName) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_GetTitle(IBrowserService* This, IShellView *psv, LPWSTR pszName, DWORD cchName) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_GetOleObject(IBrowserService* This, IOleObject **ppobjv) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_GetTravelLog(IBrowserService* This, ITravelLog **pptl) +{ + *pptl = &TravelLog; + return S_OK; +} + +static HRESULT WINAPI BrowserService_ShowControlWindow(IBrowserService* This, UINT id, BOOL fShow) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_IsControlWindowShown(IBrowserService* This, UINT id, BOOL *pfShown) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_IEGetDisplayName(IBrowserService* This, PCIDLIST_ABSOLUTE pidl, LPWSTR pwszName, UINT uFlags) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_IEParseDisplayName(IBrowserService* This, UINT uiCP, LPCWSTR pwszPath, PIDLIST_ABSOLUTE *ppidlOut) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_DisplayParseError(IBrowserService* This, HRESULT hres, LPCWSTR pwszPath) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_NavigateToPidl(IBrowserService* This, PCIDLIST_ABSOLUTE pidl, DWORD grfHLNF) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_SetNavigateState(IBrowserService* This, BNSTATE bnstate) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_GetNavigateState(IBrowserService* This, BNSTATE *pbnstate) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_NotifyRedirect(IBrowserService* This, IShellView *psv, PCIDLIST_ABSOLUTE pidl, BOOL *pfDidBrowse) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_UpdateWindowList(IBrowserService* This) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_UpdateBackForwardState(IBrowserService* This) +{ + return S_OK; +} + +static HRESULT WINAPI BrowserService_SetFlags(IBrowserService* This, DWORD dwFlags, DWORD dwFlagMask) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_GetFlags(IBrowserService* This, DWORD *pdwFlags) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_CanNavigateNow(IBrowserService* This) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_GetPidl(IBrowserService* This, PIDLIST_ABSOLUTE *ppidl) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_SetReferrer(IBrowserService* This, PCIDLIST_ABSOLUTE pidl) +{ + return E_NOTIMPL; +} + +static DWORD WINAPI BrowserService_GetBrowserIndex(IBrowserService* This) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_GetBrowserByIndex(IBrowserService* This, DWORD dwID, IUnknown **ppunk) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_GetHistoryObject(IBrowserService* This, IOleObject **ppole, IStream **pstm, IBindCtx **ppbc) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_SetHistoryObject(IBrowserService* This, IOleObject *pole, BOOL fIsLocalAnchor) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_CacheOLEServer(IBrowserService* This, IOleObject *pole) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_GetSetCodePage(IBrowserService* This, VARIANT *pvarIn, VARIANT *pvarOut) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_OnHttpEquiv(IBrowserService* This, IShellView *psv, BOOL fDone, VARIANT *pvarargIn, VARIANT *pvarargOut) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_GetPalette(IBrowserService* This, HPALETTE *hpal) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI BrowserService_RegisterWindow(IBrowserService* This, BOOL fForceRegister, int swc) +{ + return E_NOTIMPL; +} + +static IBrowserServiceVtbl BrowserServiceVtbl = { + BrowserService_QueryInterface, + BrowserService_AddRef, + BrowserService_Release, + BrowserService_GetParentSite, + BrowserService_SetTitle, + BrowserService_GetTitle, + BrowserService_GetOleObject, + BrowserService_GetTravelLog, + BrowserService_ShowControlWindow, + BrowserService_IsControlWindowShown, + BrowserService_IEGetDisplayName, + BrowserService_IEParseDisplayName, + BrowserService_DisplayParseError, + BrowserService_NavigateToPidl, + BrowserService_SetNavigateState, + BrowserService_GetNavigateState, + BrowserService_NotifyRedirect, + BrowserService_UpdateWindowList, + BrowserService_UpdateBackForwardState, + BrowserService_SetFlags, + BrowserService_GetFlags, + BrowserService_CanNavigateNow, + BrowserService_GetPidl, + BrowserService_SetReferrer, + BrowserService_GetBrowserIndex, + BrowserService_GetBrowserByIndex, + BrowserService_GetHistoryObject, + BrowserService_SetHistoryObject, + BrowserService_CacheOLEServer, + BrowserService_GetSetCodePage, + BrowserService_OnHttpEquiv, + BrowserService_GetPalette, + BrowserService_RegisterWindow +}; + +static IBrowserService BrowserService = { &BrowserServiceVtbl }; + +static HRESULT WINAPI ShellBrowser_QueryInterface(IShellBrowser *iface, REFIID riid, void **ppv) +{ + return browserservice_qi(riid, ppv); +} + +static ULONG WINAPI ShellBrowser_AddRef(IShellBrowser *iface) +{ + return 2; +} + +static ULONG WINAPI ShellBrowser_Release(IShellBrowser *iface) +{ + return 1; +} + +static HRESULT WINAPI ShellBrowser_GetWindow(IShellBrowser *iface, HWND *phwnd) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ShellBrowser_ContextSensitiveHelp(IShellBrowser *iface, BOOL fEnterMode) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ShellBrowser_InsertMenusSB(IShellBrowser *iface, HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ShellBrowser_SetMenuSB(IShellBrowser *iface, HMENU hmenuShared, HOLEMENU holemenuReserved, HWND hwndActiveObject) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ShellBrowser_RemoveMenusSB(IShellBrowser *iface, HMENU hmenuShared) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ShellBrowser_SetStatusTextSB(IShellBrowser *iface, LPCOLESTR pszStatusText) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ShellBrowser_EnableModelessSB(IShellBrowser *iface, BOOL fEnable) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ShellBrowser_TranslateAcceleratorSB(IShellBrowser *iface, MSG *pmsg, WORD wID) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ShellBrowser_BrowseObject(IShellBrowser *iface, LPCITEMIDLIST pidl, UINT wFlags) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ShellBrowser_GetViewStateStream(IShellBrowser *iface, DWORD grfMode, IStream **ppStrm) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ShellBrowser_GetControlWindow(IShellBrowser *iface, UINT id, HWND *phwnd) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ShellBrowser_SendControlMsg(IShellBrowser *iface, UINT id, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *pret) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ShellBrowser_QueryActiveShellView(IShellBrowser *iface, IShellView **ppshv) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ShellBrowser_OnViewWindowActive(IShellBrowser* iface, IShellView *pshv) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI ShellBrowser_SetToolbarItems(IShellBrowser *iface, LPTBBUTTONSB lpButtons, UINT nButtons, UINT uFlags) +{ + return E_NOTIMPL; +} + +static const IShellBrowserVtbl ShellBrowserVtbl = { + ShellBrowser_QueryInterface, + ShellBrowser_AddRef, + ShellBrowser_Release, + ShellBrowser_GetWindow, + ShellBrowser_ContextSensitiveHelp, + ShellBrowser_InsertMenusSB, + ShellBrowser_SetMenuSB, + ShellBrowser_RemoveMenusSB, + ShellBrowser_SetStatusTextSB, + ShellBrowser_EnableModelessSB, + ShellBrowser_TranslateAcceleratorSB, + ShellBrowser_BrowseObject, + ShellBrowser_GetViewStateStream, + ShellBrowser_GetControlWindow, + ShellBrowser_SendControlMsg, + ShellBrowser_QueryActiveShellView, + ShellBrowser_OnViewWindowActive, + ShellBrowser_SetToolbarItems +}; + +static IShellBrowser ShellBrowser = { &ShellBrowserVtbl }; + +static HRESULT browserservice_qi(REFIID riid, void **ppv) +{ + if(IsEqualGUID(&IID_IShellBrowser, riid)) + *ppv = &ShellBrowser; + else if(IsEqualGUID(&IID_IBrowserService, riid)) + *ppv = &BrowserService; + else { + *ppv = NULL; + return E_NOINTERFACE; + } + return S_OK; +} + +static HRESULT WINAPI WebBrowser_QueryInterface(IWebBrowser2 *iface, REFIID riid, void **ppv) +{ + return wb_qi(riid, ppv); +} + +static ULONG WINAPI WebBrowser_AddRef(IWebBrowser2 *iface) +{ + return 2; +} + +static ULONG WINAPI WebBrowser_Release(IWebBrowser2 *iface) +{ + return 1; +} + +static HRESULT WINAPI WebBrowser_GetTypeInfoCount(IWebBrowser2 *iface, UINT *pctinfo) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_GetTypeInfo(IWebBrowser2 *iface, UINT iTInfo, LCID lcid, LPTYPEINFO *ppTInfo) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_GetIDsOfNames(IWebBrowser2 *iface, REFIID riid, LPOLESTR *rgszNames, UINT cNames, + LCID lcid, DISPID *rgDispId) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_Invoke(IWebBrowser2 *iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, + DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo, UINT *puArgErr) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_GoBack(IWebBrowser2 *iface) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_GoForward(IWebBrowser2 *iface) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_GoHome(IWebBrowser2 *iface) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_GoSearch(IWebBrowser2 *iface) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_Navigate(IWebBrowser2 *iface, BSTR szUrl, VARIANT *Flags, VARIANT *TargetFrameName, + VARIANT *PostData, VARIANT *Headers) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_Refresh(IWebBrowser2 *iface) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_Refresh2(IWebBrowser2 *iface, VARIANT *Level) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_Stop(IWebBrowser2 *iface) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_Application(IWebBrowser2 *iface, IDispatch **ppDisp) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_Parent(IWebBrowser2 *iface, IDispatch **ppDisp) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_Container(IWebBrowser2 *iface, IDispatch **ppDisp) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_Document(IWebBrowser2 *iface, IDispatch **ppDisp) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_TopLevelContainer(IWebBrowser2 *iface, VARIANT_BOOL *pBool) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_Type(IWebBrowser2 *iface, BSTR *Type) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_Left(IWebBrowser2 *iface, LONG *pl) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_Left(IWebBrowser2 *iface, LONG Left) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_Top(IWebBrowser2 *iface, LONG *pl) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_Top(IWebBrowser2 *iface, LONG Top) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_Width(IWebBrowser2 *iface, LONG *pl) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_Width(IWebBrowser2 *iface, LONG Width) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_Height(IWebBrowser2 *iface, LONG *pl) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_Height(IWebBrowser2 *iface, LONG Height) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_LocationName(IWebBrowser2 *iface, BSTR *LocationName) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_LocationURL(IWebBrowser2 *iface, BSTR *LocationURL) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_Busy(IWebBrowser2 *iface, VARIANT_BOOL *pBool) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_Quit(IWebBrowser2 *iface) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_ClientToWindow(IWebBrowser2 *iface, int *pcx, int *pcy) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_PutProperty(IWebBrowser2 *iface, BSTR szProperty, VARIANT vtValue) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_GetProperty(IWebBrowser2 *iface, BSTR szProperty, VARIANT *pvtValue) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_Name(IWebBrowser2 *iface, BSTR *Name) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_HWND(IWebBrowser2 *iface, SHANDLE_PTR *pHWND) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_FullName(IWebBrowser2 *iface, BSTR *FullName) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_Path(IWebBrowser2 *iface, BSTR *Path) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_Visible(IWebBrowser2 *iface, VARIANT_BOOL *pBool) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_Visible(IWebBrowser2 *iface, VARIANT_BOOL Value) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_StatusBar(IWebBrowser2 *iface, VARIANT_BOOL *pBool) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_StatusBar(IWebBrowser2 *iface, VARIANT_BOOL Value) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_StatusText(IWebBrowser2 *iface, BSTR *StatusText) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_StatusText(IWebBrowser2 *iface, BSTR StatusText) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_ToolBar(IWebBrowser2 *iface, int *Value) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_ToolBar(IWebBrowser2 *iface, int Value) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_MenuBar(IWebBrowser2 *iface, VARIANT_BOOL *Value) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_MenuBar(IWebBrowser2 *iface, VARIANT_BOOL Value) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_FullScreen(IWebBrowser2 *iface, VARIANT_BOOL *pbFullScreen) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_FullScreen(IWebBrowser2 *iface, VARIANT_BOOL bFullScreen) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_Navigate2(IWebBrowser2 *iface, VARIANT *URL, VARIANT *Flags, + VARIANT *TargetFrameName, VARIANT *PostData, VARIANT *Headers) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_QueryStatusWB(IWebBrowser2 *iface, OLECMDID cmdID, OLECMDF *pcmdf) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_ExecWB(IWebBrowser2 *iface, OLECMDID cmdID, + OLECMDEXECOPT cmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_ShowBrowserBar(IWebBrowser2 *iface, VARIANT *pvaClsid, + VARIANT *pvarShow, VARIANT *pvarSize) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_ReadyState(IWebBrowser2 *iface, READYSTATE *lpReadyState) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_Offline(IWebBrowser2 *iface, VARIANT_BOOL *pbOffline) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_Offline(IWebBrowser2 *iface, VARIANT_BOOL bOffline) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_Silent(IWebBrowser2 *iface, VARIANT_BOOL *pbSilent) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_Silent(IWebBrowser2 *iface, VARIANT_BOOL bSilent) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_RegisterAsBrowser(IWebBrowser2 *iface, + VARIANT_BOOL *pbRegister) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_RegisterAsBrowser(IWebBrowser2 *iface, + VARIANT_BOOL bRegister) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_RegisterAsDropTarget(IWebBrowser2 *iface, + VARIANT_BOOL *pbRegister) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_RegisterAsDropTarget(IWebBrowser2 *iface, + VARIANT_BOOL bRegister) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_TheaterMode(IWebBrowser2 *iface, VARIANT_BOOL *pbRegister) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_TheaterMode(IWebBrowser2 *iface, VARIANT_BOOL bRegister) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_AddressBar(IWebBrowser2 *iface, VARIANT_BOOL *Value) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_AddressBar(IWebBrowser2 *iface, VARIANT_BOOL Value) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_get_Resizable(IWebBrowser2 *iface, VARIANT_BOOL *Value) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI WebBrowser_put_Resizable(IWebBrowser2 *iface, VARIANT_BOOL Value) +{ + return E_NOTIMPL; +} + +static const IWebBrowser2Vtbl WebBrowser2Vtbl = +{ + WebBrowser_QueryInterface, + WebBrowser_AddRef, + WebBrowser_Release, + WebBrowser_GetTypeInfoCount, + WebBrowser_GetTypeInfo, + WebBrowser_GetIDsOfNames, + WebBrowser_Invoke, + WebBrowser_GoBack, + WebBrowser_GoForward, + WebBrowser_GoHome, + WebBrowser_GoSearch, + WebBrowser_Navigate, + WebBrowser_Refresh, + WebBrowser_Refresh2, + WebBrowser_Stop, + WebBrowser_get_Application, + WebBrowser_get_Parent, + WebBrowser_get_Container, + WebBrowser_get_Document, + WebBrowser_get_TopLevelContainer, + WebBrowser_get_Type, + WebBrowser_get_Left, + WebBrowser_put_Left, + WebBrowser_get_Top, + WebBrowser_put_Top, + WebBrowser_get_Width, + WebBrowser_put_Width, + WebBrowser_get_Height, + WebBrowser_put_Height, + WebBrowser_get_LocationName, + WebBrowser_get_LocationURL, + WebBrowser_get_Busy, + WebBrowser_Quit, + WebBrowser_ClientToWindow, + WebBrowser_PutProperty, + WebBrowser_GetProperty, + WebBrowser_get_Name, + WebBrowser_get_HWND, + WebBrowser_get_FullName, + WebBrowser_get_Path, + WebBrowser_get_Visible, + WebBrowser_put_Visible, + WebBrowser_get_StatusBar, + WebBrowser_put_StatusBar, + WebBrowser_get_StatusText, + WebBrowser_put_StatusText, + WebBrowser_get_ToolBar, + WebBrowser_put_ToolBar, + WebBrowser_get_MenuBar, + WebBrowser_put_MenuBar, + WebBrowser_get_FullScreen, + WebBrowser_put_FullScreen, + WebBrowser_Navigate2, + WebBrowser_QueryStatusWB, + WebBrowser_ExecWB, + WebBrowser_ShowBrowserBar, + WebBrowser_get_ReadyState, + WebBrowser_get_Offline, + WebBrowser_put_Offline, + WebBrowser_get_Silent, + WebBrowser_put_Silent, + WebBrowser_get_RegisterAsBrowser, + WebBrowser_put_RegisterAsBrowser, + WebBrowser_get_RegisterAsDropTarget, + WebBrowser_put_RegisterAsDropTarget, + WebBrowser_get_TheaterMode, + WebBrowser_put_TheaterMode, + WebBrowser_get_AddressBar, + WebBrowser_put_AddressBar, + WebBrowser_get_Resizable, + WebBrowser_put_Resizable +}; + +static IWebBrowser2 WebBrowser2 = { &WebBrowser2Vtbl }; + +static HRESULT WINAPI WebBrowserPriv_QueryInterface(IWebBrowserPriv *iface, REFIID riid, void **ppv) +{ + return wb_qi(riid, ppv); +} + +static ULONG WINAPI WebBrowserPriv_AddRef(IWebBrowserPriv *iface) +{ + return 2; +} + +static ULONG WINAPI WebBrowserPriv_Release(IWebBrowserPriv *iface) +{ + return 1; +} + +static HRESULT WINAPI WebBrowserPriv_NavigateWithBindCtx(IWebBrowserPriv *iface, VARIANT *uri, VARIANT *flags, + VARIANT *target_frame, VARIANT *post_data, VARIANT *headers, IBindCtx *bind_ctx, LPOLESTR url_fragment) +{ + return S_OK; +} + +static HRESULT WINAPI WebBrowserPriv_OnClose(IWebBrowserPriv *iface) +{ + return E_NOTIMPL; +} + +static const IWebBrowserPrivVtbl WebBrowserPrivVtbl = { + WebBrowserPriv_QueryInterface, + WebBrowserPriv_AddRef, + WebBrowserPriv_Release, + WebBrowserPriv_NavigateWithBindCtx, + WebBrowserPriv_OnClose +}; + +static IWebBrowserPriv WebBrowserPriv = { &WebBrowserPrivVtbl }; + +static HRESULT wb_qi(REFIID riid, void **ppv) +{ + if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IWebBrowser, riid) || + IsEqualGUID(&IID_IWebBrowserApp, riid) || IsEqualGUID(&IID_IWebBrowser2, riid)) + *ppv = &WebBrowser2; + else if(IsEqualGUID(riid, &IID_IWebBrowserPriv)) + *ppv = &WebBrowserPriv; + else { + *ppv = NULL; + return E_NOINTERFACE; + } + return S_OK; +} + +static HRESULT WINAPI ServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv) +{ + return QueryInterface(riid, ppv); +} + +static ULONG WINAPI ServiceProvider_AddRef(IServiceProvider *iface) +{ + return 2; +} + +static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface) +{ + return 1; +} + +static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface, REFGUID guidService, REFIID riid, void **ppv) +{ + if(IsEqualGUID(&IID_IShellBrowser, guidService)) { + ok(IsEqualGUID(&IID_IBrowserService, riid), "unexpected riid\n"); + *ppv = &BrowserService; + return S_OK; + } + + if(IsEqualGUID(&IID_IWebBrowserApp, guidService)) { + ok(IsEqualGUID(&IID_IWebBrowser2, riid), "unexpected riid\n"); + *ppv = &WebBrowser2; + return S_OK; + } + + return E_NOINTERFACE; +} + +static const IServiceProviderVtbl ServiceProviderVtbl = { + ServiceProvider_QueryInterface, + ServiceProvider_AddRef, + ServiceProvider_Release, + ServiceProvider_QueryService +}; + +static IServiceProvider ServiceProvider = { &ServiceProviderVtbl }; + static HRESULT QueryInterface(REFIID riid, void **ppv) { *ppv = NULL; @@ -3359,6 +4321,8 @@ static HRESULT QueryInterface(REFIID riid, void **ppv) *ppv = &DocumentSite; else if(IsEqualGUID(&IID_IOleWindow, riid) || IsEqualGUID(&IID_IOleInPlaceSite, riid)) *ppv = &InPlaceSite; + else if(IsEqualGUID(&IID_IServiceProvider, riid)) + *ppv = &ServiceProvider;
return *ppv ? S_OK : E_NOINTERFACE; }
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/mshtml_private.h | 1 + dlls/mshtml/oleobj.c | 55 ++++++ dlls/mshtml/tests/doc_with_prop.html | 3 + dlls/mshtml/tests/doc_with_prop_ie9.html | 4 + dlls/mshtml/tests/events.c | 223 +++++++++++++++++++++-- dlls/mshtml/tests/rsrc.rc | 6 + 6 files changed, 275 insertions(+), 17 deletions(-) create mode 100644 dlls/mshtml/tests/doc_with_prop.html create mode 100644 dlls/mshtml/tests/doc_with_prop_ie9.html
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 7df5c5e8b30..e7f5481b886 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -677,6 +677,7 @@ struct HTMLDocumentObj { IObjectSafety IObjectSafety_iface; IServiceProvider IServiceProvider_iface; ITargetContainer ITargetContainer_iface; + IEventTarget IEventTarget_iface;
IWindowForBindingUI IWindowForBindingUI_iface;
diff --git a/dlls/mshtml/oleobj.c b/dlls/mshtml/oleobj.c index de6fd028218..e13335e6586 100644 --- a/dlls/mshtml/oleobj.c +++ b/dlls/mshtml/oleobj.c @@ -3238,6 +3238,52 @@ static const IDocumentRangeVtbl DocObjDocumentRangeVtbl = { DocObjDocumentRange_createRange };
+/********************************************************** + * IEventTarget implementation + */ +static inline HTMLDocumentObj *impl_from_IEventTarget(IEventTarget *iface) +{ + return CONTAINING_RECORD(iface, HTMLDocumentObj, IEventTarget_iface); +} + +HTMLDOCUMENTOBJ_IDISPATCH_METHODS(EventTarget) + +static HRESULT WINAPI DocObjEventTarget_addEventListener(IEventTarget *iface, BSTR type, IDispatch *listener, + VARIANT_BOOL capture) +{ + HTMLDocumentObj *This = impl_from_IEventTarget(iface); + + return IEventTarget_addEventListener(&This->doc_node->node.event_target.IEventTarget_iface, type, listener, capture); +} + +static HRESULT WINAPI DocObjEventTarget_removeEventListener(IEventTarget *iface, BSTR type, IDispatch *listener, + VARIANT_BOOL capture) +{ + HTMLDocumentObj *This = impl_from_IEventTarget(iface); + + return IEventTarget_removeEventListener(&This->doc_node->node.event_target.IEventTarget_iface, type, listener, capture); +} + +static HRESULT WINAPI DocObjEventTarget_dispatchEvent(IEventTarget *iface, IDOMEvent *event_iface, VARIANT_BOOL *result) +{ + HTMLDocumentObj *This = impl_from_IEventTarget(iface); + + return IEventTarget_dispatchEvent(&This->doc_node->node.event_target.IEventTarget_iface, event_iface, result); +} + +static const IEventTargetVtbl DocObjEventTargetVtbl = { + DocObjEventTarget_QueryInterface, + DocObjEventTarget_AddRef, + DocObjEventTarget_Release, + DocObjEventTarget_GetTypeInfoCount, + DocObjEventTarget_GetTypeInfo, + DocObjEventTarget_GetIDsOfNames, + DocObjEventTarget_Invoke, + DocObjEventTarget_addEventListener, + DocObjEventTarget_removeEventListener, + DocObjEventTarget_dispatchEvent +}; + static inline HTMLDocumentObj *impl_from_IUnknown(IUnknown *iface) { return CONTAINING_RECORD(iface, HTMLDocumentObj, IUnknown_inner); @@ -3339,6 +3385,14 @@ static HRESULT WINAPI HTMLDocumentObj_QueryInterface(IUnknown *iface, REFIID rii *ppv = &This->ITargetContainer_iface; }else if(IsEqualGUID(&IID_IConnectionPointContainer, riid)) { *ppv = &This->cp_container.IConnectionPointContainer_iface; + }else if(IsEqualGUID(&IID_IEventTarget, riid)) { + /* IEventTarget is conditionally exposed. This breaks COM rules when + it changes its compat mode, but it is how native works (see tests). */ + if(!This->doc_node || dispex_compat_mode(&This->doc_node->node.event_target.dispex) < COMPAT_MODE_IE9) { + *ppv = NULL; + return E_NOINTERFACE; + } + *ppv = &This->IEventTarget_iface; }else if(IsEqualGUID(&CLSID_CMarkup, riid)) { FIXME("(%p)->(CLSID_CMarkup %p)\n", This, ppv); *ppv = NULL; @@ -3734,6 +3788,7 @@ static HRESULT create_document_object(BOOL is_mhtml, IUnknown *outer, REFIID rii doc->IMarkupContainer_iface.lpVtbl = &DocObjMarkupContainerVtbl; doc->IDisplayServices_iface.lpVtbl = &DocObjDisplayServicesVtbl; doc->IDocumentRange_iface.lpVtbl = &DocObjDocumentRangeVtbl; + doc->IEventTarget_iface.lpVtbl = &DocObjEventTargetVtbl;
doc->outer_unk = outer ? outer : &doc->IUnknown_inner;
diff --git a/dlls/mshtml/tests/doc_with_prop.html b/dlls/mshtml/tests/doc_with_prop.html new file mode 100644 index 00000000000..4a81661bbdf --- /dev/null +++ b/dlls/mshtml/tests/doc_with_prop.html @@ -0,0 +1,3 @@ +<html> +<script type="text/javascript">document.prop = 137;</script> +</html> diff --git a/dlls/mshtml/tests/doc_with_prop_ie9.html b/dlls/mshtml/tests/doc_with_prop_ie9.html new file mode 100644 index 00000000000..ba1f5305fe1 --- /dev/null +++ b/dlls/mshtml/tests/doc_with_prop_ie9.html @@ -0,0 +1,4 @@ +<html><head> +<meta http-equiv="x-ua-compatible" content="IE=9" /> +<script type="text/javascript">document.prop = 137;</script> +</head></html> diff --git a/dlls/mshtml/tests/events.c b/dlls/mshtml/tests/events.c index 209552d17d6..511bc73315b 100644 --- a/dlls/mshtml/tests/events.c +++ b/dlls/mshtml/tests/events.c @@ -31,6 +31,7 @@ #include "mshtmhst.h" #include "docobj.h" #include "hlink.h" +#include "wininet.h" #include "shdeprecated.h" #include "dispex.h"
@@ -62,6 +63,7 @@ #define CLEAR_CALLED(func) \ expect_ ## func = called_ ## func = FALSE
+DEFINE_EXPECT(docobj_onclick); DEFINE_EXPECT(document_onclick); DEFINE_EXPECT(body_onclick); DEFINE_EXPECT(doc_onclick_attached); @@ -146,6 +148,8 @@ static const char input_doc_str[] = static const char iframe_doc_str[] = "<html><body><iframe id="ifr">Testing</iframe></body></html>";
+static void navigate(IHTMLDocument2*,const WCHAR*); + static BOOL iface_cmp(IUnknown *iface1, IUnknown *iface2) { IUnknown *unk1, *unk2; @@ -967,6 +971,16 @@ static HRESULT WINAPI DispatchEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown }; \ static IDispatchEx event ## _obj = { &event ## FuncVtbl };
+static HRESULT WINAPI docobj_onclick(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, + VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) +{ + CHECK_EXPECT(docobj_onclick); + test_event_args(document_mode < 9 ? &DIID_DispHTMLDocument : NULL, id, wFlags, pdp, pvarRes, pei, pspCaller); + return S_OK; +} + +EVENT_HANDLER_FUNC_OBJ(docobj_onclick); + static HRESULT WINAPI document_onclick(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) { @@ -2731,6 +2745,71 @@ static void test_iframe_connections(IHTMLDocument2 *doc) IHTMLDocument2_Release(iframes_doc); }
+static void test_doc_obj(IHTMLDocument2 *doc) +{ + int orig_doc_mode = document_mode; + IEventTarget *event_target; + IHTMLElement *body; + HRESULT hres; + BSTR bstr; + + event_target = (void*)0xdeadbeef; + hres = IHTMLDocument2_QueryInterface(doc, &IID_IEventTarget, (void**)&event_target); + if(document_mode < 9) { + ok(hres == E_NOINTERFACE, "hres = %08lx, expected E_NOINTERFACE\n", hres); + ok(!event_target, "event_target != NULL\n"); + }else { + IHTMLDocument2 *tmp; + + ok(hres == S_OK, "hres = %08lx, expected S_OK\n", hres); + ok(!!event_target, "event_target = NULL\n"); + + bstr = SysAllocString(L"click"); + IEventTarget_addEventListener(event_target, bstr, (IDispatch*)&docobj_onclick_obj, TRUE); + ok(hres == S_OK, "addEventListener failed: %08lx\n", hres); + SysFreeString(bstr); + + hres = IEventTarget_QueryInterface(event_target, &IID_IHTMLDocument2, (void**)&tmp); + ok(hres == S_OK, "Could not get IHTMLDocument2: %08lx\n", hres); + IEventTarget_Release(event_target); + + ok(doc == tmp, "IHTMLDocument2 from IEventTarget not same as original\n"); + IHTMLDocument2_Release(tmp); + + body = doc_get_body(doc); + SET_EXPECT(docobj_onclick); + hres = IHTMLElement_click(body); + ok(hres == S_OK, "click failed: %08lx\n", hres); + IHTMLElement_Release(body); + + pump_msgs(&called_docobj_onclick); + CHECK_CALLED(docobj_onclick); + } + + /* Navigate to a different document mode page, checking using the same doc obj. + Test that it breaks COM rules, since IEventTarget is conditionally exposed. + All the events registered on the old doc node are also removed. */ + navigate(doc, document_mode < 9 ? L"doc_with_prop_ie9.html" : L"doc_with_prop.html"); + ok(document_mode == (orig_doc_mode < 9 ? 9 : 5), "new document_mode = %d\n", document_mode); + + event_target = (void*)0xdeadbeef; + hres = IHTMLDocument2_QueryInterface(doc, &IID_IEventTarget, (void**)&event_target); + if(document_mode < 9) { + ok(hres == E_NOINTERFACE, "hres = %08lx, expected E_NOINTERFACE\n", hres); + ok(!event_target, "event_target != NULL\n"); + + body = doc_get_body(doc); + hres = IHTMLElement_click(body); + ok(hres == S_OK, "click failed: %08lx\n", hres); + IHTMLElement_Release(body); + pump_msgs(NULL); + }else { + ok(hres == S_OK, "hres = %08lx, expected S_OK\n", hres); + ok(!!event_target, "event_target = NULL\n"); + IEventTarget_Release(event_target); + } +} + static void test_create_event(IHTMLDocument2 *doc) { IDOMKeyboardEvent *keyboard_event; @@ -3325,9 +3404,11 @@ static HRESULT WINAPI DocumentSite_ActivateMe(IOleDocumentSite *iface, IOleDocum hres = IOleDocumentView_QueryInterface(pViewToActivate, &IID_IOleDocument, (void**)&document); ok(hres == S_OK, "could not get IOleDocument: %08lx\n", hres);
- hres = IOleDocument_CreateView(document, &InPlaceSite, NULL, 0, &view); + if(!view) { + hres = IOleDocument_CreateView(document, &InPlaceSite, NULL, 0, &view); + ok(hres == S_OK, "CreateView failed: %08lx\n", hres); + } IOleDocument_Release(document); - ok(hres == S_OK, "CreateView failed: %08lx\n", hres);
hres = IOleDocumentView_SetInPlaceSite(view, &InPlaceSite); ok(hres == S_OK, "SetInPlaceSite failed: %08lx\n", hres); @@ -4689,24 +4770,12 @@ static IClassFactory protocol_cf = { &ProtocolCFVtbl };
static void doc_load_string(IHTMLDocument2 *doc, const char *str) { - IInternetSession *internet_session; IPersistStreamInit *init; IStream *stream; HRESULT hres; HGLOBAL mem; SIZE_T len;
- if(protocol_doc_str) { - hres = CoInternetGetSession(0, &internet_session, 0); - ok(hres == S_OK, "CoInternetGetSession failed: %08lx\n", hres); - - hres = IInternetSession_UnregisterNameSpace(internet_session, &protocol_cf, L"http"); - ok(hres == S_OK, "RegisterNameSpace failed: %08lx\n", hres); - - IInternetSession_Release(internet_session); - protocol_doc_str = NULL; - } - notif_doc = doc;
doc_complete = FALSE; @@ -4724,6 +4793,51 @@ static void doc_load_string(IHTMLDocument2 *doc, const char *str) IStream_Release(stream); }
+static void doc_load_res(IHTMLDocument2 *doc, const WCHAR *file) +{ + static const WCHAR res[] = { 'r','e','s',':','/','/' }; + WCHAR url[INTERNET_MAX_URL_LENGTH]; + IPersistMoniker *persist; + IHlinkTarget *hlink; + IBindCtx *bind; + IMoniker *mon; + HRESULT hres; + DWORD len; + BSTR bstr; + + wcscpy(url, SZ_HTML_CLIENTSITE_OBJECTPARAM); + CreateBindCtx(0, &bind); + IBindCtx_RegisterObjectParam(bind, url, (IUnknown*)&ClientSite); + + notif_doc = doc; + doc_complete = FALSE; + + memcpy(url, res, sizeof(res)); + len = 6 + GetModuleFileNameW(NULL, url + ARRAY_SIZE(res), ARRAY_SIZE(url) - ARRAY_SIZE(res) - 1); + url[len++] = '/'; + lstrcpynW(url + len, file, ARRAY_SIZE(url) - len); + + bstr = SysAllocString(url); + hres = CreateURLMoniker(NULL, bstr, &mon); + SysFreeString(bstr); + ok(hres == S_OK, "CreateUrlMoniker failed: %08lx\n", hres); + + hres = IHTMLDocument2_QueryInterface(doc, &IID_IPersistMoniker, (void**)&persist); + ok(hres == S_OK, "Could not get IPersistMoniker iface: %08lx\n", hres); + + hres = IPersistMoniker_Load(persist, FALSE, mon, bind, 0x12); + ok(hres == S_OK, "Load failed: %08lx\n", hres); + IPersistMoniker_Release(persist); + IBindCtx_Release(bind); + IMoniker_Release(mon); + + hres = IHTMLDocument2_QueryInterface(doc, &IID_IHlinkTarget, (void**)&hlink); + ok(hres == S_OK, "Could not get IHlinkTarget iface: %08lx\n", hres); + hres = IHlinkTarget_Navigate(hlink, 0, NULL); + ok(hres == S_OK, "Navigate failed: %08lx\n", hres); + IHlinkTarget_Release(hlink); +} + static void do_advise(IUnknown *unk, REFIID riid, IUnknown *unk_advise) { IConnectionPointContainer *container; @@ -4776,6 +4890,51 @@ static void set_client_site(IHTMLDocument2 *doc, BOOL set)
IOleObject_Release(oleobj); } + +static void navigate(IHTMLDocument2 *doc, const WCHAR *url) +{ + IHTMLLocation *location; + IHTMLDocument6 *doc6; + HRESULT hres; + VARIANT res; + BSTR bstr; + MSG msg; + + location = NULL; + hres = IHTMLDocument2_get_location(doc, &location); + ok(hres == S_OK, "get_location failed: %08lx\n", hres); + ok(location != NULL, "location == NULL\n"); + + doc_complete = FALSE; + bstr = SysAllocString(url); + hres = IHTMLLocation_replace(location, bstr); + ok(hres == S_OK, "replace failed: %08lx\n", hres); + IHTMLLocation_Release(location); + SysFreeString(bstr); + + while(!doc_complete && GetMessageW(&msg, NULL, 0, 0)) { + TranslateMessage(&msg); + DispatchMessageW(&msg); + } + + hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument6, (void**)&doc6); + if(SUCCEEDED(hres)) { + hres = IHTMLDocument6_get_documentMode(doc6, &res); + ok(hres == S_OK, "get_documentMode failed: %08lx\n", hres); + ok(V_VT(&res) == VT_R4, "V_VT(documentMode) = %u\n", V_VT(&res)); + document_mode = V_R4(&res); + IHTMLDocument6_Release(doc6); + }else { + document_mode = 0; + } + + if(window) + IHTMLWindow2_Release(window); + hres = IHTMLDocument2_get_parentWindow(doc, &window); + ok(hres == S_OK, "get_parentWindow failed: %08lx\n", hres); + ok(window != NULL, "window == NULL\n"); +} + static IHTMLDocument2 *create_document(void) { IHTMLDocument2 *doc; @@ -4844,8 +5003,9 @@ static IHTMLDocument2 *create_document_with_origin(const char *str)
typedef void (*testfunc_t)(IHTMLDocument2*);
-static void run_test(const char *str, testfunc_t test) +static void run_test_impl(const char *str, const WCHAR *res, testfunc_t test) { + IInternetSession *internet_session; IHTMLDocument2 *doc; IHTMLElement *body = NULL; MSG msg; @@ -4855,7 +5015,23 @@ static void run_test(const char *str, testfunc_t test) if (!doc) return; set_client_site(doc, TRUE); - doc_load_string(doc, str); + + if(protocol_doc_str) { + hres = CoInternetGetSession(0, &internet_session, 0); + ok(hres == S_OK, "CoInternetGetSession failed: %08lx\n", hres); + + hres = IInternetSession_UnregisterNameSpace(internet_session, &protocol_cf, L"http"); + ok(hres == S_OK, "RegisterNameSpace failed: %08lx\n", hres); + + IInternetSession_Release(internet_session); + protocol_doc_str = NULL; + } + + if(res) + doc_load_res(doc, res); + else + doc_load_string(doc, str); + do_advise((IUnknown*)doc, &IID_IPropertyNotifySink, (IUnknown*)&PropertyNotifySink);
while(!doc_complete && GetMessageA(&msg, NULL, 0, 0)) { @@ -4899,6 +5075,16 @@ static void run_test(const char *str, testfunc_t test) IHTMLDocument2_Release(doc); }
+static void run_test(const char *str, testfunc_t test) +{ + return run_test_impl(str, NULL, test); +} + +static void run_test_from_res(const WCHAR *res, testfunc_t test) +{ + return run_test_impl(NULL, res, test); +} + static LRESULT WINAPI wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { return DefWindowProcA(hwnd, msg, wParam, lParam); @@ -5216,8 +5402,11 @@ START_TEST(events) run_test(empty_doc_str, test_submit); run_test(empty_doc_ie9_str, test_submit); run_test(iframe_doc_str, test_iframe_connections); - if(is_ie9plus) + if(is_ie9plus) { + run_test_from_res(L"doc_with_prop.html", test_doc_obj); + run_test_from_res(L"doc_with_prop_ie9.html", test_doc_obj); run_test(empty_doc_ie9_str, test_create_event); + }
test_empty_document(); test_storage_events(empty_doc_str); diff --git a/dlls/mshtml/tests/rsrc.rc b/dlls/mshtml/tests/rsrc.rc index 25c81246b26..9bff32a78e9 100644 --- a/dlls/mshtml/tests/rsrc.rc +++ b/dlls/mshtml/tests/rsrc.rc @@ -73,6 +73,12 @@ blank2.html HTML "blank.html" /* @makedep: blank.html */ 123 HTML "blank.html"
+/* @makedep: doc_with_prop.html */ +doc_with_prop.html HTML "doc_with_prop.html" + +/* @makedep: doc_with_prop_ie9.html */ +doc_with_prop_ie9.html HTML "doc_with_prop_ie9.html" + /* For res: protocol test: */
/* @makedep: jstest.html */
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/oleobj.c | 11 +---------- dlls/mshtml/tests/events.c | 7 +++++++ 2 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/dlls/mshtml/oleobj.c b/dlls/mshtml/oleobj.c index e13335e6586..d46f684e62a 100644 --- a/dlls/mshtml/oleobj.c +++ b/dlls/mshtml/oleobj.c @@ -2384,16 +2384,7 @@ HTMLDOCUMENTOBJ_FWD_TO_NODE_1(HTMLDocument2, put_onbeforeupdate, VARIANT) HTMLDOCUMENTOBJ_FWD_TO_NODE_1(HTMLDocument2, get_onbeforeupdate, VARIANT*) HTMLDOCUMENTOBJ_FWD_TO_NODE_1(HTMLDocument2, put_onerrorupdate, VARIANT) HTMLDOCUMENTOBJ_FWD_TO_NODE_1(HTMLDocument2, get_onerrorupdate, VARIANT*) - -static HRESULT WINAPI DocObjHTMLDocument2_toString(IHTMLDocument2 *iface, BSTR *String) -{ - HTMLDocumentObj *This = impl_from_IHTMLDocument2(iface); - - TRACE("(%p)->(%p)\n", This, String); - - return dispex_to_string(&This->dispex, String); -} - +HTMLDOCUMENTOBJ_FWD_TO_NODE_1(HTMLDocument2, toString, BSTR*) HTMLDOCUMENTOBJ_FWD_TO_NODE_3(HTMLDocument2, createStyleSheet, BSTR,LONG,IHTMLStyleSheet**)
static const IHTMLDocument2Vtbl DocObjHTMLDocument2Vtbl = { diff --git a/dlls/mshtml/tests/events.c b/dlls/mshtml/tests/events.c index 511bc73315b..220312ea628 100644 --- a/dlls/mshtml/tests/events.c +++ b/dlls/mshtml/tests/events.c @@ -2786,6 +2786,13 @@ static void test_doc_obj(IHTMLDocument2 *doc) CHECK_CALLED(docobj_onclick); }
+ bstr = NULL; + hres = IHTMLDocument2_toString(doc, &bstr); + ok(hres == S_OK, "toString failed: %08lx\n", hres); + todo_wine_if(document_mode >= 9) + ok(!wcscmp(bstr, (document_mode < 9 ? L"[object]" : L"[object Document]")), "toString returned %s\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + /* Navigate to a different document mode page, checking using the same doc obj. Test that it breaks COM rules, since IEventTarget is conditionally exposed. All the events registered on the old doc node are also removed. */
From: Gabriel Ivăncescu gabrielopcode@gmail.com
And get rid of the dispex since it's useless now.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/mshtml_private.h | 1 - dlls/mshtml/oleobj.c | 161 ++++++----------------------------- dlls/mshtml/tests/dom.c | 27 ++++++ dlls/mshtml/tests/events.c | 86 ++++++++++++++++++- 4 files changed, 137 insertions(+), 138 deletions(-)
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index e7f5481b886..e3971258b13 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -640,7 +640,6 @@ struct ConnectionPoint { };
struct HTMLDocumentObj { - DispatchEx dispex; IUnknown IUnknown_inner; IDispatchEx IDispatchEx_iface; ICustomDoc ICustomDoc_iface; diff --git a/dlls/mshtml/oleobj.c b/dlls/mshtml/oleobj.c index d46f684e62a..a8bd5751b49 100644 --- a/dlls/mshtml/oleobj.c +++ b/dlls/mshtml/oleobj.c @@ -27,6 +27,7 @@ #include "ole2.h" #include "shlguid.h" #include "shdeprecated.h" +#include "mscoree.h" #include "mshtmdid.h" #include "idispids.h"
@@ -3404,8 +3405,12 @@ static HRESULT WINAPI HTMLDocumentObj_QueryInterface(IUnknown *iface, REFIID rii TRACE("(%p)->(IID_IStdMarshalInfo %p) returning NULL\n", This, ppv); *ppv = NULL; return E_NOINTERFACE; - }else if(dispex_query_interface(&This->dispex, riid, ppv)) { - return *ppv ? S_OK : E_NOINTERFACE; + }else if(IsEqualGUID(&IID_IDispatchJS, riid) || + IsEqualGUID(&IID_UndocumentedScriptIface, riid) || + IsEqualGUID(&IID_IMarshal, riid) || + IsEqualGUID(&IID_IManagedObject, riid)) { + *ppv = NULL; + return E_NOINTERFACE; }else { FIXME("Unimplemented interface %s\n", debugstr_mshtml_guid(riid)); *ppv = NULL; @@ -3466,7 +3471,6 @@ static ULONG WINAPI HTMLDocumentObj_Release(IUnknown *iface)
remove_target_tasks(This->task_magic); ConnectionPointContainer_Destroy(&This->cp_container); - release_dispex(&This->dispex);
if(This->nscontainer) detach_gecko_browser(This->nscontainer); @@ -3484,123 +3488,46 @@ static const IUnknownVtbl HTMLDocumentObjVtbl = {
/********************************************************** * IDispatchEx implementation + * + * Forwarding this breaks Dispatch rules by potentially retrieving + * a different DISPID for the same name, if the node was changed + * while using the same doc obj, but it is how native works. */ static inline HTMLDocumentObj *impl_from_IDispatchEx(IDispatchEx *iface) { return CONTAINING_RECORD(iface, HTMLDocumentObj, IDispatchEx_iface); }
-static HRESULT WINAPI DocObjDispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv) -{ - HTMLDocumentObj *This = impl_from_IDispatchEx(iface); - return IUnknown_QueryInterface(This->outer_unk, riid, ppv); -} - -static ULONG WINAPI DocObjDispatchEx_AddRef(IDispatchEx *iface) -{ - HTMLDocumentObj *This = impl_from_IDispatchEx(iface); - return IUnknown_AddRef(This->outer_unk); -} - -static ULONG WINAPI DocObjDispatchEx_Release(IDispatchEx *iface) -{ - HTMLDocumentObj *This = impl_from_IDispatchEx(iface); - return IUnknown_Release(This->outer_unk); -} - -static HRESULT WINAPI DocObjDispatchEx_GetTypeInfoCount(IDispatchEx *iface, UINT *pctinfo) -{ - HTMLDocumentObj *This = impl_from_IDispatchEx(iface); - return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo); -} - -static HRESULT WINAPI DocObjDispatchEx_GetTypeInfo(IDispatchEx *iface, UINT iTInfo, LCID lcid, - ITypeInfo **ppTInfo) -{ - HTMLDocumentObj *This = impl_from_IDispatchEx(iface); - return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo); -} - -static HRESULT WINAPI DocObjDispatchEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid, LPOLESTR *rgszNames, - UINT cNames, LCID lcid, DISPID *rgDispId) -{ - HTMLDocumentObj *This = impl_from_IDispatchEx(iface); - return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames, lcid, rgDispId); -} +HTMLDOCUMENTOBJ_IUNKNOWN_METHODS(DispatchEx) +HTMLDOCUMENTOBJ_FWD_TO_NODE_1(DispatchEx, GetTypeInfoCount, UINT*) +HTMLDOCUMENTOBJ_FWD_TO_NODE_3(DispatchEx, GetTypeInfo, UINT,LCID,ITypeInfo**) +HTMLDOCUMENTOBJ_FWD_TO_NODE_5(DispatchEx, GetIDsOfNames, REFIID,LPOLESTR*,UINT,LCID,DISPID*)
static HRESULT WINAPI DocObjDispatchEx_Invoke(IDispatchEx *iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) { HTMLDocumentObj *This = impl_from_IDispatchEx(iface); - return IDispatchEx_InvokeEx(&This->IDispatchEx_iface, dispIdMember, lcid, wFlags, pDispParams, + + return IDispatchEx_InvokeEx(&This->doc_node->IDispatchEx_iface, dispIdMember, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, NULL); }
-static HRESULT WINAPI DocObjDispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid) -{ - HTMLDocumentObj *This = impl_from_IDispatchEx(iface); - return IDispatchEx_GetDispID(&This->dispex.IDispatchEx_iface, bstrName, grfdex, pid); -} +HTMLDOCUMENTOBJ_FWD_TO_NODE_3(DispatchEx, GetDispID, BSTR,DWORD,DISPID*)
static HRESULT WINAPI DocObjDispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) { HTMLDocumentObj *This = impl_from_IDispatchEx(iface);
- if(This->window) { - switch(id) { - case DISPID_READYSTATE: - TRACE("DISPID_READYSTATE\n"); - - if(!(wFlags & DISPATCH_PROPERTYGET)) - return E_INVALIDARG; - - V_VT(pvarRes) = VT_I4; - V_I4(pvarRes) = This->window->readystate; - return S_OK; - default: - break; - } - } - - return IDispatchEx_InvokeEx(&This->dispex.IDispatchEx_iface, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller); -} - -static HRESULT WINAPI DocObjDispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex) -{ - HTMLDocumentObj *This = impl_from_IDispatchEx(iface); - return IDispatchEx_DeleteMemberByName(&This->dispex.IDispatchEx_iface, bstrName, grfdex); + return IDispatchEx_InvokeEx(&This->doc_node->IDispatchEx_iface, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller); }
-static HRESULT WINAPI DocObjDispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id) -{ - HTMLDocumentObj *This = impl_from_IDispatchEx(iface); - return IDispatchEx_DeleteMemberByDispID(&This->dispex.IDispatchEx_iface, id); -} - -static HRESULT WINAPI DocObjDispatchEx_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex) -{ - HTMLDocumentObj *This = impl_from_IDispatchEx(iface); - return IDispatchEx_GetMemberProperties(&This->dispex.IDispatchEx_iface, id, grfdexFetch, pgrfdex); -} - -static HRESULT WINAPI DocObjDispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName) -{ - HTMLDocumentObj *This = impl_from_IDispatchEx(iface); - return IDispatchEx_GetMemberName(&This->dispex.IDispatchEx_iface, id, pbstrName); -} - -static HRESULT WINAPI DocObjDispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid) -{ - HTMLDocumentObj *This = impl_from_IDispatchEx(iface); - return IDispatchEx_GetNextDispID(&This->dispex.IDispatchEx_iface, grfdex, id, pid); -} - -static HRESULT WINAPI DocObjDispatchEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk) -{ - HTMLDocumentObj *This = impl_from_IDispatchEx(iface); - return IDispatchEx_GetNameSpaceParent(&This->dispex.IDispatchEx_iface, ppunk); -} +HTMLDOCUMENTOBJ_FWD_TO_NODE_2(DispatchEx, DeleteMemberByName, BSTR,DWORD) +HTMLDOCUMENTOBJ_FWD_TO_NODE_1(DispatchEx, DeleteMemberByDispID, DISPID) +HTMLDOCUMENTOBJ_FWD_TO_NODE_3(DispatchEx, GetMemberProperties, DISPID,DWORD,DWORD*) +HTMLDOCUMENTOBJ_FWD_TO_NODE_2(DispatchEx, GetMemberName, DISPID,BSTR*) +HTMLDOCUMENTOBJ_FWD_TO_NODE_3(DispatchEx, GetNextDispID, DWORD,DISPID,DISPID*) +HTMLDOCUMENTOBJ_FWD_TO_NODE_1(DispatchEx, GetNameSpaceParent, IUnknown**)
static const IDispatchExVtbl DocObjDispatchExVtbl = { DocObjDispatchEx_QueryInterface, @@ -3706,43 +3633,6 @@ static const cpc_entry_t HTMLDocumentObj_cpc[] = { {NULL} };
-static HRESULT HTMLDocumentObj_location_hook(DispatchEx *dispex, WORD flags, DISPPARAMS *dp, VARIANT *res, - EXCEPINFO *ei, IServiceProvider *caller) -{ - HTMLDocumentObj *This = CONTAINING_RECORD(dispex, HTMLDocumentObj, dispex); - - if(!(flags & DISPATCH_PROPERTYPUT) || !This->window) - return S_FALSE; - - return IDispatchEx_InvokeEx(&This->window->base.IDispatchEx_iface, DISPID_IHTMLWINDOW2_LOCATION, - 0, flags, dp, res, ei, caller); -} - -static const tid_t HTMLDocumentObj_iface_tids[] = { - IHTMLDocument3_tid, - IHTMLDocument4_tid, - IHTMLDocument5_tid, - 0 -}; - -static void HTMLDocumentObj_init_dispex_info(dispex_data_t *info, compat_mode_t mode) -{ - static const dispex_hook_t document2_hooks[] = { - {DISPID_IHTMLDOCUMENT2_URL, NULL, L"URL"}, - {DISPID_IHTMLDOCUMENT2_LOCATION, HTMLDocumentObj_location_hook}, - {DISPID_UNKNOWN} - }; - dispex_info_add_interface(info, IHTMLDocument2_tid, document2_hooks); -} - -static dispex_static_data_t HTMLDocumentObj_dispex = { - L"HTMLDocumentObj", - NULL, - DispHTMLDocument_tid, - HTMLDocumentObj_iface_tids, - HTMLDocumentObj_init_dispex_info -}; - static HRESULT create_document_object(BOOL is_mhtml, IUnknown *outer, REFIID riid, void **ppv) { HTMLDocumentObj *doc; @@ -3783,7 +3673,6 @@ static HRESULT create_document_object(BOOL is_mhtml, IUnknown *outer, REFIID rii
doc->outer_unk = outer ? outer : &doc->IUnknown_inner;
- init_dispatch(&doc->dispex, (IUnknown*)&doc->ICustomDoc_iface, &HTMLDocumentObj_dispex, COMPAT_MODE_QUIRKS); ConnectionPointContainer_Init(&doc->cp_container, &doc->IUnknown_inner, HTMLDocumentObj_cpc); HTMLDocumentObj_Persist_Init(doc); HTMLDocumentObj_Service_Init(doc); diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index 70b047ccbe1..c31de136cd8 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -9477,10 +9477,37 @@ static void test_elems(IHTMLDocument2 *doc) elem = get_doc_elem_by_id(doc, L"objid"); ok(elem != NULL, "elem == NULL\n"); if(elem) { + IDispatchEx *dispex = get_dispex_iface((IUnknown*)doc); + DISPPARAMS dp = { 0 }; + DISPID dispid; + VARIANT var; + BSTR name; + test_object_vspace((IUnknown*)elem, 100); test_object_name(elem, L"objname"); + + name = SysAllocString(L"objname"); + hres = IDispatchEx_GetDispID(dispex, name, fdexNameCaseSensitive, &dispid); + ok(hres == S_OK, "GetDispID(objname) returned: %08lx\n", hres); + SysFreeString(name); + + hres = IDispatchEx_Invoke(dispex, dispid, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dp, &var, NULL, NULL); + ok(hres == S_OK, "Invoke(objname) failed: %08lx\n", hres); + ok(V_VT(&var) == VT_DISPATCH, "VT = %d\n", V_VT(&var)); + ok(V_DISPATCH(&var) != NULL, "objname = null\n"); + + elem2 = get_elem_iface((IUnknown*)V_DISPATCH(&var)); + IDispatch_Release(V_DISPATCH(&var)); + + test_object_vspace((IUnknown*)elem2, 100); + test_object_name(elem2, L"objname"); + todo_wine + ok(elem != elem2, "elem == elem2\n"); + IHTMLElement_Release(elem2); + set_object_name(elem, L"test"); set_object_name(elem, NULL); + IDispatchEx_Release(dispex); IHTMLElement_Release(elem); }
diff --git a/dlls/mshtml/tests/events.c b/dlls/mshtml/tests/events.c index 220312ea628..dcd7160a67d 100644 --- a/dlls/mshtml/tests/events.c +++ b/dlls/mshtml/tests/events.c @@ -2747,9 +2747,13 @@ static void test_iframe_connections(IHTMLDocument2 *doc)
static void test_doc_obj(IHTMLDocument2 *doc) { + DISPID dispid, import_node_id, has_own_prop_id; int orig_doc_mode = document_mode; IEventTarget *event_target; + DISPPARAMS dp = { 0 }; + IDispatchEx *dispex; IHTMLElement *body; + VARIANT res, arg; HRESULT hres; BSTR bstr;
@@ -2793,9 +2797,74 @@ static void test_doc_obj(IHTMLDocument2 *doc) ok(!wcscmp(bstr, (document_mode < 9 ? L"[object]" : L"[object Document]")), "toString returned %s\n", wine_dbgstr_w(bstr)); SysFreeString(bstr);
+ /* IHTMLDocument6 prop */ + bstr = SysAllocString(L"onstoragecommit"); + hres = IHTMLDocument2_GetIDsOfNames(doc, &IID_NULL, &bstr, 1, 0, &dispid); + ok(hres == S_OK, "GetIDsOfNames(onstoragecommit) returned: %08lx\n", hres); + SysFreeString(bstr); + + /* IHTMLDocument7 method */ + bstr = SysAllocString(L"importNode"); + hres = IHTMLDocument2_GetIDsOfNames(doc, &IID_NULL, &bstr, 1, 0, &dispid); + ok(hres == (document_mode < 9 ? DISP_E_UNKNOWNNAME : S_OK), "GetIDsOfNames(importNode) returned: %08lx\n", hres); + + hres = IHTMLDocument2_QueryInterface(doc, &IID_IDispatchEx, (void**)&dispex); + ok(hres == S_OK, "Could not get IDispatchEx: %08lx\n", hres); + + hres = IDispatchEx_GetDispID(dispex, bstr, fdexNameEnsure, &import_node_id); + ok(hres == S_OK, "GetDispID(importNode) returned: %08lx\n", hres); + if(document_mode >= 9) + ok(import_node_id == dispid, "GetDispID(importNode) != GetIDsOfNames(importNode)\n"); + IDispatchEx_Release(dispex); + SysFreeString(bstr); + + /* prop set via script on node */ + bstr = SysAllocString(L"prop"); + hres = IHTMLDocument2_GetIDsOfNames(doc, &IID_NULL, &bstr, 1, 0, &dispid); + ok(hres == S_OK, "GetIDsOfNames(prop) returned: %08lx\n", hres); + SysFreeString(bstr); + + hres = IHTMLDocument2_Invoke(doc, dispid, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dp, &res, NULL, NULL); + ok(hres == S_OK, "Invoke(prop) failed: %08lx\n", hres); + ok(V_VT(&res) == VT_I4, "VT(prop) = %d\n", V_VT(&res)); + ok(V_I4(&res) == 137, "prop = %ld\n", V_I4(&res)); + + /* jscript prop on prototype chain */ + bstr = SysAllocString(L"hasOwnProperty"); + hres = IHTMLDocument2_GetIDsOfNames(doc, &IID_NULL, &bstr, 1, 0, &has_own_prop_id); + todo_wine_if(document_mode >= 9) + ok(hres == (document_mode < 9 ? DISP_E_UNKNOWNNAME : S_OK), "GetIDsOfNames(hasOwnProperty) returned: %08lx\n", hres); + SysFreeString(bstr); + + if(hres == S_OK) { + dp.cArgs = 1; + dp.rgvarg = &arg; + V_VT(&arg) = VT_BSTR; + V_BSTR(&arg) = SysAllocString(L"createElement"); + hres = IHTMLDocument2_Invoke(doc, has_own_prop_id, &IID_NULL, 0, DISPATCH_METHOD, &dp, &res, NULL, NULL); + ok(hres == S_OK, "Invoke(hasOwnProperty("createElement")) failed: %08lx\n", hres); + ok(V_VT(&res) == VT_BOOL, "VT = %d\n", V_VT(&res)); + todo_wine + ok(V_BOOL(&res) == VARIANT_FALSE, "hasOwnProperty("createElement") = %d\n", V_BOOL(&res)); + + hres = IHTMLDocument2_GetIDsOfNames(doc, &IID_NULL, &V_BSTR(&arg), 1, 0, &dispid); + ok(hres == S_OK, "GetIDsOfNames(createElement) returned: %08lx\n", hres); + SysFreeString(V_BSTR(&arg)); + + V_BSTR(&arg) = SysAllocString(L"prop"); + hres = IHTMLDocument2_Invoke(doc, has_own_prop_id, &IID_NULL, 0, DISPATCH_METHOD, &dp, &res, NULL, NULL); + ok(hres == S_OK, "Invoke(hasOwnProperty("prop")) failed: %08lx\n", hres); + ok(V_VT(&res) == VT_BOOL, "VT = %d\n", V_VT(&res)); + ok(V_BOOL(&res) == VARIANT_TRUE, "hasOwnProperty("prop") = %d\n", V_BOOL(&res)); + SysFreeString(V_BSTR(&arg)); + } + /* Navigate to a different document mode page, checking using the same doc obj. Test that it breaks COM rules, since IEventTarget is conditionally exposed. - All the events registered on the old doc node are also removed. */ + All the events registered on the old doc node are also removed. + + DISPIDs are forwarded to the node, and thus it also breaks Dispatch rules, + where the same name will potentially receive a different DISPID. */ navigate(doc, document_mode < 9 ? L"doc_with_prop_ie9.html" : L"doc_with_prop.html"); ok(document_mode == (orig_doc_mode < 9 ? 9 : 5), "new document_mode = %d\n", document_mode);
@@ -2810,10 +2879,25 @@ static void test_doc_obj(IHTMLDocument2 *doc) ok(hres == S_OK, "click failed: %08lx\n", hres); IHTMLElement_Release(body); pump_msgs(NULL); + + hres = IHTMLDocument2_QueryInterface(doc, &IID_IDispatchEx, (void**)&dispex); + ok(hres == S_OK, "Could not get IDispatchEx: %08lx\n", hres); + + bstr = SysAllocString(L"importNode"); + hres = IDispatchEx_GetDispID(dispex, bstr, fdexNameEnsure, &dispid); + ok(hres == S_OK, "GetDispID(importNode) returned: %08lx\n", hres); + ok(dispid != import_node_id, "importNode on new doc node == old importNode\n"); + IDispatchEx_Release(dispex); + SysFreeString(bstr); }else { ok(hres == S_OK, "hres = %08lx, expected S_OK\n", hres); ok(!!event_target, "event_target = NULL\n"); IEventTarget_Release(event_target); + + bstr = SysAllocString(L"importNode"); + hres = IHTMLDocument2_GetIDsOfNames(doc, &IID_NULL, &bstr, 1, 0, &dispid); + ok(hres == S_OK, "GetIDsOfNames(importNode) returned: %08lx\n", hres); + ok(dispid != import_node_id, "importNode on new doc node == old created importNode\n"); } }
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Native ignores any cNames > 1 and doesn't even fill the dispids for them. Note that it was already wrong; the multiple dispids are supposed to correspond to the member's argument names, not extra dispids.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/dispex.c | 13 ++-- dlls/mshtml/htmlwindow.c | 12 ++-- dlls/mshtml/tests/dom.c | 101 +++++++++++++++++++++++++++++ dlls/mshtml/tests/xmlhttprequest.c | 31 +++++++++ 4 files changed, 142 insertions(+), 15 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index d8aaf819f58..c70deb67209 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -1636,19 +1636,16 @@ static HRESULT WINAPI DispatchEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid, LCID lcid, DISPID *rgDispId) { DispatchEx *This = impl_from_IDispatchEx(iface); - UINT i; - HRESULT hres; + HRESULT hres = S_OK;
TRACE("(%p)->(%s %p %u %lu %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
- for(i=0; i < cNames; i++) { - hres = IDispatchEx_GetDispID(&This->IDispatchEx_iface, rgszNames[i], 0, rgDispId+i); - if(FAILED(hres)) - return hres; - } + /* Native ignores all cNames > 1, and doesn't even fill them */ + if(cNames) + hres = IDispatchEx_GetDispID(&This->IDispatchEx_iface, rgszNames[0], 0, rgDispId);
- return S_OK; + return hres; }
static HRESULT WINAPI DispatchEx_Invoke(IDispatchEx *iface, DISPID dispIdMember, diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index 7014a4cd4b4..c2475afd1f6 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -3476,19 +3476,17 @@ static HRESULT WINAPI WindowDispEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid LCID lcid, DISPID *rgDispId) { HTMLWindow *This = impl_from_IDispatchEx(iface); - UINT i; - HRESULT hres; + HRESULT hres = S_OK;
WARN("(%p)->(%s %p %u %lu %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
- for(i=0; i < cNames; i++) { + /* Native ignores all cNames > 1, and doesn't even fill them */ + if(cNames) { /* We shouldn't use script's IDispatchEx here, so we shouldn't use GetDispID */ - hres = IDispatchEx_GetDispID(&This->IDispatchEx_iface, rgszNames[i], 0, rgDispId+i); - if(FAILED(hres)) - return hres; + hres = IDispatchEx_GetDispID(&This->IDispatchEx_iface, rgszNames[0], 0, rgDispId); }
- return S_OK; + return hres; }
static HRESULT WINAPI WindowDispEx_Invoke(IDispatchEx *iface, DISPID dispIdMember, diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index c31de136cd8..4e6ad469b28 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -27,6 +27,7 @@ #include "ole2.h" #include "mshtml.h" #include "mshtmcid.h" +#include "mshtmdid.h" #include "mshtmhst.h" #include "docobj.h" #include "hlink.h" @@ -5288,6 +5289,98 @@ static void _test_doc_set_title(unsigned line, IHTMLDocument2 *doc, const WCHAR SysFreeString(tmp); }
+static void test_doc_GetIDsOfNames(IHTMLDocument2 *doc) +{ + DISPID dispids[3]; + HRESULT hres; + BSTR bstr[3]; + + bstr[0] = SysAllocString(L"createStyleSheet"); + bstr[1] = SysAllocString(L"bstrHref"); + bstr[2] = SysAllocString(L"lIndex"); + dispids[0] = 0; + dispids[1] = 0xdead; + dispids[2] = 0xbeef; + hres = IHTMLDocument2_GetIDsOfNames(doc, &IID_NULL, bstr, 3, 0, dispids); + ok(hres == S_OK, "GetIDsOfNames failed: %08lx\n", hres); + ok(dispids[0] == DISPID_IHTMLDOCUMENT2_CREATESTYLESHEET, "createStyleSheet dispid = %ld\n", dispids[0]); + ok(dispids[1] == 0xdead, "bstrHref dispid = %ld\n", dispids[1]); + ok(dispids[2] == 0xbeef, "lIndex dispid = %ld\n", dispids[2]); + SysFreeString(bstr[2]); + SysFreeString(bstr[1]); + SysFreeString(bstr[0]); +} + +static void test_window_GetIDsOfNames(IHTMLWindow2 *window) +{ + DISPID dispids[3]; + HRESULT hres; + BSTR bstr[3]; + + bstr[0] = SysAllocString(L"showHelp"); + bstr[1] = SysAllocString(L"helpURL"); + bstr[2] = SysAllocString(L"helpArg"); + dispids[0] = 0; + dispids[1] = 0xdead; + dispids[2] = 0xbeef; + hres = IHTMLWindow2_GetIDsOfNames(window, &IID_NULL, bstr, 3, 0, dispids); + ok(hres == S_OK, "GetIDsOfNames failed: %08lx\n", hres); + ok(dispids[0] == DISPID_IHTMLWINDOW2_SHOWHELP, "showHelp dispid = %ld\n", dispids[0]); + ok(dispids[1] == 0xdead, "helpURL dispid = %ld\n", dispids[1]); + ok(dispids[2] == 0xbeef, "helpArg dispid = %ld\n", dispids[2]); + SysFreeString(bstr[2]); + SysFreeString(bstr[1]); + SysFreeString(bstr[0]); +} + +static void test_elem_GetIDsOfNames(IHTMLElement *elem) +{ + DISPID dispids[3]; + HRESULT hres; + BSTR bstr[3]; + + /* IE9+ use something like js proxies even on native and have different dispids */ + if(compat_mode >= COMPAT_IE9) + return; + + bstr[0] = SysAllocString(L"insertAdjacentText"); + bstr[1] = SysAllocString(L"where"); + bstr[2] = SysAllocString(L"text"); + dispids[0] = 0; + dispids[1] = 0xdead; + dispids[2] = 0xbeef; + hres = IHTMLElement_GetIDsOfNames(elem, &IID_NULL, bstr, 3, 0, dispids); + ok(hres == S_OK, "GetIDsOfNames failed: %08lx\n", hres); + ok(dispids[0] == DISPID_IHTMLELEMENT_INSERTADJACENTTEXT, "insertAdjacentText dispid = %ld\n", dispids[0]); + ok(dispids[1] == 0xdead, "where dispid = %ld\n", dispids[1]); + ok(dispids[2] == 0xbeef, "text dispid = %ld\n", dispids[2]); + SysFreeString(bstr[2]); + SysFreeString(bstr[1]); + SysFreeString(bstr[0]); +} + +static void test_attr_GetIDsOfNames(IHTMLDOMAttribute *attr) +{ + DISPID dispids[3]; + HRESULT hres; + BSTR bstr[3]; + + bstr[0] = SysAllocString(L"insertBefore"); + bstr[1] = SysAllocString(L"newChild"); + bstr[2] = SysAllocString(L"refChild"); + dispids[0] = 0; + dispids[1] = 0xdead; + dispids[2] = 0xbeef; + hres = IHTMLDOMAttribute_GetIDsOfNames(attr, &IID_NULL, bstr, 3, 0, dispids); + ok(hres == S_OK, "GetIDsOfNames failed: %08lx\n", hres); + ok(dispids[0] == DISPID_IHTMLDOMATTRIBUTE2_INSERTBEFORE, "insertBefore dispid = %ld\n", dispids[0]); + ok(dispids[1] == 0xdead, "newChild dispid = %ld\n", dispids[1]); + ok(dispids[2] == 0xbeef, "refChild dispid = %ld\n", dispids[2]); + SysFreeString(bstr[2]); + SysFreeString(bstr[1]); + SysFreeString(bstr[0]); +} + static void test_elem_bounding_client_rect(IUnknown *unk) { IHTMLRectCollection *rects; @@ -5462,6 +5555,7 @@ static IHTMLElement *get_elem_by_id(IHTMLDocument2 *doc, const WCHAR *id, BOOL e elem = get_elem_iface((IUnknown*)disp); IDispatch_Release(disp);
+ test_elem_GetIDsOfNames(elem); return elem; }
@@ -5482,6 +5576,8 @@ static IHTMLElement *get_doc_elem_by_id(IHTMLDocument2 *doc, const WCHAR *id)
IHTMLDocument3_Release(doc3);
+ if(elem) + test_elem_GetIDsOfNames(elem); return elem; }
@@ -6854,6 +6950,8 @@ static void test_doc_elem(IHTMLDocument2 *doc) HRESULT hres; BSTR bstr;
+ test_doc_GetIDsOfNames(doc); + hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument3, (void**)&doc3); ok(hres == S_OK, "QueryInterface(IID_IHTMLDocument3) failed: %08lx\n", hres);
@@ -6875,6 +6973,7 @@ static void test_doc_elem(IHTMLDocument2 *doc) owner_doc = get_owner_doc((IUnknown*)elem); ok(iface_cmp((IUnknown *)doc_node, (IUnknown *)owner_doc), "doc_node != owner_doc\n"); IHTMLDocument2_Release(owner_doc); + test_doc_GetIDsOfNames(doc_node);
owner_doc = get_owner_doc((IUnknown*)doc_node); ok(!owner_doc, "owner_doc = %p\n", owner_doc); @@ -7158,6 +7257,7 @@ static void test_window(IHTMLDocument2 *doc) win_skip("IID_ITravelLogClient not supported\n");
test_disp((IUnknown*)window, &DIID_DispHTMLWindow2, &CLSID_HTMLWindow2, L"[object]"); + test_window_GetIDsOfNames(window);
hres = IHTMLWindow2_get_document(window, &doc2); ok(hres == S_OK, "get_document failed: %08lx\n", hres); @@ -9796,6 +9896,7 @@ static void test_attr(IHTMLDocument2 *doc, IHTMLElement *elem) test_no_iface((IUnknown*)attr, &IID_IHTMLDOMNode); test_attr_specified(attr, VARIANT_TRUE); test_attr_parent(attr); + test_attr_GetIDsOfNames(attr);
attr2 = get_elem_attr_node((IUnknown*)elem, L"id", TRUE); ok(iface_cmp((IUnknown*)attr, (IUnknown*)attr2), "attr != attr2\n"); diff --git a/dlls/mshtml/tests/xmlhttprequest.c b/dlls/mshtml/tests/xmlhttprequest.c index 6aef9f5a35d..a3ec54ffef6 100644 --- a/dlls/mshtml/tests/xmlhttprequest.c +++ b/dlls/mshtml/tests/xmlhttprequest.c @@ -25,6 +25,7 @@ #include "winbase.h" #include "ole2.h" #include "mshtml.h" +#include "mshtmdid.h" #include "objsafe.h" #include "wine/test.h"
@@ -402,6 +403,35 @@ static void create_xmlhttprequest(IHTMLDocument2 *doc) ok(xhr != NULL, "xhr == NULL\n"); }
+static void test_GetIDsOfNames(IHTMLDocument2 *doc) +{ + DISPID dispids[3]; + HRESULT hres; + BSTR bstr[3]; + + create_xmlhttprequest(doc); + if(!xhr) + return; + + bstr[0] = SysAllocString(L"open"); + bstr[1] = SysAllocString(L"bstrMethod"); + bstr[2] = SysAllocString(L"varAsync"); + dispids[0] = 0; + dispids[1] = 0xdead; + dispids[2] = 0xbeef; + hres = IHTMLXMLHttpRequest_GetIDsOfNames(xhr, &IID_NULL, bstr, 3, 0, dispids); + ok(hres == S_OK, "GetIDsOfNames failed: %08lx\n", hres); + ok(dispids[0] == DISPID_IHTMLXMLHTTPREQUEST_OPEN, "open dispid = %ld\n", dispids[0]); + ok(dispids[1] == 0xdead, "bstrMethod dispid = %ld\n", dispids[1]); + ok(dispids[2] == 0xbeef, "varAsync dispid = %ld\n", dispids[2]); + SysFreeString(bstr[2]); + SysFreeString(bstr[1]); + SysFreeString(bstr[0]); + + IHTMLXMLHttpRequest_Release(xhr); + xhr = NULL; +} + static void test_header(const struct HEADER_TYPE expect[], int num) { int i; @@ -1100,6 +1130,7 @@ START_TEST(xmlhttprequest) content_type = SysAllocString(L"Content-Type"); doc = create_doc_from_url(start_url); if(doc) { + test_GetIDsOfNames(doc); test_sync_xhr(doc, xml_url, expect_response_text); test_sync_xhr(doc, large_page_url, NULL); test_async_xhr(doc, xml_url, expect_response_text);
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=126157
Your paranoid android.
=== w8adm (testbot log) ===
WineRunTask.pl:error: The previous 1 run(s) terminated abnormally
=== debian11 (32 bit report) ===
crypt32: cert.c:4191: Test failed: success cert.c:4192: Test failed: got 00000000 cert.c:4193: Test failed: got 00000000
On Mon Nov 14 18:20:01 2022 +0000, Gabriel Ivăncescu wrote:
It was just for consistency with the other places where it's used. Should I drop the check? (I guess, in theory, it could happen that new node fails to allocate while keeping old IEventTarget around, but probably not worth in practice) BTW I noticed something else, I probably should move the document_mode and window retrieval to navigate() to keep the globals synced as it's expected (in the tests).
As I mentioned in !1125, those checks are leftovers. I think it's better to drop them now.
This merge request was approved by Jacek Caban.