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
September 2020
- 79 participants
- 771 discussions
[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
[PATCH 1/2] ntdll: Return buffer filled with random values from NtQuerySystemInformation(SystemInterruptInformation).
by Hans Leidekker 07 Sep '20
by Hans Leidekker 07 Sep '20
07 Sep '20
Based on a patch by Sebastian Lackner.
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
configure.ac | 2 ++
dlls/ntdll/tests/info.c | 3 ++-
dlls/ntdll/unix/system.c | 34 +++++++++++++++++++++++++++++-----
3 files changed, 33 insertions(+), 6 deletions(-)
diff --git a/configure.ac b/configure.ac
index 006087e05ec..c017d204aab 100644
--- a/configure.ac
+++ b/configure.ac
@@ -514,6 +514,7 @@ AC_CHECK_HEADERS(\
sys/protosw.h \
sys/ptrace.h \
sys/queue.h \
+ sys/random.h \
sys/resource.h \
sys/scsiio.h \
sys/shm.h \
@@ -2203,6 +2204,7 @@ AC_CHECK_FUNCS(\
getauxval \
getifaddrs \
getopt_long_only \
+ getrandom \
kqueue \
lstat \
mach_continuous_time \
diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c
index 057b855914a..b09c57b97a7 100644
--- a/dlls/ntdll/tests/info.c
+++ b/dlls/ntdll/tests/info.c
@@ -643,7 +643,8 @@ static void test_query_interrupt(void)
sii = HeapAlloc(GetProcessHeap(), 0, NeededLength);
status = pNtQuerySystemInformation(SystemInterruptInformation, sii, 0, &ReturnLength);
- ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
+ ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
+ ok(ReturnLength == NeededLength, "got %u\n", ReturnLength);
/* Try it for all processors */
status = pNtQuerySystemInformation(SystemInterruptInformation, sii, NeededLength, &ReturnLength);
diff --git a/dlls/ntdll/unix/system.c b/dlls/ntdll/unix/system.c
index c2412643afa..ccbc68b972d 100644
--- a/dlls/ntdll/unix/system.c
+++ b/dlls/ntdll/unix/system.c
@@ -29,6 +29,7 @@
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
+#include <errno.h>
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
@@ -42,6 +43,9 @@
#ifdef HAVE_MACHINE_CPU_H
# include <machine/cpu.h>
#endif
+#ifdef HAVE_SYS_RANDOM_H
+# include <sys/random.h>
+#endif
#ifdef HAVE_IOKIT_IOKITLIB_H
# include <CoreFoundation/CoreFoundation.h>
# include <IOKit/IOKitLib.h>
@@ -2422,16 +2426,36 @@ NTSTATUS WINAPI NtQuerySystemInformation( SYSTEM_INFORMATION_CLASS class,
case SystemInterruptInformation:
{
- SYSTEM_INTERRUPT_INFORMATION sii = {{ 0 }};
-
- len = sizeof(sii);
+ len = NtCurrentTeb()->Peb->NumberOfProcessors * sizeof(SYSTEM_INTERRUPT_INFORMATION);
if (size >= len)
{
if (!info) ret = STATUS_ACCESS_VIOLATION;
- else memcpy( info, &sii, len);
+ else
+ {
+#ifdef HAVE_GETRANDOM
+ int ret;
+ do
+ {
+ ret = getrandom( info, len, 0 );
+ }
+ while (ret == -1 && errno == EINTR);
+#else
+ int fd = open( "/dev/urandom", O_RDONLY );
+ if (fd != -1)
+ {
+ int ret;
+ do
+ {
+ ret = read( fd, info, len );
+ }
+ while (ret == -1 && errno == EINTR);
+ close( fd );
+ }
+ else WARN( "can't open /dev/urandom\n" );
+#endif
+ }
}
else ret = STATUS_INFO_LENGTH_MISMATCH;
- FIXME("info_class SYSTEM_INTERRUPT_INFORMATION\n");
break;
}
--
2.20.1
2
1
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 2/2] advapi32: Reimplement SystemFunction036 using system interrupt information.
by Hans Leidekker 07 Sep '20
by Hans Leidekker 07 Sep '20
07 Sep '20
Here's another proposal based on the discussion. If we implement system interrupt
information with random values taken from the urandom source (patch 1/2), we can
reimplement SystemFunction036 on top of that and get the same level of randomness.
Adding a cache makes this as fast as Windows on my machine, in the getrandom() case.
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/advapi32/crypt.c | 62 +++++++++++++++++++++++++++++++++----------
1 file changed, 48 insertions(+), 14 deletions(-)
diff --git a/dlls/advapi32/crypt.c b/dlls/advapi32/crypt.c
index 7199795b475..ab06c14393b 100644
--- a/dlls/advapi32/crypt.c
+++ b/dlls/advapi32/crypt.c
@@ -2422,6 +2422,36 @@ BOOL WINAPI SystemFunction035(LPCSTR lpszDllFilePath)
return TRUE;
}
+static CRITICAL_SECTION random_cs;
+static CRITICAL_SECTION_DEBUG random_debug =
+{
+ 0, 0, &random_cs,
+ { &random_debug.ProcessLocksList, &random_debug.ProcessLocksList },
+ 0, 0, { (DWORD_PTR)(__FILE__ ": random_cs") }
+};
+static CRITICAL_SECTION random_cs = { &random_debug, -1, 0, 0, 0, 0 };
+
+#define MAX_CPUS 128
+static char random_buf[sizeof(SYSTEM_INTERRUPT_INFORMATION) * MAX_CPUS];
+static ULONG random_len;
+static ULONG random_pos;
+
+/* FIXME: assumes interrupt information provides sufficient randomness */
+static BOOL fill_random_buffer(void)
+{
+ ULONG len = sizeof(SYSTEM_INTERRUPT_INFORMATION) * min( NtCurrentTeb()->Peb->NumberOfProcessors, MAX_CPUS );
+ NTSTATUS status;
+
+ if ((status = NtQuerySystemInformation( SystemInterruptInformation, random_buf, len, NULL )))
+ {
+ WARN( "failed to get random bytes %08x\n", status );
+ return FALSE;
+ }
+ random_len = len;
+ random_pos = 0;
+ return TRUE;
+}
+
/******************************************************************************
* SystemFunction036 (ADVAPI32.@)
*
@@ -2436,26 +2466,30 @@ BOOL WINAPI SystemFunction035(LPCSTR lpszDllFilePath)
* Failure: FALSE
*/
-BOOLEAN WINAPI SystemFunction036(PVOID pbBuffer, ULONG dwLen)
+BOOLEAN WINAPI SystemFunction036( void *buffer, ULONG len )
{
- int dev_random;
+ char *ptr = buffer;
- dev_random = open("/dev/urandom", O_RDONLY);
- if (dev_random != -1)
+ EnterCriticalSection( &random_cs );
+ while (len)
{
- if (read(dev_random, pbBuffer, dwLen) == (ssize_t)dwLen)
+ ULONG size;
+ if (random_pos >= random_len && !fill_random_buffer())
{
- close(dev_random);
- return TRUE;
+ SetLastError( NTE_FAIL );
+ LeaveCriticalSection( &random_cs );
+ return FALSE;
}
- close(dev_random);
+ size = min( len, random_len - random_pos );
+ memcpy( ptr, random_buf + random_pos, size );
+ random_pos += size;
+ ptr += size;
+ len -= size;
}
- else
- FIXME("couldn't open /dev/urandom\n");
- SetLastError(NTE_FAIL);
- return FALSE;
-}
-
+ LeaveCriticalSection( &random_cs );
+ return TRUE;
+}
+
/*
These functions have nearly identical prototypes to CryptProtectMemory and CryptUnprotectMemory,
in crypt32.dll.
--
2.20.1
1
0
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
3
11
07 Sep '20
Signed-off-by: Paul Gofman <pgofman(a)codeweavers.com>
---
dlls/ntdll/tests/exception.c | 24 ++++++++++++++++--------
1 file changed, 16 insertions(+), 8 deletions(-)
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index 06c4386a881..340469dd12f 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -6652,12 +6652,14 @@ static void test_extended_context(void)
length = 0xdeadbeef;
ret = pRtlGetExtendedContextLength2(flags, &length, 0);
- ok(!ret && length == expected_length_xstate - sizeof(YMMCONTEXT),
+ ok((!ret && length == expected_length_xstate - sizeof(YMMCONTEXT))
+ || broken(!ret && length == expected_length_xstate) /* win10pro */,
"Got unexpected result ret %#x, length %#x, test %u.\n", ret, length, test);
length = 0xdeadbeef;
ret = pRtlGetExtendedContextLength2(flags, &length, 3);
- ok(!ret && length == expected_length_xstate - sizeof(YMMCONTEXT),
+ ok((!ret && length == expected_length_xstate - sizeof(YMMCONTEXT))
+ || broken(!ret && length == expected_length_xstate) /* win10pro */,
"Got unexpected result ret %#x, length %#x, test %u.\n", ret, length, test);
length = 0xdeadbeef;
@@ -6839,7 +6841,9 @@ static void test_extended_context(void)
length2 = 0xdeadbeef;
p = pRtlLocateExtendedFeature(context_ex, 2, &length2);
- ok(!p && length2 == sizeof(YMMCONTEXT), "Got unexpected p %p, length %#x, flags %#x.\n", p, length2, flags);
+ ok((!p && length2 == sizeof(YMMCONTEXT))
+ || broken(p && length2 == sizeof(YMMCONTEXT)) /* win10pro */,
+ "Got unexpected p %p, length %#x, flags %#x.\n", p, length2, flags);
length2 = 0xdeadbeef;
p = pLocateXStateFeature(context, 2, &length2);
@@ -6861,7 +6865,8 @@ static void test_extended_context(void)
- context_arch[test].context_length;
ok(context_ex->XState.Offset == expected_offset,
"Got unexpected Offset %d, flags %#x.\n", context_ex->XState.Offset, flags);
- ok(context_ex->XState.Length == sizeof(XSTATE) - sizeof(YMMCONTEXT),
+ ok(context_ex->XState.Length == sizeof(XSTATE) - sizeof(YMMCONTEXT)
+ || broken(context_ex->XState.Length == sizeof(XSTATE)) /* win10pro */,
"Got unexpected Length %#x, flags %#x.\n", context_ex->XState.Length, flags);
ok(context_ex->All.Offset == -(int)context_arch[test].context_length,
@@ -6957,7 +6962,8 @@ static void test_extended_context(void)
context->ContextFlags);
expected_compaction = compaction_enabled ? (ULONG64)1 << 63 : 0;
- ok(!xs->Mask, "Got unexpected Mask %s.\n", wine_dbgstr_longlong(xs->Mask));
+ ok(!xs->Mask || broken(xs->Mask == 4) /* win10pro */,
+ "Got unexpected Mask %s.\n", wine_dbgstr_longlong(xs->Mask));
ok(xs->CompactionMask == expected_compaction, "Got unexpected CompactionMask %s.\n",
wine_dbgstr_longlong(xs->CompactionMask));
@@ -6965,7 +6971,7 @@ static void test_extended_context(void)
ok(data[i] == test_extended_context_data[i], "Got unexpected data %#x, i %u.\n", data[i], i);
for (i = 0; i < 4; ++i)
- ok(((ULONG *)&xs->YmmContext)[i] == 0xcccccccc,
+ ok(((ULONG *)&xs->YmmContext)[i] == (xs->Mask == 4 ? test_extended_context_data[i + 4] : 0xcccccccc),
"Got unexpected data %#x, i %u.\n", ((ULONG *)&xs->YmmContext)[i], i);
expected_compaction = compaction_enabled ? ((ULONG64)1 << 63) | 4 : 0;
@@ -6982,7 +6988,8 @@ static void test_extended_context(void)
ok(xs->CompactionMask == 4, "Got unexpected CompactionMask %s.\n",
wine_dbgstr_longlong(xs->CompactionMask));
for (i = 0; i < 4; ++i)
- ok(((ULONG *)&xs->YmmContext)[i] == 0xcccccccc,
+ ok(((ULONG *)&xs->YmmContext)[i] == 0xcccccccc
+ || broken(((ULONG *)&xs->YmmContext)[i] == test_extended_context_data[i + 4]) /* win10pro */,
"Got unexpected data %#x, i %u.\n", ((ULONG *)&xs->YmmContext)[i], i);
xs->CompactionMask = 4;
@@ -6997,7 +7004,8 @@ static void test_extended_context(void)
ok(xs->CompactionMask == expected_compaction, "Got unexpected CompactionMask %s.\n",
wine_dbgstr_longlong(xs->CompactionMask));
for (i = 0; i < 4; ++i)
- ok(((ULONG *)&xs->YmmContext)[i] == 0xcccccccc,
+ ok(((ULONG *)&xs->YmmContext)[i] == 0xcccccccc
+ || broken(((ULONG *)&xs->YmmContext)[i] == test_extended_context_data[i + 4]) /* win10pro */,
"Got unexpected data %#x, i %u.\n", ((ULONG *)&xs->YmmContext)[i], i);
context_ex->XState.Length = sizeof(XSTATE);
--
2.26.2
1
2
[PATCH] dwrite.idl: Use DEFINE_ENUM_FLAG_OPERATORS for enums that need it.
by Jacek Caban 07 Sep '20
by Jacek Caban 07 Sep '20
07 Sep '20
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
Fixes building Wine Gecko with Wine dwrite headers.
include/dwrite.idl | 2 ++
1 file changed, 2 insertions(+)
1
0
07 Sep '20
Make sure to restore sp from fp for CR == 3.
Fix unwinding of partial prologues/epilogues - the previous logic
had an off-by-one for the pos/skip handling; fix a few more
corner cases with odd number of saved registers.
Functions with the H flag set (saving x0-x7 on the stack) should
be considred having 4 nops (for the instructions saving the
registers) in the prologue for unwind purposes. When unwinding
through a partial epilogue, the same 4 nops should also be
considered to be there (even though no sane epilogue would restore
the registers there) based on how windows handles partial epilogue
unwinding in those cases.
Uncomment prologue/epilogue cases in an existing test and add
tests for many more cases.
Signed-off-by: Martin Storsjo <martin(a)martin.st>
---
dlls/ntdll/signal_arm64.c | 41 +++--
dlls/ntdll/tests/exception.c | 322 ++++++++++++++++++++++++++++++++++-
2 files changed, 340 insertions(+), 23 deletions(-)
diff --git a/dlls/ntdll/signal_arm64.c b/dlls/ntdll/signal_arm64.c
index df656d90f22..7100da33d54 100644
--- a/dlls/ntdll/signal_arm64.c
+++ b/dlls/ntdll/signal_arm64.c
@@ -708,6 +708,7 @@ static void *unwind_packed_data( ULONG_PTR base, ULONG_PTR pc, RUNTIME_FUNCTION
switch (func->u.s.CR)
{
case 3:
+ len++; /* mov x29,sp */
len++; /* stp x29,lr,[sp,0] */
if (local_size <= 512) break;
/* fall through */
@@ -717,9 +718,10 @@ static void *unwind_packed_data( ULONG_PTR base, ULONG_PTR pc, RUNTIME_FUNCTION
if (local_size > 4088) len++; /* sub sp,sp,#4088 */
break;
}
- if (offset < len + 4 * func->u.s.H) /* prolog */
+ len += 4 * func->u.s.H;
+ if (offset < len) /* prolog */
{
- skip = len + 4 * func->u.s.H - offset;
+ skip = len - offset;
}
else if (offset >= func->u.s.FunctionLength - (len + 1)) /* epilog */
{
@@ -733,6 +735,7 @@ static void *unwind_packed_data( ULONG_PTR base, ULONG_PTR pc, RUNTIME_FUNCTION
if (func->u.s.CR == 3)
{
DWORD64 *fp = (DWORD64 *) context->u.s.Fp; /* u.X[29] */
+ context->Sp = context->u.s.Fp;
context->u.X[29] = fp[0];
context->u.X[30] = fp[1];
}
@@ -748,34 +751,36 @@ static void *unwind_packed_data( ULONG_PTR base, ULONG_PTR pc, RUNTIME_FUNCTION
switch (func->u.s.CR)
{
case 3:
+ /* mov x29,sp */
+ if (pos++ >= skip) context->Sp = context->u.s.Fp;
if (local_size <= 512)
{
/* stp x29,lr,[sp,-#local_size]! */
- if (pos++ > skip) restore_regs( 29, 2, -local_size_regs, context, ptrs );
+ if (pos++ >= skip) restore_regs( 29, 2, -local_size_regs, context, ptrs );
break;
}
/* stp x29,lr,[sp,0] */
- if (pos++ > skip) restore_regs( 29, 2, 0, context, ptrs );
+ if (pos++ >= skip) restore_regs( 29, 2, 0, context, ptrs );
/* fall through */
case 0:
case 1:
if (!local_size) break;
/* sub sp,sp,#local_size */
- if (pos++ > skip) context->Sp += (local_size - 1) % 4088 + 1;
- if (local_size > 4088 && pos++ > skip) context->Sp += 4088;
+ if (pos++ >= skip) context->Sp += (local_size - 1) % 4088 + 1;
+ if (local_size > 4088 && pos++ >= skip) context->Sp += 4088;
break;
}
- if (func->u.s.H && offset < len + 4) pos += 4;
+ if (func->u.s.H) pos += 4;
if (fp_size)
{
- if (func->u.s.RegF % 2 == 0 && pos++ > skip)
+ if (func->u.s.RegF % 2 == 0 && pos++ >= skip)
/* str d%u,[sp,#fp_size] */
restore_fpregs( 8 + func->u.s.RegF, 1, int_regs + fp_regs - 1, context, ptrs );
- for (i = func->u.s.RegF / 2 - 1; i >= 0; i--)
+ for (i = (func->u.s.RegF + 1) / 2 - 1; i >= 0; i--)
{
- if (pos++ <= skip) continue;
+ if (pos++ < skip) continue;
if (!i && !int_size)
/* stp d8,d9,[sp,-#regsave]! */
restore_fpregs( 8, 2, -saved_regs, context, ptrs );
@@ -785,9 +790,9 @@ static void *unwind_packed_data( ULONG_PTR base, ULONG_PTR pc, RUNTIME_FUNCTION
}
}
- if (pos++ > skip)
+ if (func->u.s.RegI % 2)
{
- if (func->u.s.RegI % 2)
+ if (pos++ >= skip)
{
/* stp xn,lr,[sp,#offset] */
if (func->u.s.CR == 1) restore_regs( 30, 1, int_regs - 1, context, ptrs );
@@ -796,14 +801,16 @@ static void *unwind_packed_data( ULONG_PTR base, ULONG_PTR pc, RUNTIME_FUNCTION
(func->u.s.RegI > 1) ? func->u.s.RegI - 1 : -saved_regs,
context, ptrs );
}
- else if (func->u.s.CR == 1)
- /* str lr,[sp,#offset] */
- restore_regs( 30, 1, func->u.s.RegI ? int_regs - 1 : -saved_regs, context, ptrs );
+ }
+ else if (func->u.s.CR == 1)
+ {
+ /* str lr,[sp,#offset] */
+ if (pos++ >= skip) restore_regs( 30, 1, func->u.s.RegI ? int_regs - 1 : -saved_regs, context, ptrs );
}
- for (i = func->u.s.RegI / 2 - 1; i >= 0; i--)
+ for (i = func->u.s.RegI/ 2 - 1; i >= 0; i--)
{
- if (pos++ <= skip) continue;
+ if (pos++ < skip) continue;
if (i)
/* stp xn,xn+1,[sp,#offset] */
restore_regs( 19 + 2 * i, 2, 2 * i, context, ptrs );
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index 06c4386a881..465c123e675 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -4572,23 +4572,17 @@ static void test_virtual_unwind(void)
static const BYTE unwind_info_1[] = { DW(unwind_info_1_packed) };
- /* The prologue/epilogue locations are commented out below, as we don't
- * handle those cases at the moment. */
static const struct results results_1[] =
{
/* offset fp handler pc frame offset registers */
-#if 0
{ 0x00, 0x00, 0, ORIG_LR, 0x000, TRUE, { {-1,-1} }},
{ 0x04, 0x00, 0, ORIG_LR, 0x020, TRUE, { {x19,0x00}, {x20,0x08}, {-1,-1} }},
{ 0x08, 0x00, 0, 0x10, 0x020, TRUE, { {x19,0x00}, {x20,0x08}, {lr,0x10}, {-1,-1} }},
-#endif
{ 0x0c, 0x00, 0, 0x20, 0x030, TRUE, { {x19,0x10}, {x20,0x18}, {lr,0x20}, {-1,-1} }},
{ 0x10, 0x00, 0, 0x20, 0x030, TRUE, { {x19,0x10}, {x20,0x18}, {lr,0x20}, {-1,-1} }},
-#if 0
{ 0x14, 0x00, 0, 0x10, 0x020, TRUE, { {x19,0x00}, {x20,0x08}, {lr,0x10}, {-1,-1} }},
{ 0x18, 0x00, 0, ORIG_LR, 0x020, TRUE, { {x19,0x00}, {x20,0x08}, {-1,-1} }},
{ 0x1c, 0x00, 0, ORIG_LR, 0x000, TRUE, { {-1,-1} }},
-#endif
};
static const BYTE function_2[] =
@@ -4808,6 +4802,314 @@ static void test_virtual_unwind(void)
#endif
};
+ static const BYTE function_6[] =
+ {
+ 0xf3, 0x53, 0xbd, 0xa9, /* 00: stp x19, x20, [sp, #-48]! */
+ 0xf5, 0x0b, 0x00, 0xf9, /* 04: str x21, [sp, #16] */
+ 0xe8, 0xa7, 0x01, 0x6d, /* 08: stp d8, d9, [sp, #24] */
+ 0xea, 0x17, 0x00, 0xfd, /* 0c: str d10, [sp, #40] */
+ 0xff, 0x03, 0x00, 0xd1, /* 10: sub sp, sp, #0 */
+ 0x1f, 0x20, 0x03, 0xd5, /* 14: nop */
+ 0xff, 0x03, 0x00, 0x91, /* 18: add sp, sp, #0 */
+ 0xea, 0x17, 0x40, 0xfd, /* 1c: ldr d10, [sp, #40] */
+ 0xe8, 0xa7, 0x41, 0x6d, /* 20: ldp d8, d9, [sp, #24] */
+ 0xf5, 0x0b, 0x40, 0xf9, /* 24: ldr x21, [sp, #16] */
+ 0xf3, 0x53, 0xc3, 0xa8, /* 28: ldp x19, x20, [sp], #48 */
+ 0xc0, 0x03, 0x5f, 0xd6, /* 2c: ret */
+ };
+
+ static const DWORD unwind_info_6_packed =
+ (1 << 0) | /* Flag */
+ (sizeof(function_6)/4 << 2) | /* FunctionLength */
+ (2 << 13) | /* RegF */
+ (3 << 16) | /* RegI */
+ (0 << 20) | /* H */
+ (0 << 21) | /* CR */
+ (3 << 23); /* FrameSize */
+
+ static const BYTE unwind_info_6[] = { DW(unwind_info_6_packed) };
+
+ static const struct results results_6[] =
+ {
+ /* offset fp handler pc frame offset registers */
+ { 0x00, 0x00, 0, ORIG_LR, 0x000, TRUE, { {-1,-1} }},
+ { 0x04, 0x00, 0, ORIG_LR, 0x030, TRUE, { {x19,0x00}, {x20,0x08}, {-1,-1} }},
+ { 0x08, 0x00, 0, ORIG_LR, 0x030, TRUE, { {x19,0x00}, {x20,0x08}, {x21, 0x10}, {-1,-1} }},
+ { 0x0c, 0x00, 0, ORIG_LR, 0x030, TRUE, { {x19,0x00}, {x20,0x08}, {x21, 0x10}, {d8, 0x18}, {d9, 0x20}, {-1,-1} }},
+ { 0x10, 0x00, 0, ORIG_LR, 0x030, TRUE, { {x19,0x00}, {x20,0x08}, {x21, 0x10}, {d8, 0x18}, {d9, 0x20}, {d10, 0x28}, {-1,-1} }},
+ { 0x14, 0x00, 0, ORIG_LR, 0x030, TRUE, { {x19,0x00}, {x20,0x08}, {x21, 0x10}, {d8, 0x18}, {d9, 0x20}, {d10, 0x28}, {-1,-1} }},
+ { 0x18, 0x00, 0, ORIG_LR, 0x030, TRUE, { {x19,0x00}, {x20,0x08}, {x21, 0x10}, {d8, 0x18}, {d9, 0x20}, {d10, 0x28}, {-1,-1} }},
+ { 0x1c, 0x00, 0, ORIG_LR, 0x030, TRUE, { {x19,0x00}, {x20,0x08}, {x21, 0x10}, {d8, 0x18}, {d9, 0x20}, {d10, 0x28}, {-1,-1} }},
+ { 0x20, 0x00, 0, ORIG_LR, 0x030, TRUE, { {x19,0x00}, {x20,0x08}, {x21, 0x10}, {d8, 0x18}, {d9, 0x20}, {-1,-1} }},
+ { 0x24, 0x00, 0, ORIG_LR, 0x030, TRUE, { {x19,0x00}, {x20,0x08}, {x21, 0x10}, {-1,-1} }},
+ { 0x28, 0x00, 0, ORIG_LR, 0x030, TRUE, { {x19,0x00}, {x20,0x08}, {-1,-1} }},
+ { 0x2c, 0x00, 0, ORIG_LR, 0x000, TRUE, { {-1,-1} }},
+ };
+
+ static const BYTE function_7[] =
+ {
+ 0xf3, 0x0f, 0x1d, 0xf8, /* 00: str x19, [sp, #-48]! */
+ 0xe8, 0xa7, 0x00, 0x6d, /* 04: stp d8, d9, [sp, #8] */
+ 0xea, 0xaf, 0x01, 0x6d, /* 08: stp d10, d11, [sp, #24] */
+ 0xff, 0x03, 0x00, 0xd1, /* 0c: sub sp, sp, #0 */
+ 0x1f, 0x20, 0x03, 0xd5, /* 10: nop */
+ 0xff, 0x03, 0x00, 0x91, /* 14: add sp, sp, #0 */
+ 0xea, 0xaf, 0x41, 0x6d, /* 18: ldp d10, d11, [sp, #24] */
+ 0xe8, 0xa7, 0x40, 0x6d, /* 1c: ldp d8, d9, [sp, #8] */
+ 0xf3, 0x07, 0x43, 0xf8, /* 20: ldr x19, [sp], #48 */
+ 0xc0, 0x03, 0x5f, 0xd6, /* 24: ret */
+ };
+
+ static const DWORD unwind_info_7_packed =
+ (1 << 0) | /* Flag */
+ (sizeof(function_7)/4 << 2) | /* FunctionLength */
+ (3 << 13) | /* RegF */
+ (1 << 16) | /* RegI */
+ (0 << 20) | /* H */
+ (0 << 21) | /* CR */
+ (3 << 23); /* FrameSize */
+
+ static const BYTE unwind_info_7[] = { DW(unwind_info_7_packed) };
+
+ static const struct results results_7[] =
+ {
+ /* offset fp handler pc frame offset registers */
+ { 0x00, 0x00, 0, ORIG_LR, 0x000, TRUE, { {-1,-1} }},
+ { 0x04, 0x00, 0, ORIG_LR, 0x030, TRUE, { {x19, 0x00}, {-1,-1} }},
+ { 0x08, 0x00, 0, ORIG_LR, 0x030, TRUE, { {x19, 0x00}, {d8, 0x08}, {d9, 0x10}, {-1,-1} }},
+ { 0x0c, 0x00, 0, ORIG_LR, 0x030, TRUE, { {x19, 0x00}, {d8, 0x08}, {d9, 0x10}, {d10, 0x18}, {d11, 0x20}, {-1,-1} }},
+ { 0x10, 0x00, 0, ORIG_LR, 0x030, TRUE, { {x19, 0x00}, {d8, 0x08}, {d9, 0x10}, {d10, 0x18}, {d11, 0x20}, {-1,-1} }},
+ { 0x14, 0x00, 0, ORIG_LR, 0x030, TRUE, { {x19, 0x00}, {d8, 0x08}, {d9, 0x10}, {d10, 0x18}, {d11, 0x20}, {-1,-1} }},
+ { 0x18, 0x00, 0, ORIG_LR, 0x030, TRUE, { {x19, 0x00}, {d8, 0x08}, {d9, 0x10}, {d10, 0x18}, {d11, 0x20}, {-1,-1} }},
+ { 0x1c, 0x00, 0, ORIG_LR, 0x030, TRUE, { {x19, 0x00}, {d8, 0x08}, {d9, 0x10}, {-1,-1} }},
+ { 0x20, 0x00, 0, ORIG_LR, 0x030, TRUE, { {x19, 0x00}, {-1,-1} }},
+ { 0x24, 0x00, 0, ORIG_LR, 0x000, TRUE, { {-1,-1} }},
+ };
+
+ static const BYTE function_8[] =
+ {
+ 0xe8, 0x27, 0xbf, 0x6d, /* 00: stp d8, d9, [sp, #-16]! */
+ 0xff, 0x83, 0x00, 0xd1, /* 04: sub sp, sp, #32 */
+ 0x1f, 0x20, 0x03, 0xd5, /* 08: nop */
+ 0xff, 0x83, 0x00, 0x91, /* 0c: add sp, sp, #32 */
+ 0xe8, 0x27, 0xc1, 0x6c, /* 10: ldp d8, d9, [sp], #16 */
+ 0xc0, 0x03, 0x5f, 0xd6, /* 14: ret */
+ };
+
+ static const DWORD unwind_info_8_packed =
+ (1 << 0) | /* Flag */
+ (sizeof(function_8)/4 << 2) | /* FunctionLength */
+ (1 << 13) | /* RegF */
+ (0 << 16) | /* RegI */
+ (0 << 20) | /* H */
+ (0 << 21) | /* CR */
+ (3 << 23); /* FrameSize */
+
+ static const BYTE unwind_info_8[] = { DW(unwind_info_8_packed) };
+
+ static const struct results results_8[] =
+ {
+ /* offset fp handler pc frame offset registers */
+ { 0x00, 0x00, 0, ORIG_LR, 0x000, TRUE, { {-1,-1} }},
+ { 0x04, 0x00, 0, ORIG_LR, 0x010, TRUE, { {d8, 0x00}, {d9, 0x08}, {-1,-1} }},
+ { 0x08, 0x00, 0, ORIG_LR, 0x030, TRUE, { {d8, 0x20}, {d9, 0x28}, {-1,-1} }},
+ { 0x0c, 0x00, 0, ORIG_LR, 0x030, TRUE, { {d8, 0x20}, {d9, 0x28}, {-1,-1} }},
+ { 0x10, 0x00, 0, ORIG_LR, 0x010, TRUE, { {d8, 0x00}, {d9, 0x08}, {-1,-1} }},
+ { 0x14, 0x00, 0, ORIG_LR, 0x000, TRUE, { {-1,-1} }},
+ };
+
+ static const BYTE function_9[] =
+ {
+ 0xf3, 0x0f, 0x1b, 0xf8, /* 00: str x19, [sp, #-80]! */
+ 0xe0, 0x87, 0x00, 0xa9, /* 04: stp x0, x1, [sp, #8] */
+ 0xe2, 0x8f, 0x01, 0xa9, /* 08: stp x2, x3, [sp, #24] */
+ 0xe4, 0x97, 0x02, 0xa9, /* 0c: stp x4, x5, [sp, #40] */
+ 0xe6, 0x9f, 0x03, 0xa9, /* 10: stp x6, x7, [sp, #56] */
+ 0xff, 0x83, 0x00, 0xd1, /* 14: sub sp, sp, #32 */
+ 0x1f, 0x20, 0x03, 0xd5, /* 18: nop */
+ 0xff, 0x83, 0x00, 0x91, /* 1c: add sp, sp, #32 */
+ 0x1f, 0x20, 0x03, 0xd5, /* 20: nop */
+ 0x1f, 0x20, 0x03, 0xd5, /* 24: nop */
+ 0x1f, 0x20, 0x03, 0xd5, /* 28: nop */
+ 0x1f, 0x20, 0x03, 0xd5, /* 2c: nop */
+ 0xf3, 0x0f, 0x1b, 0xf8, /* 30: ldr x19, [sp], #80 */
+ 0xc0, 0x03, 0x5f, 0xd6, /* 34: ret */
+ };
+
+ static const DWORD unwind_info_9_packed =
+ (1 << 0) | /* Flag */
+ (sizeof(function_9)/4 << 2) | /* FunctionLength */
+ (0 << 13) | /* RegF */
+ (1 << 16) | /* RegI */
+ (1 << 20) | /* H */
+ (0 << 21) | /* CR */
+ (7 << 23); /* FrameSize */
+
+ static const BYTE unwind_info_9[] = { DW(unwind_info_9_packed) };
+
+ static const struct results results_9[] =
+ {
+ /* offset fp handler pc frame offset registers */
+ { 0x00, 0x00, 0, ORIG_LR, 0x000, TRUE, { {-1,-1} }},
+ { 0x04, 0x00, 0, ORIG_LR, 0x050, TRUE, { {x19, 0x00}, {-1,-1} }},
+ { 0x08, 0x00, 0, ORIG_LR, 0x050, TRUE, { {x19, 0x00}, {-1,-1} }},
+ { 0x0c, 0x00, 0, ORIG_LR, 0x050, TRUE, { {x19, 0x00}, {-1,-1} }},
+ { 0x10, 0x00, 0, ORIG_LR, 0x050, TRUE, { {x19, 0x00}, {-1,-1} }},
+ { 0x14, 0x00, 0, ORIG_LR, 0x050, TRUE, { {x19, 0x00}, {-1,-1} }},
+ { 0x18, 0x00, 0, ORIG_LR, 0x070, TRUE, { {x19, 0x20}, {-1,-1} }},
+ { 0x1c, 0x00, 0, ORIG_LR, 0x070, TRUE, { {x19, 0x20}, {-1,-1} }},
+ { 0x20, 0x00, 0, ORIG_LR, 0x050, TRUE, { {x19, 0x00}, {-1,-1} }},
+ { 0x24, 0x00, 0, ORIG_LR, 0x050, TRUE, { {x19, 0x00}, {-1,-1} }},
+ { 0x28, 0x00, 0, ORIG_LR, 0x050, TRUE, { {x19, 0x00}, {-1,-1} }},
+ { 0x2c, 0x00, 0, ORIG_LR, 0x050, TRUE, { {x19, 0x00}, {-1,-1} }},
+ { 0x30, 0x00, 0, ORIG_LR, 0x050, TRUE, { {x19, 0x00}, {-1,-1} }},
+ { 0x34, 0x00, 0, ORIG_LR, 0x000, TRUE, { {-1,-1} }},
+ };
+
+ static const BYTE function_10[] =
+ {
+ 0xfe, 0x0f, 0x1f, 0xf8, /* 00: str lr, [sp, #-16]! */
+ 0xff, 0x43, 0x00, 0xd1, /* 04: sub sp, sp, #16 */
+ 0x1f, 0x20, 0x03, 0xd5, /* 08: nop */
+ 0xff, 0x43, 0x00, 0x91, /* 0c: add sp, sp, #16 */
+ 0xfe, 0x07, 0x41, 0xf8, /* 10: ldr lr, [sp], #16 */
+ 0xc0, 0x03, 0x5f, 0xd6, /* 14: ret */
+ };
+
+ static const DWORD unwind_info_10_packed =
+ (1 << 0) | /* Flag */
+ (sizeof(function_10)/4 << 2) | /* FunctionLength */
+ (0 << 13) | /* RegF */
+ (0 << 16) | /* RegI */
+ (0 << 20) | /* H */
+ (1 << 21) | /* CR */
+ (2 << 23); /* FrameSize */
+
+ static const BYTE unwind_info_10[] = { DW(unwind_info_10_packed) };
+
+ static const struct results results_10[] =
+ {
+ /* offset fp handler pc frame offset registers */
+ { 0x00, 0x00, 0, ORIG_LR, 0x000, TRUE, { {-1,-1} }},
+ { 0x04, 0x00, 0, 0x00, 0x010, TRUE, { {lr, 0x00}, {-1,-1} }},
+ { 0x08, 0x00, 0, 0x10, 0x020, TRUE, { {lr, 0x10}, {-1,-1} }},
+ { 0x0c, 0x00, 0, 0x10, 0x020, TRUE, { {lr, 0x10}, {-1,-1} }},
+ { 0x10, 0x00, 0, 0x00, 0x010, TRUE, { {lr, 0x00}, {-1,-1} }},
+ { 0x14, 0x00, 0, ORIG_LR, 0x000, TRUE, { {-1,-1} }},
+ };
+
+ static const BYTE function_11[] =
+ {
+ 0xf3, 0x53, 0xbe, 0xa9, /* 00: stp x19, x20, [sp, #-32]! */
+ 0xf5, 0x7b, 0x01, 0xa9, /* 04: stp x21, lr, [sp, #16] */
+ 0xff, 0x43, 0x00, 0xd1, /* 08: sub sp, sp, #16 */
+ 0x1f, 0x20, 0x03, 0xd5, /* 0c: nop */
+ 0xff, 0x43, 0x00, 0x91, /* 10: add sp, sp, #16 */
+ 0xf5, 0x7b, 0x41, 0xa9, /* 14: ldp x21, lr, [sp, #16] */
+ 0xf3, 0x53, 0xc2, 0xa8, /* 18: ldp x19, x20, [sp], #32 */
+ 0xc0, 0x03, 0x5f, 0xd6, /* 1c: ret */
+ };
+
+ static const DWORD unwind_info_11_packed =
+ (1 << 0) | /* Flag */
+ (sizeof(function_11)/4 << 2) | /* FunctionLength */
+ (0 << 13) | /* RegF */
+ (3 << 16) | /* RegI */
+ (0 << 20) | /* H */
+ (1 << 21) | /* CR */
+ (3 << 23); /* FrameSize */
+
+ static const BYTE unwind_info_11[] = { DW(unwind_info_11_packed) };
+
+ static const struct results results_11[] =
+ {
+ /* offset fp handler pc frame offset registers */
+ { 0x00, 0x00, 0, ORIG_LR, 0x000, TRUE, { {-1,-1} }},
+ { 0x04, 0x00, 0, ORIG_LR, 0x020, TRUE, { {x19, 0x00}, {x20, 0x08}, {-1,-1} }},
+ { 0x08, 0x00, 0, 0x18, 0x020, TRUE, { {x19, 0x00}, {x20, 0x08}, {x21, 0x10}, {lr, 0x18}, {-1,-1} }},
+ { 0x0c, 0x00, 0, 0x28, 0x030, TRUE, { {x19, 0x10}, {x20, 0x18}, {x21, 0x20}, {lr, 0x28}, {-1,-1} }},
+ { 0x10, 0x00, 0, 0x28, 0x030, TRUE, { {x19, 0x10}, {x20, 0x18}, {x21, 0x20}, {lr, 0x28}, {-1,-1} }},
+ { 0x14, 0x00, 0, 0x18, 0x020, TRUE, { {x19, 0x00}, {x20, 0x08}, {x21, 0x10}, {lr, 0x18}, {-1,-1} }},
+ { 0x18, 0x00, 0, ORIG_LR, 0x020, TRUE, { {x19, 0x00}, {x20, 0x08}, {-1,-1} }},
+ { 0x1c, 0x00, 0, ORIG_LR, 0x000, TRUE, { {-1,-1} }},
+ };
+
+ static const BYTE function_12[] =
+ {
+ 0xf3, 0x53, 0xbf, 0xa9, /* 00: stp x19, x20, [sp, #-16]! */
+ 0xfd, 0x7b, 0xbe, 0xa9, /* 04: stp x29, lr, [sp, #-32]! */
+ 0xfd, 0x03, 0x00, 0x91, /* 08: mov x29, sp */
+ 0x1f, 0x20, 0x03, 0xd5, /* 0c: nop */
+ 0xbf, 0x03, 0x00, 0x91, /* 10: mov sp, x29 */
+ 0xfd, 0x7b, 0xc2, 0xa8, /* 14: ldp x29, lr, [sp], #32 */
+ 0xf3, 0x53, 0xc1, 0xa8, /* 18: ldp x19, x20, [sp], #16 */
+ 0xc0, 0x03, 0x5f, 0xd6, /* 1c: ret */
+ };
+
+ static const DWORD unwind_info_12_packed =
+ (1 << 0) | /* Flag */
+ (sizeof(function_12)/4 << 2) | /* FunctionLength */
+ (0 << 13) | /* RegF */
+ (2 << 16) | /* RegI */
+ (0 << 20) | /* H */
+ (3 << 21) | /* CR */
+ (3 << 23); /* FrameSize */
+
+ static const BYTE unwind_info_12[] = { DW(unwind_info_12_packed) };
+
+ static const struct results results_12[] =
+ {
+ /* offset fp handler pc frame offset registers */
+ { 0x00, 0x10, 0, ORIG_LR, 0x000, TRUE, { {-1,-1} }},
+ { 0x04, 0x10, 0, ORIG_LR, 0x010, TRUE, { {x19, 0x00}, {x20, 0x08}, {-1,-1} }},
+ { 0x08, 0x10, 0, 0x08, 0x030, TRUE, { {x19, 0x20}, {x20, 0x28}, {x29, 0x00}, {lr, 0x08}, {-1,-1} }},
+ { 0x0c, 0x10, 0, 0x18, 0x040, TRUE, { {x19, 0x30}, {x20, 0x38}, {x29, 0x10}, {lr, 0x18}, {-1,-1} }},
+ { 0x10, 0x10, 0, 0x18, 0x040, TRUE, { {x19, 0x30}, {x20, 0x38}, {x29, 0x10}, {lr, 0x18}, {-1,-1} }},
+ { 0x14, 0x10, 0, 0x08, 0x030, TRUE, { {x19, 0x20}, {x20, 0x28}, {x29, 0x00}, {lr, 0x08}, {-1,-1} }},
+ { 0x18, 0x10, 0, ORIG_LR, 0x010, TRUE, { {x19, 0x00}, {x20, 0x08}, {-1,-1} }},
+ { 0x1c, 0x10, 0, ORIG_LR, 0x000, TRUE, { {-1,-1} }},
+ };
+
+ static const BYTE function_13[] =
+ {
+ 0xf3, 0x53, 0xbf, 0xa9, /* 00: stp x19, x20, [sp, #-16]! */
+ 0xff, 0x43, 0x08, 0xd1, /* 04: sub sp, sp, #528 */
+ 0xfd, 0x7b, 0x00, 0xd1, /* 08: stp x29, lr, [sp] */
+ 0xfd, 0x03, 0x00, 0x91, /* 0c: mov x29, sp */
+ 0x1f, 0x20, 0x03, 0xd5, /* 10: nop */
+ 0xbf, 0x03, 0x00, 0x91, /* 14: mov sp, x29 */
+ 0xfd, 0x7b, 0x40, 0xa9, /* 18: ldp x29, lr, [sp] */
+ 0xff, 0x43, 0x08, 0x91, /* 1c: add sp, sp, #528 */
+ 0xf3, 0x53, 0xc1, 0xa8, /* 20: ldp x19, x20, [sp], #16 */
+ 0xc0, 0x03, 0x5f, 0xd6, /* 24: ret */
+ };
+
+ static const DWORD unwind_info_13_packed =
+ (1 << 0) | /* Flag */
+ (sizeof(function_13)/4 << 2) | /* FunctionLength */
+ (0 << 13) | /* RegF */
+ (2 << 16) | /* RegI */
+ (0 << 20) | /* H */
+ (3 << 21) | /* CR */
+ (34 << 23); /* FrameSize */
+
+ static const BYTE unwind_info_13[] = { DW(unwind_info_13_packed) };
+
+ static const struct results results_13[] =
+ {
+ /* offset fp handler pc frame offset registers */
+ { 0x00, 0x10, 0, ORIG_LR, 0x000, TRUE, { {-1,-1} }},
+ { 0x04, 0x10, 0, ORIG_LR, 0x010, TRUE, { {x19, 0x00}, {x20, 0x08}, {-1,-1} }},
+ { 0x08, 0x10, 0, ORIG_LR, 0x220, TRUE, { {x19, 0x210}, {x20, 0x218}, {-1,-1} }},
+ { 0x0c, 0x10, 0, 0x08, 0x220, TRUE, { {x19, 0x210}, {x20, 0x218}, {x29, 0x00}, {lr, 0x08}, {-1,-1} }},
+ { 0x10, 0x10, 0, 0x18, 0x230, TRUE, { {x19, 0x220}, {x20, 0x228}, {x29, 0x10}, {lr, 0x18}, {-1,-1} }},
+ { 0x14, 0x10, 0, 0x18, 0x230, TRUE, { {x19, 0x220}, {x20, 0x228}, {x29, 0x10}, {lr, 0x18}, {-1,-1} }},
+ { 0x18, 0x10, 0, 0x08, 0x220, TRUE, { {x19, 0x210}, {x20, 0x218}, {x29, 0x00}, {lr, 0x08}, {-1,-1} }},
+ { 0x1c, 0x10, 0, ORIG_LR, 0x220, TRUE, { {x19, 0x210}, {x20, 0x218}, {-1,-1} }},
+ { 0x20, 0x10, 0, ORIG_LR, 0x010, TRUE, { {x19, 0x00}, {x20, 0x08}, {-1,-1} }},
+ { 0x24, 0x10, 0, ORIG_LR, 0x000, TRUE, { {-1,-1} }},
+ };
+
static const struct unwind_test tests[] =
{
#define TEST(func, unwind, unwind_packed, results) \
@@ -4818,6 +5120,14 @@ static void test_virtual_unwind(void)
TEST(function_3, unwind_info_3, 0, results_3),
TEST(function_4, unwind_info_4, 0, results_4),
TEST(function_5, unwind_info_5, 0, results_5),
+ TEST(function_6, unwind_info_6, 1, results_6),
+ TEST(function_7, unwind_info_7, 1, results_7),
+ TEST(function_8, unwind_info_8, 1, results_8),
+ TEST(function_9, unwind_info_9, 1, results_9),
+ TEST(function_10, unwind_info_10, 1, results_10),
+ TEST(function_11, unwind_info_11, 1, results_11),
+ TEST(function_12, unwind_info_12, 1, results_12),
+ TEST(function_13, unwind_info_13, 1, results_13),
#undef TEST
};
unsigned int i;
--
2.17.1
2
1
07 Sep '20
From: Eric Wheeler <wine(a)linux.ewheeler.net>
Selected column should be using different background color,
this patch does not implement this.
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
v2: fixed initial index, added some tests
dlls/comctl32/listview.c | 10 ++++++---
dlls/comctl32/tests/listview.c | 37 ++++++++++++++++++++++++++++++++++
2 files changed, 44 insertions(+), 3 deletions(-)
diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c
index dba16d13a4c..e31c787c4a4 100644
--- a/dlls/comctl32/listview.c
+++ b/dlls/comctl32/listview.c
@@ -99,7 +99,6 @@
* -- LVM_GETINSERTMARKRECT
* -- LVM_GETNUMBEROFWORKAREAS
* -- LVM_GETOUTLINECOLOR, LVM_SETOUTLINECOLOR
- * -- LVM_GETSELECTEDCOLUMN, LVM_SETSELECTEDCOLUMN
* -- LVM_GETISEARCHSTRINGW, LVM_GETISEARCHSTRINGA
* -- LVM_GETTILEINFO, LVM_SETTILEINFO
* -- LVM_GETTILEVIEWINFO, LVM_SETTILEVIEWINFO
@@ -248,6 +247,7 @@ typedef struct tagLISTVIEW_INFO
/* columns */
HDPA hdpaColumns; /* array of COLUMN_INFO pointers */
BOOL colRectsDirty; /* trigger column rectangles requery from header */
+ INT selected_column; /* index for LVM_SETSELECTEDCOLUMN/LVM_GETSELECTEDCOLUMN */
/* item metrics */
BOOL bNoItemMetrics; /* flags if item metrics are not yet computed */
@@ -9506,6 +9506,7 @@ static LRESULT LISTVIEW_NCCreate(HWND hwnd, WPARAM wParam, const CREATESTRUCTW *
infoPtr->itemEdit.fEnabled = FALSE;
infoPtr->iVersion = COMCTL32_VERSION;
infoPtr->colRectsDirty = FALSE;
+ infoPtr->selected_column = -1;
/* get default font (icon title) */
SystemParametersInfoW(SPI_GETICONTITLELOGFONT, 0, &logFont, 0);
@@ -11465,7 +11466,8 @@ LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
/* case LVM_GETOUTLINECOLOR: */
- /* case LVM_GETSELECTEDCOLUMN: */
+ case LVM_GETSELECTEDCOLUMN:
+ return infoPtr->selected_column;
case LVM_GETSELECTEDCOUNT:
return LISTVIEW_GetSelectedCount(infoPtr);
@@ -11638,7 +11640,9 @@ LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
/* case LVM_SETOUTLINECOLOR: */
- /* case LVM_SETSELECTEDCOLUMN: */
+ case LVM_SETSELECTEDCOLUMN:
+ infoPtr->selected_column = (INT)wParam;
+ return TRUE;
case LVM_SETSELECTIONMARK:
return LISTVIEW_SetSelectionMark(infoPtr, (INT)lParam);
diff --git a/dlls/comctl32/tests/listview.c b/dlls/comctl32/tests/listview.c
index a9b853eda85..500cc363c2d 100644
--- a/dlls/comctl32/tests/listview.c
+++ b/dlls/comctl32/tests/listview.c
@@ -6659,6 +6659,42 @@ static void test_item_state_change(void)
}
}
+static void test_selected_column(void)
+{
+ static const DWORD styles[] = { LVS_ICON, LVS_LIST, LVS_REPORT, LVS_SMALLICON };
+ int ret, i;
+ HWND hwnd;
+
+ for (i = 0; i < ARRAY_SIZE(styles); ++i)
+ {
+ hwnd = create_listview_control(styles[i]);
+
+ /* Initial value */
+ ret = SendMessageA(hwnd, LVM_GETSELECTEDCOLUMN, 0, 0);
+ ok(ret == -1, "Unexpected column %d.\n", ret);
+
+ ret = SendMessageA(hwnd, LVM_SETSELECTEDCOLUMN, -100, 0);
+ ok(ret == 1, "Unexpected return value %d.\n", ret);
+
+ ret = SendMessageA(hwnd, LVM_GETSELECTEDCOLUMN, 0, 0);
+ ok(ret == -100, "Unexpected column %d.\n", ret);
+
+ ret = SendMessageA(hwnd, LVM_SETSELECTEDCOLUMN, 100, 0);
+ ok(ret == 1, "Unexpected return value %d.\n", ret);
+
+ ret = SendMessageA(hwnd, LVM_GETSELECTEDCOLUMN, 0, 0);
+ ok(ret == 100, "Unexpected column %d.\n", ret);
+
+ ret = SendMessageA(hwnd, LVM_SETSELECTEDCOLUMN, -1, 0);
+ ok(ret == 1, "Unexpected return value %d.\n", ret);
+
+ ret = SendMessageA(hwnd, LVM_GETSELECTEDCOLUMN, 0, 0);
+ ok(ret == -1, "Unexpected column %d.\n", ret);
+
+ DestroyWindow(hwnd);
+ }
+}
+
START_TEST(listview)
{
ULONG_PTR ctx_cookie;
@@ -6766,6 +6802,7 @@ START_TEST(listview)
test_LVN_ENDLABELEDIT();
test_LVM_GETCOUNTPERPAGE();
test_item_state_change();
+ test_selected_column();
unload_v6_module(ctx_cookie, hCtx);
--
2.28.0
1
0
[PATCH 1/5] evr/mixer: Use same max input count symbol for GetStreamLimits().
by Nikolay Sivov 07 Sep '20
by Nikolay Sivov 07 Sep '20
07 Sep '20
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/evr/mixer.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/evr/mixer.c b/dlls/evr/mixer.c
index d9f86a7fc91..7e08beae353 100644
--- a/dlls/evr/mixer.c
+++ b/dlls/evr/mixer.c
@@ -284,7 +284,7 @@ static HRESULT WINAPI video_mixer_transform_GetStreamLimits(IMFTransform *iface,
TRACE("%p, %p, %p, %p, %p.\n", iface, input_minimum, input_maximum, output_minimum, output_maximum);
*input_minimum = 1;
- *input_maximum = 16;
+ *input_maximum = MAX_MIXER_INPUT_STREAMS;
*output_minimum = 1;
*output_maximum = 1;
--
2.28.0
1
4