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