554 lines
14 KiB
C
554 lines
14 KiB
C
|
//-----------------------------------------------------------------------//
|
||
|
//
|
||
|
// 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"
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------//
|
||
|
//
|
||
|
// QueryRegistry()
|
||
|
//
|
||
|
//-----------------------------------------------------------------------//
|
||
|
|
||
|
LONG QueryRegistry(PAPPVARS pAppVars, UINT argc, TCHAR *argv[])
|
||
|
{
|
||
|
LONG nResult;
|
||
|
HKEY hKey;
|
||
|
|
||
|
//
|
||
|
// Parse the cmd-line
|
||
|
//
|
||
|
nResult = ParseQueryCmdLine(pAppVars, argc, argv);
|
||
|
if (nResult != ERROR_SUCCESS)
|
||
|
{
|
||
|
return nResult;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Connect to the Remote Machine(s) - if applicable
|
||
|
//
|
||
|
nResult = RegConnectMachine(pAppVars);
|
||
|
if (nResult != ERROR_SUCCESS)
|
||
|
{
|
||
|
return nResult;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Open the registry key
|
||
|
//
|
||
|
nResult = RegOpenKeyEx(pAppVars->hRootKey,
|
||
|
pAppVars->szSubKey,
|
||
|
0,
|
||
|
KEY_READ,
|
||
|
&hKey);
|
||
|
|
||
|
if(nResult != ERROR_SUCCESS)
|
||
|
return nResult;
|
||
|
|
||
|
MyTPrintf(stdout,_T("\r\n! REG.EXE VERSION %s\r\n"), REG_EXE_FILEVERSION);
|
||
|
|
||
|
//
|
||
|
// if query a single registry value
|
||
|
//
|
||
|
if(pAppVars->szValueName)
|
||
|
{
|
||
|
// first print the key name
|
||
|
MyTPrintf(stdout,_T("\r\n%s\r\n"), pAppVars->szFullKey);
|
||
|
|
||
|
nResult = QueryValue(hKey, pAppVars->szValueName);
|
||
|
MyTPrintf(stdout,_T("\r\n"));
|
||
|
}
|
||
|
else // query a registry key
|
||
|
{
|
||
|
nResult = QueryEnumerateKey(hKey,
|
||
|
pAppVars->szFullKey,
|
||
|
pAppVars->bRecurseSubKeys);
|
||
|
}
|
||
|
|
||
|
RegCloseKey(hKey);
|
||
|
|
||
|
return nResult;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------------//
|
||
|
//
|
||
|
// ParseQueryCmdLine()
|
||
|
//
|
||
|
//------------------------------------------------------------------------//
|
||
|
|
||
|
REG_STATUS ParseQueryCmdLine(PAPPVARS pAppVars, UINT argc, TCHAR *argv[])
|
||
|
{
|
||
|
REG_STATUS nResult;
|
||
|
UINT i;
|
||
|
|
||
|
if(argc < 3)
|
||
|
{
|
||
|
return REG_STATUS_TOFEWPARAMS;
|
||
|
}
|
||
|
else if(argc > 5)
|
||
|
{
|
||
|
return REG_STATUS_TOMANYPARAMS;
|
||
|
}
|
||
|
|
||
|
// Machine Name and Registry key
|
||
|
//
|
||
|
nResult = BreakDownKeyString(argv[2], pAppVars);
|
||
|
if(nResult != ERROR_SUCCESS)
|
||
|
return nResult;
|
||
|
|
||
|
// parsing
|
||
|
for(i=3; i<argc; i++)
|
||
|
{
|
||
|
if(!_tcsicmp(argv[i], _T("/v")))
|
||
|
{
|
||
|
if(pAppVars->szValueName || pAppVars->bRecurseSubKeys)
|
||
|
return REG_STATUS_INVALIDPARAMS;
|
||
|
|
||
|
i++;
|
||
|
if(i<argc)
|
||
|
{
|
||
|
pAppVars->szValueName = (TCHAR*) calloc(_tcslen(argv[i]) + 1,
|
||
|
sizeof(TCHAR));
|
||
|
if (!pAppVars->szValueName) {
|
||
|
return ERROR_NOT_ENOUGH_MEMORY;
|
||
|
}
|
||
|
_tcscpy(pAppVars->szValueName, argv[i]);
|
||
|
}
|
||
|
else
|
||
|
return REG_STATUS_TOFEWPARAMS;
|
||
|
}
|
||
|
else if(!_tcsicmp(argv[i], _T("/ve")))
|
||
|
{
|
||
|
if(pAppVars->szValueName || pAppVars->bRecurseSubKeys)
|
||
|
return REG_STATUS_INVALIDPARAMS;
|
||
|
|
||
|
pAppVars->szValueName = (TCHAR*) calloc(1, sizeof(TCHAR));
|
||
|
if (!pAppVars->szValueName) {
|
||
|
return ERROR_NOT_ENOUGH_MEMORY;
|
||
|
}
|
||
|
}
|
||
|
else if(!_tcsicmp(argv[i], _T("/s")))
|
||
|
{
|
||
|
if(pAppVars->szValueName)
|
||
|
return REG_STATUS_INVALIDPARAMS;
|
||
|
|
||
|
pAppVars->bRecurseSubKeys = TRUE;
|
||
|
}
|
||
|
else
|
||
|
return REG_STATUS_INVALIDPARAMS;
|
||
|
}
|
||
|
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------//
|
||
|
//
|
||
|
// GetTypeStr()
|
||
|
//
|
||
|
//-----------------------------------------------------------------------//
|
||
|
|
||
|
void GetTypeStrFromType(TCHAR *szTypeStr, DWORD dwType)
|
||
|
{
|
||
|
switch (dwType)
|
||
|
{
|
||
|
case REG_BINARY:
|
||
|
_tcscpy(szTypeStr, STR_REG_BINARY);
|
||
|
break;
|
||
|
|
||
|
case REG_DWORD:
|
||
|
_tcscpy(szTypeStr, STR_REG_DWORD);
|
||
|
break;
|
||
|
|
||
|
case REG_DWORD_BIG_ENDIAN:
|
||
|
_tcscpy(szTypeStr, STR_REG_DWORD_BIG_ENDIAN);
|
||
|
break;
|
||
|
|
||
|
case REG_EXPAND_SZ:
|
||
|
_tcscpy(szTypeStr, STR_REG_EXPAND_SZ);
|
||
|
break;
|
||
|
|
||
|
case REG_LINK:
|
||
|
_tcscpy(szTypeStr, STR_REG_LINK);
|
||
|
break;
|
||
|
|
||
|
case REG_MULTI_SZ:
|
||
|
_tcscpy(szTypeStr, STR_REG_MULTI_SZ);
|
||
|
break;
|
||
|
|
||
|
case REG_NONE:
|
||
|
_tcscpy(szTypeStr, STR_REG_NONE);
|
||
|
break;
|
||
|
|
||
|
case REG_RESOURCE_LIST:
|
||
|
_tcscpy(szTypeStr, STR_REG_RESOURCE_LIST);
|
||
|
break;
|
||
|
|
||
|
case REG_SZ:
|
||
|
_tcscpy(szTypeStr, STR_REG_SZ);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
_tcscpy(szTypeStr, STR_REG_NONE);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------//
|
||
|
//
|
||
|
// QueryValue()
|
||
|
//
|
||
|
//-----------------------------------------------------------------------//
|
||
|
|
||
|
LONG QueryValue(HKEY hKey, TCHAR* szValueName)
|
||
|
{
|
||
|
|
||
|
LONG nResult;
|
||
|
TCHAR szTypeStr[25];
|
||
|
DWORD dwType;
|
||
|
DWORD dwSize = 1;
|
||
|
UINT i;
|
||
|
BYTE* pBuff;
|
||
|
TCHAR szEmptyString[ 2 ] = L"";
|
||
|
|
||
|
if ( szValueName == NULL )
|
||
|
{
|
||
|
szValueName = szEmptyString;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// First find out how much memory to allocate.
|
||
|
//
|
||
|
nResult = RegQueryValueEx(hKey,
|
||
|
szValueName,
|
||
|
0,
|
||
|
&dwType,
|
||
|
NULL,
|
||
|
&dwSize);
|
||
|
|
||
|
if (nResult != ERROR_SUCCESS)
|
||
|
{
|
||
|
return nResult;
|
||
|
}
|
||
|
|
||
|
// to avoid problems with corrupted registry data --
|
||
|
// always allocate memory of even no. of bytes
|
||
|
dwSize += ( dwSize % 2 );
|
||
|
|
||
|
pBuff = (BYTE*) calloc(dwSize + 2, sizeof(BYTE));
|
||
|
if (!pBuff) {
|
||
|
return ERROR_NOT_ENOUGH_MEMORY;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Now get the data
|
||
|
//
|
||
|
nResult = RegQueryValueEx(hKey,
|
||
|
szValueName,
|
||
|
0,
|
||
|
&dwType,
|
||
|
(LPBYTE) pBuff,
|
||
|
&dwSize);
|
||
|
|
||
|
|
||
|
if (nResult != ERROR_SUCCESS)
|
||
|
{
|
||
|
free(pBuff);
|
||
|
return nResult;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Now list the ValueName\tType\tData
|
||
|
//
|
||
|
GetTypeStrFromType(szTypeStr, dwType);
|
||
|
|
||
|
MyTPrintf(stdout,
|
||
|
_T(" %s\t%s\t"),
|
||
|
(_tcslen(szValueName) == 0) // no name
|
||
|
? g_NoName
|
||
|
: szValueName,
|
||
|
szTypeStr);
|
||
|
|
||
|
switch (dwType)
|
||
|
{
|
||
|
default:
|
||
|
case REG_BINARY:
|
||
|
for(i=0; i<dwSize; i++)
|
||
|
{
|
||
|
MyTPrintf(stdout,_T("%02X"),pBuff[i]);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case REG_SZ:
|
||
|
case REG_EXPAND_SZ:
|
||
|
MyTPrintf(stdout,_T("%s"), (LPCWSTR)pBuff );
|
||
|
break;
|
||
|
|
||
|
case REG_DWORD:
|
||
|
case REG_DWORD_BIG_ENDIAN:
|
||
|
MyTPrintf(stdout,_T("0x%x"), *((DWORD*)pBuff) );
|
||
|
break;
|
||
|
|
||
|
case REG_MULTI_SZ:
|
||
|
{
|
||
|
//
|
||
|
// Replace '\0' with "\0" for MULTI_SZ
|
||
|
//
|
||
|
TCHAR* pEnd = (TCHAR*) pBuff;
|
||
|
while( (BYTE*)pEnd < pBuff + dwSize )
|
||
|
{
|
||
|
if(*pEnd == 0)
|
||
|
{
|
||
|
MyTPrintf(stdout,_T("\\0"));
|
||
|
pEnd++;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
MyTPrintf(stdout,_T("%s"), pEnd);
|
||
|
pEnd += _tcslen(pEnd);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
MyTPrintf(stdout,_T("\r\n"));
|
||
|
|
||
|
if(pBuff)
|
||
|
free(pBuff);
|
||
|
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------//
|
||
|
//
|
||
|
// EnumerateKey() - Recursive
|
||
|
//
|
||
|
//-----------------------------------------------------------------------//
|
||
|
|
||
|
LONG QueryEnumerateKey(HKEY hKey,
|
||
|
TCHAR* szFullKey,
|
||
|
BOOL bRecurseSubKeys)
|
||
|
{
|
||
|
DWORD nResult;
|
||
|
UINT i;
|
||
|
DWORD dwSize;
|
||
|
HKEY hSubKey;
|
||
|
TCHAR* szNameBuf;
|
||
|
TCHAR* szTempName;
|
||
|
|
||
|
// query source key info
|
||
|
DWORD dwLenOfKeyName;
|
||
|
DWORD dwLenOfValueName;
|
||
|
nResult = RegQueryInfoKey(hKey,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
&dwLenOfKeyName,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
&dwLenOfValueName,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL);
|
||
|
|
||
|
if (nResult != ERROR_SUCCESS)
|
||
|
{
|
||
|
return nResult;
|
||
|
}
|
||
|
|
||
|
#ifndef REG_FOR_WIN2000 // ansi version for win98
|
||
|
// fix API bugs: RegQueryInfoKey() returns non-correct length values
|
||
|
// on remote Win98
|
||
|
if(dwLenOfKeyName < MAX_PATH)
|
||
|
dwLenOfKeyName = MAX_PATH;
|
||
|
if(dwLenOfValueName < MAX_PATH)
|
||
|
dwLenOfValueName = MAX_PATH;
|
||
|
#endif
|
||
|
|
||
|
// create buffer
|
||
|
dwLenOfValueName++;
|
||
|
szNameBuf = (TCHAR*) calloc(dwLenOfValueName, sizeof(TCHAR));
|
||
|
if (!szNameBuf) {
|
||
|
return ERROR_NOT_ENOUGH_MEMORY;
|
||
|
}
|
||
|
|
||
|
// first print the key name
|
||
|
MyTPrintf(stdout,_T("\r\n%s\r\n"), szFullKey);
|
||
|
|
||
|
//
|
||
|
// enumerate all of the values
|
||
|
//
|
||
|
i = 0;
|
||
|
do
|
||
|
{
|
||
|
dwSize = dwLenOfValueName;
|
||
|
nResult = RegEnumValue(hKey,
|
||
|
i,
|
||
|
szNameBuf,
|
||
|
&dwSize,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL);
|
||
|
|
||
|
if (nResult == ERROR_SUCCESS)
|
||
|
{
|
||
|
nResult = QueryValue(hKey, szNameBuf);
|
||
|
|
||
|
// continue to query
|
||
|
if(nResult == ERROR_ACCESS_DENIED)
|
||
|
{
|
||
|
MyTPrintf(stderr,
|
||
|
_T("Error: Access is denied in the value %s under")
|
||
|
_T(" the key %s\r\n"),
|
||
|
szNameBuf,
|
||
|
szFullKey);
|
||
|
nResult = ERROR_SUCCESS;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
i++;
|
||
|
|
||
|
} while (nResult == ERROR_SUCCESS);
|
||
|
|
||
|
|
||
|
if(szNameBuf)
|
||
|
free(szNameBuf);
|
||
|
|
||
|
if (nResult == ERROR_NO_MORE_ITEMS)
|
||
|
nResult = ERROR_SUCCESS;
|
||
|
|
||
|
if( nResult != ERROR_SUCCESS )
|
||
|
return nResult;
|
||
|
|
||
|
//
|
||
|
// 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 ( dwLenOfKeyName == 0 )
|
||
|
{
|
||
|
dwLenOfKeyName = 256;
|
||
|
}
|
||
|
else if ( dwLenOfKeyName < 256 )
|
||
|
{
|
||
|
// always assume 100% more length than what is returned by API
|
||
|
dwLenOfKeyName *= 2;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Now Enumerate all of the keys
|
||
|
//
|
||
|
dwLenOfKeyName++;
|
||
|
szNameBuf = (TCHAR*) calloc(dwLenOfKeyName, sizeof(TCHAR));
|
||
|
if (!szNameBuf) {
|
||
|
return ERROR_NOT_ENOUGH_MEMORY;
|
||
|
}
|
||
|
i = 0;
|
||
|
do
|
||
|
{
|
||
|
dwSize = dwLenOfKeyName;
|
||
|
nResult = RegEnumKeyEx(hKey,
|
||
|
i,
|
||
|
szNameBuf,
|
||
|
&dwSize,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL);
|
||
|
|
||
|
if (nResult != ERROR_SUCCESS)
|
||
|
break;
|
||
|
|
||
|
//
|
||
|
// open up the subkey, and enumerate it
|
||
|
//
|
||
|
nResult = RegOpenKeyEx(hKey,
|
||
|
szNameBuf,
|
||
|
0,
|
||
|
KEY_READ,
|
||
|
&hSubKey);
|
||
|
|
||
|
//
|
||
|
// Build up the needed string and go down enumerating again
|
||
|
//
|
||
|
szTempName = (TCHAR*) calloc(_tcslen(szFullKey) +
|
||
|
_tcslen(szNameBuf) +
|
||
|
2,
|
||
|
sizeof(TCHAR));
|
||
|
if (!szTempName) {
|
||
|
nResult = ERROR_NOT_ENOUGH_MEMORY;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
_tcscpy(szTempName, szFullKey);
|
||
|
_tcscat(szTempName, _T("\\"));
|
||
|
_tcscat(szTempName, szNameBuf);
|
||
|
|
||
|
|
||
|
if (bRecurseSubKeys && nResult == ERROR_SUCCESS)
|
||
|
{
|
||
|
// recursive query
|
||
|
nResult = QueryEnumerateKey(hSubKey,
|
||
|
szTempName,
|
||
|
bRecurseSubKeys);
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// print key
|
||
|
MyTPrintf(stdout,_T("\r\n%s\r\n"), szTempName);
|
||
|
|
||
|
if(nResult == ERROR_ACCESS_DENIED) // continue to query next key
|
||
|
{
|
||
|
MyTPrintf(stderr,
|
||
|
_T("Error: Access is denied in the key %s\r\n"),
|
||
|
szTempName);
|
||
|
nResult = ERROR_SUCCESS;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
RegCloseKey(hSubKey);
|
||
|
if(szTempName)
|
||
|
free(szTempName);
|
||
|
|
||
|
|
||
|
i++;
|
||
|
|
||
|
} while (nResult == ERROR_SUCCESS);
|
||
|
|
||
|
Cleanup:
|
||
|
if(szNameBuf)
|
||
|
free(szNameBuf);
|
||
|
|
||
|
if (nResult == ERROR_NO_MORE_ITEMS)
|
||
|
nResult = ERROR_SUCCESS;
|
||
|
|
||
|
return nResult;
|
||
|
}
|
||
|
|