The module of package reading is tested.

This commit is contained in:
Bruce
2025-10-18 13:58:35 +08:00
parent d6d8fc5b67
commit 53203e0401
20 changed files with 872 additions and 242 deletions

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
});

View File

@@ -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);
});

View File

@@ -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
View 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
View 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
View 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);

View File

@@ -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>

View File

@@ -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">

View File

@@ -1,8 +1,8 @@
// stdafx.cpp : 只包括标准包含文件的源文件
// prireader.pch 将作为预编译头
// priread.pch 将作为预编译头
// stdafx.obj 将包含预编译类型信息
#include "stdafx.h"
// TODO: 在 STDAFX.H 中引用任何所需的附加头文件,
//而不是在此文件中引用
//而不是在此文件中引用

View File

@@ -18,4 +18,3 @@
#include <atlstr.h>
// TODO: 在此处引用程序需要的其他头文件
#include <winres.h>

View File

@@ -1 +0,0 @@
#pragma once

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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