Figure 1
Introduction
Every programmer knows about the Registry. Registry is a database to store data related to programs. Some very important information about installed hardware and software, are stored by Windows in registry. Windows has a utility to browse registry and make changes to it called regedit.exe, this is registry editor program. Figure 2 shows it.
Figure 2
I wrote some utility classes to demonstrate all of Registry capabilities. Using these classes are very easy. Windows Registry Editor (regedit.exe) has these capabilities:
- A tree to show hierarchy of Registry (Keys and Sub-Keys)
- A list to show Key's Value (Value name, Type of value and Value Data)
My classes support part two of registry editor capabilities (A list control to show Registry Values).
How to use
First of all add these files to your project
- HexEditBase.h, HexEditBase.cpp (for editing Binary values). I should thank Ch. Kuendig for his HexEditor that I used to complete my task.
- RegEditBinaryDialog.h, RegEditBinaryDialog.cpp
- RegEditDWORDDialog.h, RegEditDWORDDialog.cpp
- RegEditStringDialog.h, RegEditStringDialog.cpp
- RegistryListCtrl.h, RegistryListCtrl.cpp (main class)
Also add resources needed by these classes (Menu and Bitmap).
Dialog Based Programs:
Add a List Control to your dialog. Use Class Wizard to add a member variable with variable type CListCtrl
. Go to your dialog header file and rename your variable type from CListCtrl
to CRegistryListCtrl
. Remember to add RegistryListCtrl.h header file at top of your dialog definitioin. Now compile it. If no error occurs, everything goes right.
CRegistryListCtrl in action
When your program is running (like figure 1), and a key is open, CRegistryListCtrl
shows you all of value names stored in that key. The list shows items with full detail of them (eg. type of value and also value data). Every value name has at least one of these types:
- String type known as
REG_SZ
for storing string values
DWORD
type known as REG_DWORD
for storing integer values
- Binary type known as
REG_BINARY
for storing binary values. Generally speaking, structures or other complex data types!
CRegistryListCtrl
can change values of all that three types by it's dialogs. Figure 3, 4 and 5 show you these dialogs.
Figure 3 - Edit a string value
Figure 4 - Edit a DWORD value
Figure 5 - Edit a Binary value (HEX format)
For complete compatibility with Regedit.exe, I add some another features like adding menu support. These menus should be appear when a user pressed right click of mouse. These two menus are shown in figures 6 and 7. Menu 1 can add new items (and also new keys) and menu 2 shows a way to modify existing values.
Figure 6 - Adding new items
Figure 7 - Modify existing values
CRegistryListCtrl
has written to monitor changes in values on the fly. In other hand, if any changes occured by another programs or by regedit.exe, CRegistryListCtrl
shows it immediately! I use a thread to monitor specified key and report changes to CRegistryListCtrl
.
Working with CRegistryListCtrl
CRegistryListCtrl
has only one public member function: OpenRegKey()
:
void OpenRegKey(HKEY hMasterKey, CString SubKey)
hMasterKey
is Handle to a currently open key or any of the following predefined reserved handle values:
HKEY_CLASSES_ROOT
HKEY_CURRENT_CONFIG
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_USERS
and SubKey
is your desired key.
Example
CRegistryListCtrl m_RegList;
m_RegList.OpenRegKey(HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
All of other things will handle by CRegistryListCtrl
automatically.
How does CRegistryListCtrl Monitor Registry?
CRegistryListCtrl
has a static member function to monitor specified key of Registry. I used this static member function with a thread after calling OpenRegKey()
or when you refresh the list by pressing F5. This member function, named NotifyChangeRegKey()
notifies CRegistryListCtrl
when any changes occured to Registry.
Body of this static member function is as below:
UINT CRegistryListCtrl::NotifyChangeRegKey(void* pParam)
{
if (RunThread==FALSE)
RunThread=TRUE;
else
return 0;
DWORD dwFilter = REG_NOTIFY_CHANGE_LAST_SET;
CRegistryListCtrl* pThread=(CRegistryListCtrl*) pParam;
HANDLE hEvent;
HKEY hKey;
LONG lErrorCode;
lErrorCode = RegOpenKeyEx(pThread->m_hKey, pThread->m_SubKey,
0, KEY_NOTIFY, &hKey);
if (lErrorCode != ERROR_SUCCESS)
return 0;
hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (hEvent == NULL)
return 0;
lErrorCode = RegNotifyChangeKeyValue(hKey, TRUE,
dwFilter, hEvent, TRUE);
if (lErrorCode != ERROR_SUCCESS)
return 0;
DWORD Result;
Result=WaitForSingleObject(hEvent, INFINITE);
lErrorCode = RegCloseKey(hKey);
if (lErrorCode != ERROR_SUCCESS)
return 0;
if (!CloseHandle(hEvent))
return 0;
RunThread=FALSE;
if (Result == WAIT_FAILED)
return 0;
else
{
pThread->Refresh();
return 1;
}
After opening any key, the tread fired to monitor Registry changes. I used the following statement to fire up the thread:
AfxBeginThread(NotifyChangeRegKey, this);
The first parameter is name of static member function, and second is a pointer to CRegistryListCtrl
class. I used this technique for accessing member function and member variables of class within thread!
Future work
My future work is making a control to show hierarchy of Registry in a Tree. I will name it CRegistryTreeCtrl
. In addition to showing a tree of Keys and Subkeys, this tree monitor Registry for any changes in it's keys or subkeys and apply this changes on the fly! By using CRegistryListCtrl
and CRegistryTreeCtrl
together, you can create regedit by yourself in 3 minutes. Enjoy it!