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
October 2021
- 81 participants
- 772 discussions
28 Oct '21
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/msdasql/session.c | 58 +++++++++++++++++++++++++++++++++++
dlls/msdasql/tests/provider.c | 5 +++
2 files changed, 63 insertions(+)
diff --git a/dlls/msdasql/session.c b/dlls/msdasql/session.c
index 465a89d199a..d4d55f76c3c 100644
--- a/dlls/msdasql/session.c
+++ b/dlls/msdasql/session.c
@@ -39,6 +39,7 @@ struct msdasql_session
IUnknown session_iface;
IGetDataSource IGetDataSource_iface;
IOpenRowset IOpenRowset_iface;
+ ISessionProperties ISessionProperties_iface;
LONG refs;
};
@@ -57,6 +58,11 @@ static inline struct msdasql_session *impl_from_IOpenRowset( IOpenRowset *iface
return CONTAINING_RECORD( iface, struct msdasql_session, IOpenRowset_iface );
}
+static inline struct msdasql_session *impl_from_ISessionProperties( ISessionProperties *iface )
+{
+ return CONTAINING_RECORD( iface, struct msdasql_session, ISessionProperties_iface );
+}
+
static HRESULT WINAPI session_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
{
struct msdasql_session *session = impl_from_IUnknown( iface );
@@ -79,6 +85,11 @@ static HRESULT WINAPI session_QueryInterface(IUnknown *iface, REFIID riid, void
TRACE("(%p)->(IID_IOpenRowset %p)\n", iface, ppv);
*ppv = &session->IOpenRowset_iface;
}
+ else if(IsEqualGUID(&IID_ISessionProperties, riid))
+ {
+ TRACE("(%p)->(IID_ISessionProperties %p)\n", iface, ppv);
+ *ppv = &session->ISessionProperties_iface;
+ }
if(*ppv)
{
@@ -189,6 +200,52 @@ static const IOpenRowsetVtbl openrowsetVtbl =
openrowset_OpenRowset
};
+static HRESULT WINAPI properties_QueryInterface(ISessionProperties *iface, REFIID riid, void **out)
+{
+ struct msdasql_session *session = impl_from_ISessionProperties( iface );
+ return IUnknown_QueryInterface(&session->session_iface, riid, out);
+}
+
+static ULONG WINAPI properties_AddRef(ISessionProperties *iface)
+{
+ struct msdasql_session *session = impl_from_ISessionProperties( iface );
+ return IUnknown_AddRef(&session->session_iface);
+}
+
+static ULONG WINAPI properties_Release(ISessionProperties *iface)
+{
+ struct msdasql_session *session = impl_from_ISessionProperties( iface );
+ return IUnknown_Release(&session->session_iface);
+}
+
+
+static HRESULT WINAPI properties_GetProperties(ISessionProperties *iface, ULONG set_count,
+ const DBPROPIDSET id_sets[], ULONG *count, DBPROPSET **sets)
+{
+ struct msdasql_session *session = impl_from_ISessionProperties( iface );
+ FIXME("%p %d %p %p %p\n", session, set_count, id_sets, count, sets);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI properties_SetProperties(ISessionProperties *iface, ULONG count,
+ DBPROPSET sets[])
+{
+ struct msdasql_session *session = impl_from_ISessionProperties( iface );
+ FIXME("%p %d %p\n", session, count, sets);
+
+ return S_OK;
+}
+
+static const ISessionPropertiesVtbl propertiesVtbl =
+{
+ properties_QueryInterface,
+ properties_AddRef,
+ properties_Release,
+ properties_GetProperties,
+ properties_SetProperties
+};
+
HRESULT create_db_session(REFIID riid, void **unk)
{
struct msdasql_session *session;
@@ -201,6 +258,7 @@ HRESULT create_db_session(REFIID riid, void **unk)
session->session_iface.lpVtbl = &unkfactoryVtbl;
session->IGetDataSource_iface.lpVtbl = &datasourceVtbl;
session->IOpenRowset_iface.lpVtbl = &openrowsetVtbl;
+ session->ISessionProperties_iface.lpVtbl = &propertiesVtbl;
session->refs = 1;
hr = IUnknown_QueryInterface(&session->session_iface, riid, unk);
diff --git a/dlls/msdasql/tests/provider.c b/dlls/msdasql/tests/provider.c
index 4eaf6c07355..0d9630070b3 100644
--- a/dlls/msdasql/tests/provider.c
+++ b/dlls/msdasql/tests/provider.c
@@ -160,6 +160,7 @@ static void test_sessions(void)
IOpenRowset *openrowset = NULL;
IDBCreateCommand *create_command = NULL;
IGetDataSource *datasource = NULL;
+ ISessionProperties *session_props = NULL;
IUnknown *cmd = NULL;
HRESULT hr;
BSTR connect_str;
@@ -208,6 +209,10 @@ static void test_sessions(void)
ok(hr == S_OK, "got 0x%08x\n", hr);
IGetDataSource_Release(datasource);
+ hr = IUnknown_QueryInterface(session, &IID_ISessionProperties, (void**)&session_props);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ISessionProperties_Release(session_props);
+
hr = IUnknown_QueryInterface(session, &IID_IOpenRowset, (void**)&openrowset);
ok(hr == S_OK, "got 0x%08x\n", hr);
--
2.33.0
1
0
28 Oct '21
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/msdasql/session.c | 48 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
diff --git a/dlls/msdasql/session.c b/dlls/msdasql/session.c
index b79a80389ff..465a89d199a 100644
--- a/dlls/msdasql/session.c
+++ b/dlls/msdasql/session.c
@@ -38,6 +38,7 @@ struct msdasql_session
{
IUnknown session_iface;
IGetDataSource IGetDataSource_iface;
+ IOpenRowset IOpenRowset_iface;
LONG refs;
};
@@ -51,6 +52,11 @@ static inline struct msdasql_session *impl_from_IGetDataSource( IGetDataSource *
return CONTAINING_RECORD( iface, struct msdasql_session, IGetDataSource_iface );
}
+static inline struct msdasql_session *impl_from_IOpenRowset( IOpenRowset *iface )
+{
+ return CONTAINING_RECORD( iface, struct msdasql_session, IOpenRowset_iface );
+}
+
static HRESULT WINAPI session_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
{
struct msdasql_session *session = impl_from_IUnknown( iface );
@@ -68,6 +74,11 @@ static HRESULT WINAPI session_QueryInterface(IUnknown *iface, REFIID riid, void
TRACE("(%p)->(IID_IGetDataSource %p)\n", iface, ppv);
*ppv = &session->IGetDataSource_iface;
}
+ else if(IsEqualGUID(&IID_IOpenRowset, riid))
+ {
+ TRACE("(%p)->(IID_IOpenRowset %p)\n", iface, ppv);
+ *ppv = &session->IOpenRowset_iface;
+ }
if(*ppv)
{
@@ -142,6 +153,42 @@ static const IGetDataSourceVtbl datasourceVtbl =
datasource_GetDataSource
};
+HRESULT WINAPI openrowset_QueryInterface(IOpenRowset *iface, REFIID riid, void **out)
+{
+ struct msdasql_session *session = impl_from_IOpenRowset( iface );
+ return IUnknown_QueryInterface(&session->session_iface, riid, out);
+}
+
+ULONG WINAPI openrowset_AddRef(IOpenRowset *iface)
+{
+ struct msdasql_session *session = impl_from_IOpenRowset( iface );
+ return IUnknown_AddRef(&session->session_iface);
+}
+
+ULONG WINAPI openrowset_Release(IOpenRowset *iface)
+{
+ struct msdasql_session *session = impl_from_IOpenRowset( iface );
+ return IUnknown_Release(&session->session_iface);
+}
+
+HRESULT WINAPI openrowset_OpenRowset(IOpenRowset *iface, IUnknown *pUnkOuter, DBID *table,
+ DBID *index, REFIID riid, ULONG count, DBPROPSET propertysets[], IUnknown **rowset)
+{
+ struct msdasql_session *session = impl_from_IOpenRowset( iface );
+ FIXME("%p, %p, %p %p %s, %d %p %p stub\n", session, pUnkOuter, table, index, debugstr_guid(riid),
+ count, propertysets, rowset);
+
+ return E_NOTIMPL;
+}
+
+static const IOpenRowsetVtbl openrowsetVtbl =
+{
+ openrowset_QueryInterface,
+ openrowset_AddRef,
+ openrowset_Release,
+ openrowset_OpenRowset
+};
+
HRESULT create_db_session(REFIID riid, void **unk)
{
struct msdasql_session *session;
@@ -153,6 +200,7 @@ HRESULT create_db_session(REFIID riid, void **unk)
session->session_iface.lpVtbl = &unkfactoryVtbl;
session->IGetDataSource_iface.lpVtbl = &datasourceVtbl;
+ session->IOpenRowset_iface.lpVtbl = &openrowsetVtbl;
session->refs = 1;
hr = IUnknown_QueryInterface(&session->session_iface, riid, unk);
--
2.33.0
1
0
28 Oct '21
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/msdasql/session.c | 47 +++++++++++++++++++++++++++++++++++
dlls/msdasql/tests/provider.c | 5 ++++
2 files changed, 52 insertions(+)
diff --git a/dlls/msdasql/session.c b/dlls/msdasql/session.c
index 57174be40f8..b79a80389ff 100644
--- a/dlls/msdasql/session.c
+++ b/dlls/msdasql/session.c
@@ -37,6 +37,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msdasql);
struct msdasql_session
{
IUnknown session_iface;
+ IGetDataSource IGetDataSource_iface;
LONG refs;
};
@@ -45,6 +46,11 @@ static inline struct msdasql_session *impl_from_IUnknown( IUnknown *iface )
return CONTAINING_RECORD( iface, struct msdasql_session, session_iface );
}
+static inline struct msdasql_session *impl_from_IGetDataSource( IGetDataSource *iface )
+{
+ return CONTAINING_RECORD( iface, struct msdasql_session, IGetDataSource_iface );
+}
+
static HRESULT WINAPI session_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
{
struct msdasql_session *session = impl_from_IUnknown( iface );
@@ -57,6 +63,11 @@ static HRESULT WINAPI session_QueryInterface(IUnknown *iface, REFIID riid, void
TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
*ppv = &session->session_iface;
}
+ else if(IsEqualGUID(&IID_IGetDataSource, riid))
+ {
+ TRACE("(%p)->(IID_IGetDataSource %p)\n", iface, ppv);
+ *ppv = &session->IGetDataSource_iface;
+ }
if(*ppv)
{
@@ -96,6 +107,41 @@ static const IUnknownVtbl unkfactoryVtbl =
session_Release,
};
+
+HRESULT WINAPI datasource_QueryInterface(IGetDataSource *iface, REFIID riid, void **out)
+{
+ struct msdasql_session *session = impl_from_IGetDataSource( iface );
+ return IUnknown_QueryInterface(&session->session_iface, riid, out);
+}
+
+ULONG WINAPI datasource_AddRef(IGetDataSource *iface)
+{
+ struct msdasql_session *session = impl_from_IGetDataSource( iface );
+ return IUnknown_AddRef(&session->session_iface);
+}
+
+ULONG WINAPI datasource_Release(IGetDataSource *iface)
+{
+ struct msdasql_session *session = impl_from_IGetDataSource( iface );
+ return IUnknown_Release(&session->session_iface);
+}
+
+HRESULT WINAPI datasource_GetDataSource(IGetDataSource *iface, REFIID riid, IUnknown **datasource)
+{
+ struct msdasql_session *session = impl_from_IGetDataSource( iface );
+ FIXME("%p, %s, %p stub\n", session, debugstr_guid(riid), datasource);
+
+ return E_NOTIMPL;
+}
+
+static const IGetDataSourceVtbl datasourceVtbl =
+{
+ datasource_QueryInterface,
+ datasource_AddRef,
+ datasource_Release,
+ datasource_GetDataSource
+};
+
HRESULT create_db_session(REFIID riid, void **unk)
{
struct msdasql_session *session;
@@ -106,6 +152,7 @@ HRESULT create_db_session(REFIID riid, void **unk)
return E_OUTOFMEMORY;
session->session_iface.lpVtbl = &unkfactoryVtbl;
+ session->IGetDataSource_iface.lpVtbl = &datasourceVtbl;
session->refs = 1;
hr = IUnknown_QueryInterface(&session->session_iface, riid, unk);
diff --git a/dlls/msdasql/tests/provider.c b/dlls/msdasql/tests/provider.c
index 4cab6a24daf..4eaf6c07355 100644
--- a/dlls/msdasql/tests/provider.c
+++ b/dlls/msdasql/tests/provider.c
@@ -159,6 +159,7 @@ static void test_sessions(void)
IUnknown *session = NULL;
IOpenRowset *openrowset = NULL;
IDBCreateCommand *create_command = NULL;
+ IGetDataSource *datasource = NULL;
IUnknown *cmd = NULL;
HRESULT hr;
BSTR connect_str;
@@ -203,6 +204,10 @@ static void test_sessions(void)
hr = IDBCreateSession_CreateSession( dbsession, NULL, &IID_IUnknown, &session );
ok(hr == S_OK, "got 0x%08x\n", hr);
+ hr = IUnknown_QueryInterface(session, &IID_IGetDataSource, (void**)&datasource);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ IGetDataSource_Release(datasource);
+
hr = IUnknown_QueryInterface(session, &IID_IOpenRowset, (void**)&openrowset);
ok(hr == S_OK, "got 0x%08x\n", hr);
--
2.33.0
1
0
27 Oct '21
1
0
[PATCH 1/3] uiautomationcore: Implement UiaGetReservedNotSupportedValue.
by Connor McAdams 27 Oct '21
by Connor McAdams 27 Oct '21
27 Oct '21
Signed-off-by: Connor McAdams <cmcadams(a)codeweavers.com>
---
dlls/uiautomationcore/Makefile.in | 1 +
dlls/uiautomationcore/uia_main.c | 196 +++++++++++++++++++++++++++++-
2 files changed, 195 insertions(+), 2 deletions(-)
diff --git a/dlls/uiautomationcore/Makefile.in b/dlls/uiautomationcore/Makefile.in
index 71ea7b99c94..5a72ea144c4 100644
--- a/dlls/uiautomationcore/Makefile.in
+++ b/dlls/uiautomationcore/Makefile.in
@@ -1,5 +1,6 @@
MODULE = uiautomationcore.dll
IMPORTLIB = uiautomationcore
+IMPORTS = uuid ole32
EXTRADLLFLAGS = -Wb,--prefer-native
diff --git a/dlls/uiautomationcore/uia_main.c b/dlls/uiautomationcore/uia_main.c
index 2dada95af80..e51a4b4d555 100644
--- a/dlls/uiautomationcore/uia_main.c
+++ b/dlls/uiautomationcore/uia_main.c
@@ -16,12 +16,199 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#define COBJMACROS
+
#include "uiautomation.h"
#include "wine/debug.h"
+#include "wine/heap.h"
WINE_DEFAULT_DEBUG_CHANNEL(uiautomation);
+struct uia_rsrv_ftmarshaler
+{
+ IMarshal IMarshal_iface;
+
+ IUnknown *inner_unk;
+ IMarshal *marshal;
+};
+
+/*
+ * Create a custom proxy IMarshal, so that IMarshal::Release actually releases
+ * the interface.
+ */
+static struct uia_rsrv_ftmarshaler *impl_uia_rsrv_ft_from_IMarshal(IMarshal *iface)
+{
+ return CONTAINING_RECORD(iface, struct uia_rsrv_ftmarshaler, IMarshal_iface);
+}
+
+static HRESULT WINAPI uia_rsrv_ftmarshaler_QueryInterface(IMarshal *iface, REFIID riid, void **obj)
+{
+ struct uia_rsrv_ftmarshaler *marshaler = impl_uia_rsrv_ft_from_IMarshal(iface);
+
+ TRACE("%p, %s, %p\n", iface, debugstr_guid(riid), obj);
+
+ return IMarshal_QueryInterface(marshaler->marshal, riid, obj);
+}
+
+static ULONG WINAPI uia_rsrv_ftmarshaler_AddRef(IMarshal *iface)
+{
+ struct uia_rsrv_ftmarshaler *marshaler = impl_uia_rsrv_ft_from_IMarshal(iface);
+ ULONG ref = IUnknown_AddRef(marshaler->inner_unk);
+
+ TRACE("%p, ref %d\n", iface, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI uia_rsrv_ftmarshaler_Release(IMarshal *iface)
+{
+ struct uia_rsrv_ftmarshaler *marshaler = impl_uia_rsrv_ft_from_IMarshal(iface);
+ ULONG ref = IUnknown_Release(marshaler->inner_unk);
+
+ TRACE("%p, ref %d\n", iface, ref);
+
+ if (!ref)
+ heap_free(marshaler);
+
+ return ref;
+}
+
+static HRESULT WINAPI uia_rsrv_ftmarshaler_GetUnmarshalClass(IMarshal *iface, REFIID riid, void *pv,
+ DWORD dest_context, void *pvDestContext, DWORD mshlflags, CLSID *clsid)
+{
+ struct uia_rsrv_ftmarshaler *marshaler = impl_uia_rsrv_ft_from_IMarshal(iface);
+ TRACE("%s, %p, %#x, %p, %#x, %p\n", debugstr_guid(riid), pv, dest_context, pvDestContext, mshlflags, clsid);
+ return IMarshal_GetUnmarshalClass(marshaler->marshal, riid, pv, dest_context, pvDestContext, mshlflags, clsid);
+}
+
+static HRESULT WINAPI uia_rsrv_ftmarshaler_GetMarshalSizeMax(IMarshal *iface, REFIID riid, void *pv,
+ DWORD dest_context, void *pvDestContext, DWORD mshlflags, DWORD *size)
+{
+ struct uia_rsrv_ftmarshaler *marshaler = impl_uia_rsrv_ft_from_IMarshal(iface);
+ TRACE("%s, %p, %#x, %p, %#x, %p\n", debugstr_guid(riid), pv, dest_context, pvDestContext, mshlflags, size);
+ return IMarshal_GetMarshalSizeMax(marshaler->marshal, riid, pv, dest_context, pvDestContext, mshlflags, size);
+}
+
+static HRESULT WINAPI uia_rsrv_ftmarshaler_MarshalInterface(IMarshal *iface, IStream *stream, REFIID riid,
+ void *pv, DWORD dest_context, void *pvDestContext, DWORD mshlflags)
+{
+ struct uia_rsrv_ftmarshaler *marshaler = impl_uia_rsrv_ft_from_IMarshal(iface);
+ TRACE("%p, %s, %p, %#x, %p, %#x\n", stream, debugstr_guid(riid), pv, dest_context, pvDestContext, mshlflags);
+ return IMarshal_MarshalInterface(marshaler->marshal, stream, riid, pv, dest_context, pvDestContext, mshlflags);
+}
+
+static HRESULT WINAPI uia_rsrv_ftmarshaler_UnmarshalInterface(IMarshal *iface, IStream *stream, REFIID riid, void **ppv)
+{
+ struct uia_rsrv_ftmarshaler *marshaler = impl_uia_rsrv_ft_from_IMarshal(iface);
+ TRACE("%p, %s, %p\n", stream, debugstr_guid(riid), ppv);
+ return IMarshal_UnmarshalInterface(marshaler->marshal, stream, riid, ppv);
+}
+
+static HRESULT WINAPI uia_rsrv_ftmarshaler_ReleaseMarshalData(IMarshal *iface, IStream *stream)
+{
+ struct uia_rsrv_ftmarshaler *marshaler = impl_uia_rsrv_ft_from_IMarshal(iface);
+ TRACE("%p\n", stream);
+ return IMarshal_ReleaseMarshalData(marshaler->marshal, stream);
+}
+
+static HRESULT WINAPI uia_rsrv_ftmarshaler_DisconnectObject(IMarshal *iface, DWORD reserved)
+{
+ struct uia_rsrv_ftmarshaler *marshaler = impl_uia_rsrv_ft_from_IMarshal(iface);
+ TRACE("\n");
+ return IMarshal_DisconnectObject(marshaler->marshal, reserved);
+}
+
+static const IMarshalVtbl uia_rsrv_ftmarshaler_vtbl =
+{
+ uia_rsrv_ftmarshaler_QueryInterface,
+ uia_rsrv_ftmarshaler_AddRef,
+ uia_rsrv_ftmarshaler_Release,
+ uia_rsrv_ftmarshaler_GetUnmarshalClass,
+ uia_rsrv_ftmarshaler_GetMarshalSizeMax,
+ uia_rsrv_ftmarshaler_MarshalInterface,
+ uia_rsrv_ftmarshaler_UnmarshalInterface,
+ uia_rsrv_ftmarshaler_ReleaseMarshalData,
+ uia_rsrv_ftmarshaler_DisconnectObject
+};
+
+/*
+ * When passing the ReservedNotSupportedValue/ReservedMixedAttributeValue
+ * interface pointers across apartments within the same process, use the
+ * free threaded marshaler to preserve the pointer value. Wrap the IMarshal
+ * interface received by CoCreateFreeThreadedMarshaler so that we can maintain
+ * our own reference count and release the object when it hits 0.
+ */
+static HRESULT uia_reserved_val_create_ftm(IUnknown *outer, IMarshal **marshaler)
+{
+ struct uia_rsrv_ftmarshaler *object;
+ IUnknown *ftm_unk;
+ HRESULT hr;
+
+ TRACE("%p, %p\n", outer, marshaler);
+
+ hr = CoCreateFreeThreadedMarshaler(outer, &ftm_unk);
+ if (FAILED(hr)) return hr;
+
+ object = heap_alloc(sizeof(*object));
+ if (!object)
+ {
+ IUnknown_Release(ftm_unk);
+ return E_OUTOFMEMORY;
+ }
+
+ object->IMarshal_iface.lpVtbl = &uia_rsrv_ftmarshaler_vtbl;
+ object->inner_unk = ftm_unk;
+ hr = IUnknown_QueryInterface(ftm_unk, &IID_IMarshal, (void **)&object->marshal);
+ if (FAILED(hr))
+ FIXME("Failed to QI for IMarshal.\n");
+
+ *marshaler = &object->IMarshal_iface;
+
+ return S_OK;
+}
+
+/*
+ * UiaReservedNotSupported object.
+ */
+static HRESULT WINAPI uia_reserved_ns_QueryInterface(IUnknown *iface,
+ REFIID riid, void **ppv)
+{
+ *ppv = NULL;
+ if (IsEqualIID(riid, &IID_IUnknown))
+ *ppv = iface;
+ else if (IsEqualIID(riid, &IID_IMarshal))
+ {
+ IMarshal *ftm;
+
+ if (FAILED(uia_reserved_val_create_ftm(iface, &ftm)))
+ return E_NOINTERFACE;
+ *ppv = ftm;
+ }
+ else
+ return E_NOINTERFACE;
+
+ return S_OK;
+}
+
+static ULONG WINAPI uia_reserved_ns_AddRef(IUnknown *iface)
+{
+ return 1;
+}
+
+static ULONG WINAPI uia_reserved_ns_Release(IUnknown *iface)
+{
+ return 1;
+}
+
+static const IUnknownVtbl uia_reserved_ns_vtbl = {
+ uia_reserved_ns_QueryInterface,
+ uia_reserved_ns_AddRef,
+ uia_reserved_ns_Release,
+};
+
+static IUnknown uia_reserved_ns_iface = {&uia_reserved_ns_vtbl};
+
/***********************************************************************
* UiaClientsAreListening (uiautomationcore.@)
*/
@@ -46,8 +233,13 @@ HRESULT WINAPI UiaGetReservedMixedAttributeValue(IUnknown **value)
*/
HRESULT WINAPI UiaGetReservedNotSupportedValue(IUnknown **value)
{
- FIXME("(%p) stub!\n", value);
- *value = NULL;
+ TRACE("(%p)\n", value);
+
+ if (!value)
+ return E_INVALIDARG;
+
+ *value = &uia_reserved_ns_iface;
+
return S_OK;
}
--
2.25.1
2
7
[PATCH v2] include: Add async_uuid for IBackgroundCopyCallback in bits.idl
by Biswapriyo Nath 27 Oct '21
by Biswapriyo Nath 27 Oct '21
27 Oct '21
3
2
Always build the Mac preloader with '-mmacosx-version-min=10.7', which
works with all supported toolchains.
Fixes bug when building with Xcode 9 where preloader flags would be added
to EXTRACFLAGS and cause build failures on 32-bit.
Signed-off-by: Brendan Shanks <bshanks(a)codeweavers.com>
---
configure.ac | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/configure.ac b/configure.ac
index b8356679e63..ef0d09e974d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -739,14 +739,12 @@ case $host_os in
WINEPRELOADER_LDFLAGS="-nostartfiles -nodefaultlibs -e _start -ldylib1.o -Wl,-image_base,0x7d400000,-segalign,0x1000,-pagezero_size,0x1000,-sectcreate,__TEXT,__info_plist,loader/wine_info.plist,-segaddr,WINE_4GB_RESERVE,0x100000000"
WINE_TRY_CFLAGS([-Wl,-no_new_main -e _main],
[WINEPRELOADER_LDFLAGS="-Wl,-no_new_main $WINEPRELOADER_LDFLAGS"
- WINE_TRY_CFLAGS([-Wl,-no_new_main -e _main -nostartfiles -nodefaultlibs],,
- [WINE_TRY_CFLAGS([-Wl,-no_new_main -e _main -mmacosx-version-min=10.7 -nostartfiles -nodefaultlibs],
- [WINEPRELOADER_LDFLAGS="-mmacosx-version-min=10.7 $WINEPRELOADER_LDFLAGS"],
- [wine_can_build_preloader=no])])],
- [WINE_TRY_CFLAGS([-nostartfiles -nodefaultlibs],,
- [WINE_TRY_CFLAGS([-mmacosx-version-min=10.7 -nostartfiles -nodefaultlibs],
- [WINEPRELOADER_LDFLAGS="-mmacosx-version-min=10.7 $WINEPRELOADER_LDFLAGS"],
- [wine_can_build_preloader=no])])])
+ WINE_TRY_CFLAGS([-Wl,-no_new_main -e _main -mmacosx-version-min=10.7 -nostartfiles -nodefaultlibs],
+ [WINEPRELOADER_LDFLAGS="-mmacosx-version-min=10.7 $WINEPRELOADER_LDFLAGS"],
+ [wine_can_build_preloader=no])],
+ [WINE_TRY_CFLAGS([-mmacosx-version-min=10.7 -nostartfiles -nodefaultlibs],
+ [WINEPRELOADER_LDFLAGS="-mmacosx-version-min=10.7 $WINEPRELOADER_LDFLAGS"],
+ [wine_can_build_preloader=no])])
if test "$wine_can_build_preloader" = "yes"
then
WINE_TRY_CFLAGS([-Wl,-no_pie],
--
2.30.1 (Apple Git-130)
1
0
Hello Brent,
Seems to work fine for me using your Makefile after fixing a few casing
issues, undefined functions and creating the Debug folder.
Are you working on a Linux filesystem where you have enough permissions? There
seems to be something very weird with your setup.
Your not running under WSL or have some other uncommon setup, right?
Regards,
Fabian Maurer
2
1
I'm not sure if this mailing list is the correct place to ask for porting help, as it seems to be solely dedicated to improving WINE, but the forums on the web site seem mostly for using WINE to run programs directly, not using it for porting. If there is a better place for this query, please let me know.
So... the wine wrapper seems to run our application GUI just fine, however we need to marry the Win32 GUI code to system-level accesses so that we can port the application to Linux. I was having some luck using version 5.0, but had to do some weird linking shenanigans and using pipes to channel data from the linux side to the windows side and vice versa... it was too cumbersome and slow for our purposes, so we walked away. Hearing of version 6, we thought this new architecture might solve our problems so threw together an exploratory project simply to show that it could work. Unfortunately, I've been having some issues and having a hard time determining where they are.
If I leave out the resources and compile with the -v option, this is the build/linking step (the .onlx is a gcc direct-compiled .o file... I've also tried it as an actual .o file in case that is confusing winebuild... same result.)
winegcc -o Debug/winetest.exe -v -mwindows Debug/WINETEST.o Debug/SERVICE.o Debug/USERCODE.o Debug/CLIENT.o Debug/linux.olnx
/opt/wine-devel/bin/winebuild -v -fno-asynchronous-unwind-tables "--cc-cmd=/usr/bin/gcc -m64" --ld-cmd=/usr/bin/ld -fPIC --exe -o winetest.exe-61799713.spec.o -F winetest.exe --subsystem windows -L/opt/wine-devel/bin/../lib64/wine/x86_64-unix -L/opt/wine-devel/bin/../lib64 -- Debug/WINETEST.o Debug/SERVICE.o Debug/USERCODE.o Debug/CLIENT.o /opt/wine-devel/bin/../lib64/wine/x86_64-unix/libshell32.def /opt/wine-devel/bin/../lib64/wine/x86_64-unix/libcomdlg32.def /opt/wine-devel/bin/../lib64/wine/x86_64-unix/libgdi32.def /opt/wine-devel/bin/../lib64/wine/x86_64-unix/libadvapi32.def /opt/wine-devel/bin/../lib64/wine/x86_64-unix/libuser32.def /opt/wine-devel/bin/../lib64/wine/x86_64-unix/libwinecrt0.a /opt/wine-devel/bin/../lib64/wine/x86_64-unix/libkernel32.def /opt/wine-devel/bin/../lib64/wine/x86_64-unix/libntdll.def
winebuild: Unable to create output file 'winetest.exe-61799713.spec-61799714.s'
winegcc: /opt/wine-devel/bin/winebuild failed
make: *** [Makefile:90: all] Error 2
So, one of these subprocesses is trying to create a .s file on the way to creating the .o file, and having issues? I note a few problems that seem to exist... one, the folder for the EXE doesn't seem to be getting passed to winebuild (-F winetest.exe instead of -F Debug/winetest.exe) and the -o winetest.exe-61799713.spec.o is similarly not specifying a folder. However adding a Debug in front of them manually doesn't do anything so I don't think that's the basic problem.
/opt/wine-devel/bin/winebuild -v -fno-asynchronous-unwind-tables "--cc-cmd=/usr/bin/gcc -m64" --ld-cmd=/usr/bin/ld -fPIC --exe -o Debug/winetest.exe-61799713.spec.o -F Debug/winetest.exe --subsystem windows -L/opt/wine-devel/bin/../lib64/wine/x86_64-unix -L/opt/wine-devel/bin/../lib64 -- Debug/WINETEST.o Debug/SERVICE.o Debug/USERCODE.o Debug/CLIENT.o /opt/wine-devel/bin/../lib64/wine/x86_64-unix/libshell32.def /opt/wine-devel/bin/../lib64/wine/x86_64-unix/libcomdlg32.def /opt/wine-devel/bin/../lib64/wine/x86_64-unix/libgdi32.def /opt/wine-devel/bin/../lib64/wine/x86_64-unix/libadvapi32.def /opt/wine-devel/bin/../lib64/wine/x86_64-unix/libuser32.def /opt/wine-devel/bin/../lib64/wine/x86_64-unix/libwinecrt0.a /opt/wine-devel/bin/../lib64/wine/x86_64-unix/libkernel32.def /opt/wine-devel/bin/../lib64/wine/x86_64-unix/libntdll.def
winebuild: Unable to create output file 'winetest.exe-61799713.spec-61799cc7.s'
Any ideas on what I'm doing wrong? Bad environmental variables or other flags that need to be added? Attached is a copy of my makefile, designed so that I can pull from multiple source folders, keep track of Win32 vs linux source files, etc. It has various dummy targets to more easily experiment with different things or dump variable lists. Attaching the var_o and tar_c outputs as well, just to demonstrate the input values
I also experimented with trying to do things with gcc and ld, but didn't come across any breakthroughs.
In a similar vein, and probably related, I can't get WRC to work either. If I comment in RCflags to get debug level 31, I get the output in rc_debug31.txt in the same folder as my Makefile (ie. Writable folder)
The error output normally seems pretty non-sensical as the .res file should be an output?
wrc -foDebug/WINETEST.res WINETEST.RC
Error: Could not open Debug/WINETEST.res-61799fb9 for input : Permission denied
make: *** [Makefile:144: Debug/WINETEST.res] Error 2
This is a much simpler test program than our actual program to port, and I can't even seem to get this one to compile... it's frustrating. I'd love to be able to use WINE to support Linux servers, etc, but I'm stuck.
Any pointers people could offer would be greatly appreciated.
Thank you,
Brent
3
3
27 Oct '21
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/ntdll/tests/Makefile.in | 1 +
dlls/ntdll/tests/om.c | 574 -------------------------------
dlls/ntdll/tests/sync.c | 631 +++++++++++++++++++++++++++++++++++
3 files changed, 632 insertions(+), 574 deletions(-)
create mode 100644 dlls/ntdll/tests/sync.c
diff --git a/dlls/ntdll/tests/Makefile.in b/dlls/ntdll/tests/Makefile.in
index 7ad39e0992c..8c6a86fb965 100644
--- a/dlls/ntdll/tests/Makefile.in
+++ b/dlls/ntdll/tests/Makefile.in
@@ -21,6 +21,7 @@ C_SRCS = \
rtlbitmap.c \
rtlstr.c \
string.c \
+ sync.c \
threadpool.c \
time.c \
virtual.c \
diff --git a/dlls/ntdll/tests/om.c b/dlls/ntdll/tests/om.c
index af5e014f069..77eb58a23b5 100644
--- a/dlls/ntdll/tests/om.c
+++ b/dlls/ntdll/tests/om.c
@@ -30,10 +30,6 @@
static VOID (WINAPI *pRtlInitUnicodeString)( PUNICODE_STRING, LPCWSTR );
static NTSTATUS (WINAPI *pNtCreateEvent) ( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES, EVENT_TYPE, BOOLEAN);
static NTSTATUS (WINAPI *pNtOpenEvent) ( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES);
-static NTSTATUS (WINAPI *pNtPulseEvent) ( HANDLE, PLONG );
-static NTSTATUS (WINAPI *pNtQueryEvent) ( HANDLE, EVENT_INFORMATION_CLASS, PVOID, ULONG, PULONG );
-static NTSTATUS (WINAPI *pNtResetEvent) ( HANDLE, LONG* );
-static NTSTATUS (WINAPI *pNtSetEvent) ( HANDLE, LONG* );
static NTSTATUS (WINAPI *pNtCreateJobObject)( PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES );
static NTSTATUS (WINAPI *pNtOpenJobObject)( PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES );
static NTSTATUS (WINAPI *pNtCreateKey)( PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, ULONG,
@@ -44,11 +40,8 @@ static NTSTATUS (WINAPI *pNtCreateMailslotFile)( PHANDLE, ACCESS_MASK, POBJECT_A
ULONG, ULONG, ULONG, PLARGE_INTEGER );
static NTSTATUS (WINAPI *pNtCreateMutant)( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES, BOOLEAN );
static NTSTATUS (WINAPI *pNtOpenMutant) ( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES );
-static NTSTATUS (WINAPI *pNtQueryMutant) ( HANDLE, MUTANT_INFORMATION_CLASS, PVOID, ULONG, PULONG );
-static NTSTATUS (WINAPI *pNtReleaseMutant)( HANDLE, PLONG );
static NTSTATUS (WINAPI *pNtCreateSemaphore)( PHANDLE, ACCESS_MASK,const POBJECT_ATTRIBUTES,LONG,LONG );
static NTSTATUS (WINAPI *pNtOpenSemaphore)( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES );
-static NTSTATUS (WINAPI *pNtQuerySemaphore)( PHANDLE, SEMAPHORE_INFORMATION_CLASS, PVOID, ULONG, PULONG );
static NTSTATUS (WINAPI *pNtCreateTimer) ( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES, TIMER_TYPE );
static NTSTATUS (WINAPI *pNtOpenTimer)( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES );
static NTSTATUS (WINAPI *pNtCreateSection)( PHANDLE, ACCESS_MASK, const POBJECT_ATTRIBUTES, const PLARGE_INTEGER,
@@ -67,15 +60,9 @@ static NTSTATUS (WINAPI *pNtQueryObject)(HANDLE,OBJECT_INFORMATION_CLASS,PVOID,U
static NTSTATUS (WINAPI *pNtReleaseSemaphore)(HANDLE, ULONG, PULONG);
static NTSTATUS (WINAPI *pNtCreateKeyedEvent)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, ULONG );
static NTSTATUS (WINAPI *pNtOpenKeyedEvent)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES * );
-static NTSTATUS (WINAPI *pNtWaitForKeyedEvent)( HANDLE, const void *, BOOLEAN, const LARGE_INTEGER * );
-static NTSTATUS (WINAPI *pNtReleaseKeyedEvent)( HANDLE, const void *, BOOLEAN, const LARGE_INTEGER * );
static NTSTATUS (WINAPI *pNtCreateIoCompletion)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, ULONG);
static NTSTATUS (WINAPI *pNtOpenIoCompletion)( PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES );
static NTSTATUS (WINAPI *pNtQueryInformationFile)(HANDLE, PIO_STATUS_BLOCK, void *, ULONG, FILE_INFORMATION_CLASS);
-static NTSTATUS (WINAPI *pNtQuerySystemTime)( LARGE_INTEGER * );
-static NTSTATUS (WINAPI *pRtlWaitOnAddress)( const void *, const void *, SIZE_T, const LARGE_INTEGER * );
-static void (WINAPI *pRtlWakeAddressAll)( const void * );
-static void (WINAPI *pRtlWakeAddressSingle)( const void * );
static NTSTATUS (WINAPI *pNtOpenProcess)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, const CLIENT_ID * );
static NTSTATUS (WINAPI *pNtCreateDebugObject)( HANDLE *, ACCESS_MASK, OBJECT_ATTRIBUTES *, ULONG );
static NTSTATUS (WINAPI *pNtGetNextThread)(HANDLE process, HANDLE thread, ACCESS_MASK access, ULONG attributes,
@@ -1939,286 +1926,6 @@ static void test_type_mismatch(void)
pNtClose( h );
}
-static void test_event(void)
-{
- HANDLE Event;
- HANDLE Event2;
- LONG prev_state = 0xdeadbeef;
- NTSTATUS status;
- UNICODE_STRING str;
- OBJECT_ATTRIBUTES attr;
- EVENT_BASIC_INFORMATION info;
-
- pRtlInitUnicodeString( &str, L"\\BaseNamedObjects\\testEvent" );
- InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
-
- status = pNtCreateEvent(&Event, GENERIC_ALL, &attr, 2, 0);
- ok( status == STATUS_INVALID_PARAMETER, "NtCreateEvent failed %08x\n", status );
-
- status = pNtCreateEvent(&Event, GENERIC_ALL, &attr, NotificationEvent, 0);
- ok( status == STATUS_SUCCESS, "NtCreateEvent failed %08x\n", status );
- memset(&info, 0xcc, sizeof(info));
- status = pNtQueryEvent(Event, EventBasicInformation, &info, sizeof(info), NULL);
- ok( status == STATUS_SUCCESS, "NtQueryEvent failed %08x\n", status );
- ok( info.EventType == NotificationEvent && info.EventState == 0,
- "NtQueryEvent failed, expected 0 0, got %d %d\n", info.EventType, info.EventState );
- pNtClose(Event);
-
- status = pNtCreateEvent(&Event, GENERIC_ALL, &attr, SynchronizationEvent, 0);
- ok( status == STATUS_SUCCESS, "NtCreateEvent failed %08x\n", status );
-
- status = pNtPulseEvent(Event, &prev_state);
- ok( status == STATUS_SUCCESS, "NtPulseEvent failed %08x\n", status );
- ok( !prev_state, "prev_state = %x\n", prev_state );
-
- memset(&info, 0xcc, sizeof(info));
- status = pNtQueryEvent(Event, EventBasicInformation, &info, sizeof(info), NULL);
- ok( status == STATUS_SUCCESS, "NtQueryEvent failed %08x\n", status );
- ok( info.EventType == SynchronizationEvent && info.EventState == 0,
- "NtQueryEvent failed, expected 1 0, got %d %d\n", info.EventType, info.EventState );
-
- status = pNtOpenEvent(&Event2, GENERIC_ALL, &attr);
- ok( status == STATUS_SUCCESS, "NtOpenEvent failed %08x\n", status );
-
- pNtClose(Event);
- Event = Event2;
-
- memset(&info, 0xcc, sizeof(info));
- status = pNtQueryEvent(Event, EventBasicInformation, &info, sizeof(info), NULL);
- ok( status == STATUS_SUCCESS, "NtQueryEvent failed %08x\n", status );
- ok( info.EventType == SynchronizationEvent && info.EventState == 0,
- "NtQueryEvent failed, expected 1 0, got %d %d\n", info.EventType, info.EventState );
-
- status = pNtSetEvent( Event, &prev_state );
- ok( status == STATUS_SUCCESS, "NtSetEvent failed: %08x\n", status );
- ok( !prev_state, "prev_state = %x\n", prev_state );
-
- memset(&info, 0xcc, sizeof(info));
- status = pNtQueryEvent(Event, EventBasicInformation, &info, sizeof(info), NULL);
- ok( status == STATUS_SUCCESS, "NtQueryEvent failed %08x\n", status );
- ok( info.EventType == SynchronizationEvent && info.EventState == 1,
- "NtQueryEvent failed, expected 1 1, got %d %d\n", info.EventType, info.EventState );
-
- status = pNtSetEvent( Event, &prev_state );
- ok( status == STATUS_SUCCESS, "NtSetEvent failed: %08x\n", status );
- ok( prev_state == 1, "prev_state = %x\n", prev_state );
-
- status = pNtResetEvent( Event, &prev_state );
- ok( status == STATUS_SUCCESS, "NtSetEvent failed: %08x\n", status );
- ok( prev_state == 1, "prev_state = %x\n", prev_state );
-
- status = pNtResetEvent( Event, &prev_state );
- ok( status == STATUS_SUCCESS, "NtSetEvent failed: %08x\n", status );
- ok( !prev_state, "prev_state = %x\n", prev_state );
-
- status = pNtPulseEvent( Event, &prev_state );
- ok( status == STATUS_SUCCESS, "NtPulseEvent failed %08x\n", status );
- ok( !prev_state, "prev_state = %x\n", prev_state );
-
- status = pNtSetEvent( Event, &prev_state );
- ok( status == STATUS_SUCCESS, "NtSetEvent failed: %08x\n", status );
- ok( !prev_state, "prev_state = %x\n", prev_state );
-
- status = pNtPulseEvent( Event, &prev_state );
- ok( status == STATUS_SUCCESS, "NtPulseEvent failed %08x\n", status );
- ok( prev_state == 1, "prev_state = %x\n", prev_state );
-
- pNtClose(Event);
-}
-
-static const WCHAR keyed_nameW[] = L"\\BaseNamedObjects\\WineTestEvent";
-
-static DWORD WINAPI keyed_event_thread( void *arg )
-{
- HANDLE handle;
- NTSTATUS status;
- LARGE_INTEGER timeout;
- OBJECT_ATTRIBUTES attr;
- UNICODE_STRING str;
- ULONG_PTR i;
-
- attr.Length = sizeof(attr);
- attr.RootDirectory = 0;
- attr.ObjectName = &str;
- attr.Attributes = 0;
- attr.SecurityDescriptor = NULL;
- attr.SecurityQualityOfService = NULL;
- RtlInitUnicodeString( &str, keyed_nameW );
-
- status = pNtOpenKeyedEvent( &handle, KEYEDEVENT_ALL_ACCESS, &attr );
- ok( !status, "NtOpenKeyedEvent failed %x\n", status );
-
- for (i = 0; i < 20; i++)
- {
- if (i & 1)
- status = pNtWaitForKeyedEvent( handle, (void *)(i * 2), 0, NULL );
- else
- status = pNtReleaseKeyedEvent( handle, (void *)(i * 2), 0, NULL );
- ok( status == STATUS_SUCCESS, "%li: failed %x\n", i, status );
- Sleep( 20 - i );
- }
-
- status = pNtReleaseKeyedEvent( handle, (void *)0x1234, 0, NULL );
- ok( status == STATUS_SUCCESS, "NtReleaseKeyedEvent %x\n", status );
-
- timeout.QuadPart = -10000;
- status = pNtWaitForKeyedEvent( handle, (void *)0x5678, 0, &timeout );
- ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
- status = pNtReleaseKeyedEvent( handle, (void *)0x9abc, 0, &timeout );
- ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
-
- NtClose( handle );
- return 0;
-}
-
-static void test_keyed_events(void)
-{
- OBJECT_ATTRIBUTES attr;
- UNICODE_STRING str;
- HANDLE handle, event, thread;
- NTSTATUS status;
- LARGE_INTEGER timeout;
- ULONG_PTR i;
-
- if (!pNtCreateKeyedEvent)
- {
- win_skip( "Keyed events not supported\n" );
- return;
- }
-
- attr.Length = sizeof(attr);
- attr.RootDirectory = 0;
- attr.ObjectName = &str;
- attr.Attributes = 0;
- attr.SecurityDescriptor = NULL;
- attr.SecurityQualityOfService = NULL;
- RtlInitUnicodeString( &str, keyed_nameW );
-
- status = pNtCreateKeyedEvent( &handle, KEYEDEVENT_ALL_ACCESS | SYNCHRONIZE, &attr, 0 );
- ok( !status, "NtCreateKeyedEvent failed %x\n", status );
-
- status = WaitForSingleObject( handle, 1000 );
- ok( status == 0, "WaitForSingleObject %x\n", status );
-
- timeout.QuadPart = -100000;
- status = pNtWaitForKeyedEvent( handle, (void *)255, 0, &timeout );
- ok( status == STATUS_INVALID_PARAMETER_1, "NtWaitForKeyedEvent %x\n", status );
- status = pNtReleaseKeyedEvent( handle, (void *)255, 0, &timeout );
- ok( status == STATUS_INVALID_PARAMETER_1, "NtReleaseKeyedEvent %x\n", status );
-
- status = pNtWaitForKeyedEvent( handle, (void *)254, 0, &timeout );
- ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
- status = pNtReleaseKeyedEvent( handle, (void *)254, 0, &timeout );
- ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
-
- status = pNtWaitForKeyedEvent( handle, NULL, 0, &timeout );
- ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
- status = pNtReleaseKeyedEvent( handle, NULL, 0, &timeout );
- ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
-
- status = pNtWaitForKeyedEvent( NULL, (void *)8, 0, &timeout );
- ok( status == STATUS_TIMEOUT || broken(status == STATUS_INVALID_HANDLE), /* XP/2003 */
- "NtWaitForKeyedEvent %x\n", status );
- status = pNtReleaseKeyedEvent( NULL, (void *)8, 0, &timeout );
- ok( status == STATUS_TIMEOUT || broken(status == STATUS_INVALID_HANDLE), /* XP/2003 */
- "NtReleaseKeyedEvent %x\n", status );
-
- status = pNtWaitForKeyedEvent( (HANDLE)0xdeadbeef, (void *)9, 0, &timeout );
- ok( status == STATUS_INVALID_PARAMETER_1, "NtWaitForKeyedEvent %x\n", status );
- status = pNtReleaseKeyedEvent( (HANDLE)0xdeadbeef, (void *)9, 0, &timeout );
- ok( status == STATUS_INVALID_PARAMETER_1, "NtReleaseKeyedEvent %x\n", status );
-
- status = pNtWaitForKeyedEvent( (HANDLE)0xdeadbeef, (void *)8, 0, &timeout );
- ok( status == STATUS_INVALID_HANDLE, "NtWaitForKeyedEvent %x\n", status );
- status = pNtReleaseKeyedEvent( (HANDLE)0xdeadbeef, (void *)8, 0, &timeout );
- ok( status == STATUS_INVALID_HANDLE, "NtReleaseKeyedEvent %x\n", status );
-
- thread = CreateThread( NULL, 0, keyed_event_thread, 0, 0, NULL );
- for (i = 0; i < 20; i++)
- {
- if (i & 1)
- status = pNtReleaseKeyedEvent( handle, (void *)(i * 2), 0, NULL );
- else
- status = pNtWaitForKeyedEvent( handle, (void *)(i * 2), 0, NULL );
- ok( status == STATUS_SUCCESS, "%li: failed %x\n", i, status );
- Sleep( i );
- }
- status = pNtWaitForKeyedEvent( handle, (void *)0x1234, 0, &timeout );
- ok( status == STATUS_SUCCESS, "NtWaitForKeyedEvent %x\n", status );
- status = pNtWaitForKeyedEvent( handle, (void *)0x5678, 0, &timeout );
- ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
- status = pNtReleaseKeyedEvent( handle, (void *)0x9abc, 0, &timeout );
- ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
-
- ok( WaitForSingleObject( thread, 30000 ) == 0, "wait failed\n" );
-
- NtClose( handle );
-
- /* test access rights */
-
- status = pNtCreateKeyedEvent( &handle, KEYEDEVENT_WAIT, &attr, 0 );
- ok( !status, "NtCreateKeyedEvent failed %x\n", status );
- status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
- ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
- status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
- ok( status == STATUS_ACCESS_DENIED, "NtReleaseKeyedEvent %x\n", status );
- NtClose( handle );
-
- status = pNtCreateKeyedEvent( &handle, KEYEDEVENT_WAKE, &attr, 0 );
- ok( !status, "NtCreateKeyedEvent failed %x\n", status );
- status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
- ok( status == STATUS_ACCESS_DENIED, "NtWaitForKeyedEvent %x\n", status );
- status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
- ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
- NtClose( handle );
-
- status = pNtCreateKeyedEvent( &handle, KEYEDEVENT_ALL_ACCESS, &attr, 0 );
- ok( !status, "NtCreateKeyedEvent failed %x\n", status );
- status = WaitForSingleObject( handle, 1000 );
- ok( status == WAIT_FAILED && GetLastError() == ERROR_ACCESS_DENIED,
- "WaitForSingleObject %x err %u\n", status, GetLastError() );
- status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
- ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
- status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
- ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
- NtClose( handle );
-
- /* GENERIC_READ gives wait access */
- status = pNtCreateKeyedEvent( &handle, GENERIC_READ, &attr, 0 );
- ok( !status, "NtCreateKeyedEvent failed %x\n", status );
- status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
- ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
- status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
- ok( status == STATUS_ACCESS_DENIED, "NtReleaseKeyedEvent %x\n", status );
- NtClose( handle );
-
- /* GENERIC_WRITE gives wake access */
- status = pNtCreateKeyedEvent( &handle, GENERIC_WRITE, &attr, 0 );
- ok( !status, "NtCreateKeyedEvent failed %x\n", status );
- status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
- ok( status == STATUS_ACCESS_DENIED, "NtWaitForKeyedEvent %x\n", status );
- status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
- ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
-
- /* it's not an event */
- status = pNtPulseEvent( handle, NULL );
- ok( status == STATUS_OBJECT_TYPE_MISMATCH, "NtPulseEvent %x\n", status );
-
- status = pNtCreateEvent( &event, GENERIC_ALL, &attr, NotificationEvent, FALSE );
- ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_OBJECT_TYPE_MISMATCH /* 7+ */,
- "CreateEvent %x\n", status );
-
- NtClose( handle );
-
- status = pNtCreateEvent( &event, GENERIC_ALL, &attr, NotificationEvent, FALSE );
- ok( status == 0, "CreateEvent %x\n", status );
- status = pNtWaitForKeyedEvent( event, (void *)8, 0, &timeout );
- ok( status == STATUS_OBJECT_TYPE_MISMATCH, "NtWaitForKeyedEvent %x\n", status );
- status = pNtReleaseKeyedEvent( event, (void *)8, 0, &timeout );
- ok( status == STATUS_OBJECT_TYPE_MISMATCH, "NtReleaseKeyedEvent %x\n", status );
- NtClose( event );
-}
-
static void test_null_device(void)
{
OBJECT_ATTRIBUTES attr;
@@ -2292,269 +1999,6 @@ static void test_null_device(void)
CloseHandle(ov.hEvent);
}
-static DWORD WINAPI mutant_thread( void *arg )
-{
- MUTANT_BASIC_INFORMATION info;
- NTSTATUS status;
- HANDLE mutant;
- DWORD ret;
-
- mutant = arg;
- ret = WaitForSingleObject( mutant, 1000 );
- ok( ret == WAIT_OBJECT_0, "WaitForSingleObject failed %08x\n", ret );
-
- memset(&info, 0xcc, sizeof(info));
- status = pNtQueryMutant(mutant, MutantBasicInformation, &info, sizeof(info), NULL);
- ok( status == STATUS_SUCCESS, "NtQueryMutant failed %08x\n", status );
- ok( info.CurrentCount == 0, "expected 0, got %d\n", info.CurrentCount );
- ok( info.OwnedByCaller == TRUE, "expected TRUE, got %d\n", info.OwnedByCaller );
- ok( info.AbandonedState == FALSE, "expected FALSE, got %d\n", info.AbandonedState );
- /* abandon mutant */
-
- return 0;
-}
-
-static void test_mutant(void)
-{
- MUTANT_BASIC_INFORMATION info;
- OBJECT_ATTRIBUTES attr;
- UNICODE_STRING str;
- NTSTATUS status;
- HANDLE mutant;
- HANDLE thread;
- DWORD ret;
- ULONG len;
- LONG prev;
-
- pRtlInitUnicodeString(&str, L"\\BaseNamedObjects\\test_mutant");
- InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
- status = pNtCreateMutant(&mutant, GENERIC_ALL, &attr, TRUE);
- ok( status == STATUS_SUCCESS, "Failed to create Mutant(%08x)\n", status );
-
- /* bogus */
- status = pNtQueryMutant(mutant, MutantBasicInformation, &info, 0, NULL);
- ok( status == STATUS_INFO_LENGTH_MISMATCH,
- "Failed to NtQueryMutant, expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status );
- status = pNtQueryMutant(mutant, 0x42, &info, sizeof(info), NULL);
- ok( status == STATUS_INVALID_INFO_CLASS || broken(status == STATUS_NOT_IMPLEMENTED), /* 32-bit on Vista/2k8 */
- "Failed to NtQueryMutant, expected STATUS_INVALID_INFO_CLASS, got %08x\n", status );
- status = pNtQueryMutant((HANDLE)0xdeadbeef, MutantBasicInformation, &info, sizeof(info), NULL);
- ok( status == STATUS_INVALID_HANDLE,
- "Failed to NtQueryMutant, expected STATUS_INVALID_HANDLE, got %08x\n", status );
-
- /* new */
- len = -1;
- memset(&info, 0xcc, sizeof(info));
- status = pNtQueryMutant(mutant, MutantBasicInformation, &info, sizeof(info), &len);
- ok( status == STATUS_SUCCESS, "NtQueryMutant failed %08x\n", status );
- ok( info.CurrentCount == 0, "expected 0, got %d\n", info.CurrentCount );
- ok( info.OwnedByCaller == TRUE, "expected TRUE, got %d\n", info.OwnedByCaller );
- ok( info.AbandonedState == FALSE, "expected FALSE, got %d\n", info.AbandonedState );
- ok( len == sizeof(info), "got %u\n", len );
-
- ret = WaitForSingleObject( mutant, 1000 );
- ok( ret == WAIT_OBJECT_0, "WaitForSingleObject failed %08x\n", ret );
-
- memset(&info, 0xcc, sizeof(info));
- status = pNtQueryMutant(mutant, MutantBasicInformation, &info, sizeof(info), NULL);
- ok( status == STATUS_SUCCESS, "NtQueryMutant failed %08x\n", status );
- ok( info.CurrentCount == -1, "expected -1, got %d\n", info.CurrentCount );
- ok( info.OwnedByCaller == TRUE, "expected TRUE, got %d\n", info.OwnedByCaller );
- ok( info.AbandonedState == FALSE, "expected FALSE, got %d\n", info.AbandonedState );
-
- prev = 0xdeadbeef;
- status = pNtReleaseMutant(mutant, &prev);
- ok( status == STATUS_SUCCESS, "NtReleaseMutant failed %08x\n", status );
- ok( prev == -1, "NtReleaseMutant failed, expected -1, got %d\n", prev );
-
- prev = 0xdeadbeef;
- status = pNtReleaseMutant(mutant, &prev);
- ok( status == STATUS_SUCCESS, "NtReleaseMutant failed %08x\n", status );
- ok( prev == 0, "NtReleaseMutant failed, expected 0, got %d\n", prev );
-
- memset(&info, 0xcc, sizeof(info));
- status = pNtQueryMutant(mutant, MutantBasicInformation, &info, sizeof(info), NULL);
- ok( status == STATUS_SUCCESS, "NtQueryMutant failed %08x\n", status );
- ok( info.CurrentCount == 1, "expected 1, got %d\n", info.CurrentCount );
- ok( info.OwnedByCaller == FALSE, "expected FALSE, got %d\n", info.OwnedByCaller );
- ok( info.AbandonedState == FALSE, "expected FALSE, got %d\n", info.AbandonedState );
-
- /* abandoned */
- thread = CreateThread( NULL, 0, mutant_thread, mutant, 0, NULL );
- ret = WaitForSingleObject( thread, 1000 );
- ok( ret == WAIT_OBJECT_0, "WaitForSingleObject failed %08x\n", ret );
- CloseHandle( thread );
-
- memset(&info, 0xcc, sizeof(info));
- status = pNtQueryMutant(mutant, MutantBasicInformation, &info, sizeof(info), NULL);
- ok( status == STATUS_SUCCESS, "NtQueryMutant failed %08x\n", status );
- ok( info.CurrentCount == 1, "expected 0, got %d\n", info.CurrentCount );
- ok( info.OwnedByCaller == FALSE, "expected FALSE, got %d\n", info.OwnedByCaller );
- ok( info.AbandonedState == TRUE, "expected TRUE, got %d\n", info.AbandonedState );
-
- ret = WaitForSingleObject( mutant, 1000 );
- ok( ret == WAIT_ABANDONED_0, "WaitForSingleObject failed %08x\n", ret );
-
- memset(&info, 0xcc, sizeof(info));
- status = pNtQueryMutant(mutant, MutantBasicInformation, &info, sizeof(info), NULL);
- ok( status == STATUS_SUCCESS, "NtQueryMutant failed %08x\n", status );
- ok( info.CurrentCount == 0, "expected 0, got %d\n", info.CurrentCount );
- ok( info.OwnedByCaller == TRUE, "expected TRUE, got %d\n", info.OwnedByCaller );
- ok( info.AbandonedState == FALSE, "expected FALSE, got %d\n", info.AbandonedState );
-
- NtClose( mutant );
-}
-
-static void test_semaphore(void)
-{
- SEMAPHORE_BASIC_INFORMATION info;
- OBJECT_ATTRIBUTES attr;
- UNICODE_STRING str;
- NTSTATUS status;
- HANDLE semaphore;
- ULONG prev;
- ULONG len;
- DWORD ret;
-
- pRtlInitUnicodeString(&str, L"\\BaseNamedObjects\\test_semaphore");
- InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
-
- status = pNtCreateSemaphore(&semaphore, GENERIC_ALL, &attr, 2, 1);
- ok( status == STATUS_INVALID_PARAMETER, "Failed to create Semaphore(%08x)\n", status );
- status = pNtCreateSemaphore(&semaphore, GENERIC_ALL, &attr, 1, 2);
- ok( status == STATUS_SUCCESS, "Failed to create Semaphore(%08x)\n", status );
-
- /* bogus */
- status = pNtQuerySemaphore(semaphore, SemaphoreBasicInformation, &info, 0, NULL);
- ok( status == STATUS_INFO_LENGTH_MISMATCH,
- "Failed to NtQuerySemaphore, expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status );
- status = pNtQuerySemaphore(semaphore, 0x42, &info, sizeof(info), NULL);
- ok( status == STATUS_INVALID_INFO_CLASS,
- "Failed to NtQuerySemaphore, expected STATUS_INVALID_INFO_CLASS, got %08x\n", status );
- status = pNtQuerySemaphore((HANDLE)0xdeadbeef, SemaphoreBasicInformation, &info, sizeof(info), NULL);
- ok( status == STATUS_INVALID_HANDLE,
- "Failed to NtQuerySemaphore, expected STATUS_INVALID_HANDLE, got %08x\n", status );
-
- len = -1;
- memset(&info, 0xcc, sizeof(info));
- status = pNtQuerySemaphore(semaphore, SemaphoreBasicInformation, &info, sizeof(info), &len);
- ok( status == STATUS_SUCCESS, "NtQuerySemaphore failed %08x\n", status );
- ok( info.CurrentCount == 1, "expected 1, got %d\n", info.CurrentCount );
- ok( info.MaximumCount == 2, "expected 2, got %d\n", info.MaximumCount );
- ok( len == sizeof(info), "got %u\n", len );
-
- ret = WaitForSingleObject( semaphore, 1000 );
- ok( ret == WAIT_OBJECT_0, "WaitForSingleObject failed %08x\n", ret );
-
- memset(&info, 0xcc, sizeof(info));
- status = pNtQuerySemaphore(semaphore, SemaphoreBasicInformation, &info, sizeof(info), NULL);
- ok( status == STATUS_SUCCESS, "NtQuerySemaphore failed %08x\n", status );
- ok( info.CurrentCount == 0, "expected 0, got %d\n", info.CurrentCount );
- ok( info.MaximumCount == 2, "expected 2, got %d\n", info.MaximumCount );
-
- prev = 0xdeadbeef;
- status = pNtReleaseSemaphore(semaphore, 3, &prev);
- ok( status == STATUS_SEMAPHORE_LIMIT_EXCEEDED, "NtReleaseSemaphore failed %08x\n", status );
- ok( prev == 0xdeadbeef, "NtReleaseSemaphore failed, expected 0xdeadbeef, got %d\n", prev );
-
- prev = 0xdeadbeef;
- status = pNtReleaseSemaphore(semaphore, 1, &prev);
- ok( status == STATUS_SUCCESS, "NtReleaseSemaphore failed %08x\n", status );
- ok( prev == 0, "NtReleaseSemaphore failed, expected 0, got %d\n", prev );
-
- prev = 0xdeadbeef;
- status = pNtReleaseSemaphore(semaphore, 1, &prev);
- ok( status == STATUS_SUCCESS, "NtReleaseSemaphore failed %08x\n", status );
- ok( prev == 1, "NtReleaseSemaphore failed, expected 1, got %d\n", prev );
-
- prev = 0xdeadbeef;
- status = pNtReleaseSemaphore(semaphore, 1, &prev);
- ok( status == STATUS_SEMAPHORE_LIMIT_EXCEEDED, "NtReleaseSemaphore failed %08x\n", status );
- ok( prev == 0xdeadbeef, "NtReleaseSemaphore failed, expected 0xdeadbeef, got %d\n", prev );
-
- memset(&info, 0xcc, sizeof(info));
- status = pNtQuerySemaphore(semaphore, SemaphoreBasicInformation, &info, sizeof(info), NULL);
- ok( status == STATUS_SUCCESS, "NtQuerySemaphore failed %08x\n", status );
- ok( info.CurrentCount == 2, "expected 2, got %d\n", info.CurrentCount );
- ok( info.MaximumCount == 2, "expected 2, got %d\n", info.MaximumCount );
-
- NtClose( semaphore );
-}
-
-static void test_wait_on_address(void)
-{
- SIZE_T size;
- NTSTATUS status;
- LARGE_INTEGER start, end, timeout;
- DWORD elapsed;
- LONG64 address, compare;
-
- if (!pRtlWaitOnAddress)
- {
- win_skip("RtlWaitOnAddress not supported, skipping test\n");
- return;
- }
-
- if (0) /* crash on Windows */
- {
- pRtlWaitOnAddress(&address, NULL, 8, NULL);
- pRtlWaitOnAddress(NULL, &compare, 8, NULL);
- pRtlWaitOnAddress(NULL, NULL, 8, NULL);
- }
-
- /* don't crash */
- pRtlWakeAddressSingle(NULL);
- pRtlWakeAddressAll(NULL);
-
- /* invalid values */
- address = 0;
- compare = 0;
- status = pRtlWaitOnAddress(&address, &compare, 5, NULL);
- ok(status == STATUS_INVALID_PARAMETER, "got %x\n", status);
-
- /* values match */
- address = 0;
- compare = 0;
- pNtQuerySystemTime(&start);
- timeout.QuadPart = start.QuadPart + 100 * 10000;
- status = pRtlWaitOnAddress(&address, &compare, 8, &timeout);
- pNtQuerySystemTime(&end);
- ok(status == STATUS_TIMEOUT, "got 0x%08x\n", status);
- elapsed = (end.QuadPart - start.QuadPart) / 10000;
- ok(90 <= elapsed && elapsed <= 900, "timed out in %u ms\n", elapsed);
- ok(address == 0, "got %s\n", wine_dbgstr_longlong(address));
- ok(compare == 0, "got %s\n", wine_dbgstr_longlong(compare));
-
- /* different address size */
- for (size = 1; size <= 4; size <<= 1)
- {
- compare = ~0;
- compare <<= size * 8;
-
- pNtQuerySystemTime(&start);
- timeout.QuadPart = -100 * 10000;
- status = pRtlWaitOnAddress(&address, &compare, size, &timeout);
- pNtQuerySystemTime(&end);
- ok(status == STATUS_TIMEOUT, "got 0x%08x\n", status);
- elapsed = (end.QuadPart - start.QuadPart) / 10000;
- ok(90 <= elapsed && elapsed <= 900, "timed out in %u ms\n", elapsed);
-
- status = pRtlWaitOnAddress(&address, &compare, size << 1, &timeout);
- ok(!status, "got 0x%08x\n", status);
- }
- address = 0;
- compare = 1;
- status = pRtlWaitOnAddress(&address, &compare, 8, NULL);
- ok(!status, "got 0x%08x\n", status);
-
- /* no waiters */
- address = 0;
- pRtlWakeAddressSingle(&address);
- ok(address == 0, "got %s\n", wine_dbgstr_longlong(address));
- pRtlWakeAddressAll(&address);
- ok(address == 0, "got %s\n", wine_dbgstr_longlong(address));
-}
-
static void test_process(void)
{
OBJECT_ATTRIBUTES attr;
@@ -2957,13 +2401,7 @@ START_TEST(om)
pNtCreateMailslotFile = (void *)GetProcAddress(hntdll, "NtCreateMailslotFile");
pNtCreateMutant = (void *)GetProcAddress(hntdll, "NtCreateMutant");
pNtOpenEvent = (void *)GetProcAddress(hntdll, "NtOpenEvent");
- pNtQueryEvent = (void *)GetProcAddress(hntdll, "NtQueryEvent");
- pNtPulseEvent = (void *)GetProcAddress(hntdll, "NtPulseEvent");
- pNtResetEvent = (void *)GetProcAddress(hntdll, "NtResetEvent");
- pNtSetEvent = (void *)GetProcAddress(hntdll, "NtSetEvent");
pNtOpenMutant = (void *)GetProcAddress(hntdll, "NtOpenMutant");
- pNtQueryMutant = (void *)GetProcAddress(hntdll, "NtQueryMutant");
- pNtReleaseMutant = (void *)GetProcAddress(hntdll, "NtReleaseMutant");
pNtOpenFile = (void *)GetProcAddress(hntdll, "NtOpenFile");
pNtClose = (void *)GetProcAddress(hntdll, "NtClose");
pRtlInitUnicodeString = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString");
@@ -2975,7 +2413,6 @@ START_TEST(om)
pNtQuerySymbolicLinkObject = (void *)GetProcAddress(hntdll, "NtQuerySymbolicLinkObject");
pNtCreateSemaphore = (void *)GetProcAddress(hntdll, "NtCreateSemaphore");
pNtOpenSemaphore = (void *)GetProcAddress(hntdll, "NtOpenSemaphore");
- pNtQuerySemaphore = (void *)GetProcAddress(hntdll, "NtQuerySemaphore");
pNtCreateTimer = (void *)GetProcAddress(hntdll, "NtCreateTimer");
pNtOpenTimer = (void *)GetProcAddress(hntdll, "NtOpenTimer");
pNtCreateSection = (void *)GetProcAddress(hntdll, "NtCreateSection");
@@ -2984,15 +2421,9 @@ START_TEST(om)
pNtReleaseSemaphore = (void *)GetProcAddress(hntdll, "NtReleaseSemaphore");
pNtCreateKeyedEvent = (void *)GetProcAddress(hntdll, "NtCreateKeyedEvent");
pNtOpenKeyedEvent = (void *)GetProcAddress(hntdll, "NtOpenKeyedEvent");
- pNtWaitForKeyedEvent = (void *)GetProcAddress(hntdll, "NtWaitForKeyedEvent");
- pNtReleaseKeyedEvent = (void *)GetProcAddress(hntdll, "NtReleaseKeyedEvent");
pNtCreateIoCompletion = (void *)GetProcAddress(hntdll, "NtCreateIoCompletion");
pNtOpenIoCompletion = (void *)GetProcAddress(hntdll, "NtOpenIoCompletion");
pNtQueryInformationFile = (void *)GetProcAddress(hntdll, "NtQueryInformationFile");
- pNtQuerySystemTime = (void *)GetProcAddress(hntdll, "NtQuerySystemTime");
- pRtlWaitOnAddress = (void *)GetProcAddress(hntdll, "RtlWaitOnAddress");
- pRtlWakeAddressAll = (void *)GetProcAddress(hntdll, "RtlWakeAddressAll");
- pRtlWakeAddressSingle = (void *)GetProcAddress(hntdll, "RtlWakeAddressSingle");
pNtOpenProcess = (void *)GetProcAddress(hntdll, "NtOpenProcess");
pNtCreateDebugObject = (void *)GetProcAddress(hntdll, "NtCreateDebugObject");
pNtGetNextThread = (void *)GetProcAddress(hntdll, "NtGetNextThread");
@@ -3009,12 +2440,7 @@ START_TEST(om)
test_symboliclink();
test_query_object();
test_type_mismatch();
- test_event();
- test_mutant();
- test_semaphore();
- test_keyed_events();
test_null_device();
- test_wait_on_address();
test_process();
test_token();
test_duplicate_object();
diff --git a/dlls/ntdll/tests/sync.c b/dlls/ntdll/tests/sync.c
new file mode 100644
index 00000000000..7e389c9762b
--- /dev/null
+++ b/dlls/ntdll/tests/sync.c
@@ -0,0 +1,631 @@
+/*
+ * Unit tests for NT synchronization objects
+ *
+ * Copyright 2020 Zebediah Figura
+ *
+ * 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 <stdarg.h>
+
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winternl.h"
+#include "wine/test.h"
+
+static NTSTATUS (WINAPI *pNtClose)( HANDLE );
+static NTSTATUS (WINAPI *pNtCreateEvent) ( PHANDLE, ACCESS_MASK, const OBJECT_ATTRIBUTES *, EVENT_TYPE, BOOLEAN);
+static NTSTATUS (WINAPI *pNtCreateKeyedEvent)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, ULONG );
+static NTSTATUS (WINAPI *pNtCreateMutant)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, BOOLEAN );
+static NTSTATUS (WINAPI *pNtCreateSemaphore)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, LONG, LONG );
+static NTSTATUS (WINAPI *pNtOpenEvent)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES * );
+static NTSTATUS (WINAPI *pNtOpenKeyedEvent)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES * );
+static NTSTATUS (WINAPI *pNtPulseEvent)( HANDLE, LONG * );
+static NTSTATUS (WINAPI *pNtQueryEvent)( HANDLE, EVENT_INFORMATION_CLASS, void *, ULONG, ULONG * );
+static NTSTATUS (WINAPI *pNtQueryMutant)( HANDLE, MUTANT_INFORMATION_CLASS, void *, ULONG, ULONG * );
+static NTSTATUS (WINAPI *pNtQuerySemaphore)( HANDLE, SEMAPHORE_INFORMATION_CLASS, void *, ULONG, ULONG * );
+static NTSTATUS (WINAPI *pNtQuerySystemTime)( LARGE_INTEGER * );
+static NTSTATUS (WINAPI *pNtReleaseKeyedEvent)( HANDLE, const void *, BOOLEAN, const LARGE_INTEGER * );
+static NTSTATUS (WINAPI *pNtReleaseMutant)( HANDLE, LONG * );
+static NTSTATUS (WINAPI *pNtReleaseSemaphore)( HANDLE, ULONG, ULONG * );
+static NTSTATUS (WINAPI *pNtResetEvent)( HANDLE, LONG * );
+static NTSTATUS (WINAPI *pNtSetEvent)( HANDLE, LONG * );
+static NTSTATUS (WINAPI *pNtWaitForKeyedEvent)( HANDLE, const void *, BOOLEAN, const LARGE_INTEGER * );
+static void (WINAPI *pRtlInitUnicodeString)( UNICODE_STRING *, const WCHAR * );
+static NTSTATUS (WINAPI *pRtlWaitOnAddress)( const void *, const void *, SIZE_T, const LARGE_INTEGER * );
+static void (WINAPI *pRtlWakeAddressAll)( const void * );
+static void (WINAPI *pRtlWakeAddressSingle)( const void * );
+
+#define KEYEDEVENT_WAIT 0x0001
+#define KEYEDEVENT_WAKE 0x0002
+#define KEYEDEVENT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x0003)
+
+static void test_event(void)
+{
+ HANDLE event;
+ HANDLE event2;
+ LONG prev_state = 0xdeadbeef;
+ NTSTATUS status;
+ UNICODE_STRING str;
+ OBJECT_ATTRIBUTES attr;
+ EVENT_BASIC_INFORMATION info;
+
+ pRtlInitUnicodeString( &str, L"\\BaseNamedObjects\\testEvent" );
+ InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
+
+ status = pNtCreateEvent(&event, GENERIC_ALL, &attr, 2, 0);
+ ok( status == STATUS_INVALID_PARAMETER, "NtCreateEvent failed %08x\n", status );
+
+ status = pNtCreateEvent(&event, GENERIC_ALL, &attr, NotificationEvent, 0);
+ ok( status == STATUS_SUCCESS, "NtCreateEvent failed %08x\n", status );
+ memset(&info, 0xcc, sizeof(info));
+ status = pNtQueryEvent(event, EventBasicInformation, &info, sizeof(info), NULL);
+ ok( status == STATUS_SUCCESS, "NtQueryEvent failed %08x\n", status );
+ ok( info.EventType == NotificationEvent && info.EventState == 0,
+ "NtQueryEvent failed, expected 0 0, got %d %d\n", info.EventType, info.EventState );
+ pNtClose(event);
+
+ status = pNtCreateEvent(&event, GENERIC_ALL, &attr, SynchronizationEvent, 0);
+ ok( status == STATUS_SUCCESS, "NtCreateEvent failed %08x\n", status );
+
+ status = pNtPulseEvent(event, &prev_state);
+ ok( status == STATUS_SUCCESS, "NtPulseEvent failed %08x\n", status );
+ ok( !prev_state, "prev_state = %x\n", prev_state );
+
+ memset(&info, 0xcc, sizeof(info));
+ status = pNtQueryEvent(event, EventBasicInformation, &info, sizeof(info), NULL);
+ ok( status == STATUS_SUCCESS, "NtQueryEvent failed %08x\n", status );
+ ok( info.EventType == SynchronizationEvent && info.EventState == 0,
+ "NtQueryEvent failed, expected 1 0, got %d %d\n", info.EventType, info.EventState );
+
+ status = pNtOpenEvent(&event2, GENERIC_ALL, &attr);
+ ok( status == STATUS_SUCCESS, "NtOpenEvent failed %08x\n", status );
+
+ pNtClose(event);
+ event = event2;
+
+ memset(&info, 0xcc, sizeof(info));
+ status = pNtQueryEvent(event, EventBasicInformation, &info, sizeof(info), NULL);
+ ok( status == STATUS_SUCCESS, "NtQueryEvent failed %08x\n", status );
+ ok( info.EventType == SynchronizationEvent && info.EventState == 0,
+ "NtQueryEvent failed, expected 1 0, got %d %d\n", info.EventType, info.EventState );
+
+ status = pNtSetEvent( event, &prev_state );
+ ok( status == STATUS_SUCCESS, "NtSetEvent failed: %08x\n", status );
+ ok( !prev_state, "prev_state = %x\n", prev_state );
+
+ memset(&info, 0xcc, sizeof(info));
+ status = pNtQueryEvent(event, EventBasicInformation, &info, sizeof(info), NULL);
+ ok( status == STATUS_SUCCESS, "NtQueryEvent failed %08x\n", status );
+ ok( info.EventType == SynchronizationEvent && info.EventState == 1,
+ "NtQueryEvent failed, expected 1 1, got %d %d\n", info.EventType, info.EventState );
+
+ status = pNtSetEvent( event, &prev_state );
+ ok( status == STATUS_SUCCESS, "NtSetEvent failed: %08x\n", status );
+ ok( prev_state == 1, "prev_state = %x\n", prev_state );
+
+ status = pNtResetEvent( event, &prev_state );
+ ok( status == STATUS_SUCCESS, "NtSetEvent failed: %08x\n", status );
+ ok( prev_state == 1, "prev_state = %x\n", prev_state );
+
+ status = pNtResetEvent( event, &prev_state );
+ ok( status == STATUS_SUCCESS, "NtSetEvent failed: %08x\n", status );
+ ok( !prev_state, "prev_state = %x\n", prev_state );
+
+ status = pNtPulseEvent( event, &prev_state );
+ ok( status == STATUS_SUCCESS, "NtPulseEvent failed %08x\n", status );
+ ok( !prev_state, "prev_state = %x\n", prev_state );
+
+ status = pNtSetEvent( event, &prev_state );
+ ok( status == STATUS_SUCCESS, "NtSetEvent failed: %08x\n", status );
+ ok( !prev_state, "prev_state = %x\n", prev_state );
+
+ status = pNtPulseEvent( event, &prev_state );
+ ok( status == STATUS_SUCCESS, "NtPulseEvent failed %08x\n", status );
+ ok( prev_state == 1, "prev_state = %x\n", prev_state );
+
+ pNtClose(event);
+}
+
+static const WCHAR keyed_nameW[] = L"\\BaseNamedObjects\\WineTestEvent";
+
+static DWORD WINAPI keyed_event_thread( void *arg )
+{
+ HANDLE handle;
+ NTSTATUS status;
+ LARGE_INTEGER timeout;
+ OBJECT_ATTRIBUTES attr;
+ UNICODE_STRING str;
+ ULONG_PTR i;
+
+ attr.Length = sizeof(attr);
+ attr.RootDirectory = 0;
+ attr.ObjectName = &str;
+ attr.Attributes = 0;
+ attr.SecurityDescriptor = NULL;
+ attr.SecurityQualityOfService = NULL;
+ RtlInitUnicodeString( &str, keyed_nameW );
+
+ status = pNtOpenKeyedEvent( &handle, KEYEDEVENT_ALL_ACCESS, &attr );
+ ok( !status, "NtOpenKeyedEvent failed %x\n", status );
+
+ for (i = 0; i < 20; i++)
+ {
+ if (i & 1)
+ status = pNtWaitForKeyedEvent( handle, (void *)(i * 2), 0, NULL );
+ else
+ status = pNtReleaseKeyedEvent( handle, (void *)(i * 2), 0, NULL );
+ ok( status == STATUS_SUCCESS, "%li: failed %x\n", i, status );
+ Sleep( 20 - i );
+ }
+
+ status = pNtReleaseKeyedEvent( handle, (void *)0x1234, 0, NULL );
+ ok( status == STATUS_SUCCESS, "NtReleaseKeyedEvent %x\n", status );
+
+ timeout.QuadPart = -10000;
+ status = pNtWaitForKeyedEvent( handle, (void *)0x5678, 0, &timeout );
+ ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
+ status = pNtReleaseKeyedEvent( handle, (void *)0x9abc, 0, &timeout );
+ ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
+
+ NtClose( handle );
+ return 0;
+}
+
+static void test_keyed_events(void)
+{
+ OBJECT_ATTRIBUTES attr;
+ UNICODE_STRING str;
+ HANDLE handle, event, thread;
+ NTSTATUS status;
+ LARGE_INTEGER timeout;
+ ULONG_PTR i;
+
+ if (!pNtCreateKeyedEvent)
+ {
+ win_skip( "Keyed events not supported\n" );
+ return;
+ }
+
+ attr.Length = sizeof(attr);
+ attr.RootDirectory = 0;
+ attr.ObjectName = &str;
+ attr.Attributes = 0;
+ attr.SecurityDescriptor = NULL;
+ attr.SecurityQualityOfService = NULL;
+ RtlInitUnicodeString( &str, keyed_nameW );
+
+ status = pNtCreateKeyedEvent( &handle, KEYEDEVENT_ALL_ACCESS | SYNCHRONIZE, &attr, 0 );
+ ok( !status, "NtCreateKeyedEvent failed %x\n", status );
+
+ status = WaitForSingleObject( handle, 1000 );
+ ok( status == 0, "WaitForSingleObject %x\n", status );
+
+ timeout.QuadPart = -100000;
+ status = pNtWaitForKeyedEvent( handle, (void *)255, 0, &timeout );
+ ok( status == STATUS_INVALID_PARAMETER_1, "NtWaitForKeyedEvent %x\n", status );
+ status = pNtReleaseKeyedEvent( handle, (void *)255, 0, &timeout );
+ ok( status == STATUS_INVALID_PARAMETER_1, "NtReleaseKeyedEvent %x\n", status );
+
+ status = pNtWaitForKeyedEvent( handle, (void *)254, 0, &timeout );
+ ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
+ status = pNtReleaseKeyedEvent( handle, (void *)254, 0, &timeout );
+ ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
+
+ status = pNtWaitForKeyedEvent( handle, NULL, 0, &timeout );
+ ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
+ status = pNtReleaseKeyedEvent( handle, NULL, 0, &timeout );
+ ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
+
+ status = pNtWaitForKeyedEvent( NULL, (void *)8, 0, &timeout );
+ ok( status == STATUS_TIMEOUT || broken(status == STATUS_INVALID_HANDLE), /* XP/2003 */
+ "NtWaitForKeyedEvent %x\n", status );
+ status = pNtReleaseKeyedEvent( NULL, (void *)8, 0, &timeout );
+ ok( status == STATUS_TIMEOUT || broken(status == STATUS_INVALID_HANDLE), /* XP/2003 */
+ "NtReleaseKeyedEvent %x\n", status );
+
+ status = pNtWaitForKeyedEvent( (HANDLE)0xdeadbeef, (void *)9, 0, &timeout );
+ ok( status == STATUS_INVALID_PARAMETER_1, "NtWaitForKeyedEvent %x\n", status );
+ status = pNtReleaseKeyedEvent( (HANDLE)0xdeadbeef, (void *)9, 0, &timeout );
+ ok( status == STATUS_INVALID_PARAMETER_1, "NtReleaseKeyedEvent %x\n", status );
+
+ status = pNtWaitForKeyedEvent( (HANDLE)0xdeadbeef, (void *)8, 0, &timeout );
+ ok( status == STATUS_INVALID_HANDLE, "NtWaitForKeyedEvent %x\n", status );
+ status = pNtReleaseKeyedEvent( (HANDLE)0xdeadbeef, (void *)8, 0, &timeout );
+ ok( status == STATUS_INVALID_HANDLE, "NtReleaseKeyedEvent %x\n", status );
+
+ thread = CreateThread( NULL, 0, keyed_event_thread, 0, 0, NULL );
+ for (i = 0; i < 20; i++)
+ {
+ if (i & 1)
+ status = pNtReleaseKeyedEvent( handle, (void *)(i * 2), 0, NULL );
+ else
+ status = pNtWaitForKeyedEvent( handle, (void *)(i * 2), 0, NULL );
+ ok( status == STATUS_SUCCESS, "%li: failed %x\n", i, status );
+ Sleep( i );
+ }
+ status = pNtWaitForKeyedEvent( handle, (void *)0x1234, 0, &timeout );
+ ok( status == STATUS_SUCCESS, "NtWaitForKeyedEvent %x\n", status );
+ status = pNtWaitForKeyedEvent( handle, (void *)0x5678, 0, &timeout );
+ ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
+ status = pNtReleaseKeyedEvent( handle, (void *)0x9abc, 0, &timeout );
+ ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
+
+ ok( WaitForSingleObject( thread, 30000 ) == 0, "wait failed\n" );
+
+ NtClose( handle );
+
+ /* test access rights */
+
+ status = pNtCreateKeyedEvent( &handle, KEYEDEVENT_WAIT, &attr, 0 );
+ ok( !status, "NtCreateKeyedEvent failed %x\n", status );
+ status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
+ ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
+ status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
+ ok( status == STATUS_ACCESS_DENIED, "NtReleaseKeyedEvent %x\n", status );
+ NtClose( handle );
+
+ status = pNtCreateKeyedEvent( &handle, KEYEDEVENT_WAKE, &attr, 0 );
+ ok( !status, "NtCreateKeyedEvent failed %x\n", status );
+ status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
+ ok( status == STATUS_ACCESS_DENIED, "NtWaitForKeyedEvent %x\n", status );
+ status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
+ ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
+ NtClose( handle );
+
+ status = pNtCreateKeyedEvent( &handle, KEYEDEVENT_ALL_ACCESS, &attr, 0 );
+ ok( !status, "NtCreateKeyedEvent failed %x\n", status );
+ status = WaitForSingleObject( handle, 1000 );
+ ok( status == WAIT_FAILED && GetLastError() == ERROR_ACCESS_DENIED,
+ "WaitForSingleObject %x err %u\n", status, GetLastError() );
+ status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
+ ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
+ status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
+ ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
+ NtClose( handle );
+
+ /* GENERIC_READ gives wait access */
+ status = pNtCreateKeyedEvent( &handle, GENERIC_READ, &attr, 0 );
+ ok( !status, "NtCreateKeyedEvent failed %x\n", status );
+ status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
+ ok( status == STATUS_TIMEOUT, "NtWaitForKeyedEvent %x\n", status );
+ status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
+ ok( status == STATUS_ACCESS_DENIED, "NtReleaseKeyedEvent %x\n", status );
+ NtClose( handle );
+
+ /* GENERIC_WRITE gives wake access */
+ status = pNtCreateKeyedEvent( &handle, GENERIC_WRITE, &attr, 0 );
+ ok( !status, "NtCreateKeyedEvent failed %x\n", status );
+ status = pNtWaitForKeyedEvent( handle, (void *)8, 0, &timeout );
+ ok( status == STATUS_ACCESS_DENIED, "NtWaitForKeyedEvent %x\n", status );
+ status = pNtReleaseKeyedEvent( handle, (void *)8, 0, &timeout );
+ ok( status == STATUS_TIMEOUT, "NtReleaseKeyedEvent %x\n", status );
+
+ /* it's not an event */
+ status = pNtPulseEvent( handle, NULL );
+ ok( status == STATUS_OBJECT_TYPE_MISMATCH, "NtPulseEvent %x\n", status );
+
+ status = pNtCreateEvent( &event, GENERIC_ALL, &attr, NotificationEvent, FALSE );
+ ok( status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_OBJECT_TYPE_MISMATCH /* 7+ */,
+ "CreateEvent %x\n", status );
+
+ NtClose( handle );
+
+ status = pNtCreateEvent( &event, GENERIC_ALL, &attr, NotificationEvent, FALSE );
+ ok( status == 0, "CreateEvent %x\n", status );
+ status = pNtWaitForKeyedEvent( event, (void *)8, 0, &timeout );
+ ok( status == STATUS_OBJECT_TYPE_MISMATCH, "NtWaitForKeyedEvent %x\n", status );
+ status = pNtReleaseKeyedEvent( event, (void *)8, 0, &timeout );
+ ok( status == STATUS_OBJECT_TYPE_MISMATCH, "NtReleaseKeyedEvent %x\n", status );
+ NtClose( event );
+}
+
+static DWORD WINAPI mutant_thread( void *arg )
+{
+ MUTANT_BASIC_INFORMATION info;
+ NTSTATUS status;
+ HANDLE mutant;
+ DWORD ret;
+
+ mutant = arg;
+ ret = WaitForSingleObject( mutant, 1000 );
+ ok( ret == WAIT_OBJECT_0, "WaitForSingleObject failed %08x\n", ret );
+
+ memset(&info, 0xcc, sizeof(info));
+ status = pNtQueryMutant(mutant, MutantBasicInformation, &info, sizeof(info), NULL);
+ ok( status == STATUS_SUCCESS, "NtQueryMutant failed %08x\n", status );
+ ok( info.CurrentCount == 0, "expected 0, got %d\n", info.CurrentCount );
+ ok( info.OwnedByCaller == TRUE, "expected TRUE, got %d\n", info.OwnedByCaller );
+ ok( info.AbandonedState == FALSE, "expected FALSE, got %d\n", info.AbandonedState );
+ /* abandon mutant */
+
+ return 0;
+}
+
+static void test_mutant(void)
+{
+ MUTANT_BASIC_INFORMATION info;
+ OBJECT_ATTRIBUTES attr;
+ UNICODE_STRING str;
+ NTSTATUS status;
+ HANDLE mutant;
+ HANDLE thread;
+ DWORD ret;
+ ULONG len;
+ LONG prev;
+
+ pRtlInitUnicodeString(&str, L"\\BaseNamedObjects\\test_mutant");
+ InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
+ status = pNtCreateMutant(&mutant, GENERIC_ALL, &attr, TRUE);
+ ok( status == STATUS_SUCCESS, "Failed to create Mutant(%08x)\n", status );
+
+ /* bogus */
+ status = pNtQueryMutant(mutant, MutantBasicInformation, &info, 0, NULL);
+ ok( status == STATUS_INFO_LENGTH_MISMATCH,
+ "Failed to NtQueryMutant, expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status );
+ status = pNtQueryMutant(mutant, 0x42, &info, sizeof(info), NULL);
+ ok( status == STATUS_INVALID_INFO_CLASS || broken(status == STATUS_NOT_IMPLEMENTED), /* 32-bit on Vista/2k8 */
+ "Failed to NtQueryMutant, expected STATUS_INVALID_INFO_CLASS, got %08x\n", status );
+ status = pNtQueryMutant((HANDLE)0xdeadbeef, MutantBasicInformation, &info, sizeof(info), NULL);
+ ok( status == STATUS_INVALID_HANDLE,
+ "Failed to NtQueryMutant, expected STATUS_INVALID_HANDLE, got %08x\n", status );
+
+ /* new */
+ len = -1;
+ memset(&info, 0xcc, sizeof(info));
+ status = pNtQueryMutant(mutant, MutantBasicInformation, &info, sizeof(info), &len);
+ ok( status == STATUS_SUCCESS, "NtQueryMutant failed %08x\n", status );
+ ok( info.CurrentCount == 0, "expected 0, got %d\n", info.CurrentCount );
+ ok( info.OwnedByCaller == TRUE, "expected TRUE, got %d\n", info.OwnedByCaller );
+ ok( info.AbandonedState == FALSE, "expected FALSE, got %d\n", info.AbandonedState );
+ ok( len == sizeof(info), "got %u\n", len );
+
+ ret = WaitForSingleObject( mutant, 1000 );
+ ok( ret == WAIT_OBJECT_0, "WaitForSingleObject failed %08x\n", ret );
+
+ memset(&info, 0xcc, sizeof(info));
+ status = pNtQueryMutant(mutant, MutantBasicInformation, &info, sizeof(info), NULL);
+ ok( status == STATUS_SUCCESS, "NtQueryMutant failed %08x\n", status );
+ ok( info.CurrentCount == -1, "expected -1, got %d\n", info.CurrentCount );
+ ok( info.OwnedByCaller == TRUE, "expected TRUE, got %d\n", info.OwnedByCaller );
+ ok( info.AbandonedState == FALSE, "expected FALSE, got %d\n", info.AbandonedState );
+
+ prev = 0xdeadbeef;
+ status = pNtReleaseMutant(mutant, &prev);
+ ok( status == STATUS_SUCCESS, "NtReleaseMutant failed %08x\n", status );
+ ok( prev == -1, "NtReleaseMutant failed, expected -1, got %d\n", prev );
+
+ prev = 0xdeadbeef;
+ status = pNtReleaseMutant(mutant, &prev);
+ ok( status == STATUS_SUCCESS, "NtReleaseMutant failed %08x\n", status );
+ ok( prev == 0, "NtReleaseMutant failed, expected 0, got %d\n", prev );
+
+ memset(&info, 0xcc, sizeof(info));
+ status = pNtQueryMutant(mutant, MutantBasicInformation, &info, sizeof(info), NULL);
+ ok( status == STATUS_SUCCESS, "NtQueryMutant failed %08x\n", status );
+ ok( info.CurrentCount == 1, "expected 1, got %d\n", info.CurrentCount );
+ ok( info.OwnedByCaller == FALSE, "expected FALSE, got %d\n", info.OwnedByCaller );
+ ok( info.AbandonedState == FALSE, "expected FALSE, got %d\n", info.AbandonedState );
+
+ /* abandoned */
+ thread = CreateThread( NULL, 0, mutant_thread, mutant, 0, NULL );
+ ret = WaitForSingleObject( thread, 1000 );
+ ok( ret == WAIT_OBJECT_0, "WaitForSingleObject failed %08x\n", ret );
+ CloseHandle( thread );
+
+ memset(&info, 0xcc, sizeof(info));
+ status = pNtQueryMutant(mutant, MutantBasicInformation, &info, sizeof(info), NULL);
+ ok( status == STATUS_SUCCESS, "NtQueryMutant failed %08x\n", status );
+ ok( info.CurrentCount == 1, "expected 0, got %d\n", info.CurrentCount );
+ ok( info.OwnedByCaller == FALSE, "expected FALSE, got %d\n", info.OwnedByCaller );
+ ok( info.AbandonedState == TRUE, "expected TRUE, got %d\n", info.AbandonedState );
+
+ ret = WaitForSingleObject( mutant, 1000 );
+ ok( ret == WAIT_ABANDONED_0, "WaitForSingleObject failed %08x\n", ret );
+
+ memset(&info, 0xcc, sizeof(info));
+ status = pNtQueryMutant(mutant, MutantBasicInformation, &info, sizeof(info), NULL);
+ ok( status == STATUS_SUCCESS, "NtQueryMutant failed %08x\n", status );
+ ok( info.CurrentCount == 0, "expected 0, got %d\n", info.CurrentCount );
+ ok( info.OwnedByCaller == TRUE, "expected TRUE, got %d\n", info.OwnedByCaller );
+ ok( info.AbandonedState == FALSE, "expected FALSE, got %d\n", info.AbandonedState );
+
+ NtClose( mutant );
+}
+
+static void test_semaphore(void)
+{
+ SEMAPHORE_BASIC_INFORMATION info;
+ OBJECT_ATTRIBUTES attr;
+ UNICODE_STRING str;
+ NTSTATUS status;
+ HANDLE semaphore;
+ ULONG prev;
+ ULONG len;
+ DWORD ret;
+
+ pRtlInitUnicodeString(&str, L"\\BaseNamedObjects\\test_semaphore");
+ InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
+
+ status = pNtCreateSemaphore(&semaphore, GENERIC_ALL, &attr, 2, 1);
+ ok( status == STATUS_INVALID_PARAMETER, "Failed to create Semaphore(%08x)\n", status );
+ status = pNtCreateSemaphore(&semaphore, GENERIC_ALL, &attr, 1, 2);
+ ok( status == STATUS_SUCCESS, "Failed to create Semaphore(%08x)\n", status );
+
+ /* bogus */
+ status = pNtQuerySemaphore(semaphore, SemaphoreBasicInformation, &info, 0, NULL);
+ ok( status == STATUS_INFO_LENGTH_MISMATCH,
+ "Failed to NtQuerySemaphore, expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status );
+ status = pNtQuerySemaphore(semaphore, 0x42, &info, sizeof(info), NULL);
+ ok( status == STATUS_INVALID_INFO_CLASS,
+ "Failed to NtQuerySemaphore, expected STATUS_INVALID_INFO_CLASS, got %08x\n", status );
+ status = pNtQuerySemaphore((HANDLE)0xdeadbeef, SemaphoreBasicInformation, &info, sizeof(info), NULL);
+ ok( status == STATUS_INVALID_HANDLE,
+ "Failed to NtQuerySemaphore, expected STATUS_INVALID_HANDLE, got %08x\n", status );
+
+ len = -1;
+ memset(&info, 0xcc, sizeof(info));
+ status = pNtQuerySemaphore(semaphore, SemaphoreBasicInformation, &info, sizeof(info), &len);
+ ok( status == STATUS_SUCCESS, "NtQuerySemaphore failed %08x\n", status );
+ ok( info.CurrentCount == 1, "expected 1, got %d\n", info.CurrentCount );
+ ok( info.MaximumCount == 2, "expected 2, got %d\n", info.MaximumCount );
+ ok( len == sizeof(info), "got %u\n", len );
+
+ ret = WaitForSingleObject( semaphore, 1000 );
+ ok( ret == WAIT_OBJECT_0, "WaitForSingleObject failed %08x\n", ret );
+
+ memset(&info, 0xcc, sizeof(info));
+ status = pNtQuerySemaphore(semaphore, SemaphoreBasicInformation, &info, sizeof(info), NULL);
+ ok( status == STATUS_SUCCESS, "NtQuerySemaphore failed %08x\n", status );
+ ok( info.CurrentCount == 0, "expected 0, got %d\n", info.CurrentCount );
+ ok( info.MaximumCount == 2, "expected 2, got %d\n", info.MaximumCount );
+
+ prev = 0xdeadbeef;
+ status = pNtReleaseSemaphore(semaphore, 3, &prev);
+ ok( status == STATUS_SEMAPHORE_LIMIT_EXCEEDED, "NtReleaseSemaphore failed %08x\n", status );
+ ok( prev == 0xdeadbeef, "NtReleaseSemaphore failed, expected 0xdeadbeef, got %d\n", prev );
+
+ prev = 0xdeadbeef;
+ status = pNtReleaseSemaphore(semaphore, 1, &prev);
+ ok( status == STATUS_SUCCESS, "NtReleaseSemaphore failed %08x\n", status );
+ ok( prev == 0, "NtReleaseSemaphore failed, expected 0, got %d\n", prev );
+
+ prev = 0xdeadbeef;
+ status = pNtReleaseSemaphore(semaphore, 1, &prev);
+ ok( status == STATUS_SUCCESS, "NtReleaseSemaphore failed %08x\n", status );
+ ok( prev == 1, "NtReleaseSemaphore failed, expected 1, got %d\n", prev );
+
+ prev = 0xdeadbeef;
+ status = pNtReleaseSemaphore(semaphore, 1, &prev);
+ ok( status == STATUS_SEMAPHORE_LIMIT_EXCEEDED, "NtReleaseSemaphore failed %08x\n", status );
+ ok( prev == 0xdeadbeef, "NtReleaseSemaphore failed, expected 0xdeadbeef, got %d\n", prev );
+
+ memset(&info, 0xcc, sizeof(info));
+ status = pNtQuerySemaphore(semaphore, SemaphoreBasicInformation, &info, sizeof(info), NULL);
+ ok( status == STATUS_SUCCESS, "NtQuerySemaphore failed %08x\n", status );
+ ok( info.CurrentCount == 2, "expected 2, got %d\n", info.CurrentCount );
+ ok( info.MaximumCount == 2, "expected 2, got %d\n", info.MaximumCount );
+
+ NtClose( semaphore );
+}
+
+static void test_wait_on_address(void)
+{
+ SIZE_T size;
+ NTSTATUS status;
+ LARGE_INTEGER start, end, timeout;
+ DWORD elapsed;
+ LONG64 address, compare;
+
+ if (!pRtlWaitOnAddress)
+ {
+ win_skip("RtlWaitOnAddress not supported, skipping test\n");
+ return;
+ }
+
+ if (0) /* crash on Windows */
+ {
+ pRtlWaitOnAddress(&address, NULL, 8, NULL);
+ pRtlWaitOnAddress(NULL, &compare, 8, NULL);
+ pRtlWaitOnAddress(NULL, NULL, 8, NULL);
+ }
+
+ /* don't crash */
+ pRtlWakeAddressSingle(NULL);
+ pRtlWakeAddressAll(NULL);
+
+ /* invalid values */
+ address = 0;
+ compare = 0;
+ status = pRtlWaitOnAddress(&address, &compare, 5, NULL);
+ ok(status == STATUS_INVALID_PARAMETER, "got %x\n", status);
+
+ /* values match */
+ address = 0;
+ compare = 0;
+ pNtQuerySystemTime(&start);
+ timeout.QuadPart = start.QuadPart + 100 * 10000;
+ status = pRtlWaitOnAddress(&address, &compare, 8, &timeout);
+ pNtQuerySystemTime(&end);
+ ok(status == STATUS_TIMEOUT, "got 0x%08x\n", status);
+ elapsed = (end.QuadPart - start.QuadPart) / 10000;
+ ok(90 <= elapsed && elapsed <= 900, "timed out in %u ms\n", elapsed);
+ ok(address == 0, "got %s\n", wine_dbgstr_longlong(address));
+ ok(compare == 0, "got %s\n", wine_dbgstr_longlong(compare));
+
+ /* different address size */
+ for (size = 1; size <= 4; size <<= 1)
+ {
+ compare = ~0;
+ compare <<= size * 8;
+
+ pNtQuerySystemTime(&start);
+ timeout.QuadPart = -100 * 10000;
+ status = pRtlWaitOnAddress(&address, &compare, size, &timeout);
+ pNtQuerySystemTime(&end);
+ ok(status == STATUS_TIMEOUT, "got 0x%08x\n", status);
+ elapsed = (end.QuadPart - start.QuadPart) / 10000;
+ ok(90 <= elapsed && elapsed <= 900, "timed out in %u ms\n", elapsed);
+
+ status = pRtlWaitOnAddress(&address, &compare, size << 1, &timeout);
+ ok(!status, "got 0x%08x\n", status);
+ }
+ address = 0;
+ compare = 1;
+ status = pRtlWaitOnAddress(&address, &compare, 8, NULL);
+ ok(!status, "got 0x%08x\n", status);
+
+ /* no waiters */
+ address = 0;
+ pRtlWakeAddressSingle(&address);
+ ok(address == 0, "got %s\n", wine_dbgstr_longlong(address));
+ pRtlWakeAddressAll(&address);
+ ok(address == 0, "got %s\n", wine_dbgstr_longlong(address));
+}
+
+START_TEST(sync)
+{
+ HMODULE module = GetModuleHandleA("ntdll.dll");
+
+ pNtClose = (void *)GetProcAddress(module, "NtClose");
+ pNtCreateEvent = (void *)GetProcAddress(module, "NtCreateEvent");
+ pNtCreateKeyedEvent = (void *)GetProcAddress(module, "NtCreateKeyedEvent");
+ pNtCreateMutant = (void *)GetProcAddress(module, "NtCreateMutant");
+ pNtCreateSemaphore = (void *)GetProcAddress(module, "NtCreateSemaphore");
+ pNtOpenEvent = (void *)GetProcAddress(module, "NtOpenEvent");
+ pNtOpenKeyedEvent = (void *)GetProcAddress(module, "NtOpenKeyedEvent");
+ pNtPulseEvent = (void *)GetProcAddress(module, "NtPulseEvent");
+ pNtQueryEvent = (void *)GetProcAddress(module, "NtQueryEvent");
+ pNtQueryMutant = (void *)GetProcAddress(module, "NtQueryMutant");
+ pNtQuerySemaphore = (void *)GetProcAddress(module, "NtQuerySemaphore");
+ pNtQuerySystemTime = (void *)GetProcAddress(module, "NtQuerySystemTime");
+ pNtReleaseKeyedEvent = (void *)GetProcAddress(module, "NtReleaseKeyedEvent");
+ pNtReleaseMutant = (void *)GetProcAddress(module, "NtReleaseMutant");
+ pNtReleaseSemaphore = (void *)GetProcAddress(module, "NtReleaseSemaphore");
+ pNtResetEvent = (void *)GetProcAddress(module, "NtResetEvent");
+ pNtSetEvent = (void *)GetProcAddress(module, "NtSetEvent");
+ pNtWaitForKeyedEvent = (void *)GetProcAddress(module, "NtWaitForKeyedEvent");
+ pRtlInitUnicodeString = (void *)GetProcAddress(module, "RtlInitUnicodeString");
+ pRtlWaitOnAddress = (void *)GetProcAddress(module, "RtlWaitOnAddress");
+ pRtlWakeAddressAll = (void *)GetProcAddress(module, "RtlWakeAddressAll");
+ pRtlWakeAddressSingle = (void *)GetProcAddress(module, "RtlWakeAddressSingle");
+
+ test_wait_on_address();
+ test_event();
+ test_mutant();
+ test_semaphore();
+ test_keyed_events();
+}
--
2.33.0
2
2