Update Shell

This commit is contained in:
Bruce
2025-11-26 07:44:51 +08:00
parent ae3771bfdb
commit a70b0547bd
45 changed files with 5781 additions and 253 deletions
+2 -2
View File
@@ -10,10 +10,10 @@ BOOL APIENTRY DllMain( HMODULE hModule,
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
CoInitializeEx (NULL, COINIT_MULTITHREADED); break;
// CoInitializeEx (NULL, COINIT_MULTITHREADED); break;
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
CoUninitialize ();
// CoUninitialize ();
break;
}
return TRUE;
+871
View File
@@ -0,0 +1,871 @@
#pragma once
#include <Windows.h>
#include <string>
#include <algorithm>
#include <shlwapi.h>
#include <vector>
#include <iomanip>
#include <functional>
#include <sstream>
#include "strcmp.h"
#include "version.h"
#include "module.h"
typedef version S_VERSION;
template <typename T> constexpr T Max (T l, T r) { return l > r ? l : r; }
template <typename T> constexpr T Max (T l, T m, T r) { return Max (Max (l, r), m); }
template <typename T> constexpr T Max (T l, T ml, T mr, T r) { return Max (Max (l, ml), Max (mr, r)); }
template <typename CharT> std::basic_string <CharT> replace_substring
(
const std::basic_string <CharT> &str,
const std::basic_string <CharT> &from,
const std::basic_string <CharT> &to
)
{
if (from.empty ()) return str;
std::basic_string <CharT> result;
size_t pos = 0;
size_t start_pos;
while ((start_pos = str.find (from, pos)) != std::basic_string<CharT>::npos)
{
result.append (str, pos, start_pos - pos);
result.append (to);
pos = start_pos + from.length ();
}
result.append (str, pos, str.length () - pos);
return result;
}
std::string GetProgramRootDirectoryA (HMODULE hModule hModule_DefaultParam)
{
char path [MAX_PATH];
if (GetModuleFileNameA (hModule, path, MAX_PATH))
{
std::string dir (path);
size_t pos = dir.find_last_of ("\\/");
if (pos != std::string::npos)
{
dir = dir.substr (0, pos);
}
return dir;
}
return "";
}
std::wstring GetProgramRootDirectoryW (HMODULE hModule hModule_DefaultParam)
{
wchar_t path [MAX_PATH];
if (GetModuleFileNameW (hModule, path, MAX_PATH))
{
std::wstring dir (path);
size_t pos = dir.find_last_of (L"\\/");
if (pos != std::wstring::npos)
{
dir = dir.substr (0, pos);
}
return dir;
}
return L"";
}
std::string EnsureTrailingSlash (const std::string &path)
{
if (path.empty ()) return path; // 空路径直接返回
char lastChar = path.back ();
if (lastChar == '\\' || lastChar == '/')
return path; // 已有分隔符,直接返回
// 根据系统或原路径格式添加适当的分隔符
char separator = (path.find ('/') != std::string::npos) ? '/' : '\\';
return path + separator;
}
std::wstring EnsureTrailingSlash (const std::wstring &path)
{
if (path.empty ()) return path;
wchar_t lastChar = path.back ();
if (lastChar == L'\\' || lastChar == L'/')
return path;
wchar_t separator = (path.find (L'/') != std::wstring::npos) ? L'/' : L'\\';
return path + separator;
}
bool IsFileExistsW (LPCWSTR filename)
{
DWORD dwAttrib = GetFileAttributesW (filename);
return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
bool IsFileExistsA (LPCSTR filename)
{
DWORD dwAttrib = GetFileAttributesA (filename);
return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
bool IsFileExists (LPWSTR filePath) { return IsFileExistsW (filePath); }
bool IsFileExists (LPCSTR filePath) { return IsFileExistsA (filePath); }
bool IsFileExists (const std::string &filePath) { return IsFileExistsA (filePath.c_str ()); }
bool IsFileExists (const std::wstring &filePath) { return IsFileExistsW (filePath.c_str ()); }
bool IsDirectoryExistsA (LPCSTR path)
{
DWORD attributes = GetFileAttributesA (path);
return (attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY));
}
bool IsDirectoryExistsW (LPCWSTR path)
{
DWORD attributes = GetFileAttributesW (path);
return (attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY));
}
bool IsDirectoryExists (const std::string &path) { return IsDirectoryExistsA (path.c_str ()); }
bool IsDirectoryExists (const std::wstring &path) { return IsDirectoryExistsW (path.c_str ()); }
bool IsDirectoryExists (LPCSTR path) { return IsDirectoryExistsA (path); }
bool IsDirectoryExists (LPCWSTR path) { return IsDirectoryExistsW (path); }
bool IsPathExistsW (LPCWSTR filename)
{
DWORD dwAttrib = GetFileAttributesW (filename);
return (dwAttrib != INVALID_FILE_ATTRIBUTES);
}
bool IsPathExistsA (LPCSTR filename)
{
DWORD dwAttrib = GetFileAttributesA (filename);
return (dwAttrib != INVALID_FILE_ATTRIBUTES);
}
bool IsPathExists (const std::string &path) { return IsPathExistsA (path.c_str ()); }
bool IsPathExists (const std::wstring &path) { return IsPathExistsW (path.c_str ()); }
bool IsPathExists (LPCSTR path) { return IsPathExistsA (path); }
bool IsPathExists (LPCWSTR path) { return IsPathExistsW (path); }
std::string NormalizePath (const std::string &path)
{
if (!path.empty () && path.back () == '\\')
return path.substr (0, path.size () - 1);
return path.c_str ();
}
std::wstring NormalizePath (const std::wstring &path)
{
if (!path.empty () && path.back () == L'\\')
return path.substr (0, path.size () - 1);
return path.c_str ();
}
std::vector <std::string> EnumSubdirectories (const std::string &directory, bool includeParentPath)
{
std::vector<std::string> subdirs;
std::string normPath = NormalizePath (directory);
std::string searchPath = normPath + "\\*";
WIN32_FIND_DATAA findData;
HANDLE hFind = FindFirstFileA (searchPath.c_str (), &findData);
if (hFind == INVALID_HANDLE_VALUE) return subdirs;
do
{
// 过滤 "." 和 ".."
if (strcmp (findData.cFileName, ".") == 0 || strcmp (findData.cFileName, "..") == 0)
continue;
// 判断是否为目录
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (includeParentPath)
subdirs.push_back (normPath + "\\" + findData.cFileName);
else
subdirs.push_back (findData.cFileName);
}
} while (FindNextFileA (hFind, &findData));
FindClose (hFind);
return subdirs;
}
std::vector <std::wstring> EnumSubdirectories (const std::wstring &directory, bool includeParentPath)
{
std::vector<std::wstring> subdirs;
std::wstring normPath = NormalizePath (directory);
std::wstring searchPath = normPath + L"\\*";
WIN32_FIND_DATAW findData;
HANDLE hFind = FindFirstFileW (searchPath.c_str (), &findData);
if (hFind == INVALID_HANDLE_VALUE) return subdirs;
do
{
if (wcscmp (findData.cFileName, L".") == 0 || wcscmp (findData.cFileName, L"..") == 0)
continue;
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (includeParentPath)
subdirs.push_back (normPath + L"\\" + findData.cFileName);
else
subdirs.push_back (findData.cFileName);
}
} while (FindNextFileW (hFind, &findData));
FindClose (hFind);
return subdirs;
}
std::string GetCurrentProgramPathA (HMODULE hModule hModule_DefaultParam)
{
std::vector <CHAR> buf (Max <size_t> (MAX_PATH, GetModuleFileNameA (hModule, nullptr, 0)) + 1);
GetModuleFileNameA (hModule, buf.data (), buf.capacity ());
return buf.data ();
}
std::wstring GetCurrentProgramPathW (HMODULE hModule hModule_DefaultParam)
{
std::vector <WCHAR> buf (Max <size_t> (MAX_PATH, GetModuleFileNameW (hModule, nullptr, 0)) + 1);
GetModuleFileNameW (hModule, buf.data (), buf.capacity ());
return buf.data ();
}
std::string GetCurrentProgramNameA (HMODULE hModule hModule_DefaultParam) { return PathFindFileNameA (GetCurrentProgramPathA (hModule).c_str ()); }
std::wstring GetCurrentProgramNameW (HMODULE hModule hModule_DefaultParam) { return PathFindFileNameW (GetCurrentProgramPathW (hModule).c_str ()); }
S_VERSION GetExeFileVersion (LPCSTR lpszFilePath)
{
S_VERSION ver (0);
DWORD dummy;
DWORD size = GetFileVersionInfoSizeA (lpszFilePath, &dummy);
std::vector <BYTE> pVersionInfo (size);
if (!GetFileVersionInfoA (lpszFilePath, 0, size, pVersionInfo.data ()))
{
return ver;
}
VS_FIXEDFILEINFO* pFileInfo = nullptr;
UINT len = 0;
if (!VerQueryValueA (pVersionInfo.data (), "\\", (LPVOID *)&pFileInfo, &len))
{
return ver;
}
if (len == 0 || pFileInfo == nullptr)
{
return ver;
}
ver = S_VERSION (
HIWORD (pFileInfo->dwFileVersionMS),
LOWORD (pFileInfo->dwFileVersionMS),
HIWORD (pFileInfo->dwFileVersionLS),
LOWORD (pFileInfo->dwFileVersionLS)
);
return ver;
}
S_VERSION GetExeFileVersion (LPCWSTR lpswFilePath)
{
S_VERSION ver (0);
DWORD dummy;
DWORD size = GetFileVersionInfoSizeW (lpswFilePath, &dummy);
std::vector <BYTE> pVersionInfo (size);
if (!GetFileVersionInfoW (lpswFilePath, 0, size, pVersionInfo.data ()))
{
return ver;
}
VS_FIXEDFILEINFO* pFileInfo = nullptr;
UINT len = 0;
if (!VerQueryValueA (pVersionInfo.data (), "\\", (LPVOID *)&pFileInfo, &len))
{
return ver;
}
if (len == 0 || pFileInfo == nullptr)
{
return ver;
}
ver = S_VERSION (
HIWORD (pFileInfo->dwFileVersionMS),
LOWORD (pFileInfo->dwFileVersionMS),
HIWORD (pFileInfo->dwFileVersionLS),
LOWORD (pFileInfo->dwFileVersionLS)
);
return ver;
}
S_VERSION GetExeFileVersion (std::wstring objswFilePath)
{
return GetExeFileVersion (objswFilePath.c_str ());
}
S_VERSION GetExeFileVersion (std::string objszFilePath)
{
return GetExeFileVersion (objszFilePath.c_str ());
}
// 设置当前进程的环境变量RunPath和ProgramPath
void SetupInstanceEnvironment (HMODULE hModule hModule_DefaultParam)
{
// 设置RunPath为当前工作目录(无结尾反斜杠)
std::vector <WCHAR> currentDir (Max <size_t> (GetCurrentDirectoryW (0, nullptr), MAX_PATH) + 1);
DWORD len = GetCurrentDirectoryW (currentDir.capacity (), currentDir.data ());
if (len > 0)
{
std::wstring runPath (currentDir.data ());
if (!runPath.empty () && (runPath.back () == L'\\' || runPath.back () == L'/'))
{
runPath.pop_back ();
}
SetEnvironmentVariableW (L"RunPath", runPath.c_str ());
}
// 设置ProgramPath为程序所在目录(无结尾反斜杠)
std::vector <WCHAR> modulePath (Max <size_t> (GetModuleFileNameW (hModule, nullptr, 0), MAX_PATH) + 1);
len = GetModuleFileNameW (hModule, modulePath.data (), MAX_PATH);
if (len > 0 && len < MAX_PATH)
{
wchar_t* lastSlash = wcsrchr (modulePath.data (), L'\\');
if (!lastSlash) lastSlash = wcsrchr (modulePath.data (), L'/');
if (lastSlash) *lastSlash = L'\0';
std::wstring programPath (modulePath.data ());
if (!programPath.empty () && (programPath.back () == L'\\' || programPath.back () == L'/'))
{
programPath.pop_back ();
}
SetEnvironmentVariableW (L"ProgramPath", programPath.c_str ());
}
}
// 处理宽字符串环境变量展开
std::wstring ProcessEnvVars (const std::wstring &input)
{
DWORD requiredSize = ExpandEnvironmentStringsW (input.c_str (), nullptr, 0);
if (requiredSize == 0) return input;
std::wstring buffer (requiredSize, L'\0');
if (!ExpandEnvironmentStringsW (input.c_str (), &buffer [0], requiredSize))
{
return input;
}
buffer.resize (requiredSize - 1); // 去除终止空字符
return buffer.c_str ();
}
std::wstring ProcessEnvVars (LPCWSTR input)
{
return ProcessEnvVars (std::wstring (input));
}
// 处理ANSI字符串环境变量展开
std::string ProcessEnvVars (const std::string &input)
{
DWORD requiredSize = ExpandEnvironmentStringsA (input.c_str (), nullptr, 0);
if (requiredSize == 0) return input;
std::string buffer (requiredSize, '\0');
if (!ExpandEnvironmentStringsA (input.c_str (), &buffer [0], requiredSize))
{
return input;
}
buffer.resize (requiredSize - 1); // 去除终止空字符
return buffer.c_str ();
}
std::string ProcessEnvVars (LPCSTR input)
{
return ProcessEnvVars (std::string (input));
}
std::string GetCurrentDirectoryA ()
{
std::vector <CHAR> buf (Max <size_t> (GetCurrentDirectoryA (0, nullptr), MAX_PATH) + 1);
GetCurrentDirectoryA (buf.size (), buf.data ());
return buf.data ();
}
std::wstring GetCurrentDirectoryW ()
{
std::vector <WCHAR> buf (Max <size_t> (GetCurrentDirectoryW (0, nullptr), MAX_PATH) + 1);
GetCurrentDirectoryW (buf.size (), buf.data ());
return buf.data ();
}
std::wstring GetFileDirectoryW (const std::wstring &filePath)
{
std::vector <WCHAR> buf (filePath.capacity () + 1);
lstrcpyW (buf.data (), filePath.c_str ());
PathRemoveFileSpecW (buf.data ());
return buf.data ();
}
std::string GetFileDirectoryA (const std::string &filePath)
{
std::vector <CHAR> buf (filePath.capacity () + 1);
lstrcpyA (buf.data (), filePath.c_str ());
PathRemoveFileSpecA (buf.data ());
return buf.data ();
}
size_t EnumerateFilesW (const std::wstring &directory, const std::wstring &filter,
std::vector <std::wstring> &outFiles, bool recursive = false)
{
std::wstring searchPath = directory;
if (!searchPath.empty () && searchPath.back () != L'\\')
{
searchPath += L'\\';
}
searchPath += filter;
WIN32_FIND_DATAW findData;
HANDLE hFind = FindFirstFileW (searchPath.c_str (), &findData);
if (hFind != INVALID_HANDLE_VALUE)
{
do {
if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
outFiles.push_back (directory + L"\\" + findData.cFileName);
}
} while (FindNextFileW (hFind, &findData));
FindClose (hFind);
}
if (recursive) {
std::wstring subDirSearchPath = directory + L"\\*";
hFind = FindFirstFileW (subDirSearchPath.c_str (), &findData);
if (hFind != INVALID_HANDLE_VALUE)
{
do {
if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
wcscmp (findData.cFileName, L".") != 0 && wcscmp (findData.cFileName, L"..") != 0)
{
EnumerateFilesW (directory + L"\\" + findData.cFileName, filter, outFiles, true);
}
} while (FindNextFileW (hFind, &findData));
FindClose (hFind);
}
}
return outFiles.size ();
}
// 检查是否为 Windows 设备名(大小写不敏感)
bool IsReservedName (const std::wstring &name)
{
static const wchar_t* reserved [] = {
L"CON", L"PRN", L"AUX", L"NUL", L"COM1", L"COM2", L"COM3", L"COM4", L"COM5", L"COM6", L"COM7", L"COM8", L"COM9",
L"LPT1", L"LPT2", L"LPT3", L"LPT4", L"LPT5", L"LPT6", L"LPT7", L"LPT8", L"LPT9"
};
std::wstring upperName = StringToUpper (name);
for (const auto& res : reserved)
{
if (upperName == res || (upperName.rfind (res, 0) == 0 && upperName.length () > wcslen (res) && upperName [wcslen (res)] == L'.'))
{
return true;
}
}
return false;
}
// Windows 文件命名规范检查 (Unicode)
bool IsValidWindowsNameW (LPCWSTR name)
{
if (!name || !*name) return false;
std::wstring wname (name);
if (wname.find_first_of (L"<>:\"/\\|?*") != std::wstring::npos) return false;
if (IsReservedName (wname)) return false;
if (wname.back () == L' ' || wname.back () == L'.') return false;
return true;
}
// Windows 文件命名规范检查 (ANSI)
bool IsValidWindowsNameA (LPCSTR name)
{
if (!name || !*name) return false;
std::string str (name);
if (str.find_first_of ("<>:\"/\\|?*") != std::string::npos) return false;
// 转换 ANSI 到宽字符
int len = MultiByteToWideChar (CP_ACP, 0, name, -1, NULL, 0);
if (len <= 0) return false;
std::wstring wname (len - 1, L'\0');
MultiByteToWideChar (CP_ACP, 0, name, -1, &wname [0], len);
if (IsReservedName (wname)) return false;
if (str.back () == ' ' || str.back () == '.') return false;
return true;
}
bool IsValidWindowsName (LPCSTR name) { return IsValidWindowsNameA (name); }
bool IsValidWindowsName (LPCWSTR name) { return IsValidWindowsNameW (name); }
bool IsValidWindowsName (const std::wstring &name) { return IsValidWindowsName (name.c_str ()); }
bool IsValidWindowsName (const std::string &name) { return IsValidWindowsName (name.c_str ()); }
std::wstring GetRootFolderNameFromFilePath (const std::wstring &lpFilePath)
{
std::vector <WCHAR> szPath (Max <size_t> (lpFilePath.length (), MAX_PATH) + 1);
if (!PathCanonicalizeW (szPath.data (), lpFilePath.c_str ())) return L"";
if (PathRemoveFileSpecW (szPath.data ()) == FALSE) return L"";
LPCWSTR pszFolder = PathFindFileNameW (szPath.data ());
if (*pszFolder != L'\0') return std::wstring (pszFolder);
WCHAR rootName [3] = {szPath [0], L':', L'\0'};
return std::wstring (rootName);
}
std::wstring GetSafeTimestampForFilename ()
{
::FILETIME ft;
GetSystemTimeAsFileTime (&ft);
SYSTEMTIME st;
FileTimeToSystemTime (&ft, &st);
std::wstringstream wss;
wss << std::setfill (L'0')
<< st.wYear
<< std::setw (2) << st.wMonth
<< std::setw (2) << st.wDay << L"_"
<< std::setw (2) << st.wHour
<< std::setw (2) << st.wMinute
<< std::setw (2) << st.wSecond
<< std::setw (3) << st.wMilliseconds;
return wss.str ();
}
size_t EnumFiles (
const std::wstring &lpDir,
const std::wstring &lpFilter,
std::vector <std::wstring> &aszOutput,
bool bOutputWithPath = false,
bool bSortByLetter = false,
bool bIncludeSubDir = false
) {
if (!bIncludeSubDir) aszOutput.clear ();
std::vector<std::wstring> filters;
size_t start = 0;
while (start < lpFilter.length ())
{
size_t pos = lpFilter.find (L'\\', start);
if (pos == std::wstring::npos) pos = lpFilter.length ();
filters.emplace_back (lpFilter.substr (start, pos - start));
start = pos + 1;
}
std::function <void (const std::wstring &, std::wstring)> enumDir;
enumDir = [&] (const std::wstring &physicalPath, std::wstring relativePath)
{
WIN32_FIND_DATAW ffd;
HANDLE hFind = FindFirstFileW ((physicalPath + L"\\*").c_str (), &ffd);
if (hFind == INVALID_HANDLE_VALUE) return;
do {
if (wcscmp (ffd.cFileName, L".") == 0 ||
wcscmp (ffd.cFileName, L"..") == 0) continue;
const bool isDir = (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
const std::wstring newPhysical = physicalPath + L"\\" + ffd.cFileName;
std::wstring newRelative = relativePath;
if (isDir) {
if (bIncludeSubDir) {
newRelative += ffd.cFileName;
newRelative += L"\\";
enumDir (newPhysical, newRelative);
}
}
else
{
for (const auto &filter : filters)
{
if (PathMatchSpecW (ffd.cFileName, filter.c_str ()))
{
aszOutput.push_back
(
bOutputWithPath ? newPhysical : (relativePath + ffd.cFileName)
);
break;
}
}
}
} while (FindNextFileW (hFind, &ffd));
FindClose (hFind);
};
enumDir (lpDir, L"");
if (bSortByLetter) std::sort (aszOutput.begin (), aszOutput.end ());
return aszOutput.size ();
}
std::wstring GetRelativePath (
const std::wstring &pszBaseDir,
const std::wstring &pszFullPath,
DWORD cchRelative
) {
std::vector <WCHAR> szBase (Max <size_t> (pszBaseDir.length (), pszFullPath.length (), MAX_PATH) + 1);
wcscpy_s (szBase.data (), MAX_PATH, pszBaseDir.c_str ());
if (szBase [wcslen (szBase.data ()) - 1] != L'\\')
{
wcscat_s (szBase.data (), MAX_PATH, L"\\");
}
std::vector <WCHAR> buf (Max <size_t> (MAX_PATH, szBase.size ()) + 1);
BOOL res = PathRelativePathToW (
buf.data (),
szBase.data (),
FILE_ATTRIBUTE_DIRECTORY,
pszFullPath.c_str (),
FILE_ATTRIBUTE_NORMAL
);
if (res) return buf.data ();
else return L"";
}
size_t EnumDirectory (
const std::wstring &lpDir,
std::vector<std::wstring> &aszOutput,
bool bOutputWithPath = false,
bool bSortByLetter = false,
bool bIncludeSubDir = false
) {
aszOutput.clear ();
std::function <void (const std::wstring &, const std::wstring &)> enumDir;
enumDir = [&] (const std::wstring &physicalPath, const std::wstring &relativePath) {
WIN32_FIND_DATAW ffd;
HANDLE hFind = FindFirstFileW ((physicalPath + L"\\*").c_str (), &ffd);
if (hFind == INVALID_HANDLE_VALUE) return;
do
{
const std::wstring name = ffd.cFileName;
if (name == L"." || name == L"..") continue;
const bool isDir = (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
std::wstring newPhysical = physicalPath + L"\\" + name;
std::wstring newRelative = relativePath + name;
if (isDir)
{
if (bIncludeSubDir) enumDir (newPhysical, newRelative + L"\\");
if (bOutputWithPath) aszOutput.push_back (newPhysical);
else aszOutput.push_back (newRelative);
}
} while (FindNextFileW (hFind, &ffd));
FindClose (hFind);
};
enumDir (lpDir, L"");
if (bSortByLetter) std::sort (aszOutput.begin (), aszOutput.end ());
return aszOutput.size ();
}
static DWORD CALLBACK ProgressRoutine (
LARGE_INTEGER TotalFileSize,
LARGE_INTEGER TotalBytesTransferred,
LARGE_INTEGER /*StreamSize*/,
LARGE_INTEGER /*StreamBytesTransferred*/,
DWORD /*dwStreamNumber*/,
DWORD /*dwCallbackReason*/,
HANDLE /*hSourceFile*/,
HANDLE /*hDestinationFile*/,
LPVOID lpData
) {
auto *pCallback = reinterpret_cast <std::function <void (int)> *> (lpData);
if (pCallback && *pCallback)
{
int progress = static_cast <int> (
(TotalBytesTransferred.QuadPart * 100) / TotalFileSize.QuadPart
);
(*pCallback) (progress);
}
return PROGRESS_CONTINUE;
}
bool RenameFileW (
const std::wstring &lpSrcPath,
const std::wstring &lpDestPath,
std::function <void (int)> fProgress = nullptr
) {
LPPROGRESS_ROUTINE pRoutine = nullptr;
LPVOID pData = nullptr;
if (fProgress)
{
pRoutine = ProgressRoutine;
pData = &fProgress;
}
DWORD flags = MOVEFILE_COPY_ALLOWED;
BOOL ok = MoveFileWithProgressW (
lpSrcPath.c_str (),
lpDestPath.c_str (),
pRoutine,
pData,
flags
);
return ok != FALSE;
}
bool RenameFileA (
const std::string &lpSrcPath,
const std::string &lpDestPath,
std::function <void (int)> fProgress = nullptr
) {
LPPROGRESS_ROUTINE pRoutine = nullptr;
LPVOID pData = nullptr;
if (fProgress)
{
pRoutine = ProgressRoutine;
pData = &fProgress;
}
DWORD flags = MOVEFILE_COPY_ALLOWED;
BOOL ok = MoveFileWithProgressA (
lpSrcPath.c_str (),
lpDestPath.c_str (),
pRoutine,
pData,
flags
);
return ok != FALSE;
}
bool RenameFileW (const std::wstring &lpSrcDir, const std::wstring &lpSrcName, const std::wstring &lpDestName, std::function <void (int)> fProgress = nullptr)
{
struct BuildTask
{
LPWSTR src = nullptr, dest = nullptr;
~BuildTask ()
{
if (src != nullptr)
{
delete [] src;
src = nullptr;
}
if (dest != nullptr)
{
delete [] dest;
dest = nullptr;
}
}
};
BuildTask bt;
bt.src = new WCHAR [lpSrcDir.length () + lpSrcName.length () + 2];
bt.dest = new WCHAR [lpSrcDir.length () + lpDestName.length () + 2];
PathCombineW (bt.src, lpSrcDir.c_str (), lpSrcName.c_str ());
PathCombineW (bt.dest, lpSrcDir.c_str (), lpDestName.c_str ());
return RenameFileW (bt.src, bt.dest, fProgress);
}
bool RenameFileA (const std::string &lpSrcDir, const std::string &lpSrcName, const std::string &lpDestName, std::function <void (int)> fProgress = nullptr)
{
struct BuildTask
{
LPSTR src = nullptr, dest = nullptr;
~BuildTask ()
{
if (src != nullptr)
{
delete [] src;
src = nullptr;
}
if (dest != nullptr)
{
delete [] dest;
dest = nullptr;
}
}
};
BuildTask bt;
bt.src = new CHAR [lpSrcDir.length () + lpSrcName.length () + 2];
bt.dest = new CHAR [lpSrcDir.length () + lpDestName.length () + 2];
PathCombineA (bt.src, lpSrcDir.c_str (), lpSrcName.c_str ());
PathCombineA (bt.dest, lpSrcDir.c_str (), lpDestName.c_str ());
return RenameFileA (bt.src, bt.dest, fProgress);
}
bool RenameFile (const std::wstring &lpSrcPath, const std::wstring &lpDestPath, std::function <void (int)> fProgress = nullptr)
{
return RenameFileW (lpSrcPath, lpDestPath, fProgress);
}
bool RenameFile (const std::string &lpSrcPath, const std::string &lpDestPath, std::function <void (int)> fProgress = nullptr)
{
return RenameFileA (lpSrcPath, lpDestPath, fProgress);
}
bool RenameFile (const std::wstring &lpSrcDir, const std::wstring &lpSrcName, const std::wstring &lpDestName, std::function <void (int)> fProgress = nullptr)
{
return RenameFileW (lpSrcDir, lpSrcName, lpDestName, fProgress);
}
bool RenameFile (const std::string &lpSrcDir, const std::string &lpSrcName, const std::string &lpDestName, std::function <void (int)> fProgress = nullptr)
{
return RenameFileA (lpSrcDir, lpSrcName, lpDestName, fProgress);
}
bool RenameDirectoryW (
const std::wstring &lpSrcPath,
const std::wstring &lpDestPath,
std::function <void (int)> fProgress = nullptr
) {
LPPROGRESS_ROUTINE pRoutine = nullptr;
LPVOID pData = nullptr;
if (fProgress)
{
pRoutine = ProgressRoutine;
pData = &fProgress;
}
DWORD flags = MOVEFILE_COPY_ALLOWED;
BOOL ok = MoveFileWithProgressW (
lpSrcPath.c_str (),
lpDestPath.c_str (),
pRoutine,
pData,
flags
);
return ok != FALSE;
}
bool RenameDirectoryA (
const std::string &lpSrcPath,
const std::string &lpDestPath,
std::function <void (int)> fProgress = nullptr
) {
LPPROGRESS_ROUTINE pRoutine = nullptr;
LPVOID pData = nullptr;
if (fProgress)
{
pRoutine = ProgressRoutine;
pData = &fProgress;
}
DWORD flags = MOVEFILE_COPY_ALLOWED;
BOOL ok = MoveFileWithProgressA (
lpSrcPath.c_str (),
lpDestPath.c_str (),
pRoutine,
pData,
flags
);
return ok != FALSE;
}
bool RenameDirectoryW (
const std::wstring &lpParentDir,
const std::wstring &lpSrcName,
const std::wstring &lpDestName,
std::function <void (int)> fProgress = nullptr
) {
struct PathBuilder
{
LPWSTR src = nullptr;
LPWSTR dest = nullptr;
~PathBuilder ()
{
delete [] src;
delete [] dest;
}
} pb;
pb.src = new WCHAR [lpParentDir.length () + lpSrcName.length () + 2];
pb.dest = new WCHAR [lpParentDir.length () + lpDestName.length () + 2];
PathCombineW (pb.src, lpParentDir.c_str (), lpSrcName.c_str ());
PathCombineW (pb.dest, lpParentDir.c_str (), lpDestName.c_str ());
return RenameDirectoryW (pb.src, pb.dest, fProgress);
}
bool RenameDirectoryA (
const std::string &lpParentDir,
const std::string &lpSrcName,
const std::string &lpDestName,
std::function <void (int)> fProgress = nullptr
) {
struct PathBuilder
{
LPSTR src = nullptr;
LPSTR dest = nullptr;
~PathBuilder ()
{
delete [] src;
delete [] dest;
}
} pb;
pb.src = new CHAR [lpParentDir.length () + lpSrcName.length () + 2];
pb.dest = new CHAR [lpParentDir.length () + lpDestName.length () + 2];
PathCombineA (pb.src, lpParentDir.c_str (), lpSrcName.c_str ());
PathCombineA (pb.dest, lpParentDir.c_str (), lpDestName.c_str ());
return RenameDirectoryA (pb.src, pb.dest, fProgress);
}
bool RenameDirectory (
const std::wstring &src,
const std::wstring &dst,
std::function <void (int)> fProgress = nullptr
) {
return RenameDirectoryW (src, dst, fProgress);
}
bool RenameDirectory (
const std::string &src,
const std::string &dst,
std::function <void (int)> fProgress = nullptr
) {
return RenameDirectoryA (src, dst, fProgress);
}
bool RenameDirectory (
const std::wstring &parentDir,
const std::wstring &srcName,
const std::wstring &dstName,
std::function <void (int)> fProgress = nullptr
) {
return RenameDirectoryW (parentDir, srcName, dstName, fProgress);
}
bool RenameDirectory (
const std::string &parentDir,
const std::string &srcName,
const std::string &dstName,
std::function <void (int)> fProgress = nullptr
) {
return RenameDirectoryA (parentDir, srcName, dstName, fProgress);
}
std::wstring CombinePath (const std::wstring &left, const std::wstring &right)
{
std::vector <WCHAR> buf (left.capacity () + right.capacity () + 2);
PathCombineW (buf.data (), left.c_str (), right.c_str ());
return buf.data ();
}
#ifdef PathCommonPrefix
#undef PathCommonPrefix
#endif
std::wstring PathCommonPrefix (const std::wstring &file1, const std::wstring &file2)
{
std::vector <WCHAR> buf (Max <size_t> (file1.capacity (), file2.capacity (), MAX_PATH) + 2);
PathCommonPrefixW (file1.c_str (), file2.c_str (), buf.data ());
return buf.data ();
}
#undef GetFullPathName
std::wstring GetFullPathName (const std::wstring &lpFileName)
{
if (lpFileName.empty ()) return L"";
DWORD length = GetFullPathNameW (lpFileName.c_str (), 0, nullptr, nullptr);
if (length == 0) return L"";
std::vector <WCHAR> buffer (length + 1, L'\0');
DWORD result = GetFullPathNameW (lpFileName.c_str (), length, buffer.data (), nullptr);
if (result == 0) return L"";
return std::wstring (buffer.data (), result);
}
bool PathEquals (const std::wstring &path1, const std::wstring &path2)
{
size_t maxlen = Max <size_t> (path1.capacity () + 1, path2.capacity () + 1, MAX_PATH);
std::vector <WCHAR> buf1 (maxlen), buf2 (maxlen);
PathCanonicalizeW (buf1.data (), path1.c_str ());
PathCanonicalizeW (buf2.data (), path2.c_str ());
return IsNormalizeStringEquals (buf1.data (), buf2.data ());
}
+51
View File
@@ -0,0 +1,51 @@
#pragma once
#include <Windows.h>
#ifdef __cplusplus
#ifndef GetCurrentModule_bRefDefault
// 在 C++ 中,GetCurrentModule 将会启用默认值。你可以在之前宏定义此默认值。定义宏时别忘了等号“=”
// 用法如:HMODULE GetCurrentModule (BOOL bRef GetCurrentModule_bRefDefault)
#define GetCurrentModule_bRefDefault = FALSE
#endif
#else
#define GetCurrentModule_bRefDefault
#endif
HMODULE GetCurrentModule (BOOL bRef GetCurrentModule_bRefDefault)
{
HMODULE hModule = NULL;
if (GetModuleHandleExW (bRef ? GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS : (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
| GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT), (LPCWSTR)GetCurrentModule, &hModule))
{
return hModule;
}
return NULL;
}
HMODULE GetSelfModuleHandle ()
{
MEMORY_BASIC_INFORMATION mbi;
return ((::VirtualQuery (GetSelfModuleHandle, &mbi, sizeof (mbi)) != 0)
? (HMODULE)mbi.AllocationBase : NULL);
}
#ifndef GetModuleHandleW_lpModuleNameDefault
#define GetModuleHandleW_lpModuleNameDefault NULL
#endif
#ifndef DEFAULT_HMODULE
#ifdef HMODULE_MODE_EXE
#define DEFAULT_HMODULE GetModuleHandleW (NULL)
#elif defined (HMODULE_MODE_DLL1)
#define DEFAULT_HMODULE GetCurrentModule ()
#elif defined (HMODULE_MODE_DLL2)
#define DEFAULT_HMODULE GetSelfModuleHandle ()
#else
#define DEFAULT_HMODULE GetModuleHandleW (GetModuleHandleW_lpModuleNameDefault)
#endif
#endif
#undef GetModuleHandleW_lpModuleNameDefault
#ifdef __cplusplus
#ifndef hModule_DefaultParam
// 在 C++ 中,你可以使用此宏“hModule_DefaultParam”来用于给一些函数的形参定义默认值。你可以在之前宏定义此默认值。定义宏时别忘了等号“=”
// 用法如:std::wstring GetRCStringSW (UINT resID, HMODULE hModule hModule_DefaultParam)。
#define hModule_DefaultParam = DEFAULT_HMODULE
#endif
#else
#define hModule_DefaultParam
#endif
+1 -1
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="SQLite" version="3.12.2" targetFramework="native" />
<package id="pugixml" version="1.15.0" targetFramework="native" />
</packages>
+43
View File
@@ -1171,3 +1171,46 @@ LPWSTR StreamToBase64W (_In_ HANDLE hFileStream, _Out_writes_ (dwCharCount) LPWS
if (lpBase64Head) *lpBase64Head = retptr + head;
return retptr;
}
LPWSTR GetPackagePrerequistieSystemVersionName (_In_ HPKGREAD hReader, _In_ LPCWSTR lpName)
{
auto ptr = ToPtrPackage (hReader);
if (!ptr) return nullptr;
switch (ptr->type ())
{
case PackageType::single: {
auto read = ptr->appx_reader ();
auto pre = read.prerequisites ();
auto ver = pre.get_version (lpName ? lpName : L"");
auto str = GetPrerequistOSVersionDescription (ver);
return _wcsdup (str.c_str ());
} break;
case PackageType::bundle: {
auto br = ptr->bundle_reader ();
CComPtr <IAppxFile> iaf;
if (FAILED (br.random_application_package (&iaf))) return nullptr;
CComPtr <IStream> ist;
if (FAILED (iaf->GetStream (&ist))) return nullptr;
CComPtr <IAppxPackageReader> iar;
if (FAILED (GetAppxPackageReader (ist, &iar))) return nullptr;
appxreader read (iar.p);
auto pre = read.prerequisites ();
auto ver = pre.get_version (lpName ? lpName : L"");
auto str = GetPrerequistOSVersionDescription (ver);
return _wcsdup (str.c_str ());
}
default:
break;
}
return nullptr;
}
LPWSTR GetPackageCapabilityDisplayName (LPCWSTR lpCapabilityName)
{
if (!lpCapabilityName) return nullptr;
std::wnstring capname = (lpCapabilityName ? lpCapabilityName : L"");
if (capname.empty ()) return nullptr;
std::wstring ret = GetCapabilityDisplayName (capname);
if (IsNormalizeStringEmpty (ret)) return nullptr;
else return _wcsdup (ret.c_str ());
}
+44
View File
@@ -251,6 +251,7 @@ extern "C"
PKGREAD_API BOOL GetPackagePrerequisite (_In_ HPKGREAD hReader, _In_ LPCWSTR lpName, _Outptr_ VERSION *pVerRet);
#define GetPackagePrerequisiteOsMinVersion(_In_hReader_, _Outptr_pVerRet_) GetPackagePrerequisite (_In_hReader_, PKG_PREREQUISITE_OS_MIN_VERSION, _Outptr_pVerRet_)
#define GetPackagePrerequisiteOsMaxVersionTested(_In_hReader_, _Outptr_pVerRet_) GetPackagePrerequisite (_In_hReader_, PKG_PREREQUISITE_OS_MAX_VERSION_TESTED, _Outptr_pVerRet_)
PKGREAD_API LPWSTR GetPackagePrerequistieSystemVersionName (_In_ HPKGREAD hReader, _In_ LPCWSTR lpName);
// File Stream
// 从 Appx 包中获取 Appx 中的文件的文件流。
@@ -282,6 +283,9 @@ extern "C"
PKGREAD_API LPWSTR StreamToBase64W (_In_ HANDLE hFileStream, _Out_writes_ (dwCharCount) LPWSTR lpMimeBuf, _In_ DWORD dwCharCount, _Outptr_ LPWSTR *lpBase64Head);
// 获取 AppxBundle 包中的应用包文件流。最后通过 DestroyAppxFileStream 销毁。
PKGREAD_API HANDLE GetAppxBundleApplicationPackageFile (_In_ HPKGREAD hReader);
// 获取功能名的显示名,如 internetClient 对应“访问您的 Internet 连接”。返回的是适应于系统区域语言的文本。
// 注意:返回的字符串一定要通过 free 释放。
PKGREAD_API LPWSTR GetPackageCapabilityDisplayName (LPCWSTR lpCapabilityName);
#ifdef _DEFAULT_INIT_VALUE_
#undef _DEFAULT_INIT_VALUE_
#endif
@@ -320,6 +324,35 @@ const std::vector <std::wstring> g_filepathitems =
L"Wide310x150Logo",
L"Executable"
};
std::map <std::wstring, std::wstring> g_capnamemap;
std::wstring GetPackageCapabilityDisplayName (const std::wstring &capname)
{
try
{
if (g_capnamemap.find (capname) != g_capnamemap.end () && !g_capnamemap.at (capname).empty ()) return g_capnamemap.at (capname);
else
{
LPWSTR lpstr = GetPackageCapabilityDisplayName (capname.c_str ());
std::wstring ret = L"";
ret += lpstr ? lpstr : L"";
if (lpstr) free (lpstr);
lpstr = nullptr;
g_capnamemap [capname] = ret;
return ret;
}
}
catch (...)
{
LPWSTR lpstr = GetPackageCapabilityDisplayName (capname.c_str ());
std::wstring ret = L"";
ret += lpstr ? lpstr : L"";
if (lpstr) free (lpstr);
lpstr = nullptr;
g_capnamemap [capname] = ret;
return ret;
}
return L"";
}
class package_reader
{
private:
@@ -984,6 +1017,17 @@ class package_reader
}
VERSION os_min_version () const { return get_version (PKG_PREREQUISITE_OS_MIN_VERSION); }
VERSION os_max_version_tested () const { return get_version (PKG_PREREQUISITE_OS_MAX_VERSION_TESTED); }
std::wstring get_description (const std::wstring &name) const
{
LPWSTR lpstr = GetPackagePrerequistieSystemVersionName (hReader, name.c_str ());
deconstr relt ([&lpstr] () {
if (lpstr) free (lpstr);
lpstr = nullptr;
});
return lpstr ? lpstr : L"";
}
std::wstring os_min_version_description () const { return get_description (PKG_PREREQUISITE_OS_MIN_VERSION); }
std::wstring os_max_version_tested_description () const { return get_description (PKG_PREREQUISITE_OS_MAX_VERSION_TESTED); }
};
package_reader (): hReader (CreatePackageReader ()) {}
package_reader (const std::wstring &fpath): hReader (CreatePackageReader ())
Binary file not shown.
+18 -6
View File
@@ -86,13 +86,13 @@
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;PKGREAD_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;PKGREAD_EXPORTS;HMODULE_MODE_DLL1;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>urlmon.lib;crypt32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>urlmon.lib;crypt32.lib;version.lib;xmllite.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -115,7 +115,7 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;PKGREAD_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;PKGREAD_EXPORTS;HMODULE_MODE_DLL1;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
@@ -123,7 +123,7 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>urlmon.lib;crypt32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>urlmon.lib;crypt32.lib;version.lib;xmllite.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -148,17 +148,22 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="dynarr.h" />
<ClInclude Include="filepath.h" />
<ClInclude Include="localeex.h" />
<ClInclude Include="module.h" />
<ClInclude Include="norstr.h" />
<ClInclude Include="pkgread.h" />
<ClInclude Include="raii.h" />
<ClInclude Include="rctools.h" />
<ClInclude Include="readobj.h" />
<ClInclude Include="resource1.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="strcmp.h" />
<ClInclude Include="stringres.h" />
<ClInclude Include="syncutil.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="themeinfo.h" />
<ClInclude Include="typestrans.h" />
<ClInclude Include="version.h" />
</ItemGroup>
<ItemGroup>
@@ -185,12 +190,19 @@
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<ResourceCompile Include="pkgread.rc" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="pkgread.rc" />
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\packages\pugixml.1.15.0\build\native\pugixml.targets" Condition="Exists('..\packages\pugixml.1.15.0\build\native\pugixml.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\pugixml.1.15.0\build\native\pugixml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\pugixml.1.15.0\build\native\pugixml.targets'))" />
</Target>
</Project>
+18 -3
View File
@@ -57,6 +57,21 @@
<ClInclude Include="themeinfo.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="module.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="rctools.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="filepath.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="typestrans.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="strcmp.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
@@ -69,12 +84,12 @@
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="pkgread.rc">
<Filter>资源文件</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
</Project>
+121
View File
@@ -0,0 +1,121 @@
#pragma once
#include <Windows.h>
#include <WinBase.h>
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "typestrans.h"
#include "module.h"
// 返回的指针如果非空则一定需要用 free 释放
LPWSTR GetRCStringW (UINT resID, HMODULE hModule hModule_DefaultParam)
{
std::vector <WCHAR> buf (256);
size_t cnt = 0;
CopyStringLoop_GetRCStringW:
{
size_t len = LoadStringW (hModule, resID, buf.data (), buf.size ());
if (cnt > 1625) return _wcsdup (buf.data ());
if (len >= buf.size () - 1)
{
buf.resize (buf.size () + 20);
cnt ++;
goto CopyStringLoop_GetRCStringW;
}
else return _wcsdup (buf.data ());
}
}
// 返回的指针如果非空则一定需要用 free 释放
LPSTR GetRCStringA (UINT resID, HMODULE hModule hModule_DefaultParam)
{
std::vector <CHAR> buf (256);
size_t cnt = 0;
CopyStringLoop_GetRCStringA:
{
size_t len = LoadStringA (hModule, resID, buf.data (), buf.size ());
if (cnt > 1625) return _strdup (buf.data ());
if (len >= buf.size () - 1)
{
buf.resize (buf.size () + 20);
cnt ++;
goto CopyStringLoop_GetRCStringA;
}
else return _strdup (buf.data ());
}
}
HICON LoadRCIcon (UINT resID, HMODULE hModule hModule_DefaultParam)
{
return (HICON)LoadImageW (hModule, MAKEINTRESOURCEW (resID), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
}
HRSRC FindResourceByName (LPCWSTR resourceName, LPCWSTR resourceType, HMODULE hModule hModule_DefaultParam)
{
return FindResourceW (hModule, resourceName, resourceType);
}
#ifdef __cplusplus
#include <string>
std::wstring GetRCStringSW (UINT resID, HMODULE hModule hModule_DefaultParam)
{
std::vector <WCHAR> buf (256);
size_t cnt = 0;
CopyStringLoop_GetRCStringSW:
{
size_t len = LoadStringW (hModule, resID, buf.data (), buf.size ());
if (cnt > 1625) return buf.data ();
if (len >= buf.size () - 1)
{
buf.resize (buf.size () + 20);
cnt ++;
goto CopyStringLoop_GetRCStringSW;
}
else return buf.data ();
}
}
std::string GetRCStringSA (UINT resID, HMODULE hModule hModule_DefaultParam)
{
std::vector <CHAR> buf (256);
size_t cnt = 0;
CopyStringLoop_GetRCStringSA:
{
size_t len = LoadStringA (hModule, resID, buf.data (), buf.size ());
if (cnt > 1625) return buf.data ();
if (len >= buf.size () - 1)
{
buf.resize (buf.size () + 20);
cnt ++;
goto CopyStringLoop_GetRCStringSA;
}
else return buf.data ();
}
}
#endif
#if defined (__cplusplus) && defined (__cplusplus_cli)
using namespace System;
String ^GetRCStringCli (UINT resID, HMODULE hModule hModule_DefaultParam)
{
std::vector <WCHAR> buf (256);
size_t cnt = 0;
CopyStringLoop_GetRCStringCli:
{
size_t len = LoadStringW (hModule, resID, buf.data (), buf.size ());
if (cnt > 1625) return gcnew String (buf.data ());
if (len >= buf.size () - 1)
{
buf.resize (buf.size () + 20);
cnt ++;
goto CopyStringLoop_GetRCStringCli;
}
else return gcnew String (buf.data ());
}
}
#define GetRCIntValue(_UINT__resID_) toInt (GetRCStringCli (_UINT__resID_))
#define GetRCDoubleValue(_UINT__resID_) toDouble (GetRCStringCli (_UINT__resID_))
#define GetRCBoolValue(_UINT__resID_) toBool (GetRCStringCli (_UINT__resID_))
#define GetRCDateTimeValue(_UINT__resID_) toDateTime (GetRCStringCli (_UINT__resID_))
#define rcString(resID) GetRCStringCli (resID)
#define rcInt(resID) GetRCIntValue (resID)
#define rcDouble(resID) GetRCDoubleValue (resID)
#define rcBool(resID) GetRCBoolValue (resID)
#define rcDTime(resID) GetRCDateTimeValue (resID)
#define rcIcon(resID) LoadRCIcon (resID)
#endif
+52 -19
View File
@@ -9,27 +9,14 @@
#include <atlbase.h>
#include <functional>
#include <utility>
#include <xmllite.h>
#include "dynarr.h"
#include "version.h"
#include "stringres.h"
#include "norstr.h"
#include "raii.h"
#include "priformatcli.h"
bool IsFileExistsW (LPCWSTR filename)
{
DWORD dwAttrib = GetFileAttributesW (filename);
return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
bool IsFileExistsA (LPCSTR filename)
{
DWORD dwAttrib = GetFileAttributesA (filename);
return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
bool IsFileExists (LPWSTR filePath) { return IsFileExistsW (filePath); }
bool IsFileExists (LPCSTR filePath) { return IsFileExistsA (filePath); }
bool IsFileExists (std::string filePath) { return IsFileExistsA (filePath.c_str ()); }
bool IsFileExists (std::wstring filePath) { return IsFileExistsW (filePath.c_str ()); }
#include "filepath.h"
HRESULT GetBundleReader (_In_ LPCWSTR inputFileName, _Outptr_ IAppxBundleReader** bundleReader)
{
@@ -615,9 +602,53 @@ namespace appx_info
{
using Base = com_info <IAppxManifestDeviceCapabilitiesEnumerator>;
APPX_CAPABILITIES cflags;
std::vector <std::wnstring> cnames;
public:
using Base::Base;
appx_capabs (IAppxManifestDeviceCapabilitiesEnumerator *devicec, APPX_CAPABILITIES capa): cflags (capa), com_info (devicec) {}
appx_capabs (IAppxManifestDeviceCapabilitiesEnumerator *devicec, APPX_CAPABILITIES capa, IAppxManifestReader *&r): cflags (capa), com_info (devicec)
{
if (!r) return;
CComPtr <IStream> xmlstream;
if (FAILED (r->GetStream (&xmlstream))) return;
CComPtr <IXmlReader> xmlreader;
if (FAILED (CreateXmlReader (__uuidof (IXmlReader), (void **)&xmlreader, nullptr))) return;
xmlreader->SetInput (xmlstream.p);
XmlNodeType nodeType;
bool inPackage = false;
bool inCapabilities = false;
HRESULT hr = S_OK;
auto &reader = xmlreader;
while (SUCCEEDED (hr = xmlreader->Read (&nodeType)) && hr == S_OK)
{
if (nodeType == XmlNodeType_Element)
{
LPCWSTR localName = nullptr;
reader->GetLocalName (&localName, nullptr);
// <Package>
if (!inPackage && _wcsicmp (localName, L"Package") == 0) inPackage = true;
// <Capabilities>
else if (inPackage && !inCapabilities && _wcsicmp (localName, L"Capabilities") == 0) inCapabilities = true;
// <Capability>
else if (inCapabilities && _wcsicmp (localName, L"Capability") == 0)
{
if (SUCCEEDED (reader->MoveToAttributeByName (L"Name", nullptr)))
{
LPCWSTR value = nullptr;
reader->GetValue (&value, nullptr);
if (value && *value) cnames.push_back (value);
}
reader->MoveToElement ();
}
}
else if (nodeType == XmlNodeType_EndElement)
{
LPCWSTR localName = nullptr;
reader->GetLocalName (&localName, nullptr);
if (inCapabilities && _wcsicmp (localName, L"Capabilities") == 0) inCapabilities = false;
else if (inPackage && _wcsicmp (localName, L"Package") == 0) break;
}
}
}
appx_capabs () = default;
APPX_CAPABILITIES capabilities () const { return cflags; }
size_t device_capabilities (_Out_ std::vector <std::wstring> &output) const
@@ -634,7 +665,8 @@ namespace appx_info
size_t capabilities_names (_Out_ std::vector <std::wstring> &output) const
{
output.clear ();
CapabilitiesFlagsToNames (cflags, output);
if (cnames.empty ()) CapabilitiesFlagsToNames (cflags, output);
else for (auto &it : cnames) output.push_back (it);
return output.size ();
}
// 获取功能和设备功能的所有功能名
@@ -889,8 +921,9 @@ class appxreader: virtual public com_info_quote <IAppxPackageReader>
{
APPX_CAPABILITIES caps;
IAppxManifestDeviceCapabilitiesEnumerator *ip = nullptr;
get_device_capabilities (&ip);
if (SUCCEEDED (get_capabilities (&caps))) return appx_info::appx_capabs (ip, caps);
CComPtr <IAppxManifestReader> im;
if (SUCCEEDED (manifest (&im))) im->GetDeviceCapabilities (&ip);
if (SUCCEEDED (get_capabilities (&caps))) return appx_info::appx_capabs (ip, caps, im.p);
return appx_info::appx_capabs (ip);
}
HRESULT get_dependencies (_Outptr_ IAppxManifestPackageDependenciesEnumerator **output) const { return get_from_manifest <IAppxManifestPackageDependenciesEnumerator *> (&Manifest::GetPackageDependencies, output); }
Binary file not shown.
+154
View File
@@ -0,0 +1,154 @@
#pragma once
#include <Shlwapi.h>
#include "norstr.h"
#ifdef __cplusplus
#define ptrnull(ptr) (!(ptr))
#else
#define ptrnull(ptr) ((ptr) == NULL)
#endif
#define ptrvalid(ptr) (!ptrnull (ptr))
// 用于 char * 或 WCHAR * 字符串(结尾为 NULL),判断是否为非空字符串:指针有效且长度大于 0。千万不能是野指针,否则一定会崩溃!
#define strvalid(strptr) (ptrvalid (strptr) && *(strptr))
// 用于 char * 或 WCHAR * 字符串(结尾为 NULL),判断是否为空字符串:指针为 NULL 或长度为 0。千万不能是野指针,否则一定会崩溃!
#define strnull(strptr) (ptrnull (strptr) || !*(strptr))
typedef std::wnstring strlabel, StringLabel;
std::wstring StringTrim (const std::wstring &str) { return std::wnstring::trim (str); }
std::string StringTrim (const std::string &str) { return std::nstring::trim (str); }
#define StringToUpper l0km::toupper
#define StringToLower l0km::tolower
int LabelCompare (const std::wstring &l1, const std::wstring &l2)
{
return std::wnstring::compare (l1, l2);
}
int LabelCompare (const std::string &l1, const std::string &l2)
{
return std::nstring::compare (l1, l2);
}
bool LabelEqual (const std::wstring &l1, const std::wstring &l2)
{
return std::wnstring::equals (l1, l2);
}
bool LabelEqual (const std::string &l1, const std::string &l2)
{
return std::wnstring::equals (l1, l2);
}
bool LabelEmpty (const std::wstring &str) { return std::wnstring::empty (str); }
bool LabelEmpty (const std::string &str) { return std::nstring::empty (str); }
#define LabelNoEmpty(_str_) (!LabelEmpty (_str_))
int InStr (const std::string &text, const std::string &keyword, bool ignoreCase = false)
{
std::string s1, s2;
if (ignoreCase)
{
s1 = StringToUpper (text);
s2 = StringToUpper (keyword);
}
else
{
s1 = text;
s2 = keyword;
}
const char *found = StrStrIA (s1.c_str (), s2.c_str ());
if (!found)
{
return -1;
}
return found - text.c_str ();
}
int InStr (const std::wstring &text, const std::wstring &keyword, bool ignoreCase = false)
{
std::wstring s1, s2;
if (ignoreCase)
{
s1 = StringToUpper (text);
s2 = StringToUpper (keyword);
}
else
{
s1 = text;
s2 = keyword;
}
const WCHAR *found = StrStrIW (s1.c_str (), s2.c_str ());
if (!found)
{
return -1;
}
return found - text.c_str ();
}
bool StrInclude (const std::string &text, const std::string &keyword, bool ignoreCase = false)
{
std::string s1, s2;
if (ignoreCase)
{
s1 = StringToUpper (text);
s2 = StringToUpper (keyword);
}
else
{
s1 = text;
s2 = keyword;
}
const char *found = StrStrIA (s1.c_str (), s2.c_str ());
if (!found) return false;
return true;
}
bool StrInclude (const std::wstring &text, const std::wstring &keyword, bool ignoreCase = false)
{
std::wstring s1, s2;
if (ignoreCase)
{
s1 = StringToUpper (text);
s2 = StringToUpper (keyword);
}
else
{
s1 = text;
s2 = keyword;
}
const WCHAR *found = StrStrIW (s1.c_str (), s2.c_str ());
if (!found) return false;
return true;
}
// 该函数帮助构成 "<str1>\0<str2>\0" 这种字符串,用于通用对话框中的文件框
LPCWSTR strcpynull (LPWSTR dest, LPCWSTR endwith, size_t bufsize)
{
if (!dest || !endwith || bufsize == 0)
return dest;
if (dest [0] == L'\0' && bufsize > 1)
{
dest [1] = L'\0';
}
size_t pos = 0;
while (pos < bufsize - 1)
{
if (dest [pos] == L'\0' && dest [pos + 1] == L'\0')
{
if (dest [0]) pos ++;
break;
}
pos ++;
}
size_t i = 0;
while (pos < bufsize - 1 && endwith [i] != L'\0')
{
dest [pos ++] = endwith [i ++];
}
if (pos < bufsize)
{
dest [pos] = L'\0';
}
return dest;
}
// 取文本左边,注意:长度指的是文本字符数,比如“ch”的长度为2
std::wstring GetStringLeft (const std::wstring &str, size_t length)
{
std::vector <WCHAR> buf (length + 1);
lstrcpynW (buf.data (), str.c_str (), length + 1);
return buf.data ();
}
// 取文本右边
std::wstring GetStringRight (const std::wstring &str, size_t length)
{
if (length >= str.length ()) return str;
return str.substr (str.length () - length, length).c_str ();
}
+204
View File
@@ -1,10 +1,16 @@
#pragma once
#include <string>
#include <map>
#include <pugiconfig.hpp>
#include <pugixml.hpp>
#include "version.h"
#include "dynarr.h"
#include "norstr.h"
#include "syncutil.h"
#include "resource1.h"
#include "localeex.h"
#include "rctools.h"
#include "filepath.h"
static const std::pair <UINT64, LPCWSTR> captable [] = {
{APPX_CAPABILITY_INTERNET_CLIENT, L"internetClient"},
{APPX_CAPABILITY_INTERNET_CLIENT_SERVER, L"internetClientServer"},
@@ -123,4 +129,202 @@ bool RemoveApplicationAttributeItem (const std::wstring &lpstr)
return appitems.size () < len1;
}
return false;
}
#define MAKENAMEIDMAP(_Res_Name_) {#_Res_Name_, _Res_Name_}
std::map <std::string, unsigned> g_nameToId = {
MAKENAMEIDMAP (accessoryManager),
MAKENAMEIDMAP (activity),
MAKENAMEIDMAP (allJoyn),
MAKENAMEIDMAP (allowElevation),
MAKENAMEIDMAP (appDiagnostics),
MAKENAMEIDMAP (applicationData),
MAKENAMEIDMAP (applicationPackage),
MAKENAMEIDMAP (appLicensing),
MAKENAMEIDMAP (appointments),
MAKENAMEIDMAP (appointmentsSystem),
MAKENAMEIDMAP (appointmentSystem),
MAKENAMEIDMAP (authenticationManagerAuthentication),
MAKENAMEIDMAP (blockedChatMessages),
MAKENAMEIDMAP (bluetooth),
MAKENAMEIDMAP (bluetooth_genericAttributeProfile),
MAKENAMEIDMAP (bluetooth_rfcomm),
MAKENAMEIDMAP (broadFileSystemAccess),
MAKENAMEIDMAP (callHistory),
MAKENAMEIDMAP (callHistorySystem),
MAKENAMEIDMAP (cellularDeviceControl),
MAKENAMEIDMAP (cellularDeviceIdentity),
MAKENAMEIDMAP (cellularMessaging),
MAKENAMEIDMAP (chat),
MAKENAMEIDMAP (chatSystem),
MAKENAMEIDMAP (codeGeneration),
MAKENAMEIDMAP (confirmAppClose),
MAKENAMEIDMAP (contacts),
MAKENAMEIDMAP (contactsSystem),
MAKENAMEIDMAP (contactSystem),
MAKENAMEIDMAP (cortanaSpeechAccessory),
MAKENAMEIDMAP (customInstallActions),
MAKENAMEIDMAP (deviceManagementDmAccount),
MAKENAMEIDMAP (deviceManagementEmailAccount),
MAKENAMEIDMAP (deviceManagementFoundation),
MAKENAMEIDMAP (deviceManagementWapSecurityPolicies),
MAKENAMEIDMAP (deviceMangementFoundation),
MAKENAMEIDMAP (deviceUnlock),
MAKENAMEIDMAP (documentsLibrary),
MAKENAMEIDMAP (dualSimTiles),
MAKENAMEIDMAP (email),
MAKENAMEIDMAP (emailSystem),
MAKENAMEIDMAP (enterpriseAuthentication),
MAKENAMEIDMAP (enterpriseDataPolicy),
MAKENAMEIDMAP (enterpriseDeviceLockdown),
MAKENAMEIDMAP (extendedExecutionBackgroundAudio),
MAKENAMEIDMAP (extendedExecutionCritical),
MAKENAMEIDMAP (extendedExecutionUnconstrained),
MAKENAMEIDMAP (externalDependenciesVirtualCapability),
MAKENAMEIDMAP (firstSignInSettings),
MAKENAMEIDMAP (gameList),
MAKENAMEIDMAP (humaninterfacedevice),
MAKENAMEIDMAP (hyperLinkLearnMore),
MAKENAMEIDMAP (inputForegroundObservation),
MAKENAMEIDMAP (inputInjection),
MAKENAMEIDMAP (inputInjection_Brokered),
MAKENAMEIDMAP (inputObservation),
MAKENAMEIDMAP (inputSuppression),
MAKENAMEIDMAP (internetClient),
MAKENAMEIDMAP (internetClientServer),
MAKENAMEIDMAP (interopServices),
MAKENAMEIDMAP (localSystemServices),
MAKENAMEIDMAP (location),
MAKENAMEIDMAP (locationHistory),
MAKENAMEIDMAP (locationSystem),
MAKENAMEIDMAP (lockScreenCreatives),
MAKENAMEIDMAP (lowLevelDevices),
MAKENAMEIDMAP (microphone),
MAKENAMEIDMAP (modifiableApp),
MAKENAMEIDMAP (musicLibrary),
MAKENAMEIDMAP (networkConnectionManagerProvisioning),
MAKENAMEIDMAP (networkDataPlanProvisioning),
MAKENAMEIDMAP (networkingVpnProvider),
MAKENAMEIDMAP (objects3d),
MAKENAMEIDMAP (oemDeployment),
MAKENAMEIDMAP (oemPublicDirectory),
MAKENAMEIDMAP (optical),
MAKENAMEIDMAP (packagedServices),
MAKENAMEIDMAP (packageManagement),
MAKENAMEIDMAP (packagePolicySystem),
MAKENAMEIDMAP (packageQuery),
MAKENAMEIDMAP (packageWriteRedirectionCompatibilityShim),
MAKENAMEIDMAP (phoneCall),
MAKENAMEIDMAP (phoneCallHistory),
MAKENAMEIDMAP (phoneCallHistoryPublic),
MAKENAMEIDMAP (phoneCallHistorySystem),
MAKENAMEIDMAP (picturesLibrary),
MAKENAMEIDMAP (pointOfService),
MAKENAMEIDMAP (previewStore),
MAKENAMEIDMAP (previewUiComposition),
MAKENAMEIDMAP (privateNetworkClientServer),
MAKENAMEIDMAP (proximity),
MAKENAMEIDMAP (recordedCallsFolder),
MAKENAMEIDMAP (remotePassportAuthentication),
MAKENAMEIDMAP (removableStorage),
MAKENAMEIDMAP (runFullTrust),
MAKENAMEIDMAP (screenDuplication),
MAKENAMEIDMAP (sharedUserCertificates),
MAKENAMEIDMAP (smsSend),
MAKENAMEIDMAP (spatialPerception),
MAKENAMEIDMAP (systemManagement),
MAKENAMEIDMAP (teamEditionExperience),
MAKENAMEIDMAP (uiAccess),
MAKENAMEIDMAP (unvirtualizedResources),
MAKENAMEIDMAP (usb),
MAKENAMEIDMAP (userAccountInformation),
MAKENAMEIDMAP (userDataAccountSetup),
MAKENAMEIDMAP (userDataAccountsProvider),
MAKENAMEIDMAP (userDataSystem),
MAKENAMEIDMAP (userPrincipalName),
MAKENAMEIDMAP (userSigninSupport),
MAKENAMEIDMAP (videosLibrary),
MAKENAMEIDMAP (visualElementsSystem),
MAKENAMEIDMAP (visualVoiceMail),
MAKENAMEIDMAP (voipCall),
MAKENAMEIDMAP (walletSystem),
MAKENAMEIDMAP (webcam),
MAKENAMEIDMAP (wiFiControl),
MAKENAMEIDMAP (xboxAccessoryManagement)
};
#ifdef MAKENAMEIDMAP
#undef MAKENAMEIDMAP
#endif
std::string GetSuitableLanguageValue (const std::map <std::nstring, std::string> &map, const std::nstring &localename)
{
for (auto &it : map) if (it.first == localename) return it.second;
for (auto &it : map) if (LocaleNameCompare (pugi::as_wide (it.first), pugi::as_wide (localename))) return it.second;
for (auto &it : map) if (IsNormalizeStringEquals (GetLocaleRestrictedCodeA (it.first), GetLocaleRestrictedCodeA (localename))) return it.second;
for (auto &it : map) if (LocaleNameCompare (pugi::as_wide (GetLocaleRestrictedCodeA (it.first)), pugi::as_wide (GetLocaleRestrictedCodeA (localename)))) return it.second;
return "";
}
std::string GetSuitableLanguageValue (const std::map <std::nstring, std::string> &map)
{
if (map.empty ()) return "";
std::string ret = GetSuitableLanguageValue (map, pugi::as_utf8 (GetComputerLocaleCodeW ()));
if (ret.empty ()) ret = GetSuitableLanguageValue (map, "en-US");
if (ret.empty ()) ret = map.begin ()->second;
return ret;
}
struct xmldoc
{
pugi::xml_document doc;
bool isvalid = false;
void destroy ()
{
if (isvalid) doc.reset ();
isvalid = false;
}
bool create (const std::wstring &filepath)
{
destroy ();
auto res = doc.load_file (filepath.c_str ());
return isvalid = res;
}
xmldoc (const std::wstring &filepath) { create (filepath); }
~xmldoc () { destroy (); }
std::string get (const std::string &id) const
{
auto root = doc.first_child ();
auto nodes = root.children ();
for (auto &it : nodes)
{
if (IsNormalizeStringEquals (std::string (it.attribute ("id").as_string ()), id))
{
auto strings = it.children ();
std::map <std::nstring, std::string> lang_value;
for (auto &sub : strings)
{
std::nstring lang = sub.attribute ("name").as_string ();
if (!lang.empty ()) lang_value [lang] = sub.text ().get ();
}
return GetSuitableLanguageValue (lang_value);
}
}
return "";
}
std::wstring get (const std::wstring &id) const { return pugi::as_wide (get (pugi::as_utf8 (id))); }
std::wstring operator [] (const std::wstring &id) const { return get (id); }
std::wstring operator [] (const std::wstring &id) { return get (id); }
std::string operator [] (const std::string &id) const { return get (id); }
std::string operator [] (const std::string &id) { return get (id); }
} cap_localeres (CombinePath (GetProgramRootDirectoryW (), L"locale\\capabilities.xml"));
std::wstring GetCapabilityDisplayName (const std::wstring &capname)
{
std::nstring searchname = pugi::as_utf8 (capname);
std::wstring ret = cap_localeres [capname];
if (IsNormalizeStringEmpty (ret))
{
for (auto &it : g_nameToId)
{
if (it.first == searchname) return GetRCStringSW (it.second);
}
}
else return ret;
return L"";
}
+265
View File
@@ -0,0 +1,265 @@
#pragma once
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <Windows.h>
#ifdef __cplusplus
#include <cstdio>
#include <cstdlib>
#include <cstdbool>
#include <cstring>
#else
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#endif
unsigned _wtou (const wchar_t *str)
{
unsigned value = 0;
if (str)
{
swscanf (str, L"%u", &value);
}
return value;
}
unsigned long _wtoul (const wchar_t *str)
{
unsigned value = 0;
if (str)
{
swscanf (str, L"%lu", &value);
}
return value;
}
unsigned long long _wtou64 (const wchar_t *str)
{
unsigned long long value = 0;
if (str)
{
swscanf (str, L"%llu", &value);
}
return value;
}
double _wtod (const wchar_t *str)
{
if (!str || !*str) return 0.0; // 避免空指针或空字符串
double value = 0.0;
if (swscanf (str, L"%lg", &value) == 1)
{
return value;
}
return 0.0; // 解析失败时返回 0.0
}
unsigned atou (const char *str)
{
unsigned value = 0;
if (str)
{
sscanf (str, "%u", &value);
}
return value;
}
unsigned long atoul (const char *str)
{
unsigned value = 0;
if (str)
{
sscanf (str, "%lu", &value);
}
return value;
}
unsigned long long atou64 (const char *str)
{
unsigned long long value = 0;
if (str)
{
sscanf (str, "%llu", &value);
}
return value;
}
double atod (const char *str)
{
if (!str || !*str) return 0.0; // 避免空指针或空字符串
double value = 0.0;
if (sscanf (str, "%lg", &value) == 1)
{
return value;
}
return 0.0; // 解析失败时返回 0.0
}
int8_t atoi8 (const char *str)
{
int value = 0;
if (str) sscanf (str, "%d", &value);
return (int8_t)value;
}
int16_t atoi16 (const char *str)
{
int value = 0;
if (str) sscanf (str, "%d", &value);
return (int16_t)value;
}
int32_t atoi32 (const char *str)
{
int32_t value = 0;
if (str) sscanf (str, "%d", &value);
return value;
}
uint8_t atoui8 (const char *str)
{
unsigned value = 0;
if (str) sscanf (str, "%u", &value);
return (uint8_t)value;
}
uint16_t atoui16 (const char *str)
{
unsigned value = 0;
if (str) sscanf (str, "%u", &value);
return (uint16_t)value;
}
uint32_t atoui32 (const char *str)
{
uint32_t value = 0;
if (str) sscanf (str, "%u", &value);
return value;
}
int8_t _wtoi8 (const wchar_t *str)
{
int value = 0;
if (str) swscanf (str, L"%d", &value);
return (int8_t)value;
}
int16_t _wtoi16 (const wchar_t *str)
{
int value = 0;
if (str) swscanf (str, L"%d", &value);
return (int16_t)value;
}
int32_t _wtoi32 (const wchar_t *str)
{
int32_t value = 0;
if (str) swscanf (str, L"%d", &value);
return value;
}
uint8_t _wtoui8 (const wchar_t *str)
{
unsigned value = 0;
if (str) swscanf (str, L"%u", &value);
return (uint8_t)value;
}
uint16_t _wtoui16 (const wchar_t *str)
{
unsigned value = 0;
if (str) swscanf (str, L"%u", &value);
return (uint16_t)value;
}
uint32_t _wtoui32 (const wchar_t *str)
{
uint32_t value = 0;
if (str) swscanf (str, L"%u", &value);
return value;
}
int64_t atoi64 (const char *str)
{
int64_t value = 0;
if (str) sscanf (str, "%lld", &value);
return value;
}
EXTERN_C int StringToIntA (const char *str) { return atoi (str); }
EXTERN_C int StringToIntW (const WCHAR *str) { return _wtoi (str); }
EXTERN_C unsigned StringToUnsignedA (const char *str) { return atou (str); }
EXTERN_C unsigned StringToUnsignedW (const WCHAR *str) { return _wtou (str); }
EXTERN_C bool StringToBoolA (const char *str)
{
char buf [32] = {0};
strcpy (buf, str);
for (int cnt = 0; buf [cnt]; cnt ++) buf [cnt] = tolower (buf [cnt]);
return !strcmp (buf, "true") ||
!strcmp (buf, "yes") ||
!strcmp (buf, "ok") ||
!strcmp (buf, "sure") ||
!strcmp (buf, "okay") ||
!strcmp (buf, "zhen") ||
!strcmp (buf, "");
}
EXTERN_C bool StringToBoolW (const WCHAR *str)
{
WCHAR buf [32] = {0};
lstrcpyW (buf, str);
for (int cnt = 0; buf [cnt]; cnt ++) buf [cnt] = tolower (buf [cnt]);
return !lstrcmpW (buf, L"true") ||
!lstrcmpW (buf, L"yes") ||
!lstrcmpW (buf, L"ok") ||
!lstrcmpW (buf, L"sure") ||
!lstrcmpW (buf, L"okay") ||
!lstrcmpW (buf, L"zhen") ||
!lstrcmpW (buf, L"");
}
EXTERN_C long StringToLongA (const char *str) { return atol (str); }
EXTERN_C long StringToLongW (const WCHAR *str) { return _wtol (str); }
EXTERN_C unsigned long StringToULongA (const char *str) { return atoul (str); }
EXTERN_C unsigned long StringToULongW (const WCHAR *str) { return _wtoul (str); }
EXTERN_C long long StringToLongLongA (const char *str) { return atoll (str); }
EXTERN_C long long StringToLongLongW (const WCHAR *str) { return _wtoll (str); }
EXTERN_C unsigned long long StringToULongLongA (const char *str) { return atou64 (str); }
EXTERN_C unsigned long long StringToULongLongW (const WCHAR *str) { return _wtou64 (str); }
EXTERN_C float StringToFloatA (const char *str) { return atof (str); }
EXTERN_C float StringToFloatW (const WCHAR *str) { return _wtof (str); }
EXTERN_C double StringToDoubleA (const char *str) { return atod (str); }
EXTERN_C double StringToDoubleW (const WCHAR *str) { return _wtod (str); }
#ifdef __cplusplus
int StringToInt (LPCSTR str) { return StringToIntA (str); }
int StringToInt (LPCWSTR str) { return StringToIntW (str); }
unsigned StringToUnsigned (LPCSTR str) { return StringToUnsignedA (str); }
unsigned StringToUnsigned (LPCWSTR str) { return StringToUnsignedW (str); }
bool StringToBool (LPCSTR str) { return StringToBoolA (str); }
bool StringToBool (LPCWSTR str) { return StringToBoolW (str); }
long StringToLong (LPCSTR str) { return StringToLongA (str); }
long StringToLong (LPCWSTR str) { return StringToLongW (str); }
unsigned long StringToULong (LPCSTR str) { return StringToULongA (str); }
unsigned long StringToULong (LPCWSTR str) { return StringToULongW (str); }
long long StringToLongLong (LPCSTR str) { return StringToLongLongA (str); }
long long StringToLongLong (LPCWSTR str) { return StringToLongLongW (str); }
unsigned long long StringToULongLong (LPCSTR str) { return StringToULongLongA (str); }
unsigned long long StringToULongLong (LPCWSTR str) { return StringToULongLongW (str); }
float StringToFloat (LPCSTR str) { return StringToFloatA (str); }
float StringToFloat (LPCWSTR str) { return StringToFloatW (str); }
double StringToDouble (LPCSTR str) { return StringToDoubleA (str); }
double StringToDouble (LPCWSTR str) { return StringToDoubleW (str); }
#endif
#if defined (__cplusplus) && defined (__cplusplus_cli)
using namespace System;
#define toInt(_String_Managed_Object_) Int32::Parse (_String_Managed_Object_)
#define objToInt(_Object_Managed_) Convert::ToInt32 (_Object_Managed_)
#define toDouble(_String_Managed_Object_) Double::Parse (_String_Managed_Object_)
#define objToDouble(_Object_Managed_) Convert::ToDouble (_Object_Managed_)
#define toBool(_String_Managed_Object_) Boolean::Parse (_String_Managed_Object_)
bool objToBool (Object ^result)
{
if (!result) return false;
try
{
String ^strValue = safe_cast <String ^> (result);
return (strValue->ToLower () == "on");
}
catch (InvalidCastException ^)
{
try
{
return Convert::ToBoolean (result);
}
catch (InvalidCastException ^)
{
return false;
}
}
return false;
}
#define toDateTime(_String_Managed_Object_) DateTime::Parse (_String_Managed_Object_)
#define toDateTimeObj(_Object_Managed_) Convert::ToDateTime (_Object_Managed_)
#define objectToType(_Object_Managed_, _Type_Name_) Convert::To##_Type_Name_ (_Object_Managed_)
#endif