From 337fcca4d1e0d494192d67786dbf1feeac87f592 Mon Sep 17 00:00:00 2001 From: Anton Baskanov Date: Thu, 10 Sep 2020 02:17:37 +0700 Subject: [PATCH] amstream: Reject incompatible media types in AMDirectDrawStream::ReceiveConnection. Signed-off-by: Anton Baskanov Signed-off-by: Zebediah Figura Signed-off-by: Alexandre Julliard --- dlls/amstream/ddrawstream.c | 26 ++++++ dlls/amstream/tests/amstream.c | 152 +++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+) diff --git a/dlls/amstream/ddrawstream.c b/dlls/amstream/ddrawstream.c index 542c315930d..c281c81d334 100644 --- a/dlls/amstream/ddrawstream.c +++ b/dlls/amstream/ddrawstream.c @@ -61,6 +61,26 @@ struct ddraw_stream static HRESULT ddrawstreamsample_create(struct ddraw_stream *parent, IDirectDrawSurface *surface, const RECT *rect, IDirectDrawStreamSample **ddraw_stream_sample); +static BOOL is_format_compatible(struct ddraw_stream *stream, + DWORD width, DWORD height, const DDPIXELFORMAT *connection_pf) +{ + if (stream->format.flags & DDSD_HEIGHT) + { + if (stream->format.width != width || stream->format.height != height) + return FALSE; + } + if (stream->format.flags & DDSD_PIXELFORMAT) + { + if (stream->format.pf.dwFlags & DDPF_FOURCC) + return FALSE; + if (stream->format.pf.u1.dwRGBBitCount != connection_pf->u1.dwRGBBitCount) + return FALSE; + if (stream->format.pf.u1.dwRGBBitCount == 16 && stream->format.pf.u3.dwGBitMask != connection_pf->u3.dwGBitMask) + return FALSE; + } + return TRUE; +} + static inline struct ddraw_stream *impl_from_IAMMediaStream(IAMMediaStream *iface) { return CONTAINING_RECORD(iface, struct ddraw_stream, IAMMediaStream_iface); @@ -824,6 +844,12 @@ static HRESULT WINAPI ddraw_sink_ReceiveConnection(IPin *iface, IPin *peer, cons return VFW_E_TYPE_NOT_ACCEPTED; } + if (!is_format_compatible(stream, width, height, &pf)) + { + LeaveCriticalSection(&stream->cs); + return VFW_E_TYPE_NOT_ACCEPTED; + } + IPin_QueryDirection(peer, &dir); if (dir != PINDIR_OUTPUT) { diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c index f081c58a2aa..0b343b4912d 100644 --- a/dlls/amstream/tests/amstream.c +++ b/dlls/amstream/tests/amstream.c @@ -3353,13 +3353,34 @@ static void test_ddrawstream_receive_connection(void) IDirectDrawMediaStream *ddraw_stream; IAMMultiMediaStream *mmstream; struct testfilter source; + DDSURFACEDESC format; IMediaStream *stream; + VIDEOINFO video_info; AM_MEDIA_TYPE mt; HRESULT hr; ULONG ref; IPin *pin; int i; + static const VIDEOINFO yuy2_video_info = + { + .bmiHeader.biSize = sizeof(BITMAPINFOHEADER), + .bmiHeader.biWidth = 333, + .bmiHeader.biHeight = -444, + .bmiHeader.biPlanes = 1, + .bmiHeader.biBitCount = 16, + .bmiHeader.biCompression = MAKEFOURCC('Y', 'U', 'Y', '2'), + }; + + const AM_MEDIA_TYPE yuy2_mt = + { + .majortype = MEDIATYPE_Video, + .subtype = MEDIASUBTYPE_YUY2, + .formattype = FORMAT_VideoInfo, + .cbFormat = sizeof(VIDEOINFOHEADER), + .pbFormat = (BYTE *)&yuy2_video_info, + }; + const AM_MEDIA_TYPE video_mt = { .majortype = MEDIATYPE_Video, @@ -3420,6 +3441,137 @@ static void test_ddrawstream_receive_connection(void) } } + format = rgb8_format; + format.dwFlags = DDSD_WIDTH; + format.dwWidth = 222; + format.dwHeight = 555; + hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &format, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb32_mt); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IPin_Disconnect(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + format = rgb8_format; + format.dwFlags = DDSD_HEIGHT; + format.dwWidth = 333; + format.dwHeight = 444; + hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &format, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + video_info = rgb555_video_info; + video_info.bmiHeader.biWidth = 333; + video_info.bmiHeader.biHeight = 444; + mt = rgb555_mt; + mt.pbFormat = (BYTE *)&video_info; + hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &mt); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IPin_Disconnect(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb32_mt); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IPin_Disconnect(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + video_info = rgb32_video_info; + video_info.bmiHeader.biWidth = 332; + video_info.bmiHeader.biHeight = 444; + mt = rgb32_mt; + mt.pbFormat = (BYTE *)&video_info; + hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &mt); + ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr); + + video_info = rgb32_video_info; + video_info.bmiHeader.biWidth = 333; + video_info.bmiHeader.biHeight = 443; + mt = rgb32_mt; + mt.pbFormat = (BYTE *)&video_info; + hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &mt); + ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr); + + hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb8_format, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb555_mt); + ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr); + + hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb8_mt); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IPin_Disconnect(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb555_format, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb565_mt); + ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr); + + hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb555_mt); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IPin_Disconnect(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb565_format, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb24_mt); + ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr); + + hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb565_mt); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IPin_Disconnect(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb24_format, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb32_mt); + ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr); + + hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb24_mt); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IPin_Disconnect(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb32_format, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb8_mt); + ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr); + + hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb32_mt); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IPin_Disconnect(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &yuy2_format, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &yuy2_mt); + ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr); + + format = yuy2_format; + format.ddpfPixelFormat.dwRBitMask = 0xf800; + format.ddpfPixelFormat.dwGBitMask = 0x07e0; + format.ddpfPixelFormat.dwBBitMask = 0x001f; + hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &format, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb565_mt); + ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr); + + format = rgb8_format; + format.dwFlags = 0; + hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &format, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb565_mt); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IPin_Disconnect(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ref = IAMMultiMediaStream_Release(mmstream); ok(!ref, "Got outstanding refcount %d.\n", ref); IPin_Release(pin);