In the last issue, you learned how to determine the version of Windows your program was running on. In this article you will apply that knowledge and learn some new techniques to help you find out who is using your program.
Many times when you install new software, the installation program automatically fills in your name and the name of your organization in a dialog. Where does the installation program find this information? Although there is no official way to get the name and organization for the registered user of Windows, there are a couple of places in the Registry that you can look for user information.
As it turns out, the first place you can look is dependent on whether your program is running on Win9x or Windows NT. If you recall from last month you can use the VCL variable, Win32Platform, to determine the platform the user is running under.
The Registry may contain values under RegisteredOwner and RegisteredOrganization. Windows 9x will have these values under the key
HKEY_LOCAL_MACHINE\Software\
Microsoft\Windows\CurrentVersion
Windows NT, on the other hand, uses the key
HKEY_LOCAL_MACHINE\Software\
Microsoft\Windows NT\CurrentVersion
The second place to look is the same for both Windows 9x and NT. You can look for the values DefName and DefCompany under the key
HKEY_LOCAL_MACHINE\Software\
Microsoft\MS Setup (ACME)\User Info
Your program can attempt to read these Registry values to determine the user name and company name. I say that your program can attempt to read these values because they may or may not exist in the Registry on a given user’s machine.
If the computer is on a network your program can query the network for the user name and the computer name. This will sometimes work even if the computer is not connected to a network.
The Windows API functions GetUserName() and GetComputerName() will give you what you need. For example:
char buf[256];
DWORD bufSize = sizeof(buf);
GetUserName(buf, &bufSize);
String userName = buf;
bufSize = sizeof(buf);
GetComputerName(buf, &bufSize);
String computerName = buf;
This is a simplified example in that it does not check the return value of the GetUserName() and GetComputerName() functions. Refer to Listing A for more complete examples of the use of these functions.
Note that the network user name and computer name do not contain the same information as discussed in the previous section. Nevertheless, they can be used to determine who is using your program. Whether you are looking for a plain-text user name and company name or a network user name and computer name depends on the needs of your program.
If both of the above methods fail, you can, of course, have your program ask the user for his or her name, company, or other information you require. This could be done through a standard VCL form, and, since there is nothing special about using a VCL form to ask for user information I won’t dwell on the subject further.
Listing A shows the source code for the example program’s main form. The example demonstrates the first two methods of obtaining user information. The example’s main form contains a memo that displays the user information, and the method used to obtain that information. We don’t show the main form’s header in order to save space.
Listing A: Main.cpp
#include <vcl.h>
#pragma hdrstop
#include <registry.hpp>
#include <memory>
using namespace std;
#include "Main.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
TMainForm *MainForm;
__fastcall TMainForm::
TMainForm(TComponent* Owner) : TForm(Owner)
{
MainMemo->Lines->Add("Owner/User Information:");
MainMemo->Lines->Add("");
GetRegisteredOwner(MainMemo->Lines);
MainMemo->Lines->Add("");
GetNetworkInfo(MainMemo->Lines);
}
void __fastcall
TMainForm::GetNetworkInfo(TStrings *lines)
{
char buf[300];
DWORD bufSize = sizeof(buf);
bool success = ::GetUserName(buf, &bufSize);
if (success)
lines->Add(
"Network user name = " + String(buf));
else
lines->Add(
"Unable to get network user name.");
bufSize = sizeof(buf);
success = ::GetComputerName(buf, &bufSize);
if (success)
lines->Add(
"Network computer name = " + String(buf));
else
lines->Add(
"Unable to get network computer name.");
}
static char *MS1_NT = "\\Software\\"
"Microsoft\\Windows NT\\CurrentVersion";
static char *MS1_9X = "\\Software\\"
"Microsoft\\Windows\\CurrentVersion";
static char *MS1_NAME = "RegisteredOwner";
static char *MS1_ORG = "RegisteredOrganization";
static char *MS2 = "\\Software\\"
"Microsoft\\MS Setup (ACME)\\User Info";
static char *MS2_NAME = "DefName";
static char *MS2_ORG = "DefCompany";
void __fastcall
TMainForm::GetRegisteredOwner(TStrings *lines)
{
try {
auto_ptr<TRegistry> registry(new TRegistry);
registry->RootKey = HKEY_LOCAL_MACHINE;
String key = (Win32Platform ==
VER_PLATFORM_WIN32_NT) ? MS1_NT : MS1_9X;
if (registry->OpenKey(key, false)) {
String name, org;
lines->Add(
"Checking HKEY_LOCAL_MACHINE" + key);
if (registry->ValueExists(MS1_NAME))
name = registry->ReadString(MS1_NAME);
if (registry->ValueExists(MS1_ORG))
org = registry->ReadString(MS1_ORG);
lines->Add(String(MS1_NAME) +" = " + name);
lines->Add(String(MS1_ORG) + " = " + org);
}
else
lines->Add("Unable to open "
"HKEY_LOCAL_MACHINE" + key);
lines->Add("");
if (registry->OpenKey(MS2, false)) {
String name, org;
lines->Add("Checking HKEY_LOCAL_MACHINE" +
String(MS2));
if (registry->ValueExists(MS2_NAME))
name = registry->ReadString(MS2_NAME);
if (registry->ValueExists(MS2_ORG))
org = registry->ReadString(MS2_ORG);
lines->Add(String(MS2_NAME)+ " = " + name);
lines->Add(String(MS2_ORG) + " = " + org);
}
else
lines->Add("Unable to open "
"HKEY_LOCAL_MACHINE" + String(MS2));
}
catch (...) {
lines->Add("Stopped by an exception.");
throw;
}
}
void __fastcall
TMainForm::OKBtnClick(TObject *Sender)
{
Close();
}