/*++ Copyright (C) Microsoft Corporation, 1996 - 1999 All rights reserved. Module Name: tstpage.cxx Abstract: Print Test Page Author: Steve Kiraly (SteveKi) 16-Jan-1996 Revision History: Lazar Ivanov (LazarI) Jun-2000 (Win64 fixes) --*/ #include "precomp.hxx" #pragma hdrstop #include "tstpage.hxx" /******************************************************************** Message map used after the test page is printed. ********************************************************************/ // // Check if the printer name contains a // trailing spaces // BOOL bContainTrailingSpaces( IN LPCTSTR pszShareName ) { BOOL bResult = FALSE; if( pszShareName ) { // // Check for trailing spaces here // int iLen = lstrlen(pszShareName); if( iLen > 0 && TEXT(' ') == pszShareName[iLen-1] ) { bResult = TRUE; } } return bResult; } // // Print test page to specified printer // BOOL bPrintTestPage( IN HWND hWnd, IN LPCTSTR pszPrinterName, IN LPCTSTR pszShareName ) { INT_PTR iStatus; DBGMSG( DBG_TRACE, ( "bPrintTestPage\n" ) ); DBGMSG( DBG_TRACE, ( "PrinterName " TSTR "\n", pszPrinterName ) ); // // Set the last error to a known value. This will allow us to // display a reasonable error messege if some api fails to print // the test page. The createDC call in particular may fail if // the driver does not exist on this machine. // SetLastError( ERROR_SUCCESS ); // // We need to check the name for trailing spaces, which // can cause a problems with NT5 -> Win98 downlevel connections. // The problem is that CreateFile(...) function fails if // the printer share name contains trailing spaces. // if( bContainTrailingSpaces( pszShareName ) ) { // // Warn the user for eventual problems in this case // iMessage( hWnd, IDS_ERR_PRINTER_PROP_TITLE, IDS_WARN_TRAILINGSPACES_IN_PRINTERNAME, MB_OK|MB_ICONEXCLAMATION, kMsgNone, NULL ); } // // Insure we don't have a null printer name. // or the test page failed to print. // if( !pszPrinterName || !bDoPrintTestPage(hWnd, pszPrinterName ) ){ DBGMSG( DBG_WARN, ( "Print test page failed with %d\n", GetLastError() )); // // If the user canceled the operation then just exit. // if( GetLastError() == ERROR_CANCELLED ){ return TRUE; } // // Ask the user if they want to goto the print // trouble shooter. // if( IDYES == iMessage( hWnd, IDS_ERR_PRINTER_PROP_TITLE, IDS_ERR_TESTPAGE, MB_YESNO|MB_ICONEXCLAMATION, kMsgGetLastError, NULL ) ){ // // This jumps to the windows printer help trouble shooter section. // We have to execute the troubleshooter in a separate process because this // code sometimes is executed in a rundll process, which goes away imediately // and the help window goes away too. We don't want the help window to go away. // ShellExecute( hWnd, TEXT("open"), TEXT("helpctr.exe"), gszHelpTroubleShooterURL, NULL, SW_SHOWNORMAL ); } return FALSE; } TString strMachineName; LPCTSTR pszServer, pszPrinter; TCHAR szScratch[PRINTER_MAX_PATH]; if( SUCCEEDED(PrinterSplitFullName(pszPrinterName, szScratch, ARRAYSIZE(szScratch), &pszServer, &pszPrinter)) && bGetMachineName(strMachineName) && 0 == _tcsicmp(pszServer, strMachineName) ) { // this is local printer - update the name pszPrinterName = pszPrinter; } // // Prompt user, asking if the test page printed ok. // iStatus = DialogBoxParam( ghInst, MAKEINTRESOURCE( DLG_END_TESTPAGE ), hWnd, EndTestPageDlgProc, (LPARAM)pszPrinterName ); // // User indicated page did not print, display winhelp. // if( iStatus != IDOK ){ // // This jumps to the windows printer help trouble shooter section. // We have to execute the troubleshooter in a separate process because this // code sometimes is executed in a rundll process, which goes away imediately // and the help window goes away too. We don't want the help window to go away. // ShellExecute( hWnd, TEXT("open"), TEXT("helpctr.exe"), gszHelpTroubleShooterURL, NULL, SW_SHOWNORMAL ); return FALSE; } // // Set proper return code. // return TRUE; } // // Print test page to the specified printer. // BOOL bDoPrintTestPage( IN HWND hWnd, IN LPCTSTR pszPrinterName ) { DOCINFO DocInfo; TCHAR szBuf[kStrMax]; RECT rc; BOOL bDocumentStarted = FALSE; HDC hdcPrint = NULL; DWORD dwLastError = ERROR_SUCCESS; BOOL bStatus = FALSE; UINT uRightAlign = 0; // // Create a printer DC // hdcPrint = CreateDC( _T("WINSPOOL"), pszPrinterName, NULL, NULL ); if( hdcPrint == NULL ){ DBGMSG( DBG_WARN, ( "CreateDC failed with %d\n", GetLastError() ) ); goto Cleanup; } // // Load the test page name. // if( !LoadString( ghInst, IDS_TP_TESTPAGENAME, szBuf, COUNTOF(szBuf) ) ){ DBGMSG( DBG_WARN, ( "Load test page name failed with %d\n", GetLastError() ) ); goto Cleanup; } // // Start the document // ZeroMemory( &DocInfo, sizeof( DOCINFO )); DocInfo.cbSize = sizeof( DocInfo ); DocInfo.lpszDocName = szBuf; DocInfo.lpszOutput = NULL; DocInfo.lpszDatatype = NULL; DocInfo.fwType = 0; // // Start the print job. // if( StartDoc( hdcPrint, &DocInfo ) <= 0 ) { DBGMSG( DBG_WARN, ( "StartDoc failed with %d\n", GetLastError() ) ); goto Cleanup; } // // Indicate document was started // bDocumentStarted = TRUE; // // Start the test page. // if( StartPage( hdcPrint ) <= 0 ){ DBGMSG( DBG_WARN, ( "StartPage failed with %d\n", GetLastError() ) ); goto Cleanup; } if (GetWindowLongPtr(hWnd, GWL_EXSTYLE) & WS_EX_LAYOUTRTL) { uRightAlign = DT_RIGHT | DT_RTLREADING; } // // Get Margin clip box, Margins are expressed in 100th of an inch. // rc = GetMarginClipBox( hdcPrint, 50, 100, 100, 100 ); // // Print Test Page Header // if( !bPrintTestPageHeader( hdcPrint, TRUE, TRUE, &rc, uRightAlign ) ){ DBGMSG( DBG_WARN, ( "bPrintTestPageHeader failed with %d\n", GetLastError() ) ); goto Cleanup; } // // Print basic test page information. // if( !bPrintTestPageInfo( hdcPrint, &rc, pszPrinterName, uRightAlign ) ){ DBGMSG( DBG_WARN, ( "bPrintTestPageInfo failed with %d\n", GetLastError() ) ); goto Cleanup; } // // End the page. // if( EndPage( hdcPrint ) <= 0 ){ DBGMSG( DBG_WARN, ( "EndPage failed with %d\n", GetLastError() ) ); goto Cleanup; } // // End the print job. // if( EndDoc( hdcPrint ) <= 0 ){ DBGMSG( DBG_WARN, ( "StartDoc failed with %d\n", GetLastError() ) ); goto Cleanup; } // // Set error status. // bDocumentStarted = FALSE; bStatus = TRUE; SetLastError( ERROR_SUCCESS ); // // Cleanup any outstanding resources. // Cleanup: if( !bStatus ){ // // Save the last error state. // dwLastError = GetLastError(); // // If the document was started then abort the document. // if( bDocumentStarted && AbortDoc( hdcPrint ) <= 0 ){ DBGMSG( DBG_WARN, ( "AbortDoc failed with %d\n", GetLastError() ) ); } } // // Release DC // if( hdcPrint ){ DeleteDC( hdcPrint ); } if( !bStatus ){ // // Restore the last error state back to the caller. // SetLastError( dwLastError ); } return bStatus; } /*++ Routine Name: GetMarginClipBox Routine Description: Calculates the correct margin rectangle for the specifed DC. Note that a printer DC has non-printable regions on all sized, this routine takes these regions into account when calculating the correct margins. Margins are measured from the extream physical edge of the page. Arguments: hdcPrint - Printer device context iLeft - Desired left margin iRight - Desired left margin iTop - Desired left margin iBottom - Desired left margin Return Value: Rectangle which reflects the specified margins. Note if the desired margins are smaller than what the device is capable of then the clip box is adjusted to the physical printers margin. --*/ RECT GetMarginClipBox( IN HDC hdcPrint, IN INT iLeft, IN INT iRight, IN INT iTop, IN INT iBottom ) { INT npx = GetDeviceCaps( hdcPrint, PHYSICALOFFSETX ); INT npy = GetDeviceCaps( hdcPrint, PHYSICALOFFSETY ); INT iLogicPixelsX = GetDeviceCaps( hdcPrint, LOGPIXELSX ); INT iLogicPixelsY = GetDeviceCaps( hdcPrint, LOGPIXELSY ); RECT rcPage; rcPage.left = max( 0, iLogicPixelsX * iLeft / kInchConversion - npx ); rcPage.top = max( 0, iLogicPixelsY * iTop / kInchConversion - npy ); INT iPhysWidth = GetDeviceCaps( hdcPrint, PHYSICALWIDTH ); INT iPhysHeight = GetDeviceCaps( hdcPrint, PHYSICALHEIGHT ); INT iHorzRes = GetDeviceCaps( hdcPrint, HORZRES ); INT iVertRes = GetDeviceCaps( hdcPrint, VERTRES ); INT nprx = iPhysWidth - (npx + iHorzRes); INT npby = iPhysHeight - (npy + iVertRes); rcPage.right = iHorzRes - max( 0, iLogicPixelsX * iRight / kInchConversion - nprx ); rcPage.bottom = iVertRes - max( 0, iLogicPixelsY * iBottom / kInchConversion - npby ); return rcPage; } /*++ Routine Name: bPrintTestPageHeader Routine Description: Print out a header for the test page Arguments: hdcPrint - Printer device context bDisplayLogo - flag TRUE display logo, false do not display logo bDoGraphics - flag TRUE do graphics, false do not do graphics lpRect - Pointer to a rectangle which describes the margins uRightAlign - flags to print the test page right aligned Return Value: TRUE if header was printed, FALSE if error occurred. --*/ BOOL bPrintTestPageHeader( IN HDC hdc, IN BOOL bDisplayLogo, IN BOOL bDoGraphics, IN RECT *lprcPage, IN UINT uRightAlign ) { enum Info { PLACEABLE_SIGNATURE = 0x9AC6CDD7, METAFILEHEADER_SIZE = 22, }; BOOL bSuccess = TRUE; INT nXInch = GetDeviceCaps( hdc, LOGPIXELSX ); INT nYInch = GetDeviceCaps( hdc, LOGPIXELSY ); // // If device can do graphics. // if( RC_BITBLT & GetDeviceCaps( hdc, RASTERCAPS ) && bDoGraphics ){ if( bDisplayLogo ) { HRSRC hRes = FindResource( ghInst, MAKEINTRESOURCE(IDR_MF_LOGO), TEXT("METAFILE") ); if( hRes ) { // // Device can handle BitBlt calls--do graphic // LPBYTE lpMetaFile = (LPBYTE)LoadResource( ghInst, hRes ); if( lpMetaFile ){ LPMETAHEADER lpMH; HMETAFILE hmf; if(PLACEABLE_SIGNATURE==*((LPDWORD)lpMetaFile)) { lpMetaFile+=METAFILEHEADER_SIZE; } lpMH=(LPMETAHEADER)lpMetaFile; if( ( hmf=SetMetaFileBitsEx(lpMH->mtSize*sizeof(WORD),(LPBYTE)lpMH)) != NULL ){ INT nSavedDC=SaveDC(hdc); SetMapMode(hdc,MM_ISOTROPIC); SetWindowOrgEx(hdc,0,0,NULL); SetWindowExtEx(hdc,100,100,NULL); SetViewportExtEx(hdc,nXInch,nYInch,NULL); SetViewportOrgEx(hdc,nXInch/2,nYInch/2,NULL); bSuccess=PlayMetaFile(hdc,hmf); DeleteMetaFile(hmf); // // Restore the previous GDI state // if(nSavedDC) RestoreDC(hdc,nSavedDC); } } } } // // Output TrueType font at top of page in 36 point Times New Roman // HFONT hOldFont; hOldFont = CreateAndSelectFont( hdc, IDS_TP_TIMESNEWROMAN, 36 ); if( hOldFont ){ // // Position text so it aligns with the graphic & is 2" into // the printable region. // lprcPage->top=nYInch/2; lprcPage->left=nXInch*2; // // Print the test page header. // bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_HEADER,'\0'); // // Restore the margins. // lprcPage->top=nYInch*2; lprcPage->left=nXInch/2; // // Restore the font // DeleteObject( SelectObject( hdc, hOldFont ) ); } else { DBGMSG( DBG_WARN, ( "CreateAndSelectFontFailed with %d.\n", GetLastError() ) ); bSuccess = FALSE; } } else { DBGMSG( DBG_TRACE, ( "Printer does not do graphics.\n" ) ); // // Device can't do graphics--use default font for title. Center it // horizontally, half an inch from the top of the printable area. // lprcPage->top=nYInch/2; // // Display normal text header. // bSuccess &= PrintString(hdc,lprcPage,DT_TOP|DT_CENTER,IDS_TP_HEADER,'\n'); // // Display all of the other strings 1/2" from the left margin // lprcPage->left=nXInch/2; } return bSuccess; } /*++ Routine Name: bPrintTestPageInfo Routine Description: Print out a printer info on the test page. Arguments: hdcPrint - Printer device context lpRect - Pointer to a rectangle which describes the margins uRightAlign - flags to print the test page right aligned Return Value: TRUE if header was printed, FALSE if error occurred. --*/ BOOL bPrintTestPageInfo( IN HDC hdc, IN LPRECT lprcPage, IN LPCTSTR pszPrinterName, IN UINT uRightAlign ) { TCHAR szBuffer[kServerBufMax]; TCHAR szBuff[kStrMax]; TEXTMETRIC tm; LPCTSTR pszBuffer = NULL; DWORD dwDriverVersion = 0; BOOL bSuccess = FALSE; HFONT hOldFont = NULL; DWORD dwBufferSize = COUNTOF( szBuffer ); PPRINTER_INFO_2 lppi2 = NULL; PDRIVER_INFO_3 lpdi3 = NULL; HDC hdcScreen = NULL; UINT nYInch; TString strTemp; // // Get the screen device context. // hdcScreen = GetDC( NULL ); if( !hdcScreen ){ DBGMSG( DBG_WARN, ( "GetDC failed with %d\n", GetLastError() ) ); goto Cleanup; } #ifdef USE_DEVICE_FONT // // Get the logical pixes in the y direction. // nYInch = GetDeviceCaps( hdc, LOGPIXELSY); if( !nYInch ){ DBGMSG( DBG_WARN, ( "GetDeviceCaps failed with %d\n", GetLastError() ) ); goto Cleanup; } // // This stuff is designed to be printed in a fixed-pitch font, // using the system character set. If the current font fails // any criterion, use CourierNew in the system charset. // if( !GetTextMetrics( hdc, &tm ) || ( tm.tmPitchAndFamily & TMPF_FIXED_PITCH ) || ( GetTextCharset(hdc) != GetTextCharset( hdcScreen ) ) || ( tm.tmHeight > MulDiv( 12, nYInch, 72 ) ) ){ DBGMSG( DBG_TRACE, ( "Creating font.\n" ) ); hOldFont = CreateAndSelectFont( hdc, IDS_TP_FONTNAMEINFOTEXT, 10 ); if( !hOldFont ){ DBGMSG( DBG_WARN, ( "CreateAndSelectFont failed with %d\n", GetLastError() ) ); goto Cleanup; } } else { DBGMSG( DBG_TRACE, ( "Using Default printer font.\n" ) ); } #else hOldFont = CreateAndSelectFont( hdc, IDS_TP_FONTNAMEINFOTEXT, 10 ); if( !hOldFont ){ DBGMSG( DBG_WARN, ( "CreateAndSelectFont failed with %d\n", GetLastError() ) ); goto Cleanup; } #endif // // Get the printer information to print. // if( !bGetPrinterInfo( pszPrinterName, &lppi2, &lpdi3 ) ){ DBGMSG( DBG_WARN, ( "bGetPrinterInfo failed with %d\n", GetLastError() ) ); goto Cleanup; } // Machine Name: if( lppi2->pServerName ){ // If server name is not null copy string StringCchCopy( szBuffer, ARRAYSIZE(szBuffer), lppi2->pServerName ); } else { // Get the computer name. GetComputerName( szBuffer, &dwBufferSize ); } // Remove any leading slashes for( pszBuffer = szBuffer; pszBuffer && ( *pszBuffer == TEXT( '\\' ) ); pszBuffer++ ) ; bSuccess = TRUE; // Tell the user that we installed successfully. bSuccess &= PrintString( hdc, lprcPage, uRightAlign, IDS_TP_CONGRATULATIONS ); // Tell the user what they installed. bSuccess &= PrintString( hdc, lprcPage, uRightAlign, IDS_TP_PRINTERISINSTALLED, lppi2->pDriverName, pszBuffer ); // Get the time and date. bSuccess &= GetCurrentTimeAndDate( COUNTOF( szBuff ), szBuff ); // Print the time and date. bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_TIMEDATE, szBuff ); // Print the machine name. bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_MACHINENAME, pszBuffer ); // Printer Name: if( SUCCEEDED(AbbreviateText(lppi2->pPrinterName, MAX_TESTPAGE_DISPLAYNAME, &strTemp)) ) { bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_PRINTERNAME, (LPCTSTR)strTemp ); } else { bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_PRINTERNAME, lppi2->pPrinterName ); } // Printer Model: bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_PRINTERMODEL, lppi2->pDriverName); // Color Capability if( lppi2->pDevMode ) { bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IsColorDevice(lppi2->pDevMode)?IDS_TP_COLOR:IDS_TP_MONO); } // Printer Port: if( lppi2->pPortName && SUCCEEDED(AbbreviateText(lppi2->pPortName, MAX_TESTPAGE_DISPLAYNAME, &strTemp)) ) bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_PORTNAME, (LPCTSTR)strTemp); // Data Type: if( lppi2->pDatatype ) bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_DATATYPE, lppi2->pDatatype); // Share Name if( lppi2->pShareName && SUCCEEDED(AbbreviateText(lppi2->pShareName, MAX_TESTPAGE_DISPLAYNAME, &strTemp)) ) bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_SHARE_NAME, (LPCTSTR)strTemp); // Location if( lppi2->pLocation && SUCCEEDED(AbbreviateText(lppi2->pLocation, MAX_TESTPAGE_DISPLAYNAME, &strTemp)) ) bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_LOCATION, (LPCTSTR)strTemp); // Comment if( lppi2->pComment && SUCCEEDED(AbbreviateText(lppi2->pComment, MAX_TESTPAGE_DISPLAYNAME, &strTemp)) ) bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_COMMENT, (LPCTSTR)strTemp); // DRV Name: bSuccess &= PrintBaseFileName(hdc,lpdi3->pDriverPath,lprcPage, IDS_TP_DRV_NAME, uRightAlign); // Data file (if it's different from the driver name) if(lstrcmpi(lpdi3->pDriverPath,lpdi3->pDataFile)) { bSuccess &= PrintBaseFileName(hdc,lpdi3->pDataFile,lprcPage, IDS_TP_DATA_FILE, uRightAlign); } // Config file (if it's different from the driver name) if(lstrcmpi(lpdi3->pDriverPath,lpdi3->pDataFile)) { bSuccess &= PrintBaseFileName(hdc,lpdi3->pConfigFile,lprcPage, IDS_TP_CONFIG_FILE, uRightAlign); } // Help file if( lpdi3->pHelpFile ) { bSuccess &= PrintBaseFileName(hdc,lpdi3->pHelpFile,lprcPage,IDS_TP_HELP_FILE, uRightAlign); } // Driver version, if available if((dwDriverVersion=DeviceCapabilities(lppi2->pPrinterName,lppi2->pPortName,DC_DRIVER,NULL,NULL)) != (DWORD)-1) { bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_DRV_VERSION, HIBYTE(LOWORD(dwDriverVersion)), LOBYTE(LOWORD(dwDriverVersion))); } // Environment if( lpdi3->pEnvironment ) bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_ENVIRONMENT,lpdi3->pEnvironment); // Monitor if( lpdi3->pMonitorName ) bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_MONITOR,lpdi3->pMonitorName); // Default Datatype if( lpdi3->pDefaultDataType ) bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_DEFAULT_DATATYPE,lpdi3->pDefaultDataType); // Dependent Files: LPTSTR lpTest; lpTest = lpdi3->pDependentFiles; if(lpTest && *lpTest) { bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_DEPENDENTLIST); while(*lpTest) { bSuccess &= PrintDependentFile(hdc,lprcPage,lpTest, lpdi3->pDriverPath, uRightAlign); lpTest += (lstrlen(lpTest)+1); } } // Tell the user that we're done now bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_TESTPAGEEND); // // Release the resources. // Cleanup: FreeMem( lpdi3 ); FreeMem( lppi2 ); if( hOldFont ){ DeleteObject( SelectObject( hdc, hOldFont ) ); } if( hdcScreen ){ ReleaseDC( NULL, hdcScreen ); } return bSuccess; } //------------------------------------------------------------------------- // Function: IsColorDevice(hdc) // // Action: Determine whether or not this device supports color // // Return: TRUE if it does, FALSE if it doesn't //------------------------------------------------------------------------- BOOL IsColorDevice( IN DEVMODE *pDevMode ) { // // Assume monochrome. // DWORD dmColor = DMCOLOR_MONOCHROME; // // Get the color support if available. // if( pDevMode && ( pDevMode->dmFields & DM_COLOR ) ) dmColor = pDevMode->dmColor; // // TRUE color supported, FALSE monochrome. // return dmColor == DMCOLOR_COLOR; } /*++ Routine Name: CreateAndSelectFont Routine Description: Get a font with the face, style & point size for this device, and the character set from the screen DC, then select it in. Arguments: hdc - Currently selected dc uResFaceName - Type face name resource ID uPtSize - Desired point size Return Value: The OLD font handle if successful, Failure NULL --*/ HFONT CreateAndSelectFont( IN HDC hdc, IN UINT uResFaceName, IN UINT uPtSize ) { INT nYInch = 0; HDC hdcScreen = NULL; HFONT hNewFont = NULL; HFONT hOldFont = NULL; LOGFONT lf; // // Logical pixels in the y direction. // nYInch = GetDeviceCaps( hdc, LOGPIXELSY); // // Get a handle to the screen DC for creating a font. // hdcScreen = GetDC( NULL ); if( !hdcScreen ){ DBGMSG( DBG_TRACE, ( "CreateAndSelectFont - GetDC failed with %d.\n", GetLastError() ) ); goto Cleanup; } ZeroMemory( &lf, sizeof( LOGFONT ) ); lf.lfHeight = MulDiv( uPtSize, nYInch, 72); lf.lfWeight = 400; lf.lfCharSet = (BYTE)GetTextCharset( hdcScreen ); lf.lfQuality = (BYTE)PROOF_QUALITY; lf.lfPitchAndFamily = FF_DONTCARE; // // Load the font face name from the resource file. // if( !LoadString( ghInst, uResFaceName, lf.lfFaceName, COUNTOF( lf.lfFaceName ) ) ){ DBGMSG( DBG_TRACE, ( "CreateAndSelectFont - LoadString failed with %d.\n", GetLastError() ) ); goto Cleanup; } // // Create the font. // hNewFont = CreateFontIndirect( &lf ); if( !hNewFont ){ DBGMSG( DBG_TRACE, ( "CreateAndSelectFont - CreateFontIndirect failed with %d.\n", GetLastError() ) ); goto Cleanup; } // // Select the new font into the current dc and return the old font handle. // hOldFont = (HFONT)SelectObject( hdc, hNewFont ); if( !hOldFont || (ULONG_PTR)hOldFont == GDI_ERROR ){ DBGMSG( DBG_TRACE, ( "CreateAndSelectFont - SelectObject failed with %d, %d.\n", hOldFont, GetLastError() ) ); hOldFont = NULL; // Indicate failure to caller. goto Cleanup; } Cleanup: // // Release the screen dc handle // if( hdcScreen ){ ReleaseDC( NULL, hdcScreen ); } return hOldFont; } //------------------------------------------------------------------------- // Function: PrintString(hdc,lprcPage,uFlags,uResId,...) // // Action: Build a formatted string, then print it on the page using the // current font. Update lprcPage after the output. // // Return: TRUE if successful, FALSE if not //------------------------------------------------------------------------- BOOL cdecl PrintString( HDC hdc, LPRECT lprcPage, UINT uFlags, UINT uResId, ... ) { BOOL bSuccess = FALSE; va_list pArgs; // // Get pointer to first un-named argument. // va_start( pArgs, uResId ); // // Alocate the format and string buffer. // TCHAR npFormat[kStrMax]; TCHAR npBuffer[1024]; // // Load the string resource. // if( LoadString( ghInst, uResId, npFormat, COUNTOF( npFormat ) ) ){ // // Format the string. // StringCchVPrintf( npBuffer, COUNTOF( npBuffer ), npFormat, pArgs ); // // Output the string, updating the rectangle. // INT nHeight; nHeight = DrawText( hdc, npBuffer, -1, lprcPage, uFlags|DT_EXPANDTABS|DT_LEFT|DT_NOPREFIX|DT_WORDBREAK); // // If any text was drawn. // if( nHeight ){ // // Update the rectangle // lprcPage->top += nHeight; bSuccess=TRUE; } else { DBGMSG( DBG_TRACE, ( "PrintString - DrawText failed with %d\n", GetLastError() ) ); } } else { DBGMSG( DBG_TRACE, ( "PrintString - LoadString failed with %d\n", GetLastError() ) ); } va_end( pArgs ); return bSuccess; } //------------------------------------------------------------------------- // Function: PrintBaseFileName(hdc,lpFile,lprcPage,uResID) // // Action: Print the base filename as part of a formatted string // // Return: Whatever PrintString returns //------------------------------------------------------------------------- BOOL PrintBaseFileName( IN HDC hdc, IN LPCTSTR lpFile, IN OUT LPRECT lprcPage, IN UINT uResID, IN UINT uRightAlign ) { LPCTSTR lpTest; while( ( lpTest = _tcspbrk( lpFile, TEXT( "\\" ) ) ) != NULL ) lpFile = ++lpTest; return PrintString( hdc, lprcPage, uRightAlign, uResID, lpFile ); } //------------------------------------------------------------------------- // Function: PrintDependentFile(hdc,lprcPage,lpFile,lpDriver) // // Action: Print a line for this dependent file. Include its full path. // Try to include its version information, and it this is the // actual driver file, see if it's a minidriver and include // that information. // // Return: TRUE if successful, FALSE if not //------------------------------------------------------------------------- BOOL PrintDependentFile( IN HDC hdc, IN LPRECT lprcPage, IN LPTSTR lpFile, IN LPTSTR lpDriver, IN UINT uRightAlign ) { DWORD dwSize; DWORD dwHandle; WORD wGPCVersion; LPBYTE lpData = NULL; LPWORD lpVersion = NULL; BOOL bSuccess = FALSE; static TCHAR cszTranslation[] = TEXT( "\\VarFileInfo\\Translation" ); static TCHAR cszFileVersion[] = TEXT( "\\StringFileInfo\\%04X%04X\\FileVersion" ); static TCHAR cszProductVersion[] = TEXT( "\\StringFileInfo\\%04X%04X\\ProductVersion" ); // // Get the file attributes. // if( HFILE_ERROR == GetFileAttributes( lpFile ) ){ return FALSE; } dwSize = GetFileVersionInfoSize( lpFile, &dwHandle ); if( dwSize ){ lpData=(LPBYTE)AllocMem( dwSize ); if( lpData ){ UINT uSize; TCHAR szTemp[MAX_PATH]; LPWORD lpTrans; if(GetFileVersionInfo(lpFile,dwHandle,dwSize,lpData) && VerQueryValue(lpData,cszTranslation,(LPVOID*)&lpTrans,&uSize) && uSize){ StringCchPrintf(szTemp,ARRAYSIZE(szTemp),cszFileVersion,*lpTrans,*(lpTrans+1)); if(!VerQueryValue(lpData,szTemp,(LPVOID*)&lpVersion,&uSize)) { StringCchPrintf(szTemp,ARRAYSIZE(szTemp),cszProductVersion,*lpTrans,*(lpTrans+1)); VerQueryValue(lpData,szTemp,(LPVOID*)&lpVersion,&uSize); } } } } UNREFERENCED_PARAMETER( lpDriver ); wGPCVersion=0; // Now actually print the resulting string if(lpVersion) { bSuccess=PrintString(hdc,lprcPage,uRightAlign,wGPCVersion? IDS_TP_VERSIONANDGPC:IDS_TP_VERSIONONLY, lpFile,lpVersion,HIBYTE(wGPCVersion),LOBYTE(wGPCVersion)); } else { bSuccess=PrintString(hdc,lprcPage,uRightAlign,wGPCVersion? IDS_TP_GPCONLY:IDS_TP_NOVERSIONINFO, lpFile,wGPCVersion); } FreeMem(lpData); return bSuccess; } /*++ Routine Name: EndTestPageDlgProc Routine Description: Ask the user if the test pages was printed correctly. Arguments: Normal window proc arguments. Return Value: TRUE is message was processed, FALSE if not. --*/ INT_PTR CALLBACK EndTestPageDlgProc( IN HWND hDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam ) { BOOL bStatus = TRUE; switch( uMsg ){ case WM_INITDIALOG: { SetForegroundWindow( hDlg ); TCHAR szText[kStrMax+kPrinterBufMax]; UINT nSize = COUNTOF(szText); ConstructPrinterFriendlyName( (LPCTSTR)lParam, szText, &nSize ); SetWindowText( hDlg, szText ); break; } case WM_COMMAND: switch( GET_WM_COMMAND_ID( wParam, lParam ) ){ case IDCANCEL: case IDOK: EndDialog( hDlg, GET_WM_COMMAND_ID( wParam, lParam ) ); break; default: bStatus = FALSE; break; } break; default: bStatus = FALSE; } return bStatus; } /*++ Routine Name: GetPrinterInfo Routine Description: Routine to get the printer info 2 structures from the given printer name. Arguments: pszPrinterName = pointer to printer name **ppInfo2 - pointer where to return pointer to info 2 Return Value: TRUE if both info pointers returned, otherwise FALSE. --*/ BOOL bGetPrinterInfo( IN LPCTSTR pszPrinterName, IN PRINTER_INFO_2 **ppInfo2, IN DRIVER_INFO_3 **ppDrvInfo3 ) { BOOL bRetval = FALSE; PPRINTER_INFO_2 pInfo2 = NULL; PDRIVER_INFO_3 pDrvInfo3 = NULL; DWORD cbInfo = 0; LONG lResult = 0; TStatusB bStatus( DBG_WARN, ERROR_ACCESS_DENIED, ERROR_INSUFFICIENT_BUFFER ); // // Open the printer. // HANDLE hPrinter = NULL; DWORD dwAccess = PRINTER_READ; TStatus Status( DBG_WARN ); Status DBGCHK = TPrinter::sOpenPrinter( pszPrinterName, &dwAccess, &hPrinter ); if( Status ){ goto Cleanup; } // // Get the Printer info 2. // cbInfo = 0; bStatus DBGCHK = VDataRefresh::bGetPrinter( hPrinter, 2, (PVOID*)&pInfo2, &cbInfo ); if( !bStatus ){ goto Cleanup; } // // Get the driver info 3. // cbInfo = 0; bStatus DBGCHK = VDataRefresh::bGetPrinterDriver( hPrinter, NULL, 3, (PVOID*)&pDrvInfo3, &cbInfo ); if( !bStatus ){ goto Cleanup; } // // Success copy back the info pointers. // *ppInfo2 = pInfo2; *ppDrvInfo3 = pDrvInfo3; bRetval = TRUE; Cleanup: if( hPrinter ){ ClosePrinter( hPrinter ); } if( !bRetval ){ FreeMem( pInfo2 ); FreeMem( pDrvInfo3 ); } return bRetval; } /*++ Routine Name: GetCurrentTimeAndDate Routine Description: Routine to get the current time and date in a formatted string to print on the test page. Arguments: cchText - size in characters of the provided buffer pszText - pointer to buffer where to place time and date text. Return Value: TRUE is valid and returned in provided buffer, otherwise FALSE. --*/ BOOL GetCurrentTimeAndDate( IN UINT cchText, IN LPTSTR pszText ) { TCHAR szTemp[kStrMax]; SPLASSERT( cchText ); SPLASSERT( pszText ); // // Initialy terminate the buffer. // pszText[0] = 0; // // Get the current local time. // SYSTEMTIME LocalTime; GetSystemTime( &LocalTime ); if ( !SystemTimeToTzSpecificLocalTime( NULL, &LocalTime, &LocalTime )) { DBGMSG( DBG_TRACE, ( "SysTimeToTzSpecLocalTime failed %d\n", GetLastError( ))); return FALSE; } if( !GetTimeFormat( LOCALE_USER_DEFAULT, 0, &LocalTime, NULL, pszText, cchText )) { DBGMSG( DBG_TRACE, ( "GetTimeFormat failed with %d", GetLastError( ))); return FALSE; } StringCchCat( pszText, cchText, gszSpace ); if( !GetDateFormat( LOCALE_USER_DEFAULT, 0, &LocalTime, NULL, szTemp, ARRAYSIZE(szTemp) )) { DBGMSG( DBG_TRACE, ( "GetDateFomat failed with %d\n", GetLastError( ))); return FALSE; } StringCchCat( pszText, cchText, szTemp ); return TRUE; }