1 /* 2 * ErrorInfo API 3 * 4 * Copyright 2000 Patrik Stridvall, Juergen Schmied 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 * 20 * NOTES: 21 * 22 * The errorinfo is a per-thread object. The reference is stored in the 23 * TEB at offset 0xf80. 24 */ 25 26 #include <stdarg.h> 27 #include <string.h> 28 29 #define COBJMACROS 30 31 #include "windef.h" 32 #include "winbase.h" 33 #include "objbase.h" 34 #include "oleauto.h" 35 #include "winerror.h" 36 37 #include "wine/unicode.h" 38 #include "compobj_private.h" 39 40 #include "wine/debug.h" 41 42 WINE_DEFAULT_DEBUG_CHANNEL(ole); 43 44 static inline WCHAR *heap_strdupW(const WCHAR *str) 45 { 46 WCHAR *ret = NULL; 47 48 if(str) { 49 size_t size; 50 51 size = (strlenW(str)+1)*sizeof(WCHAR); 52 ret = heap_alloc(size); 53 if(ret) 54 memcpy(ret, str, size); 55 } 56 57 return ret; 58 } 59 60 typedef struct ErrorInfoImpl 61 { 62 IErrorInfo IErrorInfo_iface; 63 ICreateErrorInfo ICreateErrorInfo_iface; 64 ISupportErrorInfo ISupportErrorInfo_iface; 65 LONG ref; 66 67 GUID m_Guid; 68 WCHAR *source; 69 WCHAR *description; 70 WCHAR *help_file; 71 DWORD m_dwHelpContext; 72 } ErrorInfoImpl; 73 74 static inline ErrorInfoImpl *impl_from_IErrorInfo( IErrorInfo *iface ) 75 { 76 return CONTAINING_RECORD(iface, ErrorInfoImpl, IErrorInfo_iface); 77 } 78 79 static inline ErrorInfoImpl *impl_from_ICreateErrorInfo( ICreateErrorInfo *iface ) 80 { 81 return CONTAINING_RECORD(iface, ErrorInfoImpl, ICreateErrorInfo_iface); 82 } 83 84 static inline ErrorInfoImpl *impl_from_ISupportErrorInfo( ISupportErrorInfo *iface ) 85 { 86 return CONTAINING_RECORD(iface, ErrorInfoImpl, ISupportErrorInfo_iface); 87 } 88 89 static HRESULT WINAPI IErrorInfoImpl_QueryInterface( 90 IErrorInfo* iface, 91 REFIID riid, 92 void** ppvoid) 93 { 94 ErrorInfoImpl *This = impl_from_IErrorInfo(iface); 95 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid),ppvoid); 96 97 *ppvoid = NULL; 98 99 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IErrorInfo)) 100 { 101 *ppvoid = &This->IErrorInfo_iface; 102 } 103 else if(IsEqualIID(riid, &IID_ICreateErrorInfo)) 104 { 105 *ppvoid = &This->ICreateErrorInfo_iface; 106 } 107 else if(IsEqualIID(riid, &IID_ISupportErrorInfo)) 108 { 109 *ppvoid = &This->ISupportErrorInfo_iface; 110 } 111 112 if(*ppvoid) 113 { 114 IUnknown_AddRef( (IUnknown*)*ppvoid ); 115 TRACE("-- Interface: (%p)->(%p)\n",ppvoid,*ppvoid); 116 return S_OK; 117 } 118 TRACE("-- Interface: E_NOINTERFACE\n"); 119 return E_NOINTERFACE; 120 } 121 122 static ULONG WINAPI IErrorInfoImpl_AddRef( 123 IErrorInfo* iface) 124 { 125 ErrorInfoImpl *This = impl_from_IErrorInfo(iface); 126 TRACE("(%p)->(count=%u)\n",This,This->ref); 127 return InterlockedIncrement(&This->ref); 128 } 129 130 static ULONG WINAPI IErrorInfoImpl_Release( 131 IErrorInfo* iface) 132 { 133 ErrorInfoImpl *This = impl_from_IErrorInfo(iface); 134 ULONG ref = InterlockedDecrement(&This->ref); 135 136 TRACE("(%p)->(count=%u)\n",This,ref+1); 137 138 if (!ref) 139 { 140 TRACE("-- destroying IErrorInfo(%p)\n",This); 141 142 heap_free(This->source); 143 heap_free(This->description); 144 heap_free(This->help_file); 145 heap_free(This); 146 } 147 return ref; 148 } 149 150 static HRESULT WINAPI IErrorInfoImpl_GetGUID( 151 IErrorInfo* iface, 152 GUID * pGUID) 153 { 154 ErrorInfoImpl *This = impl_from_IErrorInfo(iface); 155 TRACE("(%p)->(count=%u)\n",This,This->ref); 156 if(!pGUID )return E_INVALIDARG; 157 *pGUID = This->m_Guid; 158 return S_OK; 159 } 160 161 static HRESULT WINAPI IErrorInfoImpl_GetSource( 162 IErrorInfo* iface, 163 BSTR *pBstrSource) 164 { 165 ErrorInfoImpl *This = impl_from_IErrorInfo(iface); 166 TRACE("(%p)->(pBstrSource=%p)\n",This,pBstrSource); 167 if (pBstrSource == NULL) 168 return E_INVALIDARG; 169 *pBstrSource = SysAllocString(This->source); 170 return S_OK; 171 } 172 173 static HRESULT WINAPI IErrorInfoImpl_GetDescription( 174 IErrorInfo* iface, 175 BSTR *pBstrDescription) 176 { 177 ErrorInfoImpl *This = impl_from_IErrorInfo(iface); 178 179 TRACE("(%p)->(pBstrDescription=%p)\n",This,pBstrDescription); 180 if (pBstrDescription == NULL) 181 return E_INVALIDARG; 182 *pBstrDescription = SysAllocString(This->description); 183 184 return S_OK; 185 } 186 187 static HRESULT WINAPI IErrorInfoImpl_GetHelpFile( 188 IErrorInfo* iface, 189 BSTR *pBstrHelpFile) 190 { 191 ErrorInfoImpl *This = impl_from_IErrorInfo(iface); 192 193 TRACE("(%p)->(pBstrHelpFile=%p)\n",This, pBstrHelpFile); 194 if (pBstrHelpFile == NULL) 195 return E_INVALIDARG; 196 *pBstrHelpFile = SysAllocString(This->help_file); 197 198 return S_OK; 199 } 200 201 static HRESULT WINAPI IErrorInfoImpl_GetHelpContext( 202 IErrorInfo* iface, 203 DWORD *pdwHelpContext) 204 { 205 ErrorInfoImpl *This = impl_from_IErrorInfo(iface); 206 TRACE("(%p)->(pdwHelpContext=%p)\n",This, pdwHelpContext); 207 if (pdwHelpContext == NULL) 208 return E_INVALIDARG; 209 *pdwHelpContext = This->m_dwHelpContext; 210 211 return S_OK; 212 } 213 214 static const IErrorInfoVtbl ErrorInfoVtbl = 215 { 216 IErrorInfoImpl_QueryInterface, 217 IErrorInfoImpl_AddRef, 218 IErrorInfoImpl_Release, 219 IErrorInfoImpl_GetGUID, 220 IErrorInfoImpl_GetSource, 221 IErrorInfoImpl_GetDescription, 222 IErrorInfoImpl_GetHelpFile, 223 IErrorInfoImpl_GetHelpContext 224 }; 225 226 227 static HRESULT WINAPI ICreateErrorInfoImpl_QueryInterface( 228 ICreateErrorInfo* iface, 229 REFIID riid, 230 VOID** ppvoid) 231 { 232 ErrorInfoImpl *This = impl_from_ICreateErrorInfo(iface); 233 return IErrorInfo_QueryInterface(&This->IErrorInfo_iface, riid, ppvoid); 234 } 235 236 static ULONG WINAPI ICreateErrorInfoImpl_AddRef( 237 ICreateErrorInfo* iface) 238 { 239 ErrorInfoImpl *This = impl_from_ICreateErrorInfo(iface); 240 return IErrorInfo_AddRef(&This->IErrorInfo_iface); 241 } 242 243 static ULONG WINAPI ICreateErrorInfoImpl_Release( 244 ICreateErrorInfo* iface) 245 { 246 ErrorInfoImpl *This = impl_from_ICreateErrorInfo(iface); 247 return IErrorInfo_Release(&This->IErrorInfo_iface); 248 } 249 250 251 static HRESULT WINAPI ICreateErrorInfoImpl_SetGUID( 252 ICreateErrorInfo* iface, 253 REFGUID rguid) 254 { 255 ErrorInfoImpl *This = impl_from_ICreateErrorInfo(iface); 256 TRACE("(%p)->(%s)\n", This, debugstr_guid(rguid)); 257 This->m_Guid = *rguid; 258 return S_OK; 259 } 260 261 static HRESULT WINAPI ICreateErrorInfoImpl_SetSource( 262 ICreateErrorInfo* iface, 263 LPOLESTR szSource) 264 { 265 ErrorInfoImpl *This = impl_from_ICreateErrorInfo(iface); 266 TRACE("(%p): %s\n",This, debugstr_w(szSource)); 267 268 heap_free(This->source); 269 This->source = heap_strdupW(szSource); 270 271 return S_OK; 272 } 273 274 static HRESULT WINAPI ICreateErrorInfoImpl_SetDescription( 275 ICreateErrorInfo* iface, 276 LPOLESTR szDescription) 277 { 278 ErrorInfoImpl *This = impl_from_ICreateErrorInfo(iface); 279 TRACE("(%p): %s\n",This, debugstr_w(szDescription)); 280 281 heap_free(This->description); 282 This->description = heap_strdupW(szDescription); 283 return S_OK; 284 } 285 286 static HRESULT WINAPI ICreateErrorInfoImpl_SetHelpFile( 287 ICreateErrorInfo* iface, 288 LPOLESTR szHelpFile) 289 { 290 ErrorInfoImpl *This = impl_from_ICreateErrorInfo(iface); 291 TRACE("(%p,%s)\n",This,debugstr_w(szHelpFile)); 292 heap_free(This->help_file); 293 This->help_file = heap_strdupW(szHelpFile); 294 return S_OK; 295 } 296 297 static HRESULT WINAPI ICreateErrorInfoImpl_SetHelpContext( 298 ICreateErrorInfo* iface, 299 DWORD dwHelpContext) 300 { 301 ErrorInfoImpl *This = impl_from_ICreateErrorInfo(iface); 302 TRACE("(%p,%d)\n",This,dwHelpContext); 303 This->m_dwHelpContext = dwHelpContext; 304 return S_OK; 305 } 306 307 static const ICreateErrorInfoVtbl CreateErrorInfoVtbl = 308 { 309 ICreateErrorInfoImpl_QueryInterface, 310 ICreateErrorInfoImpl_AddRef, 311 ICreateErrorInfoImpl_Release, 312 ICreateErrorInfoImpl_SetGUID, 313 ICreateErrorInfoImpl_SetSource, 314 ICreateErrorInfoImpl_SetDescription, 315 ICreateErrorInfoImpl_SetHelpFile, 316 ICreateErrorInfoImpl_SetHelpContext 317 }; 318 319 static HRESULT WINAPI ISupportErrorInfoImpl_QueryInterface( 320 ISupportErrorInfo* iface, 321 REFIID riid, 322 VOID** ppvoid) 323 { 324 ErrorInfoImpl *This = impl_from_ISupportErrorInfo(iface); 325 return IErrorInfo_QueryInterface(&This->IErrorInfo_iface, riid, ppvoid); 326 } 327 328 static ULONG WINAPI ISupportErrorInfoImpl_AddRef(ISupportErrorInfo* iface) 329 { 330 ErrorInfoImpl *This = impl_from_ISupportErrorInfo(iface); 331 return IErrorInfo_AddRef(&This->IErrorInfo_iface); 332 } 333 334 static ULONG WINAPI ISupportErrorInfoImpl_Release(ISupportErrorInfo* iface) 335 { 336 ErrorInfoImpl *This = impl_from_ISupportErrorInfo(iface); 337 return IErrorInfo_Release(&This->IErrorInfo_iface); 338 } 339 340 static HRESULT WINAPI ISupportErrorInfoImpl_InterfaceSupportsErrorInfo( 341 ISupportErrorInfo* iface, 342 REFIID riid) 343 { 344 ErrorInfoImpl *This = impl_from_ISupportErrorInfo(iface); 345 TRACE("(%p)->(%s)\n", This, debugstr_guid(riid)); 346 return (IsEqualIID(riid, &This->m_Guid)) ? S_OK : S_FALSE; 347 } 348 349 static const ISupportErrorInfoVtbl SupportErrorInfoVtbl = 350 { 351 ISupportErrorInfoImpl_QueryInterface, 352 ISupportErrorInfoImpl_AddRef, 353 ISupportErrorInfoImpl_Release, 354 ISupportErrorInfoImpl_InterfaceSupportsErrorInfo 355 }; 356 357 static IErrorInfo* IErrorInfoImpl_Constructor(void) 358 { 359 ErrorInfoImpl *This = heap_alloc(sizeof(ErrorInfoImpl)); 360 361 if (!This) return NULL; 362 363 This->IErrorInfo_iface.lpVtbl = &ErrorInfoVtbl; 364 This->ICreateErrorInfo_iface.lpVtbl = &CreateErrorInfoVtbl; 365 This->ISupportErrorInfo_iface.lpVtbl = &SupportErrorInfoVtbl; 366 This->ref = 1; 367 This->source = NULL; 368 This->description = NULL; 369 This->help_file = NULL; 370 This->m_dwHelpContext = 0; 371 372 return &This->IErrorInfo_iface; 373 } 374 375 /*********************************************************************** 376 * CreateErrorInfo (OLE32.@) 377 * 378 * Creates an object used to set details for an error info object. 379 * 380 * PARAMS 381 * pperrinfo [O]. Address where error info creation object will be stored. 382 * 383 * RETURNS 384 * Success: S_OK. 385 * Failure: HRESULT code. 386 */ 387 HRESULT WINAPI CreateErrorInfo(ICreateErrorInfo **pperrinfo) 388 { 389 IErrorInfo * pei; 390 HRESULT res; 391 TRACE("(%p)\n", pperrinfo); 392 if(! pperrinfo ) return E_INVALIDARG; 393 if(!(pei=IErrorInfoImpl_Constructor()))return E_OUTOFMEMORY; 394 395 res = IErrorInfo_QueryInterface(pei, &IID_ICreateErrorInfo, (LPVOID*)pperrinfo); 396 IErrorInfo_Release(pei); 397 return res; 398 } 399 400 /*********************************************************************** 401 * GetErrorInfo (OLE32.@) 402 * 403 * Retrieves the error information object for the current thread. 404 * 405 * PARAMS 406 * dwReserved [I]. Reserved. Must be zero. 407 * pperrinfo [O]. Address where error information object will be stored on return. 408 * 409 * RETURNS 410 * Success: S_OK if an error information object was set for the current thread. 411 * S_FALSE if otherwise. 412 * Failure: E_INVALIDARG if dwReserved is not zero. 413 * 414 * NOTES 415 * This function causes the current error info object for the thread to be 416 * cleared if one was set beforehand. 417 */ 418 HRESULT WINAPI GetErrorInfo(ULONG dwReserved, IErrorInfo **pperrinfo) 419 { 420 TRACE("(%d, %p, %p)\n", dwReserved, pperrinfo, COM_CurrentInfo()->errorinfo); 421 422 if (dwReserved) 423 { 424 ERR("dwReserved (0x%x) != 0\n", dwReserved); 425 return E_INVALIDARG; 426 } 427 428 if(!pperrinfo) return E_INVALIDARG; 429 430 if (!COM_CurrentInfo()->errorinfo) 431 { 432 *pperrinfo = NULL; 433 return S_FALSE; 434 } 435 436 *pperrinfo = COM_CurrentInfo()->errorinfo; 437 438 /* clear thread error state */ 439 COM_CurrentInfo()->errorinfo = NULL; 440 return S_OK; 441 } 442 443 /*********************************************************************** 444 * SetErrorInfo (OLE32.@) 445 * 446 * Sets the error information object for the current thread. 447 * 448 * PARAMS 449 * dwReserved [I] Reserved. Must be zero. 450 * perrinfo [I] Error info object. 451 * 452 * RETURNS 453 * Success: S_OK. 454 * Failure: E_INVALIDARG if dwReserved is not zero. 455 */ 456 HRESULT WINAPI SetErrorInfo(ULONG dwReserved, IErrorInfo *perrinfo) 457 { 458 IErrorInfo * pei; 459 460 TRACE("(%d, %p)\n", dwReserved, perrinfo); 461 462 if (dwReserved) 463 { 464 ERR("dwReserved (0x%x) != 0\n", dwReserved); 465 return E_INVALIDARG; 466 } 467 468 /* release old errorinfo */ 469 pei = COM_CurrentInfo()->errorinfo; 470 if (pei) IErrorInfo_Release(pei); 471 472 /* set to new value */ 473 COM_CurrentInfo()->errorinfo = perrinfo; 474 if (perrinfo) IErrorInfo_AddRef(perrinfo); 475 476 return S_OK; 477 } 478