1372 lines
35 KiB
C++
1372 lines
35 KiB
C++
/*++
|
|
|
|
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
|
|
_tcscpy( 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.
|
|
//
|
|
_vsntprintf( 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){
|
|
|
|
wsprintf(szTemp,cszFileVersion,*lpTrans,*(lpTrans+1));
|
|
|
|
if(!VerQueryValue(lpData,szTemp,(LPVOID*)&lpVersion,&uSize))
|
|
{
|
|
wsprintf(szTemp,cszProductVersion,*lpTrans,*(lpTrans+1));
|
|
VerQueryValue(lpData,szTemp,(LPVOID*)&lpVersion,&uSize);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
UNREFERENCED_PARAMETER( lpDriver );
|
|
#if 0
|
|
//
|
|
// Check for GPC version if this is the driver
|
|
//
|
|
// !!LATER!!
|
|
// Fetching the GPC version from Win32 API's is not suppored on NT.
|
|
//
|
|
if(!lstrcmpi(lpDriver,lpFile))
|
|
wGPCVersion=GetGPCVersion(lpDriver);
|
|
else
|
|
#endif
|
|
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
|
|
)
|
|
{
|
|
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;
|
|
}
|
|
|
|
_tcscat( pszText, gszSpace );
|
|
cchText = _tcslen( pszText );
|
|
pszText += cchText;
|
|
|
|
if( !GetDateFormat( LOCALE_USER_DEFAULT,
|
|
0,
|
|
&LocalTime,
|
|
NULL,
|
|
pszText,
|
|
kStrMax - cchText ))
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "GetDateFomat failed with %d\n", GetLastError( )));
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|