Source code of Windows XP (NT5)
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.

1225 lines
34 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 1993-1994
  4. *
  5. * TITLE: REGPRINT.C
  6. *
  7. * VERSION: 4.0
  8. *
  9. * AUTHOR: Tracy Sharpe
  10. *
  11. * DATE: 21 Nov 1993
  12. *
  13. * Print routines for the Registry Editor.
  14. *
  15. *******************************************************************************/
  16. #include "pch.h"
  17. #include "regprint.h"
  18. #include "regcdhk.h"
  19. #include "regresid.h"
  20. #include "regedit.h"
  21. #include "richedit.h"
  22. #include "regporte.h"
  23. #include "reg1632.h"
  24. #include <malloc.h>
  25. extern void PrintResourceData(PBYTE pbData, UINT uSize, DWORD dwType);
  26. const TCHAR s_PrintLineBreak[] = TEXT(",\n ");
  27. PRINTDLGEX g_PrintDlg;
  28. typedef struct _PRINT_IO {
  29. BOOL fContinueJob;
  30. UINT ErrorStringID;
  31. HWND hRegPrintAbortWnd;
  32. RECT rcPage;
  33. RECT rcOutput;
  34. PTSTR pLineBuffer;
  35. UINT cch;
  36. UINT cBufferPos;
  37. LPTSTR lpNewLineChars;
  38. } PRINT_IO;
  39. #define CANCEL_NONE 0x0000
  40. #define CANCEL_MEMORY_ERROR 0x0001
  41. #define CANCEL_PRINTER_ERROR 0x0002
  42. #define CANCEL_ABORT 0x0004
  43. #define INITIAL_PRINTBUFFER_SIZE 8192
  44. PRINT_IO s_PrintIo;
  45. BOOL
  46. CALLBACK
  47. RegPrintAbortProc(
  48. HDC hDC,
  49. int Error
  50. );
  51. INT_PTR
  52. CALLBACK
  53. RegPrintAbortDlgProc(
  54. HWND hWnd,
  55. UINT Message,
  56. WPARAM wParam,
  57. LPARAM lParam
  58. );
  59. void RegPrintSubtree();
  60. void PrintBranch(HKEY hKey, LPTSTR lpFullKeyName);
  61. void PrintKeyValues(HKEY hKey);
  62. void PrintValueData(PBYTE pbValueData, DWORD cbValueData, DWORD dwType);
  63. void PrintKeyHeader(HKEY hKey, LPTSTR lpFullKeyName);
  64. void PrintClassName(HKEY hKey);
  65. void PrintLastWriteTime(HKEY hKey);
  66. void PrintDynamicString(UINT uStringID);
  67. void PrintType(DWORD dwType);
  68. void PrintBinaryData(PBYTE ValueData, UINT cbcbValueData);
  69. void PrintDWORDData(PBYTE ValueData, UINT cbcbValueData);
  70. void PrintLiteral(PTSTR lpLiteral);
  71. BOOL PrintChar(TCHAR Char);
  72. void PrintMultiString(LPTSTR pszData, int cbData);
  73. UINT PrintToSubTreeError(UINT uPrintErrorStringID);
  74. void PrintNewLine();
  75. /*******************************************************************************
  76. *
  77. * Implement IPrintDialogCallback
  78. *
  79. * DESCRIPTION:
  80. * This interface is necessary to handle messages through PrintDlgEx
  81. * This interface doesn't need to have all the correct semantics of a COM
  82. * Object
  83. *
  84. *******************************************************************************/
  85. typedef struct
  86. {
  87. IPrintDialogCallback ipcb;
  88. } CPrintCallback;
  89. #define IMPL(type, pos, ptr) (type*)
  90. static
  91. HRESULT
  92. CPrintCallback_QueryInterface(IPrintDialogCallback *ppcb, REFIID riid, void **ppv)
  93. {
  94. CPrintCallback *this = (CPrintCallback*)ppcb;
  95. if (IsEqualIID (riid, &IID_IUnknown) || IsEqualIID (riid, &IID_IPrintDialogCallback))
  96. *ppv = &this->ipcb;
  97. else
  98. {
  99. *ppv = 0;
  100. return E_NOINTERFACE;
  101. }
  102. this->ipcb.lpVtbl->AddRef(&this->ipcb);
  103. return NOERROR;
  104. }
  105. static
  106. ULONG
  107. CPrintCallback_AddRef(IPrintDialogCallback *ppcb)
  108. {
  109. CPrintCallback *this = (CPrintCallback*)ppcb;
  110. return 1;
  111. }
  112. static
  113. ULONG
  114. CPrintCallback_Release(IPrintDialogCallback *ppcb)
  115. {
  116. CPrintCallback *this = (CPrintCallback*)ppcb;
  117. return 1;
  118. }
  119. static
  120. HRESULT
  121. CPrintCallback_InitDone(IPrintDialogCallback *ppcb)
  122. {
  123. return S_OK;
  124. }
  125. static
  126. HRESULT
  127. CPrintCallback_SelectionChange(IPrintDialogCallback *ppcb)
  128. {
  129. return S_OK;
  130. }
  131. static
  132. HRESULT
  133. CPrintCallback_HandleMessage(
  134. IPrintDialogCallback *ppcb,
  135. HWND hDlg,
  136. UINT uMsg,
  137. WPARAM wParam,
  138. LPARAM lParam,
  139. LRESULT *pResult)
  140. {
  141. *pResult = RegCommDlgHookProc(hDlg, uMsg, wParam, lParam);
  142. return S_OK;
  143. }
  144. static IPrintDialogCallbackVtbl vtblPCB =
  145. {
  146. CPrintCallback_QueryInterface,
  147. CPrintCallback_AddRef,
  148. CPrintCallback_Release,
  149. CPrintCallback_InitDone,
  150. CPrintCallback_SelectionChange,
  151. CPrintCallback_HandleMessage
  152. };
  153. CPrintCallback g_callback;
  154. /*******************************************************************************
  155. *
  156. * RegEdit_OnCommandPrint
  157. *
  158. * DESCRIPTION:
  159. * Handles the selection of the "Print" option by the user for the RegEdit
  160. * dialog box.
  161. *
  162. * PARAMETERS:
  163. * hWnd, handle of RegPrint window.
  164. *
  165. *******************************************************************************/
  166. VOID
  167. PASCAL
  168. RegEdit_OnCommandPrint(
  169. HWND hWnd
  170. )
  171. {
  172. LPDEVNAMES lpDevNames;
  173. TEXTMETRIC TextMetric;
  174. DOCINFO DocInfo;
  175. LOGFONT lf;
  176. HGLOBAL hDevMode;
  177. HGLOBAL hDevNames;
  178. RECT rc;
  179. HWND hRichEdit;
  180. FORMATRANGE fr;
  181. HINSTANCE hInstRichEdit;
  182. int nOffsetX;
  183. int nOffsetY;
  184. PTSTR pszFontName;
  185. g_callback.ipcb.lpVtbl = &vtblPCB;
  186. // We have to completely fill out the PRINTDLGEX structure
  187. // correctly or the PrintDlgEx function will return an error.
  188. // The easiest way is to memset it to 0
  189. hDevMode = g_PrintDlg.hDevMode;
  190. hDevNames = g_PrintDlg.hDevNames;
  191. memset(&g_PrintDlg, 0, sizeof(g_PrintDlg));
  192. g_PrintDlg.lStructSize = sizeof(PRINTDLGEX);
  193. g_PrintDlg.hwndOwner = hWnd;
  194. g_PrintDlg.hDevMode = hDevMode;
  195. g_PrintDlg.hDevNames = hDevNames;
  196. g_PrintDlg.hDC = NULL;
  197. g_PrintDlg.Flags = PD_NOPAGENUMS | PD_RETURNDC | PD_ENABLEPRINTTEMPLATE;
  198. g_PrintDlg.Flags2 = 0;
  199. g_PrintDlg.ExclusionFlags = 0;
  200. g_PrintDlg.hInstance = g_hInstance;
  201. g_PrintDlg.nCopies = 1;
  202. g_PrintDlg.nStartPage = START_PAGE_GENERAL;
  203. g_PrintDlg.lpCallback = (IUnknown*) &g_callback.ipcb;
  204. g_PrintDlg.lpPrintTemplateName = MAKEINTRESOURCE(IDD_REGPRINT);
  205. g_RegCommDlgDialogTemplate = IDD_REGPRINT;
  206. if (FAILED(PrintDlgEx(&g_PrintDlg)))
  207. return;
  208. if (g_PrintDlg.dwResultAction != PD_RESULT_PRINT)
  209. return;
  210. s_PrintIo.ErrorStringID = IDS_PRINTERRNOMEMORY;
  211. if ((lpDevNames = GlobalLock(g_PrintDlg.hDevNames)) == NULL)
  212. goto error_ShowDialog;
  213. //
  214. // For now, assume a page with top and bottom margins of 1/2 inch and
  215. // left and right margins of 3/4 inch (the defaults of Notepad).
  216. // rcPage and rcOutput are in TWIPS (1/20th of a point)
  217. //
  218. rc.left = rc.top = 0;
  219. rc.bottom = GetDeviceCaps(g_PrintDlg.hDC, PHYSICALHEIGHT);
  220. rc.right = GetDeviceCaps(g_PrintDlg.hDC, PHYSICALWIDTH);
  221. nOffsetX = GetDeviceCaps(g_PrintDlg.hDC, PHYSICALOFFSETX);
  222. nOffsetY = GetDeviceCaps(g_PrintDlg.hDC, PHYSICALOFFSETY);
  223. s_PrintIo.rcPage.left = s_PrintIo.rcPage.top = 0;
  224. s_PrintIo.rcPage.right = MulDiv(rc.right, 1440, GetDeviceCaps(g_PrintDlg.hDC, LOGPIXELSX));
  225. s_PrintIo.rcPage.bottom = MulDiv(rc.bottom, 1440, GetDeviceCaps(g_PrintDlg.hDC, LOGPIXELSY));
  226. s_PrintIo.rcOutput.left = 1080;
  227. s_PrintIo.rcOutput.top = 720;
  228. s_PrintIo.rcOutput.right = s_PrintIo.rcPage.right - 1080;
  229. s_PrintIo.rcOutput.bottom = s_PrintIo.rcPage.bottom - 720;
  230. //
  231. //
  232. //
  233. if ((s_PrintIo.pLineBuffer = (PTSTR) LocalAlloc(LPTR, INITIAL_PRINTBUFFER_SIZE*sizeof(TCHAR))) == NULL)
  234. goto error_DeleteDC;
  235. s_PrintIo.cch = INITIAL_PRINTBUFFER_SIZE;
  236. s_PrintIo.cBufferPos = 0;
  237. if ((s_PrintIo.hRegPrintAbortWnd = CreateDialog(g_hInstance,
  238. MAKEINTRESOURCE(IDD_REGPRINTABORT), hWnd, RegPrintAbortDlgProc)) ==
  239. NULL)
  240. goto error_FreeLineBuffer;
  241. EnableWindow(hWnd, FALSE);
  242. //
  243. // Prepare the document for printing.
  244. //
  245. s_PrintIo.ErrorStringID = 0;
  246. s_PrintIo.fContinueJob = TRUE;
  247. s_PrintIo.lpNewLineChars = TEXT("\n");
  248. SetAbortProc(g_PrintDlg.hDC, RegPrintAbortProc);
  249. DocInfo.cbSize = sizeof(DOCINFO);
  250. DocInfo.lpszDocName = LoadDynamicString(IDS_REGEDIT);
  251. DocInfo.lpszOutput = (LPTSTR) lpDevNames + lpDevNames-> wOutputOffset;
  252. DocInfo.lpszDatatype = NULL;
  253. DocInfo.fwType = 0;
  254. s_PrintIo.ErrorStringID = 0;
  255. if (StartDoc(g_PrintDlg.hDC, &DocInfo) <= 0) {
  256. if (GetLastError() != ERROR_PRINT_CANCELLED)
  257. s_PrintIo.ErrorStringID = IDS_PRINTERRPRINTER;
  258. goto error_DeleteDocName;
  259. }
  260. // Print registry subtree.
  261. RegPrintSubtree();
  262. if (s_PrintIo.ErrorStringID != 0)
  263. {
  264. InternalMessageBox(g_hInstance, hWnd,
  265. MAKEINTRESOURCE(s_PrintIo.ErrorStringID),
  266. MAKEINTRESOURCE(IDS_REGEDIT), MB_ICONERROR | MB_OK);
  267. }
  268. hInstRichEdit = LoadLibrary(TEXT("riched20.dll"));
  269. hRichEdit = CreateWindowEx(0, RICHEDIT_CLASS, NULL, ES_MULTILINE, 0, 0, 100, 100, NULL, NULL, NULL, NULL);
  270. SendMessage(hRichEdit, WM_SETTEXT, 0, (LPARAM)s_PrintIo.pLineBuffer);
  271. pszFontName = LoadDynamicString(IDS_PRINT_FONT);
  272. if (pszFontName)
  273. {
  274. CHARFORMAT cf;
  275. cf.cbSize = sizeof(CHARFORMAT);
  276. cf.dwMask = CFM_FACE | CFM_BOLD;
  277. cf.dwEffects = 0x00;
  278. cf.bPitchAndFamily = FIXED_PITCH | FF_MODERN;
  279. wsprintf(cf.szFaceName, TEXT("%s"), pszFontName);
  280. SendMessage(hRichEdit, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf);
  281. DeleteDynamicString(pszFontName);
  282. }
  283. fr.hdc = g_PrintDlg.hDC;
  284. fr.hdcTarget = g_PrintDlg.hDC;
  285. fr.rc = s_PrintIo.rcOutput;
  286. fr.rcPage = s_PrintIo.rcPage;
  287. fr.chrg.cpMin = 0;
  288. fr.chrg.cpMax = -1;
  289. while (fr.chrg.cpMin < (int) s_PrintIo.cBufferPos) {
  290. StartPage(g_PrintDlg.hDC);
  291. // We have to adjust the origin because 0,0 is not at the corner of the paper
  292. // but is at the corner of the printable region
  293. SetViewportOrgEx(g_PrintDlg.hDC, -nOffsetX, -nOffsetY, NULL);
  294. fr.chrg.cpMin = (LONG)SendMessage(hRichEdit, EM_FORMATRANGE, TRUE, (LPARAM)&fr);
  295. SendMessage(hRichEdit, EM_DISPLAYBAND, 0, (LPARAM)&s_PrintIo.rcOutput);
  296. EndPage(g_PrintDlg.hDC);
  297. if (!s_PrintIo.fContinueJob)
  298. break;
  299. }
  300. SendMessage(hRichEdit, EM_FORMATRANGE, FALSE, 0);
  301. //
  302. // End the print job.
  303. //
  304. if (s_PrintIo.ErrorStringID == 0 && s_PrintIo.fContinueJob) {
  305. if (EndDoc(g_PrintDlg.hDC) <= 0) {
  306. s_PrintIo.ErrorStringID = IDS_PRINTERRPRINTER;
  307. goto error_AbortDoc;
  308. }
  309. }
  310. //
  311. // Either a printer error occurred or the user cancelled the printing, so
  312. // abort the print job.
  313. //
  314. else {
  315. error_AbortDoc:
  316. AbortDoc(g_PrintDlg.hDC);
  317. }
  318. DestroyWindow(hRichEdit);
  319. FreeLibrary(hInstRichEdit);
  320. error_DeleteDocName:
  321. DeleteDynamicString(DocInfo.lpszDocName);
  322. // error_DestroyRegPrintAbortWnd:
  323. EnableWindow(hWnd, TRUE);
  324. DestroyWindow(s_PrintIo.hRegPrintAbortWnd);
  325. error_FreeLineBuffer:
  326. LocalFree((HLOCAL)s_PrintIo.pLineBuffer);
  327. error_DeleteDC:
  328. DeleteDC(g_PrintDlg.hDC);
  329. g_PrintDlg.hDC = NULL;
  330. GlobalUnlock(g_PrintDlg.hDevNames);
  331. error_ShowDialog:
  332. if (s_PrintIo.ErrorStringID != 0)
  333. InternalMessageBox(g_hInstance, hWnd,
  334. MAKEINTRESOURCE(s_PrintIo.ErrorStringID),
  335. MAKEINTRESOURCE(IDS_REGEDIT), MB_ICONERROR | MB_OK);
  336. }
  337. //------------------------------------------------------------------------------
  338. // RegEdit_SaveAsSubtree
  339. //
  340. // DESCRIPTION: Saves a subtree to a file
  341. //
  342. // PARAMETERS: LPTSTR lpFileName - file name
  343. // LPTSTR lpSelectedPath - path to key
  344. //------------------------------------------------------------------------------
  345. UINT RegEdit_SaveAsSubtree(LPTSTR lpFileName, LPTSTR lpSelectedPath)
  346. {
  347. s_PrintIo.pLineBuffer = (PTSTR) LocalAlloc(LPTR, INITIAL_PRINTBUFFER_SIZE*sizeof(TCHAR));
  348. if (s_PrintIo.pLineBuffer)
  349. {
  350. FILE_HANDLE hFile;
  351. // Init the printing info
  352. s_PrintIo.pLineBuffer[0] = 0xFEFF; //unicode byte order mark
  353. s_PrintIo.cch = INITIAL_PRINTBUFFER_SIZE;
  354. s_PrintIo.cBufferPos = 1;
  355. s_PrintIo.fContinueJob = TRUE;
  356. s_PrintIo.ErrorStringID = 0;
  357. s_PrintIo.lpNewLineChars = TEXT("\r\n");
  358. RegPrintSubtree();
  359. // write the buffer to the file
  360. if (OPENWRITEFILE(lpFileName, hFile))
  361. {
  362. DWORD cbWritten = 0;
  363. if (!WRITEFILE(hFile, s_PrintIo.pLineBuffer, s_PrintIo.cBufferPos*sizeof(TCHAR), &cbWritten))
  364. {
  365. s_PrintIo.ErrorStringID = IDS_EXPFILEERRFILEWRITE;
  366. }
  367. CLOSEFILE(hFile);
  368. }
  369. else
  370. {
  371. s_PrintIo.ErrorStringID = IDS_EXPFILEERRFILEOPEN;
  372. }
  373. LocalFree(s_PrintIo.pLineBuffer);
  374. }
  375. return PrintToSubTreeError(s_PrintIo.ErrorStringID);
  376. }
  377. //------------------------------------------------------------------------------
  378. // PrintToSubTreeError
  379. //
  380. // DESCRIPTION: Prints a subtree
  381. //
  382. // PARAMETER: UINT uPrintErrorStringID - print error string id
  383. //------------------------------------------------------------------------------
  384. UINT PrintToSubTreeError(UINT uPrintErrorStringID)
  385. {
  386. UINT uError = uPrintErrorStringID;
  387. switch (uPrintErrorStringID)
  388. {
  389. case IDS_PRINTERRNOMEMORY:
  390. uError = IDS_SAVETREEERRNOMEMORY;
  391. case IDS_PRINTERRCANNOTREAD:
  392. uError = IDS_SAVETREEERRCANNOTREAD;
  393. }
  394. return uError;
  395. }
  396. //------------------------------------------------------------------------------
  397. // RegPrintSubtree
  398. //
  399. // DESCRIPTION: Prints a subtree
  400. //------------------------------------------------------------------------------
  401. void RegPrintSubtree()
  402. {
  403. HTREEITEM hSelectedTreeItem = TreeView_GetSelection(g_RegEditData.hKeyTreeWnd);
  404. if (g_fRangeAll)
  405. {
  406. HTREEITEM hComputerItem = RegEdit_GetComputerItem(hSelectedTreeItem);
  407. lstrcpy(g_SelectedPath, g_RegistryRoots[INDEX_HKEY_LOCAL_MACHINE].lpKeyName);
  408. PrintBranch(Regedit_GetRootKeyFromComputer(hComputerItem, g_SelectedPath),
  409. g_SelectedPath);
  410. lstrcpy(g_SelectedPath, g_RegistryRoots[INDEX_HKEY_USERS].lpKeyName);
  411. PrintBranch(Regedit_GetRootKeyFromComputer(hComputerItem, g_SelectedPath),
  412. g_SelectedPath);
  413. }
  414. else
  415. {
  416. HKEY hKey;
  417. if (EditRegistryKey(RegEdit_GetComputerItem(hSelectedTreeItem),
  418. &hKey, g_SelectedPath, ERK_OPEN) == ERROR_SUCCESS)
  419. {
  420. PrintBranch(hKey, g_SelectedPath);
  421. RegCloseKey(hKey);
  422. }
  423. }
  424. }
  425. /*******************************************************************************
  426. *
  427. * RegPrintAbortProc
  428. *
  429. * DESCRIPTION:
  430. * Callback procedure to check if the print job should be canceled.
  431. *
  432. * PARAMETERS:
  433. * hDC, handle of printer device context.
  434. * Error, specifies whether an error has occurred.
  435. * (returns), TRUE to continue the job, else FALSE to cancel the job.
  436. *
  437. *******************************************************************************/
  438. BOOL
  439. CALLBACK
  440. RegPrintAbortProc(
  441. HDC hDC,
  442. int Error
  443. )
  444. {
  445. while (s_PrintIo.fContinueJob && MessagePump(s_PrintIo.hRegPrintAbortWnd))
  446. ;
  447. return s_PrintIo.fContinueJob;
  448. UNREFERENCED_PARAMETER(hDC);
  449. UNREFERENCED_PARAMETER(Error);
  450. }
  451. /*******************************************************************************
  452. *
  453. * RegPrintAbortDlgProc
  454. *
  455. * DESCRIPTION:
  456. * Callback procedure for the RegPrintAbort dialog box.
  457. *
  458. * PARAMETERS:
  459. * hWnd, handle of RegPrintAbort window.
  460. * Message,
  461. * wParam,
  462. * lParam,
  463. * (returns),
  464. *
  465. *******************************************************************************/
  466. INT_PTR
  467. CALLBACK
  468. RegPrintAbortDlgProc(
  469. HWND hWnd,
  470. UINT Message,
  471. WPARAM wParam,
  472. LPARAM lParam
  473. )
  474. {
  475. switch (Message) {
  476. case WM_INITDIALOG:
  477. break;
  478. case WM_CLOSE:
  479. case WM_COMMAND:
  480. s_PrintIo.fContinueJob = FALSE;
  481. break;
  482. default:
  483. return FALSE;
  484. }
  485. return TRUE;
  486. }
  487. /*******************************************************************************
  488. *
  489. * PrintBranch
  490. *
  491. * DESCRIPTION:
  492. *
  493. * PARAMETERS:
  494. *
  495. *******************************************************************************/
  496. void PrintBranch(HKEY hKey, LPTSTR lpFullKeyName)
  497. {
  498. // Write out the section header.
  499. PrintKeyHeader(hKey, lpFullKeyName);
  500. // Print the vales for the key.
  501. PrintKeyValues(hKey);
  502. if (s_PrintIo.ErrorStringID == 0)
  503. {
  504. HKEY hSubKey;
  505. int nLenFullKey;
  506. DWORD EnumIndex = 0;
  507. LPTSTR lpSubKeyName;
  508. LPTSTR lpTempFullKeyName;
  509. // Write out all of the subkeys and recurse into them.
  510. //copy the existing key into a new buffer with enough room for the next key
  511. nLenFullKey = lstrlen(lpFullKeyName);
  512. lpTempFullKeyName = (LPTSTR) alloca( (nLenFullKey+MAXKEYNAME)*sizeof(TCHAR));
  513. lstrcpy(lpTempFullKeyName, lpFullKeyName);
  514. lpSubKeyName = lpTempFullKeyName + nLenFullKey;
  515. *lpSubKeyName++ = TEXT('\\');
  516. *lpSubKeyName = 0;
  517. PrintNewLine();
  518. while (s_PrintIo.fContinueJob)
  519. {
  520. if (RegEnumKey(hKey, EnumIndex++, lpSubKeyName, MAXKEYNAME-1) !=
  521. ERROR_SUCCESS)
  522. break;
  523. if(RegOpenKeyEx(hKey,lpSubKeyName,0,KEY_ENUMERATE_SUB_KEYS|KEY_QUERY_VALUE,&hSubKey) ==
  524. NO_ERROR)
  525. {
  526. PrintBranch(hSubKey, lpTempFullKeyName);
  527. RegCloseKey(hSubKey);
  528. }
  529. else
  530. {
  531. DebugPrintf(("RegOpenKey failed."));
  532. }
  533. }
  534. }
  535. }
  536. //------------------------------------------------------------------------------
  537. // PrintKeyHeader
  538. //
  539. // DESCRIPTION: Prints the header information of a key
  540. //
  541. // PARAMETERS: HKEY hKey - key
  542. // LPTSTR lpFullKeyName - path to key
  543. //------------------------------------------------------------------------------
  544. void PrintKeyValues(HKEY hKey)
  545. {
  546. DWORD EnumIndex = 0;
  547. // Write out all of the value names and their data.
  548. while (s_PrintIo.fContinueJob)
  549. {
  550. DWORD Type;
  551. DWORD cbValueData;
  552. PBYTE pbValueData;
  553. TCHAR acAuxNumber[MAXVALUENAME_LENGTH];
  554. DWORD cchValueName = ARRAYSIZE(g_ValueNameBuffer);
  555. // Query for data size
  556. if (RegEnumValue(hKey, EnumIndex++, g_ValueNameBuffer,
  557. &cchValueName, NULL, &Type, NULL, &cbValueData) != ERROR_SUCCESS)
  558. {
  559. break;
  560. }
  561. // Print value number
  562. PrintDynamicString(IDS_PRINT_NUMBER);
  563. wsprintf(acAuxNumber, TEXT("%d"), EnumIndex - 1);
  564. PrintLiteral(acAuxNumber);
  565. PrintNewLine();
  566. // Print key name
  567. PrintDynamicString(IDS_PRINT_NAME);
  568. if (cchValueName)
  569. {
  570. PrintLiteral(g_ValueNameBuffer);
  571. }
  572. else
  573. {
  574. PrintDynamicString(IDS_PRINT_NO_NAME);
  575. }
  576. PrintNewLine();
  577. // Print Type
  578. PrintType(Type);
  579. // allocate memory for data
  580. pbValueData = LocalAlloc(LPTR, cbValueData+ExtraAllocLen(Type));
  581. if (pbValueData)
  582. {
  583. if (RegEdit_QueryValueEx(hKey, g_ValueNameBuffer,
  584. NULL, &Type, pbValueData, &cbValueData) == ERROR_SUCCESS)
  585. {
  586. PrintValueData(pbValueData, cbValueData, Type);
  587. }
  588. else
  589. {
  590. s_PrintIo.ErrorStringID = IDS_PRINTERRCANNOTREAD;
  591. }
  592. if (pbValueData)
  593. {
  594. LocalFree(pbValueData);
  595. pbValueData = NULL;
  596. }
  597. }
  598. else
  599. {
  600. s_PrintIo.ErrorStringID = IDS_PRINTERRNOMEMORY;
  601. break;
  602. }
  603. }
  604. }
  605. //------------------------------------------------------------------------------
  606. // PrintValueData
  607. //
  608. // DESCRIPTION: Prints the header information of a key
  609. //
  610. // PARAMETERS: pbValueData - byte data
  611. // cbValueData - count of bytes
  612. // dwType - data type
  613. //------------------------------------------------------------------------------
  614. void PrintValueData(PBYTE pbValueData, DWORD cbValueData, DWORD dwType)
  615. {
  616. PrintDynamicString(IDS_PRINT_DATA);
  617. switch (dwType)
  618. {
  619. case REG_MULTI_SZ:
  620. PrintMultiString((LPTSTR)pbValueData, cbValueData);
  621. break;
  622. case REG_SZ:
  623. case REG_EXPAND_SZ:
  624. PrintLiteral((LPTSTR)pbValueData);
  625. PrintNewLine();
  626. break;
  627. case REG_DWORD:
  628. PrintDWORDData((PBYTE)pbValueData, cbValueData);
  629. break;
  630. case REG_RESOURCE_LIST:
  631. case REG_FULL_RESOURCE_DESCRIPTOR:
  632. case REG_RESOURCE_REQUIREMENTS_LIST:
  633. PrintResourceData((PBYTE)pbValueData, cbValueData, dwType);
  634. break;
  635. default:
  636. PrintBinaryData((PBYTE)pbValueData, cbValueData);
  637. break;
  638. }
  639. PrintNewLine();
  640. }
  641. //------------------------------------------------------------------------------
  642. // PrintKeyHeader
  643. //
  644. // DESCRIPTION: Prints the header information of a key
  645. //
  646. // PARAMETERS: HKEY hKey - key
  647. // LPTSTR lpFullKeyName - path to key
  648. //------------------------------------------------------------------------------
  649. void PrintKeyHeader(HKEY hKey, LPTSTR lpFullKeyName)
  650. {
  651. PrintDynamicString(IDS_PRINT_KEY_NAME);
  652. PrintLiteral(lpFullKeyName);
  653. PrintNewLine();
  654. PrintClassName(hKey);
  655. PrintLastWriteTime(hKey);
  656. }
  657. //------------------------------------------------------------------------------
  658. // PrintClassName
  659. //
  660. // DESCRIPTION: Prints the class name
  661. //
  662. // PARAMETERS: HKEY hKey - key
  663. //------------------------------------------------------------------------------
  664. void PrintClassName(HKEY hKey)
  665. {
  666. PTSTR pszClass;
  667. PrintDynamicString(IDS_PRINT_CLASS_NAME);
  668. pszClass = LocalAlloc(LPTR, ALLOCATION_INCR);
  669. if (pszClass)
  670. {
  671. HRESULT hr;
  672. DWORD cbClass = sizeof(pszClass);
  673. hr = RegQueryInfoKey(hKey, pszClass, &cbClass, NULL, NULL, NULL, NULL, NULL,
  674. NULL, NULL, NULL, NULL);
  675. if (hr == ERROR_MORE_DATA)
  676. {
  677. // need a bigger buffer
  678. PBYTE pbValueData = LocalReAlloc(pszClass, cbClass + 1, LMEM_MOVEABLE);
  679. if (pbValueData)
  680. {
  681. pszClass = (PTSTR)pbValueData;
  682. hr = RegQueryInfoKey(hKey, pszClass, &cbClass, NULL, NULL, NULL, NULL, NULL,
  683. NULL, NULL, NULL, NULL);
  684. }
  685. }
  686. if (cbClass && (hr == ERROR_SUCCESS))
  687. {
  688. PrintLiteral(pszClass);
  689. }
  690. else
  691. {
  692. PrintDynamicString(IDS_PRINT_NO_CLASS);
  693. }
  694. LocalFree(pszClass);
  695. }
  696. PrintNewLine();
  697. }
  698. //------------------------------------------------------------------------------
  699. // PrintLastWriteTime
  700. //
  701. // DESCRIPTION: Prints the last write time
  702. //
  703. // PARAMETERS: HKEY hKey - key
  704. //------------------------------------------------------------------------------
  705. void PrintLastWriteTime(HKEY hKey)
  706. {
  707. FILETIME ftLastWriteTime;
  708. PrintDynamicString(IDS_PRINT_LAST_WRITE_TIME);
  709. if (RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  710. NULL, NULL, NULL, &ftLastWriteTime) == ERROR_SUCCESS)
  711. {
  712. FILETIME ftLocalLastWriteTime;
  713. if (FileTimeToLocalFileTime(&ftLastWriteTime, &ftLocalLastWriteTime))
  714. {
  715. SYSTEMTIME stLastWriteTime;
  716. if (FileTimeToSystemTime(&ftLocalLastWriteTime, &stLastWriteTime))
  717. {
  718. TCHAR achData[50];
  719. TCHAR achTime[50];
  720. GetDateFormat(GetSystemDefaultLCID(), DATE_SHORTDATE, &stLastWriteTime,
  721. NULL, achData, ARRAYSIZE(achData));
  722. GetTimeFormat(GetSystemDefaultLCID(), TIME_NOSECONDS, &stLastWriteTime,
  723. NULL, achTime, ARRAYSIZE(achTime));
  724. PrintLiteral(achData);
  725. PrintLiteral(TEXT(" - "));
  726. PrintLiteral(achTime);
  727. }
  728. }
  729. }
  730. PrintNewLine();
  731. }
  732. //------------------------------------------------------------------------------
  733. // PrintDynamicString
  734. //
  735. // DESCRIPTION: Prints the dynamic string
  736. //
  737. // PARAMETERS: UINT uStringID - resource string id
  738. //------------------------------------------------------------------------------
  739. void PrintDynamicString(UINT uStringID)
  740. {
  741. PTSTR psz = LoadDynamicString(uStringID);
  742. if (psz)
  743. {
  744. PrintLiteral(psz);
  745. DeleteDynamicString(psz);
  746. }
  747. }
  748. //------------------------------------------------------------------------------
  749. // PrintType
  750. //
  751. // DESCRIPTION: Prints the value type
  752. //
  753. // PARAMETERS: HKEY hKey - key
  754. //------------------------------------------------------------------------------
  755. void PrintType(DWORD dwType)
  756. {
  757. UINT uTypeStringId;
  758. switch (dwType)
  759. {
  760. case REG_NONE:
  761. uTypeStringId = IDS_PRINT_TYPE_REG_NONE;
  762. break;
  763. case REG_SZ:
  764. uTypeStringId = IDS_PRINT_TYPE_REG_SZ;
  765. break;
  766. case REG_EXPAND_SZ:
  767. uTypeStringId = IDS_PRINT_TYPE_REG_EXPAND_SZ;
  768. break;
  769. case REG_BINARY:
  770. uTypeStringId = IDS_PRINT_TYPE_REG_BINARY;
  771. break;
  772. case REG_DWORD:
  773. uTypeStringId = IDS_PRINT_TYPE_REG_DWORD;
  774. break;
  775. case REG_LINK:
  776. uTypeStringId = IDS_PRINT_TYPE_REG_LINK;
  777. break;
  778. case REG_MULTI_SZ:
  779. uTypeStringId = IDS_PRINT_TYPE_REG_MULTI_SZ;
  780. break;
  781. case REG_RESOURCE_LIST:
  782. uTypeStringId = IDS_PRINT_TYPE_REG_RESOURCE_LIST;
  783. break;
  784. case REG_FULL_RESOURCE_DESCRIPTOR:
  785. uTypeStringId = IDS_PRINT_TYPE_REG_FULL_RESOURCE_DESCRIPTOR;
  786. break;
  787. case REG_RESOURCE_REQUIREMENTS_LIST:
  788. uTypeStringId = IDS_PRINT_TYPE_REG_RESOURCE_REQUIREMENTS_LIST;
  789. break;
  790. case REG_QWORD:
  791. uTypeStringId = IDS_PRINT_TYPE_REG_REG_QWORD;
  792. break;
  793. default:
  794. uTypeStringId = IDS_PRINT_TYPE_REG_UNKNOWN;
  795. }
  796. PrintDynamicString(IDS_PRINT_TYPE);
  797. PrintDynamicString(uTypeStringId);
  798. PrintNewLine();
  799. }
  800. /*******************************************************************************
  801. *
  802. * PrintLiteral
  803. *
  804. * DESCRIPTION:
  805. *
  806. * PARAMETERS:
  807. *
  808. *******************************************************************************/
  809. VOID PrintLiteral(PTSTR lpLiteral)
  810. {
  811. if (s_PrintIo.fContinueJob)
  812. while (*lpLiteral != 0 && PrintChar(*lpLiteral++));
  813. }
  814. //------------------------------------------------------------------------------
  815. // PrintBinaryData
  816. //
  817. // DESCRIPTION: Print a string that contains the binary data
  818. //
  819. // PARAMETERS: ValueData - Buffer that contains the binary data
  820. // cbValueData - Number of bytes in the buffer
  821. //------------------------------------------------------------------------------
  822. void PrintBinaryData(PBYTE ValueData, UINT cbValueData)
  823. {
  824. DWORD dwDataIndex;
  825. DWORD dwDataIndex2 = 0; //tracks multiples of 16.
  826. if (cbValueData && ValueData)
  827. {
  828. // Display rows of 16 bytes of data.
  829. TCHAR achAuxData[80];
  830. PrintNewLine();
  831. for(dwDataIndex = 0;
  832. dwDataIndex < ( cbValueData >> 4 );
  833. dwDataIndex++,
  834. dwDataIndex2 = dwDataIndex << 4 )
  835. {
  836. // The string that contains the format in the sprintf below
  837. // cannot be broken because cfront on mips doesn't like it.
  838. wsprintf(achAuxData,
  839. 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"),
  840. dwDataIndex2,
  841. ValueData[ dwDataIndex2 + 0 ],
  842. ValueData[ dwDataIndex2 + 1 ],
  843. ValueData[ dwDataIndex2 + 2 ],
  844. ValueData[ dwDataIndex2 + 3 ],
  845. ValueData[ dwDataIndex2 + 4 ],
  846. ValueData[ dwDataIndex2 + 5 ],
  847. ValueData[ dwDataIndex2 + 6 ],
  848. ValueData[ dwDataIndex2 + 7 ],
  849. ValueData[ dwDataIndex2 + 8 ],
  850. ValueData[ dwDataIndex2 + 9 ],
  851. ValueData[ dwDataIndex2 + 10 ],
  852. ValueData[ dwDataIndex2 + 11 ],
  853. ValueData[ dwDataIndex2 + 12 ],
  854. ValueData[ dwDataIndex2 + 13 ],
  855. ValueData[ dwDataIndex2 + 14 ],
  856. ValueData[ dwDataIndex2 + 15 ],
  857. iswprint( ValueData[ dwDataIndex2 + 0 ] )
  858. ? ValueData[ dwDataIndex2 + 0 ] : TEXT('.'),
  859. iswprint( ValueData[ dwDataIndex2 + 1 ] )
  860. ? ValueData[ dwDataIndex2 + 1 ] : TEXT('.'),
  861. iswprint( ValueData[ dwDataIndex2 + 2 ] )
  862. ? ValueData[ dwDataIndex2 + 2 ] : TEXT('.'),
  863. iswprint( ValueData[ dwDataIndex2 + 3 ] )
  864. ? ValueData[ dwDataIndex2 + 3 ] : TEXT('.'),
  865. iswprint( ValueData[ dwDataIndex2 + 4 ] )
  866. ? ValueData[ dwDataIndex2 + 4 ] : TEXT('.'),
  867. iswprint( ValueData[ dwDataIndex2 + 5 ] )
  868. ? ValueData[ dwDataIndex2 + 5 ] : TEXT('.'),
  869. iswprint( ValueData[ dwDataIndex2 + 6 ] )
  870. ? ValueData[ dwDataIndex2 + 6 ] : TEXT('.'),
  871. iswprint( ValueData[ dwDataIndex2 + 7 ] )
  872. ? ValueData[ dwDataIndex2 + 7 ] : TEXT('.'),
  873. iswprint( ValueData[ dwDataIndex2 + 8 ] )
  874. ? ValueData[ dwDataIndex2 + 8 ] : TEXT('.'),
  875. iswprint( ValueData[ dwDataIndex2 + 9 ] )
  876. ? ValueData[ dwDataIndex2 + 9 ] : TEXT('.'),
  877. iswprint( ValueData[ dwDataIndex2 + 10 ] )
  878. ? ValueData[ dwDataIndex2 + 10 ] : TEXT('.'),
  879. iswprint( ValueData[ dwDataIndex2 + 11 ] )
  880. ? ValueData[ dwDataIndex2 + 11 ] : TEXT('.'),
  881. iswprint( ValueData[ dwDataIndex2 + 12 ] )
  882. ? ValueData[ dwDataIndex2 + 12 ] : TEXT('.'),
  883. iswprint( ValueData[ dwDataIndex2 + 13 ] )
  884. ? ValueData[ dwDataIndex2 + 13 ] : TEXT('.'),
  885. iswprint( ValueData[ dwDataIndex2 + 14 ] )
  886. ? ValueData[ dwDataIndex2 + 14 ] : TEXT('.'),
  887. iswprint( ValueData[ dwDataIndex2 + 15 ] )
  888. ? ValueData[ dwDataIndex2 + 15 ] : TEXT('.'));
  889. PrintLiteral(achAuxData);
  890. PrintNewLine();
  891. }
  892. // If the cbValueData is not an even multiple of 16
  893. // then there is one additonal line of data to display.
  894. if( cbValueData % 16 != 0 )
  895. {
  896. UINT cchBlanks = 0;
  897. UINT uLinePos = 0;
  898. DWORD dwSeperatorChars = 0;
  899. UINT uIndex = wsprintf(achAuxData, TEXT("%08x "), dwDataIndex << 4 );
  900. // Display the remaining data, one byte at a time in hex.
  901. for(dwDataIndex = dwDataIndex2;
  902. dwDataIndex < cbValueData;
  903. dwDataIndex++ )
  904. {
  905. uIndex += wsprintf((achAuxData + uIndex ), TEXT("%02x "), ValueData[dwDataIndex]);
  906. // If eight data values have been displayed, print the seperator.
  907. if( dwDataIndex % 8 == 7 )
  908. {
  909. uIndex += wsprintf( &achAuxData[uIndex], TEXT("%s"), TEXT("- "));
  910. // Remember that two seperator characters were displayed.
  911. dwSeperatorChars = 2;
  912. }
  913. }
  914. // Fill with blanks to the printable characters position.
  915. // That is position 64 less 8 spaces for the 'address',
  916. // 3 blanks, 3 spaces for each value displayed, possibly
  917. // two for the seperator plus two blanks at the end.
  918. uLinePos = (8 + 3 + (( dwDataIndex % 16 ) * 3 ) + dwSeperatorChars + 2 );
  919. uLinePos = min(uLinePos, 64);
  920. for(cchBlanks = 64 - uLinePos;
  921. cchBlanks > 0;
  922. cchBlanks--)
  923. {
  924. achAuxData[uIndex++] = TEXT(' ');
  925. }
  926. // Display the remaining data, one byte at a time as
  927. // printable characters.
  928. for(
  929. dwDataIndex = dwDataIndex2;
  930. dwDataIndex < cbValueData;
  931. dwDataIndex++ )
  932. {
  933. uIndex += wsprintf(&achAuxData[ uIndex ],
  934. TEXT("%c"),
  935. iswprint( ValueData[ dwDataIndex ] )
  936. ? ValueData[ dwDataIndex ] : TEXT('.'));
  937. }
  938. PrintLiteral(achAuxData);
  939. }
  940. }
  941. PrintNewLine();
  942. }
  943. //------------------------------------------------------------------------------
  944. // PrintDWORDData
  945. //
  946. // DESCRIPTION: Prints a DWORD
  947. //
  948. // PARAMETERS: ValueData - Buffer that contains the binary data
  949. // cbValueData - Number of bytes in the buffer
  950. //------------------------------------------------------------------------------
  951. void PrintDWORDData(PBYTE ValueData, UINT cbValueData)
  952. {
  953. DWORD dwData = *((PDWORD)ValueData);
  954. if (cbValueData && ValueData)
  955. {
  956. TCHAR achAuxData[20]; // the largest dword string is only 8 hex digits
  957. wsprintf(achAuxData, TEXT("%#x"), dwData);
  958. PrintLiteral(achAuxData);
  959. }
  960. PrintNewLine();
  961. }
  962. /*******************************************************************************
  963. *
  964. * PrintChar
  965. *
  966. * DESCRIPTION:
  967. *
  968. * PARAMETERS:
  969. *
  970. *******************************************************************************/
  971. BOOL PrintChar(TCHAR Char)
  972. {
  973. //
  974. // Keep track of what column we're currently at. This is useful in cases
  975. // such as writing a large binary registry record. Instead of writing one
  976. // very long line, the other Print* routines can break up their output.
  977. //
  978. if (s_PrintIo.cBufferPos == s_PrintIo.cch) {
  979. PTSTR pNewBuffer = LocalAlloc(LPTR, 2*s_PrintIo.cch*sizeof(TCHAR));
  980. if (pNewBuffer == NULL)
  981. return FALSE;
  982. memcpy(pNewBuffer, s_PrintIo.pLineBuffer, s_PrintIo.cch*sizeof(TCHAR));
  983. LocalFree(s_PrintIo.pLineBuffer);
  984. s_PrintIo.pLineBuffer = pNewBuffer;
  985. s_PrintIo.cch *= 2;
  986. }
  987. s_PrintIo.pLineBuffer[s_PrintIo.cBufferPos++] = Char;
  988. return TRUE;
  989. }
  990. //------------------------------------------------------------------------------
  991. // PrintMultiString
  992. //
  993. // DESCRIPTION: Prints a multi-string
  994. //
  995. // PARAMETERS: pszData - string
  996. // cbData - number of bytes in string, including nulls
  997. //------------------------------------------------------------------------------
  998. VOID PrintMultiString(LPTSTR pszData, int cbData)
  999. {
  1000. if (s_PrintIo.fContinueJob)
  1001. {
  1002. int i = 0;
  1003. int ccData = (cbData / sizeof(TCHAR)) - 2; // don't want last null of last string or multi-string
  1004. for(i = 0; i < ccData; i++)
  1005. {
  1006. if (pszData[i] == TEXT('\0'))
  1007. {
  1008. PrintNewLine();
  1009. PrintDynamicString(IDS_PRINT_KEY_NAME_INDENT);
  1010. }
  1011. else
  1012. {
  1013. PrintChar(pszData[i]);
  1014. }
  1015. }
  1016. }
  1017. PrintNewLine();
  1018. }
  1019. //------------------------------------------------------------------------------
  1020. // PrintNewLine()
  1021. //
  1022. // DESCRIPTION: Prints the newline chars.
  1023. //
  1024. // PARAMETERS: pszData - string
  1025. // cbData - number of bytes in string, including nulls
  1026. //------------------------------------------------------------------------------
  1027. void PrintNewLine()
  1028. {
  1029. PrintLiteral(s_PrintIo.lpNewLineChars);
  1030. }