mirror of
https://github.com/modernw/App-Installer-For-Windows-8.x-Reset.git
synced 2026-06-14 03:16:38 +10:00
Update Shell
This commit is contained in:
+2
-2
@@ -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;
|
||||
|
||||
@@ -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 ());
|
||||
}
|
||||
@@ -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,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>
|
||||
@@ -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 ());
|
||||
}
|
||||
@@ -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
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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
@@ -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.
@@ -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 ();
|
||||
}
|
||||
@@ -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"";
|
||||
}
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user