📄 utility.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 + -