+ q = service->queues.front();
+ check( q );
+
+ //
+ // add the printer
+ //
+ ZeroMemory(&pInfo, sizeof(pInfo));
+
+ pInfo.pPrinterName = printer->actualName.GetBuffer();
+ pInfo.pServerName = NULL;
+ pInfo.pShareName = NULL;
+ pInfo.pPortName = printer->portName.GetBuffer();
+ pInfo.pDriverName = printer->modelName.GetBuffer();
+ pInfo.pComment = printer->displayModelName.GetBuffer();
+ pInfo.pLocation = q->location.GetBuffer();
+ pInfo.pDevMode = NULL;
+ pInfo.pDevMode = NULL;
+ pInfo.pSepFile = L"";
+ pInfo.pPrintProcessor = L"winprint";
+ pInfo.pDatatype = L"RAW";
+ pInfo.pParameters = L"";
+ pInfo.pSecurityDescriptor = NULL;
+ pInfo.Attributes = PRINTER_ATTRIBUTE_QUEUED;
+ pInfo.Priority = 0;
+ pInfo.DefaultPriority = 0;
+ pInfo.StartTime = 0;
+ pInfo.UntilTime = 0;
+
+ hPrinter = AddPrinter(NULL, 2, (LPBYTE) &pInfo);
+ err = translate_errno( hPrinter, errno_compat(), kUnknownErr );
+ require_noerr_with_log( log, "AddPrinter()", err, exit );
+
+exit:
+
+ if (hPrinter != NULL)
+ {
+ ClosePrinter(hPrinter);
+ }
+
+ return err;
+}
+
+
+OSStatus
+CPrinterSetupWizardSheet::InstallPrinterIPP(Printer * printer, Service * service, Logger & log)
+{
+ DEBUG_UNUSED( service );
+
+ Queue * q = service->SelectedQueue();
+ HANDLE hPrinter = NULL;
+ PRINTER_INFO_2 pInfo;
+ OSStatus err;
+
+ check( q );
+
+ //
+ // add the printer
+ //
+ ZeroMemory(&pInfo, sizeof(PRINTER_INFO_2));
+
+ pInfo.pPrinterName = printer->actualName.GetBuffer();
+ pInfo.pPortName = printer->portName.GetBuffer();
+ pInfo.pDriverName = printer->modelName.GetBuffer();
+ pInfo.pPrintProcessor = L"winprint";
+ pInfo.pLocation = q->location.GetBuffer();
+ pInfo.pComment = printer->displayModelName.GetBuffer();
+ pInfo.Attributes = PRINTER_ATTRIBUTE_NETWORK | PRINTER_ATTRIBUTE_LOCAL;
+
+ hPrinter = AddPrinter(NULL, 2, (LPBYTE)&pInfo);
+ err = translate_errno( hPrinter, errno_compat(), kUnknownErr );
+ require_noerr_with_log( log, "AddPrinter()", err, exit );
+
+exit:
+
+ if ( hPrinter != NULL )
+ {
+ ClosePrinter(hPrinter);
+ }
+
+ return err;
+}
+
+
+OSStatus
+CPrinterSetupWizardSheet::InstallPrinterCUPS(Printer * printer, Service * service, CUPSLibrary & cupsLib )
+{
+ OSStatus err = kNoErr;
+
+ check( printer );
+ check( service );
+ check( cupsLib.IsInstalled() );
+
+ err = InstallPrinterCUPS( printer, service, cupsLib, TEXT( "Windows NT x86" ) );
+ require_noerr( err, exit );
+
+ if ( Is64BitWindows() )
+ {
+ err = InstallPrinterCUPS( printer, service, cupsLib, TEXT( "Windows x64" ) );
+ require_noerr( err, exit );
+ }
+
+exit:
+
+ return err;
+}
+
+
+OSStatus
+CPrinterSetupWizardSheet::InstallPrinterCUPS(Printer * printer, Service * service, CUPSLibrary & cupsLib, TCHAR * env )
+{
+
+ Queue * q;
+ CString ppdfile; // PPD file for printer drivers
+ TCHAR driverdir[1024]; // Directory for driver files
+ DWORD needed; // Bytes needed
+ DRIVER_INFO_3 driverinfo; // Driver information
+ PRINTER_INFO_2 printerinfo; // Printer information
+ HANDLE printerHandle = NULL; // Handle to printer
+ CString filename; // Driver filename
+ CString dependentFiles; // List of dependent files
+ CString portName; // Port Name
+ int bytes; // Bytes copied
+ TCHAR datadir[ MAX_PATH ]; // Driver files location
+ CFile in; // Input file
+ CFile out; // Output file
+ void * http; // Connection to server
+ char buffer[4096]; // Copy/error buffer
+ CString platform;
+ char hostname[ 1024 ];
+ CString dest;
+ char destANSI[ 1024 ];
+ int i;
+ DWORD num;
+ OSStatus err = 0;
+ BOOL ok;
+
+ check( printer );
+ check( service );
+ check( cupsLib.IsInstalled() );
+ check( env );
+
+ // What do we do here for multiple queues?
+ q = service->queues.front();
+ require_action( q != NULL, exit, err = kUnknownErr );
+
+ num = GetModuleFileName( NULL, datadir, MAX_PATH );
+ err = translate_errno( num > 0, GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
+ ok = PathRemoveFileSpec( datadir );
+ require_action( ok, exit, err = kUnknownErr );
+
+ ok = GetPrinterDriverDirectory(NULL, env, 1, ( LPBYTE ) driverdir, sizeof( driverdir ), &needed );
+ err = translate_errno( ok, GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
+
+ platform = env;
+ platform = platform.Right( 3 );
+
+ // Append the supported banner pages to the PPD file...
+ err = StringObjectToUTF8String( service->hostname, hostname, sizeof( hostname ) );
+ require_noerr( err, exit );
+ http = cupsLib.httpConnectEncrypt( hostname, service->portNumber, cupsLib.cupsEncryption() );
+ err = translate_errno( http != NULL, errno, kUnknownErr );
+ require_noerr( err, exit );
+
+ if ( ( service->portNumber == 443 ) || ( cupsLib.cupsEncryption() >= HTTP_ENCRYPT_REQUIRED ) )
+ {
+ // This forces the use the https: URLs below...
+ cupsLib.cupsSetEncryption( HTTP_ENCRYPT_ALWAYS );
+ }
+
+ // Strip the leading "printers/" or "classes/" from the beginning
+ // of the name
+
+ dest = q->name;
+ dest.Replace( TEXT( "printers/" ), TEXT( "" ) );
+ dest.Replace( TEXT( "classes/" ), TEXT( "" ) );
+
+ err = StringObjectToUTF8String( dest, destANSI, sizeof( destANSI ) );
+ require_noerr( err, exit );
+
+ // Get the PPD file...
+ for ( i = 0; i < 10; i++ )
+ {
+ char ppdfileANSI[ 1024 ];
+
+ if ( cupsLib.cupsAdminCreateWindowsPPD( http, destANSI, ppdfileANSI, sizeof( ppdfileANSI ) ) )
+ {
+ err = UTF8StringToStringObject( ppdfileANSI, ppdfile );
+ require_noerr( err, exit );
+ break;
+ }
+ }
+
+ err = translate_errno( i < 10, errno, kUnknownErr );
+ require_noerr( err, exit );
+
+ // Copy the PPD file to the Windows driver directory...
+ filename.Format( TEXT( "%s/%s.ppd" ), driverdir, dest );
+
+ ok = in.Open( ppdfile, CFile::modeRead | CFile::typeBinary );
+ translate_errno( ok, GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
+
+ ok = out.Open( filename, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary );
+ translate_errno( ok, GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
+
+ while ( ( bytes = in.Read( buffer, sizeof(buffer) ) ) > 0 )
+ {
+ out.Write(buffer, bytes );
+ }
+
+ in.Close();
+ out.Close();
+
+ // Cleanup temp file...
+ CFile::Remove( ppdfile );
+
+ // Copy the driver files to the driver directory...
+ for ( i = 0; i < ( sizeof( g_printerDriverFiles ) / sizeof( g_printerDriverFiles[0] ) ); i++ )
+ {
+ filename.Format( TEXT( "%s/drivers/%s/%s" ), datadir, platform, g_printerDriverFiles[i]);
+
+ ok = in.Open(filename, CFile::modeRead | CFile::typeBinary );
+ err = translate_errno( ok, GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
+
+ filename.Format( TEXT( "%s/%s" ), driverdir, g_printerDriverFiles[i] );
+ ok = out.Open(filename, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary );
+ err = translate_errno( ok, errno, kUnknownErr );
+
+ while ( ( bytes = in.Read(buffer, sizeof( buffer ) ) ) > 0 )
+ {
+ out.Write( buffer, bytes );
+ }
+
+ in.Close();
+ out.Close();
+ }
+
+ // Do the Windows system calls needed to add the printer driver...
+ filename.Format( TEXT( "%s.ppd" ), dest);
+ dependentFiles.Format( TEXT( "pscript5.dll%c" ) TEXT( "%s.ppd%c" ) TEXT( "ps5ui.dll%c" ) TEXT( "pscript.hlp%c" ) TEXT( "pscript.ntf%c" ) TEXT( "cups6.ini%c" ) TEXT( "cupsps6.dll%c" ) TEXT( "cupsui6.dll%c" ), 0, dest, 0, 0, 0, 0, 0, 0, 0);
+
+ driverinfo.cVersion = 3;
+ driverinfo.pName = printer->actualName.GetBuffer();
+ driverinfo.pEnvironment = env;
+ driverinfo.pDriverPath = TEXT( "pscript5.dll" );
+ driverinfo.pDataFile = filename.GetBuffer();
+ driverinfo.pConfigFile = TEXT( "ps5ui.dll" );
+ driverinfo.pHelpFile = TEXT( "pscript.hlp" );
+ driverinfo.pDependentFiles = dependentFiles.GetBuffer();
+ driverinfo.pMonitorName = NULL;
+ driverinfo.pDefaultDataType = TEXT( "raw" );
+
+ ok = AddPrinterDriverEx(NULL, 3, (LPBYTE) &driverinfo, APD_COPY_ALL_FILES );
+ err = translate_errno( ok, GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
+
+ // See if the printer has already been added?
+ if ( OpenPrinter( printer->actualName.GetBuffer(), &printerHandle, NULL ) )
+ {
+ // Printer already exists, so we are done now...
+ goto exit;
+ }
+
+ // Add the printer using the HTTP/IPP port...
+ portName.Format( TEXT( "%s://%s:%d/printers/%s" ), cupsLib.cupsEncryption() == HTTP_ENCRYPT_ALWAYS ? TEXT( "https" ) : TEXT( "http" ), service->hostname.GetBuffer(), service->portNumber, dest );
+
+ memset(&printerinfo, 0, sizeof(printerinfo));
+ printerinfo.pPrinterName = printer->actualName.GetBuffer();
+ printerinfo.pPortName = portName.GetBuffer();
+ printerinfo.pDriverName = printer->actualName.GetBuffer();
+ printerinfo.Attributes = PRINTER_ATTRIBUTE_NETWORK | PRINTER_ATTRIBUTE_LOCAL;
+ printerinfo.pComment = q->description.GetBuffer();
+ printerinfo.pLocation = q->location.GetBuffer();
+ printerinfo.pPrintProcessor = TEXT( "winprint" );
+
+ printerHandle = AddPrinter( NULL, 2, (LPBYTE) &printerinfo );
+ err = translate_errno( printerHandle, GetLastError(), kUnknownErr );
+ require_noerr( err, exit );
+
+exit:
+
+ if ( printerHandle != NULL )
+ {
+ ClosePrinter( printerHandle );
+ printerHandle = NULL;
+ }
+
+ return err;
+}
+
+BEGIN_MESSAGE_MAP(CPrinterSetupWizardSheet, CPropertySheet)
+ON_MESSAGE( WM_SOCKET_EVENT, OnSocketEvent )
+ON_MESSAGE( WM_PROCESS_EVENT, OnProcessEvent )
+ON_WM_SETCURSOR()
+ON_WM_TIMER()
+END_MESSAGE_MAP()
+
+
+// ------------------------------------------------------
+// OnCommand
+//
+// Traps when the user hits Finish
+//
+BOOL CPrinterSetupWizardSheet::OnCommand(WPARAM wParam, LPARAM lParam)