Separate Win16 and Win32 implementations in memlockbytes.
This commit is contained in:
parent
6d1a1d49ac
commit
6c5e872240
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#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;
|
||||
}
|
Loading…
Reference in New Issue