diff --git a/.vssbe b/.vssbe index 40ec3d7..59ad8bb 100644 --- a/.vssbe +++ b/.vssbe @@ -91,13 +91,14 @@ "Mode": { "$type": "net.r_eg.vsSBE.Events.ModeScript, vsSolutionBuildEvent", "Type": "Script", - "Command": "#[$(dbin = \"bin/$(Configuration)/\")]\n\n$(pDllExport = \"RGiesecke.DllExport\")\n$(pMeta = \"Metadata\")\n$(pNSBin = \"NSBin\")\n$(pMSBuild = \"RGiesecke.DllExport.MSBuild\")\n$(odir = \"$(dbin)raw/\")\n\n#[IO delete.directory(\"$(dbin)\", true)]\n#[IO copy.directory(\"\", \"$(dbin)\", true)]", + "Command": "#[$(dbin = \"bin/$(Configuration)/\")]\n\n$(pDllExport = \"RGiesecke.DllExport\")\n$(pMeta = \"Metadata\")\n$(pNSBin = \"NSBin\")\n$(pConf = \"Configurator\")\n$(pMSBuild = \"RGiesecke.DllExport.MSBuild\")\n$(odir = \"$(dbin)raw/\")\n\n#[IO delete.directory(\"$(dbin)\", true)]\n#[IO copy.directory(\"\", \"$(dbin)\", true)]", "Command__": [ "#[$(dbin = \"bin/$(Configuration)/\")]", "", "$(pDllExport = \"RGiesecke.DllExport\")", "$(pMeta = \"Metadata\")", "$(pNSBin = \"NSBin\")", + "$(pConf = \"Configurator\")", "$(pMSBuild = \"RGiesecke.DllExport.MSBuild\")", "$(odir = \"$(dbin)raw/\")", "", @@ -167,7 +168,7 @@ "Mode": { "$type": "net.r_eg.vsSBE.Events.ModeScript, vsSolutionBuildEvent", "Type": "Script", - "Command": "#[IO copy.file(\n \"$(SolutionDir)tools/*.*\", \n \"$(odir)/tools/\", \n true, \n {\"*.nuspec\"})]\n\n#[IO copy.file(\"tools/DllExport.nuspec\", \"$(odir)/DllExport.nuspec\", true)]\n\n#[IO copy.file(\"$(pDllExport)/$(OutDir:$(pDllExport))/*.*\", \n \"$(odir)/tools/\", true)]\n\n#[IO copy.file(\"$(pMSBuild)/$(OutDir:$(pMSBuild))/*.*\", \n \"$(odir)/tools/\", true)]\n \n#[IO copy.file(\"$(pMeta)/$(OutDir:$(pMeta))/*.dll\", \n \"$(odir)/lib/net20/\", true)]\n\n#[IO copy.file(\"$(pNSBin)/$(OutDir:$(pNSBin))/*.*\", \n \"$(odir)/tools/\", true)]\n\n#[IO copy.file(\"LICENSE\", \"$(odir)/\", true)]\n#[IO copy.file(\"Readme.md\", \"$(odir)/\", true)]", + "Command": "#[IO copy.file(\n \"$(SolutionDir)tools/*.*\", \n \"$(odir)/tools/\", \n true, \n {\"*.nuspec\"})]\n\n#[IO copy.file(\"tools/DllExport.nuspec\", \"$(odir)/DllExport.nuspec\", true)]\n\n#[IO copy.file({\n \"$(pDllExport)/$(OutDir:$(pDllExport))/*.*\",\n \"$(pMSBuild)/$(OutDir:$(pMSBuild))/*.*\",\n \"$(pNSBin)/$(OutDir:$(pNSBin))/*.*\",\n \"$(pConf)/$(OutDir:$(pConf))/*.*\"\n }, \n \"$(odir)/tools/\", true)]\n\n \n#[IO copy.file(\"$(pMeta)/$(OutDir:$(pMeta))/*.dll\", \n \"$(odir)/lib/net20/\", true)]\n\n#[IO copy.file({ \"LICENSE\", \"Readme.md\" }, \"$(odir)/\", true)]", "Command__": [ "#[IO copy.file(", " \"$(SolutionDir)tools/*.*\", ", @@ -177,20 +178,19 @@ "", "#[IO copy.file(\"tools/DllExport.nuspec\", \"$(odir)/DllExport.nuspec\", true)]", "", - "#[IO copy.file(\"$(pDllExport)/$(OutDir:$(pDllExport))/*.*\", ", - " \"$(odir)/tools/\", true)]", + "#[IO copy.file({", + " \"$(pDllExport)/$(OutDir:$(pDllExport))/*.*\",", + " \"$(pMSBuild)/$(OutDir:$(pMSBuild))/*.*\",", + " \"$(pNSBin)/$(OutDir:$(pNSBin))/*.*\",", + " \"$(pConf)/$(OutDir:$(pConf))/*.*\"", + " }, ", + " \"$(odir)/tools/\", true)]", "", - "#[IO copy.file(\"$(pMSBuild)/$(OutDir:$(pMSBuild))/*.*\", ", - " \"$(odir)/tools/\", true)]", " ", "#[IO copy.file(\"$(pMeta)/$(OutDir:$(pMeta))/*.dll\", ", " \"$(odir)/lib/net20/\", true)]", "", - "#[IO copy.file(\"$(pNSBin)/$(OutDir:$(pNSBin))/*.*\", ", - " \"$(odir)/tools/\", true)]", - "", - "#[IO copy.file(\"LICENSE\", \"$(odir)/\", true)]", - "#[IO copy.file(\"Readme.md\", \"$(odir)/\", true)]" + "#[IO copy.file({ \"LICENSE\", \"Readme.md\" }, \"$(odir)/\", true)]" ] } }, diff --git a/Configurator/Configurator.csproj b/Configurator/Configurator.csproj new file mode 100644 index 0000000..6157b3d --- /dev/null +++ b/Configurator/Configurator.csproj @@ -0,0 +1,91 @@ + + + + + Debug + AnyCPU + {9B7723F1-C89F-43E1-B27D-A46A96C82034} + Library + Properties + net.r_eg.DllExport.Configurator + net.r_eg.DllExport.Configurator + v4.0 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + + + key.snk + + + + + + + ..\packages\Microsoft.PowerShell.5.ReferenceAssemblies.1.0.0\lib\net4\System.Management.Automation.dll + True + + + + + + + + + + + + + Form + + + InstallationForm.cs + + + + + + + + + + + + + InstallationForm.cs + + + + + {311706a5-5ed2-4006-b794-055009d8a256} + NSBin + + + + + + \ No newline at end of file diff --git a/Configurator/Dynamic/IProject.cs b/Configurator/Dynamic/IProject.cs new file mode 100644 index 0000000..23b59a6 --- /dev/null +++ b/Configurator/Dynamic/IProject.cs @@ -0,0 +1,60 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016 Denis Kuzmin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. +*/ + +namespace net.r_eg.DllExport.Configurator.Dynamic +{ + internal interface IProject + { + /// + /// Property name for store ddNS. + /// + string NamespacePropertyName { get; } + + /// + /// Check if ddNS is not yet defined. + /// + bool IsDefinedNamespace { get; } + + /// + /// Define namespace value for current EnvDTE.Project. + /// + /// + void defineNamespace(string name); + + /// + /// To update namespace value for all available projects that contains this meta-library in references. + /// + /// + /// File name without extension of meta library. + /// PublicKeyToken of meta library. + void updateNamespaceForAllProjects(string name, string metalibName, string metalibKey); + + /// + /// Get property value from current project. + /// + /// + /// + string getPropertyValue(string name); + } +} diff --git a/Configurator/Dynamic/Project.cs b/Configurator/Dynamic/Project.cs new file mode 100644 index 0000000..9dd98a3 --- /dev/null +++ b/Configurator/Dynamic/Project.cs @@ -0,0 +1,167 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016 Denis Kuzmin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. +*/ + +using System; +using net.r_eg.DllExport.Configurator.Exceptions; + +namespace net.r_eg.DllExport.Configurator.Dynamic +{ + internal class Project: IProject + { + public const string NS_PROP_NAME = "DllExportNamespace"; + + /// + /// EnvDTE.Project + /// + protected dynamic pdte; + + /// + /// Microsoft.Build.Evaluation.ProjectCollection + /// + protected dynamic pmbe; + + /// + /// Property name for store ddNS. + /// + public string NamespacePropertyName + { + get { + return NS_PROP_NAME; + } + } + + /// + /// Check if ddNS is not yet defined. + /// + public bool IsDefinedNamespace + { + get { + string vNamespace = MBEProject.GetPropertyValue(NamespacePropertyName); + return String.IsNullOrEmpty(vNamespace); + } + } + + protected dynamic MBEProjects + { + get { + return loadedMBEProjects(pdte.FullName); + } + } + + protected dynamic MBEProject + { + get + { + foreach(var prj in MBEProjects) { + return prj; + } + throw new InvalidObjectException("Projects is invalid or empty"); + } + } + + protected dynamic DTEProjects + { + get { + return pdte.Collection; + } + } + + /// + /// Define namespace value for current EnvDTE.Project. + /// + /// + public void defineNamespace(string name) + { + checkName(ref name); + + MBEProject.SetProperty(NamespacePropertyName, name); + pdte.Save(); + } + + /// + /// To update namespace value for all available projects that contains this meta-library in references. + /// TODO: another way + /// + /// + /// File name without extension of meta library. + /// PublicKeyToken of meta library. + public void updateNamespaceForAllProjects(string name, string metalibName, string metalibKey) + { + checkName(ref name); + + foreach(var dtePrj in DTEProjects) + { + if(!hasReference(dtePrj.Object.References, metalibName, metalibKey)) { + continue; + } + + foreach(var ePrj in loadedMBEProjects(dtePrj.FullName)) { + if(!ePrj.FullPath.EndsWith(".user", StringComparison.OrdinalIgnoreCase)) { + ePrj.SetProperty(NamespacePropertyName, name); + } + } + dtePrj.Save(dtePrj.FullName); // save it with EnvDTE to avoid 'modified outside the environment' + } + } + + /// + /// Get property value from current project. + /// + /// + /// + public string getPropertyValue(string name) + { + return MBEProject.GetPropertyValue(name); + } + + public Project(dynamic pdte, dynamic pmbe) + { + this.pdte = pdte; + this.pmbe = pmbe; + } + + protected dynamic loadedMBEProjects(string fullname) + { + return pmbe.GetLoadedProjects(fullname); + } + + protected bool hasReference(dynamic pRefs, string name, string pubkey) + { + foreach(var pRef in pRefs) { + // https://msdn.microsoft.com/en-us/library/vslangproj.reference.aspx + if(pRef.Name == name && pRef.PublicKeyToken == pubkey) { + return true; + } + } + return false; + } + + protected void checkName(ref string name) + { + if(String.IsNullOrWhiteSpace(name)) { + throw new ArgumentException("Namespace cannot be null."); + } + } + } +} diff --git a/Configurator/Exceptions/CommonException.cs b/Configurator/Exceptions/CommonException.cs new file mode 100644 index 0000000..b01c5cc --- /dev/null +++ b/Configurator/Exceptions/CommonException.cs @@ -0,0 +1,66 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016 Denis Kuzmin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. +*/ + +using System; + +namespace net.r_eg.DllExport.Configurator.Exceptions +{ + [Serializable] + public class CommonException: Exception + { + public CommonException(string message, Exception innerException, params object[] args) + : base(format(ref message, args), innerException) + { + + } + + public CommonException(string message, params object[] args) + : base(format(ref message, args)) + { + + } + + public CommonException(string message, Exception innerException) + : base(message, innerException) + { + + } + + public CommonException(string message) + : base(message) + { + + } + + public CommonException() + { + + } + + protected static string format(ref string message, params object[] args) + { + return String.Format(message, args); + } + } +} diff --git a/Configurator/Exceptions/InvalidObjectException.cs b/Configurator/Exceptions/InvalidObjectException.cs new file mode 100644 index 0000000..882579e --- /dev/null +++ b/Configurator/Exceptions/InvalidObjectException.cs @@ -0,0 +1,38 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016 Denis Kuzmin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. +*/ + +using System; + +namespace net.r_eg.DllExport.Configurator.Exceptions +{ + [Serializable] + public class InvalidObjectException: CommonException + { + public InvalidObjectException(string message) + : base(message) + { + + } + } +} diff --git a/Configurator/Executor.cs b/Configurator/Executor.cs new file mode 100644 index 0000000..ef21cd2 --- /dev/null +++ b/Configurator/Executor.cs @@ -0,0 +1,91 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016 Denis Kuzmin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. +*/ + +using System.Text; +using net.r_eg.Conari.Log; +using net.r_eg.DllExport.Configurator.Dynamic; +using net.r_eg.DllExport.NSBin; + +namespace net.r_eg.DllExport.Configurator +{ + internal class Executor: IExecutor + { + protected UserConfig config; + protected IProject project; + protected IDDNS ddns; + + public ISender Log + { + get { + return LSender._; + } + } + + public void configure() + { + if(project.IsDefinedNamespace) + { + config.defnamespaces.Insert(0, project.getPropertyValue("RootNamespace")); + + var form = new InstallationForm(config); + form.ShowDialog(); + + project.defineNamespace(config.unamespace); + } + + cfgNamespace(); + cfgPlatform(); + cfgCompiler(); + } + + public Executor(IScriptConfig cfg) + { + ddns = new DDNS(Encoding.UTF8); + config = new UserConfig(cfg) { nsBuffer = ddns.NSBuffer }; + project = new Project(config.script.ProjectDTE, config.script.ProjectsMBE); + } + + protected void cfgNamespace() + { + project.updateNamespaceForAllProjects( + config.unamespace, + config.MetaLibAsmFileName, + config.MetaLibPublicKeyToken + ); + + // binary modifications of metalib assembly + ddns.setNamespace(config.script.MetaLib, config.unamespace); + } + + protected void cfgPlatform() + { + //TODO: + } + + protected void cfgCompiler() + { + //TODO: + } + } +} diff --git a/Configurator/IExecutor.cs b/Configurator/IExecutor.cs new file mode 100644 index 0000000..ca4dff3 --- /dev/null +++ b/Configurator/IExecutor.cs @@ -0,0 +1,35 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016 Denis Kuzmin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. +*/ + +using net.r_eg.Conari.Log; + +namespace net.r_eg.DllExport.Configurator +{ + internal interface IExecutor + { + ISender Log { get; } + + void configure(); + } +} diff --git a/Configurator/InstallationForm.Designer.cs b/Configurator/InstallationForm.Designer.cs new file mode 100644 index 0000000..8c73d92 --- /dev/null +++ b/Configurator/InstallationForm.Designer.cs @@ -0,0 +1,218 @@ +namespace net.r_eg.DllExport.Configurator +{ + partial class InstallationForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if(disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.btnConfigure = new System.Windows.Forms.Button(); + this.comboNS = new System.Windows.Forms.ComboBox(); + this.groupNS = new System.Windows.Forms.GroupBox(); + this.panelNScombo = new System.Windows.Forms.Panel(); + this.linkDDNS = new System.Windows.Forms.LinkLabel(); + this.groupPlatform = new System.Windows.Forms.GroupBox(); + this.rbPlatformX64 = new System.Windows.Forms.RadioButton(); + this.rbPlatformX86 = new System.Windows.Forms.RadioButton(); + this.groupCompiler = new System.Windows.Forms.GroupBox(); + this.numOrdinal = new System.Windows.Forms.NumericUpDown(); + this.labelOrdinals = new System.Windows.Forms.Label(); + this.toolTip = new System.Windows.Forms.ToolTip(this.components); + this.groupNS.SuspendLayout(); + this.panelNScombo.SuspendLayout(); + this.groupPlatform.SuspendLayout(); + this.groupCompiler.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numOrdinal)).BeginInit(); + this.SuspendLayout(); + // + // btnConfigure + // + this.btnConfigure.Location = new System.Drawing.Point(366, 162); + this.btnConfigure.Name = "btnConfigure"; + this.btnConfigure.Size = new System.Drawing.Size(75, 23); + this.btnConfigure.TabIndex = 0; + this.btnConfigure.Text = "Configure"; + this.btnConfigure.UseVisualStyleBackColor = true; + this.btnConfigure.Click += new System.EventHandler(this.btnConfigure_Click); + // + // comboNS + // + this.comboNS.Dock = System.Windows.Forms.DockStyle.Fill; + this.comboNS.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.comboNS.FormattingEnabled = true; + this.comboNS.Location = new System.Drawing.Point(1, 1); + this.comboNS.Name = "comboNS"; + this.comboNS.Size = new System.Drawing.Size(419, 21); + this.comboNS.TabIndex = 1; + this.toolTip.SetToolTip(this.comboNS, "It will override prev. if exists"); + this.comboNS.TextUpdate += new System.EventHandler(this.comboNS_TextUpdate); + // + // groupNS + // + this.groupNS.Controls.Add(this.panelNScombo); + this.groupNS.Controls.Add(this.linkDDNS); + this.groupNS.Location = new System.Drawing.Point(3, 3); + this.groupNS.Name = "groupNS"; + this.groupNS.Size = new System.Drawing.Size(438, 63); + this.groupNS.TabIndex = 2; + this.groupNS.TabStop = false; + this.groupNS.Text = "Namespace for DllExport"; + // + // panelNScombo + // + this.panelNScombo.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(92)))), ((int)(((byte)(158)))), ((int)(((byte)(207))))); + this.panelNScombo.Controls.Add(this.comboNS); + this.panelNScombo.Location = new System.Drawing.Point(9, 16); + this.panelNScombo.Name = "panelNScombo"; + this.panelNScombo.Padding = new System.Windows.Forms.Padding(1); + this.panelNScombo.Size = new System.Drawing.Size(421, 23); + this.panelNScombo.TabIndex = 3; + // + // linkDDNS + // + this.linkDDNS.AutoSize = true; + this.linkDDNS.Location = new System.Drawing.Point(6, 43); + this.linkDDNS.Name = "linkDDNS"; + this.linkDDNS.Size = new System.Drawing.Size(100, 13); + this.linkDDNS.TabIndex = 2; + this.linkDDNS.TabStop = true; + this.linkDDNS.Text = "? More about ddNS"; + this.linkDDNS.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkDDNS_LinkClicked); + // + // groupPlatform + // + this.groupPlatform.Controls.Add(this.rbPlatformX64); + this.groupPlatform.Controls.Add(this.rbPlatformX86); + this.groupPlatform.Enabled = false; + this.groupPlatform.Location = new System.Drawing.Point(3, 72); + this.groupPlatform.Name = "groupPlatform"; + this.groupPlatform.Size = new System.Drawing.Size(95, 84); + this.groupPlatform.TabIndex = 3; + this.groupPlatform.TabStop = false; + this.groupPlatform.Text = "Platform target"; + // + // rbPlatformX64 + // + this.rbPlatformX64.AutoSize = true; + this.rbPlatformX64.Location = new System.Drawing.Point(22, 51); + this.rbPlatformX64.Name = "rbPlatformX64"; + this.rbPlatformX64.Size = new System.Drawing.Size(42, 17); + this.rbPlatformX64.TabIndex = 1; + this.rbPlatformX64.Text = "x64"; + this.rbPlatformX64.UseVisualStyleBackColor = true; + // + // rbPlatformX86 + // + this.rbPlatformX86.AutoSize = true; + this.rbPlatformX86.Checked = true; + this.rbPlatformX86.Location = new System.Drawing.Point(22, 25); + this.rbPlatformX86.Name = "rbPlatformX86"; + this.rbPlatformX86.Size = new System.Drawing.Size(42, 17); + this.rbPlatformX86.TabIndex = 0; + this.rbPlatformX86.TabStop = true; + this.rbPlatformX86.Text = "x86"; + this.rbPlatformX86.UseVisualStyleBackColor = true; + // + // groupCompiler + // + this.groupCompiler.Controls.Add(this.numOrdinal); + this.groupCompiler.Controls.Add(this.labelOrdinals); + this.groupCompiler.Enabled = false; + this.groupCompiler.Location = new System.Drawing.Point(104, 72); + this.groupCompiler.Name = "groupCompiler"; + this.groupCompiler.Size = new System.Drawing.Size(337, 84); + this.groupCompiler.TabIndex = 4; + this.groupCompiler.TabStop = false; + this.groupCompiler.Text = "Compiler settings"; + // + // numOrdinal + // + this.numOrdinal.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.numOrdinal.Location = new System.Drawing.Point(6, 22); + this.numOrdinal.Maximum = new decimal(new int[] { + 10000000, + 0, + 0, + 0}); + this.numOrdinal.Name = "numOrdinal"; + this.numOrdinal.Size = new System.Drawing.Size(76, 20); + this.numOrdinal.TabIndex = 2; + this.numOrdinal.KeyDown += new System.Windows.Forms.KeyEventHandler(this.numOrdinal_KeyDown); + // + // labelOrdinals + // + this.labelOrdinals.AutoSize = true; + this.labelOrdinals.Location = new System.Drawing.Point(88, 25); + this.labelOrdinals.Name = "labelOrdinals"; + this.labelOrdinals.Size = new System.Drawing.Size(161, 13); + this.labelOrdinals.TabIndex = 1; + this.labelOrdinals.Text = "Base for ordinals. `.export [{0}+] `"; + // + // InstallationForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(445, 190); + this.Controls.Add(this.groupCompiler); + this.Controls.Add(this.groupPlatform); + this.Controls.Add(this.groupNS); + this.Controls.Add(this.btnConfigure); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "InstallationForm"; + this.ShowIcon = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "DllExport settings"; + this.TopMost = true; + this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.InstallationForm_FormClosed); + this.groupNS.ResumeLayout(false); + this.groupNS.PerformLayout(); + this.panelNScombo.ResumeLayout(false); + this.groupPlatform.ResumeLayout(false); + this.groupPlatform.PerformLayout(); + this.groupCompiler.ResumeLayout(false); + this.groupCompiler.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numOrdinal)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Button btnConfigure; + private System.Windows.Forms.ComboBox comboNS; + private System.Windows.Forms.GroupBox groupNS; + private System.Windows.Forms.LinkLabel linkDDNS; + private System.Windows.Forms.GroupBox groupPlatform; + private System.Windows.Forms.GroupBox groupCompiler; + private System.Windows.Forms.RadioButton rbPlatformX64; + private System.Windows.Forms.RadioButton rbPlatformX86; + private System.Windows.Forms.Label labelOrdinals; + private System.Windows.Forms.NumericUpDown numOrdinal; + private System.Windows.Forms.ToolTip toolTip; + private System.Windows.Forms.Panel panelNScombo; + } +} \ No newline at end of file diff --git a/Configurator/InstallationForm.cs b/Configurator/InstallationForm.cs new file mode 100644 index 0000000..db72baa --- /dev/null +++ b/Configurator/InstallationForm.cs @@ -0,0 +1,137 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016 Denis Kuzmin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. +*/ + +using System; +using System.Windows.Forms; +using net.r_eg.DllExport.NSBin; + +namespace net.r_eg.DllExport.Configurator +{ + using Platform = UserConfig.PlatformTarget; + + public partial class InstallationForm: Form + { + private UserConfig config; + + public InstallationForm(UserConfig cfg) + { + if(cfg == null) { + throw new ArgumentNullException("UserConfig cannot be null."); + } + config = cfg; + + InitializeComponent(); + comboNS.MaxLength = config.nsBuffer; + + foreach(var ns in cfg.defnamespaces) { + comboNS.Items.Add(ns); + } + comboNS.SelectedIndex = 0; + } + + private void saveConfig() + { + config.unamespace = getValidNS(comboNS.Text); + config.platform = rbPlatformX86.Checked ? Platform.x86 : Platform.x64; + config.compiler.ordinalsBase = (int)numOrdinal.Value; + } + + private void apply(bool byDefault = false) + { + if(byDefault) { + comboNS.Text = UserConfig.NS_DEFAULT_VALUE; + } + saveConfig(); + } + + private string getValidNS(string name) + { + if(String.IsNullOrWhiteSpace(name)) { + return UserConfig.NS_DEFAULT_VALUE; + } + return name; + } + + private void prefilter() + { + comboNS.Text = comboNS.Text.Replace(" ", ""); + } + + private void btnConfigure_Click(object sender, EventArgs e) + { + prefilter(); + + if(!DDNS.IsValidNS(comboNS.Text)) { + MessageBox.Show("Your namespace is not correct.", Text, MessageBoxButtons.OK, MessageBoxIcon.Warning); + return; + } + apply(); + + FormClosed -= InstallationForm_FormClosed; + Close(); + } + + private void numOrdinal_KeyDown(object sender, KeyEventArgs e) + { + if(e.KeyValue >= '0' && e.KeyValue <= '9') { + return; + } + + switch(e.KeyCode) + { + case Keys.Left: + case Keys.Right: + case Keys.Up: + case Keys.Down: + case Keys.Back: + case Keys.Delete: { + return; + } + } + + e.SuppressKeyPress = true; + e.Handled = true; + } + + private void InstallationForm_FormClosed(object sender, FormClosedEventArgs e) + { + apply(true); + } + + private void linkDDNS_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + System.Diagnostics.Process.Start("https://github.com/3F/DllExport/issues/2"); + } + + private void comboNS_TextUpdate(object sender, EventArgs e) + { + if(!DDNS.IsValidNS(comboNS.Text)) { + panelNScombo.BackColor = System.Drawing.Color.FromArgb(234, 0, 0); + } + else { + panelNScombo.BackColor = System.Drawing.Color.FromArgb(92, 158, 207); + } + } + } +} diff --git a/Configurator/InstallationForm.resx b/Configurator/InstallationForm.resx new file mode 100644 index 0000000..8766f29 --- /dev/null +++ b/Configurator/InstallationForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/Configurator/Properties/AssemblyInfo.cs b/Configurator/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..4064f15 --- /dev/null +++ b/Configurator/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Configurator [ github.com/3F/DllExport ]")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Configurator")] +[assembly: AssemblyCopyright("github.com/3F")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("9b7723f1-c89f-43e1-b27d-a46a96c82034")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Configurator/ScriptConfig.cs b/Configurator/ScriptConfig.cs new file mode 100644 index 0000000..e212ffd --- /dev/null +++ b/Configurator/ScriptConfig.cs @@ -0,0 +1,54 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016 Denis Kuzmin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. +*/ + +namespace net.r_eg.DllExport.Configurator +{ + public interface IScriptConfig + { + /// + /// Full path to DllExport.dll + /// + string MetaLib { get; } + + /// + /// Full path to package. + /// + string InstallPath { get; } + + /// + /// Full path of package tools. + /// + string ToolsPath { get; } + + /// + /// The instance of EnvDTE project. + /// + dynamic ProjectDTE { get; } + + /// + /// The instance of Microsoft.Build.Evaluation.ProjectCollection.GlobalProjectCollection + /// + dynamic ProjectsMBE { get; } + } +} diff --git a/Configurator/SetConfigurationCmdlet.cs b/Configurator/SetConfigurationCmdlet.cs new file mode 100644 index 0000000..a9e5dba --- /dev/null +++ b/Configurator/SetConfigurationCmdlet.cs @@ -0,0 +1,110 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016 Denis Kuzmin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. +*/ + +using System; +using System.Management.Automation; +using net.r_eg.Conari.Log; + +namespace net.r_eg.DllExport.Configurator +{ + [Cmdlet(VerbsCommon.Set, "Configuration")] + public class SetConfigurationCmdlet: Cmdlet, IScriptConfig + { + private object synch = new object(); + + /// + /// Full path to DllExport.dll + /// + [Parameter(Mandatory = true)] + public string MetaLib + { + get; + set; + } + + /// + /// Full path to package. + /// + [Parameter(Mandatory = true)] + public string InstallPath + { + get; + set; + } + + /// + /// Full path of package tools. + /// + [Parameter(Mandatory = true)] + public string ToolsPath + { + get; + set; + } + + /// + /// The instance of EnvDTE project. + /// + [Parameter(Mandatory = true)] + public dynamic ProjectDTE + { + get; + set; + } + + /// + /// The instance of Microsoft.Build.Evaluation.ProjectCollection.GlobalProjectCollection + /// + [Parameter(Mandatory = true)] + public dynamic ProjectsMBE + { + get; + set; + } + + protected override void ProcessRecord() + { + IExecutor exec = new Executor(this); + + lock(synch) { + exec.Log.Received -= onMsg; + exec.Log.Received += onMsg; + + try { + exec.configure(); + } + catch(Exception ex) { + LSender.Send(this, ex.Message); + } + + exec.Log.Received -= onMsg; + } + } + + private void onMsg(object sender, Message e) + { + WriteObject(e.content); //TODO: + } + } +} diff --git a/Configurator/UserConfig.cs b/Configurator/UserConfig.cs new file mode 100644 index 0000000..aa055ab --- /dev/null +++ b/Configurator/UserConfig.cs @@ -0,0 +1,102 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016 Denis Kuzmin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. +*/ + +using System; +using System.Collections.Generic; + +namespace net.r_eg.DllExport.Configurator +{ + public sealed class UserConfig + { + public const string NS_DEFAULT_VALUE = "System.Runtime.InteropServices"; + + /// + /// A selected namespace for dynamic definition features. + /// + public string unamespace; + + /// + /// Allowed buffer size for NS. + /// + public int nsBuffer; + + /// + /// Predefined list of namespaces. + /// + public List defnamespaces = new List() { + NS_DEFAULT_VALUE, + "RGiesecke.DllExport", + "net.r_eg.DllExport" + }; + + /// + /// Script configuration. + /// + public IScriptConfig script; + + /// + /// Platform target for project. + /// + public PlatformTarget platform; + + /// + /// Settings for ILasm etc. + /// + public CompilerCfg compiler; + + /// + /// PublicKeyToken of meta library. + /// + public string MetaLibPublicKeyToken = "8337224C9AD9E356"; + + /// + /// File name without extension of meta library. + /// + public string MetaLibAsmFileName = "DllExport"; + + public enum PlatformTarget + { + Default, + x86, + x64, + AnyCPU + } + + public struct CompilerCfg + { + /// + /// Base for ordinals. + /// + public int ordinalsBase; + } + + public UserConfig(IScriptConfig cfg) + { + if(cfg == null) { + throw new ArgumentNullException("Script configuration cannot be null."); + } + script = cfg; + } + } +} diff --git a/Configurator/key.snk b/Configurator/key.snk new file mode 100644 index 0000000..6446c98 Binary files /dev/null and b/Configurator/key.snk differ diff --git a/Configurator/packages.config b/Configurator/packages.config new file mode 100644 index 0000000..d3c195f --- /dev/null +++ b/Configurator/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/DllExport.sln b/DllExport.sln index d0c7991..49b1d9b 100644 --- a/DllExport.sln +++ b/DllExport.sln @@ -39,6 +39,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{55898433 EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NSBin", "NSBin\NSBin.csproj", "{311706A5-5ED2-4006-B794-055009D8A256}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Configurator", "Configurator\Configurator.csproj", "{9B7723F1-C89F-43E1-B27D-A46A96C82034}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NSBinTest", "NSBinTest\NSBinTest.csproj", "{3CFD9EB8-69BC-4B41-9ABA-9C1850BE324A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -61,6 +65,14 @@ Global {311706A5-5ED2-4006-B794-055009D8A256}.Debug|Any CPU.Build.0 = Debug|Any CPU {311706A5-5ED2-4006-B794-055009D8A256}.Release|Any CPU.ActiveCfg = Release|Any CPU {311706A5-5ED2-4006-B794-055009D8A256}.Release|Any CPU.Build.0 = Release|Any CPU + {9B7723F1-C89F-43E1-B27D-A46A96C82034}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9B7723F1-C89F-43E1-B27D-A46A96C82034}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9B7723F1-C89F-43E1-B27D-A46A96C82034}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9B7723F1-C89F-43E1-B27D-A46A96C82034}.Release|Any CPU.Build.0 = Release|Any CPU + {3CFD9EB8-69BC-4B41-9ABA-9C1850BE324A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3CFD9EB8-69BC-4B41-9ABA-9C1850BE324A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3CFD9EB8-69BC-4B41-9ABA-9C1850BE324A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3CFD9EB8-69BC-4B41-9ABA-9C1850BE324A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Metadata/DllExportAttribute.cs b/Metadata/DllExportAttribute.cs index 94491aa..006284f 100644 --- a/Metadata/DllExportAttribute.cs +++ b/Metadata/DllExportAttribute.cs @@ -1,4 +1,28 @@ -/* +/* + * The MIT License (MIT) + * + * Copyright (c) 2016 Denis Kuzmin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. +*/ + +/* https://github.com/3F/DllExport/issues/2#issuecomment-231593744 Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F diff --git a/NSBin/BinaryData.cs b/NSBin/BinaryData.cs new file mode 100644 index 0000000..61ac7e2 --- /dev/null +++ b/NSBin/BinaryData.cs @@ -0,0 +1,180 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016 Denis Kuzmin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. +*/ + +using System; +using System.IO; +using System.Text; + +namespace net.r_eg.DllExport.NSBin +{ + public abstract class BinaryData: BinaryReader, IDisposable + { + public Encoding Enc + { + get; + protected set; + } + + public virtual byte[] getBytesFrom(string data) + { + return Enc.GetBytes(data); + } + + public void write(string data, int offset, SeekOrigin origin = SeekOrigin.Begin) + { + write(getBytesFrom(data), offset, origin); + } + + public void write(string data) + { + write(getBytesFrom(data)); + } + + public void write(byte[] data, int offset, SeekOrigin origin = SeekOrigin.Begin) + { + BaseStream.Seek(offset, origin); + write(data); + } + + public void write(byte[] data) + { + BaseStream.Write(data, 0, data.Length); + } + + public byte[] read(int count) + { + byte[] buf = new byte[count]; + BaseStream.Read(buf, 0, count); + return buf; + } + + public byte[] read(int count, int offset, SeekOrigin origin = SeekOrigin.Begin) + { + BaseStream.Seek(offset, origin); + return read(count); + } + + public byte[] readFirst64K() + { + try { + return read(UInt16.MaxValue, 0); + } + finally { + BaseStream.Seek(0, SeekOrigin.Begin); + } + } + + public UInt16 readHexStrAsUInt16() + { + byte[] bsize = new byte[4]; + BaseStream.Read(bsize, 0, 4); + + try { + return Convert.ToUInt16(Enc.GetString(bsize), 16); + } + catch(Exception ex) { + throw new ArgumentException("Incorrect UInt16 data from stream", ex); + } + } + + public UInt16 readHexStrAsUInt16(int offset, SeekOrigin origin = SeekOrigin.Begin) + { + BaseStream.Seek(offset, origin); + return readHexStrAsUInt16(); + } + + public int find(string what, ref byte[] where) + { + return find(getBytesFrom(what), ref where); + } + + public int find(byte[] what, ref byte[] where) + { + int lpos = -1; + + if(where.Length < 1 || what.Length > where.Length) { + return lpos; + } + + for(int i = 0; i < where.Length; ++i) + { + lpos = i; + for(int j = 0; j < what.Length; ++j) { + if(where[i + j] != what[j]) { + lpos = -1; + break; + } + } + + if(lpos != -1) { + break; + } + } + + return lpos; + } + + public BinaryData(string fname, Encoding encoding) + : base(File.Open(fname, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite), encoding) + { + Enc = encoding; + } + + public BinaryData(string fname) + : this(fname, Encoding.UTF8) + { + + } + + protected void free() + { + if(BaseStream != null) { + BaseStream.Dispose(); + } + } + + #region IDisposable + + // To detect redundant calls + private bool disposed = false; + + //public void Dispose() + //{ + // Dispose(true); + //} + + protected override void Dispose(bool disposing) + { + if(disposed) { + return; + } + disposed = true; + + //... + free(); + } + + #endregion + } +} diff --git a/NSBin/DDNS.cs b/NSBin/DDNS.cs new file mode 100644 index 0000000..b91bc95 --- /dev/null +++ b/NSBin/DDNS.cs @@ -0,0 +1,87 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016 Denis Kuzmin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. +*/ + +using System.Text; +using net.r_eg.Conari.Log; + +namespace net.r_eg.DllExport.NSBin +{ + public sealed class DDNS: IDDNS + { + private Encoding encoding; + + /// + /// Available buffer for namespace. + /// + public int NSBuffer + { + get { + return Rmod.NS_BUF_MAX; + } + } + + /// + /// Access to logger. + /// + public ISender Log + { + get { + return LSender._; + } + } + + /// + /// Check that name of namespace is correct for using. + /// + /// + /// + public static bool IsValidNS(string name) + { + return Rmod.IsValidNS(name); + } + + /// + /// Define namespace. + /// + /// Full path to prepared library. + /// New namespace. + public void setNamespace(string lib, string name) + { + using(var def = new Rmod(lib, encoding)) { + def.setNamespace(name); + } + } + + public DDNS(Encoding encoding) + { + this.encoding = encoding; + } + + public DDNS() + : this(Encoding.UTF8) + { + + } + } +} diff --git a/NSBin/DefNs.cs b/NSBin/DefNs.cs deleted file mode 100644 index 711e31d..0000000 --- a/NSBin/DefNs.cs +++ /dev/null @@ -1,173 +0,0 @@ -// Modification of binary assemblies. Format and specification: -// -// https://github.com/3F/DllExport/issues/2#issuecomment-231593744 -// -// Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F -// -// 000005B0 00 C4 7B 01 00 00 00 2F 00 12 05 .Д{..../... -// 000005C0 00 00 02 00 00 00 00 00 00 00 00 00 00 00 26 00 ..............&. -// 000005D0 20 02 00 00 00 00 00 00 00 44 33 46 30 30 46 46 ........D3F00FF <<<< -// 000005E0 31 37 37 30 44 45 44 39 37 38 45 43 37 37 34 42 1770DED978EC774B <<<<... -// -// - - - - -// byte-seq via chars: -// + Identifier = [32]bytes -// + size of buffer = [ 4]bytes (range: 0000 - FFF9; reserved: FFFA - FFFF) -// + buffer of n size -// - - - - -// v1.2: 01F4 - allocated buffer size -// - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using net.r_eg.Conari.Log; - -namespace NSBin -{ - public class DefNs - { - public const string IDNS = "D3F00FF1770DED978EC774BA389F2DC9"; - public const string DEFAULT_NS = "System.Runtime.InteropServices"; - - public Encoding encoding = Encoding.UTF8; - protected string dll; - - public ISender Log - { - get { return LSender._; } - } - - public void setNamespace(string name) - { - Log.send(this, $"set new namespace: ({name}) - ({dll})"); - - if(String.IsNullOrWhiteSpace(dll) || !File.Exists(dll)) { - throw new FileNotFoundException("The DllExport assembly for modifications was not found."); - } - - if(String.IsNullOrWhiteSpace(name)) { - //name = DEFAULT_NS; - throw new ArgumentException("The namespace cannot be null or empty."); - } - - defNS(name); - } - - /// The DllExport assembly for modifications. - public DefNs(string dll) - { - this.dll = dll; - } - - protected void defNS(string ns) - { - string origin = _postfixToOrigin(dll); - - if(!File.Exists(origin)) { - File.Copy(dll, origin); - } - else { - File.Copy(origin, dll, true); - } - - var ident = encoding.GetBytes(IDNS); - - byte[] data = File.ReadAllBytes(dll); - if(data.Length < ident.Length) { - throw new FileNotFoundException("Incorrect size of library."); - } - - int lpos = -1; - for(int i = 0; i < data.Length; ++i) - { - lpos = i; - for(int j = 0; j < ident.Length; ++j) { - if(data[i + j] != ident[j]) { - lpos = -1; - break; - } - } - if(lpos != -1) { - break; - } - } - - if(lpos == -1) { - throw new FileNotFoundException("Incorrect library."); - } - - // ~ - binmod(lpos, ident.Length, nsrule(ns)); - } - - protected void binmod(int lpos, int ident, string ns) - { - using(FileStream stream = new FileStream(dll, FileMode.Open, FileAccess.ReadWrite)) - { - stream.Seek(lpos + ident, SeekOrigin.Begin); - - byte[] bsize = new byte[4]; - stream.Read(bsize, 0, 4); - - var buffer = sysrange( - Convert.ToUInt16(encoding.GetString(bsize), 16) - ); - - byte[] nsBytes = encoding.GetBytes(ns); - int fullseq = ident + bsize.Length + buffer; - - // beginning of miracles - - var nsb = new List(); - nsb.AddRange(nsBytes); - nsb.AddRange(Enumerable.Repeat((byte)0x00, fullseq - nsBytes.Length)); - - stream.Seek(lpos, SeekOrigin.Begin); - stream.Write(nsb.ToArray(), 0, nsb.Count); - - using(var fs = File.Create(_postfixToUpdated(dll))) { - fs.Write(nsBytes, 0, nsBytes.Length); - } - - Log.send(this, "The DllExport Library has been modified !"); - Log.send(this, $"namespace: {ns}"); - Log.send(this, "Details here: https://github.com/3F/DllExport/issues/2"); - } - } - - protected virtual UInt16 sysrange(UInt16 val) - { - /* reserved: FFFA - FFFF */ - - if(val < 0xFFFA) { - return val; - } - - var reserved = 0xFFFF - val; - //switch(reserved) { - // // ... - //} - - throw new NotImplementedException("The reserved combination is not yet implemented or not supported: " + reserved); - } - - protected virtual string nsrule(string name) - { - return Regex.Replace(name, @"[\.\s]{1,}", ".").Trim(new char[] { '.', ' ' }); - } - - private string _postfixToUpdated(string dll) - { - return $"{dll}.updated"; - } - - private string _postfixToOrigin(string dll) - { - return $"{dll}.origin"; - } - } -} diff --git a/NSBin/IDDNS.cs b/NSBin/IDDNS.cs new file mode 100644 index 0000000..371c2bc --- /dev/null +++ b/NSBin/IDDNS.cs @@ -0,0 +1,48 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016 Denis Kuzmin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. +*/ + +using net.r_eg.Conari.Log; + +namespace net.r_eg.DllExport.NSBin +{ + public interface IDDNS + { + /// + /// Available buffer for namespace. + /// + int NSBuffer { get; } + + /// + /// Access to logger. + /// + ISender Log { get; } + + /// + /// Define namespace. + /// + /// Full path to prepared library. + /// New namespace. + void setNamespace(string lib, string name); + } +} diff --git a/NSBin/Marker.cs b/NSBin/Marker.cs new file mode 100644 index 0000000..243f006 --- /dev/null +++ b/NSBin/Marker.cs @@ -0,0 +1,59 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016 Denis Kuzmin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. +*/ + +using System; +using System.IO; +using System.Runtime.Serialization.Formatters.Binary; + +namespace net.r_eg.DllExport.NSBin +{ + public class Marker: BinaryData + { + public const int FORMAT_V = 1; + + public void write(MarkerData data) + { + BaseStream.Seek(0, SeekOrigin.Begin); + BaseStream.SetLength(0); + + write(BitConverter.GetBytes(FORMAT_V)); + + (new BinaryFormatter()).Serialize(BaseStream, data); + } + + public MarkerData read(out int version) + { + BaseStream.Seek(0, SeekOrigin.Begin); + version = ReadInt32(); // ... reserved + + return (MarkerData)(new BinaryFormatter()).Deserialize(BaseStream); + } + + public Marker(string fname) + : base(fname) + { + + } + } +} diff --git a/NSBin/MarkerData.cs b/NSBin/MarkerData.cs new file mode 100644 index 0000000..e8c4c22 --- /dev/null +++ b/NSBin/MarkerData.cs @@ -0,0 +1,47 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016 Denis Kuzmin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. +*/ + +using System; + +namespace net.r_eg.DllExport.NSBin +{ + [Serializable] + public struct MarkerData + { + /// + /// Full namespace + /// + public string nsName; + + /// + /// Position of current nsName + /// + public int nsPosition; + + /// + /// Valid buffer size for namespace. + /// + public int nsBuffer; + } +} diff --git a/NSBin/NSBin.csproj b/NSBin/NSBin.csproj index 625c06c..eb6663f 100644 --- a/NSBin/NSBin.csproj +++ b/NSBin/NSBin.csproj @@ -7,7 +7,7 @@ {311706A5-5ED2-4006-B794-055009D8A256} Library Properties - NSBin + net.r_eg.DllExport.NSBin NSBin v4.0 512 @@ -30,6 +30,12 @@ prompt 4 + + true + + + key.snk + @@ -40,14 +46,21 @@ - + + + - + + + + + + diff --git a/NSBin/Ripper.cs b/NSBin/Ripper.cs new file mode 100644 index 0000000..0ace921 --- /dev/null +++ b/NSBin/Ripper.cs @@ -0,0 +1,37 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016 Denis Kuzmin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. +*/ + +using System.Text; + +namespace net.r_eg.DllExport.NSBin +{ + public class Ripper: BinaryData + { + public Ripper(string fname, Encoding enc) + : base(fname, enc) + { + + } + } +} diff --git a/NSBin/Rmod.cs b/NSBin/Rmod.cs new file mode 100644 index 0000000..24b1390 --- /dev/null +++ b/NSBin/Rmod.cs @@ -0,0 +1,226 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016 Denis Kuzmin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. +*/ + +// Modification of binary assemblies. Format and specification: +// +// https://github.com/3F/DllExport/issues/2#issuecomment-231593744 +// +// Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F +// +// 000005B0 00 C4 7B 01 00 00 00 2F 00 12 05 .Д{..../... +// 000005C0 00 00 02 00 00 00 00 00 00 00 00 00 00 00 26 00 ..............&. +// 000005D0 20 02 00 00 00 00 00 00 00 44 33 46 30 30 46 46 ........D3F00FF <<<< +// 000005E0 31 37 37 30 44 45 44 39 37 38 45 43 37 37 34 42 1770DED978EC774B <<<<... +// +// - - - - +// byte-seq via chars: +// + Identifier = [32]bytes +// + size of buffer = [ 4]bytes (range: 0000 - FFF9; reserved: FFFA - FFFF) +// + buffer of n size +// - - - - +// v1.2: 01F4 - allocated buffer size +// + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using net.r_eg.Conari.Log; + +namespace net.r_eg.DllExport.NSBin +{ + internal class Rmod: IDisposable + { + public const string IDNS = "D3F00FF1770DED978EC774BA389F2DC9"; + public const string DEFAULT_NS = "System.Runtime.InteropServices"; + public const int NS_BUF_MAX = 0x01F4; + + private string dll; + private Ripper ripper; + + public ISender Log + { + get { return LSender._; } + } + + public static bool IsValidNS(string name) + { + if(String.IsNullOrWhiteSpace(name)) { + return false; + } + + return Regex.IsMatch(name, "^[a-z_][a-z_0-9.]*$", RegexOptions.IgnoreCase) + && !Regex.IsMatch(name, @"(?:\.(\s*\.)+|\.\s*$)"); // left. ... .right. + } + + public void setNamespace(string name) + { + Log.send(this, $"set new namespace: ({name}) - ({dll})"); + + if(String.IsNullOrWhiteSpace(dll) || !File.Exists(dll)) { + throw new FileNotFoundException($"The '{name}' assembly for modifications was not found."); + } + + //if(String.IsNullOrWhiteSpace(name)) { + // throw new ArgumentException("The namespace cannot be null or empty."); + //} + + make(nsRule(name)); + } + + /// The DllExport assembly for modifications. + /// + public Rmod(string dll, Encoding enc) + { + this.dll = dll; + ripper = new Ripper(dll, enc); + } + + protected void make(string ns) + { + //prepareLib(dll); + + var ident = ripper.getBytesFrom(IDNS); + + byte[] data = ripper.readFirst64K(); + if(data.Length < ident.Length) { + throw new FileNotFoundException("Incorrect size of library."); + } + + int lpos = ripper.find(ident, ref data); + + if(lpos == -1) { + throw new FileNotFoundException("Incorrect library."); + } + + binmod(lpos, ident.Length, ns); + } + + protected void binmod(int lpos, int ident, string ns) + { + Log.send(this, $"binmod: lpos({lpos}); ident({ident})"); + + using(Stream stream = ripper.BaseStream) + { + stream.Seek(lpos + ident, SeekOrigin.Begin); + + ushort buffer = sysrange( + ripper.readHexStrAsUInt16() + ); + + byte[] nsBytes = ripper.getBytesFrom(ns); + int fullseq = ident + sizeof(UInt16) + buffer; + + Log.send(this, $"binmod: buffer({buffer}); fullseq({fullseq})"); + + // the beginning of miracles + + var nsb = new List(); + nsb.AddRange(nsBytes); + nsb.AddRange(Enumerable.Repeat((byte)0x00, fullseq - nsBytes.Length)); + + stream.Seek(lpos, SeekOrigin.Begin); + stream.Write(nsb.ToArray(), 0, nsb.Count); + + using(var m = new Marker(_postfixToUpdated(dll))) { + m.write(new MarkerData() { nsPosition = lpos, nsBuffer = buffer, nsName = ns }); + } + + Log.send(this, "\nThe DllExport Library has been modified !\n"); + Log.send(this, $"namespace: '{ns}' :: {dll}"); + Log.send(this, "Details here: https://github.com/3F/DllExport/issues/2"); + } + } + + protected virtual UInt16 sysrange(UInt16 val) + { + /* reserved: FFFA - FFFF */ + + if(val < 0xFFFA) { + return val; + } + + var reserved = 0xFFFF - val; + //switch(reserved) { + // // ... + //} + + throw new NotImplementedException("The reserved combination is not yet implemented or not supported: " + reserved); + } + + protected virtual string nsRule(string name) + { + // Regex.Replace(name, @"[\.\s]{1,}", ".").Trim(new char[] { '.', ' ' }); + + if(IsValidNS(name)) { + return name.Replace(" ", ""); + } + return DEFAULT_NS; + } + + //protected void prepareLib(string dll) + //{ + // string origin = _postfixToOrigin(dll); + + // if(!File.Exists(origin)) { + // File.Copy(dll, origin); + // } + // else { + // File.Copy(origin, dll, true); + // } + //} + + private string _postfixToUpdated(string dll) + { + return $"{dll}.ddNSi"; + } + + #region IDisposable + + // To detect redundant calls + private bool disposed = false; + + public void Dispose() + { + Dispose(true); + } + + protected virtual void Dispose(bool disposing) + { + if(disposed) { + return; + } + disposed = true; + + //... + if(ripper != null) { + ripper.Dispose(); + } + } + + #endregion + } +} diff --git a/NSBin/SetDDNSCmdlet.cs b/NSBin/SetDDNSCmdlet.cs new file mode 100644 index 0000000..deb5f67 --- /dev/null +++ b/NSBin/SetDDNSCmdlet.cs @@ -0,0 +1,74 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016 Denis Kuzmin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. +*/ + +using System.Management.Automation; +using System.Text; + +namespace net.r_eg.DllExport.NSBin +{ + [Cmdlet(VerbsCommon.Set, "DDNS")] + public class SetDDNSCmdlet: Cmdlet + { + private object synch = new object(); + + /// + /// Full path to prepared library. + /// + [Parameter(Mandatory = true)] + public string Dll + { + get; + set; + } + + /// + /// New namespace. + /// + [Parameter(Mandatory = true)] + public string Namespace + { + get; + set; + } + + protected override void ProcessRecord() + { + IDDNS ddns = new DDNS(Encoding.UTF8); + + lock(synch) { + ddns.Log.Received -= onMsg; + ddns.Log.Received += onMsg; + + ddns.setNamespace(Dll, Namespace); + + ddns.Log.Received -= onMsg; + } + } + + private void onMsg(object sender, net.r_eg.Conari.Log.Message e) + { + WriteObject(e.content); //TODO: + } + } +} diff --git a/NSBin/SetDllExportNSCmdlet.cs b/NSBin/SetDllExportNSCmdlet.cs deleted file mode 100644 index 343bb96..0000000 --- a/NSBin/SetDllExportNSCmdlet.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Management.Automation; -using System.Text; - -namespace NSBin -{ - [Cmdlet(VerbsCommon.Set, "DllExportNS")] - public class SetDllExportNSCmdlet: Cmdlet - { - [Parameter(Mandatory = true)] - public string Dll - { - get; - set; - } - - [Parameter(Mandatory = true)] - public string Namespace - { - get; - set; - } - - protected override void ProcessRecord() - { - var dns = new DefNs(Dll) { encoding = Encoding.UTF8 }; - dns.Log.Received += onMsg; - - dns.setNamespace(Namespace); - } - - private void onMsg(object sender, net.r_eg.Conari.Log.Message e) - { - WriteObject(e.content); - } - } -} diff --git a/NSBin/key.snk b/NSBin/key.snk new file mode 100644 index 0000000..2b60be4 Binary files /dev/null and b/NSBin/key.snk differ diff --git a/NSBinTest/DDNSTest.cs b/NSBinTest/DDNSTest.cs new file mode 100644 index 0000000..03a8698 --- /dev/null +++ b/NSBinTest/DDNSTest.cs @@ -0,0 +1,25 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using net.r_eg.DllExport.NSBin; + +namespace net.r_eg.DllExport.NSBinTest +{ + [TestClass] + public class DDNSTest + { + [TestMethod] + public void nsTest1() + { + Assert.AreEqual(true, DDNS.IsValidNS("net.r_eg.DllExport")); + Assert.AreEqual(false, DDNS.IsValidNS("net.r_eg..DllExport")); + Assert.AreEqual(false, DDNS.IsValidNS("net.r-eg.DllExport")); + Assert.AreEqual(false, DDNS.IsValidNS("net. r_eg . DllExport")); + Assert.AreEqual(false, DDNS.IsValidNS("net.r_eg.DllExport.")); + Assert.AreEqual(false, DDNS.IsValidNS("0net.r_eg.DllExport")); + Assert.AreEqual(false, DDNS.IsValidNS(".net.r_eg.DllExport")); + Assert.AreEqual(false, DDNS.IsValidNS(" ")); + Assert.AreEqual(false, DDNS.IsValidNS(null)); + } + + + } +} diff --git a/NSBinTest/MarkerTest.cs b/NSBinTest/MarkerTest.cs new file mode 100644 index 0000000..6d63b30 --- /dev/null +++ b/NSBinTest/MarkerTest.cs @@ -0,0 +1,36 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using net.r_eg.DllExport.NSBin; +using net.r_eg.vsSBE.Test; + +namespace net.r_eg.DllExport.NSBinTest +{ + [TestClass] + public class MarkerTest + { + [TestMethod] + public void rwTest1() + { + using(var tf = new TempFile()) + { + MarkerData md = new MarkerData() { + nsName = "net.r_eg", + nsBuffer = 0x01F4, + nsPosition = 1024 + }; + + var target = new Marker(tf.file); + target.write(md); + + int actualVersion; + MarkerData actual = target.read(out actualVersion); + + Assert.AreEqual(Marker.FORMAT_V, actualVersion); + Assert.AreEqual(md.nsBuffer, actual.nsBuffer); + Assert.AreEqual(md.nsName, actual.nsName); + Assert.AreEqual(md.nsPosition, actual.nsPosition); + } + } + + + } +} diff --git a/NSBinTest/NSBinTest.csproj b/NSBinTest/NSBinTest.csproj new file mode 100644 index 0000000..646acd6 --- /dev/null +++ b/NSBinTest/NSBinTest.csproj @@ -0,0 +1,95 @@ + + + + Debug + AnyCPU + {3CFD9EB8-69BC-4B41-9ABA-9C1850BE324A} + Library + Properties + net.r_eg.DllExport.NSBinTest + NSBinTest + v4.0 + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages + False + UnitTest + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + 3.5 + + + + + + + + + + + + + + + + + + + + + + + + {311706a5-5ed2-4006-b794-055009d8a256} + NSBin + + + + + + + False + + + False + + + False + + + False + + + + + + + + \ No newline at end of file diff --git a/NSBinTest/Properties/AssemblyInfo.cs b/NSBinTest/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..97b0562 --- /dev/null +++ b/NSBinTest/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("NSBinTest [ github.com/3F/DllExport ]")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("NSBinTest")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("3cfd9eb8-69bc-4b41-9aba-9c1850be324a")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/NSBinTest/RipperTest.cs b/NSBinTest/RipperTest.cs new file mode 100644 index 0000000..6fba096 --- /dev/null +++ b/NSBinTest/RipperTest.cs @@ -0,0 +1,112 @@ +using System; +using System.IO; +using System.Text; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using net.r_eg.DllExport.NSBin; +using net.r_eg.vsSBE.Test; + +namespace net.r_eg.DllExport.NSBinTest +{ + [TestClass] + public class RipperTest + { + [TestMethod] + public void getBytesFromTest1() + { + using(var tf = new TempFile()) + { + var target = new Ripper(tf.file, Encoding.UTF8); + byte[] actual = target.getBytesFrom("r_1. g"); + + Assert.AreEqual(6, actual.Length); + Assert.AreEqual((byte)'r', actual[0]); + Assert.AreEqual((byte)'_', actual[1]); + Assert.AreEqual((byte)'1', actual[2]); + Assert.AreEqual((byte)'.', actual[3]); + Assert.AreEqual((byte)' ', actual[4]); + Assert.AreEqual((byte)'g', actual[5]); + } + } + + [TestMethod] + public void rwTest1() + { + using(var tf = new TempFile()) + { + Encoding enc = Encoding.UTF8; + + var target = new Ripper(tf.file, enc); + + target.write("r_1. g"); + target.write(new byte[] { (byte)'0', (byte)'1', (byte)'F', (byte)'4' }); + + target.Dispose(); + + var target2 = new Ripper(tf.file, enc); + + byte[] readed = target2.read(3, 1); + Assert.AreEqual(3, readed.Length); + Assert.AreEqual("_1.", enc.GetString(readed)); + + Assert.AreEqual((ushort)0x01F4, target2.readHexStrAsUInt16(2, SeekOrigin.Current)); + } + } + + [TestMethod] + public void findTest1() + { + using(var tf = new TempFile()) + { + Encoding enc = Encoding.UTF8; + + var target = new Ripper(tf.file, enc); + + byte[] where = enc.GetBytes("left data 751349 and right data"); + Assert.AreEqual(5, target.find(enc.GetBytes("data"), ref where)); + Assert.AreEqual(10, target.find("751349", ref where)); + Assert.AreEqual(-1, target.find("777749", ref where)); + Assert.AreEqual(-1, target.find("Data", ref where)); + } + } + + [TestMethod] + public void findTest2() + { + using(var tf = new TempFile()) + { + Encoding enc = Encoding.UTF8; + + var target = new Ripper(tf.file, enc); + + byte[] where = enc.GetBytes("system"); + Assert.AreEqual(-1, target.find("systems", ref where)); + + byte[] whereZero = new byte[0]; + Assert.AreEqual(-1, target.find("systems", ref whereZero)); + } + } + + [TestMethod] + public void findTest3() + { + using(var tf = new TempFile()) + { + Encoding enc = Encoding.UTF8; + + var target = new Ripper(tf.file, enc); + + byte[] where = enc.GetBytes("system"); + Assert.AreEqual(0, target.find("", ref where)); + Assert.AreEqual(0, target.find(new byte[0], ref where)); + } + } + + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void ctorTest1() + { + new Ripper(null, Encoding.UTF8); + } + + } +} diff --git a/NSBinTest/TempFile.cs b/NSBinTest/TempFile.cs new file mode 100644 index 0000000..4ec109d --- /dev/null +++ b/NSBinTest/TempFile.cs @@ -0,0 +1,48 @@ +using System; +using System.IO; + +namespace net.r_eg.vsSBE.Test +{ + public sealed class TempFile: IDisposable + { + public string dir + { + get; + private set; + } + + public string file + { + get; + private set; + } + + public TempFile(bool insideDir = false, string ext = null) + { + string path = Path.GetTempPath(); + string name = Guid.NewGuid().ToString(); + + if(ext != null) { + name += ext; + } + + file = Path.Combine(path, name); + if(insideDir) { + dir = Directory.CreateDirectory(file).FullName; + file = Path.Combine(dir, name); + } + using(var f = File.Create(file)) { } + } + + public void Dispose() + { + try { + File.Delete(file); + if(dir != null) { + Directory.Delete(dir); + } + } + catch { /* we work in temp directory with unique name, so it's not important */ } + } + } +} diff --git a/tools/UnmanagedExports.nuspec b/tools/UnmanagedExports.nuspec deleted file mode 100644 index b7d2424..0000000 --- a/tools/UnmanagedExports.nuspec +++ /dev/null @@ -1,33 +0,0 @@ - - - - UnmanagedExports - 1.2.7 - Unmanaged Exports (DllExport for .Net) - Robert Giesecke - Robert Giesecke - http://opensource.org/licenses/mit-license.php - https://sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexports - false - A set of compile-time libraries (nothing to deploy) and a build task that enable you to export functions from managed code to native applications. - That means, you can create plugins in a managed language like C# or F# for native applications that only have a C-Api (like Notepad++). - The nuget package is all you need. Just mark your methods with [DllExport] and build for x86, x64 or ia64. - - Hints: - - You have to set your platform target to either x86, ia64 or x64. AnyCPU assemblies cannot export functions. - - The export name defaults to the method name and the calling convention to stdcall. If that's all what you want, you can just use [DllExport] without parameters. - - You cannot put your exports in generic types or export generic methods. (The CLR wouldn't know what type parameters to use) - Adds the ability to declare unmanaged function exports. - IOW: the exact opposite of how DllImport works. - - will use the most recent version of Microsoft.Build.Utilities.ToolLocationHelper to have a greater chance of finding the exact ildasm/ilasm for the project's target framework version - -- no longer fails the build when it can't find lib.exe - -- proper overridable MSBuild properties (see tools/RGiesecke.DllExport.targets) - en-US - dllexport unmanaged exports export - - - - - \ No newline at end of file diff --git a/tools/install.ps1 b/tools/install.ps1 index 9d23c01..0853225 100644 --- a/tools/install.ps1 +++ b/tools/install.ps1 @@ -1,18 +1,19 @@ param($installPath, $toolsPath, $package, $project) -$namespaceProp = 'DllExportNamespace'; $targetFileName = 'net.r_eg.DllExport.targets' $assemblyFName = 'DllExport' # $package.AssemblyReferences[0].Name $publicKeyToken = '8337224C9AD9E356'; -$defaultNS = 'System.Runtime.InteropServices'; +$tempRoot = (Join-Path $([System.IO.Path]::GetTempPath()) '50ACAD2A-5AB3-4E6A-BA66-07F55672E91F') -replace ' ', '` ' +$tempFolder = $([System.Guid]::NewGuid()); $escInstallPath = $installPath -replace ' ', '` ' $escToolsPath = $toolsPath -replace ' ', '` ' +$metaLib = $([System.IO.Path]::Combine($escInstallPath, 'lib\net20', $assemblyFName + '.dll')); +$guiAsmFile = 'net.r_eg.DllExport.Configurator.dll'; $targetFileName = [IO.Path]::Combine($toolsPath, $targetFileName) $targetUri = New-Object Uri -ArgumentList $targetFileName, [UriKind]::Absolute $msBuildV4Name = 'Microsoft.Build'; #, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'; $msBuildV4 = [System.Reflection.Assembly]::LoadWithPartialName($msBuildV4Name) # obsolete -$msvb = [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') # obsolete if(!$msBuildV4) { throw New-Object System.IO.FileNotFoundException("Could not load $msBuildV4Name."); @@ -21,66 +22,29 @@ if(!$msBuildV4) { $projectCollection = $msBuildV4.GetType('Microsoft.Build.Evaluation.ProjectCollection') $projects = $projectCollection::GlobalProjectCollection.GetLoadedProjects($project.FullName) +# GUI Configurator -# Define or check the DllExportNamespace property +# powershell -Command "Import-Module (Join-Path $escToolsPath Configurator.dll); Set-Configuration -Dll $asmpath" -$vNamespace = ''; -$userNS = ''; +Remove-Item -Path $tempRoot -Force -Recurse -ErrorAction SilentlyContinue -$projects | % { - $mbeProject = $_ - - $vNamespace = $mbeProject.GetPropertyValue($namespaceProp); - if([String]::IsNullOrEmpty($vNamespace)) - { - #$pFName = [System.IO.Path]::GetFileName($mbeProject.FullPath); - $userNS = [Microsoft.VisualBasic.Interaction]::InputBox( - "Select a DllExport namespace. `nIt overrides prev. if exists. `n`nHow about 'System.Runtime.InteropServices' ? `nor:", - "DllExport namespace", - "$($mbeProject.GetPropertyValue('RootNamespace'))") - - $mbeProject.SetProperty($namespaceProp, $userNS) - $project.Save() - - $vNamespace = $userNS; - } +$tdll = (Join-Path $tempRoot $tempFolder); +if(!(Test-Path -path $tdll)) { + New-Item $tdll -Type Directory >$null } +Copy-Item $toolsPath\*.dll -Destination $tdll >$null -if([String]::IsNullOrWhiteSpace($vNamespace)) { - $vNamespace = $defaultNS; # inc. the 'cancel' button by user -} +$dllGUI = (Join-Path $tdll $guiAsmFile) -# override new NS for all projects that are contains this library in references -# TODO: another way - -if(![String]::IsNullOrEmpty($vNamespace)) # -And ![String]::IsNullOrEmpty($userNS) -{ - foreach($dtePrj in $project.Collection) - { - # https://msdn.microsoft.com/en-us/library/vslangproj.reference.aspx - $dtePrj.Object.References | ? { - $_.Name -ieq $assemblyFName -And $_.PublicKeyToken -ieq $publicKeyToken - } | % { - - $ePrjs = $projectCollection::GlobalProjectCollection.GetLoadedProjects($dtePrj.FullName); - foreach($ePrj in $ePrjs) { - if(!$ePrj.FullPath.EndsWith(".user", [System.StringComparison]::OrdinalIgnoreCase)) { - $ePrj.SetProperty($namespaceProp, $vNamespace); - } - } - $dtePrj.Save($dtePrj.FullName); # save it with EnvDTE to avoid 'modified outside the environment' - - } - } +if(!(Get-Module -Name $guiAsmFile)) { + Import-Module $dllGUI; } -# binary modifications of assembly +Set-Configuration -MetaLib $metaLib -InstallPath $installPath -ToolsPath $toolsPath -ProjectDTE $project -ProjectsMBE $projectCollection::GlobalProjectCollection; -$asmpath = $([System.IO.Path]::Combine($escInstallPath, 'lib\net20', $assemblyFName + '.dll')); -$vNamespace = $vNamespace -replace ' ', '` ' -powershell -Command "Import-Module (Join-Path $escToolsPath NSBin.dll); Set-DllExportNS -Dll $asmpath -Namespace $vNamespace" # defNS $([System.IO.Path]::Combine($installPath, 'lib\net20', $assemblyFName + '.dll')) $vNamespace + # change the reference to DllExport.dll to not be copied locally $project.Object.References | ? { diff --git a/tools/net.r_eg.DllExport.targets b/tools/net.r_eg.DllExport.targets index 8bdac2d..7ee9736 100644 --- a/tools/net.r_eg.DllExport.targets +++ b/tools/net.r_eg.DllExport.targets @@ -78,10 +78,10 @@ - - + + Command="NSBin.bat "$(DllExportAttrDll)" "$(DllExportNamespace)"" /> \ No newline at end of file diff --git a/tools/nsbin.bat b/tools/nsbin.bat index 9577de8..2622c58 100644 --- a/tools/nsbin.bat +++ b/tools/nsbin.bat @@ -3,4 +3,4 @@ set dll=%1 set namespace=%2 -powershell -NonInteractive -NoProfile -NoLogo -Command "& { . %~dp0/nsbin.ps1; defNS %dll% %namespace% }" \ No newline at end of file +powershell -NonInteractive -NoProfile -NoLogo -Command "& { Import-Module %~dp0/NSBin.dll; Set-DDNS -Dll %dll% -Namespace %namespace% }" \ No newline at end of file diff --git a/tools/nsbin.ps1 b/tools/nsbin.ps1 deleted file mode 100644 index 90f1089..0000000 --- a/tools/nsbin.ps1 +++ /dev/null @@ -1,140 +0,0 @@ -# Modification of binary assemblies. Format and specification: -# -# https://github.com/3F/DllExport/issues/2#issuecomment-231593744 -# -# Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F -# -# 000005B0 00 C4 7B 01 00 00 00 2F 00 12 05 .�{..../... -# 000005C0 00 00 02 00 00 00 00 00 00 00 00 00 00 00 26 00 ..............&. -# 000005D0 20 02 00 00 00 00 00 00 00 44 33 46 30 30 46 46 ........D3F00FF <<<< -# 000005E0 31 37 37 30 44 45 44 39 37 38 45 43 37 37 34 42 1770DED978EC774B <<<<... -# -# - - - - -# byte-seq via chars: -# + Identifier = [32]bytes -# + size of buffer = [ 4]bytes (range: 0000 - FFF9; reserved: FFFA - FFFF) -# + buffer of n size -# - - - - -# v1.2: 01F4 - allocated buffer size -# - -$Identifier = 'D3F00FF1770DED978EC774BA389F2DC9'; - -Function defNS([string]$dll, [string]$namespace) -{ - Write-Host "defNS: ($dll); ($namespace)" - - if([String]::IsNullOrWhiteSpace($dll) -Or ![System.IO.File]::Exists($dll)) { - throw New-Object System.IO.FileNotFoundException("The DllExport assembly for modifications was not found."); - } - - if([String]::IsNullOrWhiteSpace($namespace)) { - #$namespace = "System.Runtime.InteropServices"; - throw New-Object System.ArgumentException("The namespace cannot be null or empty."); - } - - $origin = _postfixToOrigin($dll); - if(![System.IO.File]::Exists($origin)) { - [System.IO.File]::Copy($dll, $origin); - } - else { - [System.IO.File]::Copy($origin, $dll, $TRUE); - } - - $enc = [System.Text.Encoding]::UTF8; - $ident = $enc.GetBytes($Identifier); - - $data = [System.IO.File]::ReadAllBytes($dll); - if($data.Length -lt $ident.Length) { - throw New-Object System.IO.FileNotFoundException("Incorrect size of library."); - } - - $lpos = -1; - for($i = 0; $i -lt $data.Length; ++$i) - { - $lpos = $i; - for($j = 0; $j -lt $ident.Length; ++$j) { - if($data[$i + $j] -ne $ident[$j]) { - $lpos = -1; - break; - } - } - if($lpos -ne -1) { - break; - } - } - - if($lpos -eq -1) { - throw New-Object System.IO.FileNotFoundException("Incorrect library."); - } - - # ~ - binmod $lpos $dll $enc $namespace -} - -Function binmod([int]$lpos, [string]$dll, $enc, [string]$namespace) -{ - $stream = $null; - try - { - $stream = New-Object System.IO.FileStream($dll, [System.IO.FileMode]::Open, [System.IO.FileAccess]::ReadWrite); - $stream.Seek($lpos + $ident.Length, [System.IO.SeekOrigin]::Begin); - - $bsize = New-Object byte[] 4; - $stream.Read($bsize, 0, 4); - - $buffer = sysrange( - [System.Convert]::ToUInt16($enc.GetString($bsize), 16) - ); - - $nsBytes = $enc.GetBytes($namespace); - $fullseq = $ident.Length + $bsize.Length + $buffer; - - # beginning of miracles - - $nsb = New-Object 'System.Collections.Generic.List[byte]' - $nsb.AddRange($nsBytes); - $nsb.AddRange([System.Linq.Enumerable]::Repeat([byte]0x00, $fullseq - $nsBytes.Length)); - - $stream.Seek($lpos, [System.IO.SeekOrigin]::Begin); - $stream.Write($nsb.ToArray(), 0, $nsb.Count); - - $fs = [System.IO.File]::Create($(_postfixToUpdated($dll))); - $fs.write($nsBytes, 0, $nsBytes.Length); - $fs.Dispose(); - - Write-Host 'The DllExport Library has been modified !' - Write-Host "namespace: $namespace" - Write-Host 'Details here: https://github.com/3F/DllExport/issues/2' - } - finally { - if($stream -ne $null) { - $stream.Dispose(); - } - } - -} - -Function sysrange([uint16]$val) -{ - # reserved: FFFA - FFFF - - if($val -lt 0xFFFA) { - return $val; - } - - $reserved = 0xFFFF - $val; - - # ... - throw New-Object System.NotImplementedException("The reserved combination is not yet implemented or not supported: " + $reserved); -} - -Function _postfixToUpdated([string]$dll) -{ - return "$dll.updated"; -} - -Function _postfixToOrigin([string]$dll) -{ - return "$dll.origin"; -} \ No newline at end of file