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