Add Original SDK

This commit is contained in:
2026-05-06 07:47:36 +02:00
parent 2915e04380
commit 0ed627517a
674 changed files with 89334 additions and 0 deletions

View File

@@ -0,0 +1,31 @@
Imports System.Reflection
Imports System.Runtime.InteropServices
' General Information about an assembly is controlled through the following
' set of attributes. Change these attribute values to modify the information
' associated with an assembly.
' Review the values of the assembly attributes
<Assembly: AssemblyTitle("")>
<Assembly: AssemblyDescription("")>
<Assembly: AssemblyCompany("")>
<Assembly: AssemblyProduct("")>
<Assembly: AssemblyCopyright("")>
<Assembly: AssemblyTrademark("")>
<Assembly: CLSCompliant(True)>
'The following GUID is for the ID of the typelib if this project is exposed to COM
<Assembly: Guid("0D48F329-866C-4C45-AC60-38C686817356")>
' Version information for an assembly consists of the following four values:
'
' Major Version
' Minor Version
' Build Number
' Revision
'
' You can specify all the values or you can default the Build and Revision Numbers
' by using the '*' as shown below:
<Assembly: AssemblyVersion("1.0.*")>

View File

@@ -0,0 +1,21 @@
Microsoft Visual Studio Solution File, Format Version 7.00
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "DllTest", "DllTest.vbproj", "{7C92E3C8-2E6D-4347-B8B3-579231D8E24D}"
EndProject
Global
GlobalSection(SolutionConfiguration) = preSolution
ConfigName.0 = Debug
ConfigName.1 = Release
EndGlobalSection
GlobalSection(ProjectDependencies) = postSolution
EndGlobalSection
GlobalSection(ProjectConfiguration) = postSolution
{7C92E3C8-2E6D-4347-B8B3-579231D8E24D}.Debug.ActiveCfg = Debug|.NET
{7C92E3C8-2E6D-4347-B8B3-579231D8E24D}.Debug.Build.0 = Debug|.NET
{7C92E3C8-2E6D-4347-B8B3-579231D8E24D}.Release.ActiveCfg = Release|.NET
{7C92E3C8-2E6D-4347-B8B3-579231D8E24D}.Release.Build.0 = Release|.NET
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection
GlobalSection(ExtensibilityAddIns) = postSolution
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,121 @@
<VisualStudioProject>
<VisualBasic
ProjectType = "Local"
ProductVersion = "7.0.9466"
SchemaVersion = "1.0"
ProjectGuid = "{7C92E3C8-2E6D-4347-B8B3-579231D8E24D}"
>
<Build>
<Settings
ApplicationIcon = ""
AssemblyKeyContainerName = ""
AssemblyName = "DllTest"
AssemblyOriginatorKeyFile = ""
AssemblyOriginatorKeyMode = "None"
DefaultClientScript = "JScript"
DefaultHTMLPageLayout = "Grid"
DefaultTargetSchema = "IE50"
DelaySign = "false"
OutputType = "WinExe"
OptionCompare = "Binary"
OptionExplicit = "On"
OptionStrict = "Off"
RootNamespace = "DllTest"
StartupObject = "DllTest.Form1"
>
<Config
Name = "Debug"
BaseAddress = "285212672"
ConfigurationOverrideFile = ""
DefineConstants = ""
DefineDebug = "true"
DefineTrace = "true"
DebugSymbols = "true"
IncrementalBuild = "true"
Optimize = "false"
OutputPath = "bin\"
RegisterForComInterop = "false"
RemoveIntegerChecks = "false"
TreatWarningsAsErrors = "false"
WarningLevel = "1"
/>
<Config
Name = "Release"
BaseAddress = "285212672"
ConfigurationOverrideFile = ""
DefineConstants = ""
DefineDebug = "false"
DefineTrace = "true"
DebugSymbols = "false"
IncrementalBuild = "false"
Optimize = "true"
OutputPath = "bin\"
RegisterForComInterop = "false"
RemoveIntegerChecks = "false"
TreatWarningsAsErrors = "false"
WarningLevel = "1"
/>
</Settings>
<References>
<Reference
Name = "System"
AssemblyName = "System"
/>
<Reference
Name = "System.Data"
AssemblyName = "System.Data"
/>
<Reference
Name = "System.Drawing"
AssemblyName = "System.Drawing"
/>
<Reference
Name = "System.Windows.Forms"
AssemblyName = "System.Windows.Forms"
/>
<Reference
Name = "System.XML"
AssemblyName = "System.Xml"
/>
</References>
<Imports>
<Import Namespace = "Microsoft.VisualBasic" />
<Import Namespace = "System" />
<Import Namespace = "System.Collections" />
<Import Namespace = "System.Data" />
<Import Namespace = "System.Drawing" />
<Import Namespace = "System.Diagnostics" />
<Import Namespace = "System.Windows.Forms" />
</Imports>
</Build>
<Files>
<Include>
<File
RelPath = "AssemblyInfo.vb"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "dris.vb"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Form1.vb"
SubType = "Form"
BuildAction = "Compile"
/>
<File
RelPath = "Form1.resx"
DependentUpon = "Form1.vb"
BuildAction = "EmbeddedResource"
/>
<File
RelPath = "readme.txt"
BuildAction = "Content"
/>
</Include>
</Files>
</VisualBasic>
</VisualStudioProject>

View File

@@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 1.3
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">1.3</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1">this is my long string</data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
[base64 mime encoded serialized .NET Framework object]
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
[base64 mime encoded string representing a byte array form of the .NET Framework object]
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Label1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Assembly</value>
</data>
<data name="$this.Name">
<value>Form1</value>
</data>
</root>

View File

@@ -0,0 +1,988 @@
' !! 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
Imports System.Runtime.InteropServices
Public Class Form1
Inherits System.Windows.Forms.Form
#Region " Windows Form Designer generated code "
Public Sub New()
MyBase.New()
'This call is required by the Windows Form Designer.
InitializeComponent()
'Add any initialization after the InitializeComponent() call
End Sub
'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents Label1 As System.Windows.Forms.Label
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
Me.Label1 = New System.Windows.Forms.Label()
Me.SuspendLayout()
'
'Label1
'
Me.Label1.Font = New System.Drawing.Font("Microsoft Sans Serif", 24.0!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
Me.Label1.Location = New System.Drawing.Point(72, 80)
Me.Label1.Name = "Label1"
Me.Label1.Size = New System.Drawing.Size(168, 40)
Me.Label1.TabIndex = 0
Me.Label1.Text = "It Worked!"
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(304, 213)
Me.Controls.AddRange(New System.Windows.Forms.Control() {Me.Label1})
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
End Sub
#End Region
' The sample code contains 11 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. You should
' implement the protection in a stronger way using the techniques described in
' the "Increasing your Protection" chapter of the manual.
'
' The 11 functions are:
' ProtCheck a standard protection check
' ProtCheckWithAlg a protection check & executing an Algorithm
' WriteBytes a protection check & write data to the dongle
' ReadBytes a protection check & read data from the dongle
' EncryptUserData a protection check,& encrypting data and then decrypting the data
'
' these functions are the same as the functions listed above but encrypting all parameters passed to our API
' ProtCheckEnc a standard protection check
' ProtCheckWithAlgEnc a protection check & executing an Algorithm
' WriteBytesEnc a protection check & write data to the dongle
' ReadBytesEnc a protection check & read data from the dongle
' EncryptUserDataEnc a protection check & encrypting data and then decrypting the data
' this function displays the current network users
' DisplayNetUsers
' !!!!
Public Const MY_SDSN As Integer = 10101 ' !!!! change this value to be the value of your SDSN (demo = 10101)
Public Const MY_PRODCODE As String = "DEMO" ' !!!! change this value to match the Product Code in the dongle
' If you are using Dinkey Lite then you can only use 4 functions:
' ProtCheck, ProtCheckWithAlg, ProtCheckEnc, ProtCheckWithAlgEnc
Private Sub Form1_Load(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles MyBase.Load
' call the function(s) of your choice here
' here I have chosen a standard protection check
If ProtCheck() <> 0 Then
End 'terminate
End If
End Sub
' ************************* our 10 functions **********************************
' ************************** ProtCheck ***************************************
Function ProtCheck() As Integer
Dim dris As DRIS = New DRIS
Dim ret_code As Integer
On Error GoTo Protection_Err
' set the DRIS to have random values
Call RandomSet(dris)
' then set the values we want to use
dris.header1 = Asc("D")
dris.header2 = Asc("R")
dris.header3 = Asc("I")
dris.header4 = Asc("S")
dris.size = Marshal.SizeOf(dris)
dris.myfunction = PROTECTION_CHECK ' standard protection check
dris.flags = 0 ' no extra flags, but you may want to specify some if you want to start a network user or decrement execs,...
ret_code = DDProtCheck(dris, Nothing)
If (ret_code <> 0) Then
Call DisplayError(ret_code, dris.ext_err)
ProtCheck = ret_code
Exit Function
End If
' later in your code you can check other values in the DRIS...
If (dris.sdsn <> MY_SDSN) Then
MsgBox("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.", MsgBoxStyle.OkOnly, "Error")
ProtCheck = -1
Exit Function
End If
If (GetProductCode(dris) <> MY_PRODCODE) Then
MsgBox("Incorrect Product Code! Please modify your source code so that MY_PRODCODE is set to be the Product Code in the dongle.", MsgBoxStyle.OkOnly, "Error")
ProtCheck = -1
Exit Function
End If
' later on in your program you can check the return code again
If (dris.ret_code <> 0) Then
MsgBox("Dinkey Dongle protection error", MsgBoxStyle.OkOnly, "Error")
ProtCheck = -1
Exit Function
End If
' NB if you are using a network dongle and you want to list the network users then use this function:
' DisplayNetUsers(dris.net_users, dris.model)
ProtCheck = 0
Exit Function
Protection_Err: ' see readme.txt for explanation of this exception handler
Protection_Exception()
ProtCheck = -1
End Function
' ************************** ProtCheckWithAlg ******************************
' !!!! You should replace this function with the one generated by the
' "generate source code" button in Algorithm tab for DinkeyAdd (if you have specified an algorithm)
' or from DinkeyLook if you are using Dinkey Lite dongles.
' see readme.txt notes concerning using the algorithm in vb.net
Private Function MyAlgorithm(ByVal a As Integer, ByVal b As Integer, ByVal c As Integer, ByVal d As Integer, ByVal e As Integer, ByVal f As Integer, ByVal g As Integer, ByVal h As Integer) As Integer
MyAlgorithm = a + b + c + d + e + f + g + h
End Function
' NB for this to work you must program at least "user algorithm" into the dongle
' NB We have used a very simple algorithm here (in the MyAlgorithm function). You must patch this with the
' sample code generated by DinkeyAdd for the algorithm that you are using.
Function ProtCheckWithAlg() As Integer
Dim dris As DRIS = New DRIS
Dim ret_code As Integer
On Error GoTo Protection_Err
' set the DRIS to have random values
Call RandomSet(dris)
' then set the values we want to use
dris.header1 = Asc("D")
dris.header2 = Asc("R")
dris.header3 = Asc("I")
dris.header4 = Asc("S")
dris.size = Marshal.SizeOf(dris)
dris.myfunction = EXECUTE_ALGORITHM ' standard protection check & execute algorithm
dris.flags = 0 ' no extra flags, but you may want to specify some if you want to start a network user or decrement execs,...
dris.alg_number = 1 ' execute first algorithm (you do not need to specify this field for Dinkey Lite dongles)
' you should remove these entries if you are using Dinkey Lite so that algorithm arguments are random
dris.var_a = 1 ' sample values
dris.var_b = 2
dris.var_c = 3
dris.var_d = 4
dris.var_e = 5
dris.var_f = 6
dris.var_g = 7
dris.var_h = 8
ret_code = DDProtCheck(dris, Nothing)
If (ret_code <> 0) Then
Call DisplayError(ret_code, dris.ext_err)
ProtCheckWithAlg = ret_code
Exit Function
End If
' later in your code you can check other values in the DRIS...
If (dris.sdsn <> MY_SDSN) Then
MsgBox("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.", MsgBoxStyle.OkOnly, "Error")
ProtCheckWithAlg = -1
Exit Function
End If
' later on in your program you can check the return code again
If (dris.ret_code <> 0) Then
MsgBox("Dinkey Dongle protection error", MsgBoxStyle.OkOnly, "Error")
ProtCheckWithAlg = -1
Exit Function
End If
' if you want you can check the algorithm answer - however if algorithm is from your code then best to just use the answer in your code
' NB read the note in the "readme.txt" about possible overflow errors in VB.NET
' !!!! Make sure you have replaced the MyAlgorithm routine with the algorithm you have specified in DinkeyAdd
If (MyAlgorithm(dris.var_a, dris.var_b, dris.var_c, dris.var_d, dris.var_e, dris.var_f, dris.var_g, dris.var_h) <> dris.alg_answer) Then
MsgBox("Dinkey protection error!\nYou have not patched your algorithm in the MyAlgorithm routine", MsgBoxStyle.OkOnly, "Error")
ProtCheckWithAlg = -1
Exit Function
End If
ProtCheckWithAlg = 0
Exit Function
Protection_Err: ' see readme.txt for explanation of this exception handler
Protection_Exception()
ProtCheckWithAlg = -1
End Function
' ************************** WriteBytes ******************************
' This writes the data array 0,1,2,3,4,5,6,7,8,9 to the dongle data area at offset 7
' In order for this function to work you will need to have a data area in your dongle that is at least 18 bytes long.
' if you want to write a string then you need to convert it to a byte array first:
' encoding.GetBytes(your_string, 0, your_string.Length, data, 0) where encoding is declared: Dim encoding As New ASCIIEncoding() You also need to include System.Text
Function WriteBytes() As Integer
Dim dris As DRIS = New DRIS
Dim ret_code As Integer
Dim data() As Byte = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
On Error GoTo Protection_Err
' set the DRIS to have random values
Call RandomSet(dris)
' then set the values we want to use
dris.header1 = Asc("D")
dris.header2 = Asc("R")
dris.header3 = Asc("I")
dris.header4 = Asc("S")
dris.size = Marshal.SizeOf(dris)
dris.myfunction = WRITE_DATA_AREA ' standard protection check & write data
dris.flags = USE_FUNCTION_ARGUMENT ' you have to do it this way in vb.net
dris.rw_offset = 7
dris.rw_length = data.Length
ret_code = DDProtCheck(dris, data)
If (ret_code <> 0) Then
Call DisplayError(ret_code, dris.ext_err)
WriteBytes = ret_code
Exit Function
End If
' later in your code you can check other values in the DRIS...
If (dris.sdsn <> MY_SDSN) Then
MsgBox("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.", MsgBoxStyle.OkOnly, "Error")
WriteBytes = -1
Exit Function
End If
' later on in your program you can check the return code again
If (dris.ret_code <> 0) Then
MsgBox("Dinkey Dongle protection error", MsgBoxStyle.OkOnly, "Error")
WriteBytes = -1
Exit Function
End If
WriteBytes = 0
Exit Function
Protection_Err: ' see readme.txt for explanation of this exception handler
Protection_Exception()
WriteBytes = -1
End Function
' ************************ ReadBytes ************************************
' This reads 10 bytes of data from offset 7 in the dongle data area
' In order for this function to work you will need to have a data area in your dongle that is at least 18 bytes long.
' if you want to read a string then you need to convert it from a byte array (via an array of char). You also need to include System.Text
' CharArray = encoding.GetChars(data); where CharArray is of type char[] and encoding is of type ASCIIEncoding
' your_string = new String(CharArray, 0, your_string_length);
Function ReadBytes() As Integer
Dim dris As DRIS = New DRIS
Dim ret_code As Integer
Dim data(10) As Byte
On Error GoTo Protection_Err
' set the DRIS to have random values
Call RandomSet(dris)
' then set the values we want to use
dris.header1 = Asc("D")
dris.header2 = Asc("R")
dris.header3 = Asc("I")
dris.header4 = Asc("S")
dris.size = Marshal.SizeOf(dris)
dris.myfunction = READ_DATA_AREA ' standard protection check & read data
dris.flags = USE_FUNCTION_ARGUMENT ' you have to do it this way in vb.net
dris.rw_offset = 7
dris.rw_length = data.Length
ret_code = DDProtCheck(dris, data)
If (ret_code <> 0) Then
Call DisplayError(ret_code, dris.ext_err)
ReadBytes = ret_code
Exit Function
End If
' later in your code you can check other values in the DRIS...
If (dris.sdsn <> MY_SDSN) Then
MsgBox("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.", MsgBoxStyle.OkOnly, "Error")
ReadBytes = -1
Exit Function
End If
' later on in your program you can check the return code again
If (dris.ret_code <> 0) Then
MsgBox("Dinkey Dongle protection error", MsgBoxStyle.OkOnly, "Error")
ReadBytes = -1
Exit Function
End If
MsgBox("Dinkey Dongle Data Area, offset 7 is : " + Str(data(0)) + "," + Str(data(1)) + "," + Str(data(2)) + "," + Str(data(3)) + "," + _
Str(data(4)) + "," + Str(data(5)) + "," + Str(data(6)) + "," + Str(data(7)) + "," + Str(data(8)) + "," + Str(data(9)), MsgBoxStyle.OkOnly)
ReadBytes = 0
Exit Function
Protection_Err: ' see readme.txt for explanation of this exception handler
Protection_Exception()
ReadBytes = -1
End Function
' ************************** EncryptUserData ************************************
' This function will do a protection check and ask the dongle to encrypt some data using encryption key 1
' It will then do another protection check & decrypt the data
' to encrypt or decrypt strings please read notes for WriteBytes and ReadBytes functions
Function EncryptUserData() As Integer
Dim dris As DRIS = New DRIS
Dim ret_code As Integer
Dim data() As Byte = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
On Error GoTo Protection_Err
' set the DRIS to have random values
Call RandomSet(dris)
' then set the values we want to use
dris.header1 = Asc("D")
dris.header2 = Asc("R")
dris.header3 = Asc("I")
dris.header4 = Asc("S")
dris.size = Marshal.SizeOf(dris)
dris.myfunction = ENCRYPT_USER_DATA ' standard protection check & encrypt data
dris.flags = USE_FUNCTION_ARGUMENT ' you have to do it this way in vb.net
dris.rw_length = data.Length
dris.data_crypt_key_num = 1
ret_code = DDProtCheck(dris, data)
If (ret_code <> 0) Then
Call DisplayError(ret_code, dris.ext_err)
EncryptUserData = ret_code
Exit Function
End If
' ... could add code to check other elements of the DRIS, e.g. ret_code, sdsn, ...
' Now decrypt the same data to get the original values
Call RandomSet(dris)
' then set the values we want to use
dris.header1 = Asc("D")
dris.header2 = Asc("R")
dris.header3 = Asc("I")
dris.header4 = Asc("S")
dris.size = Marshal.SizeOf(dris)
dris.myfunction = DECRYPT_USER_DATA ' standard protection check & decrypt data
dris.flags = USE_FUNCTION_ARGUMENT ' you have to do it this way in vb.net
dris.rw_length = data.Length
dris.data_crypt_key_num = 1
ret_code = DDProtCheck(dris, data)
If (ret_code <> 0) Then
Call DisplayError(ret_code, dris.ext_err)
EncryptUserData = ret_code
Exit Function
End If
' later in your code you can check other values in the DRIS...
If (dris.sdsn <> MY_SDSN) Then
MsgBox("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.", MsgBoxStyle.OkOnly, "Error")
EncryptUserData = -1
Exit Function
End If
' later on in your program you can check the return code again
If (dris.ret_code <> 0) Then
MsgBox("Dinkey Dongle protection error", MsgBoxStyle.OkOnly, "Error")
EncryptUserData = -1
Exit Function
End If
MsgBox("Decrypted data is : " + Str(data(0)) + "," + Str(data(1)) + "," + Str(data(2)) + "," + Str(data(3)) + "," + _
Str(data(4)) + "," + Str(data(5)) + "," + Str(data(6)) + "," + Str(data(7)) + "," + Str(data(8)) + "," + Str(data(9)), MsgBoxStyle.OkOnly)
EncryptUserData = 0
Exit Function
Protection_Err: ' see readme.txt for explanation of this exception handler
Protection_Exception()
EncryptUserData = -1
End Function
' !!!!!!!!!!! all the functions listed below encrypt all parameters to our API !!!!!!!!!!!!!!!!!!!!!
' In order for them to work properly you need to choose "Encrypt DRIS" and "Encrypt Data passed to API"
' in the Extra Security tab of DinkeyAdd. In this example, for Data Encryption I use the r/w algorithm
' but the code can be modified easily to use the 3 encryption parameters.
' !!!! please overwrite this function with the one generated by DinkeyAdd for R/W Algorithm
Private Function MyRWAlgorithm(ByVal a As Integer, ByVal b As Integer, ByVal c As Integer, ByVal d As Integer, ByVal e As Integer, ByVal f As Integer, ByVal g As Integer, ByVal h As Integer) As Integer
MyRWAlgorithm = a Xor b Xor c Xor d Xor e Xor f
MyRWAlgorithm = MyRWAlgorithm And &HFFFFFF ' we only use bottom 3 bytes. -ve numbers can cause problems for CryptApiData
End Function
' !!!! please overwrite this function with the one generated by DinkeyAdd
Private Sub CryptDRIS(ByRef dris As DRIS)
Dim i, j, k, t As Integer
Dim bigseed(255) As Byte
Dim S(255) As Byte
Dim temp As Byte
Dim temp_dris(Marshal.SizeOf(dris) - 1) As Byte
DrisToByteArray(dris, temp_dris) ' convert DRIS to byte array so we can encrypt it
For i = 0 To 255 Step 8
Call Set4Bytes(bigseed, i, dris.seed1)
Call Set4Bytes(bigseed, i + 4, dris.seed2)
Next
For i = 0 To 255
S(i) = i
Next
j = 0
For i = 0 To 255
j = (j + CInt(S(i)) + CInt(bigseed(i)) + 123) Mod 256
temp = S(i)
S(i) = S(j)
S(j) = temp
Next
i = 0
j = 0
For k = 16 To Marshal.SizeOf(dris) - 1
i = (i + 1) Mod 256
j = (j + CInt(S(i)) + 212) Mod 256
temp = S(i)
S(i) = S(j)
S(j) = temp
t = (CInt(S(i)) + CInt(S(j)) + 97) Mod 256
temp_dris(k) = temp_dris(k) Xor S(t)
Next
ByteArrayToDris(temp_dris, dris) ' convert it back again
End Sub
' !!!! please overwrite this function with the one generated by DinkeyAdd
Private Sub CryptApiData(ByVal dris As DRIS, ByVal data() As Byte, ByVal length As Integer, ByVal alg_answer As Integer)
Dim i, j, k, t As Integer
Dim bigseed(255) As Byte
Dim S(255) As Byte
Dim temp As Byte
For i = 0 To 255 Step 8
Call Set4Bytes(bigseed, i, dris.seed1)
Call Set4Bytes(bigseed, i + 4, dris.seed2)
Next
For i = 0 To 255
S(i) = i
Next
j = 0
For i = 0 To 255
j = (j + CInt(S(i)) + CInt(bigseed(i)) + (alg_answer And &HFF)) Mod 256
temp = S(i)
S(i) = S(j)
S(j) = temp
Next
i = 0
j = 0
For k = 0 To length - 1
i = (i + 1) Mod 256
j = (j + CInt(S(i)) + ((alg_answer \ &H100) And &HFF)) Mod 256
temp = S(i)
S(i) = S(j)
S(j) = temp
t = (CInt(S(i)) + CInt(S(j)) + ((alg_answer \ &H10000) And &HFF)) Mod 256
data(k) = data(k) Xor S(t)
Next
End Sub
' ************************** ProtCheckEnc ************************************
' We encrypt the DRIS passed to the API. Patch the CryptDRIS function in this file from source code generated by DinkeyAdd.
Function ProtCheckEnc() As Integer
Dim dris As DRIS = New DRIS
Dim ret_code As Integer
On Error GoTo Protection_Err
' set the DRIS to have random values
Call RandomSet(dris)
' then set the values we want to use
dris.header1 = Asc("D")
dris.header2 = Asc("R")
dris.header3 = Asc("I")
dris.header4 = Asc("S")
dris.size = Marshal.SizeOf(dris)
dris.myfunction = PROTECTION_CHECK ' standard protection check
dris.flags = 0 ' no extra flags, but you may want to specify some if you want to start a network user or decrement execs,...
Call CryptDRIS(dris) ' encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
ret_code = DDProtCheck(dris, Nothing)
Call CryptDRIS(dris) ' decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
If (ret_code <> 0) Then
Call DisplayError(ret_code, dris.ext_err)
ProtCheckEnc = ret_code
Exit Function
End If
' later in your code you can check other values in the DRIS...
If (dris.sdsn <> MY_SDSN) Then
MsgBox("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.", MsgBoxStyle.OkOnly, "Error")
ProtCheckEnc = -1
Exit Function
End If
If (GetProductCode(dris) <> MY_PRODCODE) Then
MsgBox("Incorrect Product Code! Please modify your source code so that MY_PRODCODE is set to be the Product Code in the dongle.", MsgBoxStyle.OkOnly, "Error")
ProtCheckEnc = -1
Exit Function
End If
' later on in your program you can check the return code again
If (dris.ret_code <> 0) Then
MsgBox("Dinkey Dongle protection error", MsgBoxStyle.OkOnly, "Error")
ProtCheckEnc = -1
Exit Function
End If
ProtCheckEnc = 0
Exit Function
Protection_Err: ' see readme.txt for explanation of this exception handler
Protection_Exception()
ProtCheckEnc = -1
End Function
' ************************** ProtCheckWithAlgEnc ****************************
' NB for this to work you must program at least "user algorithm" into the dongle
' NB We have used a very simple algorithm here (in the MyAlgorithm function). You must patch this with the
' sample code generated by DinkeyAdd for the algorithm that you are using. For Dinkey Lite get source from DinkeyLook.
' We encrypt the DRIS passed to the API. Patch the CryptDRIS function in this file from source code generated by DinkeyAdd.
Function ProtCheckWithAlgEnc() As Integer
Dim dris As DRIS = New DRIS
Dim ret_code As Integer
On Error GoTo Protection_Err
' set the DRIS to have random values
Call RandomSet(dris)
' then set the values we want to use
dris.header1 = Asc("D")
dris.header2 = Asc("R")
dris.header3 = Asc("I")
dris.header4 = Asc("S")
dris.size = Marshal.SizeOf(dris)
dris.myfunction = EXECUTE_ALGORITHM ' standard protection check & execute algorithm
dris.flags = 0 ' no extra flags, but you may want to specify some if you want to start a network user or decrement execs,...
dris.alg_number = 1 ' execute first algorithm (you do not need to specify this field for Dinkey Lite dongles)
' you should remove these entries if you are using Dinkey Lite so that algorithm arguments are random
dris.var_a = 1 ' sample values
dris.var_b = 2
dris.var_c = 3
dris.var_d = 4
dris.var_e = 5
dris.var_f = 6
dris.var_g = 7
dris.var_h = 8
Call CryptDRIS(dris) ' encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
ret_code = DDProtCheck(dris, Nothing)
Call CryptDRIS(dris) ' decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
If (ret_code <> 0) Then
Call DisplayError(ret_code, dris.ext_err)
ProtCheckWithAlgEnc = ret_code
Exit Function
End If
' later in your code you can check other values in the DRIS...
If (dris.sdsn <> MY_SDSN) Then
MsgBox("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.", MsgBoxStyle.OkOnly, "Error")
ProtCheckWithAlgEnc = -1
Exit Function
End If
' later on in your program you can check the return code again
If (dris.ret_code <> 0) Then
MsgBox("Dinkey Dongle protection error", MsgBoxStyle.OkOnly, "Error")
ProtCheckWithAlgEnc = -1
Exit Function
End If
' if you want you can check the algorithm answer - however if algorithm is from your code then best to just use the answer in your code
' !!!! Make sure you have replaced the MyAlgorithm routine with the algorithm you have specified in DinkeyAdd
If (MyAlgorithm(dris.var_a, dris.var_b, dris.var_c, dris.var_d, dris.var_e, dris.var_f, dris.var_g, dris.var_h) <> dris.alg_answer) Then
MsgBox("Dinkey protection error!\nYou have not patched your algorithm in the MyAlgorithm routine", MsgBoxStyle.OkOnly, "Error")
ProtCheckWithAlgEnc = -1
Exit Function
End If
ProtCheckWithAlgEnc = 0
Exit Function
Protection_Err: ' see readme.txt for explanation of this exception handler
Protection_Exception()
ProtCheckWithAlgEnc = -1
End Function
' ************************** WriteBytesEnc ******************************
' This writes the data array 0,1,2,3,4,5,6,7,8,9 to the dongle data area at offset 7
' In order for this function to work you will need to have a data area in your dongle that is at least 18 bytes long.
' We encrypt the DRIS and Data passed to the API. Patch the CryptDRIS and CryptApiData functions in this file from source code generated by DinkeyAdd.
' to write string data please read notes for WriteBytes
Function WriteBytesEnc() As Integer
Dim dris As DRIS = New DRIS
Dim ret_code, alg_ans As Integer
Dim data() As Byte = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
On Error GoTo Protection_Err
' set the DRIS to have random values
Call RandomSet(dris) ' sets DRIS to have random values including seed1, seed2 and var_a..var_h
' then set the values we want to use
dris.header1 = Asc("D")
dris.header2 = Asc("R")
dris.header3 = Asc("I")
dris.header4 = Asc("S")
dris.size = Marshal.SizeOf(dris)
dris.myfunction = WRITE_DATA_AREA ' standard protection check & write data
dris.flags = USE_FUNCTION_ARGUMENT ' you have to do it this way in vb.net
dris.rw_offset = 7
dris.rw_length = data.Length
dris.var_a = dris.var_a And &HFFFFFF ' restrict to 24-bit to prevent potential overflow in algorithm
dris.var_b = dris.var_b And &HFFFFFF
dris.var_c = dris.var_c And &HFFFFFF
dris.var_d = dris.var_d And &HFFFFFF
dris.var_e = dris.var_e And &HFFFFFF
dris.var_f = dris.var_f And &HFFFFFF
dris.var_g = dris.var_g And &HFFFFFF
dris.var_h = dris.var_h And &HFFFFFF
' calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code for r/w algorithm
alg_ans = MyRWAlgorithm(dris.var_a, dris.var_b, dris.var_c, dris.var_d, dris.var_e, dris.var_f, dris.var_g, dris.var_h)
' encrypt data we want to write.
CryptApiData(dris, data, data.Length, alg_ans)
Call CryptDRIS(dris) ' encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
ret_code = DDProtCheck(dris, data)
Call CryptDRIS(dris) ' decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
If (ret_code <> 0) Then
Call DisplayError(ret_code, dris.ext_err)
WriteBytesEnc = ret_code
Exit Function
End If
' later in your code you can check other values in the DRIS...
If (dris.sdsn <> MY_SDSN) Then
MsgBox("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.", MsgBoxStyle.OkOnly, "Error")
WriteBytesEnc = -1
Exit Function
End If
' later on in your program you can check the return code again
If (dris.ret_code <> 0) Then
MsgBox("Dinkey Dongle protection error", MsgBoxStyle.OkOnly, "Error")
WriteBytesEnc = -1
Exit Function
End If
WriteBytesEnc = 0
Exit Function
Protection_Err: ' see readme.txt for explanation of this exception handler
Protection_Exception()
WriteBytesEnc = -1
End Function
' ************************ ReadBytesEnc ************************************
' This reads 10 bytes of data from offset 7 in the dongle data area
' In order for this function to work you will need to have a data area in your dongle that is at least 18 bytes long.
' We encrypt the DRIS and Data passed from the API. Patch the CryptDRIS and CryptApiData functions in this file from source code generated by DinkeyAdd.
' to read string data please notes for ReadBytes function
Function ReadBytesEnc() As Integer
Dim dris As DRIS = New DRIS
Dim ret_code, alg_ans As Integer
Dim data(10) As Byte
On Error GoTo Protection_Err
' set the DRIS to have random values
Call RandomSet(dris) ' sets DRIS to have random values including seed1, seed2 and var_a..var_h
' then set the values we want to use
dris.header1 = Asc("D")
dris.header2 = Asc("R")
dris.header3 = Asc("I")
dris.header4 = Asc("S")
dris.size = Marshal.SizeOf(dris)
dris.myfunction = READ_DATA_AREA ' standard protection check & read data
dris.flags = USE_FUNCTION_ARGUMENT ' you have to do it this way in vb.net
dris.rw_offset = 7
dris.rw_length = data.Length
dris.var_a = dris.var_a And &HFFFFFF ' restrict to 24-bit to prevent potential overflow in algorithm
dris.var_b = dris.var_b And &HFFFFFF
dris.var_c = dris.var_c And &HFFFFFF
dris.var_d = dris.var_d And &HFFFFFF
dris.var_e = dris.var_e And &HFFFFFF
dris.var_f = dris.var_f And &HFFFFFF
dris.var_g = dris.var_g And &HFFFFFF
dris.var_h = dris.var_h And &HFFFFFF
' calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code for r/w algorithm
alg_ans = MyRWAlgorithm(dris.var_a, dris.var_b, dris.var_c, dris.var_d, dris.var_e, dris.var_f, dris.var_g, dris.var_h)
Call CryptDRIS(dris) ' encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
ret_code = DDProtCheck(dris, data)
Call CryptDRIS(dris) ' decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
If (ret_code <> 0) Then
Call DisplayError(ret_code, dris.ext_err)
ReadBytesEnc = ret_code
Exit Function
End If
' later in your code you can check other values in the DRIS...
If (dris.sdsn <> MY_SDSN) Then
MsgBox("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.", MsgBoxStyle.OkOnly, "Error")
ReadBytesEnc = -1
Exit Function
End If
' later on in your program you can check the return code again
If (dris.ret_code <> 0) Then
MsgBox("Dinkey Dongle protection error", MsgBoxStyle.OkOnly, "Error")
ReadBytesEnc = -1
Exit Function
End If
' decrypt data just read.
CryptApiData(dris, data, data.Length, alg_ans)
MsgBox("Dinkey Dongle Data Area, offset 7 is : " + Str(data(0)) + "," + Str(data(1)) + "," + Str(data(2)) + "," + Str(data(3)) + "," + _
Str(data(4)) + "," + Str(data(5)) + "," + Str(data(6)) + "," + Str(data(7)) + "," + Str(data(8)) + "," + Str(data(9)), MsgBoxStyle.OkOnly)
ReadBytesEnc = 0
Exit Function
Protection_Err: ' see readme.txt for explanation of this exception handler
Protection_Exception()
ReadBytesEnc = -1
End Function
' ************************** EncryptUserDataEnc *********************************
' This function will do a protection check and ask the dongle to encrypt some data using encryption key 1
' It will then do another protection check & decrypt the data
' We encrypt the DRIS and Data passed to/from the API. Patch the CryptDRIS and CryptApiData functions in this file from source code generated by DinkeyAdd.
' to encrypt or decrypt strings please read notes for WriteBytes and ReadBytes functions
Function EncryptUserDataEnc() As Integer
Dim dris As DRIS = New DRIS
Dim ret_code, alg_ans As Integer
Dim data() As Byte = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
On Error GoTo Protection_Err
' set the DRIS to have random values
Call RandomSet(dris) ' sets DRIS to have random values including seed1, seed2 and var_a..var_h
' then set the values we want to use
dris.header1 = Asc("D")
dris.header2 = Asc("R")
dris.header3 = Asc("I")
dris.header4 = Asc("S")
dris.size = Marshal.SizeOf(dris)
dris.myfunction = ENCRYPT_USER_DATA ' standard protection check & encrypt data
dris.flags = USE_FUNCTION_ARGUMENT ' you have to do it this way in vb.net
dris.rw_length = data.Length
dris.data_crypt_key_num = 1
dris.var_a = dris.var_a And &HFFFFFF ' restrict to 24-bit to prevent potential overflow in algorithm
dris.var_b = dris.var_b And &HFFFFFF
dris.var_c = dris.var_c And &HFFFFFF
dris.var_d = dris.var_d And &HFFFFFF
dris.var_e = dris.var_e And &HFFFFFF
dris.var_f = dris.var_f And &HFFFFFF
dris.var_g = dris.var_g And &HFFFFFF
dris.var_h = dris.var_h And &HFFFFFF
' calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code for r/w algorithm
alg_ans = MyRWAlgorithm(dris.var_a, dris.var_b, dris.var_c, dris.var_d, dris.var_e, dris.var_f, dris.var_g, dris.var_h)
' encrypt data we pass to our API
CryptApiData(dris, data, data.Length, alg_ans)
Call CryptDRIS(dris) ' encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
ret_code = DDProtCheck(dris, data)
Call CryptDRIS(dris) ' decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
If (ret_code <> 0) Then
Call DisplayError(ret_code, dris.ext_err)
EncryptUserDataEnc = ret_code
Exit Function
End If
' ... could add code to check other elements of the DRIS, e.g. ret_code, sdsn, ...
' Now decrypt the same data to get the original values
Call RandomSet(dris) ' sets DRIS to have random values including seed1, seed2 and var_a..var_h
' then set the values we want to use
dris.header1 = Asc("D")
dris.header2 = Asc("R")
dris.header3 = Asc("I")
dris.header4 = Asc("S")
dris.size = Marshal.SizeOf(dris)
dris.myfunction = DECRYPT_USER_DATA ' standard protection check & decrypt data
dris.flags = USE_FUNCTION_ARGUMENT ' you have to do it this way in vb.net
dris.rw_length = data.Length
dris.data_crypt_key_num = 1
dris.var_a = dris.var_a And &HFFFFFF ' restrict to 24-bit to prevent potential overflow in algorithm
dris.var_b = dris.var_b And &HFFFFFF
dris.var_c = dris.var_c And &HFFFFFF
dris.var_d = dris.var_d And &HFFFFFF
dris.var_e = dris.var_e And &HFFFFFF
dris.var_f = dris.var_f And &HFFFFFF
dris.var_g = dris.var_g And &HFFFFFF
dris.var_h = dris.var_h And &HFFFFFF
Call CryptDRIS(dris) ' encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
ret_code = DDProtCheck(dris, data)
Call CryptDRIS(dris) ' decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)
If (ret_code <> 0) Then
Call DisplayError(ret_code, dris.ext_err)
EncryptUserDataEnc = ret_code
Exit Function
End If
' calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code for r/w algorithm
alg_ans = MyRWAlgorithm(dris.var_a, dris.var_b, dris.var_c, dris.var_d, dris.var_e, dris.var_f, dris.var_g, dris.var_h)
' later in your code you can check other values in the DRIS...
If (dris.sdsn <> MY_SDSN) Then
MsgBox("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.", MsgBoxStyle.OkOnly, "Error")
EncryptUserDataEnc = -1
Exit Function
End If
' later on in your program you can check the return code again
If (dris.ret_code <> 0) Then
MsgBox("Dinkey Dongle protection error", MsgBoxStyle.OkOnly, "Error")
EncryptUserDataEnc = -1
Exit Function
End If
' decrypt data just returned by API.
CryptApiData(dris, data, data.Length, alg_ans)
MsgBox("Decrypted data is : " + Str(data(0)) + "," + Str(data(1)) + "," + Str(data(2)) + "," + Str(data(3)) + "," + _
Str(data(4)) + "," + Str(data(5)) + "," + Str(data(6)) + "," + Str(data(7)) + "," + Str(data(8)) + "," + Str(data(9)), MsgBoxStyle.OkOnly)
EncryptUserDataEnc = 0
Exit Function
Protection_Err: ' see readme.txt for explanation of this exception handler
Protection_Exception()
EncryptUserDataEnc = -1
End Function
' *********************** DisplayNetUsers *******************************
' This function displays the current network users (for DinkeyNet only).
' The DDProtCheck function must be called before this function is called.
' (Normally you would use DinkeyServer to view the network users but this enables you to do it from the client if you want)
Function DisplayNetUsers(net_users As Integer, model As Integer) As Integer
Dim num_net_users, extended_error, ret_code, i, max_net_users As Integer
Dim DisplayString As String
If net_users = -1 Then
max_net_users = 100 ' if unlimited network users are allowed then display up to 100 users (for example)
Else
max_net_users = net_users
End If
If max_net_users = 0 Then ' no network users are allowed, so nothing to do!
DisplayNetUsers = 0
Exit Function
End If
If model < 3 Then
MsgBox("A network dongle has not been detected. Therefore you cannot display the network users.", MsgBoxStyle.OKOnly)
DisplayNetUsers = -1
Exit Function
End If
Dim nu_info_array(max_net_users) As NU_INFO
' now get net users
ret_code = DDGetNetUserList(Nothing, num_net_users, nu_info_array, max_net_users, extended_error)
If ret_code <> 0 Then
MsgBox("Error " + Str(ret_code) + "/" + Str(extended_error) + " finding network user information.", MsgBoxStyle.OKOnly)
Else
DisplayString = "number of net users: " + Str(num_net_users) + Environment.NewLine
For i = 0 To num_net_users - 1
DisplayString = DisplayString + Str(i + 1) + ". licence: " + nu_info_array(i).LicenceName + ", user: " + nu_info_array(i).UserName + ", computer: " + nu_info_array(i).ComputerName + ", ip address: " + nu_info_array(i).IPAddress + Environment.NewLine
Next
MsgBox(DisplayString, MsgBoxStyle.OKOnly, "Net Users")
End If
DisplayNetUsers = ret_code
End Function
' look at the error code and try to display an appropriate message
' you may want to change these messages and specify your own
Public Sub DisplayError(ByVal ret_code As Integer, ByVal extended_error As Integer)
Select Case ret_code
Case 401
MsgBox("Error! No dongles detected!", MsgBoxStyle.OKOnly, "Error")
Case 403
MsgBox("Error! A dongle was detected but it was a different type to the one specified in DinkeyAdd.", MsgBoxStyle.OKOnly, "Error")
Case 404
MsgBox("Error! A dongle was detected but it was a different model to those specified in DinkeyAdd.", MsgBoxStyle.OKOnly, "Error")
Case 409
MsgBox("Error! The dongle detected has not been programmed by DinkeyAdd.", MsgBoxStyle.OKOnly, "Error")
Case 410
MsgBox("Error! A dongle was detected but it has a different Product Code to the one specified in DinkeyAdd.", MsgBoxStyle.OKOnly, "Error")
Case 411
MsgBox("Error! The dongle detected does not contain the licence associated with this program.", MsgBoxStyle.OKOnly, "Error")
Case 413
MsgBox("Error! This program has not been protected by DinkeyAdd. For guidance please read the DinkeyAdd chapter of the Dinkey manual.", MsgBoxStyle.OKOnly, "Error")
Case 417
MsgBox("Error! One or more of the parameters set in the DRIS is incorrect. This could be caused if you are encrypting the DRIS in your code but did not specify DRIS encryption in DinkeyAdd - or vice versa.", MsgBoxStyle.OKOnly, "Error")
Case 423
MsgBox("Error! The number of network users has been exceeded.", MsgBoxStyle.OKOnly, "Error")
Case 435
MsgBox("Error! DinkeyServer has not been detected on the network.", MsgBoxStyle.OKOnly, "Error")
Case 922
MsgBox("Error! The Software Key has expired.", MsgBoxStyle.OKOnly, "Error")
Case Else
MsgBox("An error occurred checking the dongle. Error: " + Str(ret_code) + ". Extended Error: " + Str(extended_error) + ".", MsgBoxStyle.OKOnly, "Error")
End Select
End Sub
' if an error exception occurs during a protection check function then display an appropiate message
' see readme.txt for an explaination
Sub Protection_Exception()
If (TypeOf Err.GetException() Is DllNotFoundException) Then
If (IntPtr.Size = 4) Then
MsgBox("Error! Cannot find dpwin32.dll. This should be in the same folder that DLLTest.exe is in.", MsgBoxStyle.OKOnly, "Error")
Else
MsgBox("Error! Cannot find dpwin64.dll. This should be in the same folder that DLLTest.exe is in.", MsgBoxStyle.OKOnly, "Error")
End If
Else
MsgBox("Error! An exception occurred: " + Err.GetException.Message, MsgBoxStyle.OKOnly, "Error")
End If
End Sub
End Class

View File

@@ -0,0 +1,180 @@
DllTest - sample code to call the Runtime Module in VB.NET
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This project is written in Visual Studio 2002 but will work in more recent versions of Visual Studio
(it will upgrade the Project to the latest version. If prompted you should also upgrade the .NET
framework the project requires).
The main source files in the project are:
File name Description
Form1.vb main source code file for VB.NET
dris.vb contains the DRIS structure and low-level functions to manipulate it.
The best approach is to compile the sample code and see how it works and then to take the appropriate code
and apply it to your own project. You should include the dris.vb file in your project and use/modify which
ever functions from form1.vb you feel are appropriate. The dris.vb file should not be modified.
The sample code contains 11 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.
You should implement the protection in a stronger way using the techniques described in the
"Increasing your Protection" chapter of the manual.
Code marked with !!!! are places where you should customise the sample code so that it will work properly:
* Change the MY_SDSN value to the value of your SDSN
* Change the MY_PRODCODE value to the Product Code in the dongle
* Change the MyAlgorithm code (if you call a user algorithm)
* Change the CryptDRIS code (if you encrypt the DRIS)
* Change the CryptApiData (if you encrypt Data you send to our API)
* Change the MyRWAlgorithm code (if encrypt Data you send to our API using the R/W algorithm)
You will also probably want to replace our error messages with your own. However, you should still
display or log any error codes returned by the protection check otherwise you will not be able to
identify the cause of the error. (You can look up error codes in our knowledge base: microcosm.com/kb).
For users of Visual Studio 2005 or higher, the default setting for projects is to compile for the Target
Platform "Any". This means that on 32-bit Windows, your code will run as 32-bit code (and needs to call
dpwin32.dll) and under 64-bit Windows your code will run as 64-bit code (and needs to call dpwin64.dll).
The sample code works this out automatically. If you select the target platform as "x86" then it will
always be 32-bit and so you only need to use dpwin32.dll. If you select "x64" then your code will be
64-bit and you only need to use dpwin64.dll.
Note - as you are using the API method in this sample you should protect dpwin32.dll and/or dpwin64.dll
and not your program. Because your program is linked to the DLL it is protected. You can also protect
your program with the Shell Method should you wish.
Note - if you are compiling for the Platform target "Any" (and therefore need to protect both dpwin32.dll
and dpwin64.dll) then you will probably want to protect these modules to the same licence so that they share
a common set of protection parameters.
Make sure you remember to do the following:
1) Insert the following namespaces in your code file:
Imports System.Runtime.InteropServices
2) Insert the dris.vb file in your project.
3) The protected dpwin32.dll (dpwin64.dll) should be output to the folder that contains your EXE file.
Otherwise the message "Unable to open DLL (dpwin32.dll)" or System.DllNotFoundException error will appear
when you run DllTest. Unfortunately, when the system displays these exceptions, it gives the choice of
"Continue" which will return from the program assuming it returned success - and thereby bypassing the
protection check. To combat this we have added the Protection_Err exception handler to handle exceptions.
This behaviour appears to be unique to VB.NET.
If you wish you can rename dpwin32.dll (dpwin64.dll) to a name of your choice. In this case you will need to
modify the dll name in the dris.vb file.
Note - VB.NET is an interpreted language and so it is easier to decompile than other languages. You can
improve security if you use an obfuscator to obfuscate your code. Or - even better - you could use the
Shell Method to protect your executable. This encrypts your code (making it impossible to decompile).
Note for using strings in DRIS
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To set the alt_licence_name field and read the prodcode field in the DRIS you need to use the
SetAltLicenceName and GetProductCode functions. You can use other fields directly, e.g. dris.sdsn
Notes on Debugging 64-bit Code
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When you use the 64-bit runtime module (dpwin64.dll) to protect your software the anti-debug code is so
strong that if you are debugging your code, after the call DDProtCheck then it will crash with an SEH
exception. If you want to be able to debug your code then you can setup your project so that your code
calls the debug module (dpwin64debug.dll) in your "debug" build and the standard module (dpwin64.dll)
in your release build. You can do this by modifying the declaration of DDProtCheck64 in dris.vb like this:
#if DEBUG ' debug module
Declare Function DDProtCheck64 Lib "dpwin64debug.dll" Alias "DDProtCheck" (ByRef mydris As DRIS, ByVal data() As Byte) As Integer
#else ' standard module
Declare Function DDProtCheck64 Lib "dpwin64.dll" Alias "DDProtCheck" (ByRef mydris As DRIS, ByVal data() As Byte) As Integer
#endif
Note - the debug module has the following restrictions:
1) It will not correctly start a network user (network dongles only). However, other than that the protection
check will function correctly and return success.
2) You will not be able to encrypt the DRIS. (If you do encrypt the DRIS in your release build then you
should make sure that CryptDRIS does not get called in your debug build).
3) The protection check will take slightly longer than normal.
4) The DDGetNetUserList function will return error 428 (not implemented).
5) A temporary subprocess is created which may be (falsely) detected as malicious by anti-virus programs.
This behaviour does not occur in 32-bit code, so if you are using dpwin32.dll then you can debug your code.
Special Note for using Algorithms in VB.NET
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The algorithms are calculated using 32-bit integers (Integer in vb.net). It is quite possible for the
MyAlgorithm and MyRWAlgorithm functions to overflow if the values provided are too big. In the dongle the
algorithms can never overflow - if the answer is too big then the high part of the answer is ignored.
In practical terms:
When you are using the r/w algorithm it is best not to pass random 32-bit integers. It is better to restrict
the variables to 24-bit to avoid the possibility of overflows. You can see this implemented in the MyRWAlgorithm
and WriteBytesEnc function, for example.
You can also use this technique with the user algorithms. Another option in MyAlgorithm is to convert each input
to 64-bit, apply the algorithm and then convert back to 32-bit to return the answer.
When using a user algorithm it will behave exactly as the corresponding MyAlgorithm function will in VB
except it will not give overflow errors.
Important Note for UWP app Developers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Universal Windows Platform (UWP) application (previously called Windows Store Apps or Metro Apps) are not
compatible with Lite or Plus dongles because the restrictions imposed by these applications. However, you
can protect these Apps with network dongles (because the restrictive access is performed by the non-UWP
DinkeyServer process). If you do this you will need to enable the "Private Networks (Client and Server)"
Capability in your package manifest.
.NET Core / .NET 5+
~~~~~~~~~~~~~~~~~~~
The sample code provided also works with .NET Core. However, .NET Core also supports Linux and macOS as well
as other platforms. If you want to support these OS then please replace dris.vb with dris_dotnetcore.vb.
The files are very similar but dris_dotnetcore.vb will load the relevant native runtime module (dpwin32.dll
under 32-bit Windows; dpwin64.dll under 64-bit Windows; dplin64.so under Linux OS; dpmac64debug.dylib under
macOS - unfortunately the release module is not compatible with the .NET Core framework so you have to use
the debug one. This also means that our solution is not compatible with ARM-based macOS - because the debug
modules do not exist).
If you are using .NET Core version earlier than 3.0 then Windows.Forms are not supported and you will have to
replace the MessageBox.Show lines with Console.WriteLine.
The Shell Method is compatible with .NET Core Console, Windows.Forms and WPF applications. It is supported
under Windows and Linux but not macOS. It is only supported for .NET Core version 3.0 or higher. If you are
using the Shell Method then you should protect your compiled dll and not the "appHost" (this is a native
executable which is just a stub program that loads the assemblies in your dll). Also do not use "dotnet run"
to launch your application - it will run the unprotected version. Either launch the executable or run using
"dotnet <program.dll>".
If you publish a "single-file executable" file then although this file can be protected we do not recommend
it because it is not secure. (The single-file executable just comprises a stub loader with your compiled
assemblies and configuration files appended to the end of the executable. These files are just considered as
data appended to the executable file in a custom format and therefore are not protected. When you shell
protect your executable you are just protecting the loader but not your assemblies). Instead you need to
build your code and then add protection before publishing. You should protect your assemblies in the obj
directory (and in the platform type you specified) e.g. obj/Release/net5.0/win-x64, because the publish
process takes your assemblies from this location when it builds the single-file executable. You will also
need to distribute all the extra files that DinkeyAdd generates. e.g. <file>.dp64.dll.
If you publish using the ReadytoRun compilation this will not work because it includes mixtures of .NET
assemblies and native code and the .NET Shell Method does not support that.
Visual Studio Installer Projects Extension
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can use this extension to create a project in your solution that will create an installation program / msi
file. Please note that after your application has been built you need to protect it with DinkeyAdd before you
can invoke the installer project. You can do this manually by building your application project (not the entire
solution); then adding protection to your application using DinkeyAdd; then building your installer project.
Or you can automate this by executing DinkeyAddCmd as a post-build step. For example:
"c:\program files (x86)\Dinkey Pro 7.6.0\DinkeyAdd\DinkeyAddCmd.exe" c:\adir\mydapf.dapfj /a2
Note - if you specify "primary output" in your installer project then it will take the files from
obj\Release\net5.0 (for example), rather than bin\Release\net5.0. So, you need to add protection to your files
in this folder.
Note - if you use the API Method you will also need to include the protected runtime modules that you use
(e.g. dpwin64.dll). If you use the Shell Method you will also need to include in your installer project all
of the output files mentioned by DinkeyAdd. e.g. <application_name>.dp64.dll

View File

@@ -0,0 +1,218 @@
' !! this file should not be modified
Imports System.Runtime.InteropServices
Imports System.Text
Module dris_code
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi, Pack:=1)> _
Structure DRIS
' the first 4 fields are never encrypted
Dim header1 As Byte ' should be set to 'DRIS'
Dim header2 As Byte
Dim header3 As Byte
Dim header4 As Byte
' inputs
Dim size As Integer ' size of this structure
Dim seed1 As Integer ' seed for data/dris encryption
Dim seed2 As Integer ' as above
' (maybe encrypted from now on)
Dim myfunction As Integer ' specify only one function
Dim flags As Integer ' options for the function selected. To use more than one OR them together: OPTION1 Or OPTION2...
Dim execs_decrement As UInt32 ' amount by which to dec execs if we use flag: DEC_MANY_EXECS
Dim data_crypt_key_num As Integer ' number of the key (1-3) that the dongle uses to encrypt or decrypt user data
Dim rw_offset As Integer ' offset in the dongle data area to read or write data
Dim rw_length As Integer ' length of data are to read/write/encrypt/decrypt
Dim DoNotUse As IntPtr ' do not use the rw_data_ptr element use the "Data" argument of the DDProtCheck function
' to set this field use the function SetAltLicenceName instead
<VBFixedArray(256), MarshalAs(UnmanagedType.ByValArray, SizeConst:=256)> Dim _alt_licence_name As Byte()
Dim var_a As Integer ' variable values for user algorithm
Dim var_b As Integer
Dim var_c As Integer
Dim var_d As Integer
Dim var_e As Integer
Dim var_f As Integer
Dim var_g As Integer
Dim var_h As Integer
Dim alg_number As Integer ' the number of the user algorithm that you want to execute
' outputs
Dim ret_code As Integer ' return code from the protection check
Dim ext_err As Integer ' extended error
Dim type As Integer ' type of dongle detected. 1 = Pro, 2 = FD
Dim model As Integer ' model of dongle detected. 1 = Lite, 2 = Plus, 4 = Net 5, 7 = Net Unlimited
Dim sdsn As Integer ' Software Developer's Serial Number
'to read this field use the function GetProductCode instead
<VBFixedArray(12), MarshalAs(UnmanagedType.ByValArray, SizeConst:=12)> Dim _prodcode As Byte()
Dim dongle_number As UInt32
Dim update_number As Integer
Dim data_area_size As UInt32 ' size of the data area in the dongle detected
Dim max_alg_num As Integer ' the maximum algorithm number in the dongle detected
Dim execs As Integer ' executions left: -1 indicates 'no limit'
Dim exp_day As Integer ' expiry day: -1 indicates 'no limit'
Dim exp_month As Integer ' expiry month: -1 indicates 'no limit'
Dim exp_year As Integer ' expiry year: -1 indicates 'no limit'
Dim features As UInt32 ' features value
Dim net_users As Integer ' maximum number of network users for the dongle detected: -1 indicates 'mo limit'
Dim alg_answer As Integer ' answer to the user algorithm executed with the given variable values
Dim fd_capacity As UInt32 ' capacity of the data area in FD dongle. Currently fixed at ~10MB but may change in the future.
'to read this field use the function GetFDDrive instead
<VBFixedArray(128), MarshalAs(UnmanagedType.ByValArray, SizeConst:=128)> Dim _fd_drive As Byte()
Dim swkey_type As Integer ' 0 = no swkey detected, 1 = temporary software key, 2 = demo software key
Dim swkey_exp_day As Integer ' software key expiry date (if software key detected)
Dim swkey_exp_month As Integer
Dim swkey_exp_year As Integer
End Structure
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi, Pack:=1)> _
Structure NU_INFO
<VBFixedString(256), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=256)> _
Dim LicenceName As String
<VBFixedString(50), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=50)> _
Dim UserName As String
<VBFixedString(256), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=256)> _
Dim ComputerName As String
<VBFixedString(16), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=16)> _
Dim IPAddress As String
End Structure
' functions exported from dpwin32.dll / dpwin32.dll - do 32-bit and 64-bit separately
' DDProtCheck
Declare Function DDProtCheck32 Lib "dpwin32.dll" Alias "DDProtCheck" (ByRef mydris As DRIS, ByVal data() As Byte) As Integer
Declare Function DDProtCheck64 Lib "dpwin64.dll" Alias "DDProtCheck" (ByRef mydris As DRIS, ByVal data() As Byte) As Integer
' DDGetNetUserList
Declare Ansi Function DDGetNetUserList32 Lib "dpwin32.dll" Alias "DDGetNetUserList" (ByVal licence_name As String, ByRef num_net_users As Integer, _
ByVal nu_info_bytes() As Byte, ByVal num_info_structs As Integer, ByRef extended_error As Integer) As Integer
Declare Ansi Function DDGetNetUserList64 Lib "dpwin64.dll" Alias "DDGetNetUserList" (ByVal licence_name As String, ByRef num_net_users As Integer, _
ByVal nu_info_bytes() As Byte, ByVal num_info_structs As Integer, ByRef extended_error As Integer) As Integer
' call the correct dll depending on whether we are running 32-bit or 64-bit code
Function DDProtCheck(ByRef mydris As DRIS, ByVal data() As Byte) As Integer
If (IntPtr.Size = 4) Then
DDProtCheck = DDProtCheck32(mydris, data)
Else
DDProtCheck = DDProtCheck64(mydris, data)
End If
End Function
Function DDGetNetUserList(ByVal licence_name As String, ByRef num_net_users As Integer, ByRef nu_info_array() As NU_INFO, ByVal num_info_structs As Integer, ByRef extended_error As Integer) As Integer
Dim i As Integer
Dim my_nu_info As New NU_INFO ' NB this only exists so we can get the size of the NU_INFO stucture
Dim nu_info_bytes(num_info_structs * Marshal.SizeOf(my_nu_info)) As Byte
Dim nu_info_one_struct(Marshal.SizeOf(my_nu_info)) As Byte
Dim MyGC As GCHandle
' call the function and get info as a byte array
If (IntPtr.Size = 4) Then
DDGetNetUserList = DDGetNetUserList32(licence_name, num_net_users, nu_info_bytes, num_info_structs, extended_error)
Else
DDGetNetUserList = DDGetNetUserList64(licence_name, num_net_users, nu_info_bytes, num_info_structs, extended_error)
End If
' convert byte array to an array of structs
For i = 0 To num_net_users - 1
nu_info_array(i) = New NU_INFO
Array.Copy(nu_info_bytes, i * Marshal.SizeOf(my_nu_info.GetType), nu_info_one_struct, 0, Marshal.SizeOf(my_nu_info.GetType))
MyGC = GCHandle.Alloc(nu_info_one_struct, GCHandleType.Pinned)
nu_info_array(i) = Marshal.PtrToStructure(MyGC.AddrOfPinnedObject, my_nu_info.GetType)
MyGC.Free()
Next
End Function
' Functions
Public Const PROTECTION_CHECK As Integer = 1 ' checks for dongle, check program params...
Public Const EXECUTE_ALGORITHM As Integer = 2 ' protection check + calculate answer for specified algorithm with specified inputs
Public Const WRITE_DATA_AREA As Integer = 3 ' protection check + writes dongle data area
Public Const READ_DATA_AREA As Integer = 4 ' protection check + reads dongle data area
Public Const ENCRYPT_USER_DATA As Integer = 5 ' protection check + the dongle will encrypt user data
Public Const DECRYPT_USER_DATA As Integer = 6 ' protection check + the dongle will decrypt user data
Public Const FAST_PRESENCE_CHECK As Integer = 7 ' checks for the presence of the correct dongle only with minimal security, no flags allowed
Public Const STOP_NET_USER As Integer = 8 ' stops a network user (a protection check is NOT performed)
' Flags
Public Const DEC_ONE_EXEC As Integer = 1 ' decrement execs by 1
Public Const DEC_MANY_EXECS As Integer = 2 ' decrement execs by number specified in execs
Public Const START_NET_USER As Integer = 4 ' starts a network user
Public Const USE_FUNCTION_ARGUMENT As Integer = 16 ' use the extra argument in the function for pointers
Public Const CHECK_LOCAL_FIRST As Integer = 32 ' always look in local ports before looking in network ports
Public Const CHECK_NETWORK_FIRST As Integer = 64 ' always look on the network before looking in local ports
Public Const USE_ALT_LICENCE_NAME As Integer = 128 ' use name specified in alt_licence_name instead of the default one
Public Const DONT_SET_MAXDAYS_EXPIRY As Integer = 256 ' if the max days expiry date has not been calculated then do not do it this time
Public Const MATCH_DONGLE_NUMBER As Integer = 512 ' restrict the search to match the dongle number specified in the DRIS
Public Const DONT_RETURN_FD_DRIVE As Integer = 1024 ' if an FD dongle has been detected then don't return the flash drive/mount name in the DRIS
Public Const NU_INFO_SIZE As Integer = (256 + 50 + 256 + 16) ' size of NU_INFO structure (for listing network users)
' ********************** useful functions for use in sample code ***************************
' use this function to set the alt_licence_name field of the DRIS
Public Sub SetAltLicenceName(ByVal mydris As DRIS, ByVal altlicencename As String)
Dim i, num_bytes As Integer
Dim ascii As New ASCIIEncoding
Dim temp As Byte()
temp = ascii.GetBytes(altlicencename)
num_bytes = ascii.GetByteCount(altlicencename)
For i = 0 To num_bytes - 1
mydris._alt_licence_name(i) = temp(i)
Next
mydris._alt_licence_name(num_bytes) = 0 'null-terminate string
End Sub
' use this function to read the prodcode field of the DRIS
Public Function GetProductCode(ByVal mydris As DRIS) As String
Dim ascii As New ASCIIEncoding
Dim i As Integer
For i = 0 To 11
If mydris._prodcode(i) = 0 Then
Exit For
End If
Next
Return ascii.GetString(mydris._prodcode, 0, i)
End Function
' use this function to read the fd_drive field of the DRIS
Public Function GetFDDrive(ByVal mydris As DRIS) As String
Dim ascii As New ASCIIEncoding
Dim i As Integer
For i = 0 To 127
If mydris._fd_drive(i) = 0 Then
Exit For
End If
Next
Return ascii.GetString(mydris._fd_drive, 0, i)
End Function
' copies an integer to offset "index" in trhe specified byte array
Public Sub Set4Bytes(ByVal data() As Byte, ByVal index As Integer, ByVal value As Integer)
Dim MyGC As GCHandle = GCHandle.Alloc(value, GCHandleType.Pinned)
Dim AddressOfValue As IntPtr = MyGC.AddrOfPinnedObject()
Marshal.Copy(AddressOfValue, data, index, 4)
MyGC.Free()
End Sub
' converts to DRIS structure to a byte array (so we can do encryption)
Public Sub DrisToByteArray(ByVal mydris As DRIS, ByVal data() As Byte)
Dim MyGC As GCHandle = GCHandle.Alloc(data, GCHandleType.Pinned)
Marshal.StructureToPtr(mydris, MyGC.AddrOfPinnedObject, False)
MyGC.Free()
End Sub
' converts a byte array to the DRIS structure (so we can do encryption)
Public Sub ByteArrayToDris(ByVal data() As Byte, ByRef mydris As DRIS)
Dim MyGC As GCHandle = GCHandle.Alloc(data, GCHandleType.Pinned)
mydris = Marshal.PtrToStructure(MyGC.AddrOfPinnedObject, mydris.GetType)
MyGC.Free()
End Sub
' initialise the DRIS with random values
Public Sub RandomSet(ByRef mydris As DRIS)
Dim temp_dris(Marshal.SizeOf(mydris) - 1) As Byte
Dim rnd As New Random
rnd.NextBytes(temp_dris)
ByteArrayToDris(temp_dris, mydris)
End Sub
End Module

View File

@@ -0,0 +1,236 @@
' !! this file should not be modified
Imports System.Runtime.InteropServices
Imports System.Text
Module dris_code
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi, Pack:=1)> _
Structure DRIS
' the first 4 fields are never encrypted
Dim header1 As Byte ' should be set to 'DRIS'
Dim header2 As Byte
Dim header3 As Byte
Dim header4 As Byte
' inputs
Dim size As Integer ' size of this structure
Dim seed1 As Integer ' seed for data/dris encryption
Dim seed2 As Integer ' as above
' (maybe encrypted from now on)
Dim myfunction As Integer ' specify only one function
Dim flags As Integer ' options for the function selected. To use more than one OR them together: OPTION1 Or OPTION2...
Dim execs_decrement As UInt32 ' amount by which to dec execs if we use flag: DEC_MANY_EXECS
Dim data_crypt_key_num As Integer ' number of the key (1-3) that the dongle uses to encrypt or decrypt user data
Dim rw_offset As Integer ' offset in the dongle data area to read or write data
Dim rw_length As Integer ' length of data are to read/write/encrypt/decrypt
Dim DoNotUse As IntPtr ' do not use the rw_data_ptr element use the "Data" argument of the DDProtCheck function
' to set this field use the function SetAltLicenceName instead
<VBFixedArray(256), MarshalAs(UnmanagedType.ByValArray, SizeConst:=256)> Dim _alt_licence_name As Byte()
Dim var_a As Integer ' variable values for user algorithm
Dim var_b As Integer
Dim var_c As Integer
Dim var_d As Integer
Dim var_e As Integer
Dim var_f As Integer
Dim var_g As Integer
Dim var_h As Integer
Dim alg_number As Integer ' the number of the user algorithm that you want to execute
' outputs
Dim ret_code As Integer ' return code from the protection check
Dim ext_err As Integer ' extended error
Dim type As Integer ' type of dongle detected. 1 = Pro, 2 = FD
Dim model As Integer ' model of dongle detected. 1 = Lite, 2 = Plus, 4 = Net 5, 7 = Net Unlimited
Dim sdsn As Integer ' Software Developer's Serial Number
'to read this field use the function GetProductCode instead
<VBFixedArray(12), MarshalAs(UnmanagedType.ByValArray, SizeConst:=12)> Dim _prodcode As Byte()
Dim dongle_number As UInt32
Dim update_number As Integer
Dim data_area_size As UInt32 ' size of the data area in the dongle detected
Dim max_alg_num As Integer ' the maximum algorithm number in the dongle detected
Dim execs As Integer ' executions left: -1 indicates 'no limit'
Dim exp_day As Integer ' expiry day: -1 indicates 'no limit'
Dim exp_month As Integer ' expiry month: -1 indicates 'no limit'
Dim exp_year As Integer ' expiry year: -1 indicates 'no limit'
Dim features As UInt32 ' features value
Dim net_users As Integer ' maximum number of network users for the dongle detected: -1 indicates 'mo limit'
Dim alg_answer As Integer ' answer to the user algorithm executed with the given variable values
Dim fd_capacity As UInt32 ' capacity of the data area in FD dongle. Currently fixed at ~10MB but may change in the future.
'to read this field use the function GetFDDrive instead
<VBFixedArray(128), MarshalAs(UnmanagedType.ByValArray, SizeConst:=128)> Dim _fd_drive As Byte()
Dim swkey_type As Integer ' 0 = no swkey detected, 1 = temporary software key, 2 = demo software key
Dim swkey_exp_day As Integer ' software key expiry date (if software key detected)
Dim swkey_exp_month As Integer
Dim swkey_exp_year As Integer
End Structure
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi, Pack:=1)> _
Structure NU_INFO
<VBFixedString(256), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=256)> _
Dim LicenceName As String
<VBFixedString(50), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=50)> _
Dim UserName As String
<VBFixedString(256), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=256)> _
Dim ComputerName As String
<VBFixedString(16), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=16)> _
Dim IPAddress As String
End Structure
' functions exported from runtime module e.g. dpwin64.dll etc
' DDProtCheck
Declare Function DDProtCheckWin32 Lib "dpwin32.dll" Alias "DDProtCheck" (ByRef mydris As DRIS, ByVal data() As Byte) As Integer
Declare Function DDProtCheckWin64 Lib "dpwin64.dll" Alias "DDProtCheck" (ByRef mydris As DRIS, ByVal data() As Byte) As Integer
Declare Function DDProtCheckLin64 Lib "dplin64.so" Alias "DDProtCheck" (ByRef mydris As DRIS, ByVal data() As Byte) As Integer
Declare Function DDProtCheckMac64 Lib "dpmac64debug.dylib" Alias "DDProtCheck" (ByRef mydris As DRIS, ByVal data() As Byte) As Integer
' DDGetNetUserList - NB not supported for macOS as this function does not exist in the debug module
Declare Ansi Function DDGetNetUserListWin32 Lib "dpwin32.dll" Alias "DDGetNetUserList" (ByVal licence_name As String, ByRef num_net_users As Integer,
ByVal nu_info_bytes() As Byte, ByVal num_info_structs As Integer, ByRef extended_error As Integer) As Integer
Declare Ansi Function DDGetNetUserListWin64 Lib "dpwin64.dll" Alias "DDGetNetUserList" (ByVal licence_name As String, ByRef num_net_users As Integer,
ByVal nu_info_bytes() As Byte, ByVal num_info_structs As Integer, ByRef extended_error As Integer) As Integer
Declare Ansi Function DDGetNetUserListLin64 Lib "dplin64.so" Alias "DDGetNetUserList" (ByVal licence_name As String, ByRef num_net_users As Integer,
ByVal nu_info_bytes() As Byte, ByVal num_info_structs As Integer, ByRef extended_error As Integer) As Integer
' call the correct dll depending on whether we are running 32-bit or 64-bit code
Function DDProtCheck(ByRef mydris As DRIS, ByVal data() As Byte) As Integer
If (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) Then
If (Environment.Is64BitProcess) Then
DDProtCheck = DDProtCheckWin64(mydris, data)
Else
DDProtCheck = DDProtCheckWin32(mydris, data)
End If
ElseIf (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) Then
DDProtCheck = DDProtCheckLin64(mydris, data)
ElseIf (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) Then
DDProtCheck = DDProtCheckMac64(mydris, data)
Else
DDProtCheck = -1 ' OS not supported
End If
End Function
Function DDGetNetUserList(ByVal licence_name As String, ByRef num_net_users As Integer, ByRef nu_info_array() As NU_INFO, ByVal num_info_structs As Integer, ByRef extended_error As Integer) As Integer
Dim i As Integer
Dim my_nu_info As New NU_INFO ' NB this only exists so we can get the size of the NU_INFO stucture
Dim nu_info_bytes(num_info_structs * Marshal.SizeOf(my_nu_info)) As Byte
Dim nu_info_one_struct(Marshal.SizeOf(my_nu_info)) As Byte
Dim MyGC As GCHandle
' call the function and get info as a byte array
If (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) Then
If (Environment.Is64BitProcess) Then
DDGetNetUserList = DDGetNetUserListWin64(licence_name, num_net_users, nu_info_bytes, num_info_structs, extended_error)
Else
DDGetNetUserList = DDGetNetUserListWin32(licence_name, num_net_users, nu_info_bytes, num_info_structs, extended_error)
End If
ElseIf (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) Then
DDGetNetUserList = DDGetNetUserListLin64(licence_name, num_net_users, nu_info_bytes, num_info_structs, extended_error)
Else
DDGetNetUserList = -1 ' OS not supported (this includes macOS)
End If
' convert byte array to an array of structs
For i = 0 To num_net_users - 1
nu_info_array(i) = New NU_INFO
Array.Copy(nu_info_bytes, i * Marshal.SizeOf(my_nu_info.GetType), nu_info_one_struct, 0, Marshal.SizeOf(my_nu_info.GetType))
MyGC = GCHandle.Alloc(nu_info_one_struct, GCHandleType.Pinned)
nu_info_array(i) = Marshal.PtrToStructure(MyGC.AddrOfPinnedObject, my_nu_info.GetType)
MyGC.Free()
Next
End Function
' Functions
Public Const PROTECTION_CHECK As Integer = 1 ' checks for dongle, check program params...
Public Const EXECUTE_ALGORITHM As Integer = 2 ' protection check + calculate answer for specified algorithm with specified inputs
Public Const WRITE_DATA_AREA As Integer = 3 ' protection check + writes dongle data area
Public Const READ_DATA_AREA As Integer = 4 ' protection check + reads dongle data area
Public Const ENCRYPT_USER_DATA As Integer = 5 ' protection check + the dongle will encrypt user data
Public Const DECRYPT_USER_DATA As Integer = 6 ' protection check + the dongle will decrypt user data
Public Const FAST_PRESENCE_CHECK As Integer = 7 ' checks for the presence of the correct dongle only with minimal security, no flags allowed
Public Const STOP_NET_USER As Integer = 8 ' stops a network user (a protection check is NOT performed)
' Flags
Public Const DEC_ONE_EXEC As Integer = 1 ' decrement execs by 1
Public Const DEC_MANY_EXECS As Integer = 2 ' decrement execs by number specified in execs
Public Const START_NET_USER As Integer = 4 ' starts a network user
Public Const USE_FUNCTION_ARGUMENT As Integer = 16 ' use the extra argument in the function for pointers
Public Const CHECK_LOCAL_FIRST As Integer = 32 ' always look in local ports before looking in network ports
Public Const CHECK_NETWORK_FIRST As Integer = 64 ' always look on the network before looking in local ports
Public Const USE_ALT_LICENCE_NAME As Integer = 128 ' use name specified in alt_licence_name instead of the default one
Public Const DONT_SET_MAXDAYS_EXPIRY As Integer = 256 ' if the max days expiry date has not been calculated then do not do it this time
Public Const MATCH_DONGLE_NUMBER As Integer = 512 ' restrict the search to match the dongle number specified in the DRIS
Public Const DONT_RETURN_FD_DRIVE As Integer = 1024 ' if an FD dongle has been detected then don't return the flash drive/mount name in the DRIS
Public Const NU_INFO_SIZE As Integer = (256 + 50 + 256 + 16) ' size of NU_INFO structure (for listing network users)
' ********************** useful functions for use in sample code ***************************
' use this function to set the alt_licence_name field of the DRIS
Public Sub SetAltLicenceName(ByVal mydris As DRIS, ByVal altlicencename As String)
Dim i, num_bytes As Integer
Dim ascii As New ASCIIEncoding
Dim temp As Byte()
temp = ascii.GetBytes(altlicencename)
num_bytes = ascii.GetByteCount(altlicencename)
For i = 0 To num_bytes - 1
mydris._alt_licence_name(i) = temp(i)
Next
mydris._alt_licence_name(num_bytes) = 0 'null-terminate string
End Sub
' use this function to read the prodcode field of the DRIS
Public Function GetProductCode(ByVal mydris As DRIS) As String
Dim ascii As New ASCIIEncoding
Dim i As Integer
For i = 0 To 11
If mydris._prodcode(i) = 0 Then
Exit For
End If
Next
Return ascii.GetString(mydris._prodcode, 0, i)
End Function
' use this function to read the fd_drive field of the DRIS
Public Function GetFDDrive(ByVal mydris As DRIS) As String
Dim ascii As New ASCIIEncoding
Dim i As Integer
For i = 0 To 127
If mydris._fd_drive(i) = 0 Then
Exit For
End If
Next
Return ascii.GetString(mydris._fd_drive, 0, i)
End Function
' copies an integer to offset "index" in trhe specified byte array
Public Sub Set4Bytes(ByVal data() As Byte, ByVal index As Integer, ByVal value As Integer)
Dim MyGC As GCHandle = GCHandle.Alloc(value, GCHandleType.Pinned)
Dim AddressOfValue As IntPtr = MyGC.AddrOfPinnedObject()
Marshal.Copy(AddressOfValue, data, index, 4)
MyGC.Free()
End Sub
' converts to DRIS structure to a byte array (so we can do encryption)
Public Sub DrisToByteArray(ByVal mydris As DRIS, ByVal data() As Byte)
Dim MyGC As GCHandle = GCHandle.Alloc(data, GCHandleType.Pinned)
Marshal.StructureToPtr(mydris, MyGC.AddrOfPinnedObject, False)
MyGC.Free()
End Sub
' converts a byte array to the DRIS structure (so we can do encryption)
Public Sub ByteArrayToDris(ByVal data() As Byte, ByRef mydris As DRIS)
Dim MyGC As GCHandle = GCHandle.Alloc(data, GCHandleType.Pinned)
mydris = Marshal.PtrToStructure(MyGC.AddrOfPinnedObject, mydris.GetType)
MyGC.Free()
End Sub
' initialise the DRIS with random values
Public Sub RandomSet(ByRef mydris As DRIS)
Dim temp_dris(Marshal.SizeOf(mydris) - 1) As Byte
Dim rnd As New Random
rnd.NextBytes(temp_dris)
ByteArrayToDris(temp_dris, mydris)
End Sub
End Module