summaryrefslogtreecommitdiffstats
path: root/private/ole32/ole232/util/utstream.cpp
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ole32/ole232/util/utstream.cpp
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ole32/ole232/util/utstream.cpp')
-rw-r--r--private/ole32/ole232/util/utstream.cpp986
1 files changed, 986 insertions, 0 deletions
diff --git a/private/ole32/ole232/util/utstream.cpp b/private/ole32/ole232/util/utstream.cpp
new file mode 100644
index 000000000..155278c89
--- /dev/null
+++ b/private/ole32/ole232/util/utstream.cpp
@@ -0,0 +1,986 @@
+
+//+----------------------------------------------------------------------------
+//
+// File:
+// utstream.cpp
+//
+// Contents:
+// Ole stream utilities
+//
+// Classes:
+//
+// Functions:
+//
+// History:
+// 10-May-94 KevinRo Added ansi versions of StringStream stuff
+// 25-Jan-94 alexgo first pass at converting to Cairo-style
+// memory allocations.
+// 01/11/94 - alexgo - added VDATEHEAP macros to every function
+// 12/07/93 - ChrisWe - file inspection and cleanup; fixed
+// String reading and writing to cope with OLESTR, and
+// with differing alignment requirements
+// 06/23/93 - SriniK - moved ReadStringStream(),
+// WriteStringStream(), and OpenOrCreateStream() here
+// from api.cpp and ole2.cpp
+// 03/14/92 - SriniK - created
+//
+//-----------------------------------------------------------------------------
+
+#include <le2int.h>
+#pragma SEG(utstream)
+
+#include <reterr.h>
+#include <limits.h>
+
+NAME_SEG(UtStream)
+ASSERTDATA
+
+// this constant is used to size string buffers when we attempt to write out
+// a string and its length in one write call
+#define UTSTRINGBUF_SIZE 100
+
+// REVIEW, I thought that OpenStream already had an option to do this. If
+// so, this function shouldn't be used in our code. But we can't remove it
+// because it is exported to the outside.
+// this is exported to the outside
+#pragma SEG(OpenOrCreateStream)
+STDAPI OpenOrCreateStream(IStorage FAR * pstg, LPCOLESTR pwcsName,
+ IStream FAR* FAR* ppstm)
+{
+ VDATEHEAP();
+
+ HRESULT error;
+
+ error = pstg->CreateStream(pwcsName, STGM_SALL | STGM_FAILIFTHERE,
+ 0, 0, ppstm);
+ if (GetScode(error) == STG_E_FILEALREADYEXISTS)
+ error = pstg->OpenStream(pwcsName, NULL, STGM_SALL, 0, ppstm);
+
+ return(error);
+}
+
+// returns S_OK when string read and allocated (even if zero length)
+STDAPI ReadStringStream(CStmBufRead & StmRead, LPOLESTR FAR * ppsz)
+{
+ VDATEHEAP();
+
+ ULONG cb; // the length of the string in *bytes* (NOT CHARACTERS)
+ HRESULT hresult;
+
+ // initialize the the string pointer for error returns
+ *ppsz = NULL;
+
+ if ((hresult = StmRead.Read((void FAR *)&cb, sizeof(ULONG))) != NOERROR)
+ return hresult;
+
+ // is string empty?
+ if (cb == 0)
+ return(NOERROR);
+
+ // allocate memory to hold the string
+ if (!(*ppsz = (LPOLESTR)PubMemAlloc(cb)))
+ return(ReportResult(0, E_OUTOFMEMORY, 0, 0));
+
+ // read the string; this includes a trailing NULL
+ if ((hresult = StmRead.Read((void FAR *)(*ppsz), cb)) != NOERROR)
+ goto errRtn;
+
+ return(NOERROR);
+
+errRtn:
+ // delete the string, and return without one
+ PubMemFree(*ppsz);
+ *ppsz = NULL;
+ return(hresult);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ReadStringStreamA
+//
+// Synopsis: Read a ANSI stream from the stream
+//
+// Effects:
+//
+// Arguments: [pstm] -- Stream to read from
+// [ppsz] -- Output pointer
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-12-94 kevinro Created
+// 2-20-95 KentCe Converted to buffer stream reads.
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI ReadStringStreamA(CStmBufRead & StmRead, LPSTR FAR * ppsz)
+{
+ VDATEHEAP();
+
+ ULONG cb; // the length of the string in *bytes* (NOT CHARACTERS)
+ HRESULT hresult;
+
+ // initialize the the string pointer for error returns
+ *ppsz = NULL;
+
+ if ((hresult = StmRead.Read((void FAR *)&cb, sizeof(ULONG))) != NOERROR)
+ return hresult;
+
+ // is string empty?
+ if (cb == 0)
+ return(NOERROR);
+
+ // allocate memory to hold the string
+ if (!(*ppsz = (LPSTR)PubMemAlloc(cb)))
+ return(ReportResult(0, E_OUTOFMEMORY, 0, 0));
+
+ // read the string; this includes a trailing NULL
+ if ((hresult = StmRead.Read((void FAR *)(*ppsz), cb)) != NOERROR)
+ goto errRtn;
+
+ return(NOERROR);
+
+errRtn:
+ // delete the string, and return without one
+ PubMemFree(*ppsz);
+ *ppsz = NULL;
+ return(hresult);
+}
+
+
+// this is exported to the outside
+STDAPI WriteStringStream(CStmBufWrite & StmWrite, LPCOLESTR psz)
+{
+ VDATEHEAP();
+
+ HRESULT error;
+ ULONG cb; // the count of bytes (NOT CHARACTERS) to write to the stream
+
+ // if the string pointer is NULL, use zero length
+ if (!psz)
+ cb = 0;
+ else
+ {
+ // count is length of string, plus terminating null
+ cb = (1 + _xstrlen(psz))*sizeof(OLECHAR);
+
+ // if possible, do a single write instead of two
+
+ if (cb <= UTSTRINGBUF_SIZE)
+ {
+ BYTE bBuf[sizeof(ULONG)+
+ UTSTRINGBUF_SIZE*sizeof(OLECHAR)];
+ // buffer for count and string
+
+ // we have to use _xmemcpy to copy the length into
+ // the buffer to avoid potential boundary faults,
+ // since bBuf might not be aligned strictly enough
+ // to do *((ULONG FAR *)bBuf) = cb;
+ _xmemcpy((void FAR *)bBuf, (const void FAR *)&cb,
+ sizeof(cb));
+ _xmemcpy((void FAR *)(bBuf+sizeof(cb)),
+ (const void FAR *)psz, cb);
+
+ // write contents of buffer all at once
+ return( StmWrite.Write((VOID FAR *)bBuf,
+ cb+sizeof(ULONG)));
+ }
+ }
+
+ // if we got here, our buffer isn't large enough, so we do two writes
+ // first, write the length
+ if (error = StmWrite.Write((VOID FAR *)&cb, sizeof(ULONG)))
+ return error;
+
+ // are we are done writing the string?
+ if (psz == NULL)
+ return NOERROR;
+
+ // write the string
+ return(StmWrite.Write((VOID FAR *)psz, cb));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteStringStreamA
+//
+// Synopsis: Writes an ANSI string to a stream in a length prefixed format.
+//
+// Effects:
+//
+// Arguments: [pstm] -- Stream
+// [psz] -- Ansi string to write
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-12-94 kevinro Created
+// 2-20-95 KentCe Converted to buffer stream writes.
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+FARINTERNAL_(HRESULT) WriteStringStreamA(CStmBufWrite & StmWrite, LPCSTR psz)
+{
+ VDATEHEAP();
+
+ HRESULT error;
+ ULONG cb; // the count of bytes (NOT CHARACTERS) to write to the stream
+
+ // if the string pointer is NULL, use zero length
+ if (!psz)
+ cb = 0;
+ else
+ {
+ // count is length of string, plus terminating null
+ cb = (1 + strlen(psz));
+
+ // if possible, do a single write instead of two
+
+ if (cb <= UTSTRINGBUF_SIZE)
+ {
+ BYTE bBuf[sizeof(ULONG)+
+ UTSTRINGBUF_SIZE];
+ // buffer for count and string
+
+ // we have to use _xmemcpy to copy the length into
+ // the buffer to avoid potential boundary faults,
+ // since bBuf might not be aligned strictly enough
+ // to do *((ULONG FAR *)bBuf) = cb;
+ _xmemcpy((void FAR *)bBuf, (const void FAR *)&cb,
+ sizeof(cb));
+ _xmemcpy((void FAR *)(bBuf+sizeof(cb)),
+ (const void FAR *)psz, cb);
+
+ // write contents of buffer all at once
+ return(StmWrite.Write((VOID FAR *)bBuf,
+ cb+sizeof(ULONG)));
+ }
+ }
+
+ // if we got here, our buffer isn't large enough, so we do two writes
+ // first, write the length
+ if (error = StmWrite.Write((VOID FAR *)&cb, sizeof(ULONG)))
+ return error;
+
+ // are we are done writing the string?
+ if (psz == NULL)
+ return NOERROR;
+
+ // write the string
+ return(StmWrite.Write((VOID FAR *)psz, cb));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: StRead
+//
+// Synopsis: Stream read that only succeeds if all requested bytes read
+//
+// Arguments: [pStm] -- source stream
+// [pvBuffer] -- destination buffer
+// [ulcb] -- bytes to read
+//
+// Returns: S_OK if successful, else error code
+//
+// Algorithm:
+//
+// History: 18-May-94 AlexT Added header block, fixed S_FALSE case
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(StRead)
+FARINTERNAL_(HRESULT) StRead(IStream FAR * pStm, LPVOID pvBuffer, ULONG ulcb)
+{
+ VDATEHEAP();
+
+ HRESULT hr;
+ ULONG cbRead;
+
+ hr = pStm->Read(pvBuffer, ulcb, &cbRead);
+ if (FAILED(hr))
+ {
+ return(hr);
+ }
+
+ if (ulcb == cbRead)
+ {
+ return(S_OK);
+ }
+
+ // We got a success code but not enough bytes - turn it into an error
+
+ return(STG_E_READFAULT);
+}
+
+
+// if fRelative is FALSE then dwSize is the size of the stream
+// if it is TRUE then find the current seek position and add dwSize to that
+// and then set it as the stream size.
+FARINTERNAL StSetSize(LPSTREAM pstm, DWORD dwSize, BOOL fRelative)
+{
+ VDATEHEAP();
+
+ LARGE_INTEGER large_int; // indicates where to seek to
+ ULARGE_INTEGER ularge_int; // indicates absolute position
+ ULARGE_INTEGER ularge_integer; // the size we will set for the stream
+ HRESULT error;
+
+ LISet32(large_int, 0);
+ ULISet32(ularge_integer, dwSize);
+
+ if (fRelative)
+ {
+ if (error = pstm->Seek(large_int, STREAM_SEEK_CUR, &ularge_int))
+ return(error);
+
+ // REVIEW: is there a routine to do 64 bit addition ???
+ ularge_integer.LowPart += ularge_int.LowPart;
+ }
+
+ return(pstm->SetSize(ularge_integer));
+}
+
+
+// REVIEW, is this actually used?
+#pragma SEG(StSave10NativeData)
+FARINTERNAL_(HRESULT) StSave10NativeData(IStorage FAR* pstgSave,
+ HANDLE hNative, BOOL fIsOle1Interop)
+{
+ VDATEHEAP();
+
+ DWORD dwSize;
+ HRESULT error;
+
+ if (!hNative)
+ return ReportResult(0, E_UNSPEC, 0, 0);
+
+ if (!(dwSize = GlobalSize (hNative)))
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+
+#ifdef OLE1INTEROP
+ if ( fIsOle1Interop )
+ {
+ LPLOCKBYTES plkbyt;
+ LPSTORAGE pstgNative= NULL;
+ const DWORD grfStg = STGM_READWRITE | STGM_SHARE_EXCLUSIVE
+ | STGM_DIRECT ;
+
+ if ((error = CreateILockBytesOnHGlobal (hNative, FALSE, &plkbyt))!=NOERROR)
+ goto errRtn;
+
+ if ((error = StgOpenStorageOnILockBytes (plkbyt, (LPSTORAGE)NULL, grfStg,
+ (SNB)NULL, 0, &pstgNative)) != NOERROR){
+ error = ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ plkbyt->Release();
+ goto errRtn;
+ }
+
+ pstgNative->CopyTo (0, NULL, 0, pstgSave);
+ plkbyt->Release();
+ pstgNative->Release();
+ }
+ else
+#endif
+ {
+ LPSTREAM lpstream = NULL;
+
+ if (error = OpenOrCreateStream(pstgSave, OLE10_NATIVE_STREAM, &lpstream))
+ goto errRtn;
+
+ if (error = StWrite(lpstream, &dwSize, sizeof(DWORD))) {
+ lpstream->Release();
+ goto errRtn;
+ }
+
+ error = UtHGLOBALtoStm(hNative, dwSize, lpstream);
+
+ lpstream->Release();
+ }
+
+errRtn:
+ return error;
+}
+
+
+
+#pragma SEG(StSave10ItemName)
+FARINTERNAL StSave10ItemName
+ (IStorage FAR* pstg,
+ LPCSTR szItemNameAnsi)
+{
+ VDATEHEAP();
+
+ CStmBufWrite StmWrite;
+ HRESULT hresult;
+
+
+ if ((hresult = StmWrite.OpenOrCreateStream(pstg, OLE10_ITEMNAME_STREAM))
+ != NOERROR)
+ {
+ return hresult;
+ }
+
+ hresult = WriteStringStreamA(StmWrite, szItemNameAnsi);
+ if (FAILED(hresult))
+ {
+ goto errRtn;
+ }
+
+ hresult = StmWrite.Flush();
+
+errRtn:
+ StmWrite.Release();
+
+ return hresult;
+}
+
+
+#pragma SEG(StRead10NativeData)
+FARINTERNAL StRead10NativeData
+ (IStorage FAR* pstg,
+ HANDLE FAR* phNative)
+{
+ VDATEHEAP();
+
+ DWORD dwSize;
+ LPSTREAM pstream = NULL;
+ HRESULT hresult;
+
+ *phNative = NULL;
+
+ RetErr (pstg->OpenStream (OLE10_NATIVE_STREAM, NULL, STGM_SALL, 0, &pstream));
+ ErrRtnH (StRead (pstream, &dwSize, sizeof (DWORD)));
+
+ ErrRtnH (UtGetHGLOBALFromStm(pstream, dwSize, phNative));
+
+errRtn:
+ if (pstream)
+ pstream->Release();
+ return hresult;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStmBuf::CStmBuf, public
+//
+// Synopsis: Constructor.
+//
+// Arguments: None.
+//
+// Returns: None.
+//
+// History: 20-Feb-95 KentCe Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+CStmBuf::CStmBuf(void)
+{
+ m_pStm = NULL;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStmBuf::~CStmBuf, public
+//
+// Synopsis: Destructor.
+//
+// Arguments: None.
+//
+// Returns: None.
+//
+// History: 20-Feb-95 KentCe Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+CStmBuf::~CStmBuf(void)
+{
+ //
+ // Verify that the programmer released the stream interface.
+ //
+ Assert(m_pStm == NULL);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStmBufRead::Init, public
+//
+// Synopsis: Define the stream interface to read from.
+//
+// Arguments: [pstm] -- Pointer to stream to read.
+//
+// Returns: None.
+//
+// History: 20-Feb-95 KentCe Created
+//
+// Notes: Release method must be called.
+//
+//----------------------------------------------------------------------------
+void CStmBufRead::Init(IStream * pstm)
+{
+ Assert(m_pStm == NULL);
+
+ m_pStm = pstm;
+
+ m_pStm->AddRef();
+
+ Reset();
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStmBufRead::OpenStream, public
+//
+// Synopsis: Open a stream for reading.
+//
+// Arguments: [pstg] -- Pointer to storage that contains stream to open.
+// [pwcsName] -- Name of stream to open.
+//
+// Returns: HRESULT.
+//
+// History: 20-Feb-95 KentCe Created
+//
+// Notes: Release method must be called.
+//
+//----------------------------------------------------------------------------
+HRESULT CStmBufRead::OpenStream(IStorage * pstg, const OLECHAR * pwcsName)
+{
+ VDATEHEAP();
+ HRESULT hr;
+
+
+ Assert(m_pStm == NULL);
+
+ hr = pstg->OpenStream(pwcsName, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0,
+ &m_pStm);
+
+ Reset();
+
+ return hr;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStmBufRead::Read, public
+//
+// Synopsis: Read data from the stream.
+//
+// Arguments: [pBuf] - Address to store read bytes in.
+// [cBuf] - Maximum number of bytes to read.
+//
+// Returns: HRESULT.
+//
+// History: 20-Feb-95 KentCe Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT CStmBufRead::Read(PVOID pBuf, ULONG cBuf)
+{
+ ULONG cnt;
+ HRESULT hr;
+
+
+ //
+ // While more bytes to read.
+ //
+ while (cBuf)
+ {
+ //
+ // If our buffer is empty, read more data.
+ //
+ if (m_cBuffer == 0)
+ {
+ hr = m_pStm->Read(m_aBuffer, sizeof(m_aBuffer), &m_cBuffer);
+ if (FAILED(hr))
+ return hr;
+
+ if (m_cBuffer == 0)
+ return STG_E_READFAULT;
+
+ m_pBuffer = m_aBuffer;
+ }
+
+ //
+ // Determine number of bytes to read.
+ //
+ cnt = min(m_cBuffer, cBuf);
+
+ //
+ // Copy the input from the input buffer, update variables.
+ //
+ memcpy(pBuf, m_pBuffer, cnt);
+ pBuf = (PBYTE)pBuf + cnt;
+ cBuf -= cnt;
+ m_pBuffer += cnt;
+ m_cBuffer -= cnt;
+ }
+
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStmBufRead::ReadLong, public
+//
+// Synopsis: Read a long value from the stream.
+//
+// Arguments: [plValue] - Address of long to fill.
+//
+// Returns: HRESULT.
+//
+// History: 20-Feb-95 KentCe Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT CStmBufRead::ReadLong(LONG * plValue)
+{
+ return Read(plValue, sizeof(LONG));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStmBufRead::Reset
+//
+// Synopsis: Reset buffer variables.
+//
+// Arguments: None.
+//
+// Returns: None.
+//
+// History: 20-Feb-95 KentCe Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void CStmBufRead::Reset(void)
+{
+ m_pBuffer = m_aBuffer;
+ m_cBuffer = 0;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStmBufRead::Release, public
+//
+// Synopsis: Release read stream interface.
+//
+// Arguments: None.
+//
+// Returns: None.
+//
+// History: 20-Feb-95 KentCe Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void CStmBufRead::Release()
+{
+ if (m_pStm)
+ {
+ m_pStm->Release();
+ m_pStm = NULL;
+ }
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStmBufWrite::Init, public
+//
+// Synopsis: Define the stream interface to write to.
+//
+// Arguments: [pstm] -- Pointer to stream to write.
+//
+// Returns: None.
+//
+// History: 20-Feb-95 KentCe Created
+//
+// Notes: Release method must be called.
+//
+//----------------------------------------------------------------------------
+void CStmBufWrite::Init(IStream * pstm)
+{
+ Assert(m_pStm == NULL);
+
+ m_pStm = pstm;
+
+ m_pStm->AddRef();
+
+ Reset();
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStmBufRead::OpenOrCreateStream, public
+//
+// Synopsis: Open/Create a stream for writing.
+//
+// Arguments: [pstg] -- Pointer to storage that contains stream to open.
+// [pwcsName] -- Name of stream to open.
+//
+// Returns: HRESULT.
+//
+// History: 20-Feb-95 KentCe Created
+//
+// Notes: Release method must be called.
+//
+//----------------------------------------------------------------------------
+HRESULT CStmBufWrite::OpenOrCreateStream(IStorage * pstg,
+ const OLECHAR * pwcsName)
+{
+ VDATEHEAP();
+ HRESULT hr;
+
+
+ hr = pstg->CreateStream(pwcsName, STGM_SALL | STGM_FAILIFTHERE, 0, 0,
+ &m_pStm);
+
+ if (hr == STG_E_FILEALREADYEXISTS)
+ {
+ hr = pstg->OpenStream(pwcsName, NULL, STGM_SALL, 0, &m_pStm);
+ }
+
+ Reset();
+
+ return hr;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStmBufRead::CreateStream, public
+//
+// Synopsis: Create a stream for writing.
+//
+// Arguments: [pstg] -- Pointer storage that contains stream to create.
+// [pwcsName] -- Name of stream to create.
+//
+// Returns: HRESULT.
+//
+// History: 20-Feb-95 KentCe Created
+//
+// Notes: Release method must be called.
+//
+//----------------------------------------------------------------------------
+HRESULT CStmBufWrite::CreateStream(IStorage * pstg, const OLECHAR * pwcsName)
+{
+ VDATEHEAP();
+
+ HRESULT hr;
+
+
+ hr = pstg->CreateStream(pwcsName, STGM_CREATE | STGM_READWRITE |
+ STGM_SHARE_EXCLUSIVE, 0, 0, &m_pStm);
+
+ Reset();
+
+ return hr;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStmBufWrite::Write, public
+//
+// Synopsis: Write data to the stream.
+//
+// Arguments: [pBuf] - Address to store write bytes to.
+// [cBuf] - Maximum number of bytes to write.
+//
+// Returns: HRESULT.
+//
+// History: 20-Feb-95 KentCe Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT CStmBufWrite::Write(void const * pBuf, ULONG cBuf)
+{
+ ULONG cnt;
+ HRESULT hr;
+
+
+ //
+ // Keep writing until the caller's buffer is empty.
+ //
+ while (cBuf)
+ {
+ //
+ // Compute the number of bytes to copy.
+ //
+ cnt = min(m_cBuffer, cBuf);
+
+ //
+ // Copy to the internal write buffer and update variables.
+ //
+ memcpy(m_pBuffer, pBuf, cnt);
+ pBuf = (PBYTE)pBuf + cnt;
+ cBuf -= cnt;
+ m_pBuffer += cnt;
+ m_cBuffer -= cnt;
+
+ //
+ // On full internal buffer, flush.
+ //
+ if (m_cBuffer == 0)
+ {
+ LEDebugOut((DEB_WARN, "WARNING: Multiple buffer flushes.\n"));
+
+ hr = Flush();
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ }
+ }
+
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStmBufWrite::WriteLong, public
+//
+// Synopsis: Write long value to the stream.
+//
+// Arguments: [lValue] - Long value to write.
+//
+// Returns: HRESULT.
+//
+// History: 20-Feb-95 KentCe Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT CStmBufWrite::WriteLong(LONG lValue)
+{
+ return Write(&lValue, sizeof(LONG));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStmBufWrite::Flush, public
+//
+// Synopsis: Flush write buffer to the system.
+//
+// Arguments: None.
+//
+// Returns: HRESULT.
+//
+// History: 20-Feb-95 KentCe Created
+//
+// Notes: Performs a write of the stream buffer to the system, does not
+// force a flush to disk.
+//
+//----------------------------------------------------------------------------
+HRESULT CStmBufWrite::Flush(void)
+{
+ ULONG cnt;
+ HRESULT hr;
+
+
+ //
+ // This might be an overactive assert, but shouldn't happen.
+ //
+ Assert(m_cBuffer != sizeof(m_aBuffer));
+
+ hr = m_pStm->Write(m_aBuffer, sizeof(m_aBuffer) - m_cBuffer, &cnt);
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ if (cnt != sizeof(m_aBuffer) - m_cBuffer)
+ {
+ return STG_E_MEDIUMFULL;
+ }
+
+ Reset();
+
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStmBufWrite::Reset, public
+//
+// Synopsis: Reset buffer variables.
+//
+// Arguments: None.
+//
+// Returns: None.
+//
+// History: 20-Feb-95 KentCe Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void CStmBufWrite::Reset(void)
+{
+ m_pBuffer = m_aBuffer;
+ m_cBuffer = sizeof(m_aBuffer);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStmBufWrite::Release, public
+//
+// Synopsis: Release write stream interface.
+//
+// Arguments: None.
+//
+// Returns: None.
+//
+// History: 20-Feb-95 KentCe Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void CStmBufWrite::Release()
+{
+ if (m_pStm)
+ {
+ //
+ // Verify that flush was called.
+ //
+ Assert(m_cBuffer == sizeof(m_aBuffer));
+
+ m_pStm->Release();
+ m_pStm = NULL;
+ }
+}