| /* | |
| * Copyright 2015, 2016 Hans Leidekker for CodeWeavers | |
| * | |
| * This library is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Lesser General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * | |
| * This library is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library; if not, write to the Free Software | |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | |
| */ | |
| #include <stdarg.h> | |
| #include "windef.h" | |
| #include "winbase.h" | |
| #include "winnls.h" | |
| #include "webservices.h" | |
| #include "wine/debug.h" | |
| #include "wine/list.h" | |
| #include "webservices_private.h" | |
| WINE_DEFAULT_DEBUG_CHANNEL(webservices); | |
| static const struct prop_desc error_props[] = | |
| { | |
| { sizeof(ULONG), TRUE }, /* WS_ERROR_PROPERTY_STRING_COUNT */ | |
| { sizeof(ULONG), FALSE }, /* WS_ERROR_PROPERTY_ORIGINAL_ERROR_CODE */ | |
| { sizeof(LANGID), FALSE } /* WS_ERROR_PROPERTY_LANGID */ | |
| }; | |
| struct error | |
| { | |
| ULONG magic; | |
| CRITICAL_SECTION cs; | |
| ULONG prop_count; | |
| struct prop prop[sizeof(error_props)/sizeof(error_props[0])]; | |
| }; | |
| #define ERROR_MAGIC (('E' << 24) | ('R' << 16) | ('R' << 8) | 'O') | |
| static struct error *alloc_error(void) | |
| { | |
| static const ULONG count = sizeof(error_props)/sizeof(error_props[0]); | |
| struct error *ret; | |
| ULONG size = sizeof(*ret) + prop_size( error_props, count ); | |
| if (!(ret = heap_alloc_zero( size ))) return NULL; | |
| ret->magic = ERROR_MAGIC; | |
| InitializeCriticalSection( &ret->cs ); | |
| ret->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": error.cs"); | |
| prop_init( error_props, count, ret->prop, &ret[1] ); | |
| ret->prop_count = count; | |
| return ret; | |
| } | |
| static void free_error( struct error *error ) | |
| { | |
| error->cs.DebugInfo->Spare[0] = 0; | |
| DeleteCriticalSection( &error->cs ); | |
| heap_free( error ); | |
| } | |
| /************************************************************************** | |
| * WsCreateError [webservices.@] | |
| */ | |
| HRESULT WINAPI WsCreateError( const WS_ERROR_PROPERTY *properties, ULONG count, WS_ERROR **handle ) | |
| { | |
| struct error *error; | |
| LANGID langid = GetUserDefaultUILanguage(); | |
| HRESULT hr; | |
| ULONG i; | |
| TRACE( "%p %u %p\n", properties, count, handle ); | |
| if (!handle) return E_INVALIDARG; | |
| if (!(error = alloc_error())) return E_OUTOFMEMORY; | |
| prop_set( error->prop, error->prop_count, WS_ERROR_PROPERTY_LANGID, &langid, sizeof(langid) ); | |
| for (i = 0; i < count; i++) | |
| { | |
| if (properties[i].id == WS_ERROR_PROPERTY_ORIGINAL_ERROR_CODE) | |
| { | |
| free_error( error ); | |
| return E_INVALIDARG; | |
| } | |
| hr = prop_set( error->prop, error->prop_count, properties[i].id, properties[i].value, | |
| properties[i].valueSize ); | |
| if (hr != S_OK) | |
| { | |
| free_error( error ); | |
| return hr; | |
| } | |
| } | |
| TRACE( "created %p\n", error ); | |
| *handle = (WS_ERROR *)error; | |
| return S_OK; | |
| } | |
| static void reset_error( struct error *error ) | |
| { | |
| ULONG code = 0; | |
| /* FIXME: release strings added with WsAddErrorString when it's implemented, reset string count */ | |
| prop_set( error->prop, error->prop_count, WS_ERROR_PROPERTY_ORIGINAL_ERROR_CODE, &code, sizeof(code) ); | |
| } | |
| /************************************************************************** | |
| * WsFreeError [webservices.@] | |
| */ | |
| void WINAPI WsFreeError( WS_ERROR *handle ) | |
| { | |
| struct error *error = (struct error *)handle; | |
| TRACE( "%p\n", handle ); | |
| if (!error) return; | |
| EnterCriticalSection( &error->cs ); | |
| if (error->magic != ERROR_MAGIC) | |
| { | |
| LeaveCriticalSection( &error->cs ); | |
| return; | |
| } | |
| reset_error( error ); | |
| error->magic = 0; | |
| LeaveCriticalSection( &error->cs ); | |
| free_error( error ); | |
| } | |
| /************************************************************************** | |
| * WsResetError [webservices.@] | |
| */ | |
| HRESULT WINAPI WsResetError( WS_ERROR *handle ) | |
| { | |
| struct error *error = (struct error *)handle; | |
| TRACE( "%p\n", handle ); | |
| if (!error) return E_INVALIDARG; | |
| EnterCriticalSection( &error->cs ); | |
| if (error->magic != ERROR_MAGIC) | |
| { | |
| LeaveCriticalSection( &error->cs ); | |
| return E_INVALIDARG; | |
| } | |
| reset_error( error ); | |
| LeaveCriticalSection( &error->cs ); | |
| return S_OK; | |
| } | |
| /************************************************************************** | |
| * WsGetErrorProperty [webservices.@] | |
| */ | |
| HRESULT WINAPI WsGetErrorProperty( WS_ERROR *handle, WS_ERROR_PROPERTY_ID id, void *buf, | |
| ULONG size ) | |
| { | |
| struct error *error = (struct error *)handle; | |
| HRESULT hr; | |
| TRACE( "%p %u %p %u\n", handle, id, buf, size ); | |
| if (!error) return E_INVALIDARG; | |
| EnterCriticalSection( &error->cs ); | |
| if (error->magic != ERROR_MAGIC) | |
| { | |
| LeaveCriticalSection( &error->cs ); | |
| return E_INVALIDARG; | |
| } | |
| hr = prop_get( error->prop, error->prop_count, id, buf, size ); | |
| LeaveCriticalSection( &error->cs ); | |
| return hr; | |
| } | |
| /************************************************************************** | |
| * WsGetErrorString [webservices.@] | |
| */ | |
| HRESULT WINAPI WsGetErrorString( WS_ERROR *handle, ULONG index, WS_STRING *str ) | |
| { | |
| FIXME( "%p %u %p: stub\n", handle, index, str ); | |
| return E_NOTIMPL; | |
| } | |
| /************************************************************************** | |
| * WsSetErrorProperty [webservices.@] | |
| */ | |
| HRESULT WINAPI WsSetErrorProperty( WS_ERROR *handle, WS_ERROR_PROPERTY_ID id, const void *value, | |
| ULONG size ) | |
| { | |
| struct error *error = (struct error *)handle; | |
| HRESULT hr; | |
| TRACE( "%p %u %p %u\n", handle, id, value, size ); | |
| if (!error) return E_INVALIDARG; | |
| EnterCriticalSection( &error->cs ); | |
| if (error->magic != ERROR_MAGIC) | |
| { | |
| LeaveCriticalSection( &error->cs ); | |
| return E_INVALIDARG; | |
| } | |
| if (id == WS_ERROR_PROPERTY_LANGID) | |
| { | |
| LeaveCriticalSection( &error->cs ); | |
| return WS_E_INVALID_OPERATION; | |
| } | |
| hr = prop_set( error->prop, error->prop_count, id, value, size ); | |
| LeaveCriticalSection( &error->cs ); | |
| return hr; | |
| } |