-/*
+/* -*- 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
-<rdar://problem/4190104> Use "application/octet-stream" to determine if CUPS shared queue supports raw
-
-Revision 1.26 2005/07/11 20:17:15 shersche
-<rdar://4124524> 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
-<rdar://problem/4124524> Workaround for Mac OS X Printer Sharing bug
-
-Revision 1.23 2005/04/18 02:33:47 shersche
-<rdar://problem/4091216> Default printer option cannot be deselected
-
-Revision 1.22 2005/04/13 17:46:22 shersche
-<rdar://problem/4082122> 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
-<rdar://problem/4030388> Generic drivers don't do color
-
-Revision 1.19 2005/02/23 02:08:51 shersche
-<rdar://problem/4012275> 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
-<rdar://problem/4003724> Display different UI text when generic printer drivers are selected
-
-Revision 1.17 2005/02/08 21:45:06 shersche
-<rdar://problem/3947490> 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
-<rdar://problem/3911084> 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
-<rdar://problem/3841218> 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
-<rdar://problem/3725106>
-<rdar://problem/3737413> 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
-<rdar://problem/3827624> 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 <dns_sd.h>
-#include <tcpxcv.h>
#include <winspool.h>
+#include <setupapi.h>
// 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
//
#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;
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);
+ //
+ // <rdar://problem/4826126>
+ //
+ // 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
}
-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
//
// ----------------------------------------------------
if (nIndex != -1)
{
m_manufacturerListCtrl.SetItemState(nIndex, LVIS_SELECTED, LVIS_SELECTED);
- m_manufacturerListCtrl.EnsureVisible(nIndex, FALSE);
+ //
+ //<rdar://problem/4528853> mDNS: When auto-highlighting items in lists, scroll list so highlighted item is in the middle
+ //
+ AutoScroll(m_manufacturerListCtrl, nIndex);
}
//
if (nIndex != -1)
{
m_modelListCtrl.SetItemState(nIndex, LVIS_SELECTED, LVIS_SELECTED);
- m_modelListCtrl.EnsureVisible(nIndex, FALSE);
+ AutoScroll( m_modelListCtrl, nIndex );
m_modelListCtrl.SetFocus();
}
CopyPrinterSettings( printer, service, manufacturer, model );
}
-
void
CThirdPage::SelectMatch(Manufacturers & manufacturers, Printer * printer, Service * service, Manufacturer * manufacturer, Model * model)
{
SelectMatch( printer, service, manufacturer, model );
}
-
// --------------------------------------------------------
// CopyPrinterSettings
//
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;
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 )
+{
+ //
+ //<rdar://problem/4528853> 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,
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<CString, CString> 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)
+ // <http://msdn.microsoft.com/en-us/library/ms794359.aspx>
+ 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;
}
//
// 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.
//
return err;
}
-
// -------------------------------------------------------
// LoadGenericPrintDriverDefs
//
// 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 );
if ( model )
{
psDriverName = model->name;
-
}
// Look for PCL
if ( model )
{
- pclDriverName = model->name;
+ pclDriverName = model->name;
}
// If we found either a generic PS driver, or a generic PCL driver,
// ------------------------------------------------------
// 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)
return lower;
}
-
// ------------------------------------------------------
// ConvertToModelName
//
return lower;
}
-
// ------------------------------------------------------
// NormalizeManufacturerName
//
return normalized;
}
-
// -------------------------------------------------------
// MatchPrinter
//
hasGenericDriver = true;
}
- // <rdar://problem/4190104> Use "application/octet-stream" to determine if CUPS
+ // <rdar://problem/4190104> Use "application/octet-stream" to determine if CUPS
// shared queue supports raw
if ( q->pdl.Find( L"application/octet-stream" ) != -1 )
useCUPSWorkaround = false;
}
- if ( useCUPSWorkaround && printer->isSharedFromOSX && hasGenericDriver )
+ if ( useCUPSWorkaround && printer->isCUPSPrinter && hasGenericDriver )
{
- SelectMatch(manufacturers, printer, service, genericManufacturer, genericModel );
+ //
+ // <rdar://problem/4496652> mDNS: Don't allow user to choose non-working driver
+ //
+ Manufacturers genericManufacturers;
+
+ LoadGenericPrintDriverDefs( genericManufacturers );
+
+ SelectMatch( genericManufacturers, printer, service, genericManufacturer, genericModel );
+
+ FreeManufacturers( genericManufacturers );
}
else
{
if (found)
{
text.LoadString(IDS_PRINTER_MATCH_GOOD);
+ err = kNoErr;
}
else if ( MatchGeneric( manufacturers, printer, service, &genericManufacturer, &genericModel ) )
- {
- if ( printer->isSharedFromOSX )
+ {
+ if ( printer->isCUPSPrinter )
{
+ //
+ // <rdar://problem/4496652> 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
{
if (nIndex != -1)
{
m_manufacturerListCtrl.SetItemState(nIndex, LVIS_SELECTED, LVIS_SELECTED);
- m_manufacturerListCtrl.EnsureVisible(nIndex, FALSE);
+
+ //
+ //<rdar://problem/4528853> 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);
return err;
}
-
// ------------------------------------------------------
// MatchManufacturer
//
return NULL;
}
-
// -------------------------------------------------------
// MatchModel
//
return NULL;
}
-
// -------------------------------------------------------
// MatchGeneric
//
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;
return ok;
}
-
// -----------------------------------------------------------
// 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 )
//
//
- // 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
return (err);
}
-
void CThirdPage::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
}
-
// ----------------------------------------------------------
// OnSetActive
//
m_initialized = true;
}
+ //
+ // <rdar://problem/4580061> 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
//
// 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
{
return CPropertyPage::OnSetActive();
}
-
BOOL
CThirdPage::OnKillActive()
{
CPrinterSetupWizardSheet * psheet;
psheet = reinterpret_cast<CPrinterSetupWizardSheet*>(GetParent());
- require_quiet( psheet, exit );
+ require_quiet( psheet, exit );
psheet->SetLastPage(this);
return CPropertyPage::OnKillActive();
}
-
// -------------------------------------------------------
// PopulateUI
//
return 0;
}
-
BEGIN_MESSAGE_MAP(CThirdPage, CPropertyPage)
ON_NOTIFY(LVN_ITEMCHANGED, IDC_PRINTER_MANUFACTURER, OnLvnItemchangedManufacturer)
ON_NOTIFY(LVN_ITEMCHANGED, IDC_PRINTER_MODEL, OnLvnItemchangedPrinterModel)
ON_BN_CLICKED(IDC_HAVE_DISK, OnBnClickedHaveDisk)
END_MESSAGE_MAP()
-
// CThirdPage message handlers
void CThirdPage::OnLvnItemchangedManufacturer(NMHDR *pNMHDR, LRESULT *pResult)
{
*pResult = 0;
}
-
void CThirdPage::OnBnClickedDefaultPrinter()
{
CPrinterSetupWizardSheet * psheet;
{
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
{
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 );
+}