mirror of
https://github.com/modernw/App-Installer-For-Windows-8.x-Reset.git
synced 2026-04-11 17:57:19 +10:00
Organized the project files.
And also fixed some bugs.
This commit is contained in:
@@ -5,11 +5,6 @@ VisualStudioVersion = 14.0.25420.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pkgread", "pkgread\pkgread.vcxproj", "{A7753282-AA16-43D9-8ACA-7065239DD702}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "priformatcli", "..\priformatcli\priformatcli\priformatcli.vcxproj", "{33D91B58-1981-4A3C-B4D1-86EE406CDE12}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D} = {EF4012D4-EF08-499C-B803-177739350B2D}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pkgmgr", "pkgmgr\pkgmgr.vcxproj", "{8EAC0230-4990-4E41-8E0F-D641D1561396}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "notice", "notice\notice.vcxproj", "{798ED492-EECE-457D-8FD8-129DA93CE126}"
|
||||
@@ -25,6 +20,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "appinstaller", "appinstalle
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702} = {A7753282-AA16-43D9-8ACA-7065239DD702}
|
||||
{798ED492-EECE-457D-8FD8-129DA93CE126} = {798ED492-EECE-457D-8FD8-129DA93CE126}
|
||||
{E04CCAB9-35DB-495C-A279-5B483C707CD0} = {E04CCAB9-35DB-495C-A279-5B483C707CD0}
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D} = {EF4012D4-EF08-499C-B803-177739350B2D}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "settings", "settings\settings.vcxproj", "{AD25497F-A15F-4DFF-AC7A-B8ABF5F411D6}"
|
||||
@@ -39,6 +35,13 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shortcut", "shortcut\shortc
|
||||
{798ED492-EECE-457D-8FD8-129DA93CE126} = {798ED492-EECE-457D-8FD8-129DA93CE126}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "desktopini", "desktopini\desktopini.vcxproj", "{7A05E943-6E0A-4F57-8BD7-BE90F44DCAD7}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "priformatcli", "priformatcli\priformatcli.vcxproj", "{33D91B58-1981-4A3C-B4D1-86EE406CDE12}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D} = {EF4012D4-EF08-499C-B803-177739350B2D}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -59,16 +62,6 @@ Global
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702}.Release|x64.Build.0 = Release|x64
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702}.Release|x86.ActiveCfg = Release|Win32
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702}.Release|x86.Build.0 = Release|Win32
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Debug|x64.Build.0 = Debug|x64
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Debug|x86.Build.0 = Debug|Win32
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Release|x64.ActiveCfg = Release|x64
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Release|x64.Build.0 = Release|x64
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Release|x86.ActiveCfg = Release|Win32
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Release|x86.Build.0 = Release|Win32
|
||||
{8EAC0230-4990-4E41-8E0F-D641D1561396}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{8EAC0230-4990-4E41-8E0F-D641D1561396}.Debug|x64.ActiveCfg = Debug|Win32
|
||||
{8EAC0230-4990-4E41-8E0F-D641D1561396}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
@@ -147,6 +140,26 @@ Global
|
||||
{18E0189B-F3F1-4CB2-A3AF-5606ADD5E279}.Release|x64.Build.0 = Release|x64
|
||||
{18E0189B-F3F1-4CB2-A3AF-5606ADD5E279}.Release|x86.ActiveCfg = Release|Win32
|
||||
{18E0189B-F3F1-4CB2-A3AF-5606ADD5E279}.Release|x86.Build.0 = Release|Win32
|
||||
{7A05E943-6E0A-4F57-8BD7-BE90F44DCAD7}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{7A05E943-6E0A-4F57-8BD7-BE90F44DCAD7}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{7A05E943-6E0A-4F57-8BD7-BE90F44DCAD7}.Debug|x64.Build.0 = Debug|x64
|
||||
{7A05E943-6E0A-4F57-8BD7-BE90F44DCAD7}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{7A05E943-6E0A-4F57-8BD7-BE90F44DCAD7}.Debug|x86.Build.0 = Debug|Win32
|
||||
{7A05E943-6E0A-4F57-8BD7-BE90F44DCAD7}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{7A05E943-6E0A-4F57-8BD7-BE90F44DCAD7}.Release|x64.ActiveCfg = Release|x64
|
||||
{7A05E943-6E0A-4F57-8BD7-BE90F44DCAD7}.Release|x64.Build.0 = Release|x64
|
||||
{7A05E943-6E0A-4F57-8BD7-BE90F44DCAD7}.Release|x86.ActiveCfg = Release|Win32
|
||||
{7A05E943-6E0A-4F57-8BD7-BE90F44DCAD7}.Release|x86.Build.0 = Release|Win32
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Debug|x64.Build.0 = Debug|x64
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Debug|x86.Build.0 = Debug|Win32
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Release|x64.ActiveCfg = Release|x64
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Release|x64.Build.0 = Release|x64
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Release|x86.ActiveCfg = Release|Win32
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
Binary file not shown.
@@ -1 +0,0 @@
|
||||
E:/Profiles/Bruce/Documents/Visual Studio 2015/Projects/PriFileFormat/PriFileFormat
|
||||
14
PriFileFormat/ByteSpan.cs
Normal file
14
PriFileFormat/ByteSpan.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System.Runtime.InteropServices;
|
||||
namespace PriFileFormat
|
||||
{
|
||||
public struct ByteSpan
|
||||
{
|
||||
public long Offset;
|
||||
public uint Length;
|
||||
internal ByteSpan (long offset, uint length)
|
||||
{
|
||||
Offset = offset;
|
||||
Length = length;
|
||||
}
|
||||
}
|
||||
}
|
||||
122
PriFileFormat/ComStreamWrapper.cs
Normal file
122
PriFileFormat/ComStreamWrapper.cs
Normal file
@@ -0,0 +1,122 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
|
||||
namespace PriFileFormat
|
||||
{
|
||||
public class ComStreamWrapper: Stream
|
||||
{
|
||||
private IStream comStream;
|
||||
public ComStreamWrapper (IStream stream)
|
||||
{
|
||||
if (stream == null)
|
||||
throw new ArgumentNullException ("stream");
|
||||
comStream = stream;
|
||||
}
|
||||
public override bool CanRead
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
public override bool CanSeek
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
public override bool CanWrite
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
public override long Length
|
||||
{
|
||||
get
|
||||
{
|
||||
System.Runtime.InteropServices.ComTypes.STATSTG stat;
|
||||
comStream.Stat (out stat, 1); // STATFLAG_NONAME = 1
|
||||
return stat.cbSize;
|
||||
}
|
||||
}
|
||||
public override long Position
|
||||
{
|
||||
get
|
||||
{
|
||||
IntPtr posPtr = Marshal.AllocHGlobal (sizeof (long));
|
||||
try
|
||||
{
|
||||
// SEEK_CUR = 1
|
||||
comStream.Seek (0, 1, posPtr);
|
||||
return Marshal.ReadInt64 (posPtr);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeHGlobal (posPtr);
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
// SEEK_SET = 0
|
||||
comStream.Seek (value, 0, IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
public override void Flush ()
|
||||
{
|
||||
comStream.Commit (0); // STGC_DEFAULT = 0
|
||||
}
|
||||
public override int Read (byte [] buffer, int offset, int count)
|
||||
{
|
||||
if (offset != 0)
|
||||
throw new NotSupportedException ("Offset != 0 not supported in this wrapper.");
|
||||
|
||||
IntPtr bytesRead = Marshal.AllocHGlobal (sizeof (int));
|
||||
try
|
||||
{
|
||||
comStream.Read (buffer, count, bytesRead);
|
||||
return Marshal.ReadInt32 (bytesRead);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeHGlobal (bytesRead);
|
||||
}
|
||||
}
|
||||
public override void Write (byte [] buffer, int offset, int count)
|
||||
{
|
||||
if (offset != 0)
|
||||
throw new NotSupportedException ("Offset != 0 not supported in this wrapper.");
|
||||
|
||||
IntPtr bytesWritten = Marshal.AllocHGlobal (sizeof (int));
|
||||
try
|
||||
{
|
||||
comStream.Write (buffer, count, bytesWritten);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeHGlobal (bytesWritten);
|
||||
}
|
||||
}
|
||||
public override long Seek (long offset, SeekOrigin origin)
|
||||
{
|
||||
int originInt = 0;
|
||||
switch (origin)
|
||||
{
|
||||
case SeekOrigin.Begin: originInt = 0; break; // STREAM_SEEK_SET
|
||||
case SeekOrigin.Current: originInt = 1; break; // STREAM_SEEK_CUR
|
||||
case SeekOrigin.End: originInt = 2; break; // STREAM_SEEK_END
|
||||
}
|
||||
|
||||
IntPtr posPtr = Marshal.AllocHGlobal (sizeof (long));
|
||||
try
|
||||
{
|
||||
comStream.Seek (offset, originInt, posPtr);
|
||||
return Marshal.ReadInt64 (posPtr);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeHGlobal (posPtr);
|
||||
}
|
||||
}
|
||||
public override void SetLength (long value)
|
||||
{
|
||||
comStream.SetSize (value);
|
||||
}
|
||||
~ComStreamWrapper () { comStream = null;}
|
||||
}
|
||||
}
|
||||
71
PriFileFormat/DataItemSection.cs
Normal file
71
PriFileFormat/DataItemSection.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
namespace PriFileFormat
|
||||
{
|
||||
public class DataItemSection: Section
|
||||
{
|
||||
private List<ByteSpan> _dataItems;
|
||||
public IReadOnlyList<ByteSpan> DataItems
|
||||
{
|
||||
get { return _dataItems; }
|
||||
}
|
||||
internal const string Identifier = "[mrm_dataitem] \0";
|
||||
internal DataItemSection (PriFile priFile) : base (Identifier, priFile)
|
||||
{
|
||||
}
|
||||
protected override bool ParseSectionContent (BinaryReader binaryReader)
|
||||
{
|
||||
long sectionPosition = (binaryReader.BaseStream as SubStream)?.SubStreamPosition ?? 0;
|
||||
binaryReader.ExpectUInt32 (0);
|
||||
ushort numStrings = binaryReader.ReadUInt16 ();
|
||||
ushort numBlobs = binaryReader.ReadUInt16 ();
|
||||
uint totalDataLength = binaryReader.ReadUInt32 ();
|
||||
List <ByteSpan> dataItems = new List<ByteSpan> (numStrings + numBlobs);
|
||||
long dataStartOffset = binaryReader.BaseStream.Position +
|
||||
numStrings * 2 * sizeof (ushort) + numBlobs * 2 * sizeof (uint);
|
||||
|
||||
for (int i = 0; i < numStrings; i++)
|
||||
{
|
||||
ushort stringOffset = binaryReader.ReadUInt16 ();
|
||||
ushort stringLength = binaryReader.ReadUInt16 ();
|
||||
dataItems.Add (new ByteSpan (sectionPosition + dataStartOffset + stringOffset, stringLength));
|
||||
}
|
||||
|
||||
for (int i = 0; i < numBlobs; i++)
|
||||
{
|
||||
uint blobOffset = binaryReader.ReadUInt32 ();
|
||||
uint blobLength = binaryReader.ReadUInt32 ();
|
||||
dataItems.Add (new ByteSpan (sectionPosition + dataStartOffset + blobOffset, blobLength));
|
||||
}
|
||||
|
||||
_dataItems = dataItems;
|
||||
|
||||
return true;
|
||||
}
|
||||
public void ClearData ()
|
||||
{
|
||||
_dataItems?.Clear ();
|
||||
_dataItems = null;
|
||||
}
|
||||
~DataItemSection () { ClearData (); }
|
||||
}
|
||||
|
||||
public struct DataItemRef
|
||||
{
|
||||
internal SectionRef<DataItemSection> dataItemSection;
|
||||
internal int itemIndex;
|
||||
|
||||
internal DataItemRef (SectionRef<DataItemSection> dataItemSection, int itemIndex)
|
||||
{
|
||||
this.dataItemSection = dataItemSection;
|
||||
this.itemIndex = itemIndex;
|
||||
}
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
return $"Data item {itemIndex} in section {dataItemSection.sectionIndex}";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
222
PriFileFormat/DecisionInfoSection.cs
Normal file
222
PriFileFormat/DecisionInfoSection.cs
Normal file
@@ -0,0 +1,222 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
namespace PriFileFormat
|
||||
{
|
||||
public class DecisionInfoSection: Section
|
||||
{
|
||||
public IReadOnlyList <Decision> Decisions { get; private set; }
|
||||
public IReadOnlyList <QualifierSet> QualifierSets { get; private set; }
|
||||
public IReadOnlyList <Qualifier> Qualifiers { get; private set; }
|
||||
internal const string Identifier = "[mrm_decn_info]\0";
|
||||
internal DecisionInfoSection (PriFile priFile) : base (Identifier, priFile) {}
|
||||
protected override bool ParseSectionContent (BinaryReader binaryReader)
|
||||
{
|
||||
ushort numDistinctQualifiers = binaryReader.ReadUInt16 ();
|
||||
ushort numQualifiers = binaryReader.ReadUInt16 ();
|
||||
ushort numQualifierSets = binaryReader.ReadUInt16 ();
|
||||
ushort numDecisions = binaryReader.ReadUInt16 ();
|
||||
ushort numIndexTableEntries = binaryReader.ReadUInt16 ();
|
||||
ushort totalDataLength = binaryReader.ReadUInt16 ();
|
||||
|
||||
List<DecisionInfo> decisionInfos = new List<DecisionInfo> (numDecisions);
|
||||
for (int i = 0; i < numDecisions; i++)
|
||||
{
|
||||
ushort firstQualifierSetIndexIndex = binaryReader.ReadUInt16 ();
|
||||
ushort numQualifierSetsInDecision = binaryReader.ReadUInt16 ();
|
||||
decisionInfos.Add (new DecisionInfo (firstQualifierSetIndexIndex, numQualifierSetsInDecision));
|
||||
}
|
||||
|
||||
List<QualifierSetInfo> qualifierSetInfos = new List<QualifierSetInfo> (numQualifierSets);
|
||||
for (int i = 0; i < numQualifierSets; i++)
|
||||
{
|
||||
ushort firstQualifierIndexIndex = binaryReader.ReadUInt16 ();
|
||||
ushort numQualifiersInSet = binaryReader.ReadUInt16 ();
|
||||
qualifierSetInfos.Add (new QualifierSetInfo (firstQualifierIndexIndex, numQualifiersInSet));
|
||||
}
|
||||
|
||||
List<QualifierInfo> qualifierInfos = new List<QualifierInfo> (numQualifiers);
|
||||
for (int i = 0; i < numQualifiers; i++)
|
||||
{
|
||||
ushort index = binaryReader.ReadUInt16 ();
|
||||
ushort priority = binaryReader.ReadUInt16 ();
|
||||
ushort fallbackScore = binaryReader.ReadUInt16 ();
|
||||
binaryReader.ExpectUInt16 (0);
|
||||
qualifierInfos.Add (new QualifierInfo (index, priority, fallbackScore));
|
||||
}
|
||||
|
||||
List<DistinctQualifierInfo> distinctQualifierInfos = new List<DistinctQualifierInfo> (numDistinctQualifiers);
|
||||
for (int i = 0; i < numDistinctQualifiers; i++)
|
||||
{
|
||||
binaryReader.ReadUInt16 ();
|
||||
QualifierType qualifierType = (QualifierType)binaryReader.ReadUInt16 ();
|
||||
binaryReader.ReadUInt16 ();
|
||||
binaryReader.ReadUInt16 ();
|
||||
uint operandValueOffset = binaryReader.ReadUInt32 ();
|
||||
distinctQualifierInfos.Add (new DistinctQualifierInfo (qualifierType, operandValueOffset));
|
||||
}
|
||||
|
||||
ushort [] indexTable = new ushort [numIndexTableEntries];
|
||||
|
||||
for (int i = 0; i < numIndexTableEntries; i++)
|
||||
indexTable [i] = binaryReader.ReadUInt16 ();
|
||||
|
||||
long dataStartOffset = binaryReader.BaseStream.Position;
|
||||
|
||||
List<Qualifier> qualifiers = new List<Qualifier> (numQualifiers);
|
||||
|
||||
for (int i = 0; i < numQualifiers; i++)
|
||||
{
|
||||
DistinctQualifierInfo distinctQualifierInfo = distinctQualifierInfos [qualifierInfos [i].Index];
|
||||
|
||||
binaryReader.BaseStream.Seek (dataStartOffset + distinctQualifierInfo.OperandValueOffset * 2, SeekOrigin.Begin);
|
||||
|
||||
string value = binaryReader.ReadNullTerminatedString (Encoding.Unicode);
|
||||
|
||||
qualifiers.Add (new Qualifier (
|
||||
(ushort)i,
|
||||
distinctQualifierInfo.QualifierType,
|
||||
qualifierInfos [i].Priority,
|
||||
qualifierInfos [i].FallbackScore / 1000f,
|
||||
value));
|
||||
}
|
||||
|
||||
Qualifiers = qualifiers;
|
||||
|
||||
List<QualifierSet> qualifierSets = new List<QualifierSet> (numQualifierSets);
|
||||
|
||||
for (int i = 0; i < numQualifierSets; i++)
|
||||
{
|
||||
List<Qualifier> qualifiersInSet = new List<Qualifier> (qualifierSetInfos [i].NumQualifiersInSet);
|
||||
|
||||
for (int j = 0; j < qualifierSetInfos [i].NumQualifiersInSet; j++)
|
||||
qualifiersInSet.Add (qualifiers [indexTable [qualifierSetInfos [i].FirstQualifierIndexIndex + j]]);
|
||||
|
||||
qualifierSets.Add (new QualifierSet ((ushort)i, qualifiersInSet));
|
||||
}
|
||||
|
||||
QualifierSets = qualifierSets;
|
||||
|
||||
List<Decision> decisions = new List<Decision> (numDecisions);
|
||||
|
||||
for (int i = 0; i < numDecisions; i++)
|
||||
{
|
||||
List<QualifierSet> qualifierSetsInDecision = new List<QualifierSet> (decisionInfos [i].NumQualifierSetsInDecision);
|
||||
|
||||
for (int j = 0; j < decisionInfos [i].NumQualifierSetsInDecision; j++)
|
||||
qualifierSetsInDecision.Add (qualifierSets [indexTable [decisionInfos [i].FirstQualifierSetIndexIndex + j]]);
|
||||
|
||||
decisions.Add (new Decision ((ushort)i, qualifierSetsInDecision));
|
||||
}
|
||||
|
||||
Decisions = decisions;
|
||||
|
||||
return true;
|
||||
}
|
||||
private struct DecisionInfo
|
||||
{
|
||||
public ushort FirstQualifierSetIndexIndex;
|
||||
public ushort NumQualifierSetsInDecision;
|
||||
public DecisionInfo (ushort firstQualifierSetIndexIndex, ushort numQualifierSetsInDecision)
|
||||
{
|
||||
FirstQualifierSetIndexIndex = firstQualifierSetIndexIndex;
|
||||
NumQualifierSetsInDecision = numQualifierSetsInDecision;
|
||||
}
|
||||
}
|
||||
private struct QualifierSetInfo
|
||||
{
|
||||
public ushort FirstQualifierIndexIndex;
|
||||
public ushort NumQualifiersInSet;
|
||||
public QualifierSetInfo (ushort firstQualifierIndexIndex, ushort numQualifiersInSet)
|
||||
{
|
||||
FirstQualifierIndexIndex = firstQualifierIndexIndex;
|
||||
NumQualifiersInSet = numQualifiersInSet;
|
||||
}
|
||||
}
|
||||
private struct QualifierInfo
|
||||
{
|
||||
public ushort Index;
|
||||
public ushort Priority;
|
||||
public ushort FallbackScore;
|
||||
public QualifierInfo (ushort index, ushort priority, ushort fallbackScore)
|
||||
{
|
||||
Index = index;
|
||||
Priority = priority;
|
||||
FallbackScore = fallbackScore;
|
||||
}
|
||||
}
|
||||
private struct DistinctQualifierInfo
|
||||
{
|
||||
public QualifierType QualifierType;
|
||||
public uint OperandValueOffset;
|
||||
public DistinctQualifierInfo (QualifierType qualifierType, uint operandValueOffset)
|
||||
{
|
||||
QualifierType = qualifierType;
|
||||
OperandValueOffset = operandValueOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
public enum QualifierType
|
||||
{
|
||||
Language,
|
||||
Contrast,
|
||||
Scale,
|
||||
HomeRegion,
|
||||
TargetSize,
|
||||
LayoutDirection,
|
||||
Theme,
|
||||
AlternateForm,
|
||||
DXFeatureLevel,
|
||||
Configuration,
|
||||
DeviceFamily,
|
||||
Custom
|
||||
}
|
||||
public class Qualifier
|
||||
{
|
||||
public ushort Index { get; }
|
||||
public QualifierType Type { get; }
|
||||
public ushort Priority { get; }
|
||||
public float FallbackScore { get; }
|
||||
public string Value { get; }
|
||||
internal Qualifier (ushort index, QualifierType type, ushort priority, float fallbackScore, string value)
|
||||
{
|
||||
Index = index;
|
||||
Type = type;
|
||||
Priority = priority;
|
||||
FallbackScore = fallbackScore;
|
||||
Value = value;
|
||||
}
|
||||
public override string ToString ()
|
||||
{
|
||||
return $"Index: {Index} Type: {Type} Value: {Value} Priority: {Priority} FallbackScore: {FallbackScore}";
|
||||
}
|
||||
}
|
||||
public class QualifierSet
|
||||
{
|
||||
public ushort Index { get; }
|
||||
public IReadOnlyList <Qualifier> Qualifiers { get; }
|
||||
internal QualifierSet (ushort index, IReadOnlyList <Qualifier> qualifiers)
|
||||
{
|
||||
Index = index;
|
||||
Qualifiers = qualifiers;
|
||||
}
|
||||
public override string ToString ()
|
||||
{
|
||||
return $"Index: {Index} Qualifiers: {Qualifiers.Count}";
|
||||
}
|
||||
}
|
||||
public class Decision
|
||||
{
|
||||
public ushort Index { get; }
|
||||
public IReadOnlyList <QualifierSet> QualifierSets { get; }
|
||||
internal Decision (ushort index, IReadOnlyList<QualifierSet> qualifierSets)
|
||||
{
|
||||
Index = index;
|
||||
QualifierSets = qualifierSets;
|
||||
}
|
||||
public override string ToString ()
|
||||
{
|
||||
return $"Index: {Index} Qualifier sets: {QualifierSets.Count}";
|
||||
}
|
||||
}
|
||||
}
|
||||
289
PriFileFormat/HierarchicalSchemaSection.cs
Normal file
289
PriFileFormat/HierarchicalSchemaSection.cs
Normal file
@@ -0,0 +1,289 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
namespace PriFileFormat
|
||||
{
|
||||
public class HierarchicalSchemaSection: Section
|
||||
{
|
||||
public HierarchicalSchemaVersionInfo Version { get; private set; }
|
||||
public string UniqueName { get; private set; }
|
||||
public string Name { get; private set; }
|
||||
public IReadOnlyList <ResourceMapScope> Scopes { get; private set; }
|
||||
public IReadOnlyList <ResourceMapItem> Items { get; private set; }
|
||||
bool extendedVersion;
|
||||
internal const string Identifier1 = "[mrm_hschema] \0";
|
||||
internal const string Identifier2 = "[mrm_hschemaex] ";
|
||||
internal HierarchicalSchemaSection (PriFile priFile, bool extendedVersion) : base (extendedVersion ? Identifier2 : Identifier1, priFile)
|
||||
{
|
||||
this.extendedVersion = extendedVersion;
|
||||
}
|
||||
protected override bool ParseSectionContent (BinaryReader binaryReader)
|
||||
{
|
||||
if (binaryReader.BaseStream.Length == 0)
|
||||
{
|
||||
Version = null;
|
||||
UniqueName = null;
|
||||
Name = null;
|
||||
Scopes = Array.Empty<ResourceMapScope> ();
|
||||
Items = Array.Empty<ResourceMapItem> ();
|
||||
return true;
|
||||
}
|
||||
binaryReader.ExpectUInt16 (1);
|
||||
ushort uniqueNameLength = binaryReader.ReadUInt16 ();
|
||||
ushort nameLength = binaryReader.ReadUInt16 ();
|
||||
binaryReader.ExpectUInt16 (0);
|
||||
bool extendedHNames;
|
||||
if (extendedVersion)
|
||||
{
|
||||
extendedHNames = false;
|
||||
string extstr = new string (binaryReader.ReadChars (16));
|
||||
if (extstr == "[def_hnamesx] \0") extendedHNames = true;
|
||||
else if (extstr == "[def_hnames] \0") extendedHNames = false;
|
||||
else throw new InvalidDataException ();
|
||||
}
|
||||
else extendedHNames = false;
|
||||
// hierarchical schema version info
|
||||
ushort majorVersion = binaryReader.ReadUInt16 ();
|
||||
ushort minorVersion = binaryReader.ReadUInt16 ();
|
||||
binaryReader.ExpectUInt32 (0);
|
||||
uint checksum = binaryReader.ReadUInt32 ();
|
||||
uint numScopes = binaryReader.ReadUInt32 ();
|
||||
uint numItems = binaryReader.ReadUInt32 ();
|
||||
Version = new HierarchicalSchemaVersionInfo (majorVersion, minorVersion, checksum, numScopes, numItems);
|
||||
UniqueName = binaryReader.ReadNullTerminatedString (Encoding.Unicode);
|
||||
Name = binaryReader.ReadNullTerminatedString (Encoding.Unicode);
|
||||
if (UniqueName.Length != uniqueNameLength - 1 || Name.Length != nameLength - 1) throw new InvalidDataException ();
|
||||
binaryReader.ExpectUInt16 (0);
|
||||
ushort maxFullPathLength = binaryReader.ReadUInt16 ();
|
||||
binaryReader.ExpectUInt16 (0);
|
||||
binaryReader.ExpectUInt32 (numScopes + numItems);
|
||||
binaryReader.ExpectUInt32 (numScopes);
|
||||
binaryReader.ExpectUInt32 (numItems);
|
||||
uint unicodeDataLength = binaryReader.ReadUInt32 ();
|
||||
binaryReader.ReadUInt32 (); // meaning unknown
|
||||
if (extendedHNames) binaryReader.ReadUInt32 (); // meaning unknown
|
||||
List <ScopeAndItemInfo> scopeAndItemInfos = new List<ScopeAndItemInfo> ((int)(numScopes + numItems));
|
||||
for (int i = 0; i < numScopes + numItems; i++)
|
||||
{
|
||||
ushort parent = binaryReader.ReadUInt16 ();
|
||||
ushort fullPathLength = binaryReader.ReadUInt16 ();
|
||||
char uppercaseFirstChar = (char)binaryReader.ReadUInt16 ();
|
||||
byte nameLength2 = binaryReader.ReadByte ();
|
||||
byte flags = binaryReader.ReadByte ();
|
||||
uint nameOffset = binaryReader.ReadUInt16 () | (uint)((flags & 0xF) << 16);
|
||||
ushort index = binaryReader.ReadUInt16 ();
|
||||
bool isScope = (flags & 0x10) != 0;
|
||||
bool nameInAscii = (flags & 0x20) != 0;
|
||||
scopeAndItemInfos.Add (new ScopeAndItemInfo (parent, fullPathLength, isScope, nameInAscii, nameOffset, index));
|
||||
}
|
||||
List <ScopeExInfo> scopeExInfos = new List <ScopeExInfo> ((int)numScopes);
|
||||
for (int i = 0; i < numScopes; i++)
|
||||
{
|
||||
ushort scopeIndex = binaryReader.ReadUInt16 ();
|
||||
ushort childCount = binaryReader.ReadUInt16 ();
|
||||
ushort firstChildIndex = binaryReader.ReadUInt16 ();
|
||||
binaryReader.ExpectUInt16 (0);
|
||||
scopeExInfos.Add (new ScopeExInfo (scopeIndex, childCount, firstChildIndex));
|
||||
}
|
||||
ushort [] itemIndexPropertyToIndex = new ushort [numItems];
|
||||
for (int i = 0; i < numItems; i++) itemIndexPropertyToIndex [i] = binaryReader.ReadUInt16 ();
|
||||
long unicodeDataOffset = binaryReader.BaseStream.Position;
|
||||
long asciiDataOffset = binaryReader.BaseStream.Position + unicodeDataLength * 2;
|
||||
ResourceMapScope [] scopes = new ResourceMapScope [numScopes];
|
||||
ResourceMapItem [] items = new ResourceMapItem [numItems];
|
||||
for (int i = 0; i < numScopes + numItems; i++)
|
||||
{
|
||||
long pos;
|
||||
if (scopeAndItemInfos [i].NameInAscii) pos = asciiDataOffset + scopeAndItemInfos [i].NameOffset;
|
||||
else pos = unicodeDataOffset + scopeAndItemInfos [i].NameOffset * 2;
|
||||
binaryReader.BaseStream.Seek (pos, SeekOrigin.Begin);
|
||||
string name;
|
||||
if (scopeAndItemInfos [i].FullPathLength != 0) name = binaryReader.ReadNullTerminatedString (scopeAndItemInfos [i].NameInAscii ? Encoding.ASCII : Encoding.Unicode);
|
||||
else name = string.Empty;
|
||||
ushort index = scopeAndItemInfos [i].Index;
|
||||
if (scopeAndItemInfos [i].IsScope)
|
||||
{
|
||||
if (scopes [index] != null) throw new InvalidDataException ();
|
||||
scopes [index] = new ResourceMapScope (index, null, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (items [index] != null) throw new InvalidDataException ();
|
||||
items [index] = new ResourceMapItem (index, null, name);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < numScopes + numItems; i++)
|
||||
{
|
||||
ushort index = scopeAndItemInfos [i].Index;
|
||||
ushort parent = scopeAndItemInfos [scopeAndItemInfos [i].Parent].Index;
|
||||
if (parent != 0xFFFF)
|
||||
if (scopeAndItemInfos [i].IsScope)
|
||||
{
|
||||
if (parent != index) scopes [index].Parent = scopes [parent];
|
||||
}
|
||||
else items [index].Parent = scopes [parent];
|
||||
}
|
||||
for (int i = 0; i < numScopes; i++)
|
||||
{
|
||||
List <ResourceMapEntry> children = new List<ResourceMapEntry> (scopeExInfos [i].ChildCount);
|
||||
for (int j = 0; j < scopeExInfos [i].ChildCount; j++)
|
||||
{
|
||||
ScopeAndItemInfo saiInfo = scopeAndItemInfos [scopeExInfos [i].FirstChildIndex + j];
|
||||
if (saiInfo.IsScope) children.Add (scopes [saiInfo.Index]);
|
||||
else children.Add (items [saiInfo.Index]);
|
||||
}
|
||||
scopes [i].Children = children;
|
||||
}
|
||||
Scopes = scopes;
|
||||
Items = items;
|
||||
//if (checksum != ComputeHierarchicalSchemaVersionInfoChecksum())
|
||||
// throw new Exception();
|
||||
return true;
|
||||
}
|
||||
private struct ScopeAndItemInfo
|
||||
{
|
||||
public ushort Parent;
|
||||
public ushort FullPathLength;
|
||||
public bool IsScope;
|
||||
public bool NameInAscii;
|
||||
public uint NameOffset;
|
||||
public ushort Index;
|
||||
public ScopeAndItemInfo (ushort parent, ushort fullPathLength, bool isScope, bool nameInAscii, uint nameOffset, ushort index)
|
||||
{
|
||||
Parent = parent;
|
||||
FullPathLength = fullPathLength;
|
||||
IsScope = isScope;
|
||||
NameInAscii = nameInAscii;
|
||||
NameOffset = nameOffset;
|
||||
Index = index;
|
||||
}
|
||||
}
|
||||
private struct ScopeExInfo
|
||||
{
|
||||
public ushort ScopeIndex;
|
||||
public ushort ChildCount;
|
||||
public ushort FirstChildIndex;
|
||||
public ScopeExInfo (ushort scopeIndex, ushort childCount, ushort firstChildIndex)
|
||||
{
|
||||
ScopeIndex = scopeIndex;
|
||||
ChildCount = childCount;
|
||||
FirstChildIndex = firstChildIndex;
|
||||
}
|
||||
}
|
||||
~HierarchicalSchemaSection ()
|
||||
{
|
||||
Version = null;
|
||||
foreach (var item in Items) { item.Parent = null; }
|
||||
foreach (var scope in Scopes) { scope.Parent = null; }
|
||||
Scopes = null;
|
||||
Items = null;
|
||||
}
|
||||
// Checksum computation is buggy for some files
|
||||
|
||||
//private uint ComputeHierarchicalSchemaVersionInfoChecksum()
|
||||
//{
|
||||
// CRC32 crc32 = new CRC32();
|
||||
|
||||
// StringChecksum(crc32, UniqueName);
|
||||
// StringChecksum(crc32, Name);
|
||||
// crc32.TransformBlock(BitConverter.GetBytes(Version.MajorVersion), 0, 2, new byte[2], 0);
|
||||
// crc32.TransformBlock(BitConverter.GetBytes(Version.MinorVersion), 0, 2, new byte[2], 0);
|
||||
|
||||
// crc32.TransformBlock(BitConverter.GetBytes(0), 0, 4, new byte[4], 0);
|
||||
// crc32.TransformBlock(BitConverter.GetBytes(0), 0, 4, new byte[4], 0);
|
||||
// crc32.TransformBlock(BitConverter.GetBytes(1), 0, 4, new byte[4], 0);
|
||||
|
||||
// crc32.TransformBlock(BitConverter.GetBytes(Scopes.Count), 0, 4, new byte[4], 0);
|
||||
// foreach (ResourceMapScope scope in Scopes)
|
||||
// StringChecksum(crc32, scope.FullName.Replace('\\', '/').TrimStart('/'));
|
||||
|
||||
// crc32.TransformBlock(BitConverter.GetBytes(0), 0, 4, new byte[4], 0);
|
||||
// crc32.TransformBlock(BitConverter.GetBytes(0), 0, 4, new byte[4], 0);
|
||||
// crc32.TransformBlock(BitConverter.GetBytes(1), 0, 4, new byte[4], 0);
|
||||
|
||||
// crc32.TransformBlock(BitConverter.GetBytes(Items.Count), 0, 4, new byte[4], 0);
|
||||
// foreach (ResourceMapItem item in Items)
|
||||
// StringChecksum(crc32, item.FullName.Replace('\\', '/').TrimStart('/'));
|
||||
|
||||
// return crc32.Result;
|
||||
//}
|
||||
|
||||
//private void StringChecksum(CRC32 crc32, string s)
|
||||
//{
|
||||
// if (s == null)
|
||||
// {
|
||||
// byte[] data = new byte[8];
|
||||
|
||||
// crc32.TransformBlock(data, 0, data.Length, new byte[data.Length], 0);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// byte[] data = Encoding.Unicode.GetBytes(s.ToLowerInvariant() + '\0');
|
||||
// byte[] l = BitConverter.GetBytes(data.Length);
|
||||
|
||||
// crc32.TransformBlock(l, 0, l.Length, new byte[l.Length], 0);
|
||||
// crc32.TransformBlock(data, 0, data.Length, new byte[data.Length], 0);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
public class HierarchicalSchemaVersionInfo
|
||||
{
|
||||
public ushort MajorVersion { get; }
|
||||
public ushort MinorVersion { get; }
|
||||
public uint Checksum { get; }
|
||||
public uint NumScopes { get; }
|
||||
public uint NumItems { get; }
|
||||
internal HierarchicalSchemaVersionInfo (ushort majorVersion, ushort minorVersion, uint checksum, uint numScopes, uint numItems)
|
||||
{
|
||||
MajorVersion = majorVersion;
|
||||
MinorVersion = minorVersion;
|
||||
Checksum = checksum;
|
||||
NumScopes = numScopes;
|
||||
NumItems = numItems;
|
||||
}
|
||||
}
|
||||
public class ResourceMapEntry
|
||||
{
|
||||
public ushort Index { get; }
|
||||
public ResourceMapScope Parent { get; internal set; }
|
||||
public string Name { get; }
|
||||
internal ResourceMapEntry (ushort index, ResourceMapScope parent, string name)
|
||||
{
|
||||
Index = index;
|
||||
Parent = parent;
|
||||
Name = name;
|
||||
}
|
||||
string fullName;
|
||||
public string FullName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (fullName == null)
|
||||
if (Parent == null) fullName = Name;
|
||||
else fullName = Parent.FullName + "\\" + Name;
|
||||
return fullName;
|
||||
}
|
||||
}
|
||||
~ResourceMapEntry () { Parent = null; }
|
||||
}
|
||||
public class ResourceMapScope: ResourceMapEntry
|
||||
{
|
||||
internal ResourceMapScope (ushort index, ResourceMapScope parent, string name) : base (index, parent, name) {}
|
||||
public IReadOnlyList <ResourceMapEntry> Children { get; internal set; }
|
||||
public override string ToString ()
|
||||
{
|
||||
return $"Scope {Index} {FullName} ({Children.Count} children)";
|
||||
}
|
||||
~ResourceMapScope () { Children = null; }
|
||||
}
|
||||
public class ResourceMapItem: ResourceMapEntry
|
||||
{
|
||||
internal ResourceMapItem (ushort index, ResourceMapScope parent, string name) : base (index, parent, name) {}
|
||||
public override string ToString ()
|
||||
{
|
||||
return $"Item {Index} {FullName}";
|
||||
}
|
||||
}
|
||||
}
|
||||
74
PriFileFormat/PriDescriptorSection.cs
Normal file
74
PriFileFormat/PriDescriptorSection.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
namespace PriFileFormat
|
||||
{
|
||||
public class PriDescriptorSection: Section
|
||||
{
|
||||
public PriDescriptorFlags PriFlags { get; private set; }
|
||||
public IReadOnlyList <SectionRef <HierarchicalSchemaSection>> HierarchicalSchemaSections { get; private set; }
|
||||
public IReadOnlyList <SectionRef <DecisionInfoSection>> DecisionInfoSections { get; private set; }
|
||||
public IReadOnlyList<SectionRef <ResourceMapSection>> ResourceMapSections { get; private set; }
|
||||
public IReadOnlyList <SectionRef <ReferencedFileSection>> ReferencedFileSections { get; private set; }
|
||||
public IReadOnlyList<SectionRef <DataItemSection>> DataItemSections { get; private set; }
|
||||
public SectionRef <ResourceMapSection> ?PrimaryResourceMapSection { get; private set; }
|
||||
internal const string Identifier = "[mrm_pridescex]\0";
|
||||
internal PriDescriptorSection (PriFile priFile) : base (Identifier, priFile) {}
|
||||
protected override bool ParseSectionContent (BinaryReader binaryReader)
|
||||
{
|
||||
PriFlags = (PriDescriptorFlags)binaryReader.ReadUInt16 ();
|
||||
ushort includedFileListSection = binaryReader.ReadUInt16 ();
|
||||
binaryReader.ExpectUInt16 (0);
|
||||
ushort numHierarchicalSchemaSections = binaryReader.ReadUInt16 ();
|
||||
ushort numDecisionInfoSections = binaryReader.ReadUInt16 ();
|
||||
ushort numResourceMapSections = binaryReader.ReadUInt16 ();
|
||||
ushort primaryResourceMapSection = binaryReader.ReadUInt16 ();
|
||||
if (primaryResourceMapSection != 0xFFFF) PrimaryResourceMapSection = new SectionRef<ResourceMapSection> (primaryResourceMapSection);
|
||||
else PrimaryResourceMapSection = null;
|
||||
ushort numReferencedFileSections = binaryReader.ReadUInt16 ();
|
||||
ushort numDataItemSections = binaryReader.ReadUInt16 ();
|
||||
binaryReader.ExpectUInt16 (0);
|
||||
List <SectionRef <HierarchicalSchemaSection>> hierarchicalSchemaSections = new List <SectionRef <HierarchicalSchemaSection>> (numHierarchicalSchemaSections);
|
||||
for (int i = 0; i < numHierarchicalSchemaSections; i++) hierarchicalSchemaSections.Add (new SectionRef <HierarchicalSchemaSection> (binaryReader.ReadUInt16 ()));
|
||||
HierarchicalSchemaSections = hierarchicalSchemaSections;
|
||||
List <SectionRef <DecisionInfoSection>> decisionInfoSections = new List <SectionRef <DecisionInfoSection>> (numDecisionInfoSections);
|
||||
for (int i = 0; i < numDecisionInfoSections; i++) decisionInfoSections.Add (new SectionRef <DecisionInfoSection> (binaryReader.ReadUInt16 ()));
|
||||
DecisionInfoSections = decisionInfoSections;
|
||||
List<SectionRef<ResourceMapSection>> resourceMapSections = new List<SectionRef<ResourceMapSection>> (numResourceMapSections);
|
||||
for (int i = 0; i < numResourceMapSections; i++) resourceMapSections.Add (new SectionRef <ResourceMapSection> (binaryReader.ReadUInt16 ()));
|
||||
ResourceMapSections = resourceMapSections;
|
||||
List <SectionRef <ReferencedFileSection>> referencedFileSections = new List <SectionRef <ReferencedFileSection>> (numReferencedFileSections);
|
||||
for (int i = 0; i < numReferencedFileSections; i++) referencedFileSections.Add (new SectionRef <ReferencedFileSection> (binaryReader.ReadUInt16 ()));
|
||||
ReferencedFileSections = referencedFileSections;
|
||||
List <SectionRef <DataItemSection>> dataItemSections = new List <SectionRef <DataItemSection>> (numDataItemSections);
|
||||
for (int i = 0; i < numDataItemSections; i++) dataItemSections.Add (new SectionRef <DataItemSection> (binaryReader.ReadUInt16 ()));
|
||||
DataItemSections = dataItemSections;
|
||||
return true;
|
||||
}
|
||||
~PriDescriptorSection ()
|
||||
{
|
||||
HierarchicalSchemaSections = null;
|
||||
DecisionInfoSections = null;
|
||||
ResourceMapSections = null;
|
||||
ReferencedFileSections = null;
|
||||
DataItemSections = null;
|
||||
PrimaryResourceMapSection = null;
|
||||
}
|
||||
}
|
||||
[Flags]
|
||||
public enum PriDescriptorFlags: ushort
|
||||
{
|
||||
AutoMerge = 1,
|
||||
IsDeploymentMergeable = 2,
|
||||
IsDeploymentMergeResult = 4,
|
||||
IsAutomergeMergeResult = 8
|
||||
}
|
||||
public struct SectionRef <T> where T : Section
|
||||
{
|
||||
internal int sectionIndex;
|
||||
internal SectionRef (int sectionIndex) { this.sectionIndex = sectionIndex; }
|
||||
public override string ToString () { return $"Section {typeof (T).Name} at index {sectionIndex}"; }
|
||||
}
|
||||
|
||||
}
|
||||
187
PriFileFormat/PriFile.cs
Normal file
187
PriFileFormat/PriFile.cs
Normal file
@@ -0,0 +1,187 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System;
|
||||
|
||||
namespace PriFileFormat
|
||||
{
|
||||
public class PriFile: IDisposable
|
||||
{
|
||||
public string Version { get; private set; }
|
||||
public uint TotalFileSize { get; private set; }
|
||||
public IReadOnlyList <TocEntry> TableOfContents { get; private set; }
|
||||
public IReadOnlyList <Section> Sections { get; private set; }
|
||||
private bool _disposed = false;
|
||||
private Stream _internalStream; // 跟踪内部流
|
||||
private PriFile ()
|
||||
{
|
||||
}
|
||||
|
||||
public static PriFile Parse (Stream stream)
|
||||
{
|
||||
PriFile priFile = new PriFile ();
|
||||
priFile.ParseInternal (stream, false);
|
||||
return priFile;
|
||||
}
|
||||
|
||||
public static PriFile Parse (System.Runtime.InteropServices.ComTypes.IStream stream)
|
||||
{
|
||||
|
||||
ComStreamWrapper csw = new ComStreamWrapper (stream);
|
||||
PriFile priFile = new PriFile ();
|
||||
priFile.ParseInternal (csw, true);
|
||||
return priFile;
|
||||
}
|
||||
|
||||
private void ParseInternal (Stream stream, bool ownStream)
|
||||
{
|
||||
if (ownStream) { _internalStream = stream; }
|
||||
using (BinaryReader binaryReader = new BinaryReader (stream, Encoding.ASCII, true))
|
||||
{
|
||||
long fileStartOffset = binaryReader.BaseStream.Position;
|
||||
|
||||
string magic = new string (binaryReader.ReadChars (8));
|
||||
|
||||
switch (magic)
|
||||
{
|
||||
case "mrm_pri0":
|
||||
case "mrm_pri1":
|
||||
case "mrm_pri2":
|
||||
case "mrm_prif":
|
||||
Version = magic;
|
||||
break;
|
||||
default:
|
||||
throw new InvalidDataException ("Data does not start with a PRI file header.");
|
||||
}
|
||||
|
||||
binaryReader.ExpectUInt16 (0);
|
||||
binaryReader.ExpectUInt16 (1);
|
||||
TotalFileSize = binaryReader.ReadUInt32 ();
|
||||
uint tocOffset = binaryReader.ReadUInt32 ();
|
||||
uint sectionStartOffset = binaryReader.ReadUInt32 ();
|
||||
ushort numSections = binaryReader.ReadUInt16 ();
|
||||
|
||||
binaryReader.ExpectUInt16 (0xFFFF);
|
||||
binaryReader.ExpectUInt32 (0);
|
||||
|
||||
binaryReader.BaseStream.Seek (fileStartOffset + TotalFileSize - 16, SeekOrigin.Begin);
|
||||
|
||||
binaryReader.ExpectUInt32 (0xDEFFFADE);
|
||||
binaryReader.ExpectUInt32 (TotalFileSize);
|
||||
binaryReader.ExpectString (magic);
|
||||
|
||||
binaryReader.BaseStream.Seek (tocOffset, SeekOrigin.Begin);
|
||||
|
||||
List<TocEntry> toc = new List<TocEntry> (numSections);
|
||||
|
||||
for (int i = 0; i < numSections; i++)
|
||||
toc.Add (TocEntry.Parse (binaryReader));
|
||||
|
||||
TableOfContents = toc;
|
||||
|
||||
Section [] sections = new Section [numSections];
|
||||
|
||||
Sections = sections;
|
||||
|
||||
bool parseSuccess = false;
|
||||
bool parseFailure = false;
|
||||
|
||||
do
|
||||
{
|
||||
for (int i = 0; i < sections.Length; i++)
|
||||
if (sections [i] == null)
|
||||
{
|
||||
binaryReader.BaseStream.Seek (sectionStartOffset + toc [i].SectionOffset, SeekOrigin.Begin);
|
||||
|
||||
Section section = Section.CreateForIdentifier (toc [i].SectionIdentifier, this);
|
||||
|
||||
if (section.Parse (binaryReader))
|
||||
{
|
||||
sections [i] = section;
|
||||
parseSuccess = true;
|
||||
}
|
||||
else
|
||||
parseFailure = true;
|
||||
}
|
||||
} while (parseFailure && parseSuccess);
|
||||
|
||||
if (parseFailure)
|
||||
throw new InvalidDataException ();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
Dispose (true);
|
||||
GC.SuppressFinalize (this);
|
||||
}
|
||||
protected virtual void Dispose (bool disposing)
|
||||
{
|
||||
if (_disposed) return;
|
||||
if (disposing)
|
||||
{
|
||||
// 释放托管资源
|
||||
if (_internalStream != null)
|
||||
{
|
||||
_internalStream.Dispose ();
|
||||
_internalStream = null;
|
||||
}
|
||||
|
||||
// 释放 section 内容
|
||||
if (Sections != null)
|
||||
{
|
||||
foreach (var section in Sections)
|
||||
{
|
||||
var unknown = section as UnknownSection;
|
||||
if (unknown != null)
|
||||
unknown.ClearContent ();
|
||||
|
||||
var dataSection = section as DataItemSection;
|
||||
if (dataSection != null)
|
||||
dataSection.ClearData ();
|
||||
}
|
||||
Sections = null;
|
||||
}
|
||||
}
|
||||
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
~PriFile ()
|
||||
{
|
||||
Dispose (false);
|
||||
}
|
||||
|
||||
PriDescriptorSection priDescriptorSection;
|
||||
|
||||
public PriDescriptorSection PriDescriptorSection
|
||||
{
|
||||
get
|
||||
{
|
||||
if (priDescriptorSection == null) priDescriptorSection = Sections.OfType<PriDescriptorSection> ().Single ();
|
||||
return priDescriptorSection;
|
||||
}
|
||||
}
|
||||
|
||||
public T GetSectionByRef<T> (SectionRef<T> sectionRef) where T : Section
|
||||
{
|
||||
return (T)Sections [sectionRef.sectionIndex];
|
||||
}
|
||||
|
||||
public ResourceMapItem GetResourceMapItemByRef (ResourceMapItemRef resourceMapItemRef)
|
||||
{
|
||||
return GetSectionByRef (resourceMapItemRef.schemaSection).Items [resourceMapItemRef.itemIndex];
|
||||
}
|
||||
|
||||
public ByteSpan GetDataItemByRef (DataItemRef dataItemRef)
|
||||
{
|
||||
return GetSectionByRef (dataItemRef.dataItemSection).DataItems [dataItemRef.itemIndex];
|
||||
}
|
||||
|
||||
public ReferencedFile GetReferencedFileByRef (ReferencedFileRef referencedFileRef)
|
||||
{
|
||||
return GetSectionByRef (PriDescriptorSection.ReferencedFileSections.First ()).ReferencedFiles [referencedFileRef.fileIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
87
PriFileFormat/PriFile.csproj
Normal file
87
PriFileFormat/PriFile.csproj
Normal file
@@ -0,0 +1,87 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{EF4012D4-EF08-499C-B803-177739350B2D}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>PriFileFormat</RootNamespace>
|
||||
<AssemblyName>PriFileFormat</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
|
||||
<RegisterForComInterop>false</RegisterForComInterop>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
<RegisterForComInterop>false</RegisterForComInterop>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ByteSpan.cs" />
|
||||
<Compile Include="ComStreamWrapper.cs" />
|
||||
<Compile Include="DataItemSection.cs" />
|
||||
<Compile Include="DecisionInfoSection.cs" />
|
||||
<Compile Include="HierarchicalSchemaSection.cs" />
|
||||
<Compile Include="PriDescriptorSection.cs" />
|
||||
<Compile Include="PriFile.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="ReferencedFileSection.cs" />
|
||||
<Compile Include="Replenish.cs" />
|
||||
<Compile Include="ResourceMapSection.cs" />
|
||||
<Compile Include="ReverseMapSection.cs" />
|
||||
<Compile Include="Section.cs" />
|
||||
<Compile Include="SubStream.cs" />
|
||||
<Compile Include="TocEntry.cs" />
|
||||
<Compile Include="UnknownSection.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
36
PriFileFormat/Properties/AssemblyInfo.cs
Normal file
36
PriFileFormat/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// 有关程序集的一般信息由以下
|
||||
// 控制。更改这些特性值可修改
|
||||
// 与程序集关联的信息。
|
||||
[assembly: AssemblyTitle ("Pri File Format")]
|
||||
[assembly: AssemblyDescription ("Pri File Reader")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany ("")]
|
||||
[assembly: AssemblyProduct ("Pri File Reader")]
|
||||
[assembly: AssemblyCopyright ("© 2025 Windows Modern. Based on chausner/PriTools (Apache 2.0). All rights reserved.")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
//将 ComVisible 设置为 false 将使此程序集中的类型
|
||||
//对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
|
||||
//请将此类型的 ComVisible 特性设置为 true。
|
||||
[assembly: ComVisible (false)]
|
||||
|
||||
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
|
||||
[assembly: Guid("ef4012d4-ef08-499c-b803-177739350b2d")]
|
||||
|
||||
// 程序集的版本信息由下列四个值组成:
|
||||
//
|
||||
// 主版本
|
||||
// 次版本
|
||||
// 生成号
|
||||
// 修订号
|
||||
//
|
||||
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
|
||||
// 方法是按如下所示使用“*”: :
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
63
PriFileFormat/Properties/Resources.Designer.cs
generated
Normal file
63
PriFileFormat/Properties/Resources.Designer.cs
generated
Normal file
@@ -0,0 +1,63 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// 此代码由工具生成。
|
||||
// 运行时版本:4.0.30319.42000
|
||||
//
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果
|
||||
// 重新生成代码,这些更改将会丢失。
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace PriFileFormat.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("PriFileFormat.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
101
PriFileFormat/Properties/Resources.resx
Normal file
101
PriFileFormat/Properties/Resources.resx
Normal file
@@ -0,0 +1,101 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 1.3
|
||||
|
||||
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">1.3</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1">this is my long string</data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
[base64 mime encoded serialized .NET Framework object]
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
[base64 mime encoded string representing a byte array form of the .NET Framework object]
|
||||
</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.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:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<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" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</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>1.3</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
174
PriFileFormat/ReferencedFileSection.cs
Normal file
174
PriFileFormat/ReferencedFileSection.cs
Normal file
@@ -0,0 +1,174 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
namespace PriFileFormat
|
||||
{
|
||||
public class ReferencedFileSection: Section
|
||||
{
|
||||
public List <ReferencedFile> ReferencedFiles { get; private set; }
|
||||
internal const string Identifier = "[def_file_list]\0";
|
||||
internal ReferencedFileSection (PriFile priFile) : base (Identifier, priFile) {}
|
||||
protected override bool ParseSectionContent (BinaryReader binaryReader)
|
||||
{
|
||||
ushort numRoots = binaryReader.ReadUInt16 ();
|
||||
ushort numFolders = binaryReader.ReadUInt16 ();
|
||||
ushort numFiles = binaryReader.ReadUInt16 ();
|
||||
binaryReader.ExpectUInt16 (0);
|
||||
uint totalDataLength = binaryReader.ReadUInt32 ();
|
||||
List <FolderInfo> folderInfos = new List <FolderInfo> (numFolders);
|
||||
for (int i = 0; i < numFolders; i++)
|
||||
{
|
||||
binaryReader.ExpectUInt16 (0);
|
||||
ushort parentFolder = binaryReader.ReadUInt16 ();
|
||||
ushort numFoldersInFolder = binaryReader.ReadUInt16 ();
|
||||
ushort firstFolderInFolder = binaryReader.ReadUInt16 ();
|
||||
ushort numFilesInFolder = binaryReader.ReadUInt16 ();
|
||||
ushort firstFileInFolder = binaryReader.ReadUInt16 ();
|
||||
ushort folderNameLength = binaryReader.ReadUInt16 ();
|
||||
ushort fullPathLength = binaryReader.ReadUInt16 ();
|
||||
uint folderNameOffset = binaryReader.ReadUInt32 ();
|
||||
folderInfos.Add (new FolderInfo (parentFolder, numFoldersInFolder, firstFolderInFolder, numFilesInFolder, firstFileInFolder, folderNameLength, fullPathLength, folderNameOffset));
|
||||
}
|
||||
List <FileInfo> fileInfos = new List <FileInfo> (numFiles);
|
||||
for (int i = 0; i < numFiles; i++)
|
||||
{
|
||||
binaryReader.ReadUInt16 ();
|
||||
ushort parentFolder = binaryReader.ReadUInt16 ();
|
||||
ushort fullPathLength = binaryReader.ReadUInt16 ();
|
||||
ushort fileNameLength = binaryReader.ReadUInt16 ();
|
||||
uint fileNameOffset = binaryReader.ReadUInt32 ();
|
||||
fileInfos.Add (new FileInfo (parentFolder, fullPathLength, fileNameLength, fileNameOffset));
|
||||
}
|
||||
long dataStartPosition = binaryReader.BaseStream.Position;
|
||||
List <ReferencedFolder> referencedFolders = new List <ReferencedFolder> (numFolders);
|
||||
for (int i = 0; i < numFolders; i++)
|
||||
{
|
||||
binaryReader.BaseStream.Seek (dataStartPosition + folderInfos [i].FolderNameOffset * 2, SeekOrigin.Begin);
|
||||
string name = binaryReader.ReadString (Encoding.Unicode, folderInfos [i].FolderNameLength);
|
||||
referencedFolders.Add (new ReferencedFolder (null, name));
|
||||
}
|
||||
for (int i = 0; i < numFolders; i++)
|
||||
if (folderInfos [i].ParentFolder != 0xFFFF)
|
||||
referencedFolders [i].Parent = referencedFolders [folderInfos [i].ParentFolder];
|
||||
List <ReferencedFile> referencedFiles = new List<ReferencedFile> (numFiles);
|
||||
for (int i = 0; i < numFiles; i++)
|
||||
{
|
||||
binaryReader.BaseStream.Seek (dataStartPosition + fileInfos [i].FileNameOffset * 2, SeekOrigin.Begin);
|
||||
|
||||
string name = binaryReader.ReadString (Encoding.Unicode, fileInfos [i].FileNameLength);
|
||||
|
||||
ReferencedFolder parentFolder;
|
||||
|
||||
if (fileInfos [i].ParentFolder != 0xFFFF)
|
||||
parentFolder = referencedFolders [fileInfos [i].ParentFolder];
|
||||
else
|
||||
parentFolder = null;
|
||||
|
||||
referencedFiles.Add (new ReferencedFile (parentFolder, name));
|
||||
}
|
||||
|
||||
for (int i = 0; i < numFolders; i++)
|
||||
{
|
||||
List<ReferencedEntry> children = new List<ReferencedEntry> (folderInfos [i].NumFoldersInFolder + folderInfos [i].NumFilesInFolder);
|
||||
|
||||
for (int j = 0; j < folderInfos [i].NumFoldersInFolder; j++)
|
||||
children.Add (referencedFolders [folderInfos [i].FirstFolderInFolder + j]);
|
||||
|
||||
for (int j = 0; j < folderInfos [i].NumFilesInFolder; j++)
|
||||
children.Add (referencedFiles [folderInfos [i].FirstFileInFolder + j]);
|
||||
|
||||
referencedFolders [i].Children = children;
|
||||
}
|
||||
|
||||
ReferencedFiles = referencedFiles;
|
||||
|
||||
return true;
|
||||
}
|
||||
private struct FolderInfo
|
||||
{
|
||||
public ushort ParentFolder;
|
||||
public ushort NumFoldersInFolder;
|
||||
public ushort FirstFolderInFolder;
|
||||
public ushort NumFilesInFolder;
|
||||
public ushort FirstFileInFolder;
|
||||
public ushort FolderNameLength;
|
||||
public ushort FullPathLength;
|
||||
public uint FolderNameOffset;
|
||||
public FolderInfo (ushort parentFolder, ushort numFoldersInFolder, ushort firstFolderInFolder, ushort numFilesInFolder, ushort firstFileInFolder, ushort folderNameLength, ushort fullPathLength, uint folderNameOffset)
|
||||
{
|
||||
ParentFolder = parentFolder;
|
||||
NumFoldersInFolder = numFoldersInFolder;
|
||||
FirstFolderInFolder = firstFolderInFolder;
|
||||
NumFilesInFolder = numFilesInFolder;
|
||||
FirstFileInFolder = firstFileInFolder;
|
||||
FolderNameLength = folderNameLength;
|
||||
FullPathLength = fullPathLength;
|
||||
FolderNameOffset = folderNameOffset;
|
||||
}
|
||||
}
|
||||
private struct FileInfo
|
||||
{
|
||||
public ushort ParentFolder;
|
||||
public ushort FullPathLength;
|
||||
public ushort FileNameLength;
|
||||
public uint FileNameOffset;
|
||||
public FileInfo (ushort parentFolder, ushort fullPathLength, ushort fileNameLength, uint fileNameOffset)
|
||||
{
|
||||
ParentFolder = parentFolder;
|
||||
FullPathLength = fullPathLength;
|
||||
FileNameLength = fileNameLength;
|
||||
FileNameOffset = fileNameOffset;
|
||||
}
|
||||
}
|
||||
~ReferencedFileSection ()
|
||||
{
|
||||
foreach (var file in ReferencedFiles) { file.Parent = null; }
|
||||
ReferencedFiles = null;
|
||||
}
|
||||
}
|
||||
public class ReferencedEntry
|
||||
{
|
||||
public ReferencedFolder Parent { get; internal set; }
|
||||
public string Name { get; }
|
||||
internal ReferencedEntry (ReferencedFolder parent, string name)
|
||||
{
|
||||
Parent = parent;
|
||||
Name = name;
|
||||
}
|
||||
string fullName;
|
||||
public string FullName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (fullName == null)
|
||||
if (Parent == null)
|
||||
fullName = Name;
|
||||
else
|
||||
fullName = Parent.FullName + "\\" + Name;
|
||||
|
||||
return fullName;
|
||||
}
|
||||
}
|
||||
~ReferencedEntry () { Parent = null; }
|
||||
}
|
||||
public class ReferencedFolder: ReferencedEntry
|
||||
{
|
||||
internal ReferencedFolder (ReferencedFolder parent, string name) : base (parent, name) {}
|
||||
public IReadOnlyList<ReferencedEntry> Children { get; internal set; }
|
||||
~ReferencedFolder () { Children = null; }
|
||||
}
|
||||
public class ReferencedFile: ReferencedEntry
|
||||
{
|
||||
internal ReferencedFile (ReferencedFolder parent, string name) : base (parent, name) {}
|
||||
}
|
||||
public struct ReferencedFileRef
|
||||
{
|
||||
internal int fileIndex;
|
||||
internal ReferencedFileRef (int fileIndex)
|
||||
{
|
||||
this.fileIndex = fileIndex;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
55
PriFileFormat/Replenish.cs
Normal file
55
PriFileFormat/Replenish.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
namespace PriFileFormat
|
||||
{
|
||||
internal static class Replenish
|
||||
{
|
||||
public static string ReadString (this BinaryReader reader, Encoding encoding, int length)
|
||||
{
|
||||
using (BinaryReader r = new BinaryReader (reader.BaseStream, encoding, true))
|
||||
return new string (r.ReadChars (length));
|
||||
}
|
||||
|
||||
public static string ReadNullTerminatedString (this BinaryReader reader, Encoding encoding)
|
||||
{
|
||||
using (BinaryReader r = new BinaryReader (reader.BaseStream, encoding, true))
|
||||
{
|
||||
StringBuilder result = new StringBuilder ();
|
||||
char c;
|
||||
while ((c = r.ReadChar ()) != '\0')
|
||||
result.Append (c);
|
||||
return result.ToString ();
|
||||
}
|
||||
}
|
||||
|
||||
public static void ExpectByte (this BinaryReader reader, byte expectedValue)
|
||||
{
|
||||
if (reader.ReadByte () != expectedValue)
|
||||
throw new InvalidDataException ("Unexpected value read.");
|
||||
}
|
||||
|
||||
public static void ExpectUInt16 (this BinaryReader reader, ushort expectedValue)
|
||||
{
|
||||
if (reader.ReadUInt16 () != expectedValue)
|
||||
throw new InvalidDataException ("Unexpected value read.");
|
||||
}
|
||||
|
||||
public static void ExpectUInt32 (this BinaryReader reader, uint expectedValue)
|
||||
{
|
||||
if (reader.ReadUInt32 () != expectedValue)
|
||||
throw new InvalidDataException ("Unexpected value read.");
|
||||
}
|
||||
|
||||
public static void ExpectString (this BinaryReader reader, string s)
|
||||
{
|
||||
if (new string (reader.ReadChars (s.Length)) != s)
|
||||
throw new InvalidDataException ("Unexpected value read.");
|
||||
}
|
||||
public static string Limit (this string s, int length)
|
||||
{
|
||||
if (string.IsNullOrEmpty (s)) return s;
|
||||
return s.Length <= length ? s : s.Substring (0, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
390
PriFileFormat/ResourceMapSection.cs
Normal file
390
PriFileFormat/ResourceMapSection.cs
Normal file
@@ -0,0 +1,390 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
namespace PriFileFormat
|
||||
{
|
||||
public class ResourceMapSection: Section
|
||||
{
|
||||
public HierarchicalSchemaReference HierarchicalSchemaReference { get; private set; }
|
||||
public SectionRef<HierarchicalSchemaSection> SchemaSection { get; private set; }
|
||||
public SectionRef<DecisionInfoSection> DecisionInfoSection { get; private set; }
|
||||
public IReadOnlyDictionary <ushort, CandidateSet> CandidateSets { get; private set; }
|
||||
bool version2;
|
||||
internal const string Identifier1 = "[mrm_res_map__]\0";
|
||||
internal const string Identifier2 = "[mrm_res_map2_]\0";
|
||||
internal ResourceMapSection (PriFile priFile, bool version2) : base (version2 ? Identifier2 : Identifier1, priFile)
|
||||
{
|
||||
this.version2 = version2;
|
||||
}
|
||||
protected override bool ParseSectionContent (BinaryReader binaryReader)
|
||||
{
|
||||
long sectionPosition = (binaryReader.BaseStream as SubStream)?.SubStreamPosition ?? 0;
|
||||
|
||||
ushort environmentReferencesLength = binaryReader.ReadUInt16 ();
|
||||
ushort numEnvironmentReferences = binaryReader.ReadUInt16 ();
|
||||
if (!version2)
|
||||
{
|
||||
if (environmentReferencesLength == 0 || numEnvironmentReferences == 0)
|
||||
throw new InvalidDataException ();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (environmentReferencesLength != 0 || numEnvironmentReferences != 0)
|
||||
throw new InvalidDataException ();
|
||||
}
|
||||
SchemaSection = new SectionRef<HierarchicalSchemaSection> (binaryReader.ReadUInt16 ());
|
||||
ushort hierarchicalSchemaReferenceLength = binaryReader.ReadUInt16 ();
|
||||
DecisionInfoSection = new SectionRef<DecisionInfoSection> (binaryReader.ReadUInt16 ());
|
||||
ushort resourceValueTypeTableSize = binaryReader.ReadUInt16 ();
|
||||
ushort ItemToItemInfoGroupCount = binaryReader.ReadUInt16 ();
|
||||
ushort itemInfoGroupCount = binaryReader.ReadUInt16 ();
|
||||
uint itemInfoCount = binaryReader.ReadUInt32 ();
|
||||
uint numCandidates = binaryReader.ReadUInt32 ();
|
||||
uint dataLength = binaryReader.ReadUInt32 ();
|
||||
uint largeTableLength = binaryReader.ReadUInt32 ();
|
||||
|
||||
if (PriFile.GetSectionByRef (DecisionInfoSection) == null)
|
||||
return false;
|
||||
|
||||
byte [] environmentReferencesData = binaryReader.ReadBytes (environmentReferencesLength);
|
||||
|
||||
byte [] schemaReferenceData = binaryReader.ReadBytes (hierarchicalSchemaReferenceLength);
|
||||
|
||||
if (schemaReferenceData.Length != 0)
|
||||
using (BinaryReader r = new BinaryReader (new MemoryStream (schemaReferenceData, false)))
|
||||
{
|
||||
ushort majorVersion = r.ReadUInt16 ();
|
||||
ushort minorVersion = r.ReadUInt16 ();
|
||||
r.ExpectUInt32 (0);
|
||||
uint checksum = r.ReadUInt32 ();
|
||||
uint numScopes = r.ReadUInt32 ();
|
||||
uint numItems = r.ReadUInt32 ();
|
||||
|
||||
HierarchicalSchemaVersionInfo versionInfo = new HierarchicalSchemaVersionInfo (majorVersion, minorVersion, checksum, numScopes, numItems);
|
||||
|
||||
ushort stringDataLength = r.ReadUInt16 ();
|
||||
r.ExpectUInt16 (0);
|
||||
uint unknown1 = r.ReadUInt32 ();
|
||||
uint unknown2 = r.ReadUInt32 ();
|
||||
string uniqueName = r.ReadNullTerminatedString (Encoding.Unicode);
|
||||
|
||||
if (uniqueName.Length != stringDataLength - 1)
|
||||
throw new InvalidDataException ();
|
||||
|
||||
HierarchicalSchemaReference = new HierarchicalSchemaReference (versionInfo, unknown1, unknown2, uniqueName);
|
||||
}
|
||||
|
||||
List<ResourceValueType> resourceValueTypeTable = new List<ResourceValueType> (resourceValueTypeTableSize);
|
||||
for (int i = 0; i < resourceValueTypeTableSize; i++)
|
||||
{
|
||||
binaryReader.ExpectUInt32 (4);
|
||||
ResourceValueType resourceValueType = (ResourceValueType)binaryReader.ReadUInt32 ();
|
||||
resourceValueTypeTable.Add (resourceValueType);
|
||||
}
|
||||
|
||||
List<ItemToItemInfoGroup> itemToItemInfoGroups = new List<ItemToItemInfoGroup> ();
|
||||
for (int i = 0; i < ItemToItemInfoGroupCount; i++)
|
||||
{
|
||||
ushort firstItem = binaryReader.ReadUInt16 ();
|
||||
ushort itemInfoGroup = binaryReader.ReadUInt16 ();
|
||||
itemToItemInfoGroups.Add (new ItemToItemInfoGroup (firstItem, itemInfoGroup));
|
||||
}
|
||||
|
||||
List<ItemInfoGroup> itemInfoGroups = new List<ItemInfoGroup> ();
|
||||
for (int i = 0; i < itemInfoGroupCount; i++)
|
||||
{
|
||||
ushort groupSize = binaryReader.ReadUInt16 ();
|
||||
ushort firstItemInfo = binaryReader.ReadUInt16 ();
|
||||
itemInfoGroups.Add (new ItemInfoGroup (groupSize, firstItemInfo));
|
||||
}
|
||||
|
||||
List<ItemInfo> itemInfos = new List<ItemInfo> ();
|
||||
for (int i = 0; i < itemInfoCount; i++)
|
||||
{
|
||||
ushort decision = binaryReader.ReadUInt16 ();
|
||||
ushort firstCandidate = binaryReader.ReadUInt16 ();
|
||||
itemInfos.Add (new ItemInfo (decision, firstCandidate));
|
||||
}
|
||||
|
||||
byte [] largeTable = binaryReader.ReadBytes ((int)largeTableLength);
|
||||
|
||||
if (largeTable.Length != 0)
|
||||
using (BinaryReader r = new BinaryReader (new MemoryStream (largeTable, false)))
|
||||
{
|
||||
uint ItemToItemInfoGroupCountLarge = r.ReadUInt32 ();
|
||||
uint itemInfoGroupCountLarge = r.ReadUInt32 ();
|
||||
uint itemInfoCountLarge = r.ReadUInt32 ();
|
||||
|
||||
for (int i = 0; i < ItemToItemInfoGroupCountLarge; i++)
|
||||
{
|
||||
uint firstItem = r.ReadUInt32 ();
|
||||
uint itemInfoGroup = r.ReadUInt32 ();
|
||||
itemToItemInfoGroups.Add (new ItemToItemInfoGroup (firstItem, itemInfoGroup));
|
||||
}
|
||||
|
||||
for (int i = 0; i < itemInfoGroupCountLarge; i++)
|
||||
{
|
||||
uint groupSize = r.ReadUInt32 ();
|
||||
uint firstItemInfo = r.ReadUInt32 ();
|
||||
itemInfoGroups.Add (new ItemInfoGroup (groupSize, firstItemInfo));
|
||||
}
|
||||
|
||||
for (int i = 0; i < itemInfoCountLarge; i++)
|
||||
{
|
||||
uint decision = r.ReadUInt32 ();
|
||||
uint firstCandidate = r.ReadUInt32 ();
|
||||
itemInfos.Add (new ItemInfo (decision, firstCandidate));
|
||||
}
|
||||
|
||||
if (r.BaseStream.Position != r.BaseStream.Length)
|
||||
throw new InvalidDataException ();
|
||||
}
|
||||
|
||||
List<CandidateInfo> candidateInfos = new List<CandidateInfo> ((int)numCandidates);
|
||||
for (int i = 0; i < numCandidates; i++)
|
||||
{
|
||||
byte type = binaryReader.ReadByte ();
|
||||
|
||||
if (type == 0x01)
|
||||
{
|
||||
ResourceValueType resourceValueType = resourceValueTypeTable [binaryReader.ReadByte ()];
|
||||
ushort sourceFileIndex = binaryReader.ReadUInt16 ();
|
||||
ushort valueLocation = binaryReader.ReadUInt16 ();
|
||||
ushort dataItemSection = binaryReader.ReadUInt16 ();
|
||||
candidateInfos.Add (new CandidateInfo (resourceValueType, sourceFileIndex, valueLocation, dataItemSection));
|
||||
}
|
||||
else if (type == 0x00)
|
||||
{
|
||||
ResourceValueType resourceValueType = resourceValueTypeTable [binaryReader.ReadByte ()];
|
||||
ushort length = binaryReader.ReadUInt16 ();
|
||||
uint stringOffset = binaryReader.ReadUInt32 ();
|
||||
candidateInfos.Add (new CandidateInfo (resourceValueType, length, stringOffset));
|
||||
}
|
||||
else
|
||||
throw new InvalidDataException ();
|
||||
}
|
||||
|
||||
long stringDataStartOffset = binaryReader.BaseStream.Position;
|
||||
|
||||
Dictionary<ushort, CandidateSet> candidateSets = new Dictionary<ushort, CandidateSet> ();
|
||||
|
||||
for (int itemToItemInfoGroupIndex = 0; itemToItemInfoGroupIndex < itemToItemInfoGroups.Count; itemToItemInfoGroupIndex++)
|
||||
{
|
||||
ItemToItemInfoGroup itemToItemInfoGroup = itemToItemInfoGroups [itemToItemInfoGroupIndex];
|
||||
|
||||
ItemInfoGroup itemInfoGroup;
|
||||
|
||||
if (itemToItemInfoGroup.ItemInfoGroup < itemInfoGroups.Count)
|
||||
itemInfoGroup = itemInfoGroups [(int)itemToItemInfoGroup.ItemInfoGroup];
|
||||
else
|
||||
itemInfoGroup = new ItemInfoGroup (1, (uint)(itemToItemInfoGroup.ItemInfoGroup - itemInfoGroups.Count));
|
||||
|
||||
for (uint itemInfoIndex = itemInfoGroup.FirstItemInfo; itemInfoIndex < itemInfoGroup.FirstItemInfo + itemInfoGroup.GroupSize; itemInfoIndex++)
|
||||
{
|
||||
ItemInfo itemInfo = itemInfos [(int)itemInfoIndex];
|
||||
|
||||
ushort decisionIndex = (ushort)itemInfo.Decision;
|
||||
|
||||
Decision decision = PriFile.GetSectionByRef (DecisionInfoSection).Decisions [decisionIndex];
|
||||
|
||||
List<Candidate> candidates = new List<Candidate> (decision.QualifierSets.Count);
|
||||
|
||||
for (int i = 0; i < decision.QualifierSets.Count; i++)
|
||||
{
|
||||
CandidateInfo candidateInfo = candidateInfos [(int)itemInfo.FirstCandidate + i];
|
||||
|
||||
if (candidateInfo.Type == 0x01)
|
||||
{
|
||||
ReferencedFileRef? sourceFile;
|
||||
|
||||
if (candidateInfo.SourceFileIndex == 0)
|
||||
sourceFile = null;
|
||||
else
|
||||
sourceFile = new ReferencedFileRef (candidateInfo.SourceFileIndex - 1);
|
||||
|
||||
candidates.Add (new Candidate (decision.QualifierSets [i].Index, candidateInfo.ResourceValueType, sourceFile,
|
||||
new DataItemRef (new SectionRef<DataItemSection> (candidateInfo.DataItemSection), candidateInfo.DataItemIndex)));
|
||||
}
|
||||
else if (candidateInfo.Type == 0x00)
|
||||
{
|
||||
ByteSpan data = new ByteSpan (sectionPosition + stringDataStartOffset + candidateInfo.DataOffset, candidateInfo.DataLength);
|
||||
|
||||
candidates.Add (new Candidate (decision.QualifierSets [i].Index, candidateInfo.ResourceValueType, data));
|
||||
}
|
||||
}
|
||||
|
||||
ushort resourceMapItemIndex = (ushort)(itemToItemInfoGroup.FirstItem + (itemInfoIndex - itemInfoGroup.FirstItemInfo));
|
||||
|
||||
CandidateSet candidateSet = new CandidateSet (
|
||||
new ResourceMapItemRef (SchemaSection, resourceMapItemIndex),
|
||||
decisionIndex,
|
||||
candidates);
|
||||
|
||||
candidateSets.Add (resourceMapItemIndex, candidateSet);
|
||||
}
|
||||
}
|
||||
|
||||
CandidateSets = candidateSets;
|
||||
|
||||
return true;
|
||||
}
|
||||
private struct ItemToItemInfoGroup
|
||||
{
|
||||
public uint FirstItem;
|
||||
public uint ItemInfoGroup;
|
||||
public ItemToItemInfoGroup (uint firstItem, uint itemInfoGroup)
|
||||
{
|
||||
FirstItem = firstItem;
|
||||
ItemInfoGroup = itemInfoGroup;
|
||||
}
|
||||
}
|
||||
private struct ItemInfoGroup
|
||||
{
|
||||
public uint GroupSize;
|
||||
public uint FirstItemInfo;
|
||||
public ItemInfoGroup (uint groupSize, uint firstItemInfo)
|
||||
{
|
||||
GroupSize = groupSize;
|
||||
FirstItemInfo = firstItemInfo;
|
||||
}
|
||||
}
|
||||
private struct ItemInfo
|
||||
{
|
||||
public uint Decision;
|
||||
public uint FirstCandidate;
|
||||
|
||||
public ItemInfo (uint decision, uint firstCandidate)
|
||||
{
|
||||
Decision = decision;
|
||||
FirstCandidate = firstCandidate;
|
||||
}
|
||||
}
|
||||
private struct CandidateInfo
|
||||
{
|
||||
public byte Type;
|
||||
public ResourceValueType ResourceValueType;
|
||||
|
||||
// Type 1
|
||||
public ushort SourceFileIndex;
|
||||
public ushort DataItemIndex;
|
||||
public ushort DataItemSection;
|
||||
|
||||
// Type 0
|
||||
public ushort DataLength;
|
||||
public uint DataOffset;
|
||||
|
||||
public CandidateInfo (ResourceValueType resourceValueType, ushort sourceFileIndex, ushort dataItemIndex, ushort dataItemSection)
|
||||
{
|
||||
Type = 0x01;
|
||||
ResourceValueType = resourceValueType;
|
||||
SourceFileIndex = sourceFileIndex;
|
||||
DataItemIndex = dataItemIndex;
|
||||
DataItemSection = dataItemSection;
|
||||
DataLength = 0;
|
||||
DataOffset = 0;
|
||||
}
|
||||
|
||||
public CandidateInfo (ResourceValueType resourceValueType, ushort dataLength, uint dataOffset)
|
||||
{
|
||||
Type = 0x00;
|
||||
ResourceValueType = resourceValueType;
|
||||
SourceFileIndex = 0;
|
||||
DataItemIndex = 0;
|
||||
DataItemSection = 0;
|
||||
DataLength = dataLength;
|
||||
DataOffset = dataOffset;
|
||||
}
|
||||
}
|
||||
~ResourceMapSection ()
|
||||
{
|
||||
HierarchicalSchemaReference = null;
|
||||
CandidateSets = null;
|
||||
}
|
||||
}
|
||||
public enum ResourceValueType
|
||||
{
|
||||
String,
|
||||
Path,
|
||||
EmbeddedData,
|
||||
AsciiString,
|
||||
Utf8String,
|
||||
AsciiPath,
|
||||
Utf8Path
|
||||
}
|
||||
public class CandidateSet
|
||||
{
|
||||
public ResourceMapItemRef ResourceMapItem { get; }
|
||||
public ushort DecisionIndex { get; }
|
||||
public IReadOnlyList <Candidate> Candidates { get; private set; }
|
||||
internal CandidateSet (ResourceMapItemRef resourceMapItem, ushort decisionIndex, IReadOnlyList<Candidate> candidates)
|
||||
{
|
||||
ResourceMapItem = resourceMapItem;
|
||||
DecisionIndex = decisionIndex;
|
||||
Candidates = candidates;
|
||||
}
|
||||
~CandidateSet ()
|
||||
{
|
||||
Candidates = null;
|
||||
}
|
||||
}
|
||||
|
||||
public class Candidate
|
||||
{
|
||||
public ushort QualifierSet { get; }
|
||||
public ResourceValueType Type { get; }
|
||||
public ReferencedFileRef? SourceFile { get; private set; }
|
||||
public DataItemRef? DataItem { get; private set; }
|
||||
public ByteSpan? Data { get; private set; }
|
||||
internal Candidate (ushort qualifierSet, ResourceValueType type, ReferencedFileRef? sourceFile, DataItemRef dataItem)
|
||||
{
|
||||
QualifierSet = qualifierSet;
|
||||
Type = type;
|
||||
SourceFile = sourceFile;
|
||||
DataItem = dataItem;
|
||||
Data = null;
|
||||
}
|
||||
internal Candidate (ushort qualifierSet, ResourceValueType type, ByteSpan data)
|
||||
{
|
||||
QualifierSet = qualifierSet;
|
||||
Type = type;
|
||||
SourceFile = null;
|
||||
DataItem = null;
|
||||
Data = data;
|
||||
}
|
||||
~Candidate ()
|
||||
{
|
||||
SourceFile = null;
|
||||
DataItem = null;
|
||||
Data = null;
|
||||
}
|
||||
}
|
||||
public class HierarchicalSchemaReference
|
||||
{
|
||||
public HierarchicalSchemaVersionInfo VersionInfo { get; private set; }
|
||||
public uint Unknown1 { get; }
|
||||
public uint Unknown2 { get; }
|
||||
public string UniqueName { get; }
|
||||
internal HierarchicalSchemaReference (HierarchicalSchemaVersionInfo versionInfo, uint unknown1, uint unknown2, string uniqueName)
|
||||
{
|
||||
VersionInfo = versionInfo;
|
||||
Unknown1 = unknown1;
|
||||
Unknown2 = unknown2;
|
||||
UniqueName = uniqueName;
|
||||
}
|
||||
~HierarchicalSchemaReference ()
|
||||
{
|
||||
VersionInfo = null;
|
||||
}
|
||||
}
|
||||
public struct ResourceMapItemRef
|
||||
{
|
||||
internal SectionRef <HierarchicalSchemaSection> schemaSection;
|
||||
internal int itemIndex;
|
||||
internal ResourceMapItemRef (SectionRef<HierarchicalSchemaSection> schemaSection, int itemIndex)
|
||||
{
|
||||
this.schemaSection = schemaSection;
|
||||
this.itemIndex = itemIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
159
PriFileFormat/ReverseMapSection.cs
Normal file
159
PriFileFormat/ReverseMapSection.cs
Normal file
@@ -0,0 +1,159 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
namespace PriFileFormat
|
||||
{
|
||||
public class ReverseMapSection: Section
|
||||
{
|
||||
public uint [] Mapping { get; private set; }
|
||||
public IReadOnlyList<ResourceMapScope> Scopes { get; private set; }
|
||||
public IReadOnlyList<ResourceMapItem> Items { get; private set; }
|
||||
|
||||
internal const string Identifier = "[mrm_rev_map] \0";
|
||||
|
||||
internal ReverseMapSection (PriFile priFile) : base (Identifier, priFile)
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool ParseSectionContent (BinaryReader binaryReader)
|
||||
{
|
||||
uint numItems = binaryReader.ReadUInt32 ();
|
||||
binaryReader.ExpectUInt32 ((uint)(binaryReader.BaseStream.Length - 8));
|
||||
|
||||
uint [] mapping = new uint [numItems];
|
||||
for (int i = 0; i < numItems; i++)
|
||||
mapping [i] = binaryReader.ReadUInt32 ();
|
||||
Mapping = mapping;
|
||||
|
||||
ushort maxFullPathLength = binaryReader.ReadUInt16 ();
|
||||
binaryReader.ExpectUInt16 (0);
|
||||
uint numEntries = binaryReader.ReadUInt32 ();
|
||||
uint numScopes = binaryReader.ReadUInt32 ();
|
||||
binaryReader.ExpectUInt32 (numItems);
|
||||
uint unicodeDataLength = binaryReader.ReadUInt32 ();
|
||||
binaryReader.ReadUInt32 ();
|
||||
|
||||
List<Tuple<ushort, ushort, uint, uint, ushort>> scopeAndItemInfo = new List<Tuple<ushort, ushort, uint, uint, ushort>> ();
|
||||
|
||||
for (int i = 0; i < numScopes + numItems; i++)
|
||||
{
|
||||
ushort parent = binaryReader.ReadUInt16 ();
|
||||
ushort fullPathLength = binaryReader.ReadUInt16 ();
|
||||
uint hashCode = binaryReader.ReadUInt32 ();
|
||||
uint nameOffset = binaryReader.ReadUInt16 () | (((hashCode >> 24) & 0xF) << 16);
|
||||
ushort index = binaryReader.ReadUInt16 ();
|
||||
scopeAndItemInfo.Add (new Tuple<ushort, ushort, uint, uint, ushort> (parent, fullPathLength, hashCode, nameOffset, index));
|
||||
}
|
||||
|
||||
List<Tuple<ushort, ushort, ushort>> scopeExInfo = new List<Tuple<ushort, ushort, ushort>> ();
|
||||
|
||||
for (int i = 0; i < numScopes; i++)
|
||||
{
|
||||
ushort scopeIndex = binaryReader.ReadUInt16 ();
|
||||
ushort childCount = binaryReader.ReadUInt16 ();
|
||||
ushort firstChildIndex = binaryReader.ReadUInt16 ();
|
||||
binaryReader.ExpectUInt16 (0);
|
||||
scopeExInfo.Add (new Tuple<ushort, ushort, ushort> (scopeIndex, childCount, firstChildIndex));
|
||||
}
|
||||
|
||||
ushort [] itemIndexPropertyToIndex = new ushort [numItems];
|
||||
for (int i = 0; i < numItems; i++)
|
||||
{
|
||||
itemIndexPropertyToIndex [i] = binaryReader.ReadUInt16 ();
|
||||
}
|
||||
|
||||
long unicodeDataOffset = binaryReader.BaseStream.Position;
|
||||
long asciiDataOffset = binaryReader.BaseStream.Position + unicodeDataLength * 2;
|
||||
|
||||
ResourceMapScope [] scopes = new ResourceMapScope [numScopes];
|
||||
ResourceMapItem [] items = new ResourceMapItem [numItems];
|
||||
|
||||
for (int i = 0; i < numScopes + numItems; i++)
|
||||
{
|
||||
bool nameInAscii = (scopeAndItemInfo [i].Item3 & 0x20000000) != 0;
|
||||
long pos = (nameInAscii ? asciiDataOffset : unicodeDataOffset) + (scopeAndItemInfo [i].Item4 * (nameInAscii ? 1 : 2));
|
||||
|
||||
binaryReader.BaseStream.Seek (pos, SeekOrigin.Begin);
|
||||
|
||||
string name;
|
||||
|
||||
if (scopeAndItemInfo [i].Item2 != 0)
|
||||
name = binaryReader.ReadNullTerminatedString (nameInAscii ? Encoding.ASCII : Encoding.Unicode);
|
||||
else
|
||||
name = string.Empty;
|
||||
|
||||
ushort index = scopeAndItemInfo [i].Item5;
|
||||
|
||||
bool isScope = (scopeAndItemInfo [i].Item3 & 0x10000000) != 0;
|
||||
|
||||
if (isScope)
|
||||
{
|
||||
if (scopes [index] != null)
|
||||
throw new InvalidDataException ();
|
||||
|
||||
scopes [index] = new ResourceMapScope (index, null, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (items [index] != null)
|
||||
throw new InvalidDataException ();
|
||||
|
||||
items [index] = new ResourceMapItem (index, null, name);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < numScopes + numItems; i++)
|
||||
{
|
||||
ushort index = scopeAndItemInfo [i].Item5;
|
||||
|
||||
bool isScope = (scopeAndItemInfo [i].Item3 & 0x10000000) != 0;
|
||||
|
||||
ushort parent = scopeAndItemInfo [i].Item1;
|
||||
|
||||
parent = scopeAndItemInfo [parent].Item5;
|
||||
|
||||
if (parent != 0xFFFF)
|
||||
if (isScope)
|
||||
{
|
||||
if (parent != index)
|
||||
scopes [index].Parent = scopes [parent];
|
||||
}
|
||||
else
|
||||
items [index].Parent = scopes [parent];
|
||||
}
|
||||
|
||||
for (int i = 0; i < numScopes; i++)
|
||||
{
|
||||
ResourceMapEntry [] children = new ResourceMapEntry [scopeExInfo [i].Item2];
|
||||
|
||||
for (int j = 0; j < children.Length; j++)
|
||||
{
|
||||
var saiInfo = scopeAndItemInfo [scopeExInfo [i].Item3 + j];
|
||||
|
||||
bool isScope = (saiInfo.Item3 & 0x10000000) != 0;
|
||||
|
||||
if (isScope)
|
||||
children [j] = scopes [saiInfo.Item5];
|
||||
else
|
||||
children [j] = items [saiInfo.Item5];
|
||||
}
|
||||
|
||||
scopes [i].Children = children;
|
||||
}
|
||||
|
||||
Scopes = scopes;
|
||||
Items = items;
|
||||
|
||||
return true;
|
||||
}
|
||||
~ReverseMapSection ()
|
||||
{
|
||||
Mapping = null;
|
||||
Scopes = null;
|
||||
Items = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
89
PriFileFormat/Section.cs
Normal file
89
PriFileFormat/Section.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
namespace PriFileFormat
|
||||
{
|
||||
public abstract class Section
|
||||
{
|
||||
protected PriFile PriFile { get; private set; }
|
||||
public string SectionIdentifier { get; private set; }
|
||||
public uint SectionQualifier { get; private set; }
|
||||
public uint Flags { get; private set; }
|
||||
public uint SectionFlags { get; private set; }
|
||||
public uint SectionLength { get; private set; }
|
||||
|
||||
protected Section (string sectionIdentifier, PriFile priFile)
|
||||
{
|
||||
if (sectionIdentifier.Length != 16)
|
||||
throw new ArgumentException ("Section identifiers need to be exactly 16 characters long.", nameof (sectionIdentifier));
|
||||
|
||||
SectionIdentifier = sectionIdentifier;
|
||||
PriFile = priFile;
|
||||
}
|
||||
|
||||
internal bool Parse (BinaryReader binaryReader)
|
||||
{
|
||||
if (new string (binaryReader.ReadChars (16)) != SectionIdentifier)
|
||||
throw new InvalidDataException ("Unexpected section identifier.");
|
||||
|
||||
SectionQualifier = binaryReader.ReadUInt32 ();
|
||||
Flags = binaryReader.ReadUInt16 ();
|
||||
SectionFlags = binaryReader.ReadUInt16 ();
|
||||
SectionLength = binaryReader.ReadUInt32 ();
|
||||
binaryReader.ExpectUInt32 (0);
|
||||
|
||||
binaryReader.BaseStream.Seek (SectionLength - 16 - 24, SeekOrigin.Current);
|
||||
|
||||
binaryReader.ExpectUInt32 (0xDEF5FADE);
|
||||
binaryReader.ExpectUInt32 (SectionLength);
|
||||
|
||||
binaryReader.BaseStream.Seek (-8 - (SectionLength - 16 - 24), SeekOrigin.Current);
|
||||
|
||||
using (SubStream subStream = new SubStream (binaryReader.BaseStream, binaryReader.BaseStream.Position, (int)SectionLength - 16 - 24))
|
||||
using (BinaryReader subBinaryReader = new BinaryReader (subStream, Encoding.ASCII))
|
||||
{
|
||||
return ParseSectionContent (subBinaryReader);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract bool ParseSectionContent (BinaryReader binaryReader);
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
return $"{SectionIdentifier.TrimEnd ('\0', ' ')} length: {SectionLength}";
|
||||
}
|
||||
|
||||
internal static Section CreateForIdentifier (string sectionIdentifier, PriFile priFile)
|
||||
{
|
||||
switch (sectionIdentifier)
|
||||
{
|
||||
case PriDescriptorSection.Identifier:
|
||||
return new PriDescriptorSection (priFile);
|
||||
case HierarchicalSchemaSection.Identifier1:
|
||||
return new HierarchicalSchemaSection (priFile, false);
|
||||
case HierarchicalSchemaSection.Identifier2:
|
||||
return new HierarchicalSchemaSection (priFile, true);
|
||||
case DecisionInfoSection.Identifier:
|
||||
return new DecisionInfoSection (priFile);
|
||||
case ResourceMapSection.Identifier1:
|
||||
return new ResourceMapSection (priFile, false);
|
||||
case ResourceMapSection.Identifier2:
|
||||
return new ResourceMapSection (priFile, true);
|
||||
case DataItemSection.Identifier:
|
||||
return new DataItemSection (priFile);
|
||||
case ReverseMapSection.Identifier:
|
||||
return new ReverseMapSection (priFile);
|
||||
case ReferencedFileSection.Identifier:
|
||||
return new ReferencedFileSection (priFile);
|
||||
default:
|
||||
return new UnknownSection (sectionIdentifier, priFile);
|
||||
}
|
||||
}
|
||||
|
||||
~Section ()
|
||||
{
|
||||
PriFile = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
76
PriFileFormat/SubStream.cs
Normal file
76
PriFileFormat/SubStream.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
namespace PriFileFormat
|
||||
{
|
||||
public class SubStream: Stream
|
||||
{
|
||||
Stream baseStream;
|
||||
long subStreamPosition;
|
||||
long subStreamLength;
|
||||
|
||||
public SubStream (Stream baseStream, long subStreamPosition, long subStreamLength)
|
||||
{
|
||||
this.baseStream = baseStream;
|
||||
this.subStreamPosition = subStreamPosition;
|
||||
this.subStreamLength = subStreamLength;
|
||||
}
|
||||
|
||||
public long SubStreamPosition => subStreamPosition;
|
||||
|
||||
public override bool CanRead => baseStream.CanRead;
|
||||
|
||||
public override bool CanSeek => baseStream.CanSeek;
|
||||
|
||||
public override bool CanWrite => false;
|
||||
|
||||
public override long Length => subStreamLength;
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get { return baseStream.Position - subStreamPosition; }
|
||||
set { baseStream.Position = subStreamPosition + value; }
|
||||
}
|
||||
|
||||
public override void Flush ()
|
||||
{
|
||||
}
|
||||
|
||||
public override int Read (byte [] buffer, int offset, int count)
|
||||
{
|
||||
if (Position < 0)
|
||||
throw new InvalidOperationException ("Cannot read when position is negative.");
|
||||
if (Position + count > subStreamLength)
|
||||
count = (int)(subStreamLength - Position);
|
||||
|
||||
return baseStream.Read (buffer, offset, count);
|
||||
}
|
||||
|
||||
public override long Seek (long offset, SeekOrigin origin)
|
||||
{
|
||||
switch (origin)
|
||||
{
|
||||
case SeekOrigin.Begin:
|
||||
return baseStream.Seek (subStreamPosition + offset, SeekOrigin.Begin) - subStreamPosition;
|
||||
case SeekOrigin.Current:
|
||||
return baseStream.Seek (offset, SeekOrigin.Current) - subStreamPosition;
|
||||
case SeekOrigin.End:
|
||||
return baseStream.Seek (subStreamPosition + subStreamLength + offset, SeekOrigin.Begin) - subStreamPosition;
|
||||
default:
|
||||
throw new ArgumentException ("Invalid origin.", nameof (origin));
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetLength (long value)
|
||||
{
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
|
||||
public override void Write (byte [] buffer, int offset, int count)
|
||||
{
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
|
||||
~SubStream () { baseStream = null; }
|
||||
}
|
||||
}
|
||||
37
PriFileFormat/TocEntry.cs
Normal file
37
PriFileFormat/TocEntry.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
namespace PriFileFormat
|
||||
{
|
||||
public class TocEntry
|
||||
{
|
||||
public string SectionIdentifier { get; }
|
||||
public ushort Flags { get; }
|
||||
public ushort SectionFlags { get; }
|
||||
public uint SectionQualifier { get; }
|
||||
public uint SectionOffset { get; }
|
||||
public uint SectionLength { get; }
|
||||
private TocEntry (string sectionIdentifier, ushort flags, ushort sectionFlags, uint sectionQualifier, uint sectionOffset, uint sectionLength)
|
||||
{
|
||||
SectionIdentifier = sectionIdentifier;
|
||||
Flags = flags;
|
||||
SectionFlags = sectionFlags;
|
||||
SectionQualifier = sectionQualifier;
|
||||
SectionOffset = sectionOffset;
|
||||
SectionLength = sectionLength;
|
||||
}
|
||||
internal static TocEntry Parse (BinaryReader binaryReader)
|
||||
{
|
||||
return new TocEntry (
|
||||
new string (binaryReader.ReadChars (16)),
|
||||
binaryReader.ReadUInt16 (),
|
||||
binaryReader.ReadUInt16 (),
|
||||
binaryReader.ReadUInt32 (),
|
||||
binaryReader.ReadUInt32 (),
|
||||
binaryReader.ReadUInt32 ());
|
||||
}
|
||||
public override string ToString ()
|
||||
{
|
||||
return $"{SectionIdentifier.TrimEnd ('\0', ' ')} length: {SectionLength}";
|
||||
}
|
||||
}
|
||||
}
|
||||
23
PriFileFormat/UnknownSection.cs
Normal file
23
PriFileFormat/UnknownSection.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
namespace PriFileFormat
|
||||
{
|
||||
public class UnknownSection: Section
|
||||
{
|
||||
public byte [] SectionContent { get; private set; }
|
||||
internal UnknownSection (string sectionIdentifier, PriFile priFile) : base (sectionIdentifier, priFile) {}
|
||||
protected override bool ParseSectionContent (BinaryReader binaryReader)
|
||||
{
|
||||
int contentLength = (int)(binaryReader.BaseStream.Length - binaryReader.BaseStream.Position);
|
||||
|
||||
SectionContent = binaryReader.ReadBytes (contentLength);
|
||||
|
||||
return true;
|
||||
}
|
||||
public void ClearContent ()
|
||||
{
|
||||
SectionContent = null;
|
||||
}
|
||||
~UnknownSection () { ClearContent (); }
|
||||
}
|
||||
}
|
||||
3
PriFileFormat/app.config
Normal file
3
PriFileFormat/app.config
Normal file
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
</configuration>
|
||||
Binary file not shown.
@@ -84,15 +84,15 @@
|
||||
<ClInclude Include="..\pkgread\pkgread.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\priformatcli\priformatcli.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="localeex.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="bridge.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\priformatcli\priformatcli.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp">
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
#include "strcode.h"
|
||||
#include "nstring.h"
|
||||
#include "typestrans.h"
|
||||
#ifdef _cplusplus_cli
|
||||
#include "mpstr.h"
|
||||
#endif
|
||||
|
||||
template <typename T> std::wstring TypeToString (T value, const std::wstring &reserve = L"") { return std::to_wstring (value); }
|
||||
template <typename T> std::string TypeToString (T value, const std::string &reserve = "") { return std::to_string (value); }
|
||||
@@ -236,6 +239,8 @@ class initkey
|
||||
bool write_string (pcstring value) { return write (value); }
|
||||
bool write (pcwstring value) { return WritePrivateProfileStringW (filepath, section, key, value); }
|
||||
bool write (pcstring value) { return write (StringToWString (value)); }
|
||||
bool write (LPCWSTR value) { return write_string (std::wstring (value ? value : L"")); }
|
||||
bool write (LPCSTR value) { return write_string (value ? value : ""); }
|
||||
bool write (int value) { return write_t (value); }
|
||||
bool write (unsigned int value) { return write_t (value); }
|
||||
bool write (short value) { return write_t (value); }
|
||||
@@ -351,6 +356,8 @@ class initsection
|
||||
template <typename T> bool read_struct (const std::wstring &key, T &structinst) const { return read_struct (key, &structinst, sizeof (structinst)); }
|
||||
bool write_string (const std::wstring &key, const std::wstring &value) { return WritePrivateProfileStringW (filepath, section, key, value); }
|
||||
bool write_string (const std::string &key, const std::string &value) { return write_string (StringToWString (key), StringToWString (value)); }
|
||||
bool write (pcwstring key, LPCWSTR value) { return write_string (key, value ? value : L""); }
|
||||
bool write (pcstring key, LPCSTR value) { return write_string (key, value ? value : ""); }
|
||||
bool write (const std::wstring &key, const std::wstring &value) { return write_string (key, value); }
|
||||
bool write (const std::string &key, const std::string &value) { return write_string (key, value); }
|
||||
bool write (pcwstring key, short value) { return write_t (key, value); }
|
||||
@@ -474,6 +481,8 @@ bool write (INIT_WRITE_WARGS (_type_)) { return write_t (section, key, value); }
|
||||
bool write (INIT_WRITE_WARGS (bool)) { return write (section, key, value ? L"true" : L"false"); }
|
||||
bool write (INIT_WRITE_WARGS (int8_t)) { return write_t (section, key, (int16_t)value); }
|
||||
bool write (INIT_WRITE_WARGS (uint8_t)) { return write_t (section, key, (uint16_t)value); }
|
||||
bool write (pcwstring section, pcwstring key, LPCWSTR value) { return write (section, key, std::wstring (value ? value : L"")); }
|
||||
bool write (pcstring section, pcstring key, LPCSTR value) { return write (StringToWString (section), StringToWString (key), StringToWString (value)); }
|
||||
bool write (pcwstring section, pcwstring key, void *buf, size_t bufsize) { return WritePrivateProfileStructW (filepath, section, key, buf, bufsize); }
|
||||
initsection operator [] (pcwstring section) { return initsection (filepath, section); }
|
||||
initsection operator [] (pcstring section) { return initsection (filepath, StringToWString (section)); }
|
||||
|
||||
@@ -1 +1 @@
|
||||
E:/Profiles/Bruce/Documents/Visual Studio 2015/Projects/AppInstallerReset/priformatcli/priformatcli.h
|
||||
../priformatcli/priformatcli.h
|
||||
Binary file not shown.
170
desktopini/desktopini.vcxproj
Normal file
170
desktopini/desktopini.vcxproj
Normal file
@@ -0,0 +1,170 @@
|
||||
<?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>{7A05E943-6E0A-4F57-8BD7-BE90F44DCAD7}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>desktopini</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</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>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
|
||||
<AdditionalDependencies>shlwapi.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
|
||||
<AdditionalDependencies>shlwapi.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="filepath.h" />
|
||||
<ClInclude Include="initfile.h" />
|
||||
<ClInclude Include="module.h" />
|
||||
<ClInclude Include="nstring.h" />
|
||||
<ClInclude Include="raii.h" />
|
||||
<ClInclude Include="strcmp.h" />
|
||||
<ClInclude Include="strcode.h" />
|
||||
<ClInclude Include="syncutil.h" />
|
||||
<ClInclude Include="typestrans.h" />
|
||||
<ClInclude Include="version.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
54
desktopini/desktopini.vcxproj.filters
Normal file
54
desktopini/desktopini.vcxproj.filters
Normal file
@@ -0,0 +1,54 @@
|
||||
<?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>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="filepath.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="initfile.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="module.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="nstring.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="raii.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="strcmp.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="strcode.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="syncutil.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="typestrans.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="version.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
871
desktopini/filepath.h
Normal file
871
desktopini/filepath.h
Normal file
@@ -0,0 +1,871 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <shlwapi.h>
|
||||
#include <vector>
|
||||
#include <iomanip>
|
||||
#include <functional>
|
||||
#include <sstream>
|
||||
#include "strcmp.h"
|
||||
#include "version.h"
|
||||
#include "module.h"
|
||||
typedef version S_VERSION;
|
||||
template <typename T> constexpr T Max (T l, T r) { return l > r ? l : r; }
|
||||
template <typename T> constexpr T Max (T l, T m, T r) { return Max (Max (l, r), m); }
|
||||
template <typename T> constexpr T Max (T l, T ml, T mr, T r) { return Max (Max (l, ml), Max (mr, r)); }
|
||||
template <typename CharT> std::basic_string <CharT> replace_substring
|
||||
(
|
||||
const std::basic_string <CharT> &str,
|
||||
const std::basic_string <CharT> &from,
|
||||
const std::basic_string <CharT> &to
|
||||
)
|
||||
{
|
||||
if (from.empty ()) return str;
|
||||
std::basic_string <CharT> result;
|
||||
size_t pos = 0;
|
||||
size_t start_pos;
|
||||
while ((start_pos = str.find (from, pos)) != std::basic_string<CharT>::npos)
|
||||
{
|
||||
result.append (str, pos, start_pos - pos);
|
||||
result.append (to);
|
||||
pos = start_pos + from.length ();
|
||||
}
|
||||
result.append (str, pos, str.length () - pos);
|
||||
return result;
|
||||
}
|
||||
std::string GetProgramRootDirectoryA (HMODULE hModule hModule_DefaultParam)
|
||||
{
|
||||
char path [MAX_PATH];
|
||||
if (GetModuleFileNameA (hModule, path, MAX_PATH))
|
||||
{
|
||||
std::string dir (path);
|
||||
size_t pos = dir.find_last_of ("\\/");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
dir = dir.substr (0, pos);
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
std::wstring GetProgramRootDirectoryW (HMODULE hModule hModule_DefaultParam)
|
||||
{
|
||||
wchar_t path [MAX_PATH];
|
||||
if (GetModuleFileNameW (hModule, path, MAX_PATH))
|
||||
{
|
||||
std::wstring dir (path);
|
||||
size_t pos = dir.find_last_of (L"\\/");
|
||||
if (pos != std::wstring::npos)
|
||||
{
|
||||
dir = dir.substr (0, pos);
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
return L"";
|
||||
}
|
||||
std::string EnsureTrailingSlash (const std::string &path)
|
||||
{
|
||||
if (path.empty ()) return path; // 空路径直接返回
|
||||
|
||||
char lastChar = path.back ();
|
||||
if (lastChar == '\\' || lastChar == '/')
|
||||
return path; // 已有分隔符,直接返回
|
||||
// 根据系统或原路径格式添加适当的分隔符
|
||||
char separator = (path.find ('/') != std::string::npos) ? '/' : '\\';
|
||||
return path + separator;
|
||||
}
|
||||
std::wstring EnsureTrailingSlash (const std::wstring &path)
|
||||
{
|
||||
if (path.empty ()) return path;
|
||||
|
||||
wchar_t lastChar = path.back ();
|
||||
if (lastChar == L'\\' || lastChar == L'/')
|
||||
return path;
|
||||
|
||||
wchar_t separator = (path.find (L'/') != std::wstring::npos) ? L'/' : L'\\';
|
||||
return path + separator;
|
||||
}
|
||||
bool IsFileExistsW (LPCWSTR filename)
|
||||
{
|
||||
DWORD dwAttrib = GetFileAttributesW (filename);
|
||||
return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
|
||||
}
|
||||
bool IsFileExistsA (LPCSTR filename)
|
||||
{
|
||||
DWORD dwAttrib = GetFileAttributesA (filename);
|
||||
return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
|
||||
}
|
||||
bool IsFileExists (LPWSTR filePath) { return IsFileExistsW (filePath); }
|
||||
bool IsFileExists (LPCSTR filePath) { return IsFileExistsA (filePath); }
|
||||
bool IsFileExists (const std::string &filePath) { return IsFileExistsA (filePath.c_str ()); }
|
||||
bool IsFileExists (const std::wstring &filePath) { return IsFileExistsW (filePath.c_str ()); }
|
||||
bool IsDirectoryExistsA (LPCSTR path)
|
||||
{
|
||||
DWORD attributes = GetFileAttributesA (path);
|
||||
return (attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY));
|
||||
}
|
||||
bool IsDirectoryExistsW (LPCWSTR path)
|
||||
{
|
||||
DWORD attributes = GetFileAttributesW (path);
|
||||
return (attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY));
|
||||
}
|
||||
bool IsDirectoryExists (const std::string &path) { return IsDirectoryExistsA (path.c_str ()); }
|
||||
bool IsDirectoryExists (const std::wstring &path) { return IsDirectoryExistsW (path.c_str ()); }
|
||||
bool IsDirectoryExists (LPCSTR path) { return IsDirectoryExistsA (path); }
|
||||
bool IsDirectoryExists (LPCWSTR path) { return IsDirectoryExistsW (path); }
|
||||
bool IsPathExistsW (LPCWSTR filename)
|
||||
{
|
||||
DWORD dwAttrib = GetFileAttributesW (filename);
|
||||
return (dwAttrib != INVALID_FILE_ATTRIBUTES);
|
||||
}
|
||||
bool IsPathExistsA (LPCSTR filename)
|
||||
{
|
||||
DWORD dwAttrib = GetFileAttributesA (filename);
|
||||
return (dwAttrib != INVALID_FILE_ATTRIBUTES);
|
||||
}
|
||||
bool IsPathExists (const std::string &path) { return IsPathExistsA (path.c_str ()); }
|
||||
bool IsPathExists (const std::wstring &path) { return IsPathExistsW (path.c_str ()); }
|
||||
bool IsPathExists (LPCSTR path) { return IsPathExistsA (path); }
|
||||
bool IsPathExists (LPCWSTR path) { return IsPathExistsW (path); }
|
||||
std::string NormalizePath (const std::string &path)
|
||||
{
|
||||
if (!path.empty () && path.back () == '\\')
|
||||
return path.substr (0, path.size () - 1);
|
||||
return path.c_str ();
|
||||
}
|
||||
std::wstring NormalizePath (const std::wstring &path)
|
||||
{
|
||||
if (!path.empty () && path.back () == L'\\')
|
||||
return path.substr (0, path.size () - 1);
|
||||
return path.c_str ();
|
||||
}
|
||||
std::vector <std::string> EnumSubdirectories (const std::string &directory, bool includeParentPath)
|
||||
{
|
||||
std::vector<std::string> subdirs;
|
||||
std::string normPath = NormalizePath (directory);
|
||||
std::string searchPath = normPath + "\\*";
|
||||
WIN32_FIND_DATAA findData;
|
||||
HANDLE hFind = FindFirstFileA (searchPath.c_str (), &findData);
|
||||
if (hFind == INVALID_HANDLE_VALUE) return subdirs;
|
||||
do
|
||||
{
|
||||
// 过滤 "." 和 ".."
|
||||
if (strcmp (findData.cFileName, ".") == 0 || strcmp (findData.cFileName, "..") == 0)
|
||||
continue;
|
||||
// 判断是否为目录
|
||||
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
if (includeParentPath)
|
||||
subdirs.push_back (normPath + "\\" + findData.cFileName);
|
||||
else
|
||||
subdirs.push_back (findData.cFileName);
|
||||
}
|
||||
} while (FindNextFileA (hFind, &findData));
|
||||
FindClose (hFind);
|
||||
return subdirs;
|
||||
}
|
||||
std::vector <std::wstring> EnumSubdirectories (const std::wstring &directory, bool includeParentPath)
|
||||
{
|
||||
std::vector<std::wstring> subdirs;
|
||||
std::wstring normPath = NormalizePath (directory);
|
||||
std::wstring searchPath = normPath + L"\\*";
|
||||
WIN32_FIND_DATAW findData;
|
||||
HANDLE hFind = FindFirstFileW (searchPath.c_str (), &findData);
|
||||
if (hFind == INVALID_HANDLE_VALUE) return subdirs;
|
||||
do
|
||||
{
|
||||
if (wcscmp (findData.cFileName, L".") == 0 || wcscmp (findData.cFileName, L"..") == 0)
|
||||
continue;
|
||||
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
if (includeParentPath)
|
||||
subdirs.push_back (normPath + L"\\" + findData.cFileName);
|
||||
else
|
||||
subdirs.push_back (findData.cFileName);
|
||||
}
|
||||
} while (FindNextFileW (hFind, &findData));
|
||||
FindClose (hFind);
|
||||
return subdirs;
|
||||
}
|
||||
std::string GetCurrentProgramPathA (HMODULE hModule hModule_DefaultParam)
|
||||
{
|
||||
std::vector <CHAR> buf (Max <size_t> (MAX_PATH, GetModuleFileNameA (hModule, nullptr, 0)) + 1);
|
||||
GetModuleFileNameA (hModule, buf.data (), buf.capacity ());
|
||||
return buf.data ();
|
||||
}
|
||||
std::wstring GetCurrentProgramPathW (HMODULE hModule hModule_DefaultParam)
|
||||
{
|
||||
std::vector <WCHAR> buf (Max <size_t> (MAX_PATH, GetModuleFileNameW (hModule, nullptr, 0)) + 1);
|
||||
GetModuleFileNameW (hModule, buf.data (), buf.capacity ());
|
||||
return buf.data ();
|
||||
}
|
||||
std::string GetCurrentProgramNameA (HMODULE hModule hModule_DefaultParam) { return PathFindFileNameA (GetCurrentProgramPathA (hModule).c_str ()); }
|
||||
std::wstring GetCurrentProgramNameW (HMODULE hModule hModule_DefaultParam) { return PathFindFileNameW (GetCurrentProgramPathW (hModule).c_str ()); }
|
||||
S_VERSION GetExeFileVersion (LPCSTR lpszFilePath)
|
||||
{
|
||||
S_VERSION ver (0);
|
||||
DWORD dummy;
|
||||
DWORD size = GetFileVersionInfoSizeA (lpszFilePath, &dummy);
|
||||
std::vector <BYTE> pVersionInfo (size);
|
||||
if (!GetFileVersionInfoA (lpszFilePath, 0, size, pVersionInfo.data ()))
|
||||
{
|
||||
return ver;
|
||||
}
|
||||
VS_FIXEDFILEINFO* pFileInfo = nullptr;
|
||||
UINT len = 0;
|
||||
if (!VerQueryValueA (pVersionInfo.data (), "\\", (LPVOID *)&pFileInfo, &len))
|
||||
{
|
||||
return ver;
|
||||
}
|
||||
if (len == 0 || pFileInfo == nullptr)
|
||||
{
|
||||
return ver;
|
||||
}
|
||||
ver = S_VERSION (
|
||||
HIWORD (pFileInfo->dwFileVersionMS),
|
||||
LOWORD (pFileInfo->dwFileVersionMS),
|
||||
HIWORD (pFileInfo->dwFileVersionLS),
|
||||
LOWORD (pFileInfo->dwFileVersionLS)
|
||||
);
|
||||
return ver;
|
||||
}
|
||||
S_VERSION GetExeFileVersion (LPCWSTR lpswFilePath)
|
||||
{
|
||||
S_VERSION ver (0);
|
||||
DWORD dummy;
|
||||
DWORD size = GetFileVersionInfoSizeW (lpswFilePath, &dummy);
|
||||
std::vector <BYTE> pVersionInfo (size);
|
||||
if (!GetFileVersionInfoW (lpswFilePath, 0, size, pVersionInfo.data ()))
|
||||
{
|
||||
return ver;
|
||||
}
|
||||
VS_FIXEDFILEINFO* pFileInfo = nullptr;
|
||||
UINT len = 0;
|
||||
if (!VerQueryValueA (pVersionInfo.data (), "\\", (LPVOID *)&pFileInfo, &len))
|
||||
{
|
||||
return ver;
|
||||
}
|
||||
if (len == 0 || pFileInfo == nullptr)
|
||||
{
|
||||
return ver;
|
||||
}
|
||||
ver = S_VERSION (
|
||||
HIWORD (pFileInfo->dwFileVersionMS),
|
||||
LOWORD (pFileInfo->dwFileVersionMS),
|
||||
HIWORD (pFileInfo->dwFileVersionLS),
|
||||
LOWORD (pFileInfo->dwFileVersionLS)
|
||||
);
|
||||
return ver;
|
||||
}
|
||||
S_VERSION GetExeFileVersion (std::wstring objswFilePath)
|
||||
{
|
||||
return GetExeFileVersion (objswFilePath.c_str ());
|
||||
}
|
||||
S_VERSION GetExeFileVersion (std::string objszFilePath)
|
||||
{
|
||||
return GetExeFileVersion (objszFilePath.c_str ());
|
||||
}
|
||||
// 设置当前进程的环境变量RunPath和ProgramPath
|
||||
void SetupInstanceEnvironment (HMODULE hModule hModule_DefaultParam)
|
||||
{
|
||||
// 设置RunPath为当前工作目录(无结尾反斜杠)
|
||||
std::vector <WCHAR> currentDir (Max <size_t> (GetCurrentDirectoryW (0, nullptr), MAX_PATH) + 1);
|
||||
DWORD len = GetCurrentDirectoryW (currentDir.capacity (), currentDir.data ());
|
||||
if (len > 0)
|
||||
{
|
||||
std::wstring runPath (currentDir.data ());
|
||||
if (!runPath.empty () && (runPath.back () == L'\\' || runPath.back () == L'/'))
|
||||
{
|
||||
runPath.pop_back ();
|
||||
}
|
||||
SetEnvironmentVariableW (L"RunPath", runPath.c_str ());
|
||||
}
|
||||
// 设置ProgramPath为程序所在目录(无结尾反斜杠)
|
||||
std::vector <WCHAR> modulePath (Max <size_t> (GetModuleFileNameW (hModule, nullptr, 0), MAX_PATH) + 1);
|
||||
len = GetModuleFileNameW (hModule, modulePath.data (), MAX_PATH);
|
||||
if (len > 0 && len < MAX_PATH)
|
||||
{
|
||||
wchar_t* lastSlash = wcsrchr (modulePath.data (), L'\\');
|
||||
if (!lastSlash) lastSlash = wcsrchr (modulePath.data (), L'/');
|
||||
if (lastSlash) *lastSlash = L'\0';
|
||||
std::wstring programPath (modulePath.data ());
|
||||
if (!programPath.empty () && (programPath.back () == L'\\' || programPath.back () == L'/'))
|
||||
{
|
||||
programPath.pop_back ();
|
||||
}
|
||||
SetEnvironmentVariableW (L"ProgramPath", programPath.c_str ());
|
||||
}
|
||||
}
|
||||
// 处理宽字符串环境变量展开
|
||||
std::wstring ProcessEnvVars (const std::wstring &input)
|
||||
{
|
||||
DWORD requiredSize = ExpandEnvironmentStringsW (input.c_str (), nullptr, 0);
|
||||
if (requiredSize == 0) return input;
|
||||
std::wstring buffer (requiredSize, L'\0');
|
||||
if (!ExpandEnvironmentStringsW (input.c_str (), &buffer [0], requiredSize))
|
||||
{
|
||||
return input;
|
||||
}
|
||||
buffer.resize (requiredSize - 1); // 去除终止空字符
|
||||
return buffer.c_str ();
|
||||
}
|
||||
std::wstring ProcessEnvVars (LPCWSTR input)
|
||||
{
|
||||
return ProcessEnvVars (std::wstring (input));
|
||||
}
|
||||
// 处理ANSI字符串环境变量展开
|
||||
std::string ProcessEnvVars (const std::string &input)
|
||||
{
|
||||
DWORD requiredSize = ExpandEnvironmentStringsA (input.c_str (), nullptr, 0);
|
||||
if (requiredSize == 0) return input;
|
||||
std::string buffer (requiredSize, '\0');
|
||||
if (!ExpandEnvironmentStringsA (input.c_str (), &buffer [0], requiredSize))
|
||||
{
|
||||
return input;
|
||||
}
|
||||
buffer.resize (requiredSize - 1); // 去除终止空字符
|
||||
return buffer.c_str ();
|
||||
}
|
||||
std::string ProcessEnvVars (LPCSTR input)
|
||||
{
|
||||
return ProcessEnvVars (std::string (input));
|
||||
}
|
||||
std::string GetCurrentDirectoryA ()
|
||||
{
|
||||
std::vector <CHAR> buf (Max <size_t> (GetCurrentDirectoryA (0, nullptr), MAX_PATH) + 1);
|
||||
GetCurrentDirectoryA (buf.size (), buf.data ());
|
||||
return buf.data ();
|
||||
}
|
||||
std::wstring GetCurrentDirectoryW ()
|
||||
{
|
||||
std::vector <WCHAR> buf (Max <size_t> (GetCurrentDirectoryW (0, nullptr), MAX_PATH) + 1);
|
||||
GetCurrentDirectoryW (buf.size (), buf.data ());
|
||||
return buf.data ();
|
||||
}
|
||||
std::wstring GetFileDirectoryW (const std::wstring &filePath)
|
||||
{
|
||||
std::vector <WCHAR> buf (filePath.capacity () + 1);
|
||||
lstrcpyW (buf.data (), filePath.c_str ());
|
||||
PathRemoveFileSpecW (buf.data ());
|
||||
return buf.data ();
|
||||
}
|
||||
std::string GetFileDirectoryA (const std::string &filePath)
|
||||
{
|
||||
std::vector <CHAR> buf (filePath.capacity () + 1);
|
||||
lstrcpyA (buf.data (), filePath.c_str ());
|
||||
PathRemoveFileSpecA (buf.data ());
|
||||
return buf.data ();
|
||||
}
|
||||
size_t EnumerateFilesW (const std::wstring &directory, const std::wstring &filter,
|
||||
std::vector <std::wstring> &outFiles, bool recursive = false)
|
||||
{
|
||||
std::wstring searchPath = directory;
|
||||
if (!searchPath.empty () && searchPath.back () != L'\\')
|
||||
{
|
||||
searchPath += L'\\';
|
||||
}
|
||||
searchPath += filter;
|
||||
WIN32_FIND_DATAW findData;
|
||||
HANDLE hFind = FindFirstFileW (searchPath.c_str (), &findData);
|
||||
if (hFind != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
do {
|
||||
if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
||||
{
|
||||
outFiles.push_back (directory + L"\\" + findData.cFileName);
|
||||
}
|
||||
} while (FindNextFileW (hFind, &findData));
|
||||
FindClose (hFind);
|
||||
}
|
||||
if (recursive) {
|
||||
std::wstring subDirSearchPath = directory + L"\\*";
|
||||
hFind = FindFirstFileW (subDirSearchPath.c_str (), &findData);
|
||||
if (hFind != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
do {
|
||||
if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
|
||||
wcscmp (findData.cFileName, L".") != 0 && wcscmp (findData.cFileName, L"..") != 0)
|
||||
{
|
||||
EnumerateFilesW (directory + L"\\" + findData.cFileName, filter, outFiles, true);
|
||||
}
|
||||
} while (FindNextFileW (hFind, &findData));
|
||||
FindClose (hFind);
|
||||
}
|
||||
}
|
||||
return outFiles.size ();
|
||||
}
|
||||
// 检查是否为 Windows 设备名(大小写不敏感)
|
||||
bool IsReservedName (const std::wstring &name)
|
||||
{
|
||||
static const wchar_t* reserved [] = {
|
||||
L"CON", L"PRN", L"AUX", L"NUL", L"COM1", L"COM2", L"COM3", L"COM4", L"COM5", L"COM6", L"COM7", L"COM8", L"COM9",
|
||||
L"LPT1", L"LPT2", L"LPT3", L"LPT4", L"LPT5", L"LPT6", L"LPT7", L"LPT8", L"LPT9"
|
||||
};
|
||||
std::wstring upperName = StringToUpper (name);
|
||||
for (const auto& res : reserved)
|
||||
{
|
||||
if (upperName == res || (upperName.rfind (res, 0) == 0 && upperName.length () > wcslen (res) && upperName [wcslen (res)] == L'.'))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// Windows 文件命名规范检查 (Unicode)
|
||||
bool IsValidWindowsNameW (LPCWSTR name)
|
||||
{
|
||||
if (!name || !*name) return false;
|
||||
std::wstring wname (name);
|
||||
if (wname.find_first_of (L"<>:\"/\\|?*") != std::wstring::npos) return false;
|
||||
if (IsReservedName (wname)) return false;
|
||||
if (wname.back () == L' ' || wname.back () == L'.') return false;
|
||||
return true;
|
||||
}
|
||||
// Windows 文件命名规范检查 (ANSI)
|
||||
bool IsValidWindowsNameA (LPCSTR name)
|
||||
{
|
||||
if (!name || !*name) return false;
|
||||
std::string str (name);
|
||||
if (str.find_first_of ("<>:\"/\\|?*") != std::string::npos) return false;
|
||||
|
||||
// 转换 ANSI 到宽字符
|
||||
int len = MultiByteToWideChar (CP_ACP, 0, name, -1, NULL, 0);
|
||||
if (len <= 0) return false;
|
||||
std::wstring wname (len - 1, L'\0');
|
||||
MultiByteToWideChar (CP_ACP, 0, name, -1, &wname [0], len);
|
||||
if (IsReservedName (wname)) return false;
|
||||
if (str.back () == ' ' || str.back () == '.') return false;
|
||||
return true;
|
||||
}
|
||||
bool IsValidWindowsName (LPCSTR name) { return IsValidWindowsNameA (name); }
|
||||
bool IsValidWindowsName (LPCWSTR name) { return IsValidWindowsNameW (name); }
|
||||
bool IsValidWindowsName (const std::wstring &name) { return IsValidWindowsName (name.c_str ()); }
|
||||
bool IsValidWindowsName (const std::string &name) { return IsValidWindowsName (name.c_str ()); }
|
||||
std::wstring GetRootFolderNameFromFilePath (const std::wstring &lpFilePath)
|
||||
{
|
||||
std::vector <WCHAR> szPath (Max <size_t> (lpFilePath.length (), MAX_PATH) + 1);
|
||||
if (!PathCanonicalizeW (szPath.data (), lpFilePath.c_str ())) return L"";
|
||||
if (PathRemoveFileSpecW (szPath.data ()) == FALSE) return L"";
|
||||
LPCWSTR pszFolder = PathFindFileNameW (szPath.data ());
|
||||
if (*pszFolder != L'\0') return std::wstring (pszFolder);
|
||||
WCHAR rootName [3] = {szPath [0], L':', L'\0'};
|
||||
return std::wstring (rootName);
|
||||
}
|
||||
std::wstring GetSafeTimestampForFilename ()
|
||||
{
|
||||
::FILETIME ft;
|
||||
GetSystemTimeAsFileTime (&ft);
|
||||
SYSTEMTIME st;
|
||||
FileTimeToSystemTime (&ft, &st);
|
||||
std::wstringstream wss;
|
||||
wss << std::setfill (L'0')
|
||||
<< st.wYear
|
||||
<< std::setw (2) << st.wMonth
|
||||
<< std::setw (2) << st.wDay << L"_"
|
||||
<< std::setw (2) << st.wHour
|
||||
<< std::setw (2) << st.wMinute
|
||||
<< std::setw (2) << st.wSecond
|
||||
<< std::setw (3) << st.wMilliseconds;
|
||||
return wss.str ();
|
||||
}
|
||||
size_t EnumFiles (
|
||||
const std::wstring &lpDir,
|
||||
const std::wstring &lpFilter,
|
||||
std::vector <std::wstring> &aszOutput,
|
||||
bool bOutputWithPath = false,
|
||||
bool bSortByLetter = false,
|
||||
bool bIncludeSubDir = false
|
||||
) {
|
||||
if (!bIncludeSubDir) aszOutput.clear ();
|
||||
std::vector<std::wstring> filters;
|
||||
size_t start = 0;
|
||||
while (start < lpFilter.length ())
|
||||
{
|
||||
size_t pos = lpFilter.find (L'\\', start);
|
||||
if (pos == std::wstring::npos) pos = lpFilter.length ();
|
||||
filters.emplace_back (lpFilter.substr (start, pos - start));
|
||||
start = pos + 1;
|
||||
}
|
||||
|
||||
std::function <void (const std::wstring &, std::wstring)> enumDir;
|
||||
enumDir = [&] (const std::wstring &physicalPath, std::wstring relativePath)
|
||||
{
|
||||
WIN32_FIND_DATAW ffd;
|
||||
HANDLE hFind = FindFirstFileW ((physicalPath + L"\\*").c_str (), &ffd);
|
||||
if (hFind == INVALID_HANDLE_VALUE) return;
|
||||
do {
|
||||
if (wcscmp (ffd.cFileName, L".") == 0 ||
|
||||
wcscmp (ffd.cFileName, L"..") == 0) continue;
|
||||
const bool isDir = (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
|
||||
const std::wstring newPhysical = physicalPath + L"\\" + ffd.cFileName;
|
||||
std::wstring newRelative = relativePath;
|
||||
if (isDir) {
|
||||
if (bIncludeSubDir) {
|
||||
newRelative += ffd.cFileName;
|
||||
newRelative += L"\\";
|
||||
enumDir (newPhysical, newRelative);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const auto &filter : filters)
|
||||
{
|
||||
if (PathMatchSpecW (ffd.cFileName, filter.c_str ()))
|
||||
{
|
||||
aszOutput.push_back
|
||||
(
|
||||
bOutputWithPath ? newPhysical : (relativePath + ffd.cFileName)
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (FindNextFileW (hFind, &ffd));
|
||||
FindClose (hFind);
|
||||
};
|
||||
enumDir (lpDir, L"");
|
||||
if (bSortByLetter) std::sort (aszOutput.begin (), aszOutput.end ());
|
||||
return aszOutput.size ();
|
||||
}
|
||||
std::wstring GetRelativePath (
|
||||
const std::wstring &pszBaseDir,
|
||||
const std::wstring &pszFullPath,
|
||||
DWORD cchRelative
|
||||
) {
|
||||
std::vector <WCHAR> szBase (Max <size_t> (pszBaseDir.length (), pszFullPath.length (), MAX_PATH) + 1);
|
||||
wcscpy_s (szBase.data (), MAX_PATH, pszBaseDir.c_str ());
|
||||
if (szBase [wcslen (szBase.data ()) - 1] != L'\\')
|
||||
{
|
||||
wcscat_s (szBase.data (), MAX_PATH, L"\\");
|
||||
}
|
||||
std::vector <WCHAR> buf (Max <size_t> (MAX_PATH, szBase.size ()) + 1);
|
||||
BOOL res = PathRelativePathToW (
|
||||
buf.data (),
|
||||
szBase.data (),
|
||||
FILE_ATTRIBUTE_DIRECTORY,
|
||||
pszFullPath.c_str (),
|
||||
FILE_ATTRIBUTE_NORMAL
|
||||
);
|
||||
if (res) return buf.data ();
|
||||
else return L"";
|
||||
}
|
||||
size_t EnumDirectory (
|
||||
const std::wstring &lpDir,
|
||||
std::vector<std::wstring> &aszOutput,
|
||||
bool bOutputWithPath = false,
|
||||
bool bSortByLetter = false,
|
||||
bool bIncludeSubDir = false
|
||||
) {
|
||||
aszOutput.clear ();
|
||||
std::function <void (const std::wstring &, const std::wstring &)> enumDir;
|
||||
enumDir = [&] (const std::wstring &physicalPath, const std::wstring &relativePath) {
|
||||
WIN32_FIND_DATAW ffd;
|
||||
HANDLE hFind = FindFirstFileW ((physicalPath + L"\\*").c_str (), &ffd);
|
||||
if (hFind == INVALID_HANDLE_VALUE) return;
|
||||
do
|
||||
{
|
||||
const std::wstring name = ffd.cFileName;
|
||||
if (name == L"." || name == L"..") continue;
|
||||
const bool isDir = (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
|
||||
std::wstring newPhysical = physicalPath + L"\\" + name;
|
||||
std::wstring newRelative = relativePath + name;
|
||||
if (isDir)
|
||||
{
|
||||
if (bIncludeSubDir) enumDir (newPhysical, newRelative + L"\\");
|
||||
if (bOutputWithPath) aszOutput.push_back (newPhysical);
|
||||
else aszOutput.push_back (newRelative);
|
||||
}
|
||||
} while (FindNextFileW (hFind, &ffd));
|
||||
FindClose (hFind);
|
||||
};
|
||||
enumDir (lpDir, L"");
|
||||
if (bSortByLetter) std::sort (aszOutput.begin (), aszOutput.end ());
|
||||
return aszOutput.size ();
|
||||
}
|
||||
|
||||
static DWORD CALLBACK ProgressRoutine (
|
||||
LARGE_INTEGER TotalFileSize,
|
||||
LARGE_INTEGER TotalBytesTransferred,
|
||||
LARGE_INTEGER /*StreamSize*/,
|
||||
LARGE_INTEGER /*StreamBytesTransferred*/,
|
||||
DWORD /*dwStreamNumber*/,
|
||||
DWORD /*dwCallbackReason*/,
|
||||
HANDLE /*hSourceFile*/,
|
||||
HANDLE /*hDestinationFile*/,
|
||||
LPVOID lpData
|
||||
) {
|
||||
auto *pCallback = reinterpret_cast <std::function <void (int)> *> (lpData);
|
||||
if (pCallback && *pCallback)
|
||||
{
|
||||
int progress = static_cast <int> (
|
||||
(TotalBytesTransferred.QuadPart * 100) / TotalFileSize.QuadPart
|
||||
);
|
||||
(*pCallback) (progress);
|
||||
}
|
||||
return PROGRESS_CONTINUE;
|
||||
}
|
||||
bool RenameFileW (
|
||||
const std::wstring &lpSrcPath,
|
||||
const std::wstring &lpDestPath,
|
||||
std::function <void (int)> fProgress = nullptr
|
||||
) {
|
||||
LPPROGRESS_ROUTINE pRoutine = nullptr;
|
||||
LPVOID pData = nullptr;
|
||||
if (fProgress)
|
||||
{
|
||||
pRoutine = ProgressRoutine;
|
||||
pData = &fProgress;
|
||||
}
|
||||
DWORD flags = MOVEFILE_COPY_ALLOWED;
|
||||
BOOL ok = MoveFileWithProgressW (
|
||||
lpSrcPath.c_str (),
|
||||
lpDestPath.c_str (),
|
||||
pRoutine,
|
||||
pData,
|
||||
flags
|
||||
);
|
||||
return ok != FALSE;
|
||||
}
|
||||
bool RenameFileA (
|
||||
const std::string &lpSrcPath,
|
||||
const std::string &lpDestPath,
|
||||
std::function <void (int)> fProgress = nullptr
|
||||
) {
|
||||
LPPROGRESS_ROUTINE pRoutine = nullptr;
|
||||
LPVOID pData = nullptr;
|
||||
if (fProgress)
|
||||
{
|
||||
pRoutine = ProgressRoutine;
|
||||
pData = &fProgress;
|
||||
}
|
||||
DWORD flags = MOVEFILE_COPY_ALLOWED;
|
||||
BOOL ok = MoveFileWithProgressA (
|
||||
lpSrcPath.c_str (),
|
||||
lpDestPath.c_str (),
|
||||
pRoutine,
|
||||
pData,
|
||||
flags
|
||||
);
|
||||
return ok != FALSE;
|
||||
}
|
||||
bool RenameFileW (const std::wstring &lpSrcDir, const std::wstring &lpSrcName, const std::wstring &lpDestName, std::function <void (int)> fProgress = nullptr)
|
||||
{
|
||||
struct BuildTask
|
||||
{
|
||||
LPWSTR src = nullptr, dest = nullptr;
|
||||
~BuildTask ()
|
||||
{
|
||||
if (src != nullptr)
|
||||
{
|
||||
delete [] src;
|
||||
src = nullptr;
|
||||
}
|
||||
if (dest != nullptr)
|
||||
{
|
||||
delete [] dest;
|
||||
dest = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
BuildTask bt;
|
||||
bt.src = new WCHAR [lpSrcDir.length () + lpSrcName.length () + 2];
|
||||
bt.dest = new WCHAR [lpSrcDir.length () + lpDestName.length () + 2];
|
||||
PathCombineW (bt.src, lpSrcDir.c_str (), lpSrcName.c_str ());
|
||||
PathCombineW (bt.dest, lpSrcDir.c_str (), lpDestName.c_str ());
|
||||
return RenameFileW (bt.src, bt.dest, fProgress);
|
||||
}
|
||||
bool RenameFileA (const std::string &lpSrcDir, const std::string &lpSrcName, const std::string &lpDestName, std::function <void (int)> fProgress = nullptr)
|
||||
{
|
||||
struct BuildTask
|
||||
{
|
||||
LPSTR src = nullptr, dest = nullptr;
|
||||
~BuildTask ()
|
||||
{
|
||||
if (src != nullptr)
|
||||
{
|
||||
delete [] src;
|
||||
src = nullptr;
|
||||
}
|
||||
if (dest != nullptr)
|
||||
{
|
||||
delete [] dest;
|
||||
dest = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
BuildTask bt;
|
||||
bt.src = new CHAR [lpSrcDir.length () + lpSrcName.length () + 2];
|
||||
bt.dest = new CHAR [lpSrcDir.length () + lpDestName.length () + 2];
|
||||
PathCombineA (bt.src, lpSrcDir.c_str (), lpSrcName.c_str ());
|
||||
PathCombineA (bt.dest, lpSrcDir.c_str (), lpDestName.c_str ());
|
||||
return RenameFileA (bt.src, bt.dest, fProgress);
|
||||
}
|
||||
bool RenameFile (const std::wstring &lpSrcPath, const std::wstring &lpDestPath, std::function <void (int)> fProgress = nullptr)
|
||||
{
|
||||
return RenameFileW (lpSrcPath, lpDestPath, fProgress);
|
||||
}
|
||||
bool RenameFile (const std::string &lpSrcPath, const std::string &lpDestPath, std::function <void (int)> fProgress = nullptr)
|
||||
{
|
||||
return RenameFileA (lpSrcPath, lpDestPath, fProgress);
|
||||
}
|
||||
bool RenameFile (const std::wstring &lpSrcDir, const std::wstring &lpSrcName, const std::wstring &lpDestName, std::function <void (int)> fProgress = nullptr)
|
||||
{
|
||||
return RenameFileW (lpSrcDir, lpSrcName, lpDestName, fProgress);
|
||||
}
|
||||
bool RenameFile (const std::string &lpSrcDir, const std::string &lpSrcName, const std::string &lpDestName, std::function <void (int)> fProgress = nullptr)
|
||||
{
|
||||
return RenameFileA (lpSrcDir, lpSrcName, lpDestName, fProgress);
|
||||
}
|
||||
bool RenameDirectoryW (
|
||||
const std::wstring &lpSrcPath,
|
||||
const std::wstring &lpDestPath,
|
||||
std::function <void (int)> fProgress = nullptr
|
||||
) {
|
||||
LPPROGRESS_ROUTINE pRoutine = nullptr;
|
||||
LPVOID pData = nullptr;
|
||||
if (fProgress)
|
||||
{
|
||||
pRoutine = ProgressRoutine;
|
||||
pData = &fProgress;
|
||||
}
|
||||
DWORD flags = MOVEFILE_COPY_ALLOWED;
|
||||
BOOL ok = MoveFileWithProgressW (
|
||||
lpSrcPath.c_str (),
|
||||
lpDestPath.c_str (),
|
||||
pRoutine,
|
||||
pData,
|
||||
flags
|
||||
);
|
||||
return ok != FALSE;
|
||||
}
|
||||
bool RenameDirectoryA (
|
||||
const std::string &lpSrcPath,
|
||||
const std::string &lpDestPath,
|
||||
std::function <void (int)> fProgress = nullptr
|
||||
) {
|
||||
LPPROGRESS_ROUTINE pRoutine = nullptr;
|
||||
LPVOID pData = nullptr;
|
||||
if (fProgress)
|
||||
{
|
||||
pRoutine = ProgressRoutine;
|
||||
pData = &fProgress;
|
||||
}
|
||||
DWORD flags = MOVEFILE_COPY_ALLOWED;
|
||||
BOOL ok = MoveFileWithProgressA (
|
||||
lpSrcPath.c_str (),
|
||||
lpDestPath.c_str (),
|
||||
pRoutine,
|
||||
pData,
|
||||
flags
|
||||
);
|
||||
return ok != FALSE;
|
||||
}
|
||||
bool RenameDirectoryW (
|
||||
const std::wstring &lpParentDir,
|
||||
const std::wstring &lpSrcName,
|
||||
const std::wstring &lpDestName,
|
||||
std::function <void (int)> fProgress = nullptr
|
||||
) {
|
||||
struct PathBuilder
|
||||
{
|
||||
LPWSTR src = nullptr;
|
||||
LPWSTR dest = nullptr;
|
||||
~PathBuilder ()
|
||||
{
|
||||
delete [] src;
|
||||
delete [] dest;
|
||||
}
|
||||
} pb;
|
||||
pb.src = new WCHAR [lpParentDir.length () + lpSrcName.length () + 2];
|
||||
pb.dest = new WCHAR [lpParentDir.length () + lpDestName.length () + 2];
|
||||
PathCombineW (pb.src, lpParentDir.c_str (), lpSrcName.c_str ());
|
||||
PathCombineW (pb.dest, lpParentDir.c_str (), lpDestName.c_str ());
|
||||
return RenameDirectoryW (pb.src, pb.dest, fProgress);
|
||||
}
|
||||
bool RenameDirectoryA (
|
||||
const std::string &lpParentDir,
|
||||
const std::string &lpSrcName,
|
||||
const std::string &lpDestName,
|
||||
std::function <void (int)> fProgress = nullptr
|
||||
) {
|
||||
struct PathBuilder
|
||||
{
|
||||
LPSTR src = nullptr;
|
||||
LPSTR dest = nullptr;
|
||||
~PathBuilder ()
|
||||
{
|
||||
delete [] src;
|
||||
delete [] dest;
|
||||
}
|
||||
} pb;
|
||||
pb.src = new CHAR [lpParentDir.length () + lpSrcName.length () + 2];
|
||||
pb.dest = new CHAR [lpParentDir.length () + lpDestName.length () + 2];
|
||||
PathCombineA (pb.src, lpParentDir.c_str (), lpSrcName.c_str ());
|
||||
PathCombineA (pb.dest, lpParentDir.c_str (), lpDestName.c_str ());
|
||||
return RenameDirectoryA (pb.src, pb.dest, fProgress);
|
||||
}
|
||||
bool RenameDirectory (
|
||||
const std::wstring &src,
|
||||
const std::wstring &dst,
|
||||
std::function <void (int)> fProgress = nullptr
|
||||
) {
|
||||
return RenameDirectoryW (src, dst, fProgress);
|
||||
}
|
||||
bool RenameDirectory (
|
||||
const std::string &src,
|
||||
const std::string &dst,
|
||||
std::function <void (int)> fProgress = nullptr
|
||||
) {
|
||||
return RenameDirectoryA (src, dst, fProgress);
|
||||
}
|
||||
bool RenameDirectory (
|
||||
const std::wstring &parentDir,
|
||||
const std::wstring &srcName,
|
||||
const std::wstring &dstName,
|
||||
std::function <void (int)> fProgress = nullptr
|
||||
) {
|
||||
return RenameDirectoryW (parentDir, srcName, dstName, fProgress);
|
||||
}
|
||||
bool RenameDirectory (
|
||||
const std::string &parentDir,
|
||||
const std::string &srcName,
|
||||
const std::string &dstName,
|
||||
std::function <void (int)> fProgress = nullptr
|
||||
) {
|
||||
return RenameDirectoryA (parentDir, srcName, dstName, fProgress);
|
||||
}
|
||||
std::wstring CombinePath (const std::wstring &left, const std::wstring &right)
|
||||
{
|
||||
std::vector <WCHAR> buf (left.capacity () + right.capacity () + 2);
|
||||
PathCombineW (buf.data (), left.c_str (), right.c_str ());
|
||||
return buf.data ();
|
||||
}
|
||||
#ifdef PathCommonPrefix
|
||||
#undef PathCommonPrefix
|
||||
#endif
|
||||
std::wstring PathCommonPrefix (const std::wstring &file1, const std::wstring &file2)
|
||||
{
|
||||
std::vector <WCHAR> buf (Max <size_t> (file1.capacity (), file2.capacity (), MAX_PATH) + 2);
|
||||
PathCommonPrefixW (file1.c_str (), file2.c_str (), buf.data ());
|
||||
return buf.data ();
|
||||
}
|
||||
#undef GetFullPathName
|
||||
std::wstring GetFullPathName (const std::wstring &lpFileName)
|
||||
{
|
||||
if (lpFileName.empty ()) return L"";
|
||||
DWORD length = GetFullPathNameW (lpFileName.c_str (), 0, nullptr, nullptr);
|
||||
if (length == 0) return L"";
|
||||
std::vector <WCHAR> buffer (length + 1, L'\0');
|
||||
DWORD result = GetFullPathNameW (lpFileName.c_str (), length, buffer.data (), nullptr);
|
||||
if (result == 0) return L"";
|
||||
return std::wstring (buffer.data (), result);
|
||||
}
|
||||
bool PathEquals (const std::wstring &path1, const std::wstring &path2)
|
||||
{
|
||||
size_t maxlen = Max <size_t> (path1.capacity () + 1, path2.capacity () + 1, MAX_PATH);
|
||||
std::vector <WCHAR> buf1 (maxlen), buf2 (maxlen);
|
||||
PathCanonicalizeW (buf1.data (), path1.c_str ());
|
||||
PathCanonicalizeW (buf2.data (), path2.c_str ());
|
||||
return IsNormalizeStringEquals (buf1.data (), buf2.data ());
|
||||
}
|
||||
607
desktopini/initfile.h
Normal file
607
desktopini/initfile.h
Normal file
@@ -0,0 +1,607 @@
|
||||
#pragma once
|
||||
#ifndef _CRT_NON_CONFORMING_SWPRINTFS
|
||||
#define _CRT_NON_CONFORMING_SWPRINTFS
|
||||
#endif
|
||||
#include <Windows.h>
|
||||
#include <string>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <cstdint>
|
||||
#include <cwchar>
|
||||
#include <type_traits>
|
||||
#include "strcode.h"
|
||||
#include "nstring.h"
|
||||
#include "typestrans.h"
|
||||
#ifdef _cplusplus_cli
|
||||
#include "mpstr.h"
|
||||
#endif
|
||||
|
||||
template <typename T> std::wstring TypeToString (T value, const std::wstring &reserve = L"") { return std::to_wstring (value); }
|
||||
template <typename T> std::string TypeToString (T value, const std::string &reserve = "") { return std::to_string (value); }
|
||||
|
||||
std::string GetPrivateProfileStringA (const std::string &filePath, const std::string §ion, const std::string &key, LPCSTR defaultValue = "")
|
||||
{
|
||||
char buf [32768] = {0};
|
||||
GetPrivateProfileStringA (section.c_str (), key.c_str (), defaultValue, buf, 32767, filePath.c_str ());
|
||||
return buf;
|
||||
}
|
||||
std::wstring GetPrivateProfileStringW (const std::wstring &filePath, const std::wstring §ion, const std::wstring &key, LPCWSTR defaultValue = L"")
|
||||
{
|
||||
WCHAR buf [32768] = {0};
|
||||
GetPrivateProfileStringW (section.c_str (), key.c_str (), defaultValue, buf, 32767, filePath.c_str ());
|
||||
return buf;
|
||||
}
|
||||
UINT GetPrivateProfileIntA (const std::string &filePath, const std::string §ion, const std::string &key, INT defaultValue = 0)
|
||||
{
|
||||
return GetPrivateProfileIntA (section.c_str (), key.c_str (), defaultValue, filePath.c_str ());
|
||||
}
|
||||
UINT GetPrivateProfileIntW (const std::wstring &filePath, const std::wstring §ion, const std::wstring &key, INT defaultValue = 0)
|
||||
{
|
||||
return GetPrivateProfileIntW (section.c_str (), key.c_str (), defaultValue, filePath.c_str ());
|
||||
}
|
||||
BOOL WritePrivateProfileStringA (const std::string &filePath, const std::string §ion, const std::string &key, const std::string &value)
|
||||
{
|
||||
return WritePrivateProfileStringA (section.c_str (), key.c_str (), value.c_str (), filePath.c_str ());
|
||||
}
|
||||
BOOL WritePrivateProfileStringW (const std::wstring &filePath, const std::wstring §ion, const std::wstring &key, const std::wstring &value)
|
||||
{
|
||||
return WritePrivateProfileStringW (section.c_str (), key.c_str (), value.c_str (), filePath.c_str ());
|
||||
}
|
||||
size_t GetPrivateProfileSectionA (const std::string &filePath, const std::string §ion, std::vector <std::string> &output)
|
||||
{
|
||||
char buf [32768] = {0};
|
||||
DWORD len = GetPrivateProfileSectionA (section.c_str (), buf, sizeof (buf), filePath.c_str ());
|
||||
output.clear ();
|
||||
if (len == 0) return 0;
|
||||
char *ptr = buf;
|
||||
while (*ptr)
|
||||
{
|
||||
output.emplace_back (ptr);
|
||||
ptr += strlen (ptr) + 1;
|
||||
}
|
||||
return output.size ();
|
||||
}
|
||||
size_t GetPrivateProfileSectionW (const std::wstring &filePath, const std::wstring §ion, std::vector <std::wstring> &output)
|
||||
{
|
||||
WCHAR buf [32768] = {0};
|
||||
DWORD len = GetPrivateProfileSectionW (section.c_str (), buf, sizeof (buf) / sizeof (WCHAR), filePath.c_str ());
|
||||
output.clear ();
|
||||
if (len == 0) return 0;
|
||||
WCHAR *ptr = buf;
|
||||
while (*ptr)
|
||||
{
|
||||
output.emplace_back (ptr);
|
||||
ptr += wcslen (ptr) + 1;
|
||||
}
|
||||
return output.size ();
|
||||
}
|
||||
size_t GetPrivateProfileSectionNamesA (const std::string &filePath, std::vector <std::string> &output)
|
||||
{
|
||||
char buf [32768] = {0};
|
||||
DWORD len = GetPrivateProfileSectionNamesA (buf, sizeof (buf), filePath.c_str ());
|
||||
output.clear ();
|
||||
if (len == 0) return 0;
|
||||
char *ptr = buf;
|
||||
while (*ptr)
|
||||
{
|
||||
output.emplace_back (ptr);
|
||||
ptr += strlen (ptr) + 1;
|
||||
}
|
||||
return output.size ();
|
||||
}
|
||||
size_t GetPrivateProfileSectionNamesW (const std::wstring &filePath, std::vector <std::wstring> &output)
|
||||
{
|
||||
WCHAR buf [32768] = {0};
|
||||
DWORD len = GetPrivateProfileSectionNamesW (buf, sizeof (buf) / sizeof (WCHAR), filePath.c_str ());
|
||||
output.clear ();
|
||||
if (len == 0) return 0;
|
||||
WCHAR *ptr = buf;
|
||||
while (*ptr)
|
||||
{
|
||||
output.emplace_back (ptr);
|
||||
ptr += wcslen (ptr) + 1;
|
||||
}
|
||||
return output.size ();
|
||||
}
|
||||
bool WritePrivateProfileSectionA (const std::string &filePath, const std::string §ion, const std::vector <std::string> &lines)
|
||||
{
|
||||
std::string buf;
|
||||
for (const auto &line : lines) buf.append (line).push_back ('\0');
|
||||
buf.push_back ('\0');
|
||||
return WritePrivateProfileSectionA (section.c_str (), buf.c_str (), filePath.c_str ()) != 0;
|
||||
}
|
||||
bool WritePrivateProfileSectionW (const std::wstring &filePath, const std::wstring §ion, const std::vector <std::wstring> &lines)
|
||||
{
|
||||
std::wstring buf;
|
||||
for (const auto &line : lines) buf.append (line).push_back (L'\0');
|
||||
buf.push_back (L'\0'); // Ë« \0 ½áβ
|
||||
return WritePrivateProfileSectionW (section.c_str (), buf.c_str (), filePath.c_str ()) != 0;
|
||||
}
|
||||
bool GetPrivateProfileStructA (const std::string &filePath, const std::string §ion, const std::string &key, void *output, UINT size)
|
||||
{
|
||||
return GetPrivateProfileStructA (section.c_str (), key.c_str (), output, size, filePath.c_str ()) != 0;
|
||||
}
|
||||
bool WritePrivateProfileStructA (const std::string &filePath, const std::string §ion, const std::string &key, void *data, UINT size)
|
||||
{
|
||||
return WritePrivateProfileStructA (section.c_str (), key.c_str (), data, size, filePath.c_str ()) != 0;
|
||||
}
|
||||
bool GetPrivateProfileStructW (const std::wstring &filePath, const std::wstring §ion, const std::wstring &key, void *output, UINT size)
|
||||
{
|
||||
return GetPrivateProfileStructW (section.c_str (), key.c_str (), output, size, filePath.c_str ()) != 0;
|
||||
}
|
||||
bool WritePrivateProfileStructW (const std::wstring &filePath, const std::wstring §ion, const std::wstring &key, void *data, UINT size)
|
||||
{
|
||||
return WritePrivateProfileStructW (section.c_str (), key.c_str (), data, size, filePath.c_str ()) != 0;
|
||||
}
|
||||
size_t GetPrivateProfileKeysW (const std::wstring &filePath, const std::wstring §ion, std::vector <std::wstring> &keys)
|
||||
{
|
||||
WCHAR buf [32768] = {0};
|
||||
DWORD len = GetPrivateProfileSectionW (section.c_str (), buf, sizeof (buf) / sizeof (WCHAR), filePath.c_str ());
|
||||
keys.clear ();
|
||||
if (len == 0) return 0;
|
||||
WCHAR* ptr = buf;
|
||||
while (*ptr)
|
||||
{
|
||||
std::wstring line = ptr;
|
||||
size_t pos = line.find (L'=');
|
||||
if (pos != std::wstring::npos) keys.push_back (line.substr (0, pos));
|
||||
ptr += wcslen (ptr) + 1;
|
||||
}
|
||||
return keys.size ();
|
||||
}
|
||||
size_t GetPrivateProfileKeysA (const std::string &filePath, const std::string §ion, std::vector <std::string> &keys)
|
||||
{
|
||||
char buf [32768] = {0};
|
||||
DWORD len = GetPrivateProfileSectionA (section.c_str (), buf, sizeof (buf), filePath.c_str ());
|
||||
keys.clear ();
|
||||
if (len == 0)
|
||||
return 0;
|
||||
char *ptr = buf;
|
||||
while (*ptr)
|
||||
{
|
||||
std::string line = ptr;
|
||||
size_t pos = line.find ('=');
|
||||
if (pos != std::string::npos) keys.push_back (line.substr (0, pos));
|
||||
ptr += strlen (ptr) + 1;
|
||||
}
|
||||
return keys.size ();
|
||||
}
|
||||
bool DeletePrivateProfileKeyA (const std::string &filePath, const std::string §ion, const std::string &key)
|
||||
{
|
||||
return WritePrivateProfileStringA (section.c_str (), key.c_str (), NULL, filePath.c_str ()) != FALSE;
|
||||
}
|
||||
bool DeletePrivateProfileKeyW (const std::wstring &filePath, const std::wstring §ion, const std::wstring &key)
|
||||
{
|
||||
return WritePrivateProfileStringW (section.c_str (), key.c_str (), NULL, filePath.c_str ()) != FALSE;
|
||||
}
|
||||
bool DeletePrivateProfileSectionA (const std::string &filePath, const std::string §ion)
|
||||
{
|
||||
return WritePrivateProfileStringA (section.c_str (), NULL, NULL, filePath.c_str ()) != FALSE;
|
||||
}
|
||||
bool DeletePrivateProfileSectionW (const std::wstring &filePath, const std::wstring §ion)
|
||||
{
|
||||
return WritePrivateProfileStringW (section.c_str (), NULL, NULL, filePath.c_str ()) != FALSE;
|
||||
}
|
||||
|
||||
class initkey
|
||||
{
|
||||
public:
|
||||
using pstring = std::string &;
|
||||
using pwstring = std::wstring &;
|
||||
using pcstring = const std::string &;
|
||||
using pcwstring = const std::wstring &;
|
||||
private:
|
||||
pcwstring filepath;
|
||||
pcwstring section;
|
||||
template <typename T, typename Trans = T, typename Func> T read_t (T defaultvalue, Func process) const
|
||||
{
|
||||
auto res = read_wstring (std::to_wstring ((Trans)defaultvalue));
|
||||
if (IsNormalizeStringEmpty (res)) return defaultvalue;
|
||||
return (T)process (res.c_str ());
|
||||
}
|
||||
template <typename T> bool write_t (T value) { return write_string (std::to_wstring (value)); }
|
||||
public:
|
||||
std::wstring key;
|
||||
initkey (pcwstring path, pcwstring sect, pcwstring k): filepath (path), section (sect), key (k) {}
|
||||
std::wstring read_wstring (pcwstring defaultvalue = L"") const { return GetPrivateProfileStringW (filepath, section, key, defaultvalue.c_str ()); }
|
||||
std::string read_string (pcstring defaultvalue = "") const { return WStringToString (read_wstring (StringToWString (defaultvalue))); }
|
||||
short read_short (short defaultvalue = 0) const { return read_t (defaultvalue, _wtoi16); }
|
||||
unsigned short read_ushort (unsigned short defaultvalue = 0) const { return read_t (defaultvalue, _wtoui16); }
|
||||
int read_int (int defaultvalue = 0) const { return read_t (defaultvalue, _wtoi); }
|
||||
unsigned int read_uint (unsigned int defaultvalue = 0) const { return read_t (defaultvalue, _wtou); }
|
||||
long read_long (long defaultvalue = 0) const { return read_t (defaultvalue, _wtol); }
|
||||
unsigned long read_ulong (unsigned long defaultvalue = 0) const { return read_t (defaultvalue, _wtoul); }
|
||||
long long read_llong (long long defaultvalue = 0) const { return read_t (defaultvalue, _wtoll); }
|
||||
unsigned long long read_ullong (unsigned long long defaultvalue = 0) const { return read_t (defaultvalue, _wtou64); }
|
||||
float read_float (float defaultvalue = 0) const { return read_t (defaultvalue, _wtof); }
|
||||
double read_double (double defaultvalue = 0) const { return read_t (defaultvalue, _wtod); }
|
||||
bool read_bool (bool defaultvalue = false) const
|
||||
{
|
||||
std::wnstring res = read_wstring (defaultvalue ? L"true" : L"false");
|
||||
if (res.empty ()) return defaultvalue;
|
||||
if (res.equals (L"true") || res.equals (L"yes") || res.equals (L"zhen") || res.equals (L"Õæ") || res.equals (L"1") || _wtoi (res.c_str ()) != 0) return true;
|
||||
else if (res.equals (L"false") || res.equals (L"no") || res.equals (L"jia") || res.equals (L"¼Ù") || res.equals (L"0")) return false;
|
||||
else return defaultvalue;
|
||||
}
|
||||
int8_t read_i8 (int8_t defaultvalue = 0) const { return read_t <int8_t, int16_t> (defaultvalue, _wtoi8); }
|
||||
uint8_t read_u8 (uint8_t defaultvalue = 0) const { return read_t <uint8_t, uint16_t> (defaultvalue, _wtoui8); }
|
||||
int16_t read_i16 (int16_t defaultvalue = 0) const { return read_t (defaultvalue, _wtoi16); }
|
||||
uint16_t read_u16 (uint16_t defaultvalue = 0) const { return read_t (defaultvalue, _wtoui16); }
|
||||
int32_t read_i32 (int32_t defaultvalue = 0) const { return read_t (defaultvalue, _wtoi32); }
|
||||
uint32_t read_u32 (uint32_t defaultvalue = 0) const { return read_t (defaultvalue, _wtoui32); }
|
||||
int64_t read_i64 (int64_t defaultvalue = 0) const { return read_t (defaultvalue, _wtoi64); }
|
||||
uint64_t read_u64 (uint64_t defaultvalue = 0) const { return read_t (defaultvalue, _wtou64); }
|
||||
bool read_struct (void *output, size_t size) const { return GetPrivateProfileStructW (filepath, section, key, output, size); }
|
||||
template <typename T> bool read_struct (T &structinst) const { return read_struct (&structinst, sizeof (structinst)); }
|
||||
bool write_string (pcwstring value) { return write (value); }
|
||||
bool write_string (pcstring value) { return write (value); }
|
||||
bool write (pcwstring value) { return WritePrivateProfileStringW (filepath, section, key, value); }
|
||||
bool write (pcstring value) { return write (StringToWString (value)); }
|
||||
bool write (LPCWSTR value) { return write_string (std::wstring (value ? value : L"")); }
|
||||
bool write (LPCSTR value) { return write_string (value ? value : ""); }
|
||||
bool write (int value) { return write_t (value); }
|
||||
bool write (unsigned int value) { return write_t (value); }
|
||||
bool write (short value) { return write_t (value); }
|
||||
bool write (unsigned short value) { return write_t (value); }
|
||||
bool write (long value) { return write_t (value); }
|
||||
bool write (unsigned long value) { return write_t (value); }
|
||||
bool write (long long value) { return write_t (value); }
|
||||
bool write (unsigned long long value) { return write_t (value); }
|
||||
bool write (int8_t value) { return write_t ((int16_t)value); }
|
||||
bool write (uint8_t value) { return write_t ((uint16_t)value); }
|
||||
bool write (float value) { return write_t (value); }
|
||||
bool write (double value) { return write_t (value); }
|
||||
bool write (bool value) { return write (value ? L"true" : L"false"); }
|
||||
bool write (void *buf, size_t bufsize) { return WritePrivateProfileStructW (filepath, section, key, buf, bufsize); }
|
||||
operator std::wstring () { return read_wstring (); }
|
||||
operator std::string () { return read_string (); }
|
||||
template <typename T> initkey &operator = (T value) { write (value); return *this; }
|
||||
initkey &operator = (const initkey &) = delete;
|
||||
// ɾ³ýÏî
|
||||
bool clear () { return DeletePrivateProfileKeyW (filepath, section, key); }
|
||||
bool empty () const { return read_wstring ().empty (); }
|
||||
#define OPERATOR_TYPE_READ(_type_, _method_) \
|
||||
operator _type_ () { return _method_ (); }
|
||||
OPERATOR_TYPE_READ (int, read_int)
|
||||
OPERATOR_TYPE_READ (unsigned int, read_uint)
|
||||
OPERATOR_TYPE_READ (long, read_long)
|
||||
OPERATOR_TYPE_READ (unsigned long, read_ulong)
|
||||
OPERATOR_TYPE_READ (long long, read_llong)
|
||||
OPERATOR_TYPE_READ (unsigned long long, read_ullong)
|
||||
OPERATOR_TYPE_READ (short, read_short)
|
||||
OPERATOR_TYPE_READ (unsigned short, read_ushort)
|
||||
OPERATOR_TYPE_READ (float, read_float)
|
||||
OPERATOR_TYPE_READ (double, read_double)
|
||||
OPERATOR_TYPE_READ (bool, read_bool)
|
||||
#ifdef OPERATOR_TYPE_READ
|
||||
#undef OPERATOR_TYPE_READ
|
||||
#endif
|
||||
};
|
||||
class initsection
|
||||
{
|
||||
private:
|
||||
const std::wstring &filepath;
|
||||
template <typename T, typename Trans = T, typename CT, typename Func> T read_t (const std::basic_string <CT> &key, T defaultvalue, Func process) const
|
||||
{
|
||||
std::basic_string <CT> temp;
|
||||
auto res = read_string (key, TypeToString ((Trans)defaultvalue, temp));
|
||||
if (IsNormalizeStringEmpty (res)) return defaultvalue;
|
||||
return (T)process (res.c_str ());
|
||||
}
|
||||
template <typename T, typename CT> bool write_t (const std::basic_string <CT> &key, T value)
|
||||
{
|
||||
std::basic_string <CT> temp;
|
||||
return write_string (key, TypeToString (value, temp));
|
||||
}
|
||||
public:
|
||||
using pcstring = const std::string &;
|
||||
using pcwstring = const std::wstring &;
|
||||
std::wstring section;
|
||||
initsection (const std::wstring &path, const std::wstring §): filepath (path), section (sect) {}
|
||||
size_t keys (std::vector <std::wstring> &output) const { return GetPrivateProfileKeysW (filepath, section, output); }
|
||||
size_t keys (std::vector <std::string> &output) const { return GetPrivateProfileKeysA (WStringToString (filepath), WStringToString (section), output); }
|
||||
bool key_values (const std::vector <std::wstring> &lines) { return WritePrivateProfileSectionW (filepath, section, lines); }
|
||||
bool key_values (const std::vector <std::string> &lines) { return WritePrivateProfileSectionA (WStringToString (filepath), WStringToString (section), lines); }
|
||||
size_t key_values (std::vector <std::wstring> &output) const { return GetPrivateProfileSectionW (filepath, section, output); }
|
||||
size_t key_values (std::vector <std::string> &output) const { return GetPrivateProfileSectionA (WStringToString (filepath), WStringToString (section), output); }
|
||||
std::wstring read_string (const std::wstring &key, const std::wstring &defaultvalue = L"") const { return GetPrivateProfileStringW (filepath, section, key, defaultvalue.c_str ()); }
|
||||
std::string read_string (const std::string &key, const std::string &defaultvalue = "") const { return WStringToString (read_string (StringToWString (key), StringToWString (defaultvalue))); }
|
||||
std::wstring read_wstring (const std::wstring &key, const std::wstring &defaultvalue = L"") const { return read_string (key, defaultvalue); }
|
||||
int read_int (const std::wstring &key, int defaultvalue = 0) const { return read_t (key, defaultvalue, _wtoi); }
|
||||
int read_int (const std::string &key, int defaultvalue = 0) const { return read_t (key, defaultvalue, atoi); }
|
||||
unsigned int read_uint (const std::wstring &key, unsigned int defaultvalue = 0) const { return read_t (key, defaultvalue, _wtou); }
|
||||
unsigned int read_uint (const std::string &key, unsigned int defaultvalue = 0) const { return read_t (key, defaultvalue, atou); }
|
||||
long read_long (const std::wstring &key, long defaultvalue = 0) const { return read_t (key, defaultvalue, _wtol); }
|
||||
long read_long (const std::string &key, long defaultvalue = 0) const { return read_t (key, defaultvalue, atol); }
|
||||
unsigned long read_ulong (const std::wstring &key, unsigned long defaultvalue = 0) const { return read_t (key, defaultvalue, _wtoul); }
|
||||
unsigned long read_ulong (const std::string &key, unsigned long defaultvalue = 0) const { return read_t (key, defaultvalue, atoul); }
|
||||
long long read_llong (const std::wstring &key, long long defaultvalue = 0) const { return read_t (key, defaultvalue, _wtoll); }
|
||||
long long read_llong (const std::string &key, long long defaultvalue = 0) const { return read_t (key, defaultvalue, atoll); }
|
||||
unsigned long long read_ullong (const std::wstring &key, unsigned long long defaultvalue = 0) const { return read_t (key, defaultvalue, _wtou64); }
|
||||
unsigned long long read_ullong (const std::string &key, unsigned long long defaultvalue = 0) const { return read_t (key, defaultvalue, atou64); }
|
||||
int8_t read_i8 (const std::wstring &key, int8_t defaultvalue = 0) const { return read_t <int8_t, int16_t> (key, defaultvalue, _wtoi8); }
|
||||
int8_t read_i8 (const std::string &key, int8_t defaultvalue = 0) const { return read_t <int8_t, int16_t> (key, defaultvalue, atoi8); }
|
||||
uint8_t read_u8 (const std::wstring &key, uint8_t defaultvalue = 0) const { return read_t <uint8_t, uint16_t> (key, defaultvalue, _wtoui8); }
|
||||
uint8_t read_u8 (const std::string &key, uint8_t defaultvalue = 0) const { return read_t <uint8_t, uint16_t> (key, defaultvalue, atoui8); }
|
||||
int16_t read_i16 (const std::wstring &key, int16_t defaultvalue = 0) const { return read_t (key, defaultvalue, _wtoi16); }
|
||||
int16_t read_i16 (const std::string &key, int16_t defaultvalue = 0) const { return read_t (key, defaultvalue, atoi16); }
|
||||
short read_short (pcwstring key, short defaultvalue = 0) const { return read_i16 (key, defaultvalue); }
|
||||
short read_short (pcstring key, short defaultvalue = 0) const { return read_i16 (key, defaultvalue); }
|
||||
unsigned short read_ushort (pcwstring key, unsigned short defaultvalue = 0) const { return read_u16 (key, defaultvalue); }
|
||||
unsigned short read_ushort (pcstring key, unsigned short defaultvalue = 0) const { return read_u16 (key, defaultvalue); }
|
||||
uint16_t read_u16 (const std::wstring &key, uint16_t defaultvalue = 0) const { return read_t (key, defaultvalue, _wtoui16); }
|
||||
uint16_t read_u16 (const std::string &key, uint16_t defaultvalue = 0) const { return read_t (key, defaultvalue, atoui16); }
|
||||
int32_t read_i32 (const std::wstring &key, int32_t defaultvalue = 0) const { return read_t (key, defaultvalue, _wtoi32); }
|
||||
int32_t read_i32 (const std::string &key, int32_t defaultvalue = 0) const { return read_t (key, defaultvalue, atoi32); }
|
||||
uint32_t read_u32 (const std::wstring &key, uint32_t defaultvalue = 0) const { return read_t (key, defaultvalue, _wtoui32); }
|
||||
uint32_t read_u32 (const std::string &key, uint32_t defaultvalue = 0) const { return read_t (key, defaultvalue, atoui32); }
|
||||
int64_t read_i64 (const std::wstring &key, int64_t defaultvalue = 0) const { return read_t (key, defaultvalue, _wtoi64); }
|
||||
int64_t read_i64 (const std::string &key, int64_t defaultvalue = 0) const { return read_t (key, defaultvalue, atoi64); }
|
||||
uint64_t read_u64 (const std::wstring &key, uint64_t defaultvalue = 0) const { return read_ullong (key, defaultvalue); }
|
||||
uint64_t read_u64 (const std::string &key, uint64_t defaultvalue = 0) const { return read_ullong (key, defaultvalue); }
|
||||
float read_float (const std::wstring &key, float defaultvalue = 0) const { return read_t (key, defaultvalue, _wtof); }
|
||||
double read_double (const std::wstring &key, double defaultvalue = 0) const { return read_t (key, defaultvalue, _wtod); }
|
||||
bool read_bool (const std::wstring &key, bool defaultvalue = false) const
|
||||
{
|
||||
std::wnstring res = read_string (key, defaultvalue ? L"true" : L"false");
|
||||
if (res.empty ()) return defaultvalue;
|
||||
if (res.equals (L"true") || res.equals (L"yes") || res.equals (L"zhen") || res.equals (L"Õæ") || res.equals (L"1") || _wtoi (res.c_str ()) != 0) return true;
|
||||
else if (res.equals (L"false") || res.equals (L"no") || res.equals (L"jia") || res.equals (L"¼Ù") || res.equals (L"0")) return false;
|
||||
else return defaultvalue;
|
||||
}
|
||||
bool read_bool (const std::string &key, bool defaultvalue = false) const { return read_bool (StringToWString (key), defaultvalue); }
|
||||
bool read_struct (const std::wstring &key, void *output, size_t size) const { return GetPrivateProfileStructW (filepath, section, key, output, size); }
|
||||
template <typename T> bool read_struct (const std::wstring &key, T &structinst) const { return read_struct (key, &structinst, sizeof (structinst)); }
|
||||
bool write_string (const std::wstring &key, const std::wstring &value) { return WritePrivateProfileStringW (filepath, section, key, value); }
|
||||
bool write_string (const std::string &key, const std::string &value) { return write_string (StringToWString (key), StringToWString (value)); }
|
||||
bool write (pcwstring key, LPCWSTR value) { return write_string (key, value ? value : L""); }
|
||||
bool write (pcstring key, LPCSTR value) { return write_string (key, value ? value : ""); }
|
||||
bool write (const std::wstring &key, const std::wstring &value) { return write_string (key, value); }
|
||||
bool write (const std::string &key, const std::string &value) { return write_string (key, value); }
|
||||
bool write (pcwstring key, short value) { return write_t (key, value); }
|
||||
bool write (pcwstring key, unsigned short value) { return write_t (key, value); }
|
||||
bool write (pcwstring key, int value) { return write_t (key, value); }
|
||||
bool write (pcwstring key, unsigned int value) { return write_t (key, value); }
|
||||
bool write (pcwstring key, long value) { return write_t (key, value); }
|
||||
bool write (pcwstring key, unsigned long value) { return write_t (key, value); }
|
||||
bool write (pcwstring key, long long value) { return write_t (key, value); }
|
||||
bool write (pcwstring key, unsigned long long value) { return write_t (key, value); }
|
||||
bool write (pcwstring key, int8_t value) { return write_t (key, (int16_t)value); }
|
||||
bool write (pcwstring key, uint8_t value) { return write_t (key, (uint16_t)value); }
|
||||
bool write (pcwstring key, bool value) { return write (key, value ? L"true" : L"false"); }
|
||||
bool write (pcstring key, short value) { return write_t (key, value); }
|
||||
bool write (pcstring key, unsigned short value) { return write_t (key, value); }
|
||||
bool write (pcstring key, int value) { return write_t (key, value); }
|
||||
bool write (pcstring key, unsigned int value) { return write_t (key, value); }
|
||||
bool write (pcstring key, long value) { return write_t (key, value); }
|
||||
bool write (pcstring key, unsigned long value) { return write_t (key, value); }
|
||||
bool write (pcstring key, long long value) { return write_t (key, value); }
|
||||
bool write (pcstring key, unsigned long long value) { return write_t (key, value); }
|
||||
bool write (pcstring key, int8_t value) { return write_t (key, (int16_t)value); }
|
||||
bool write (pcstring key, uint8_t value) { return write_t (key, (uint16_t)value); }
|
||||
bool write (pcstring key, bool value) { return write (StringToWString (key), value ? L"true" : L"false"); }
|
||||
bool write (pcwstring key, void *buf, size_t bufsize) { return WritePrivateProfileStructW (filepath, section, key, buf, bufsize); }
|
||||
bool write (pcstring key, void *buf, size_t bufsize) { return write (StringToWString (key), buf, bufsize); }
|
||||
initkey operator [] (pcwstring key) { return initkey (filepath, section, key); }
|
||||
initkey operator [] (pcstring key) { return initkey (filepath, section, StringToWString (key)); }
|
||||
std::wstring operator [] (pcwstring key) const { return read_string (key); }
|
||||
std::wstring operator [] (pcstring key) const { return read_string (StringToWString (key)); }
|
||||
bool delete_key (pcwstring key) { return DeletePrivateProfileKeyW (filepath, section, key); }
|
||||
bool delete_key (pcstring key) { return delete_key (StringToWString (key)); }
|
||||
bool clear () { return DeletePrivateProfileSectionW (filepath, section); }
|
||||
initkey get_key (pcwstring key) const { return initkey (filepath, section, key); }
|
||||
initkey get_key (pcwstring key) { return initkey (filepath, section, key); }
|
||||
initkey get_key (pcstring key) const { return initkey (filepath, section, StringToWString (key)); }
|
||||
initkey get_key (pcstring key) { return initkey (filepath, section, StringToWString (key)); }
|
||||
initsection &operator = (const initsection &) = delete;
|
||||
};
|
||||
class initfile
|
||||
{
|
||||
public:
|
||||
using pstring = std::string &;
|
||||
using pwstring = std::wstring &;
|
||||
using pcstring = const std::string &;
|
||||
using pcwstring = const std::wstring &;
|
||||
std::wstring filepath;
|
||||
private:
|
||||
template <typename T, typename TRANS = T, typename FN> T read_t (pcwstring section, pcwstring key, T defaultvalue, FN process) const
|
||||
{
|
||||
auto res = read_wstring (section, key, std::to_wstring ((TRANS)defaultvalue));
|
||||
if (IsNormalizeStringEmpty (res)) return defaultvalue;
|
||||
return (T)process (res.c_str ());
|
||||
}
|
||||
template <typename T> bool write_t (pcwstring section, pcwstring key, T value) { return write (section, key, std::to_wstring (value)); }
|
||||
public:
|
||||
initfile (const std::wstring &initpath): filepath (initpath) {}
|
||||
size_t sections (std::vector <std::wstring> §) const { return GetPrivateProfileSectionNamesW (filepath, sect); }
|
||||
size_t sections (std::vector <std::string> §) const { return GetPrivateProfileSectionNamesA (WStringToString (filepath), sect); }
|
||||
bool delete_section (pcwstring section) { return DeletePrivateProfileSectionW (filepath, section); }
|
||||
bool delete_section (pcstring section) { return delete_section (StringToWString (section)); }
|
||||
size_t key_values (pcwstring section, std::vector <std::wstring> &keyvalues) const { return GetPrivateProfileSectionW (filepath, section, keyvalues); }
|
||||
size_t key_values (pcstring section, std::vector <std::string> &keyvalues) const { return GetPrivateProfileSectionA (WStringToString (filepath), section, keyvalues); }
|
||||
size_t keys (pcwstring section, std::vector <std::wstring> &keyvalues) const { return GetPrivateProfileKeysW (filepath, section, keyvalues); }
|
||||
size_t keys (pcstring section, std::vector <std::string> &keyvalues) const { return GetPrivateProfileKeysA (WStringToString (filepath), section, keyvalues); }
|
||||
initsection get_section (pcwstring section) { return initsection (filepath, section); }
|
||||
initsection get_section (pcwstring section) const { return initsection (filepath, section); }
|
||||
std::wstring read_wstring (pcwstring section, pcwstring key, pcwstring dflt = L"") const { return GetPrivateProfileStringW (filepath, section, key, dflt.c_str ()); }
|
||||
std::string read_string (pcwstring section, pcwstring key, pcstring dflt = "") const { return WStringToString (read_wstring (section, key, StringToWString (dflt))); }
|
||||
#define INIT_READ_WARGS(_type_, _dfltvalue_) pcwstring section, pcwstring key, _type_ dflt = _dfltvalue_
|
||||
#define METHOD_INIT_READ(_type_, _typename_, _dfltvalue_, _process_) \
|
||||
_type_ read_##_typename_ (INIT_READ_WARGS (_type_, _dfltvalue_)) const { return read_t (section, key, dflt, _process_); }
|
||||
METHOD_INIT_READ (int, int, 0, _wtoi)
|
||||
METHOD_INIT_READ (unsigned int, uint, 0, _wtou)
|
||||
METHOD_INIT_READ (long, long, 0, _wtol)
|
||||
METHOD_INIT_READ (unsigned long, ulong, 0, _wtoul)
|
||||
METHOD_INIT_READ (long long, llong, 0, _wtoll)
|
||||
METHOD_INIT_READ (unsigned long, ullong, 0, _wtou64)
|
||||
METHOD_INIT_READ (short, short, 0, _wtoi16)
|
||||
METHOD_INIT_READ (unsigned short, ushort, 0, _wtoui16)
|
||||
METHOD_INIT_READ (int16_t, i16, 0, _wtoi16)
|
||||
METHOD_INIT_READ (uint16_t, u16, 0, _wtoui16)
|
||||
METHOD_INIT_READ (int32_t, i32, 0, _wtoi32)
|
||||
METHOD_INIT_READ (uint32_t, u32, 0, _wtoui32)
|
||||
METHOD_INIT_READ (int64_t, i64, 0, _wtoi64)
|
||||
METHOD_INIT_READ (uint64_t, u64, 0, _wtou64)
|
||||
METHOD_INIT_READ (float, float, 0, _wtof)
|
||||
METHOD_INIT_READ (double, double, 0, _wtod)
|
||||
int8_t read_i8 (INIT_READ_WARGS (int8_t, 0)) const { return read_t <int8_t, int16_t> (section, key, dflt, _wtoi8); }
|
||||
uint8_t read_u8 (INIT_READ_WARGS (uint8_t, 0)) const { return read_t <uint8_t, uint16_t> (section, key, dflt, _wtoui8); }
|
||||
bool read_bool (INIT_READ_WARGS (bool, false)) const
|
||||
{
|
||||
std::wnstring res = read_wstring (section, key, dflt ? L"true" : L"false");
|
||||
if (res.empty ()) return dflt;
|
||||
if (res.equals (L"true") || res.equals (L"yes") || res.equals (L"zhen") || res.equals (L"Õæ") || res.equals (L"1") || _wtoi (res.c_str ()) != 0) return true;
|
||||
else if (res.equals (L"false") || res.equals (L"no") || res.equals (L"jia") || res.equals (L"¼Ù") || res.equals (L"0")) return false;
|
||||
else return dflt;
|
||||
}
|
||||
bool read_struct (pcwstring section, pcwstring key, void *output, size_t size) const { return GetPrivateProfileStructW (filepath, section, key, output, size); }
|
||||
template <typename T> bool read_struct (pcwstring section, pcwstring key, T &structinst) const { return read_struct (key, &structinst, sizeof (structinst)); }
|
||||
#ifdef INIT_READ_WARGS
|
||||
#undef INIT_READ_WARGS
|
||||
#endif
|
||||
#ifdef METHOD_INIT_READ
|
||||
#undef METHOD_INIT_READ
|
||||
#endif
|
||||
#define INIT_WRITE_WARGS(_type_) pcwstring section, pcwstring key, _type_ value
|
||||
bool write (INIT_WRITE_WARGS (pcwstring)) { return WritePrivateProfileStringW (filepath, section, key, value); }
|
||||
#define METHOD_INIT_WRITE(_type_) \
|
||||
bool write (INIT_WRITE_WARGS (_type_)) { return write_t (section, key, value); }
|
||||
METHOD_INIT_WRITE (short)
|
||||
METHOD_INIT_WRITE (unsigned short)
|
||||
METHOD_INIT_WRITE (int)
|
||||
METHOD_INIT_WRITE (unsigned int)
|
||||
METHOD_INIT_WRITE (long)
|
||||
METHOD_INIT_WRITE (unsigned long)
|
||||
METHOD_INIT_WRITE (long long)
|
||||
METHOD_INIT_WRITE (unsigned long long)
|
||||
METHOD_INIT_WRITE (float)
|
||||
METHOD_INIT_WRITE (double)
|
||||
bool write (INIT_WRITE_WARGS (bool)) { return write (section, key, value ? L"true" : L"false"); }
|
||||
bool write (INIT_WRITE_WARGS (int8_t)) { return write_t (section, key, (int16_t)value); }
|
||||
bool write (INIT_WRITE_WARGS (uint8_t)) { return write_t (section, key, (uint16_t)value); }
|
||||
bool write (pcwstring section, pcwstring key, LPCWSTR value) { return write (section, key, std::wstring (value ? value : L"")); }
|
||||
bool write (pcstring section, pcstring key, LPCSTR value) { return write (StringToWString (section), StringToWString (key), StringToWString (value)); }
|
||||
bool write (pcwstring section, pcwstring key, void *buf, size_t bufsize) { return WritePrivateProfileStructW (filepath, section, key, buf, bufsize); }
|
||||
initsection operator [] (pcwstring section) { return initsection (filepath, section); }
|
||||
initsection operator [] (pcstring section) { return initsection (filepath, StringToWString (section)); }
|
||||
initsection operator [] (pcwstring section) const { return initsection (filepath, section); }
|
||||
initsection operator [] (pcstring section) const { return initsection (filepath, StringToWString (section)); }
|
||||
#ifdef METHOD_INIT_WRITE
|
||||
#undef METHOD_INIT_WRITE
|
||||
#endif
|
||||
#ifdef INIT_WRITE_WARGS
|
||||
#undef INIT_WRITE_WARGS
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef __cplusplus_cli
|
||||
namespace Win32
|
||||
{
|
||||
using namespace System;
|
||||
using namespace System::Runtime::InteropServices;
|
||||
[ComVisible (true)]
|
||||
public ref class Key
|
||||
{
|
||||
private:
|
||||
String ^filepath = "";
|
||||
String ^section = "";
|
||||
String ^key = "";
|
||||
public:
|
||||
property String ^FilePath { String ^get () { return filepath; }}
|
||||
property String ^Section { String ^get () { return section; }}
|
||||
property String ^KeyName { String ^get () { return key; }}
|
||||
Key (String ^file, String ^sect, String ^k): filepath (file), section (sect), key (k) {}
|
||||
Object ^Get (Object ^dflt)
|
||||
{
|
||||
auto res = GetPrivateProfileStringW (
|
||||
MPStringToStdW (filepath),
|
||||
MPStringToStdW (section),
|
||||
MPStringToStdW (key),
|
||||
dflt ? MPStringToStdW (dflt->ToString ()).c_str () : L""
|
||||
);
|
||||
return CStringToMPString (res);
|
||||
}
|
||||
Object ^Get ()
|
||||
{
|
||||
auto res = GetPrivateProfileStringW (
|
||||
MPStringToStdW (filepath),
|
||||
MPStringToStdW (section),
|
||||
MPStringToStdW (key)
|
||||
);
|
||||
return CStringToMPString (res);
|
||||
}
|
||||
bool Set (Object ^value)
|
||||
{
|
||||
return WritePrivateProfileStringW (
|
||||
MPStringToStdW (filepath),
|
||||
MPStringToStdW (section),
|
||||
MPStringToStdW (key),
|
||||
MPStringToStdW (value ? value->ToString () : L"")
|
||||
);
|
||||
}
|
||||
property Object ^Value { Object ^get () { return Get (); } void set (Object ^value) { Set (value); } }
|
||||
Key %operator = (Object ^value) { Value = value; return *this; }
|
||||
operator String ^ () { return Value->ToString (); }
|
||||
explicit operator bool ()
|
||||
{
|
||||
auto boolstr = Value->ToString ()->Trim ()->ToLower ();
|
||||
if (boolstr == "true" || boolstr == "zhen" || boolstr == "yes" || boolstr == "Õæ") return true;
|
||||
else if (boolstr == "false" || boolstr == "jia" || boolstr == "no" || boolstr == "¼Ù") return false;
|
||||
else return false;
|
||||
}
|
||||
#define OPERATOR_TRANSITION_DEFINE(type, transfunc, defaultret) \
|
||||
operator type () { try { transfunc (Value->ToString ()); } catch (...) { return defaultret; }}
|
||||
OPERATOR_TRANSITION_DEFINE (int8_t, Convert::ToSByte, 0)
|
||||
OPERATOR_TRANSITION_DEFINE (uint8_t, Convert::ToByte, 0)
|
||||
OPERATOR_TRANSITION_DEFINE (int16_t, Convert::ToInt16, 0)
|
||||
OPERATOR_TRANSITION_DEFINE (uint16_t, Convert::ToUInt16, 0)
|
||||
OPERATOR_TRANSITION_DEFINE (int32_t, Convert::ToInt32, 0)
|
||||
OPERATOR_TRANSITION_DEFINE (uint32_t, Convert::ToUInt32, 0)
|
||||
OPERATOR_TRANSITION_DEFINE (int64_t, Convert::ToInt64, 0)
|
||||
OPERATOR_TRANSITION_DEFINE (uint64_t, Convert::ToUInt64, 0)
|
||||
OPERATOR_TRANSITION_DEFINE (float, Convert::ToSingle, 0)
|
||||
OPERATOR_TRANSITION_DEFINE (double, Convert::ToDouble, 0)
|
||||
OPERATOR_TRANSITION_DEFINE (System::Decimal, Convert::ToDecimal, 0)
|
||||
OPERATOR_TRANSITION_DEFINE (System::DateTime, Convert::ToDateTime, Convert::ToDateTime (0))
|
||||
#ifdef OPERATOR_TRANSITION_DEFINE
|
||||
#undef OPERATOR_TRANSITION_DEFINE
|
||||
#endif
|
||||
};
|
||||
[ComVisible (true)]
|
||||
public ref class Section
|
||||
{
|
||||
private:
|
||||
String ^filepath = "";
|
||||
String ^section = "";
|
||||
public:
|
||||
property String ^FilePath { String ^get () { return filepath; } }
|
||||
property String ^SectionName { String ^get () { return section; } }
|
||||
Section (String ^file, String ^sect): filepath (file), section (sect) {}
|
||||
Key ^GetKey (String ^key) { return gcnew Key (filepath, section, key); }
|
||||
Object ^Get (String ^key, Object ^dflt) { return GetKey (key)->Get (dflt); }
|
||||
Object ^Get (String ^key) { return GetKey (key)->Get (); }
|
||||
bool Set (String ^key, Object ^value) { return GetKey (key)->Set (value); }
|
||||
Key ^operator [] (String ^key) { return GetKey (key); }
|
||||
};
|
||||
[ComVisible (true)]
|
||||
public ref class InitConfig
|
||||
{
|
||||
private:
|
||||
String ^filepath = "";
|
||||
public:
|
||||
property String ^FilePath { String ^get () { return filepath; } void set (String ^path) { filepath = path; } }
|
||||
InitConfig (String ^path): filepath (path) {}
|
||||
InitConfig () {}
|
||||
Section ^GetSection (String ^section) { return gcnew Section (filepath, section); }
|
||||
Key ^GetKey (String ^section, String ^key) { return gcnew Key (filepath, section, key); }
|
||||
Object ^Get (String ^section, String ^key, String ^dflt) { return GetKey (section, key)->Get (dflt); }
|
||||
Object ^Get (String ^section, String ^key) { return GetKey (section, key)->Get (); }
|
||||
Section ^Get (String ^section) { return GetSection (section); }
|
||||
bool Set (String ^section, String ^key, String ^value) { return GetKey (section, key)->Set (value); }
|
||||
Section ^operator [] (String ^section) { return GetSection (section); }
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
158
desktopini/main.cpp
Normal file
158
desktopini/main.cpp
Normal file
@@ -0,0 +1,158 @@
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#define HMODULE_MODE_EXE
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
#include <Windows.h>
|
||||
#include "module.h"
|
||||
#include "filepath.h"
|
||||
#include "initfile.h"
|
||||
#include <fstream>
|
||||
|
||||
std::wstring GetWin32ErrorMessage (DWORD err)
|
||||
{
|
||||
if (err == 0) return L"";
|
||||
LPWSTR buffer = nullptr;
|
||||
FormatMessageW (
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
nullptr,
|
||||
err,
|
||||
MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPWSTR)&buffer,
|
||||
0,
|
||||
nullptr
|
||||
);
|
||||
std::wstring msg = buffer ? buffer : L"Unknown error";
|
||||
if (buffer) LocalFree (buffer);
|
||||
return msg;
|
||||
}
|
||||
|
||||
int wmain (int argc, wchar_t** argv)
|
||||
{
|
||||
if (argc <= 1)
|
||||
{
|
||||
std::cout <<
|
||||
"Usage:\n"
|
||||
" desktopini.exe <filepath | dirpath> <section> <key> <value>\n\n"
|
||||
"<filepath>: The tool does not modify the file itself. It writes\n"
|
||||
"information to the desktop.ini file located in the same directory.\n";
|
||||
return 0;
|
||||
}
|
||||
else if (argc < 5)
|
||||
{
|
||||
std::cout << "ERROR: Invalid arguments.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::wstring desktopini;
|
||||
if (IsFileExists (argv [1]))
|
||||
{
|
||||
desktopini = CombinePath (GetFileDirectoryW (argv [1]), L"desktop.ini");
|
||||
std::wcout << L"INFO: Input is a file. Using directory desktop.ini:\n "
|
||||
<< desktopini << L"\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
desktopini = CombinePath (argv [1], L"desktop.ini");
|
||||
std::wcout << L"INFO: Input is a directory. Using desktop.ini:\n "
|
||||
<< desktopini << L"\n";
|
||||
}
|
||||
|
||||
std::wstring parent = GetFileDirectoryW (desktopini);
|
||||
|
||||
// Write INI
|
||||
if (!IsFileExists (desktopini))
|
||||
{
|
||||
std::wfstream wfs (desktopini, std::ios::out);
|
||||
wfs << L"";
|
||||
wfs.close ();
|
||||
}
|
||||
initfile dini (desktopini);
|
||||
auto res = dini [argv [2]] [argv [3]].write (argv [4]);
|
||||
if (res)
|
||||
{
|
||||
std::wcout << L"OK: Wrote INI entry ["
|
||||
<< argv [2] << L"] "
|
||||
<< argv [3] << L" = "
|
||||
<< argv [4] << L"\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::wcout << L"ERROR: Failed to write to desktop.ini.\n";
|
||||
return 2;
|
||||
}
|
||||
|
||||
// desktop.ini attributes
|
||||
DWORD iniattr = GetFileAttributesW (desktopini.c_str ());
|
||||
if (iniattr == INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
DWORD err = GetLastError ();
|
||||
std::wcout << L"WARNING: Cannot query desktop.ini attributes.\n"
|
||||
<< L" Win32 Error "
|
||||
<< err << L": "
|
||||
<< GetWin32ErrorMessage (err) << L"\n";
|
||||
iniattr = FILE_ATTRIBUTE_ARCHIVE;
|
||||
}
|
||||
|
||||
if (!(iniattr & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)))
|
||||
{
|
||||
if (SetFileAttributesW (
|
||||
desktopini.c_str (),
|
||||
iniattr | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM))
|
||||
{
|
||||
std::wcout << L"OK: desktop.ini attributes set to HIDDEN | SYSTEM.\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD err = GetLastError ();
|
||||
std::wcout << L"ERROR: Failed to set attributes on desktop.ini.\n"
|
||||
<< L" Path: " << desktopini << L"\n"
|
||||
<< L" Win32 Error "
|
||||
<< err << L": "
|
||||
<< GetWin32ErrorMessage (err) << L"\n";
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::wcout << L"INFO: desktop.ini already has required attributes.\n";
|
||||
}
|
||||
|
||||
// parent directory attributes
|
||||
DWORD parentattr = GetFileAttributesW (parent.c_str ());
|
||||
if (parentattr == INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
DWORD err = GetLastError ();
|
||||
std::wcout << L"ERROR: Cannot query parent directory attributes.\n"
|
||||
<< L" Path: " << parent << L"\n"
|
||||
<< L" Win32 Error "
|
||||
<< err << L": "
|
||||
<< GetWin32ErrorMessage (err) << L"\n";
|
||||
return 4;
|
||||
}
|
||||
if (!(parentattr & FILE_ATTRIBUTE_SYSTEM))
|
||||
{
|
||||
if (SetFileAttributesW (parent.c_str (), parentattr | FILE_ATTRIBUTE_SYSTEM))
|
||||
{
|
||||
std::wcout << L"OK: Parent directory marked as SYSTEM.\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD err = GetLastError ();
|
||||
std::wcout << L"ERROR: Failed to set SYSTEM attribute on directory.\n"
|
||||
<< L" Path: " << parent << L"\n"
|
||||
<< L" Win32 Error "
|
||||
<< err << L": "
|
||||
<< GetWin32ErrorMessage (err) << L"\n";
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::wcout << L"INFO: Parent directory is already SYSTEM.\n";
|
||||
}
|
||||
std::wcout << L"\nSUCCESS: desktop.ini configuration completed successfully.\n";
|
||||
return 0;
|
||||
}
|
||||
51
desktopini/module.h
Normal file
51
desktopini/module.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#ifdef __cplusplus
|
||||
#ifndef GetCurrentModule_bRefDefault
|
||||
// 在 C++ 中,GetCurrentModule 将会启用默认值。你可以在之前宏定义此默认值。定义宏时别忘了等号“=”
|
||||
// 用法如:HMODULE GetCurrentModule (BOOL bRef GetCurrentModule_bRefDefault)
|
||||
#define GetCurrentModule_bRefDefault = FALSE
|
||||
#endif
|
||||
#else
|
||||
#define GetCurrentModule_bRefDefault
|
||||
#endif
|
||||
HMODULE GetCurrentModule (BOOL bRef GetCurrentModule_bRefDefault)
|
||||
{
|
||||
HMODULE hModule = NULL;
|
||||
if (GetModuleHandleExW (bRef ? GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS : (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
|
||||
| GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT), (LPCWSTR)GetCurrentModule, &hModule))
|
||||
{
|
||||
return hModule;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
HMODULE GetSelfModuleHandle ()
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
return ((::VirtualQuery (GetSelfModuleHandle, &mbi, sizeof (mbi)) != 0)
|
||||
? (HMODULE)mbi.AllocationBase : NULL);
|
||||
}
|
||||
#ifndef GetModuleHandleW_lpModuleNameDefault
|
||||
#define GetModuleHandleW_lpModuleNameDefault NULL
|
||||
#endif
|
||||
#ifndef DEFAULT_HMODULE
|
||||
#ifdef HMODULE_MODE_EXE
|
||||
#define DEFAULT_HMODULE GetModuleHandleW (NULL)
|
||||
#elif defined (HMODULE_MODE_DLL1)
|
||||
#define DEFAULT_HMODULE GetCurrentModule ()
|
||||
#elif defined (HMODULE_MODE_DLL2)
|
||||
#define DEFAULT_HMODULE GetSelfModuleHandle ()
|
||||
#else
|
||||
#define DEFAULT_HMODULE GetModuleHandleW (GetModuleHandleW_lpModuleNameDefault)
|
||||
#endif
|
||||
#endif
|
||||
#undef GetModuleHandleW_lpModuleNameDefault
|
||||
#ifdef __cplusplus
|
||||
#ifndef hModule_DefaultParam
|
||||
// 在 C++ 中,你可以使用此宏“hModule_DefaultParam”来用于给一些函数的形参定义默认值。你可以在之前宏定义此默认值。定义宏时别忘了等号“=”
|
||||
// 用法如:std::wstring GetRCStringSW (UINT resID, HMODULE hModule hModule_DefaultParam)。
|
||||
#define hModule_DefaultParam = DEFAULT_HMODULE
|
||||
#endif
|
||||
#else
|
||||
#define hModule_DefaultParam
|
||||
#endif
|
||||
465
desktopini/nstring.h
Normal file
465
desktopini/nstring.h
Normal file
@@ -0,0 +1,465 @@
|
||||
#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>
|
||||
{
|
||||
bool default_upper = false, default_include_blank_in_str = false;
|
||||
public:
|
||||
using base = std::basic_string <ct, tr, al>;
|
||||
using derive = std::basic_nstring <ct, tr, al>;
|
||||
using typename base::size_type;
|
||||
using typename base::value_type;
|
||||
using base::base;
|
||||
using pstr = ct *;
|
||||
using pcstr = const ct *;
|
||||
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 - 1) {}
|
||||
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); }
|
||||
bool operator == (pcstr &other) const { return equals (other, false); }
|
||||
bool operator != (pcstr &other) const { return !equals (other, false); }
|
||||
bool operator < (pcstr &other) const { return compare (other, false) < 0; }
|
||||
bool operator > (pcstr &other) const { return compare (other, false) > 0; }
|
||||
bool operator <= (pcstr &other) const { return compare (other, false) <= 0; }
|
||||
bool operator >= (pcstr &other) const { return compare (other, false) >= 0; }
|
||||
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;
|
||||
}
|
||||
10
desktopini/raii.h
Normal file
10
desktopini/raii.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include <functional>
|
||||
typedef struct raii
|
||||
{
|
||||
std::function <void ()> endtask = nullptr;
|
||||
raii (std::function <void ()> pFunc = nullptr): endtask (pFunc) {}
|
||||
~raii () { if (endtask) endtask (); }
|
||||
raii (const raii &) = delete;
|
||||
raii (raii &&) = delete;
|
||||
} destruct;
|
||||
154
desktopini/strcmp.h
Normal file
154
desktopini/strcmp.h
Normal file
@@ -0,0 +1,154 @@
|
||||
#pragma once
|
||||
#include <Shlwapi.h>
|
||||
#include "nstring.h"
|
||||
#ifdef __cplusplus
|
||||
#define ptrnull(ptr) (!(ptr))
|
||||
#else
|
||||
#define ptrnull(ptr) ((ptr) == NULL)
|
||||
#endif
|
||||
#define ptrvalid(ptr) (!ptrnull (ptr))
|
||||
// 用于 char * 或 WCHAR * 字符串(结尾为 NULL),判断是否为非空字符串:指针有效且长度大于 0。千万不能是野指针,否则一定会崩溃!
|
||||
#define strvalid(strptr) (ptrvalid (strptr) && *(strptr))
|
||||
// 用于 char * 或 WCHAR * 字符串(结尾为 NULL),判断是否为空字符串:指针为 NULL 或长度为 0。千万不能是野指针,否则一定会崩溃!
|
||||
#define strnull(strptr) (ptrnull (strptr) || !*(strptr))
|
||||
typedef std::wnstring strlabel, StringLabel;
|
||||
std::wstring StringTrim (const std::wstring &str) { return std::wnstring::trim (str); }
|
||||
std::string StringTrim (const std::string &str) { return std::nstring::trim (str); }
|
||||
#define StringToUpper l0km::toupper
|
||||
#define StringToLower l0km::tolower
|
||||
int LabelCompare (const std::wstring &l1, const std::wstring &l2)
|
||||
{
|
||||
return std::wnstring::compare (l1, l2);
|
||||
}
|
||||
int LabelCompare (const std::string &l1, const std::string &l2)
|
||||
{
|
||||
return std::nstring::compare (l1, l2);
|
||||
}
|
||||
bool LabelEqual (const std::wstring &l1, const std::wstring &l2)
|
||||
{
|
||||
return std::wnstring::equals (l1, l2);
|
||||
}
|
||||
bool LabelEqual (const std::string &l1, const std::string &l2)
|
||||
{
|
||||
return std::wnstring::equals (l1, l2);
|
||||
}
|
||||
bool LabelEmpty (const std::wstring &str) { return std::wnstring::empty (str); }
|
||||
bool LabelEmpty (const std::string &str) { return std::nstring::empty (str); }
|
||||
#define LabelNoEmpty(_str_) (!LabelEmpty (_str_))
|
||||
int InStr (const std::string &text, const std::string &keyword, bool ignoreCase = false)
|
||||
{
|
||||
std::string s1, s2;
|
||||
if (ignoreCase)
|
||||
{
|
||||
s1 = StringToUpper (text);
|
||||
s2 = StringToUpper (keyword);
|
||||
}
|
||||
else
|
||||
{
|
||||
s1 = text;
|
||||
s2 = keyword;
|
||||
}
|
||||
const char *found = StrStrIA (s1.c_str (), s2.c_str ());
|
||||
if (!found)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return found - text.c_str ();
|
||||
}
|
||||
int InStr (const std::wstring &text, const std::wstring &keyword, bool ignoreCase = false)
|
||||
{
|
||||
std::wstring s1, s2;
|
||||
if (ignoreCase)
|
||||
{
|
||||
s1 = StringToUpper (text);
|
||||
s2 = StringToUpper (keyword);
|
||||
}
|
||||
else
|
||||
{
|
||||
s1 = text;
|
||||
s2 = keyword;
|
||||
}
|
||||
const WCHAR *found = StrStrIW (s1.c_str (), s2.c_str ());
|
||||
if (!found)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return found - text.c_str ();
|
||||
}
|
||||
bool StrInclude (const std::string &text, const std::string &keyword, bool ignoreCase = false)
|
||||
{
|
||||
std::string s1, s2;
|
||||
if (ignoreCase)
|
||||
{
|
||||
s1 = StringToUpper (text);
|
||||
s2 = StringToUpper (keyword);
|
||||
}
|
||||
else
|
||||
{
|
||||
s1 = text;
|
||||
s2 = keyword;
|
||||
}
|
||||
const char *found = StrStrIA (s1.c_str (), s2.c_str ());
|
||||
if (!found) return false;
|
||||
return true;
|
||||
}
|
||||
bool StrInclude (const std::wstring &text, const std::wstring &keyword, bool ignoreCase = false)
|
||||
{
|
||||
std::wstring s1, s2;
|
||||
if (ignoreCase)
|
||||
{
|
||||
s1 = StringToUpper (text);
|
||||
s2 = StringToUpper (keyword);
|
||||
}
|
||||
else
|
||||
{
|
||||
s1 = text;
|
||||
s2 = keyword;
|
||||
}
|
||||
const WCHAR *found = StrStrIW (s1.c_str (), s2.c_str ());
|
||||
if (!found) return false;
|
||||
return true;
|
||||
}
|
||||
// 该函数帮助构成 "<str1>\0<str2>\0" 这种字符串,用于通用对话框中的文件框
|
||||
LPCWSTR strcpynull (LPWSTR dest, LPCWSTR endwith, size_t bufsize)
|
||||
{
|
||||
if (!dest || !endwith || bufsize == 0)
|
||||
return dest;
|
||||
if (dest [0] == L'\0' && bufsize > 1)
|
||||
{
|
||||
dest [1] = L'\0';
|
||||
}
|
||||
size_t pos = 0;
|
||||
while (pos < bufsize - 1)
|
||||
{
|
||||
if (dest [pos] == L'\0' && dest [pos + 1] == L'\0')
|
||||
{
|
||||
if (dest [0]) pos ++;
|
||||
break;
|
||||
}
|
||||
pos ++;
|
||||
}
|
||||
size_t i = 0;
|
||||
while (pos < bufsize - 1 && endwith [i] != L'\0')
|
||||
{
|
||||
dest [pos ++] = endwith [i ++];
|
||||
}
|
||||
if (pos < bufsize)
|
||||
{
|
||||
dest [pos] = L'\0';
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
// 取文本左边,注意:长度指的是文本字符数,比如“ch”的长度为2
|
||||
std::wstring GetStringLeft (const std::wstring &str, size_t length)
|
||||
{
|
||||
std::vector <WCHAR> buf (length + 1);
|
||||
lstrcpynW (buf.data (), str.c_str (), length + 1);
|
||||
return buf.data ();
|
||||
}
|
||||
// 取文本右边
|
||||
std::wstring GetStringRight (const std::wstring &str, size_t length)
|
||||
{
|
||||
if (length >= str.length ()) return str;
|
||||
return str.substr (str.length () - length, length).c_str ();
|
||||
}
|
||||
33
desktopini/strcode.h
Normal file
33
desktopini/strcode.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <Windows.h>
|
||||
#include <locale>
|
||||
#include <codecvt>
|
||||
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;
|
||||
}
|
||||
std::string WStringToString (const std::wstring &wstr, UINT codePage = CP_ACP)
|
||||
{
|
||||
if (wstr.empty ()) return std::string ();
|
||||
int len = WideCharToMultiByte (codePage, 0, wstr.c_str (), -1, nullptr, 0, nullptr, nullptr);
|
||||
if (len == 0) return std::string ();
|
||||
std::string str (len - 1, '\0');
|
||||
WideCharToMultiByte (codePage, 0, wstr.c_str (), -1, &str [0], len, nullptr, nullptr);
|
||||
return str;
|
||||
}
|
||||
std::string WStringToUtf8 (const std::wstring& ws)
|
||||
{
|
||||
static std::wstring_convert <std::codecvt_utf8_utf16 <wchar_t>> conv;
|
||||
return conv.to_bytes (ws);
|
||||
}
|
||||
std::wstring Utf8ToWString (const std::string& s)
|
||||
{
|
||||
static std::wstring_convert <std::codecvt_utf8_utf16 <wchar_t>> conv;
|
||||
return conv.from_bytes (s);
|
||||
}
|
||||
124
desktopini/syncutil.h
Normal file
124
desktopini/syncutil.h
Normal file
@@ -0,0 +1,124 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
class CriticalSection
|
||||
{
|
||||
private:
|
||||
CRITICAL_SECTION m_csection;
|
||||
public:
|
||||
CriticalSection (DWORD spinCount = 4000) { InitializeCriticalSectionAndSpinCount (&m_csection, spinCount); }
|
||||
CriticalSection (const CriticalSection &) = delete;
|
||||
CriticalSection &operator = (const CriticalSection &) = delete;
|
||||
~CriticalSection () { DeleteCriticalSection (&m_csection); }
|
||||
void Lock () { EnterCriticalSection (&m_csection); }
|
||||
void Unlock () { LeaveCriticalSection (&m_csection); }
|
||||
bool TryLock () { return TryEnterCriticalSection (&m_csection) != 0; }
|
||||
class ScopedLock
|
||||
{
|
||||
public:
|
||||
explicit ScopedLock (CriticalSection &cs): m_cs (cs) { m_cs.Lock (); }
|
||||
~ScopedLock () { m_cs.Unlock (); }
|
||||
ScopedLock (const ScopedLock &) = delete;
|
||||
ScopedLock &operator = (const ScopedLock &) = delete;
|
||||
private:
|
||||
CriticalSection& m_cs;
|
||||
};
|
||||
};
|
||||
|
||||
#define CreateScopedLock(_obj_cs_) CriticalSection::ScopedLock _obj_cs_##sl (_obj_cs_)
|
||||
|
||||
#ifdef __cplusplus_cli
|
||||
ref struct TaskStructEvent
|
||||
{
|
||||
typedef array <Object ^> args;
|
||||
typedef void (*eventfunc) (... args ^args);
|
||||
eventfunc post;
|
||||
args ^postargs;
|
||||
public:
|
||||
TaskStructEvent (
|
||||
eventfunc prefunc,
|
||||
args ^preargs,
|
||||
eventfunc postfunc,
|
||||
args ^postargs
|
||||
): post (postfunc), postargs (postargs)
|
||||
{
|
||||
if (prefunc == nullptr) {
|
||||
#pragma message("警告:预处理函数指针为空,可能跳过初始化操作")
|
||||
}
|
||||
if (prefunc)
|
||||
{
|
||||
if (preargs)
|
||||
{
|
||||
#pragma region 参数验证示例
|
||||
/*
|
||||
实际项目中应添加具体类型检查,例如:
|
||||
ValidateArgsType<Button^>(preargs);
|
||||
*/
|
||||
#pragma endregion
|
||||
prefunc (preargs);
|
||||
}
|
||||
else prefunc (gcnew args {});
|
||||
}
|
||||
}
|
||||
~TaskStructEvent ()
|
||||
{
|
||||
if (post == nullptr)
|
||||
{
|
||||
#pragma message("警告:后处理函数指针为空,资源可能无法正确释放")
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
if (postargs) { post (postargs); }
|
||||
else { post (gcnew args {}); }
|
||||
}
|
||||
catch (Exception ^e)
|
||||
{
|
||||
#pragma message("注意:后处理中的异常需手动处理")
|
||||
}
|
||||
}
|
||||
};
|
||||
#define CreateStructEvent(_varname_taskname_, _func_construct_, _args_construct_, _func_destruct_, _args_destruct_) \
|
||||
TaskStructEvent _varname_taskname_ ( \
|
||||
_func_construct_, \
|
||||
_args_construct_, \
|
||||
_func_destruct_, \
|
||||
_args_destruct_ \
|
||||
)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
template <typename PreCallback, typename PostCallback> class ScopedEvent
|
||||
{
|
||||
public:
|
||||
ScopedEvent (PreCallback &&pre, PostCallback &&post)
|
||||
: m_post (std::forward <PostCallback> (post))
|
||||
{
|
||||
static_assert (
|
||||
std::is_constructible <std::function <void ()>, PreCallback>::value,
|
||||
"预处理回调必须可转换为 void () 类型"
|
||||
);
|
||||
|
||||
if (pre) { pre (); }
|
||||
}
|
||||
~ScopedEvent () noexcept
|
||||
{
|
||||
if (m_post) { m_post (); }
|
||||
}
|
||||
ScopedEvent (const ScopedEvent &) = delete;
|
||||
ScopedEvent &operator = (const ScopedEvent &) = delete;
|
||||
ScopedEvent (ScopedEvent &&) = default;
|
||||
ScopedEvent &operator =(ScopedEvent &&) = default;
|
||||
private:
|
||||
PostCallback m_post;
|
||||
};
|
||||
template <typename PreFunc, typename PostFunc> auto make_scoped_event (PreFunc &&pre, PostFunc &&post)
|
||||
{
|
||||
return ScopedEvent <PreFunc, PostFunc> (
|
||||
std::forward <PreFunc> (pre),
|
||||
std::forward <PostFunc> (post)
|
||||
);
|
||||
}
|
||||
#endif
|
||||
267
desktopini/typestrans.h
Normal file
267
desktopini/typestrans.h
Normal file
@@ -0,0 +1,267 @@
|
||||
#pragma once
|
||||
#ifndef _CRT_SECURE_NO_WARNINGS
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
#include <Windows.h>
|
||||
#ifdef __cplusplus
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstdbool>
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <cstdint>
|
||||
#endif
|
||||
unsigned _wtou (const wchar_t *str)
|
||||
{
|
||||
unsigned value = 0;
|
||||
if (str)
|
||||
{
|
||||
swscanf (str, L"%u", &value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
unsigned long _wtoul (const wchar_t *str)
|
||||
{
|
||||
unsigned value = 0;
|
||||
if (str)
|
||||
{
|
||||
swscanf (str, L"%lu", &value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
unsigned long long _wtou64 (const wchar_t *str)
|
||||
{
|
||||
unsigned long long value = 0;
|
||||
if (str)
|
||||
{
|
||||
swscanf (str, L"%llu", &value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
double _wtod (const wchar_t *str)
|
||||
{
|
||||
if (!str || !*str) return 0.0; // 避免空指针或空字符串
|
||||
double value = 0.0;
|
||||
if (swscanf (str, L"%lg", &value) == 1)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
return 0.0; // 解析失败时返回 0.0
|
||||
}
|
||||
unsigned atou (const char *str)
|
||||
{
|
||||
unsigned value = 0;
|
||||
if (str)
|
||||
{
|
||||
sscanf (str, "%u", &value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
unsigned long atoul (const char *str)
|
||||
{
|
||||
unsigned value = 0;
|
||||
if (str)
|
||||
{
|
||||
sscanf (str, "%lu", &value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
unsigned long long atou64 (const char *str)
|
||||
{
|
||||
unsigned long long value = 0;
|
||||
if (str)
|
||||
{
|
||||
sscanf (str, "%llu", &value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
double atod (const char *str)
|
||||
{
|
||||
if (!str || !*str) return 0.0; // 避免空指针或空字符串
|
||||
double value = 0.0;
|
||||
if (sscanf (str, "%lg", &value) == 1)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
return 0.0; // 解析失败时返回 0.0
|
||||
}
|
||||
int8_t atoi8 (const char *str)
|
||||
{
|
||||
int value = 0;
|
||||
if (str) sscanf (str, "%d", &value);
|
||||
return (int8_t)value;
|
||||
}
|
||||
int16_t atoi16 (const char *str)
|
||||
{
|
||||
int value = 0;
|
||||
if (str) sscanf (str, "%d", &value);
|
||||
return (int16_t)value;
|
||||
}
|
||||
int32_t atoi32 (const char *str)
|
||||
{
|
||||
int32_t value = 0;
|
||||
if (str) sscanf (str, "%d", &value);
|
||||
return value;
|
||||
}
|
||||
uint8_t atoui8 (const char *str)
|
||||
{
|
||||
unsigned value = 0;
|
||||
if (str) sscanf (str, "%u", &value);
|
||||
return (uint8_t)value;
|
||||
}
|
||||
uint16_t atoui16 (const char *str)
|
||||
{
|
||||
unsigned value = 0;
|
||||
if (str) sscanf (str, "%u", &value);
|
||||
return (uint16_t)value;
|
||||
}
|
||||
uint32_t atoui32 (const char *str)
|
||||
{
|
||||
uint32_t value = 0;
|
||||
if (str) sscanf (str, "%u", &value);
|
||||
return value;
|
||||
}
|
||||
int8_t _wtoi8 (const wchar_t *str)
|
||||
{
|
||||
int value = 0;
|
||||
if (str) swscanf (str, L"%d", &value);
|
||||
return (int8_t)value;
|
||||
}
|
||||
int16_t _wtoi16 (const wchar_t *str)
|
||||
{
|
||||
int value = 0;
|
||||
if (str) swscanf (str, L"%d", &value);
|
||||
return (int16_t)value;
|
||||
}
|
||||
int32_t _wtoi32 (const wchar_t *str)
|
||||
{
|
||||
int32_t value = 0;
|
||||
if (str) swscanf (str, L"%d", &value);
|
||||
return value;
|
||||
}
|
||||
uint8_t _wtoui8 (const wchar_t *str)
|
||||
{
|
||||
unsigned value = 0;
|
||||
if (str) swscanf (str, L"%u", &value);
|
||||
return (uint8_t)value;
|
||||
}
|
||||
uint16_t _wtoui16 (const wchar_t *str)
|
||||
{
|
||||
unsigned value = 0;
|
||||
if (str) swscanf (str, L"%u", &value);
|
||||
return (uint16_t)value;
|
||||
}
|
||||
uint32_t _wtoui32 (const wchar_t *str)
|
||||
{
|
||||
uint32_t value = 0;
|
||||
if (str) swscanf (str, L"%u", &value);
|
||||
return value;
|
||||
}
|
||||
int64_t atoi64 (const char *str)
|
||||
{
|
||||
int64_t value = 0;
|
||||
if (str) sscanf (str, "%lld", &value);
|
||||
return value;
|
||||
}
|
||||
|
||||
EXTERN_C int StringToIntA (const char *str) { return atoi (str); }
|
||||
EXTERN_C int StringToIntW (const WCHAR *str) { return _wtoi (str); }
|
||||
EXTERN_C unsigned StringToUnsignedA (const char *str) { return atou (str); }
|
||||
EXTERN_C unsigned StringToUnsignedW (const WCHAR *str) { return _wtou (str); }
|
||||
EXTERN_C bool StringToBoolA (const char *str)
|
||||
{
|
||||
char buf [32] = {0};
|
||||
strcpy (buf, str);
|
||||
for (int cnt = 0; buf [cnt]; cnt ++) buf [cnt] = tolower (buf [cnt]);
|
||||
return !strcmp (buf, "true") ||
|
||||
!strcmp (buf, "yes") ||
|
||||
!strcmp (buf, "ok") ||
|
||||
!strcmp (buf, "sure") ||
|
||||
!strcmp (buf, "okay") ||
|
||||
!strcmp (buf, "zhen") ||
|
||||
!strcmp (buf, "真");
|
||||
}
|
||||
EXTERN_C bool StringToBoolW (const WCHAR *str)
|
||||
{
|
||||
WCHAR buf [32] = {0};
|
||||
lstrcpyW (buf, str);
|
||||
for (int cnt = 0; buf [cnt]; cnt ++) buf [cnt] = tolower (buf [cnt]);
|
||||
return !lstrcmpW (buf, L"true") ||
|
||||
!lstrcmpW (buf, L"yes") ||
|
||||
!lstrcmpW (buf, L"ok") ||
|
||||
!lstrcmpW (buf, L"sure") ||
|
||||
!lstrcmpW (buf, L"okay") ||
|
||||
!lstrcmpW (buf, L"zhen") ||
|
||||
!lstrcmpW (buf, L"真");
|
||||
}
|
||||
EXTERN_C long StringToLongA (const char *str) { return atol (str); }
|
||||
EXTERN_C long StringToLongW (const WCHAR *str) { return _wtol (str); }
|
||||
EXTERN_C unsigned long StringToULongA (const char *str) { return atoul (str); }
|
||||
EXTERN_C unsigned long StringToULongW (const WCHAR *str) { return _wtoul (str); }
|
||||
EXTERN_C long long StringToLongLongA (const char *str) { return atoll (str); }
|
||||
EXTERN_C long long StringToLongLongW (const WCHAR *str) { return _wtoll (str); }
|
||||
EXTERN_C unsigned long long StringToULongLongA (const char *str) { return atou64 (str); }
|
||||
EXTERN_C unsigned long long StringToULongLongW (const WCHAR *str) { return _wtou64 (str); }
|
||||
EXTERN_C float StringToFloatA (const char *str) { return atof (str); }
|
||||
EXTERN_C float StringToFloatW (const WCHAR *str) { return _wtof (str); }
|
||||
EXTERN_C double StringToDoubleA (const char *str) { return atod (str); }
|
||||
EXTERN_C double StringToDoubleW (const WCHAR *str) { return _wtod (str); }
|
||||
|
||||
#ifdef __cplusplus
|
||||
int StringToInt (LPCSTR str) { return StringToIntA (str); }
|
||||
int StringToInt (LPCWSTR str) { return StringToIntW (str); }
|
||||
unsigned StringToUnsigned (LPCSTR str) { return StringToUnsignedA (str); }
|
||||
unsigned StringToUnsigned (LPCWSTR str) { return StringToUnsignedW (str); }
|
||||
bool StringToBool (LPCSTR str) { return StringToBoolA (str); }
|
||||
bool StringToBool (LPCWSTR str) { return StringToBoolW (str); }
|
||||
long StringToLong (LPCSTR str) { return StringToLongA (str); }
|
||||
long StringToLong (LPCWSTR str) { return StringToLongW (str); }
|
||||
unsigned long StringToULong (LPCSTR str) { return StringToULongA (str); }
|
||||
unsigned long StringToULong (LPCWSTR str) { return StringToULongW (str); }
|
||||
long long StringToLongLong (LPCSTR str) { return StringToLongLongA (str); }
|
||||
long long StringToLongLong (LPCWSTR str) { return StringToLongLongW (str); }
|
||||
unsigned long long StringToULongLong (LPCSTR str) { return StringToULongLongA (str); }
|
||||
unsigned long long StringToULongLong (LPCWSTR str) { return StringToULongLongW (str); }
|
||||
float StringToFloat (LPCSTR str) { return StringToFloatA (str); }
|
||||
float StringToFloat (LPCWSTR str) { return StringToFloatW (str); }
|
||||
double StringToDouble (LPCSTR str) { return StringToDoubleA (str); }
|
||||
double StringToDouble (LPCWSTR str) { return StringToDoubleW (str); }
|
||||
#endif
|
||||
|
||||
#if defined (__cplusplus) && defined (__cplusplus_cli)
|
||||
using namespace System;
|
||||
#define toInt(_String_Managed_Object_) Int32::Parse (_String_Managed_Object_)
|
||||
#define objToInt(_Object_Managed_) Convert::ToInt32 (_Object_Managed_)
|
||||
#define toDouble(_String_Managed_Object_) Double::Parse (_String_Managed_Object_)
|
||||
#define objToDouble(_Object_Managed_) Convert::ToDouble (_Object_Managed_)
|
||||
#define toBool(_String_Managed_Object_) Boolean::Parse (_String_Managed_Object_)
|
||||
bool objToBool (Object ^result)
|
||||
{
|
||||
if (!result) return false;
|
||||
try
|
||||
{
|
||||
String ^strValue = safe_cast <String ^> (result);
|
||||
return (strValue->ToLower () == "on");
|
||||
}
|
||||
catch (InvalidCastException ^)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Convert::ToBoolean (result);
|
||||
}
|
||||
catch (InvalidCastException ^)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#define toDateTime(_String_Managed_Object_) DateTime::Parse (_String_Managed_Object_)
|
||||
#define toDateTimeObj(_Object_Managed_) Convert::ToDateTime (_Object_Managed_)
|
||||
#define objectToType(_Object_Managed_, _Type_Name_) Convert::To##_Type_Name_ (_Object_Managed_)
|
||||
#endif
|
||||
193
desktopini/version.h
Normal file
193
desktopini/version.h
Normal file
@@ -0,0 +1,193 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
typedef uint64_t UINT64;
|
||||
typedef int64_t INT64;
|
||||
typedef uint16_t UINT16;
|
||||
typedef struct version
|
||||
{
|
||||
UINT16 major = 0, minor = 0, build = 0, revision = 0;
|
||||
version (UINT64 value):
|
||||
major ((value >> 0x30) & 0xFFFF), minor ((value >> 0x20) & 0xFFFF),
|
||||
build ((value >> 0x10) & 0xFFFF), revision ((value) & 0xFFFF) {}
|
||||
version (UINT16 major, UINT16 minor, UINT16 build, UINT16 revision):
|
||||
major (major), minor (minor), build (build), revision (revision) {}
|
||||
version (const std::wstring &verstr) { this->interpret (verstr); }
|
||||
version (const std::string &verstr) { this->interpret (verstr); }
|
||||
version () {}
|
||||
version (const version &other): major (other.major), minor (other.minor), build (other.build), revision (other.revision) {}
|
||||
version (version &&other) noexcept: major (other.major), minor (other.minor), build (other.build), revision (other.revision) {}
|
||||
version &operator = (const version &other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
major = other.major;
|
||||
minor = other.minor;
|
||||
build = other.build;
|
||||
revision = other.revision;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
version &operator = (version &&other) noexcept
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
major = other.major;
|
||||
minor = other.minor;
|
||||
build = other.build;
|
||||
revision = other.revision;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
version &operator = (UINT64 value) { this->data (value); return *this; }
|
||||
UINT64 data () const { return (((UINT64)major) << 48) | (((UINT64)minor) << 32) | (((UINT64)build) << 16) | ((UINT64)revision); }
|
||||
UINT64 data (UINT64 value)
|
||||
{
|
||||
major = (value >> 48) & 0xFFFF;
|
||||
minor = (value >> 32) & 0xFFFF;
|
||||
build = (value >> 16) & 0xFFFF;
|
||||
revision = value & 0xFFFF;
|
||||
return value;
|
||||
}
|
||||
std::wstring stringifyw () const
|
||||
{
|
||||
std::wstringstream ss;
|
||||
ss << major << L'.' << minor << L'.' << build << L'.' << revision;
|
||||
return ss.str ();
|
||||
}
|
||||
std::string stringify () const
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << major << '.' << minor << '.' << build << '.' << revision;
|
||||
return ss.str ();
|
||||
}
|
||||
version &interpret (const std::wstring &verstr)
|
||||
{
|
||||
auto result = split (verstr);
|
||||
if (result.size () > 0) this->major = _wtoi (result [0].c_str ());
|
||||
if (result.size () > 1) this->minor = _wtoi (result [1].c_str ());
|
||||
if (result.size () > 2) this->build = _wtoi (result [2].c_str ());
|
||||
if (result.size () > 3) this->revision = _wtoi (result [3].c_str ());
|
||||
return *this;
|
||||
}
|
||||
version &interpret (const std::string &verstr)
|
||||
{
|
||||
auto result = split (verstr);
|
||||
if (result.size () > 0) this->major = atoi (result [0].c_str ());
|
||||
if (result.size () > 1) this->minor = atoi (result [1].c_str ());
|
||||
if (result.size () > 2) this->build = atoi (result [2].c_str ());
|
||||
if (result.size () > 3) this->revision = atoi (result [3].c_str ());
|
||||
return *this;
|
||||
}
|
||||
bool empty () const { return *(UINT64 *)this == 0; }
|
||||
friend bool operator == (const version &l, const version &r) { return *(UINT64 *)&l == *(UINT64 *)&r; }
|
||||
friend bool operator == (const version &l, const UINT64 &r) { return l.data () == r; }
|
||||
friend bool operator == (const UINT64 &r, const version &l) { return l.data () == r; }
|
||||
friend bool operator < (const version &l, const version &r) { return l.data () < r.data (); }
|
||||
friend bool operator > (const version &l, const version &r) { return l.data () > r.data (); }
|
||||
friend bool operator <= (const version &l, const version &r) { return l.data () <= r.data (); }
|
||||
friend bool operator >= (const version &l, const version &r) { return l.data () >= r.data (); }
|
||||
friend bool operator != (const version &l, const version &r) { return *(UINT64 *)&l != *(UINT64 *)&r; }
|
||||
explicit operator bool () const { return !this->empty (); }
|
||||
bool operator ! () { return this->empty (); }
|
||||
friend std::ostream &operator << (std::ostream &o, const version &v) { return o << v.major << '.' << v.minor << '.' << v.build << '.' << v.revision; }
|
||||
friend std::wostream &operator << (std::wostream &o, const version &v) { return o << v.major << '.' << v.minor << '.' << v.build << '.' << v.revision; }
|
||||
bool equals (const version &r) const { return *this == r; }
|
||||
INT64 compare (const version &r) const { return this->data () - r.data (); }
|
||||
static version parse (const std::wstring &value) { return version (value); }
|
||||
static version parse (const std::string &value) { return version (value); }
|
||||
static std::wstring stringifyw (const version &v) { return v.stringifyw (); }
|
||||
static std::string stringify (const version &v) { return v.stringify (); }
|
||||
static bool equals (const version &l, const version &r) { return l == r; }
|
||||
static INT64 compare (const version &l, const version &r) { return l.data () - r.data (); }
|
||||
static version decode (UINT64 value) { return version (value); }
|
||||
static UINT64 encode (const version &v) { return v.data (); }
|
||||
protected:
|
||||
template <typename StringType> std::vector <StringType> split (const StringType &str, typename StringType::value_type delimiter1 = '.', typename StringType::value_type delimiter2 = ',')
|
||||
{
|
||||
std::vector <StringType> result;
|
||||
std::basic_stringstream<typename StringType::value_type> ss (str);
|
||||
StringType segment;
|
||||
while (std::getline (ss, segment, delimiter1))
|
||||
{
|
||||
size_t pos = 0;
|
||||
while ((pos = segment.find (delimiter2)) != StringType::npos)
|
||||
{
|
||||
result.push_back (segment.substr (0, pos));
|
||||
segment.erase (0, pos + 1);
|
||||
}
|
||||
if (!segment.empty ()) result.push_back (segment);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} Version;
|
||||
|
||||
#ifdef __cplusplus_cli
|
||||
using namespace System;
|
||||
using namespace System::Runtime::InteropServices;
|
||||
[ComVisible (true)]
|
||||
public ref class _I_Version
|
||||
{
|
||||
private:
|
||||
UINT16 major = 0, minor = 0, build = 0, revision = 0;
|
||||
public:
|
||||
property UINT16 Major { UINT16 get () { return major; } void set (UINT16 value) { major = value; } }
|
||||
property UINT16 Minor { UINT16 get () { return minor; } void set (UINT16 value) { minor = value; } }
|
||||
property UINT16 Build { UINT16 get () { return build; } void set (UINT16 value) { build = value; } }
|
||||
property UINT16 Revision { UINT16 get () { return revision; } void set (UINT16 value) { revision = value; } }
|
||||
property array <UINT16> ^Data
|
||||
{
|
||||
array <UINT16> ^get ()
|
||||
{
|
||||
return gcnew array <UINT16> {
|
||||
major, minor, build, revision
|
||||
};
|
||||
}
|
||||
void set (array <UINT16> ^arr)
|
||||
{
|
||||
major = minor = build = revision = 0;
|
||||
for (size_t i = 0; i < arr->Length; i ++)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: major = arr [i]; break;
|
||||
case 1: minor = arr [i]; break;
|
||||
case 2: build = arr [i]; break;
|
||||
case 3: revision = arr [i]; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
property String ^DataStr
|
||||
{
|
||||
String ^get () { return Stringify (); }
|
||||
void set (String ^str) { Parse (str); }
|
||||
}
|
||||
_I_Version (UINT16 p_ma, UINT16 p_mi, UINT16 p_b, UINT16 p_r):
|
||||
major (p_ma), minor (p_mi), build (p_b), revision (p_r) {}
|
||||
_I_Version (UINT16 p_ma, UINT16 p_mi, UINT16 p_b):
|
||||
major (p_ma), minor (p_mi), build (p_b), revision (0) {}
|
||||
_I_Version (UINT16 p_ma, UINT16 p_mi):
|
||||
major (p_ma), minor (p_mi), build (0), revision (0) {}
|
||||
_I_Version (UINT16 p_ma):
|
||||
major (p_ma), minor (0), build (0), revision (0) {}
|
||||
_I_Version () {}
|
||||
_I_Version %Parse (String ^ver)
|
||||
{
|
||||
auto strarr = ver->Split ('.');
|
||||
auto arr = gcnew array <UINT16> (4);
|
||||
for (size_t i = 0; i < strarr->Length; i ++)
|
||||
{
|
||||
try { arr [i] = Convert::ToUInt16 (strarr [i]); }
|
||||
catch (...) {}
|
||||
}
|
||||
Data = arr;
|
||||
return *this;
|
||||
}
|
||||
String ^Stringify () { return major + "." + minor + "." + build + "." + revision; }
|
||||
String ^ToString () override { return Stringify (); }
|
||||
bool Valid () { return Major != 0 && Minor != 0 && Build != 0 && Revision != 0; }
|
||||
};
|
||||
#endif
|
||||
BIN
notice/notice.rc
BIN
notice/notice.rc
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
6278
others/Autosave/autosave_2025-12-07_22-40-28.suf
Normal file
6278
others/Autosave/autosave_2025-12-07_22-40-28.suf
Normal file
File diff suppressed because it is too large
Load Diff
@@ -683,11 +683,11 @@
|
||||
<SCDesk>0</SCDesk>
|
||||
<SCQLaunch>0</SCQLaunch>
|
||||
<SCStartPinOption>0</SCStartPinOption>
|
||||
<SCCust>0</SCCust>
|
||||
<CustSCPath/>
|
||||
<SCDesc>Settings</SCDesc>
|
||||
<SCCust>1</SCCust>
|
||||
<CustSCPath>%StartProgramsFolderCommon%\\%AppShortcutFolderName%</CustSCPath>
|
||||
<SCDesc>Update</SCDesc>
|
||||
<SCComment/>
|
||||
<SCArgs/>
|
||||
<SCArgs>appinstaller update /autoupdate</SCArgs>
|
||||
<SCWork/>
|
||||
<UseExtIco>0</UseExtIco>
|
||||
<IcoFN/>
|
||||
@@ -880,6 +880,79 @@
|
||||
<CRC>0</CRC>
|
||||
<StoreOnly>0</StoreOnly>
|
||||
</FileData>
|
||||
<FileData>
|
||||
<FldRef>0</FldRef>
|
||||
<FullName>E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstallerReset\Release\desktopini.exe</FullName>
|
||||
<FileName>desktopini.exe</FileName>
|
||||
<Source>E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstallerReset\Release</Source>
|
||||
<Ext>exe</Ext>
|
||||
<RTSource>µµ°¸</RTSource>
|
||||
<Desc/>
|
||||
<Recurse>1</Recurse>
|
||||
<MatchMode>0</MatchMode>
|
||||
<Dest>%AppFolder%</Dest>
|
||||
<Overwrite>1</Overwrite>
|
||||
<Backup>0</Backup>
|
||||
<Protect>0</Protect>
|
||||
<InstallOrder>1000</InstallOrder>
|
||||
<SCStartRoot>0</SCStartRoot>
|
||||
<SCStartProgs>0</SCStartProgs>
|
||||
<SCAppFld>0</SCAppFld>
|
||||
<SCStartup>0</SCStartup>
|
||||
<SCDesk>0</SCDesk>
|
||||
<SCQLaunch>0</SCQLaunch>
|
||||
<SCStartPinOption>0</SCStartPinOption>
|
||||
<SCCust>0</SCCust>
|
||||
<CustSCPath/>
|
||||
<SCDesc>desktopini</SCDesc>
|
||||
<SCComment/>
|
||||
<SCArgs/>
|
||||
<SCWork/>
|
||||
<UseExtIco>0</UseExtIco>
|
||||
<IcoFN/>
|
||||
<IcoIdx>0</IcoIdx>
|
||||
<IcoShowMd>0</IcoShowMd>
|
||||
<IcoHK>0</IcoHK>
|
||||
<RegTTF>0</RegTTF>
|
||||
<TTFName/>
|
||||
<RegOCX>0</RegOCX>
|
||||
<RegTLB>0</RegTLB>
|
||||
<SupInUse>0</SupInUse>
|
||||
<Compress>1</Compress>
|
||||
<UseOrigAttr>1</UseOrigAttr>
|
||||
<Attr>0</Attr>
|
||||
<NoCRC>0</NoCRC>
|
||||
<NoRemove>0</NoRemove>
|
||||
<Shared>0</Shared>
|
||||
<OSCond>
|
||||
<OS>32768</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
</OSCond>
|
||||
<RTCond/>
|
||||
<BuildConfigs>
|
||||
<Cfg>All</Cfg>
|
||||
</BuildConfigs>
|
||||
<Package>None</Package>
|
||||
<Packages/>
|
||||
<Notes/>
|
||||
<CompSize>0</CompSize>
|
||||
<CRC>0</CRC>
|
||||
<StoreOnly>0</StoreOnly>
|
||||
</FileData>
|
||||
</ArchiveFiles>
|
||||
<ExternalFiles/>
|
||||
<BeforeInstallingScreens>
|
||||
@@ -4090,10 +4163,23 @@ function CreateShortcut(lnkpath, targetfile, appid)
|
||||
ret = File.Run(SessionVar.Expand("%AppFolder%\\shortcut.exe"), "\"" .. lnkpath .. "\" \"" .. targetfile .. "\" \"" .. appid .. "\"", "", SW_HIDE, true);
|
||||
return ret;
|
||||
end
|
||||
CreateShortcut (SessionVar.Expand ("%StartProgramsFolderCommon%\\%AppShortcutFolderName%\\App Installer.lnk"), SessionVar.Expand("%AppFolder%\\appinstaller.exe"), "Microsoft.DesktopAppInstaller!App");
|
||||
Registry.SetValue(HKEY_CURRENT_USER, "SOFTWARE\\Windows Modern\\App Installer", "AppInstallerLnk", SessionVar.Expand("%StartProgramsFolderCommon%\\%AppShortcutFolderName%\\App Installer.lnk"), REG_SZ);
|
||||
CreateShortcut (SessionVar.Expand ("%StartProgramsFolderCommon%\\%AppShortcutFolderName%\\Settings.lnk"), SessionVar.Expand("%AppFolder%\\settings.exe"), "WindowsModern.PracticalToolsProject!Settings");
|
||||
Registry.SetValue(HKEY_CURRENT_USER, "SOFTWARE\\Windows Modern\\App Installer", "SettingsLnk", SessionVar.Expand("%StartProgramsFolderCommon%\\%AppShortcutFolderName%\\Settings.lnk"), REG_SZ);
|
||||
function SetDesktopInit(inipath, section, key, value)
|
||||
ret = File.Run(SessionVar.Expand ("%AppFolder%\\desktopini.exe"), "\"" .. inipath .. "\" \"" .. section .. "\" \"" .. key .. "\" \"" .. value .. "\"", "", SW_SHOWNORMAL, true);
|
||||
return ret;
|
||||
end
|
||||
startitemfolder = SessionVar.Expand ("%StartProgramsFolderCommon%\\%AppShortcutFolderName%");
|
||||
applnkpath = startitemfolder .. "\\App Installer.lnk";
|
||||
setlnkpath = startitemfolder .. "\\Settings.lnk";
|
||||
desktopini = startitemfolder .. "";
|
||||
CreateShortcut (applnkpath, SessionVar.Expand("%AppFolder%\\appinstaller.exe"), "Microsoft.DesktopAppInstaller!App");
|
||||
Registry.SetValue(HKEY_CURRENT_USER, "SOFTWARE\\Windows Modern\\App Installer", "AppInstallerLnk", applnkpath, REG_SZ);
|
||||
CreateShortcut (setlnkpath, SessionVar.Expand("%AppFolder%\\settings.exe"), "WindowsModern.PracticalToolsProject!Settings");
|
||||
Registry.SetValue(HKEY_CURRENT_USER, "SOFTWARE\\Windows Modern\\App Installer", "SettingsLnk", setlnkpath, REG_SZ);
|
||||
SetDesktopInit (desktopini, ".ShellClassInfo", "ConfirmFileOp", 0);
|
||||
SetDesktopInit (desktopini, "LocalizedFileNames", "App Installer.lnk", SessionVar.Expand("@%AppFolder%\\appinstaller.exe,-300"));
|
||||
SetDesktopInit (desktopini, "LocalizedFileNames", "Settings.lnk", SessionVar.Expand("@%AppFolder%\\settings.exe,-200"));
|
||||
SetDesktopInit (desktopini, "LocalizedFileNames", "Update.lnk", SessionVar.Expand("@%AppFolder%\\reslib.dll,-103"));
|
||||
SetDesktopInit (desktopini, "LocalizedFileNames", "Uninstaller.lnk", SessionVar.Expand("@%AppFolder%\\reslib.dll,-131"));
|
||||
|
||||
DlgScrollingText.AppendLine(CTRL_SCROLLTEXT_BODY, "Updating system PATH...");
|
||||
local appFolder = SessionVar.Expand("%AppFolder%");
|
||||
@@ -683,11 +683,11 @@
|
||||
<SCDesk>0</SCDesk>
|
||||
<SCQLaunch>0</SCQLaunch>
|
||||
<SCStartPinOption>0</SCStartPinOption>
|
||||
<SCCust>0</SCCust>
|
||||
<CustSCPath/>
|
||||
<SCDesc>Settings</SCDesc>
|
||||
<SCCust>1</SCCust>
|
||||
<CustSCPath>%StartProgramsFolderCommon%\\%AppShortcutFolderName%</CustSCPath>
|
||||
<SCDesc>Update</SCDesc>
|
||||
<SCComment/>
|
||||
<SCArgs/>
|
||||
<SCArgs>appinstaller update /autoupdate</SCArgs>
|
||||
<SCWork/>
|
||||
<UseExtIco>0</UseExtIco>
|
||||
<IcoFN/>
|
||||
@@ -880,6 +880,79 @@
|
||||
<CRC>0</CRC>
|
||||
<StoreOnly>0</StoreOnly>
|
||||
</FileData>
|
||||
<FileData>
|
||||
<FldRef>0</FldRef>
|
||||
<FullName>E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstallerReset\Release\desktopini.exe</FullName>
|
||||
<FileName>desktopini.exe</FileName>
|
||||
<Source>E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstallerReset\Release</Source>
|
||||
<Ext>exe</Ext>
|
||||
<RTSource>µµ°¸</RTSource>
|
||||
<Desc/>
|
||||
<Recurse>1</Recurse>
|
||||
<MatchMode>0</MatchMode>
|
||||
<Dest>%AppFolder%</Dest>
|
||||
<Overwrite>1</Overwrite>
|
||||
<Backup>0</Backup>
|
||||
<Protect>0</Protect>
|
||||
<InstallOrder>1000</InstallOrder>
|
||||
<SCStartRoot>0</SCStartRoot>
|
||||
<SCStartProgs>0</SCStartProgs>
|
||||
<SCAppFld>0</SCAppFld>
|
||||
<SCStartup>0</SCStartup>
|
||||
<SCDesk>0</SCDesk>
|
||||
<SCQLaunch>0</SCQLaunch>
|
||||
<SCStartPinOption>0</SCStartPinOption>
|
||||
<SCCust>0</SCCust>
|
||||
<CustSCPath/>
|
||||
<SCDesc>desktopini</SCDesc>
|
||||
<SCComment/>
|
||||
<SCArgs/>
|
||||
<SCWork/>
|
||||
<UseExtIco>0</UseExtIco>
|
||||
<IcoFN/>
|
||||
<IcoIdx>0</IcoIdx>
|
||||
<IcoShowMd>0</IcoShowMd>
|
||||
<IcoHK>0</IcoHK>
|
||||
<RegTTF>0</RegTTF>
|
||||
<TTFName/>
|
||||
<RegOCX>0</RegOCX>
|
||||
<RegTLB>0</RegTLB>
|
||||
<SupInUse>0</SupInUse>
|
||||
<Compress>1</Compress>
|
||||
<UseOrigAttr>1</UseOrigAttr>
|
||||
<Attr>0</Attr>
|
||||
<NoCRC>0</NoCRC>
|
||||
<NoRemove>0</NoRemove>
|
||||
<Shared>0</Shared>
|
||||
<OSCond>
|
||||
<OS>32768</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
</OSCond>
|
||||
<RTCond/>
|
||||
<BuildConfigs>
|
||||
<Cfg>All</Cfg>
|
||||
</BuildConfigs>
|
||||
<Package>None</Package>
|
||||
<Packages/>
|
||||
<Notes/>
|
||||
<CompSize>0</CompSize>
|
||||
<CRC>0</CRC>
|
||||
<StoreOnly>0</StoreOnly>
|
||||
</FileData>
|
||||
</ArchiveFiles>
|
||||
<ExternalFiles/>
|
||||
<BeforeInstallingScreens>
|
||||
@@ -4090,10 +4163,23 @@ function CreateShortcut(lnkpath, targetfile, appid)
|
||||
ret = File.Run(SessionVar.Expand("%AppFolder%\\shortcut.exe"), "\"" .. lnkpath .. "\" \"" .. targetfile .. "\" \"" .. appid .. "\"", "", SW_HIDE, true);
|
||||
return ret;
|
||||
end
|
||||
CreateShortcut (SessionVar.Expand ("%StartProgramsFolderCommon%\\%AppShortcutFolderName%\\App Installer.lnk"), SessionVar.Expand("%AppFolder%\\appinstaller.exe"), "Microsoft.DesktopAppInstaller!App");
|
||||
Registry.SetValue(HKEY_CURRENT_USER, "SOFTWARE\\Windows Modern\\App Installer", "AppInstallerLnk", SessionVar.Expand("%StartProgramsFolderCommon%\\%AppShortcutFolderName%\\App Installer.lnk"), REG_SZ);
|
||||
CreateShortcut (SessionVar.Expand ("%StartProgramsFolderCommon%\\%AppShortcutFolderName%\\Settings.lnk"), SessionVar.Expand("%AppFolder%\\settings.exe"), "WindowsModern.PracticalToolsProject!Settings");
|
||||
Registry.SetValue(HKEY_CURRENT_USER, "SOFTWARE\\Windows Modern\\App Installer", "SettingsLnk", SessionVar.Expand("%StartProgramsFolderCommon%\\%AppShortcutFolderName%\\Settings.lnk"), REG_SZ);
|
||||
function SetDesktopInit(inipath, section, key, value)
|
||||
ret = File.Run(SessionVar.Expand ("%AppFolder%\\desktopini.exe"), "\"" .. inipath .. "\" \"" .. section .. "\" \"" .. key .. "\" \"" .. value .. "\"", "", SW_SHOWNORMAL, true);
|
||||
return ret;
|
||||
end
|
||||
startitemfolder = SessionVar.Expand ("%StartProgramsFolderCommon%\\%AppShortcutFolderName%");
|
||||
applnkpath = startitemfolder .. "\\App Installer.lnk";
|
||||
setlnkpath = startitemfolder .. "\\Settings.lnk";
|
||||
desktopini = startitemfolder .. "";
|
||||
CreateShortcut (applnkpath, SessionVar.Expand("%AppFolder%\\appinstaller.exe"), "Microsoft.DesktopAppInstaller!App");
|
||||
Registry.SetValue(HKEY_CURRENT_USER, "SOFTWARE\\Windows Modern\\App Installer", "AppInstallerLnk", applnkpath, REG_SZ);
|
||||
CreateShortcut (setlnkpath, SessionVar.Expand("%AppFolder%\\settings.exe"), "WindowsModern.PracticalToolsProject!Settings");
|
||||
Registry.SetValue(HKEY_CURRENT_USER, "SOFTWARE\\Windows Modern\\App Installer", "SettingsLnk", setlnkpath, REG_SZ);
|
||||
SetDesktopInit (desktopini, ".ShellClassInfo", "ConfirmFileOp", 0);
|
||||
SetDesktopInit (desktopini, "LocalizedFileNames", "App Installer.lnk", SessionVar.Expand("@%AppFolder%\\appinstaller.exe,-300"));
|
||||
SetDesktopInit (desktopini, "LocalizedFileNames", "Settings.lnk", SessionVar.Expand("@%AppFolder%\\settings.exe,-200"));
|
||||
SetDesktopInit (desktopini, "LocalizedFileNames", "Update.lnk", SessionVar.Expand("@%AppFolder%\\reslib.dll,-103"));
|
||||
SetDesktopInit (desktopini, "LocalizedFileNames", "Uninstaller.lnk", SessionVar.Expand("@%AppFolder%\\reslib.dll,-131"));
|
||||
|
||||
DlgScrollingText.AppendLine(CTRL_SCROLLTEXT_BODY, "Updating system PATH...");
|
||||
local appFolder = SessionVar.Expand("%AppFolder%");
|
||||
@@ -683,11 +683,11 @@
|
||||
<SCDesk>0</SCDesk>
|
||||
<SCQLaunch>0</SCQLaunch>
|
||||
<SCStartPinOption>0</SCStartPinOption>
|
||||
<SCCust>0</SCCust>
|
||||
<CustSCPath/>
|
||||
<SCDesc>Settings</SCDesc>
|
||||
<SCCust>1</SCCust>
|
||||
<CustSCPath>%StartProgramsFolderCommon%\\%AppShortcutFolderName%</CustSCPath>
|
||||
<SCDesc>Update</SCDesc>
|
||||
<SCComment/>
|
||||
<SCArgs/>
|
||||
<SCArgs>appinstaller update /autoupdate</SCArgs>
|
||||
<SCWork/>
|
||||
<UseExtIco>0</UseExtIco>
|
||||
<IcoFN/>
|
||||
@@ -880,6 +880,79 @@
|
||||
<CRC>0</CRC>
|
||||
<StoreOnly>0</StoreOnly>
|
||||
</FileData>
|
||||
<FileData>
|
||||
<FldRef>0</FldRef>
|
||||
<FullName>E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstallerReset\Release\desktopini.exe</FullName>
|
||||
<FileName>desktopini.exe</FileName>
|
||||
<Source>E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstallerReset\Release</Source>
|
||||
<Ext>exe</Ext>
|
||||
<RTSource>µµ°¸</RTSource>
|
||||
<Desc/>
|
||||
<Recurse>1</Recurse>
|
||||
<MatchMode>0</MatchMode>
|
||||
<Dest>%AppFolder%</Dest>
|
||||
<Overwrite>1</Overwrite>
|
||||
<Backup>0</Backup>
|
||||
<Protect>0</Protect>
|
||||
<InstallOrder>1000</InstallOrder>
|
||||
<SCStartRoot>0</SCStartRoot>
|
||||
<SCStartProgs>0</SCStartProgs>
|
||||
<SCAppFld>0</SCAppFld>
|
||||
<SCStartup>0</SCStartup>
|
||||
<SCDesk>0</SCDesk>
|
||||
<SCQLaunch>0</SCQLaunch>
|
||||
<SCStartPinOption>0</SCStartPinOption>
|
||||
<SCCust>0</SCCust>
|
||||
<CustSCPath/>
|
||||
<SCDesc>desktopini</SCDesc>
|
||||
<SCComment/>
|
||||
<SCArgs/>
|
||||
<SCWork/>
|
||||
<UseExtIco>0</UseExtIco>
|
||||
<IcoFN/>
|
||||
<IcoIdx>0</IcoIdx>
|
||||
<IcoShowMd>0</IcoShowMd>
|
||||
<IcoHK>0</IcoHK>
|
||||
<RegTTF>0</RegTTF>
|
||||
<TTFName/>
|
||||
<RegOCX>0</RegOCX>
|
||||
<RegTLB>0</RegTLB>
|
||||
<SupInUse>0</SupInUse>
|
||||
<Compress>1</Compress>
|
||||
<UseOrigAttr>1</UseOrigAttr>
|
||||
<Attr>0</Attr>
|
||||
<NoCRC>0</NoCRC>
|
||||
<NoRemove>0</NoRemove>
|
||||
<Shared>0</Shared>
|
||||
<OSCond>
|
||||
<OS>32768</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
</OSCond>
|
||||
<RTCond/>
|
||||
<BuildConfigs>
|
||||
<Cfg>All</Cfg>
|
||||
</BuildConfigs>
|
||||
<Package>None</Package>
|
||||
<Packages/>
|
||||
<Notes/>
|
||||
<CompSize>0</CompSize>
|
||||
<CRC>0</CRC>
|
||||
<StoreOnly>0</StoreOnly>
|
||||
</FileData>
|
||||
</ArchiveFiles>
|
||||
<ExternalFiles/>
|
||||
<BeforeInstallingScreens>
|
||||
@@ -4090,10 +4163,23 @@ function CreateShortcut(lnkpath, targetfile, appid)
|
||||
ret = File.Run(SessionVar.Expand("%AppFolder%\\shortcut.exe"), "\"" .. lnkpath .. "\" \"" .. targetfile .. "\" \"" .. appid .. "\"", "", SW_HIDE, true);
|
||||
return ret;
|
||||
end
|
||||
CreateShortcut (SessionVar.Expand ("%StartProgramsFolderCommon%\\%AppShortcutFolderName%\\App Installer.lnk"), SessionVar.Expand("%AppFolder%\\appinstaller.exe"), "Microsoft.DesktopAppInstaller!App");
|
||||
Registry.SetValue(HKEY_CURRENT_USER, "SOFTWARE\\Windows Modern\\App Installer", "AppInstallerLnk", SessionVar.Expand("%StartProgramsFolderCommon%\\%AppShortcutFolderName%\\App Installer.lnk"), REG_SZ);
|
||||
CreateShortcut (SessionVar.Expand ("%StartProgramsFolderCommon%\\%AppShortcutFolderName%\\Settings.lnk"), SessionVar.Expand("%AppFolder%\\settings.exe"), "WindowsModern.PracticalToolsProject!Settings");
|
||||
Registry.SetValue(HKEY_CURRENT_USER, "SOFTWARE\\Windows Modern\\App Installer", "SettingsLnk", SessionVar.Expand("%StartProgramsFolderCommon%\\%AppShortcutFolderName%\\Settings.lnk"), REG_SZ);
|
||||
function SetDesktopInit(inipath, section, key, value)
|
||||
ret = File.Run(SessionVar.Expand ("%AppFolder%\\desktopini.exe"), "\"" .. inipath .. "\" \"" .. section .. "\" \"" .. key .. "\" \"" .. value .. "\"", "", SW_SHOWNORMAL, true);
|
||||
return ret;
|
||||
end
|
||||
startitemfolder = SessionVar.Expand ("%StartProgramsFolderCommon%\\%AppShortcutFolderName%");
|
||||
applnkpath = startitemfolder .. "\\App Installer.lnk";
|
||||
setlnkpath = startitemfolder .. "\\Settings.lnk";
|
||||
desktopini = startitemfolder .. "";
|
||||
CreateShortcut (applnkpath, SessionVar.Expand("%AppFolder%\\appinstaller.exe"), "Microsoft.DesktopAppInstaller!App");
|
||||
Registry.SetValue(HKEY_CURRENT_USER, "SOFTWARE\\Windows Modern\\App Installer", "AppInstallerLnk", applnkpath, REG_SZ);
|
||||
CreateShortcut (setlnkpath, SessionVar.Expand("%AppFolder%\\settings.exe"), "WindowsModern.PracticalToolsProject!Settings");
|
||||
Registry.SetValue(HKEY_CURRENT_USER, "SOFTWARE\\Windows Modern\\App Installer", "SettingsLnk", setlnkpath, REG_SZ);
|
||||
SetDesktopInit (desktopini, ".ShellClassInfo", "ConfirmFileOp", 0);
|
||||
SetDesktopInit (desktopini, "LocalizedFileNames", "App Installer.lnk", SessionVar.Expand("@%AppFolder%\\appinstaller.exe,-300"));
|
||||
SetDesktopInit (desktopini, "LocalizedFileNames", "Settings.lnk", SessionVar.Expand("@%AppFolder%\\settings.exe,-200"));
|
||||
SetDesktopInit (desktopini, "LocalizedFileNames", "Update.lnk", SessionVar.Expand("@%AppFolder%\\reslib.dll,-103"));
|
||||
SetDesktopInit (desktopini, "LocalizedFileNames", "Uninstaller.lnk", SessionVar.Expand("@%AppFolder%\\reslib.dll,-131"));
|
||||
|
||||
DlgScrollingText.AppendLine(CTRL_SCROLLTEXT_BODY, "Updating system PATH...");
|
||||
local appFolder = SessionVar.Expand("%AppFolder%");
|
||||
@@ -683,11 +683,11 @@
|
||||
<SCDesk>0</SCDesk>
|
||||
<SCQLaunch>0</SCQLaunch>
|
||||
<SCStartPinOption>0</SCStartPinOption>
|
||||
<SCCust>0</SCCust>
|
||||
<CustSCPath/>
|
||||
<SCDesc>Settings</SCDesc>
|
||||
<SCCust>1</SCCust>
|
||||
<CustSCPath>%StartProgramsFolderCommon%\\%AppShortcutFolderName%</CustSCPath>
|
||||
<SCDesc>Update</SCDesc>
|
||||
<SCComment/>
|
||||
<SCArgs/>
|
||||
<SCArgs>appinstaller update /autoupdate</SCArgs>
|
||||
<SCWork/>
|
||||
<UseExtIco>0</UseExtIco>
|
||||
<IcoFN/>
|
||||
@@ -880,6 +880,79 @@
|
||||
<CRC>0</CRC>
|
||||
<StoreOnly>0</StoreOnly>
|
||||
</FileData>
|
||||
<FileData>
|
||||
<FldRef>0</FldRef>
|
||||
<FullName>E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstallerReset\Release\desktopini.exe</FullName>
|
||||
<FileName>desktopini.exe</FileName>
|
||||
<Source>E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstallerReset\Release</Source>
|
||||
<Ext>exe</Ext>
|
||||
<RTSource>µµ°¸</RTSource>
|
||||
<Desc/>
|
||||
<Recurse>1</Recurse>
|
||||
<MatchMode>0</MatchMode>
|
||||
<Dest>%AppFolder%</Dest>
|
||||
<Overwrite>1</Overwrite>
|
||||
<Backup>0</Backup>
|
||||
<Protect>0</Protect>
|
||||
<InstallOrder>1000</InstallOrder>
|
||||
<SCStartRoot>0</SCStartRoot>
|
||||
<SCStartProgs>0</SCStartProgs>
|
||||
<SCAppFld>0</SCAppFld>
|
||||
<SCStartup>0</SCStartup>
|
||||
<SCDesk>0</SCDesk>
|
||||
<SCQLaunch>0</SCQLaunch>
|
||||
<SCStartPinOption>0</SCStartPinOption>
|
||||
<SCCust>0</SCCust>
|
||||
<CustSCPath/>
|
||||
<SCDesc>desktopini</SCDesc>
|
||||
<SCComment/>
|
||||
<SCArgs/>
|
||||
<SCWork/>
|
||||
<UseExtIco>0</UseExtIco>
|
||||
<IcoFN/>
|
||||
<IcoIdx>0</IcoIdx>
|
||||
<IcoShowMd>0</IcoShowMd>
|
||||
<IcoHK>0</IcoHK>
|
||||
<RegTTF>0</RegTTF>
|
||||
<TTFName/>
|
||||
<RegOCX>0</RegOCX>
|
||||
<RegTLB>0</RegTLB>
|
||||
<SupInUse>0</SupInUse>
|
||||
<Compress>1</Compress>
|
||||
<UseOrigAttr>1</UseOrigAttr>
|
||||
<Attr>0</Attr>
|
||||
<NoCRC>0</NoCRC>
|
||||
<NoRemove>0</NoRemove>
|
||||
<Shared>0</Shared>
|
||||
<OSCond>
|
||||
<OS>32768</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
</OSCond>
|
||||
<RTCond/>
|
||||
<BuildConfigs>
|
||||
<Cfg>All</Cfg>
|
||||
</BuildConfigs>
|
||||
<Package>None</Package>
|
||||
<Packages/>
|
||||
<Notes/>
|
||||
<CompSize>0</CompSize>
|
||||
<CRC>0</CRC>
|
||||
<StoreOnly>0</StoreOnly>
|
||||
</FileData>
|
||||
</ArchiveFiles>
|
||||
<ExternalFiles/>
|
||||
<BeforeInstallingScreens>
|
||||
@@ -4090,10 +4163,23 @@ function CreateShortcut(lnkpath, targetfile, appid)
|
||||
ret = File.Run(SessionVar.Expand("%AppFolder%\\shortcut.exe"), "\"" .. lnkpath .. "\" \"" .. targetfile .. "\" \"" .. appid .. "\"", "", SW_HIDE, true);
|
||||
return ret;
|
||||
end
|
||||
CreateShortcut (SessionVar.Expand ("%StartProgramsFolderCommon%\\%AppShortcutFolderName%\\App Installer.lnk"), SessionVar.Expand("%AppFolder%\\appinstaller.exe"), "Microsoft.DesktopAppInstaller!App");
|
||||
Registry.SetValue(HKEY_CURRENT_USER, "SOFTWARE\\Windows Modern\\App Installer", "AppInstallerLnk", SessionVar.Expand("%StartProgramsFolderCommon%\\%AppShortcutFolderName%\\App Installer.lnk"), REG_SZ);
|
||||
CreateShortcut (SessionVar.Expand ("%StartProgramsFolderCommon%\\%AppShortcutFolderName%\\Settings.lnk"), SessionVar.Expand("%AppFolder%\\settings.exe"), "WindowsModern.PracticalToolsProject!Settings");
|
||||
Registry.SetValue(HKEY_CURRENT_USER, "SOFTWARE\\Windows Modern\\App Installer", "SettingsLnk", SessionVar.Expand("%StartProgramsFolderCommon%\\%AppShortcutFolderName%\\Settings.lnk"), REG_SZ);
|
||||
function SetDesktopInit(inipath, section, key, value)
|
||||
ret = File.Run(SessionVar.Expand ("%AppFolder%\\desktopini.exe"), "\"" .. inipath .. "\" \"" .. section .. "\" \"" .. key .. "\" \"" .. value .. "\"", "", SW_HIDE, true);
|
||||
return ret;
|
||||
end
|
||||
startitemfolder = SessionVar.Expand ("%StartProgramsFolderCommon%\\%AppShortcutFolderName%");
|
||||
applnkpath = startitemfolder .. "\\App Installer.lnk";
|
||||
setlnkpath = startitemfolder .. "\\Settings.lnk";
|
||||
desktopini = startitemfolder .. "";
|
||||
CreateShortcut (applnkpath, SessionVar.Expand("%AppFolder%\\appinstaller.exe"), "Microsoft.DesktopAppInstaller!App");
|
||||
Registry.SetValue(HKEY_CURRENT_USER, "SOFTWARE\\Windows Modern\\App Installer", "AppInstallerLnk", applnkpath, REG_SZ);
|
||||
CreateShortcut (setlnkpath, SessionVar.Expand("%AppFolder%\\settings.exe"), "WindowsModern.PracticalToolsProject!Settings");
|
||||
Registry.SetValue(HKEY_CURRENT_USER, "SOFTWARE\\Windows Modern\\App Installer", "SettingsLnk", setlnkpath, REG_SZ);
|
||||
SetDesktopInit (desktopini, ".ShellClassInfo", "ConfirmFileOp", 0);
|
||||
SetDesktopInit (desktopini, "LocalizedFileNames", "App Installer.lnk", SessionVar.Expand("@%AppFolder%\\appinstaller.exe,-300"));
|
||||
SetDesktopInit (desktopini, "LocalizedFileNames", "Settings.lnk", SessionVar.Expand("@%AppFolder%\\settings.exe,-200"));
|
||||
SetDesktopInit (desktopini, "LocalizedFileNames", "Update.lnk", SessionVar.Expand("@%AppFolder%\\reslib.dll,-103"));
|
||||
SetDesktopInit (desktopini, "LocalizedFileNames", "Uninstall.lnk", SessionVar.Expand("@%AppFolder%\\reslib.dll,-131"));
|
||||
|
||||
DlgScrollingText.AppendLine(CTRL_SCROLLTEXT_BODY, "Updating system PATH...");
|
||||
local appFolder = SessionVar.Expand("%AppFolder%");
|
||||
6279
others/Autosave/autosave_2025-12-08_07-59-56.suf
Normal file
6279
others/Autosave/autosave_2025-12-08_07-59-56.suf
Normal file
File diff suppressed because it is too large
Load Diff
6279
others/Autosave/autosave_2025-12-08_08-03-34.suf
Normal file
6279
others/Autosave/autosave_2025-12-08_08-03-34.suf
Normal file
File diff suppressed because it is too large
Load Diff
6279
others/Autosave/autosave_2025-12-08_10-54-17.suf
Normal file
6279
others/Autosave/autosave_2025-12-08_10-54-17.suf
Normal file
File diff suppressed because it is too large
Load Diff
6279
others/Autosave/autosave_2025-12-08_10-59-13.suf
Normal file
6279
others/Autosave/autosave_2025-12-08_10-59-13.suf
Normal file
File diff suppressed because it is too large
Load Diff
6425
others/Autosave/autosave_2025-12-08_13-08-26.suf
Normal file
6425
others/Autosave/autosave_2025-12-08_13-08-26.suf
Normal file
File diff suppressed because it is too large
Load Diff
@@ -683,11 +683,11 @@
|
||||
<SCDesk>0</SCDesk>
|
||||
<SCQLaunch>0</SCQLaunch>
|
||||
<SCStartPinOption>0</SCStartPinOption>
|
||||
<SCCust>0</SCCust>
|
||||
<CustSCPath/>
|
||||
<SCDesc>Settings</SCDesc>
|
||||
<SCCust>1</SCCust>
|
||||
<CustSCPath>%StartProgramsFolderCommon%\\%AppShortcutFolderName%</CustSCPath>
|
||||
<SCDesc>Update</SCDesc>
|
||||
<SCComment/>
|
||||
<SCArgs/>
|
||||
<SCArgs>appinstaller update /checkupdate</SCArgs>
|
||||
<SCWork/>
|
||||
<UseExtIco>0</UseExtIco>
|
||||
<IcoFN/>
|
||||
@@ -880,6 +880,225 @@
|
||||
<CRC>0</CRC>
|
||||
<StoreOnly>0</StoreOnly>
|
||||
</FileData>
|
||||
<FileData>
|
||||
<FldRef>0</FldRef>
|
||||
<FullName>E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstallerReset\Release\desktopini.exe</FullName>
|
||||
<FileName>desktopini.exe</FileName>
|
||||
<Source>E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstallerReset\Release</Source>
|
||||
<Ext>exe</Ext>
|
||||
<RTSource>档案</RTSource>
|
||||
<Desc/>
|
||||
<Recurse>1</Recurse>
|
||||
<MatchMode>0</MatchMode>
|
||||
<Dest>%AppFolder%</Dest>
|
||||
<Overwrite>1</Overwrite>
|
||||
<Backup>0</Backup>
|
||||
<Protect>0</Protect>
|
||||
<InstallOrder>1000</InstallOrder>
|
||||
<SCStartRoot>0</SCStartRoot>
|
||||
<SCStartProgs>0</SCStartProgs>
|
||||
<SCAppFld>0</SCAppFld>
|
||||
<SCStartup>0</SCStartup>
|
||||
<SCDesk>0</SCDesk>
|
||||
<SCQLaunch>0</SCQLaunch>
|
||||
<SCStartPinOption>0</SCStartPinOption>
|
||||
<SCCust>0</SCCust>
|
||||
<CustSCPath/>
|
||||
<SCDesc>desktopini</SCDesc>
|
||||
<SCComment/>
|
||||
<SCArgs/>
|
||||
<SCWork/>
|
||||
<UseExtIco>0</UseExtIco>
|
||||
<IcoFN/>
|
||||
<IcoIdx>0</IcoIdx>
|
||||
<IcoShowMd>0</IcoShowMd>
|
||||
<IcoHK>0</IcoHK>
|
||||
<RegTTF>0</RegTTF>
|
||||
<TTFName/>
|
||||
<RegOCX>0</RegOCX>
|
||||
<RegTLB>0</RegTLB>
|
||||
<SupInUse>0</SupInUse>
|
||||
<Compress>1</Compress>
|
||||
<UseOrigAttr>1</UseOrigAttr>
|
||||
<Attr>0</Attr>
|
||||
<NoCRC>0</NoCRC>
|
||||
<NoRemove>0</NoRemove>
|
||||
<Shared>0</Shared>
|
||||
<OSCond>
|
||||
<OS>32768</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
</OSCond>
|
||||
<RTCond/>
|
||||
<BuildConfigs>
|
||||
<Cfg>All</Cfg>
|
||||
</BuildConfigs>
|
||||
<Package>None</Package>
|
||||
<Packages/>
|
||||
<Notes/>
|
||||
<CompSize>0</CompSize>
|
||||
<CRC>0</CRC>
|
||||
<StoreOnly>0</StoreOnly>
|
||||
</FileData>
|
||||
<FileData>
|
||||
<FldRef>0</FldRef>
|
||||
<FullName>E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstallerReset\Release\PriFileFormat.dll.config</FullName>
|
||||
<FileName>PriFileFormat.dll.config</FileName>
|
||||
<Source>E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstallerReset\Release</Source>
|
||||
<Ext>config</Ext>
|
||||
<RTSource>档案</RTSource>
|
||||
<Desc/>
|
||||
<Recurse>1</Recurse>
|
||||
<MatchMode>0</MatchMode>
|
||||
<Dest>%AppFolder%</Dest>
|
||||
<Overwrite>1</Overwrite>
|
||||
<Backup>0</Backup>
|
||||
<Protect>0</Protect>
|
||||
<InstallOrder>1000</InstallOrder>
|
||||
<SCStartRoot>0</SCStartRoot>
|
||||
<SCStartProgs>0</SCStartProgs>
|
||||
<SCAppFld>0</SCAppFld>
|
||||
<SCStartup>0</SCStartup>
|
||||
<SCDesk>0</SCDesk>
|
||||
<SCQLaunch>0</SCQLaunch>
|
||||
<SCStartPinOption>0</SCStartPinOption>
|
||||
<SCCust>0</SCCust>
|
||||
<CustSCPath/>
|
||||
<SCDesc/>
|
||||
<SCComment/>
|
||||
<SCArgs/>
|
||||
<SCWork/>
|
||||
<UseExtIco>0</UseExtIco>
|
||||
<IcoFN/>
|
||||
<IcoIdx>0</IcoIdx>
|
||||
<IcoShowMd>0</IcoShowMd>
|
||||
<IcoHK>0</IcoHK>
|
||||
<RegTTF>0</RegTTF>
|
||||
<TTFName/>
|
||||
<RegOCX>0</RegOCX>
|
||||
<RegTLB>0</RegTLB>
|
||||
<SupInUse>0</SupInUse>
|
||||
<Compress>1</Compress>
|
||||
<UseOrigAttr>1</UseOrigAttr>
|
||||
<Attr>0</Attr>
|
||||
<NoCRC>0</NoCRC>
|
||||
<NoRemove>0</NoRemove>
|
||||
<Shared>0</Shared>
|
||||
<OSCond>
|
||||
<OS>32768</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
</OSCond>
|
||||
<RTCond/>
|
||||
<BuildConfigs>
|
||||
<Cfg>All</Cfg>
|
||||
</BuildConfigs>
|
||||
<Package>None</Package>
|
||||
<Packages/>
|
||||
<Notes/>
|
||||
<CompSize>0</CompSize>
|
||||
<CRC>0</CRC>
|
||||
<StoreOnly>0</StoreOnly>
|
||||
</FileData>
|
||||
<FileData>
|
||||
<FldRef>0</FldRef>
|
||||
<FullName>E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstallerReset\Release\priformatcli.dll.metagen</FullName>
|
||||
<FileName>priformatcli.dll.metagen</FileName>
|
||||
<Source>E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstallerReset\Release</Source>
|
||||
<Ext>metagen</Ext>
|
||||
<RTSource>档案</RTSource>
|
||||
<Desc/>
|
||||
<Recurse>1</Recurse>
|
||||
<MatchMode>0</MatchMode>
|
||||
<Dest>%AppFolder%</Dest>
|
||||
<Overwrite>1</Overwrite>
|
||||
<Backup>0</Backup>
|
||||
<Protect>0</Protect>
|
||||
<InstallOrder>1000</InstallOrder>
|
||||
<SCStartRoot>0</SCStartRoot>
|
||||
<SCStartProgs>0</SCStartProgs>
|
||||
<SCAppFld>0</SCAppFld>
|
||||
<SCStartup>0</SCStartup>
|
||||
<SCDesk>0</SCDesk>
|
||||
<SCQLaunch>0</SCQLaunch>
|
||||
<SCStartPinOption>0</SCStartPinOption>
|
||||
<SCCust>0</SCCust>
|
||||
<CustSCPath/>
|
||||
<SCDesc/>
|
||||
<SCComment/>
|
||||
<SCArgs/>
|
||||
<SCWork/>
|
||||
<UseExtIco>0</UseExtIco>
|
||||
<IcoFN/>
|
||||
<IcoIdx>0</IcoIdx>
|
||||
<IcoShowMd>0</IcoShowMd>
|
||||
<IcoHK>0</IcoHK>
|
||||
<RegTTF>0</RegTTF>
|
||||
<TTFName/>
|
||||
<RegOCX>0</RegOCX>
|
||||
<RegTLB>0</RegTLB>
|
||||
<SupInUse>0</SupInUse>
|
||||
<Compress>1</Compress>
|
||||
<UseOrigAttr>1</UseOrigAttr>
|
||||
<Attr>0</Attr>
|
||||
<NoCRC>0</NoCRC>
|
||||
<NoRemove>0</NoRemove>
|
||||
<Shared>0</Shared>
|
||||
<OSCond>
|
||||
<OS>32768</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
</OSCond>
|
||||
<RTCond/>
|
||||
<BuildConfigs>
|
||||
<Cfg>All</Cfg>
|
||||
</BuildConfigs>
|
||||
<Package>None</Package>
|
||||
<Packages/>
|
||||
<Notes/>
|
||||
<CompSize>0</CompSize>
|
||||
<CRC>0</CRC>
|
||||
<StoreOnly>0</StoreOnly>
|
||||
</FileData>
|
||||
</ArchiveFiles>
|
||||
<ExternalFiles/>
|
||||
<BeforeInstallingScreens>
|
||||
@@ -4090,10 +4309,24 @@ function CreateShortcut(lnkpath, targetfile, appid)
|
||||
ret = File.Run(SessionVar.Expand("%AppFolder%\\shortcut.exe"), "\"" .. lnkpath .. "\" \"" .. targetfile .. "\" \"" .. appid .. "\"", "", SW_HIDE, true);
|
||||
return ret;
|
||||
end
|
||||
CreateShortcut (SessionVar.Expand ("%StartProgramsFolderCommon%\\%AppShortcutFolderName%\\App Installer.lnk"), SessionVar.Expand("%AppFolder%\\appinstaller.exe"), "Microsoft.DesktopAppInstaller!App");
|
||||
Registry.SetValue(HKEY_CURRENT_USER, "SOFTWARE\\Windows Modern\\App Installer", "AppInstallerLnk", SessionVar.Expand("%StartProgramsFolderCommon%\\%AppShortcutFolderName%\\App Installer.lnk"), REG_SZ);
|
||||
CreateShortcut (SessionVar.Expand ("%StartProgramsFolderCommon%\\%AppShortcutFolderName%\\Settings.lnk"), SessionVar.Expand("%AppFolder%\\settings.exe"), "WindowsModern.PracticalToolsProject!Settings");
|
||||
Registry.SetValue(HKEY_CURRENT_USER, "SOFTWARE\\Windows Modern\\App Installer", "SettingsLnk", SessionVar.Expand("%StartProgramsFolderCommon%\\%AppShortcutFolderName%\\Settings.lnk"), REG_SZ);
|
||||
function SetDesktopInit(inipath, section, key, value)
|
||||
ret = File.Run(SessionVar.Expand ("%AppFolder%\\desktopini.exe"), "\"" .. inipath .. "\" \"" .. section .. "\" \"" .. key .. "\" \"" .. value .. "\"", "", SW_HIDE, true);
|
||||
return ret;
|
||||
end
|
||||
startitemfolder = SessionVar.Expand ("%StartProgramsFolderCommon%\\%AppShortcutFolderName%");
|
||||
applnkpath = startitemfolder .. "\\App Installer.lnk";
|
||||
setlnkpath = startitemfolder .. "\\Settings.lnk";
|
||||
desktopini = startitemfolder .. "";
|
||||
CreateShortcut (applnkpath, SessionVar.Expand("%AppFolder%\\appinstaller.exe"), "Microsoft.DesktopAppInstaller!App");
|
||||
Registry.SetValue(HKEY_CURRENT_USER, "SOFTWARE\\Windows Modern\\App Installer", "AppInstallerLnk", applnkpath, REG_SZ);
|
||||
CreateShortcut (setlnkpath, SessionVar.Expand("%AppFolder%\\settings.exe"), "WindowsModern.PracticalToolsProject!Settings");
|
||||
Registry.SetValue(HKEY_CURRENT_USER, "SOFTWARE\\Windows Modern\\App Installer", "SettingsLnk", setlnkpath, REG_SZ);
|
||||
SetDesktopInit (desktopini, ".ShellClassInfo", "ConfirmFileOp", 0);
|
||||
SetDesktopInit (desktopini, "LocalizedFileNames", "App Installer.lnk", SessionVar.Expand("@%AppFolder%\\appinstaller.exe,-300"));
|
||||
SetDesktopInit (desktopini, "LocalizedFileNames", "Settings.lnk", SessionVar.Expand("@%AppFolder%\\settings.exe,-200"));
|
||||
SetDesktopInit (desktopini, "LocalizedFileNames", "Update.lnk", SessionVar.Expand("@%AppFolder%\\reslib.dll,-103"));
|
||||
SetDesktopInit (desktopini, "LocalizedFileNames", "Uninstall.lnk", SessionVar.Expand("@%AppFolder%\\reslib.dll,-131"));
|
||||
SetDesktopInit (desktopini, ".ShellClassInfo", "LocalizedResourceName", SessionVar.Expand("@%AppFolder%\\appinstaller.exe,-300"));
|
||||
|
||||
DlgScrollingText.AppendLine(CTRL_SCROLLTEXT_BODY, "Updating system PATH...");
|
||||
local appFolder = SessionVar.Expand("%AppFolder%");
|
||||
@@ -6095,7 +6328,7 @@ g_HandleSystemReboot();
|
||||
</SessionVar>
|
||||
<SessionVar>
|
||||
<Name>%ProductVer%</Name>
|
||||
<Value>0.1.0.0</Value>
|
||||
<Value>0.2.0.0</Value>
|
||||
<Type>1</Type>
|
||||
</SessionVar>
|
||||
<SessionVar>
|
||||
|
||||
@@ -257,7 +257,7 @@ struct pkg_info
|
||||
pkg_info pi;
|
||||
if (!pkg) throw ref new InvalidArgumentException ("No package found.");
|
||||
#define WAPParseSetValue(_left_part_, _right_part_, _default_value_) \
|
||||
do { try { _left_part_ = _right_part_; } catch (...) { _left_part_ = _default_value_; } } while (false)
|
||||
do { try { _left_part_ = _right_part_; } catch (Platform::Exception ^) { _left_part_ = _default_value_; } catch (...) { _left_part_ = _default_value_; } } while (false)
|
||||
#define WAPParseSetStringValue(_left_part_, _right_part_) \
|
||||
WAPParseSetValue (_left_part_, WinRTStringToStdString (_right_part_), L"")
|
||||
WAPParseSetStringValue (pi.id.name, pkg->Id->Name);
|
||||
@@ -271,7 +271,15 @@ struct pkg_info
|
||||
WAPParseSetStringValue (pi.prop.displayname, pkg->DisplayName);
|
||||
WAPParseSetStringValue (pi.prop.description, pkg->Description);
|
||||
WAPParseSetStringValue (pi.prop.publisher, pkg->PublisherDisplayName);
|
||||
WAPParseSetStringValue (pi.prop.logo, pkg->Logo->ToString ());
|
||||
try
|
||||
{
|
||||
auto logo = pkg->Logo;
|
||||
String ^logouri = "";
|
||||
if (logo && logo->DisplayUri) { logouri = logo->DisplayUri; }
|
||||
WAPParseSetStringValue (pi.prop.logo, logouri);
|
||||
}
|
||||
catch (Platform::Exception ^) {}
|
||||
catch (...) {}
|
||||
WAPParseSetValue (pi.prop.framework, pkg->IsFramework, false);
|
||||
WAPParseSetValue (pi.prop.resource_package, pkg->IsResourcePackage, false);
|
||||
WAPParseSetValue (pi.bundle, pkg->IsBundle, false);
|
||||
@@ -298,6 +306,7 @@ struct pkg_info
|
||||
i ++;
|
||||
}
|
||||
}
|
||||
catch (Platform::Exception ^) {}
|
||||
catch (...) {}
|
||||
if (g_enableIterDeps && iterdeps)
|
||||
{
|
||||
@@ -315,6 +324,7 @@ struct pkg_info
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Platform::Exception ^) {}
|
||||
catch (...) {}
|
||||
}
|
||||
return pi;
|
||||
|
||||
BIN
pkgmgr/pkgmgr.rc
BIN
pkgmgr/pkgmgr.rc
Binary file not shown.
Binary file not shown.
@@ -15,7 +15,6 @@
|
||||
#include "stringres.h"
|
||||
#include "norstr.h"
|
||||
#include "raii.h"
|
||||
#include "priformatcli.h"
|
||||
#include "filepath.h"
|
||||
|
||||
HRESULT GetBundleReader (_In_ LPCWSTR inputFileName, _Outptr_ IAppxBundleReader** bundleReader)
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
E:/Profiles/Bruce/Documents/visual studio 2015/Projects/priformatcli/priformatcli
|
||||
BIN
priformatcli/PriFileFormat.dll
Normal file
BIN
priformatcli/PriFileFormat.dll
Normal file
Binary file not shown.
30
priformatcli/ReadMe.txt
Normal file
30
priformatcli/ReadMe.txt
Normal file
@@ -0,0 +1,30 @@
|
||||
========================================================================
|
||||
动态链接库:priformatcli 项目概述
|
||||
========================================================================
|
||||
|
||||
应用程序向导已为您创建了此 priformatcli DLL。
|
||||
|
||||
本文件概要介绍组成 priformatcli 应用程序的每个文件的内容。
|
||||
|
||||
|
||||
priformatcli.vcxproj
|
||||
这是使用应用程序向导生成的 VC++ 项目的主项目文件,其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
|
||||
|
||||
priformatcli.vcxproj.filters
|
||||
这是使用“应用程序向导”生成的 VC++ 项目筛选器文件。它包含有关项目文件与筛选器之间的关联信息。在 IDE 中,通过这种关联,在特定节点下以分组形式显示具有相似扩展名的文件。例如,“.cpp”文件与“源文件”筛选器关联。
|
||||
|
||||
priformatcli.cpp
|
||||
这是主 DLL 源文件。
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
其他标准文件:
|
||||
|
||||
StdAfx.h, StdAfx.cpp
|
||||
这些文件用于生成名为 priformatcli.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
其他注释:
|
||||
|
||||
应用程序向导使用“TODO:”注释来指示应添加或自定义的源代码部分。
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
19
priformatcli/dllmain.cpp
Normal file
19
priformatcli/dllmain.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
// 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;
|
||||
}
|
||||
|
||||
256
priformatcli/localeex.h
Normal file
256
priformatcli/localeex.h
Normal file
@@ -0,0 +1,256 @@
|
||||
#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 (const std::wstring &localeCode)
|
||||
{
|
||||
#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
|
||||
try
|
||||
{
|
||||
BYTE buf [LOCALE_NAME_MAX_LENGTH * sizeof (WCHAR)] = {0};
|
||||
int res = GetLocaleInfoEx (localeCode.c_str (), LOCALE_RETURN_NUMBER | LOCALE_ILANGUAGE, (LPWSTR)buf, LOCALE_NAME_MAX_LENGTH);
|
||||
LCID lcid = *((LCID *)buf);
|
||||
return lcid;
|
||||
}
|
||||
catch (const std::exception &e) {}
|
||||
return LocaleNameToLCID (localeCode.c_str (), 0);
|
||||
#else
|
||||
return LocaleNameToLCID (localeCode.c_str (), 0);
|
||||
#endif
|
||||
}
|
||||
LCID LocaleCodeToLcidA (const std::string &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'-')
|
||||
{
|
||||
#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
|
||||
try
|
||||
{
|
||||
WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0};
|
||||
LCIDToLocaleName (lcid, buf, LOCALE_NAME_MAX_LENGTH, 0);
|
||||
return buf;
|
||||
}
|
||||
catch (const std::exception &e) {}
|
||||
return GetLocaleRestrictedCodeFromLcidW (lcid) + divide + GetLocaleElaboratedCodeFromLcidW (lcid);
|
||||
#else
|
||||
return GetLocaleRestrictedCodeFromLcidW (lcid) + divide + GetLocaleElaboratedCodeFromLcidW (lcid);
|
||||
#endif
|
||||
}
|
||||
std::wstring LcidToLocaleCode (LCID lcid, WCHAR divide = L'-') { return LcidToLocaleCodeW (lcid, divide); }
|
||||
std::string LcidToLocaleCode (LCID lcid, char divide = '-') { return LcidToLocaleCodeA (lcid, divide); }
|
||||
|
||||
std::wstring GetUserDefaultLocaleName ()
|
||||
{
|
||||
#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
|
||||
try
|
||||
{
|
||||
WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0};
|
||||
GetUserDefaultLocaleName (buf, LOCALE_NAME_MAX_LENGTH);
|
||||
return buf;
|
||||
}
|
||||
catch (const std::exception &e) {}
|
||||
return LcidToLocaleCodeW (GetUserDefaultLCID ());
|
||||
#else
|
||||
return LcidToLocaleCodeW (GetUserDefaultLCID ());
|
||||
#endif
|
||||
}
|
||||
std::wstring GetSystemDefaultLocaleName ()
|
||||
{
|
||||
#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
|
||||
try
|
||||
{
|
||||
WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0};
|
||||
GetSystemDefaultLocaleName (buf, LOCALE_NAME_MAX_LENGTH);
|
||||
return buf;
|
||||
}
|
||||
catch (const std::exception &e) {}
|
||||
return LcidToLocaleCodeW (GetSystemDefaultLCID ());
|
||||
#else
|
||||
return LcidToLocaleCodeW (GetSystemDefaultLCID ());
|
||||
#endif
|
||||
}
|
||||
|
||||
std::wstring GetComputerLocaleCodeW ()
|
||||
{
|
||||
#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
|
||||
{
|
||||
try
|
||||
{
|
||||
{
|
||||
LCID lcid = GetThreadLocale ();
|
||||
std::wstring tmp = LcidToLocaleCodeW (lcid);
|
||||
if (lcid && tmp.length () > 1) return tmp;
|
||||
}
|
||||
{
|
||||
WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0};
|
||||
GetUserDefaultLocaleName (buf, LOCALE_NAME_MAX_LENGTH);
|
||||
if (lstrlenW (buf)) return buf;
|
||||
}
|
||||
{
|
||||
WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0};
|
||||
GetSystemDefaultLocaleName (buf, LOCALE_NAME_MAX_LENGTH);
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e) {}
|
||||
LCID lcid = GetThreadLocale ();
|
||||
if (!lcid) lcid = GetUserDefaultLCID ();
|
||||
if (!lcid) lcid = GetSystemDefaultLCID ();
|
||||
return LcidToLocaleCodeW (lcid);
|
||||
}
|
||||
#else
|
||||
{
|
||||
LCID lcid = GetThreadLocale ();
|
||||
if (!lcid) lcid = GetUserDefaultLCID ();
|
||||
if (!lcid) lcid = GetSystemDefaultLCID ();
|
||||
return LcidToLocaleCodeW (lcid);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
bool LocaleNameCompare (const std::wstring &left, const std::wstring &right)
|
||||
{
|
||||
return std::wnstring::equals (left, right) || LocaleCodeToLcidW (left) == LocaleCodeToLcidW (right);
|
||||
}
|
||||
42
priformatcli/mpstr.h
Normal file
42
priformatcli/mpstr.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
#include <windef.h>
|
||||
#include <string>
|
||||
#include <vcclr.h>
|
||||
|
||||
using namespace System;
|
||||
using namespace System::Text;
|
||||
|
||||
String ^CStringToMPString (LPCSTR lpstr) { return (lpstr ? gcnew String (lpstr) : String::Empty); }
|
||||
String ^CStringToMPString (LPCWSTR lpstr) { return (lpstr ? gcnew String (lpstr) : String::Empty); }
|
||||
String ^CStringToMPString (const std::string &objstr) { return CStringToMPString (objstr.c_str ()); }
|
||||
String ^CStringToMPString (const std::wstring &objstr) { return CStringToMPString (objstr.c_str ()); }
|
||||
// 转换为 UTF-16,指针不需要释放(本质是指针转换)
|
||||
LPCWSTR MPStringToPtrW (String ^in)
|
||||
{
|
||||
if (in == nullptr) return NULL;
|
||||
pin_ptr <const wchar_t> wch = PtrToStringChars (in);
|
||||
return wch;
|
||||
}
|
||||
// 转换为 std::wstring(UTF-16)
|
||||
std::wstring MPStringToStdW (String^ in)
|
||||
{
|
||||
if (in == nullptr) return std::wstring ();
|
||||
pin_ptr <const wchar_t> wch = PtrToStringChars (in);
|
||||
return std::wstring (wch, in->Length);
|
||||
}
|
||||
// 转换为 ANSI 编码的 std::string
|
||||
std::string MPStringToStdA (String^ in)
|
||||
{
|
||||
if (in == nullptr) return std::string ();
|
||||
array <unsigned char> ^bytes = Encoding::Default->GetBytes (in);
|
||||
pin_ptr <unsigned char> pinned = &bytes [0];
|
||||
return std::string (reinterpret_cast <const char *> (pinned), bytes->Length);
|
||||
}
|
||||
// 转换为 UTF-8 编码的 std::string
|
||||
std::string MPStringToStdU8 (String^ in)
|
||||
{
|
||||
if (in == nullptr) return std::string ();
|
||||
array <unsigned char> ^bytes = Encoding::UTF8->GetBytes (in);
|
||||
pin_ptr <unsigned char> pinned = &bytes [0];
|
||||
return std::string (reinterpret_cast <const char*> (pinned), bytes->Length);
|
||||
}
|
||||
457
priformatcli/nstring.h
Normal file
457
priformatcli/nstring.h
Normal file
@@ -0,0 +1,457 @@
|
||||
#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>
|
||||
{
|
||||
bool default_upper = false, default_include_blank_in_str = false;
|
||||
public:
|
||||
using base = std::basic_string <ct, tr, al>;
|
||||
using derive = std::basic_nstring <ct, tr, al>;
|
||||
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;
|
||||
}
|
||||
19
priformatcli/prifile.h
Normal file
19
priformatcli/prifile.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#using "./PriFileFormat.dll"
|
||||
using namespace PriFileFormat;
|
||||
#include <comip.h>
|
||||
#include <atlbase.h>
|
||||
#include <atlsafe.h>
|
||||
#include <objidl.h>
|
||||
#include <msclr/marshal.h>
|
||||
#include <msclr/gcroot.h>
|
||||
System::Runtime::InteropServices::ComTypes::IStream ^ComIStreamToCliIStream (IStream *pNativeStream)
|
||||
{
|
||||
if (pNativeStream == nullptr) throw gcnew System::ArgumentNullException ("pNativeStream");
|
||||
pNativeStream->AddRef ();
|
||||
System::IntPtr ptr (pNativeStream);
|
||||
// ½« IUnknown ת»»ÎªÍÐ¹Ü IStream
|
||||
System::Object ^obj = System::Runtime::InteropServices::Marshal::GetObjectForIUnknown (ptr);
|
||||
// ·µ»ØÎª ComTypes::IStream^
|
||||
return (System::Runtime::InteropServices::ComTypes::IStream ^)obj;
|
||||
}
|
||||
877
priformatcli/priformatcli.cpp
Normal file
877
priformatcli/priformatcli.cpp
Normal file
@@ -0,0 +1,877 @@
|
||||
// priformatcli.cpp : 定义 DLL 应用程序的导出函数。
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "priformatcli.h"
|
||||
#include "prifile.h"
|
||||
#include "typestrans.h"
|
||||
#include "mpstr.h"
|
||||
#include "nstring.h"
|
||||
#include "themeinfo.h"
|
||||
#include "localeex.h"
|
||||
#include "syncutil.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <cwchar>
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
|
||||
const std::wstring g_swMsResUriProtocolName = L"ms-resource:";
|
||||
const size_t g_cbMsResPNameLength = lstrlenW (g_swMsResUriProtocolName.c_str ());
|
||||
std::wstring g_swExcept = L"";
|
||||
CriticalSection g_csLastErr;
|
||||
CriticalSection g_threadlock;
|
||||
CriticalSection g_iterlock;
|
||||
struct destruct
|
||||
{
|
||||
std::function <void ()> endtask = nullptr;
|
||||
destruct (std::function <void ()> init): endtask (init) {}
|
||||
~destruct () { if (endtask) endtask (); }
|
||||
};
|
||||
void SetPriLastError (const std::wstring &lpMsg)
|
||||
{
|
||||
CreateScopedLock (g_csLastErr);
|
||||
g_swExcept = lpMsg;
|
||||
}
|
||||
enum class OpenType
|
||||
{
|
||||
Unknown,
|
||||
IStream,
|
||||
Stream
|
||||
};
|
||||
ref class PriFileInst
|
||||
{
|
||||
public:
|
||||
PriFile ^inst = nullptr;
|
||||
OpenType opentype = OpenType::Unknown;
|
||||
IStream *isptr = nullptr;
|
||||
System::IO::FileStream ^fsptr = nullptr;
|
||||
operator PriFile ^ () { return inst; }
|
||||
operator IStream * () { return isptr; }
|
||||
operator System::IO::FileStream ^ () { return fsptr; }
|
||||
explicit operator bool () { return inst && (int)opentype && ((bool)isptr ^ (fsptr != nullptr)); }
|
||||
operator System::IO::Stream ^ ()
|
||||
{
|
||||
if (isptr) return gcnew ComStreamWrapper (ComIStreamToCliIStream (isptr));
|
||||
else return fsptr;
|
||||
}
|
||||
size_t Seek (int64_t offset, System::IO::SeekOrigin origin)
|
||||
{
|
||||
if (isptr)
|
||||
{
|
||||
ULARGE_INTEGER ul;
|
||||
ul.QuadPart = 0;
|
||||
LARGE_INTEGER lo;
|
||||
lo.QuadPart = offset;
|
||||
DWORD dwOrigin = 0;
|
||||
switch (origin)
|
||||
{
|
||||
case System::IO::SeekOrigin::Begin: dwOrigin = STREAM_SEEK_SET;
|
||||
break;
|
||||
case System::IO::SeekOrigin::Current: dwOrigin = STREAM_SEEK_CUR;
|
||||
break;
|
||||
case System::IO::SeekOrigin::End: dwOrigin = STREAM_SEEK_END;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
HRESULT hr = isptr->Seek (lo, dwOrigin, &ul);
|
||||
return ul.QuadPart;
|
||||
}
|
||||
else if (fsptr)
|
||||
{
|
||||
return fsptr->Seek (offset, origin);
|
||||
}
|
||||
throw gcnew NullReferenceException ("Error: cannot get the stream.");
|
||||
return 0;
|
||||
}
|
||||
!PriFileInst ()
|
||||
{
|
||||
if (fsptr)
|
||||
{
|
||||
fsptr->Close ();
|
||||
delete fsptr;
|
||||
fsptr = nullptr;
|
||||
}
|
||||
if (inst)
|
||||
{
|
||||
delete inst;
|
||||
inst = nullptr;
|
||||
}
|
||||
}
|
||||
~PriFileInst ()
|
||||
{
|
||||
if (fsptr)
|
||||
{
|
||||
fsptr->Close ();
|
||||
delete fsptr;
|
||||
fsptr = nullptr;
|
||||
}
|
||||
if (inst)
|
||||
{
|
||||
delete inst;
|
||||
inst = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
std::wstring GetStringLeft (const std::wstring &str, size_t length = 1)
|
||||
{
|
||||
std::wstring ret = L"";
|
||||
ret.reserve (length + 1);
|
||||
size_t slen = lstrlenW (str.c_str ());
|
||||
for (size_t i = 0; i < length && i < slen; i ++)
|
||||
{
|
||||
ret += str.at (i);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
std::wstring GetStringRight (const std::wstring &str, size_t length = 1)
|
||||
{
|
||||
std::wstring ret = L"";
|
||||
ret.reserve (length + 1);
|
||||
size_t slen = lstrlenW (str.c_str ());
|
||||
for (size_t i = ((int64_t)slen - length) < 0 ? 0 : slen - length; i < slen; i ++) ret += str.at (i);
|
||||
return ret;
|
||||
}
|
||||
std::string GetStringLeft (const std::string &str, size_t length = 1)
|
||||
{
|
||||
std::string ret = "";
|
||||
ret.reserve (length + 1);
|
||||
size_t slen = strlen (str.c_str ());
|
||||
for (size_t i = 0; i < length && i < slen; i ++)
|
||||
{
|
||||
ret += str.at (i);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
std::string GetStringRight (const std::string &str, size_t length = 1)
|
||||
{
|
||||
std::string ret = "";
|
||||
ret.reserve (length + 1);
|
||||
size_t slen = strlen (str.c_str ());
|
||||
for (size_t i = ((int64_t)slen - length) < 0 ? 0 : slen - length; i < slen; i ++) ret += str.at (i);
|
||||
return ret;
|
||||
}
|
||||
size_t KeyToPath (const std::wstring &key, std::vector <std::wnstring> &output);
|
||||
typedef struct _TASKITEM_SEARCH
|
||||
{
|
||||
std::wstring swKey;
|
||||
int iTaskType; // 0: 字符串,1: 文件路径
|
||||
operator std::wstring () { return swKey; }
|
||||
operator LPCWSTR () { return swKey.c_str (); }
|
||||
operator std::wnstring () { return swKey; }
|
||||
void set_key (const std::wstring &value)
|
||||
{
|
||||
iTaskType = std::wnstring (GetStringLeft (std::wnstring::trim (value), g_cbMsResPNameLength)) != g_swMsResUriProtocolName;
|
||||
swKey = value;
|
||||
}
|
||||
bool isuri () const
|
||||
{
|
||||
return std::wnstring (GetStringLeft (std::wnstring::trim (swKey), g_cbMsResPNameLength)) == g_swMsResUriProtocolName;
|
||||
}
|
||||
bool isfulluri () const
|
||||
{
|
||||
const std::wstring root = L"//";
|
||||
return std::wnstring (GetStringLeft (std::wnstring::trim (swKey), g_cbMsResPNameLength + root.length ())) == g_swMsResUriProtocolName + root;
|
||||
}
|
||||
bool isfilepath () const { return !isuri (); }
|
||||
bool isrelativeuri () const { return !isfulluri () && isuri (); }
|
||||
size_t get_path (std::vector <std::wnstring> &output) const
|
||||
{
|
||||
output.clear ();
|
||||
auto &path = output;
|
||||
KeyToPath (swKey, path);
|
||||
if (isrelativeuri ())
|
||||
{
|
||||
std::wstring nopre = GetStringRight (swKey, swKey.length () - g_cbMsResPNameLength);
|
||||
std::wstring firstch = GetStringLeft (nopre, 1);
|
||||
if (firstch [0] != L'/') path.insert (path.begin (), L"resources");
|
||||
}
|
||||
else if (isfilepath ()) path.insert (path.begin (), L"Files");
|
||||
return output.size ();
|
||||
}
|
||||
_TASKITEM_SEARCH &operator = (const std::wstring &v)
|
||||
{
|
||||
set_key (v);
|
||||
return *this;
|
||||
}
|
||||
explicit _TASKITEM_SEARCH (const std::wstring &v, int type = -1)
|
||||
{
|
||||
if (type < 0 || type > 1) set_key (v);
|
||||
else
|
||||
{
|
||||
swKey = v;
|
||||
iTaskType = type;
|
||||
}
|
||||
}
|
||||
_TASKITEM_SEARCH (int type, const std::wstring &v = L"")
|
||||
{
|
||||
if (type < 0 || type > 1) set_key (v);
|
||||
else
|
||||
{
|
||||
swKey = v;
|
||||
iTaskType = type;
|
||||
}
|
||||
}
|
||||
_TASKITEM_SEARCH () = default;
|
||||
bool operator == (const _TASKITEM_SEARCH &another) const
|
||||
{
|
||||
return std::wnstring (swKey).equals (another.swKey);
|
||||
}
|
||||
bool operator < (const _TASKITEM_SEARCH &another) const
|
||||
{
|
||||
return std::wnstring (swKey).compare (another.swKey) < 0;
|
||||
}
|
||||
} TASKITEM_SEARCH;
|
||||
typedef struct _TASKRESULT_FIND
|
||||
{
|
||||
std::wstring swValue = L"";
|
||||
int iFindResult = -1; // -1 未进行查找,0:查找但未找到,1:查找且已找到
|
||||
operator std::wstring () { return swValue; }
|
||||
operator LPCWSTR () { return swValue.c_str (); }
|
||||
operator std::wnstring () { return swValue; }
|
||||
_TASKRESULT_FIND (const std::wstring &v, int findres = -1):
|
||||
swValue (v), iFindResult (findres) {}
|
||||
_TASKRESULT_FIND (int findres, const std::wstring &v = L""):
|
||||
swValue (v), iFindResult (findres) {}
|
||||
_TASKRESULT_FIND () = default;
|
||||
// 是否查找到
|
||||
bool is_find () const { return iFindResult > 0; }
|
||||
// 是否进行过查找
|
||||
bool has_search () const { return iFindResult >= 0; }
|
||||
} TASKRESULT_FIND;
|
||||
typedef struct _TASKINFO_SEARCH
|
||||
{
|
||||
bool bIsRunning = false;
|
||||
std::map <TASKITEM_SEARCH, TASKRESULT_FIND> mapTasks;
|
||||
operator std::map <TASKITEM_SEARCH, TASKRESULT_FIND> () { return mapTasks; }
|
||||
} TASKINFO_SEARCH;
|
||||
|
||||
size_t UriToPath (System::Uri ^uri, std::vector <std::wnstring> &output)
|
||||
{
|
||||
output.clear ();
|
||||
try
|
||||
{
|
||||
auto path = uri->AbsolutePath;
|
||||
auto arr = path->Split ('/');
|
||||
for (size_t i = 0; i < arr->Length; i ++)
|
||||
{
|
||||
auto str = arr [i];
|
||||
std::wnstring cppstr = MPStringToStdW (str);
|
||||
if (cppstr.empty ()) continue;
|
||||
output.push_back (cppstr);
|
||||
}
|
||||
}
|
||||
catch (Exception ^e)
|
||||
{
|
||||
SetPriLastError (MPStringToStdW (e->Message));
|
||||
}
|
||||
return output.size ();
|
||||
}
|
||||
std::vector <std::wstring> split_wcstok (const std::wstring &str, const std::wstring &delim)
|
||||
{
|
||||
std::vector <std::wstring> result;
|
||||
std::wstring cpy = L"" + str;
|
||||
LPWSTR context = nullptr;
|
||||
LPWSTR token = wcstok ((LPWSTR)cpy.c_str (), delim.c_str (), &context);
|
||||
while (token)
|
||||
{
|
||||
result.push_back (token);
|
||||
token = wcstok (nullptr, delim.c_str (), &context);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
std::vector <std::wnstring> VecWStringToWNString (const std::vector <std::wstring> &vec)
|
||||
{
|
||||
std::vector <std::wnstring> wns;
|
||||
wns.reserve (vec.size ());
|
||||
for (auto &it : vec) wns.push_back (it);
|
||||
return wns;
|
||||
}
|
||||
size_t KeyToPath (const std::wstring &key, std::vector <std::wnstring> &output)
|
||||
{
|
||||
output.clear ();
|
||||
try
|
||||
{
|
||||
// 1: 字符串,0: 文件路径
|
||||
int iTaskType = std::wnstring (GetStringLeft (key, g_cbMsResPNameLength)) == g_swMsResUriProtocolName;
|
||||
if (iTaskType)
|
||||
{
|
||||
Uri ^uri = gcnew Uri (CStringToMPString (key.c_str ()));
|
||||
size_t ret = UriToPath (uri, output);
|
||||
delete uri;
|
||||
uri = nullptr;
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto arr = split_wcstok (key, L"\\");
|
||||
for (auto &it : arr)
|
||||
{
|
||||
if (std::wnstring (it).empty ()) continue;
|
||||
else output.push_back (it);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ^e)
|
||||
{
|
||||
auto arr = split_wcstok (key, L"\\");
|
||||
for (auto &it : arr)
|
||||
{
|
||||
if (std::wnstring (it).empty ()) continue;
|
||||
else output.push_back (it);
|
||||
}
|
||||
}
|
||||
return output.size ();
|
||||
}
|
||||
size_t KeyToPath (const TASKITEM_SEARCH &key, std::vector <std::wnstring> &output)
|
||||
{
|
||||
return KeyToPath (key.swKey, output);
|
||||
}
|
||||
bool PathEquals (const std::vector <std::wnstring> &left, const std::vector <std::wnstring> &right)
|
||||
{
|
||||
if (left.size () != right.size ()) return false;
|
||||
try
|
||||
{
|
||||
for (size_t i = 0; i < left.size () && i < right.size (); i ++)
|
||||
{
|
||||
if (left.at (i) != right.at (i)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception &e) {}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::map <PCSPRIFILE, TASKINFO_SEARCH> g_tasklist;
|
||||
|
||||
PCSPRIFILE CreatePriFileInstanceFromStream (PCOISTREAM pStream)
|
||||
{
|
||||
if (!pStream) return nullptr;
|
||||
try
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (pStream) hr = ((IStream *)pStream)->Seek (LARGE_INTEGER {}, STREAM_SEEK_SET, nullptr);
|
||||
auto pri = PriFile::Parse (ComIStreamToCliIStream (reinterpret_cast <IStream *> (pStream)));
|
||||
PriFileInst ^inst = gcnew PriFileInst ();
|
||||
inst->inst = pri;
|
||||
inst->opentype = OpenType::IStream;
|
||||
inst->isptr = reinterpret_cast <IStream *> (pStream);
|
||||
auto handle = System::Runtime::InteropServices::GCHandle::Alloc (inst);
|
||||
IntPtr token = System::Runtime::InteropServices::GCHandle::ToIntPtr (handle);
|
||||
return reinterpret_cast <PCSPRIFILE> (token.ToPointer ());
|
||||
}
|
||||
catch (System::Exception ^e)
|
||||
{
|
||||
SetPriLastError (MPStringToStdW (e->Message));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
PCSPRIFILE CreatePriFileInstanceFromPath (LPCWSTR lpswFilePath)
|
||||
{
|
||||
if (!lpswFilePath) return nullptr;
|
||||
if (!*lpswFilePath) return nullptr;
|
||||
try
|
||||
{
|
||||
auto fstream = System::IO::File::OpenRead (CStringToMPString (lpswFilePath ? lpswFilePath : L""));
|
||||
auto pri = PriFile::Parse (fstream);
|
||||
PriFileInst ^inst = gcnew PriFileInst ();
|
||||
inst->inst = pri;
|
||||
inst->opentype = OpenType::Stream;
|
||||
inst->fsptr = fstream;
|
||||
auto handle = System::Runtime::InteropServices::GCHandle::Alloc (inst);
|
||||
IntPtr token = System::Runtime::InteropServices::GCHandle::ToIntPtr (handle);
|
||||
return reinterpret_cast <PCSPRIFILE> (token.ToPointer ());
|
||||
}
|
||||
catch (System::Exception ^e)
|
||||
{
|
||||
SetPriLastError (MPStringToStdW (e->Message));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
void DestroyPriFileInstance (PCSPRIFILE pFilePri)
|
||||
{
|
||||
if (!pFilePri) return;
|
||||
try
|
||||
{
|
||||
if (g_tasklist.find (pFilePri) != g_tasklist.end ())
|
||||
{
|
||||
g_tasklist [pFilePri].bIsRunning = false;
|
||||
g_tasklist.erase (pFilePri);
|
||||
}
|
||||
IntPtr handlePtr = IntPtr (pFilePri);
|
||||
System::Runtime::InteropServices::GCHandle handle = System::Runtime::InteropServices::GCHandle::FromIntPtr (handlePtr);
|
||||
PriFileInst ^inst = safe_cast <PriFileInst ^> (handle.Target);
|
||||
delete inst;
|
||||
handle.Free ();
|
||||
System::GC::Collect ();
|
||||
System::GC::WaitForPendingFinalizers ();
|
||||
System::GC::Collect ();
|
||||
}
|
||||
catch (System::Exception ^e)
|
||||
{
|
||||
SetPriLastError (MPStringToStdW (e->Message));
|
||||
}
|
||||
}
|
||||
LPCWSTR PriFileGetLastError ()
|
||||
{
|
||||
CreateScopedLock (g_csLastErr);
|
||||
return g_swExcept.c_str ();
|
||||
}
|
||||
enum class Contrast
|
||||
{
|
||||
None,
|
||||
White,
|
||||
Black,
|
||||
High,
|
||||
Low
|
||||
};
|
||||
struct candidate_value
|
||||
{
|
||||
int type; // 1:语言;2:缩放和对比度;0:未知
|
||||
std::wstring value;
|
||||
union restitem
|
||||
{
|
||||
struct // type==1
|
||||
{
|
||||
std::wstring languages;
|
||||
};
|
||||
struct // type==2
|
||||
{
|
||||
uint32_t scale;
|
||||
Contrast contrast;
|
||||
};
|
||||
struct // type==0
|
||||
{
|
||||
std::wstring not_support_restrict;
|
||||
};
|
||||
restitem () {} // 不做初始化,由外层控制构造
|
||||
~restitem () {} // 不自动析构,由外层控制析构
|
||||
} restitems;
|
||||
candidate_value (const std::wstring &val, const std::wstring &lang): type (1), value (val)
|
||||
{
|
||||
new(&restitems.languages) std::wstring (lang);
|
||||
}
|
||||
candidate_value (const std::wstring &val, uint32_t scale, Contrast contrast = Contrast::None): type (2), value (val)
|
||||
{
|
||||
restitems.scale = scale;
|
||||
restitems.contrast = contrast;
|
||||
}
|
||||
candidate_value (const std::wstring &val): type (0), value (val)
|
||||
{
|
||||
new (&restitems.not_support_restrict) std::wstring (L"");
|
||||
}
|
||||
candidate_value (const candidate_value &other): type (other.type), value (other.value)
|
||||
{
|
||||
if (type == 1) new(&restitems.languages) std::wstring (other.restitems.languages);
|
||||
else if (type == 2)
|
||||
{
|
||||
restitems.scale = other.restitems.scale;
|
||||
restitems.contrast = other.restitems.contrast;
|
||||
}
|
||||
else new (&restitems.not_support_restrict) std::wstring (other.restitems.not_support_restrict);
|
||||
}
|
||||
candidate_value &operator = (const candidate_value &other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
this->~candidate_value (); // 先析构旧内容
|
||||
new (this) candidate_value (other); // 再调用拷贝构造
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
~candidate_value ()
|
||||
{
|
||||
if (type == 1) restitems.languages.~basic_string ();
|
||||
else if (type == 0) restitems.not_support_restrict.~basic_string ();
|
||||
}
|
||||
std::wstring get_language () const { return type == 1 ? restitems.languages : L""; }
|
||||
uint32_t get_scale () const { return type == 2 ? restitems.scale : 0; }
|
||||
Contrast get_contrast () const { return type == 2 ? restitems.contrast : Contrast::None; }
|
||||
};
|
||||
std::wstring GetStringValueByLocale (std::vector <candidate_value> &stringcand, const std::wstring &llc)
|
||||
{
|
||||
for (auto &it : stringcand)
|
||||
{
|
||||
if (LocaleNameCompare (it.get_language (), llc)) return it.value;
|
||||
}
|
||||
std::vector <std::wstring> scrc;
|
||||
for (auto &it : stringcand)
|
||||
{
|
||||
std::wstring rc;
|
||||
scrc.push_back (rc = GetLocaleRestrictedCodeFromLcidW (LocaleCodeToLcidW (it.get_language ())));
|
||||
if (LocaleNameCompare (rc, llc)) return it.value;
|
||||
}
|
||||
std::wstring lrc = GetLocaleRestrictedCodeFromLcidW (LocaleCodeToLcidW (llc));
|
||||
for (size_t i = 0; i < stringcand.size (); i ++)
|
||||
{
|
||||
auto &rc = scrc.at (i);
|
||||
auto &it = stringcand.at (i);
|
||||
if (LocaleNameCompare (rc, llc)) return it.value;
|
||||
}
|
||||
return L"";
|
||||
}
|
||||
std::wstring GetSuitableStringValue (std::vector <candidate_value> &stringcand)
|
||||
{
|
||||
std::wstring ret = GetStringValueByLocale (stringcand, GetComputerLocaleCodeW ());
|
||||
if (ret.empty () || std::wnstring::trim (ret).length () == 0) ret = GetStringValueByLocale (stringcand, L"en-US");
|
||||
if (ret.empty () || std::wnstring::trim (ret).length () == 0)
|
||||
{
|
||||
for (auto &it : stringcand) return it.value;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
std::wstring GetSuitablePathValueByDPI (std::vector<candidate_value> &pathcand)
|
||||
{
|
||||
std::sort (pathcand.begin (), pathcand.end (),
|
||||
[] (const candidate_value &v1, const candidate_value &v2) {
|
||||
return v1.get_scale () < v2.get_scale ();
|
||||
});
|
||||
if (pathcand.empty ()) return L"";
|
||||
uint32_t nowdpi = GetDPI ();
|
||||
for (auto &cv : pathcand) if (cv.get_scale () >= nowdpi) return cv.value;
|
||||
return pathcand.back ().value;
|
||||
}
|
||||
std::wstring GetSuitablePathValue (std::vector <candidate_value> &pathcand)
|
||||
{
|
||||
std::vector <candidate_value> contrasted;
|
||||
for (auto &it : pathcand) if (it.get_contrast () == Contrast::None) contrasted.emplace_back (it);
|
||||
std::wstring ret = GetSuitablePathValueByDPI (contrasted);
|
||||
if (std::wnstring (ret).empty ())
|
||||
{
|
||||
contrasted.clear ();
|
||||
for (auto &it: pathcand) if (it.get_contrast () == Contrast::White) contrasted.emplace_back (it);
|
||||
ret = GetSuitablePathValueByDPI (contrasted);
|
||||
}
|
||||
if (std::wnstring (ret).empty ())
|
||||
{
|
||||
contrasted.clear ();
|
||||
for (auto &it : pathcand) if (it.get_contrast () == Contrast::Black) contrasted.emplace_back (it);
|
||||
ret = GetSuitablePathValueByDPI (contrasted);
|
||||
}
|
||||
if (std::wnstring (ret).empty ())
|
||||
{
|
||||
contrasted.clear ();
|
||||
for (auto &it : pathcand) contrasted.emplace_back (it);
|
||||
ret = GetSuitablePathValueByDPI (contrasted);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void PriFileIterateTask (PCSPRIFILE pFilePri)
|
||||
{
|
||||
CreateScopedLock (g_threadlock);
|
||||
if (g_tasklist.find (pFilePri) == g_tasklist.end ()) g_tasklist [pFilePri] = TASKINFO_SEARCH ();
|
||||
try { g_tasklist.at (pFilePri); } catch (const std::exception &e) { return; }
|
||||
auto &task = g_tasklist.at (pFilePri);
|
||||
if (task.bIsRunning == false) task.bIsRunning = true;
|
||||
else return;
|
||||
destruct endt ([&task] () {
|
||||
task.bIsRunning = false;
|
||||
});
|
||||
auto &taskitems = task.mapTasks;
|
||||
IntPtr handlePtr = IntPtr (pFilePri);
|
||||
System::Runtime::InteropServices::GCHandle handle = System::Runtime::InteropServices::GCHandle::FromIntPtr (handlePtr);
|
||||
auto pri = safe_cast <PriFileInst ^> (handle.Target);
|
||||
auto &priFile = pri;
|
||||
auto resmapsect = pri->inst->PriDescriptorSection->ResourceMapSections;
|
||||
bool isallsearched = true;
|
||||
size_t allitemslen = 0;
|
||||
std::map <std::wnstring, size_t> mapitemscnt;
|
||||
auto begtime = System::DateTime::Now;
|
||||
SearchLoop:
|
||||
allitemslen = 0;
|
||||
for (size_t i = 0; i < resmapsect->Count; i ++)
|
||||
{
|
||||
CreateScopedLock (g_iterlock);
|
||||
auto resourceMapSectionRef = resmapsect [i];
|
||||
auto resourceMapSection = pri->inst->GetSectionByRef (resourceMapSectionRef);
|
||||
if (resourceMapSection->HierarchicalSchemaReference != nullptr) continue;
|
||||
auto decisionInfoSection = pri->inst->GetSectionByRef (resourceMapSection->DecisionInfoSection);
|
||||
for each (auto candidateSet in resourceMapSection->CandidateSets->Values)
|
||||
{
|
||||
// 超时强制退出(也就没有遍及的必要了)
|
||||
if ((System::DateTime::Now - begtime).TotalSeconds > 20) return;
|
||||
allitemslen ++;
|
||||
auto item = pri->inst->GetResourceMapItemByRef (candidateSet->ResourceMapItem);
|
||||
std::wstring itemfullname = MPStringToStdW (item->FullName);
|
||||
std::vector <std::wnstring> itempath;
|
||||
{
|
||||
auto ips = split_wcstok (itemfullname, L"\\");
|
||||
for (auto &it : ips)
|
||||
{
|
||||
if (std::wnstring::empty (it)) continue;
|
||||
itempath.push_back (it);
|
||||
}
|
||||
}
|
||||
bool willcont = true;
|
||||
TASKITEM_SEARCH *taskkey = nullptr;
|
||||
for (auto &it : taskitems)
|
||||
{
|
||||
auto &key = it.first;
|
||||
auto &value = it.second;
|
||||
mapitemscnt [key.swKey] ++;
|
||||
if (value.has_search ()) continue;
|
||||
std::vector <std::wnstring> namepath;
|
||||
key.get_path (namepath);
|
||||
// KeyToPath (key, namepath);
|
||||
if (PathEquals (itempath, namepath))
|
||||
{
|
||||
taskkey = (TASKITEM_SEARCH *)&key;
|
||||
willcont = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (willcont) continue;
|
||||
auto keyname = taskkey->swKey;
|
||||
auto keytype = taskkey->iTaskType;
|
||||
std::vector <candidate_value> cands;
|
||||
for each (auto candidate in candidateSet->Candidates)
|
||||
{
|
||||
System::String ^value = nullptr;
|
||||
if (candidate->SourceFile.HasValue)
|
||||
{
|
||||
// 内嵌资源,暂无法处理
|
||||
// value = System::String::Format ("<external in {0}>", pri->GetReferencedFileByRef (candidate->SourceFile.Value)->FullName);
|
||||
value = pri->inst->GetReferencedFileByRef (candidate->SourceFile.Value)->FullName;
|
||||
}
|
||||
else
|
||||
{
|
||||
ByteSpan ^byteSpan = nullptr;
|
||||
if (candidate->DataItem.HasValue) byteSpan = priFile->inst->GetDataItemByRef (candidate->DataItem.Value);
|
||||
else byteSpan = candidate->Data.Value;
|
||||
pri->Seek (byteSpan->Offset, System::IO::SeekOrigin::Begin);
|
||||
auto binaryReader = gcnew System::IO::BinaryReader (pri, System::Text::Encoding::Default, true);
|
||||
auto data = binaryReader->ReadBytes ((int)byteSpan->Length);
|
||||
switch (candidate->Type)
|
||||
{
|
||||
case ResourceValueType::AsciiPath:
|
||||
case ResourceValueType::AsciiString:
|
||||
value = System::Text::Encoding::ASCII->GetString (data)->TrimEnd ('\0');
|
||||
break;
|
||||
case ResourceValueType::Utf8Path:
|
||||
case ResourceValueType::Utf8String:
|
||||
value = System::Text::Encoding::UTF8->GetString (data)->TrimEnd ('\0');
|
||||
break;
|
||||
case ResourceValueType::Path:
|
||||
case ResourceValueType::String:
|
||||
value = System::Text::Encoding::Unicode->GetString (data)->TrimEnd ('\0');
|
||||
break;
|
||||
case ResourceValueType::EmbeddedData:
|
||||
value = Convert::ToBase64String (data);
|
||||
break;
|
||||
}
|
||||
delete binaryReader;
|
||||
delete data;
|
||||
binaryReader = nullptr;
|
||||
data = nullptr;
|
||||
}
|
||||
auto qualifierSet = decisionInfoSection->QualifierSets [candidate->QualifierSet];
|
||||
auto qualis = gcnew System::Collections::Generic::Dictionary <QualifierType, Object ^> ();
|
||||
for each (auto quali in qualifierSet->Qualifiers)
|
||||
{
|
||||
auto type = quali->Type;
|
||||
auto value = quali->Value;
|
||||
qualis->Add (type, value);
|
||||
}
|
||||
if (qualis->ContainsKey (QualifierType::Language))
|
||||
{
|
||||
cands.push_back (candidate_value (MPStringToStdW (value ? value : System::String::Empty), MPStringToStdW (qualis [QualifierType::Language]->ToString ())));
|
||||
}
|
||||
else if (qualis->ContainsKey (QualifierType::Scale))
|
||||
{
|
||||
if (qualis->ContainsKey (QualifierType::Contrast))
|
||||
{
|
||||
Contrast ct = Contrast::None;
|
||||
auto contstr = std::wnstring (MPStringToStdW (qualis [QualifierType::Contrast]->ToString ()->Trim ()->ToUpper ()));
|
||||
if (contstr.equals (L"WHITE")) ct = Contrast::White;
|
||||
else if (contstr.equals (L"BLACK")) ct = Contrast::Black;
|
||||
else if (contstr.equals (L"HIGH")) ct = Contrast::High;
|
||||
cands.push_back (candidate_value (
|
||||
MPStringToStdW (value ? value : System::String::Empty),
|
||||
Convert::ToUInt32 (qualis [QualifierType::Scale]),
|
||||
ct
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
cands.push_back (candidate_value (
|
||||
MPStringToStdW (value ? value : System::String::Empty),
|
||||
Convert::ToUInt32 (qualis [QualifierType::Scale])
|
||||
));
|
||||
}
|
||||
}
|
||||
else cands.push_back (candidate_value (MPStringToStdW (value ? value : System::String::Empty)));
|
||||
delete qualis;
|
||||
qualis = nullptr;
|
||||
}
|
||||
switch (keytype)
|
||||
{
|
||||
case 0: {
|
||||
TASKRESULT_FIND tfind;
|
||||
tfind.iFindResult = 1;
|
||||
tfind.swValue = GetSuitableStringValue (cands);
|
||||
taskitems [*taskkey] = tfind;
|
||||
} break;
|
||||
case 1: {
|
||||
TASKRESULT_FIND tfind;
|
||||
tfind.iFindResult = 1;
|
||||
tfind.swValue = GetSuitablePathValue (cands);
|
||||
taskitems [*taskkey] = tfind;
|
||||
} break;
|
||||
default: {
|
||||
TASKRESULT_FIND tfind;
|
||||
tfind.iFindResult = 0;
|
||||
try
|
||||
{
|
||||
tfind.swValue = cands.at (0).value;
|
||||
}
|
||||
catch (const std::exception &e) {}
|
||||
taskitems [*taskkey] = tfind;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
// delete resourceMapSection;
|
||||
resourceMapSection = nullptr;
|
||||
}
|
||||
isallsearched = true;
|
||||
for (auto &it : mapitemscnt)
|
||||
{
|
||||
auto &result = taskitems [TASKITEM_SEARCH (it.first)];
|
||||
isallsearched = isallsearched && (it.second >= allitemslen && result.has_search ());
|
||||
if (it.second >= allitemslen)
|
||||
{
|
||||
if (!result.has_search ()) result.iFindResult = 0;
|
||||
}
|
||||
it.second = 0;
|
||||
}
|
||||
if (!isallsearched)
|
||||
{
|
||||
for (auto &it : mapitemscnt) it.second = 0;
|
||||
goto SearchLoop;
|
||||
}
|
||||
// task.bIsRunning = false;
|
||||
}
|
||||
void PriFileIterateTaskCli (Object^ pFilePriObj)
|
||||
{
|
||||
if (pFilePriObj == nullptr) return;
|
||||
IntPtr ptr = safe_cast <IntPtr> (pFilePriObj);
|
||||
PCSPRIFILE pFilePri = (PCSPRIFILE)ptr.ToPointer ();
|
||||
PriFileIterateTask (pFilePri);
|
||||
}
|
||||
void AddPriResourceName (PCSPRIFILE pFilePri, const std::vector <std::wnstring> &urilist)
|
||||
{
|
||||
if (!pFilePri) return;
|
||||
if (!urilist.size ()) return;
|
||||
try { g_tasklist.at (pFilePri); } catch (const std::exception &e) { g_tasklist [pFilePri] = TASKINFO_SEARCH (); }
|
||||
auto &task = g_tasklist.at (pFilePri);
|
||||
bool isallfined = true;
|
||||
{
|
||||
CreateScopedLock (g_threadlock);
|
||||
CreateScopedLock (g_iterlock);
|
||||
for (auto &it : urilist)
|
||||
{
|
||||
if (it.empty ()) continue;
|
||||
try
|
||||
{
|
||||
if (task.mapTasks [TASKITEM_SEARCH (it)].has_search ())
|
||||
{
|
||||
isallfined = isallfined && true;
|
||||
continue;
|
||||
}
|
||||
else isallfined = isallfined && false;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
task.mapTasks [TASKITEM_SEARCH (it)] = TASKRESULT_FIND ();
|
||||
isallfined = isallfined && false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isallfined) return;
|
||||
// while (task.bIsRunning) { Sleep (200); }
|
||||
System::Threading::Thread ^t = nullptr;
|
||||
if (!task.bIsRunning)
|
||||
{
|
||||
// task.bIsRunning = true;
|
||||
t = gcnew System::Threading::Thread (gcnew System::Threading::ParameterizedThreadStart (PriFileIterateTaskCli));
|
||||
t->IsBackground = true;
|
||||
t->Start (IntPtr (pFilePri));
|
||||
}
|
||||
}
|
||||
void FindPriResource (PCSPRIFILE pFilePri, HLPCWSTRLIST hUriList)
|
||||
{
|
||||
if (!pFilePri) return;
|
||||
if (!hUriList || !hUriList->dwLength) return;
|
||||
std::vector <std::wnstring> list;
|
||||
for (size_t i = 0; i < hUriList->dwLength; i ++)
|
||||
{
|
||||
auto &str = hUriList->aswArray [i];
|
||||
if (!str || !*str) continue;
|
||||
std::wnstring wstr (str);
|
||||
if (wstr.empty ()) continue;
|
||||
list.emplace_back (wstr);
|
||||
}
|
||||
AddPriResourceName (pFilePri, list);
|
||||
}
|
||||
void FindPriStringResource (PCSPRIFILE pFilePri, HLPCWSTRLIST hUriList)
|
||||
{
|
||||
FindPriResource (pFilePri, hUriList);
|
||||
}
|
||||
void FindPriPathResource (PCSPRIFILE pFilePri, HLPCWSTRLIST hPathList)
|
||||
{
|
||||
FindPriResource (pFilePri, hPathList);
|
||||
}
|
||||
LPWSTR GetPriResource (PCSPRIFILE pFilePri, LPCWSTR lpswResId)
|
||||
{
|
||||
if (!pFilePri || !lpswResId || !*lpswResId) return nullptr;
|
||||
try { g_tasklist.at (pFilePri); }
|
||||
catch (const std::exception &e) { g_tasklist [pFilePri]; }
|
||||
auto &task = g_tasklist.at (pFilePri);
|
||||
{
|
||||
auto &result = task.mapTasks [TASKITEM_SEARCH (lpswResId)];
|
||||
if (result.has_search ()) return _wcsdup (result.swValue.c_str ());
|
||||
}
|
||||
BYTE buf [sizeof (LPCWSTRLIST) + sizeof (LPCWSTR)] = {0};
|
||||
HLPCWSTRLIST hStrList = (HLPCWSTRLIST)buf;
|
||||
hStrList->dwLength = 1;
|
||||
hStrList->aswArray [0] = lpswResId;
|
||||
FindPriResource (pFilePri, hStrList);
|
||||
while (task.bIsRunning) { Sleep (200); }
|
||||
try
|
||||
{
|
||||
auto item = task.mapTasks.at (TASKITEM_SEARCH (lpswResId));
|
||||
if (!item.has_search ()) return GetPriResource (pFilePri, lpswResId);
|
||||
return _wcsdup (item.swValue.c_str ());
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
SetPriLastError (StringToWString (e.what () ? e.what () : "Error: cannot find the resource."));
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
LPWSTR GetPriStringResource (PCSPRIFILE pFilePri, LPCWSTR lpswUri) { return GetPriResource (pFilePri, lpswUri); }
|
||||
LPWSTR GetPriPathResource (PCSPRIFILE pFilePri, LPCWSTR lpswFilePath) { return GetPriResource (pFilePri, lpswFilePath); }
|
||||
void ClearPriCacheData ()
|
||||
{
|
||||
g_tasklist.clear ();
|
||||
}
|
||||
|
||||
BOOL IsMsResourcePrefix (LPCWSTR pResName)
|
||||
{
|
||||
return std::wnstring (GetStringLeft (std::wnstring::trim (std::wstring (pResName ? pResName : L"")), g_cbMsResPNameLength)) == g_swMsResUriProtocolName;
|
||||
}
|
||||
BOOL IsMsResourceUriFull (LPCWSTR pResUri)
|
||||
{
|
||||
const std::wstring root = L"//";
|
||||
return std::wnstring (GetStringLeft (std::wnstring::trim (std::wstring (pResUri)), g_cbMsResPNameLength + root.length ())) == g_swMsResUriProtocolName + root;
|
||||
}
|
||||
BOOL IsMsResourceUri (LPCWSTR pResUri)
|
||||
{
|
||||
if (!IsMsResourcePrefix (pResUri)) return false;
|
||||
try { Uri ^uri = gcnew Uri (gcnew String (pResUri ? pResUri : L"")); delete uri; }
|
||||
catch (Exception ^e) { return false; }
|
||||
return true;
|
||||
}
|
||||
315
priformatcli/priformatcli.h
Normal file
315
priformatcli/priformatcli.h
Normal file
@@ -0,0 +1,315 @@
|
||||
// 下列 ifdef 块是创建使从 DLL 导出更简单的
|
||||
// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 PRIFORMATCLI_EXPORTS
|
||||
// 符号编译的。在使用此 DLL 的
|
||||
// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
|
||||
// PRIFORMATCLI_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
|
||||
// 符号视为是被导出的。
|
||||
#ifdef PRIFORMATCLI_EXPORTS
|
||||
#define PRIFORMATCLI_API __declspec(dllexport)
|
||||
#else
|
||||
#define PRIFORMATCLI_API __declspec(dllimport)
|
||||
#endif
|
||||
|
||||
#ifndef _PRI_READER_CLI_HEADER_
|
||||
#define _PRI_READER_CLI_HEADER_
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define _DEFAULT_VALUE_SET(valueexpr) = valueexpr
|
||||
#ifndef PRIFORMATCLI_EXPORTS
|
||||
#define _DEFAULT_VALUE_SET_FUNC(valueexpr) _DEFAULT_VALUE_SET (valueexpr)
|
||||
#else
|
||||
#define _DEFAULT_VALUE_SET_FUNC(valueexpr)
|
||||
#endif
|
||||
#else
|
||||
#define _DEFAULT_VALUE_SET(valueexpr)
|
||||
#define _DEFAULT_VALUE_SET_FUNC(valueexpr)
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
// 为了兼容。将 IStream * 转换成 PCOISTREAM 使用(C 用强制类型转换,C++ 也可以用强制类型,或者 reinterpret_cast?)。
|
||||
typedef struct COISTREAM__ *PCOISTREAM;
|
||||
// 返回 PriFile 实例指针。
|
||||
typedef struct CSPRIFILE__ *PCSPRIFILE;
|
||||
// 创建 PriFile 实例。请传入有效指针。失败返回 nullptr。
|
||||
typedef struct LPCWSTRLIST__
|
||||
{
|
||||
DWORD dwLength _DEFAULT_VALUE_SET (0);
|
||||
LPCWSTR aswArray [1] _DEFAULT_VALUE_SET ({0});
|
||||
} LPCWSTRLIST, *HLPCWSTRLIST;
|
||||
// 注意:PriFile 使用 IStream * 流类似于“借用”关系。要保证 PriFile 实例的生命周期
|
||||
// 在 IStream * 的生命周期内。
|
||||
PRIFORMATCLI_API PCSPRIFILE CreatePriFileInstanceFromStream (PCOISTREAM pStream);
|
||||
// 销毁 PriFile 对象。注意: PriFile 的销毁不会影响 IStream *。
|
||||
PRIFORMATCLI_API void DestroyPriFileInstance (PCSPRIFILE pFilePri);
|
||||
// 获取 PriFile 的文本资源。文本资源是会根据当前系统/用户正在使用的语言来选择最合适的文本。
|
||||
// 这里没有自定义获取。注:返回的有效非空指针请用 free 来释放。
|
||||
// 传入的是 ms-resource: 开头的字符串,以 URI 形式。
|
||||
// 示例:
|
||||
// 1. ms-resource://microsoft.windowscommunicationsapps/hxoutlookintl/AppManifest_OutlookDesktop_DisplayName (常见于 UWP 应用)
|
||||
// 2. ms-resource:ApplicationTitleWithBranding (常见于 Windows 8.x 应用)
|
||||
PRIFORMATCLI_API LPWSTR GetPriStringResource (PCSPRIFILE pFilePri, LPCWSTR lpswUri);
|
||||
// 获取 PriFile 的文件路径资源。对于一些如图像资源,会有对于系统不同 DPI 的适应
|
||||
// 目录分隔符为“\”(在应用清单中对于文件路径一直使用“\”),“/”不会支持。且一定为相对路径。
|
||||
// 注:返回的有效非空指针请用 free 释放。
|
||||
PRIFORMATCLI_API LPWSTR GetPriPathResource (PCSPRIFILE pFilePri, LPCWSTR lpswFilePath);
|
||||
// 从文件路径创建 PriFile 实例。(虽然用不上)。销毁同样通过 DestroyPriFileInstance。
|
||||
PRIFORMATCLI_API PCSPRIFILE CreatePriFileInstanceFromPath (LPCWSTR lpswFilePath);
|
||||
// 注意:可能会由于并发等导致返回的异常信息会错乱。
|
||||
PRIFORMATCLI_API LPCWSTR PriFileGetLastError ();
|
||||
// 对于多个资源,建议一次遍及,预先进行缓存。通过 GetPriStringResource 获取值。
|
||||
PRIFORMATCLI_API void FindPriStringResource (PCSPRIFILE pFilePri, HLPCWSTRLIST hUriList);
|
||||
// 对于多个资源,建议一次遍及,预先进行缓存。通过 GetPriPathResource 获取值。
|
||||
PRIFORMATCLI_API void FindPriPathResource (PCSPRIFILE pFilePri, HLPCWSTRLIST hPathList);
|
||||
// 清理内存缓存数据,仅用于测试用。注意:清理指的是所有。
|
||||
PRIFORMATCLI_API void ClearPriCacheData ();
|
||||
// 获取资源,作用与 GetPriStringResource 和 GetPriPathResource 一样。(因为这两个函数都是调用此函数)
|
||||
PRIFORMATCLI_API LPWSTR GetPriResource (PCSPRIFILE pFilePri, LPCWSTR lpswResId);
|
||||
// 开始查找资源,与 FindPriStringResource 和 FindPriPathResource 一样(因为这两个函数都是调用此函数)
|
||||
PRIFORMATCLI_API void FindPriResource (PCSPRIFILE pFilePri, HLPCWSTRLIST hUriList);
|
||||
// 工具函数,用于判断是否为 ms-resource: 前缀
|
||||
PRIFORMATCLI_API BOOL IsMsResourcePrefix (LPCWSTR pResName);
|
||||
// 工具函数,用于判断是否为 ms-resource:// 前缀
|
||||
PRIFORMATCLI_API BOOL IsMsResourceUriFull (LPCWSTR pResUri);
|
||||
// 工具函数,用于判断是否为 MS-Resource URI
|
||||
PRIFORMATCLI_API BOOL IsMsResourceUri (LPCWSTR pResUri);
|
||||
#ifdef _DEFAULT_VALUE_SET
|
||||
#undef _DEFAULT_VALUE_SET
|
||||
#endif
|
||||
#ifdef _DEFAULT_VALUE_SET_FUNC
|
||||
#undef _DEFAULT_VALUE_SET_FUNC
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined (__cplusplus)
|
||||
#include <string>
|
||||
#include <atlbase.h>
|
||||
#include <Shlwapi.h>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
// 注意:此类仅为操作类,如果以 IStream * 来初始化类的话在类销毁时不会释放 IStream *。请在此类实例生命期结束后必须释放 IStream *
|
||||
typedef class prifile
|
||||
{
|
||||
private:
|
||||
PCSPRIFILE m_hPriFile = nullptr;
|
||||
class reltask
|
||||
{
|
||||
public:
|
||||
std::function <void ()> endtask;
|
||||
reltask (std::function <void ()> pf): endtask (pf) {}
|
||||
reltask () { if (endtask) endtask (); }
|
||||
};
|
||||
public:
|
||||
bool valid () const { return m_hPriFile != nullptr; }
|
||||
void destroy ()
|
||||
{
|
||||
if (m_hPriFile)
|
||||
{
|
||||
DestroyPriFileInstance (m_hPriFile);
|
||||
m_hPriFile = nullptr;
|
||||
}
|
||||
}
|
||||
~prifile () { destroy (); }
|
||||
bool create (IStream *p)
|
||||
{
|
||||
try
|
||||
{
|
||||
destroy ();
|
||||
if (!p) return false;
|
||||
m_hPriFile = CreatePriFileInstanceFromStream ((PCOISTREAM)p);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
m_hPriFile = nullptr;
|
||||
}
|
||||
return valid ();
|
||||
}
|
||||
bool create (const std::wstring &filepath)
|
||||
{
|
||||
try
|
||||
{
|
||||
destroy ();
|
||||
if (filepath.empty ()) return false;
|
||||
m_hPriFile = CreatePriFileInstanceFromPath (filepath.c_str ());
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
m_hPriFile = nullptr;
|
||||
}
|
||||
return valid ();
|
||||
}
|
||||
prifile (IStream *pStream) { create (pStream); }
|
||||
prifile (const std::wstring &filepath) { create (filepath); }
|
||||
prifile () = default;
|
||||
void add_search (const std::vector <std::wstring> &arr) const
|
||||
{
|
||||
BYTE *buf = (BYTE *)malloc (sizeof (LPCWSTRLIST) + sizeof (LPWSTR) * arr.size ());
|
||||
reltask release ([&buf] () {
|
||||
if (buf) free (buf);
|
||||
buf = nullptr;
|
||||
});
|
||||
HLPCWSTRLIST hList = (HLPCWSTRLIST)buf;
|
||||
hList->dwLength = arr.size ();
|
||||
for (size_t i = 0; i < hList->dwLength; i ++)
|
||||
{
|
||||
hList->aswArray [i] = arr [i].c_str ();
|
||||
}
|
||||
FindPriResource (m_hPriFile, hList);
|
||||
}
|
||||
void add_search (const std::wstring &arr) const
|
||||
{
|
||||
BYTE buf [sizeof (LPCWSTRLIST) + sizeof (LPWSTR)] = {0};
|
||||
HLPCWSTRLIST hList = (HLPCWSTRLIST)buf;
|
||||
hList->dwLength = 1;
|
||||
hList->aswArray [0] = arr.c_str ();
|
||||
FindPriResource (m_hPriFile, hList);
|
||||
}
|
||||
std::wstring resource (const std::wstring &resname) const
|
||||
{
|
||||
LPWSTR lpstr = nullptr;
|
||||
reltask release ([&lpstr] () {
|
||||
if (lpstr) free (lpstr);
|
||||
lpstr = nullptr;
|
||||
});
|
||||
lpstr = GetPriResource (m_hPriFile, resname.c_str ());
|
||||
return lpstr ? lpstr : L"";
|
||||
}
|
||||
size_t resources (const std::vector <std::wstring> &resnames, std::map <std::wstring, std::wstring> &output) const
|
||||
{
|
||||
add_search (resnames);
|
||||
for (auto &it : resnames) output [it] = resource (it);
|
||||
return output.size ();
|
||||
}
|
||||
LPCWSTR last_error () { return PriFileGetLastError (); }
|
||||
std::wstring path (const std::wstring &resname) const { return resource (resname); }
|
||||
size_t paths (const std::vector <std::wstring> &resnames, std::map <std::wstring, std::wstring> &output) const { return resources (resnames, output); }
|
||||
std::wstring string (const std::wstring &resname) const { return resource (resname); }
|
||||
size_t strings (const std::vector <std::wstring> &resnames, std::map <std::wstring, std::wstring> &output) const { return resources (resnames, output); }
|
||||
} prifilecli;
|
||||
// 注意:此类仅为操作类,如果以 IStream * 来初始化类的话在类销毁时不会释放 IStream *。请在此类实例生命期结束后必须释放 IStream *
|
||||
typedef class prifilebundle
|
||||
{
|
||||
public:
|
||||
struct PRI_INST
|
||||
{
|
||||
// 0b01 语言 0b10 缩放资源 0b11 两者(或者是应用包的资源包)
|
||||
uint8_t type = 0;
|
||||
prifile priinst;
|
||||
bool res_language () const { return type & 0b01; }
|
||||
bool res_scale () const { return type & 0b10; }
|
||||
bool res_both () const { return type & 0b11; }
|
||||
bool is_valid () const { return type & 0b11; }
|
||||
// 类型:0: 无效,不许插入,1:语言资源,2:缩放资源,3:两者都有
|
||||
// 必须插入有效的内容
|
||||
PRI_INST (uint8_t type = 0, IStream *ipri = nullptr):
|
||||
type (type), priinst (ipri) {}
|
||||
};
|
||||
private:
|
||||
std::vector <PRI_INST> prifiles;
|
||||
std::map <uint8_t, PRI_INST *> mappri;
|
||||
public:
|
||||
prifilebundle () { prifiles.reserve (3); }
|
||||
// 类型:0: 无效,不许插入,1:语言资源,2:缩放资源,3:两者都有
|
||||
// 插入 3 类型的不会顶替 1 和 2 类型,只会顶替 3 类型。所以类中储存的实例最多只有三个。
|
||||
// 必须指定有效类型。如果 prifile 为 nullptr,则以位置相应类型的 pri 要执行销毁。
|
||||
bool set (uint8_t type, IStream *prifile)
|
||||
{
|
||||
uint8_t realt = type & 0b11;
|
||||
if (!type) return false;
|
||||
if (mappri.find (type & 0b11) != mappri.end ())
|
||||
{
|
||||
auto &prii = mappri [realt];
|
||||
prii->priinst.destroy ();
|
||||
if (prifile) prii->priinst.create (prifile);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!prifile) return false;
|
||||
prifiles.emplace_back (realt, prifile);
|
||||
for (auto &it : prifiles)
|
||||
{
|
||||
if (it.type == realt) { mappri [realt] = ⁢ break; }
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// 类型:0: 无效,不许插入,1:语言资源,2:缩放资源,3:两者都有
|
||||
// 失败返回 nullptr
|
||||
// 注意:获取 1 和 2 对应的 pri 资源,如果不存在会尝试返回 3 的资源。
|
||||
// mustreturn 指的是必须返回一个 pri 实例,不管是否符合。这是个没办法的办法
|
||||
prifile *get (uint8_t type, bool mustreturn = false)
|
||||
{
|
||||
type &= 0b11;
|
||||
auto it = mappri.find (type);
|
||||
if (it != mappri.end ()) return &it->second->priinst;
|
||||
if (type != 0b11)
|
||||
{
|
||||
it = mappri.find (0b11);
|
||||
if (it != mappri.end ()) return &it->second->priinst;
|
||||
}
|
||||
if (!prifiles.empty () && mustreturn) return &prifiles.front ().priinst;
|
||||
return nullptr;
|
||||
}
|
||||
void add_search (const std::vector <std::wstring> &arr)
|
||||
{
|
||||
std::vector <std::wstring> strresname;
|
||||
std::vector <std::wstring> pathresname;
|
||||
for (auto &it : arr)
|
||||
{
|
||||
if (IsMsResourcePrefix (it.c_str ())) strresname.push_back (it);
|
||||
else pathresname.push_back (it);
|
||||
}
|
||||
auto langpri = get (1, true);
|
||||
auto scalepri = get (2, true);
|
||||
if (langpri) langpri->add_search (strresname);
|
||||
if (scalepri) scalepri->add_search (pathresname);
|
||||
}
|
||||
void add_search (const std::wstring &resname)
|
||||
{
|
||||
if (IsMsResourcePrefix (resname.c_str ()))
|
||||
{
|
||||
auto langpri = get (1, true);
|
||||
if (langpri) langpri->add_search (resname);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto scalepri = get (2, true);
|
||||
if (scalepri) scalepri->add_search (resname);
|
||||
}
|
||||
}
|
||||
std::wstring resource (const std::wstring &resname)
|
||||
{
|
||||
if (IsMsResourcePrefix (resname.c_str ()))
|
||||
{
|
||||
auto langpri = get (1, true);
|
||||
if (langpri) return langpri->resource (resname);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto scalepri = get (2, true);
|
||||
if (scalepri) return scalepri->resource (resname);
|
||||
}
|
||||
return L"";
|
||||
}
|
||||
size_t resources (const std::vector <std::wstring> &resnames, std::map <std::wstring, std::wstring> &output)
|
||||
{
|
||||
add_search (resnames);
|
||||
for (auto &it : resnames) output [it] = resource (it);
|
||||
return output.size ();
|
||||
}
|
||||
std::wstring path (const std::wstring &resname) { return resource (resname); }
|
||||
size_t paths (const std::vector <std::wstring> &resnames, std::map <std::wstring, std::wstring> &output) { return resources (resnames, output); }
|
||||
std::wstring string (const std::wstring &resname) { return resource (resname); }
|
||||
size_t strings (const std::vector <std::wstring> &resnames, std::map <std::wstring, std::wstring> &output) { return resources (resnames, output); }
|
||||
void destroy ()
|
||||
{
|
||||
mappri.clear ();
|
||||
prifiles.clear ();
|
||||
}
|
||||
} prifilebcli;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
BIN
priformatcli/priformatcli.rc
Normal file
BIN
priformatcli/priformatcli.rc
Normal file
Binary file not shown.
191
priformatcli/priformatcli.vcxproj
Normal file
191
priformatcli/priformatcli.vcxproj
Normal file
@@ -0,0 +1,191 @@
|
||||
<?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>{33D91B58-1981-4A3C-B4D1-86EE406CDE12}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>priformatcli</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
|
||||
</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>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
</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>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;PRIFORMATCLI_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;PRIFORMATCLI_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>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;PRIFORMATCLI_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(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>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;PRIFORMATCLI_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="mpstr.h" />
|
||||
<ClInclude Include="nstring.h" />
|
||||
<ClInclude Include="prifile.h" />
|
||||
<ClInclude Include="priformatcli.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="syncutil.h" />
|
||||
<ClInclude Include="targetver.h" />
|
||||
<ClInclude Include="themeinfo.h" />
|
||||
<ClInclude Include="typestrans.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="priformatcli.cpp" />
|
||||
<ClCompile Include="stdafx.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="priformatcli.rc" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
71
priformatcli/priformatcli.vcxproj.filters
Normal file
71
priformatcli/priformatcli.vcxproj.filters
Normal file
@@ -0,0 +1,71 @@
|
||||
<?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="priformatcli.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="prifile.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="typestrans.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="mpstr.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="localeex.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="nstring.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="themeinfo.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="syncutil.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="priformatcli.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="priformatcli.rc">
|
||||
<Filter>资源文件</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
14
priformatcli/resource.h
Normal file
14
priformatcli/resource.h
Normal file
@@ -0,0 +1,14 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by priformatcli.rc
|
||||
|
||||
// 新对象的下一组默认值
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
8
priformatcli/stdafx.cpp
Normal file
8
priformatcli/stdafx.cpp
Normal file
@@ -0,0 +1,8 @@
|
||||
// stdafx.cpp : 只包括标准包含文件的源文件
|
||||
// priformatcli.pch 将作为预编译头
|
||||
// stdafx.obj 将包含预编译类型信息
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: 在 STDAFX.H 中引用任何所需的附加头文件,
|
||||
//而不是在此文件中引用
|
||||
16
priformatcli/stdafx.h
Normal file
16
priformatcli/stdafx.h
Normal file
@@ -0,0 +1,16 @@
|
||||
// stdafx.h : 标准系统包含文件的包含文件,
|
||||
// 或是经常使用但不常更改的
|
||||
// 特定于项目的包含文件
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "targetver.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // 从 Windows 头中排除极少使用的资料
|
||||
// Windows 头文件:
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
|
||||
// TODO: 在此处引用程序需要的其他头文件
|
||||
124
priformatcli/syncutil.h
Normal file
124
priformatcli/syncutil.h
Normal file
@@ -0,0 +1,124 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
class CriticalSection
|
||||
{
|
||||
private:
|
||||
CRITICAL_SECTION m_csection;
|
||||
public:
|
||||
CriticalSection (DWORD spinCount = 4000) { InitializeCriticalSectionAndSpinCount (&m_csection, spinCount); }
|
||||
CriticalSection (const CriticalSection &) = delete;
|
||||
CriticalSection &operator = (const CriticalSection &) = delete;
|
||||
~CriticalSection () { DeleteCriticalSection (&m_csection); }
|
||||
void Lock () { EnterCriticalSection (&m_csection); }
|
||||
void Unlock () { LeaveCriticalSection (&m_csection); }
|
||||
bool TryLock () { return TryEnterCriticalSection (&m_csection) != 0; }
|
||||
class ScopedLock
|
||||
{
|
||||
public:
|
||||
explicit ScopedLock (CriticalSection &cs): m_cs (cs) { m_cs.Lock (); }
|
||||
~ScopedLock () { m_cs.Unlock (); }
|
||||
ScopedLock (const ScopedLock &) = delete;
|
||||
ScopedLock &operator = (const ScopedLock &) = delete;
|
||||
private:
|
||||
CriticalSection& m_cs;
|
||||
};
|
||||
};
|
||||
|
||||
#define CreateScopedLock(_obj_cs_) CriticalSection::ScopedLock _obj_cs_##sl (_obj_cs_)
|
||||
|
||||
#ifdef __cplusplus_cli
|
||||
ref struct TaskStructEvent
|
||||
{
|
||||
typedef array <Object ^> args;
|
||||
typedef void (*eventfunc) (... args ^args);
|
||||
eventfunc post;
|
||||
args ^postargs;
|
||||
public:
|
||||
TaskStructEvent (
|
||||
eventfunc prefunc,
|
||||
args ^preargs,
|
||||
eventfunc postfunc,
|
||||
args ^postargs
|
||||
): post (postfunc), postargs (postargs)
|
||||
{
|
||||
if (prefunc == nullptr) {
|
||||
#pragma message("警告:预处理函数指针为空,可能跳过初始化操作")
|
||||
}
|
||||
if (prefunc)
|
||||
{
|
||||
if (preargs)
|
||||
{
|
||||
#pragma region 参数验证示例
|
||||
/*
|
||||
实际项目中应添加具体类型检查,例如:
|
||||
ValidateArgsType<Button^>(preargs);
|
||||
*/
|
||||
#pragma endregion
|
||||
prefunc (preargs);
|
||||
}
|
||||
else prefunc (gcnew args {});
|
||||
}
|
||||
}
|
||||
~TaskStructEvent ()
|
||||
{
|
||||
if (post == nullptr)
|
||||
{
|
||||
#pragma message("警告:后处理函数指针为空,资源可能无法正确释放")
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
if (postargs) { post (postargs); }
|
||||
else { post (gcnew args {}); }
|
||||
}
|
||||
catch (Exception ^e)
|
||||
{
|
||||
#pragma message("注意:后处理中的异常需手动处理")
|
||||
}
|
||||
}
|
||||
};
|
||||
#define CreateStructEvent(_varname_taskname_, _func_construct_, _args_construct_, _func_destruct_, _args_destruct_) \
|
||||
TaskStructEvent _varname_taskname_ ( \
|
||||
_func_construct_, \
|
||||
_args_construct_, \
|
||||
_func_destruct_, \
|
||||
_args_destruct_ \
|
||||
)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
template <typename PreCallback, typename PostCallback> class ScopedEvent
|
||||
{
|
||||
public:
|
||||
ScopedEvent (PreCallback &&pre, PostCallback &&post)
|
||||
: m_post (std::forward <PostCallback> (post))
|
||||
{
|
||||
static_assert (
|
||||
std::is_constructible <std::function <void ()>, PreCallback>::value,
|
||||
"预处理回调必须可转换为 void () 类型"
|
||||
);
|
||||
|
||||
if (pre) { pre (); }
|
||||
}
|
||||
~ScopedEvent () noexcept
|
||||
{
|
||||
if (m_post) { m_post (); }
|
||||
}
|
||||
ScopedEvent (const ScopedEvent &) = delete;
|
||||
ScopedEvent &operator = (const ScopedEvent &) = delete;
|
||||
ScopedEvent (ScopedEvent &&) = default;
|
||||
ScopedEvent &operator =(ScopedEvent &&) = default;
|
||||
private:
|
||||
PostCallback m_post;
|
||||
};
|
||||
template <typename PreFunc, typename PostFunc> auto make_scoped_event (PreFunc &&pre, PostFunc &&post)
|
||||
{
|
||||
return ScopedEvent <PreFunc, PostFunc> (
|
||||
std::forward <PreFunc> (pre),
|
||||
std::forward <PostFunc> (post)
|
||||
);
|
||||
}
|
||||
#endif
|
||||
8
priformatcli/targetver.h
Normal file
8
priformatcli/targetver.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
// 包括 SDKDDKVer.h 将定义可用的最高版本的 Windows 平台。
|
||||
|
||||
// 如果要为以前的 Windows 平台生成应用程序,请包括 WinSDKVer.h,并将
|
||||
// 将 _WIN32_WINNT 宏设置为要支持的平台,然后再包括 SDKDDKVer.h。
|
||||
|
||||
#include <SDKDDKVer.h>
|
||||
40
priformatcli/themeinfo.h
Normal file
40
priformatcli/themeinfo.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#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;
|
||||
}
|
||||
187
priformatcli/typestrans.h
Normal file
187
priformatcli/typestrans.h
Normal file
@@ -0,0 +1,187 @@
|
||||
#pragma once
|
||||
#ifndef _CRT_SECURE_NO_WARNINGS
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
#include <Windows.h>
|
||||
#ifdef __cplusplus
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstdbool>
|
||||
#include <cstring>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
unsigned _wtou (const wchar_t *str)
|
||||
{
|
||||
unsigned value = 0;
|
||||
if (str)
|
||||
{
|
||||
swscanf (str, L"%u", &value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
unsigned long _wtoul (const wchar_t *str)
|
||||
{
|
||||
unsigned value = 0;
|
||||
if (str)
|
||||
{
|
||||
swscanf (str, L"%lu", &value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
unsigned long long _wtou64 (const wchar_t *str)
|
||||
{
|
||||
unsigned long long value = 0;
|
||||
if (str)
|
||||
{
|
||||
swscanf (str, L"%llu", &value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
double _wtod (const wchar_t *str)
|
||||
{
|
||||
if (!str || !*str) return 0.0; // 避免空指针或空字符串
|
||||
double value = 0.0;
|
||||
if (swscanf (str, L"%lg", &value) == 1)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
return 0.0; // 解析失败时返回 0.0
|
||||
}
|
||||
unsigned atou (const char *str)
|
||||
{
|
||||
unsigned value = 0;
|
||||
if (str)
|
||||
{
|
||||
sscanf (str, "%u", &value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
unsigned long atoul (const char *str)
|
||||
{
|
||||
unsigned value = 0;
|
||||
if (str)
|
||||
{
|
||||
sscanf (str, "%lu", &value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
unsigned long long atou64 (const char *str)
|
||||
{
|
||||
unsigned long long value = 0;
|
||||
if (str)
|
||||
{
|
||||
sscanf (str, "%llu", &value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
double atod (const char *str)
|
||||
{
|
||||
if (!str || !*str) return 0.0; // 避免空指针或空字符串
|
||||
double value = 0.0;
|
||||
if (sscanf (str, "%lg", &value) == 1)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
return 0.0; // 解析失败时返回 0.0
|
||||
}
|
||||
|
||||
EXTERN_C int StringToIntA (const char *str) { return atoi (str); }
|
||||
EXTERN_C int StringToIntW (const WCHAR *str) { return _wtoi (str); }
|
||||
EXTERN_C unsigned StringToUnsignedA (const char *str) { return atou (str); }
|
||||
EXTERN_C unsigned StringToUnsignedW (const WCHAR *str) { return _wtou (str); }
|
||||
EXTERN_C bool StringToBoolA (const char *str)
|
||||
{
|
||||
char buf [32] = {0};
|
||||
strcpy (buf, str);
|
||||
for (int cnt = 0; buf [cnt]; cnt ++) buf [cnt] = tolower (buf [cnt]);
|
||||
return !strcmp (buf, "true") ||
|
||||
!strcmp (buf, "yes") ||
|
||||
!strcmp (buf, "ok") ||
|
||||
!strcmp (buf, "sure") ||
|
||||
!strcmp (buf, "okay") ||
|
||||
!strcmp (buf, "zhen") ||
|
||||
!strcmp (buf, "真");
|
||||
}
|
||||
EXTERN_C bool StringToBoolW (const WCHAR *str)
|
||||
{
|
||||
WCHAR buf [32] = {0};
|
||||
lstrcpyW (buf, str);
|
||||
for (int cnt = 0; buf [cnt]; cnt ++) buf [cnt] = tolower (buf [cnt]);
|
||||
return !lstrcmpW (buf, L"true") ||
|
||||
!lstrcmpW (buf, L"yes") ||
|
||||
!lstrcmpW (buf, L"ok") ||
|
||||
!lstrcmpW (buf, L"sure") ||
|
||||
!lstrcmpW (buf, L"okay") ||
|
||||
!lstrcmpW (buf, L"zhen") ||
|
||||
!lstrcmpW (buf, L"真");
|
||||
}
|
||||
EXTERN_C long StringToLongA (const char *str) { return atol (str); }
|
||||
EXTERN_C long StringToLongW (const WCHAR *str) { return _wtol (str); }
|
||||
EXTERN_C unsigned long StringToULongA (const char *str) { return atoul (str); }
|
||||
EXTERN_C unsigned long StringToULongW (const WCHAR *str) { return _wtoul (str); }
|
||||
EXTERN_C long long StringToLongLongA (const char *str) { return atoll (str); }
|
||||
EXTERN_C long long StringToLongLongW (const WCHAR *str) { return _wtoll (str); }
|
||||
EXTERN_C unsigned long long StringToULongLongA (const char *str) { return atou64 (str); }
|
||||
EXTERN_C unsigned long long StringToULongLongW (const WCHAR *str) { return _wtou64 (str); }
|
||||
EXTERN_C float StringToFloatA (const char *str) { return atof (str); }
|
||||
EXTERN_C float StringToFloatW (const WCHAR *str) { return _wtof (str); }
|
||||
EXTERN_C double StringToDoubleA (const char *str) { return atod (str); }
|
||||
EXTERN_C double StringToDoubleW (const WCHAR *str) { return _wtod (str); }
|
||||
|
||||
#ifdef __cplusplus
|
||||
int StringToInt (LPCSTR str) { return StringToIntA (str); }
|
||||
int StringToInt (LPCWSTR str) { return StringToIntW (str); }
|
||||
unsigned StringToUnsigned (LPCSTR str) { return StringToUnsignedA (str); }
|
||||
unsigned StringToUnsigned (LPCWSTR str) { return StringToUnsignedW (str); }
|
||||
bool StringToBool (LPCSTR str) { return StringToBoolA (str); }
|
||||
bool StringToBool (LPCWSTR str) { return StringToBoolW (str); }
|
||||
long StringToLong (LPCSTR str) { return StringToLongA (str); }
|
||||
long StringToLong (LPCWSTR str) { return StringToLongW (str); }
|
||||
unsigned long StringToULong (LPCSTR str) { return StringToULongA (str); }
|
||||
unsigned long StringToULong (LPCWSTR str) { return StringToULongW (str); }
|
||||
long long StringToLongLong (LPCSTR str) { return StringToLongLongA (str); }
|
||||
long long StringToLongLong (LPCWSTR str) { return StringToLongLongW (str); }
|
||||
unsigned long long StringToULongLong (LPCSTR str) { return StringToULongLongA (str); }
|
||||
unsigned long long StringToULongLong (LPCWSTR str) { return StringToULongLongW (str); }
|
||||
float StringToFloat (LPCSTR str) { return StringToFloatA (str); }
|
||||
float StringToFloat (LPCWSTR str) { return StringToFloatW (str); }
|
||||
double StringToDouble (LPCSTR str) { return StringToDoubleA (str); }
|
||||
double StringToDouble (LPCWSTR str) { return StringToDoubleW (str); }
|
||||
#endif
|
||||
|
||||
#if defined (__cplusplus) && defined (__cplusplus_cli)
|
||||
using namespace System;
|
||||
#define toInt(_String_Managed_Object_) Int32::Parse (_String_Managed_Object_)
|
||||
#define objToInt(_Object_Managed_) Convert::ToInt32 (_Object_Managed_)
|
||||
#define toDouble(_String_Managed_Object_) Double::Parse (_String_Managed_Object_)
|
||||
#define objToDouble(_Object_Managed_) Convert::ToDouble (_Object_Managed_)
|
||||
#define toBool(_String_Managed_Object_) Boolean::Parse (_String_Managed_Object_)
|
||||
bool objToBool (Object ^result)
|
||||
{
|
||||
if (!result) return false;
|
||||
try
|
||||
{
|
||||
String ^strValue = safe_cast <String ^> (result);
|
||||
return (strValue->ToLower () == "on");
|
||||
}
|
||||
catch (InvalidCastException ^)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Convert::ToBoolean (result);
|
||||
}
|
||||
catch (InvalidCastException ^)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#define toDateTime(_String_Managed_Object_) DateTime::Parse (_String_Managed_Object_)
|
||||
#define toDateTimeObj(_Object_Managed_) Convert::ToDateTime (_Object_Managed_)
|
||||
#define objectToType(_Object_Managed_, _Type_Name_) Convert::To##_Type_Name_ (_Object_Managed_)
|
||||
#endif
|
||||
BIN
reslib/reslib.rc
BIN
reslib/reslib.rc
Binary file not shown.
Binary file not shown.
@@ -129,13 +129,7 @@ struct xmlstrres
|
||||
std::string operator [] (const std::string &id) { return get (id); }
|
||||
};
|
||||
xmlstrres g_winjspri (CombinePath (GetProgramRootDirectoryW (), L"locale\\resources.xml"));
|
||||
struct
|
||||
{
|
||||
bool jump = false;
|
||||
std::wstring section = L"";
|
||||
std::wstring item = L"";
|
||||
std::wstring arg = L"";
|
||||
};
|
||||
std::vector <std::wstring> g_cmdargs;
|
||||
|
||||
size_t ExploreFile (HWND hParent, std::vector <std::wstring> &results, LPWSTR lpFilter = L"Windows Store App Package (*.appx; *.appxbundle)\0*.appx;*.appxbundle", DWORD dwFlags = OFN_EXPLORER | OFN_ALLOWMULTISELECT | OFN_PATHMUSTEXIST, const std::wstring &swWndTitle = std::wstring (L"Please select the file(-s): "), const std::wstring &swInitDir = GetFileDirectoryW (g_lastfile))
|
||||
{
|
||||
@@ -826,6 +820,9 @@ public ref class MainHtmlWnd: public System::Windows::Forms::Form, public IScrip
|
||||
{
|
||||
private:
|
||||
MainHtmlWnd ^wndinst = nullptr;
|
||||
bool hasjump1 = false,
|
||||
hasjump2 = false,
|
||||
hasexec = false;
|
||||
public:
|
||||
using String = System::String;
|
||||
[ComVisible (true)]
|
||||
@@ -950,6 +947,10 @@ public ref class MainHtmlWnd: public System::Windows::Forms::Form, public IScrip
|
||||
property _I_Process ^Process { _I_Process ^get () { return proc; }}
|
||||
property _I_ResourcePri ^WinJsStringRes { _I_ResourcePri ^get () { return winjs_res; }}
|
||||
String ^FormatDateTime (String ^fmt, String ^jsDate) { return FormatString (fmt, Convert::ToDateTime (jsDate)); }
|
||||
property String ^CmdArgs { String ^get () { return CStringToMPString (StringArrayToJson (g_cmdargs)); }}
|
||||
property bool Jump1 { bool get () { return hasjump1; } void set (bool value) { hasjump1 = value; } }
|
||||
property bool Jump2 { bool get () { return hasjump2; } void set (bool value) { hasjump2 = value; } }
|
||||
property bool Exec1 { bool get () { return hasexec; } void set (bool value) { hasexec = value; } }
|
||||
void CloseWindow ()
|
||||
{
|
||||
if (wndinst && wndinst->IsHandleCreated) wndinst->Close ();
|
||||
@@ -1348,6 +1349,15 @@ int APIENTRY wWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCm
|
||||
destruct relco ([] () {
|
||||
CoUninitialize ();
|
||||
});
|
||||
{
|
||||
auto cmdline = GetCommandLineW ();
|
||||
int argc = 0;
|
||||
auto argv = CommandLineToArgvW (cmdline, &argc);
|
||||
destruct relt ([&argv] () {
|
||||
if (argv) LocalFree (argv);
|
||||
});
|
||||
for (size_t i = 1; i < argc; i ++) g_cmdargs.push_back (argv [i]);
|
||||
}
|
||||
SetWebBrowserEmulation ();
|
||||
System::Windows::Forms::Application::EnableVisualStyles ();
|
||||
System::Windows::Forms::Application::SetCompatibleTextRenderingDefault (false);
|
||||
|
||||
Binary file not shown.
@@ -46,7 +46,7 @@
|
||||
</ul>
|
||||
</nav>
|
||||
</aside>
|
||||
<iframe class="main right">
|
||||
<iframe class="main right"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
@@ -33,16 +33,37 @@
|
||||
if (child.classList.contains("selected"))
|
||||
child.classList.remove("selected");
|
||||
}
|
||||
content.src = this.getAttribute("data-page");
|
||||
setTimeout(function() {
|
||||
content.style.display = "";
|
||||
Windows.UI.Animation.runAsync(content, [Windows.UI.Animation.Keyframes.Flyout.toLeft, Windows.UI.Animation.Keyframes.Opacity.visible]);
|
||||
}, 0);
|
||||
|
||||
setTimeout(function(thisnode) {
|
||||
content.style.display = "none";
|
||||
content.src = thisnode.getAttribute("data-page");
|
||||
setTimeout(function(thisnode2) {
|
||||
thisnode2.style.display = "";
|
||||
}, 500, content);
|
||||
}, 0, this);
|
||||
this.classList.add("selected");
|
||||
});
|
||||
list.appendChild(li);
|
||||
}
|
||||
content.src = guidePage.page;
|
||||
eventutil.addEvent(content, "load", function() {
|
||||
Windows.UI.Animation.runAsync(this, [Windows.UI.Animation.Keyframes.Flyout.toLeft, Windows.UI.Animation.Keyframes.Opacity.visible]);
|
||||
this.style.display = "";
|
||||
});
|
||||
var jumppage = "";
|
||||
try { var args = cmdargs; if (args.length > 1) jumppage = args[1]; } catch (e) {}
|
||||
if (jumppage && jumppage.length > 0 && !Bridge.External.jump2) {
|
||||
for (var i = 0; i < list.children.length; i++) {
|
||||
var child = list.children[i];
|
||||
if (Bridge.NString.equals(child.getAttribute("data-tag"), jumppage)) {
|
||||
Bridge.External.jump2 = true;
|
||||
setTimeout(function(thisnode) {
|
||||
thisnode.click();
|
||||
}, 0, child)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
global.setDisabledForOperation = function(disabled) {
|
||||
var list = document.querySelector("#settingpage .guide aside ul");
|
||||
for (var i = 0; i < list.children.length; i++) {
|
||||
|
||||
@@ -27,4 +27,9 @@
|
||||
}
|
||||
return null;
|
||||
};
|
||||
Object.defineProperty(global, "cmdargs", {
|
||||
get: function() {
|
||||
return JSON.parse(Bridge.External.cmdArgs);
|
||||
}
|
||||
});
|
||||
})(this);
|
||||
@@ -1,5 +1,6 @@
|
||||
(function(global) {
|
||||
"use strict";
|
||||
var cmdargs = JSON.parse(Bridge.External.cmdArgs);
|
||||
|
||||
function ready(e) {
|
||||
var page = document.querySelector("#settingpage");
|
||||
@@ -15,6 +16,8 @@
|
||||
var item = items[keys[i]];
|
||||
var inode = document.createElement("li");
|
||||
inode.setAttribute("data-page", item.page);
|
||||
inode.setAttribute("data-name", item.displayName);
|
||||
inode.setAttribute("data-tag", keys[i]);
|
||||
inode.textContent = item.displayName;
|
||||
Windows.UI.Event.Util.addEvent(inode, "click", function(e) {
|
||||
window.location = "settings/" + this.getAttribute("data-page");
|
||||
@@ -22,6 +25,19 @@
|
||||
list.appendChild(inode);
|
||||
// WinJS.UI.Animation.createAddToListAnimation(list, inode).execute();
|
||||
}
|
||||
var current = "";
|
||||
try { if (cmdargs.length > 0) current = cmdargs[0] } catch (e) {}
|
||||
if (current && current.length > 0 && !Bridge.External.jump1) {
|
||||
for (var i = 0; i < list.children.length; i++) {
|
||||
if (Bridge.NString.equals(list.children[i].getAttribute("data-tag"), current)) {
|
||||
Bridge.External.jump1 = true;
|
||||
setTimeout(function(thisnode) {
|
||||
thisnode.click();
|
||||
}, 0, list.children[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
OnLoad.add(ready);
|
||||
})(this);
|
||||
@@ -46,7 +46,7 @@
|
||||
</ul>
|
||||
</nav>
|
||||
</aside>
|
||||
<iframe class="main right">
|
||||
<iframe class="main right"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
@@ -42,7 +42,26 @@
|
||||
});
|
||||
list.appendChild(li);
|
||||
}
|
||||
content.src = items.general.page;
|
||||
content.src = guidePage.page;
|
||||
for (var i = 0; i < list.children.length; i++) {
|
||||
var child = list.children[i];
|
||||
child.click();
|
||||
break;
|
||||
}
|
||||
var jumppage = "";
|
||||
try { var args = cmdargs; if (args.length > 1) jumppage = args[1]; } catch (e) {}
|
||||
if (jumppage && jumppage.length > 0 && !Bridge.External.jump2) {
|
||||
for (var i = 0; i < list.children.length; i++) {
|
||||
var child = list.children[i];
|
||||
if (Bridge.NString.equals(child.getAttribute("data-tag"), jumppage)) {
|
||||
Bridge.External.jump2 = true;
|
||||
setTimeout(function(thisnode) {
|
||||
thisnode.click();
|
||||
}, 0, child)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
global.setDisabledForOperation = function(disabled) {
|
||||
var list = document.querySelector("#settingpage .guide aside ul");
|
||||
for (var i = 0; i < list.children.length; i++) {
|
||||
|
||||
@@ -252,6 +252,7 @@
|
||||
window.parent.setItemHighlight = function() {};
|
||||
}
|
||||
</script>
|
||||
<script type="text/javascript" src="updateinit.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -275,7 +276,7 @@
|
||||
</div>
|
||||
<div class="section padding" style="">
|
||||
<div class="block" id="check-update-block" style="height: 0px;">
|
||||
<span id="loading-amine">123</span><span id="check-update-text" data-res-fromfile="publicRes (106)"></span><br>
|
||||
<span id="loading-amine"></span><span id="check-update-text" data-res-fromfile="publicRes (106)"></span><br>
|
||||
<progress id="progress" min="0" max="100"></progress>
|
||||
<a target="_blank" id="doc-link" data-res-fromfile="publicRes (107)"></a>
|
||||
</div>
|
||||
@@ -385,6 +386,7 @@
|
||||
break;
|
||||
}
|
||||
}
|
||||
window.parent.setDisabledForOperation(false);
|
||||
if (compareVersion(window.currver, window.newver) >= 0) {
|
||||
checkUpdateText.textContent = getPublicRes(114);
|
||||
checkUpdateBtn.textContent = getPublicRes(115);
|
||||
@@ -393,8 +395,13 @@
|
||||
checkUpdateText.textContent = Bridge.String.format(getPublicRes(116), window.newver);
|
||||
checkUpdateBtn.textContent = getPublicRes(117);
|
||||
checkUpdateBtn.setAttribute("data-action", "download");
|
||||
if (autoInstallUpdate) {
|
||||
setTimeout(function(thisnode) {
|
||||
thisnode.click();
|
||||
autoInstallUpdate = false;
|
||||
}, 0, self);
|
||||
}
|
||||
}
|
||||
window.parent.setDisabledForOperation(false);
|
||||
}, function(error) {
|
||||
// console.log("error", error);
|
||||
var json = JSON.parse(error.responseText);
|
||||
@@ -482,6 +489,22 @@
|
||||
})();
|
||||
</script>
|
||||
</div>
|
||||
<script>
|
||||
(function(global) {
|
||||
"use strict";
|
||||
|
||||
function ready(e) {
|
||||
var checkButton = document.getElementById("check-update");
|
||||
if (autoCheckUpdate) {
|
||||
setTimeout(function(thisnode) {
|
||||
thisnode.click();
|
||||
autoCheckUpdate = false;
|
||||
}, 0, checkButton);
|
||||
}
|
||||
}
|
||||
OnLoad.add(ready);
|
||||
})(this);
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
26
shared/html/settings/updateinit.js
Normal file
26
shared/html/settings/updateinit.js
Normal file
@@ -0,0 +1,26 @@
|
||||
(function(global) {
|
||||
global.autoCheckUpdate = false;
|
||||
global.autoInstallUpdate = false;
|
||||
if (Bridge.External.exec1 == true) return;
|
||||
var args = cmdargs;
|
||||
var optionarg = "";
|
||||
if (args.length > 2) {
|
||||
optionarg = args[2];
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
Bridge.NString.equals(optionarg, "/checkupdate") ||
|
||||
Bridge.NString.equals(optionarg, "-checkupdate") ||
|
||||
Bridge.NString.equals(optionarg, "checkupdate")
|
||||
) global.autoCheckUpdate = true;
|
||||
if (
|
||||
Bridge.NString.equals(optionarg, "/autoupdate") ||
|
||||
Bridge.NString.equals(optionarg, "-autoupdate") ||
|
||||
Bridge.NString.equals(optionarg, "autoupdate")
|
||||
) {
|
||||
global.autoCheckUpdate = true;
|
||||
global.autoInstallUpdate = true;
|
||||
}
|
||||
Bridge.External.exec1 = true;
|
||||
})(this);
|
||||
Reference in New Issue
Block a user