4 * Copyright 2000 Patrik Stridvall, Juergen Schmied
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.
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.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 * The errorinfo is a per-thread object. The reference is stored in the
23 * TEB at offset 0xf80.
37 #include "wine/unicode.h"
38 #include "compobj_private.h"
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
44 static inline void *heap_alloc(size_t len
)
46 return HeapAlloc(GetProcessHeap(), 0, len
);
49 static inline BOOL
heap_free(void *mem
)
51 return HeapFree(GetProcessHeap(), 0, mem
);
54 static inline WCHAR
*heap_strdupW(const WCHAR
*str
)
61 size
= (strlenW(str
)+1)*sizeof(WCHAR
);
62 ret
= heap_alloc(size
);
64 memcpy(ret
, str
, size
);
70 /* this code is from SysAllocStringLen (ole2disp.c in oleaut32) */
71 static BSTR
ERRORINFO_SysAllocString(const OLECHAR
* in
)
81 * Find the length of the buffer passed-in, in bytes.
84 bufferSize
= len
* sizeof (WCHAR
);
87 * Allocate a new buffer to hold the string.
88 * don't forget to keep an empty spot at the beginning of the
89 * buffer for the character count and an extra character at the
92 newBuffer
= HeapAlloc(GetProcessHeap(), 0,
93 bufferSize
+ sizeof(WCHAR
) + sizeof(DWORD
));
96 * If the memory allocation failed, return a null pointer.
102 * Copy the length of the string in the placeholder.
104 *newBuffer
= bufferSize
;
107 * Skip the byte count.
112 * Copy the information in the buffer. It is not possible to pass
113 * a NULL pointer here.
115 memcpy(newBuffer
, in
, bufferSize
);
118 * Make sure that there is a nul character at the end of the
121 stringBuffer
= (WCHAR
*)newBuffer
;
122 stringBuffer
[len
] = 0;
127 /* this code is from SysFreeString (ole2disp.c in oleaut32)*/
128 static VOID
ERRORINFO_SysFreeString(BSTR in
)
130 DWORD
* bufferPointer
;
132 /* NULL is a valid parameter */
136 * We have to be careful when we free a BSTR pointer, it points to
137 * the beginning of the string but it skips the byte count contained
140 bufferPointer
= (DWORD
*)in
;
145 * Free the memory from it's "real" origin.
147 HeapFree(GetProcessHeap(), 0, bufferPointer
);
150 typedef struct ErrorInfoImpl
152 IErrorInfo IErrorInfo_iface
;
153 ICreateErrorInfo ICreateErrorInfo_iface
;
154 ISupportErrorInfo ISupportErrorInfo_iface
;
161 DWORD m_dwHelpContext
;
164 static inline ErrorInfoImpl
*impl_from_IErrorInfo( IErrorInfo
*iface
)
166 return CONTAINING_RECORD(iface
, ErrorInfoImpl
, IErrorInfo_iface
);
169 static inline ErrorInfoImpl
*impl_from_ICreateErrorInfo( ICreateErrorInfo
*iface
)
171 return CONTAINING_RECORD(iface
, ErrorInfoImpl
, ICreateErrorInfo_iface
);
174 static inline ErrorInfoImpl
*impl_from_ISupportErrorInfo( ISupportErrorInfo
*iface
)
176 return CONTAINING_RECORD(iface
, ErrorInfoImpl
, ISupportErrorInfo_iface
);
179 static HRESULT WINAPI
IErrorInfoImpl_QueryInterface(
184 ErrorInfoImpl
*This
= impl_from_IErrorInfo(iface
);
185 TRACE("(%p)->(%s,%p)\n", This
, debugstr_guid(riid
),ppvoid
);
189 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IErrorInfo
))
191 *ppvoid
= &This
->IErrorInfo_iface
;
193 else if(IsEqualIID(riid
, &IID_ICreateErrorInfo
))
195 *ppvoid
= &This
->ICreateErrorInfo_iface
;
197 else if(IsEqualIID(riid
, &IID_ISupportErrorInfo
))
199 *ppvoid
= &This
->ISupportErrorInfo_iface
;
204 IUnknown_AddRef( (IUnknown
*)*ppvoid
);
205 TRACE("-- Interface: (%p)->(%p)\n",ppvoid
,*ppvoid
);
208 TRACE("-- Interface: E_NOINTERFACE\n");
209 return E_NOINTERFACE
;
212 static ULONG WINAPI
IErrorInfoImpl_AddRef(
215 ErrorInfoImpl
*This
= impl_from_IErrorInfo(iface
);
216 TRACE("(%p)->(count=%u)\n",This
,This
->ref
);
217 return InterlockedIncrement(&This
->ref
);
220 static ULONG WINAPI
IErrorInfoImpl_Release(
223 ErrorInfoImpl
*This
= impl_from_IErrorInfo(iface
);
224 ULONG ref
= InterlockedDecrement(&This
->ref
);
226 TRACE("(%p)->(count=%u)\n",This
,ref
+1);
230 TRACE("-- destroying IErrorInfo(%p)\n",This
);
232 heap_free(This
->source
);
233 heap_free(This
->description
);
234 ERRORINFO_SysFreeString(This
->bstrHelpFile
);
235 HeapFree(GetProcessHeap(),0,This
);
241 static HRESULT WINAPI
IErrorInfoImpl_GetGUID(
245 ErrorInfoImpl
*This
= impl_from_IErrorInfo(iface
);
246 TRACE("(%p)->(count=%u)\n",This
,This
->ref
);
247 if(!pGUID
)return E_INVALIDARG
;
248 *pGUID
= This
->m_Guid
;
252 static HRESULT WINAPI
IErrorInfoImpl_GetSource(
256 ErrorInfoImpl
*This
= impl_from_IErrorInfo(iface
);
257 TRACE("(%p)->(pBstrSource=%p)\n",This
,pBstrSource
);
258 if (pBstrSource
== NULL
)
260 *pBstrSource
= SysAllocString(This
->source
);
264 static HRESULT WINAPI
IErrorInfoImpl_GetDescription(
266 BSTR
*pBstrDescription
)
268 ErrorInfoImpl
*This
= impl_from_IErrorInfo(iface
);
270 TRACE("(%p)->(pBstrDescription=%p)\n",This
,pBstrDescription
);
271 if (pBstrDescription
== NULL
)
273 *pBstrDescription
= SysAllocString(This
->description
);
278 static HRESULT WINAPI
IErrorInfoImpl_GetHelpFile(
282 ErrorInfoImpl
*This
= impl_from_IErrorInfo(iface
);
284 TRACE("(%p)->(pBstrHelpFile=%p)\n",This
, pBstrHelpFile
);
285 if (pBstrHelpFile
== NULL
)
287 *pBstrHelpFile
= ERRORINFO_SysAllocString(This
->bstrHelpFile
);
292 static HRESULT WINAPI
IErrorInfoImpl_GetHelpContext(
294 DWORD
*pdwHelpContext
)
296 ErrorInfoImpl
*This
= impl_from_IErrorInfo(iface
);
297 TRACE("(%p)->(pdwHelpContext=%p)\n",This
, pdwHelpContext
);
298 if (pdwHelpContext
== NULL
)
300 *pdwHelpContext
= This
->m_dwHelpContext
;
305 static const IErrorInfoVtbl ErrorInfoVtbl
=
307 IErrorInfoImpl_QueryInterface
,
308 IErrorInfoImpl_AddRef
,
309 IErrorInfoImpl_Release
,
310 IErrorInfoImpl_GetGUID
,
311 IErrorInfoImpl_GetSource
,
312 IErrorInfoImpl_GetDescription
,
313 IErrorInfoImpl_GetHelpFile
,
314 IErrorInfoImpl_GetHelpContext
318 static HRESULT WINAPI
ICreateErrorInfoImpl_QueryInterface(
319 ICreateErrorInfo
* iface
,
323 ErrorInfoImpl
*This
= impl_from_ICreateErrorInfo(iface
);
324 return IErrorInfo_QueryInterface(&This
->IErrorInfo_iface
, riid
, ppvoid
);
327 static ULONG WINAPI
ICreateErrorInfoImpl_AddRef(
328 ICreateErrorInfo
* iface
)
330 ErrorInfoImpl
*This
= impl_from_ICreateErrorInfo(iface
);
331 return IErrorInfo_AddRef(&This
->IErrorInfo_iface
);
334 static ULONG WINAPI
ICreateErrorInfoImpl_Release(
335 ICreateErrorInfo
* iface
)
337 ErrorInfoImpl
*This
= impl_from_ICreateErrorInfo(iface
);
338 return IErrorInfo_Release(&This
->IErrorInfo_iface
);
342 static HRESULT WINAPI
ICreateErrorInfoImpl_SetGUID(
343 ICreateErrorInfo
* iface
,
346 ErrorInfoImpl
*This
= impl_from_ICreateErrorInfo(iface
);
347 TRACE("(%p)->(%s)\n", This
, debugstr_guid(rguid
));
348 This
->m_Guid
= *rguid
;
352 static HRESULT WINAPI
ICreateErrorInfoImpl_SetSource(
353 ICreateErrorInfo
* iface
,
356 ErrorInfoImpl
*This
= impl_from_ICreateErrorInfo(iface
);
357 TRACE("(%p): %s\n",This
, debugstr_w(szSource
));
359 heap_free(This
->source
);
360 This
->source
= heap_strdupW(szSource
);
365 static HRESULT WINAPI
ICreateErrorInfoImpl_SetDescription(
366 ICreateErrorInfo
* iface
,
367 LPOLESTR szDescription
)
369 ErrorInfoImpl
*This
= impl_from_ICreateErrorInfo(iface
);
370 TRACE("(%p): %s\n",This
, debugstr_w(szDescription
));
372 heap_free(This
->description
);
373 This
->description
= heap_strdupW(szDescription
);
377 static HRESULT WINAPI
ICreateErrorInfoImpl_SetHelpFile(
378 ICreateErrorInfo
* iface
,
381 ErrorInfoImpl
*This
= impl_from_ICreateErrorInfo(iface
);
382 TRACE("(%p,%s)\n",This
,debugstr_w(szHelpFile
));
383 if (This
->bstrHelpFile
!= NULL
)
384 ERRORINFO_SysFreeString(This
->bstrHelpFile
);
385 This
->bstrHelpFile
= ERRORINFO_SysAllocString(szHelpFile
);
389 static HRESULT WINAPI
ICreateErrorInfoImpl_SetHelpContext(
390 ICreateErrorInfo
* iface
,
393 ErrorInfoImpl
*This
= impl_from_ICreateErrorInfo(iface
);
394 TRACE("(%p,%d)\n",This
,dwHelpContext
);
395 This
->m_dwHelpContext
= dwHelpContext
;
399 static const ICreateErrorInfoVtbl CreateErrorInfoVtbl
=
401 ICreateErrorInfoImpl_QueryInterface
,
402 ICreateErrorInfoImpl_AddRef
,
403 ICreateErrorInfoImpl_Release
,
404 ICreateErrorInfoImpl_SetGUID
,
405 ICreateErrorInfoImpl_SetSource
,
406 ICreateErrorInfoImpl_SetDescription
,
407 ICreateErrorInfoImpl_SetHelpFile
,
408 ICreateErrorInfoImpl_SetHelpContext
411 static HRESULT WINAPI
ISupportErrorInfoImpl_QueryInterface(
412 ISupportErrorInfo
* iface
,
416 ErrorInfoImpl
*This
= impl_from_ISupportErrorInfo(iface
);
417 return IErrorInfo_QueryInterface(&This
->IErrorInfo_iface
, riid
, ppvoid
);
420 static ULONG WINAPI
ISupportErrorInfoImpl_AddRef(ISupportErrorInfo
* iface
)
422 ErrorInfoImpl
*This
= impl_from_ISupportErrorInfo(iface
);
423 return IErrorInfo_AddRef(&This
->IErrorInfo_iface
);
426 static ULONG WINAPI
ISupportErrorInfoImpl_Release(ISupportErrorInfo
* iface
)
428 ErrorInfoImpl
*This
= impl_from_ISupportErrorInfo(iface
);
429 return IErrorInfo_Release(&This
->IErrorInfo_iface
);
432 static HRESULT WINAPI
ISupportErrorInfoImpl_InterfaceSupportsErrorInfo(
433 ISupportErrorInfo
* iface
,
436 ErrorInfoImpl
*This
= impl_from_ISupportErrorInfo(iface
);
437 TRACE("(%p)->(%s)\n", This
, debugstr_guid(riid
));
438 return (IsEqualIID(riid
, &This
->m_Guid
)) ? S_OK
: S_FALSE
;
441 static const ISupportErrorInfoVtbl SupportErrorInfoVtbl
=
443 ISupportErrorInfoImpl_QueryInterface
,
444 ISupportErrorInfoImpl_AddRef
,
445 ISupportErrorInfoImpl_Release
,
446 ISupportErrorInfoImpl_InterfaceSupportsErrorInfo
449 static IErrorInfo
* IErrorInfoImpl_Constructor(void)
451 ErrorInfoImpl
*This
= heap_alloc(sizeof(ErrorInfoImpl
));
453 if (!This
) return NULL
;
455 This
->IErrorInfo_iface
.lpVtbl
= &ErrorInfoVtbl
;
456 This
->ICreateErrorInfo_iface
.lpVtbl
= &CreateErrorInfoVtbl
;
457 This
->ISupportErrorInfo_iface
.lpVtbl
= &SupportErrorInfoVtbl
;
460 This
->description
= NULL
;
461 This
->bstrHelpFile
= NULL
;
462 This
->m_dwHelpContext
= 0;
464 return &This
->IErrorInfo_iface
;
467 /***********************************************************************
468 * CreateErrorInfo (OLE32.@)
470 * Creates an object used to set details for an error info object.
473 * pperrinfo [O]. Address where error info creation object will be stored.
477 * Failure: HRESULT code.
479 HRESULT WINAPI
CreateErrorInfo(ICreateErrorInfo
**pperrinfo
)
483 TRACE("(%p)\n", pperrinfo
);
484 if(! pperrinfo
) return E_INVALIDARG
;
485 if(!(pei
=IErrorInfoImpl_Constructor()))return E_OUTOFMEMORY
;
487 res
= IErrorInfo_QueryInterface(pei
, &IID_ICreateErrorInfo
, (LPVOID
*)pperrinfo
);
488 IErrorInfo_Release(pei
);
492 /***********************************************************************
493 * GetErrorInfo (OLE32.@)
495 * Retrieves the error information object for the current thread.
498 * dwReserved [I]. Reserved. Must be zero.
499 * pperrinfo [O]. Address where error information object will be stored on return.
502 * Success: S_OK if an error information object was set for the current thread.
503 * S_FALSE if otherwise.
504 * Failure: E_INVALIDARG if dwReserved is not zero.
507 * This function causes the current error info object for the thread to be
508 * cleared if one was set beforehand.
510 HRESULT WINAPI
GetErrorInfo(ULONG dwReserved
, IErrorInfo
**pperrinfo
)
512 TRACE("(%d, %p, %p)\n", dwReserved
, pperrinfo
, COM_CurrentInfo()->errorinfo
);
516 ERR("dwReserved (0x%x) != 0\n", dwReserved
);
520 if(!pperrinfo
) return E_INVALIDARG
;
522 if (!COM_CurrentInfo()->errorinfo
)
528 *pperrinfo
= COM_CurrentInfo()->errorinfo
;
530 /* clear thread error state */
531 COM_CurrentInfo()->errorinfo
= NULL
;
535 /***********************************************************************
536 * SetErrorInfo (OLE32.@)
538 * Sets the error information object for the current thread.
541 * dwReserved [I] Reserved. Must be zero.
542 * perrinfo [I] Error info object.
546 * Failure: E_INVALIDARG if dwReserved is not zero.
548 HRESULT WINAPI
SetErrorInfo(ULONG dwReserved
, IErrorInfo
*perrinfo
)
552 TRACE("(%d, %p)\n", dwReserved
, perrinfo
);
556 ERR("dwReserved (0x%x) != 0\n", dwReserved
);
560 /* release old errorinfo */
561 pei
= COM_CurrentInfo()->errorinfo
;
562 if (pei
) IErrorInfo_Release(pei
);
564 /* set to new value */
565 COM_CurrentInfo()->errorinfo
= perrinfo
;
566 if (perrinfo
) IErrorInfo_AddRef(perrinfo
);