Wine-devel
Threads by month
- ----- 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
August 2020
- 78 participants
- 638 discussions
08 Sep '20
Signed-off-by: Anton Baskanov <baskanov(a)gmail.com>
---
dlls/amstream/ddrawstream.c | 46 ++++++++++-
dlls/amstream/tests/amstream.c | 135 +++++++++++++++++++++++++++++++++
2 files changed, 178 insertions(+), 3 deletions(-)
diff --git a/dlls/amstream/ddrawstream.c b/dlls/amstream/ddrawstream.c
index 0d3f2d0d4b8..0a291f37214 100644
--- a/dlls/amstream/ddrawstream.c
+++ b/dlls/amstream/ddrawstream.c
@@ -47,6 +47,7 @@ struct ddraw_stream
IPin *peer;
IMemAllocator *allocator;
AM_MEDIA_TYPE mt;
+ DDSURFACEDESC format;
};
static HRESULT ddrawstreamsample_create(struct ddraw_stream *parent, IDirectDrawSurface *surface,
@@ -363,11 +364,40 @@ static HRESULT WINAPI ddraw_IDirectDrawMediaStream_GetFormat(IDirectDrawMediaStr
DDSURFACEDESC *current_format, IDirectDrawPalette **palette,
DDSURFACEDESC *desired_format, DWORD *flags)
{
- FIXME("(%p)->(%p,%p,%p,%p) stub!\n", iface, current_format, palette, desired_format,
- flags);
+ struct ddraw_stream *stream = impl_from_IDirectDrawMediaStream(iface);
+
+ TRACE("stream %p, current_format %p, palette %p, desired_format %p, flags %p.\n", stream, current_format, palette,
+ desired_format, flags);
+
+ EnterCriticalSection(&stream->cs);
- return MS_E_NOSTREAM;
+ if (!stream->peer)
+ {
+ LeaveCriticalSection(&stream->cs);
+ return MS_E_NOSTREAM;
+ }
+
+ if (current_format)
+ {
+ *current_format = stream->format;
+ current_format->dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
+ }
+ if (palette)
+ *palette = NULL;
+
+ if (desired_format)
+ {
+ *desired_format = stream->format;
+ desired_format->dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
+ }
+
+ if (flags)
+ *flags = 0;
+
+ LeaveCriticalSection(&stream->cs);
+
+ return S_OK;
}
static HRESULT WINAPI ddraw_IDirectDrawMediaStream_SetFormat(IDirectDrawMediaStream *iface,
@@ -637,6 +667,7 @@ static HRESULT WINAPI ddraw_sink_Connect(IPin *iface, IPin *peer, const AM_MEDIA
static HRESULT WINAPI ddraw_sink_ReceiveConnection(IPin *iface, IPin *peer, const AM_MEDIA_TYPE *mt)
{
+ const VIDEOINFOHEADER *video_info = (const VIDEOINFOHEADER *)mt->pbFormat;
struct ddraw_stream *stream = impl_from_IPin(iface);
PIN_DIRECTION dir;
@@ -673,6 +704,9 @@ static HRESULT WINAPI ddraw_sink_ReceiveConnection(IPin *iface, IPin *peer, cons
CopyMediaType(&stream->mt, mt);
IPin_AddRef(stream->peer = peer);
+ stream->format.dwWidth = video_info->bmiHeader.biWidth;
+ stream->format.dwHeight = abs(video_info->bmiHeader.biHeight);
+
LeaveCriticalSection(&stream->cs);
return S_OK;
@@ -981,6 +1015,12 @@ HRESULT ddraw_stream_create(IUnknown *outer, void **out)
object->IPin_iface.lpVtbl = &ddraw_sink_vtbl;
object->ref = 1;
+ object->format.dwSize = sizeof(DDSURFACEDESC);
+ object->format.dwFlags = DDSD_CAPS;
+ object->format.dwWidth = 100;
+ object->format.dwHeight = 100;
+ object->format.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
+
InitializeCriticalSection(&object->cs);
TRACE("Created ddraw stream %p.\n", object);
diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c
index f4c033a1807..934639258d6 100644
--- a/dlls/amstream/tests/amstream.c
+++ b/dlls/amstream/tests/amstream.c
@@ -51,6 +51,26 @@ static const AM_MEDIA_TYPE audio_mt =
.pbFormat = (BYTE *)&audio_format,
};
+static const VIDEOINFO rgb32_video_info =
+{
+ .bmiHeader.biSize = sizeof(BITMAPINFOHEADER),
+ .bmiHeader.biWidth = 333,
+ .bmiHeader.biHeight = -444,
+ .bmiHeader.biPlanes = 1,
+ .bmiHeader.biBitCount = 32,
+ .bmiHeader.biCompression = BI_RGB,
+};
+
+static const AM_MEDIA_TYPE rgb32_mt =
+{
+ /* MEDIATYPE_Video, MEDIASUBTYPE_RGB32, FORMAT_VideoInfo */
+ .majortype = {0x73646976, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}},
+ .subtype = {0xe436eb7e, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}},
+ .formattype = {0x05589f80, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}},
+ .cbFormat = sizeof(VIDEOINFO),
+ .pbFormat = (BYTE *)&rgb32_video_info,
+};
+
static const WCHAR primary_video_sink_id[] = L"I{A35FF56A-9FDA-11D0-8FDF-00C04FD9189D}";
static const WCHAR primary_audio_sink_id[] = L"I{A35FF56B-9FDA-11D0-8FDF-00C04FD9189D}";
@@ -4474,6 +4494,120 @@ static void test_ddrawstream_initialize(void)
ok(!ref, "Got outstanding refcount %d.\n", ref);
}
+static void check_ddrawstream_get_format(IDirectDrawMediaStream *ddraw_stream)
+{
+ DDSURFACEDESC current_format;
+ DDSURFACEDESC desired_format;
+ IDirectDrawPalette *palette;
+ DWORD flags;
+ HRESULT hr;
+
+ memset(¤t_format, 0xcc, sizeof(current_format));
+ current_format.dwSize = sizeof(current_format);
+ palette = (IDirectDrawPalette *)0xdeadbeef;
+ memset(&desired_format, 0xcc, sizeof(desired_format));
+ desired_format.dwSize = sizeof(desired_format);
+ flags = 0xdeadbeef;
+ hr = IDirectDrawMediaStream_GetFormat(ddraw_stream, ¤t_format, &palette, &desired_format, &flags);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(current_format.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS), "Got flags %#x.\n", current_format.dwFlags);
+ ok(current_format.dwWidth == 333, "Got width %u.\n", current_format.dwWidth);
+ ok(current_format.dwHeight == 444, "Got height %u.\n", current_format.dwHeight);
+ ok(current_format.ddsCaps.dwCaps == (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY),
+ "Got caps %#x.\n", current_format.ddsCaps.dwCaps);
+ ok(palette == NULL, "Got palette %p.\n", palette);
+ ok(desired_format.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT), "Got flags %#x.\n", desired_format.dwFlags);
+ ok(desired_format.dwWidth == 333, "Got width %u.\n", desired_format.dwWidth);
+ ok(desired_format.dwHeight == 444, "Got height %u.\n", desired_format.dwHeight);
+ ok(flags == 0, "Got flags %#x.\n", flags);
+}
+
+static void test_ddrawstream_get_format(void)
+{
+ IAMMultiMediaStream *mmstream = create_ammultimediastream();
+ IDirectDrawMediaStream *ddraw_stream;
+ DDSURFACEDESC current_format;
+ DDSURFACEDESC desired_format;
+ IDirectDrawPalette *palette;
+ struct testfilter source;
+ IGraphBuilder *graph;
+ IMediaStream *stream;
+ VIDEOINFO video_info;
+ AM_MEDIA_TYPE mt;
+ DWORD flags;
+ HRESULT hr;
+ ULONG ref;
+ IPin *pin;
+
+ hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!!graph, "Expected non-NULL graph.\n");
+
+ testfilter_init(&source);
+
+ hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, L"source");
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ current_format.dwSize = sizeof(current_format);
+ desired_format.dwSize = sizeof(desired_format);
+ hr = IDirectDrawMediaStream_GetFormat(ddraw_stream, ¤t_format, &palette, &desired_format, &flags);
+ ok(hr == MS_E_NOSTREAM, "Got hr %#x.\n", hr);
+
+ video_info = rgb32_video_info;
+ video_info.rcSource.right = 222;
+ video_info.rcSource.bottom = 333;
+ video_info.rcTarget.right = 444;
+ video_info.rcTarget.bottom = 666;
+ mt = rgb32_mt;
+ mt.pbFormat = (BYTE *)&video_info;
+ hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ check_ddrawstream_get_format(ddraw_stream);
+
+ hr = IGraphBuilder_Disconnect(graph, pin);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ video_info = rgb32_video_info;
+ video_info.bmiHeader.biHeight = 444;
+ mt = rgb32_mt;
+ mt.pbFormat = (BYTE *)&video_info;
+ hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ check_ddrawstream_get_format(ddraw_stream);
+
+ hr = IGraphBuilder_Disconnect(graph, pin);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ current_format.dwSize = sizeof(current_format);
+ desired_format.dwSize = sizeof(desired_format);
+ hr = IDirectDrawMediaStream_GetFormat(ddraw_stream, ¤t_format, &palette, &desired_format, &flags);
+ ok(hr == MS_E_NOSTREAM, "Got hr %#x.\n", hr);
+
+ ref = IAMMultiMediaStream_Release(mmstream);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IGraphBuilder_Release(graph);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ IPin_Release(pin);
+ IDirectDrawMediaStream_Release(ddraw_stream);
+ ref = IMediaStream_Release(stream);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ref = IBaseFilter_Release(&source.filter.IBaseFilter_iface);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+}
+
static void check_ammediastream_join_am_multi_media_stream(const CLSID *clsid)
{
IAMMultiMediaStream *mmstream = create_ammultimediastream();
@@ -5936,6 +6070,7 @@ START_TEST(amstream)
test_ddrawstream_getsetdirectdraw();
test_ddrawstream_receive_connection();
test_ddrawstream_create_sample();
+ test_ddrawstream_get_format();
test_ddrawstreamsample_get_media_stream();
--
2.17.1
2
14
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=35782
Signed-off-by: Robert Wilhelm <robert.wilhelm(a)gmx.net>
---
dlls/vbscript/parser.y | 2 ++
dlls/vbscript/tests/lang.vbs | 6 ++++++
2 files changed, 8 insertions(+)
diff --git a/dlls/vbscript/parser.y b/dlls/vbscript/parser.y
index 71bea72b1b..ad606c1b26 100644
--- a/dlls/vbscript/parser.y
+++ b/dlls/vbscript/parser.y
@@ -221,6 +221,8 @@ SimpleStatement
| tON tERROR tRESUME tNEXT { $$ = new_onerror_statement(ctx, @$, TRUE); CHECK_ERROR; }
| tON tERROR tGOTO '0' { $$ = new_onerror_statement(ctx, @$, FALSE); CHECK_ERROR; }
| tCONST ConstDeclList { $$ = new_const_statement(ctx, @$, $2); CHECK_ERROR; }
+ | tFOR Identifier '=' Expression tTO Expression Step_opt ':' SimpleStatement ':' tNEXT
+ { $$ = new_forto_statement(ctx, @$, $2, $4, $6, $7, $9); CHECK_ERROR; }
| tFOR Identifier '=' Expression tTO Expression Step_opt StSep StatementsNl_opt tNEXT
{ $$ = new_forto_statement(ctx, @$, $2, $4, $6, $7, $9); CHECK_ERROR; }
| tFOR tEACH Identifier tIN Expression StSep StatementsNl_opt tNEXT
diff --git a/dlls/vbscript/tests/lang.vbs b/dlls/vbscript/tests/lang.vbs
index 94e2bbd436..5754292079 100644
--- a/dlls/vbscript/tests/lang.vbs
+++ b/dlls/vbscript/tests/lang.vbs
@@ -542,6 +542,12 @@ for x = 1 to 5 :
Call ok(false, "exit for not escaped the loop?")
next
+dim a1(8)
+a1(6)=8
+for x=1 to 8:a1(x)=x-1:next
+Call ok(a1(6) = 5, "colon used in for loop")
+
+
do while true
for x = 1 to 100
exit do
--
2.26.2
3
6
[PATCH] shell32: Add a browser custom protocol handler to run the application through the web browser
by Haoyang Chen 08 Sep '20
by Haoyang Chen 08 Sep '20
08 Sep '20
When functions like /ShellExecute/ use PIDL to open a URL, it will not work.
It’s a bit difficult to test this, you need to add the corresponding
browser custom protocol handler to the registry.
3
3
07 Sep '20
Signed-off-by: Jactry Zeng <jzeng(a)codeweavers.com>
---
v3:
- Fix some leaks.
- Add more tests.
- Check SysAllocString() result in CreateProperty().
v2: No changes.
---
dlls/comsvcs/comsvcs_private.h | 2 +
dlls/comsvcs/property.c | 250 ++++++++++++++++++++++++++++++++-
dlls/comsvcs/tests/property.c | 81 +++++++++++
3 files changed, 331 insertions(+), 2 deletions(-)
diff --git a/dlls/comsvcs/comsvcs_private.h b/dlls/comsvcs/comsvcs_private.h
index eee6e9938c..3eeb9d751a 100644
--- a/dlls/comsvcs/comsvcs_private.h
+++ b/dlls/comsvcs/comsvcs_private.h
@@ -38,6 +38,7 @@ enum tid_t
NULL_tid,
ISharedPropertyGroupManager_tid,
ISharedPropertyGroup_tid,
+ ISharedProperty_tid,
LAST_tid
};
@@ -46,6 +47,7 @@ static REFIID tid_ids[] =
&IID_NULL,
&IID_ISharedPropertyGroupManager,
&IID_ISharedPropertyGroup,
+ &IID_ISharedProperty,
};
HRESULT get_typeinfo(enum tid_t tid, ITypeInfo **typeinfo);
diff --git a/dlls/comsvcs/property.c b/dlls/comsvcs/property.c
index a73964d288..b2b3920a2d 100644
--- a/dlls/comsvcs/property.c
+++ b/dlls/comsvcs/property.c
@@ -21,6 +21,13 @@
WINE_DEFAULT_DEBUG_CHANNEL(comsvcs);
+struct shared_property
+{
+ ISharedProperty ISharedProperty_iface;
+ LONG refcount;
+ BSTR name;
+};
+
struct group_manager
{
ISharedPropertyGroupManager ISharedPropertyGroupManager_iface;
@@ -37,10 +44,44 @@ struct property_group
LONG isolation, release;
struct list entry;
BSTR name;
+ struct shared_property *properties;
+ size_t capacity, count;
+ CRITICAL_SECTION cs;
};
static struct group_manager *group_manager = NULL;
+static BOOL comsvcs_array_reserve(void **elements, size_t *capacity, size_t count, size_t size)
+{
+ size_t new_capacity, max_capacity;
+ void *new_elements;
+
+ if (count <= *capacity)
+ return TRUE;
+
+ max_capacity = ~(size_t)0 / size;
+ if (count > max_capacity)
+ return FALSE;
+
+ new_capacity = max(4, *capacity);
+ while (new_capacity < count && new_capacity <= max_capacity / 2)
+ new_capacity *= 2;
+ if (new_capacity < count)
+ new_capacity = max_capacity;
+
+ if (!*elements)
+ new_elements = heap_alloc_zero(new_capacity * size);
+ else
+ new_elements = heap_realloc(*elements, new_capacity * size);
+ if (!new_elements)
+ return FALSE;
+
+ *elements = new_elements;
+ *capacity = new_capacity;
+
+ return TRUE;
+}
+
static inline struct group_manager *impl_from_ISharedPropertyGroupManager(ISharedPropertyGroupManager *iface)
{
return CONTAINING_RECORD(iface, struct group_manager, ISharedPropertyGroupManager_iface);
@@ -51,6 +92,139 @@ static inline struct property_group *impl_from_ISharedPropertyGroup(ISharedPrope
return CONTAINING_RECORD(iface, struct property_group, ISharedPropertyGroup_iface);
}
+static inline struct shared_property *impl_from_ISharedProperty(ISharedProperty *iface)
+{
+ return CONTAINING_RECORD(iface, struct shared_property, ISharedProperty_iface);
+}
+
+static HRESULT WINAPI shared_property_QueryInterface(ISharedProperty *iface, REFIID riid, void **out)
+{
+ struct shared_property *property = impl_from_ISharedProperty(iface);
+
+ TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
+
+ if (IsEqualGUID(riid, &IID_IUnknown)
+ || IsEqualGUID(riid, &IID_IDispatch)
+ || IsEqualGUID(riid, &IID_ISharedProperty))
+ {
+ *out = &property->ISharedProperty_iface;
+ IUnknown_AddRef((IUnknown *)*out);
+ return S_OK;
+ }
+
+ WARN("%s not implemented.\n", debugstr_guid(riid));
+ *out = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI shared_property_AddRef(ISharedProperty *iface)
+{
+ struct shared_property *property = impl_from_ISharedProperty(iface);
+ ULONG refcount = InterlockedIncrement(&property->refcount);
+
+ TRACE("%p increasing refcount to %u.\n", iface, refcount);
+
+ return refcount;
+}
+
+static ULONG WINAPI shared_property_Release(ISharedProperty *iface)
+{
+ struct shared_property *property = impl_from_ISharedProperty(iface);
+ ULONG refcount = InterlockedDecrement(&property->refcount);
+
+ TRACE("%p decreasing refcount to %u.\n", iface, refcount);
+
+ if (!refcount)
+ {
+ SysFreeString(property->name);
+ }
+
+ return refcount;
+}
+
+static HRESULT WINAPI shared_property_GetTypeInfoCount(ISharedProperty *iface, UINT *info)
+{
+ TRACE("iface %p, info %p.\n", iface, info);
+
+ if (!info)
+ return E_INVALIDARG;
+ *info = 1;
+ return S_OK;
+}
+
+static HRESULT WINAPI shared_property_GetTypeInfo(ISharedProperty *iface, UINT index, LCID lcid, ITypeInfo **info)
+{
+ TRACE("iface %p, index %u, lcid %u, info %p.\n", iface, index, lcid, info);
+
+ if (index)
+ return DISP_E_BADINDEX;
+
+ return get_typeinfo(ISharedProperty_tid, info);
+}
+
+static HRESULT WINAPI shared_property_GetIDsOfNames(ISharedProperty *iface, REFIID riid, LPOLESTR *names, UINT count,
+ LCID lcid, DISPID *dispid)
+{
+ ITypeInfo *typeinfo;
+ HRESULT hr;
+
+ TRACE("iface %p, riid %s, names %p, count %u, lcid %u, dispid %p.\n",
+ iface, debugstr_guid(riid), names, count, lcid, dispid);
+
+ hr = get_typeinfo(ISharedProperty_tid, &typeinfo);
+ if (SUCCEEDED(hr))
+ {
+ hr = ITypeInfo_GetIDsOfNames(typeinfo, names, count, dispid);
+ ITypeInfo_Release(typeinfo);
+ }
+
+ return hr;
+}
+
+static HRESULT WINAPI shared_property_Invoke(ISharedProperty *iface, DISPID member, REFIID riid, LCID lcid,
+ WORD flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *except, UINT *argerr)
+{
+ ITypeInfo *typeinfo;
+ HRESULT hr;
+
+ TRACE("iface %p, member %u, riid %s, lcid %u, flags %x, params %p, result %p, except %p, argerr %p.\n",
+ iface, member, debugstr_guid(riid), lcid, flags, params, result, except, argerr);
+
+ hr = get_typeinfo(ISharedProperty_tid, &typeinfo);
+ if (SUCCEEDED(hr))
+ {
+ hr = ITypeInfo_Invoke(typeinfo, iface, member, flags, params, result, except, argerr);
+ ITypeInfo_Release(typeinfo);
+ }
+
+ return hr;
+}
+
+static HRESULT WINAPI shared_property_get_Value(ISharedProperty *iface, VARIANT *value)
+{
+ FIXME("iface %p, value %p: stub.\n", iface, value);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI shared_property_put_Value(ISharedProperty *iface, VARIANT value)
+{
+ FIXME("iface %p, value %s: stub.\n", iface, debugstr_variant(&value));
+ return E_NOTIMPL;
+}
+
+static const ISharedPropertyVtbl shared_property_vtbl =
+{
+ shared_property_QueryInterface,
+ shared_property_AddRef,
+ shared_property_Release,
+ shared_property_GetTypeInfoCount,
+ shared_property_GetTypeInfo,
+ shared_property_GetIDsOfNames,
+ shared_property_Invoke,
+ shared_property_get_Value,
+ shared_property_put_Value
+};
+
static HRESULT WINAPI property_group_QueryInterface(ISharedPropertyGroup *iface, REFIID riid, void **out)
{
struct property_group *group = impl_from_ISharedPropertyGroup(iface);
@@ -93,12 +267,14 @@ static ULONG WINAPI property_group_Release(ISharedPropertyGroup *iface)
struct group_manager *manager = group->parent;
SysFreeString(group->name);
+ heap_free(group->properties);
EnterCriticalSection(&manager->cs);
list_remove(&group->entry);
LeaveCriticalSection(&manager->cs);
ISharedPropertyGroupManager_Release(&manager->ISharedPropertyGroupManager_iface);
+ DeleteCriticalSection(&group->cs);
heap_free(group);
}
@@ -163,6 +339,18 @@ static HRESULT WINAPI property_group_Invoke(ISharedPropertyGroup *iface, DISPID
return hr;
}
+static struct shared_property *find_shared_property(struct property_group *group, BSTR name)
+{
+ int index;
+
+ for (index = 0; index < group->count; index++)
+ {
+ if (!lstrcmpW(group->properties[index].name, name))
+ return &group->properties[index];
+ }
+ return NULL;
+}
+
static HRESULT WINAPI property_group_CreatePropertyByPosition(ISharedPropertyGroup *iface, int index,
VARIANT_BOOL *exists, ISharedProperty **property)
{
@@ -180,8 +368,54 @@ static HRESULT WINAPI property_group_get_PropertyByPosition(ISharedPropertyGroup
static HRESULT WINAPI property_group_CreateProperty(ISharedPropertyGroup *iface, BSTR name, VARIANT_BOOL *exists,
ISharedProperty **property)
{
- FIXME("iface %p, name %s, exists %p, property %p: stub.\n", iface, debugstr_w(name), exists, property);
- return E_NOTIMPL;
+ struct property_group *group = impl_from_ISharedPropertyGroup(iface);
+ struct shared_property *shared_property;
+ BSTR property_name;
+ HRESULT hr;
+
+ TRACE("iface %p, name %s, exists %p, property %p.\n", iface, debugstr_w(name), exists, property);
+
+ EnterCriticalSection(&group->cs);
+
+ shared_property = find_shared_property(group, name);
+ if (!shared_property)
+ {
+ property_name = SysAllocString(name);
+ if (!property_name)
+ {
+ heap_free(shared_property);
+ LeaveCriticalSection(&group->cs);
+ return E_OUTOFMEMORY;
+ }
+
+ if (!comsvcs_array_reserve((void **)&group->properties, &group->capacity, group->count + 1,
+ sizeof(*group->properties)))
+ {
+ SysFreeString(property_name);
+ LeaveCriticalSection(&group->cs);
+ return E_OUTOFMEMORY;
+ }
+
+ shared_property = &group->properties[group->count];
+ shared_property->refcount = 1;
+ shared_property->name = property_name;
+ shared_property->ISharedProperty_iface.lpVtbl = &shared_property_vtbl;
+
+ group->count++;
+ *exists = FALSE;
+ *property = &shared_property->ISharedProperty_iface;
+ hr = S_OK;
+ }
+ else
+ {
+ *exists = TRUE;
+ hr = ISharedProperty_QueryInterface(&shared_property->ISharedProperty_iface,
+ &IID_ISharedProperty, (void **)property);
+ }
+
+ LeaveCriticalSection(&group->cs);
+
+ return hr;
}
static HRESULT WINAPI property_group_get_Property(ISharedPropertyGroup *iface, BSTR name, ISharedProperty **property)
@@ -349,6 +583,17 @@ static HRESULT WINAPI group_manager_CreatePropertyGroup(ISharedPropertyGroupMana
property_group->isolation = *isolation;
property_group->release = *release;
property_group->refcount = 1;
+ property_group->capacity = 0;
+ property_group->count = 0;
+ property_group->properties = NULL;
+ if (!comsvcs_array_reserve((void **)&property_group->properties, &property_group->capacity, 2,
+ sizeof(*property_group->properties)))
+ {
+ heap_free(property_group);
+ LeaveCriticalSection(&manager->cs);
+ return E_OUTOFMEMORY;
+ }
+
property_group->name = SysAllocString(name);
if (!property_group->name)
{
@@ -356,6 +601,7 @@ static HRESULT WINAPI group_manager_CreatePropertyGroup(ISharedPropertyGroupMana
heap_free(property_group);
return E_OUTOFMEMORY;
}
+ InitializeCriticalSection(&property_group->cs);
list_add_tail(&manager->property_groups, &property_group->entry);
diff --git a/dlls/comsvcs/tests/property.c b/dlls/comsvcs/tests/property.c
index 7321bbcfe6..1f62656e7a 100644
--- a/dlls/comsvcs/tests/property.c
+++ b/dlls/comsvcs/tests/property.c
@@ -320,12 +320,93 @@ static void test_property_group(void)
ISharedPropertyGroupManager_Release(manager);
}
+static void test_shared_property(void)
+{
+ ISharedProperty *property, *property1;
+ ISharedPropertyGroupManager *manager;
+ ULONG refcount, expected_refcount;
+ ISharedPropertyGroup *group;
+ BSTR name, property_name;
+ LONG isolation, release;
+ VARIANT_BOOL exists;
+ IDispatch *dispatch;
+ HRESULT hr;
+ static const struct test_name_id test_name_ids[] =
+ {
+ {L"Value", DISPID_VALUE},
+ };
+
+ hr = CoCreateInstance(&CLSID_SharedPropertyGroupManager, NULL, CLSCTX_INPROC_SERVER,
+ &IID_ISharedPropertyGroupManager, (void **)&manager);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ name = SysAllocString(L"testgroupname");
+ isolation = 0;
+ release = 0;
+ exists = FALSE;
+ hr = ISharedPropertyGroupManager_CreatePropertyGroup(manager, name, &isolation, &release, &exists, &group);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ SysFreeString(name);
+
+ property_name = SysAllocString(L"testpropertyname");
+ exists = TRUE;
+ expected_refcount = get_refcount(group);
+ hr = ISharedPropertyGroup_CreateProperty(group, property_name, &exists, &property);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!exists, "Got unexpected value: %d.\n", exists);
+ refcount = get_refcount(group);
+ ok(refcount == expected_refcount, "Got refcount: %u, expected %u.\n", refcount, expected_refcount);
+
+ hr = ISharedPropertyGroup_get_PropertyByPosition(group, 0, &property1);
+ todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ hr = ISharedPropertyGroup_get_PropertyByPosition(group, 1, &property1);
+ todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+
+ exists = FALSE;
+ expected_refcount = get_refcount(property) + 1;
+ hr = ISharedPropertyGroup_CreateProperty(group, property_name, &exists, &property1);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!!exists, "Got unexpected value: %d.\n", exists);
+ refcount = get_refcount(property);
+ ok(refcount == expected_refcount, "Got refcount: %u, expected %u.\n", refcount, expected_refcount);
+ expected_refcount--;
+ ISharedProperty_Release(property1);
+ refcount = get_refcount(property);
+ ok(refcount == expected_refcount, "Got refcount: %u, expected %u.\n", refcount, expected_refcount);
+
+ expected_refcount = get_refcount(property) + 1;
+ property1 = NULL;
+ hr = ISharedPropertyGroup_get_Property(group, property_name, &property1);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(property1 == property, "Got wrong pointer %p.\n", property);
+ refcount = get_refcount(property);
+ todo_wine ok(refcount == expected_refcount, "Got refcount: %u, expected %u.\n", refcount, expected_refcount);
+ if (property1)
+ ISharedProperty_Release(property1);
+ SysFreeString(property_name);
+
+ property_name = SysAllocString(L"Testpropertyname");
+ hr = ISharedPropertyGroup_get_Property(group, property_name, &property1);
+ todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ SysFreeString(property_name);
+
+ hr = ISharedProperty_QueryInterface(property, &IID_IDispatch, (void **)&dispatch);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ TEST_TYPEINFO(dispatch, test_name_ids, ARRAY_SIZE(test_name_ids), &IID_ISharedProperty);
+ IDispatch_Release(dispatch);
+
+ ISharedProperty_Release(property);
+ ISharedPropertyGroup_Release(group);
+ ISharedPropertyGroupManager_Release(manager);
+}
+
START_TEST(property)
{
CoInitialize(NULL);
test_interfaces();
test_property_group();
+ test_shared_property();
CoUninitialize();
}
--
2.28.0
3
2
[PATCH v3 3/5] comsvcs: Implement ISharedPropertyGroupManager_CreatePropertyGroup().
by Jactry Zeng 07 Sep '20
by Jactry Zeng 07 Sep '20
07 Sep '20
Signed-off-by: Jactry Zeng <jzeng(a)codeweavers.com>
---
v3:
- Free group in ISharedPropertyGroup_Release().
- Use LIST_FOR_EACH_ENTRY instead of LIST_FOR_EACH_ENTRY_SAFE in find_propery_group().
- Add CRITICAL_SECTION for struct group_manager.
- Simplify CreatePropertyGroup() and check SysAllocString() result.
- Fix some leaks.
- Add more tests.
v2:
- Storage struct group_manager * instead of ISharedPropertyGroupManager * in struct property_group;
- Storage property groups to a link instead of an array;
- Add more tests of ISharedPropertyGroupManager_CreatePropertyGroup().
---
dlls/comsvcs/comsvcs_private.h | 2 +
dlls/comsvcs/property.c | 244 ++++++++++++++++++++++++++++++++-
dlls/comsvcs/tests/property.c | 129 +++++++++++++++++
include/winerror.h | 11 ++
4 files changed, 384 insertions(+), 2 deletions(-)
diff --git a/dlls/comsvcs/comsvcs_private.h b/dlls/comsvcs/comsvcs_private.h
index 8a67bcffd8..eee6e9938c 100644
--- a/dlls/comsvcs/comsvcs_private.h
+++ b/dlls/comsvcs/comsvcs_private.h
@@ -37,6 +37,7 @@ enum tid_t
{
NULL_tid,
ISharedPropertyGroupManager_tid,
+ ISharedPropertyGroup_tid,
LAST_tid
};
@@ -44,6 +45,7 @@ static REFIID tid_ids[] =
{
&IID_NULL,
&IID_ISharedPropertyGroupManager,
+ &IID_ISharedPropertyGroup,
};
HRESULT get_typeinfo(enum tid_t tid, ITypeInfo **typeinfo);
diff --git a/dlls/comsvcs/property.c b/dlls/comsvcs/property.c
index 44e111fe71..045415e246 100644
--- a/dlls/comsvcs/property.c
+++ b/dlls/comsvcs/property.c
@@ -17,6 +17,7 @@
*/
#include <comsvcs_private.h>
+#include <wine/list.h>
WINE_DEFAULT_DEBUG_CHANNEL(comsvcs);
@@ -24,6 +25,18 @@ struct group_manager
{
ISharedPropertyGroupManager ISharedPropertyGroupManager_iface;
LONG refcount;
+ struct list property_groups;
+ CRITICAL_SECTION cs;
+};
+
+struct property_group
+{
+ ISharedPropertyGroup ISharedPropertyGroup_iface;
+ LONG refcount;
+ struct group_manager *parent;
+ LONG isolation, release;
+ struct list entry;
+ BSTR name;
};
static struct group_manager *group_manager = NULL;
@@ -33,6 +46,165 @@ static inline struct group_manager *impl_from_ISharedPropertyGroupManager(IShare
return CONTAINING_RECORD(iface, struct group_manager, ISharedPropertyGroupManager_iface);
}
+static inline struct property_group *impl_from_ISharedPropertyGroup(ISharedPropertyGroup *iface)
+{
+ return CONTAINING_RECORD(iface, struct property_group, ISharedPropertyGroup_iface);
+}
+
+static HRESULT WINAPI property_group_QueryInterface(ISharedPropertyGroup *iface, REFIID riid, void **out)
+{
+ struct property_group *group = impl_from_ISharedPropertyGroup(iface);
+
+ TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
+
+ if (IsEqualGUID(riid, &IID_IUnknown)
+ || IsEqualGUID(riid, &IID_IDispatch)
+ || IsEqualGUID(riid, &IID_ISharedPropertyGroup))
+ {
+ *out = &group->ISharedPropertyGroup_iface;
+ IUnknown_AddRef((IUnknown *)*out);
+ return S_OK;
+ }
+
+ WARN("%s not implemented.\n", debugstr_guid(riid));
+ *out = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI property_group_AddRef(ISharedPropertyGroup *iface)
+{
+ struct property_group *group = impl_from_ISharedPropertyGroup(iface);
+ ULONG refcount = InterlockedIncrement(&group->refcount);
+
+ TRACE("%p increasing refcount to %u.\n", iface, refcount);
+
+ return refcount;
+}
+
+static ULONG WINAPI property_group_Release(ISharedPropertyGroup *iface)
+{
+ struct property_group *group = impl_from_ISharedPropertyGroup(iface);
+ ULONG refcount = InterlockedDecrement(&group->refcount);
+
+ TRACE("%p decreasing refcount to %u.\n", iface, refcount);
+
+ if (!refcount)
+ {
+ struct group_manager *manager = group->parent;
+
+ SysFreeString(group->name);
+
+ EnterCriticalSection(&manager->cs);
+ list_remove(&group->entry);
+ LeaveCriticalSection(&manager->cs);
+
+ ISharedPropertyGroupManager_Release(&manager->ISharedPropertyGroupManager_iface);
+ heap_free(group);
+ }
+
+ return refcount;
+}
+
+static HRESULT WINAPI property_group_GetTypeInfoCount(ISharedPropertyGroup *iface, UINT *info)
+{
+ TRACE("iface %p, info %p.\n", iface, info);
+
+ if (!info)
+ return E_INVALIDARG;
+ *info = 1;
+ return S_OK;
+}
+
+static HRESULT WINAPI property_group_GetTypeInfo(ISharedPropertyGroup *iface, UINT index, LCID lcid, ITypeInfo **info)
+{
+ TRACE("iface %p, index %u, lcid %u, info %p.\n", iface, index, lcid, info);
+
+ if (index)
+ return DISP_E_BADINDEX;
+
+ return get_typeinfo(ISharedPropertyGroup_tid, info);
+}
+
+static HRESULT WINAPI property_group_GetIDsOfNames(ISharedPropertyGroup *iface, REFIID riid, LPOLESTR *names, UINT count,
+ LCID lcid, DISPID *dispid)
+{
+ ITypeInfo *typeinfo;
+ HRESULT hr;
+
+ TRACE("iface %p, riid %s, names %p, count %u, lcid %u, dispid %p.\n",
+ iface, debugstr_guid(riid), names, count, lcid, dispid);
+
+ hr = get_typeinfo(ISharedPropertyGroup_tid, &typeinfo);
+ if (SUCCEEDED(hr))
+ {
+ hr = ITypeInfo_GetIDsOfNames(typeinfo, names, count, dispid);
+ ITypeInfo_Release(typeinfo);
+ }
+
+ return hr;
+}
+
+static HRESULT WINAPI property_group_Invoke(ISharedPropertyGroup *iface, DISPID member, REFIID riid, LCID lcid,
+ WORD flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *except, UINT *argerr)
+{
+ ITypeInfo *typeinfo;
+ HRESULT hr;
+
+ TRACE("iface %p, member %u, riid %s, lcid %u, flags %x, params %p, result %p, except %p, argerr %p.\n",
+ iface, member, debugstr_guid(riid), lcid, flags, params, result, except, argerr);
+
+ hr = get_typeinfo(ISharedPropertyGroup_tid, &typeinfo);
+ if (SUCCEEDED(hr))
+ {
+ hr = ITypeInfo_Invoke(typeinfo, iface, member, flags, params, result, except, argerr);
+ ITypeInfo_Release(typeinfo);
+ }
+
+ return hr;
+}
+
+static HRESULT WINAPI property_group_CreatePropertyByPosition(ISharedPropertyGroup *iface, int index,
+ VARIANT_BOOL *exists, ISharedProperty **property)
+{
+ FIXME("iface %p, index %d, exisits %p, property %p: stub.\n",
+ iface, index, exists, property);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI property_group_get_PropertyByPosition(ISharedPropertyGroup *iface, int index, ISharedProperty **property)
+{
+ FIXME("iface %p, index %d, property %p: stub.\n", iface, index, property);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI property_group_CreateProperty(ISharedPropertyGroup *iface, BSTR name, VARIANT_BOOL *exists,
+ ISharedProperty **property)
+{
+ FIXME("iface %p, name %s, exists %p, property %p: stub.\n", iface, debugstr_w(name), exists, property);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI property_group_get_Property(ISharedPropertyGroup *iface, BSTR name, ISharedProperty **property)
+{
+ FIXME("iface %p, name %s, property %p: stub.\n", iface, debugstr_w(name), property);
+ return E_NOTIMPL;
+}
+
+static const ISharedPropertyGroupVtbl property_group_vtbl =
+{
+ property_group_QueryInterface,
+ property_group_AddRef,
+ property_group_Release,
+ property_group_GetTypeInfoCount,
+ property_group_GetTypeInfo,
+ property_group_GetIDsOfNames,
+ property_group_Invoke,
+ property_group_CreatePropertyByPosition,
+ property_group_get_PropertyByPosition,
+ property_group_CreateProperty,
+ property_group_get_Property,
+};
+
static HRESULT WINAPI group_manager_QueryInterface(ISharedPropertyGroupManager *iface, REFIID riid, void **out)
{
struct group_manager *manager = impl_from_ISharedPropertyGroupManager(iface);
@@ -131,12 +303,77 @@ static HRESULT WINAPI group_manager_Invoke(ISharedPropertyGroupManager *iface, D
return hr;
}
+static struct property_group *find_propery_group(struct group_manager *manager, BSTR name)
+{
+ struct property_group *group;
+
+ LIST_FOR_EACH_ENTRY(group, &group_manager->property_groups, struct property_group, entry)
+ {
+ if (!lstrcmpW(group->name, name))
+ return group;
+ }
+ return NULL;
+}
+
static HRESULT WINAPI group_manager_CreatePropertyGroup(ISharedPropertyGroupManager *iface, BSTR name, LONG *isolation,
LONG *release, VARIANT_BOOL *exists, ISharedPropertyGroup **group)
{
- FIXME("iface %p, name %s, isolation %p, release %p, exists %p, group %p: stub.\n",
+ struct group_manager *manager = impl_from_ISharedPropertyGroupManager(iface);
+ struct property_group *property_group;
+
+ TRACE("iface %p, name %s, isolation %p, release %p, exists %p, group %p.\n",
iface, debugstr_w(name), isolation, release, exists, group);
- return E_NOTIMPL;
+
+ if (!name)
+ return E_POINTER;
+
+ if (*isolation > 1 || *release > 1)
+ return E_INVALIDARG;
+
+ if (*isolation || *release)
+ FIXME("Unsopported mode: isolation %d, release %d.\n", *isolation, *release);
+
+ EnterCriticalSection(&manager->cs);
+
+ property_group = find_propery_group(manager, name);
+ if (!property_group)
+ {
+ property_group = heap_alloc(sizeof(*property_group));
+ if (!property_group)
+ {
+ LeaveCriticalSection(&manager->cs);
+ return E_OUTOFMEMORY;
+ }
+ property_group->ISharedPropertyGroup_iface.lpVtbl = &property_group_vtbl;
+ property_group->parent = manager;
+ property_group->isolation = *isolation;
+ property_group->release = *release;
+ property_group->refcount = 1;
+ property_group->name = SysAllocString(name);
+ if (!property_group->name)
+ {
+ LeaveCriticalSection(&manager->cs);
+ heap_free(property_group);
+ return E_OUTOFMEMORY;
+ }
+
+ list_add_tail(&manager->property_groups, &property_group->entry);
+
+ *exists = FALSE;
+ ISharedPropertyGroupManager_AddRef(&property_group->parent->ISharedPropertyGroupManager_iface);
+ }
+ else
+ {
+ *exists = TRUE;
+ *isolation = property_group->isolation;
+ *release = property_group->release;
+ ISharedPropertyGroup_AddRef(&property_group->ISharedPropertyGroup_iface);
+ }
+ *group = &property_group->ISharedPropertyGroup_iface;
+
+ LeaveCriticalSection(&manager->cs);
+
+ return S_OK;
}
static HRESULT WINAPI group_manager_get_Group(ISharedPropertyGroupManager *iface, BSTR name, ISharedPropertyGroup **group)
@@ -182,9 +419,12 @@ HRESULT WINAPI group_manager_create(IClassFactory *iface, IUnknown *outer, REFII
}
manager->ISharedPropertyGroupManager_iface.lpVtbl = &group_manager_vtbl;
manager->refcount = 1;
+ list_init(&manager->property_groups);
+ InitializeCriticalSection(&manager->cs);
if (InterlockedCompareExchangePointer((void **)&group_manager, manager, NULL))
{
+ DeleteCriticalSection(&manager->cs);
heap_free(manager);
}
}
diff --git a/dlls/comsvcs/tests/property.c b/dlls/comsvcs/tests/property.c
index 2cc7ff1d44..8ac5e522f5 100644
--- a/dlls/comsvcs/tests/property.c
+++ b/dlls/comsvcs/tests/property.c
@@ -164,11 +164,140 @@ static void test_interfaces(void)
ISharedPropertyGroupManager_Release(manager);
}
+static void test_property_group(void)
+{
+ ISharedPropertyGroup *group, *group1;
+ ISharedPropertyGroupManager *manager;
+ ULONG refcount, expected_refcount;
+ LONG isolation, release;
+ VARIANT_BOOL exists;
+ IDispatch *dispatch;
+ HRESULT hr;
+ BSTR name;
+ static const struct test_name_id test_name_ids[] =
+ {
+ {L"CreatePropertyByPosition", 0x1},
+ {L"PropertyByPosition", 0x2},
+ {L"CreateProperty", 0x3},
+ {L"Property", 0x4},
+ };
+
+ hr = CoCreateInstance(&CLSID_SharedPropertyGroupManager, NULL, CLSCTX_INPROC_SERVER,
+ &IID_ISharedPropertyGroupManager, (void **)&manager);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = ISharedPropertyGroupManager_CreatePropertyGroup(manager, NULL, &isolation, &release, &exists, &group);
+ ok(hr == E_POINTER, "Got hr %#x.\n", hr);
+
+ name = SysAllocString(L"testgroupname");
+ isolation = 2;
+ release = 0;
+ hr = ISharedPropertyGroupManager_CreatePropertyGroup(manager, name, &isolation, &release, &exists, &group);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+
+ /* Crash on Windows */
+ if (0)
+ {
+ ISharedPropertyGroupManager_CreatePropertyGroup(manager, name, NULL, &release, &exists, &group);
+ ISharedPropertyGroupManager_CreatePropertyGroup(manager, name, &isolation, NULL, &exists, &group);
+ ISharedPropertyGroupManager_CreatePropertyGroup(manager, name, &isolation, &release, NULL, &group);
+ }
+
+ isolation = 0;
+ release = 2;
+ hr = ISharedPropertyGroupManager_CreatePropertyGroup(manager, name, &isolation, &release, &exists, &group);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+
+ isolation = 1;
+ release = 0;
+ hr = ISharedPropertyGroupManager_CreatePropertyGroup(manager, name, &isolation, &release, &exists, &group);
+ todo_wine ok(hr == CONTEXT_E_NOCONTEXT, "Got hr %#x.\n", hr);
+ if (group)
+ ISharedPropertyGroup_Release(group);
+
+ isolation = 0;
+ release = 0;
+ exists = TRUE;
+ expected_refcount = get_refcount(manager) + 1;
+ hr = ISharedPropertyGroupManager_CreatePropertyGroup(manager, name, &isolation, &release, &exists, &group);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!exists, "Got unexpected value %d.\n", exists);
+ refcount = get_refcount(group);
+ ok(refcount == 1, "Got unexpected refcount: %u.\n", refcount);
+
+ refcount = get_refcount(manager);
+ ok(refcount == expected_refcount, "Got refcount: %u, expected %u.\n", refcount, expected_refcount);
+ ISharedPropertyGroup_AddRef(group);
+ refcount = get_refcount(manager);
+ ok(refcount == expected_refcount, "Got refcount: %u, expected %u.\n", refcount, expected_refcount);
+ ISharedPropertyGroup_Release(group);
+ refcount = get_refcount(manager);
+ ok(refcount == expected_refcount, "Got refcount: %u, expected %u.\n", refcount, expected_refcount);
+
+ /* Create an existing group */
+ isolation = 1;
+ release = 1;
+ expected_refcount = get_refcount(manager);
+ hr = ISharedPropertyGroupManager_CreatePropertyGroup(manager, name, &isolation, &release, &exists, &group1);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!!exists, "Got unexpected value %d.\n", exists);
+ ok(!isolation, "Got unexpected value %d.\n", isolation);
+ ok(!release, "Got unexpected value %d.\n", release);
+ ok(group == group1, "Got unexpected pointer: %p.\n", group1);
+ refcount = get_refcount(group);
+ ok(refcount == 2, "Got unexpected refcount: %u.\n", refcount);
+ refcount = get_refcount(manager);
+ ok(refcount == expected_refcount, "Got refcount: %u, expected %u.\n", refcount, expected_refcount);
+ ISharedPropertyGroup_Release(group1);
+ refcount = get_refcount(group);
+ ok(refcount == 1, "Got unexpected refcount: %u.\n", refcount);
+ SysFreeString(name);
+
+ name = SysAllocString(L"testgroupname2");
+ isolation = 0;
+ release = 1;
+ exists = TRUE;
+ expected_refcount = get_refcount(manager) + 1;
+ hr = ISharedPropertyGroupManager_CreatePropertyGroup(manager, name, &isolation, &release, &exists, &group1);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!exists, "Got unexpected value %d.\n", exists);
+ refcount = get_refcount(manager);
+ ok(refcount == expected_refcount, "Got refcount: %u, expected %u.\n", refcount, expected_refcount);
+ refcount = get_refcount(group1);
+ todo_wine ok(refcount == 2, "Got unexpected refcount: %u.\n", refcount);
+ SysFreeString(name);
+
+ if (refcount >= 2)
+ {
+ expected_refcount = get_refcount(manager);
+ ISharedPropertyGroup_Release(group1);
+ refcount = get_refcount(manager);
+ todo_wine ok(refcount == expected_refcount, "Got refcount: %u, expected %u.\n", refcount, expected_refcount);
+ expected_refcount = get_refcount(manager) - 1;
+ ISharedPropertyGroup_Release(group1);
+ refcount = get_refcount(manager);
+ todo_wine ok(refcount == expected_refcount, "Got refcount: %u, expected %u.\n", refcount, expected_refcount);
+ }
+
+ hr = ISharedPropertyGroup_QueryInterface(group, &IID_IDispatch, (void **)&dispatch);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ TEST_TYPEINFO(dispatch, test_name_ids, ARRAY_SIZE(test_name_ids), &IID_ISharedPropertyGroup);
+ IDispatch_Release(dispatch);
+
+ expected_refcount = get_refcount(manager) - 1;
+ ISharedPropertyGroup_Release(group);
+ refcount = get_refcount(manager);
+ ok(refcount == expected_refcount, "Got refcount: %u, expected %u.\n", refcount, expected_refcount);
+
+ ISharedPropertyGroupManager_Release(manager);
+}
+
START_TEST(property)
{
CoInitialize(NULL);
test_interfaces();
+ test_property_group();
CoUninitialize();
}
diff --git a/include/winerror.h b/include/winerror.h
index 4ebb48c124..ef5279201d 100644
--- a/include/winerror.h
+++ b/include/winerror.h
@@ -3036,6 +3036,17 @@ static inline HRESULT HRESULT_FROM_WIN32(unsigned int x)
#define CO_E_DECODEFAILED _HRESULT_TYPEDEF_(0x8004021A)
#define CO_E_ACNOTINITIALIZED _HRESULT_TYPEDEF_(0x8004021B)
+#define CONTEXT_E_ABORTED _HRESULT_TYPEDEF_(0x8004e002)
+#define CONTEXT_E_ABORTING _HRESULT_TYPEDEF_(0x8004e003)
+#define CONTEXT_E_NOCONTEXT _HRESULT_TYPEDEF_(0x8004e004)
+#define CONTEXT_E_WOULD_DEADLOCK _HRESULT_TYPEDEF_(0x8004e005)
+#define CONTEXT_E_SYNCH_TIMEOUT _HRESULT_TYPEDEF_(0x8004e006)
+#define CONTEXT_E_OLDREF _HRESULT_TYPEDEF_(0x8004e007)
+#define CONTEXT_E_ROLENOTFOUND _HRESULT_TYPEDEF_(0x8004e00c)
+#define CONTEXT_E_TMNOTAVAILABLE _HRESULT_TYPEDEF_(0x8004e00f)
+#define CONTEXT_E_NOJIT _HRESULT_TYPEDEF_(0x8004e026)
+#define CONTEXT_E_NOTRANSACTION _HRESULT_TYPEDEF_(0x8004e027)
+
/* Task Scheduler Service Error Codes */
#define SCHED_S_TASK_READY _HRESULT_TYPEDEF_(0x00041300)
#define SCHED_S_TASK_RUNNING _HRESULT_TYPEDEF_(0x00041301)
--
2.28.0
3
2
Signed-off-by: Jactry Zeng <jzeng(a)codeweavers.com>
---
v3:
- Make creation of group manager safe.
v2:
- Add CRITICAL_SECTION for struct group_manager;
- Use DISPID_VALUE and DISPID_NEWENUM instead;
- Improve tests.
---
dlls/comsvcs/Makefile.in | 3 +-
dlls/comsvcs/comsvcs_private.h | 38 ++++++++
dlls/comsvcs/main.c | 28 +++---
dlls/comsvcs/property.c | 163 +++++++++++++++++++++++++++++++++
dlls/comsvcs/tests/Makefile.in | 3 +-
dlls/comsvcs/tests/property.c | 115 +++++++++++++++++++++++
include/comsvcs.idl | 65 +++++++++++++
7 files changed, 401 insertions(+), 14 deletions(-)
create mode 100644 dlls/comsvcs/comsvcs_private.h
create mode 100644 dlls/comsvcs/property.c
create mode 100644 dlls/comsvcs/tests/property.c
diff --git a/dlls/comsvcs/Makefile.in b/dlls/comsvcs/Makefile.in
index 7845400cb2..b4a4244bce 100644
--- a/dlls/comsvcs/Makefile.in
+++ b/dlls/comsvcs/Makefile.in
@@ -5,7 +5,8 @@ IMPORTS = ole32 uuid
EXTRADLLFLAGS = -mno-cygwin
C_SRCS = \
- main.c
+ main.c \
+ property.c
IDL_SRCS = \
comsvcs_classes.idl \
diff --git a/dlls/comsvcs/comsvcs_private.h b/dlls/comsvcs/comsvcs_private.h
new file mode 100644
index 0000000000..6d299d3a88
--- /dev/null
+++ b/dlls/comsvcs/comsvcs_private.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2020 Jactry Zeng for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _COMSVCS_PRIVATE_H_
+#define _COMSVCS_PRIVATE_H_
+
+#define COBJMACROS
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "ole2.h"
+#include "rpcproxy.h"
+#include "comsvcs.h"
+#include "initguid.h"
+
+#include "wine/heap.h"
+#include "wine/debug.h"
+
+HRESULT WINAPI group_manager_create(IClassFactory *iface, IUnknown *outer, REFIID riid, void **out);
+
+#endif
diff --git a/dlls/comsvcs/main.c b/dlls/comsvcs/main.c
index 9ab77dfced..1d3f7db174 100644
--- a/dlls/comsvcs/main.c
+++ b/dlls/comsvcs/main.c
@@ -18,18 +18,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#define COBJMACROS
-
-#include <stdarg.h>
-
-#include "windef.h"
-#include "winbase.h"
-#include "ole2.h"
-#include "rpcproxy.h"
-#include "comsvcs.h"
-#include "wine/heap.h"
-#include "wine/debug.h"
-#include "initguid.h"
+#include "comsvcs_private.h"
#include "comsvcs_classes.h"
WINE_DEFAULT_DEBUG_CHANNEL(comsvcs);
@@ -1027,8 +1016,18 @@ static const IClassFactoryVtbl newmoniker_cf_vtbl =
comsvcscf_LockServer
};
+static const IClassFactoryVtbl group_manager_cf_vtbl =
+{
+ comsvcscf_QueryInterface,
+ comsvcscf_AddRef,
+ comsvcscf_Release,
+ group_manager_create,
+ comsvcscf_LockServer
+};
+
static IClassFactory DispenserManageFactory = { &comsvcscf_vtbl };
static IClassFactory NewMonikerFactory = { &newmoniker_cf_vtbl };
+static IClassFactory GroupManagerFactory = { &group_manager_cf_vtbl };
/******************************************************************
* DllGetClassObject
@@ -1045,6 +1044,11 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
TRACE("(CLSID_NewMoniker %s %p)\n", debugstr_guid(riid), ppv);
return IClassFactory_QueryInterface(&NewMonikerFactory, riid, ppv);
}
+ else if (IsEqualGUID(&CLSID_SharedPropertyGroupManager, rclsid))
+ {
+ TRACE("(CLSID_SharedPropertyGroupManager %s %p)\n", debugstr_guid(riid), ppv);
+ return IClassFactory_QueryInterface(&GroupManagerFactory, riid, ppv);
+ }
FIXME("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
return CLASS_E_CLASSNOTAVAILABLE;
diff --git a/dlls/comsvcs/property.c b/dlls/comsvcs/property.c
new file mode 100644
index 0000000000..3c9917c926
--- /dev/null
+++ b/dlls/comsvcs/property.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2020 Jactry Zeng for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <comsvcs_private.h>
+
+WINE_DEFAULT_DEBUG_CHANNEL(comsvcs);
+
+struct group_manager
+{
+ ISharedPropertyGroupManager ISharedPropertyGroupManager_iface;
+ LONG refcount;
+};
+
+static struct group_manager *group_manager = NULL;
+
+static inline struct group_manager *impl_from_ISharedPropertyGroupManager(ISharedPropertyGroupManager *iface)
+{
+ return CONTAINING_RECORD(iface, struct group_manager, ISharedPropertyGroupManager_iface);
+}
+
+static HRESULT WINAPI group_manager_QueryInterface(ISharedPropertyGroupManager *iface, REFIID riid, void **out)
+{
+ struct group_manager *manager = impl_from_ISharedPropertyGroupManager(iface);
+
+ TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
+
+ if (IsEqualGUID(riid, &IID_IUnknown)
+ || IsEqualGUID(riid, &IID_IDispatch)
+ || IsEqualGUID(riid, &IID_ISharedPropertyGroupManager))
+ {
+ *out = &manager->ISharedPropertyGroupManager_iface;
+ IUnknown_AddRef((IUnknown *)*out);
+ return S_OK;
+ }
+
+ WARN("%s not implemented.\n", debugstr_guid(riid));
+ *out = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI group_manager_AddRef(ISharedPropertyGroupManager *iface)
+{
+ struct group_manager *manager = impl_from_ISharedPropertyGroupManager(iface);
+ ULONG refcount = InterlockedIncrement(&manager->refcount);
+
+ TRACE("%p increasing refcount to %u.\n", iface, refcount);
+
+ return refcount;
+}
+
+static ULONG WINAPI group_manager_Release(ISharedPropertyGroupManager *iface)
+{
+ struct group_manager *manager = impl_from_ISharedPropertyGroupManager(iface);
+ ULONG refcount = InterlockedDecrement(&manager->refcount);
+
+ TRACE("%p decreasing refcount to %u.\n", iface, refcount);
+
+ return refcount;
+}
+
+static HRESULT WINAPI group_manager_GetTypeInfoCount(ISharedPropertyGroupManager *iface, UINT *info)
+{
+ FIXME("iface %p, info %p: stub.\n", iface, info);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI group_manager_GetTypeInfo(ISharedPropertyGroupManager *iface, UINT index, LCID lcid, ITypeInfo **info)
+{
+ FIXME("iface %p, index %u, lcid %u, info %p: stub.\n", iface, index, lcid, info);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI group_manager_GetIDsOfNames(ISharedPropertyGroupManager *iface, REFIID riid, LPOLESTR *names, UINT count,
+ LCID lcid, DISPID *dispid)
+{
+ FIXME("iface %p, riid %s, names %p, count %u, lcid %u, dispid %p: stub.\n",
+ iface, debugstr_guid(riid), names, count, lcid, dispid);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI group_manager_Invoke(ISharedPropertyGroupManager *iface, DISPID member, REFIID riid, LCID lcid,
+ WORD flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *except, UINT *argerr)
+{
+ FIXME("iface %p, member %u, riid %s, lcid %u, flags %x, params %p, result %p, except %p, argerr %p: stub.\n",
+ iface, member, debugstr_guid(riid), lcid, flags, params, result, except, argerr);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI group_manager_CreatePropertyGroup(ISharedPropertyGroupManager *iface, BSTR name, LONG *isolation,
+ LONG *release, VARIANT_BOOL *exists, ISharedPropertyGroup **group)
+{
+ FIXME("iface %p, name %s, isolation %p, release %p, exists %p, group %p: stub.\n",
+ iface, debugstr_w(name), isolation, release, exists, group);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI group_manager_get_Group(ISharedPropertyGroupManager *iface, BSTR name, ISharedPropertyGroup **group)
+{
+ FIXME("iface %p, name %s, group %p: stub.\n", iface, debugstr_w(name), group);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI group_manager_get__NewEnum(ISharedPropertyGroupManager *iface, IUnknown **retval)
+{
+ FIXME("iface %p, retval %p: stub.\n", iface, retval);
+ return E_NOTIMPL;
+}
+
+static const ISharedPropertyGroupManagerVtbl group_manager_vtbl =
+{
+ group_manager_QueryInterface,
+ group_manager_AddRef,
+ group_manager_Release,
+ group_manager_GetTypeInfoCount,
+ group_manager_GetTypeInfo,
+ group_manager_GetIDsOfNames,
+ group_manager_Invoke,
+ group_manager_CreatePropertyGroup,
+ group_manager_get_Group,
+ group_manager_get__NewEnum
+};
+
+HRESULT WINAPI group_manager_create(IClassFactory *iface, IUnknown *outer, REFIID riid, void **out)
+{
+ struct group_manager *manager;
+
+ if (outer)
+ return CLASS_E_NOAGGREGATION;
+
+ if (!group_manager)
+ {
+ manager = heap_alloc(sizeof(*manager));
+ if (!manager)
+ {
+ *out = NULL;
+ return E_OUTOFMEMORY;
+ }
+ manager->ISharedPropertyGroupManager_iface.lpVtbl = &group_manager_vtbl;
+ manager->refcount = 1;
+
+ if (InterlockedCompareExchangePointer((void **)&group_manager, manager, NULL))
+ {
+ heap_free(manager);
+ }
+ }
+ return ISharedPropertyGroupManager_QueryInterface(&group_manager->ISharedPropertyGroupManager_iface, riid, out);
+}
diff --git a/dlls/comsvcs/tests/Makefile.in b/dlls/comsvcs/tests/Makefile.in
index 86da9fda66..1d9146ba5b 100644
--- a/dlls/comsvcs/tests/Makefile.in
+++ b/dlls/comsvcs/tests/Makefile.in
@@ -2,4 +2,5 @@ TESTDLL = comsvcs.dll
IMPORTS = uuid oleaut32 ole32
C_SRCS = \
- comsvcs.c
+ comsvcs.c \
+ property.c
diff --git a/dlls/comsvcs/tests/property.c b/dlls/comsvcs/tests/property.c
new file mode 100644
index 0000000000..adad7bd539
--- /dev/null
+++ b/dlls/comsvcs/tests/property.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2020 Jactry Zeng for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define COBJMACROS
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "comsvcs.h"
+
+#include "wine/test.h"
+
+static ULONG get_refcount(void *iface)
+{
+ IUnknown *unknown = iface;
+ IUnknown_AddRef(unknown);
+ return IUnknown_Release(unknown);
+}
+
+static HRESULT WINAPI outer_QueryInterface(IUnknown *iface, REFIID iid, void **out)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI outer_AddRef(IUnknown *iface)
+{
+ ok(0, "Unexpected call.\n");
+ return 1;
+}
+
+static ULONG WINAPI outer_Release(IUnknown *iface)
+{
+ ok(0, "Unexpected call.\n");
+ return 0;
+}
+
+static const IUnknownVtbl outer_vtbl =
+{
+ outer_QueryInterface,
+ outer_AddRef,
+ outer_Release,
+};
+
+static IUnknown test_outer = {&outer_vtbl};
+
+static void test_interfaces(void)
+{
+ ISharedPropertyGroupManager *manager, *manager1;
+ ULONG refcount, expected_refcount;
+ IDispatch *dispatch;
+ IUnknown *unk;
+ HRESULT hr;
+
+ hr = CoCreateInstance(&CLSID_SharedPropertyGroupManager, &test_outer, CLSCTX_INPROC_SERVER,
+ &IID_ISharedPropertyGroupManager, (void **)&manager);
+ ok(hr == CLASS_E_NOAGGREGATION, "Got hr %#x.\n", hr);
+
+ hr = CoCreateInstance(&CLSID_SharedPropertyGroupManager, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IUnknown, (void **)&unk);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ expected_refcount = get_refcount(unk) + 1;
+ hr = IUnknown_QueryInterface(unk, &IID_ISharedPropertyGroupManager, (void **)&manager);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ refcount = get_refcount(unk);
+ ok(refcount == expected_refcount, "Got refcount: %u, expected %u.\n", refcount, expected_refcount);
+
+ expected_refcount = get_refcount(manager) + 1;
+ hr = CoCreateInstance(&CLSID_SharedPropertyGroupManager, NULL, CLSCTX_INPROC_SERVER,
+ &IID_ISharedPropertyGroupManager, (void **)&manager1);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(manager1 == manager, "Got wrong pointer: %p.\n", manager1);
+ refcount = get_refcount(manager1);
+ ok(refcount == expected_refcount, "Got refcount: %u, expected %u.\n", refcount, expected_refcount);
+ refcount = get_refcount(manager);
+ ok(refcount == expected_refcount, "Got refcount: %u, expected %u.\n", refcount, expected_refcount);
+ ISharedPropertyGroupManager_Release(manager1);
+
+ hr = IUnknown_QueryInterface(unk, &IID_IDispatch, (void **)&dispatch);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ refcount = get_refcount(dispatch);
+ ok(refcount == expected_refcount, "Got refcount: %u, expected %u.\n", refcount, expected_refcount);
+ refcount = get_refcount(manager);
+ ok(refcount == expected_refcount, "Got refcount: %u, expected %u.\n", refcount, expected_refcount);
+
+ IDispatch_Release(dispatch);
+ IUnknown_Release(unk);
+ ISharedPropertyGroupManager_Release(manager);
+}
+
+START_TEST(property)
+{
+ CoInitialize(NULL);
+
+ test_interfaces();
+
+ CoUninitialize();
+}
diff --git a/include/comsvcs.idl b/include/comsvcs.idl
index d64af1f5a8..ee1fede360 100644
--- a/include/comsvcs.idl
+++ b/include/comsvcs.idl
@@ -37,6 +37,8 @@ typedef DWORD_PTR TRANSID;
]
library COMSVCSLib
{
+ importlib("stdole2.tlb");
+
[
object,
hidden,
@@ -96,4 +98,67 @@ library COMSVCSLib
{
[default] interface IDispenserManager;
};
+
+ [
+ object,
+ hidden,
+ local,
+ uuid(2a005c01-a5de-11cf-9e66-00aa00a3f464),
+ pointer_default(unique)
+ ]
+ interface ISharedProperty : IDispatch
+ {
+ [id(DISPID_VALUE), propget]
+ HRESULT Value([out, retval] VARIANT *value);
+ [id(DISPID_VALUE), propput]
+ HRESULT Value([in] VARIANT value);
+ }
+
+ [
+ object,
+ hidden,
+ local,
+ uuid(2a005c07-a5de-11cf-9e66-00aa00a3f464),
+ pointer_default(unique)
+ ]
+ interface ISharedPropertyGroup : IDispatch
+ {
+ [id(0x00000001)]
+ HRESULT CreatePropertyByPosition([in] int index, [out] VARIANT_BOOL *exists, [out, retval] ISharedProperty **property);
+ [id(0x00000002), propget]
+ HRESULT PropertyByPosition([in] int index, [out, retval] ISharedProperty **property);
+ [id(0x00000003)]
+ HRESULT CreateProperty([in] BSTR name, [out] VARIANT_BOOL *exists, [out, retval] ISharedProperty **property);
+ [id(0x00000004), propget]
+ HRESULT Property([in] BSTR name, [out, retval] ISharedProperty **property);
+ }
+
+ [
+ object,
+ hidden,
+ local,
+ uuid(2a005c0d-a5de-11cf-9e66-00aa00a3f464),
+ pointer_default(unique)
+ ]
+ interface ISharedPropertyGroupManager : IDispatch
+ {
+ [id(0x00000001)]
+ HRESULT CreatePropertyGroup([in] BSTR name, [in, out] LONG *isolation, [in, out] LONG *release,
+ [out] VARIANT_BOOL *exists, [out, retval] ISharedPropertyGroup **group);
+ [id(0x00000002), propget]
+ HRESULT Group([in] BSTR name, [out, retval] ISharedPropertyGroup **group);
+ [id(DISPID_NEWENUM), propget]
+ HRESULT _NewEnum([out, retval] IUnknown **retval);
+ }
+
+ [
+ uuid(2a005c11-a5de-11cf-9e66-00aa00a3f464),
+ progid("MTxSpm.SharedPropertyGroupManager.1"),
+ vi_progid("MTxSpm.SharedPropertyGroupManager"),
+ threading(both)
+ ]
+ coclass SharedPropertyGroupManager
+ {
+ [default] interface ISharedPropertyGroupManager;
+ }
}
--
2.28.0
3
2
[PATCH v2] wininet: Implement INTERNET_OPTION_SECURITY_CERTIFICATE flag for InternetQueryOption.
by Daniel Lehman 05 Sep '20
by Daniel Lehman 05 Sep '20
05 Sep '20
Signed-off-by: Daniel Lehman <dlehman25(a)gmail.com>
---
v2: reverting to the \r -> %c thing for the wine.pot build
---
dlls/wininet/http.c | 71 +++++++++++++++++++++
dlls/wininet/resource.h | 3 +
dlls/wininet/tests/http.c | 127 +++++++++++++++++++++++++++++++++++++-
dlls/wininet/wininet.rc | 11 ++++
4 files changed, 210 insertions(+), 2 deletions(-)
diff --git a/dlls/wininet/http.c b/dlls/wininet/http.c
index 220493718c3..5d10db0a308 100644
--- a/dlls/wininet/http.c
+++ b/dlls/wininet/http.c
@@ -54,6 +54,7 @@
#include "internet.h"
#include "zlib.h"
+#include "resource.h"
#include "wine/debug.h"
#include "wine/exception.h"
@@ -2277,6 +2278,76 @@ static DWORD HTTPREQ_QueryOption(object_header_t *hdr, DWORD option, void *buffe
return get_security_cert_struct(req, (INTERNET_CERTIFICATE_INFOA*)buffer);
}
+ case INTERNET_OPTION_SECURITY_CERTIFICATE: {
+ DWORD err;
+ int needed;
+ char fmt[512];
+ char strength[16];
+ char start_date[32];
+ char start_time[32];
+ char expiry_date[32];
+ char expiry_time[32];
+ SYSTEMTIME start, expiry;
+ INTERNET_CERTIFICATE_INFOA info;
+
+ if(!size)
+ return ERROR_INVALID_PARAMETER;
+
+ if(!req->netconn) {
+ *size = 0;
+ return ERROR_INTERNET_INVALID_OPERATION;
+ }
+
+ if(!buffer) {
+ *size = 1;
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+
+ if((err = get_security_cert_struct(req, &info)))
+ return err;
+
+ if (PRIMARYLANGID(GetUserDefaultLangID()) != LANG_ENGLISH)
+ FIXME("INTERNET_OPTION_SECURITY_CERTIFICATE currently English-only\n");
+
+ LoadStringA(WININET_hModule, IDS_CERT_FORMAT, fmt, sizeof(fmt));
+ LoadStringA(WININET_hModule, info.dwKeySize >= 128 ? IDS_CERT_HIGH : IDS_CERT_LOW,
+ strength, sizeof(strength));
+
+ FileTimeToSystemTime(&info.ftStart, &start);
+ FileTimeToSystemTime(&info.ftExpiry, &expiry);
+ GetDateFormatA(LOCALE_USER_DEFAULT, 0, &start, NULL, start_date, sizeof(start_date));
+ GetTimeFormatA(LOCALE_USER_DEFAULT, 0, &start, NULL, start_time, sizeof(start_time));
+ GetDateFormatA(LOCALE_USER_DEFAULT, 0, &expiry, NULL, expiry_date, sizeof(expiry_date));
+ GetTimeFormatA(LOCALE_USER_DEFAULT, 0, &expiry, NULL, expiry_time, sizeof(expiry_time));
+
+ needed = _scprintf(fmt,
+ '\r', info.lpszSubjectInfo, '\r',
+ '\r', info.lpszIssuerInfo, '\r',
+ start_date, start_time, '\r',
+ expiry_date, expiry_time, '\r',
+ '\r', '\r', '\r',
+ strength, info.dwKeySize);
+ if(needed < *size) {
+ err = ERROR_SUCCESS;
+ *size = snprintf(buffer, *size, fmt,
+ '\r', info.lpszSubjectInfo, '\r',
+ '\r', info.lpszIssuerInfo, '\r',
+ start_date, start_time, '\r',
+ expiry_date, expiry_time, '\r',
+ '\r', '\r', '\r',
+ strength, info.dwKeySize);
+ }else {
+ err = ERROR_INSUFFICIENT_BUFFER;
+ *size = 1;
+ }
+
+ LocalFree(info.lpszSubjectInfo);
+ LocalFree(info.lpszIssuerInfo);
+ LocalFree(info.lpszProtocolName);
+ LocalFree(info.lpszSignatureAlgName);
+ LocalFree(info.lpszEncryptionAlgName);
+ return err;
+ }
case INTERNET_OPTION_CONNECT_TIMEOUT:
if (*size < sizeof(DWORD))
return ERROR_INSUFFICIENT_BUFFER;
diff --git a/dlls/wininet/resource.h b/dlls/wininet/resource.h
index 256a374af08..190d3cc397c 100644
--- a/dlls/wininet/resource.h
+++ b/dlls/wininet/resource.h
@@ -38,3 +38,6 @@
#define IDS_CERT_DATE_INVALID 0x502
#define IDS_CERT_CN_INVALID 0x503
#define IDS_CERT_ERRORS 0x504
+#define IDS_CERT_FORMAT 0x505
+#define IDS_CERT_HIGH 0x506
+#define IDS_CERT_LOW 0x507
diff --git a/dlls/wininet/tests/http.c b/dlls/wininet/tests/http.c
index c07d60d2a9d..e0a38e05c41 100644
--- a/dlls/wininet/tests/http.c
+++ b/dlls/wininet/tests/http.c
@@ -6112,9 +6112,26 @@ static const cert_struct_test_t test_winehq_com_cert = {
"webmaster(a)winehq.org"
};
+static const char *cert_string_fmt =
+ "Subject:\r\n%s\r\n"
+ "Issuer:\r\n%s\r\n"
+ "Effective Date:\t%s %s\r\n"
+ "Expiration Date:\t%s %s\r\n"
+ "Security Protocol:\t%s\r\n"
+ "Signature Type:\t%s\r\n"
+ "Encryption Type:\t%s\r\n"
+ "Privacy Strength:\t%s (%u bits)";
+
static void test_cert_struct(HINTERNET req, const cert_struct_test_t *test)
{
INTERNET_CERTIFICATE_INFOA info;
+ SYSTEMTIME start, expiry;
+ char expiry_date[32];
+ char expiry_time[32];
+ char start_date[32];
+ char start_time[32];
+ char expect[512];
+ char actual[512];
DWORD size;
BOOL res;
@@ -6138,6 +6155,42 @@ static void test_cert_struct(HINTERNET req, const cert_struct_test_t *test)
ok(!info.lpszProtocolName, "lpszProtocolName = %s\n", info.lpszProtocolName);
ok(info.dwKeySize >= 128 && info.dwKeySize <= 256, "dwKeySize = %u\n", info.dwKeySize);
+ if (PRIMARYLANGID(GetUserDefaultLangID()) != LANG_ENGLISH)
+ {
+ skip("Non-English locale (test with hardcoded English)\n");
+ release_cert_info(&info);
+ return;
+ }
+
+ size = sizeof(actual);
+ SetLastError(0xdeadbeef);
+ memset(actual, 0x55, sizeof(actual));
+ res = InternetQueryOptionA(req, INTERNET_OPTION_SECURITY_CERTIFICATE, actual, &size);
+ ok(res, "InternetQueryOption failed: %u\n", GetLastError());
+
+ FileTimeToSystemTime(&info.ftStart, &start);
+ FileTimeToSystemTime(&info.ftExpiry, &expiry);
+
+ GetDateFormatA(LOCALE_USER_DEFAULT, 0, &start, NULL, start_date, sizeof(start_date));
+ GetTimeFormatA(LOCALE_USER_DEFAULT, 0, &start, NULL, start_time, sizeof(start_time));
+ GetDateFormatA(LOCALE_USER_DEFAULT, 0, &expiry, NULL, expiry_date, sizeof(expiry_date));
+ GetTimeFormatA(LOCALE_USER_DEFAULT, 0, &expiry, NULL, expiry_time, sizeof(expiry_time));
+
+ snprintf(expect, sizeof(expect), cert_string_fmt, info.lpszSubjectInfo, info.lpszIssuerInfo,
+ start_date, start_time, expiry_date, expiry_time,
+ info.lpszSignatureAlgName, info.lpszEncryptionAlgName, info.lpszProtocolName,
+ info.dwKeySize >= 128 ? "High" : "Low", info.dwKeySize);
+ ok(size == strlen(actual), "size = %u\n", size);
+ ok(!strcmp(actual, expect), "cert = actual\n%s\n", actual);
+
+ --size;
+ SetLastError(0xdeadbeef);
+ memset(actual, 0x55, sizeof(actual));
+ res = InternetQueryOptionA(req, INTERNET_OPTION_SECURITY_CERTIFICATE, actual, &size);
+ ok(!res && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "InternetQueryOption failed: %d\n", GetLastError());
+ ok(size == 1, "unexpected size: %u\n", size);
+ ok(actual[0] == 0x55, "unexpected byte: %02x\n", actual[0]);
+
release_cert_info(&info);
}
@@ -6217,7 +6270,7 @@ static void test_security_flags(void)
INTERNET_CERTIFICATE_INFOA *cert;
HINTERNET ses, conn, req;
DWORD size, flags;
- char buf[100];
+ char buf[512];
BOOL res;
if (!https_support)
@@ -6378,6 +6431,30 @@ static void test_security_flags(void)
}
HeapFree(GetProcessHeap(), 0, cert);
+ SetLastError(0xdeadbeef);
+ res = InternetQueryOptionW(req, INTERNET_OPTION_SECURITY_CERTIFICATE, NULL, NULL);
+ ok(!res && GetLastError() == ERROR_INVALID_PARAMETER, "InternetQueryOption failed: %d\n", GetLastError());
+
+ size = 0;
+ SetLastError(0xdeadbeef);
+ res = InternetQueryOptionW(req, INTERNET_OPTION_SECURITY_CERTIFICATE, NULL, &size);
+ ok(!res && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "InternetQueryOption failed: %d\n", GetLastError());
+ ok(size == 1, "unexpected size: %u\n", size);
+
+ size = 42;
+ SetLastError(0xdeadbeef);
+ memset(buf, 0x55, sizeof(buf));
+ res = InternetQueryOptionW(req, INTERNET_OPTION_SECURITY_CERTIFICATE, buf, &size);
+ ok(!res && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "InternetQueryOption failed: %d\n", GetLastError());
+ ok(size == 1, "unexpected size: %u\n", size);
+ ok(buf[0] == 0x55, "unexpected byte: %02x\n", buf[0]);
+
+ size = sizeof(buf);
+ SetLastError(0xdeadbeef);
+ res = InternetQueryOptionW(req, INTERNET_OPTION_SECURITY_CERTIFICATE, buf, &size);
+ ok(res && GetLastError() == ERROR_SUCCESS, "InternetQueryOption failed: %d\n", GetLastError());
+ ok(size < sizeof(buf), "unexpected size: %u\n", size);
+
CHECK_NOTIFIED2(INTERNET_STATUS_CONNECTING_TO_SERVER, 2);
CHECK_NOTIFIED2(INTERNET_STATUS_CONNECTED_TO_SERVER, 2);
CHECK_NOTIFIED2(INTERNET_STATUS_CLOSING_CONNECTION, 2);
@@ -6562,9 +6639,10 @@ static void test_secure_connection(void)
static const WCHAR get[] = {'G','E','T',0};
static const WCHAR testpage[] = {'/','t','e','s','t','s','/','h','e','l','l','o','.','h','t','m','l',0};
HINTERNET ses, con, req;
- DWORD size, flags, err;
+ DWORD size, size2, flags, err;
INTERNET_CERTIFICATE_INFOA *certificate_structA = NULL;
INTERNET_CERTIFICATE_INFOW *certificate_structW = NULL;
+ char certstr1[512], certstr2[512];
BOOL ret;
ses = InternetOpenA("Gizmo5", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
@@ -6629,6 +6707,19 @@ static void test_secure_connection(void)
}
HeapFree(GetProcessHeap(), 0, certificate_structW);
+ SetLastError(0xdeadbeef);
+ size = sizeof(certstr1);
+ ret = InternetQueryOptionW(req, INTERNET_OPTION_SECURITY_CERTIFICATE, certstr1, &size);
+ ok(ret && GetLastError() == ERROR_SUCCESS, "InternetQueryOption failed: %d\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ size2 = sizeof(certstr2);
+ ret = InternetQueryOptionA(req, INTERNET_OPTION_SECURITY_CERTIFICATE, certstr2, &size2);
+ ok(ret && GetLastError() == ERROR_SUCCESS, "InternetQueryOption failed: %d\n", GetLastError());
+
+ ok(size == size2, "expected same size\n");
+ ok(!strcmp(certstr1, certstr2), "expected same string\n");
+
InternetCloseHandle(req);
InternetCloseHandle(con);
InternetCloseHandle(ses);
@@ -7517,6 +7608,37 @@ static void test_concurrent_header_access(void)
CloseHandle( wait );
}
+static void test_cert_string(void)
+{
+ HINTERNET ses, con, req;
+ char actual[512];
+ DWORD size;
+ BOOL res;
+
+ ses = InternetOpenA( "winetest", 0, NULL, NULL, 0 );
+ ok( ses != NULL, "InternetOpenA failed\n" );
+
+ con = InternetConnectA( ses, "test.winehq.org", INTERNET_DEFAULT_HTTP_PORT, NULL, NULL,
+ INTERNET_SERVICE_HTTP, 0, 0 );
+ ok( con != NULL, "InternetConnectA failed %u\n", GetLastError() );
+
+ req = HttpOpenRequestA( con, NULL, "/", NULL, NULL, NULL, 0, 0 );
+ ok( req != NULL, "HttpOpenRequestA failed %u\n", GetLastError() );
+
+ size = sizeof(actual);
+ SetLastError( 0xdeadbeef );
+ memset( actual, 0x55, sizeof(actual) );
+ res = InternetQueryOptionA( req, INTERNET_OPTION_SECURITY_CERTIFICATE, actual, &size );
+ ok( !res && GetLastError() == ERROR_INTERNET_INVALID_OPERATION,
+ "InternetQueryOption failed: %u\n", GetLastError() );
+ ok( size == 0, "unexpected size: %u\n", size );
+ ok( actual[0] == 0x55, "unexpected byte: %02x\n", actual[0] );
+
+ InternetCloseHandle( req );
+ InternetCloseHandle( con );
+ InternetCloseHandle( ses );
+}
+
START_TEST(http)
{
HMODULE hdll;
@@ -7566,5 +7688,6 @@ START_TEST(http)
test_connection_failure();
test_default_service_port();
test_concurrent_header_access();
+ test_cert_string();
free_events();
}
diff --git a/dlls/wininet/wininet.rc b/dlls/wininet/wininet.rc
index b6e35629ca2..ede9edab09c 100644
--- a/dlls/wininet/wininet.rc
+++ b/dlls/wininet/wininet.rc
@@ -29,6 +29,17 @@ STRINGTABLE
IDS_CERT_DATE_INVALID "The date on the certificate is invalid."
IDS_CERT_CN_INVALID "The name on the certificate does not match the site."
IDS_CERT_ERRORS "There is at least one unspecified security problem with this certificate."
+
+ IDS_CERT_FORMAT "Subject:%c\n%s%c\n" \
+ "Issuer:%c\n%s%c\n" \
+ "Effective Date:\t%s %s%c\n" \
+ "Expiration Date:\t%s %s%c\n" \
+ "Security Protocol:\t(null)%c\n" \
+ "Signature Type:\t(null)%c\n" \
+ "Encryption Type:\t(null)%c\n" \
+ "Privacy Strength:\t%s (%u bits)"
+ IDS_CERT_HIGH "High"
+ IDS_CERT_LOW "Low"
}
IDD_PROXYDLG DIALOG 36, 24, 220, 146
--
2.25.1
3
6
Is there any particular reason to place the pthread stack adjacent to
the win32 stack? If the pthread stack happened to extend past
PTHREAD_STACK_MIN while the win32 thread was started, writes to the
win32 stack (such as the initial CONTEXT) would overwrite the pthread stack.
-Jefferson
2
2
Instead of every time they don't match another face.
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/gdi32/freetype.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c
index f82a8c1641f..38d59e3fd9b 100644
--- a/dlls/gdi32/freetype.c
+++ b/dlls/gdi32/freetype.c
@@ -1574,12 +1574,11 @@ static BOOL insert_face_in_family_list( Face *face, Family *family )
return TRUE;
}
}
- else
- TRACE("Adding new %s\n", debugstr_w(face->file));
if (style_order( face ) < style_order( cursor )) break;
}
+ TRACE("Adding new %s\n", debugstr_w(face->file));
list_add_before( &cursor->entry, &face->entry );
face->family = family;
family->refcount++;
--
2.28.0
3
4
Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
---
dlls/mfplat/main.c | 207 +------------------------------------
dlls/mfplat/tests/mfplat.c | 106 +++++++++++--------
2 files changed, 64 insertions(+), 249 deletions(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c
index 6cd409d63b7..ea1b1770e15 100644
--- a/dlls/mfplat/main.c
+++ b/dlls/mfplat/main.c
@@ -5679,188 +5679,6 @@ HRESULT WINAPI MFGetPluginControl(IMFPluginControl **ret)
return S_OK;
}
-typedef struct _mfsource
-{
- IMFMediaSource IMFMediaSource_iface;
- LONG ref;
-} mfsource;
-
-static inline mfsource *impl_from_IMFMediaSource(IMFMediaSource *iface)
-{
- return CONTAINING_RECORD(iface, mfsource, IMFMediaSource_iface);
-}
-
-static HRESULT WINAPI mfsource_QueryInterface(IMFMediaSource *iface, REFIID riid, void **out)
-{
- mfsource *This = impl_from_IMFMediaSource(iface);
-
- TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), out);
-
- if (IsEqualIID(riid, &IID_IMFMediaSource) ||
- IsEqualIID(riid, &IID_IMFMediaEventGenerator) ||
- IsEqualIID(riid, &IID_IUnknown))
- {
- *out = &This->IMFMediaSource_iface;
- }
- else
- {
- FIXME("(%s, %p)\n", debugstr_guid(riid), out);
- *out = NULL;
- return E_NOINTERFACE;
- }
-
- IUnknown_AddRef((IUnknown*)*out);
- return S_OK;
-}
-
-static ULONG WINAPI mfsource_AddRef(IMFMediaSource *iface)
-{
- mfsource *This = impl_from_IMFMediaSource(iface);
- ULONG ref = InterlockedIncrement(&This->ref);
-
- TRACE("(%p) ref=%u\n", This, ref);
-
- return ref;
-}
-
-static ULONG WINAPI mfsource_Release(IMFMediaSource *iface)
-{
- mfsource *This = impl_from_IMFMediaSource(iface);
- ULONG ref = InterlockedDecrement(&This->ref);
-
- TRACE("(%p) ref=%u\n", This, ref);
-
- if (!ref)
- {
- HeapFree(GetProcessHeap(), 0, This);
- }
-
- return ref;
-}
-
-static HRESULT WINAPI mfsource_GetEvent(IMFMediaSource *iface, DWORD flags, IMFMediaEvent **event)
-{
- mfsource *This = impl_from_IMFMediaSource(iface);
-
- FIXME("(%p)->(%#x, %p)\n", This, flags, event);
-
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI mfsource_BeginGetEvent(IMFMediaSource *iface, IMFAsyncCallback *callback, IUnknown *state)
-{
- mfsource *This = impl_from_IMFMediaSource(iface);
-
- FIXME("(%p)->(%p, %p)\n", This, callback, state);
-
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI mfsource_EndGetEvent(IMFMediaSource *iface, IMFAsyncResult *result, IMFMediaEvent **event)
-{
- mfsource *This = impl_from_IMFMediaSource(iface);
-
- FIXME("(%p)->(%p, %p)\n", This, result, event);
-
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI mfsource_QueueEvent(IMFMediaSource *iface, MediaEventType event_type, REFGUID ext_type,
- HRESULT hr, const PROPVARIANT *value)
-{
- mfsource *This = impl_from_IMFMediaSource(iface);
-
- FIXME("(%p)->(%d, %s, %#x, %p)\n", This, event_type, debugstr_guid(ext_type), hr, value);
-
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI mfsource_GetCharacteristics(IMFMediaSource *iface, DWORD *characteristics)
-{
- mfsource *This = impl_from_IMFMediaSource(iface);
-
- FIXME("(%p)->(%p): stub\n", This, characteristics);
-
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI mfsource_CreatePresentationDescriptor(IMFMediaSource *iface, IMFPresentationDescriptor **descriptor)
-{
- mfsource *This = impl_from_IMFMediaSource(iface);
- IMFStreamDescriptor *sd;
- IMFMediaType *mediatype;
- HRESULT hr;
-
- FIXME("(%p)->(%p): stub\n", This, descriptor);
-
- if (FAILED(hr = MFCreateMediaType(&mediatype)))
- return hr;
-
- hr = MFCreateStreamDescriptor(0, 1, &mediatype, &sd);
- IMFMediaType_Release(mediatype);
- if (FAILED(hr))
- return hr;
-
- hr = MFCreatePresentationDescriptor(1, &sd, descriptor);
- IMFStreamDescriptor_Release(sd);
-
- return hr;
-}
-
-static HRESULT WINAPI mfsource_Start(IMFMediaSource *iface, IMFPresentationDescriptor *descriptor,
- const GUID *time_format, const PROPVARIANT *start_position)
-{
- mfsource *This = impl_from_IMFMediaSource(iface);
-
- FIXME("(%p)->(%p, %p, %p): stub\n", This, descriptor, time_format, start_position);
-
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI mfsource_Stop(IMFMediaSource *iface)
-{
- mfsource *This = impl_from_IMFMediaSource(iface);
-
- FIXME("(%p): stub\n", This);
-
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI mfsource_Pause(IMFMediaSource *iface)
-{
- mfsource *This = impl_from_IMFMediaSource(iface);
-
- FIXME("(%p): stub\n", This);
-
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI mfsource_Shutdown(IMFMediaSource *iface)
-{
- mfsource *This = impl_from_IMFMediaSource(iface);
-
- FIXME("(%p): stub\n", This);
-
- return S_OK;
-}
-
-static const IMFMediaSourceVtbl mfsourcevtbl =
-{
- mfsource_QueryInterface,
- mfsource_AddRef,
- mfsource_Release,
- mfsource_GetEvent,
- mfsource_BeginGetEvent,
- mfsource_EndGetEvent,
- mfsource_QueueEvent,
- mfsource_GetCharacteristics,
- mfsource_CreatePresentationDescriptor,
- mfsource_Start,
- mfsource_Stop,
- mfsource_Pause,
- mfsource_Shutdown,
-};
-
enum resolved_object_origin
{
OBJECT_FROM_BYTESTREAM,
@@ -6505,7 +6323,7 @@ static HRESULT WINAPI source_resolver_CreateObjectFromByteStream(IMFSourceResolv
return E_POINTER;
if (FAILED(hr = resolver_get_bytestream_handler(stream, url, flags, &handler)))
- goto fallback;
+ return MF_E_UNSUPPORTED_BYTESTREAM_TYPE;
hr = RtwqCreateAsyncResult((IUnknown *)handler, NULL, NULL, &result);
IMFByteStreamHandler_Release(handler);
@@ -6528,28 +6346,7 @@ static HRESULT WINAPI source_resolver_CreateObjectFromByteStream(IMFSourceResolv
hr = resolver_end_create_object(resolver, OBJECT_FROM_BYTESTREAM, result, obj_type, object);
IRtwqAsyncResult_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;
-
- new_object = HeapAlloc( GetProcessHeap(), 0, sizeof(*new_object) );
- if (!new_object)
- return E_OUTOFMEMORY;
-
- new_object->IMFMediaSource_iface.lpVtbl = &mfsourcevtbl;
- new_object->ref = 1;
-
- *object = (IUnknown *)&new_object->IMFMediaSource_iface;
- *obj_type = MF_OBJECT_MEDIASOURCE;
- return S_OK;
- }
-
- return E_NOTIMPL;
+ return hr;
}
static HRESULT WINAPI source_resolver_BeginCreateObjectFromURL(IMFSourceResolver *iface, const WCHAR *url,
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index 01749dd9ef8..fa90f1e4bac 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -382,12 +382,16 @@ static HRESULT WINAPI test_create_from_file_handler_callback_Invoke(IMFAsyncCall
handler = (IMFSchemeHandler *)IMFAsyncResult_GetStateNoAddRef(result);
hr = IMFSchemeHandler_EndCreateObject(handler, result, &obj_type, &object);
+todo_wine
ok(hr == S_OK, "Failed to create an object, hr %#x.\n", hr);
- hr = IMFAsyncResult_GetObject(result, &object2);
- ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
+ if (SUCCEEDED(hr))
+ {
+ hr = IMFAsyncResult_GetObject(result, &object2);
+ ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
- IUnknown_Release(object);
+ IUnknown_Release(object);
+ }
SetEvent(callback->event);
@@ -502,13 +506,43 @@ static void test_source_resolver(void)
hr = IMFSourceResolver_CreateObjectFromByteStream(resolver, stream, NULL, MF_RESOLUTION_MEDIASOURCE, NULL,
&obj_type, (IUnknown **)&mediasource);
- todo_wine ok(hr == MF_E_UNSUPPORTED_BYTESTREAM_TYPE, "got 0x%08x\n", hr);
+ ok(hr == MF_E_UNSUPPORTED_BYTESTREAM_TYPE, "got 0x%08x\n", hr);
if (hr == S_OK) IMFMediaSource_Release(mediasource);
hr = IMFSourceResolver_CreateObjectFromByteStream(resolver, stream, NULL, MF_RESOLUTION_BYTESTREAM, NULL,
&obj_type, (IUnknown **)&mediasource);
- todo_wine ok(hr == MF_E_UNSUPPORTED_BYTESTREAM_TYPE, "got 0x%08x\n", hr);
+ ok(hr == MF_E_UNSUPPORTED_BYTESTREAM_TYPE, "got 0x%08x\n", hr);
+
+ IMFByteStream_Release(stream);
+
+ /* Create from URL. */
+ callback.event = CreateEventA(NULL, FALSE, FALSE, NULL);
+
+ hr = IMFSourceResolver_CreateObjectFromURL(resolver, L"nonexisting.mp4", MF_RESOLUTION_BYTESTREAM, NULL, &obj_type,
+ (IUnknown **)&stream);
+ ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "Unexpected hr %#x.\n", hr);
+
+ hr = IMFSourceResolver_CreateObjectFromURL(resolver, filename, MF_RESOLUTION_BYTESTREAM, NULL, &obj_type,
+ (IUnknown **)&stream);
+ ok(hr == S_OK, "Failed to resolve url, hr %#x.\n", hr);
+ IMFByteStream_Release(stream);
+
+ hr = IMFSourceResolver_BeginCreateObjectFromURL(resolver, filename, MF_RESOLUTION_BYTESTREAM, NULL,
+ &cancel_cookie, &callback.IMFAsyncCallback_iface, (IUnknown *)resolver);
+ ok(hr == S_OK, "Create request failed, hr %#x.\n", hr);
+ ok(cancel_cookie != NULL, "Unexpected cancel object.\n");
+ IUnknown_Release(cancel_cookie);
+
+ if (SUCCEEDED(hr))
+ WaitForSingleObject(callback.event, INFINITE);
+
+ /* With explicit scheme. */
+ lstrcpyW(pathW, fileschemeW);
+ lstrcatW(pathW, filename);
+ hr = IMFSourceResolver_CreateObjectFromURL(resolver, pathW, MF_RESOLUTION_BYTESTREAM, NULL, &obj_type,
+ (IUnknown **)&stream);
+ ok(hr == S_OK, "Failed to resolve url, hr %#x.\n", hr);
IMFByteStream_Release(stream);
/* We have to create a new bytestream here, because all following
@@ -522,14 +556,31 @@ static void test_source_resolver(void)
ok(hr == S_OK, "Failed to set string value, hr %#x.\n", hr);
IMFAttributes_Release(attributes);
+ /* Start of gstreamer dependent tests */
+
hr = IMFSourceResolver_CreateObjectFromByteStream(resolver, stream, NULL, MF_RESOLUTION_MEDIASOURCE, NULL,
&obj_type, (IUnknown **)&mediasource);
- ok(hr == S_OK, "got 0x%08x\n", hr);
+ if (strcmp(winetest_platform, "wine"))
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ if (FAILED(hr))
+ {
+ IMFByteStream_Release(stream);
+ IMFSourceResolver_Release(resolver);
+
+ hr = MFShutdown();
+ ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
+
+ DeleteFileW(filename);
+ return;
+ }
ok(mediasource != NULL, "got %p\n", mediasource);
ok(obj_type == MF_OBJECT_MEDIASOURCE, "got %d\n", obj_type);
hr = IMFMediaSource_CreatePresentationDescriptor(mediasource, &descriptor);
+todo_wine
ok(hr == S_OK, "Failed to get presentation descriptor, hr %#x.\n", hr);
+ if (FAILED(hr))
+ goto skip_source_tests;
ok(descriptor != NULL, "got %p\n", descriptor);
hr = IMFPresentationDescriptor_GetStreamDescriptorByIndex(descriptor, 0, &selected, &sd);
@@ -540,10 +591,7 @@ static void test_source_resolver(void)
IMFStreamDescriptor_Release(sd);
hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
-todo_wine
ok(hr == S_OK, "Failed to get stream major type, hr %#x.\n", hr);
- if (FAILED(hr))
- goto skip_source_tests;
/* Check major/minor type for the test media. */
ok(IsEqualGUID(&guid, &MFMediaType_Video), "Unexpected major type %s.\n", debugstr_guid(&guid));
@@ -624,6 +672,7 @@ todo_wine
get_event((IMFMediaEventGenerator *)mediasource, MEEndOfPresentation, NULL);
IMFMediaTypeHandler_Release(handler);
+ IMFPresentationDescriptor_Release(descriptor);
hr = IMFMediaSource_Shutdown(mediasource);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
@@ -633,42 +682,9 @@ todo_wine
skip_source_tests:
- IMFPresentationDescriptor_Release(descriptor);
IMFMediaSource_Release(mediasource);
IMFByteStream_Release(stream);
- /* Create from URL. */
- callback.event = CreateEventA(NULL, FALSE, FALSE, NULL);
-
- hr = IMFSourceResolver_CreateObjectFromURL(resolver, L"nonexisting.mp4", MF_RESOLUTION_BYTESTREAM, NULL, &obj_type,
- (IUnknown **)&stream);
- ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "Unexpected hr %#x.\n", hr);
-
- hr = IMFSourceResolver_CreateObjectFromURL(resolver, filename, MF_RESOLUTION_BYTESTREAM, NULL, &obj_type,
- (IUnknown **)&stream);
- ok(hr == S_OK, "Failed to resolve url, hr %#x.\n", hr);
- IMFByteStream_Release(stream);
-
- hr = IMFSourceResolver_BeginCreateObjectFromURL(resolver, filename, MF_RESOLUTION_BYTESTREAM, NULL,
- &cancel_cookie, &callback.IMFAsyncCallback_iface, (IUnknown *)resolver);
- ok(hr == S_OK, "Create request failed, hr %#x.\n", hr);
- ok(cancel_cookie != NULL, "Unexpected cancel object.\n");
- IUnknown_Release(cancel_cookie);
-
- if (SUCCEEDED(hr))
- WaitForSingleObject(callback.event, INFINITE);
-
- /* With explicit scheme. */
- lstrcpyW(pathW, fileschemeW);
- lstrcatW(pathW, filename);
-
- hr = IMFSourceResolver_CreateObjectFromURL(resolver, pathW, MF_RESOLUTION_BYTESTREAM, NULL, &obj_type,
- (IUnknown **)&stream);
- ok(hr == S_OK, "Failed to resolve url, hr %#x.\n", hr);
- IMFByteStream_Release(stream);
-
- IMFSourceResolver_Release(resolver);
-
/* Create directly through scheme handler. */
hr = CoInitialize(NULL);
ok(SUCCEEDED(hr), "Failed to initialize, hr %#x.\n", hr);
@@ -693,12 +709,14 @@ skip_source_tests:
if (do_uninit)
CoUninitialize();
+ CloseHandle(callback.event);
+
+ IMFSourceResolver_Release(resolver);
+
hr = MFShutdown();
ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
DeleteFileW(filename);
-
- CloseHandle(callback.event);
}
static void init_functions(void)
--
2.28.0
4
21