SAFE REGISTRY AND INI FILE ALTERNATIVE
Intermediate level
by Alyce Watson, 2002

Home

Liberty BASIC News
Safe Registry and Ini File Alternative
Deleting and Renaming Disk Files
Segments and Flushing
Flat Toolbar with Toolips
Translating 32-bit VB API Calls
Event-Driven Programming Concepts
Spotlight on the Community!
ODBC in Liberty BASIC
Hex Viewer
Listing Files Recursively
Registering Hot Keys
Preventing more than 1 instance
Multi-Coloured Text Input Boxes
Images on Buttons and Statictext
Two Demos by David Conner

Did you ever wonder how a program can remember the list of your most recently opened files, or your font preference, or that you are a registered user? There are several ways this can be done. One way is to write a simple text file, called an "ini" file.

INI FILES
"Ini" is short for "initialization". Liberty BASIC has an ini file that contains your font preference, your list of recent files, your list of externals, and other preferences and records. It is called lbasic302.ini and you will find it in the same folder that contains your copy of Liberty BASIC. When Liberty BASIC starts up, it reads the information in this file, and uses it to set your prefered font, list your recent files in the File menu, and so on. You can open this file in a texteditor and read it.

The gui designer that comes with Liberty BASIC, Freeform, has an ini file. The open source Liberty BASIC editor that was developed in a series of tutorials in this newsletter, also has an ini file, and ini files were the subject of an earlier newsletter article. See the attached version of the open source editor for an ini file example. The user's font preference and three most recently opened files are written to the ini file.

WRITING TO THE REGISTRY
Windows has a repository of information about the way it works. This is called The Registry. Windows looks in the registry to see which shortcuts should be displayed on your desktop, to record your list of recently opened files, to record your choice of desktop color scheme, display resolution, and all kinds of other information. Applications can write to the registry. This is a very bad idea for novice programmers! If the registry becomes corrupt, Windows may not function properly, or some applications may not function properly. In the worst case, the computer may not be usable at all! Considering the risks involved, it makes little sense to store information in the registry when something like an ini file will work just fine.


USING THE API TO CREATE AN INI FILE
The two functions, WritePrivateProfileStringA and GetPrivateProfileStringA provide an easy and precise way to write to and read from initialization files. These "ini" files are simple text files. Use this method as an alternative to writing information to the Windows registry. Tampering with the registry can have dire results, even causing Windows to become unusable. Writing to a private ini file can only have an impact on the single program referenced.

You might want to use ini files to record a user's list of recently opened files, or his preferences for use of the program, like syntax color "on" or "off", or even whether he is a registered user of your program.


WRITING AN INI FILE BY API
WritePrivateProfileStringA

First, we'll examine writing to a private ini file. Here is the syntax of the function, which is a part of kernel32.dll:

calldll #kernel32, "WritePrivateProfileStringA", _
Section$ as ptr, _    'section name
Entry$ as ptr, _      'entry name
String$ as ptr, _     'actual entry
FileName$ as ptr, _   'name of ini file
result as long

NOTE: The syntax above is for LB3. Syntax for this function for LB2 usage is included at the end of this article.

Following, find the descriptions for each argument of the function:

********
Section$
Points to a null-terminated string that specifies the section name to which a string will be copied. Liberty BASIC automatically adds the necessary single null terminator, which is chr$(0), so we don't need to add it. If the section does not exist, it will be created. If you were to read the file in a texteditor, this entry would look like this -- the section name, contained in square brackets:

[section]

If the section were called "user", it would look like this:
[user]


******
Entry$
Points to a null-terminated string containing the entry associated with the value string. If the entry does not exist it will be created. If this is NULL (""), the entire section is deleted. If you were to read the file in a texteditor, this entry would look like this -- the Entry$ followed by an = sign, followed by the String$

Entry=String

If the Entry was called "name" and its value was "Carl Gundel", it would look like this:
name=Carl Gundel

*******
String$
Points to the null-terminated string value to be written to the file. If this is NULL, (""), the Entry$ entry is deleted from the file.

Entry=String

If the Entry was called "name", and the String$ was "Carl Gundel",it would look like this:
name=Carl Gundel

*********
FileName$
Points to a null-terminated string that names the INI file. If this name is a fully-qualified path and file name, it will be used. If there is no path, Windows searches for the file in the Windows directory. If it doesn't exist, it will be created.

******
result
Returns zero if it fails, or nonzero if it is successful.


DEMO
Here is a demo. After running this small routine, look in the Windows folder for the file "testme.ini". Open it in Notepad to see the result. Notice that your program does not need to "open" or "close" the file as you would normally do when writing to a file in Liberty BASIC.

Section$="User"
Entry$="Name"
String$="Carl Gundel"
FileName$="testme.ini"

CallDLL #kernel32, "WritePrivateProfileStringA", _
Section$ As ptr, _
Entry$ As ptr, _
String$ As ptr, _
FileName$ As ptr, _
result As long

This function can be written on a single line. Imagine that, writing information to an ini file with a single line of code! The following line may line-wrap in your text editor, but you may type or copy/paste it into the LB editor to run it, making sure to eliminate any line wraps. The single line constitutes an entire program.

calldll #kernel32, "WritePrivateProfileStringA","User" as ptr,"Name" as ptr,"Carl Gundel" as ptr,"testme.ini" as ptr, result as long

I ran the single-line program, then looked in my Windows folder for the file, "testme.ini" and this is what it contained:

[User]
Name=Carl Gundel

We can use this method to record many kinds of information.


READING AN INI FILE BY API
GetPrivateProfileStringA
This function reads a specific ini file. Many arguments are the same as the ones in WritePrivateProfileStringA. There are some additional arguments, which will be explained later.

Section$, and FileName$ are explained earlier in the decription of WritePrivateProfileStringA.


******
Entry$
Points to the null-terminated string that is associated with the value string. If this parameter is empty, the return string will contain a list of all values in the specified section, separated by null characters, and terminated with double null characters.


********
Default$
Points to a null-terminated string that specifies the default value for the given entry if the entry cannot be found in the initialization file. This parameter must never be NULL or empty. You might want to specify a value that makes it clear that this section of the ini file was blank.

Default$ = "no name given"


*************
ReturnString$
Points to a null-terminated string that will contain the key value stored in the ini file. If the key value cannot be found, this buffer will contain the contents of the Default$ value. There is an important difference in the use of this string argument in GetPrivateProfileStringA. We will be reading data that is placed into this variables by the API function. This means that we must pass this argument "By Reference". Passing it this way means that we are not just passing the value of the string, we are passing its memory address so that the function can alter the data contained at that address. To let Liberty BASIC know that we want to pass the argument "By Reference", we include a null-termination on the string, like this:

ReturnString$ = space$(100) + chr$(0)

Above, we are creating a buffer, or location in memory that is large enough to contain the data that will be placed there by the function.


**********
SizeString
This parameter specifies the length of the buffer, ReturnString$


******
result
The return value specifies the number of bytes copied to the specified buffer, not including the terminating null character. This means that it specifies the length of the text that the function placed into the buffer. We can use this information to read the value in the ini file without extraneous characters that might be tacked onto the end.


Here is a working example, that reads the values written to "testme.ini" that were produced in the routine above:

Section$="User"
Entry$="Name"
FileName$="testme.ini"
Default$ = "no name" + Chr$(0)
SizeString=100
ReturnString$=Space$(SizeString)+Chr$(0)

CallDLL #kernel32, "GetPrivateProfileStringA", _
Section$ As ptr, _
Entry$ As ptr, _
Default$ As ptr, _
ReturnString$ As ptr, _
SizeString As long, _
FileName$ As ptr, _
result As long

Print "The key is "
Print Left$(ReturnString$,result)
End

If you were now to use Notepad to open "testme.ini" found in the Windows directory, it would look like this:
[User]
Name=Carl Gundel


DEMO TO RECORD USER'S PASSWORD
Here is a small demo that checks the ini file to see if the user has registered. You would, of course, put your own code to handle the situation. The demo simply gives a notice telling if the user is registered when the program starts. There is a button that the user can click to enter his password. Run the program for the first time, and you will get a "Not registered." notice. Click the button and type the proper password. Close the program. Run the program again, and you should receive notice that you are a "Registered user."

This demo is similar to the earlier demos, but it uses a different section and entry name:

Section$="Register"
Entry$="Password"


nomainwin
button #1, "Register",[reg],UL,10,10,120,26
statictext #1, "Password = 'Official'",10,50,200,30
open "Register My App" for window_nf as #1
print #1, "trapclose [quit]"

gosub [readReg] 'see if user has registered

if key$<>"Official" then
notice "Not registered."
else
notice "Registered user."
end if

wait


[quit]
close #1:end

[reg]
prompt "Enter password";pw$
if pw$="" then
notice "Not a valid password."
end if

Section$="Register"
Entry$="Password"
String$=pw$
FileName$="testme.ini"

CallDLL #kernel32, "WritePrivateProfileStringA", _
Section$ As ptr, _
Entry$ As ptr, _
String$ As ptr, _
FileName$ As ptr, _
result As long
wait


[readReg]
Section$="Register"
Entry$="Password"
FileName$="testme.ini"
Default$ = "no password" + Chr$(0)
SizeString=100
ReturnString$=Space$(SizeString)+Chr$(0)

CallDLL #kernel32, "GetPrivateProfileStringA", _
Section$ As ptr, _
Entry$ As ptr, _
Default$ As ptr, _
ReturnString$ As ptr, _
SizeString As long, _
FileName$ As ptr, _
result As long

key$=Left$(ReturnString$,result)
return

*******************************
LIBERTY BASIC 2, 16-BIT SYNTAX:
Here are the functions in LB2 syntax:

WRITING:
'open "kernel" for dll as #kernel
CallDLL #kernel32, "WritePrivateProfileString", _
Section$ As ptr, _
Entry$ As ptr, _
String$ As ptr, _
FileName$ As ptr, _
result As word
close #kernel  

READING:
'open "kernel" for dll as #kernel
calldll #kernel, "GetPrivateProfileString", _
Section$ as ptr, _
Entry$ as ptr, _
Default$ as ptr, _
ReturnString$ as ptr, _
SizeString as word, _
FileName$ as ptr, _
result as word
close #kernel  



Home

Liberty BASIC News
Safe Registry and Ini File Alternative
Deleting and Renaming Disk Files
Segments and Flushing
Flat Toolbar with Toolips
Translating 32-bit VB API Calls
Event-Driven Programming Concepts
Spotlight on the Community!
ODBC in Liberty BASIC
Hex Viewer
Listing Files Recursively
Registering Hot Keys
Preventing more than 1 instance
Multi-Coloured Text Input Boxes
Images on Buttons and Statictext
Two Demos by David Conner