You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1503 lines
43 KiB
1503 lines
43 KiB
//-----------------------------------------------------------------------//
|
|
//
|
|
// File: query.cpp
|
|
// Created: Jan 1997
|
|
// By: Martin Holladay (a-martih)
|
|
// Purpose: Registry Query Support for REG.CPP
|
|
// Modification History:
|
|
// Created - Jan 1997 (a-martih)
|
|
// Aug 1997 (John Whited) Implemented a Binary output function for
|
|
// REG_BINARY
|
|
// Oct 1997 (martinho) fixed output for REG_MULTI_SZ \0 delimited strings
|
|
// April 1998 - MartinHo - Incremented to 1.05 for REG_MULTI_SZ bug fixes.
|
|
// Correct support for displaying query REG_MULTI_SZ of. Fix AV.
|
|
// April 1999 Zeyong Xu: re-design, revision -> version 2.0
|
|
//
|
|
//------------------------------------------------------------------------//
|
|
|
|
#include "stdafx.h"
|
|
#include "reg.h"
|
|
|
|
//
|
|
// query specific structure
|
|
//
|
|
typedef struct __tagRegQueryInfo
|
|
{
|
|
// instance level variables
|
|
BOOL bShowKey;
|
|
BOOL bKeyMatched;
|
|
BOOL bValueNameMatched;
|
|
BOOL bUpdateMatchCount;
|
|
|
|
// ...
|
|
DWORD dwMatchCount;
|
|
} TREG_QUERY_INFO, *PTREG_QUERY_INFO;
|
|
|
|
//
|
|
// function prototypes
|
|
//
|
|
BOOL ParseQueryCmdLine( DWORD argc, LPCWSTR argv[],
|
|
PTREG_PARAMS pParams, BOOL* pbUsage );
|
|
LONG QueryValue( HKEY hKey,
|
|
LPCWSTR pwszFullKey, LPCWSTR pwszValueName,
|
|
PTREG_PARAMS pParams, PTREG_QUERY_INFO pInfo );
|
|
LONG QueryEnumValues( HKEY hKey,
|
|
LPCWSTR pwszFullKey,
|
|
PTREG_PARAMS pParams, PTREG_QUERY_INFO pInfo );
|
|
LONG QueryEnumKeys( HKEY hKey,
|
|
LPCWSTR pwszFullKey,
|
|
PTREG_PARAMS pParams, PTREG_QUERY_INFO pInfo );
|
|
BOOL SearchData( LPBYTE pByteData, DWORD dwType,
|
|
DWORD dwSize, PTREG_PARAMS pParams );
|
|
BOOL ParseTypeInfo( LPCWSTR pwszTypes, PTREG_PARAMS pParams );
|
|
|
|
|
|
//
|
|
// implementation
|
|
//
|
|
|
|
//-----------------------------------------------------------------------//
|
|
//
|
|
// QueryRegistry()
|
|
//
|
|
//-----------------------------------------------------------------------//
|
|
|
|
LONG
|
|
QueryRegistry( DWORD argc, LPCWSTR argv[] )
|
|
/*++
|
|
Routine Description:
|
|
Main function for QUERY option which calls appropriate functions
|
|
|
|
Arguments:
|
|
None
|
|
Return Value:
|
|
ERROR_SUCCESS on success
|
|
EXIT_FAILURE on failure
|
|
--*/
|
|
{
|
|
// local variables
|
|
LONG lResult = 0;
|
|
HKEY hKey = NULL;
|
|
BOOL bResult = FALSE;
|
|
BOOL bUsage = FALSE;
|
|
TREG_PARAMS params;
|
|
DWORD dwExitCode = 0;
|
|
TREG_QUERY_INFO info;
|
|
BOOL bSearchMessage = FALSE;
|
|
|
|
if ( argc == 0 || argv == NULL )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
ShowLastError( stderr );
|
|
return 1;
|
|
}
|
|
|
|
// initialize the global data structure
|
|
InitGlobalData( REG_QUERY, ¶ms );
|
|
|
|
//
|
|
// Parse the cmd-line
|
|
//
|
|
bResult = ParseQueryCmdLine( 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_QUERY );
|
|
FreeGlobalData( ¶ms );
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// Connect to the Remote Machine(s) - if applicable
|
|
//
|
|
bResult = RegConnectMachine( ¶ms );
|
|
if( bResult == FALSE )
|
|
{
|
|
SaveErrorMessage( -1 );
|
|
ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
|
|
FreeGlobalData( ¶ms );
|
|
return 1;
|
|
}
|
|
|
|
//
|
|
// Open the registry key
|
|
//
|
|
lResult = RegOpenKeyEx( params.hRootKey,
|
|
params.pwszSubKey, 0, KEY_READ, &hKey );
|
|
if( lResult != ERROR_SUCCESS)
|
|
{
|
|
SaveErrorMessage( lResult );
|
|
ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
|
|
FreeGlobalData( ¶ms );
|
|
return 1;
|
|
}
|
|
|
|
// show a blank line below starting the output
|
|
ShowMessage( stdout, L"\n" );
|
|
|
|
//
|
|
// do the query
|
|
//
|
|
ZeroMemory( &info, sizeof( TREG_QUERY_INFO ) );
|
|
if( params.pwszSearchData == NULL &&
|
|
params.pwszValueName != NULL &&
|
|
params.arrTypes == NULL &&
|
|
params.bRecurseSubKeys == FALSE )
|
|
{
|
|
info.bShowKey = TRUE;
|
|
if ( params.pwszValueName != NULL &&
|
|
( StringLength( params.pwszValueName, 0 ) == 0 ||
|
|
FindOneOf2( params.pwszValueName, L"*?", TRUE, 0 ) == -1 ) )
|
|
{
|
|
lResult = QueryValue( hKey,
|
|
params.pwszFullKey, params.pwszValueName, ¶ms, &info );
|
|
|
|
bSearchMessage = FALSE;
|
|
ShowMessage( stdout, L"\n" );
|
|
}
|
|
else
|
|
{
|
|
bSearchMessage = TRUE;
|
|
lResult = QueryEnumValues( hKey, params.pwszFullKey, ¶ms, &info );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
info.bShowKey = TRUE;
|
|
lResult = QueryEnumKeys( hKey, params.pwszFullKey, ¶ms, &info );
|
|
|
|
// determine the kind of success message that needs to be displayed
|
|
bSearchMessage = ! ( params.pwszSearchData == NULL &&
|
|
params.pwszValueName == NULL && params.arrTypes == NULL );
|
|
}
|
|
|
|
dwExitCode = 0;
|
|
if ( lResult == ERROR_SUCCESS )
|
|
{
|
|
if ( bSearchMessage == FALSE )
|
|
{
|
|
//
|
|
// BUG: 698877 Reg.exe: Need to turn off newly-added success messages to avoid breaking scripts
|
|
// that parse output
|
|
//
|
|
// SaveErrorMessage( ERROR_SUCCESS );
|
|
// ShowLastErrorEx( stdout, SLE_INTERNAL );
|
|
//
|
|
}
|
|
else
|
|
{
|
|
if ( info.dwMatchCount == 0 )
|
|
{
|
|
dwExitCode = 1;
|
|
}
|
|
|
|
// ...
|
|
ShowMessageEx( stdout, 1, TRUE, STATISTICS_QUERY, info.dwMatchCount );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwExitCode = 1;
|
|
ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
|
|
}
|
|
|
|
// release the handle
|
|
SafeCloseKey( &hKey );
|
|
|
|
// return the error code
|
|
return dwExitCode;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------//
|
|
//
|
|
// ParseQueryCmdLine()
|
|
//
|
|
//------------------------------------------------------------------------//
|
|
|
|
BOOL
|
|
ParseQueryCmdLine( DWORD argc,
|
|
LPCWSTR argv[],
|
|
PTREG_PARAMS pParams, BOOL* pbUsage )
|
|
/*++
|
|
Routine Description:
|
|
Parse the command line arguments
|
|
|
|
Arguments:
|
|
None
|
|
Return Value:
|
|
REG_STATUS
|
|
--*/
|
|
{
|
|
//
|
|
// local variables
|
|
DWORD dw = 0;
|
|
DWORD dwLength = 0;
|
|
LPCWSTR pwszTemp = NULL;
|
|
LPCWSTR pwszSearchData = NULL;
|
|
|
|
// query parser result trackers
|
|
LONG lResult = 0;
|
|
BOOL bResult = FALSE;
|
|
|
|
// query operation validators
|
|
BOOL bHasSeparator = FALSE;
|
|
|
|
//
|
|
// implementation starts from here
|
|
//
|
|
|
|
// 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;
|
|
}
|
|
|
|
//
|
|
// Do we have a *valid* number of cmd-line params
|
|
//
|
|
if( argc < 3 || argc > 12 )
|
|
{
|
|
SetLastError( (DWORD) MK_E_SYNTAX );
|
|
SetReason2( 1, ERROR_INVALID_SYNTAX_WITHOPT, g_wszOptions[ REG_QUERY ] );
|
|
return FALSE;
|
|
}
|
|
else if ( StringCompareEx( argv[ 1 ], L"QUERY", 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_QUERY ] );
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
// Machine Name and Registry key
|
|
//
|
|
bResult = BreakDownKeyString( argv[ 2 ], pParams );
|
|
if( bResult == FALSE )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// parsing the command line arguments
|
|
bResult = TRUE;
|
|
lResult = ERROR_SUCCESS;
|
|
pParams->dwSearchFlags = 0;
|
|
pParams->bExactMatch = FALSE;
|
|
pParams->bCaseSensitive = FALSE;
|
|
pParams->bRecurseSubKeys = FALSE;
|
|
pParams->bShowTypeNumber = FALSE;
|
|
for( dw = 3; dw < argc; dw++ )
|
|
{
|
|
// /f -- search the registry
|
|
if( StringCompareEx( argv[ dw ], L"/f", TRUE, 0 ) == 0 )
|
|
{
|
|
if ( pwszSearchData != NULL )
|
|
{
|
|
bResult = FALSE;
|
|
lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT;
|
|
break;
|
|
}
|
|
|
|
// ...
|
|
dw++;
|
|
if( dw < argc )
|
|
{
|
|
pwszSearchData = argv[ dw ];
|
|
}
|
|
else
|
|
{
|
|
bResult = FALSE;
|
|
lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// /k -- searches the REGISTRY KEYS
|
|
else if ( StringCompareEx( argv[ dw ], L"/k", TRUE, 0 ) == 0 )
|
|
{
|
|
if ( pParams->dwSearchFlags & REG_FIND_KEYS )
|
|
{
|
|
// /k is already specified
|
|
bResult = FALSE;
|
|
lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT;
|
|
break;
|
|
}
|
|
|
|
// ...
|
|
pParams->dwSearchFlags |= REG_FIND_KEYS;
|
|
}
|
|
|
|
// /v -- searches/displays contents of the specific value names
|
|
else if( StringCompareEx( argv[ dw ], L"/v", TRUE, 0 ) == 0 )
|
|
{
|
|
if( pParams->pwszValueName != NULL ||
|
|
(pParams->dwSearchFlags & REG_FIND_VALUENAMES) )
|
|
{
|
|
bResult = FALSE;
|
|
lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT;
|
|
break;
|
|
}
|
|
|
|
if( dw + 1 < argc )
|
|
{
|
|
// determine the length of the current argument
|
|
dwLength = StringLength( argv[ dw + 1 ], 0 );
|
|
|
|
// since the value for the /v switch is optional,
|
|
// we need to see if the user specified the next switch
|
|
// or data to this switch
|
|
if ( dwLength < 2 ||
|
|
argv[ dw + 1 ][ 0 ] != L'/' ||
|
|
InString( argv[ dw + 1 ] + 1, L"z|ve|f|k|d|c|e|s|t|se", TRUE ) == FALSE )
|
|
{
|
|
// get the value for /v
|
|
dw++;
|
|
dwLength++;
|
|
pParams->pwszValueName = (LPWSTR) AllocateMemory( dwLength * sizeof( WCHAR ) );
|
|
if ( pParams->pwszValueName == NULL )
|
|
{
|
|
lResult = ERROR_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
|
|
// ...
|
|
StringCopy( pParams->pwszValueName, argv[ dw ], dwLength );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// since the value for the /v is optional
|
|
// this is a valid condition
|
|
}
|
|
|
|
// if the /v is specified and no memory is allocated for the buffer
|
|
if ( pParams->pwszValueName == NULL )
|
|
{
|
|
// set the flag
|
|
pParams->dwSearchFlags |= REG_FIND_VALUENAMES;
|
|
}
|
|
}
|
|
|
|
// /ve -- displays the data for empty value name "(Default)"
|
|
else if( StringCompareEx( argv[ dw ], L"/ve", TRUE, 0 ) == 0 )
|
|
{
|
|
if( pParams->pwszValueName != NULL ||
|
|
(pParams->dwSearchFlags & REG_FIND_VALUENAMES) )
|
|
{
|
|
bResult = FALSE;
|
|
lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT;
|
|
break;
|
|
}
|
|
|
|
pParams->pwszValueName = (LPWSTR) AllocateMemory( 2 * sizeof( WCHAR ) );
|
|
if ( pParams->pwszValueName == NULL)
|
|
{
|
|
lResult = ERROR_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// /d -- searches the DATA field of the REGISTRY
|
|
else if ( StringCompareEx( argv[ dw ], L"/d", TRUE, 0 ) == 0 )
|
|
{
|
|
if ( pParams->dwSearchFlags & REG_FIND_DATA )
|
|
{
|
|
// /d is already specified
|
|
bResult = FALSE;
|
|
lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT;
|
|
break;
|
|
}
|
|
|
|
// ...
|
|
pParams->dwSearchFlags |= REG_FIND_DATA;
|
|
}
|
|
|
|
// /c -- case sensitive search
|
|
else if( StringCompareEx( argv[ dw ], L"/c", TRUE, 0 ) == 0 )
|
|
{
|
|
if ( pParams->bCaseSensitive == TRUE )
|
|
{
|
|
bResult = FALSE;
|
|
lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT;
|
|
break;
|
|
}
|
|
|
|
// ...
|
|
pParams->bCaseSensitive = TRUE;
|
|
}
|
|
|
|
// /e -- exact text match
|
|
else if( StringCompareEx( argv[ dw ], L"/e", TRUE, 0 ) == 0 )
|
|
{
|
|
if ( pParams->bExactMatch == TRUE )
|
|
{
|
|
bResult = FALSE;
|
|
lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT;
|
|
break;
|
|
}
|
|
|
|
// ...
|
|
pParams->bExactMatch = TRUE;
|
|
}
|
|
|
|
// /z -- show the type number along with the text
|
|
else if ( StringCompareEx( argv[ dw ], L"/z", TRUE, 0 ) == 0 )
|
|
{
|
|
if ( pParams->bShowTypeNumber == TRUE )
|
|
{
|
|
bResult = FALSE;
|
|
lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT;
|
|
break;
|
|
}
|
|
|
|
// ...
|
|
pParams->bShowTypeNumber = TRUE;
|
|
}
|
|
|
|
// /s -- recursive search/display
|
|
else if( StringCompareEx( argv[ dw ], L"/s", TRUE, 0 ) == 0 )
|
|
{
|
|
if( pParams->bRecurseSubKeys == TRUE )
|
|
{
|
|
bResult = FALSE;
|
|
lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT;
|
|
break;
|
|
}
|
|
|
|
pParams->bRecurseSubKeys = TRUE;
|
|
}
|
|
|
|
// /se -- seperator to display for REG_MULTI_SZ valuename type
|
|
else if( StringCompareEx( argv[ dw ], L"/se", TRUE, 0 ) == 0 )
|
|
{
|
|
if( bHasSeparator == TRUE )
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
|
|
// /t -- REGISTRY value type that only needs to be shown
|
|
else if( StringCompareEx( argv[ dw ], L"/t", TRUE, 0 ) == 0 )
|
|
{
|
|
if ( pParams->arrTypes != NULL )
|
|
{
|
|
bResult = FALSE;
|
|
lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT;
|
|
break;
|
|
}
|
|
|
|
dw++;
|
|
if( dw < argc )
|
|
{
|
|
if ( ParseTypeInfo( argv[ dw ], pParams ) == FALSE )
|
|
{
|
|
if ( GetLastError() == (DWORD) MK_E_SYNTAX )
|
|
{
|
|
bResult = FALSE;
|
|
lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
bResult = TRUE;
|
|
lResult = GetLastError();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bResult = FALSE;
|
|
lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// default -- invalid
|
|
else
|
|
{
|
|
bResult = FALSE;
|
|
lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// validate the search information specified
|
|
if ( lResult == ERROR_SUCCESS )
|
|
{
|
|
if ( pwszSearchData == NULL )
|
|
{
|
|
if ( pParams->dwSearchFlags != 0 ||
|
|
pParams->bExactMatch == TRUE ||
|
|
pParams->bCaseSensitive == TRUE )
|
|
{
|
|
bResult = FALSE;
|
|
lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT;
|
|
}
|
|
}
|
|
else if ( pParams->dwSearchFlags == 0 )
|
|
{
|
|
if ( pParams->pwszValueName == NULL )
|
|
{
|
|
pParams->dwSearchFlags = REG_FIND_ALL;
|
|
}
|
|
else
|
|
{
|
|
pParams->dwSearchFlags = REG_FIND_KEYS | REG_FIND_DATA;
|
|
}
|
|
}
|
|
}
|
|
|
|
// prepare the final search pattern
|
|
if ( pwszSearchData != NULL && lResult == ERROR_SUCCESS )
|
|
{
|
|
// determine the length of the search pattern
|
|
dwLength = StringLength( pwszSearchData, 0 );
|
|
if ( pParams->bExactMatch == FALSE )
|
|
{
|
|
dwLength += 2;
|
|
}
|
|
|
|
// accomodate space for null characters
|
|
dwLength++;
|
|
|
|
// allocate memory
|
|
pParams->pwszSearchData = AllocateMemory( (dwLength + 2) * sizeof( WCHAR ) );
|
|
if ( pParams->pwszSearchData == NULL )
|
|
{
|
|
lResult = ERROR_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
// if the /e is not specified -- we will search for "*<text>*"
|
|
// otherwise if /e is specified we will search exactly for "<text>"
|
|
// where "<text>" is what is specified by user at the command prompt
|
|
|
|
StringCopy( pParams->pwszSearchData, L"", dwLength );
|
|
if ( pParams->bExactMatch == FALSE )
|
|
{
|
|
StringCopy( pParams->pwszSearchData, L"*", dwLength );
|
|
}
|
|
|
|
// ...
|
|
StringConcat( pParams->pwszSearchData, pwszSearchData, dwLength );
|
|
|
|
// ...
|
|
if ( pParams->bExactMatch == FALSE )
|
|
{
|
|
StringConcat( pParams->pwszSearchData, L"*", dwLength );
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// if /t is specified, then /s needs to be specified
|
|
// if /s is not specified, then atleast /v or /ve should not be specified
|
|
//
|
|
// if ( lResult == ERROR_SUCCESS && pParams->arrTypes != NULL &&
|
|
// pParams->bRecurseSubKeys == FALSE && pParams->pwszValueName != NULL )
|
|
// {
|
|
// bResult = FALSE;
|
|
// lResult = IDS_ERROR_INVALID_SYNTAX_WITHOPT;
|
|
// }
|
|
|
|
//
|
|
// parse the pattern information if specified by user and store only
|
|
// the optimized version of it
|
|
//
|
|
if ( lResult == ERROR_SUCCESS )
|
|
{
|
|
//
|
|
// value name
|
|
//
|
|
if ( pParams->pwszValueName != NULL &&
|
|
StringLength( pParams->pwszValueName, 0 ) != 0 )
|
|
{
|
|
pwszTemp = ParsePattern( pParams->pwszValueName );
|
|
if ( pwszTemp == NULL )
|
|
{
|
|
lResult = GetLastError();
|
|
}
|
|
|
|
// copy the optimized pattern into the original buffer
|
|
dw = GetBufferSize( pParams->pwszValueName );
|
|
StringCopy( pParams->pwszValueName, pwszTemp, dw );
|
|
}
|
|
|
|
//
|
|
// search data
|
|
//
|
|
if ( pParams->pwszSearchData != NULL )
|
|
{
|
|
pwszTemp = ParsePattern( pParams->pwszSearchData );
|
|
if ( pwszTemp == NULL )
|
|
{
|
|
lResult = GetLastError();
|
|
}
|
|
|
|
// copy the optimized pattern into the original buffer
|
|
dw = GetBufferSize( pParams->pwszSearchData );
|
|
StringCopy( pParams->pwszSearchData, pwszTemp, dw );
|
|
}
|
|
}
|
|
|
|
//
|
|
// check the end result
|
|
//
|
|
if( lResult != ERROR_SUCCESS )
|
|
{
|
|
if( bResult == FALSE )
|
|
{
|
|
SetLastError( (DWORD) MK_E_SYNTAX );
|
|
SetReason2( 1, ERROR_INVALID_SYNTAX_WITHOPT, g_wszOptions[ REG_QUERY ] );
|
|
}
|
|
else
|
|
{
|
|
SaveErrorMessage( lResult );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
}
|
|
|
|
// return the result
|
|
return (lResult == ERROR_SUCCESS);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------//
|
|
//
|
|
// QueryValue()
|
|
//
|
|
//-----------------------------------------------------------------------//
|
|
LONG
|
|
QueryValue( HKEY hKey,
|
|
LPCWSTR pwszFullKey,
|
|
LPCWSTR pwszValueName,
|
|
PTREG_PARAMS pParams, PTREG_QUERY_INFO pInfo )
|
|
{
|
|
// local variables
|
|
LONG lResult = 0;
|
|
DWORD dwType = 0;
|
|
DWORD dwLength = 0;
|
|
PBYTE pByteData = NULL;
|
|
TREG_SHOW_INFO showinfo;
|
|
BOOL bDataMatched = FALSE;
|
|
|
|
// check the input
|
|
if ( hKey == NULL || pwszFullKey == NULL ||
|
|
pwszValueName == NULL || pParams == NULL || pInfo == NULL )
|
|
{
|
|
SaveErrorMessage( ERROR_INVALID_PARAMETER );
|
|
lResult = ERROR_INVALID_PARAMETER;
|
|
goto cleanup;
|
|
}
|
|
|
|
// get the size of the buffer to hold the value associated with the value name
|
|
lResult = RegQueryValueEx( hKey, pwszValueName, NULL, NULL, NULL, &dwLength );
|
|
if ( lResult != ERROR_SUCCESS )
|
|
{
|
|
// special case -- "(Default)" value
|
|
if ( lResult == ERROR_FILE_NOT_FOUND &&
|
|
StringLength( pwszValueName, 0 ) == 0 )
|
|
{
|
|
dwLength = StringLength( GetResString2( IDS_VALUENOTSET, 0 ), 0 ) + 1;
|
|
dwLength *= sizeof( WCHAR );
|
|
}
|
|
else
|
|
{
|
|
SaveErrorMessage( lResult );
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
//
|
|
// to handle the corrupted registry data properly, adjust the memory
|
|
// allocation size which is divisible by 2
|
|
//
|
|
dwLength += (dwLength % 2);
|
|
|
|
// allocate the buffer
|
|
pByteData = (LPBYTE) AllocateMemory( (dwLength + 2) * sizeof( BYTE ) );
|
|
if ( pByteData == NULL )
|
|
{
|
|
SaveErrorMessage( ERROR_OUTOFMEMORY );
|
|
lResult = ERROR_OUTOFMEMORY;
|
|
goto cleanup;
|
|
}
|
|
|
|
// now get the data
|
|
lResult = RegQueryValueEx( hKey, pwszValueName, NULL, &dwType, pByteData, &dwLength );
|
|
if ( lResult != ERROR_SUCCESS )
|
|
{
|
|
// special case -- "(Default)" value
|
|
if ( lResult == ERROR_FILE_NOT_FOUND &&
|
|
StringLength( pwszValueName, 0 ) == 0 )
|
|
{
|
|
dwType = REG_SZ;
|
|
StringCopy( (LPWSTR) pByteData,
|
|
GetResString2( IDS_VALUENOTSET, 0 ), dwLength / sizeof( WCHAR ));
|
|
}
|
|
else
|
|
{
|
|
SaveErrorMessage( lResult );
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
// check whether the data matches with the search pattern specified
|
|
bDataMatched = TRUE; // default
|
|
if ( pInfo->bValueNameMatched == FALSE )
|
|
{
|
|
if ( pParams->dwSearchFlags & REG_FIND_DATA )
|
|
{
|
|
bDataMatched = SearchData( pByteData, dwType, dwLength, pParams );
|
|
if ( bDataMatched == TRUE )
|
|
{
|
|
pInfo->dwMatchCount++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// check the result of the search
|
|
if ( bDataMatched == FALSE )
|
|
{
|
|
SetLastError( ERROR_NOT_FOUND );
|
|
lResult = ERROR_SUCCESS;
|
|
goto cleanup;
|
|
}
|
|
|
|
// if the bUpdateMatchCount flag is set -- increment the matched
|
|
// count by 1 and reset the flag
|
|
if ( pInfo->bUpdateMatchCount == TRUE )
|
|
{
|
|
if ( pParams->pwszValueName == NULL && pParams->arrTypes == NULL )
|
|
{
|
|
pInfo->dwMatchCount++;
|
|
}
|
|
|
|
// ...
|
|
pInfo->bUpdateMatchCount = FALSE;
|
|
}
|
|
|
|
// show the full key -- if needed
|
|
if ( pInfo->bShowKey == TRUE )
|
|
{
|
|
// display the key path for which query proceeds
|
|
ShowMessageEx( stdout, 1, TRUE, L"%s\n", pwszFullKey );
|
|
|
|
// flag off -- this will block from display the full key for each value
|
|
pInfo->bShowKey = FALSE;
|
|
}
|
|
|
|
// update the match count -- if needed
|
|
if ( pParams->pwszValueName != NULL || pParams->arrTypes != NULL )
|
|
{
|
|
pInfo->dwMatchCount++;
|
|
}
|
|
|
|
// init to ZERO
|
|
ZeroMemory( &showinfo, sizeof( TREG_SHOW_INFO ) );
|
|
|
|
// set the data
|
|
showinfo.pwszValueName = pwszValueName;
|
|
showinfo.dwType = dwType;
|
|
showinfo.pByteData = pByteData;
|
|
showinfo.pwszSeparator = L" ";
|
|
showinfo.dwMaxValueNameLength = 0;
|
|
showinfo.dwPadLength = 4;
|
|
showinfo.dwSize = dwLength;
|
|
showinfo.pwszMultiSzSeparator = pParams->wszSeparator;
|
|
if ( pParams->bShowTypeNumber == TRUE )
|
|
{
|
|
showinfo.dwFlags |= RSI_SHOWTYPENUMBER;
|
|
}
|
|
|
|
// show
|
|
ShowRegistryValue( &showinfo );
|
|
|
|
// end result
|
|
lResult = ERROR_SUCCESS;
|
|
|
|
cleanup:
|
|
|
|
// release the memory
|
|
FreeMemory( &pByteData );
|
|
|
|
// return
|
|
return lResult;
|
|
}
|
|
|
|
|
|
LONG
|
|
QueryEnumValues( HKEY hKey,
|
|
LPCWSTR pwszFullKey,
|
|
PTREG_PARAMS pParams, PTREG_QUERY_INFO pInfo )
|
|
/*++
|
|
Routine Description:
|
|
Queries Values and Data
|
|
|
|
Arguments:
|
|
None
|
|
Return Value:
|
|
ERROR_SUCCESS on success
|
|
EXIT_FAILURE on failure
|
|
--*/
|
|
{
|
|
// local variables
|
|
DWORD dw = 0;
|
|
LONG lResult = 0;
|
|
DWORD dwType = 0;
|
|
DWORD dwLength = 0;
|
|
DWORD dwMaxLength = 0;
|
|
DWORD dwValueNames = 0;
|
|
LPWSTR pwszValueName = NULL;
|
|
|
|
// check the input
|
|
if ( hKey == NULL || pwszFullKey == NULL || pParams == NULL || pInfo == NULL )
|
|
{
|
|
SaveErrorMessage( ERROR_INVALID_PARAMETER );
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// First find out how much memory to allocate.
|
|
//
|
|
lResult = RegQueryInfoKey( hKey,
|
|
NULL, NULL, NULL, NULL, NULL, NULL,
|
|
&dwValueNames, &dwMaxLength, NULL, NULL, NULL );
|
|
if ( lResult != ERROR_SUCCESS )
|
|
{
|
|
SaveErrorMessage( lResult );
|
|
return lResult;
|
|
}
|
|
|
|
//
|
|
// do the memory allocations
|
|
//
|
|
|
|
// value name
|
|
dwMaxLength++;
|
|
pwszValueName = (LPWSTR) AllocateMemory( dwMaxLength * sizeof( WCHAR ) );
|
|
if ( pwszValueName == NULL )
|
|
{
|
|
SaveErrorMessage( ERROR_OUTOFMEMORY );
|
|
return lResult;
|
|
}
|
|
|
|
//
|
|
// enumerate the value names and display
|
|
//
|
|
lResult = ERROR_SUCCESS;
|
|
for( dw = 0; dw < dwValueNames; dw++ )
|
|
{
|
|
dwLength = dwMaxLength;
|
|
ZeroMemory( pwszValueName, dwLength * sizeof( WCHAR ) );
|
|
lResult = RegEnumValue( hKey, dw,
|
|
pwszValueName, &dwLength, NULL, &dwType, NULL, NULL );
|
|
if ( lResult != ERROR_SUCCESS )
|
|
{
|
|
SaveErrorMessage( lResult );
|
|
break;
|
|
}
|
|
|
|
// check if user is looking for any explicit value name
|
|
// this will improve the performance of the tool
|
|
if ( pParams->pwszValueName != NULL &&
|
|
MatchPatternEx( pwszValueName,
|
|
pParams->pwszValueName,
|
|
PATTERN_COMPARE_IGNORECASE | PATTERN_NOPARSING ) == FALSE )
|
|
{
|
|
// skip processing this value name
|
|
continue;
|
|
}
|
|
|
|
// filter on type information
|
|
if ( pParams->arrTypes != NULL &&
|
|
DynArrayFindLongEx( pParams->arrTypes, 1, dwType ) == -1 )
|
|
{
|
|
// skip processing this value names
|
|
continue;
|
|
}
|
|
|
|
// search for the pattern -- if needed
|
|
pInfo->bValueNameMatched = TRUE; // default
|
|
if ( pParams->dwSearchFlags & REG_FIND_VALUENAMES )
|
|
{
|
|
pInfo->bValueNameMatched = SearchData(
|
|
(BYTE*) pwszValueName, REG_SZ, dwLength * sizeof( WCHAR ), pParams );
|
|
if ( pInfo->bValueNameMatched == FALSE )
|
|
{
|
|
if ( pParams->dwSearchFlags == REG_FIND_VALUENAMES )
|
|
{
|
|
// user just want to search in the value names
|
|
// since the current didn't match skip this valuename
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( pParams->pwszValueName == NULL && pParams->arrTypes == NULL )
|
|
{
|
|
pInfo->dwMatchCount++;
|
|
}
|
|
}
|
|
}
|
|
else if ( pParams->dwSearchFlags != 0 &&
|
|
pParams->pwszValueName == NULL && pParams->arrTypes == NULL )
|
|
{
|
|
pInfo->bValueNameMatched = FALSE;
|
|
}
|
|
|
|
// process the value of this regisry valuename
|
|
if ( pInfo->bValueNameMatched == TRUE ||
|
|
pParams->dwSearchFlags == 0 || pParams->dwSearchFlags & REG_FIND_DATA )
|
|
{
|
|
lResult = QueryValue( hKey, pwszFullKey, pwszValueName, pParams, pInfo );
|
|
}
|
|
}
|
|
|
|
// show the new line at the end -- only if needed
|
|
if ( pInfo->bShowKey == FALSE )
|
|
{
|
|
ShowMessage( stdout, L"\n" );
|
|
}
|
|
|
|
// release the memory
|
|
FreeMemory( &pwszValueName );
|
|
|
|
// return
|
|
return lResult;
|
|
}
|
|
|
|
|
|
LONG
|
|
QueryEnumKeys( HKEY hKey,
|
|
LPCWSTR pwszFullKey,
|
|
PTREG_PARAMS pParams, PTREG_QUERY_INFO pInfo )
|
|
/*++
|
|
Routine Description:
|
|
Queries Values and Data
|
|
|
|
Arguments:
|
|
None
|
|
Return Value:
|
|
ERROR_SUCCESS on success
|
|
EXIT_FAILURE on failure
|
|
--*/
|
|
{
|
|
// local variables
|
|
DWORD dw = 0;
|
|
LONG lResult = 0;
|
|
DWORD dwLength = 0;
|
|
DWORD dwSubKeys = 0;
|
|
DWORD dwMaxLength = 0;
|
|
HKEY hSubKey = NULL;
|
|
DWORD dwNewFullKeyLength = 0;
|
|
LPWSTR pwszSubKey = NULL;
|
|
LPWSTR pwszNewFullKey = NULL;
|
|
|
|
// check the input
|
|
if ( hKey == NULL ||
|
|
pwszFullKey == NULL ||
|
|
pParams == NULL || pInfo == NULL )
|
|
{
|
|
SaveErrorMessage( ERROR_INVALID_PARAMETER );
|
|
lResult = ERROR_INVALID_PARAMETER;
|
|
goto cleanup;
|
|
}
|
|
|
|
// show the values under the current hive first
|
|
// NOTE: enumerate the values only when /F is not specified
|
|
// or subkey is matched or search flags specify to search in
|
|
// value names and/or data also
|
|
if ( pInfo->bKeyMatched == TRUE &&
|
|
pParams->dwSearchFlags == REG_FIND_KEYS &&
|
|
pParams->pwszValueName == NULL && pParams->arrTypes == NULL )
|
|
{
|
|
// do nothing
|
|
}
|
|
else if ( pParams->dwSearchFlags == 0 ||
|
|
pParams->dwSearchFlags != REG_FIND_KEYS ||
|
|
(pInfo->bKeyMatched == TRUE && (pParams->pwszValueName != NULL || pParams->arrTypes != NULL)) )
|
|
{
|
|
lResult = QueryEnumValues( hKey, pwszFullKey, pParams, pInfo );
|
|
if ( lResult != ERROR_SUCCESS )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
//
|
|
// First find out how much memory to allocate.
|
|
//
|
|
lResult = RegQueryInfoKey( hKey, NULL, NULL, NULL,
|
|
&dwSubKeys, &dwMaxLength, NULL, NULL, NULL, NULL, NULL, NULL );
|
|
if ( lResult != ERROR_SUCCESS )
|
|
{
|
|
SaveErrorMessage( lResult );
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// SPECIAL CASE:
|
|
// -------------
|
|
// For HKLM\SYSTEM\CONTROLSET002 it is found to be API returning value 0 for dwMaxLength
|
|
// though there are subkeys underneath this -- to handle this, we are doing a workaround
|
|
// by assuming the max registry key length
|
|
//
|
|
if ( dwSubKeys != 0 && dwMaxLength == 0 )
|
|
{
|
|
dwMaxLength = 256;
|
|
}
|
|
else if ( dwMaxLength < 256 )
|
|
{
|
|
// always assume 100% more length that what is returned by the API
|
|
dwMaxLength *= 2;
|
|
}
|
|
|
|
//
|
|
// do the memory allocations
|
|
//
|
|
|
|
// sub key
|
|
dwMaxLength++;
|
|
pwszSubKey = (LPWSTR) AllocateMemory( dwMaxLength * sizeof( WCHAR ) );
|
|
if ( pwszSubKey == NULL )
|
|
{
|
|
SaveErrorMessage( ERROR_OUTOFMEMORY );
|
|
lResult = ERROR_OUTOFMEMORY;
|
|
goto cleanup;
|
|
}
|
|
|
|
// buffer for new full key name
|
|
dwNewFullKeyLength = StringLength( pwszFullKey, 0 ) + dwMaxLength + 1;
|
|
pwszNewFullKey = (LPWSTR) AllocateMemory( dwNewFullKeyLength * sizeof( WCHAR ) );
|
|
if ( pwszNewFullKey == NULL )
|
|
{
|
|
SaveErrorMessage( ERROR_OUTOFMEMORY );
|
|
lResult = ERROR_OUTOFMEMORY;
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// enumerate the value names and display
|
|
//
|
|
lResult = ERROR_SUCCESS;
|
|
for( dw = 0; dw < dwSubKeys; dw++ )
|
|
{
|
|
dwLength = dwMaxLength;
|
|
ZeroMemory( pwszSubKey, dwLength * sizeof( WCHAR ) );
|
|
lResult = RegEnumKeyEx( hKey, dw,
|
|
pwszSubKey, &dwLength, NULL, NULL, NULL, NULL );
|
|
if ( lResult != ERROR_SUCCESS )
|
|
{
|
|
// **********************************************************
|
|
// simply ignore the error here -- for a detailed description
|
|
// check the raid bug #572077
|
|
// **********************************************************
|
|
lResult = ERROR_SUCCESS;
|
|
continue;
|
|
}
|
|
|
|
// search for the pattern -- if needed
|
|
pInfo->bKeyMatched = TRUE; // default
|
|
pInfo->bUpdateMatchCount = FALSE;
|
|
if ( pParams->dwSearchFlags & REG_FIND_KEYS )
|
|
{
|
|
pInfo->bKeyMatched = SearchData(
|
|
(BYTE*) pwszSubKey, REG_SZ, dwLength * sizeof( WCHAR ), pParams );
|
|
if ( pInfo->bKeyMatched == FALSE )
|
|
{
|
|
if ( pParams->bRecurseSubKeys == FALSE &&
|
|
pParams->dwSearchFlags == REG_FIND_KEYS )
|
|
{
|
|
// user just want to search in the key names
|
|
// and there is no recursion
|
|
// since the current didn't match skip this key
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pInfo->bUpdateMatchCount = TRUE;
|
|
}
|
|
}
|
|
else if ( pParams->dwSearchFlags != 0 || pParams->pwszValueName != NULL )
|
|
{
|
|
pInfo->bKeyMatched = FALSE;
|
|
}
|
|
|
|
// format the new full key name
|
|
StringCopy( pwszNewFullKey, pwszFullKey, dwNewFullKeyLength );
|
|
StringConcat( pwszNewFullKey, L"\\", dwNewFullKeyLength );
|
|
StringConcat( pwszNewFullKey, pwszSubKey, dwNewFullKeyLength );
|
|
|
|
// show the key name
|
|
pInfo->bShowKey = TRUE;
|
|
if ( pInfo->bKeyMatched == TRUE && pParams->pwszValueName == NULL && pParams->arrTypes == NULL )
|
|
{
|
|
// update the match count
|
|
pInfo->dwMatchCount++;
|
|
pInfo->bUpdateMatchCount = FALSE;
|
|
|
|
// ...
|
|
pInfo->bShowKey = FALSE;
|
|
ShowMessageEx( stdout, 1, TRUE, L"%s\n", pwszNewFullKey );
|
|
}
|
|
|
|
// check whether we need to recurse or not
|
|
if ( pParams->bRecurseSubKeys == TRUE )
|
|
{
|
|
lResult = RegOpenKeyEx( hKey, pwszSubKey, 0, KEY_READ, &hSubKey );
|
|
if ( lResult == ERROR_SUCCESS )
|
|
{
|
|
// enumerate the sub-keys
|
|
lResult = QueryEnumKeys( hSubKey, pwszNewFullKey, pParams, pInfo );
|
|
|
|
// close the sub key
|
|
SafeCloseKey( &hSubKey );
|
|
}
|
|
else
|
|
{
|
|
// **********************************************************
|
|
// simply ignore the error here -- for a detailed description
|
|
// check the raid bug #572077
|
|
// **********************************************************
|
|
lResult = ERROR_SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
|
|
cleanup:
|
|
|
|
// release the memory
|
|
FreeMemory( &pwszSubKey );
|
|
FreeMemory( &pwszNewFullKey );
|
|
|
|
// return
|
|
return lResult;
|
|
}
|
|
|
|
|
|
BOOL
|
|
SearchData( LPBYTE pByteData, DWORD dwType,
|
|
DWORD dwSize, PTREG_PARAMS pParams )
|
|
{
|
|
// local variables
|
|
DWORD dw = 0;
|
|
DWORD dwLength = 0;
|
|
BOOL bResult = FALSE;
|
|
LPCWSTR pwszEnd = NULL;
|
|
LPCWSTR pwszData = NULL;
|
|
LPWSTR pwszString = NULL;
|
|
LPCWSTR pwszSeparator = NULL;
|
|
BOOL bShowSeparator = FALSE;
|
|
DWORD dwFlags = 0;
|
|
|
|
// check input
|
|
if ( pByteData == NULL || pParams == NULL )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return FALSE;
|
|
}
|
|
|
|
switch( dwType )
|
|
{
|
|
case REG_SZ:
|
|
case REG_EXPAND_SZ:
|
|
{
|
|
pwszData = (LPCWSTR) pByteData;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
// allocate memory which is double the (dwSize + 1) & +10 -> buffer
|
|
// but do this only for types that need memory allocation
|
|
dwLength = (dwSize + 1) * 2 + 10;
|
|
pwszString = (LPWSTR) AllocateMemory( dwLength * sizeof( WCHAR ) );
|
|
if ( pwszString == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// ...
|
|
pwszData = pwszString;
|
|
}
|
|
}
|
|
|
|
switch( dwType )
|
|
{
|
|
case REG_MULTI_SZ:
|
|
{
|
|
//
|
|
// Replace '\0' with "\0" for MULTI_SZ
|
|
//
|
|
pwszEnd = (LPCWSTR) pByteData;
|
|
pwszSeparator = pParams->wszSeparator;
|
|
StringCopy( pwszString, cwszNullString, dwLength );
|
|
while( ((BYTE*) pwszEnd) < (pByteData + dwSize) )
|
|
{
|
|
if( *pwszEnd == 0 )
|
|
{
|
|
// enable the display of value separator and skip this
|
|
pwszEnd++;
|
|
bShowSeparator = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// check whether we need to display the separator or not
|
|
if ( bShowSeparator == TRUE )
|
|
{
|
|
StringConcat( pwszString, pwszSeparator, dwLength );
|
|
}
|
|
|
|
// ...
|
|
StringConcat( pwszString, pwszEnd, dwLength );
|
|
pwszEnd += StringLength( pwszEnd, 0 );
|
|
}
|
|
}
|
|
|
|
// ...
|
|
break;
|
|
}
|
|
|
|
case REG_SZ:
|
|
case REG_EXPAND_SZ:
|
|
// do nothing
|
|
break;
|
|
|
|
default:
|
|
{
|
|
StringCopy( pwszString, cwszNullString, dwLength );
|
|
for( dw = 0; dw < dwSize; dw++ )
|
|
{
|
|
if ( SetReason2( 1, L"%02X", pByteData[ dw ] ) == FALSE )
|
|
{
|
|
FreeMemory( &pwszString );
|
|
SetLastError( ERROR_OUTOFMEMORY );
|
|
return FALSE;
|
|
}
|
|
|
|
// ...
|
|
StringConcat( pwszString, GetReason(), dwLength );
|
|
}
|
|
|
|
// ...
|
|
break;
|
|
}
|
|
|
|
case REG_DWORD:
|
|
case REG_DWORD_BIG_ENDIAN:
|
|
{
|
|
if ( StringCompare( pParams->pwszSearchData, L"0x", TRUE, 2 ) == 0 )
|
|
{
|
|
if ( SetReason2( 1, L"0x%x", *((DWORD*) pByteData) ) == FALSE )
|
|
{
|
|
FreeMemory( &pwszString );
|
|
SetLastError( ERROR_OUTOFMEMORY );
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( SetReason2( 1, L"%d", *((DWORD*) pByteData) ) == FALSE )
|
|
{
|
|
FreeMemory( &pwszString );
|
|
SetLastError( ERROR_OUTOFMEMORY );
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
// ...
|
|
StringCopy( pwszString, GetReason(), dwLength );
|
|
break;
|
|
}
|
|
}
|
|
|
|
// do the search now
|
|
bResult = TRUE;
|
|
if ( pParams->bExactMatch == FALSE )
|
|
{
|
|
// prepare the comparision flags
|
|
dwFlags = PATTERN_NOPARSING;
|
|
dwFlags |= ((pParams->bCaseSensitive == FALSE) ? PATTERN_COMPARE_IGNORECASE : 0);
|
|
|
|
// ...
|
|
if ( MatchPatternEx( pwszData, pParams->pwszSearchData, dwFlags ) == FALSE )
|
|
{
|
|
bResult = FALSE;
|
|
SetLastError( ERROR_NOT_FOUND );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( StringCompare( pwszData,
|
|
pParams->pwszSearchData,
|
|
(pParams->bCaseSensitive == FALSE), 0 ) != 0 )
|
|
{
|
|
bResult = FALSE;
|
|
SetLastError( ERROR_NOT_FOUND );
|
|
}
|
|
}
|
|
|
|
// release the memory allocated
|
|
FreeMemory( &pwszString );
|
|
|
|
// return
|
|
return bResult;
|
|
}
|
|
|
|
|
|
BOOL
|
|
ParseTypeInfo( LPCWSTR pwszTypes,
|
|
PTREG_PARAMS pParams )
|
|
{
|
|
// local variables
|
|
LONG lArrayIndex = 0;
|
|
LONG lLength = 0;
|
|
LONG lIndex = 0;
|
|
LONG lStart = 0;
|
|
LONG lType = 0;
|
|
LPCWSTR pwsz = NULL;
|
|
|
|
// check input
|
|
if ( pwszTypes == NULL || pParams == NULL )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return FALSE;
|
|
}
|
|
|
|
// validate the types array
|
|
if ( pParams->arrTypes == NULL )
|
|
{
|
|
pParams->arrTypes = CreateDynamicArray();
|
|
if ( pParams->arrTypes == NULL )
|
|
{
|
|
SetLastError( ERROR_OUTOFMEMORY );
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
// parse the types information
|
|
lStart = lIndex = 0;
|
|
while ( lIndex != -1 )
|
|
{
|
|
lIndex = FindString2( pwszTypes, L",", TRUE, lStart );
|
|
if ( lIndex == -1 )
|
|
{
|
|
lLength = 0;
|
|
}
|
|
else
|
|
{
|
|
lLength = lIndex - lStart;
|
|
}
|
|
|
|
// append a row
|
|
lArrayIndex = DynArrayAppendRow( pParams->arrTypes, 2 );
|
|
if ( lArrayIndex == -1 )
|
|
{
|
|
SetLastError( ERROR_OUTOFMEMORY );
|
|
return FALSE;
|
|
}
|
|
|
|
// add the type info
|
|
if ( DynArraySetString2( pParams->arrTypes,
|
|
lArrayIndex, 0, pwszTypes + lStart, lLength ) == -1 )
|
|
{
|
|
SetLastError( ERROR_OUTOFMEMORY );
|
|
return FALSE;
|
|
}
|
|
|
|
// get the type back from array
|
|
pwsz = DynArrayItemAsString2( pParams->arrTypes, lArrayIndex, 0 );
|
|
if ( pwsz == NULL )
|
|
{
|
|
SetLastError( (DWORD) STG_E_UNKNOWN );
|
|
return FALSE;
|
|
}
|
|
|
|
// determine the numeric equivalent of it
|
|
lType = IsRegDataType( pwsz );
|
|
if( lType == -1 )
|
|
{
|
|
if (IsNumeric( pwsz, 10, TRUE ) == TRUE )
|
|
{
|
|
lType = AsLong( pwsz, 10 );
|
|
}
|
|
else
|
|
{
|
|
SetLastError( (DWORD) MK_E_SYNTAX );
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
if ( DynArraySetLong2( pParams->arrTypes, lArrayIndex, 1, lType ) == -1 )
|
|
{
|
|
SetLastError( ERROR_OUTOFMEMORY );
|
|
return FALSE;
|
|
}
|
|
|
|
// update the start position
|
|
lStart = lIndex + 1;
|
|
}
|
|
|
|
// ...
|
|
SetLastError( ERROR_SUCCESS );
|
|
return TRUE;
|
|
}
|