Add Original SDK
This commit is contained in:
151
Dinkey Pro 7.6.1/Samples/Delphi/VCL/DinkeyChange/Change.dfm
Normal file
151
Dinkey Pro 7.6.1/Samples/Delphi/VCL/DinkeyChange/Change.dfm
Normal file
@@ -0,0 +1,151 @@
|
||||
object ChangeForm: TChangeForm
|
||||
Left = 192
|
||||
Top = 107
|
||||
Width = 345
|
||||
Height = 658
|
||||
Caption = 'ChangeTest'
|
||||
Color = clBtnFace
|
||||
Font.Charset = DEFAULT_CHARSET
|
||||
Font.Color = clWindowText
|
||||
Font.Height = -11
|
||||
Font.Name = 'MS Sans Serif'
|
||||
Font.Style = []
|
||||
OldCreateOrder = False
|
||||
PixelsPerInch = 96
|
||||
TextHeight = 13
|
||||
object Label1: TLabel
|
||||
Left = 16
|
||||
Top = 72
|
||||
Width = 123
|
||||
Height = 13
|
||||
Caption = 'Enter Diagnostic filename:'
|
||||
end
|
||||
object Label2: TLabel
|
||||
Left = 16
|
||||
Top = 168
|
||||
Width = 120
|
||||
Height = 13
|
||||
Caption = 'Enter short Update Code:'
|
||||
end
|
||||
object Label3: TLabel
|
||||
Left = 16
|
||||
Top = 264
|
||||
Width = 146
|
||||
Height = 13
|
||||
Caption = 'Enter path to Update Code file:'
|
||||
end
|
||||
object Label4: TLabel
|
||||
Left = 8
|
||||
Top = 528
|
||||
Width = 165
|
||||
Height = 13
|
||||
Caption = 'Demo Software Key Product Code:'
|
||||
end
|
||||
object DiagInfo: TButton
|
||||
Left = 64
|
||||
Top = 24
|
||||
Width = 209
|
||||
Height = 25
|
||||
Caption = 'Get Dongle Information'
|
||||
TabOrder = 0
|
||||
OnClick = DiagInfoClick
|
||||
end
|
||||
object DiagFilename: TEdit
|
||||
Left = 16
|
||||
Top = 88
|
||||
Width = 305
|
||||
Height = 21
|
||||
TabOrder = 1
|
||||
end
|
||||
object WriteDiags: TButton
|
||||
Left = 72
|
||||
Top = 120
|
||||
Width = 193
|
||||
Height = 25
|
||||
Caption = 'Write Diagnostics to File'
|
||||
TabOrder = 2
|
||||
OnClick = WriteDiagsClick
|
||||
end
|
||||
object UpdateCodeString: TEdit
|
||||
Left = 16
|
||||
Top = 184
|
||||
Width = 305
|
||||
Height = 21
|
||||
TabOrder = 3
|
||||
end
|
||||
object DoUpdateCodeString: TButton
|
||||
Left = 72
|
||||
Top = 216
|
||||
Width = 193
|
||||
Height = 25
|
||||
Caption = 'Make Changes'
|
||||
TabOrder = 4
|
||||
OnClick = DoUpdateCodeStringClick
|
||||
end
|
||||
object UpdateCodeFile: TEdit
|
||||
Left = 16
|
||||
Top = 280
|
||||
Width = 305
|
||||
Height = 21
|
||||
TabOrder = 5
|
||||
end
|
||||
object DoUpdateCodeFile: TButton
|
||||
Left = 72
|
||||
Top = 312
|
||||
Width = 193
|
||||
Height = 25
|
||||
Caption = 'Make Changes'
|
||||
TabOrder = 6
|
||||
OnClick = DoUpdateCodeFileClick
|
||||
end
|
||||
object RestoreFDLite: TButton
|
||||
Left = 72
|
||||
Top = 368
|
||||
Width = 193
|
||||
Height = 25
|
||||
Caption = 'Restore FD Lite'
|
||||
TabOrder = 7
|
||||
OnClick = DoRestoreFDLiteClick
|
||||
end
|
||||
object GetMachineID: TButton
|
||||
Left = 16
|
||||
Top = 424
|
||||
Width = 145
|
||||
Height = 25
|
||||
Caption = 'Get Machine ID'
|
||||
TabOrder = 8
|
||||
OnClick = DoGetMachineIDClick
|
||||
end
|
||||
object DownloadTempSWKey: TButton
|
||||
Left = 56
|
||||
Top = 480
|
||||
Width = 225
|
||||
Height = 25
|
||||
Caption = 'Download Temporary Software Key'
|
||||
TabOrder = 9
|
||||
OnClick = DoDownloadTempSWKeyClick
|
||||
end
|
||||
object ShowMachineID: TEdit
|
||||
Left = 168
|
||||
Top = 424
|
||||
Width = 153
|
||||
Height = 21
|
||||
TabOrder = 10
|
||||
end
|
||||
object DownloadDemoSWKey: TButton
|
||||
Left = 56
|
||||
Top = 576
|
||||
Width = 225
|
||||
Height = 25
|
||||
Caption = 'Download Demo Software Key'
|
||||
TabOrder = 11
|
||||
OnClick = DoDownloadDemoSWKeyClick
|
||||
end
|
||||
object SwkeyProdCode: TEdit
|
||||
Left = 8
|
||||
Top = 544
|
||||
Width = 305
|
||||
Height = 21
|
||||
TabOrder = 12
|
||||
end
|
||||
end
|
||||
340
Dinkey Pro 7.6.1/Samples/Delphi/VCL/DinkeyChange/Change.pas
Normal file
340
Dinkey Pro 7.6.1/Samples/Delphi/VCL/DinkeyChange/Change.pas
Normal file
@@ -0,0 +1,340 @@
|
||||
unit Change;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
|
||||
Dialogs, StdCtrls;
|
||||
|
||||
type
|
||||
TChangeForm = class(TForm)
|
||||
DiagInfo: TButton;
|
||||
Label1: TLabel;
|
||||
DiagFilename: TEdit;
|
||||
WriteDiags: TButton;
|
||||
UpdateCodeString: TEdit;
|
||||
Label2: TLabel;
|
||||
DoUpdateCodeString: TButton;
|
||||
UpdateCodeFile: TEdit;
|
||||
Label3: TLabel;
|
||||
DoUpdateCodeFile: TButton;
|
||||
RestoreFDLite: TButton;
|
||||
GetMachineID: TButton;
|
||||
DownloadTempSWKey: TButton;
|
||||
ShowMachineID: TEdit;
|
||||
DownloadDemoSWKey: TButton;
|
||||
SwkeyProdCode: TEdit;
|
||||
Label4: TLabel;
|
||||
procedure DiagInfoClick(Sender: TObject);
|
||||
procedure WriteDiagsClick(Sender: TObject);
|
||||
procedure DoUpdateCodeStringClick(Sender: TObject);
|
||||
procedure DoUpdateCodeFileClick(Sender: TObject);
|
||||
procedure DoRestoreFDLiteClick(Sender: TObject);
|
||||
procedure DoGetMachineIDClick(Sender: TObject);
|
||||
procedure DoDownloadTempSWKeyClick(Sender: TObject);
|
||||
procedure DoDownloadDemoSWKeyClick(Sender: TObject);
|
||||
private
|
||||
{ Private declarations }
|
||||
public
|
||||
{ Public declarations }
|
||||
end;
|
||||
|
||||
var
|
||||
ChangeForm: TChangeForm;
|
||||
|
||||
{ constants }
|
||||
const MAX_USB_DEVICES = 128; { maximum number of USB devices that can be attached to the system at one time }
|
||||
const MAX_PRODCODE_LEN = 8; { maximum length of a Product Code }
|
||||
|
||||
{ mask values }
|
||||
const TYPE_MASK_PRO = 1;
|
||||
const TYPE_MASK_FD = 2;
|
||||
const TYPE_MASK_ALL = TYPE_MASK_PRO or TYPE_MASK_FD;
|
||||
|
||||
const MODEL_MASK_LITE = 1;
|
||||
const MODEL_MASK_PLUS = 2;
|
||||
const MODEL_MASK_NET = 4;
|
||||
const MODEL_MASK_ALL = MODEL_MASK_LITE or MODEL_MASK_PLUS or MODEL_MASK_NET;
|
||||
const MODEL_MASK_DEFAULT = MODEL_MASK_PLUS or MODEL_MASK_NET;
|
||||
|
||||
{ type values for DCGetInfo (returned in the array) }
|
||||
const TYPE_PRO = 1;
|
||||
const TYPE_FD = 2;
|
||||
|
||||
{ model values for DCGetInfo (returned in the array) }
|
||||
const MODEL_LITE = 1;
|
||||
const MODEL_PLUS = 2;
|
||||
const MODEL_NET5 = 4;
|
||||
const MODEL_NETU = 7;
|
||||
|
||||
{ model values for DCDownloadDemoSoftwareKey }
|
||||
const SWKEY_MODEL_DEFAULT = -1; { NB this assumes that the Demo Software Key Template was created with only one valid dongle model }
|
||||
const SWKEY_MODEL_PRO_LITE = 0;
|
||||
const SWKEY_MODEL_PRO_PLUS = 1;
|
||||
const SWKEY_MODEL_PRO_NET = 2;
|
||||
const SWKEY_MODEL_FD_LITE = 3;
|
||||
const SWKEY_MODEL_FD_PLUS = 4;
|
||||
const SWKEY_MODEL_FD_NET = 5;
|
||||
|
||||
{ functions exported by DinkeyChange.dll }
|
||||
{$IFDEF WIN32}
|
||||
function DCGetInfo(type_mask, model_mask:LongInt; prodcode_mask:PAnsiChar; array_length:LongInt; num_found:PLongInt; type_array,model_array:pointer; prodcode_array:pointer; dongle_number_array:pointer; update_number_array: pointer) : LongInt; stdcall; external 'DinkeyChange.dll';
|
||||
function DCGetDiagnosticInfo(filename: PAnsiChar): LongInt; stdcall; external 'DinkeyChange.dll';
|
||||
function DCDoUpdateCodeString(UpdateCodeString: PAnsiChar; confirmation_code, extended_error: PLongInt): LongInt; stdcall; external 'DinkeyChange.dll';
|
||||
function DCDoUpdateCodeFromFile(filename: PAnsiChar; confirmation_code, extended_error: PLongInt): LongInt; stdcall; external 'DinkeyChange.dll';
|
||||
function DCRestoreDinkeyFDLite(): LongInt; stdcall; external 'DinkeyChange.dll';
|
||||
function DCGetMachineID(machineID:PLongWord; extended_error:PLongInt): LongInt; stdcall; external 'DinkeyChange.dll';
|
||||
function DCDownloadTempSoftwareKey(machineID:LongWord; extended_error:PLongInt): LongInt; stdcall; external 'DinkeyChange.dll';
|
||||
function DCDownloadDemoSoftwareKey(machineID:LongWord; prodcode: PAnsiChar; model: LongInt; extended_error:PLongInt): LongInt; stdcall; external 'DinkeyChange.dll';
|
||||
{$ELSE}
|
||||
function DCGetInfo(type_mask, model_mask:LongInt; prodcode_mask:PAnsiChar; array_length:LongInt; num_found:PLongInt; type_array,model_array:pointer; prodcode_array:pointer; dongle_number_array:pointer; update_number_array: pointer) : LongInt; stdcall; external 'DinkeyChange64.dll';
|
||||
function DCGetDiagnosticInfo(filename: PAnsiChar): LongInt; stdcall; external 'DinkeyChange64.dll';
|
||||
function DCDoUpdateCodeString(UpdateCodeString: PAnsiChar; confirmation_code, extended_error: PLongInt): LongInt; stdcall; external 'DinkeyChange64.dll';
|
||||
function DCDoUpdateCodeFromFile(filename: PAnsiChar; confirmation_code, extended_error: PLongInt): LongInt; stdcall; external 'DinkeyChange64.dll';
|
||||
function DCRestoreDinkeyFDLite(): LongInt; stdcall; external 'DinkeyChange64.dll';
|
||||
function DCGetMachineID(machineID:PLongWord; extended_error:PLongInt): LongInt; stdcall; external 'DinkeyChange64.dll';
|
||||
function DCDownloadTempSoftwareKey(machineID:LongWord; extended_error:PLongInt): LongInt; stdcall; external 'DinkeyChange64.dll';
|
||||
function DCDownloadDemoSoftwareKey(machineID:LongWord; prodcode: PAnsiChar; model: LongInt; extended_error:PLongInt): LongInt; stdcall; external 'DinkeyChange64.dll';
|
||||
{$ENDIF}
|
||||
|
||||
implementation
|
||||
|
||||
{$R *.dfm}
|
||||
|
||||
{ displays messages for the most common errors when updating the code.
|
||||
You will want to change this for your code }
|
||||
procedure DisplayError(ret_code, extended_error:integer);
|
||||
var
|
||||
display : string;
|
||||
begin
|
||||
case ret_code of
|
||||
401: display := 'Error! No dongles detected that meet the search criteria.';
|
||||
409: display := 'Error! The dongle detected has not been programmed by DinkeyAdd.';
|
||||
758: display := 'Error! Cannot open the Update Code file specified.';
|
||||
759: display := 'Error! The file specified is not a valid Update Code file.';
|
||||
762..764: display := 'Error! Update Code is not in a correct format / update code file is corrupt.';
|
||||
765: display := 'Error! The Update Code does not match any dongle attached to your machine.';
|
||||
766: display := 'Error! The update number for this Update Code is too high. You need to first enter an update code that was previously sent to you.';
|
||||
767: display := 'Error! You have already entered this Update Code.';
|
||||
1905: display := 'Error! There is no Software Key available for download.';
|
||||
1907: display := 'Error! The Temporary Software Key has expired. Cannot download it.';
|
||||
1910: display := 'Error! The Software Key has already been downloaded.';
|
||||
1921: display := 'Error! You specified the default model but there is more than one model available. You need to specify a specific dongle model.';
|
||||
1922: display := 'Error! The model you requested is not available.';
|
||||
1923: display := 'Error! The Demo Software Key Template has been disabled.';
|
||||
1924: display := 'Error! You have run out of Demo Software Key activations. You need to order some more.';
|
||||
else
|
||||
display := 'An error occurred checking the dongle. Error: ' + IntToStr(ret_code) + '. Extended Error code: ' + IntToStr(extended_error);
|
||||
end;
|
||||
messagedlg(display, mtError, [mbok], 0);
|
||||
end;
|
||||
|
||||
procedure TChangeForm.DiagInfoClick(Sender: TObject);
|
||||
var
|
||||
i : Integer;
|
||||
sType, sModel, sProdCode, display : string;
|
||||
ret_code, num_found : LongInt;
|
||||
type_array, model_array, update_number_array: packed array[0..(MAX_USB_DEVICES-1)] of LongInt;
|
||||
dongle_number_array: packed array[0..(MAX_USB_DEVICES-1)] of LongWord;
|
||||
prodcode_array: packed array[0..(MAX_USB_DEVICES-1)] of packed array[0..MAX_PRODCODE_LEN] of AnsiChar;
|
||||
begin
|
||||
|
||||
{ find dongle information for all dongle types, Plus & Net models, for all product codes
|
||||
NB In practice you will probably want to set the prodcode_mask to the value of your product code }
|
||||
|
||||
ret_code := DCGetInfo(TYPE_MASK_ALL, MODEL_MASK_DEFAULT, nil, MAX_USB_DEVICES, @num_found, @type_array, @model_array, @prodcode_array, @dongle_number_array, @update_number_array);
|
||||
|
||||
{ check error code and display error if an error occurs }
|
||||
if (ret_code = 401) then
|
||||
begin
|
||||
messagedlg('No dongles detected matching the search criteria specified', mtError, [mbok], 0);
|
||||
exit;
|
||||
end
|
||||
else if (ret_code <> 0) then
|
||||
begin
|
||||
messagedlg('Error ' + IntToStr(ret_code) + ' getting dongle information', mtError, [mbok], 0);
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ display info from the dongle detected }
|
||||
display := '';
|
||||
for i := 0 to num_found-1 do
|
||||
begin
|
||||
{ get type of dongle }
|
||||
if (type_array[i] = TYPE_PRO) then
|
||||
sType := 'Pro'
|
||||
else
|
||||
sType := 'FD';
|
||||
|
||||
{ get model of dongle }
|
||||
if (model_array[i] = MODEL_LITE) then
|
||||
sModel := 'Lite'
|
||||
else if (model_array[i] = MODEL_PLUS) then
|
||||
sModel := 'Plus'
|
||||
else
|
||||
sModel := 'Net';
|
||||
|
||||
sProdCode := String(prodcode_array[i]);
|
||||
|
||||
display := display + IntToStr(i+1) + '. Dinkey ' + sType + ' ' + sModel + ' with dongle number: ' + IntToStr(dongle_number_array[i]) +
|
||||
', product code: ' + sProdCode + ', update number: ' + IntToStr(update_number_array[i]) + #13#10;
|
||||
end;
|
||||
messagedlg(display, mtInformation, [mbok], 0);
|
||||
|
||||
end;
|
||||
|
||||
{ write dongle diagnostics to file }
|
||||
procedure TChangeForm.WriteDiagsClick(Sender: TObject);
|
||||
var
|
||||
ret_code: longInt;
|
||||
diag_file : array[0..255] of AnsiChar;
|
||||
|
||||
begin
|
||||
StrPCopy(diag_file, AnsiString(DiagFilename.Text)); { to get a null-terminated string }
|
||||
ret_code := DCGetDiagnosticInfo(@diag_file);
|
||||
|
||||
{ check error code and display error if an error occurs }
|
||||
if (ret_code = 754) then
|
||||
begin
|
||||
messagedlg('Could not create the diagnostic file. Please check that the path exists: ' + DiagFileName.Text, mtError, [mbok], 0);
|
||||
exit;
|
||||
end
|
||||
else if (ret_code <> 0) then
|
||||
begin
|
||||
messagedlg('Error ' + IntToStr(ret_code) + 'writing diagnostic file.', mtError, [mbok], 0);
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ display success }
|
||||
messagedlg('Diagnostic file written successfully.', mtInformation, [mbok], 0);
|
||||
end;
|
||||
|
||||
{ update dongle with short update code string typed-in }
|
||||
procedure TChangeForm.DoUpdateCodeStringClick(Sender: TObject);
|
||||
var
|
||||
ret_code, confirmation_code, extended_error: LongInt;
|
||||
update_code : array[0..255] of AnsiChar;
|
||||
begin
|
||||
StrPCopy(update_code, AnsiString(UpdateCodeString.Text)); { to get a null-terminated string }
|
||||
ret_code := DCDoUpdateCodeString(@update_code, @confirmation_code, @extended_error);
|
||||
|
||||
if (ret_code <> 0) then
|
||||
begin
|
||||
DisplayError(ret_code, extended_error);
|
||||
exit;
|
||||
end;
|
||||
|
||||
messagedlg('Dongle updated successfully!' + #13#10 + 'Confirmation code is : ' + IntToHex(confirmation_code, 4), mtInformation, [mbok], 0);
|
||||
end;
|
||||
|
||||
{ update dongle with update code in file specified }
|
||||
procedure TChangeForm.DoUpdateCodeFileClick(Sender: TObject);
|
||||
var
|
||||
ret_code, confirmation_code, extended_error: LongInt;
|
||||
update_code_file : array[0..255] of AnsiChar;
|
||||
begin
|
||||
StrPCopy(update_code_file, AnsiString(UpdateCodeFile.Text)); { to get a null-terminated string }
|
||||
ret_code := DCDoUpdateCodeFromFile(@update_code_file, @confirmation_code, @extended_error);
|
||||
|
||||
if (ret_code <> 0) then
|
||||
begin
|
||||
DisplayError(ret_code, extended_error);
|
||||
exit;
|
||||
end;
|
||||
|
||||
messagedlg('Dongle updated successfully!' + #13#10 + 'Confirmation code is : ' + IntToHex(confirmation_code, 4), mtInformation, [mbok], 0);
|
||||
end;
|
||||
|
||||
{ attempt to restore Dinkey FD Lite dongle }
|
||||
procedure TChangeForm.DoRestoreFDLiteClick(Sender: TObject);
|
||||
var
|
||||
ret_code: LongInt;
|
||||
begin
|
||||
ret_code := DCRestoreDinkeyFDlite();
|
||||
|
||||
if (ret_code <> 0) then
|
||||
begin
|
||||
DisplayError(ret_code, 0);
|
||||
exit;
|
||||
end;
|
||||
|
||||
messagedlg('Dinkey FD Lite dongle restored successfully!', mtInformation, [mbok], 0);
|
||||
end;
|
||||
|
||||
{ Get Machine ID (for use with Temporary Software Key) }
|
||||
procedure TChangeForm.DoGetMachineIDClick(Sender: TObject);
|
||||
var
|
||||
ret_code, extended_error: LongInt;
|
||||
machineID: LongWord;
|
||||
begin
|
||||
ret_code := DCGetMachineID(@machineID, @extended_error);
|
||||
|
||||
if (ret_code <> 0) then
|
||||
begin
|
||||
DisplayError(ret_code, extended_error);
|
||||
exit;
|
||||
end;
|
||||
{don't display mesage, just display the Machine ID }
|
||||
ShowMachineID.Text := IntToHex(machineID, 8);
|
||||
end;
|
||||
|
||||
{ Download Temporary Software Key }
|
||||
procedure TChangeForm.DoDownloadTempSWKeyClick(Sender: TObject);
|
||||
var
|
||||
ret_code, extended_error: LongInt;
|
||||
machineID: LongWord;
|
||||
begin
|
||||
{ first get the machine ID... }
|
||||
ret_code := DCGetMachineID(@machineID, @extended_error);
|
||||
|
||||
if (ret_code <> 0) then
|
||||
begin
|
||||
DisplayError(ret_code, extended_error);
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ ... then try to download the temporary software key }
|
||||
ret_code := DCDownloadTempSoftwareKey(machineID, @extended_error);
|
||||
|
||||
if (ret_code <> 0) then
|
||||
begin
|
||||
DisplayError(ret_code, extended_error);
|
||||
exit;
|
||||
end;
|
||||
|
||||
messagedlg('Temporary Software Key Downloaded Successfully!', mtInformation, [mbok], 0);
|
||||
end;
|
||||
|
||||
{ Download Demo Software Key }
|
||||
procedure TChangeForm.DoDownloadDemoSWKeyClick(Sender: TObject);
|
||||
var
|
||||
ret_code, extended_error: LongInt;
|
||||
machineID: LongWord;
|
||||
prodcode : array[0..9] of AnsiChar;
|
||||
begin
|
||||
{ first get the machine ID... }
|
||||
ret_code := DCGetMachineID(@machineID, @extended_error);
|
||||
|
||||
if (ret_code <> 0) then
|
||||
begin
|
||||
DisplayError(ret_code, extended_error);
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ ... then try to download the demo software key }
|
||||
{ NB we are assuming only one dongle model is set in the Demo Software Template. }
|
||||
{ If multiple models are set you will also need to specify the exact model }
|
||||
StrPCopy(prodcode, AnsiString(SwkeyProdCode.Text)); { to get a null-terminated string }
|
||||
ret_code := DCDownloadDemoSoftwareKey(machineID, @prodcode, SWKEY_MODEL_DEFAULT, @extended_error);
|
||||
|
||||
if (ret_code <> 0) then
|
||||
begin
|
||||
DisplayError(ret_code, extended_error);
|
||||
exit;
|
||||
end;
|
||||
|
||||
messagedlg('Demo Software Key Downloaded Successfully!', mtInformation, [mbok], 0);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
program ChangeTest;
|
||||
|
||||
uses
|
||||
Forms,
|
||||
Change in 'Change.pas' {ChangeForm};
|
||||
|
||||
{$R *.res}
|
||||
|
||||
begin
|
||||
Application.Initialize;
|
||||
Application.CreateForm(TChangeForm, ChangeForm);
|
||||
Application.Run;
|
||||
end.
|
||||
22
Dinkey Pro 7.6.1/Samples/Delphi/VCL/DinkeyChange/README.txt
Normal file
22
Dinkey Pro 7.6.1/Samples/Delphi/VCL/DinkeyChange/README.txt
Normal file
@@ -0,0 +1,22 @@
|
||||
ChangeTest - sample code to call DinkeyChange.dll in Delphi
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This project is written in Delphi 6 but will also work in more recent versions
|
||||
(they will upgrade the Project to the latest version).
|
||||
|
||||
The sample code contains 7 functions. Just use which ever functions are most
|
||||
appropriate and customise in your own way. The sample code is just a guide.
|
||||
As none of the parameters are sensitive then there is no need to implement
|
||||
strong security in calling DinkeyChange.
|
||||
|
||||
It is also recommended that you rename DinkeyChange.dll to a name of your choice. In
|
||||
this case you will need to modify the dll name in the change.pas file.
|
||||
|
||||
Important Note - you will not be able to debug your program after our API has been called.
|
||||
Our strong anti-debug code will cause the debugger to throw an exception. You will also
|
||||
not be able to run your program from the development platform either as Delphi still has
|
||||
the Debugger running. You should run it instead from My Computer or from the command line.
|
||||
|
||||
However, if you do need to debug your code you can use our debug module for DinkeyChange:
|
||||
DinkeyChangeDebug.dll. So, you can use DinkeyChange.dll for your release build
|
||||
and DinkeyChangeDebug.dll for your debug build.
|
||||
14
Dinkey Pro 7.6.1/Samples/Delphi/VCL/Runtime/ObjTest.dpr
Normal file
14
Dinkey Pro 7.6.1/Samples/Delphi/VCL/Runtime/ObjTest.dpr
Normal file
@@ -0,0 +1,14 @@
|
||||
program ObjTest;
|
||||
|
||||
uses
|
||||
Forms,
|
||||
apitest in 'apitest.pas' {Form1},
|
||||
dris in 'dris.pas';
|
||||
|
||||
{$R *.res}
|
||||
|
||||
begin
|
||||
Application.Initialize;
|
||||
Application.CreateForm(TForm1, Form1);
|
||||
Application.Run;
|
||||
end.
|
||||
97
Dinkey Pro 7.6.1/Samples/Delphi/VCL/Runtime/README.txt
Normal file
97
Dinkey Pro 7.6.1/Samples/Delphi/VCL/Runtime/README.txt
Normal file
@@ -0,0 +1,97 @@
|
||||
Sample code to call Runtime modules in Delphi
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This project is written in Delphi 6 but will work in more recent versions
|
||||
(they will upgrade the Project to the latest version. For Delphi XE or earlier
|
||||
you will need to delete the reference to System.UITypes).
|
||||
|
||||
If you want to create multi-platform or multi-device applications please use
|
||||
the FireMonkey projects instead.
|
||||
|
||||
The source files in the project are:
|
||||
|
||||
File name Description
|
||||
apitest.pas main source code file for Delphi
|
||||
dris.pas contains DRIS structure definition and other definitions.
|
||||
apitest.dfm
|
||||
ObjTest.dpr project file
|
||||
|
||||
The idea is to include the dris.pas file in your project and use/modify which ever
|
||||
functions from apitest.pas you feel are appropriate.
|
||||
|
||||
This sample can also compile to 64-bit code (if your version of Delphi supports 64-bit
|
||||
code i.e. Delphi XE2 and higher). Just Add the 64-bit Platform to the project.
|
||||
|
||||
In order for the projects to compile without modification we have also installed in
|
||||
this folder the relevant object modules for Delphi:
|
||||
|
||||
dpwin32_omf.obj for 32-bit builds
|
||||
dpwin64_delphi.obj for 64-bit builds
|
||||
|
||||
The sample code will detect whether you are building in 32-bit or 64-bit and compile
|
||||
the appropriate Windows module.
|
||||
|
||||
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).
|
||||
|
||||
The project currently links with our static protection modules. If you want to link to
|
||||
our dynamic protection modules instead (dpwin32.dll or dpwin64.dll) then you need
|
||||
to modify dris.pas as follows:
|
||||
|
||||
1) Modify the declarations of DDProtCheck and DDGetNetUserList so that they refer
|
||||
to the appropriate runtime DLL.
|
||||
|
||||
2) Delete the code that links the object module.
|
||||
|
||||
We have made these changes and put them in a file called dris_for_dll.pas.
|
||||
Use this in your project instead of dris.pas.
|
||||
|
||||
It is also recommended that you rename dpwin32.dll to a name of your choice. In
|
||||
this case you will need to modify the dll name in the dris.pas file.
|
||||
|
||||
Note - if you link the static module dpwin32_omf.obj then you should protect your program.
|
||||
If you are linking to dpwin32.dll then you need to protect dpwin32.dll and *not* your program.
|
||||
Because your program is linked to the DLL it is protected. The protected DLL will need to be
|
||||
in the same folder as your compiled program for it to run correctly.
|
||||
|
||||
Debug Modules
|
||||
~~~~~~~~~~~~~~
|
||||
Note - once your program (or dpwin32.dll) is protected you will not be able to debug
|
||||
your program - after our API has been called. Our strong anti-debug code will cause
|
||||
the debugger to throw an exception. You will also not be able to run your program from
|
||||
the development platform either as Delphi still has the Debugger running. You should run
|
||||
it instead from My Computer or from the command line. If you do want to debug your code
|
||||
then you can use our debug module: dpwin32_omf_debug.obj (or dpwin32debug.dll), but these
|
||||
should not be used for release.
|
||||
|
||||
You could setup your project so that your code links the debug module during your debug build
|
||||
and the standard module when you produce your release code.
|
||||
|
||||
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.
|
||||
29
Dinkey Pro 7.6.1/Samples/Delphi/VCL/Runtime/apitest.dfm
Normal file
29
Dinkey Pro 7.6.1/Samples/Delphi/VCL/Runtime/apitest.dfm
Normal file
@@ -0,0 +1,29 @@
|
||||
object Form1: TForm1
|
||||
Left = 386
|
||||
Top = 317
|
||||
Width = 372
|
||||
Height = 265
|
||||
Caption = 'Form1'
|
||||
Color = clBtnFace
|
||||
Font.Charset = DEFAULT_CHARSET
|
||||
Font.Color = clWindowText
|
||||
Font.Height = -11
|
||||
Font.Name = 'MS Sans Serif'
|
||||
Font.Style = []
|
||||
OldCreateOrder = False
|
||||
PixelsPerInch = 96
|
||||
TextHeight = 13
|
||||
object Label1: TLabel
|
||||
Left = 104
|
||||
Top = 88
|
||||
Width = 146
|
||||
Height = 37
|
||||
Caption = 'It Worked!'
|
||||
Font.Charset = DEFAULT_CHARSET
|
||||
Font.Color = clWindowText
|
||||
Font.Height = -32
|
||||
Font.Name = 'MS Sans Serif'
|
||||
Font.Style = []
|
||||
ParentFont = False
|
||||
end
|
||||
end
|
||||
874
Dinkey Pro 7.6.1/Samples/Delphi/VCL/Runtime/apitest.pas
Normal file
874
Dinkey Pro 7.6.1/Samples/Delphi/VCL/Runtime/apitest.pas
Normal file
@@ -0,0 +1,874 @@
|
||||
unit apitest;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
|
||||
Dialogs, StdCtrls, System.UITypes, { !!!! for Delphi XE and earlier remove System.UITypes }
|
||||
dris; { contains the DRIS structure declaration }
|
||||
|
||||
type
|
||||
TForm1 = class(TForm)
|
||||
Label1: TLabel;
|
||||
private
|
||||
{ Private declarations }
|
||||
public
|
||||
{ Public declarations }
|
||||
end;
|
||||
|
||||
var
|
||||
Form1: TForm1;
|
||||
|
||||
implementation
|
||||
|
||||
{$R *.dfm}
|
||||
|
||||
{ !! 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 }
|
||||
|
||||
{ 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. To choose which function
|
||||
this code uses see the startup code at the bottom of this file.
|
||||
|
||||
this file contains 11 protection-check functions.
|
||||
longint ProtCheck(); a standard protection check
|
||||
longint ProtCheckWithAlg(); a protection check & executing an Algorithm
|
||||
longint WriteBytes(); a protection check & write data to the dongle
|
||||
longint ReadBytes(); a protection check & read data from the dongle
|
||||
longint 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
|
||||
longint ProtCheckEnc(); a standard protection check
|
||||
longint ProtCheckWithAlgEnc(); a protection check & executing an Algorithm
|
||||
longint WriteBytesEnc(); a protection check & write data to the dongle
|
||||
longint ReadBytesEnc(); a protection check & read data from the dongle
|
||||
longint EncryptUserDataEnc(); a protection check & encrypting data and then decrypting the data
|
||||
|
||||
longint DisplayNetUsers(net_users, model); this function displays the current network users
|
||||
|
||||
If you are using Dinkey Lite then you can only use 4 functions:
|
||||
ProtCheck, ProtCheckWithAlg, ProtCheckEnc, ProtCheckWithAlgEnc
|
||||
}
|
||||
|
||||
const MY_SDSN = 10101; { !!!! change this value to be the value of your SDSN (demo = 10101) }
|
||||
const MY_PRODCODE = 'DEMO';
|
||||
|
||||
{ this procedure initialises the DRIS with random bytes }
|
||||
procedure random_set(data: PByte; length: integer);
|
||||
var
|
||||
i : integer;
|
||||
begin
|
||||
Randomize();
|
||||
for i := 0 to length-1 do
|
||||
begin
|
||||
data^ := Random(256);
|
||||
Inc(data); { increment the pointer so we can access the next byte }
|
||||
end;
|
||||
end;
|
||||
|
||||
{ displays messages for the most common errors. You will want to change this for your code }
|
||||
procedure DisplayError(ret_code, extended_error:integer);
|
||||
var
|
||||
display : string;
|
||||
begin
|
||||
case ret_code of
|
||||
401: display := 'Error! No dongles detected!';
|
||||
403: display := 'Error! The dongle detected has a different type to the one specified in DinkeyAdd.';
|
||||
404: display := 'Error! The dongle detected has a different model to those specified in DinkeyAdd.';
|
||||
409: display := 'Error! The dongle detected has not been programmed by DinkeyAdd.';
|
||||
410: display := 'Error! The dongle detected has a different Product Code to the one specified in DinkeyAdd.';
|
||||
411: display := 'Error! The dongle detected does not contain the licence associated with this program.';
|
||||
413: display := 'Error! This program has not been protected by DinkeyAdd. For guidance please read the DinkeyAdd chapter of the Dinkey manual.';
|
||||
417: display := '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.';
|
||||
423: display := 'Error! The number of network users has been exceeded.';
|
||||
435: display := 'Error! DinkeyServer has not been detected on the network.';
|
||||
922: display := 'Error! The Software Key has expired.';
|
||||
else
|
||||
display := 'An error occurred checking the dongle. Error: ' + IntToStr(ret_code) + '. Extended Error code: ' + IntToStr(extended_error);
|
||||
end;
|
||||
messagedlg(display, mtError, [mbok], 0);
|
||||
end;
|
||||
|
||||
{ ************************* our 11 functions follow *************************** }
|
||||
|
||||
{ *********************** 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, model : LongInt) : LongInt;
|
||||
var
|
||||
display : string;
|
||||
nu_info: packed array[0..99] of nu_infoType; { !!!! this assumes that you will display max. 100 net users }
|
||||
i, max_net_users, num_net_users, extended_error : LongInt;
|
||||
|
||||
begin
|
||||
if (net_users = -1) then
|
||||
begin
|
||||
max_net_users := 100; { if unlimited network users are allowed then display up to 100 users (for example) If you want more than 1000 net users you need to change the value above}
|
||||
end
|
||||
else
|
||||
begin
|
||||
max_net_users := net_users;
|
||||
end;
|
||||
|
||||
if (net_users = 0) then { no network users are allowed, so nothing to do! }
|
||||
begin
|
||||
result := 0;
|
||||
exit;
|
||||
end;
|
||||
|
||||
if (model < 3) then
|
||||
begin
|
||||
messagedlg('A network dongle has not been detected. Therefore you cannot display the network users.', mtError, [mbok], 0);
|
||||
result := -1;
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ now get net users }
|
||||
result := DDGetNetUserList(NIL, @num_net_users, @nu_info, max_net_users, @extended_error);
|
||||
|
||||
if (result <> 0) then
|
||||
begin
|
||||
messagedlg('Error ' + IntToStr(result) + '/' + IntToStr(extended_error) + ' finding network user information.', mtError, [mbok], 0);
|
||||
end
|
||||
else
|
||||
begin
|
||||
display:= 'number of net users: ' + IntToStr(num_net_users) + #13#10;
|
||||
for i := 0 to num_net_users-1 do
|
||||
begin
|
||||
display := display + IntToStr(i+1) + '. licence: ' + String(nu_info[i].licenceName) + ', user: ' + String(nu_info[i].userName) +
|
||||
', computer: ' + String(nu_info[i].computerName) + ', ipaddress: ' + String(nu_info[i].ipAddress) + #13#10;
|
||||
end;
|
||||
messagedlg(display, mtInformation, [mbok], 0);
|
||||
end;
|
||||
end;
|
||||
|
||||
{ ************************** ProtCheck *************************************** }
|
||||
Function ProtCheck : LongInt;
|
||||
var
|
||||
dris: drisType;
|
||||
|
||||
begin
|
||||
{ set the DRIS to have random values }
|
||||
random_set(@dris, SizeOf(dris));
|
||||
{ then set the values we want to use }
|
||||
Move(AnsiString('DRIS'), dris.header, 4);
|
||||
dris.size:= 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 dongle-checking code }
|
||||
result := DDProtCheck(@dris, NIL);
|
||||
|
||||
if (result <> 0) then
|
||||
begin
|
||||
DisplayError(result, dris.ext_err); { display messages for any errors that have occurred }
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ later in your code you can check other values in the DRIS... }
|
||||
|
||||
if (dris.sdsn <> MY_SDSN) then
|
||||
begin
|
||||
messagedlg('Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.', mtError, [mbok], 0);
|
||||
result := -1;
|
||||
exit;
|
||||
end;
|
||||
|
||||
if (dris.prodcode <> AnsiString(MY_PRODCODE)) then
|
||||
begin
|
||||
messagedlg('Incorrect Product Code! Please modify your source code so that MY_PRODCODE is set to be the Product Code in the dongle.', mtError, [mbok], 0);
|
||||
result := -1;
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ later on in your program you can check the return code again }
|
||||
if (dris.ret_code <> 0) then
|
||||
begin
|
||||
messagedlg('Dinkey Dongle protection error.', mtError, [mbok], 0);
|
||||
result := -1;
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ 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); }
|
||||
end;
|
||||
|
||||
{ ************************** 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).
|
||||
If you are using Dinkey Lite the copy the source code from DinkeyLook }
|
||||
Function MyAlgorithm(a,b,c,d,e,f,g,h:LongInt):LongInt;
|
||||
begin
|
||||
MyAlgorithm:= a + b + c + d + e + f + g + h;
|
||||
end;
|
||||
|
||||
{ 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 copy source code from DinkeyLook}
|
||||
Function ProtCheckWithAlg : LongInt;
|
||||
var
|
||||
dris: drisType;
|
||||
|
||||
begin
|
||||
{ set the DRIS to have random values }
|
||||
random_set(@dris, SizeOf(dris));
|
||||
{ then set the values we want to use }
|
||||
Move(AnsiString('DRIS'), dris.header, 4);
|
||||
dris.size:= 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 algorithm 1 (you do not need to specify this field if you are only using Lite models) }
|
||||
{ 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 dongle-checking code }
|
||||
result := DDProtCheck(@dris, NIL);
|
||||
|
||||
if (result <> 0) then
|
||||
begin
|
||||
DisplayError(result, dris.ext_err); { display messages for any errors that have occurred }
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ later in your code you can check other values in the DRIS... }
|
||||
|
||||
if (dris.sdsn <> MY_SDSN) then
|
||||
begin
|
||||
messagedlg('Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.', mtError, [mbok], 0);
|
||||
result := -1;
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ later on in your program you can check the return code again }
|
||||
if (dris.ret_code <> 0) then
|
||||
begin
|
||||
messagedlg('Dinkey Dongle protection error.', mtError, [mbok], 0);
|
||||
result := -1;
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ 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
|
||||
begin
|
||||
messagedlg('Dinkey protection error! You have not patched your algorithm in the MyAlgorithm routine', mtError, [mbok], 0);
|
||||
result := -1;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ ************************** WriteBytes *************************************** }
|
||||
{ This writes the Data "Hello, World" 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 21 bytes long. }
|
||||
|
||||
Function WriteBytes : LongInt;
|
||||
var
|
||||
dris: drisType;
|
||||
DataToWrite : array[0..13] of AnsiChar;
|
||||
|
||||
begin
|
||||
{ set the DRIS to have random values }
|
||||
random_set(@dris, SizeOf(dris));
|
||||
{ then set the values we want to use }
|
||||
Move(AnsiString('DRIS'), dris.header, 4);
|
||||
dris.size:= SizeOf(dris);
|
||||
dris.myfunction:= WRITE_DATA_AREA; { standard protection check & write data}
|
||||
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.rw_offset := 7;
|
||||
dris.rw_length := 13;
|
||||
DataToWrite := 'Hello, World!'; { string to write }
|
||||
dris.rw_data_ptr := Addr(DataToWrite);
|
||||
|
||||
{ call dongle-checking code }
|
||||
result := DDProtCheck(@dris, NIL);
|
||||
|
||||
if (result <> 0) then
|
||||
begin
|
||||
DisplayError(result, dris.ext_err); { display messages for any errors that have occurred }
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ later in your code you can check other values in the DRIS... }
|
||||
|
||||
if (dris.sdsn <> MY_SDSN) then
|
||||
begin
|
||||
messagedlg('Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.', mtError, [mbok], 0);
|
||||
result := -1;
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ later on in your program you can check the return code again }
|
||||
if (dris.ret_code <> 0) then
|
||||
begin
|
||||
messagedlg('Dinkey Dongle protection error.', mtError, [mbok], 0);
|
||||
result := -1;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ ************************** ReadBytes *************************************** }
|
||||
{ This reads 14 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 21 bytes long.
|
||||
In order for the data to be displayed properly by this routine it will need to be text data }
|
||||
Function ReadBytes : LongInt;
|
||||
var
|
||||
dris: drisType;
|
||||
DataToRead : array[0..13] of AnsiChar;
|
||||
display : string;
|
||||
|
||||
begin
|
||||
{ set the DRIS to have random values }
|
||||
random_set(@dris, SizeOf(dris));
|
||||
{ then set the values we want to use }
|
||||
Move(AnsiString('DRIS'), dris.header, 4);
|
||||
dris.size:= SizeOf(dris);
|
||||
dris.myfunction:= READ_DATA_AREA; { standard protection check & write data}
|
||||
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.rw_offset := 7;
|
||||
dris.rw_length := 13; { we will add null termination after reading }
|
||||
dris.rw_data_ptr := Addr(DataToRead);
|
||||
|
||||
{ call dongle-checking code }
|
||||
result := DDProtCheck(@dris, NIL);
|
||||
|
||||
if (result <> 0) then
|
||||
begin
|
||||
DisplayError(result, dris.ext_err); { display messages for any errors that have occurred }
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ later in your code you can check other values in the DRIS... }
|
||||
|
||||
if (dris.sdsn <> MY_SDSN) then
|
||||
begin
|
||||
messagedlg('Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.', mtError, [mbok], 0);
|
||||
result := -1;
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ later on in your program you can check the return code again }
|
||||
if (dris.ret_code <> 0) then
|
||||
begin
|
||||
messagedlg('Dinkey Dongle protection error.', mtError, [mbok], 0);
|
||||
result := -1;
|
||||
exit;
|
||||
end;
|
||||
|
||||
DataToRead[13] := Chr(0); { null end of string }
|
||||
display := 'Dinkey Dongle data area contains: ' + DataToRead;
|
||||
messagedlg(display, mtInformation, [mbok], 0);
|
||||
end;
|
||||
|
||||
{ ************************** 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 }
|
||||
Function EncryptUserData : LongInt;
|
||||
var
|
||||
dris: drisType;
|
||||
display : string;
|
||||
DataString : array[0..13] of AnsiChar;
|
||||
|
||||
begin
|
||||
{ set the DRIS to have random values }
|
||||
random_set(@dris, SizeOf(dris));
|
||||
{ then set the values we want to use }
|
||||
Move(AnsiString('DRIS'), dris.header, 4);
|
||||
dris.size:= SizeOf(dris);
|
||||
dris.myfunction:= ENCRYPT_USER_DATA; { standard protection check & encrypt data }
|
||||
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.data_crypt_key_num := 1;
|
||||
dris.rw_length := 13;
|
||||
DataString := 'Hello, World!'; { string to encrypt }
|
||||
dris.rw_data_ptr := Addr(DataString);
|
||||
|
||||
{ call dongle-checking code }
|
||||
result := DDProtCheck(@dris, NIL);
|
||||
|
||||
if (result <> 0) then
|
||||
begin
|
||||
DisplayError(result, dris.ext_err); { display messages for any errors that have occurred }
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ ... 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 }
|
||||
random_set(@dris, SizeOf(dris));
|
||||
{ then set the values we want to use }
|
||||
Move(AnsiString('DRIS'), dris.header, 4);
|
||||
dris.size:= SizeOf(dris);
|
||||
dris.myfunction:= DECRYPT_USER_DATA; { standard protection check & decrypt data }
|
||||
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.data_crypt_key_num := 1;
|
||||
dris.rw_length := 13;
|
||||
dris.rw_data_ptr := Addr(DataString);
|
||||
|
||||
{ call dongle-checking code }
|
||||
result := DDProtCheck(@dris, NIL);
|
||||
|
||||
{ later in your code you can check other values in the DRIS... }
|
||||
|
||||
if (dris.sdsn <> MY_SDSN) then
|
||||
begin
|
||||
messagedlg('Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.', mtError, [mbok], 0);
|
||||
result := -1;
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ later on in your program you can check the return code again }
|
||||
if (dris.ret_code <> 0) then
|
||||
begin
|
||||
messagedlg('Dinkey Dongle protection error.', mtError, [mbok], 0);
|
||||
result := -1;
|
||||
exit;
|
||||
end;
|
||||
|
||||
DataString[13] := Chr(0); { null end of string }
|
||||
display := 'Decrypted data is: ' + DataString;
|
||||
messagedlg(display, mtInformation, [mbok], 0);
|
||||
end;
|
||||
|
||||
{!!!! 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 }
|
||||
Function MyRWAlgorithm(a,b,c,d,e,f,g,h:LongInt):LongInt;
|
||||
begin
|
||||
MyRWAlgorithm:= a xor b xor c xor d xor e xor f;
|
||||
end;
|
||||
|
||||
{ !!!! please overwrite this function with the one generated by DinkeyAdd }
|
||||
procedure CryptDRIS(dris : PByte; seed1,seed2 : Longword);
|
||||
var
|
||||
i,j,k : Integer;
|
||||
bigseed,S : packed array[0..255] of byte;
|
||||
temp,t : byte;
|
||||
begin
|
||||
i := 0;
|
||||
while (i < 255) do
|
||||
begin
|
||||
Move(seed1, bigseed[i], 4); {NB move actually copies data}
|
||||
Move(seed2, bigseed[i+4], 4);
|
||||
i := i + 8;
|
||||
end;
|
||||
|
||||
for i := 0 to 255 do S[i]:= i;
|
||||
|
||||
j := 0;
|
||||
for i := 0 to 255 do
|
||||
begin
|
||||
j := (j + S[i] + bigseed[i] + 123) Mod 256;
|
||||
temp := S[i];
|
||||
S[i] := S[j];
|
||||
S[j] := temp;
|
||||
end;
|
||||
i := 0;
|
||||
j := 0;
|
||||
Inc(dris, 16); {the first part of the DRIS is not encrypted}
|
||||
for k := 16 to SizeOf(drisType)-1 do
|
||||
begin
|
||||
i := (i + 1) Mod 256;
|
||||
j := (j + S[i] + 212) Mod 256;
|
||||
temp := S[i];
|
||||
S[i] := S[j];
|
||||
S[j] := temp;
|
||||
t := (S[i] + S[j] + 97) Mod 256;
|
||||
dris^ := dris^ xor S[t];
|
||||
Inc(dris);
|
||||
end;
|
||||
end;
|
||||
{ !!!! please overwrite this function with the one generated by DinkeyAdd }
|
||||
procedure CryptApiData(data : pbyte; length : integer; seed1,seed2 : Longword; alg_answer: LongInt);
|
||||
var
|
||||
i,j,k : Integer;
|
||||
bigseed,S : packed array[0..255] of byte;
|
||||
temp,t : byte;
|
||||
begin
|
||||
i := 0;
|
||||
while (i < 255) do
|
||||
begin
|
||||
Move(seed1, bigseed[i], 4); {NB move actually copies data}
|
||||
Move(seed2, bigseed[i+4], 4);
|
||||
i := i + 8;
|
||||
end;
|
||||
|
||||
for i := 0 to 255 do S[i]:= i;
|
||||
|
||||
j := 0;
|
||||
for i := 0 to 255 do
|
||||
begin
|
||||
j := (j + S[i] + bigseed[i] + (alg_answer And $FF)) Mod 256;
|
||||
temp := S[i];
|
||||
S[i] := S[j];
|
||||
S[j] := temp;
|
||||
end;
|
||||
i := 0;
|
||||
j := 0;
|
||||
for k := 0 to length-1 do
|
||||
begin
|
||||
i := (i + 1) Mod 256;
|
||||
j := (j + S[i] + ((alg_answer shr 8) And $FF)) Mod 256;
|
||||
temp := S[i];
|
||||
S[i] := S[j];
|
||||
S[j] := temp;
|
||||
t := (S[i] + S[j] + ((alg_answer shr 16) And $FF)) Mod 256;
|
||||
data^ := data^ xor S[t];
|
||||
Inc(data);
|
||||
end;
|
||||
end;
|
||||
|
||||
{ ************************** ProtCheckEnc ************************************ }
|
||||
{ We encrypt the DRIS passed to the API.
|
||||
Patch the CryptDRIS function in this file from source code generated by DinkeyAdd. }
|
||||
Function ProtCheckEnc : LongInt;
|
||||
var
|
||||
dris: drisType;
|
||||
|
||||
begin
|
||||
{ set the DRIS to have random values }
|
||||
random_set(@dris, SizeOf(dris)); { NB this also fills seed1, seed2 with random values }
|
||||
{ then set the values we want to use }
|
||||
Move(AnsiString('DRIS'), dris.header, 4);
|
||||
dris.size:= 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,... }
|
||||
|
||||
CryptDRIS(@dris, dris.seed1, dris.seed2); { encrypt DRIS - !!!! you should separate from DDProtCheck for greater security }
|
||||
|
||||
result := DDProtCheck(@dris, NIL);
|
||||
|
||||
CryptDRIS(@dris, dris.seed1, dris.seed2); { decrypt DRIS - !!!! you should separate from DDProtCheck for greater security }
|
||||
|
||||
if (result <> 0) then
|
||||
begin
|
||||
DisplayError(result, dris.ext_err); { display messages for any errors that have occurred }
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ later in your code you can check other values in the DRIS... }
|
||||
|
||||
if (dris.sdsn <> MY_SDSN) then
|
||||
begin
|
||||
messagedlg('Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.', mtError, [mbok], 0);
|
||||
result := -1;
|
||||
exit;
|
||||
end;
|
||||
|
||||
if (dris.prodcode <> AnsiString(MY_PRODCODE)) then
|
||||
begin
|
||||
messagedlg('Incorrect Product Code! Please modify your source code so that MY_PRODCODE is set to be the Product Code in the dongle.', mtError, [mbok], 0);
|
||||
result := -1;
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ later on in your program you can check the return code again }
|
||||
if (dris.ret_code <> 0) then
|
||||
begin
|
||||
messagedlg('Dinkey Dongle protection error.', mtError, [mbok], 0);
|
||||
result := -1;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ ************************** 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 copy source code 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 : LongInt;
|
||||
var
|
||||
dris: drisType;
|
||||
|
||||
begin
|
||||
{ set the DRIS to have random values }
|
||||
random_set(@dris, SizeOf(dris)); { NB this also fills seed1, seed2, var_a...var_h with random values }
|
||||
{ then set the values we want to use }
|
||||
Move(AnsiString('DRIS'), dris.header, 4);
|
||||
dris.size:= 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 algorithm 1 - you do not need to specify this field if you are only using Lite models}
|
||||
{ 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;
|
||||
|
||||
CryptDRIS(@dris, dris.seed1, dris.seed2); { encrypt DRIS - !!!!you should separate from DDProtCheck for greater security }
|
||||
|
||||
result := DDProtCheck(@dris, NIL);
|
||||
|
||||
CryptDRIS(@dris, dris.seed1, dris.seed2); { decrypt DRIS - !!!!you should separate from DDProtCheck for greater security }
|
||||
|
||||
if (result <> 0) then
|
||||
begin
|
||||
DisplayError(result, dris.ext_err); { display messages for any errors that have occurred }
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ later in your code you can check other values in the DRIS... }
|
||||
|
||||
if (dris.sdsn <> MY_SDSN) then
|
||||
begin
|
||||
messagedlg('Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.', mtError, [mbok], 0);
|
||||
result := -1;
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ later on in your program you can check the return code again }
|
||||
if (dris.ret_code <> 0) then
|
||||
begin
|
||||
messagedlg('Dinkey Dongle protection error.', mtError, [mbok], 0);
|
||||
result := -1;
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ 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
|
||||
begin
|
||||
messagedlg('Dinkey protection error! You have not patched your algorithm in the MyAlgorithm routine', mtError, [mbok], 0);
|
||||
result := -1;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ ************************** WriteBytesEnc************************************** }
|
||||
{ This writes the Data 012...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.}
|
||||
Function WriteBytesEnc : LongInt;
|
||||
var
|
||||
dris: drisType;
|
||||
DataToWrite : packed array[0..9] of byte;
|
||||
alg_ans, i: longint;
|
||||
|
||||
begin
|
||||
for i := 0 to 9 do
|
||||
DataToWrite[i] := i;
|
||||
{ set the DRIS to have random values }
|
||||
random_set(@dris, SizeOf(dris)); { NB this also fills seed1, seed2, var_a...var_h with random values }
|
||||
{ then set the values we want to use }
|
||||
Move(AnsiString('DRIS'), dris.header, 4);
|
||||
dris.size:= SizeOf(dris);
|
||||
dris.myfunction:= WRITE_DATA_AREA; { standard protection check & write data}
|
||||
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.rw_offset := 7;
|
||||
dris.rw_length := SizeOf(DataToWrite);
|
||||
dris.rw_data_ptr := Addr(DataToWrite);
|
||||
|
||||
{ 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(@DataToWrite, SizeOf(DataToWrite), dris.seed1, dris.seed2, alg_ans);
|
||||
|
||||
CryptDRIS(@dris, dris.seed1, dris.seed2); { encrypt DRIS - !!!!you should separate from DDProtCheck for greater security }
|
||||
|
||||
{ call dongle-checking code }
|
||||
result := DDProtCheck(@dris, NIL);
|
||||
|
||||
CryptDRIS(@dris, dris.seed1, dris.seed2); { decrypt DRIS - !!!!you should separate from DDProtCheck for greater security }
|
||||
|
||||
if (result <> 0) then
|
||||
begin
|
||||
DisplayError(result, dris.ext_err); { display messages for any errors that have occurred }
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ later in your code you can check other values in the DRIS... }
|
||||
|
||||
if (dris.sdsn <> MY_SDSN) then
|
||||
begin
|
||||
messagedlg('Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.', mtError, [mbok], 0);
|
||||
result := -1;
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ later on in your program you can check the return code again }
|
||||
if (dris.ret_code <> 0) then
|
||||
begin
|
||||
messagedlg('Dinkey Dongle protection error.', mtError, [mbok], 0);
|
||||
result := -1;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ ************************** 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.}
|
||||
Function ReadBytesEnc : LongInt;
|
||||
var
|
||||
dris: drisType;
|
||||
DataToRead : packed array[0..9] of byte;
|
||||
display : string;
|
||||
alg_ans, i: longint;
|
||||
|
||||
begin
|
||||
{ set the DRIS to have random values }
|
||||
random_set(@dris, SizeOf(dris)); { NB this also fills seed1, seed2, var_a...var_h with random values }
|
||||
{ then set the values we want to use }
|
||||
Move(AnsiString('DRIS'), dris.header, 4);
|
||||
dris.size:= SizeOf(dris);
|
||||
dris.myfunction:= READ_DATA_AREA; { standard protection check & write data}
|
||||
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.rw_offset := 7;
|
||||
dris.rw_length := SizeOf(DataToRead);
|
||||
dris.rw_data_ptr := Addr(DataToRead);
|
||||
|
||||
{ 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);
|
||||
|
||||
CryptDRIS(@dris, dris.seed1, dris.seed2); { encrypt DRIS - !!!!you should separate from DDProtCheck for greater security }
|
||||
|
||||
{ call dongle-checking code }
|
||||
result := DDProtCheck(@dris, NIL);
|
||||
|
||||
CryptDRIS(@dris, dris.seed1, dris.seed2); { decrypt DRIS - !!!!you should separate from DDProtCheck for greater security }
|
||||
|
||||
if (result <> 0) then
|
||||
begin
|
||||
DisplayError(result, dris.ext_err); { display messages for any errors that have occurred }
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ later in your code you can check other values in the DRIS... }
|
||||
|
||||
if (dris.sdsn <> MY_SDSN) then
|
||||
begin
|
||||
messagedlg('Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.', mtError, [mbok], 0);
|
||||
result := -1;
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ later on in your program you can check the return code again }
|
||||
if (dris.ret_code <> 0) then
|
||||
begin
|
||||
messagedlg('Dinkey Dongle protection error.', mtError, [mbok], 0);
|
||||
result := -1;
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ decrypt data that was read }
|
||||
CryptApiData(@DataToRead, SizeOf(DataToRead), dris.seed1, dris.seed2, alg_ans);
|
||||
display := 'Dinkey Dongle data area contains: ';
|
||||
for i:=0 to 9 do
|
||||
display := display + IntToStr(DataToRead[i]) + ' ';
|
||||
messagedlg(display, mtInformation, [mbok], 0);
|
||||
end;
|
||||
|
||||
{ ************************** 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 & 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.}
|
||||
Function EncryptUserDataEnc : LongInt;
|
||||
var
|
||||
dris: drisType;
|
||||
display : string;
|
||||
DataBytes : packed array[0..9] of byte;
|
||||
alg_ans,i : LongInt;
|
||||
|
||||
begin
|
||||
for i := 0 to 9 do
|
||||
DataBytes[i] := i; { initialise data to 0,1,2,3,4,5,6,7,8,9}
|
||||
{ set the DRIS to have random values }
|
||||
random_set(@dris, SizeOf(dris)); { NB this also fills seed1, seed2, var_a...var_h with random values }
|
||||
{ then set the values we want to use }
|
||||
Move(AnsiString('DRIS'), dris.header, 4);
|
||||
dris.size:= SizeOf(dris);
|
||||
dris.myfunction:= ENCRYPT_USER_DATA; { standard protection check & encrypt data }
|
||||
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.data_crypt_key_num := 1;
|
||||
dris.rw_length := SizeOf(DataBytes);
|
||||
dris.rw_data_ptr := Addr(DataBytes);
|
||||
|
||||
{ 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(@DataBytes, Sizeof(DataBytes), dris.seed1, dris.seed2, alg_ans);
|
||||
|
||||
CryptDRIS(@dris, dris.seed1, dris.seed2); { encrypt DRIS - !!!!you should separate from DDProtCheck for greater security }
|
||||
|
||||
{ call dongle-checking code }
|
||||
result := DDProtCheck(@dris, NIL);
|
||||
|
||||
CryptDRIS(@dris, dris.seed1, dris.seed2); { decrypt DRIS - !!!!you should separate from DDProtCheck for greater security }
|
||||
|
||||
if (result <> 0) then
|
||||
begin
|
||||
DisplayError(result, dris.ext_err); { display messages for any errors that have occurred }
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ ... 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 }
|
||||
random_set(@dris, SizeOf(dris));
|
||||
{ then set the values we want to use }
|
||||
Move(AnsiString('DRIS'), dris.header, 4);
|
||||
dris.size:= SizeOf(dris);
|
||||
dris.myfunction:= DECRYPT_USER_DATA; { standard protection check & decrypt data }
|
||||
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.data_crypt_key_num := 1;
|
||||
dris.rw_length := SizeOf(DataBytes);
|
||||
dris.rw_data_ptr := Addr(DataBytes);
|
||||
|
||||
CryptDRIS(@dris, dris.seed1, dris.seed2); { encrypt DRIS - !!!!you should separate from DDProtCheck for greater security }
|
||||
|
||||
{ call dongle-checking code }
|
||||
result := DDProtCheck(@dris, NIL);
|
||||
|
||||
CryptDRIS(@dris, dris.seed1, dris.seed2); { decrypt DRIS - !!!!you should separate from DDProtCheck for greater security }
|
||||
|
||||
{ later in your code you can check other values in the DRIS... }
|
||||
|
||||
if (dris.sdsn <> MY_SDSN) then
|
||||
begin
|
||||
messagedlg('Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.', mtError, [mbok], 0);
|
||||
result := -1;
|
||||
exit;
|
||||
end;
|
||||
|
||||
{ later on in your program you can check the return code again }
|
||||
if (dris.ret_code <> 0) then
|
||||
begin
|
||||
messagedlg('Dinkey Dongle protection error.', mtError, [mbok], 0);
|
||||
result := -1;
|
||||
exit;
|
||||
end;
|
||||
|
||||
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);
|
||||
{ decrypt data that was read }
|
||||
CryptApiData(@DataBytes, SizeOf(DataBytes), dris.seed1, dris.seed2, alg_ans);
|
||||
display := 'Data decrypted by dongle is: ';
|
||||
for i:=0 to 9 do
|
||||
display := display + IntToStr(DataBytes[i]) + ' ';
|
||||
messagedlg(display, mtInformation, [mbok], 0);
|
||||
end;
|
||||
|
||||
{ *************** code that gets executed on startup *********************** }
|
||||
begin
|
||||
{call the function(s) of your choice here - in this example I have chosen a standard protection check}
|
||||
if (ProtCheck() <> 0) then
|
||||
halt;
|
||||
end.
|
||||
|
||||
BIN
Dinkey Pro 7.6.1/Samples/Delphi/VCL/Runtime/dpwin32_omf.obj
Normal file
BIN
Dinkey Pro 7.6.1/Samples/Delphi/VCL/Runtime/dpwin32_omf.obj
Normal file
Binary file not shown.
BIN
Dinkey Pro 7.6.1/Samples/Delphi/VCL/Runtime/dpwin64_delphi.obj
Normal file
BIN
Dinkey Pro 7.6.1/Samples/Delphi/VCL/Runtime/dpwin64_delphi.obj
Normal file
Binary file not shown.
102
Dinkey Pro 7.6.1/Samples/Delphi/VCL/Runtime/dris.pas
Normal file
102
Dinkey Pro 7.6.1/Samples/Delphi/VCL/Runtime/dris.pas
Normal file
@@ -0,0 +1,102 @@
|
||||
{ !! this file should not be modified }
|
||||
unit dris;
|
||||
|
||||
interface
|
||||
|
||||
uses Windows;
|
||||
|
||||
TYPE
|
||||
drisType = packed record
|
||||
{ the first 4 fields are never encrypted }
|
||||
header : array[0..3] of AnsiChar; { should be set to DRIS }
|
||||
{ inputs }
|
||||
size : longint; { size of this structure }
|
||||
seed1 : longint; { seed for data/dris encryption }
|
||||
seed2 : longint; { as above }
|
||||
{ maybe encrypted from now on }
|
||||
myfunction : longint; { specify only one function. NB can't name it "function" as it is a reserved keyword }
|
||||
flags : longint; { options for the function selected. To use more than one OR them together: OPTION1 or OPTION2... }
|
||||
execs_decrement : longword; { amount by which to dec execs if we use flag: DEC_MANY_EXECS }
|
||||
data_crypt_key_num : longint; { number of the key (1-3) that the dongle uses to encrypt or decrypt user data }
|
||||
rw_offset : longint; { offset in the dongle data area to read or write data }
|
||||
rw_length : longint; { length of data are to read/write/encrypt/decrypt }
|
||||
rw_data_ptr : Pbyte; { pointer to data to write / be read }
|
||||
alt_licence_name : array[0..255] of AnsiChar; { protection check for different licence instead of the default one, must be null-terminated }
|
||||
var_a : longint; { variable values for user algorithm }
|
||||
var_b : longint;
|
||||
var_c : longint;
|
||||
var_d : longint;
|
||||
var_e : longint;
|
||||
var_f : longint;
|
||||
var_g : longint;
|
||||
var_h : longint;
|
||||
alg_number : longint; { the number of the user algorithm that you want to execute }
|
||||
{ outputs }
|
||||
ret_code : longint; { return code from the protection check }
|
||||
ext_err : longint; { extended error }
|
||||
dongle_type : longint; { type of dongle detected. 1 = Pro, 2 = FD. NB "type" is a reserved word so I use dongle_type }
|
||||
model : longint; { model of dongle detected. 1 = Lite, 2 = Plus, 4 = Net 5, 7 = Net Unlimited }
|
||||
sdsn : longint; { Software Developer's Serial Number }
|
||||
prodcode : array[0..11] of AnsiChar; { Product Code (null-terminated) }
|
||||
dongle_number : longword;
|
||||
update_number : longint;
|
||||
data_area_size : longword; { size of the data area in the dongle detected }
|
||||
max_alg_num : longint; { the maximum algorithm number in the dongle detected }
|
||||
execs : longint; { executions left: -1 indicates 'no limit' }
|
||||
exp_day : longint; { expiry day: -1 indicates 'no limit' }
|
||||
exp_month : longint; { expiry month: -1 indicates 'no limit' }
|
||||
exp_year : longint; { expiry year: -1 indicates 'no limit' }
|
||||
features : longword; { features value }
|
||||
net_users : longint; { maximum number of network users for the dongle detected: -1 indicates 'no limit' }
|
||||
alg_answer : longint; { answer to the user algorithm executed with the given variable values }
|
||||
fd_capacity : longword; { capacity of the data area in FD dongle. Currently fixed at ~10MB but may change in the future. }
|
||||
fd_drive : array[0..127] of AnsiChar; { drive letter of FD dongle detected (if any) 'f:\' }
|
||||
swkey_type : longint; { 0 = no swkey detected, 1 = temporary software key, 2 = demo software key }
|
||||
swkey_exp_day : longint; { software key expiry date (if software key detected) }
|
||||
swkey_exp_month : longint;
|
||||
swkey_exp_year : longint;
|
||||
end;
|
||||
|
||||
TYPE
|
||||
nu_infoType = packed record
|
||||
licenceName : array[0..255] of AnsiChar;
|
||||
userName : array[0..49] of AnsiChar;
|
||||
computerName : array[0..255] of AnsiChar;
|
||||
ipAddress : array[0..15] of AnsiChar;
|
||||
end;
|
||||
|
||||
{ function constants - specify one only }
|
||||
const PROTECTION_CHECK = 1; { checks for dongle, check program params... }
|
||||
const EXECUTE_ALGORITHM = 2; { protection check + calculate answer for specified algorithm with specified inputs }
|
||||
const WRITE_DATA_AREA = 3; { protection check + writes dongle data area }
|
||||
const READ_DATA_AREA = 4; { protection check + reads dongle data area }
|
||||
const ENCRYPT_USER_DATA = 5; { protection check + the dongle will encrypt user data }
|
||||
const DECRYPT_USER_DATA = 6; { protection check + the dongle will decrypt user data }
|
||||
const FAST_PRESENCE_CHECK = 7; { checks for the presence of the correct dongle only with minimal security, no flags allowed. }
|
||||
const STOP_NET_USER = 8; { stops a network user (a protection check is NOT performed) }
|
||||
|
||||
{ flag constants - can specify more than one }
|
||||
const DEC_ONE_EXEC = 1; { decrement execs by 1 }
|
||||
const DEC_MANY_EXECS = 2; { decrement execs by number specified in execs_decrement }
|
||||
const START_NET_USER = 4; { starts a network user }
|
||||
const USE_FUNCTION_ARGUMENT = 16; { use the extra argument in the function for pointers }
|
||||
const CHECK_LOCAL_FIRST = 32; { always look in local ports before looking in network ports }
|
||||
const CHECK_NETWORK_FIRST = 64; { always look on the network before looking in local ports }
|
||||
const USE_ALT_LICENCE_NAME = 128; { use name specified in alt_licence_name instead of the default one }
|
||||
const DONT_SET_MAXDAYS_EXPIRY = 256; { if the max days expiry date has not been calculated then do not do it this time }
|
||||
const MATCH_DONGLE_NUMBER = 512; { restrict the search to match the dongle number specified in the DRIS }
|
||||
const DONT_RETURN_FD_DRIVE = 1024; { if an FD dongle has been detected then don't return the flash drive/mount name in the DRIS }
|
||||
|
||||
{ runtime api functions}
|
||||
function DDProtCheck( dris, data:pointer ):LongInt; stdcall; external;
|
||||
function DDGetNetUserList(licence_name:PAnsiChar; num_net_users:PLongInt; nu_info:pointer; num_info_structs:LongInt; extended_error:PLongInt):LongInt; stdcall; external;
|
||||
|
||||
implementation
|
||||
|
||||
{$IFDEF WIN32}
|
||||
{$L dpwin32_omf.obj}
|
||||
{$ELSE}
|
||||
{$L dpwin64_delphi.obj}
|
||||
{$ENDIF}
|
||||
|
||||
end.
|
||||
100
Dinkey Pro 7.6.1/Samples/Delphi/VCL/Runtime/dris_for_dll.pas
Normal file
100
Dinkey Pro 7.6.1/Samples/Delphi/VCL/Runtime/dris_for_dll.pas
Normal file
@@ -0,0 +1,100 @@
|
||||
{ !! this file should not be modified }
|
||||
unit dris;
|
||||
|
||||
interface
|
||||
|
||||
uses Windows;
|
||||
|
||||
TYPE
|
||||
drisType = packed record
|
||||
{ the first 4 fields are never encrypted }
|
||||
header : array[0..3] of AnsiChar; { should be set to DRIS }
|
||||
{ inputs }
|
||||
size : longint; { size of this structure }
|
||||
seed1 : longint; { seed for data/dris encryption }
|
||||
seed2 : longint; { as above }
|
||||
{ maybe encrypted from now on }
|
||||
myfunction : longint; { specify only one function. NB can't name it "function" as it is a reserved keyword }
|
||||
flags : longint; { options for the function selected. To use more than one OR them together: OPTION1 or OPTION2... }
|
||||
execs_decrement : longword; { amount by which to dec execs if we use flag: DEC_MANY_EXECS }
|
||||
data_crypt_key_num : longint; { number of the key (1-3) that the dongle uses to encrypt or decrypt user data }
|
||||
rw_offset : longint; { offset in the dongle data area to read or write data }
|
||||
rw_length : longint; { length of data are to read/write/encrypt/decrypt }
|
||||
rw_data_ptr : Pbyte; { pointer to data to write / be read }
|
||||
alt_licence_name : array[0..255] of AnsiChar; { protection check for different licence instead of the default one, must be null-terminated }
|
||||
var_a : longint; { variable values for user algorithm }
|
||||
var_b : longint;
|
||||
var_c : longint;
|
||||
var_d : longint;
|
||||
var_e : longint;
|
||||
var_f : longint;
|
||||
var_g : longint;
|
||||
var_h : longint;
|
||||
alg_number : longint; { the number of the user algorithm that you want to execute }
|
||||
{ outputs }
|
||||
ret_code : longint; { return code from the protection check }
|
||||
ext_err : longint; { extended error }
|
||||
dongle_type : longint; { type of dongle detected. 1 = Pro, 2 = FD. NB "type" is a reserved word so I use dongle_type }
|
||||
model : longint; { model of dongle detected. 1 = Lite, 2 = Plus, 4 = Net 5, 7 = Net Unlimited }
|
||||
sdsn : longint; { Software Developer's Serial Number }
|
||||
prodcode : array[0..11] of AnsiChar; { Product Code (null-terminated) }
|
||||
dongle_number : longword;
|
||||
update_number : longint;
|
||||
data_area_size : longword; { size of the data area in the dongle detected }
|
||||
max_alg_num : longint; { the maximum algorithm number in the dongle detected }
|
||||
execs : longint; { executions left: -1 indicates 'no limit' }
|
||||
exp_day : longint; { expiry day: -1 indicates 'no limit' }
|
||||
exp_month : longint; { expiry month: -1 indicates 'no limit' }
|
||||
exp_year : longint; { expiry year: -1 indicates 'no limit' }
|
||||
features : longword; { features value }
|
||||
net_users : longint; { maximum number of network users for the dongle detected: -1 indicates 'no limit' }
|
||||
alg_answer : longint; { answer to the user algorithm executed with the given variable values }
|
||||
fd_capacity : longword; { capacity of the data area in FD dongle. Currently fixed at ~10MB but may change in the future. }
|
||||
fd_drive : array[0..127] of AnsiChar; { drive letter of FD dongle detected (if any) 'f:\' }
|
||||
swkey_type : longint; { 0 = no swkey detected, 1 = temporary software key, 2 = demo software key }
|
||||
swkey_exp_day : longint; { software key expiry date (if software key detected) }
|
||||
swkey_exp_month : longint;
|
||||
swkey_exp_year : longint;
|
||||
end;
|
||||
|
||||
TYPE
|
||||
nu_infoType = packed record
|
||||
licenceName : array[0..255] of AnsiChar;
|
||||
userName : array[0..49] of AnsiChar;
|
||||
computerName : array[0..255] of AnsiChar;
|
||||
ipAddress : array[0..15] of AnsiChar;
|
||||
end;
|
||||
|
||||
{ function constants - specify one only }
|
||||
const PROTECTION_CHECK = 1; { checks for dongle, check program params... }
|
||||
const EXECUTE_ALGORITHM = 2; { protection check + calculate answer for specified algorithm with specified inputs }
|
||||
const WRITE_DATA_AREA = 3; { protection check + writes dongle data area }
|
||||
const READ_DATA_AREA = 4; { protection check + reads dongle data area }
|
||||
const ENCRYPT_USER_DATA = 5; { protection check + the dongle will encrypt user data }
|
||||
const DECRYPT_USER_DATA = 6; { protection check + the dongle will decrypt user data }
|
||||
const FAST_PRESENCE_CHECK = 7; { checks for the presence of the correct dongle only with minimal security, no flags allowed. }
|
||||
const STOP_NET_USER = 8; { stops a network user (a protection check is NOT performed) }
|
||||
|
||||
{ flag constants - can specify more than one }
|
||||
const DEC_ONE_EXEC = 1; { decrement execs by 1 }
|
||||
const DEC_MANY_EXECS = 2; { decrement execs by number specified in execs_decrement }
|
||||
const START_NET_USER = 4; { starts a network user }
|
||||
const USE_FUNCTION_ARGUMENT = 16; { use the extra argument in the function for pointers }
|
||||
const CHECK_LOCAL_FIRST = 32; { always look in local ports before looking in network ports }
|
||||
const CHECK_NETWORK_FIRST = 64; { always look on the network before looking in local ports }
|
||||
const USE_ALT_LICENCE_NAME = 128; { use name specified in alt_licence_name instead of the default one }
|
||||
const DONT_SET_MAXDAYS_EXPIRY = 256; { if the max days expiry date has not been calculated then do not do it this time }
|
||||
const MATCH_DONGLE_NUMBER = 512; { restrict the search to match the dongle number specified in the DRIS }
|
||||
const DONT_RETURN_FD_DRIVE = 1024; { if an FD dongle has been detected then don't return the flash drive/mount name in the DRIS }
|
||||
|
||||
{$IFDEF WIN32}
|
||||
function DDProtCheck( dris, data:pointer ):LongInt; stdcall; external 'dpwin32.dll';
|
||||
function DDGetNetUserList(licence_name:PAnsiChar; num_net_users:PLongInt; nu_info:pointer; num_info_structs:LongInt; extended_error:PLongInt):LongInt; stdcall; external 'dpwin32.dll';
|
||||
{$ELSE}
|
||||
function DDProtCheck( dris, data:pointer ):LongInt; stdcall; external 'dpwin64.dll';
|
||||
function DDGetNetUserList(licence_name:PAnsiChar; num_net_users:PLongInt; nu_info:pointer; num_info_structs:LongInt; extended_error:PLongInt):LongInt; stdcall; external 'dpwin64.dll';
|
||||
{$ENDIF}
|
||||
|
||||
implementation
|
||||
|
||||
end.
|
||||
Reference in New Issue
Block a user