--- vendor/wine/dlls/oleaut32/current/connpt.c 2004-12-31 15:20:48 UTC (rev 12575)
+++ vendor/wine/dlls/oleaut32/current/connpt.c 2004-12-31 15:25:53 UTC (rev 12576)
@@ -0,0 +1,632 @@
+/*
+ * Implementation of a generic ConnectionPoint object.
+ *
+ * Copyright 2000 Huw D M Davies for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * NOTES:
+ * See one exported function here is CreateConnectionPoint, see
+ * comments just above that function for information.
+ */
+
+#include <assert.h>
+#include <stdarg.h>
+#include <string.h>
+
+#define COBJMACROS
+
+#include "winerror.h"
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "ole2.h"
+#include "olectl.h"
+#include "connpt.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(ole);
+
+#define MAXSINKS 10
+
+/************************************************************************
+ * Implementation of IConnectionPoint
+ */
+typedef struct ConnectionPointImpl {
+
+ IConnectionPointVtbl *lpvtbl;
+
+ /* IUnknown of our main object*/
+ IUnknown *Obj;
+
+ /* Reference count */
+ DWORD ref;
+
+ /* IID of sink interface */
+ IID iid;
+
+ /* Array of sink IUnknowns */
+ IUnknown **sinks;
+ DWORD maxSinks;
+
+ DWORD nSinks;
+} ConnectionPointImpl;
+
+static IConnectionPointVtbl ConnectionPointImpl_VTable;
+
+
+/************************************************************************
+ * Implementation of IEnumConnections
+ */
+typedef struct EnumConnectionsImpl {
+
+ IEnumConnectionsVtbl *lpvtbl;
+
+ DWORD ref;
+
+ /* IUnknown of ConnectionPoint, used for ref counting */
+ IUnknown *pUnk;
+
+ /* Connection Data */
+ CONNECTDATA *pCD;
+ DWORD nConns;
+
+ /* Next connection to enumerate from */
+ DWORD nCur;
+
+} EnumConnectionsImpl;
+
+static EnumConnectionsImpl *EnumConnectionsImpl_Construct(IUnknown *pUnk,
+ DWORD nSinks,
+ CONNECTDATA *pCD);
+
+
+/************************************************************************
+ * ConnectionPointImpl_Construct
+ */
+static ConnectionPointImpl *ConnectionPointImpl_Construct(IUnknown *pUnk,
+ REFIID riid)
+{
+ ConnectionPointImpl *Obj;
+
+ Obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj));
+ Obj->lpvtbl = &ConnectionPointImpl_VTable;
+ Obj->Obj = pUnk;
+ Obj->ref = 1;
+ Obj->iid = *riid;
+ Obj->maxSinks = MAXSINKS;
+ Obj->sinks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof(IUnknown*) * MAXSINKS);
+ Obj->nSinks = 0;
+ return Obj;
+}
+
+/************************************************************************
+ * ConnectionPointImpl_Destroy
+ */
+static void ConnectionPointImpl_Destroy(ConnectionPointImpl *Obj)
+{
+ DWORD i;
+ for(i = 0; i < Obj->maxSinks; i++) {
+ if(Obj->sinks[i]) {
+ IUnknown_Release(Obj->sinks[i]);
+ Obj->sinks[i] = NULL;
+ }
+ }
+ HeapFree(GetProcessHeap(), 0, Obj->sinks);
+ HeapFree(GetProcessHeap(), 0, Obj);
+ return;
+}
+
+static ULONG WINAPI ConnectionPointImpl_AddRef(IConnectionPoint* iface);
+/************************************************************************
+ * ConnectionPointImpl_QueryInterface (IUnknown)
+ *
+ * See Windows documentation for more details on IUnknown methods.
+ */
+static HRESULT WINAPI ConnectionPointImpl_QueryInterface(
+ IConnectionPoint* iface,
+ REFIID riid,
+ void** ppvObject)
+{
+ ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
+ TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
+
+ /*
+ * Perform a sanity check on the parameters.
+ */
+ if ( (This==0) || (ppvObject==0) )
+ return E_INVALIDARG;
+
+ /*
+ * Initialize the return parameter.
+ */
+ *ppvObject = 0;
+
+ /*
+ * Compare the riid with the interface IDs implemented by this object.
+ */
+ if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
+ {
+ *ppvObject = (IConnectionPoint*)This;
+ }
+ else if (memcmp(&IID_IConnectionPoint, riid, sizeof(IID_IConnectionPoint)) == 0)
+ {
+ *ppvObject = (IConnectionPoint*)This;
+ }
+
+ /*
+ * Check that we obtained an interface.
+ */
+ if ((*ppvObject)==0)
+ {
+ FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
+ return E_NOINTERFACE;
+ }
+
+ /*
+ * Query Interface always increases the reference count by one when it is
+ * successful
+ */
+ ConnectionPointImpl_AddRef((IConnectionPoint*)This);
+
+ return S_OK;
+}
+
+
+/************************************************************************
+ * ConnectionPointImpl_AddRef (IUnknown)
+ *
+ * See Windows documentation for more details on IUnknown methods.
+ */
+static ULONG WINAPI ConnectionPointImpl_AddRef(IConnectionPoint* iface)
+{
+ ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
+ TRACE("(%p)->(ref=%ld)\n", This, This->ref);
+ return InterlockedIncrement(&This->ref);
+}
+
+/************************************************************************
+ * ConnectionPointImpl_Release (IUnknown)
+ *
+ * See Windows documentation for more details on IUnknown methods.
+ */
+static ULONG WINAPI ConnectionPointImpl_Release(
+ IConnectionPoint* iface)
+{
+ ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
+ ULONG ref;
+ TRACE("(%p)->(ref=%ld)\n", This, This->ref);
+
+ /*
+ * Decrease the reference count on this object.
+ */
+ ref = InterlockedDecrement(&This->ref);
+
+ /*
+ * If the reference count goes down to 0, perform suicide.
+ */
+ if (ref == 0) ConnectionPointImpl_Destroy(This);
+
+ return ref;
+}
+
+/************************************************************************
+ * ConnectionPointImpl_GetConnectionInterface (IConnectionPoint)
+ *
+ */
+static HRESULT WINAPI ConnectionPointImpl_GetConnectionInterface(
+ IConnectionPoint *iface,
+ IID *piid)
+{
+ ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
+ TRACE("(%p)->(%p) returning %s\n", This, piid, debugstr_guid(&(This->iid)));
+ *piid = This->iid;
+ return S_OK;
+}
+
+/************************************************************************
+ * ConnectionPointImpl_GetConnectionPointContainer (IConnectionPoint)
+ *
+ */
+static HRESULT WINAPI ConnectionPointImpl_GetConnectionPointContainer(
+ IConnectionPoint *iface,
+ IConnectionPointContainer **ppCPC)
+{
+ ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
+ TRACE("(%p)->(%p)\n", This, ppCPC);
+
+ return IUnknown_QueryInterface(This->Obj,
+ &IID_IConnectionPointContainer,
+ (LPVOID)ppCPC);
+}
+
+/************************************************************************
+ * ConnectionPointImpl_Advise (IConnectionPoint)
+ *
+ */
+static HRESULT WINAPI ConnectionPointImpl_Advise(IConnectionPoint *iface,
+ IUnknown *lpUnk,
+ DWORD *pdwCookie)
+{
+ DWORD i;
+ ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
+ IUnknown *lpSink;
+ TRACE("(%p)->(%p, %p)\n", This, lpUnk, pdwCookie);
+
+ *pdwCookie = 0;
+ if(FAILED(IUnknown_QueryInterface(lpUnk, &This->iid, (LPVOID)&lpSink)))
+ return CONNECT_E_CANNOTCONNECT;
+
+ for(i = 0; i < This->maxSinks; i++) {
+ if(This->sinks[i] == NULL)
+ break;
+ }
+ if(i == This->maxSinks) {
+ This->maxSinks += MAXSINKS;
+ This->sinks = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->sinks,
+ This->maxSinks * sizeof(IUnknown *));
+ }
+ This->sinks[i] = lpSink;
+ This->nSinks++;
+ *pdwCookie = i + 1;
+ return S_OK;
+}
+
+
+/************************************************************************
+ * ConnectionPointImpl_Unadvise (IConnectionPoint)
+ *
+ */
+static HRESULT WINAPI ConnectionPointImpl_Unadvise(IConnectionPoint *iface,
+ DWORD dwCookie)
+{
+ ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
+ TRACE("(%p)->(%ld)\n", This, dwCookie);
+
+ if(dwCookie == 0 || dwCookie > This->maxSinks) return E_INVALIDARG;
+
+ if(This->sinks[dwCookie-1] == NULL) return CONNECT_E_NOCONNECTION;
+
+ IUnknown_Release(This->sinks[dwCookie-1]);
+ This->sinks[dwCookie-1] = NULL;
+ This->nSinks--;
+ return S_OK;
+}
+
+/************************************************************************
+ * ConnectionPointImpl_EnumConnections (IConnectionPoint)
+ *
+ */
+static HRESULT WINAPI ConnectionPointImpl_EnumConnections(
+ IConnectionPoint *iface,
+ LPENUMCONNECTIONS *ppEnum)
+{
+ ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
+ CONNECTDATA *pCD;
+ DWORD i, nextslot;
+ EnumConnectionsImpl *EnumObj;
+ HRESULT hr;
+
+ TRACE("(%p)->(%p)\n", This, ppEnum);
+
+ *ppEnum = NULL;
+
+ if(This->nSinks == 0) return OLE_E_NOCONNECTION;
+
+ pCD = HeapAlloc(GetProcessHeap(), 0, sizeof(CONNECTDATA) * This->nSinks);
+
+ for(i = 0, nextslot = 0; i < This->maxSinks; i++) {
+ if(This->sinks[i] != NULL) {
+ pCD[nextslot].pUnk = This->sinks[i];
+ pCD[nextslot].dwCookie = i + 1;
+ nextslot++;
+ }
+ }
+ assert(nextslot == This->nSinks);
+
+ /* Bump the ref count of this object up by one. It gets Released in
+ IEnumConnections_Release */
+ IUnknown_AddRef((IUnknown*)This);
+
+ EnumObj = EnumConnectionsImpl_Construct((IUnknown*)This, This->nSinks, pCD);
+ hr = IEnumConnections_QueryInterface((IEnumConnections*)EnumObj,
+ &IID_IEnumConnections, (LPVOID)ppEnum);
+ IEnumConnections_Release((IEnumConnections*)EnumObj);
+
+ HeapFree(GetProcessHeap(), 0, pCD);
+ return hr;
+}
+
+static IConnectionPointVtbl ConnectionPointImpl_VTable =
+{
+ ConnectionPointImpl_QueryInterface,
+ ConnectionPointImpl_AddRef,
+ ConnectionPointImpl_Release,
+ ConnectionPointImpl_GetConnectionInterface,
+ ConnectionPointImpl_GetConnectionPointContainer,
+ ConnectionPointImpl_Advise,
+ ConnectionPointImpl_Unadvise,
+ ConnectionPointImpl_EnumConnections
+};
+
+
+static IEnumConnectionsVtbl EnumConnectionsImpl_VTable;
+static ULONG WINAPI EnumConnectionsImpl_AddRef(IEnumConnections* iface);
+
+/************************************************************************
+ * EnumConnectionsImpl_Construct
+ */
+static EnumConnectionsImpl *EnumConnectionsImpl_Construct(IUnknown *pUnk,
+ DWORD nSinks,
+ CONNECTDATA *pCD)
+{
+ EnumConnectionsImpl *Obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*Obj));
+ DWORD i;
+
+ Obj->lpvtbl = &EnumConnectionsImpl_VTable;
+ Obj->ref = 1;
+ Obj->pUnk = pUnk;
+ Obj->pCD = HeapAlloc(GetProcessHeap(), 0, nSinks * sizeof(CONNECTDATA));
+ Obj->nConns = nSinks;
+ Obj->nCur = 0;
+
+ for(i = 0; i < nSinks; i++) {
+ Obj->pCD[i] = pCD[i];
+ IUnknown_AddRef(Obj->pCD[i].pUnk);
+ }
+ return Obj;
+}
+
+/************************************************************************
+ * EnumConnectionsImpl_Destroy
+ */
+static void EnumConnectionsImpl_Destroy(EnumConnectionsImpl *Obj)
+{
+ DWORD i;
+
+ for(i = 0; i < Obj->nConns; i++)
+ IUnknown_Release(Obj->pCD[i].pUnk);
+
+ HeapFree(GetProcessHeap(), 0, Obj->pCD);
+ HeapFree(GetProcessHeap(), 0, Obj);
+ return;
+}
+
+/************************************************************************
+ * EnumConnectionsImpl_QueryInterface (IUnknown)
+ *
+ * See Windows documentation for more details on IUnknown methods.
+ */
+static HRESULT WINAPI EnumConnectionsImpl_QueryInterface(
+ IEnumConnections* iface,
+ REFIID riid,
+ void** ppvObject)
+{
+ ConnectionPointImpl *This = (ConnectionPointImpl *)iface;
+ TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
+
+ /*
+ * Perform a sanity check on the parameters.
+ */
+ if ( (This==0) || (ppvObject==0) )
+ return E_INVALIDARG;
+
+ /*
+ * Initialize the return parameter.
+ */
+ *ppvObject = 0;
+
+ /*
+ * Compare the riid with the interface IDs implemented by this object.
+ */
+ if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
+ {
+ *ppvObject = (IEnumConnections*)This;
+ }
+ else if (memcmp(&IID_IEnumConnections, riid, sizeof(IID_IEnumConnections)) == 0)
+ {
+ *ppvObject = (IEnumConnections*)This;
+ }
+
+ /*
+ * Check that we obtained an interface.
+ */
+ if ((*ppvObject)==0)
+ {
+ FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
+ return E_NOINTERFACE;
+ }
+
+ /*
+ * Query Interface always increases the reference count by one when it is
+ * successful
+ */
+ EnumConnectionsImpl_AddRef((IEnumConnections*)This);
+
+ return S_OK;
+}
+
+
+/************************************************************************
+ * EnumConnectionsImpl_AddRef (IUnknown)
+ *
+ * See Windows documentation for more details on IUnknown methods.
+ */
+static ULONG WINAPI EnumConnectionsImpl_AddRef(IEnumConnections* iface)
+{
+ EnumConnectionsImpl *This = (EnumConnectionsImpl *)iface;
+ ULONG ref;
+ TRACE("(%p)->(ref=%ld)\n", This, This->ref);
+ ref = InterlockedIncrement(&This->ref);
+ IUnknown_AddRef(This->pUnk);
+ return ref;
+}
+
+/************************************************************************
+ * EnumConnectionsImpl_Release (IUnknown)
+ *
+ * See Windows documentation for more details on IUnknown methods.
+ */
+static ULONG WINAPI EnumConnectionsImpl_Release(IEnumConnections* iface)
+{
+ EnumConnectionsImpl *This = (EnumConnectionsImpl *)iface;
+ ULONG ref;
+ TRACE("(%p)->(ref=%ld)\n", This, This->ref);
+
+ IUnknown_Release(This->pUnk);
+
+ /*
+ * Decrease the reference count on this object.
+ */
+ ref = InterlockedDecrement(&This->ref);
+
+ /*
+ * If the reference count goes down to 0, perform suicide.
+ */
+ if (ref == 0) EnumConnectionsImpl_Destroy(This);
+
+ return ref;
+}
+
+/************************************************************************
+ * EnumConnectionsImpl_Next (IEnumConnections)
+ *
+ */
+static HRESULT WINAPI EnumConnectionsImpl_Next(IEnumConnections* iface,
+ ULONG cConn, LPCONNECTDATA pCD,
+ ULONG *pEnum)
+{
+ EnumConnectionsImpl *This = (EnumConnectionsImpl *)iface;
+ DWORD nRet = 0;
+ TRACE("(%p)->(%ld, %p, %p)\n", This, cConn, pCD, pEnum);
+
+ if(pEnum == NULL) {
+ if(cConn != 1)
+ return E_POINTER;
+ } else
+ *pEnum = 0;
+
+ if(This->nCur >= This->nConns)
+ return S_FALSE;
+
+ while(This->nCur < This->nConns && cConn) {
+ *pCD++ = This->pCD[This->nCur];
+ IUnknown_AddRef(This->pCD[This->nCur].pUnk);
+ This->nCur++;
+ cConn--;
+ nRet++;
+ }
+
+ if(pEnum)
+ *pEnum = nRet;
+
+ return S_OK;
+}
+
+
+/************************************************************************
+ * EnumConnectionsImpl_Skip (IEnumConnections)
+ *
+ */
+static HRESULT WINAPI EnumConnectionsImpl_Skip(IEnumConnections* iface,
+ ULONG cSkip)
+{
+ EnumConnectionsImpl *This = (EnumConnectionsImpl *)iface;
+ TRACE("(%p)->(%ld)\n", This, cSkip);
+
+ if(This->nCur + cSkip >= This->nConns)
+ return S_FALSE;
+
+ This->nCur += cSkip;
+
+ return S_OK;
+}
+
+
+/************************************************************************
+ * EnumConnectionsImpl_Reset (IEnumConnections)
+ *
+ */
+static HRESULT WINAPI EnumConnectionsImpl_Reset(IEnumConnections* iface)
+{
+ EnumConnectionsImpl *This = (EnumConnectionsImpl *)iface;
+ TRACE("(%p)\n", This);
+
+ This->nCur = 0;
+
+ return S_OK;
+}
+
+
+/************************************************************************
+ * EnumConnectionsImpl_Clone (IEnumConnections)
+ *
+ */
+static HRESULT WINAPI EnumConnectionsImpl_Clone(IEnumConnections* iface,
+ LPENUMCONNECTIONS *ppEnum)
+{
+ EnumConnectionsImpl *This = (EnumConnectionsImpl *)iface;
+ EnumConnectionsImpl *newObj;
+ TRACE("(%p)->(%p)\n", This, ppEnum);
+
+ newObj = EnumConnectionsImpl_Construct(This->pUnk, This->nConns, This->pCD);
+ newObj->nCur = This->nCur;
+ *ppEnum = (LPENUMCONNECTIONS)newObj;
+ IUnknown_AddRef(This->pUnk);
+ return S_OK;
+}
+
+static IEnumConnectionsVtbl EnumConnectionsImpl_VTable =
+{
+ EnumConnectionsImpl_QueryInterface,
+ EnumConnectionsImpl_AddRef,
+ EnumConnectionsImpl_Release,
+ EnumConnectionsImpl_Next,
+ EnumConnectionsImpl_Skip,
+ EnumConnectionsImpl_Reset,
+ EnumConnectionsImpl_Clone
+};
+
+/************************************************************************
+ *
+ * The exported function to create the connection point.
+ * NB not a windows API
+ *
+ * PARAMS
+ * pUnk [in] IUnknown of object to which the ConnectionPoint is associated.
+ * Needed to access IConnectionPointContainer.
+ *
+ * riid [in] IID of sink interface that this ConnectionPoint manages
+ *
+ * pCP [out] returns IConnectionPoint
+ *
+ */
+HRESULT CreateConnectionPoint(IUnknown *pUnk, REFIID riid,
+ IConnectionPoint **pCP)
+{
+ ConnectionPointImpl *Obj;
+ HRESULT hr;
+
+ Obj = ConnectionPointImpl_Construct(pUnk, riid);
+ if(!Obj) return E_OUTOFMEMORY;
+
+ hr = IConnectionPoint_QueryInterface((IConnectionPoint *)Obj,
+ &IID_IConnectionPoint, (LPVOID)pCP);
+ IConnectionPoint_Release((IConnectionPoint *)Obj);
+ return hr;
+}
--- vendor/wine/dlls/oleaut32/current/dispatch.c 2004-12-31 15:20:48 UTC (rev 12575)
+++ vendor/wine/dlls/oleaut32/current/dispatch.c 2004-12-31 15:25:53 UTC (rev 12576)
@@ -0,0 +1,456 @@
+/**
+ * Dispatch API functions
+ *
+ * Copyright 2000 Francois Jacques, Macadamian Technologies Inc.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * TODO: Type coercion is implemented in variant.c but not called yet.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+#include "objbase.h"
+#include "oleauto.h"
+#include "winerror.h"
+#include "winreg.h"
+#include "winnls.h" /* for PRIMARYLANGID */
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(ole);
+WINE_DECLARE_DEBUG_CHANNEL(typelib);
+
+static IDispatch * WINAPI StdDispatch_Construct(IUnknown * punkOuter, void * pvThis, ITypeInfo * pTypeInfo);
+
+/******************************************************************************
+ * DispInvoke (OLEAUT32.30)
+ *
+ * Call an object method using the information from its type library.
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: Returns DISP_E_EXCEPTION and updates pexcepinfo if an exception occurs.
+ * DISP_E_BADPARAMCOUNT if the number of parameters is incorrect.
+ * DISP_E_MEMBERNOTFOUND if the method does not exist.
+ * puArgErr is updated if a parameter error (see notes) occurs.
+ * Otherwise, returns the result of calling ITypeInfo_Invoke().
+ *
+ * NOTES
+ * Parameter errors include the following:
+ *| DISP_E_BADVARTYPE
+ *| E_INVALIDARG An argument was invalid
+ *| DISP_E_TYPEMISMATCH,
+ *| DISP_E_OVERFLOW An argument was valid but could not be coerced
+ *| DISP_E_PARAMNOTOPTIONAL A non optional parameter was not passed
+ *| DISP_E_PARAMNOTFOUND A parameter was passed that was not expected by the method
+ * This call defers to ITypeInfo_Invoke().
+ */
+HRESULT WINAPI DispInvoke(
+ VOID *_this, /* [in] Object to call method on */
+ ITypeInfo *ptinfo, /* [in] Object type info */
+ DISPID dispidMember, /* [in] DISPID of the member (e.g. from GetIDsOfNames()) */
+ USHORT wFlags, /* [in] Kind of method call (DISPATCH_ flags from "oaidl.h") */
+ DISPPARAMS *pparams, /* [in] Array of method arguments */
+ VARIANT *pvarResult, /* [out] Destination for the result of the call */
+ EXCEPINFO *pexcepinfo, /* [out] Destination for exception information */
+ UINT *puArgErr) /* [out] Destination for bad argument */
+{
+ /**
+ * TODO:
+ * For each param, call DispGetParam to perform type coercion
+ */
+ FIXME("Coercion of arguments not implemented\n");
+
+ return ITypeInfo_Invoke(ptinfo, _this, dispidMember, wFlags,
+ pparams, pvarResult, pexcepinfo, puArgErr);
+}
+
+/******************************************************************************
+ * DispGetIDsOfNames (OLEAUT32.29)
+ *
+ * Convert a set of parameter names to DISPID's for DispInvoke().
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: An HRESULT error code.
+ *
+ * NOTES
+ * This call defers to ITypeInfo_GetIDsOfNames(). The ITypeInfo interface passed
+ * as ptinfo contains the information to map names to DISPID's.
+ */
+HRESULT WINAPI DispGetIDsOfNames(
+ ITypeInfo *ptinfo, /* [in] Object's type info */
+ OLECHAR **rgszNames, /* [in] Array of names to get DISPID's for */
+ UINT cNames, /* [in] Number of names in rgszNames */
+ DISPID *rgdispid) /* [out] Destination for converted DISPID's */
+{
+ return ITypeInfo_GetIDsOfNames(ptinfo, rgszNames, cNames, rgdispid);
+}
+
+/******************************************************************************
+ * DispGetParam (OLEAUT32.28)
+ *
+ * Retrive a parameter from a DISPPARAMS structure and coerce it to the
+ * specified variant type.
+ *
+ * NOTES
+ * Coercion is done using system (0) locale.
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: DISP_E_PARAMNOTFOUND, if position is invalid. or
+ * DISP_E_TYPEMISMATCH, if the coercion failed. puArgErr is
+ * set to the index of the argument in pdispparams.
+ */
+HRESULT WINAPI DispGetParam(
+ DISPPARAMS *pdispparams, /* [in] Parameter list */
+ UINT position, /* [in] Position of parameter to coerce in pdispparams */
+ VARTYPE vtTarg, /* [in] Type of value to coerce to */
+ VARIANT *pvarResult, /* [out] Destination for resulting variant */
+ UINT *puArgErr) /* [out] Destination for error code */
+{
+ /* position is counted backwards */
+ UINT pos;
+ HRESULT hr;
+
+ TRACE("position=%d, cArgs=%d, cNamedArgs=%d\n",
+ position, pdispparams->cArgs, pdispparams->cNamedArgs);
+ if (position < pdispparams->cArgs) {
+ /* positional arg? */
+ pos = pdispparams->cArgs - position - 1;
+ } else {
+ /* FIXME: is this how to handle named args? */
+ for (pos=0; pos<pdispparams->cNamedArgs; pos++)
+ if (pdispparams->rgdispidNamedArgs[pos] == position) break;
+
+ if (pos==pdispparams->cNamedArgs)
+ return DISP_E_PARAMNOTFOUND;
+ }
+ hr = VariantChangeType(pvarResult,
+ &pdispparams->rgvarg[pos],
+ 0, vtTarg);
+ if (hr == DISP_E_TYPEMISMATCH) *puArgErr = pos;
+ return hr;
+}
+
+/******************************************************************************
+ * CreateStdDispatch [OLEAUT32.32]
+ *
+ * Create and return a standard IDispatch object.
+ *
+ * RETURNS
+ * Success: S_OK. ppunkStdDisp contains the new object.
+ * Failure: An HRESULT error code.
+ *
+ * NOTES
+ * Outer unknown appears to be completely ignored.
+ */
+HRESULT WINAPI CreateStdDispatch(
+ IUnknown* punkOuter,
+ void* pvThis,
+ ITypeInfo* ptinfo,
+ IUnknown** ppunkStdDisp)
+{
+ TRACE("(%p, %p, %p, %p)\n", punkOuter, pvThis, ptinfo, ppunkStdDisp);
+
+ *ppunkStdDisp = (LPUNKNOWN)StdDispatch_Construct(punkOuter, pvThis, ptinfo);
+ if (!*ppunkStdDisp)
+ return E_OUTOFMEMORY;
+ return S_OK;
+}
+
+
+/******************************************************************************
+ * IDispatch {OLEAUT32}
+ *
+ * NOTES
+ * The IDispatch interface provides a single interface to dispatch method calls,
+ * regardless of whether the object to be called is in or out of process,
+ * local or remote (e.g. being called over a network). This interface is late-bound
+ * (linked at run-time), as opposed to early-bound (linked at compile time).
+ *
+ * The interface is used by objects that wish to called by scripting
+ * languages such as VBA, in order to minimise the amount of COM and C/C++
+ * knowledge required, or by objects that wish to live out of process from code
+ * that will call their methods.
+ *
+ * Method, property and parameter names can be localised. The details required to
+ * map names to methods and parameters are collected in a type library, usually
+ * output by an IDL compiler using the objects IDL description. This information is
+ * accessible programatically through the ITypeLib interface (for a type library),
+ * and the ITypeInfo interface (for an object within the type library). Type information
+ * can also be created at run-time using CreateDispTypeInfo().
+ *
+ * WRAPPERS
+ * Instead of using IDispatch directly, there are several wrapper functions available
+ * to simplify the process of calling an objects methods through IDispatch.
+ *
+ * A standard implementation of an IDispatch object is created by calling
+ * CreateStdDispatch(). Numeric Id values for the parameters and methods (DISPID's)
+ * of an object of interest are retrieved by calling DispGetIDsOfNames(). DispGetParam()
+ * retrieves information about a particular parameter. Finally the DispInvoke()
+ * function is responsable for actually calling methods on an object.
+ *
+ * METHODS
+ */
+
+typedef struct
+{
+ IDispatchVtbl *lpVtbl;
+ void * pvThis;
+ ITypeInfo * pTypeInfo;
+ ULONG ref;
+} StdDispatch;
+
+/******************************************************************************
+ * IDispatch_QueryInterface {OLEAUT32}
+ *
+ * See IUnknown_QueryInterface.
+ */
+static HRESULT WINAPI StdDispatch_QueryInterface(
+ LPDISPATCH iface,
+ REFIID riid,
+ void** ppvObject)
+{
+ StdDispatch *This = (StdDispatch *)iface;
+ TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppvObject);
+
+ if (IsEqualIID(riid, &IID_IDispatch) ||
+ IsEqualIID(riid, &IID_IUnknown))
+ {
+ *ppvObject = (LPVOID)This;
+ IUnknown_AddRef((LPUNKNOWN)*ppvObject);
+ return S_OK;
+ }
+ return E_NOINTERFACE;
+}
+
+/******************************************************************************
+ * IDispatch_AddRef {OLEAUT32}
+ *
+ * See IUnknown_AddRef.
+ */
+static ULONG WINAPI StdDispatch_AddRef(LPDISPATCH iface)
+{
+ StdDispatch *This = (StdDispatch *)iface;
+ TRACE("()\n");
+
+ return InterlockedIncrement(&This->ref);
+}
+
+/******************************************************************************
+ * IDispatch_Release {OLEAUT32}
+ *
+ * See IUnknown_Release.
+ */
+static ULONG WINAPI StdDispatch_Release(LPDISPATCH iface)
+{
+ StdDispatch *This = (StdDispatch *)iface;
+ ULONG ref;
+ TRACE("(%p)->()\n", This);
+
+ ref = InterlockedDecrement(&This->ref);
+
+ if (ref == 0)
+ {
+ ITypeInfo_Release(This->pTypeInfo);
+ CoTaskMemFree(This);
[truncated at 1000 lines; 50703 more skipped]