windows-nt/Source/XPSP1/NT/base/fs/utils/reg/query.c
2020-09-26 16:20:57 +08:00

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;
}