// !! this file should not be modified

using System;
using System.Runtime.InteropServices;				// so we can import DLL functions
using System.Text;									// so we can extract prodcode from array        

// classes to load the correct 32-bit/64-bit DinkeyChange.dll functions - used by DinkeyChange class

// loads DCGetInfo from the 32-bit DinkeyChange.dll
class DCGetInfo32
{
    [DllImport("DinkeyChange.dll", CharSet = CharSet.Ansi)]
    public static extern int DCGetInfo(int type_mask, int model_mask, string prodcode_mask, int array_length, out int num_found, int[] type, int[] model, byte[] prodcode, uint[] dongle_number, int[] update_number);
}

// loads DCGetInfo from the 64-bit DinkeyChange64.dll
class DCGetInfo64
{
    [DllImport("DinkeyChange64.dll", CharSet = CharSet.Ansi)]
    public static extern int DCGetInfo(int type_mask, int model_mask, string prodcode_mask, int array_length, out int num_found, int[] type, int[] model, byte[] prodcode, uint[] dongle_number, int[] update_number);
}

// loads DCGetDiagnosticInfo from the 32-bit DinkeyChange.dll
class DCGetDiagnosticInfo32
{
    [DllImport("DinkeyChange.dll", CharSet = CharSet.Ansi)]
    public static extern int DCGetDiagnosticInfo(string filename);
}

// loads DCGetDiagnosticInfo from the 64-bit DinkeyChange64.dll
class DCGetDiagnosticInfo64
{
    [DllImport("DinkeyChange64.dll", CharSet = CharSet.Ansi)]
    public static extern int DCGetDiagnosticInfo(string filename);
}

// loads DCDoUpdateCodeString from the 32-bit DinkeyChange.dll
class DCDoUpdateCodeString32
{
    [DllImport("DinkeyChange.dll", CharSet = CharSet.Ansi)]
    public static extern int DCDoUpdateCodeString(string update_code_string, out int confirmation_code, out int extended_error);
}

// loads DCDoUpdateCodeString from the 64-bit DinkeyChange64.dll
class DCDoUpdateCodeString64
{
    [DllImport("DinkeyChange64.dll", CharSet = CharSet.Ansi)]
    public static extern int DCDoUpdateCodeString(string update_code_string, out int confirmation_code, out int extended_error);
}

// loads DCDoUpdateCodeFromFile from the 32-bit DinkeyChange.dll
class DCDoUpdateCodeFromFile32
{
    [DllImport("DinkeyChange.dll", CharSet = CharSet.Ansi)]
    public static extern int DCDoUpdateCodeFromFile(string update_code_file, out int confirmation_code, out int extended_error);
}

// loads DCDoUpdateCodeFromFile from the 64-bit DinkeyChange64.dll
class DCDoUpdateCodeFromFile64
{
    [DllImport("DinkeyChange64.dll", CharSet = CharSet.Ansi)]
    public static extern int DCDoUpdateCodeFromFile(string update_code_file, out int confirmation_code, out int extended_error);
}

// loads DCRestoreDinkeyFDLite from the 32-bit DinkeyChange.dll
class DCRestoreDinkeyFDLite32
{
    [DllImport("DinkeyChange.dll", CharSet = CharSet.Ansi)]
    public static extern int DCRestoreDinkeyFDLite();
}

// loads DCRestoreDinkeyFDLite from the 64-bit DinkeyChange64.dll
class DCRestoreDinkeyFDLite64
{
    [DllImport("DinkeyChange64.dll", CharSet = CharSet.Ansi)]
    public static extern int DCRestoreDinkeyFDLite();
}

// loads DCGetMachineID from the 32-bit DinkeyChange.dll
class DCGetMachineID32
{
    [DllImport("DinkeyChange.dll", CharSet = CharSet.Ansi)]
    public static extern int DCGetMachineID(out uint machineID, out int extended_error);
}

// loads DCGetMachineID from the 64-bit DinkeyChange64.dll
class DCGetMachineID64
{
    [DllImport("DinkeyChange64.dll", CharSet = CharSet.Ansi)]
    public static extern int DCGetMachineID(out uint machineID, out int extended_error);
}

// loads DCDownloadTempSoftwareKey from the 32-bit DinkeyChange.dll
class DCDownloadTempSoftwareKey32
{
    [DllImport("DinkeyChange.dll", CharSet = CharSet.Ansi)]
    public static extern int DCDownloadTempSoftwareKey(uint machineID, out int extended_error);
}

// loads DCDownloadTempSoftwareKey from the 64-bit DinkeyChange64.dll
class DCDownloadTempSoftwareKey64
{
    [DllImport("DinkeyChange64.dll", CharSet = CharSet.Ansi)]
    public static extern int DCDownloadTempSoftwareKey(uint machineID, out int extended_error);
}

// loads DCDownloadDemoSoftwareKey from the 32-bit DinkeyChange.dll
class DCDownloadDemoSoftwareKey32
{
    [DllImport("DinkeyChange.dll", CharSet = CharSet.Ansi)]
    public static extern int DCDownloadDemoSoftwareKey(uint machineID, string prodcode, int model, out int extended_error);
}

// loads DCDownloadDemoSoftwareKey from the 64-bit DinkeyChange64.dll
class DCDownloadDemoSoftwareKey64
{
    [DllImport("DinkeyChange64.dll", CharSet = CharSet.Ansi)]
    public static extern int DCDownloadDemoSoftwareKey(uint machineID, string prodcode, int model, out int extended_error);
}

class DinkeyChange
{    

    // **** main API
    // We only want to load the correct DLL for the bit-ness of the computer. The other DLL may not exist.
    // if the appropriate DLL does not exist in the same directory as this test program you will receive a DllNotFoundException    

    // detects whether running 32-bit code or 64-bit code and loads appropriate Dll.
    public static int DCGetInfo(int type_mask, int model_mask, string prodcode_mask, int array_length, out int num_found, int[] type, int[] model, byte[] prodcode, uint[] dongle_number, int[] update_number)
    {
        if (IntPtr.Size == 4)
            return DCGetInfo32.DCGetInfo(type_mask, model_mask, prodcode_mask, array_length, out num_found, type, model, prodcode, dongle_number, update_number);
        return DCGetInfo64.DCGetInfo(type_mask, model_mask, prodcode_mask, array_length, out num_found, type, model, prodcode, dongle_number, update_number);
    }

    public static int DCGetDiagnosticInfo(string filename)
    {
        if (IntPtr.Size == 4)
            return DCGetDiagnosticInfo32.DCGetDiagnosticInfo(filename);
        return DCGetDiagnosticInfo64.DCGetDiagnosticInfo(filename);
    }

    public static int DCDoUpdateCodeString(string update_code_string, out int confirmation_code, out int extended_error)
    {
        if (IntPtr.Size == 4)
            return DCDoUpdateCodeString32.DCDoUpdateCodeString(update_code_string, out confirmation_code, out extended_error);
        return DCDoUpdateCodeString64.DCDoUpdateCodeString(update_code_string, out confirmation_code, out extended_error);
    }

    public static int DCDoUpdateCodeFromFile(string update_code_string, out int confirmation_code, out int extended_error)
    {
        if (IntPtr.Size == 4)
            return DCDoUpdateCodeFromFile32.DCDoUpdateCodeFromFile(update_code_string, out confirmation_code, out extended_error);
        return DCDoUpdateCodeFromFile64.DCDoUpdateCodeFromFile(update_code_string, out confirmation_code, out extended_error);
    }

    public static int DCRestoreDinkeyFDLite()
    {
        if (IntPtr.Size == 4)
            return DCRestoreDinkeyFDLite32.DCRestoreDinkeyFDLite();
        return DCRestoreDinkeyFDLite64.DCRestoreDinkeyFDLite();
    }

    public static int DCGetMachineID(out uint machineID, out int extended_error)
    {
        if (IntPtr.Size == 4)
            return DCGetMachineID32.DCGetMachineID(out machineID, out extended_error);
        return DCGetMachineID64.DCGetMachineID(out machineID, out extended_error);
    }

    public static int DCDownloadTempSoftwareKey(uint machineID, out int extended_error)
    {
        if (IntPtr.Size == 4)
            return DCDownloadTempSoftwareKey32.DCDownloadTempSoftwareKey(machineID, out extended_error);
        return DCDownloadTempSoftwareKey64.DCDownloadTempSoftwareKey(machineID, out extended_error);
    }
    
    public static int DCDownloadDemoSoftwareKey(uint machineID, string prodcode, int model, out int extended_error)
    {
        if (IntPtr.Size == 4)
            return DCDownloadDemoSoftwareKey32.DCDownloadDemoSoftwareKey(machineID, prodcode, model, out extended_error);
        return DCDownloadDemoSoftwareKey64.DCDownloadDemoSoftwareKey(machineID, prodcode, model, out extended_error);
    }
    
    // **** general purpose routines
    
    // routine to extract product code string from array of product codes
    public static string GetProductCode(byte[] prodcode, int index) 
    {
        int i;
        StringBuilder sb = new StringBuilder(8);
        
        for (i=index*9; i<(index+1)*9; i++)
        {
            if (prodcode[i] == 0)
                return sb.ToString();
            else
                sb.Append((char)prodcode[i]);
        }
        return sb.ToString();
    }    
  
}
