ole32: COM cleanup of HGLOBAL ILockBytes implementation.

This commit is contained in:
Nikolay Sivov 2012-07-17 10:53:14 +04:00 committed by Alexandre Julliard
parent 52ce30d242
commit 897d4d4e4a
1 changed files with 61 additions and 149 deletions

View File

@ -48,16 +48,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole);
*/
struct HGLOBALLockBytesImpl
{
/*
* Needs to be the first item in the struct
* since we want to cast this in an ILockBytes pointer
*/
const ILockBytesVtbl *lpVtbl;
/*
* Reference count
*/
LONG ref;
ILockBytes ILockBytes_iface;
LONG ref;
/*
* Support for the LockBytes object
@ -78,16 +70,10 @@ struct HGLOBALLockBytesImpl
typedef struct HGLOBALLockBytesImpl HGLOBALLockBytesImpl;
/*
* Method definition for the HGLOBALLockBytesImpl class.
*/
static HGLOBALLockBytesImpl* HGLOBALLockBytesImpl_Construct(
HGLOBAL hGlobal,
BOOL fDeleteOnRelease);
static void HGLOBALLockBytesImpl_Destroy(HGLOBALLockBytesImpl* This);
static HRESULT WINAPI HGLOBALLockBytesImpl_SetSize( ILockBytes* iface, ULARGE_INTEGER libNewSize );
static inline HGLOBALLockBytesImpl *impl_from_ILockBytes( ILockBytes *iface )
{
return CONTAINING_RECORD(iface, HGLOBALLockBytesImpl, ILockBytes_iface);
}
static const ILockBytesVtbl HGLOBALLockBytesImpl_Vtbl;
@ -98,9 +84,9 @@ static const ILockBytesVtbl HGLOBALLockBytesImpl_Vtbl;
* This object supports a COM implementation of the ILockBytes interface.
*
* PARAMS
* hGlobal [ I] Global memory handle
* fDeleteOnRelease [ I] Whether the handle should be freed when the object is released.
* ppLkbyt [ O] Address of ILockBytes pointer that receives
* global [ I] Global memory handle
* delete_on_release [ I] Whether the handle should be freed when the object is released.
* ret [ O] Address of ILockBytes pointer that receives
* the interface pointer to the new byte array object.
*
* RETURNS
@ -112,22 +98,37 @@ static const ILockBytesVtbl HGLOBALLockBytesImpl_Vtbl;
* The ILockBytes interface instance calls the GlobalReAlloc function to grow
* the memory block as required.
*/
HRESULT WINAPI CreateILockBytesOnHGlobal(HGLOBAL hGlobal,
BOOL fDeleteOnRelease,
LPLOCKBYTES* ppLkbyt)
HRESULT WINAPI CreateILockBytesOnHGlobal(HGLOBAL global, BOOL delete_on_release, ILockBytes **ret)
{
HGLOBALLockBytesImpl* newLockBytes;
HGLOBALLockBytesImpl* lockbytes;
newLockBytes = HGLOBALLockBytesImpl_Construct(hGlobal, fDeleteOnRelease);
lockbytes = HeapAlloc(GetProcessHeap(), 0, sizeof(HGLOBALLockBytesImpl));
if (!lockbytes) return E_OUTOFMEMORY;
if (newLockBytes != NULL)
{
return IUnknown_QueryInterface((IUnknown*)newLockBytes,
&IID_ILockBytes,
(void**)ppLkbyt);
}
lockbytes->ILockBytes_iface.lpVtbl = &HGLOBALLockBytesImpl_Vtbl;
lockbytes->ref = 1;
return E_OUTOFMEMORY;
/*
* Initialize the support.
*/
lockbytes->supportHandle = global;
lockbytes->deleteOnRelease = delete_on_release;
/*
* This method will allocate a handle if one is not supplied.
*/
if (lockbytes->supportHandle == 0)
lockbytes->supportHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD, 0);
/*
* Initialize the size of the array to the size of the handle.
*/
lockbytes->byteArraySize.u.HighPart = 0;
lockbytes->byteArraySize.u.LowPart = GlobalSize(lockbytes->supportHandle);
*ret = &lockbytes->ILockBytes_iface;
return S_OK;
}
/******************************************************************************
@ -144,23 +145,23 @@ HRESULT WINAPI CreateILockBytesOnHGlobal(HGLOBAL hGlobal,
* E_INVALIDARG if any parameters are invalid
*
*/
HRESULT WINAPI GetHGlobalFromILockBytes(ILockBytes* plkbyt, HGLOBAL* phglobal)
HRESULT WINAPI GetHGlobalFromILockBytes(ILockBytes* iface, HGLOBAL* phglobal)
{
HGLOBALLockBytesImpl* const pMemLockBytes = (HGLOBALLockBytesImpl*)plkbyt;
HGLOBALLockBytesImpl* This = impl_from_ILockBytes(iface);
STATSTG stbuf;
HRESULT hres;
ULARGE_INTEGER start;
ULONG xread;
*phglobal = 0;
if (pMemLockBytes->lpVtbl == &HGLOBALLockBytesImpl_Vtbl) {
*phglobal = pMemLockBytes->supportHandle;
if (This->ILockBytes_iface.lpVtbl == &HGLOBALLockBytesImpl_Vtbl) {
*phglobal = This->supportHandle;
if (*phglobal == 0)
return E_INVALIDARG;
return S_OK;
}
/* It is not our lockbytes implementation, so use a more generic way */
hres = ILockBytes_Stat(plkbyt,&stbuf,STATFLAG_NONAME);
hres = ILockBytes_Stat(iface,&stbuf,STATFLAG_NONAME);
if (hres != S_OK) {
ERR("Cannot ILockBytes_Stat, %x\n",hres);
return hres;
@ -170,10 +171,10 @@ HRESULT WINAPI GetHGlobalFromILockBytes(ILockBytes* plkbyt, HGLOBAL* phglobal)
if (!*phglobal)
return E_INVALIDARG;
memset(&start,0,sizeof(start));
hres = ILockBytes_ReadAt(plkbyt, start, GlobalLock(*phglobal), stbuf.cbSize.u.LowPart, &xread);
hres = ILockBytes_ReadAt(iface, start, GlobalLock(*phglobal), stbuf.cbSize.u.LowPart, &xread);
GlobalUnlock(*phglobal);
if (hres != S_OK) {
FIXME("%p->ReadAt failed with %x\n",plkbyt,hres);
FIXME("%p->ReadAt failed with %x\n",iface,hres);
return hres;
}
if (stbuf.cbSize.u.LowPart != xread) {
@ -188,79 +189,6 @@ HRESULT WINAPI GetHGlobalFromILockBytes(ILockBytes* plkbyt, HGLOBAL* phglobal)
*
*/
/******************************************************************************
* This is the constructor for the HGLOBALLockBytesImpl class.
*
* PARAMS
* hGlobal [ I] Handle that will support the stream. can be NULL.
* fDeleteOnRelease [ I] Flag set to TRUE if the HGLOBAL will be released
* when the IStream object is destroyed.
*/
static HGLOBALLockBytesImpl* HGLOBALLockBytesImpl_Construct(HGLOBAL hGlobal,
BOOL fDeleteOnRelease)
{
HGLOBALLockBytesImpl* newLockBytes;
newLockBytes = HeapAlloc(GetProcessHeap(), 0, sizeof(HGLOBALLockBytesImpl));
if (newLockBytes!=0)
{
/*
* Set up the virtual function table and reference count.
*/
newLockBytes->lpVtbl = &HGLOBALLockBytesImpl_Vtbl;
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 = GlobalAlloc(GMEM_MOVEABLE |
GMEM_NODISCARD,
0);
}
/*
* Initialize the size of the array to the size of the handle.
*/
newLockBytes->byteArraySize.u.HighPart = 0;
newLockBytes->byteArraySize.u.LowPart = GlobalSize(
newLockBytes->supportHandle);
}
return newLockBytes;
}
/******************************************************************************
* This is the destructor of the HGLOBALStreamImpl class.
*
* This method will clean-up all the resources used-up by the given
* HGLOBALLockBytesImpl class. The pointer passed-in to this function will be
* freed and will not be valid anymore.
*/
static void HGLOBALLockBytesImpl_Destroy(HGLOBALLockBytesImpl* This)
{
/*
* Release the HGlobal if the constructor asked for that.
*/
if (This->deleteOnRelease)
{
GlobalFree(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
@ -270,39 +198,22 @@ static HRESULT WINAPI HGLOBALLockBytesImpl_QueryInterface(
REFIID riid, /* [in] */
void** ppvObject) /* [iid_is][out] */
{
HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface;
HGLOBALLockBytesImpl* This = impl_from_ILockBytes(iface);
/*
* 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 (IsEqualIID(riid, &IID_IUnknown) ||
IsEqualIID(riid, &IID_ILockBytes))
{
*ppvObject = This;
*ppvObject = &This->ILockBytes_iface;
}
/*
* Check that we obtained an interface.
*/
if ((*ppvObject)==0)
else
return E_NOINTERFACE;
/*
* Query Interface always increases the reference count by one when it is
* successful
*/
IUnknown_AddRef(iface);
ILockBytes_AddRef(iface);
return S_OK;
}
@ -313,7 +224,7 @@ static HRESULT WINAPI HGLOBALLockBytesImpl_QueryInterface(
*/
static ULONG WINAPI HGLOBALLockBytesImpl_AddRef(ILockBytes* iface)
{
HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface;
HGLOBALLockBytesImpl* This = impl_from_ILockBytes(iface);
return InterlockedIncrement(&This->ref);
}
@ -323,17 +234,18 @@ static ULONG WINAPI HGLOBALLockBytesImpl_AddRef(ILockBytes* iface)
*/
static ULONG WINAPI HGLOBALLockBytesImpl_Release(ILockBytes* iface)
{
HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface;
HGLOBALLockBytesImpl* This = impl_from_ILockBytes(iface);
ULONG ref;
ref = InterlockedDecrement(&This->ref);
/*
* If the reference count goes down to 0, perform suicide.
*/
if (ref==0)
if (!ref)
{
HGLOBALLockBytesImpl_Destroy(This);
if (This->deleteOnRelease)
{
GlobalFree(This->supportHandle);
This->supportHandle = 0;
}
HeapFree(GetProcessHeap(), 0, This);
}
return ref;
@ -354,7 +266,7 @@ static HRESULT WINAPI HGLOBALLockBytesImpl_ReadAt(
ULONG cb, /* [in] */
ULONG* pcbRead) /* [out] */
{
HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface;
HGLOBALLockBytesImpl* This = impl_from_ILockBytes(iface);
void* supportBuffer;
ULONG bytesReadBuffer = 0;
@ -426,7 +338,7 @@ static HRESULT WINAPI HGLOBALLockBytesImpl_WriteAt(
ULONG cb, /* [in] */
ULONG* pcbWritten) /* [out] */
{
HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface;
HGLOBALLockBytesImpl* This = impl_from_ILockBytes(iface);
void* supportBuffer;
ULARGE_INTEGER newSize;
@ -455,7 +367,7 @@ static HRESULT WINAPI HGLOBALLockBytesImpl_WriteAt(
if (newSize.u.LowPart > This->byteArraySize.u.LowPart)
{
/* grow stream */
if (HGLOBALLockBytesImpl_SetSize(iface, newSize) == STG_E_MEDIUMFULL)
if (ILockBytes_SetSize(iface, newSize) == STG_E_MEDIUMFULL)
return STG_E_MEDIUMFULL;
}
@ -500,7 +412,7 @@ static HRESULT WINAPI HGLOBALLockBytesImpl_SetSize(
ILockBytes* iface,
ULARGE_INTEGER libNewSize) /* [in] */
{
HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface;
HGLOBALLockBytesImpl* This = impl_from_ILockBytes(iface);
HGLOBAL supportHandle;
/*
@ -571,7 +483,7 @@ static HRESULT WINAPI HGLOBALLockBytesImpl_Stat(
STATSTG* pstatstg, /* [out] */
DWORD grfStatFlag) /* [in] */
{
HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface;
HGLOBALLockBytesImpl* This = impl_from_ILockBytes(iface);
memset(pstatstg, 0, sizeof(STATSTG));