// This code contains the following functions. Please choose the one that matches your needs:
//   ProtCheck
//   ProtCheckWithAlg   (the function also depends on the function MyAlgorithm)
//   WriteString
//   ReadString
//   EncryptUserData
// or the same functions but using DRIS and API data encryption
// (these functions also require the functions CryptDRIS and possibly CryptApiData and MyRWAlgorithm)
//   ProtCheckEnc
//   ProtCheckWithAlgEnc
//   WriteStringEnc
//   ReadStringEnc
//   EncryptUserDataEnc


// Summary: does a standard protection check
// Syntax:
//[ <Result> = ] ProtCheck ()
// return value is 0 (success) or an error code
PROCEDURE ProtCheck()
hLib, ret_code are system int

// set the DRIS to have random values
RandomSet()
// then set the values we want to use
DRIS.header = "DRIS"
DRIS.size = Length(DRIS)
DRIS.dpfunction = 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...

// Load the protection DLL.
hLib = LoadDLL(protectdllname)
IF hLib = 0 THEN
	Info("Cannot load " + protectdllname, "This DLL should be in the same folder as this executable")
	RESULT -1
END

//do a protection check
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)
FreeDLL(hLib)

IF ret_code <> 0 THEN								// an error occured so display an appropriate error message
	DisplayError(ret_code, DRIS.ext_err)
	RESULT ret_code
END

// later in your code you can check other values in the DRIS...
IF (DRIS.sdsn <> MY_SDSN) THEN
	Info("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.")
	RESULT -1
END

IF (ExtractString(DRIS.prodcode, 1, Charact(0)) <> MY_PRODCODE) THEN
	Info("Incorrect Product Code. Please modify your source code so that MY_PRODCODE is set to be your Product Code.")
	RESULT -1	
END

// later on in your program you can check the return code again
IF (DRIS.ret_code <> 0) THEN
	Info("Dinkey Dongle protection error")
	RESULT -1
END

Info("It worked!")

// Summary: does a standard protection check and executes an algorithm
// 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 Lite models copy the sample
// code from DinkeyLook
// Syntax:
//[ <Result> = ] ProtCheckWithAlg ()
// return value is 0 (success) or an error code
PROCEDURE ProtCheckWithAlg()
hLib, ret_code are system int

// set the DRIS to have random values
RandomSet()
// then set the values we want to use
DRIS.header = "DRIS"
DRIS.size = Length(DRIS)
DRIS.dpfunction = EXECUTE_ALGORITHM					// protection check and execute specified 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
// !!!! 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

// Load the protection DLL.
hLib = LoadDLL(protectdllname)
IF hLib = 0 THEN
	DelayBeforeClosing(1000)
	Info("Cannot load " + protectdllname, "This DLL should be in the same folder as this executable")
	RESULT -1
END

//do a protection check
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)
FreeDLL(hLib)

IF ret_code <> 0 THEN								// an error occured so display an appropriate error message
	DisplayError(ret_code, DRIS.ext_err)
	RESULT ret_code
END

// later in your code you can check other values in the DRIS...
IF (DRIS.sdsn <> MY_SDSN) THEN
	Info("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.")
	RESULT -1
END

IF (ExtractString(DRIS.prodcode, 1, Charact(0)) <> MY_PRODCODE) THEN
	Info("Incorrect Product Code. Please modify your source code so that MY_PRODCODE is set to be your Product Code.")
	RESULT -1	
END

// later on in your program you can check the return code again
IF (DRIS.ret_code <> 0) THEN
	Info("Dinkey Dongle protection error")
	RESULT -1
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
	Info("Dinkey protection error!", "You have not patched your algorithm in the MyAlgorithm routine")
	RESULT -1
END

Info("It worked!")

// Summary:
// !!!! You should replace this function with the one generated by the
// "generate source code" button in Algorithm tab for DinkeyAdd (if you have specified an algorithm)
// or from DinkeyLook if you are using a Dinkey Lite dongle. You can modify the C code to make it compatiable with Windev.
// Syntax:
//[ <Result> = ] MyAlgorithm (<var_a> is int, <var_b> is int, <var_c> is int, <var_d> is int, <var_e> is int, <var_f> is int, <var_g> is int, <var_h> is int)
//
PROCEDURE MyAlgorithm(var_a is int, var_b is int, var_c is int, var_d is int, var_e is int, var_f is int, var_g is int, var_h is int)
RESULT var_a + var_b + var_c + var_d + var_e + var_f + var_g + var_h


// Summary: This function does a protection check and writes the string "Hello, World!" to the 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.
// NB you can easily modify the code to write a byte array instead of a string
// Syntax:
//[ <Result> = ] WriteString ()
// return value is 0 (success) or an error code
//
PROCEDURE WriteString()
hLib, ret_code are system int
OurString is fixed string on 1024 = "Hello, World!"      // NB max. data write is 1K

// set the DRIS to have random values
RandomSet()
// then set the values we want to use
DRIS.header = "DRIS"
DRIS.size = Length(DRIS)
DRIS.dpfunction = WRITE_DATA_AREA					// protection check and write specified 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 = Length(Left(OurString))			// the length of the string (in this case 13 bytes)
DRIS.rw_data_ptr = &OurString

// Load the protection DLL.
hLib = LoadDLL(protectdllname)
IF hLib = 0 THEN
	Info("Cannot load " + protectdllname, "This DLL should be in the same folder as this executable")
	RESULT -1
END

//do a protection check
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)	
FreeDLL(hLib)

IF ret_code <> 0 THEN								// an error occured so display an appropriate error message
	DisplayError(ret_code, DRIS.ext_err)
	RESULT ret_code
END

// later in your code you can check other values in the DRIS...
IF (DRIS.sdsn <> MY_SDSN) THEN
	Info("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.")
	RESULT -1
END

IF (ExtractString(DRIS.prodcode, 1, Charact(0)) <> MY_PRODCODE) THEN
	Info("Incorrect Product Code. Please modify your source code so that MY_PRODCODE is set to be your Product Code.")
	RESULT -1	
END

// later on in your program you can check the return code again
IF (DRIS.ret_code <> 0) THEN
	Info("Dinkey Dongle protection error")
	RESULT -1
END

Info("It worked!")


// Summary: This function does a protection check and reads 13 bytes of data from the 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.
// NB you can amend this code to read a byte array instead of a string if you prefer.
// Syntax:
//[ <Result> = ] ReadString ()
// return value is 0 (success) or an error code
//
PROCEDURE ReadString()
hLib, ret_code are system int
OurString is fixed string on 1024					// NB max. data read is 1K

// set the DRIS to have random values
RandomSet()
// then set the values we want to use
DRIS.header = "DRIS"
DRIS.size = Length(DRIS)
DRIS.dpfunction = READ_DATA_AREA					// protection check and read 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
DRIS.rw_data_ptr = &OurString

// Load the protection DLL.
hLib = LoadDLL(protectdllname)
IF hLib = 0 THEN
	Info("Cannot load " + protectdllname, "This DLL should be in the same folder as this executable")
	RESULT -1
END

//do a protection check
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)	
FreeDLL(hLib)

IF ret_code <> 0 THEN								// an error occured so display an appropriate error message
	DisplayError(ret_code, DRIS.ext_err)
	RESULT ret_code
END

// later in your code you can check other values in the DRIS...
IF (DRIS.sdsn <> MY_SDSN) THEN
	Info("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.")
	RESULT -1
END

IF (ExtractString(DRIS.prodcode, 1, Charact(0)) <> MY_PRODCODE) THEN
	Info("Incorrect Product Code. Please modify your source code so that MY_PRODCODE is set to be your Product Code.")
	RESULT -1	
END

// later on in your program you can check the return code again
IF (DRIS.ret_code <> 0) THEN
	Info("Dinkey Dongle protection error")
	RESULT -1
END

Info("It worked! Dinkey Dongle data area at offset 7 is:", OurString)


// Summary: 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. NB you can modify the code to encrypt byte arrays instead of strings
// NB you can amend this code to read a byte array instead of a string if you prefer.
// Syntax:
//[ <Result> = ] EncryptUserData ()
// return value is 0 (success) or an error code
//
PROCEDURE EncryptUserData()
hLib, ret_code are system int
OurString is fixed string on 1024 = "Hello, World!"      // NB max. data we can encrypt is 1K

// set the DRIS to have random values
RandomSet()
// then set the values we want to use
DRIS.header = "DRIS"
DRIS.size = Length(DRIS)
DRIS.dpfunction = ENCRYPT_USER_DATA					// protection check and encrypt specified 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 = Length(Left(OurString))			// the length of the string (in this case 13 bytes)
DRIS.rw_data_ptr = &OurString

// Load the protection DLL.
hLib = LoadDLL(protectdllname)
IF hLib = 0 THEN
	Info("Cannot load " + protectdllname, "This DLL should be in the same folder as this executable")
	RESULT -1
END

//do a protection check
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)	

IF ret_code <> 0 THEN								// an error occured so display an appropriate error message
	DisplayError(ret_code, DRIS.ext_err)
	FreeDLL(hLib)
	RESULT ret_code
END

// NB can add code to check other elements of the DRIS e.g. SDSN, ProductCode (see ProtCheck function)

// Now decrypt the same data to get the original values
RandomSet()
// then set the values we want to use
DRIS.header = "DRIS"
DRIS.size = Length(DRIS)
DRIS.dpfunction = DECRYPT_USER_DATA					// protection check and decrypt specified 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									// the length of the string (in this case 13 bytes)
DRIS.rw_data_ptr = &OurString						// NB the data is encrypted at this point

ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)	
FreeDLL(hLib)

IF ret_code <> 0 THEN								// an error occured so display an appropriate error message
	DisplayError(ret_code, DRIS.ext_err)
	RESULT ret_code
END

// NB can add code to check other elements of the DRIS e.g. SDSN, ProductCode (see ProtCheck function)

Info("It worked! Dinkey Dongle data area at offset 7 is:", OurString)


// !!!!!!!!!!!   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 (you will have to adapt the C code generated by DinkeyAdd)
PROCEDURE MyRWAlgorithm(var_a is int, var_b is int, var_c is int, var_d is int, var_e is int, var_f is int, nVar_g is int, nVar_h is int)
RESULT BinaryXOR(BinaryXOR(BinaryXOR(BinaryXOR(BinaryXOR(var_a, var_b), var_c), var_d), var_e), var_f)

// !!!! please overwrite this function with the one generated by DinkeyAdd
// (just modify the parameters specified in DinkeyAdd in the positiions indicated below):
// Note arrays in Windev are 1-base which makes it a real pain
PROCEDURE CryptDRIS()
i, j, k are int
bigseed, S are array of 256 1-byte unsigned int
DRIS_bytes is an array of Length(DRIS) 1-byte unsigned int
temp, t are 1-byte unsigned int
 
FOR i = 1 _TO_ 256 STEP 8
	Transfer(&bigseed[i], &DRIS.seed1, 4) 
	Transfer(&bigseed[i+4], &DRIS.seed2, 4) 
END

FOR i = 0 _TO_ 255
	S[i+1] = i
END

j = 0
FOR i = 0 _TO_ 255
	j = (j + S[i+1] + bigseed[i+1] + 123) modulo 256	// parameter 1, modify 123
	temp = S[i+1]
	S[i+1] = S[j+1]
	S[j+1] = temp
END

Transfer(&DRIS_bytes, &DRIS, Length(DRIS))				// convert DRIS to bytes

i = 0
j = 0
FOR k = 17 _TO_ Length(DRIS)
	i = (i + 1) modulo 256
	j = (j + S[i+1] + 212) modulo 256					// parameter 2, modify 212
	temp = S[i+1]
	S[i+1] = S[j+1]
	S[j+1] = temp
	t = (S[i+1] + S[j+1] + 97) modulo 256				// parameter 3, modify 97
	DRIS_bytes[k] = BinaryXOR(DRIS_bytes[k], S[t+1])
END

Transfer(&DRIS, &DRIS_bytes, Length(DRIS))		// convert back again



// Note arrays in Windev are 1-base which makes it a real pain
// Summary: <specify the procedure action>
// Syntax:
//CryptApiData (<data>, <enc_length> is 4-byte unsigned int, <alg_ans> is int)
PROCEDURE CryptApiData(data, enc_length is unsigned int, alg_ans is int)
i, j, k are int
bigseed, S are array of 256 1-byte unsigned int
temp, t are 1-byte unsigned int

FOR i = 1 _TO_ 256 STEP 8
	Transfer(&bigseed[i], &DRIS.seed1, 4) 
	Transfer(&bigseed[i+4], &DRIS.seed2, 4) 
END

FOR i = 0 _TO_ 255
	S[i+1] = i
END

j = 0
FOR i = 0 _TO_ 255
	j = (j + S[i+1] + bigseed[i+1] + BinaryAND(alg_ans, 0xff)) modulo 256
	temp = S[i+1]
	S[i+1] = S[j+1]
	S[j+1] = temp
END

i = 0
j = 0
FOR k = 1 _TO_ enc_length
	i = (i + 1) modulo 256
	j = (j + S[i+1] + (BinaryAND(alg_ans, 0xff00))/256) modulo 256
	temp = S[i+1]
	S[i+1] = S[j+1]
	S[j+1] = temp
	t = (S[i+1] + S[j+1] + (BinaryAND(alg_ans, 0xff0000))/65536) modulo 256
	data[k] = BinaryXOR(data[k], S[t+1])
END


// Summary: does a standard protection check and encrypt the DRIS we pass and from the API.
// We encrypt the DRIS passed to the API. !!!! Patch the CryptDRIS function in this file from source code generated by DinkeyAdd.
// Syntax:
//[ <Result> = ] ProtCheckEnc ()
// return value is 0 (success) or an error code
PROCEDURE ProtCheckEnc()
hLib, ret_code are system int

// set the DRIS to have random values
RandomSet()
// then set the values we want to use
DRIS.header = "DRIS"
DRIS.size = Length(DRIS)
DRIS.dpfunction = 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...

// Load the protection DLL.
hLib = LoadDLL(protectdllname)
IF hLib = 0 THEN
	Info("Cannot load " + protectdllname, "This DLL should be in the same folder as this executable")
	RESULT -1
END

CryptDRIS()											// encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)

//do a protection check
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)
FreeDLL(hLib)

CryptDRIS()											// decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)

IF ret_code <> 0 THEN								// an error occured so display an appropriate error message
	DisplayError(ret_code, DRIS.ext_err)
	RESULT ret_code
END

// later in your code you can check other values in the DRIS...
IF (DRIS.sdsn <> MY_SDSN) THEN
	Info("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.")
	RESULT -1
END

IF (ExtractString(DRIS.prodcode, 1, Charact(0)) <> MY_PRODCODE) THEN
	Info("Incorrect Product Code. Please modify your source code so that MY_PRODCODE is set to be your Product Code.")
	RESULT -1	
END

// later on in your program you can check the return code again
IF (DRIS.ret_code <> 0) THEN
	Info("Dinkey Dongle protection error")
	RESULT -1
END

Info("It worked!")


// Summary: does a standard protection check and executes an algorithm and encrypts the DRIS
// NB for this to work you must program at least one "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 Lite models copy the sample
// code from DinkeyLook.
// We encrypt the DRIS passed to the API. !!!! Patch the CryptDRIS function in this file from source code generated by DinkeyAdd.
// Syntax:
//[ <Result> = ] ProtCheckWithAlgEnc ()
// return value is 0 (success) or an error code
PROCEDURE ProtCheckWithAlgEnc()
hLib, ret_code are system int

// set the DRIS to have random values
RandomSet()
// then set the values we want to use
DRIS.header = "DRIS"
DRIS.size = Length(DRIS)
DRIS.dpfunction = EXECUTE_ALGORITHM					// protection check and execute specified 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
// !!!! 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

// Load the protection DLL.
hLib = LoadDLL(protectdllname)
IF hLib = 0 THEN
	DelayBeforeClosing(1000)
	Info("Cannot load " + protectdllname, "This DLL should be in the same folder as this executable")
	RESULT -1
END

CryptDRIS()											// encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)

//do a protection check
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)
FreeDLL(hLib)

CryptDRIS()											// decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)

IF ret_code <> 0 THEN								// an error occured so display an appropriate error message
	DisplayError(ret_code, DRIS.ext_err)
	RESULT ret_code
END

// later in your code you can check other values in the DRIS...
IF (DRIS.sdsn <> MY_SDSN) THEN
	Info("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.")
	RESULT -1
END

IF (ExtractString(DRIS.prodcode, 1, Charact(0)) <> MY_PRODCODE) THEN
	Info("Incorrect Product Code. Please modify your source code so that MY_PRODCODE is set to be your Product Code.")
	RESULT -1	
END

// later on in your program you can check the return code again
IF (DRIS.ret_code <> 0) THEN
	Info("Dinkey Dongle protection error")
	RESULT -1
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
	Info("Dinkey protection error!", "You have not patched your algorithm in the MyAlgorithm routine")
	RESULT -1
END

Info("It worked!")


// Summary: This function does a protection check and writes the string "Hello, World!" to the 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.
// NB you can easily modify the code to write a byte array instead of a string
// We encrypt the DRIS and Data passed to the API. !!!! Patch the CryptDRIS, CryptApiData and MyRWAlgorithm functions in this file from source code generated by DinkeyAdd.
// Syntax:
//[ <Result> = ] WriteStringEnc ()
// return value is 0 (success) or an error code
//
PROCEDURE WriteStringEnc()
hLib, ret_code are system int
alg_ans are int
OurString is fixed string on 1024 = "Hello, World!"      			// NB max. data write is 1K
OurString_bytes is array of 1024 1-byte unsigned int			// byte-array of the encrypted string

// set the DRIS to have random values
RandomSet()
// then set the values we want to use
DRIS.header = "DRIS"
DRIS.size = Length(DRIS)
DRIS.dpfunction = WRITE_DATA_AREA					// protection check and write specified 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 = Length(Left(OurString))			// the length of the string (in this case 13 bytes)
DRIS.rw_data_ptr = &OurString_bytes					// we convert the string to write to a byte array (so we can encrypt it) and then we pass that value to our API

// Load the protection DLL.
hLib = LoadDLL(protectdllname)
IF hLib = 0 THEN
	Info("Cannot load " + protectdllname, "This DLL should be in the same folder as this executable")
	RESULT -1
END

// calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code generated by DinkeyAdd
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 (we must first convert it to a byte array so we can encrypt)
Transfer(&OurString_bytes, &OurString, DRIS.rw_length)
CryptApiData(OurString_bytes, DRIS.rw_length, alg_ans)

CryptDRIS()											// encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)

//do a protection check
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)	
FreeDLL(hLib)

CryptDRIS()											// decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)

IF ret_code <> 0 THEN								// an error occured so display an appropriate error message
	DisplayError(ret_code, DRIS.ext_err)
	RESULT ret_code
END

// later in your code you can check other values in the DRIS...
IF (DRIS.sdsn <> MY_SDSN) THEN
	Info("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.")
	RESULT -1
END

IF (ExtractString(DRIS.prodcode, 1, Charact(0)) <> MY_PRODCODE) THEN
	Info("Incorrect Product Code. Please modify your source code so that MY_PRODCODE is set to be your Product Code.")
	RESULT -1	
END

// later on in your program you can check the return code again
IF (DRIS.ret_code <> 0) THEN
	Info("Dinkey Dongle protection error")
	RESULT -1
END

Info("It worked!")


// Summary: This function does a protection check and reads 13 bytes of data from the 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.
// NB you can amend this code to read a byte array instead of a string if you prefer.
// We encrypt the DRIS and Data passed to the API. !!!! Patch the CryptDRIS, CryptApiData and MyRWAlgorithm functions in this file from source code generated by DinkeyAdd.
// Syntax:
//[ <Result> = ] ReadStringEnc ()
// return value is 0 (success) or an error code
//
PROCEDURE ReadStringEnc()
hLib, ret_code are system int
alg_ans are int
OurString is fixed string on 1024					// NB max. data read is 1K
OurString_bytes is array of 1024 1-byte unsigned int	// byte-array of the encrypted string

// set the DRIS to have random values
RandomSet()
// then set the values we want to use
DRIS.header = "DRIS"
DRIS.size = Length(DRIS)
DRIS.dpfunction = READ_DATA_AREA					// protection check and read 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
DRIS.rw_data_ptr = &OurString_bytes					// read it to our byte array first and then convert to a string

// Load the protection DLL.
hLib = LoadDLL(protectdllname)
IF hLib = 0 THEN
	Info("Cannot load " + protectdllname, "This DLL should be in the same folder as this executable")
	RESULT -1
END

// calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code generated by DinkeyAdd
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()											// encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)

//do a protection check
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)	
FreeDLL(hLib)

CryptDRIS()											// decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)

IF ret_code <> 0 THEN								// an error occured so display an appropriate error message
	DisplayError(ret_code, DRIS.ext_err)
	RESULT ret_code
END

// later in your code you can check other values in the DRIS...
IF (DRIS.sdsn <> MY_SDSN) THEN
	Info("Incorrect SDSN! Please modify your source code so that MY_SDSN is set to be your SDSN.")
	RESULT -1
END

IF (ExtractString(DRIS.prodcode, 1, Charact(0)) <> MY_PRODCODE) THEN
	Info("Incorrect Product Code. Please modify your source code so that MY_PRODCODE is set to be your Product Code.")
	RESULT -1	
END

// later on in your program you can check the return code again
IF (DRIS.ret_code <> 0) THEN
	Info("Dinkey Dongle protection error")
	RESULT -1
END

// decrypt data we have just read (then convert to string)
CryptApiData(OurString_bytes, DRIS.rw_length, alg_ans)
Transfer(&OurString, &OurString_bytes, DRIS.rw_length)

Info("It worked! Dinkey Dongle data area at offset 7 is:", OurString)


// Summary: 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. NB you can modify the code to encrypt byte arrays instead of strings
// NB you can amend this code to read a byte array instead of a string if you prefer.
// We encrypt the DRIS and Data passed to the API. !!!! Patch the CryptDRIS, CryptApiData and MyRWAlgorithm functions in this file from source code generated by DinkeyAdd.
// Syntax:
//[ <Result> = ] EncryptUserDataEnc ()
// return value is 0 (success) or an error code
//
PROCEDURE EncryptUserDataEnc()
hLib, ret_code are system int
alg_ans is int
OurString is fixed string on 1024 = "Hello, World!"      // NB max. data we can encrypt is 1K
OurString_bytes is array of 1024 1-byte unsigned int	// byte-array of the encrypted string

// set the DRIS to have random values
RandomSet()
// then set the values we want to use
DRIS.header = "DRIS"
DRIS.size = Length(DRIS)
DRIS.dpfunction = ENCRYPT_USER_DATA					// protection check and encrypt specified 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 = Length(Left(OurString))			// the length of the string (in this case 13 bytes)
DRIS.rw_data_ptr = &OurString_bytes					// we convert the string to encrypt to a byte array (so we can encrypt it) and then we pass that to the API

// Load the protection DLL.
hLib = LoadDLL(protectdllname)
IF hLib = 0 THEN
	Info("Cannot load " + protectdllname, "This DLL should be in the same folder as this executable")
	RESULT -1
END

// calculate r/w algorithm answer - NB need to replace MyRWAlgorithm code with code generated by DinkeyAdd
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 (we must first convert it to a byte array so we can encrypt)
Transfer(&OurString_bytes, &OurString, DRIS.rw_length)
CryptApiData(OurString_bytes, DRIS.rw_length, alg_ans)

CryptDRIS()											// encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)

//do a protection check
ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)	

CryptDRIS()											// decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)

IF ret_code <> 0 THEN								// an error occured so display an appropriate error message
	DisplayError(ret_code, DRIS.ext_err)
	FreeDLL(hLib)
	RESULT ret_code
END

// NB can add code to check other elements of the DRIS e.g. SDSN, ProductCode (see ProtCheck function)

// Now decrypt the same data to get the original values
RandomSet()
// then set the values we want to use
DRIS.header = "DRIS"
DRIS.size = Length(DRIS)
DRIS.dpfunction = DECRYPT_USER_DATA					// protection check and decrypt specified 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									// the length of the string (in this case 13 bytes)
DRIS.rw_data_ptr = &OurString_bytes					// NB this wil still be the encrypted data at this point

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()											// encrypt DRIS (!!!!you should separate from DDProtCheck for greater security)

ret_code = CallDLL32(protectdllname, "DDProtCheck", &DRIS, 0)	
FreeDLL(hLib)

CryptDRIS()											// decrypt DRIS (!!!!you should separate from DDProtCheck for greater security)

IF ret_code <> 0 THEN								// an error occured so display an appropriate error message
	DisplayError(ret_code, DRIS.ext_err)
	RESULT ret_code
END

// NB can add code to check other elements of the DRIS e.g. SDSN, ProductCode (see ProtCheck function)

// decrypt the returned value and convert to a string
CryptApiData(OurString_bytes, DRIS.rw_length, alg_ans)
Transfer(&OurString, &OurString_bytes, DRIS.rw_length)
Info("It worked! Dinkey Dongle data area at offset 7 is:", OurString)

