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.
176 lines
4.7 KiB
176 lines
4.7 KiB
#include "stdinc.h"
|
|
#include "win32file.h"
|
|
#include "atlbase.h"
|
|
#include "atlconv.h"
|
|
|
|
#define IS_NT() ((GetVersion() & 0x80000000) == 0)
|
|
|
|
using std::wstring;
|
|
|
|
void Win32File::snarfFullFile(wstring& output)
|
|
{
|
|
output = L"";
|
|
CByteVector bytes;
|
|
DWORD dwReadSize = 0;
|
|
|
|
bytes.resize(filesize() - filepointer());
|
|
if (!ReadFile(_hFile, &bytes.front(), bytes.size(), &dwReadSize, NULL))
|
|
{
|
|
throw new ReadWriteError(false, ::GetLastError());
|
|
}
|
|
|
|
// Otherwise, bash the byte vector into a wstring for output
|
|
output = ConvertToWstring(bytes, _type);
|
|
}
|
|
|
|
|
|
|
|
|
|
void Win32File::writeLine(const wstring& dump)
|
|
{
|
|
CByteVector vb;
|
|
DWORD dwWritten;
|
|
|
|
vb = ConvertWstringToDestination(dump, _type);
|
|
if (!WriteFile(_hFile, &vb.front(), vb.size(), &dwWritten, NULL))
|
|
throw new ReadWriteError(true, ::GetLastError());
|
|
}
|
|
|
|
|
|
|
|
bool Win32File::eof() { return false; }
|
|
|
|
void
|
|
Win32File::openForRead(wstring wstname)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
if (_hFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
throw new AlreadyOpened;
|
|
}
|
|
|
|
const PCWSTR pcwstr = wstname.c_str();
|
|
const DWORD Flags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN;
|
|
|
|
_hFile =
|
|
IS_NT() ? CreateFileW(pcwstr, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, Flags, NULL)
|
|
: CreateFileA(W2A(pcwstr), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, Flags, NULL);
|
|
|
|
if (_hFile == INVALID_HANDLE_VALUE || _hFile == NULL)
|
|
{
|
|
throw new OpeningError(GetLastError());
|
|
}
|
|
|
|
|
|
// If this was for reading, then sniff the first few bytes and see what kind
|
|
// of file it is.
|
|
DWORD dwReadBytes = 0;
|
|
BYTE bBuffer[256];
|
|
if (!ReadFile(_hFile, bBuffer, sizeof(bBuffer), &dwReadBytes, NULL))
|
|
{
|
|
throw new ReadWriteError(true, GetLastError());
|
|
}
|
|
|
|
// Now let's determine what kind of buffer we've got
|
|
_type = DetermineFileTypeFromBuffer(bBuffer, dwReadBytes);
|
|
_bOpenForRead = true;
|
|
|
|
// Let's zip the file pointer past the first gunk
|
|
SetFilePointer(_hFile, DetermineFileTypeSigSize(_type), NULL, FILE_BEGIN);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
Win32File::openForWrite(wstring wstname, FileContentType fct, bool bOverwrite)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
if (_hFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
throw new AlreadyOpened;
|
|
}
|
|
|
|
const DWORD OpenOrCreate = bOverwrite ? CREATE_ALWAYS : CREATE_NEW;
|
|
const DWORD Flags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN;
|
|
PCWSTR pcwstr = wstname.c_str();
|
|
|
|
_hFile =
|
|
IS_NT() ? CreateFileW(pcwstr, GENERIC_WRITE, FILE_SHARE_READ, NULL, OpenOrCreate, Flags, NULL)
|
|
: CreateFileA(W2A(pcwstr), GENERIC_WRITE, FILE_SHARE_READ, NULL, OpenOrCreate, Flags, NULL);
|
|
|
|
if (_hFile == INVALID_HANDLE_VALUE || _hFile == NULL)
|
|
{
|
|
throw new OpeningError(GetLastError());
|
|
}
|
|
|
|
// Now that we have an open file, let's blop the signature bytes into it.
|
|
DWORD dwWritten;
|
|
DWORD dwToWrite;
|
|
PCVOID pvWriteBuffer;
|
|
switch (fct) {
|
|
case FileContentsUnicode:
|
|
pvWriteBuffer = UNICODE_SIGNATURE;
|
|
dwToWrite = sizeof(UNICODE_SIGNATURE);
|
|
break;
|
|
case FileContentsUnicodeBigEndian:
|
|
pvWriteBuffer = UNICODE_BIG_ENDIAN_SIGNATURE;
|
|
dwToWrite = sizeof(UNICODE_BIG_ENDIAN_SIGNATURE);
|
|
break;
|
|
case FileContentsUTF8:
|
|
pvWriteBuffer = NULL;
|
|
dwToWrite = 0;
|
|
break;
|
|
default:
|
|
pvWriteBuffer = UNICODE_SIGNATURE;
|
|
dwToWrite = 0;
|
|
break;
|
|
}
|
|
|
|
if (!WriteFile(_hFile, pvWriteBuffer, dwToWrite, &dwWritten, NULL) || (dwWritten != dwToWrite)) {
|
|
throw new ReadWriteError(false, GetLastError());
|
|
}
|
|
|
|
_bOpenForRead = false;
|
|
_type = fct;
|
|
}
|
|
|
|
|
|
|
|
|
|
Win32File::Win32File()
|
|
: _hFile(INVALID_HANDLE_VALUE), _type(FileContentsUTF8),
|
|
_bOpenForRead(false), _bEof(false)
|
|
{
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Win32File::~Win32File() { if (_hFile != INVALID_HANDLE_VALUE) { CloseHandle(_hFile); } };
|
|
|
|
|
|
FileContentType DetermineFileTypeFromBuffer(unsigned char *data, int length)
|
|
{
|
|
#define CHECKMARK(tp, ct) if ((length > sizeof(tp)) && (memcmp(data, tp, sizeof(tp)) == 0)) return ct;
|
|
|
|
CHECKMARK(UNICODE_SIGNATURE, FileContentsUnicode);
|
|
CHECKMARK(UNICODE_BIG_ENDIAN_SIGNATURE, FileContentsUnicodeBigEndian);
|
|
CHECKMARK(UTF8_SIGNATURE, FileContentsUTF8);
|
|
return FileContentsUTF8;
|
|
}
|
|
|
|
int DetermineFileTypeSigSize(FileContentType type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case FileContentsUnicode: return sizeof(UNICODE_SIGNATURE);
|
|
case FileContentsUnicodeBigEndian: return sizeof(UNICODE_BIG_ENDIAN_SIGNATURE);
|
|
case FileContentsUTF8:
|
|
default: return 0;
|
|
}
|
|
}
|