/* * Copyright 2015 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 #include "windef.h" #include "winbase.h" #include "winnls.h" #include "webservices.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(webservices); static inline void *heap_alloc( SIZE_T size ) { return HeapAlloc( GetProcessHeap(), 0, size ); } static inline void *heap_alloc_zero( SIZE_T size ) { return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size ); } static inline void *heap_realloc( void *mem, SIZE_T size ) { return HeapReAlloc( GetProcessHeap(), 0, mem, size ); } static inline BOOL heap_free( void *mem ) { return HeapFree( GetProcessHeap(), 0, mem ); } static const struct { ULONG size; BOOL readonly; } 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 prop_count; WS_ERROR_PROPERTY prop[sizeof(error_props)/sizeof(error_props[0])]; }; static struct error *alloc_error(void) { static const ULONG count = sizeof(error_props)/sizeof(error_props[0]); struct error *ret; ULONG i, size = sizeof(*ret) + count * sizeof(WS_ERROR_PROPERTY); char *ptr; for (i = 0; i < count; i++) size += error_props[i].size; if (!(ret = heap_alloc_zero( size ))) return NULL; ptr = (char *)&ret->prop[count]; for (i = 0; i < count; i++) { ret->prop[i].value = ptr; ret->prop[i].valueSize = error_props[i].size; ptr += ret->prop[i].valueSize; } ret->prop_count = count; return ret; } static HRESULT set_error_prop( struct error *error, WS_ERROR_PROPERTY_ID id, const void *value, ULONG size ) { if (id >= error->prop_count || size != error_props[id].size || error_props[id].readonly) return E_INVALIDARG; memcpy( error->prop[id].value, value, size ); return S_OK; } /************************************************************************** * 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; set_error_prop( error, WS_ERROR_PROPERTY_LANGID, &langid, sizeof(langid) ); for (i = 0; i < count; i++) { if (properties[i].id == WS_ERROR_PROPERTY_ORIGINAL_ERROR_CODE) { heap_free( error ); return E_INVALIDARG; } hr = set_error_prop( error, properties[i].id, properties[i].value, properties[i].valueSize ); if (hr != S_OK) { heap_free( error ); return hr; } } *handle = (WS_ERROR *)error; return S_OK; } /************************************************************************** * WsFreeError [webservices.@] */ void WINAPI WsFreeError( WS_ERROR *handle ) { struct error *error = (struct error *)handle; TRACE( "%p\n", handle ); heap_free( error ); }