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.
541 lines
13 KiB
541 lines
13 KiB
/*
|
|
File: regprint.c
|
|
|
|
'ras diag' sub context
|
|
|
|
08/21/01
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
|
|
//
|
|
// const's only used in this obj
|
|
//
|
|
static CONST WCHAR g_wszLParen = L'(';
|
|
static CONST WCHAR g_wszRParen = L')';
|
|
static CONST WCHAR g_wszAmp = L'@';
|
|
static CONST WCHAR g_wszEqual = L'=';
|
|
static CONST WCHAR g_wszQuote = L'\"';
|
|
static CONST WCHAR g_wszColon = L':';
|
|
static CONST WCHAR g_wszComma = L',';
|
|
static CONST WCHAR g_wszZero = L'0';
|
|
static CONST WCHAR g_pwszDword[] = L"dword:";
|
|
static CONST WCHAR g_pwszHex[] = L"hex";
|
|
static CONST WCHAR g_HexConversion[16] = {L'0', L'1', L'2', L'3', L'4', L'5',
|
|
L'6', L'7', L'8', L'9', L'a', L'b',
|
|
L'c', L'd', L'e', L'f'};
|
|
|
|
static CONST REGISTRYROOT g_RegRoots[] =
|
|
{
|
|
L"HKEY_ROOT", 9, HKEY_ROOT,
|
|
L"HKEY_LOCAL_MACHINE", 18, HKEY_LOCAL_MACHINE,
|
|
L"HKEY_USERS", 10, HKEY_USERS,
|
|
L"HKEY_CURRENT_USER", 17, HKEY_CURRENT_USER,
|
|
L"HKEY_CURRENT_CONFIG", 19, HKEY_CURRENT_CONFIG,
|
|
L"HKEY_CLASSES_ROOT", 17, HKEY_CLASSES_ROOT,
|
|
L"HKEY_DYN_DATA", 13, HKEY_DYN_DATA,
|
|
};
|
|
|
|
static CONST UINT g_ulNumRegRoots = sizeof(g_RegRoots) / sizeof(REGISTRYROOT);
|
|
|
|
static CONST PWCHAR g_pwszRegKeys[] =
|
|
{
|
|
RASREGCHK01, RASREGCHK02, RASREGCHK03, RASREGCHK04, RASREGCHK05,
|
|
RASREGCHK06, RASREGCHK07, RASREGCHK08, RASREGCHK09, RASREGCHK10,
|
|
RASREGCHK11, RASREGCHK12, RASREGCHK13, RASREGCHK14, RASREGCHK15,
|
|
RASREGCHK16, RASREGCHK17, RASREGCHK18, RASREGCHK19, RASREGCHK20,
|
|
RASREGCHK21, RASREGCHK22, RASREGCHK23, RASREGCHK24, RASREGCHK25,
|
|
RASREGCHK26, RASREGCHK27, RASREGCHK28, RASREGCHK29, RASREGCHK30,
|
|
RASREGCHK31, RASREGCHK32, RASREGCHK33, RASREGCHK34, RASREGCHK35,
|
|
RASREGCHK36, RASREGCHK37, RASREGCHK38, RASREGCHK39, RASREGCHK40,
|
|
RASREGCHK41, RASREGCHK42, RASREGCHK43, RASREGCHK44, RASREGCHK45,
|
|
RASREGCHK46
|
|
};
|
|
|
|
static CONST UINT g_ulNumRegKeys = sizeof(g_pwszRegKeys) / sizeof(PWCHAR);
|
|
|
|
//
|
|
// This count is used to control how many places over to the right that we
|
|
// print before going to the next line
|
|
//
|
|
UINT g_ulCharCount = 0;
|
|
|
|
BOOL
|
|
RegPrintSubtree(
|
|
IN BUFFER_WRITE_FILE* pBuff,
|
|
IN LPCWSTR pwszFullKeyName);
|
|
|
|
HKEY
|
|
ConvertRootStringToKey(
|
|
IN CONST PWCHAR pwszFullKeyName);
|
|
|
|
DWORD
|
|
PutBranch(
|
|
IN BUFFER_WRITE_FILE* pBuff,
|
|
IN HKEY hKey,
|
|
IN LPCWSTR pwszFullKeyName);
|
|
|
|
VOID
|
|
PutString(
|
|
IN BUFFER_WRITE_FILE* pBuff,
|
|
IN PWCHAR pwszString);
|
|
|
|
VOID
|
|
PutDword(
|
|
IN BUFFER_WRITE_FILE* pBuff,
|
|
IN DWORD Dword,
|
|
IN BOOL fLeadingZeroes);
|
|
|
|
VOID
|
|
PutBinary(
|
|
IN BUFFER_WRITE_FILE* pBuff,
|
|
IN CONST BYTE FAR* lpBuffer,
|
|
IN DWORD Type,
|
|
IN DWORD cbBytes);
|
|
|
|
VOID
|
|
PrintRasRegistryKeys(
|
|
IN BUFFER_WRITE_FILE* pBuff)
|
|
{
|
|
UINT i;
|
|
BOOL bAtleastOneFail = FALSE;
|
|
LPBYTE pFailed = NULL;
|
|
|
|
do
|
|
{
|
|
pFailed = RutlAlloc(g_ulNumRegKeys * sizeof(BYTE), TRUE);
|
|
if (!pFailed)
|
|
{
|
|
break;
|
|
}
|
|
|
|
for (i = 0; i < g_ulNumRegKeys; i++)
|
|
{
|
|
if (RegPrintSubtree(pBuff, g_pwszRegKeys[i]))
|
|
{
|
|
pFailed[i] = TRUE;
|
|
bAtleastOneFail = TRUE;
|
|
}
|
|
}
|
|
//
|
|
// Print all failures at the end
|
|
//
|
|
if (bAtleastOneFail)
|
|
{
|
|
BufferWriteMessage(
|
|
pBuff,
|
|
g_hModule,
|
|
MSG_RASDIAG_SHOW_RASCHK_REG_NOT_FOUND);
|
|
|
|
for (i = 0; i < g_ulNumRegKeys; i++)
|
|
{
|
|
if (pFailed[i])
|
|
{
|
|
BufferWriteFileStrW(pBuff, g_pwszRegKeys[i]);
|
|
WriteNewLine(pBuff);
|
|
}
|
|
}
|
|
}
|
|
|
|
} while (FALSE);
|
|
//
|
|
// Clean up
|
|
//
|
|
RutlFree(pFailed);
|
|
|
|
return;
|
|
}
|
|
|
|
BOOL
|
|
RegPrintSubtree(
|
|
IN BUFFER_WRITE_FILE* pBuff,
|
|
IN LPCWSTR pwszFullKeyName)
|
|
{
|
|
HKEY hKey = NULL;
|
|
BOOL bReturn = TRUE;
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
|
|
do
|
|
{
|
|
hKey = ConvertRootStringToKey((PWCHAR)pwszFullKeyName);
|
|
if (!hKey)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (PutBranch(pBuff, hKey, pwszFullKeyName))
|
|
{
|
|
break;
|
|
}
|
|
//
|
|
// Success
|
|
//
|
|
bReturn = FALSE;
|
|
|
|
} while (FALSE);
|
|
//
|
|
// Clean up
|
|
//
|
|
if (hKey)
|
|
{
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
HKEY
|
|
ConvertRootStringToKey(
|
|
IN CONST PWCHAR pwszFullKeyName)
|
|
{
|
|
HKEY hKey = NULL;
|
|
UINT i;
|
|
PWCHAR pwszKey = NULL;
|
|
|
|
for (i = 0; i < g_ulNumRegRoots; i++)
|
|
{
|
|
if (RutlStrNCmp(
|
|
pwszFullKeyName,
|
|
g_RegRoots[i].RootText,
|
|
g_RegRoots[i].TextLength))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (pwszFullKeyName[g_RegRoots[i].TextLength] != g_pwszBackSlash)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
pwszKey = pwszFullKeyName + g_RegRoots[i].TextLength + 1;
|
|
|
|
if (RegOpenKeyEx(
|
|
g_RegRoots[i].RootKey,
|
|
pwszKey,
|
|
0,
|
|
KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
|
|
&hKey)
|
|
)
|
|
{
|
|
hKey = NULL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return hKey;
|
|
}
|
|
|
|
DWORD
|
|
PutBranch(
|
|
IN BUFFER_WRITE_FILE* pBuff,
|
|
IN HKEY hKey,
|
|
IN LPCWSTR pwszFullKeyName)
|
|
{
|
|
HKEY hSubKey = NULL;
|
|
DWORD dwErr = NO_ERROR;
|
|
UINT ulLenFullKey = 0;
|
|
PBYTE pbValueData = NULL;
|
|
DWORD EnumIndex = 0, cchValueName = 0, cbValueData = 0, Type = 0;
|
|
WCHAR szValueNameBuffer[MAX_PATH];
|
|
LPTSTR lpSubKeyName = NULL, lpTempFullKeyName = NULL;
|
|
|
|
do
|
|
{
|
|
//
|
|
// Write out the section header.
|
|
//
|
|
BufferWriteFileCharW(pBuff, g_pwszLBracket);
|
|
BufferWriteFileStrW(pBuff, pwszFullKeyName);
|
|
BufferWriteFileCharW(pBuff, g_pwszRBracket);
|
|
WriteNewLine(pBuff);
|
|
//
|
|
// Write out all of the value names and their data.
|
|
//
|
|
for (;;)
|
|
{
|
|
cchValueName = ARRAYSIZE(szValueNameBuffer);
|
|
//
|
|
// VALUE DATA
|
|
// Query for data size
|
|
//
|
|
dwErr = RegEnumValue(
|
|
hKey,
|
|
EnumIndex++,
|
|
szValueNameBuffer,
|
|
&cchValueName,
|
|
NULL,
|
|
&Type,
|
|
NULL,
|
|
&cbValueData);
|
|
BREAK_ON_DWERR(dwErr);
|
|
//
|
|
// allocate memory for data
|
|
//
|
|
pbValueData = LocalAlloc(LPTR, cbValueData + ExtraAllocLen(Type));
|
|
if (!pbValueData)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
dwErr = RegQueryValueEx(
|
|
hKey,
|
|
szValueNameBuffer,
|
|
NULL,
|
|
&Type,
|
|
pbValueData,
|
|
&cbValueData);
|
|
BREAK_ON_DWERR(dwErr);
|
|
//
|
|
// If cbValueName is zero, then this is the default value of
|
|
// the key, or the Windows 3.1 compatible key value.
|
|
//
|
|
g_ulCharCount = 0;
|
|
|
|
if (cchValueName)
|
|
{
|
|
PutString(pBuff, szValueNameBuffer);
|
|
}
|
|
else
|
|
{
|
|
BufferWriteFileCharW(pBuff, g_wszAmp);
|
|
g_ulCharCount = 1;
|
|
}
|
|
|
|
BufferWriteFileCharW(pBuff, g_wszEqual);
|
|
g_ulCharCount++;
|
|
|
|
switch (Type)
|
|
{
|
|
case REG_SZ:
|
|
PutString(pBuff, (PWCHAR)pbValueData);
|
|
break;
|
|
|
|
case REG_DWORD:
|
|
if (cbValueData == sizeof(DWORD))
|
|
{
|
|
BufferWriteFileStrW(pBuff, g_pwszDword);
|
|
PutDword(pBuff, *((LPDWORD) pbValueData), TRUE);
|
|
break;
|
|
}
|
|
//
|
|
// FALL THROUGH
|
|
//
|
|
case REG_BINARY:
|
|
default:
|
|
PutBinary(pBuff, (LPBYTE) pbValueData, Type, cbValueData);
|
|
break;
|
|
}
|
|
|
|
WriteNewLine(pBuff);
|
|
|
|
LocalFree(pbValueData);
|
|
pbValueData = NULL;
|
|
}
|
|
|
|
WriteNewLine(pBuff);
|
|
|
|
if (dwErr == ERROR_NO_MORE_ITEMS)
|
|
{
|
|
dwErr = NO_ERROR;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
//
|
|
// Write out all of the subkeys and recurse into them.
|
|
//
|
|
// copy the existing key into a new buffer with enough room for the next key
|
|
//
|
|
ulLenFullKey = lstrlen(pwszFullKeyName);
|
|
|
|
lpTempFullKeyName = LocalAlloc(
|
|
LPTR,
|
|
(ulLenFullKey + MAX_PATH) * sizeof(WCHAR));
|
|
if (!lpTempFullKeyName)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
lstrcpy(lpTempFullKeyName, pwszFullKeyName);
|
|
lpSubKeyName = lpTempFullKeyName + ulLenFullKey;
|
|
*lpSubKeyName++ = g_pwszBackSlash;
|
|
*lpSubKeyName = 0;
|
|
|
|
EnumIndex = 0;
|
|
|
|
for (;;)
|
|
{
|
|
dwErr = RegEnumKey(hKey, EnumIndex++, lpSubKeyName, MAX_PATH - 1);
|
|
BREAK_ON_DWERR(dwErr);
|
|
|
|
dwErr = RegOpenKeyEx(
|
|
hKey,
|
|
lpSubKeyName,
|
|
0,
|
|
KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
|
|
&hSubKey);
|
|
BREAK_ON_DWERR(dwErr);
|
|
|
|
dwErr = PutBranch(pBuff, hSubKey, lpTempFullKeyName);
|
|
BREAK_ON_DWERR(dwErr);
|
|
|
|
RegCloseKey(hSubKey);
|
|
hSubKey = NULL;
|
|
}
|
|
|
|
if (dwErr == ERROR_NO_MORE_ITEMS)
|
|
{
|
|
dwErr = NO_ERROR;
|
|
}
|
|
|
|
} while (FALSE);
|
|
//
|
|
// Clean up
|
|
//
|
|
if (hSubKey)
|
|
{
|
|
RegCloseKey(hSubKey);
|
|
hSubKey = NULL;
|
|
}
|
|
if (lpTempFullKeyName)
|
|
{
|
|
LocalFree(lpTempFullKeyName);
|
|
lpTempFullKeyName = NULL;
|
|
}
|
|
if (pbValueData)
|
|
{
|
|
LocalFree(pbValueData);
|
|
pbValueData = NULL;
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
VOID
|
|
PutString(
|
|
IN BUFFER_WRITE_FILE* pBuff,
|
|
IN PWCHAR pwszString)
|
|
{
|
|
WCHAR Char;
|
|
|
|
BufferWriteFileCharW(pBuff, g_wszQuote);
|
|
g_ulCharCount++;
|
|
|
|
while ((Char = *pwszString++) != 0)
|
|
{
|
|
switch (Char)
|
|
{
|
|
case L'\\':
|
|
case L'"':
|
|
BufferWriteFileCharW(pBuff, g_pwszBackSlash);
|
|
g_ulCharCount++;
|
|
//
|
|
// FALL THROUGH
|
|
//
|
|
default:
|
|
BufferWriteFileCharW(pBuff, Char);
|
|
g_ulCharCount++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
BufferWriteFileCharW(pBuff, g_wszQuote);
|
|
g_ulCharCount++;
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
PutDword(
|
|
IN BUFFER_WRITE_FILE* pBuff,
|
|
IN DWORD Dword,
|
|
IN BOOL fLeadingZeroes)
|
|
{
|
|
INT CurrentNibble;
|
|
BOOL fWroteNonleadingChar = fLeadingZeroes;
|
|
WCHAR Char;
|
|
|
|
for (CurrentNibble = 7; CurrentNibble >= 0; CurrentNibble--)
|
|
{
|
|
Char = g_HexConversion[(Dword >> (CurrentNibble * 4)) & 0x0F];
|
|
|
|
if (fWroteNonleadingChar || Char != g_wszZero)
|
|
{
|
|
BufferWriteFileCharW(pBuff, Char);
|
|
g_ulCharCount++;
|
|
fWroteNonleadingChar = TRUE;
|
|
}
|
|
}
|
|
//
|
|
// We need to write at least one character, so if we haven't written
|
|
// anything yet, just spit out one zero.
|
|
//
|
|
if (!fWroteNonleadingChar)
|
|
{
|
|
BufferWriteFileCharW(pBuff, g_wszZero);
|
|
g_ulCharCount++;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
PutBinary(
|
|
IN BUFFER_WRITE_FILE* pBuff,
|
|
IN CONST BYTE FAR* lpBuffer,
|
|
IN DWORD Type,
|
|
IN DWORD cbBytes)
|
|
{
|
|
BOOL fFirstByteOnLine;
|
|
BYTE Byte;
|
|
|
|
BufferWriteFileStrW(pBuff, g_pwszHex);
|
|
g_ulCharCount += 3;
|
|
|
|
if (Type != REG_BINARY)
|
|
{
|
|
BufferWriteFileCharW(pBuff, g_wszLParen);
|
|
PutDword(pBuff, Type, FALSE);
|
|
BufferWriteFileCharW(pBuff, g_wszRParen);
|
|
g_ulCharCount += 2;
|
|
}
|
|
|
|
BufferWriteFileCharW(pBuff, g_wszColon);
|
|
g_ulCharCount++;
|
|
|
|
fFirstByteOnLine = TRUE;
|
|
|
|
while (cbBytes--)
|
|
{
|
|
if (g_ulCharCount > 75 && !fFirstByteOnLine)
|
|
{
|
|
BufferWriteFileCharW(pBuff, g_wszComma);
|
|
BufferWriteFileCharW(pBuff, g_pwszBackSlash);
|
|
WriteNewLine(pBuff);
|
|
BufferWriteFileStrW(pBuff, g_pwszSpace);
|
|
BufferWriteFileStrW(pBuff, g_pwszSpace);
|
|
fFirstByteOnLine = TRUE;
|
|
g_ulCharCount = 3;
|
|
}
|
|
|
|
if (!fFirstByteOnLine)
|
|
{
|
|
BufferWriteFileCharW(pBuff, g_wszComma);
|
|
g_ulCharCount++;
|
|
}
|
|
|
|
Byte = *lpBuffer++;
|
|
|
|
BufferWriteFileCharW(pBuff, g_HexConversion[Byte >> 4]);
|
|
BufferWriteFileCharW(pBuff, g_HexConversion[Byte & 0x0F]);
|
|
g_ulCharCount += 2;
|
|
|
|
fFirstByteOnLine = FALSE;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|