mirror of
https://github.com/modernw/App-Installer-For-Windows-8.x-Reset.git
synced 2026-04-11 17:57:19 +10:00
The module of package reading is tested.
This commit is contained in:
@@ -7,10 +7,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "appinstaller", "AppInstalle
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pkgread", "pkgread\pkgread.vcxproj", "{A7753282-AA16-43D9-8ACA-7065239DD702}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "prireader", "prireader\prireader.vcxproj", "{D8CFAA98-0A77-4C5B-A61B-11EF44206712}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dlltest", "dlltest\dlltest.vcxproj", "{F5CCB3AB-AC43-432A-862D-4F264760B09B}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "priread", "priread\priread.vcxproj", "{99D714D9-F40D-425B-BAFA-8B41C17971A5}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
@@ -35,14 +35,6 @@ Global
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702}.Release|x64.Build.0 = Release|x64
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702}.Release|x86.ActiveCfg = Release|Win32
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702}.Release|x86.Build.0 = Release|Win32
|
||||
{D8CFAA98-0A77-4C5B-A61B-11EF44206712}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{D8CFAA98-0A77-4C5B-A61B-11EF44206712}.Debug|x64.Build.0 = Debug|x64
|
||||
{D8CFAA98-0A77-4C5B-A61B-11EF44206712}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{D8CFAA98-0A77-4C5B-A61B-11EF44206712}.Debug|x86.Build.0 = Debug|Win32
|
||||
{D8CFAA98-0A77-4C5B-A61B-11EF44206712}.Release|x64.ActiveCfg = Release|x64
|
||||
{D8CFAA98-0A77-4C5B-A61B-11EF44206712}.Release|x64.Build.0 = Release|x64
|
||||
{D8CFAA98-0A77-4C5B-A61B-11EF44206712}.Release|x86.ActiveCfg = Release|Win32
|
||||
{D8CFAA98-0A77-4C5B-A61B-11EF44206712}.Release|x86.Build.0 = Release|Win32
|
||||
{F5CCB3AB-AC43-432A-862D-4F264760B09B}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{F5CCB3AB-AC43-432A-862D-4F264760B09B}.Debug|x64.Build.0 = Debug|x64
|
||||
{F5CCB3AB-AC43-432A-862D-4F264760B09B}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
@@ -51,6 +43,14 @@ Global
|
||||
{F5CCB3AB-AC43-432A-862D-4F264760B09B}.Release|x64.Build.0 = Release|x64
|
||||
{F5CCB3AB-AC43-432A-862D-4F264760B09B}.Release|x86.ActiveCfg = Release|Win32
|
||||
{F5CCB3AB-AC43-432A-862D-4F264760B09B}.Release|x86.Build.0 = Release|Win32
|
||||
{99D714D9-F40D-425B-BAFA-8B41C17971A5}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{99D714D9-F40D-425B-BAFA-8B41C17971A5}.Debug|x64.Build.0 = Debug|x64
|
||||
{99D714D9-F40D-425B-BAFA-8B41C17971A5}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{99D714D9-F40D-425B-BAFA-8B41C17971A5}.Debug|x86.Build.0 = Debug|Win32
|
||||
{99D714D9-F40D-425B-BAFA-8B41C17971A5}.Release|x64.ActiveCfg = Release|x64
|
||||
{99D714D9-F40D-425B-BAFA-8B41C17971A5}.Release|x64.Build.0 = Release|x64
|
||||
{99D714D9-F40D-425B-BAFA-8B41C17971A5}.Release|x86.ActiveCfg = Release|Win32
|
||||
{99D714D9-F40D-425B-BAFA-8B41C17971A5}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
301
dlltest/main.cpp
301
dlltest/main.cpp
@@ -2,75 +2,252 @@
|
||||
#include "..\pkgread\pkgread.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <thread>
|
||||
|
||||
void read_package (const std::wstring &filepath)
|
||||
{
|
||||
package_reader pr (filepath);
|
||||
std::wcout << L"Is Valid: " << (pr.valid () ? L"true" : L"false") << std::endl;
|
||||
std::wcout << L"Package Type: ";
|
||||
switch (pr.package_type ())
|
||||
{
|
||||
case PKGTYPE_APPX: std::wcout << L"Appx"; break;
|
||||
case PKGTYPE_BUNDLE: std::wcout << L"AppxBundle"; break;
|
||||
}
|
||||
std::wcout << std::endl;
|
||||
std::wcout << L"Package Role: ";
|
||||
switch (pr.package_role ())
|
||||
{
|
||||
case PKGROLE_APPLICATION: std::wcout << L"Application"; break;
|
||||
case PKGROLE_FRAMEWORK: std::wcout << L"Framework"; break;
|
||||
case PKGROLE_RESOURCE: std::wcout << L"Resource"; break;
|
||||
case PKGROLE_UNKNOWN: std::wcout << L"Unknown"; break;
|
||||
}
|
||||
std::wcout << std::endl;
|
||||
auto id = pr.get_identity ();
|
||||
std::wcout << L"Identity" << std::endl;
|
||||
std::wcout << L"\tName: " << id.name () << std::endl;
|
||||
std::wcout << L"\tPublisher: " << id.publisher () << std::endl;
|
||||
auto ver = id.version ();
|
||||
std::wcout << L"\tVersion: " << ver.major << L"." << ver.minor << L"." << ver.build << L"." << ver.revision << std::endl;
|
||||
std::wcout << L"\tPackage Family Name: " << id.package_family_name () << std::endl;
|
||||
std::wcout << L"\tPackage Full Name: " << id.package_full_name () << std::endl;
|
||||
std::wcout << L"\tResource Id: " << id.resource_id () << std::endl;
|
||||
std::wcout << L"\tArchitecture: ";
|
||||
DWORD archi = id.architecture ();
|
||||
for (size_t i = 0xF; i > 0; i /= 2)
|
||||
{
|
||||
if (archi & i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case PKG_ARCHITECTURE_ARM: std::wcout << "Arm"; break;
|
||||
case PKG_ARCHITECTURE_ARM64: std::wcout << "Arm64"; break;
|
||||
case PKG_ARCHITECTURE_NEUTRAL: std::wcout << "Neutral"; break;
|
||||
case PKG_ARCHITECTURE_X64: std::wcout << "x64"; break;
|
||||
case PKG_ARCHITECTURE_X86: std::wcout << "x86"; break;
|
||||
default: continue;
|
||||
}
|
||||
std::wcout << L", ";
|
||||
}
|
||||
}
|
||||
std::wcout << std::endl;
|
||||
ver = id.version (true);
|
||||
std::wcout << L"\tVersion (Appx): " << ver.major << L"." << ver.minor << L"." << ver.build << L"." << ver.revision << std::endl;
|
||||
std::wcout << L"Properties" << std::endl;
|
||||
auto prop = pr.get_properties ();
|
||||
std::wcout << L"\tDisplay Name: " << prop.display_name () << std::endl;
|
||||
std::wcout << L"\tDescription: " << prop.description () << std::endl;
|
||||
std::wcout << L"\tPublisher Display Name: " << prop.publisher_display_name () << std::endl;
|
||||
std::wcout << L"\tLogo: " << prop.logo () << std::endl;
|
||||
std::wcout << L"\tFramework: " << (prop.framework () ? L"true" : L"false") << std::endl;
|
||||
std::wcout << L"\tResource Package: " << (prop.resource_package () ? L"true" : L"false") << std::endl;
|
||||
auto preq = pr.get_prerequisites ();
|
||||
std::wcout << L"Prerequisites" << std::endl;
|
||||
ver = preq.os_min_version ();
|
||||
std::wcout << L"\tOS Min Version: " << ver.major << L"." << ver.minor << L"." << ver.build << L"." << ver.revision << std::endl;
|
||||
ver = preq.os_max_version_tested ();
|
||||
std::wcout << L"\tOS Max Version Tested: " << ver.major << L"." << ver.minor << L"." << ver.build << L"." << ver.revision << std::endl;
|
||||
std::wcout << L"Resources" << std::endl;
|
||||
auto res = pr.get_resources ();
|
||||
{
|
||||
std::vector <std::wstring> langs;
|
||||
std::vector <UINT32> scales;
|
||||
std::vector <DWORD> dx_levels;
|
||||
res.languages (langs);
|
||||
res.scales (scales);
|
||||
res.dx_feature_level (dx_levels);
|
||||
std::wcout << L"\tSupported Languages: ";
|
||||
for (auto &it : langs)
|
||||
{
|
||||
std::wcout << it << L", ";
|
||||
}
|
||||
std::wcout << std::endl;
|
||||
std::wcout << L"\tSupported Scales: ";
|
||||
for (auto &it : scales)
|
||||
{
|
||||
std::wcout << it << L", ";
|
||||
}
|
||||
std::wcout << std::endl;
|
||||
std::wcout << L"\tSupported Languages: ";
|
||||
for (auto &it : dx_levels)
|
||||
{
|
||||
switch (it)
|
||||
{
|
||||
case PKG_RESOURCES_DXFEATURE_LEVEL9: std::wcout << L"9, "; break;
|
||||
case PKG_RESOURCES_DXFEATURE_LEVEL10: std::wcout << L"10, "; break;
|
||||
case PKG_RESOURCES_DXFEATURE_LEVEL11: std::wcout << L"11, "; break;
|
||||
case PKG_RESOURCES_DXFEATURE_LEVEL12: std::wcout << L"12, "; break;
|
||||
}
|
||||
}
|
||||
std::wcout << std::endl;
|
||||
}
|
||||
std::wcout << L"Capabilities" << std::endl;
|
||||
auto cap = pr.get_capabilities ();
|
||||
{
|
||||
std::vector <std::wstring> caps;
|
||||
std::vector <std::wstring> devicecaps;
|
||||
cap.capabilities_name (caps);
|
||||
cap.device_capabilities (devicecaps);
|
||||
std::wcout << L"\tCapabilities: ";
|
||||
for (auto &it : caps)
|
||||
{
|
||||
std::wcout << it << L", ";
|
||||
}
|
||||
std::wcout << std::endl;
|
||||
std::wcout << L"\tDevice Capabilities: ";
|
||||
for (auto &it : devicecaps)
|
||||
{
|
||||
std::wcout << it << L", ";
|
||||
}
|
||||
std::wcout << std::endl;
|
||||
}
|
||||
std::wcout << L"Applications" << std::endl;
|
||||
auto apps = pr.get_applications ();
|
||||
{
|
||||
std::vector <package_reader::application> appmaps;
|
||||
apps.get (appmaps);
|
||||
size_t cnt = 1;
|
||||
for (auto &it : appmaps)
|
||||
{
|
||||
std::wcout << L"\tApplication" << cnt ++ << std::endl;
|
||||
for (auto &it_s : it)
|
||||
{
|
||||
std::wcout << L"\t\t" << it_s.first << L": " << it_s.second << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
auto deps = pr.get_dependencies ();
|
||||
std::wcout << L"Dependencies" << std::endl;
|
||||
{
|
||||
std::vector <package_reader::dependency> deparr;
|
||||
deps.get (deparr);
|
||||
size_t cnt = 1;
|
||||
for (auto &it : deparr)
|
||||
{
|
||||
std::wcout << L"\tDependency" << cnt ++ << std::endl;
|
||||
std::wcout << L"\t\tName: " << it.name << std::endl;
|
||||
std::wcout << L"\t\tPublisher: " << it.publisher << std::endl;
|
||||
ver = it.vermin;
|
||||
std::wcout << L"\t\tMin Version: " << ver.major << L"." << ver.minor << L"." << ver.build << L"." << ver.revision << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct head
|
||||
{
|
||||
CHAR szMagic [8];
|
||||
WORD wPlaceholder1, // 0
|
||||
wPlaceholder2; // 1
|
||||
DWORD dwFileSize,
|
||||
dwToCOffset,
|
||||
dwSectStartOffset;
|
||||
WORD wSectCount,
|
||||
wPlaceholder3; // 0xFFFF
|
||||
DWORD dwPlaceholder4; // 0
|
||||
};
|
||||
struct footer
|
||||
{
|
||||
DWORD dwChkCode, // 0xDEFFFADE
|
||||
dwTotalFileSize;
|
||||
};
|
||||
struct tocentry
|
||||
{
|
||||
CHAR szIdentifier [16] = {0};
|
||||
WORD wFlags = 0;
|
||||
WORD wSectFlags = 0;
|
||||
DWORD dwSectQualifier = 0;
|
||||
DWORD dwSectOffset = 0;
|
||||
DWORD dwSectLength = 0;
|
||||
};
|
||||
// #pragma pack (push, 1)
|
||||
struct section_header
|
||||
{
|
||||
CHAR szIdentifier [16] = {0};
|
||||
DWORD dwQualifier = 0;
|
||||
WORD wFlags = 0;
|
||||
DWORD dwLength = 0;
|
||||
DWORD dwPlaceholder1 = -1; // 0
|
||||
};
|
||||
struct section_check
|
||||
{
|
||||
DWORD dwChkCode = 0, // 0xDEF5FADE
|
||||
dwSectLength = 0;
|
||||
};
|
||||
|
||||
int main (int argc, char *argv [])
|
||||
{
|
||||
// 1. 创建 Reader 对象
|
||||
HPKGREAD hReader = CreatePackageReader ();
|
||||
if (!hReader) {
|
||||
std::wcerr << L"CreatePackageReader failed!" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
std::wcout << L"CreatePackageReader succeeded!" << std::endl;
|
||||
|
||||
// 2. 加载包文件
|
||||
setlocale (LC_ALL, "");
|
||||
std::wcout.imbue (std::locale ("", LC_CTYPE));
|
||||
std::wcout << L"Please enter the file path: " << std::endl;
|
||||
std::wcout << L"\\> ";
|
||||
std::wstring pkgPathStr;
|
||||
std::getline (std::wcin, pkgPathStr);
|
||||
if (!pkgPathStr.empty () && pkgPathStr.front () == L'\"' && pkgPathStr.back () == L'\"' && pkgPathStr.size () >= 2) {
|
||||
pkgPathStr = pkgPathStr.substr (1, pkgPathStr.size () - 2);
|
||||
std::wstring pkgPathStr = L"E:\\Profiles\\Bruce\\Desktop\\resources.pri";
|
||||
//std::getline (std::wcin, pkgPathStr);
|
||||
pkgPathStr.erase (
|
||||
std::remove (pkgPathStr.begin (), pkgPathStr.end (), L'\"'),
|
||||
pkgPathStr.end ()
|
||||
);
|
||||
HANDLE hFile = CreateFileW (
|
||||
pkgPathStr.c_str (), // 文件名
|
||||
GENERIC_READ, // 只读
|
||||
FILE_SHARE_READ, // 允许其他进程读取
|
||||
NULL, // 默认安全属性
|
||||
OPEN_EXISTING, // 必须文件存在
|
||||
FILE_ATTRIBUTE_NORMAL, // 普通文件
|
||||
NULL // 无模板
|
||||
);
|
||||
head header;
|
||||
footer foot;
|
||||
DWORD headRead = 0, footRead = 0;
|
||||
ReadFile (hFile, &header, sizeof (header), &headRead, NULL);
|
||||
SetFilePointer (hFile, header.dwFileSize - 16, NULL, FILE_BEGIN);
|
||||
ReadFile (hFile, &foot, sizeof (foot), &footRead, NULL);
|
||||
SetFilePointer (hFile, header.dwToCOffset, NULL, FILE_BEGIN);
|
||||
std::vector <tocentry> tocs;
|
||||
for (size_t i = 0; i < header.wSectCount; i ++)
|
||||
{
|
||||
tocentry toc;
|
||||
DWORD dwRead;
|
||||
ReadFile (hFile, &toc, sizeof (toc), &dwRead, NULL);
|
||||
tocs.push_back (toc);
|
||||
}
|
||||
LPCWSTR pkgPath = pkgPathStr.c_str ();
|
||||
if (!LoadPackageFromFile (hReader, pkgPath)) {
|
||||
std::wcerr << L"LoadPackageFromFile failed for " << pkgPath << std::endl;
|
||||
DestroyPackageReader (hReader);
|
||||
return 1;
|
||||
for (size_t i = 0; i < header.wSectCount; i ++)
|
||||
{
|
||||
SetFilePointer (hFile, header.dwSectStartOffset + tocs [i].dwSectOffset, NULL, FILE_BEGIN);
|
||||
section_header sh;
|
||||
section_check sc;
|
||||
DWORD dwsh, dwsc;
|
||||
ReadFile (hFile, &sh, sizeof (sh), &dwsh, NULL);
|
||||
SetFilePointer (hFile, sh.dwLength - 16 - 24, NULL, FILE_CURRENT);
|
||||
ReadFile (hFile, &sc, sizeof (sc), &dwsc, NULL);
|
||||
SetFilePointer (hFile, 32 - sh.dwLength, NULL, FILE_CURRENT);
|
||||
//subsection ss;
|
||||
//ss.dwOffset = SetFilePointer (hFile, 0, NULL, FILE_CURRENT);
|
||||
//ss.dwLength = sh.dwLength - 16 - 24;
|
||||
//SetFilePointer (hFile, 32, NULL, FILE_CURRENT);
|
||||
}
|
||||
std::wcout << L"LoadPackageFromFile succeeded!" << std::endl;
|
||||
|
||||
// 3. 验证包类型
|
||||
WORD type = GetPackageType (hReader);
|
||||
std::wcout << L"Package Type: " << type << std::endl;
|
||||
|
||||
// 4. 验证包有效性
|
||||
BOOL valid = IsPackageValid (hReader);
|
||||
std::wcout << L"IsPackageValid: " << (valid ? L"True" : L"False") << std::endl;
|
||||
|
||||
// 5. 获取包名称
|
||||
LPWSTR pkgName = GetPackageIdentityStringValue (hReader, PKG_IDENTITY_NAME);
|
||||
if (pkgName)
|
||||
std::wcout << L"Package Name: " << pkgName << std::endl;
|
||||
else
|
||||
std::wcerr << L"GetPackageIdentityStringValue PKG_IDENTITY_NAME failed!" << std::endl;
|
||||
|
||||
// 6. 获取包版本
|
||||
VERSION ver;
|
||||
if (GetPackageIdentityVersion (hReader, &ver, FALSE)) {
|
||||
std::wcout << L"Package Version: " << ver.major << L"." << ver.minor << L"." << ver.build << L"." << ver.revision << std::endl;
|
||||
}
|
||||
else {
|
||||
std::wcerr << L"GetPackageIdentityVersion failed!" << std::endl;
|
||||
}
|
||||
|
||||
// 7. 列举所有 Application 名称
|
||||
HLIST_PVOID appList = GetAllApplicationItemsName ();
|
||||
if (appList) {
|
||||
std::wcout << L"Application Count: " << appList->dwSize << std::endl;
|
||||
for (DWORD i = 0; i < appList->dwSize; ++i) {
|
||||
LPCWSTR appName = (LPCWSTR)appList->alpVoid [i];
|
||||
if (appName)
|
||||
std::wcout << L"App[" << i << L"]: " << appName << std::endl;
|
||||
}
|
||||
DestroyApplicationItemsName (appList);
|
||||
}
|
||||
else {
|
||||
std::wcerr << L"GetAllApplicationItemsName failed!" << std::endl;
|
||||
}
|
||||
|
||||
// 8. 清理
|
||||
DestroyPackageReader (hReader);
|
||||
|
||||
CloseHandle (hFile);
|
||||
system ("pause");
|
||||
return 0;
|
||||
}
|
||||
@@ -766,7 +766,7 @@ HLIST_PVOID GetCapabilitiesList (_In_ HPKGREAD hReader)
|
||||
}
|
||||
} break;
|
||||
}
|
||||
size_t len = sizeof (LIST_PVOID) * sizeof (LPWSTR) * caps.size ();
|
||||
size_t len = sizeof (LIST_PVOID) + sizeof (LPWSTR) * caps.size ();
|
||||
HLIST_PVOID hList = (HLIST_PVOID)malloc (len);
|
||||
ZeroMemory (hList, len);
|
||||
hList->dwSize = 0;
|
||||
@@ -811,7 +811,7 @@ HLIST_PVOID GetDeviceCapabilitiesList (_In_ HPKGREAD hReader)
|
||||
}
|
||||
} break;
|
||||
}
|
||||
size_t len = sizeof (LIST_PVOID) * sizeof (LPWSTR) * caps.size ();
|
||||
size_t len = sizeof (LIST_PVOID) + sizeof (LPWSTR) * caps.size ();
|
||||
HLIST_PVOID hList = (HLIST_PVOID)malloc (len);
|
||||
ZeroMemory (hList, len);
|
||||
hList->dwSize = 0;
|
||||
@@ -831,3 +831,32 @@ void DestroyWStringList (_In_ HLIST_PVOID hList)
|
||||
}
|
||||
free (hList);
|
||||
}
|
||||
|
||||
// Prerequisite
|
||||
BOOL GetPackagePrerequisite (_In_ HPKGREAD hReader, _In_ LPCWSTR lpName, _Outptr_ VERSION *pVerRet)
|
||||
{
|
||||
auto ptr = ToPtrPackage (hReader);
|
||||
if (!ptr) return FALSE;
|
||||
switch (ptr->type ())
|
||||
{
|
||||
case PackageType::single: {
|
||||
auto reader = ptr->appx_reader ();
|
||||
auto pre = reader.prerequisites ();
|
||||
auto ver = pre.get_version (lpName ? lpName : L"");
|
||||
*pVerRet = VersionClassToStruct (ver);
|
||||
return !ver.empty ();
|
||||
} break;
|
||||
case PackageType::bundle: {
|
||||
auto br = ptr->bundle_reader ();
|
||||
CComPtr <IAppxPackageReader> ar;
|
||||
HRESULT hr = br.random_application_package (&ar);
|
||||
if (FAILED (hr)) return false;
|
||||
auto reader = appxreader (ar.p);
|
||||
auto pre = reader.prerequisites ();
|
||||
auto ver = pre.get_version (lpName ? lpName : L"");
|
||||
*pVerRet = VersionClassToStruct (ver);
|
||||
return !ver.empty ();
|
||||
} break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
@@ -12,35 +12,48 @@
|
||||
#define PKGREAD_API __declspec(dllimport)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
#define _DEFAULT_INIT_VALUE_(_init_value_) = _init_value_
|
||||
#ifdef PKGREAD_EXPORTS
|
||||
#define _DEFAULT_INIT_VALUE_FORFUNC_(_init_value_) = _init_value_
|
||||
#else
|
||||
#define _DEFAULT_INIT_VALUE_FORFUNC_(_init_value_)
|
||||
#endif
|
||||
#ifdef PKGREAD_EXPORTS
|
||||
#define _DEFAULT_INIT_VALUE_FORFUNC_(_init_value_) = _init_value_
|
||||
#else
|
||||
#define _DEFAULT_INIT_VALUE_FORFUNC_(_init_value_)
|
||||
#endif
|
||||
#else
|
||||
#define _DEFAULT_INIT_VALUE_(_init_value_)
|
||||
#define _DEFAULT_INIT_VALUE_FORFUNC_(_init_value_)
|
||||
#endif
|
||||
|
||||
#if defined (__cplusplus) && defined (PKGREAD_EXPORTS)
|
||||
#include <iostream>
|
||||
#endif
|
||||
|
||||
#ifndef _TYPE_STRUCT_VERSION_
|
||||
#define _TYPE_STRUCT_VERSION_
|
||||
typedef struct _VERSION
|
||||
typedef struct _VERSION
|
||||
{
|
||||
UINT16 major _DEFAULT_INIT_VALUE_ (0),
|
||||
minor _DEFAULT_INIT_VALUE_ (0),
|
||||
build _DEFAULT_INIT_VALUE_ (0),
|
||||
revision _DEFAULT_INIT_VALUE_ (0);
|
||||
#if defined (__cplusplus) && defined (PKGREAD_EXPORTS)
|
||||
_VERSION (UINT16 major = 0, UINT16 minor = 0, UINT16 build = 0, UINT16 revision = 0):
|
||||
major (major), minor (minor), build (build), revision (revision) {}
|
||||
friend std::ostream &operator << (std::ostream &o, const _VERSION &v)
|
||||
{
|
||||
#if defined (__cplusplus) && defined (PKGREAD_EXPORTS)
|
||||
_VERSION (UINT16 major = 0, UINT16 minor = 0, UINT16 build = 0, UINT16 revision = 0):
|
||||
major (major), minor (minor), build (build), revision (revision) {}
|
||||
#endif
|
||||
UINT16 major _DEFAULT_INIT_VALUE_ (0),
|
||||
minor _DEFAULT_INIT_VALUE_ (0),
|
||||
build _DEFAULT_INIT_VALUE_ (0),
|
||||
revision _DEFAULT_INIT_VALUE_ (0);
|
||||
} VERSION;
|
||||
return o << v.major << "." << v.minor << "." << v.build << "." << v.revision;
|
||||
}
|
||||
friend std::wostream &operator << (std::wostream &o, const _VERSION &v)
|
||||
{
|
||||
return o << v.major << L"." << v.minor << L"." << v.build << L"." << v.revision;
|
||||
}
|
||||
#endif
|
||||
} VERSION;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#ifndef _TYPE_STRUCT_LIST_PVOID_
|
||||
@@ -106,6 +119,11 @@ extern "C"
|
||||
// 获取身份信息能获取文本值的项。支持 PKG_IDENTITY_* 前缀的宏 NAME, PUBLISHER, PACKAGEFAMILYNAME, PACKAGEFULLNAME, RESOURCEID。
|
||||
// 当与 PKG_IDENTITY_BUNDLE_GETAPPXINFO 通过位或结合时,则获取 AppxBundle 中某一个应用包。
|
||||
PKGREAD_API LPWSTR GetPackageIdentityStringValue (_In_ HPKGREAD hReader, _In_ DWORD dwName);
|
||||
#define GetPackageIdentityName(_In_hReader_) GetPackageIdentityStringValue (_In_hReader_, PKG_IDENTITY_NAME)
|
||||
#define GetPackageIdentityPublisher(_In_hReader_) GetPackageIdentityStringValue (_In_hReader_, PKG_IDENTITY_PUBLISHER)
|
||||
#define GetPackageIdentityPackageFamilyName(_In_hReader_) GetPackageIdentityStringValue (_In_hReader_, PKG_IDENTITY_PACKAGEFAMILYNAME)
|
||||
#define GetPackageIdentityPackageFullName(_In_hReader_) GetPackageIdentityStringValue (_In_hReader_, PKG_IDENTITY_PACKAGEFULLNAME)
|
||||
#define GetPackageIdentityResourceId(_In_hReader_) GetPackageIdentityStringValue (_In_hReader_, PKG_IDENTITY_RESOURCEID)
|
||||
// 获取身份信息。当 bGetSubPkgVer 为真,且打开的包为 AppxBundle 包,返回 AppxBundle 包中的某个应用包的版本号。
|
||||
PKGREAD_API BOOL GetPackageIdentityVersion (_In_ HPKGREAD hReader, _Out_ VERSION *pVersion, _In_ BOOL bGetSubPkgVer _DEFAULT_INIT_VALUE_FORFUNC_ (0));
|
||||
// 对于 AppxBundle 包,当传入的值有 PKG_IDENTITY_BUNDLE_GETAPPXINFO,则返回一个按位值,如 0b0011,则意味着支持 x86 和 x64
|
||||
@@ -123,14 +141,21 @@ extern "C"
|
||||
// 传入参数参考:https://learn.microsoft.com/en-us/windows/win32/api/appxpackaging/nf-appxpackaging-iappxmanifestproperties-getstringvalue
|
||||
// 可以使用宏 PKG_PROPERTIES_* 前缀的 DISPLAYNAME, DESCRIPTION, LOGO, PUBLISHER
|
||||
PKGREAD_API LPWSTR GetPackagePropertiesStringValue (_In_ HPKGREAD hReader, _In_ LPCWSTR lpName);
|
||||
#define GetPackagePropertiesDisplayName(_In_hReader_) GetPackagePropertiesStringValue (_In_hReader_, PKG_PROPERTIES_DISPLAYNAME)
|
||||
#define GetPackagePropertiesDescription(_In_hReader_) GetPackagePropertiesStringValue (_In_hReader_, PKG_PROPERTIES_DESCRIPTION)
|
||||
#define GetPackagePropertiesLogo(_In_hReader_) GetPackagePropertiesStringValue (_In_hReader_, PKG_PROPERTIES_LOGO)
|
||||
#define GetPackagePropertiesPublisher(_In_hReader_) GetPackagePropertiesStringValue (_In_hReader_, PKG_PROPERTIES_PUBLISHER)
|
||||
// 传入参数参考:https://learn.microsoft.com/zh-cn/windows/win32/api/appxpackaging/nf-appxpackaging-iappxmanifestproperties-getboolvalue
|
||||
// 可以使用宏 PKG_PROPERTIES_* 前缀的 FRAMEWORD, IS_RESOURCE (Windows 8.1 支持)
|
||||
PKGREAD_API HRESULT GetPackagePropertiesBoolValue (_In_ HPKGREAD hReader, _In_ LPCWSTR lpName, _Outptr_ BOOL *pRet);
|
||||
#define GetPackagePropertiesIsFramework(_In_hReader_, _Outptr_pRetValue_) GetPackagePropertiesBoolValue (_In_hReader_, PKG_PROPERTIES_FRAMEWORD, _Outptr_pRetValue_)
|
||||
#define GetPackagePropertiesIsResourcePackage(_In_hReader_, _Outptr_pRetValue_) GetPackagePropertiesBoolValue (_In_hReader_, PKG_PROPERTIES_IS_RESOURCE, _Outptr_pRetValue_)
|
||||
// Applications
|
||||
// 注意:由于读取 Application 在官方 API 中是枚举类型,只能枚举一次。
|
||||
// 所以请预先安排好需要的信息,并在枚举时进行缓存。
|
||||
// 添加和删除的请参考这些:https://learn.microsoft.com/en-us/windows/win32/api/appxpackaging/nf-appxpackaging-iappxmanifestapplication-getstringvalue
|
||||
// DLL 本身支持:Id, DisplayName, BackgroundColor, ForegroundText, ShortName, Square44x44Logo
|
||||
// 注:一定会保留项:AppUserModelID。这是必须项。
|
||||
PKGREAD_API BOOL AddPackageApplicationItemGetName (_In_ LPCWSTR lpName);
|
||||
// 移除不需要的信息项名。
|
||||
PKGREAD_API BOOL RemovePackageApplicationItemGetName (_In_ LPCWSTR lpName);
|
||||
@@ -220,65 +245,12 @@ extern "C"
|
||||
#define DestroyCapabilitiesList DestroyWStringList
|
||||
#define DestroyDeviceCapabilitiesList DestroyWStringList
|
||||
|
||||
#if defined (__cplusplus) && defined (PKGREAD_EXPORTS)
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
class package_info
|
||||
{
|
||||
private:
|
||||
HPKGREAD hReader = nullptr;
|
||||
std::wstring filepath = L"";
|
||||
struct deconstr
|
||||
{
|
||||
std::function <void ()> endtask = nullptr;
|
||||
deconstr (std::function <void ()> pf): endtask (pf) {}
|
||||
~deconstr () { if (endtask) endtask (); }
|
||||
};
|
||||
public:
|
||||
class identity
|
||||
{
|
||||
private:
|
||||
HPKGREAD &hReader;
|
||||
public:
|
||||
identity (HPKGREAD hReader): hReader (hReader) {}
|
||||
std::wstring string_value (DWORD dwName) const
|
||||
{
|
||||
LPWSTR lpstr = nullptr;
|
||||
deconstr rel ([&lpstr] () {
|
||||
if (lpstr) free (lpstr);
|
||||
lpstr = nullptr;
|
||||
});
|
||||
lpstr = GetPackageIdentityStringValue (hReader, dwName);
|
||||
return lpstr;
|
||||
}
|
||||
VERSION version (bool read_subpkg_ver = false) const
|
||||
{
|
||||
VERSION ver;
|
||||
GetPackageIdentityVersion (hReader, &ver, read_subpkg_ver);
|
||||
return ver;
|
||||
}
|
||||
DWORD architecture () const
|
||||
{
|
||||
DWORD dw = 0;
|
||||
GetPackageIdentityArchitecture (hReader, &dw);
|
||||
return dw;
|
||||
}
|
||||
};
|
||||
package_info (): hReader (CreatePackageReader ()) {}
|
||||
~package_info () { DestroyPackageReader (hReader); hReader = nullptr; }
|
||||
std::wstring file () const { return filepath; }
|
||||
bool file (const std::wstring &path)
|
||||
{
|
||||
return LoadPackageFromFile (hReader, (filepath = path).c_str ());
|
||||
}
|
||||
WORD package_type () const { return GetPackageType (hReader); }
|
||||
bool valid () const { return hReader && IsPackageValid (hReader); }
|
||||
WORD package_role () const { return GetPackageRole (hReader); }
|
||||
identity get_identity () const { return identity (hReader); }
|
||||
|
||||
};
|
||||
#endif
|
||||
// Prerequisite
|
||||
#define PKG_PREREQUISITE_OS_MIN_VERSION L"OSMinVersion"
|
||||
#define PKG_PREREQUISITE_OS_MAX_VERSION_TESTED L"OSMaxVersionTested"
|
||||
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_)
|
||||
|
||||
#ifdef _DEFAULT_INIT_VALUE_
|
||||
#undef _DEFAULT_INIT_VALUE_
|
||||
@@ -290,4 +262,332 @@ extern "C"
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#if defined (__cplusplus) && !defined (PKGREAD_EXPORTS)
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <cstring>
|
||||
class package_reader
|
||||
{
|
||||
private:
|
||||
HPKGREAD hReader = nullptr;
|
||||
std::wstring filepath = L"";
|
||||
struct deconstr
|
||||
{
|
||||
std::function <void ()> endtask = nullptr;
|
||||
deconstr (std::function <void ()> pf): endtask (pf) {}
|
||||
~deconstr () { if (endtask) endtask (); }
|
||||
};
|
||||
public:
|
||||
class base_subitems
|
||||
{
|
||||
protected:
|
||||
HPKGREAD &hReader;
|
||||
public:
|
||||
base_subitems (HPKGREAD &hReader): hReader (hReader) {}
|
||||
};
|
||||
class identity: public base_subitems
|
||||
{
|
||||
using base = base_subitems;
|
||||
public:
|
||||
using base::base;
|
||||
std::wstring string_value (DWORD dwName) const
|
||||
{
|
||||
LPWSTR lpstr = nullptr;
|
||||
deconstr rel ([&lpstr] () {
|
||||
if (lpstr) free (lpstr);
|
||||
lpstr = nullptr;
|
||||
});
|
||||
lpstr = GetPackageIdentityStringValue (hReader, dwName);
|
||||
return lpstr ? lpstr : L"";
|
||||
}
|
||||
std::wstring name () const { return string_value (PKG_IDENTITY_NAME); }
|
||||
std::wstring publisher () const { return string_value (PKG_IDENTITY_PUBLISHER); }
|
||||
std::wstring package_family_name () const { return string_value (PKG_IDENTITY_PACKAGEFAMILYNAME); }
|
||||
std::wstring package_full_name () const { return string_value (PKG_IDENTITY_PACKAGEFULLNAME); }
|
||||
std::wstring resource_id () const { return string_value (PKG_IDENTITY_RESOURCEID); }
|
||||
VERSION version (bool read_subpkg_ver = false) const { VERSION ver; GetPackageIdentityVersion (hReader, &ver, read_subpkg_ver); return ver; }
|
||||
DWORD architecture () const { DWORD dw = 0; GetPackageIdentityArchitecture (hReader, &dw); return dw; }
|
||||
};
|
||||
class properties: public base_subitems
|
||||
{
|
||||
using base = base_subitems;
|
||||
public:
|
||||
using base::base;
|
||||
std::wstring string_value (const std::wstring &swName) const
|
||||
{
|
||||
LPWSTR lpstr = nullptr;
|
||||
deconstr rel ([&lpstr] () {
|
||||
if (lpstr) free (lpstr);
|
||||
lpstr = nullptr;
|
||||
});
|
||||
lpstr = GetPackagePropertiesStringValue (hReader, swName.c_str ());
|
||||
return lpstr ? lpstr : L"";
|
||||
}
|
||||
bool bool_value (const std::wstring &swName, bool bRetWhenFailed = false) const
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
HRESULT hr = GetPackagePropertiesBoolValue (hReader, swName.c_str (), &ret);
|
||||
if (FAILED (hr)) return bRetWhenFailed;
|
||||
else return ret != FALSE;
|
||||
}
|
||||
std::wstring display_name () const { return string_value (PKG_PROPERTIES_DISPLAYNAME); }
|
||||
std::wstring publisher_display_name () const { return string_value (PKG_PROPERTIES_PUBLISHER); }
|
||||
std::wstring description () const { return string_value (PKG_PROPERTIES_DESCRIPTION); }
|
||||
std::wstring logo () const { return string_value (PKG_PROPERTIES_LOGO); }
|
||||
bool framework () const { return bool_value (PKG_PROPERTIES_FRAMEWORD); }
|
||||
bool resource_package () const { return bool_value (PKG_PROPERTIES_IS_RESOURCE); }
|
||||
};
|
||||
class application: public std::map <std::wstring, std::wstring>
|
||||
{
|
||||
using base = std::map <std::wstring, std::wstring>;
|
||||
public:
|
||||
using base::base;
|
||||
std::wstring user_model_id () const { return this->find (L"AppUserModelID")->second; }
|
||||
friend bool operator == (const application &a1, const application &a2) { return !_wcsicmp (a1.user_model_id ().c_str (), a2.user_model_id ().c_str ()); }
|
||||
friend bool operator != (const application &a1, const application &a2) { return _wcsicmp (a1.user_model_id ().c_str (), a2.user_model_id ().c_str ()); }
|
||||
explicit operator bool () const { return this->user_model_id ().empty (); }
|
||||
std::wstring &operator [] (const std::wstring &key)
|
||||
{
|
||||
auto it = this->find (key);
|
||||
if (it == this->end ())
|
||||
{
|
||||
it = this->insert (std::make_pair (key, L"")).first;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
typename base::iterator find_case_insensitive (const std::wstring &key)
|
||||
{
|
||||
for (auto it = this->begin (); it != this->end (); ++it)
|
||||
{
|
||||
if (_wcsicmp (it->first.c_str (), key.c_str ()) == 0)
|
||||
return it;
|
||||
}
|
||||
return this->end ();
|
||||
}
|
||||
typename base::const_iterator find_case_insensitive (const std::wstring &key) const
|
||||
{
|
||||
for (auto it = this->begin (); it != this->end (); ++ it)
|
||||
{
|
||||
if (_wcsicmp (it->first.c_str (), key.c_str ()) == 0)
|
||||
return it;
|
||||
}
|
||||
return this->end ();
|
||||
}
|
||||
};
|
||||
class applications
|
||||
{
|
||||
private:
|
||||
HPKGREAD &hReader;
|
||||
HAPPENUMERATOR hList = nullptr;
|
||||
public:
|
||||
applications (HPKGREAD &hReader): hReader (hReader)
|
||||
{
|
||||
hList = GetPackageApplications (hReader);
|
||||
}
|
||||
~applications ()
|
||||
{
|
||||
if (hList) DestroyPackageApplications (hList);
|
||||
hList = nullptr;
|
||||
}
|
||||
size_t get (std::vector <application> &apps)
|
||||
{
|
||||
apps.clear ();
|
||||
if (!hList) return 0;
|
||||
HLIST_PVOID hMapList = ApplicationsToMap (hList);
|
||||
deconstr endt ([&hMapList] {
|
||||
if (hMapList) DestroyApplicationsMap (hMapList);
|
||||
hMapList = nullptr;
|
||||
});
|
||||
if (!hMapList) return 0;
|
||||
for (size_t i = 0; i < hMapList->dwSize; i ++)
|
||||
{
|
||||
HLIST_PVOID &hKeyValues = ((HLIST_PVOID *)hMapList->alpVoid) [i];
|
||||
application app;
|
||||
for (size_t j = 0; j < hKeyValues->dwSize; j ++)
|
||||
{
|
||||
HPAIR_PVOID &hPair = ((HPAIR_PVOID *)hKeyValues->alpVoid) [j];
|
||||
LPWSTR lpKey = (LPWSTR)hPair->lpKey;
|
||||
LPWSTR lpValue = (LPWSTR)hPair->lpValue;
|
||||
if (!lpKey || !*lpKey) continue;
|
||||
app [lpKey] = lpValue ? lpValue : L"";
|
||||
}
|
||||
apps.push_back (app);
|
||||
}
|
||||
return apps.size ();
|
||||
}
|
||||
};
|
||||
class capabilities: public base_subitems
|
||||
{
|
||||
using base = base_subitems;
|
||||
public:
|
||||
using base::base;
|
||||
size_t capabilities_name (std::vector <std::wstring> &output) const
|
||||
{
|
||||
output.clear ();
|
||||
HLIST_PVOID hList = GetCapabilitiesList (hReader);
|
||||
deconstr endt ([&hList] () {
|
||||
if (hList) DestroyCapabilitiesList (hList);
|
||||
hList = nullptr;
|
||||
});
|
||||
if (!hList) return 0;
|
||||
for (size_t i = 0; i < hList->dwSize; i ++)
|
||||
{
|
||||
LPWSTR lpstr = (LPWSTR)hList->alpVoid [i];
|
||||
if (!lpstr) continue;
|
||||
output.push_back (lpstr);
|
||||
}
|
||||
return output.size ();
|
||||
}
|
||||
size_t device_capabilities (std::vector <std::wstring> &output) const
|
||||
{
|
||||
output.clear ();
|
||||
HLIST_PVOID hList = GetDeviceCapabilitiesList (hReader);
|
||||
deconstr endt ([&hList] () {
|
||||
if (hList) DestroyDeviceCapabilitiesList (hList);
|
||||
hList = nullptr;
|
||||
});
|
||||
if (!hList) return 0;
|
||||
for (size_t i = 0; i < hList->dwSize; i ++)
|
||||
{
|
||||
LPWSTR lpstr = (LPWSTR)hList->alpVoid [i];
|
||||
if (!lpstr) continue;
|
||||
output.push_back (lpstr);
|
||||
}
|
||||
return output.size ();
|
||||
}
|
||||
};
|
||||
struct dependency
|
||||
{
|
||||
std::wstring name, publisher;
|
||||
VERSION vermin;
|
||||
dependency (const std::wstring &name = L"", const std::wstring &pub = L"", const VERSION &ver = VERSION ()):
|
||||
name (name), publisher (pub), vermin (ver) {}
|
||||
};
|
||||
class dependencies: public base_subitems
|
||||
{
|
||||
using base = base_subitems;
|
||||
public:
|
||||
using base::base;
|
||||
size_t get (std::vector <dependency> &output) const
|
||||
{
|
||||
auto hList = GetDependencesInfoList (hReader);
|
||||
deconstr rel ([&hList] () {
|
||||
DestroyDependencesInfoList (hList);
|
||||
});
|
||||
if (!hList) return 0;
|
||||
for (size_t i = 0; i < hList->dwSize; i ++)
|
||||
{
|
||||
DEPENDENCY_INFO &depinf = ((DEPENDENCY_INFO *)hList->aDepInfo) [i];
|
||||
if (!depinf.lpName || !*depinf.lpName) continue;
|
||||
output.push_back (dependency (depinf.lpName, depinf.lpPublisher ? depinf.lpPublisher : L"", depinf.verMin));
|
||||
}
|
||||
return output.size ();
|
||||
}
|
||||
};
|
||||
class resources: public base_subitems
|
||||
{
|
||||
using base = base_subitems;
|
||||
public:
|
||||
using base::base;
|
||||
size_t languages (std::vector <std::wstring> &langs) const
|
||||
{
|
||||
langs.clear ();
|
||||
auto hList = GetResourcesLanguages (hReader);
|
||||
deconstr rel ([&hList] () {
|
||||
if (hList) DestroyResourcesLanguagesList (hList);
|
||||
hList = nullptr;
|
||||
});
|
||||
if (!hList) return 0;
|
||||
for (size_t i = 0; i < hList->dwSize; i ++)
|
||||
{
|
||||
LPWSTR lpstr = ((LPWSTR *)hList->alpVoid) [i];
|
||||
if (lpstr && *lpstr) langs.push_back (std::wstring (lpstr));
|
||||
}
|
||||
return langs.size ();
|
||||
}
|
||||
size_t languages (std::vector <LCID> &langs) const
|
||||
{
|
||||
langs.clear ();
|
||||
auto hList = GetResourcesLanguagesToLcid (hReader);
|
||||
deconstr rel ([&hList] () {
|
||||
if (hList) DestroyResourcesLanguagesLcidList (hList);
|
||||
hList = nullptr;
|
||||
});
|
||||
if (!hList) return 0;
|
||||
for (size_t i = 0; i < hList->dwSize; i ++)
|
||||
{
|
||||
if (hList->aLcid [i]) langs.push_back (hList->aLcid [i]);
|
||||
}
|
||||
return langs.size ();
|
||||
}
|
||||
size_t scales (std::vector <UINT32> &output) const
|
||||
{
|
||||
output.clear ();
|
||||
auto hList = GetResourcesScales (hReader);
|
||||
deconstr rel ([&hList] () {
|
||||
if (hList) DestroyResourcesScalesList (hList);
|
||||
});
|
||||
if (!hList) return 0;
|
||||
for (size_t i = 0; i < hList->dwSize; i ++)
|
||||
{
|
||||
UINT32 s = hList->aUI32 [i];
|
||||
if (s) output.push_back (s);
|
||||
}
|
||||
return output.size ();
|
||||
}
|
||||
DWORD dx_feature_level () const { return GetResourcesDxFeatureLevels (hReader); }
|
||||
// 向数组添加的是以 PKG_RESOURCES_DXFEATURE_* 前缀的常量
|
||||
size_t dx_feature_level (std::vector <DWORD> &ret)
|
||||
{
|
||||
DWORD dx = dx_feature_level ();
|
||||
if (dx & PKG_RESOURCES_DXFEATURE_LEVEL9) ret.push_back (PKG_RESOURCES_DXFEATURE_LEVEL9);
|
||||
else if (dx & PKG_RESOURCES_DXFEATURE_LEVEL10) ret.push_back (PKG_RESOURCES_DXFEATURE_LEVEL10);
|
||||
else if (dx & PKG_RESOURCES_DXFEATURE_LEVEL11) ret.push_back (PKG_RESOURCES_DXFEATURE_LEVEL11);
|
||||
else if (dx & PKG_RESOURCES_DXFEATURE_LEVEL12) ret.push_back (PKG_RESOURCES_DXFEATURE_LEVEL12);
|
||||
return ret.size ();
|
||||
}
|
||||
};
|
||||
class prerequisites: public base_subitems
|
||||
{
|
||||
using base = base_subitems;
|
||||
public:
|
||||
using base::base;
|
||||
VERSION get_version (const std::wstring &name) const
|
||||
{
|
||||
VERSION ver;
|
||||
GetPackagePrerequisite (hReader, name.c_str (), &ver);
|
||||
return ver;
|
||||
}
|
||||
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); }
|
||||
};
|
||||
package_reader (): hReader (CreatePackageReader ()) {}
|
||||
package_reader (const std::wstring &fpath): hReader (CreatePackageReader ())
|
||||
{
|
||||
file (fpath);
|
||||
}
|
||||
~package_reader () { DestroyPackageReader (hReader); hReader = nullptr; }
|
||||
std::wstring file () const { return filepath; }
|
||||
bool file (const std::wstring &path)
|
||||
{
|
||||
return LoadPackageFromFile (hReader, (filepath = path).c_str ());
|
||||
}
|
||||
// PKGTYPE_* 前缀常量
|
||||
WORD package_type () const { return GetPackageType (hReader); }
|
||||
bool valid () const { return hReader && IsPackageValid (hReader); }
|
||||
// PKGROLE_* 前缀常量
|
||||
WORD package_role () const { return GetPackageRole (hReader); }
|
||||
identity get_identity () { return identity (hReader); }
|
||||
properties get_properties () { return properties (hReader); }
|
||||
applications get_applications () { return applications (hReader); }
|
||||
capabilities get_capabilities () { return capabilities (hReader); }
|
||||
dependencies get_dependencies () { return dependencies (hReader); }
|
||||
resources get_resources () { return resources (hReader); }
|
||||
prerequisites get_prerequisites () { return prerequisites (hReader); }
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -512,7 +512,6 @@ namespace appx_info
|
||||
appx_preq (IAppxManifestReader *ptr = nullptr): com_info (nullptr) { set (ptr); }
|
||||
version os_min_version () const { return get_version (L"OSMinVersion"); }
|
||||
version os_max_version_tested () const { return get_version (L"OSMaxVersionTested"); }
|
||||
private:
|
||||
version get_version (const std::wstring &name) const
|
||||
{
|
||||
UINT64 u64 = 0;
|
||||
@@ -551,8 +550,10 @@ namespace appx_info
|
||||
if (lpstr) CoTaskMemFree (lpstr);
|
||||
lpstr = nullptr;
|
||||
});
|
||||
if (SUCCEEDED (p->GetStringValue (it.c_str (), &lpstr))) app [it] = lpstr;
|
||||
else app [it] = nullptr;
|
||||
if (std::wnstring (it) == std::wnstring (L"AppUserModelID")) continue;
|
||||
if (SUCCEEDED (p->GetStringValue (it.c_str (), &lpstr)) && lpstr)
|
||||
app [it] = lpstr;
|
||||
else app [it] = std::wstring ();
|
||||
}
|
||||
return app;
|
||||
});
|
||||
|
||||
@@ -102,6 +102,7 @@ static CriticalSection g_appcs;
|
||||
bool PushApplicationAttributeItem (const std::wstring &lpstr)
|
||||
{
|
||||
CreateScopedLock (g_appcs);
|
||||
if (std::wnstring (L"AppUserModelID") == lpstr) return false;
|
||||
size_t len1 = appitems.size ();
|
||||
push_unique <std::wstring> (appitems, lpstr, [] (const std::wstring &v1, const std::wstring &v2) -> bool {
|
||||
return std::wnstring (v1) == std::wnstring (v2);
|
||||
@@ -111,6 +112,7 @@ bool PushApplicationAttributeItem (const std::wstring &lpstr)
|
||||
bool RemoveApplicationAttributeItem (const std::wstring &lpstr)
|
||||
{
|
||||
CreateScopedLock (g_appcs);
|
||||
if (std::wnstring (L"AppUserModelID") == lpstr) return false;
|
||||
auto it = std::find_if (appitems.begin (), appitems.end (), [&] (const std::wstring &v) {
|
||||
return std::wnstring (v) == std::wnstring (lpstr);
|
||||
});
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
========================================================================
|
||||
动态链接库:prireader 项目概述
|
||||
动态链接库:priread 项目概述
|
||||
========================================================================
|
||||
|
||||
应用程序向导已为您创建了此 prireader DLL。
|
||||
应用程序向导已为您创建了此 priread DLL。
|
||||
|
||||
本文件概要介绍组成 prireader 应用程序的每个文件的内容。
|
||||
本文件概要介绍组成 priread 应用程序的每个文件的内容。
|
||||
|
||||
|
||||
prireader.vcxproj
|
||||
priread.vcxproj
|
||||
这是使用应用程序向导生成的 VC++ 项目的主项目文件,其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
|
||||
|
||||
prireader.vcxproj.filters
|
||||
priread.vcxproj.filters
|
||||
这是使用“应用程序向导”生成的 VC++ 项目筛选器文件。它包含有关项目文件与筛选器之间的关联信息。在 IDE 中,通过这种关联,在特定节点下以分组形式显示具有相似扩展名的文件。例如,“.cpp”文件与“源文件”筛选器关联。
|
||||
|
||||
prireader.cpp
|
||||
priread.cpp
|
||||
这是主 DLL 源文件。
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
其他标准文件:
|
||||
|
||||
StdAfx.h, StdAfx.cpp
|
||||
这些文件用于生成名为 prireader.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。
|
||||
这些文件用于生成名为 priread.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
其他注释:
|
||||
141
priread/prifile.h
Normal file
141
priread/prifile.h
Normal file
@@ -0,0 +1,141 @@
|
||||
#pragma once
|
||||
#include <atlbase.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
struct destruct
|
||||
{
|
||||
std::function <void ()> endtask = nullptr;
|
||||
destruct (std::function <void ()> init): endtask (init) {}
|
||||
~destruct () { if (endtask) endtask (); }
|
||||
};
|
||||
typedef struct LargeInt
|
||||
{
|
||||
LARGE_INTEGER val;
|
||||
LargeInt (LONGLONG v) { val.QuadPart = v; }
|
||||
operator LARGE_INTEGER() const { return val; }
|
||||
} lint;
|
||||
|
||||
struct head
|
||||
{
|
||||
CHAR szMagic [8] = {};
|
||||
WORD wPlaceholder1 = -1, // 0
|
||||
wPlaceholder2 = 0; // 1
|
||||
DWORD dwFileSize = 0,
|
||||
dwToCOffset = 0,
|
||||
dwSectStartOffset = 0;
|
||||
WORD wSectCount = 0,
|
||||
wPlaceholder3 = 0; // 0xFFFF
|
||||
DWORD dwPlaceholder4 = -1; // 0
|
||||
bool valid ()
|
||||
{
|
||||
CHAR m7 = szMagic [7];
|
||||
destruct endt ([this, m7] () {
|
||||
if (m7) szMagic [7] = m7;
|
||||
});
|
||||
szMagic [7] = '\0';
|
||||
if (!stricmp (szMagic, "mrm_pri")) return false;
|
||||
switch (m7)
|
||||
{
|
||||
case '0': case '1': case 'f': case 'F': break;
|
||||
default: return false;
|
||||
}
|
||||
if (wPlaceholder1 != 0) return false;
|
||||
if (wPlaceholder2 != 1) return false;
|
||||
if (wPlaceholder3 != 0xFFFF) return false;
|
||||
if (dwPlaceholder4 != 0) return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
struct foot
|
||||
{
|
||||
DWORD dwChkCode = 0, // 0xDEFFFADE
|
||||
dwTotalFileSize = 0;
|
||||
CHAR szMagic [8] = {};
|
||||
bool valid (const head &fh)
|
||||
{
|
||||
if (dwChkCode != 0xDEFFFADE) return false;
|
||||
if (dwTotalFileSize != fh.dwFileSize) return false;
|
||||
for (int i = 0; i < 8; i ++)
|
||||
{
|
||||
if (szMagic [i] != fh.szMagic [i] && tolower (szMagic [i]) != tolower (fh.szMagic [i])) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
struct tocentry
|
||||
{
|
||||
CHAR szIdentifier [16] = {0};
|
||||
WORD wFlags = 0;
|
||||
WORD wSectFlags = 0;
|
||||
DWORD dwSectQualifier = 0;
|
||||
DWORD dwSectOffset = 0;
|
||||
DWORD dwSectLength = 0;
|
||||
};
|
||||
struct section_header
|
||||
{
|
||||
CHAR szIdentifier [16] = {0};
|
||||
DWORD dwQualifier = 0;
|
||||
WORD wFlags = 0;
|
||||
DWORD dwLength = 0;
|
||||
DWORD dwPlaceholder1 = -1; // 0
|
||||
bool valid () const { return szIdentifier [0] && !dwPlaceholder1; }
|
||||
};
|
||||
struct section_check
|
||||
{
|
||||
DWORD dwChkCode = 0, // 0xDEF5FADE
|
||||
dwSectLength = 0;
|
||||
bool valid (const section_header &h) const { return dwChkCode == 0xDEF5FADE && dwSectLength == h.dwLength; }
|
||||
};
|
||||
struct substream
|
||||
{
|
||||
IStream *&ifile;
|
||||
UINT64 offset = 0,
|
||||
size = 0;
|
||||
substream (IStream *&ifile, UINT64 ofs = 0, UINT64 siz = 0): ifile (ifile), offset (ofs), size (siz) {}
|
||||
};
|
||||
struct section
|
||||
{
|
||||
section_header head;
|
||||
section_check foot;
|
||||
substream childst;
|
||||
};
|
||||
class prifile
|
||||
{
|
||||
private:
|
||||
IStream *pfile = nullptr;
|
||||
head header; foot footer;
|
||||
std::vector <tocentry> toclist;
|
||||
public:
|
||||
bool load (IStream *ifile)
|
||||
{
|
||||
if (!ifile) return false;
|
||||
header = head ();
|
||||
footer = foot ();
|
||||
ifile->Seek (lint (0), STREAM_SEEK_SET, nullptr);
|
||||
DWORD dwhead = 0, dwfoot = 0;
|
||||
ifile->Read (&header, sizeof (header), &dwhead);
|
||||
if (!dwhead) return false;
|
||||
if (!header.valid ()) return false;
|
||||
ifile->Seek (lint (header.dwFileSize - 16), STREAM_SEEK_SET, nullptr);
|
||||
ifile->Read (&footer, sizeof (footer), &dwfoot);
|
||||
if (!dwfoot) return false;
|
||||
if (!footer.valid (header)) return false;
|
||||
pfile = ifile;
|
||||
bool res = inittoc ();
|
||||
return true;
|
||||
}
|
||||
bool inittoc ()
|
||||
{
|
||||
toclist.clear ();
|
||||
pfile->Seek (lint (header.dwToCOffset), STREAM_SEEK_SET, nullptr);
|
||||
for (size_t i = 0; i < header.wSectCount; i ++)
|
||||
{
|
||||
tocentry toc;
|
||||
DWORD dwRead;
|
||||
pfile->Read (&toc, sizeof (toc), &dwRead);
|
||||
toclist.push_back (toc);
|
||||
}
|
||||
}
|
||||
};
|
||||
22
priread/priread.cpp
Normal file
22
priread/priread.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
// priread.cpp : 定义 DLL 应用程序的导出函数。
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "priread.h"
|
||||
|
||||
|
||||
// 这是导出变量的一个示例
|
||||
PRIREAD_API int npriread=0;
|
||||
|
||||
// 这是导出函数的一个示例。
|
||||
PRIREAD_API int fnpriread(void)
|
||||
{
|
||||
return 42;
|
||||
}
|
||||
|
||||
// 这是已导出类的构造函数。
|
||||
// 有关类定义的信息,请参阅 priread.h
|
||||
Cpriread::Cpriread()
|
||||
{
|
||||
return;
|
||||
}
|
||||
22
priread/priread.h
Normal file
22
priread/priread.h
Normal file
@@ -0,0 +1,22 @@
|
||||
// 下列 ifdef 块是创建使从 DLL 导出更简单的
|
||||
// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 PRIREAD_EXPORTS
|
||||
// 符号编译的。在使用此 DLL 的
|
||||
// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
|
||||
// PRIREAD_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
|
||||
// 符号视为是被导出的。
|
||||
#ifdef PRIREAD_EXPORTS
|
||||
#define PRIREAD_API __declspec(dllexport)
|
||||
#else
|
||||
#define PRIREAD_API __declspec(dllimport)
|
||||
#endif
|
||||
|
||||
// 此类是从 priread.dll 导出的
|
||||
class PRIREAD_API Cpriread {
|
||||
public:
|
||||
Cpriread(void);
|
||||
// TODO: 在此添加您的方法。
|
||||
};
|
||||
|
||||
extern PRIREAD_API int npriread;
|
||||
|
||||
PRIREAD_API int fnpriread(void);
|
||||
@@ -19,9 +19,9 @@
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{D8CFAA98-0A77-4C5B-A61B-11EF44206712}</ProjectGuid>
|
||||
<ProjectGuid>{99D714D9-F40D-425B-BAFA-8B41C17971A5}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>prireader</RootNamespace>
|
||||
<RootNamespace>priread</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
@@ -34,7 +34,7 @@
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
@@ -86,7 +86,7 @@
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;PRIREADER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;PRIREAD_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
@@ -99,7 +99,7 @@
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;PRIREADER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;PRIREAD_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
@@ -114,7 +114,7 @@
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;PRIREADER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;PRIREAD_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
@@ -131,7 +131,7 @@
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;PRIREADER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;PRIREAD_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
@@ -145,9 +145,8 @@
|
||||
<Text Include="ReadMe.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="prifile.h" />
|
||||
<ClInclude Include="priread.h" />
|
||||
<ClInclude Include="prireader.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="targetver.h" />
|
||||
</ItemGroup>
|
||||
@@ -166,7 +165,7 @@
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="prireader.cpp" />
|
||||
<ClCompile Include="priread.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
@@ -24,21 +24,18 @@
|
||||
<ClInclude Include="targetver.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="prireader.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="priread.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="prifile.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="prireader.cpp">
|
||||
<ClCompile Include="priread.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
@@ -1,8 +1,8 @@
|
||||
// stdafx.cpp : 只包括标准包含文件的源文件
|
||||
// prireader.pch 将作为预编译头
|
||||
// priread.pch 将作为预编译头
|
||||
// stdafx.obj 将包含预编译类型信息
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: 在 STDAFX.H 中引用任何所需的附加头文件,
|
||||
//而不是在此文件中引用
|
||||
//而不是在此文件中引用
|
||||
@@ -18,4 +18,3 @@
|
||||
#include <atlstr.h>
|
||||
|
||||
// TODO: 在此处引用程序需要的其他头文件
|
||||
#include <winres.h>
|
||||
@@ -1 +0,0 @@
|
||||
#pragma once
|
||||
@@ -1,22 +0,0 @@
|
||||
// prireader.cpp : 定义 DLL 应用程序的导出函数。
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "prireader.h"
|
||||
|
||||
|
||||
// 这是导出变量的一个示例
|
||||
PRIREADER_API int nprireader=0;
|
||||
|
||||
// 这是导出函数的一个示例。
|
||||
PRIREADER_API int fnprireader(void)
|
||||
{
|
||||
return 42;
|
||||
}
|
||||
|
||||
// 这是已导出类的构造函数。
|
||||
// 有关类定义的信息,请参阅 prireader.h
|
||||
Cprireader::Cprireader()
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
// 下列 ifdef 块是创建使从 DLL 导出更简单的
|
||||
// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 PRIREADER_EXPORTS
|
||||
// 符号编译的。在使用此 DLL 的
|
||||
// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
|
||||
// PRIREADER_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
|
||||
// 符号视为是被导出的。
|
||||
#ifdef PRIREADER_EXPORTS
|
||||
#define PRIREADER_API __declspec(dllexport)
|
||||
#else
|
||||
#define PRIREADER_API __declspec(dllimport)
|
||||
#endif
|
||||
|
||||
// 此类是从 prireader.dll 导出的
|
||||
class PRIREADER_API Cprireader {
|
||||
public:
|
||||
Cprireader(void);
|
||||
// TODO: 在此添加您的方法。
|
||||
};
|
||||
|
||||
extern PRIREADER_API int nprireader;
|
||||
|
||||
PRIREADER_API int fnprireader(void);
|
||||
@@ -1,14 +0,0 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by prireader.rc
|
||||
|
||||
// 新对象的下一组默认值
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
Reference in New Issue
Block a user