#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; } }