Leaked source code of windows server 2003
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.

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