;Help text for RkPlus 3.2
;Copyright (c) 1991-93 Serious Cybernetics
;All rights reserved
;by Danny Sosebee
;
;Set wordwrap to 76 columns
;
!WIDTH 76
!WRAP
;---------------------------------------------------------------------------
;Section Layout Data
;---------------------------------------------------------------------------
;!TOPIC ## <keyword>                           Ŀ
;<keyword> = definition                      =001
;Description Text                              =002
;   ##<Cross Reference Keywords>            =003
;   programming examples                     =004
;   <keyword>                                =005
;                                              
;---------------------------------------------------------------------------
!TOPIC 1 Rkp
RkpRec = Record
           21Registered : Boolean;
           22ID         : String[36];
           23Name1      : String[36];
           24Name2      : String[36];
           25Name3      : String[36];
           26Message    : String[36];
           27Level      : Byte;
           28ExpYear    : Word;
           52ExpMonth   : Byte;
           53ExpDay     : Byte;
           29Key        : String[12];
         End;

RkpRec is the Type used by the variable Rkp, which contains the registration
information.
;---------------------------------------------------------------------------
!TOPIC 2 EncFuncType
EncFuncType = Function(t1,t2,t3 : String; l : Byte; i : Integer) : Word;

EncFuncType is the function type used to define a custom encoding
function.  See 35SetEncode for details.
;---------------------------------------------------------------------------
!TOPIC 3 NoError
NoError = $0000;

If 34RkpError returns NoError then no error has occurred.  If this is
the case, then 33RkpOK will also return True.  If RkpError returns any
non-zero value, then RkpOK will return False.
;---------------------------------------------------------------------------
!TOPIC 4 FileNotFound
FileNotFound = $0002;

If 34RkpError returns FileNotFound then the previous function or
procedure was unable to find a required file.
;---------------------------------------------------------------------------
!TOPIC 5 PathNotFound
PathNotFound = $0003;

If 34RkpError returns PathNotFound then the previous function or
procedure was unable to find the path of a required file.
;---------------------------------------------------------------------------
!TOPIC 6 TooManyFiles
TooManyFiles = $0004;

If 34RkpError returns TooManyFiles then RkPlus(tm) was unable to open
a file because not enough file handles were defined in CONFIG.SYS.
;---------------------------------------------------------------------------
!TOPIC 7 AccessDenied
AccessDenied = $0005;

If 34RkpError returns AccessDenied then an attempt was made to write to
a Read Only file or a currently open shared file.
;---------------------------------------------------------------------------
!TOPIC 8 InvalidFile
InvalidFile = $0101;

If 34RkpError returns InvalidFile then the previous function or
procedure attempted to process a file that is not a valid RkPlus(tm) file.
;---------------------------------------------------------------------------
!TOPIC 9 InvalidRecord
InvalidRecord = $0102;

This error is not returned by 34RkpError, but is included for future use
and compatibility with other Serious Cybernetics units.
;---------------------------------------------------------------------------
!TOPIC 10 RecordNotFound
RecordNotFound = $0103;

This error is not returned by 34RkpError, but is included for future use
and compatibility with other Serious Cybernetics units.
;---------------------------------------------------------------------------
!TOPIC 11 InvalidParameter
InvalidParameter = $0201;

If 34RkpError returns InvalidParameter, then the previous function or
procedure was passed invalid data.
;---------------------------------------------------------------------------
!TOPIC 12 VersionMismatch
VersionMismatch = $0202;

This error is not currently used by RkPlus(tm), but is included for future
use and is presently used by the encoding units 50Rkp2Enc and
51Rkp3Enc.
;---------------------------------------------------------------------------
!TOPIC 13 NoEncodeFunc
NoEncodeFunc = $0301;

If 34RkpError returns NoEncodeFunc then you are attempting to use
RkPlus(tm) without either providing a custom encode function or using one
of the encoding units (50Rkp2Enc or 51Rkp3Enc), both of which
automatically set their encode functions.
;---------------------------------------------------------------------------
!TOPIC 14 InvalidKey
InvalidKey = $0302;

If 34RkpError returns InvalidKey then the current key in the 1Rkp record
(29Rkp.Key) is not valid.
;---------------------------------------------------------------------------
!TOPIC 15 ExpiredKey
ExpiredKey = $0303;

If 34RkpError returns ExpiredKey then the current key in the 1Rkp record
(29Rkp.Key) has expired.
;---------------------------------------------------------------------------
!TOPIC 16 BadTPU
BadTPU = $FFFF;

If 34RkpError returns BadTPU then the RKPLUS.TPU file is corrupt or
has been tampered with and SHOULD BE REPLACED IMMEDIATELY.
;---------------------------------------------------------------------------
!TOPIC 17 BaseYear
BaseYear : Word;

This variable contains the base year that will be used when calculating
expiration keys.  It is initialised to 1992 by RkPlus(tm).  It is VERY
important that the value of BaseYear be the same in the programme that
generated the key and the programme that uses it, otherwise expiration dates
will be calculated incorrectly.

Example :

BaseYear := 1990;

All expiration dates will be calculated and stored as offsets from
1-Jan-1990.
;---------------------------------------------------------------------------
!TOPIC 18 UseExpDays
UseExpDays : Boolean;

This variable determines whether expiration days will be included in
expiration dates for keys.  If UseExpDays is True (default), then
expiration days will be included (allowing a valid range of 21 years).  If
UseExpDays is False, then expiration days will not be included (allowing a
valid range of 304 years).  If expiration days are not used, keys will
expire on the first day of the expiration month.  The 50Rkp2Enc unit sets
UseExpDays to False to maintain compatibility with RkPlus(tm) version
2.x keys.
;---------------------------------------------------------------------------
!TOPIC 19 UseExePath
UseExePath : Boolean;

This variable controls how RkPlus(tm) handles filenames with no specified
path. If UseExePath is True (default), then RkPlus(tm) will use the path
that the programme was executed from if no path is specified.  If
UseExePath is False, then RkPlus(tm) will use the current path if no
path is specified.
;---------------------------------------------------------------------------
!TOPIC 20 KeyFileSize
KeyFileSize : Integer;

This variable is used by 46SaveRegInfo to determine the size of the key
file when it is created.  If KeyFileSize is less than or equal to 337 (the
number of bytes used by RkPlus(tm)), the file will be 337 bytes long.
However, if KeyFileSize is greater than 337, random bytes will be appended
to the key file to cause it to be KeyFileSize bytes long.

Example :

KeyFileSize := 1024;
!LINE
Randomize;

Any future calls to 46SaveRegInfo will result in a key file that has been
padded to 1024 bytes.

Note:  RkPlus(tm) does NOT automatically randomize the seed number used to
generate the random bytes that are appended to the key file.  In order to
have true random values, your programme must call the Randomize procedure
before SaveRegInfo is called.  If you are not using KeyFileSize (it is
less than or equal to 337), then you do not need to call Randomize (since
no random bytes will be appended).
;---------------------------------------------------------------------------
!TOPIC 21 Registered
1Rkp.Registered : Boolean;

This field of the Rkp record is initialised by RkPlus(tm) to False.  It is
set by 43CreateKey, 44VerifyKey, 45GetRegInfo, 46SaveRegInfo,
and 47BrandRegInfo to True if the current key contained in 29Rkp.Key
is valid and has not expired.

Example :

If Rkp.Registered then

The code following would only be executed if the programme has been
registered. This assumes, of course, that an RkPlus(tm) procedure (such as
GetRegInfo or VerifyKey) has been called previously.
;---------------------------------------------------------------------------
!TOPIC 22 ID
1Rkp.ID : String[36];

This variable is initialised by RkPlus(tm) to ''.  Rkp.ID is not used by
RkPlus(tm), and has no effect on key encryption.  However, it is read from
the key file by 45GetRegInfo, written to the key file by
46SaveRegInfo, and branded into the EXE file by 47BrandRegInfo.  This
will normally be used to ID your key files, so that your programme can
distinguish its own key files from those of other programmes. However, since
it is not used in the encryption of the registration key, it can be used to
store any information that you want.

Example :

If (Rkp.ID <> 'RkData') then
  WriteLn('Error!  This is NOT an RkData key file!');

If Rkp.ID doesn't equal 'RkData' then the message 'Error!  This is NOT an
RkData key file!' will be displayed.
;---------------------------------------------------------------------------
!TOPIC 23 Name1
1Rkp.Name1 : String;

This variable is initialised by RkPlus(tm) to ''.  It is used (along with
24Rkp.Name2 and 25Rkp.Name3) in the encryption of the registration key
by 43CreateKey, 44VerifyKey, 46SaveRegInfo (which also writes it to
the key file), and 47BrandRegInfo (which also brands it to the EXE file).
It is read from the key file by 45GetRegInfo.  This will normally contain
the name of the person that the software is registered to.

Example :

If Rkp.Registered then
  WriteLn('Registered to ',Rkp.Name1)
!LINE
Else
  WriteLn('Unregistered');

If the programme is registered, it will display the name of the person it is
registered to.  Otherwise, it will display "Unregistered".
;---------------------------------------------------------------------------
!TOPIC 24 Name2
1Rkp.Name2 : String;

This variable is initialised by RkPlus(tm) to ''.  It is used (along with
23Rkp.Name1 and 25Rkp.Name3) in the encryption of the registration key
by 43CreateKey, 44VerifyKey, 46SaveRegInfo (which also writes it to
the key file), and 47BrandRegInfo (which also brands in to the EXE file).
It is read from the key file by 45GetRegInfo.  This may contain a company
name, a BBS name, or any additional information that you want to use in key
encryption.

Example :

If Rkp.Registered then Begin
  WriteLn('Registered to ',Rkp.Name1,'.');
  WriteLn('For use at ',Rkp.Name2,'.');
!LINE
End Else
  WriteLn('Remember to Register!');

If the programme is registered, it will display the name and company of the
user that it is registered to.  Otherwise, it will display "Remember to
Register!".
;---------------------------------------------------------------------------
!TOPIC 25 Name3
1Rkp.Name3 : String;

This variable is initialised by RkPlus(tm) to ''.  It is used (along with
23Rkp.Name1 and 24Rkp.Name2) in the encryption of the registration key
by 43CreateKey, 44VerifyKey, 46SaveRegInfo (which also writes it to
the key file), and 47BrandRegInfo (which also brands it into the EXE
file).  It is read from the key file by 45GetRegInfo.  This may contain a
customer number, address, or any additional information that you want to use
in key encryption.

Example :

If Rkp.Registered then Begin
  WriteLn('Registered to ',Rkp.Name1);
  WriteLn('              ',Rkp.Name2);
  WriteLn('              ',Rkp.Name3);
!LINE
End Else
  WriteLn('Unregistered');

If the programme is registered, it will display the name of the person it is
registered to (Rkp.Name1) followed by a 2 line mailing address (from
Rkp.Name2 and Rkp.Name3).  Otherwise, the message 'Unregistered' will be
displayed.
;---------------------------------------------------------------------------
!TOPIC 26 Message
1Rkp.Message : String[36];

This variable is initialised by RkPlus(tm) to ''.  Rkp.Message is not
used by RkPlus(tm), and has no effect on key encryption.  However, it is
read from the key file by 45GetRegInfo, written to the key file by
46SaveRegInfo, and branded to the EXE file by 47BrandRegInfo.  This
will normally be used to ID your key files, so that your programme can
distinguish your key files from those of other programers/companies.
However, since it is not used in the encryption of the registration key, it
can be used to store any information that you want.

Example :

If(Rkp.Message <> 'Serious Cybernetics') then
  WriteLn('Error!  This is NOT a Serious Cybernetics key file!');

If Rkp.Message doesn't equal 'Serious Cybernetics', then the message
'Error! This is NOT a Serious Cybernetics key file!' will be displayed.
;---------------------------------------------------------------------------
!TOPIC 27 Level
1Rkp.Level : Byte;

This variable is initialised by RkPlus(tm) to 0.  It is used in the
encryption of the registration key by 43CreateKey, 44VerifyKey,
46SaveRegInfo (which also writes it to the key file), and
47BrandRegInfo (which also brands it to the EXE file). It is read from
the key file by 45GetRegInfo. If you don't wish to use registration
levels, Rkp.Level should always be 0.

Example :

If Rkp.Level > 0 then
  WriteLn('[G]raphs');
!LINE
If Rkp.Level > 1 then
  WriteLn('[O]ther functions');

If the registration level is greater than 0 then the menu option "[G]raphs"
would be displayed.  If the registration level is greater than 1 then the
menu option "[O]ther functions" would also be displayed.

Note : Unlike the expiration date, which is binary encoded into the key
number (after the encoding functions are called) and therefore can be
extracted from any given key number, the registration level is only used for
the encryption of the key, and is stored in the key file but can not be
extracted from a key number itself.  Therefore, if you use registration
levels, you will need to make sure that the brand programme or key file
creation programme knows, or can determine, the registration level, because
it can NOT be extracted from the key number alone (see the files
SAMPLE2.PAS, REGISTER.PAS, and BRAND.PAS for examples).
;---------------------------------------------------------------------------
!TOPIC 28 ExpYear
!NOWRAP
1Rkp.ExpYear  : Word;
Rkp.ExpMonth : Byte;
Rkp.ExpDay   : Byte;
!WRAP

These variables are initialised by RkPlus(tm) to 0.  They are
binary-encoded into the registration key by 43CreateKey,
46SaveRegInfo, and 47BrandRegInfo.  They are decoded from the
registration key by 44VerifyKey and 45GetRegInfo.  Valid values for
Rkp.ExpYear are 0 (No expiration) or BaseYear+1 to BaseYear+340 (if
18UseExpDays is False) or BaseYear+1 to BaseYear+21 (if UseExpDays is
True) . Valid values for Rkp.ExpMonth are 0 (No expiration) or 1 to 12.
Valid values for Rkp.ExpDay are 0 (No expiration) or odd days 1 to 29 (if
UseExpDays is True). Even values (1 to 28) will be rounded up to the next
odd value.  If you don't wish to use expiration dates, Rkp.ExpYear,
Rkp.ExpMonth, and Rkp.ExpDay should always be 0.

Example :

!NOWRAP
Const
 Months : Array[1..12] of String[3] =
 ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');

BaseYear := 1990;
UseExpDays := False;
.
. { rest of programme would be here }
.
If (RkpError = ExpiredKey) then
  WriteLn('Your key expired 1-',Months(Rkp.ExpMonth),'-',Rkp.ExpYear)
Else If Rkp.Registered then
  WriteLn('Your key will expire 1-',Months(Rkp.ExpMonth),'-',Rkp.ExpYear);
!WRAP

If the key has expired, the date that the key expired is displayed.
Otherwise, if the programme is registered, the date that the key will expire
is displayed.
;---------------------------------------------------------------------------
!TOPIC 29 Key
1Rkp.Key : String[12];

This variable is initialised by RkPlus(tm) to '000000000000'.  It is set
by 43CreateKey and 45GetRegInfo.  It is used by 44VerifyKey,
46SaveRegInfo, and 47BrandRegInfo.  This contains the 12 digit
alphanumeric registration key as a string.

Example :

If Rkp.Registered then Begin
  WriteLn('Registered to ',Rkp.Name1,'.');
  WriteLn('Registration key is ',Rkp.Key,'.');
!LINE
End Else
  WriteLn('Not registered.');
  WriteLn('Please read the READ.ME file for more info.');
!LINE
End;

If the programme is registered, the name of the person that it is registered
to, and the registration key will be displayed.  Otherwise, a message will
be displayed telling the user how to register the programme.
;---------------------------------------------------------------------------
!TOPIC 30 KeyFileCode
KeyFileCode : LongInt;

This variable defaults to 0 (no KeyFile scrambling).  If it set to any valid
non-zero value ($00000001 to $FFFFFFFF) then it will be used to generate an
algorythm to "scramble" the key file as it is written.  If KeyFileCode is
not set to the exact same value in programmes which read the key file, the
file will be unreadable.

KeyFileCode is designed to prevent hackers from being able to use a copy
of RkPlus(tm) to read your key files.  It has the additional effect of
making the key file illegible when listed by text file viewers.
;---------------------------------------------------------------------------
!TOPIC 31 RkPlusVer
Function RkPlusVer : String;

RkPlusVer returns the current version of RkPlus(tm).

Example :

WriteLn('using ',RkPlusVer);

will display "using RkPlus 3.2".
;---------------------------------------------------------------------------
!TOPIC 32 BadSystemDate
Function BadSystemDate : Boolean;

This Function will return True if the current system date is 1-Jan-1980
(which usually indicates that the date was not set on the PC), or False if
the current system date is anything other than 1-Jan-1980.

The main purpose for this Function is for use with limited keys (with
embedded expiration dates).  By calling BadSystemDate, your programme can
handle situations where the system date was not set (which would cause
expiration dates to be meaningless).

Example :

If BadSystemDate then Begin
  WriteLn('The system date must be set!');
  Halt(1);
!LINE
End;

If the system date was not set (BadSystemDate returns True) then display a
message and exit with an ErrorLevel of 1.
;---------------------------------------------------------------------------
!TOPIC 33 RkpOK
Function RkpOK : Boolean;

RkpOK will return True if the result of the last procedure or function was
3NoError.  If RkpOK is False, then an error has occurred.

Example :

If RkpOK then
  WriteLn('Key file written!');

If RkpOk returns True, then the message "Key file written!" will be
displayed.
;---------------------------------------------------------------------------
!TOPIC 34 RkpError
Function RkpError : Word;

RkpError will return the actual error code of the last procedure/function.
If RkpError = 3NoError, then no error occurred.  If RkpError is
between $0001 and $00FF, then an I/O error occurred during the operation and
the result is an IoResult code.  Otherwise, the error is an RkPlus(tm)
error.

Example :

If RkpOK then
  WriteLn('Key file written.')
!LINE
Else
  WriteLn('Error ',RkpError,'!');

If no error occurred, "Key file written." will be displayed.  Otherwise, the
error code will be displayed.
;---------------------------------------------------------------------------
!TOPIC 35 SetEncode
Procedure SetEncode(e1, e2, e3 : EncFuncType);

This procedure will specify the functions that will be called to encode the
registration key.  An encoding function must be defined as FAR {$F+} and
must be of the type 2EncFuncType.  Each encode function is used to encode
one 4-character section of the final key number (the actual number to
character conversion is handled by RkPlus(tm)) and is passed 3 strings, a
Byte and an Integer.  Any or all of these values may be used by any single
encode function to produce a Word result. However, the 3 Strings and the
Byte should be used in at least one of the encode functions.  Otherwise,
that value will have no effect on key generation.  The 3 strings correspond
to 23Rkp.Name1, 24Rkp.Name2 and 25Rkp.Name3. The Byte corresponds
to the registration level (27Rkp.Level) and the Integer is the expiration
date stored as an offset from 1-Jan of BaseYear. Since the expiration date
will be binary-encoded into the key number after the encode function
returns, it is not required that it be used in the encode function.  If you
use 50Rkp2Enc (for RkPlus(tm) 2.x/compatible keys) or 51Rkp3Enc (for
RkPlus(tm) 3.x keys), you do not need to provide encoding functions or
call SetEncode (it is handled automatically in the encoding unit's startup
code).
;---------------------------------------------------------------------------
!TOPIC 36 SetKeyFile
Procedure SetKeyFile(s : String);

This procedure will specify the name of the key file for RkPlus(tm) to use
(with optional path and extension).  The key file will default to the name
of the programme with an extension of '.RKP' (or '.EXE' when using
47BrandRegInfo) and the path will default to the path the programme was
executed from (if 19UseExePath is True) or the current directory (if
UseExePath is False).

Example :

UseExePath := False;
!LINE
SetKeyFile('DEMO1');

RkPlus(tm) will use 'DEMO1.RKP' (in the current directory) as the key
file. If BrandRegInfo is called, it will use 'DEMO1.EXE' (in the current
directory).
;---------------------------------------------------------------------------
!TOPIC 37 KeyFileName
Function KeyFileName : String;

This function will return the full path, filename and extension of the key 
file.

Example :

UseExePath := True;
!LINE
SetKeyFile('DEMO2');
!LINE
WriteLn(KeyFileName);

If the current directory is (for example) D:\ and the programme was executed
from (for example) C:\DEMOS, then it would display "C:\DEMOS\DEMO2.RKP".
;---------------------------------------------------------------------------
!TOPIC 38 ExeFileName
Function ExeFileName : String;

This function will return the full path, filename and extension of the exe
file that would be branded by 47BrandRegInfo.  This will be identical to
the result of 37KeyFileName, except that the extension will be '.EXE'.

Example :

UseExePath := False;
!LINE
SetKeyFile('DEMO3');
!LINE
WriteLn(ExeFileName);

If the current directory is (for example) D:\ and the programme was executed
from (for example) C:\DEMOS, then it would display "D:\DEMO3.EXE".
;---------------------------------------------------------------------------
!TOPIC 39 GetKeyFileSize
Function GetKeyFileSize : Integer;

This Function will return the size (in bytes) of the key file.

Example :

If (GetKeyFileSize <> 1024) then
  WriteLn('Invalid file size');

If the size of the key file is not equal to 1024, then "Invalid File Size" 
will be displayed.
;---------------------------------------------------------------------------
!TOPIC 40 MakeKey
Function MakeKey(Name1,Name2,Name3 : String;
                 Level : Byte;
                 ExpYear : Word;
                 ExpMonth,ExpDay : Byte) : String;

The function MakeKey will return a string containing the 12 digit
registration key for Names and Level (using the encode functions defined
with 35SetEncode) specified, with an encoded expiration date of ExpYear,
ExpMonth and ExpDay. If you do not wish to use registration levels, simply
pass a 0 as the Level parameter.  If you do not wish to use expiration
dates, simply pass 0 as the ExpYear, ExpMonth and ExpDay parameters.  ExpDay
will only be used if 18UseExpDays is True.  Unlike the higher-level
43CreateKey procedure, this function does NOT use or change the values of
the 1Rkp record.

Example :

!NOWRAP
Write('Enter name : ');
ReadLn(n);
Write('Enter company : ');
ReadLn(c);
Write('Enter phone number (XXX) XXX-XXXX : ');
ReadLn(p);
k := MakeKey(n,c,p,0,0,0,0);    { registration levels and expiration
                                  dates are not being used }
WriteLn;
WriteLn('Registration key is ',k);
!WRAP

This will prompt for a name, company name and phone number.  MakeKey is
then passed the name, company name and phone number, a 0 for the
registration level and 0 for expiration year, month and day. It will return
the key in the variable k, which is then displayed.

It is usually preferable to use the higher-level 43CreateKey procedure,
instead of MakeKey.  MakeKey is included to allow for situations where
you may need to make a key and don't want to affect the values contained in
the Rkp record.
;---------------------------------------------------------------------------
!TOPIC 41 ValidKey
Function ValidKey(Name1,Name2,Name3 : String;
                  Level : Byte;
                  Key : String) : Boolean;

ValidKey will return TRUE if the Key is valid for Name1, Name2, Name3 and
Level (using the encode functions defined with 35SetEncode).  If you do
not wish to use registration levels (and levels weren't used when the key
was generated), simply pass 0 as the Level parameter.  If ValidKey returns
False, the key is not valid. Unlike the higher-level procedure
44VerifyKey, this function does NOT use or change the values of the 1Rkp
record.

Example :

!NOWRAP
Write('Enter your name : ');
ReadLn(n);
Write('Enter your BBS name : ');
ReadLn(b);
Write('Enter your FidoNet address : ');
ReadLn(f);
Write('Enter your registration key : ');
ReadLn(k);
If Not ValidKey(n,b,f,0,k) then Begin  { registration levels not used }
  WriteLn('Invalid key!');
  Halt(1);
End;
!WRAP

This programme will prompt the user to enter a name, BBS name, FidoNet
address and a registration key.   If the registration key is not valid, the
programme will display 'Invalid key!' and Halt with an errorlevel of 1.

It is usually preferable to use the higher-level VerifyKey procedure,
instead of ValidKey.  ValidKey is included to allow for situations where
you may need to validate a key and don't want to affect the values contained
in the Rkp record.
;---------------------------------------------------------------------------
!TOPIC 42 SetRegInfo
Procedure SetRegInfo(t,s1,s2,s3,m : String;
                     l : Byte;
                     ey : Word;
                     em,ed : Byte;
                     k : String);

SetRegInfo makes the following assignments :

!NOWRAP
22Rkp.ID       := t         27Rkp.Level    := l
23Rkp.Name1    := s1        28Rkp.ExpYear  := ey
24Rkp.Name2    := s2        52Rkp.ExpMonth := em
25Rkp.Name3    := s3        53Rkp.ExpDay   := ed
26Rkp.Message  := m         29Rkp.Key      := k
!WRAP

Since the values in the 1Rkp record may be accessed directly, you will not
normally need SetRegInfo.  However, if you are using 40MakeKey and/or
41ValidKey with temporary values, you might want to use SetRegInfo as a
"short-cut" method of assigning those values to the Rkp record.

Example :

!NOWRAP
Write('Enter your customer ID : ');
ReadLn(i);
Write('Enter your name : ');
ReadLn(n);
Write('Enter your address (line 1) : ');
ReadLn(a1);
Write('Enter your address (line 2) : ');
ReadLn(a2);
Write('Enter your phone number : ');
ReadLn(p);
Write('Enter your registration key number : ');
ReadLn(k);
WriteLn;
If Not ValidKey(n,a1,a2,0,k) then      { registration levels not used }
  WriteLn('Registration key number invalid!')
Else
  SetRegInfo(i,n,a1,a2,p,0,0,0,0,k);
!WRAP

In the above example, the existing registration information (in the Rkp
record) will not be changed if the registration key is invalid.  Note also
that this example uses Rkp.ID (set to the value of the variable i) to
store a customer number, and Rkp.Message (set to the value of the variable
p) to store the user's phone number.  These values are not used in the
encryption of keys and, therefore, may be used to store any information that
you want.
;---------------------------------------------------------------------------
!TOPIC 43 CreateKey
Procedure CreateKey;

The procedure CreateKey will use the encode functions defined with
35SetEncode to generate a key encrypted from 23Rkp.Name1,
24Rkp.Name2, 25Rkp.Name3, 27Rkp.Level, 28Rkp.ExpYear,
52Rkp.ExpMonth (and 53Rkp.ExpDay, if 18UseExpDays is True) with an
embedded expiration date, returning the resulting key in 29Rkp.Key.  If
you don't wish to use registration levels, simply set Rkp.Level to 0
before calling CreateKey.  If you don't wish to use expiration dates,
simply set Rkp.ExpYear, Rkp.ExpMonth and Rkp.ExpDay to 0 before
calling CreateKey.

CreateKey sets the following result code, which will be returned by
subsequent calls to 34RkpError :

16BadTPU     - RKPLUS.TPU is corrupt or has been tampered with

Example :

!NOWRAP
Write('Enter name : ');
ReadLn(Rkp.Name1);
Write('Enter company : ');
ReadLn(Rkp.Name2);
Write('Enter phone number (XXX) XXX-XXXX : ');
ReadLn(Rkp.Name3);
Rkp.Level := 0;    { registration levels are not being used }
Rkp.ExpYear := 0;  { expiration dates are not being used }
Rkp.ExpMonth := 0;
Rkp.ExpDay := 0;
CreateKey;
WriteLn;
If RkpOK then
  WriteLn('Registration key is ',Rkp.Key);
!WRAP

This will display a warning message and then prompt for a name, company
name, and phone number.  CreateKey is called and the key is returned in
Rkp.Key, which is then displayed, if no error has occurred.

Note:  It is possible to use CreateKey to create keys and then to store
the contents of the 1Rkp record into your own configuration file (instead of
using 46SaveRegInfo) and then read the information into your programme
and use 44VerifyKey to verify that the key is valid (rather than using
45GetRegInfo).  This way you can keep registration information in your
own configuration file with other programme information, rather than in its
own key file.  If using this method, its important that you save Rkp.Name1
(as well as Rkp.Name2, Rkp.Name3 and/or Rkp.Level, if used), so that
keys will be built correctly. It is not necessary to save Rkp.ExpYear,
Rkp.ExpMonth or Rkp.ExpDay, since the expiration date is binary-encoded
in the key number and extracted by any call to VerifyKey.
;---------------------------------------------------------------------------
!TOPIC 44 VerifyKey
Procedure VerifyKey;

The procedure VerifyKey will use the encode functions defined with
35SetEncode to generate a key encrypted from 23Rkp.Name1,
24Rkp.Name2, 25Rkp.Name3 and 27Rkp.Level; and compare the resulting
key to 29Rkp.Key, setting 21Rkp.Registered to True if the key is valid
and not expired. 28Rkp.ExpYear, 52Rkp.ExpMonth (and 53Rkp.ExpDay,
if 18UseExpDays is True) will be set to the expiration date encoded in
the key.  If you don't wish to use registration levels, simply set
Rkp.Level to 0 before calling VerifyKey.

VerifyKey sets the following result codes, which will be returned by
subsequent calls to 34RkpError :

14InvalidKey - Key is not valid
!LINE
15ExpiredKey - Key has expired
!LINE
16BadTPU     - RKPLUS.TPU is corrupt or has been tampered with

Example :

!NOWRAP
Write('Enter your name : ');
ReadLn(Rkp.Name1);
Write('Enter your BBS name : ');
ReadLn(Rkp.Name2);
Write('Enter your FidoNet address : ');
ReadLn(Rkp.Name3);
Write('Enter your registration key : ');
ReadLn(Rkp.Key);
Rkp.Level := 0;    { registration levels are not used }
VerifyKey;
If Not RkpOK then Begin
  Case RkpError of
    ExpiredKey : WriteLn('This key has expired!');
    InvalidKey : WriteLn('This key is invalid!');
    Else         WriteLn('Error ',RkpError);
  End;
  Halt(1);
End;
!WRAP

This programme will prompt the user to enter a name, BBS name, FidoNet
address, and a registration key.   If the registration key has expired,
"This key has expired!" will be displayed.  If the registration key is
invalid, "This key is invalid!" will be displayed.  Otherwise, if an error
has occurred, an error message will be displayed.  In any case where the key
is not validated, the programme will halt with an errorlevel of 1.
;---------------------------------------------------------------------------
!TOPIC 45 GetRegInfo
Procedure GetRegInfo;

GetRegInfo will read the key file (if it exists) and set the value of the
following variables :

!NOWRAP
23Rkp.Name1    - set to primary registration name
24Rkp.Name2    - set to secondary registration name
25Rkp.Name3    - set to third registration name
27Rkp.Level    - set to registration level (0 if not used)
28Rkp.ExpYear  - set to expiration year (0 if not used)
52Rkp.ExpMonth - set to expiration month (0 if not used)
53Rkp.ExpDay   - set to expiration day
                    (0 if not used or if 18UseExpDays is False)
29Rkp.Key      - set to 12 digit alphanumeric registration key
!WRAP

GetRegInfo would generally be called near the beginning of a programme
(after 35SetEncode has been called to define the encode functions and
36SetKeyFile has been called to define the key file).

GetRegInfo sets the following result codes, which will be returned by
subsequent calls to 34RkpError :

!NOWRAP
15ExpiredKey  - Registration key has expired
14InvalidKey  - programme is registered with an invalid key
8InvalidFile - File is not an RkPlus(tm) registration key file
16BadTPU      - RKPLUS.TPU is corrupt or has been tampered with
!WRAP

Example :

!NOWRAP
GetRegInfo;
If Rkp.Registered then
  WriteLn('Registered to ',Rkp.Name1);
!WRAP

GetRegInfo will read the key file (specified in an earlier call to
SetKeyFile). If the programme is registered, 21Rkp.Registered will be
True and the programme will display the name of the person that the
programme is registered to.
;---------------------------------------------------------------------------
!TOPIC 46 SaveRegInfo
Procedure SaveRegInfo;

The procedure SaveRegInfo will use the encode functions defined with
35SetEncode to generate a key encrypted from 23Rkp.Name1,
24Rkp.Name2, 25Rkp.Name3, 27Rkp.Level, 28Rkp.ExpYear,
52Rkp.ExpMonth (and 53Rkp.ExpDay, if 18UseExpDays is True). It will
them compare the resulting key with 29Rkp.Key and write the contents of
the 1Rkp record to the keyfile.  If you don't wish to use registration
levels, simply set Rkp.Level to 0 before calling SaveRegInfo. If you
don't wish to use expiration dates, simply set Rkp.ExpYear,
Rkp.ExpMonth, and Rkp.ExpDay to 0 before calling SaveRegInfo.

SaveRegInfo sets the following result codes, which will be returned by
subsequent calls to 34RkpError :

14InvalidKey - Key is not valid
!LINE
16BadTPU     - RKPLUS.TPU is corrupt or has been tampered with

Example :

!NOWRAP
Write('Enter your name : ');
ReadLn(Rkp.Name1);
Write('Enter your company name : ');
ReadLn(Rkp.Name2);
Write('Enter your registration key : ');
ReadLn(Rkp.Key);
Rkp.Level := 0;    { registration levels not used }
Rkp.ExpYear := 0;  { expiration dates not used }
Rkp.ExpMonth := 0;
Rkp.ExpDay := 0;
SaveRegInfo;
If Not RkpOK then
  WriteLn('Invalid Key or File Error.  Programme not installed.');
!WRAP

This programme will prompt the user for a name, company name, and a
registration key.  SaveRegInfo will then be called. If 21Rkp.Registered
is not True, then an error occurred and no key file was written (the
programme displays 'Invalid Key or File Error.  Programme not installed.').
Otherwise, the key file was written.
;---------------------------------------------------------------------------
!TOPIC 47 BrandRegInfo
Procedure BrandRegInfo;

The procedure BrandRegInfo will use the encode functions defined with
35SetEncode to generate a key encrypted from 23Rkp.Name1,
24Rkp.Name2, 25Rkp.Name3, 27Rkp.Level, 28Rkp.ExpYear,
52Rkp.ExpMonth (and 53Rkp.ExpDay, if 18UseExpDays is True). It will
them compare the resulting key with 29Rkp.Key and brand the contents of
the 1Rkp record to the EXE file.  If you don't wish to use registration
levels, simply set Rkp.Level to 0 before calling BrandRegInfo. If you
don't wish to use expiration dates, simply set Rkp.ExpYear,
Rkp.ExpMonth, and Rkp.ExpDay to 0 before calling BrandRegInfo.

BrandRegInfo sets the following result codes, which will be returned by
subsequent calls to 34RkpError :

14InvalidKey  - Key is not valid
!LINE
8InvalidFile - EXE file is NOT an RkPlus(tm) 3.x file
!LINE
16BadTPU      - RKPLUS.TPU is corrupt or has been tampered with

Example :

!NOWRAP
Write('Enter your name : ');
ReadLn(Rkp.Name1);
Write('Enter your company name : ');
ReadLn(Rkp.Name2);
Write('Enter your registration key : ');
ReadLn(Rkp.Key);
Rkp.Level := 0;    { registration levels not used }
Rkp.ExpYear := 0;  { expiration dates not used }
Rkp.ExpMonth := 0;
Rkp.ExpDay := 0;
BrandRegInfo;
If Not Rkp.Registered then
  WriteLn('Invalid Key or File Error.  Programme not branded.');
!WRAP

This programme will prompt the user for a name, company name, and a
registration key.  BrandRegInfo will then be called. If
21Rkp.Registered is not True, then an error occurred and the EXE file was
not modified (the programme displays 'Invalid Key or File Error.  Programme
not branded.'). Otherwise, the EXE file was modified to include the
registration information.

Note:  BrandRegInfo has NOT been tested with any EXE-compression
programmes. Because of the way that RkPlus(tm) searches for it's ID stamp,
it will most likely NOT work on "compressed" files.  Calls to BrandRegInfo
(when the EXE file set with 36SetKeyFile has been "compressed") will
probably set the result code of 8InvalidFile.
;---------------------------------------------------------------------------
!TOPIC 48 FileFuncType
FileFuncType = Function(v : Byte; b : Boolean) : Byte;

This type defines the function type that would be passed to 49SetFileEnc,
when specifying a File Encoding Function.  It is automatically set by
50Rkp2Enc and 51Rkp3Enc.  You will only need to use FileFuncType if
you are using user-written encoding functions.
;---------------------------------------------------------------------------
!TOPIC 49 SetFileEnc
Procedure SetFileEnc(ef : FileFuncType);

This procedure is used to specify the File Encoding Function that will be
used by RkPlus(tm) to "scramble" key files (see 30KeyFileCode).  It is
automatically set by 50Rkp2Enc and 51Rkp3Enc.  You will only need to
use SetFileEnc if you are using user-written encoding functions.
;---------------------------------------------------------------------------
!TOPIC 50 Rkp2Enc
Uses Rkp2Enc

Rkp2Enc is an RkPlus(tm) Encoding Unit designed to provide compatibility
with RkPlus(tm) version 2.x.  In order to maintain RkPlus(tm) v2.x key
compatibility, you must use Rkp2Enc.
;---------------------------------------------------------------------------
!TOPIC 51 Rkp3Enc
Uses Rkp3Enc

Rkp3Enc is an RkPlus(tm) Encoding Unit designed to provide compatibility
with RkPlus(tm) version 3.x.  In order to maintain RkPlus(tm) v3.x key
compatibility, you must use Rkp3Enc.  RkPlus(tm) version 3.x key
encryption is substantially different (and far more sophisticated) than
version 2.x key encryption.
;---------------------------------------------------------------------------
!TOPIC 52 ExpMonth
!NOWRAP
1Rkp.ExpYear  : Word;
Rkp.ExpMonth : Byte;
Rkp.ExpDay   : Byte;
!WRAP

These variables are initialised by RkPlus(tm) to 0.  They are
binary-encoded into the registration key by 43CreateKey,
46SaveRegInfo, and 47BrandRegInfo.  They are decoded from the
registration key by 44VerifyKey and 45GetRegInfo.  Valid values for
Rkp.ExpYear are 0 (No expiration) or BaseYear+1 to BaseYear+340 (if
18UseExpDays is False) or BaseYear+1 to BaseYear+21 (if UseExpDays is
True) . Valid values for Rkp.ExpMonth are 0 (No expiration) or 1 to 12.
Valid values for Rkp.ExpDay are 0 (No expiration) or odd days 1 to 29 (if
UseExpDays is True). Even values (1 to 28) will be rounded up to the next
odd value.  If you don't wish to use expiration dates, Rkp.ExpYear,
Rkp.ExpMonth, and Rkp.ExpDay should always be 0.

Example :

!NOWRAP
Const
 Months : Array[1..12] of String[3] =
 ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');

BaseYear := 1990;
UseExpDays := False;
.
. { rest of programme would be here }
.
If (RkpError = ExpiredKey) then
  WriteLn('Your key expired 1-',Months(Rkp.ExpMonth),'-',Rkp.ExpYear)
Else If Rkp.Registered then
  WriteLn('Your key will expire 1-',Months(Rkp.ExpMonth),'-',Rkp.ExpYear);
!WRAP

If the key has expired, the date that the key expired is displayed.
Otherwise, if the programme is registered, the date that the key will expire
is displayed.
;---------------------------------------------------------------------------
!TOPIC 53 ExpDay
!NOWRAP
1Rkp.ExpYear  : Word;
Rkp.ExpMonth : Byte;
Rkp.ExpDay   : Byte;
!WRAP

These variables are initialised by RkPlus(tm) to 0.  They are
binary-encoded into the registration key by 43CreateKey,
46SaveRegInfo, and 47BrandRegInfo.  They are decoded from the
registration key by 44VerifyKey and 45GetRegInfo.  Valid values for
Rkp.ExpYear are 0 (No expiration) or BaseYear+1 to BaseYear+340 (if
18UseExpDays is False) or BaseYear+1 to BaseYear+21 (if UseExpDays is
True) . Valid values for Rkp.ExpMonth are 0 (No expiration) or 1 to 12.
Valid values for Rkp.ExpDay are 0 (No expiration) or odd days 1 to 29 (if
UseExpDays is True). Even values (1 to 28) will be rounded up to the next
odd value.  If you don't wish to use expiration dates, Rkp.ExpYear,
Rkp.ExpMonth, and Rkp.ExpDay should always be 0.

Example :

!NOWRAP
Const
 Months : Array[1..12] of String[3] =
 ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');

BaseYear := 1990;
UseExpDays := False;
.
. { rest of programme would be here }
.
If (RkpError = ExpiredKey) then
  WriteLn('Your key expired 1-',Months(Rkp.ExpMonth),'-',Rkp.ExpYear)
Else If Rkp.Registered then
  WriteLn('Your key will expire 1-',Months(Rkp.ExpMonth),'-',Rkp.ExpYear);
!WRAP

If the key has expired, the date that the key expired is displayed.
Otherwise, if the programme is registered, the date that the key will expire
is displayed.
;---------------------------------------------------------------------------
!TOPIC 54 About RkPlus
!NOWRAP
 ___________ 
(           )
 \               RkPlus(tm) 3.2
   \     /   
     \ /         (c) 1991-93 Serious Cybernetics
     / \         by C. Scott Davis
   /     \   
  (______  \ 
(___________)
!WRAP        

RkPlus(tm) is a Turbo Pascal (tm) Unit designed to allow programmers to
easily handle secure registration keys in their software.  All of the key
encryption, checking, and key file routines are handled in RkPlus(tm),
requiring little effort on the part of the programmer.  RkPlus(tm) can allow
anything from simple registration messages to multiple registration levels,
limited use demo keys, and custom written encoding functions.

RkPlus(tm) is Shareware.  You may copy and distribute the RKPLUS32 archive
freely.  All I ask is that you include all of the original files,
unmodified, and that you do not charge for the distribution of RkPlus(tm)
itself.  If you use RkPlus(tm) to develop software, you are required to
register BEFORE releasing it (see REGISTER.TXT for registration
information).

There are no royalties for the distribution of programmes that are written
with RkPlus(tm).  A single registration fee entitles you to write and
distribute any number of programmes using RkPlus(tm).

Questions, comments, and suggestions are welcome.

Send E/Mail to   Scott Davis
                 Phoenix StarFighter BBS [300-14400 HST/v.32bis]
                 Phone (404) 869-3410
                 FidoNet Node 1:3616/20

Send US Mail to  Serious Cybernetics
                 6804 Belton Place
                 Lula, GA 30554
;-------------------------------------------------------------------
; Highest Topic Number is 54
