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.

1362 lines
36 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. All rights reserved.
  4. Module Name:
  5. tstpage.cxx
  6. Abstract:
  7. Print Test Page
  8. Author:
  9. Steve Kiraly (SteveKi) 16-Jan-1996
  10. Revision History:
  11. Lazar Ivanov (LazarI) Jun-2000 (Win64 fixes)
  12. --*/
  13. #include "precomp.hxx"
  14. #pragma hdrstop
  15. #include "tstpage.hxx"
  16. /********************************************************************
  17. Message map used after the test page is printed.
  18. ********************************************************************/
  19. //
  20. // Check if the printer name contains a
  21. // trailing spaces
  22. //
  23. BOOL
  24. bContainTrailingSpaces(
  25. IN LPCTSTR pszShareName
  26. )
  27. {
  28. BOOL bResult = FALSE;
  29. if( pszShareName )
  30. {
  31. //
  32. // Check for trailing spaces here
  33. //
  34. int iLen = lstrlen(pszShareName);
  35. if( iLen > 0 && TEXT(' ') == pszShareName[iLen-1] )
  36. {
  37. bResult = TRUE;
  38. }
  39. }
  40. return bResult;
  41. }
  42. //
  43. // Print test page to specified printer
  44. //
  45. BOOL
  46. bPrintTestPage(
  47. IN HWND hWnd,
  48. IN LPCTSTR pszPrinterName,
  49. IN LPCTSTR pszShareName
  50. )
  51. {
  52. INT_PTR iStatus;
  53. DBGMSG( DBG_TRACE, ( "bPrintTestPage\n" ) );
  54. DBGMSG( DBG_TRACE, ( "PrinterName " TSTR "\n", pszPrinterName ) );
  55. //
  56. // Set the last error to a known value. This will allow us to
  57. // display a reasonable error messege if some api fails to print
  58. // the test page. The createDC call in particular may fail if
  59. // the driver does not exist on this machine.
  60. //
  61. SetLastError( ERROR_SUCCESS );
  62. //
  63. // We need to check the name for trailing spaces, which
  64. // can cause a problems with NT5 -> Win98 downlevel connections.
  65. // The problem is that CreateFile(...) function fails if
  66. // the printer share name contains trailing spaces.
  67. //
  68. if( bContainTrailingSpaces( pszShareName ) ) {
  69. //
  70. // Warn the user for eventual problems in this case
  71. //
  72. iMessage( hWnd,
  73. IDS_ERR_PRINTER_PROP_TITLE,
  74. IDS_WARN_TRAILINGSPACES_IN_PRINTERNAME,
  75. MB_OK|MB_ICONEXCLAMATION,
  76. kMsgNone,
  77. NULL );
  78. }
  79. //
  80. // Insure we don't have a null printer name.
  81. // or the test page failed to print.
  82. //
  83. if( !pszPrinterName ||
  84. !bDoPrintTestPage(hWnd, pszPrinterName ) ){
  85. DBGMSG( DBG_WARN, ( "Print test page failed with %d\n", GetLastError() ));
  86. //
  87. // If the user canceled the operation then just exit.
  88. //
  89. if( GetLastError() == ERROR_CANCELLED ){
  90. return TRUE;
  91. }
  92. //
  93. // Ask the user if they want to goto the print
  94. // trouble shooter.
  95. //
  96. if( IDYES == iMessage( hWnd,
  97. IDS_ERR_PRINTER_PROP_TITLE,
  98. IDS_ERR_TESTPAGE,
  99. MB_YESNO|MB_ICONEXCLAMATION,
  100. kMsgGetLastError,
  101. NULL ) ){
  102. //
  103. // This jumps to the windows printer help trouble shooter section.
  104. // We have to execute the troubleshooter in a separate process because this
  105. // code sometimes is executed in a rundll process, which goes away imediately
  106. // and the help window goes away too. We don't want the help window to go away.
  107. //
  108. ShellExecute( hWnd, TEXT("open"), TEXT("helpctr.exe"), gszHelpTroubleShooterURL, NULL, SW_SHOWNORMAL );
  109. }
  110. return FALSE;
  111. }
  112. TString strMachineName;
  113. LPCTSTR pszServer, pszPrinter;
  114. TCHAR szScratch[PRINTER_MAX_PATH];
  115. if( SUCCEEDED(PrinterSplitFullName(pszPrinterName, szScratch, ARRAYSIZE(szScratch), &pszServer, &pszPrinter)) &&
  116. bGetMachineName(strMachineName) &&
  117. 0 == _tcsicmp(pszServer, strMachineName) )
  118. {
  119. // this is local printer - update the name
  120. pszPrinterName = pszPrinter;
  121. }
  122. //
  123. // Prompt user, asking if the test page printed ok.
  124. //
  125. iStatus = DialogBoxParam( ghInst,
  126. MAKEINTRESOURCE( DLG_END_TESTPAGE ),
  127. hWnd,
  128. EndTestPageDlgProc,
  129. (LPARAM)pszPrinterName );
  130. //
  131. // User indicated page did not print, display winhelp.
  132. //
  133. if( iStatus != IDOK ){
  134. //
  135. // This jumps to the windows printer help trouble shooter section.
  136. // We have to execute the troubleshooter in a separate process because this
  137. // code sometimes is executed in a rundll process, which goes away imediately
  138. // and the help window goes away too. We don't want the help window to go away.
  139. //
  140. ShellExecute( hWnd, TEXT("open"), TEXT("helpctr.exe"), gszHelpTroubleShooterURL, NULL, SW_SHOWNORMAL );
  141. return FALSE;
  142. }
  143. //
  144. // Set proper return code.
  145. //
  146. return TRUE;
  147. }
  148. //
  149. // Print test page to the specified printer.
  150. //
  151. BOOL
  152. bDoPrintTestPage(
  153. IN HWND hWnd,
  154. IN LPCTSTR pszPrinterName
  155. )
  156. {
  157. DOCINFO DocInfo;
  158. TCHAR szBuf[kStrMax];
  159. RECT rc;
  160. BOOL bDocumentStarted = FALSE;
  161. HDC hdcPrint = NULL;
  162. DWORD dwLastError = ERROR_SUCCESS;
  163. BOOL bStatus = FALSE;
  164. UINT uRightAlign = 0;
  165. //
  166. // Create a printer DC
  167. //
  168. hdcPrint = CreateDC( _T("WINSPOOL"), pszPrinterName, NULL, NULL );
  169. if( hdcPrint == NULL ){
  170. DBGMSG( DBG_WARN, ( "CreateDC failed with %d\n", GetLastError() ) );
  171. goto Cleanup;
  172. }
  173. //
  174. // Load the test page name.
  175. //
  176. if( !LoadString( ghInst, IDS_TP_TESTPAGENAME, szBuf, COUNTOF(szBuf) ) ){
  177. DBGMSG( DBG_WARN, ( "Load test page name failed with %d\n", GetLastError() ) );
  178. goto Cleanup;
  179. }
  180. //
  181. // Start the document
  182. //
  183. ZeroMemory( &DocInfo, sizeof( DOCINFO ));
  184. DocInfo.cbSize = sizeof( DocInfo );
  185. DocInfo.lpszDocName = szBuf;
  186. DocInfo.lpszOutput = NULL;
  187. DocInfo.lpszDatatype = NULL;
  188. DocInfo.fwType = 0;
  189. //
  190. // Start the print job.
  191. //
  192. if( StartDoc( hdcPrint, &DocInfo ) <= 0 ) {
  193. DBGMSG( DBG_WARN, ( "StartDoc failed with %d\n", GetLastError() ) );
  194. goto Cleanup;
  195. }
  196. //
  197. // Indicate document was started
  198. //
  199. bDocumentStarted = TRUE;
  200. //
  201. // Start the test page.
  202. //
  203. if( StartPage( hdcPrint ) <= 0 ){
  204. DBGMSG( DBG_WARN, ( "StartPage failed with %d\n", GetLastError() ) );
  205. goto Cleanup;
  206. }
  207. if (GetWindowLongPtr(hWnd, GWL_EXSTYLE) & WS_EX_LAYOUTRTL) {
  208. uRightAlign = DT_RIGHT | DT_RTLREADING;
  209. }
  210. //
  211. // Get Margin clip box, Margins are expressed in 100th of an inch.
  212. //
  213. rc = GetMarginClipBox( hdcPrint, 50, 100, 100, 100 );
  214. //
  215. // Print Test Page Header
  216. //
  217. if( !bPrintTestPageHeader( hdcPrint, TRUE, TRUE, &rc, uRightAlign ) ){
  218. DBGMSG( DBG_WARN, ( "bPrintTestPageHeader failed with %d\n", GetLastError() ) );
  219. goto Cleanup;
  220. }
  221. //
  222. // Print basic test page information.
  223. //
  224. if( !bPrintTestPageInfo( hdcPrint, &rc, pszPrinterName, uRightAlign ) ){
  225. DBGMSG( DBG_WARN, ( "bPrintTestPageInfo failed with %d\n", GetLastError() ) );
  226. goto Cleanup;
  227. }
  228. //
  229. // End the page.
  230. //
  231. if( EndPage( hdcPrint ) <= 0 ){
  232. DBGMSG( DBG_WARN, ( "EndPage failed with %d\n", GetLastError() ) );
  233. goto Cleanup;
  234. }
  235. //
  236. // End the print job.
  237. //
  238. if( EndDoc( hdcPrint ) <= 0 ){
  239. DBGMSG( DBG_WARN, ( "StartDoc failed with %d\n", GetLastError() ) );
  240. goto Cleanup;
  241. }
  242. //
  243. // Set error status.
  244. //
  245. bDocumentStarted = FALSE;
  246. bStatus = TRUE;
  247. SetLastError( ERROR_SUCCESS );
  248. //
  249. // Cleanup any outstanding resources.
  250. //
  251. Cleanup:
  252. if( !bStatus ){
  253. //
  254. // Save the last error state.
  255. //
  256. dwLastError = GetLastError();
  257. //
  258. // If the document was started then abort the document.
  259. //
  260. if( bDocumentStarted && AbortDoc( hdcPrint ) <= 0 ){
  261. DBGMSG( DBG_WARN, ( "AbortDoc failed with %d\n", GetLastError() ) );
  262. }
  263. }
  264. //
  265. // Release DC
  266. //
  267. if( hdcPrint ){
  268. DeleteDC( hdcPrint );
  269. }
  270. if( !bStatus ){
  271. //
  272. // Restore the last error state back to the caller.
  273. //
  274. SetLastError( dwLastError );
  275. }
  276. return bStatus;
  277. }
  278. /*++
  279. Routine Name:
  280. GetMarginClipBox
  281. Routine Description:
  282. Calculates the correct margin rectangle for the specifed DC.
  283. Note that a printer DC has non-printable regions on all sized,
  284. this routine takes these regions into account when calculating
  285. the correct margins. Margins are measured from the extream
  286. physical edge of the page.
  287. Arguments:
  288. hdcPrint - Printer device context
  289. iLeft - Desired left margin
  290. iRight - Desired left margin
  291. iTop - Desired left margin
  292. iBottom - Desired left margin
  293. Return Value:
  294. Rectangle which reflects the specified margins. Note if the
  295. desired margins are smaller than what the device is capable
  296. of then the clip box is adjusted to the physical printers
  297. margin.
  298. --*/
  299. RECT
  300. GetMarginClipBox(
  301. IN HDC hdcPrint,
  302. IN INT iLeft,
  303. IN INT iRight,
  304. IN INT iTop,
  305. IN INT iBottom
  306. )
  307. {
  308. INT npx = GetDeviceCaps( hdcPrint, PHYSICALOFFSETX );
  309. INT npy = GetDeviceCaps( hdcPrint, PHYSICALOFFSETY );
  310. INT iLogicPixelsX = GetDeviceCaps( hdcPrint, LOGPIXELSX );
  311. INT iLogicPixelsY = GetDeviceCaps( hdcPrint, LOGPIXELSY );
  312. RECT rcPage;
  313. rcPage.left = max( 0, iLogicPixelsX * iLeft / kInchConversion - npx );
  314. rcPage.top = max( 0, iLogicPixelsY * iTop / kInchConversion - npy );
  315. INT iPhysWidth = GetDeviceCaps( hdcPrint, PHYSICALWIDTH );
  316. INT iPhysHeight = GetDeviceCaps( hdcPrint, PHYSICALHEIGHT );
  317. INT iHorzRes = GetDeviceCaps( hdcPrint, HORZRES );
  318. INT iVertRes = GetDeviceCaps( hdcPrint, VERTRES );
  319. INT nprx = iPhysWidth - (npx + iHorzRes);
  320. INT npby = iPhysHeight - (npy + iVertRes);
  321. rcPage.right = iHorzRes - max( 0, iLogicPixelsX * iRight / kInchConversion - nprx );
  322. rcPage.bottom = iVertRes - max( 0, iLogicPixelsY * iBottom / kInchConversion - npby );
  323. return rcPage;
  324. }
  325. /*++
  326. Routine Name:
  327. bPrintTestPageHeader
  328. Routine Description:
  329. Print out a header for the test page
  330. Arguments:
  331. hdcPrint - Printer device context
  332. bDisplayLogo - flag TRUE display logo, false do not display logo
  333. bDoGraphics - flag TRUE do graphics, false do not do graphics
  334. lpRect - Pointer to a rectangle which describes the margins
  335. uRightAlign - flags to print the test page right aligned
  336. Return Value:
  337. TRUE if header was printed, FALSE if error occurred.
  338. --*/
  339. BOOL
  340. bPrintTestPageHeader(
  341. IN HDC hdc,
  342. IN BOOL bDisplayLogo,
  343. IN BOOL bDoGraphics,
  344. IN RECT *lprcPage,
  345. IN UINT uRightAlign
  346. )
  347. {
  348. enum Info { PLACEABLE_SIGNATURE = 0x9AC6CDD7,
  349. METAFILEHEADER_SIZE = 22,
  350. };
  351. BOOL bSuccess = TRUE;
  352. INT nXInch = GetDeviceCaps( hdc, LOGPIXELSX );
  353. INT nYInch = GetDeviceCaps( hdc, LOGPIXELSY );
  354. //
  355. // If device can do graphics.
  356. //
  357. if( RC_BITBLT & GetDeviceCaps( hdc, RASTERCAPS ) && bDoGraphics ){
  358. if( bDisplayLogo ) {
  359. HRSRC hRes = FindResource( ghInst,
  360. MAKEINTRESOURCE(IDR_MF_LOGO),
  361. TEXT("METAFILE") );
  362. if( hRes ) {
  363. //
  364. // Device can handle BitBlt calls--do graphic
  365. //
  366. LPBYTE lpMetaFile = (LPBYTE)LoadResource( ghInst, hRes );
  367. if( lpMetaFile ){
  368. LPMETAHEADER lpMH;
  369. HMETAFILE hmf;
  370. if(PLACEABLE_SIGNATURE==*((LPDWORD)lpMetaFile)) {
  371. lpMetaFile+=METAFILEHEADER_SIZE;
  372. }
  373. lpMH=(LPMETAHEADER)lpMetaFile;
  374. if( ( hmf=SetMetaFileBitsEx(lpMH->mtSize*sizeof(WORD),(LPBYTE)lpMH)) != NULL ){
  375. INT nSavedDC=SaveDC(hdc);
  376. SetMapMode(hdc,MM_ISOTROPIC);
  377. SetWindowOrgEx(hdc,0,0,NULL);
  378. SetWindowExtEx(hdc,100,100,NULL);
  379. SetViewportExtEx(hdc,nXInch,nYInch,NULL);
  380. SetViewportOrgEx(hdc,nXInch/2,nYInch/2,NULL);
  381. bSuccess=PlayMetaFile(hdc,hmf);
  382. DeleteMetaFile(hmf);
  383. //
  384. // Restore the previous GDI state
  385. //
  386. if(nSavedDC)
  387. RestoreDC(hdc,nSavedDC);
  388. }
  389. }
  390. }
  391. }
  392. //
  393. // Output TrueType font at top of page in 36 point Times New Roman
  394. //
  395. HFONT hOldFont;
  396. hOldFont = CreateAndSelectFont( hdc, IDS_TP_TIMESNEWROMAN, 36 );
  397. if( hOldFont ){
  398. //
  399. // Position text so it aligns with the graphic & is 2" into
  400. // the printable region.
  401. //
  402. lprcPage->top=nYInch/2;
  403. lprcPage->left=nXInch*2;
  404. //
  405. // Print the test page header.
  406. //
  407. bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_HEADER,'\0');
  408. //
  409. // Restore the margins.
  410. //
  411. lprcPage->top=nYInch*2;
  412. lprcPage->left=nXInch/2;
  413. //
  414. // Restore the font
  415. //
  416. DeleteObject( SelectObject( hdc, hOldFont ) );
  417. } else {
  418. DBGMSG( DBG_WARN, ( "CreateAndSelectFontFailed with %d.\n", GetLastError() ) );
  419. bSuccess = FALSE;
  420. }
  421. } else {
  422. DBGMSG( DBG_TRACE, ( "Printer does not do graphics.\n" ) );
  423. //
  424. // Device can't do graphics--use default font for title. Center it
  425. // horizontally, half an inch from the top of the printable area.
  426. //
  427. lprcPage->top=nYInch/2;
  428. //
  429. // Display normal text header.
  430. //
  431. bSuccess &= PrintString(hdc,lprcPage,DT_TOP|DT_CENTER,IDS_TP_HEADER,'\n');
  432. //
  433. // Display all of the other strings 1/2" from the left margin
  434. //
  435. lprcPage->left=nXInch/2;
  436. }
  437. return bSuccess;
  438. }
  439. /*++
  440. Routine Name:
  441. bPrintTestPageInfo
  442. Routine Description:
  443. Print out a printer info on the test page.
  444. Arguments:
  445. hdcPrint - Printer device context
  446. lpRect - Pointer to a rectangle which describes the margins
  447. uRightAlign - flags to print the test page right aligned
  448. Return Value:
  449. TRUE if header was printed, FALSE if error occurred.
  450. --*/
  451. BOOL
  452. bPrintTestPageInfo(
  453. IN HDC hdc,
  454. IN LPRECT lprcPage,
  455. IN LPCTSTR pszPrinterName,
  456. IN UINT uRightAlign
  457. )
  458. {
  459. TCHAR szBuffer[kServerBufMax];
  460. TCHAR szBuff[kStrMax];
  461. TEXTMETRIC tm;
  462. LPCTSTR pszBuffer = NULL;
  463. DWORD dwDriverVersion = 0;
  464. BOOL bSuccess = FALSE;
  465. HFONT hOldFont = NULL;
  466. DWORD dwBufferSize = COUNTOF( szBuffer );
  467. PPRINTER_INFO_2 lppi2 = NULL;
  468. PDRIVER_INFO_3 lpdi3 = NULL;
  469. HDC hdcScreen = NULL;
  470. UINT nYInch;
  471. TString strTemp;
  472. //
  473. // Get the screen device context.
  474. //
  475. hdcScreen = GetDC( NULL );
  476. if( !hdcScreen ){
  477. DBGMSG( DBG_WARN, ( "GetDC failed with %d\n", GetLastError() ) );
  478. goto Cleanup;
  479. }
  480. #ifdef USE_DEVICE_FONT
  481. //
  482. // Get the logical pixes in the y direction.
  483. //
  484. nYInch = GetDeviceCaps( hdc, LOGPIXELSY);
  485. if( !nYInch ){
  486. DBGMSG( DBG_WARN, ( "GetDeviceCaps failed with %d\n", GetLastError() ) );
  487. goto Cleanup;
  488. }
  489. //
  490. // This stuff is designed to be printed in a fixed-pitch font,
  491. // using the system character set. If the current font fails
  492. // any criterion, use CourierNew in the system charset.
  493. //
  494. if( !GetTextMetrics( hdc, &tm ) ||
  495. ( tm.tmPitchAndFamily & TMPF_FIXED_PITCH ) ||
  496. ( GetTextCharset(hdc) != GetTextCharset( hdcScreen ) ) ||
  497. ( tm.tmHeight > MulDiv( 12, nYInch, 72 ) ) ){
  498. DBGMSG( DBG_TRACE, ( "Creating font.\n" ) );
  499. hOldFont = CreateAndSelectFont( hdc, IDS_TP_FONTNAMEINFOTEXT, 10 );
  500. if( !hOldFont ){
  501. DBGMSG( DBG_WARN, ( "CreateAndSelectFont failed with %d\n", GetLastError() ) );
  502. goto Cleanup;
  503. }
  504. } else {
  505. DBGMSG( DBG_TRACE, ( "Using Default printer font.\n" ) );
  506. }
  507. #else
  508. hOldFont = CreateAndSelectFont( hdc, IDS_TP_FONTNAMEINFOTEXT, 10 );
  509. if( !hOldFont ){
  510. DBGMSG( DBG_WARN, ( "CreateAndSelectFont failed with %d\n", GetLastError() ) );
  511. goto Cleanup;
  512. }
  513. #endif
  514. //
  515. // Get the printer information to print.
  516. //
  517. if( !bGetPrinterInfo( pszPrinterName, &lppi2, &lpdi3 ) ){
  518. DBGMSG( DBG_WARN, ( "bGetPrinterInfo failed with %d\n", GetLastError() ) );
  519. goto Cleanup;
  520. }
  521. // Machine Name:
  522. if( lppi2->pServerName ){
  523. // If server name is not null copy string
  524. StringCchCopy( szBuffer, ARRAYSIZE(szBuffer), lppi2->pServerName );
  525. } else {
  526. // Get the computer name.
  527. GetComputerName( szBuffer, &dwBufferSize );
  528. }
  529. // Remove any leading slashes
  530. for( pszBuffer = szBuffer; pszBuffer && ( *pszBuffer == TEXT( '\\' ) ); pszBuffer++ )
  531. ;
  532. bSuccess = TRUE;
  533. // Tell the user that we installed successfully.
  534. bSuccess &= PrintString( hdc, lprcPage, uRightAlign, IDS_TP_CONGRATULATIONS );
  535. // Tell the user what they installed.
  536. bSuccess &= PrintString( hdc, lprcPage, uRightAlign, IDS_TP_PRINTERISINSTALLED, lppi2->pDriverName, pszBuffer );
  537. // Get the time and date.
  538. bSuccess &= GetCurrentTimeAndDate( COUNTOF( szBuff ), szBuff );
  539. // Print the time and date.
  540. bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_TIMEDATE, szBuff );
  541. // Print the machine name.
  542. bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_MACHINENAME, pszBuffer );
  543. // Printer Name:
  544. if( SUCCEEDED(AbbreviateText(lppi2->pPrinterName, MAX_TESTPAGE_DISPLAYNAME, &strTemp)) )
  545. {
  546. bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_PRINTERNAME, (LPCTSTR)strTemp );
  547. }
  548. else
  549. {
  550. bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_PRINTERNAME, lppi2->pPrinterName );
  551. }
  552. // Printer Model:
  553. bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_PRINTERMODEL, lppi2->pDriverName);
  554. // Color Capability
  555. if( lppi2->pDevMode )
  556. {
  557. bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IsColorDevice(lppi2->pDevMode)?IDS_TP_COLOR:IDS_TP_MONO);
  558. }
  559. // Printer Port:
  560. if( lppi2->pPortName && SUCCEEDED(AbbreviateText(lppi2->pPortName, MAX_TESTPAGE_DISPLAYNAME, &strTemp)) )
  561. bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_PORTNAME, (LPCTSTR)strTemp);
  562. // Data Type:
  563. if( lppi2->pDatatype )
  564. bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_DATATYPE, lppi2->pDatatype);
  565. // Share Name
  566. if( lppi2->pShareName && SUCCEEDED(AbbreviateText(lppi2->pShareName, MAX_TESTPAGE_DISPLAYNAME, &strTemp)) )
  567. bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_SHARE_NAME, (LPCTSTR)strTemp);
  568. // Location
  569. if( lppi2->pLocation && SUCCEEDED(AbbreviateText(lppi2->pLocation, MAX_TESTPAGE_DISPLAYNAME, &strTemp)) )
  570. bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_LOCATION, (LPCTSTR)strTemp);
  571. // Comment
  572. if( lppi2->pComment && SUCCEEDED(AbbreviateText(lppi2->pComment, MAX_TESTPAGE_DISPLAYNAME, &strTemp)) )
  573. bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_COMMENT, (LPCTSTR)strTemp);
  574. // DRV Name:
  575. bSuccess &= PrintBaseFileName(hdc,lpdi3->pDriverPath,lprcPage, IDS_TP_DRV_NAME, uRightAlign);
  576. // Data file (if it's different from the driver name)
  577. if(lstrcmpi(lpdi3->pDriverPath,lpdi3->pDataFile))
  578. {
  579. bSuccess &= PrintBaseFileName(hdc,lpdi3->pDataFile,lprcPage, IDS_TP_DATA_FILE, uRightAlign);
  580. }
  581. // Config file (if it's different from the driver name)
  582. if(lstrcmpi(lpdi3->pDriverPath,lpdi3->pDataFile))
  583. {
  584. bSuccess &= PrintBaseFileName(hdc,lpdi3->pConfigFile,lprcPage,
  585. IDS_TP_CONFIG_FILE, uRightAlign);
  586. }
  587. // Help file
  588. if( lpdi3->pHelpFile )
  589. {
  590. bSuccess &= PrintBaseFileName(hdc,lpdi3->pHelpFile,lprcPage,IDS_TP_HELP_FILE, uRightAlign);
  591. }
  592. // Driver version, if available
  593. if((dwDriverVersion=DeviceCapabilities(lppi2->pPrinterName,lppi2->pPortName,DC_DRIVER,NULL,NULL)) != (DWORD)-1)
  594. {
  595. bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_DRV_VERSION,
  596. HIBYTE(LOWORD(dwDriverVersion)),
  597. LOBYTE(LOWORD(dwDriverVersion)));
  598. }
  599. // Environment
  600. if( lpdi3->pEnvironment )
  601. bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_ENVIRONMENT,lpdi3->pEnvironment);
  602. // Monitor
  603. if( lpdi3->pMonitorName )
  604. bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_MONITOR,lpdi3->pMonitorName);
  605. // Default Datatype
  606. if( lpdi3->pDefaultDataType )
  607. bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_DEFAULT_DATATYPE,lpdi3->pDefaultDataType);
  608. // Dependent Files:
  609. LPTSTR lpTest;
  610. lpTest = lpdi3->pDependentFiles;
  611. if(lpTest && *lpTest)
  612. {
  613. bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_DEPENDENTLIST);
  614. while(*lpTest)
  615. {
  616. bSuccess &= PrintDependentFile(hdc,lprcPage,lpTest, lpdi3->pDriverPath, uRightAlign);
  617. lpTest += (lstrlen(lpTest)+1);
  618. }
  619. }
  620. // Tell the user that we're done now
  621. bSuccess &= PrintString(hdc,lprcPage,uRightAlign,IDS_TP_TESTPAGEEND);
  622. //
  623. // Release the resources.
  624. //
  625. Cleanup:
  626. FreeMem( lpdi3 );
  627. FreeMem( lppi2 );
  628. if( hOldFont ){
  629. DeleteObject( SelectObject( hdc, hOldFont ) );
  630. }
  631. if( hdcScreen ){
  632. ReleaseDC( NULL, hdcScreen );
  633. }
  634. return bSuccess;
  635. }
  636. //-------------------------------------------------------------------------
  637. // Function: IsColorDevice(hdc)
  638. //
  639. // Action: Determine whether or not this device supports color
  640. //
  641. // Return: TRUE if it does, FALSE if it doesn't
  642. //-------------------------------------------------------------------------
  643. BOOL
  644. IsColorDevice(
  645. IN DEVMODE *pDevMode
  646. )
  647. {
  648. //
  649. // Assume monochrome.
  650. //
  651. DWORD dmColor = DMCOLOR_MONOCHROME;
  652. //
  653. // Get the color support if available.
  654. //
  655. if( pDevMode && ( pDevMode->dmFields & DM_COLOR ) )
  656. dmColor = pDevMode->dmColor;
  657. //
  658. // TRUE color supported, FALSE monochrome.
  659. //
  660. return dmColor == DMCOLOR_COLOR;
  661. }
  662. /*++
  663. Routine Name:
  664. CreateAndSelectFont
  665. Routine Description:
  666. Get a font with the face, style & point size for this device,
  667. and the character set from the screen DC, then select it in.
  668. Arguments:
  669. hdc - Currently selected dc
  670. uResFaceName - Type face name resource ID
  671. uPtSize - Desired point size
  672. Return Value:
  673. The OLD font handle if successful, Failure NULL
  674. --*/
  675. HFONT
  676. CreateAndSelectFont(
  677. IN HDC hdc,
  678. IN UINT uResFaceName,
  679. IN UINT uPtSize
  680. )
  681. {
  682. INT nYInch = 0;
  683. HDC hdcScreen = NULL;
  684. HFONT hNewFont = NULL;
  685. HFONT hOldFont = NULL;
  686. LOGFONT lf;
  687. //
  688. // Logical pixels in the y direction.
  689. //
  690. nYInch = GetDeviceCaps( hdc, LOGPIXELSY);
  691. //
  692. // Get a handle to the screen DC for creating a font.
  693. //
  694. hdcScreen = GetDC( NULL );
  695. if( !hdcScreen ){
  696. DBGMSG( DBG_TRACE, ( "CreateAndSelectFont - GetDC failed with %d.\n", GetLastError() ) );
  697. goto Cleanup;
  698. }
  699. ZeroMemory( &lf, sizeof( LOGFONT ) );
  700. lf.lfHeight = MulDiv( uPtSize, nYInch, 72);
  701. lf.lfWeight = 400;
  702. lf.lfCharSet = (BYTE)GetTextCharset( hdcScreen );
  703. lf.lfQuality = (BYTE)PROOF_QUALITY;
  704. lf.lfPitchAndFamily = FF_DONTCARE;
  705. //
  706. // Load the font face name from the resource file.
  707. //
  708. if( !LoadString( ghInst, uResFaceName, lf.lfFaceName, COUNTOF( lf.lfFaceName ) ) ){
  709. DBGMSG( DBG_TRACE, ( "CreateAndSelectFont - LoadString failed with %d.\n", GetLastError() ) );
  710. goto Cleanup;
  711. }
  712. //
  713. // Create the font.
  714. //
  715. hNewFont = CreateFontIndirect( &lf );
  716. if( !hNewFont ){
  717. DBGMSG( DBG_TRACE, ( "CreateAndSelectFont - CreateFontIndirect failed with %d.\n", GetLastError() ) );
  718. goto Cleanup;
  719. }
  720. //
  721. // Select the new font into the current dc and return the old font handle.
  722. //
  723. hOldFont = (HFONT)SelectObject( hdc, hNewFont );
  724. if( !hOldFont ||
  725. (ULONG_PTR)hOldFont == GDI_ERROR ){
  726. DBGMSG( DBG_TRACE, ( "CreateAndSelectFont - SelectObject failed with %d, %d.\n", hOldFont, GetLastError() ) );
  727. hOldFont = NULL; // Indicate failure to caller.
  728. goto Cleanup;
  729. }
  730. Cleanup:
  731. //
  732. // Release the screen dc handle
  733. //
  734. if( hdcScreen ){
  735. ReleaseDC( NULL, hdcScreen );
  736. }
  737. return hOldFont;
  738. }
  739. //-------------------------------------------------------------------------
  740. // Function: PrintString(hdc,lprcPage,uFlags,uResId,...)
  741. //
  742. // Action: Build a formatted string, then print it on the page using the
  743. // current font. Update lprcPage after the output.
  744. //
  745. // Return: TRUE if successful, FALSE if not
  746. //-------------------------------------------------------------------------
  747. BOOL
  748. cdecl
  749. PrintString(
  750. HDC hdc,
  751. LPRECT lprcPage,
  752. UINT uFlags,
  753. UINT uResId,
  754. ...
  755. )
  756. {
  757. BOOL bSuccess = FALSE;
  758. va_list pArgs;
  759. //
  760. // Get pointer to first un-named argument.
  761. //
  762. va_start( pArgs, uResId );
  763. //
  764. // Alocate the format and string buffer.
  765. //
  766. TCHAR npFormat[kStrMax];
  767. TCHAR npBuffer[1024];
  768. //
  769. // Load the string resource.
  770. //
  771. if( LoadString( ghInst, uResId, npFormat, COUNTOF( npFormat ) ) ){
  772. //
  773. // Format the string.
  774. //
  775. StringCchVPrintf( npBuffer, COUNTOF( npBuffer ), npFormat, pArgs );
  776. //
  777. // Output the string, updating the rectangle.
  778. //
  779. INT nHeight;
  780. nHeight = DrawText( hdc,
  781. npBuffer,
  782. -1,
  783. lprcPage,
  784. uFlags|DT_EXPANDTABS|DT_LEFT|DT_NOPREFIX|DT_WORDBREAK);
  785. //
  786. // If any text was drawn.
  787. //
  788. if( nHeight ){
  789. //
  790. // Update the rectangle
  791. //
  792. lprcPage->top += nHeight;
  793. bSuccess=TRUE;
  794. } else {
  795. DBGMSG( DBG_TRACE, ( "PrintString - DrawText failed with %d\n", GetLastError() ) );
  796. }
  797. } else {
  798. DBGMSG( DBG_TRACE, ( "PrintString - LoadString failed with %d\n", GetLastError() ) );
  799. }
  800. va_end( pArgs );
  801. return bSuccess;
  802. }
  803. //-------------------------------------------------------------------------
  804. // Function: PrintBaseFileName(hdc,lpFile,lprcPage,uResID)
  805. //
  806. // Action: Print the base filename as part of a formatted string
  807. //
  808. // Return: Whatever PrintString returns
  809. //-------------------------------------------------------------------------
  810. BOOL
  811. PrintBaseFileName(
  812. IN HDC hdc,
  813. IN LPCTSTR lpFile,
  814. IN OUT LPRECT lprcPage,
  815. IN UINT uResID,
  816. IN UINT uRightAlign
  817. )
  818. {
  819. LPCTSTR lpTest;
  820. while( ( lpTest = _tcspbrk( lpFile, TEXT( "\\" ) ) ) != NULL )
  821. lpFile = ++lpTest;
  822. return PrintString( hdc, lprcPage, uRightAlign, uResID, lpFile );
  823. }
  824. //-------------------------------------------------------------------------
  825. // Function: PrintDependentFile(hdc,lprcPage,lpFile,lpDriver)
  826. //
  827. // Action: Print a line for this dependent file. Include its full path.
  828. // Try to include its version information, and it this is the
  829. // actual driver file, see if it's a minidriver and include
  830. // that information.
  831. //
  832. // Return: TRUE if successful, FALSE if not
  833. //-------------------------------------------------------------------------
  834. BOOL
  835. PrintDependentFile(
  836. IN HDC hdc,
  837. IN LPRECT lprcPage,
  838. IN LPTSTR lpFile,
  839. IN LPTSTR lpDriver,
  840. IN UINT uRightAlign
  841. )
  842. {
  843. DWORD dwSize;
  844. DWORD dwHandle;
  845. WORD wGPCVersion;
  846. LPBYTE lpData = NULL;
  847. LPWORD lpVersion = NULL;
  848. BOOL bSuccess = FALSE;
  849. static TCHAR cszTranslation[] = TEXT( "\\VarFileInfo\\Translation" );
  850. static TCHAR cszFileVersion[] = TEXT( "\\StringFileInfo\\%04X%04X\\FileVersion" );
  851. static TCHAR cszProductVersion[] = TEXT( "\\StringFileInfo\\%04X%04X\\ProductVersion" );
  852. //
  853. // Get the file attributes.
  854. //
  855. if( HFILE_ERROR == GetFileAttributes( lpFile ) ){
  856. return FALSE;
  857. }
  858. dwSize = GetFileVersionInfoSize( lpFile, &dwHandle );
  859. if( dwSize ){
  860. lpData=(LPBYTE)AllocMem( dwSize );
  861. if( lpData ){
  862. UINT uSize;
  863. TCHAR szTemp[MAX_PATH];
  864. LPWORD lpTrans;
  865. if(GetFileVersionInfo(lpFile,dwHandle,dwSize,lpData) &&
  866. VerQueryValue(lpData,cszTranslation,(LPVOID*)&lpTrans,&uSize) &&
  867. uSize){
  868. StringCchPrintf(szTemp,ARRAYSIZE(szTemp),cszFileVersion,*lpTrans,*(lpTrans+1));
  869. if(!VerQueryValue(lpData,szTemp,(LPVOID*)&lpVersion,&uSize))
  870. {
  871. StringCchPrintf(szTemp,ARRAYSIZE(szTemp),cszProductVersion,*lpTrans,*(lpTrans+1));
  872. VerQueryValue(lpData,szTemp,(LPVOID*)&lpVersion,&uSize);
  873. }
  874. }
  875. }
  876. }
  877. UNREFERENCED_PARAMETER( lpDriver );
  878. wGPCVersion=0;
  879. // Now actually print the resulting string
  880. if(lpVersion)
  881. {
  882. bSuccess=PrintString(hdc,lprcPage,uRightAlign,wGPCVersion?
  883. IDS_TP_VERSIONANDGPC:IDS_TP_VERSIONONLY,
  884. lpFile,lpVersion,HIBYTE(wGPCVersion),LOBYTE(wGPCVersion));
  885. }
  886. else
  887. {
  888. bSuccess=PrintString(hdc,lprcPage,uRightAlign,wGPCVersion?
  889. IDS_TP_GPCONLY:IDS_TP_NOVERSIONINFO,
  890. lpFile,wGPCVersion);
  891. }
  892. FreeMem(lpData);
  893. return bSuccess;
  894. }
  895. /*++
  896. Routine Name:
  897. EndTestPageDlgProc
  898. Routine Description:
  899. Ask the user if the test pages was printed correctly.
  900. Arguments:
  901. Normal window proc arguments.
  902. Return Value:
  903. TRUE is message was processed, FALSE if not.
  904. --*/
  905. INT_PTR
  906. CALLBACK
  907. EndTestPageDlgProc(
  908. IN HWND hDlg,
  909. IN UINT uMsg,
  910. IN WPARAM wParam,
  911. IN LPARAM lParam
  912. )
  913. {
  914. BOOL bStatus = TRUE;
  915. switch( uMsg ){
  916. case WM_INITDIALOG:
  917. {
  918. SetForegroundWindow( hDlg );
  919. TCHAR szText[kStrMax+kPrinterBufMax];
  920. UINT nSize = COUNTOF(szText);
  921. ConstructPrinterFriendlyName( (LPCTSTR)lParam, szText, &nSize );
  922. SetWindowText( hDlg, szText );
  923. break;
  924. }
  925. case WM_COMMAND:
  926. switch( GET_WM_COMMAND_ID( wParam, lParam ) ){
  927. case IDCANCEL:
  928. case IDOK:
  929. EndDialog( hDlg, GET_WM_COMMAND_ID( wParam, lParam ) );
  930. break;
  931. default:
  932. bStatus = FALSE;
  933. break;
  934. }
  935. break;
  936. default:
  937. bStatus = FALSE;
  938. }
  939. return bStatus;
  940. }
  941. /*++
  942. Routine Name:
  943. GetPrinterInfo
  944. Routine Description:
  945. Routine to get the printer info 2 structures from
  946. the given printer name.
  947. Arguments:
  948. pszPrinterName = pointer to printer name
  949. **ppInfo2 - pointer where to return pointer to info 2
  950. Return Value:
  951. TRUE if both info pointers returned, otherwise FALSE.
  952. --*/
  953. BOOL
  954. bGetPrinterInfo(
  955. IN LPCTSTR pszPrinterName,
  956. IN PRINTER_INFO_2 **ppInfo2,
  957. IN DRIVER_INFO_3 **ppDrvInfo3
  958. )
  959. {
  960. BOOL bRetval = FALSE;
  961. PPRINTER_INFO_2 pInfo2 = NULL;
  962. PDRIVER_INFO_3 pDrvInfo3 = NULL;
  963. DWORD cbInfo = 0;
  964. LONG lResult = 0;
  965. TStatusB bStatus( DBG_WARN, ERROR_ACCESS_DENIED, ERROR_INSUFFICIENT_BUFFER );
  966. //
  967. // Open the printer.
  968. //
  969. HANDLE hPrinter = NULL;
  970. DWORD dwAccess = PRINTER_READ;
  971. TStatus Status( DBG_WARN );
  972. Status DBGCHK = TPrinter::sOpenPrinter( pszPrinterName,
  973. &dwAccess,
  974. &hPrinter );
  975. if( Status ){
  976. goto Cleanup;
  977. }
  978. //
  979. // Get the Printer info 2.
  980. //
  981. cbInfo = 0;
  982. bStatus DBGCHK = VDataRefresh::bGetPrinter( hPrinter,
  983. 2,
  984. (PVOID*)&pInfo2,
  985. &cbInfo );
  986. if( !bStatus ){
  987. goto Cleanup;
  988. }
  989. //
  990. // Get the driver info 3.
  991. //
  992. cbInfo = 0;
  993. bStatus DBGCHK = VDataRefresh::bGetPrinterDriver( hPrinter,
  994. NULL,
  995. 3,
  996. (PVOID*)&pDrvInfo3,
  997. &cbInfo );
  998. if( !bStatus ){
  999. goto Cleanup;
  1000. }
  1001. //
  1002. // Success copy back the info pointers.
  1003. //
  1004. *ppInfo2 = pInfo2;
  1005. *ppDrvInfo3 = pDrvInfo3;
  1006. bRetval = TRUE;
  1007. Cleanup:
  1008. if( hPrinter ){
  1009. ClosePrinter( hPrinter );
  1010. }
  1011. if( !bRetval ){
  1012. FreeMem( pInfo2 );
  1013. FreeMem( pDrvInfo3 );
  1014. }
  1015. return bRetval;
  1016. }
  1017. /*++
  1018. Routine Name:
  1019. GetCurrentTimeAndDate
  1020. Routine Description:
  1021. Routine to get the current time and date in a
  1022. formatted string to print on the test page.
  1023. Arguments:
  1024. cchText - size in characters of the provided buffer
  1025. pszText - pointer to buffer where to place time and
  1026. date text.
  1027. Return Value:
  1028. TRUE is valid and returned in provided buffer, otherwise FALSE.
  1029. --*/
  1030. BOOL
  1031. GetCurrentTimeAndDate(
  1032. IN UINT cchText,
  1033. IN LPTSTR pszText
  1034. )
  1035. {
  1036. TCHAR szTemp[kStrMax];
  1037. SPLASSERT( cchText );
  1038. SPLASSERT( pszText );
  1039. //
  1040. // Initialy terminate the buffer.
  1041. //
  1042. pszText[0] = 0;
  1043. //
  1044. // Get the current local time.
  1045. //
  1046. SYSTEMTIME LocalTime;
  1047. GetSystemTime( &LocalTime );
  1048. if ( !SystemTimeToTzSpecificLocalTime( NULL,
  1049. &LocalTime,
  1050. &LocalTime ))
  1051. {
  1052. DBGMSG( DBG_TRACE, ( "SysTimeToTzSpecLocalTime failed %d\n", GetLastError( )));
  1053. return FALSE;
  1054. }
  1055. if( !GetTimeFormat( LOCALE_USER_DEFAULT,
  1056. 0,
  1057. &LocalTime,
  1058. NULL,
  1059. pszText,
  1060. cchText ))
  1061. {
  1062. DBGMSG( DBG_TRACE, ( "GetTimeFormat failed with %d", GetLastError( )));
  1063. return FALSE;
  1064. }
  1065. StringCchCat( pszText, cchText, gszSpace );
  1066. if( !GetDateFormat( LOCALE_USER_DEFAULT,
  1067. 0,
  1068. &LocalTime,
  1069. NULL,
  1070. szTemp,
  1071. ARRAYSIZE(szTemp) ))
  1072. {
  1073. DBGMSG( DBG_TRACE, ( "GetDateFomat failed with %d\n", GetLastError( )));
  1074. return FALSE;
  1075. }
  1076. StringCchCat( pszText, cchText, szTemp );
  1077. return TRUE;
  1078. }