DEBUG_LOCAL OSStatus EnableNSP( const char *inGUID, BOOL inEnable ) { OSStatus err; WSADATA wsd; GUID guid; require_action( inGUID && ( *inGUID != '\0' ), exit, err = kParamErr ); err = StringToGUID( inGUID, &guid ); require_noerr( err, exit ); err = WSAStartup( MAKEWORD( 2, 2 ), &wsd ); err = translate_errno( err == 0, errno_compat(), WSAEINVAL ); require_noerr( err, exit ); err = WSCEnableNSProvider( &guid, inEnable ); err = translate_errno( err == 0, errno_compat(), WSAEINVAL ); WSACleanup(); require_noerr( err, exit ); if (!gToolQuietMode) { fprintf( stderr, "Removed NSP %s\n", inGUID ); } exit: if( err != kNoErr ) { fprintf( stderr, "### FAILED (%d) to remove %s Name Space Provider\n", err, inGUID ); } return( err ); }
OSStatus CSecondPage::LoadPrinterNames() { PBYTE buffer = NULL; OSStatus err = 0; // // rdar://problem/3701926 - Printer can't be installed twice // // First thing we want to do is make sure the printer isn't already installed. // If the printer name is found, we'll try and rename it until we // find a unique name // DWORD dwNeeded = 0, dwNumPrinters = 0; BOOL ok = EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, NULL, 0, &dwNeeded, &dwNumPrinters); err = translate_errno( ok, errno_compat(), kUnknownErr ); if ((err == ERROR_INSUFFICIENT_BUFFER) && (dwNeeded > 0)) { try { buffer = new unsigned char[dwNeeded]; } catch (...) { buffer = NULL; } require_action( buffer, exit, kNoMemoryErr ); ok = EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, buffer, dwNeeded, &dwNeeded, &dwNumPrinters); err = translate_errno( ok, errno_compat(), kUnknownErr ); require_noerr( err, exit ); for (DWORD index = 0; index < dwNumPrinters; index++) { PRINTER_INFO_4 * lppi4 = (PRINTER_INFO_4*) (buffer + index * sizeof(PRINTER_INFO_4)); m_printerNames[lppi4->pPrinterName] = lppi4->pPrinterName; } } exit: if (buffer != NULL) { delete [] buffer; } return err; }
OSStatus CPrinterSetupWizardSheet::InstallPrinterIPP(Printer * printer, Service * service) { DEBUG_UNUSED( service ); HANDLE hPrinter = NULL; PRINTER_INFO_2 pInfo; OSStatus err; // // add the printer // ZeroMemory(&pInfo, sizeof(PRINTER_INFO_2)); pInfo.pPrinterName = printer->actualName.GetBuffer(); pInfo.pPortName = printer->portName.GetBuffer(); pInfo.pDriverName = printer->model.GetBuffer(); pInfo.pPrintProcessor = L"winprint"; pInfo.pLocation = service->location.GetBuffer(); pInfo.Attributes = PRINTER_ATTRIBUTE_NETWORK | PRINTER_ATTRIBUTE_LOCAL; hPrinter = AddPrinter(NULL, 2, (LPBYTE)&pInfo); err = translate_errno( hPrinter, errno_compat(), kUnknownErr ); require_noerr( err, exit ); exit: if ( hPrinter != NULL ) { ClosePrinter(hPrinter); } return err; }
OSStatus InstallNSP( const char *inName, const char *inGUID, const char *inPath ) { OSStatus err; size_t size; WSADATA wsd; WCHAR name[ 256 ]; GUID guid; WCHAR path[ MAX_PATH ]; require_action( inName && ( *inName != '\0' ), exit, err = kParamErr ); require_action( inGUID && ( *inGUID != '\0' ), exit, err = kParamErr ); require_action( inPath && ( *inPath != '\0' ), exit, err = kParamErr ); size = strlen( inName ); require_action( size < sizeof_array( name ), exit, err = kSizeErr ); CharToWCharString( inName, name ); err = StringToGUID( inGUID, &guid ); require_noerr( err, exit ); size = strlen( inPath ); require_action( size < sizeof_array( path ), exit, err = kSizeErr ); CharToWCharString( inPath, path ); err = WSAStartup( MAKEWORD( 2, 2 ), &wsd ); err = translate_errno( err == 0, errno_compat(), WSAEINVAL ); require_noerr( err, exit ); err = WSCInstallNameSpace( name, path, NS_DNS, 1, &guid ); err = translate_errno( err == 0, errno_compat(), WSAEINVAL ); WSACleanup(); require_noerr( err, exit ); if (!gToolQuietMode) { fprintf( stderr, "Installed NSP \"%s\" (%s) at %s\n", inName, inGUID, inPath ); } exit: if( err != kNoErr ) { fprintf( stderr, "### FAILED (%d) to install \"%s\" (%s) Name Space Provider at %s\n", err, inName, inGUID, inPath ); } return( err ); }
unsigned WINAPI CPrinterSetupWizardSheet::InstallDriverThread( LPVOID inParam ) { Printer * printer = (Printer*) inParam; DWORD exitCode = 0; DWORD dwResult; OSStatus err; STARTUPINFO si; PROCESS_INFORMATION pi; BOOL ok; check( printer ); check( m_self ); // // because we're calling endthreadex(), C++ objects won't be cleaned up // correctly. we'll nest the CString 'command' inside a block so // that it's destructor will be invoked. // { CString command; ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); ZeroMemory( &pi, sizeof(pi) ); command.Format(L"rundll32.exe printui.dll,PrintUIEntry /ia /m \"%s\" /f \"%s\"", (LPCTSTR) printer->modelName, (LPCTSTR) printer->infFileName ); ok = CreateProcess(NULL, command.GetBuffer(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); err = translate_errno( ok, errno_compat(), kUnknownErr ); require_noerr( err, exit ); dwResult = WaitForSingleObject( pi.hProcess, INFINITE ); translate_errno( dwResult == WAIT_OBJECT_0, errno_compat(), err = kUnknownErr ); require_noerr( err, exit ); ok = GetExitCodeProcess( pi.hProcess, &exitCode ); err = translate_errno( ok, errno_compat(), kUnknownErr ); require_noerr( err, exit ); } exit: // // Close process and thread handles. // if ( pi.hProcess ) { CloseHandle( pi.hProcess ); } if ( pi.hThread ) { CloseHandle( pi.hThread ); } // // alert the main thread // m_self->PostMessage( WM_PROCESS_EVENT, err, exitCode ); _endthreadex_compat( 0 ); return 0; }
OSStatus CPrinterSetupWizardSheet::InstallPrinterPDLAndLPR(Printer * printer, Service * service, DWORD protocol ) { PRINTER_DEFAULTS printerDefaults = { NULL, NULL, SERVER_ACCESS_ADMINISTER }; DWORD dwStatus; DWORD cbInputData = 100; PBYTE pOutputData = NULL; DWORD cbOutputNeeded = 0; PORT_DATA_1 portData; PRINTER_INFO_2 pInfo; HANDLE hXcv = NULL; HANDLE hPrinter = NULL; Queue * q; BOOL ok; OSStatus err; check(printer != NULL); check(printer->installed == false); q = service->queues.front(); check( q ); ok = OpenPrinter(L",XcvMonitor Standard TCP/IP Port", &hXcv, &printerDefaults); err = translate_errno( ok, errno_compat(), kUnknownErr ); require_noerr( err, exit ); // // BUGBUG: MSDN said this is not required, but my experience shows it is required // try { pOutputData = new BYTE[cbInputData]; } catch (...) { pOutputData = NULL; } require_action( pOutputData, exit, err = kNoMemoryErr ); // // setup the port // ZeroMemory(&portData, sizeof(PORT_DATA_1)); wcscpy(portData.sztPortName, printer->portName); portData.dwPortNumber = service->portNumber; portData.dwVersion = 1; portData.dwProtocol = protocol; portData.cbSize = sizeof PORT_DATA_1; portData.dwReserved = 0L; wcscpy(portData.sztQueue, q->name); wcscpy(portData.sztIPAddress, service->hostname); wcscpy(portData.sztHostAddress, service->hostname); ok = XcvData(hXcv, L"AddPort", (PBYTE) &portData, sizeof(PORT_DATA_1), pOutputData, cbInputData, &cbOutputNeeded, &dwStatus); err = translate_errno( ok, errno_compat(), kUnknownErr ); require_noerr( err, exit ); // // 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( err, exit ); exit: if (hPrinter != NULL) { ClosePrinter(hPrinter); } if (hXcv != NULL) { ClosePrinter(hXcv); } if (pOutputData != NULL) { delete [] pOutputData; } return err; }
OSStatus CPrinterSetupWizardSheet::InstallPrinter(Printer * printer) { Service * service; BOOL ok; OSStatus err; service = printer->services.front(); check( service ); // // if the driver isn't installed, then install it // if ( !printer->driverInstalled ) { DWORD dwResult; HANDLE hThread; unsigned threadID; m_driverThreadFinished = false; // // create the thread // hThread = (HANDLE) _beginthreadex_compat( NULL, 0, InstallDriverThread, printer, 0, &threadID ); err = translate_errno( hThread, (OSStatus) GetLastError(), kUnknownErr ); require_noerr( err, exit ); // // go modal // while (!m_driverThreadFinished) { MSG msg; GetMessage( &msg, m_hWnd, 0, 0 ); TranslateMessage(&msg); DispatchMessage(&msg); } // // Wait until child process exits. // dwResult = WaitForSingleObject( hThread, INFINITE ); err = translate_errno( dwResult == WAIT_OBJECT_0, errno_compat(), err = kUnknownErr ); require_noerr( err, exit ); // // check the return value of thread // require_noerr( m_driverThreadExitCode, exit ); // // now we know that the driver was successfully installed // printer->driverInstalled = true; } if ( service->type == kPDLServiceType ) { err = InstallPrinterPDLAndLPR( printer, service, PROTOCOL_RAWTCP_TYPE ); require_noerr( err, exit ); } else if ( service->type == kLPRServiceType ) { err = InstallPrinterPDLAndLPR( printer, service, PROTOCOL_LPR_TYPE ); require_noerr( err, exit ); } else if ( service->type == kIPPServiceType ) { err = InstallPrinterIPP( printer, service ); require_noerr( err, exit ); } else { err = kUnknownErr; require_noerr( err, exit ); } printer->installed = true; // // if the user specified a default printer, set it // if (printer->deflt) { ok = SetDefaultPrinter( printer->actualName ); err = translate_errno( ok, errno_compat(), err = kUnknownErr ); require_noerr( err, exit ); } exit: return err; }
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; m_psp.dwFlags &= ~(PSP_HASHELP); m_psp.dwFlags |= PSP_DEFAULT|PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE; m_psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_INSTALL_TITLE); m_psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_INSTALL_SUBTITLE); // // load printers from ntprint.inf // ok = GetWindowsDirectory( windowsDirectory, bufferSize ); err = translate_errno( ok, errno_compat(), kUnknownErr ); 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 // err = LoadPrintDriverDefs( m_manufacturers ); require_noerr(err, exit); // // load our own special generic printer defs // err = LoadGenericPrintDriverDefs( m_manufacturers ); require_noerr( err, exit ); exit: return; }
// ------------------------------------------------------- // LoadPrintDriverDefs // // This function is responsible for loading the print driver // definitions of all print drivers that have been installed // on this machine. // ------------------------------------------------------- OSStatus CThirdPage::LoadPrintDriverDefs( Manufacturers & manufacturers ) { BYTE * buffer = NULL; DWORD bytesReceived = 0; DWORD numPrinters = 0; OSStatus err = 0; BOOL ok; // // like a lot of win32 calls, we call this first to get the // size of the buffer we need. // EnumPrinterDrivers(NULL, L"all", 6, NULL, 0, &bytesReceived, &numPrinters); if (bytesReceived > 0) { try { buffer = new BYTE[bytesReceived]; } catch (...) { buffer = NULL; } require_action( buffer, exit, err = kNoMemoryErr ); // // this call gets the real info // ok = EnumPrinterDrivers(NULL, L"all", 6, buffer, bytesReceived, &bytesReceived, &numPrinters); err = translate_errno( ok, errno_compat(), kUnknownErr ); require_noerr( err, exit ); DRIVER_INFO_6 * info = (DRIVER_INFO_6*) buffer; for (DWORD i = 0; i < numPrinters; i++) { Manufacturer * manufacturer; Model * model; CString name; // // skip over anything that doesn't have a manufacturer field. This // 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. // if (info[i].pszMfgName == NULL) { continue; } // // look for manufacturer // Manufacturers::iterator iter; // // save the name // name = NormalizeManufacturerName( info[i].pszMfgName ); iter = manufacturers.find(name); if (iter != manufacturers.end()) { manufacturer = iter->second; } else { try { manufacturer = new Manufacturer; } catch (...) { manufacturer = NULL; } require_action( manufacturer, exit, err = kNoMemoryErr ); manufacturer->name = name; manufacturers[name] = manufacturer; } // // now look to see if we have already seen this guy. this could // happen if we have already installed printers that are described // in ntprint.inf. the extant drivers will show up in EnumPrinterDrivers // but we have already loaded their info // // if ( MatchModel( manufacturer, ConvertToModelName( info[i].pName ) ) == NULL ) { try { model = new Model; } catch (...) { model = NULL; } require_action( model, exit, err = kNoMemoryErr ); model->displayName = info[i].pName; model->name = info[i].pName; model->driverInstalled = true; manufacturer->models.push_back(model); } } } exit: if (buffer != NULL) { delete [] buffer; } return err; }
DEBUG_LOCAL OSStatus ReorderNameSpaces( void ) { OSStatus err; WSADATA wsd; bool started; int n; int i; DWORD size; WSANAMESPACE_INFO * array; WCHAR name[ 256 ]; WCHAR path[ MAX_PATH ]; array = NULL; started = false; err = WSAStartup( MAKEWORD( 2, 2 ), &wsd ); err = translate_errno( err == 0, errno_compat(), WSAEINVAL ); require_noerr( err, exit ); started = true; // Build an array of all the NSPs. Call it first with NULL to get the size, allocate a buffer, then get them into it. size = 0; n = WSAEnumNameSpaceProviders( &size, NULL ); err = translate_errno( n != SOCKET_ERROR, (OSStatus) GetLastError(), kUnknownErr ); require_action( err == WSAEFAULT, exit, err = kUnknownErr ); array = (WSANAMESPACE_INFO *) malloc( size ); require_action( array, exit, err = kNoMemoryErr ); n = WSAEnumNameSpaceProviders( &size, array ); err = translate_errno( n != SOCKET_ERROR, (OSStatus) GetLastError(), kUnknownErr ); require_noerr( err, exit ); // Find the "Tcpip" NSP. for( i = 0; i < n; ++i ) { if( strcmp( array[ i ].lpszIdentifier, "Tcpip" ) == 0 ) { break; } } require_action( i < n, exit, err = kNotFoundErr ); // Uninstall it then re-install it to move it to the end. size = (DWORD) strlen( array[ i ].lpszIdentifier ); require_action( size < sizeof_array( name ), exit, err = kSizeErr ); CharToWCharString( array[ i ].lpszIdentifier, name ); size = (DWORD) strlen( "%SystemRoot%\\System32\\mswsock.dll" ); require_action( size < sizeof_array( path ), exit, err = kSizeErr ); CharToWCharString( "%SystemRoot%\\System32\\mswsock.dll", path ); err = WSCUnInstallNameSpace( &array[ i ].NSProviderId ); err = translate_errno( err == 0, errno_compat(), WSAEINVAL ); require_noerr( err, exit ); err = WSCInstallNameSpace( name, path, NS_DNS, array[ i ].dwVersion, &array[ i ].NSProviderId ); err = translate_errno( err == 0, errno_compat(), WSAEINVAL ); require_noerr( err, exit ); // Success! fprintf( stderr, "Reordered \"Tcpip\" NSP to to the bottom of the NSP chain\n" ); err = kNoErr; exit: if( array ) { free( array ); } if( started ) { WSACleanup(); } if( err != kNoErr ) { fprintf( stderr, "### FAILED (%d) to reorder Name Space Providers\n", err ); } return( err ); }
DEBUG_LOCAL OSStatus ListNameSpaces( void ) { OSStatus err; WSADATA wsd; bool started; int n; int i; DWORD size; WSANAMESPACE_INFO * array; char s[ 256 ]; array = NULL; started = false; err = WSAStartup( MAKEWORD( 2, 2 ), &wsd ); err = translate_errno( err == 0, errno_compat(), WSAEINVAL ); require_noerr( err, exit ); started = true; // Build an array of all the NSPs. Call it first with NULL to get the size, allocate a buffer, then get them into it. size = 0; n = WSAEnumNameSpaceProviders( &size, NULL ); err = translate_errno( n != SOCKET_ERROR, (OSStatus) GetLastError(), kUnknownErr ); require_action( err == WSAEFAULT, exit, err = kUnknownErr ); array = (WSANAMESPACE_INFO *) malloc( size ); require_action( array, exit, err = kNoMemoryErr ); n = WSAEnumNameSpaceProviders( &size, array ); err = translate_errno( n != SOCKET_ERROR, (OSStatus) GetLastError(), kUnknownErr ); require_noerr( err, exit ); fprintf( stdout, "\n" ); for( i = 0; i < n; ++i ) { fprintf( stdout, "Name Space %d\n", i + 1 ); fprintf( stdout, " NSProviderId: %s\n", GUIDtoString( &array[ i ].NSProviderId, sizeof( s ), s ) ); fprintf( stdout, " dwNameSpace: %d\n", array[ i ].dwNameSpace ); fprintf( stdout, " fActive: %s\n", array[ i ].fActive ? "YES" : "NO" ); fprintf( stdout, " dwVersion: %d\n", array[ i ].dwVersion ); fprintf( stdout, " lpszIdentifier: \"%s\"\n", array[ i ].lpszIdentifier ); fprintf( stdout, "\n" ); } err = kNoErr; exit: if( array ) { free( array ); } if( started ) { WSACleanup(); } if( err != kNoErr ) { fprintf( stderr, "### FAILED (%d) to list Name Space Providers\n", err ); } return( err ); }