Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1808 lines
35 KiB

/*++
Copyright (c) 1993 Microsoft Corporation
Module Name:
Report.c
Abstract:
This module contains support for displaying the Hardware dialog.
Author:
Gregg R. Acheson (GreggA) 1-Oct-1993
Environment:
User Mode
--*/
//
// Hardware.h must be included first because it includes <nt.h>
//
#include "hardware.h"
#include "dialogs.h"
#include "report.h"
#include "msg.h"
#include "winmsd.h"
#include "strresid.h"
#include "dlgprint.h"
#include "Printer.h"
#include "osver.h"
#include "mem.h"
#include "service.h"
#include "drives.h"
#include "resprint.h"
#include "environ.h"
#include "network.h"
#include <commdlg.h>
#include <string.h>
#include <tchar.h>
#include <lmerr.h>
//
// Global Variables
//
LPREPORT_LINE lpReportHeadg;
LPREPORT_LINE lpReportLastg = NULL;
BOOL bAbortReport;
HWND volatile hdlgProgress;
LRESULT
CALLBACK
ProgressDialogProc(
HWND hwndDlg,
UINT message,
WPARAM wParam,
LPARAM lParam
);
long WINAPI
ProgressThread(
VOID
);
BOOL
ReportDlgProc(
IN HWND hWnd,
IN UINT message,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
Routine Description:
ReportDlgProc allows the selection of report options.
Arguments:
Standard DLGPROC entry.
Return Value:
BOOL - Depending on input message and processing options.
--*/
{
static
UINT ReportType;
BOOL Success;
int i;
static
UINT iScope = IDC_ALL_TABS;
static
UINT iDetailLevel = IDC_SUMMARY_REPORT;
static
UINT iDestination = IDC_SEND_TO_PRINTER;
switch( message ) {
case WM_INITDIALOG:
{
//
// The report type is passed in lParam
//
ReportType = ( DWORD ) lParam;
//
// Validate the report type
//
Success = ( ReportType == IDM_FILE_PRINT ) ||
( ReportType == IDC_PUSH_PRINT ) ||
( ReportType == IDM_FILE_SAVE );
DbgAssert( Success );
if( Success == FALSE ) {
return FALSE;
}
//
// Initial settings.
//
SetDlgItemText( hWnd, IDC_SYSTEM_NAME, _lpszSelectedComputer);
Success = CheckRadioButton(
hWnd,
IDC_CURRENT_TAB,
IDC_ALL_TABS,
iScope
);
DbgAssert( Success );
Success = CheckRadioButton(
hWnd,
IDC_SUMMARY_REPORT,
IDC_COMPLETE_REPORT,
iDetailLevel
);
DbgAssert( Success );
if ( ReportType == IDM_FILE_SAVE ) {
Success = CheckRadioButton(
hWnd,
IDC_SEND_TO_FILE,
IDC_SEND_TO_PRINTER,
IDC_SEND_TO_FILE
);
DbgAssert( Success );
iDestination = IDC_SEND_TO_FILE;
} else {
Success = CheckRadioButton(
hWnd,
IDC_SEND_TO_FILE,
IDC_SEND_TO_PRINTER,
IDC_SEND_TO_PRINTER
);
DbgAssert( Success );
iDestination = IDC_SEND_TO_PRINTER;
}
if( Success == FALSE ) {
return FALSE;
}
return TRUE;
}
case WM_COMMAND:
switch( LOWORD( wParam )) {
case IDOK: {
EndDialog ( hWnd, 1 ) ;
//
// Generate the report.
//
Success = GenerateReport ( GetParent( hWnd ), iDestination, iScope, iDetailLevel, FALSE );
if( Success == FALSE ) {
return FALSE;
}
return TRUE;
}
case IDC_CURRENT_TAB:
case IDC_ALL_TABS:
Success = CheckRadioButton(
hWnd,
IDC_CURRENT_TAB,
IDC_ALL_TABS,
LOWORD( wParam )
);
DbgAssert( Success );
iScope = LOWORD( wParam );
break;
case IDC_SUMMARY_REPORT:
case IDC_COMPLETE_REPORT:
Success = CheckRadioButton(
hWnd,
IDC_SUMMARY_REPORT,
IDC_COMPLETE_REPORT,
LOWORD( wParam )
);
DbgAssert( Success );
iDetailLevel = LOWORD( wParam );
break;
case IDC_SEND_TO_FILE:
case IDC_CLIPBOARD:
case IDC_SEND_TO_PRINTER:
Success = CheckRadioButton(
hWnd,
IDC_SEND_TO_FILE,
IDC_SEND_TO_PRINTER,
LOWORD( wParam )
);
DbgAssert( Success );
iDestination = LOWORD( wParam );
break;
case IDCANCEL:
EndDialog( hWnd, 1 );
return TRUE;
}
}
return FALSE;
}
BOOL
GenerateReport(
IN HWND hWnd,
IN UINT iDestination,
IN UINT iScope,
IN UINT iDetailLevel,
IN BOOL bCallFromCommandLine
)
/*++
Routine Description:
GenerateReport prints the selected items.
Arguments:
IN HWND hWnd - handle of main window
IN UINT iDestination - report desitination
IN UINT iScope - single tab or all tabs?
IN UINT iDetailLevel - summary or all details
IN BOOL bCallFromCommandLine - Was this function called because of command line options?
Return Value:
BOOL - TRUE if report was generated, FALSE otherwise.
--*/
{
BOOL Success;
TCHAR Title [ MAX_PATH*2 ];
TCHAR RptFileName[ MAX_PATH*2 ];
HDC PrinterDC;
int i;
DLGHDR *pHdr = (DLGHDR *) GetWindowLong( hWnd, GWL_USERDATA );
HANDLE hProgressThread;
HCURSOR hSaveCursor;
TC_ITEM tci;
//
// Initialize the abort flag
//
bAbortReport = FALSE;
//
// Make sure we get a valid filename or hPrinter
//
if ( iDestination == IDC_SEND_TO_FILE ) {
if (bCallFromCommandLine) {
lstrcpy( RptFileName, _lpszSelectedComputer+2 );
lstrcat( RptFileName, L".TXT" );
} else {
Success = GetReportFileName ( hWnd, RptFileName );
if ( ! Success )
return FALSE;
}
}
if ( iDestination == IDC_SEND_TO_PRINTER ) {
//
// If its a printed report, get the default printer DC
//
Success = GetPrinterDC( hWnd, &PrinterDC );
if ( ! Success )
return FALSE;
}
UpdateWindow( hWnd );
//
// Display the modeless progress / cancel dialog
//
hdlgProgress = 0;
hProgressThread = CreateThread( NULL,
0,
(LPTHREAD_START_ROUTINE) ProgressThread,
NULL,
0,
&i);
//
// Disable the application's window.
//
EnableWindow( hWnd, FALSE );
//
// Wait until dialog appears
//
while(!hdlgProgress);
//
// Initialize the report head pointer.
//
Success = InitializeReport( );
DbgAssert( Success );
DbgPointerAssert( lpReportHeadg );
//
// Set the last node to the head
//
lpReportLastg = lpReportHeadg;
//
// Set up the title for the report
//
lstrcpy( Title, GetString( IDS_REPORT_TITLE ) );
lstrcat( Title, _lpszSelectedComputer );
//
// Add 2 blank lines.
//
Success = AddLineToReport( 2, RFO_SKIPLINE, NULL, NULL );
DbgAssert( Success );
//
// Add the title.
//
Success = AddLineToReport( 0, RFO_SINGLELINE, Title, NULL );
DbgAssert( Success );
//
// Add a separator.
//
Success = AddLineToReport( 0, RFO_SEPARATOR, NULL, NULL );
DbgAssert( Success );
//
// Call selected report functions
//
if (iScope == IDC_CURRENT_TAB) {
//
//get the proper index to the appropriate procs
//that were set in MakeTabs
//
tci.mask = TCIF_PARAM;
i = TabCtrl_GetCurSel( pHdr->hwndTab );
TabCtrl_GetItem(pHdr->hwndTab, i, &tci);
pHdr->TabPrintProc[ tci.lParam ]( GetParent( hWnd ), iDetailLevel);
}
else
{
// cycle through all the active tabs
for (i = 0; i < TabCtrl_GetItemCount(pHdr->hwndTab); i++)
{
tci.mask = TCIF_PARAM;
TabCtrl_GetItem(pHdr->hwndTab, i, &tci);
SendMessage(GetDlgItem(hdlgProgress, IDD_REPORT_PROGRESS), PBM_STEPIT, 0, 0);
pHdr->TabPrintProc[ tci.lParam ]( GetParent( hWnd ), iDetailLevel);
//
// Check to see if we need to abort
//
if (bAbortReport)
{
goto AbortReport;
}
}
}
//
// Check to see if we need to abort
//
if (bAbortReport)
{
goto AbortReport;
}
//
// See if there is anything to report.
// The title and header take up 4 lines.
//
if ( NumReportLines( lpReportHeadg ) < 5 )
{
Success = FALSE;
goto AbortReport;
}
//
// Set up to save report to a file
//
switch (iDestination) {
case IDC_SEND_TO_FILE:
Success = SaveReportToFile( hWnd, lpReportHeadg, RptFileName );
break;
case IDC_SEND_TO_PRINTER:
Success = PrintReportToPrinter( hWnd, lpReportHeadg, PrinterDC );
break;
case IDC_CLIPBOARD:
Success = CopyReportToClipboard( hWnd, lpReportHeadg );
break;
default:
Success = FALSE;
break;
}
AbortReport:
//
// Re-enable the application's window.
//
EnableWindow( hWnd, TRUE );
//
// Remove the Progress window and thread.
//
SendMessage( hdlgProgress, WM_CLOSE, 0, 0 );
TerminateThread( hProgressThread, 0 );
//
// Set the focus on the OK button on main window
//
SetFocus( GetDlgItem( _hWndMain, IDOK) );
return Success;
}
BOOL
SaveReportToFile(
IN HWND hWnd,
IN LPREPORT_LINE lpReportHead,
IN LPTSTR RptFileName
)
/*++
Routine Description:
SaveReportToFile formats the report data and writes it to a file.
Arguments:
hWnd - Handle to window
ReportFileName - Name of file to save report to.
Return Value:
BOOL - True if report was saved to file successfully, FALSE otherwise.
--*/
{
HANDLE hReportFile;
TCHAR Buffer [ MAX_PATH*2 ];
DWORD dwLastError;
BOOL Success;
//
// Create or OpenAndTruncate file.
//
hReportFile = CreateFile( RptFileName,
GENERIC_WRITE,
0,
(LPSECURITY_ATTRIBUTES) NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL);
//
// Check Handle
//
if ( hReportFile == INVALID_HANDLE_VALUE ) {
//
// Get the error SCODE
//
dwLastError = GetLastError( );
//
// Format an error message and report the error
//
wsprintf( Buffer, GetString( IDS_FILE_OPEN_ERROR ), dwLastError );
MessageBox( hWnd, Buffer, GetString( IDS_APPLICATION_FULLNAME ), MB_OK | MB_ICONSTOP );
return FALSE;
}
Success = OutputReportLines( hWnd, hReportFile, IDC_SEND_TO_FILE, lpReportHead );
//
// See if the write succeded.
//
if ( ! Success ) {
//
// Get the error SCODE.
//
dwLastError = GetLastError( );
//
// Format an error message and report the error.
//
wsprintf( Buffer, GetString( IDS_FILE_WRITE_ERROR ), dwLastError );
MessageBox( hWnd, Buffer, GetString( IDS_APPLICATION_FULLNAME ), MB_OK | MB_ICONSTOP );
CloseHandle( hReportFile );
return FALSE;
}
//
// Close the file.
//
CloseHandle( hReportFile );
//
// Saving report was successful.
//
return TRUE;
}
BOOL
CopyReportToClipboard(
IN HWND hWnd,
IN LPREPORT_LINE lpReportHead
)
/*++
Routine Description:
CopyReportToClipboard formats the report data and copies it to the clipboard.
Arguments:
hWnd - Handle to window
ReportFileName - Name of file to save report to.
Return Value:
BOOL - True if report was copied to the clipboard successfully, FALSE otherwise.
--*/
{
HANDLE hReportFile;
TCHAR szBuffer [ MAX_PATH*2 ];
DWORD dwLastError;
BOOL Success;
LPTSTR lptstrCopy;
HGLOBAL hglbCopy;
UINT nLines = NumReportLines( lpReportHead );
//
// Open the clipboard, and empty it.
//
if (!OpenClipboard(hWnd))
return FALSE;
EmptyClipboard();
//
// Allocate a global memory object for the text.
//
hglbCopy = GlobalAlloc(GMEM_DDESHARE | GMEM_ZEROINIT, 1024 * nLines );
if (hglbCopy == NULL) {
CloseClipboard();
return FALSE;
}
//
// Lock the handle and copy the text to the buffer.
//
lptstrCopy = GlobalLock(hglbCopy);
Success = OutputReportLines( hWnd, lptstrCopy, IDC_CLIPBOARD, lpReportHead );
GlobalUnlock(hglbCopy);
//
// Place the handle on the clipboard.
//
SetClipboardData(CF_UNICODETEXT, hglbCopy);
//
// Close the clipboard.
//
CloseClipboard();
return TRUE;
}
BOOL
GetReportFileName(
IN HWND hWnd,
IN OUT LPTSTR ReportFileName
)
/*++
Routine Description:
GetReportFileName calls the save file comdlg.
Arguments:
ReportFileName - pointer to string to return filename.
Return Value:
BOOL - True if we get a valid filename, FALSE otherwise.
--*/
{
//
// User wants to save a reoport
//
OPENFILENAME Ofn;
TCHAR FileName[ MAX_PATH*2 ];
LPCTSTR FilterString;
TCHAR ReplaceChar;
int Length;
int i;
static BOOL MakeFilterString = TRUE;
static TCHAR FilterStringBuffer[ MAX_CHARS ];
//
// Validate _hModule and the string we were passed
//
DbgHandleAssert( _hModule );
if ( _hModule == NULL || _hModule == INVALID_HANDLE_VALUE ) {
return FALSE;
}
DbgPointerAssert( ReportFileName );
if ( ReportFileName == NULL ) {
return FALSE;
}
//
// If the filter string was never made before, get it and scan
// it replacing each replacement character with a NUL
// character. This is necessary since there is no way of
// entering a NUL character in the resource file.
//
if( MakeFilterString == TRUE ) {
MakeFilterString = FALSE;
//
// Load the filter string
//
FilterString = GetString( IDS_FILE_REPORT_FILTER );
DbgPointerAssert( FilterString );
if ( FilterString == NULL ) {
return FALSE;
}
//
// Copy the FilterString into the FilterStringBuffer
//
_tcscpy( FilterStringBuffer, FilterString );
//
// Get the length of the filter string
//
Length = _tcslen( FilterString );
ReplaceChar = GetString( IDS_FILE_REPORT_FILTER )[ Length - 1 ];
for( i = 0; FilterStringBuffer[ i ] != TEXT( '\0' ); i++ ) {
if( FilterStringBuffer[ i ] == ReplaceChar ) {
FilterStringBuffer[ i ] = TEXT( '\0' );
}
}
}
//
// Get the default filename
//
lstrcpy ( FileName, GetString( IDS_DEFAULT_FILENAME ) );
//
// Fill in the Ofn structure for the OpenFile CommDlg
//
Ofn.lStructSize = sizeof( OPENFILENAMEW );
Ofn.hwndOwner = hWnd;
Ofn.hInstance = NULL;
Ofn.lpstrFilter = FilterStringBuffer;
Ofn.lpstrCustomFilter = NULL;
Ofn.nMaxCustFilter = 0;
Ofn.nFilterIndex = 1;
Ofn.lpstrFile = FileName;
Ofn.nMaxFile = NumberOfCharacters( FileName );
Ofn.lpstrFileTitle = NULL;
Ofn.nMaxFileTitle = 0;
Ofn.lpstrInitialDir = NULL;
Ofn.lpstrTitle = GetString( IDS_FILE_REPORT_TITLE );
Ofn.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;
Ofn.nFileOffset = 0;
Ofn.nFileExtension = 0;
Ofn.lpstrDefExt = NULL;
Ofn.lCustData = 0;
Ofn.lpfnHook = NULL;
Ofn.lpTemplateName = NULL;
//
// Let the user choose files.
//
if( GetSaveFileName( &Ofn )) {
//
// The user pressed OK so set the path and file to search
// for to what was browsed.
//
lstrcpy( ReportFileName, Ofn.lpstrFile );
} else {
//
// The user pressed Cancel or closed the dialog.
//
return FALSE;
}
return TRUE;
}
BOOL
OutputReportLines(
IN HWND hWnd,
IN HANDLE hDevice,
IN UINT Destination,
IN LPREPORT_LINE lpReportHead
)
/*++
Routine Description:
OutputReportLines - walks the report list and hands the line to the device.
Arguments:
hWnd - Handle to window.
Device - Handle to device to write to (hFile or hPrinterDC or pointer to clipboard data).
Destination - Indicates file or printer.
ReportHead - Head pointer to report.
Return Value:
BOOL - True if report was saved to file successfully, FALSE otherwise.
--*/
{
LPREPORT_LINE lpNode, lpNext;
TCHAR LineBuffer [ MAX_PATH*2+4];
UINT LinesToPrint;
UINT u;
BOOL Success = TRUE;
//
// Prepare to walk the ReportLine linked list.
//
lpNode = lpReportHead;
//
// Validate the node.
//
DbgPointerAssert( lpNode );
DbgAssert( CheckSignature ( lpNode ));
if( lpNode == NULL )
return FALSE;
//
// While the node is valid...
//
while ( lpNode ) {
//
// Validate the node.
//
DbgAssert( CheckSignature ( lpNode ));
//
// Build the report line
//
BuildReportLine( lpNode, LineBuffer );
//
// See if we have multiple RFO_SKIPLINE's
//
if ( lpNode->FormatOpt == RFO_SKIPLINE && lpNode->Indent > 1 ) {
//
// If we are skipping lines, see how many to skip.
//
LinesToPrint = lpNode->Indent;
} else {
//
// Only one line to print.
//
LinesToPrint = 1;
}
//
// Loop through LinesToPrint times.
//
for( u = 1; u <= LinesToPrint; ++u ) {
//
// Send the line to the device
//
switch( Destination ) {
case IDC_SEND_TO_PRINTER:
Success = PrintLine( hDevice, LineBuffer );
DbgAssert( Success );
break;
case IDC_SEND_TO_FILE:
//
// Append a newline onto the end of the LineBuffer.
//
lstrcat( LineBuffer, L"\r\n" );
//
// Save it to the file.
//
Success = AnsiWriteFile( hDevice, (LPTSTR) LineBuffer );
DbgAssert( Success );
break;
case IDC_CLIPBOARD:
//
// Append a newline onto the end of the LineBuffer.
//
lstrcat( LineBuffer, L"\r\n" );
if (lstrlen( (LPTSTR) hDevice ) ) {
lstrcat( (LPTSTR) hDevice, LineBuffer );
} else {
lstrcpy( (LPTSTR) hDevice, LineBuffer );
}
break;
defualt:
break;
}
}
//
// Get the next node in the list.
//
lpNext = lpNode->NextLine;
//
// Free the Label and Value strings.
//
FreeMemory( lpNode->Label );
FreeMemory( lpNode->Value );
//
// Free the ReportLine node.
//
FreeMemory( lpNode );
//
// Make the next node the current node.
//
lpNode = lpNext;
}
return Success;
}
BOOL
AddLineToReport(
IN UINT Indent,
IN DWORD FormatOpt,
IN LPTSTR Label,
IN LPTSTR Value
)
/*++
Routine Description:
Add a line of text to the report buffer.
Arguments:
Indent - Number of spaces to indent.
FormatOpt - Formatting options.
Label - Pointer to the Label string.
Value - Pointer to the Value string.
Return Value:
BOOL - TRUE if the line was successfully added. FALSE otherwise.
--*/
{
LPREPORT_LINE ReportNew;
LPTSTR lpszNextValue;
BOOL bMultilineValue = FALSE;
//
// Check to see if the value is multi-line
//
if ( FormatOpt & (RFO_RPTLINE | RFO_RPTVALUE) ) {
lpszNextValue = wcschr( Value, '\r');
if (lpszNextValue) {
bMultilineValue = TRUE;
*lpszNextValue++ = UNICODE_NULL;
lpszNextValue++;
}
}
//
// Validate Head (Global)
//
DbgPointerAssert( lpReportHeadg );
if( lpReportHeadg == NULL )
return FALSE;
//
// Check Last Pointer
//
DbgPointerAssert( lpReportLastg );
if( lpReportLastg == NULL )
return FALSE;
//
// Allocate a new report line
//
ReportNew = AllocateObject( REPORT_LINE, 1 );
//
// Validate new report line.
//
DbgPointerAssert ( ReportNew );
if( ReportNew == NULL )
return FALSE;
//
// Set the signature on the report line
//
SetSignature( ReportNew );
//
// Link it into the list
//
lpReportLastg->NextLine = ReportNew;
lpReportLastg = ReportNew;
//
// Add the passed information
//
ReportNew->Indent = Indent;
ReportNew->FormatOpt = FormatOpt;
//
// See if we need to help with the formatting...
//
if ( (FormatOpt == RFO_SKIPLINE) ||
(FormatOpt & RFO_SEPARATOR) ) {
//
// RFO_SKIPLINE or RFO_SEPARATOR - Nothing to add.
//
return TRUE;
}
if ( FormatOpt & RFO_SINGLELINE ) {
//
// RFO_SINGLELINE - Add line to Label.
//
if( Label )
{
ReportNew->Label = (LPTSTR) LocalAlloc(LPTR, (lstrlen(Label)*sizeof(TCHAR)) + 2);
lstrcpyn( ReportNew->Label, Label,(lstrlen(Label)*sizeof(TCHAR)) );
}
return TRUE;
}
if ( FormatOpt & RFO_RPTVALUE ) {
//
// RFO_RPTVALUE - Add line to Value.
//
if( Value )
{
ReportNew->Value = (LPTSTR) LocalAlloc( LPTR, (lstrlen(Value)*sizeof(TCHAR)) + 2);
lstrcpyn( ReportNew->Value, Value, (lstrlen(Value)*sizeof(TCHAR)) );
}
//
// if this was a multi-line value, call function again with next line
//
if (bMultilineValue)
{
AddLineToReport(Indent, FormatOpt, Label, lpszNextValue);
}
return TRUE;
}
if ( FormatOpt & RFO_RPTLINE ) {
//
// RFO_RPTLINE - Add both Label and Value.
//
if( Label )
{
ReportNew->Label = (LPTSTR) LocalAlloc(LPTR, (lstrlen(Label)*sizeof(TCHAR)) + 2);
lstrcpyn( ReportNew->Label, Label,(lstrlen(Label)*sizeof(TCHAR)) );
}
if( Value )
{
ReportNew->Value = (LPTSTR) LocalAlloc( LPTR, (lstrlen(Value)*sizeof(TCHAR)) + 2);
lstrcpyn( ReportNew->Value, Value, (lstrlen(Value)*sizeof(TCHAR)) );
}
//
// if this was a multi-line value, call function again with next line
//
if (bMultilineValue) {
_wcsset( Label, ' ');
AddLineToReport(Indent, FormatOpt, Label, lpszNextValue);
}
return TRUE;
}
return TRUE;
}
UINT
NumReportLines(
IN LPREPORT_LINE lpReportHead
)
/*++
Routine Description:
Count the number of lines in the ReportBuffer.
Arguments:
None.
Return Value:
UINT - Number of entries in the Report Buffer.
--*/
{
UINT Count = 0;
LPREPORT_LINE Node;
//
// Validate ReportHead
//
DbgPointerAssert( lpReportHead );
if( lpReportHead == NULL )
return 0;
Node = lpReportHead;
//
// Walk the report list and incrment count for each node;
//
while( Node ) {
//
// Make sure the node is valid.
//
DbgAssert( CheckSignature( Node ) );
//
// Get the next node and increment the count.
//
Node=Node->NextLine;
++Count;
}
return Count;
}
BOOL
AnsiWriteFile (
IN HANDLE hFile,
IN LPTSTR lpBuffer
)
/*++
Routine Description:
Converts a UNICODE string to ASCII and writes it to a file.
Arguments:
hFile - Handle to file where data is going to be written.
lpBuffer - Unicode string to convert and write to file.
Return Value:
BOOL - TRUE if write succeeds, FALSE otherwise.
--*/
{
LPSTR lpAnsi;
int nBytes;
BOOL Success;
BOOL fDefCharUsed;
DWORD dwBytesWritten;
DWORD nChars;
//
// Get the length of the Unicode string.
//
DbgPointerAssert( lpBuffer );
if ( lpBuffer == NULL ) {
CloseHandle( hFile );
return FALSE;
}
nChars = lstrlen( lpBuffer );
//
// Convert string to MultiByte.
//
nBytes = WideCharToMultiByte ( CP_ACP,
0,
(LPWSTR) lpBuffer,
nChars,
NULL,
0,
NULL,
&fDefCharUsed
);
//
// Allocate a new string
//
lpAnsi = (LPSTR) LocalAlloc (LPTR, nBytes + 1);
DbgPointerAssert( lpAnsi );
if ( lpAnsi == NULL ) {
CloseHandle( hFile );
return FALSE;
}
//
// Convert new string to ANSI.
//
WideCharToMultiByte ( CP_ACP,
0,
(LPWSTR) lpBuffer,
nChars,
lpAnsi,
nBytes,
NULL,
&fDefCharUsed
);
//
// Write the ANSI string to the file.
//
Success = WriteFile( hFile,
(LPSTR) lpAnsi,
(DWORD) nBytes,
&dwBytesWritten,
NULL
);
//
// Free the ANSI buffer.
//
LocalFree ( lpAnsi );
return Success;
}
BOOL
BuildReportLine (
IN LPREPORT_LINE lpNode,
IN LPTSTR LineBuffer
)
/*++
Routine Description:
BuildReportLine
Arguments:
Return Value:
BOOL - TRUE if build succeeds, FALSE otherwise.
--*/
{
int i, iLen;
UINT u;
TCHAR Buffer [ MAX_PATH*2 ];
//
// Validate the node and the buffer
//
DbgPointerAssert( lpNode );
DbgPointerAssert( LineBuffer );
DbgAssert( CheckSignature( lpNode ) );
if( !(lpNode) || !(LineBuffer) ) {
return FALSE;
}
//
// Clear the line buffer.
//
lstrcpy( LineBuffer, L"\0" );
//
// Check the node formatting information.
//
if ( lpNode->FormatOpt & RFO_SINGLELINE ) {
//
// RFO_SINGLELINE - Copy only the Label into the LineBuffer.
//
DbgPointerAssert( lpNode->Label );
if ( lpNode->Label == NULL ) {
return FALSE;
}
lstrcpy( LineBuffer, lpNode->Label );
}
if ( lpNode->FormatOpt & RFO_RPTVALUE ) {
//
// RFO_RPTVALUE - Justify and copy the Value into the LineBuffer.
//
DbgPointerAssert( lpNode->Value );
if ( lpNode->Value == NULL ) {
return FALSE;
}
//
// Append the string to the LineBuffer.
//
if ( lpNode->Value )
lstrcat( LineBuffer, lpNode->Value );
}
if ( lpNode->FormatOpt & RFO_RPTLINE ) {
//
// RFO_RPTLINE - Copy the label and append the value to the LineBuffer.
//
//
// Center justify the buffer around the separator.
//
DbgPointerAssert( lpNode->Label );
if ( lpNode->Label == NULL ) {
return FALSE;
}
//
// Append the string to the padded LineBuffer.
//
lstrcat( LineBuffer, lpNode->Label );
//
// Insert a space between the strings.
//
lstrcat( LineBuffer, L" " );
//
// Append the string to the LineBuffer.
//
if ( lpNode->Value )
lstrcat( LineBuffer, lpNode->Value );
}
if ( lpNode->FormatOpt & RFO_SEPARATOR ) {
//
// RFO_SEPARATOR - Copy a line of dashes into the LineBuf.
//
for( i = 0; i < 5; ++i )
lstrcat( LineBuffer, L"--------------" );
}
if ( lpNode->FormatOpt & RFO_CENTER ) {
//
// RFO_CENTER - Center the line on the page.
//
//
// Assume a file 'width' of 78 chars and calculate the number
// of spaces needed to pad the line.
//
// BUGBUG: #define FILE_WIDTH
#if defined(DBCS) && defined(UNICODE)
// Get number of bytes, not number of characters
iLen = 35 - (WideCharToMultiByte(CP_ACP,
WC_COMPOSITECHECK,
LineBuffer, -1,
NULL, 0,
NULL, NULL) / 2);
#else
iLen = 35 - (lstrlen( LineBuffer ) / 2);
#endif
//
// Save a copy of the LineBuffer in Buffer.
//
lstrcpy( Buffer, LineBuffer );
//
// Clear the Line Buffer.
//
lstrcpy( LineBuffer, L"\0" );
//
// Append spaces to LineBuffer to pad for centering.
//
for( i = 0; i < iLen; ++i )
lstrcat( LineBuffer, L" " );
//
// Append the string to the padded LineBuffer.
//
lstrcat( LineBuffer, Buffer );
}
if ( lpNode->Indent ) {
//
// Indent the line on the page.
//
//
// Save a copy of the LineBuffer in Buffer.
//
lstrcpy( Buffer, LineBuffer );
//
// Clear the Line Buffer.
//
lstrcpy( LineBuffer, L"\0" );
//
// Append spaces to LineBuffer to indent.
//
for( u = 0; u < lpNode->Indent; ++u )
lstrcat( LineBuffer, L" " );
//
// Append the string to the padded LineBuffer.
//
lstrcat( LineBuffer, Buffer );
}
//
// Check to make sure we have a string, unless it was a RPT_SKIPLINE.
//
if ( (!lstrlen( LineBuffer )) && (lpNode->FormatOpt != RFO_SKIPLINE) ) {
DbgAssert( FALSE );
return FALSE;
}
}
BOOL
InitializeReport(
VOID
)
/*++
Routine Description:
Prepare the report head pointer for use.
Arguments:
lpReportHead - Head pointer of the list.
Return Value:
BOOL - TRUE if the node was successfully initialized. FALSE otherwise.
--*/
{
//
// Allocate a new report line
//
lpReportHeadg = AllocateObject( REPORT_LINE, 1 );
//
// Validate new report line.
//
DbgPointerAssert ( lpReportHeadg );
if( lpReportHeadg == NULL )
return FALSE;
//
// Set the signature on the report line
//
SetSignature( lpReportHeadg );
return TRUE;
}
long WINAPI
ProgressThread(
VOID
)
/*++
Routine Description:
ProgressThread - entry point for thread tracking progress of report generation.
Arguments:
None
Return Value:
BOOL
--*/
{
MSG msg;
hdlgProgress = CreateDialog( _hModule,
(LPTSTR) L"AbortDlg",
NULL,
(DLGPROC) ProgressDialogProc );
SetForegroundWindow( hdlgProgress );
//
// Retrieve and remove messages from the thread's message queue.
//
while( GetMessage( &msg, hdlgProgress, 0, 0 )) {
if( ! IsDialogMessage( hdlgProgress, &msg ) ) {
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
return msg.wParam;
}
LRESULT
CALLBACK
ProgressDialogProc(
HWND hwndDlg,
UINT message,
WPARAM wParam,
LPARAM lParam
)
/*++
Routine Description:
ProgressDialogProc - handles the Progress dialog.
Arguments:
Standard dialog entry
Return Value:
BOOL - Depending on input message and processing options.
--*/
{
int Success;
switch (message) {
case WM_INITDIALOG:
{
RECT rc;
GetWindowRect( _hWndMain, &rc);
Success = SetWindowPos(
hwndDlg,
_hWndMain,
( rc.left + 60 ),
( rc.top + 95 ),
0,
0,
SWP_NOSIZE | SWP_SHOWWINDOW
);
DbgAssert( Success );
//
// Initialize the static text control.
//
//SetDlgItemText( hwndDlg, IDD_FILE, GetString( IDS_DOC_TITLE ) );
return TRUE;
}
case WM_COMMAND:
if (wParam == IDD_CANCEL) {
//
// If we have hit the cancel button, flip the global flag to cancel,
// but do not close this dialog yet. A message will be sent to kill
// this thread.
//
bAbortReport = TRUE;
SetDlgItemText( hwndDlg, IDD_FILE, GetString( IDS_CANCEL_REPORT ) );
}
break;
case WM_DESTROY:
PostQuitMessage(0);
return(0);
}
return FALSE;
}