#if defined(__FLAT__)
#ifndef _COMMON_OPENFILE_HPP_
#define _COMMON_OPENFILE_HPP_
#ifndef _COMMON_WINDOWS_HPP_
#include <common/windows.hpp>
#endif
#ifndef _COMMON_STRING_HPP_
#include <common/string.hpp>
#endif
#ifndef _COMMON_FILETIME_HPP_
#include <common/filetime.hpp>
#endif
#ifndef _COMMON_SYSTEMTIME_HPP_
#include <common/systime.hpp>
#endif
#ifndef _COMMON_OVERLAPPED_HPP_
#include <common/overlap.hpp>
#endif

class Overlapped;

class FileHandle
{
public:
  enum {ErrorReturn=0xFFFFFFFF};
	enum Method{SeekBegin=FILE_BEGIN,SeekCurrent=FILE_CURRENT,SeekEnd=FILE_END};
	enum Mode{Create=CREATE_NEW,Overwrite=CREATE_ALWAYS,Open=OPEN_EXISTING};
	enum Share{ShareNone=0,ShareRead=FILE_SHARE_READ,ShareWrite=FILE_SHARE_WRITE,ShareReadWrite=FILE_SHARE_READ|FILE_SHARE_WRITE};
	enum Access{Read=GENERIC_READ,Write=GENERIC_WRITE,ReadWrite=GENERIC_READ|GENERIC_WRITE,Query=0};
	enum Disposition{CloseHandle,AssumedHandle,InvalidHandle};
	enum Attribute{Normal=FILE_ATTRIBUTE_NORMAL,Archive=FILE_ATTRIBUTE_ARCHIVE,
								 Hidden=FILE_ATTRIBUTE_HIDDEN,ReadOnly=FILE_ATTRIBUTE_READONLY,
								 System=FILE_ATTRIBUTE_SYSTEM,Temporary=FILE_ATTRIBUTE_TEMPORARY,
					       FlagDeleteOnClose=FILE_FLAG_DELETE_ON_CLOSE,FlagOverlapped=FILE_FLAG_OVERLAPPED};
	FileHandle(void);
	FileHandle(const String &pathFileName,Access access=ReadWrite,Share share=ShareRead,Mode open=Open,Attribute attribute=Normal);
	FileHandle(const FileHandle &someFileHandle);
  FileHandle(HANDLE hFile);
	virtual ~FileHandle();
	operator HANDLE(void)const;
	FileHandle &operator=(const FileHandle &someFileHandle);
	FileHandle &operator=(HANDLE hFile);
  WORD open(const String &pathFileName,Access access=ReadWrite,Share share=ShareNone,Mode open=Open,Attribute attribute=Normal);
  void close(void);
	WORD isOkay(void)const;
	DWORD seek(long offset,Method seekMethod);
	DWORD tell(void)const;
	DWORD rewind(void)const;
	WORD read(BYTE &someByte)const;
  WORD read(BYTE *lpBytePtr,DWORD dwExtent)const;
	WORD read(DWORD &someDWORD)const;
	BOOL read(BYTE &someByte,Overlapped &overlapped)const;
  BOOL read(BYTE *lpBytePtr,DWORD dwExtent,Overlapped &overlapped)const;
	BOOL read(DWORD &someDWORD,Overlapped &overlapped)const;
  DWORD getLine(String &lineString)const;
	WORD write(const BYTE &someByte)const;
	DWORD write(const String &someString)const;
  DWORD writeLine(const String &someString)const;
  WORD write(BYTE *lpBytePtr,DWORD dwExtent)const;
	WORD write(const DWORD &someDWORD)const;
	WORD write(const WORD &someWORD)const;
  WORD flush(void)const;
	BOOL getOverlappedResult(Overlapped &overlapped,BOOL wait=FALSE)const;
	DWORD size(void)const;
	String pathFileName(void)const;
	Share share(void)const;
	Access access(void)const;
	SystemTime creationTime(void)const;
	SystemTime lastAccessTime(void)const;
	SystemTime lastModifyTime(void)const;
	void disposition(Disposition disposition);
private:
//  enum {CarriageReturn=0x0D,LineFeed=0x0A,NullChar=0x00};
  enum {CarriageReturn=0x0D,LineFeed=0x0A,TabChar=0x09,NullChar=0x00};
  Disposition disposition(void)const;
	void pathFileName(const String &pathFileName);
	void share(Share share);
  void access(Access access);
  HANDLE mhFileHandle;
	Disposition mDisposition;
	String mPathFileName;
	Share mShare;
	Access mAccess;
};

inline
FileHandle::FileHandle(void)
: mhFileHandle(INVALID_HANDLE_VALUE), mDisposition(InvalidHandle),
	mShare(ShareNone), mAccess(ReadWrite)
{
}

inline
FileHandle::FileHandle(HANDLE hFile)
{
	*this=hFile;
}

inline
FileHandle::FileHandle(const String &pathFileName,Access access,Share share,Mode open,Attribute attribute)
: mhFileHandle(INVALID_HANDLE_VALUE), mDisposition(InvalidHandle), mPathFileName(pathFileName), mShare(share),
  mAccess(access)
{
  if(mPathFileName.isNull())return;
	mhFileHandle=::CreateFile(mPathFileName,access,share,(LPSECURITY_ATTRIBUTES)0,open,attribute,(HANDLE)0);
	if(INVALID_HANDLE_VALUE!=mhFileHandle)mDisposition=CloseHandle;
}

inline
FileHandle::FileHandle(const FileHandle &someFileHandle)
{
	*this=someFileHandle;
}

inline
FileHandle::operator HANDLE(void)const
{
  return mhFileHandle;
}

inline
FileHandle &FileHandle::operator=(const FileHandle &someFileHandle)
{
	mhFileHandle=(HANDLE)someFileHandle;
	pathFileName(someFileHandle.pathFileName());
	share(someFileHandle.share());
	access(someFileHandle.access());
  disposition(AssumedHandle);
  return *this;
}

inline
FileHandle &FileHandle::operator=(HANDLE hFile)
{
	mhFileHandle=hFile;
	disposition(AssumedHandle);
	share(ShareReadWrite);
	access(ReadWrite);
  return *this;
}

inline
WORD FileHandle::open(const String &pathFileName,Access access,Share share,Mode open,Attribute attribute)
{
	close();
	mPathFileName=pathFileName;
	mShare=share;
	mAccess=access;
	if(mPathFileName.isNull())return FALSE;
	mhFileHandle=::CreateFile(mPathFileName,access,share,(LPSECURITY_ATTRIBUTES)0,open,attribute,(HANDLE)0);
	if(INVALID_HANDLE_VALUE!=mhFileHandle)mDisposition=CloseHandle;
	return isOkay();
}

inline
DWORD FileHandle::seek(long offset,Method seekMethod)
{
  if(!isOkay())return FALSE;
	return ::SetFilePointer((HANDLE)*this,offset,(PLONG)0,seekMethod);
}

inline
DWORD FileHandle::tell(void)const
{
	if(!isOkay())return FALSE;
  return ::SetFilePointer((HANDLE)*this,0L,(PLONG)0,SeekCurrent);
}

inline
DWORD FileHandle::rewind(void)const
{
	if(!isOkay())return FALSE;
  return ::SetFilePointer((HANDLE)*this,0L,(PLONG)0,SeekBegin);
}

inline
BOOL FileHandle::getOverlappedResult(Overlapped &overlapped,BOOL wait)const
{
  DWORD bytesReadThusFar;
  if(!isOkay())return FALSE;
	return ::GetOverlappedResult(mhFileHandle,&overlapped.getOverlapped(),&bytesReadThusFar,wait);
}

inline
BOOL FileHandle::read(BYTE &someByte,Overlapped &overlapped)const
{
	DWORD bytesRead;

	if(!isOkay())return FALSE;
	return ::ReadFile((HANDLE)*this,&someByte,sizeof(BYTE),&bytesRead,&overlapped.getOverlapped());
}

inline
BOOL FileHandle::read(BYTE *lpBytePtr,DWORD dwExtent,Overlapped &overlapped)const
{
	DWORD bytesRead;

	if(!isOkay())return FALSE;
	return ::ReadFile((HANDLE)*this,lpBytePtr,dwExtent,&bytesRead,&overlapped.getOverlapped());
}

inline
BOOL FileHandle::read(DWORD &someDWORD,Overlapped &overlapped)const
{
	DWORD bytesRead;

	if(!isOkay())return FALSE;
	return ::ReadFile((HANDLE)*this,&someDWORD,sizeof(DWORD),&bytesRead,&overlapped.getOverlapped());
}

inline
WORD FileHandle::read(BYTE &someByte)const
{
	DWORD bytesRead;

	if(!isOkay())return FALSE;
	::ReadFile((HANDLE)*this,&someByte,sizeof(BYTE),&bytesRead,(LPOVERLAPPED)0);
	return sizeof(BYTE)==bytesRead;
}

inline
WORD FileHandle::read(BYTE *lpBytePtr,DWORD dwExtent)const
{
	DWORD bytesRead;

	if(!isOkay())return FALSE;
	::ReadFile((HANDLE)*this,lpBytePtr,dwExtent,&bytesRead,(LPOVERLAPPED)0);
  return bytesRead==dwExtent;
}

inline
WORD FileHandle::read(DWORD &someDWORD)const
{
	DWORD bytesRead;

	if(!isOkay())return FALSE;
	::ReadFile((HANDLE)*this,&someDWORD,sizeof(DWORD),&bytesRead,(LPOVERLAPPED)0);
	return sizeof(DWORD)==bytesRead;
}

inline
WORD FileHandle::write(const BYTE &someByte)const
{
	DWORD bytesWritten;

	if(!isOkay())return FALSE;
	::WriteFile((HANDLE)*this,&someByte,sizeof(BYTE),&bytesWritten,(LPOVERLAPPED)0);
	return sizeof(BYTE)==bytesWritten;
}

inline
WORD FileHandle::write(const DWORD &someDWORD)const
{
	DWORD bytesWritten;

	if(!isOkay())return FALSE;
	::WriteFile((HANDLE)*this,&someDWORD,sizeof(DWORD),&bytesWritten,(LPOVERLAPPED)0);
	return sizeof(DWORD)==bytesWritten;
}

inline
WORD FileHandle::write(const WORD &someWORD)const
{
	DWORD bytesWritten;

	if(!isOkay())return FALSE;
	::WriteFile((HANDLE)*this,&someWORD,sizeof(WORD),&bytesWritten,(LPOVERLAPPED)0);
	return sizeof(WORD)==bytesWritten;
}

inline
WORD FileHandle::write(BYTE *lpBytePtr,DWORD dwExtent)const
{
	DWORD bytesWritten;

	if(!isOkay())return FALSE;
	::WriteFile((HANDLE)*this,lpBytePtr,dwExtent,&bytesWritten,(LPOVERLAPPED)0);
  return dwExtent==bytesWritten;
}

inline
DWORD FileHandle::write(const String &someString)const
{
	WORD stringLength(someString.length());
	DWORD bytesWritten;

	if(!isOkay())return FALSE;
	::WriteFile((HANDLE)*this,(char*)someString,stringLength,&bytesWritten,(LPOVERLAPPED)0);
	return bytesWritten;
}

inline
DWORD FileHandle::writeLine(const String &someString)const
{
	String lineString(someString);
	WORD stringLength;
	DWORD bytesWritten;

	if(!isOkay())return FALSE;
	lineString+=(BYTE)CarriageReturn;
	lineString+=(BYTE)LineFeed;
	stringLength=lineString.length();
	::WriteFile((HANDLE)*this,(char*)lineString,stringLength,&bytesWritten,(LPOVERLAPPED)0);
	return bytesWritten;
}

inline
WORD FileHandle::flush(void)const
{
	if(!isOkay())return FALSE;
  return ::FlushFileBuffers((HANDLE)*this);
}

inline
String FileHandle::pathFileName(void)const
{
  return mPathFileName;
}

inline
void FileHandle::pathFileName(const String &pathFileName)
{
	mPathFileName=pathFileName;
}

inline
FileHandle::Share FileHandle::share(void)const
{
	return mShare;
}

inline
void FileHandle::share(Share share)
{
	mShare=share;
}

inline
FileHandle::Access FileHandle::access(void)const
{
	return mAccess;
}

inline
void FileHandle::access(Access access)
{
	mAccess=access;
}

inline
void FileHandle::disposition(Disposition disposition)
{
  mDisposition=disposition;
}

inline
FileHandle::Disposition FileHandle::disposition(void)const
{
  return mDisposition;
}

inline
WORD FileHandle::isOkay(void)const
{
	return (INVALID_HANDLE_VALUE==mhFileHandle?FALSE:TRUE);
}

inline
DWORD FileHandle::size(void)const
{
	if(!isOkay())return FALSE;
	return ::GetFileSize((HANDLE)*this,0);
}

inline
void FileHandle::close(void)
{
	if(INVALID_HANDLE_VALUE==mhFileHandle)return;
	if(CloseHandle==mDisposition)::CloseHandle(mhFileHandle);
	mhFileHandle=INVALID_HANDLE_VALUE;
}
#endif
#endif