ReactOS 0.4.16-dev-2320-ge1853c6
hglobalstream.c
Go to the documentation of this file.
1/*
2 * HGLOBAL Stream implementation
3 *
4 * Copyright 1999 Francis Beaudet
5 * Copyright 2016 Dmitry Timoshkov
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22#define COBJMACROS
23#include "objbase.h"
24
25#include "wine/debug.h"
26
28
30{
35};
36
38{
40}
41
43{
45
46 if (!ref)
47 {
48 if (handle->delete_on_release) GlobalFree(handle->hglobal);
49 free(handle);
50 }
51}
52
54{
55 struct handle_wrapper *handle;
56
57 handle = malloc(sizeof(*handle));
58 if (!handle) return NULL;
59
60 /* allocate a handle if one is not supplied */
62 if (!hglobal)
63 {
64 free(handle);
65 return NULL;
66 }
67 handle->ref = 1;
68 handle->hglobal = hglobal;
69 handle->size = GlobalSize(hglobal);
70 handle->delete_on_release = delete_on_release;
71
72 return handle;
73}
74
76{
79
82};
83
84static inline struct hglobal_stream *impl_from_IStream(IStream *iface)
85{
86 return CONTAINING_RECORD(iface, struct hglobal_stream, IStream_iface);
87}
88
89static const IStreamVtbl hglobalstreamvtbl;
90
92{
93 struct hglobal_stream *object = calloc(1, sizeof(*object));
94
95 if (object)
96 {
97 object->IStream_iface.lpVtbl = &hglobalstreamvtbl;
98 object->ref = 1;
99 }
100 return object;
101}
102
104{
105 if (!obj)
106 return E_INVALIDARG;
107
109 IsEqualIID(&IID_ISequentialStream, riid) ||
110 IsEqualIID(&IID_IStream, riid))
111 {
112 *obj = iface;
113 IStream_AddRef(iface);
114 return S_OK;
115 }
116
117 *obj = NULL;
118 return E_NOINTERFACE;
119}
120
122{
123 struct hglobal_stream *stream = impl_from_IStream(iface);
124 return InterlockedIncrement(&stream->ref);
125}
126
128{
129 struct hglobal_stream *stream = impl_from_IStream(iface);
131
132 if (!ref)
133 {
134 handle_release(stream->handle);
135 free(stream);
136 }
137
138 return ref;
139}
140
141static HRESULT WINAPI stream_Read(IStream *iface, void *pv, ULONG cb, ULONG *read_len)
142{
143 struct hglobal_stream *stream = impl_from_IStream(iface);
144 ULONG dummy, len;
145 char *buffer;
146
147 TRACE("%p, %p, %ld, %p\n", iface, pv, cb, read_len);
148
149 if (!read_len)
150 read_len = &dummy;
151
152 if (stream->handle->size >= stream->position.LowPart)
153 len = min(stream->handle->size - stream->position.LowPart, cb);
154 else
155 len = 0;
156
157 buffer = GlobalLock(stream->handle->hglobal);
158 if (!buffer)
159 {
160 WARN("Failed to lock hglobal %p\n", stream->handle->hglobal);
161 *read_len = 0;
162 return S_OK;
163 }
164
165 memcpy(pv, buffer + stream->position.LowPart, len);
166 stream->position.LowPart += len;
167
168 *read_len = len;
169
170 GlobalUnlock(stream->handle->hglobal);
171
172 return S_OK;
173}
174
175static HRESULT WINAPI stream_Write(IStream *iface, const void *pv, ULONG cb, ULONG *written)
176{
177 struct hglobal_stream *stream = impl_from_IStream(iface);
179 ULONG dummy = 0;
180 char *buffer;
181
182 TRACE("%p, %p, %ld, %p\n", iface, pv, cb, written);
183
184 if (!written)
185 written = &dummy;
186
187 if (!cb)
188 goto out;
189
190 *written = 0;
191
192 size.HighPart = 0;
193 size.LowPart = stream->position.LowPart + cb;
194
195 if (size.LowPart > stream->handle->size)
196 {
197 /* grow stream */
198 HRESULT hr = IStream_SetSize(iface, size);
199 if (FAILED(hr))
200 {
201 ERR("IStream_SetSize failed with error %#lx\n", hr);
202 return hr;
203 }
204 }
205
206 buffer = GlobalLock(stream->handle->hglobal);
207 if (!buffer)
208 {
209 WARN("write to invalid hglobal %p\n", stream->handle->hglobal);
210 return S_OK;
211 }
212
213 memcpy(buffer + stream->position.LowPart, pv, cb);
214 stream->position.LowPart += cb;
215
216 GlobalUnlock(stream->handle->hglobal);
217
218out:
219 *written = cb;
220
221 return S_OK;
222}
223
226{
227 struct hglobal_stream *stream = impl_from_IStream(iface);
228 ULARGE_INTEGER position = stream->position;
229 HRESULT hr = S_OK;
230
231 TRACE("%p, %s, %ld, %p\n", iface, wine_dbgstr_longlong(move.QuadPart), origin, pos);
232
233 switch (origin)
234 {
235 case STREAM_SEEK_SET:
236 position.QuadPart = 0;
237 break;
238 case STREAM_SEEK_CUR:
239 break;
240 case STREAM_SEEK_END:
241 position.QuadPart = stream->handle->size;
242 break;
243 default:
245 goto end;
246 }
247
248 position.HighPart = 0;
249 position.LowPart += move.QuadPart;
250
251 if (move.LowPart >= 0x80000000 && position.LowPart >= move.LowPart)
252 {
253 /* We tried to seek backwards and went past the start. */
255 goto end;
256 }
257
258 stream->position = position;
259
260end:
261 if (pos) *pos = stream->position;
262
263 return hr;
264}
265
267{
268 struct hglobal_stream *stream = impl_from_IStream(iface);
269 HGLOBAL hglobal;
270
271 TRACE("%p, %s\n", iface, wine_dbgstr_longlong(size.QuadPart));
272
273 if (stream->handle->size == size.LowPart)
274 return S_OK;
275
276 hglobal = GlobalReAlloc(stream->handle->hglobal, size.LowPart, GMEM_MOVEABLE);
277 if (!hglobal)
278 return E_OUTOFMEMORY;
279
280 stream->handle->hglobal = hglobal;
281 stream->handle->size = size.LowPart;
282
283 return S_OK;
284}
285
287 ULARGE_INTEGER *read_len, ULARGE_INTEGER *written)
288{
289 ULARGE_INTEGER total_read, total_written;
290 HRESULT hr = S_OK;
291 BYTE buffer[128];
292
293 TRACE("%p, %p, %ld, %p, %p\n", iface, dest, cb.LowPart, read_len, written);
294
295 if (!dest)
297
298 total_read.QuadPart = 0;
299 total_written.QuadPart = 0;
300
301 while (cb.QuadPart > 0)
302 {
303 ULONG chunk_size = cb.QuadPart >= sizeof(buffer) ? sizeof(buffer) : cb.LowPart;
304 ULONG chunk_read, chunk_written;
305
306 hr = IStream_Read(iface, buffer, chunk_size, &chunk_read);
307 if (FAILED(hr))
308 break;
309
310 total_read.QuadPart += chunk_read;
311
312 if (chunk_read)
313 {
314 hr = IStream_Write(dest, buffer, chunk_read, &chunk_written);
315 if (FAILED(hr))
316 break;
317
318 total_written.QuadPart += chunk_written;
319 }
320
321 if (chunk_read != chunk_size)
322 cb.QuadPart = 0;
323 else
324 cb.QuadPart -= chunk_read;
325 }
326
327 if (read_len)
328 read_len->QuadPart = total_read.QuadPart;
329 if (written)
330 written->QuadPart = total_written.QuadPart;
331
332 return hr;
333}
334
336{
337 return S_OK;
338}
339
341{
342 return S_OK;
343}
344
346 ULARGE_INTEGER len, DWORD lock_type)
347{
349}
350
352 ULARGE_INTEGER len, DWORD lock_type)
353{
354 return S_OK;
355}
356
357static HRESULT WINAPI stream_Stat(IStream *iface, STATSTG *pstatstg, DWORD flags)
358{
359 struct hglobal_stream *stream = impl_from_IStream(iface);
360
361 memset(pstatstg, 0, sizeof(STATSTG));
362
363 pstatstg->pwcsName = NULL;
364 pstatstg->type = STGTY_STREAM;
365 pstatstg->cbSize.QuadPart = stream->handle->size;
366
367 return S_OK;
368}
369
371{
372 struct hglobal_stream *stream = impl_from_IStream(iface), *clone;
375
376 TRACE("%p, %p\n", iface, ppstm);
377
378 *ppstm = NULL;
379
380 clone = hglobalstream_construct();
381 if (!clone) return E_OUTOFMEMORY;
382
383 *ppstm = &clone->IStream_iface;
384 handle_addref(stream->handle);
385 clone->handle = stream->handle;
386
387 offset.QuadPart = (LONGLONG)stream->position.QuadPart;
388 IStream_Seek(*ppstm, offset, STREAM_SEEK_SET, &dummy);
389 return S_OK;
390}
391
392static const IStreamVtbl hglobalstreamvtbl =
393{
408};
409
410/***********************************************************************
411 * CreateStreamOnHGlobal (combase.@)
412 */
414{
415 struct hglobal_stream *object;
416
417 if (!stream)
418 return E_INVALIDARG;
419
420 object = hglobalstream_construct();
421 if (!object) return E_OUTOFMEMORY;
422
423 object->handle = handle_create(hGlobal, delete_on_release);
424 if (!object->handle)
425 {
426 free(object);
427 return E_OUTOFMEMORY;
428 }
429
430 *stream = &object->IStream_iface;
431
432 return S_OK;
433}
434
435/***********************************************************************
436 * GetHGlobalFromStream (combase.@)
437 */
439{
440 struct hglobal_stream *object;
441
442 if (!stream || !phglobal)
443 return E_INVALIDARG;
444
445 object = impl_from_IStream(stream);
446
447 if (object->IStream_iface.lpVtbl == &hglobalstreamvtbl)
448 *phglobal = object->handle->hglobal;
449 else
450 {
451 *phglobal = 0;
452 return E_INVALIDARG;
453 }
454
455 return S_OK;
456}
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
const GUID IID_IUnknown
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
static HRESULT WINAPI stream_Read(IStream *iface, void *pv, ULONG cb, ULONG *read_len)
HRESULT WINAPI GetHGlobalFromStream(IStream *stream, HGLOBAL *phglobal)
static ULONG WINAPI stream_AddRef(IStream *iface)
static HRESULT WINAPI stream_UnlockRegion(IStream *iface, ULARGE_INTEGER offset, ULARGE_INTEGER len, DWORD lock_type)
static HRESULT WINAPI stream_Write(IStream *iface, const void *pv, ULONG cb, ULONG *written)
static struct hglobal_stream * impl_from_IStream(IStream *iface)
Definition: hglobalstream.c:84
static void handle_release(struct handle_wrapper *handle)
Definition: hglobalstream.c:42
static const IStreamVtbl hglobalstreamvtbl
Definition: hglobalstream.c:89
static ULONG WINAPI stream_Release(IStream *iface)
static HRESULT WINAPI stream_CopyTo(IStream *iface, IStream *dest, ULARGE_INTEGER cb, ULARGE_INTEGER *read_len, ULARGE_INTEGER *written)
HRESULT WINAPI CreateStreamOnHGlobal(HGLOBAL hGlobal, BOOL delete_on_release, IStream **stream)
static void handle_addref(struct handle_wrapper *handle)
Definition: hglobalstream.c:37
static HRESULT WINAPI stream_Revert(IStream *iface)
static HRESULT WINAPI stream_Seek(IStream *iface, LARGE_INTEGER move, DWORD origin, ULARGE_INTEGER *pos)
static HRESULT WINAPI stream_Stat(IStream *iface, STATSTG *pstatstg, DWORD flags)
static HRESULT WINAPI stream_QueryInterface(IStream *iface, REFIID riid, void **obj)
static HRESULT WINAPI stream_Clone(IStream *iface, IStream **ppstm)
static HRESULT WINAPI stream_LockRegion(IStream *iface, ULARGE_INTEGER offset, ULARGE_INTEGER len, DWORD lock_type)
static HRESULT WINAPI stream_Commit(IStream *iface, DWORD flags)
static struct handle_wrapper * handle_create(HGLOBAL hglobal, BOOL delete_on_release)
Definition: hglobalstream.c:53
static struct hglobal_stream * hglobalstream_construct(void)
Definition: hglobalstream.c:91
static HRESULT WINAPI stream_SetSize(IStream *iface, ULARGE_INTEGER size)
static __inline const char * wine_dbgstr_longlong(ULONGLONG ll)
Definition: compat.h:49
static MonoProfilerRuntimeShutdownBeginCallback cb
Definition: metahost.c:118
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLuint end
Definition: gl.h:1545
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
GLintptr offset
Definition: glext.h:5920
GLbitfield flags
Definition: glext.h:7161
GLenum GLsizei len
Definition: glext.h:6722
HGLOBAL NTAPI GlobalFree(HGLOBAL hMem)
Definition: heapmem.c:611
HGLOBAL NTAPI GlobalReAlloc(HGLOBAL hMem, SIZE_T dwBytes, UINT uFlags)
Definition: heapmem.c:825
BOOL NTAPI GlobalUnlock(HGLOBAL hMem)
Definition: heapmem.c:1190
HGLOBAL NTAPI GlobalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:368
SIZE_T NTAPI GlobalSize(HGLOBAL hMem)
Definition: heapmem.c:1090
REFIID riid
Definition: atlbase.h:39
#define S_OK
Definition: intsafe.h:52
#define FAILED(hr)
Definition: intsafe.h:51
voidpf uLong int origin
Definition: ioapi.h:144
static ERESOURCE GlobalLock
Definition: sys_arch.c:8
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static char * dest
Definition: rtl.c:135
#define min(a, b)
Definition: monoChain.cc:55
long LONG
Definition: pedump.c:60
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
#define REFIID
Definition: guiddef.h:118
#define calloc
Definition: rosglue.h:14
#define memset(x, y, z)
Definition: compat.h:39
HRESULT hr
Definition: shlfolder.c:183
#define TRACE(s)
Definition: solgame.cpp:4
$ULONG LowPart
Definition: ntbasedef.h:581
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
$ULONG HighPart
Definition: ntbasedef.h:582
BOOL delete_on_release
Definition: hglobalstream.c:34
IStream IStream_iface
Definition: hglobalstream.c:77
ULARGE_INTEGER position
Definition: hglobalstream.c:81
struct handle_wrapper * handle
Definition: hglobalstream.c:80
Definition: send.c:48
Definition: parse.h:23
unsigned int size
Definition: parse.h:27
IStream IStream_iface
Definition: request.c:4377
int64_t LONGLONG
Definition: typedefs.h:68
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
LONGLONG QuadPart
Definition: typedefs.h:114
ULONG LowPart
Definition: typedefs.h:106
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t ** out
Definition: wcsftime.cpp:383
#define GMEM_NODISCARD
Definition: winbase.h:326
#define GMEM_MOVEABLE
Definition: winbase.h:318
#define GMEM_SHARE
Definition: winbase.h:329
#define WINAPI
Definition: msvc.h:6
#define STG_E_INVALIDPOINTER
Definition: winerror.h:3666
#define STG_E_SEEKERROR
Definition: winerror.h:3669
#define E_NOINTERFACE
Definition: winerror.h:3479
#define STG_E_INVALIDFUNCTION
Definition: winerror.h:3659
unsigned char BYTE
Definition: xxhash.c:193