|
|
/*******************************************************************************
* * (C) COPYRIGHT MICROSOFT CORP., 1993-1994 * * TITLE: REGPRINT.C * * VERSION: 4.0 * * AUTHOR: Tracy Sharpe * * DATE: 21 Nov 1993 * * Print routines for the Registry Editor. * *******************************************************************************/
#include "pch.h"
#include "regprint.h"
#include "regcdhk.h"
#include "regresid.h"
#include "regedit.h"
#include "richedit.h"
#include "regporte.h"
#include "reg1632.h"
#include <malloc.h>
extern void PrintResourceData(PBYTE pbData, UINT uSize, DWORD dwType);
const TCHAR s_PrintLineBreak[] = TEXT(",\n ");
PRINTDLGEX g_PrintDlg;
typedef struct _PRINT_IO { BOOL fContinueJob; UINT ErrorStringID; HWND hRegPrintAbortWnd; RECT rcPage; RECT rcOutput; PTSTR pLineBuffer; UINT cch; UINT cBufferPos; LPTSTR lpNewLineChars; } PRINT_IO;
#define CANCEL_NONE 0x0000
#define CANCEL_MEMORY_ERROR 0x0001
#define CANCEL_PRINTER_ERROR 0x0002
#define CANCEL_ABORT 0x0004
#define INITIAL_PRINTBUFFER_SIZE 8192
PRINT_IO s_PrintIo;
BOOL CALLBACK RegPrintAbortProc( HDC hDC, int Error );
INT_PTR CALLBACK RegPrintAbortDlgProc( HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam );
void RegPrintSubtree(); void PrintBranch(HKEY hKey, LPTSTR lpFullKeyName); void PrintKeyValues(HKEY hKey); void PrintValueData(PBYTE pbValueData, DWORD cbValueData, DWORD dwType); void PrintKeyHeader(HKEY hKey, LPTSTR lpFullKeyName); void PrintClassName(HKEY hKey); void PrintLastWriteTime(HKEY hKey); void PrintDynamicString(UINT uStringID); void PrintType(DWORD dwType); void PrintBinaryData(PBYTE ValueData, UINT cbcbValueData); void PrintDWORDData(PBYTE ValueData, UINT cbcbValueData); void PrintLiteral(PTSTR lpLiteral); BOOL PrintChar(TCHAR Char); void PrintMultiString(LPTSTR pszData, int cbData); UINT PrintToSubTreeError(UINT uPrintErrorStringID); void PrintNewLine();
/*******************************************************************************
* * Implement IPrintDialogCallback * * DESCRIPTION: * This interface is necessary to handle messages through PrintDlgEx * This interface doesn't need to have all the correct semantics of a COM * Object * *******************************************************************************/
typedef struct { IPrintDialogCallback ipcb; } CPrintCallback;
#define IMPL(type, pos, ptr) (type*)
static HRESULT CPrintCallback_QueryInterface(IPrintDialogCallback *ppcb, REFIID riid, void **ppv) { CPrintCallback *this = (CPrintCallback*)ppcb; if (IsEqualIID (riid, &IID_IUnknown) || IsEqualIID (riid, &IID_IPrintDialogCallback)) *ppv = &this->ipcb; else { *ppv = 0; return E_NOINTERFACE; }
this->ipcb.lpVtbl->AddRef(&this->ipcb); return NOERROR; }
static ULONG CPrintCallback_AddRef(IPrintDialogCallback *ppcb) { CPrintCallback *this = (CPrintCallback*)ppcb; return 1; }
static ULONG CPrintCallback_Release(IPrintDialogCallback *ppcb) { CPrintCallback *this = (CPrintCallback*)ppcb; return 1; }
static HRESULT CPrintCallback_InitDone(IPrintDialogCallback *ppcb) { return S_OK; }
static HRESULT CPrintCallback_SelectionChange(IPrintDialogCallback *ppcb) { return S_OK; }
static HRESULT CPrintCallback_HandleMessage( IPrintDialogCallback *ppcb, HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *pResult) { *pResult = RegCommDlgHookProc(hDlg, uMsg, wParam, lParam); return S_OK; }
static IPrintDialogCallbackVtbl vtblPCB = { CPrintCallback_QueryInterface, CPrintCallback_AddRef, CPrintCallback_Release, CPrintCallback_InitDone, CPrintCallback_SelectionChange, CPrintCallback_HandleMessage };
CPrintCallback g_callback;
/*******************************************************************************
* * RegEdit_OnCommandPrint * * DESCRIPTION: * Handles the selection of the "Print" option by the user for the RegEdit * dialog box. * * PARAMETERS: * hWnd, handle of RegPrint window. * *******************************************************************************/
VOID PASCAL RegEdit_OnCommandPrint( HWND hWnd ) {
LPDEVNAMES lpDevNames; TEXTMETRIC TextMetric; DOCINFO DocInfo; LOGFONT lf; HGLOBAL hDevMode; HGLOBAL hDevNames; RECT rc; HWND hRichEdit; FORMATRANGE fr; HINSTANCE hInstRichEdit; int nOffsetX; int nOffsetY; PTSTR pszFontName;
g_callback.ipcb.lpVtbl = &vtblPCB;
// We have to completely fill out the PRINTDLGEX structure
// correctly or the PrintDlgEx function will return an error.
// The easiest way is to memset it to 0
hDevMode = g_PrintDlg.hDevMode; hDevNames = g_PrintDlg.hDevNames; memset(&g_PrintDlg, 0, sizeof(g_PrintDlg));
g_PrintDlg.lStructSize = sizeof(PRINTDLGEX); g_PrintDlg.hwndOwner = hWnd; g_PrintDlg.hDevMode = hDevMode; g_PrintDlg.hDevNames = hDevNames; g_PrintDlg.hDC = NULL; g_PrintDlg.Flags = PD_NOPAGENUMS | PD_RETURNDC | PD_ENABLEPRINTTEMPLATE; g_PrintDlg.Flags2 = 0; g_PrintDlg.ExclusionFlags = 0; g_PrintDlg.hInstance = g_hInstance; g_PrintDlg.nCopies = 1; g_PrintDlg.nStartPage = START_PAGE_GENERAL; g_PrintDlg.lpCallback = (IUnknown*) &g_callback.ipcb; g_PrintDlg.lpPrintTemplateName = MAKEINTRESOURCE(IDD_REGPRINT); g_RegCommDlgDialogTemplate = IDD_REGPRINT;
if (FAILED(PrintDlgEx(&g_PrintDlg))) return; if (g_PrintDlg.dwResultAction != PD_RESULT_PRINT) return;
s_PrintIo.ErrorStringID = IDS_PRINTERRNOMEMORY;
if ((lpDevNames = GlobalLock(g_PrintDlg.hDevNames)) == NULL) goto error_ShowDialog;
//
// For now, assume a page with top and bottom margins of 1/2 inch and
// left and right margins of 3/4 inch (the defaults of Notepad).
// rcPage and rcOutput are in TWIPS (1/20th of a point)
//
rc.left = rc.top = 0; rc.bottom = GetDeviceCaps(g_PrintDlg.hDC, PHYSICALHEIGHT); rc.right = GetDeviceCaps(g_PrintDlg.hDC, PHYSICALWIDTH); nOffsetX = GetDeviceCaps(g_PrintDlg.hDC, PHYSICALOFFSETX); nOffsetY = GetDeviceCaps(g_PrintDlg.hDC, PHYSICALOFFSETY);
s_PrintIo.rcPage.left = s_PrintIo.rcPage.top = 0; s_PrintIo.rcPage.right = MulDiv(rc.right, 1440, GetDeviceCaps(g_PrintDlg.hDC, LOGPIXELSX)); s_PrintIo.rcPage.bottom = MulDiv(rc.bottom, 1440, GetDeviceCaps(g_PrintDlg.hDC, LOGPIXELSY));
s_PrintIo.rcOutput.left = 1080; s_PrintIo.rcOutput.top = 720; s_PrintIo.rcOutput.right = s_PrintIo.rcPage.right - 1080; s_PrintIo.rcOutput.bottom = s_PrintIo.rcPage.bottom - 720;
//
//
//
if ((s_PrintIo.pLineBuffer = (PTSTR) LocalAlloc(LPTR, INITIAL_PRINTBUFFER_SIZE*sizeof(TCHAR))) == NULL) goto error_DeleteDC; s_PrintIo.cch = INITIAL_PRINTBUFFER_SIZE; s_PrintIo.cBufferPos = 0;
if ((s_PrintIo.hRegPrintAbortWnd = CreateDialog(g_hInstance, MAKEINTRESOURCE(IDD_REGPRINTABORT), hWnd, RegPrintAbortDlgProc)) == NULL) goto error_FreeLineBuffer;
EnableWindow(hWnd, FALSE);
//
// Prepare the document for printing.
//
s_PrintIo.ErrorStringID = 0; s_PrintIo.fContinueJob = TRUE; s_PrintIo.lpNewLineChars = TEXT("\n"); SetAbortProc(g_PrintDlg.hDC, RegPrintAbortProc);
DocInfo.cbSize = sizeof(DOCINFO); DocInfo.lpszDocName = LoadDynamicString(IDS_REGEDIT); DocInfo.lpszOutput = (LPTSTR) lpDevNames + lpDevNames-> wOutputOffset; DocInfo.lpszDatatype = NULL; DocInfo.fwType = 0;
s_PrintIo.ErrorStringID = 0;
if (StartDoc(g_PrintDlg.hDC, &DocInfo) <= 0) {
if (GetLastError() != ERROR_PRINT_CANCELLED) s_PrintIo.ErrorStringID = IDS_PRINTERRPRINTER; goto error_DeleteDocName;
}
// Print registry subtree.
RegPrintSubtree();
if (s_PrintIo.ErrorStringID != 0) { InternalMessageBox(g_hInstance, hWnd, MAKEINTRESOURCE(s_PrintIo.ErrorStringID), MAKEINTRESOURCE(IDS_REGEDIT), MB_ICONERROR | MB_OK); }
hInstRichEdit = LoadLibrary(TEXT("riched20.dll"));
hRichEdit = CreateWindowEx(0, RICHEDIT_CLASS, NULL, ES_MULTILINE, 0, 0, 100, 100, NULL, NULL, NULL, NULL); SendMessage(hRichEdit, WM_SETTEXT, 0, (LPARAM)s_PrintIo.pLineBuffer);
pszFontName = LoadDynamicString(IDS_PRINT_FONT); if (pszFontName) { CHARFORMAT cf;
cf.cbSize = sizeof(CHARFORMAT); cf.dwMask = CFM_FACE | CFM_BOLD; cf.dwEffects = 0x00; cf.bPitchAndFamily = FIXED_PITCH | FF_MODERN; wsprintf(cf.szFaceName, TEXT("%s"), pszFontName);
SendMessage(hRichEdit, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf);
DeleteDynamicString(pszFontName); }
fr.hdc = g_PrintDlg.hDC; fr.hdcTarget = g_PrintDlg.hDC; fr.rc = s_PrintIo.rcOutput; fr.rcPage = s_PrintIo.rcPage; fr.chrg.cpMin = 0; fr.chrg.cpMax = -1;
while (fr.chrg.cpMin < (int) s_PrintIo.cBufferPos) { StartPage(g_PrintDlg.hDC);
// We have to adjust the origin because 0,0 is not at the corner of the paper
// but is at the corner of the printable region
SetViewportOrgEx(g_PrintDlg.hDC, -nOffsetX, -nOffsetY, NULL); fr.chrg.cpMin = (LONG)SendMessage(hRichEdit, EM_FORMATRANGE, TRUE, (LPARAM)&fr); SendMessage(hRichEdit, EM_DISPLAYBAND, 0, (LPARAM)&s_PrintIo.rcOutput); EndPage(g_PrintDlg.hDC); if (!s_PrintIo.fContinueJob) break; } SendMessage(hRichEdit, EM_FORMATRANGE, FALSE, 0);
//
// End the print job.
//
if (s_PrintIo.ErrorStringID == 0 && s_PrintIo.fContinueJob) {
if (EndDoc(g_PrintDlg.hDC) <= 0) { s_PrintIo.ErrorStringID = IDS_PRINTERRPRINTER; goto error_AbortDoc; } }
//
// Either a printer error occurred or the user cancelled the printing, so
// abort the print job.
//
else {
error_AbortDoc: AbortDoc(g_PrintDlg.hDC);
}
DestroyWindow(hRichEdit); FreeLibrary(hInstRichEdit);
error_DeleteDocName: DeleteDynamicString(DocInfo.lpszDocName);
// error_DestroyRegPrintAbortWnd:
EnableWindow(hWnd, TRUE); DestroyWindow(s_PrintIo.hRegPrintAbortWnd);
error_FreeLineBuffer: LocalFree((HLOCAL)s_PrintIo.pLineBuffer);
error_DeleteDC: DeleteDC(g_PrintDlg.hDC); g_PrintDlg.hDC = NULL; GlobalUnlock(g_PrintDlg.hDevNames);
error_ShowDialog: if (s_PrintIo.ErrorStringID != 0) InternalMessageBox(g_hInstance, hWnd, MAKEINTRESOURCE(s_PrintIo.ErrorStringID), MAKEINTRESOURCE(IDS_REGEDIT), MB_ICONERROR | MB_OK);
}
//------------------------------------------------------------------------------
// RegEdit_SaveAsSubtree
//
// DESCRIPTION: Saves a subtree to a file
//
// PARAMETERS: LPTSTR lpFileName - file name
// LPTSTR lpSelectedPath - path to key
//------------------------------------------------------------------------------
UINT RegEdit_SaveAsSubtree(LPTSTR lpFileName, LPTSTR lpSelectedPath) { s_PrintIo.pLineBuffer = (PTSTR) LocalAlloc(LPTR, INITIAL_PRINTBUFFER_SIZE*sizeof(TCHAR)); if (s_PrintIo.pLineBuffer) { FILE_HANDLE hFile;
// Init the printing info
s_PrintIo.pLineBuffer[0] = 0xFEFF; //unicode byte order mark
s_PrintIo.cch = INITIAL_PRINTBUFFER_SIZE; s_PrintIo.cBufferPos = 1; s_PrintIo.fContinueJob = TRUE; s_PrintIo.ErrorStringID = 0; s_PrintIo.lpNewLineChars = TEXT("\r\n");
RegPrintSubtree();
// write the buffer to the file
if (OPENWRITEFILE(lpFileName, hFile)) { DWORD cbWritten = 0;
if (!WRITEFILE(hFile, s_PrintIo.pLineBuffer, s_PrintIo.cBufferPos*sizeof(TCHAR), &cbWritten)) { s_PrintIo.ErrorStringID = IDS_EXPFILEERRFILEWRITE; }
CLOSEFILE(hFile); } else { s_PrintIo.ErrorStringID = IDS_EXPFILEERRFILEOPEN; }
LocalFree(s_PrintIo.pLineBuffer); }
return PrintToSubTreeError(s_PrintIo.ErrorStringID); }
//------------------------------------------------------------------------------
// PrintToSubTreeError
//
// DESCRIPTION: Prints a subtree
//
// PARAMETER: UINT uPrintErrorStringID - print error string id
//------------------------------------------------------------------------------
UINT PrintToSubTreeError(UINT uPrintErrorStringID) { UINT uError = uPrintErrorStringID;
switch (uPrintErrorStringID) { case IDS_PRINTERRNOMEMORY: uError = IDS_SAVETREEERRNOMEMORY;
case IDS_PRINTERRCANNOTREAD: uError = IDS_SAVETREEERRCANNOTREAD; }
return uError; }
//------------------------------------------------------------------------------
// RegPrintSubtree
//
// DESCRIPTION: Prints a subtree
//------------------------------------------------------------------------------
void RegPrintSubtree() { HTREEITEM hSelectedTreeItem = TreeView_GetSelection(g_RegEditData.hKeyTreeWnd);
if (g_fRangeAll) { HTREEITEM hComputerItem = RegEdit_GetComputerItem(hSelectedTreeItem);
lstrcpy(g_SelectedPath, g_RegistryRoots[INDEX_HKEY_LOCAL_MACHINE].lpKeyName); PrintBranch(Regedit_GetRootKeyFromComputer(hComputerItem, g_SelectedPath), g_SelectedPath);
lstrcpy(g_SelectedPath, g_RegistryRoots[INDEX_HKEY_USERS].lpKeyName); PrintBranch(Regedit_GetRootKeyFromComputer(hComputerItem, g_SelectedPath), g_SelectedPath); } else { HKEY hKey;
if (EditRegistryKey(RegEdit_GetComputerItem(hSelectedTreeItem), &hKey, g_SelectedPath, ERK_OPEN) == ERROR_SUCCESS) { PrintBranch(hKey, g_SelectedPath); RegCloseKey(hKey); } } }
/*******************************************************************************
* * RegPrintAbortProc * * DESCRIPTION: * Callback procedure to check if the print job should be canceled. * * PARAMETERS: * hDC, handle of printer device context. * Error, specifies whether an error has occurred. * (returns), TRUE to continue the job, else FALSE to cancel the job. * *******************************************************************************/
BOOL CALLBACK RegPrintAbortProc( HDC hDC, int Error ) {
while (s_PrintIo.fContinueJob && MessagePump(s_PrintIo.hRegPrintAbortWnd)) ;
return s_PrintIo.fContinueJob;
UNREFERENCED_PARAMETER(hDC); UNREFERENCED_PARAMETER(Error);
}
/*******************************************************************************
* * RegPrintAbortDlgProc * * DESCRIPTION: * Callback procedure for the RegPrintAbort dialog box. * * PARAMETERS: * hWnd, handle of RegPrintAbort window. * Message, * wParam, * lParam, * (returns), * *******************************************************************************/
INT_PTR CALLBACK RegPrintAbortDlgProc( HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam ) {
switch (Message) {
case WM_INITDIALOG: break;
case WM_CLOSE: case WM_COMMAND: s_PrintIo.fContinueJob = FALSE; break;
default: return FALSE;
}
return TRUE;
}
/*******************************************************************************
* * PrintBranch * * DESCRIPTION: * * PARAMETERS: * *******************************************************************************/
void PrintBranch(HKEY hKey, LPTSTR lpFullKeyName) { // Write out the section header.
PrintKeyHeader(hKey, lpFullKeyName);
// Print the vales for the key.
PrintKeyValues(hKey);
if (s_PrintIo.ErrorStringID == 0) { HKEY hSubKey; int nLenFullKey; DWORD EnumIndex = 0; LPTSTR lpSubKeyName; LPTSTR lpTempFullKeyName;
// 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
nLenFullKey = lstrlen(lpFullKeyName); lpTempFullKeyName = (LPTSTR) alloca( (nLenFullKey+MAXKEYNAME)*sizeof(TCHAR)); lstrcpy(lpTempFullKeyName, lpFullKeyName); lpSubKeyName = lpTempFullKeyName + nLenFullKey; *lpSubKeyName++ = TEXT('\\'); *lpSubKeyName = 0;
PrintNewLine();
while (s_PrintIo.fContinueJob) { if (RegEnumKey(hKey, EnumIndex++, lpSubKeyName, MAXKEYNAME-1) != ERROR_SUCCESS) break;
if(RegOpenKeyEx(hKey,lpSubKeyName,0,KEY_ENUMERATE_SUB_KEYS|KEY_QUERY_VALUE,&hSubKey) == NO_ERROR) {
PrintBranch(hSubKey, lpTempFullKeyName); RegCloseKey(hSubKey); } else { DebugPrintf(("RegOpenKey failed.")); }
} } }
//------------------------------------------------------------------------------
// PrintKeyHeader
//
// DESCRIPTION: Prints the header information of a key
//
// PARAMETERS: HKEY hKey - key
// LPTSTR lpFullKeyName - path to key
//------------------------------------------------------------------------------
void PrintKeyValues(HKEY hKey) { DWORD EnumIndex = 0;
// Write out all of the value names and their data.
while (s_PrintIo.fContinueJob) { DWORD Type; DWORD cbValueData; PBYTE pbValueData; TCHAR acAuxNumber[MAXVALUENAME_LENGTH]; DWORD cchValueName = ARRAYSIZE(g_ValueNameBuffer);
// Query for data size
if (RegEnumValue(hKey, EnumIndex++, g_ValueNameBuffer, &cchValueName, NULL, &Type, NULL, &cbValueData) != ERROR_SUCCESS) { break; }
// Print value number
PrintDynamicString(IDS_PRINT_NUMBER); wsprintf(acAuxNumber, TEXT("%d"), EnumIndex - 1); PrintLiteral(acAuxNumber); PrintNewLine();
// Print key name
PrintDynamicString(IDS_PRINT_NAME); if (cchValueName) { PrintLiteral(g_ValueNameBuffer); } else { PrintDynamicString(IDS_PRINT_NO_NAME); } PrintNewLine();
// Print Type
PrintType(Type);
// allocate memory for data
pbValueData = LocalAlloc(LPTR, cbValueData+ExtraAllocLen(Type)); if (pbValueData) { if (RegEdit_QueryValueEx(hKey, g_ValueNameBuffer, NULL, &Type, pbValueData, &cbValueData) == ERROR_SUCCESS) { PrintValueData(pbValueData, cbValueData, Type); } else { s_PrintIo.ErrorStringID = IDS_PRINTERRCANNOTREAD; }
if (pbValueData) { LocalFree(pbValueData); pbValueData = NULL; } } else { s_PrintIo.ErrorStringID = IDS_PRINTERRNOMEMORY; break; } } }
//------------------------------------------------------------------------------
// PrintValueData
//
// DESCRIPTION: Prints the header information of a key
//
// PARAMETERS: pbValueData - byte data
// cbValueData - count of bytes
// dwType - data type
//------------------------------------------------------------------------------
void PrintValueData(PBYTE pbValueData, DWORD cbValueData, DWORD dwType) { PrintDynamicString(IDS_PRINT_DATA);
switch (dwType) { case REG_MULTI_SZ: PrintMultiString((LPTSTR)pbValueData, cbValueData); break;
case REG_SZ: case REG_EXPAND_SZ: PrintLiteral((LPTSTR)pbValueData); PrintNewLine(); break;
case REG_DWORD: PrintDWORDData((PBYTE)pbValueData, cbValueData); break;
case REG_RESOURCE_LIST: case REG_FULL_RESOURCE_DESCRIPTOR: case REG_RESOURCE_REQUIREMENTS_LIST: PrintResourceData((PBYTE)pbValueData, cbValueData, dwType); break;
default: PrintBinaryData((PBYTE)pbValueData, cbValueData); break; }
PrintNewLine(); }
//------------------------------------------------------------------------------
// PrintKeyHeader
//
// DESCRIPTION: Prints the header information of a key
//
// PARAMETERS: HKEY hKey - key
// LPTSTR lpFullKeyName - path to key
//------------------------------------------------------------------------------
void PrintKeyHeader(HKEY hKey, LPTSTR lpFullKeyName) { PrintDynamicString(IDS_PRINT_KEY_NAME); PrintLiteral(lpFullKeyName); PrintNewLine();
PrintClassName(hKey); PrintLastWriteTime(hKey); }
//------------------------------------------------------------------------------
// PrintClassName
//
// DESCRIPTION: Prints the class name
//
// PARAMETERS: HKEY hKey - key
//------------------------------------------------------------------------------
void PrintClassName(HKEY hKey) { PTSTR pszClass;
PrintDynamicString(IDS_PRINT_CLASS_NAME);
pszClass = LocalAlloc(LPTR, ALLOCATION_INCR); if (pszClass) { HRESULT hr; DWORD cbClass = sizeof(pszClass);
hr = RegQueryInfoKey(hKey, pszClass, &cbClass, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if (hr == ERROR_MORE_DATA) { // need a bigger buffer
PBYTE pbValueData = LocalReAlloc(pszClass, cbClass + 1, LMEM_MOVEABLE); if (pbValueData) { pszClass = (PTSTR)pbValueData; hr = RegQueryInfoKey(hKey, pszClass, &cbClass, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); } }
if (cbClass && (hr == ERROR_SUCCESS)) { PrintLiteral(pszClass); } else { PrintDynamicString(IDS_PRINT_NO_CLASS); }
LocalFree(pszClass); }
PrintNewLine(); }
//------------------------------------------------------------------------------
// PrintLastWriteTime
//
// DESCRIPTION: Prints the last write time
//
// PARAMETERS: HKEY hKey - key
//------------------------------------------------------------------------------
void PrintLastWriteTime(HKEY hKey) { FILETIME ftLastWriteTime;
PrintDynamicString(IDS_PRINT_LAST_WRITE_TIME);
if (RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &ftLastWriteTime) == ERROR_SUCCESS) { FILETIME ftLocalLastWriteTime; if (FileTimeToLocalFileTime(&ftLastWriteTime, &ftLocalLastWriteTime)) { SYSTEMTIME stLastWriteTime; if (FileTimeToSystemTime(&ftLocalLastWriteTime, &stLastWriteTime)) { TCHAR achData[50]; TCHAR achTime[50];
GetDateFormat(GetSystemDefaultLCID(), DATE_SHORTDATE, &stLastWriteTime, NULL, achData, ARRAYSIZE(achData));
GetTimeFormat(GetSystemDefaultLCID(), TIME_NOSECONDS, &stLastWriteTime, NULL, achTime, ARRAYSIZE(achTime));
PrintLiteral(achData); PrintLiteral(TEXT(" - ")); PrintLiteral(achTime); } } }
PrintNewLine(); }
//------------------------------------------------------------------------------
// PrintDynamicString
//
// DESCRIPTION: Prints the dynamic string
//
// PARAMETERS: UINT uStringID - resource string id
//------------------------------------------------------------------------------
void PrintDynamicString(UINT uStringID) { PTSTR psz = LoadDynamicString(uStringID); if (psz) { PrintLiteral(psz); DeleteDynamicString(psz); } }
//------------------------------------------------------------------------------
// PrintType
//
// DESCRIPTION: Prints the value type
//
// PARAMETERS: HKEY hKey - key
//------------------------------------------------------------------------------
void PrintType(DWORD dwType) { UINT uTypeStringId;
switch (dwType) { case REG_NONE: uTypeStringId = IDS_PRINT_TYPE_REG_NONE; break; case REG_SZ: uTypeStringId = IDS_PRINT_TYPE_REG_SZ; break; case REG_EXPAND_SZ: uTypeStringId = IDS_PRINT_TYPE_REG_EXPAND_SZ; break; case REG_BINARY: uTypeStringId = IDS_PRINT_TYPE_REG_BINARY; break; case REG_DWORD: uTypeStringId = IDS_PRINT_TYPE_REG_DWORD; break; case REG_LINK: uTypeStringId = IDS_PRINT_TYPE_REG_LINK; break; case REG_MULTI_SZ: uTypeStringId = IDS_PRINT_TYPE_REG_MULTI_SZ; break; case REG_RESOURCE_LIST: uTypeStringId = IDS_PRINT_TYPE_REG_RESOURCE_LIST; break; case REG_FULL_RESOURCE_DESCRIPTOR: uTypeStringId = IDS_PRINT_TYPE_REG_FULL_RESOURCE_DESCRIPTOR; break; case REG_RESOURCE_REQUIREMENTS_LIST: uTypeStringId = IDS_PRINT_TYPE_REG_RESOURCE_REQUIREMENTS_LIST; break; case REG_QWORD: uTypeStringId = IDS_PRINT_TYPE_REG_REG_QWORD; break; default: uTypeStringId = IDS_PRINT_TYPE_REG_UNKNOWN; }
PrintDynamicString(IDS_PRINT_TYPE); PrintDynamicString(uTypeStringId); PrintNewLine(); }
/*******************************************************************************
* * PrintLiteral * * DESCRIPTION: * * PARAMETERS: * *******************************************************************************/ VOID PrintLiteral(PTSTR lpLiteral) { if (s_PrintIo.fContinueJob) while (*lpLiteral != 0 && PrintChar(*lpLiteral++)); }
//------------------------------------------------------------------------------
// PrintBinaryData
//
// DESCRIPTION: Print a string that contains the binary data
//
// PARAMETERS: ValueData - Buffer that contains the binary data
// cbValueData - Number of bytes in the buffer
//------------------------------------------------------------------------------
void PrintBinaryData(PBYTE ValueData, UINT cbValueData) { DWORD dwDataIndex; DWORD dwDataIndex2 = 0; //tracks multiples of 16.
if (cbValueData && ValueData) { // Display rows of 16 bytes of data.
TCHAR achAuxData[80];
PrintNewLine();
for(dwDataIndex = 0; dwDataIndex < ( cbValueData >> 4 ); dwDataIndex++, dwDataIndex2 = dwDataIndex << 4 ) { // The string that contains the format in the sprintf below
// cannot be broken because cfront on mips doesn't like it.
wsprintf(achAuxData, TEXT("%08x %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x %02x %02x %02x %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c"), dwDataIndex2, ValueData[ dwDataIndex2 + 0 ], ValueData[ dwDataIndex2 + 1 ], ValueData[ dwDataIndex2 + 2 ], ValueData[ dwDataIndex2 + 3 ], ValueData[ dwDataIndex2 + 4 ], ValueData[ dwDataIndex2 + 5 ], ValueData[ dwDataIndex2 + 6 ], ValueData[ dwDataIndex2 + 7 ], ValueData[ dwDataIndex2 + 8 ], ValueData[ dwDataIndex2 + 9 ], ValueData[ dwDataIndex2 + 10 ], ValueData[ dwDataIndex2 + 11 ], ValueData[ dwDataIndex2 + 12 ], ValueData[ dwDataIndex2 + 13 ], ValueData[ dwDataIndex2 + 14 ], ValueData[ dwDataIndex2 + 15 ], iswprint( ValueData[ dwDataIndex2 + 0 ] ) ? ValueData[ dwDataIndex2 + 0 ] : TEXT('.'), iswprint( ValueData[ dwDataIndex2 + 1 ] ) ? ValueData[ dwDataIndex2 + 1 ] : TEXT('.'), iswprint( ValueData[ dwDataIndex2 + 2 ] ) ? ValueData[ dwDataIndex2 + 2 ] : TEXT('.'), iswprint( ValueData[ dwDataIndex2 + 3 ] ) ? ValueData[ dwDataIndex2 + 3 ] : TEXT('.'), iswprint( ValueData[ dwDataIndex2 + 4 ] ) ? ValueData[ dwDataIndex2 + 4 ] : TEXT('.'), iswprint( ValueData[ dwDataIndex2 + 5 ] ) ? ValueData[ dwDataIndex2 + 5 ] : TEXT('.'), iswprint( ValueData[ dwDataIndex2 + 6 ] ) ? ValueData[ dwDataIndex2 + 6 ] : TEXT('.'), iswprint( ValueData[ dwDataIndex2 + 7 ] ) ? ValueData[ dwDataIndex2 + 7 ] : TEXT('.'), iswprint( ValueData[ dwDataIndex2 + 8 ] ) ? ValueData[ dwDataIndex2 + 8 ] : TEXT('.'), iswprint( ValueData[ dwDataIndex2 + 9 ] ) ? ValueData[ dwDataIndex2 + 9 ] : TEXT('.'), iswprint( ValueData[ dwDataIndex2 + 10 ] ) ? ValueData[ dwDataIndex2 + 10 ] : TEXT('.'), iswprint( ValueData[ dwDataIndex2 + 11 ] ) ? ValueData[ dwDataIndex2 + 11 ] : TEXT('.'), iswprint( ValueData[ dwDataIndex2 + 12 ] ) ? ValueData[ dwDataIndex2 + 12 ] : TEXT('.'), iswprint( ValueData[ dwDataIndex2 + 13 ] ) ? ValueData[ dwDataIndex2 + 13 ] : TEXT('.'), iswprint( ValueData[ dwDataIndex2 + 14 ] ) ? ValueData[ dwDataIndex2 + 14 ] : TEXT('.'), iswprint( ValueData[ dwDataIndex2 + 15 ] ) ? ValueData[ dwDataIndex2 + 15 ] : TEXT('.'));
PrintLiteral(achAuxData); PrintNewLine(); }
// If the cbValueData is not an even multiple of 16
// then there is one additonal line of data to display.
if( cbValueData % 16 != 0 ) { UINT cchBlanks = 0; UINT uLinePos = 0; DWORD dwSeperatorChars = 0; UINT uIndex = wsprintf(achAuxData, TEXT("%08x "), dwDataIndex << 4 );
// Display the remaining data, one byte at a time in hex.
for(dwDataIndex = dwDataIndex2; dwDataIndex < cbValueData; dwDataIndex++ ) { uIndex += wsprintf((achAuxData + uIndex ), TEXT("%02x "), ValueData[dwDataIndex]);
// If eight data values have been displayed, print the seperator.
if( dwDataIndex % 8 == 7 ) { uIndex += wsprintf( &achAuxData[uIndex], TEXT("%s"), TEXT("- ")); // Remember that two seperator characters were displayed.
dwSeperatorChars = 2; } }
// Fill with blanks to the printable characters position.
// That is position 64 less 8 spaces for the 'address',
// 3 blanks, 3 spaces for each value displayed, possibly
// two for the seperator plus two blanks at the end.
uLinePos = (8 + 3 + (( dwDataIndex % 16 ) * 3 ) + dwSeperatorChars + 2 ); uLinePos = min(uLinePos, 64);
for(cchBlanks = 64 - uLinePos; cchBlanks > 0; cchBlanks--) { achAuxData[uIndex++] = TEXT(' '); }
// Display the remaining data, one byte at a time as
// printable characters.
for( dwDataIndex = dwDataIndex2; dwDataIndex < cbValueData; dwDataIndex++ ) {
uIndex += wsprintf(&achAuxData[ uIndex ], TEXT("%c"), iswprint( ValueData[ dwDataIndex ] ) ? ValueData[ dwDataIndex ] : TEXT('.'));
} PrintLiteral(achAuxData); } } PrintNewLine(); }
//------------------------------------------------------------------------------
// PrintDWORDData
//
// DESCRIPTION: Prints a DWORD
//
// PARAMETERS: ValueData - Buffer that contains the binary data
// cbValueData - Number of bytes in the buffer
//------------------------------------------------------------------------------
void PrintDWORDData(PBYTE ValueData, UINT cbValueData) { DWORD dwData = *((PDWORD)ValueData); if (cbValueData && ValueData) { TCHAR achAuxData[20]; // the largest dword string is only 8 hex digits
wsprintf(achAuxData, TEXT("%#x"), dwData);
PrintLiteral(achAuxData); } PrintNewLine(); }
/*******************************************************************************
* * PrintChar * * DESCRIPTION: * * PARAMETERS: * *******************************************************************************/
BOOL PrintChar(TCHAR Char) {
//
// Keep track of what column we're currently at. This is useful in cases
// such as writing a large binary registry record. Instead of writing one
// very long line, the other Print* routines can break up their output.
//
if (s_PrintIo.cBufferPos == s_PrintIo.cch) { PTSTR pNewBuffer = LocalAlloc(LPTR, 2*s_PrintIo.cch*sizeof(TCHAR)); if (pNewBuffer == NULL) return FALSE; memcpy(pNewBuffer, s_PrintIo.pLineBuffer, s_PrintIo.cch*sizeof(TCHAR)); LocalFree(s_PrintIo.pLineBuffer); s_PrintIo.pLineBuffer = pNewBuffer; s_PrintIo.cch *= 2; }
s_PrintIo.pLineBuffer[s_PrintIo.cBufferPos++] = Char;
return TRUE; }
//------------------------------------------------------------------------------
// PrintMultiString
//
// DESCRIPTION: Prints a multi-string
//
// PARAMETERS: pszData - string
// cbData - number of bytes in string, including nulls
//------------------------------------------------------------------------------
VOID PrintMultiString(LPTSTR pszData, int cbData) { if (s_PrintIo.fContinueJob) { int i = 0; int ccData = (cbData / sizeof(TCHAR)) - 2; // don't want last null of last string or multi-string
for(i = 0; i < ccData; i++) { if (pszData[i] == TEXT('\0')) { PrintNewLine(); PrintDynamicString(IDS_PRINT_KEY_NAME_INDENT); } else { PrintChar(pszData[i]); } } } PrintNewLine(); }
//------------------------------------------------------------------------------
// PrintNewLine()
//
// DESCRIPTION: Prints the newline chars.
//
// PARAMETERS: pszData - string
// cbData - number of bytes in string, including nulls
//------------------------------------------------------------------------------
void PrintNewLine() { PrintLiteral(s_PrintIo.lpNewLineChars); }
|