Wine-devel
Threads by month
- ----- 2026 -----
- March
- February
- January
- ----- 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
[PATCH v3 4/5] msdasql: Implement IDBCreateSession CreateSession
by Alistair Leslie-Hughes 27 Oct '21
by Alistair Leslie-Hughes 27 Oct '21
27 Oct '21
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/msdasql/Makefile.in | 3 +-
dlls/msdasql/msdasql_main.c | 12 +++-
dlls/msdasql/msdasql_private.h | 19 ++++++
dlls/msdasql/session.c | 114 +++++++++++++++++++++++++++++++++
4 files changed, 145 insertions(+), 3 deletions(-)
create mode 100644 dlls/msdasql/msdasql_private.h
create mode 100644 dlls/msdasql/session.c
diff --git a/dlls/msdasql/Makefile.in b/dlls/msdasql/Makefile.in
index 04d9cb29f2a..ee8fa672623 100644
--- a/dlls/msdasql/Makefile.in
+++ b/dlls/msdasql/Makefile.in
@@ -4,7 +4,8 @@ IMPORTS = uuid ole32 oleaut32
EXTRADLLFLAGS = -Wb,--prefer-native
C_SRCS = \
- msdasql_main.c
+ msdasql_main.c \
+ session.c
RC_SRCS = msdasql.rc
diff --git a/dlls/msdasql/msdasql_main.c b/dlls/msdasql/msdasql_main.c
index b6f0c8136e9..0f23d50ae80 100644
--- a/dlls/msdasql/msdasql_main.c
+++ b/dlls/msdasql/msdasql_main.c
@@ -30,6 +30,8 @@
#include "initguid.h"
#include "msdasql.h"
+#include "msdasql_private.h"
+
WINE_DEFAULT_DEBUG_CHANNEL(msdasql);
DEFINE_GUID(DBPROPSET_DBINIT, 0xc8b522bc, 0x5cf3, 0x11ce, 0xad, 0xe5, 0x00, 0xaa, 0x00, 0x44, 0x77, 0x3d);
@@ -435,10 +437,16 @@ static HRESULT WINAPI dbsess_CreateSession(IDBCreateSession *iface, IUnknown *ou
IUnknown **session)
{
struct msdasql *provider = impl_from_IDBCreateSession(iface);
+ HRESULT hr;
- FIXME("%p, outer %p, riid %s, session %p stub\n", provider, outer, debugstr_guid(riid), session);
+ TRACE("%p, outer %p, riid %s, session %p stub\n", provider, outer, debugstr_guid(riid), session);
- return E_FAIL;
+ if (outer)
+ FIXME("outer currently not supported.\n");
+
+ hr = create_db_session(riid, (void**)session);
+
+ return hr;
}
static const struct IDBCreateSessionVtbl dbsess_vtbl =
diff --git a/dlls/msdasql/msdasql_private.h b/dlls/msdasql/msdasql_private.h
new file mode 100644
index 00000000000..a3d73498fe9
--- /dev/null
+++ b/dlls/msdasql/msdasql_private.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2020 Alistair Leslie-Hughes
+ *
+ * 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
+ */
+
+HRESULT create_db_session(REFIID riid, void **unk) DECLSPEC_HIDDEN;
diff --git a/dlls/msdasql/session.c b/dlls/msdasql/session.c
new file mode 100644
index 00000000000..57174be40f8
--- /dev/null
+++ b/dlls/msdasql/session.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2020 Alistair Leslie-Hughes
+ *
+ * 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 "objbase.h"
+#include "rpcproxy.h"
+#include "msdasc.h"
+#include "wine/heap.h"
+#include "wine/debug.h"
+
+#include "msdasql.h"
+
+#include "msdasql_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(msdasql);
+
+struct msdasql_session
+{
+ IUnknown session_iface;
+ LONG refs;
+};
+
+static inline struct msdasql_session *impl_from_IUnknown( IUnknown *iface )
+{
+ return CONTAINING_RECORD( iface, struct msdasql_session, session_iface );
+}
+
+static HRESULT WINAPI session_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
+{
+ struct msdasql_session *session = impl_from_IUnknown( iface );
+
+ TRACE( "%p, %s, %p\n", iface, debugstr_guid(riid), ppv );
+ *ppv = NULL;
+
+ if(IsEqualGUID(&IID_IUnknown, riid))
+ {
+ TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
+ *ppv = &session->session_iface;
+ }
+
+ if(*ppv)
+ {
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+ }
+
+ FIXME("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppv);
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI session_AddRef(IUnknown *iface)
+{
+ struct msdasql_session *session = impl_from_IUnknown( iface );
+ LONG refs = InterlockedIncrement( &session->refs );
+ TRACE( "%p new refcount %d\n", session, refs );
+ return refs;
+}
+
+static ULONG WINAPI session_Release(IUnknown *iface)
+{
+ struct msdasql_session *session = impl_from_IUnknown( iface );
+ LONG refs = InterlockedDecrement( &session->refs );
+ TRACE( "%p new refcount %d\n", session, refs );
+ if (!refs)
+ {
+ TRACE( "destroying %p\n", session );
+ heap_free( session );
+ }
+ return refs;
+}
+
+static const IUnknownVtbl unkfactoryVtbl =
+{
+ session_QueryInterface,
+ session_AddRef,
+ session_Release,
+};
+
+HRESULT create_db_session(REFIID riid, void **unk)
+{
+ struct msdasql_session *session;
+ HRESULT hr;
+
+ session = heap_alloc(sizeof(*session));
+ if (!session)
+ return E_OUTOFMEMORY;
+
+ session->session_iface.lpVtbl = &unkfactoryVtbl;
+ session->refs = 1;
+
+ hr = IUnknown_QueryInterface(&session->session_iface, riid, unk);
+ IUnknown_Release(&session->session_iface);
+ return hr;
+}
--
2.33.0
1
0
27 Oct '21
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/msdasql/msdasql_main.c | 50 +++++++++++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
diff --git a/dlls/msdasql/msdasql_main.c b/dlls/msdasql/msdasql_main.c
index 96a1bc392e2..b6f0c8136e9 100644
--- a/dlls/msdasql/msdasql_main.c
+++ b/dlls/msdasql/msdasql_main.c
@@ -175,6 +175,7 @@ struct msdasql
IUnknown MSDASQL_iface;
IDBProperties IDBProperties_iface;
IDBInitialize IDBInitialize_iface;
+ IDBCreateSession IDBCreateSession_iface;
LONG ref;
};
@@ -194,6 +195,11 @@ static inline struct msdasql *impl_from_IDBInitialize(IDBInitialize *iface)
return CONTAINING_RECORD(iface, struct msdasql, IDBInitialize_iface);
}
+static inline struct msdasql *impl_from_IDBCreateSession(IDBCreateSession *iface)
+{
+ return CONTAINING_RECORD(iface, struct msdasql, IDBCreateSession_iface);
+}
+
static HRESULT WINAPI msdsql_QueryInterface(IUnknown *iface, REFIID riid, void **out)
{
struct msdasql *provider = impl_from_IUnknown(iface);
@@ -213,6 +219,10 @@ static HRESULT WINAPI msdsql_QueryInterface(IUnknown *iface, REFIID riid, void *
{
*out = &provider->IDBInitialize_iface;
}
+ else if (IsEqualGUID(riid, &IID_IDBCreateSession))
+ {
+ *out = &provider->IDBCreateSession_iface;
+ }
else
{
FIXME("(%s, %p)\n", debugstr_guid(riid), out);
@@ -400,6 +410,45 @@ static const struct IDBInitializeVtbl dbinit_vtbl =
dbinit_Uninitialize
};
+static HRESULT WINAPI dbsess_QueryInterface(IDBCreateSession *iface, REFIID riid, void **ppvObject)
+{
+ struct msdasql *provider = impl_from_IDBCreateSession(iface);
+
+ return IUnknown_QueryInterface(&provider->MSDASQL_iface, riid, ppvObject);
+}
+
+static ULONG WINAPI dbsess_AddRef(IDBCreateSession *iface)
+{
+ struct msdasql *provider = impl_from_IDBCreateSession(iface);
+
+ return IUnknown_AddRef(&provider->MSDASQL_iface);
+}
+
+static ULONG WINAPI dbsess_Release(IDBCreateSession *iface)
+{
+ struct msdasql *provider = impl_from_IDBCreateSession(iface);
+
+ return IUnknown_Release(&provider->MSDASQL_iface);
+}
+
+static HRESULT WINAPI dbsess_CreateSession(IDBCreateSession *iface, IUnknown *outer, REFIID riid,
+ IUnknown **session)
+{
+ struct msdasql *provider = impl_from_IDBCreateSession(iface);
+
+ FIXME("%p, outer %p, riid %s, session %p stub\n", provider, outer, debugstr_guid(riid), session);
+
+ return E_FAIL;
+}
+
+static const struct IDBCreateSessionVtbl dbsess_vtbl =
+{
+ dbsess_QueryInterface,
+ dbsess_AddRef,
+ dbsess_Release,
+ dbsess_CreateSession
+};
+
static HRESULT create_msdasql_provider(REFIID riid, void **ppv)
{
struct msdasql *provider;
@@ -412,6 +461,7 @@ static HRESULT create_msdasql_provider(REFIID riid, void **ppv)
provider->MSDASQL_iface.lpVtbl = &msdsql_vtbl;
provider->IDBProperties_iface.lpVtbl = &dbprops_vtbl;
provider->IDBInitialize_iface.lpVtbl = &dbinit_vtbl;
+ provider->IDBCreateSession_iface.lpVtbl = &dbsess_vtbl;
provider->ref = 1;
hr = IUnknown_QueryInterface(&provider->MSDASQL_iface, riid, ppv);
--
2.33.0
1
0
[PATCH v3 2/5] msdasql: Implement IDBProperties GetPropertyInfo
by Alistair Leslie-Hughes 27 Oct '21
by Alistair Leslie-Hughes 27 Oct '21
27 Oct '21
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/msdasql/Makefile.in | 2 +-
dlls/msdasql/msdasql_main.c | 106 +++++++++++++++++++++++++++++++++-
dlls/msdasql/tests/provider.c | 11 +++-
dlls/oledb32/tests/database.c | 8 ++-
4 files changed, 120 insertions(+), 7 deletions(-)
diff --git a/dlls/msdasql/Makefile.in b/dlls/msdasql/Makefile.in
index 8c99c8ea6f0..04d9cb29f2a 100644
--- a/dlls/msdasql/Makefile.in
+++ b/dlls/msdasql/Makefile.in
@@ -1,5 +1,5 @@
MODULE = msdasql.dll
-IMPORTS = uuid
+IMPORTS = uuid ole32 oleaut32
EXTRADLLFLAGS = -Wb,--prefer-native
diff --git a/dlls/msdasql/msdasql_main.c b/dlls/msdasql/msdasql_main.c
index 00dbcec6780..96a1bc392e2 100644
--- a/dlls/msdasql/msdasql_main.c
+++ b/dlls/msdasql/msdasql_main.c
@@ -32,6 +32,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(msdasql);
+DEFINE_GUID(DBPROPSET_DBINIT, 0xc8b522bc, 0x5cf3, 0x11ce, 0xad, 0xe5, 0x00, 0xaa, 0x00, 0x44, 0x77, 0x3d);
+
static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
{
*ppv = NULL;
@@ -100,6 +102,74 @@ HRESULT WINAPI DllGetClassObject( REFCLSID rclsid, REFIID riid, void **ppv )
return CLASS_E_CLASSNOTAVAILABLE;
}
+struct dbproperty
+{
+ const WCHAR *name;
+ DBPROPID id;
+ DBPROPOPTIONS options;
+ VARTYPE type;
+ HRESULT (*convert_dbproperty)(const WCHAR *src, VARIANT *dest);
+};
+
+struct mode_propval
+{
+ const WCHAR *name;
+ DWORD value;
+};
+
+static int __cdecl dbmodeprop_compare(const void *a, const void *b)
+{
+ const WCHAR *src = a;
+ const struct mode_propval *propval = b;
+ return wcsicmp(src, propval->name);
+}
+
+static HRESULT convert_dbproperty_mode(const WCHAR *src, VARIANT *dest)
+{
+ struct mode_propval mode_propvals[] =
+ {
+ { L"Read", DB_MODE_READ },
+ { L"ReadWrite", DB_MODE_READWRITE },
+ { L"Share Deny None", DB_MODE_SHARE_DENY_NONE },
+ { L"Share Deny Read", DB_MODE_SHARE_DENY_READ },
+ { L"Share Deny Write", DB_MODE_SHARE_DENY_WRITE },
+ { L"Share Exclusive", DB_MODE_SHARE_EXCLUSIVE },
+ { L"Write", DB_MODE_WRITE },
+ };
+ struct mode_propval *prop;
+
+ if ((prop = bsearch(src, mode_propvals, ARRAY_SIZE(mode_propvals),
+ sizeof(struct mode_propval), dbmodeprop_compare)))
+ {
+ V_VT(dest) = VT_I4;
+ V_I4(dest) = prop->value;
+ TRACE("%s = %#x\n", debugstr_w(src), prop->value);
+ return S_OK;
+ }
+
+ return E_FAIL;
+}
+
+static const VARTYPE intptr_vartype = (sizeof(void *) == 8 ? VT_I8 : VT_I4);
+
+static const struct dbproperty dbproperties[] =
+{
+ { L"Password", DBPROP_AUTH_PASSWORD, DBPROPOPTIONS_OPTIONAL, VT_BSTR },
+ { L"Persist Security Info", DBPROP_AUTH_PERSIST_SENSITIVE_AUTHINFO, DBPROPOPTIONS_OPTIONAL, VT_BOOL },
+ { L"User ID", DBPROP_AUTH_USERID, DBPROPOPTIONS_OPTIONAL, VT_BSTR },
+ { L"Data Source", DBPROP_INIT_DATASOURCE, DBPROPOPTIONS_REQUIRED, VT_BSTR },
+ { L"Window Handle", DBPROP_INIT_HWND, DBPROPOPTIONS_OPTIONAL, intptr_vartype },
+ { L"Location", DBPROP_INIT_LOCATION, DBPROPOPTIONS_OPTIONAL, VT_BSTR },
+ { L"Mode", DBPROP_INIT_MODE, DBPROPOPTIONS_OPTIONAL, VT_I4, convert_dbproperty_mode },
+ { L"Prompt", DBPROP_INIT_PROMPT, DBPROPOPTIONS_OPTIONAL, VT_I2 },
+ { L"Connect Timeout", DBPROP_INIT_TIMEOUT, DBPROPOPTIONS_OPTIONAL, VT_I4 },
+ { L"Extended Properties", DBPROP_INIT_PROVIDERSTRING, DBPROPOPTIONS_REQUIRED, VT_BSTR },
+ { L"Locale Identifier", DBPROP_INIT_LCID, DBPROPOPTIONS_OPTIONAL, VT_I4 },
+ { L"Initial Catalog", DBPROP_INIT_CATALOG, DBPROPOPTIONS_OPTIONAL, VT_BSTR },
+ { L"OLE DB Services", DBPROP_INIT_OLEDBSERVICES, DBPROPOPTIONS_OPTIONAL, VT_I4 },
+ { L"General Timeout", DBPROP_INIT_GENERALTIMEOUT, DBPROPOPTIONS_OPTIONAL, VT_I4 },
+};
+
struct msdasql
{
IUnknown MSDASQL_iface;
@@ -222,11 +292,43 @@ static HRESULT WINAPI dbprops_GetPropertyInfo(IDBProperties *iface, ULONG cPrope
DBPROPINFOSET **prgPropertyInfoSets, OLECHAR **ppDescBuffer)
{
struct msdasql *provider = impl_from_IDBProperties(iface);
+ int i;
+ DBPROPINFOSET *infoset;
+ int size = 1;
+ OLECHAR *ptr;
- FIXME("(%p)->(%d %p %p %p %p)\n", provider, cPropertyIDSets, rgPropertyIDSets, pcPropertyInfoSets,
+ TRACE("(%p)->(%d %p %p %p %p)\n", provider, cPropertyIDSets, rgPropertyIDSets, pcPropertyInfoSets,
prgPropertyInfoSets, ppDescBuffer);
- return E_NOTIMPL;
+ infoset = CoTaskMemAlloc(sizeof(DBPROPINFOSET));
+ memcpy(&infoset->guidPropertySet, &DBPROPSET_DBINIT, sizeof(GUID));
+ infoset->cPropertyInfos = ARRAY_SIZE(dbproperties);
+ infoset->rgPropertyInfos = CoTaskMemAlloc(sizeof(DBPROPINFO) * ARRAY_SIZE(dbproperties));
+
+ for(i=0; i < ARRAY_SIZE(dbproperties); i++)
+ {
+ size += lstrlenW(dbproperties[i].name) + 1;
+ }
+
+ ptr = *ppDescBuffer = CoTaskMemAlloc(size * sizeof(WCHAR));
+ memset(*ppDescBuffer, 0, size * sizeof(WCHAR));
+
+ for(i=0; i < ARRAY_SIZE(dbproperties); i++)
+ {
+ lstrcpyW(ptr, dbproperties[i].name);
+ infoset->rgPropertyInfos[i].pwszDescription = ptr;
+ infoset->rgPropertyInfos[i].dwPropertyID = dbproperties[i].id;
+ infoset->rgPropertyInfos[i].dwFlags = DBPROPFLAGS_DBINIT | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE;
+ infoset->rgPropertyInfos[i].vtType = dbproperties[i].type;
+ V_VT(&infoset->rgPropertyInfos[i].vValues) = VT_EMPTY;
+
+ ptr += lstrlenW(dbproperties[i].name) + 1;
+ }
+
+ *pcPropertyInfoSets = 1;
+ *prgPropertyInfoSets = infoset;
+
+ return S_OK;
}
static HRESULT WINAPI dbprops_SetProperties(IDBProperties *iface, ULONG cPropertySets,
diff --git a/dlls/msdasql/tests/provider.c b/dlls/msdasql/tests/provider.c
index 96d33f6bd10..2e90d2f848d 100644
--- a/dlls/msdasql/tests/provider.c
+++ b/dlls/msdasql/tests/provider.c
@@ -22,6 +22,7 @@
#include "msdasc.h"
#include "oledb.h"
#include "odbcinst.h"
+#include "wtypes.h"
#include "initguid.h"
@@ -30,10 +31,13 @@
#include "wine/test.h"
DEFINE_GUID(DBPROPSET_DBINITALL, 0xc8b522ca, 0x5cf3, 0x11ce, 0xad, 0xe5, 0x00, 0xaa, 0x00, 0x44, 0x77, 0x3d);
+DEFINE_GUID(DBPROPSET_DBINIT, 0xc8b522bc, 0x5cf3, 0x11ce, 0xad, 0xe5, 0x00, 0xaa, 0x00, 0x44, 0x77, 0x3d);
static BOOL db_created;
static char mdbpath[MAX_PATH];
+static const VARTYPE intptr_vartype = (sizeof(void *) == 8 ? VT_I8 : VT_I4);
+
static void test_Properties(void)
{
HRESULT hr;
@@ -52,16 +56,21 @@ static void test_Properties(void)
infocount = 0;
hr = IDBProperties_GetPropertyInfo(props, 1, &propidset, &infocount, &propinfoset, &desc);
- todo_wine ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
if (hr == S_OK)
{
ULONG i;
+ VARTYPE types[14] = { VT_BSTR, VT_BOOL, VT_BSTR, VT_BSTR, intptr_vartype, VT_BSTR, VT_I4, VT_I2 , VT_I4, VT_BSTR, VT_I4, VT_BSTR, VT_I4, VT_I4 };
+ ok(IsEqualGUID(&propinfoset->guidPropertySet, &DBPROPSET_DBINIT), "got %s\n", debugstr_guid(&propinfoset->guidPropertySet));
ok(propinfoset->cPropertyInfos == 14, "got %d\n", propinfoset->cPropertyInfos);
for (i = 0; i < propinfoset->cPropertyInfos; i++)
{
trace("%d: pwszDescription: %s\n", i, debugstr_w(propinfoset->rgPropertyInfos[i].pwszDescription) );
+ ok(propinfoset->rgPropertyInfos[i].vtType == types[i], "got %d\n", propinfoset->rgPropertyInfos[i].vtType);
+ ok(propinfoset->rgPropertyInfos[i].dwFlags == (DBPROPFLAGS_DBINIT | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE),
+ "got %d\n", propinfoset->rgPropertyInfos[i].dwFlags);
}
for (i = 0; i < propinfoset->cPropertyInfos; i++)
diff --git a/dlls/oledb32/tests/database.c b/dlls/oledb32/tests/database.c
index 3baa91b87a4..775da0f7b61 100644
--- a/dlls/oledb32/tests/database.c
+++ b/dlls/oledb32/tests/database.c
@@ -82,7 +82,7 @@ static void test_GetDataSource(WCHAR *initstring)
EXPECT_REF(dbinit, 2);
EXPECT_REF(props, 2);
hr = IDBProperties_GetPropertyInfo(props, 0, NULL, &cnt, &pInfoset, &ary);
- todo_wine ok(hr == S_OK, "got %08x\n", hr);
+ ok(hr == S_OK, "got %08x\n", hr);
if(hr == S_OK)
{
ULONG i;
@@ -1006,7 +1006,7 @@ static void test_odbc_provider(void)
infocount = 0;
hr = IDBProperties_GetPropertyInfo(props, 1, &propidset, &infocount, &propinfoset, &desc);
- todo_wine ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
if (hr == S_OK)
{
ULONG i;
@@ -1039,7 +1039,8 @@ static void test_odbc_provider(void)
CoTaskMemFree(propinfoset);
hr = IDBProperties_GetProperties(props, 1, &propidlist, &propcnt, &propset);
- ok(hr == S_OK, "got 0x%08x\n", hr);
+ todo_wine ok(hr == S_OK, "got 0x%08x\n", hr);
+ if (hr == S_OK) { /* Remove if, once _GetProperties is implemented */
ok(propidlist.cPropertyIDs == 14, "got %d\n", propinfoset->cPropertyInfos);
for (i = 0; i < propidlist.cPropertyIDs; i++)
@@ -1049,6 +1050,7 @@ static void test_odbc_provider(void)
propidlist.rgPropertyIDs[i] = propinfoset->rgPropertyInfos[i].dwPropertyID;
}
+ }
CoTaskMemFree(propidlist.rgPropertyIDs);
CoTaskMemFree(propset);
--
2.33.0
1
0
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/msdasql/tests/provider.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/dlls/msdasql/tests/provider.c b/dlls/msdasql/tests/provider.c
index 951ab2a7387..96d33f6bd10 100644
--- a/dlls/msdasql/tests/provider.c
+++ b/dlls/msdasql/tests/provider.c
@@ -241,9 +241,22 @@ static void setup_database(void)
static void cleanup_database(void)
{
+ BOOL ret;
+
if (winetest_interactive)
return;
+ ret = SQLConfigDataSource(NULL, ODBC_REMOVE_DSN, "Microsoft Access Driver (*.mdb)", "DSN=wine_test\0\0");
+ if (!ret)
+ {
+ DWORD code;
+ char buffer[1024];
+ WORD size;
+
+ SQLInstallerError(1, &code, buffer, sizeof(buffer), &size);
+ trace("code %d, buffer %s, size %d\n", code, debugstr_a(buffer), size);
+ }
+
DeleteFileA(mdbpath);
}
--
2.33.0
1
0
[PATCH v2 2/5] msdasql: Implement IDBProperties GetPropertyInfo
by Alistair Leslie-Hughes 27 Oct '21
by Alistair Leslie-Hughes 27 Oct '21
27 Oct '21
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/msdasql/Makefile.in | 2 +-
dlls/msdasql/msdasql_main.c | 106 +++++++++++++++++++++++++++++++++-
dlls/msdasql/tests/provider.c | 11 +++-
dlls/oledb32/tests/database.c | 10 ++--
4 files changed, 121 insertions(+), 8 deletions(-)
diff --git a/dlls/msdasql/Makefile.in b/dlls/msdasql/Makefile.in
index 8c99c8ea6f0..04d9cb29f2a 100644
--- a/dlls/msdasql/Makefile.in
+++ b/dlls/msdasql/Makefile.in
@@ -1,5 +1,5 @@
MODULE = msdasql.dll
-IMPORTS = uuid
+IMPORTS = uuid ole32 oleaut32
EXTRADLLFLAGS = -Wb,--prefer-native
diff --git a/dlls/msdasql/msdasql_main.c b/dlls/msdasql/msdasql_main.c
index 00dbcec6780..96a1bc392e2 100644
--- a/dlls/msdasql/msdasql_main.c
+++ b/dlls/msdasql/msdasql_main.c
@@ -32,6 +32,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(msdasql);
+DEFINE_GUID(DBPROPSET_DBINIT, 0xc8b522bc, 0x5cf3, 0x11ce, 0xad, 0xe5, 0x00, 0xaa, 0x00, 0x44, 0x77, 0x3d);
+
static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
{
*ppv = NULL;
@@ -100,6 +102,74 @@ HRESULT WINAPI DllGetClassObject( REFCLSID rclsid, REFIID riid, void **ppv )
return CLASS_E_CLASSNOTAVAILABLE;
}
+struct dbproperty
+{
+ const WCHAR *name;
+ DBPROPID id;
+ DBPROPOPTIONS options;
+ VARTYPE type;
+ HRESULT (*convert_dbproperty)(const WCHAR *src, VARIANT *dest);
+};
+
+struct mode_propval
+{
+ const WCHAR *name;
+ DWORD value;
+};
+
+static int __cdecl dbmodeprop_compare(const void *a, const void *b)
+{
+ const WCHAR *src = a;
+ const struct mode_propval *propval = b;
+ return wcsicmp(src, propval->name);
+}
+
+static HRESULT convert_dbproperty_mode(const WCHAR *src, VARIANT *dest)
+{
+ struct mode_propval mode_propvals[] =
+ {
+ { L"Read", DB_MODE_READ },
+ { L"ReadWrite", DB_MODE_READWRITE },
+ { L"Share Deny None", DB_MODE_SHARE_DENY_NONE },
+ { L"Share Deny Read", DB_MODE_SHARE_DENY_READ },
+ { L"Share Deny Write", DB_MODE_SHARE_DENY_WRITE },
+ { L"Share Exclusive", DB_MODE_SHARE_EXCLUSIVE },
+ { L"Write", DB_MODE_WRITE },
+ };
+ struct mode_propval *prop;
+
+ if ((prop = bsearch(src, mode_propvals, ARRAY_SIZE(mode_propvals),
+ sizeof(struct mode_propval), dbmodeprop_compare)))
+ {
+ V_VT(dest) = VT_I4;
+ V_I4(dest) = prop->value;
+ TRACE("%s = %#x\n", debugstr_w(src), prop->value);
+ return S_OK;
+ }
+
+ return E_FAIL;
+}
+
+static const VARTYPE intptr_vartype = (sizeof(void *) == 8 ? VT_I8 : VT_I4);
+
+static const struct dbproperty dbproperties[] =
+{
+ { L"Password", DBPROP_AUTH_PASSWORD, DBPROPOPTIONS_OPTIONAL, VT_BSTR },
+ { L"Persist Security Info", DBPROP_AUTH_PERSIST_SENSITIVE_AUTHINFO, DBPROPOPTIONS_OPTIONAL, VT_BOOL },
+ { L"User ID", DBPROP_AUTH_USERID, DBPROPOPTIONS_OPTIONAL, VT_BSTR },
+ { L"Data Source", DBPROP_INIT_DATASOURCE, DBPROPOPTIONS_REQUIRED, VT_BSTR },
+ { L"Window Handle", DBPROP_INIT_HWND, DBPROPOPTIONS_OPTIONAL, intptr_vartype },
+ { L"Location", DBPROP_INIT_LOCATION, DBPROPOPTIONS_OPTIONAL, VT_BSTR },
+ { L"Mode", DBPROP_INIT_MODE, DBPROPOPTIONS_OPTIONAL, VT_I4, convert_dbproperty_mode },
+ { L"Prompt", DBPROP_INIT_PROMPT, DBPROPOPTIONS_OPTIONAL, VT_I2 },
+ { L"Connect Timeout", DBPROP_INIT_TIMEOUT, DBPROPOPTIONS_OPTIONAL, VT_I4 },
+ { L"Extended Properties", DBPROP_INIT_PROVIDERSTRING, DBPROPOPTIONS_REQUIRED, VT_BSTR },
+ { L"Locale Identifier", DBPROP_INIT_LCID, DBPROPOPTIONS_OPTIONAL, VT_I4 },
+ { L"Initial Catalog", DBPROP_INIT_CATALOG, DBPROPOPTIONS_OPTIONAL, VT_BSTR },
+ { L"OLE DB Services", DBPROP_INIT_OLEDBSERVICES, DBPROPOPTIONS_OPTIONAL, VT_I4 },
+ { L"General Timeout", DBPROP_INIT_GENERALTIMEOUT, DBPROPOPTIONS_OPTIONAL, VT_I4 },
+};
+
struct msdasql
{
IUnknown MSDASQL_iface;
@@ -222,11 +292,43 @@ static HRESULT WINAPI dbprops_GetPropertyInfo(IDBProperties *iface, ULONG cPrope
DBPROPINFOSET **prgPropertyInfoSets, OLECHAR **ppDescBuffer)
{
struct msdasql *provider = impl_from_IDBProperties(iface);
+ int i;
+ DBPROPINFOSET *infoset;
+ int size = 1;
+ OLECHAR *ptr;
- FIXME("(%p)->(%d %p %p %p %p)\n", provider, cPropertyIDSets, rgPropertyIDSets, pcPropertyInfoSets,
+ TRACE("(%p)->(%d %p %p %p %p)\n", provider, cPropertyIDSets, rgPropertyIDSets, pcPropertyInfoSets,
prgPropertyInfoSets, ppDescBuffer);
- return E_NOTIMPL;
+ infoset = CoTaskMemAlloc(sizeof(DBPROPINFOSET));
+ memcpy(&infoset->guidPropertySet, &DBPROPSET_DBINIT, sizeof(GUID));
+ infoset->cPropertyInfos = ARRAY_SIZE(dbproperties);
+ infoset->rgPropertyInfos = CoTaskMemAlloc(sizeof(DBPROPINFO) * ARRAY_SIZE(dbproperties));
+
+ for(i=0; i < ARRAY_SIZE(dbproperties); i++)
+ {
+ size += lstrlenW(dbproperties[i].name) + 1;
+ }
+
+ ptr = *ppDescBuffer = CoTaskMemAlloc(size * sizeof(WCHAR));
+ memset(*ppDescBuffer, 0, size * sizeof(WCHAR));
+
+ for(i=0; i < ARRAY_SIZE(dbproperties); i++)
+ {
+ lstrcpyW(ptr, dbproperties[i].name);
+ infoset->rgPropertyInfos[i].pwszDescription = ptr;
+ infoset->rgPropertyInfos[i].dwPropertyID = dbproperties[i].id;
+ infoset->rgPropertyInfos[i].dwFlags = DBPROPFLAGS_DBINIT | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE;
+ infoset->rgPropertyInfos[i].vtType = dbproperties[i].type;
+ V_VT(&infoset->rgPropertyInfos[i].vValues) = VT_EMPTY;
+
+ ptr += lstrlenW(dbproperties[i].name) + 1;
+ }
+
+ *pcPropertyInfoSets = 1;
+ *prgPropertyInfoSets = infoset;
+
+ return S_OK;
}
static HRESULT WINAPI dbprops_SetProperties(IDBProperties *iface, ULONG cPropertySets,
diff --git a/dlls/msdasql/tests/provider.c b/dlls/msdasql/tests/provider.c
index 96d33f6bd10..2e90d2f848d 100644
--- a/dlls/msdasql/tests/provider.c
+++ b/dlls/msdasql/tests/provider.c
@@ -22,6 +22,7 @@
#include "msdasc.h"
#include "oledb.h"
#include "odbcinst.h"
+#include "wtypes.h"
#include "initguid.h"
@@ -30,10 +31,13 @@
#include "wine/test.h"
DEFINE_GUID(DBPROPSET_DBINITALL, 0xc8b522ca, 0x5cf3, 0x11ce, 0xad, 0xe5, 0x00, 0xaa, 0x00, 0x44, 0x77, 0x3d);
+DEFINE_GUID(DBPROPSET_DBINIT, 0xc8b522bc, 0x5cf3, 0x11ce, 0xad, 0xe5, 0x00, 0xaa, 0x00, 0x44, 0x77, 0x3d);
static BOOL db_created;
static char mdbpath[MAX_PATH];
+static const VARTYPE intptr_vartype = (sizeof(void *) == 8 ? VT_I8 : VT_I4);
+
static void test_Properties(void)
{
HRESULT hr;
@@ -52,16 +56,21 @@ static void test_Properties(void)
infocount = 0;
hr = IDBProperties_GetPropertyInfo(props, 1, &propidset, &infocount, &propinfoset, &desc);
- todo_wine ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
if (hr == S_OK)
{
ULONG i;
+ VARTYPE types[14] = { VT_BSTR, VT_BOOL, VT_BSTR, VT_BSTR, intptr_vartype, VT_BSTR, VT_I4, VT_I2 , VT_I4, VT_BSTR, VT_I4, VT_BSTR, VT_I4, VT_I4 };
+ ok(IsEqualGUID(&propinfoset->guidPropertySet, &DBPROPSET_DBINIT), "got %s\n", debugstr_guid(&propinfoset->guidPropertySet));
ok(propinfoset->cPropertyInfos == 14, "got %d\n", propinfoset->cPropertyInfos);
for (i = 0; i < propinfoset->cPropertyInfos; i++)
{
trace("%d: pwszDescription: %s\n", i, debugstr_w(propinfoset->rgPropertyInfos[i].pwszDescription) );
+ ok(propinfoset->rgPropertyInfos[i].vtType == types[i], "got %d\n", propinfoset->rgPropertyInfos[i].vtType);
+ ok(propinfoset->rgPropertyInfos[i].dwFlags == (DBPROPFLAGS_DBINIT | DBPROPFLAGS_READ | DBPROPFLAGS_WRITE),
+ "got %d\n", propinfoset->rgPropertyInfos[i].dwFlags);
}
for (i = 0; i < propinfoset->cPropertyInfos; i++)
diff --git a/dlls/oledb32/tests/database.c b/dlls/oledb32/tests/database.c
index 3baa91b87a4..44b783dba85 100644
--- a/dlls/oledb32/tests/database.c
+++ b/dlls/oledb32/tests/database.c
@@ -82,7 +82,7 @@ static void test_GetDataSource(WCHAR *initstring)
EXPECT_REF(dbinit, 2);
EXPECT_REF(props, 2);
hr = IDBProperties_GetPropertyInfo(props, 0, NULL, &cnt, &pInfoset, &ary);
- todo_wine ok(hr == S_OK, "got %08x\n", hr);
+ ok(hr == S_OK, "got %08x\n", hr);
if(hr == S_OK)
{
ULONG i;
@@ -279,7 +279,7 @@ static void test_GetDataSource2(WCHAR *initstring)
dbinit = &dbinittest;
hr = IDataInitialize_GetDataSource(datainit, NULL, CLSCTX_INPROC_SERVER, initstring, &IID_IDBInitialize, (IUnknown**)&dbinit);
- ok(hr == S_OK, "got %08x\n", hr);
+ todo_wine ok(hr == S_OK, "got %08x\n", hr);
IDataInitialize_Release(datainit);
}
@@ -1006,7 +1006,7 @@ static void test_odbc_provider(void)
infocount = 0;
hr = IDBProperties_GetPropertyInfo(props, 1, &propidset, &infocount, &propinfoset, &desc);
- todo_wine ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
if (hr == S_OK)
{
ULONG i;
@@ -1039,7 +1039,8 @@ static void test_odbc_provider(void)
CoTaskMemFree(propinfoset);
hr = IDBProperties_GetProperties(props, 1, &propidlist, &propcnt, &propset);
- ok(hr == S_OK, "got 0x%08x\n", hr);
+ todo_wine ok(hr == S_OK, "got 0x%08x\n", hr);
+ if (hr == S_OK) { /* Remove if, once _GetProperties is implemented */
ok(propidlist.cPropertyIDs == 14, "got %d\n", propinfoset->cPropertyInfos);
for (i = 0; i < propidlist.cPropertyIDs; i++)
@@ -1049,6 +1050,7 @@ static void test_odbc_provider(void)
propidlist.rgPropertyIDs[i] = propinfoset->rgPropertyInfos[i].dwPropertyID;
}
+ }
CoTaskMemFree(propidlist.rgPropertyIDs);
CoTaskMemFree(propset);
--
2.33.0
2
1
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 | 630 +++++++++++++++++++++++++++++++++++
3 files changed, 631 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..3d6b6a3a04d
--- /dev/null
+++ b/dlls/ntdll/tests/sync.c
@@ -0,0 +1,630 @@
+/*
+ * 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)
+{
+ DWORD ticks;
+ SIZE_T size;
+ NTSTATUS status;
+ LARGE_INTEGER timeout;
+ 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(&timeout);
+ timeout.QuadPart += 100*10000;
+ ticks = GetTickCount();
+ status = pRtlWaitOnAddress(&address, &compare, 8, &timeout);
+ ticks = GetTickCount() - ticks;
+ ok(status == STATUS_TIMEOUT, "got 0x%08x\n", status);
+ ok(ticks >= 90 && ticks <= 1000, "got %u\n", ticks);
+ 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;
+
+ timeout.QuadPart = -100 * 10000;
+ ticks = GetTickCount();
+ status = pRtlWaitOnAddress(&address, &compare, size, &timeout);
+ ticks = GetTickCount() - ticks;
+ ok(status == STATUS_TIMEOUT, "got 0x%08x\n", status);
+ ok(ticks >= 90 && ticks <= 1000, "got %u\n", ticks);
+
+ 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
3
27 Oct '21
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/msdasql/msdasql_main.c | 50 +++++++++++++++++++++++++++++++++++
dlls/msdasql/tests/provider.c | 27 +++++++++++++++++++
2 files changed, 77 insertions(+)
diff --git a/dlls/msdasql/msdasql_main.c b/dlls/msdasql/msdasql_main.c
index 0f23d50ae80..76b93ac0490 100644
--- a/dlls/msdasql/msdasql_main.c
+++ b/dlls/msdasql/msdasql_main.c
@@ -178,6 +178,7 @@ struct msdasql
IDBProperties IDBProperties_iface;
IDBInitialize IDBInitialize_iface;
IDBCreateSession IDBCreateSession_iface;
+ IPersist IPersist_iface;
LONG ref;
};
@@ -202,6 +203,11 @@ static inline struct msdasql *impl_from_IDBCreateSession(IDBCreateSession *iface
return CONTAINING_RECORD(iface, struct msdasql, IDBCreateSession_iface);
}
+static inline struct msdasql *impl_from_IPersist( IPersist *iface )
+{
+ return CONTAINING_RECORD( iface, struct msdasql, IPersist_iface );
+}
+
static HRESULT WINAPI msdsql_QueryInterface(IUnknown *iface, REFIID riid, void **out)
{
struct msdasql *provider = impl_from_IUnknown(iface);
@@ -225,6 +231,10 @@ static HRESULT WINAPI msdsql_QueryInterface(IUnknown *iface, REFIID riid, void *
{
*out = &provider->IDBCreateSession_iface;
}
+ else if(IsEqualGUID(&IID_IPersist, riid))
+ {
+ *out = &provider->IPersist_iface;
+ }
else
{
FIXME("(%s, %p)\n", debugstr_guid(riid), out);
@@ -457,6 +467,45 @@ static const struct IDBCreateSessionVtbl dbsess_vtbl =
dbsess_CreateSession
};
+static HRESULT WINAPI persist_QueryInterface(IPersist *iface, REFIID riid, void **ppv)
+{
+ struct msdasql *provider = impl_from_IPersist( iface );
+ return IUnknown_QueryInterface(&provider->MSDASQL_iface, riid, ppv);
+}
+
+static ULONG WINAPI persist_AddRef(IPersist *iface)
+{
+ struct msdasql *provider = impl_from_IPersist( iface );
+ return IUnknown_AddRef(&provider->MSDASQL_iface);
+}
+
+static ULONG WINAPI persist_Release(IPersist *iface)
+{
+ struct msdasql *provider = impl_from_IPersist( iface );
+ return IUnknown_Release(&provider->MSDASQL_iface);
+}
+
+static HRESULT WINAPI persist_GetClassID(IPersist *iface, CLSID *classid)
+{
+ struct msdasql *provider = impl_from_IPersist( iface );
+
+ TRACE("(%p)->(%p)\n", provider, classid);
+
+ if(!classid)
+ return E_INVALIDARG;
+
+ *classid = CLSID_MSDASQL;
+ return S_OK;
+
+}
+
+static const IPersistVtbl persistVtbl = {
+ persist_QueryInterface,
+ persist_AddRef,
+ persist_Release,
+ persist_GetClassID
+};
+
static HRESULT create_msdasql_provider(REFIID riid, void **ppv)
{
struct msdasql *provider;
@@ -470,6 +519,7 @@ static HRESULT create_msdasql_provider(REFIID riid, void **ppv)
provider->IDBProperties_iface.lpVtbl = &dbprops_vtbl;
provider->IDBInitialize_iface.lpVtbl = &dbinit_vtbl;
provider->IDBCreateSession_iface.lpVtbl = &dbsess_vtbl;
+ provider->IPersist_iface.lpVtbl = &persistVtbl;
provider->ref = 1;
hr = IUnknown_QueryInterface(&provider->MSDASQL_iface, riid, ppv);
diff --git a/dlls/msdasql/tests/provider.c b/dlls/msdasql/tests/provider.c
index 2e90d2f848d..4cab6a24daf 100644
--- a/dlls/msdasql/tests/provider.c
+++ b/dlls/msdasql/tests/provider.c
@@ -38,6 +38,32 @@ static char mdbpath[MAX_PATH];
static const VARTYPE intptr_vartype = (sizeof(void *) == 8 ? VT_I8 : VT_I4);
+static void test_msdasql(void)
+{
+ HRESULT hr;
+ IUnknown *unk;
+ IPersist *persist;
+ CLSID classid;
+
+ hr = CoCreateInstance( &CLSID_MSDASQL, NULL, CLSCTX_ALL, &IID_IUnknown, (void **)&unk);
+ ok(hr == S_OK, "Failed to create object 0x%08x\n", hr);
+ if (FAILED(hr))
+ {
+ return;
+ }
+
+ hr = IUnknown_QueryInterface(unk, &IID_IPersist, (void**)&persist);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = IPersist_GetClassID(persist, &classid);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(IsEqualGUID(&classid, &CLSID_MSDASQL), "got %s\n", debugstr_guid(&classid));
+
+ IPersist_Release(persist);
+
+ IUnknown_Release(unk);
+}
+
static void test_Properties(void)
{
HRESULT hr;
@@ -275,6 +301,7 @@ START_TEST(provider)
setup_database();
+ test_msdasql();
test_Properties();
test_sessions();
--
2.33.0
1
0
[PATCH v2 4/5] msdasql: Implement IDBCreateSession CreateSession
by Alistair Leslie-Hughes 27 Oct '21
by Alistair Leslie-Hughes 27 Oct '21
27 Oct '21
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/msdasql/Makefile.in | 3 +-
dlls/msdasql/msdasql_main.c | 12 +++-
dlls/msdasql/msdasql_private.h | 19 ++++++
dlls/msdasql/session.c | 114 +++++++++++++++++++++++++++++++++
4 files changed, 145 insertions(+), 3 deletions(-)
create mode 100644 dlls/msdasql/msdasql_private.h
create mode 100644 dlls/msdasql/session.c
diff --git a/dlls/msdasql/Makefile.in b/dlls/msdasql/Makefile.in
index 04d9cb29f2a..ee8fa672623 100644
--- a/dlls/msdasql/Makefile.in
+++ b/dlls/msdasql/Makefile.in
@@ -4,7 +4,8 @@ IMPORTS = uuid ole32 oleaut32
EXTRADLLFLAGS = -Wb,--prefer-native
C_SRCS = \
- msdasql_main.c
+ msdasql_main.c \
+ session.c
RC_SRCS = msdasql.rc
diff --git a/dlls/msdasql/msdasql_main.c b/dlls/msdasql/msdasql_main.c
index b6f0c8136e9..0f23d50ae80 100644
--- a/dlls/msdasql/msdasql_main.c
+++ b/dlls/msdasql/msdasql_main.c
@@ -30,6 +30,8 @@
#include "initguid.h"
#include "msdasql.h"
+#include "msdasql_private.h"
+
WINE_DEFAULT_DEBUG_CHANNEL(msdasql);
DEFINE_GUID(DBPROPSET_DBINIT, 0xc8b522bc, 0x5cf3, 0x11ce, 0xad, 0xe5, 0x00, 0xaa, 0x00, 0x44, 0x77, 0x3d);
@@ -435,10 +437,16 @@ static HRESULT WINAPI dbsess_CreateSession(IDBCreateSession *iface, IUnknown *ou
IUnknown **session)
{
struct msdasql *provider = impl_from_IDBCreateSession(iface);
+ HRESULT hr;
- FIXME("%p, outer %p, riid %s, session %p stub\n", provider, outer, debugstr_guid(riid), session);
+ TRACE("%p, outer %p, riid %s, session %p stub\n", provider, outer, debugstr_guid(riid), session);
- return E_FAIL;
+ if (outer)
+ FIXME("outer currently not supported.\n");
+
+ hr = create_db_session(riid, (void**)session);
+
+ return hr;
}
static const struct IDBCreateSessionVtbl dbsess_vtbl =
diff --git a/dlls/msdasql/msdasql_private.h b/dlls/msdasql/msdasql_private.h
new file mode 100644
index 00000000000..a3d73498fe9
--- /dev/null
+++ b/dlls/msdasql/msdasql_private.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2020 Alistair Leslie-Hughes
+ *
+ * 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
+ */
+
+HRESULT create_db_session(REFIID riid, void **unk) DECLSPEC_HIDDEN;
diff --git a/dlls/msdasql/session.c b/dlls/msdasql/session.c
new file mode 100644
index 00000000000..57174be40f8
--- /dev/null
+++ b/dlls/msdasql/session.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2020 Alistair Leslie-Hughes
+ *
+ * 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 "objbase.h"
+#include "rpcproxy.h"
+#include "msdasc.h"
+#include "wine/heap.h"
+#include "wine/debug.h"
+
+#include "msdasql.h"
+
+#include "msdasql_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(msdasql);
+
+struct msdasql_session
+{
+ IUnknown session_iface;
+ LONG refs;
+};
+
+static inline struct msdasql_session *impl_from_IUnknown( IUnknown *iface )
+{
+ return CONTAINING_RECORD( iface, struct msdasql_session, session_iface );
+}
+
+static HRESULT WINAPI session_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
+{
+ struct msdasql_session *session = impl_from_IUnknown( iface );
+
+ TRACE( "%p, %s, %p\n", iface, debugstr_guid(riid), ppv );
+ *ppv = NULL;
+
+ if(IsEqualGUID(&IID_IUnknown, riid))
+ {
+ TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
+ *ppv = &session->session_iface;
+ }
+
+ if(*ppv)
+ {
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+ }
+
+ FIXME("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppv);
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI session_AddRef(IUnknown *iface)
+{
+ struct msdasql_session *session = impl_from_IUnknown( iface );
+ LONG refs = InterlockedIncrement( &session->refs );
+ TRACE( "%p new refcount %d\n", session, refs );
+ return refs;
+}
+
+static ULONG WINAPI session_Release(IUnknown *iface)
+{
+ struct msdasql_session *session = impl_from_IUnknown( iface );
+ LONG refs = InterlockedDecrement( &session->refs );
+ TRACE( "%p new refcount %d\n", session, refs );
+ if (!refs)
+ {
+ TRACE( "destroying %p\n", session );
+ heap_free( session );
+ }
+ return refs;
+}
+
+static const IUnknownVtbl unkfactoryVtbl =
+{
+ session_QueryInterface,
+ session_AddRef,
+ session_Release,
+};
+
+HRESULT create_db_session(REFIID riid, void **unk)
+{
+ struct msdasql_session *session;
+ HRESULT hr;
+
+ session = heap_alloc(sizeof(*session));
+ if (!session)
+ return E_OUTOFMEMORY;
+
+ session->session_iface.lpVtbl = &unkfactoryVtbl;
+ session->refs = 1;
+
+ hr = IUnknown_QueryInterface(&session->session_iface, riid, unk);
+ IUnknown_Release(&session->session_iface);
+ return hr;
+}
--
2.33.0
1
0
27 Oct '21
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/msdasql/msdasql_main.c | 50 +++++++++++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
diff --git a/dlls/msdasql/msdasql_main.c b/dlls/msdasql/msdasql_main.c
index 96a1bc392e2..b6f0c8136e9 100644
--- a/dlls/msdasql/msdasql_main.c
+++ b/dlls/msdasql/msdasql_main.c
@@ -175,6 +175,7 @@ struct msdasql
IUnknown MSDASQL_iface;
IDBProperties IDBProperties_iface;
IDBInitialize IDBInitialize_iface;
+ IDBCreateSession IDBCreateSession_iface;
LONG ref;
};
@@ -194,6 +195,11 @@ static inline struct msdasql *impl_from_IDBInitialize(IDBInitialize *iface)
return CONTAINING_RECORD(iface, struct msdasql, IDBInitialize_iface);
}
+static inline struct msdasql *impl_from_IDBCreateSession(IDBCreateSession *iface)
+{
+ return CONTAINING_RECORD(iface, struct msdasql, IDBCreateSession_iface);
+}
+
static HRESULT WINAPI msdsql_QueryInterface(IUnknown *iface, REFIID riid, void **out)
{
struct msdasql *provider = impl_from_IUnknown(iface);
@@ -213,6 +219,10 @@ static HRESULT WINAPI msdsql_QueryInterface(IUnknown *iface, REFIID riid, void *
{
*out = &provider->IDBInitialize_iface;
}
+ else if (IsEqualGUID(riid, &IID_IDBCreateSession))
+ {
+ *out = &provider->IDBCreateSession_iface;
+ }
else
{
FIXME("(%s, %p)\n", debugstr_guid(riid), out);
@@ -400,6 +410,45 @@ static const struct IDBInitializeVtbl dbinit_vtbl =
dbinit_Uninitialize
};
+static HRESULT WINAPI dbsess_QueryInterface(IDBCreateSession *iface, REFIID riid, void **ppvObject)
+{
+ struct msdasql *provider = impl_from_IDBCreateSession(iface);
+
+ return IUnknown_QueryInterface(&provider->MSDASQL_iface, riid, ppvObject);
+}
+
+static ULONG WINAPI dbsess_AddRef(IDBCreateSession *iface)
+{
+ struct msdasql *provider = impl_from_IDBCreateSession(iface);
+
+ return IUnknown_AddRef(&provider->MSDASQL_iface);
+}
+
+static ULONG WINAPI dbsess_Release(IDBCreateSession *iface)
+{
+ struct msdasql *provider = impl_from_IDBCreateSession(iface);
+
+ return IUnknown_Release(&provider->MSDASQL_iface);
+}
+
+static HRESULT WINAPI dbsess_CreateSession(IDBCreateSession *iface, IUnknown *outer, REFIID riid,
+ IUnknown **session)
+{
+ struct msdasql *provider = impl_from_IDBCreateSession(iface);
+
+ FIXME("%p, outer %p, riid %s, session %p stub\n", provider, outer, debugstr_guid(riid), session);
+
+ return E_FAIL;
+}
+
+static const struct IDBCreateSessionVtbl dbsess_vtbl =
+{
+ dbsess_QueryInterface,
+ dbsess_AddRef,
+ dbsess_Release,
+ dbsess_CreateSession
+};
+
static HRESULT create_msdasql_provider(REFIID riid, void **ppv)
{
struct msdasql *provider;
@@ -412,6 +461,7 @@ static HRESULT create_msdasql_provider(REFIID riid, void **ppv)
provider->MSDASQL_iface.lpVtbl = &msdsql_vtbl;
provider->IDBProperties_iface.lpVtbl = &dbprops_vtbl;
provider->IDBInitialize_iface.lpVtbl = &dbinit_vtbl;
+ provider->IDBCreateSession_iface.lpVtbl = &dbsess_vtbl;
provider->ref = 1;
hr = IUnknown_QueryInterface(&provider->MSDASQL_iface, riid, ppv);
--
2.33.0
1
0
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/msdasql/tests/provider.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/dlls/msdasql/tests/provider.c b/dlls/msdasql/tests/provider.c
index 951ab2a7387..96d33f6bd10 100644
--- a/dlls/msdasql/tests/provider.c
+++ b/dlls/msdasql/tests/provider.c
@@ -241,9 +241,22 @@ static void setup_database(void)
static void cleanup_database(void)
{
+ BOOL ret;
+
if (winetest_interactive)
return;
+ ret = SQLConfigDataSource(NULL, ODBC_REMOVE_DSN, "Microsoft Access Driver (*.mdb)", "DSN=wine_test\0\0");
+ if (!ret)
+ {
+ DWORD code;
+ char buffer[1024];
+ WORD size;
+
+ SQLInstallerError(1, &code, buffer, sizeof(buffer), &size);
+ trace("code %d, buffer %s, size %d\n", code, debugstr_a(buffer), size);
+ }
+
DeleteFileA(mdbpath);
}
--
2.33.0
1
0