The profile API and its encapsulation in a group of C++ classes

Written by Gordon Zeglinski

Introduction
Profile Files (aka INI files) are used in most OS/2 applications. In this issue, we will look at the profile API and then encapsulate it within a group of C++ classes.

The Profile API
In this section, we will look at the functions in the profile API that will be used to create the C++ classes.

Opening the File
Before we can read or write to our own profile files, we must open the profile file. The PrfOpenProfile function returns a handle to the opened profile file, and takes an anchor block handle and file name as arguments. The function prototype follows: HINI PrfOpenProfile(HAB hab,PSZ ProfileName)

Closing the File
Of course, we should close any INI file we open. The handle returned by PrfOpenProfile is this function's only argument. BOOL PrfCloseProfile(HINI hini)

Profile File Structure
Now that we can open and close profile files, we need to write and read from them. Before we can proceed, however, we will look at how profile files are organized. Data is stored by an application name and key name. Both the application and key names are strings. One can conceptually think of the file structure as follows:



Keys within a given application must be unique, but they do not have to be unique within the profile file. Application strings must be unique within the profile file.

Writing Data
Data can be written to the profile file using either of the following functions: BOOL PrfWriteProfileData(HINI hini,                         PSZ pszApp,                          PSZ pszKey,                          PVOID pData,                          ULONG cchDataLen); BOOL PrfWriteProfileString(HINI hini,                           PSZ pszApp,                            PSZ pszKey,                            PSZ pszData); The pData parameter in PrfWriteProfileData is the address of the data to be written while cchDataLen is the length of the data. This function can be used to write binary data to the profile file, while the PrfWriteProfileString function writes a NULL terminated string only.

Reading Data
The profile file API provides three functions which can be used to read in data from the application/key pair. Two of these functions are just the inverse of the two read functions, while the third function converts a number stored as a string into an integer. Finally, there is a function which returns the length of the data stored under an application/key pair. The prototypes for these functions follow: BOOL PrfQueryProfileData(HINI hini,                         PSZ pszApp,                          PSZ pszKey,                          PVOID pBuffer,                          PULONG pulBufferMax); ULONG PrfQueryProfileString(HINI hini,                            PSZ pszApp,                             PSZ pszKey,                             PSZ pszDefault,                             PVOID pBuffer,                             ULONG cchBufferMax); LONG PrfQueryProfileInt(HINI hini,                        PSZ pszApp,                         PSZ pszKey,                         LONG lDefault); BOOL PrfQueryProfileSize(HINI hini,                         PSZ pszApp,                          PSZ pszKey,                          PULONG pDataLen); The functions PrfQueryProfileSize and PrfQueryProfileData can be used to enumerate the application and key values (see the PM Reference for details). The functions PrfQueryProfileString and PrfQueryProfileInt allow the programmer to specify default values. This is very handy when the application is executed for the first time and its profile information may not be present.

Encapsulating The Profile API
As with all first attempts at encapsulation, we will wrap the profile API loosely with a C++ class. To do this, we will have have member functions for reading and writing data, and data members to store the profile file's name and handle. Following is the class definition for the base ProfileFile class: You will notice that each of the API functions we looked at has a corresponding member function. In addition, we added a function to write an integer that can be read later by the GetInt member function.

The system and user INI files, have predefined handles. We will subclass ProfileFile to allow us to use the same encapsulation method on the system and user INI files. Following are the definitions of these two classes: The use of these classes is pretty straight forward. The following sample code will show some of the basics. The above program opens the file "APP.INI", then attempts to read a string from this file. If the application/key pair is not present, SomeString will contain the value "Default String" on return from GetString. SomeString is then written to the user INI file under the application/key pair "Application"/"Key".

The files INIFLOBJ.H and INIFLOBJ.CPP contain the source code necessary to compile the profile classes.

Summary
In this issue, we have examined the profile file API and encapsulated it. You should now be able to use profile files in your application.