From 53203e04019c0cbdb69462677c5e870e6bc8cf55 Mon Sep 17 00:00:00 2001 From: Bruce Date: Sat, 18 Oct 2025 13:58:35 +0800 Subject: [PATCH] The module of package reading is tested. --- AppInstallerReset.sln | 20 +- dlltest/main.cpp | 301 +++++++++--- pkgread/pkgread.cpp | 33 +- pkgread/pkgread.h | 458 +++++++++++++++--- pkgread/readobj.h | 7 +- pkgread/stringres.h | 2 + {prireader => priread}/ReadMe.txt | 14 +- {prireader => priread}/dllmain.cpp | 0 priread/prifile.h | 141 ++++++ priread/priread.cpp | 22 + priread/priread.h | 22 + .../priread.vcxproj | 19 +- .../priread.vcxproj.filters | 11 +- {prireader => priread}/stdafx.cpp | 4 +- {prireader => priread}/stdafx.h | 1 - {prireader => priread}/targetver.h | 0 prireader/priread.h | 1 - prireader/prireader.cpp | 22 - prireader/prireader.h | 22 - prireader/resource.h | 14 - 20 files changed, 872 insertions(+), 242 deletions(-) rename {prireader => priread}/ReadMe.txt (75%) rename {prireader => priread}/dllmain.cpp (100%) create mode 100644 priread/prifile.h create mode 100644 priread/priread.cpp create mode 100644 priread/priread.h rename prireader/prireader.vcxproj => priread/priread.vcxproj (92%) rename prireader/prireader.vcxproj.filters => priread/priread.vcxproj.filters (89%) rename {prireader => priread}/stdafx.cpp (73%) rename {prireader => priread}/stdafx.h (95%) rename {prireader => priread}/targetver.h (100%) delete mode 100644 prireader/priread.h delete mode 100644 prireader/prireader.cpp delete mode 100644 prireader/prireader.h delete mode 100644 prireader/resource.h diff --git a/AppInstallerReset.sln b/AppInstallerReset.sln index 321a35f..1b9fb52 100644 --- a/AppInstallerReset.sln +++ b/AppInstallerReset.sln @@ -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 diff --git a/dlltest/main.cpp b/dlltest/main.cpp index 01cdc79..b24f3d4 100644 --- a/dlltest/main.cpp +++ b/dlltest/main.cpp @@ -2,75 +2,252 @@ #include "..\pkgread\pkgread.h" #include #include +#include +#include + +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 langs; + std::vector scales; + std::vector 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 caps; + std::vector 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 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 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 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; } \ No newline at end of file diff --git a/pkgread/pkgread.cpp b/pkgread/pkgread.cpp index d41959c..d01e03a 100644 --- a/pkgread/pkgread.cpp +++ b/pkgread/pkgread.cpp @@ -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 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; +} \ No newline at end of file diff --git a/pkgread/pkgread.h b/pkgread/pkgread.h index 81c55b8..4f09cd6 100644 --- a/pkgread/pkgread.h +++ b/pkgread/pkgread.h @@ -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 +#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 -#include -#include - class package_info - { - private: - HPKGREAD hReader = nullptr; - std::wstring filepath = L""; - struct deconstr - { - std::function endtask = nullptr; - deconstr (std::function 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 \ No newline at end of file +#if defined (__cplusplus) && !defined (PKGREAD_EXPORTS) +#include +#include +#include +#include +#include +#include +class package_reader +{ + private: + HPKGREAD hReader = nullptr; + std::wstring filepath = L""; + struct deconstr + { + std::function endtask = nullptr; + deconstr (std::function 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 + { + using base = std::map ; + 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 &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 &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 &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 &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 &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 &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 &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 &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 diff --git a/pkgread/readobj.h b/pkgread/readobj.h index a73e1ff..ff91359 100644 --- a/pkgread/readobj.h +++ b/pkgread/readobj.h @@ -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; }); diff --git a/pkgread/stringres.h b/pkgread/stringres.h index 6c58348..fa3fb27 100644 --- a/pkgread/stringres.h +++ b/pkgread/stringres.h @@ -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 (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); }); diff --git a/prireader/ReadMe.txt b/priread/ReadMe.txt similarity index 75% rename from prireader/ReadMe.txt rename to priread/ReadMe.txt index 4fe6aba..98d5062 100644 --- a/prireader/ReadMe.txt +++ b/priread/ReadMe.txt @@ -1,26 +1,26 @@ 锘======================================================================== - 鍔ㄦ侀摼鎺ュ簱锛歱rireader 椤圭洰姒傝堪 + 鍔ㄦ侀摼鎺ュ簱锛歱riread 椤圭洰姒傝堪 ======================================================================== -搴旂敤绋嬪簭鍚戝宸蹭负鎮ㄥ垱寤轰簡姝 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 鐨勯缂栬瘧绫诲瀷鏂囦欢銆 ///////////////////////////////////////////////////////////////////////////// 鍏朵粬娉ㄩ噴: diff --git a/prireader/dllmain.cpp b/priread/dllmain.cpp similarity index 100% rename from prireader/dllmain.cpp rename to priread/dllmain.cpp diff --git a/priread/prifile.h b/priread/prifile.h new file mode 100644 index 0000000..39e1f62 --- /dev/null +++ b/priread/prifile.h @@ -0,0 +1,141 @@ +#pragma once +#include +#include +#include +#include + +struct destruct +{ + std::function endtask = nullptr; + destruct (std::function 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 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); + } + } +}; \ No newline at end of file diff --git a/priread/priread.cpp b/priread/priread.cpp new file mode 100644 index 0000000..d89cbc9 --- /dev/null +++ b/priread/priread.cpp @@ -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; +} diff --git a/priread/priread.h b/priread/priread.h new file mode 100644 index 0000000..dc15979 --- /dev/null +++ b/priread/priread.h @@ -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); diff --git a/prireader/prireader.vcxproj b/priread/priread.vcxproj similarity index 92% rename from prireader/prireader.vcxproj rename to priread/priread.vcxproj index da5a034..227b2b3 100644 --- a/prireader/prireader.vcxproj +++ b/priread/priread.vcxproj @@ -19,9 +19,9 @@ - {D8CFAA98-0A77-4C5B-A61B-11EF44206712} + {99D714D9-F40D-425B-BAFA-8B41C17971A5} Win32Proj - prireader + priread 8.1 @@ -34,7 +34,7 @@ DynamicLibrary false - v120 + v140 true Unicode @@ -86,7 +86,7 @@ Use Level3 Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;PRIREADER_EXPORTS;%(PreprocessorDefinitions) + WIN32;_DEBUG;_WINDOWS;_USRDLL;PRIREAD_EXPORTS;%(PreprocessorDefinitions) true @@ -99,7 +99,7 @@ Use Level3 Disabled - _DEBUG;_WINDOWS;_USRDLL;PRIREADER_EXPORTS;%(PreprocessorDefinitions) + _DEBUG;_WINDOWS;_USRDLL;PRIREAD_EXPORTS;%(PreprocessorDefinitions) true @@ -114,7 +114,7 @@ MaxSpeed true true - WIN32;NDEBUG;_WINDOWS;_USRDLL;PRIREADER_EXPORTS;%(PreprocessorDefinitions) + WIN32;NDEBUG;_WINDOWS;_USRDLL;PRIREAD_EXPORTS;%(PreprocessorDefinitions) true @@ -131,7 +131,7 @@ MaxSpeed true true - NDEBUG;_WINDOWS;_USRDLL;PRIREADER_EXPORTS;%(PreprocessorDefinitions) + NDEBUG;_WINDOWS;_USRDLL;PRIREAD_EXPORTS;%(PreprocessorDefinitions) true @@ -145,9 +145,8 @@ + - - @@ -166,7 +165,7 @@ - + Create Create diff --git a/prireader/prireader.vcxproj.filters b/priread/priread.vcxproj.filters similarity index 89% rename from prireader/prireader.vcxproj.filters rename to priread/priread.vcxproj.filters index 9b749c6..9b04e58 100644 --- a/prireader/prireader.vcxproj.filters +++ b/priread/priread.vcxproj.filters @@ -24,21 +24,18 @@ 澶存枃浠 - - 澶存枃浠 - - - 澶存枃浠 - 澶存枃浠 + + 澶存枃浠 + 婧愭枃浠 - + 婧愭枃浠 diff --git a/prireader/stdafx.cpp b/priread/stdafx.cpp similarity index 73% rename from prireader/stdafx.cpp rename to priread/stdafx.cpp index 4886866..85e805e 100644 --- a/prireader/stdafx.cpp +++ b/priread/stdafx.cpp @@ -1,8 +1,8 @@ // stdafx.cpp : 只包括标准包含文件的源文件 -// prireader.pch 将作为预编译头 +// priread.pch 将作为预编译头 // stdafx.obj 将包含预编译类型信息 #include "stdafx.h" // TODO: 在 STDAFX.H 中引用任何所需的附加头文件, -//而不是在此文件中引用 \ No newline at end of file +//而不是在此文件中引用 diff --git a/prireader/stdafx.h b/priread/stdafx.h similarity index 95% rename from prireader/stdafx.h rename to priread/stdafx.h index db3c4b1..4f79067 100644 --- a/prireader/stdafx.h +++ b/priread/stdafx.h @@ -18,4 +18,3 @@ #include // TODO: 在此处引用程序需要的其他头文件 -#include diff --git a/prireader/targetver.h b/priread/targetver.h similarity index 100% rename from prireader/targetver.h rename to priread/targetver.h diff --git a/prireader/priread.h b/prireader/priread.h deleted file mode 100644 index 6f70f09..0000000 --- a/prireader/priread.h +++ /dev/null @@ -1 +0,0 @@ -#pragma once diff --git a/prireader/prireader.cpp b/prireader/prireader.cpp deleted file mode 100644 index 8fa7053..0000000 --- a/prireader/prireader.cpp +++ /dev/null @@ -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; -} diff --git a/prireader/prireader.h b/prireader/prireader.h deleted file mode 100644 index 26c097b..0000000 --- a/prireader/prireader.h +++ /dev/null @@ -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); diff --git a/prireader/resource.h b/prireader/resource.h deleted file mode 100644 index 31a3d19..0000000 --- a/prireader/resource.h +++ /dev/null @@ -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