X-Git-Url: https://git.saurik.com/apple/mdnsresponder.git/blobdiff_plain/4aea607d357d16eb4a69db265dc8f5c7faef7405..2682e09e0dbe18ba42fd4707b09a89e8c34f697c:/Clients/PrinterSetupWizard/ThirdPage.cpp?ds=inline diff --git a/Clients/PrinterSetupWizard/ThirdPage.cpp b/Clients/PrinterSetupWizard/ThirdPage.cpp index bf16fe2..6caf55c 100644 --- a/Clients/PrinterSetupWizard/ThirdPage.cpp +++ b/Clients/PrinterSetupWizard/ThirdPage.cpp @@ -1,143 +1,43 @@ -/* +/* -*- Mode: C; tab-width: 4 -*- + * * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - - Change History (most recent first): - -$Log: ThirdPage.cpp,v $ -Revision 1.27 2005/10/05 21:41:45 herscher - Use "application/octet-stream" to determine if CUPS shared queue supports raw - -Revision 1.26 2005/07/11 20:17:15 shersche - UI fixes associated with CUPS printer workaround fix. - -Revision 1.25 2005/07/07 17:53:20 shersche -Fix problems associated with the CUPS printer workaround fix. - -Revision 1.24 2005/06/30 18:02:54 shersche - Workaround for Mac OS X Printer Sharing bug - -Revision 1.23 2005/04/18 02:33:47 shersche - Default printer option cannot be deselected - -Revision 1.22 2005/04/13 17:46:22 shersche - Generic PCL not selected when printers advertise multiple text records - -Revision 1.21 2005/03/30 02:09:55 shersche -Auto-resize the column width to account for differing fonts and font sizes - -Revision 1.20 2005/03/05 02:27:45 shersche - Generic drivers don't do color - -Revision 1.19 2005/02/23 02:08:51 shersche - If we can't match the manufacturer, and select a generic printer, then show all the manufacturers in the manufacturer pane, not just "Generic". - -Revision 1.18 2005/02/15 07:02:51 shersche - Display different UI text when generic printer drivers are selected - -Revision 1.17 2005/02/08 21:45:06 shersche - Default to Generic PostScript or PCL if unable to match driver - -Revision 1.16 2005/02/08 18:56:03 shersche -Fix generated IPP url so that it doesn't add "/printers" string - -Revision 1.15 2005/02/01 01:44:07 shersche -Load ntprint.inf at startup. This will cause the wizard to take a second or two longer to come up, but will eliminate the pause when auto-selecting the print drivers. - -Revision 1.14 2005/01/25 08:55:54 shersche - Load icons at run-time from resource DLL -Bug #: 3911084 - -Revision 1.13 2005/01/06 08:15:45 shersche -Append queue name to end of LPR port name, correctly build port name when queue name is absent - -Revision 1.12 2005/01/05 01:06:12 shersche - Strip the first substring off the product key if an initial match can't be found with the whole product key. -Bug #: 3841218 - -Revision 1.11 2004/12/29 18:53:38 shersche - - Added support for LPR and IPP protocols as well as support for obtaining multiple text records. Reorganized and simplified codebase. -Bug #: 3725106, 3737413 - -Revision 1.10 2004/10/11 22:55:34 shersche - Use the IP port number when deriving the printer port name. -Bug #: 3827624 - -Revision 1.9 2004/06/27 23:08:00 shersche -code cleanup, make sure EnumPrintDrivers returns non-zero value, ignore comments in inf files - -Revision 1.8 2004/06/27 08:06:45 shersche -Parse [Strings] section of inf file - -Revision 1.7 2004/06/26 04:00:05 shersche -fix warnings compiling in debug mode -Submitted by: herscher - -Revision 1.6 2004/06/26 03:19:57 shersche -clean up warning messages - -Submitted by: herscher - -Revision 1.5 2004/06/25 05:06:02 shersche -Trim whitespace from key/value pairs when parsing inf files -Submitted by: herscher - -Revision 1.4 2004/06/25 02:44:13 shersche -Tweaked code to handle Xerox Phaser printer identification -Submitted by: herscher - -Revision 1.3 2004/06/25 02:27:58 shersche -Do a CListCtrl::FindItem() before calling CListCtrl::SetItemState(). -Submitted by: herscher - -Revision 1.2 2004/06/23 18:09:23 shersche -Normalize tag names when parsing inf files. -Submitted by: herscher - -Revision 1.1 2004/06/18 04:36:58 rpantos -First checked in - - -*/ + */ #include "stdafx.h" #include "PrinterSetupWizardApp.h" #include "PrinterSetupWizardSheet.h" #include "ThirdPage.h" -#include "StdioFileEx.h" +#include "tcpxcv.h" #include -#include #include +#include // local variable is initialize but not referenced #pragma warning(disable:4189) - // // This is the printer description file that is shipped -// with Windows +// with Windows XP and below // #define kNTPrintFile L"inf\\ntprint.inf" +// +// Windows Vista ships with a set of prn*.inf files +// +#define kVistaPrintFiles L"inf\\prn*.inf" + // // These are pre-defined names for Generic manufacturer and model // @@ -153,29 +53,24 @@ First checked in #define kGenericPCLDriver L"HP LaserJet 4050 Series PCL" -// -// states for parsing ntprint.inf -// -enum PrinterParsingState -{ - Looking, - ParsingManufacturers, - ParsingModels, - ParsingStrings -}; - - // CThirdPage dialog IMPLEMENT_DYNAMIC(CThirdPage, CPropertyPage) CThirdPage::CThirdPage() : CPropertyPage(CThirdPage::IDD), + m_manufacturerSelected( NULL ), + m_modelSelected( NULL ), + m_genericPostscript( NULL ), + m_genericPCL( NULL ), m_initialized(false), m_printerImage( NULL ) { static const int bufferSize = 32768; TCHAR windowsDirectory[bufferSize]; CString header; + WIN32_FIND_DATA findFileData; + HANDLE findHandle; + CString prnFiles; CString ntPrint; OSStatus err; BOOL ok; @@ -193,9 +88,38 @@ CThirdPage::CThirdPage() err = translate_errno( ok, errno_compat(), kUnknownErr ); require_noerr( err, exit ); - ntPrint.Format(L"%s\\%s", windowsDirectory, kNTPrintFile); - err = LoadPrintDriverDefsFromFile( m_manufacturers, ntPrint, false ); - require_noerr(err, exit); + // + // + // + // If there are no *prn.inf files, we'll assume that the information + // is in ntprint.inf + // + prnFiles.Format( L"%s\\%s", windowsDirectory, kVistaPrintFiles ); + findHandle = FindFirstFile( prnFiles, &findFileData ); + + if ( findHandle != INVALID_HANDLE_VALUE ) + { + CString absolute; + + absolute.Format( L"%s\\inf\\%s", windowsDirectory, findFileData.cFileName ); + err = LoadPrintDriverDefsFromFile( m_manufacturers, absolute, false ); + require_noerr( err, exit ); + + while ( FindNextFile( findHandle, &findFileData ) ) + { + absolute.Format( L"%s\\inf\\%s", windowsDirectory, findFileData.cFileName ); + err = LoadPrintDriverDefsFromFile( m_manufacturers, absolute, false ); + require_noerr( err, exit ); + } + + FindClose( findHandle ); + } + else + { + ntPrint.Format(L"%s\\%s", windowsDirectory, kNTPrintFile); + err = LoadPrintDriverDefsFromFile( m_manufacturers, ntPrint, false ); + require_noerr(err, exit); + } // // load printer drivers that have been installed on this machine @@ -215,39 +139,32 @@ exit: } -CThirdPage::~CThirdPage() +void +CThirdPage::FreeManufacturers( Manufacturers & manufacturers ) { - // - // clean up all the printer manufacturers - // - while (m_manufacturers.size()) + for ( Manufacturers::iterator it = manufacturers.begin(); it != manufacturers.end(); it++ ) { - Manufacturers::iterator iter = m_manufacturers.begin(); - - while (iter->second->models.size()) + for ( Models::iterator it2 = it->second->models.begin(); it2 != it->second->models.end(); it2++ ) { - Models::iterator it = iter->second->models.begin(); - - Model * model = *it; - - delete model; - - iter->second->models.erase(it); + delete *it2; } - delete iter->second; - - m_manufacturers.erase(iter); + delete it->second; } } +CThirdPage::~CThirdPage() +{ + FreeManufacturers( m_manufacturers ); +} + // ---------------------------------------------------- // SelectMatch // // SelectMatch will do all the UI work associated with // selected a manufacturer and model of printer. It also -// makes sure the printer object is update with the +// makes sure the printer object is update with the // latest settings // // ---------------------------------------------------- @@ -272,7 +189,10 @@ CThirdPage::SelectMatch(Printer * printer, Service * service, Manufacturer * man if (nIndex != -1) { m_manufacturerListCtrl.SetItemState(nIndex, LVIS_SELECTED, LVIS_SELECTED); - m_manufacturerListCtrl.EnsureVisible(nIndex, FALSE); + // + // mDNS: When auto-highlighting items in lists, scroll list so highlighted item is in the middle + // + AutoScroll(m_manufacturerListCtrl, nIndex); } // @@ -286,7 +206,7 @@ CThirdPage::SelectMatch(Printer * printer, Service * service, Manufacturer * man if (nIndex != -1) { m_modelListCtrl.SetItemState(nIndex, LVIS_SELECTED, LVIS_SELECTED); - m_modelListCtrl.EnsureVisible(nIndex, FALSE); + AutoScroll( m_modelListCtrl, nIndex ); m_modelListCtrl.SetFocus(); } @@ -294,7 +214,6 @@ CThirdPage::SelectMatch(Printer * printer, Service * service, Manufacturer * man CopyPrinterSettings( printer, service, manufacturer, model ); } - void CThirdPage::SelectMatch(Manufacturers & manufacturers, Printer * printer, Service * service, Manufacturer * manufacturer, Model * model) { @@ -303,7 +222,6 @@ CThirdPage::SelectMatch(Manufacturers & manufacturers, Printer * printer, Servic SelectMatch( printer, service, manufacturer, model ); } - // -------------------------------------------------------- // CopyPrinterSettings // @@ -314,6 +232,8 @@ CThirdPage::SelectMatch(Manufacturers & manufacturers, Printer * printer, Servic void CThirdPage::CopyPrinterSettings( Printer * printer, Service * service, Manufacturer * manufacturer, Model * model ) { + DWORD portNameLen; + printer->manufacturer = manufacturer->name; printer->displayModelName = model->displayName; printer->modelName = model->name; @@ -357,31 +277,80 @@ CThirdPage::CopyPrinterSettings( Printer * printer, Service * service, Manufactu service->protocol = L"IPP"; } + + // If it's not an IPP printr, truncate the portName so that it's valid + + if ( service->type != kIPPServiceType ) + { + portNameLen = printer->portName.GetLength() + 1; + + if ( portNameLen > MAX_PORTNAME_LEN ) + { + printer->portName.Delete( MAX_PORTNAME_LEN - 1, ( portNameLen - MAX_PORTNAME_LEN ) ); + } + } +} + +// -------------------------------------------------------- +// DefaultPrinterExists +// +// Checks to see if a default printer has been configured +// on this machine +// -------------------------------------------------------- +BOOL +CThirdPage::DefaultPrinterExists() +{ + CPrintDialog dlg(FALSE); + + dlg.m_pd.Flags |= PD_RETURNDEFAULT; + + return dlg.GetDefaults(); } +// -------------------------------------------------------- +// AutoScroll +// +// Ensure selected item is in middle of list +// -------------------------------------------------------- +void +CThirdPage::AutoScroll( CListCtrl & list, int nIndex ) +{ + // + // mDNS: When auto-highlighting items in lists, scroll list so highlighted item is in the middle + // + + int top; + int count; + + list.EnsureVisible( nIndex, FALSE ); + + top = list.GetTopIndex(); + count = list.GetCountPerPage(); + + if ( ( nIndex == top ) || ( ( nIndex + 1 ) == ( top + count ) ) ) + { + CRect rect; + int rows; + + rows = ( count / 2 ); + + if ( nIndex == top ) + { + list.GetItemRect(0, rect, LVIR_BOUNDS); + list.Scroll( CPoint( 0, rows * rect.Height() * -1 ) ); + } + else + { + list.GetItemRect(0, rect, LVIR_BOUNDS); + list.Scroll( CPoint( 0, rows * rect.Height() ) ); + } + } +} // ------------------------------------------------------ // LoadPrintDriverDefsFromFile // -// This function does all the heavy lifting in parsing inf -// files. It is called to parse both ntprint.inf, and driver -// files that might be shipped on a printer's installation -// disk -// -// The inf file is not totally parsed. I only want to determine -// the manufacturer and models that are involved. I leave it -// to printui.dll to actually copy the driver files to the -// right places. -// -// I was aiming to parse as little as I could so as not to -// duplicate the parsing code that is contained in Windows. There -// are no public APIs for parsing inf files. -// -// That part of the inf file that we're interested in has a fairly -// easy format. Tags are strings that are enclosed in brackets. -// We are only interested in [MANUFACTURERS] and models. -// -// The only potentially opaque thing about this function is the +// The only potentially opaque thing about this function is the // checkForDuplicateModels flag. The problem here is that ntprint.inf // doesn't contain duplicate models, and it has hundreds of models // listed. You wouldn't check for duplicates there. But oftentimes, @@ -393,305 +362,190 @@ CThirdPage::CopyPrinterSettings( Printer * printer, Service * service, Manufactu OSStatus CThirdPage::LoadPrintDriverDefsFromFile(Manufacturers & manufacturers, const CString & filename, bool checkForDuplicateModels ) { - PrinterParsingState state = Looking; - Manufacturers::iterator iter = manufacturers.end(); - CStdioFileEx file; - CFileException feError; - CString s; - OSStatus err; - BOOL ok; - - typedef std::map StringMap; + HINF handle = INVALID_HANDLE_VALUE; + const TCHAR * section = TEXT( "Manufacturer" ); + LONG sectionCount; + TCHAR line[ 1000 ]; + CString klass; + INFCONTEXT manufacturerContext; + BOOL ok; + OSStatus err = 0; + + // Make sure we can open the file + handle = SetupOpenInfFile( filename, NULL, INF_STYLE_WIN4, NULL ); + translate_errno( handle != INVALID_HANDLE_VALUE, GetLastError(), kUnknownErr ); + require_noerr( err, exit ); - StringMap strings; - - ok = file.Open( filename, CFile::modeRead|CFile::typeText, &feError); - err = translate_errno( ok, errno_compat(), kUnknownErr ); + // Make sure it's a printer file + ok = SetupGetLineText( NULL, handle, TEXT( "Version" ), TEXT( "Class" ), line, sizeof( line ), NULL ); + translate_errno( ok, GetLastError(), kUnknownErr ); require_noerr( err, exit ); + klass = line; + require_action( klass == TEXT( "Printer" ), exit, err = kUnknownErr ); - check ( state == Looking ); - check ( iter == manufacturers.end() ); + sectionCount = SetupGetLineCount( handle, section ); + translate_errno( sectionCount != -1, GetLastError(), kUnknownErr ); + require_noerr( err, exit ); - // - // first, parse the file looking for string sections - // - while (file.ReadString(s)) + memset( &manufacturerContext, 0, sizeof( manufacturerContext ) ); + + for ( LONG i = 0; i < sectionCount; i++ ) { - // - // check for comment - // - if (s.Find(';') == 0) + Manufacturers::iterator iter; + Manufacturer * manufacturer; + CString manufacturerName; + CString temp; + CStringList modelSectionNameDecl; + CString modelSectionName; + CString baseModelName; + CString model; + INFCONTEXT modelContext; + LONG modelCount; + POSITION p; + + if ( i == 0 ) { - continue; - } - - // - // check for tag - // - else if (s.Find('[') == 0) - { - // - // handle any capitalization issues here - // - CString tag = s; - - tag.MakeLower(); - - if (tag == L"[strings]") - { - state = ParsingStrings; - } - else - { - state = Looking; - } + ok = SetupFindFirstLine( handle, section, NULL, &manufacturerContext ); + err = translate_errno( ok, GetLastError(), kUnknownErr ); + require_noerr( err, exit ); } else { - switch (state) - { - case ParsingStrings: - { - int curPos = 0; - - if (s.GetLength() > 0) - { - CString key = s.Tokenize(L"=",curPos); - CString val = s.Tokenize(L"=",curPos); - - // - // get rid of all delimiters - // - key.Trim(); - val.Remove('"'); - - // - // and store it - // - strings[key] = val; - } - } - break; - } + ok = SetupFindNextLine( &manufacturerContext, &manufacturerContext ); + err = translate_errno( ok, GetLastError(), kUnknownErr ); + require_noerr( err, exit ); } - } - - file.Close(); - ok = file.Open( filename, CFile::modeRead|CFile::typeText, &feError); - err = translate_errno( ok, errno_compat(), kUnknownErr ); - require_noerr( err, exit ); - - state = Looking; + ok = SetupGetStringField( &manufacturerContext, 0, line, sizeof( line ), NULL ); + err = translate_errno( ok, GetLastError(), kUnknownErr ); + require_noerr( err, exit ); + manufacturerName = line; - check ( iter == manufacturers.end() ); + ok = SetupGetLineText( &manufacturerContext, handle, NULL, NULL, line, sizeof( line ), NULL ); + err = translate_errno( ok, GetLastError(), kUnknownErr ); + require_noerr( err, exit ); - while (file.ReadString(s)) - { + // Try to find some model section name that has entries. Explanation of int file structure + // can be found at: // - // check for comment - // - if (s.Find(';') == 0) + // + Split( line, ',', modelSectionNameDecl ); + + p = modelSectionNameDecl.GetHeadPosition(); + modelSectionName = modelSectionNameDecl.GetNext( p ); + modelCount = SetupGetLineCount( handle, modelSectionName ); + baseModelName = modelSectionName; + + while ( modelCount <= 0 && p ) { - continue; + CString targetOSVersion; + + targetOSVersion = modelSectionNameDecl.GetNext( p ); + modelSectionName = baseModelName + TEXT( "." ) + targetOSVersion; + modelCount = SetupGetLineCount( handle, modelSectionName ); } - // - // check for tag - // - else if (s.Find('[') == 0) + if ( modelCount > 0 ) { - // - // handle any capitalization issues here - // - CString tag = s; + manufacturerName = NormalizeManufacturerName( manufacturerName ); - tag.MakeLower(); + iter = manufacturers.find( manufacturerName ); - if (tag == L"[manufacturer]") + if ( iter != manufacturers.end() ) { - state = ParsingManufacturers; + manufacturer = iter->second; + require_action( manufacturer, exit, err = kUnknownErr ); } else { - // remove the leading and trailing delimiters - // - s.Remove('['); - s.Remove(']'); - - // check to see if this is a printer entry - // - iter = manufacturers.find(s); - - if (iter != manufacturers.end()) + try { - state = ParsingModels; + manufacturer = new Manufacturer; } - else + catch (...) { - state = Looking; + manufacturer = NULL; } - } - } - // - // only look at this if the line isn't empty, or - // if it isn't a comment - // - else if ((s.GetLength() > 0) && (s.Find(';') != 0)) - { - switch (state) - { - // - // if we're parsing manufacturers, then we will parse - // an entry of the form key=val, where key is a delimited - // string specifying a manufacturer name, and val is - // a tag that is used later in the file. the key is - // delimited by either '"' (quotes) or '%' (percent sign). - // - // the tag is used further down the file when models are - // declared. this allows multiple manufacturers to exist - // in a single inf file. - // - case ParsingManufacturers: - { - Manufacturer * manufacturer; - int curPos = 0; - - CString key = s.Tokenize(L"=",curPos); - CString val = s.Tokenize(L"=",curPos); - - try - { - manufacturer = new Manufacturer; - } - catch (...) - { - manufacturer = NULL; - } - - require_action( manufacturer, exit, err = kNoMemoryErr ); - // - // if it's a variable, look it up - // - if (key.Find('%') == 0) - { - StringMap::iterator it; - - key.Remove('%'); - - it = strings.find(key); - - if (it != strings.end()) - { - key = it->second; - } - } - else - { - key.Remove('"'); - } - - val.TrimLeft(); - val.TrimRight(); + require_action( manufacturer, exit, err = kNoMemoryErr ); - // - // why is there no consistency in inf files? - // - if (val.GetLength() == 0) - { - val = key; - } + manufacturer->name = manufacturerName; + manufacturers[ manufacturerName ] = manufacturer; + } - // - // fix the manufacturer name if necessary - // - curPos = 0; - val = val.Tokenize(L",", curPos); + memset( &modelContext, 0, sizeof( modelContext ) ); - manufacturer->name = NormalizeManufacturerName( key ); - manufacturer->tag = val; + for ( LONG j = 0; j < modelCount; j++ ) + { + CString modelName; + Model * model; - manufacturers[val] = manufacturer; + if ( j == 0 ) + { + ok = SetupFindFirstLine( handle, modelSectionName, NULL, &modelContext ); + err = translate_errno( ok, GetLastError(), kUnknownErr ); + require_noerr( err, exit ); } - break; - - case ParsingModels: + else { - check( iter != manufacturers.end() ); - - Model * model; - int curPos = 0; - - CString name = s.Tokenize(L"=",curPos); - CString description = s.Tokenize(L"=",curPos); - - if (name.Find('%') == 0) - { - StringMap::iterator it; + SetupFindNextLine( &modelContext, &modelContext ); + err = translate_errno( ok, GetLastError(), kUnknownErr ); + require_noerr( err, exit ); + } - name.Remove('%'); + ok = SetupGetStringField( &modelContext, 0, line, sizeof( line ), NULL ); + err = translate_errno( ok, GetLastError(), kUnknownErr ); + require_noerr( err, exit ); - it = strings.find(name); + modelName = line; - if (it != strings.end()) - { - name = it->second; - } - } - else - { - name.Remove('"'); - } - - name.Trim(); - description.Trim(); - - // - // If true, see if we've seen this guy before - // - if (checkForDuplicateModels == true) - { - if ( MatchModel( iter->second, ConvertToModelName( name ) ) != NULL ) - { - continue; - } - } - - try - { - model = new Model; - } - catch (...) + if (checkForDuplicateModels == true) + { + if ( MatchModel( manufacturer, ConvertToModelName( modelName ) ) != NULL ) { - model = NULL; + continue; } + } - require_action( model, exit, err = kNoMemoryErr ); - - model->infFileName = filename; - model->displayName = name; - model->name = name; - model->driverInstalled = false; - - iter->second->models.push_back(model); + // + // Stock Vista printer inf files embed guids in the model + // declarations for Epson printers. Let's ignore those. + // + if ( modelName.Find( TEXT( "{" ), 0 ) != -1 ) + { + continue; } - break; - default: + try { - // pay no attention if we are in any other state + model = new Model; } - break; + catch (...) + { + model = NULL; + } + + require_action( model, exit, err = kNoMemoryErr ); + + model->infFileName = filename; + model->displayName = modelName; + model->name = modelName; + model->driverInstalled = false; + + manufacturer->models.push_back(model); } } } exit: - file.Close(); + if ( handle != INVALID_HANDLE_VALUE ) + { + SetupCloseInfFile( handle ); + handle = NULL; + } - return (err); + return err; } @@ -747,7 +601,7 @@ CThirdPage::LoadPrintDriverDefs( Manufacturers & manufacturers ) // // skip over anything that doesn't have a manufacturer field. This - // fixes a bug that I noticed that occurred after I installed + // fixes a bug that I noticed that occurred after I installed // ProComm. This program add a print driver with no manufacturer // that screwed up this wizard. // @@ -829,7 +683,6 @@ exit: return err; } - // ------------------------------------------------------- // LoadGenericPrintDriverDefs // @@ -853,10 +706,10 @@ CThirdPage::LoadGenericPrintDriverDefs( Manufacturers & manufacturers ) // First try and find our generic driver names iter = m_manufacturers.find(L"HP"); - require_action( iter != manufacturers.end(), exit, err = kUnknownErr ); + require_action( iter != m_manufacturers.end(), exit, err = kUnknownErr ); manufacturer = iter->second; - // Look for Postscript + // Look for Postscript model = manufacturer->find( kGenericPSColorDriver ); @@ -868,7 +721,6 @@ CThirdPage::LoadGenericPrintDriverDefs( Manufacturers & manufacturers ) if ( model ) { psDriverName = model->name; - } // Look for PCL @@ -882,7 +734,7 @@ CThirdPage::LoadGenericPrintDriverDefs( Manufacturers & manufacturers ) if ( model ) { - pclDriverName = model->name; + pclDriverName = model->name; } // If we found either a generic PS driver, or a generic PCL driver, @@ -964,7 +816,7 @@ exit: // ------------------------------------------------------ // ConvertToManufacturerName // -// This function is responsible for tweaking the +// This function is responsible for tweaking the // name so that subsequent string operations won't fail because // of capitalizations/different names for the same manufacturer // (i.e. Hewlett-Packard/HP/Hewlett Packard) @@ -1001,7 +853,6 @@ CThirdPage::ConvertToManufacturerName( const CString & name ) return lower; } - // ------------------------------------------------------ // ConvertToModelName // @@ -1022,7 +873,6 @@ CThirdPage::ConvertToModelName( const CString & name ) return lower; } - // ------------------------------------------------------ // NormalizeManufacturerName // @@ -1047,7 +897,6 @@ CThirdPage::NormalizeManufacturerName( const CString & name ) return normalized; } - // ------------------------------------------------------- // MatchPrinter // @@ -1120,7 +969,7 @@ OSStatus CThirdPage::MatchPrinter(Manufacturers & manufacturers, Printer * print hasGenericDriver = true; } - // Use "application/octet-stream" to determine if CUPS + // Use "application/octet-stream" to determine if CUPS // shared queue supports raw if ( q->pdl.Find( L"application/octet-stream" ) != -1 ) @@ -1128,9 +977,18 @@ OSStatus CThirdPage::MatchPrinter(Manufacturers & manufacturers, Printer * print useCUPSWorkaround = false; } - if ( useCUPSWorkaround && printer->isSharedFromOSX && hasGenericDriver ) + if ( useCUPSWorkaround && printer->isCUPSPrinter && hasGenericDriver ) { - SelectMatch(manufacturers, printer, service, genericManufacturer, genericModel ); + // + // mDNS: Don't allow user to choose non-working driver + // + Manufacturers genericManufacturers; + + LoadGenericPrintDriverDefs( genericManufacturers ); + + SelectMatch( genericManufacturers, printer, service, genericManufacturer, genericModel ); + + FreeManufacturers( genericManufacturers ); } else { @@ -1148,19 +1006,32 @@ OSStatus CThirdPage::MatchPrinter(Manufacturers & manufacturers, Printer * print if (found) { text.LoadString(IDS_PRINTER_MATCH_GOOD); + err = kNoErr; } else if ( MatchGeneric( manufacturers, printer, service, &genericManufacturer, &genericModel ) ) - { - if ( printer->isSharedFromOSX ) + { + if ( printer->isCUPSPrinter ) { + // + // mDNS: Don't allow user to choose non-working driver + // + Manufacturers genericManufacturers; + + LoadGenericPrintDriverDefs( genericManufacturers ); + + SelectMatch( genericManufacturers, printer, service, genericManufacturer, genericModel ); + text.LoadString(IDS_PRINTER_MATCH_GOOD); + + FreeManufacturers( genericManufacturers ); } else { + SelectMatch( manufacturers, printer, service, genericManufacturer, genericModel ); text.LoadString(IDS_PRINTER_MATCH_MAYBE); } - SelectMatch( manufacturers, printer, service, genericManufacturer, genericModel ); + err = kNoErr; } else { @@ -1190,9 +1061,15 @@ OSStatus CThirdPage::MatchPrinter(Manufacturers & manufacturers, Printer * print if (nIndex != -1) { m_manufacturerListCtrl.SetItemState(nIndex, LVIS_SELECTED, LVIS_SELECTED); - m_manufacturerListCtrl.EnsureVisible(nIndex, FALSE); + + // + // mDNS: When auto-highlighting items in lists, scroll list so highlighted item is in the middle + // + AutoScroll(m_manufacturerListCtrl, nIndex); } } + + err = kUnknownErr; } m_printerSelectionText.SetWindowText(text); @@ -1200,7 +1077,6 @@ OSStatus CThirdPage::MatchPrinter(Manufacturers & manufacturers, Printer * print return err; } - // ------------------------------------------------------ // MatchManufacturer // @@ -1237,7 +1113,6 @@ CThirdPage::MatchManufacturer( Manufacturers & manufacturers, const CString & na return NULL; } - // ------------------------------------------------------- // MatchModel // @@ -1288,7 +1163,6 @@ CThirdPage::MatchModel(Manufacturer * manufacturer, const CString & name) return NULL; } - // ------------------------------------------------------- // MatchGeneric // @@ -1318,12 +1192,12 @@ CThirdPage::MatchGeneric( Manufacturers & manufacturers, Printer * printer, Serv pdl = q->pdl; pdl.MakeLower(); - if ( pdl.Find( kPDLPCLKey ) != -1 ) + if ( m_genericPCL && ( pdl.Find( kPDLPCLKey ) != -1 ) ) { *model = m_genericPCL; ok = TRUE; } - else if ( pdl.Find( kPDLPostscriptKey ) != -1 ) + else if ( m_genericPostscript && ( pdl.Find( kPDLPostscriptKey ) != -1 ) ) { *model = m_genericPostscript; ok = TRUE; @@ -1334,7 +1208,6 @@ exit: return ok; } - // ----------------------------------------------------------- // OnInitPage // @@ -1349,12 +1222,9 @@ OSStatus CThirdPage::OnInitPage() OSStatus err = kNoErr; // Load printer icon - - - check( m_printerImage == NULL ); - m_printerImage = (CStatic*) GetDlgItem( IDR_MANIFEST ); + m_printerImage = (CStatic*) GetDlgItem( 1 ); // 1 == IDR_MANIFEST check( m_printerImage ); if ( m_printerImage != NULL ) @@ -1372,7 +1242,7 @@ OSStatus CThirdPage::OnInitPage() // // - // we have to make sure that we only do this once. Typically, + // we have to make sure that we only do this once. Typically, // we would do this in something like OnInitDialog, but we don't // have this in Wizards, because the window is a PropertySheet. // We're considered fully initialized when we receive the first @@ -1389,7 +1259,6 @@ OSStatus CThirdPage::OnInitPage() return (err); } - void CThirdPage::DoDataExchange(CDataExchange* pDX) { CPropertyPage::DoDataExchange(pDX); @@ -1401,7 +1270,6 @@ void CThirdPage::DoDataExchange(CDataExchange* pDX) } - // ---------------------------------------------------------- // OnSetActive // @@ -1436,6 +1304,20 @@ CThirdPage::OnSetActive() m_initialized = true; } + // + // mDNS: Printers added using Bonjour should be set as the default printer. + // + if ( DefaultPrinterExists() ) + { + m_defaultPrinterCtrl.SetCheck( BST_UNCHECKED ); + printer->deflt = false; + } + else + { + m_defaultPrinterCtrl.SetCheck( BST_CHECKED ); + printer->deflt = true; + } + // // update the UI with the printer name // @@ -1451,9 +1333,14 @@ CThirdPage::OnSetActive() // and try and match the printer // - if ( psheet->GetLastPage() == psheet->GetPage(1) ) + if ( psheet->GetLastPage() == psheet->GetPage(0) ) { MatchPrinter( m_manufacturers, printer, service, true ); + + if ( ( m_manufacturerSelected != NULL ) && ( m_modelSelected != NULL ) ) + { + GetParent()->PostMessage(PSM_SETCURSEL, 2 ); + } } else { @@ -1465,14 +1352,13 @@ exit: return CPropertyPage::OnSetActive(); } - BOOL CThirdPage::OnKillActive() { CPrinterSetupWizardSheet * psheet; psheet = reinterpret_cast(GetParent()); - require_quiet( psheet, exit ); + require_quiet( psheet, exit ); psheet->SetLastPage(this); @@ -1481,7 +1367,6 @@ exit: return CPropertyPage::OnKillActive(); } - // ------------------------------------------------------- // PopulateUI // @@ -1510,7 +1395,6 @@ CThirdPage::PopulateUI(Manufacturers & manufacturers) return 0; } - BEGIN_MESSAGE_MAP(CThirdPage, CPropertyPage) ON_NOTIFY(LVN_ITEMCHANGED, IDC_PRINTER_MANUFACTURER, OnLvnItemchangedManufacturer) ON_NOTIFY(LVN_ITEMCHANGED, IDC_PRINTER_MODEL, OnLvnItemchangedPrinterModel) @@ -1518,7 +1402,6 @@ BEGIN_MESSAGE_MAP(CThirdPage, CPropertyPage) ON_BN_CLICKED(IDC_HAVE_DISK, OnBnClickedHaveDisk) END_MESSAGE_MAP() - // CThirdPage message handlers void CThirdPage::OnLvnItemchangedManufacturer(NMHDR *pNMHDR, LRESULT *pResult) { @@ -1595,7 +1478,6 @@ exit: *pResult = 0; } - void CThirdPage::OnBnClickedDefaultPrinter() { CPrinterSetupWizardSheet * psheet; @@ -1646,10 +1528,29 @@ void CThirdPage::OnBnClickedHaveDisk() { PopulateUI( manufacturers ); - MatchPrinter( manufacturers, printer, service, false ); + if ( MatchPrinter( manufacturers, printer, service, false ) != kNoErr ) + { + CString errorMessage; + CString errorCaption; + + errorMessage.LoadString( IDS_NO_MATCH_INF_FILE ); + errorCaption.LoadString( IDS_NO_MATCH_INF_FILE_CAPTION ); + + MessageBox( errorMessage, errorCaption, MB_OK ); + } break; } + else + { + CString errorMessage; + CString errorCaption; + + errorMessage.LoadString( IDS_BAD_INF_FILE ); + errorCaption.LoadString( IDS_BAD_INF_FILE_CAPTION ); + + MessageBox( errorMessage, errorCaption, MB_OK ); + } } else { @@ -1659,5 +1560,24 @@ void CThirdPage::OnBnClickedHaveDisk() exit: + FreeManufacturers( manufacturers ); return; } + + +void +CThirdPage::Split( const CString & string, TCHAR ch, CStringList & components ) +{ + CString temp; + int n; + + temp = string; + + while ( ( n = temp.Find( ch ) ) != -1 ) + { + components.AddTail( temp.Left( n ) ); + temp = temp.Right( temp.GetLength() - ( n + 1 ) ); + } + + components.AddTail( temp ); +}