Updated manager and added appx manifest reader.

This commit is contained in:
Bruce
2026-01-24 22:06:55 +08:00
parent 75cb72964d
commit 503ece1c64
60 changed files with 4980 additions and 3819 deletions

View File

@@ -61,6 +61,9 @@ EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WAShell", "WAShell\WAShell.csproj", "{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Manager", "Manager\Manager.csproj", "{DC074727-72E4-43C5-BAAF-E0D548104797}"
ProjectSection(ProjectDependencies) = postProject
{3AE2A022-ED83-41F1-948A-12A7593CBD00} = {3AE2A022-ED83-41F1-948A-12A7593CBD00}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IEHelper", "IEHelper\IEHelper.vcxproj", "{E4CA78A9-9408-4F5F-ADD6-730FD501FF8E}"
EndProject

View File

@@ -62,6 +62,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="DataInterface.cs" />
<Compile Include="ManifestReader.cs" />
<Compile Include="PackageManager.cs" />
<Compile Include="PackageReader.cs" />
<Compile Include="PkgMgrNative.cs" />

File diff suppressed because it is too large Load Diff

View File

@@ -77,7 +77,8 @@ namespace AppxPackage
private string familyName = "";
private string fullName = "";
private string resourceId = "";
public PMIdentity (string _name, string _publisher, DataUtils.Version _ver, IEnumerable<Architecture> _archs, string _family, string _full, string _resid)
private string publisherId = "";
public PMIdentity (string _name, string _publisher, DataUtils.Version _ver, IEnumerable<Architecture> _archs, string _family, string _full, string _resid, string _publisherId)
{
name = _name;
publisher = _publisher;
@@ -86,6 +87,7 @@ namespace AppxPackage
familyName = _family;
fullName = _full;
resourceId = _resid;
publisherId = _publisherId;
}
public PMIdentity (PackageManageHelper.FIND_PACKAGE_ID pkgId) :
this (
@@ -95,7 +97,8 @@ namespace AppxPackage
new Architecture [] { (Architecture)pkgId.wProcessArchitecture },
Marshal.PtrToStringUni (pkgId.lpFamilyName),
Marshal.PtrToStringUni (pkgId.lpFullName),
Marshal.PtrToStringUni (pkgId.lpResourceId)
Marshal.PtrToStringUni (pkgId.lpResourceId),
Marshal.PtrToStringUni (pkgId.lpPublisherId)
)
{ }
public string FamilyName => familyName;
@@ -103,8 +106,9 @@ namespace AppxPackage
public string Name => name;
public List<Architecture> ProcessArchitecture => archs.ToList ();
public string Publisher => publisher;
public string PublisherId => publisherId;
public string ResourceId => resourceId;
DataUtils.Version IIdentity.Version => version;
public DataUtils.Version Version => version;
}
[ComVisible (true)]
[ClassInterface (ClassInterfaceType.AutoDual)]

View File

@@ -104,10 +104,10 @@ namespace AppxPackage
[ClassInterface (ClassInterfaceType.AutoDual)]
public class BaseInfoSectWithPRI: BaseInfoSection
{
protected Ref<PackageReader> m_reader = null;
protected Ref<PriReaderBundle> m_priBundle = null;
protected Ref<bool> m_usePri = false;
protected Ref<bool> m_enablePri = false;
protected Ref<PackageReader> m_reader = new Ref<PackageReader> (null);
protected Ref<PriReaderBundle> m_priBundle = new Ref<PriReaderBundle> (null);
protected Ref<bool> m_usePri = new Ref<bool> (false);
protected Ref<bool> m_enablePri = new Ref<bool> (false);
public BaseInfoSectWithPRI (ref IntPtr hReader, PackageReader reader, ref PriReaderBundle priBundle, ref bool usePri, ref bool enablePri) : base (ref hReader)
{
m_reader.Set (reader);
@@ -1168,7 +1168,7 @@ namespace AppxPackage
public PackageReader (string filePath) { FilePath = filePath; }
public PackageReader () { }
public string JSONText { get { return BuildJsonText (); } }
private string BuildJsonText ()
public string BuildJsonText ()
{
var obj = BuildJsonObject ();
return Newtonsoft.Json.JsonConvert.SerializeObject (

View File

@@ -210,7 +210,8 @@ namespace NativeWrappers
string s = Marshal.PtrToStringUni (nativePtr);
try
{
crt_free (nativePtr);
PackageReaderFreeString (nativePtr);
nativePtr = IntPtr.Zero;
}
catch
{
@@ -303,5 +304,103 @@ namespace NativeWrappers
{
}
}
// ================= Manifest Reader =================
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern IntPtr CreateManifestReader ();
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
[return: MarshalAs (UnmanagedType.Bool)]
public static extern bool LoadManifestFromFile (
IntPtr hReader,
string lpFilePath
);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern void DestroyManifestReader (IntPtr hReader);
[DllImport (DllName, CallingConvention = CallConv)]
public static extern ushort GetManifestType (IntPtr hReader);
[DllImport (DllName, CallingConvention = CallConv)]
[return: MarshalAs (UnmanagedType.Bool)]
public static extern bool IsManifestValid (IntPtr hReader);
[DllImport (DllName, CallingConvention = CallConv)]
public static extern ushort GetManifestRole (IntPtr hReader);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern IntPtr GetManifestIdentityStringValue (
IntPtr hReader,
uint dwName
);
[DllImport (DllName, CallingConvention = CallConv)]
[return: MarshalAs (UnmanagedType.Bool)]
public static extern bool GetManifestIdentityVersion (
IntPtr hReader,
out VERSION pVersion
);
[DllImport (DllName, CallingConvention = CallConv)]
[return: MarshalAs (UnmanagedType.Bool)]
public static extern bool GetManifestIdentityArchitecture (
IntPtr hReader,
out DWORD pdwArchi
);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern IntPtr GetManifestPropertiesStringValue (
IntPtr hReader,
string lpName
);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
public static extern HRESULT GetManifestPropertiesBoolValue (
IntPtr hReader,
string lpName,
out BOOL pRet
);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
[return: MarshalAs (UnmanagedType.Bool)]
public static extern bool AddManifestApplicationItemGetName (string lpName);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
[return: MarshalAs (UnmanagedType.Bool)]
public static extern bool RemoveManifestApplicationItemGetName (string lpName);
[DllImport (DllName, CallingConvention = CallConv)]
public static extern IntPtr GetManifestApplications (IntPtr hReader);
[DllImport (DllName, CallingConvention = CallConv)]
public static extern void DestroyManifestApplications (IntPtr hEnumerator);
[DllImport (DllName, CallingConvention = CallConv)]
public static extern IntPtr GetManifestResourcesLanguages (IntPtr hReader);
[DllImport (DllName, CallingConvention = CallConv)]
public static extern IntPtr GetManifestResourcesLanguagesToLcid (IntPtr hReader);
[DllImport (DllName, CallingConvention = CallConv)]
public static extern IntPtr GetManifestResourcesScales (IntPtr hReader);
[DllImport (DllName, CallingConvention = CallConv)]
public static extern DWORD GetManifestResourcesDxFeatureLevels (IntPtr hReader);
[DllImport (DllName, CallingConvention = CallConv)]
public static extern IntPtr GetManifestDependencesInfoList (IntPtr hReader);
[DllImport (DllName, CallingConvention = CallConv)]
public static extern IntPtr GetManifestCapabilitiesList (IntPtr hReader);
[DllImport (DllName, CallingConvention = CallConv)]
public static extern IntPtr GetManifestDeviceCapabilitiesList (IntPtr hReader);
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
[return: MarshalAs (UnmanagedType.Bool)]
public static extern bool GetManifestPrerequisite (
IntPtr hReader,
string lpName,
out VERSION pVerRet
);
[DllImport (DllName, CallingConvention = CallConv)]
public static extern void PackageReaderFreeString (IntPtr p);
}
}

View File

@@ -57,11 +57,13 @@ namespace AppxPackage
[DllImport (DLL, CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs (UnmanagedType.Bool)]
public static extern bool IsMsResourceUri ([MarshalAs (UnmanagedType.LPWStr)] string pResUri);
[DllImport (DLL, CallingConvention = CallingConvention.Cdecl)]
public static extern void PriFormatFreeString (IntPtr ptr);
public static string PtrToString (IntPtr ptr)
{
if (ptr == IntPtr.Zero) return null;
string s = Marshal.PtrToStringUni (ptr);
Marshal.FreeHGlobal (ptr); // 如果 DLL 返回的内存要求 free
PriFormatFreeString (ptr); // 如果 DLL 返回的内存要求 free
return s;
}
[DllImport (DLL, CallingConvention = CallingConvention.Cdecl)]

View File

@@ -496,6 +496,8 @@ namespace Bridge
{
public AppxPackage.PackageReader Reader (string packagePath) { return new AppxPackage.PackageReader (packagePath); }
public _I_PackageManager Manager => new _I_PackageManager ();
public AppxPackage.ManifestReader Manifest (string manifestPath) { return new AppxPackage.ManifestReader (manifestPath); }
public AppxPackage.ManifestReader FromInstallLocation (string installLocation) { return Manifest (Path.Combine (installLocation, "AppxManifest.xml")); }
}
[ComVisible (true)]
[ClassInterface (ClassInterfaceType.AutoDual)]

View File

@@ -5,7 +5,7 @@ using System.Runtime.InteropServices;
namespace DataUtils
{
internal static class VisualElementsStore
public static class VisualElementsStore
{
// Publicly accessible instances for internal use
public static readonly VisualElementManifest Vemanifest;

View File

@@ -186,17 +186,6 @@ namespace DataUtils
if (string.IsNullOrWhiteSpace (colorStr)) return Color.Transparent;
string s = colorStr.Trim ();
// Named color
try
{
Color byName = Color.FromName (s);
if (byName.IsKnownColor || byName.IsNamedColor)
{
return byName;
}
}
catch { /* ignore */ }
// Hex: #RGB, #RRGGBB, #AARRGGBB
if (s.StartsWith ("#"))
{
@@ -321,6 +310,17 @@ namespace DataUtils
}
}
// Named color
try
{
Color byName = Color.FromName (s);
if (byName.IsKnownColor || byName.IsNamedColor)
{
return byName;
}
}
catch { /* ignore */ }
// fallback: try parse as known color again (case-insensitive)
try
{

View File

@@ -53,6 +53,7 @@
<Compile Include="ManagerShell.Designer.cs">
<DependentUpon>ManagerShell.cs</DependentUpon>
</Compile>
<Compile Include="Polyfill.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="ManagerShell.resx">
@@ -66,6 +67,7 @@
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<None Include="app.manifest" />
<None Include="Properties\Settings.settings">

View File

@@ -40,6 +40,7 @@
this.PageScale = 125;
this.Text = "Form1";
this.Load += new System.EventHandler(this.ManagerShell_Load);
this.Resize += new System.EventHandler(this.ManagerShell_Resize);
this.ResumeLayout(false);
}

View File

@@ -14,12 +14,82 @@ namespace Manager
public ManagerShell ()
{
InitializeComponent ();
SplashScreen.SplashBackgroundColor = Color.Honeydew;
try
{
var relativePath = DataUtils.VisualElementsStore.Vemanifest.SplashScreenImage (Program.g_appId);
var img = Image.FromFile (relativePath);
SplashScreen.SplashImage = img;
} catch (Exception e) {
var ex = e;
}
try
{
SplashScreen.SplashBackgroundColor = DataUtils.UITheme.StringToColor (DataUtils.VisualElementsStore.Vemanifest.SplashScreenBackgroundColor (Program.g_appId));
}
catch { }
InitSize ();
}
private void InitSize ()
{
uint ww = 0, wh = 0;
var ini = Bridge.InitFileStore.Config;
var setsect = ini ["Settings"];
var savepos = setsect.GetKey ("PackageManager:SavePosAndSizeBeforeCancel");
var lastw = setsect.GetKey ("PackageManager:LastWidth");
var lasth = setsect.GetKey ("PackageManager:LastHeight");
var defw = setsect.GetKey ("PackageManager:DefaultWidth");
var defh = setsect.GetKey ("PackageManager:DefaultHeight");
var minw = setsect.GetKey ("PackageManager:MinimumWidth");
var minh = setsect.GetKey ("PackageManager:MinimumHeight");
var lasts = setsect.GetKey ("PackageManager:LastWndState");
if (savepos.ReadBool ())
{
ww = lastw.ReadUInt (defw.ReadUInt (Properties.Resources.IDS_DEFAULTWIDTH.ParseTo <uint> ()));
wh = lasth.ReadUInt (defh.ReadUInt (Properties.Resources.IDS_DEFAULTHEIGHT.ParseTo <uint> ()));
}
else
{
ww = defw.ReadUInt (Properties.Resources.IDS_DEFAULTWIDTH.ParseTo<uint> ());
wh = defh.ReadUInt (Properties.Resources.IDS_DEFAULTHEIGHT.ParseTo<uint> ());
}
ClientSize = new Size ((int)(ww * DataUtils.UITheme.DPIDouble), (int)(wh * DataUtils.UITheme.DPIDouble));
int hborder = Size.Width - ClientSize.Width,
vborder = Size.Height - ClientSize.Height;
MinimumSize = new Size (
(int)(minw.ReadUInt (Properties.Resources.IDS_MINWIDTH.ParseTo <uint> ()) * DataUtils.UITheme.DPIDouble) + hborder,
(int)(minh.ReadUInt (Properties.Resources.IDS_MINHEIGHT.ParseTo <uint> ()) * DataUtils.UITheme.DPIDouble) + vborder
);
WindowState = (FormWindowState)lasts.ReadInt ((int)FormWindowState.Normal);
}
private void ManagerShell_Load (object sender, EventArgs e)
{
var root = Path.GetDirectoryName (DataUtils.Utilities.GetCurrentProgramPath ());
WebUI.Navigate (Path.Combine (root, "html\\manager.html"));
var pkg = new AppxPackage.PackageReader (@"F:\新建文件夹 (2)\9E2F88E3.Twitter_1.1.13.8_x86__wgeqdkkx372wm.appx");
pkg.EnablePri = true;
pkg.UsePri = true;
var displayName = pkg.Properties.LogoBase64;
}
private void ManagerShell_Resize (object sender, EventArgs e)
{
var ini = Bridge.InitFileStore.Config;
var setsect = ini ["Settings"];
var savepos = setsect.GetKey ("PackageManager:SavePosAndSizeBeforeCancel");
var lastw = setsect.GetKey ("PackageManager:LastWidth");
var lasth = setsect.GetKey ("PackageManager:LastHeight");
var lasts = setsect.GetKey ("PackageManager:LastWndState");
switch (WindowState)
{
case FormWindowState.Normal:
case FormWindowState.Maximized:
lasts.Write ((int)WindowState);
break;
}
if (WindowState == FormWindowState.Normal && savepos.ReadBool ())
{
lastw.Write ((int)(ClientSize.Width / DataUtils.UITheme.DPIDouble));
lasth.Write ((int)(ClientSize.Height / DataUtils.UITheme.DPIDouble));
}
}
}
}

40
Manager/Polyfill.cs Normal file
View File

@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Text;
namespace Manager
{
public static class Polyfill
{
public static T ParseTo <T> (this string src, T dflt = default (T))
{
if (string.IsNullOrWhiteSpace (src)) return dflt;
try
{
Type targetType = typeof (T);
Type underlying = Nullable.GetUnderlyingType (targetType);
if (underlying != null)
{
object v = Convert.ChangeType (src, underlying, CultureInfo.InvariantCulture);
return (T)v;
}
if (targetType.IsEnum)
{
object enumValue = Enum.Parse (targetType, src, true);
return (T)enumValue;
}
TypeConverter converter = TypeDescriptor.GetConverter (targetType);
if (converter != null && converter.CanConvertFrom (typeof (string)))
{
object v = converter.ConvertFrom (null, CultureInfo.InvariantCulture, src);
return (T)v;
}
}
catch { }
return dflt;
}
}
}

View File

@@ -7,6 +7,8 @@ namespace Manager
{
static class Program
{
static public readonly string g_appUserId = "WindowsModern.PracticalToolsProject!Manager";
static public readonly string g_appId = "Manager";
/// <summary>
/// 应用程序的主入口点。
/// </summary>

View File

@@ -3,47 +3,42 @@
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
//
// 对此文件的更改可能导致不正确的行为,如果
// 重新生成代码,则所做更改将丢失。
// 对此文件的更改可能导致不正确的行为,并且如果
// 重新生成代码,这些更改将丢失。
// </auto-generated>
//------------------------------------------------------------------------------
namespace Manager.Properties
{
namespace Manager.Properties {
using System;
/// <summary>
/// 强类型资源类,用于查找本地化字符串等。
/// 一个强类型资源类,用于查找本地化字符串等。
/// </summary>
// 此类是由 StronglyTypedResourceBuilder
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
// 若要添加或除成员,请编辑 .ResX 文件,然后重新运行 ResGen
// 若要添加或除成员,请编辑 .ResX 文件,然后重新运行 ResGen
// (以 /str 作为命令选项),或重新生成 VS 项目。
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources
{
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources ()
{
internal Resources() {
}
/// <summary>
/// 返回此类使用的缓存 ResourceManager 实例。
/// 返回此类使用的缓存 ResourceManager 实例。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ((resourceMan == null))
{
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Manager.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
@@ -52,20 +47,53 @@ namespace Manager.Properties
}
/// <summary>
/// 覆盖当前线程的 CurrentUICulture 属性
/// 使用此强类型的资源类的资源查找
/// 使用此强类型资源类,为所有资源查找
/// 重写当前线程的 CurrentUICulture 属性
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set
{
set {
resourceCulture = value;
}
}
/// <summary>
/// 查找类似 600 的本地化字符串。
/// </summary>
internal static string IDS_DEFAULTHEIGHT {
get {
return ResourceManager.GetString("IDS_DEFAULTHEIGHT", resourceCulture);
}
}
/// <summary>
/// 查找类似 800 的本地化字符串。
/// </summary>
internal static string IDS_DEFAULTWIDTH {
get {
return ResourceManager.GetString("IDS_DEFAULTWIDTH", resourceCulture);
}
}
/// <summary>
/// 查找类似 412 的本地化字符串。
/// </summary>
internal static string IDS_MINHEIGHT {
get {
return ResourceManager.GetString("IDS_MINHEIGHT", resourceCulture);
}
}
/// <summary>
/// 查找类似 504 的本地化字符串。
/// </summary>
internal static string IDS_MINWIDTH {
get {
return ResourceManager.GetString("IDS_MINWIDTH", resourceCulture);
}
}
}
}

View File

@@ -46,7 +46,7 @@
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
@@ -60,6 +60,7 @@
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
@@ -68,9 +69,10 @@
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
@@ -85,9 +87,10 @@
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
@@ -109,9 +112,25 @@
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="IDS_DEFAULTHEIGHT" xml:space="preserve">
<value>600</value>
<comment>默认窗口高度</comment>
</data>
<data name="IDS_DEFAULTWIDTH" xml:space="preserve">
<value>800</value>
<comment>默认窗口宽度</comment>
</data>
<data name="IDS_MINHEIGHT" xml:space="preserve">
<value>412</value>
<comment>默认最小窗口高度</comment>
</data>
<data name="IDS_MINWIDTH" xml:space="preserve">
<value>504</value>
<comment>默认最小窗口宽度</comment>
</data>
</root>

View File

@@ -8,16 +8,16 @@
如果想要更改 Windows 用户帐户控制级别,请使用
以下节点之一替换 requestedExecutionLevel 节点。n
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
<requestedExecutionLevel level="asInvoker" uiAccess="false" /> -->
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
<!-- <requestedExecutionLevel level="highestAvailable" uiAccess="false" />
指定 requestedExecutionLevel 元素将禁用文件和注册表虚拟化。
如果你的应用程序需要此虚拟化来实现向后兼容性,则删除此
元素。
-->
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
<!-- <requestedExecutionLevel level="asInvoker" uiAccess="false" /> -->
</requestedPrivileges>
</security>
</trustInfo>

View File

@@ -186,7 +186,7 @@ namespace Win32
public object Get (string section, string key, object dflt) => GetKey (section, key).Get (dflt);
public object Get (string section, string key) => GetKey (section, key).Get ();
public bool Set (string section, string key, object value) => GetKey (section, key).Set (value);
public object this [string key] => GetSection (key);
public InitSection this [string key] => GetSection (key);
public string [] GetAllSections ()
{
var sections = new System.Collections.Generic.List<string> ();

BIN
Release.7z Normal file

Binary file not shown.

63
WAShell/Properties/Resources.Designer.cs generated Normal file
View File

@@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
namespace WAShell.Properties {
using System;
/// <summary>
/// 一个强类型的资源类,用于查找本地化的字符串等。
/// </summary>
// 此类是由 StronglyTypedResourceBuilder
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
// (以 /str 作为命令选项),或重新生成 VS 项目。
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// 返回此类使用的缓存的 ResourceManager 实例。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WAShell.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// 使用此强类型资源类,为所有资源查找
/// 重写当前线程的 CurrentUICulture 属性。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -38,6 +38,7 @@
//
this.picbox.Anchor = System.Windows.Forms.AnchorStyles.None;
this.picbox.BackColor = System.Drawing.Color.Transparent;
this.picbox.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
this.picbox.Location = new System.Drawing.Point(6, 47);
this.picbox.Name = "picbox";
this.picbox.Size = new System.Drawing.Size(620, 300);

View File

@@ -87,9 +87,9 @@ namespace WAShell
set
{
splashImage = value;
if (picbox != null && picbox.IsHandleCreated)
if (picbox != null)
{
picbox.Image = splashImage;
try { picbox.Image = splashImage; } catch { }
}
}
}

View File

@@ -42,6 +42,11 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="SplashForm.cs">
<SubType>Form</SubType>
</Compile>
@@ -78,6 +83,10 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Include="SplashForm.resx">
<DependentUpon>SplashForm.cs</DependentUpon>
</EmbeddedResource>

View File

@@ -298,10 +298,10 @@ struct pkg_info
pi.users += sid;
}
{
std::wstring sid;
WAPParseSetStringValue (sid, it->UserSecurityId);
std::wstring sid2;
WAPParseSetStringValue (sid2, it->UserSecurityId);
if (i) pi.sids += L';';
pi.sids += sid;
pi.sids += sid2;
}
i ++;
}
@@ -858,3 +858,148 @@ void PackageManagerFreeString (LPWSTR lpString)
{
if (lpString) free (lpString);
}
[STAThread]
HRESULT CreateAppDataManager (LPCWSTR lpFamilyName, HWRTAPPDATA *ppApplicationData, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
{
g_swExceptionCode = L"";
g_swExceptionDetail = L"";
try
{
auto adm = ApplicationDataManager::CreateForPackageFamily (ref new String (lpFamilyName ? lpFamilyName : L""));
auto insp = reinterpret_cast <IInspectable *> (adm);
insp->AddRef ();
if (ppApplicationData) *ppApplicationData = (HWRTAPPDATA)insp;
return S_OK;
}
catch (AccessDeniedException ^e)
{
g_swExceptionDetail = e->ToString ()->Data ();
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return (SUCCEEDED ((HRESULT)e->HResult) ? E_FAIL : (HRESULT)e->HResult);
}
catch (Exception ^e)
{
g_swExceptionDetail = e->ToString ()->Data ();
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return (SUCCEEDED ((HRESULT)e->HResult) ? E_FAIL : (HRESULT)e->HResult);
}
catch (const std::exception &e)
{
g_swExceptionDetail = StringToWString (e.what () ? e.what () : "Unknown exception.");
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return E_FAIL;
}
catch (...)
{
g_swExceptionDetail = L"Unknown exception";
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return E_FAIL;
}
return E_FAIL;
}
HRESULT RunAsyncActionOperation (Windows::Foundation::IAsyncAction ^asyncAction, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
{
g_swExceptionCode.clear ();
g_swExceptionDetail.clear ();
if (pErrorCode) *pErrorCode = nullptr;
if (pDetailMsg) *pDetailMsg = nullptr;
if (!asyncAction) return E_POINTER;
HANDLE hCompEvt = CreateEventExW (
nullptr,
nullptr,
CREATE_EVENT_MANUAL_RESET,
EVENT_ALL_ACCESS
);
if (!hCompEvt) return HRESULT_FROM_WIN32 (GetLastError ());
auto closeEvt = destruct ([&] () {
CloseHandle (hCompEvt);
});
try
{
asyncAction->Completed =
ref new Windows::Foundation::AsyncActionCompletedHandler (
[&hCompEvt] (
Windows::Foundation::IAsyncAction^,
Windows::Foundation::AsyncStatus)
{
SetEvent (hCompEvt);
});
WaitForSingleObject (hCompEvt, INFINITE);
switch (asyncAction->Status)
{
case Windows::Foundation::AsyncStatus::Completed: return S_OK;
case Windows::Foundation::AsyncStatus::Canceled:
g_swExceptionDetail = L"Async action was canceled.";
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return E_ABORT;
case Windows::Foundation::AsyncStatus::Error:
{
auto err = asyncAction->ErrorCode;
HRESULT hr = (HRESULT)err.Value;
auto errStr = Platform::Exception::CreateException (err.Value)->ToString ();
if (errStr && errStr->Data ()) g_swExceptionCode = errStr->Data ();
if (pErrorCode) *pErrorCode = _wcsdup (g_swExceptionCode.c_str ());
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return hr;
}
default: return E_FAIL;
}
}
catch (Platform::Exception^ e)
{
g_swExceptionDetail = e->ToString ()->Data ();
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return e->HResult;
}
catch (const std::exception& e)
{
g_swExceptionDetail = StringToWString (e.what () ? e.what () : "Unknown exception.");
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return E_FAIL;
}
catch (...)
{
g_swExceptionDetail = L"Unknown exception.";
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return E_FAIL;
}
}
#define HWRTAppDataToAppData(pInspectable) \
safe_cast <Windows::Storage::ApplicationData ^> (reinterpret_cast <Platform::Object ^>(pInspectable))
[MTAThread]
HRESULT WRTAppDataClearAll (HWRTAPPDATA hAppData, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
{
g_swExceptionCode = L"";
g_swExceptionDetail = L"";
try
{
ApplicationData ^appData = HWRTAppDataToAppData (hAppData, appData, pErrorCode, pDetailMsg);
if (appData == nullptr) return E_FAIL;
return RunAsyncActionOperation (appData->ClearAsync (), pErrorCode, pDetailMsg);
}
catch (AccessDeniedException ^e)
{
g_swExceptionDetail = e->ToString ()->Data ();
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return (SUCCEEDED ((HRESULT)e->HResult) ? E_FAIL : (HRESULT)e->HResult);
}
catch (Exception ^e)
{
g_swExceptionDetail = e->ToString ()->Data ();
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return (SUCCEEDED ((HRESULT)e->HResult) ? E_FAIL : (HRESULT)e->HResult);
}
catch (const std::exception &e)
{
g_swExceptionDetail = StringToWString (e.what () ? e.what () : "Unknown exception.");
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return E_FAIL;
}
catch (...)
{
g_swExceptionDetail = L"Unknown exception";
if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
return E_FAIL;
}
return E_FAIL;
}

View File

@@ -194,6 +194,15 @@ extern "C"
PKGMGR_API HRESULT FindAppxPackagesByFamilyName (LPCWSTR lpPkgFamilyName, PKGMGR_FINDENUMCALLBACK pfCallback, void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
// 释放由 pkgmgr.dll 返回的动态字符串。
PKGMGR_API void PackageManagerFreeString (LPWSTR lpString);
#ifndef TEMPLATE_STRUCT
#define TEMPLATE_STRUCT(_typename_) typedef struct _typename_##__ _typename_
#endif // ! TEMPLATE_STRUCT
TEMPLATE_STRUCT (WRTAPPDATA);
typedef WRTAPPDATA *HWRTAPPDATA;
// 创建应用数据管理器。通过 Package Family Name
PKGMGR_API HRESULT CreateAppDataManager (LPCWSTR lpFamilyName, HWRTAPPDATA *ppApplicationData, LPWSTR *pErrorCode, LPWSTR *pDetailMsg);
// 从本地、漫游和临时应用数据存储中删除所有应用程序数据。
PKGMGR_API HRESULT WRTAppDataClearAll (HWRTAPPDATA hAppData, LPWSTR *pErrorCode, LPWSTR *pDetailMsg);
#ifdef _DEFAULT_INIT_VALUE_
#undef _DEFAULT_INIT_VALUE_
#endif

View File

@@ -32,3 +32,5 @@
using namespace Platform;
using namespace Windows::Foundation;
using namespace Windows::Management::Deployment;
using namespace Windows::Management::Core;
using namespace Windows::Storage;

View File

@@ -1214,3 +1214,543 @@ LPWSTR GetPackageCapabilityDisplayName (LPCWSTR lpCapabilityName)
if (IsNormalizeStringEmpty (ret)) return nullptr;
else return _wcsdup (ret.c_str ());
}
void PackageReaderFreeString (LPWSTR lpStrFromThisDll)
{
if (!lpStrFromThisDll) return;
free (lpStrFromThisDll);
}
// ========== 以下是对清单文件的读取 ==========
#define ToHandleMRead(_cpp_ptr_) reinterpret_cast <HPKGMANIFESTREAD> (_cpp_ptr_)
#define ToPtrManifest(_cpp_ptr_) reinterpret_cast <manifest *> (_cpp_ptr_)
HPKGMANIFESTREAD CreateManifestReader () { return ToHandleMRead (new manifest ()); }
BOOL LoadManifestFromFile (_In_ HPKGMANIFESTREAD hReader, _In_ LPCWSTR lpFilePath)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return false;
return ptr->create (lpFilePath);
}
void DestroyManifestReader (_In_ HPKGMANIFESTREAD hReader)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return;
return delete ptr;
}
WORD GetManifestType (_In_ HPKGMANIFESTREAD hReader)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return PKGTYPE_UNKNOWN;
switch (ptr->type ())
{
case PackageType::unknown: return PKGTYPE_UNKNOWN;
case PackageType::single: return PKGTYPE_APPX;
case PackageType::bundle: return PKGTYPE_BUNDLE;
}
return PKGTYPE_UNKNOWN;
}
BOOL IsManifestValid (_In_ HPKGMANIFESTREAD hReader)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return false;
return ptr->valid ();
}
WORD GetManifestRole (_In_ HPKGMANIFESTREAD hReader)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return PKGROLE_UNKNOWN;
switch (ptr->type ())
{
case PackageType::unknown: return PKGROLE_UNKNOWN;
case PackageType::bundle: return PKGROLE_APPLICATION;
case PackageType::single: {
auto ar = ptr->appx_reader ();
switch (ar.package_role ())
{
case PackageRole::unknown: return PKGROLE_UNKNOWN;
case PackageRole::application: return PKGROLE_APPLICATION;
case PackageRole::framework: return PKGROLE_FRAMEWORK;
case PackageRole::resource: return PKGROLE_RESOURCE;
}
} break;
}
return PKGROLE_UNKNOWN;
}
// Identity
LPWSTR GetManifestIdentityStringValue (_In_ HPKGMANIFESTREAD hReader, _In_ DWORD dwName)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return nullptr;
switch (ptr->type ())
{
case PackageType::single: {
auto reader = ptr->appx_reader ();
auto id = reader.identity ();
switch (LOWORD (dwName))
{
case PKG_IDENTITY_NAME: return _wcsdup (id.name ().c_str ());
case PKG_IDENTITY_PUBLISHER: return _wcsdup (id.publisher ().c_str ());
case PKG_IDENTITY_PACKAGEFAMILYNAME: return _wcsdup (id.package_family_name ().c_str ());
case PKG_IDENTITY_PACKAGEFULLNAME: return _wcsdup (id.package_full_name ().c_str ());
case PKG_IDENTITY_RESOURCEID: return _wcsdup (id.resource_id ().c_str ());
}
} break;
case PackageType::bundle: {
auto reader = ptr->bundle_reader ();
auto id = reader.identity ();
{
switch (LOWORD (dwName))
{
case PKG_IDENTITY_NAME: return _wcsdup (id.name ().c_str ());
case PKG_IDENTITY_PUBLISHER: return _wcsdup (id.publisher ().c_str ());
case PKG_IDENTITY_PACKAGEFAMILYNAME: return _wcsdup (id.package_family_name ().c_str ());
case PKG_IDENTITY_PACKAGEFULLNAME: return _wcsdup (id.package_full_name ().c_str ());
case PKG_IDENTITY_RESOURCEID: return _wcsdup (id.resource_id ().c_str ());
}
}
} break;
}
return nullptr;
}
BOOL GetManifestIdentityVersion (_In_ HPKGMANIFESTREAD hReader, _Out_ VERSION *pVersion)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return FALSE;
if (!pVersion) return FALSE;
switch (ptr->type ())
{
case PackageType::single: {
auto reader = ptr->appx_reader ();
auto id = reader.identity ();
auto ver = id.version ();
*pVersion = VersionClassToStruct (ver);
return !ver.empty ();
} break;
case PackageType::bundle: {
auto reader = ptr->bundle_reader ();
auto id = reader.identity ();
{
auto ver = id.version ();
*pVersion = VersionClassToStruct (ver);
return !ver.empty ();
}
} break;
}
return FALSE;
}
BOOL GetManifestIdentityArchitecture (_In_ HPKGMANIFESTREAD hReader, _Out_ DWORD *pdwArchi)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return FALSE;
if (!pdwArchi) return FALSE;
switch (ptr->type ())
{
case PackageType::single: {
auto reader = ptr->appx_reader ();
auto id = reader.identity ();
auto archi = id.architecture ();
DWORD ret = 0;
switch (archi)
{
case APPX_PACKAGE_ARCHITECTURE::APPX_PACKAGE_ARCHITECTURE_X86:
ret = PKG_ARCHITECTURE_X86; break;
case APPX_PACKAGE_ARCHITECTURE::APPX_PACKAGE_ARCHITECTURE_ARM:
ret = PKG_ARCHITECTURE_ARM; break;
case APPX_PACKAGE_ARCHITECTURE::APPX_PACKAGE_ARCHITECTURE_X64:
ret = PKG_ARCHITECTURE_X64; break;
case APPX_PACKAGE_ARCHITECTURE::APPX_PACKAGE_ARCHITECTURE_NEUTRAL:
ret = PKG_ARCHITECTURE_NEUTRAL; break;
case (APPX_PACKAGE_ARCHITECTURE)12: // ARM64
ret = PKG_ARCHITECTURE_ARM64; break;
}
*pdwArchi = ret;
return ret != PKG_ARCHITECTURE_UNKNOWN;
} break;
case PackageType::bundle: {
auto reader = ptr->bundle_reader ();
auto ids = reader.package_id_items ();
std::vector <appx_info::appx_iditem> apps;
ids.application_packages (apps);
DWORD ret = 0;
for (auto &it : apps)
{
auto id = it.identity ();
auto archi = id.architecture ();
switch (archi)
{
case APPX_PACKAGE_ARCHITECTURE::APPX_PACKAGE_ARCHITECTURE_X86:
ret |= PKG_ARCHITECTURE_X86; break;
case APPX_PACKAGE_ARCHITECTURE::APPX_PACKAGE_ARCHITECTURE_ARM:
ret |= PKG_ARCHITECTURE_ARM; break;
case APPX_PACKAGE_ARCHITECTURE::APPX_PACKAGE_ARCHITECTURE_X64:
ret |= PKG_ARCHITECTURE_X64; break;
case APPX_PACKAGE_ARCHITECTURE::APPX_PACKAGE_ARCHITECTURE_NEUTRAL:
ret |= PKG_ARCHITECTURE_NEUTRAL; break;
case (APPX_PACKAGE_ARCHITECTURE)12: // ARM64
ret |= PKG_ARCHITECTURE_ARM64; break;
}
}
*pdwArchi = ret;
return ret != PKG_ARCHITECTURE_UNKNOWN;
} break;
}
return FALSE;
}
// Properties
LPWSTR GetManifestPropertiesStringValue (_In_ HPKGMANIFESTREAD hReader, _In_ LPCWSTR lpName)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return nullptr;
switch (ptr->type ())
{
case PackageType::single: {
auto reader = ptr->appx_reader ();
auto prop = reader.properties ();
return _wcsdup (prop.string_value (lpName ? lpName : L"").c_str ());
} break;
}
return nullptr;
}
HRESULT GetManifestPropertiesBoolValue (_In_ HPKGMANIFESTREAD hReader, _In_ LPCWSTR lpName, _Outptr_ BOOL *pRet)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return E_INVALIDARG;
if (!pRet) return E_INVALIDARG;
*pRet = FALSE;
switch (ptr->type ())
{
case PackageType::single: {
auto reader = ptr->appx_reader ();
IAppxManifestReader *m = reader.manifest ();
if (!m) return E_FAIL;
CComPtr <IAppxManifestProperties> p;
HRESULT hr = m->GetProperties (&p);
if (FAILED (hr)) return hr;
return p->GetBoolValue (lpName, pRet);
} break;
}
return E_FAIL;
}
// Applications
BOOL AddManifestApplicationItemGetName (_In_ LPCWSTR lpName)
{
if (std::wnstring (lpName ? lpName : L"").empty ()) return FALSE;
return PushApplicationAttributeItem (lpName);
}
BOOL RemoveManifestApplicationItemGetName (_In_ LPCWSTR lpName)
{
if (std::wnstring (lpName ? lpName : L"").empty ()) return FALSE;
return RemoveApplicationAttributeItem (lpName);
}
HAPPENUMERATOR GetManifestApplications (_In_ HPKGMANIFESTREAD hReader)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return nullptr;
switch (ptr->type ())
{
case PackageType::single: {
auto reader = ptr->appx_reader ();
auto app = reader.applications ();
auto appvec = new app_enumerator ();
app.applications (*appvec);
return ToHandleAppEnumerator (appvec);
} break;
}
return nullptr;
}
void DestroyManifestApplications (_In_ HAPPENUMERATOR hEnumerator)
{
auto ptr = ToPtrAppxApps (hEnumerator);
if (ptr) delete ptr;
}
// Resources
HLIST_PVOID GetManifestResourcesLanguages (_In_ HPKGMANIFESTREAD hReader)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return nullptr;
std::vector <std::wnstring> langs;
switch (ptr->type ())
{
case PackageType::single:
{
auto reader = ptr->appx_reader ();
auto res = reader.resources ();
res.languages (langs);
break;
}
case PackageType::bundle:
{
auto br = ptr->bundle_reader ();
auto res = br.package_id_items ();
res.enumerate ([&langs] (IAppxBundleManifestPackageInfo *inf) {
auto item = appx_info::appx_iditem (inf);
std::vector <std::wnstring> l;
auto qr = item.qualified_resources ();
qr.languages (l);
for (auto &it : l) push_unique <std::wnstring> (langs, it);
});
break;
}
default: return nullptr;
}
if (langs.empty ()) return nullptr;
size_t count = langs.size ();
size_t bytes = sizeof (LIST_PVOID) + sizeof (LPWSTR) * (count - 1);
auto list = (HLIST_PVOID)malloc (bytes);
ZeroMemory (list, bytes);
if (!list) return nullptr;
list->dwSize = 0;
for (auto &it : langs) list->alpVoid [list->dwSize ++] = _wcsdup (it.c_str ());
return list;
}
HLIST_LCID GetManifestResourcesLanguagesToLcid (_In_ HPKGMANIFESTREAD hReader)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return nullptr;
std::vector <std::wnstring> langs;
switch (ptr->type ())
{
case PackageType::single:
{
auto reader = ptr->appx_reader ();
auto res = reader.resources ();
res.languages (langs);
break;
}
case PackageType::bundle:
{
auto br = ptr->bundle_reader ();
auto res = br.package_id_items ();
res.enumerate ([&langs] (IAppxBundleManifestPackageInfo *inf) {
auto item = appx_info::appx_iditem (inf);
std::vector <std::wnstring> l;
auto qr = item.qualified_resources ();
qr.languages (l);
for (auto &it : l) push_unique <std::wnstring> (langs, it);
});
break;
}
default: return nullptr;
}
if (langs.empty ()) return nullptr;
size_t len = sizeof (LIST_LCID) + sizeof (LCID) * langs.size ();
HLIST_LCID hList = (HLIST_LCID)malloc (len);
ZeroMemory (hList, len);
hList->dwSize = 0;
for (auto &it : langs)
{
LCID lcid = LocaleCodeToLcid (it);
if (lcid)
{
hList->aLcid [hList->dwSize ++] = lcid;
}
}
return hList;
}
HLIST_UINT32 GetManifestResourcesScales (_In_ HPKGMANIFESTREAD hReader)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return nullptr;
std::vector <UINT32> scales;
switch (ptr->type ())
{
case PackageType::single:
{
auto reader = ptr->appx_reader ();
auto res = reader.resources ();
res.scales (scales);
break;
}
case PackageType::bundle:
{
auto br = ptr->bundle_reader ();
auto res = br.package_id_items ();
res.enumerate ([&scales] (IAppxBundleManifestPackageInfo *inf) {
auto item = appx_info::appx_iditem (inf);
std::vector <UINT32> s;
auto qr = item.qualified_resources ();
qr.scales (s);
for (auto &it : s) push_unique (scales, it);
});
break;
}
default: return nullptr;
}
if (scales.empty ()) return nullptr;
size_t len = sizeof (LIST_UINT32) + sizeof (UINT32) * scales.size ();
HLIST_UINT32 hList = (HLIST_UINT32)malloc (len);
ZeroMemory (hList, len);
hList->dwSize = 0;
for (auto &it : scales)
{
if (!it) continue;
hList->aUI32 [hList->dwSize ++] = it;
}
return hList;
}
DWORD GetManifestResourcesDxFeatureLevels (_In_ HPKGMANIFESTREAD hReader)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return 0;
DWORD dwFlags = 0;
switch (ptr->type ())
{
case PackageType::single:
{
auto reader = ptr->appx_reader ();
auto res = reader.resources ();
std::vector <DX_FEATURE_LEVEL> dxlevels;
res.dx_feature_level (dxlevels);
for (auto &it : dxlevels)
{
switch (it)
{
case DX_FEATURE_LEVEL::DX_FEATURE_LEVEL_9:
dwFlags |= PKG_RESOURCES_DXFEATURE_LEVEL9; break;
case DX_FEATURE_LEVEL::DX_FEATURE_LEVEL_10:
dwFlags |= PKG_RESOURCES_DXFEATURE_LEVEL10; break;
case DX_FEATURE_LEVEL::DX_FEATURE_LEVEL_11:
dwFlags |= PKG_RESOURCES_DXFEATURE_LEVEL11; break;
case (DX_FEATURE_LEVEL)4:
dwFlags |= PKG_RESOURCES_DXFEATURE_LEVEL12; break;
}
}
break;
}
case PackageType::bundle:
{
auto br = ptr->bundle_reader ();
auto res = br.package_id_items ();
res.enumerate ([&dwFlags] (IAppxBundleManifestPackageInfo *inf) {
auto item = appx_info::appx_iditem (inf);
std::vector <DX_FEATURE_LEVEL> dxlevels;
auto qr = item.qualified_resources ();
qr.dx_feature_level (dxlevels);
for (auto &it : dxlevels)
{
switch (it)
{
case DX_FEATURE_LEVEL::DX_FEATURE_LEVEL_9:
dwFlags |= PKG_RESOURCES_DXFEATURE_LEVEL9; break;
case DX_FEATURE_LEVEL::DX_FEATURE_LEVEL_10:
dwFlags |= PKG_RESOURCES_DXFEATURE_LEVEL10; break;
case DX_FEATURE_LEVEL::DX_FEATURE_LEVEL_11:
dwFlags |= PKG_RESOURCES_DXFEATURE_LEVEL11; break;
case (DX_FEATURE_LEVEL)4:
dwFlags |= PKG_RESOURCES_DXFEATURE_LEVEL12; break;
}
}
});
break;
}
default: return 0;
}
return dwFlags;
}
// Dependencies
HLIST_DEPINFO GetManifestDependencesInfoList (_In_ HPKGMANIFESTREAD hReader)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return nullptr;
std::vector <dep_info> vec;
switch (ptr->type ())
{
case PackageType::single: {
auto reader = ptr->appx_reader ();
auto deps = reader.dependencies ();
deps.dependencies (vec);
} break;
}
size_t len = sizeof (LIST_DEPINFO) + sizeof (DEPENDENCY_INFO) * vec.size ();
HLIST_DEPINFO hList = (HLIST_DEPINFO)malloc (len);
ZeroMemory (hList, len);
hList->dwSize = 0;
for (auto &it : vec)
{
auto &dep = hList->aDepInfo [hList->dwSize ++];
dep.lpName = _wcsdup (it.name.c_str ());
dep.lpPublisher = _wcsdup (it.publisher.c_str ());
dep.verMin = VersionClassToStruct (it.minversion);
}
return hList;
}
// Capabilities
HLIST_PVOID GetManifestCapabilitiesList (_In_ HPKGMANIFESTREAD hReader)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return nullptr;
std::vector <std::wnstring> caps;
switch (ptr->type ())
{
case PackageType::single: {
auto reader = ptr->appx_reader ();
auto cap = reader.capabilities ();
std::vector <std::wstring> vec;
cap.capabilities_names (vec);
for (auto &it : vec)
{
auto cname = std::wnstring (it.c_str ());
if (cname.empty ()) continue;
push_unique (caps, cname);
}
} break;
}
size_t len = sizeof (LIST_PVOID) + sizeof (LPWSTR) * caps.size ();
HLIST_PVOID hList = (HLIST_PVOID)malloc (len);
ZeroMemory (hList, len);
hList->dwSize = 0;
for (auto &it : caps)
{
hList->alpVoid [hList->dwSize ++] = (LPVOID)_wcsdup (it.c_str ());
}
return hList;
}
HLIST_PVOID GetManifestDeviceCapabilitiesList (_In_ HPKGMANIFESTREAD hReader)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return nullptr;
std::vector <std::wnstring> caps;
switch (ptr->type ())
{
case PackageType::single: {
auto reader = ptr->appx_reader ();
auto cap = reader.capabilities ();
std::vector <std::wstring> vec;
cap.device_capabilities (vec);
for (auto &it : vec)
{
auto cname = std::wnstring (it.c_str ());
if (cname.empty ()) continue;
push_unique (caps, cname);
}
} break;
}
size_t len = sizeof (LIST_PVOID) + sizeof (LPWSTR) * caps.size ();
HLIST_PVOID hList = (HLIST_PVOID)malloc (len);
ZeroMemory (hList, len);
hList->dwSize = 0;
for (auto &it : caps)
{
hList->alpVoid [hList->dwSize ++] = (LPVOID)_wcsdup (it.c_str ());
}
return hList;
}
// Prerequisite
BOOL GetManifestPrerequisite (_In_ HPKGMANIFESTREAD hReader, _In_ LPCWSTR lpName, _Outptr_ VERSION *pVerRet)
{
auto ptr = ToPtrManifest (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;
}
return FALSE;
}

View File

@@ -286,6 +286,155 @@ extern "C"
// 获取功能名的显示名,如 internetClient 对应“访问您的 Internet 连接”。返回的是适应于系统区域语言的文本。
// 注意:返回的字符串一定要通过 free 释放。
PKGREAD_API LPWSTR GetPackageCapabilityDisplayName (LPCWSTR lpCapabilityName);
// 释放从本库中返回的字符串
// 其实通过 free 释放即可,但考虑到环境问题,那么另写了个函数
PKGREAD_API void PackageReaderFreeString (LPWSTR lpStrFromThisDll);
// ========= 以下是针对于应用清单的读取器,一些常量和类型等是复用的 =========
TEMPLATE_STRUCT (PKGMANIFESTREAD);
typedef PKGMANIFESTREAD *HPKGMANIFESTREAD;
// 创建 Manifest 读取器。
// 返回一个 Manifest Reader 句柄,初始状态未加载任何文件。
PKGREAD_API HPKGMANIFESTREAD CreateManifestReader ();
// 从文件加载 Manifest。
// 支持的输入:
// - AppxManifest.xml
// - .appx / .msix
// - .appxbundle / .msixbundle
// 加载成功后,读取器会自动识别 Manifest 类型。
PKGREAD_API BOOL LoadManifestFromFile (_In_ HPKGMANIFESTREAD hReader, _In_ LPCWSTR lpFilePath);
// 从文件加载 Manifest。
// 支持的输入:
// - AppxManifest.xml
// - .appx / .msix
// - .appxbundle / .msixbundle
// 加载成功后,读取器会自动识别 Manifest 类型。
PKGREAD_API BOOL LoadManifestFromFile (_In_ HPKGMANIFESTREAD hReader, _In_ LPCWSTR lpFilePath);
// 销毁 Manifest 读取器(必须调用)。
// 释放内部所有资源,句柄在此之后不可再使用。
PKGREAD_API void DestroyManifestReader (_In_ HPKGMANIFESTREAD hReader);
// 获取 Manifest 的类型。
// 返回值:
// - PKGTYPE_APPX :单一 Appx / Msix 包
// - PKGTYPE_BUNDLE AppxBundle / MsixBundle
// - PKGTYPE_UNKNOWN :未知或未加载
PKGREAD_API WORD GetManifestType (_In_ HPKGMANIFESTREAD hReader);
// 获取 Manifest 的类型。
// 返回值:
// - PKGTYPE_APPX :单一 Appx / Msix 包
// - PKGTYPE_BUNDLE AppxBundle / MsixBundle
// - PKGTYPE_UNKNOWN :未知或未加载
PKGREAD_API WORD GetManifestType (_In_ HPKGMANIFESTREAD hReader);
// 判断 Manifest 是否有效。
// 如果 Manifest 解析失败、结构非法或未加载,返回 FALSE。
PKGREAD_API BOOL IsManifestValid (_In_ HPKGMANIFESTREAD hReader);
// 获取 Manifest 所表示包的角色。
// 返回值:
// - PKGROLE_APPLICATION :应用包
// - PKGROLE_FRAMEWORK :框架包
// - PKGROLE_RESOURCE :资源包
// - PKGROLE_UNKNOWN :未知
//
// 说明:
// - 对于 AppxBundle永远返回 PKGROLE_APPLICATION。
PKGREAD_API WORD GetManifestRole (_In_ HPKGMANIFESTREAD hReader);
// 获取 Identity 的字符串字段。
// dwName 可取值:
// - PKG_IDENTITY_NAME
// - PKG_IDENTITY_PUBLISHER
// - PKG_IDENTITY_PACKAGEFAMILYNAME
// - PKG_IDENTITY_PACKAGEFULLNAME
// - PKG_IDENTITY_RESOURCEID
//
// 返回值:
// - 成功:返回新分配的字符串(调用者负责释放)
// - 失败:返回 NULL
PKGREAD_API LPWSTR GetManifestIdentityStringValue (_In_ HPKGMANIFESTREAD hReader, _In_ DWORD dwName);
#define GetManifestIdentityName(_In_hReader_) GetManifestIdentityStringValue (_In_hReader_, PKG_IDENTITY_NAME)
#define GetManifestIdentityPublisher(_In_hReader_) GetManifestIdentityStringValue (_In_hReader_, PKG_IDENTITY_PUBLISHER)
#define GetManifestIdentityPackageFamilyName(_In_hReader_) GetManifestIdentityStringValue (_In_hReader_, PKG_IDENTITY_PACKAGEFAMILYNAME)
#define GetManifestIdentityPackageFullName(_In_hReader_) GetManifestIdentityStringValue (_In_hReader_, PKG_IDENTITY_PACKAGEFULLNAME)
#define GetManifestIdentityResourceId(_In_hReader_) GetManifestIdentityStringValue (_In_hReader_, PKG_IDENTITY_RESOURCEID)
// 获取 Identity 的版本号。
//
// pVersion 返回格式化后的 VERSION 结构。
// 返回值:
// - TRUE :成功
// - FALSE :失败或版本不存在
PKGREAD_API BOOL GetManifestIdentityVersion (_In_ HPKGMANIFESTREAD hReader, _Out_ VERSION *pVersion);
// 获取包支持的架构信息。
// 对于单一 Appx 包,返回单一架构;
// 对于 Bundle返回所有子包架构的组合按位或
//
// 返回值通过 pdwArchi 输出,取值为 PKG_ARCHITECTURE_* 宏。
PKGREAD_API BOOL GetManifestIdentityArchitecture (_In_ HPKGMANIFESTREAD hReader, _Out_ DWORD *pdwArchi);
// 获取 Properties 中的字符串值。
// lpName 为属性名(如 "DisplayName")。
// 返回值:
// - 成功:返回新分配的字符串(调用者负责释放)
// - 失败:返回 NULL
//
// 说明:
// - 仅适用于单一 Appx 包。
PKGREAD_API LPWSTR GetManifestPropertiesStringValue (_In_ HPKGMANIFESTREAD hReader, _In_ LPCWSTR lpName);
// 获取 Properties 中的布尔值。
//
// pRet 返回布尔结果。
// 返回 HRESULT便于区分失败原因。
//
// 说明:
// - 仅适用于单一 Appx 包。
PKGREAD_API HRESULT GetManifestPropertiesBoolValue (_In_ HPKGMANIFESTREAD hReader, _In_ LPCWSTR lpName, _Outptr_ BOOL *pRet);
// 向应用枚举器中添加需要读取的 Application 属性名。
// 返回 FALSE 表示属性名非法或重复。
PKGREAD_API BOOL AddManifestApplicationItemGetName (_In_ LPCWSTR lpName);
// 从应用枚举器中移除指定的 Application 属性名。
PKGREAD_API BOOL RemoveManifestApplicationItemGetName (_In_ LPCWSTR lpName);
// 获取 Applications 枚举器。
// 返回一个应用枚举器句柄,调用者需手动销毁。
//
// 说明:
// - 仅适用于单一 Appx 包。
PKGREAD_API HAPPENUMERATOR GetManifestApplications (_In_ HPKGMANIFESTREAD hReader);
// 销毁 Applications 枚举器。
PKGREAD_API void DestroyManifestApplications (_In_ HAPPENUMERATOR hEnumerator);
// 获取资源支持的语言列表(字符串形式)。
// 返回 HLIST_PVOID内部元素为 LPWSTR。
PKGREAD_API HLIST_PVOID GetManifestResourcesLanguages (_In_ HPKGMANIFESTREAD hReader);
// 获取资源支持的语言列表LCID 形式)。
// 返回 HLIST_LCID。
PKGREAD_API HLIST_LCID GetManifestResourcesLanguagesToLcid (_In_ HPKGMANIFESTREAD hReader);
// 获取资源支持的缩放比例Scale
// 返回 HLIST_UINT32。
PKGREAD_API HLIST_UINT32 GetManifestResourcesScales (_In_ HPKGMANIFESTREAD hReader);
// 获取资源支持的 DirectX Feature Level。
// 返回值为 PKG_RESOURCES_DXFEATURE_LEVEL* 位掩码组合。
PKGREAD_API DWORD GetManifestResourcesDxFeatureLevels (_In_ HPKGMANIFESTREAD hReader);
// 获取依赖包信息列表。
// 返回 HLIST_DEPINFO其中包含名称、发布者及最低版本。
//
// 说明:
// - 仅适用于单一 Appx 包。
PKGREAD_API HLIST_DEPINFO GetManifestDependencesInfoList (_In_ HPKGMANIFESTREAD hReader);
// 获取 Capability 列表Capability
// 返回的列表元素为 LPWSTR。
//
// 说明:
// - 仅适用于单一 Appx 包。
PKGREAD_API HLIST_PVOID GetManifestCapabilitiesList (_In_ HPKGMANIFESTREAD hReader);
// 获取 Device Capability 列表。
// 返回的列表元素为 LPWSTR。
//
// 说明:
// - 仅适用于单一 Appx 包。
PKGREAD_API HLIST_PVOID GetManifestDeviceCapabilitiesList (_In_ HPKGMANIFESTREAD hReader);
// 获取指定前置条件的最低版本要求。
// lpName 为前置组件名称。
// pVerRet 返回版本结构。
// 返回 TRUE 表示存在该前置条件。
PKGREAD_API BOOL GetManifestPrerequisite (_In_ HPKGMANIFESTREAD hReader, _In_ LPCWSTR lpName, _Outptr_ VERSION *pVerRet);
#ifdef _DEFAULT_INIT_VALUE_
#undef _DEFAULT_INIT_VALUE_
#endif

View File

@@ -1336,3 +1336,202 @@ class package
appxreader appx_reader () const { return appxreader (*(IAppxPackageReader **)&this->appx); }
bundlereader bundle_reader () const { return bundlereader (*(IAppxBundleReader **)&this->bundle); }
};
class appxmanifest: virtual public com_info_quote <IAppxManifestReader>
{
using Base = com_info_quote <IAppxManifestReader>;
template <typename IComPtr, typename ReturnType, typename Fn> HRESULT get (IComPtr iptr, Fn func, ReturnType *retvalue) const { if (!iptr) return E_FAIL; return (iptr->*func) (retvalue); }
using Manifest = IAppxManifestReader;
public:
using Base::Base;
Manifest *manifest () { return pointer (); }
template <class IComPtr, class Func> HRESULT get_from_manifest (Func fn, _Outptr_ IComPtr *output) const
{
if (!pointer ()) return E_FAIL;
return get (pointer (), fn, output);
}
HRESULT get_identity (_Outptr_ IAppxManifestPackageId **output) const { return get_from_manifest <IAppxManifestPackageId *> (&Manifest::GetPackageId, output); }
appx_info::appx_id identity () const
{
IAppxManifestPackageId *ip = nullptr;
get_identity (&ip);
return appx_info::appx_id (ip);
}
appx_info::appx_res resources () const
{
return appx_info::appx_res (pointer ());
}
HRESULT get_properties (_Outptr_ IAppxManifestProperties **output) const { return get_from_manifest <IAppxManifestProperties *> (&Manifest::GetProperties, output); }
appx_info::appx_prop properties () const
{
IAppxManifestProperties *ip = nullptr;
HRESULT hr = get_properties (&ip);
return appx_info::appx_prop (ip);
}
appx_info::appx_preq prerequisites () const
{
return appx_info::appx_preq (pointer ());
}
HRESULT get_applications (_Outptr_ IAppxManifestApplicationsEnumerator **output) const { return get_from_manifest <IAppxManifestApplicationsEnumerator *> (&Manifest::GetApplications, output); }
appx_info::appx_apps applications () const
{
IAppxManifestApplicationsEnumerator *ip = nullptr;
get_applications (&ip);
return appx_info::appx_apps (ip);
}
HRESULT get_capabilities (_Outptr_ APPX_CAPABILITIES *output) const { return get_from_manifest <APPX_CAPABILITIES> (&Manifest::GetCapabilities, output); }
HRESULT get_device_capabilities (_Outptr_ IAppxManifestDeviceCapabilitiesEnumerator **output) const { return get_from_manifest <IAppxManifestDeviceCapabilitiesEnumerator *> (&Manifest::GetDeviceCapabilities, output); }
appx_info::appx_capabs capabilities () const
{
APPX_CAPABILITIES caps;
IAppxManifestDeviceCapabilitiesEnumerator *ip = nullptr;
if (pointer ()) pointer ()->GetDeviceCapabilities (&ip);
auto im = pointer ();
if (SUCCEEDED (get_capabilities (&caps))) return appx_info::appx_capabs (ip, caps, im);
return appx_info::appx_capabs (ip);
}
HRESULT get_dependencies (_Outptr_ IAppxManifestPackageDependenciesEnumerator **output) const { return get_from_manifest <IAppxManifestPackageDependenciesEnumerator *> (&Manifest::GetPackageDependencies, output); }
appx_info::appx_deps dependencies () const
{
IAppxManifestPackageDependenciesEnumerator *ip = nullptr;
get_dependencies (&ip);
return appx_info::appx_deps (ip);
}
PackageRole package_role () const
{
auto prop = properties ();
if (prop.framework ()) return PackageRole::framework;
try { if (prop.resource_package ()) return PackageRole::resource; }
catch (const std::exception &e) {}
auto app = applications ();
std::vector <std::wstring> apps;
if (app.app_user_model_ids (apps)) return PackageRole::application;
else return PackageRole::unknown;
}
};
class bundlemanifest: virtual public com_info_quote <IAppxBundleManifestReader>
{
using Base = com_info_quote <IAppxBundleManifestReader>;
public:
using Base::Base;
template <typename IComPtr, typename ReturnType, typename Fn> HRESULT get (IComPtr iptr, Fn func, ReturnType *retvalue) const { if (!iptr) return E_FAIL; return (iptr->*func) (retvalue); }
using Manifest = IAppxBundleManifestReader;
Manifest *manifest () { return pointer (); }
template <class IComPtr, class Func> HRESULT get_from_manifest (Func fn, _Outptr_ IComPtr *output) const
{
if (!pointer ()) return E_FAIL;
return get (pointer (), fn, output);
}
HRESULT get_identity (_Outptr_ IAppxManifestPackageId **output) const { return get_from_manifest (&Manifest::GetPackageId, output); }
appx_info::appx_id identity () const
{
IAppxManifestPackageId *ip = nullptr;
get_identity (&ip);
return appx_info::appx_id (ip);
}
HRESULT get_package_id_items (_Outptr_ IAppxBundleManifestPackageInfoEnumerator **output) const { return get_from_manifest (&Manifest::GetPackageInfoItems, output); }
appx_info::appx_iditems package_id_items () const
{
IAppxBundleManifestPackageInfoEnumerator *ip = nullptr;
get_package_id_items (&ip);
return appx_info::appx_iditems (ip);
}
};
HRESULT GetAppxManifestReader (_In_ LPCWSTR inputPath, _Outptr_ IAppxManifestReader **manifestReader)
{
if (!manifestReader) return E_POINTER;
*manifestReader = nullptr;
HRESULT hr;
CComPtr <IStream> stream;
CComPtr <IAppxFactory> factory;
CComPtr <IAppxPackageReader> packageReader;
hr = SHCreateStreamOnFileEx (
inputPath,
STGM_READ | STGM_SHARE_DENY_NONE,
FILE_ATTRIBUTE_NORMAL,
FALSE,
nullptr,
&stream
);
if (FAILED (hr)) return hr;
hr = CoCreateInstance (
__uuidof (AppxFactory),
nullptr,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS (&factory)
);
if (FAILED (hr)) return hr;
hr = factory->CreatePackageReader (stream, &packageReader);
if (SUCCEEDED (hr))
{
return packageReader->GetManifest (manifestReader);
}
hr = factory->CreateManifestReader (stream, manifestReader);
return hr;
}
HRESULT GetBundleManifestReader (_In_ LPCWSTR bundlePath, _Outptr_ IAppxBundleManifestReader **manifestReader)
{
if (!manifestReader) return E_POINTER;
*manifestReader = nullptr;
HRESULT hr;
CComPtr <IStream> stream;
CComPtr <IAppxBundleFactory> factory;
CComPtr <IAppxBundleReader> bundleReader;
hr = SHCreateStreamOnFileEx (
bundlePath,
STGM_READ | STGM_SHARE_DENY_NONE,
FILE_ATTRIBUTE_NORMAL,
FALSE,
nullptr,
&stream
);
if (FAILED (hr)) return hr;
hr = CoCreateInstance (
__uuidof(AppxBundleFactory),
nullptr,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS (&factory)
);
if (FAILED (hr)) return hr;
hr = factory->CreateBundleReader (stream, &bundleReader);
if (FAILED (hr)) return hr;
hr = bundleReader->GetManifest (manifestReader);
if (FAILED (hr)) return hr = factory->CreateBundleManifestReader (stream, manifestReader);
return hr;
}
class manifest
{
IAppxManifestReader *appx = nullptr;
IAppxBundleManifestReader *bundle = nullptr;
public:
~manifest () { destroy (); }
manifest (const std::wstring &filepath = L"") { create (filepath); }
void destroy ()
{
if (appx) { appx->Release (); appx = nullptr; }
if (bundle) { bundle->Release (); bundle = nullptr; }
}
bool create (const std::wstring &filepath)
{
destroy ();
if (!IsFileExists (filepath)) return false;
HRESULT hr = GetBundleManifestReader (filepath.c_str (), &bundle);
if (SUCCEEDED (hr)) return true;
if (bundle) { bundle->Release (); bundle = nullptr; }
hr = GetAppxManifestReader (filepath.c_str (), &appx);
if (SUCCEEDED (hr)) return true;
if (appx) { appx->Release (); appx = nullptr; }
return false;
}
bool valid () const { return (bool)appx ^ (bool)bundle; }
PackageType type () const
{
if (appx) return PackageType::single;
if (bundle) return PackageType::bundle;
return PackageType::unknown;
}
appxmanifest appx_reader () const { return appxmanifest (*(IAppxManifestReader **)&this->appx); }
bundlemanifest bundle_reader () const { return bundlemanifest (*(IAppxBundleManifestReader **)&this->bundle); }
};

View File

@@ -916,3 +916,9 @@ BOOL IsMsResourceUri (LPCWSTR pResUri)
catch (Exception ^e) { return false; }
return true;
}
void PriFormatFreeString (LPWSTR lpStrFromThisDll)
{
if (!lpStrFromThisDll) return;
free (lpStrFromThisDll);
}

View File

@@ -73,6 +73,8 @@ extern "C" {
PRIFORMATCLI_API BOOL IsMsResourceUriFull (LPCWSTR pResUri);
// 工具函数,用于判断是否为 MS-Resource URI
PRIFORMATCLI_API BOOL IsMsResourceUri (LPCWSTR pResUri);
// 工具函数,用于释放本地 DLL 返回的字符串
PRIFORMATCLI_API void PriFormatFreeString (LPWSTR lpStrFromThisDll);
#ifdef _DEFAULT_VALUE_SET
#undef _DEFAULT_VALUE_SET
#endif

View File

@@ -1,30 +0,0 @@
========================================================================
动态链接库priread 项目概述
========================================================================
应用程序向导已为您创建了此 priread DLL。
本文件概要介绍组成 priread 应用程序的每个文件的内容。
priread.vcxproj
这是使用应用程序向导生成的 VC++ 项目的主项目文件,其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
priread.vcxproj.filters
这是使用“应用程序向导”生成的 VC++ 项目筛选器文件。它包含有关项目文件与筛选器之间的关联信息。在 IDE 中,通过这种关联,在特定节点下以分组形式显示具有相似扩展名的文件。例如,“.cpp”文件与“源文件”筛选器关联。
priread.cpp
这是主 DLL 源文件。
/////////////////////////////////////////////////////////////////////////////
其他标准文件:
StdAfx.h, StdAfx.cpp
这些文件用于生成名为 priread.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。
/////////////////////////////////////////////////////////////////////////////
其他注释:
应用程序向导使用“TODO:”注释来指示应添加或自定义的源代码部分。
/////////////////////////////////////////////////////////////////////////////

View File

@@ -1,19 +0,0 @@
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

View File

@@ -1,163 +0,0 @@
#pragma once
#include <WinNls.h>
#include <string>
static std::wstring StringToWString (const std::string &str, UINT codePage = CP_ACP)
{
if (str.empty ()) return std::wstring ();
int len = MultiByteToWideChar (codePage, 0, str.c_str (), -1, nullptr, 0);
if (len == 0) return std::wstring ();
std::wstring wstr (len - 1, L'\0');
MultiByteToWideChar (codePage, 0, str.c_str (), -1, &wstr [0], len);
return wstr;
}
#undef GetLocaleInfo
std::string GetLocaleInfoA (LCID code, LCTYPE type)
{
char buf [LOCALE_NAME_MAX_LENGTH] = {0};
GetLocaleInfoA (code, type, buf, LOCALE_NAME_MAX_LENGTH);
return buf;
}
std::wstring GetLocaleInfoW (LCID code, LCTYPE type)
{
WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0};
GetLocaleInfoW (code, type, buf, LOCALE_NAME_MAX_LENGTH);
return buf;
}
void GetLocaleInfo (LCID code, LCTYPE type, std::wstring &output)
{
output = GetLocaleInfoW (code, type);
}
void GetLocaleInfo (LCID code, LCTYPE type, std::string &output)
{
output = GetLocaleInfoA (code, type);
}
int GetLocaleInfoEx (std::wstring lpLocaleName, LCTYPE type, std::wstring &output)
{
WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0};
int res = GetLocaleInfoEx (lpLocaleName.c_str (), type, buf, LOCALE_NAME_MAX_LENGTH);
if (&output) output = std::wstring (buf);
return res;
}
#undef SetLocaleInfo
BOOL SetLocaleInfoA (LCID code, LCTYPE type, const std::string &lcData)
{
return SetLocaleInfoA (code, type, lcData.c_str ());
}
BOOL SetLocaleInfoW (LCID code, LCTYPE type, const std::wstring &lcData)
{
return SetLocaleInfoW (code, type, lcData.c_str ());
}
BOOL SetLocaleInfo (LCID code, LCTYPE type, const std::wstring &lcData)
{
return SetLocaleInfoW (code, type, lcData);
}
BOOL SetLocaleInfo (LCID code, LCTYPE type, const std::string &lcData)
{
return SetLocaleInfoA (code, type, lcData);
}
std::string GetLocaleRestrictedCodeFromLcidA (LCID lcid)
{
return GetLocaleInfoA (lcid, 89);
}
std::wstring GetLocaleRestrictedCodeFromLcidW (LCID lcid)
{
return GetLocaleInfoW (lcid, 89);
}
void GetLocaleRestrictedCodeFromLcid (LCID lcid, std::string &ret)
{
ret = GetLocaleRestrictedCodeFromLcidA (lcid);
}
void GetLocaleRestrictedCodeFromLcid (LCID lcid, std::wstring &ret)
{
ret = GetLocaleRestrictedCodeFromLcidW (lcid);
}
std::string GetLocaleElaboratedCodeFromLcidA (LCID lcid)
{
return GetLocaleInfoA (lcid, 90);
}
std::wstring GetLocaleElaboratedCodeFromLcidW (LCID lcid)
{
return GetLocaleInfoW (lcid, 90);
}
void GetLocaleElaboratedCodeFromLcid (LCID lcid, std::wstring &ret)
{
ret = GetLocaleElaboratedCodeFromLcidW (lcid);
}
void GetLocaleElaboratedCodeFromLcid (LCID lcid, std::string &ret)
{
ret = GetLocaleElaboratedCodeFromLcidA (lcid);
}
LCID LocaleCodeToLcidW (LPCWSTR localeCode)
{
BYTE buf [LOCALE_NAME_MAX_LENGTH * sizeof (WCHAR)] = {0};
int res = GetLocaleInfoEx (localeCode, LOCALE_RETURN_NUMBER | LOCALE_ILANGUAGE, (LPWSTR)buf, LOCALE_NAME_MAX_LENGTH);
LCID lcid = *((LCID *)buf);
return lcid;
}
LCID LocaleCodeToLcidA (LPCSTR localeCode)
{
std::wstring lcWide = StringToWString (std::string (localeCode));
return LocaleCodeToLcidW (lcWide.c_str ());
}
LCID LocaleCodeToLcid (const std::wstring &loccode)
{
return LocaleCodeToLcidW (loccode.c_str ());
}
LCID LocaleCodeToLcid (const std::string &loccode)
{
return LocaleCodeToLcidA (loccode.c_str ());
}
std::string GetLocaleRestrictedCodeA (LPCSTR lc)
{
return GetLocaleInfoA (LocaleCodeToLcidA (lc), 89);
}
std::string GetLocaleRestrictedCodeA (const std::string &lc)
{
return GetLocaleInfoA (LocaleCodeToLcidA (lc.c_str ()), 89);
}
std::wstring GetLocaleRestrictedCodeW (LPCWSTR lc)
{
return GetLocaleInfoW (LocaleCodeToLcidW (lc), 89);
}
std::wstring GetLocaleRestrictedCodeW (const std::wstring &lc)
{
return GetLocaleInfoW (LocaleCodeToLcidW (lc.c_str ()), 89);
}
std::wstring GetLocaleRestrictedCode (const std::wstring &lc) { return GetLocaleRestrictedCodeW (lc); }
std::string GetLocaleRestrictedCode (const std::string &lc) { return GetLocaleRestrictedCodeA (lc); }
std::string GetLocaleElaboratedCodeA (LPCSTR lc)
{
return GetLocaleInfoA (LocaleCodeToLcidA (lc), 90);
}
std::string GetLocaleElaboratedCodeA (const std::string &lc)
{
return GetLocaleInfoA (LocaleCodeToLcidA (lc.c_str ()), 90);
}
std::wstring GetLocaleElaboratedCodeW (LPCWSTR lc)
{
return GetLocaleInfoW (LocaleCodeToLcidW (lc), 90);
}
std::wstring GetLocaleElaboratedCodeW (const std::wstring &lc)
{
return GetLocaleInfoW (LocaleCodeToLcidW (lc.c_str ()), 90);
}
std::wstring GetLocaleElaboratedCode (const std::wstring &lc) { return GetLocaleElaboratedCodeW (lc); }
std::string GetLocaleElaboratedCode (const std::string &lc) { return GetLocaleElaboratedCodeA (lc); }
std::string LcidToLocaleCodeA (LCID lcid, char divide = '-')
{
return GetLocaleRestrictedCodeFromLcidA (lcid) + divide + GetLocaleElaboratedCodeFromLcidA (lcid);
}
std::wstring LcidToLocaleCodeW (LCID lcid, WCHAR divide = L'-')
{
return GetLocaleRestrictedCodeFromLcidW (lcid) + divide + GetLocaleElaboratedCodeFromLcidW (lcid);
}
std::wstring LcidToLocaleCode (LCID lcid, WCHAR divide = L'-') { return LcidToLocaleCodeW (lcid, divide); }
std::string LcidToLocaleCode (LCID lcid, char divide = '-') { return LcidToLocaleCodeA (lcid, divide); }

View File

@@ -1,456 +0,0 @@
#pragma once
#include <string>
#include <locale>
#include <cctype>
namespace l0km
{
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>> inline std::basic_string<E, TR, AL> toupper (const std::basic_string <E, TR, AL> &src)
{
std::basic_string <E, TR, AL> dst = src;
static const std::locale loc;
const std::ctype <E> &ctype = std::use_facet <std::ctype <E>> (loc);
for (typename std::basic_string <E, TR, AL>::size_type i = 0; i < src.size (); ++ i)
{
dst [i] = ctype.toupper (src [i]);
}
return dst;
}
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>> inline std::basic_string <E, TR, AL> tolower (const std::basic_string <E, TR, AL> &src)
{
std::basic_string <E, TR, AL> dst = src;
static const std::locale loc;
const std::ctype <E> &ctype = std::use_facet <std::ctype <E>> (loc);
for (typename std::basic_string <E, TR, AL>::size_type i = 0; i < src.size (); ++ i)
{
dst [i] = ctype.tolower (src [i]);
}
return dst;
}
inline char toupper (char ch)
{
if (ch < -1) return ch;
static const std::locale loc;
return std::use_facet <std::ctype <char>> (loc).toupper (ch);
}
inline char tolower (char ch)
{
if (ch < -1) return ch;
static const std::locale loc;
return std::use_facet <std::ctype <char>> (loc).tolower (ch);
}
inline wchar_t toupper (wchar_t ch)
{
if (ch < -1) return ch;
static const std::locale loc;
return std::use_facet <std::ctype <wchar_t>> (loc).toupper (ch);
}
inline wchar_t tolower (wchar_t ch)
{
if (ch < -1) return ch;
static const std::locale loc;
return std::use_facet <std::ctype <wchar_t>> (loc).tolower (ch);
}
inline int toupper (int ch)
{
if (ch < -1) return ch;
static const std::locale loc;
return std::use_facet <std::ctype <int>> (loc).toupper (ch);
}
inline int tolower (int ch)
{
if (ch < -1) return ch;
static const std::locale loc;
return std::use_facet <std::ctype <int>> (loc).tolower (ch);
}
}
template <typename ct> bool is_blank (ct &ch)
{
return ch == ct (' ') || ch == ct ('\t') || ch == ct ('\n');
}
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>> std::basic_string <E, TR, AL> NormalizeString (const std::basic_string <E, TR, AL> &str, bool upper = false, bool includemidblank = false)
{
typedef std::basic_string <E, TR, AL> string_type;
string_type result;
if (str.empty ()) return result;
auto begin_it = str.begin ();
auto end_it = str.end ();
while (begin_it != end_it && is_blank (*begin_it)) ++begin_it;
while (end_it != begin_it && is_blank (*(end_it - 1))) --end_it;
bool in_space = false;
for (auto it = begin_it; it != end_it; ++ it)
{
if (is_blank (*it))
{
if (includemidblank)
{
if (!in_space)
{
result.push_back (E (' '));
in_space = true;
}
}
else
{
result.push_back (*it);
in_space = true;
}
}
else
{
result.push_back (*it);
in_space = false;
}
}
if (upper) return l0km::toupper (result);
else return l0km::tolower (result);
}
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>> bool IsNormalizeStringEquals (const std::basic_string <E, TR, AL> &l, const std::basic_string <E, TR, AL> &r, bool includemidblank = false)
{
auto _local_strlen = [] (const E *p) -> size_t {
size_t cnt = 0;
while (*(p + cnt)) { cnt ++; }
return cnt;
};
const E *pl = l.c_str ();
const E *pr = r.c_str ();
while (*pl && is_blank (*pl)) ++ pl;
while (*pr && is_blank (*pr)) ++ pr;
const E *el = l.c_str () + _local_strlen (l.c_str ());
const E *er = r.c_str () + _local_strlen (r.c_str ());
while (el > pl && is_blank (*(el - 1))) --el;
while (er > pr && is_blank (*(er - 1))) --er;
while (pl < el && pr < er)
{
if (includemidblank)
{
if (is_blank (*pl) && is_blank (*pr))
{
while (pl < el && is_blank (*pl)) ++pl;
while (pr < er && is_blank (*pr)) ++pr;
continue;
}
else if (is_blank (*pl))
{
while (pl < el && is_blank (*pl)) ++pl;
continue;
}
else if (is_blank (*pr))
{
while (pr < er && is_blank (*pr)) ++pr;
continue;
}
}
if (l0km::tolower (*pl) != l0km::tolower (*pr)) return false;
++ pl;
++ pr;
}
while (pl < el && is_blank (*pl)) ++ pl;
while (pr < er && is_blank (*pr)) ++ pr;
return pl == el && pr == er;
}
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>> int64_t NormalizeStringCompare (const std::basic_string <E, TR, AL> &l, const std::basic_string <E, TR, AL> &r, bool includemidblank = false)
{
auto _local_strlen = [] (const E *p) -> size_t {
size_t cnt = 0;
while (*(p + cnt)) { cnt ++; }
return cnt;
};
const E *pl = l.c_str ();
const E *pr = r.c_str ();
while (*pl && is_blank (*pl)) ++ pl;
while (*pr && is_blank (*pr)) ++ pr;
const E *el = l.c_str () + _local_strlen (l.c_str ());
const E *er = r.c_str () + _local_strlen (r.c_str ());
while (el > pl && is_blank (*(el - 1))) -- el;
while (er > pr && is_blank (*(er - 1))) -- er;
while (pl < el && pr < er)
{
if (includemidblank)
{
if (is_blank (*pl) && is_blank (*pr))
{
while (pl < el && is_blank (*pl)) ++pl;
while (pr < er && is_blank (*pr)) ++pr;
continue;
}
else if (is_blank (*pl))
{
while (pl < el && is_blank (*pl)) ++pl;
continue;
}
else if (is_blank (*pr))
{
while (pr < er && is_blank (*pr)) ++pr;
continue;
}
}
E chl = l0km::tolower (*pl);
E chr = l0km::tolower (*pr);
if (chl != chr) return (int64_t)chl - (int64_t)chr;
++ pl;
++ pr;
}
while (pl < el && is_blank (*pl)) ++ pl;
while (pr < er && is_blank (*pr)) ++ pr;
if (pl == el && pr == er) return 0;
if (pl == el) return -1;
if (pr == er) return 1;
return (int64_t)l0km::tolower (*pl) - (int64_t)l0km::tolower (*pr);
}
template <typename CharT> bool IsNormalizeStringEquals (const CharT *l, const CharT *r, bool includemidblank = false)
{
if (!l || !r) return l == r;
auto skip_blank = [] (const CharT *&p)
{
while (*p && is_blank (*p)) ++ p;
};
const CharT *p1 = l;
const CharT *p2 = r;
skip_blank (p1);
skip_blank (p2);
while (*p1 && *p2)
{
CharT ch1 = l0km::tolower (*p1);
CharT ch2 = l0km::tolower (*p2);
if (ch1 != ch2) return false;
++ p1;
++ p2;
if (includemidblank)
{
if (is_blank (*p1) || is_blank (*p2))
{
skip_blank (p1);
skip_blank (p2);
}
}
}
skip_blank (p1);
skip_blank (p2);
return *p1 == 0 && *p2 == 0;
}
template <typename CharT> int64_t NormalizeStringCompare (const CharT *l, const CharT *r, bool includemidblank = false)
{
if (!l || !r) return l ? 1 : (r ? -1 : 0);
auto skip_blank = [] (const CharT *&p)
{
while (*p && is_blank (*p)) ++ p;
};
const CharT *p1 = l;
const CharT *p2 = r;
skip_blank (p1);
skip_blank (p2);
while (*p1 && *p2)
{
CharT ch1 = l0km::tolower (*p1);
CharT ch2 = l0km::tolower (*p2);
if (ch1 != ch2) return (ch1 < ch2) ? -1 : 1;
++ p1;
++ p2;
if (includemidblank)
{
if (is_blank (*p1) || is_blank (*p2))
{
skip_blank (p1);
skip_blank (p2);
}
}
}
skip_blank (p1);
skip_blank (p2);
if (*p1 == 0 && *p2 == 0) return 0;
if (*p1 == 0) return -1;
return 1;
}
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>> bool IsNormalizeStringEmpty (const std::basic_string <E, TR, AL> &str)
{
return IsNormalizeStringEquals (str, std::basic_string <E, TR, AL> ());
}
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>> std::basic_string <E, TR, AL> StringTrim (const std::basic_string <E, TR, AL> &str, bool includemidblank = false)
{
typedef std::basic_string <E, TR, AL> string_type;
typedef typename string_type::size_type size_type;
if (str.empty ()) return string_type ();
size_type first = 0;
size_type last = str.size ();
while (first < last && is_blank (str [first])) ++first;
while (last > first && is_blank (str [last - 1])) --last;
if (first == last) return string_type ();
string_type result;
result.reserve (last - first);
bool in_space = false;
for (size_type i = first; i < last; ++ i)
{
if (is_blank (str [i]))
{
if (includemidblank)
{
if (!in_space)
{
result.push_back (E (' '));
in_space = true;
}
}
else
{
result.push_back (str [i]);
in_space = true;
}
}
else
{
result.push_back (str [i]);
in_space = false;
}
}
return result;
}
template <typename E, typename TR = std::char_traits<E>, typename AL = std::allocator <E>> size_t GetNormalizeStringLength (const std::basic_string <E, TR, AL> &str, bool includemidblank = false)
{
typedef typename std::basic_string <E, TR, AL>::size_type size_type;
if (str.empty ()) return 0;
size_type first = 0, last = str.size ();
while (first < last && is_blank (str [first])) ++first;
while (last > first && is_blank (str [last - 1])) --last;
if (first == last) return 0;
size_t length = 0;
bool in_space = false;
for (size_type i = first; i < last; ++i)
{
if (is_blank (str [i]))
{
if (includemidblank)
{
if (!in_space)
{
++ length;
in_space = true;
}
}
else
{
++ length;
in_space = true;
}
}
else
{
++ length;
in_space = false;
}
}
return length;
}
namespace std
{
template <typename ct, typename tr = std::char_traits <ct>, typename al = std::allocator <ct>> class basic_nstring: public std::basic_string <ct, tr, al>
{
using base = std::basic_string <ct, tr, al>;
bool default_upper = false, default_include_blank_in_str = false;
public:
using typename base::size_type;
using typename base::value_type;
using base::base;
basic_nstring (): base (), default_upper (false), default_include_blank_in_str (false) {}
basic_nstring (const ct *pStr): base (pStr), default_upper (false), default_include_blank_in_str (false) {}
basic_nstring (const base &str): base (str) {}
basic_nstring (base &&str): base (std::move (str)) {}
basic_nstring (const ct *data, size_type count): base (data, count), default_upper (false), default_include_blank_in_str (false) {}
template <std::size_t N> basic_nstring (const ct (&arr) [N]) : base (arr, N) {}
template <typename InputIt> basic_nstring (InputIt first, InputIt last): base (first, last), default_upper (false), default_include_blank_in_str (false) {}
bool upper_default () const { return this->default_upper; }
bool upper_default (bool value) { return this->default_upper = value; }
bool include_blank_in_str_middle () const { return this->default_include_blank_in_str; }
bool include_blank_in_str_middle (bool value) { return this->default_include_blank_in_str = value; }
base normalize (bool upper, bool includemidblank) const
{
return NormalizeString <ct, tr, al> (*this, upper, includemidblank);
}
base normalize (bool upper) const
{
return this->normalize (upper, default_include_blank_in_str);
}
base normalize () const { return this->normalize (default_upper); }
base upper (bool includemidblank) const
{
return NormalizeString <ct, tr, al> (*this, true, includemidblank);
}
base upper () const { return this->upper (default_include_blank_in_str); }
base lower (bool includemidblank) const
{
return NormalizeString <ct, tr, al> (*this, false, includemidblank);
}
base lower () const { return this->lower (default_include_blank_in_str); }
base trim (bool includemidblank) const
{
return StringTrim <ct, tr, al> (*this, includemidblank);
}
base trim () const { return this->trim (default_include_blank_in_str); }
size_t length (bool includemidblank) const { return GetNormalizeStringLength (*this, includemidblank); }
size_t length () const { return length (default_include_blank_in_str); }
bool empty () const
{
return IsNormalizeStringEmpty (*this);
}
bool equals (const base &another, bool includemidblank) const
{
return IsNormalizeStringEquals <ct, tr, al> (*this, another, includemidblank);
}
bool equals (const base &another) const { return equals (another, default_include_blank_in_str); }
int64_t compare (const base &another, bool includemidblank) const
{
return NormalizeStringCompare <ct, tr, al> (*this, another, includemidblank);
}
int64_t compare (const base &another) const { return compare (another, default_include_blank_in_str); }
base &string () { return *this; }
base to_string (bool upper, bool includemidblank) const { return this->normalize (upper, includemidblank); }
base to_string (bool upper) const { return this->normalize (upper, default_include_blank_in_str); }
base to_string () const { return this->normalize (default_upper); }
bool operator == (const base &other) const { return equals (other, false); }
bool operator != (const base &other) const { return !equals (other, false); }
bool operator < (const base &other) const { return compare (other, false) < 0; }
bool operator > (const base &other) const { return compare (other, false) > 0; }
bool operator <= (const base &other) const { return compare (other, false) <= 0; }
bool operator >= (const base &other) const { return compare (other, false) >= 0; }
int64_t operator - (const base &other) const { return compare (other, false); }
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>>
static bool equals (const std::basic_string <E> &l, const std::basic_string <E> &r, bool remove_mid_blank = false)
{
return IsNormalizeStringEquals <E, TR, AL> (l, r, remove_mid_blank);
}
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>>
static int64_t compare (const std::basic_string <E> &l, const std::basic_string <E> &r, bool remove_mid_blank = false)
{
return NormalizeStringCompare <E, TR, AL> (l, r, remove_mid_blank);
}
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>>
static std::basic_string <E, TR, AL> normalize (const std::basic_string <E> &str, bool to_upper = false, bool remove_mid_blank = false)
{
return NormalizeString <E, TR, AL> (str, to_upper, remove_mid_blank);
}
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>>
static std::basic_string <E, TR, AL> trim (const std::basic_string <E> &str, bool remove_mid_blank = false)
{
return StringTrim <E, TR, AL> (str, remove_mid_blank);
}
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>>
static size_t length (const std::basic_string <E> &str, bool remove_mid_blank = false)
{
return GetNormalizeStringLength <E, TR, AL> (str, remove_mid_blank);
}
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>>
static bool empty (const std::basic_string <E> &str)
{
return IsNormalizeStringEmpty <E, TR, AL> (str);
}
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>>
static std::basic_nstring <E, TR, AL> to_nstring (std::basic_string <E> &str) { return std::basic_nstring <E> (str); }
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>>
static std::basic_nstring <E, TR, AL> toupper (const std::basic_nstring <E, TR, AL> &str) { return l0km::toupper (str); }
template <typename E, typename TR = std::char_traits <E>, typename AL = std::allocator <E>>
static std::basic_nstring <E, TR, AL> tolower (const std::basic_nstring <E, TR, AL> &str) { return l0km::tolower (str); }
};
typedef basic_nstring <char> nstring;
typedef basic_nstring <wchar_t> wnstring;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,22 +0,0 @@
// 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;
}

View File

@@ -1,22 +0,0 @@
// 下列 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

@@ -1,182 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{99D714D9-F40D-425B-BAFA-8B41C17971A5}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>priread</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;PRIREAD_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;PRIREAD_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;PRIREAD_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;PRIREAD_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="localeex.h" />
<ClInclude Include="nstring.h" />
<ClInclude Include="prifile.h" />
<ClInclude Include="priread.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="themeinfo.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</PrecompiledHeader>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
</PrecompiledHeader>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</PrecompiledHeader>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
</PrecompiledHeader>
</ClCompile>
<ClCompile Include="priread.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -1,54 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="源文件">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="targetver.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="priread.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="prifile.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="nstring.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="localeex.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="themeinfo.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="priread.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="dllmain.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

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

View File

@@ -1,20 +0,0 @@
// stdafx.h : 标准系统包含文件的包含文件,
// 或是经常使用但不常更改的
// 特定于项目的包含文件
//
#pragma once
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN // 从 Windows 头中排除极少使用的资料
// Windows 头文件:
#include <windows.h>
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // 某些 CString 构造函数将是显式的
#include <atlbase.h>
#include <atlstr.h>
// TODO: 在此处引用程序需要的其他头文件

View File

@@ -1,8 +0,0 @@
#pragma once
// 包括 SDKDDKVer.h 将定义可用的最高版本的 Windows 平台。
// 如果要为以前的 Windows 平台生成应用程序,请包括 WinSDKVer.h并将
// 将 _WIN32_WINNT 宏设置为要支持的平台,然后再包括 SDKDDKVer.h。
#include <SDKDDKVer.h>

View File

@@ -1,40 +0,0 @@
#pragma once
#include <Windows.h>
bool IsHighContrastEnabled ()
{
HIGHCONTRAST hc = {sizeof (HIGHCONTRAST)};
if (SystemParametersInfo (SPI_GETHIGHCONTRAST, sizeof (hc), &hc, 0)) return (hc.dwFlags & HCF_HIGHCONTRASTON) != 0;
return false;
}
enum class HighContrastTheme
{
None,
Black,
White,
Other
};
HighContrastTheme GetHighContrastTheme ()
{
HIGHCONTRAST hc = {sizeof (HIGHCONTRAST)};
if (!SystemParametersInfo (SPI_GETHIGHCONTRAST, sizeof (hc), &hc, 0)) return HighContrastTheme::None;
if (!(hc.dwFlags & HCF_HIGHCONTRASTON)) return HighContrastTheme::None;
COLORREF bgColor = GetSysColor (COLOR_WINDOW);
COLORREF textColor = GetSysColor (COLOR_WINDOWTEXT);
int brightnessBg = (GetRValue (bgColor) + GetGValue (bgColor) + GetBValue (bgColor)) / 3;
int brightnessText = (GetRValue (textColor) + GetGValue (textColor) + GetBValue (textColor)) / 3;
if (brightnessBg < brightnessText) return HighContrastTheme::Black;
else if (brightnessBg > brightnessText) return HighContrastTheme::White;
else return HighContrastTheme::Other;
}
int GetDPI ()
{
HDC hDC = GetDC (NULL);
int DPI_A = (int)(((double)GetDeviceCaps (hDC, 118) / (double)GetDeviceCaps (hDC, 8)) * 100);
int DPI_B = (int)(((double)GetDeviceCaps (hDC, 88) / 96) * 100);
ReleaseDC (NULL, hDC);
if (DPI_A == 100) return DPI_B;
else if (DPI_B == 100) return DPI_A;
else if (DPI_A == DPI_B) return DPI_A;
else return 0;
}

View File

@@ -12,6 +12,18 @@
DarkModeBackgroundColor='#001629' />
</VisualElements>
</Application>
<Application Id='Manager'>
<VisualElements
DisplayName='Package Manager'
Logo='Settings.Assets\Logo.png'
SmallLogo='Settings.Assets\SmallLogo.png'
ForegroundText='light'
BackgroundColor='#159d9d'>
<DefaultTile ShowName='allLogos' />
<SplashScreen Image="VisualElements\splash\settings\splashscreen.png"
BackgroundColor="#159d9d" DarkModeBackgroundColor='#2e1e5c' />
</VisualElements>
</Application>
<Application Id='Settings'>
<VisualElements
DisplayName='Settings'

Binary file not shown.

View File

@@ -170,7 +170,7 @@
element.style.animation = generateAnimeString(swKeyFrames, uMillisecond, swTimingFunc, uDelayMs, swIteration, swDirection, swFillMode, swPlayState);
element.addEventListener("animationend", function() {
element.style.animation = "";
complete();
complete(element);
});
});
}

396
shared/html/js/appbar.js Normal file
View File

@@ -0,0 +1,396 @@
(function(global) {
"use strict";
// 基类:提供 element 管理与基础 dispose 行为
function PMAppBarBaseMember() {
var _element = null;
Object.defineProperty(this, "element", {
configurable: true, // <- 关键:允许子类重定义该属性
enumerable: false,
get: function() { return _element; },
set: function(value) {
_element = value;
try {
if (_element) {
// 让 DOM 节点可以反查到对应的 member
_element.appBarMember = this;
}
} catch (e) {}
}
});
// 可被子类或外部调用来从 DOM 中移除自身
this.dispose = function() {
try {
if (this.element && this.element.parentNode) {
this.element.parentNode.removeChild(this.element);
}
} catch (e) {}
};
}
function PMAppBarCommand() {
PMAppBarBaseMember.call(this);
var _button = document.createElement("button");
var _iconcontainer = document.createElement("span");
var _iconnode = document.createElement("span");
var _labelnode = document.createElement("span");
_button.appendChild(_iconcontainer);
_iconcontainer.appendChild(_iconnode);
_button.appendChild(_labelnode);
_button.classList.add("win-command");
_button.setAttribute("role", "menuitem");
_iconcontainer.classList.add("win-commandicon");
_iconcontainer.classList.add("win-commandring");
_iconnode.classList.add("win-commandimage");
_labelnode.classList.add("win-label");
_iconcontainer.tabIndex = -1;
_iconnode.tabIndex = -1;
_labelnode.tabIndex = -1;
_button.classList.add("win-global");
Windows.UI.Event.Util.addEvent(_button, "keydown", function(event) {
if (event.keyCode === 13) {
_button.click();
}
});
Object.defineProperty(this, "element", {
get: function() { return _button; },
set: function(value) { _button = value; }
});
Object.defineProperty(this, "icon", {
get: function() { return _iconnode.innerHTML; },
set: function(value) { _iconnode.innerHTML = value; }
});
Object.defineProperty(this, "label", {
get: function() { return _labelnode.textContent; },
set: function(value) { _labelnode.textContent = value; }
});
Object.defineProperty(this, "onclick", {
get: function() { return _button.onclick; },
set: function(value) { _button.onclick = value; }
});
Object.defineProperty(this, "selectable", {
get: function() { return _button.classList.contains("win-selectable"); },
set: function(value) {
try { Windows.UI.Event.Util.removeEvent(this.element, "click", selectHandler); } catch (e) {}
_button.classList.toggle("win-selectable", value);
if (!value) {
if (_button.classList.contains("win-selected")) {
_button.classList.remove("win-selected");
}
}
if (value) Windows.UI.Event.Util.addEvent(this.element, "click", selectHandler);
else Windows.UI.Event.Util.removeEvent(this.element, "click", selectHandler);
}
});
Object.defineProperty(this, "selected", {
get: function() { return _button.classList.contains("win-selected"); },
set: function(value) { _button.classList.toggle("win-selected", value); }
});
Object.defineProperty(this, "disabled", {
get: function() { try { return this.element.disabled; } catch (e) { return false; } },
set: function(value) { try { this.element.disabled = value; } catch (e) {} }
});
// global 或 selection (始终显示或有选择时显示)
Object.defineProperty(this, "section", {
get: function() {
if (_button.classList.contains("win-global")) return "global";
if (_button.classList.contains("win-selection")) return "selection";
return "none";
},
set: function(value) {
_button.classList.remove("win-global");
_button.classList.remove("win-selection");
if (value == "global") _button.classList.add("win-global");
if (value == "selection") _button.classList.add("win-selection");
}
});
function selectHandler(event) {
_button.classList.toggle("win-selected");
}
this.addEventListener = function(type, listener) {
try { Windows.UI.Event.Util.addEvent(this.element, type, listener); } catch (e) {}
};
this.removeEventListener = function(type, listener) {
try { Windows.UI.Event.Util.removeEvent(this.element, type, listener); } catch (e) {}
};
}
function PMAppBarSeparator() {
PMAppBarBaseMember.call(this);
var _hr = document.createElement("hr");
_hr.classList.add("win-command");
_hr.classList.add("win-global");
_hr.setAttribute("role", "separator");
Object.defineProperty(this, "element", {
get: function() { return _hr; },
set: function(value) { _hr = value; }
});
}
function PMAppBar(container) {
var _container = container;
var _enable = true;
function init(node) {
var classNames = [
"win-overlay",
"win-commandlayout",
"win-appbar",
"appbar"
]
try {
for (var i = 0; i < classNames.length; i++) {
if (!node.classList.contains(classNames[i]))
node.classList.add(classNames[i]);
}
} catch (e) {}
try {
node.appBarControl = this;
} catch (e) {}
}
Object.defineProperty(this, "element", {
get: function() { return _container; },
set: function(value) {
_container = value;
init(value);
// 将已有成员渲染到新的容器中
try {
// 先移除所有成员 DOM如果之前挂载过
for (var i = 0; i < this._members.length; i++) {
try {
var mEl = this._members[i].element;
if (mEl && mEl.parentNode === _container) {
_container.removeChild(mEl);
}
} catch (e) {}
}
// 重新挂载所有成员,按数组顺序
for (i = 0; i < this._members.length; i++) {
try {
var el = this._members[i].element;
if (el) _container.appendChild(el);
} catch (e) {}
}
} catch (e) {}
}
});
// 成员管理
this._members = [];
// 返回内部数组引用(只读语义上)
Object.defineProperty(this, "members", {
get: function() { return this._members; }
});
// 添加成员到末尾,返回索引;若失败返回 -1
this.add = function(member) {
if (!member || !member.element) return -1;
this._members.push(member);
try {
if (_container) _container.appendChild(member.element);
} catch (e) {}
this._updateSelectionVisibility();
return this._members.length - 1;
};
this.addMember = this.add; // alias
// 在指定索引处插入(如果 index 为 undefined 或超范围,则 append
this.insertAt = function(member, index) {
if (!member || !member.element) return -1;
var len = this._members.length;
if (typeof index !== "number" || index < 0 || index > len) {
return this.add(member);
}
this._members.splice(index, 0, member);
try {
if (_container) {
var refNode = _container.childNodes[index] || null;
_container.insertBefore(member.element, refNode);
}
} catch (e) {}
this._updateSelectionVisibility();
return index;
};
// remove 接受成员对象或索引
this.remove = function(memberOrIndex) {
var idx = -1;
if (typeof memberOrIndex === "number") {
idx = memberOrIndex;
} else {
idx = this._members.indexOf(memberOrIndex);
}
if (idx < 0 || idx >= this._members.length) return false;
var removed = this._members.splice(idx, 1)[0];
try {
if (removed && removed.element && removed.element.parentNode) {
removed.element.parentNode.removeChild(removed.element);
}
} catch (e) {}
this._updateSelectionVisibility();
return true;
};
// 替换指定索引的成员,返回 true/false
this.replaceAt = function(index, member) {
if (!member || !member.element) return false;
if (typeof index !== "number" || index < 0 || index >= this._members.length) return false;
var old = this._members[index];
this._members[index] = member;
try {
if (_container && old && old.element) {
// 如果 old.element 在容器中,直接 replaceChild
if (old.element.parentNode === _container) {
_container.replaceChild(member.element, old.element);
} else {
// 备用:在位置 index 插入
var ref = _container.childNodes[index] || null;
_container.insertBefore(member.element, ref);
}
} else if (_container) {
// 没有 old 元素,直接 append
_container.appendChild(member.element);
}
} catch (e) {}
this._updateSelectionVisibility();
return true;
};
this.getMember = function(index) {
return this._members[index];
};
this.indexOf = function(member) {
return this._members.indexOf(member);
};
this.clear = function() {
while (this._members.length) {
var m = this._members.shift();
try {
if (m && m.element && m.element.parentNode) {
m.element.parentNode.removeChild(m.element);
}
} catch (e) {}
}
};
var timer = null;
var isupdating = false;
function waitTimer(ms) {
clearTimeout(timer);
isupdating = true;
timer = setTimeout(function(t) {
isupdating = false;
t = null;
}, ms, timer);
}
Object.defineProperty(this, "isupdating", {
get: function() { return isupdating; }
});
var touchHide = document.createElement("div");
touchHide.classList.add("appbar-touchhide");
touchHide.style.display = "none";
Windows.UI.Event.Util.addEvent(touchHide, "click", function(event) {
touchHide.style.display = "none";
this.hide();
}.bind(this));
document.body.appendChild(touchHide);
function showTouchHide() {
if (touchHide == null || touchHide == void 0) {
touchHide = document.createElement("div");
touchHide.classList.add("appbar-touchhide");
}
touchHide.style.display = "";
}
function hideTouchHide() {
touchHide.style.display = "none";
}
this.show = function() {
try {
if (!_enable) return;
if (!this.element.classList.contains("show"))
this.element.classList.add("show");
waitTimer(500);
showTouchHide();
} catch (e) {}
};
this.hide = function() {
try {
if (this.element.classList.contains("show"))
this.element.classList.remove("show");
waitTimer(500);
hideTouchHide();
} catch (e) {}
};
this.setSelectionActive = function(active) {
this._hasSelection = !!active;
this._updateSelectionVisibility();
};
this._updateSelectionVisibility = function() {
for (var i = 0; i < this._members.length; i++) {
var el = this._members[i].element;
if (el && el.classList && el.classList.contains("win-selection")) {
el.style.display = this._hasSelection ? "" : "none";
}
}
};
Object.defineProperty(this, "enabled", {
get: function() { return _enable; },
set: function(value) {
_enable = value;
if (!value) {
this.hide();
}
}
});
Object.defineProperty(this, "isshowing", {
get: function() { return this.element.classList.contains("show"); },
set: function(value) {
if (value) {
this.show();
} else {
this.hide();
}
}
});
this._eventShowHandler = function(event) {
if (!this.isshowing) this.show();
else this.hide();
};
this._eventHideHandler = function(event) {
this.hide();
};
var EventUtil = Windows.UI.Event.Util;
var self = this;
EventUtil.addEvent(document, "contextmenu", function(event) {
self._eventShowHandler(event);
event.preventDefault();
});
var pressTimer = null;
EventUtil.addEvent(document, "mousedown", function(event) {
if (!self._enable) return;
pressTimer = setTimeout(function(e) {
self._eventShowHandler(e);
event.preventDefault();
}, 600, event);
});
EventUtil.addEvent(document, "mouseup", function() {
clearTimeout(pressTimer);
});
}
global.AppBar = {
AppBar: PMAppBar,
Command: PMAppBarCommand,
Separator: PMAppBarSeparator,
BaseMember: PMAppBarBaseMember
};
})(this);

479
shared/html/js/datasrc.js Normal file
View File

@@ -0,0 +1,479 @@
(function(global) {
"use strict";
global.DataView = {
ChangeType: {
add: "add",
remove: "remove",
change: "change",
clear: "clear",
move: "move",
sort: "sort",
},
};
var childAnimeDuration = 120;
var parentAnimeDuration = 400;
function showItemAmine(node) {
return Windows.UI.Animation.runAsync(node, [
Windows.UI.Animation.Keyframes.Scale.up,
Windows.UI.Animation.Keyframes.Opacity.visible,
], childAnimeDuration);
}
function hideItemAmine(node) {
return Windows.UI.Animation.runAsync(node, [
Windows.UI.Animation.Keyframes.Scale.down,
Windows.UI.Animation.Keyframes.Opacity.hidden,
], childAnimeDuration);
}
function updateItemAmine(node, updateCallback) {
return Windows.UI.Animation.runAsync(node, [
Windows.UI.Animation.Keyframes.Opacity.hidden,
Windows.UI.Animation.Keyframes.Scale.down
], 120).then(function() {
if (updateCallback && typeof updateCallback === 'function') {
updateCallback(node);
}
return Windows.UI.Animation.runAsync(node, [
Windows.UI.Animation.Keyframes.Opacity.visible,
Windows.UI.Animation.Keyframes.Scale.up
], 120);
}).then(function() {
return node;
});
}
function PMChangeEvent(type, datas, detailOperation) {
this.type = type; // ChangeType
this.datas = datas || []; // 受影响的数据
this.detail = detailOperation || null;
}
function PMDataSource() {
var _list = [];
var _listeners = [];
this.subscribe = function(fn) {
if (typeof fn === "function") {
_listeners.push(fn);
}
};
function emit(evt) {
for (var i = 0; i < _listeners.length; i++) {
_listeners[i](evt);
}
}
this.add = function(item) {
_list.push(item);
emit(new PMChangeEvent(
DataView.ChangeType.add, [item], { index: _list.length - 1 }
));
};
this.removeAt = function(index) {
if (index < 0 || index >= _list.length) return;
var item = _list.splice(index, 1)[0];
emit(new PMChangeEvent(
DataView.ChangeType.remove, [item], { index: index }
));
};
this.changeAt = function(index, newItem) {
if (index < 0 || index >= _list.length) return;
_list[index] = newItem;
emit(new PMChangeEvent(
DataView.ChangeType.change, [newItem], { index: index }
));
};
this.clear = function() {
_list.length = 0;
emit(new PMChangeEvent(
DataView.ChangeType.clear
));
};
this.move = function(from, to) {
if (from === to ||
from < 0 || to < 0 ||
from >= _list.length || to >= _list.length) {
return;
}
var item = _list.splice(from, 1)[0];
_list.splice(to, 0, item);
emit(new PMChangeEvent(
DataView.ChangeType.move, [item], { from: from, to: to }
));
};
this.sort = function(compareFn) {
_list.sort(compareFn);
emit(new PMChangeEvent(
DataView.ChangeType.sort,
_list.slice(0), { compare: compareFn }
));
};
this.get = function() {
return _list.slice(0);
};
this.addList = function(list, keySelector) {
if (!list || !list.length) return;
var added = [];
var changed = [];
var useKey = keySelector !== void 0;
var getKey;
if (keySelector === null) {
getKey = function(item) {
return item && item.id;
};
} else if (typeof keySelector === "function") {
getKey = keySelector;
}
for (var i = 0; i < list.length; i++) {
var item = list[i];
if (!useKey) {
_list.push(item);
added.push({ item: item, index: _list.length - 1 });
continue;
}
var key = getKey(item);
if (key === void 0) {
_list.push(item);
added.push({ item: item, index: _list.length - 1, key: key });
continue;
}
var found = -1;
for (var j = 0; j < _list.length; j++) {
if (getKey(_list[j]) === key) {
found = j;
break;
}
}
if (found >= 0) {
_list[found] = item;
changed.push({ item: item, index: found, key: key });
} else {
_list.push(item);
added.push({ item: item, index: _list.length - 1, key: key });
}
}
// 统一发出一个事件
if (added.length > 0) {
emit(new PMChangeEvent(DataView.ChangeType.add, added));
}
if (changed.length > 0) {
emit(new PMChangeEvent(DataView.ChangeType.change, changed));
}
};
this.updateList = function(list, fnGetKey) {
if (!list) list = [];
var getKey;
if (fnGetKey === null) {
getKey = function(item) {
return item && item.id;
};
} else if (typeof fnGetKey === "function") {
getKey = fnGetKey;
} else {
// 不提供 key直接整体替换
_list = list.slice(0);
emit(new PMChangeEvent(
DataView.ChangeType.clear
));
emit(new PMChangeEvent(
DataView.ChangeType.add,
list.map(function(item, index) {
return { item: item, index: index };
})
));
return;
}
var oldList = _list;
var newList = list;
var oldKeyIndex = {};
var newKeyIndex = {};
var i;
// 建立旧列表 key → index
for (i = 0; i < oldList.length; i++) {
var ok = getKey(oldList[i]);
if (ok !== void 0) {
oldKeyIndex[ok] = i;
}
}
// 建立新列表 key → index
for (i = 0; i < newList.length; i++) {
var nk = getKey(newList[i]);
if (nk !== void 0) {
newKeyIndex[nk] = i;
}
}
var added = [];
var changed = [];
var removed = [];
// 1⃣ 找 remove
for (i = oldList.length - 1; i >= 0; i--) {
var oldItem = oldList[i];
var oldKey = getKey(oldItem);
if (oldKey === void 0 || newKeyIndex[oldKey] === void 0) {
removed.push({
item: oldItem,
index: i,
key: oldKey
});
}
}
// 2⃣ 找 add / change
for (i = 0; i < newList.length; i++) {
var newItem = newList[i];
var newKey = getKey(newItem);
if (newKey === void 0 || oldKeyIndex[newKey] === void 0) {
added.push({
item: newItem,
index: i,
key: newKey
});
} else {
var oldIndex = oldKeyIndex[newKey];
var oldItem2 = oldList[oldIndex];
if (oldItem2 !== newItem) {
changed.push({
item: newItem,
index: oldIndex,
key: newKey
});
}
}
}
// 3⃣ 执行 remove从后往前
if (removed.length > 0) {
for (i = 0; i < removed.length; i++) {
_list.splice(removed[i].index, 1);
}
emit(new PMChangeEvent(
DataView.ChangeType.remove,
removed
));
}
// 4⃣ 执行 add / change重建顺序
_list = newList.slice(0);
if (added.length > 0) {
emit(new PMChangeEvent(
DataView.ChangeType.add,
added
));
}
if (changed.length > 0) {
emit(new PMChangeEvent(
DataView.ChangeType.change,
changed
));
}
};
}
function PMDataListView(container, templateFn) {
this.container = container;
this.templateFn = templateFn;
this.listViewControl = this;
}
PMDataListView.prototype.bind = function(ds) {
var self = this;
var items = ds.get();
self.container.innerHTML = "";
// 动画队列,保证异步操作不会乱序
var queue = Promise.resolve();
function renderItem(data, index) {
var el = self.templateFn(data, index);
el.addEventListener("click", function() {
self._toggleSelect(el);
});
return el;
}
// 初始化渲染
for (var i = 0; i < items.length; i++) {
self.container.appendChild(renderItem(items[i], i));
}
ds.subscribe(function(evt) {
// 把每次事件放进队列,保证顺序执行
queue = queue.then(function() {
switch (evt.type) {
case DataView.ChangeType.add:
{
// evt.datas = [{item, index}, ...]
var datas = evt.datas;
// 先批量 append 到 DOM顺序必须保持
var nodes = [];
for (var i = 0; i < datas.length; i++) {
var n = renderItem(datas[i].item, datas[i].index);
nodes.push(n);
self.container.appendChild(n);
}
// 如果数量>=20动画并行否则串行
if (datas.length >= 20) {
var promises = [];
for (var j = 0; j < nodes.length; j++) {
promises.push(showItemAmine(nodes[j]));
}
return Promise.all(promises);
} else {
// 串行
var p = Promise.resolve();
for (var k = 0; k < nodes.length; k++) {
(function(node) {
p = p.then(function() {
return showItemAmine(node);
});
})(nodes[k]);
}
return p;
}
}
case DataView.ChangeType.remove:
{
var node = self.container.children[evt.detail.index];
if (!node) return;
// 隐藏动画完成后再移除
return hideItemAmine(node).then(function() {
self.container.removeChild(node);
});
}
case DataView.ChangeType.change:
{
var oldNode = self.container.children[evt.detail.index];
if (!oldNode) return;
// 先淡出旧节点
return hideItemAmine(oldNode).then(function() {
// 替换节点
var newNode = renderItem(evt.datas[0], evt.detail.index);
self.container.replaceChild(newNode, oldNode);
// 再淡入新节点
return showItemAmine(newNode);
});
}
case DataView.ChangeType.clear:
self.container.innerHTML = "";
return Promise.resolve();
case DataView.ChangeType.move:
{
var node = self.container.children[evt.detail.from];
var ref = self.container.children[evt.detail.to] || null;
if (node) self.container.insertBefore(node, ref);
return Promise.resolve();
}
case DataView.ChangeType.sort:
{
self.container.innerHTML = "";
for (var i = 0; i < evt.datas.length; i++) {
self.container.appendChild(renderItem(evt.datas[i], i));
}
return Promise.resolve();
}
}
});
});
};
PMDataListView.prototype._toggleSelect = function(ele) {
// 如果选择模式为 none则不处理
if (this.selectionMode === "none") return;
var isSelected = ele.classList.contains("selected");
if (this.selectionMode === "single") {
// 单选:先取消所有选中
this._clearSelected();
if (!isSelected) {
ele.classList.add("selected");
}
} else if (this.selectionMode === "multiple") {
// 多选:点一次切换状态
if (isSelected) {
ele.classList.remove("selected");
} else {
ele.classList.add("selected");
}
}
};
PMDataListView.prototype._clearSelected = function() {
var selected = this.container.querySelectorAll(".selected");
for (var i = 0; i < selected.length; i++) {
selected[i].classList.remove("selected");
}
};
Object.defineProperty(PMDataListView.prototype, "selectionMode", {
get: function() {
return this._selectionMode || "none";
},
set: function(value) {
var mode = String(value).toLowerCase();
if (mode !== "none" && mode !== "single" && mode !== "multiple") {
mode = "none";
}
this._selectionMode = mode;
// 切换模式时,清空选中状态(可选)
if (mode === "none") {
this._clearSelected();
}
if (mode === "single") {
// 单选模式:如果多选了多个,保留第一个
var selected = this.container.querySelectorAll(".selected");
if (selected.length > 1) {
for (var i = 1; i < selected.length; i++) {
selected[i].classList.remove("selected");
}
}
}
}
});
Object.defineProperty(PMDataListView.prototype, "selectedItems", {
get: function() {
return Array.prototype.slice.call(this.container.querySelectorAll(".selected"));
}
});
global.DataView.ChangeEvent = PMChangeEvent;
global.DataView.DataSource = PMDataSource;
global.DataView.ListView = PMDataListView;
})(this);

View File

@@ -0,0 +1,50 @@
(function(global) {
"use strict";
var pkg_ns = external.Package;
function archsToStr(archs) {
var arr = [];
for (var i = 0; i < archs.length; i++) {
switch (archs[i]) {
case 0:
arr.push("x86");
break;
case 5:
arr.push("ARM");
break;
case 9:
arr.push("x64");
break;
case 11:
arr.push("Neutral");
break;
case 12:
arr.push("ARM64");
break;
case 65535:
arr.push("Unknown");
break;
}
}
return arr.join(", ");
}
function setAppInfoPageContent(info) {
var page = document.getElementById("page-appinfo");
page.querySelector(".display-name").textContent = info.Properties.DisplayName;
page.querySelector(".publisher-display-name").textContent = info.Properties.Publisher;
page.querySelector(".version").textContent = info.Identity.Version.Expression;
page.querySelector(".description").textContent = info.Properties.Description;
page.querySelector(".identity .name").textContent = info.Identity.Name;
page.querySelector(".identity .publisher").textContent = info.Identity.Publisher;
page.querySelector(".identity .publisher-id").textContent = info.Identity.PublisherId;
page.querySelector(".identity .family-name").textContent = info.Identity.FamilyName;
page.querySelector(".identity .full-name").textContent = info.Identity.FullName;
page.querySelector(".identity .architecture").textContent = archsToStr(info.Identity.ProcessArchitecture);
var il = info.InstallLocation;
var pkg = pkg_ns.fromInstallLocation(il);
var json = pkg.jsonText;
console.log(JSON.parse(json));
}
global.setAppInfoPageContent = setAppInfoPageContent;
})(this);

524
shared/html/js/mgrinit.js Normal file
View File

@@ -0,0 +1,524 @@
(function(global) {
function _createImage(src, onload, onerror) {
var img = new Image();
img.onload = function() {
onload(img);
};
img.onerror = function() {
onerror && onerror();
};
img.src = src;
}
function getSolidOpaqueBackgroundColor(source, callback) {
function processImage(img) {
if (!img || !img.complete) {
callback(null);
return;
}
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = img.naturalWidth || img.width;
canvas.height = img.naturalHeight || img.height;
ctx.drawImage(img, 0, 0);
try {
var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
} catch (e) {
// 跨域导致的安全异常
callback(null);
return;
}
var data = imageData.data;
var w = canvas.width;
var h = canvas.height;
var colors = {};
var total = 0;
function pushColor(r, g, b, a) {
if (a !== 255) return;
var key = r + "," + g + "," + b;
colors[key] = (colors[key] || 0) + 1;
total++;
}
// top + bottom
for (var x = 0; x < w; x++) {
var topIndex = (0 * w + x) * 4;
var botIndex = ((h - 1) * w + x) * 4;
pushColor(data[topIndex], data[topIndex + 1], data[topIndex + 2], data[topIndex + 3]);
pushColor(data[botIndex], data[botIndex + 1], data[botIndex + 2], data[botIndex + 3]);
}
// left + right
for (var y = 1; y < h - 1; y++) {
var leftIndex = (y * w + 0) * 4;
var rightIndex = (y * w + (w - 1)) * 4;
pushColor(data[leftIndex], data[leftIndex + 1], data[leftIndex + 2], data[leftIndex + 3]);
pushColor(data[rightIndex], data[rightIndex + 1], data[rightIndex + 2], data[rightIndex + 3]);
}
if (total === 0) {
callback(null);
return;
}
var bestKey = null;
var bestCount = 0;
for (var key in colors) {
if (colors.hasOwnProperty(key)) {
if (colors[key] > bestCount) {
bestCount = colors[key];
bestKey = key;
}
}
}
// 95% 纯色阈值
if (bestCount / total < 0.95) {
callback(null);
return;
}
callback(bestKey);
}
// 如果传入的是 img 元素
if (source && source.tagName && source.tagName.toLowerCase() === "img") {
processImage(source);
return;
}
// 如果传入的是 data url 或普通 url
if (typeof source === "string") {
_createImage(source, processImage, function() {
callback(null);
});
return;
}
callback(null);
}
function getHamonyColor(source, callback) {
function _createImage(src, onload, onerror) {
var img = new Image();
img.onload = function() { onload(img); };
img.onerror = function() { onerror && onerror(); };
img.src = src;
}
function _toKey(r, g, b) {
return r + "," + g + "," + b;
}
function _rgbToHsl(r, g, b) {
r /= 255;
g /= 255;
b /= 255;
var max = Math.max(r, g, b);
var min = Math.min(r, g, b);
var h, s, l = (max + min) / 2;
if (max === min) {
h = s = 0;
} else {
var d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r:
h = (g - b) / d + (g < b ? 6 : 0);
break;
case g:
h = (b - r) / d + 2;
break;
case b:
h = (r - g) / d + 4;
break;
}
h /= 6;
}
return { h: h, s: s, l: l };
}
function _hslToRgb(h, s, l) {
var r, g, b;
function hue2rgb(p, q, t) {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1 / 6) return p + (q - p) * 6 * t;
if (t < 1 / 2) return q;
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
return p;
}
if (s === 0) {
r = g = b = l;
} else {
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
var p = 2 * l - q;
r = hue2rgb(p, q, h + 1 / 3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1 / 3);
}
return {
r: Math.round(r * 255),
g: Math.round(g * 255),
b: Math.round(b * 255)
};
}
function _lum(r, g, b) {
function f(x) {
x = x / 255;
return x <= 0.03928 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4);
}
return 0.2126 * f(r) + 0.7152 * f(g) + 0.0722 * f(b);
}
function _contrast(a, b) {
var L1 = _lum(a.r, a.g, a.b);
var L2 = _lum(b.r, b.g, b.b);
var lighter = Math.max(L1, L2);
var darker = Math.min(L1, L2);
return (lighter + 0.05) / (darker + 0.05);
}
function _tryPureBackground(data, w, h) {
var edgeColors = {};
var edgeTotal = 0;
function push(r, g, b, a) {
if (a !== 255) return;
var k = _toKey(r, g, b);
edgeColors[k] = (edgeColors[k] || 0) + 1;
edgeTotal++;
}
for (var x = 0; x < w; x++) {
var top = (0 * w + x) * 4;
var bot = ((h - 1) * w + x) * 4;
push(data[top], data[top + 1], data[top + 2], data[top + 3]);
push(data[bot], data[bot + 1], data[bot + 2], data[bot + 3]);
}
for (var y = 1; y < h - 1; y++) {
var left = (y * w + 0) * 4;
var right = (y * w + (w - 1)) * 4;
push(data[left], data[left + 1], data[left + 2], data[left + 3]);
push(data[right], data[right + 1], data[right + 2], data[right + 3]);
}
if (edgeTotal === 0) return null;
var best = null,
bestCount = 0;
for (var k in edgeColors) {
if (edgeColors.hasOwnProperty(k) && edgeColors[k] > bestCount) {
bestCount = edgeColors[k];
best = k;
}
}
if (best && bestCount / edgeTotal >= 0.95) return best;
return null;
}
function _process(img) {
if (!img || !img.complete) { callback(null); return; }
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = img.naturalWidth || img.width;
canvas.height = img.naturalHeight || img.height;
ctx.drawImage(img, 0, 0);
var imageData;
try {
imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
} catch (e) {
callback(null);
return;
}
var data = imageData.data;
var w = canvas.width,
h = canvas.height;
// 1) 尝试纯色背景
var pure = _tryPureBackground(data, w, h);
if (pure) { callback(pure); return; }
// 2) 统计不透明像素(抽样)
var sumR = 0,
sumG = 0,
sumB = 0,
count = 0;
var samples = 0;
var step = 4; // 4x抽样减少性能消耗
for (var y = 0; y < h; y += step) {
for (var x = 0; x < w; x += step) {
var i = (y * w + x) * 4;
var a = data[i + 3];
if (a === 255) {
sumR += data[i];
sumG += data[i + 1];
sumB += data[i + 2];
count++;
}
samples++;
}
}
if (count === 0) { callback(null); return; }
var avgR = sumR / count,
avgG = sumG / count,
avgB = sumB / count;
// 3) 生成候选色(借鉴流行配色)
var base = _rgbToHsl(avgR, avgG, avgB);
function clamp(v, min, max) { return Math.max(min, Math.min(max, v)); }
var candidates = [];
// 中性色(低饱和)
candidates.push(_hslToRgb(base.h, 0.05, 0.5));
candidates.push(_hslToRgb(base.h, 0.1, 0.6));
candidates.push(_hslToRgb(base.h, 0.1, 0.4));
// 平均色去饱和
candidates.push(_hslToRgb(base.h, clamp(base.s * 0.4, 0.05, 0.2), clamp(base.l, 0.2, 0.8)));
// 互补色(活泼)
candidates.push(_hslToRgb((base.h + 0.5) % 1, clamp(base.s * 0.6, 0.1, 0.8), clamp(base.l, 0.35, 0.7)));
// 类似色
candidates.push(_hslToRgb((base.h + 0.083) % 1, clamp(base.s * 0.5, 0.1, 0.8), clamp(base.l, 0.35, 0.7)));
candidates.push(_hslToRgb((base.h - 0.083 + 1) % 1, clamp(base.s * 0.5, 0.1, 0.8), clamp(base.l, 0.35, 0.7)));
// 三分色
candidates.push(_hslToRgb((base.h + 0.333) % 1, clamp(base.s * 0.6, 0.1, 0.8), clamp(base.l, 0.35, 0.7)));
candidates.push(_hslToRgb((base.h - 0.333 + 1) % 1, clamp(base.s * 0.6, 0.1, 0.8), clamp(base.l, 0.35, 0.7)));
// 4) 计算最小对比度(与所有不透明像素)
function minContrastWithImage(bg) {
var bgObj = { r: bg.r, g: bg.g, b: bg.b };
var minC = Infinity;
for (var y = 0; y < h; y += step) {
for (var x = 0; x < w; x += step) {
var i = (y * w + x) * 4;
if (data[i + 3] !== 255) continue;
var px = { r: data[i], g: data[i + 1], b: data[i + 2] };
var c = _contrast(bgObj, px);
if (c < minC) minC = c;
}
}
return minC;
}
var best = null;
for (var i = 0; i < candidates.length; i++) {
var c = candidates[i];
var minC = minContrastWithImage(c);
if (minC >= 4.5) {
best = c;
break;
}
}
if (best) {
callback(_toKey(best.r, best.g, best.b));
} else {
callback(null);
}
}
if (source && source.tagName && source.tagName.toLowerCase() === "img") {
_process(source);
} else if (typeof source === "string") {
_createImage(source, _process, function() { callback(null); });
} else {
callback(null);
}
}
function getSuitableBackgroundColor(source, callback) {
getSolidOpaqueBackgroundColor(source, function(color) {
if (color) {
callback(color);
} else {
getHamonyColor(source, callback);
}
});
}
function createLocalizedCompare(locale) {
return function(a, b) {
a = a || "";
b = b || "";
return a.localeCompare(b, locale, {
numeric: true, // 2 < 10
sensitivity: "base" // 不区分大小写 / 重音
});
};
}
var pagemgr = new PageManager();
OnLoad.add(function() {
var listContainer = document.getElementById("applist");
var appItemTemplate = document.getElementById("appitem-template");
var mgr = Package.manager;
var nstr = Bridge.NString;
var datasrc = new DataView.DataSource();
var themeColor = Bridge.UI.themeColor;
var loadingDisplay = document.getElementById("applist-loading");
var loadingStatus = loadingDisplay.querySelector(".title");
var listView = new DataView.ListView(listContainer, function(item) {
var appItem = appItemTemplate.cloneNode(true);
appItem.id = "";
appItem.style.display = "";
var logoimg = appItem.querySelector("img");
logoimg.src = item.Properties.LogoBase64 || logoimg.src;
logoimg.parentElement.style.backgroundColor = themeColor;
var appName = appItem.querySelector(".displayName");
appName.textContent = item.Properties.DisplayName || item.Identity.Name;
var appPub = appItem.querySelector(".publisher");
appPub.textContent = item.Properties.Publisher;
appItem.data = item;
appItem.setAttribute("data-install-location", item.InstallLocation);
appItem.setAttribute("data-development-mode", item.DevelopmentMode);
appItem.setAttribute("data-is-bundle", item.IsBundle);
appItem.setAttribute("data-is-framework", item.Properties.Framework);
appItem.setAttribute("data-family-name", item.Identity.FamilyName);
appItem.setAttribute("data-full-name", item.Identity.FullName);
appItem.setAttribute("data-version", item.Identity.Version.Expression);
appItem.setAttribute("data-users", item.Users);
appItem.setAttribute("data-publisher-id", item.Identity.PublisherId);
setTimeout(function(a, b) {
getSolidOpaqueBackgroundColor(a, function(color) {
try {
var pipes = color.split(",");
var colorobj = new Color(parseInt(pipes[0]), parseInt(pipes[1]), parseInt(pipes[2]));
if (colorobj.hex == "#ffffff" || colorobj.hex == "#000000") throw "too white or black";
var rgbstr = colorobj.RGB.toString();
b.style.backgroundColor = rgbstr;
} catch (e) {}
});
}, 0, item.Properties.LogoBase64, logoimg.parentElement);
Windows.UI.Event.Util.addEvent(appItem.querySelector("div[role=advance] a"), "click", function(e) {
e.stopPropagation();
try {
pagemgr.go("appinfo", this.parentNode.parentNode.parentNode.data);
} catch (ex) {}
});
return appItem;
});
listView.selectionMode = "single";
listView.bind(datasrc);
var timer = null;
function refreshAppList() {
function update(datas) {
var newDatas = [];
for (var i = 0; i < datas.length; i++) {
var data = datas[i];
if (data.Properties.Framework) continue; // 过滤依赖项
var isfind = false; // 过滤系统应用
for (var j = 0; data && data.Users && j < data.Users.length; j++) {
if (Bridge.NString.equals(data.Users[j], "NT AUTHORITY\\SYSTEM")) {
isfind = true;
break;
}
}
if (isfind) continue;
newDatas.push(data);
}
datasrc.updateList(newDatas, function(item) {
return item.Identity.FullName || "";
});
var compare = function(a, b) { return a - b; };
try {
compare = createLocalizedCompare(external.System.Locale.currentLocale);
} catch (e) {
try {
compare = createLocalizedCompare(navigator.language);
} catch (e) {
compare = function(a, b) {
if (a < b) return -1;
if (a > b) return 1;
return 0;
};
}
}
datasrc.sort(function(a, b) {
return compare(a.Properties.DisplayName, b.Properties.DisplayName);
});
}
if (timer) clearTimeout(timer);
timer = null;
loadingDisplay.style.display = "";
loadingDisplay.classList.remove("noloading");
function waitAndHide() {
if (timer) clearTimeout(timer);
timer = null;
timer = setTimeout(function() {
loadingDisplay.style.display = "none";
}, 10000);
}
loadingStatus.textContent = "正在加载数据...";
return mgr.get().then(function(result) {
loadingDisplay.classList.add("noloading");
loadingStatus.textContent = "已经加载了所有数据";
update(result.list);
waitAndHide();
}, function(error) {
loadingDisplay.classList.add("noloading");
loadingStatus.textContent = "更新时出错: " + (error.result ? (error.result.message || error.result.ErrorCode || "获取失败") : (error.message || error.error || error));
try { update(error.list); } catch (e) {}
waitAndHide();
})
}
var appbar = document.getElementById("appBar");
var appbarControl = new AppBar.AppBar(appbar);
var refreshButton = new AppBar.Command();
refreshButton.icon = "&#57623;";
refreshButton.label = "刷新";
global.refreshAppList2 = function refreshAppList2() {
appbarControl.hide();
refreshButton.disabled = true;
refreshAppList().done(function() {
refreshButton.disabled = false;
}, function(error) {
refreshButton.disabled = false;
});
}
refreshButton.addEventListener("click", refreshAppList2);
appbarControl.add(refreshButton);
refreshAppList2();
pagemgr.register("manager", document.getElementById("tag-manager"), document.getElementById("page-manager"));
pagemgr.register("appinfo", document.getElementById("tag-appinfo"), document.getElementById("page-appinfo"), setAppInfoPageContent);
var appinfoBackPage = document.getElementById("page-appinfo").querySelector(".win-backbutton");
Windows.UI.Event.Util.addEvent(appinfoBackPage, "click", function(e) {
pagemgr.back();
});
pagemgr.addEventListener("load", function(e) {
appbarControl.enabled = e == "manager";
refreshButton.style.display = e == "manager" ? "" : "none";
});
pagemgr.go("manager");
});
})(this);

359
shared/html/js/pagemgr.js Normal file
View File

@@ -0,0 +1,359 @@
(function(global) {
"use strict";
var eu = Windows.UI.Event.Util;
var anime = Windows.UI.Animation;
function PagePair(guideNode, pageNode, respHandler) {
var _guide = guideNode;
var _page = pageNode;
var _handler = respHandler || null;
Object.defineProperty(this, "guide", {
get: function() { return _guide; },
set: function(value) { _guide = value; }
});
Object.defineProperty(this, "page", {
get: function() { return _page; },
set: function(value) { _page = value; }
});
Object.defineProperty(this, "handler", {
get: function() { return _handler; },
set: function(value) { _handler = value; }
});
}
function PageManager() {
var dict = {};
var stack = [];
var current = -1;
var record = {}; // 记录哪些界面已经第一次加载过
var paramStack = [];
// scrollStack 与 stack 对齐scrollStack[i] 对应 stack[i]
var scrollStack = [];
var nowScroll = 0;
var events = {
firstload: [],
beforeload: [],
load: [],
afterload: [],
willunload: [],
unload: []
};
function addHandler(type, fn) {
if (typeof fn !== "function") return;
events[type].push(fn);
}
function removeHandler(type, fn) {
var list = events[type];
for (var i = list.length - 1; i >= 0; i--) {
if (list[i] === fn) {
list.splice(i, 1);
}
}
}
function emit(type, arg) {
var list = events[type];
for (var i = 0; i < list.length; i++) {
try {
list[i](arg);
} catch (e) {}
}
}
function emitCancelable(type, arg) {
var list = events[type];
for (var i = 0; i < list.length; i++) {
try {
var r = list[i](arg);
if (r === false) return false;
} catch (e) {}
}
return true;
}
/**
* 添加载入事件
* @param {string} type 支持:"firstload"
"beforeload"
"load"
"afterload"
"willunload"
"unload"
* @param {function} fn
*/
this.addEventListener = function(type, fn) {
addHandler(type, fn);
};
/**
* 移除载入事件
* @param {string} type 支持:"firstload"
"beforeload"
"load"
"afterload"
"willunload"
"unload"
* @param {function} fn
*/
this.removeEventListener = function(type, fn) {
removeHandler(type, fn);
};
function guideClickHandler(e) {
var tag = this.__pageTag;
if (!tag) return;
if (this.classList.contains("selected")) return;
self.go(tag);
return;
var keys = Object.keys(dict);
var promises = [];
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
var pair = dict[key];
if (pair.guide.classList.contains("selected")) {
promises.push(anime.runAsync(
pair.page, [
anime.Keyframes.Opacity.hidden,
anime.Keyframes.Scale.down
]
).then(function(el) {
el.style.display = "none";
}));
}
}
this.classList.add("selected");
var after = Promise.join(promises);
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
var pair = dict[key];
if (pair.guide.classList.contains("selected")) {
pair.page.style.display = "";
after.then(function() {
anime.runAsync(
pair.page, [
anime.Keyframes.Opacity.visible,
anime.Keyframes.Flyout.toLeft
]
);
});
}
}
}
var self = this;
function _activate(tag, args, fromHistory) {
var pair = dict[tag];
if (!pair) throw "Page not found: " + tag;
if (!emitCancelable("beforeload", tag)) {
return;
}
var keys = Object.keys(dict);
var promises = [];
var oldTags = [];
for (var i = 0; i < keys.length; i++) {
var k = keys[i];
var p = dict[k];
if (p.guide.classList.contains("selected") && k !== tag) {
if (!emitCancelable("willunload", k)) {
return;
}
oldTags.push(k);
promises.push(
anime.runAsync(p.page, [
anime.Keyframes.Opacity.hidden
]).then((function(page, key) {
return function() {
page.style.display = "none";
page.style.opacity = 0;
emit("unload", key);
};
})(p.page, k))
);
p.guide.classList.remove("selected");
}
}
pair.guide.classList.add("selected");
pair.page.style.display = "";
emit("load", tag);
var after = Promise.join(promises);
after.then(function() {
if (!record[tag]) {
record[tag] = true;
emit("firstload", tag);
}
pair.page.style.opacity = 1;
if (pair.handler) {
// fix: use pair.handler
pair.handler(args);
}
try {
setTimeout(function(tnode) {
try {
tnode.scrollTop = nowScroll || 0;
} catch (ex) {}
}, 10, pair.page.parentNode);
} catch (ex) {}
return anime.runAsync(pair.page, [
anime.Keyframes.Opacity.visible,
anime.Keyframes.Flyout.toLeft
]).then(function() {
});
}).then(function() {
emit("afterload", tag);
});
}
this.register = function(tag, guideNode, pageNode, respHandler) {
dict[tag] = new PagePair(guideNode, pageNode, respHandler);
guideNode.__pageTag = tag;
try {
eu.removeEvent(guideNode, "click", guideClickHandler);
eu.addEvent(guideNode, "click", guideClickHandler);
} catch (e) {}
};
this.edit = function(tag, pagePair) {
try {
if (dict[tag] && dict[tag].guide) {
dict[tag].guide.__pageTag = null;
}
} catch (e) {}
dict[tag] = pagePair;
try {
pagePair.guide.__pageTag = tag;
eu.removeEvent(pagePair.guide, "click", guideClickHandler);
eu.addEvent(pagePair.guide, "click", guideClickHandler);
} catch (e) {}
};
this.get = function(tag) {
return dict[tag];
};
this.getGuide = function(tag) {
return dict[tag].guide;
};
this.getPage = function(tag) {
return dict[tag].page;
};
this.getHandler = function(tag) {
return dict[tag].handler;
};
this.setGuide = function(tag, guideNode) {
try {
if (dict[tag] && dict[tag].guide) {
eu.removeEvent(dict[tag].guide, "click", guideClickHandler);
dict[tag].guide.__pageTag = null;
}
} catch (e) {}
dict[tag].guide = guideNode;
try {
guideNode.__pageTag = tag;
eu.removeEvent(guideNode, "click", guideClickHandler);
eu.addEvent(guideNode, "click", guideClickHandler);
} catch (e) {}
};
this.setPage = function(tag, pageNode) {
dict[tag].page = pageNode;
};
this.setHandler = function(tag, handler) {
dict[tag].handler = handler;
};
this.remove = function(tag) {
try {
try {
if (dict[tag] && dict[tag].guide) {
eu.removeEvent(dict[tag].guide, "click", guideClickHandler);
}
} catch (e) {}
delete dict[tag];
} catch (e) {}
};
this.clear = function() {
try {
var keys = Object.keys(dict);
for (var i = 0; i < keys.length; i++) {
this.remove(keys[i]);
}
} catch (e) {}
};
this.jump = function(tag, args) {
_activate(tag, args, true);
};
this.go = function(tag, params) {
// limit history
if (stack.length > 300) {
stack.length = 0;
paramStack.length = 0;
scrollStack.length = 0;
current = -1;
}
// if we are in the middle, truncate forward history
if (current < stack.length - 1) {
stack.splice(current + 1);
paramStack.splice(current + 1);
scrollStack.splice(current + 1);
}
// save current page scrollTop
try {
if (current >= 0 && stack[current] && dict[stack[current]] && dict[stack[current]].page && dict[stack[current]].page.parentNode) {
scrollStack[current] = dict[stack[current]].page.parentNode.scrollTop;
}
} catch (e) {}
// push new entry
stack.push(tag);
paramStack.push(params);
// initialize scroll value for the new page (will be used if user goes back to it later)
scrollStack.push(0);
current++;
_activate(tag, params, false);
};
this.back = function() {
if (current <= 0) return false;
// save scroll of current page
try {
if (stack[current] && dict[stack[current]] && dict[stack[current]].page && dict[stack[current]].page.parentNode) {
scrollStack[current] = dict[stack[current]].page.parentNode.scrollTop;
}
} catch (e) {}
// move back
current--;
// restore scroll for new current
nowScroll = scrollStack[current] || 0;
_activate(stack[current], paramStack[current], true);
return true;
};
this.next = function() {
if (current >= stack.length - 1) return false;
// save scroll of current page
try {
if (stack[current] && dict[stack[current]] && dict[stack[current]].page && dict[stack[current]].page.parentNode) {
scrollStack[current] = dict[stack[current]].page.parentNode.scrollTop;
}
} catch (e) {}
// move forward
current++;
// restore scroll for new current
nowScroll = scrollStack[current] || 0;
_activate(stack[current], paramStack[current], true);
return true;
};
Object.defineProperty(this, "current", {
get: function() { return stack[current]; },
set: function(value) {
if (value < 0 || value >= stack.length) return;
current = value;
// restore scroll for assigned current
nowScroll = scrollStack[current] || 0;
_activate(stack[current], paramStack[current], true);
}
});
Object.defineProperty(this, "canback", {
get: function() { return current > 0; }
});
Object.defineProperty(this, "cannext", {
get: function() { return current < stack.length - 1; }
});
}
global.PageManager = PageManager;
})(this);

128
shared/html/js/pkginfo.js Normal file
View File

@@ -0,0 +1,128 @@
(function(global) {
"use strict";
var mgr = external.Package.manager;
function parseJsonCallback(swJson, callback) {
var ret = swJson;
try {
if (swJson) ret = JSON.parse(swJson);
} catch (e) {}
if (callback) callback(ret);
}
global.Package = {
reader: function(pkgPath) { external.Package.reader(pkgPath); },
manager: {
add: function(swPkgPath, uOptions) {
return new Promise(function(resolve, reject, progress) {
mgr.addPackage(swPkgPath, uOptions, function(result) {
parseJsonCallback(result, resolve);
}, function(result) {
parseJsonCallback(result, reject);
}, progress);
})
},
get: function() {
return new Promise(function(resolve, reject) {
mgr.getPackages(function(result) {
parseJsonCallback(result, resolve);
}, function(result) {
parseJsonCallback(result, reject);
});
});
},
remove: function(swPkgFullName) {
return new Promise(function(resolve, reject, progress) {
mgr.removePackage(swPkgFullName, function(result) {
parseJsonCallback(result, resolve);
}, function(result) {
parseJsonCallback(result, reject);
}, progress);
});
},
clearup: function(swPkgName, swUserSID) {
return new Promise(function(resolve, reject, progress) {
mgr.clearupPackage(swPkgName, swUserSID, function(result) {
parseJsonCallback(result, resolve);
}, function(result) {
parseJsonCallback(result, reject);
}, progress);
});
},
register: function(swPkgPath, uOptions) {
return new Promise(function(resolve, reject, progress) {
mgr.registerPackage(swPkgPath, uOptions, function(result) {
parseJsonCallback(result, resolve);
}, function(result) {
parseJsonCallback(result, reject);
}, progress);
});
},
registerByFullName: function(swPkgFullName, uOptions) {
return new Promise(function(resolve, reject, progress) {
mgr.registerPackageByFullName(swPkgFullName, uOptions, function(result) {
parseJsonCallback(result, resolve);
}, function(result) {
parseJsonCallback(result, reject);
}, progress);
});
},
setStatus: function(swPkgFullName, uStatus) {
mgr.setPackageStatus(swPkgFullName, uStatus);
},
stage: function(swPkgPath, uOptions) {
return new Promise(function(resolve, reject, progress) {
mgr.stagePackage(swPkgPath, uOptions, function(result) {
parseJsonCallback(result, resolve);
}, function(result) {
parseJsonCallback(result, reject);
}, progress);
});
},
stageUserData: function(swPkgFullName) {
return new Promise(function(resolve, reject, progress) {
mgr.stagePackageUserData(swPkgFullName, function(result) {
parseJsonCallback(result, resolve);
}, function(result) {
parseJsonCallback(result, reject);
}, progress);
});
},
update: function(swPkgPath, uOptions) {
return new Promise(function(resolve, reject, progress) {
mgr.updatePackage(swPkgPath, uOptions, function(result) {
parseJsonCallback(result, resolve);
}, function(result) {
parseJsonCallback(result, reject);
}, progress);
});
},
findByIdentity: function(swIdName, swIdPublisher) {
return new Promise(function(resolve, reject) {
mgr.findPackageByIdentity(swIdName, swIdPublisher, function(result) {
parseJsonCallback(result, resolve);
}, function(result) {
parseJsonCallback(result, reject);
});
});
},
findByFamilyName: function(swFamilyName) {
return new Promise(function(resolve, reject) {
mgr.findPackageByFamilyName(swFamilyName, function(result) {
parseJsonCallback(result, resolve);
}, function(result) {
parseJsonCallback(result, reject);
});
});
},
findByFullName: function(swPkgFullName) {
return new Promise(function(resolve, reject) {
mgr.findPackageByFullName(swPkgFullName, function(result) {
parseJsonCallback(result, resolve);
}, function(result) {
parseJsonCallback(result, reject);
});
});
},
},
};
})(this);

View File

@@ -381,3 +381,152 @@ function messageBoxAsync(swText, swTitle, uType, swColor, pfCallback) {
}
});
}
function MessageBoxButton(swDisplayName, nValueReturn) {
this.displayName = swDisplayName;
this.value = nValueReturn;
}
function messageBoxAdvance(swText, swCaption, aCommands, swColor, pfCallback) {
var _lpText = swText;
var _lpCaption = swCaption;
var msgbox = document.createElement("div");
msgbox.classList.add("notice-back");
msgbox.classList.add("win-ui-dark");
var uniqueId = "msgbox_" + new Date().getTime();
msgbox.id = uniqueId;
var msgbody = document.createElement("div");
msgbody.classList.add("notice-body");
if (!IsBlackLabel(swColor)) {
msgbody.style.backgroundColor = swColor;
}
msgbox.appendChild(msgbody);
var msgcontainter = document.createElement("div");
msgcontainter.style.height = "100%";
msgcontainter.style.width = "100%";
msgcontainter.style.maxHeight = "100%";
msgcontainter.style.minHeight = "0px";
msgcontainter.style.boxSizing = "border-box";
msgbody.appendChild(msgcontainter);
var msgcaption = document.createElement("div");
msgcontainter.appendChild(msgcaption);
msgcontainter.style.display = "flex";
msgcontainter.style.flexDirection = "column";
var msgcontent = document.createElement("div");
msgcontent.style.flex = "1 1 auto";
msgcontent.style.marginRight = "3px";
msgcontent.style.overflowX = "hidden";
msgcontent.style.overflowY = "auto";
msgcontent.style.minHeight = "0px";
msgcontainter.appendChild(msgcontent);
if (_lpCaption instanceof HTMLElement) {
msgcaption.appendChild(_lpCaption);
msgcaption.classList.add("notice-title");
} else {
if (!IsBlackLabel(_lpCaption)) {
var msgtitle = document.createElement("h2");
msgtitle.textContent = _lpCaption;
msgtitle.classList.add("notice-title");
msgcaption.appendChild(msgtitle);
} else {
var msgtitle = document.createElement("h2");
msgtitle.textContent = "";
msgtitle.classList.add("notice-title");
msgcaption.appendChild(msgtitle);
}
}
if (_lpText instanceof HTMLElement || _lpText instanceof HTMLDivElement || typeof _lpText !== "string") {
try {
_lpText.classList.add("notice-text");
msgcontent.appendChild(_lpText);
} catch (e) {
if (!IsBlackLabel(_lpText)) {
var msgtext = document.createElement("p");
msgtext.textContent = _lpText;
msgtext.classList.add("notice-text");
if (IsBlackLabel(_lpCaption)) {
msgtext.style.marginTop = "0";
}
msgcontent.appendChild(msgtext);
} else {
var msgtext = document.createElement("p");
msgtext.innerText = "";
msgtext.classList.add("notice-text");
if (IsBlackLabel(_lpCaption)) {
msgtext.style.marginTop = "0";
}
msgcontent.appendChild(msgtext);
}
}
} else {
if (!IsBlackLabel(_lpText)) {
var msgtext = document.createElement("p");
msgtext.textContent = _lpText;
msgtext.classList.add("notice-text");
if (IsBlackLabel(_lpCaption)) {
msgtext.style.marginTop = "0";
}
msgcontent.appendChild(msgtext);
} else {
var msgtext = document.createElement("p");
msgtext.innerText = "";
msgtext.classList.add("notice-text");
if (IsBlackLabel(_lpCaption)) {
msgtext.style.marginTop = "0";
}
msgcontent.appendChild(msgtext);
}
}
var msgctrls = document.createElement("div");
msgctrls.classList.add("notice-controls");
msgcontainter.appendChild(msgctrls);
if (aCommands.length <= 0) {
aCommands.push(new MessageBoxButton(GetLocaleStringFromResId(800) || "OK", MBRET.IDOK));
}
for (var i = 0; i < aCommands.length; i++) {
var cmd = aCommands[i];
var btn = document.createElement("button");
btn.textContent = cmd.displayName;
btn.setAttribute("data-msgbox-value", cmd.value);
Windows.UI.Event.Util.addEvent(btn, "click", function(event) {
var btns = this.parentNode.querySelectorAll("button");
var lastbtnstatus = [];
for (var j = 0; j < btns.length; j++) {
lastbtnstatus.push(btns[j].disabled);
btns[j].disabled = true;
}
try {
pfCallback(this.getAttribute("data-msgbox-value"));
} catch (e) {}
msgbox.style.opacity = 0;
setTimeout(function(nodes, laststatus) {
for (var k = 0; k < nodes.length; k++) {
nodes[k].disabled = laststatus[k];
}
document.body.removeChild(msgbox);
}, 500, btns, lastbtnstatus);
});
msgctrls.appendChild(btn);
}
document.body.appendChild(msgbox);
setTimeout(function() {
msgbox.style.opacity = 1;
}, 1);
return msgbox.id;
}
function messageBoxAdvanceAsync(swText, swCaption, aCommands, swColor) {
if (typeof Promise === "undefined") {
console.error("Promise is not supported in this environment.");
messageBoxAdvance(swText, swCaption, aCommands, swColor);
}
return new Promise(function(resolve, reject) {
try {
messageBoxAdvance(swText, swCaption, aCommands, swColor, function(valueReturn) {
if (resolve) resolve(valueReturn);
});
} catch (ex) {
if (reject) reject(ex);
}
});
}

View File

@@ -8,6 +8,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript" src="js/module.js"></script>
<script type="text/javascript" src="js/polyfill-ie.js"></script>
<link rel="stylesheet" href="libs/winjs/1.0/css/ui-light.css" id="winjs-style-1">
<link rel="stylesheet" href="libs/winjs/2.0/css/ui-light.css" id="winjs-style">
<script type="text/javascript" src="libs/winjs/1.0/js/base.js"></script>
<script type="text/javascript" src="libs/winjs/1.0/js/ui.js"></script>
@@ -21,38 +22,77 @@
<link rel="stylesheet" href="fonts/segx.css">
<link rel="stylesheet" href="manager/page.css">
<link rel="stylesheet" href="manager/appitem.css">
<link rel="stylesheet" href="manager/appbar.css">
<script type="text/javascript" src="js/event.js"></script>
<script type="text/javascript" src="js/tileback.js"></script>
<script type="text/javascript" src="js/load.js"></script>
<link rel="stylesheet" type="text/css" href="libs/msgbox/msgbox.css">
<script type="text/javascript" src="libs/msgbox/msgbox.js"></script>
<script type="text/javascript" src="js/init.js"></script>
<script type="text/javascript" src="js/pkginfo.js"></script>
<script type="text/javascript" src="js/datasrc.js"></script>
<script type="text/javascript" src="js/appbar.js"></script>
<script type="text/javascript" src="js/pagemgr.js"></script>
<script type="text/javascript" src="js/manager/pages.js"></script>
<script type="text/javascript" src="js/mgrinit.js"></script>
</head>
<body>
<div id="settingpage" class="pagecontainer full">
<div id="managerpage" class="pagecontainer full">
<div class="page full guide fold">
<main class="main padding">
<div id="page-manager">
<div id="page-manager" style="display: none;" class="ispage">
<h2>应用</h2>
<p>在这里,可以对安装的 Windows 商店应用进行管理。</p>
<h3>安装的应用</h3>
<template id="appitem-template">
</template>
<div class="appitem selected">
<div role="img">
<img width="24" height="24" src="images/applogo.default.png" />
<br>
<div class="app-loading" id="applist-loading" style="display: none;">
<progress class="win-ring"></progress>
<span class="win-label title">正在加载应用...</span>
<br>
</div>
<div role="divide"></div>
<div class="appitem" id="appitem-template" style="display: none;">
<div role="img" style="pointer-events: none;">
<img width="" height="" src="images/applogo.default.png" />
</div>
<div role="divide" style="pointer-events: none;"></div>
<div role="excepticon">
<div role="title" class="win-type-x-small"><span>App Name</span></div>
<div role="control"><button>卸载</button></div>
<div role="title" class="win-type-x-small" style="pointer-events: none;">
<span class="displayName">App Name</span><br>
<span class="publisher">Publisher</span>
</div>
<div role="advance">
<a>高级选项</a>
</div>
<div role="control">
<button name="uninstall">卸载</button>
</div>
</div>
<ul>
<li></li>
</ul>
</div>
<div id="applist" class="appitem-list" style="width: 100%; height: auto;">
</div>
<div class="bottom-compensate"></div>
</div>
<div id="page-appinfo" class="ispage app-detailpage">
<header>
<button class="win-backbutton"></button>
<h2 class="display-name">App DisplayName</h2>
</header>
<span class="publisher-display-name">App PublisherDisplayName</span><br>
<span class="version">App Version</span><br>
<span class="description">App Description</span>
<p><strong>应用身份</strong></p>
<div class="identity win-type-body" style="width: 100%; max-width: 100%; box-sizing: border-box; -ms-user-select: element;">
<span style="font-weight: bold;">名称</span><span>: </span><span class="name"></span><br>
<span style="font-weight: bold;">发布者</span><span>: </span><span class="publisher"></span><br>
<span style="font-weight: bold;">发布者 ID</span><span>: </span><span class="publisher-id"></span><br>
<span style="font-weight: bold;">系列名</span><span>: </span><span class="family-name"></span><br>
<span style="font-weight: bold;">全名</span><span>: </span><span class="full-name"></span><br>
<span style="font-weight: bold;">支持的处理器架构</span><span>: </span><span class="architecture"></span><br>
</div>
<p><strong>卸载</strong></p>
<p>卸载此应用及其设置。</p>
<button id="detail-uninstall-btn" data-app-fullname="">卸载</button>
</div>
</main>
<aside class="win-ui-dark">
@@ -75,10 +115,14 @@
</ul>
<hr>
<ul class="list">
<li>
<li id="tag-manager">
<div role="img">&#57587;</div>
<span class="win-type-base">管理</span>
</li>
<li id="tag-appinfo" class="subitem">
<div role="img">&#57650;</div>
<span class="win-type-base">应用信息</span>
</li>
<li>
<div role="img">&#57587;</div>
<span class="win-type-base">Manager</span>
@@ -88,6 +132,8 @@
</aside>
</div>
</div>
<div class="win-overlay win-commandlayout win-appbar win-bottom appbar win-ui-dark" id="appBar" role="menubar">
</div>
</body>
</html>

View File

@@ -0,0 +1,49 @@
.win-bottom {
position: absolute;
bottom: 0;
top: auto;
left: 0;
right: 0;
}
.appbar {
-ms-transform: translateY(100%);
transform: translateY(100%);
transition: all 0.5s cubic-bezier(0.1, 0.9, 0.2, 1);
}
.appbar.show {
-ms-transform: translateY(0);
transform: translateY(0);
}
.appbar.win-ui-dark .win-label {
color: white;
}
.appbar-touchhide {
background-color: transparent;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 88px;
}
.appbar button.win-command,
.win-appbar .win-commandlayout button.win-command {
box-sizing: border-box;
/* 含 padding/border 计算宽度 */
min-width: 100px;
/* 强制最小宽度 100px */
}
/* 同时覆盖在窄屏 media query 中的行为(确保在 @media (max-width:1023px) 之后或在文件末尾定义) */
@media (max-width: 1023px) {
.appbar button.win-command,
.win-appbar .win-commandlayout button.win-command {
min-width: 100px;
}
}

View File

@@ -2,7 +2,7 @@
padding: 10px;
box-sizing: border-box;
height: 60px;
width: 450px;
width: 460px;
max-width: 100%;
display: -ms-flexbox;
/* IE10 */
@@ -53,6 +53,14 @@
-ms-flex-line-pack: center;
/* IE10 -> align-content */
align-content: center;
overflow-x: hidden;
overflow-y: hidden;
transition: all 0.3s cubic-bezier(0.1, 0.9, 0.2, 1);
}
.appitem div[role=img] img {
width: 30px;
height: 30px;
}
.appitem div[role=divide] {
@@ -65,6 +73,23 @@
font-weight: normal;
flex: 1;
-ms-flex: 1;
width: 100%;
overflow-x: hidden;
overflow-y: hidden;
text-overflow: ellipsis;
}
.appitem div[role=excepticon] div[role=advance] {
display: none;
opacity: 0;
height: 0;
transition: all 0.3s cubic-bezier(0.1, 0.9, 0.2, 1);
}
.appitem.selected div[role=excepticon] div[role=advance] {
display: block;
opacity: 1;
height: auto;
}
.appitem div[role=excepticon] {
@@ -85,12 +110,12 @@
-ms-flex-pack: start;
/* IE10 -> justify-content */
justify-content: flex-start;
width: calc(100% - 40px - 10px);
}
.appitem div[role=excepticon] div[role=control] {
display: none;
/* IE10 */
display: flex;
-ms-flex-direction: row-reverse;
/* IE10 */
flex-direction: row-reverse;
@@ -106,13 +131,95 @@
-ms-flex-align: center;
/* IE10 -> align-items */
align-items: center;
transition: all 0.3s cubic-bezier(0.1, 0.9, 0.2, 1);
opacity: 0;
height: 0;
}
.appitem.selected {
height: 119px;
background-color: rgba(232, 232, 232, 1);
}
.appitem.selected div[role=excepticon] div[role=control] {
display: flex;
display: -ms-flexbox;
opacity: 1;
height: auto;
}
ul.appitem-list,
ul.appitem-list li {
margin: 0;
padding: 0;
list-style: none;
}
.appitem .displayName,
.appitem .publisher {
text-overflow: ellipsis;
overflow-x: hidden;
overflow-y: hidden;
white-space: nowrap;
max-width: 100%;
}
.appitem .publisher {
color: rgb(102, 102, 102);
}
.app-loading {
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-content: center;
justify-content: flex-start;
align-items: center;
width: 100%;
height: auto;
}
.app-loading.noloading progress {
display: none;
}
.app-loading .title {
margin-left: 10px;
}
.app-loading.noloading .title {
margin-left: 0;
}
.app-detailpage header {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-content: flex-start;
justify-content: flex-start;
overflow-x: hidden;
overflow-y: hidden;
text-overflow: ellipsis;
width: 100%;
height: 67px;
box-sizing: border-box;
max-width: 100%;
}
.app-detailpage header .win-backbutton {
width: 35px;
height: 35px;
font-size: 11.9pt;
line-height: 32px;
min-width: 35px;
min-height: 35px;
}
.app-detailpage header .display-name {
padding-left: 10px;
box-sizing: border-box;
width: calc(100% - 35px - 10px);
overflow-y: hidden;
overflow-x: hidden;
text-overflow: ellipsis;
}

View File

@@ -168,6 +168,7 @@ aside>nav ul li {
.page.fold>aside>nav ul li {
padding: 0;
cursor: pointer;
}
aside>nav ul li div[role=img] {
@@ -189,6 +190,33 @@ aside>nav ul li div[role=img] {
text-align: center;
}
.page>aside>nav ul li.selected {
background-color: #159d9d;
}
.page>aside>nav ul li.selected:hover {
background-color: rgb(23, 187, 187);
}
.page>aside>nav ul li.selected:active {
background-color: rgb(29, 224, 224);
}
.page>aside>nav ul li.subitem {
opacity: 0;
height: 0;
min-height: 0;
}
.page>aside>nav ul li.subitem.selected {
opacity: 1;
height: 50px;
}
.page.fold>aside>nav ul li * {
pointer-events: none;
}
.page.fold>aside>nav ul li div[role=img] {
min-width: 90px;
width: 90px;
@@ -213,7 +241,8 @@ aside>nav ul li div[role=img] {
.page>aside>nav ul li div[role=img] {
font-size: 15pt;
margin-right: 5px;
margin-right: 10px;
width: 1em;
}
.page>aside>nav ul li.title div[role=img] {
@@ -256,7 +285,7 @@ aside>nav ul li div[role=img] {
.page.fold>aside>nav ul li:hover div[role=img] {
min-width: 0;
width: auto;
width: 1em;
}
.page.fold>aside>nav ul li:hover span {
@@ -292,6 +321,10 @@ aside>nav ul li div[role=img] {
overflow-y: visible;
}
.main {
transition: all 0.3s cubic-bezier(0.1, 0.9, 0.2, 1);
}
.main.padding {
padding: 44px 60px;
}
@@ -307,12 +340,18 @@ aside>nav ul li div[role=img] {
top: 0px;
left: 0px;
background-color: white;
transition: all 0.3s cubic-bezier(0.1, 0.9, 0.2, 1);
}
.section.padding {
padding: 44px 60px;
}
.section.padding .bottom-compensate {
.bottom-compensate {
padding-bottom: 44px;
}
.ispage {
opacity: 1;
transition: all 0.4s cubic-bezier(0.1, 0.9, 0.2, 1);
}