Author: Jonas Bilinkevicius
How do I add a password to a Paradox table using nothing but code?
Answer:
It is said that necessity is the mother of invention. And I've found that saying to
ring true time and time again. With respect to the subject at hand, I didn't need
to know how to do this until I actually had to do it with a program that I needed
to write.
But before I started out, I did the usual thing by asking myself some questions:
Is there a method in an existing component (for our purposes TTable) that can do
this? Why reinvent the wheel?
If not, is there any resource available that might be able to do this? Again, why
reinvent the wheel?
If the answer to both questions is "No," then I know I have to build the capability
myself.
You might be thinking, why did I spend time with the discussion above? Well folks,
we live in an object-oriented world; moreover, we live in a world where there are a
lot of software developers. Someone, somewhere had to think the along the same
lines. So as a rule of thumb, before I make an attempt to write a specialized
function or component, I always do research to make sure it hasn't been created
elsewhere. That said, let's move on, shall we?
First of all, let's talk about Paradox passwords. Paradox has a hierarchical
password system. Each table can have a master password that defines any access to
it. In addition a table can have several auxilliary passwords that define table and
field rights, limiting access in very specialized ways.
In general, though, I've found that encrypting a table with just a master table is
adequate because most of the programs I've created that require data encryption
only require "all or nothing" security. Besides, having to cover the ins and outs
of auxilliary passwords in Delphi would have created an artilce that was just too
long. In any case, let me list the code below that will add a master password to a
Paradox table, then we'll discuss particulars following it. Here goes...
1 procedure EncryptPDOXTable(TableName,
2 Password: string);
3 var
4 TblDesc: CRTblDesc;
5 LocDB: TDatabase;
6 begin
7 //Initialize the BDE
8 Check(DBIInit(nil));
9
10 //Initialize random number generator
11 Randomize;
12
13 //Create a local, non-owned database object that
14 //points to the path associated with the table.
15 LocDB := TDatabase.Create(nil);
16 with LocDB do
17 begin
18 Params.Add('path=' + ExtractFilePath(TableName));
19 DatabaseName := 'PDOXEncryptDB' + IntToStr(Random(50));
20 DriverName := 'STANDARD';
21 Connected := True;
22 end;
23
24 //Now, initialize the Table Descriptor with the values
25 //required to set a master password.
26 FillChar(TblDesc, SizeOf(CRTblDesc), 0);
27 StrPCopy(TblDesc.szTblName, ExtractFileName(TableName));
28 with TblDesc do
29 begin
30 bProtected := True;
31 StrPCopy(TblDesc.szPassword, Password);
32 end;
33
34 //Now do the restructure.
35 try
36 Check(DbiDoRestructure(LocDB.Handle, 1, @TblDesc,
37 nil, nil, nil, False));
38 finally
39 LocDB.Free;
40 DBIExit;
41 end;
42 end;
I think you've figured out by now that to create a master password in a Paradox
table, you have to use direct BDE calls. And while it may seem a bit complex, it's
actually pretty easy. You'll notice that I put a couple of words in the code in
boldface type. These are the two things that you really have to worry about as far
as setting a password. The other stuff is pretty routine stuff. So looked at from
that perspective simplifies the process entirely. Why don't we discuss the code in
a bit more detail.
The first things that I do in the procedure is to initialize the BDE and create a
TDatabase object. You'll find that almost all things that you do in the BDE require
a database handle of some sort. DbiDoRestructure is no exception. With respect to
initializing the BDE, that's purely an option, but something that I've done as a
habit primarily because some of my programs don't make use of any data aware
components, and thus won't initialize the BDE by default. If you make calls to the
BDE without it having been initialized in some way, you'll get an initialization
error. So it's a good idea to do this.
The next thing that happens in the code is that I initialize a table descriptor
structure. This is a standard structure defined in the BDE that tells BDE functions
that use it, like DbiDoRestructure, about the table that they're going to work
with. CRTblDesc is a fairly complex structure that has substructures attached to
it. If you want to know more about what kinds of fields are in this structure, I
suggest looking in the BDE help file in the BDE directory on your hard disk. But
the way cool thing about CRTblDesc is that you only need to fill in the fields that
are pertinent to the operation you want to perform. In the case of adding a
password to a table, all you need to fill in are the szTblName field and szPassword
field. That's it.
Then, once the structure has been filled with proper values, it's a simple matter
of calling DbiDoRestructure to restructure the table. We supply the handle to the
database that was created at the top, the number of table descriptors we're using
(1), the address to the table descriptor, then set the next three parameters to
"nil" and the last parameter to False. Easy.
If you want to know more about using DbiDoRestructure (since it's obviously used to do many more table operations than what I just discussed) I encourage you to study the online help, or obtain a copy of the "Borland Database Engine Developer's Guide" which you can purchase directly from Borland. Cheers!
|