1 /******************************************************************************
3 * Global memory implementation of ILockBytes.
5 * Copyright 1999 Thuy Nguyen
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "wine/winbase16.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(ole);
40 /******************************************************************************
41 * HGLOBALLockBytesImpl definition.
43 * This class imlements the ILockBytes inteface and represents a byte array
44 * object supported by an HGLOBAL pointer.
46 struct HGLOBALLockBytesImpl
49 * Needs to be the first item in the stuct
50 * since we want to cast this in an ILockBytes pointer
52 ICOM_VFIELD(ILockBytes);
60 * Support for the LockBytes object
62 HGLOBAL supportHandle;
65 * This flag is TRUE if the HGLOBAL is destroyed when the object
66 * is finally released.
71 * Helper variable that contains the size of the byte array
73 ULARGE_INTEGER byteArraySize;
76 typedef struct HGLOBALLockBytesImpl HGLOBALLockBytesImpl;
79 * Method definition for the HGLOBALLockBytesImpl class.
81 HGLOBALLockBytesImpl* HGLOBALLockBytesImpl_Construct(
83 BOOL fDeleteOnRelease);
85 void HGLOBALLockBytesImpl_Destroy(HGLOBALLockBytesImpl* This);
87 HRESULT WINAPI HGLOBALLockBytesImpl_QueryInterface(
89 REFIID riid, /* [in] */
90 void** ppvObject); /* [iid_is][out] */
92 ULONG WINAPI HGLOBALLockBytesImpl_AddRef(
95 ULONG WINAPI HGLOBALLockBytesImpl_Release(
98 HRESULT WINAPI HGLOBALLockBytesImpl_ReadAt(
100 ULARGE_INTEGER ulOffset, /* [in] */
101 void* pv, /* [length_is][size_is][out] */
103 ULONG* pcbRead); /* [out] */
105 HRESULT WINAPI HGLOBALLockBytesImpl_WriteAt(
107 ULARGE_INTEGER ulOffset, /* [in] */
108 const void* pv, /* [size_is][in] */
110 ULONG* pcbWritten); /* [out] */
112 HRESULT WINAPI HGLOBALLockBytesImpl_Flush(
115 HRESULT WINAPI HGLOBALLockBytesImpl_SetSize(
117 ULARGE_INTEGER libNewSize); /* [in] */
119 HRESULT WINAPI HGLOBALLockBytesImpl_LockRegion(
121 ULARGE_INTEGER libOffset, /* [in] */
122 ULARGE_INTEGER cb, /* [in] */
123 DWORD dwLockType); /* [in] */
125 HRESULT WINAPI HGLOBALLockBytesImpl_UnlockRegion(
127 ULARGE_INTEGER libOffset, /* [in] */
128 ULARGE_INTEGER cb, /* [in] */
129 DWORD dwLockType); /* [in] */
131 HRESULT WINAPI HGLOBALLockBytesImpl_Stat(
133 STATSTG* pstatstg, /* [out] */
134 DWORD grfStatFlag); /* [in] */
137 * Virtual function table for the HGLOBALLockBytesImpl class.
139 static ICOM_VTABLE(ILockBytes) HGLOBALLockBytesImpl_Vtbl =
141 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
142 HGLOBALLockBytesImpl_QueryInterface,
143 HGLOBALLockBytesImpl_AddRef,
144 HGLOBALLockBytesImpl_Release,
145 HGLOBALLockBytesImpl_ReadAt,
146 HGLOBALLockBytesImpl_WriteAt,
147 HGLOBALLockBytesImpl_Flush,
148 HGLOBALLockBytesImpl_SetSize,
149 HGLOBALLockBytesImpl_LockRegion,
150 HGLOBALLockBytesImpl_UnlockRegion,
151 HGLOBALLockBytesImpl_Stat,
154 /******************************************************************************
155 * CreateILockBytesOnHGlobal [OLE32.57]
157 HRESULT WINAPI CreateILockBytesOnHGlobal(HGLOBAL hGlobal,
158 BOOL fDeleteOnRelease,
159 LPLOCKBYTES* ppLkbyt)
161 HGLOBALLockBytesImpl* newLockBytes;
163 newLockBytes = HGLOBALLockBytesImpl_Construct(hGlobal, fDeleteOnRelease);
165 if (newLockBytes != NULL)
167 return IUnknown_QueryInterface((IUnknown*)newLockBytes,
172 return E_OUTOFMEMORY;
175 /******************************************************************************
176 * GetHGlobalFromILockBytes [OLE32.70]
178 HRESULT WINAPI GetHGlobalFromILockBytes(ILockBytes* plkbyt, HGLOBAL* phglobal)
180 HGLOBALLockBytesImpl* const pMemLockBytes = (HGLOBALLockBytesImpl*)plkbyt;
183 ULARGE_INTEGER start;
187 if (ICOM_VTBL(pMemLockBytes) == &HGLOBALLockBytesImpl_Vtbl) {
188 *phglobal = pMemLockBytes->supportHandle;
193 /* It is not our lockbytes implementation, so use a more generic way */
194 hres = ILockBytes_Stat(plkbyt,&stbuf,0);
196 ERR("Cannot ILockBytes_Stat, %lx\n",hres);
199 FIXME("cbSize is %ld\n",stbuf.cbSize.s.LowPart);
200 *phglobal = GlobalAlloc( GMEM_MOVEABLE|GMEM_SHARE, stbuf.cbSize.s.LowPart);
203 memset(&start,0,sizeof(start));
204 hres = ILockBytes_ReadAt(plkbyt, start, GlobalLock(*phglobal), stbuf.cbSize.s.LowPart, &xread);
205 GlobalUnlock(*phglobal);
207 FIXME("%p->ReadAt failed with %lx\n",plkbyt,hres);
210 if (stbuf.cbSize.s.LowPart != xread) {
211 FIXME("Read size is not requested size %ld vs %ld?\n",stbuf.cbSize.s.LowPart, xread);
216 /******************************************************************************
218 * HGLOBALLockBytesImpl implementation
222 /******************************************************************************
223 * This is the constructor for the HGLOBALLockBytesImpl class.
226 * hGlobal - Handle that will support the stream. can be NULL.
227 * fDeleteOnRelease - Flag set to TRUE if the HGLOBAL will be released
228 * when the IStream object is destroyed.
230 HGLOBALLockBytesImpl* HGLOBALLockBytesImpl_Construct(HGLOBAL hGlobal,
231 BOOL fDeleteOnRelease)
233 HGLOBALLockBytesImpl* newLockBytes;
234 newLockBytes = HeapAlloc(GetProcessHeap(), 0, sizeof(HGLOBALLockBytesImpl));
239 * Set up the virtual function table and reference count.
241 ICOM_VTBL(newLockBytes) = &HGLOBALLockBytesImpl_Vtbl;
242 newLockBytes->ref = 0;
245 * Initialize the support.
247 newLockBytes->supportHandle = hGlobal;
248 newLockBytes->deleteOnRelease = fDeleteOnRelease;
251 * This method will allocate a handle if one is not supplied.
253 if (newLockBytes->supportHandle == 0)
255 newLockBytes->supportHandle = GlobalAlloc(GMEM_MOVEABLE |
261 * Initialize the size of the array to the size of the handle.
263 newLockBytes->byteArraySize.s.HighPart = 0;
264 newLockBytes->byteArraySize.s.LowPart = GlobalSize(
265 newLockBytes->supportHandle);
271 /******************************************************************************
272 * This is the destructor of the HGLOBALStreamImpl class.
274 * This method will clean-up all the resources used-up by the given
275 * HGLOBALLockBytesImpl class. The pointer passed-in to this function will be
276 * freed and will not be valid anymore.
278 void HGLOBALLockBytesImpl_Destroy(HGLOBALLockBytesImpl* This)
281 * Release the HGlobal if the constructor asked for that.
283 if (This->deleteOnRelease)
285 GlobalFree(This->supportHandle);
286 This->supportHandle = 0;
290 * Finally, free the memory used-up by the class.
292 HeapFree(GetProcessHeap(), 0, This);
295 /******************************************************************************
296 * This implements the IUnknown method QueryInterface for this
299 HRESULT WINAPI HGLOBALLockBytesImpl_QueryInterface(
301 REFIID riid, /* [in] */
302 void** ppvObject) /* [iid_is][out] */
304 HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface;
307 * Perform a sanity check on the parameters.
313 * Initialize the return parameter.
318 * Compare the riid with the interface IDs implemented by this object.
320 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
322 *ppvObject = (ILockBytes*)This;
324 else if (memcmp(&IID_ILockBytes, riid, sizeof(IID_ILockBytes)) == 0)
326 *ppvObject = (ILockBytes*)This;
330 * Check that we obtained an interface.
333 return E_NOINTERFACE;
336 * Query Interface always increases the reference count by one when it is
339 HGLOBALLockBytesImpl_AddRef(iface);
344 /******************************************************************************
345 * This implements the IUnknown method AddRef for this
348 ULONG WINAPI HGLOBALLockBytesImpl_AddRef(ILockBytes* iface)
350 HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface;
357 /******************************************************************************
358 * This implements the IUnknown method Release for this
361 ULONG WINAPI HGLOBALLockBytesImpl_Release(ILockBytes* iface)
363 HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface;
372 * If the reference count goes down to 0, perform suicide.
376 HGLOBALLockBytesImpl_Destroy(This);
382 /******************************************************************************
383 * This method is part of the ILockBytes interface.
385 * It reads a block of information from the byte array at the specified
388 * See the documentation of ILockBytes for more info.
390 HRESULT WINAPI HGLOBALLockBytesImpl_ReadAt(
392 ULARGE_INTEGER ulOffset, /* [in] */
393 void* pv, /* [length_is][size_is][out] */
395 ULONG* pcbRead) /* [out] */
397 HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface;
400 ULONG bytesReadBuffer = 0;
401 ULONG bytesToReadFromBuffer;
404 * If the caller is not interested in the number of bytes read,
405 * we use another buffer to avoid "if" statements in the code.
408 pcbRead = &bytesReadBuffer;
411 * Make sure the offset is valid.
413 if (ulOffset.s.LowPart > This->byteArraySize.s.LowPart)
417 * Using the known size of the array, calculate the number of bytes
420 bytesToReadFromBuffer = min(This->byteArraySize.s.LowPart -
421 ulOffset.s.LowPart, cb);
424 * Lock the buffer in position and copy the data.
426 supportBuffer = GlobalLock(This->supportHandle);
429 (char *) supportBuffer + ulOffset.s.LowPart,
430 bytesToReadFromBuffer);
433 * Return the number of bytes read.
435 *pcbRead = bytesToReadFromBuffer;
440 GlobalUnlock(This->supportHandle);
443 * The function returns S_OK if the specified number of bytes were read
444 * or the end of the array was reached.
445 * It returns STG_E_READFAULT if the number of bytes to read does not equal
446 * the number of bytes actually read.
451 return STG_E_READFAULT;
454 /******************************************************************************
455 * This method is part of the ILockBytes interface.
457 * It writes the specified bytes at the specified offset.
458 * position. If the array is too small, it will be resized.
460 * See the documentation of ILockBytes for more info.
462 HRESULT WINAPI HGLOBALLockBytesImpl_WriteAt(
464 ULARGE_INTEGER ulOffset, /* [in] */
465 const void* pv, /* [size_is][in] */
467 ULONG* pcbWritten) /* [out] */
469 HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface;
472 ULARGE_INTEGER newSize;
473 ULONG bytesWritten = 0;
476 * If the caller is not interested in the number of bytes written,
477 * we use another buffer to avoid "if" statements in the code.
480 pcbWritten = &bytesWritten;
488 newSize.s.HighPart = 0;
489 newSize.s.LowPart = ulOffset.s.LowPart + cb;
493 * Verify if we need to grow the stream
495 if (newSize.s.LowPart > This->byteArraySize.s.LowPart)
498 if (HGLOBALLockBytesImpl_SetSize(iface, newSize) == STG_E_MEDIUMFULL)
499 return STG_E_MEDIUMFULL;
503 * Lock the buffer in position and copy the data.
505 supportBuffer = GlobalLock(This->supportHandle);
507 memcpy((char *) supportBuffer + ulOffset.s.LowPart, pv, cb);
510 * Return the number of bytes written.
517 GlobalUnlock(This->supportHandle);
522 /******************************************************************************
523 * This method is part of the ILockBytes interface.
525 * See the documentation of ILockBytes for more info.
527 HRESULT WINAPI HGLOBALLockBytesImpl_Flush(ILockBytes* iface)
532 /******************************************************************************
533 * This method is part of the ILockBytes interface.
535 * It will change the size of the byte array.
537 * See the documentation of ILockBytes for more info.
539 HRESULT WINAPI HGLOBALLockBytesImpl_SetSize(
541 ULARGE_INTEGER libNewSize) /* [in] */
543 HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface;
548 if (libNewSize.s.HighPart != 0)
549 return STG_E_INVALIDFUNCTION;
551 if (This->byteArraySize.s.LowPart == libNewSize.s.LowPart)
555 * Re allocate the HGlobal to fit the new size of the stream.
557 This->supportHandle = GlobalReAlloc(This->supportHandle,
558 libNewSize.s.LowPart,
561 if (This->supportHandle == 0)
562 return STG_E_MEDIUMFULL;
564 This->byteArraySize.s.LowPart = libNewSize.s.LowPart;
569 /******************************************************************************
570 * This method is part of the ILockBytes interface.
572 * The global memory implementation of ILockBytes does not support locking.
574 * See the documentation of ILockBytes for more info.
576 HRESULT WINAPI HGLOBALLockBytesImpl_LockRegion(
578 ULARGE_INTEGER libOffset, /* [in] */
579 ULARGE_INTEGER cb, /* [in] */
580 DWORD dwLockType) /* [in] */
582 return STG_E_INVALIDFUNCTION;
585 /******************************************************************************
586 * This method is part of the ILockBytes interface.
588 * The global memory implementation of ILockBytes does not support locking.
590 * See the documentation of ILockBytes for more info.
592 HRESULT WINAPI HGLOBALLockBytesImpl_UnlockRegion(
594 ULARGE_INTEGER libOffset, /* [in] */
595 ULARGE_INTEGER cb, /* [in] */
596 DWORD dwLockType) /* [in] */
598 return STG_E_INVALIDFUNCTION;
601 /******************************************************************************
602 * This method is part of the ILockBytes interface.
604 * This method returns information about the current
607 * See the documentation of ILockBytes for more info.
609 HRESULT WINAPI HGLOBALLockBytesImpl_Stat(
611 STATSTG* pstatstg, /* [out] */
612 DWORD grfStatFlag) /* [in] */
614 HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface;
616 memset(pstatstg, 0, sizeof(STATSTG));
618 pstatstg->pwcsName = NULL;
619 pstatstg->type = STGTY_LOCKBYTES;
620 pstatstg->cbSize = This->byteArraySize;
625 /******************************************************************************
626 * HGLOBALLockBytesImpl16 definition.
628 * This class imlements the ILockBytes inteface and represents a byte array
629 * object supported by an HGLOBAL pointer.
631 struct HGLOBALLockBytesImpl16
634 * Needs to be the first item in the stuct
635 * since we want to cast this in an ILockBytes pointer
637 ICOM_VFIELD(ILockBytes16);
641 * Support for the LockBytes object
643 HGLOBAL16 supportHandle;
646 * This flag is TRUE if the HGLOBAL is destroyed when the object
647 * is finally released.
649 BOOL deleteOnRelease;
651 * Helper variable that contains the size of the byte array
653 ULARGE_INTEGER byteArraySize;
656 typedef struct HGLOBALLockBytesImpl16 HGLOBALLockBytesImpl16;
658 HGLOBALLockBytesImpl16* HGLOBALLockBytesImpl16_Construct(
660 BOOL16 fDeleteOnRelease);
662 void HGLOBALLockBytesImpl16_Destroy(HGLOBALLockBytesImpl16* This);
664 HRESULT WINAPI HGLOBALLockBytesImpl16_QueryInterface(
666 REFIID riid, /* [in] */
667 void** ppvObject); /* [iid_is][out] */
669 ULONG WINAPI HGLOBALLockBytesImpl16_AddRef(
670 ILockBytes16* iface);
672 ULONG WINAPI HGLOBALLockBytesImpl16_Release(
673 ILockBytes16* iface);
675 HRESULT WINAPI HGLOBALLockBytesImpl16_ReadAt(
677 ULARGE_INTEGER ulOffset, /* [in] */
678 void* pv, /* [length_is][size_is][out] */
680 ULONG* pcbRead); /* [out] */
682 HRESULT WINAPI HGLOBALLockBytesImpl16_WriteAt(
684 ULARGE_INTEGER ulOffset, /* [in] */
685 const void* pv, /* [size_is][in] */
687 ULONG* pcbWritten); /* [out] */
689 HRESULT WINAPI HGLOBALLockBytesImpl16_Flush(
690 ILockBytes16* iface);
692 HRESULT WINAPI HGLOBALLockBytesImpl16_SetSize(
694 ULARGE_INTEGER libNewSize); /* [in] */
696 HRESULT WINAPI HGLOBALLockBytesImpl16_LockRegion(
698 ULARGE_INTEGER libOffset, /* [in] */
699 ULARGE_INTEGER cb, /* [in] */
700 DWORD dwLockType); /* [in] */
702 HRESULT WINAPI HGLOBALLockBytesImpl16_UnlockRegion(
704 ULARGE_INTEGER libOffset, /* [in] */
705 ULARGE_INTEGER cb, /* [in] */
706 DWORD dwLockType); /* [in] */
708 HRESULT WINAPI HGLOBALLockBytesImpl16_Stat(
710 STATSTG16* pstatstg, /* [out] */
711 DWORD grfStatFlag); /* [in] */
713 /******************************************************************************
715 * HGLOBALLockBytesImpl16 implementation
719 /******************************************************************************
720 * This is the constructor for the HGLOBALLockBytesImpl16 class.
723 * hGlobal - Handle that will support the stream. can be NULL.
724 * fDeleteOnRelease - Flag set to TRUE if the HGLOBAL16 will be released
725 * when the IStream object is destroyed.
727 HGLOBALLockBytesImpl16*
728 HGLOBALLockBytesImpl16_Construct(HGLOBAL16 hGlobal,
729 BOOL16 fDeleteOnRelease)
731 HGLOBALLockBytesImpl16* newLockBytes;
733 static ICOM_VTABLE(ILockBytes16) vt16;
734 static SEGPTR msegvt16;
735 HMODULE16 hcomp = GetModuleHandle16("OLE2");
738 TRACE("(%x,%d)\n",hGlobal,fDeleteOnRelease);
739 newLockBytes = HeapAlloc(GetProcessHeap(), 0, sizeof(HGLOBALLockBytesImpl16));
740 if (newLockBytes == NULL)
744 * Set up the virtual function table and reference count.
748 #define VTENT(x) vt16.x = (void*)GetProcAddress16(hcomp,"HGLOBALLockBytesImpl16_"#x);assert(vt16.x)
749 VTENT(QueryInterface);
759 msegvt16 = MapLS( &vt16 );
761 ICOM_VTBL(newLockBytes) = (ICOM_VTABLE(ILockBytes16)*)msegvt16;
762 newLockBytes->ref = 0;
764 * Initialize the support.
766 newLockBytes->supportHandle = hGlobal;
767 newLockBytes->deleteOnRelease = fDeleteOnRelease;
770 * This method will allocate a handle if one is not supplied.
772 if (newLockBytes->supportHandle == 0)
773 newLockBytes->supportHandle = GlobalAlloc16(GMEM_MOVEABLE | GMEM_NODISCARD, 0);
776 * Initialize the size of the array to the size of the handle.
778 newLockBytes->byteArraySize.s.HighPart = 0;
779 newLockBytes->byteArraySize.s.LowPart = GlobalSize16(
780 newLockBytes->supportHandle);
782 return (HGLOBALLockBytesImpl16*)MapLS(newLockBytes);
785 /******************************************************************************
786 * This is the destructor of the HGLOBALStreamImpl class.
788 * This method will clean-up all the resources used-up by the given
789 * HGLOBALLockBytesImpl16 class. The pointer passed-in to this function will be
790 * freed and will not be valid anymore.
792 void HGLOBALLockBytesImpl16_Destroy(HGLOBALLockBytesImpl16* This)
796 * Release the HGlobal if the constructor asked for that.
798 if (This->deleteOnRelease)
800 GlobalFree16(This->supportHandle);
801 This->supportHandle = 0;
805 * Finally, free the memory used-up by the class.
807 HeapFree(GetProcessHeap(), 0, This);
810 /******************************************************************************
811 * This implements the IUnknown method QueryInterface for this
814 HRESULT WINAPI HGLOBALLockBytesImpl16_QueryInterface(
815 ILockBytes16* iface, /* [in] SEGPTR */
816 REFIID riid, /* [in] */
817 void** ppvObject) /* [iid_is][out] (ptr to SEGPTR!) */
819 HGLOBALLockBytesImpl16* const This=(HGLOBALLockBytesImpl16*)MapSL((SEGPTR)iface);
821 TRACE("(%p,%s,%p)\n",iface,debugstr_guid(riid),ppvObject);
823 * Perform a sanity check on the parameters.
829 * Initialize the return parameter.
833 * Compare the riid with the interface IDs implemented by this object.
835 if ( !memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) ||
836 !memcmp(&IID_ILockBytes, riid, sizeof(IID_ILockBytes))
838 *ppvObject = (void*)iface;
841 * Check that we obtained an interface.
844 return E_NOINTERFACE;
847 * Query Interface always increases the reference count by one when it is
850 HGLOBALLockBytesImpl16_AddRef((ILockBytes16*)This);
855 /******************************************************************************
856 * This implements the IUnknown method AddRef for this
859 ULONG WINAPI HGLOBALLockBytesImpl16_AddRef(ILockBytes16* iface)
861 HGLOBALLockBytesImpl16* const This=(HGLOBALLockBytesImpl16*)iface;
863 TRACE("(%p)\n",This);
870 /******************************************************************************
871 * This implements the IUnknown method Release for this
874 ULONG WINAPI HGLOBALLockBytesImpl16_Release(ILockBytes16* iface)
876 HGLOBALLockBytesImpl16* const This=(HGLOBALLockBytesImpl16*)iface;
879 TRACE("(%p)\n",This);
886 * If the reference count goes down to 0, perform suicide.
889 HGLOBALLockBytesImpl16_Destroy(This);
893 /******************************************************************************
894 * This method is part of the ILockBytes interface.
896 * It reads a block of information from the byte array at the specified
899 * See the documentation of ILockBytes for more info.
901 HRESULT WINAPI HGLOBALLockBytesImpl16_ReadAt(
903 ULARGE_INTEGER ulOffset, /* [in] */
904 void* pv, /* [length_is][size_is][out] */
906 ULONG* pcbRead) /* [out] */
908 HGLOBALLockBytesImpl16* const This=(HGLOBALLockBytesImpl16*)iface;
911 ULONG bytesReadBuffer = 0;
912 ULONG bytesToReadFromBuffer;
914 TRACE("(%p,%ld,%p,%ld,%p)\n",This,ulOffset.s.LowPart,pv,cb,pcbRead);
916 * If the caller is not interested in the number of bytes read,
917 * we use another buffer to avoid "if" statements in the code.
920 pcbRead = &bytesReadBuffer;
923 * Make sure the offset is valid.
925 if (ulOffset.s.LowPart > This->byteArraySize.s.LowPart)
929 * Using the known size of the array, calculate the number of bytes
932 bytesToReadFromBuffer = min(This->byteArraySize.s.LowPart -
933 ulOffset.s.LowPart, cb);
936 * Lock the buffer in position and copy the data.
938 supportBuffer = GlobalLock16(This->supportHandle);
941 (char *) supportBuffer + ulOffset.s.LowPart,
942 bytesToReadFromBuffer);
945 * Return the number of bytes read.
947 *pcbRead = bytesToReadFromBuffer;
952 GlobalUnlock16(This->supportHandle);
955 * The function returns S_OK if the specified number of bytes were read
956 * or the end of the array was reached.
957 * It returns STG_E_READFAULT if the number of bytes to read does not equal
958 * the number of bytes actually read.
963 return STG_E_READFAULT;
966 /******************************************************************************
967 * This method is part of the ILockBytes interface.
969 * It writes the specified bytes at the specified offset.
970 * position. If the array is too small, it will be resized.
972 * See the documentation of ILockBytes for more info.
974 HRESULT WINAPI HGLOBALLockBytesImpl16_WriteAt(
976 ULARGE_INTEGER ulOffset, /* [in] */
977 const void* pv, /* [size_is][in] */
979 ULONG* pcbWritten) /* [out] */
981 HGLOBALLockBytesImpl16* const This=(HGLOBALLockBytesImpl16*)iface;
984 ULARGE_INTEGER newSize;
985 ULONG bytesWritten = 0;
987 TRACE("(%p,%ld,%p,%ld,%p)\n",This,ulOffset.s.LowPart,pv,cb,pcbWritten);
989 * If the caller is not interested in the number of bytes written,
990 * we use another buffer to avoid "if" statements in the code.
993 pcbWritten = &bytesWritten;
998 newSize.s.HighPart = 0;
999 newSize.s.LowPart = ulOffset.s.LowPart + cb;
1002 * Verify if we need to grow the stream
1004 if (newSize.s.LowPart > This->byteArraySize.s.LowPart)
1007 if (HGLOBALLockBytesImpl16_SetSize(iface, newSize) == STG_E_MEDIUMFULL)
1008 return STG_E_MEDIUMFULL;
1012 * Lock the buffer in position and copy the data.
1014 supportBuffer = GlobalLock16(This->supportHandle);
1016 memcpy((char *) supportBuffer + ulOffset.s.LowPart, pv, cb);
1019 * Return the number of bytes written.
1026 GlobalUnlock16(This->supportHandle);
1031 /******************************************************************************
1032 * This method is part of the ILockBytes interface.
1034 * See the documentation of ILockBytes for more info.
1036 HRESULT WINAPI HGLOBALLockBytesImpl16_Flush(ILockBytes16* iface)
1038 TRACE("(%p)\n",iface);
1042 /******************************************************************************
1043 * This method is part of the ILockBytes interface.
1045 * It will change the size of the byte array.
1047 * See the documentation of ILockBytes for more info.
1049 HRESULT WINAPI HGLOBALLockBytesImpl16_SetSize(
1050 ILockBytes16* iface,
1051 ULARGE_INTEGER libNewSize) /* [in] */
1053 HGLOBALLockBytesImpl16* const This=(HGLOBALLockBytesImpl16*)iface;
1055 TRACE("(%p,%ld)\n",This,libNewSize.s.LowPart);
1059 if (libNewSize.s.HighPart != 0)
1060 return STG_E_INVALIDFUNCTION;
1062 if (This->byteArraySize.s.LowPart == libNewSize.s.LowPart)
1066 * Re allocate the HGlobal to fit the new size of the stream.
1068 This->supportHandle = GlobalReAlloc16(This->supportHandle,
1069 libNewSize.s.LowPart,
1072 if (This->supportHandle == 0)
1073 return STG_E_MEDIUMFULL;
1075 This->byteArraySize.s.LowPart = libNewSize.s.LowPart;
1080 /******************************************************************************
1081 * This method is part of the ILockBytes interface.
1083 * The global memory implementation of ILockBytes does not support locking.
1085 * See the documentation of ILockBytes for more info.
1087 HRESULT WINAPI HGLOBALLockBytesImpl16_LockRegion(
1088 ILockBytes16* iface,
1089 ULARGE_INTEGER libOffset, /* [in] */
1090 ULARGE_INTEGER cb, /* [in] */
1091 DWORD dwLockType) /* [in] */
1093 return STG_E_INVALIDFUNCTION;
1096 /******************************************************************************
1097 * This method is part of the ILockBytes interface.
1099 * The global memory implementation of ILockBytes does not support locking.
1101 * See the documentation of ILockBytes for more info.
1103 HRESULT WINAPI HGLOBALLockBytesImpl16_UnlockRegion(
1104 ILockBytes16* iface,
1105 ULARGE_INTEGER libOffset, /* [in] */
1106 ULARGE_INTEGER cb, /* [in] */
1107 DWORD dwLockType) /* [in] */
1109 return STG_E_INVALIDFUNCTION;
1112 /******************************************************************************
1113 * This method is part of the ILockBytes interface.
1115 * This method returns information about the current
1116 * byte array object.
1118 * See the documentation of ILockBytes for more info.
1120 HRESULT WINAPI HGLOBALLockBytesImpl16_Stat(
1122 STATSTG16* pstatstg, /* [out] */
1123 DWORD grfStatFlag) /* [in] */
1125 HGLOBALLockBytesImpl16* const This=(HGLOBALLockBytesImpl16*)iface;
1127 memset(pstatstg, 0, sizeof(STATSTG16));
1129 pstatstg->pwcsName = NULL;
1130 pstatstg->type = STGTY_LOCKBYTES;
1131 pstatstg->cbSize = This->byteArraySize;
1136 /******************************************************************************
1137 * CreateILockBytesOnHGlobal [OLE2.54]
1139 * Creates an ILockBytes interface for a HGLOBAL handle.
1142 * hGlobal the global handle (16bit)
1143 * fDeleteOnRelease delete handle on release.
1144 * ppLkbyt pointer to ILockBytes interface.
1147 * Staddard OLE error return codes.
1150 HRESULT WINAPI CreateILockBytesOnHGlobal16(HGLOBAL16 hGlobal,
1151 BOOL16 fDeleteOnRelease,
1152 /*SEGPTR**/ LPLOCKBYTES16* ppLkbyt)
1154 HGLOBALLockBytesImpl16* newLockBytes; /* SEGPTR */
1156 newLockBytes = HGLOBALLockBytesImpl16_Construct(hGlobal, fDeleteOnRelease);
1158 if (newLockBytes != NULL)
1159 return HGLOBALLockBytesImpl16_QueryInterface((ILockBytes16*)newLockBytes,
1162 return E_OUTOFMEMORY;