Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- include/mfidl.idl | 52 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+)
diff --git a/include/mfidl.idl b/include/mfidl.idl index 04a6d71bf9..630dc6120d 100644 --- a/include/mfidl.idl +++ b/include/mfidl.idl @@ -183,6 +183,58 @@ interface IMFMediaSession : IMFMediaEventGenerator HRESULT GetFullTopology([in] DWORD flags, [in] TOPOID id, [out] IMFTopology **topology); }
+[ + object, + uuid(bb420aa4-765b-4a1f-91fe-d6a8a143924c), + local +] +interface IMFByteStreamHandler : IUnknown +{ + HRESULT BeginCreateObject( + [in] IMFByteStream *stream, + [in] const WCHAR *url, + [in] DWORD flags, + [in] IPropertyStore *props, + [out] IUnknown **cancel_cookie, + [in] IMFAsyncCallback *callback, + [in] IUnknown *state); + + HRESULT EndCreateObject( + [in] IMFAsyncResult *result, + [out] MF_OBJECT_TYPE *obj_type, + [out] IUnknown **object); + + HRESULT CancelObjectCreation( + [in] IUnknown *cancel_cookie); + + HRESULT GetMaxNumberOfBytesRequiredForResolution( + [out] QWORD *bytes); +} + +[ + object, + uuid(6d4c7b74-52a0-4bb7-b0db-55f29f47a668), + local +] +interface IMFSchemeHandler : IUnknown +{ + HRESULT BeginCreateObject( + [in] const WCHAR *url, + [in] DWORD flags, + [in] IPropertyStore *props, + [out] IUnknown **cancel_cookie, + [in] IMFAsyncCallback *callback, + [in] IUnknown *state); + + HRESULT EndCreateObject( + [in] IMFAsyncResult *result, + [out] MF_OBJECT_TYPE *obj_type, + [out] IUnknown **object); + + HRESULT CancelObjectCreation( + [in] IUnknown *cancel_cookie); +} + [ object, uuid(fbe5a32d-a497-4b61-bb85-97b1a848a6e3)
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/queue.c | 2 ++ dlls/mfplat/tests/mfplat.c | 67 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+)
diff --git a/dlls/mfplat/queue.c b/dlls/mfplat/queue.c index 408526fec0..66f8588f82 100644 --- a/dlls/mfplat/queue.c +++ b/dlls/mfplat/queue.c @@ -649,6 +649,8 @@ static ULONG WINAPI async_result_Release(IMFAsyncResult *iface) IUnknown_Release(result->object); if (result->state) IUnknown_Release(result->state); + if (result->result.hEvent) + CloseHandle(result->result.hEvent); heap_free(result);
MFUnlockPlatform(); diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index 1bf7ebb41e..278112a9c5 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -907,7 +907,10 @@ static void test_MFCreateAsyncResult(void) IUnknown *state, *object; MFASYNCRESULT *data; ULONG refcount; + HANDLE event; + DWORD flags; HRESULT hr; + BOOL ret;
init_test_callback(&callback);
@@ -994,6 +997,35 @@ static void test_MFCreateAsyncResult(void) ok(!refcount, "Unexpected refcount %u\n.", refcount); refcount = IMFAsyncResult_Release(result); ok(!refcount, "Unexpected refcount %u\n.", refcount); + + /* Event handle is closed on release. */ + hr = MFCreateAsyncResult(NULL, NULL, NULL, &result); + ok(hr == S_OK, "Failed to create object, hr %#x.\n", hr); + + data = (MFASYNCRESULT *)result; + data->hEvent = event = CreateEventA(NULL, FALSE, FALSE, NULL); + ok(data->hEvent != NULL, "Failed to create event.\n"); + ret = GetHandleInformation(event, &flags); + ok(ret, "Failed to get handle info.\n"); + + refcount = IMFAsyncResult_Release(result); + ok(!refcount, "Unexpected refcount %u\n.", refcount); + ret = GetHandleInformation(event, &flags); + ok(!ret, "Expected handle to be closed.\n"); + + hr = MFCreateAsyncResult(NULL, &callback.IMFAsyncCallback_iface, NULL, &result); + ok(hr == S_OK, "Failed to create object, hr %#x.\n", hr); + + data = (MFASYNCRESULT *)result; + data->hEvent = event = CreateEventA(NULL, FALSE, FALSE, NULL); + ok(data->hEvent != NULL, "Failed to create event.\n"); + ret = GetHandleInformation(event, &flags); + ok(ret, "Failed to get handle info.\n"); + + refcount = IMFAsyncResult_Release(result); + ok(!refcount, "Unexpected refcount %u\n.", refcount); + ret = GetHandleInformation(event, &flags); + ok(!ret, "Expected handle to be closed.\n"); }
static void test_startup(void) @@ -1696,6 +1728,40 @@ static void test_system_time_source(void) IMFPresentationTimeSource_Release(time_source); }
+static void test_MFInvokeCallback(void) +{ + struct test_callback callback; + IMFAsyncResult *result; + MFASYNCRESULT *data; + ULONG refcount; + HRESULT hr; + DWORD ret; + + hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); + ok(hr == S_OK, "Failed to start up, hr %#x.\n", hr); + + init_test_callback(&callback); + + hr = MFCreateAsyncResult(NULL, &callback.IMFAsyncCallback_iface, NULL, &result); + ok(hr == S_OK, "Failed to create object, hr %#x.\n", hr); + + data = (MFASYNCRESULT *)result; + data->hEvent = CreateEventA(NULL, FALSE, FALSE, NULL); + ok(data->hEvent != NULL, "Failed to create event.\n"); + + hr = MFInvokeCallback(result); + ok(hr == S_OK, "Failed to invoke, hr %#x.\n", hr); + + ret = WaitForSingleObject(data->hEvent, 100); + ok(ret == WAIT_TIMEOUT, "Expected timeout, ret %#x.\n", ret); + + refcount = IMFAsyncResult_Release(result); + ok(!refcount, "Unexpected refcount %u\n.", refcount); + + hr = MFShutdown(); + ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr); +} + START_TEST(mfplat) { CoInitialize(NULL); @@ -1723,6 +1789,7 @@ START_TEST(mfplat) test_event_queue(); test_presentation_descriptor(); test_system_time_source(); + test_MFInvokeCallback();
CoUninitialize(); }
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=49077
Your paranoid android.
=== wxppro (32 bit report) ===
mfplat: 0b40:mfplat: unhandled exception c0000005 at 2F2E2E2F
=== debian9 (64 bit WoW report) ===
mfplat: mfplat.c:1759: Test failed: Unexpected refcount 1
Report errors: mfplat:mfplat crashed (c0000005)
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/main.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index 6bec41884e..7a8361f858 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -2088,7 +2088,7 @@ HRESULT WINAPI MFCreateSourceResolver(IMFSourceResolver **resolver) return S_OK; }
-typedef struct _mfmediaevent +typedef struct media_event { mfattributes attributes; IMFMediaEvent IMFMediaEvent_iface; @@ -2139,14 +2139,15 @@ static ULONG WINAPI mfmediaevent_AddRef(IMFMediaEvent *iface)
static ULONG WINAPI mfmediaevent_Release(IMFMediaEvent *iface) { - mfmediaevent *This = impl_from_IMFMediaEvent(iface); - ULONG ref = InterlockedDecrement(&This->attributes.ref); + struct media_event *event = impl_from_IMFMediaEvent(iface); + ULONG ref = InterlockedDecrement(&event->attributes.ref);
- TRACE("(%p) ref=%u\n", This, ref); + TRACE("(%p) ref=%u\n", iface, ref);
if (!ref) { - HeapFree(GetProcessHeap(), 0, This); + PropVariantClear(&event->value); + heap_free(event); }
return ref;
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=49078
Your paranoid android.
=== debian9 (32 bit Chinese:China report) ===
mfplat: mfplat.c:1759: Test failed: Unexpected refcount 1
Report errors: mfplat:mfplat crashed (c0000005)
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- include/mferror.h | 137 +++++++++++++++++++++++++--------------------- 1 file changed, 74 insertions(+), 63 deletions(-)
diff --git a/include/mferror.h b/include/mferror.h index f7f0934d6c..17a006c96d 100644 --- a/include/mferror.h +++ b/include/mferror.h @@ -19,70 +19,81 @@ #ifndef __WINE_MFERROR_H #define __WINE_MFERROR_H
-#define MF_E_PLATFORM_NOT_INITIALIZED _HRESULT_TYPEDEF_(0xc00d36b0) -#define MF_E_BUFFERTOOSMALL _HRESULT_TYPEDEF_(0xc00d36b1) -#define MF_E_INVALIDREQUEST _HRESULT_TYPEDEF_(0xc00d36b2) -#define MF_E_INVALIDSTREAMNUMBER _HRESULT_TYPEDEF_(0xc00d36b3) -#define MF_E_INVALIDMEDIATYPE _HRESULT_TYPEDEF_(0xc00d36b4) -#define MF_E_NOTACCEPTING _HRESULT_TYPEDEF_(0xc00d36b5) -#define MF_E_NOT_INITIALIZED _HRESULT_TYPEDEF_(0xc00d36b6) -#define MF_E_UNSUPPORTED_REPRESENTATION _HRESULT_TYPEDEF_(0xc00d36b7) -#define MF_E_NO_MORE_TYPES _HRESULT_TYPEDEF_(0xc00d36b9) -#define MF_E_UNSUPPORTED_SERVICE _HRESULT_TYPEDEF_(0xc00d36ba) -#define MF_E_UNEXPECTED _HRESULT_TYPEDEF_(0xc00d36bb) -#define MF_E_INVALIDNAME _HRESULT_TYPEDEF_(0xc00d36bc) -#define MF_E_INVALIDTYPE _HRESULT_TYPEDEF_(0xc00d36bd) -#define MF_E_INVALID_FILE_FORMAT _HRESULT_TYPEDEF_(0xc00d36be) -#define MF_E_INVALIDINDEX _HRESULT_TYPEDEF_(0xc00d36bf) -#define MF_E_INVALID_TIMESTAMP _HRESULT_TYPEDEF_(0xc00d36c0) -#define MF_E_UNSUPPORTED_SCHEME _HRESULT_TYPEDEF_(0xc00d36c3) -#define MF_E_UNSUPPORTED_BYTESTREAM_TYPE _HRESULT_TYPEDEF_(0xc00d36c4) -#define MF_E_UNSUPPORTED_TIME_FORMAT _HRESULT_TYPEDEF_(0xc00d36c5) -#define MF_E_NO_SAMPLE_TIMESTAMP _HRESULT_TYPEDEF_(0xc00d36c8) -#define MF_E_NO_SAMPLE_DURATION _HRESULT_TYPEDEF_(0xc00d36c9) -#define MF_E_INVALID_STREAM_DATA _HRESULT_TYPEDEF_(0xc00d36cb) -#define MF_E_RT_UNAVAILABLE _HRESULT_TYPEDEF_(0xc00d36cf) -#define MF_E_UNSUPPORTED_RATE _HRESULT_TYPEDEF_(0xc00d36d0) -#define MF_E_THINNING_UNSUPPORTED _HRESULT_TYPEDEF_(0xc00d36d1) -#define MF_E_REVERSE_UNSUPPORTED _HRESULT_TYPEDEF_(0xc00d36d2) -#define MF_E_UNSUPPORTED_RATE_TRANSITION _HRESULT_TYPEDEF_(0xc00d36d3) -#define MF_E_RATE_CHANGE_PREEMPTED _HRESULT_TYPEDEF_(0xc00d36d4) -#define MF_E_NOT_FOUND _HRESULT_TYPEDEF_(0xc00d36d5) -#define MF_E_NOT_AVAILABLE _HRESULT_TYPEDEF_(0xc00d36d6) -#define MF_E_NO_CLOCK _HRESULT_TYPEDEF_(0xc00d36d7) -#define MF_S_MULTIPLE_BEGIN _HRESULT_TYPEDEF_(0x000d36d8) -#define MF_E_MULTIPLE_BEGIN _HRESULT_TYPEDEF_(0xc00d36d9) -#define MF_E_MULTIPLE_SUBSCRIBERS _HRESULT_TYPEDEF_(0xc00d36da) -#define MF_E_TIMER_ORPHANED _HRESULT_TYPEDEF_(0xc00d36db) -#define MF_E_STATE_TRANSITION_PENDING _HRESULT_TYPEDEF_(0xc00d36dc) -#define MF_E_UNSUPPORTED_STATE_TRANSITION _HRESULT_TYPEDEF_(0xc00d36dd) -#define MF_E_UNRECOVERABLE_ERROR_OCCURRED _HRESULT_TYPEDEF_(0xc00d36de) -#define MF_E_SAMPLE_HAS_TOO_MANY_BUFFERS _HRESULT_TYPEDEF_(0xc00d36df) -#define MF_E_SAMPLE_NOT_WRITABLE _HRESULT_TYPEDEF_(0xc00d36e0) -#define MF_E_INVALID_KEY _HRESULT_TYPEDEF_(0xc00d36e2) -#define MF_E_BAD_STARTUP_VERSION _HRESULT_TYPEDEF_(0xc00d36e3) -#define MF_E_UNSUPPORTED_CAPTION _HRESULT_TYPEDEF_(0xc00d36e4) -#define MF_E_INVALID_POSITION _HRESULT_TYPEDEF_(0xc00d36e5) -#define MF_E_ATTRIBUTENOTFOUND _HRESULT_TYPEDEF_(0xc00d36e6) -#define MF_E_PROPERTY_TYPE_NOT_ALLOWED _HRESULT_TYPEDEF_(0xc00d36e7) -#define MF_E_INVALID_WORKQUEUE _HRESULT_TYPEDEF_(0xc00d36ff) -#define MF_E_NO_EVENTS_AVAILABLE _HRESULT_TYPEDEF_(0xc00d3e80) -#define MF_E_SHUTDOWN _HRESULT_TYPEDEF_(0xc00d3e85) +#define MF_E_PLATFORM_NOT_INITIALIZED _HRESULT_TYPEDEF_(0xc00d36b0) +#define MF_E_BUFFERTOOSMALL _HRESULT_TYPEDEF_(0xc00d36b1) +#define MF_E_INVALIDREQUEST _HRESULT_TYPEDEF_(0xc00d36b2) +#define MF_E_INVALIDSTREAMNUMBER _HRESULT_TYPEDEF_(0xc00d36b3) +#define MF_E_INVALIDMEDIATYPE _HRESULT_TYPEDEF_(0xc00d36b4) +#define MF_E_NOTACCEPTING _HRESULT_TYPEDEF_(0xc00d36b5) +#define MF_E_NOT_INITIALIZED _HRESULT_TYPEDEF_(0xc00d36b6) +#define MF_E_UNSUPPORTED_REPRESENTATION _HRESULT_TYPEDEF_(0xc00d36b7) +#define MF_E_NO_MORE_TYPES _HRESULT_TYPEDEF_(0xc00d36b9) +#define MF_E_UNSUPPORTED_SERVICE _HRESULT_TYPEDEF_(0xc00d36ba) +#define MF_E_UNEXPECTED _HRESULT_TYPEDEF_(0xc00d36bb) +#define MF_E_INVALIDNAME _HRESULT_TYPEDEF_(0xc00d36bc) +#define MF_E_INVALIDTYPE _HRESULT_TYPEDEF_(0xc00d36bd) +#define MF_E_INVALID_FILE_FORMAT _HRESULT_TYPEDEF_(0xc00d36be) +#define MF_E_INVALIDINDEX _HRESULT_TYPEDEF_(0xc00d36bf) +#define MF_E_INVALID_TIMESTAMP _HRESULT_TYPEDEF_(0xc00d36c0) +#define MF_E_UNSUPPORTED_SCHEME _HRESULT_TYPEDEF_(0xc00d36c3) +#define MF_E_UNSUPPORTED_BYTESTREAM_TYPE _HRESULT_TYPEDEF_(0xc00d36c4) +#define MF_E_UNSUPPORTED_TIME_FORMAT _HRESULT_TYPEDEF_(0xc00d36c5) +#define MF_E_NO_SAMPLE_TIMESTAMP _HRESULT_TYPEDEF_(0xc00d36c8) +#define MF_E_NO_SAMPLE_DURATION _HRESULT_TYPEDEF_(0xc00d36c9) +#define MF_E_INVALID_STREAM_DATA _HRESULT_TYPEDEF_(0xc00d36cb) +#define MF_E_RT_UNAVAILABLE _HRESULT_TYPEDEF_(0xc00d36cf) +#define MF_E_UNSUPPORTED_RATE _HRESULT_TYPEDEF_(0xc00d36d0) +#define MF_E_THINNING_UNSUPPORTED _HRESULT_TYPEDEF_(0xc00d36d1) +#define MF_E_REVERSE_UNSUPPORTED _HRESULT_TYPEDEF_(0xc00d36d2) +#define MF_E_UNSUPPORTED_RATE_TRANSITION _HRESULT_TYPEDEF_(0xc00d36d3) +#define MF_E_RATE_CHANGE_PREEMPTED _HRESULT_TYPEDEF_(0xc00d36d4) +#define MF_E_NOT_FOUND _HRESULT_TYPEDEF_(0xc00d36d5) +#define MF_E_NOT_AVAILABLE _HRESULT_TYPEDEF_(0xc00d36d6) +#define MF_E_NO_CLOCK _HRESULT_TYPEDEF_(0xc00d36d7) +#define MF_S_MULTIPLE_BEGIN _HRESULT_TYPEDEF_(0x000d36d8) +#define MF_E_MULTIPLE_BEGIN _HRESULT_TYPEDEF_(0xc00d36d9) +#define MF_E_MULTIPLE_SUBSCRIBERS _HRESULT_TYPEDEF_(0xc00d36da) +#define MF_E_TIMER_ORPHANED _HRESULT_TYPEDEF_(0xc00d36db) +#define MF_E_STATE_TRANSITION_PENDING _HRESULT_TYPEDEF_(0xc00d36dc) +#define MF_E_UNSUPPORTED_STATE_TRANSITION _HRESULT_TYPEDEF_(0xc00d36dd) +#define MF_E_UNRECOVERABLE_ERROR_OCCURRED _HRESULT_TYPEDEF_(0xc00d36de) +#define MF_E_SAMPLE_HAS_TOO_MANY_BUFFERS _HRESULT_TYPEDEF_(0xc00d36df) +#define MF_E_SAMPLE_NOT_WRITABLE _HRESULT_TYPEDEF_(0xc00d36e0) +#define MF_E_INVALID_KEY _HRESULT_TYPEDEF_(0xc00d36e2) +#define MF_E_BAD_STARTUP_VERSION _HRESULT_TYPEDEF_(0xc00d36e3) +#define MF_E_UNSUPPORTED_CAPTION _HRESULT_TYPEDEF_(0xc00d36e4) +#define MF_E_INVALID_POSITION _HRESULT_TYPEDEF_(0xc00d36e5) +#define MF_E_ATTRIBUTENOTFOUND _HRESULT_TYPEDEF_(0xc00d36e6) +#define MF_E_PROPERTY_TYPE_NOT_ALLOWED _HRESULT_TYPEDEF_(0xc00d36e7) +#define MF_E_PROPERTY_TYPE_NOT_SUPPORTED _HRESULT_TYPEDEF_(0xc00d36e8) +#define MF_E_PROPERTY_EMPTY _HRESULT_TYPEDEF_(0xc00d36e9) +#define MF_E_PROPERTY_NOT_EMPTY _HRESULT_TYPEDEF_(0xc00d36ea) +#define MF_E_PROPERTY_VECTOR_NOT_ALLOWED _HRESULT_TYPEDEF_(0xc00d36eb) +#define MF_E_PROPERTY_VECTOR_REQUIRED _HRESULT_TYPEDEF_(0xc00d36ec) +#define MF_E_OPERATION_CANCELLED _HRESULT_TYPEDEF_(0xc00d36ed) +#define MF_E_BYTESTREAM_NOT_SEEKABLE _HRESULT_TYPEDEF_(0xc00d36ee) +#define MF_E_DISABLED_IN_SAFEMODE _HRESULT_TYPEDEF_(0xc00d36ef) +#define MF_E_CANNOT_PARSE_BYTESTREAM _HRESULT_TYPEDEF_(0xc00d36f0) +#define MF_E_SOURCERESOLVER_MUTUALLY_EXCLUSIVE_FLAGS _HRESULT_TYPEDEF_(0xc00d36f1) +#define MF_E_BYTESTREAM_UNKNOWN_LENGTH _HRESULT_TYPEDEF_(0xc00d36fb) +#define MF_E_INVALID_WORKQUEUE _HRESULT_TYPEDEF_(0xc00d36ff) +#define MF_E_NO_EVENTS_AVAILABLE _HRESULT_TYPEDEF_(0xc00d3e80) +#define MF_E_SHUTDOWN _HRESULT_TYPEDEF_(0xc00d3e85)
-#define MF_E_TOPO_INVALID_OPTIONAL_NODE _HRESULT_TYPEDEF_(0xc00d520e) -#define MF_E_TOPO_CANNOT_FIND_DECRYPTOR _HRESULT_TYPEDEF_(0xc00d5211) -#define MF_E_TOPO_CODEC_NOT_FOUND _HRESULT_TYPEDEF_(0xc00d5212) -#define MF_E_TOPO_CANNOT_CONNECT _HRESULT_TYPEDEF_(0xc00d5213) -#define MF_E_TOPO_UNSUPPORTED _HRESULT_TYPEDEF_(0xc00d5214) -#define MF_E_TOPO_INVALID_TIME_ATTRIBUTES _HRESULT_TYPEDEF_(0xc00d5215) -#define MF_E_TOPO_LOOPS_IN_TOPOLOGY _HRESULT_TYPEDEF_(0xC00d5216) -#define MF_E_TOPO_MISSING_PRESENTATION_DESCRIPTOR _HRESULT_TYPEDEF_(0xc00d5217) -#define MF_E_TOPO_MISSING_STREAM_DESCRIPTOR _HRESULT_TYPEDEF_(0xc00d5218) -#define MF_E_TOPO_STREAM_DESCRIPTOR_NOT_SELECTED _HRESULT_TYPEDEF_(0xc00d5219) -#define MF_E_TOPO_MISSING_SOURCE _HRESULT_TYPEDEF_(0xc00d521a) -#define MF_E_TOPO_SINK_ACTIVATES_UNSUPPORTED _HRESULT_TYPEDEF_(0xc00d521b) +#define MF_E_TOPO_INVALID_OPTIONAL_NODE _HRESULT_TYPEDEF_(0xc00d520e) +#define MF_E_TOPO_CANNOT_FIND_DECRYPTOR _HRESULT_TYPEDEF_(0xc00d5211) +#define MF_E_TOPO_CODEC_NOT_FOUND _HRESULT_TYPEDEF_(0xc00d5212) +#define MF_E_TOPO_CANNOT_CONNECT _HRESULT_TYPEDEF_(0xc00d5213) +#define MF_E_TOPO_UNSUPPORTED _HRESULT_TYPEDEF_(0xc00d5214) +#define MF_E_TOPO_INVALID_TIME_ATTRIBUTES _HRESULT_TYPEDEF_(0xc00d5215) +#define MF_E_TOPO_LOOPS_IN_TOPOLOGY _HRESULT_TYPEDEF_(0xC00d5216) +#define MF_E_TOPO_MISSING_PRESENTATION_DESCRIPTOR _HRESULT_TYPEDEF_(0xc00d5217) +#define MF_E_TOPO_MISSING_STREAM_DESCRIPTOR _HRESULT_TYPEDEF_(0xc00d5218) +#define MF_E_TOPO_STREAM_DESCRIPTOR_NOT_SELECTED _HRESULT_TYPEDEF_(0xc00d5219) +#define MF_E_TOPO_MISSING_SOURCE _HRESULT_TYPEDEF_(0xc00d521a) +#define MF_E_TOPO_SINK_ACTIVATES_UNSUPPORTED _HRESULT_TYPEDEF_(0xc00d521b)
-#define MF_E_CLOCK_NO_TIME_SOURCE _HRESULT_TYPEDEF_(0xc00d9c41) -#define MF_E_CLOCK_STATE_ALREADY_SET _HRESULT_TYPEDEF_(0xc00d9c42) +#define MF_E_CLOCK_NO_TIME_SOURCE _HRESULT_TYPEDEF_(0xc00d9c41) +#define MF_E_CLOCK_STATE_ALREADY_SET _HRESULT_TYPEDEF_(0xc00d9c42)
#endif /* __WINE_MFERROR_H */
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfreadwrite/main.c | 7 +++---- dlls/mfreadwrite/tests/mfplat.c | 6 +----- dlls/mfuuid/mfuuid.c | 3 +++ 3 files changed, 7 insertions(+), 9 deletions(-)
diff --git a/dlls/mfreadwrite/main.c b/dlls/mfreadwrite/main.c index a83ece0359..098100df91 100644 --- a/dlls/mfreadwrite/main.c +++ b/dlls/mfreadwrite/main.c @@ -27,16 +27,15 @@ #include "initguid.h" #include "ole2.h" #include "rpcproxy.h" + +#undef INITGUID +#include <guiddef.h> #include "mfidl.h" #include "mfreadwrite.h"
#include "wine/debug.h" #include "wine/heap.h"
-DEFINE_GUID(CLSID_MFReadWriteClassFactory, 0x48e2ed0f, 0x98c2, 0x4a37, 0xbe, 0xd5, 0x16, 0x63, 0x12, 0xdd, 0xd8, 0x3f); -DEFINE_GUID(CLSID_MFSourceReader, 0x1777133c, 0x0881, 0x411b, 0xa5, 0x77, 0xad, 0x54, 0x5f, 0x07, 0x14, 0xc4); -DEFINE_GUID(CLSID_MFSinkWriter, 0xa3bbfb17, 0x8273, 0x4e52, 0x9e, 0x0e, 0x97, 0x39, 0xdc, 0x88, 0x79, 0x90); - WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
static HINSTANCE mfinstance; diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c index b2675dc71f..58533ccd3a 100644 --- a/dlls/mfreadwrite/tests/mfplat.c +++ b/dlls/mfreadwrite/tests/mfplat.c @@ -26,6 +26,7 @@ #include "winuser.h" #include "winreg.h"
+#undef INITGUID #include "mfapi.h" #include "mfidl.h" #include "mferror.h" @@ -33,11 +34,6 @@
#include "wine/test.h"
-#include "initguid.h" -DEFINE_GUID(MF_READWRITE_MMCSS_PRIORITY_AUDIO,0x273db885, 0x2de2, 0x4db2, 0xa6, 0xa7, 0xfd, 0xb6, 0x6f, 0xb4, 0x0b, 0x61); -DEFINE_GUID(MF_READWRITE_MMCSS_CLASS_AUDIO, 0x430847da, 0x0890, 0x4b0e, 0x93, 0x8c, 0x05, 0x43, 0x32, 0xc5, 0x47, 0xe1); -DEFINE_GUID(CLSID_MFReadWriteClassFactory, 0x48e2ed0f, 0x98c2, 0x4a37, 0xbe, 0xd5, 0x16, 0x63, 0x12, 0xdd, 0xd8, 0x3f); - static HRESULT (WINAPI *pMFCreateMFByteStreamOnStream)(IStream *stream, IMFByteStream **bytestream);
static void init_functions(void) diff --git a/dlls/mfuuid/mfuuid.c b/dlls/mfuuid/mfuuid.c index f9b1a8a4b4..5bfd521aec 100644 --- a/dlls/mfuuid/mfuuid.c +++ b/dlls/mfuuid/mfuuid.c @@ -23,6 +23,9 @@ #include "strmif.h" #include "mediaobj.h"
+#undef EXTERN_GUID +#define EXTERN_GUID DEFINE_GUID + #include "initguid.h"
#include "mfapi.h"
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/Makefile.in | 2 +- dlls/mfplat/main.c | 1 + dlls/mfplat/mfplat_private.h | 2 ++ dlls/mfplat/tests/Makefile.in | 2 +- dlls/mfplat/tests/mfplat.c | 19 +++++++++---------- 5 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/dlls/mfplat/Makefile.in b/dlls/mfplat/Makefile.in index a117ede271..e64e4058c1 100644 --- a/dlls/mfplat/Makefile.in +++ b/dlls/mfplat/Makefile.in @@ -1,6 +1,6 @@ MODULE = mfplat.dll IMPORTLIB = mfplat -IMPORTS = advapi32 ole32 +IMPORTS = advapi32 ole32 mfuuid
C_SRCS = \ buffer.c \ diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index 7a8361f858..e3b802cade 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -27,6 +27,7 @@ #include "winreg.h"
#include "initguid.h" +#include "ole2.h"
#include "wine/debug.h" #include "wine/unicode.h" diff --git a/dlls/mfplat/mfplat_private.h b/dlls/mfplat/mfplat_private.h index 72f8f684f6..c42570c8a9 100644 --- a/dlls/mfplat/mfplat_private.h +++ b/dlls/mfplat/mfplat_private.h @@ -16,6 +16,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+#undef INITGUID +#include <guiddef.h> #include "mfapi.h" #include "mfidl.h" #include "mferror.h" diff --git a/dlls/mfplat/tests/Makefile.in b/dlls/mfplat/tests/Makefile.in index 07cf328ad2..15b8e17842 100644 --- a/dlls/mfplat/tests/Makefile.in +++ b/dlls/mfplat/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = mfplat.dll -IMPORTS = ole32 mfplat +IMPORTS = ole32 mfplat mfuuid
C_SRCS = \ mfplat.c diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index 278112a9c5..ae9d3b5719 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -29,6 +29,15 @@ #include "winreg.h"
#include "initguid.h" +#include "ole2.h" + +DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); +DEFINE_GUID(DUMMY_CLSID, 0x12345678,0x1234,0x1234,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19); +DEFINE_GUID(DUMMY_GUID1, 0x12345678,0x1234,0x1234,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21); +DEFINE_GUID(DUMMY_GUID2, 0x12345678,0x1234,0x1234,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22); + +#undef INITGUID +#include <guiddef.h> #include "mfapi.h" #include "mfidl.h" #include "mferror.h" @@ -49,16 +58,6 @@ static HRESULT (WINAPI *pMFAllocateSerialWorkQueue)(DWORD queue, DWORD *serial_q static HRESULT (WINAPI *pMFAddPeriodicCallback)(MFPERIODICCALLBACK callback, IUnknown *context, DWORD *key); static HRESULT (WINAPI *pMFRemovePeriodicCallback)(DWORD key);
-DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); - -DEFINE_GUID(MF_BYTESTREAM_CONTENT_TYPE, 0xfc358289,0x3cb6,0x460c,0xa4,0x24,0xb6,0x68,0x12,0x60,0x37,0x5a); - -DEFINE_GUID(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, 0xa634a91c, 0x822b, 0x41b9, 0xa4, 0x94, 0x4d, 0xe4, 0x64, 0x36, 0x12, 0xb0); - -DEFINE_GUID(DUMMY_CLSID, 0x12345678,0x1234,0x1234,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19); -DEFINE_GUID(DUMMY_GUID1, 0x12345678,0x1234,0x1234,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21); -DEFINE_GUID(DUMMY_GUID2, 0x12345678,0x1234,0x1234,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22); - static const WCHAR mp4file[] = {'t','e','s','t','.','m','p','4',0};
static WCHAR *load_resource(const WCHAR *name)
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=49081
Your paranoid android.
=== wxppro (32 bit report) ===
mfplat: 0b40:mfplat: unhandled exception c0000005 at 2F2E2E2F
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/main.c | 342 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 317 insertions(+), 25 deletions(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index e3b802cade..0e620529b2 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -1905,15 +1905,259 @@ static const IMFMediaSourceVtbl mfsourcevtbl = mfsource_Shutdown, };
-typedef struct _mfsourceresolver +enum resolved_object_origin +{ + OBJECT_FROM_BYTESTREAM, +}; + +struct resolver_queued_result +{ + struct list entry; + IUnknown *object; + MF_OBJECT_TYPE obj_type; + HRESULT hr; + enum resolved_object_origin origin; +}; + +typedef struct source_resolver { IMFSourceResolver IMFSourceResolver_iface; - LONG ref; + LONG refcount; + IMFAsyncCallback stream_callback; + CRITICAL_SECTION cs; + struct list pending; } mfsourceresolver;
-static inline mfsourceresolver *impl_from_IMFSourceResolver(IMFSourceResolver *iface) +static struct source_resolver *impl_from_IMFSourceResolver(IMFSourceResolver *iface) +{ + return CONTAINING_RECORD(iface, struct source_resolver, IMFSourceResolver_iface); +} + +static struct source_resolver *impl_from_stream_IMFAsyncCallback(IMFAsyncCallback *iface) +{ + return CONTAINING_RECORD(iface, struct source_resolver, stream_callback); +} + +static HRESULT resolver_handler_end_create(struct source_resolver *resolver, enum resolved_object_origin origin, + IMFAsyncResult *result) +{ + IMFAsyncResult *inner_result = (IMFAsyncResult *)IMFAsyncResult_GetStateNoAddRef(result); + struct resolver_queued_result *queued_result; + union + { + IUnknown *handler; + IMFByteStreamHandler *stream_handler; + } handler; + + queued_result = heap_alloc(sizeof(*queued_result)); + + IMFAsyncResult_GetObject(inner_result, &handler.handler); + + switch (origin) + { + case OBJECT_FROM_BYTESTREAM: + queued_result->hr = IMFByteStreamHandler_EndCreateObject(handler.stream_handler, result, &queued_result->obj_type, + &queued_result->object); + break; + default: + queued_result->hr = E_FAIL; + } + + IUnknown_Release(handler.handler); + + if (SUCCEEDED(queued_result->hr)) + { + MFASYNCRESULT *data = (MFASYNCRESULT *)inner_result; + + /* Push resolved object type and created object, so we don't have to guess on End*() call. */ + EnterCriticalSection(&resolver->cs); + list_add_tail(&resolver->pending, &queued_result->entry); + LeaveCriticalSection(&resolver->cs); + + if (data->hEvent) + SetEvent(data->hEvent); + } + else + heap_free(queued_result); + + return S_OK; +} + +static HRESULT WINAPI source_resolver_callback_QueryInterface(IMFAsyncCallback *iface, REFIID riid, void **obj) +{ + if (IsEqualIID(riid, &IID_IMFAsyncCallback) || + IsEqualIID(riid, &IID_IUnknown)) + { + *obj = iface; + IMFAsyncCallback_AddRef(iface); + return S_OK; + } + + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI source_resolver_callback_stream_AddRef(IMFAsyncCallback *iface) +{ + struct source_resolver *resolver = impl_from_stream_IMFAsyncCallback(iface); + return IMFSourceResolver_AddRef(&resolver->IMFSourceResolver_iface); +} + +static ULONG WINAPI source_resolver_callback_stream_Release(IMFAsyncCallback *iface) +{ + struct source_resolver *resolver = impl_from_stream_IMFAsyncCallback(iface); + return IMFSourceResolver_Release(&resolver->IMFSourceResolver_iface); +} + +static HRESULT WINAPI source_resolver_callback_GetParameters(IMFAsyncCallback *iface, DWORD *flags, DWORD *queue) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI source_resolver_callback_stream_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result) +{ + struct source_resolver *resolver = impl_from_stream_IMFAsyncCallback(iface); + + return resolver_handler_end_create(resolver, OBJECT_FROM_BYTESTREAM, result); +} + +static const IMFAsyncCallbackVtbl source_resolver_callback_stream_vtbl = +{ + source_resolver_callback_QueryInterface, + source_resolver_callback_stream_AddRef, + source_resolver_callback_stream_Release, + source_resolver_callback_GetParameters, + source_resolver_callback_stream_Invoke, +}; + +static HRESULT resolver_create_registered_handler(HKEY hkey, REFIID riid, void **handler) +{ + unsigned int j = 0, name_length, type; + HRESULT hr = E_FAIL; + WCHAR clsidW[39]; + CLSID clsid; + + name_length = ARRAY_SIZE(clsidW); + while (!RegEnumValueW(hkey, j++, clsidW, &name_length, NULL, &type, NULL, NULL)) + { + if (type == REG_SZ) + { + if (SUCCEEDED(CLSIDFromString(clsidW, &clsid))) + { + hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, riid, handler); + if (SUCCEEDED(hr)) + break; + } + } + + name_length = ARRAY_SIZE(clsidW); + } + + return hr; +} + +static HRESULT resolver_get_bytestream_handler(IMFByteStream *stream, const WCHAR *url, DWORD flags, + IMFByteStreamHandler **handler) +{ + static const char streamhandlerspath[] = "Software\Microsoft\Windows Media Foundation\ByteStreamHandlers"; + static const HKEY hkey_roots[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE }; + IMFAttributes *attributes; + const WCHAR *url_ext; + WCHAR *mimeW = NULL; + unsigned int i, j; + UINT32 length; + HRESULT hr; + + *handler = NULL; + + /* MIME type */ + if (SUCCEEDED(IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&attributes))) + { + IMFAttributes_GetAllocatedString(attributes, &MF_BYTESTREAM_CONTENT_TYPE, &mimeW, &length); + IMFAttributes_Release(attributes); + } + + /* Extension */ + url_ext = url ? strrchrW(url, '.') : NULL; + + if (!url_ext && !mimeW) + { + CoTaskMemFree(mimeW); + return MF_E_UNSUPPORTED_BYTESTREAM_TYPE; + } + + /* FIXME: check local handlers first */ + + for (i = 0, hr = E_FAIL; i < ARRAY_SIZE(hkey_roots); ++i) + { + const WCHAR *namesW[2] = { mimeW, url_ext }; + HKEY hkey, hkey_handler; + + if (RegOpenKeyA(hkey_roots[i], streamhandlerspath, &hkey)) + continue; + + for (j = 0; j < ARRAY_SIZE(namesW); ++j) + { + if (!namesW[j]) + continue; + + if (!RegOpenKeyW(hkey, namesW[j], &hkey_handler)) + { + hr = resolver_create_registered_handler(hkey_handler, &IID_IMFByteStreamHandler, (void **)handler); + RegCloseKey(hkey_handler); + } + + if (SUCCEEDED(hr)) + break; + } + + RegCloseKey(hkey); + + if (SUCCEEDED(hr)) + break; + } + + CoTaskMemFree(mimeW); + return hr; +} + +static HRESULT resolver_end_create_object(struct source_resolver *resolver, enum resolved_object_origin origin, + IMFAsyncResult *result, MF_OBJECT_TYPE *obj_type, IUnknown **out) { - return CONTAINING_RECORD(iface, mfsourceresolver, IMFSourceResolver_iface); + struct resolver_queued_result *queued_result = NULL, *iter; + IUnknown *object; + HRESULT hr; + + if (FAILED(hr = IMFAsyncResult_GetObject(result, &object))) + return hr; + + EnterCriticalSection(&resolver->cs); + + LIST_FOR_EACH_ENTRY(iter, &resolver->pending, struct resolver_queued_result, entry) + { + if (iter->object == object && iter->origin == origin) + { + list_remove(&iter->entry); + queued_result = iter; + break; + } + } + + LeaveCriticalSection(&resolver->cs); + + IUnknown_Release(object); + + if (queued_result) + { + *out = queued_result->object; + *obj_type = queued_result->obj_type; + hr = queued_result->hr; + heap_free(queued_result); + } + else + hr = E_UNEXPECTED; + + return hr; }
static HRESULT WINAPI mfsourceresolver_QueryInterface(IMFSourceResolver *iface, REFIID riid, void **obj) @@ -1938,27 +2182,38 @@ static HRESULT WINAPI mfsourceresolver_QueryInterface(IMFSourceResolver *iface, return S_OK; }
-static ULONG WINAPI mfsourceresolver_AddRef(IMFSourceResolver *iface) +static ULONG WINAPI source_resolver_AddRef(IMFSourceResolver *iface) { - mfsourceresolver *This = impl_from_IMFSourceResolver(iface); - ULONG ref = InterlockedIncrement(&This->ref); + struct source_resolver *resolver = impl_from_IMFSourceResolver(iface); + ULONG refcount = InterlockedIncrement(&resolver->refcount);
- TRACE("(%p)->(%u)\n", This, ref); + TRACE("%p, refcount %d.\n", iface, refcount);
- return ref; + return refcount; }
-static ULONG WINAPI mfsourceresolver_Release(IMFSourceResolver *iface) +static ULONG WINAPI source_resolver_Release(IMFSourceResolver *iface) { - mfsourceresolver *This = impl_from_IMFSourceResolver(iface); - ULONG ref = InterlockedDecrement(&This->ref); + struct source_resolver *resolver = impl_from_IMFSourceResolver(iface); + ULONG refcount = InterlockedDecrement(&resolver->refcount); + struct resolver_queued_result *result, *result2;
- TRACE("(%p)->(%u)\n", This, ref); + TRACE("%p, refcount %d.\n", iface, refcount);
- if (!ref) - HeapFree(GetProcessHeap(), 0, This); + if (!refcount) + { + LIST_FOR_EACH_ENTRY_SAFE(result, result2, &resolver->pending, struct resolver_queued_result, entry) + { + if (result->object) + IUnknown_Release(result->object); + list_remove(&result->entry); + heap_free(result); + } + DeleteCriticalSection(&resolver->cs); + heap_free(resolver); + }
- return ref; + return refcount; }
static HRESULT WINAPI mfsourceresolver_CreateObjectFromURL(IMFSourceResolver *iface, const WCHAR *url, @@ -1971,16 +2226,49 @@ static HRESULT WINAPI mfsourceresolver_CreateObjectFromURL(IMFSourceResolver *if return E_NOTIMPL; }
-static HRESULT WINAPI mfsourceresolver_CreateObjectFromByteStream(IMFSourceResolver *iface, IMFByteStream *stream, +static HRESULT WINAPI source_resolver_CreateObjectFromByteStream(IMFSourceResolver *iface, IMFByteStream *stream, const WCHAR *url, DWORD flags, IPropertyStore *props, MF_OBJECT_TYPE *obj_type, IUnknown **object) { - mfsourceresolver *This = impl_from_IMFSourceResolver(iface); + struct source_resolver *resolver = impl_from_IMFSourceResolver(iface); + IMFByteStreamHandler *handler; + IMFAsyncResult *result; + MFASYNCRESULT *data; + HRESULT hr;
- FIXME("(%p)->(%p, %s, %#x, %p, %p, %p): stub\n", This, stream, debugstr_w(url), flags, props, obj_type, object); + TRACE("%p, %p, %s, %#x, %p, %p, %p.\n", iface, stream, debugstr_w(url), flags, props, obj_type, object);
if (!stream || !obj_type || !object) return E_POINTER;
+ if (FAILED(hr = resolver_get_bytestream_handler(stream, url, flags, &handler))) + goto fallback; + + hr = MFCreateAsyncResult((IUnknown *)handler, NULL, NULL, &result); + IMFByteStreamHandler_Release(handler); + if (FAILED(hr)) + return hr; + + data = (MFASYNCRESULT *)result; + data->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + + hr = IMFByteStreamHandler_BeginCreateObject(handler, stream, url, flags, props, NULL, &resolver->stream_callback, + (IUnknown *)result); + if (FAILED(hr)) + { + IMFAsyncResult_Release(result); + return hr; + } + + WaitForSingleObject(data->hEvent, INFINITE); + + hr = resolver_end_create_object(resolver, OBJECT_FROM_BYTESTREAM, result, obj_type, object); + IMFAsyncResult_Release(result); + + /* TODO: following stub is left intentionally until real source plugins are implemented. */ + if (SUCCEEDED(hr)) + return hr; + +fallback: if (flags & MF_RESOLUTION_MEDIASOURCE) { mfsource *new_object; @@ -2055,10 +2343,10 @@ static HRESULT WINAPI mfsourceresolver_CancelObjectCreation(IMFSourceResolver *i static const IMFSourceResolverVtbl mfsourceresolvervtbl = { mfsourceresolver_QueryInterface, - mfsourceresolver_AddRef, - mfsourceresolver_Release, + source_resolver_AddRef, + source_resolver_Release, mfsourceresolver_CreateObjectFromURL, - mfsourceresolver_CreateObjectFromByteStream, + source_resolver_CreateObjectFromByteStream, mfsourceresolver_BeginCreateObjectFromURL, mfsourceresolver_EndCreateObjectFromURL, mfsourceresolver_BeginCreateObjectFromByteStream, @@ -2071,21 +2359,25 @@ static const IMFSourceResolverVtbl mfsourceresolvervtbl = */ HRESULT WINAPI MFCreateSourceResolver(IMFSourceResolver **resolver) { - mfsourceresolver *object; + struct source_resolver *object;
TRACE("%p\n", resolver);
if (!resolver) return E_POINTER;
- object = HeapAlloc( GetProcessHeap(), 0, sizeof(*object) ); + object = heap_alloc_zero(sizeof(*object)); if (!object) return E_OUTOFMEMORY;
object->IMFSourceResolver_iface.lpVtbl = &mfsourceresolvervtbl; - object->ref = 1; + object->stream_callback.lpVtbl = &source_resolver_callback_stream_vtbl; + object->refcount = 1; + list_init(&object->pending); + InitializeCriticalSection(&object->cs);
*resolver = &object->IMFSourceResolver_iface; + return S_OK; }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/main.c | 193 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 166 insertions(+), 27 deletions(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index 0e620529b2..06be27daa3 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -1919,6 +1919,19 @@ struct resolver_queued_result enum resolved_object_origin origin; };
+struct resolver_cancel_object +{ + IUnknown IUnknown_iface; + LONG refcount; + union + { + IUnknown *handler; + IMFByteStreamHandler *stream_handler; + } u; + IUnknown *cancel_cookie; + enum resolved_object_origin origin; +}; + typedef struct source_resolver { IMFSourceResolver IMFSourceResolver_iface; @@ -1976,6 +1989,17 @@ static HRESULT resolver_handler_end_create(struct source_resolver *resolver, enu
if (data->hEvent) SetEvent(data->hEvent); + else + { + IUnknown *caller_state = IMFAsyncResult_GetStateNoAddRef(inner_result); + IMFAsyncResult *caller_result; + + if (SUCCEEDED(MFCreateAsyncResult(queued_result->object, data->pCallback, caller_state, &caller_result))) + { + MFInvokeCallback(caller_result); + IMFAsyncResult_Release(caller_result); + } + } } else heap_free(queued_result); @@ -1983,6 +2007,84 @@ static HRESULT resolver_handler_end_create(struct source_resolver *resolver, enu return S_OK; }
+static struct resolver_cancel_object *impl_cancel_obj_from_IUnknown(IUnknown *iface) +{ + return CONTAINING_RECORD(iface, struct resolver_cancel_object, IUnknown_iface); +} + +static HRESULT WINAPI resolver_cancel_object_QueryInterface(IUnknown *iface, REFIID riid, void **obj) +{ + if (IsEqualIID(riid, &IID_IUnknown)) + { + *obj = iface; + IUnknown_AddRef(iface); + return S_OK; + } + + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI resolver_cancel_object_AddRef(IUnknown *iface) +{ + struct resolver_cancel_object *object = impl_cancel_obj_from_IUnknown(iface); + return InterlockedIncrement(&object->refcount); +} + +static ULONG WINAPI resolver_cancel_object_Release(IUnknown *iface) +{ + struct resolver_cancel_object *object = impl_cancel_obj_from_IUnknown(iface); + ULONG refcount = InterlockedDecrement(&object->refcount); + + if (!refcount) + { + if (object->cancel_cookie) + IUnknown_Release(object->cancel_cookie); + IUnknown_Release(object->u.handler); + heap_free(object); + } + + return refcount; +} + +static const IUnknownVtbl resolver_cancel_object_vtbl = +{ + resolver_cancel_object_QueryInterface, + resolver_cancel_object_AddRef, + resolver_cancel_object_Release, +}; + +static struct resolver_cancel_object *unsafe_impl_cancel_obj_from_IUnknown(IUnknown *iface) +{ + if (!iface) + return NULL; + + return (iface->lpVtbl == &resolver_cancel_object_vtbl) ? + CONTAINING_RECORD(iface, struct resolver_cancel_object, IUnknown_iface) : NULL; +} + +static HRESULT resolver_create_cancel_object(IUnknown *handler, enum resolved_object_origin origin, + IUnknown *cancel_cookie, IUnknown **cancel_object) +{ + struct resolver_cancel_object *object; + + object = heap_alloc_zero(sizeof(*object)); + if (!object) + return E_OUTOFMEMORY; + + object->IUnknown_iface.lpVtbl = &resolver_cancel_object_vtbl; + object->refcount = 1; + object->u.handler = handler; + IUnknown_AddRef(object->u.handler); + object->cancel_cookie = cancel_cookie; + IUnknown_AddRef(object->cancel_cookie); + object->origin = origin; + + *cancel_object = &object->IUnknown_iface; + + return S_OK; +} + static HRESULT WINAPI source_resolver_callback_QueryInterface(IMFAsyncCallback *iface, REFIID riid, void **obj) { if (IsEqualIID(riid, &IID_IMFAsyncCallback) || @@ -2160,7 +2262,7 @@ static HRESULT resolver_end_create_object(struct source_resolver *resolver, enum return hr; }
-static HRESULT WINAPI mfsourceresolver_QueryInterface(IMFSourceResolver *iface, REFIID riid, void **obj) +static HRESULT WINAPI source_resolver_QueryInterface(IMFSourceResolver *iface, REFIID riid, void **obj) { mfsourceresolver *This = impl_from_IMFSourceResolver(iface);
@@ -2309,49 +2411,86 @@ static HRESULT WINAPI mfsourceresolver_EndCreateObjectFromURL(IMFSourceResolver return E_NOTIMPL; }
-static HRESULT WINAPI mfsourceresolver_BeginCreateObjectFromByteStream(IMFSourceResolver *iface, IMFByteStream *stream, - const WCHAR *url, DWORD flags, IPropertyStore *props, IUnknown **cancel_cookie, IMFAsyncCallback *callback, - IUnknown *unk_state) +static HRESULT WINAPI source_resolver_BeginCreateObjectFromByteStream(IMFSourceResolver *iface, IMFByteStream *stream, + const WCHAR *url, DWORD flags, IPropertyStore *props, IUnknown **cancel_cookie, IMFAsyncCallback *callback, + IUnknown *state) { - mfsourceresolver *This = impl_from_IMFSourceResolver(iface); + struct source_resolver *resolver = impl_from_IMFSourceResolver(iface); + IMFByteStreamHandler *handler; + IUnknown *inner_cookie = NULL; + IMFAsyncResult *result; + HRESULT hr;
- FIXME("(%p)->(%p, %s, %#x, %p, %p, %p, %p): stub\n", This, stream, debugstr_w(url), flags, props, cancel_cookie, - callback, unk_state); + TRACE("%p, %p, %s, %#x, %p, %p, %p, %p.\n", iface, stream, debugstr_w(url), flags, props, cancel_cookie, + callback, state);
- return E_NOTIMPL; + if (FAILED(hr = resolver_get_bytestream_handler(stream, url, flags, &handler))) + return hr; + + if (cancel_cookie) + *cancel_cookie = NULL; + + hr = MFCreateAsyncResult((IUnknown *)handler, callback, state, &result); + IMFByteStreamHandler_Release(handler); + if (FAILED(hr)) + return hr; + + hr = IMFByteStreamHandler_BeginCreateObject(handler, stream, url, flags, props, + cancel_cookie ? &inner_cookie : NULL, &resolver->stream_callback, (IUnknown *)result); + + /* Cancel object wraps underlying handler cancel cookie with context necessary to call CancelObjectCreate(). */ + if (SUCCEEDED(hr) && inner_cookie) + resolver_create_cancel_object((IUnknown *)handler, OBJECT_FROM_BYTESTREAM, inner_cookie, cancel_cookie); + + IMFAsyncResult_Release(result); + + return hr; }
-static HRESULT WINAPI mfsourceresolver_EndCreateObjectFromByteStream(IMFSourceResolver *iface, IMFAsyncResult *result, - MF_OBJECT_TYPE *obj_type, IUnknown **object) +static HRESULT WINAPI source_resolver_EndCreateObjectFromByteStream(IMFSourceResolver *iface, IMFAsyncResult *result, + MF_OBJECT_TYPE *obj_type, IUnknown **object) { - mfsourceresolver *This = impl_from_IMFSourceResolver(iface); + struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
- FIXME("(%p)->(%p, %p, %p): stub\n", This, result, obj_type, object); + TRACE("%p, %p, %p, %p.\n", iface, result, obj_type, object);
- return E_NOTIMPL; + return resolver_end_create_object(resolver, OBJECT_FROM_BYTESTREAM, result, obj_type, object); }
-static HRESULT WINAPI mfsourceresolver_CancelObjectCreation(IMFSourceResolver *iface, IUnknown *cancel_cookie) +static HRESULT WINAPI source_resolver_CancelObjectCreation(IMFSourceResolver *iface, IUnknown *cancel_cookie) { - mfsourceresolver *This = impl_from_IMFSourceResolver(iface); + struct resolver_cancel_object *object; + HRESULT hr;
- FIXME("(%p)->(%p): stub\n", This, cancel_cookie); + TRACE("%p, %p.\n", iface, cancel_cookie);
- return E_NOTIMPL; + if (!(object = unsafe_impl_cancel_obj_from_IUnknown(cancel_cookie))) + return E_UNEXPECTED; + + switch (object->origin) + { + case OBJECT_FROM_BYTESTREAM: + hr = IMFByteStreamHandler_CancelObjectCreation(object->u.stream_handler, object->cancel_cookie); + break; + default: + hr = E_UNEXPECTED; + } + + return hr; }
static const IMFSourceResolverVtbl mfsourceresolvervtbl = { - mfsourceresolver_QueryInterface, - source_resolver_AddRef, - source_resolver_Release, - mfsourceresolver_CreateObjectFromURL, - source_resolver_CreateObjectFromByteStream, - mfsourceresolver_BeginCreateObjectFromURL, - mfsourceresolver_EndCreateObjectFromURL, - mfsourceresolver_BeginCreateObjectFromByteStream, - mfsourceresolver_EndCreateObjectFromByteStream, - mfsourceresolver_CancelObjectCreation, + source_resolver_QueryInterface, + source_resolver_AddRef, + source_resolver_Release, + mfsourceresolver_CreateObjectFromURL, + source_resolver_CreateObjectFromByteStream, + mfsourceresolver_BeginCreateObjectFromURL, + mfsourceresolver_EndCreateObjectFromURL, + source_resolver_BeginCreateObjectFromByteStream, + source_resolver_EndCreateObjectFromByteStream, + source_resolver_CancelObjectCreation, };
/***********************************************************************