|
|
//-----------------------------------------------------------------------//
//
// File: add.cpp
// Created: March 1997
// By: Martin Holladay (a-martih)
// Purpose: Registry Add (Write) Support for REG.CPP
// Modification History:
// March 1997 (a-martih):
// Copied from Query.cpp and modificd.
// October 1997 (martinho)
// Added additional termination character for MULTI_SZ strings.
// Added \0 delimiter between MULTI_SZ strings items
// April 1999 Zeyong Xu: re-design, revision -> version 2.0
//------------------------------------------------------------------------//
#include "stdafx.h"
#include "reg.h"
//
// function prototypes
//
BOOL ParseAddCmdLine( DWORD argc, LPCWSTR argv[], PTREG_PARAMS pParams, BOOL* pbUsage );
//
// implementation
//
//-----------------------------------------------------------------------//
//
// AddRegistry()
//
//-----------------------------------------------------------------------//
LONG AddRegistry( DWORD argc, LPCWSTR argv[] ) { // local variables
DWORD dw = 0; DWORD dwBase = 0; DWORD dwCount = 0; HKEY hKey = NULL; LONG lEnd = 0; LONG lStart = 0; LONG lResult = 0; DWORD dwLength = 0; TREG_PARAMS params; BOOL bResult = FALSE; BYTE* pByteData = NULL; DWORD dwDisposition = 0; WCHAR wszTemp[ 3 ] = L"\0"; LPWSTR pwszValue = NULL; BOOL bTrailing = FALSE; BOOL bErrorString = FALSE; DWORD dwLengthOfSeparator = 0; LPWSTR pwszData = NULL; LPWSTR pwszTemp = NULL; LPCWSTR pwszFormat = NULL; LPCWSTR pwszList = NULL; BOOL bUsage = FALSE;
if ( argc == 0 || argv == NULL ) { SetLastError( ERROR_INVALID_PARAMETER ); ShowLastError( stderr ); return 1; }
// initialize the global data structure
InitGlobalData( REG_ADD, ¶ms );
//
// Parse the cmd-line
//
bResult = ParseAddCmdLine( argc, argv, ¶ms, &bUsage ); if( bResult == FALSE ) { ShowLastErrorEx( stderr, SLE_INTERNAL ); FreeGlobalData( ¶ms ); return 1; }
// check whether we need to display the usage
if ( bUsage == TRUE ) { Usage( REG_ADD ); FreeGlobalData( ¶ms ); return 0; }
//
// Connect to the Remote Machine - if applicable
//
bResult = RegConnectMachine( ¶ms ); if( bResult == FALSE ) { SaveErrorMessage( -1 ); ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL ); FreeGlobalData( ¶ms ); return 1; }
//
// Create/Open the registry key
//
lResult = RegCreateKeyEx( params.hRootKey, params.pwszSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hKey, &dwDisposition ); if( lResult == ERROR_SUCCESS ) { // safety check
if ( hKey == NULL ) { SaveErrorMessage( ERROR_PROCESS_ABORTED ); ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL ); FreeGlobalData( ¶ms ); return 1; }
// value name should not be NULL
if ( params.pwszValueName == NULL ) { SafeCloseKey( &hKey ); SaveErrorMessage( ERROR_INVALID_PARAMETER ); ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL ); FreeGlobalData( ¶ms ); return 1; }
// check value if existed
lResult = RegQueryValueEx( hKey, params.pwszValueName, NULL, NULL, NULL, NULL ); if( lResult == ERROR_SUCCESS ) { pwszFormat = GetResString2( IDS_OVERWRITE_CONFIRM, 0 ); pwszList = GetResString2( IDS_CONFIRM_CHOICE_LIST, 1 ); do { lResult = Prompt( pwszFormat, params.pwszValueName, pwszList, params.bForce ); } while ( lResult > 2 );
if( lResult != 1 ) { SafeCloseKey( &hKey ); SaveErrorMessage( ERROR_CANCELLED ); ShowLastErrorEx( stdout, SLE_INTERNAL ); FreeGlobalData( ¶ms ); return 0; } }
// check the error code
else if ( lResult != ERROR_FILE_NOT_FOUND ) { // some thing else happened -- need to quit
SaveErrorMessage( lResult ); ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL ); SafeCloseKey( &hKey ); FreeGlobalData( ¶ms ); return 1; }
bResult = TRUE; lResult = ERROR_SUCCESS; switch( params.lRegDataType ) { case REG_DWORD: case REG_DWORD_BIG_ENDIAN: //
// auto convert szValue (hex, octal, decimal format) to dwData
//
{ if( params.pwszValue == NULL ) { lResult = ERROR_INVALID_PARAMETER; } else { // determine the base
dwBase = 10; if ( StringCompare( params.pwszValue, L"0x", TRUE, 2 ) == 0 ) { dwBase = 16; }
if( IsNumeric( params.pwszValue, dwBase, FALSE ) == FALSE ) { // invalid data format
bResult = FALSE; lResult = IDS_ERROR_INVALID_NUMERIC_ADD; } else { // ...
dw = (DWORD) AsLong( params.pwszValue, dwBase ); lResult = RegSetValueEx( hKey, params.pwszValueName, 0, params.lRegDataType, (BYTE*) &dw, sizeof(DWORD) ); } }
break; }
case REG_BINARY: { if ( params.pwszValue == NULL ) { lResult = ERROR_INVALID_PARAMETER; } else { //
// Convert szValue (hex data string) to binary
//
dwLength = StringLength( params.pwszValue, 0 );
//
// We're converting a string (representing
// hex) into a binary stream. How much to
// allocate? E.g. for "0xABCD", which has
// a length of 4, we would need 2 bytes.
//
dwLength = (dwLength / 2) + (dwLength % 2) + 1;
pByteData = (BYTE*) AllocateMemory( dwLength * sizeof( BYTE ) ); if( pByteData == NULL ) { lResult = ERROR_NOT_ENOUGH_MEMORY; } else { dwCount = 0; pwszValue = params.pwszValue; SecureZeroMemory( wszTemp, SIZE_OF_ARRAY( wszTemp ) * sizeof( WCHAR ) ); while( (dw = StringLength( pwszValue, 0 )) > 1 ) { if ( (dw % 2) == 0 ) { wszTemp[ 0 ] = *pwszValue; pwszValue++; } else { wszTemp[ 0 ] = L'0'; }
wszTemp[ 1 ] = *pwszValue; pwszValue++;
// hex format
if( IsNumeric( wszTemp, 16, TRUE ) == FALSE ) { bResult = FALSE; lResult = IDS_ERROR_INVALID_HEXVALUE_ADD; break; } else { pByteData[ dwCount] = (BYTE) AsLong( wszTemp, 16 ); }
dwCount++;
//
// make sure we aren't stepping off our buffer
//
if( dwCount >= dwLength ) { ASSERT(0); lResult = ERROR_PROCESS_ABORTED; break; } }
if( lResult == ERROR_SUCCESS ) { lResult = RegSetValueEx( hKey, params.pwszValueName, 0, params.lRegDataType, pByteData, dwCount ); }
FreeMemory( &pByteData); } }
break; }
default: case REG_SZ: case REG_EXPAND_SZ: case REG_NONE: { if ( params.pwszValue == NULL ) { lResult = ERROR_INVALID_PARAMETER; } else { dw = (StringLength(params.pwszValue, 0) + 1) * sizeof(WCHAR); lResult = RegSetValueEx( hKey, params.pwszValueName, 0, params.lRegDataType, (BYTE*) params.pwszValue, dw ); }
break; }
case REG_MULTI_SZ: { //
// Replace separator("\0") with '\0' for MULTI_SZ,
// "\0" uses to separate string by default,
// if two separators("\0\0"), error
//
dwLength = StringLength( params.pwszValue, 0 ); dwLengthOfSeparator = StringLength( params.wszSeparator, 0 );
// calloc() initializes all char to 0
dwCount = dwLength + 2; pwszData = (LPWSTR) AllocateMemory( (dwCount + 1) * sizeof(WCHAR) ); if ( pwszData == NULL) { lResult = ERROR_NOT_ENOUGH_MEMORY; } else { lEnd = -1; lStart = 0; pwszTemp = pwszData; while( lStart < (LONG) dwLength ) { lEnd = FindString2( params.pwszValue, params.wszSeparator, TRUE, lStart ); if( lEnd != -1 ) { // specifying two separators in the data is error
bTrailing = FALSE; if ( lEnd == lStart ) { bErrorString = TRUE; break; } else if ( (dwLength - lEnd) == dwLengthOfSeparator ) { // set the flag
bTrailing = TRUE; } } else { lEnd = dwLength; }
StringCopy( pwszTemp, (params.pwszValue + lStart), (lEnd - lStart) + 1 ); pwszTemp += StringLength( pwszTemp, 0 ) + 1;
//
// make sure we aren't stepping off our buffer
//
if( pwszTemp >= (pwszData + dwCount) ) { ASSERT(0); lResult = ERROR_PROCESS_ABORTED; break; }
lStart = lEnd + dwLengthOfSeparator; }
// empty
if( StringCompare( params.pwszValue, params.wszSeparator, TRUE, 0 ) == 0 ) { pwszTemp = pwszData + 2; bErrorString = FALSE; } else { pwszTemp += 1; // double null terminated string
}
if( bErrorString == TRUE ) { bResult = FALSE; lResult = IDS_ERROR_INVALID_DATA_ADD; } else { dwCount = (DWORD)((pwszTemp - pwszData) * sizeof(WCHAR)); lResult = RegSetValueEx( hKey, params.pwszValueName, 0, params.lRegDataType, (BYTE*) pwszData, dwCount ); }
FreeMemory( &pwszData ); }
break; }
// default:
// lResult = ERROR_PROCESS_ABORTED;
// break;
} }
// close the registry key
SafeCloseKey( &hKey );
// release the memory allocated for global data
FreeGlobalData( ¶ms );
// check the result of the operation performed
if ( bResult == FALSE ) { // custom error message
ShowResMessage( stderr, lResult ); lResult = 1; } else if ( lResult != ERROR_SUCCESS ) { SaveErrorMessage( lResult ); ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL ); lResult = 1; } else { lResult = 0; SaveErrorMessage( ERROR_SUCCESS ); ShowLastErrorEx( stdout, SLE_INTERNAL ); }
// return the exit code
return lResult; }
//------------------------------------------------------------------------//
//
// ParseAddCmdLine()
//
//------------------------------------------------------------------------//
BOOL ParseAddCmdLine( DWORD argc, LPCWSTR argv[], PTREG_PARAMS pParams, BOOL* pbUsage ) { // local variables
DWORD dw = 0; LONG lResult = 0; DWORD dwLength = 0; BOOL bResult = FALSE; BOOL bHasType = FALSE; BOOL bHasSeparator = FALSE;
// check the input
if ( argc == 0 || argv == NULL || pParams == NULL || pbUsage == NULL ) { SaveErrorMessage( ERROR_INVALID_PARAMETER ); return FALSE; }
// check whether this function is being called for
// valid operation or not
if ( pParams->lOperation < 0 || pParams->lOperation >= REG_OPTIONS_COUNT ) { SaveErrorMessage( ERROR_INVALID_PARAMETER ); return FALSE; }
if( argc < 3 ) { SetLastError( (DWORD) MK_E_SYNTAX ); SetReason2( 1, ERROR_INVALID_SYNTAX_WITHOPT, g_wszOptions[ REG_ADD ] ); return FALSE; } else if ( StringCompareEx( argv[ 1 ], L"ADD", TRUE, 0 ) != 0 ) { SaveErrorMessage( ERROR_INVALID_PARAMETER ); return FALSE; } else if ( InString( argv[ 2 ], L"-?|/?|-h|/h", TRUE ) == TRUE ) { if ( argc == 3 ) { *pbUsage = TRUE; return TRUE; } else { SetLastError( (DWORD) MK_E_SYNTAX ); SetReason2( 1, ERROR_INVALID_SYNTAX_WITHOPT, g_wszOptions[ REG_ADD ] ); return FALSE; } }
// Machine Name and Registry key
//
bResult = BreakDownKeyString( argv[ 2 ], pParams ); if( bResult == FALSE ) { return FALSE; }
// parsing
bResult = TRUE; lResult = ERROR_SUCCESS; pParams->bForce = FALSE; for( dw = 3; dw < argc; dw++ ) { if( StringCompareEx( argv[ dw ], L"/v", TRUE, 0 ) == 0 ) { if( pParams->pwszValueName != NULL ) { bResult = FALSE; lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT; break; }
dw++; if( dw < argc ) { dwLength = StringLength( argv[ dw ], 0 ) + 1; pParams->pwszValueName = (LPWSTR) AllocateMemory( dwLength * sizeof(WCHAR) ); if ( pParams->pwszValueName == NULL ) { lResult = ERROR_OUTOFMEMORY; break; }
StringCopy( pParams->pwszValueName, argv[ dw ], dwLength ); TrimString( pParams->pwszValueName, TRIM_ALL ); } else { bResult = FALSE; lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT; break; } } else if( StringCompareEx( argv[ dw ], L"/ve", TRUE, 0 ) == 0 ) { if( pParams->pwszValueName != NULL ) { bResult = FALSE; lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT; break; }
// allocate some memory so that "/v" will not allowed
pParams->pwszValueName = (LPWSTR) AllocateMemory( 1 * sizeof(WCHAR) ); if( pParams->pwszValueName == NULL ) { lResult = ERROR_OUTOFMEMORY; break; } } else if( StringCompareEx( argv[ dw ], L"/t", TRUE, 0 ) == 0 ) { if ( bHasType == TRUE ) { bResult = FALSE; lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT; break; }
dw++; if( dw < argc ) { pParams->lRegDataType = IsRegDataType( argv[ dw ] ); if( pParams->lRegDataType == -1 ) { if ( IsNumeric( argv[ dw ], 10, TRUE ) == FALSE ) { bResult = FALSE; lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT; break; } else { pParams->lRegDataType = AsLong( argv[ dw ], 10 ); } }
// ...
if ( bHasSeparator == TRUE && pParams->lRegDataType != REG_MULTI_SZ ) { bResult = FALSE; lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT; break; }
bHasType = TRUE; } else { bResult = FALSE; lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT; break; } } else if( StringCompareEx( argv[ dw ], L"/s", TRUE, 0 ) == 0 ) { if( bHasSeparator == TRUE || (bHasType == TRUE && pParams->lRegDataType != REG_MULTI_SZ) ) { bResult = FALSE; lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT; break; }
dw++; if( dw < argc ) { if( StringLength( argv[ dw ], 0 ) == 1 ) { bHasSeparator = TRUE; StringCopy( pParams->wszSeparator, argv[ dw ], SIZE_OF_ARRAY( pParams->wszSeparator ) ); } else { bResult = FALSE; lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT; break; } } else { bResult = FALSE; lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT; break; } } else if( StringCompareEx( argv[ dw ], L"/d", TRUE, 0 ) == 0 ) { if( pParams->pwszValue != NULL ) { bResult = FALSE; lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT; break; }
dw++; if( dw < argc ) { dwLength = StringLength( argv[ dw ], 0 ) + 1; pParams->pwszValue = (LPWSTR) AllocateMemory( dwLength * sizeof(WCHAR) ); if (pParams->pwszValue == NULL) { lResult = ERROR_OUTOFMEMORY; break; }
StringCopy( pParams->pwszValue, argv[ dw ], dwLength ); } else { bResult = FALSE; lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT; break; } } else if( StringCompareEx( argv[ dw ], L"/f", TRUE, 0 ) == 0 ) { if ( pParams->bForce == TRUE ) { bResult = FALSE; lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT; break; }
pParams->bForce = TRUE; } else { bResult = FALSE; lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT; break; } }
if ( lResult == ERROR_SUCCESS ) { if( bHasSeparator == TRUE && bHasType == FALSE ) { bResult = FALSE; lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT; }
// if no value (or) value name, set to empty
else { if ( pParams->pwszValueName == NULL ) { pParams->pwszValueName = (LPWSTR) AllocateMemory( 1 * sizeof(WCHAR)); if( pParams->pwszValueName == NULL ) { lResult = ERROR_OUTOFMEMORY; } }
if( lResult == ERROR_SUCCESS && pParams->pwszValue == NULL ) { pParams->pwszValue = (LPWSTR) AllocateMemory( 1 * sizeof(WCHAR)); if( pParams->pwszValue == NULL ) { lResult = ERROR_OUTOFMEMORY; } } } }
if( lResult != ERROR_SUCCESS ) { if( bResult == FALSE ) { SetLastError( (DWORD) MK_E_SYNTAX ); SetReason2( 1, ERROR_INVALID_SYNTAX_WITHOPT, g_wszOptions[ REG_ADD ] ); } else { SaveErrorMessage( lResult ); } }
return (lResult == ERROR_SUCCESS); }
|