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.

