ReactOS  0.4.14-dev-57-g333b8f1
hglobalstream.c
Go to the documentation of this file.
1 /*
2  * HGLOBAL Stream implementation
3  *
4  * This file contains the implementation of the stream interface
5  * for streams contained supported by an HGLOBAL pointer.
6  *
7  * Copyright 1999 Francis Beaudet
8  * Copyright 2016 Dmitry Timoshkov
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include "config.h"
26 
27 #include <assert.h>
28 #include <stdlib.h>
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <string.h>
32 
33 #define COBJMACROS
34 #define NONAMELESSUNION
35 
36 #include "windef.h"
37 #include "winbase.h"
38 #include "winuser.h"
39 #include "objbase.h"
40 #include "ole2.h"
41 #include "winerror.h"
42 #include "winternl.h"
43 
44 #include "wine/debug.h"
45 
46 WINE_DEFAULT_DEBUG_CHANNEL(hglobalstream);
47 
49 {
55 };
56 
57 static void handle_addref(struct handle_wrapper *handle)
58 {
60 }
61 
62 static void handle_release(struct handle_wrapper *handle)
63 {
65 
66  if (!ref)
67  {
68  if (handle->delete_on_release)
69  {
70  GlobalFree(handle->hglobal);
71  handle->hglobal = NULL;
72  }
73 
74  handle->lock.DebugInfo->Spare[0] = 0;
77  }
78 }
79 
81 {
82  void *source;
83 
85 
86  if (*pos < handle->size)
87  len = min(handle->size - *pos, len);
88  else
89  len = 0;
90 
91  source = GlobalLock(handle->hglobal);
92  if (source)
93  {
94  memcpy(dest, (char *)source + *pos, len);
95  *pos += len;
96  GlobalUnlock(handle->hglobal);
97  }
98  else
99  {
100  WARN("read from invalid hglobal %p\n", handle->hglobal);
101  len = 0;
102  }
103 
105  return len;
106 }
107 
108 static ULONG handle_write(struct handle_wrapper *handle, ULONG *pos, const void *source, ULONG len)
109 {
110  void *dest;
111 
112  if (!len)
113  return 0;
114 
116 
117  if (*pos + len > handle->size)
118  {
119  HGLOBAL hglobal = GlobalReAlloc(handle->hglobal, *pos + len, GMEM_MOVEABLE);
120  if (hglobal)
121  {
122  handle->hglobal = hglobal;
123  handle->size = *pos + len;
124  }
125  else
126  {
127  len = 0;
128  goto done;
129  }
130  }
131 
132  dest = GlobalLock(handle->hglobal);
133  if (dest)
134  {
135  memcpy((char *)dest + *pos, source, len);
136  *pos += len;
137  GlobalUnlock(handle->hglobal);
138  }
139  else
140  {
141  WARN("write to invalid hglobal %p\n", handle->hglobal);
142  /* len = 0; */
143  }
144 
145 done:
147  return len;
148 }
149 
151 {
152  return handle->hglobal;
153 }
154 
156 {
157  HRESULT hr = S_OK;
158 
160 
161  if (handle->size != size)
162  {
163  HGLOBAL hglobal = GlobalReAlloc(handle->hglobal, size, GMEM_MOVEABLE);
164  if (hglobal)
165  {
166  handle->hglobal = hglobal;
167  handle->size = size;
168  }
169  else
170  hr = E_OUTOFMEMORY;
171  }
172 
174  return hr;
175 }
176 
178 {
179  return handle->size;
180 }
181 
183 {
184  struct handle_wrapper *handle;
185 
186  handle = HeapAlloc(GetProcessHeap(), 0, sizeof(*handle));
187  if (handle)
188  {
189  handle->ref = 1;
190  handle->hglobal = hglobal;
191  handle->size = GlobalSize(hglobal);
192  handle->delete_on_release = delete_on_release;
194  handle->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": handle_wrapper.lock");
195  }
196  return handle;
197 }
198 
199 /****************************************************************************
200  * HGLOBALStreamImpl definition.
201  *
202  * This class implements the IStream interface and represents a stream
203  * supported by an HGLOBAL pointer.
204  */
205 typedef struct
206 {
209 
211 
212  /* current position of the cursor */
215 
217 {
218  return CONTAINING_RECORD(iface, HGLOBALStreamImpl, IStream_iface);
219 }
220 
222  IStream* iface,
223  REFIID riid, /* [in] */
224  void** ppvObject) /* [iid_is][out] */
225 {
227 
228  if (ppvObject==0)
229  return E_INVALIDARG;
230 
231  *ppvObject = 0;
232 
233  if (IsEqualIID(&IID_IUnknown, riid) ||
234  IsEqualIID(&IID_ISequentialStream, riid) ||
235  IsEqualIID(&IID_IStream, riid))
236  {
237  *ppvObject = &This->IStream_iface;
238  }
239 
240  if ((*ppvObject)==0)
241  return E_NOINTERFACE;
242 
243  IStream_AddRef(iface);
244 
245  return S_OK;
246 }
247 
249 {
251  return InterlockedIncrement(&This->ref);
252 }
253 
255  IStream* iface)
256 {
259 
260  if (!ref)
261  {
262  handle_release(This->handle);
264  }
265 
266  return ref;
267 }
268 
269 /***
270  * This method is part of the ISequentialStream interface.
271  *
272  * If reads a block of information from the stream at the current
273  * position. It then moves the current position at the end of the
274  * read block
275  *
276  * See the documentation of ISequentialStream for more info.
277  */
279  IStream* iface,
280  void* pv, /* [length_is][size_is][out] */
281  ULONG cb, /* [in] */
282  ULONG* pcbRead) /* [out] */
283 {
286 
287  TRACE("(%p, %p, %d, %p)\n", iface, pv, cb, pcbRead);
288 
289  num_bytes = handle_read(This->handle, &This->currentPosition.u.LowPart, pv, cb);
290  if (pcbRead) *pcbRead = num_bytes;
291 
292  return S_OK;
293 }
294 
295 /***
296  * This method is part of the ISequentialStream interface.
297  *
298  * It writes a block of information to the stream at the current
299  * position. It then moves the current position at the end of the
300  * written block. If the stream is too small to fit the block,
301  * the stream is grown to fit.
302  *
303  * See the documentation of ISequentialStream for more info.
304  */
306  IStream* iface,
307  const void* pv, /* [size_is][in] */
308  ULONG cb, /* [in] */
309  ULONG* pcbWritten) /* [out] */
310 {
313 
314  TRACE("(%p, %p, %d, %p)\n", iface, pv, cb, pcbWritten);
315 
316  num_bytes = handle_write(This->handle, &This->currentPosition.u.LowPart, pv, cb);
317  if (pcbWritten) *pcbWritten = num_bytes;
318 
319  return (num_bytes < cb) ? E_OUTOFMEMORY : S_OK;
320 }
321 
322 /***
323  * This method is part of the IStream interface.
324  *
325  * It will move the current stream pointer according to the parameters
326  * given.
327  *
328  * See the documentation of IStream for more info.
329  */
331  IStream* iface,
332  LARGE_INTEGER dlibMove, /* [in] */
333  DWORD dwOrigin, /* [in] */
334  ULARGE_INTEGER* plibNewPosition) /* [out] */
335 {
337 
338  ULARGE_INTEGER newPosition = This->currentPosition;
339  HRESULT hr = S_OK;
340 
341  TRACE("(%p, %x%08x, %d, %p)\n", iface, dlibMove.u.HighPart,
342  dlibMove.u.LowPart, dwOrigin, plibNewPosition);
343 
344  /*
345  * The file pointer is moved depending on the given "function"
346  * parameter.
347  */
348  switch (dwOrigin)
349  {
350  case STREAM_SEEK_SET:
351  newPosition.u.HighPart = 0;
352  newPosition.u.LowPart = 0;
353  break;
354  case STREAM_SEEK_CUR:
355  break;
356  case STREAM_SEEK_END:
357  newPosition.QuadPart = handle_getsize(This->handle);
358  break;
359  default:
361  goto end;
362  }
363 
364  /*
365  * Move the actual file pointer
366  * If the file pointer ends-up after the end of the stream, the next Write operation will
367  * make the file larger. This is how it is documented.
368  */
369  newPosition.u.HighPart = 0;
370  newPosition.u.LowPart += dlibMove.QuadPart;
371 
372  if (dlibMove.u.LowPart >= 0x80000000 &&
373  newPosition.u.LowPart >= dlibMove.u.LowPart)
374  {
375  /* We tried to seek backwards and went past the start. */
377  goto end;
378  }
379 
380  This->currentPosition = newPosition;
381 
382 end:
383  if (plibNewPosition) *plibNewPosition = This->currentPosition;
384 
385  return hr;
386 }
387 
388 /***
389  * This method is part of the IStream interface.
390  *
391  * It will change the size of a stream.
392  *
393  * TODO: Switch from small blocks to big blocks and vice versa.
394  *
395  * See the documentation of IStream for more info.
396  */
398  IStream* iface,
399  ULARGE_INTEGER libNewSize) /* [in] */
400 {
402 
403  TRACE("(%p, %d)\n", iface, libNewSize.u.LowPart);
404 
405  /*
406  * HighPart is ignored as shown in tests
407  */
408  return handle_setsize(This->handle, libNewSize.u.LowPart);
409 }
410 
411 /***
412  * This method is part of the IStream interface.
413  *
414  * It will copy the 'cb' Bytes to 'pstm' IStream.
415  *
416  * See the documentation of IStream for more info.
417  */
419  IStream* iface,
420  IStream* pstm, /* [unique][in] */
421  ULARGE_INTEGER cb, /* [in] */
422  ULARGE_INTEGER* pcbRead, /* [out] */
423  ULARGE_INTEGER* pcbWritten) /* [out] */
424 {
425  HRESULT hr = S_OK;
426  BYTE tmpBuffer[128];
427  ULONG bytesRead, bytesWritten, copySize;
428  ULARGE_INTEGER totalBytesRead;
429  ULARGE_INTEGER totalBytesWritten;
430 
431  TRACE("(%p, %p, %d, %p, %p)\n", iface, pstm,
432  cb.u.LowPart, pcbRead, pcbWritten);
433 
434  if ( pstm == 0 )
435  return STG_E_INVALIDPOINTER;
436 
437  totalBytesRead.QuadPart = 0;
438  totalBytesWritten.QuadPart = 0;
439 
440  while ( cb.QuadPart > 0 )
441  {
442  if ( cb.QuadPart >= sizeof(tmpBuffer) )
443  copySize = sizeof(tmpBuffer);
444  else
445  copySize = cb.u.LowPart;
446 
447  hr = IStream_Read(iface, tmpBuffer, copySize, &bytesRead);
448  if (FAILED(hr))
449  break;
450 
451  totalBytesRead.QuadPart += bytesRead;
452 
453  if (bytesRead)
454  {
455  hr = IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten);
456  if (FAILED(hr))
457  break;
458 
459  totalBytesWritten.QuadPart += bytesWritten;
460  }
461 
462  if (bytesRead!=copySize)
463  cb.QuadPart = 0;
464  else
465  cb.QuadPart -= bytesRead;
466  }
467 
468  if (pcbRead) pcbRead->QuadPart = totalBytesRead.QuadPart;
469  if (pcbWritten) pcbWritten->QuadPart = totalBytesWritten.QuadPart;
470 
471  return hr;
472 }
473 
474 /***
475  * This method is part of the IStream interface.
476  *
477  * For streams supported by HGLOBALS, this function does nothing.
478  * This is what the documentation tells us.
479  *
480  * See the documentation of IStream for more info.
481  */
483  IStream* iface,
484  DWORD grfCommitFlags) /* [in] */
485 {
486  return S_OK;
487 }
488 
489 /***
490  * This method is part of the IStream interface.
491  *
492  * For streams supported by HGLOBALS, this function does nothing.
493  * This is what the documentation tells us.
494  *
495  * See the documentation of IStream for more info.
496  */
498  IStream* iface)
499 {
500  return S_OK;
501 }
502 
503 /***
504  * This method is part of the IStream interface.
505  *
506  * For streams supported by HGLOBALS, this function does nothing.
507  * This is what the documentation tells us.
508  *
509  * See the documentation of IStream for more info.
510  */
512  IStream* iface,
513  ULARGE_INTEGER libOffset, /* [in] */
514  ULARGE_INTEGER cb, /* [in] */
515  DWORD dwLockType) /* [in] */
516 {
517  return STG_E_INVALIDFUNCTION;
518 }
519 
520 /*
521  * This method is part of the IStream interface.
522  *
523  * For streams supported by HGLOBALS, this function does nothing.
524  * This is what the documentation tells us.
525  *
526  * See the documentation of IStream for more info.
527  */
529  IStream* iface,
530  ULARGE_INTEGER libOffset, /* [in] */
531  ULARGE_INTEGER cb, /* [in] */
532  DWORD dwLockType) /* [in] */
533 {
534  return S_OK;
535 }
536 
537 /***
538  * This method is part of the IStream interface.
539  *
540  * This method returns information about the current
541  * stream.
542  *
543  * See the documentation of IStream for more info.
544  */
546  IStream* iface,
547  STATSTG* pstatstg, /* [out] */
548  DWORD grfStatFlag) /* [in] */
549 {
551 
552  memset(pstatstg, 0, sizeof(STATSTG));
553 
554  pstatstg->pwcsName = NULL;
555  pstatstg->type = STGTY_STREAM;
556  pstatstg->cbSize.QuadPart = handle_getsize(This->handle);
557 
558  return S_OK;
559 }
560 
561 static const IStreamVtbl HGLOBALStreamImplVtbl;
562 
564 {
566 
567  This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
568  if (This)
569  {
570  This->IStream_iface.lpVtbl = &HGLOBALStreamImplVtbl;
571  This->ref = 1;
572  }
573  return This;
574 }
575 
577  IStream* iface,
578  IStream** ppstm) /* [out] */
579 {
581  HGLOBALStreamImpl* clone;
584 
585  if (!ppstm) return E_INVALIDARG;
586 
587  *ppstm = NULL;
588 
589  TRACE(" Cloning %p (seek position=%d)\n", iface, This->currentPosition.u.LowPart);
590 
591  clone = HGLOBALStreamImpl_Create();
592  if (!clone) return E_OUTOFMEMORY;
593 
594  *ppstm = &clone->IStream_iface;
595 
596  handle_addref(This->handle);
597  clone->handle = This->handle;
598 
599  offset.QuadPart = (LONGLONG)This->currentPosition.QuadPart;
600  IStream_Seek(*ppstm, offset, STREAM_SEEK_SET, &dummy);
601  return S_OK;
602 }
603 
604 static const IStreamVtbl HGLOBALStreamImplVtbl =
605 {
620 };
621 
622 /***********************************************************************
623  * CreateStreamOnHGlobal [OLE32.@]
624  */
626  HGLOBAL hGlobal,
627  BOOL fDeleteOnRelease,
628  LPSTREAM* ppstm)
629 {
631 
632  if (!ppstm)
633  return E_INVALIDARG;
634 
636  if (!This) return E_OUTOFMEMORY;
637 
638  /* allocate a handle if one is not supplied */
639  if (!hGlobal)
641 
642  This->handle = handle_create(hGlobal, fDeleteOnRelease);
643 
644  /* start at the beginning */
645  This->currentPosition.u.HighPart = 0;
646  This->currentPosition.u.LowPart = 0;
647 
648  *ppstm = &This->IStream_iface;
649 
650  return S_OK;
651 }
652 
653 /***********************************************************************
654  * GetHGlobalFromStream [OLE32.@]
655  */
657 {
658  HGLOBALStreamImpl* pStream;
659 
660  if (!pstm || !phglobal)
661  return E_INVALIDARG;
662 
663  pStream = impl_from_IStream(pstm);
664 
665  /*
666  * Verify that the stream object was created with CreateStreamOnHGlobal.
667  */
668  if (pStream->IStream_iface.lpVtbl == &HGLOBALStreamImplVtbl)
669  *phglobal = handle_gethglobal(pStream->handle);
670  else
671  {
672  *phglobal = 0;
673  return E_INVALIDARG;
674  }
675 
676  return S_OK;
677 }
static ULONG WINAPI HGLOBALStreamImpl_AddRef(IStream *iface)
static HGLOBALStreamImpl * impl_from_IStream(IStream *iface)
namespace GUID const ADDRINFOEXW ADDRINFOEXW struct timeval OVERLAPPED LPLOOKUPSERVICE_COMPLETION_ROUTINE HANDLE * handle
Definition: sock.c:82
#define REFIID
Definition: guiddef.h:118
HGLOBAL NTAPI GlobalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:368
HRESULT WINAPI GetHGlobalFromStream(IStream *pstm, HGLOBAL *phglobal)
#define E_NOINTERFACE
Definition: winerror.h:2364
#define DWORD_PTR
Definition: treelist.c:76
HRESULT hr
Definition: shlfolder.c:183
HGLOBAL NTAPI GlobalReAlloc(HGLOBAL hMem, SIZE_T dwBytes, UINT uFlags)
Definition: heapmem.c:825
#define STG_E_INVALIDPOINTER
Definition: winerror.h:2571
#define GMEM_NODISCARD
Definition: winbase.h:299
ULARGE_INTEGER currentPosition
static HRESULT WINAPI HGLOBALStreamImpl_Read(IStream *iface, void *pv, ULONG cb, ULONG *pcbRead)
REFIID riid
Definition: precomp.h:44
#define WARN(fmt,...)
Definition: debug.h:111
static const IStreamVtbl HGLOBALStreamImplVtbl
GLintptr offset
Definition: glext.h:5920
HRESULT WINAPI CreateStreamOnHGlobal(HGLOBAL hGlobal, BOOL fDeleteOnRelease, LPSTREAM *ppstm)
interface IStream * LPSTREAM
Definition: objfwd.h:10
GLuint GLuint end
Definition: gl.h:1545
#define GMEM_SHARE
Definition: winbase.h:302
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
Definition: send.c:47
SIZE_T NTAPI GlobalSize(HGLOBAL hMem)
Definition: heapmem.c:1090
static void handle_addref(struct handle_wrapper *handle)
Definition: hglobalstream.c:57
static HRESULT handle_setsize(struct handle_wrapper *handle, ULONG size)
static ULONG handle_write(struct handle_wrapper *handle, ULONG *pos, const void *source, ULONG len)
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
struct _LARGE_INTEGER::@2201 u
static ULONG handle_getsize(struct handle_wrapper *handle)
GLenum GLint ref
Definition: glext.h:6028
static HRESULT WINAPI HGLOBALStreamImpl_Seek(IStream *iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
#define E_INVALIDARG
Definition: ddrawi.h:101
static HRESULT WINAPI HGLOBALStreamImpl_CopyTo(IStream *iface, IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:751
smooth NULL
Definition: ftsmooth.c:416
static HRESULT WINAPI HGLOBALStreamImpl_SetSize(IStream *iface, ULARGE_INTEGER libNewSize)
#define STG_E_INVALIDFUNCTION
Definition: winerror.h:2564
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
static HRESULT WINAPI HGLOBALStreamImpl_Stat(IStream *iface, STATSTG *pstatstg, DWORD grfStatFlag)
int64_t LONGLONG
Definition: typedefs.h:66
#define TRACE(s)
Definition: solgame.cpp:4
GLsizeiptr size
Definition: glext.h:5919
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
LONG HRESULT
Definition: typedefs.h:77
static HGLOBALStreamImpl * HGLOBALStreamImpl_Create(void)
const GUID IID_IUnknown
#define WINAPI
Definition: msvc.h:8
ed2 num_bytes
Definition: write.c:2846
unsigned long DWORD
Definition: ntddk_ex.h:95
HGLOBAL NTAPI GlobalFree(HGLOBAL hMem)
Definition: heapmem.c:611
static DWORD cb
Definition: integrity.c:41
WINE_DEFAULT_DEBUG_CHANNEL(hglobalstream)
struct handle_wrapper * handle
LPVOID NTAPI GlobalLock(HGLOBAL hMem)
Definition: heapmem.c:755
#define InterlockedDecrement
Definition: armddk.h:52
BOOL delete_on_release
Definition: hglobalstream.c:53
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
unsigned char BYTE
Definition: mem.h:68
REFIID LPVOID * ppvObject
Definition: precomp.h:44
static HRESULT WINAPI HGLOBALStreamImpl_Commit(IStream *iface, DWORD grfCommitFlags)
static ULONG handle_read(struct handle_wrapper *handle, ULONG *pos, void *dest, ULONG len)
Definition: hglobalstream.c:80
GLenum GLsizei GLuint GLint * bytesWritten
Definition: glext.h:11123
#define S_OK
Definition: intsafe.h:59
static HRESULT WINAPI HGLOBALStreamImpl_LockRegion(IStream *iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
#define InterlockedIncrement
Definition: armddk.h:53
static void handle_release(struct handle_wrapper *handle)
Definition: hglobalstream.c:62
GLsizei GLsizei GLchar * source
Definition: glext.h:6048
unsigned char dummy
Definition: maze.c:118
static HRESULT WINAPI HGLOBALStreamImpl_UnlockRegion(IStream *iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
struct _ULARGE_INTEGER::@3746 u
static HRESULT WINAPI HGLOBALStreamImpl_Clone(IStream *iface, IStream **ppstm)
#define min(a, b)
Definition: monoChain.cc:55
BOOL NTAPI GlobalUnlock(HGLOBAL hMem)
Definition: heapmem.c:1190
static HRESULT WINAPI HGLOBALStreamImpl_Write(IStream *iface, const void *pv, ULONG cb, ULONG *pcbWritten)
CRITICAL_SECTION lock
Definition: hglobalstream.c:54
static HRESULT WINAPI HGLOBALStreamImpl_QueryInterface(IStream *iface, REFIID riid, void **ppvObject)
unsigned int ULONG
Definition: retypes.h:1
static HRESULT WINAPI HGLOBALStreamImpl_Revert(IStream *iface)
static char * dest
Definition: rtl.c:135
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
static struct handle_wrapper * handle_create(HGLOBAL hglobal, BOOL delete_on_release)
#define memset(x, y, z)
Definition: compat.h:39
#define HeapFree(x, y, z)
Definition: compat.h:394
#define STG_E_SEEKERROR
Definition: winerror.h:2574
#define GMEM_MOVEABLE
Definition: winbase.h:291
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
static HGLOBAL handle_gethglobal(struct handle_wrapper *handle)
static ULONG WINAPI HGLOBALStreamImpl_Release(IStream *iface)
LONGLONG QuadPart
Definition: typedefs.h:112