Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/msado15/Makefile.in | 1 +
dlls/msado15/command.c | 388 +++++++++++++++++++++++++++++++
dlls/msado15/main.c | 5 +
dlls/msado15/msado15_classes.idl | 8 +
dlls/msado15/msado15_private.h | 1 +
dlls/msado15/tests/msado15.c | 28 +++
6 files changed, 431 insertions(+)
create mode 100644 dlls/msado15/command.c
diff --git a/dlls/msado15/Makefile.in b/dlls/msado15/Makefile.in
index 604f9ff018..9852e0863d 100644
--- a/dlls/msado15/Makefile.in
+++ b/dlls/msado15/Makefile.in
@@ -4,6 +4,7 @@ IMPORTS = oleaut32
EXTRADLLFLAGS = -mno-cygwin
C_SRCS = \
+ command.c \
connection.c \
main.c \
recordset.c \
diff --git a/dlls/msado15/command.c b/dlls/msado15/command.c
new file mode 100644
index 0000000000..9856b52e91
--- /dev/null
+++ b/dlls/msado15/command.c
@@ -0,0 +1,388 @@
+/*
+ * Copyright 2019 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
+ */
+#include <stdarg.h>
+#include "windef.h"
+#include "winbase.h"
+#define COBJMACROS
+#include "objbase.h"
+#include "msado15_backcompat.h"
+
+#include "wine/debug.h"
+#include "wine/heap.h"
+
+#include "msado15_private.h"
+#include "msado15_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(msado);
+
+struct command
+{
+ _Command Command_iface;
+
+ LONG ref;
+};
+
+
+static inline struct command *impl_from_Command(_Command *iface)
+{
+ return CONTAINING_RECORD(iface, struct command, Command_iface);
+}
+
+static HRESULT WINAPI command_QueryInterface(_Command *iface, REFIID riid, void **out)
+{
+ struct command *command = impl_from_Command(iface);
+ TRACE("(%p)->(%s, %p)\n", command, debugstr_guid(riid), out);
+
+ *out = NULL;
+
+ if (IsEqualIID(riid, &IID_IUnknown) ||
+ IsEqualIID(riid, &IID_IDispatch) ||
+ IsEqualIID(riid, &IID__ADO) ||
+ IsEqualIID(riid, &IID_Command15) ||
+ IsEqualIID(riid, &IID_Command25) ||
+ IsEqualIID(riid, &IID__Command))
+ {
+ *out = iface;
+ }
+ else
+ {
+ FIXME("interface %s not implemented\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+ }
+
+ _Command_AddRef(iface);
+ return S_OK;
+}
+
+static ULONG WINAPI command_AddRef(_Command *iface)
+{
+ struct command *command = impl_from_Command(iface);
+ TRACE("(%p)\n", command);
+
+ return InterlockedIncrement(&command->ref);
+}
+
+static ULONG WINAPI command_Release(_Command *iface)
+{
+ struct command *command = impl_from_Command(iface);
+ LONG ref;
+
+ TRACE("(%p)\n", command);
+
+ ref = InterlockedDecrement(&command->ref);
+ if (!ref)
+ heap_free(command);
+
+ return ref;
+}
+
+static HRESULT WINAPI command_GetTypeInfoCount(_Command *iface, UINT *pctinfo)
+{
+ struct command *command = impl_from_Command(iface);
+ TRACE("(%p)->()\n", command);
+
+ *pctinfo = 1;
+ return S_OK;
+}
+
+static HRESULT WINAPI command_GetTypeInfo(_Command *iface, UINT iTInfo, LCID lcid, ITypeInfo **typeinfo)
+{
+ struct command *command = impl_from_Command(iface);
+ FIXME("(%p)->(%u %u %p)\n", command, iTInfo, lcid, typeinfo);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_GetIDsOfNames(_Command *iface, REFIID riid, LPOLESTR *rgszNames,
+ UINT cNames, LCID lcid, DISPID *rgDispId)
+{
+ struct command *command = impl_from_Command(iface);
+ FIXME("(%p)->(%s %p %u %u %p)\n", command, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_Invoke(_Command *iface, DISPID dispIdMember, REFIID riid,
+ LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
+ UINT *puArgErr)
+{
+ struct command *command = impl_from_Command(iface);
+ FIXME("(%p)->(%d %s %d %d %p %p %p %p)\n", command, dispIdMember, debugstr_guid(riid),
+ lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_get_Properties(_Command *iface, Properties **props)
+{
+ struct command *command = impl_from_Command(iface);
+ FIXME("(%p)->(%p)\n", command, props);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_get_ActiveConnection(_Command *iface, _Connection **connection)
+{
+ struct command *command = impl_from_Command(iface);
+ FIXME("(%p)->(%p)\n", command, connection);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_putref_ActiveConnection(_Command *iface, _Connection *connection)
+{
+ struct command *command = impl_from_Command(iface);
+ FIXME("(%p)->(%p)\n", command, connection);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_put_ActiveConnection(_Command *iface, VARIANT connection)
+{
+ struct command *command = impl_from_Command(iface);
+ FIXME("(%p)->()\n", command);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_get_CommandText(_Command *iface, BSTR *text)
+{
+ struct command *command = impl_from_Command(iface);
+ FIXME("(%p)->(%p)\n", command, text);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_put_CommandText(_Command *iface, BSTR text)
+{
+ struct command *command = impl_from_Command(iface);
+ FIXME("(%p)->(%s)\n", command, debugstr_w(text));
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_get_CommandTimeout(_Command *iface, LONG *timeout)
+{
+ struct command *command = impl_from_Command(iface);
+ FIXME("(%p)->(%p)\n", command, timeout);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_put_CommandTimeout(_Command *iface, LONG timeout)
+{
+ struct command *command = impl_from_Command(iface);
+ FIXME("(%p)->(%d)\n", command, timeout);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_get_Prepared(_Command *iface, VARIANT_BOOL *prepared)
+{
+ struct command *command = impl_from_Command(iface);
+ FIXME("(%p)->(%p)\n", command, prepared);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_put_Prepared(_Command *iface, VARIANT_BOOL prepared)
+{
+ struct command *command = impl_from_Command(iface);
+ FIXME("(%p)->(%d)\n", command, prepared);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_Execute(_Command *iface, VARIANT *recordsaffected, VARIANT *parameters,
+ LONG options, _Recordset **recordset)
+{
+ struct command *command = impl_from_Command(iface);
+ FIXME("(%p)->(%p %p %d %p)\n", command, recordsaffected, parameters, options, recordset);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_CreateParameter(_Command *iface, BSTR name, DataTypeEnum type,
+ ParameterDirectionEnum direction, LONG size, VARIANT value, _Parameter **parameter)
+{
+ struct command *command = impl_from_Command(iface);
+ FIXME("(%p)->(%s %d %d %d %p)\n", command, debugstr_w(name), type, direction, size,
+ parameter);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_get_Parameters(_Command *iface, Parameters **parameters)
+{
+ struct command *command = impl_from_Command(iface);
+ FIXME("(%p)->(%p)\n", command, parameters);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_put_CommandType(_Command *iface, CommandTypeEnum cmdtype)
+{
+ struct command *command = impl_from_Command(iface);
+ FIXME("(%p)->(%d)\n", command, cmdtype);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_get_CommandType(_Command *iface, CommandTypeEnum *cmdtype)
+{
+ struct command *command = impl_from_Command(iface);
+ FIXME("(%p)->(%p)\n", command, cmdtype);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_get_Name(_Command *iface, BSTR *name)
+{
+ struct command *command = impl_from_Command(iface);
+ FIXME("(%p)->(%p)\n", command, name);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_put_Name(_Command *iface, BSTR name)
+{
+ struct command *command = impl_from_Command(iface);
+ FIXME("(%p)->(%s)\n", command, debugstr_w(name));
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_get_State(_Command *iface, LONG *state)
+{
+ struct command *command = impl_from_Command(iface);
+ FIXME("(%p)->(%p)\n", command, state);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_Cancel(_Command *iface)
+{
+ struct command *command = impl_from_Command(iface);
+ FIXME("(%p)->()\n", command);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_putref_CommandStream(_Command *iface, IUnknown *stream)
+{
+ struct command *command = impl_from_Command(iface);
+ FIXME("(%p)->(%p)\n", command, stream);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_get_CommandStream(_Command *iface, VARIANT *stream)
+{
+ struct command *command = impl_from_Command(iface);
+ FIXME("(%p)->(%p)\n", command, stream);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_put_Dialect(_Command *iface, BSTR dialect)
+{
+ struct command *command = impl_from_Command(iface);
+ FIXME("(%p)->(%s)\n", command, debugstr_w(dialect));
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_get_Dialect(_Command *iface, BSTR *dialect)
+{
+ struct command *command = impl_from_Command(iface);
+ FIXME("(%p)->(%p)\n", command, dialect);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_put_NamedParameters(_Command *iface, VARIANT_BOOL namedparameters)
+{
+ struct command *command = impl_from_Command(iface);
+ FIXME("(%p)->(%d)\n", command, namedparameters);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI command_get_NamedParameters(_Command *iface, VARIANT_BOOL *namedparameters)
+{
+ struct command *command = impl_from_Command(iface);
+ FIXME("(%p)->(%p)\n", command, namedparameters);
+
+ return E_NOTIMPL;
+}
+
+static const struct _CommandVtbl command_vtbl =
+{
+ command_QueryInterface,
+ command_AddRef,
+ command_Release,
+ command_GetTypeInfoCount,
+ command_GetTypeInfo,
+ command_GetIDsOfNames,
+ command_Invoke,
+ command_get_Properties,
+ command_get_ActiveConnection,
+ command_putref_ActiveConnection,
+ command_put_ActiveConnection,
+ command_get_CommandText,
+ command_put_CommandText,
+ command_get_CommandTimeout,
+ command_put_CommandTimeout,
+ command_get_Prepared,
+ command_put_Prepared,
+ command_Execute,
+ command_CreateParameter,
+ command_get_Parameters,
+ command_put_CommandType,
+ command_get_CommandType,
+ command_get_Name,
+ command_put_Name,
+ command_get_State,
+ command_Cancel,
+ command_putref_CommandStream,
+ command_get_CommandStream,
+ command_put_Dialect,
+ command_get_Dialect,
+ command_put_NamedParameters,
+ command_get_NamedParameters
+};
+
+HRESULT Command_create( void **out )
+{
+ struct command *command;
+
+ TRACE("(%p)\n", out);
+
+ *out = NULL;
+
+ command = heap_alloc(sizeof(*command));
+ if (!command)
+ return E_OUTOFMEMORY;
+
+ command->Command_iface.lpVtbl = &command_vtbl;
+ command->ref = 1;
+
+ *out = &command->Command_iface;
+
+ return S_OK;
+}
diff --git a/dlls/msado15/main.c b/dlls/msado15/main.c
index 32ae252337..3115474b84 100644
--- a/dlls/msado15/main.c
+++ b/dlls/msado15/main.c
@@ -117,6 +117,7 @@ static const struct IClassFactoryVtbl msadocf_vtbl =
msadocf_LockServer
};
+static struct msadocf command_cf = { { &msadocf_vtbl }, Command_create };
static struct msadocf connection_cf = { { &msadocf_vtbl }, Connection_create };
static struct msadocf recordset_cf = { { &msadocf_vtbl }, Recordset_create };
static struct msadocf stream_cf = { { &msadocf_vtbl }, Stream_create };
@@ -142,6 +143,10 @@ HRESULT WINAPI DllGetClassObject( REFCLSID clsid, REFIID iid, void **obj )
{
cf = &stream_cf.IClassFactory_iface;
}
+ else if (IsEqualGUID( clsid, &CLSID_Command ))
+ {
+ cf = &command_cf.IClassFactory_iface;
+ }
if (!cf) return CLASS_E_CLASSNOTAVAILABLE;
return IClassFactory_QueryInterface( cf, iid, obj );
}
diff --git a/dlls/msado15/msado15_classes.idl b/dlls/msado15/msado15_classes.idl
index 5ede180240..51f8bd77db 100644
--- a/dlls/msado15/msado15_classes.idl
+++ b/dlls/msado15/msado15_classes.idl
@@ -18,6 +18,14 @@
#pragma makedep register
+[
+ threading(apartment),
+ progid("ADODB.Command.6.0"),
+ vi_progid("ADODB.Command"),
+ uuid(00000507-0000-0010-8000-00aa006d2ea4)
+]
+coclass Command { interface _Command; }
+
[
threading(apartment),
progid("ADODB.Connection.6.0"),
diff --git a/dlls/msado15/msado15_private.h b/dlls/msado15/msado15_private.h
index 7239e48b53..f6c60f0304 100644
--- a/dlls/msado15/msado15_private.h
+++ b/dlls/msado15/msado15_private.h
@@ -21,6 +21,7 @@
#define MAKE_ADO_HRESULT( err ) MAKE_HRESULT( SEVERITY_ERROR, FACILITY_CONTROL, err )
+HRESULT Command_create( void ** ) DECLSPEC_HIDDEN;
HRESULT Connection_create( void ** ) DECLSPEC_HIDDEN;
HRESULT Recordset_create( void ** ) DECLSPEC_HIDDEN;
HRESULT Stream_create( void ** ) DECLSPEC_HIDDEN;
diff --git a/dlls/msado15/tests/msado15.c b/dlls/msado15/tests/msado15.c
index 5a1813694b..7850c45231 100644
--- a/dlls/msado15/tests/msado15.c
+++ b/dlls/msado15/tests/msado15.c
@@ -444,6 +444,33 @@ if (0) /* Crashes on windows */
_Connection_Release(connection);
}
+static void test_Command(void)
+{
+ HRESULT hr;
+ _Command *command;
+ _ADO *ado;
+ Command15 *command15;
+ Command25 *command25;
+
+ hr = CoCreateInstance(&CLSID_Command, NULL, CLSCTX_INPROC_SERVER,
+ &IID__Command, (void**)&command);
+ ok( hr == S_OK, "got %08x\n", hr );
+
+ hr = _Command_QueryInterface(command, &IID__ADO, (void**)&ado);
+ ok( hr == S_OK, "got %08x\n", hr );
+ _ADO_Release(ado);
+
+ hr = _Command_QueryInterface(command, &IID_Command15, (void**)&command15);
+ ok( hr == S_OK, "got %08x\n", hr );
+ Command15_Release(command15);
+
+ hr = _Command_QueryInterface(command, &IID_Command25, (void**)&command25);
+ ok( hr == S_OK, "got %08x\n", hr );
+ Command25_Release(command25);
+
+ _Command_Release(command);
+}
+
START_TEST(msado15)
{
CoInitialize( NULL );
@@ -451,5 +478,6 @@ START_TEST(msado15)
test_Fields();
test_Recordset();
test_Stream();
+ test_Command();
CoUninitialize();
}
--
2.17.1