566 lines
9.5 KiB
C++
566 lines
9.5 KiB
C++
/*++
|
|
|
|
Copyright (C) Microsoft Corporation, 1998 - 1999
|
|
All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
Stream.cxx
|
|
|
|
Abstract:
|
|
|
|
implements TStream class methods
|
|
|
|
Author:
|
|
|
|
Adina Trufinescu (AdinaTru) 4-Nov-1998
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#include "stream.hxx"
|
|
|
|
/*++
|
|
|
|
Title:
|
|
|
|
TStream
|
|
|
|
Routine Description:
|
|
|
|
Initialize the TStream class; note the class is initaliy
|
|
in an in valid state until a read or write occurs in which
|
|
case the file handle is created and then the class becomes valid.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Nothing
|
|
|
|
--*/
|
|
TStream::
|
|
TStream(
|
|
IN TString& strFileName
|
|
) : m_strFileName(strFileName),
|
|
m_hFileHandle(INVALID_HANDLE_VALUE),
|
|
m_dwAccess(0),
|
|
m_bCreated(FALSE)
|
|
{
|
|
m_uliStreamSize.QuadPart = 0;
|
|
}
|
|
|
|
/*++
|
|
|
|
Title:
|
|
|
|
~TStream
|
|
|
|
Routine Description:
|
|
|
|
Releases the stream file handle.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Nothing
|
|
|
|
--*/
|
|
TStream::
|
|
~TStream(
|
|
VOID
|
|
)
|
|
{
|
|
if(m_hFileHandle != INVALID_HANDLE_VALUE)
|
|
{
|
|
CloseHandle(m_hFileHandle);
|
|
}
|
|
}
|
|
|
|
/*++
|
|
|
|
Title:
|
|
|
|
bValid
|
|
|
|
Routine Description:
|
|
|
|
check class member validity : file handle invalid
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
TRUE if class is in a valid state.
|
|
|
|
--*/
|
|
BOOL
|
|
TStream::
|
|
bValid(
|
|
VOID
|
|
)
|
|
{
|
|
return (m_hFileHandle != INVALID_HANDLE_VALUE);
|
|
}
|
|
|
|
/*++
|
|
|
|
Title:
|
|
|
|
Read
|
|
|
|
Routine Description:
|
|
|
|
Reads cb bytes into pv , from current position of file.
|
|
Number of actual reded bytes stored in pbcRead
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
The error code from ReadFile API is converted to HRESULT
|
|
|
|
--*/
|
|
HRESULT
|
|
TStream::
|
|
Read(
|
|
VOID *pv,
|
|
ULONG cb,
|
|
ULONG *pcbRead
|
|
)
|
|
{
|
|
TStatusH hr;
|
|
|
|
if(!bValid())
|
|
{
|
|
m_hFileHandle = PCreateFile(&m_dwAccess);
|
|
|
|
if(!bValid())
|
|
{
|
|
hr DBGCHK = E_UNEXPECTED;
|
|
|
|
goto End;
|
|
}
|
|
}
|
|
|
|
if(bValid())
|
|
{
|
|
if(pv)
|
|
{
|
|
if(!ReadFile( m_hFileHandle,
|
|
reinterpret_cast<LPDWORD>(pv),
|
|
static_cast<DWORD>(cb),
|
|
reinterpret_cast<LPDWORD>(pcbRead),
|
|
NULL))
|
|
{
|
|
*pcbRead = 0;
|
|
|
|
hr DBGCHK = MapWin32ErrorCodeToHRes(GetLastError());
|
|
|
|
goto End;
|
|
|
|
}
|
|
|
|
hr DBGCHK = ((*pcbRead) == cb) && (*pcbRead != 0 && cb != 0) ? S_OK : E_FAIL;
|
|
|
|
}
|
|
else
|
|
{
|
|
hr DBGCHK = STG_E_INVALIDPOINTER;
|
|
}
|
|
}
|
|
|
|
End:
|
|
|
|
return hr;
|
|
|
|
}
|
|
/*++
|
|
|
|
Title:
|
|
|
|
Write
|
|
|
|
Routine Description:
|
|
|
|
Writes cb bytes from pv , at current position of file.
|
|
Number of actual written bytes stored in pcbWritten
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
The error code from WriteFile API is converted to HRESULT
|
|
|
|
--*/
|
|
HRESULT
|
|
TStream::
|
|
Write(
|
|
VOID const* pv,
|
|
ULONG cb,
|
|
ULONG * pcbWritten
|
|
)
|
|
{
|
|
HRESULT hr = E_UNEXPECTED;
|
|
|
|
if(!bValid())
|
|
{
|
|
m_hFileHandle = PCreateFile(&m_dwAccess);
|
|
|
|
if(!bValid())
|
|
{
|
|
goto End;
|
|
}
|
|
}
|
|
|
|
if(bValid())
|
|
{
|
|
if(pv)
|
|
{
|
|
if(!WriteFile(m_hFileHandle,
|
|
static_cast<LPCVOID>(pv),
|
|
static_cast<DWORD>(cb),
|
|
reinterpret_cast<LPDWORD>(pcbWritten),
|
|
NULL))
|
|
{
|
|
if (pcbWritten)
|
|
{
|
|
*pcbWritten = 0;
|
|
}
|
|
|
|
hr = MapWin32ErrorCodeToHRes(GetLastError());
|
|
}
|
|
|
|
if (pcbWritten)
|
|
{
|
|
hr = (*pcbWritten == cb) ? S_OK : hr;
|
|
}
|
|
else
|
|
{
|
|
hr = STG_E_INVALIDPOINTER;
|
|
}
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
DBGMSG( DBG_NONE, ( "TPrnStream::Write OK !!!\n" ));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = STG_E_INVALIDPOINTER;
|
|
}
|
|
}
|
|
|
|
End:
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
/*++
|
|
|
|
Title:
|
|
|
|
Seek
|
|
|
|
Routine Description:
|
|
|
|
Set stream pointer
|
|
|
|
Arguments:
|
|
|
|
dlibMove - Offset relative to dwOrigin
|
|
dwOrigin - Specifies the origin for the offset
|
|
plibNewPosition - Pointer to location containing new seek
|
|
|
|
Return Value:
|
|
|
|
The error code from SetFilePointer API is converted to HRESULT
|
|
|
|
--*/
|
|
HRESULT
|
|
TStream::
|
|
Seek(
|
|
LARGE_INTEGER dlibMove,
|
|
DWORD dwOrigin,
|
|
ULARGE_INTEGER * plibNewPosition
|
|
)
|
|
{
|
|
DWORD dwMoveMethod;
|
|
DWORD dwCurrentFilePosition ;
|
|
LONG lDistanceToMoveHigh;
|
|
|
|
TStatusB bStatus;
|
|
TStatusH hr;
|
|
DWORD dwError;
|
|
|
|
static const DWORD adwMoveMethode[] =
|
|
{
|
|
FILE_BEGIN,
|
|
FILE_CURRENT,
|
|
FILE_END,
|
|
};
|
|
|
|
dwMoveMethod = adwMoveMethode[dwOrigin];
|
|
|
|
if(!bValid())
|
|
{
|
|
m_hFileHandle = PCreateFile(&m_dwAccess);
|
|
|
|
if(!bValid())
|
|
{
|
|
hr DBGCHK = E_UNEXPECTED;
|
|
|
|
goto End;
|
|
}
|
|
}
|
|
|
|
|
|
lDistanceToMoveHigh = dlibMove.HighPart;
|
|
|
|
dwCurrentFilePosition = SetFilePointer( m_hFileHandle,
|
|
static_cast<LONG>(dlibMove.LowPart),
|
|
&lDistanceToMoveHigh,
|
|
dwMoveMethod );
|
|
|
|
DBGMSG( DBG_NONE, ( "Seek: Current pos: high %d low %d\n" ,lDistanceToMoveHigh, dwCurrentFilePosition) );
|
|
|
|
if (dwCurrentFilePosition == 0xFFFFFFFF && (dwError = GetLastError()) != NO_ERROR )
|
|
{
|
|
hr DBGCHK = MapWin32ErrorCodeToHRes(dwError);
|
|
}
|
|
else
|
|
{
|
|
if(plibNewPosition)
|
|
{
|
|
plibNewPosition->HighPart = static_cast<DWORD>(lDistanceToMoveHigh);
|
|
|
|
plibNewPosition->LowPart = dwCurrentFilePosition;
|
|
}
|
|
|
|
hr DBGNOCHK = S_OK;
|
|
}
|
|
|
|
End:
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Title:
|
|
|
|
PCreateFile
|
|
|
|
Routine Description:
|
|
|
|
If file doesn't exists , create it with write / read access
|
|
If file exists , try open it with read wrire access ; if fail , try to open with read
|
|
|
|
Arguments:
|
|
|
|
pdwAccess - access rights if succeeded , 0 if failed
|
|
|
|
Return Value:
|
|
|
|
The error code from SetFilePointer API is converted to HRESULT
|
|
|
|
--*/
|
|
HANDLE
|
|
TStream::
|
|
PCreateFile(
|
|
OUT LPDWORD pdwAccess
|
|
)
|
|
{
|
|
HANDLE hFileHandle;
|
|
DWORD dwAccess;
|
|
|
|
*pdwAccess = 0;
|
|
|
|
//
|
|
// try to open an existing file with read/write access
|
|
//
|
|
dwAccess = GENERIC_WRITE | GENERIC_READ;
|
|
|
|
hFileHandle = CreateFile( m_strFileName,
|
|
dwAccess,
|
|
0,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL);
|
|
|
|
if(hFileHandle == INVALID_HANDLE_VALUE)
|
|
{
|
|
//
|
|
// if last error is access denied , try to open only with read access
|
|
//
|
|
if(GetLastError() == ERROR_ACCESS_DENIED)
|
|
{
|
|
dwAccess = GENERIC_READ;
|
|
|
|
hFileHandle = CreateFile( m_strFileName,
|
|
GENERIC_READ,
|
|
0,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL);
|
|
}
|
|
else if(GetLastError() == ERROR_FILE_NOT_FOUND)
|
|
{
|
|
dwAccess = GENERIC_WRITE | GENERIC_READ;
|
|
|
|
//
|
|
// if last error was file don't exist , try to create it
|
|
//
|
|
hFileHandle = CreateFile( m_strFileName,
|
|
dwAccess,
|
|
0,
|
|
NULL,
|
|
OPEN_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL);
|
|
|
|
m_bCreated = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
if(hFileHandle != INVALID_HANDLE_VALUE)
|
|
{
|
|
*pdwAccess = dwAccess;
|
|
|
|
m_uliStreamSize.LowPart = GetFileSize(hFileHandle, &m_uliStreamSize.HighPart);
|
|
}
|
|
|
|
return hFileHandle;
|
|
|
|
}
|
|
|
|
/*++
|
|
|
|
Title:
|
|
|
|
DestroyFile
|
|
|
|
Routine Description:
|
|
|
|
If file handle is invalid , it means that file wasn't creaded - return TRUE
|
|
If file handle is valid , close it and delete file
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
TRUE if succeeded
|
|
|
|
--*/
|
|
HRESULT
|
|
TStream::
|
|
DestroyFile(
|
|
VOID
|
|
)
|
|
{
|
|
TStatusB bStatus;
|
|
|
|
bStatus DBGNOCHK = TRUE;
|
|
|
|
if(m_hFileHandle != INVALID_HANDLE_VALUE)
|
|
{
|
|
CloseHandle(m_hFileHandle);
|
|
|
|
m_hFileHandle = INVALID_HANDLE_VALUE;
|
|
|
|
bStatus DBGCHK = DeleteFile(m_strFileName);
|
|
}
|
|
|
|
return bStatus ? S_OK : MapWin32ErrorCodeToHRes(GetLastError());
|
|
}
|
|
|
|
/*++
|
|
|
|
Title:
|
|
|
|
bSetEndOfFile
|
|
|
|
Routine Description:
|
|
|
|
If file handle is valid , set end of file
|
|
Needed it for truncating the file in case of overwritting
|
|
Called at the end of every successfull storing
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
TRUE if succeeded
|
|
|
|
--*/
|
|
BOOL
|
|
TStream::
|
|
bSetEndOfFile(
|
|
VOID
|
|
)
|
|
{
|
|
TStatusB bStatus;
|
|
|
|
bStatus DBGCHK = (m_hFileHandle != INVALID_HANDLE_VALUE);
|
|
|
|
if(bStatus)
|
|
{
|
|
bStatus DBGCHK = SetEndOfFile(m_hFileHandle);
|
|
}
|
|
|
|
return bStatus;
|
|
|
|
}
|
|
|
|
/*++
|
|
|
|
Title:
|
|
|
|
MapWin32ErrorCodeToHRes
|
|
|
|
Routine Description:
|
|
|
|
maps file error codes to HRESULT errors
|
|
|
|
Arguments:
|
|
|
|
Error value to convert
|
|
|
|
Return Value:
|
|
|
|
Converted error value to an HRESULT
|
|
|
|
Last Error:
|
|
|
|
--*/
|
|
HRESULT
|
|
TStream::
|
|
MapWin32ErrorCodeToHRes(
|
|
IN DWORD dwErrorCode
|
|
)
|
|
{
|
|
return MAKE_HRESULT( SEVERITY_ERROR, FACILITY_STORAGE, dwErrorCode);
|
|
}
|