Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
September 2018
- 70 participants
- 1549 messages
[PATCH v4 3/4] riched20: Add IID_ITextDocument2Old support for ITextServices_QueryInterface().
by Jactry Zeng
Superseded patch 151084.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=20613
Signed-off-by: Jactry Zeng <jzeng(a)codeweavers.com>
---
dlls/riched20/tests/txtsrv.c | 34 ++++++++++++++++++++++++++++++++++
dlls/riched20/txtsrv.c | 5 +++--
2 files changed, 37 insertions(+), 2 deletions(-)
diff --git a/dlls/riched20/tests/txtsrv.c b/dlls/riched20/tests/txtsrv.c
index a8cf6ff1ad..1aa08f89a4 100644
--- a/dlls/riched20/tests/txtsrv.c
+++ b/dlls/riched20/tests/txtsrv.c
@@ -904,6 +904,7 @@ static void test_QueryInterface(void)
HRESULT hres;
IRichEditOle *reole, *txtsrv_reole;
ITextDocument *txtdoc, *txtsrv_txtdoc;
+ ITextDocument2Old *txtdoc2old, *txtsrv_txtdoc2old;
ULONG refcount;
if(!init_texthost(&txtserv, &host))
@@ -930,6 +931,17 @@ static void test_QueryInterface(void)
ITextDocument_Release(txtdoc);
refcount = get_refcount((IUnknown *)txtserv);
ok(refcount == 2, "got wrong ref count: %d\n", refcount);
+
+ hres = IRichEditOle_QueryInterface(txtsrv_reole, &IID_ITextDocument2Old, (void **)&txtdoc2old);
+ ok(hres == S_OK, "IRichEditOle_QueryInterface: 0x%08x\n", hres);
+ refcount = get_refcount((IUnknown *)txtserv);
+ ok(refcount == 3, "got wrong ref count: %d\n", refcount);
+ refcount = get_refcount((IUnknown *)txtsrv_reole);
+ ok(refcount == 3, "got wrong ref count: %d\n", refcount);
+
+ ITextDocument2Old_Release(txtdoc2old);
+ refcount = get_refcount((IUnknown *)txtserv);
+ ok(refcount == 2, "got wrong ref count: %d\n", refcount);
IRichEditOle_Release(txtsrv_reole);
refcount = get_refcount((IUnknown *)txtserv);
ok(refcount == 1, "got wrong ref count: %d\n", refcount);
@@ -956,6 +968,28 @@ static void test_QueryInterface(void)
refcount = get_refcount((IUnknown *)txtserv);
ok(refcount == 1, "got wrong ref count: %d\n", refcount);
+ /* ITextDocument2Old */
+ hres = ITextServices_QueryInterface(txtserv, &IID_ITextDocument2Old, (void **)&txtsrv_txtdoc2old);
+ ok(hres == S_OK, "ITextServices_QueryInterface: 0x%08x\n", hres);
+ refcount = get_refcount((IUnknown *)txtserv);
+ ok(refcount == 2, "got wrong ref count: %d\n", refcount);
+ refcount = get_refcount((IUnknown *)txtsrv_txtdoc2old);
+ ok(refcount == 2, "got wrong ref count: %d\n", refcount);
+
+ hres = ITextDocument2Old_QueryInterface(txtsrv_txtdoc2old, &IID_IRichEditOle, (void **)&reole);
+ ok(hres == S_OK, "ITextDocument2Old_QueryInterface: 0x%08x\n", hres);
+ refcount = get_refcount((IUnknown *)txtserv);
+ ok(refcount == 3, "got wrong ref count: %d\n", refcount);
+ refcount = get_refcount((IUnknown *)txtsrv_txtdoc2old);
+ ok(refcount == 3, "got wrong ref count: %d\n", refcount);
+
+ IRichEditOle_Release(reole);
+ refcount = get_refcount((IUnknown *)txtserv);
+ ok(refcount == 2, "got wrong ref count: %d\n", refcount);
+ ITextDocument2Old_Release(txtsrv_txtdoc2old);
+ refcount = get_refcount((IUnknown *)txtserv);
+ ok(refcount == 1, "got wrong ref count: %d\n", refcount);
+
ITextServices_Release(txtserv);
ITextHost_Release(host);
}
diff --git a/dlls/riched20/txtsrv.c b/dlls/riched20/txtsrv.c
index 5ab3322e6b..cf957cff89 100644
--- a/dlls/riched20/txtsrv.c
+++ b/dlls/riched20/txtsrv.c
@@ -78,11 +78,12 @@ static HRESULT WINAPI ITextServicesImpl_QueryInterface(IUnknown *iface, REFIID r
*ppv = &This->IUnknown_inner;
else if (IsEqualIID(riid, &IID_ITextServices))
*ppv = &This->ITextServices_iface;
- else if (IsEqualIID(riid, &IID_IRichEditOle) || IsEqualIID(riid, &IID_ITextDocument)) {
+ else if (IsEqualIID(riid, &IID_IRichEditOle) || IsEqualIID(riid, &IID_ITextDocument) ||
+ IsEqualIID(riid, &IID_ITextDocument2Old)) {
if (!This->editor->reOle)
if (!CreateIRichEditOle(This->outer_unk, This->editor, (void **)(&This->editor->reOle)))
return E_OUTOFMEMORY;
- if (IsEqualIID(riid, &IID_ITextDocument))
+ if (IsEqualIID(riid, &IID_ITextDocument) || IsEqualIID(riid, &IID_ITextDocument2Old))
ME_GetITextDocument2OldInterface(This->editor->reOle, ppv);
else
*ppv = This->editor->reOle;
--
2.19.0
Sept. 26, 2018
[PATCH v4 2/4] riched20: Add stub for ITextDocument2Old interface.
by Jactry Zeng
Superseded patch 151083.
ChangLog:
v4: Add tests of type info.
Signed-off-by: Jactry Zeng <jzeng(a)codeweavers.com>
---
dlls/riched20/editor.h | 2 +-
dlls/riched20/richole.c | 435 ++++++++++++++++++++++++----------
dlls/riched20/tests/richole.c | 37 +++
dlls/riched20/txtsrv.c | 2 +-
4 files changed, 348 insertions(+), 128 deletions(-)
diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h
index 141c63aca9..eba6d35fc7 100644
--- a/dlls/riched20/editor.h
+++ b/dlls/riched20/editor.h
@@ -233,7 +233,7 @@ void ME_DrawOLE(ME_Context *c, int x, int y, ME_Run* run, BOOL selected) DECLSPE
void ME_GetOLEObjectSize(const ME_Context *c, ME_Run *run, SIZE *pSize) DECLSPEC_HIDDEN;
void ME_CopyReObject(REOBJECT *dst, const REOBJECT *src, DWORD flags) DECLSPEC_HIDDEN;
void ME_DeleteReObject(struct re_object *re_object) DECLSPEC_HIDDEN;
-void ME_GetITextDocumentInterface(IRichEditOle *iface, LPVOID *ppvObj) DECLSPEC_HIDDEN;
+void ME_GetITextDocument2OldInterface(IRichEditOle *iface, LPVOID *ppvObj) DECLSPEC_HIDDEN;
/* editor.c */
ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10) DECLSPEC_HIDDEN;
diff --git a/dlls/riched20/richole.c b/dlls/riched20/richole.c
index 11b9920b57..dc1a3b8405 100644
--- a/dlls/riched20/richole.c
+++ b/dlls/riched20/richole.c
@@ -46,6 +46,7 @@ DEFINE_GUID(IID_ITextServices, 0x8d33f740, 0xcf58, 0x11ce, 0xa8, 0x9d, 0x00, 0xa
DEFINE_GUID(IID_ITextHost, 0x13e670f4,0x1a5a,0x11cf,0xab,0xeb,0x00,0xaa,0x00,0xb6,0x5e,0xa1);
DEFINE_GUID(IID_ITextHost2, 0x13e670f5,0x1a5a,0x11cf,0xab,0xeb,0x00,0xaa,0x00,0xb6,0x5e,0xa1);
DEFINE_GUID(IID_ITextDocument, 0x8cc497c0, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xaa, 0x00, 0x47, 0xbe, 0x5d);
+DEFINE_GUID(IID_ITextDocument2Old, 0x01c25500, 0x4268, 0x11d1, 0x88, 0x3a, 0x3c, 0x8b, 0x00, 0xc1, 0x00, 0x00);
DEFINE_GUID(IID_ITextRange, 0x8cc497c2, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xaa, 0x00, 0x47, 0xbe, 0x5d);
DEFINE_GUID(IID_ITextSelection, 0x8cc497c1, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xaa, 0x00, 0x47, 0xbe, 0x5d);
DEFINE_GUID(IID_ITextFont, 0x8cc497c3, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xaa, 0x00, 0x47, 0xbe, 0x5d);
@@ -208,7 +209,7 @@ enum range_update_op {
typedef struct IRichEditOleImpl {
IUnknown IUnknown_inner;
IRichEditOle IRichEditOle_iface;
- ITextDocument ITextDocument_iface;
+ ITextDocument2Old ITextDocument2Old_iface;
IUnknown *outer_unk;
LONG ref;
@@ -267,9 +268,9 @@ static inline IRichEditOleImpl *impl_from_IRichEditOle(IRichEditOle *iface)
return CONTAINING_RECORD(iface, IRichEditOleImpl, IRichEditOle_iface);
}
-static inline IRichEditOleImpl *impl_from_ITextDocument(ITextDocument *iface)
+static inline IRichEditOleImpl *impl_from_ITextDocument2Old(ITextDocument2Old *iface)
{
- return CONTAINING_RECORD(iface, IRichEditOleImpl, ITextDocument_iface);
+ return CONTAINING_RECORD(iface, IRichEditOleImpl, ITextDocument2Old_iface);
}
static inline IRichEditOleImpl *impl_from_IUnknown(IUnknown *iface)
@@ -943,8 +944,8 @@ static HRESULT WINAPI IRichEditOleImpl_inner_fnQueryInterface(IUnknown *iface, R
*ppvObj = &This->IUnknown_inner;
else if (IsEqualGUID(riid, &IID_IRichEditOle))
*ppvObj = &This->IRichEditOle_iface;
- else if (IsEqualGUID(riid, &IID_ITextDocument))
- *ppvObj = &This->ITextDocument_iface;
+ else if (IsEqualGUID(riid, &IID_ITextDocument) || IsEqualGUID(riid, &IID_ITextDocument2Old))
+ *ppvObj = &This->ITextDocument2Old_iface;
if (*ppvObj)
{
IUnknown_AddRef((IUnknown *)*ppvObj);
@@ -3859,43 +3860,38 @@ static HRESULT create_textpara(ITextRange *range, ITextPara **ret)
}
/* ITextDocument */
-static HRESULT WINAPI
-ITextDocument_fnQueryInterface(ITextDocument* me, REFIID riid,
- void** ppvObject)
+static HRESULT WINAPI ITextDocument2Old_fnQueryInterface(ITextDocument2Old* iface, REFIID riid,
+ void **ppvObject)
{
- IRichEditOleImpl *This = impl_from_ITextDocument(me);
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
return IRichEditOle_QueryInterface(&This->IRichEditOle_iface, riid, ppvObject);
}
-static ULONG WINAPI
-ITextDocument_fnAddRef(ITextDocument* me)
+static ULONG WINAPI ITextDocument2Old_fnAddRef(ITextDocument2Old *iface)
{
- IRichEditOleImpl *This = impl_from_ITextDocument(me);
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
return IRichEditOle_AddRef(&This->IRichEditOle_iface);
}
-static ULONG WINAPI
-ITextDocument_fnRelease(ITextDocument* me)
+static ULONG WINAPI ITextDocument2Old_fnRelease(ITextDocument2Old *iface)
{
- IRichEditOleImpl *This = impl_from_ITextDocument(me);
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
return IRichEditOle_Release(&This->IRichEditOle_iface);
}
-static HRESULT WINAPI
-ITextDocument_fnGetTypeInfoCount(ITextDocument* me,
- UINT* pctinfo)
+static HRESULT WINAPI ITextDocument2Old_fnGetTypeInfoCount(ITextDocument2Old *iface,
+ UINT *pctinfo)
{
- IRichEditOleImpl *This = impl_from_ITextDocument(me);
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
TRACE("(%p)->(%p)\n", This, pctinfo);
*pctinfo = 1;
return S_OK;
}
-static HRESULT WINAPI
-ITextDocument_fnGetTypeInfo(ITextDocument* me, UINT iTInfo, LCID lcid,
- ITypeInfo** ppTInfo)
+static HRESULT WINAPI ITextDocument2Old_fnGetTypeInfo(ITextDocument2Old *iface, UINT iTInfo, LCID lcid,
+ ITypeInfo **ppTInfo)
{
- IRichEditOleImpl *This = impl_from_ITextDocument(me);
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
HRESULT hr;
TRACE("(%p)->(%u,%d,%p)\n", This, iTInfo, lcid, ppTInfo);
@@ -3906,11 +3902,11 @@ ITextDocument_fnGetTypeInfo(ITextDocument* me, UINT iTInfo, LCID lcid,
return hr;
}
-static HRESULT WINAPI
-ITextDocument_fnGetIDsOfNames(ITextDocument* me, REFIID riid,
- LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId)
+static HRESULT WINAPI ITextDocument2Old_fnGetIDsOfNames(ITextDocument2Old *iface, REFIID riid,
+ LPOLESTR *rgszNames, UINT cNames,
+ LCID lcid, DISPID *rgDispId)
{
- IRichEditOleImpl *This = impl_from_ITextDocument(me);
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
ITypeInfo *ti;
HRESULT hr;
@@ -3923,12 +3919,12 @@ ITextDocument_fnGetIDsOfNames(ITextDocument* me, REFIID riid,
return hr;
}
-static HRESULT WINAPI
-ITextDocument_fnInvoke(ITextDocument* me, DISPID dispIdMember,
- REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
- VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
+static HRESULT WINAPI ITextDocument2Old_fnInvoke(ITextDocument2Old *iface, DISPID dispIdMember,
+ REFIID riid, LCID lcid, WORD wFlags,
+ DISPPARAMS *pDispParams, VARIANT *pVarResult,
+ EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
- IRichEditOleImpl *This = impl_from_ITextDocument(me);
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
ITypeInfo *ti;
HRESULT hr;
@@ -3938,24 +3934,22 @@ ITextDocument_fnInvoke(ITextDocument* me, DISPID dispIdMember,
hr = get_typeinfo(ITextDocument_tid, &ti);
if (SUCCEEDED(hr))
- hr = ITypeInfo_Invoke(ti, me, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
+ hr = ITypeInfo_Invoke(ti, iface, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
return hr;
}
-static HRESULT WINAPI
-ITextDocument_fnGetName(ITextDocument* me, BSTR* pName)
+static HRESULT WINAPI ITextDocument2Old_fnGetName(ITextDocument2Old *iface, BSTR *pName)
{
- IRichEditOleImpl *This = impl_from_ITextDocument(me);
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
FIXME("stub %p\n",This);
return E_NOTIMPL;
}
-static HRESULT WINAPI
-ITextDocument_fnGetSelection(ITextDocument *me, ITextSelection **selection)
+static HRESULT WINAPI ITextDocument2Old_fnGetSelection(ITextDocument2Old *iface, ITextSelection **selection)
{
- IRichEditOleImpl *This = impl_from_ITextDocument(me);
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
- TRACE("(%p)->(%p)\n", me, selection);
+ TRACE("(%p)->(%p)\n", iface, selection);
if (!selection)
return E_INVALIDARG;
@@ -3973,125 +3967,110 @@ ITextDocument_fnGetSelection(ITextDocument *me, ITextSelection **selection)
return S_OK;
}
-static HRESULT WINAPI
-ITextDocument_fnGetStoryCount(ITextDocument* me, LONG* pCount)
+static HRESULT WINAPI ITextDocument2Old_fnGetStoryCount(ITextDocument2Old *iface, LONG *pCount)
{
- IRichEditOleImpl *This = impl_from_ITextDocument(me);
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
FIXME("stub %p\n",This);
return E_NOTIMPL;
}
-static HRESULT WINAPI
-ITextDocument_fnGetStoryRanges(ITextDocument* me,
- ITextStoryRanges** ppStories)
+static HRESULT WINAPI ITextDocument2Old_fnGetStoryRanges(ITextDocument2Old *iface,
+ ITextStoryRanges **ppStories)
{
- IRichEditOleImpl *This = impl_from_ITextDocument(me);
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
FIXME("stub %p\n",This);
return E_NOTIMPL;
}
-static HRESULT WINAPI
-ITextDocument_fnGetSaved(ITextDocument* me, LONG* pValue)
+static HRESULT WINAPI ITextDocument2Old_fnGetSaved(ITextDocument2Old *iface, LONG *pValue)
{
- IRichEditOleImpl *This = impl_from_ITextDocument(me);
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
FIXME("stub %p\n",This);
return E_NOTIMPL;
}
-static HRESULT WINAPI
-ITextDocument_fnSetSaved(ITextDocument* me, LONG Value)
+static HRESULT WINAPI ITextDocument2Old_fnSetSaved(ITextDocument2Old *iface, LONG Value)
{
- IRichEditOleImpl *This = impl_from_ITextDocument(me);
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
FIXME("stub %p\n",This);
return E_NOTIMPL;
}
-static HRESULT WINAPI
-ITextDocument_fnGetDefaultTabStop(ITextDocument* me, float* pValue)
+static HRESULT WINAPI ITextDocument2Old_fnGetDefaultTabStop(ITextDocument2Old *iface, float *pValue)
{
- IRichEditOleImpl *This = impl_from_ITextDocument(me);
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
FIXME("stub %p\n",This);
return E_NOTIMPL;
}
-static HRESULT WINAPI
-ITextDocument_fnSetDefaultTabStop(ITextDocument* me, float Value)
+static HRESULT WINAPI ITextDocument2Old_fnSetDefaultTabStop(ITextDocument2Old *iface, float Value)
{
- IRichEditOleImpl *This = impl_from_ITextDocument(me);
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
FIXME("stub %p\n",This);
return E_NOTIMPL;
}
-static HRESULT WINAPI
-ITextDocument_fnNew(ITextDocument* me)
+static HRESULT WINAPI ITextDocument2Old_fnNew(ITextDocument2Old *iface)
{
- IRichEditOleImpl *This = impl_from_ITextDocument(me);
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
FIXME("stub %p\n",This);
return E_NOTIMPL;
}
-static HRESULT WINAPI
-ITextDocument_fnOpen(ITextDocument* me, VARIANT* pVar, LONG Flags,
- LONG CodePage)
+static HRESULT WINAPI ITextDocument2Old_fnOpen(ITextDocument2Old *iface, VARIANT *pVar,
+ LONG Flags, LONG CodePage)
{
- IRichEditOleImpl *This = impl_from_ITextDocument(me);
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
FIXME("stub %p\n",This);
return E_NOTIMPL;
}
-static HRESULT WINAPI
-ITextDocument_fnSave(ITextDocument* me, VARIANT* pVar, LONG Flags,
- LONG CodePage)
+static HRESULT WINAPI ITextDocument2Old_fnSave(ITextDocument2Old *iface, VARIANT *pVar,
+ LONG Flags, LONG CodePage)
{
- IRichEditOleImpl *This = impl_from_ITextDocument(me);
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
FIXME("stub %p\n",This);
return E_NOTIMPL;
}
-static HRESULT WINAPI
-ITextDocument_fnFreeze(ITextDocument* me, LONG* pCount)
+static HRESULT WINAPI ITextDocument2Old_fnFreeze(ITextDocument2Old *iface, LONG *pCount)
{
- IRichEditOleImpl *This = impl_from_ITextDocument(me);
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
FIXME("stub %p\n",This);
return E_NOTIMPL;
}
-static HRESULT WINAPI
-ITextDocument_fnUnfreeze(ITextDocument* me, LONG* pCount)
+static HRESULT WINAPI ITextDocument2Old_fnUnfreeze(ITextDocument2Old *iface, LONG *pCount)
{
- IRichEditOleImpl *This = impl_from_ITextDocument(me);
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
FIXME("stub %p\n",This);
return E_NOTIMPL;
}
-static HRESULT WINAPI
-ITextDocument_fnBeginEditCollection(ITextDocument* me)
+static HRESULT WINAPI ITextDocument2Old_fnBeginEditCollection(ITextDocument2Old *iface)
{
- IRichEditOleImpl *This = impl_from_ITextDocument(me);
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
FIXME("stub %p\n",This);
return E_NOTIMPL;
}
-static HRESULT WINAPI
-ITextDocument_fnEndEditCollection(ITextDocument* me)
+static HRESULT WINAPI ITextDocument2Old_fnEndEditCollection(ITextDocument2Old *iface)
{
- IRichEditOleImpl *This = impl_from_ITextDocument(me);
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
FIXME("stub %p\n",This);
return E_NOTIMPL;
}
-static HRESULT WINAPI
-ITextDocument_fnUndo(ITextDocument* me, LONG Count, LONG* prop)
+static HRESULT WINAPI ITextDocument2Old_fnUndo(ITextDocument2Old *iface, LONG Count, LONG *prop)
{
- IRichEditOleImpl *This = impl_from_ITextDocument(me);
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
FIXME("stub %p\n",This);
return E_NOTIMPL;
}
-static HRESULT WINAPI
-ITextDocument_fnRedo(ITextDocument* me, LONG Count, LONG* prop)
+static HRESULT WINAPI ITextDocument2Old_fnRedo(ITextDocument2Old *iface, LONG Count, LONG *prop)
{
- IRichEditOleImpl *This = impl_from_ITextDocument(me);
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
FIXME("stub %p\n",This);
return E_NOTIMPL;
}
@@ -4112,11 +4091,10 @@ static HRESULT CreateITextRange(IRichEditOleImpl *reOle, LONG start, LONG end, I
return S_OK;
}
-static HRESULT WINAPI
-ITextDocument_fnRange(ITextDocument* me, LONG cp1, LONG cp2,
- ITextRange** ppRange)
+static HRESULT WINAPI ITextDocument2Old_fnRange(ITextDocument2Old *iface, LONG cp1, LONG cp2,
+ ITextRange **ppRange)
{
- IRichEditOleImpl *This = impl_from_ITextDocument(me);
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
const int len = ME_GetTextLength(This->editor) + 1;
TRACE("%p %p %d %d\n", This, ppRange, cp1, cp2);
@@ -4140,42 +4118,247 @@ ITextDocument_fnRange(ITextDocument* me, LONG cp1, LONG cp2,
return CreateITextRange(This, cp1, cp2, ppRange);
}
-static HRESULT WINAPI
-ITextDocument_fnRangeFromPoint(ITextDocument* me, LONG x, LONG y,
- ITextRange** ppRange)
+static HRESULT WINAPI ITextDocument2Old_fnRangeFromPoint(ITextDocument2Old *iface, LONG x, LONG y,
+ ITextRange **ppRange)
{
- IRichEditOleImpl *This = impl_from_ITextDocument(me);
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
FIXME("stub %p\n",This);
return E_NOTIMPL;
}
-static const ITextDocumentVtbl tdvt = {
- ITextDocument_fnQueryInterface,
- ITextDocument_fnAddRef,
- ITextDocument_fnRelease,
- ITextDocument_fnGetTypeInfoCount,
- ITextDocument_fnGetTypeInfo,
- ITextDocument_fnGetIDsOfNames,
- ITextDocument_fnInvoke,
- ITextDocument_fnGetName,
- ITextDocument_fnGetSelection,
- ITextDocument_fnGetStoryCount,
- ITextDocument_fnGetStoryRanges,
- ITextDocument_fnGetSaved,
- ITextDocument_fnSetSaved,
- ITextDocument_fnGetDefaultTabStop,
- ITextDocument_fnSetDefaultTabStop,
- ITextDocument_fnNew,
- ITextDocument_fnOpen,
- ITextDocument_fnSave,
- ITextDocument_fnFreeze,
- ITextDocument_fnUnfreeze,
- ITextDocument_fnBeginEditCollection,
- ITextDocument_fnEndEditCollection,
- ITextDocument_fnUndo,
- ITextDocument_fnRedo,
- ITextDocument_fnRange,
- ITextDocument_fnRangeFromPoint
+/* ITextDocument2Old methods */
+static HRESULT WINAPI ITextDocument2Old_fnAttachMsgFilter(ITextDocument2Old *iface, IUnknown *filter)
+{
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
+
+ FIXME("(%p)->(%p): stub\n", This, filter);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextDocument2Old_fnSetEffectColor(ITextDocument2Old *iface, LONG index, COLORREF cr)
+{
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
+
+ FIXME("(%p)->(%d, 0x%x): stub\n", This, index, cr);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextDocument2Old_fnGetEffectColor(ITextDocument2Old *iface, LONG index, COLORREF *cr)
+{
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
+
+ FIXME("(%p)->(%d, %p): stub\n", This, index, cr);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextDocument2Old_fnGetCaretType(ITextDocument2Old *iface, LONG *type)
+{
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
+
+ FIXME("(%p)->(%p): stub\n", This, type);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextDocument2Old_fnSetCaretType(ITextDocument2Old *iface, LONG type)
+{
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
+
+ FIXME("(%p)->(%d): stub\n", This, type);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextDocument2Old_fnGetImmContext(ITextDocument2Old *iface, LONG *context)
+{
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
+
+ FIXME("(%p)->(%p): stub\n", This, context);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextDocument2Old_fnReleaseImmContext(ITextDocument2Old *iface, LONG context)
+{
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
+
+ FIXME("(%p)->(%d): stub\n", This, context);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextDocument2Old_fnGetPreferredFont(ITextDocument2Old *iface, LONG cp, LONG charrep,
+ LONG options, LONG current_charrep, LONG current_fontsize,
+ BSTR *bstr, LONG *pitch_family, LONG *new_fontsize)
+{
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
+
+ FIXME("(%p)->(%d, %d, %d, %d, %d, %p, %p, %p): stub\n", This, cp, charrep, options, current_charrep,
+ current_fontsize, bstr, pitch_family, new_fontsize);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextDocument2Old_fnGetNotificationMode(ITextDocument2Old *iface, LONG *mode)
+{
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
+
+ FIXME("(%p)->(%p): stub\n", This, mode);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextDocument2Old_fnSetNotificationMode(ITextDocument2Old *iface, LONG mode)
+{
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
+
+ FIXME("(%p)->(0x%x): stub\n", This, mode);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextDocument2Old_fnGetClientRect(ITextDocument2Old *iface, LONG type, LONG *left, LONG *top,
+ LONG *right, LONG *bottom)
+{
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
+
+ FIXME("(%p)->(%d, %p, %p, %p, %p): stub\n", This, type, left, top, right, bottom);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextDocument2Old_fnGetSelectionEx(ITextDocument2Old *iface, ITextSelection **selection)
+{
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
+
+ FIXME("(%p)->(%p): stub\n", This, selection);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextDocument2Old_fnGetWindow(ITextDocument2Old *iface, LONG *hwnd)
+{
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
+
+ FIXME("(%p)->(%p): stub\n", This, hwnd);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextDocument2Old_fnGetFEFlags(ITextDocument2Old *iface, LONG *flags)
+{
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
+
+ FIXME("(%p)->(%p): stub\n", This, flags);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextDocument2Old_fnUpdateWindow(ITextDocument2Old *iface)
+{
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
+
+ FIXME("(%p): stub\n", This);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextDocument2Old_fnCheckTextLimit(ITextDocument2Old *iface, LONG cch, LONG *exceed)
+{
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
+
+ FIXME("(%p)->(%d, %p): stub\n", This, cch, exceed);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextDocument2Old_fnIMEInProgress(ITextDocument2Old *iface, LONG mode)
+{
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
+
+ FIXME("(%p)->(0x%x): stub\n", This, mode);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextDocument2Old_fnSysBeep(ITextDocument2Old *iface)
+{
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
+
+ FIXME("(%p): stub\n", This);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextDocument2Old_fnUpdate(ITextDocument2Old *iface, LONG mode)
+{
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
+
+ FIXME("(%p)->(0x%x): stub\n", This, mode);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ITextDocument2Old_fnNotify(ITextDocument2Old *iface, LONG notify)
+{
+ IRichEditOleImpl *This = impl_from_ITextDocument2Old(iface);
+
+ FIXME("(%p)->(%d): stub\n", This, notify);
+
+ return E_NOTIMPL;
+}
+
+static const ITextDocument2OldVtbl tdvt = {
+ ITextDocument2Old_fnQueryInterface,
+ ITextDocument2Old_fnAddRef,
+ ITextDocument2Old_fnRelease,
+ ITextDocument2Old_fnGetTypeInfoCount,
+ ITextDocument2Old_fnGetTypeInfo,
+ ITextDocument2Old_fnGetIDsOfNames,
+ ITextDocument2Old_fnInvoke,
+ ITextDocument2Old_fnGetName,
+ ITextDocument2Old_fnGetSelection,
+ ITextDocument2Old_fnGetStoryCount,
+ ITextDocument2Old_fnGetStoryRanges,
+ ITextDocument2Old_fnGetSaved,
+ ITextDocument2Old_fnSetSaved,
+ ITextDocument2Old_fnGetDefaultTabStop,
+ ITextDocument2Old_fnSetDefaultTabStop,
+ ITextDocument2Old_fnNew,
+ ITextDocument2Old_fnOpen,
+ ITextDocument2Old_fnSave,
+ ITextDocument2Old_fnFreeze,
+ ITextDocument2Old_fnUnfreeze,
+ ITextDocument2Old_fnBeginEditCollection,
+ ITextDocument2Old_fnEndEditCollection,
+ ITextDocument2Old_fnUndo,
+ ITextDocument2Old_fnRedo,
+ ITextDocument2Old_fnRange,
+ ITextDocument2Old_fnRangeFromPoint,
+ /* ITextDocument2Old methods */
+ ITextDocument2Old_fnAttachMsgFilter,
+ ITextDocument2Old_fnSetEffectColor,
+ ITextDocument2Old_fnGetEffectColor,
+ ITextDocument2Old_fnGetCaretType,
+ ITextDocument2Old_fnSetCaretType,
+ ITextDocument2Old_fnGetImmContext,
+ ITextDocument2Old_fnReleaseImmContext,
+ ITextDocument2Old_fnGetPreferredFont,
+ ITextDocument2Old_fnGetNotificationMode,
+ ITextDocument2Old_fnSetNotificationMode,
+ ITextDocument2Old_fnGetClientRect,
+ ITextDocument2Old_fnGetSelectionEx,
+ ITextDocument2Old_fnGetWindow,
+ ITextDocument2Old_fnGetFEFlags,
+ ITextDocument2Old_fnUpdateWindow,
+ ITextDocument2Old_fnCheckTextLimit,
+ ITextDocument2Old_fnIMEInProgress,
+ ITextDocument2Old_fnSysBeep,
+ ITextDocument2Old_fnUpdate,
+ ITextDocument2Old_fnNotify
};
/* ITextSelection */
@@ -5276,7 +5459,7 @@ LRESULT CreateIRichEditOle(IUnknown *outer_unk, ME_TextEditor *editor, LPVOID *p
reo->IUnknown_inner.lpVtbl = &reo_unk_vtbl;
reo->IRichEditOle_iface.lpVtbl = &revt;
- reo->ITextDocument_iface.lpVtbl = &tdvt;
+ reo->ITextDocument2Old_iface.lpVtbl = &tdvt;
reo->ref = 1;
reo->editor = editor;
reo->txtSel = NULL;
@@ -5509,8 +5692,8 @@ void ME_CopyReObject(REOBJECT *dst, const REOBJECT *src, DWORD flags)
}
}
-void ME_GetITextDocumentInterface(IRichEditOle *iface, LPVOID *ppvObj)
+void ME_GetITextDocument2OldInterface(IRichEditOle *iface, LPVOID *ppvObj)
{
IRichEditOleImpl *This = impl_from_IRichEditOle(iface);
- *ppvObj = &This->ITextDocument_iface;
+ *ppvObj = &This->ITextDocument2Old_iface;
}
diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c
index aaf52bcfdd..0a788982d2 100644
--- a/dlls/riched20/tests/richole.c
+++ b/dlls/riched20/tests/richole.c
@@ -113,10 +113,36 @@ static ULONG get_refcount(IUnknown *iface)
return IUnknown_Release(iface);
}
+#define CHECK_TYPEINFO(disp,expected_riid) _check_typeinfo((IDispatch *)disp, expected_riid, __LINE__)
+static void _check_typeinfo(IDispatch* disp, REFIID expected_riid, int line)
+{
+ ITypeInfo *typeinfo;
+ TYPEATTR *typeattr;
+ UINT count;
+ HRESULT hr;
+
+ count = 10;
+ hr = IDispatch_GetTypeInfoCount(disp, &count);
+ ok_(__FILE__,line)(hr == S_OK, "IDispatch_GetTypeInfoCount failed: 0x%08x.\n", hr);
+ ok_(__FILE__,line)(count == 1, "got wrong count: %u.\n", count);
+
+ hr = IDispatch_GetTypeInfo(disp, 0, LOCALE_SYSTEM_DEFAULT, &typeinfo);
+ ok_(__FILE__,line)(hr == S_OK, "IDispatch_GetTypeInfo failed: 0x%08x.\n", hr);
+
+ hr = ITypeInfo_GetTypeAttr(typeinfo, &typeattr);
+ ok_(__FILE__,line)(hr == S_OK, "ITypeInfo_GetTypeAttr failed: 0x%08x.\n", hr);
+ ok_(__FILE__,line)(IsEqualGUID(&typeattr->guid, expected_riid),
+ "Unexpected type guid: %s.\n", wine_dbgstr_guid(&typeattr->guid));
+
+ ITypeInfo_ReleaseTypeAttr(typeinfo, typeattr);
+ ITypeInfo_Release(typeinfo);
+}
+
static void test_Interfaces(void)
{
IRichEditOle *reOle = NULL, *reOle1 = NULL;
ITextDocument *txtDoc = NULL;
+ ITextDocument2Old *txtDoc2Old = NULL;
ITextSelection *txtSel = NULL, *txtSel2;
IUnknown *punk;
HRESULT hres;
@@ -144,6 +170,7 @@ static void test_Interfaces(void)
(void **) &txtDoc);
ok(hres == S_OK, "IRichEditOle_QueryInterface\n");
ok(txtDoc != NULL, "IRichEditOle_QueryInterface\n");
+ CHECK_TYPEINFO(txtDoc, &IID_ITextDocument);
hres = ITextDocument_GetSelection(txtDoc, NULL);
ok(hres == E_INVALIDARG, "ITextDocument_GetSelection: 0x%x\n", hres);
@@ -195,6 +222,16 @@ static void test_Interfaces(void)
hres = IRichEditOle_QueryInterface(reOle, &IID_IOleInPlaceSite, (void **) &punk);
ok(hres == E_NOINTERFACE, "IRichEditOle_QueryInterface\n");
+ hres = IRichEditOle_QueryInterface(reOle, &IID_ITextDocument2Old, (void **)&txtDoc2Old);
+ ok(hres == S_OK, "IRichEditOle_QueryInterface\n");
+ ok(txtDoc2Old != NULL, "IRichEditOle_QueryInterface\n");
+ ok((ITextDocument *)txtDoc2Old == txtDoc, "interface pointer isn't equal.\n");
+ EXPECT_REF(txtDoc2Old, 5);
+ EXPECT_REF(reOle, 5);
+ CHECK_TYPEINFO(txtDoc2Old, &IID_ITextDocument);
+
+ ITextDocument2Old_Release(txtDoc2Old);
+
ITextDocument_Release(txtDoc);
IRichEditOle_Release(reOle);
refcount = IRichEditOle_Release(reOle);
diff --git a/dlls/riched20/txtsrv.c b/dlls/riched20/txtsrv.c
index ee65621b1d..5ab3322e6b 100644
--- a/dlls/riched20/txtsrv.c
+++ b/dlls/riched20/txtsrv.c
@@ -83,7 +83,7 @@ static HRESULT WINAPI ITextServicesImpl_QueryInterface(IUnknown *iface, REFIID r
if (!CreateIRichEditOle(This->outer_unk, This->editor, (void **)(&This->editor->reOle)))
return E_OUTOFMEMORY;
if (IsEqualIID(riid, &IID_ITextDocument))
- ME_GetITextDocumentInterface(This->editor->reOle, ppv);
+ ME_GetITextDocument2OldInterface(This->editor->reOle, ppv);
else
*ppv = This->editor->reOle;
} else {
--
2.19.0
Sept. 26, 2018
[PATCH v4 1/4] include: Add ITextDocument2Old and ITextDocument2 interface.
by Jactry Zeng
Superseded patch 151082.
Signed-off-by: Jactry Zeng <jzeng(a)codeweavers.com>
---
include/tom.idl | 91 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 91 insertions(+)
diff --git a/include/tom.idl b/include/tom.idl
index 357b0457a5..afc24ca5fb 100644
--- a/include/tom.idl
+++ b/include/tom.idl
@@ -237,6 +237,97 @@ interface ITextDocument : IDispatch
HRESULT RangeFromPoint([in]LONG x, [in]LONG y, [retval, out]ITextRange **ppRange);
}
+[
+ object,
+ uuid(01C25500-4268-11D1-883A-3C8B00C10000)
+]
+interface ITextDocument2Old : ITextDocument
+{
+ HRESULT AttachMsgFilter([in]IUnknown *filter);
+ HRESULT SetEffectColor([in]LONG index, [in]COLORREF cr);
+ HRESULT GetEffectColor([in]LONG index, [out]COLORREF *cr);
+ HRESULT GetCaretType([retval, out]LONG *type);
+ HRESULT SetCaretType([in]LONG type);
+ HRESULT GetImmContext([retval, out]LONG *context);
+ HRESULT ReleaseImmContext([in]LONG context);
+ HRESULT GetPreferredFont([in]LONG cp, [in]LONG codepage, [in]LONG option, [in]LONG current_codepage, [in]LONG current_fontsize,
+ [out]BSTR *bstr, [out]LONG *pitch_family, [out]LONG *new_fontsize);
+ HRESULT GetNotificationMode([retval, out]LONG *mode);
+ HRESULT SetNotificationMode([in]LONG mode);
+ HRESULT GetClientRect([in]LONG type, [out]LONG *left, [out]LONG *top, [out]LONG *right, [out]LONG *bottom);
+ HRESULT GetSelectionEx([retval, out]ITextSelection **selection);
+ HRESULT GetWindow([out]LONG *hwnd);
+ HRESULT GetFEFlags([out]LONG *flags);
+ HRESULT UpdateWindow();
+ HRESULT CheckTextLimit([in]LONG cch, [out]LONG *exceed);
+ HRESULT IMEInProgress([in]LONG mode);
+ HRESULT SysBeep();
+ HRESULT Update([in]LONG mode);
+ HRESULT Notify([in]LONG notify);
+}
+
+interface ITextDisplays;
+interface ITextFont2;
+interface ITextPara2;
+interface ITextRange2;
+interface ITextSelection2;
+interface ITextStory;
+interface ITextStoryRanges2;
+interface ITextStrings;
+
+[
+ object,
+ uuid(c241f5e0-7206-11d8-a2c7-00a0d1d6c6b3)
+]
+interface ITextDocument2 : ITextDocument
+{
+ HRESULT GetCaretType([retval, out]LONG *value);
+ HRESULT SetCaretType([in]LONG value);
+ HRESULT GetDisplays([retval, out]ITextDisplays **displays);
+ HRESULT GetDocumentFont([retval, out]ITextFont2 **font);
+ HRESULT SetDocumentFont([in]ITextFont2 *font);
+ HRESULT GetDocumentPara([retval, out]ITextPara2 **para);
+ HRESULT SetDocumentPara([in]ITextPara2 *para);
+ HRESULT GetEastAsianFlags([retval, out]LONG *flags);
+ HRESULT GetGenerator([retval, out]BSTR *bstr);
+ HRESULT SetIMEInProgress([in]LONG value);
+ HRESULT GetNotificationMode([retval, out]LONG *mode);
+ HRESULT SetNotificationMode([in]LONG mode);
+ HRESULT GetSelection2([retval, out]ITextSelection2 **selection);
+ HRESULT GetStoryRanges2([retval, out]ITextStoryRanges2 **stories);
+ HRESULT GetTypographyOptions([retval, out]LONG *options);
+ HRESULT GetVersion([retval, out]LONG *value);
+ HRESULT GetWindow([retval, out]LONG *hwnd);
+ HRESULT AttachMsgFilter([in]IUnknown *filter);
+ HRESULT CheckTextLimit([in]LONG cch, [out]LONG *exceed);
+ HRESULT GetCallManager([retval, out]IUnknown **manager);
+ HRESULT GetClientRect([in]LONG type, [out]LONG *left, [out]LONG *top, [out]LONG *right, [out]LONG *bottom);
+ HRESULT GetEffectColor([in]LONG index, [out]COLORREF *cr);
+ HRESULT GetImmContext([retval, out]LONG *context);
+ HRESULT GetPreferredFont([in]LONG cp, [in]LONG codepage, [in]LONG option, [in]LONG current_codepage, [in]LONG current_fontsize,
+ [out]BSTR *bstr, [out]LONG *pitch_family, [out]LONG *new_fontsize);
+ HRESULT GetProperty([in]LONG type, [out]LONG *value);
+ HRESULT GetStrings([out]ITextStrings **strings);
+ HRESULT Notify([in]LONG notify);
+ HRESULT Range2([in]LONG cp_active, [in]LONG cp_anchor, [retval, out]ITextRange2 **range);
+ HRESULT RangeFromPoint2([in]LONG x, [in]LONG y, [in]LONG type, [retval, out]ITextRange2 **range);
+ HRESULT ReleaseCallManager([in]IUnknown *manager);
+ HRESULT ReleaseImmContext([in]LONG context);
+ HRESULT SetEffectColor([in]LONG index, [in]LONG value);
+ HRESULT SetProperty([in]LONG type, [in]LONG value);
+ HRESULT SetTypographyOptions([in]LONG options, [in]LONG mask);
+ HRESULT SysBeep();
+ HRESULT Update([in]LONG value);
+ HRESULT UpdateWindow();
+ HRESULT GetMathProperties([out]LONG *options);
+ HRESULT SetMathProperties([in]LONG options, [in]LONG mask);
+ HRESULT GetActiveStory([retval, out]ITextStory **story);
+ HRESULT SetActiveStory([in]ITextStory *story);
+ HRESULT GetMainStory([retval, out]ITextStory **story);
+ HRESULT GetNewStory([retval, out]ITextStory **story);
+ HRESULT GetStory([in]LONG index, [retval, out]ITextStory **story);
+}
+
interface ITextFont;
interface ITextPara;
--
2.19.0
Sept. 26, 2018
[PATCH] testbot/WineSendLog: Fix the reference log path.
by Francois Gouget
Use the same reference logs that JobDetails uses.
$RefFileName was missing a slash anyway.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/bin/WineSendLog.pl | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/testbot/bin/WineSendLog.pl b/testbot/bin/WineSendLog.pl
index 36d47c3a6..bb6dab51a 100755
--- a/testbot/bin/WineSendLog.pl
+++ b/testbot/bin/WineSendLog.pl
@@ -287,7 +287,7 @@ EOF
foreach my $LogName (@{$JobErrors->{$Key}->{LogNames}})
{
my $LogErrors = $JobErrors->{$Key}->{$LogName};
- my $RefFileName = "$DataDir/latest". $StepTask->VM->Name ."_$LogName";
+ my $RefFileName = $StepTask->GetFullFileName($StepTask->VM->Name ."_$LogName");
my ($NewGroups, $NewErrors, $_NewIndices) = GetNewLogErrors($RefFileName, $LogErrors->{Groups}, $LogErrors->{Errors});
if (!$NewGroups)
{
--
2.19.0
Sept. 26, 2018
[PATCH vkd3d v2 6/9] vkd3d: Use heap memory for placed resources.
by Józef Kucia
From: Józef Kucia <jkucia(a)codeweavers.com>
Signed-off-by: Józef Kucia <jkucia(a)codeweavers.com>
---
Version 2: bind -> bound
---
libs/vkd3d/resource.c | 95 ++++++++++++++++++++++++++++++++++++----------
libs/vkd3d/vkd3d_private.h | 1 +
2 files changed, 77 insertions(+), 19 deletions(-)
diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c
index 272fa70585f7..98c703a9313d 100644
--- a/libs/vkd3d/resource.c
+++ b/libs/vkd3d/resource.c
@@ -57,7 +57,7 @@ static unsigned int vkd3d_select_memory_type(struct d3d12_device *device, uint32
static HRESULT vkd3d_allocate_device_memory(struct d3d12_device *device,
const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags,
- const VkMemoryRequirements *memory_requirements, VkDeviceMemory *vk_memory)
+ const VkMemoryRequirements *memory_requirements, VkDeviceMemory *vk_memory, uint32_t *vk_memory_type)
{
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
VkMemoryAllocateInfo allocate_info;
@@ -88,6 +88,9 @@ static HRESULT vkd3d_allocate_device_memory(struct d3d12_device *device,
return hresult_from_vk_result(vr);
}
+ if (vk_memory_type)
+ *vk_memory_type = allocate_info.memoryTypeIndex;
+
return S_OK;
}
@@ -284,7 +287,7 @@ static HRESULT d3d12_heap_init(struct d3d12_heap *heap,
memory_requirements.memoryTypeBits = ~(uint32_t)0;
if (FAILED(hr = vkd3d_allocate_device_memory(device, &heap->desc.Properties,
- heap->desc.Flags, &memory_requirements, &heap->vk_memory)))
+ heap->desc.Flags, &memory_requirements, &heap->vk_memory, &heap->vk_memory_type)))
return hr;
heap->device = device;
@@ -529,7 +532,7 @@ HRESULT vkd3d_allocate_buffer_memory(struct d3d12_device *device, VkBuffer vk_bu
VK_CALL(vkGetBufferMemoryRequirements(device->vk_device, vk_buffer, &memory_requirements));
if (FAILED(hr = vkd3d_allocate_device_memory(device, heap_properties, heap_flags,
- &memory_requirements, vk_memory)))
+ &memory_requirements, vk_memory, NULL)))
return hr;
if ((vr = VK_CALL(vkBindBufferMemory(device->vk_device, vk_buffer, *vk_memory, 0))) < 0)
@@ -554,7 +557,7 @@ static HRESULT vkd3d_allocate_image_memory(struct d3d12_device *device, VkImage
VK_CALL(vkGetImageMemoryRequirements(device->vk_device, vk_image, &memory_requirements));
if (FAILED(hr = vkd3d_allocate_device_memory(device, heap_properties, heap_flags,
- &memory_requirements, vk_memory)))
+ &memory_requirements, vk_memory, NULL)))
return hr;
if ((vr = VK_CALL(vkBindImageMemory(device->vk_device, vk_image, *vk_memory, 0))) < 0)
@@ -1056,6 +1059,22 @@ static HRESULT d3d12_resource_create(struct d3d12_device *device,
return hr;
}
+static HRESULT vkd3d_allocate_resource_memory(
+ struct d3d12_device *device, struct d3d12_resource *resource,
+ const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags)
+{
+ if (d3d12_resource_is_buffer(resource))
+ {
+ return vkd3d_allocate_buffer_memory(device, resource->u.vk_buffer,
+ heap_properties, heap_flags, &resource->vk_memory);
+ }
+ else
+ {
+ return vkd3d_allocate_image_memory(device, resource->u.vk_image,
+ heap_properties, heap_flags, &resource->vk_memory);
+ }
+}
+
HRESULT d3d12_committed_resource_create(struct d3d12_device *device,
const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags,
const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state,
@@ -1068,40 +1087,78 @@ HRESULT d3d12_committed_resource_create(struct d3d12_device *device,
desc, initial_state, optimized_clear_value, &object)))
return hr;
- if (d3d12_resource_is_buffer(object))
+ if (FAILED(hr = vkd3d_allocate_resource_memory(device, object, heap_properties, heap_flags)))
{
- hr = vkd3d_allocate_buffer_memory(device, object->u.vk_buffer,
- heap_properties, heap_flags, &object->vk_memory);
+ d3d12_resource_Release(&object->ID3D12Resource_iface);
+ return hr;
}
+
+ TRACE("Created committed resource %p.\n", object);
+
+ *resource = object;
+
+ return S_OK;
+}
+
+static HRESULT vkd3d_bind_heap_memory(struct d3d12_device *device,
+ struct d3d12_resource *resource, struct d3d12_heap *heap, UINT64 heap_offset)
+{
+ const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+ VkDevice vk_device = device->vk_device;
+ VkMemoryRequirements requirements;
+ VkResult vr;
+
+ if (d3d12_resource_is_buffer(resource))
+ VK_CALL(vkGetBufferMemoryRequirements(vk_device, resource->u.vk_buffer, &requirements));
else
+ VK_CALL(vkGetImageMemoryRequirements(vk_device, resource->u.vk_image, &requirements));
+
+ if (heap_offset % requirements.alignment)
{
- hr = vkd3d_allocate_image_memory(device, object->u.vk_image,
- heap_properties, heap_flags, &object->vk_memory);
+ FIXME("Invalid heap offset %#"PRIx64".\n", heap_offset);
+ return E_INVALIDARG;
}
- if (FAILED(hr))
+ if (!(requirements.memoryTypeBits & (1u << heap->vk_memory_type)))
{
- d3d12_resource_Release(&object->ID3D12Resource_iface);
- return hr;
+ FIXME("Memory type %u cannot be bound to resource %p (allowed types %#x).\n",
+ heap->vk_memory_type, resource, requirements.memoryTypeBits);
+ return E_NOTIMPL;
}
- TRACE("Created committed resource %p.\n", object);
+ if (d3d12_resource_is_buffer(resource))
+ vr = VK_CALL(vkBindBufferMemory(vk_device, resource->u.vk_buffer, heap->vk_memory, heap_offset));
+ else
+ vr = VK_CALL(vkBindImageMemory(vk_device, resource->u.vk_image, heap->vk_memory, heap_offset));
- *resource = object;
+ if (vr < 0)
+ WARN("Failed to bind memory, vr %d.\n", vr);
- return S_OK;
+ return hresult_from_vk_result(vr);
}
HRESULT d3d12_placed_resource_create(struct d3d12_device *device, struct d3d12_heap *heap, UINT64 heap_offset,
const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state,
const D3D12_CLEAR_VALUE *optimized_clear_value, struct d3d12_resource **resource)
{
- const D3D12_HEAP_DESC *heap_desc = &heap->desc;
+ struct d3d12_resource *object;
+ HRESULT hr;
- FIXME("Ignoring heap %p, offset %"PRIu64".\n", heap, heap_offset);
+ if (FAILED(hr = d3d12_resource_create(device, &heap->desc.Properties, heap->desc.Flags,
+ desc, initial_state, optimized_clear_value, &object)))
+ return hr;
- return d3d12_committed_resource_create(device, &heap_desc->Properties, heap_desc->Flags,
- desc, initial_state, optimized_clear_value, resource);
+ if (FAILED(hr = vkd3d_bind_heap_memory(device, object, heap, heap_offset)))
+ {
+ d3d12_resource_Release(&object->ID3D12Resource_iface);
+ return hr;
+ }
+
+ TRACE("Created placed resource %p.\n", object);
+
+ *resource = object;
+
+ return S_OK;
}
HRESULT vkd3d_create_image_resource(ID3D12Device *device,
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h
index 4865671dd0dc..aca0e5098b79 100644
--- a/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/vkd3d_private.h
@@ -191,6 +191,7 @@ struct d3d12_heap
D3D12_HEAP_DESC desc;
VkDeviceMemory vk_memory;
+ uint32_t vk_memory_type;
struct d3d12_device *device;
};
--
2.16.4
Sept. 26, 2018
Re: [PATCH] winhttp: Use the ARRAY_SIZE() macro
by Hans Leidekker
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
Sept. 26, 2018
Re: [PATCH] winhttp: Avoid a variable that holds an ARRAY_SIZE() result
by Hans Leidekker
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
Sept. 26, 2018
[PATCH 6/6] quartz/filtergraph: Check for AM_FILTER_MISC_FLAGS_IS_RENDERER or IMediaSeeking to count renderers.
by Zebediah Figura
Instead of using IPin_QueryInternalConnections().
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/quartz/filtergraph.c | 49 +++++++++++++++++++++++++++++++++++------
dlls/quartz/tests/filtergraph.c | 5 -----
2 files changed, 42 insertions(+), 12 deletions(-)
diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c
index 1857f92..baa5cb1 100644
--- a/dlls/quartz/filtergraph.c
+++ b/dlls/quartz/filtergraph.c
@@ -2118,8 +2118,34 @@ static HRESULT WINAPI MediaControl_Invoke(IMediaControl *iface, DISPID dispIdMem
typedef HRESULT(WINAPI *fnFoundFilter)(IBaseFilter *, DWORD_PTR data);
+static BOOL has_output_pins(IBaseFilter *filter)
+{
+ IEnumPins *enumpins;
+ PIN_DIRECTION dir;
+ IPin *pin;
+
+ if (FAILED(IBaseFilter_EnumPins(filter, &enumpins)))
+ return FALSE;
+
+ while (IEnumPins_Next(enumpins, 1, &pin, NULL) == S_OK)
+ {
+ IPin_QueryDirection(pin, &dir);
+ IPin_Release(pin);
+ if (dir == PINDIR_OUTPUT)
+ {
+ IEnumPins_Release(enumpins);
+ return TRUE;
+ }
+ }
+
+ IEnumPins_Release(enumpins);
+ return FALSE;
+}
+
static HRESULT ExploreGraph(IFilterGraphImpl* pGraph, IPin* pOutputPin, fnFoundFilter FoundFilter, DWORD_PTR data)
{
+ IAMFilterMiscFlags *flags;
+ IMediaSeeking *seeking;
HRESULT hr;
IPin* pInputPin;
IPin** ppPins;
@@ -2142,13 +2168,7 @@ static HRESULT ExploreGraph(IFilterGraphImpl* pGraph, IPin* pOutputPin, fnFoundF
if (SUCCEEDED(hr))
{
- if (nb == 0)
- {
- TRACE("Reached a renderer\n");
- /* Count renderers for end of stream notification */
- pGraph->nRenderers++;
- }
- else
+ if (nb)
{
for(i = 0; i < nb; i++)
{
@@ -2163,6 +2183,21 @@ static HRESULT ExploreGraph(IFilterGraphImpl* pGraph, IPin* pOutputPin, fnFoundF
}
TRACE("Doing stuff with filter %p\n", PinInfo.pFilter);
+ if (SUCCEEDED(IBaseFilter_QueryInterface(PinInfo.pFilter,
+ &IID_IAMFilterMiscFlags, (void **)&flags)))
+ {
+ if (IAMFilterMiscFlags_GetMiscFlags(flags) & AM_FILTER_MISC_FLAGS_IS_RENDERER)
+ pGraph->nRenderers++;
+ IAMFilterMiscFlags_Release(flags);
+ }
+ else if (SUCCEEDED(IBaseFilter_QueryInterface(PinInfo.pFilter,
+ &IID_IMediaSeeking, (void **)&seeking)))
+ {
+ if (!has_output_pins(PinInfo.pFilter))
+ pGraph->nRenderers++;
+ IMediaSeeking_Release(seeking);
+ }
+
FoundFilter(PinInfo.pFilter, data);
}
diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c
index 1345e41..74a3b68 100644
--- a/dlls/quartz/tests/filtergraph.c
+++ b/dlls/quartz/tests/filtergraph.c
@@ -3080,10 +3080,8 @@ static void test_ec_complete(void)
ok(hr == S_OK, "Got hr %#x.\n", hr);
hr = IMediaEvent_GetEvent(eventsrc, &code, ¶m1, ¶m2, 0);
-todo_wine {
ok(hr == S_OK, "Got hr %#x.\n", hr);
ok(code == EC_COMPLETE, "Got code %#x.\n", code);
-}
ok(param1 == S_OK, "Got param1 %#lx.\n", param1);
ok(!param2, "Got param2 %#lx.\n", param2);
hr = IMediaEvent_FreeEventParams(eventsrc, code, param1, param2);
@@ -3096,7 +3094,6 @@ todo_wine {
ok(hr == S_OK, "Got hr %#x.\n", hr);
hr = IMediaEvent_GetEvent(eventsrc, &code, ¶m1, ¶m2, 50);
-todo_wine
ok(hr == E_ABORT, "Got hr %#x.\n", hr);
IMediaControl_Stop(control);
@@ -3156,7 +3153,6 @@ todo_wine
IFilterGraph2_ConnectDirect(graph, &source_pins[0].IPin_iface, &filter1_pin.IPin_iface, NULL);
hr = check_ec_complete(graph, &filter1.IBaseFilter_iface);
-todo_wine
ok(hr == E_ABORT, "Got hr %#x.\n", hr);
IFilterGraph2_RemoveFilter(graph, &filter1.IBaseFilter_iface);
@@ -3185,7 +3181,6 @@ todo_wine
IFilterGraph2_ConnectDirect(graph, &source_pins[0].IPin_iface, &filter1_pin.IPin_iface, NULL);
hr = check_ec_complete(graph, &filter1.IBaseFilter_iface);
-todo_wine
ok(hr == E_ABORT, "Got hr %#x.\n", hr);
IMediaControl_Release(control);
--
2.7.4
Sept. 26, 2018
[PATCH 5/6] quartz/tests/filtergraph: Add some tests for EC_COMPLETE.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/quartz/tests/filtergraph.c | 430 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 430 insertions(+)
diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c
index 6838c02..1345e41 100644
--- a/dlls/quartz/tests/filtergraph.c
+++ b/dlls/quartz/tests/filtergraph.c
@@ -1139,6 +1139,11 @@ struct testfilter
IEnumPins IEnumPins_iface;
struct testpin *pins;
unsigned int pin_count, enum_idx;
+
+ IAMFilterMiscFlags IAMFilterMiscFlags_iface;
+ ULONG misc_flags;
+
+ IMediaSeeking IMediaSeeking_iface;
};
static inline struct testfilter *impl_from_IEnumPins(IEnumPins *iface)
@@ -1234,6 +1239,18 @@ static HRESULT WINAPI testfilter_QueryInterface(IBaseFilter *iface, REFIID iid,
IBaseFilter_AddRef(*out);
return S_OK;
}
+ else if (IsEqualGUID(iid, &IID_IAMFilterMiscFlags) && filter->IAMFilterMiscFlags_iface.lpVtbl)
+ {
+ *out = &filter->IAMFilterMiscFlags_iface;
+ IAMFilterMiscFlags_AddRef(*out);
+ return S_OK;
+ }
+ else if (IsEqualGUID(iid, &IID_IMediaSeeking) && filter->IMediaSeeking_iface.lpVtbl)
+ {
+ *out = &filter->IMediaSeeking_iface;
+ IMediaSeeking_AddRef(*out);
+ return S_OK;
+ }
*out = NULL;
return E_NOINTERFACE;
@@ -1418,6 +1435,195 @@ static const IBaseFilterVtbl testfilter_vtbl =
testfilter_QueryVendorInfo
};
+static struct testfilter *impl_from_IAMFilterMiscFlags(IAMFilterMiscFlags *iface)
+{
+ return CONTAINING_RECORD(iface, struct testfilter, IAMFilterMiscFlags_iface);
+}
+
+static HRESULT WINAPI testmiscflags_QueryInterface(IAMFilterMiscFlags *iface, REFIID iid, void **out)
+{
+ struct testfilter *filter = impl_from_IAMFilterMiscFlags(iface);
+ return IBaseFilter_QueryInterface(&filter->IBaseFilter_iface, iid, out);
+}
+
+static ULONG WINAPI testmiscflags_AddRef(IAMFilterMiscFlags *iface)
+{
+ struct testfilter *filter = impl_from_IAMFilterMiscFlags(iface);
+ return InterlockedIncrement(&filter->ref);
+}
+
+static ULONG WINAPI testmiscflags_Release(IAMFilterMiscFlags *iface)
+{
+ struct testfilter *filter = impl_from_IAMFilterMiscFlags(iface);
+ return InterlockedDecrement(&filter->ref);
+}
+
+static ULONG WINAPI testmiscflags_GetMiscFlags(IAMFilterMiscFlags *iface)
+{
+ struct testfilter *filter = impl_from_IAMFilterMiscFlags(iface);
+ if (winetest_debug > 1) trace("%p->GetMiscFlags()\n", filter);
+ return filter->misc_flags;
+}
+
+static const IAMFilterMiscFlagsVtbl testmiscflags_vtbl =
+{
+ testmiscflags_QueryInterface,
+ testmiscflags_AddRef,
+ testmiscflags_Release,
+ testmiscflags_GetMiscFlags,
+};
+
+static struct testfilter *impl_from_IMediaSeeking(IMediaSeeking *iface)
+{
+ return CONTAINING_RECORD(iface, struct testfilter, IMediaSeeking_iface);
+}
+
+static HRESULT WINAPI testseek_QueryInterface(IMediaSeeking *iface, REFIID iid, void **out)
+{
+ struct testfilter *filter = impl_from_IMediaSeeking(iface);
+ return IBaseFilter_QueryInterface(&filter->IBaseFilter_iface, iid, out);
+}
+
+static ULONG WINAPI testseek_AddRef(IMediaSeeking *iface)
+{
+ struct testfilter *filter = impl_from_IMediaSeeking(iface);
+ return InterlockedIncrement(&filter->ref);
+}
+
+static ULONG WINAPI testseek_Release(IMediaSeeking *iface)
+{
+ struct testfilter *filter = impl_from_IMediaSeeking(iface);
+ return InterlockedDecrement(&filter->ref);
+}
+
+static HRESULT WINAPI testseek_GetCapabilities(IMediaSeeking *iface, DWORD *caps)
+{
+ if (winetest_debug > 1) trace("%p->GetCapabilities()\n", iface);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testseek_CheckCapabilities(IMediaSeeking *iface, DWORD *caps)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testseek_IsFormatSupported(IMediaSeeking *iface, const GUID *format)
+{
+ if (winetest_debug > 1) trace("%p->IsFormatSupported(%s)\n", iface, wine_dbgstr_guid(format));
+ return S_OK;
+}
+
+static HRESULT WINAPI testseek_QueryPreferredFormat(IMediaSeeking *iface, GUID *format)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testseek_GetTimeFormat(IMediaSeeking *iface, GUID *format)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testseek_IsUsingTimeFormat(IMediaSeeking *iface, const GUID *format)
+{
+ if (winetest_debug > 1) trace("%p->IsUsingTimeFormat(%s)\n", iface, wine_dbgstr_guid(format));
+ return S_FALSE;
+}
+
+static HRESULT WINAPI testseek_SetTimeFormat(IMediaSeeking *iface, const GUID *format)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testseek_GetDuration(IMediaSeeking *iface, LONGLONG *duration)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testseek_GetStopPosition(IMediaSeeking *iface, LONGLONG *stop)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testseek_GetCurrentPosition(IMediaSeeking *iface, LONGLONG *current)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testseek_ConvertTimeFormat(IMediaSeeking *iface, LONGLONG *target,
+ const GUID *target_format, LONGLONG source, const GUID *source_format)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testseek_SetPositions(IMediaSeeking *iface, LONGLONG *current,
+ DWORD current_flags, LONGLONG *stop, DWORD stop_flags )
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testseek_GetPositions(IMediaSeeking *iface, LONGLONG *current, LONGLONG *stop)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testseek_GetAvailable(IMediaSeeking *iface, LONGLONG *earliest, LONGLONG *latest)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testseek_SetRate(IMediaSeeking *iface, double rate)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testseek_GetRate(IMediaSeeking *iface, double *rate)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testseek_GetPreroll(IMediaSeeking *iface, LONGLONG *preroll)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static const IMediaSeekingVtbl testseek_vtbl =
+{
+ testseek_QueryInterface,
+ testseek_AddRef,
+ testseek_Release,
+ testseek_GetCapabilities,
+ testseek_CheckCapabilities,
+ testseek_IsFormatSupported,
+ testseek_QueryPreferredFormat,
+ testseek_GetTimeFormat,
+ testseek_IsUsingTimeFormat,
+ testseek_SetTimeFormat,
+ testseek_GetDuration,
+ testseek_GetStopPosition,
+ testseek_GetCurrentPosition,
+ testseek_ConvertTimeFormat,
+ testseek_SetPositions,
+ testseek_GetPositions,
+ testseek_GetAvailable,
+ testseek_SetRate,
+ testseek_GetRate,
+ testseek_GetPreroll,
+};
+
struct testfilter_cf
{
IClassFactory IClassFactory_iface;
@@ -2769,6 +2975,229 @@ todo_wine
ok(sink.state == State_Stopped, "Got state %u.\n", sink.state);
}
+/* Helper function to check whether a filter is considered a renderer, i.e.
+ * whether its EC_COMPLETE notification will be passed on to the application. */
+static HRESULT check_ec_complete(IFilterGraph2 *graph, IBaseFilter *filter)
+{
+ IMediaEventSink *eventsink;
+ LONG_PTR param1, param2;
+ IMediaControl *control;
+ IMediaEvent *eventsrc;
+ HRESULT hr, ret_hr;
+ LONG code;
+
+ IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
+ IFilterGraph2_QueryInterface(graph, &IID_IMediaEvent, (void **)&eventsrc);
+ IFilterGraph2_QueryInterface(graph, &IID_IMediaEventSink, (void **)&eventsink);
+
+ IMediaControl_Run(control);
+
+ hr = IMediaEvent_GetEvent(eventsrc, &code, ¶m1, ¶m2, 0);
+ ok(hr == E_ABORT, "Got hr %#x.\n", hr);
+
+ hr = IMediaEventSink_Notify(eventsink, EC_COMPLETE, S_OK, (LONG_PTR)filter);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ ret_hr = IMediaEvent_GetEvent(eventsrc, &code, ¶m1, ¶m2, 0);
+ if (ret_hr == S_OK)
+ {
+ ok(code == EC_COMPLETE, "Got code %#x.\n", code);
+ ok(param1 == S_OK, "Got param1 %#lx.\n", param1);
+ ok(!param2, "Got param2 %#lx.\n", param2);
+ hr = IMediaEvent_FreeEventParams(eventsrc, code, param1, param2);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaEvent_GetEvent(eventsrc, &code, ¶m1, ¶m2, 0);
+ ok(hr == E_ABORT, "Got hr %#x.\n", hr);
+ }
+
+ IMediaControl_Stop(control);
+
+ IMediaControl_Release(control);
+ IMediaEvent_Release(eventsrc);
+ IMediaEventSink_Release(eventsink);
+ return ret_hr;
+}
+
+static void test_ec_complete(void)
+{
+ struct testpin filter1_pin, filter2_pin, filter3_pin, source_pins[3];
+ struct testfilter filter1, filter2, filter3, source;
+
+ IFilterGraph2 *graph = create_graph();
+ IMediaEventSink *eventsink;
+ LONG_PTR param1, param2;
+ IMediaControl *control;
+ IMediaEvent *eventsrc;
+ HRESULT hr;
+ LONG code;
+
+ testsink_init(&filter1_pin);
+ testsink_init(&filter2_pin);
+ testsink_init(&filter3_pin);
+ testfilter_init(&filter1, &filter1_pin, 1);
+ testfilter_init(&filter2, &filter2_pin, 1);
+ testfilter_init(&filter3, &filter3_pin, 1);
+ testsource_init(&source_pins[0], NULL, 0);
+ testsource_init(&source_pins[1], NULL, 0);
+ testsource_init(&source_pins[2], NULL, 0);
+ testfilter_init(&source, source_pins, 3);
+
+ filter1.IAMFilterMiscFlags_iface.lpVtbl = &testmiscflags_vtbl;
+ filter2.IAMFilterMiscFlags_iface.lpVtbl = &testmiscflags_vtbl;
+ filter1.misc_flags = filter2.misc_flags = AM_FILTER_MISC_FLAGS_IS_RENDERER;
+
+ IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
+ IFilterGraph2_QueryInterface(graph, &IID_IMediaEvent, (void **)&eventsrc);
+ IFilterGraph2_QueryInterface(graph, &IID_IMediaEventSink, (void **)&eventsink);
+
+ IFilterGraph2_AddFilter(graph, &filter1.IBaseFilter_iface, NULL);
+ IFilterGraph2_AddFilter(graph, &filter2.IBaseFilter_iface, NULL);
+ IFilterGraph2_AddFilter(graph, &filter3.IBaseFilter_iface, NULL);
+ IFilterGraph2_AddFilter(graph, &source.IBaseFilter_iface, NULL);
+ IFilterGraph2_ConnectDirect(graph, &source_pins[0].IPin_iface, &filter1_pin.IPin_iface, NULL);
+ IFilterGraph2_ConnectDirect(graph, &source_pins[1].IPin_iface, &filter2_pin.IPin_iface, NULL);
+ IFilterGraph2_ConnectDirect(graph, &source_pins[2].IPin_iface, &filter3_pin.IPin_iface, NULL);
+
+ /* EC_COMPLETE is only delivered to the user after all renderers deliver it. */
+
+ IMediaControl_Run(control);
+
+ while ((hr = IMediaEvent_GetEvent(eventsrc, &code, ¶m1, ¶m2, 0)) == S_OK)
+ {
+ ok(code != EC_COMPLETE, "Got unexpected EC_COMPLETE.\n");
+ IMediaEvent_FreeEventParams(eventsrc, code, param1, param2);
+ }
+ ok(hr == E_ABORT, "Got hr %#x.\n", hr);
+
+ hr = IMediaEventSink_Notify(eventsink, EC_COMPLETE, S_OK, (LONG_PTR)&filter1.IBaseFilter_iface);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaEvent_GetEvent(eventsrc, &code, ¶m1, ¶m2, 50);
+ ok(hr == E_ABORT, "Got hr %#x.\n", hr);
+
+ hr = IMediaEventSink_Notify(eventsink, EC_COMPLETE, S_OK, (LONG_PTR)&filter2.IBaseFilter_iface);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaEvent_GetEvent(eventsrc, &code, ¶m1, ¶m2, 0);
+todo_wine {
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(code == EC_COMPLETE, "Got code %#x.\n", code);
+}
+ ok(param1 == S_OK, "Got param1 %#lx.\n", param1);
+ ok(!param2, "Got param2 %#lx.\n", param2);
+ hr = IMediaEvent_FreeEventParams(eventsrc, code, param1, param2);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaEvent_GetEvent(eventsrc, &code, ¶m1, ¶m2, 50);
+ ok(hr == E_ABORT, "Got hr %#x.\n", hr);
+
+ hr = IMediaEventSink_Notify(eventsink, EC_COMPLETE, S_OK, (LONG_PTR)&filter3.IBaseFilter_iface);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaEvent_GetEvent(eventsrc, &code, ¶m1, ¶m2, 50);
+todo_wine
+ ok(hr == E_ABORT, "Got hr %#x.\n", hr);
+
+ IMediaControl_Stop(control);
+
+ /* Test CancelDefaultHandling(). */
+
+ IMediaControl_Run(control);
+
+ hr = IMediaEvent_CancelDefaultHandling(eventsrc, EC_COMPLETE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaEvent_GetEvent(eventsrc, &code, ¶m1, ¶m2, 50);
+ ok(hr == E_ABORT, "Got hr %#x.\n", hr);
+
+ hr = IMediaEventSink_Notify(eventsink, EC_COMPLETE, S_OK, (LONG_PTR)&filter1.IBaseFilter_iface);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaEvent_GetEvent(eventsrc, &code, ¶m1, ¶m2, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(code == EC_COMPLETE, "Got code %#x.\n", code);
+ ok(param1 == S_OK, "Got param1 %#lx.\n", param1);
+ ok(param2 == (LONG_PTR)&filter1.IBaseFilter_iface, "Got param2 %#lx.\n", param2);
+ hr = IMediaEvent_FreeEventParams(eventsrc, code, param1, param2);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaEvent_GetEvent(eventsrc, &code, ¶m1, ¶m2, 50);
+ ok(hr == E_ABORT, "Got hr %#x.\n", hr);
+
+ hr = IMediaEventSink_Notify(eventsink, EC_COMPLETE, S_OK, (LONG_PTR)&filter3.IBaseFilter_iface);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaEvent_GetEvent(eventsrc, &code, ¶m1, ¶m2, 0);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(code == EC_COMPLETE, "Got code %#x.\n", code);
+ ok(param1 == S_OK, "Got param1 %#lx.\n", param1);
+ ok(param2 == (LONG_PTR)&filter3.IBaseFilter_iface, "Got param2 %#lx.\n", param2);
+ hr = IMediaEvent_FreeEventParams(eventsrc, code, param1, param2);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaEvent_GetEvent(eventsrc, &code, ¶m1, ¶m2, 50);
+ ok(hr == E_ABORT, "Got hr %#x.\n", hr);
+
+ IMediaControl_Stop(control);
+ hr = IMediaEvent_RestoreDefaultHandling(eventsrc, EC_COMPLETE);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ /* A filter counts as a renderer if it (1) exposes IAMFilterMiscFlags and
+ * reports itself as a renderer, or (2) exposes IMediaSeeking and has no
+ * output pins. Despite MSDN, QueryInternalConnections() does not seem to
+ * be used. */
+
+ IFilterGraph2_RemoveFilter(graph, &filter1.IBaseFilter_iface);
+ IFilterGraph2_RemoveFilter(graph, &filter2.IBaseFilter_iface);
+ IFilterGraph2_RemoveFilter(graph, &filter3.IBaseFilter_iface);
+ filter1.misc_flags = 0;
+ IFilterGraph2_AddFilter(graph, &filter1.IBaseFilter_iface, NULL);
+ IFilterGraph2_ConnectDirect(graph, &source_pins[0].IPin_iface, &filter1_pin.IPin_iface, NULL);
+
+ hr = check_ec_complete(graph, &filter1.IBaseFilter_iface);
+todo_wine
+ ok(hr == E_ABORT, "Got hr %#x.\n", hr);
+
+ IFilterGraph2_RemoveFilter(graph, &filter1.IBaseFilter_iface);
+ filter1_pin.dir = PINDIR_INPUT;
+ filter1.IAMFilterMiscFlags_iface.lpVtbl = NULL;
+ filter1.IMediaSeeking_iface.lpVtbl = &testseek_vtbl;
+ IFilterGraph2_AddFilter(graph, &filter1.IBaseFilter_iface, NULL);
+ IFilterGraph2_ConnectDirect(graph, &source_pins[0].IPin_iface, &filter1_pin.IPin_iface, NULL);
+
+ hr = check_ec_complete(graph, &filter1.IBaseFilter_iface);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ IFilterGraph2_RemoveFilter(graph, &filter1.IBaseFilter_iface);
+ filter1_pin.dir = PINDIR_OUTPUT;
+ IFilterGraph2_AddFilter(graph, &filter1.IBaseFilter_iface, NULL);
+
+ hr = check_ec_complete(graph, &filter1.IBaseFilter_iface);
+ ok(hr == E_ABORT, "Got hr %#x.\n", hr);
+
+ IFilterGraph2_RemoveFilter(graph, &filter1.IBaseFilter_iface);
+ filter1.IMediaSeeking_iface.lpVtbl = NULL;
+ filter1_pin.dir = PINDIR_INPUT;
+ filter1.pin_count = 1;
+ filter1_pin.QueryInternalConnections_hr = S_OK;
+ IFilterGraph2_AddFilter(graph, &filter1.IBaseFilter_iface, NULL);
+ IFilterGraph2_ConnectDirect(graph, &source_pins[0].IPin_iface, &filter1_pin.IPin_iface, NULL);
+
+ hr = check_ec_complete(graph, &filter1.IBaseFilter_iface);
+todo_wine
+ ok(hr == E_ABORT, "Got hr %#x.\n", hr);
+
+ IMediaControl_Release(control);
+ IMediaEvent_Release(eventsrc);
+ IMediaEventSink_Release(eventsink);
+ hr = IFilterGraph2_Release(graph);
+ ok(!hr, "Got outstanding refcount %d.\n", hr);
+ ok(filter1.ref == 1, "Got outstanding refcount %d.\n", filter1.ref);
+ ok(filter2.ref == 1, "Got outstanding refcount %d.\n", filter2.ref);
+ ok(filter3.ref == 1, "Got outstanding refcount %d.\n", filter3.ref);
+}
+
START_TEST(filtergraph)
{
CoInitializeEx(NULL, COINIT_MULTITHREADED);
@@ -2785,6 +3214,7 @@ START_TEST(filtergraph)
test_connect_direct();
test_sync_source();
test_filter_state();
+ test_ec_complete();
CoUninitialize();
test_render_with_multithread();
--
2.7.4
Sept. 26, 2018
[PATCH 4/6] quartz/filtergraph: Implement IMediaControl state functions on top of IMediaFilter.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/quartz/filtergraph.c | 211 ++++++++++++++++++++--------------------
dlls/quartz/tests/filtergraph.c | 2 -
2 files changed, 108 insertions(+), 105 deletions(-)
diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c
index e721388..1857f92 100644
--- a/dlls/quartz/filtergraph.c
+++ b/dlls/quartz/filtergraph.c
@@ -2262,114 +2262,34 @@ static HRESULT SendFilterMessage(IFilterGraphImpl *This, fnFoundFilter FoundFilt
return S_FALSE;
}
-/*** IMediaControl methods ***/
static HRESULT WINAPI MediaControl_Run(IMediaControl *iface)
{
- IFilterGraphImpl *This = impl_from_IMediaControl(iface);
+ IFilterGraphImpl *graph = impl_from_IMediaControl(iface);
- TRACE("(%p/%p)->()\n", This, iface);
-
- EnterCriticalSection(&This->cs);
- if (This->state == State_Running)
- goto out;
- This->EcCompleteCount = 0;
-
- if (This->defaultclock && !This->refClock)
- IFilterGraph2_SetDefaultSyncSource(&This->IFilterGraph2_iface);
-
- if (This->refClock)
- {
- REFERENCE_TIME now;
- IReferenceClock_GetTime(This->refClock, &now);
- if (This->state == State_Stopped)
- This->start_time = now + 500000;
- else if (This->pause_time >= 0)
- This->start_time += now - This->pause_time;
- else
- This->start_time = now;
- }
- else This->start_time = 0;
-
- SendFilterMessage(This, SendRun, (DWORD_PTR)&This->start_time);
- This->state = State_Running;
-out:
- LeaveCriticalSection(&This->cs);
- return S_FALSE;
+ return IMediaFilter_Run(&graph->IMediaFilter_iface, 0);
}
static HRESULT WINAPI MediaControl_Pause(IMediaControl *iface)
{
- IFilterGraphImpl *This = impl_from_IMediaControl(iface);
+ IFilterGraphImpl *graph = impl_from_IMediaControl(iface);
- TRACE("(%p/%p)->()\n", This, iface);
-
- EnterCriticalSection(&This->cs);
- if (This->state == State_Paused)
- goto out;
-
- if (This->defaultclock && !This->refClock)
- IFilterGraph2_SetDefaultSyncSource(&This->IFilterGraph2_iface);
-
- if (This->state == State_Running && This->refClock && This->start_time >= 0)
- IReferenceClock_GetTime(This->refClock, &This->pause_time);
- else
- This->pause_time = -1;
-
- SendFilterMessage(This, SendPause, 0);
- This->state = State_Paused;
-out:
- LeaveCriticalSection(&This->cs);
- return S_FALSE;
+ return IMediaFilter_Pause(&graph->IMediaFilter_iface);
}
static HRESULT WINAPI MediaControl_Stop(IMediaControl *iface)
{
- IFilterGraphImpl *This = impl_from_IMediaControl(iface);
+ IFilterGraphImpl *graph = impl_from_IMediaControl(iface);
- TRACE("(%p/%p)->()\n", This, iface);
-
- if (This->state == State_Stopped) return S_OK;
-
- EnterCriticalSection(&This->cs);
- if (This->state == State_Running) SendFilterMessage(This, SendPause, 0);
- SendFilterMessage(This, SendStop, 0);
- This->state = State_Stopped;
- LeaveCriticalSection(&This->cs);
- return S_OK;
+ return IMediaFilter_Stop(&graph->IMediaFilter_iface);
}
-static HRESULT WINAPI MediaControl_GetState(IMediaControl *iface, LONG msTimeout,
- OAFilterState *pfs)
+static HRESULT WINAPI MediaControl_GetState(IMediaControl *iface, LONG timeout, OAFilterState *state)
{
- IFilterGraphImpl *This = impl_from_IMediaControl(iface);
- DWORD end;
+ IFilterGraphImpl *graph = impl_from_IMediaControl(iface);
- TRACE("(%p/%p)->(%d, %p)\n", This, iface, msTimeout, pfs);
+ if (timeout < 0) timeout = INFINITE;
- if (!pfs)
- return E_POINTER;
-
- EnterCriticalSection(&This->cs);
-
- *pfs = This->state;
- if (msTimeout > 0)
- {
- end = GetTickCount() + msTimeout;
- }
- else if (msTimeout < 0)
- {
- end = INFINITE;
- }
- else
- {
- end = 0;
- }
- if (end)
- SendFilterMessage(This, SendGetState, end);
-
- LeaveCriticalSection(&This->cs);
-
- return S_OK;
+ return IMediaFilter_GetState(&graph->IMediaFilter_iface, timeout, (FILTER_STATE *)state);
}
static HRESULT WINAPI MediaControl_RenderFile(IMediaControl *iface, BSTR strFilename)
@@ -5488,34 +5408,119 @@ static HRESULT WINAPI MediaFilter_GetClassID(IMediaFilter *iface, CLSID * pClass
static HRESULT WINAPI MediaFilter_Stop(IMediaFilter *iface)
{
- IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
+ IFilterGraphImpl *graph = impl_from_IMediaFilter(iface);
- return MediaControl_Stop(&This->IMediaControl_iface);
+ TRACE("graph %p.\n", graph);
+
+ EnterCriticalSection(&graph->cs);
+
+ if (graph->state == State_Stopped)
+ {
+ LeaveCriticalSection(&graph->cs);
+ return S_OK;
+ }
+
+ if (graph->state == State_Running)
+ SendFilterMessage(graph, SendPause, 0);
+ SendFilterMessage(graph, SendStop, 0);
+ graph->state = State_Stopped;
+
+ LeaveCriticalSection(&graph->cs);
+ return S_OK;
}
static HRESULT WINAPI MediaFilter_Pause(IMediaFilter *iface)
{
- IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
+ IFilterGraphImpl *graph = impl_from_IMediaFilter(iface);
- return MediaControl_Pause(&This->IMediaControl_iface);
+ TRACE("graph %p.\n", graph);
+
+ EnterCriticalSection(&graph->cs);
+
+ if (graph->state == State_Paused)
+ {
+ LeaveCriticalSection(&graph->cs);
+ return S_OK;
+ }
+
+ if (graph->defaultclock && !graph->refClock)
+ IFilterGraph2_SetDefaultSyncSource(&graph->IFilterGraph2_iface);
+
+ if (graph->state == State_Running && graph->refClock && graph->start_time >= 0)
+ IReferenceClock_GetTime(graph->refClock, &graph->pause_time);
+ else
+ graph->pause_time = -1;
+
+ SendFilterMessage(graph, SendPause, 0);
+ graph->state = State_Paused;
+
+ LeaveCriticalSection(&graph->cs);
+ return S_FALSE;
}
-static HRESULT WINAPI MediaFilter_Run(IMediaFilter *iface, REFERENCE_TIME tStart)
+static HRESULT WINAPI MediaFilter_Run(IMediaFilter *iface, REFERENCE_TIME start)
{
- IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
+ IFilterGraphImpl *graph = impl_from_IMediaFilter(iface);
- if (tStart)
- FIXME("Run called with non-null tStart: %s\n", wine_dbgstr_longlong(tStart));
+ TRACE("graph %p, start %s.\n", graph, wine_dbgstr_longlong(start));
- return MediaControl_Run(&This->IMediaControl_iface);
+ EnterCriticalSection(&graph->cs);
+
+ if (graph->state == State_Running)
+ {
+ LeaveCriticalSection(&graph->cs);
+ return S_OK;
+ }
+ graph->EcCompleteCount = 0;
+
+ if (graph->defaultclock && !graph->refClock)
+ IFilterGraph2_SetDefaultSyncSource(&graph->IFilterGraph2_iface);
+
+ if (!start && graph->refClock)
+ {
+ REFERENCE_TIME now;
+ IReferenceClock_GetTime(graph->refClock, &now);
+ if (graph->state == State_Stopped)
+ graph->start_time = now + 500000;
+ else if (graph->pause_time >= 0)
+ graph->start_time += now - graph->pause_time;
+ else
+ graph->start_time = now;
+ }
+ else
+ graph->start_time = start;
+
+ SendFilterMessage(graph, SendRun, (DWORD_PTR)&graph->start_time);
+ graph->state = State_Running;
+
+ LeaveCriticalSection(&graph->cs);
+ return S_FALSE;
}
-static HRESULT WINAPI MediaFilter_GetState(IMediaFilter *iface, DWORD dwMsTimeout,
- FILTER_STATE *pState)
+static HRESULT WINAPI MediaFilter_GetState(IMediaFilter *iface, DWORD timeout, FILTER_STATE *state)
{
- IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
+ IFilterGraphImpl *graph = impl_from_IMediaFilter(iface);
+ DWORD end;
- return MediaControl_GetState(&This->IMediaControl_iface, dwMsTimeout, (OAFilterState*)pState);
+ TRACE("graph %p, timeout %u, state %p.\n", graph, timeout, state);
+
+ if (!state)
+ return E_POINTER;
+
+ EnterCriticalSection(&graph->cs);
+
+ *state = graph->state;
+ if (timeout > 0)
+ end = GetTickCount() + timeout;
+ else if (timeout == INFINITE)
+ end = INFINITE;
+ else
+ end = 0;
+ if (end)
+ SendFilterMessage(graph, SendGetState, end);
+
+ LeaveCriticalSection(&graph->cs);
+ return S_OK;
}
static HRESULT WINAPI MediaFilter_SetSyncSource(IMediaFilter *iface, IReferenceClock *pClock)
diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c
index 8dc7341..6838c02 100644
--- a/dlls/quartz/tests/filtergraph.c
+++ b/dlls/quartz/tests/filtergraph.c
@@ -2698,10 +2698,8 @@ todo_wine
todo_wine
ok(hr == S_OK, "Got hr %#x.\n", hr);
check_filter_state(graph, State_Running);
-todo_wine {
ok(source.start_time == 0xdeadbeef, "Got time %s.\n", wine_dbgstr_longlong(source.start_time));
ok(sink.start_time == 0xdeadbeef, "Got time %s.\n", wine_dbgstr_longlong(sink.start_time));
-}
hr = IMediaFilter_Pause(filter);
todo_wine
--
2.7.4
Sept. 26, 2018