More Advanced Registry Techniques

By: Kenn Scribner for TechTalk


Run the demo program (all demos require Visual C++ 5.0!)
Download the demo source
Access the Registry using ActiveX control (ATL/VB)

Background: This is where you really get into the Registry...using the Win32 API.  It's frustrating.   It adds a bit of code.  But it also gives you precision and control, which when dealing with the Registry is pretty much what you want. 

Getting down to Business

Now that we've seen the basics, as demonstrated in the last two issues, it's time to get a bit more advanced. Last issue, we used MFC's handy built-in Registry handling. However, I mentioned a limitation and a burning question. As you've no doubt realized, the limitation is we only store information on a per-user basis in HKEY_CURRENT_USER when we use MFC's stuff. There isn't any way to access information in HKEY_LOCAL_MACHINE. The question is, of course, how do we get to the other parts of the Registry?

The answer is we abandon the built-in MFC Registry support for the areas MFC doesn't touch. I've seen commercially available class libraries for MFC that reach all of the Registry—we could design our own here if there is interest. For now, though, we're going to use the Win32 API calls directly. You'll find it isn't really difficult, but it can be tedious. It sometimes seems like you need to write an excessive amount of support code just to access a single Registry value. By way of example, when you download the demonstration code and examine it, you'll soon realize I store only a single value in HKEY_LOCAL_MACHINE, yet there are many, many lines of code there to support that value. Of course, it is an important value--an administrator password. But even so, we do have a place to store "global" information, and that's what is really important.

There are many Win32 API calls available to us when we want to deal directly with the Registry. However, you'll most likely use this subset the vast majority of the time:

RegCreateKeyEx()

RegQueryValueEx()

RegOpenKeyEx()

RegDeleteKey()

RegSetValueEx()

RegCloseKey()

You don't have to look too closely to see the file system analogy I referred to in the last issue. As with files, when you deal with the Registry you may create or open a key, set or read (query) its value, delete keys you no longer need, and close an open key. I use all of these calls in the demonstration code (most of them in the RegDemo2.cpp file). There are many other API calls with similar file API cousins, and a quick study through the "help" file should provide you with their names and uses.

The Registry API calls deal with a "key handle", and using a key handle is much like using a file handle. When you create or open a key, you reach any subkeys or values below it through its key handle. We would open a key and retrieve some data using code similar to this:

lnResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,_T("Software\\MyCompany\\MyApp\\"),0, KEY_READ,&hKey);

We typically check the result of the Registry action (open, in this case), and take further action based on that result code.

The demonstration program asks you for an administrator password the first time it is executed (or after you "clean the Registry" while using the application). For fun, I encrypt the password when I store it. I wouldn't consider it military-quality encryption, but it will definitely stump the average Registry browsing user. Being an administrator isn't all that exciting, but you can change the password or remove it from HKEY_LOCAL_MACHINE altogether. Oh boy. It does show how to work with the Registry using the Win32 API, however.

Some details to note…if you open a key using RegCreateKeyEx() (which you can do, see CRegDemo2::GetPasswd()), you effectively "lock" the key while it's open. This is the reason you can't really "clean" the Registry from within the application. MFC locked the key in HKEY_CURRENT_USER, which prevents us from deleting it while we're running the MFC application. That isn't normally a problem, as it's unusual to want to delete an entire key tree for the application while you're in the application. Your "uninstall" program would handle that. In our case, I wrote a "clean" program you might use to clear the Registry, or you could do it by hand using RegEdit. I do recommend you clean the Registry when you're done with this demonstration. There isn't much sense in polluting your Registry with demonstration data after you're done with the demo.

If you look up RegCreateKeyEx() in the "help" file, you'll see a note buried deep within the "Remarks" section which tells you an application can't create a key in HKEY_LOCAL_MACHINE. Don't believe it. In fact, if you fire up RegEdit and look into HKEY_LOCAL_MACHINE\Software, I'd bet you'll see some of your application software there. This must be a bug in the help file.

When you delete keys, you must delete them one at a time. That is, RegDeleteKey() works much like DOS' old rmdir command, in that you can't delete a key which contains subkeys (though the key and any stored data will be deleted even if the key contains values, unlike deleting subdirectories using rmdir).

I took the liberty of adding a lot of extra features to this issue's demonstration program. I threw in the window state save code from the last demonstration program, just so we'd also store something user-specific to HKEY_CURRENT_USER. If you've executed the demonstration, you'll also see I do some basic animation for fun (we may take a look at animation in future issues). Just select the "bubbles" or "squares" from the "Tools/Options…" menu. These options are also saved to the Registry in HKEY_CURRENT_USER. If you're wondering why the animation slows when the window is enlarged or maximized, it's because the BitBlt() function in CRegDemo2View::OnDraw() requires more time to copy the animation buffer to the screen device context. The larger the animation buffer, the more time it takes to move the memory. It was noticeable on my 200MHz MMX Pentium, but it was horrible on my 66MHz 486DX2! This is why Microsoft designed DirectDraw! But that’s another topic.

Probably the biggest "extra" I tossed into this issue was the use of Structured Exception Handling (SEH) when dealing with the Registry. With SEH, you "throw an exception" rather than return an error value. While there are many benefits to using SEH, probably the biggest in this case is SEH obviates the need to check a return code in the case of an error, and I don't need a special message box for each error. Perhaps we'll examine SEH in more detail in a future issue. For now, though, you should be able to use my CRegException class when working with the Registry on your own (you may want to be more creative with your error messages…). Granted, in this demo’s case it's probably overkill. In real applications, however, CRegException is a very handy class to keep around.

Master the Registry and you've mastered a huge chunk of heavy-duty Windows programming. In my opinion, you've taken the step from neophyte hacker to true guru! Pretty soon, jumping into the Registry to fix other application's information isn't so bad, either. You'd be amazed what you can find and change using RegEdit (be very careful doing this, however!). As usual, I created the demonstration program using Visual C++ version 5.0, so if you're using an older version, you'll need to delete my project file, create your own, and insert my source files into your new project. The source code may be downloaded from (see top of page). Give it a try! Happy coding, all of you Registry gurus!

Comments? Questions? Find a bug? Please send me a note!


[Back] [Left Arrow] [Right Arrow][Home]