diff --git a/dlls/ole32/Makefile.in b/dlls/ole32/Makefile.in index 3e6501ea6aa..4886c8d0840 100644 --- a/dlls/ole32/Makefile.in +++ b/dlls/ole32/Makefile.in @@ -45,7 +45,9 @@ C_SRCS = \ storage.c \ storage32.c -C_SRCS16 = ole2nls.c +C_SRCS16 = \ + memlockbytes16.c \ + ole2nls.c RC_SRCS = ole32res.rc version.rc diff --git a/dlls/ole32/memlockbytes.c b/dlls/ole32/memlockbytes.c index 0c258da6c7e..9dad21725f9 100644 --- a/dlls/ole32/memlockbytes.c +++ b/dlls/ole32/memlockbytes.c @@ -623,543 +623,3 @@ HRESULT WINAPI HGLOBALLockBytesImpl_Stat( return S_OK; } - -/****************************************************************************** - * HGLOBALLockBytesImpl16 definition. - * - * This class imlements the ILockBytes inteface and represents a byte array - * object supported by an HGLOBAL pointer. - */ -struct HGLOBALLockBytesImpl16 -{ - /* - * Needs to be the first item in the stuct - * since we want to cast this in an ILockBytes pointer - */ - ICOM_VFIELD(ILockBytes16); - ULONG ref; - - /* - * Support for the LockBytes object - */ - HGLOBAL16 supportHandle; - - /* - * This flag is TRUE if the HGLOBAL is destroyed when the object - * is finally released. - */ - BOOL deleteOnRelease; - /* - * Helper variable that contains the size of the byte array - */ - ULARGE_INTEGER byteArraySize; -}; - -typedef struct HGLOBALLockBytesImpl16 HGLOBALLockBytesImpl16; - -HGLOBALLockBytesImpl16* HGLOBALLockBytesImpl16_Construct( - HGLOBAL16 hGlobal, - BOOL16 fDeleteOnRelease); - -void HGLOBALLockBytesImpl16_Destroy(HGLOBALLockBytesImpl16* This); - -HRESULT WINAPI HGLOBALLockBytesImpl16_QueryInterface( - ILockBytes16* iface, - REFIID riid, /* [in] */ - void** ppvObject); /* [iid_is][out] */ - -ULONG WINAPI HGLOBALLockBytesImpl16_AddRef( - ILockBytes16* iface); - -ULONG WINAPI HGLOBALLockBytesImpl16_Release( - ILockBytes16* iface); - -HRESULT WINAPI HGLOBALLockBytesImpl16_ReadAt( - ILockBytes16* iface, - ULARGE_INTEGER ulOffset, /* [in] */ - void* pv, /* [length_is][size_is][out] */ - ULONG cb, /* [in] */ - ULONG* pcbRead); /* [out] */ - -HRESULT WINAPI HGLOBALLockBytesImpl16_WriteAt( - ILockBytes16* iface, - ULARGE_INTEGER ulOffset, /* [in] */ - const void* pv, /* [size_is][in] */ - ULONG cb, /* [in] */ - ULONG* pcbWritten); /* [out] */ - -HRESULT WINAPI HGLOBALLockBytesImpl16_Flush( - ILockBytes16* iface); - -HRESULT WINAPI HGLOBALLockBytesImpl16_SetSize( - ILockBytes16* iface, - ULARGE_INTEGER libNewSize); /* [in] */ - -HRESULT WINAPI HGLOBALLockBytesImpl16_LockRegion( - ILockBytes16* iface, - ULARGE_INTEGER libOffset, /* [in] */ - ULARGE_INTEGER cb, /* [in] */ - DWORD dwLockType); /* [in] */ - -HRESULT WINAPI HGLOBALLockBytesImpl16_UnlockRegion( - ILockBytes16* iface, - ULARGE_INTEGER libOffset, /* [in] */ - ULARGE_INTEGER cb, /* [in] */ - DWORD dwLockType); /* [in] */ - -HRESULT WINAPI HGLOBALLockBytesImpl16_Stat( - ILockBytes16* iface, - STATSTG16* pstatstg, /* [out] */ - DWORD grfStatFlag); /* [in] */ - -/****************************************************************************** - * - * HGLOBALLockBytesImpl16 implementation - * - */ - -/****************************************************************************** - * This is the constructor for the HGLOBALLockBytesImpl16 class. - * - * Params: - * hGlobal - Handle that will support the stream. can be NULL. - * fDeleteOnRelease - Flag set to TRUE if the HGLOBAL16 will be released - * when the IStream object is destroyed. - */ -HGLOBALLockBytesImpl16* -HGLOBALLockBytesImpl16_Construct(HGLOBAL16 hGlobal, - BOOL16 fDeleteOnRelease) -{ - HGLOBALLockBytesImpl16* newLockBytes; - - static ICOM_VTABLE(ILockBytes16) vt16; - static SEGPTR msegvt16; - HMODULE16 hcomp = GetModuleHandle16("OLE2"); - - - TRACE("(%x,%d)\n",hGlobal,fDeleteOnRelease); - newLockBytes = HeapAlloc(GetProcessHeap(), 0, sizeof(HGLOBALLockBytesImpl16)); - if (newLockBytes == NULL) - return NULL; - - /* - * Set up the virtual function table and reference count. - */ - if (!msegvt16) - { -#define VTENT(x) vt16.x = (void*)GetProcAddress16(hcomp,"HGLOBALLockBytesImpl16_"#x);assert(vt16.x) - VTENT(QueryInterface); - VTENT(AddRef); - VTENT(Release); - VTENT(ReadAt); - VTENT(WriteAt); - VTENT(Flush); - VTENT(SetSize); - VTENT(LockRegion); - VTENT(UnlockRegion); -#undef VTENT - msegvt16 = MapLS( &vt16 ); - } - newLockBytes->lpVtbl = (ICOM_VTABLE(ILockBytes16)*)msegvt16; - newLockBytes->ref = 0; - /* - * Initialize the support. - */ - newLockBytes->supportHandle = hGlobal; - newLockBytes->deleteOnRelease = fDeleteOnRelease; - - /* - * This method will allocate a handle if one is not supplied. - */ - if (newLockBytes->supportHandle == 0) - newLockBytes->supportHandle = GlobalAlloc16(GMEM_MOVEABLE | GMEM_NODISCARD, 0); - - /* - * Initialize the size of the array to the size of the handle. - */ - newLockBytes->byteArraySize.s.HighPart = 0; - newLockBytes->byteArraySize.s.LowPart = GlobalSize16( - newLockBytes->supportHandle); - - return (HGLOBALLockBytesImpl16*)MapLS(newLockBytes); -} - -/****************************************************************************** - * This is the destructor of the HGLOBALStreamImpl class. - * - * This method will clean-up all the resources used-up by the given - * HGLOBALLockBytesImpl16 class. The pointer passed-in to this function will be - * freed and will not be valid anymore. - */ -void HGLOBALLockBytesImpl16_Destroy(HGLOBALLockBytesImpl16* This) -{ - TRACE("()\n"); - /* - * Release the HGlobal if the constructor asked for that. - */ - if (This->deleteOnRelease) - { - GlobalFree16(This->supportHandle); - This->supportHandle = 0; - } - - /* - * Finally, free the memory used-up by the class. - */ - HeapFree(GetProcessHeap(), 0, This); -} - -/****************************************************************************** - * This implements the IUnknown method QueryInterface for this - * class - */ -HRESULT WINAPI HGLOBALLockBytesImpl16_QueryInterface( - ILockBytes16* iface, /* [in] SEGPTR */ - REFIID riid, /* [in] */ - void** ppvObject) /* [iid_is][out] (ptr to SEGPTR!) */ -{ - HGLOBALLockBytesImpl16* const This=(HGLOBALLockBytesImpl16*)MapSL((SEGPTR)iface); - - TRACE("(%p,%s,%p)\n",iface,debugstr_guid(riid),ppvObject); - /* - * Perform a sanity check on the parameters. - */ - if (ppvObject==0) - return E_INVALIDARG; - - /* - * Initialize the return parameter. - */ - *ppvObject = 0; - /* - * Compare the riid with the interface IDs implemented by this object. - */ - if ( !memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) || - !memcmp(&IID_ILockBytes, riid, sizeof(IID_ILockBytes)) - ) - *ppvObject = (void*)iface; - - /* - * Check that we obtained an interface. - */ - if ((*ppvObject)==0) - return E_NOINTERFACE; - - /* - * Query Interface always increases the reference count by one when it is - * successful - */ - HGLOBALLockBytesImpl16_AddRef((ILockBytes16*)This); - - return S_OK; -} - -/****************************************************************************** - * This implements the IUnknown method AddRef for this - * class - */ -ULONG WINAPI HGLOBALLockBytesImpl16_AddRef(ILockBytes16* iface) -{ - HGLOBALLockBytesImpl16* const This=(HGLOBALLockBytesImpl16*)iface; - - TRACE("(%p)\n",This); - - This->ref++; - - return This->ref; -} - -/****************************************************************************** - * This implements the IUnknown method Release for this - * class - */ -ULONG WINAPI HGLOBALLockBytesImpl16_Release(ILockBytes16* iface) -{ - HGLOBALLockBytesImpl16* const This=(HGLOBALLockBytesImpl16*)iface; - - ULONG newRef; - TRACE("(%p)\n",This); - - This->ref--; - - newRef = This->ref; - - /* - * If the reference count goes down to 0, perform suicide. - */ - if (newRef==0) - HGLOBALLockBytesImpl16_Destroy(This); - return newRef; -} - -/****************************************************************************** - * This method is part of the ILockBytes interface. - * - * It reads a block of information from the byte array at the specified - * offset. - * - * See the documentation of ILockBytes for more info. - */ -HRESULT WINAPI HGLOBALLockBytesImpl16_ReadAt( - ILockBytes16* iface, - ULARGE_INTEGER ulOffset, /* [in] */ - void* pv, /* [length_is][size_is][out] */ - ULONG cb, /* [in] */ - ULONG* pcbRead) /* [out] */ -{ - HGLOBALLockBytesImpl16* const This=(HGLOBALLockBytesImpl16*)iface; - - void* supportBuffer; - ULONG bytesReadBuffer = 0; - ULONG bytesToReadFromBuffer; - - TRACE("(%p,%ld,%p,%ld,%p)\n",This,ulOffset.s.LowPart,pv,cb,pcbRead); - /* - * If the caller is not interested in the number of bytes read, - * we use another buffer to avoid "if" statements in the code. - */ - if (pcbRead == 0) - pcbRead = &bytesReadBuffer; - - /* - * Make sure the offset is valid. - */ - if (ulOffset.s.LowPart > This->byteArraySize.s.LowPart) - return E_FAIL; - - /* - * Using the known size of the array, calculate the number of bytes - * to read. - */ - bytesToReadFromBuffer = min(This->byteArraySize.s.LowPart - - ulOffset.s.LowPart, cb); - - /* - * Lock the buffer in position and copy the data. - */ - supportBuffer = GlobalLock16(This->supportHandle); - - memcpy(pv, - (char *) supportBuffer + ulOffset.s.LowPart, - bytesToReadFromBuffer); - - /* - * Return the number of bytes read. - */ - *pcbRead = bytesToReadFromBuffer; - - /* - * Cleanup - */ - GlobalUnlock16(This->supportHandle); - - /* - * The function returns S_OK if the specified number of bytes were read - * or the end of the array was reached. - * It returns STG_E_READFAULT if the number of bytes to read does not equal - * the number of bytes actually read. - */ - if(*pcbRead == cb) - return S_OK; - - return STG_E_READFAULT; -} - -/****************************************************************************** - * This method is part of the ILockBytes interface. - * - * It writes the specified bytes at the specified offset. - * position. If the array is too small, it will be resized. - * - * See the documentation of ILockBytes for more info. - */ -HRESULT WINAPI HGLOBALLockBytesImpl16_WriteAt( - ILockBytes16* iface, - ULARGE_INTEGER ulOffset, /* [in] */ - const void* pv, /* [size_is][in] */ - ULONG cb, /* [in] */ - ULONG* pcbWritten) /* [out] */ -{ - HGLOBALLockBytesImpl16* const This=(HGLOBALLockBytesImpl16*)iface; - - void* supportBuffer; - ULARGE_INTEGER newSize; - ULONG bytesWritten = 0; - - TRACE("(%p,%ld,%p,%ld,%p)\n",This,ulOffset.s.LowPart,pv,cb,pcbWritten); - /* - * If the caller is not interested in the number of bytes written, - * we use another buffer to avoid "if" statements in the code. - */ - if (pcbWritten == 0) - pcbWritten = &bytesWritten; - - if (cb == 0) - return S_OK; - - newSize.s.HighPart = 0; - newSize.s.LowPart = ulOffset.s.LowPart + cb; - - /* - * Verify if we need to grow the stream - */ - if (newSize.s.LowPart > This->byteArraySize.s.LowPart) - { - /* grow stream */ - if (HGLOBALLockBytesImpl16_SetSize(iface, newSize) == STG_E_MEDIUMFULL) - return STG_E_MEDIUMFULL; - } - - /* - * Lock the buffer in position and copy the data. - */ - supportBuffer = GlobalLock16(This->supportHandle); - - memcpy((char *) supportBuffer + ulOffset.s.LowPart, pv, cb); - - /* - * Return the number of bytes written. - */ - *pcbWritten = cb; - - /* - * Cleanup - */ - GlobalUnlock16(This->supportHandle); - - return S_OK; -} - -/****************************************************************************** - * This method is part of the ILockBytes interface. - * - * See the documentation of ILockBytes for more info. - */ -HRESULT WINAPI HGLOBALLockBytesImpl16_Flush(ILockBytes16* iface) -{ - TRACE("(%p)\n",iface); - return S_OK; -} - -/****************************************************************************** - * This method is part of the ILockBytes interface. - * - * It will change the size of the byte array. - * - * See the documentation of ILockBytes for more info. - */ -HRESULT WINAPI HGLOBALLockBytesImpl16_SetSize( - ILockBytes16* iface, - ULARGE_INTEGER libNewSize) /* [in] */ -{ - HGLOBALLockBytesImpl16* const This=(HGLOBALLockBytesImpl16*)iface; - - TRACE("(%p,%ld)\n",This,libNewSize.s.LowPart); - /* - * As documented. - */ - if (libNewSize.s.HighPart != 0) - return STG_E_INVALIDFUNCTION; - - if (This->byteArraySize.s.LowPart == libNewSize.s.LowPart) - return S_OK; - - /* - * Re allocate the HGlobal to fit the new size of the stream. - */ - This->supportHandle = GlobalReAlloc16(This->supportHandle, - libNewSize.s.LowPart, - 0); - - if (This->supportHandle == 0) - return STG_E_MEDIUMFULL; - - This->byteArraySize.s.LowPart = libNewSize.s.LowPart; - - return S_OK; -} - -/****************************************************************************** - * This method is part of the ILockBytes interface. - * - * The global memory implementation of ILockBytes does not support locking. - * - * See the documentation of ILockBytes for more info. - */ -HRESULT WINAPI HGLOBALLockBytesImpl16_LockRegion( - ILockBytes16* iface, - ULARGE_INTEGER libOffset, /* [in] */ - ULARGE_INTEGER cb, /* [in] */ - DWORD dwLockType) /* [in] */ -{ - return STG_E_INVALIDFUNCTION; -} - -/****************************************************************************** - * This method is part of the ILockBytes interface. - * - * The global memory implementation of ILockBytes does not support locking. - * - * See the documentation of ILockBytes for more info. - */ -HRESULT WINAPI HGLOBALLockBytesImpl16_UnlockRegion( - ILockBytes16* iface, - ULARGE_INTEGER libOffset, /* [in] */ - ULARGE_INTEGER cb, /* [in] */ - DWORD dwLockType) /* [in] */ -{ - return STG_E_INVALIDFUNCTION; -} - -/****************************************************************************** - * This method is part of the ILockBytes interface. - * - * This method returns information about the current - * byte array object. - * - * See the documentation of ILockBytes for more info. - */ -HRESULT WINAPI HGLOBALLockBytesImpl16_Stat( - ILockBytes16*iface, - STATSTG16* pstatstg, /* [out] */ - DWORD grfStatFlag) /* [in] */ -{ - HGLOBALLockBytesImpl16* const This=(HGLOBALLockBytesImpl16*)iface; - - memset(pstatstg, 0, sizeof(STATSTG16)); - - pstatstg->pwcsName = NULL; - pstatstg->type = STGTY_LOCKBYTES; - pstatstg->cbSize = This->byteArraySize; - - return S_OK; -} - -/****************************************************************************** - * CreateILockBytesOnHGlobal [OLE2.54] - * - * Creates an ILockBytes interface for a HGLOBAL handle. - * - * Params: - * hGlobal the global handle (16bit) - * fDeleteOnRelease delete handle on release. - * ppLkbyt pointer to ILockBytes interface. - * - * Returns: - * Staddard OLE error return codes. - * - */ -HRESULT WINAPI CreateILockBytesOnHGlobal16(HGLOBAL16 hGlobal, - BOOL16 fDeleteOnRelease, - /*SEGPTR**/ LPLOCKBYTES16* ppLkbyt) -{ - HGLOBALLockBytesImpl16* newLockBytes; /* SEGPTR */ - - newLockBytes = HGLOBALLockBytesImpl16_Construct(hGlobal, fDeleteOnRelease); - - if (newLockBytes != NULL) - return HGLOBALLockBytesImpl16_QueryInterface((ILockBytes16*)newLockBytes, - &IID_ILockBytes, - (void**)ppLkbyt); - return E_OUTOFMEMORY; -} diff --git a/dlls/ole32/memlockbytes16.c b/dlls/ole32/memlockbytes16.c new file mode 100644 index 00000000000..74743919e26 --- /dev/null +++ b/dlls/ole32/memlockbytes16.c @@ -0,0 +1,579 @@ +/* + * Global memory implementation of ILockBytes. + * + * Copyright 1999 Thuy Nguyen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include +#include + +#define NONAMELESSUNION +#define NONAMELESSSTRUCT +#include "windef.h" +#include "wine/winbase16.h" +#include "objbase.h" +#include "ole2.h" +#include "winbase.h" +#include "winerror.h" + +#include "ifs.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(ole); + +/****************************************************************************** + * HGLOBALLockBytesImpl16 definition. + * + * This class imlements the ILockBytes inteface and represents a byte array + * object supported by an HGLOBAL pointer. + */ +struct HGLOBALLockBytesImpl16 +{ + /* + * Needs to be the first item in the stuct + * since we want to cast this in an ILockBytes pointer + */ + ICOM_VFIELD(ILockBytes16); + ULONG ref; + + /* + * Support for the LockBytes object + */ + HGLOBAL16 supportHandle; + + /* + * This flag is TRUE if the HGLOBAL is destroyed when the object + * is finally released. + */ + BOOL deleteOnRelease; + /* + * Helper variable that contains the size of the byte array + */ + ULARGE_INTEGER byteArraySize; +}; + +typedef struct HGLOBALLockBytesImpl16 HGLOBALLockBytesImpl16; + +HGLOBALLockBytesImpl16* HGLOBALLockBytesImpl16_Construct( + HGLOBAL16 hGlobal, + BOOL16 fDeleteOnRelease); + +void HGLOBALLockBytesImpl16_Destroy(HGLOBALLockBytesImpl16* This); + +HRESULT WINAPI HGLOBALLockBytesImpl16_QueryInterface( + ILockBytes16* iface, + REFIID riid, /* [in] */ + void** ppvObject); /* [iid_is][out] */ + +ULONG WINAPI HGLOBALLockBytesImpl16_AddRef( + ILockBytes16* iface); + +ULONG WINAPI HGLOBALLockBytesImpl16_Release( + ILockBytes16* iface); + +HRESULT WINAPI HGLOBALLockBytesImpl16_ReadAt( + ILockBytes16* iface, + ULARGE_INTEGER ulOffset, /* [in] */ + void* pv, /* [length_is][size_is][out] */ + ULONG cb, /* [in] */ + ULONG* pcbRead); /* [out] */ + +HRESULT WINAPI HGLOBALLockBytesImpl16_WriteAt( + ILockBytes16* iface, + ULARGE_INTEGER ulOffset, /* [in] */ + const void* pv, /* [size_is][in] */ + ULONG cb, /* [in] */ + ULONG* pcbWritten); /* [out] */ + +HRESULT WINAPI HGLOBALLockBytesImpl16_Flush( + ILockBytes16* iface); + +HRESULT WINAPI HGLOBALLockBytesImpl16_SetSize( + ILockBytes16* iface, + ULARGE_INTEGER libNewSize); /* [in] */ + +HRESULT WINAPI HGLOBALLockBytesImpl16_LockRegion( + ILockBytes16* iface, + ULARGE_INTEGER libOffset, /* [in] */ + ULARGE_INTEGER cb, /* [in] */ + DWORD dwLockType); /* [in] */ + +HRESULT WINAPI HGLOBALLockBytesImpl16_UnlockRegion( + ILockBytes16* iface, + ULARGE_INTEGER libOffset, /* [in] */ + ULARGE_INTEGER cb, /* [in] */ + DWORD dwLockType); /* [in] */ + +HRESULT WINAPI HGLOBALLockBytesImpl16_Stat( + ILockBytes16* iface, + STATSTG16* pstatstg, /* [out] */ + DWORD grfStatFlag); /* [in] */ + +/****************************************************************************** + * + * HGLOBALLockBytesImpl16 implementation + * + */ + +/****************************************************************************** + * This is the constructor for the HGLOBALLockBytesImpl16 class. + * + * Params: + * hGlobal - Handle that will support the stream. can be NULL. + * fDeleteOnRelease - Flag set to TRUE if the HGLOBAL16 will be released + * when the IStream object is destroyed. + */ +HGLOBALLockBytesImpl16* +HGLOBALLockBytesImpl16_Construct(HGLOBAL16 hGlobal, + BOOL16 fDeleteOnRelease) +{ + HGLOBALLockBytesImpl16* newLockBytes; + + static ICOM_VTABLE(ILockBytes16) vt16; + static SEGPTR msegvt16; + HMODULE16 hcomp = GetModuleHandle16("OLE2"); + + + TRACE("(%x,%d)\n",hGlobal,fDeleteOnRelease); + newLockBytes = HeapAlloc(GetProcessHeap(), 0, sizeof(HGLOBALLockBytesImpl16)); + if (newLockBytes == NULL) + return NULL; + + /* + * Set up the virtual function table and reference count. + */ + if (!msegvt16) + { +#define VTENT(x) vt16.x = (void*)GetProcAddress16(hcomp,"HGLOBALLockBytesImpl16_"#x);assert(vt16.x) + VTENT(QueryInterface); + VTENT(AddRef); + VTENT(Release); + VTENT(ReadAt); + VTENT(WriteAt); + VTENT(Flush); + VTENT(SetSize); + VTENT(LockRegion); + VTENT(UnlockRegion); +#undef VTENT + msegvt16 = MapLS( &vt16 ); + } + newLockBytes->lpVtbl = (ICOM_VTABLE(ILockBytes16)*)msegvt16; + newLockBytes->ref = 0; + /* + * Initialize the support. + */ + newLockBytes->supportHandle = hGlobal; + newLockBytes->deleteOnRelease = fDeleteOnRelease; + + /* + * This method will allocate a handle if one is not supplied. + */ + if (newLockBytes->supportHandle == 0) + newLockBytes->supportHandle = GlobalAlloc16(GMEM_MOVEABLE | GMEM_NODISCARD, 0); + + /* + * Initialize the size of the array to the size of the handle. + */ + newLockBytes->byteArraySize.s.HighPart = 0; + newLockBytes->byteArraySize.s.LowPart = GlobalSize16( + newLockBytes->supportHandle); + + return (HGLOBALLockBytesImpl16*)MapLS(newLockBytes); +} + +/****************************************************************************** + * This is the destructor of the HGLOBALStreamImpl class. + * + * This method will clean-up all the resources used-up by the given + * HGLOBALLockBytesImpl16 class. The pointer passed-in to this function will be + * freed and will not be valid anymore. + */ +void HGLOBALLockBytesImpl16_Destroy(HGLOBALLockBytesImpl16* This) +{ + TRACE("()\n"); + /* + * Release the HGlobal if the constructor asked for that. + */ + if (This->deleteOnRelease) + { + GlobalFree16(This->supportHandle); + This->supportHandle = 0; + } + + /* + * Finally, free the memory used-up by the class. + */ + HeapFree(GetProcessHeap(), 0, This); +} + +/****************************************************************************** + * This implements the IUnknown method QueryInterface for this + * class + */ +HRESULT WINAPI HGLOBALLockBytesImpl16_QueryInterface( + ILockBytes16* iface, /* [in] SEGPTR */ + REFIID riid, /* [in] */ + void** ppvObject) /* [iid_is][out] (ptr to SEGPTR!) */ +{ + HGLOBALLockBytesImpl16* const This=(HGLOBALLockBytesImpl16*)MapSL((SEGPTR)iface); + + TRACE("(%p,%s,%p)\n",iface,debugstr_guid(riid),ppvObject); + /* + * Perform a sanity check on the parameters. + */ + if (ppvObject==0) + return E_INVALIDARG; + + /* + * Initialize the return parameter. + */ + *ppvObject = 0; + /* + * Compare the riid with the interface IDs implemented by this object. + */ + if ( !memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) || + !memcmp(&IID_ILockBytes, riid, sizeof(IID_ILockBytes)) + ) + *ppvObject = (void*)iface; + + /* + * Check that we obtained an interface. + */ + if ((*ppvObject)==0) + return E_NOINTERFACE; + + /* + * Query Interface always increases the reference count by one when it is + * successful + */ + HGLOBALLockBytesImpl16_AddRef((ILockBytes16*)This); + + return S_OK; +} + +/****************************************************************************** + * This implements the IUnknown method AddRef for this + * class + */ +ULONG WINAPI HGLOBALLockBytesImpl16_AddRef(ILockBytes16* iface) +{ + HGLOBALLockBytesImpl16* const This=(HGLOBALLockBytesImpl16*)iface; + + TRACE("(%p)\n",This); + + This->ref++; + + return This->ref; +} + +/****************************************************************************** + * This implements the IUnknown method Release for this + * class + */ +ULONG WINAPI HGLOBALLockBytesImpl16_Release(ILockBytes16* iface) +{ + HGLOBALLockBytesImpl16* const This=(HGLOBALLockBytesImpl16*)iface; + + ULONG newRef; + TRACE("(%p)\n",This); + + This->ref--; + + newRef = This->ref; + + /* + * If the reference count goes down to 0, perform suicide. + */ + if (newRef==0) + HGLOBALLockBytesImpl16_Destroy(This); + return newRef; +} + +/****************************************************************************** + * This method is part of the ILockBytes interface. + * + * It reads a block of information from the byte array at the specified + * offset. + * + * See the documentation of ILockBytes for more info. + */ +HRESULT WINAPI HGLOBALLockBytesImpl16_ReadAt( + ILockBytes16* iface, + ULARGE_INTEGER ulOffset, /* [in] */ + void* pv, /* [length_is][size_is][out] */ + ULONG cb, /* [in] */ + ULONG* pcbRead) /* [out] */ +{ + HGLOBALLockBytesImpl16* const This=(HGLOBALLockBytesImpl16*)iface; + + void* supportBuffer; + ULONG bytesReadBuffer = 0; + ULONG bytesToReadFromBuffer; + + TRACE("(%p,%ld,%p,%ld,%p)\n",This,ulOffset.s.LowPart,pv,cb,pcbRead); + /* + * If the caller is not interested in the number of bytes read, + * we use another buffer to avoid "if" statements in the code. + */ + if (pcbRead == 0) + pcbRead = &bytesReadBuffer; + + /* + * Make sure the offset is valid. + */ + if (ulOffset.s.LowPart > This->byteArraySize.s.LowPart) + return E_FAIL; + + /* + * Using the known size of the array, calculate the number of bytes + * to read. + */ + bytesToReadFromBuffer = min(This->byteArraySize.s.LowPart - + ulOffset.s.LowPart, cb); + + /* + * Lock the buffer in position and copy the data. + */ + supportBuffer = GlobalLock16(This->supportHandle); + + memcpy(pv, + (char *) supportBuffer + ulOffset.s.LowPart, + bytesToReadFromBuffer); + + /* + * Return the number of bytes read. + */ + *pcbRead = bytesToReadFromBuffer; + + /* + * Cleanup + */ + GlobalUnlock16(This->supportHandle); + + /* + * The function returns S_OK if the specified number of bytes were read + * or the end of the array was reached. + * It returns STG_E_READFAULT if the number of bytes to read does not equal + * the number of bytes actually read. + */ + if(*pcbRead == cb) + return S_OK; + + return STG_E_READFAULT; +} + +/****************************************************************************** + * This method is part of the ILockBytes interface. + * + * It writes the specified bytes at the specified offset. + * position. If the array is too small, it will be resized. + * + * See the documentation of ILockBytes for more info. + */ +HRESULT WINAPI HGLOBALLockBytesImpl16_WriteAt( + ILockBytes16* iface, + ULARGE_INTEGER ulOffset, /* [in] */ + const void* pv, /* [size_is][in] */ + ULONG cb, /* [in] */ + ULONG* pcbWritten) /* [out] */ +{ + HGLOBALLockBytesImpl16* const This=(HGLOBALLockBytesImpl16*)iface; + + void* supportBuffer; + ULARGE_INTEGER newSize; + ULONG bytesWritten = 0; + + TRACE("(%p,%ld,%p,%ld,%p)\n",This,ulOffset.s.LowPart,pv,cb,pcbWritten); + /* + * If the caller is not interested in the number of bytes written, + * we use another buffer to avoid "if" statements in the code. + */ + if (pcbWritten == 0) + pcbWritten = &bytesWritten; + + if (cb == 0) + return S_OK; + + newSize.s.HighPart = 0; + newSize.s.LowPart = ulOffset.s.LowPart + cb; + + /* + * Verify if we need to grow the stream + */ + if (newSize.s.LowPart > This->byteArraySize.s.LowPart) + { + /* grow stream */ + if (HGLOBALLockBytesImpl16_SetSize(iface, newSize) == STG_E_MEDIUMFULL) + return STG_E_MEDIUMFULL; + } + + /* + * Lock the buffer in position and copy the data. + */ + supportBuffer = GlobalLock16(This->supportHandle); + + memcpy((char *) supportBuffer + ulOffset.s.LowPart, pv, cb); + + /* + * Return the number of bytes written. + */ + *pcbWritten = cb; + + /* + * Cleanup + */ + GlobalUnlock16(This->supportHandle); + + return S_OK; +} + +/****************************************************************************** + * This method is part of the ILockBytes interface. + * + * See the documentation of ILockBytes for more info. + */ +HRESULT WINAPI HGLOBALLockBytesImpl16_Flush(ILockBytes16* iface) +{ + TRACE("(%p)\n",iface); + return S_OK; +} + +/****************************************************************************** + * This method is part of the ILockBytes interface. + * + * It will change the size of the byte array. + * + * See the documentation of ILockBytes for more info. + */ +HRESULT WINAPI HGLOBALLockBytesImpl16_SetSize( + ILockBytes16* iface, + ULARGE_INTEGER libNewSize) /* [in] */ +{ + HGLOBALLockBytesImpl16* const This=(HGLOBALLockBytesImpl16*)iface; + + TRACE("(%p,%ld)\n",This,libNewSize.s.LowPart); + /* + * As documented. + */ + if (libNewSize.s.HighPart != 0) + return STG_E_INVALIDFUNCTION; + + if (This->byteArraySize.s.LowPart == libNewSize.s.LowPart) + return S_OK; + + /* + * Re allocate the HGlobal to fit the new size of the stream. + */ + This->supportHandle = GlobalReAlloc16(This->supportHandle, + libNewSize.s.LowPart, + 0); + + if (This->supportHandle == 0) + return STG_E_MEDIUMFULL; + + This->byteArraySize.s.LowPart = libNewSize.s.LowPart; + + return S_OK; +} + +/****************************************************************************** + * This method is part of the ILockBytes interface. + * + * The global memory implementation of ILockBytes does not support locking. + * + * See the documentation of ILockBytes for more info. + */ +HRESULT WINAPI HGLOBALLockBytesImpl16_LockRegion( + ILockBytes16* iface, + ULARGE_INTEGER libOffset, /* [in] */ + ULARGE_INTEGER cb, /* [in] */ + DWORD dwLockType) /* [in] */ +{ + return STG_E_INVALIDFUNCTION; +} + +/****************************************************************************** + * This method is part of the ILockBytes interface. + * + * The global memory implementation of ILockBytes does not support locking. + * + * See the documentation of ILockBytes for more info. + */ +HRESULT WINAPI HGLOBALLockBytesImpl16_UnlockRegion( + ILockBytes16* iface, + ULARGE_INTEGER libOffset, /* [in] */ + ULARGE_INTEGER cb, /* [in] */ + DWORD dwLockType) /* [in] */ +{ + return STG_E_INVALIDFUNCTION; +} + +/****************************************************************************** + * This method is part of the ILockBytes interface. + * + * This method returns information about the current + * byte array object. + * + * See the documentation of ILockBytes for more info. + */ +HRESULT WINAPI HGLOBALLockBytesImpl16_Stat( + ILockBytes16*iface, + STATSTG16* pstatstg, /* [out] */ + DWORD grfStatFlag) /* [in] */ +{ + HGLOBALLockBytesImpl16* const This=(HGLOBALLockBytesImpl16*)iface; + + memset(pstatstg, 0, sizeof(STATSTG16)); + + pstatstg->pwcsName = NULL; + pstatstg->type = STGTY_LOCKBYTES; + pstatstg->cbSize = This->byteArraySize; + + return S_OK; +} + +/****************************************************************************** + * CreateILockBytesOnHGlobal [OLE2.54] + * + * Creates an ILockBytes interface for a HGLOBAL handle. + * + * Params: + * hGlobal the global handle (16bit) + * fDeleteOnRelease delete handle on release. + * ppLkbyt pointer to ILockBytes interface. + * + * Returns: + * Staddard OLE error return codes. + * + */ +HRESULT WINAPI CreateILockBytesOnHGlobal16(HGLOBAL16 hGlobal, + BOOL16 fDeleteOnRelease, + /*SEGPTR**/ LPLOCKBYTES16* ppLkbyt) +{ + HGLOBALLockBytesImpl16* newLockBytes; /* SEGPTR */ + + newLockBytes = HGLOBALLockBytesImpl16_Construct(hGlobal, fDeleteOnRelease); + + if (newLockBytes != NULL) + return HGLOBALLockBytesImpl16_QueryInterface((ILockBytes16*)newLockBytes, + &IID_ILockBytes, + (void**)ppLkbyt); + return E_OUTOFMEMORY; +}