/******************************************************************************* * * Copyright 1999 American Power Conversion, All Rights Reserved * * TITLE: UPSREG.C * * VERSION: 1.0 * * AUTHOR: SteveT * * DATE: 07 June, 1999 * * Revision History: * v-stebe 23May2000 added check for NULL in ReadRegistryValue() (bug 112595) * v-stebe 23May2000 added code to avoid rewriting the registry value if the * value is unchanged in setDwordValue() (bug #92799) * v-stebe 11Sep2000 Fixed PREfix error (bug #170456) *******************************************************************************/ /* * system includes */ #include #include /* * local includes */ //#include "upsdefines.h" #include "upsreg.h" #include "regdefs.h" #ifdef __cplusplus extern "C" { #endif /* * Reg entry info structure declaration */ struct _reg_entry { HKEY hKey; /* the key */ LPTSTR lpSubKey; /* address of SubKey name */ LPTSTR lpValueName; /* address of name of value to query */ DWORD ulType; /* buffer for value type */ LPBYTE lpData; /* address of data buffer */ DWORD cbData; /* data buffer size */ BOOL changed; /* ID of dialog that changed this entry */ }; /* * local function pre-declarations */ void freeBlock(struct _reg_entry *aBlock[]); void readBlock(struct _reg_entry *aBlock[], BOOL changed); void writeBlock(struct _reg_entry *aBlock[], BOOL forceAll); LONG setDwordValue(struct _reg_entry *aRegEntry, DWORD aValue); LONG setStringValue(struct _reg_entry *aRegEntry, LPCTSTR aBuffer); static BOOL isRegistryInitialized(); static void CheckForUpgrade(); static void InitializeServiceKeys(); static void InitializeServiceProviders(); static void InitializeConfigValues(); static void InitializeStatusValues(); /* * Reg entry value name declarations */ #define UPS_VENDOR _T("Vendor") #define UPS_MODEL _T("Model") #define UPS_SERIALNUMBER _T("SerialNumber") #define UPS_FIRMWAREREV _T("FirmwareRev") #define UPS_UTILITYSTATUS _T("UtilityPowerStatus") #define UPS_RUNTIME _T("TotalUPSRuntime") #define UPS_BATTERYSTATUS _T("BatteryStatus") #define UPS_PORT _T("Port") #define UPS_OPTIONS _T("Options") #define UPS_SHUTDOWNWAIT _T("ShutdownWait") #define UPS_FIRSTMESSAGEDELAY _T("FirstMessageDelay") #define UPS_MESSAGEINTERVAL _T("MessageInterval") #define UPS_SERVICEDLL _T("ServiceProviderDLL") #define UPS_NOTIFYENABLE _T("NotifyEnable") #define UPS_SHUTBATTENABLE _T("ShutdownOnBatteryEnable") #define UPS_SHUTBATTWAIT _T("ShutdownOnBatteryWait") #define UPS_RUNTASKENABLE _T("RunTaskEnable") #define UPS_TASKNAME _T("TaskName") #define UPS_TURNUPSOFFENABLE _T("TurnUPSOffEnable") #define UPS_APCLINKURL _T("APCLinkURL") #define UPS_CUSTOMOPTIONS _T("CustomOptions") #define UPS_UPGRADE _T("Upgrade") #define UPS_COMMSTATUS _T("CommStatus") #define UPS_CRITICALPOWERACTION _T("CriticalPowerAction") #define UPS_TURNUPSOFFWAIT _T("TurnUPSOffWait") #define UPS_SHOWTAB _T("ShowUPSTab") #define UPS_BATTERYCAPACITY _T("BatteryCapacity") #define UPS_IMAGEPATH _T("ImagePath") #define UPS_ERRORCONTROL _T("ErrorControl") #define UPS_OBJECTNAME _T("ObjectName") #define UPS_START _T("Start") #define UPS_TYPE _T("Type") // This specifies the key to examine to determine if the registry // has been updated for the UPS Service. #define UPS_SERVICE_INITIALIZED_KEY TEXT("SYSTEM\\CurrentControlSet\\Services\\UPS\\Config") // Specifies the name of the BatteryLife key used in the NT 4.0 UPS Service #define UPS_BATTLIFE_KEY TEXT("BatteryLife") // This specifies the default name for the shutdown Task #define DEFAULT_SHUTDOWN_TASK_NAME TEXT("") // Default values for the Config settings #define DEFAULT_CONFIG_VENDOR_OLD TEXT("\\(NONE)") #define DEFAULT_CONFIG_VENDOR TEXT("") #define DEFAULT_CONFIG_MODEL TEXT("") #define DEFAULT_CONFIG_PORT TEXT("COM1") #define DEFAULT_CONFIG_OPTIONS 0x7e #define DEFAULT_CONFIG_FIRSTMSG_DELAY 5 #define DEFAULT_CONFIG_MESSAGE_INTERVAL 120 #define DEFAULT_CONFIG_PROVIDER_DLL TEXT("") #define DEFAULT_CONFIG_NOTIFY_ENABLE 1 #define DEFAULT_CONFIG_SHUTDOWN_ONBATT_ENABLE FALSE #define DEFAULT_CONFIG_SHUTDOWN_ONBATT_WAIT 2 #define DEFAULT_CONFIG_RUNTASK_ENABLE FALSE #define DEFAULT_CONFIG_TASK_NAME DEFAULT_SHUTDOWN_TASK_NAME #define DEFAULT_CONFIG_TURNOFF_UPS_ENABLE TRUE #define DEFAULT_CONFIG_CUSTOM_OPTIONS UPS_DEFAULT_SIGMASK #define DEFAULT_CONFIG_CRITICALPOWERACTION UPS_SHUTDOWN_SHUTDOWN #define DEFAULT_CONFIG_TURNOFF_UPS_WAIT 180 #define DEFAULT_CONFIG_ERRORCONTROL 1 #define DEFAULT_CONFIG_OBJECTNAME TEXT("LocalSystem") #define DEFAULT_CONFIG_START SERVICE_DEMAND_START #define DEFAULT_CONFIG_TYPE 16 #define DEFAULT_CONFIG_SHOWUPSTAB FALSE // Default values for the Status settings #define DEFAULT_STATUS_SERIALNO TEXT("") #define DEFAULT_STATUS_FIRMWARE_REV TEXT("") #define DEFAULT_STATUS_UTILITY_STAT 0 #define DEFAULT_STATUS_TOTAL_RUNTIME 0 #define DEFAULT_STATUS_BATTERY_STAT 0 #define DEFAULT_STATUS_BATTERY_CAPACITY 0 // Default values for upgraded services #define UPGRADE_CONFIG_VENDOR_OLD TEXT("\\Generic") #define UPGRADE_CONFIG_VENDOR TEXT("") #define UPGRADE_CONFIG_MODEL TEXT("") /* * Allocate the individual Configuration Reg entry records */ struct _reg_entry UPSConfigVendor = {HKEY_LOCAL_MACHINE,UPS_CONFIG_ROOT,UPS_VENDOR,REG_SZ,NULL,0,FALSE}; struct _reg_entry UPSConfigModel = {HKEY_LOCAL_MACHINE,UPS_CONFIG_ROOT,UPS_MODEL,REG_SZ,NULL,0,FALSE}; struct _reg_entry UPSConfigPort = {HKEY_LOCAL_MACHINE,UPS_DEFAULT_ROOT,UPS_PORT,REG_SZ,NULL,0,FALSE}; struct _reg_entry UPSConfigOptions = {HKEY_LOCAL_MACHINE,UPS_DEFAULT_ROOT,UPS_OPTIONS,REG_DWORD,NULL,0,FALSE}; struct _reg_entry UPSConfigServiceDLL = {HKEY_LOCAL_MACHINE,UPS_CONFIG_ROOT,UPS_SERVICEDLL,REG_SZ,NULL,0,FALSE}; struct _reg_entry UPSConfigNotifyEnable = {HKEY_LOCAL_MACHINE,UPS_CONFIG_ROOT,UPS_NOTIFYENABLE,REG_DWORD,NULL,0,FALSE}; struct _reg_entry UPSConfigFirstMessageDelay= {HKEY_LOCAL_MACHINE,UPS_DEFAULT_ROOT,UPS_FIRSTMESSAGEDELAY,REG_DWORD,NULL,0,FALSE}; struct _reg_entry UPSConfigMessageInterval = {HKEY_LOCAL_MACHINE,UPS_DEFAULT_ROOT,UPS_MESSAGEINTERVAL,REG_DWORD,NULL,0,FALSE}; struct _reg_entry UPSConfigShutBattEnable = {HKEY_LOCAL_MACHINE,UPS_CONFIG_ROOT,UPS_SHUTBATTENABLE,REG_DWORD,NULL,0,FALSE}; struct _reg_entry UPSConfigShutBattWait = {HKEY_LOCAL_MACHINE,UPS_CONFIG_ROOT,UPS_SHUTBATTWAIT,REG_DWORD,NULL,0,FALSE}; struct _reg_entry UPSConfigRunTaskEnable = {HKEY_LOCAL_MACHINE,UPS_CONFIG_ROOT,UPS_RUNTASKENABLE,REG_DWORD,NULL,0,FALSE}; struct _reg_entry UPSConfigTaskName = {HKEY_LOCAL_MACHINE,UPS_CONFIG_ROOT,UPS_TASKNAME,REG_SZ,NULL,0,FALSE}; struct _reg_entry UPSConfigTurnOffEnable = {HKEY_LOCAL_MACHINE,UPS_CONFIG_ROOT,UPS_TURNUPSOFFENABLE,REG_DWORD,NULL,0,FALSE}; struct _reg_entry UPSConfigCustomOptions = {HKEY_LOCAL_MACHINE,UPS_CONFIG_ROOT,UPS_CUSTOMOPTIONS,REG_DWORD,NULL,0,FALSE}; struct _reg_entry UPSConfigAPCLinkURL = {HKEY_LOCAL_MACHINE,UPS_CONFIG_ROOT,UPS_APCLINKURL,REG_SZ,NULL,0,FALSE}; struct _reg_entry UPSConfigShutdownWait = {HKEY_LOCAL_MACHINE,UPS_DEFAULT_ROOT,UPS_SHUTDOWNWAIT,REG_DWORD,NULL,0,FALSE}; struct _reg_entry UPSConfigUpgrade = {HKEY_LOCAL_MACHINE,UPS_CONFIG_ROOT,UPS_UPGRADE,REG_DWORD,NULL,0,FALSE}; struct _reg_entry UPSConfigCriticalPowerAction = {HKEY_LOCAL_MACHINE,UPS_CONFIG_ROOT,UPS_CRITICALPOWERACTION,REG_DWORD,NULL,0,FALSE}; struct _reg_entry UPSConfigTurnOffWait = {HKEY_LOCAL_MACHINE,UPS_CONFIG_ROOT,UPS_TURNUPSOFFWAIT,REG_DWORD,NULL,0,FALSE}; struct _reg_entry UPSConfigImagePath = {HKEY_LOCAL_MACHINE,UPS_DEFAULT_ROOT,UPS_IMAGEPATH,REG_EXPAND_SZ,NULL,0,FALSE}; struct _reg_entry UPSConfigObjectName = {HKEY_LOCAL_MACHINE,UPS_DEFAULT_ROOT,UPS_OBJECTNAME,REG_EXPAND_SZ,NULL,0,FALSE}; struct _reg_entry UPSConfigErrorControl = {HKEY_LOCAL_MACHINE,UPS_DEFAULT_ROOT,UPS_ERRORCONTROL,REG_DWORD,NULL,0,FALSE}; struct _reg_entry UPSConfigStart = {HKEY_LOCAL_MACHINE,UPS_DEFAULT_ROOT,UPS_START,REG_DWORD,NULL,0,FALSE}; struct _reg_entry UPSConfigType = {HKEY_LOCAL_MACHINE,UPS_DEFAULT_ROOT,UPS_TYPE,REG_DWORD,NULL,0,FALSE}; struct _reg_entry UPSConfigShowUPSTab = {HKEY_LOCAL_MACHINE,UPS_DEFAULT_ROOT,UPS_SHOWTAB,REG_DWORD,NULL,0,FALSE}; /* * Allocate the individual Status Reg entry records */ struct _reg_entry UPSStatusSerialNum = {HKEY_LOCAL_MACHINE,UPS_STATUS_ROOT,UPS_SERIALNUMBER,REG_SZ,NULL,0,FALSE}; struct _reg_entry UPSStatusFirmRev = {HKEY_LOCAL_MACHINE,UPS_STATUS_ROOT,UPS_FIRMWAREREV,REG_SZ,NULL,0,FALSE}; struct _reg_entry UPSStatusUtilityStatus= {HKEY_LOCAL_MACHINE,UPS_STATUS_ROOT,UPS_UTILITYSTATUS,REG_DWORD,NULL,0,FALSE}; struct _reg_entry UPSStatusRuntime = {HKEY_LOCAL_MACHINE,UPS_STATUS_ROOT,UPS_RUNTIME,REG_DWORD,NULL,0,FALSE}; struct _reg_entry UPSStatusBatteryStatus= {HKEY_LOCAL_MACHINE,UPS_STATUS_ROOT,UPS_BATTERYSTATUS,REG_DWORD,NULL,0,FALSE}; struct _reg_entry UPSStatusCommStatus = {HKEY_LOCAL_MACHINE,UPS_STATUS_ROOT,UPS_COMMSTATUS,REG_DWORD,NULL,0,FALSE}; struct _reg_entry UPSStatusBatteryCapacity = {HKEY_LOCAL_MACHINE,UPS_STATUS_ROOT,UPS_BATTERYCAPACITY,REG_DWORD,NULL,0,FALSE}; /* * Allocate an array of pointers to the Configuration Reg entry records */ struct _reg_entry *ConfigBlock[] = {&UPSConfigVendor, &UPSConfigModel, &UPSConfigPort, &UPSConfigOptions, &UPSConfigServiceDLL, &UPSConfigNotifyEnable, &UPSConfigFirstMessageDelay, &UPSConfigMessageInterval, &UPSConfigShutBattEnable, &UPSConfigShutBattWait, &UPSConfigRunTaskEnable, &UPSConfigTaskName, &UPSConfigTurnOffEnable, &UPSConfigCustomOptions, &UPSConfigAPCLinkURL, &UPSConfigShutdownWait, &UPSConfigUpgrade, &UPSConfigCriticalPowerAction, &UPSConfigTurnOffWait, &UPSConfigImagePath, &UPSConfigObjectName, &UPSConfigErrorControl, &UPSConfigStart, &UPSConfigType, &UPSConfigShowUPSTab, NULL}; /* * Allocate an array of pointers to the Status Reg entry records */ struct _reg_entry *StatusBlock[] = {&UPSStatusSerialNum, &UPSStatusFirmRev, &UPSStatusUtilityStatus, &UPSStatusRuntime, &UPSStatusBatteryStatus, &UPSStatusCommStatus, &UPSStatusBatteryCapacity, NULL}; /****************************************************************** * Public functions */ LONG GetUPSConfigVendor(LPTSTR aBuffer, size_t aBufferLen) { return getStringValue( &UPSConfigVendor, aBuffer, aBufferLen); } LONG GetUPSConfigModel(LPTSTR aBuffer, size_t aBufferLen) { return getStringValue(&UPSConfigModel, aBuffer, aBufferLen); } LONG GetUPSConfigPort(LPTSTR aBuffer, size_t aBufferLen) { return getStringValue(&UPSConfigPort, aBuffer, aBufferLen); } LONG GetUPSConfigOptions( LPDWORD aValue) { return getDwordValue( &UPSConfigOptions, aValue); } LONG GetUPSConfigServiceDLL(LPTSTR aBuffer, size_t aBufferLen) { return getStringValue(&UPSConfigServiceDLL, aBuffer, aBufferLen); } LONG GetUPSConfigNotifyEnable( LPDWORD aValue) { return getDwordValue( &UPSConfigNotifyEnable, aValue); } LONG GetUPSConfigFirstMessageDelay( LPDWORD aValue) { return getDwordValue( &UPSConfigFirstMessageDelay, aValue); } LONG GetUPSConfigMessageInterval( LPDWORD aValue) { return getDwordValue( &UPSConfigMessageInterval, aValue); } LONG GetUPSConfigShutdownOnBatteryEnable( LPDWORD aValue) { return getDwordValue( &UPSConfigShutBattEnable, aValue); } LONG GetUPSConfigShutdownOnBatteryWait( LPDWORD aValue) { return getDwordValue( &UPSConfigShutBattWait, aValue); } LONG GetUPSConfigRunTaskEnable( LPDWORD aValue) { return getDwordValue( &UPSConfigRunTaskEnable, aValue); } LONG GetUPSConfigTaskName( LPTSTR aBuffer, size_t aBufferLen) { return getStringValue(&UPSConfigTaskName, aBuffer, aBufferLen); } LONG GetUPSConfigTurnOffEnable( LPDWORD aValue) { return getDwordValue( &UPSConfigTurnOffEnable, aValue); } LONG GetUPSConfigCustomOptions( LPDWORD aValue) { return getDwordValue( &UPSConfigCustomOptions, aValue); } LONG GetUPSConfigAPCLinkURL(LPTSTR aBuffer, size_t aBufferLen) { return getStringValue(&UPSConfigAPCLinkURL, aBuffer, aBufferLen); } LONG GetUPSConfigShutdownWait( LPDWORD aValue) { return getDwordValue( &UPSConfigShutdownWait, aValue); } LONG GetUPSConfigUpgrade( LPDWORD aValue) { return getDwordValue( &UPSConfigUpgrade, aValue); } LONG GetUPSConfigCriticalPowerAction( LPDWORD aValue) { return getDwordValue( &UPSConfigCriticalPowerAction, aValue); } LONG GetUPSConfigTurnOffWait( LPDWORD aValue) { return getDwordValue( &UPSConfigTurnOffWait, aValue); } LONG GetUPSConfigShowUPSTab( LPDWORD aValue) { return getDwordValue( &UPSConfigShowUPSTab, aValue); } LONG GetUPSConfigImagePath(LPTSTR aBuffer, size_t aBufferLen) { return getStringValue(&UPSConfigImagePath, aBuffer, aBufferLen); } LONG GetUPSConfigObjectName(LPTSTR aBuffer, size_t aBufferLen) { return getStringValue(&UPSConfigObjectName, aBuffer, aBufferLen); } LONG GetUPSConfigErrorControl( LPDWORD aValue) { return getDwordValue( &UPSConfigErrorControl, aValue); } LONG GetUPSConfigStart( LPDWORD aValue) { return getDwordValue( &UPSConfigStart, aValue); } LONG GetUPSConfigType( LPDWORD aValue) { return getDwordValue( &UPSConfigType, aValue); } /////////////////////////////////////////// LONG SetUPSConfigVendor( LPCTSTR aBuffer) { return setStringValue( &UPSConfigVendor, aBuffer); } LONG SetUPSConfigModel( LPCTSTR aBuffer) { return setStringValue( &UPSConfigModel, aBuffer); } LONG SetUPSConfigPort( LPCTSTR aBuffer) { return setStringValue( &UPSConfigPort, aBuffer); } LONG SetUPSConfigOptions( DWORD aValue) { return setDwordValue( &UPSConfigOptions, aValue); } LONG SetUPSConfigServiceDLL( LPCTSTR aBuffer) { return setStringValue( &UPSConfigServiceDLL, aBuffer); } LONG SetUPSConfigNotifyEnable( DWORD aValue) { return setDwordValue( &UPSConfigNotifyEnable, aValue); } LONG SetUPSConfigFirstMessageDelay( DWORD aValue) { return setDwordValue( &UPSConfigFirstMessageDelay, aValue); } LONG SetUPSConfigMessageInterval( DWORD aValue) { return setDwordValue( &UPSConfigMessageInterval, aValue); } LONG SetUPSConfigShutdownOnBatteryEnable( DWORD aValue) { return setDwordValue( &UPSConfigShutBattEnable, aValue); } LONG SetUPSConfigShutdownOnBatteryWait( DWORD aValue) { return setDwordValue( &UPSConfigShutBattWait, aValue); } LONG SetUPSConfigRunTaskEnable( DWORD aValue) { return setDwordValue( &UPSConfigRunTaskEnable, aValue); } LONG SetUPSConfigTaskName( LPCTSTR aBuffer) { return setStringValue( &UPSConfigTaskName, aBuffer); } LONG SetUPSConfigTurnOffEnable( DWORD aValue) { return setDwordValue( &UPSConfigTurnOffEnable, aValue); } LONG SetUPSConfigCustomOptions( DWORD aValue) { return setDwordValue( &UPSConfigCustomOptions, aValue); } LONG SetUPSConfigAPCLinkURL( LPCTSTR aBuffer) { return setStringValue( &UPSConfigAPCLinkURL, aBuffer); } LONG SetUPSConfigShutdownWait( DWORD aValue) { return setDwordValue( &UPSConfigShutdownWait, aValue); } LONG SetUPSConfigUpgrade( DWORD aValue) { return setDwordValue( &UPSConfigUpgrade, aValue); } LONG SetUPSConfigCriticalPowerAction( DWORD aValue) { return setDwordValue( &UPSConfigCriticalPowerAction, aValue); } LONG SetUPSConfigTurnOffWait( DWORD aValue) { return setDwordValue( &UPSConfigTurnOffWait, aValue); } LONG SetUPSConfigShowUPSTab( DWORD aValue) { return setDwordValue( &UPSConfigShowUPSTab, aValue); } LONG SetUPSConfigImagePath( LPCTSTR aBuffer) { return setStringValue( &UPSConfigImagePath, aBuffer); } LONG SetUPSConfigObjectName( LPCTSTR aBuffer) { return setStringValue( &UPSConfigObjectName, aBuffer); } LONG SetUPSConfigErrorControl( DWORD aValue) { return setDwordValue( &UPSConfigErrorControl, aValue); } LONG SetUPSConfigStart( DWORD aValue) { return setDwordValue( &UPSConfigStart, aValue); } LONG SetUPSConfigType( DWORD aValue) { return setDwordValue( &UPSConfigType, aValue); } //////////////////////////////////////////////// LONG GetUPSStatusSerialNum(LPTSTR aBuffer, size_t aBufferLen) { return getStringValue( &UPSStatusSerialNum, aBuffer, aBufferLen); } LONG GetUPSStatusFirmRev(LPTSTR aBuffer, size_t aBufferLen) { return getStringValue(&UPSStatusFirmRev, aBuffer, aBufferLen); } LONG GetUPSStatusUtilityStatus( LPDWORD aValue) { return getDwordValue( &UPSStatusUtilityStatus, aValue); } LONG GetUPSStatusRuntime( LPDWORD aValue) { return getDwordValue( &UPSStatusRuntime, aValue); } LONG GetUPSStatusBatteryStatus( LPDWORD aValue) { return getDwordValue( &UPSStatusBatteryStatus, aValue); } LONG GetUPSStatusCommStatus( LPDWORD aValue) { return getDwordValue( &UPSStatusCommStatus, aValue); } LONG GetUPSBatteryCapacity( LPDWORD aValue) { return getDwordValue( &UPSStatusBatteryCapacity, aValue); } ///////////////////////////////////////// LONG SetUPSStatusSerialNum( LPCTSTR aBuffer) { return setStringValue( &UPSStatusSerialNum, aBuffer); } LONG SetUPSStatusFirmRev( LPCTSTR aBuffer) { return setStringValue( &UPSStatusFirmRev, aBuffer); } LONG SetUPSStatusUtilityStatus( DWORD aValue) { return setDwordValue( &UPSStatusUtilityStatus,aValue); } LONG SetUPSStatusRuntime( DWORD aValue) { return setDwordValue( &UPSStatusRuntime,aValue); } LONG SetUPSStatusBatteryStatus( DWORD aValue) { return setDwordValue( &UPSStatusBatteryStatus,aValue); } LONG SetUPSStatusCommStatus( DWORD aValue) { return setDwordValue( &UPSStatusCommStatus,aValue); } LONG SetUPSStatusBatteryCapacity( DWORD aValue) { return setDwordValue( &UPSStatusBatteryCapacity,aValue); } ////////////////////////////////////////////////////////////// void FreeUPSConfigBlock() { freeBlock(ConfigBlock); } void FreeUPSStatusBlock() { freeBlock(StatusBlock); } void InitUPSConfigBlock() { readBlock(ConfigBlock,FALSE); } void InitUPSStatusBlock() { readBlock(StatusBlock,FALSE); } void RestoreUPSConfigBlock() { readBlock(ConfigBlock, TRUE); } void RestoreUPSStatusBlock() { readBlock(StatusBlock, TRUE); } void SaveUPSConfigBlock(BOOL forceAll) { writeBlock(ConfigBlock, forceAll); } void SaveUPSStatusBlock(BOOL forceAll) { writeBlock(StatusBlock, forceAll); } /****************************************************************** * Local functions */ /* * freeBlock() * * Description: Frees storage allocated when a block of registry * entries is read * * Parameters: aBlock - pointer to an array of _reg_entry structures * * Returns: */ void freeBlock(struct _reg_entry *aBlock[]) { while ((NULL != aBlock) && (NULL != *aBlock)) { struct _reg_entry *anEntry = *aBlock; if (NULL != anEntry->lpData) { LocalFree(anEntry->lpData); } anEntry->lpData = NULL; anEntry->cbData = 0; anEntry->changed = FALSE; aBlock++; } } /* * readBlock() * * Description: Loads all of the items in a array of registry entries * * Parameters: aBlock - pointer to an array of _reg_entry structures * changed - boolean which, when true, causes only the * structures that are marked as changed to be loaded. * * Returns: */ void readBlock(struct _reg_entry *aBlock[], BOOL changed) { LONG res; HKEY hkResult; while ((NULL != aBlock) && (NULL != *aBlock)) { struct _reg_entry *anEntry = *aBlock; /* * if changed is FALSE, we read all entries * otherwise, only re-read the changed entries */ if ((FALSE == changed) || (TRUE == anEntry->changed)) { /* * delete current value, in case this is a reload */ if (NULL != anEntry->lpData) { LocalFree(anEntry->lpData); } anEntry->lpData = NULL; anEntry->cbData = 0; anEntry->changed = FALSE; /* * open key */ res = RegOpenKeyEx( anEntry->hKey, anEntry->lpSubKey, 0, KEY_QUERY_VALUE, &hkResult); if (ERROR_SUCCESS == res) { DWORD ulTmpType; /* * query for the data size */ res = RegQueryValueEx( hkResult, anEntry->lpValueName, NULL, &ulTmpType, NULL, &anEntry->cbData); /* * if the data has 0 size, we don't read it */ if ((ERROR_SUCCESS == res) && (anEntry->cbData > 0) && (anEntry->ulType == ulTmpType) && (NULL != (anEntry->lpData = (LPBYTE)LocalAlloc(LMEM_FIXED, anEntry->cbData)))) // (NULL != (anEntry->lpData = (LPBYTE)malloc(anEntry->cbData)))) { /* * query for data */ res = RegQueryValueEx( hkResult, anEntry->lpValueName, NULL, &ulTmpType, anEntry->lpData, &anEntry->cbData); /* * something went wrong; reset */ if (ERROR_SUCCESS != res) { LocalFree(anEntry->lpData); anEntry->lpData = NULL; anEntry->cbData = 0; } } else { anEntry->cbData = 0; } RegCloseKey(hkResult); } } aBlock++; } } /* * writeBlock() * * Description: Stores all of the items in a array of registry entries * * Parameters: aBlock - pointer to an array of _reg_entry structures * forceAll - boolean which, when true, causes all of the * structures to be written to the registry, otherwise only * those entries that are marked as changed are stored. * * Returns: */ void writeBlock(struct _reg_entry *aBlock[], BOOL forceAll) { LONG res; HKEY hkResult; while ((NULL != aBlock) && (NULL != *aBlock)) { struct _reg_entry *anEntry = *aBlock; /* * if forcall is true, write out everything * otherwise only write out the changed entries */ if ((NULL != anEntry->lpData) && ((TRUE == forceAll) || (TRUE == anEntry->changed))) { /* * open key */ res = RegOpenKeyEx( anEntry->hKey, anEntry->lpSubKey, 0, KEY_SET_VALUE, &hkResult); if (ERROR_SUCCESS == res) { /* * set data */ res = RegSetValueEx( hkResult, anEntry->lpValueName, 0, anEntry->ulType, anEntry->lpData, anEntry->cbData); RegCloseKey(hkResult); } anEntry->changed = FALSE; } aBlock++; } } /* * setDwordValue() * * Description: Sets the value of a REG_DWORD entry record. * * Parameters: aRegEntry - pointer to a _reg_entry structure * aValue - the value to store in the entry * * Returns: ERROR_SUCCESS, E_OUTOFMEMORY, ERROR_INVALID_PARAMETER */ LONG setDwordValue(struct _reg_entry *aRegEntry, DWORD aValue) { LONG res = ERROR_SUCCESS; DWORD value_changed = TRUE; if (NULL != aRegEntry) { /* * Check to see if a value already exists */ if (NULL != aRegEntry->lpData) { /* * If the value is the different, delete it. */ if (memcmp(aRegEntry->lpData, &aValue, sizeof(aValue)) != 0) { LocalFree (aRegEntry->lpData); aRegEntry->lpData = NULL; aRegEntry->cbData = 0; } else { /* * The value is the same, don't change it. That would cause an * unnecessary write to the registry (see bug #92799) */ value_changed = FALSE; } } /* * set value */ if (value_changed) { aRegEntry->cbData = sizeof(DWORD); if (NULL != (aRegEntry->lpData = LocalAlloc(LMEM_FIXED, aRegEntry->cbData))) { *((DWORD*)aRegEntry->lpData) = aValue; aRegEntry->changed = TRUE; } else { res = E_OUTOFMEMORY; aRegEntry->cbData = 0; } } } else { res = ERROR_INVALID_PARAMETER; } return res; } /* * setStringValue() * * Description: Sets the value of a REG_SZ entry record. * * Parameters: aRegEntry - pointer to a _reg_entry structure * aBuffer - pointer to the string to store in the entry * * Returns: ERROR_SUCCESS, E_OUTOFMEMORY, ERROR_INVALID_PARAMETER */ LONG setStringValue(struct _reg_entry *aRegEntry, LPCTSTR aBuffer) { LONG res = ERROR_SUCCESS; if ((NULL != aRegEntry) && (NULL != aBuffer)) { /* * if value already exists, delete it */ if (NULL != aRegEntry->lpData) { LocalFree(aRegEntry->lpData); aRegEntry->lpData = NULL; aRegEntry->cbData = 0; } /* * set value */ aRegEntry->cbData = (_tcslen(aBuffer)+1)*sizeof(TCHAR); if (NULL != (aRegEntry->lpData = LocalAlloc(LMEM_FIXED, aRegEntry->cbData))) { _tcscpy((LPTSTR)aRegEntry->lpData,aBuffer); aRegEntry->changed = TRUE; } else { res = E_OUTOFMEMORY; aRegEntry->cbData = 0; } } else { res = ERROR_INVALID_PARAMETER; } return res; } /* * getStringValue() * * Description: Gets the value of a REG_SZ entry record. * * Parameters: * aRegEntry pointer to a _reg_entry structure * aBuffer pointer to the string to receive the string * aBufferLen the length (in characters) of the buffer * * Returns: ERROR_SUCCESS, REGDB_E_INVALIDVALUE, ERROR_INVALID_PARAMETER */ LONG getStringValue(struct _reg_entry *aRegEntry, LPTSTR aBuffer, size_t aBufferLen) { LONG res = REGDB_E_INVALIDVALUE; if ((NULL != aRegEntry) && (NULL != aBuffer)) { if (NULL != aRegEntry->lpData) { if (_tcslen((LPCTSTR) aRegEntry->lpData) < aBufferLen) { _tcscpy(aBuffer, (LPCTSTR)aRegEntry->lpData); res = ERROR_SUCCESS; } } } else { res = ERROR_INVALID_PARAMETER; } return res; } /* * getDwordValue() * * Description: Gets the value of a REG_DWORD entry record. * * Parameters: aRegEntry - pointer to a _reg_entry structure * aValue - pointer to the variable to receive the value * * Returns: ERROR_SUCCESS, REGDB_E_INVALIDVALUE, ERROR_INVALID_PARAMETER */ LONG getDwordValue(struct _reg_entry *aRegEntry, LPDWORD aValue) { LONG res = ERROR_SUCCESS; if ((NULL != aRegEntry) && (NULL != aValue)) { if (NULL != aRegEntry->lpData) { *aValue = *((DWORD*)aRegEntry->lpData); } else { res = REGDB_E_INVALIDVALUE; } } else { res = ERROR_INVALID_PARAMETER; } return res; } /** * InitializeRegistry * * Description: * This function initiates the registry for the UPS service and the * configuration application. When called, this function calls the * function isRegistryInitialized(..) to determine if the registry * has been initialied. If it has not, the following Keys are updated: * Status * Config * ServiceProviders * * The values for the ServiceProviders key is supplied in the regdefs.h * header file. * * Parameters: * none * * Returns: * TRUE if able to open registry keys with write access. */ BOOL InitializeRegistry() { BOOL ret_val = FALSE; HKEY key; TCHAR szKeyName[MAX_PATH] = _T(""); // Initialize UPS Service registry keys InitializeServiceKeys(); // Check to see if the registry is already initialized if (isRegistryInitialized() == FALSE) { CheckForUpgrade(); InitializeServiceProviders(); InitializeConfigValues(); InitializeStatusValues(); } /* * Remove "(None)" and "Generic" Service Provider keys if they exist * This fixes a localization bug introduced in RC2 */ _tcscpy(szKeyName, UPS_SERVICE_ROOT); _tcscat(szKeyName, DEFAULT_CONFIG_VENDOR_OLD); RegDeleteKey(HKEY_LOCAL_MACHINE, szKeyName); _tcscpy(szKeyName, UPS_SERVICE_ROOT); _tcscat(szKeyName, UPGRADE_CONFIG_VENDOR_OLD); RegDeleteKey(HKEY_LOCAL_MACHINE, szKeyName); // ...and check if we have write access if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, UPS_DEFAULT_ROOT, 0, KEY_WRITE, &key) == ERROR_SUCCESS ) { RegCloseKey(key); ret_val = TRUE; } return ret_val; } /** * isRegistryInitialized * * Description: * This function determines if the registry has been initialized for * the UPS service. This is done by examine the registry key specified * by the identifier UPS_SERVICE_INITIALIED_KEY. If the key is present, * the registry is assumed to be initialized and TRUE is returned. * Otherwise, FALSE is returned. * * Parameters: * none * * Returns: * TRUE - if the registry has been initialized for the UPS service * FALSE - otherwise */ static BOOL isRegistryInitialized() { BOOL ret_val = FALSE; HKEY key; if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, UPS_SERVICE_INITIALIZED_KEY, 0, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) { ret_val = TRUE; RegCloseKey(key); } return ret_val; } /** * CheckForUpgrade * * Description: * This function determines if this installation is an upgrade from * the WINNT 4.x UPS service. This is done by checking to see if the * Config registry key is present. If it is not present and the Options * key is set to UPS_INSTALLED, then the Upgrade registry key is set to * TRUE. Otherwise, it is set to FALSE. * * Parameters: * none * * Returns: * nothing */ static void CheckForUpgrade() { DWORD result; HKEY key; DWORD options = 0; // Create the Config key if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, UPS_CONFIG_ROOT, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &key, &result) == ERROR_SUCCESS) { // close the key, we only needed to create it RegCloseKey(key); // Check to see if the Config key was present if (result != REG_OPENED_EXISTING_KEY) { // Config key was not found InitUPSConfigBlock(); // Check the port value if (ERROR_SUCCESS != GetUPSConfigOptions(&options)) { // Options key is not found SetUPSConfigUpgrade(FALSE); } else if (options & UPS_INSTALLED) { // The Options key is present and UPS_INSTALLED is set // This is an upgrade SetUPSConfigUpgrade(TRUE); } else { // The Config key is present and UPS_INSTALLED is not set SetUPSConfigUpgrade(FALSE); } } else { // Config key does not exist SetUPSConfigUpgrade(FALSE); } // Write the Config values, force a save of all values SaveUPSConfigBlock(TRUE); // Free the Config block FreeUPSConfigBlock(); } } /** * InitializeServiceKeys * * Description: * This function initializes the UPS service registry keys to * default values, if the values are not present. * * Parameters: * none * * Returns: * nothing */ static void InitializeServiceKeys() { TCHAR tmpString[MAX_PATH]; DWORD tmpDword; // Initialize the registry functions InitUPSConfigBlock(); // Check the service keys and initialize any missing keys if (GetUPSConfigImagePath(tmpString, MAX_PATH) != ERROR_SUCCESS) { SetUPSConfigImagePath(DEFAULT_CONFIG_IMAGEPATH); } if (GetUPSConfigObjectName(tmpString, MAX_PATH) != ERROR_SUCCESS) { SetUPSConfigObjectName(DEFAULT_CONFIG_OBJECTNAME); } if (GetUPSConfigErrorControl(&tmpDword) != ERROR_SUCCESS) { SetUPSConfigErrorControl(DEFAULT_CONFIG_ERRORCONTROL); } if (GetUPSConfigStart(&tmpDword) != ERROR_SUCCESS) { SetUPSConfigStart(DEFAULT_CONFIG_START); } if (GetUPSConfigType(&tmpDword) != ERROR_SUCCESS) { SetUPSConfigType(DEFAULT_CONFIG_TYPE); } // Write the Config values, force a save of all values SaveUPSConfigBlock(TRUE); // Free the Status block FreeUPSConfigBlock(); } /** * InitializeServiceProviders * * Description: * This function initializes the ServiceProviders registry keys with the * data provided in the global structure _theStaticProvidersTable. This * structure is defined in the file regdefs.h and is automatically * generated. * * Parameters: * none * * Returns: * nothing */ static void InitializeServiceProviders() { DWORD result; HKEY key; int index = 0; // Loop through the list of Service Providers while (_theStaticProvidersTable[index].theModelName != NULL) { // Open the vendor registry key if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, _theStaticProvidersTable[index].theVendorKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &key, &result) == ERROR_SUCCESS) { // Set the model value RegSetValueEx(key, _theStaticProvidersTable[index].theModelName, 0, REG_SZ, (LPSTR) _theStaticProvidersTable[index].theValue, wcslen(_theStaticProvidersTable[index].theValue)*sizeof(TCHAR)); RegCloseKey(key); } // Increment counter index++; } } /** * InitializeConfigValues * * Description: * This function initializes the Config registry keys with * default values. * * Parameters: * none * * Returns: * nothing */ static void InitializeConfigValues() { DWORD result; HKEY key; DWORD options_val, batt_life, type; DWORD batt_life_size = sizeof(DWORD); // Create the Config key if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, UPS_CONFIG_ROOT, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &key, &result) == ERROR_SUCCESS) { // close the key, we only needed to create it RegCloseKey(key); // Initialize the registry functions InitUPSConfigBlock(); // Set default values SetUPSConfigServiceDLL(DEFAULT_CONFIG_PROVIDER_DLL); SetUPSConfigNotifyEnable(DEFAULT_CONFIG_NOTIFY_ENABLE); SetUPSConfigShutdownOnBatteryEnable(DEFAULT_CONFIG_SHUTDOWN_ONBATT_ENABLE); SetUPSConfigShutdownOnBatteryWait(DEFAULT_CONFIG_SHUTDOWN_ONBATT_WAIT); SetUPSConfigRunTaskEnable(DEFAULT_CONFIG_RUNTASK_ENABLE); SetUPSConfigTaskName(DEFAULT_CONFIG_TASK_NAME); SetUPSConfigTurnOffEnable(DEFAULT_CONFIG_TURNOFF_UPS_ENABLE); SetUPSConfigCustomOptions(DEFAULT_CONFIG_CUSTOM_OPTIONS); SetUPSConfigCriticalPowerAction(DEFAULT_CONFIG_CRITICALPOWERACTION); SetUPSConfigTurnOffWait(DEFAULT_CONFIG_TURNOFF_UPS_WAIT); // If this is not an upgrade, set the appropriate values if ((GetUPSConfigUpgrade(&result) != ERROR_SUCCESS) || (result == FALSE)) { SetUPSConfigVendor(DEFAULT_CONFIG_VENDOR); SetUPSConfigModel(DEFAULT_CONFIG_MODEL); SetUPSConfigPort(DEFAULT_CONFIG_PORT); SetUPSConfigOptions(DEFAULT_CONFIG_OPTIONS); SetUPSConfigFirstMessageDelay(DEFAULT_CONFIG_FIRSTMSG_DELAY); SetUPSConfigMessageInterval(DEFAULT_CONFIG_MESSAGE_INTERVAL); } else { // This is an upgrade SetUPSConfigVendor(UPGRADE_CONFIG_VENDOR); SetUPSConfigModel(UPGRADE_CONFIG_MODEL); // Migrate the run command file option bit to the RunTaskEnable key if ((GetUPSConfigOptions(&options_val) == ERROR_SUCCESS) && (options_val & UPS_RUNCMDFILE)) { // Run command file is enabled, set RunTaskEnable to TRUE SetUPSConfigRunTaskEnable(TRUE); } else { // Run command file is not enabled SetUPSConfigRunTaskEnable(FALSE); } // Migrate the BatteryLife value to the ShutdownOnBatteryWait value if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, UPS_DEFAULT_ROOT, 0, KEY_ALL_ACCESS, &key) == ERROR_SUCCESS) { result = RegQueryValueEx(key, UPS_BATTLIFE_KEY, NULL, &type, (LPBYTE) &batt_life, &batt_life_size); if ((result == ERROR_SUCCESS) && (type == REG_DWORD)) { // Migrate the value and enable shutdown on battery SetUPSConfigShutdownOnBatteryWait(batt_life); SetUPSConfigShutdownOnBatteryEnable(TRUE); // Delete the value RegDeleteValue(key, UPS_BATTLIFE_KEY); } // Close the key RegCloseKey(key); } } // Write the Config values, force a save of all values SaveUPSConfigBlock(TRUE); // Free the Config block FreeUPSConfigBlock(); } } /** * InitializeStatusValues * * Description: * This function initializes the Status registry keys with * default values. * * Parameters: * none * * Returns: * nothing */ static void InitializeStatusValues() { DWORD result; HKEY key; // Create the Status key if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, UPS_STATUS_ROOT, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &key, &result) == ERROR_SUCCESS) { // close the key, we only needed to create it RegCloseKey(key); // Initialize the registry functions InitUPSStatusBlock(); // Put in default values SetUPSStatusSerialNum(DEFAULT_STATUS_SERIALNO); SetUPSStatusFirmRev(DEFAULT_STATUS_FIRMWARE_REV); SetUPSStatusUtilityStatus(DEFAULT_STATUS_UTILITY_STAT); SetUPSStatusRuntime(DEFAULT_STATUS_TOTAL_RUNTIME); SetUPSStatusBatteryStatus(DEFAULT_STATUS_BATTERY_STAT); SetUPSStatusBatteryCapacity(DEFAULT_STATUS_BATTERY_CAPACITY); // Write the Config values, force a save of all values SaveUPSStatusBlock(TRUE); // Free the Status block FreeUPSStatusBlock(); } } /////////////////////////////////////////////////////////////////////////////// // upsdata.c /////////////////////////////////////////////////////////////////////////////// //Note that the order of the following RegField is linked to the enum //tUPSDataItemID. //Do not change these value without due care and attention. It's OK to change //them as long as the enum is updated to match. //To access the RegField associated with Firmware, for example, use //g_upsRegFields[(DWORD) eREG_FIRMWARE_REVISION] static RegField g_upsRegFields[] = { { HKEY_LOCAL_MACHINE, CONFIG_KEY_NAME, TEXT("Vendor"), REG_SZ }, { HKEY_LOCAL_MACHINE, CONFIG_KEY_NAME, TEXT("Model"), REG_SZ }, { HKEY_LOCAL_MACHINE, STATUS_KEY_NAME, TEXT("SerialNumber"), REG_SZ }, { HKEY_LOCAL_MACHINE, STATUS_KEY_NAME, TEXT("FirmwareRev"), REG_SZ }, { HKEY_LOCAL_MACHINE, STATUS_KEY_NAME, TEXT("UtilityPowerStatus"), REG_DWORD }, { HKEY_LOCAL_MACHINE, STATUS_KEY_NAME, TEXT("TotalUPSRuntime"), REG_DWORD }, { HKEY_LOCAL_MACHINE, STATUS_KEY_NAME, TEXT("BatteryCapacity"), REG_DWORD }, { HKEY_LOCAL_MACHINE, STATUS_KEY_NAME, TEXT("BatteryStatus"), REG_DWORD }, { HKEY_LOCAL_MACHINE, UPS_KEY_NAME, TEXT("Options"), REG_DWORD }, { HKEY_LOCAL_MACHINE, CONFIG_KEY_NAME, TEXT("ServiceProviderDLL"), REG_EXPAND_SZ }, { HKEY_LOCAL_MACHINE, CONFIG_KEY_NAME, TEXT("ShutdownOnBatteryEnable"), REG_DWORD }, { HKEY_LOCAL_MACHINE, CONFIG_KEY_NAME, TEXT("ShutdownOnBatteryWait"), REG_DWORD }, { HKEY_LOCAL_MACHINE, CONFIG_KEY_NAME, TEXT("TurnUPSOffEnable"), REG_DWORD }, { HKEY_LOCAL_MACHINE, CONFIG_KEY_NAME, TEXT("APCLinkURL"), REG_SZ }, { HKEY_LOCAL_MACHINE, CONFIG_KEY_NAME, TEXT("Upgrade"), REG_DWORD }, { HKEY_LOCAL_MACHINE, STATUS_KEY_NAME, TEXT("CommStatus"), REG_DWORD }, { HKEY_LOCAL_MACHINE, UPS_KEY_NAME, TEXT("Port"), REG_SZ } }; // functions /////////////////////////////////////////////////////////////////////////////// DWORD ReadRegistryValue (const tUPSDataItemID aDataItemID, DWORD aAllowedTypes, DWORD * aTypePtr, LPBYTE aReturnBuffer, DWORD * aBufferSizePtr); /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////_/_// //////////////////////////////////////////////////////////////////////////_/_// // RegField * GetRegField (DWORD aIndex); // // Description: This function returns a pointer to a RegField from the // static array of RegFields named g_upsRegFields. The parameter // aIndex is an index into this array. // // Additional Information: // // Parameters: // // DWORD aIndex :- A index into array of known RegFields g_upsRegFields // // Return Value: If aIndex is within range this function returns a point to // the corresponding RegField, otherwise it ASSERTs and returns // NULL. // RegField * GetRegField (DWORD aIndex) { static const DWORD numRegFields = DIMENSION_OF(g_upsRegFields); RegField * pRequiredReg = NULL; if (aIndex < numRegFields) { pRequiredReg = &g_upsRegFields[aIndex]; } else { _ASSERT(FALSE); } return(pRequiredReg); } //////////////////////////////////////////////////////////////////////////_/_// //////////////////////////////////////////////////////////////////////////_/_// // BOOL GetUPSDataItemDWORD (const tUPSDataItemID aDataItemID, DWORD * aReturnValuePtr); // // Description: This function reads the DWORD value from the registry that // corresponds to the registry field identified by aDataItemID. // The registry value must be one of the DWORD types (REG_DWORD, // REG_DWORD_LITTLE_ENDIAN, REG_DWORD_BIG_ENDIAN) // // For example, if aDataItemID is eREG_UPS_OPTIONS (=7), the // RegField at index 7 in g_upsRegFields identifies the required // registry information. The RegField identifies that the registry // key is HKLM\SYSTEM\CurrentControlSet\Services\UPS and the // value name is Options and it's of type DWORD. Using this // information this function gets the information from the // registry and puts the result in aReturnValuePtr. // // Additional Information: // // Parameters: // // const tUPSDataItemID aDataItemID :- This parameter identifies the registry // value being queried. The value ranges // from eREG_VENDOR_NAME (which equals 0) // to eREG_PORT, the values incrementing // by 1 for each enum in the range. The // range of values in tUPSDataItemID // corresponds directly to the number of // elements in the array g_upsRegFields // because this enum is used to index the // elements in g_upsRegFields. // // DWORD * aReturnValuePtr :- The DWORD value is returned through this // pointer. // // Return Value: // BOOL GetUPSDataItemDWORD (const tUPSDataItemID aDataItemID, DWORD * aReturnValuePtr) { BOOL bGotValue = FALSE; DWORD nDWORDSize = sizeof(DWORD); if (ReadRegistryValue(aDataItemID, REG_DWORD, NULL, (LPBYTE) aReturnValuePtr, &nDWORDSize) == ERROR_SUCCESS) { bGotValue = TRUE; } return(bGotValue); } //////////////////////////////////////////////////////////////////////////_/_// //////////////////////////////////////////////////////////////////////////_/_// // BOOL GetUPSDataItemString (const tUPSDataItemID aDataItemID, // LPTSTR aBufferPtr, // DWORD * pSizeOfBufferPtr); // // Description: This function reads the string value from the registry that // corresponds to the registry field identified by aDataItemID. // The registry value must be one of the string types (REG_SZ or // REG_EXPAND_SZ) // // Additional Information: // // Parameters: // // const tUPSDataItemID aDataItemID :- This parameter identifies the registry // value being queried. The value must be // one of the string types (REG_SZ or // REG_EXPAND_SZ). // // LPTSTR aBufferPtr :- The buffer into which the data is to be placed. This // parameter can be NULL in which case no data is // retrieved. // // DWORD * pSizeOfBufferPtr :- This should point to a DWORD that contains the // size of the buffer. This parameter cannot be // NULL. When this function returns this value // will contain the size actually required. This // is useful if the user want to determine how // big a buffer is required by calling this // function with aBufferPtr set to NULL and // pSizeOfBufferPtr pointing to a DWORD that // is set to 0. When the function returns the // DWORD pointed to by pSizeOfBufferPtr should // contain the size of string required. This can // then be used to dynamically allocate memory // and call this function again with the buffer // included this time. // // Return Value: The function returns TRUE if successful, FALSE otherwise. // BOOL GetUPSDataItemString (const tUPSDataItemID aDataItemID, LPTSTR aBufferPtr, DWORD * pSizeOfBufferPtr) { BOOL bGotValue = FALSE; DWORD nType = 0; if (ReadRegistryValue(aDataItemID, REG_SZ | REG_EXPAND_SZ, &nType, (LPBYTE) aBufferPtr, pSizeOfBufferPtr) == ERROR_SUCCESS) { //RegQueryValueEx stores the size of the data, in bytes, in the variable //pointed to by lpcbData. If the data has the REG_SZ, REG_MULTI_SZ or //REG_EXPAND_SZ type, then lpcbData will also include the size of the //terminating null character. //For Unicode the terminating NULL character is two-bytes. if ((pSizeOfBufferPtr != NULL) && (*pSizeOfBufferPtr > sizeof(TCHAR))) { if (nType == REG_EXPAND_SZ) { TCHAR expandBuffer[MAX_MESSAGE_LENGTH] = TEXT(""); DWORD expandBufferSize = DIMENSION_OF(expandBuffer); //ExpandEnvironmentStrings return number of bytes(ANSI) or //number of character(UNICODE) including the NULL character if (ExpandEnvironmentStrings(aBufferPtr, expandBuffer, expandBufferSize) > 0) { _tcscpy(aBufferPtr, expandBuffer); } } bGotValue = TRUE; } } return(bGotValue); } //////////////////////////////////////////////////////////////////////////_/_// //////////////////////////////////////////////////////////////////////////_/_// // DWORD ReadRegistryValue (const tUPSDataItemID aDataItemID, // DWORD aAllowedTypes, // DWORD * aTypePtr, // LPBYTE aReturnBuffer, // DWORD * aBufferSizePtr); // // Description: This function reads the registry value identified by // aDataItemID. This function can read any type of registry value // but the value must match that identified in the RegField // description for this field. // // For example, if aDataItemID is eREG_UPS_OPTIONS (=7), the // RegField at index 7 in g_upsRegFields identifies the required // registry information. The RegField identifies that the registry // key is HKLM\SYSTEM\CurrentControlSet\Services\UPS and the // value name is Options and it's of type DWORD. This function // will succeed only if it's called with an aAllowedTypes value // equal to REG_DWORD. // // Additional Information: // // Parameters: // // const tUPSDataItemID aDataItemID :- This parameter identifies the registry // value being queried. // // DWORD aAllowedTypes :- This identifies the allowed type of the registry // data. The registry value types are not bit value // that can be |'d (the types are sequentially // numbered 0, 1, 2, 3, 4, not 0, 1, 2, 4, 8). // However, the parameter is still called // aAllowedTypes because we actually call the function // with a value of REG_SZ | REG_EXPAND_SZ (1 | 2) to // allow the same function to work if the value is // either of these. Except for this case assume that // the aAllowedTypes is actually aAllowedType. // // DWORD * aTypePtr :- A pointer to the buffer that will receive the type. // If the type is not required then this parameter can be // set to NULL. // // LPBYTE aReturnBuffer :- The buffer into which the data is to be placed. // This parameter can be NULL in which case no data // is retrieved. // // DWORD * aBufferSizePtr :- This should point to a DWORD that contains the // size of the buffer. This parameter cannot be // NULL. When this function returns this value // will contain the size actually required. // // Return Value: This function returns a Win32 error code, ERROS_SUCCESS on // success. // DWORD ReadRegistryValue (const tUPSDataItemID aDataItemID, DWORD aAllowedTypes, DWORD * aTypePtr, LPBYTE aReturnBuffer, DWORD * aBufferSizePtr) { DWORD ret_val = ERROR_NO_MATCH; RegField * pRegField = GetRegField((DWORD) aDataItemID); if (pRegField != NULL ) { _ASSERT((pRegField->theValueType & aAllowedTypes) == pRegField->theValueType); ret_val = ReadRegistryValueData(pRegField->theRootKey, pRegField->theKeyName, pRegField->theValueName, aAllowedTypes, aTypePtr, (LPTSTR) aReturnBuffer, aBufferSizePtr); } return ret_val; } //////////////////////////////////////////////////////////////////////////_/_// //////////////////////////////////////////////////////////////////////////_/_// // DWORD ReadRegistryValueData (HKEY aRootKey, // LPCTSTR aKeyName, // LPCTSTR aValueName, // DWORD aAllowedTypes, // DWORD * aTypePtr, // LPTSTR aReturnBuffer, // DWORD * aBufferSizePtr); // // Description: // // Additional Information: // // Parameters: // // HKEY aRootKey :- A handle to an open registry key. // // LPCTSTR aKeyName :- The name of the key relative to the open key. // // LPCTSTR aValueName :- The name of the value to read // // DWORD aAllowedTypes :- See help on ReadRegistryValue. // // DWORD * aTypePtr :- A pointer to the buffer that will receive the type. // If the type is not required then this parameter can be // set to NULL. // // LPBYTE aReturnBuffer :- The buffer into which the data is to be placed. // This parameter can be NULL in which case no data // is retrieved. // // DWORD * aBufferSizePtr :- This should point to a DWORD that contains the // size of the buffer. This parameter cannot be // NULL. When this function returns this value // will contain the size actually required. // // Return Value: This function returns a Win32 error code, ERROS_SUCCESS on // success. // DWORD ReadRegistryValueData (HKEY aRootKey, LPCTSTR aKeyName, LPCTSTR aValueName, DWORD aAllowedTypes, DWORD * aTypePtr, LPTSTR aReturnBuffer, DWORD * aBufferSizePtr) { DWORD nType = 0; DWORD errCode = ERROR_INVALID_PARAMETER; HKEY hOpenKey = NULL; if ((errCode = RegOpenKeyEx(aRootKey, aKeyName, 0, KEY_READ, &hOpenKey)) == ERROR_SUCCESS) { _ASSERT(hOpenKey != NULL); //Key exists and is now open if ((errCode = RegQueryValueEx(hOpenKey, aValueName, NULL, &nType, (LPBYTE) aReturnBuffer, aBufferSizePtr)) == ERROR_SUCCESS) { if (aTypePtr != NULL) { *aTypePtr = nType; } if ((nType & aAllowedTypes) == 0) { //The value type in the registry does not match the expected //type for this function call. _ASSERT(FALSE); } if ((aReturnBuffer != NULL) && (*aBufferSizePtr == 1)) { //If the registry entry was in fact empty, the buffer needs to //be 1 character, for the NULL termination. *aReturnBuffer = TEXT('\0'); } } else { //Something prevented us from reading the value. //The value may not exist, the buffer size might //not be large enough. May be using the function to //read a DWORD value on a registry value that is a //shorter string. if (errCode == ERROR_MORE_DATA) { //There is most likely a mismatch between the type we expect //and the actual type of this registry value. _ASSERT(FALSE); } } RegCloseKey(hOpenKey); } return(errCode); } #ifdef __cplusplus } #endif