You are on page 1of 26

Enumerating Registry Subkeys

The following example uses the RegQueryInfoKey, RegEnumKeyEx, and RegEnumValue functions to
enumerate the subkeys of the specified key. The hKey parameter passed to each function is a handle to an open
key. This key must be opened before the function call and closed afterward.

Copy Code
// QueryKey - Enumerates the subkeys of key and its associated values.
// hKey - Key whose subkeys and values are to be enumerated.

#include <windows.h>
#include <stdio.h>
#include <tchar.h>

#define MAX_KEY_LENGTH 255


#define MAX_VALUE_NAME 16383

void QueryKey(HKEY hKey)


{
TCHAR achKey[MAX_KEY_LENGTH]; // buffer for subkey name
DWORD cbName; // size of name string
TCHAR achClass[MAX_PATH] = TEXT(""); // buffer for class name
DWORD cchClassName = MAX_PATH; // size of class string
DWORD cSubKeys=0; // number of subkeys
DWORD cbMaxSubKey; // longest subkey size
DWORD cchMaxClass; // longest class string
DWORD cValues; // number of values for key
DWORD cchMaxValue; // longest value name
DWORD cbMaxValueData; // longest value data
DWORD cbSecurityDescriptor; // size of security descriptor
FILETIME ftLastWriteTime; // last write time

DWORD i, retCode;

TCHAR achValue[MAX_VALUE_NAME];
DWORD cchValue = MAX_VALUE_NAME;

// Get the class name and the value count.


retCode = RegQueryInfoKey(
hKey, // key handle
achClass, // buffer for class name
&cchClassName, // size of class string
NULL, // reserved
&cSubKeys, // number of subkeys
&cbMaxSubKey, // longest subkey size
&cchMaxClass, // longest class string
&cValues, // number of values for this key
&cchMaxValue, // longest value name
&cbMaxValueData, // longest value data
&cbSecurityDescriptor, // security descriptor
&ftLastWriteTime); // last write time

// Enumerate the subkeys, until RegEnumKeyEx fails.

if (cSubKeys)
{
printf( "\nNumber of subkeys: %d\n", cSubKeys);

for (i=0; i<cSubKeys; i++)


{
cbName = MAX_KEY_LENGTH;
retCode = RegEnumKeyEx(hKey, i,
achKey,
&cbName,
NULL,
NULL,
NULL,
&ftLastWriteTime);
if (retCode == ERROR_SUCCESS)
{
_tprintf(TEXT("(%d) %s\n"), i+1, achKey);
}
}
}

// Enumerate the key values.

if (cValues)
{
printf( "\nNumber of values: %d\n", cValues);

for (i=0, retCode=ERROR_SUCCESS; i<cValues; i++)


{
cchValue = MAX_VALUE_NAME;
achValue[0] = '\0';
retCode = RegEnumValue(hKey, i,
achValue,
&cchValue,
NULL,
NULL,
NULL,
NULL);

if (retCode == ERROR_SUCCESS )
{
_tprintf(TEXT("(%d) %s\n"), i+1, achValue);
}
}
}
}

void _tmain(void)
{
HKEY hTestKey;

if( RegOpenKeyEx( HKEY_CURRENT_USER,


TEXT("SOFTWARE\\Microsoft"),
0,
KEY_READ,
&hTestKey) == ERROR_SUCCESS
)
{
QueryKey(hTestKey);
}

RegCloseKey(hTestKey);
}
 

Deleting a Key with Subkeys


The example in this topic uses the RegOpenKeyEx, RegEnumKeyEx, and RegDeleteKey functions to delete a
registry key with subkeys.

To test this example, create the following registry key by using Regedt32.exe, and then add a few values and
subkeys:

HKEY_CURRENT_USER\Software\TestDir

After running the code, use the F5 key to refresh the registry data, and notice that the TestDir key is deleted.

Copy Code
#include <windows.h>
#include <stdio.h>
#include <strsafe.h>

//*************************************************************
//
// RegDelnodeRecurse()
//
// Purpose: Deletes a registry key and all it's subkeys / values.
//
// Parameters: hKeyRoot - Root key
// lpSubKey - SubKey to delete
//
// Return: TRUE if successful.
// FALSE if an error occurs.
//
//*************************************************************

BOOL RegDelnodeRecurse (HKEY hKeyRoot, LPTSTR lpSubKey)


{
LPTSTR lpEnd;
LONG lResult;
DWORD dwSize;
TCHAR szName[MAX_PATH];
HKEY hKey;
FILETIME ftWrite;

// First, see if we can delete the key without having


// to recurse.

lResult = RegDeleteKey(hKeyRoot, lpSubKey);

if (lResult == ERROR_SUCCESS)
return TRUE;
lResult = RegOpenKeyEx (hKeyRoot, lpSubKey, 0, KEY_READ, &hKey);

if (lResult != ERROR_SUCCESS)
{
if (lResult == ERROR_FILE_NOT_FOUND) {
printf("Key not found.\n");
return TRUE;
}
else {
printf("Error opening key.\n");
return FALSE;
}
}

// Check for an ending slash and add one if it is missing.

lpEnd = lpSubKey + lstrlen(lpSubKey);

if (*(lpEnd - 1) != TEXT('\\'))
{
*lpEnd = TEXT('\\');
lpEnd++;
*lpEnd = TEXT('\0');
}

// Enumerate the keys

dwSize = MAX_PATH;
lResult = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL,
NULL, NULL, &ftWrite);

if (lResult == ERROR_SUCCESS)
{
do {

StringCchCopy (lpEnd, MAX_PATH*2, szName);

if (!RegDelnodeRecurse(hKeyRoot, lpSubKey)) {
break;
}

dwSize = MAX_PATH;

lResult = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL,


NULL, NULL, &ftWrite);

} while (lResult == ERROR_SUCCESS);


}

lpEnd--;
*lpEnd = TEXT('\0');

RegCloseKey (hKey);

// Try again to delete the key.

lResult = RegDeleteKey(hKeyRoot, lpSubKey);


if (lResult == ERROR_SUCCESS)
return TRUE;

return FALSE;
}

//*************************************************************
//
// RegDelnode()
//
// Purpose: Deletes a registry key and all it's subkeys / values.
//
// Parameters: hKeyRoot - Root key
// lpSubKey - SubKey to delete
//
// Return: TRUE if successful.
// FALSE if an error occurs.
//
//*************************************************************

BOOL RegDelnode (HKEY hKeyRoot, LPTSTR lpSubKey)


{
TCHAR szDelKey[MAX_PATH*2];

StringCchCopy (szDelKey, MAX_PATH*2, lpSubKey);


return RegDelnodeRecurse(hKeyRoot, szDelKey);

void main()
{
BOOL bSuccess;

bSuccess = RegDelnode(HKEY_CURRENT_USER, TEXT("Software\\TestDir"));

if(bSuccess)
printf("Success!\n");
else printf("Failure.\n");
}
 

Determining the Registry Size


On Windows 2000, it is common for an installation utility to check the current and maximum size of the registry to
determine whether there is enough available space for the new data it will be adding. This sample demonstrates
how to do this programmatically using the "% Registry Quota In Use" performance counter within the System
object.

The following sample uses performance data helper (PDH) to obtain the counter value; it must be linked with
Pdh.lib. PDH is a high-level set of APIs used to obtain performance data.

Note  It is not necessary to implement this registry size-check on Windows Server 2003 or Windows XP because
they do not have a registry quota limit.

Copy Code
//*******************************************************************
//
// Determines the current and maximum registry size.
//
//*******************************************************************

#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <pdh.h>

PDH_STATUS GetRegistrySize( LPTSTR szMachineName,


LPDWORD lpdwCurrentSize, LPDWORD lpdwMaximumSize );

//*******************************************************************
//
// Entry point for the program. This function demonstrates how to
// use the GetRegistrySize function implemented below.
//
// It will use the first argument, if present, as the name of the
// computer whose registry you wish to determine. If unspecified,
// it will use the local computer.
//*******************************************************************

int _tmain( int argc, TCHAR *argv[] )


{

LPTSTR szMachineName = NULL;


PDH_STATUS pdhStatus = 0;
DWORD dwCurrent = 0;
DWORD dwMaximum = 0;

// Allow a computer name to be specified on the command line.


if ( argc > 1 )
szMachineName = argv[1];

// Get the registry size.


pdhStatus=GetRegistrySize(szMachineName, &dwCurrent, &dwMaximum);

// Print the results.


if ( pdhStatus == ERROR_SUCCESS )
{
_tprintf( TEXT("Registry size: %ld bytes\n"), dwCurrent );
_tprintf( TEXT("Max registry size: %ld bytes\n"), dwMaximum );

}
else
{
// If the operation failed, print the PDH error message.
LPTSTR szMessage = NULL;

FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_HMODULE,
GetModuleHandle( TEXT("PDH.DLL") ), pdhStatus,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
szMessage, 0, NULL );
_tprintf( TEXT("GetRegistrySize failed: %s"), szMessage );

LocalFree( szMessage );
}

return 0;
}

//*******************************************************************
//
// Retrieves the current and maximum registry size. It gets this
// information from the raw counter values for the "% Registry Quota
// In Use" performance counter within the System object.
//
// PARAMETERS:
// szMachineName - Null-terminated string that specifies the
// name of the computer whose registry you wish to query.
// If this parameter is NULL, the local computer is used.
//
// lpdwCurrentSize - Receives the current registry size.
//
// lpdwMaximumSize - Receives the maximum registry size.
//
// RETURN VALUE:
// ERROR_SUCCESS if successful. Otherwise, the function
// returns a PDH error code. These error codes can be
// found in PDHMSG.H. A textual error message can be
// retrieved from PDH.DLL using the FormatMessage function.
//
//******************************************************************

PDH_STATUS GetRegistrySize( LPTSTR szMachineName,


LPDWORD lpdwCurrentSize, LPDWORD lpdwMaximumSize )
{
PDH_STATUS pdhResult = 0;
TCHAR szCounterPath[1024];
DWORD dwPathSize = 1024;
PDH_COUNTER_PATH_ELEMENTS pe;
PDH_RAW_COUNTER pdhRawValues;
HQUERY hQuery = NULL;
HCOUNTER hCounter = NULL;
DWORD dwType = 0;

// Open PDH query


pdhResult = PdhOpenQuery( NULL, 0, &hQuery );
if ( pdhResult != ERROR_SUCCESS )
return pdhResult;

__try
{
// Create counter path
pe.szMachineName = szMachineName;
pe.szObjectName = TEXT("System");
pe.szInstanceName = NULL;
pe.szParentInstance = NULL;
pe.dwInstanceIndex = 1;
pe.szCounterName = TEXT("% Registry Quota In Use");
pdhResult = PdhMakeCounterPath( &pe, szCounterPath,
&dwPathSize, 0 );
if ( pdhResult != ERROR_SUCCESS )
__leave;

// Add the counter to the query


pdhResult=PdhAddCounter(hQuery, szCounterPath, 0, &hCounter);
if ( pdhResult != ERROR_SUCCESS )
__leave;

// Run the query to collect the performance data


pdhResult = PdhCollectQueryData( hQuery );
if ( pdhResult != ERROR_SUCCESS )
__leave;

// Retrieve the raw counter data:


// The dividend (FirstValue) is the current registry size
// The divisor (SecondValue) is the maximum registry size
ZeroMemory( &pdhRawValues, sizeof(pdhRawValues) );
pdhResult = PdhGetRawCounterValue( hCounter, &dwType,
&pdhRawValues );
if ( pdhResult != ERROR_SUCCESS )
__leave;

// Store the sizes in variables.


if ( lpdwCurrentSize )
*lpdwCurrentSize = (DWORD) pdhRawValues.FirstValue;

if ( lpdwMaximumSize )
*lpdwMaximumSize = (DWORD) pdhRawValues.SecondValue;

}
__finally
{
// Close the query
PdhCloseQuery( hQuery );
}

return 0;
}
 

Getting System Information


The following example uses the GetComputerName, GetUserName, GetSystemDirectory,
GetWindowsDirectory, and ExpandEnvironmentStrings functions to get information that describes the system
configuration.

Copy Code
#include <windows.h>
#include <tchar.h>
#include <stdio.h>

TCHAR* envVarStrings[] =
{
TEXT("OS = %OS%"),
TEXT("PATH = %PATH%"),
TEXT("HOMEPATH = %HOMEPATH%"),
TEXT("TEMP = %TEMP%")
};
#define ENV_VAR_STRING_COUNT (sizeof(envVarStrings)/sizeof(TCHAR*))
#define INFO_BUFFER_SIZE 32767
void printError( TCHAR* msg );

void main( )
{
DWORD i;
TCHAR infoBuf[INFO_BUFFER_SIZE];
DWORD bufCharCount = INFO_BUFFER_SIZE;

// Get and display the name of the computer.


bufCharCount = INFO_BUFFER_SIZE;
if( !GetComputerName( infoBuf, &bufCharCount ) )
printError( TEXT("GetComputerName") );
_tprintf( TEXT("\nComputer name: %s"), infoBuf );

// Get and display the user name.


bufCharCount = INFO_BUFFER_SIZE;
if( !GetUserName( infoBuf, &bufCharCount ) )
printError( TEXT("GetUserName") );
_tprintf( TEXT("\nUser name: %s"), infoBuf );

// Get and display the system directory.


if( !GetSystemDirectory( infoBuf, INFO_BUFFER_SIZE ) )
printError( TEXT("GetSystemDirectory") );
_tprintf( TEXT("\nSystem Directory: %s"), infoBuf );

// Get and display the Windows directory.


if( !GetWindowsDirectory( infoBuf, INFO_BUFFER_SIZE ) )
printError( TEXT("GetWindowsDirectory") );
_tprintf( TEXT("\nWindows Directory: %s"), infoBuf );

// Expand and display a few environment variables.


_tprintf( TEXT("\n\nSmall selection of Environment Variables:") );
for( i = 0; i < ENV_VAR_STRING_COUNT; ++i )
{
bufCharCount = ExpandEnvironmentStrings(envVarStrings[i], infoBuf,
INFO_BUFFER_SIZE );
if( bufCharCount > INFO_BUFFER_SIZE )
_tprintf( TEXT("\n\t(Buffer too small to expand: \"%s\")"),
envVarStrings[i] );
else if( !bufCharCount )
printError( TEXT("ExpandEnvironmentStrings") );
else
_tprintf( TEXT("\n %s"), infoBuf );
}
}

void printError( TCHAR* msg )


{
DWORD eNum;
TCHAR sysMsg[256];
TCHAR* p;

eNum = GetLastError( );
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, eNum,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
sysMsg, 256, NULL );

// Trim the end of the line and terminate it with a null


p = sysMsg;
while( ( *p > 31 ) || ( *p == 9 ) )
++p;
do { *p-- = 0; } while( ( p >= sysMsg ) &&
( ( *p == '.' ) || ( *p < 33 ) ) );

// Display the message


_tprintf( TEXT("\n\t%s failed with error %d (%s)"), msg, eNum, sysMsg );
}
 

 
Getting the System Version
The following example uses the GetVersionEx, GetSystemMetrics, GetProductInfo, and
GetNativeSystemInfo functions to determine the version information of the currently running operating system.
If compatibility mode is in effect, the example displays the operating system selected for application compatibility.
The example displays the information to the console.

To obtain the full version number for the operating system, call the GetFileVersionInfo function on one of the
system DLLs, such as Kernel32.dll, then call VerQueryValue to obtain the
\\StringFileInfo\\<lang><codepage>\\ProductVersion subblock of the file version information.

Relying on version information is not the best way to test for a feature. Instead, refer to the documentation for the
feature of interest. For more information on common techniques for feature detection, see Operating System
Version.

If you must require a particular operating system, be sure to use it as a minimum supported version, rather than
design the test for the one operating system. This way, your detection code will continue to work on future
versions of Windows.

Copy Code
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>

#pragma comment(lib, "User32.lib")

#define BUFSIZE 256

typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);


typedef BOOL (WINAPI *PGPI)(DWORD, DWORD, DWORD, DWORD, PDWORD);

BOOL GetOSDisplayString( LPTSTR pszOS)


{
OSVERSIONINFOEX osvi;
SYSTEM_INFO si;
PGNSI pGNSI;
PGPI pGPI;
BOOL bOsVersionInfoEx;
DWORD dwType;

ZeroMemory(&si, sizeof(SYSTEM_INFO));
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));

osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);

if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )


return 1;

// Call GetNativeSystemInfo if supported or GetSystemInfo otherwise.

pGNSI = (PGNSI) GetProcAddress(


GetModuleHandle(TEXT("kernel32.dll")),
"GetNativeSystemInfo");
if(NULL != pGNSI)
pGNSI(&si);
else GetSystemInfo(&si);

if ( VER_PLATFORM_WIN32_NT==osvi.dwPlatformId &&
osvi.dwMajorVersion > 4 )
{
StringCchCopy(pszOS, BUFSIZE, TEXT("Microsoft "));

// Test for the specific product.

if ( osvi.dwMajorVersion == 6 )
{
if( osvi.dwMinorVersion == 0 )
{
if( osvi.wProductType == VER_NT_WORKSTATION )
StringCchCat(pszOS, BUFSIZE, TEXT("Windows Vista "));
else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2008 " ));
}

if ( osvi.dwMinorVersion == 1 )
{
if( osvi.wProductType == VER_NT_WORKSTATION )
StringCchCat(pszOS, BUFSIZE, TEXT("Windows 7 "));
else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2008 R2
" ));
}

pGPI = (PGPI) GetProcAddress(


GetModuleHandle(TEXT("kernel32.dll")),
"GetProductInfo");

pGPI( osvi.dwMajorVersion, osvi.dwMinorVersion, 0, 0, &dwType);

switch( dwType )
{
case PRODUCT_ULTIMATE:
StringCchCat(pszOS, BUFSIZE, TEXT("Ultimate Edition" ));
break;
case PRODUCT_PROFESSIONAL:
StringCchCat(pszOS, BUFSIZE, TEXT("Professional" ));
break;
case PRODUCT_HOME_PREMIUM:
StringCchCat(pszOS, BUFSIZE, TEXT("Home Premium Edition" ));
break;
case PRODUCT_HOME_BASIC:
StringCchCat(pszOS, BUFSIZE, TEXT("Home Basic Edition" ));
break;
case PRODUCT_ENTERPRISE:
StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition" ));
break;
case PRODUCT_BUSINESS:
StringCchCat(pszOS, BUFSIZE, TEXT("Business Edition" ));
break;
case PRODUCT_STARTER:
StringCchCat(pszOS, BUFSIZE, TEXT("Starter Edition" ));
break;
case PRODUCT_CLUSTER_SERVER:
StringCchCat(pszOS, BUFSIZE, TEXT("Cluster Server Edition" ));
break;
case PRODUCT_DATACENTER_SERVER:
StringCchCat(pszOS, BUFSIZE, TEXT("Datacenter Edition" ));
break;
case PRODUCT_DATACENTER_SERVER_CORE:
StringCchCat(pszOS, BUFSIZE, TEXT("Datacenter Edition (core
installation)" ));
break;
case PRODUCT_ENTERPRISE_SERVER:
StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition" ));
break;
case PRODUCT_ENTERPRISE_SERVER_CORE:
StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition (core
installation)" ));
break;
case PRODUCT_ENTERPRISE_SERVER_IA64:
StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition for
Itanium-based Systems" ));
break;
case PRODUCT_SMALLBUSINESS_SERVER:
StringCchCat(pszOS, BUFSIZE, TEXT("Small Business Server" ));
break;
case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
StringCchCat(pszOS, BUFSIZE, TEXT("Small Business Server
Premium Edition" ));
break;
case PRODUCT_STANDARD_SERVER:
StringCchCat(pszOS, BUFSIZE, TEXT("Standard Edition" ));
break;
case PRODUCT_STANDARD_SERVER_CORE:
StringCchCat(pszOS, BUFSIZE, TEXT("Standard Edition (core
installation)" ));
break;
case PRODUCT_WEB_SERVER:
StringCchCat(pszOS, BUFSIZE, TEXT("Web Server Edition" ));
break;
}
}

if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 )


{
if( GetSystemMetrics(SM_SERVERR2) )
StringCchCat(pszOS, BUFSIZE, TEXT( "Windows Server 2003 R2, "));
else if ( osvi.wSuiteMask & VER_SUITE_STORAGE_SERVER )
StringCchCat(pszOS, BUFSIZE, TEXT( "Windows Storage Server
2003"));
else if ( osvi.wSuiteMask & VER_SUITE_WH_SERVER )
StringCchCat(pszOS, BUFSIZE, TEXT( "Windows Home Server"));
else if( osvi.wProductType == VER_NT_WORKSTATION &&
si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64)
{
StringCchCat(pszOS, BUFSIZE, TEXT( "Windows XP Professional x64
Edition"));
}
else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2003, "));

// Test for the server type.


if ( osvi.wProductType != VER_NT_WORKSTATION )
{
if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_IA64 )
{
if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter Edition for
Itanium-based Systems" ));
else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
StringCchCat(pszOS, BUFSIZE, TEXT( "Enterprise Edition for
Itanium-based Systems" ));
}

else if
( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 )
{
if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter x64 Edition"
));
else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
StringCchCat(pszOS, BUFSIZE, TEXT( "Enterprise x64 Edition"
));
else StringCchCat(pszOS, BUFSIZE, TEXT( "Standard x64 Edition"
));
}

else
{
if ( osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER )
StringCchCat(pszOS, BUFSIZE, TEXT( "Compute Cluster
Edition" ));
else if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter Edition" ));
else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
StringCchCat(pszOS, BUFSIZE, TEXT( "Enterprise Edition" ));
else if ( osvi.wSuiteMask & VER_SUITE_BLADE )
StringCchCat(pszOS, BUFSIZE, TEXT( "Web Edition" ));
else StringCchCat(pszOS, BUFSIZE, TEXT( "Standard Edition" ));
}
}
}

if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 )


{
StringCchCat(pszOS, BUFSIZE, TEXT("Windows XP "));
if( osvi.wSuiteMask & VER_SUITE_PERSONAL )
StringCchCat(pszOS, BUFSIZE, TEXT( "Home Edition" ));
else StringCchCat(pszOS, BUFSIZE, TEXT( "Professional" ));
}

if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 )


{
StringCchCat(pszOS, BUFSIZE, TEXT("Windows 2000 "));

if ( osvi.wProductType == VER_NT_WORKSTATION )
{
StringCchCat(pszOS, BUFSIZE, TEXT( "Professional" ));
}
else
{
if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter Server" ));
else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
StringCchCat(pszOS, BUFSIZE, TEXT( "Advanced Server" ));
else StringCchCat(pszOS, BUFSIZE, TEXT( "Server" ));
}
}

// Include service pack (if any) and build number.

if( _tcslen(osvi.szCSDVersion) > 0 )


{
StringCchCat(pszOS, BUFSIZE, TEXT(" ") );
StringCchCat(pszOS, BUFSIZE, osvi.szCSDVersion);
}

TCHAR buf[80];

StringCchPrintf( buf, 80, TEXT(" (build %d)"), osvi.dwBuildNumber);


StringCchCat(pszOS, BUFSIZE, buf);

if ( osvi.dwMajorVersion >= 6 )
{
if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 )
StringCchCat(pszOS, BUFSIZE, TEXT( ", 64-bit" ));
else if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_INTEL )
StringCchCat(pszOS, BUFSIZE, TEXT(", 32-bit"));
}

return TRUE;
}

else
{
printf( "This sample does not support this version of Windows.\n");
return FALSE;
}
}

int __cdecl _tmain()


{
TCHAR szOS[BUFSIZE];

if( GetOSDisplayString( szOS ) )


_tprintf( TEXT("\n%s\n"), szOS );
}
 

Verifying the System Version


This contains examples that use the VerifyVersionInfo function to determine whether the application is running
on a specific operating system.

The main steps in each example are as follows:

1. Set the appropriate values in the OSVERSIONINFOEX structure.

2. Set the appropriate condition mask using the VER_SET_CONDITION macro.

3. Call VerifyVersionInfo to perform the test.

Example 1

The following example determines whether the application is running on Windows XP with Service Pack 2 (SP2) or
a later version of Windows, such as Windows Server 2003 or Windows Vista.

Copy Code
#include <windows.h>
#include <stdio.h>

BOOL Is_WinXP_SP2_or_Later ()
{
OSVERSIONINFOEX osvi;
DWORDLONG dwlConditionMask = 0;
int op=VER_GREATER_EQUAL;

// Initialize the OSVERSIONINFOEX structure.

ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
osvi.dwMajorVersion = 5;
osvi.dwMinorVersion = 1;
osvi.wServicePackMajor = 2;
osvi.wServicePackMinor = 0;

// Initialize the condition mask.

VER_SET_CONDITION( dwlConditionMask, VER_MAJORVERSION, op );


VER_SET_CONDITION( dwlConditionMask, VER_MINORVERSION, op );
VER_SET_CONDITION( dwlConditionMask, VER_SERVICEPACKMAJOR, op );
VER_SET_CONDITION( dwlConditionMask, VER_SERVICEPACKMINOR, op );

// Perform the test.

return VerifyVersionInfo(
&osvi,
VER_MAJORVERSION | VER_MINORVERSION |
VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
dwlConditionMask);
}

void main()
{
if(Is_WinXP_SP2_or_Later())
printf("The system meets the requirements.\n");
else printf("The system does not meet the requirements.\n");
}

Example 2

The following code verifies that the application is running on Windows 2000 Server or a later server, such as
Windows Server 2003 or Windows Server 2008.

Copy Code
#include <windows.h>
#include <stdio.h>

BOOL Is_Win_Server()
{
OSVERSIONINFOEX osvi;
DWORDLONG dwlConditionMask = 0;
int op=VER_GREATER_EQUAL;

// Initialize the OSVERSIONINFOEX structure.

ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
osvi.dwMajorVersion = 5;
osvi.dwMinorVersion = 0;
osvi.wServicePackMajor = 0;
osvi.wServicePackMinor = 0;
osvi.wProductType = VER_NT_SERVER;

// Initialize the condition mask.

VER_SET_CONDITION( dwlConditionMask, VER_MAJORVERSION, op );


VER_SET_CONDITION( dwlConditionMask, VER_MINORVERSION, op );
VER_SET_CONDITION( dwlConditionMask, VER_SERVICEPACKMAJOR, op );
VER_SET_CONDITION( dwlConditionMask, VER_SERVICEPACKMINOR, op );
VER_SET_CONDITION( dwlConditionMask, VER_PRODUCT_TYPE, VER_EQUAL );

// Perform the test.

return VerifyVersionInfo(
&osvi,
VER_MAJORVERSION | VER_MINORVERSION |
VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR |
VER_PRODUCT_TYPE,
dwlConditionMask);
}

void main()
{
if(Is_Win_Server())
printf("The system meets the requirements.\n");
else printf("The system does not meet the requirements.\n");
}
 

 
Verifying the System Version
This contains examples that use the VerifyVersionInfo function to determine whether the application is running
on a specific operating system.

The main steps in each example are as follows:

1. Set the appropriate values in the OSVERSIONINFOEX structure.

2. Set the appropriate condition mask using the VER_SET_CONDITION macro.

3. Call VerifyVersionInfo to perform the test.

Example 1

The following example determines whether the application is running on Windows XP with Service Pack 2 (SP2) or
a later version of Windows, such as Windows Server 2003 or Windows Vista.

Copy Code
#include <windows.h>
#include <stdio.h>

BOOL Is_WinXP_SP2_or_Later ()
{
OSVERSIONINFOEX osvi;
DWORDLONG dwlConditionMask = 0;
int op=VER_GREATER_EQUAL;

// Initialize the OSVERSIONINFOEX structure.

ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
osvi.dwMajorVersion = 5;
osvi.dwMinorVersion = 1;
osvi.wServicePackMajor = 2;
osvi.wServicePackMinor = 0;

// Initialize the condition mask.

VER_SET_CONDITION( dwlConditionMask, VER_MAJORVERSION, op );


VER_SET_CONDITION( dwlConditionMask, VER_MINORVERSION, op );
VER_SET_CONDITION( dwlConditionMask, VER_SERVICEPACKMAJOR, op );
VER_SET_CONDITION( dwlConditionMask, VER_SERVICEPACKMINOR, op );

// Perform the test.

return VerifyVersionInfo(
&osvi,
VER_MAJORVERSION | VER_MINORVERSION |
VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
dwlConditionMask);
}

void main()
{
if(Is_WinXP_SP2_or_Later())
printf("The system meets the requirements.\n");
else printf("The system does not meet the requirements.\n");
}

Example 2

The following code verifies that the application is running on Windows 2000 Server or a later server, such as
Windows Server 2003 or Windows Server 2008.

Copy Code
#include <windows.h>
#include <stdio.h>

BOOL Is_Win_Server()
{
OSVERSIONINFOEX osvi;
DWORDLONG dwlConditionMask = 0;
int op=VER_GREATER_EQUAL;

// Initialize the OSVERSIONINFOEX structure.

ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
osvi.dwMajorVersion = 5;
osvi.dwMinorVersion = 0;
osvi.wServicePackMajor = 0;
osvi.wServicePackMinor = 0;
osvi.wProductType = VER_NT_SERVER;

// Initialize the condition mask.

VER_SET_CONDITION( dwlConditionMask, VER_MAJORVERSION, op );


VER_SET_CONDITION( dwlConditionMask, VER_MINORVERSION, op );
VER_SET_CONDITION( dwlConditionMask, VER_SERVICEPACKMAJOR, op );
VER_SET_CONDITION( dwlConditionMask, VER_SERVICEPACKMINOR, op );
VER_SET_CONDITION( dwlConditionMask, VER_PRODUCT_TYPE, VER_EQUAL );

// Perform the test.

return VerifyVersionInfo(
&osvi,
VER_MAJORVERSION | VER_MINORVERSION |
VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR |
VER_PRODUCT_TYPE,
dwlConditionMask);
}

void main()
{
if(Is_Win_Server())
printf("The system meets the requirements.\n");
else printf("The system does not meet the requirements.\n");
}
 

Getting Hardware Information


The following examples get or set hardware information.

Example 1

The following example uses the GetSystemInfo function to obtain hardware information such as the OEM
identifier, processor type, page size, and so on. The example displays the information in the console.

Copy Code
#include <windows.h>
#include <stdio.h>
#pragma comment(lib, "user32.lib")

void main()
{
SYSTEM_INFO siSysInfo;

// Copy the hardware information to the SYSTEM_INFO structure.

GetSystemInfo(&siSysInfo);

// Display the contents of the SYSTEM_INFO structure.

printf("Hardware information: \n");


printf(" OEM ID: %u\n", siSysInfo.dwOemId);
printf(" Number of processors: %u\n",
siSysInfo.dwNumberOfProcessors);
printf(" Page size: %u\n", siSysInfo.dwPageSize);
printf(" Processor type: %u\n", siSysInfo.dwProcessorType);
printf(" Minimum application address: %lx\n",
siSysInfo.lpMinimumApplicationAddress);
printf(" Maximum application address: %lx\n",
siSysInfo.lpMaximumApplicationAddress);
printf(" Active processor mask: %u\n",
siSysInfo.dwActiveProcessorMask);
}

Example 2
The following example uses the GetSystemMetrics function to determine whether a mouse is installed and
whether the mouse buttons are swapped. The example also uses the SystemParametersInfo function to retrieve
the mouse threshold and speed. It displays the information in the console.

Copy Code
#include <windows.h>
#include <stdio.h>
#pragma comment(lib, "user32.lib")

void main()
{
BOOL fResult;
int aMouseInfo[3];

fResult = GetSystemMetrics(SM_MOUSEPRESENT);

if (fResult == 0)
printf("No mouse installed.\n");
else
{
printf("Mouse installed.\n");

// Determine whether the buttons are swapped.

fResult = GetSystemMetrics(SM_SWAPBUTTON);

if (fResult == 0)
printf("Buttons not swapped.\n");
else printf("Buttons swapped.\n");

// Get the mouse speed and the threshold values.

fResult = SystemParametersInfo(
SPI_GETMOUSE, // get mouse information
0, // not used
&aMouseInfo, // holds mouse information
0); // not used

if( fResult )
{
printf("Speed: %d\n", aMouseInfo[2]);
printf("Threshold (x,y): %d,%d\n",
aMouseInfo[0], aMouseInfo[1]);
}
}
}

Example 3

The following example uses SystemParametersInfo to double the mouse speed.

Copy Code
#include <windows.h>
#include <stdio.h>
#pragma comment(lib, "user32.lib")

void main()
{
BOOL fResult;
int aMouseInfo[3]; // array for mouse information

// Get the current mouse speed.

fResult = SystemParametersInfo(
SPI_GETMOUSE, // get mouse information
0, // not used
&aMouseInfo, // holds mouse information
0); // not used

// Double it.

if( fResult )
{
aMouseInfo[2] = 2 * aMouseInfo[2];

// Change the mouse speed to the new value.

SystemParametersInfo(
SPI_SETMOUSE, // set mouse information
0, // not used
aMouseInfo, // mouse information
SPIF_SENDCHANGE); // update win.ini
}
}
 

Changing the Colors of Window Elements


The following example demonstrates the use of the GetSysColor and SetSysColors functions. First, the example
uses GetSysColor to retrieve the colors of the window background and active caption and displays the red, green,
blue (RGB) values in hexadecimal notation. Next, example uses SetSysColors to change the color of the window
background to light gray and the active title bars to dark purple. After a 10-second delay, the example restores the
previous colors for these elements using SetSysColors.

Copy Code
#include <windows.h>
#include <stdio.h>
#pragma comment(lib, "user32.lib")

void main()
{
int aElements[2] = {COLOR_WINDOW, COLOR_ACTIVECAPTION};
DWORD aOldColors[2];
DWORD aNewColors[2];

// Get the current color of the window background.

aOldColors[0] = GetSysColor(aElements[0]);
printf("Current window color: {0x%x, 0x%x, 0x%x}\n",
GetRValue(aOldColors[0]),
GetGValue(aOldColors[0]),
GetBValue(aOldColors[0]));

// Get the current color of the active caption.

aOldColors[1] = GetSysColor(aElements[1]);

printf("Current active caption color: {0x%x, 0x%x, 0x%x}\n",


GetRValue(aOldColors[1]),
GetGValue(aOldColors[1]),
GetBValue(aOldColors[1]));

// Define new colors for the elements

aNewColors[0] = RGB(0x80, 0x80, 0x80); // light gray


aNewColors[1] = RGB(0x80, 0x00, 0x80); // dark purple

printf("\nNew window color: {0x%x, 0x%x, 0x%x}\n",


GetRValue(aNewColors[0]),
GetGValue(aNewColors[0]),
GetBValue(aNewColors[0]));

printf("New active caption color: {0x%x, 0x%x, 0x%x}\n",


GetRValue(aNewColors[1]),
GetGValue(aNewColors[1]),
GetBValue(aNewColors[1]));

// Set the elements defined in aElements to the colors defined


// in aNewColors

SetSysColors(2, aElements, aNewColors);

printf("\nWindow background and active border have been changed.\n");


printf("Reverting to previous colors in 10 seconds...\n");

Sleep(10000);

// Restore the elements to their original colors

SetSysColors(2, aElements, aOldColors);


}
 

Retrieving the Last-Write Time


The following example uses the GetFileTime function to retrieve the last-write time for a file. It converts the time
to local time based on the current time-zone settings, and creates a date and time string that can be shown to the
user.

Copy Code
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>

// GetLastWriteTime - Retrieves the last-write time and converts


// the time to a string
//
// Return value - TRUE if successful, FALSE otherwise
// hFile - Valid file handle
// lpszString - Pointer to buffer to receive string

BOOL GetLastWriteTime(HANDLE hFile, LPTSTR lpszString, DWORD dwSize)


{
FILETIME ftCreate, ftAccess, ftWrite;
SYSTEMTIME stUTC, stLocal;
DWORD dwRet;

// Retrieve the file times for the file.


if (!GetFileTime(hFile, &ftCreate, &ftAccess, &ftWrite))
return FALSE;

// Convert the last-write time to local time.


FileTimeToSystemTime(&ftWrite, &stUTC);
SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal);

// Build a string showing the date and time.


dwRet = StringCchPrintf(lpszString, dwSize,
TEXT("%02d/%02d/%d %02d:%02d"),
stLocal.wMonth, stLocal.wDay, stLocal.wYear,
stLocal.wHour, stLocal.wMinute);

if( S_OK == dwRet )


return TRUE;
else return FALSE;
}

int _tmain(int argc, TCHAR *argv[])


{
HANDLE hFile;
TCHAR szBuf[MAX_PATH];

if( argc != 2 )
{
printf("This sample takes a file name as a parameter\n");
return 0;
}
hFile = CreateFile(argv[1], GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, 0, NULL);

if(hFile == INVALID_HANDLE_VALUE)
{
printf("CreateFile failed with %d\n", GetLastError());
return 0;
}
if(GetLastWriteTime( hFile, szBuf, MAX_PATH ))
_tprintf(TEXT("Last write time is: %s\n"), szBuf);

CloseHandle(hFile);
}
Changing a File Time to the Current Time
The following example sets the last-write time for a file to the current system time using the SetFileTime function.

The NTFS file system stores time values in UTC format, so they are not affected by changes in time zone or
daylight saving time. The FAT file system stores time values based on the local time of the computer.

The file must be opened with the CreateFile function using FILE_WRITE_ATTRIBUTES access.

Copy Code
#include <windows.h>

// SetFileToCurrentTime - sets last write time to current system time


// Return value - TRUE if successful, FALSE otherwise
// hFile - must be a valid file handle

BOOL SetFileToCurrentTime(HANDLE hFile)


{
FILETIME ft;
SYSTEMTIME st;
BOOL f;

GetSystemTime(&st); // Gets the current system time


SystemTimeToFileTime(&st, &ft); // Converts the current system time to
file time format
f = SetFileTime(hFile, // Sets last-write time of the file
(LPFILETIME) NULL, // to the converted current system time
(LPFILETIME) NULL,
&ft);

return f;
}
 

Converting a time_t Value to a File Time


The time functions included in the C run-time use the time_t type to represent the number of seconds elapsed
since midnight, January 1, 1970. The following example converts a time_t value to a file time, using the
Int32x32To64 function.

Copy Code
#include <windows.h>
#include <time.h>

void TimetToFileTime( time_t t, LPFILETIME pft )


{
LONGLONG ll = Int32x32To64(t, 10000000) + 116444736000000000;
pft->dwLowDateTime = (DWORD) ll;
pft->dwHighDateTime = ll >>32;
}

Sample Time Provider


The following example demonstrates how to structure a time provider. In this example, the DLL supports two
hardware time providers.

#include <windows.h>
#include "timeprov.h"

// Global variables.
TimeProvSysCallbacks sc;
WCHAR ProviderName1[] = L"MyCompanyMyAppProvider1";
WCHAR ProviderName2[] = L"MyCompanyMyAppProvider2";
const TimeProvHandle htp1 = (TimeProvHandle)1;
const TimeProvHandle htp2 = (TimeProvHandle)2;

// Stores the current set of best samples.


TpcGetSamplesArgs Samples;

// Stores the polling interval the system requires to maintain clock


// stability. The provider need not poll more often.
DWORD dwPollInterval;

HRESULT CALLBACK TimeProvOpen(


WCHAR *wszName,
TimeProvSysCallbacks *pSysCallback,
TimeProvHandle *phTimeProv)
{
// Spawn a thread to read configuration information from the
// registry.
;

// Copy the system callback pointers to a buffer.


CopyMemory(&sc, (PVOID)pSysCallback, sizeof(TimeProvSysCallbacks));

// Return the handle to the appropriate time provider.


if ( lstrcmp(wszName, ProviderName1) == 0 )
*phTimeProv = htp1;
else *phTimeProv = htp2;

return S_OK;
}

HRESULT CALLBACK TimeProvCommand(


TimeProvHandle hTimeProv,
TimeProvCmd eCmd,
PVOID pvArgs)
{
switch( eCmd )
{
case TPC_GetSamples:
// Return the Samples structure in pvArgs.
CopyMemory(pvArgs, &Samples, sizeof(TpcGetSamplesArgs));
break;
case TPC_PollIntervalChanged:
// Retrieve the new value.
sc.pfnGetTimeSysInfo( TSI_PollInterval, &dwPollInterval );
break;
case TPC_TimeJumped:
// Discard samples saved in the Samples structure.
ZeroMemory(&Samples, sizeof(TpcGetSamplesArgs));
break;
case TPC_UpdateConfig:
// Read the configuration information from the registry.
break;
}
return S_OK;
}

HRESULT CALLBACK TimeProvClose(


TimeProvHandle hTimeProv)
{
if( hTimeProv == htp1 )
{
// Terminate MyCompanyMyAppProvider1, performing any cleanup.
;
}
else
{
// Terminate MyCompanyMyAppProvider2, performing any cleanup.
;
}

return S_OK;
}
 

You might also like