/* * 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 #include "windef.h" #include "winbase.h" #define COBJMACROS #include "objbase.h" #include "msdasc.h" #include "msado15_backcompat.h" #include "wine/debug.h" #include "wine/heap.h" #include "msado15_private.h" WINE_DEFAULT_DEBUG_CHANNEL(msado15); struct command { _Command Command_iface; LONG ref; CommandTypeEnum type; BSTR text; _Connection *connection; }; 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 **obj ) { TRACE( "%p, %s, %p\n", iface, debugstr_guid(riid), obj ); *obj = 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)) { *obj = 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 ); return InterlockedIncrement( &command->ref ); } static ULONG WINAPI command_Release( _Command *iface ) { struct command *command = impl_from_Command( iface ); LONG ref = InterlockedDecrement( &command->ref ); if (!ref) { TRACE( "destroying %p\n", command ); if (command->connection) _Connection_Release(command->connection); heap_free( command->text ); heap_free( command ); } return ref; } static HRESULT WINAPI command_GetTypeInfoCount( _Command *iface, UINT *count ) { struct command *command = impl_from_Command( iface ); TRACE( "%p, %p\n", command, count ); *count = 1; return S_OK; } static HRESULT WINAPI command_GetTypeInfo( _Command *iface, UINT index, LCID lcid, ITypeInfo **info ) { struct command *command = impl_from_Command( iface ); TRACE( "%p, %u, %u, %p\n", command, index, lcid, info ); return get_typeinfo(Command_tid, info); } static HRESULT WINAPI command_GetIDsOfNames( _Command *iface, REFIID riid, LPOLESTR *names, UINT count, LCID lcid, DISPID *dispid ) { struct command *command = impl_from_Command( iface ); HRESULT hr; ITypeInfo *typeinfo; TRACE( "%p, %s, %p, %u, %u, %p\n", command, debugstr_guid(riid), names, count, lcid, dispid ); hr = get_typeinfo(Command_tid, &typeinfo); if(SUCCEEDED(hr)) { hr = ITypeInfo_GetIDsOfNames(typeinfo, names, count, dispid); ITypeInfo_Release(typeinfo); } return hr; } static HRESULT WINAPI command_Invoke( _Command *iface, DISPID member, REFIID riid, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *excep_info, UINT *arg_err ) { struct command *command = impl_from_Command( iface ); HRESULT hr; ITypeInfo *typeinfo; TRACE( "%p, %d, %s, %d, %d, %p, %p, %p, %p\n", command, member, debugstr_guid(riid), lcid, flags, params, result, excep_info, arg_err ); hr = get_typeinfo(Command_tid, &typeinfo); if(SUCCEEDED(hr)) { hr = ITypeInfo_Invoke(typeinfo, &command->Command_iface, member, flags, params, result, excep_info, arg_err); ITypeInfo_Release(typeinfo); } return hr; } static HRESULT WINAPI command_get_Properties( _Command *iface, Properties **props ) { FIXME( "%p, %p\n", iface, props ); return E_NOTIMPL; } static HRESULT WINAPI command_get_ActiveConnection( _Command *iface, _Connection **connection ) { struct command *command = impl_from_Command( iface ); TRACE( "%p, %p\n", iface, connection ); *connection = command->connection; if (command->connection) _Connection_AddRef(command->connection); return S_OK; } static HRESULT WINAPI command_putref_ActiveConnection( _Command *iface, _Connection *connection ) { struct command *command = impl_from_Command( iface ); TRACE( "%p, %p\n", iface, connection ); if (command->connection) _Connection_Release(command->connection); command->connection = connection; if (command->connection) _Connection_AddRef(command->connection); return S_OK; } static HRESULT WINAPI command_put_ActiveConnection( _Command *iface, VARIANT connection ) { FIXME( "%p, %s\n", iface, debugstr_variant(&connection) ); return E_NOTIMPL; } static HRESULT WINAPI command_get_CommandText( _Command *iface, BSTR *text ) { struct command *command = impl_from_Command( iface ); BSTR cmd_text = NULL; TRACE( "%p, %p\n", command, text ); if (command->text && !(cmd_text = SysAllocString( command->text ))) return E_OUTOFMEMORY; *text = cmd_text; return S_OK; } static HRESULT WINAPI command_put_CommandText( _Command *iface, BSTR text ) { struct command *command = impl_from_Command( iface ); WCHAR *source = NULL; TRACE( "%p, %s\n", command, debugstr_w( text ) ); if (text && !(source = strdupW( text ))) return E_OUTOFMEMORY; heap_free( command->text ); command->text = source; return S_OK; } static HRESULT WINAPI command_get_CommandTimeout( _Command *iface, LONG *timeout ) { FIXME( "%p, %p\n", iface, timeout ); return E_NOTIMPL; } static HRESULT WINAPI command_put_CommandTimeout( _Command *iface, LONG timeout ) { FIXME( "%p, %d\n", iface, timeout ); return E_NOTIMPL; } static HRESULT WINAPI command_get_Prepared( _Command *iface, VARIANT_BOOL *prepared ) { FIXME( "%p, %p\n", iface, prepared ); return E_NOTIMPL; } static HRESULT WINAPI command_put_Prepared( _Command *iface, VARIANT_BOOL prepared ) { FIXME( "%p, %d\n", iface, prepared ); return E_NOTIMPL; } static HRESULT WINAPI command_Execute( _Command *iface, VARIANT *affected, VARIANT *parameters, LONG options, _Recordset **recordset ) { FIXME( "%p, %p, %p, %d, %p\n", iface, affected, 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 ) { FIXME( "%p, %s, %d, %d, %d, %p\n", iface, debugstr_w(name), type, direction, size, parameter ); return E_NOTIMPL; } static HRESULT WINAPI command_get_Parameters( _Command *iface, Parameters **parameters ) { FIXME( "%p, %p\n", iface, parameters ); return E_NOTIMPL; } static HRESULT WINAPI command_put_CommandType( _Command *iface, CommandTypeEnum type ) { struct command *command = impl_from_Command( iface ); TRACE( "%p, %d\n", iface, type ); switch (type) { case adCmdUnspecified: case adCmdUnknown: case adCmdText: case adCmdTable: case adCmdStoredProc: case adCmdFile: case adCmdTableDirect: command->type = type; return S_OK; } return MAKE_ADO_HRESULT( adErrInvalidArgument ); } static HRESULT WINAPI command_get_CommandType( _Command *iface, CommandTypeEnum *type ) { struct command *command = impl_from_Command( iface ); TRACE( "%p, %p\n", iface, type ); *type = command->type; return S_OK; } static HRESULT WINAPI command_get_Name(_Command *iface, BSTR *name) { FIXME( "%p, %p\n", iface, name ); return E_NOTIMPL; } static HRESULT WINAPI command_put_Name( _Command *iface, BSTR name ) { FIXME( "%p, %s\n", iface, debugstr_w(name) ); return E_NOTIMPL; } static HRESULT WINAPI command_get_State( _Command *iface, LONG *state ) { FIXME( "%p, %p\n", iface, state ); return E_NOTIMPL; } static HRESULT WINAPI command_Cancel( _Command *iface ) { FIXME( "%p\n", iface ); return E_NOTIMPL; } static HRESULT WINAPI command_putref_CommandStream( _Command *iface, IUnknown *stream ) { FIXME( "%p, %p\n", iface, stream ); return E_NOTIMPL; } static HRESULT WINAPI command_get_CommandStream( _Command *iface, VARIANT *stream ) { FIXME( "%p, %p\n", iface, stream ); return E_NOTIMPL; } static HRESULT WINAPI command_put_Dialect( _Command *iface, BSTR dialect ) { FIXME( "%p, %s\n", iface, debugstr_w(dialect) ); return E_NOTIMPL; } static HRESULT WINAPI command_get_Dialect( _Command *iface, BSTR *dialect ) { FIXME( "%p, %p\n", iface, dialect ); return E_NOTIMPL; } static HRESULT WINAPI command_put_NamedParameters( _Command *iface, VARIANT_BOOL parameters ) { FIXME( "%p, %d\n", iface, parameters ); return E_NOTIMPL; } static HRESULT WINAPI command_get_NamedParameters( _Command *iface, VARIANT_BOOL *parameters ) { FIXME( "%p, %p\n", iface, parameters ); 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 **obj ) { struct command *command; if (!(command = heap_alloc( sizeof(*command) ))) return E_OUTOFMEMORY; command->Command_iface.lpVtbl = &command_vtbl; command->type = adCmdUnknown; command->text = NULL; command->connection = NULL; command->ref = 1; *obj = &command->Command_iface; TRACE( "returning iface %p\n", *obj ); return S_OK; }