// !! this file should not be modified // DRPF file is in the following format: // REMOTEINFO // LICENCEINFO (however many are needed) // ALGCHANGE (however many are needed) // DATACHANGE (however many are needed) - may refer to external files. // Remember: you only need to specify a value if you want to change it. Otherwise you // specify the default "no change" setting. For most entries this is indicated by 0. // However, for MaxNetUsers and LicenceNetUsers it is "-2" because 0 is a valid value to change to. using System; using System.Runtime.InteropServices; // so we can marshal the structures as a block of memory using System.Text; // for StringBuilder class for GetLastMessage API [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi, Pack=1)] public struct REMOTEINFO { public byte Header1; // Should be set to "DRPF" = DinkeyRemote Parameter File public byte Header2; public byte Header3; public byte Header4; public int Version; // version of this structure - currently 2 [MarshalAs(UnmanagedType.ByValTStr, SizeConst=12)] public string ProdCode; // Product Code public uint DongleNumber; public int UpdateNumber; [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] public string Notes; // user-defined notes public int NumLicences; public int NumAlgs; // number of algs to set (incl r/w alg) public int NumDataChanges; // number of data change blocks specified public int DataAreaSize; // -1 = increase as necessary. specifies the new size of the data area public int PerLicence; // 0 = no change, 1 = per licence net users, 2 = per product net users public int MaxNetUsers; // product net users, unlimited = -1, no change = -2 public int LastUsedDay; // Day = 0 (only) -> no change public int LastUsedMonth; public int LastUsedYear; [MarshalAs(UnmanagedType.ByValTStr, SizeConst=12)] public string DataEncKeyProdCode; public int ChangeCodeType; // 0 = no change, bit0 = only accept secure codes, bit1 = accept secure & short codes public int CodeType; // type of code to generate. 0 = secure code, 1 = short code [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] public string OutputFileName; // name of file to output code to. Null (default) -> UpdateCode.ducf public int LockDongle; // 1 = lock dongle to user's computer public int ResetDongleLock; // 1 = reset the dongle lock so that the dongle can be locked to a new machine } [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi, Pack=1)] public struct LICENCEINFO { [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] public string LicenceName; // name of the licence public int Action; // 0 = change, 1 = delete, 2 = add public int AddSetExecs; // 0 = no change to execs, 1 = add, 2 = set public int Execs; // -1 = no limit public int ExecsWarn; // 0 = remove warning, -1 = no change public int ExpiryDay; // -1 = no limit, 0 = no change public int ExpiryMonth; public int ExpiryYear; public int AddSetMaxDays; // 0 = no change, 1 = add, 2 = set public int MaxDays; // -1 = no limit public int DaysWarn; // 0 = remove warning, -1 = no change public int FeaturesFlag; // 0 = don't change features, 1 = change features public uint Features; // all values OK public int LicenceNetUsers; // unlimited = -1, no change = -2 } [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi, Pack=1)] public struct ALGCHANGE { public int alg_number; // number of algorithm to set (0 = r/w algorithm) [MarshalAs(UnmanagedType.ByValArray, SizeConst=12)] public byte[] alg; // algorithm } [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi, Pack=1)] public struct DATACHANGE { public int type; // 1 = file, 2 = hex data, 3 = ascii, 4 = ascii null-term string public int offset; // offset in dongle data memory to write data public int length; // length of data to change [MarshalAs(UnmanagedType.ByValArray, SizeConst=256)] public byte[] data; // data to write OR name of data file depending on which method set } [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi, Pack=1)] public struct UPDATE_CODE_OUTPUTS { [MarshalAs(UnmanagedType.ByValTStr, SizeConst=128*3)] public string ShortCode; // the update code (for short update codes only) [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] public string UpdateCodeFile; // the output ducf that contains the update code [MarshalAs(UnmanagedType.ByValTStr, SizeConst=8)] public string ConfirmationCode; // the confirmation code } // ********************** API functions ************************ // we declare classes for all the API functions for each bitness // Loads DRPF from disk and returns handle class LoadDRPFFromFile32 { [DllImport("DinkeyRemote32.dll", CharSet = CharSet.Ansi)] public static extern IntPtr LoadDRPFFromFile(string drpf_file, out int err_code); } class LoadDRPFFromFile64 { [DllImport("DinkeyRemote64.dll", CharSet = CharSet.Ansi)] public static extern IntPtr LoadDRPFFromFile(string drpf_file, out int err_code); } // Loads DRPF from disk into structures supplied (so we can modify DRPF in memory) class ReadDRPFEx32 { [DllImport("DinkeyRemote32.dll", CharSet = CharSet.Ansi)] public static extern int ReadDRPFEx(string drpf_file, out REMOTEINFO RemoteInfo, byte[] licence_bytes, byte[] algchange_bytes, byte[] datachange_bytes, out int drpf_version, out int drpf_format); } class ReadDRPFEx64 { [DllImport("DinkeyRemote64.dll", CharSet = CharSet.Ansi)] public static extern int ReadDRPFEx(string drpf_file, out REMOTEINFO RemoteInfo, byte[] licence_bytes, byte[] algchange_bytes, byte[] datachange_bytes, out int drpf_version, out int drpf_format); } // Loads DRPF from structures and returns a handle class LoadDRPF32 { [DllImport("DinkeyRemote32.dll", CharSet = CharSet.Ansi)] public static extern IntPtr LoadDRPF(ref REMOTEINFO RemoteInfo, byte[] licence_bytes, byte[] algchange_bytes, byte[] datachange_bytes, out int ret_code); } class LoadDRPF64 { [DllImport("DinkeyRemote64.dll", CharSet = CharSet.Ansi)] public static extern IntPtr LoadDRPF(ref REMOTEINFO RemoteInfo, byte[] licence_bytes, byte[] algchange_bytes, byte[] datachange_bytes, out int ret_code); } // saves the DRPF file to disk class WriteDRPFEx32 { [DllImport("DinkeyRemote32.dll", CharSet = CharSet.Ansi)] public static extern int WriteDRPFEx(IntPtr drpf_handle, string drpf_file, int drpf_format, int drpf_version, int flags); } class WriteDRPFEx64 { [DllImport("DinkeyRemote64.dll", CharSet = CharSet.Ansi)] public static extern int WriteDRPFEx(IntPtr drpf_handle, string drpf_file, int drpf_format, int drpf_version, int flags); } // unloads the DRPF file class UnloadDRPF32 { [DllImport("DinkeyRemote32.dll", CharSet = CharSet.Ansi)] public static extern void UnloadDRPF(ref IntPtr drpf_handle); } class UnloadDRPF64 { [DllImport("DinkeyRemote64.dll", CharSet = CharSet.Ansi)] public static extern void UnloadDRPF(ref IntPtr drpf_handle); } class GenerateUpdateCode32 { [DllImport("DinkeyRemote32.dll", CharSet = CharSet.Ansi)] public static extern int GenerateUpdateCode(IntPtr drpf_handle, uint dongle_number, int update_number, string ducf_file, string logfile, out UPDATE_CODE_OUTPUTS Outputs); } class GenerateUpdateCode64 { [DllImport("DinkeyRemote64.dll", CharSet = CharSet.Ansi)] public static extern int GenerateUpdateCode(IntPtr drpf_handle, uint dongle_number, int update_number, string ducf_file, string logfile, out UPDATE_CODE_OUTPUTS Outputs); } class GetLastMessage32 { [DllImport("DinkeyRemote32.dll", CharSet = CharSet.Ansi)] public static extern void GetLastMessage(StringBuilder message, int buffer_size, out int message_length); } class GetLastMessage64 { [DllImport("DinkeyRemote64.dll", CharSet = CharSet.Ansi)] public static extern void GetLastMessage(StringBuilder message, int buffer_size, out int message_length); } class GetLastExtendedError32 { [DllImport("DinkeyRemote32.dll", CharSet = CharSet.Ansi)] public static extern int GetLastExtendedError(); } class GetLastExtendedError64 { [DllImport("DinkeyRemote64.dll", CharSet = CharSet.Ansi)] public static extern int GetLastExtendedError(); } // ********************* DinkeyRemote class ********************** class DinkeyRemote { // constants public const int DRPF_VERSION = 2; // current DRPF version // WriteDRPFEx API flags public const int FLAGS_LOSE_FEATURES = 1; // means that you can save the DRPF file to an earlier version even if it means losing some new features that have been currently set // constants for drpf_format in ReadDRPFEx and WriteDRPFEx functions public const int DRPF_FORMAT_BINARY = 1; public const int DRPF_FORMAT_JSON = 2; public const int DRPF_FORMAT_JSON_MIN = 3; // this value is only used with WriteDRPFEx. ReadDRPFEx cannot return this value. // private constants private const int MAX_LICENCES = 255; // max number of licence changes in a DRPF file (theoretically unlimited but easier if we limit it) private const int MAX_ALG_CHANGES = 21; // max number of alg changes in DRPF file private const int MAX_DATA_CHANGES = 127; // max number of data area changes in DRPF file // **** 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 public static IntPtr LoadDRPFFromFile(string drpf_file, out int err_code) { if (IntPtr.Size == 4) return LoadDRPFFromFile32.LoadDRPFFromFile(drpf_file, out err_code); return LoadDRPFFromFile64.LoadDRPFFromFile(drpf_file, out err_code); } // we have to do some marshalling of arrays of bytes into arrays of structures public static int ReadDRPFEx(string drpf_file, out REMOTEINFO RemoteInfo, out LICENCEINFO[] LicenceInfo, out ALGCHANGE[] AlgChanges, out DATACHANGE[] DataChanges, out int drpf_version, out int drpf_format) { int ret_code, i; byte[] licence_bytes = new byte[MAX_LICENCES * Marshal.SizeOf(typeof(LICENCEINFO))]; byte[] licence_bytes_one_struct = new byte[Marshal.SizeOf(typeof(LICENCEINFO))]; byte[] algchange_bytes = new byte[MAX_ALG_CHANGES * Marshal.SizeOf(typeof(ALGCHANGE))]; byte[] algchange_bytes_one_struct = new byte[Marshal.SizeOf(typeof(ALGCHANGE))]; byte[] datachange_bytes = new byte[MAX_DATA_CHANGES * Marshal.SizeOf(typeof(DATACHANGE))]; byte[] datachange_bytes_one_struct = new byte[Marshal.SizeOf(typeof(DATACHANGE))]; GCHandle MyGC; RemoteInfo = new REMOTEINFO(); LicenceInfo = null; AlgChanges = null; DataChanges = null; if (IntPtr.Size == 4) ret_code = ReadDRPFEx32.ReadDRPFEx(drpf_file, out RemoteInfo, licence_bytes, algchange_bytes, datachange_bytes, out drpf_version, out drpf_format); else ret_code = ReadDRPFEx64.ReadDRPFEx(drpf_file, out RemoteInfo, licence_bytes, algchange_bytes, datachange_bytes, out drpf_version, out drpf_format); if (ret_code != 0) return ret_code; // convert byte array to an array of structs LicenceInfo = new LICENCEINFO[RemoteInfo.NumLicences]; for (i=0; i