📄 fastcopy.cpp
字号:
static char *fastcopy_id = "@(#)Copyright (C) H.Shirouzu 2004-2008 fastcopy.cpp Ver1.70";/* ======================================================================== Project Name : Fast Copy file and directory Create : 2004-09-15(Wed) Update : 2008-02-02(Sat) Copyright : H.Shirouzu Reference : ======================================================================== */#include "fastcopy.h"#include <stdarg.h>#include <stddef.h>#include <process.h>#include <stdio.h>void *NTFS_STR_V; // "NTFS"void *FMT_RENAME_V; // ".%03d"void *FMT_LIST1_V; //void *FMT_LIST2_V; //#define STRMID_OFFSET offsetof(WIN32_STREAM_ID, cStreamName)#define MAX_ALTSTREAM 1000#define IsDir(attr) (attr & FILE_ATTRIBUTE_DIRECTORY)#define IsReparse(attr) (attr & FILE_ATTRIBUTE_REPARSE_POINT)#define IsNoReparseDir(attr) (IsDir(attr) && !IsReparse(attr))BOOL SetPrivilege(LPTSTR pszPrivilege, BOOL bEnable){ HANDLE hToken; TOKEN_PRIVILEGES tp; if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) return FALSE; if (!::LookupPrivilegeValue(NULL, pszPrivilege, &tp.Privileges[0].Luid)) return FALSE; tp.PrivilegeCount = 1; if (bEnable) tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; else tp.Privileges[0].Attributes = 0; if (!::AdjustTokenPrivileges(hToken, FALSE, &tp, 0, (PTOKEN_PRIVILEGES)NULL, 0)) return FALSE; if (!::CloseHandle(hToken)) return FALSE; return TRUE;}/*========================================================================= 僋儔僗 丗 FastCopy 奣 梫 丗 儅儖僠僗儗僢僪側僼傽僀儖僐僺乕娗棟僋儔僗 愢 柧 丗 拲 堄 丗 =========================================================================*/FastCopy::FastCopy(){ hReadThread = hWriteThread = NULL; SetPrivilege(SE_BACKUP_NAME, TRUE); SetPrivilege(SE_RESTORE_NAME, TRUE); SetPrivilege(SE_CREATE_SYMBOLIC_LINK_NAME, TRUE); ::InitializeCriticalSection(&errCs); ::InitializeCriticalSection(&listCs); hRunMutex = ::CreateMutex(NULL, FALSE, FASTCOPY_MUTEX); if (IS_WINNT_V) { src = new WCHAR [MAX_PATHLEN_V + MAX_PATH]; dst = new WCHAR [MAX_PATHLEN_V + MAX_PATH]; confirmDst = new WCHAR [MAX_PATHLEN_V + MAX_PATH]; NTFS_STR_V = L"NTFS"; FMT_INT_STR_V = L"%d"; FMT_RENAME_V = L"%.*s(%d)%s"; FMT_LIST1_V = L"%c %s%s%s"; FMT_LIST2_V = L"\r\n%c %s%s%s"; } else { src = new char [MAX_PATHLEN_V + MAX_PATH_EX]; dst = new char [MAX_PATHLEN_V + MAX_PATH_EX]; confirmDst = new char [MAX_PATHLEN_V + MAX_PATH_EX]; NTFS_STR_V = "NTFS"; FMT_INT_STR_V = "%d"; FMT_RENAME_V = "%.*s(%d)%s"; FMT_LIST1_V = "%c %s%s%s"; FMT_LIST2_V = "\r\n%c %s%s%s"; } maxStatSize = (MAX_PATH * CHAR_LEN_V) * 2 + offsetof(FileStat, cFileName) + 8; hashVal.Init(MAX_PATH * CHAR_LEN_V); waitTick = 0;}FastCopy::~FastCopy(){ delete [] confirmDst; delete [] dst; delete [] src; ::CloseHandle(hRunMutex); ::DeleteCriticalSection(&listCs); ::DeleteCriticalSection(&errCs);}BOOL FastCopy::GetRootDir(const void *path, void *root_dir){ if (GetChar(path, 0) == '\\') { // "\\server\volname\" 4偮栚偺 \ 傪尒偮偗傞 DWORD ch; int backslash_cnt = 0, offset; for (offset=0; (ch = GetChar(path, offset)) != 0 && backslash_cnt < 4; offset++) { if (ch == '\\') backslash_cnt++; } memcpy(root_dir, path, offset * CHAR_LEN_V); if (backslash_cnt < 4) // 4偮偺 \ 偑側偄応崌偼丄枛旜偵 \ 傪晅梌 SetChar(root_dir, offset++, '\\'); // 乮\\server\volume 側偳乯 SetChar(root_dir, offset, 0); // NULL terminate } else { // "C:\" 摍 memcpy(root_dir, path, 3 * CHAR_LEN_V); SetChar(root_dir, 3, 0); // NULL terminate } return TRUE;}FastCopy::FsType FastCopy::GetFsType(const void *root_dir){ if (GetDriveTypeV(root_dir) == DRIVE_REMOTE) return FSTYPE_NETWORK; DWORD serial, max_fname, fs_flags; WCHAR vol[MAX_PATH], fs[MAX_PATH]; if (GetVolumeInformationV(root_dir, vol, MAX_PATH, &serial, &max_fname, &fs_flags, fs, MAX_PATH) == FALSE) return ConfirmErr("GetVolumeInformation", root_dir, FALSE), FSTYPE_NONE; return lstrcmpiV(fs, NTFS_STR_V) == 0 ? FSTYPE_NTFS : FSTYPE_FAT;}int FastCopy::GetSectorSize(const void *root_dir){ DWORD spc, bps, fc, cl; if (GetDiskFreeSpaceV(root_dir, &spc, &bps, &fc, &cl) == FALSE) {// if (IS_WINNT_V)// ConfirmErr("GetDiskFreeSpace", root_dir, FALSE); return OPT_SECTOR_SIZE; } return bps;}BOOL FastCopy::IsSameDrive(const void *root1, const void *root2){ if (GetChar(root1, 1) == ':' && GetChar(root2, 1) == ':') return driveMng.IsSameDrive(GetChar(root1, 0), GetChar(root2, 0)); if (GetChar(root1, 1) != GetChar(root2, 1) || GetDriveTypeV(root1) != GetDriveTypeV(root2)) return FALSE; return lstrcmpiV(root1, root2) == 0 ? TRUE : FALSE;}int FastCopy::MakeUnlimitedPath(WCHAR *buf){ int prefix_len; WCHAR *prefix; BOOL isUNC = (*buf == '\\') ? TRUE : FALSE; prefix = isUNC ? PATH_UNC_PREFIX : PATH_LOCAL_PREFIX; prefix_len = isUNC ? PATH_UNC_PREFIX_LEN : PATH_LOCAL_PREFIX_LEN; // (isUNC ? 1 : 0) ... PATH_UNC_PREFIX 偺応崌丄\\server -> \\?\UNC\server // 偵偡傞偨傔丄\\server 偺摢偺 \ 傪堦偮捵偡丅 memmove(buf + prefix_len - (isUNC ? 1 : 0), buf, (strlenV(buf) + 1) * CHAR_LEN_V); memcpy(buf, prefix, prefix_len * CHAR_LEN_V); return prefix_len;}BOOL FastCopy::InitDstPath(void){ DWORD attr; WCHAR wbuf[MAX_PATH_EX]; void *buf = wbuf, *fname = NULL; const void *org_path = dstArray.Path(0), *dst_root; // dst 偺妋擣/壛岺 if (GetChar(org_path, 1) == ':' && GetChar(org_path, 2) != '\\') return ConfirmErr(GetLoadStr(IDS_BACKSLASHERR), org_path, FALSE), FALSE; if (GetFullPathNameV(org_path, MAX_PATHLEN_V, dst, &fname) == 0) return ConfirmErr("GetFullPathName", org_path, FALSE), FALSE; GetRootDir(dst, buf); dstArray.RegisterPath(buf); dst_root = dstArray.Path(dstArray.Num() -1); attr = GetFileAttributesV(dst); if ((attr = GetFileAttributesV(dst)) == 0xffffffff) { if (info.flags & LISTING_ONLY) info.overWrite = BY_ALWAYS; // dst 偑懚嵼偟側偄偨傔丄挷嵏偺昁梫偑側偄 else { CreateDirectoryV(dst, NULL); if ((attr = GetFileAttributesV(dst)) == 0xffffffff) return ConfirmErr("CreateDirectory", dst, FALSE), FALSE; } } if (!IsDir(attr)) // 椺奜揑偵 reparse point 傕 dir 埖偄 return ConfirmErr("Not a directory", dst, FALSE), FALSE; strcpyV(buf, dst); MakePathV(dst, buf, EMPTY_STR_V); // src帺懱傪僐僺乕偡傞偐乮dst枛旜偵 \ 偑偮偄偰偄傞 or 暋悢巜掕乯 isExtendDir = strcmpV(buf, dst) == 0 || srcArray.Num() > 1 ? TRUE : FALSE; dstPrefixLen = IS_WINNT_V ? MakeUnlimitedPath((WCHAR *)dst) : 0; dstBaseLen = strlenV(dst); // dst 僼傽僀儖僔僗僥儉忣曬庢摼 dstSectorSize = GetSectorSize(dst_root); dstFsType = GetFsType(dst_root); nbMinSize = dstFsType == FSTYPE_NTFS ? info.nbMinSizeNtfs : info.nbMinSizeFat; // 嵟戝揮憲僒僀僘 maxTransSize = isSameDrv ? info.bufSize : info.bufSize / 2; maxTransSize = min(info.maxTransSize, maxTransSize); // 嵎暘僐僺乕梡dst愭僼傽僀儖妋擣 strcpyV(confirmDst, dst); return TRUE;}BOOL FastCopy::InitSrcPath(int idx){ DWORD attr; BYTE src_root_cur[MAX_PATH]; WCHAR wbuf[MAX_PATH_EX]; void *buf = wbuf, *fname = NULL; const void *dst_root = dstArray.Path(dstArray.Num() -1); const void *org_path = srcArray.Path(idx); // src 偺妋擣/壛岺 if (GetChar(org_path, 1) == ':' && GetChar(org_path, 2) != '\\') return ConfirmErr(GetLoadStr(IDS_BACKSLASHERR), org_path), FALSE; if (GetFullPathNameV(org_path, MAX_PATHLEN_V, src, &fname) == 0) return ConfirmErr("GetFullPathName", org_path), FALSE; GetRootDir(src, src_root_cur); isMetaSrc = FALSE; if ((attr = GetFileAttributesV(src)) == 0xffffffff) { isMetaSrc = TRUE; } else if (IsDir(attr)) { // 恊僨傿儗僋僩儕帺懱傪僐僺乕偟側偄応崌丄\* 傪晅梌 strcpyV(buf, src); MakePathV(src, buf, ASTERISK_V); if (lstrcmpiV(buf, src_root_cur) && (isExtendDir || ((info.flags & DIR_REPARSE) == 0 && IsReparse(attr)))) SetChar(src, strlenV(src) - 2, 0); // 枛旜偵 \* 傪晅偗側偄 else isMetaSrc = TRUE; } srcPrefixLen = IS_WINNT_V ? MakeUnlimitedPath((WCHAR *)src) : 0; if (GetFullPathNameV(src, MAX_PATH_EX, buf, &fname) == 0 || fname == NULL) return ConfirmErr("GetFullPathName2", MakeAddr(src, srcPrefixLen)), FALSE; // 妋擣梡dst惗惉 strcpyV(MakeAddr(confirmDst, dstBaseLen), fname); // 摨堦僷僗偱側偄偙偲偺妋擣 if (lstrcmpiV(buf, confirmDst) == 0) { if (info.mode != DIFFCP_MODE || (info.flags & SAMEDIR_RENAME) == 0) return ConfirmErr(GetLoadStr(IDS_SAMEPATHERR), MakeAddr(confirmDst, dstBaseLen), FALSE), FALSE; strcpyV(MakeAddr(confirmDst, dstBaseLen), ASTERISK_V); isRename = TRUE; } else isRename = FALSE; if (info.mode == MOVE_MODE && IsNoReparseDir(attr)) { // 恊偐傜巕傊偺堏摦偼擣傔側偄 int end_offset = 0; if (GetChar(fname, 0) == '*' || attr == 0xffffffff) { SetChar(fname, 0, 0); end_offset = 1; } int len = IS_WINNT_V ? strlenV(buf) : ::lstrlenA((char *)buf); if (srcBaseLen <= dstBaseLen && strnicmpV(buf, confirmDst, len) == 0) { DWORD ch = GetChar(confirmDst, len - end_offset); if (ch == 0 || ch == '\\') { return ConfirmErr(GetLoadStr(IDS_PARENTPATHERR), MakeAddr(buf, srcPrefixLen), FALSE), FALSE; } } } SetChar(fname, 0, 0); srcBaseLen = strlenV(buf); // src 僼傽僀儖僔僗僥儉忣曬庢摼 if (lstrcmpiV(src_root_cur, src_root)) { srcSectorSize = GetSectorSize(src_root_cur); srcFsType = GetFsType(src_root_cur); sectorSize = max(srcSectorSize, dstSectorSize); // 戝偒偄傎偆偵崌傢偣傞 sectorSize = max(sectorSize, MIN_SECTOR_SIZE); // 摨堦暔棟僪儔僀僽偐偳偆偐偺挷嵏 if (info.flags & FIX_SAMEDISK) isSameDrv = TRUE; else if (info.flags & FIX_DIFFDISK) isSameDrv = FALSE; else isSameDrv = IsSameDrive(src_root_cur, dst_root); if (info.mode == MOVE_MODE) isSameVol = strcmpV(src_root_cur, dst_root); } enableAcl = (info.flags & WITH_ACL) && srcFsType != FSTYPE_FAT && dstFsType != FSTYPE_FAT; enableStream = (info.flags & WITH_ALTSTREAM) && srcFsType != FSTYPE_FAT && dstFsType != FSTYPE_FAT; strcpyV(src_root, src_root_cur); return TRUE;}BOOL FastCopy::InitDeletePath(int idx){ DWORD attr; WCHAR wbuf[MAX_PATH_EX]; void *buf = wbuf, *fname = NULL; const void *org_path = srcArray.Path(idx); BYTE dst_root[MAX_PATH]; // delete 梡 path 偺妋擣/壛岺 if (GetChar(org_path, 1) == ':' && GetChar(org_path, 2) != '\\') return ConfirmErr(GetLoadStr(IDS_BACKSLASHERR), org_path), FALSE; if (GetFullPathNameV(org_path, MAX_PATHLEN_V, dst, &fname) == 0) return ConfirmErr("GetFullPathName", org_path), FALSE; attr = GetFileAttributesV(dst); if (attr != 0xffffffff && IsNoReparseDir(attr) || (info.flags & (OVERWRITE_DELETE|OVERWRITE_DELETE_NSA))) { GetRootDir(dst, dst_root); if (info.flags & (OVERWRITE_DELETE|OVERWRITE_DELETE_NSA)) { dstSectorSize = GetSectorSize(dst_root); dstFsType = GetFsType(dst_root); nbMinSize = dstFsType == FSTYPE_NTFS ? info.nbMinSizeNtfs : info.nbMinSizeFat; } } isMetaSrc = FALSE; if (attr == 0xffffffff) { isMetaSrc = TRUE; } else if (IsDir(attr)) { strcpyV(buf, dst); // root_dir 偼枛旜偵 "\*" 傪晅梌丄偦傟埲奜偼枛旜偺 "\"傪嶍彍 MakePathV(dst, buf, ASTERISK_V); if (!IsReparse(attr) && lstrcmpiV(buf, dst_root) == 0) isMetaSrc = TRUE; else SetChar(dst, strlenV(dst) - 2, 0); } dstPrefixLen = IS_WINNT_V ? MakeUnlimitedPath((WCHAR *)dst) : 0; if (GetFullPathNameV(dst, MAX_PATH_EX, buf, &fname) == 0 || fname == NULL) return ConfirmErr("GetFullPathName2", MakeAddr(dst, dstPrefixLen)), FALSE; SetChar(fname, 0, 0); dstBaseLen = strlenV(buf); if (info.flags & (OVERWRITE_DELETE|OVERWRITE_DELETE_NSA)) { strcpyV(confirmDst, dst); // for renaming before deleting } return TRUE;}BOOL FastCopy::RegisterInfo(const PathArray *_srcArray, const PathArray *_dstArray, Info *_info, const PathArray *_includeArray, const PathArray *_excludeArray){ isAbort = FALSE; isRename = FALSE; isMetaSrc = FALSE; isFilter = FALSE; endTick = 0; info = *_info; SetChar(src_root, 0, 0); if (info.flags & LISTING_ONLY) info.flags &= ~PRE_SEARCH; // filter PathArray pathArray[] = { *_includeArray, *_excludeArray }; void *path = NULL; for (int kind=0; kind < MAX_KIND_EXP; kind++) { for (int ftype=0; ftype < MAX_FTYPE_EXP; ftype++) regExp[kind][ftype].Init(); for (int idx=0; idx < pathArray[kind].Num(); idx++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -