- Made sure that the files that contains the declarations
[wine] / dlls / ole32 / errorinfo.c
1 /*
2  * ErrorInfo API
3  *
4  * Copyright 2000 Patrik Stridvall, Juergen Schmied
5  *
6  *
7  * The errorinfo is a per-thread object. The reference is stored in the 
8  * TEB at offset 0xf80
9  */
10
11 #include <string.h>
12
13 #include "windef.h"
14 #include "oleauto.h"
15 #include "winerror.h"
16
17 #include "wine/obj_base.h"
18 #include "wine/obj_oleaut.h"
19 #include "wine/obj_errorinfo.h"
20 #include "wine/unicode.h"
21 #include "heap.h"
22 #include "thread.h"
23
24 #include "debugtools.h"
25
26 DEFAULT_DEBUG_CHANNEL(ole);
27
28 /* this code is from SysAllocStringLen (ole2disp.c in oleaut32) */
29 static BSTR WINAPI ERRORINFO_SysAllocString(const OLECHAR* in)
30 {
31     DWORD  bufferSize;
32     DWORD* newBuffer;
33     WCHAR* stringBuffer;
34     DWORD len;
35     
36     if (in == NULL)
37         return NULL;
38     /*
39      * Find the lenth of the buffer passed-in in bytes.
40      */
41     len = strlenW(in);
42     bufferSize = len * sizeof (WCHAR);
43
44     /*
45      * Allocate a new buffer to hold the string.
46      * dont't forget to keep an empty spot at the begining of the
47      * buffer for the character count and an extra character at the
48      * end for the NULL.
49      */
50     newBuffer = (DWORD*)HeapAlloc(GetProcessHeap(),
51                                  0,
52                                  bufferSize + sizeof(WCHAR) + sizeof(DWORD));
53
54     /*
55      * If the memory allocation failed, return a null pointer.
56      */
57     if (newBuffer==0)
58       return 0;
59
60     /*
61      * Copy the length of the string in the placeholder.
62      */
63     *newBuffer = bufferSize;
64
65     /*
66      * Skip the byte count.
67      */
68     newBuffer++;
69
70     /*
71      * Copy the information in the buffer.
72      * Since it is valid to pass a NULL pointer here, we'll initialize the
73      * buffer to nul if it is the case.
74      */
75     if (in != 0)
76       memcpy(newBuffer, in, bufferSize);
77     else
78       memset(newBuffer, 0, bufferSize);
79
80     /*
81      * Make sure that there is a nul character at the end of the
82      * string.
83      */
84     stringBuffer = (WCHAR*)newBuffer;
85     stringBuffer[len] = 0;
86
87     return (LPWSTR)stringBuffer;
88 }
89
90 /* this code is from SysFreeString (ole2disp.c in oleaut32)*/
91 static VOID WINAPI ERRORINFO_SysFreeString(BSTR in)
92 {
93     DWORD* bufferPointer;
94     
95     /* NULL is a valid parameter */
96     if(!in) return;
97
98     /*
99      * We have to be careful when we free a BSTR pointer, it points to
100      * the beginning of the string but it skips the byte count contained
101      * before the string.
102      */
103     bufferPointer = (DWORD*)in;
104
105     bufferPointer--;
106
107     /*
108      * Free the memory from it's "real" origin.
109      */
110     HeapFree(GetProcessHeap(), 0, bufferPointer);
111 }
112
113
114 typedef struct ErrorInfoImpl
115 {
116         ICOM_VTABLE(IErrorInfo)         *lpvtei;
117         ICOM_VTABLE(ICreateErrorInfo)   *lpvtcei;
118         ICOM_VTABLE(ISupportErrorInfo)  *lpvtsei;
119         DWORD                           ref;
120         
121         GUID m_Guid;
122         BSTR bstrSource;
123         BSTR bstrDescription;
124         BSTR bstrHelpFile;
125         DWORD m_dwHelpContext;
126 } ErrorInfoImpl;
127
128 static ICOM_VTABLE(IErrorInfo)          IErrorInfoImpl_VTable;
129 static ICOM_VTABLE(ICreateErrorInfo)    ICreateErrorInfoImpl_VTable;
130 static ICOM_VTABLE(ISupportErrorInfo)   ISupportErrorInfoImpl_VTable;
131
132 /*
133  converts a objectpointer to This
134  */
135 #define _IErrorInfo_Offset ((int)(&(((ErrorInfoImpl*)0)->lpvtei))) 
136 #define _ICOM_THIS_From_IErrorInfo(class, name) class* This = (class*)(((char*)name)-_IErrorInfo_Offset); 
137
138 #define _ICreateErrorInfo_Offset ((int)(&(((ErrorInfoImpl*)0)->lpvtcei))) 
139 #define _ICOM_THIS_From_ICreateErrorInfo(class, name) class* This = (class*)(((char*)name)-_ICreateErrorInfo_Offset); 
140
141 #define _ISupportErrorInfo_Offset ((int)(&(((ErrorInfoImpl*)0)->lpvtsei))) 
142 #define _ICOM_THIS_From_ISupportErrorInfo(class, name) class* This = (class*)(((char*)name)-_ISupportErrorInfo_Offset); 
143
144 /*
145  converts This to a objectpointer
146  */
147 #define _IErrorInfo_(This)              (IErrorInfo*)&(This->lpvtei)
148 #define _ICreateErrorInfo_(This)        (ICreateErrorInfo*)&(This->lpvtcei)
149 #define _ISupportErrorInfo_(This)       (ISupportErrorInfo*)&(This->lpvtsei)
150
151 IErrorInfo * IErrorInfoImpl_Constructor()
152 {
153         ErrorInfoImpl * ei = HeapAlloc(GetProcessHeap(), 0, sizeof(ErrorInfoImpl));
154         if (ei)
155         {
156           ei->lpvtei = &IErrorInfoImpl_VTable;
157           ei->lpvtcei = &ICreateErrorInfoImpl_VTable;
158           ei->lpvtsei = &ISupportErrorInfoImpl_VTable;
159           ei->ref = 1;
160           ei->bstrSource = NULL;
161           ei->bstrDescription = NULL;
162           ei->bstrHelpFile = NULL;
163           ei->m_dwHelpContext = 0;
164         }
165         return (IErrorInfo *)ei;
166 }
167
168
169 static HRESULT WINAPI IErrorInfoImpl_QueryInterface(
170         IErrorInfo* iface,
171         REFIID     riid,
172         VOID**     ppvoid)
173 {
174         _ICOM_THIS_From_IErrorInfo(ErrorInfoImpl, iface);
175         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvoid);
176
177         *ppvoid = NULL;
178
179         if(IsEqualIID(riid, &IID_IErrorInfo))
180         {
181           *ppvoid = _IErrorInfo_(This); 
182         }
183         else if(IsEqualIID(riid, &IID_ICreateErrorInfo))
184         {
185           *ppvoid = _ICreateErrorInfo_(This);
186         }
187         else if(IsEqualIID(riid, &IID_ISupportErrorInfo))
188         {
189           *ppvoid = _ISupportErrorInfo_(This);
190         }
191
192         if(*ppvoid)
193         {
194           IUnknown_AddRef( (IUnknown*)*ppvoid );
195           TRACE("-- Interface: (%p)->(%p)\n",ppvoid,*ppvoid);
196           return S_OK;
197         }
198         TRACE("-- Interface: E_NOINTERFACE\n");
199         return E_NOINTERFACE;
200 }
201
202 static ULONG WINAPI IErrorInfoImpl_AddRef(
203         IErrorInfo* iface)
204 {
205         _ICOM_THIS_From_IErrorInfo(ErrorInfoImpl, iface);
206         TRACE("(%p)->(count=%lu)\n",This,This->ref);
207         return InterlockedIncrement(&This->ref);
208 }
209
210 static ULONG WINAPI IErrorInfoImpl_Release(
211         IErrorInfo* iface)
212 {
213         _ICOM_THIS_From_IErrorInfo(ErrorInfoImpl, iface);
214         TRACE("(%p)->(count=%lu)\n",This,This->ref);
215
216         if (!InterlockedDecrement(&This->ref))
217         {
218           TRACE("-- destroying IErrorInfo(%p)\n",This);
219           HeapFree(GetProcessHeap(),0,This);
220           return 0;
221         }
222         return This->ref;
223 }
224
225 static HRESULT WINAPI IErrorInfoImpl_GetGUID(
226         IErrorInfo* iface,
227         GUID * pGUID) 
228 {
229         _ICOM_THIS_From_IErrorInfo(ErrorInfoImpl, iface);
230         TRACE("(%p)->(count=%lu)\n",This,This->ref);
231         if(!pGUID )return E_INVALIDARG;
232         memcpy(pGUID, &This->m_Guid, sizeof(GUID));
233         return S_OK;
234 }
235
236 static HRESULT WINAPI IErrorInfoImpl_GetSource(
237         IErrorInfo* iface,
238         BSTR *pBstrSource)
239 {
240         _ICOM_THIS_From_IErrorInfo(ErrorInfoImpl, iface);
241         TRACE("(%p)->(pBstrSource=%p)\n",This,pBstrSource);
242         if (pBstrSource == NULL)
243             return E_INVALIDARG;
244         *pBstrSource = ERRORINFO_SysAllocString(This->bstrSource);
245         return S_OK;
246 }
247
248 static HRESULT WINAPI IErrorInfoImpl_GetDescription(
249         IErrorInfo* iface,
250         BSTR *pBstrDescription)
251 {
252         _ICOM_THIS_From_IErrorInfo(ErrorInfoImpl, iface);
253
254         TRACE("(%p)->(pBstrDescription=%p)\n",This,pBstrDescription);
255         if (pBstrDescription == NULL)
256             return E_INVALIDARG;
257         *pBstrDescription = ERRORINFO_SysAllocString(This->bstrDescription);
258         
259         return S_OK;
260 }
261
262 static HRESULT WINAPI IErrorInfoImpl_GetHelpFile(
263         IErrorInfo* iface,
264         BSTR *pBstrHelpFile)
265 {
266         _ICOM_THIS_From_IErrorInfo(ErrorInfoImpl, iface);
267
268         TRACE("(%p)->(pBstrHelpFile=%p)\n",This, pBstrHelpFile);
269         if (pBstrHelpFile == NULL)
270             return E_INVALIDARG;
271         *pBstrHelpFile = ERRORINFO_SysAllocString(This->bstrHelpFile);
272         
273         return S_OK;
274 }
275
276 static HRESULT WINAPI IErrorInfoImpl_GetHelpContext(
277         IErrorInfo* iface,
278         DWORD *pdwHelpContext)
279 {
280         _ICOM_THIS_From_IErrorInfo(ErrorInfoImpl, iface);
281         TRACE("(%p)->(pdwHelpContext=%p)\n",This, pdwHelpContext);
282         if (pdwHelpContext == NULL)
283             return E_INVALIDARG;
284         *pdwHelpContext = This->m_dwHelpContext;
285         
286         return S_OK;
287 }
288
289 static ICOM_VTABLE(IErrorInfo) IErrorInfoImpl_VTable =
290 {
291   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
292   IErrorInfoImpl_QueryInterface,
293   IErrorInfoImpl_AddRef,
294   IErrorInfoImpl_Release,
295  
296   IErrorInfoImpl_GetGUID,
297   IErrorInfoImpl_GetSource,
298   IErrorInfoImpl_GetDescription,
299   IErrorInfoImpl_GetHelpFile,
300   IErrorInfoImpl_GetHelpContext
301 };
302
303
304 static HRESULT WINAPI ICreateErrorInfoImpl_QueryInterface(
305         ICreateErrorInfo* iface,
306         REFIID     riid,
307         VOID**     ppvoid)
308 {
309         _ICOM_THIS_From_ICreateErrorInfo(ErrorInfoImpl, iface);
310         TRACE("(%p)\n", This);
311         return IErrorInfo_QueryInterface(_IErrorInfo_(This), riid, ppvoid);
312 }
313
314 static ULONG WINAPI ICreateErrorInfoImpl_AddRef(
315         ICreateErrorInfo* iface)
316 {
317         _ICOM_THIS_From_ICreateErrorInfo(ErrorInfoImpl, iface);
318         TRACE("(%p)\n", This);
319         return IErrorInfo_AddRef(_IErrorInfo_(This));
320 }
321
322 static ULONG WINAPI ICreateErrorInfoImpl_Release(
323         ICreateErrorInfo* iface)
324 {
325         _ICOM_THIS_From_ICreateErrorInfo(ErrorInfoImpl, iface);
326         TRACE("(%p)\n", This);
327         return IErrorInfo_Release(_IErrorInfo_(This));
328 }
329
330
331 static HRESULT WINAPI ICreateErrorInfoImpl_SetGUID(
332         ICreateErrorInfo* iface,
333         REFGUID rguid)
334 {
335         _ICOM_THIS_From_ICreateErrorInfo(ErrorInfoImpl, iface);
336         TRACE("(%p)->(%s)\n", This, debugstr_guid(rguid));
337         memcpy(&This->m_Guid,  rguid, sizeof(GUID));
338         return S_OK;
339 }
340
341 static HRESULT WINAPI ICreateErrorInfoImpl_SetSource(
342         ICreateErrorInfo* iface,
343         LPOLESTR szSource)
344 {
345         _ICOM_THIS_From_ICreateErrorInfo(ErrorInfoImpl, iface);
346         TRACE("(%p)\n",This);
347         if (This->bstrSource != NULL)
348             ERRORINFO_SysFreeString(This->bstrSource);
349         This->bstrSource = ERRORINFO_SysAllocString(szSource);
350         
351         return S_OK;
352 }
353
354 static HRESULT WINAPI ICreateErrorInfoImpl_SetDescription(
355         ICreateErrorInfo* iface,
356         LPOLESTR szDescription)
357 {
358         _ICOM_THIS_From_ICreateErrorInfo(ErrorInfoImpl, iface);
359         TRACE("(%p)\n",This);
360         if (This->bstrDescription != NULL)
361             ERRORINFO_SysFreeString(This->bstrDescription);
362         This->bstrDescription = ERRORINFO_SysAllocString(szDescription);
363         
364         return S_OK;
365 }
366
367 static HRESULT WINAPI ICreateErrorInfoImpl_SetHelpFile(
368         ICreateErrorInfo* iface,
369         LPOLESTR szHelpFile)
370 {
371         _ICOM_THIS_From_ICreateErrorInfo(ErrorInfoImpl, iface);
372         TRACE("(%p)\n",This);
373         if (This->bstrHelpFile != NULL)
374             ERRORINFO_SysFreeString(This->bstrHelpFile);
375         This->bstrHelpFile = ERRORINFO_SysAllocString(szHelpFile);
376
377         return S_OK;
378 }
379
380 static HRESULT WINAPI ICreateErrorInfoImpl_SetHelpContext(
381         ICreateErrorInfo* iface,
382         DWORD dwHelpContext)
383 {
384         _ICOM_THIS_From_ICreateErrorInfo(ErrorInfoImpl, iface);
385         TRACE("(%p)\n",This);
386         This->m_dwHelpContext = dwHelpContext;
387         
388         return S_OK;
389 }
390
391 static ICOM_VTABLE(ICreateErrorInfo) ICreateErrorInfoImpl_VTable =
392 {
393   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
394   ICreateErrorInfoImpl_QueryInterface,
395   ICreateErrorInfoImpl_AddRef,
396   ICreateErrorInfoImpl_Release,
397
398   ICreateErrorInfoImpl_SetGUID,
399   ICreateErrorInfoImpl_SetSource,
400   ICreateErrorInfoImpl_SetDescription,
401   ICreateErrorInfoImpl_SetHelpFile,
402   ICreateErrorInfoImpl_SetHelpContext
403 };
404
405 static HRESULT WINAPI ISupportErrorInfoImpl_QueryInterface(
406         ISupportErrorInfo* iface,
407         REFIID     riid,
408         VOID**     ppvoid)
409 {
410         _ICOM_THIS_From_ISupportErrorInfo(ErrorInfoImpl, iface);
411         TRACE("(%p)\n", This);
412         
413         return IErrorInfo_QueryInterface(_IErrorInfo_(This), riid, ppvoid);
414 }
415
416 static ULONG WINAPI ISupportErrorInfoImpl_AddRef(
417         ISupportErrorInfo* iface)
418 {
419         _ICOM_THIS_From_ISupportErrorInfo(ErrorInfoImpl, iface);
420         TRACE("(%p)\n", This);
421         return IErrorInfo_AddRef(_IErrorInfo_(This));
422 }
423
424 static ULONG WINAPI ISupportErrorInfoImpl_Release(
425         ISupportErrorInfo* iface)
426 {
427         _ICOM_THIS_From_ISupportErrorInfo(ErrorInfoImpl, iface);
428         TRACE("(%p)\n", This);
429         return IErrorInfo_Release(_IErrorInfo_(This));
430 }
431
432
433 static HRESULT WINAPI ISupportErrorInfoImpl_InterfaceSupportsErrorInfo(
434         ISupportErrorInfo* iface,
435         REFIID riid)
436 {
437         _ICOM_THIS_From_ISupportErrorInfo(ErrorInfoImpl, iface);
438         TRACE("(%p)->(%s)\n", This, debugstr_guid(riid));
439         return (IsEqualIID(riid, &This->m_Guid)) ? S_OK : S_FALSE;
440 }
441
442 static ICOM_VTABLE(ISupportErrorInfo) ISupportErrorInfoImpl_VTable =
443 {
444   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
445   ISupportErrorInfoImpl_QueryInterface,
446   ISupportErrorInfoImpl_AddRef,
447   ISupportErrorInfoImpl_Release,
448
449
450   ISupportErrorInfoImpl_InterfaceSupportsErrorInfo
451 };
452 /***********************************************************************
453  *              CreateErrorInfo (OLE32.192)
454  */
455 HRESULT WINAPI CreateErrorInfo(ICreateErrorInfo **pperrinfo)
456 {
457         IErrorInfo * pei;
458         HRESULT res;
459         TRACE("(%p): stub:\n", pperrinfo);
460         if(! pperrinfo ) return E_INVALIDARG;
461         if(!(pei=IErrorInfoImpl_Constructor()))return E_OUTOFMEMORY;
462         
463         res = IErrorInfo_QueryInterface(pei, &IID_ICreateErrorInfo, (LPVOID*)pperrinfo);
464         IErrorInfo_Release(pei);
465         return res;
466 }
467
468 /***********************************************************************
469  *              GetErrorInfo (OLE32.196)
470  */
471 HRESULT WINAPI GetErrorInfo(ULONG dwReserved, IErrorInfo **pperrinfo)
472 {
473         TRACE("(%ld, %p, %p): stub:\n", dwReserved, pperrinfo, NtCurrentTeb()->ErrorInfo);
474
475         if(! pperrinfo ) return E_INVALIDARG;
476         if(!(*pperrinfo = (IErrorInfo*)(NtCurrentTeb()->ErrorInfo))) return S_FALSE;
477
478         /* clear thread error state */
479         NtCurrentTeb()->ErrorInfo = NULL;
480         return S_OK;
481 }
482
483 /***********************************************************************
484  *              SetErrorInfo (OLE32.255)
485  */
486 HRESULT WINAPI SetErrorInfo(ULONG dwReserved, IErrorInfo *perrinfo)
487 {
488         IErrorInfo * pei;
489         TRACE("(%ld, %p): stub:\n", dwReserved, perrinfo);
490
491         /* release old errorinfo */
492         pei = (IErrorInfo*)NtCurrentTeb()->ErrorInfo;
493         if(pei) IErrorInfo_Release(pei);
494
495         /* set to new value */
496         NtCurrentTeb()->ErrorInfo = perrinfo;
497         if(perrinfo) IErrorInfo_AddRef(perrinfo);
498         return S_OK;
499 }