// !! We strongly recommend that you read the "readme.txt" file in the sample code folder.
// !! It contains important instructions on how to use the sample code

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Runtime.InteropServices;	// so we can marshal our structures in dapf.cs

namespace dapfTest
{
	/// <summary>
	/// Summary description for Form1.
	/// </summary>
	public class Form1 : System.Windows.Forms.Form
	{
		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;

		public Form1()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();

			//
			// TODO: Add any constructor code after InitializeComponent call
			//
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		private System.Windows.Forms.GroupBox groupBox1;
		private System.Windows.Forms.TextBox machineIDText;
		private System.Windows.Forms.Label label2;
		private System.Windows.Forms.Label label3;
		private System.Windows.Forms.TextBox expdayText;
		private System.Windows.Forms.Label label4;
		private System.Windows.Forms.TextBox expmonthText;
		private System.Windows.Forms.Label label5;
		private System.Windows.Forms.TextBox expyearText;
        private GroupBox groupBox2;
        private Label label9;
        private TextBox maxDaysText;
        private Button demoSoftwareKey;

		public string AppName = "dapfTest";

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
            this.label1 = new System.Windows.Forms.Label();
            this.dapfFile = new System.Windows.Forms.TextBox();
            this.programDongle = new System.Windows.Forms.Button();
            this.programDongleMod = new System.Windows.Forms.Button();
            this.lockSoftware = new System.Windows.Forms.Button();
            this.tempSoftwareKey = new System.Windows.Forms.Button();
            this.encryptShellData = new System.Windows.Forms.Button();
            this.groupBox1 = new System.Windows.Forms.GroupBox();
            this.expyearText = new System.Windows.Forms.TextBox();
            this.label5 = new System.Windows.Forms.Label();
            this.expmonthText = new System.Windows.Forms.TextBox();
            this.label4 = new System.Windows.Forms.Label();
            this.expdayText = new System.Windows.Forms.TextBox();
            this.label3 = new System.Windows.Forms.Label();
            this.label2 = new System.Windows.Forms.Label();
            this.machineIDText = new System.Windows.Forms.TextBox();
            this.groupBox2 = new System.Windows.Forms.GroupBox();
            this.label9 = new System.Windows.Forms.Label();
            this.maxDaysText = new System.Windows.Forms.TextBox();
            this.demoSoftwareKey = new System.Windows.Forms.Button();
            this.groupBox1.SuspendLayout();
            this.groupBox2.SuspendLayout();
            this.SuspendLayout();
            // 
            // label1
            // 
            this.label1.Location = new System.Drawing.Point(16, 24);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(416, 16);
            this.label1.TabIndex = 0;
            this.label1.Text = "Full path of dapf file:";
            // 
            // dapfFile
            // 
            this.dapfFile.Location = new System.Drawing.Point(16, 40);
            this.dapfFile.Name = "dapfFile";
            this.dapfFile.Size = new System.Drawing.Size(344, 20);
            this.dapfFile.TabIndex = 1;
            // 
            // programDongle
            // 
            this.programDongle.Location = new System.Drawing.Point(84, 88);
            this.programDongle.Name = "programDongle";
            this.programDongle.Size = new System.Drawing.Size(208, 23);
            this.programDongle.TabIndex = 2;
            this.programDongle.Text = "Program Dongle";
            this.programDongle.Click += new System.EventHandler(this.programDongle_Click);
            // 
            // programDongleMod
            // 
            this.programDongleMod.Location = new System.Drawing.Point(84, 128);
            this.programDongleMod.Name = "programDongleMod";
            this.programDongleMod.Size = new System.Drawing.Size(208, 23);
            this.programDongleMod.TabIndex = 3;
            this.programDongleMod.Text = "Program Dongle with modification";
            this.programDongleMod.Click += new System.EventHandler(this.programDongleMod_Click);
            // 
            // lockSoftware
            // 
            this.lockSoftware.Location = new System.Drawing.Point(84, 168);
            this.lockSoftware.Name = "lockSoftware";
            this.lockSoftware.Size = new System.Drawing.Size(208, 23);
            this.lockSoftware.TabIndex = 4;
            this.lockSoftware.Text = "Lock Software";
            this.lockSoftware.Click += new System.EventHandler(this.lockSoftware_Click);
            // 
            // tempSoftwareKey
            // 
            this.tempSoftwareKey.Location = new System.Drawing.Point(64, 88);
            this.tempSoftwareKey.Name = "tempSoftwareKey";
            this.tempSoftwareKey.Size = new System.Drawing.Size(208, 23);
            this.tempSoftwareKey.TabIndex = 5;
            this.tempSoftwareKey.Text = "Create Software Key";
            // 
            // encryptShellData
            // 
            this.encryptShellData.Location = new System.Drawing.Point(84, 208);
            this.encryptShellData.Name = "encryptShellData";
            this.encryptShellData.Size = new System.Drawing.Size(208, 23);
            this.encryptShellData.TabIndex = 6;
            this.encryptShellData.Text = "Encrypt Shell Data Files";
            this.encryptShellData.Click += new System.EventHandler(this.encryptShellData_Click);
            // 
            // groupBox1
            // 
            this.groupBox1.Controls.Add(this.expyearText);
            this.groupBox1.Controls.Add(this.label5);
            this.groupBox1.Controls.Add(this.expmonthText);
            this.groupBox1.Controls.Add(this.label4);
            this.groupBox1.Controls.Add(this.expdayText);
            this.groupBox1.Controls.Add(this.label3);
            this.groupBox1.Controls.Add(this.label2);
            this.groupBox1.Controls.Add(this.machineIDText);
            this.groupBox1.Controls.Add(this.tempSoftwareKey);
            this.groupBox1.Location = new System.Drawing.Point(16, 256);
            this.groupBox1.Name = "groupBox1";
            this.groupBox1.Size = new System.Drawing.Size(336, 128);
            this.groupBox1.TabIndex = 7;
            this.groupBox1.TabStop = false;
            this.groupBox1.Text = "Temporary Software Key";
            // 
            // expyearText
            // 
            this.expyearText.Location = new System.Drawing.Point(240, 56);
            this.expyearText.Name = "expyearText";
            this.expyearText.Size = new System.Drawing.Size(32, 20);
            this.expyearText.TabIndex = 13;
            this.expyearText.Text = "yyyy";
            // 
            // label5
            // 
            this.label5.Location = new System.Drawing.Point(224, 56);
            this.label5.Name = "label5";
            this.label5.Size = new System.Drawing.Size(8, 20);
            this.label5.TabIndex = 12;
            this.label5.Text = "/";
            this.label5.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
            // 
            // expmonthText
            // 
            this.expmonthText.Location = new System.Drawing.Point(184, 56);
            this.expmonthText.Name = "expmonthText";
            this.expmonthText.Size = new System.Drawing.Size(32, 20);
            this.expmonthText.TabIndex = 11;
            this.expmonthText.Text = "mm";
            // 
            // label4
            // 
            this.label4.Location = new System.Drawing.Point(168, 56);
            this.label4.Name = "label4";
            this.label4.Size = new System.Drawing.Size(8, 20);
            this.label4.TabIndex = 10;
            this.label4.Text = "/";
            this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
            // 
            // expdayText
            // 
            this.expdayText.Location = new System.Drawing.Point(128, 56);
            this.expdayText.Name = "expdayText";
            this.expdayText.Size = new System.Drawing.Size(32, 20);
            this.expdayText.TabIndex = 9;
            this.expdayText.Text = "dd";
            // 
            // label3
            // 
            this.label3.Location = new System.Drawing.Point(24, 56);
            this.label3.Name = "label3";
            this.label3.Size = new System.Drawing.Size(100, 20);
            this.label3.TabIndex = 8;
            this.label3.Text = "Expiry Date:";
            this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
            // 
            // label2
            // 
            this.label2.Location = new System.Drawing.Point(24, 24);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(100, 20);
            this.label2.TabIndex = 7;
            this.label2.Text = "Machine ID:";
            this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
            // 
            // machineIDText
            // 
            this.machineIDText.Location = new System.Drawing.Point(128, 24);
            this.machineIDText.Name = "machineIDText";
            this.machineIDText.Size = new System.Drawing.Size(184, 20);
            this.machineIDText.TabIndex = 6;
            // 
            // groupBox2
            // 
            this.groupBox2.Controls.Add(this.label9);
            this.groupBox2.Controls.Add(this.maxDaysText);
            this.groupBox2.Controls.Add(this.demoSoftwareKey);
            this.groupBox2.Location = new System.Drawing.Point(19, 400);
            this.groupBox2.Name = "groupBox2";
            this.groupBox2.Size = new System.Drawing.Size(336, 99);
            this.groupBox2.TabIndex = 14;
            this.groupBox2.TabStop = false;
            this.groupBox2.Text = "Demo Software Key";
            // 
            // label9
            // 
            this.label9.Location = new System.Drawing.Point(24, 24);
            this.label9.Name = "label9";
            this.label9.Size = new System.Drawing.Size(100, 20);
            this.label9.TabIndex = 7;
            this.label9.Text = "Max Days:";
            this.label9.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
            // 
            // maxDaysText
            // 
            this.maxDaysText.Location = new System.Drawing.Point(128, 24);
            this.maxDaysText.Name = "maxDaysText";
            this.maxDaysText.Size = new System.Drawing.Size(184, 20);
            this.maxDaysText.TabIndex = 6;
            // 
            // demoSoftwareKey
            // 
            this.demoSoftwareKey.Location = new System.Drawing.Point(61, 59);
            this.demoSoftwareKey.Name = "demoSoftwareKey";
            this.demoSoftwareKey.Size = new System.Drawing.Size(208, 23);
            this.demoSoftwareKey.TabIndex = 5;
            this.demoSoftwareKey.Text = "Create Demo Template";
            this.demoSoftwareKey.Click += new System.EventHandler(this.demoSoftwareKey_Click);
            // 
            // Form1
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.ClientSize = new System.Drawing.Size(376, 523);
            this.Controls.Add(this.groupBox2);
            this.Controls.Add(this.groupBox1);
            this.Controls.Add(this.encryptShellData);
            this.Controls.Add(this.lockSoftware);
            this.Controls.Add(this.programDongleMod);
            this.Controls.Add(this.programDongle);
            this.Controls.Add(this.dapfFile);
            this.Controls.Add(this.label1);
            this.Name = "Form1";
            this.Text = "Form1";
            this.groupBox1.ResumeLayout(false);
            this.groupBox1.PerformLayout();
            this.groupBox2.ResumeLayout(false);
            this.groupBox2.PerformLayout();
            this.ResumeLayout(false);
            this.PerformLayout();

		}
		#endregion

		private System.Windows.Forms.Label label1;
		private System.Windows.Forms.TextBox dapfFile;
		private System.Windows.Forms.Button programDongle;
		private System.Windows.Forms.Button programDongleMod;
		private System.Windows.Forms.Button lockSoftware;
		private System.Windows.Forms.Button tempSoftwareKey;
		private System.Windows.Forms.Button encryptShellData;

        /* The sample code contains 5 functions. You will not need to use all these functions in your code.
        Just use which ever functions are most appropriate and customise in your own way. The sample code
        is just a guide.  
        
        There are two methods to loading a DAPF file. These are shown in the first two functions
        programDongle_Click and programDongleMod_Click:
        
        programDongle_Click: we load the DAPF file from disk and get a handle and use it "as is" using the API
                             call LoadDAPFFromFile. You can make some limited changes to overwrite the default
                             behaviour by using API flags.
                             
        programDongleMod_Click: we load the DAPF file from disk and load into structures. We can then modify the
                                DAPF settings by modifying this structure. This method uses the API calls
                                ReadDAPFEx and LoadDAPF.
                                
        The other functions use the first method (as it is simpler) but you can use the second method instead if
        you prefer.
        
        Note - an alternative to using the programDongleMod_Click technique is to modify the DAPF file on disk
        and then use the programDongle_Click technique. To modify a binary DAPF you would use the binary structures
        that are defined in dapf.h. To modify JSON DAPF you would need to use a JSON parser.

        lockSoftware_Click : locks software (protect it) to a dongle as specified by the DAPF file.
        
        encryptShellData_Click: encrypts the shell data files specified in the DAPF file (this is used with encrypting
                                data file if you use the Shell Method with "Data File Encryption" enabled).
                             
        tempSoftwareKey_Click: creates a Temporary Software Key based on the DAPF file and settings the user has entered. 

        demoSoftwareKey_Click: creates a Demo Software Key Template based on the DAPF file and settings the user has entered. 

        */

        /// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main() 
		{
			Application.Run(new Form1());
		}

		// load a DAPF file from disk and program the dongle as specified by the DAPF file
		private void programDongle_Click(object sender, System.EventArgs e)
		{
			IntPtr dapfHandle;
			int err_code;
			uint dongle_number;

			// load DAPF from File into memory
			dapfHandle = DinkeyAdd.LoadDAPFFromFile(dapfFile.Text, out err_code);
			if (dapfHandle == IntPtr.Zero)
			{
				MessageBox.Show(DinkeyAdd.GetLastMessage(), AppName, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
				return;
			}

			// program dongle as specified by the DAPF file
			err_code = DinkeyAdd.AddProtection(dapfHandle, DinkeyAdd.ACTION_PROGRAM_DONGLE, 0, 0, out dongle_number);

			// Unload DAPF from memory
			DinkeyAdd.UnloadDAPF(ref dapfHandle);

			// display message (error or success)
			MessageBox.Show(DinkeyAdd.GetLastMessage(), AppName, MessageBoxButtons.OK, MessageBoxIcon.Information);
			return;
		}

        // load a DAPF file from disk, modify it in memory and then program the dongle
		private void programDongleMod_Click(object sender, System.EventArgs e)
		{
			IntPtr dapfHandle;
			int dummy1, dummy2, err_code;
			uint dongle_number;
			DINKEYINFO DinkeyInfo;
			LICENCEINFO[] LicenceInfo;
			FILEINFO[] FileInfo;
			ALGORITHM[] Algorithms;
			DATAFILEENC[] DataFileEnc;

			// in this case we need to read the DAPF into our structures, so that the DAPF values can be modified
			err_code = DinkeyAdd.ReadDAPFEx(dapfFile.Text, out DinkeyInfo, out LicenceInfo, out FileInfo, out Algorithms, out DataFileEnc, out dummy1, out dummy2);
			if (err_code != 0)
			{
				MessageBox.Show(DinkeyAdd.GetLastMessage(), AppName, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
				return;
			}

			// patch new values
			LicenceInfo[0].Features = 12345;
			LicenceInfo[0].Execs = 100;
			LicenceInfo[0].LicenceName = "fred";

			// get DAPF handle
			dapfHandle = DinkeyAdd.LoadDAPF(DinkeyInfo, LicenceInfo, FileInfo, Algorithms, DataFileEnc, out err_code);
			if (dapfHandle == IntPtr.Zero)
			{
				MessageBox.Show(DinkeyAdd.GetLastMessage(), AppName, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
				return;
			}

			// program dongle
			err_code = DinkeyAdd.AddProtection(dapfHandle, DinkeyAdd.ACTION_PROGRAM_DONGLE, 0, 0, out dongle_number);

			// Unload DAPF from memory
			DinkeyAdd.UnloadDAPF(ref dapfHandle);

			// display message (error or success)
			MessageBox.Show(DinkeyAdd.GetLastMessage(), AppName, MessageBoxButtons.OK, MessageBoxIcon.Information);
			return;			
		}

		// load a DAPF file from disk and protect the files specified
		// (in practice it is better to protect the files one at a time and output messages as you go along, similar to DinkeyAdd.exe)
		// In this example we specify the flag to overwrite any existing output file that might exist.
		private void lockSoftware_Click(object sender, System.EventArgs e)
		{
			IntPtr dapfHandle;
			int err_code;
			uint dummy;

			// load DAPF from File into memory
			dapfHandle = DinkeyAdd.LoadDAPFFromFile(dapfFile.Text, out err_code);
			if (dapfHandle == IntPtr.Zero)
			{
				MessageBox.Show(DinkeyAdd.GetLastMessage(), AppName, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
				return;
			}

			// protect all the files listed in the DAPF file
			err_code = DinkeyAdd.AddProtection(dapfHandle, DinkeyAdd.ACTION_PROTECT_SOFTWARE, -1, DinkeyAdd.FLAGS_OVERWRITE_OUTPUT, out dummy);

			// Unload DAPF from memory
			DinkeyAdd.UnloadDAPF(ref dapfHandle);

			// display message (error or success)
			MessageBox.Show(DinkeyAdd.GetLastMessage(), AppName, MessageBoxButtons.OK, MessageBoxIcon.Information);
			return;	
		}

		// load a DAPF file from disk and encrypt the shell data files specified
		// (in practice it is better to encrypt the files one at a time and output messages as you go along, similar to DinkeyAdd.exe)
		// In this example we specify the flag to overwrite any existing output file that might exist.
		private void encryptShellData_Click(object sender, System.EventArgs e)
		{
			IntPtr dapfHandle;
			int err_code;

			// load DAPF from File into memory
			dapfHandle = DinkeyAdd.LoadDAPFFromFile(dapfFile.Text, out err_code);
			if (dapfHandle == IntPtr.Zero)
			{
				MessageBox.Show(DinkeyAdd.GetLastMessage(), AppName, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
				return;
			}

			// encrypt all the shell data files listed in the DAPF file
			err_code = DinkeyAdd.EncryptShellDataFiles(dapfHandle, -1, DinkeyAdd.FLAGS_OVERWRITE_OUTPUT);

			// Unload DAPF from memory
			DinkeyAdd.UnloadDAPF(ref dapfHandle);

			// display message (error or success)
			MessageBox.Show(DinkeyAdd.GetLastMessage(), AppName, MessageBoxButtons.OK, MessageBoxIcon.Information);
			return;			
		}

		// load a DAPF file from disk and create a Temporary Software Key using the info that the user entered
		private void tempSoftwareKey_Click(object sender, System.EventArgs e)
		{
			IntPtr dapfHandle;
			int err_code;
			TEMP_SWKEY_INFO swkey_info = new TEMP_SWKEY_INFO();

			// load DAPF from File into memory
			dapfHandle = DinkeyAdd.LoadDAPFFromFile(dapfFile.Text, out err_code);
			if (dapfHandle == IntPtr.Zero)
			{
				MessageBox.Show(DinkeyAdd.GetLastMessage(), AppName, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
				return;
			}

			// fill out the SWKEY structure from the values the user entered
			swkey_info.size = Marshal.SizeOf(typeof(TEMP_SWKEY_INFO));
			swkey_info.machineID = Convert.ToUInt32(machineIDText.Text, 16);
			swkey_info.expiry_day = Convert.ToInt32(expdayText.Text, 10);			
			swkey_info.expiry_month = Convert.ToInt32(expmonthText.Text, 10);			
			swkey_info.expiry_year = Convert.ToInt32(expyearText.Text, 10);			
			// !!!! in this case we just choose Pro Plus. You could load the DAPF file into structures and see which model is selected.
			// If there is more than one model selected you can ask the customer to choose which model they want.
			swkey_info.dongle_model = DinkeyAdd.SWKEY_MODEL_PRO_PLUS;
			swkey_info.dongle_number = 0;

			// attempt to create the Temporary Software Key
			err_code = DinkeyAdd.CreateTempSoftwareKey(dapfHandle, swkey_info, 0);

			// Unload DAPF from memory
			DinkeyAdd.UnloadDAPF(ref dapfHandle);

			// display message (error or success)
			MessageBox.Show(DinkeyAdd.GetLastMessage(), AppName, MessageBoxButtons.OK, MessageBoxIcon.Information);
			return;			
		}

        private void demoSoftwareKey_Click(object sender, EventArgs e)
        {
            IntPtr dapfHandle;
            int err_code;
            DEMO_SWKEY_INFO swkey_info = new DEMO_SWKEY_INFO();

            // load DAPF from File into memory
            dapfHandle = DinkeyAdd.LoadDAPFFromFile(dapfFile.Text, out err_code);
            if (dapfHandle == IntPtr.Zero)
            {
                MessageBox.Show(DinkeyAdd.GetLastMessage(), AppName, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }

            // fill out the SWKEY structure from the values the user entered
            swkey_info.size = Marshal.SizeOf(typeof(DEMO_SWKEY_INFO));
            swkey_info.max_days = Convert.ToInt32(maxDaysText.Text, 10);
            // !!!! in this case we just choose the default model (assuming you only selected one in the DAPF file).
            // If you want to specify more than one model then OR the flags together. e.g. DinkeyAdd.SWKEY_BITMAP_PRO_LITE | DinkeyAdd.SWKEY_BITMAP_PRO_PLUS
            swkey_info.models = DinkeyAdd.SWKEY_BITMAP_DEFAULT;

            // attempt to create the Temporary Software Key
            err_code = DinkeyAdd.CreateDemoSoftwareKeyTemplate(dapfHandle, swkey_info, 0);

            // Unload DAPF from memory
            DinkeyAdd.UnloadDAPF(ref dapfHandle);

            // display message (error or success)
            MessageBox.Show(DinkeyAdd.GetLastMessage(), AppName, MessageBoxButtons.OK, MessageBoxIcon.Information);
            return;
        }

	}
}
