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.
407 lines
7.3 KiB
407 lines
7.3 KiB
/*++
|
|
|
|
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(wstring pszPath)
|
|
{
|
|
if (m_hFile != INVALID_HANDLE_VALUE)
|
|
return false;
|
|
|
|
m_hFile = ::CreateFileW(
|
|
pszPath.c_str(),
|
|
GENERIC_WRITE,
|
|
0,
|
|
NULL,
|
|
CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL);
|
|
|
|
return (m_hFile != INVALID_HANDLE_VALUE);
|
|
}
|
|
|
|
bool
|
|
CFileStreamBase::OpenForRead(wstring pszPath)
|
|
{
|
|
if (m_hFile != INVALID_HANDLE_VALUE)
|
|
return false;
|
|
|
|
m_hFile = ::CreateFileW(
|
|
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;
|
|
}
|
|
|