/*++ Copyright (C) Microsoft Corporation Module Name: printer.cpp Abstract: This module implements CPrinter -- class that support printing Author: William Hsieh (williamh) created Revision History: --*/ #include "devmgr.h" #include "printer.h" #include "cdriver.h" #include "sysinfo.h" const TCHAR* const g_BlankLine = TEXT(""); // // CPrinter Class implementation // BOOL CPrinter::s_UserAborted = FALSE; HWND CPrinter::s_hCancelDlg = NULL; void CPrintCancelDialog::OnCommand( WPARAM wParam, LPARAM lParam ) { UNREFERENCED_PARAMETER(lParam); if (BN_CLICKED == HIWORD(wParam) && IDCANCEL == LOWORD(wParam)) { CPrinter::s_UserAborted = TRUE; } } CPrinter::CPrinter( HWND hwndOwner, HDC hDC ) { m_hwndOwner = hwndOwner; s_UserAborted = FALSE; m_hDC = hDC; ASSERT(hDC); m_CurLine = 0; m_CurPage = 0; m_Indent = 0; m_Status = 1; TEXTMETRIC tm; GetTextMetrics(m_hDC, &tm); m_yChar = tm.tmHeight + tm.tmExternalLeading; m_xChar = tm.tmAveCharWidth; // // Give a little room for dot matrix printers. // m_xMargin = GetDeviceCaps(m_hDC, LOGPIXELSX) * 3 / 4; DWORD LinesPerPage; LinesPerPage = GetDeviceCaps(m_hDC, VERTRES) / m_yChar; m_yBottomMargin = LinesPerPage - 3; // Bottom Margin 3 lines from bottom of page. m_CancelDlg.DoModaless(hwndOwner, (LPARAM)&m_CancelDlg); s_hCancelDlg = m_CancelDlg.m_hDlg; // // Set the abort proc to allow cancel // SetAbortProc(m_hDC, AbortPrintProc); // // Four lines for top margin // m_yTopMargin = 4; } int CPrinter::StartDoc( LPCTSTR DocTitle ) { m_Status = 0; if (m_hDC) { if (m_hwndOwner) { ::EnableWindow(m_hwndOwner, FALSE); } // // Initialize DOCINFO // DOCINFO DocInfo; DocInfo.cbSize = sizeof(DocInfo); DocInfo.lpszDocName = DocTitle; DocInfo.lpszOutput = NULL; DocInfo.lpszDatatype = NULL; DocInfo.fwType = 0; m_CurPage = 1; m_CurLine = 0; m_Status = ::StartDoc(m_hDC, &DocInfo); } return m_Status; } int CPrinter::EndDoc() { m_Status = 0; if (m_hDC) { if (m_hwndOwner) { ::EnableWindow(m_hwndOwner, TRUE); } if (s_hCancelDlg) { DestroyWindow(s_hCancelDlg); s_hCancelDlg = NULL; } if (!s_UserAborted) { m_Status = ::EndDoc(m_hDC); } } return m_Status; } int CPrinter::AbortDoc() { m_Status = 0; if (m_hDC) { if (m_hwndOwner) { ::EnableWindow(m_hwndOwner, TRUE); } if (s_hCancelDlg) { DestroyWindow(s_hCancelDlg); s_hCancelDlg = NULL; } m_Status = ::AbortDoc(m_hDC); } return m_Status; } int CPrinter::FlushPage() { return PrintLine(NULL); } int CPrinter::PrintLine( LPCTSTR LineText ) { // // NULL LineText means flush the page // if ((!LineText && m_CurLine) || (m_CurLine > m_yBottomMargin)) { m_CurLine = 0; if (m_Status) { m_Status = ::EndPage(m_hDC); } } if (LineText) { // // If this is the first line and we are still in good shape, // start a new page // if (!m_CurLine && m_Status) { m_Status = ::StartPage(m_hDC); if (m_Status) { String strPageTitle; strPageTitle.Format((LPCTSTR)m_strPageTitle, m_CurPage); m_CurLine = m_yTopMargin; TextOut(m_hDC, m_xMargin, m_yChar*m_CurLine, (LPTSTR)strPageTitle, strPageTitle.GetLength()); // // Have one blank line right after page title // LineFeed(); m_CurLine++; m_CurPage++; } } if (m_Status) { TextOut(m_hDC, m_xMargin + m_xChar*m_Indent*2, m_yChar*m_CurLine, LineText, lstrlen(LineText)); } m_CurLine++; } return m_Status; } inline void CPrinter::LineFeed() { PrintLine(g_BlankLine); } // the abort procedure BOOL CALLBACK AbortPrintProc( HDC hDC, int nCode ) { MSG msg; UNREFERENCED_PARAMETER(hDC); UNREFERENCED_PARAMETER(nCode); while (!CPrinter::s_UserAborted && PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (!IsDialogMessage(CPrinter::s_hCancelDlg, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return !CPrinter::s_UserAborted; } // // This function prints system summary. // INPUT: // Machine -- the machine // OUTPUT: // 0 -- failed else succeeded. // // int CPrinter::PrintSystemSummary( void ) { CSystemInfo SysInfo; String strLine; String strFormat; String strBuffer; String strUnknown; TCHAR Buffer[MAX_PATH]; TCHAR szTemp[30]; DWORD Size, BufferSize; BufferSize = ARRAYLEN(Buffer); // // Preload the "Unknown" string which will be used as default when // the corresponding value can not found // strUnknown.LoadString(g_hInstance, IDS_PRINT_UNKNOWN); // // Print System summary heading // LoadString(g_hInstance, IDS_PRINT_HEADING_SYSSUMMARY, Buffer, ARRAYLEN(Buffer)); strFormat.LoadString(g_hInstance, IDS_PRINT_BANNER); strLine.Format((LPCTSTR)strFormat, Buffer); PrintLine((LPCTSTR)strLine); LineFeed(); // // Windows version // strLine.LoadString(g_hInstance, IDS_PRINT_WINVER); Size = SysInfo.WindowsVersion(Buffer, BufferSize); strLine += Size ? (LPCTSTR)Buffer : strUnknown; PrintLine((LPCTSTR)strLine); // // Registered Owner // strLine.LoadString(g_hInstance, IDS_PRINT_OWNER); Size = SysInfo.RegisteredOwner(Buffer, BufferSize); strLine += Size ? (LPCTSTR)Buffer : strUnknown; PrintLine((LPCTSTR)strLine); // // Registered Organization // strLine.LoadString(g_hInstance, IDS_PRINT_ORGANIZATION); Size = SysInfo.RegisteredOrganization(Buffer, BufferSize); strLine += Size ? (LPCTSTR)Buffer : strUnknown; PrintLine((LPCTSTR)strLine); // // Computer name // strLine.LoadString(g_hInstance, IDS_PRINT_COMPUTERNAME); strLine += (LPCTSTR)SysInfo.ComputerName(); PrintLine((LPCTSTR)strLine); // // Machine Type // strLine.LoadString(g_hInstance, IDS_PRINT_MACHINE_TYPE); Size = SysInfo.MachineType(Buffer, BufferSize); strLine += Size ? (LPCTSTR)Buffer : strUnknown; PrintLine((LPCTSTR)strLine); // // System BIOS Version // strLine.LoadString(g_hInstance, IDS_PRINT_SYSBIOS_VERSION); Size = SysInfo.SystemBiosVersion(Buffer, BufferSize); strLine += Size ? (LPCTSTR)Buffer : strUnknown; PrintLine((LPCTSTR)strLine); // // System BIOS Date // strLine.LoadString(g_hInstance, IDS_PRINT_SYSBIOS_DATE); Size = SysInfo.SystemBiosDate(Buffer, BufferSize); strLine += Size ? (LPCTSTR)Buffer : strUnknown; PrintLine((LPCTSTR)strLine); // // Processor type // strLine.LoadString(g_hInstance, IDS_PRINT_PROCESSOR_TYPE); Size = SysInfo.ProcessorType(Buffer, BufferSize); strLine += Size ? (LPCTSTR)Buffer : strUnknown; PrintLine((LPCTSTR)strLine); // // Processor vendor // strLine.LoadString(g_hInstance, IDS_PRINT_PROCESSOR_VENDOR); Size = SysInfo.ProcessorVendor(Buffer, BufferSize); strLine += Size ? (LPCTSTR)Buffer : strUnknown; PrintLine((LPCTSTR)strLine); // // Number of processors // strLine.LoadString(g_hInstance, IDS_PRINT_PROCESSORS); DWORD NumProcessors = SysInfo.NumberOfProcessors(); if (NumProcessors) { strFormat.Format(TEXT("%u"), NumProcessors); strLine += strFormat; } else { strLine += strUnknown; } PrintLine((LPCTSTR)strLine); // // Total physical memory // ULARGE_INTEGER MemorySize; SysInfo.TotalPhysicalMemory(MemorySize); strLine.LoadString(g_hInstance, IDS_PRINT_PHY_MEMORY); if (MemorySize.QuadPart) { strFormat.LoadString(g_hInstance, IDS_PRINT_MEMORY_UNIT); MemorySize.QuadPart += 1024*1024 - 1; strBuffer.Format((LPCTSTR)strFormat, Int64ShrlMod32(MemorySize.QuadPart, 20)); strLine += strBuffer; } else { strLine += strUnknown; } PrintLine((LPCTSTR)strLine); LineFeed(); // // Local disk drive information // // Print Disk info summary heading // strBuffer.LoadString(g_hInstance, IDS_PRINT_HEADING_DISKINFO); strFormat.LoadString(g_hInstance, IDS_PRINT_BANNER); strLine.Format((LPCTSTR)strFormat, (LPCTSTR)strBuffer); PrintLine((LPCTSTR)strLine); LineFeed(); DISK_INFO DiskInfo; DiskInfo.cbSize = sizeof(DiskInfo); for(int Drive = 0; Drive < 25; Drive++) { // information we want to report on the drive: // (1). drive letter and type // (2). Total space // (3). Free space(if available) // (4). Cylinders // (5). Heads // (6). Sectors per track // (7). Bytes per sector Indent(); if(SysInfo.GetDiskInfo(Drive, DiskInfo)) { TCHAR DriveLetter; DriveLetter = (TCHAR)(Drive + _T('A')); strFormat.LoadString(g_hInstance, IDS_PRINT_DRIVE_LETTER); strLine.Format((LPCTSTR)strFormat, DriveLetter); PrintLine((LPCTSTR)strLine); Indent(); // // Drive type // strFormat.LoadString(g_hInstance, IDS_PRINT_DRIVE_TYPE); strBuffer.LoadString(g_hInstance, IDS_MEDIA_BASE + (int)DiskInfo.MediaType); strLine.Format((LPCTSTR)strFormat, (LPCTSTR)strBuffer); PrintLine((LPCTSTR)strLine); // //Total and free space // strFormat.LoadString(g_hInstance, IDS_PRINT_TOTAL_SPACE); strLine.Format((LPCTSTR)strFormat, AddCommas64(DiskInfo.TotalSpace.QuadPart, szTemp, ARRAYLEN(szTemp))); PrintLine((LPCTSTR)strLine); if (-1 != DiskInfo.FreeSpace.QuadPart) { strFormat.LoadString(g_hInstance, IDS_PRINT_FREE_SPACE); strLine.Format((LPCTSTR)strFormat, AddCommas64(DiskInfo.FreeSpace.QuadPart, szTemp, ARRAYLEN(szTemp))); PrintLine((LPCTSTR)strLine); } // // Disk physical dimension // skip CD-ROM because the dimension it reports is bogus // if (DRIVE_CDROM != DiskInfo.DriveType) { // // Heads // strFormat.LoadString(g_hInstance, IDS_PRINT_HEADS); strLine.Format((LPCTSTR)strFormat, DiskInfo.Heads); PrintLine((LPCTSTR)strLine); // // Cylinders // if (DiskInfo.Cylinders.HighPart) { strFormat.LoadString(g_hInstance, IDS_PRINT_CYLINDERS_XL); strLine.Format((LPCTSTR)strFormat, DiskInfo.Cylinders.HighPart, DiskInfo.Cylinders.LowPart); PrintLine((LPCTSTR)strLine); } else { strFormat.LoadString(g_hInstance, IDS_PRINT_CYLINDERS); strLine.Format((LPCTSTR)strFormat, DiskInfo.Cylinders.LowPart); PrintLine((LPCTSTR)strLine); } // // Sectors per track // strFormat.LoadString(g_hInstance, IDS_PRINT_TRACKSIZE); strLine.Format((LPCTSTR)strFormat, DiskInfo.SectorsPerTrack); PrintLine((LPCTSTR)strLine); // // Bytes per sector // strFormat.LoadString(g_hInstance, IDS_PRINT_SECTORSIZE); strLine.Format((LPCTSTR)strFormat, DiskInfo.BytesPerSector); PrintLine((LPCTSTR)strLine); } UnIndent(); LineFeed(); } UnIndent(); } return 1; } int CPrinter::PrintResourceSummary( CMachine& Machine ) { String strLine; String str; String strBanner; if (Machine.IsLocal()) { PrintSystemSummary(); } // // print IRQ summary heading // str.LoadString(g_hInstance, IDS_PRINT_HEADING_IRQSUMMARY); strBanner.LoadString(g_hInstance, IDS_PRINT_BANNER); strLine.Format((LPCTSTR)strBanner, (LPCTSTR)str); PrintLine((LPCTSTR)strLine); LineFeed(); CResourceList IrqSummary(&Machine, ResType_IRQ); if (IrqSummary.GetCount()) { CResource* pResRoot; IrqSummary.CreateResourceTree(&pResRoot); str.LoadString(g_hInstance, IDS_PRINT_IRQSUM); PrintLine(str); Indent(); PrintResourceSubtree(pResRoot); UnIndent(); LineFeed(); } // // print DMA summary heading // str.LoadString(g_hInstance, IDS_PRINT_HEADING_DMASUMMARY); strLine.Format((LPCTSTR)strBanner, (LPCTSTR)str); PrintLine((LPCTSTR)strLine); LineFeed(); CResourceList DmaSummary(&Machine, ResType_DMA); if (DmaSummary.GetCount()) { CResource* pResRoot; DmaSummary.CreateResourceTree(&pResRoot); str.LoadString(g_hInstance, IDS_PRINT_DMASUM); PrintLine(str); Indent(); PrintResourceSubtree(pResRoot); UnIndent(); LineFeed(); } // // print MEM summary heading // str.LoadString(g_hInstance, IDS_PRINT_HEADING_MEMSUMMARY); strLine.Format((LPCTSTR)strBanner, (LPCTSTR)str); PrintLine((LPCTSTR)strLine); LineFeed(); CResourceList MemSummary(&Machine, ResType_Mem); if (MemSummary.GetCount()) { CResource* pResRoot; MemSummary.CreateResourceTree(&pResRoot); str.LoadString(g_hInstance, IDS_PRINT_MEMSUM); PrintLine(str); Indent(); PrintResourceSubtree(pResRoot); UnIndent(); LineFeed(); } // // print IO summary heading // str.LoadString(g_hInstance, IDS_PRINT_HEADING_IOSUMMARY); strLine.Format((LPCTSTR)strBanner, (LPCTSTR)str); PrintLine((LPCTSTR)strLine); LineFeed(); CResourceList IoSummary(&Machine, ResType_IO); if (IoSummary.GetCount()) { CResource* pResRoot; IoSummary.CreateResourceTree(&pResRoot); str.LoadString(g_hInstance, IDS_PRINT_IOSUM); PrintLine(str); Indent(); PrintResourceSubtree(pResRoot); UnIndent(); LineFeed(); } return 1; } int CPrinter::PrintResourceSubtree( CResource* pResRoot ) { while (pResRoot) { DWORD Status, Problem; if (pResRoot->m_pDevice->GetStatus(&Status, &Problem) && Problem || pResRoot->m_pDevice->IsDisabled()) { TCHAR Temp[MAX_PATH]; Temp[0] = _T('*'); StringCchCopy(&Temp[1], (ARRAYLEN(Temp) - 1), pResRoot->GetViewName()); PrintLine(Temp); } else { PrintLine(pResRoot->GetViewName()); } if (pResRoot->GetChild()) { if ((ResType_IO == pResRoot->ResType()) || (ResType_Mem == pResRoot->ResType())) { Indent(); } PrintResourceSubtree(pResRoot->GetChild()); if ((ResType_IO == pResRoot->ResType()) || (ResType_Mem == pResRoot->ResType())) { UnIndent(); } } pResRoot = pResRoot->GetSibling(); } return 1; } int CPrinter::PrintAllClassAndDevice( CMachine* pMachine ) { if (!pMachine) { return 0; } String strHeading; String strBanner; String strLine; strHeading.LoadString(g_hInstance, IDS_PRINT_HEADING_SYSDEVINFO); strBanner.LoadString(g_hInstance, IDS_PRINT_BANNER); strLine.Format((LPCTSTR)strBanner, (LPCTSTR)strHeading); PrintLine((LPCTSTR)strLine); LineFeed(); CClass* pClass; PVOID Context; if (pMachine->GetFirstClass(&pClass, Context)) { do { PrintClass(pClass, FALSE); } while (pMachine->GetNextClass(&pClass, Context)); } return 1; } int CPrinter::PrintClass( CClass* pClass, BOOL PrintBanner ) { PVOID Context; CDevice* pDevice; if (!pClass) { return 0; } if (PrintBanner) { String strHeading; String strBanner; String strLine; strHeading.LoadString(g_hInstance, IDS_PRINT_HEADING_SYSDEVCLASS); strBanner.LoadString(g_hInstance, IDS_PRINT_BANNER); strLine.Format((LPCTSTR)strBanner, (LPCTSTR)strHeading); PrintLine((LPCTSTR)strLine); LineFeed(); } if (pClass && pClass->GetFirstDevice(&pDevice, Context)) { do { // // Do print banner on the device // PrintDevice(pDevice, FALSE); } while (pClass->GetNextDevice(&pDevice, Context)); } return 1; } int CPrinter::PrintDevice( CDevice* pDevice, BOOL PrintBanner ) { if (!pDevice) { return 0; } String str; String strLine; if (PrintBanner) { String strBanner; str.LoadString(g_hInstance, IDS_PRINT_HEADING_SYSDEVICE); strBanner.LoadString(g_hInstance, IDS_PRINT_BANNER); strLine.Format((LPCTSTR)strBanner, (LPCTSTR)str); PrintLine((LPCTSTR)strLine); LineFeed(); } DWORD Status, Problem; if (pDevice->GetStatus(&Status, &Problem) && Problem || pDevice->IsDisabled()) { strLine.LoadString(g_hInstance, IDS_PRINT_DEVICE_DISABLED); PrintLine((LPCTSTR)strLine); } str.LoadString(g_hInstance, IDS_PRINT_CLASS); strLine.Format((LPCTSTR)str, pDevice->GetClassDisplayName()); PrintLine((LPCTSTR)strLine); str.LoadString(g_hInstance, IDS_PRINT_DEVICE); strLine.Format((LPCTSTR)str, pDevice->GetDisplayName()); PrintLine((LPCTSTR)strLine); PrintDeviceResource(pDevice); PrintDeviceDriver(pDevice); return 1; } int CPrinter::PrintAll( CMachine& Machine ) { PrintResourceSummary(Machine); PrintAllClassAndDevice(&Machine); return 1; } // // This function prints the given device's resource summary // int CPrinter::PrintDeviceResource( CDevice* pDevice ) { if (!pDevice) { return 0; } CResourceList IrqSummary(pDevice, ResType_IRQ); CResourceList DmaSummary(pDevice, ResType_DMA); CResourceList MemSummary(pDevice, ResType_Mem); CResourceList IoSummary(pDevice, ResType_IO); String str; TCHAR Temp[MAX_PATH]; // // If the device has any kind of resources, print it // if (IrqSummary.GetCount() || DmaSummary.GetCount() || MemSummary.GetCount() || IoSummary.GetCount()) { str.LoadString(g_hInstance, IDS_PRINT_RESOURCE); PrintLine(str); // // Start printing individual resources // Indent(); PVOID Context; CResource* pResource; DWORDLONG dlBase, dlLen; if (IrqSummary.GetFirst(&pResource, Context)) { LoadString(g_hInstance, IDS_PRINT_IRQ_FORMAT, Temp, ARRAYLEN(Temp)); do { pResource->GetValue(&dlBase, &dlLen); str.Format(Temp, (ULONG)dlBase); PrintLine((LPCTSTR)str); } while (IrqSummary.GetNext(&pResource, Context)); } if (DmaSummary.GetFirst(&pResource, Context)) { LoadString(g_hInstance, IDS_PRINT_DMA_FORMAT, Temp, ARRAYLEN(Temp)); do { pResource->GetValue(&dlBase, &dlLen); str.Format(Temp, (ULONG)dlBase); PrintLine((LPCTSTR)str); } while (DmaSummary.GetNext(&pResource, Context)); } if (MemSummary.GetFirst(&pResource, Context)) { LoadString(g_hInstance, IDS_PRINT_MEM_FORMAT, Temp, ARRAYLEN(Temp)); do { pResource->GetValue(&dlBase, &dlLen); str.Format(Temp, (ULONG)dlBase, (ULONG)(dlBase + dlLen - 1)); PrintLine((LPCTSTR)str); } while (MemSummary.GetNext(&pResource, Context)); } if (IoSummary.GetFirst(&pResource, Context)) { LoadString(g_hInstance, IDS_PRINT_IO_FORMAT, Temp, ARRAYLEN(Temp)); do { pResource->GetValue(&dlBase, &dlLen); str.Format(Temp, (ULONG)dlBase, (ULONG)(dlBase + dlLen -1)); PrintLine((LPCTSTR)str); } while (IoSummary.GetNext(&pResource, Context)); } UnIndent(); } else { str.LoadString(g_hInstance, IDS_PRINT_NORES); PrintLine(str); } return 1; } // // This function prints the given device's driver information // INPUT: // pDevice -- the device // OUTPUT: // >0 if the function succeeded. // 0 if the function failed. // int CPrinter::PrintDeviceDriver( CDevice* pDevice ) { if (!pDevice) { return 0; } String str; TCHAR Temp[MAX_PATH]; CDriver* pDriver; pDriver = pDevice->CreateDriver(); SafePtr DrvPtr; if (pDriver) { DrvPtr.Attach(pDriver); str.LoadString(g_hInstance, IDS_PRINT_DRVINFO); PrintLine(str); PVOID Context; CDriverFile* pDrvFile; Indent(); // // Build up a list of function and filter drivers for this device. // pDriver->BuildDriverList(); if (pDriver->GetFirstDriverFile(&pDrvFile, Context)) { do { PrintLine(pDrvFile->GetFullPathName()); HANDLE hFile; Indent(); hFile = CreateFile(pDrvFile->GetFullPathName(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN, NULL ); if (INVALID_HANDLE_VALUE != hFile) { DWORD FileSize; FileSize = ::GetFileSize(hFile, NULL); CloseHandle(hFile); LoadString(g_hInstance, IDS_PRINT_FILESIZE, Temp, ARRAYLEN(Temp)); str.Format(Temp, FileSize); PrintLine(str); // print the driver version infomation TCHAR Unknown[MAX_PATH]; LoadString(g_hInstance, IDS_PRINT_UNKNOWN, Unknown, ARRAYLEN(Unknown)); if (pDrvFile->HasVersionInfo()) { LoadString(g_hInstance, IDS_PRINT_FILEVERSION, Temp, ARRAYLEN(Temp)); if (pDrvFile->GetVersion()) { str.Format(Temp, pDrvFile->GetVersion()); } else { str.Format(Temp, Unknown); } PrintLine(str); LoadString(g_hInstance, IDS_PRINT_FILEMFG, Temp, ARRAYLEN(Temp)); if (pDrvFile->GetProvider()) { str.Format(Temp, pDrvFile->GetProvider()); } else { str.Format(Temp, Unknown); } PrintLine(str); LoadString(g_hInstance, IDS_PRINT_FILECOPYRIGHT, Temp, ARRAYLEN(Temp)); if (pDrvFile->GetCopyright()) { str.Format(Temp, pDrvFile->GetCopyright()); } else { str.Format(Temp, Unknown); } PrintLine(str); } else { str.LoadString(g_hInstance, IDS_PRINT_NOVERSION); PrintLine(str); } } else { str.LoadString(g_hInstance, IDS_PRINT_DRVMISSING); PrintLine(str); } UnIndent(); } while (pDriver->GetNextDriverFile(&pDrvFile, Context)); } UnIndent(); } LineFeed(); return 1; }