diff --git a/dlls/mshtml/htmldoc.c b/dlls/mshtml/htmldoc.c
index 87ee8e6b685..7595ad852a6 100644
--- a/dlls/mshtml/htmldoc.c
+++ b/dlls/mshtml/htmldoc.c
@@ -5159,6 +5159,85 @@ static const IDisplayServicesVtbl DisplayServicesVtbl = {
DisplayServices_HasFlowLayout
};
+/**********************************************************
+ * IDocumentRange implementation
+ */
+static inline HTMLDocument *impl_from_IDocumentRange(IDocumentRange *iface)
+{
+ return CONTAINING_RECORD(iface, HTMLDocument, IDocumentRange_iface);
+}
+
+static HRESULT WINAPI DocumentRange_QueryInterface(IDocumentRange *iface, REFIID riid, void **ppv)
+{
+ HTMLDocument *This = impl_from_IDocumentRange(iface);
+
+ return htmldoc_query_interface(This, riid, ppv);
+}
+
+static ULONG WINAPI DocumentRange_AddRef(IDocumentRange *iface)
+{
+ HTMLDocument *This = impl_from_IDocumentRange(iface);
+
+ return htmldoc_addref(This);
+}
+
+static ULONG WINAPI DocumentRange_Release(IDocumentRange *iface)
+{
+ HTMLDocument *This = impl_from_IDocumentRange(iface);
+
+ return htmldoc_release(This);
+}
+
+static HRESULT WINAPI DocumentRange_GetTypeInfoCount(IDocumentRange *iface, UINT *pctinfo)
+{
+ HTMLDocument *This = impl_from_IDocumentRange(iface);
+
+ return IDispatchEx_GetTypeInfoCount(&This->IDispatchEx_iface, pctinfo);
+}
+
+static HRESULT WINAPI DocumentRange_GetTypeInfo(IDocumentRange *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
+{
+ HTMLDocument *This = impl_from_IDocumentRange(iface);
+
+ return IDispatchEx_GetTypeInfo(&This->IDispatchEx_iface, iTInfo, lcid, ppTInfo);
+}
+
+static HRESULT WINAPI DocumentRange_GetIDsOfNames(IDocumentRange *iface, REFIID riid, LPOLESTR *rgszNames, UINT cNames,
+ LCID lcid, DISPID *rgDispId)
+{
+ HTMLDocument *This = impl_from_IDocumentRange(iface);
+
+ return IDispatchEx_GetIDsOfNames(&This->IDispatchEx_iface, riid, rgszNames, cNames, lcid,
+ rgDispId);
+}
+
+static HRESULT WINAPI DocumentRange_Invoke(IDocumentRange *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
+ WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
+{
+ HTMLDocument *This = impl_from_IDocumentRange(iface);
+
+ return IDispatchEx_Invoke(&This->IDispatchEx_iface, dispIdMember, riid, lcid, wFlags,
+ pDispParams, pVarResult, pExcepInfo, puArgErr);
+}
+
+static HRESULT WINAPI DocumentRange_createRange(IDocumentRange *iface, IHTMLDOMRange **p)
+{
+ HTMLDocument *This = impl_from_IDocumentRange(iface);
+ FIXME("(%p)->(%p)\n", This, p);
+ return E_NOTIMPL;
+}
+
+static const IDocumentRangeVtbl DocumentRangeVtbl = {
+ DocumentRange_QueryInterface,
+ DocumentRange_AddRef,
+ DocumentRange_Release,
+ DocumentRange_GetTypeInfoCount,
+ DocumentRange_GetTypeInfo,
+ DocumentRange_GetIDsOfNames,
+ DocumentRange_Invoke,
+ DocumentRange_createRange,
+};
+
static BOOL htmldoc_qi(HTMLDocument *This, REFIID riid, void **ppv)
{
*ppv = NULL;
@@ -5243,6 +5322,8 @@ static BOOL htmldoc_qi(HTMLDocument *This, REFIID riid, void **ppv)
*ppv = &This->IMarkupContainer_iface;
else if(IsEqualGUID(&IID_IDisplayServices, riid))
*ppv = &This->IDisplayServices_iface;
+ else if(IsEqualGUID(&IID_IDocumentRange, riid))
+ *ppv = &This->IDocumentRange_iface;
else if(IsEqualGUID(&CLSID_CMarkup, riid)) {
FIXME("(%p)->(CLSID_CMarkup %p)\n", This, ppv);
*ppv = NULL;
@@ -5294,6 +5375,7 @@ static void init_doc(HTMLDocument *doc, IUnknown *outer, IDispatchEx *dispex)
doc->IMarkupServices_iface.lpVtbl = &MarkupServicesVtbl;
doc->IMarkupContainer_iface.lpVtbl = &MarkupContainerVtbl;
doc->IDisplayServices_iface.lpVtbl = &DisplayServicesVtbl;
+ doc->IDocumentRange_iface.lpVtbl = &DocumentRangeVtbl;
doc->outer_unk = outer;
doc->dispex = dispex;
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h
index 6bfce89698c..ef56f1d23d7 100644
--- a/dlls/mshtml/mshtml_private.h
+++ b/dlls/mshtml/mshtml_private.h
@@ -144,6 +144,7 @@ typedef struct EventTarget EventTarget;
XIID(IDOMMouseEvent) \
XIID(IDOMUIEvent) \
XIID(IDocumentEvent) \
+ XIID(IDocumentRange) \
XIID(IDocumentSelector) \
XIID(IElementSelector) \
XIID(IElementTraversal) \
@@ -626,6 +627,7 @@ struct HTMLDocument {
IMarkupServices IMarkupServices_iface;
IMarkupContainer IMarkupContainer_iface;
IDisplayServices IDisplayServices_iface;
+ IDocumentRange IDocumentRange_iface;
IUnknown *outer_unk;
IDispatchEx *dispex;
diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c
index f6eebbc18b8..586df7d8a5b 100644
--- a/dlls/mshtml/tests/dom.c
+++ b/dlls/mshtml/tests/dom.c
@@ -171,6 +171,7 @@ static const IID * const doc_node_iids[] = {
&IID_IHTMLDocument3,
&IID_IHTMLDocument4,
&IID_IHTMLDocument5,
+ &IID_IDocumentRange,
&IID_IDocumentSelector,
&IID_IDispatchEx,
&IID_IDisplayServices,
@@ -190,6 +191,7 @@ static const IID * const doc_obj_iids[] = {
&IID_IHTMLDocument3,
&IID_IHTMLDocument4,
&IID_IHTMLDocument5,
+ &IID_IDocumentRange,
&IID_IDocumentSelector,
&IID_IDispatchEx,
&IID_IDisplayServices,
diff --git a/include/mshtmdid.h b/include/mshtmdid.h
index 82055f690bf..87b8877f4e8 100644
--- a/include/mshtmdid.h
+++ b/include/mshtmdid.h
@@ -4711,4 +4711,7 @@
#define DISPID_IDOCUMENTSELECTOR_QUERYSELECTOR DISPID_OMDOCUMENT+105
#define DISPID_IDOCUMENTSELECTOR_QUERYSELECTORALL DISPID_OMDOCUMENT+106
+/* IDocumentRange */
+#define DISPID_IDOCUMENTRANGE_CREATERANGE DISPID_OMDOCUMENT+111
+
#endif /* __MSHTMDID_H__ */
diff --git a/include/mshtml.idl b/include/mshtml.idl
index f7ebd9e71ab..aea888b2b85 100644
--- a/include/mshtml.idl
+++ b/include/mshtml.idl
@@ -23451,6 +23451,19 @@ interface IDocumentSelector : IDispatch
[out, retval] IHTMLDOMChildrenCollection **pel);
}
+[
+ odl,
+ oleautomation,
+ dual,
+ uuid(305104af-98b5-11cf-bb82-00aa00bdce0b)
+]
+interface IDocumentRange : IDispatch
+{
+ [id(DISPID_IDOCUMENTRANGE_CREATERANGE)]
+ HRESULT createRange(
+ [out, retval] IHTMLDOMRange **ppIHTMLDOMRange);
+}
+
/*****************************************************************************
* DispHTMLDocument dispinterface
*/
@@ -24058,6 +24071,9 @@ methods:
[id(DISPID_IDOCUMENTSELECTOR_QUERYSELECTORALL)]
IHTMLDOMChildrenCollection *querySelectorAll([in] BSTR v);
+
+ [id(DISPID_IDOCUMENTRANGE_CREATERANGE)]
+ IHTMLDOMRange *createRange();
}
/*****************************************************************************