/*
 *	this class implements a pure IStream object
 *	and can be used for many purposes
 *
 *	the main reason for implementing this was
 *	a cleaner implementation of IShellLink which
 *	needs to be able to load lnk's from a IStream
 *	interface so it was obvious to capsule the file
 *	access in a IStream to.
 */

#include <string.h>

#include "winbase.h"
#include "winerror.h"
#include "shlobj.h"
#include "debugtools.h"
#include "shell32_main.h"

DEFAULT_DEBUG_CHANNEL(shell);

static HRESULT WINAPI IStream_fnQueryInterface(IStream *iface, REFIID riid, LPVOID *ppvObj);
static ULONG WINAPI IStream_fnAddRef(IStream *iface);
static ULONG WINAPI IStream_fnRelease(IStream *iface);
static HRESULT WINAPI IStream_fnRead (IStream * iface, void* pv, ULONG cb, ULONG* pcbRead);
static HRESULT WINAPI IStream_fnWrite (IStream * iface, const void* pv, ULONG cb, ULONG* pcbWritten);
static HRESULT WINAPI IStream_fnSeek (IStream * iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition);
static HRESULT WINAPI IStream_fnSetSize (IStream * iface, ULARGE_INTEGER libNewSize);
static HRESULT WINAPI IStream_fnCopyTo (IStream * iface, IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten);
static HRESULT WINAPI IStream_fnCommit (IStream * iface, DWORD grfCommitFlags);
static HRESULT WINAPI IStream_fnRevert (IStream * iface);
static HRESULT WINAPI IStream_fnLockRegion (IStream * iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType);
static HRESULT WINAPI IStream_fnUnlockRegion (IStream * iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType);
static HRESULT WINAPI IStream_fnStat (IStream * iface, STATSTG*   pstatstg, DWORD grfStatFlag);
static HRESULT WINAPI IStream_fnClone (IStream * iface, IStream** ppstm);

static ICOM_VTABLE(IStream) stvt = 
{	
	ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
	IStream_fnQueryInterface,
	IStream_fnAddRef,
	IStream_fnRelease,
	IStream_fnRead,
	IStream_fnWrite,
	IStream_fnSeek,
	IStream_fnSetSize,
	IStream_fnCopyTo,
	IStream_fnCommit,
	IStream_fnRevert,
	IStream_fnLockRegion,
	IStream_fnUnlockRegion,
	IStream_fnStat,
	IStream_fnClone
	
};

typedef struct 
{	ICOM_VTABLE(IStream)	*lpvtst;
	DWORD		ref;
	LPBYTE		pImage;
	HANDLE		hMapping;
	DWORD		dwLength;
	DWORD		dwPos;
} ISHFileStream;

/**************************************************************************
 *   CreateStreamOnFile()
 *
 *   similar to CreateStreamOnHGlobal
 */
HRESULT CreateStreamOnFile (LPCSTR pszFilename, IStream ** ppstm)
{
	ISHFileStream*	fstr;
	OFSTRUCT	ofs;
	HFILE		hFile = OpenFile( pszFilename, &ofs, OF_READ );
	HRESULT		ret = E_FAIL;
	
	fstr = (ISHFileStream*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ISHFileStream));
	fstr->lpvtst=&stvt;
	fstr->ref = 1;
	fstr->dwLength = GetFileSize (hFile, NULL);

	shell32_ObjCount++;

	if (!(fstr->hMapping = CreateFileMappingA(hFile,NULL,PAGE_READONLY|SEC_COMMIT,0,0,NULL)))
	{
	  WARN("failed to create filemap.\n");
	  goto end_2;
	}

	if (!(fstr->pImage = MapViewOfFile(fstr->hMapping,FILE_MAP_READ,0,0,0)))
	{
	  WARN("failed to mmap filemap.\n");
	  goto end_3;
	}

	ret = S_OK;
	goto end_1;
	
end_3:	CloseHandle(fstr->hMapping);
end_2:	HeapFree(GetProcessHeap(), 0, fstr);
	fstr = NULL;

end_1:	_lclose(hFile);
	(*ppstm) = (IStream*)fstr;
	return ret;
}

/**************************************************************************
*  IStream_fnQueryInterface
*/
static HRESULT WINAPI IStream_fnQueryInterface(IStream *iface, REFIID riid, LPVOID *ppvObj)
{
	ICOM_THIS(ISHFileStream, iface);

	TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);

	*ppvObj = NULL;

	if(IsEqualIID(riid, &IID_IUnknown) ||
	   IsEqualIID(riid, &IID_IStream))
	{
	  *ppvObj = This;
	}

	if(*ppvObj)
	{ 
	  IStream_AddRef((IStream*)*ppvObj);      
	  TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
	  return S_OK;
	}
	TRACE("-- Interface: E_NOINTERFACE\n");
	return E_NOINTERFACE;
}

/**************************************************************************
*  IStream_fnAddRef
*/
static ULONG WINAPI IStream_fnAddRef(IStream *iface)
{
	ICOM_THIS(ISHFileStream, iface);

	TRACE("(%p)->(count=%lu)\n",This, This->ref);

	shell32_ObjCount++;
	return ++(This->ref);
}

/**************************************************************************
*  IStream_fnRelease
*/
static ULONG WINAPI IStream_fnRelease(IStream *iface)
{
	ICOM_THIS(ISHFileStream, iface);

	TRACE("(%p)->()\n",This);

	shell32_ObjCount--;

	if (!--(This->ref)) 
	{ TRACE(" destroying SHFileStream (%p)\n",This);

	  UnmapViewOfFile(This->pImage);
	  CloseHandle(This->hMapping);

	  HeapFree(GetProcessHeap(),0,This);
	  return 0;
	}
	return This->ref;
}

static HRESULT WINAPI IStream_fnRead (IStream * iface, void* pv, ULONG cb, ULONG* pcbRead)
{
	ICOM_THIS(ISHFileStream, iface);

	DWORD dwBytesToRead, dwBytesLeft;
	
	TRACE("(%p)->(%p,0x%08lx,%p)\n",This, pv, cb, pcbRead);
	
	if ( !pv )
	  return STG_E_INVALIDPOINTER;

	dwBytesLeft = This->dwLength - This->dwPos;

	if ( 0 >= dwBytesLeft )						/* end of buffer */
	  return S_FALSE;
	
	dwBytesToRead = ( cb > dwBytesLeft) ? dwBytesLeft : cb;

	memmove ( pv, (This->pImage) + (This->dwPos), dwBytesToRead);
	
	This->dwPos += dwBytesToRead;					/* adjust pointer */

	if (pcbRead)
	  *pcbRead = dwBytesToRead;

	return S_OK;
}
static HRESULT WINAPI IStream_fnWrite (IStream * iface, const void* pv, ULONG cb, ULONG* pcbWritten)
{
	ICOM_THIS(ISHFileStream, iface);

	TRACE("(%p)\n",This);

	return E_NOTIMPL;
}
static HRESULT WINAPI IStream_fnSeek (IStream * iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition)
{
	ICOM_THIS(ISHFileStream, iface);

	TRACE("(%p)\n",This);

	return E_NOTIMPL;
}
static HRESULT WINAPI IStream_fnSetSize (IStream * iface, ULARGE_INTEGER libNewSize)
{
	ICOM_THIS(ISHFileStream, iface);

	TRACE("(%p)\n",This);

	return E_NOTIMPL;
}
static HRESULT WINAPI IStream_fnCopyTo (IStream * iface, IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten)
{
	ICOM_THIS(ISHFileStream, iface);

	TRACE("(%p)\n",This);

	return E_NOTIMPL;
}
static HRESULT WINAPI IStream_fnCommit (IStream * iface, DWORD grfCommitFlags)
{
	ICOM_THIS(ISHFileStream, iface);

	TRACE("(%p)\n",This);

	return E_NOTIMPL;
}
static HRESULT WINAPI IStream_fnRevert (IStream * iface)
{
	ICOM_THIS(ISHFileStream, iface);

	TRACE("(%p)\n",This);

	return E_NOTIMPL;
}
static HRESULT WINAPI IStream_fnLockRegion (IStream * iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
{
	ICOM_THIS(ISHFileStream, iface);

	TRACE("(%p)\n",This);

	return E_NOTIMPL;
}
static HRESULT WINAPI IStream_fnUnlockRegion (IStream * iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
{
	ICOM_THIS(ISHFileStream, iface);

	TRACE("(%p)\n",This);

	return E_NOTIMPL;
}
static HRESULT WINAPI IStream_fnStat (IStream * iface, STATSTG*   pstatstg, DWORD grfStatFlag)
{
	ICOM_THIS(ISHFileStream, iface);

	TRACE("(%p)\n",This);

	return E_NOTIMPL;
}
static HRESULT WINAPI IStream_fnClone (IStream * iface, IStream** ppstm)
{
	ICOM_THIS(ISHFileStream, iface);

	TRACE("(%p)\n",This);

	return E_NOTIMPL;
}
