添加编译批处理

This commit is contained in:
gb 2022-07-06 18:09:13 +08:00
parent f9057909f9
commit b5491bcb01
33 changed files with 4055 additions and 3 deletions

61
build.bat Normal file
View File

@ -0,0 +1,61 @@
echo off
echo "build.bat [hw | lsc] [x86 | x64] [0x100 | 0x...]"
set OEM=hg
set CPU=x86
set PID=0x100
set VAL=%1
if "%1"=="hw" (
set OEM=%1
)else if "%1"=="lsc" (
set OEM=%1
) else (
if "%1"=="x64" (
set CPU=%1
) else if "%1"=="x86" (
set CPU=%1
) else if "%VAL:~0,2%"=="0x" (
set PID=%VAL%
)
)
set VAL=%2
if "%2"=="hw" (
set OEM=%2
)else if "%2"=="lsc" (
set OEM=%2
) else (
if "%2"=="x64" (
set CPU=%2
) else if "%2"=="x86" (
set CPU=%2
) else if "%VAL:~0,2%"=="0x" (
set PID=%VAL%
)
)
set VAL=%3
if "%3"=="hw" (
set OEM=%3
)else if "%3"=="lsc" (
set OEM=%3
) else (
if "%3"=="x64" (
set CPU=%3
) else if "%3"=="x86" (
set CPU=%3
) else if "%VAL:~0,2%"=="0x" (
set PID=%VAL%
)
)
echo oem=%OEM%
echo cpu=%CPU%
echo pid=%PID%
"%~dp0\sln\release\hgsetver.exe" "%~dp0\twain\brand.h" -oem %OEM% -cpu %CPU% -pid %PID%
"C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Current\Bin\MSBuild.exe" "%~dp0\device\scanner.vcxproj" /p:Configuration=Release /p:Platform=x86
"C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Current\Bin\MSBuild.exe" "%~dp0\sane\sane.vcxproj" /p:Configuration=Release /p:Platform=x86
"C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Current\Bin\MSBuild.exe" "%~dp0\twain\twain.vcxproj" /p:Configuration=Release /p:Platform=x86

14
device/resource.h Normal file
View File

@ -0,0 +1,14 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by scanner.rc
// 新对象的下一组默认值
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

100
device/scanner.rc Normal file
View File

@ -0,0 +1,100 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// 中文(简体,中国) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
#pragma code_page(936)
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,1015,2022,7061
PRODUCTVERSION 4,1015,2022,7061
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "080404b0"
BEGIN
VALUE "CompanyName", "宁波华高信息科技有限公司"
VALUE "FileDescription", "华高扫描仪应用程序"
VALUE "FileVersion", "4.1015.2022.7061"
VALUE "InternalName", "scanner.dll"
VALUE "LegalCopyright", "Copyright (C) 2022"
VALUE "OriginalFilename", "scanner.dll"
VALUE "ProductName", "HUAGOScan"
VALUE "ProductVersion", "4.1015.2022.7061"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x804, 1200
END
END
#endif // 中文(简体,中国) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@ -323,6 +323,7 @@ move /Y "$(OutDirFullPath)$(ProjectName).pdb" "$(SolutionDir)..\..\sdk\lib\win\$
<ClInclude Include="..\..\sdk\include\sane\sanei_debug.h" />
<ClInclude Include="..\..\sdk\include\sane\sane_ex.h" />
<ClInclude Include="..\..\sdk\include\sane\sane_option_definitions.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="win_usb\usbview\enum.h" />
<ClInclude Include="win_usb\usbview\usbdesc.h" />
<ClInclude Include="win_usb\usbview\uvcdesc.h" />
@ -334,6 +335,9 @@ move /Y "$(OutDirFullPath)$(ProjectName).pdb" "$(SolutionDir)..\..\sdk\lib\win\$
<ItemGroup>
<Text Include="..\..\code_device\hgdriver\wrapper\CMakeLists.txt" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="scanner.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>

View File

@ -392,6 +392,9 @@
<ClInclude Include="..\..\code_device\hgdriver\ImageProcess\G4Tiff.h">
<Filter>image</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="device.def">
@ -401,4 +404,9 @@
<ItemGroup>
<Text Include="..\..\code_device\hgdriver\wrapper\CMakeLists.txt" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="scanner.rc">
<Filter>资源文件</Filter>
</ResourceCompile>
</ItemGroup>
</Project>

View File

@ -241,6 +241,45 @@ BEGIN
0
END
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,1015,2022,7061
PRODUCTVERSION 4,1015,2022,7061
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "080404b0"
BEGIN
VALUE "CompanyName", "宁波华高信息科技有限公司"
VALUE "FileDescription", "华高扫描仪应用程序"
VALUE "FileVersion", "4.1015.2022.7061"
VALUE "InternalName", "sane.dll"
VALUE "LegalCopyright", "Copyright (C) 2022"
VALUE "OriginalFilename", "sane.dll"
VALUE "ProductName", "HUAGOScan"
VALUE "ProductVersion", "4.1015.2022.7061"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x804, 1200
END
END
#endif // 中文(简体,中国) resources
/////////////////////////////////////////////////////////////////////////////

BIN
sln/Release/hgsetver.exe Normal file

Binary file not shown.

View File

@ -9,6 +9,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scanner", "..\device\scanne
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "twain", "..\twain\twain.vcxproj", "{C3B47CE2-27CE-4509-AB59-3C0F194F0FCE}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "setup", "setup", "{F6774650-403F-476C-8373-2EA8D4AF06FF}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hgsetver", "hgsetver\hgsetver.vcxproj", "{A7528596-FBA2-4FFF-8649-C8D0EEBC6554}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@ -39,10 +43,21 @@ Global
{C3B47CE2-27CE-4509-AB59-3C0F194F0FCE}.Release|x64.ActiveCfg = Release|Win32
{C3B47CE2-27CE-4509-AB59-3C0F194F0FCE}.Release|x86.ActiveCfg = Release|Win32
{C3B47CE2-27CE-4509-AB59-3C0F194F0FCE}.Release|x86.Build.0 = Release|Win32
{A7528596-FBA2-4FFF-8649-C8D0EEBC6554}.Debug|x64.ActiveCfg = Debug|x64
{A7528596-FBA2-4FFF-8649-C8D0EEBC6554}.Debug|x64.Build.0 = Debug|x64
{A7528596-FBA2-4FFF-8649-C8D0EEBC6554}.Debug|x86.ActiveCfg = Debug|Win32
{A7528596-FBA2-4FFF-8649-C8D0EEBC6554}.Debug|x86.Build.0 = Debug|Win32
{A7528596-FBA2-4FFF-8649-C8D0EEBC6554}.Release|x64.ActiveCfg = Release|x64
{A7528596-FBA2-4FFF-8649-C8D0EEBC6554}.Release|x64.Build.0 = Release|x64
{A7528596-FBA2-4FFF-8649-C8D0EEBC6554}.Release|x86.ActiveCfg = Release|Win32
{A7528596-FBA2-4FFF-8649-C8D0EEBC6554}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{A7528596-FBA2-4FFF-8649-C8D0EEBC6554} = {F6774650-403F-476C-8373-2EA8D4AF06FF}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A89068FF-95C4-3C1E-B126-70B66C9824BB}
EndGlobalSection

791
sln/hgsetver/hgsetver.cpp Normal file
View File

@ -0,0 +1,791 @@
// hgsetver.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <Windows.h>
#include <iostream>
#include <file/file_util.h>
#include <process/process_util.h>
#include <coding/coding.h>
#include <time.h>
#pragma warning(disable: 4996)
enum oem
{
OEM_NOT = -1,
OEM_NONE = 0,
OEM_HANWANG,
OEM_LISICHENG,
};
#define GET_ENUM_NAME_W(e, v) \
if(e == v) return L###e;
#define GET_ENUM_VALUE_W(e, v) \
if(L###e == v) return e;
static bool set_ver(const wchar_t* file, oem vendor, bool x86, int pid, int main = 0);
int main()
{
// hgsetver "brand.h" x86|x64 oem
process_util::ICmd* cmd = process_util::create_command_line();
if (cmd->count() < 2)
{
std::wstring pe(cmd->main_pe());
size_t pos = pe.rfind(L'\\');
if (pos++ != std::wstring::npos)
pe.erase(0, pos);
pos = pe.rfind(L'.');
if (pos != std::wstring::npos)
pe.erase(pos);
std::wcout << L"Usage: " << pe.c_str() << L"<path-file> [-pid product_id lead with '0x'] [-main main-ver, all version will be omitted if this was not given or be ZERO] [-cpu x86|x64] [-oem hw|lsc]\r\n";
cmd->release();
DWORD pid = process_util::get_parent_process(GetCurrentProcessId());
wchar_t path[MAX_PATH] = { 0 }, * n = NULL;
process_util::get_process_name(pid, path);
n = wcsrchr(path, L'\\');
if (n++ == NULL)
n = path;
if(wcsicmp(n, L"explorer.exe") == 0)
getchar();
return -1;
}
oem vendor = OEM_NONE;
bool x86 = true;
int main = 0, pid = 0x100;
if (cmd->parameter(L"-main"))
{
main = _wtoi(cmd->parameter(L"-main"));
if (main <= 0)
{
main = 0;
std::wcout << L" Main version '" << cmd->parameter(L"-main") << L"' is invalid, no changes to it.\r\n";
}
}
if (cmd->parameter(L"-pid"))
{
pid = coding_util::pick_integer(cmd->parameter(L"-pid"));
}
if (cmd->parameter(L"-cpu"))
x86 = wcsicmp(cmd->parameter(L"-cpu"), L"x64") != 0;
if (cmd->parameter(L"-oem"))
{
if (wcsicmp(cmd->parameter(L"-oem"), L"hw") == 0)
vendor = OEM_HANWANG;
else if (wcsicmp(cmd->parameter(L"-oem"), L"lsc") == 0)
vendor = OEM_LISICHENG;
else
std::wcout << L" OEM '" << cmd->parameter(L"-oem") << L"' is not supported! set as OEM_NONE.\r\n";
}
std::wstring file(cmd->parameter(1));
STR_TO_ABSOLUTE_PATH(file);
set_ver(file.c_str(), vendor, x86, pid, main);
cmd->release();
return 0;
}
// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单
// 入门使用技巧:
// 1. 使用解决方案资源管理器窗口添加/管理文件
// 2. 使用团队资源管理器窗口连接到源代码管理
// 3. 使用输出窗口查看生成输出和其他消息
// 4. 使用错误列表窗口查看错误
// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件
static INTER_MODULE_CALLBACK(got_str)
{
*((std::string*)param) += std::string(data, len);
return inter_module_data::SET_RESULT_CONTINUE;
}
static INTER_MODULE_CALLBACK(got_wstr)
{
*((std::wstring*)param) += std::wstring((wchar_t*)data, len / 2);
return inter_module_data::SET_RESULT_CONTINUE;
}
enum bom
{
BOM_ANSI = 0,
BOM_UTF8,
BOM_UNICODE,
};
static std::wstring oem_str(oem o)
{
GET_ENUM_NAME_W(OEM_NONE, o);
GET_ENUM_NAME_W(OEM_HANWANG, o);
GET_ENUM_NAME_W(OEM_LISICHENG, o);
}
static oem from_str(const wchar_t* str)
{
std::wstring s(str);
GET_ENUM_VALUE_W(OEM_NONE, s);
GET_ENUM_VALUE_W(OEM_HANWANG, s);
GET_ENUM_VALUE_W(OEM_LISICHENG, s);
return OEM_NOT;
}
static int find_line(std::wstring& brand, const wchar_t* line_tag, int* end)
{
int bgn = 0, next = 0, start = -1;
std::wstring line(L"");
do
{
bgn += next;
line = L"";
coding_util::pick_line(brand.c_str() + bgn, got_wstr, &line, &next);
if (line.find(line_tag) != std::wstring::npos)
{
start = bgn;
if (end)
*end = bgn + next;
break;
}
} while (next > 0);
return start;
}
static bool change_oem(std::wstring& brand, oem o)
{
std::wstring oem_def(L"#define " + oem_str(o) + L"\r\n");
int end = -1,
bgn = find_line(brand, L"#define OEM_", &end);
if (bgn >= 0)
{
brand.replace(bgn, end - bgn, oem_def);
}
else
{
bgn = find_line(brand, L"#define ", &end);
if(bgn >= 0)
brand.replace(bgn, end - bgn, oem_def + L"\r\n");
else
std::wcout << L" Modify vendor to '" << oem_def.c_str() << L"' failed.\r\n";
}
return bgn >= 0;
}
static bool change_main(std::wstring& brand, int main)
{
wchar_t ver[20] = { 0 };
int next = 0,
bgn = find_line(brand, L"#define VERSION_MAIN", &next);
bool ret = false;
swprintf_s(ver, _countof(ver) - 1, L"%d\r\n", main);
if (bgn >= 0)
{
bgn += lstrlenW(L"#define VERSION_MAIN");
while (brand[bgn] == L'\t' || brand[bgn] == L' ')
bgn++;
if (brand[bgn] >= L'0' && brand[bgn] <= L'9')
{
brand.replace(bgn, next - bgn, ver);
ret = true;
}
}
if (!ret)
std::wcout << L" change VERSION_MAIN to '" << ver << L"' failed.\r\n";
return ret;
}
static bool change_sub(std::wstring& brand, int sub, int main)
{
wchar_t ver[20] = { 0 };
int next = 0,
bgn = find_line(brand, L"#define VERSION_SUB", &next);
bool ret = false;
if (bgn >= 0)
{
bgn += lstrlenW(L"#define VERSION_SUB");
while (brand[bgn] == L'\t' || brand[bgn] == L' ')
bgn++;
if (brand[bgn] >= L'0' && brand[bgn] <= L'9')
{
sub += _wtoi(brand.c_str() + bgn) % 100;
if(main)
sub++;
swprintf_s(ver, _countof(ver) - 1, L"%d\r\n", sub);
brand.replace(bgn, next - bgn, ver);
ret = true;
}
}
if (!ret)
std::wcout << L" change VERSION_SUB to '" << ver << L"+' failed.\r\n";
return ret;
}
static bool change_build(std::wstring& brand, int build)
{
wchar_t ver[20] = { 0 };
int next = 0,
bgn = find_line(brand, L"#define VERSION_BUILD", &next);
bool ret = false;
swprintf_s(ver, _countof(ver) - 1, L"%d\r\n", build);
if (bgn >= 0)
{
bgn += lstrlenW(L"#define VERSION_BUILD");
while (brand[bgn] == L'\t' || brand[bgn] == L' ')
bgn++;
if (brand[bgn] >= L'0' && brand[bgn] <= L'9')
{
brand.replace(bgn, next - bgn, ver);
ret = true;
}
}
if (!ret)
std::wcout << L" change VERSION_BUILD to '" << ver << L"+' failed.\r\n";
return ret;
}
static bool change_patch(std::wstring& brand, int patch)
{
wchar_t ver[20] = { 0 };
int next = 0,
bgn = find_line(brand, L"#define VERSION_PATCH", &next);
bool ret = false;
swprintf_s(ver, _countof(ver) - 1, L"%d\r\n", patch);
if (bgn >= 0)
{
bgn += lstrlenW(L"#define VERSION_PATCH");
while (brand[bgn] == L'\t' || brand[bgn] == L' ')
bgn++;
if (brand[bgn] >= L'0' && brand[bgn] <= L'9')
{
brand.replace(bgn, next - bgn, ver);
ret = true;
}
}
if (!ret)
std::wcout << L" change VERSION_PATCH to '" << ver << L"+' failed.\r\n";
return ret;
}
static bool change_product_id(std::wstring& brand, int pid)
{
wchar_t ver[20] = { 0 };
int next = 0,
bgn = find_line(brand, L"#define PRODUCT_ID", &next);
bool ret = false;
swprintf_s(ver, _countof(ver) - 1, L"%x\r\n", pid);
if (bgn >= 0)
{
bgn += lstrlenW(L"#define PRODUCT_ID");
while (brand[bgn] == L'\t' || brand[bgn] == L' ')
bgn++;
if ((brand[bgn] >= L'0' && brand[bgn] <= L'9') ||
(brand[bgn] >= L'a' && brand[bgn] <= L'f') ||
(brand[bgn] >= L'A' && brand[bgn] <= L'F'))
{
brand.replace(bgn, next - bgn, ver);
ret = true;
}
}
if (!ret)
std::wcout << L" change PRODUCT_ID to '" << ver << L"+' failed.\r\n";
return ret;
}
namespace rc
{
static std::wstring load_file(const wchar_t* file, bom* bm)
{
std::string cont("");
std::wstring unic(L"");
file_util::load_file(file, got_str, &cont);
if (cont.length() > 3)
{
if (bm)
{
if (coding_util::bom::is_unicode(cont.c_str(), NULL))
*bm = BOM_UNICODE;
else if (coding_util::bom::is_utf8(cont.c_str()))
*bm = BOM_UTF8;
else
*bm = BOM_ANSI;
}
coding_util::bom::to_unicode(cont.c_str(), cont.length(), got_wstr, &unic);
}
return unic;
}
static void trim_left(std::wstring& str)
{
int bgn = 0;
while (str[bgn] == L'\t' || str[bgn] == L' ')
bgn++;
if (bgn)
str.erase(0, bgn);
}
static bool get_version_from_file(const wchar_t* file, int* v1, int* v2, int* v3, int* v4, std::wstring* company_name, std::wstring* short_company_name, std::wstring* vendor_name)
{
std::wstring cont(load_file(file, NULL)), line(L""), tag(L"#define VERSION_MAIN");
int end = -1, bgn = -1;
oem o = OEM_NONE;
if (v1)
{
bgn = find_line(cont, tag.c_str(), &end);
if (bgn < 0)
return false;
bgn = cont.find(tag, bgn);
bgn += tag.length();
while (cont[bgn] == L'\t' || cont[bgn] == L' ')
bgn++;
*v1 = _wtoi(cont.c_str() + bgn);
}
tag = L"#define VERSION_SUB";
if (v2)
{
bgn = find_line(cont, tag.c_str(), &end);
if (bgn < 0)
return false;
bgn = cont.find(tag, bgn);
bgn += tag.length();
while (cont[bgn] == L'\t' || cont[bgn] == L' ')
bgn++;
*v2 = _wtoi(cont.c_str() + bgn);
}
tag = L"#define VERSION_BUILD";
if (v3)
{
bgn = find_line(cont, tag.c_str(), &end);
if (bgn < 0)
return false;
bgn = cont.find(tag, bgn);
bgn += tag.length();
while (cont[bgn] == L'\t' || cont[bgn] == L' ')
bgn++;
*v3 = _wtoi(cont.c_str() + bgn);
}
tag = L"#define VERSION_PATCH";
if (v4)
{
bgn = find_line(cont, tag.c_str(), &end);
if (bgn < 0)
return false;
bgn = cont.find(tag, bgn);
bgn += tag.length();
while (cont[bgn] == L'\t' || cont[bgn] == L' ')
bgn++;
*v4 = _wtoi(cont.c_str() + bgn);
}
tag = L"#define OEM_";
{
bgn = find_line(cont, tag.c_str(), &end);
if (bgn < 0)
return false;
line = cont.substr(bgn, end - bgn);
if (line.find(oem_str(OEM_HANWANG)) != std::wstring::npos)
o = OEM_HANWANG;
else if (line.find(oem_str(OEM_LISICHENG)) != std::wstring::npos)
o = OEM_LISICHENG;
}
bool found = false, is_oem = false;
bgn = end = 0;
do
{
bgn += end;
line = L"";
coding_util::pick_line(cont.c_str() + bgn, got_wstr, &line, &end);
trim_left(line);
if (line.find(L"#if") == 0)
{
if (line.find(L"#ifdef ") == 0)
{
line.erase(0, lstrlenW(L"#ifdef "));
trim_left(line);
}
else if (line.find(L"#if ") == 0)
{
line.erase(0, 4);
trim_left(line);
if (line.find(L"defined(") == 0)
{
line.erase(0, lstrlenW(L"defined("));
trim_left(line);
size_t pos = line.find(L")");
if (pos != std::wstring::npos)
line.erase(pos);
}
}
if (line == oem_str(o))
{
found = true;
cont.erase(0, bgn);
// end -= bgn;
bgn = 0;
}
else if (!is_oem)
{
is_oem = from_str(line.c_str()) != OEM_NOT;
}
}
else if (line.find(L"#el") == 0)
{
if (found)
{
cont.erase(bgn + end);
break;
}
else if (line.find(L"#elif ") == 0)
{
line.erase(0, lstrlenW(L"elif "));
trim_left(line);
if (line.find(L"defined(") == 0)
{
line.erase(0, lstrlenW(L"defined("));
trim_left(line);
size_t pos = line.find(L")");
if (pos != std::wstring::npos)
line.erase(pos);
if (line == oem_str(o))
{
found = true;
cont.erase(0, bgn);
// end -= bgn;
bgn = 0;
}
else if (!is_oem)
{
is_oem = from_str(line.c_str()) != OEM_NOT;
}
}
}
else if (line.find(L"#else") == 0)
{
found = is_oem;
if (found)
{
cont.erase(0, bgn);
// end -= bgn;
bgn = 0;
}
}
}
else if (line.find(L"#endif") == 0)
{
if (found)
{
cont.erase(bgn + end);
break;
}
}
} while (end);
if (!found)
return false;
//
bgn = end = 0;
do
{
bgn += end;
line = L"";
coding_util::pick_line(cont.c_str() + bgn, got_wstr, &line, &end);
trim_left(line);
if (line.find(L"#define OEM_NAME") == 0)
{
line.erase(0, lstrlenW(L"#define OEM_NAME"));
trim_left(line);
size_t pos = line.find(L"\"");
if (pos++ != std::wstring::npos)
{
line.erase(0, pos);
pos = line.find(L"\"");
if(pos != std::wstring::npos)
line.erase(pos);
if(company_name)
coding_util::from_web_style(line.c_str(), got_wstr, company_name);
}
}
else if (line.find(L"#define OEM_SHORT_NAME") == 0)
{
line.erase(0, lstrlenW(L"#define OEM_SHORT_NAME"));
trim_left(line);
size_t pos = line.find(L"\"");
if (pos++ != std::wstring::npos)
{
line.erase(0, pos);
pos = line.find(L"\"");
if(pos != std::wstring::npos)
line.erase(pos);
if(short_company_name)
coding_util::from_web_style(line.c_str(), got_wstr, short_company_name);
}
}
else if (line.find(L"#define PRODUCT_VENDOR") == 0)
{
line.erase(0, lstrlenW(L"#define PRODUCT_VENDOR"));
trim_left(line);
size_t pos = line.find(L"\"");
if (pos++ != std::wstring::npos)
{
line.erase(0, pos);
pos = line.find(L"\"");
if(pos != std::wstring::npos)
line.erase(pos);
if(vendor_name)
coding_util::from_web_style(line.c_str(), got_wstr, vendor_name);
}
}
} while (end);
}
bool set_rc_ver(const wchar_t* file, int v_1, int v_2, int v_3, int v_4, const wchar_t* company_name, const wchar_t* short_company_name, const wchar_t* vender)
{
bom bm = BOM_UTF8;
std::wstring cont(load_file(file, &bm)), tag(L"FILEVERSION "), cr(bm == BOM_ANSI ? L"(C)" : L"\u00a9");
int bgn = -1, end = -1;
wchar_t ver[80] = { 0 };
if (cont.length() < 1000)
return false;
swprintf_s(ver, _countof(ver) - 1, L"%d,%d,%d,%d\r\n", v_1, v_2, v_3, v_4);
{
bgn = find_line(cont, tag.c_str(), &end);
if (bgn < 0)
return false;
bgn = cont.find(tag.c_str(), bgn);
bgn += tag.length();
while (cont[bgn] == L'\t' || cont[bgn] == L' ')
bgn++;
cont.replace(bgn, end - bgn, ver);
}
tag = L"PRODUCTVERSION";
{
bgn = find_line(cont, tag.c_str(), &end);
if (bgn < 0)
return false;
bgn = cont.find(tag.c_str(), bgn);
bgn += tag.length();
while (cont[bgn] == L'\t' || cont[bgn] == L' ')
bgn++;
cont.replace(bgn, end - bgn, ver);
}
tag = L"VALUE \"CompanyName\",";
{
bgn = find_line(cont, tag.c_str(), &end);
if (bgn < 0)
return false;
bgn = cont.find(tag.c_str(), bgn);
bgn += tag.length();
while (cont[bgn] == L'\t' || cont[bgn] == L' ')
bgn++;
cont.replace(bgn, end - bgn, std::wstring(L"\"") + company_name + L"\"\r\n");
}
tag = L"VALUE \"FileDescription\",";
{
bgn = find_line(cont, tag.c_str(), &end);
if (bgn < 0)
return false;
bgn = cont.find(tag.c_str(), bgn);
bgn += tag.length();
while (cont[bgn] == L'\t' || cont[bgn] == L' ')
bgn++;
cont.replace(bgn, end - bgn, std::wstring(L"\"") + short_company_name + L"\u626B\u63CF\u4EEA\u5E94\u7528\u7A0B\u5E8F\"\r\n");
}
tag = L"VALUE \"FileVersion\",";
{
bgn = find_line(cont, tag.c_str(), &end);
if (bgn < 0)
return false;
swprintf_s(ver, _countof(ver) - 1, L"\"%d.%d.%d.%d\"\r\n", v_1, v_2, v_3, v_4);
bgn = cont.find(tag.c_str(), bgn);
bgn += tag.length();
while (cont[bgn] == L'\t' || cont[bgn] == L' ')
bgn++;
cont.replace(bgn, end - bgn, ver);
}
tag = L"VALUE \"LegalCopyright\",";
{
bgn = find_line(cont, tag.c_str(), &end);
if (bgn < 0)
return false;
swprintf_s(ver, _countof(ver) - 1, L"\"Copyright %s %d\"\r\n", cr.c_str(), v_3);
bgn = cont.find(tag.c_str(), bgn);
bgn += tag.length();
while (cont[bgn] == L'\t' || cont[bgn] == L' ')
bgn++;
cont.replace(bgn, end - bgn, ver);
}
tag = L"VALUE \"ProductName\",";
{
bgn = find_line(cont, tag.c_str(), &end);
if (bgn < 0)
return false;
swprintf_s(ver, _countof(ver) - 1, L"\"%sScan\"\r\n", vender);
bgn = cont.find(tag.c_str(), bgn);
bgn += tag.length();
while (cont[bgn] == L'\t' || cont[bgn] == L' ')
bgn++;
cont.replace(bgn, end - bgn, ver);
}
tag = L"VALUE \"ProductVersion\",";
{
bgn = find_line(cont, tag.c_str(), &end);
if (bgn < 0)
return false;
swprintf_s(ver, _countof(ver) - 1, L"\"%d.%d.%d.%d\"\r\n", v_1, v_2, v_3, v_4);
bgn = cont.find(tag.c_str(), bgn);
bgn += tag.length();
while (cont[bgn] == L'\t' || cont[bgn] == L' ')
bgn++;
cont.replace(bgn, end - bgn, ver);
}
std::string bomstr("");
if (bm == BOM_UNICODE)
coding_util::bom::from_unicode(cont.c_str(), cont.length() * 2, got_str, &bomstr);
else if (bm == BOM_UTF8)
{
std::string utf8("");
coding_util::unicode_2_utf8(cont.c_str(), got_str, &utf8);
coding_util::bom::from_utf8(utf8.c_str(), utf8.length(), got_str, &bomstr);
}
else
coding_util::unicode_2_ansi(cont.c_str(), got_str, &bomstr);
file_util::save_2_file(bomstr.c_str(), bomstr.length(), file);
return true;
}
};
static bool set_ver(const wchar_t* file, oem vendor, bool x86, int pid, int main)
{
bool ret = false;
bom bm = BOM_UTF8;
std::string cont("");
std::wstring unic(rc::load_file(file, &bm));
if (unic.length() < 1000)
{
std::wcout << L"File length(" << unic.length() << L") is too small : " << file << std::endl;
}
else
{
time_t now = time(NULL);
struct tm* cur = localtime(&now);
int sub = x86 ? 1000 : 1100,
build = cur->tm_year + 1900,
patch = (cur->tm_mon + 1) * 1000 + cur->tm_mday * 10;
if (vendor == OEM_HANWANG)
patch += 6;
else if (vendor == OEM_LISICHENG)
patch += 7;
else
patch += 1;
while (change_oem(unic, vendor))
{
if (main && !change_main(unic, main))
break;
if (!change_sub(unic, sub, main))
break;
if (!change_build(unic, build))
break;
if (!change_patch(unic, patch))
break;
if (!change_product_id(unic, pid))
break;
ret = true;
break;
}
if (ret)
{
cont = "";
if (bm == BOM_UNICODE)
coding_util::bom::from_unicode(unic.c_str(), unic.length() * 2, got_str, &cont);
else if (bm == BOM_UTF8)
{
std::string utf8("");
coding_util::unicode_2_utf8(unic.c_str(), got_str, &utf8);
coding_util::bom::from_utf8(utf8.c_str(), utf8.length(), got_str, &cont);
}
else
coding_util::unicode_2_ansi(unic.c_str(), got_str, &cont);
file_util::save_2_file(cont.c_str(), cont.length(), file);
std::wstring cn(L""), scn(L""), vendor(L""), base(file), rcf(L"");
STR_PARENT_FOLDER(base);
if (rc::get_version_from_file(file, &main, &sub, &build, &patch, &cn, &scn, &vendor))
{
rcf = base + L"\\..\\sane\\sane.rc";
STR_SIMPLIFY_PATH(rcf);
if (!rc::set_rc_ver(rcf.c_str(), main, sub, build, patch, cn.c_str(), scn.c_str(), vendor.c_str()))
std::wcout << "change version failed: " << rcf.c_str() << std::endl;
rcf = base + L"\\..\\device\\scanner.rc";
STR_SIMPLIFY_PATH(rcf);
if (!rc::set_rc_ver(rcf.c_str(), main, sub, build, patch, cn.c_str(), scn.c_str(), vendor.c_str()))
std::wcout << "change version failed: " << rcf.c_str() << std::endl;
}
else
{
std::wcout << L"get version info failed\r\n";
}
}
else
std::wcout << L"change first file version failed: " << file << std::endl;
}
return ret;
}

View File

@ -0,0 +1,153 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{a7528596-fba2-4fff-8649-c8d0eebc6554}</ProjectGuid>
<RootNamespace>hgsetver</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(SolutionDir)sdk\include;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)sdk\lib\$(Configuration);$(LibraryPath)</LibraryPath>
<IntDir>$(SolutionDir)..\..\tmp\$(PlatformTarget)\$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(SolutionDir)sdk\include;$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)sdk\lib\$(Configuration);$(LibraryPath)</LibraryPath>
<IntDir>$(SolutionDir)..\..\tmp\$(PlatformTarget)\$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="hgsetver.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="源文件">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="hgsetver.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LocalDebuggerCommandArguments>F:\projs\huagao\working\code_twain\twain\brand.h -oem hw</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LocalDebuggerCommandArguments>F:\projs\huagao\working\code_twain\twain\brand.h -oem lsc</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,516 @@
// gb_base64.h : base64 encoding, allow you use your own BASE64 letter table
//
// Author: Gongbing
//
// Date: 2016-07-02
#pragma once
#ifndef _INCLUDED_REF_
#define _INCLUDED_REF_
#include "../ref/ref.h"
#endif
#define MINI_BUF_LEN 40
// this MACRO should include <algorithm> and <string> header files ...
#define STD_STR_TO_LOWER(str) std::transform((str).begin(), (str).end(), (str).begin(), tolower)
namespace coding_util
{
// all apis return error code, except commenting specially
__declspec(novtable) struct IBase64 : public ref_util::IRef
{
COM_API_DECLARE(bool, init_table(const char* base64_table = 0));
// parameter: result((char*)data, ...)
// return: error code
COM_API_DECLARE(int, encode(const char* data, size_t len, inter_module_data::set_data result, void* param, unsigned int max_line_len = -1, bool need_padding = true));
COM_API_DECLARE(int, decode(const char* data, size_t len, inter_module_data::set_data result, void* param));
};
__declspec(novtable) struct IBitsBuf : public ref_util::IRef
{
COM_API_DECLARE(bool, resize(int len, bool init_val = false));
COM_API_DECLARE(void, reset(bool val = false));
COM_API_DECLARE(void, set(int index, bool val));
COM_API_DECLARE(bool, get(int index));
// following for two-dimension
COM_API_DECLARE(bool, resize(short row, short col, bool init_val = false));
COM_API_DECLARE(void, set(short row, short col, bool val));
COM_API_DECLARE(bool, get(short row, short col));
};
// convert a hex letter to 4-bits integer.
// ch: to receive the result
// return whether the parameter 'hex' is a valid hex-letter
PORT_API(bool) hex_str_2_int(char hex, unsigned char* ch);
/* commonplace code page: refer to https://www.cnblogs.com/answercard/p/10122434.html
GBK: 936
BIG5: 950
UTF-16: 1200
unicode: 1201
GB2312: 20936
hz-gb-2312: 52936
GB18030: 54936
UTF-7: 65000
UTF-8: 65001
*/
// get code page of given charset name, 0 is failure
PORT_API(UINT) code_page_from_name(const char* name);
PORT_API(UINT) code_page_from_name(const wchar_t* name);
// result((wchar_t*)data, ...);
//
// return: error code, 0 is success
PORT_API(int) ansi_2_unicode(const char* data, inter_module_data::set_data result, void* param, int chars = -1, UINT ansi_code_page = CP_ACP);
PORT_API(int) ansi_2_utf8(const char* data, inter_module_data::set_data result, void* param, int chars = -1, UINT ansi_code_page = CP_ACP);
PORT_API(int) unicode_2_ansi(const wchar_t* data, inter_module_data::set_data result, void* param, int chars = -1, UINT ansi_code_page = CP_ACP);
PORT_API(int) unicode_2_utf8(const wchar_t* data, inter_module_data::set_data result, void* param, int chars = -1);
PORT_API(int) utf8_2_ansi(const char* data, inter_module_data::set_data result, void* param, int chars = -1, UINT ansi_code_page = CP_ACP);
PORT_API(int) utf8_2_unicode(const char* data, inter_module_data::set_data result, void* param, int chars = -1);
// case transfer, return changes
PORT_API(int) to_upper(char* str, int len = -1);
PORT_API(int) to_upper(wchar_t* str, int len = -1);
PORT_API(int) to_lower(char* str, int len = -1);
PORT_API(int) to_lower(wchar_t* str, int len = -1);
// Function: transform string between unicode style as 0x1234 and web style such as \u1234, %12%34 ...
// result((wchar_t*)data, ...);
PORT_API(void) from_web_style(const wchar_t* data, inter_module_data::set_data result, void* param);
PORT_API(void) to_web_style(const wchar_t* data, inter_module_data::set_data result, void* param);
namespace bom
{
PORT_API(bool) is_unicode(const char* bom_str, bool* big_ending); // bom_str must be great than 3 bytes, big_ending to receive whether the bom is a Big-Ending unicode
PORT_API(bool) is_utf8(const char* bom_str); // bom_str must be great than 3 bytes
// result((char*)data, ...), maybe DATA_FLAG_ERROR
PORT_API(void) to_ansi(const char* bom_str, size_t bytes, inter_module_data::set_data result, void* param);
PORT_API(void) to_utf8(const char* bom_str, size_t bytes, inter_module_data::set_data result, void* param);
// result((wchar_t*)data, ...), maybe DATA_FLAG_ERROR
PORT_API(void) to_unicode(const char* bom_str, size_t bytes, inter_module_data::set_data result, void* param, bool little_ending = true);
// result((char*)data, ...), maybe DATA_FLAG_ERROR
PORT_API(void) from_ansi(const char* bom_str, size_t bytes, inter_module_data::set_data result, void* param);
PORT_API(void) from_unicode(const wchar_t* bom_str, size_t bytes, inter_module_data::set_data result, void* param, bool little_ending = true);
PORT_API(void) from_utf8(const char* bom_str, size_t bytes, inter_module_data::set_data result, void* param);
}
PORT_API(int) trim_left(char* str, const char* trim_letter = " \t"); // return erased letters count
PORT_API(int) trim_left(wchar_t* str, const wchar_t* trim_letter = L" \t"); // return erased letters count
PORT_API(int) trim_right(char* str, const char* trim_letter = " \t"); // return erased letters count
PORT_API(int) trim_right(wchar_t* str, const wchar_t* trim_letter = L" \t"); // return erased letters count
// return whether replaced, maybe DATA_FLAG_ERROR if 'old' is a sub-string in rep when 'all' is true
// all string should ended with '\0'
PORT_API(bool) replace(const char* str, const char* old, const char* rep, inter_module_data::set_data result, void* param, bool all = true);
PORT_API(bool) replace(const wchar_t* str, const wchar_t* old, const wchar_t* rep, inter_module_data::set_data result, void* param, bool all = true);
// function: to pick the value between 'lead' and 'end' block.
// cont: the origin text
// lead: the leading mark
// end: the ending mark
// result: data - (const wchar_t*) or (const char*) value, without lead and rear mark
// len - data bytes
// total - found count
// flag - DATA_FLAG_FINAL
// param - same as the parameter 'param'
// first: to receive the beginning of the found value
// last: to receive the endding of the found value
// include_tag: picked result whether include the 'lead' and 'end' string
// case_sensitive: whether the lead and end are case sensitive
//
// return: found count, -1 is error
enum mark_layer
{
MARK_LAYER_FLAT = 1, // context formed as lead + val + end + ... + lead + val + end + ...
MARK_LAYER_EMBED, // context formed as lead + (lead + val + end) ... + end + ...
};
PORT_API(int) pick_value(const char* cont, const char* lead, const char* end, inter_module_data::set_data result, void* param, bool include_tag = false, bool case_sensitive = true, mark_layer layer = MARK_LAYER_EMBED);
PORT_API(int) pick_value(const char* cont, const char* lead, const char* end, int* first, int* last, bool include_tag = false, bool case_sensitive = true, mark_layer layer = MARK_LAYER_EMBED);
PORT_API(int) pick_value(const wchar_t* cont, const wchar_t* lead, const wchar_t* end, inter_module_data::set_data result, void* param, bool include_tag = false, bool case_sensitive = true, mark_layer layer = MARK_LAYER_EMBED);
PORT_API(int) pick_value(const wchar_t* cont, const wchar_t* lead, const wchar_t* end, int* first, int* last, bool include_tag = false, bool case_sensitive = true, mark_layer layer = MARK_LAYER_EMBED);
PORT_API(int) pick_first_branch_in_if_else_endif(const wchar_t* cont, const wchar_t* lead, const wchar_t* elif, const wchar_t* end, int* first, int* last, bool include_tag = false, bool case_sensitive = true);
// simple_line: consider followin lines
// line 1\
// -line 2
// true - return "line 1"
// false - return "line 1-line 2"
PORT_API(void) pick_line(const char* str, inter_module_data::set_data result, void* param, int* next_line = NULL, bool simple_line = false);
PORT_API(void) pick_line(const wchar_t* str, inter_module_data::set_data result, void* param, int* next_line = NULL, bool simple_line = false);
PORT_API(void) pick_whole_line(const char* cur, const char* bgn, inter_module_data::set_data result, void* param, int* next_line = NULL, bool simple_line = false);
PORT_API(void) pick_whole_line(const wchar_t* cur, const wchar_t* bgn, inter_module_data::set_data result, void* param, int* next_line = NULL, bool simple_line = false);
enum num_format
{
NUM_FMT_DECIMAL, // float/double
NUM_FMT_INTEGER, // int in decimal
NUM_FMT_BIN,
NUM_FMT_OCT,
NUM_FMT_HEX,
};
// function: to pick a number from string
// num_str: number string
// ret: to receive the ending point of the number
// nf: format of num_str
//
// return: all in double value, if nf is in BIN, OCT or HEX, this contains max 32-bits
// maybe return NON if num_str in DECIMAL or INTEGER
PORT_API(double) pick_number(const char* num_str, const char** ret = NULL, num_format nf = NUM_FMT_DECIMAL);
PORT_API(double) pick_number(const wchar_t* num_str, const wchar_t** ret = NULL, num_format nf = NUM_FMT_DECIMAL);
// function: to pick an integer from a number string
//
// remarks: if all digit is in [0, 9], then consider it as a decimal
// 0xnnn or nnnh: heximal
// nnno: oct
// nnnb: binary
// other: decimal
// return: -1 if failed
PORT_API(unsigned long long) pick_integer(const char* num_str, size_t bytes = 4);
PORT_API(unsigned long long) pick_integer(const wchar_t* num_str, size_t bytes = 4);
// following two apis replace the string in str buffer, and return ERROR_SUCCESS or ERROR_INSUFFICIENT_BUFFER
// all string should ended with '\0'
PORT_API(int) replace(char* str, size_t str_buf_len, const char* old, const char* _new, bool *rep);
PORT_API(int) replace(wchar_t* str, size_t str_buf_len, const wchar_t* old, const wchar_t* _new, bool *rep);
PORT_API(IBase64*) create_base64(void);
PORT_API(IBitsBuf*) create_bits_buffer(void);
// function: calculate md5
// return: md5_val, may be empty if the path_file is not accessible
PORT_API(char*) md5(const char* data, size_t len, char md5_val[MINI_BUF_LEN]);
PORT_API(char*) md5(const wchar_t* path_file, char md5_val[MINI_BUF_LEN]);
enum _aes_type_
{
AES_ECB = 1,
AES_CBC,
AES_OFB,
AES_CFB,
};
PORT_API(int) aes_encoding(const char* plain, size_t len, const char *iv, const char* pwd, inter_module_data::set_data result, void* param, int iv_len = 16, int pwd_len = 16, _aes_type_ type = AES_CBC);
PORT_API(int) aes_decoding(const char* cipher, size_t len, const char *iv, const char* pwd, inter_module_data::set_data result, void* param, int iv_len = 16, int pwd_len = 16, _aes_type_ type = AES_CBC);
// return 0 if success
PORT_API(int) lzw_encoding(const char* plain, size_t len, inter_module_data::set_data result, void* param);
PORT_API(int) lzw_decoding(const char* cipher, size_t len, inter_module_data::set_data result, void* param);
// wildcard matching ...
// str: to be compared string
// pattern: include '*' or '?', e.g. "*.bat"
PORT_API(bool) is_wildcard_match(const char* str, const char* pattern, int str_len = -1, int patt_len = -1);
PORT_API(bool) is_wildcard_match(const wchar_t* str, const wchar_t* pattern, int str_len = -1, int patt_len = -1);
// convert time to string like: "yyyy-mm-dd hh:mm:ss"
// NOTE: parameter 'tmprc' is valid only when 't' is ZERO
enum _time_precision
{
TIME_PRECISION_SECOND = 0,
TIME_PRECISION_MILLISECOND,
TIME_PRECISION_ms = TIME_PRECISION_MILLISECOND,
TIME_PRECISION_MICROSECOND,
TIME_PRECISION_us = TIME_PRECISION_MICROSECOND,
TIME_PRECISION_NANOSECOND,
TIME_PRECISION_ns = TIME_PRECISION_NANOSECOND,
};
enum _week
{
WEEK_DAY_NO = 0,
WEEK_DAY_CN,
WEEK_DAY_EN,
};
PORT_API(bool) local_time_2_string(char tm_str[MINI_BUF_LEN], _time_precision tmprc = TIME_PRECISION_SECOND, _week week = WEEK_DAY_NO, time_t t = 0);
PORT_API(bool) local_time_2_string(wchar_t tm_str[MINI_BUF_LEN], _time_precision tmprc = TIME_PRECISION_SECOND, _week week = WEEK_DAY_NO, time_t t = 0);
PORT_API(const wchar_t*) get_week_string(int day_of_week, bool chinese);
// convert string like "yyyy-mm-dd hh:mm:ss" to local time, return -1 is error
PORT_API(time_t) time_str_2_date_time(const char* tm_str);
PORT_API(time_t) time_str_2_date_time(const wchar_t* tm_str);
// version ...
// function: convert version '1.2.3.4' to 0x01020304
PORT_API(UINT64) version_string_2_int(const char* dot_version);
PORT_API(UINT64) version_string_2_int(const wchar_t* dot_version);
// return ver_buf
PORT_API(char*) version_string_from_int(UINT64 val, char ver_buf[MINI_BUF_LEN]);
PORT_API(wchar_t*) version_string_from_int(UINT64 val, wchar_t ver_buf[MINI_BUF_LEN]);
// return: 0 - equal; 1 - dot_version1 > dot_version2; -1 - dot_version1 < dot_version2
PORT_API(int) compare_version(const char* dot_version1, const char* dot_version2);
PORT_API(int) compare_version(const wchar_t* dot_version1, const wchar_t* dot_version2);
// file time
PORT_API(bool) file_time_2_time(FILETIME ft, time_t* t);
PORT_API(bool) file_time_from_time(time_t t, FILETIME* ft);
// convert the hex-string '12cdef' to [0x12, 0xcd, 0xef]
// return: ending position in hex_str after this
PORT_API(int) hex_string_2_bytes_seq(const char* hex_str, inter_module_data::set_data result, void* param, const char* omit = " \t\r\n");
PORT_API(int) hex_string_2_bytes_seq(const wchar_t* hex_str, inter_module_data::set_data result, void* param, const wchar_t* omit = L" \t\r\n");
// transferred char like '\r', '\n' ... 'ok' to receive whether transfered
PORT_API(char*) to_transfer_text(char trans_char, bool* ok); // return "\n" for '\n'
PORT_API(wchar_t*) to_transfer_text(wchar_t trans_char, bool* ok); // return L"\n" for L'\n
PORT_API(char) from_transfer_text(const char* trans_char, int* used_bytes, bool* ok); // return '\n' for "\n"
PORT_API(wchar_t) from_transfer_text(const wchar_t* trans_char, int* used_bytes, bool* ok); // return L'\n' for L"\n"
// create guid as "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}", return buf
wchar_t* create_guid(wchar_t buf[MINI_BUF_LEN * 2]);
};
namespace cxx_code
{
// function: to check a character is space or not
//
// parameter: ch - the character to be check
//
// return: whether the character 'ch' is a space
//
// NOTE: we assume the following characters spaces:
// ' ', '\r', '\n', '\t'
PORT_API(bool) is_space_char(wchar_t ch);
// function: skip the space character until valid character or ending
//
// parameter: codes - the cxx codes string
//
// pos - [in] starting pos to skip, [out] - the first none-space character position
//
// has_lrn - whether the spaces has '\n'
//
// return: whether any spaces has been skipped, i.e. the out pos is greater than in pos
//
// NOTE: space characters: ' '; '\t'; '\r'; '\n'
PORT_API(bool) skip_space(const wchar_t* codes, int* pos, bool *has_lrn = NULL);
// function: to check the character 'ch' is whether a valid leading character of a variable
PORT_API(bool) is_var_leading_char(wchar_t ch);
// function: to check the character 'ch' is whether a valid character of a variable
PORT_API(bool) is_var_char(wchar_t ch);
// return the line ending char '\n' position or ending position if no, support multi-line joint by '\\'
// str[ret] = L'\n' || str[ret] = 0
PORT_API(long) line_ending(const wchar_t* str, int bgn);
// find the next 'key' position in 'str', omit those in quotes or comments, return -1 when not found
PORT_API(long) next_key(const wchar_t* str, const wchar_t* key, int bgn = 0);
// return comment block beginning position (str[ret] = L'/'), -1 if not a comment block, start from *pos and set ending in pos when return
//
// pos when out will be the line ending (str[*pos] = L'\n') or the last '/' character of "/**/" block (str[*pos] = L'/')
PORT_API(long) comment_block(const wchar_t* str, int* pos);
// function: erase the comments in "/**/" or after "//"
//
// parameter: codes - the cxx codes string
//
// notify - data: (const wchar_t*)the codes string after erasing comments
//
// len: unused
//
// total: unused
//
// flag: always be DATA_FLAG_FINAL
//
// param: same as the parameter 'param' you passed in the function
//
// param - for callback 'notify' using
//
// return: nonsence
//
// NOTE: the last '\n' after the comments will be reserved
PORT_API(void) erase_comments(const wchar_t* codes, INTER_MODULE_CALLBACK_VAR(notify), void* param);
// function: pick a variable or function name
//
// parameter: codes - the cxx codes string
//
// pos - [in] starting pos, [out] - ending position after the last name character, or error position when failed
//
// digit - true to pick a digit, false to pick a variable
//
// return: the beginning of the name, -1 for error
PORT_API(int) pick_variable(const wchar_t* codes, int* pos, bool digit = false);
// function: pick a block between characters 'bgn_ch' and 'end_ch'
//
// parameter: codes - the cxx codes string
//
// pos - [in] starting pos, [out] - ending position after the last name character(codes[*pos] == 'end_ch'), or error position when failed
//
// bgn_ch - the beginning character of the block, e.g. '('
//
// end_ch - the ending character of the block, e.g. ')'
//
// single_line - whether the block will be a single line in commonplace, or else with '\\' at the line ending
//
// other_comment_leading_char - other sinle line comment leading character
//
// return: the beginning of the block (codes[ret] == 'bgn_ch'), -1 for error.
// failed also when single_line was true and meeting line-endig before 'end_ch'
//
// NOTE: this function will ommit the 'bgn_ch' and 'end_ch' which is after '\\' or in quotes "" or ''
PORT_API(int) pick_block(const wchar_t* codes, int* pos, wchar_t bgn_ch, wchar_t end_ch, bool single_line = false, wchar_t other_comment_leading_char = 0);
// function: pick a if-else codes block
//
// parameter: codes - the cxx codes string
//
// pos - [in] starting pos, [out] - ending position after the last name character, or error position when failed
//
// notify - to notify a picked branch
//
// data: (const wchar_t*)condition, "(...)", empty string if the last 'else' branch
//
// len: (const wchar_t*)entity, "{...}"
//
// total: unused, always be ZERO
//
// flag: always be DATA_FLAG_FINAL. no invoking if error occurs
//
// param: same as the parameter 'param' you passed in the function
//
// return: SET_RESULT_CONTINUE to continue, SET_RESULT_STOP to stop this invoking
//
// param - for callback 'notify' using
//
// other_comment_leading_char - other sinle line comment leading character
//
// return: the beginning of the block, -1 for error
//
// NOTE: first word must be "if"
PORT_API(int) pick_if_else_block(const wchar_t* codes, int* pos, INTER_MODULE_CALLBACK_VAR(notify), void* param, wchar_t other_comment_leading_char = 0);
// function: pick a #if-#endif codes block
//
// parameter: codes - the cxx codes string
//
// pos - [in] starting pos, [out] - ending position after the last name character, or error position when failed
//
// notify - to notify a picked branch
//
// data: (const wchar_t*)condition, empty string if the last 'else' branch
//
// len: (const wchar_t*)entity
//
// total: unused, always be ZERO
//
// flag: always be DATA_FLAG_FINAL. no invoking if error occurs
//
// param: same as the parameter 'param' you passed in the function
//
// return: SET_RESULT_CONTINUE to continue, SET_RESULT_STOP to stop this invoking
//
// param - for callback 'notify' using
//
// return: the beginning of the block, -1 for error
//
// NOTE: first word must be "#if"
PORT_API(int) pick_macro_if_else_block(const wchar_t* codes, int* pos, INTER_MODULE_CALLBACK_VAR(notify), void* param);
// function: pick a function block
//
// parameter: codes - the cxx codes string
//
// pos - [in] starting pos, [out] - ending position after the last '}', or error position when return false
//
// notify - data: (const wchar_t*)function name and pre_leading declaration
//
// len: parameters ending with double '\0'
//
// total: (const wchar_t*)function entity, leading with '{' and ending with '}'
//
// flag: always be DATA_FLAG_FINAL. no invoking if error occurs
//
// param: same as the parameter 'param' you passed in the function
//
// param - for callback 'notify' using
//
// other_comment_leading_char - other sinle line comment leading character
//
// return: true when success, and then the function elements is passed back by 'notify'
//
// NOTE: it will be without entity if it was a function invoking
PORT_API(bool) pick_function(const wchar_t* codes, int* pos, INTER_MODULE_CALLBACK_VAR(notify), void* param, wchar_t other_comment_leading_char = 0);
// function: to get the line number from offset 'pos'
//
PORT_API(unsigned) line_from_pos(const wchar_t* cont, unsigned pos);
// Function: to save and calculate a logical action result
//
// e.g.: set 'is_win' is 'true, then check 'is_win' will return true and '!is_win' is false
//
// NOTE: now support '||', '&&' and '!' operator and consider expression like 'i >= 0' as ONE variable
// this means every expression between '&&' and '||' will consider as ONE variable
//
__declspec(novtable) struct ILogicAction : public ref_util::IRef
{
// Function: to set the callback to query value when a variable is unknown
//
// get_variable_val: data - see 'inter_module_data::DATA_FLAG_GET_VAL'
//
// len - see 'inter_module_data::DATA_FLAG_GET_VAL'
//
// total - see 'inter_module_data::DATA_FLAG_GET_VAL'
//
// flag - always be DATA_FLAG_GET_VAL
//
// param - the same as 'param' in this function
//
// NOTE: all unknown variable would be considered as 'false' if you did not set the callback
// variable values has multi-strings format, and end with '\0' per value, double '\0' for all values
COM_API_DECLARE(void, set_callback(inter_module_data::set_data get_variable_val, void* param));
// Function: add or modify known boolean value
//
// var: boolean variable, multi-vars divided by ';'
//
COM_API_DECLARE(void, set_variable_value(const wchar_t* var, const wchar_t* val, int bytes = 0));
COM_API_DECLARE(void, set_variable_value(const wchar_t* var, bool val));
COM_API_DECLARE(void, remove_variable(const wchar_t* var));
COM_API_DECLARE(void, clear(void));
// Function: calculate logical expression such as 'is_win && is_android' ...
//
// logic_exp: logical expression, like 'is_win && is_android', '!is_win' ...
//
// supported: to receive whether the logic_exp is valid/supported now, return value would be nonsence if this was false
//
// return: boolean result. SEE 'supported' !!!
//
COM_API_DECLARE(bool, logic_expression_result(const wchar_t* logic_exp, bool* supported));
// Function: to query an logical expression value without user interacting
//
// Parameter: logic_expression - logical expression, like 'is_win && is_android', '!is_win' ...
//
// val - to receive the expression value if it was existing
//
// Return: whether the 'logic_expression' all are existing already (until calculate the result)
COM_API_DECLARE(bool, query_existing_value(const wchar_t* logic_exp, bool* val));
COM_API_DECLARE(inter_module_data::set_result, last_input_result(void));
// Function: get symbol's value. e.g. return L"1" of symbol_value(L"BUILD_TYPE", ...) if L"BUILD_TYPE=1" was existed
//
// return: value, NULL if not found. you should use it immediately, and need not free it.
COM_API_DECLARE(const wchar_t*, symbol_value(const wchar_t* symbol));
// save the logical-expressions to path_file which it is 'true'
COM_API_DECLARE(int, save(const wchar_t* path_file));
};
// logical action
PORT_API(ILogicAction*) create_logical_action(void);
}

Binary file not shown.

View File

@ -0,0 +1,70 @@
// database.h: simple database interface
//
// Author: Gongbing
//
// Date: 2020-09-11
#pragma once
#ifndef _INCLUDED_REF_
#define _INCLUDED_REF_
#include "../ref/ref.h"
#endif
#include <OAIdl.h> // for VARIANT
#define MAX_TABLE_FIELD_NAME_LEN 20
namespace db_util
{
enum // Driver type
{
DBDRIVER_ODBC_DBASE = 533,
DBDRIVER_ODBC_EXCEL = 790,
DBDRIVER_ODBC_ACCESS = 25,
DBDRIVER_ODBC_VFDB,
DBDRIVER_ODBC_VFTABLE,
DBDRIVER_FILE_SQLITE = 1000,
};
typedef struct _table_fields
{
wchar_t name[MAX_TABLE_FIELD_NAME_LEN];
VARIANT default_val; // the field 'type' is defining the field type too.
// NOW support VT_BOOL, VT_BSTR, VT_DATE, VT_I1(to VT_I8), VT_R4, VT_R8
// VT_DATE use function VariantTimeToSystemTime to convert !!!
int length; // 0 is not set, always for TEXT field
bool unique;
bool not_null;
bool primary_key;
bool foreign_key;
bool use_default_val; // whether use the 'default_val' in table as the field's default value
}TBLFLD;
__declspec(novtable) struct IRecordset : public ref_util::IRef
{
COM_API_DECLARE(int, get_rows(void)); // get count of records
COM_API_DECLARE(int, get_cols(void)); // get count of record fields
COM_API_DECLARE(bool, get_value(int row, int col, bool* boolean));
COM_API_DECLARE(bool, get_value(int row, int col, int* integer));
COM_API_DECLARE(bool, get_value(int row, int col, double* decimal));
COM_API_DECLARE(bool, get_value(int row, int col, wchar_t* buf, int* words/*[in] - words in buf; [out] - real length of the value. you should provide greater buffer if it was greater than in*/));
COM_API_DECLARE(bool, get_value(int row, int col, inter_module_data::set_data set_val/*data: pointed to an unicode string*/, void* param));
};
__declspec(novtable) struct IDatabase : public ref_util::IRef
{
COM_API_DECLARE(int, open(const wchar_t* db_name, const wchar_t* user_name = 0, const wchar_t* password = 0));
COM_API_DECLARE(int, create_table(const wchar_t* table_name, db_util::TBLFLD* fields, int fields_num, int *composed_primary_key_index = NULL));
COM_API_DECLARE(int, close(void));
COM_API_DECLARE(int, execute_sql(const wchar_t* sql, IRecordset** record = 0));
COM_API_DECLARE(int, get_error_msg(inter_module_data::set_data set_msg/*data: pointed to an unicode string*/, void* param)); // return error code
};
// exports ...
PORT_API(bool) add_database(const wchar_t* db_name, const wchar_t* db_file, int driver_type);
PORT_API(bool) del_database(const wchar_t* db_name, int driver_type = DBDRIVER_ODBC_ACCESS);
PORT_API(IDatabase*) create_database_instance(int driver_type = DBDRIVER_ODBC_ACCESS);
PORT_API(bool) create_table_sql(const wchar_t* table_name, TBLFLD* fields, int fields_num
, inter_module_data::set_data set_msg/*data: pointed to an unicode string*/, void* param
, int *composed_primary_key_index = NULL); // -1 is over
};

View File

@ -0,0 +1,230 @@
// folder_util.h : include utilities for manage folders
//
// Author: Gongbing
//
// Date: 2016-09-21
#pragma once
#include <vector>
#include <string>
#include <list>
#ifndef _INCLUDED_REF_
#define _INCLUDED_REF_
#include "../ref/ref.h"
#endif
namespace file_util
{
// 1 - all paths returned by these apis ended with '\\'
typedef struct _path_file
{
wchar_t path[MAX_PATH];
}PATHFILE, *LPPATHFILE;
enum file_coding
{
FILE_CODING_ANSI = 1,
FILE_CODING_UTF8,
FILE_CODING_UNICODE,
};
__declspec(novtable) struct IFileFinder : public ref_util::IRef
{
// found_file: to receive the found file with full path
// NOTE: child folder will always be in the found queue wherever you given the 'mark' !!!
// filter '*.*' will not match the file which without extension, so use '*' as default filter for mark
COM_API_DECLARE(int, find_first(const wchar_t* dir, LPPATHFILE found_file, const wchar_t* mark = L"*", bool recursive = true, bool depth_first = true, bool ignore_dot_folder = true));
COM_API_DECLARE(int, find_next(LPPATHFILE found_file));
COM_API_DECLARE(int, current_file_attr(WIN32_FILE_ATTRIBUTE_DATA* attr)); // return file attributes, -1 is error
COM_API_DECLARE(int, current_root(LPPATHFILE root)); // root: full path with last '\\' of current finding path
COM_API_DECLARE(int, stop_find(void));
COM_API_DECLARE(bool, is_current_folder(void));
};
__declspec(novtable) struct ISimpleShareMemory : public ref_util::IRef
{
// for monitor using, called should before write_result
COM_API_DECLARE(int, wait_result(const wchar_t* id, inter_module_data::set_data notify, void* notify_param, DWORD wait_milliseconds = -1, size_t max_size = -1/*one page*/));
// for notifier using
COM_API_DECLARE(int, write_result(const wchar_t* id, const char* data, size_t data_bytes));
};
__declspec(novtable) struct IGroupFile : public ref_util::IRef // to write grp_0000.txt, grp_0001.txt, ... files
{
COM_API_DECLARE(int, set_read_param(inter_module_data::set_data set_d, file_coding fc = FILE_CODING_ANSI));
COM_API_DECLARE(int, to_line(int line/*ZERO-based*/, int file_ind = -1)); // locate in read, return ERROR_SUCCESS in success
COM_API_DECLARE(int, read_line(void* param, bool next = true)); // param is used in the set_d callback; get the first line if next was true
COM_API_DECLARE(int, write(const char* data, size_t len));
COM_API_DECLARE(int, next_file(void));
COM_API_DECLARE(DWORD, cur_size(void));
COM_API_DECLARE(DWORD, cur_index(void)); // return current file index
COM_API_DECLARE(DWORD, cur_line(void)); // return current line in file
};
__declspec(novtable) struct IOvlHandler : public ref_util::IRef
{
COM_API_DECLARE(long, on_data_arrived(const char* data, size_t bytes, void* user_key)); // return how many bytes used, -1 to stop receiving !!!
COM_API_DECLARE(bool, on_data_sent(char* data, size_t bytes, size_t data_buf_len/*for reuse inner_buffer*/, void* user_key)); // return whether to keep the data buffer in use. true - use again, false - default value, should free it
COM_API_DECLARE(void, on_error(int err));
};
__declspec(novtable) struct IPipe : public ref_util::IRef
{
COM_API_DECLARE(int, read(void)); // data returned by IOvlHandler::on_data_arrived
COM_API_DECLARE(int, write(const char* data, size_t bytes, bool inner_buf/*whether the 'data' is returned by get_write_buf*/));
COM_API_DECLARE(int, close(void));
COM_API_DECLARE(char*, get_write_buf(size_t bytes));
COM_API_DECLARE(void, free_got_write_buf(void* buf/*returned by get_write_buf*/));
};
PORT_API(int) get_special_folder(int clsidl, LPPATHFILE path);
PORT_API(int) desktop(bool current_user, LPPATHFILE path);
PORT_API(int) start_menu(bool current_user, LPPATHFILE path);
PORT_API(int) start_menu_program(bool current_user, LPPATHFILE path);
PORT_API(int) start_menu_startup(bool current_user, LPPATHFILE path);
PORT_API(int) start_menu_recently(LPPATHFILE path);
PORT_API(int) application_data(bool current_user, LPPATHFILE path);
PORT_API(int) my_documents(bool current_user, LPPATHFILE path);
PORT_API(int) self_path(LPPATHFILE path);
PORT_API(int) local_application_data(LPPATHFILE path);
PORT_API(int) program_files(LPPATHFILE path);
PORT_API(int) windows(LPPATHFILE path);
PORT_API(int) system(LPPATHFILE path);
PORT_API(int) start_menu_program(LPPATHFILE path);
PORT_API(int) quick_launch(bool current_user, LPPATHFILE path, LPPATHFILE path_pin = NULL/*full path*/);
PORT_API(int) temporary_file(LPPATHFILE path, const wchar_t* prefix = NULL);
PORT_API(int) get_currentLoginUser_AppdataPath(LPPATHFILE path);//add by weidongli on 2019-6-3
PORT_API(void) simplify_path(wchar_t* path, size_t path_buf_len = 0/*as lstrlenW(path) + 1*/);
PORT_API(void) to_absolute_path(LPPATHFILE path); // convert './', '%WINDOWS%', '%SYSTEM%', ... to absolute path
PORT_API(void) to_relative_path(const wchar_t* path_file_base, const wchar_t* path_file_tobe, LPPATHFILE rel_path);
PORT_API(void) to_known_path(LPPATHFILE path); // convert absolute path to './', '%WINDOWS%', '%SYSTEM%', ...
PORT_API(void) append_name(const wchar_t* path_file, const wchar_t* append, LPPATHFILE result); // to insert string 'append' before extension name
PORT_API(bool) is_file_existing(const wchar_t* path_file);
PORT_API(bool) is_valid_file_name_character(wchar_t file_name_char);
PORT_API(int) force_rename_file(const wchar_t* from, const wchar_t* to);
PORT_API(int) force_copy_file(const wchar_t* from, const wchar_t* to);
PORT_API(int) force_move_file(const wchar_t* from, const wchar_t* to);
PORT_API(int) force_delete_file(const wchar_t* file);
PORT_API(int) force_create_file(const wchar_t* path_file, HANDLE* ret, DWORD acc = GENERIC_WRITE | GENERIC_READ, DWORD share = 0, DWORD method = CREATE_ALWAYS
, DWORD attr = FILE_ATTRIBUTE_NORMAL, LPSECURITY_ATTRIBUTES psa = NULL);
PORT_API(int) force_create_folder(const wchar_t* path_folder, SECURITY_ATTRIBUTES* psa = NULL, bool default_psa = true);
PORT_API(bool) initialize_commonplace_security(SECURITY_ATTRIBUTES* psa);
PORT_API(bool) is_valid_path(const wchar_t* path);
PORT_API(bool) is_dir(DWORD attr);
PORT_API(bool) is_dir(const wchar_t* path);
PORT_API(int) get_file_attributes(const wchar_t* path_file, WIN32_FILE_ATTRIBUTE_DATA* attr);
PORT_API(bool) get_file_version(const wchar_t* path_file, WORD* lpver_hh, WORD* lpver_hl, WORD* lpver_lh, WORD* lpver_ll, bool file_ver = true/*false is product version*/);
PORT_API(UINT64) get_file_size(const wchar_t* path_file);
PORT_API(UINT64) get_disk_available_space(const wchar_t* disk_path);
// when return false, 'err' can be:
//
// 1: ERROR_DISK_FULL - the free space in 'disk' is not enough
//
// 2: ERROR_FILE_SYSTEM_LIMITATION - 'bytes' exceedes the maximum of the file-system's limitation
//
PORT_API(bool) is_disk_space_enough_for_single_file(const wchar_t* disk, UINT64 bytes, int* err = NULL);
PORT_API(bool) is_parent_path(const wchar_t* path_to_check, const wchar_t* file); // to check whether the path 'path_to_check' is the parent path of 'file'
PORT_API(int) parent_folder(const wchar_t* path_file, LPPATHFILE path); // without last '\\'
PORT_API(int) common_parent_folder(const wchar_t* path_file1, const wchar_t* path_file2, LPPATHFILE parent);
PORT_API(int) file_name(const wchar_t* path_file, LPPATHFILE path, bool with_ext = NULL);
PORT_API(int) file_extension(const wchar_t* path_file, LPPATHFILE path); // without '.'
PORT_API(int) load_file(const wchar_t* file, inter_module_data::set_data result, void* param);
PORT_API(int) save_2_file(const char* data, size_t len, const wchar_t* file);
PORT_API(void*) map_file_to_memory(const wchar_t* path_file, bool read_only = true, DWORD expand_size = 0, HANDLE *file_handle = NULL, HANDLE *map_handle = NULL);
// clipboard
PORT_API(int) set_clipboard(const void* data, size_t bytes, int format = CF_TEXT, HWND owner = NULL);
PORT_API(int) set_clipboard_directly(HANDLE data, int format = CF_TEXT, HWND owner = NULL);
PORT_API(int) get_clipboard(void* buf, size_t* bytes/*[in]-bytes of buf, [out]-content bytes in clipboard*/, int format = CF_TEXT, HWND owner = NULL);
// parameter of result:
//
// data: real data of the clipboard format
//
// len: bytes of the data
//
// total: clipboard fromat, support CF_TEXT - (char*)data
// CF_UNICODETEXT - (wchar_t*)data
// CF_BITMAP - 'data' contains contents of PNG file
// CF_DIB - 'data' contains contents of BMP file
// CF_HDROP - (wchar_t*)data, copying files list, separated by "\r\n"
//
// flag: DATA_FLAG_FINAL
//
// param: same as 'user'
//
PORT_API(int) get_clipboard(inter_module_data::set_data result, void* user);
PORT_API(bool) browser_file(HWND owner, LPPATHFILE file, const wchar_t *filter = L"All Files(*.*)\0\0", bool open = true, const wchar_t* title = NULL, WNDPROC cust_proc = NULL, LPARAM proc_param = NULL);
// function: monitor file & folder
//
// path: full path, can be a folder or a file
//
// mask: FILE_NOTIFY_CHANGE_FILE_NAME FILE_NOTIFY_CHANGE_DIR_NAME FILE_NOTIFY_CHANGE_ATTRIBUTES FILE_NOTIFY_CHANGE_SIZE FILE_NOTIFY_CHANGE_LAST_WRITE FILE_NOTIFY_CHANGE_LAST_ACCESS FILE_NOTIFY_CHANGE_CREATION FILE_NOTIFY_CHANGE_SECURITY
//
// result: data - (const wchar_t*)path_file_name
// len - bytes of data
// total - unused
// flag - DATA_FLAG_FINAL
// param - the same as 'param' of this function
//
// return: monitor key , NULL if failed. should call un_monitor to free the return value
//
PORT_API(void*) monitor_files(const wchar_t* path, int mask, bool sub_dir, inter_module_data::set_data result, void* param);
PORT_API(void) un_monitor(void* key);
PORT_API(void) display_file_in_explorer(const wchar_t* path_file);
PORT_API(UINT64) get_filesystem_maximum_file_bytes(const wchar_t* disk, wchar_t* fs_name = NULL/*provids NULL or not less than "MAX_PATH + 2"*/);
PORT_API(IFileFinder*) create_file_finder(void);
PORT_API(ISimpleShareMemory*) create_simple_share_memory(void);
PORT_API(IGroupFile*) create_group_files(const wchar_t* first_file, bool for_read, int sn_digits = 4, DWORD limit_bytes = 0); // the limit_bytes would be ommited if fro_read was true
PORT_API(IPipe*) open_pipe(IOvlHandler* handler, const wchar_t* name);
}
#define STR_SIMPLIFY_PATH(str) \
{ \
file_util::PATHFILE pf = { 0 }; \
wcscpy_s(pf.path, _countof(pf.path) - 1, (str).c_str()); \
file_util::simplify_path(pf.path); \
(str) = pf.path; \
}
#define STR_TO_ABSOLUTE_PATH(str) \
{ \
file_util::PATHFILE pf = { 0 }; \
wcscpy_s(pf.path, _countof(pf.path) - 1, (str).c_str()); \
file_util::to_absolute_path(&pf); \
(str) = pf.path; \
}
#define STR_TO_KNOWN_PATH(str) \
{ \
file_util::PATHFILE pf = { 0 }; \
wcscpy_s(pf.path, _countof(pf.path) - 1, (str).c_str()); \
file_util::to_known_path(&pf); \
(str) = pf.path; \
}
#define STR_PARENT_FOLDER(str) \
{ \
file_util::PATHFILE pf = { 0 }; \
file_util::parent_folder((str).c_str(), &pf); \
(str) = pf.path; \
}
#define STR_FILE_NAME(str, with_ext) \
{ \
file_util::PATHFILE pf = { 0 }; \
file_util::file_name((str).c_str(), &pf, with_ext); \
(str) = pf.path; \
}
#define STR_FILE_EXTENSION(str) \
{ \
file_util::PATHFILE pf = { 0 }; \
file_util::file_extension((str).c_str(), &pf); \
(str) = pf.path; \
}

75
sln/sdk/include/log/log.h Normal file
View File

@ -0,0 +1,75 @@
// log.h : log utility
//
// Author: Gongbing
//
// Create: 2019-08-07
#pragma once
#ifndef _INCLUDED_REF_
#define _INCLUDED_REF_
#include "../ref/ref.h"
#endif
//////////////////////////////////////////////////////////////////////////////////////////
// level
enum _log_level
{
LOG_LEVEL_ALL = 1,
LOG_LEVEL_PART,
LOG_LEVEL_IMPORTANT,
LOG_LEVEL_VERY_IMPORTANT,
LOG_LEVEL_NONE = INT_MAX,
};
enum _log_type
{
LOG_TYPE_NONE,
LOG_TYPE_CONSOLE_OUT,
LOG_TYPE_OUTPUTDBG,
LOG_TYPE_WRITE_FILE,
LOG_TYPE_USER_CUSTOM,
};
//////////////////////////////////////////////////////////////////////////////////////////
// macros
#ifndef UNICODE_STR
#define _TO_UNICODE(str) L##str
#define UNICODE_STR(str) _TO_UNICODE(str)
#define MAKE_UNICODE(str) UNICODE_STR(str)
#endif
#define LOG_API_PROTO(name) void(__stdcall *name)(const wchar_t* info, size_t words, void* user)
#define LOG_API_INSTANCE(name) void __stdcall name(const wchar_t* info, size_t words, void* user)
namespace log_util
{
//////////////////////////////////////////////////////////////////////////////////////////
// log interface
typedef LOG_API_PROTO(real_log);
__declspec(novtable) struct ILog : public ref_util::IRef
{
// param0: (const wchar_t*)path file when type is LOG_TYPE_WRITE_FILE, real_log when type is LOG_TYPE_USER_CUSTOM. otherwise always be ZERO
// param1: for parameter 'user' of real_log when type is LOG_TYPE_USER_CUSTOM, otherwise always be ZERO
COM_API_DECLARE(int, set_log_level(_log_level level));
COM_API_DECLARE(int, set_log_type(_log_type type, void* param0 = NULL, void* param1 = NULL)); // return type after this oper
COM_API_DECLARE(void, write_log(const wchar_t* info, size_t bytes, _log_level level));
COM_API_DECLARE(bool, is_level_enabled(_log_level level)); // whether the message of level can be logged
COM_API_DECLARE(void, set_prefix(const wchar_t* pref)); // default is without prefix
COM_API_DECLARE(void, enable_time_stamp(bool enable)); // default is without timestamp
};
// use inner log_util
// param0: (const wchar_t*)path file when type is LOG_TYPE_WRITE_FILE, real_log when type is LOG_TYPE_USER_CUSTOM. otherwise always be ZERO
// param1: for parameter 'user' of real_log when type is LOG_TYPE_USER_CUSTOM, otherwise always be ZERO
PORT_API(ILog*) start_log(_log_type type = LOG_TYPE_OUTPUTDBG, _log_level level = LOG_LEVEL_ALL, void* param0 = NULL, void* param1 = NULL);
PORT_API(ILog*) get_cur_log_util(void);
// set an external log_util, NULL to stop current log, will invoke log->add_ref() if log is valid
PORT_API(void) set_log_util(ILog* log);
// invoke log
PORT_API(bool) is_logging_enable(_log_level level);
PORT_API_CALL(void, __cdecl) log(_log_level level, size_t estimate_bytes, const wchar_t* format, ...);
PORT_API_CALL(void, __cdecl) log(_log_level level, size_t estimate_bytes, const char* format, ...);
}

View File

@ -0,0 +1,259 @@
// net_app.h : network applications
//
// Author: Gongbing
//
// Create: 2019-07-22
#pragma once
#include "net_base.h"
//typedef struct ip_option_information {
// UCHAR Ttl;
// UCHAR Tos;
// UCHAR Flags;
// UCHAR OptionsSize;
// PUCHAR OptionsData;
//} IP_OPTION_INFORMATION, *PIP_OPTION_INFORMATION;
//typedef struct icmp_echo_reply {
// struct sockaddr_in Address;
// ULONG Status;
// ULONG RoundTripTime;
// USHORT DataSize;
// USHORT Reserved;
// PVOID Data;
// struct ip_option_information Options;
//} ICMP_ECHO_REPLY, *PICMP_ECHO_REPLY;
//#define IPAddr struct sockaddr_in
namespace net_app
{
enum web_format
{
WEB_FMT_UNKNOWN = 0,
WEB_FMT_STREAM, // binary stream ...
WEB_FMT_ANSI,
WEB_FMT_UTF8,
WEB_FMT_UNICODE,
WEB_FMT_DECIDE_BY_CONTENT, // text/html should decide by content
};
__declspec(novtable) struct IAcceptClient : public ref_util::IRef
{
COM_API_DECLARE(long, client_accepted(SOCKET s, const char* ip, unsigned port));
COM_API_DECLARE(void, on_server_exited(unsigned exit_code));
};
__declspec(novtable) struct ITcpSvrSocket : public ref_util::IRef
{
COM_API_DECLARE(long, listen_at(unsigned short port, const char* ip = NULL/*INADDR_ANY*/, bool reuse_addr = true));
COM_API_DECLARE(long, stop(void));
COM_API_DECLARE(long, listen_port(void));
COM_API_DECLARE(SOCKET, listen_socket(void));
};
__declspec(novtable) struct IAsyncTcpSvr : public ITcpSvrSocket
{
// following two functions return ERROR_FILE_HANDLE_REVOKED if the peer is used in transmit file
COM_API_DECLARE(long, read_from_peer(void* peer_key)); // DO NOT call this until you stop the read with return -1 in IPeerManager::on_data_arrived, server will invoke this automately
COM_API_DECLARE(long, write_2_peer(void* peer_key, const char* data, size_t data_len, bool inner_buffer = false/*whether the data buffer is returned by request_sent_buffer, if failed and iner_buffer is 'true', the 'data' would be freed !!!*/));
COM_API_DECLARE(long, close_peer(void* peer_key, int* peer_ref));
COM_API_DECLARE(long, set_peer_data(void* peer_key, int index, void* data));
COM_API_DECLARE(long, get_peer_data(void* peer_key, int index, void** data));
COM_API_DECLARE(long, peer_address(void* peer_key, char ip_buf[IP_BUF_LEN], unsigned* port));
COM_API_DECLARE(long, send_file_content(void* peer_key, HANDLE file)); // NOTE: this method only used for transmitting file content, all pre- or post-task should done by caller !!!
COM_API_DECLARE(size_t, io_buffer_size(bool in_buf));
// add on 2017-08-26 for add an existing connecting into client queue (DO NOT add it which is already in queue !!!)
// after this, you should operate the peer in IPeerManager.
// following two apis return peer_key
COM_API_DECLARE(void*, add_2_client_queue(SOCKET s));
COM_API_DECLARE(void*, create_async_tcp_client(const char* ip, unsigned short port, unsigned conn_timeout_seconds = 0, const char* reuse_ip = NULL, unsigned reuse_port = 0));
// for reducing the times of memory copying, request memory from inner - added on 2019-07-28
COM_API_DECLARE(char*, request_sent_buffer(size_t bytes));
COM_API_DECLARE(void, free_unsent_buffer(void* buf)); // free the returned value of request_sent_buffer which has NOT called write_2_peer with inner_buffer is 'true' yet!!!
};
__declspec(novtable) struct IAsyncTcpHatcher : public ref_util::IRef
{
COM_API_DECLARE(void*, connect(const char* ip, int port, const char* reuse_ip = NULL, unsigned reuse_port = 0));
COM_API_DECLARE(int, write(void* client, const char* buf, size_t data_len, bool inner_buf));
//COM_API_DECLARE(void*, add_2_client_queue(SOCKET s));
COM_API_DECLARE(int, close_client(void* client));
COM_API_DECLARE(int, destroy(void));
COM_API_DECLARE(long, send_file_content(void* client, HANDLE file)); // NOTE: this method only used for transmitting file content, all pre- or post-task should done by caller !!!
COM_API_DECLARE(bool, get_address(void* client, char* ip/*at least with 40 bytes!!!*/, int* port, bool svr = true));
};
__declspec(novtable) struct IAsyncTcpHandler : public ref_util::IRef
{
COM_API_DECLARE(long, on_data_arrived(void* client, const char* data, size_t data_len, bool* rcv_file/*[in] - whether in receiving file for transmit_file, [out] - stop(true) or continue(true) receiving file*/)); // return how many bytes used, -1 to stop receiving !!!
COM_API_DECLARE(bool, on_data_sent(void* client, char* data, size_t data_len, size_t data_buf_len/*for reuse inner_buffer*/)); // return whether to keep the data buffer in use. true - use again, false - default value, should free it
COM_API_DECLARE(void, on_closed(void* client, int err));
COM_API_DECLARE(void, on_file_content_sent(void* client, HANDLE file, ULONGLONG bytes, int error)); // response for IAsyncTcpSvr::send_file_content
};
__declspec(novtable) struct IPeerManager : public ref_util::IRef
{
COM_API_DECLARE(void, on_peer_connected(void* peer_key));
COM_API_DECLARE(void, on_server_exited(unsigned exit_code));
COM_API_DECLARE(long, on_data_arrived(void* peer_key, const char* data, size_t data_len, bool* rcv_file/*[in] - whether in receiving file for transmit_file, [out] - stop(true) or continue(true) receiving file*/)); // return how many bytes used, -1 to stop receiving !!!
COM_API_DECLARE(bool, on_data_sent(void* peer_key, char* data, size_t data_len, size_t data_buf_len/*for reuse inner_buffer*/)); // return whether to keep the data buffer in use. true - use again, false - default value, should free it
COM_API_DECLARE(void, on_peer_error(void* peer_key, unsigned err_code));
COM_API_DECLARE(void, on_peer_closed(void* peer_key));
COM_API_DECLARE(bool, is_peer_timeout(void* peer_key, int elapsed_seconds/*elapsed seconds from last active*/));
COM_API_DECLARE(void, on_file_content_sent(void* peer_key, HANDLE file, ULONGLONG bytes, int error)); // response for IAsyncTcpSvr::send_file_content
};
__declspec(novtable) struct IBlockTcp : public ref_util::IRef
{
COM_API_DECLARE(SOCKET, attach(SOCKET s));
COM_API_DECLARE(SOCKET, detach(void));
COM_API_DECLARE(SOCKET, socket_handle(void));
COM_API_DECLARE(int, re_connect(const char* dot_ip = NULL, unsigned short port = 0));
COM_API_DECLARE(int, set_timeout(unsigned *read_timeout/*milliseconds*/, unsigned *write_timeout/*milliseconds*/));
COM_API_DECLARE(int, read(char* buf, size_t buf_len, size_t* read_bytes));
COM_API_DECLARE(int, write(const char* buf, size_t data_len, size_t* wrote));
COM_API_DECLARE(int, last_error(void));
COM_API_DECLARE(long, send_file_content(HANDLE file)); // NOTE: this method only used for transmitting file content, all pre- or post-task should done by caller !!!
COM_API_DECLARE(void, get_address(char* ip/*at least with 40 bytes!!!*/, int* port, bool svr = true));
COM_API_DECLARE(int, close(void));
};
__declspec(novtable) struct IUdpSvrHandler : public ref_util::IRef
{
COM_API_DECLARE(size_t,on_udp_data_arrived(const char* data, size_t data_len, const char* ip, unsigned port)); // return used data bytes
COM_API_DECLARE(bool, on_udp_data_sent(char* data, size_t data_len, size_t data_buf_len/*for reuse inner_buffer*/, const char* ip, unsigned port)); // return whether to keep the data buffer in use. true - use again, false - default value, should free it
COM_API_DECLARE(void, on_udp_server_exit(unsigned err));
};
__declspec(novtable) struct IUdpServer : public ref_util::IRef
{
COM_API_DECLARE(int, start(unsigned short port));
COM_API_DECLARE(int, send_to(const char* buf, size_t len, const char* ip, unsigned port, bool inner_buffer = false/*whether the data buffer is returned by request_sent_buffer*/));
COM_API_DECLARE(int, broad_cast(const char* buf, size_t len, unsigned short port, bool inner_buffer = false, const char* broad_ip_seg = NULL));
COM_API_DECLARE(int, stop(void));
// for reducing the times of memory copying, request memory from inner - added on 2019-07-28
COM_API_DECLARE(char*, request_sent_buffer(size_t bytes));
COM_API_DECLARE(void, free_unsent_buffer(void* buf)); // free the returned value of request_sent_buffer which has NOT called write_2_peer with inner_buffer is 'true' yet!!!
};
typedef struct _set_cookie // all members and its' buffers will be in the same buffer with the head
{
char *name;
char *val;
char *path;
char *expire;
char *domain;
bool http_only;
bool https_only; // true - secure 1; false - secure 0
}SETCOOKIE, *LPSETCOOKIE;
enum _add_head_flag
{
ADD_HEAD_ADD = 1, // new item added if the key was not existing, or else failed
ADD_HEAD_NEW, // new item added however the key is existing already
ADD_HEAD_REPLACE, // new item added if the key was not existing, or else replace it with new val
ADD_HEAD_APPEND_COMMA, // like ADD_HEAD_REPLACE but append new val to rear with comma(,) if the key was existing
ADD_HEAD_APPEND_SEMIC, // like ADD_HEAD_REPLACE but append new val to rear with semicolon(;) if the key was existing
};
enum _cookie_index
{
COOKIE_INDEX_ALL = -1,
};
#ifdef _USE_HTTP_CALLBACK_
__declspec(novtable) struct IHttpCallback : public ref_util::IRef
{
COM_API_DECLARE(void, on_response_header_ok(int response_code, unsigned __int64 cont_len, bool cont_chunked, bool cont_zipped));
COM_API_DECLARE(int, on_response_content(const char* content, size_t len)); // return 0 to continue, other to stop
COM_API_DECLARE(int, on_url_jump(int jump_code, const char* utf8_new_url)); // return 0 to continue, other to stop
};
#endif
__declspec(novtable) struct IHttp : public ref_util::IRef // all methods are thread unsafe, all history cookies will occur in last request
{
#ifndef _USE_HTTP_CALLBACK_
COM_API_DECLARE(void, set_response_data_callback(inter_module_data::set_data setdata, void* param));
#endif
COM_API_DECLARE(int, add_header(const char* utf8_key, const char* utf8_val, _add_head_flag flag = ADD_HEAD_REPLACE)); // 0 - ok; ERROR_ALREADY_EXISTS. must call before open_url or post_data
COM_API_DECLARE(int, remove_header(const char* utf8_key/*NULL to clear all extra headers*/)); // 0 - ok; ERROR_NOT_FOUND. must call before open_url or post_data
COM_API_DECLARE(int, clear_cookie(void)); // all history cookies would be added on the last request, call this to clear all cookies
COM_API_DECLARE(int, open_url(const char* url, const char* cookie, const char* agent, bool get = true, const char* content = NULL, size_t content_len = 0));
COM_API_DECLARE(int, post_data(const char* url, const char* data, unsigned __int64 data_len, const char* utf8_file_tag, const char* utf8_file_name, const char* cookie, const char* agent));
COM_API_DECLARE(int, get_response_code(void));
COM_API_DECLARE(int, get_set_cookie(LPSETCOOKIE buf/*format: cookie1\0cookie2\0\0*/, size_t* len/*[in] - bytes of buf, [out] - string length in buf or minimum buffer size if buf was NULL*/
, int index = 0/*if index == COOKIE_INDEX_ALL, then return all cookies in ONE string and put it in buf*/)); // 0 - ok; ERROR_NOT_FOUND
COM_API_DECLARE(int, get_jump_url(char* buf, size_t* len/*[in] - bytes of buf, [out] - string length in buf or minimum buffer size if buf was NULL*/)); // 0 - ok; ERROR_NOT_FOUND
COM_API_DECLARE(int, get_response_all_header(char* buf, size_t* len/*[in] - bytes of buf, [out] - string length in buf or minimum buffer size if buf was NULL*/)); // 0 - ok; ERROR_NOT_FOUND
COM_API_DECLARE(unsigned __int64, get_response_content_length(void));
COM_API_DECLARE(enum web_format, get_content_format(void));
COM_API_DECLARE(void, close(void));
};
PORT_API(ITcpSvrSocket*) create_tcp_server_socket(IAcceptClient* ac, bool ipv6 = false);
enum _svr_ip_type
{
SVR_TYPE_NONE = 0,
SVR_TYPE_IPV4_ONLY = 1,
SVR_TYPE_IPV6_ONLY,
SVR_TYPE_IPV4_AND_IPV6,
};
PORT_API(IAsyncTcpSvr*) create_async_tcp_server(IPeerManager* peer, _svr_ip_type svr_type = SVR_TYPE_IPV4_ONLY, int buf_size_in = 0, int buf_size_out = 0, int desired_threads = 0, unsigned allow_cpu_mask = -1);
// for blocking tcp would blocks following operation, this function will set r/w timeout to be 9 seconds;
PORT_API(IBlockTcp*) connect_2_server(const char* ip, unsigned short port, unsigned conn_timeout_seconds = 0, const char* reuse_ip = NULL, unsigned reuse_port = 0);
PORT_API(IBlockTcp*) connect_2_server_by_host(const char* host, unsigned short port, unsigned conn_timeout_seconds = 0, const char* reuse_ip = NULL, unsigned reuse_port = 0);
PORT_API(IAsyncTcpHatcher*) create_async_tcp_hatcher(IAsyncTcpHandler* handler);
PORT_API(IUdpServer*) create_udp_server(IUdpSvrHandler* handler, _svr_ip_type type = SVR_TYPE_IPV4_ONLY);
#ifdef _USE_HTTP_CALLBACK_
PORT_API(IHttp*) create_http(IHttpCallback* cb);
#else
PORT_API(IHttp*) create_http(void);
#endif
// trace route by ICMPxxx function, to be completed ...
// parameter of result:
// data: ip, NULL when over
// len: milliseconds, -1 is timeout, or error code when over
// total: hops count, unused when over
// flag: DATA_FLAG_FINAL in hops, DATA_FLAG_INSTAR in beginning information, and DATA_FLAG_OVER for over
// param: 'param'
PORT_API(int) trace_route(const char* www, inter_module_data::set_data result, void* param, int max_hops = 30);
PORT_API(int) get_default_gateway(char gateway[IP_BUF_LEN]);
PORT_API(int) get_mac(const char* dot_ip, char *mac, int* mac_bytes/*in - bytes of 'mac', out - result bytes in 'mac'*/);
// enum all ips in given subnet ...
// parameter of result:
// data: ip, NULL when over
// len: bytes of 'data'
// total: unused
// flag: DATA_FLAG_FINAL
// param: same as 'param'
PORT_API(int) enum_all_ips_in_subnet(const char* dot_ip, const char* dot_subnet, inter_module_data::set_data result, void* param);
PORT_API(int) parse_cookie(const char* cookie_str, LPSETCOOKIE lpcookie, size_t size/*size of lpcookie must great than sizeof(SETCOOKIE) + lstrlenA(cookie_str) * 2*/);
PORT_API(int) cookie_for_url(LPSETCOOKIE lpcookie, const char* url, char* cookie, size_t* len);
PORT_API(int) http_post(const char* url, const char* content, size_t length, const char* utf8_file_tag, const char* utf8_file_name = NULL, const char* cookie = NULL, const char* agent = NULL);
PORT_API(int) http_download(const char* url, inter_module_data::set_data setdata, void* param, const char* cookie = NULL, const char* agent = NULL, const char* extra_data = 0, size_t extra_data_len = 0);
PORT_API(enum web_format) web_content_format(const char* web_cont, size_t bytes, UINT* cp = NULL/*to receive the code page*/);
// function: send file by 'TransmitFile' for more efficiency, the function is blocked until all content transfered or error happens if parameter 'lpovl' was NULL
// file: an openning file handle, suggest use flag with 'FILE_FLAG_SEQUENTIAL_SCAN'
// s: an connection socket
// packet_size: bytes of every packet
// lpovl: asynchronous OVERLAPPED data. if you bind the socket on an IOCP, the IOCP will receive a write complete notify
// pre: the content sent to remote before the file content
// pre_bytes: bytes of 'pre' content
// rear: the content sent to remote after all file contents transfered
// rear_bytes: bytes of 'rear' content
//
// return: error code.
PORT_API(int) transmit_file(HANDLE file, SOCKET s, size_t bytes_to_sent = 0/*max up to INT_MAX - 1*/, size_t packet_size = 4096, LPOVERLAPPED lpovl = NULL, void* pre = NULL, size_t pre_bytes = 0, void* rear = NULL, size_t rear_bytes = 0);
PORT_API(HANDLE) open_file_for_sending(const wchar_t* local_file);
enum
{
NIC_CHANGED = 0, // MibParameterNotification,
NIC_ADDED = 1, // MibAddInstance,
NIC_DELETED = 2, // MibDeleteInstance,
};
// parameter of notify:
// data: ip, this is the final ip
// len: index of network interface
// total_len: NIC_CHANGED - parameter changed; NIC_ADDED - new NIC added; NIC_DELETED - NIC deleted
// flag: be inter_module_data::DATA_FLAG_FINAL always
PORT_API(void*) reg_interface_notification(inter_module_data::set_data notify, void* param); // free the returned object by unreg_interface_notification
PORT_API(void) unreg_interface_notification(void* key/*returned by reg_interface_notification()*/);
}

View File

@ -0,0 +1,332 @@
// net_base.h : network utility
//
// Author: Gongbing
//
// Create: 2019-07-18
#pragma once
//////////////////////////////////////////////////////////////////////////////////////////
// module type and global definition
#ifndef _INCLUDED_REF_
#define _INCLUDED_REF_
#include "../ref/ref.h"
#endif
#ifndef SOCKET
#define SOCKET unsigned int
#endif
//////////////////////////////////////////////////////////////////////////////////////////
// import headers
//////////////////////////////////////////////////////////////////////////////////////////
// structures && enumerations
#define IP_BUF_LEN 48
typedef struct _ip_info
{
int index; // NIC index
char ip[IP_BUF_LEN];
char gateway[IP_BUF_LEN];
char subnet[IP_BUF_LEN];
}IPINFO, *LPIPINFO;
enum firewall_port_cat
{
FWPORT_UNKNOWN = 0,
FWPORT_TCP,
FWPORT_UDP,
FWPORT_ALL,
};
#pragma pack(push)
#pragma pack(1)
typedef struct _ip_pack
{
// all in net-sn, i.e. big-endian
unsigned long ver : 4; // version of the ip-datagram
unsigned long head_len : 4; // length in four-bytes of this head, unit as long
unsigned long service : 8; // service type ...
unsigned long total_len : 16; // total bytes of this datagram, include this header
unsigned long mark : 16;
unsigned long flag : 3;
unsigned long offset : 13; // offet of part data in whole data
unsigned long ttl : 8; // living time, as hops
unsigned long protocol : 8; // protocol type, see IPPROTO_ICMP ...
unsigned long checksum : 16; //
unsigned long src_ip;
unsigned long dst_ip;
unsigned char head_data[0];
void from_buffer(const unsigned char* buf)
{
ver = *buf >> 4;
head_len = *buf++;
service = *buf++;
total_len = *buf++;
total_len <<= 8;
total_len |= *buf++;
mark = *buf++;
mark <<= 8;
mark |= *buf++;
flag = *buf >> 5;
offset = *buf & 0x1f;
offset <<= 8;
offset |= buf[1];
buf += 2;
ttl = *buf++;
protocol = *buf++;
checksum = *buf++;
checksum <<= 8;
checksum |= *buf++;
src_ip = *buf++;
src_ip <<= 8;
src_ip |= *buf++;
src_ip <<= 8;
src_ip |= *buf++;
src_ip <<= 8;
src_ip |= *buf++;
dst_ip = *buf++;
dst_ip <<= 8;
dst_ip |= *buf++;
dst_ip <<= 8;
dst_ip |= *buf++;
dst_ip <<= 8;
dst_ip |= *buf++;
// data, you should ensure enough buffer to contains it !!!
int rest = head_len * 4 - sizeof(*this);
if (rest > 0)
memcpy(head_data, buf, rest);
}
unsigned long calc_checksum(void)
{
unsigned long chk = 0;
// 1 - fixed fields:
chk = (ver << 12) | (head_len << 8) | service;
chk += total_len;
chk += mark;
chk += (flag << 13) | offset;
chk += (ttl << 8) | protocol;
chk += src_ip & 0x0ffff;
chk += src_ip >> 16;
chk += dst_ip & 0x0ffff;
chk += dst_ip >> 16;
// 2 - appendix data in header:
unsigned short *d = (unsigned short*)head_data;
int num = (head_len * 4 - sizeof(*this)) / 2;
for (int i = 0; i < num; ++i)
chk += *d++;
// 3 - add the overflow of short
chk = (chk & 0x0ffff) + (chk >> 16);
chk = (chk & 0x0ffff) + (chk >> 16);
// 4 - NOT
checksum = ~chk;
return checksum;
}
int to_buffer(unsigned char* buf)
{
calc_checksum();
*buf++ = (ver << 4) | head_len;
*buf++ = service;
*buf++ = total_len >> 8;
*buf++ = total_len;
*buf++ = mark >> 8;
*buf++ = mark;
*buf++ = (flag << 5) | (offset >> 8);
*buf++ = offset;
*buf++ = ttl;
*buf++ = protocol;
*buf++ = checksum >> 8;
*buf++ = checksum;
*buf++ = src_ip >> 24;
*buf++ = src_ip >> 16;
*buf++ = src_ip >> 8;
*buf++ = src_ip;
*buf++ = dst_ip >> 24;
*buf++ = dst_ip >> 16;
*buf++ = dst_ip >> 8;
*buf++ = dst_ip;
int rest = head_len * 4 - sizeof(*this);
if (rest > 0)
memcpy(buf, head_data, rest);
return head_len * 4;
}
}IPPACK, *LPIPPACK;
enum _icmp_type
{
ICMP_TYPE_TERM_UNREACHABLE = 3, // the terminal is unreachable
ICMP_TYPE_RESTRICT_SOURCE,
ICMP_TYPE_MODIFY_ROUTER,
ICMP_TYPE_TIMEOUT = 11, // when ttl == 0, send back this type by router
ICMP_TYPE_INVALID_PARAMETER,
ICMP_TYPE_ECHO_ANSWER = 0, // answer for query request
ICMP_TYPE_ECHO_REQUEST = 8,
ICMP_TYPE_TIMESTAMP_REQUEST = 13,
ICMP_TYPE_TIMESTAMP_ANSWER,
};
enum _term_unrechable_code
{
TERM_UNREACHABLE_NETWORK = 0,
TERM_UNREACHABLE_TERMINAL,
TERM_UNREACHABLE_PROTOCOL,
TERM_UNREACHABLE_PORT,
TERM_UNREACHABLE_DATA_SEGMENT, // data should divided into several segments
TERM_UNREACHABLE_SOURCE_ROUTER, // source router cannot complete
TERM_UNREACHABLE_UNKNOWN_DST_NET, // destination network is unknown
TERM_UNREACHABLE_UNKNOWN_TERMINAL,
TERM_UNREACHABLE_SOURCE_DISABLED, // source host is disabled
TERM_UNREACHABLE_DISABLE_NETWORK, // disabled with network by policy
TERM_UNREACHABLE_DISABLE_TERM, // disabled with destion terminal by policy
TERM_UNREACHABLE_SERVICE_NETWORK, // network cannot support the service
TERM_UNREACHABLE_SERVICE_TERM, // destion terminal cannot support the service
TERM_UNREACHABLE_TERM_FILTER, // destion terminal has filter
TERM_UNREACHABLE_TERM_PRIORITY, // confilict with priority policy
TERM_UNREACHABLE_PRIORITY_DISABLED, //
};
enum _modi_router_code
{
MODI_ROUTER_FOR_NETWORK = 0, // modify the router-table for given network
MODI_ROUTER_FOR_TERM, // modify the router-table for given terminal
MODI_ROUTER_FOR_SERVICE_NETWORK, // modify the router-table for given network on given service
MODI_ROUTER_FOR_SERVICE_TERM, // modify the router-table for given termina on given service
};
typedef struct _icmp_pack
{
unsigned char type;
unsigned char code;
unsigned short checksum;
unsigned short mark;
unsigned short seq;
void from_buffer(const unsigned char* buf)
{
type = *buf++;
code = *buf++;
checksum = (buf[0] << 8) | buf[1];
buf += 2;
mark = (buf[0] << 8) | buf[1];
buf += 2;
seq = (buf[0] << 8) | buf[1];
}
void to_buffer(unsigned char* buf)
{
*buf++ = type;
*buf++ = code;
*buf++ = checksum >> 8;
*buf++ = checksum;
*buf++ = mark >> 8;
*buf++ = mark;
*buf++ = seq >> 8;
*buf++ = seq;
}
}ICMPPACK, *LPICMPPACK;
#pragma pack(pop)
//////////////////////////////////////////////////////////////////////////////////////////
// apis
namespace net_base_util
{
PORT_API(void) free_sock_addr(void* sockaddr);
PORT_API(void*) init_sock_addr(const char* ip, unsigned port, int* addrlen, int family = /*AF_INET*/2, int type = /*SOCK_STREAM*/1, int proto = /*IPPROTO_TCP*/6); // return sockaddr_in* type. call net_base_util::free_sock_addr to free the returned value !!!
PORT_API(void) ipv4_broadcast_address(unsigned self_ip, unsigned subnet, char ipbuf[IP_BUF_LEN]);
PORT_API(bool) ip_from_sockaddr_storage(const void/*sockaddr_storage*/* sockaddr_storage_, char ipbuf[IP_BUF_LEN], unsigned* port);
PORT_API(bool) is_ip_equal(const void/*sockaddr_storage*/* sockaddr_storage1_, const void/*sockaddr_storage*/* sockaddr_storage2_, bool compare_port = false);
// following apis return as base-socket api
PORT_API(int) init_network(unsigned min_ver = 2, unsigned max_ver = 2);
PORT_API(int) cleanup_network(void);
PORT_API(SOCKET) raw_socket(int raw_proto, bool overlapped = false, bool ipv6 = false);
PORT_API(SOCKET) tcp_socket(bool overlapped = false, bool ipv6 = false);
PORT_API(SOCKET) udp_socket(bool overlapped = false, bool ipv6 = false, bool broadcast = false);
PORT_API(int) close_socket(SOCKET s);
PORT_API(int) bind_socket(SOCKET s, bool ipv6_socket, const char* ip, unsigned port);
PORT_API(int) ip_from_domain(const char* domain, char ipbuf[IP_BUF_LEN]);
PORT_API(int) get_local_ip(LPIPINFO ips, size_t* count/*[in] - count of ips; [out] - ip numbers in ips*/);
PORT_API(int) get_ipv6_addrress(LPIPINFO ips, size_t* count/*[in] - count of ips; [out] - ip numbers in ips*/, const char* hostname = NULL/*local ipv6 when NULL*/);
PORT_API(int) set_socket_block(SOCKET s, bool blocked);
PORT_API(int) set_socket_buffer(SOCKET s, int buf_size, bool in_buf/*true for in buffer and false for out buffer*/);
PORT_API(int) set_socket_keepalive(SOCKET s, bool keep_alive);
PORT_API(int) set_socket_keepalive_detect(SOCKET s, bool detect_on, int alive_heart_milliseconds = 0, int retry_heart_milliseconds = 0);
PORT_API(int) set_socket_timeout(SOCKET s, int milliseconds = 0/*no timeout*/, bool rcv_timeout = true);
PORT_API(int) get_socket_timeout(SOCKET s, int *milliseconds, bool rcv_timeout);
PORT_API(int) set_socket_nagle(SOCKET s, bool nagle_on); // if nagle_on is true, then the packet maybe sent delayed
PORT_API(int) set_socket_ttl(SOCKET s, unsigned short ttl);
PORT_API(int) set_reused_address(SOCKET s, bool reused);
PORT_API(int) set_broadcast(SOCKET s, bool enabled);
PORT_API(int) connect_with_timeout(SOCKET s, const char* ip, unsigned port, unsigned timeout_seconds, bool return_block_socket = false);
PORT_API(SOCKET) connect_2_server(const char* ip, unsigned short port, unsigned timeout_seconds = 0/*0 to blocked*/, bool return_block_socket = false, const char* bind_ip = NULL, unsigned bind_port = 0);
// following apis return 0 for success otherwise error code
PORT_API(int) ipv4_broadcast_address(const char* self_ip, const char* subnet, char ip_buf[IP_BUF_LEN]);
PORT_API(int) get_peer_address(SOCKET s, bool remote, unsigned* port, char ip_buf[IP_BUF_LEN]);
PORT_API(int) ipv4_address(unsigned addr, char ip_buf[IP_BUF_LEN]);
PORT_API(unsigned) ipv4_address(const char* ipv4);
PORT_API(bool) is_in_same_ipv4_subnet(const char* ip1, const char* ip2, const char* subnet);
// parameters of result:
// data: (const char*)adapter_name
// data_len: (const char*)adapter_description
// total_len: IPINFO*
// flag: inter_module_data::DATA_FLAG_FINAL
// param: the same as 'param'
PORT_API(int) enum_network_adapters(inter_module_data::set_data result, void* param);
// parameters of result:
// data: (const char*)local address
// data_len: (const char*)remote address
// total_len: HIDWORD = state, LODWORD = owning pid
// flag: inter_module_data::DATA_FLAG_FINAL
// param: the same as 'param'
PORT_API(int) enum_sockets(bool tcp, inter_module_data::set_data result, void* param);
// trace route by raw socket with ICMP
// parameter of result:
// data: ip, NULL when over
// len: milliseconds, -1 is timeout, or error code when over
// total: hops count, unused when over
// flag: DATA_FLAG_FINAL in hops, DATA_FLAG_INSTAR in beginning information, and DATA_FLAG_OVER for over
// param: 'param'
// PORT_API(int) trace_route(const char* www, inter_module_data::set_data result, void* param, int max_hops = 30); // commented, use net_app::trace_route
PORT_API(unsigned) proto_default_port(const char* proto);
// function: get the next hop, generally as gateway
// for_ip: in multi-network-card, get the the next hop for given ip, if was NULL, return the first
PORT_API(int) get_next_hop(char next_hop[IP_BUF_LEN], const char* for_ip = NULL);
// Note: the buffer length of proto(proto_buf_len) must be double of url!!! for host and page would use the buffer
// and need not free host and page
PORT_API(bool) parse_url(const char* url, char* proto, size_t proto_buf_len, char** host, char** page, unsigned* port, bool* port_from_host = NULL);
PORT_API(bool) parse_url(const wchar_t* url, wchar_t* proto, size_t proto_buf_len, wchar_t** host, wchar_t** page, unsigned* port, bool* port_from_host = NULL);
PORT_API(unsigned short) calculate_ip_datagram_checksum(const unsigned char* buf, int bytes, bool* ok = NULL);
PORT_API(unsigned short) calculate_icmp_checksum(LPICMPPACK pack, int bytes, bool* ok = NULL);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// windows firewall
PORT_API(bool) firewall_is_on(void);
PORT_API(bool) firewall_is_app_enabled(const wchar_t* app_pe_name);
PORT_API(bool) firewall_is_port_enabled(unsigned port, firewall_port_cat fpc);
PORT_API(int) firewall_turn_on(void);
PORT_API(int) firewall_turn_off(void);
PORT_API(int) firewall_enable_app(const wchar_t* name/*display name in firewall*/, const wchar_t* pe/*pe-image file name*/, bool enable);
PORT_API(int) firewall_enable_port(unsigned port, firewall_port_cat fpc, bool enable, const wchar_t* name/*display name in firewall*/ = NULL);
}

View File

@ -0,0 +1,223 @@
// process_util.h : include utilities for manage folders
//
// Author: Gongbing
//
// Date: 2016-09-25
#pragma once
#include <string>
#include <vector>
#ifndef _INCLUDED_REF_
#define _INCLUDED_REF_
#include "../ref/ref.h"
#endif
// hook utils
namespace pe_util
{
__declspec(novtable) struct IObscurityCall : public ref_util::IRef
{
// params must not be NULL but the API was no parameter
COM_API_DECLARE(long, invoke(void** params, int* ret_val = NULL)); // return error code
};
#pragma pack(push)
#pragma pack(1)
typedef struct _hook_instruction_info
{
// e.g. in instruction 'E912345678', then bytes = 5, rel_addr_off = 1, rel_addr_size = 4
unsigned long bytes : 6; // all bytes in this instruction
unsigned long far_bytes : 3; // the far jumping instruction bytes if this was a near jumping instruction
unsigned long rel_addr_off : 3; // relative address offset to instruction in this
unsigned long rel_addr_size : 3; // relative address size of this instruction, ZERO is none
unsigned char far_instruction[8]; // far jumping instruction, relative address size always be 4 bytes (int)
unsigned long far_adden; // the jumping offset should added this value for converting near jumping to far jumping
}HOOKII, *LPHOOKII;
typedef struct _group_icon_entry
{
unsigned char width;
unsigned char height;
unsigned char color_count;
unsigned char reserved;
unsigned short planes;
unsigned short bits_per_pixel;
unsigned long bytes;
unsigned short id;
}GROUPICONENTRY, *LPGROUPICONENTRY;
typedef struct _group_icon // for RT_GROUP_ICON
{
unsigned short reserved;
unsigned short res_type; // 1 for icon
unsigned short entries;
GROUPICONENTRY entry[1];
}GROUPICON, *LPGROUPICON;
#pragma pack(pop)
PORT_API(LPVOID) allocate_code_buffer(size_t size);
PORT_API(void) free_code_buffer(LPVOID code_buf);
PORT_API(int) get_min_code_buffer_bytes(void);
// function: calculate hooking info at hook_addr
// hook_addr: the address will be hooked
// lphii: the hooking instruction info, at least 6 elements
// size: [in] - count of lphii, [out] - valid elements in lphii
// bytes: to receive the minimum bytes to be moved for hooking
// return: error code
PORT_API(int) calculate_hook_bytes(const BYTE* hook_addr, LPHOOKII lphii, int* size, int* bytes);
PORT_API(LPVOID) move_src_code_for_hook(LPVOID src_code, LPHOOKII lphii, int count, LPVOID given_buf = NULL, int bytes = 0);
// hook_addr: the instruction address which you should hooking at
// new_addr: your hooking codes which would jump from hood_addr
// origin_code: to receive origin codes at hook_addr. or the given address for hook junk if was not NULL, then the moved_bytes contains the size of the buffer when in
// moved_bytes: to receive copied bytes from hook_addr. it can contains the origin_code buffer bytes if origin_code is not NULL
PORT_API(int) hook_at(DWORD_PTR hook_addr, FARPROC new_addr, DWORD_PTR *origin_code, int *moved_bytes);
PORT_API(int) hook_at(const char* module_name, const char* api, FARPROC new_addr, DWORD_PTR *origin_code, int *moved_bytes, int api_offset = 0);
PORT_API(int) hook_with_shellcode(DWORD_PTR hook_addr, unsigned char* shellcodes, size_t shell_codes_bytes); // // RVA in shellcodes will not be handled !!!
PORT_API(int) unhook_at(DWORD_PTR unhook_addr, DWORD_PTR* origin_code, int bytes_moved);
PORT_API(int) unhook_at(const char* module_name, const char* api, DWORD_PTR *origin_code, int bytes_moved, int api_offset = 0);
// hook_bef: call method must be '__stdcall', and the parameters are pointers that points to the parameter of the origin api
// hook_after: call method must be '__stdcall', and the first parameter is the return value of origin api whenever the origin api return value or not
// and following the parameters is the same as origin api
//
// e.g. system api: HANDLE WINAPI CreateFileW(_In_ LPCWSTR lpFileName,
// _In_ DWORD dwDesiredAccess, _In_ DWORD dwShareMode,
// _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
// _In_ DWORD dwCreationDisposition, _In_ DWORD dwFlagsAndAttributes,
// _In_opt_ HANDLE hTemplateFile);
// hook_bef: void __stdcall hook_bef(LPCWSTR* lpFileName,
// DWORD* dwDesiredAccess, DWORD* dwShareMode,
// LPSECURITY_ATTRIBUTES* lpSecurityAttributes,
// DWORD* dwCreationDisposition, DWORD* dwFlagsAndAttributes,
// HANDLE* hTemplateFile
// void* user_data);
// or can be void __stdcall hook_bef(void* user_data) if no_param_for_hook_before was true;
//
// hook_after: void __stdcall hook_after(HANDLE* ret, LPCWSTR lpFileName,
// DWORD dwDesiredAccess, DWORD dwShareMode,
// LPSECURITY_ATTRIBUTES lpSecurityAttributes,
// DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
// HANDLE hTemplateFile
// void* user_data);
//
//
PORT_API(void*) any_hook_at(FARPROC api, size_t param_count, bool stdcall, FARPROC hook_bef = NULL, bool hook_bef_without_param = false, FARPROC hook_after = NULL, void* user_data = NULL);
PORT_API(void) free_any_hook(void* any_hook);
PORT_API(IObscurityCall*) create_obscurity_caller(const wchar_t* module, const char* api, int api_params, bool stdcall);
PORT_API(IObscurityCall*) create_obscurity_caller(HMODULE module, const char* api, int api_params, bool stdcall);
// pe parsing ...
enum pe_address_type
{
PE_ADDR_RELATIVE_TO_FILE = 0,
PE_ADDR_RELATIVE_TO_MEM,
PE_ADDR_ABSOLUTE_ON_DEFAULT_BASE,
};
__declspec(novtable) struct IPe : public ref_util::IRef
{
// params must not be NULL but the API was no parameter
COM_API_DECLARE(long, load_pe(const wchar_t* path_pe)); // return error code
COM_API_DECLARE(long, close(void)); // return error code, owner MUST call this before 'release' when you never use this !!!
COM_API_DECLARE(long, attach(unsigned char* buf, UINT64 bytes)); // return error code
COM_API_DECLARE(long, detach(unsigned char** buf)); // return error code
// cb: data - (const char*)dll_name if flag was DATA_FLAG_FINAL or (const char*)err_msg if flag was DATA_FLAG_ERROR
// or "IAT" if flag was DATA_FLAG_INSTAR
// len - (const char*)api_name
// or IAT sector info(void*[2]) if flag was DATA_FLAG_INSTAR: [0] - (char*)section name, [1] - (UINT64) offset to file
// total - UINT64[2]: [0] - hint, [2] - offset in file(EAT only), [1] - offset in mem set to be '0' if 'only_dll' was true if flag was DATA_FLAG_FINAL or unused if flag was DATA_FLAG_ERROR
// or IAT table info(UINT64[3]) if flag was DATA_FLAG_INSTAR: [0] - offset to file, [1] - offset in memory, [2] - table bytes
// flag - DATA_FLAG_FINAL or DATA_FLAG_INSTAR or DATA_FLAG_ERROR
//
// param - same as the paramenter you passed 'param'
//
// return non 'SET_RESULT_CONTINUE' to stop working
COM_API_DECLARE(long, dump_iat(INTER_MODULE_CALLBACK_VAR(cb), void* param, bool only_dll = false));
COM_API_DECLARE(long, dump_eat(INTER_MODULE_CALLBACK_VAR(cb), void* param));
// cb: data - (const char*)section name
//
// len - bytes of section name
//
// total - UINT64 pos[3]: pos[0] - offset in file, pos[1] - offset in memory, pos[2] - section size in bytes
//
// flag - DATA_FLAG_FINAL
//
// param - same as the paramenter you passed 'param'
COM_API_DECLARE(long, dump_sections(INTER_MODULE_CALLBACK_VAR(cb), void* param));
// cb: data - (const char*)resource name
//
// len - UINT64[2]: [0] - bytes of resource; [1] - (void*)resource_data
//
// total - UINT64[4]: [0] - id; [1] - memory offset; [2] - file offset, [3] - codepage
//
// flag - DATA_FLAG_FINAL
//
// param - same as the paramenter you passed 'param'
COM_API_DECLARE(long, dump_resources(INTER_MODULE_CALLBACK_VAR(cb), void* param));
// function: convert RVA between memory offset and file offset
//
// parameter: from - source address;
//
// to - to receive the target address
//
// off2rva - true: file offset to memory offset; false: memory offset to file offset
COM_API_DECLARE(long, rva(UINT64 from, UINT64* to, bool off2rva));
// cb: data - (const char*)assembly
//
// len - bytes of assembly
//
// total - UINT[2]: 0 - offset in file of the code, 1 - offset in memory of the assembly
//
// flag - DATA_FLAG_FINAL
//
// param - same as the paramenter you passed 'param'
COM_API_DECLARE(long, find_address_ref(UINT64 addr, INTER_MODULE_CALLBACK_VAR(cb), void* param, short addr_bytes = 4));
COM_API_DECLARE(long, find_iat_ref(const char* dll_name, const char* api_name/*consider as hint if less than 0x10000*/, INTER_MODULE_CALLBACK_VAR(cb), void* param));
COM_API_DECLARE(long, find_string_ref(const char* str, INTER_MODULE_CALLBACK_VAR(cb), void* param));
COM_API_DECLARE(long, find_string_ref(const wchar_t* str, INTER_MODULE_CALLBACK_VAR(cb), void* param));
// function: un-assembly given function begin from 'addr' and ENDING at instruction 'ret' or 'cb' return SET_RESULT_STOP
//
// parameter: addr - given address
//
// addr_type - how to use the address 'addr'
//
// cb - data: (const char*) assembly
// len: bytes of data
// total: UINT64[4]: 0 - file offset; 1 - instruction absolute address; 2 - bytes; [3] - (unsigned char*) codes
// flag: DATA_FLAG_FINAL
// param: same as the paramenter you passed 'param'
// return SET_RESULT_CONTINUE to work until 'ret', or SET_RESULT_STOP to stop immediately
//
// param - parameter for 'cb'
//
// img_base - specify the image base. use default base if it was '0'
COM_API_DECLARE(long, un_assembly(UINT64 addr, enum pe_address_type addr_type, INTER_MODULE_CALLBACK_VAR(cb), void* param, UINT64 img_base = 0));
COM_API_DECLARE(long, un_assembly(const char* export_api_name, INTER_MODULE_CALLBACK_VAR(cb), void* param));
// function: to change content at given file offset
//
// cb - data: (const wchar_t*) target file after changed
// len: bytes of data
// total: unused
// flag: DATA_FLAG_FINAL
// param: same as the parameter you passed 'param'
// return: omitted
COM_API_DECLARE(long, change(UINT64 file_off, const unsigned char* data, size_t bytes, INTER_MODULE_CALLBACK_VAR(cb), void* param));
COM_API_DECLARE(bool, is_pe_64(void)); // whether the PE is a 64-bits module
COM_API_DECLARE(long, get_entry_point(UINT64* off)); // get offset of entry-point in memory
COM_API_DECLARE(long, get_image_base_addr(UINT64* addr)); // get offset of entry-point in memory
COM_API_DECLARE(long, get_file_time(UINT64* file_time)); // get file compiled time
};
PORT_API(IPe*) create_pe_parser(void);
};

View File

@ -0,0 +1,171 @@
// process_util.h : include utilities for manage folders
//
// Author: Gongbing
//
// Date: 2016-09-25
#pragma once
#include <string>
#include <vector>
#ifndef _INCLUDED_REF_
#define _INCLUDED_REF_
#include "../ref/ref.h"
#endif
#define STATUS_SUCCESS 0x00000000
#define STATUS_BUFFER_OVERFLOW 0x80000005
#define STATUS_INFO_LENGTH_MISMATCH 0xC0000004
// process utils
namespace process_util
{
PORT_API(int) start_program(const wchar_t* prog_file, const wchar_t* param, bool show_wnd, DWORD* pid = NULL, bool as_admin = false, const wchar_t* path_dll = NULL);
PORT_API(bool) is_me_in_admin(void);
PORT_API(int) try_me_in_admin(bool show_wnd, DWORD *pid = NULL, const wchar_t* append_param = NULL);
PORT_API(int) start_program_as_current_user(const wchar_t* prog_file, const wchar_t* param, bool show_wnd, unsigned* proc_id = NULL, bool merge_pe_2_param = true, const wchar_t* path_dll = NULL);
PORT_API(bool) start_program_by_cmd(const wchar_t* prog_file, const wchar_t* param);
PORT_API(bool) query_acting_user_token(HANDLE* aut);
PORT_API(int) enable_privilege(const wchar_t* privilege_name, bool enabled);
PORT_API(bool) kill_process_by_name(const wchar_t* proc_name, const wchar_t* taskkill_path = NULL);
PORT_API(bool) is_process_living(const wchar_t* proc_name, DWORD* pid = NULL);
// parameter of result:
// data: (wchar_t*)pe_path_file
// len: process id
// total: parent process id
PORT_API(void) enum_processes(inter_module_data::set_data result, void* param);
// parameter of result:
// data: (wchar_t*)module path file
// len: base address
// total: module size
PORT_API(void) enum_modules(DWORD proc_id, inter_module_data::set_data result, void* param);
PORT_API(bool) module_pe_from_run_address(void* addr, wchar_t path_name[MAX_PATH], void** base_addr = NULL);
PORT_API(int) find_resource(HINSTANCE inst, const wchar_t* res_type, UINT res_id, inter_module_data::set_data result, void* param);
PORT_API(bool) is_pe_checksum_ok(const wchar_t* pe_path_file, DWORD* lppe_chksum = NULL, DWORD* lpfile_chksum = NULL);
PORT_API(bool) get_module_info(HMODULE module, void** base, void** entry, size_t* size);
PORT_API(bool) get_process_time(DWORD proc_id, LPFILETIME start = NULL, LPFILETIME kern = NULL, LPFILETIME user = NULL);
PORT_API(DWORD) get_parent_process(DWORD proc_id);
PORT_API(int) get_process_name(DWORD proc_id, wchar_t path_name[MAX_PATH]);
PORT_API(int) get_self_pathname(wchar_t path_name[MAX_PATH], bool call_module = false/*default to get exe pathname*/);
PORT_API(void) quit_and_delete_self(void);
PORT_API(char*) set_command_lineA(char* cmda); // the return buffer need not free
PORT_API(wchar_t*) set_command_lineW(wchar_t* cmda, bool is_setpeb); // the return buffer need not free
PORT_API(void) set_peb_command_lineW(wchar_t* cmda);
PORT_API(HANDLE) get_file_handle_by_name(const wchar_t* filename, ULONG *pid = NULL);
PORT_API(BOOL) is_wow64_process(DWORD proc_id);
PORT_API(HMODULE) load_system_dll(const wchar_t* dll);
PORT_API(void*) write_to_process(HANDLE proc, const void* src, int bytes);
PORT_API(void*) write_to_process(DWORD proc_id, const void* src, int bytes);
PORT_API(int) read_process_memory(DWORD proc_id, void* base_addr, int read_bytes, unsigned char* buf); // read proc_id [base_addr, base_addr] contents into buf, return error code, 0 is success
// function: create a remote thread in given process
// proc_id: the target process ID
// code_bytes: remote thread code size in bytes
// susbend: whether to supspend this thread when create it
// parameter_size: remote thread parameter size
// tid: to receive the remote thread id
// thread: to receive the remote thread handle
// fill: to fill the thread code and parameter in this callback
// data: unused, always be NULL
// len: (LPVOID), the memory address in process proc_id
// total: (unsigned char*), to receive the content
// flag: write code when DATA_FLAG_REMOTE_THREAD_INSTRUCT, or parameter when DATA_FLAG_REMOTE_THREAD_PARAMETER if parameter_bytes was great than ZERO
// param: the same as 'param'
// param: parameter 'param' of callback fill
// return: error code, 0 is success
PORT_API(int) create_remote_thread(DWORD proc_id, int code_bytes, inter_module_data::set_data fill, void* param, bool suspend = false
, int parameter_bytes = 0, DWORD* tid = NULL, HANDLE* thread = NULL);
// code and param: [in] - the source code or parameter buffer; [out] - remote code or parameter buffer
PORT_API(int) create_remote_thread(DWORD proc_id, const unsigned char **code, int code_bytes, bool suspend = false
, const unsigned char** param = NULL, int param_bytes = 0, DWORD* tid = NULL, HANDLE* thread = NULL);
PORT_API(bool) get_api_in_process(DWORD proc_id, const wchar_t* dll, const char* apis/*GetTickCount\0CreateFileW\0\0*/, FARPROC* api_addrs/*length as same as apis*/);
PORT_API(HMODULE) load_dll_in_process(DWORD proc_id, const wchar_t* path_dll); // return the loaded dll handle in the process
PORT_API(HMODULE) free_dll_in_process(DWORD proc_id, const wchar_t* path_dll); // return the dll in the process
enum _inst_statu
{
INST_STATU_FIRST = 0, // 0 - I am the FIRST instance
INST_STATU_FAILED_CREATE, // 1 - no instance existing and failed to create the singleton instance
INST_STATU_INFO_FIRST, // 2 - an instance is already existing and informed my parameter
INST_STATU_FAILED_INFO_FIRST, // 3 - an instance is already existing and failed in informing my parameter
INST_STATU_ID_USED, // 4 - the name is used by other object
INST_STATU_UNKNOWN = 10, // unknown error
};
__declspec(novtable) struct ISingleton : public ref_util::IRef
{
COM_API_DECLARE(_inst_statu, statu(void));
COM_API_DECLARE(bool, set_max_run_seconds(DWORD seconds = -1)); // quit after seconds when not -1
};
__declspec(novtable) struct ICmd : public ref_util::IRef
{
COM_API_DECLARE(void, reset(const wchar_t* cmdline = NULL)); // reset command line string, use GetCommandLineW if cmd_line was NULL
COM_API_DECLARE(long, count(void)); // return parameter count, if has key-val pair, then count them as 2
// function: whether the command line has 'param'
// case_sens: is case sensitive
// ind: to receive the index in command line if has
COM_API_DECLARE(bool, has(const wchar_t* param, bool case_sens = false, int *ind = NULL));
COM_API_DECLARE(bool, is_first_main_pe(void)); // return whether the first parameter is main-pe
COM_API_DECLARE(const wchar_t*, parameter(int index)); // ZERO-based index, should not free the return buffer but use it immediately
// key: the key for the parameter
// case_sens: whether the 'key' is case sensitive
// return: return im.exe of key '/im' in "taskkill /f /im im.exe", should not free but use it immediately
COM_API_DECLARE(const wchar_t*, parameter(const wchar_t* key, bool case_sens = false));
COM_API_DECLARE(const wchar_t*, main_pe(void)); // DO NOT free the return buffer but use it immediately
COM_API_DECLARE(int, add(const wchar_t* param, bool case_sens = false, int index = -1));
COM_API_DECLARE(int, add(const wchar_t* key, const wchar_t* val, bool case_sens = false, int index = -1));
// if as_key was true, then remove param and the next item to it
COM_API_DECLARE(int, remove(const wchar_t* param, bool case_sens = false, bool as_key = false));
COM_API_DECLARE(int, remove(int index));
// function: convert to a command line string
// buf: to receive the string, can be NULL
// len: [in] - count of buf, [out] - content length in buf, if buf was NULL or len is small, then contains the minimum length and return ERROR_INSUFFICIENT_BUFFER
// return: ERROR_SUCCESS if buf is length enough, or ERROR_INSUFFICIENT_BUFFER if len was less than required,
COM_API_DECLARE(int, to_command_line(wchar_t* buf, int* len));
// data: (const wchar_t*)
// len: bytes of 'data'
// total: unused, be ZERO
// flag: inter_module_data::DATA_FLAG_FINAL
// param: same as 'user'
COM_API_DECLARE(int, to_command_line(INTER_MODULE_CALLBACK_VAR(got_result), void* user));
};
PORT_API(long) invoke_api(FARPROC func, bool stdcall_, int param_count, void** params, int* ret_val = NULL);
PORT_API(long) invoke_api(const wchar_t* path_module, const char* api, bool stdcall_, int param_count, void** params, int* ret_val = NULL);
// parameter of result:
// data: (const wchar_t*)command line
// len: length of (const wchar_t*)data
// total: as same as len
// flag: DATA_FLAG_FINAL in commonplace, or DATA_FLAG_UNKNOWN to quit
// param: like 'param'
PORT_API(ISingleton*) create_singleton(const wchar_t* inst_id, inter_module_data::set_data result, void* param);
PORT_API(ICmd*) create_command_line(const wchar_t* cmd = NULL);
enum _console_attr
{
CA_FOREGROUND_BLUE = FOREGROUND_BLUE,
CA_FOREGROUND_GREEN = FOREGROUND_GREEN,
CA_FOREGROUND_RED = FOREGROUND_RED,
CA_FOREGROUND_INTENSITY = FOREGROUND_INTENSITY,
CA_BACKGROUND_BLUE = BACKGROUND_BLUE,
CA_BACKGROUND_GREEN = BACKGROUND_GREEN,
CA_BACKGROUND_RED = BACKGROUND_RED,
CA_BACKGROUND_INTENSITY = BACKGROUND_INTENSITY,
};
PORT_API(WORD) set_console_attribute(WORD attr);
PORT_API(ICmd*) from_console(const wchar_t* tips = L"input");
PORT_API(ICmd*) from_console(const char* tips = "input");
}

View File

@ -0,0 +1,126 @@
// un_asm.h : include utilities for unassembly
//
// Author: Gongbing
//
// Date: 2020-03-19
#pragma once
#ifndef _INCLUDED_REF_
#define _INCLUDED_REF_
#include "../ref/ref.h"
#endif
namespace ia_asm
{
// unassembly utils
enum ia_arch
{
IA_ARCHITECTURE_32 = 1,
IA_ARCHITECTURE_64,
};
const UINT64 REGISTER_BMP_RAX = (UINT64)1 << 0; const UINT64 REGISTER_BMP_EAX = (UINT64)1 << 0;
const UINT64 REGISTER_BMP_RCX = (UINT64)1 << 1; const UINT64 REGISTER_BMP_ECX = (UINT64)1 << 1;
const UINT64 REGISTER_BMP_RDX = (UINT64)1 << 2; const UINT64 REGISTER_BMP_EDX = (UINT64)1 << 2;
const UINT64 REGISTER_BMP_RBX = (UINT64)1 << 3; const UINT64 REGISTER_BMP_EBX = (UINT64)1 << 3;
const UINT64 REGISTER_BMP_RSP = (UINT64)1 << 4; const UINT64 REGISTER_BMP_ESP = (UINT64)1 << 4;
const UINT64 REGISTER_BMP_RBP = (UINT64)1 << 5; const UINT64 REGISTER_BMP_EBP = (UINT64)1 << 5;
const UINT64 REGISTER_BMP_RSI = (UINT64)1 << 6; const UINT64 REGISTER_BMP_ESI = (UINT64)1 << 6;
const UINT64 REGISTER_BMP_RDI = (UINT64)1 << 7; const UINT64 REGISTER_BMP_EDI = (UINT64)1 << 7;
const UINT64 REGISTER_BMP_R08 = (UINT64)1 << 8;
const UINT64 REGISTER_BMP_R09 = (UINT64)1 << 9;
const UINT64 REGISTER_BMP_R10 = (UINT64)1 << 10;
const UINT64 REGISTER_BMP_R11 = (UINT64)1 << 11;
const UINT64 REGISTER_BMP_R12 = (UINT64)1 << 12;
const UINT64 REGISTER_BMP_R13 = (UINT64)1 << 13;
const UINT64 REGISTER_BMP_R14 = (UINT64)1 << 14;
const UINT64 REGISTER_BMP_R15 = (UINT64)1 << 15;
const UINT64 REGISTER_BMP_MM0 = (UINT64)1 << 16;
const UINT64 REGISTER_BMP_MM1 = (UINT64)1 << 17;
const UINT64 REGISTER_BMP_MM2 = (UINT64)1 << 18;
const UINT64 REGISTER_BMP_MM3 = (UINT64)1 << 19;
const UINT64 REGISTER_BMP_MM4 = (UINT64)1 << 20;
const UINT64 REGISTER_BMP_MM5 = (UINT64)1 << 21;
const UINT64 REGISTER_BMP_MM6 = (UINT64)1 << 22;
const UINT64 REGISTER_BMP_MM7 = (UINT64)1 << 23;
const UINT64 REGISTER_BMP_XMM0 = (UINT64)1 << 24;
const UINT64 REGISTER_BMP_XMM1 = (UINT64)1 << 25;
const UINT64 REGISTER_BMP_XMM2 = (UINT64)1 << 26;
const UINT64 REGISTER_BMP_XMM3 = (UINT64)1 << 27;
const UINT64 REGISTER_BMP_XMM4 = (UINT64)1 << 28;
const UINT64 REGISTER_BMP_XMM5 = (UINT64)1 << 29;
const UINT64 REGISTER_BMP_XMM6 = (UINT64)1 << 30;
const UINT64 REGISTER_BMP_XMM7 = (UINT64)1 << 31;
const UINT64 REGISTER_BMP_FLAG = (UINT64)1 << 32;
#pragma pack(push)
#pragma pack(1)
typedef struct _instruction_data
{
unsigned long long address; // instruction address
unsigned long bytes; // all bytes of this instruction
unsigned long cycle; // cpu cycle
UINT64 reg_chg_bmp; // changed register bit-map mask
struct _rel_addr
{
union
{
unsigned char rel_byte;
struct
{
unsigned char offset : 5; // the offest to codes[0] of the relative address, ZERO means no
unsigned char size : 3; // bytes of the relative address, ZERO means no
};
};
}rel_addr[4]; // relative address in this instruction, max up to 4
struct
{
unsigned char bytes[4]; // bytes for val, ZERO means no imm val, often be 1, 2, 4, 8
UINT64 val[4]; // imm value
}imm;
char codes[20]; // instruction code bytes
char assembly[84]; // instruction text
struct _instruction_data()
{
clear();
}
void clear(void)
{
memset(this, 0, sizeof(struct _instruction_data));
}
void copy(struct _instruction_data* r)
{
memcpy(this, r, sizeof(struct _instruction_data));
}
}INSTRUCTION, *LPINSTRUCTION;
#pragma pack(pop)
// function: to un-assembly the codes
//
// return: error codes, ZERO is success
PORT_API(int) unasm(const unsigned char* codes // code stream
, LPINSTRUCTION lpasm // to receive the assembly text
, unsigned long long address = 0 // instruction address, use address 'codes' if this was ZERO
, ia_arch ia32 = IA_ARCHITECTURE_32); // intel architecture
// function: to convert near instruction to far instruction
//
// return: ZERO - have far instruction; 1 - no far instruction
PORT_API(int) far_instruction(const LPINSTRUCTION near
, LPINSTRUCTION far // to receive the far instruction
, unsigned long long far_instruction_addr = 0 // the address of the far instruction, use near's address if was ZERO
, ia_arch ia32 = IA_ARCHITECTURE_32); // intel architecture);
// function: compile single instruction
//
// return: error codes, ZERO is success
PORT_API(int) compile(const char* assembly // assembly text such as 'mov eax, ebp'
, unsigned long long *address // [in] - address of this assembly, [out] - address of the next statement, commonly [in] add lpasm->bytes
, LPINSTRUCTION lpasm // instruction array to receive the result
, inter_module_data::set_data label // label callback. see DATA_FLAG_UNASM_SET_LABEL && DATA_FLAG_UNASM_GET_LABEL
, ia_arch ia32 = IA_ARCHITECTURE_32); // assembly architecture
PORT_API(int) compile_one(const char* assembly
, unsigned char *code // minimum length with 40 bytes. [bytes]codes[bytes]codes[0]
, unsigned long long address = 0);
}

208
sln/sdk/include/ref/ref.h Normal file
View File

@ -0,0 +1,208 @@
// ref.h : the base utility for life-cycle control by reference
//
// Author: Gongbing
//
// Create: 2017-05-20
#pragma once
#ifdef _AS_DLL_
#ifdef _NET_EXPORTS_
#define PORT_API(ret) __declspec(dllexport) ret __stdcall
#define PORT_API_CALL(ret, call_) __declspec(dllexport) ret call_
#else
#define PORT_API(ret) __declspec(dllimport) ret __stdcall
#define PORT_API_CALL(ret, call_) __declspec(dllimport) ret call_
#ifdef _DEBUG
#pragma comment(lib, "./Debug/base_util.lib")
#else
#pragma comment(lib, "./Release/base_util.lib")
#endif
#endif
#else
#define PORT_API(ret) ret __stdcall
#define PORT_API_CALL(ret, call_) ret call_
#ifndef _BASE_EXPORTS_
#ifdef _DEBUG
#pragma comment(lib, "base_util.lib")
#else
#pragma comment(lib, "base_util.lib")
#endif
#endif
#endif
//#define STRUCT_ALIGN(bytes) \
// #pragma pack(push) \
// #pragma pack(bytes)
//#define STRUCT_ALIGN_END \
// #pragma pack(pop)
#define COM_API_DECLARE(ret, decl) virtual ret __stdcall decl = 0
#define COM_API_DECLARE_NON_PURE(ret, decl) virtual ret __stdcall decl
#define COM_API_OVERRIDE(ret, decl) virtual ret __stdcall decl override
#define COM_API_IMPLEMENT(cls, ret, decl) ret __stdcall cls##::decl
#define ALIGN_MEMORY(n, align) ((n + align - 1) / (align) * (align))
#define _TO_UNICODE_(str) L##str
#define UNICODE_STR(str) _TO_UNICODE_(str)
// refferer simulating-COM
namespace ref_util
{
//
// rule:
//
// if a member of container owns the container pointer, the member should release the container pointer
// in an explicit function like 'stop'; the container could release the member pointer in destructor!!!
//
__declspec(novtable) struct IRef
{
COM_API_DECLARE(long, add_ref(void));
COM_API_DECLARE(long, release(void));
};
class refer : public IRef
{
volatile long m_ref;
public:
refer() : m_ref(1)
{}
protected:
virtual ~refer()
{}
public:
COM_API_OVERRIDE(long, add_ref(void))
{
return InterlockedIncrement(&m_ref);
}
COM_API_OVERRIDE(long, release(void))
{
long ref = InterlockedDecrement(&m_ref);
if (ref <= 0) delete this;
return ref;
}
};
template<class T>
class auto_pointer
{
T* m_ptr;
public:
auto_pointer() : m_ptr(NULL)
{}
auto_pointer(T* ptr) : m_ptr(ptr)
{}
auto_pointer(const auto_pointer& r)
{
m_ptr = r.m_ptr;
if (m_ptr) m_ptr->add_ref();
}
~auto_pointer()
{
if (m_ptr) m_ptr->release();
}
public:
auto_pointer& operator=(T* ptr)
{
if (m_ptr) m_ptr->release();
m_ptr = ptr;
return *this;
}
auto_pointer& operator=(const auto_pointer& r)
{
if (m_ptr) m_ptr->release();
m_ptr = r.m_ptr;
if (m_ptr) m_ptr->add_ref();
return *this;
}
T* ptr(void)
{
return m_ptr;
}
T* operator->(void)
{
return m_ptr;
}
bool is_empty(void)
{
return m_ptr == NULL;
}
};
}
#define IMPL_REF_BY_REFER() \
COM_API_OVERRIDE(long, add_ref(void)) \
{ \
return ref_util::refer::add_ref(); \
} \
COM_API_OVERRIDE(long, release(void)) \
{ \
return ref_util::refer::release(); \
}
// inter-module data
namespace inter_module_data
{
enum data_flag
{
// commonly
DATA_FLAG_UNKNOWN = 0,
DATA_FLAG_ERROR, // the parameter 'len' is contains the error code, total is extension info for 'len'
DATA_FLAG_FINAL, // data is final result for the api which you called
DATA_FLAG_INSTAR, // data is instar for your api, and finally will notified with flag DATA_TYPE_FINAL
DATA_FLAG_OVER, // all data has been transfered, parameter data, len and total are all invalid
DATA_FLAG_GET_VAL, // (const wchar_t*)data, 'len' is bytes of data, 'total' is set_data
// call (set_data)total(const wchar_t* data, bytes of 'data', 0, DATA_FLAG_FINAL, param)
DATA_FLAG_DEBUG_INFO,
// for http data
DATA_FLAG_HTTP_HEAD = 100, // http(s) response head
DATA_FLAG_302, // 301 or 302 to new url, the data contains the url. in this case, return SET_RESULT_CONTINUE to jump, SET_RESULT_DISCARD to stop jumping
// for remote thread
DATA_FLAG_REMOTE_THREAD_INSTRUCT = 200, // to fill the remote thread code in given address
DATA_FLAG_REMOTE_THREAD_PARAMETER, // to fill the remote thread parameter in given address
// the parameter data, len and total will be all set to ZERO if unused
DATA_FALG_SVC_ENTER = 300, // service callback, called when initailizing, parameter 'data' is pointing to proc_util::ICmd*
DATA_FALG_SVC_TIMER, // service callback, called when timer is set, parameter 'len' is the count base from ZERO
DATA_FALG_SVC_CONTROL, // service callback, called when service control is invoked, parameter 'len' is the control code
DATA_FALG_SVC_EXIT, // service callback, called when service exiting
// for un-assembly
DATA_FLAG_UNASM_SET_LABEL = 1000, // set the label address, data is label, len is address, other has no mean
DATA_FLAG_UNASM_GET_LABEL, // query the label address. data is label, param is a pointer points to the UINT64 variable to receive the address
};
// return true to continue, false to stop
enum set_result
{
SET_RESULT_CONTINUE = ERROR_SUCCESS, // continue doing the task of the calling api
SET_RESULT_UNKNOWN = -100, // omit this value
SET_RESULT_DISCARD, // discard this data handling. i.e. it will stop jump to new url if flag is DATA_FLAG_302
SET_RESULT_STOP, // this will stop all operations of the api you calling
};
// real usage of these parameters, see the API which use this callback ...
typedef set_result(__stdcall* set_data)(const char* data // data buffer
, UINT64 len // bytes of data in data-buffer or error code if flag was DATA_FLAG_ERROR
, UINT64 total // total bytes of the data for the api which you called
, data_flag flag // data flag
, void* param); // user defined data, and passing it when call the callback
}
#define INTER_MODULE_CALLBACK(name) \
inter_module_data::set_result __stdcall name(const char* data, UINT64 len, UINT64 total, inter_module_data::data_flag flag, void* param)
#define INTER_MODULE_CALLBACK_VAR(name) \
inter_module_data::set_result (__stdcall *name)(const char* data, UINT64 len, UINT64 total, inter_module_data::data_flag flag, void* param)

View File

@ -0,0 +1,242 @@
// utility for registery operation
//
// Date: 2019-10-30
//
#pragma once
#ifndef _INCLUDED_REF_
#define _INCLUDED_REF_
#include "../ref/ref.h"
#endif
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// export interface for other modules on 2017-08-23 by GB
namespace sys_util
{
/////////////////////////////////////////////////////////////////////////////////////////////
// registry utilities ...
enum _wow_type
{
WOW_TYPE_DEFAULT = 0, // both given path and the Wow6432Node path in 32-bits app
WOW_TYPE_32_BITS, // the same as WOW_TYPE_DEFAULT in 32-bits app
WOW_TYPE_64_BITS, // no affect on registry in 32-bits app
};
// if parameter 'temporary' is true, then the key you created would lost after the system restart !!!
PORT_API(long) reg_create_key(const wchar_t* path, HKEY* ret = NULL, HKEY root = HKEY_LOCAL_MACHINE, _wow_type type = WOW_TYPE_DEFAULT, bool temporary = false);
PORT_API(long) reg_close_key(HKEY key);
PORT_API(long) reg_remove_key(const wchar_t* path, HKEY root = HKEY_LOCAL_MACHINE, _wow_type type = WOW_TYPE_DEFAULT);
PORT_API(long) reg_remove_value(const wchar_t* path, const wchar_t* val_name, HKEY root = HKEY_LOCAL_MACHINE, _wow_type type = WOW_TYPE_DEFAULT);
// parameter of cb
// data: (const wchar_t*)
// len: bytes of data
// total: unused
// flag: inter_module_data::DATA_FLAG_FINAL
// param: the same as the parameter 'param'
//
// return: error code
PORT_API(long) reg_get_string(HKEY root, const wchar_t* path, const wchar_t* name, inter_module_data::set_data cb, void* param, _wow_type type = WOW_TYPE_DEFAULT);
PORT_API(long) reg_get_binary(HKEY root, const wchar_t* path, const wchar_t* name, inter_module_data::set_data cb, void* param, _wow_type type = WOW_TYPE_DEFAULT);
PORT_API(long) reg_get_integer(HKEY root, const wchar_t* path, const wchar_t* name, int* val, _wow_type type = WOW_TYPE_DEFAULT);
PORT_API(long) reg_get_integer(HKEY root, const wchar_t* path, const wchar_t* name, unsigned long long* val, _wow_type type = WOW_TYPE_DEFAULT);
// parameter of cb
// data: (const wchar_t*)key_name
// len: (const wchar_t*)path
// total: unused
// flag: inter_module_data::DATA_FLAG_FINAL
// param: the same as the parameter 'param'
//
// return: error code
PORT_API(long) reg_enum_key(HKEY root, const wchar_t* path, inter_module_data::set_data cb, void* param, _wow_type type = WOW_TYPE_DEFAULT);
// parameter of cb
// data: (const wchar_t*) reg_value name
// len: (HIDWORD): type - REG_SZ, (wchar_t*)total; REG_DWORD/REG_QWORD, (DWORD/UINT64)total; REG_BINARY, (unsigned char*)total
// (LODWORD): bytes of data
// total: value
// flag: inter_module_data::DATA_FLAG_FINAL
// param: the same as the parameter 'param'
//
// return: error code
PORT_API(long) reg_enum_value(HKEY root, const wchar_t* path, inter_module_data::set_data cb, void* param, _wow_type type = WOW_TYPE_DEFAULT);
// function: set string value
// val: can be multi-string fromat such as "123\0456\0789\0\0", in this circumstance, caller must provides val_bytes
// val_bytes: length of val, in bytes. will consider as single string if it was 0
//
// NOTE: this api would not support REG_EXPAND_SZ that with unexpanded string such as %systemroot%
PORT_API(long) reg_set_string(HKEY root, const wchar_t* path, const wchar_t* name, const wchar_t* val, int val_bytes = 0, _wow_type type = WOW_TYPE_DEFAULT);
PORT_API(long) reg_set_integer(HKEY root, const wchar_t* path, const wchar_t* name, unsigned val, _wow_type type = WOW_TYPE_DEFAULT);
PORT_API(long) reg_set_integer(HKEY root, const wchar_t* path, const wchar_t* name, unsigned long long val, _wow_type type = WOW_TYPE_DEFAULT);
PORT_API(long) reg_set_binary(HKEY root, const wchar_t* path, const wchar_t* name, unsigned char* val, int val_bytes, _wow_type type = WOW_TYPE_DEFAULT);
// function: to find the default opener of given file type
// file_ext: the extension name of the file, such as ".txt", lead with '.'
// cb: data - (const wchar_t*)path_opener
PORT_API(long) reg_get_file_opener(const wchar_t* file_ext/*.txt*/, inter_module_data::set_data cb, void* param);
// function: enumerate installed service
// cb: data - (const wchar_t*) reg_service name
// len - (const wchar_t*) reg_service path file
// total - (const wchar_t*) reg_service description
// flag - inter_module_data::DATA_FLAG_FINAL
PORT_API(long) reg_enum_service(inter_module_data::set_data cb, void* param);
// function: enumerate the auto starting program when system power on
// cb: data - (const wchar_t*) reg_program name
// len - (const wchar_t*) reg_program path file
// total - (const wchar_t*) reg_startup parameter
// flag - inter_module_data::DATA_FLAG_FINAL
PORT_API(long) reg_enum_program_on_system_poweron(inter_module_data::set_data cb, void* param);
PORT_API(long) reg_remove_program_on_system_poweron(const wchar_t* name); // the name should be the same as in enum_program_on_system_poweron
// function: enumerate installed service
// cb: data - (const wchar_t*) reg_software display name
// len - (const wchar_t*) reg_uninstaller path file
// total - (const wchar_t*) reg_publisher
// flag - inter_module_data::DATA_FLAG_FINAL
PORT_API(long) reg_enum_uninstaller(inter_module_data::set_data cb, void* param);
PORT_API(long) reg_reg_uninstaller(const wchar_t* app_name, const wchar_t* display_name, const wchar_t* uninstall_pe, const wchar_t* uninstall_param = NULL
, const wchar_t* publisher = NULL, const wchar_t* version = NULL, unsigned size_in_bytes = 0, _wow_type type = WOW_TYPE_DEFAULT);
PORT_API(long) reg_del_uninstaller(const wchar_t* app_name, _wow_type type = WOW_TYPE_DEFAULT);
/////////////////////////////////////////////////////////////////////////////////////////////
// wmi utilities ...
// initialize a WMI object, use wmi_free to free the returned object
PORT_API(void*) wmi_initialize(void);
// because WMI is query system database, so consider it as registry and provides here ...
// function: query system configuration through by WMI
// win32_cls: the class name like Win32_xxxx, e.g. "Win32_NetworkAdapterConfiguration"
// attr_name: the attribute name in the win32_cls, e.g. "IPAddress" of "Win32_NetworkAdapterConfiguration"
// cb: data - value depends on len, see comments of parameter 'len'
// len - value type: VT_BSTR(const wchar_t*), VT_I1~8(char*, short*, int*, longlong*), VT_R4/8(float*, double*), VT_BOOL(bool*)
// total - unused
// flag - inter_module_data::DATA_FLAG_INSTAR in enumeration, and inter_module_data::DATA_FLAG_FINAL at over, then the data is invalid
// param - the same as parameter 'param'
PORT_API(HRESULT) wmi_query(const wchar_t* win32_cls, const wchar_t* attr_name, inter_module_data::set_data cb, void* param, void* wmi = NULL/*returned by wmi_initialize*/);
PORT_API(void) wmi_free(void* wmi/*returned by wmi_initialize*/);
/////////////////////////////////////////////////////////////////////////////////////////////
// service utilities ...
enum _svc_state
{
SVC_STATE_UNKNOWN = 0,
SVC_STATE_STOPPED,
SVC_STATE_STARTING,
SVC_STATE_STOPPING,
SVC_STATE_RUNNING,
SVC_STATE_RESUMING,
SVC_STATE_PAUSING,
SVC_STATE_PAUSED,
};
PORT_API(long) svc_install(const wchar_t* svc_file, const wchar_t* svc_name, const wchar_t* svc_desc, const wchar_t* display_name = NULL);
PORT_API(long) svc_uninstall(const wchar_t* svc_name);
PORT_API(long) svc_start(const wchar_t* svc_name, DWORD wait_running_timeout = 0/*milliseconds*/);
PORT_API(long) svc_pause(const wchar_t* svc_name);
PORT_API(long) svc_resume(const wchar_t* svc_name);
PORT_API(long) svc_enable(const wchar_t* svc_name, bool enable);
PORT_API(long) svc_stop(const wchar_t* svc_name, DWORD wait_stopped_timeout = 0/*milliseconds*/);
PORT_API(long) svc_change_pe_file(const wchar_t* svc_name, const wchar_t* to_pe_file);
PORT_API(long) svc_change_description(const wchar_t* svc_name, const wchar_t* description);
PORT_API(bool) svc_is_running(const wchar_t* svc_name);
PORT_API(long) svc_pe_file(const wchar_t* svc_name, inter_module_data::set_data cb, void* param); // NOTE: DLL service will return "%system%\svchost.exe -k name" !!!
// function: handle the service common command, supporting following commands:
// --install: install self, or other service if with "-pe given service file" parameter
// --uninstall: uninstall self
// --restart: restart self
// --start: start self
// --stop: stop self
// --pause: pause self
// --resume: resume self
//
// return: whether handled the command
//
// NOTE: this API's codes must be in the service module; if with parameter "-pe given service file" then all operation are both on the given service
PORT_API(bool) svc_handle_common_command(const wchar_t* svc_name, const wchar_t* svc_desc, long* err);
// function: service enter, call this in main() for exe service.... support --install, --uninstall and --restart startup parameter
// parameter of cb: see the comment of DATA_FALG_SVC_xxx
PORT_API(long) start_as_service(const wchar_t* svc_name, const wchar_t* svc_desc, inter_module_data::set_data cb, void* param, DWORD timer_elapse = 0/*millisecond*/);
/////////////////////////////////////////////////////////////////////////////////////////////
// shortcut utilities ...
//
// lnk_file: the file which with '.lnk' extension name
// target_file: the final file linked by lnk_file
//
PORT_API(HRESULT) link_create(const wchar_t* lnk_file, const wchar_t* target_file, const wchar_t* start_arguments
, const wchar_t* icon_path_file = NULL, int icon_index = 0, const wchar_t* lnk_desc = NULL);
// icon_index: change the icon in target file of icon index; or not change the icon if it was -1, you can call link_change_icon to change it later
PORT_API(HRESULT) link_change_target_file(const wchar_t* lnk_file, const wchar_t* target_file, int icon_index = 0);
PORT_API(HRESULT) link_change_icon(const wchar_t* lnk_file, const wchar_t* file_ico, int index = 0);
PORT_API(HRESULT) link_change_startup_arguments(const wchar_t* lnk_file, const wchar_t* start_arguments);
PORT_API(HRESULT) link_change_description(const wchar_t* lnk_file, const wchar_t* description);
PORT_API(long) link_pin_to_taskbar(const wchar_t* lnk_file, bool pin = true);
// flag: DATA_FLAG_INSTAR for startup arguments, DATA_FLAG_FINAL for the target pe file
PORT_API(HRESULT) link_get_target_file(const wchar_t* lnk_file, inter_module_data::set_data cb, void* param);
///////////////////////////////////////////////////////////////////////////////////////
// hardware info
enum cpu_cache_type
{
CPU_CACHE_NULL = 0, // 0 = Null - No more caches.
CPU_CACHE_DATA, // 1 = Data Cache.
CPU_CACHE_INSTRUCTION, // 2 = Instruction Cache.
CPU_CACHE_UNIFIED, // 3 = Unified Cache.
CPU_CACHE_COUNT,
};
typedef struct _cpu_cache
{
cpu_cache_type type;
int level;
UINT64 bytes;
}CPUCACHE, *LPCPUCACHE;
typedef struct _cpu_info
{
int max_cpuid;
int cores;
int speed_base; // in MHz, 0 - not got; < 0 is unreliable
int speed_max; // in MHz, 0 - not got; < 0 is unreliable
char *manufactor;
char *product;
int cache_num;
CPUCACHE caches[4];
}CPUINFO, *LPCPUINFO;
typedef struct _bios_info
{
char *base_board_manufactor;
char *base_board_product_name;
char *base_board_version;
char *bios_vendor;
char *bios_version;
char *bios_release_date;
char bios_major_release;
char bios_minor_release;
char controller_major_release;
char controller_minor_release;
}BIOSINFO, *LPBIOSINFO;
// result: data - LPCPUINFO
// len - error code, 0 is success
// total - unused, always be ZERO
// flag - DATA_FLAG_FINAL
// param - same as the parameter 'param'
PORT_API(bool) get_cpu_info(inter_module_data::set_data result, void* param);
// result: data - LPBIOSINFO
// len - error code, 0 is success
// total - unused, always be ZERO
// flag - DATA_FLAG_FINAL
// param - same as the parameter 'param'
PORT_API(bool) get_bios_info(inter_module_data::set_data result, void* param);
};

View File

@ -0,0 +1,224 @@
// thread.h : the base utility for thread pool management
//
// Author: Gongbing
//
// Create: 2017-05-20
#pragma once
#ifndef _INCLUDED_REF_
#define _INCLUDED_REF_
#include "../ref/ref.h"
#endif
#pragma warning(disable: 4996)
////////////////////////////////////////////////////////////////////////////////////////////
// thread ...
//
// purpose: if you CreateThrad and TerminateThread then, the new thread maybe occupying the global
// RTL_CRITICAL_SECTION variable in ntdll.dll module. In this situation, all threads that
// created by CreateThread will no longer have opportunity to run!!!
// This class is providing you to TerminateThread safely
namespace thread_util
{
enum _io_direction
{
IO_WRITE = 1,
IO_READ,
IO_CONTROL,
IO_USER_TYPE_BASE = 10,
};
#pragma pack(push)
#pragma pack(1)
typedef struct _ovl_extension : OVERLAPPED
{
int io_direction; // _io_direction
size_t buf_len; // bytes of payload buffer
size_t data_len; // valid bytes of payload
size_t io_pos; // current IO position
char payload[8]; // payload data buffer
char* user_payload(void)
{
return payload;
}
}OVLEX, *LPOVLEX;
#pragma pack(pop)
__declspec(novtable) struct ILock : public ref_util::IRef
{
COM_API_DECLARE(void, lock(void));
COM_API_DECLARE(bool, try_lock(void));
COM_API_DECLARE(void, unlock(void));
};
__declspec(novtable) struct IThreadWorker : public ref_util::IRef
{
COM_API_DECLARE(void*/*void* tls*/, thread_enter(void)); // you can initialize tls in this method
COM_API_DECLARE(void, thread_work(void*/*bind data*/ task_key, LPOVLEX task_data, unsigned data_size, DWORD err_code, void* enter_data));
COM_API_DECLARE(void, thread_exit(void* enter_data/*tls*/));
};
__declspec(novtable) struct IThreadPool : public ref_util::IRef
{
COM_API_DECLARE(long, add_task(void* task_key, void* task_data, unsigned data_size)); // return 0 when success
COM_API_DECLARE(long, stop(void));
COM_API_DECLARE(long, worker_threads(void));
COM_API_DECLARE(long, busy_threads(void));
COM_API_DECLARE(long, waiting_task(void));
};
__declspec(novtable) struct IEventDispatchThreadPool : public IThreadPool // dispach thread pool through by hardware-event mechanism
{
COM_API_DECLARE(long, bind_object(void* object, void* bind_key));
COM_API_DECLARE(long, remove_object(void* object, void* bind_key));
};
class simple_lock
{
ILock *lck_;
public:
simple_lock(ILock* lck)
{
lck_ = lck;
if (lck_)
{
//lck_->add_ref();
lck_->lock();
}
}
~simple_lock()
{
if (lck_)
{
lck_->unlock();
//lck_->release();
}
}
};
// for reducing the times of memory copying, request memory from inner - added on 2019-07-28
PORT_API(LPOVLEX) inner_buffer_to_OVLEX_head(void* buf/*'buf' is returned by request_inner_buffer*/);
PORT_API(char*) request_inner_buffer(size_t bytes);
PORT_API(void) free_inner_buffer(void* buf); // free the buffer returned by 'request_inner_buffer'
PORT_API(void) free_inner_buffer(LPOVLEX buf); // free the buffer returned by 'request_inner_buffer'
PORT_API(HANDLE) create_thread(unsigned(__stdcall* thread)(void*), void* param, bool suspend = false, unsigned allow_cpu_mask = -1); // return thread id
PORT_API(ILock*) create_lock(void);
PORT_API(IThreadPool*) create_thread_pool(IThreadWorker* worker, int desired_threads = 0, unsigned cpu_allow_mask = -1);
PORT_API(IEventDispatchThreadPool*) create_event_thread_pool(IThreadWorker* worker, int desired_threads = 0, unsigned cpu_allow_mask = -1);
// parameter of result:
// data: (wchar_t*)thread name, maybe null
// len: thread id
// total: start address
PORT_API(void) enum_threads(DWORD proc_id, inter_module_data::set_data result, void* param);
PORT_API(LPVOID) get_thread_start_address(DWORD thread_id);
PORT_API(DWORD) get_call_stack(DWORD ebp, DWORD *stack/*caller allocate the buffer*/, int depth = 6, void* ensure_module = NULL/*ensure the module which contains the address ensure_module in the stack, omit if stack_data was valid*/
, unsigned char* stack_data = NULL, int stack_bytes = 0); // return depth in stack
PORT_API(DWORD) get_thread_call_stack(DWORD thread_id, DWORD *stack/*caller allocate the buffer*/, int depth = 6, void* ensure_module = NULL/*ensure the module which contains the address ensure_module in the stack*/); // return depth in stack
PORT_API(void) set_thread_name(DWORD thread_id, const char* thread_name);
// the parameter 'allow_cpu_mask' is is a bit vector in which each bit represents the processors that a thread is allowed to run on
// 1 represent CPU0, 5 represent CPU0 and CPU2, and so on...
enum _ict_state
{
ICT_STATE_NONE = 0,
ICT_STATE_START_FAIL,
ICT_STATE_RUNNING,
ICT_STATE_COMPLETE,
};
template<class T> // NOTE: class T must derived from ref_util::IRef !!!
class invoke_class_thread : public ref_util::refer
{
void(__stdcall T::* handle_func)(void*);
void *param_; // dynamic parameter should free in handle_func !!!
T *obj_;
HANDLE wait_;
HANDLE thread_;
unsigned thread_id_;
unsigned affinity_mask_;
_ict_state state_;
unsigned start_tick_; // elapse milliseconds if state_ == ICT_STATE_COMPLETE, start time tick counts in others
public:
invoke_class_thread(T* obj, void(__stdcall T::* thread_func)(void*), void* param, unsigned allow_cpu_mask = -1) : state_(ICT_STATE_NONE), start_tick_(0)
{
if (obj) obj->add_ref();
obj_ = obj;
param_ = param;
handle_func = thread_func;
wait_ = CreateEvent(NULL, TRUE, FALSE, NULL);
thread_ = thread_util::create_thread(invoke_thread, this, false, allow_cpu_mask);
if (thread_ == NULL) state_ = ICT_STATE_START_FAIL;
else
{
thread_id_ = GetThreadId(thread_);
WaitForSingleObject(wait_, INFINITE);
}
CloseHandle(wait_);
wait_ = NULL;
}
protected:
~invoke_class_thread()
{
if (thread_) CloseHandle(thread_);
if (obj_) obj_->release();
}
private:
static unsigned WINAPI invoke_thread(void* lp)
{
invoke_class_thread *obj = (invoke_class_thread*)lp;
obj->add_ref();
obj->state_ = ICT_STATE_RUNNING;
obj->start_tick_ = GetTickCount();
SetEvent(obj->wait_);
(obj->obj_->*obj->handle_func)(obj->param_);
obj->state_ = ICT_STATE_COMPLETE;
obj->start_tick_ = GetTickCount() - obj->start_tick_;
obj->release();
return 0;
}
public:
unsigned thread_id(void)
{
return thread_id_;
}
HANDLE thread(bool take = false)
{
HANDLE h = thread_;
if (take)
thread_ = NULL;
return h;
}
enum _ict_state thread_state(void)
{
return state_;
}
unsigned start_tick_count(bool elapse = false)
{
return elapse && state_ != ICT_STATE_COMPLETE ? GetTickCount() - start_tick_ : start_tick_;
}
int terminate(int reason = 0)
{
HANDLE h = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id_);
int err = GetLastError();
if (h)
{
err = TerminateThread(h, reason) ? ERROR_SUCCESS : GetLastError();
CloseHandle(h);
}
return err;
}
};
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,152 @@
// zip_util.h : include utilities for manage zip/unzip
//
// Author: Gongbing
//
// Date: 2016-09-25
#pragma once
#ifndef _INCLUDED_REF_
#define _INCLUDED_REF_
#include "../ref/ref.h"
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
#pragma pack(push)
#pragma pack(1)
typedef struct zip_local_file_header
{
unsigned signature; // 0x04034B50
unsigned short ver;
unsigned short flag;
unsigned short compression;
unsigned short last_modify_time;
unsigned short last_modify_date;
unsigned crc;
unsigned compressed_size;
unsigned uncompressed_size;
unsigned short name_len;
unsigned short ext_len;
char name[0];
char* extension()
{
char *ext = NULL;
if (ext_len)
{
ext = (char*)this;
ext += sizeof(struct zip_local_file_header);
ext += name_len;
}
return ext;
}
}ZIPLFH, *LPZIPLFH;
typedef struct zip_centeral_file_header
{
unsigned signature; // 0x02014B50
unsigned short ver_zip;
unsigned short ver_unzip;
unsigned short flag;
unsigned short compression;
unsigned short last_modify_time;
unsigned short last_modify_date;
unsigned crc;
unsigned compressed_size;
unsigned uncompressed_size;
unsigned short name_len;
unsigned short ext_len;
unsigned short comment_len;
unsigned short start_disk_number;
unsigned short inter_file_attr;
unsigned outer_file_attr;
unsigned lfh_rva;
char file_name[0]; // follwing by extra & comment
}ZIPCFH, *LPZIPCFH;
#pragma pack(pop)
namespace zip_util
{
__declspec(novtable) struct IUnzipPack : public ref_util::IRef
{
// open a local packet file
COM_API_DECLARE(int, open(const wchar_t* path_file, const char* pwd = NULL));
// open a memory packet content
COM_API_DECLARE(int, open(void* data, size_t len, const char* pwd = NULL));
// files: to receive all items include folder
// folders: to receive folders in this packet
// total_size: to receive every file size(exclude folder)
// return: result statu code, ERROR_SUCCESS or other error code
COM_API_DECLARE(int, get_files(int *files, int* folders, UINT64* total_size));
// index: ZERO-based index in this packet
// size: to receive the item bytes data in returned buffer
// name: to receive the item name, maybe with relative path. call free_zip_buffer to free it
// cont: to receive the content, call free_zip_buffer to free it
// attr: to receive the item attribute
// create_time: to receive the item created time
// modi_time: to receive the item last modified time
// acc_time: to receive the item last accessed time
COM_API_DECLARE(int, get_item(int index, DWORD* attr, wchar_t** name = NULL, char** cont = NULL, UINT64* size = NULL
, FILETIME* create_time = NULL, FILETIME* modi_time = NULL, FILETIME* acc_time = NULL));
// Function: unzip this packet to an existing local directory. caller should ensure the path local_dir is existing already
// prog: data - points to a wchar_t* buffer contains the current file path
// len - current file bytes of data if flag was DATA_FLAG_FINAL, when flag is DATA_FLAG_ERROR then contains error:
// ERROR_ALREADY_EXISTS, return SET_RESULT_DISCARD to reserve the file; SET_RESULT_CONTINUE to overwrite
// ERROR_CREATE_FAILED, create local file failed, parameter 'total' is GetLastError
// ERROR_DATA_CHECKSUM_ERROR, unzip the file failed, the (wchar_t*)data is unreliable
// total- all data bytes to be unzipped
// flag - be DATA_FLAG_FINAL always in normal or DATA_FLAG_ERROR if error occurs
// param- be prog_param always
COM_API_DECLARE(int, unzip_to(const wchar_t* local_dir, inter_module_data::set_data prog, void* prog_param));
COM_API_DECLARE(int, close(void));
};
__declspec(novtable) struct IZipPack : public ref_util::IRef
{
// add a local file or directory into the packet, rel_path is relative to the packet
// rel_path: relative to the packet, only file name if NULL. e.g. 'first\\data.txt' or 'data.txt'
COM_API_DECLARE(int, add_local_file(const wchar_t* path_file, const wchar_t* rel_path = NULL));
// add memory data into the packet, rel_path_name is relative to the packet
// rel_path_name: e.g. 'first\\data.txt' or 'data.txt'
COM_API_DECLARE(int, add_data(void* data, size_t len, const wchar_t* rel_path_name));
// add a folder into the packet, only folder, no data. path is relative to the packet
// add local directory into the packet, use add_local_file
// folder_rel_path_name: e.g. 'folder' or 'top\\folder'
COM_API_DECLARE(int, add_folder(const wchar_t* folder_rel_path_name));
// if you create a memory packet, this will return the start buffer and data length.
// the buffer 'data' is caller passed in
COM_API_DECLARE(int, get_memory_data(void** data, UINT64* len));
COM_API_DECLARE(int, close(void));
};
// Function: zip data into stream which leading by 0x1f, 0x8b, ...
// data: should be zipped data
// len: bytes of data
// return: error code
PORT_API(int) gzip_zip(const char* data, ULONGLONG len, inter_module_data::set_data result, void* result_param);
// Function: unzip the gzip data which leading by 0x1f, 0x8b, ...
// data: should be unzipped data
// len: bytes of data
// return: error code
PORT_API(int) gzip_unzip(const char* data, ULONGLONG len, inter_module_data::set_data result, void* result_param);
PORT_API(IZipPack*) create_zip_file(const wchar_t* local_file, const char* pwd = NULL);
PORT_API(IZipPack*) create_zip_memory(void* buf, UINT64 len, const char* pwd = NULL);
PORT_API(IUnzipPack*) open_zip(const wchar_t* local_file, const char* pwd = NULL);
PORT_API(IUnzipPack*) open_zip(void* buf, UINT64 len, const char* pwd = NULL);
};

Binary file not shown.

Binary file not shown.

View File

@ -4,11 +4,11 @@
//
//
// #define OEM_HANWANG
#define OEM_NONE
#define VERSION_MAIN 4
#define VERSION_SUB 1007
#define VERSION_SUB 1015
#define VERSION_BUILD 2022
#define VERSION_PATCH 6271
#define VERSION_PATCH 7061
#define TO_STR(a) #a
#define TO_VER_STR(vs) TO_STR(v##vs)
@ -24,18 +24,24 @@
#ifdef OEM_HANWANG
#define OEM_NAME L"\u6C49\u738B\u79D1\u6280\u80A1\u4EFD\u6709\u9650\u516C\u53F8"
#define OEM_SHORT_NAME L"\u6c49\u738b"
#define FULL_NAME(a) FINAL_STR(HANVONSCAN\x20, a, \x20TWAIN)
#define PRODUCT_VID 0x2903
#define PRODUCT_VENDOR "Hanvon"
#elif defined(OEM_LISICHENG)
#define OEM_NAME L"\u5317\u4EAC\u7ACB\u601D\u8FB0\u8BA1\u7B97\u673A\u6280\u672F\u6709\u9650\u516C\u53F8"
#define OEM_SHORT_NAME L"\u7acb\u601d\u8fb0"
#define FULL_NAME(a) FINAL_STR(LANXUMSCAN\x20, a, \x20TWAIN)
#define PRODUCT_VID 0x31c9
#define PRODUCT_VENDOR "Lanxum"
#else
#define OEM_NAME L"\u5B81\u6CE2\u534E\u9AD8\u4FE1\u606F\u79D1\u6280\u6709\u9650\u516C\u53F8"
#define OEM_SHORT_NAME L"\u534e\u9ad8"
#define FULL_NAME(a) FINAL_STR(HUAGOSCAN\x20, a, \x20TWAIN)
#define PRODUCT_VID 0x3072
#define PRODUCT_VENDOR "HUAGO"