Determining the Registry Size Program Example
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. The following program example 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 that 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.
Create a new empty Win32 console application project. Give a suitable project name and change the project location if needed.
Then, add the source file and give it a suitable name.
Next, add the following source code.
//***************************************************
// Determines the current and maximum registry size.
//***************************************************
#include <windows.h>
#include <stdio.h>
// Don't forget to link to pdh.lib library
#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 wmain(int argc, WCHAR *argv[])
{
LPTSTR szMachineName = NULL;
PDH_STATUS pdhStatus = 0;
DWORD dwCurrent = 0;
DWORD dwMaximum = 0;
LPTSTR szMessage;
wprintf(LUsage: %s <computer_name>\n, argv[0]);
wprintf(LElse, local computer will be used as default\n\n);
// Allow a computer name to be specified on the command line
// Else, just query the local machine
if (argc > 1)
szMachineName = argv[1];
// Get the registry size.
pdhStatus=GetRegistrySize(szMachineName, &dwCurrent, &dwMaximum);
// Print the results.
if (pdhStatus == ERROR_SUCCESS)
{
wprintf(L\n);
wprintf(LRegistry size: %ld bytes\n, dwCurrent);
wprintf(LMax registry size: %ld bytes\n, dwMaximum);
}
else
{
// If the operation failed, print the PDH error message
szMessage = NULL;
// A system (GetLastError()) or a PDH error code can be used/extracted
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_HMODULE,
GetModuleHandle(LPDH.DLL), pdhStatus,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
szMessage, 0, NULL);
wprintf(LGetRegistrySize() 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;
WCHAR 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;
else
wprintf(LPdhOpenQuery() looks fine!\n);
// Exception handling, __try-__finally
__try
{
// Create counter path
pe.szMachineName = szMachineName;
pe.szObjectName = LSystem;
pe.szInstanceName = NULL;
pe.szParentInstance = NULL;
pe.dwInstanceIndex = 1;
pe.szCounterName = L% Registry Quota In Use;
pdhResult = PdhMakeCounterPath(&pe, szCounterPath, &dwPathSize, 0);
if (pdhResult != ERROR_SUCCESS)
__leave;
else
wprintf(LPdhMakeCounterPath() is OK!\n);
// Add the counter to the query
pdhResult=PdhAddCounter(hQuery, szCounterPath, 0, &hCounter);
if (pdhResult != ERROR_SUCCESS)
__leave;
else
wprintf(LPdhAddCounter() is working!\n);
// Run the query to collect the performance data
pdhResult = PdhCollectQueryData(hQuery);
if (pdhResult != ERROR_SUCCESS)
__leave;
else
wprintf(LWell, PdhCollectQueryData() is also working!\n);
// 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;
else
wprintf(LPdhGetRawCounterValue() is OK!\n);
// Store the sizes in variables.
if (lpdwCurrentSize)
*lpdwCurrentSize = (DWORD)pdhRawValues.FirstValue;
if (lpdwMaximumSize)
*lpdwMaximumSize = (DWORD)pdhRawValues.SecondValue;
}
__finally
{
// Close the query
if(PdhCloseQuery(hQuery) == ERROR_SUCCESS)
wprintf(LhQuery handle was closed successfully!\n);
}
return 0;
}
Build and run the project. The following screenshot is a sample output.
