tsMuxer/libmediation/fs/osdep/file_win32.cpp

264 lines
5.9 KiB
C++
Raw Normal View History

#include "../file.h"
#include "../directory.h"
#include <sstream>
#include <io.h>
#include <windows.h>
void throwFileError()
{
char msgBuf[32*1024];
memset( msgBuf, 0, sizeof(msgBuf) );
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &msgBuf,
sizeof(msgBuf),
NULL );
throw std::runtime_error( msgBuf );
}
void makeWin32OpenFlags(
unsigned int oflag,
DWORD* const dwDesiredAccess,
DWORD* const dwCreationDisposition,
DWORD* const dwShareMode )
{
*dwDesiredAccess = 0;
*dwCreationDisposition = CREATE_ALWAYS;
if( oflag & File::ofRead )
{
*dwDesiredAccess = GENERIC_READ & ~SYNCHRONIZE;
*dwCreationDisposition = OPEN_EXISTING;
*dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
}
if( oflag & File::ofWrite )
{
*dwDesiredAccess |= GENERIC_WRITE & ~SYNCHRONIZE;
*dwCreationDisposition = CREATE_ALWAYS;
*dwShareMode = FILE_SHARE_READ;
}
if( oflag & File::ofAppend )
*dwCreationDisposition = OPEN_ALWAYS;
if( oflag & File::ofNoTruncate)
*dwCreationDisposition = OPEN_ALWAYS;
if( oflag & File::ofOpenExisting )
*dwCreationDisposition = OPEN_EXISTING;
if( oflag & File::ofCreateNew )
*dwCreationDisposition = CREATE_NEW;
}
File::File():
AbstractOutputStream(),
m_impl( INVALID_HANDLE_VALUE ),
m_name ( "" ),
m_pos(0)
{
}
File::File( const char* fName, unsigned int oflag, unsigned int systemDependentFlags ) /* throw ( std::runtime_error ) */:
AbstractOutputStream(),
m_impl( INVALID_HANDLE_VALUE ),
m_name ( fName ),
m_pos(0)
{
DWORD dwDesiredAccess = 0;
DWORD dwCreationDisposition = CREATE_ALWAYS;
DWORD dwShareMode = 0;
makeWin32OpenFlags( oflag, &dwDesiredAccess, &dwCreationDisposition, &dwShareMode );
if( !systemDependentFlags )
{
if( (oflag & ofRead) && !(oflag & ofWrite) )
systemDependentFlags = FILE_FLAG_SEQUENTIAL_SCAN;
else
systemDependentFlags = FILE_FLAG_RANDOM_ACCESS;
}
m_impl = CreateFile(
fName,
dwDesiredAccess,
dwShareMode,
NULL,
dwCreationDisposition,
systemDependentFlags,
NULL );
if( m_impl == INVALID_HANDLE_VALUE )
{
throwFileError();
}
else
{
if( oflag & File::ofAppend ) {
long hiword = 0;
DWORD newPointerLow = SetFilePointer( m_impl, 0, &hiword, FILE_END );
if( newPointerLow == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR )
throwFileError();
}
}
}
File::~File()
{
if( isOpen() )
close();
}
bool File::open( const char* fName, unsigned int oflag, unsigned int systemDependentFlags )
{
m_name = fName;
m_pos = 0;
DWORD dwDesiredAccess = 0;
DWORD dwCreationDisposition = CREATE_ALWAYS;
DWORD dwShareMode = 0;
makeWin32OpenFlags( oflag, &dwDesiredAccess, &dwCreationDisposition, &dwShareMode );
if( !systemDependentFlags )
{
if( (oflag & ofRead) && !(oflag & ofWrite) )
systemDependentFlags = FILE_FLAG_SEQUENTIAL_SCAN;
else
systemDependentFlags = FILE_FLAG_RANDOM_ACCESS;
}
createDir ( extractFileDir ( fName ), true );
m_impl = CreateFile(
fName,
dwDesiredAccess,
dwShareMode,
NULL,
dwCreationDisposition,
systemDependentFlags,
NULL );
if( m_impl == INVALID_HANDLE_VALUE )
{
return false;
}
else
{
if( oflag & File::ofAppend ) {
long hiword = 0;
DWORD newPointerLow = SetFilePointer( m_impl, 0, &hiword, FILE_END );
if( newPointerLow == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR )
throwFileError();
}
}
return true;
}
bool File::close()
{
//sync();
BOOL res = CloseHandle( m_impl );
m_impl = INVALID_HANDLE_VALUE;
return res != 0;
}
int File::read( void* buffer, uint32_t count ) const
{
if( !isOpen() )
return -1;
DWORD bytesRead = 0;
BOOL res = ReadFile( m_impl, buffer, count, &bytesRead, NULL );
if( !res )
return -1;
m_pos += bytesRead;
return (int)bytesRead;
}
int File::write( const void* buffer, uint32_t count )
{
if( !isOpen() )
return -1;
DWORD bytesWritten = 0;
BOOL res = WriteFile( m_impl, buffer, count, &bytesWritten, NULL );
if( !res )
{
throwFileError();
}
if( !res )
return -1;
m_pos += bytesWritten;
return (int)bytesWritten;
}
void File::sync()
{
FlushFileBuffers( m_impl );
}
bool File::isOpen() const
{
return m_impl != INVALID_HANDLE_VALUE;
}
bool File::size( uint64_t* const fileSize ) const
{
DWORD highDw;
DWORD lowDw = GetFileSize( m_impl, &highDw );
if( (lowDw == INVALID_FILE_SIZE) && (GetLastError() != NO_ERROR) )
return false;
*fileSize = highDw;
*fileSize <<= 32;
*fileSize |= lowDw;
return true;
}
uint64_t File::seek( int64_t offset, SeekMethod whence )
{
if( !isOpen() )
return (uint64_t)-1;
DWORD moveMethod = 0;
switch( whence )
{
case smBegin:
moveMethod = FILE_BEGIN;
break;
case smCurrent:
moveMethod = FILE_CURRENT;
break;
case smEnd:
moveMethod = FILE_END;
break;
}
LONG distanceToMoveLow = (uint32_t)(offset & 0xffffffff);
LONG distanceToMoveHigh = (uint32_t)((offset & 0xffffffff00000000ull) >> 32);
DWORD newPointerLow = SetFilePointer( m_impl, distanceToMoveLow, &distanceToMoveHigh, moveMethod );
if( newPointerLow == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR )
return (uint64_t)-1;
m_pos = newPointerLow | ((uint64_t)distanceToMoveHigh << 32);
return m_pos;
}
bool File::truncate( uint64_t newFileSize)
{
LONG distanceToMoveLow = (uint32_t)(newFileSize & 0xffffffff);
LONG distanceToMoveHigh = (uint32_t)((newFileSize & 0xffffffff00000000ull) >> 32);
DWORD newPointerLow = SetFilePointer(
m_impl,
distanceToMoveLow,
&distanceToMoveHigh,
FILE_BEGIN );
int errCode = GetLastError();
if( (newPointerLow == INVALID_SET_FILE_POINTER) && (errCode != NO_ERROR) )
//return false;
throwFileError();
return SetEndOfFile( m_impl ) > 0;
}