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,15 +48,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole);
*/ */
struct HGLOBALLockBytesImpl struct HGLOBALLockBytesImpl
{ {
/* ILockBytes ILockBytes_iface;
* 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; LONG ref;
/* /*
@ -78,16 +70,10 @@ struct HGLOBALLockBytesImpl
typedef struct HGLOBALLockBytesImpl HGLOBALLockBytesImpl; typedef struct HGLOBALLockBytesImpl HGLOBALLockBytesImpl;
/* static inline HGLOBALLockBytesImpl *impl_from_ILockBytes( ILockBytes *iface )
* Method definition for the HGLOBALLockBytesImpl class. {
*/ return CONTAINING_RECORD(iface, HGLOBALLockBytesImpl, ILockBytes_iface);
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 const ILockBytesVtbl HGLOBALLockBytesImpl_Vtbl; static const ILockBytesVtbl HGLOBALLockBytesImpl_Vtbl;
@ -98,9 +84,9 @@ static const ILockBytesVtbl HGLOBALLockBytesImpl_Vtbl;
* This object supports a COM implementation of the ILockBytes interface. * This object supports a COM implementation of the ILockBytes interface.
* *
* PARAMS * PARAMS
* hGlobal [ I] Global memory handle * global [ I] Global memory handle
* fDeleteOnRelease [ I] Whether the handle should be freed when the object is released. * delete_on_release [ I] Whether the handle should be freed when the object is released.
* ppLkbyt [ O] Address of ILockBytes pointer that receives * ret [ O] Address of ILockBytes pointer that receives
* the interface pointer to the new byte array object. * the interface pointer to the new byte array object.
* *
* RETURNS * RETURNS
@ -112,22 +98,37 @@ static const ILockBytesVtbl HGLOBALLockBytesImpl_Vtbl;
* The ILockBytes interface instance calls the GlobalReAlloc function to grow * The ILockBytes interface instance calls the GlobalReAlloc function to grow
* the memory block as required. * the memory block as required.
*/ */
HRESULT WINAPI CreateILockBytesOnHGlobal(HGLOBAL hGlobal, HRESULT WINAPI CreateILockBytesOnHGlobal(HGLOBAL global, BOOL delete_on_release, ILockBytes **ret)
BOOL fDeleteOnRelease,
LPLOCKBYTES* ppLkbyt)
{ {
HGLOBALLockBytesImpl* newLockBytes; HGLOBALLockBytesImpl* lockbytes;
newLockBytes = HGLOBALLockBytesImpl_Construct(hGlobal, fDeleteOnRelease); lockbytes = HeapAlloc(GetProcessHeap(), 0, sizeof(HGLOBALLockBytesImpl));
if (!lockbytes) return E_OUTOFMEMORY;
if (newLockBytes != NULL) lockbytes->ILockBytes_iface.lpVtbl = &HGLOBALLockBytesImpl_Vtbl;
{ lockbytes->ref = 1;
return IUnknown_QueryInterface((IUnknown*)newLockBytes,
&IID_ILockBytes,
(void**)ppLkbyt);
}
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 * 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; STATSTG stbuf;
HRESULT hres; HRESULT hres;
ULARGE_INTEGER start; ULARGE_INTEGER start;
ULONG xread; ULONG xread;
*phglobal = 0; *phglobal = 0;
if (pMemLockBytes->lpVtbl == &HGLOBALLockBytesImpl_Vtbl) { if (This->ILockBytes_iface.lpVtbl == &HGLOBALLockBytesImpl_Vtbl) {
*phglobal = pMemLockBytes->supportHandle; *phglobal = This->supportHandle;
if (*phglobal == 0) if (*phglobal == 0)
return E_INVALIDARG; return E_INVALIDARG;
return S_OK; return S_OK;
} }
/* It is not our lockbytes implementation, so use a more generic way */ /* 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) { if (hres != S_OK) {
ERR("Cannot ILockBytes_Stat, %x\n",hres); ERR("Cannot ILockBytes_Stat, %x\n",hres);
return hres; return hres;
@ -170,10 +171,10 @@ HRESULT WINAPI GetHGlobalFromILockBytes(ILockBytes* plkbyt, HGLOBAL* phglobal)
if (!*phglobal) if (!*phglobal)
return E_INVALIDARG; return E_INVALIDARG;
memset(&start,0,sizeof(start)); 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); GlobalUnlock(*phglobal);
if (hres != S_OK) { if (hres != S_OK) {
FIXME("%p->ReadAt failed with %x\n",plkbyt,hres); FIXME("%p->ReadAt failed with %x\n",iface,hres);
return hres; return hres;
} }
if (stbuf.cbSize.u.LowPart != xread) { 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 * This implements the IUnknown method QueryInterface for this
* class * class
@ -270,39 +198,22 @@ static HRESULT WINAPI HGLOBALLockBytesImpl_QueryInterface(
REFIID riid, /* [in] */ REFIID riid, /* [in] */
void** ppvObject) /* [iid_is][out] */ 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) if (ppvObject==0)
return E_INVALIDARG; return E_INVALIDARG;
/*
* Initialize the return parameter.
*/
*ppvObject = 0; *ppvObject = 0;
/*
* Compare the riid with the interface IDs implemented by this object.
*/
if (IsEqualIID(riid, &IID_IUnknown) || if (IsEqualIID(riid, &IID_IUnknown) ||
IsEqualIID(riid, &IID_ILockBytes)) IsEqualIID(riid, &IID_ILockBytes))
{ {
*ppvObject = This; *ppvObject = &This->ILockBytes_iface;
} }
else
/*
* Check that we obtained an interface.
*/
if ((*ppvObject)==0)
return E_NOINTERFACE; return E_NOINTERFACE;
/* ILockBytes_AddRef(iface);
* Query Interface always increases the reference count by one when it is
* successful
*/
IUnknown_AddRef(iface);
return S_OK; return S_OK;
} }
@ -313,7 +224,7 @@ static HRESULT WINAPI HGLOBALLockBytesImpl_QueryInterface(
*/ */
static ULONG WINAPI HGLOBALLockBytesImpl_AddRef(ILockBytes* iface) static ULONG WINAPI HGLOBALLockBytesImpl_AddRef(ILockBytes* iface)
{ {
HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface; HGLOBALLockBytesImpl* This = impl_from_ILockBytes(iface);
return InterlockedIncrement(&This->ref); return InterlockedIncrement(&This->ref);
} }
@ -323,17 +234,18 @@ static ULONG WINAPI HGLOBALLockBytesImpl_AddRef(ILockBytes* iface)
*/ */
static ULONG WINAPI HGLOBALLockBytesImpl_Release(ILockBytes* iface) static ULONG WINAPI HGLOBALLockBytesImpl_Release(ILockBytes* iface)
{ {
HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface; HGLOBALLockBytesImpl* This = impl_from_ILockBytes(iface);
ULONG ref; ULONG ref;
ref = InterlockedDecrement(&This->ref); ref = InterlockedDecrement(&This->ref);
if (!ref)
/*
* If the reference count goes down to 0, perform suicide.
*/
if (ref==0)
{ {
HGLOBALLockBytesImpl_Destroy(This); if (This->deleteOnRelease)
{
GlobalFree(This->supportHandle);
This->supportHandle = 0;
}
HeapFree(GetProcessHeap(), 0, This);
} }
return ref; return ref;
@ -354,7 +266,7 @@ static HRESULT WINAPI HGLOBALLockBytesImpl_ReadAt(
ULONG cb, /* [in] */ ULONG cb, /* [in] */
ULONG* pcbRead) /* [out] */ ULONG* pcbRead) /* [out] */
{ {
HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface; HGLOBALLockBytesImpl* This = impl_from_ILockBytes(iface);
void* supportBuffer; void* supportBuffer;
ULONG bytesReadBuffer = 0; ULONG bytesReadBuffer = 0;
@ -426,7 +338,7 @@ static HRESULT WINAPI HGLOBALLockBytesImpl_WriteAt(
ULONG cb, /* [in] */ ULONG cb, /* [in] */
ULONG* pcbWritten) /* [out] */ ULONG* pcbWritten) /* [out] */
{ {
HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface; HGLOBALLockBytesImpl* This = impl_from_ILockBytes(iface);
void* supportBuffer; void* supportBuffer;
ULARGE_INTEGER newSize; ULARGE_INTEGER newSize;
@ -455,7 +367,7 @@ static HRESULT WINAPI HGLOBALLockBytesImpl_WriteAt(
if (newSize.u.LowPart > This->byteArraySize.u.LowPart) if (newSize.u.LowPart > This->byteArraySize.u.LowPart)
{ {
/* grow stream */ /* grow stream */
if (HGLOBALLockBytesImpl_SetSize(iface, newSize) == STG_E_MEDIUMFULL) if (ILockBytes_SetSize(iface, newSize) == STG_E_MEDIUMFULL)
return STG_E_MEDIUMFULL; return STG_E_MEDIUMFULL;
} }
@ -500,7 +412,7 @@ static HRESULT WINAPI HGLOBALLockBytesImpl_SetSize(
ILockBytes* iface, ILockBytes* iface,
ULARGE_INTEGER libNewSize) /* [in] */ ULARGE_INTEGER libNewSize) /* [in] */
{ {
HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface; HGLOBALLockBytesImpl* This = impl_from_ILockBytes(iface);
HGLOBAL supportHandle; HGLOBAL supportHandle;
/* /*
@ -571,7 +483,7 @@ static HRESULT WINAPI HGLOBALLockBytesImpl_Stat(
STATSTG* pstatstg, /* [out] */ STATSTG* pstatstg, /* [out] */
DWORD grfStatFlag) /* [in] */ DWORD grfStatFlag) /* [in] */
{ {
HGLOBALLockBytesImpl* const This=(HGLOBALLockBytesImpl*)iface; HGLOBALLockBytesImpl* This = impl_from_ILockBytes(iface);
memset(pstatstg, 0, sizeof(STATSTG)); memset(pstatstg, 0, sizeof(STATSTG));