Files
App-Installer-For-Windows-8…/AppxPackage/PkgReadNative.cs
2026-01-20 22:34:22 +08:00

307 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// PackageReadHelper.cs
// P/Invoke wrapper for pkgread.dll (x86).
//
// 说明:此文件兼容 .NET Framework 4。
// - 将项目 Platform target 设置为 x86因为你只编译了 x86 的本机 DLL
// - pkgread.dll 返回了很多需由调用者释放的 LPWSTR 指针header 中未提供通用释放函数,示例中调用 CRT 的 freemsvcrt.dll来释放。
// 如果能修改 pkgread.dll 并导出专用释放函数(如 PackageReadFreeString那是更安全的做法。
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace NativeWrappers
{
// 本机类型别名(便于阅读)
using BOOL = System.Int32;
using WORD = System.UInt16;
using DWORD = System.UInt32;
using UINT16 = System.UInt16;
using UINT64 = System.UInt64;
using HRESULT = System.Int32;
using ULONG = System.UInt32;
public static class PackageReadHelper
{
private const string DllName = "pkgread.dll";
private const CallingConvention CallConv = CallingConvention.Cdecl;
[StructLayout (LayoutKind.Sequential)]
public struct VERSION
{
public ushort major;
public ushort minor;
public ushort build;
public ushort revision;
}
[StructLayout (LayoutKind.Sequential)]
public struct PAIR_PVOID
{
public IntPtr lpKey;
public IntPtr lpValue;
}
[StructLayout (LayoutKind.Sequential)]
public struct DEPENDENCY_INFO
{
public VERSION verMin;
public IntPtr lpName; // LPWSTR
public IntPtr lpPublisher; // LPWSTR
}
[StructLayout (LayoutKind.Sequential)]
public struct LIST_DEPINFO
{
public DWORD dwSize;
public IntPtr aDepInfo; // tail array
}
// Delegates
[UnmanagedFunctionPointer (CallConv)]
public delegate void PKGMRR_PROGRESSCALLBACK (DWORD dwProgress, IntPtr pCustom);
// ========== P/Invoke ==========
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern IntPtr CreatePackageReader ();
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
[return: MarshalAs (UnmanagedType.Bool)]
public static extern bool LoadPackageFromFile (IntPtr hReader, string lpFilePath);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern void DestroyPackageReader (IntPtr hReader);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern ushort GetPackageType (IntPtr hReader);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
[return: MarshalAs (UnmanagedType.Bool)]
public static extern bool IsPackageValid (IntPtr hReader);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern ushort GetPackageRole (IntPtr hReader);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern IntPtr GetPackageIdentityStringValue (IntPtr hReader, uint dwName);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
[return: MarshalAs (UnmanagedType.Bool)]
public static extern bool GetPackageIdentityVersion (IntPtr hReader, out VERSION pVersion, [MarshalAs (UnmanagedType.Bool)] bool bGetSubPkgVer);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
[return: MarshalAs (UnmanagedType.Bool)]
public static extern bool GetPackageIdentityArchitecture (IntPtr hReader, out DWORD pdwArchi);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern IntPtr GetPackagePropertiesStringValue (IntPtr hReader, string lpName);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern HRESULT GetPackagePropertiesBoolValue (IntPtr hReader, string lpName, out BOOL pRet);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
[return: MarshalAs (UnmanagedType.Bool)]
public static extern bool AddPackageApplicationItemGetName (string lpName);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
[return: MarshalAs (UnmanagedType.Bool)]
public static extern bool RemovePackageApplicationItemGetName (string lpName);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern IntPtr GetAllApplicationItemsName ();
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern void DestroyApplicationItemsName (IntPtr hList);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern IntPtr GetPackageApplications (IntPtr hReader);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern IntPtr ApplicationsToMap (IntPtr hEnumerator);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern void DestroyApplicationsMap (IntPtr hEnumerator);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern void DestroyPackageApplications (IntPtr hEnumerator);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern IntPtr GetResourcesLanguages (IntPtr hReader);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern IntPtr GetResourcesLanguagesToLcid (IntPtr hReader);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern IntPtr GetResourcesScales (IntPtr hReader);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern DWORD GetResourcesDxFeatureLevels (IntPtr hReader);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern void DestroyResourcesLanguagesList (IntPtr hList);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern void DestroyResourcesLanguagesLcidList (IntPtr hList);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern void DestroyUInt32List (IntPtr hList);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern IntPtr GetDependencesInfoList (IntPtr hReader);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern void DestroyDependencesInfoList (IntPtr hList);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern IntPtr GetCapabilitiesList (IntPtr hReader);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern IntPtr GetDeviceCapabilitiesList (IntPtr hReader);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern void DestroyWStringList (IntPtr hList);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
[return: MarshalAs (UnmanagedType.Bool)]
public static extern bool GetPackagePrerequisite (IntPtr hReader, string lpName, out VERSION pVerRet);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern IntPtr GetPackagePrerequistieSystemVersionName (IntPtr hReader, string lpName);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern IntPtr GetAppxFileFromAppxPackage (IntPtr hReader, string lpFileName);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern IntPtr GetAppxBundlePayloadPackageFile (IntPtr hReader, string lpFileName);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern IntPtr GetAppxPriFileStream (IntPtr hReader);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern IntPtr GetFileFromPayloadPackage (IntPtr hPackageStream, string lpFileName);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern IntPtr GetPriFileFromPayloadPackage (IntPtr hPackageStream);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
[return: MarshalAs (UnmanagedType.Bool)]
public static extern bool GetSuitablePackageFromBundle (IntPtr hReader, out IntPtr pStreamForLang, out IntPtr pStreamForScale);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern ULONG DestroyAppxFileStream (IntPtr hFileStream);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern IntPtr StreamToBase64W (IntPtr hFileStream, StringBuilder lpMimeBuf, DWORD dwCharCount, out IntPtr lpBase64Head);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern IntPtr GetAppxBundleApplicationPackageFile (IntPtr hReader);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern IntPtr GetPackageCapabilityDisplayName (string lpCapabilityName);
// CRT free当 header 指示用 free 释放)
[DllImport ("msvcrt.dll", CallingConvention = CallConv, EntryPoint = "free")]
private static extern void crt_free (IntPtr ptr);
// ========== 托管辅助方法 ==========
public static string GetStringAndFreeFromPkgRead (IntPtr nativePtr)
{
if (nativePtr == IntPtr.Zero) return null;
string s = Marshal.PtrToStringUni (nativePtr);
try
{
crt_free (nativePtr);
}
catch
{
// 忽略释放失败(注意可能的 CRT 不匹配风险)
}
return s;
}
public static string GetStringFromPkgRead (IntPtr nativePtr)
{
if (nativePtr == IntPtr.Zero) return null;
string s = Marshal.PtrToStringUni (nativePtr);
return s;
}
public static string PtrToStringNoFree (IntPtr nativePtr)
{
if (nativePtr == IntPtr.Zero) return null;
return Marshal.PtrToStringUni (nativePtr);
}
// 解析 HLIST_PVOID (字符串列表)
public static string [] ReadWStringList (IntPtr hList)
{
if (hList == IntPtr.Zero) return new string [0];
uint size = (uint)Marshal.ReadInt32 (hList);
if (size == 0) return new string [0];
string [] result = new string [size];
int offset = Marshal.SizeOf (typeof (uint)); // typically 4 on x86
for (int i = 0; i < size; i++)
{
IntPtr pSlot = Marshal.ReadIntPtr (hList, offset + i * IntPtr.Size);
result [i] = pSlot == IntPtr.Zero ? null : Marshal.PtrToStringUni (pSlot);
}
return result;
}
public static uint [] ReadUInt32List (IntPtr hList)
{
if (hList == IntPtr.Zero) return new uint [0];
uint size = (uint)Marshal.ReadInt32 (hList);
if (size == 0) return new uint [0];
uint [] result = new uint [size];
int offset = Marshal.SizeOf (typeof (uint));
for (int i = 0; i < size; i++)
{
result [i] = (uint)Marshal.ReadInt32 (hList, offset + i * 4);
}
return result;
}
public static int [] ReadLcidList (IntPtr hList)
{
if (hList == IntPtr.Zero) return new int [0];
uint size = (uint)Marshal.ReadInt32 (hList);
if (size == 0) return new int [0];
int [] result = new int [size];
int offset = Marshal.SizeOf (typeof (uint));
for (int i = 0; i < size; i++)
{
result [i] = Marshal.ReadInt32 (hList, offset + i * 4);
}
return result;
}
public static DEPENDENCY_INFO [] ReadDependencyInfoList (IntPtr hList)
{
if (hList == IntPtr.Zero) return new DEPENDENCY_INFO [0];
uint size = (uint)Marshal.ReadInt32 (hList);
if (size == 0) return new DEPENDENCY_INFO [0];
DEPENDENCY_INFO [] result = new DEPENDENCY_INFO [size];
int baseOffset = Marshal.SizeOf (typeof (uint));
int structSize = Marshal.SizeOf (typeof (DEPENDENCY_INFO));
for (int i = 0; i < size; i++)
{
IntPtr pItem = IntPtr.Add (hList, baseOffset + i * structSize);
object boxed = Marshal.PtrToStructure (pItem, typeof (DEPENDENCY_INFO));
result [i] = (DEPENDENCY_INFO)boxed;
}
return result;
}
public static void FreePkgReadMemory (IntPtr nativePtr)
{
if (nativePtr == IntPtr.Zero) return;
try
{
crt_free (nativePtr);
}
catch
{
}
}
}
}