288 lines
12 KiB
C#
288 lines
12 KiB
C#
// !! this file should not be modified
|
|
|
|
using System;
|
|
using System.Runtime.InteropServices; // so we can marshal the DRIS as a block of memory
|
|
using System.Text; // so we can extract / set strings in the DRIS
|
|
using System.Windows.Forms; // for MessageBox
|
|
|
|
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi, Pack=1)]
|
|
public class DRIS
|
|
{
|
|
// the first 4 fields are never encrypted
|
|
public byte header1; // should be set to "DRIS"
|
|
public byte header2;
|
|
public byte header3;
|
|
public byte header4;
|
|
// inputs
|
|
public int size; // size of this structure
|
|
public int seed1; // seed for data/dris encryption
|
|
public int seed2; // as above
|
|
// (maybe encrypted from now on)
|
|
public int function; // specify only one function
|
|
public int flags; // options for the function selected. To use more than one OR them together: OPTION1 | OPTION2...
|
|
public uint execs_decrement; // amount by which to dec execs if we use flag: DEC_MANY_EXECS
|
|
public int data_crypt_key_num; // number of the key (1-3) that the dongle uses to encrypt or decrypt user data
|
|
public int rw_offset; // offset in the dongle data area to read or write data
|
|
public int rw_length; // length of data are to read/write/encrypt/decrypt
|
|
public IntPtr DoNotUse; // do not use the rw_data_ptr element use the "Data" argument of the DDProtCheck function
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst=256)] // NB access this field by using alg_licence_name (see below)
|
|
private byte[] _alt_licence_name = null; // protection check for different licence instead of this one
|
|
public int var_a; // variable values for user algorithm
|
|
public int var_b;
|
|
public int var_c;
|
|
public int var_d;
|
|
public int var_e;
|
|
public int var_f;
|
|
public int var_g;
|
|
public int var_h;
|
|
public int alg_number; // the number of the user algorithm that you want to execute
|
|
|
|
// outputs
|
|
public int ret_code; // return code from the protection check
|
|
public int ext_err; // extended error
|
|
public int type; // type of dongle detected. 1 = Pro, 2 = FD
|
|
public int model; // model of dongle detected. 1 = Lite, 2 = Plus, 4 = Net 5, 7 = Net Unlimited
|
|
public int sdsn; // Software Developer's Serial Number
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst=12)] // NB access this field by using prodcode (see below)
|
|
private byte[] _prodcode = null; // product code (null-terminated)
|
|
public uint dongle_number;
|
|
public int update_number;
|
|
public uint data_area_size; // size of the data area in the dongle detected
|
|
public int max_alg_num; // number of algorithms in the dongle detected
|
|
public int execs; // executions left: -1 indicates 'no limit'
|
|
public int exp_day; // expiry day: -1 indicates 'no limit'
|
|
public int exp_month; // expiry month: -1 indicates 'no limit'
|
|
public int exp_year; // expiry year: -1 indicates 'no limit'
|
|
public uint features; // features value
|
|
public int net_users; // maximum number of network users for the dongle detected: -1 indicates 'mo limit'
|
|
public int alg_answer; // answer to the user algorithm executed with the given variable values
|
|
public uint fd_capacity; // capacity of the data area in FD dongle. Currently fixed at ~10MB but may change in the future.
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst=128)] // NB access this field by using fd_drive (see below)
|
|
private byte[] _fd_drive = null; // fd drive letter (null-terminated)
|
|
public int swkey_type; // 0 = no swkey detected, 1 = temporary software key, 2 = demo software key
|
|
public int swkey_exp_day; // software key expiry date (if software key detected)
|
|
public int swkey_exp_month;
|
|
public int swkey_exp_year;
|
|
|
|
// NB we have to do it this way because we cannot encrypt strings correctly unless they are byte arrays
|
|
public string prodcode
|
|
{
|
|
get
|
|
{
|
|
StringBuilder sb = new StringBuilder(12);
|
|
foreach (byte b in _prodcode)
|
|
{
|
|
if (b == 0)
|
|
return sb.ToString();
|
|
else
|
|
sb.Append((char)b);
|
|
}
|
|
return sb.ToString();
|
|
}
|
|
}
|
|
|
|
public string fd_drive
|
|
{
|
|
get
|
|
{
|
|
StringBuilder sb = new StringBuilder(128);
|
|
foreach (byte b in _fd_drive)
|
|
{
|
|
if (b == 0)
|
|
return sb.ToString();
|
|
else
|
|
sb.Append((char)b);
|
|
}
|
|
return sb.ToString();
|
|
}
|
|
}
|
|
|
|
// NB we have to do it this way because we cannot encrypt strings correctly unless they are byte arrays
|
|
public string alt_licence_name
|
|
{
|
|
set
|
|
{
|
|
int i;
|
|
StringBuilder sb = new StringBuilder(value, 256);
|
|
for (i=0; i<sb.Length; i++)
|
|
{
|
|
_alt_licence_name[i] = (byte)sb[i];
|
|
}
|
|
_alt_licence_name[i] = 0; // null terminate
|
|
}
|
|
}
|
|
|
|
|
|
// sets 4 bytes from an integer at the specified offset in a data array
|
|
public void Set4Bytes(byte[] data, int offset, int value)
|
|
{
|
|
data[offset] = (byte)(value & 0xff);
|
|
data[offset+1] = (byte)((value >> 8) & 0xff);
|
|
data[offset+2] = (byte)((value >> 16) & 0xff);
|
|
data[offset+3] = (byte)((value >> 24) & 0xff);
|
|
return;
|
|
}
|
|
|
|
// converts to DRIS structure to a byte array (so we can do encryption)
|
|
public void DrisToByteArray(DRIS dris, byte[] data)
|
|
{
|
|
GCHandle MyGC = GCHandle.Alloc(data, GCHandleType.Pinned);
|
|
Marshal.StructureToPtr(dris, MyGC.AddrOfPinnedObject(), false);
|
|
MyGC.Free();
|
|
return;
|
|
}
|
|
|
|
// converts a byte array to the DRIS structure (so we can do encryption)
|
|
public void ByteArrayToDris(byte[] data, DRIS dris)
|
|
{
|
|
GCHandle MyGC = GCHandle.Alloc(data, GCHandleType.Pinned);
|
|
Marshal.PtrToStructure(MyGC.AddrOfPinnedObject(), dris);
|
|
MyGC.Free();
|
|
return;
|
|
}
|
|
|
|
// to make a new instance of this class, initialise every element to a random value and then set the header
|
|
public DRIS()
|
|
{
|
|
Random rnd = new Random();
|
|
Byte[] temp = new Byte[Marshal.SizeOf(this)];
|
|
rnd.NextBytes(temp);
|
|
ByteArrayToDris(temp, this);
|
|
this.header1 = (byte)'D';
|
|
this.header2 = (byte)'R';
|
|
this.header3 = (byte)'I';
|
|
this.header4 = (byte)'S';
|
|
}
|
|
|
|
// functions - must specify only one
|
|
public const int PROTECTION_CHECK = 1; // checks for dongle, check program params...
|
|
public const int EXECUTE_ALGORITHM = 2; // protection check + calculate answer for specified algorithm with specified inputs
|
|
public const int WRITE_DATA_AREA = 3; // protection check + writes dongle data area
|
|
public const int READ_DATA_AREA = 4; // protection check + reads dongle data area
|
|
public const int ENCRYPT_USER_DATA = 5; // protection check + the dongle will encrypt user data
|
|
public const int DECRYPT_USER_DATA = 6; // protection check + the dongle will decrypt user data
|
|
public const int FAST_PRESENCE_CHECK = 7; // checks for the presence of the correct dongle only with minimal security, no flags allowed.
|
|
public const int STOP_NET_USER = 8; // stops a network user (a protection check is NOT performed)
|
|
|
|
// flags - can specify as many as you like
|
|
public const int DEC_ONE_EXEC = 1; // decrement execs by 1
|
|
public const int DEC_MANY_EXECS = 2; // decrement execs by number specified in execs_decrement
|
|
public const int START_NET_USER = 4; // starts a network user
|
|
public const int USE_FUNCTION_ARGUMENT = 16; // use the extra argument in the function for pointers
|
|
public const int CHECK_LOCAL_FIRST = 32; // always look in local ports before looking in network ports
|
|
public const int CHECK_NETWORK_FIRST = 64; // always look on the network before looking in local ports
|
|
public const int USE_ALT_LICENCE_NAME = 128; // use name specified in alt_licence_name instead of the default one
|
|
public const int DONT_SET_MAXDAYS_EXPIRY = 256; // if the max days expiry date has not been calculated then do not do it this time
|
|
public const int MATCH_DONGLE_NUMBER = 512; // restrict the search to match the dongle number specified in the DRIS
|
|
public const int DONT_RETURN_FD_DRIVE = 1024; // if an FD dongle has been detected then don't return the flash drive/mount name in the DRIS
|
|
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi, Pack=1)]
|
|
public struct NU_INFO
|
|
{
|
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)]
|
|
public string licenceName;
|
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=50)]
|
|
public string userName;
|
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)]
|
|
public string computerName;
|
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=16)]
|
|
public string ipAddress;
|
|
}
|
|
|
|
// 32-bit protection check (loads 32-bit DLL)
|
|
class DDProtCheck32
|
|
{
|
|
[DllImport("dpwin32.dll", CharSet = CharSet.Ansi)]
|
|
public static extern int DDProtCheck([In, Out, MarshalAs(UnmanagedType.LPStruct)]DRIS dris, byte[] data);
|
|
}
|
|
|
|
// 64-bit protection check (loads 64-bit DLL)
|
|
class DDProtCheck64
|
|
{
|
|
[DllImport("dpwin64.dll", CharSet = CharSet.Ansi)]
|
|
public static extern int DDProtCheck([In, Out, MarshalAs(UnmanagedType.LPStruct)]DRIS dris, byte[] data);
|
|
}
|
|
|
|
// 32-bit get network user info (loads 32-bit DLL)
|
|
class DDGetNetUserList32
|
|
{
|
|
[DllImport("dpwin32.dll", CharSet = CharSet.Ansi)]
|
|
public static extern int DDGetNetUserList(string licence_name, out int num_net_users, byte[] nu_info_bytes, int num_info_structs, out int extended_error);
|
|
}
|
|
|
|
// 64-bit get network user info (loads 64-bit DLL)
|
|
class DDGetNetUserList64
|
|
{
|
|
[DllImport("dpwin64.dll", CharSet = CharSet.Ansi)]
|
|
public static extern int DDGetNetUserList(string licence_name, out int num_net_users, byte[] nu_info_bytes, int num_info_structs, out int extended_error);
|
|
}
|
|
|
|
// call our API - we only want to load the correct DLL for the bit-ness of the computer. The other DLL may not exist.
|
|
class DinkeyPro
|
|
{
|
|
// calls the DDProtCheck function in the appropriate DLL
|
|
public static int DDProtCheck(DRIS dris, byte[] data)
|
|
{
|
|
int ret_code = -1;
|
|
|
|
if (IntPtr.Size == 4)
|
|
{
|
|
try
|
|
{
|
|
ret_code = DDProtCheck32.DDProtCheck(dris, data);
|
|
}
|
|
catch (DllNotFoundException)
|
|
{
|
|
MessageBox.Show("Error! Cannot find dpwin32.dll. This should be in the same folder as DllTest.", "Sample", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
|
|
}
|
|
}
|
|
else {
|
|
try
|
|
{
|
|
ret_code = DDProtCheck64.DDProtCheck(dris, data);
|
|
}
|
|
catch (DllNotFoundException)
|
|
{
|
|
MessageBox.Show("Error! Cannot find dpwin64.dll. This should be in the same folder as DllTest.", "Sample", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
|
|
}
|
|
}
|
|
return ret_code;
|
|
}
|
|
|
|
public static int DDGetNetUserList(string licence_name, out int num_net_users, out NU_INFO[] nu_info, int num_info_structs, out int extended_error)
|
|
{
|
|
int ret_code = -1;
|
|
int i;
|
|
extended_error = num_net_users = 0;
|
|
byte[] nu_info_bytes = new byte[num_info_structs * Marshal.SizeOf(typeof(NU_INFO))];
|
|
byte[] nu_info_one_struct = new byte[Marshal.SizeOf(typeof(NU_INFO))];
|
|
GCHandle MyGC;
|
|
nu_info = null;
|
|
|
|
// call the function and get info as a byte array
|
|
if (IntPtr.Size == 4)
|
|
ret_code = DDGetNetUserList32.DDGetNetUserList(licence_name, out num_net_users, nu_info_bytes, num_info_structs, out extended_error);
|
|
else
|
|
ret_code = DDGetNetUserList64.DDGetNetUserList(licence_name, out num_net_users, nu_info_bytes, num_info_structs, out extended_error);
|
|
|
|
if (ret_code != 0)
|
|
return ret_code;
|
|
|
|
// convert byte array to an array of structs
|
|
nu_info = new NU_INFO[num_net_users];
|
|
for (i=0; i<num_net_users; i++)
|
|
{
|
|
Array.Copy(nu_info_bytes, i*Marshal.SizeOf(typeof(NU_INFO)), nu_info_one_struct, 0, Marshal.SizeOf(typeof(NU_INFO)));
|
|
MyGC = GCHandle.Alloc(nu_info_one_struct, GCHandleType.Pinned);
|
|
nu_info[i] = (NU_INFO)Marshal.PtrToStructure(MyGC.AddrOfPinnedObject(), typeof(NU_INFO));
|
|
MyGC.Free();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
|