You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1500 lines
41 KiB
1500 lines
41 KiB
// --------------------------------------------------------------------------------
|
|
// 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);
|
|
}
|
|
|