// !! this file should not be modified // DAPF file is in the following format: // DINKEYINFO // LICENCEINFO (however many are needed) // FILEINFO (however many are needed) // ALGORITHM (however many are needed) // DATAFILEENC (however many are needed) 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 // *********** define structures that make up the DAPF file ******************* [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi, Pack=1)] public struct DINKEYINFO { public byte Header1; // should be set to "DAPF" public byte Header2; public byte Header3; public byte Header4; public int Version; // version of this structure. Currently 9. public int SelectedModels; // BIT0 = Dinkey Pro Lite, BIT1 = Dinkey Pro Plus, BIT2 = Dinkey Pro Net etc... [MarshalAs(UnmanagedType.ByValTStr, SizeConst=12)] public string ProdCode; public int PerLicence; // 1 = per licence, 0 = per product (default) public int MaxNetUsers; // product net users, unlimited = -1, no entry = -2 public int RangeSettings; // 0 = any number, 1 = dongle in computer, 2 = range public uint RangeMin; public uint RangeMax; public int NumLicences; // number of LICENCEINFO structures in this DAPF file public int NumProgs; // number of FILEINFO structures in this DAPF file public int NumAlgs; public int DataSizeType; // 1 = set the zero data size, 0 = use file to initialise data area public int ZeroDataSize; // size of the data area area in bytes [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] public string DataFile; // path to data file (0 = no data file) public int DataAreaSize; // file size in bytes, -1 = file not found [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] public string ShellSuccessMsg; // Shell Method messages... [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] public string ShellNoDongleMsg; [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] public string ShellExpiryDateMsg; [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] public string ShellExpiryExecsMsg; [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] public string ShellWarnDateMsg; [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] public string ShellWarnExecsMsg; [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] public string ShellNetUserLimitMsg; [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] public string ShellOtherErrorMsg; [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] public string ShellBackgroundMsg; [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] public string NetNoServerMsg; [MarshalAs(UnmanagedType.ByValArray, SizeConst=12)] public byte[] rwalg; // coded form of rw algorithm (0 = no algorithm) public int SecOptions; // BIT0: DRIS encryption, BIT1: Data encryption, BIT2: Data enc with alg, BIT3: only secure update codes public byte SecDRISEncKey1; // DRIS encryption parameters public byte SecDRISEncKey2; public byte SecDRISEncKey3; public byte Ignored1; // this byte is ignored public byte SecDataEncKey1; // API Data encryption parameters public byte SecDataEncKey2; public byte SecDataEncKey3; public byte Ignored2; // this byte is ignored public int ProtectionType; // 0 = software + dongle, 1 = dongle only, 2 = program only [MarshalAs(UnmanagedType.ByValTStr, SizeConst=12)] public string DataEncKeyProdCode; // Alternative Product Code used to generate internal encryption keys. Normally set to 0. [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] public string Notes; // user-defined notes public int LockDongle; // 0 = don't lock (default), 1 = lock dongle to user's computer public int Reserved1; // must be 0 public int Reserved2; // must be 0 public int AdvancedOptions; // BIT0 = do not allow usb-over-network for non-Net dongles, BIT1 = do not check for Software Key at Runtime. public int NumDataFileEnc; // Number of data files in our encryption list } [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi, Pack=1)] public struct LICENCEINFO { [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] public string LicenceName; public int MaxDays; // -1 = no limit public int ExpiryDay; // -1 = no limit, 0 = no change public int ExpiryMonth; public int ExpiryYear; public int Execs; // -1 = no limit public int ExecsWarn; // 0 = no warning (just for Shell method) public int DaysWarn; // 0 = no warning (just for Shell method) public uint Features; public int LicenceNetUsers; // unlimited = -1 (-2 = not needed (this is for display only)) } [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi, Pack=1)] public struct FILEINFO { [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] public string InputName; // input file (full path) [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] public string OutputName; // output file/folder [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] public string CallingProg; // calling program name public int LicenceIndex; // index (of licence) in the LicenceInfo structure (1-based index. 0 = no selection) public int Method; // 0-api, 1-shell, 2-shell & api public int ShellFlags; // same bit flag values as in dris. i.e. 1 = DEC_ONE_EXEC, 4 = START_NET_USER public int BackGround; // 0=no background, 1=1min, 2=5min, 3=10min, 4=30min, 5=60min public int OtherShellOptions; // BIT0 = Shell Data Encryption is enabled, BIT1: Extra Anti-Debug is disabled, BIT2: Extra Anti-Piracy is disabled [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] public string EncFileList; // files (or file types) that the Shell-protected program will treat as encrypted (separated by ':') [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] public string ExceptList; // files (or file types) that are exceptions to the above list (separated by ':') public int ExtraAntiPiracy; // 0 = off, 1=min, 10=max } [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi, Pack=1)] public struct ALGORITHM { [MarshalAs(UnmanagedType.ByValArray, SizeConst=12)] public byte[] alg; } [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi, Pack=1)] public struct DATAFILEENC { [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] public string InputName; // file name, wild cards are allowed [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] public string OutputName; // file name (or folder name if input is a wildcard) } // this structure is used for creating temporary software keys [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi, Pack=1)] public struct TEMP_SWKEY_INFO { public int size; // size of this structure (must be initialised) public uint machineID; // machine ID in (hex) integer form public int expiry_day; // expiry date of the Software Key public int expiry_month; public int expiry_year; public int dongle_model; // model of the Software Key. See constant values below public uint dongle_number; // dongle number of the Software Key. 0 = default (random) } // this structure is used for creating demo software key templates [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi, Pack=1)] public struct DEMO_SWKEY_INFO { public int size; // size of this structure (must be initialised) public int max_days; // max days demo swkey installation is valid (0-60) public int models; // bitmap of valid dongle models. See constant values below. 0 = default (only use if only one model is selected in DINKEYINFO) } // ********************** API functions ************************ // we declare classes for all the API functions for each bitness // Loads DAPF from disk and returns handle class LoadDAPFFromFile32 { [DllImport("DinkeyAdd32.dll", CharSet = CharSet.Ansi)] public static extern IntPtr LoadDAPFFromFile(string dapf_file, out int err_code); } class LoadDAPFFromFile64 { [DllImport("DinkeyAdd64.dll", CharSet = CharSet.Ansi)] public static extern IntPtr LoadDAPFFromFile(string dapf_file, out int err_code); } // Loads DAPF from disk into structures supplied (so we can modify DAPF in memory) class ReadDAPFEx32 { [DllImport("DinkeyAdd32.dll", CharSet = CharSet.Ansi)] public static extern int ReadDAPFEx(string dapf_file, out DINKEYINFO DinkeyInfo, byte[] licence_bytes, byte[] fileinfo_bytes, byte[] alg_bytes, byte[] datafile_bytes, out int dapf_version, out int dapf_format); } class ReadDAPFEx64 { [DllImport("DinkeyAdd64.dll", CharSet = CharSet.Ansi)] public static extern int ReadDAPFEx(string dapf_file, out DINKEYINFO DinkeyInfo, byte[] licence_bytes, byte[] fileinfo_bytes, byte[] alg_bytes, byte[] datafile_bytes, out int dapf_version, out int dapf_format); } // Loads DAPF from structures and returns a handle class LoadDAPF32 { [DllImport("DinkeyAdd32.dll", CharSet = CharSet.Ansi)] public static extern IntPtr LoadDAPF(ref DINKEYINFO DinkeyInfo, byte[] licence_bytes, byte[] fileinfo_bytes, byte[] alg_bytes, byte[] datafile_bytes, out int ret_code); } class LoadDAPF64 { [DllImport("DinkeyAdd64.dll", CharSet = CharSet.Ansi)] public static extern IntPtr LoadDAPF(ref DINKEYINFO DinkeyInfo, byte[] licence_bytes, byte[] fileinfo_bytes, byte[] alg_bytes, byte[] datafile_bytes, out int ret_code); } // saves the DAPF file to disk class WriteDAPFEx32 { [DllImport("DinkeyAdd32.dll", CharSet = CharSet.Ansi)] public static extern int WriteDAPFEx(IntPtr dapf_handle, string dapf_file, int dapf_format, int dapf_version, int flags); } class WriteDAPFEx64 { [DllImport("DinkeyAdd64.dll", CharSet = CharSet.Ansi)] public static extern int WriteDAPFEx(IntPtr dapf_handle, string dapf_file, int dapf_format, int dapf_version, int flags); } // unloads the DAPF file class UnloadDAPF32 { [DllImport("DinkeyAdd32.dll", CharSet = CharSet.Ansi)] public static extern void UnloadDAPF(ref IntPtr dapf_handle); } class UnloadDAPF64 { [DllImport("DinkeyAdd64.dll", CharSet = CharSet.Ansi)] public static extern void UnloadDAPF(ref IntPtr dapf_handle); } class AddProtection32 { [DllImport("DinkeyAdd32.dll", CharSet = CharSet.Ansi)] public static extern int AddProtection(IntPtr dapf_handle, int action, int file_num, int flags, out uint dongle_number); } class AddProtection64 { [DllImport("DinkeyAdd64.dll", CharSet = CharSet.Ansi)] public static extern int AddProtection(IntPtr dapf_handle, int action, int file_num, int flags, out uint dongle_number); } class CreateTempSoftwareKey32 { [DllImport("DinkeyAdd32.dll", CharSet = CharSet.Ansi)] public static extern int CreateTempSoftwareKey(IntPtr dapf_handle, ref TEMP_SWKEY_INFO swkey_info, int flags); } class CreateTempSoftwareKey64 { [DllImport("DinkeyAdd64.dll", CharSet = CharSet.Ansi)] public static extern int CreateTempSoftwareKey(IntPtr dapf_handle, ref TEMP_SWKEY_INFO swkey_info, int flags); } class CreateDemoSoftwareKeyTemplate32 { [DllImport("DinkeyAdd32.dll", CharSet = CharSet.Ansi)] public static extern int CreateDemoSoftwareKeyTemplate(IntPtr dapf_handle, ref DEMO_SWKEY_INFO swkey_info, int flags); } class CreateDemoSoftwareKeyTemplate64 { [DllImport("DinkeyAdd64.dll", CharSet = CharSet.Ansi)] public static extern int CreateDemoSoftwareKeyTemplate(IntPtr dapf_handle, ref DEMO_SWKEY_INFO swkey_info, int flags); } class EncryptShellDataFiles32 { [DllImport("DinkeyAdd32.dll", CharSet = CharSet.Ansi)] public static extern int EncryptShellDataFiles(IntPtr dapf_handle, int file_num, int flags); } class EncryptShellDataFiles64 { [DllImport("DinkeyAdd64.dll", CharSet = CharSet.Ansi)] public static extern int EncryptShellDataFiles(IntPtr dapf_handle, int file_num, int flags); } class GetLastMessage32 { [DllImport("DinkeyAdd32.dll", CharSet = CharSet.Ansi)] public static extern void GetLastMessage(StringBuilder message, int buffer_size, out int message_length); } class GetLastMessage64 { [DllImport("DinkeyAdd64.dll", CharSet = CharSet.Ansi)] public static extern void GetLastMessage(StringBuilder message, int buffer_size, out int message_length); } class GetLastExtendedError32 { [DllImport("DinkeyAdd32.dll", CharSet = CharSet.Ansi)] public static extern int GetLastExtendedError(); } class GetLastExtendedError64 { [DllImport("DinkeyAdd64.dll", CharSet = CharSet.Ansi)] public static extern int GetLastExtendedError(); } // ********************* DinkeyAdd class ********************** class DinkeyAdd { // constants public const int DAPF_VERSION = 9; // current DAPF version // WriteDAPFEx API flags public const int FLAGS_LOSE_FEATURES = 1; // means that you can save the DAPF file to an earlier version even if it means losing some new features that have been currently set // AddProtection API action values public const int ACTION_USE_DAPF_SETTINGS = 0; // means you just ignore the action value and use the default dapf settings public const int ACTION_PROGRAM_DONGLE = 1; // program the dongle only public const int ACTION_PROTECT_SOFTWARE = 2; // protect a software file (index indicated by separate parameter) public const int ACTION_PROGRAM_AND_PROTECT = 3; // program the dongle and protect software // AddProtection API flags values public const int FLAGS_OVERWRITE_OUTPUT = 1; // overwrite the output file if it already exists (default is to give an error) // SoftwareKey API flags public const int FLAGS_OVERWRITE_SWKEY = 1; // overwrite an existing swkey with the new one public const int FLAGS_EXPIRY_DONTCARE = 2; // create the Software Key even though the expiry date (or max days) is less than the expiry date of the key itself. // constants for dapf_format in ReadDAPFEx and WriteDAPFEx functions public const int DAPF_FORMAT_BINARY = 1; public const int DAPF_FORMAT_JSON = 2; public const int DAPF_FORMAT_JSON_MIN = 3; // this value is only used with WriteDAPEx. ReadDAPFEx cannot return this value. // constants for values for model in the TEMP_SWKEY_INFO structure public const int SWKEY_MODEL_PRO_LITE = 0; public const int SWKEY_MODEL_PRO_PLUS = 1; public const int SWKEY_MODEL_PRO_NET = 2; public const int SWKEY_MODEL_FD_LITE = 3; public const int SWKEY_MODEL_FD_PLUS = 4; public const int SWKEY_MODEL_FD_NET = 5; // constants for models bitmap in the DEMO_SWKEY_INFO structure public const int SWKEY_BITMAP_DEFAULT = 0; // use default value set in DINKEYINFO.SelectedModels public const int SWKEY_BITMAP_PRO_LITE = 1; // BIT0 public const int SWKEY_BITMAP_PRO_PLUS = 2; // BIT1 public const int SWKEY_BITMAP_PRO_NET = 4; // BIT2 public const int SWKEY_BITMAP_FD_LITE = 8; // BIT3 public const int SWKEY_BITMAP_FD_PLUS = 16; // BIT4 public const int SWKEY_BITMAP_FD_NET = 32; // BIT5 // private constants private const int MAX_LICENCES = 255; // max number of licences in a DAPF file private const int MAX_FILE_INFO = 1000; // theoretically unlimited but in practice it is easier if we limit it private const int MAX_USER_ALGS = 20; // max number of user algs in DAPF file private const int MAX_DATA_ENCS = 255; // max number of Shell data encryption files in DAPF 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 LoadDAPFFromFile(string dapf_file, out int err_code) { if (IntPtr.Size == 4) return LoadDAPFFromFile32.LoadDAPFFromFile(dapf_file, out err_code); return LoadDAPFFromFile64.LoadDAPFFromFile(dapf_file, out err_code); } // we have to do some marshalling of arrays of bytes into arrays of structures public static int ReadDAPFEx(string dapf_file, out DINKEYINFO DinkeyInfo, out LICENCEINFO[] LicenceInfo, out FILEINFO[] FileInfo, out ALGORITHM[] Algorithms, out DATAFILEENC[] DataFileEnc, out int dapf_version, out int dapf_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[] fileinfo_bytes = new byte[MAX_FILE_INFO * Marshal.SizeOf(typeof(FILEINFO))]; byte[] fileinfo_bytes_one_struct = new byte[Marshal.SizeOf(typeof(FILEINFO))]; byte[] alg_bytes = new byte[MAX_USER_ALGS * Marshal.SizeOf(typeof(ALGORITHM))]; byte[] alg_bytes_one_struct = new byte[Marshal.SizeOf(typeof(ALGORITHM))]; byte[] datafile_bytes = new byte[MAX_DATA_ENCS * Marshal.SizeOf(typeof(DATAFILEENC))]; byte[] datafile_bytes_one_struct = new byte[Marshal.SizeOf(typeof(DATAFILEENC))]; GCHandle MyGC; DinkeyInfo = new DINKEYINFO(); LicenceInfo = null; FileInfo = null; Algorithms = null; DataFileEnc = null; if (IntPtr.Size == 4) ret_code = ReadDAPFEx32.ReadDAPFEx(dapf_file, out DinkeyInfo, licence_bytes, fileinfo_bytes, alg_bytes, datafile_bytes, out dapf_version, out dapf_format); else ret_code = ReadDAPFEx64.ReadDAPFEx(dapf_file, out DinkeyInfo, licence_bytes, fileinfo_bytes, alg_bytes, datafile_bytes, out dapf_version, out dapf_format); if (ret_code != 0) return ret_code; // convert byte array to an array of structs LicenceInfo = new LICENCEINFO[DinkeyInfo.NumLicences]; for (i=0; i