Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 1 | /* |
| 2 | * HGLOBAL Stream implementation |
| 3 | * |
| 4 | * This file contains the implementation of the stream interface |
Alexandre Julliard | 81ee21d | 1999-12-27 05:26:00 +0000 | [diff] [blame] | 5 | * for streams contained supported by an HGLOBAL pointer. |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 6 | * |
| 7 | * Copyright 1999 Francis Beaudet |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 8 | * |
| 9 | * This library is free software; you can redistribute it and/or |
| 10 | * modify it under the terms of the GNU Lesser General Public |
| 11 | * License as published by the Free Software Foundation; either |
| 12 | * version 2.1 of the License, or (at your option) any later version. |
| 13 | * |
| 14 | * This library is distributed in the hope that it will be useful, |
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 17 | * Lesser General Public License for more details. |
| 18 | * |
| 19 | * You should have received a copy of the GNU Lesser General Public |
| 20 | * License along with this library; if not, write to the Free Software |
Jonathan Ernst | 360a3f9 | 2006-05-18 14:49:52 +0200 | [diff] [blame] | 21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 22 | */ |
Patrik Stridvall | bc38d6b | 2001-07-20 18:00:00 +0000 | [diff] [blame] | 23 | |
| 24 | #include "config.h" |
| 25 | |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 26 | #include <assert.h> |
| 27 | #include <stdlib.h> |
Alexandre Julliard | e37c6e1 | 2003-09-05 23:08:26 +0000 | [diff] [blame] | 28 | #include <stdarg.h> |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 29 | #include <stdio.h> |
| 30 | #include <string.h> |
| 31 | |
Francois Gouget | 486d020 | 2004-10-07 03:06:48 +0000 | [diff] [blame] | 32 | #define COBJMACROS |
Dimitrie O. Paun | 297f3d8 | 2003-01-07 20:36:20 +0000 | [diff] [blame] | 33 | #define NONAMELESSUNION |
| 34 | #define NONAMELESSSTRUCT |
Francois Gouget | 486d020 | 2004-10-07 03:06:48 +0000 | [diff] [blame] | 35 | |
Patrik Stridvall | bc38d6b | 2001-07-20 18:00:00 +0000 | [diff] [blame] | 36 | #include "windef.h" |
Alexandre Julliard | e37c6e1 | 2003-09-05 23:08:26 +0000 | [diff] [blame] | 37 | #include "winbase.h" |
Alexandre Julliard | 20c169e | 2003-09-09 19:39:31 +0000 | [diff] [blame] | 38 | #include "winuser.h" |
Patrik Stridvall | bc38d6b | 2001-07-20 18:00:00 +0000 | [diff] [blame] | 39 | #include "objbase.h" |
| 40 | #include "ole2.h" |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 41 | #include "winerror.h" |
Patrik Stridvall | 9c1de6d | 2002-09-12 22:07:02 +0000 | [diff] [blame] | 42 | #include "winternl.h" |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 43 | |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 44 | #include "wine/debug.h" |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 45 | |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 46 | WINE_DEFAULT_DEBUG_CHANNEL(storage); |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 47 | |
| 48 | /**************************************************************************** |
| 49 | * HGLOBALStreamImpl definition. |
| 50 | * |
Huw Davies | 8519a6c | 2006-11-21 20:44:54 +0000 | [diff] [blame] | 51 | * This class implements the IStream interface and represents a stream |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 52 | * supported by an HGLOBAL pointer. |
| 53 | */ |
| 54 | struct HGLOBALStreamImpl |
| 55 | { |
Dmitry Timoshkov | eba47f1 | 2005-06-06 19:50:35 +0000 | [diff] [blame] | 56 | const IStreamVtbl *lpVtbl; /* Needs to be the first item in the struct |
Francois Gouget | 93416cd | 2005-03-23 13:15:18 +0000 | [diff] [blame] | 57 | * since we want to cast this in an IStream pointer */ |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 58 | |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 59 | /* |
| 60 | * Reference count |
| 61 | */ |
Mike McCormack | c7fdb45 | 2005-07-05 11:02:54 +0000 | [diff] [blame] | 62 | LONG ref; |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 63 | |
| 64 | /* |
| 65 | * Support for the stream |
| 66 | */ |
| 67 | HGLOBAL supportHandle; |
| 68 | |
| 69 | /* |
| 70 | * This flag is TRUE if the HGLOBAL is destroyed when the stream |
| 71 | * is finally released. |
| 72 | */ |
| 73 | BOOL deleteOnRelease; |
| 74 | |
| 75 | /* |
| 76 | * Helper variable that contains the size of the stream |
| 77 | */ |
| 78 | ULARGE_INTEGER streamSize; |
| 79 | |
| 80 | /* |
| 81 | * This is the current position of the cursor in the stream |
| 82 | */ |
| 83 | ULARGE_INTEGER currentPosition; |
| 84 | }; |
| 85 | |
| 86 | typedef struct HGLOBALStreamImpl HGLOBALStreamImpl; |
| 87 | |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 88 | /*** |
| 89 | * This is the destructor of the HGLOBALStreamImpl class. |
| 90 | * |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 91 | * This method will clean-up all the resources used-up by the given HGLOBALStreamImpl |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 92 | * class. The pointer passed-in to this function will be freed and will not |
| 93 | * be valid anymore. |
| 94 | */ |
Marcus Meissner | 45bc1c2 | 2005-05-16 08:47:14 +0000 | [diff] [blame] | 95 | static void HGLOBALStreamImpl_Destroy(HGLOBALStreamImpl* This) |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 96 | { |
Alexandre Julliard | 359f497e | 1999-07-04 16:02:24 +0000 | [diff] [blame] | 97 | TRACE("(%p)\n", This); |
Francis Beaudet | ec2edc7 | 1999-05-02 11:41:10 +0000 | [diff] [blame] | 98 | |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 99 | /* |
| 100 | * Release the HGlobal if the constructor asked for that. |
| 101 | */ |
| 102 | if (This->deleteOnRelease) |
| 103 | { |
| 104 | GlobalFree(This->supportHandle); |
| 105 | This->supportHandle=0; |
| 106 | } |
| 107 | |
| 108 | /* |
| 109 | * Finally, free the memory used-up by the class. |
| 110 | */ |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 111 | HeapFree(GetProcessHeap(), 0, This); |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 112 | } |
| 113 | |
| 114 | /*** |
Marcus Meissner | 45bc1c2 | 2005-05-16 08:47:14 +0000 | [diff] [blame] | 115 | * This implements the IUnknown method AddRef for this |
| 116 | * class |
| 117 | */ |
| 118 | static ULONG WINAPI HGLOBALStreamImpl_AddRef( |
| 119 | IStream* iface) |
| 120 | { |
| 121 | HGLOBALStreamImpl* const This=(HGLOBALStreamImpl*)iface; |
| 122 | return InterlockedIncrement(&This->ref); |
| 123 | } |
| 124 | |
| 125 | /*** |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 126 | * This implements the IUnknown method QueryInterface for this |
| 127 | * class |
| 128 | */ |
Marcus Meissner | 45bc1c2 | 2005-05-16 08:47:14 +0000 | [diff] [blame] | 129 | static HRESULT WINAPI HGLOBALStreamImpl_QueryInterface( |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 130 | IStream* iface, |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 131 | REFIID riid, /* [in] */ |
| 132 | void** ppvObject) /* [iid_is][out] */ |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 133 | { |
| 134 | HGLOBALStreamImpl* const This=(HGLOBALStreamImpl*)iface; |
| 135 | |
| 136 | /* |
| 137 | * Perform a sanity check on the parameters. |
| 138 | */ |
| 139 | if (ppvObject==0) |
| 140 | return E_INVALIDARG; |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 141 | |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 142 | /* |
| 143 | * Initialize the return parameter. |
| 144 | */ |
| 145 | *ppvObject = 0; |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 146 | |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 147 | /* |
| 148 | * Compare the riid with the interface IDs implemented by this object. |
| 149 | */ |
Rob Shearman | 482063b | 2007-01-07 12:15:59 +0000 | [diff] [blame] | 150 | if (IsEqualIID(&IID_IUnknown, riid) || |
| 151 | IsEqualIID(&IID_ISequentialStream, riid) || |
| 152 | IsEqualIID(&IID_IStream, riid)) |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 153 | { |
Michael Stefaniuc | 0449701 | 2009-02-11 10:48:38 +0100 | [diff] [blame] | 154 | *ppvObject = This; |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 155 | } |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 156 | |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 157 | /* |
| 158 | * Check that we obtained an interface. |
| 159 | */ |
| 160 | if ((*ppvObject)==0) |
| 161 | return E_NOINTERFACE; |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 162 | |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 163 | /* |
| 164 | * Query Interface always increases the reference count by one when it is |
| 165 | * successful |
| 166 | */ |
| 167 | HGLOBALStreamImpl_AddRef(iface); |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 168 | |
| 169 | return S_OK; |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 170 | } |
| 171 | |
| 172 | /*** |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 173 | * This implements the IUnknown method Release for this |
| 174 | * class |
| 175 | */ |
Marcus Meissner | 45bc1c2 | 2005-05-16 08:47:14 +0000 | [diff] [blame] | 176 | static ULONG WINAPI HGLOBALStreamImpl_Release( |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 177 | IStream* iface) |
| 178 | { |
| 179 | HGLOBALStreamImpl* const This=(HGLOBALStreamImpl*)iface; |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 180 | ULONG newRef; |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 181 | |
Joris Huizer | 34cffce | 2004-09-24 01:16:53 +0000 | [diff] [blame] | 182 | newRef = InterlockedDecrement(&This->ref); |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 183 | |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 184 | /* |
| 185 | * If the reference count goes down to 0, perform suicide. |
| 186 | */ |
| 187 | if (newRef==0) |
| 188 | { |
| 189 | HGLOBALStreamImpl_Destroy(This); |
| 190 | } |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 191 | |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 192 | return newRef; |
| 193 | } |
| 194 | |
| 195 | /*** |
| 196 | * This method is part of the ISequentialStream interface. |
| 197 | * |
| 198 | * If reads a block of information from the stream at the current |
| 199 | * position. It then moves the current position at the end of the |
| 200 | * read block |
| 201 | * |
| 202 | * See the documentation of ISequentialStream for more info. |
| 203 | */ |
Marcus Meissner | 45bc1c2 | 2005-05-16 08:47:14 +0000 | [diff] [blame] | 204 | static HRESULT WINAPI HGLOBALStreamImpl_Read( |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 205 | IStream* iface, |
| 206 | void* pv, /* [length_is][size_is][out] */ |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 207 | ULONG cb, /* [in] */ |
| 208 | ULONG* pcbRead) /* [out] */ |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 209 | { |
| 210 | HGLOBALStreamImpl* const This=(HGLOBALStreamImpl*)iface; |
| 211 | |
| 212 | void* supportBuffer; |
| 213 | ULONG bytesReadBuffer; |
| 214 | ULONG bytesToReadFromBuffer; |
Francis Beaudet | ec2edc7 | 1999-05-02 11:41:10 +0000 | [diff] [blame] | 215 | |
Michael Stefaniuc | 21ff87b | 2006-10-15 12:28:08 +0200 | [diff] [blame] | 216 | TRACE("(%p, %p, %d, %p)\n", iface, |
Francis Beaudet | ec2edc7 | 1999-05-02 11:41:10 +0000 | [diff] [blame] | 217 | pv, cb, pcbRead); |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 218 | |
| 219 | /* |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 220 | * If the caller is not interested in the nubmer of bytes read, |
| 221 | * we use another buffer to avoid "if" statements in the code. |
| 222 | */ |
| 223 | if (pcbRead==0) |
| 224 | pcbRead = &bytesReadBuffer; |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 225 | |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 226 | /* |
| 227 | * Using the known size of the stream, calculate the number of bytes |
| 228 | * to read from the block chain |
| 229 | */ |
Ge van Geldorp | 399901e | 2004-01-23 01:51:33 +0000 | [diff] [blame] | 230 | bytesToReadFromBuffer = min( This->streamSize.u.LowPart - This->currentPosition.u.LowPart, cb); |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 231 | |
| 232 | /* |
| 233 | * Lock the buffer in position and copy the data. |
| 234 | */ |
| 235 | supportBuffer = GlobalLock(This->supportHandle); |
Rob Shearman | 82cfed9 | 2007-05-17 17:06:56 +0100 | [diff] [blame] | 236 | if (!supportBuffer) |
| 237 | { |
| 238 | WARN("read from invalid hglobal %p\n", This->supportHandle); |
| 239 | *pcbRead = 0; |
| 240 | return S_OK; |
| 241 | } |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 242 | |
Ge van Geldorp | 399901e | 2004-01-23 01:51:33 +0000 | [diff] [blame] | 243 | memcpy(pv, (char *) supportBuffer+This->currentPosition.u.LowPart, bytesToReadFromBuffer); |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 244 | |
| 245 | /* |
| 246 | * Move the current position to the new position |
| 247 | */ |
Ge van Geldorp | 399901e | 2004-01-23 01:51:33 +0000 | [diff] [blame] | 248 | This->currentPosition.u.LowPart+=bytesToReadFromBuffer; |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 249 | |
| 250 | /* |
| 251 | * Return the number of bytes read. |
| 252 | */ |
| 253 | *pcbRead = bytesToReadFromBuffer; |
| 254 | |
| 255 | /* |
| 256 | * Cleanup |
| 257 | */ |
| 258 | GlobalUnlock(This->supportHandle); |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 259 | |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 260 | /* |
Robert Shearman | a552c2e | 2006-09-11 11:11:56 +0100 | [diff] [blame] | 261 | * Always returns S_OK even if the end of the stream is reached before the |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 262 | * buffer is filled |
| 263 | */ |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 264 | |
Robert Shearman | a552c2e | 2006-09-11 11:11:56 +0100 | [diff] [blame] | 265 | return S_OK; |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 266 | } |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 267 | |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 268 | /*** |
| 269 | * This method is part of the ISequentialStream interface. |
| 270 | * |
| 271 | * It writes a block of information to the stream at the current |
| 272 | * position. It then moves the current position at the end of the |
| 273 | * written block. If the stream is too small to fit the block, |
| 274 | * the stream is grown to fit. |
| 275 | * |
| 276 | * See the documentation of ISequentialStream for more info. |
| 277 | */ |
Marcus Meissner | 45bc1c2 | 2005-05-16 08:47:14 +0000 | [diff] [blame] | 278 | static HRESULT WINAPI HGLOBALStreamImpl_Write( |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 279 | IStream* iface, |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 280 | const void* pv, /* [size_is][in] */ |
| 281 | ULONG cb, /* [in] */ |
| 282 | ULONG* pcbWritten) /* [out] */ |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 283 | { |
| 284 | HGLOBALStreamImpl* const This=(HGLOBALStreamImpl*)iface; |
| 285 | |
| 286 | void* supportBuffer; |
| 287 | ULARGE_INTEGER newSize; |
| 288 | ULONG bytesWritten = 0; |
Francis Beaudet | ec2edc7 | 1999-05-02 11:41:10 +0000 | [diff] [blame] | 289 | |
Michael Stefaniuc | 21ff87b | 2006-10-15 12:28:08 +0200 | [diff] [blame] | 290 | TRACE("(%p, %p, %d, %p)\n", iface, pv, cb, pcbWritten); |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 291 | |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 292 | /* |
| 293 | * If the caller is not interested in the number of bytes written, |
| 294 | * we use another buffer to avoid "if" statements in the code. |
| 295 | */ |
| 296 | if (pcbWritten == 0) |
| 297 | pcbWritten = &bytesWritten; |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 298 | |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 299 | if (cb == 0) |
Mike McCormack | 8dc5bd8 | 2006-08-14 14:06:53 +0900 | [diff] [blame] | 300 | goto out; |
| 301 | |
Rob Shearman | 82cfed9 | 2007-05-17 17:06:56 +0100 | [diff] [blame] | 302 | *pcbWritten = 0; |
| 303 | |
Mike McCormack | 8dc5bd8 | 2006-08-14 14:06:53 +0900 | [diff] [blame] | 304 | newSize.u.HighPart = 0; |
| 305 | newSize.u.LowPart = This->currentPosition.u.LowPart + cb; |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 306 | |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 307 | /* |
| 308 | * Verify if we need to grow the stream |
| 309 | */ |
Ge van Geldorp | 399901e | 2004-01-23 01:51:33 +0000 | [diff] [blame] | 310 | if (newSize.u.LowPart > This->streamSize.u.LowPart) |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 311 | { |
| 312 | /* grow stream */ |
Robert Shearman | dfa74b9 | 2006-01-03 12:07:49 +0100 | [diff] [blame] | 313 | HRESULT hr = IStream_SetSize(iface, newSize); |
| 314 | if (FAILED(hr)) |
| 315 | { |
Michael Stefaniuc | 21ff87b | 2006-10-15 12:28:08 +0200 | [diff] [blame] | 316 | ERR("IStream_SetSize failed with error 0x%08x\n", hr); |
Robert Shearman | dfa74b9 | 2006-01-03 12:07:49 +0100 | [diff] [blame] | 317 | return hr; |
| 318 | } |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 319 | } |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 320 | |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 321 | /* |
| 322 | * Lock the buffer in position and copy the data. |
| 323 | */ |
| 324 | supportBuffer = GlobalLock(This->supportHandle); |
Rob Shearman | 82cfed9 | 2007-05-17 17:06:56 +0100 | [diff] [blame] | 325 | if (!supportBuffer) |
| 326 | { |
| 327 | WARN("write to invalid hglobal %p\n", This->supportHandle); |
| 328 | return S_OK; |
| 329 | } |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 330 | |
Ge van Geldorp | 399901e | 2004-01-23 01:51:33 +0000 | [diff] [blame] | 331 | memcpy((char *) supportBuffer+This->currentPosition.u.LowPart, pv, cb); |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 332 | |
| 333 | /* |
| 334 | * Move the current position to the new position |
| 335 | */ |
Ge van Geldorp | 399901e | 2004-01-23 01:51:33 +0000 | [diff] [blame] | 336 | This->currentPosition.u.LowPart+=cb; |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 337 | |
| 338 | /* |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 339 | * Cleanup |
| 340 | */ |
| 341 | GlobalUnlock(This->supportHandle); |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 342 | |
Mike McCormack | 8dc5bd8 | 2006-08-14 14:06:53 +0900 | [diff] [blame] | 343 | out: |
| 344 | /* |
| 345 | * Return the number of bytes read. |
| 346 | */ |
| 347 | *pcbWritten = cb; |
| 348 | |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 349 | return S_OK; |
| 350 | } |
| 351 | |
| 352 | /*** |
| 353 | * This method is part of the IStream interface. |
| 354 | * |
| 355 | * It will move the current stream pointer according to the parameters |
| 356 | * given. |
| 357 | * |
| 358 | * See the documentation of IStream for more info. |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 359 | */ |
Marcus Meissner | 45bc1c2 | 2005-05-16 08:47:14 +0000 | [diff] [blame] | 360 | static HRESULT WINAPI HGLOBALStreamImpl_Seek( |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 361 | IStream* iface, |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 362 | LARGE_INTEGER dlibMove, /* [in] */ |
| 363 | DWORD dwOrigin, /* [in] */ |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 364 | ULARGE_INTEGER* plibNewPosition) /* [out] */ |
| 365 | { |
| 366 | HGLOBALStreamImpl* const This=(HGLOBALStreamImpl*)iface; |
| 367 | |
Reece Dunn | f08206b | 2010-02-25 09:14:37 +0000 | [diff] [blame] | 368 | ULARGE_INTEGER newPosition = This->currentPosition; |
| 369 | HRESULT hr = S_OK; |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 370 | |
Michael Stefaniuc | 21ff87b | 2006-10-15 12:28:08 +0200 | [diff] [blame] | 371 | TRACE("(%p, %x%08x, %d, %p)\n", iface, dlibMove.u.HighPart, |
Ge van Geldorp | 399901e | 2004-01-23 01:51:33 +0000 | [diff] [blame] | 372 | dlibMove.u.LowPart, dwOrigin, plibNewPosition); |
Francis Beaudet | ec2edc7 | 1999-05-02 11:41:10 +0000 | [diff] [blame] | 373 | |
Reece Dunn | f08206b | 2010-02-25 09:14:37 +0000 | [diff] [blame] | 374 | if (dlibMove.u.LowPart >= 0x80000000) |
| 375 | { |
| 376 | hr = STG_E_SEEKERROR; |
| 377 | goto end; |
| 378 | } |
| 379 | |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 380 | /* |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 381 | * The file pointer is moved depending on the given "function" |
| 382 | * parameter. |
| 383 | */ |
| 384 | switch (dwOrigin) |
| 385 | { |
| 386 | case STREAM_SEEK_SET: |
Ge van Geldorp | 399901e | 2004-01-23 01:51:33 +0000 | [diff] [blame] | 387 | newPosition.u.HighPart = 0; |
| 388 | newPosition.u.LowPart = 0; |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 389 | break; |
| 390 | case STREAM_SEEK_CUR: |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 391 | break; |
| 392 | case STREAM_SEEK_END: |
Juergen Schmied | 3381737 | 2002-07-01 18:10:34 +0000 | [diff] [blame] | 393 | newPosition = This->streamSize; |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 394 | break; |
| 395 | default: |
Reece Dunn | f08206b | 2010-02-25 09:14:37 +0000 | [diff] [blame] | 396 | hr = STG_E_SEEKERROR; |
| 397 | goto end; |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 398 | } |
| 399 | |
| 400 | /* |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 401 | * Move the actual file pointer |
| 402 | * If the file pointer ends-up after the end of the stream, the next Write operation will |
| 403 | * make the file larger. This is how it is documented. |
| 404 | */ |
Reece Dunn | f08206b | 2010-02-25 09:14:37 +0000 | [diff] [blame] | 405 | newPosition.u.HighPart = 0; |
| 406 | newPosition.u.LowPart += dlibMove.QuadPart; |
Robert Shearman | 398a595 | 2004-12-14 11:35:12 +0000 | [diff] [blame] | 407 | |
Reece Dunn | f08206b | 2010-02-25 09:14:37 +0000 | [diff] [blame] | 408 | end: |
Juergen Schmied | 3381737 | 2002-07-01 18:10:34 +0000 | [diff] [blame] | 409 | if (plibNewPosition) *plibNewPosition = newPosition; |
| 410 | This->currentPosition = newPosition; |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 411 | |
Reece Dunn | f08206b | 2010-02-25 09:14:37 +0000 | [diff] [blame] | 412 | return hr; |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 413 | } |
| 414 | |
| 415 | /*** |
| 416 | * This method is part of the IStream interface. |
| 417 | * |
| 418 | * It will change the size of a stream. |
| 419 | * |
| 420 | * TODO: Switch from small blocks to big blocks and vice versa. |
| 421 | * |
| 422 | * See the documentation of IStream for more info. |
| 423 | */ |
Marcus Meissner | 45bc1c2 | 2005-05-16 08:47:14 +0000 | [diff] [blame] | 424 | static HRESULT WINAPI HGLOBALStreamImpl_SetSize( |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 425 | IStream* iface, |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 426 | ULARGE_INTEGER libNewSize) /* [in] */ |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 427 | { |
| 428 | HGLOBALStreamImpl* const This=(HGLOBALStreamImpl*)iface; |
Dimitrie O. Paun | a1cee57 | 2003-11-26 03:36:18 +0000 | [diff] [blame] | 429 | HGLOBAL supportHandle; |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 430 | |
Michael Stefaniuc | 21ff87b | 2006-10-15 12:28:08 +0200 | [diff] [blame] | 431 | TRACE("(%p, %d)\n", iface, libNewSize.u.LowPart); |
Francis Beaudet | ec2edc7 | 1999-05-02 11:41:10 +0000 | [diff] [blame] | 432 | |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 433 | /* |
Robert Shearman | bfc1bdc | 2006-09-11 11:13:34 +0100 | [diff] [blame] | 434 | * HighPart is ignored as shown in tests |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 435 | */ |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 436 | |
Ge van Geldorp | 399901e | 2004-01-23 01:51:33 +0000 | [diff] [blame] | 437 | if (This->streamSize.u.LowPart == libNewSize.u.LowPart) |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 438 | return S_OK; |
| 439 | |
| 440 | /* |
| 441 | * Re allocate the HGlobal to fit the new size of the stream. |
| 442 | */ |
Ge van Geldorp | 399901e | 2004-01-23 01:51:33 +0000 | [diff] [blame] | 443 | supportHandle = GlobalReAlloc(This->supportHandle, libNewSize.u.LowPart, 0); |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 444 | |
Dimitrie O. Paun | a1cee57 | 2003-11-26 03:36:18 +0000 | [diff] [blame] | 445 | if (supportHandle == 0) |
Rob Shearman | fb883d8 | 2006-12-17 23:48:25 +0000 | [diff] [blame] | 446 | return E_OUTOFMEMORY; |
Dimitrie O. Paun | a1cee57 | 2003-11-26 03:36:18 +0000 | [diff] [blame] | 447 | |
| 448 | This->supportHandle = supportHandle; |
Ge van Geldorp | 399901e | 2004-01-23 01:51:33 +0000 | [diff] [blame] | 449 | This->streamSize.u.LowPart = libNewSize.u.LowPart; |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 450 | |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 451 | return S_OK; |
| 452 | } |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 453 | |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 454 | /*** |
| 455 | * This method is part of the IStream interface. |
| 456 | * |
| 457 | * It will copy the 'cb' Bytes to 'pstm' IStream. |
| 458 | * |
| 459 | * See the documentation of IStream for more info. |
| 460 | */ |
Marcus Meissner | 45bc1c2 | 2005-05-16 08:47:14 +0000 | [diff] [blame] | 461 | static HRESULT WINAPI HGLOBALStreamImpl_CopyTo( |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 462 | IStream* iface, |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 463 | IStream* pstm, /* [unique][in] */ |
| 464 | ULARGE_INTEGER cb, /* [in] */ |
| 465 | ULARGE_INTEGER* pcbRead, /* [out] */ |
| 466 | ULARGE_INTEGER* pcbWritten) /* [out] */ |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 467 | { |
| 468 | HRESULT hr = S_OK; |
| 469 | BYTE tmpBuffer[128]; |
| 470 | ULONG bytesRead, bytesWritten, copySize; |
| 471 | ULARGE_INTEGER totalBytesRead; |
| 472 | ULARGE_INTEGER totalBytesWritten; |
| 473 | |
Michael Stefaniuc | 21ff87b | 2006-10-15 12:28:08 +0200 | [diff] [blame] | 474 | TRACE("(%p, %p, %d, %p, %p)\n", iface, pstm, |
Ge van Geldorp | 399901e | 2004-01-23 01:51:33 +0000 | [diff] [blame] | 475 | cb.u.LowPart, pcbRead, pcbWritten); |
Francis Beaudet | ec2edc7 | 1999-05-02 11:41:10 +0000 | [diff] [blame] | 476 | |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 477 | if ( pstm == 0 ) |
| 478 | return STG_E_INVALIDPOINTER; |
| 479 | |
Huw Davies | 0aedac3 | 2008-03-06 12:05:52 +0000 | [diff] [blame] | 480 | totalBytesRead.QuadPart = 0; |
| 481 | totalBytesWritten.QuadPart = 0; |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 482 | |
Huw Davies | 0aedac3 | 2008-03-06 12:05:52 +0000 | [diff] [blame] | 483 | while ( cb.QuadPart > 0 ) |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 484 | { |
Huw Davies | 0aedac3 | 2008-03-06 12:05:52 +0000 | [diff] [blame] | 485 | if ( cb.QuadPart >= sizeof(tmpBuffer) ) |
| 486 | copySize = sizeof(tmpBuffer); |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 487 | else |
Ge van Geldorp | 399901e | 2004-01-23 01:51:33 +0000 | [diff] [blame] | 488 | copySize = cb.u.LowPart; |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 489 | |
Rob Shearman | fd07191 | 2007-01-09 17:16:07 +0000 | [diff] [blame] | 490 | hr = IStream_Read(iface, tmpBuffer, copySize, &bytesRead); |
| 491 | if (FAILED(hr)) |
| 492 | break; |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 493 | |
Huw Davies | 0aedac3 | 2008-03-06 12:05:52 +0000 | [diff] [blame] | 494 | totalBytesRead.QuadPart += bytesRead; |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 495 | |
Rob Shearman | fd07191 | 2007-01-09 17:16:07 +0000 | [diff] [blame] | 496 | if (bytesRead) |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 497 | { |
Rob Shearman | fd07191 | 2007-01-09 17:16:07 +0000 | [diff] [blame] | 498 | hr = IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten); |
| 499 | if (FAILED(hr)) |
| 500 | break; |
| 501 | |
Huw Davies | 0aedac3 | 2008-03-06 12:05:52 +0000 | [diff] [blame] | 502 | totalBytesWritten.QuadPart += bytesWritten; |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 503 | } |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 504 | |
Francis Beaudet | ec2edc7 | 1999-05-02 11:41:10 +0000 | [diff] [blame] | 505 | if (bytesRead!=copySize) |
Huw Davies | 0aedac3 | 2008-03-06 12:05:52 +0000 | [diff] [blame] | 506 | cb.QuadPart = 0; |
Francis Beaudet | ec2edc7 | 1999-05-02 11:41:10 +0000 | [diff] [blame] | 507 | else |
Huw Davies | 0aedac3 | 2008-03-06 12:05:52 +0000 | [diff] [blame] | 508 | cb.QuadPart -= bytesRead; |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 509 | } |
| 510 | |
Huw Davies | 0aedac3 | 2008-03-06 12:05:52 +0000 | [diff] [blame] | 511 | if (pcbRead) pcbRead->QuadPart = totalBytesRead.QuadPart; |
| 512 | if (pcbWritten) pcbWritten->QuadPart = totalBytesWritten.QuadPart; |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 513 | |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 514 | return hr; |
| 515 | } |
| 516 | |
| 517 | /*** |
| 518 | * This method is part of the IStream interface. |
| 519 | * |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 520 | * For streams supported by HGLOBALS, this function does nothing. |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 521 | * This is what the documentation tells us. |
| 522 | * |
| 523 | * See the documentation of IStream for more info. |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 524 | */ |
Marcus Meissner | 45bc1c2 | 2005-05-16 08:47:14 +0000 | [diff] [blame] | 525 | static HRESULT WINAPI HGLOBALStreamImpl_Commit( |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 526 | IStream* iface, |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 527 | DWORD grfCommitFlags) /* [in] */ |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 528 | { |
| 529 | return S_OK; |
| 530 | } |
| 531 | |
| 532 | /*** |
| 533 | * This method is part of the IStream interface. |
| 534 | * |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 535 | * For streams supported by HGLOBALS, this function does nothing. |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 536 | * This is what the documentation tells us. |
| 537 | * |
| 538 | * See the documentation of IStream for more info. |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 539 | */ |
Marcus Meissner | 45bc1c2 | 2005-05-16 08:47:14 +0000 | [diff] [blame] | 540 | static HRESULT WINAPI HGLOBALStreamImpl_Revert( |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 541 | IStream* iface) |
| 542 | { |
| 543 | return S_OK; |
| 544 | } |
| 545 | |
| 546 | /*** |
| 547 | * This method is part of the IStream interface. |
| 548 | * |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 549 | * For streams supported by HGLOBALS, this function does nothing. |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 550 | * This is what the documentation tells us. |
| 551 | * |
| 552 | * See the documentation of IStream for more info. |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 553 | */ |
Marcus Meissner | 45bc1c2 | 2005-05-16 08:47:14 +0000 | [diff] [blame] | 554 | static HRESULT WINAPI HGLOBALStreamImpl_LockRegion( |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 555 | IStream* iface, |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 556 | ULARGE_INTEGER libOffset, /* [in] */ |
| 557 | ULARGE_INTEGER cb, /* [in] */ |
| 558 | DWORD dwLockType) /* [in] */ |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 559 | { |
Robert Shearman | 355903d | 2006-09-11 11:12:32 +0100 | [diff] [blame] | 560 | return STG_E_INVALIDFUNCTION; |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 561 | } |
| 562 | |
| 563 | /* |
| 564 | * This method is part of the IStream interface. |
| 565 | * |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 566 | * For streams supported by HGLOBALS, this function does nothing. |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 567 | * This is what the documentation tells us. |
| 568 | * |
| 569 | * See the documentation of IStream for more info. |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 570 | */ |
Marcus Meissner | 45bc1c2 | 2005-05-16 08:47:14 +0000 | [diff] [blame] | 571 | static HRESULT WINAPI HGLOBALStreamImpl_UnlockRegion( |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 572 | IStream* iface, |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 573 | ULARGE_INTEGER libOffset, /* [in] */ |
| 574 | ULARGE_INTEGER cb, /* [in] */ |
| 575 | DWORD dwLockType) /* [in] */ |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 576 | { |
| 577 | return S_OK; |
| 578 | } |
| 579 | |
| 580 | /*** |
| 581 | * This method is part of the IStream interface. |
| 582 | * |
| 583 | * This method returns information about the current |
| 584 | * stream. |
| 585 | * |
| 586 | * See the documentation of IStream for more info. |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 587 | */ |
Marcus Meissner | 45bc1c2 | 2005-05-16 08:47:14 +0000 | [diff] [blame] | 588 | static HRESULT WINAPI HGLOBALStreamImpl_Stat( |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 589 | IStream* iface, |
| 590 | STATSTG* pstatstg, /* [out] */ |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 591 | DWORD grfStatFlag) /* [in] */ |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 592 | { |
| 593 | HGLOBALStreamImpl* const This=(HGLOBALStreamImpl*)iface; |
| 594 | |
| 595 | memset(pstatstg, 0, sizeof(STATSTG)); |
| 596 | |
| 597 | pstatstg->pwcsName = NULL; |
| 598 | pstatstg->type = STGTY_STREAM; |
| 599 | pstatstg->cbSize = This->streamSize; |
| 600 | |
| 601 | return S_OK; |
| 602 | } |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 603 | |
Marcus Meissner | 45bc1c2 | 2005-05-16 08:47:14 +0000 | [diff] [blame] | 604 | static HRESULT WINAPI HGLOBALStreamImpl_Clone( |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 605 | IStream* iface, |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 606 | IStream** ppstm) /* [out] */ |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 607 | { |
Alberto Massari | 544efc8 | 2002-11-12 02:13:49 +0000 | [diff] [blame] | 608 | ULARGE_INTEGER dummy; |
| 609 | LARGE_INTEGER offset; |
| 610 | HRESULT hr; |
| 611 | HGLOBALStreamImpl* const This=(HGLOBALStreamImpl*)iface; |
| 612 | TRACE(" Cloning %p (deleteOnRelease=%d seek position=%ld)\n",iface,This->deleteOnRelease,(long)This->currentPosition.QuadPart); |
| 613 | hr=CreateStreamOnHGlobal(This->supportHandle, FALSE, ppstm); |
| 614 | if(FAILED(hr)) |
| 615 | return hr; |
| 616 | offset.QuadPart=(LONGLONG)This->currentPosition.QuadPart; |
| 617 | HGLOBALStreamImpl_Seek(*ppstm,offset,STREAM_SEEK_SET,&dummy); |
| 618 | return S_OK; |
Francis Beaudet | 4f8b5a8 | 1999-04-24 12:00:31 +0000 | [diff] [blame] | 619 | } |
Marcus Meissner | 45bc1c2 | 2005-05-16 08:47:14 +0000 | [diff] [blame] | 620 | |
| 621 | /* |
| 622 | * Virtual function table for the HGLOBALStreamImpl class. |
| 623 | */ |
Dmitry Timoshkov | eba47f1 | 2005-06-06 19:50:35 +0000 | [diff] [blame] | 624 | static const IStreamVtbl HGLOBALStreamImpl_Vtbl = |
Marcus Meissner | 45bc1c2 | 2005-05-16 08:47:14 +0000 | [diff] [blame] | 625 | { |
| 626 | HGLOBALStreamImpl_QueryInterface, |
| 627 | HGLOBALStreamImpl_AddRef, |
| 628 | HGLOBALStreamImpl_Release, |
| 629 | HGLOBALStreamImpl_Read, |
| 630 | HGLOBALStreamImpl_Write, |
| 631 | HGLOBALStreamImpl_Seek, |
| 632 | HGLOBALStreamImpl_SetSize, |
| 633 | HGLOBALStreamImpl_CopyTo, |
| 634 | HGLOBALStreamImpl_Commit, |
| 635 | HGLOBALStreamImpl_Revert, |
| 636 | HGLOBALStreamImpl_LockRegion, |
| 637 | HGLOBALStreamImpl_UnlockRegion, |
| 638 | HGLOBALStreamImpl_Stat, |
| 639 | HGLOBALStreamImpl_Clone |
| 640 | }; |
| 641 | |
| 642 | /****************************************************************************** |
| 643 | ** HGLOBALStreamImpl implementation |
| 644 | */ |
| 645 | |
| 646 | /*** |
| 647 | * This is the constructor for the HGLOBALStreamImpl class. |
| 648 | * |
| 649 | * Params: |
| 650 | * hGlobal - Handle that will support the stream. can be NULL. |
| 651 | * fDeleteOnRelease - Flag set to TRUE if the HGLOBAL will be released |
| 652 | * when the IStream object is destroyed. |
| 653 | */ |
Andrew Talbot | 02a5f73 | 2007-01-18 21:50:56 +0000 | [diff] [blame] | 654 | static HGLOBALStreamImpl* HGLOBALStreamImpl_Construct( |
Marcus Meissner | 45bc1c2 | 2005-05-16 08:47:14 +0000 | [diff] [blame] | 655 | HGLOBAL hGlobal, |
| 656 | BOOL fDeleteOnRelease) |
| 657 | { |
| 658 | HGLOBALStreamImpl* newStream; |
| 659 | |
| 660 | newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(HGLOBALStreamImpl)); |
| 661 | |
| 662 | if (newStream!=0) |
| 663 | { |
| 664 | /* |
| 665 | * Set-up the virtual function table and reference count. |
| 666 | */ |
| 667 | newStream->lpVtbl = &HGLOBALStreamImpl_Vtbl; |
| 668 | newStream->ref = 0; |
| 669 | |
| 670 | /* |
| 671 | * Initialize the support. |
| 672 | */ |
| 673 | newStream->supportHandle = hGlobal; |
| 674 | newStream->deleteOnRelease = fDeleteOnRelease; |
| 675 | |
| 676 | /* |
| 677 | * This method will allocate a handle if one is not supplied. |
| 678 | */ |
| 679 | if (!newStream->supportHandle) |
| 680 | { |
| 681 | newStream->supportHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD | |
| 682 | GMEM_SHARE, 0); |
| 683 | } |
| 684 | |
| 685 | /* |
| 686 | * Start the stream at the beginning. |
| 687 | */ |
| 688 | newStream->currentPosition.u.HighPart = 0; |
| 689 | newStream->currentPosition.u.LowPart = 0; |
| 690 | |
| 691 | /* |
| 692 | * Initialize the size of the stream to the size of the handle. |
| 693 | */ |
| 694 | newStream->streamSize.u.HighPart = 0; |
| 695 | newStream->streamSize.u.LowPart = GlobalSize(newStream->supportHandle); |
| 696 | } |
| 697 | |
| 698 | return newStream; |
| 699 | } |
| 700 | |
| 701 | |
| 702 | /*********************************************************************** |
| 703 | * CreateStreamOnHGlobal [OLE32.@] |
| 704 | */ |
| 705 | HRESULT WINAPI CreateStreamOnHGlobal( |
| 706 | HGLOBAL hGlobal, |
| 707 | BOOL fDeleteOnRelease, |
| 708 | LPSTREAM* ppstm) |
| 709 | { |
| 710 | HGLOBALStreamImpl* newStream; |
| 711 | |
Rob Shearman | 4edca3c | 2007-11-12 20:10:32 +0000 | [diff] [blame] | 712 | if (!ppstm) |
| 713 | return E_INVALIDARG; |
| 714 | |
Marcus Meissner | 45bc1c2 | 2005-05-16 08:47:14 +0000 | [diff] [blame] | 715 | newStream = HGLOBALStreamImpl_Construct(hGlobal, |
| 716 | fDeleteOnRelease); |
| 717 | |
| 718 | if (newStream!=NULL) |
| 719 | { |
| 720 | return IUnknown_QueryInterface((IUnknown*)newStream, |
| 721 | &IID_IStream, |
| 722 | (void**)ppstm); |
| 723 | } |
| 724 | |
| 725 | return E_OUTOFMEMORY; |
| 726 | } |
| 727 | |
| 728 | /*********************************************************************** |
| 729 | * GetHGlobalFromStream [OLE32.@] |
| 730 | */ |
| 731 | HRESULT WINAPI GetHGlobalFromStream(IStream* pstm, HGLOBAL* phglobal) |
| 732 | { |
| 733 | HGLOBALStreamImpl* pStream; |
| 734 | |
| 735 | if (pstm == NULL) |
| 736 | return E_INVALIDARG; |
| 737 | |
| 738 | pStream = (HGLOBALStreamImpl*) pstm; |
| 739 | |
| 740 | /* |
| 741 | * Verify that the stream object was created with CreateStreamOnHGlobal. |
| 742 | */ |
| 743 | if (pStream->lpVtbl == &HGLOBALStreamImpl_Vtbl) |
| 744 | *phglobal = pStream->supportHandle; |
| 745 | else |
| 746 | { |
| 747 | *phglobal = 0; |
| 748 | return E_INVALIDARG; |
| 749 | } |
| 750 | |
| 751 | return S_OK; |
| 752 | } |