/*++ Copyright (c) 1996 Microsoft Corporation Module Name: printer.c Abstract: This file implements the printer/spooler code. Environment: WIN32 User Mode Author: Wesley Witt (wesw) 17-Feb-1996 --*/ #include "wizard.h" #pragma hdrstop TCHAR Environment[MAX_PATH]; TCHAR DataFile[MAX_PATH]; TCHAR ConfigFile[MAX_PATH]; TCHAR DriverFile[MAX_PATH]; TCHAR MonitorFile[MAX_PATH]; TCHAR PrinterName[MAX_PATH]; TCHAR DriverDirectory[MAX_PATH]; DRIVER_INFO_2 DriverInfo = { 2, // cVersion FAX_DRIVER_NAME, // pName Environment, // pEnvironment DriverFile, // pDriverPath DataFile, // pDataFile ConfigFile // pConfigFile }; PRINTER_INFO_2 PrinterInfo = { NULL, // pServerName PrinterName, // pPrinterName NULL, // pShareName NULL, // pPortName FAX_DRIVER_NAME, // pDriverName NULL, // pComment NULL, // pLocation NULL, // pDevMode NULL, // pSepFile TEXT("winprint"), // pPrintProcessor TEXT("RAW"), // pDatatype NULL, // pParameters NULL, // pSecurityDescriptor 0, // Attributes 0, // Priority 0, // DefaultPriority 0, // StartTime 0, // UntilTime 0, // Status 0, // cJobs 0 // AveragePPM }; MONITOR_INFO_2 MonitorInfo = { FAX_MONITOR_NAME, // pName Environment, // pEnvironment MonitorFile // pDLLName }; BOOL AddPrinterDrivers( VOID ) { DWORD i; DWORD BytesNeeded; for (i=0; i 3) || (EnumPlatforms[SystemInfo.wProcessorArchitecture] == WRONG_PLATFORM ) ) { return FALSE; } _tcscpy( Environment, Platforms[ EnumPlatforms[SystemInfo.wProcessorArchitecture] ].PrintPlatform ); _tcscpy( MonitorFile, TEXT("faxmon.dll") ); if ((!AddMonitor( NULL, 2, (LPBYTE) &MonitorInfo )) && (GetLastError() != ERROR_PRINT_MONITOR_ALREADY_INSTALLED)) { DebugPrint(( TEXT("AddMonitor() failed, ec=%d"), GetLastError() )); return FALSE; } // // enumerate the ports so we can isolate the fax ports // if ((!EnumPorts( NULL, 2, NULL, 0, &BytesNeeded, &PortCount )) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) { PortInfo = (PORT_INFO_2 *) MemAlloc( BytesNeeded ); if (PortInfo) { if (EnumPorts( NULL, 2, (LPBYTE)PortInfo, BytesNeeded, &BytesNeeded, &PortCount )) { for (BytesNeeded=0,i=0; i 3) || (EnumPlatforms[SystemInfo.wProcessorArchitecture] == WRONG_PLATFORM)) { return ERROR_INVALID_FUNCTION; } _tcscpy( Environment, Platforms[ EnumPlatforms[SystemInfo.wProcessorArchitecture] ].PrintPlatform ); if (!GetPrinterDriverDirectory( NULL, Environment, 1, (LPBYTE) DriverDirectory, sizeof(DriverDirectory), &i )) { ec = GetLastError(); DebugPrint(( TEXT("GetPrinterDriverDirectory() failed, ec=%d"), ec )); return ec; } // // form the file names // _tcscpy( DriverFile, DriverDirectory ); _tcscat( DriverFile, TEXT("\\faxdrv.dll") ); _tcscpy( DataFile, DriverDirectory ); _tcscat( DataFile, TEXT("\\faxwiz.dll") ); _tcscpy( ConfigFile, DriverDirectory ); _tcscat( ConfigFile, TEXT("\\faxui.dll") ); if ((!AddPrinterDriver( NULL, 2, (LPBYTE) &DriverInfo )) && (GetLastError() != ERROR_PRINTER_DRIVER_ALREADY_INSTALLED)) { ec = GetLastError(); DebugPrint(( TEXT("AddPrinterDriver() failed, ec=%d"), GetLastError() )); return ec; } // // add the printer // add_printer_connection: if (!AddPrinterConnection( FaxPrinterName )) { i = GetLastError(); if (i == ERROR_INVALID_PRINTER_NAME) { int DlgErr = DialogBoxParam( FaxWizModuleHandle, MAKEINTRESOURCE(IDD_PRINTER_NAME), hwnd, PrinterNameDlgProc, (LPARAM) FaxPrinterName ); if (DlgErr == -1 || DlgErr == 0) { DebugPrint(( TEXT("PrinterNameDlgProc() failed or was cancelled") )); return ERROR_INVALID_FUNCTION; } if (!AddPrinterConnection( FaxPrinterName )) { DebugPrint(( TEXT("AddPrinterConnection() failed, ec=%d"), i )); goto add_printer_connection; } } else { DebugPrint(( TEXT("AddPrinterConnection() failed, ec=%d"), i )); return i; } } // // make the fax printer the default printer, if it is the only printer // SetDefaultPrinter( FaxPrinterName, FALSE); return ERROR_SUCCESS; } BOOL IsPrinterFaxPrinter( LPTSTR PrinterName ) { HANDLE hPrinter = NULL; PRINTER_DEFAULTS PrinterDefaults; SYSTEM_INFO SystemInfo; DWORD Size; DWORD Rval = FALSE; LPDRIVER_INFO_2 DriverInfo = NULL; PrinterDefaults.pDatatype = NULL; PrinterDefaults.pDevMode = NULL; PrinterDefaults.DesiredAccess = PRINTER_READ; if (!OpenPrinter( PrinterName, &hPrinter, &PrinterDefaults )) { DebugPrint(( TEXT("OpenPrinter() failed, ec=%d"), GetLastError() )); return FALSE; } GetSystemInfo( &SystemInfo ); Size = 4096; DriverInfo = (LPDRIVER_INFO_2) MemAlloc( Size ); if (!DriverInfo) { DebugPrint(( TEXT("Memory allocation failed, size=%d"), Size )); goto exit; } if ( (SystemInfo.wProcessorArchitecture > 3) || (EnumPlatforms[SystemInfo.wProcessorArchitecture] == WRONG_PLATFORM ) ) { return FALSE; } Rval = GetPrinterDriver( hPrinter, Platforms[ EnumPlatforms[SystemInfo.wProcessorArchitecture] ].PrintPlatform, 2, (LPBYTE) DriverInfo, Size, &Size ); if (!Rval) { DebugPrint(( TEXT("GetPrinterDriver() failed, ec=%d"), GetLastError() )); goto exit; } if (_tcscmp( DriverInfo->pName, FAX_DRIVER_NAME ) == 0) { Rval = TRUE; } else { Rval = FALSE; } exit: MemFree( DriverInfo ); ClosePrinter( hPrinter ); return Rval; } LPTSTR MakePrinterShareName( LPTSTR pServerName, LPTSTR pPrinterName ) /*++ Routine Description: Given a server name and a printer name, generate a unique share name. Arguments: pServerName - Specifies the server name, NULL for local host pPrinterName - Specifies the printer name Return Value: Pointer to the generated share name, NULL if there is an error --*/ { static TCHAR illegalDosChars[] = TEXT( " *?/\\|,;:+=<>[]\"" ); TCHAR shareName[16]; INT cch, shareSuffix; DWORD dwFlags, cPrinters, index; LPTSTR pDest, pShareName; PPRINTER_INFO_2 pPrinterInfo2; // // Copy up to the first 8 characters of the printer name // ZeroMemory( shareName, sizeof(shareName) ); pDest = shareName; cch = 0; while (cch < 8 && *pPrinterName) { // // Skip invalid DOS filename characters // if (!_tcschr( illegalDosChars, *pPrinterName )) { *pDest++ = *pPrinterName; cch++; } pPrinterName++; } // // If the share name is empty, start with a default. // This should very rarely happen. // if (cch == 0) { _tcscpy( shareName, GetString( IDS_DEFAULT_SHARE ) ); pDest += _tcslen(pDest); } // // Get the list of shared printers on the server. // Be aware that share names returned by EnumPrinters // may be in the form of \\servername\sharename. // dwFlags = PRINTER_ENUM_SHARED | (pServerName ? PRINTER_ENUM_NAME : PRINTER_ENUM_LOCAL); if (! (pPrinterInfo2 = MyEnumPrinters( pServerName, 2, &cPrinters, dwFlags ))) { cPrinters = 0; } for (index = 0; index < cPrinters; index++) { if (pPrinterInfo2[index].pShareName && (pShareName = _tcsrchr(pPrinterInfo2[index].pShareName, TEXT('\\')))) { pPrinterInfo2[index].pShareName = pShareName + 1; } } // // Make sure the share name is unique. If not, add a numeric suffix to it. // for (shareSuffix = 0; shareSuffix < 1000; shareSuffix++) { if (shareSuffix > 0) { *pDest = TEXT('.'); wsprintf( pDest + 1, TEXT("%d"), shareSuffix ); } // // Check if the proposed share name matches any of the existing share names. // for (index = 0; index < cPrinters; index++) { if (pPrinterInfo2[index].pShareName && _tcsicmp(pPrinterInfo2[index].pShareName, shareName) == 0) { break; } } // // Stop searching when we find a unique share name. // if (index >= cPrinters) { break; } } MemFree( pPrinterInfo2 ); return (shareSuffix < 1000) ? StringDup( shareName ) : NULL; } BOOL ShareFaxPrinter( LPHANDLE hPrinter, LPTSTR FaxPrinterName ) { DWORD i; DWORD Size; TCHAR String[4]; HANDLE hPrinterServer; LPPRINTER_INFO_2 PrinterInfo = NULL; PRINTER_DEFAULTS PrinterDefaults; BOOL Rval = FALSE; LPTSTR ShareName; ShareName = MakePrinterShareName( NULL, FaxPrinterName ); if (!ShareName) { return FALSE; } if ((!GetPrinter( *hPrinter, 2, NULL, 0, &i )) && (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) { DebugPrint(( TEXT("GetPrinter() failed, ec=%d"), GetLastError() )); goto exit; } PrinterInfo = (LPPRINTER_INFO_2) MemAlloc( i ); if (!PrinterInfo) { DebugPrint(( TEXT("MemAlloc() failed, size=%d"), i )); goto exit; } if (!GetPrinter( *hPrinter, 2, (LPBYTE) PrinterInfo, i, &i )) { DebugPrint(( TEXT("GetPrinter() failed, ec=%d"), GetLastError() )); goto exit; } PrinterInfo->pShareName = ShareName; PrinterInfo->Attributes |= PRINTER_ATTRIBUTE_SHARED; PrinterInfo->pComment = GetString( IDS_FAX_SHARE_COMMENT ); if (!SetPrinter( *hPrinter, 2, (LPBYTE) PrinterInfo, 0 )) { DebugPrint(( TEXT("SetPrinter() failed, ec=%d"), GetLastError() )); goto exit; } // // allow the printer to have remote connections // PrinterDefaults.pDatatype = NULL; PrinterDefaults.pDevMode = NULL; PrinterDefaults.DesiredAccess = SERVER_ACCESS_ADMINISTER; if (!OpenPrinter( NULL, &hPrinterServer, &PrinterDefaults )) { DebugPrint(( TEXT("OpenPrinter() failed, ec=%d"), GetLastError() )); goto exit; } // // remove the fax driver from the list of driver names // String[0] = 0; Size = sizeof(TCHAR); i = SetPrinterData( hPrinterServer, SPLREG_NO_REMOTE_PRINTER_DRIVERS, REG_SZ, (LPBYTE) String, Size ); if ((i != ERROR_SUCCESS) && (i != ERROR_SUCCESS_RESTART_REQUIRED)) { DebugPrint(( TEXT("SetPrinterData() failed, ec=%d"), i )); goto exit; } // // we have to restart the spooler for the // SetPrinterData() to take affect // ClosePrinter( *hPrinter ); PrinterDefaults.pDatatype = NULL; PrinterDefaults.pDevMode = NULL; PrinterDefaults.DesiredAccess = PRINTER_ALL_ACCESS; if (!OpenPrinter( FaxPrinterName, hPrinter, &PrinterDefaults )) { DebugPrint(( TEXT("OpenPrinter() failed, ec=%d"), GetLastError() )); goto exit; } Rval = TRUE; exit: MemFree( PrinterInfo ); MemFree( ShareName ); ClosePrinter( hPrinterServer ); return Rval; } BOOL DeleteFaxPrinters( HWND hwnd ) { PPRINTER_INFO_2 PrinterInfo; PMONITOR_INFO_2 MonitorInfo; DWORD Count; HANDLE hPrinter; PRINTER_DEFAULTS PrinterDefaults; DWORD i,j; LPTSTR FileName = NULL; PDRIVER_INFO_2 DriverInfo; PDRIVER_INFO_2 DriverInfoDel; TCHAR Buffer[MAX_PATH]; PrinterInfo = MyEnumPrinters( NULL, 2, &Count, 0 ); if (!PrinterInfo) { return FALSE; } PrinterDefaults.pDatatype = NULL; PrinterDefaults.pDevMode = NULL; PrinterDefaults.DesiredAccess = PRINTER_ALL_ACCESS; for (i=0; ipDriverPath ); MyDeleteFile( DriverInfoDel->pDataFile ); MyDeleteFile( DriverInfoDel->pConfigFile ); } if (DriverInfo) { MemFree( DriverInfo ); } } return TRUE; } PVOID MyEnumPrinters( LPTSTR pServerName, DWORD level, PDWORD pcPrinters, DWORD Flags ) { PBYTE pPrinterInfo = NULL; DWORD cb; if (!Flags) { Flags = PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS; } if (!EnumPrinters(Flags, pServerName, level, NULL, 0, &cb, pcPrinters) && GetLastError() == ERROR_INSUFFICIENT_BUFFER && (pPrinterInfo = MemAlloc(cb)) && EnumPrinters(Flags, pServerName, level, pPrinterInfo, cb, &cb, pcPrinters)) { return pPrinterInfo; } MemFree(pPrinterInfo); return NULL; } PVOID MyEnumDrivers( LPTSTR pEnvironment, PDWORD pcDrivers ) { PBYTE pDriverInfo = NULL; DWORD cb; if (!EnumPrinterDrivers(NULL, pEnvironment, 2, 0, 0, &cb, pcDrivers ) && GetLastError() == ERROR_INSUFFICIENT_BUFFER && (pDriverInfo = MemAlloc(cb)) && EnumPrinterDrivers(NULL, pEnvironment, 2, pDriverInfo, cb, &cb, pcDrivers )) { return pDriverInfo; } MemFree(pDriverInfo); return NULL; } PVOID MyEnumMonitors( PDWORD pcMonitors ) { PBYTE pMonitorInfo = NULL; DWORD cb; if (!EnumMonitors(NULL, 2, 0, 0, &cb, pcMonitors ) && GetLastError() == ERROR_INSUFFICIENT_BUFFER && (pMonitorInfo = MemAlloc(cb)) && EnumMonitors(NULL, 2, pMonitorInfo, cb, &cb, pcMonitors )) { return pMonitorInfo; } MemFree(pMonitorInfo); return NULL; }