📄 hglobalstream.c
字号:
break;
case STREAM_SEEK_CUR:
newPosition = This->currentPosition;
break;
case STREAM_SEEK_END:
newPosition = This->streamSize;
break;
default:
return STG_E_INVALIDFUNCTION;
}
/*
* Move the actual file pointer
* If the file pointer ends-up after the end of the stream, the next Write operation will
* make the file larger. This is how it is documented.
*/
if (dlibMove.QuadPart < 0 && newPosition.QuadPart < -dlibMove.QuadPart) return STG_E_INVALIDFUNCTION;
newPosition.QuadPart = RtlLargeIntegerAdd(newPosition.QuadPart, dlibMove.QuadPart);
if (plibNewPosition) *plibNewPosition = newPosition;
This->currentPosition = newPosition;
return S_OK;
}
/***
* This method is part of the IStream interface.
*
* It will change the size of a stream.
*
* TODO: Switch from small blocks to big blocks and vice versa.
*
* See the documentation of IStream for more info.
*/
static HRESULT WINAPI HGLOBALStreamImpl_SetSize(
IStream* iface,
ULARGE_INTEGER libNewSize) /* [in] */
{
HGLOBALStreamImpl* const This=(HGLOBALStreamImpl*)iface;
HGLOBAL supportHandle;
TRACE("(%p, %d)\n", iface, libNewSize.u.LowPart);
/*
* HighPart is ignored as shown in tests
*/
if (This->streamSize.u.LowPart == libNewSize.u.LowPart)
return S_OK;
/*
* Re allocate the HGlobal to fit the new size of the stream.
*/
supportHandle = GlobalReAlloc(This->supportHandle, libNewSize.u.LowPart, 0);
if (supportHandle == 0)
return E_OUTOFMEMORY;
This->supportHandle = supportHandle;
This->streamSize.u.LowPart = libNewSize.u.LowPart;
return S_OK;
}
/***
* This method is part of the IStream interface.
*
* It will copy the 'cb' Bytes to 'pstm' IStream.
*
* See the documentation of IStream for more info.
*/
static HRESULT WINAPI HGLOBALStreamImpl_CopyTo(
IStream* iface,
IStream* pstm, /* [unique][in] */
ULARGE_INTEGER cb, /* [in] */
ULARGE_INTEGER* pcbRead, /* [out] */
ULARGE_INTEGER* pcbWritten) /* [out] */
{
HRESULT hr = S_OK;
BYTE tmpBuffer[128];
ULONG bytesRead, bytesWritten, copySize;
ULARGE_INTEGER totalBytesRead;
ULARGE_INTEGER totalBytesWritten;
TRACE("(%p, %p, %d, %p, %p)\n", iface, pstm,
cb.u.LowPart, pcbRead, pcbWritten);
/*
* Sanity check
*/
if ( pstm == 0 )
return STG_E_INVALIDPOINTER;
totalBytesRead.u.LowPart = totalBytesRead.u.HighPart = 0;
totalBytesWritten.u.LowPart = totalBytesWritten.u.HighPart = 0;
/*
* use stack to store data temporarly
* there is surely more performant way of doing it, for now this basic
* implementation will do the job
*/
while ( cb.u.LowPart > 0 )
{
if ( cb.u.LowPart >= 128 )
copySize = 128;
else
copySize = cb.u.LowPart;
hr = IStream_Read(iface, tmpBuffer, copySize, &bytesRead);
if (FAILED(hr))
break;
totalBytesRead.u.LowPart += bytesRead;
if (bytesRead)
{
hr = IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten);
if (FAILED(hr))
break;
totalBytesWritten.u.LowPart += bytesWritten;
}
if (bytesRead!=copySize)
cb.u.LowPart = 0;
else
cb.u.LowPart -= bytesRead;
}
/*
* Update number of bytes read and written
*/
if (pcbRead)
{
pcbRead->u.LowPart = totalBytesRead.u.LowPart;
pcbRead->u.HighPart = totalBytesRead.u.HighPart;
}
if (pcbWritten)
{
pcbWritten->u.LowPart = totalBytesWritten.u.LowPart;
pcbWritten->u.HighPart = totalBytesWritten.u.HighPart;
}
return hr;
}
/***
* This method is part of the IStream interface.
*
* For streams supported by HGLOBALS, this function does nothing.
* This is what the documentation tells us.
*
* See the documentation of IStream for more info.
*/
static HRESULT WINAPI HGLOBALStreamImpl_Commit(
IStream* iface,
DWORD grfCommitFlags) /* [in] */
{
return S_OK;
}
/***
* This method is part of the IStream interface.
*
* For streams supported by HGLOBALS, this function does nothing.
* This is what the documentation tells us.
*
* See the documentation of IStream for more info.
*/
static HRESULT WINAPI HGLOBALStreamImpl_Revert(
IStream* iface)
{
return S_OK;
}
/***
* This method is part of the IStream interface.
*
* For streams supported by HGLOBALS, this function does nothing.
* This is what the documentation tells us.
*
* See the documentation of IStream for more info.
*/
static HRESULT WINAPI HGLOBALStreamImpl_LockRegion(
IStream* iface,
ULARGE_INTEGER libOffset, /* [in] */
ULARGE_INTEGER cb, /* [in] */
DWORD dwLockType) /* [in] */
{
return STG_E_INVALIDFUNCTION;
}
/*
* This method is part of the IStream interface.
*
* For streams supported by HGLOBALS, this function does nothing.
* This is what the documentation tells us.
*
* See the documentation of IStream for more info.
*/
static HRESULT WINAPI HGLOBALStreamImpl_UnlockRegion(
IStream* iface,
ULARGE_INTEGER libOffset, /* [in] */
ULARGE_INTEGER cb, /* [in] */
DWORD dwLockType) /* [in] */
{
return S_OK;
}
/***
* This method is part of the IStream interface.
*
* This method returns information about the current
* stream.
*
* See the documentation of IStream for more info.
*/
static HRESULT WINAPI HGLOBALStreamImpl_Stat(
IStream* iface,
STATSTG* pstatstg, /* [out] */
DWORD grfStatFlag) /* [in] */
{
HGLOBALStreamImpl* const This=(HGLOBALStreamImpl*)iface;
memset(pstatstg, 0, sizeof(STATSTG));
pstatstg->pwcsName = NULL;
pstatstg->type = STGTY_STREAM;
pstatstg->cbSize = This->streamSize;
return S_OK;
}
static HRESULT WINAPI HGLOBALStreamImpl_Clone(
IStream* iface,
IStream** ppstm) /* [out] */
{
ULARGE_INTEGER dummy;
LARGE_INTEGER offset;
HRESULT hr;
HGLOBALStreamImpl* const This=(HGLOBALStreamImpl*)iface;
TRACE(" Cloning %p (deleteOnRelease=%d seek position=%ld)\n",iface,This->deleteOnRelease,(long)This->currentPosition.QuadPart);
hr=CreateStreamOnHGlobal(This->supportHandle, FALSE, ppstm);
if(FAILED(hr))
return hr;
offset.QuadPart=(LONGLONG)This->currentPosition.QuadPart;
HGLOBALStreamImpl_Seek(*ppstm,offset,STREAM_SEEK_SET,&dummy);
return S_OK;
}
/*
* Virtual function table for the HGLOBALStreamImpl class.
*/
static const IStreamVtbl HGLOBALStreamImpl_Vtbl =
{
HGLOBALStreamImpl_QueryInterface,
HGLOBALStreamImpl_AddRef,
HGLOBALStreamImpl_Release,
HGLOBALStreamImpl_Read,
HGLOBALStreamImpl_Write,
HGLOBALStreamImpl_Seek,
HGLOBALStreamImpl_SetSize,
HGLOBALStreamImpl_CopyTo,
HGLOBALStreamImpl_Commit,
HGLOBALStreamImpl_Revert,
HGLOBALStreamImpl_LockRegion,
HGLOBALStreamImpl_UnlockRegion,
HGLOBALStreamImpl_Stat,
HGLOBALStreamImpl_Clone
};
/******************************************************************************
** HGLOBALStreamImpl implementation
*/
/***
* This is the constructor for the HGLOBALStreamImpl class.
*
* Params:
* hGlobal - Handle that will support the stream. can be NULL.
* fDeleteOnRelease - Flag set to TRUE if the HGLOBAL will be released
* when the IStream object is destroyed.
*/
static HGLOBALStreamImpl* HGLOBALStreamImpl_Construct(
HGLOBAL hGlobal,
BOOL fDeleteOnRelease)
{
HGLOBALStreamImpl* newStream;
newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(HGLOBALStreamImpl));
if (newStream!=0)
{
/*
* Set-up the virtual function table and reference count.
*/
newStream->lpVtbl = &HGLOBALStreamImpl_Vtbl;
newStream->ref = 0;
/*
* Initialize the support.
*/
newStream->supportHandle = hGlobal;
newStream->deleteOnRelease = fDeleteOnRelease;
/*
* This method will allocate a handle if one is not supplied.
*/
if (!newStream->supportHandle)
{
newStream->supportHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD |
GMEM_SHARE, 0);
}
/*
* Start the stream at the beginning.
*/
newStream->currentPosition.u.HighPart = 0;
newStream->currentPosition.u.LowPart = 0;
/*
* Initialize the size of the stream to the size of the handle.
*/
newStream->streamSize.u.HighPart = 0;
newStream->streamSize.u.LowPart = GlobalSize(newStream->supportHandle);
}
return newStream;
}
/***********************************************************************
* CreateStreamOnHGlobal [OLE32.@]
*/
HRESULT WINAPI CreateStreamOnHGlobal(
HGLOBAL hGlobal,
BOOL fDeleteOnRelease,
LPSTREAM* ppstm)
{
HGLOBALStreamImpl* newStream;
newStream = HGLOBALStreamImpl_Construct(hGlobal,
fDeleteOnRelease);
if (newStream!=NULL)
{
return IUnknown_QueryInterface((IUnknown*)newStream,
&IID_IStream,
(void**)ppstm);
}
return E_OUTOFMEMORY;
}
/***********************************************************************
* GetHGlobalFromStream [OLE32.@]
*/
HRESULT WINAPI GetHGlobalFromStream(IStream* pstm, HGLOBAL* phglobal)
{
HGLOBALStreamImpl* pStream;
if (pstm == NULL)
return E_INVALIDARG;
pStream = (HGLOBALStreamImpl*) pstm;
/*
* Verify that the stream object was created with CreateStreamOnHGlobal.
*/
if (pStream->lpVtbl == &HGLOBALStreamImpl_Vtbl)
*phglobal = pStream->supportHandle;
else
{
*phglobal = 0;
return E_INVALIDARG;
}
return S_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -