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.

1118 lines
27 KiB

  1. /*++
  2. Copyright (C) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. printer.cpp
  5. Abstract:
  6. This module implements CPrinter -- class that support printing
  7. Author:
  8. William Hsieh (williamh) created
  9. Revision History:
  10. --*/
  11. #include "devmgr.h"
  12. #include "printer.h"
  13. #include "cdriver.h"
  14. #include "sysinfo.h"
  15. const TCHAR* const g_BlankLine = TEXT("");
  16. const TCHAR* const g_NewLine = TEXT("\r\n");
  17. const CHAR* const g_NewLineA = "\r\n";
  18. //
  19. // CPrinter Class implementation
  20. //
  21. BOOL CPrinter::s_UserAborted = FALSE;
  22. HWND CPrinter::s_hCancelDlg = NULL;
  23. void
  24. CPrintCancelDialog::OnCommand(
  25. WPARAM wParam,
  26. LPARAM lParam
  27. )
  28. {
  29. if (BN_CLICKED == HIWORD(wParam) && IDCANCEL == LOWORD(wParam)) {
  30. CPrinter::s_UserAborted = TRUE;
  31. }
  32. }
  33. CPrinter::CPrinter(
  34. HWND hwndOwner,
  35. HDC hDC
  36. )
  37. {
  38. m_hwndOwner = hwndOwner;
  39. s_UserAborted = FALSE;
  40. m_hDC = hDC;
  41. ASSERT(hDC);
  42. m_CurLine = 0;
  43. m_CurPage = 0;
  44. m_Indent = 0;
  45. m_Status = 1;
  46. TEXTMETRIC tm;
  47. GetTextMetrics(m_hDC, &tm);
  48. m_yChar = tm.tmHeight + tm.tmExternalLeading;
  49. m_xChar = tm.tmAveCharWidth;
  50. //
  51. // Give a little room for dot matrix printers.
  52. //
  53. m_xMargin = GetDeviceCaps(m_hDC, LOGPIXELSX) * 3 / 4;
  54. DWORD LinesPerPage;
  55. LinesPerPage = GetDeviceCaps(m_hDC, VERTRES) / m_yChar;
  56. m_yBottomMargin = LinesPerPage - 3; // Bottom Margin 3 lines from bottom of page.
  57. m_CancelDlg.DoModaless(hwndOwner, (LPARAM)&m_CancelDlg);
  58. s_hCancelDlg = m_CancelDlg.m_hDlg;
  59. //
  60. // Set the abort proc to allow cancel
  61. //
  62. SetAbortProc(m_hDC, AbortPrintProc);
  63. //
  64. // Four lines for top margin
  65. //
  66. m_yTopMargin = 4;
  67. m_hLogFile = INVALID_HANDLE_VALUE;
  68. }
  69. int
  70. CPrinter::StartDoc(
  71. LPCTSTR DocTitle
  72. )
  73. {
  74. if (m_hDC) {
  75. if (m_hwndOwner) {
  76. ::EnableWindow(m_hwndOwner, FALSE);
  77. }
  78. //
  79. // Initialize DOCINFO
  80. //
  81. DOCINFO DocInfo;
  82. DocInfo.cbSize = sizeof(DocInfo);
  83. TCHAR Temp[MAX_PATH];
  84. lstrcpyn(Temp, DocTitle, ARRAYLEN(Temp));
  85. DocInfo.lpszDocName = Temp;
  86. DocInfo.lpszOutput = NULL;
  87. DocInfo.lpszDatatype = NULL;
  88. DocInfo.fwType = 0;
  89. m_CurPage = 1;
  90. m_CurLine = 0;
  91. m_Status = ::StartDoc(m_hDC, &DocInfo);
  92. }
  93. else {
  94. if (!DocTitle || _T('\0') == *DocTitle) {
  95. m_Status = 0;
  96. }
  97. else {
  98. m_hLogFile = CreateFile(DocTitle,
  99. GENERIC_READ | GENERIC_WRITE,
  100. 0,
  101. NULL,
  102. CREATE_NEW,
  103. FILE_ATTRIBUTE_NORMAL,
  104. NULL);
  105. m_Status = (INVALID_HANDLE_VALUE == m_hLogFile) ? 0 : 1;
  106. }
  107. }
  108. return m_Status;
  109. }
  110. int
  111. CPrinter::EndDoc()
  112. {
  113. if (m_hDC) {
  114. if (m_hwndOwner) {
  115. ::EnableWindow(m_hwndOwner, TRUE);
  116. }
  117. if (s_hCancelDlg) {
  118. DestroyWindow(s_hCancelDlg);
  119. s_hCancelDlg = NULL;
  120. }
  121. if (!s_UserAborted) {
  122. m_Status = ::EndDoc(m_hDC);
  123. }
  124. } else {
  125. m_Status = 1;
  126. if (INVALID_HANDLE_VALUE != m_hLogFile) {
  127. CloseHandle(m_hLogFile);
  128. } else {
  129. m_Status = 0;
  130. }
  131. m_hLogFile = INVALID_HANDLE_VALUE;
  132. }
  133. return m_Status;
  134. }
  135. int
  136. CPrinter::AbortDoc()
  137. {
  138. if (m_hDC) {
  139. if (m_hwndOwner) {
  140. ::EnableWindow(m_hwndOwner, TRUE);
  141. }
  142. if (s_hCancelDlg) {
  143. DestroyWindow(s_hCancelDlg);
  144. s_hCancelDlg = NULL;
  145. }
  146. m_Status = ::AbortDoc(m_hDC);
  147. } else {
  148. m_Status = 1;
  149. if (INVALID_HANDLE_VALUE != m_hLogFile) {
  150. CloseHandle(m_hLogFile);
  151. } else {
  152. m_Status = 0;
  153. }
  154. m_hLogFile = INVALID_HANDLE_VALUE;
  155. }
  156. return m_Status;
  157. }
  158. int
  159. CPrinter::FlushPage()
  160. {
  161. return PrintLine(NULL);
  162. }
  163. int
  164. CPrinter::PrintLine(
  165. LPCTSTR LineText
  166. )
  167. {
  168. if (INVALID_HANDLE_VALUE != m_hLogFile) {
  169. if (LineText) {
  170. DWORD BytesWritten;
  171. if (m_Indent) {
  172. int Count = m_Indent * 2;
  173. CHAR Blanks[MAX_PATH];
  174. for (int i = 0; i < Count; i++) {
  175. Blanks[i] = _T(' ');
  176. }
  177. WriteFile(m_hLogFile, Blanks, Count * sizeof(CHAR), &BytesWritten, NULL);
  178. }
  179. #ifdef UNICODE
  180. int LenW = wcslen(LineText);
  181. CHAR LineTextA[MAX_PATH];
  182. int LenA;
  183. LenA = WideCharToMultiByte(CP_ACP, 0, LineText, LenW, LineTextA, ARRAYLEN(LineTextA), NULL, NULL);
  184. WriteFile(m_hLogFile, LineTextA, LenA * sizeof(CHAR), &BytesWritten, NULL);
  185. WriteFile(m_hLogFile, g_NewLineA, strlen(g_NewLineA) * sizeof(CHAR), &BytesWritten, NULL);
  186. #else
  187. WriteFile(m_hLogFile, LineText, lstrlen(LineText) * sizeof(CHAR), &BytesWritten, NULL);
  188. WriteFike(m_hLogFile, g_NewLine, lstrlen(g_NewLine) * sizeof(CHAR), &BytesWritten, NULL);
  189. #endif
  190. }
  191. }
  192. else {
  193. //
  194. // !LineText means flush the page
  195. //
  196. if ((!LineText && m_CurLine) || (m_CurLine > m_yBottomMargin)) {
  197. m_CurLine = 0;
  198. if (m_Status) {
  199. m_Status = ::EndPage(m_hDC);
  200. }
  201. }
  202. if (LineText) {
  203. //
  204. // If this is the first line and we are still in good shape,
  205. // start a new page
  206. //
  207. if (!m_CurLine && m_Status) {
  208. m_Status = ::StartPage(m_hDC);
  209. if (m_Status) {
  210. TCHAR PageTitle[MAX_PATH];
  211. wsprintf(PageTitle, (LPCTSTR)m_strPageTitle, m_CurPage);
  212. m_CurLine = m_yTopMargin;
  213. TextOut(m_hDC, m_xMargin, m_yChar*m_CurLine, PageTitle, lstrlen(PageTitle));
  214. //
  215. // Have one blank line right after page title
  216. //
  217. LineFeed();
  218. m_CurLine++;
  219. m_CurPage++;
  220. }
  221. }
  222. if (m_Status) {
  223. TextOut(m_hDC, m_xMargin + m_xChar*m_Indent*2, m_yChar*m_CurLine, LineText, lstrlen(LineText));
  224. }
  225. m_CurLine++;
  226. }
  227. }
  228. return m_Status;
  229. }
  230. inline
  231. void
  232. CPrinter::LineFeed()
  233. {
  234. PrintLine(g_BlankLine);
  235. }
  236. // the abort procedure
  237. BOOL CALLBACK
  238. AbortPrintProc(
  239. HDC hDC,
  240. int nCode
  241. )
  242. {
  243. MSG msg;
  244. while (!CPrinter::s_UserAborted && PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  245. if (!IsDialogMessage(CPrinter::s_hCancelDlg, &msg)) {
  246. TranslateMessage(&msg);
  247. DispatchMessage(&msg);
  248. }
  249. }
  250. return !CPrinter::s_UserAborted;
  251. }
  252. //
  253. // This function prints system summary.
  254. // INPUT:
  255. // Machine -- the machine
  256. // OUTPUT:
  257. // 0 -- failed else succeeded.
  258. //
  259. //
  260. int
  261. CPrinter::PrintSystemSummary(
  262. CMachine& Machine
  263. )
  264. {
  265. CSystemInfo SysInfo;
  266. TCHAR Line[MAX_PATH];
  267. TCHAR Buffer[MAX_PATH];
  268. TCHAR Format[MAX_PATH];
  269. TCHAR Unknown[30];
  270. TCHAR szTemp[30];
  271. DWORD Size, BufferSize;
  272. BufferSize = ARRAYLEN(Buffer);
  273. //
  274. // Preload the "Unknown" string which will be used as default when
  275. // the corresponding value can not found
  276. //
  277. LoadString(g_hInstance, IDS_PRINT_UNKNOWN, Unknown, ARRAYLEN(Unknown));
  278. //
  279. // Print System summary heading
  280. //
  281. LoadString(g_hInstance, IDS_PRINT_HEADING_SYSSUMMARY, Buffer, ARRAYLEN(Buffer));
  282. LoadString(g_hInstance, IDS_PRINT_BANNER, Format, ARRAYLEN(Format));
  283. wsprintf(Line, Format, Buffer);
  284. PrintLine(Line);
  285. LineFeed();
  286. //
  287. // Windows version
  288. //
  289. LoadString(g_hInstance, IDS_PRINT_WINVER, Line, ARRAYLEN(Line));
  290. Size = SysInfo.WindowsVersion(Buffer, BufferSize);
  291. lstrcat(Line, Size ? Buffer : Unknown);
  292. PrintLine(Line);
  293. //
  294. // Registered Owner
  295. //
  296. LoadString(g_hInstance, IDS_PRINT_OWNER, Line, ARRAYLEN(Line));
  297. Size = SysInfo.RegisteredOwner(Buffer, BufferSize);
  298. lstrcat(Line, Size ? Buffer : Unknown);
  299. PrintLine(Line);
  300. //
  301. // Registered Organization
  302. //
  303. LoadString(g_hInstance, IDS_PRINT_ORGANIZATION, Line, ARRAYLEN(Line));
  304. Size = SysInfo.RegisteredOrganization(Buffer, BufferSize);
  305. lstrcat(Line, Size ? Buffer : Unknown);
  306. PrintLine(Line);
  307. //
  308. // Computer name
  309. //
  310. LoadString(g_hInstance, IDS_PRINT_COMPUTERNAME, Line, ARRAYLEN(Line));
  311. lstrcat(Line, SysInfo.ComputerName());
  312. PrintLine(Line);
  313. //
  314. // Machine Type
  315. //
  316. LoadString(g_hInstance, IDS_PRINT_MACHINE_TYPE, Line, ARRAYLEN(Line));
  317. Size = SysInfo.MachineType(Buffer, BufferSize);
  318. lstrcat(Line, Size ? Buffer : Unknown);
  319. PrintLine(Line);
  320. //
  321. // System BIOS Version
  322. //
  323. LoadString(g_hInstance, IDS_PRINT_SYSBIOS_VERSION, Line, ARRAYLEN(Line));
  324. Size = SysInfo.SystemBiosVersion(Buffer, BufferSize);
  325. lstrcat(Line, Size ? Buffer : Unknown);
  326. PrintLine(Line);
  327. //
  328. // System BIOS Date
  329. //
  330. LoadString(g_hInstance, IDS_PRINT_SYSBIOS_DATE, Line, ARRAYLEN(Line));
  331. Size = SysInfo.SystemBiosDate(Buffer, BufferSize);
  332. lstrcat(Line, Size ? Buffer : Unknown);
  333. PrintLine(Line);
  334. //
  335. // Processor type
  336. //
  337. LoadString(g_hInstance, IDS_PRINT_PROCESSOR_TYPE, Line, ARRAYLEN(Line));
  338. Size = SysInfo.ProcessorType(Buffer, BufferSize);
  339. lstrcat(Line, Size ? Buffer : Unknown);
  340. PrintLine(Line);
  341. //
  342. // Processor vendor
  343. //
  344. LoadString(g_hInstance, IDS_PRINT_PROCESSOR_VENDOR, Line, ARRAYLEN(Line));
  345. Size = SysInfo.ProcessorVendor(Buffer, BufferSize);
  346. lstrcat(Line, Size ? Buffer : Unknown);
  347. PrintLine(Line);
  348. //
  349. // Number of processors
  350. //
  351. LoadString(g_hInstance, IDS_PRINT_PROCESSORS, Line, ARRAYLEN(Line));
  352. DWORD NumProcessors = SysInfo.NumberOfProcessors();
  353. if (NumProcessors) {
  354. wsprintf(Buffer, TEXT("%u"), NumProcessors);
  355. lstrcat(Line, Buffer);
  356. } else {
  357. lstrcat(Line, Unknown);
  358. }
  359. PrintLine(Line);
  360. //
  361. // Total physical memory
  362. //
  363. ULARGE_INTEGER MemorySize;
  364. SysInfo.TotalPhysicalMemory(MemorySize);
  365. LoadString(g_hInstance, IDS_PRINT_PHY_MEMORY, Line, ARRAYLEN(Line));
  366. if (MemorySize.QuadPart) {
  367. LoadString(g_hInstance, IDS_PRINT_MEMORY_UNIT, Format, ARRAYLEN(Format));
  368. MemorySize.QuadPart += 1024*1024 - 1;
  369. wsprintf(Buffer, Format, Int64ShrlMod32(MemorySize.QuadPart, 20));
  370. lstrcat(Line, Buffer);
  371. } else {
  372. lstrcat(Line, Unknown);
  373. }
  374. PrintLine(Line);
  375. LineFeed();
  376. //
  377. // Local disk drive information
  378. //
  379. // Print Disk info summary heading
  380. //
  381. LoadString(g_hInstance, IDS_PRINT_HEADING_DISKINFO, Buffer, ARRAYLEN(Buffer));
  382. LoadString(g_hInstance, IDS_PRINT_BANNER, Format, ARRAYLEN(Format));
  383. wsprintf(Line, Format, Buffer);
  384. PrintLine(Line);
  385. LineFeed();
  386. DISK_INFO DiskInfo;
  387. DiskInfo.cbSize = sizeof(DiskInfo);
  388. for(int Drive = 0; Drive < 25; Drive++) {
  389. // information we want to report on the drive:
  390. // (1). drive letter and type
  391. // (2). Total space
  392. // (3). Free space(if available)
  393. // (4). Cylinders
  394. // (5). Heads
  395. // (6). Sectors per track
  396. // (7). Bytes per sector
  397. Indent();
  398. if(SysInfo.GetDiskInfo(Drive, DiskInfo)) {
  399. TCHAR DriveLetter;
  400. DriveLetter = Drive + _T('A');
  401. LoadString(g_hInstance, IDS_PRINT_DRIVE_LETTER, Format, ARRAYLEN(Format));
  402. wsprintf(Line, Format, DriveLetter);
  403. PrintLine(Line);
  404. Indent();
  405. //
  406. // Drive type
  407. //
  408. LoadString(g_hInstance, IDS_PRINT_DRIVE_TYPE, Format, ARRAYLEN(Format));
  409. int StringId;
  410. LoadString(g_hInstance,
  411. IDS_MEDIA_BASE + (int)DiskInfo.MediaType,
  412. Buffer, ARRAYLEN(Buffer));
  413. wsprintf(Line, Format, Buffer);
  414. PrintLine(Line);
  415. //
  416. //Total and free space
  417. //
  418. LoadString(g_hInstance, IDS_PRINT_TOTAL_SPACE, Format, ARRAYLEN(Format));
  419. wsprintf(Line, Format, AddCommas64(DiskInfo.TotalSpace.QuadPart, szTemp, ARRAYLEN(szTemp)));
  420. PrintLine(Line);
  421. if (-1 != DiskInfo.FreeSpace.QuadPart) {
  422. LoadString(g_hInstance, IDS_PRINT_FREE_SPACE, Format, ARRAYLEN(Format));
  423. wsprintf(Line, Format, AddCommas64(DiskInfo.FreeSpace.QuadPart, szTemp, ARRAYLEN(szTemp)));
  424. PrintLine(Line);
  425. }
  426. //
  427. // Disk physical dimension
  428. // skip CD-ROM because the dimension it reports is bogus
  429. //
  430. if (DRIVE_CDROM != DiskInfo.DriveType) {
  431. //
  432. // Heads
  433. //
  434. LoadString(g_hInstance, IDS_PRINT_HEADS, Format, ARRAYLEN(Format));
  435. wsprintf(Line, Format, DiskInfo.Heads);
  436. PrintLine(Line);
  437. //
  438. // Cylinders
  439. //
  440. if (DiskInfo.Cylinders.HighPart) {
  441. LoadString(g_hInstance, IDS_PRINT_CYLINDERS_XL, Format, ARRAYLEN(Format));
  442. wsprintf(Line, Format, DiskInfo.Cylinders.HighPart,
  443. DiskInfo.Cylinders.LowPart);
  444. PrintLine(Line);
  445. } else {
  446. LoadString(g_hInstance, IDS_PRINT_CYLINDERS, Format, ARRAYLEN(Format));
  447. wsprintf(Line, Format, DiskInfo.Cylinders.LowPart);
  448. PrintLine(Line);
  449. }
  450. //
  451. // Sectors per track
  452. //
  453. LoadString(g_hInstance, IDS_PRINT_TRACKSIZE, Format, ARRAYLEN(Format));
  454. wsprintf(Line, Format, DiskInfo.SectorsPerTrack);
  455. PrintLine(Line);
  456. //
  457. // Bytes per sector
  458. //
  459. LoadString(g_hInstance, IDS_PRINT_SECTORSIZE, Format, ARRAYLEN(Format));
  460. wsprintf(Line, Format, DiskInfo.BytesPerSector);
  461. PrintLine(Line);
  462. }
  463. UnIndent();
  464. LineFeed();
  465. }
  466. UnIndent();
  467. }
  468. return 1;
  469. }
  470. int
  471. CPrinter::PrintResourceSummary(
  472. CMachine& Machine
  473. )
  474. {
  475. TCHAR Temp[MAX_PATH];
  476. CResource* pResource;
  477. String str;
  478. String strBanner;
  479. PrintSystemSummary(Machine);
  480. //
  481. // print IRQ summary heading
  482. //
  483. str.LoadString(g_hInstance, IDS_PRINT_HEADING_IRQSUMMARY);
  484. strBanner.LoadString(g_hInstance, IDS_PRINT_BANNER);
  485. wsprintf(Temp, (LPCTSTR)strBanner, (LPCTSTR)str);
  486. PrintLine(Temp);
  487. LineFeed();
  488. CResourceList IrqSummary(&Machine, ResType_IRQ);
  489. if (IrqSummary.GetCount()) {
  490. CResource* pResRoot;
  491. IrqSummary.CreateResourceTree(&pResRoot);
  492. str.LoadString(g_hInstance, IDS_PRINT_IRQSUM);
  493. PrintLine(str);
  494. Indent();
  495. PrintResourceSubtree(pResRoot);
  496. UnIndent();
  497. LineFeed();
  498. }
  499. //
  500. // print DMA summary heading
  501. //
  502. str.LoadString(g_hInstance, IDS_PRINT_HEADING_DMASUMMARY);
  503. wsprintf(Temp, (LPCTSTR)strBanner, (LPCTSTR)str);
  504. PrintLine(Temp);
  505. LineFeed();
  506. CResourceList DmaSummary(&Machine, ResType_DMA);
  507. if (DmaSummary.GetCount()) {
  508. CResource* pResRoot;
  509. DmaSummary.CreateResourceTree(&pResRoot);
  510. str.LoadString(g_hInstance, IDS_PRINT_DMASUM);
  511. PrintLine(str);
  512. Indent();
  513. PrintResourceSubtree(pResRoot);
  514. UnIndent();
  515. LineFeed();
  516. }
  517. //
  518. // print MEM summary heading
  519. //
  520. str.LoadString(g_hInstance, IDS_PRINT_HEADING_MEMSUMMARY);
  521. wsprintf(Temp, (LPCTSTR)strBanner, (LPCTSTR)str);
  522. PrintLine(Temp);
  523. LineFeed();
  524. CResourceList MemSummary(&Machine, ResType_Mem);
  525. if (MemSummary.GetCount()) {
  526. CResource* pResRoot;
  527. MemSummary.CreateResourceTree(&pResRoot);
  528. str.LoadString(g_hInstance, IDS_PRINT_MEMSUM);
  529. PrintLine(str);
  530. Indent();
  531. PrintResourceSubtree(pResRoot);
  532. UnIndent();
  533. LineFeed();
  534. }
  535. //
  536. // print IO summary heading
  537. //
  538. str.LoadString(g_hInstance, IDS_PRINT_HEADING_IOSUMMARY);
  539. wsprintf(Temp, (LPCTSTR)strBanner, (LPCTSTR)str);
  540. PrintLine(Temp);
  541. LineFeed();
  542. CResourceList IoSummary(&Machine, ResType_IO);
  543. if (IoSummary.GetCount()) {
  544. CResource* pResRoot;
  545. IoSummary.CreateResourceTree(&pResRoot);
  546. str.LoadString(g_hInstance, IDS_PRINT_IOSUM);
  547. PrintLine(str);
  548. Indent();
  549. PrintResourceSubtree(pResRoot);
  550. UnIndent();
  551. LineFeed();
  552. }
  553. return 1;
  554. }
  555. int
  556. CPrinter::PrintResourceSubtree(
  557. CResource* pResRoot
  558. )
  559. {
  560. while (pResRoot)
  561. {
  562. DWORD Status, Problem;
  563. if (pResRoot->m_pDevice->GetStatus(&Status, &Problem) && Problem ||
  564. pResRoot->m_pDevice->IsDisabled()) {
  565. TCHAR Temp[MAX_PATH];
  566. Temp[0] = _T('*');
  567. lstrcpy(&Temp[1], pResRoot->GetViewName());
  568. PrintLine(Temp);
  569. } else {
  570. PrintLine(pResRoot->GetViewName());
  571. }
  572. if (pResRoot->GetChild()) {
  573. if ((ResType_IO == pResRoot->ResType()) ||
  574. (ResType_Mem == pResRoot->ResType())) {
  575. Indent();
  576. }
  577. PrintResourceSubtree(pResRoot->GetChild());
  578. if ((ResType_IO == pResRoot->ResType()) ||
  579. (ResType_Mem == pResRoot->ResType())) {
  580. UnIndent();
  581. }
  582. }
  583. pResRoot = pResRoot->GetSibling();
  584. }
  585. return 1;
  586. }
  587. int
  588. CPrinter::PrintAllClassAndDevice(
  589. CMachine* pMachine
  590. )
  591. {
  592. if (!pMachine) {
  593. return 0;
  594. }
  595. String strHeading;
  596. String strBanner;
  597. TCHAR Temp[MAX_PATH];
  598. strHeading.LoadString(g_hInstance, IDS_PRINT_HEADING_SYSDEVINFO);
  599. strBanner.LoadString(g_hInstance, IDS_PRINT_BANNER);
  600. wsprintf(Temp, (LPCTSTR)strBanner, (LPCTSTR)strHeading);
  601. PrintLine(Temp);
  602. LineFeed();
  603. CClass* pClass;
  604. PVOID Context;
  605. if (pMachine->GetFirstClass(&pClass, Context)) {
  606. do {
  607. PrintClass(pClass, FALSE);
  608. } while (pMachine->GetNextClass(&pClass, Context));
  609. }
  610. return 1;
  611. }
  612. int
  613. CPrinter::PrintClass(
  614. CClass* pClass,
  615. BOOL PrintBanner
  616. )
  617. {
  618. PVOID Context;
  619. CDevice* pDevice;
  620. if (!pClass) {
  621. return 0;
  622. }
  623. if (PrintBanner) {
  624. String strHeading;
  625. String strBanner;
  626. TCHAR Temp[MAX_PATH];
  627. strHeading.LoadString(g_hInstance, IDS_PRINT_HEADING_SYSDEVCLASS);
  628. strBanner.LoadString(g_hInstance, IDS_PRINT_BANNER);
  629. wsprintf(Temp, (LPCTSTR)strBanner, (LPCTSTR)strHeading);
  630. PrintLine(Temp);
  631. LineFeed();
  632. }
  633. if (pClass && pClass->GetFirstDevice(&pDevice, Context)) {
  634. do {
  635. //
  636. // Do print banner on the device
  637. //
  638. PrintDevice(pDevice, FALSE);
  639. } while (pClass->GetNextDevice(&pDevice, Context));
  640. }
  641. return 1;
  642. }
  643. int
  644. CPrinter::PrintDevice(
  645. CDevice* pDevice,
  646. BOOL PrintBanner
  647. )
  648. {
  649. if (!pDevice) {
  650. return 0;
  651. }
  652. String str;
  653. TCHAR Temp[MAX_PATH];
  654. if (PrintBanner) {
  655. String strBanner;
  656. str.LoadString(g_hInstance, IDS_PRINT_HEADING_SYSDEVICE);
  657. strBanner.LoadString(g_hInstance, IDS_PRINT_BANNER);
  658. wsprintf(Temp, (LPCTSTR)strBanner, (LPCTSTR)str);
  659. PrintLine(Temp);
  660. LineFeed();
  661. }
  662. DWORD Status, Problem;
  663. if (pDevice->GetStatus(&Status, &Problem) && Problem ||
  664. pDevice->IsDisabled()) {
  665. LoadString(g_hInstance, IDS_PRINT_DEVICE_DISABLED, Temp, ARRAYLEN(Temp));
  666. PrintLine(Temp);
  667. }
  668. str.LoadString(g_hInstance, IDS_PRINT_CLASS);
  669. wsprintf(Temp, (LPCTSTR)str, pDevice->GetClassDisplayName());
  670. PrintLine(Temp);
  671. str.LoadString(g_hInstance, IDS_PRINT_DEVICE);
  672. wsprintf(Temp, (LPCTSTR)str, pDevice->GetDisplayName());
  673. PrintLine(Temp);
  674. PrintDeviceResource(pDevice);
  675. PrintDeviceDriver(pDevice);
  676. return 1;
  677. }
  678. int
  679. CPrinter::PrintAll(
  680. CMachine& Machine
  681. )
  682. {
  683. PrintResourceSummary(Machine);
  684. PrintAllClassAndDevice(&Machine);
  685. return 1;
  686. }
  687. //
  688. // This function prints the given device's resource summary
  689. //
  690. int
  691. CPrinter::PrintDeviceResource(
  692. CDevice* pDevice
  693. )
  694. {
  695. if (!pDevice) {
  696. return 0;
  697. }
  698. CResourceList IrqSummary(pDevice, ResType_IRQ);
  699. CResourceList DmaSummary(pDevice, ResType_DMA);
  700. CResourceList MemSummary(pDevice, ResType_Mem);
  701. CResourceList IoSummary(pDevice, ResType_IO);
  702. String str;
  703. TCHAR Temp[MAX_PATH];
  704. //
  705. // If the device has any kind of resources, print it
  706. //
  707. if (IrqSummary.GetCount() || DmaSummary.GetCount() ||
  708. MemSummary.GetCount() || IoSummary.GetCount()) {
  709. str.LoadString(g_hInstance, IDS_PRINT_RESOURCE);
  710. PrintLine(str);
  711. //
  712. // Start printing individual resources
  713. //
  714. Indent();
  715. PVOID Context;
  716. CResource* pResource;
  717. DWORDLONG dlBase, dlLen;
  718. TCHAR Format[MAX_PATH];
  719. if (IrqSummary.GetFirst(&pResource, Context)) {
  720. LoadString(g_hInstance, IDS_PRINT_IRQ_FORMAT, Temp, ARRAYLEN(Temp));
  721. do {
  722. pResource->GetValue(&dlBase, &dlLen);
  723. str.Format(Temp, (ULONG)dlBase);
  724. PrintLine((LPCTSTR)str);
  725. } while (IrqSummary.GetNext(&pResource, Context));
  726. }
  727. if (DmaSummary.GetFirst(&pResource, Context)) {
  728. LoadString(g_hInstance, IDS_PRINT_DMA_FORMAT, Temp, ARRAYLEN(Temp));
  729. do {
  730. pResource->GetValue(&dlBase, &dlLen);
  731. str.Format(Temp, (ULONG)dlBase);
  732. PrintLine((LPCTSTR)str);
  733. } while (DmaSummary.GetNext(&pResource, Context));
  734. }
  735. if (MemSummary.GetFirst(&pResource, Context)) {
  736. LoadString(g_hInstance, IDS_PRINT_MEM_FORMAT, Temp, ARRAYLEN(Temp));
  737. do {
  738. pResource->GetValue(&dlBase, &dlLen);
  739. str.Format(Temp, (ULONG)dlBase, (ULONG)(dlBase + dlLen - 1));
  740. PrintLine((LPCTSTR)str);
  741. } while (MemSummary.GetNext(&pResource, Context));
  742. }
  743. if (IoSummary.GetFirst(&pResource, Context)) {
  744. LoadString(g_hInstance, IDS_PRINT_IO_FORMAT, Temp, ARRAYLEN(Temp));
  745. do {
  746. pResource->GetValue(&dlBase, &dlLen);
  747. str.Format(Temp, (ULONG)dlBase, (ULONG)(dlBase + dlLen -1));
  748. PrintLine((LPCTSTR)str);
  749. } while (IoSummary.GetNext(&pResource, Context));
  750. }
  751. UnIndent();
  752. } else {
  753. str.LoadString(g_hInstance, IDS_PRINT_NORES);
  754. PrintLine(str);
  755. }
  756. return 1;
  757. }
  758. //
  759. // This function prints the given device's driver information
  760. // INPUT:
  761. // pDevice -- the device
  762. // OUTPUT:
  763. // >0 if the function succeeded.
  764. // 0 if the function failed.
  765. //
  766. int
  767. CPrinter::PrintDeviceDriver(
  768. CDevice* pDevice
  769. )
  770. {
  771. if (!pDevice) {
  772. return 0;
  773. }
  774. String str;
  775. TCHAR Temp[MAX_PATH];
  776. CDriver* pDriver;
  777. pDriver = pDevice->CreateDriver();
  778. SafePtr<CDriver> DrvPtr;
  779. if (pDriver) {
  780. DrvPtr.Attach(pDriver);
  781. str.LoadString(g_hInstance, IDS_PRINT_DRVINFO);
  782. PrintLine(str);
  783. PVOID Context;
  784. CDriverFile* pDrvFile;
  785. Indent();
  786. if (pDriver->GetFirstDriverFile(&pDrvFile, Context)) {
  787. do {
  788. PrintLine(pDrvFile->GetFullPathName());
  789. HANDLE hFile;
  790. Indent();
  791. hFile = CreateFile(pDrvFile->GetFullPathName(),
  792. GENERIC_READ,
  793. 0,
  794. NULL,
  795. OPEN_EXISTING,
  796. FILE_ATTRIBUTE_NORMAL |
  797. FILE_ATTRIBUTE_READONLY |
  798. FILE_ATTRIBUTE_SYSTEM |
  799. FILE_ATTRIBUTE_HIDDEN,
  800. NULL
  801. );
  802. if (INVALID_HANDLE_VALUE != hFile) {
  803. DWORD FileSize;
  804. FileSize = ::GetFileSize(hFile, NULL);
  805. CloseHandle(hFile);
  806. LoadString(g_hInstance, IDS_PRINT_FILESIZE, Temp, ARRAYLEN(Temp));
  807. str.Format(Temp, FileSize);
  808. PrintLine(str);
  809. // print the driver version infomation
  810. TCHAR Unknown[MAX_PATH];
  811. LoadString(g_hInstance, IDS_PRINT_UNKNOWN, Unknown, ARRAYLEN(Unknown));
  812. if (pDrvFile->HasVersionInfo()) {
  813. LoadString(g_hInstance, IDS_PRINT_FILEVERSION, Temp, ARRAYLEN(Temp));
  814. if (pDrvFile->GetVersion()) {
  815. str.Format(Temp, pDrvFile->GetVersion());
  816. } else {
  817. str.Format(Temp, Unknown);
  818. }
  819. PrintLine(str);
  820. LoadString(g_hInstance, IDS_PRINT_FILEMFG, Temp, ARRAYLEN(Temp));
  821. if (pDrvFile->GetProvider()) {
  822. str.Format(Temp, pDrvFile->GetProvider());
  823. } else {
  824. str.Format(Temp, Unknown);
  825. }
  826. PrintLine(str);
  827. LoadString(g_hInstance, IDS_PRINT_FILECOPYRIGHT, Temp, ARRAYLEN(Temp));
  828. if (pDrvFile->GetCopyright()) {
  829. str.Format(Temp, pDrvFile->GetCopyright());
  830. } else {
  831. str.Format(Temp, Unknown);
  832. }
  833. PrintLine(str);
  834. } else {
  835. str.LoadString(g_hInstance, IDS_PRINT_NOVERSION);
  836. PrintLine(str);
  837. }
  838. } else {
  839. str.LoadString(g_hInstance, IDS_PRINT_DRVMISSING);
  840. PrintLine(str);
  841. }
  842. UnIndent();
  843. } while (pDriver->GetNextDriverFile(&pDrvFile, Context));
  844. }
  845. UnIndent();
  846. }
  847. LineFeed();
  848. return 1;
  849. }