Windows2003-3790/inetcore/outlookexpress/msoert/stmutil.cpp
2020-09-30 16:53:55 +02:00

1501 lines
41 KiB
C++

// --------------------------------------------------------------------------------
// Stmutil.cpp
// Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
// Steven J. Bailey
// --------------------------------------------------------------------------------
#include "pch.hxx"
#include "oertpriv.h"
#include "shlwapi.h"
#include "unicnvrt.h"
#include <BadStrFunctions.h>
#pragma warning (disable: 4127) // conditional expression is constant
// Stream Block Copy Size
#define STMTRNSIZE 4096
// --------------------------------------------------------------------------------
// Disk full simulation on CFileStream
// --------------------------------------------------------------------------------
#ifdef DEBUG
static BOOL g_fSimulateFullDisk = 0;
#endif
// --------------------------------------------------------------------------------
// HrIsStreamUnicode
// --------------------------------------------------------------------------------
OESTDAPI_(HRESULT) HrIsStreamUnicode(LPSTREAM pStream, BOOL *pfLittleEndian)
{
// Locals
HRESULT hr=S_OK;
BYTE rgb[2];
DWORD cbRead;
DWORD cbPosition;
// Invalid Args
if (NULL == pStream || NULL == pfLittleEndian)
return(TraceResult(E_INVALIDARG));
// Trace
TraceCall("HrIsStreamUnicode");
// Get the current position
IF_FAILEXIT(hr = HrGetStreamPos(pStream, &cbPosition));
// Read Two Bytes
IF_FAILEXIT(hr = pStream->Read(rgb, 2, &cbRead));
// Reposition the Stream
HrStreamSeekSet(pStream, cbPosition);
// Didn't Read Enough ?
if (2 != cbRead)
{
hr = S_FALSE;
goto exit;
}
// Little Endian
if (0xFF == rgb[0] && 0xFE == rgb[1])
{
*pfLittleEndian = TRUE;
hr = S_OK;
goto exit;
}
// Big Endian
if (0xFE == rgb[0] && 0xFF == rgb[1])
{
*pfLittleEndian = FALSE;
hr = S_OK;
goto exit;
}
// Not Unicode
hr = S_FALSE;
exit:
// Done
return(hr);
}
// --------------------------------------------------------------------------------
// HrCopyLockBytesToStream
// --------------------------------------------------------------------------------
OESTDAPI_(HRESULT) HrCopyLockBytesToStream(ILockBytes *pLockBytes, IStream *pStream, ULONG *pcbCopied)
{
// Locals
HRESULT hr=S_OK;
ULARGE_INTEGER uliCopy;
ULONG cbRead;
BYTE rgbBuffer[STMTRNSIZE];
// Invalid Artg
Assert(pLockBytes && pStream);
// Set offset
uliCopy.QuadPart = 0;
// Copy m_pLockBytes to pstmTemp
while(1)
{
// Read
CHECKHR(hr = pLockBytes->ReadAt(uliCopy, rgbBuffer, sizeof(rgbBuffer), &cbRead));
// Done
if (0 == cbRead)
break;
// Write to stream
CHECKHR(hr = pStream->Write(rgbBuffer, cbRead, NULL));
// Increment offset
uliCopy.QuadPart += cbRead;
}
// Return Amount Copied
if (pcbCopied)
*pcbCopied = (ULONG)uliCopy.QuadPart;
exit:
// Done
return hr;
}
// --------------------------------------------------------------------------------
// FDoesStreamContains8bit
// --------------------------------------------------------------------------------
BOOL FDoesStreamContain8bit (LPSTREAM lpstm)
{
// Locals
BOOL fResult=FALSE;
BYTE buf[4096];
ULONG cbRead,
i;
// Loop through the stream
while(1)
{
// Read cbCopy bytes from in
if (FAILED(lpstm->Read (buf, sizeof(buf), &cbRead)) || cbRead == 0)
break;
// Scan for 8bit
for (i=0; i<cbRead; i++)
{
if (IS_EXTENDED(buf[i]))
{
fResult = TRUE;
break;
}
}
}
// Done
return fResult;
}
// --------------------------------------------------------------------------------
// HrCopyStreamCB - A generic implementation of IStream::CopyTo
// --------------------------------------------------------------------------------
OESTDAPI_(HRESULT) HrCopyStreamCB(
LPSTREAM lpstmIn,
LPSTREAM lpstmOut,
ULARGE_INTEGER uliCopy,
ULARGE_INTEGER *puliRead,
ULARGE_INTEGER *puliWritten)
{
// Locals
HRESULT hr = S_OK;
BYTE buf[4096];
ULONG cbRead,
cbWritten,
cbRemaining = uliCopy.LowPart,
cbGet;
// Init out params
if (puliRead)
ULISet32(*puliRead, 0);
if (puliWritten)
ULISet32(*puliWritten, 0);
if ((NULL == lpstmIn) || (NULL == lpstmOut) ||
((0 != uliCopy.HighPart) && ((DWORD)-1 != uliCopy.HighPart || (DWORD)-1 != uliCopy.LowPart)))
return TrapError(E_INVALIDARG);
while (cbRemaining)
{
cbGet = min(sizeof(buf), cbRemaining);
CHECKHR (hr = lpstmIn->Read (buf, cbGet, &cbRead));
if (0 == cbRead)
break;
CHECKHR (hr = lpstmOut->Write (buf, cbRead, &cbWritten));
// Verify
Assert (cbWritten == cbRead);
if (puliRead)
puliRead->LowPart += cbRead;
if (puliWritten)
puliWritten->LowPart += cbWritten;
// Compute number of bytes left to copy
cbRemaining -= cbRead;
}
exit:
return hr;
}
// --------------------------------------------------------------------------------
// HrCopyStreamCBEndOnCRLF - Copy cb bytes from lpstmIn to lpstmOut, and last CRLF
// --------------------------------------------------------------------------------
OESTDAPI_(HRESULT) HrCopyStreamCBEndOnCRLF(LPSTREAM lpstmIn, LPSTREAM lpstmOut, ULONG cb, ULONG *pcbActual)
{
// Locals
HRESULT hr = S_OK;
BYTE buf[4096];
ULONG cbRead = 0, cbWritten = 0, cbTotal = 0, cbRemaining = 0, cbCopy;
do
{
// Compute number of bytes left to copy
cbRemaining = cb - cbTotal;
if (cbRemaining >= sizeof (buf))
cbCopy = sizeof (buf);
else
cbCopy = cbRemaining;
// Done
if (cbCopy == 0)
break;
// Read cbCopy bytes from in
CHECKHR (hr = lpstmIn->Read (buf, cbCopy, &cbRead));
if (cbRead == 0)
break;
// Write cbCopy bytes to out
CHECKHR (hr = lpstmOut->Write (buf, cbRead, NULL));
// Verify
cbTotal += cbRead;
} while (cbRead == cbCopy);
// If last character was not a '\n', append until we append a '\n'
// Yes, please do not tell me that this is horable because I know that copying one
// character at a time from a stream is not good and I should be deported right
// along with brettm, but, this loop should never iterate more than the max line
// length of the body of a message, so there. (sbailey)
if (cbRead && buf[cbRead] != '\n')
{
do
{
// Read cbCopy bytes from in
CHECKHR (hr = lpstmIn->Read (buf, 1, &cbRead));
// Nothing left
if (cbRead == 0)
break;
// Write cbCopy bytes to out
CHECKHR (hr = lpstmOut->Write (buf, 1, NULL));
// Inc Total
cbTotal++;
} while (buf[0] != '\n');
}
exit:
if (pcbActual)
*pcbActual = cbTotal;
return hr;
}
// --------------------------------------------------------------------------------
// HrCopyStream2 - copies lpstmIn to two out streams - caller must do the commit
// --------------------------------------------------------------------------------
HRESULT HrCopyStream2(LPSTREAM lpstmIn, LPSTREAM lpstmOut1, LPSTREAM lpstmOut2, ULONG *pcb)
{
// Locals
HRESULT hr = S_OK;
BYTE buf[4096];
ULONG cbRead = 0, cbWritten = 0, cbTotal = 0;
do
{
CHECKHR (hr = lpstmIn->Read (buf, sizeof (buf), &cbRead));
if (cbRead == 0) break;
CHECKHR (hr = lpstmOut1->Write (buf, cbRead, &cbWritten));
Assert (cbWritten == cbRead);
CHECKHR (hr = lpstmOut2->Write (buf, cbRead, &cbWritten));
Assert (cbWritten == cbRead);
cbTotal += cbRead;
}
while (cbRead == sizeof (buf));
exit:
if (pcb)
*pcb = cbTotal;
return hr;
}
// --------------------------------------------------------------------------------
// HrCopyStreamToFile
// --------------------------------------------------------------------------------
HRESULT HrCopyStreamToFile (LPSTREAM lpstm, HANDLE hFile, ULONG *pcb)
{
// Locals
HRESULT hr = S_OK;
BYTE buf[4096];
ULONG cbRead = 0, cbWritten = 0, cbTotal = 0;
BOOL bResult;
do
{
// Read a block
CHECKHR (hr = lpstm->Read (buf, sizeof (buf), &cbRead));
if (cbRead == 0) break;
// Write the block to the file
bResult = WriteFile (hFile, buf, cbRead, &cbWritten, NULL);
if (bResult == FALSE || cbWritten != cbRead)
{
hr = TrapError(E_FAIL);
goto exit;
}
// Keep Track of Total bytes written
cbTotal += cbRead;
}
while (cbRead == sizeof (buf));
exit:
// Set Total
if (pcb)
*pcb = cbTotal;
// Done
return hr;
}
// --------------------------------------------------------------------------------
// HrStreamToByte
// --------------------------------------------------------------------------------
OESTDAPI_(HRESULT) HrStreamToByte(LPSTREAM lpstm, LPBYTE *lppb, ULONG *pcb)
{
// Locals
HRESULT hr = S_OK;
ULONG cbRead, cbSize;
// Check Params
AssertSz (lpstm && lppb, "Null Parameter");
CHECKHR(hr = HrGetStreamSize(lpstm, &cbSize));
CHECKHR(hr = HrRewindStream(lpstm));
// Allocate Memory
CHECKHR(hr = HrAlloc((LPVOID *)lppb, cbSize + 10));
// Read Everything to lppsz
CHECKHR(hr = lpstm->Read(*lppb, cbSize, &cbRead));
if (cbRead != cbSize)
{
hr = TrapError(S_FALSE);
goto exit;
}
// Outbound size
if (pcb)
*pcb = cbSize;
exit:
// Done
return hr;
}
// --------------------------------------------------------------------------------
// HrCopyStream
// --------------------------------------------------------------------------------
OESTDAPI_(HRESULT) HrCopyStream(LPSTREAM pstmIn, LPSTREAM pstmOut, OPTIONAL ULONG *pcb)
{
// Locals
HRESULT hr = S_OK;
BYTE buf[STMTRNSIZE];
ULONG cbRead=0,
cbTotal=0;
do
{
CHECKHR(hr = pstmIn->Read(buf, sizeof(buf), &cbRead));
if (cbRead == 0) break;
CHECKHR(hr = pstmOut->Write(buf, cbRead, NULL));
cbTotal += cbRead;
}
while (cbRead == sizeof (buf));
exit:
if (pcb)
*pcb = cbTotal;
return hr;
}
// --------------------------------------------------------------------------------
// HrCopyStreamToByte
// --------------------------------------------------------------------------------
OESTDAPI_(HRESULT) HrCopyStreamToByte(LPSTREAM lpstmIn, LPBYTE pbDest, ULONG *pcb)
{
// Locals
HRESULT hr=S_OK;
BYTE buf[STMTRNSIZE];
ULONG cbRead=0,
cbTotal=0;
do
{
// Read a buffer from stream
CHECKHR(hr = lpstmIn->Read (buf, sizeof (buf), &cbRead));
// Nothing Read...
if (cbRead == 0)
break;
// Copy that
CopyMemory(pbDest + cbTotal, buf, cbRead);
// Increment total
cbTotal += cbRead;
} while (cbRead == sizeof(buf));
exit:
// Set total
if (pcb)
*pcb = cbTotal;
// Done
return hr;
}
// --------------------------------------------------------------------------------
// HrByteToStream
// --------------------------------------------------------------------------------
OESTDAPI_(HRESULT) HrByteToStream(LPSTREAM *lppstm, LPBYTE lpb, ULONG cb)
{
// Locals
HRESULT hr=S_OK;
// Check Params
AssertSz(lppstm && lpb, "Null Parameter");
// Create H Global Stream
CHECKHR(hr = CreateStreamOnHGlobal (NULL, TRUE, lppstm));
// Write String
CHECKHR(hr = (*lppstm)->Write (lpb, cb, NULL));
// Rewind the steam
CHECKHR(hr = HrRewindStream(*lppstm));
exit:
// Done
return hr;
}
// --------------------------------------------------------------------------------
// HrRewindStream
// --------------------------------------------------------------------------------
OESTDAPI_(HRESULT) HrRewindStream(LPSTREAM pstm)
{
// Locals
HRESULT hr=S_OK;
LARGE_INTEGER liOrigin = {0,0};
// Check Params
Assert(pstm);
// Seek to 0
CHECKHR(hr = pstm->Seek(liOrigin, STREAM_SEEK_SET, NULL));
exit:
// Done
return hr;
}
// --------------------------------------------------------------------------------
// HrGetStreamPos
// --------------------------------------------------------------------------------
HRESULT HrGetStreamPos(LPSTREAM pstm, ULONG *piPos)
{
// Locals
HRESULT hr=S_OK;
ULARGE_INTEGER uliPos = {0,0};
LARGE_INTEGER liOrigin = {0,0};
// check Params
Assert(piPos && pstm);
// Seek
CHECKHR(hr = pstm->Seek(liOrigin, STREAM_SEEK_CUR, &uliPos));
// Set position
*piPos = uliPos.LowPart;
exit:
// Done
return hr;
}
// --------------------------------------------------------------------------------
// HrGetStreamSize
// --------------------------------------------------------------------------------
OESTDAPI_(HRESULT) HrGetStreamSize(LPSTREAM pstm, ULONG *pcb)
{
// Locals
HRESULT hr=S_OK;
ULARGE_INTEGER uliPos = {0,0};
LARGE_INTEGER liOrigin = {0,0};
// check params
Assert(pcb && pstm);
// Seek
CHECKHR(hr = pstm->Seek(liOrigin, STREAM_SEEK_END, &uliPos));
// set size
*pcb = uliPos.LowPart;
exit:
// Done
return hr;
}
// --------------------------------------------------------------------------------
// HrSafeGetStreamSize
// --------------------------------------------------------------------------------
HRESULT HrSafeGetStreamSize(LPSTREAM pstm, ULONG *pcb)
{
// Locals
HRESULT hr=S_OK;
ULONG iPos;
ULARGE_INTEGER uliPos = {0,0};
LARGE_INTEGER liOrigin = {0,0};
// check params
Assert(pcb && pstm);
// Get the stream position
CHECKHR(hr = HrGetStreamPos(pstm, &iPos));
// Seek
CHECKHR(hr = pstm->Seek(liOrigin, STREAM_SEEK_END, &uliPos));
// set size
*pcb = uliPos.LowPart;
// Seek back to original position
CHECKHR(hr = HrStreamSeekSet(pstm, iPos));
exit:
// Done
return hr;
}
// --------------------------------------------------------------------------------
// HrStreamSeekSet
// --------------------------------------------------------------------------------
OESTDAPI_(HRESULT) HrStreamSeekSet(LPSTREAM pstm, ULONG iPos)
{
// Locals
HRESULT hr=S_OK;
LARGE_INTEGER liOrigin;
// Check Params
Assert(pstm);
// Set Origin Correctly
liOrigin.QuadPart = iPos;
// Seek
CHECKHR(hr = pstm->Seek(liOrigin, STREAM_SEEK_SET, NULL));
exit:
// Done
return hr;
}
// --------------------------------------------------------------------------------
// HrStreamSeekEnd
// --------------------------------------------------------------------------------
OESTDAPI_(HRESULT) HrStreamSeekEnd(LPSTREAM pstm)
{
// Locals
HRESULT hr=S_OK;
LARGE_INTEGER liOrigin = {0,0};
// Check Params
Assert(pstm);
// Seek
CHECKHR(hr = pstm->Seek(liOrigin, STREAM_SEEK_END, NULL));
exit:
// Done
return hr;
}
// --------------------------------------------------------------------------------
// HrStreamSeekBegin
// --------------------------------------------------------------------------------
OESTDAPI_(HRESULT) HrStreamSeekBegin(LPSTREAM pstm)
{
// Locals
HRESULT hr=S_OK;
LARGE_INTEGER liOrigin = {0,0};
// Check Params
Assert(pstm);
// Seek
CHECKHR(hr = pstm->Seek(liOrigin, STREAM_SEEK_SET, NULL));
exit:
// Done
return hr;
}
// --------------------------------------------------------------------------------
// HrStreamSeekCur
// --------------------------------------------------------------------------------
OESTDAPI_(HRESULT) HrStreamSeekCur(LPSTREAM pstm, LONG iPos)
{
// Locals
HRESULT hr=S_OK;
LARGE_INTEGER liOrigin;
// Check Params
Assert(pstm);
// Setup Origin
liOrigin.QuadPart = iPos;
// Seek
CHECKHR(hr = pstm->Seek(liOrigin, STREAM_SEEK_CUR, NULL));
exit:
// Done
return hr;
}
// --------------------------------------------------------------------------------
// CreateFileStream
// --------------------------------------------------------------------------------
HRESULT CreateFileStream(
LPWSTR pszFile,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDistribution,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile,
LPSTREAM *ppstmFile)
{
// Locals
HRESULT hr=S_OK;
FILESTREAMINFO rInfo;
CFileStream *pstmFile=NULL;
WCHAR szTempDir[MAX_PATH];
// check params
if (NULL == ppstmFile)
return TrapError(E_INVALIDARG);
// Check Params
Assert(dwDesiredAccess & GENERIC_READ || dwDesiredAccess & GENERIC_WRITE);
// Setup File Stream Info struct
ZeroMemory(&rInfo, sizeof(rInfo));
rInfo.dwDesiredAccess = dwDesiredAccess;
rInfo.dwShareMode = dwShareMode;
if (lpSecurityAttributes)
CopyMemory(&rInfo.rSecurityAttributes, lpSecurityAttributes, sizeof(SECURITY_ATTRIBUTES));
rInfo.dwCreationDistribution = dwCreationDistribution;
rInfo.dwFlagsAndAttributes = dwFlagsAndAttributes;
rInfo.hTemplateFile = hTemplateFile;
// Create Object
pstmFile = new CFileStream();
if (NULL == pstmFile)
{
hr = TrapError(E_OUTOFMEMORY);
goto exit;
}
// Temp File ?
if (NULL == pszFile)
{
// Get Temp Dir
DWORD nBufferLength = AthGetTempPathW(ARRAYSIZE(szTempDir), szTempDir);
if (nBufferLength == 0 || nBufferLength > ARRAYSIZE(szTempDir))
{
hr = TrapError(E_FAIL);
goto exit;
}
// Get Temp File Name
UINT uFile = AthGetTempFileNameW(szTempDir, L"tmp", 0, rInfo.szFilePath);
if (uFile == 0)
{
hr = TrapError(E_FAIL);
goto exit;
}
#ifdef DEBUG
else if (g_fSimulateFullDisk)
{
hr = TrapError(E_FAIL);
goto exit;
}
#endif
// Delete When Done
rInfo.dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
// Always create a new temp file
rInfo.dwCreationDistribution = OPEN_EXISTING;
}
else
{
// Copy filename
StrCpyNW(rInfo.szFilePath, pszFile, ARRAYSIZE(rInfo.szFilePath));
}
// Open it
CHECKHR(hr = pstmFile->Open(&rInfo));
// Success
*ppstmFile = pstmFile;
pstmFile = NULL;
exit:
// Cleanup
SafeRelease(pstmFile);
// Done
return hr;
}
// --------------------------------------------------------------------------------
// CreateTempFileStream
// --------------------------------------------------------------------------------
OESTDAPI_(HRESULT) CreateTempFileStream(LPSTREAM *ppstmFile)
{
return CreateFileStream(NULL,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL,
ppstmFile);
}
// --------------------------------------------------------------------------------
// OpenFileStream
// --------------------------------------------------------------------------------
OESTDAPI_(HRESULT) OpenFileStream(LPSTR pszFile, DWORD dwCreationDistribution,
DWORD dwAccess, LPSTREAM *ppstmFile)
{
// Locals
HRESULT hr=S_OK;
LPWSTR pszFileW=NULL;
// Trace
TraceCall("OpenFileStream");
// Convert
IF_NULLEXIT(pszFileW = PszToUnicode(CP_ACP, pszFile));
// Call unicode version
IF_FAILEXIT(hr = OpenFileStreamW(pszFileW, dwCreationDistribution, dwAccess, ppstmFile));
exit:
// Cleanup
SafeMemFree(pszFileW);
// Done
return(hr);
}
// --------------------------------------------------------------------------------
// OpenFileStreamW
// --------------------------------------------------------------------------------
OESTDAPI_(HRESULT) OpenFileStreamW(LPWSTR pszFile, DWORD dwCreationDistribution,
DWORD dwAccess, LPSTREAM *ppstmFile)
{
Assert(pszFile);
return CreateFileStream(pszFile,
dwAccess,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
dwCreationDistribution,
FILE_ATTRIBUTE_NORMAL,
NULL,
ppstmFile);
}
// --------------------------------------------------------------------------------
// OpenFileStreamWithFlags
// --------------------------------------------------------------------------------
OESTDAPI_(HRESULT) OpenFileStreamWithFlags(LPSTR pszFile, DWORD dwCreationDistribution,
DWORD dwAccess, DWORD dwFlagsAndAttributes, LPSTREAM *ppstmFile)
{
// Locals
HRESULT hr=S_OK;
LPWSTR pszFileW=NULL;
// Trace
TraceCall("OpenFileStreamWithFlags");
// Convert to unicode
IF_NULLEXIT(pszFileW = PszToUnicode(CP_ACP, pszFile));
// Call unicode version
IF_FAILEXIT(hr = OpenFileStreamWithFlagsW(pszFileW, dwCreationDistribution, dwAccess, dwFlagsAndAttributes, ppstmFile));
exit:
// Cleanup
SafeMemFree(pszFileW);
// Done
return(hr);
}
// --------------------------------------------------------------------------------
// OpenFileStreamWithFlagsW
// --------------------------------------------------------------------------------
OESTDAPI_(HRESULT) OpenFileStreamWithFlagsW(LPWSTR pszFile, DWORD dwCreationDistribution,
DWORD dwAccess, DWORD dwFlagsAndAttributes, LPSTREAM *ppstmFile)
{
Assert(pszFile);
return CreateFileStream(pszFile,
dwAccess,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
dwCreationDistribution,
dwFlagsAndAttributes,
NULL,
ppstmFile);
}
// --------------------------------------------------------------------------------
// WriteStreamToFile
// --------------------------------------------------------------------------------
OESTDAPI_(HRESULT) WriteStreamToFile(LPSTREAM pstm, LPSTR lpszFile, DWORD dwCreationDistribution, DWORD dwAccess)
{
// Locals
HRESULT hr=S_OK;
LPWSTR pszFileW=NULL;
// Trace
TraceCall("WriteStreamToFile");
// Convert to unicode
IF_NULLEXIT(pszFileW = PszToUnicode(CP_ACP, lpszFile));
// Call Unicode Version
IF_FAILEXIT(hr = WriteStreamToFileW(pstm, pszFileW, dwCreationDistribution, dwAccess));
exit:
// Cleanup
SafeMemFree(pszFileW);
// Done
return(hr);
}
// --------------------------------------------------------------------------------
// WriteStreamToFileW
// --------------------------------------------------------------------------------
OESTDAPI_(HRESULT) WriteStreamToFileW(LPSTREAM pstm, LPWSTR lpszFile, DWORD dwCreationDistribution, DWORD dwAccess)
{
// Locals
HRESULT hr=S_OK;
LPSTREAM pstmFile=NULL;
// Open the stream
IF_FAILEXIT(hr = OpenFileStreamW(lpszFile, dwCreationDistribution, dwAccess, &pstmFile));
// Rewind
IF_FAILEXIT(hr = HrRewindStream(pstm));
// Copy
IF_FAILEXIT(hr = HrCopyStream (pstm, pstmFile, NULL));
// Rewind
IF_FAILEXIT(hr = HrRewindStream(pstm));
exit:
// Cleanup
SafeRelease(pstmFile);
// Done
return(hr);
}
// --------------------------------------------------------------------------------
// OpenFileStreamShare
// --------------------------------------------------------------------------------
OESTDAPI_(HRESULT) OpenFileStreamShare(LPSTR pszFile, DWORD dwCreationDistribution, DWORD dwAccess,
DWORD dwShare, LPSTREAM *ppstmFile)
{
// Locals
HRESULT hr=S_OK;
LPWSTR pszFileW=NULL;
// Trace
TraceCall("OpenFileStreamShare");
// Convert to unicode
IF_NULLEXIT(pszFileW = PszToUnicode(CP_ACP, pszFile));
// Call unicode versoin
IF_FAILEXIT(hr = OpenFileStreamShareW(pszFileW, dwCreationDistribution, dwAccess, dwShare, ppstmFile));
exit:
// Cleanup
SafeMemFree(pszFileW);
// Done
return(hr);
}
// --------------------------------------------------------------------------------
// OpenFileStreamShareW
// --------------------------------------------------------------------------------
OESTDAPI_(HRESULT) OpenFileStreamShareW(LPWSTR pszFile, DWORD dwCreationDistribution, DWORD dwAccess,
DWORD dwShare, LPSTREAM *ppstmFile)
{
Assert(pszFile);
return CreateFileStream(pszFile,
dwAccess,
dwShare,
NULL,
dwCreationDistribution,
FILE_ATTRIBUTE_NORMAL,
NULL,
ppstmFile);
}
// --------------------------------------------------------------------------------
// CFileStream::Constructor
// --------------------------------------------------------------------------------
CFileStream::CFileStream(void)
{
m_cRef = 1;
m_hFile = INVALID_HANDLE_VALUE;
ZeroMemory(&m_rInfo, sizeof(FILESTREAMINFO));
}
// --------------------------------------------------------------------------------
// CFileStream::Deconstructor
// --------------------------------------------------------------------------------
CFileStream::~CFileStream(void)
{
Close();
}
// --------------------------------------------------------------------------------
// CFileStream::AddRef
// --------------------------------------------------------------------------------
ULONG CFileStream::AddRef ()
{
return ++m_cRef;
}
// --------------------------------------------------------------------------------
// CFileStream::Release
// --------------------------------------------------------------------------------
ULONG CFileStream::Release ()
{
if (0 != --m_cRef)
return m_cRef;
delete this;
return 0;
}
// --------------------------------------------------------------------------------
// CFileStream::QueryInterface
// --------------------------------------------------------------------------------
STDMETHODIMP CFileStream::QueryInterface (REFIID iid, LPVOID* ppvObj)
{
if (IsEqualIID(iid, IID_IUnknown) || IsEqualIID(iid, IID_IStream))
{
*ppvObj = this;
AddRef();
return(S_OK);
}
return E_NOINTERFACE;
}
// --------------------------------------------------------------------------------
// CFileStream::Open
// --------------------------------------------------------------------------------
HRESULT CFileStream::Open(LPFILESTREAMINFO pFileStreamInfo)
{
// Better not be open
Assert(m_hFile == INVALID_HANDLE_VALUE);
// Copy File Info
CopyMemory(&m_rInfo, pFileStreamInfo, sizeof(FILESTREAMINFO));
// Open the file
m_hFile = AthCreateFileW(m_rInfo.szFilePath, m_rInfo.dwDesiredAccess, m_rInfo.dwShareMode,
NULL, m_rInfo.dwCreationDistribution,
m_rInfo.dwFlagsAndAttributes, m_rInfo.hTemplateFile);
// Error
if (INVALID_HANDLE_VALUE == m_hFile)
return TrapError(E_FAIL);
#ifdef DEBUG
else if (g_fSimulateFullDisk)
return TrapError(E_FAIL);
#endif
// Success
return S_OK;
}
// --------------------------------------------------------------------------------
// CFileStream::Close
// --------------------------------------------------------------------------------
void CFileStream::Close(void)
{
if (INVALID_HANDLE_VALUE != m_hFile)
{
CloseHandle_F16(m_hFile);
m_hFile = INVALID_HANDLE_VALUE;
}
}
// --------------------------------------------------------------------------------
// CFileStream::Read
// --------------------------------------------------------------------------------
STDMETHODIMP CFileStream::Read (void HUGEP_16 *lpv, ULONG cb, ULONG *pcbRead)
{
// Locals
HRESULT hr = S_OK;
BOOL fReturn;
DWORD dwRead;
// Check Params
Assert(lpv && m_hFile != INVALID_HANDLE_VALUE);
// Read some bytes from m_hFile
fReturn = ReadFile (m_hFile, lpv, cb, &dwRead, NULL);
if (!fReturn)
{
AssertSz(FALSE, "CFileStream::Read Failed");
hr = TrapError(E_FAIL);
goto exit;
}
// Write byte
if (pcbRead)
*pcbRead = dwRead;
exit:
// Done
return hr;
}
// --------------------------------------------------------------------------------
// CFileStream::Write
// --------------------------------------------------------------------------------
STDMETHODIMP CFileStream::Write(const void HUGEP_16 *lpv, ULONG cb, ULONG *pcbWritten)
{
// Locals
HRESULT hr = S_OK;
BOOL fReturn;
DWORD dwWritten;
// Check Params
Assert(lpv);
Assert(m_hFile != INVALID_HANDLE_VALUE);
// Read some bytes from m_hFile
fReturn = WriteFile(m_hFile, lpv, cb, &dwWritten, NULL);
if (!fReturn)
{
AssertSz (FALSE, "CFileStream::Write Failed");
hr = TrapError(E_FAIL);
goto exit;
}
#ifdef DEBUG
else if (g_fSimulateFullDisk)
{
AssertSz (FALSE, "CFileStream::Write Failed");
hr = TrapError(E_FAIL);
goto exit;
}
#endif
// Write byte
if (pcbWritten)
*pcbWritten = dwWritten;
exit:
// Done
return hr;
}
// --------------------------------------------------------------------------------
// CFileStream::Seek
// --------------------------------------------------------------------------------
STDMETHODIMP CFileStream::Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
{
// Locals
HRESULT hr = S_OK;
DWORD dwReturn;
LONG lMove; // Cast to signed, could be negative
Assert (m_hFile != INVALID_HANDLE_VALUE);
// Cast lowpart
lMove = (LONG)dlibMove.QuadPart;
// Seek the file pointer
switch (dwOrigin)
{
case STREAM_SEEK_SET:
dwReturn = SetFilePointer (m_hFile, lMove, NULL, FILE_BEGIN);
break;
case STREAM_SEEK_CUR:
dwReturn = SetFilePointer (m_hFile, lMove, NULL, FILE_CURRENT);
break;
case STREAM_SEEK_END:
dwReturn = SetFilePointer (m_hFile, lMove, NULL, FILE_END);
break;
default:
dwReturn = 0xFFFFFFFF;
}
// Failure ?
if (dwReturn == 0xFFFFFFFF)
{
AssertSz(FALSE, "CFileStream::Seek Failed");
hr = TrapError(E_FAIL);
goto exit;
}
// Return Position
if (plibNewPosition)
plibNewPosition->QuadPart = dwReturn;
exit:
// Done
return hr;
}
// --------------------------------------------------------------------------------
// CFileStream::Commit
// --------------------------------------------------------------------------------
STDMETHODIMP CFileStream::Commit(DWORD)
{
// Locals
HRESULT hr = S_OK;
Assert(m_hFile != INVALID_HANDLE_VALUE);
// Flush the buffers
if (FlushFileBuffers (m_hFile) == FALSE)
{
AssertSz(FALSE, "FlushFileBuffers failed");
hr = TrapError(E_FAIL);
goto exit;
}
exit:
// Done
return hr;
}
// --------------------------------------------------------------------------------
// CFileStream::SetSize
// --------------------------------------------------------------------------------
STDMETHODIMP CFileStream::SetSize (ULARGE_INTEGER uli)
{
DWORD dwOrig;
// remember the current file position
dwOrig = SetFilePointer (m_hFile, 0, NULL, FILE_CURRENT);
if (dwOrig == 0xFFFFFFFF)
{
AssertSz(FALSE, "Get current position failed");
return TrapError(E_FAIL);
}
// Seek to dwSize
if (SetFilePointer (m_hFile, uli.LowPart, NULL, FILE_BEGIN) == 0xFFFFFFFF)
{
AssertSz(FALSE, "SetFilePointer failed");
return TrapError(STG_E_MEDIUMFULL);
}
// SetEndOfFile
if (SetEndOfFile (m_hFile) == FALSE)
{
AssertSz(FALSE, "SetEndOfFile failed");
return TrapError(STG_E_MEDIUMFULL);
}
// if the original position we less than the new size, return the file
// pointer to the original position
if (dwOrig < uli.LowPart)
{
if (SetFilePointer (m_hFile, dwOrig, NULL, FILE_BEGIN) == 0xFFFFFFFF)
{
AssertSz(FALSE, "SetFilePointer failed");
return TrapError(STG_E_MEDIUMFULL);
}
}
// Done
return S_OK;
}
// --------------------------------------------------------------------------------
// CFileStream::CopyTo
// This needs to be written better, but for now it's no worse that what a
// client would do
// --------------------------------------------------------------------------------
STDMETHODIMP CFileStream::CopyTo (LPSTREAM pstmDst,
ULARGE_INTEGER uli,
ULARGE_INTEGER* puliRead,
ULARGE_INTEGER* puliWritten)
{
ULONG cbBuf;
ULONG cbCopy;
VOID * pvBuf = 0;
BYTE rgBuf[STMTRNSIZE];
ULONG cbRemain;
ULONG cbReadTot = 0;
ULONG cbWriteTot = 0;
HRESULT hr = 0;
if (uli.HighPart)
cbRemain = 0xFFFFFFFF;
else
cbRemain = uli.LowPart;
// Attempt to allocate a buffer
cbBuf = (UINT)cbRemain;
if (cbBuf > STMTRNSIZE)
cbBuf = STMTRNSIZE;
// Copy the data one buffer at a time
while (cbRemain > 0)
{
// Compute maximum bytes to copy this time
cbCopy = cbRemain;
if (cbCopy > cbBuf)
cbCopy = cbBuf;
// Read into the buffer
hr = Read (rgBuf, cbCopy, &cbCopy);
if (FAILED(hr))
goto err;
if (cbCopy == 0)
break;
cbReadTot += cbCopy;
cbRemain -= cbCopy;
// Write buffer into the destination stream
{
ULONG cbWrite = cbCopy;
while (cbWrite)
{
hr = pstmDst->Write(rgBuf, cbWrite, &cbCopy);
if (FAILED(hr))
goto err;
cbWriteTot += cbCopy;
cbWrite -= cbCopy;
if (cbCopy == 0)
break;
}
}
}
err:
if (puliRead)
{
puliRead->HighPart = 0;
puliRead->LowPart = cbReadTot;
}
if (puliWritten)
{
puliWritten->HighPart = 0;
puliWritten->LowPart = cbWriteTot;
}
return (hr);
}
// --------------------------------------------------------------------------------
// CFileStream::Revert
// --------------------------------------------------------------------------------
STDMETHODIMP CFileStream::Revert ()
{
return E_NOTIMPL;
}
// --------------------------------------------------------------------------------
// CFileStream::LockRegion
// --------------------------------------------------------------------------------
STDMETHODIMP CFileStream::LockRegion (ULARGE_INTEGER, ULARGE_INTEGER,DWORD)
{
return E_NOTIMPL;
}
// --------------------------------------------------------------------------------
// CFileStream::UnlockRegion
// --------------------------------------------------------------------------------
STDMETHODIMP CFileStream::UnlockRegion (ULARGE_INTEGER, ULARGE_INTEGER, DWORD)
{
return E_NOTIMPL;
}
// --------------------------------------------------------------------------------
// CFileStream::Stat
// --------------------------------------------------------------------------------
STDMETHODIMP CFileStream::Stat (STATSTG*, DWORD)
{
return E_NOTIMPL;
}
// --------------------------------------------------------------------------------
// CFileStream::Clone
// --------------------------------------------------------------------------------
STDMETHODIMP CFileStream::Clone (LPSTREAM*)
{
return E_NOTIMPL;
}
DWORD RemoveCRLF(LPSTR pszT, DWORD cbT, BOOL * pfBadDBCS)
{
DWORD i = 0;
*pfBadDBCS = FALSE;
while (i < cbT)
{
if (IsDBCSLeadByte(pszT[i]))
{
if ((i + 1) >= cbT)
{
cbT--;
*pfBadDBCS = TRUE;
break;
}
i += 2;
}
else if ('\n' == pszT[i] || '\r' == pszT[i])
{
MoveMemory(pszT + i, pszT + (i + 1), cbT - i);
cbT--;
}
else
{
i++;
}
}
return cbT;
}
#define CB_STREAMMATCH 0x00000FFF
// --------------------------------------------------------------------------------
// StreamSubStringMatch
// --------------------------------------------------------------------------------
OESTDAPI_(BOOL) StreamSubStringMatch(LPSTREAM pstm, CHAR * pszSearch)
{
BOOL fRet = FALSE;
ULONG cbSave = 0;
LONG cbSize = 0;
CHAR rgchBuff[CB_STREAMMATCH + 1];
LPSTR pszRead = NULL;
ULONG cbRead = 0;
ULONG cbIn = 0;
BOOL fBadDBCS = FALSE;
CHAR chSave = 0;
// Check incoming params
if ((NULL == pstm) || (NULL == pszSearch))
{
goto exit;
}
// We want to save off the entire string and
// a possible ending lead byte...
cbSave = lstrlen(pszSearch);
// Get the stream size
if (FAILED(HrGetStreamSize(pstm, (ULONG *) &cbSize)))
{
goto exit;
}
// Reset the stream to the beginning
if (FAILED(HrRewindStream(pstm)))
{
goto exit;
}
// Set up the defaults
pszRead = rgchBuff;
cbRead = CB_STREAMMATCH;
// Search for string through the entire stream
while ((cbSize > 0) && (S_OK == pstm->Read(pszRead, cbRead, &cbIn)))
{
// We're done if we read nothing...
if (0 == cbIn)
{
goto exit;
}
// Note that we've read the bytes
cbSize -= cbIn;
// Raid 2741: FIND: OE: FE: Find Text/Message to be able to find wrapped DBCS words in plain text message body
cbIn = RemoveCRLF(rgchBuff, (DWORD) (cbIn + pszRead - rgchBuff), &fBadDBCS);
// Do we need to save the char
if (FALSE != fBadDBCS)
{
chSave = rgchBuff[cbIn];
}
// Terminate the buffer
rgchBuff[cbIn] = '\0';
// Search for string
if (NULL != StrStrIA(rgchBuff, pszSearch))
{
fRet = TRUE;
break;
}
// Are we done with the stream
if (0 >= cbSize)
{
break;
}
// Do we need to restore the char
if (FALSE != fBadDBCS)
{
rgchBuff[cbIn] = chSave;
cbIn++;
}
// Save part of the buffer
// How much space do we have in the buffer
cbRead = CB_STREAMMATCH - cbSave;
// Save the characters
MoveMemory(rgchBuff, rgchBuff + cbIn - cbSave, cbSave);
// Figure out the new start of the buffer
pszRead = rgchBuff + cbSave;
}
exit:
return(fRet);
}