windows-nt/Source/XPSP1/NT/base/win32/fusion/tools/buildtool/filestream.cpp
2020-09-26 16:20:57 +08:00

408 lines
6.9 KiB
C++

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
filestream.cpp
Abstract:
Implementation of IStream over a win32 file.
Author:
Michael J. Grier (MGrier) 23-Feb-2000
Revision History:
--*/
#include "stdinc.h"
#include "helpers.h"
#include <windows.h>
#define UNUSED(x)
BOOL
MySetFilePointerEx(
HANDLE File, // handle to file
LARGE_INTEGER DistanceToMove, // bytes to move pointer
PLARGE_INTEGER NewFilePointer, // new file pointer
DWORD MoveMethod // starting point
)
{
LONG DistanceToMoveLow = static_cast<LONG>(DistanceToMove.LowPart);
LONG DistanceToMoveHigh = DistanceToMove.HighPart;
DWORD NewPositionLow = SetFilePointer(File, DistanceToMoveLow, &DistanceToMoveHigh, MoveMethod);
if (NewPositionLow == INVALID_SET_FILE_POINTER)
{
if (GetLastError() != NO_ERROR)
return FALSE;
}
if (NewFilePointer != NULL)
{
NewFilePointer->LowPart = NewPositionLow;
NewFilePointer->HighPart = DistanceToMoveHigh;
}
return TRUE;
}
CFileStreamBase::~CFileStreamBase()
{
const DWORD dwLastError = ::GetLastError();
Close();
::SetLastError(dwLastError);
}
bool
CFileStreamBase::OpenForWrite(string pszPath)
{
if (m_hFile != INVALID_HANDLE_VALUE)
return false;
m_hFile = ::CreateFileA(
pszPath.c_str(),
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
return (m_hFile != INVALID_HANDLE_VALUE);
}
bool
CFileStreamBase::OpenForRead(string pszPath)
{
if (m_hFile != INVALID_HANDLE_VALUE)
return false;
m_hFile = ::CreateFileA(
pszPath.c_str(),
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
return (m_hFile != INVALID_HANDLE_VALUE);
}
bool
CFileStreamBase::Close()
{
if (m_hFile != INVALID_HANDLE_VALUE)
{
if (!::CloseHandle(m_hFile))
{
return false;
}
m_hFile = INVALID_HANDLE_VALUE;
}
return true;
}
ULONG
CFileStreamBase::AddRef()
{
return ::InterlockedIncrement(&m_cRef);
}
ULONG
CFileStreamBase::Release()
{
const ULONG ulRefCount = ::InterlockedDecrement(&m_cRef);
if ( ulRefCount == 0 )
{
delete this;
return 0;
}
else
{
return ulRefCount;
}
}
HRESULT
CFileStreamBase::QueryInterface(
REFIID riid,
PVOID *ppvObj
)
{
HRESULT hr = NOERROR;
IUnknown *pIUnknown = NULL;
if (ppvObj != NULL)
*ppvObj = NULL;
if (ppvObj == NULL)
{
hr = E_POINTER;
goto Exit;
}
if ((riid == IID_IUnknown) ||
(riid == IID_ISequentialStream) ||
(riid == IID_IStream))
pIUnknown = static_cast<IStream *>(this);
if (pIUnknown == NULL)
{
hr = E_NOINTERFACE;
goto Exit;
}
pIUnknown->AddRef();
*ppvObj = pIUnknown;
hr = NOERROR;
Exit:
return hr;
}
HRESULT
CFileStreamBase::Read(
void *pv,
ULONG cb,
ULONG *pcbRead
)
{
HRESULT hr = NOERROR;
ULONG cbRead = 0;
if (pcbRead != NULL)
*pcbRead = 0;
if (m_hFile == INVALID_HANDLE_VALUE)
{
hr = E_UNEXPECTED;
goto Exit;
}
if (!m_bSeenFirstCharacter)
{
#ifdef AWFUL_SPACE_HACK
while (true)
{
CHAR ch;
ReadFile(m_hFile, &ch, 1, &cbRead, NULL);
if ((ch != '\n') && (ch != '\r') && (ch != ' ') && (ch != '\t')) {
m_bSeenFirstCharacter = true;
LARGE_INTEGER li;
li.QuadPart = -1;
::MySetFilePointerEx(m_hFile, li, NULL, FILE_CURRENT);
break;
}
}
#endif
}
if (!::ReadFile(m_hFile, pv, cb, &cbRead, NULL))
{
hr = HRESULT_FROM_WIN32(::GetLastError());
goto Exit;
}
if (cbRead == 0)
hr = S_FALSE;
else
hr = NOERROR;
if (pcbRead != NULL)
*pcbRead = cbRead;
Exit:
return hr;
}
HRESULT
CFileStreamBase::Write(
void const *pv,
ULONG cb,
ULONG *pcbWritten
)
{
HRESULT hr = NOERROR;
ULONG cbWritten = 0;
if (pcbWritten != NULL)
*pcbWritten = 0;
if (m_hFile == INVALID_HANDLE_VALUE)
{
hr = E_UNEXPECTED;
goto Exit;
}
if (!::WriteFile(m_hFile, pv, cb, &cbWritten, NULL))
{
hr = HRESULT_FROM_WIN32(::GetLastError());
goto Exit;
}
if (cbWritten == 0)
hr = S_FALSE;
else
hr = NOERROR;
if (pcbWritten != NULL)
*pcbWritten = cbWritten;
Exit:
return hr;
}
HRESULT
CFileStreamBase::Seek(
LARGE_INTEGER dlibMove,
DWORD dwOrigin,
ULARGE_INTEGER *plibNewPosition
)
{
HRESULT hr = NOERROR;
DWORD dwWin32Origin = 0;
if (m_hFile == INVALID_HANDLE_VALUE)
{
hr = E_UNEXPECTED;
goto Exit;
}
switch (dwOrigin)
{
default:
hr = E_INVALIDARG;
goto Exit;
case STREAM_SEEK_SET:
dwWin32Origin = FILE_BEGIN;
break;
case STREAM_SEEK_CUR:
dwWin32Origin = FILE_CURRENT;
break;
case STREAM_SEEK_END:
dwWin32Origin = FILE_END;
break;
}
if (!::MySetFilePointerEx(
m_hFile,
dlibMove,
(LARGE_INTEGER *) plibNewPosition,
dwWin32Origin))
{
hr = HRESULT_FROM_WIN32(::GetLastError());
goto Exit;
}
hr = NOERROR;
Exit:
return hr;
}
HRESULT
CFileStreamBase::SetSize(
ULARGE_INTEGER libNewSize
)
{
UNUSED(libNewSize);
return E_NOTIMPL;
}
HRESULT
CFileStreamBase::CopyTo(
IStream *pstm,
ULARGE_INTEGER cb,
ULARGE_INTEGER *pcbRead,
ULARGE_INTEGER *pcbWritten
)
{
if (pcbRead != NULL)
pcbRead->QuadPart = 0;
if (pcbWritten != NULL)
pcbWritten->QuadPart = 0;
return E_NOTIMPL;
}
HRESULT
CFileStreamBase::Commit(
DWORD grfCommitFlags
)
{
HRESULT hr = NOERROR;
if (grfCommitFlags != 0)
return E_INVALIDARG;
if (!Close())
hr = HRESULT_FROM_WIN32 (GetLastError());
return hr;
}
HRESULT
CFileStreamBase::Revert()
{
return E_NOTIMPL;
}
HRESULT
CFileStreamBase::LockRegion(
ULARGE_INTEGER libOffset,
ULARGE_INTEGER cb,
DWORD dwLockType
)
{
UNUSED(libOffset);
UNUSED(cb);
UNUSED(dwLockType);
return E_NOTIMPL;
}
HRESULT
CFileStreamBase::UnlockRegion(
ULARGE_INTEGER libOffset,
ULARGE_INTEGER cb,
DWORD dwLockType
)
{
UNUSED(libOffset);
UNUSED(cb);
UNUSED(dwLockType);
return E_NOTIMPL;
}
HRESULT
CFileStreamBase::Stat(
STATSTG *pstatstg,
DWORD grfStatFlag
)
{
if (pstatstg != NULL)
memset(pstatstg, 0, sizeof(*pstatstg));
return E_NOTIMPL;
}
HRESULT
CFileStreamBase::Clone(
IStream **ppIStream
)
{
if (ppIStream != NULL)
*ppIStream = NULL;
return E_NOTIMPL;
}