windows-nt/Source/XPSP1/NT/base/ntsetup/legacy/dll/registr2.c

1893 lines
45 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
#include "precomp.h"
#pragma hdrstop
//
// Uncomment the next #define line to get debug trace info about
// Registry keys opened, created or closed.
//
// #define DBG_REG_HANDLES
//
extern HWND hwndFrame;
//
// Updated by DavidHov on 6/1/92:
//
// Centralized error handling;
// Eliminated "title" parameter from APIs; it's
// reserved now, so using it gives "invalid parameter"
//
//
// Updated by DavidHov on 1/6/93
//
// Chnaged FCreateRegKey and FOpenRegKey to always update
// the desired value; a null (empty) string is used if the
// operation has failed.
//
//
// Local Prototypes
//
BOOL FDeleteTree( HKEY KeyHandle );
BOOL FSetRegValueSz( HKEY hKey, SZ szValueName, UINT TitleIndex, SZ szValueData );
BOOL FSetRegValueExpandSz( HKEY hKey, SZ szValueName, UINT TitleIndex, SZ szValueData );
BOOL FSetRegValueMultiSz( HKEY hKey, SZ szValueName, UINT TitleIndex, UINT ValueType, SZ szValueData );
BOOL FSetRegValueDword( HKEY hKey, SZ szValueName, UINT TitleIndex, SZ szValueData );
BOOL FSetRegValueBin( HKEY hKey, SZ szValueName, UINT TitleIndex, UINT ValueType, SZ szValueData );
PVOID SzToMultiSz( SZ sz, PDWORD cbData );
SZ MultiSzToSz( PVOID Data, DWORD cbData );
PVOID SzToBin( SZ sz, PDWORD cbData );
SZ BinToSz( PVOID Data, DWORD cbData );
SZ ValueDataToSz( DWORD ValueType, PVOID ValueData, DWORD cbData );
//
// Central error handling for all Registry processing errors.
//
void FUpdateRegLastError ( LONG Status, SZ szOp, SZ szName )
{
char RegLastError[25];
_ltoa( Status, RegLastError, 10 );
FAddSymbolValueToSymTab( REGLASTERROR, RegLastError );
/* Uncomment to display all registry errors and their origin */
#if defined(DBG_REG_HANDLES)
OutputDebugString( "SETUP: Reg Error in " );
OutputDebugString( szOp );
OutputDebugString( " = " );
OutputDebugString( RegLastError ) ;
if ( szName )
{
OutputDebugString( "; " );
OutputDebugString( szName ) ;
}
OutputDebugString( "\n" );
#endif
}
// Debugging helper routing for finding lost Registry handles.
void FDebugRegKey ( SZ szHandle, SZ szAction, SZ szName )
{
OutputDebugString( "SETUP: REGKEYTRACE: " );
OutputDebugString( szHandle );
OutputDebugString( " : " );
OutputDebugString( szAction );
OutputDebugString( " : " );
if ( szName )
{
OutputDebugString( szName ) ;
}
OutputDebugString( "\n" );
}
#if defined(DBG_REG_HANDLES)
#define DEBUGREGKEY(a,b,c) FDebugRegKey(a,b,c)
#else
#define DEBUGREGKEY(a,b,c)
#endif
/*
* FCreateRegKey
*
* Crates a key in the registry
*
* Arguments:
*
*/
BOOL FCreateRegKey( SZ szHandle, SZ szKeyName, UINT TitleIndex, SZ szClass,
SZ Security, UINT Access, UINT Options, SZ szNewHandle,
CMO cmo )
{
BOOL fOkay;
HKEY hKey;
HKEY hSubKey;
DWORD Disposition;
LONG Status;
char LibraryHandleSTR[25];
LPSECURITY_ATTRIBUTES SecurityAttributes;
hKey = (HKEY)LongToHandle(atol( szHandle + 1 ));
//
// If the Security parameter is specified, it must contain the
// string "&<Address>" where <Address> is the decimal numeric
// representation of the memory address of a SECURITY_ATTRIBUTES
// structure.
//
if ( !Security || Security[0] != '\0' ) {
if ( Security[0] != '&' ) {
return fFalse;
}
SecurityAttributes = (LPSECURITY_ATTRIBUTES)LongToHandle(atol( Security + 1 ));
if ( !SecurityAttributes ||
!IsValidSecurityDescriptor( SecurityAttributes->lpSecurityDescriptor )
) {
return fFalse;
}
} else {
SecurityAttributes = NULL;
}
//
// Create the key
//
fOkay = !( Status = RegCreateKeyEx( hKey,
szKeyName,
0,
szClass,
Options,
Access,
SecurityAttributes,
&hSubKey,
&Disposition ));
// Prepare an initial null result
LibraryHandleSTR[0] = '\0' ;
if ( !fOkay ) {
FUpdateRegLastError( Status, "CreateRegKey", szKeyName );
} else {
//
// If the key already existed, we error out.
//
if ( Disposition == REG_OPENED_EXISTING_KEY ) {
RegCloseKey( hSubKey );
FUpdateRegLastError( ERROR_CANTOPEN, "CreateRegKey", szKeyName );
fOkay = fFalse;
} else {
//
// Put the handle in the specified variable
//
LibraryHandleSTR[0] = '|';
#if defined(_WIN64)
_ui64toa( (DWORD_PTR)hSubKey, LibraryHandleSTR+1, 20 );
#else
_ultoa( (DWORD)hSubKey, LibraryHandleSTR+1, 10 );
#endif
DEBUGREGKEY( LibraryHandleSTR+1, "created", szKeyName ) ;
}
}
// Always add the value to the symbol table, even if null (empty).
while ( !FAddSymbolValueToSymTab( szNewHandle, LibraryHandleSTR ) )
{
if ( !FHandleOOM( hwndFrame ) )
{
if ( fOkay )
{
RegCloseKey( hSubKey );
RegDeleteKey( hKey, szKeyName );
fOkay = fFalse;
}
break;
}
}
return (cmo & cmoVital) ? fOkay : fTrue;
}
/*
* FOpenRegKey
*
* Opens a key in the registry
*
* Arguments:
*
*/
BOOL FOpenRegKey( SZ szHandle, SZ szMachineName, SZ szKeyName, UINT Access, SZ szNewHandle, CMO cmo )
{
BOOL fOkay = fTrue;
HKEY hKey;
HKEY hSubKey;
LONG Status;
char LibraryHandleSTR[25];
hKey = (HKEY)LongToHandle(atol( szHandle + 1 ));
//
// If a remote machine is specified, we connect to the remote
// machine and use the new handle.
//
if ( szMachineName[0] != '\0' ) {
// BUGBUG ramonsa - Until RegConnectRegistry is operational
//
Status = ERROR_INVALID_PARAMETER;
fOkay = fFalse;
//
//fOkay = !(Status = RegConnectRegistry( szMachineName,
// hKey,
// &hKey
// );
} else if ( szKeyName[0] == '\0' ) {
//
// If no machine name was given then a subkey name must
// be given!
//
Status = ERROR_INVALID_PARAMETER;
fOkay = fFalse;
}
// Prepare an initial null result
LibraryHandleSTR[0] = '\0' ;
if ( fOkay ) {
//
// If no subkey is given, we just want a root handle of the
// remote machine. Otherwise we must open the subkey (and
// close the handle if remote).
//
if ( szKeyName[0] == '\0' ) {
//
// The remote handle is what we want.
//
hSubKey = hKey;
} else {
//
// We want a subkey.
//
fOkay = !( Status = RegOpenKeyEx( hKey,
szKeyName,
0,
Access,
&hSubKey ));
//
// If a remote machine is specified, then hkey has
// a remote handle and we must close it.
//
if ( szMachineName[0] != '\0' ) {
RegCloseKey( hKey );
}
}
if ( fOkay ) {
//
// Put the handle in the specified variable
//
LibraryHandleSTR[0] = '|';
#if defined(_WIN64)
_ui64toa( (DWORD_PTR)hSubKey, LibraryHandleSTR+1, 20 );
#else
_ultoa( (DWORD)hSubKey, LibraryHandleSTR+1, 10 );
#endif
DEBUGREGKEY( LibraryHandleSTR+1, "opened ", szKeyName ) ;
}
}
if ( !fOkay ) {
FUpdateRegLastError( Status, "OpenRegKey", szKeyName );
}
while ( !FAddSymbolValueToSymTab( szNewHandle, LibraryHandleSTR ) )
{
if ( !FHandleOOM( hwndFrame ) )
{
if ( fOkay )
{
RegCloseKey( hSubKey );
Status = 0;
fOkay = fFalse;
}
break ;
}
}
return (cmo & cmoVital) ? fOkay : fTrue;
}
/*
* FFlushRegKey
*
* Flushes a key in the registry
*
* Arguments:
*
*/
BOOL FFlushRegKey( SZ szHandle, CMO cmo )
{
BOOL fOkay;
HKEY hKey;
hKey = (HKEY)LongToHandle(atol( szHandle + 1 ));
fOkay = !RegFlushKey( hKey );
return (cmo & cmoVital) ? fOkay : fTrue;
}
/*
* FCloseRegKey
*
* Close a key in the registry
*
* Arguments:
*
*/
BOOL FCloseRegKey( SZ szHandle, CMO cmo )
{
BOOL fOkay;
HKEY hKey;
LONG Status;
if ( szHandle[0] != '|' )
return fTrue;
hKey = (HKEY)LongToHandle(atol( szHandle + 1 ));
if ( hKey == NULL )
return fTrue ;
DEBUGREGKEY( szHandle+1, "closed ", NULL ) ;
fOkay = !( Status = RegCloseKey( hKey ) );
if ( !fOkay ) {
FUpdateRegLastError( Status, "CloseRegKey", NULL );
}
return (cmo & cmoVital) ? fOkay : fTrue;
}
/*
* FDeleteRegKey
*
* Deletes a key from the registry
*
* Arguments:
*
*/
BOOL FDeleteRegKey( SZ szHandle, SZ szKeyName, CMO cmo )
{
BOOL fOkay;
HKEY hKey;
LONG Status;
hKey = (HKEY)LongToHandle(atol( szHandle + 1 ));
fOkay = !( Status = RegDeleteKey( hKey, szKeyName ) );
if ( !fOkay ) {
FUpdateRegLastError( Status, "DeleteRegKey", NULL );
}
return (cmo & cmoVital) ? fOkay : fTrue;
}
/*
* FDeleteRegTree
*
* Deletes a key and all its descentants from the registry
*
* Arguments:
*
*/
BOOL FDeleteRegTree( SZ szHandle, SZ szKeyName, CMO cmo )
{
BOOL fOkay;
HKEY hKey;
HKEY hSubKey;
LONG Status;
hKey = (HKEY)LongToHandle(atol( szHandle + 1 ));
//
// Open the key
//
fOkay = !( Status = RegOpenKeyEx( hKey,
szKeyName,
0,
KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
&hSubKey ) );
if ( !fOkay ) {
FUpdateRegLastError( Status, "DeleteRegTree", szKeyName );
} else {
fOkay = FDeleteTree( hSubKey );
}
//
// Now delete the key
//
if ( fOkay ) {
fOkay = !( Status = RegCloseKey( hSubKey ) );
if ( !fOkay ) {
FUpdateRegLastError( Status, "DeleteRegTree", szKeyName );
} else {
fOkay = !RegDeleteKey( hKey, szKeyName );
}
}
return (cmo & cmoVital) ? fOkay : fTrue;
}
/*
* FDeleteTree
*
* Recursively deletes all the descendants of a key
*
* Arguments:
*
*/
BOOL FDeleteTree( HKEY KeyHandle )
{
BOOL fOkay;
DWORD Index;
HKEY ChildHandle;
CHAR KeyName[ cchlFullPathMax ];
DWORD KeyNameLength;
CHAR ClassName[ cchlFullPathMax ];
DWORD ClassNameLength;
DWORD TitleIndex = 0 ;
DWORD NumberOfSubKeys;
DWORD MaxSubKeyLength;
DWORD MaxClassLength;
DWORD NumberOfValues;
DWORD MaxValueNameLength;
DWORD MaxValueDataLength;
DWORD SizeSecurityDescriptor;
FILETIME LastWriteTime;
LONG Status;
ClassNameLength = cchlFullPathMax;
if ( Status = RegQueryInfoKey( KeyHandle,
ClassName,
&ClassNameLength,
NULL,
&NumberOfSubKeys,
&MaxSubKeyLength,
&MaxClassLength,
&NumberOfValues,
&MaxValueNameLength,
&MaxValueDataLength,
&SizeSecurityDescriptor,
&LastWriteTime
) ) {
FUpdateRegLastError( Status, "DeleteTree", NULL );
return fFalse;
}
for ( Index = 0; Index < NumberOfSubKeys; Index++ ) {
KeyNameLength = cchlFullPathMax;
if ( Status = RegEnumKey( KeyHandle,
0,
KeyName,
KeyNameLength
) ) {
FUpdateRegLastError( Status, "DeleteTree", NULL );
return fFalse;
}
#ifdef BUGBUG
// BUGBUG This should work when MAXIMUM_ALLOWED access works.
if ( Status = RegOpenKey( KeyHandle,
KeyName,
&ChildHandle
) ) {
FUpdateRegLastError( Status, "DeleteTree", NULL );
return fFalse;
}
#else
if ( Status = RegOpenKeyEx( KeyHandle,
KeyName,
0,
KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
&ChildHandle
) ) {
FUpdateRegLastError( Status, "DeleteTree", NULL );
return fFalse;
}
#endif // ROBERTRE
fOkay = FDeleteTree( ChildHandle );
//
// Whether DeleteTree of the ChildHandle succeeded or not, we'll
// try to close it.
//
RegCloseKey( ChildHandle );
if ( fOkay ) {
if ( fOkay = !(Status = RegDeleteKey( KeyHandle, KeyName ) )) {
FUpdateRegLastError( Status, "DeleteTree", NULL );
}
}
if ( !fOkay ) {
return fFalse;
}
}
return fTrue;
}
/*
* FEnumRegKey
*
* Obtains subkey enumeration
*
* Arguments:
*
*/
BOOL FEnumRegKey( SZ szHandle, SZ szInfVar, CMO cmo )
{
BOOL fOkay = fTrue;
HKEY hKey;
CHAR KeyName[ cbFullPathMax ];
CHAR Class[ cbFullPathMax ];
DWORD cbKeyName;
DWORD cbClass;
DWORD TitleIndex = 0 ;
FILETIME FileTime;
RGSZ rgszEnum;
UINT EnumSize;
RGSZ rgszKey;
SZ szInfo;
char szTitle[25];
UINT Index;
LONG Status;
DWORD NumberOfSubKeys;
DWORD MaxSubKeyLength;
DWORD MaxClassLength;
DWORD NumberOfValues;
DWORD MaxValueNameLength;
DWORD MaxValueDataLength;
DWORD SizeSecurityDescriptor;
FILETIME LastWriteTime;
hKey = (HKEY)LongToHandle(atol( szHandle + 1 ));
while ( (rgszEnum = (RGSZ)SAlloc( (CB)( 1 * sizeof(SZ)))) == NULL ) {
if ( !FHandleOOM( hwndFrame ) ) {
fOkay = fFalse;
break;
}
}
if ( fOkay ) {
rgszEnum[0] = NULL;
EnumSize = 0;
cbClass = cbFullPathMax;
if ( Status = RegQueryInfoKey( hKey,
Class,
&cbClass,
NULL,
&NumberOfSubKeys,
&MaxSubKeyLength,
&MaxClassLength,
&NumberOfValues,
&MaxValueNameLength,
&MaxValueDataLength,
&SizeSecurityDescriptor,
&LastWriteTime
) ) {
FUpdateRegLastError( Status, "EnumRegKey", NULL );
return fFalse;
}
for ( Index = 0 ; Index < NumberOfSubKeys; Index++ ) {
cbKeyName = cbFullPathMax;
cbClass = cbFullPathMax;
if ( Status = RegEnumKeyEx( hKey,
Index,
KeyName,
&cbKeyName,
NULL,
(LPSTR)&Class,
&cbClass,
&FileTime ) ) {
FUpdateRegLastError( Status, "EnumRegKey", NULL );
break;
}
//
// Get a list in which to put the key information.
//
while ( (rgszKey = (RGSZ)SAlloc( (CB)( 4 * sizeof(SZ)))) == NULL ) {
if ( !FHandleOOM( hwndFrame ) ) {
fOkay = fFalse;
break;
}
}
if ( fOkay ) {
//
// Put the information in the list
//
_ultoa( TitleIndex, szTitle, 10 );
rgszKey[0] = KeyName;
rgszKey[1] = szTitle;
rgszKey[2] = Class;
rgszKey[3] = NULL;
//
// Transform the list into a string so that it can be added to the
// symbol table.
//
while ( (szInfo = SzListValueFromRgsz( rgszKey )) == (SZ)NULL ) {
if ( !FHandleOOM( hwndFrame ) ) {
fOkay = fFalse;
break;
}
}
if ( fOkay ) {
while ( (rgszEnum = (RGSZ)SRealloc( rgszEnum,
(CB)( (EnumSize+2) * sizeof(SZ)))
) == NULL ) {
if ( !FHandleOOM( hwndFrame ) ) {
fOkay = fFalse;
break;
}
}
if ( fOkay ) {
rgszEnum[EnumSize] = szInfo;
EnumSize++;
rgszEnum[EnumSize] = NULL;
}
}
SFree(rgszKey);
}
}
//
// Convert to SZ
//
while ( (szInfo = SzListValueFromRgsz( rgszEnum )) == (SZ)NULL ) {
if ( !FHandleOOM( hwndFrame ) ) {
fOkay = fFalse;
break;
}
}
if ( fOkay ) {
//
// Add it to the symbol table.
//
while ( !FAddSymbolValueToSymTab( szInfVar, szInfo ) ) {
if ( !FHandleOOM( hwndFrame ) ) {
fOkay = fFalse;
break;
}
}
SFree(szInfo);
}
FFreeRgsz( rgszEnum );
}
return (cmo & cmoVital) ? fOkay : fTrue;
}
/*
* FSetRegValue
*
* Sets a value under the given key
*
* Arguments:
*
*/
BOOL FSetRegValue( SZ szHandle, SZ szValueName, UINT TitleIndex,
UINT ValueType, SZ szValueData, CMO cmo )
{
BOOL fOkay;
HKEY hKey;
hKey = (HKEY)LongToHandle(atol( szHandle + 1 ));
switch ( ValueType ) {
case REG_MULTI_SZ:
fOkay = FSetRegValueMultiSz( hKey, szValueName, TitleIndex, REG_MULTI_SZ, szValueData );
break;
case REG_SZ:
fOkay = FSetRegValueSz( hKey, szValueName, TitleIndex, szValueData );
break;
case REG_EXPAND_SZ:
fOkay = FSetRegValueExpandSz( hKey, szValueName, TitleIndex, szValueData );
break;
case REG_DWORD:
fOkay = FSetRegValueDword( hKey, szValueName, TitleIndex, szValueData );
break;
case REG_BINARY:
fOkay = FSetRegValueBin( hKey, szValueName, TitleIndex, REG_BINARY, szValueData );
break;
case REG_RESOURCE_LIST:
fOkay = FSetRegValueBin( hKey, szValueName, TitleIndex, REG_RESOURCE_LIST, szValueData );
break;
case REG_FULL_RESOURCE_DESCRIPTOR:
fOkay = FSetRegValueBin( hKey, szValueName, TitleIndex, REG_FULL_RESOURCE_DESCRIPTOR, szValueData );
break;
case REG_RESOURCE_REQUIREMENTS_LIST:
fOkay = FSetRegValueBin( hKey, szValueName, TitleIndex, REG_RESOURCE_REQUIREMENTS_LIST, szValueData );
break;
default:
fOkay = FSetRegValueBin( hKey, szValueName, TitleIndex, ValueType, szValueData );
break;
}
return (cmo & cmoVital) ? fOkay : fTrue;
}
/*
* FGetRegValue
*
* Gets the specified value under the given key
*
* Arguments:
*
*/
BOOL FGetRegValue( SZ szHandle, SZ szValueName, SZ szInfVar, CMO cmo )
{
BOOL fOkay;
HKEY hKey;
DWORD cbData;
DWORD TitleIndex = 0 ;
DWORD ValueType;
PVOID ValueData;
SZ szValueData;
RGSZ rgszValue;
SZ szInfo;
LONG Status;
char szTitle[25];
char szValueType[25];
char szKClass[ MAX_PATH ];
DWORD cbKClass;
DWORD KTitleIndex = 0 ;
DWORD KSubKeys;
DWORD cbKMaxSubKeyLen;
DWORD cbKMaxClassLen;
DWORD KValues;
DWORD cbKMaxValueNameLen;
DWORD SizeSecurityDescriptor;
FILETIME KLastWriteTime;
hKey = (HKEY)LongToHandle(atol( szHandle + 1 ));
//
// Get the size of the buffer needed
//
cbKClass = MAX_PATH;
fOkay = !( Status = RegQueryInfoKey ( hKey,
szKClass,
&cbKClass,
NULL,
&KSubKeys,
&cbKMaxSubKeyLen,
&cbKMaxClassLen,
&KValues,
&cbKMaxValueNameLen,
&cbData,
&SizeSecurityDescriptor,
&KLastWriteTime ) );
//cbData = 0;
//fOkay = !RegQueryValueEx( hKey,
// szValueName,
// NULL,
// NULL,
// NULL,
// &cbData );
if ( !fOkay ) {
FUpdateRegLastError( Status, "GetRegValue", szValueName );
} else {
//
// Allocate the buffer and get the data
//
while ( (ValueData = (PVOID)SAlloc( (CB)( cbData ))) == NULL ) {
if ( !FHandleOOM( hwndFrame ) ) {
fOkay = fFalse;
break;
}
}
if ( fOkay ) {
fOkay = !( Status = RegQueryValueEx( hKey,
szValueName,
NULL,
&ValueType,
ValueData,
&cbData ) );
if ( !fOkay ) {
FUpdateRegLastError( Status, "GetRegValue", szValueName );
} else {
//
// Get a list in which to put the key information.
//
while ( (rgszValue = (RGSZ)SAlloc( (CB)( 5 * sizeof(SZ)))) == NULL ) {
if ( !FHandleOOM( hwndFrame ) ) {
fOkay = fFalse;
break;
}
}
if ( fOkay ) {
//
// Put the information in the list
//
if ( (fOkay = (szValueData = ValueDataToSz( ValueType, ValueData, cbData)) != NULL) ) {
_ultoa( TitleIndex, szTitle, 10 );
_ultoa( ValueType, szValueType, 10 );
rgszValue[0] = szValueName;
rgszValue[1] = szTitle;
rgszValue[2] = szValueType;
rgszValue[3] = szValueData;
rgszValue[4] = NULL;
//
// Transform the list into a string so that it can be added to the
// symbol table.
//
while ( (szInfo = SzListValueFromRgsz( rgszValue )) == (SZ)NULL ) {
if ( !FHandleOOM( hwndFrame ) ) {
fOkay = fFalse;
break;
}
}
if ( fOkay ) {
//
// Add it to the symbol table.
//
while ( !FAddSymbolValueToSymTab( szInfVar, szInfo ) ) {
if ( !FHandleOOM( hwndFrame ) ) {
fOkay = fFalse;
break;
}
}
SFree(szInfo);
}
SFree( szValueData );
}
SFree( rgszValue );
}
}
SFree( ValueData );
}
}
return (cmo & cmoVital) ? fOkay : fTrue;
}
/*
* FDeleteRegValue
*
* Deletes a value under the given key
*
* Arguments:
*
*/
BOOL FDeleteRegValue( SZ szHandle, SZ szValueName, CMO cmo )
{
BOOL fOkay;
HKEY hKey;
LONG Status;
hKey = (HKEY)LongToHandle(atol( szHandle + 1 ));
fOkay = !( Status = RegDeleteValue( hKey, szValueName ) );
if ( !fOkay ) {
FUpdateRegLastError( Status, "DeleteRegValue", szValueName );
}
return (cmo & cmoVital) ? fOkay : fTrue;
}
/*
* FEnumRegValue
*
* Obtains information for a value with a certain index.
*
* Arguments:
*
*/
BOOL FEnumRegValue( SZ szHandle, SZ szInfVar, CMO cmo )
{
BOOL fOkay;
HKEY hKey;
DWORD cbData;
DWORD cbName;
DWORD TitleIndex = 0 ;
DWORD ValueType;
PVOID ValueData;
SZ szValueData;
DWORD cbValueData;
RGSZ rgszValue;
RGSZ rgszEnum;
UINT EnumSize;
SZ szInfo;
SZ szValueName;
DWORD cbValueName;
UINT Index;
LONG Status;
char szTitle[25];
char szValueType[25];
char szKClass[ cchlFullPathMax ];
DWORD cbKClass;
DWORD KTitleIndex = 0 ;
DWORD KSubKeys;
DWORD cbKMaxSubKeyLen;
DWORD cbKMaxClassLen;
DWORD SizeSecurityDescriptor;
DWORD KValues;
FILETIME KLastWriteTime;
hKey = (HKEY)LongToHandle(atol( szHandle + 1 ));
//
// Get the size of the buffer needed
//
cbKClass = MAX_PATH;
fOkay = !( Status = RegQueryInfoKey ( hKey,
szKClass,
&cbKClass,
NULL,
&KSubKeys,
&cbKMaxSubKeyLen,
&cbKMaxClassLen,
&KValues,
&cbName,
&cbData,
&SizeSecurityDescriptor,
&KLastWriteTime ) );
if ( !fOkay ) {
FUpdateRegLastError( Status, "EnumRegValue", NULL );
} else {
//
// Allocate the buffer to get the data.
//
while ( (ValueData = (PVOID)SAlloc( (CB)( cbData ))) == NULL ) {
if ( !FHandleOOM( hwndFrame ) ) {
fOkay = fFalse;
break;
}
}
if ( fOkay ) {
//
// Allocate a buffer to get the name. Allow for the string terminator.
//
while ( (szValueName = (SZ)SAlloc( (CB)( ( ++cbName ) * sizeof( TCHAR ) ))) == NULL ) {
if ( !FHandleOOM( hwndFrame ) ) {
fOkay = fFalse;
break;
}
}
if ( fOkay ) {
//
// Allocate empty enum list.
//
while ( (rgszEnum = (RGSZ)SAlloc( (CB)( 1 * sizeof(SZ)))) == NULL ) {
if ( !FHandleOOM( hwndFrame ) ) {
fOkay = fFalse;
break;
}
}
if ( fOkay ) {
rgszEnum[0] = NULL;
EnumSize = 0;
for ( Index = 0 ; ; Index++ ) {
cbValueName = cbName;
cbValueData = cbData;
if ( Status = RegEnumValue( hKey,
Index,
szValueName,
&cbValueName,
NULL,
&ValueType,
ValueData,
&cbValueData ) ) {
FUpdateRegLastError( Status, "EnumRegValue", NULL );
break;
}
//
// Get a list in which to put the key information.
//
while ( (rgszValue = (RGSZ)SAlloc( (CB)( 5 * sizeof(SZ)))) == NULL ) {
if ( !FHandleOOM( hwndFrame ) ) {
fOkay = fFalse;
break;
}
}
if ( fOkay ) {
//
// Put the information in the list
//
if ( (fOkay = (szValueData = ValueDataToSz( ValueType, ValueData, cbValueData)) != NULL) ) {
_ultoa( TitleIndex, szTitle, 10 );
_ultoa( ValueType, szValueType, 10 );
rgszValue[0] = szValueName;
rgszValue[1] = szTitle;
rgszValue[2] = szValueType;
rgszValue[3] = szValueData;
rgszValue[4] = NULL;
//
// Transform the list into a string so that it can be added to the
// symbol table.
//
while ( (szInfo = SzListValueFromRgsz( rgszValue )) == (SZ)NULL ) {
if ( !FHandleOOM( hwndFrame ) ) {
fOkay = fFalse;
break;
}
}
if ( fOkay ) {
while ( (rgszEnum = (RGSZ)SRealloc( rgszEnum,
(CB)( (EnumSize+2) * sizeof(SZ)))
) == NULL ) {
if ( !FHandleOOM( hwndFrame ) ) {
fOkay = fFalse;
break;
}
}
if ( fOkay ) {
rgszEnum[EnumSize] = szInfo;
EnumSize++;
rgszEnum[EnumSize] = NULL;
}
}
SFree( szValueData );
}
SFree( rgszValue );
}
}
//
// Convert to SZ
//
while ( (szInfo = SzListValueFromRgsz( rgszEnum )) == (SZ)NULL ) {
if ( !FHandleOOM( hwndFrame ) ) {
fOkay = fFalse;
break;
}
}
if ( fOkay ) {
//
// Add it to the symbol table.
//
while ( !FAddSymbolValueToSymTab( szInfVar, szInfo ) ) {
if ( !FHandleOOM( hwndFrame ) ) {
fOkay = fFalse;
break;
}
}
SFree( szInfo );
}
FFreeRgsz( rgszEnum );
}
SFree( szValueName );
}
SFree( ValueData );
}
}
return (cmo & cmoVital) ? fOkay : fTrue;
}
/*
* FSetRegValueSz
*
* Sets a value under the given key for SZ type
*
* Arguments:
*
*/
BOOL FSetRegValueSz( HKEY hKey, SZ szValueName, UINT TitleIndex, SZ szValueData )
{
LONG Status;
Status = RegSetValueEx( hKey,
szValueName,
0,
REG_SZ,
szValueData,
lstrlen( szValueData ) + 1 );
if ( Status ) {
FUpdateRegLastError( Status,"SetRegValueSz", szValueName );
}
return !Status;
}
/*
* FSetRegValueExpandSz
*
* Sets a value under the given key for expand SZ type
*
* Arguments:
*
*/
BOOL
FSetRegValueExpandSz(
HKEY hKey,
SZ szValueName,
UINT TitleIndex,
SZ szValueData
)
{
LONG Status;
Status = RegSetValueEx( hKey,
szValueName,
0,
REG_EXPAND_SZ,
szValueData,
lstrlen( szValueData ) + 1 );
if ( Status ) {
FUpdateRegLastError( Status,"SetRegValueExpandSz", szValueName );
}
return !Status;
}
/*
* FSetRegValueMultiSz
*
* Sets a value under the given key for REG_MULTI_SZ type
*
* Arguments:
*
*/
BOOL
FSetRegValueMultiSz(
HKEY hKey,
SZ szValueName,
UINT TitleIndex,
UINT ValueType,
SZ szValueData
)
{
BOOL fOkay = fFalse;
PVOID Data;
DWORD cbData;
LONG Status;
Data = SzToMultiSz( szValueData, &cbData );
fOkay = !( Status = RegSetValueEx( hKey,
szValueName,
0,
ValueType,
Data,
cbData ) );
if ( !fOkay ) {
FUpdateRegLastError( Status,"SetRegValueMultiSz", szValueName );
}
if ( Data ) {
SFree( Data );
}
return fOkay;
}
/*
* FSetRegValueDword
*
* Sets a value under the given key for DWORD type
*
* Arguments:
*
*/
BOOL FSetRegValueDword( HKEY hKey, SZ szValueName, UINT TitleIndex, SZ szValueData )
{
DWORD Data;
LONG Status;
Data = (DWORD)atol(szValueData );
Status = RegSetValueEx( hKey,
szValueName,
0,
REG_DWORD,
(LPBYTE)&Data,
sizeof( DWORD ) );
if ( Status ) {
FUpdateRegLastError( Status,"SetRegValueDword", szValueName );
}
return !Status;
}
/*
* FSetRegValueBin
*
* Sets a value under the given key for BINARY and unknown types
*
* Arguments:
*
*/
BOOL FSetRegValueBin( HKEY hKey, SZ szValueName, UINT TitleIndex,
UINT ValueType, SZ szValueData )
{
BOOL fOkay = fFalse;
PVOID Data;
DWORD cbData;
LONG Status;
Data = SzToBin( szValueData, &cbData );
fOkay = !( Status = RegSetValueEx( hKey,
szValueName,
0,
ValueType,
Data,
cbData ) );
if ( !fOkay ) {
switch( ValueType ) {
case REG_BINARY:
FUpdateRegLastError( Status,"SetRegValueBin", szValueName );
break;
case REG_RESOURCE_LIST:
FUpdateRegLastError( Status,"SetRegValueResourceList", szValueName );
break;
case REG_FULL_RESOURCE_DESCRIPTOR:
FUpdateRegLastError( Status,"SetRegValueFullResourceDescriptor", szValueName );
break;
case REG_RESOURCE_REQUIREMENTS_LIST:
FUpdateRegLastError( Status,"SetRegValueResourceRequirementsList", szValueName );
break;
default:
FUpdateRegLastError( Status,"SetRegValueUnknownType", szValueName );
break;
}
}
if ( Data ) {
SFree( Data );
}
return fOkay;
}
/*
* SzToMultiSz
*
* Converts a list of sz strings to a single multi sz string
*
* Arguments:
*
*/
PVOID SzToMultiSz( SZ sz, PDWORD cbData )
{
RGSZ rgsz;
SZ p = NULL, q;
int i, j;
*cbData = 0;
if ( FListValue( sz )) {
if ( rgsz = RgszFromSzListValue( sz )) {
//
// Get size of required buffer
//
for (i = 0, j = 0; rgsz[i] != NULL; i++ ) {
j = j + strlen( rgsz[i] ) + 1;
}
j = j + 1; // for the last null
//
// Allocate buffer
//
while ( (p = q = (SZ)SAlloc( (CB)( j * sizeof( CHAR )))) == NULL ) {
if ( !FHandleOOM( hwndFrame ) ) {
break;
}
}
if ( p ) {
for ( i=0; rgsz[i] != NULL; i++ ) {
lstrcpy( q, rgsz[ i ] );
q = q + lstrlen( rgsz[ i ] ) + 1;
}
*q = '\0';
*cbData = j * sizeof( CHAR );
}
FFreeRgsz( rgsz );
}
}
return (PVOID)p;
}
/*
* MultiSzToSz
*
* Converts a block of memory to a list containing hex digits
*
* Arguments:
*
*/
SZ MultiSzToSz( PVOID Data, DWORD cbData )
{
RGSZ rgsz;
SZ sz = NULL, szData, szEnd;
DWORD i, cbList = 0;
//
// Count the number of list elements in the multi sz list. We do this
// by counting the number of '0's in the string and subtracting 1 from
// this
//
szData = (SZ)( Data );
szEnd = (SZ)( (PBYTE)Data + cbData );
while( szData < szEnd ) {
if (*szData++ == '\0') {
cbList++;
}
}
if( cbList > 0 ) {
cbList--; // remove the terminating null
//
// Allocate a rgsz list with cbList elements;
//
while ( (rgsz = (RGSZ)SAlloc( (CB)( (cbList + 1) * sizeof(SZ)))) == NULL ) {
if ( !FHandleOOM( hwndFrame ) ) {
break;
}
}
if( rgsz ) {
//
// Go through the szList and fill the rgsz structure
//
szData = (SZ)( Data );
for ( i = 0; i < cbList; i++ ) {
rgsz[i] = SzDupl( szData );
szData = szData + lstrlen( szData ) + 1;
}
rgsz[cbList] = NULL;
//
// Transform the list into a string.
//
while ( (sz = SzListValueFromRgsz( rgsz )) == (SZ)NULL ) {
if ( !FHandleOOM( hwndFrame ) ) {
break;
}
}
EvalAssert( FFreeRgsz( rgsz ) );
}
}
return( sz );
}
/*
* SzToBin
*
* Converts a list of hex digits to binary
*
* Arguments:
*
*/
PVOID SzToBin( SZ sz, PDWORD cbData )
{
RGSZ rgsz;
PBYTE p, q = NULL;
int i;
*cbData = 0;
if ( FListValue( sz )) {
if ( rgsz = RgszFromSzListValue( sz )) {
//
// Get size of required buffer
//
for (i=0; rgsz[i] != NULL; i++ );
//
// Allocate buffer
//
while ( (p = q = (PBYTE)SAlloc( (CB)( i ))) == NULL ) {
if ( !FHandleOOM( hwndFrame ) ) {
break;
}
}
if ( p ) {
for ( i=0; rgsz[i] != NULL; i++ ) {
*p++ = (BYTE)atoi( rgsz[i] );
}
*cbData = i;
}
FFreeRgsz( rgsz );
}
}
return q;
}
/*
* BinToSz
*
* Converts a block of memory to a list containing hex digits
*
* Arguments:
*
*/
SZ BinToSz( PVOID Data, DWORD cbData )
{
RGSZ rgsz;
SZ sz = NULL;
SZ szElement;
DWORD i;
PBYTE pbData;
//
// The list will contain cbData elements
//
while ( (rgsz = (RGSZ)SAlloc( (CB)( (cbData+1) * sizeof(SZ)))) == NULL ) {
if ( !FHandleOOM( hwndFrame ) ) {
break;
}
}
if ( rgsz ) {
//
// For each element of the list, allocate a buffer and convert it
// to a string
//
pbData = (PBYTE)Data;
for (i=0; i<cbData; i++ ) {
while ( (szElement = (SZ)SAlloc( (CB)( 25 ))) == NULL ) {
if ( !FHandleOOM( hwndFrame ) ) {
break;
}
}
if ( szElement ) {
_ultoa( *(pbData + i), szElement, 10 );
rgsz[i] = szElement;
} else {
rgsz[i] = NULL;
break;
}
}
if ( i == cbData ) {
rgsz[i] = NULL;
//
// Transform the list into a string.
//
while ( (sz = SzListValueFromRgsz( rgsz )) == (SZ)NULL ) {
if ( !FHandleOOM( hwndFrame ) ) {
break;
}
}
}
FFreeRgsz( rgsz );
}
return sz;
}
/*
* ValueDataToSz
*
* Converts a value data to its string form
*
* Arguments:
*
*/
SZ ValueDataToSz( DWORD ValueType, PVOID ValueData, DWORD cbData )
{
SZ sz = NULL;
switch ( ValueType ) {
case REG_SZ:
sz = SzDupl((SZ)ValueData);
break;
case REG_EXPAND_SZ:
sz = SzDupl((SZ)ValueData);
break;
case REG_DWORD:
while ( (sz = (SZ)SAlloc( (CB)( 25 ))) == NULL ) {
if ( !FHandleOOM( hwndFrame ) ) {
break;
}
}
if ( sz ) {
_ultoa( *(PDWORD)ValueData, sz, 10 );
}
break;
case REG_MULTI_SZ:
sz = MultiSzToSz( ValueData, cbData );
break;
case REG_BINARY:
default:
sz = BinToSz( ValueData, cbData );
break;
}
return sz;
}
RGSZ
MultiSzToRgsz(
IN PVOID MultiSz
)
{
PCHAR p;
ULONG Count;
RGSZ rgsz;
//
// First count the number of strings in the the multisz.
//
Count = 0;
p = MultiSz;
while(*p) {
Count++;
p = strchr(p,'\0') + 1;
}
//
// Allocate the rgsz.
//
rgsz = (RGSZ)SAlloc((Count + 1) * sizeof(PCHAR));
if(rgsz == NULL) {
return(NULL);
}
memset(rgsz,0,(Count + 1) * sizeof(PCHAR));
//
// Now place the strings in the rgsz.
//
p = MultiSz;
Count = 0;
while(*p) {
if(rgsz[Count++] = SzDupl((SZ)p)) {
p = strchr(p,'\0') + 1;
} else {
FFreeRgsz(rgsz);
return(NULL);
}
}
return(rgsz);
}
PCHAR
RgszToMultiSz(
IN RGSZ rgsz
)
{
ULONG Size;
ULONG Str;
PCHAR MultiSz;
//
// First determine the size of the block to hold the multisz.
//
Size = 0;
Str = 0;
while(rgsz[Str]) {
Size += strlen(rgsz[Str++]) + 1;
}
Size++; // for extra NUL to terminate the multisz.
MultiSz = SAlloc(Size);
if(MultiSz == NULL) {
return(NULL);
}
Str = 0;
Size = 0;
while(rgsz[Str]) {
lstrcpy(MultiSz + Size, rgsz[Str]);
Size += lstrlen(rgsz[Str++]) + 1;
}
MultiSz[Size] = 0;
return(MultiSz);
}