fdopen: don't rewind the file after creating the FILE* handle. Added
[wine] / dlls / oleaut32 / dispatch.c
1 /**
2  * Dispatch API functions
3  *
4  * Copyright 2000  Francois Jacques, Macadamian Technologies Inc.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * TODO: Type coercion is implemented in variant.c but not called yet.
21  */
22
23 #include "config.h"
24
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdio.h>
28 #include <ctype.h>
29
30 #include "windef.h"
31 #include "ole.h"
32 #include "oleauto.h"
33 #include "winerror.h"
34 #include "winreg.h"         /* for HKEY_LOCAL_MACHINE */
35 #include "winnls.h"         /* for PRIMARYLANGID */
36
37 #include "wine/debug.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(ole);
40 WINE_DECLARE_DEBUG_CHANNEL(typelib);
41
42 static IDispatch * WINAPI StdDispatch_Construct(IUnknown * punkOuter, void * pvThis, ITypeInfo * pTypeInfo);
43
44 /******************************************************************************
45  *              DispInvoke (OLEAUT32.30)
46  *
47  *
48  * Calls method of an object through its IDispatch interface.
49  *
50  * NOTES
51  *              - Defer method invocation to ITypeInfo::Invoke()
52  *
53  * RETURNS
54  *
55  *              S_OK on success.
56  */
57 HRESULT WINAPI DispInvoke(
58         VOID       *_this,        /* [in] object instance */
59         ITypeInfo  *ptinfo,       /* [in] object's type info */
60         DISPID      dispidMember, /* [in] member id */
61         USHORT      wFlags,       /* [in] kind of method call */
62         DISPPARAMS *pparams,      /* [in] array of arguments */
63         VARIANT    *pvarResult,   /* [out] result of method call */
64         EXCEPINFO  *pexcepinfo,   /* [out] information about exception */
65         UINT       *puArgErr)     /* [out] index of bad argument(if any) */
66 {
67     HRESULT hr = E_FAIL;
68
69     /**
70      * TODO:
71      * For each param, call DispGetParam to perform type coercion
72      */
73     FIXME("Coercion of arguments not implemented\n");
74
75     hr = ICOM_CALL7(Invoke,
76                     ptinfo,
77                     _this,
78                     dispidMember,
79                     wFlags,
80                     pparams, pvarResult, pexcepinfo, puArgErr);
81
82     return (hr);
83 }
84
85
86 /******************************************************************************
87  *              DispGetIDsOfNames (OLEAUT32.29)
88  *
89  * Convert a set of names to dispids, based on information
90  * contained in object's type library.
91  *
92  * NOTES
93  *              - Defers to ITypeInfo::GetIDsOfNames()
94  *
95  * RETURNS
96  *
97  *              S_OK on success.
98  */
99 HRESULT WINAPI DispGetIDsOfNames(
100         ITypeInfo  *ptinfo,    /* [in] */
101         OLECHAR   **rgszNames, /* [in] */
102         UINT        cNames,    /* [in] */
103         DISPID     *rgdispid)  /* [out] */
104 {
105     HRESULT hr = E_FAIL;
106
107     hr = ICOM_CALL3(GetIDsOfNames,
108                     ptinfo,
109                     rgszNames,
110                     cNames,
111                     rgdispid);
112     return (hr);
113 }
114
115 /******************************************************************************
116  *              DispGetParam (OLEAUT32.28)
117  *
118  * Retrive a parameter from a DISPPARAMS structures and coerce it to
119  * specified variant type
120  *
121  * NOTES
122  *              Coercion is done using system (0) locale.
123  *
124  * RETURNS
125  *
126  *              S_OK on success.
127  */
128 HRESULT WINAPI DispGetParam(
129         DISPPARAMS *pdispparams, /* [in] */
130         UINT        position,    /* [in] */
131         VARTYPE     vtTarg,      /* [in] */
132         VARIANT    *pvarResult,  /* [out] */
133         UINT       *puArgErr)    /* [out] */
134 {
135     /* position is counted backwards */
136     UINT pos;
137     HRESULT hr;
138
139     TRACE("position=%d, cArgs=%d, cNamedArgs=%d\n",
140           position, pdispparams->cArgs, pdispparams->cNamedArgs);
141     if (position < pdispparams->cArgs) {
142       /* positional arg? */
143       pos = pdispparams->cArgs - position - 1;
144     } else {
145       /* FIXME: is this how to handle named args? */
146       for (pos=0; pos<pdispparams->cNamedArgs; pos++)
147         if (pdispparams->rgdispidNamedArgs[pos] == position) break;
148
149       if (pos==pdispparams->cNamedArgs)
150         return DISP_E_PARAMNOTFOUND;
151     }
152     hr = VariantChangeType(pvarResult,
153                            &pdispparams->rgvarg[pos],
154                            0, vtTarg);
155     if (hr == DISP_E_TYPEMISMATCH) *puArgErr = pos;
156     return hr;
157 }
158
159 /******************************************************************************
160  * CreateStdDispatch [OLEAUT32.32]
161  */
162 HRESULT WINAPI CreateStdDispatch(
163         IUnknown* punkOuter,
164         void* pvThis,
165         ITypeInfo* ptinfo,
166         IUnknown** ppunkStdDisp)
167 {
168     TRACE("(%p, %p, %p, %p)\n", punkOuter, pvThis, ptinfo, ppunkStdDisp);
169
170     *ppunkStdDisp = (LPUNKNOWN)StdDispatch_Construct(punkOuter, pvThis, ptinfo);
171     if (!*ppunkStdDisp)
172         return E_OUTOFMEMORY;
173     return S_OK;
174 }
175
176 /******************************************************************************
177  * CreateDispTypeInfo [OLEAUT32.31]
178  */
179 HRESULT WINAPI CreateDispTypeInfo(
180         INTERFACEDATA *pidata,
181         LCID lcid,
182         ITypeInfo **pptinfo)
183 {
184         FIXME("(%p,%ld,%p),stub\n",pidata,lcid,pptinfo);
185         return 0;
186 }
187
188 typedef struct
189 {
190     ICOM_VFIELD(IDispatch);
191     IUnknown * outerUnknown;
192     void * pvThis;
193     ITypeInfo * pTypeInfo;
194     ULONG ref;
195 } StdDispatch;
196
197 static HRESULT WINAPI StdDispatch_QueryInterface(
198   LPDISPATCH iface,
199   REFIID riid,
200   void** ppvObject)
201 {
202     ICOM_THIS(StdDispatch, iface);
203     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppvObject);
204
205     if (This->outerUnknown)
206         return IUnknown_QueryInterface(This->outerUnknown, riid, ppvObject);
207
208     if (IsEqualIID(riid, &IID_IDispatch) ||
209         IsEqualIID(riid, &IID_IUnknown))
210     {
211         *ppvObject = (LPVOID)This;
212         IUnknown_AddRef((LPUNKNOWN)*ppvObject);
213         return S_OK;
214     }
215     return E_NOINTERFACE;
216 }
217
218 static ULONG WINAPI StdDispatch_AddRef(LPDISPATCH iface)
219 {
220     ICOM_THIS(StdDispatch, iface);
221     TRACE("()\n");
222     This->ref++;
223     if (This->outerUnknown)
224         return IUnknown_AddRef(This->outerUnknown);
225     else
226         return This->ref;
227 }
228
229 static ULONG WINAPI StdDispatch_Release(LPDISPATCH iface)
230 {
231     ICOM_THIS(StdDispatch, iface);
232     ULONG ret;
233     TRACE("(%p)->()\n", This);
234
235     This->ref--;
236
237     if (This->outerUnknown)
238         ret = IUnknown_Release(This->outerUnknown);
239     else
240         ret = This->ref;
241
242     if (This->ref <= 0)
243         CoTaskMemFree(This);
244
245     return ret;
246 }
247
248 static HRESULT WINAPI StdDispatch_GetTypeInfoCount(LPDISPATCH iface, UINT * pctinfo)
249 {
250     TRACE("(%p)\n", pctinfo);
251
252     *pctinfo = 1;
253     return S_OK;
254 }
255
256 static HRESULT WINAPI StdDispatch_GetTypeInfo(LPDISPATCH iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
257 {
258     ICOM_THIS(StdDispatch, iface);
259     TRACE("(%d, %lx, %p)\n", iTInfo, lcid, ppTInfo);
260
261     if (iTInfo != 0)
262         return DISP_E_BADINDEX;
263     *ppTInfo = This->pTypeInfo;
264     return S_OK;
265 }
266
267 static HRESULT WINAPI StdDispatch_GetIDsOfNames(LPDISPATCH iface, REFIID riid, LPOLESTR * rgszNames, UINT cNames, LCID lcid, DISPID * rgDispId)
268 {
269     ICOM_THIS(StdDispatch, iface);
270     TRACE("(%s, %p, %d, 0x%lx, %p)\n", debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
271
272     if (!IsEqualGUID(riid, &IID_NULL))
273     {
274         FIXME(" expected riid == IID_NULL\n");
275         return E_INVALIDARG;
276     }
277     return DispGetIDsOfNames(This->pTypeInfo, rgszNames, cNames, rgDispId);
278 }
279
280 static HRESULT WINAPI StdDispatch_Invoke(LPDISPATCH iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS * pDispParams, VARIANT * pVarResult, EXCEPINFO * pExcepInfo, UINT * puArgErr)
281 {
282     ICOM_THIS(StdDispatch, iface);
283     TRACE("(%ld, %s, 0x%lx, 0x%x, %p, %p, %p, %p)\n", dispIdMember, debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
284
285     if (!IsEqualGUID(riid, &IID_NULL))
286     {
287         FIXME(" expected riid == IID_NULL\n");
288         return E_INVALIDARG;
289     }
290     return DispInvoke(This->pvThis, This->pTypeInfo, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
291 }
292
293 static ICOM_VTABLE(IDispatch) StdDispatch_VTable =
294 {
295   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
296   StdDispatch_QueryInterface,
297   StdDispatch_AddRef,
298   StdDispatch_Release,
299   StdDispatch_GetTypeInfoCount,
300   StdDispatch_GetTypeInfo,
301   StdDispatch_GetIDsOfNames,
302   StdDispatch_Invoke
303 };
304
305 static IDispatch * WINAPI StdDispatch_Construct(
306   IUnknown * punkOuter,
307   void * pvThis,
308   ITypeInfo * pTypeInfo)
309 {
310     StdDispatch * pStdDispatch;
311
312     pStdDispatch = CoTaskMemAlloc(sizeof(StdDispatch));
313     if (!pStdDispatch)
314         return (IDispatch *)pStdDispatch;
315
316     pStdDispatch->lpVtbl = &StdDispatch_VTable;
317     pStdDispatch->outerUnknown = punkOuter;
318     pStdDispatch->pvThis = pvThis;
319     pStdDispatch->pTypeInfo = pTypeInfo;
320     pStdDispatch->ref = 1;
321
322     return (IDispatch *)pStdDispatch;
323 }