]> git.saurik.com Git - apple/mdnsresponder.git/blobdiff - Clients/PrinterSetupWizard/ThirdPage.cpp
mDNSResponder-878.200.35.tar.gz
[apple/mdnsresponder.git] / Clients / PrinterSetupWizard / ThirdPage.cpp
index 4c156fd98d32cc0da1bacc359fec8a5b9676aa54..6caf55cb29207c46313c46ccd23c12a75ad476f0 100644 (file)
  * 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.
-
-    Change History (most recent first):
-    
-$Log: ThirdPage.cpp,v $
-Revision 1.37  2007/06/08 06:30:26  herscher
-<rdar://problem/5257700> Fix uninitialized pointers when detecting generic PCL and PS drivers
-
-Revision 1.36  2007/06/06 20:39:10  cheshire
-<rdar://problem/5254377> Printer Setup Wizard started crashing in Bonjour104A8, after update to Visual Studio 2005
-
-Revision 1.35  2007/06/06 20:08:01  cheshire
-<rdar://problem/4528853> mDNS: When auto-highlighting items in lists, scroll list so highlighted item is in the middle
-AutoScroll model list as well as manufacturer list
-
-Revision 1.34  2007/06/06 19:53:48  cheshire
-<rdar://problem/5187308> Move build train to Visual Studio 2005
-
-Revision 1.33  2007/04/20 22:58:10  herscher
-<rdar://problem/4826126> mDNS: Printer Wizard doesn't offer generic HP printers or generic PS support on Vista RC2
-
-Revision 1.32  2007/04/13 23:42:20  herscher
-<rdar://problem/4580061> mDNS: Printers added using Bonjour should be set as the default printer.
-
-Revision 1.31  2007/04/13 21:38:46  herscher
-<rdar://problem/4528853> mDNS: When auto-highlighting items in lists, scroll list so highlighted item is in the middle
-
-Revision 1.30  2007/04/13 20:23:40  herscher
-Fixed mistake in previous checkin that reverted license text for this file
-
-Revision 1.29  2007/04/13 18:10:24  herscher
-<rdar://problem/4496652> mDNS: Don't allow user to choose non-working driver
-
-Revision 1.28  2006/08/14 23:24:09  cheshire
-Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
-
-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://problem/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)
@@ -179,16 +52,6 @@ First checked in
 #define kGenericPCLColorDriver         L"HP Color LaserJet 4550 PCL"
 #define kGenericPCLDriver                      L"HP LaserJet 4050 Series PCL"
 
-//
-// states for parsing ntprint.inf
-//
-enum PrinterParsingState
-{
-       Looking,
-       ParsingManufacturers,
-       ParsingModels,
-       ParsingStrings
-};
 
 // CThirdPage dialog
 
@@ -275,32 +138,27 @@ exit:
        return;
 }
 
-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
 //
@@ -374,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;
@@ -417,6 +277,18 @@ 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 ) );
+               }
+       }
 }
 
 // --------------------------------------------------------
@@ -478,24 +350,6 @@ CThirdPage::AutoScroll( CListCtrl & list, int nIndex )
 // ------------------------------------------------------
 // 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
 // checkForDuplicateModels flag.  The problem here is that ntprint.inf
 // doesn't contain duplicate models, and it has hundreds of models
@@ -508,345 +362,193 @@ CThirdPage::AutoScroll( CListCtrl & list, int nIndex )
 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)
-               {
-                       continue;
-               }
-
-               //
-               // check for tag
-               //
-               else 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 )
                {
-                       //
-                       // 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))
-       {
-               //
-               // check for comment
+               // Try to find some model section name that has entries. Explanation of int file structure
+               // can be found at:
                //
-               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
                        {
-                               CString name;
-                               int             curPos;
-
-                               //
-                               // remove the leading and trailing delimiters
-                               //
-                               s.Remove('[');
-                               s.Remove(']');
-
-                               //
-                               // <rdar://problem/4826126>
-                               //
-                               // Ignore decorations in model declarations
-                               //
-                               curPos  = 0;
-                               name    = s.Tokenize( L".", curPos );
-
-                               //
-                               // check to see if this is a printer entry
-                               //
-                               iter = manufacturers.find( name );
-
-                               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();
-
-                                       //
-                                       // why is there no consistency in inf files?
-                                       //
-                                       if (val.GetLength() == 0)
-                                       {
-                                               val = key;
-                                       }
+                               require_action( manufacturer, exit, err = kNoMemoryErr );
 
-                                       //
-                                       // fix the manufacturer name if necessary
-                                       //
-                                       curPos  =       0;
-                                       val             =       val.Tokenize(L",", curPos);
+                               manufacturer->name                                      = manufacturerName;
+                               manufacturers[ manufacturerName ]       = manufacturer;
+                       }
 
-                                       for ( ;; )
-                                       {
-                                               CString decoration;
-
-                                               decoration = val.Tokenize( L",", curPos );
-
-                                               if ( decoration.GetLength() > 0 )
-                                               {
-                                                       manufacturer->decorations.push_back( decoration );
-                                               }
-                                               else
-                                               {
-                                                       break;
-                                               }
-                                       }
+                       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;
-
-                                               name.Remove('%');
+                                       SetupFindNextLine( &modelContext, &modelContext );
+                                       err = translate_errno( ok, GetLastError(), kUnknownErr );
+                                       require_noerr( err, exit );
+                               }
 
-                                               it = strings.find(name);
+                               ok = SetupGetStringField( &modelContext, 0, line, sizeof( line ), NULL );
+                               err = translate_errno( ok, GetLastError(), kUnknownErr );
+                               require_noerr( err, exit );
 
-                                               if (it != strings.end())
-                                               {
-                                                       name = it->second;
-                                               }
-                                       }
-                                       else
-                                       {
-                                               name.Remove('"');
-                                       }
+                               modelName = line;
 
-                                       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;
-                                               }
-                                       }
-
-                                       //
-                                       // Stock Vista printer inf files embed guids in the model
-                                       // declarations for Epson printers. Let's ignore those.
-                                       //
-                                       if ( name.Find( L"{", 0 ) != -1 )
+                               if (checkForDuplicateModels == true)
+                               {
+                                       if ( MatchModel( manufacturer, ConvertToModelName( modelName ) ) != NULL )
                                        {
                                                continue;
                                        }
+                               }
 
-                                       try
-                                       {
-                                               model = new Model;
-                                       }
-                                       catch (...)
-                                       {
-                                               model = NULL;
-                                       }
-
-                                       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;
 }
 
+
 // -------------------------------------------------------
 // LoadPrintDriverDefs
 //
@@ -1275,7 +977,7 @@ OSStatus CThirdPage::MatchPrinter(Manufacturers & manufacturers, Printer * print
                                useCUPSWorkaround = false;
                        }
 
-                       if ( useCUPSWorkaround && printer->isSharedFromOSX && hasGenericDriver )
+                       if ( useCUPSWorkaround && printer->isCUPSPrinter && hasGenericDriver )
                        {
                                //
                                // <rdar://problem/4496652> mDNS: Don't allow user to choose non-working driver
@@ -1285,6 +987,8 @@ OSStatus CThirdPage::MatchPrinter(Manufacturers & manufacturers, Printer * print
                                LoadGenericPrintDriverDefs( genericManufacturers );
 
                                SelectMatch( genericManufacturers, printer, service, genericManufacturer, genericModel );
+
+                               FreeManufacturers( genericManufacturers );
                        }
                        else
                        {
@@ -1302,10 +1006,11 @@ 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 )
                {
                        //
                        // <rdar://problem/4496652> mDNS: Don't allow user to choose non-working driver
@@ -1317,12 +1022,16 @@ OSStatus CThirdPage::MatchPrinter(Manufacturers & manufacturers, Printer * print
                        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);
                }
+
+               err = kNoErr;
        }
        else
        {
@@ -1359,6 +1068,8 @@ OSStatus CThirdPage::MatchPrinter(Manufacturers & manufacturers, Printer * print
                                AutoScroll(m_manufacturerListCtrl, nIndex);
                        }
                }
+
+               err = kUnknownErr;
        }
 
        m_printerSelectionText.SetWindowText(text);
@@ -1622,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
        {
@@ -1812,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
                {
@@ -1825,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 );
+}