⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 utility.cpp

📁 FastCopy 利用缓冲技术加快文件拷贝
💻 CPP
字号:
static char *utility_id = 
	"@(#)Copyright (C) H.Shirouzu 2004-2005   utility.cpp	Ver1.30";
/* ========================================================================
	Project  Name			: general routine
	Create					: 2004-09-15(Wed)
	Update					: 2005-11-28(Mon)
	Copyright				: H.Shirouzu
	Reference				: 
	======================================================================== */

#include <stdio.h>
#include "utility.h"
#include "resource.h"

/*=========================================================================
  僋儔僗 丗 Condition
  奣  梫 丗 忦審曄悢僋儔僗
  愢  柧 丗 
  拲  堄 丗 
=========================================================================*/
Condition::Condition(void)
{
	hEvents = NULL;
}

Condition::~Condition(void)
{
	UnInitialize();
}

BOOL Condition::Initialize(int _max_threads)
{
	UnInitialize();

	max_threads = _max_threads;
	waitEvents = new WaitEvent [max_threads];
	hEvents = new HANDLE [max_threads];
	for (int wait_id=0; wait_id < max_threads; wait_id++) {
		if (!(hEvents[wait_id] = ::CreateEvent(0, FALSE, FALSE, NULL)))
			return	FALSE;
		waitEvents[wait_id] = CLEAR_EVENT;
	}
	::InitializeCriticalSection(&cs);
	waitCnt = 0;
	return	TRUE;
}

void Condition::UnInitialize(void)
{
	if (hEvents) {
		while (--max_threads >= 0)
			::CloseHandle(hEvents[max_threads]);
		delete [] hEvents;
		delete [] waitEvents;
		hEvents = NULL;
		waitEvents = NULL;
		::DeleteCriticalSection(&cs);
	}
}

BOOL Condition::Wait(DWORD timeout)
{
	int		wait_id = 0;

	while (waitEvents[wait_id] != CLEAR_EVENT)
		wait_id++;
	waitEvents[wait_id] = WAIT_EVENT;
	waitCnt++;
	UnLock();

	DWORD	status = ::WaitForSingleObject(hEvents[wait_id], timeout);

	Lock();
	--waitCnt;
	waitEvents[wait_id] = CLEAR_EVENT;

	return	status == WAIT_TIMEOUT ? FALSE : TRUE;
}

void Condition::Notify(void)	// 尰忬偱偼丄柊偭偰偄傞僗儗僢僪慡堳傪婲偙偡
{
	if (waitCnt > 0) {
		for (int wait_id=0, done_cnt=0; wait_id < max_threads; wait_id++) {
			if (waitEvents[wait_id] == WAIT_EVENT) {
				::SetEvent(hEvents[wait_id]);
				waitEvents[wait_id] = DONE_EVENT;
				if (++done_cnt >= waitCnt)
					break;
			}
		}
	}
}

/*=========================================================================
  僋儔僗 丗 VBuf
  奣  梫 丗 壖憐儊儌儕娗棟僋儔僗
  愢  柧 丗 
  拲  堄 丗 
=========================================================================*/
VBuf::VBuf(int _size, int _max_size)
{
	Init();

	if (_size || _max_size)
		AllocBuf(_size, _max_size);
}

VBuf::~VBuf()
{
	if (buf)
		FreeBuf();
}

void VBuf::Init(void)
{
	buf = NULL;
	size = usedSize = maxSize = 0;
}

BOOL VBuf::AllocBuf(int _size, int _max_size)
{
	if (_max_size == 0)
		_max_size = _size;
	maxSize = _max_size;

// 1page 暘偩偗梋寁偵妋曐乮buffer over flow 専弌梡乯
	if (!(buf = (BYTE *)::VirtualAlloc(NULL, maxSize + PAGE_SIZE, MEM_RESERVE, PAGE_READWRITE))) {
		Init();
		return	FALSE;
	}
	return	Grow(_size);
}

BOOL VBuf::LockBuf(void)
{
	return	::VirtualLock(buf, size);
}

void VBuf::FreeBuf(void)
{
	if (buf)
		::VirtualFree(buf, 0, MEM_RELEASE);
	Init();
}

BOOL VBuf::Grow(int grow_size)
{
	if (size + grow_size > maxSize)
		return	FALSE;

	if (grow_size && !::VirtualAlloc(buf + size, grow_size, MEM_COMMIT, PAGE_READWRITE))
		return	FALSE;

	size += grow_size;
	return	TRUE;
}

/*=========================================================================
	奼挘 strtok()
		"" 偵弌偔傢偡偲丄"" 偺拞恎傪庢傝弌偡
		token 偺慜屻偵嬻敀偑偁傟偽庢傝彍偔
		偦傟埲奜偼丄strtok_r() 偲摨偠
=========================================================================*/
void *strtok_pathV(void *str, const void *sep, void **p)
{
	const void	*quote=QUOTE_V, *org_sep = sep;

	if (str)
		*p = str;
	else
		str = *p;

	if (!*p)
		return	NULL;

	// 摢偩偟
	while (GetChar(str, 0) && (strchrV(sep, GetChar(str, 0)) || GetChar(str, 0) == ' '))
		str = MakeAddr(str, 1);
	if (GetChar(str, 0) == 0)
		return	NULL;

	// 廔抂専弌
	void	*in = str, *out = str;
	for ( ; GetChar(in, 0); in = MakeAddr(in, 1)) {
		if (sep == org_sep) {	// 捠忢 mode
			if (GetChar(in, 0) == '"') {
				sep = quote;	// quote mode 偵慗堏
			}
			else if (strchrV(sep, GetChar(in, 0))) {
				break;
			}
			else {
				SetChar(out, 0, GetChar(in, 0));
				out = MakeAddr(out, 1);
			}
		}
		else {					// quote mode
			if (GetChar(in, 0) == '"') {
				sep = org_sep;	// 捠忢 mode 偵慗堏
			}
			else {
				SetChar(out, 0, GetChar(in, 0));
				out = MakeAddr(out, 1);
			}
		}
	}
	*p = GetChar(in, 0) ? MakeAddr(in, 1) : NULL;
	SetChar(out, 0, 0);

	// 枛旜偺嬻敀傪庢傝彍偔
	for (out = MakeAddr(out, -1); out >= str && GetChar(out, 0) == ' '; out = MakeAddr(out, -1))
		SetChar(out, 0, 0);

	return	str;
}

/*=========================================================================
	僐儅儞僪儔僀儞夝愅乮CommandLineToArgvW API 偺 ANSI斉乯
		CommandLineToArgvW() 偲摨偠偔丄曉傝抣偺奐曻偼屇傃尦偱偡傞偙偲
=========================================================================*/
void **CommandLineToArgvV(void *cmdLine, int *_argc)
{
#define MAX_ARG_ALLOC	16
	int&	argc = *_argc;
	void	**argv = NULL, *p;
	void	*separantor = IS_WINNT_V ? (char *)L" \t" : " \t";

	argc = 0;
	while (1) {
		if ((argc % MAX_ARG_ALLOC) == 0)
			argv = (void **)realloc(argv, (argc + MAX_ARG_ALLOC) * sizeof(void *));
		if ((argv[argc] = strtok_pathV(argc ? NULL : cmdLine, separantor, &p)) == NULL)
			break;
		argc++;
	}

	return	argv;
}

/*=========================================================================
	PathArray
=========================================================================*/
PathArray::PathArray(void)
{
	num = 0;
	pathArray = NULL;
}

PathArray::PathArray(const PathArray &src)
{
	num = 0;
	pathArray = NULL;
	*this = src;
}

PathArray::~PathArray()
{
	Init();
}

void PathArray::Init(void)
{
	while (--num >= 0)
		free(pathArray[num]);
	free(pathArray);
	num = 0;
	pathArray = NULL;
}

int PathArray::RegisterMultiPath(const void *_multi_path, const void *separator)
{
	void	*multi_path = strdupV(_multi_path);
	void	*tok, *p;
	int		cnt = 0;

	for (tok = strtok_pathV(multi_path, separator, &p); tok; tok = strtok_pathV(NULL, separator, &p)) {
		if (RegisterPath(tok))
			cnt++;
	}
	free(multi_path);
	return	cnt;
}

int PathArray::GetMultiPath(void *multi_path, int max_len, const void *separator, const void *escape_char)
{
	void	*buf = multi_path;
	void	*FMT_STRSTR_V = IS_WINNT_V ? (void *)L"%s%s" : (void *)"%s%s";
	int		len = 0;
	int		escape_val = GetChar(escape_char, 0);

	SetChar(multi_path, 0, 0);
	for (int i=0; i < num; i++) {
		if (max_len - len - strlenV(pathArray[i]) < 3)
			break;
		if (i)
			len += sprintfV(MakeAddr(buf, len), FMT_STR_V, separator);
		len += sprintfV(MakeAddr(buf, len), escape_val && strchrV(pathArray[i], escape_val) ? FMT_QUOTE_STR_V : FMT_STR_V, pathArray[i]);
	}
	return	len;
}

BOOL PathArray::SetPath(int idx, const void *path)
{
	int	size = (strlenV(path) + 1) * CHAR_LEN_V;
	pathArray[idx] = malloc(size);
	memcpy(pathArray[idx], path, size);
	return	TRUE;
}

BOOL PathArray::RegisterPath(const void *path)
{
	for (int i=0; i < num; i++)
		if (lstrcmpiV(path, pathArray[i]) == 0)
			return	FALSE;

#define MAX_ALLOC	100
	if ((num % MAX_ALLOC) == 0)
		pathArray = (void **)realloc(pathArray, (num + MAX_ALLOC) * sizeof(void *));
	SetPath(num++, path);

	return	TRUE;
}

BOOL PathArray::ReplacePath(int idx, void *new_path)
{
	if (idx >= num)
		return	FALSE;

	if (pathArray[idx])
		free(pathArray[idx]);
	SetPath(idx, new_path);
	return	TRUE;
}

PathArray& PathArray::operator=(const PathArray& init)
{
	Init();

	pathArray = (void **)malloc(((((num = init.num) / MAX_ALLOC) + 1) * MAX_ALLOC) * sizeof(void *));

	for (int i=0; i < init.num; i++)
		SetPath(i, init.pathArray[i]);

	return	*this;
}

/*=========================================================================
	DriveMng
=========================================================================*/
DriveMng::DriveMng()
{
	memset(drvID, 0, sizeof(drvID));
	noIdCnt = 0;
}

DriveMng::~DriveMng()
{
	Init();
}

void DriveMng::Init()
{
	for (int i=0; i < MAX_DRIVE_LETTER; i++) {
		if (drvID[i].data)
			delete [] drvID[i].data;
	}
	memset(drvID, 0, sizeof(drvID));
}

BOOL DriveMng::RegisterDriveID(int idx, void *data, int len)
{
	drvID[idx].data = new BYTE [len];
	memcpy(drvID[idx].data, data, drvID[idx].len = len);
	return	TRUE;
}

BOOL DriveMng::SetDriveID(int drvLetter)
{
	TRegistry	reg(HKEY_LOCAL_MACHINE);
	BYTE		buf[1024];
	char		reg_path[MAX_PATH * 2];
	int			size, idx = LetterToIndex(drvLetter);
	DWORD		val = 0;

// NT 宯
	if (IS_WINNT_V) {
		if (reg.OpenKey(MOUNTED_DEVICES)) {
			::sprintf(reg_path, FMT_DOSDEVICES, drvLetter);
			size = sizeof(buf);
			if (reg.GetByte(reg_path, buf, &size))
				return	RegisterDriveID(idx, &buf, size <= 16 ? 4 : size);
		}
		return	RegisterDriveID(idx, &val, 1);
	}

// 95 宯
	TRegistry	dynReg(HKEY_DYN_DATA);
	char		dyn_path[MAX_PATH];
	int			no_id_cnt = 0;

	if (reg.OpenKey(ENUM_DEVICES)) {
		for (int i=0; reg.EnumKey(i, reg_path, MAX_PATH); i++) {	// SCSI, etc...
			if (reg.OpenKey(reg_path) == FALSE)
				continue;
			char *ctrl = reg_path + strlen(reg_path);
			*ctrl++ = '\\';

			for (int j=0; reg.EnumKey(j, ctrl, MAX_PATH); j++) { // Controller
				if (reg.OpenKey(ctrl) == FALSE)
					continue;
				char *dev = ctrl + strlen(ctrl);
				*dev++ = '\\';

				for (int k=0; reg.EnumKey(k, dev, MAX_PATH); k++) { // Devices...
					if (reg.OpenKey(dev) == FALSE)
						continue;

					val = 0;
					if (reg.GetStr(DRIVE_LETTERS, (char *)buf, sizeof(buf))) {
						if (*buf == 0)
							no_id_cnt++;	// format 屻丄reboot 偡傞傑偱 registry 偵枹斀塮傜偟偄
						for (int l=0; buf[l]; l++) {
							if (drvLetter == buf[l]) {
								val = 1;
								break;
							}
						}
					}
					if (val && dynReg.OpenKey(CONFIG_ENUM)) {
						for (int m=0; dynReg.EnumKey(m, dyn_path, sizeof(dyn_path)); m++) {
							if (dynReg.OpenKey(dyn_path) == FALSE)
								continue;
							if (dynReg.GetStr(HARDWARE_KEY, (char *)buf, sizeof(buf))) {
								if (strcmp(reg_path, (char *)buf) == 0) {
									return	RegisterDriveID(idx, buf, strlen((char *)buf));
								}
							}
							dynReg.CloseKey();
						}
						dynReg.CloseKey();
					}
					reg.CloseKey();
				}
				reg.CloseKey();
			}
			reg.CloseKey();
		}
	}
	if (noIdCnt == 0)
		noIdCnt = no_id_cnt;
	val = 0;
	return	RegisterDriveID(idx, &val, sizeof(val));
}

BOOL DriveMng::IsSameDrive(int drvLetter1, int drvLetter2)
{
	drvLetter1 = toupper(drvLetter1);
	drvLetter2 = toupper(drvLetter2);

	if (drvLetter1 == drvLetter2)
		return	TRUE;

	int	idx1 = LetterToIndex(drvLetter1);
	int	idx2 = LetterToIndex(drvLetter2);

	if (drvID[idx1].len == 0)
		SetDriveID(drvLetter1);

	if (drvID[idx2].len == 0)
		SetDriveID(drvLetter2);

	return	drvID[idx1].len != drvID[idx2].len ||
			memcmp(drvID[idx1].data, drvID[idx2].data, drvID[idx1].len) ||
			(IS_WINNT_V ? drvID[idx1].len == 1 : (drvID[idx1].len != 0 || noIdCnt != 1)) ? FALSE : TRUE;
}

// 儚乕僪扨埵偱偼側偔丄暥帤扨埵偱愜傝曉偡偨傔偺 EDIT Control 梡 CallBack
int CALLBACK EditWordBreakProc(LPTSTR str, int cur, int len, int action)
{
	switch (action) {
	case WB_LEFT:
		return	cur + 1;
	case WB_RIGHT:
		return	cur - 1;
	case WB_ISDELIMITER:
		return	TRUE;
	}
	return	0;
}


/*
	庤敳偒僴僢僔儏惗惉儖乕僠儞
*/
HashVal::HashVal(int _max_size)
{
	rand_data = NULL;
	if (_max_size)
		Init(_max_size);
}

HashVal::~HashVal()
{
	delete [] rand_data;
}

void HashVal::Init(int _max_size)
{
	srand(_max_size);
	rand_data = new u_int [max_size = _max_size];

	for (int i=0; i < max_size; i++) {
		rand_data[i] = ((rand() & 0xff0) << 20) | ((rand() & 0xff0) << 12) | ((rand() & 0xff0) << 4) | ((rand() & 0xff0) >> 4);
	}
}

u_int HashVal::MakeHash(void *data, int size)
{
#define MAKE_HASH_CORE(sum, data, i) ((((sum) << 7) | ((sum) >> 25)) ^ (data) ^ rand_data[(rand_data[i] ^ (data)) % max_size])
	u_int	val = 0;
	int		max_loop = size / sizeof(u_int);
	int		mod = size % sizeof(u_int);

	for (int i=0; i < max_loop; i++) {
		u_int	tmp_val = *((u_int *)data + i);
		val = MAKE_HASH_CORE(val, tmp_val, i);
	}

	if (mod) {
		u_int	mod_val = 0;
		u_char	*p = (u_char *)data + (max_loop * sizeof(u_int) + mod);
		while (mod--) {
			mod_val <<= 8;
			mod_val |= *--p;
		}
		val = MAKE_HASH_CORE(val, mod_val, i);
	}
	return	val;
}


/*
	16恑暥帤楍 <-> 僶僀僫儕曄姺儖乕僠儞
*/
inline u_char hexchar2char(u_char ch)
{
	if (ch >= '0' && ch <= '9')
		return ch - '0';
	ch = toupper(ch);
	if (ch >= 'A' && ch <= 'Z')
		return ch - 'A' + 10;
	return 0;
}

BOOL hexstr2bin(const char *buf, BYTE *bindata, int maxlen, int *len)
{
	for (*len=0; buf[0] && buf[1] && *len < maxlen; buf+=2, (*len)++)
	{
		bindata[*len] = hexchar2char(buf[0]) << 4 | hexchar2char(buf[1]);
	}
	return	TRUE;
}

void bin2hexstr(const BYTE *bindata, int len, char *buf)
{
	static char *hexstr = "0123456789abcdef";

	for (int cnt=0; cnt < len; cnt++)
	{
		*buf++ = hexstr[bindata[cnt] >> 4];
		*buf++ = hexstr[bindata[cnt] & 0x0f];
	}
	*buf = 0;
}

/*
	僱僢僩儚乕僋僾儗乕僗傪 UNC path 偵曄姺 (src == dst 壜乯
*/

BOOL NetPlaceConvertV(void *src, void *dst)
{
	IShellLink		*shellLink;		// VC4 偵偼 IShellLink ANSI 斉偟偐掕媊偑側偄偨傔偺巄掕張抲
	IPersistFile	*persistFile;	// 乮幚嵺偼 NT宯偱偼 IShellLinkW 傪屇傃弌偟乯
	WCHAR	wSrcBuf[MAX_PATH], wDstBuf[MAX_PATH];
	WCHAR	*wSrc = IS_WINNT_V ? (WCHAR *)src : wSrcBuf;
	WCHAR	*wDst = IS_WINNT_V ? wDstBuf : (WCHAR *)dst;
	BOOL	ret = FALSE;
	DWORD	attr, attr_mask = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_READONLY;

	if (SHGetPathFromIDListV == NULL)	// NT4.0 宯偼柍帇
		return	FALSE;

	if ((attr = GetFileAttributesV(src)) == 0xffffffff || (attr & attr_mask) != attr_mask)
		return	FALSE;	// 僨傿儗僋僩儕偐偮ronly 偱側偄傕偺偼娭學側偄

	if (SUCCEEDED(CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkV, (void **)&shellLink))) {
		if (SUCCEEDED(shellLink->QueryInterface(IID_IPersistFile, (void **)&persistFile))) {
			if (!IS_WINNT_V)
				::MultiByteToWideChar(CP_ACP, 0, (char *)src, -1, wSrc, MAX_PATH);

			if (SUCCEEDED(persistFile->Load(wSrc, STGM_READ))) {
				if (SUCCEEDED(shellLink->GetPath((char *)wDst, MAX_PATH, NULL, SLGP_UNCPRIORITY))) {
					if (!IS_WINNT_V)
						::WideCharToMultiByte(CP_ACP, 0, wDst, -1, (char *)wDstBuf, MAX_PATH, 0, 0);
					MakePathV(dst, wDstBuf, EMPTY_STR_V);
					ret = TRUE;
				}
			}
			persistFile->Release();
		}
		shellLink->Release();
	}

	return	ret;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -