// File64.h: CFile64 クラスのインターフェイス
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_FILE64_H__F0029628_60C7_4586_8446_24AAABA6944D__INCLUDED_)
#define AFX_FILE64_H__F0029628_60C7_4586_8446_24AAABA6944D__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

class CFile64  
{
public:
    HANDLE hFile;//ファイルハンドル

    CFile64(){ hFile=NULL; }
    CFile64(const char*lpFileName,DWORD flag){ hFile=NULL;Open(lpFileName,flag); }
    virtual ~CFile64() { Close(); }

    //enum定義
    enum OpenFlags {
        modeRead =          0x0000, modeWrite =         0x0001, modeReadWrite =     0x0002,
        shareCompat =       0x0000, shareExclusive =    0x0010, shareDenyWrite =    0x0020,
        shareDenyRead =     0x0030, shareDenyNone =     0x0040,
        modeNoInherit =     0x0080, modeCreate =        0x1000, modeNoTruncate =    0x2000,
        typeText =          0x4000, typeBinary =   (int)0x8000  };

    enum Attribute {
        normal =    0x00,   readOnly =  0x01,   hidden =    0x02,   system =    0x04,
        volume =    0x08,   directory = 0x10,   archive =   0x20};

    enum SeekPosition { begin = 0x0, current = 0x1, end = 0x2 };

    //オープン
    //CFile互換のオープン 引数などはCFile参照
    BOOL Open(const char*lpFileName,DWORD nOpenFlags){
        DWORD a=GENERIC_READ,b=0,c=OPEN_EXISTING,d=0;
        if((nOpenFlags & modeWrite)) a+=GENERIC_WRITE;
        if((nOpenFlags & modeReadWrite)) a+=GENERIC_WRITE;
        if((nOpenFlags & shareDenyWrite)) b+=FILE_SHARE_READ;
        if((nOpenFlags & shareDenyRead)) b+=FILE_SHARE_WRITE;
        if((nOpenFlags & shareDenyNone)) b+=(FILE_SHARE_WRITE|FILE_SHARE_READ);
        if((nOpenFlags & modeCreate)) c=CREATE_NEW;
        if((nOpenFlags & modeNoTruncate)) c=OPEN_ALWAYS;
        Close();
        return Open(lpFileName, a, b, NULL, c);

    }

    //CreateFile互換のオープン 引数などは CreateFile参照
    BOOL Open(const char*lpFileName ,DWORD dwDesiredAccess,
                               DWORD dwShareMode,
                               LPSECURITY_ATTRIBUTES lpSecurityAttributes=NULL,
                               DWORD dwCreationDisposition=OPEN_EXISTING,
                               DWORD dwFlagsAndAttributes=FILE_ATTRIBUTE_ARCHIVE,
                               HANDLE hTemplateFile=NULL){
        Close();
        hFile = CreateFile(lpFileName, dwDesiredAccess,
            dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
        if(hFile==INVALID_HANDLE_VALUE) return FALSE;
        return TRUE;
    }

    //簡潔に開くために作った関数
    //openexist=FALSE : ファイルがない場合生成しファイルを開く
    //          TRUE  : ファイルがない場合は生成せずに終わる
    BOOL Openm(const char*lpFileName,BOOL openexist=TRUE){//短くFALSEでファイルが無いときも作成してオープン
        if(openexist==TRUE)
            return Open(lpFileName,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL);
        else
            return Open(lpFileName,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_ALWAYS);
    }
    
    int Read(void* buf,DWORD len){//読み込み
        DWORD lenb;
        BOOL r=ReadFile(hFile,buf,len,&lenb,NULL);
        if(r==0) return 0;
        return lenb;
    }

    int Write(void* buf,DWORD len){//書き込み
        DWORD lenb;
        BOOL r=WriteFile(hFile,buf,len,&lenb,NULL);
        if(r==0) return 0;
        return lenb;
    }

    __int64 Seek(__int64 len,DWORD f){//シーク
        LARGE_INTEGER li;
        li.QuadPart = len;
        li.LowPart = SetFilePointer (hFile, li.LowPart, &li.HighPart, f);
        if (li.LowPart == -1 && GetLastError() != NO_ERROR){
            li.QuadPart = -1;
        }
        return li.QuadPart;
    }
    void SeekToBegin() { Seek(0,FILE_BEGIN); }//シーク頭へ
    void SeekToEnd() { Seek(0,FILE_END); }//シーク最後へ

    __int64 GetLength() {//長さを獲得
        LARGE_INTEGER li;
        li.LowPart=GetFileSize(hFile,(DWORD*)&li.HighPart);
        return li.QuadPart;
    }

    __int64 GetPosition(){//現在の位置を獲得
        LARGE_INTEGER li;
        li.LowPart = ::SetFilePointer((HANDLE)hFile, 0, (long*)&li.HighPart, FILE_CURRENT);
        return li.QuadPart;
    }

    void Flush() {
        if(hFile==NULL) return;
        FlushFileBuffers(hFile);
    }

    void Close() {//閉じる
        if(hFile!=0)
            CloseHandle(hFile);
        hFile=0;
    }

    //以下スタティック関数
    //使用方法は CFile64::Rename( ... ) という具合に直接実行
    //ファイルまたはフォルダに対して有効
    //戻り値 FALSE:正常終了 それ以外:異常終了
    static BOOL Rename(HWND h,CString oldname,CString newname){//リネーム
        SHFILEOPSTRUCT Op;
        ZeroMemory( &Op,sizeof(SHFILEOPSTRUCT));
        Op.hwnd   = h;        // 実行するウインドウのハンドル
        Op.wFunc  = FO_RENAME;     // リネーム
        Op.pFrom  = oldname;
        Op.pTo    = newname;
        Op.fFlags = FOF_NOCONFIRMATION|FOF_NOCONFIRMMKDIR|FOF_SILENT|FOF_NOERRORUI;
        return SHFileOperation( &Op );
    }

    static BOOL Copy(HWND h,CString oldname,CString newname){//コピー
        SHFILEOPSTRUCT Op;
        ZeroMemory( &Op,sizeof(SHFILEOPSTRUCT));
        Op.hwnd   = h;        // 実行するウインドウのハンドル
        Op.wFunc  = FO_COPY;     // コピー
        Op.pFrom  = oldname;
        Op.pTo    = newname;
        Op.fFlags = FOF_NOCONFIRMATION|FOF_NOCONFIRMMKDIR|FOF_SILENT|FOF_NOERRORUI;
        return SHFileOperation( &Op );
    }

    static BOOL Move(HWND h,CString oldname,CString newname){//移動
        SHFILEOPSTRUCT Op;
        ZeroMemory( &Op,sizeof(SHFILEOPSTRUCT));
        Op.hwnd   = h;        // 実行するウインドウのハンドル
        Op.wFunc  = FO_MOVE;     // 移動
        Op.pFrom  = oldname;
        Op.pTo    = newname;
        Op.fFlags = FOF_NOCONFIRMATION|FOF_NOCONFIRMMKDIR|FOF_SILENT|FOF_NOERRORUI;
        return SHFileOperation( &Op );
    }

    static BOOL Delete(HWND h,CString deletename){//削除
        SHFILEOPSTRUCT Op;
        ZeroMemory( &Op,sizeof(SHFILEOPSTRUCT));
        Op.hwnd   = h;        // 実行するウインドウのハンドル
        Op.wFunc  = FO_DELETE;     // 削除
        Op.pFrom  = deletename;
        Op.fFlags = FOF_NOCONFIRMATION|FOF_NOCONFIRMMKDIR|FOF_SILENT|FOF_NOERRORUI;
        return SHFileOperation( &Op );
    }
};

#endif // !defined(AFX_FILE64_H__F0029628_60C7_4586_8446_24AAABA6944D__INCLUDED_)