ReactOS Fundraising Campaign 2012
 
€ 4,060 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

dispatch.c
Go to the documentation of this file.
00001 
00022 #include "config.h"
00023 
00024 #include <stdlib.h>
00025 #include <string.h>
00026 #include <stdarg.h>
00027 #include <stdio.h>
00028 #include <ctype.h>
00029 
00030 #define COBJMACROS
00031 
00032 #include "windef.h"
00033 #include "winbase.h"
00034 #include "objbase.h"
00035 #include "oleauto.h"
00036 #include "winerror.h"
00037 
00038 #include "wine/debug.h"
00039 
00040 WINE_DEFAULT_DEBUG_CHANNEL(ole);
00041 
00042 static IDispatch * StdDispatch_Construct(IUnknown * punkOuter, void * pvThis, ITypeInfo * pTypeInfo);
00043 
00044 /******************************************************************************
00045  *      DispInvoke (OLEAUT32.30)
00046  *
00047  * Call an object method using the information from its type library.
00048  *
00049  * RETURNS
00050  *  Success: S_OK.
00051  *  Failure: Returns DISP_E_EXCEPTION and updates pexcepinfo if an exception occurs.
00052  *           DISP_E_BADPARAMCOUNT if the number of parameters is incorrect.
00053  *           DISP_E_MEMBERNOTFOUND if the method does not exist.
00054  *           puArgErr is updated if a parameter error (see notes) occurs.
00055  *           Otherwise, returns the result of calling ITypeInfo_Invoke().
00056  *
00057  * NOTES
00058  *  Parameter errors include the following:
00059  *| DISP_E_BADVARTYPE
00060  *| E_INVALIDARG            An argument was invalid
00061  *| DISP_E_TYPEMISMATCH,
00062  *| DISP_E_OVERFLOW         An argument was valid but could not be coerced
00063  *| DISP_E_PARAMNOTOPTIONAL A non optional parameter was not passed
00064  *| DISP_E_PARAMNOTFOUND    A parameter was passed that was not expected by the method
00065  *  This call defers to ITypeInfo_Invoke().
00066  */
00067 HRESULT WINAPI DispInvoke(
00068     VOID       *_this,        /* [in] Object to call method on */
00069     ITypeInfo  *ptinfo,       /* [in] Object type info */
00070     DISPID      dispidMember, /* [in] DISPID of the member (e.g. from GetIDsOfNames()) */
00071     USHORT      wFlags,       /* [in] Kind of method call (DISPATCH_ flags from "oaidl.h") */
00072     DISPPARAMS *pparams,      /* [in] Array of method arguments */
00073     VARIANT    *pvarResult,   /* [out] Destination for the result of the call */
00074     EXCEPINFO  *pexcepinfo,   /* [out] Destination for exception information */
00075     UINT       *puArgErr)     /* [out] Destination for bad argument */
00076 {
00077     TRACE("\n");
00078 
00079     return ITypeInfo_Invoke(ptinfo, _this, dispidMember, wFlags,
00080                             pparams, pvarResult, pexcepinfo, puArgErr);
00081 }
00082 
00083 /******************************************************************************
00084  *      DispGetIDsOfNames (OLEAUT32.29)
00085  *
00086  * Convert a set of parameter names to DISPIDs for DispInvoke().
00087  *
00088  * RETURNS
00089  *  Success: S_OK.
00090  *  Failure: An HRESULT error code.
00091  *
00092  * NOTES
00093  *  This call defers to ITypeInfo_GetIDsOfNames(). The ITypeInfo interface passed
00094  *  as ptinfo contains the information to map names to DISPIDs.
00095  */
00096 HRESULT WINAPI DispGetIDsOfNames(
00097     ITypeInfo  *ptinfo,    /* [in] Object's type info */
00098     OLECHAR   **rgszNames, /* [in] Array of names to get DISPIDs for */
00099     UINT        cNames,    /* [in] Number of names in rgszNames */
00100     DISPID     *rgdispid)  /* [out] Destination for converted DISPIDs */
00101 {
00102     return ITypeInfo_GetIDsOfNames(ptinfo, rgszNames, cNames, rgdispid);
00103 }
00104 
00105 /******************************************************************************
00106  *      DispGetParam (OLEAUT32.28)
00107  *
00108  * Retrieve a parameter from a DISPPARAMS structure and coerce it to the
00109  * specified variant type.
00110  *
00111  * NOTES
00112  *  Coercion is done using system (0) locale.
00113  *
00114  * RETURNS
00115  *  Success: S_OK.
00116  *  Failure: DISP_E_PARAMNOTFOUND, if position is invalid. or
00117  *           DISP_E_TYPEMISMATCH, if the coercion failed. puArgErr is
00118  *           set to the index of the argument in pdispparams.
00119  */
00120 HRESULT WINAPI DispGetParam(
00121     DISPPARAMS *pdispparams, /* [in] Parameter list */
00122     UINT        position,    /* [in] Position of parameter to coerce in pdispparams */
00123     VARTYPE     vtTarg,      /* [in] Type of value to coerce to */
00124     VARIANT    *pvarResult,  /* [out] Destination for resulting variant */
00125     UINT       *puArgErr)    /* [out] Destination for error code */
00126 {
00127     /* position is counted backwards */
00128     UINT pos;
00129     HRESULT hr;
00130 
00131     TRACE("position=%d, cArgs=%d, cNamedArgs=%d\n",
00132           position, pdispparams->cArgs, pdispparams->cNamedArgs);
00133 
00134     if (position < pdispparams->cArgs)
00135     {
00136       /* positional arg? */
00137       pos = pdispparams->cArgs - position - 1;
00138     }
00139     else
00140     {
00141       /* FIXME: is this how to handle named args? */
00142       for (pos=0; pos<pdispparams->cNamedArgs; pos++)
00143         if (pdispparams->rgdispidNamedArgs[pos] == position) break;
00144 
00145       if (pos==pdispparams->cNamedArgs)
00146         return DISP_E_PARAMNOTFOUND;
00147     }
00148 
00149     if (pdispparams->cArgs > 0 && !pdispparams->rgvarg)
00150     {
00151         hr = E_INVALIDARG;
00152         goto done;
00153     }
00154 
00155     if (!pvarResult)
00156     {
00157         hr = E_INVALIDARG;
00158         goto done;
00159     }
00160 
00161     hr = VariantChangeType(pvarResult,
00162                            &pdispparams->rgvarg[pos],
00163                            0, vtTarg);
00164 
00165 done:
00166     if (FAILED(hr))
00167         *puArgErr = pos;
00168 
00169     return hr;
00170 }
00171 
00172 /******************************************************************************
00173  * CreateStdDispatch [OLEAUT32.32]
00174  *
00175  * Create and return a standard IDispatch object.
00176  *
00177  * RETURNS
00178  *  Success: S_OK. ppunkStdDisp contains the new object.
00179  *  Failure: An HRESULT error code.
00180  *
00181  * NOTES
00182  *  Outer unknown appears to be completely ignored.
00183  */
00184 HRESULT WINAPI CreateStdDispatch(
00185         IUnknown* punkOuter,
00186         void* pvThis,
00187     ITypeInfo* ptinfo,
00188     IUnknown** ppunkStdDisp)
00189 {
00190     TRACE("(%p, %p, %p, %p)\n", punkOuter, pvThis, ptinfo, ppunkStdDisp);
00191 
00192     *ppunkStdDisp = (LPUNKNOWN)StdDispatch_Construct(punkOuter, pvThis, ptinfo);
00193     if (!*ppunkStdDisp)
00194         return E_OUTOFMEMORY;
00195     return S_OK;
00196 }
00197 
00198 
00199 /******************************************************************************
00200  * IDispatch {OLEAUT32}
00201  *
00202  * NOTES
00203  *  The IDispatch interface provides a single interface to dispatch method calls,
00204  *  regardless of whether the object to be called is in or out of process,
00205  *  local or remote (e.g. being called over a network). This interface is late-bound
00206  *  (linked at run-time), as opposed to early-bound (linked at compile time).
00207  *
00208  *  The interface is used by objects that wish to called by scripting
00209  *  languages such as VBA, in order to minimise the amount of COM and C/C++
00210  *  knowledge required, or by objects that wish to live out of process from code
00211  *  that will call their methods.
00212  *
00213  *  Method, property and parameter names can be localised. The details required to
00214  *  map names to methods and parameters are collected in a type library, usually
00215  *  output by an IDL compiler using the objects IDL description. This information is
00216  *  accessible programmatically through the ITypeLib interface (for a type library),
00217  *  and the ITypeInfo interface (for an object within the type library). Type information
00218  *  can also be created at run-time using CreateDispTypeInfo().
00219  *
00220  * WRAPPERS
00221  *  Instead of using IDispatch directly, there are several wrapper functions available
00222  *  to simplify the process of calling an objects methods through IDispatch.
00223  *
00224  *  A standard implementation of an IDispatch object is created by calling
00225  *  CreateStdDispatch(). Numeric Id values for the parameters and methods (DISPIDs)
00226  *  of an object of interest are retrieved by calling DispGetIDsOfNames(). DispGetParam()
00227  *  retrieves information about a particular parameter. Finally the DispInvoke()
00228  *  function is responsible for actually calling methods on an object.
00229  *
00230  * METHODS
00231  */
00232 
00233 typedef struct
00234 {
00235     const IDispatchVtbl *lpVtbl;
00236     void * pvThis;
00237     ITypeInfo * pTypeInfo;
00238     LONG ref;
00239 } StdDispatch;
00240 
00241 /******************************************************************************
00242  * IDispatch_QueryInterface {OLEAUT32}
00243  *
00244  * See IUnknown_QueryInterface.
00245  */
00246 static HRESULT WINAPI StdDispatch_QueryInterface(
00247   LPDISPATCH iface,
00248   REFIID riid,
00249   void** ppvObject)
00250 {
00251     StdDispatch *This = (StdDispatch *)iface;
00252     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppvObject);
00253 
00254     if (IsEqualIID(riid, &IID_IDispatch) ||
00255         IsEqualIID(riid, &IID_IUnknown))
00256     {
00257         *ppvObject = This;
00258         IUnknown_AddRef((LPUNKNOWN)*ppvObject);
00259         return S_OK;
00260     }
00261     return E_NOINTERFACE;
00262 }
00263 
00264 /******************************************************************************
00265  * IDispatch_AddRef {OLEAUT32}
00266  *
00267  * See IUnknown_AddRef.
00268  */
00269 static ULONG WINAPI StdDispatch_AddRef(LPDISPATCH iface)
00270 {
00271     StdDispatch *This = (StdDispatch *)iface;
00272     ULONG refCount = InterlockedIncrement(&This->ref);
00273 
00274     TRACE("(%p)->(ref before=%u)\n",This, refCount - 1);
00275 
00276     return refCount;
00277 }
00278 
00279 /******************************************************************************
00280  * IDispatch_Release {OLEAUT32}
00281  *
00282  * See IUnknown_Release.
00283  */
00284 static ULONG WINAPI StdDispatch_Release(LPDISPATCH iface)
00285 {
00286     StdDispatch *This = (StdDispatch *)iface;
00287     ULONG refCount = InterlockedDecrement(&This->ref);
00288 
00289     TRACE("(%p)->(ref before=%u)\n", This, refCount + 1);
00290 
00291     if (!refCount)
00292     {
00293         ITypeInfo_Release(This->pTypeInfo);
00294         CoTaskMemFree(This);
00295     }
00296 
00297     return refCount;
00298 }
00299 
00300 /******************************************************************************
00301  * IDispatch_GetTypeInfoCount {OLEAUT32}
00302  *
00303  * Get the count of type information in an IDispatch interface.
00304  *
00305  * PARAMS
00306  *  iface   [I] IDispatch interface
00307  *  pctinfo [O] Destination for the count
00308  *
00309  * RETURNS
00310  *  Success: S_OK. pctinfo is updated with the count. This is always 1 if
00311  *           the object provides type information, and 0 if it does not.
00312  *  Failure: E_NOTIMPL. The object does not provide type information.
00313  *
00314  * NOTES
00315  *  See IDispatch() and IDispatch_GetTypeInfo().
00316  */
00317 static HRESULT WINAPI StdDispatch_GetTypeInfoCount(LPDISPATCH iface, UINT * pctinfo)
00318 {
00319     StdDispatch *This = (StdDispatch *)iface;
00320     TRACE("(%p)\n", pctinfo);
00321 
00322     *pctinfo = This->pTypeInfo ? 1 : 0;
00323     return S_OK;
00324 }
00325 
00326 /******************************************************************************
00327  * IDispatch_GetTypeInfo {OLEAUT32}
00328  *
00329  * Get type information from an IDispatch interface.
00330  *
00331  * PARAMS
00332  *  iface   [I] IDispatch interface
00333  *  iTInfo  [I] Index of type information.
00334  *  lcid    [I] Locale of the type information to get
00335  *  ppTInfo [O] Destination for the ITypeInfo object
00336  *
00337  * RETURNS
00338  *  Success: S_OK. ppTInfo is updated with the objects type information
00339  *  Failure: DISP_E_BADINDEX, if iTInfo is any value other than 0.
00340  *
00341  * NOTES
00342  *  See IDispatch.
00343  */
00344 static HRESULT WINAPI StdDispatch_GetTypeInfo(LPDISPATCH iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
00345 {
00346     StdDispatch *This = (StdDispatch *)iface;
00347     TRACE("(%d, %x, %p)\n", iTInfo, lcid, ppTInfo);
00348 
00349     *ppTInfo = NULL;
00350     if (iTInfo != 0)
00351         return DISP_E_BADINDEX;
00352 
00353     if (This->pTypeInfo)
00354     {
00355       *ppTInfo = This->pTypeInfo;
00356       ITypeInfo_AddRef(*ppTInfo);
00357     }
00358     return S_OK;
00359 }
00360 
00361 /******************************************************************************
00362  * IDispatch_GetIDsOfNames {OLEAUT32}
00363  *
00364  * Convert a methods name and an optional set of parameter names into DISPIDs
00365  * for passing to IDispatch_Invoke().
00366  *
00367  * PARAMS
00368  *  iface     [I] IDispatch interface
00369  *  riid      [I] Reserved, set to IID_NULL
00370  *  rgszNames [I] Name to convert
00371  *  cNames    [I] Number of names in rgszNames
00372  *  lcid      [I] Locale of the type information to convert from
00373  *  rgDispId  [O] Destination for converted DISPIDs.
00374  *
00375  * RETURNS
00376  *  Success: S_OK.
00377  *  Failure: DISP_E_UNKNOWNNAME, if any of the names is invalid.
00378  *           DISP_E_UNKNOWNLCID if lcid is invalid.
00379  *           Otherwise, an HRESULT error code.
00380  *
00381  * NOTES
00382  *  This call defers to ITypeInfo_GetIDsOfNames(), using the ITypeInfo object
00383  *  contained within the IDispatch object.
00384  *  The first member of the names list must be a method name. The names following
00385  *  the method name are the parameters for that method.
00386  */
00387 static HRESULT WINAPI StdDispatch_GetIDsOfNames(LPDISPATCH iface, REFIID riid, LPOLESTR * rgszNames, UINT cNames, LCID lcid, DISPID * rgDispId)
00388 {
00389     StdDispatch *This = (StdDispatch *)iface;
00390     TRACE("(%s, %p, %d, 0x%x, %p)\n", debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
00391 
00392     if (!IsEqualGUID(riid, &IID_NULL))
00393     {
00394         FIXME(" expected riid == IID_NULL\n");
00395         return E_INVALIDARG;
00396     }
00397     return DispGetIDsOfNames(This->pTypeInfo, rgszNames, cNames, rgDispId);
00398 }
00399 
00400 /******************************************************************************
00401  * IDispatch_Invoke {OLEAUT32}
00402  *
00403  * Call an object method.
00404  *
00405  * PARAMS
00406  *  iface        [I] IDispatch interface
00407  *  dispIdMember [I] DISPID of the method (from GetIDsOfNames())
00408  *  riid         [I] Reserved, set to IID_NULL
00409  *  lcid         [I] Locale of the type information to convert parameters with
00410  *  wFlags,      [I] Kind of method call (DISPATCH_ flags from "oaidl.h")
00411  *  pDispParams  [I] Array of method arguments
00412  *  pVarResult   [O] Destination for the result of the call
00413  *  pExcepInfo   [O] Destination for exception information
00414  *  puArgErr     [O] Destination for bad argument
00415  *
00416  * RETURNS
00417  *  Success: S_OK.
00418  *  Failure: See DispInvoke() for failure cases.
00419  *
00420  * NOTES
00421  *  See DispInvoke() and IDispatch().
00422  */
00423 static HRESULT WINAPI StdDispatch_Invoke(LPDISPATCH iface, DISPID dispIdMember, REFIID riid, LCID lcid,
00424                                          WORD wFlags, DISPPARAMS * pDispParams, VARIANT * pVarResult,
00425                                          EXCEPINFO * pExcepInfo, UINT * puArgErr)
00426 {
00427     StdDispatch *This = (StdDispatch *)iface;
00428     TRACE("(%d, %s, 0x%x, 0x%x, %p, %p, %p, %p)\n", dispIdMember, debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
00429 
00430     if (!IsEqualGUID(riid, &IID_NULL))
00431     {
00432         FIXME(" expected riid == IID_NULL\n");
00433         return E_INVALIDARG;
00434     }
00435     return DispInvoke(This->pvThis, This->pTypeInfo, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
00436 }
00437 
00438 static const IDispatchVtbl StdDispatch_VTable =
00439 {
00440   StdDispatch_QueryInterface,
00441   StdDispatch_AddRef,
00442   StdDispatch_Release,
00443   StdDispatch_GetTypeInfoCount,
00444   StdDispatch_GetTypeInfo,
00445   StdDispatch_GetIDsOfNames,
00446   StdDispatch_Invoke
00447 };
00448 
00449 static IDispatch * StdDispatch_Construct(
00450   IUnknown * punkOuter,
00451   void * pvThis,
00452   ITypeInfo * pTypeInfo)
00453 {
00454     StdDispatch * pStdDispatch;
00455 
00456     pStdDispatch = CoTaskMemAlloc(sizeof(StdDispatch));
00457     if (!pStdDispatch)
00458         return (IDispatch *)pStdDispatch;
00459 
00460     pStdDispatch->lpVtbl = &StdDispatch_VTable;
00461     pStdDispatch->pvThis = pvThis;
00462     pStdDispatch->pTypeInfo = pTypeInfo;
00463     pStdDispatch->ref = 1;
00464 
00465     /* we keep a reference to the type info so prevent it from
00466      * being destroyed until we are done with it */
00467     ITypeInfo_AddRef(pTypeInfo);
00468 
00469     return (IDispatch *)pStdDispatch;
00470 }

Generated on Tue May 22 2012 04:23:57 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.