2 * Copyright 2015, 2016 Hans Leidekker for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "webservices.h"
26 #include "wine/debug.h"
27 #include "wine/heap.h"
28 #include "wine/list.h"
29 #include "webservices_private.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(webservices
);
33 static const struct prop_desc heap_props
[] =
35 { sizeof(SIZE_T
), FALSE
}, /* WS_HEAP_PROPERTY_MAX_SIZE */
36 { sizeof(SIZE_T
), FALSE
}, /* WS_HEAP_PROPERTY_TRIM_SIZE */
37 { sizeof(SIZE_T
), TRUE
}, /* WS_HEAP_PROPERTY_REQUESTED_SIZE */
38 { sizeof(SIZE_T
), TRUE
} /* WS_HEAP_PROPERTY_ACTUAL_SIZE */
49 struct prop prop
[ARRAY_SIZE( heap_props
)];
52 #define HEAP_MAGIC (('H' << 24) | ('E' << 16) | ('A' << 8) | 'P')
54 static BOOL
ensure_heap( struct heap
*heap
)
57 if (heap
->handle
) return TRUE
;
58 prop_get( heap
->prop
, heap
->prop_count
, WS_HEAP_PROPERTY_MAX_SIZE
, &size
, sizeof(size
) );
59 if (!(heap
->handle
= HeapCreate( 0, 0, 0 ))) return FALSE
;
60 heap
->max_size
= size
;
65 void *ws_alloc( WS_HEAP
*handle
, SIZE_T size
)
67 struct heap
*heap
= (struct heap
*)handle
;
70 EnterCriticalSection( &heap
->cs
);
72 if (heap
->magic
!= HEAP_MAGIC
) goto done
;
73 if (!ensure_heap( heap
) || size
> heap
->max_size
- heap
->allocated
) goto done
;
74 if ((ret
= HeapAlloc( heap
->handle
, 0, size
))) heap
->allocated
+= size
;
77 LeaveCriticalSection( &heap
->cs
);
81 void *ws_alloc_zero( WS_HEAP
*handle
, SIZE_T size
)
83 struct heap
*heap
= (struct heap
*)handle
;
86 EnterCriticalSection( &heap
->cs
);
88 if (heap
->magic
!= HEAP_MAGIC
) goto done
;
89 if (!ensure_heap( heap
) || size
> heap
->max_size
- heap
->allocated
) goto done
;
90 if ((ret
= HeapAlloc( heap
->handle
, HEAP_ZERO_MEMORY
, size
))) heap
->allocated
+= size
;
93 LeaveCriticalSection( &heap
->cs
);
97 void *ws_realloc( WS_HEAP
*handle
, void *ptr
, SIZE_T old_size
, SIZE_T new_size
)
99 struct heap
*heap
= (struct heap
*)handle
;
102 EnterCriticalSection( &heap
->cs
);
104 if (heap
->magic
!= HEAP_MAGIC
|| !ensure_heap( heap
)) goto done
;
105 if (new_size
>= old_size
)
107 SIZE_T size
= new_size
- old_size
;
108 if (size
> heap
->max_size
- heap
->allocated
) goto done
;
109 if ((ret
= HeapReAlloc( heap
->handle
, 0, ptr
, new_size
))) heap
->allocated
+= size
;
113 SIZE_T size
= old_size
- new_size
;
114 if ((ret
= HeapReAlloc( heap
->handle
, 0, ptr
, new_size
))) heap
->allocated
-= size
;
118 LeaveCriticalSection( &heap
->cs
);
122 void *ws_realloc_zero( WS_HEAP
*handle
, void *ptr
, SIZE_T old_size
, SIZE_T new_size
)
124 struct heap
*heap
= (struct heap
*)handle
;
127 EnterCriticalSection( &heap
->cs
);
129 if (heap
->magic
!= HEAP_MAGIC
|| !ensure_heap( heap
)) goto done
;
130 if (new_size
>= old_size
)
132 SIZE_T size
= new_size
- old_size
;
133 if (size
> heap
->max_size
- heap
->allocated
) goto done
;
134 if ((ret
= HeapReAlloc( heap
->handle
, HEAP_ZERO_MEMORY
, ptr
, new_size
))) heap
->allocated
+= size
;
138 SIZE_T size
= old_size
- new_size
;
139 if ((ret
= HeapReAlloc( heap
->handle
, HEAP_ZERO_MEMORY
, ptr
, new_size
))) heap
->allocated
-= size
;
143 LeaveCriticalSection( &heap
->cs
);
147 void ws_free( WS_HEAP
*handle
, void *ptr
, SIZE_T size
)
149 struct heap
*heap
= (struct heap
*)handle
;
151 EnterCriticalSection( &heap
->cs
);
153 if (heap
->magic
== HEAP_MAGIC
)
155 HeapFree( heap
->handle
, 0, ptr
);
156 heap
->allocated
-= size
;
159 LeaveCriticalSection( &heap
->cs
);
162 /**************************************************************************
163 * WsAlloc [webservices.@]
165 HRESULT WINAPI
WsAlloc( WS_HEAP
*handle
, SIZE_T size
, void **ptr
, WS_ERROR
*error
)
169 TRACE( "%p %u %p %p\n", handle
, (ULONG
)size
, ptr
, error
);
170 if (error
) FIXME( "ignoring error parameter\n" );
172 if (!handle
|| !ptr
) return E_INVALIDARG
;
173 if (!(mem
= ws_alloc( handle
, size
))) return WS_E_QUOTA_EXCEEDED
;
178 static struct heap
*alloc_heap(void)
180 static const ULONG count
= ARRAY_SIZE( heap_props
);
182 ULONG size
= sizeof(*ret
) + prop_size( heap_props
, count
);
184 if (!(ret
= heap_alloc_zero( size
))) return NULL
;
186 ret
->magic
= HEAP_MAGIC
;
187 InitializeCriticalSection( &ret
->cs
);
188 ret
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": heap.cs");
190 prop_init( heap_props
, count
, ret
->prop
, &ret
[1] );
191 ret
->prop_count
= count
;
195 /**************************************************************************
196 * WsCreateHeap [webservices.@]
198 HRESULT WINAPI
WsCreateHeap( SIZE_T max_size
, SIZE_T trim_size
, const WS_HEAP_PROPERTY
*properties
,
199 ULONG count
, WS_HEAP
**handle
, WS_ERROR
*error
)
203 TRACE( "%u %u %p %u %p %p\n", (ULONG
)max_size
, (ULONG
)trim_size
, properties
, count
, handle
, error
);
204 if (error
) FIXME( "ignoring error parameter\n" );
206 if (!handle
|| count
) return E_INVALIDARG
;
207 if (!(heap
= alloc_heap())) return E_OUTOFMEMORY
;
209 prop_set( heap
->prop
, heap
->prop_count
, WS_HEAP_PROPERTY_MAX_SIZE
, &max_size
, sizeof(max_size
) );
210 prop_set( heap
->prop
, heap
->prop_count
, WS_HEAP_PROPERTY_TRIM_SIZE
, &trim_size
, sizeof(trim_size
) );
212 TRACE( "created %p\n", heap
);
213 *handle
= (WS_HEAP
*)heap
;
217 static void reset_heap( struct heap
*heap
)
219 if (heap
->handle
) HeapDestroy( heap
->handle
);
221 heap
->max_size
= heap
->allocated
= 0;
224 /**************************************************************************
225 * WsFreeHeap [webservices.@]
227 void WINAPI
WsFreeHeap( WS_HEAP
*handle
)
229 struct heap
*heap
= (struct heap
*)handle
;
231 TRACE( "%p\n", handle
);
235 EnterCriticalSection( &heap
->cs
);
237 if (heap
->magic
!= HEAP_MAGIC
)
239 LeaveCriticalSection( &heap
->cs
);
246 LeaveCriticalSection( &heap
->cs
);
248 heap
->cs
.DebugInfo
->Spare
[0] = 0;
249 DeleteCriticalSection( &heap
->cs
);
253 /**************************************************************************
254 * WsResetHeap [webservices.@]
256 HRESULT WINAPI
WsResetHeap( WS_HEAP
*handle
, WS_ERROR
*error
)
258 struct heap
*heap
= (struct heap
*)handle
;
261 TRACE( "%p %p\n", handle
, error
);
262 if (error
) FIXME( "ignoring error parameter\n" );
264 if (!heap
) return E_INVALIDARG
;
266 EnterCriticalSection( &heap
->cs
);
268 if (heap
->magic
!= HEAP_MAGIC
)
270 LeaveCriticalSection( &heap
->cs
);
276 LeaveCriticalSection( &heap
->cs
);
277 TRACE( "returning %08x\n", hr
);
281 /**************************************************************************
282 * WsGetHeapProperty [webservices.@]
284 HRESULT WINAPI
WsGetHeapProperty( WS_HEAP
*handle
, WS_HEAP_PROPERTY_ID id
, void *buf
,
285 ULONG size
, WS_ERROR
*error
)
287 struct heap
*heap
= (struct heap
*)handle
;
290 TRACE( "%p %u %p %u %p\n", handle
, id
, buf
, size
, error
);
291 if (error
) FIXME( "ignoring error parameter\n" );
293 if (!heap
) return E_INVALIDARG
;
295 EnterCriticalSection( &heap
->cs
);
297 if (heap
->magic
!= HEAP_MAGIC
)
299 LeaveCriticalSection( &heap
->cs
);
305 case WS_HEAP_PROPERTY_REQUESTED_SIZE
:
306 case WS_HEAP_PROPERTY_ACTUAL_SIZE
:
308 SIZE_T
*heap_size
= buf
;
309 if (!buf
|| size
!= sizeof(heap_size
)) hr
= E_INVALIDARG
;
310 else *heap_size
= heap
->allocated
;
314 hr
= prop_get( heap
->prop
, heap
->prop_count
, id
, buf
, size
);
317 LeaveCriticalSection( &heap
->cs
);
318 TRACE( "returning %08x\n", hr
);
322 #define XML_BUFFER_INITIAL_ALLOCATED_SIZE 256
323 struct xmlbuf
*alloc_xmlbuf( WS_HEAP
*heap
, SIZE_T size
, WS_XML_WRITER_ENCODING_TYPE encoding
, WS_CHARSET charset
,
324 const WS_XML_DICTIONARY
*dict_static
, WS_XML_DICTIONARY
*dict
)
328 if (!size
) size
= XML_BUFFER_INITIAL_ALLOCATED_SIZE
;
329 if (!(ret
= ws_alloc( heap
, sizeof(*ret
) ))) return NULL
;
330 if (!(ret
->bytes
.bytes
= ws_alloc( heap
, size
)))
332 ws_free( heap
, ret
, sizeof(*ret
) );
337 ret
->bytes
.length
= 0;
338 ret
->encoding
= encoding
;
339 ret
->charset
= charset
;
340 ret
->dict_static
= dict_static
;
345 void free_xmlbuf( struct xmlbuf
*xmlbuf
)
348 ws_free( xmlbuf
->heap
, xmlbuf
->bytes
.bytes
, xmlbuf
->size
);
349 ws_free( xmlbuf
->heap
, xmlbuf
, sizeof(*xmlbuf
) );
352 /**************************************************************************
353 * WsCreateXmlBuffer [webservices.@]
355 HRESULT WINAPI
WsCreateXmlBuffer( WS_HEAP
*heap
, const WS_XML_BUFFER_PROPERTY
*properties
,
356 ULONG count
, WS_XML_BUFFER
**handle
, WS_ERROR
*error
)
358 struct xmlbuf
*xmlbuf
;
360 TRACE( "%p %p %u %p %p\n", heap
, properties
, count
, handle
, error
);
361 if (error
) FIXME( "ignoring error parameter\n" );
363 if (!heap
|| !handle
) return E_INVALIDARG
;
364 if (count
) FIXME( "properties not implemented\n" );
366 if (!(xmlbuf
= alloc_xmlbuf( heap
, 0, WS_XML_WRITER_ENCODING_TYPE_TEXT
, WS_CHARSET_UTF8
, NULL
, NULL
)))
368 return WS_E_QUOTA_EXCEEDED
;
371 TRACE( "created %p\n", xmlbuf
);
372 *handle
= (WS_XML_BUFFER
*)xmlbuf
;