ReactOS  0.4.14-dev-554-g2f8d847
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 <assert.h>
26 #include <stdlib.h>
27 #include <stdarg.h>
28 #include <stdio.h>
29 #include <string.h>
30 
31 #define COBJMACROS
32 #define NONAMELESSUNION
33 
34 #include "windef.h"
35 #include "winbase.h"
36 #include "winuser.h"
37 #include "objbase.h"
38 #include "ole2.h"
39 #include "winerror.h"
40 #include "winternl.h"
41 
42 #include "wine/debug.h"
43 
44 WINE_DEFAULT_DEBUG_CHANNEL(hglobalstream);
45 
47 {
53 };
54 
55 static void handle_addref(struct handle_wrapper *handle)
56 {
58 }
59 
60 static void handle_release(struct handle_wrapper *handle)
61 {
63 
64  if (!ref)
65  {
66  if (handle->delete_on_release)
67  {
68  GlobalFree(handle->hglobal);
69  handle->hglobal = NULL;
70  }
71 
72  handle->lock.DebugInfo->Spare[0] = 0;
75  }
76 }
77 
79 {
80  void *source;
81 
83 
84  if (*pos < handle->size)
85  len = min(handle->size - *pos, len);
86  else
87  len = 0;
88 
89  source = GlobalLock(handle->hglobal);
90  if (source)
91  {
92  memcpy(dest, (char *)source + *pos, len);
93  *pos += len;
94  GlobalUnlock(handle->hglobal);
95  }
96  else
97  {
98  WARN("read from invalid hglobal %p\n", handle->hglobal);
99  len = 0;
100  }
101 
103  return len;
104 }
105 
106 static ULONG handle_write(struct handle_wrapper *handle, ULONG *pos, const void *source, ULONG len)
107 {
108  void *dest;
109 
110  if (!len)
111  return 0;
112 
114 
115  if (*pos + len > handle->size)
116  {
117  HGLOBAL hglobal = GlobalReAlloc(handle->hglobal, *pos + len, GMEM_MOVEABLE);
118  if (hglobal)
119  {
120  handle->hglobal = hglobal;
121  handle->size = *pos + len;
122  }
123  else
124  {
125  len = 0;
126  goto done;
127  }
128  }
129 
130  dest = GlobalLock(handle->hglobal);
131  if (dest)
132  {
133  memcpy((char *)dest + *pos, source, len);
134  *pos += len;
135  GlobalUnlock(handle->hglobal);
136  }
137  else
138  {
139  WARN("write to invalid hglobal %p\n", handle->hglobal);
140  /* len = 0; */
141  }
142 
143 done:
145  return len;
146 }
147 
149 {
150  return handle->hglobal;
151 }
152 
154 {
155  HRESULT hr = S_OK;
156 
158 
159  if (handle->size != size)
160  {
161  HGLOBAL hglobal = GlobalReAlloc(handle->hglobal, size, GMEM_MOVEABLE);
162  if (hglobal)
163  {
164  handle->hglobal = hglobal;
165  handle->size = size;
166  }
167  else
168  hr = E_OUTOFMEMORY;
169  }
170 
172  return hr;
173 }
174 
176 {
177  return handle->size;
178 }
179 
181 {
182  struct handle_wrapper *handle;
183 
184  handle = HeapAlloc(GetProcessHeap(), 0, sizeof(*handle));
185  if (handle)
186  {
187  handle->ref = 1;
188  handle->hglobal = hglobal;
189  handle->size = GlobalSize(hglobal);
190  handle->delete_on_release = delete_on_release;
192  handle->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": handle_wrapper.lock");
193  }
194  return handle;
195 }
196 
197 /****************************************************************************
198  * HGLOBALStreamImpl definition.
199  *
200  * This class implements the IStream interface and represents a stream
201  * supported by an HGLOBAL pointer.
202  */
203 typedef struct
204 {
207 
209 
210  /* current position of the cursor */
213 
215 {
216  return CONTAINING_RECORD(iface, HGLOBALStreamImpl, IStream_iface);
217 }
218 
220  IStream* iface,
221  REFIID riid, /* [in] */
222  void** ppvObject) /* [iid_is][out] */
223 {
225 
226  if (ppvObject==0)
227  return E_INVALIDARG;
228 
229  *ppvObject = 0;
230 
231  if (IsEqualIID(&IID_IUnknown, riid) ||
232  IsEqualIID(&IID_ISequentialStream, riid) ||
233  IsEqualIID(&IID_IStream, riid))
234  {
235  *ppvObject = &This->IStream_iface;
236  }
237 
238  if ((*ppvObject)==0)
239  return E_NOINTERFACE;
240 
241  IStream_AddRef(iface);
242 
243  return S_OK;
244 }
245 
247 {
249  return InterlockedIncrement(&This->ref);
250 }
251 
253  IStream* iface)
254 {
257 
258  if (!ref)
259  {
260  handle_release(This->handle);
262  }
263 
264  return ref;
265 }
266 
267 /***
268  * This method is part of the ISequentialStream interface.
269  *
270  * If reads a block of information from the stream at the current
271  * position. It then moves the current position at the end of the
272  * read block
273  *
274  * See the documentation of ISequentialStream for more info.
275  */
277  IStream* iface,
278  void* pv, /* [length_is][size_is][out] */
279  ULONG cb, /* [in] */
280  ULONG* pcbRead) /* [out] */
281 {
284 
285  TRACE("(%p, %p, %d, %p)\n", iface, pv, cb, pcbRead);
286 
287  num_bytes = handle_read(This->handle, &This->currentPosition.u.LowPart, pv, cb);
288  if (pcbRead) *pcbRead = num_bytes;
289 
290  return S_OK;
291 }
292 
293 /***
294  * This method is part of the ISequentialStream interface.
295  *
296  * It writes a block of information to the stream at the current
297  * position. It then moves the current position at the end of the
298  * written block. If the stream is too small to fit the block,
299  * the stream is grown to fit.
300  *
301  * See the documentation of ISequentialStream for more info.
302  */
304  IStream* iface,
305  const void* pv, /* [size_is][in] */
306  ULONG cb, /* [in] */
307  ULONG* pcbWritten) /* [out] */
308 {
311 
312  TRACE("(%p, %p, %d, %p)\n", iface, pv, cb, pcbWritten);
313 
314  num_bytes = handle_write(This->handle, &This->currentPosition.u.LowPart, pv, cb);
315  if (pcbWritten) *pcbWritten = num_bytes;
316 
317  return (num_bytes < cb) ? E_OUTOFMEMORY : S_OK;
318 }
319 
320 /***
321  * This method is part of the IStream interface.
322  *
323  * It will move the current stream pointer according to the parameters
324  * given.
325  *
326  * See the documentation of IStream for more info.
327  */
329  IStream* iface,
330  LARGE_INTEGER dlibMove, /* [in] */
331  DWORD dwOrigin, /* [in] */
332  ULARGE_INTEGER* plibNewPosition) /* [out] */
333 {
335 
336  ULARGE_INTEGER newPosition = This->currentPosition;
337  HRESULT hr = S_OK;
338 
339  TRACE("(%p, %x%08x, %d, %p)\n", iface, dlibMove.u.HighPart,
340  dlibMove.u.LowPart, dwOrigin, plibNewPosition);
341 
342  /*
343  * The file pointer is moved depending on the given "function"
344  * parameter.
345  */
346  switch (dwOrigin)
347  {
348  case STREAM_SEEK_SET:
349  newPosition.u.HighPart = 0;
350  newPosition.u.LowPart = 0;
351  break;
352  case STREAM_SEEK_CUR:
353  break;
354  case STREAM_SEEK_END:
355  newPosition.QuadPart = handle_getsize(This->handle);
356  break;
357  default:
359  goto end;
360  }
361 
362  /*
363  * Move the actual file pointer
364  * If the file pointer ends-up after the end of the stream, the next Write operation will
365  * make the file larger. This is how it is documented.
366  */
367  newPosition.u.HighPart = 0;
368  newPosition.u.LowPart += dlibMove.QuadPart;
369 
370  if (dlibMove.u.LowPart >= 0x80000000 &&
371  newPosition.u.LowPart >= dlibMove.u.LowPart)
372  {
373  /* We tried to seek backwards and went past the start. */
375  goto end;
376  }
377 
378  This->currentPosition = newPosition;
379 
380 end:
381  if (plibNewPosition) *plibNewPosition = This->currentPosition;
382 
383  return hr;
384 }
385 
386 /***
387  * This method is part of the IStream interface.
388  *
389  * It will change the size of a stream.
390  *
391  * TODO: Switch from small blocks to big blocks and vice versa.
392  *
393  * See the documentation of IStream for more info.
394  */
396  IStream* iface,
397  ULARGE_INTEGER libNewSize) /* [in] */
398 {
400 
401  TRACE("(%p, %d)\n", iface, libNewSize.u.LowPart);
402 
403  /*
404  * HighPart is ignored as shown in tests
405  */
406  return handle_setsize(This->handle, libNewSize.u.LowPart);
407 }
408 
409 /***
410  * This method is part of the IStream interface.
411  *
412  * It will copy the 'cb' Bytes to 'pstm' IStream.
413  *
414  * See the documentation of IStream for more info.
415  */
417  IStream* iface,
418  IStream* pstm, /* [unique][in] */
419  ULARGE_INTEGER cb, /* [in] */
420  ULARGE_INTEGER* pcbRead, /* [out] */
421  ULARGE_INTEGER* pcbWritten) /* [out] */
422 {
423  HRESULT hr = S_OK;
424  BYTE tmpBuffer[128];
425  ULONG bytesRead, bytesWritten, copySize;
426  ULARGE_INTEGER totalBytesRead;
427  ULARGE_INTEGER totalBytesWritten;
428 
429  TRACE("(%p, %p, %d, %p, %p)\n", iface, pstm,
430  cb.u.LowPart, pcbRead, pcbWritten);
431 
432  if ( pstm == 0 )
433  return STG_E_INVALIDPOINTER;
434 
435  totalBytesRead.QuadPart = 0;
436  totalBytesWritten.QuadPart = 0;
437 
438  while ( cb.QuadPart > 0 )
439  {
440  if ( cb.QuadPart >= sizeof(tmpBuffer) )
441  copySize = sizeof(tmpBuffer);
442  else
443  copySize = cb.u.LowPart;
444 
445  hr = IStream_Read(iface, tmpBuffer, copySize, &bytesRead);
446  if (FAILED(hr))
447  break;
448 
449  totalBytesRead.QuadPart += bytesRead;
450 
451  if (bytesRead)
452  {
453  hr = IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten);
454  if (FAILED(hr))
455  break;
456 
457  totalBytesWritten.QuadPart += bytesWritten;
458  }
459 
460  if (bytesRead!=copySize)
461  cb.QuadPart = 0;
462  else
463  cb.QuadPart -= bytesRead;
464  }
465 
466  if (pcbRead) pcbRead->QuadPart = totalBytesRead.QuadPart;
467  if (pcbWritten) pcbWritten->QuadPart = totalBytesWritten.QuadPart;
468 
469  return hr;
470 }
471 
472 /***
473  * This method is part of the IStream interface.
474  *
475  * For streams supported by HGLOBALS, this function does nothing.
476  * This is what the documentation tells us.
477  *
478  * See the documentation of IStream for more info.
479  */
481  IStream* iface,
482  DWORD grfCommitFlags) /* [in] */
483 {
484  return S_OK;
485 }
486 
487 /***
488  * This method is part of the IStream interface.
489  *
490  * For streams supported by HGLOBALS, this function does nothing.
491  * This is what the documentation tells us.
492  *
493  * See the documentation of IStream for more info.
494  */
496  IStream* iface)
497 {
498  return S_OK;
499 }
500 
501 /***
502  * This method is part of the IStream interface.
503  *
504  * For streams supported by HGLOBALS, this function does nothing.
505  * This is what the documentation tells us.
506  *
507  * See the documentation of IStream for more info.
508  */
510  IStream* iface,
511  ULARGE_INTEGER libOffset, /* [in] */
512  ULARGE_INTEGER cb, /* [in] */
513  DWORD dwLockType) /* [in] */
514 {
515  return STG_E_INVALIDFUNCTION;
516 }
517 
518 /*
519  * This method is part of the IStream interface.
520  *
521  * For streams supported by HGLOBALS, this function does nothing.
522  * This is what the documentation tells us.
523  *
524  * See the documentation of IStream for more info.
525  */
527  IStream* iface,
528  ULARGE_INTEGER libOffset, /* [in] */
529  ULARGE_INTEGER cb, /* [in] */
530  DWORD dwLockType) /* [in] */
531 {
532  return S_OK;
533 }
534 
535 /***
536  * This method is part of the IStream interface.
537  *
538  * This method returns information about the current
539  * stream.
540  *
541  * See the documentation of IStream for more info.
542  */
544  IStream* iface,
545  STATSTG* pstatstg, /* [out] */
546  DWORD grfStatFlag) /* [in] */
547 {
549 
550  memset(pstatstg, 0, sizeof(STATSTG));
551 
552  pstatstg->pwcsName = NULL;
553  pstatstg->type = STGTY_STREAM;
554  pstatstg->cbSize.QuadPart = handle_getsize(This->handle);
555 
556  return S_OK;
557 }
558 
559 static const IStreamVtbl HGLOBALStreamImplVtbl;
560 
562 {
564 
565  This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
566  if (This)
567  {
568  This->IStream_iface.lpVtbl = &HGLOBALStreamImplVtbl;
569  This->ref = 1;
570  }
571  return This;
572 }
573 
575  IStream* iface,
576  IStream** ppstm) /* [out] */
577 {
579  HGLOBALStreamImpl* clone;
582 
583  if (!ppstm) return E_INVALIDARG;
584 
585  *ppstm = NULL;
586 
587  TRACE(" Cloning %p (seek position=%d)\n", iface, This->currentPosition.u.LowPart);
588 
589  clone = HGLOBALStreamImpl_Create();
590  if (!clone) return E_OUTOFMEMORY;
591 
592  *ppstm = &clone->IStream_iface;
593 
594  handle_addref(This->handle);
595  clone->handle = This->handle;
596 
597  offset.QuadPart = (LONGLONG)This->currentPosition.QuadPart;
598  IStream_Seek(*ppstm, offset, STREAM_SEEK_SET, &dummy);
599  return S_OK;
600 }
601 
602 static const IStreamVtbl HGLOBALStreamImplVtbl =
603 {
618 };
619 
620 /***********************************************************************
621  * CreateStreamOnHGlobal [OLE32.@]
622  */
624  HGLOBAL hGlobal,
625  BOOL fDeleteOnRelease,
626  LPSTREAM* ppstm)
627 {
629 
630  if (!ppstm)
631  return E_INVALIDARG;
632 
634  if (!This) return E_OUTOFMEMORY;
635 
636  /* allocate a handle if one is not supplied */
637  if (!hGlobal)
639 
640  This->handle = handle_create(hGlobal, fDeleteOnRelease);
641 
642  /* start at the beginning */
643  This->currentPosition.u.HighPart = 0;
644  This->currentPosition.u.LowPart = 0;
645 
646  *ppstm = &This->IStream_iface;
647 
648  return S_OK;
649 }
650 
651 /***********************************************************************
652  * GetHGlobalFromStream [OLE32.@]
653  */
655 {
656  HGLOBALStreamImpl* pStream;
657 
658  if (!pstm || !phglobal)
659  return E_INVALIDARG;
660 
661  pStream = impl_from_IStream(pstm);
662 
663  /*
664  * Verify that the stream object was created with CreateStreamOnHGlobal.
665  */
666  if (pStream->IStream_iface.lpVtbl == &HGLOBALStreamImplVtbl)
667  *phglobal = handle_gethglobal(pStream->handle);
668  else
669  {
670  *phglobal = 0;
671  return E_INVALIDARG;
672  }
673 
674  return S_OK;
675 }
struct _LARGE_INTEGER::@2220 u
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:55
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
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:403
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
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:51
#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:78
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:60
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)
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)
static HMODULE MODULEINFO DWORD cb
Definition: module.c:32
CRITICAL_SECTION lock
Definition: hglobalstream.c:52
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
struct _ULARGE_INTEGER::@3769 u
#define HeapFree(x, y, z)
Definition: compat.h:402
#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