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