ReactOS 0.4.15-dev-8135-g1bc6c90
memlockbytes.c
Go to the documentation of this file.
1/******************************************************************************
2 *
3 * Global memory implementation of ILockBytes.
4 *
5 * Copyright 1999 Thuy Nguyen
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#include <assert.h>
23#include <stdarg.h>
24#include <string.h>
25
26#define COBJMACROS
27#define NONAMELESSUNION
28
29#include "windef.h"
30#include "winbase.h"
31#include "winuser.h"
32#include "objbase.h"
33#include "ole2.h"
34#include "winerror.h"
35
36#include "wine/debug.h"
37
39
40/******************************************************************************
41 * HGLOBALLockBytesImpl definition.
42 *
43 * This class implements the ILockBytes interface and represents a byte array
44 * object supported by an HGLOBAL pointer.
45 */
47{
50
51 /*
52 * Support for the LockBytes object
53 */
55
56 /*
57 * This flag is TRUE if the HGLOBAL is destroyed when the object
58 * is finally released.
59 */
61
62 /*
63 * Helper variable that contains the size of the byte array
64 */
66};
67
69
71{
73}
74
75static const ILockBytesVtbl HGLOBALLockBytesImpl_Vtbl;
76
77/******************************************************************************
78 * CreateILockBytesOnHGlobal [OLE32.@]
79 *
80 * Create a byte array object which is intended to be the compound file foundation.
81 * This object supports a COM implementation of the ILockBytes interface.
82 *
83 * PARAMS
84 * global [ I] Global memory handle
85 * delete_on_release [ I] Whether the handle should be freed when the object is released.
86 * ret [ O] Address of ILockBytes pointer that receives
87 * the interface pointer to the new byte array object.
88 *
89 * RETURNS
90 * Success: S_OK
91 *
92 * NOTES
93 * The supplied ILockBytes pointer can be used by the StgCreateDocfileOnILockBytes
94 * function to build a compound file on top of this byte array object.
95 * The ILockBytes interface instance calls the GlobalReAlloc function to grow
96 * the memory block as required.
97 */
99{
100 HGLOBALLockBytesImpl* lockbytes;
101
102 lockbytes = HeapAlloc(GetProcessHeap(), 0, sizeof(HGLOBALLockBytesImpl));
103 if (!lockbytes) return E_OUTOFMEMORY;
104
105 lockbytes->ILockBytes_iface.lpVtbl = &HGLOBALLockBytesImpl_Vtbl;
106 lockbytes->ref = 1;
107
108 /*
109 * Initialize the support.
110 */
111 lockbytes->supportHandle = global;
112 lockbytes->deleteOnRelease = delete_on_release;
113
114 /*
115 * This method will allocate a handle if one is not supplied.
116 */
117 if (lockbytes->supportHandle == 0)
119
120 /*
121 * Initialize the size of the array to the size of the handle.
122 */
123 lockbytes->byteArraySize.u.HighPart = 0;
124 lockbytes->byteArraySize.u.LowPart = GlobalSize(lockbytes->supportHandle);
125
126 *ret = &lockbytes->ILockBytes_iface;
127
128 return S_OK;
129}
130
131/******************************************************************************
132 * GetHGlobalFromILockBytes [OLE32.@]
133 *
134 * Retrieve a global memory handle to a byte array object created
135 * using the CreateILockBytesOnHGlobal function.
136 *
137 * PARAMS
138 * plkbyt [ I] Pointer to the ILockBytes interface on byte array object
139 * phglobal [ O] Address to store a global memory handle
140 * RETURNS
141 * S_OK if *phglobal has a correct value
142 * E_INVALIDARG if any parameters are invalid
143 *
144 */
146{
148 STATSTG stbuf;
151 ULONG xread;
152
153 *phglobal = 0;
154 if (This->ILockBytes_iface.lpVtbl == &HGLOBALLockBytesImpl_Vtbl) {
155 *phglobal = This->supportHandle;
156 if (*phglobal == 0)
157 return E_INVALIDARG;
158 return S_OK;
159 }
160 /* It is not our lockbytes implementation, so use a more generic way */
161 hres = ILockBytes_Stat(iface,&stbuf,STATFLAG_NONAME);
162 if (hres != S_OK) {
163 ERR("Cannot ILockBytes_Stat, %x\n",hres);
164 return hres;
165 }
166 TRACE("cbSize is %s\n", wine_dbgstr_longlong(stbuf.cbSize.QuadPart));
167 *phglobal = GlobalAlloc( GMEM_MOVEABLE|GMEM_SHARE, stbuf.cbSize.u.LowPart);
168 if (!*phglobal)
169 return E_INVALIDARG;
170 memset(&start,0,sizeof(start));
171 hres = ILockBytes_ReadAt(iface, start, GlobalLock(*phglobal), stbuf.cbSize.u.LowPart, &xread);
172 GlobalUnlock(*phglobal);
173 if (hres != S_OK) {
174 FIXME("%p->ReadAt failed with %x\n",iface,hres);
175 return hres;
176 }
177 if (stbuf.cbSize.u.LowPart != xread) {
178 FIXME("Read size is not requested size %d vs %d?\n",stbuf.cbSize.u.LowPart, xread);
179 }
180 return S_OK;
181}
182
183/******************************************************************************
184 *
185 * HGLOBALLockBytesImpl implementation
186 *
187 */
188
189/******************************************************************************
190 * This implements the IUnknown method QueryInterface for this
191 * class
192 */
194 ILockBytes* iface,
195 REFIID riid, /* [in] */
196 void** ppvObject) /* [iid_is][out] */
197{
199
200 if (ppvObject==0)
201 return E_INVALIDARG;
202
203 *ppvObject = 0;
204
206 IsEqualIID(riid, &IID_ILockBytes))
207 {
208 *ppvObject = &This->ILockBytes_iface;
209 }
210 else
211 return E_NOINTERFACE;
212
213 ILockBytes_AddRef(iface);
214
215 return S_OK;
216}
217
218/******************************************************************************
219 * This implements the IUnknown method AddRef for this
220 * class
221 */
223{
225 return InterlockedIncrement(&This->ref);
226}
227
228/******************************************************************************
229 * This implements the IUnknown method Release for this
230 * class
231 */
233{
235 ULONG ref;
236
238 if (!ref)
239 {
240 if (This->deleteOnRelease)
241 {
242 GlobalFree(This->supportHandle);
243 This->supportHandle = 0;
244 }
246 }
247
248 return ref;
249}
250
251/******************************************************************************
252 * This method is part of the ILockBytes interface.
253 *
254 * It reads a block of information from the byte array at the specified
255 * offset.
256 *
257 * See the documentation of ILockBytes for more info.
258 */
260 ILockBytes* iface,
261 ULARGE_INTEGER ulOffset, /* [in] */
262 void* pv, /* [length_is][size_is][out] */
263 ULONG cb, /* [in] */
264 ULONG* pcbRead) /* [out] */
265{
267
268 void* supportBuffer;
269 ULONG bytesReadBuffer = 0;
270 ULONG bytesToReadFromBuffer;
271
272 /*
273 * If the caller is not interested in the number of bytes read,
274 * we use another buffer to avoid "if" statements in the code.
275 */
276 if (pcbRead == 0)
277 pcbRead = &bytesReadBuffer;
278
279 /*
280 * Make sure the offset is valid.
281 */
282 if (ulOffset.u.LowPart > This->byteArraySize.u.LowPart)
283 return E_FAIL;
284
285 /*
286 * Using the known size of the array, calculate the number of bytes
287 * to read.
288 */
289 bytesToReadFromBuffer = min(This->byteArraySize.u.LowPart -
290 ulOffset.u.LowPart, cb);
291
292 /*
293 * Lock the buffer in position and copy the data.
294 */
295 supportBuffer = GlobalLock(This->supportHandle);
296
297 memcpy(pv,
298 (char *) supportBuffer + ulOffset.u.LowPart,
299 bytesToReadFromBuffer);
300
301 /*
302 * Return the number of bytes read.
303 */
304 *pcbRead = bytesToReadFromBuffer;
305
306 /*
307 * Cleanup
308 */
309 GlobalUnlock(This->supportHandle);
310
311 /*
312 * The function returns S_OK if the specified number of bytes were read
313 * or the end of the array was reached.
314 * It returns STG_E_READFAULT if the number of bytes to read does not equal
315 * the number of bytes actually read.
316 */
317 if(*pcbRead == cb)
318 return S_OK;
319
320 return STG_E_READFAULT;
321}
322
323/******************************************************************************
324 * This method is part of the ILockBytes interface.
325 *
326 * It writes the specified bytes at the specified offset.
327 * position. If the array is too small, it will be resized.
328 *
329 * See the documentation of ILockBytes for more info.
330 */
332 ILockBytes* iface,
333 ULARGE_INTEGER ulOffset, /* [in] */
334 const void* pv, /* [size_is][in] */
335 ULONG cb, /* [in] */
336 ULONG* pcbWritten) /* [out] */
337{
339
340 void* supportBuffer;
341 ULARGE_INTEGER newSize;
343
344 /*
345 * If the caller is not interested in the number of bytes written,
346 * we use another buffer to avoid "if" statements in the code.
347 */
348 if (pcbWritten == 0)
349 pcbWritten = &bytesWritten;
350
351 if (cb == 0)
352 {
353 return S_OK;
354 }
355 else
356 {
357 newSize.u.HighPart = 0;
358 newSize.u.LowPart = ulOffset.u.LowPart + cb;
359 }
360
361 /*
362 * Verify if we need to grow the stream
363 */
364 if (newSize.u.LowPart > This->byteArraySize.u.LowPart)
365 {
366 /* grow stream */
367 if (ILockBytes_SetSize(iface, newSize) == STG_E_MEDIUMFULL)
368 return STG_E_MEDIUMFULL;
369 }
370
371 /*
372 * Lock the buffer in position and copy the data.
373 */
374 supportBuffer = GlobalLock(This->supportHandle);
375
376 memcpy((char *) supportBuffer + ulOffset.u.LowPart, pv, cb);
377
378 /*
379 * Return the number of bytes written.
380 */
381 *pcbWritten = cb;
382
383 /*
384 * Cleanup
385 */
386 GlobalUnlock(This->supportHandle);
387
388 return S_OK;
389}
390
391/******************************************************************************
392 * This method is part of the ILockBytes interface.
393 *
394 * See the documentation of ILockBytes for more info.
395 */
397{
398 return S_OK;
399}
400
401/******************************************************************************
402 * This method is part of the ILockBytes interface.
403 *
404 * It will change the size of the byte array.
405 *
406 * See the documentation of ILockBytes for more info.
407 */
409 ILockBytes* iface,
410 ULARGE_INTEGER libNewSize) /* [in] */
411{
414
415 /*
416 * As documented.
417 */
418 if (libNewSize.u.HighPart != 0)
420
421 if (This->byteArraySize.u.LowPart == libNewSize.u.LowPart)
422 return S_OK;
423
424 /*
425 * Re allocate the HGlobal to fit the new size of the stream.
426 */
427 supportHandle = GlobalReAlloc(This->supportHandle, libNewSize.u.LowPart, 0);
428
429 if (supportHandle == 0)
430 return STG_E_MEDIUMFULL;
431
432 This->supportHandle = supportHandle;
433 This->byteArraySize.u.LowPart = libNewSize.u.LowPart;
434
435 return S_OK;
436}
437
438/******************************************************************************
439 * This method is part of the ILockBytes interface.
440 *
441 * The global memory implementation of ILockBytes does not support locking.
442 *
443 * See the documentation of ILockBytes for more info.
444 */
446 ILockBytes* iface,
447 ULARGE_INTEGER libOffset, /* [in] */
448 ULARGE_INTEGER cb, /* [in] */
449 DWORD dwLockType) /* [in] */
450{
452}
453
454/******************************************************************************
455 * This method is part of the ILockBytes interface.
456 *
457 * The global memory implementation of ILockBytes does not support locking.
458 *
459 * See the documentation of ILockBytes for more info.
460 */
462 ILockBytes* iface,
463 ULARGE_INTEGER libOffset, /* [in] */
464 ULARGE_INTEGER cb, /* [in] */
465 DWORD dwLockType) /* [in] */
466{
468}
469
470/******************************************************************************
471 * This method is part of the ILockBytes interface.
472 *
473 * This method returns information about the current
474 * byte array object.
475 *
476 * See the documentation of ILockBytes for more info.
477 */
479 ILockBytes* iface,
480 STATSTG* pstatstg, /* [out] */
481 DWORD grfStatFlag) /* [in] */
482{
484
485 memset(pstatstg, 0, sizeof(STATSTG));
486
487 pstatstg->pwcsName = NULL;
488 pstatstg->type = STGTY_LOCKBYTES;
489 pstatstg->cbSize = This->byteArraySize;
490
491 return S_OK;
492}
493
494/*
495 * Virtual function table for the HGLOBALLockBytesImpl class.
496 */
497static const ILockBytesVtbl HGLOBALLockBytesImpl_Vtbl =
498{
509};
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
const GUID IID_IUnknown
#define FIXME(fmt,...)
Definition: debug.h:114
#define ERR(fmt,...)
Definition: debug.h:113
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_FAIL
Definition: ddrawi.h:102
#define NULL
Definition: types.h:112
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
static __inline const char * wine_dbgstr_longlong(ULONGLONG ll)
Definition: compat.h:49
#define HeapFree(x, y, z)
Definition: compat.h:735
int global
Definition: ehframes.cpp:22
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint start
Definition: gl.h:1545
GLenum GLsizei GLuint GLint * bytesWritten
Definition: glext.h:11123
LPVOID NTAPI GlobalLock(HGLOBAL hMem)
Definition: heapmem.c:755
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
static ULONG WINAPI HGLOBALLockBytesImpl_AddRef(ILockBytes *iface)
Definition: memlockbytes.c:222
static HGLOBALLockBytesImpl * impl_from_ILockBytes(ILockBytes *iface)
Definition: memlockbytes.c:70
static ULONG WINAPI HGLOBALLockBytesImpl_Release(ILockBytes *iface)
Definition: memlockbytes.c:232
HRESULT WINAPI GetHGlobalFromILockBytes(ILockBytes *iface, HGLOBAL *phglobal)
Definition: memlockbytes.c:145
static HRESULT WINAPI HGLOBALLockBytesImpl_WriteAt(ILockBytes *iface, ULARGE_INTEGER ulOffset, const void *pv, ULONG cb, ULONG *pcbWritten)
Definition: memlockbytes.c:331
static HRESULT WINAPI HGLOBALLockBytesImpl_Stat(ILockBytes *iface, STATSTG *pstatstg, DWORD grfStatFlag)
Definition: memlockbytes.c:478
static HRESULT WINAPI HGLOBALLockBytesImpl_ReadAt(ILockBytes *iface, ULARGE_INTEGER ulOffset, void *pv, ULONG cb, ULONG *pcbRead)
Definition: memlockbytes.c:259
static HRESULT WINAPI HGLOBALLockBytesImpl_LockRegion(ILockBytes *iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
Definition: memlockbytes.c:445
static HRESULT WINAPI HGLOBALLockBytesImpl_UnlockRegion(ILockBytes *iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
Definition: memlockbytes.c:461
static HRESULT WINAPI HGLOBALLockBytesImpl_QueryInterface(ILockBytes *iface, REFIID riid, void **ppvObject)
Definition: memlockbytes.c:193
static HRESULT WINAPI HGLOBALLockBytesImpl_Flush(ILockBytes *iface)
Definition: memlockbytes.c:396
HRESULT WINAPI CreateILockBytesOnHGlobal(HGLOBAL global, BOOL delete_on_release, ILockBytes **ret)
Definition: memlockbytes.c:98
static const ILockBytesVtbl HGLOBALLockBytesImpl_Vtbl
Definition: memlockbytes.c:75
static HRESULT WINAPI HGLOBALLockBytesImpl_SetSize(ILockBytes *iface, ULARGE_INTEGER libNewSize)
Definition: memlockbytes.c:408
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
HRESULT hres
Definition: protocol.c:465
static HMODULE MODULEINFO DWORD cb
Definition: module.c:33
#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 memset(x, y, z)
Definition: compat.h:39
#define TRACE(s)
Definition: solgame.cpp:4
ILockBytes ILockBytes_iface
Definition: memlockbytes.c:48
ULARGE_INTEGER byteArraySize
Definition: memlockbytes.c:65
struct _ULARGE_INTEGER::@4145 u
Definition: send.c:48
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
int ret
#define GMEM_NODISCARD
Definition: winbase.h:302
#define GMEM_MOVEABLE
Definition: winbase.h:294
#define GMEM_SHARE
Definition: winbase.h:305
_In_ void _In_ PCCERT_CONTEXT _In_opt_ LPFILETIME _In_ DWORD _In_ DWORD _Outptr_opt_ void ** ppvObject
Definition: wincrypt.h:6082
#define WINAPI
Definition: msvc.h:6
#define E_NOINTERFACE
Definition: winerror.h:2364
#define STG_E_READFAULT
Definition: winerror.h:2576
#define STG_E_MEDIUMFULL
Definition: winerror.h:2581
#define STG_E_INVALIDFUNCTION
Definition: winerror.h:2564