winspool: Move CUPS printer enumeration to cups.c.
Signed-off-by: Huw Davies <huw@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
9d8bf3bf96
commit
5a163d5537
|
@ -41,11 +41,22 @@
|
|||
#include "winspool.h"
|
||||
#include "ddk/winsplp.h"
|
||||
#include "wine/debug.h"
|
||||
#include "wine/unicode.h"
|
||||
|
||||
#include "wspool.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(winspool);
|
||||
|
||||
/* Temporary helpers until switch to unixlib */
|
||||
#include "winnls.h"
|
||||
#include "wine/heap.h"
|
||||
#define malloc( sz ) heap_alloc( sz )
|
||||
#define free( ptr ) heap_free( ptr )
|
||||
static DWORD ntdll_umbstowcs( const char *src, DWORD srclen, WCHAR *dst, DWORD dstlen )
|
||||
{
|
||||
return MultiByteToWideChar( CP_UNIXCP, 0, src, srclen, dst, dstlen );
|
||||
}
|
||||
|
||||
#ifdef SONAME_LIBCUPS
|
||||
|
||||
void *libcups_handle = NULL;
|
||||
|
@ -99,3 +110,109 @@ NTSTATUS unix_process_attach( void *arg )
|
|||
return STATUS_NOT_SUPPORTED;
|
||||
#endif /* SONAME_LIBCUPS */
|
||||
}
|
||||
|
||||
#ifdef SONAME_LIBCUPS
|
||||
static WCHAR *cups_get_optionW( const char *opt_name, int num_options, cups_option_t *options )
|
||||
{
|
||||
const char *value;
|
||||
WCHAR *ret;
|
||||
int len;
|
||||
|
||||
value = pcupsGetOption( opt_name, num_options, options );
|
||||
if (!value) return NULL;
|
||||
|
||||
len = strlen( value ) + 1;
|
||||
ret = malloc( len * sizeof(WCHAR) );
|
||||
if (ret) ntdll_umbstowcs( value, len, ret, len );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static cups_ptype_t cups_get_printer_type( const cups_dest_t *dest )
|
||||
{
|
||||
const char *value;
|
||||
cups_ptype_t ret;
|
||||
char *end;
|
||||
|
||||
value = pcupsGetOption( "printer-type", dest->num_options, dest->options );
|
||||
if (!value) return 0;
|
||||
ret = (cups_ptype_t)strtoul( value, &end, 10 );
|
||||
if (*end) ret = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL cups_is_scanner( cups_dest_t *dest )
|
||||
{
|
||||
return cups_get_printer_type( dest ) & 0x2000000 /* CUPS_PRINTER_SCANNER */;
|
||||
}
|
||||
#endif /* SONAME_LIBCUPS */
|
||||
|
||||
NTSTATUS unix_enum_printers( void *args )
|
||||
{
|
||||
struct enum_printers_params *params = args;
|
||||
#ifdef SONAME_LIBCUPS
|
||||
unsigned int num, i, name_len, comment_len, location_len, needed;
|
||||
WCHAR *comment, *location, *ptr;
|
||||
struct printer_info *info;
|
||||
cups_dest_t *dests;
|
||||
|
||||
params->num = 0;
|
||||
if (!pcupsGetDests) return STATUS_NOT_SUPPORTED;
|
||||
|
||||
num = pcupsGetDests( &dests );
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
if (cups_is_scanner( dests + i ))
|
||||
{
|
||||
TRACE( "Printer %d: %s - skipping scanner\n", i, debugstr_a( dests[i].name ) );
|
||||
continue;
|
||||
}
|
||||
TRACE( "Printer %d: %s\n", i, debugstr_a( dests[i].name ) );
|
||||
params->num++;
|
||||
}
|
||||
|
||||
needed = sizeof( *info ) * params->num;
|
||||
info = params->printers;
|
||||
ptr = (WCHAR *)(info + params->num);
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
if (cups_is_scanner( dests + i )) continue;
|
||||
|
||||
comment = cups_get_optionW( "printer-info", dests[i].num_options, dests[i].options );
|
||||
location = cups_get_optionW( "printer-location", dests[i].num_options, dests[i].options );
|
||||
|
||||
name_len = strlen( dests[i].name ) + 1;
|
||||
comment_len = comment ? strlenW( comment ) + 1 : 0;
|
||||
location_len = location ? strlenW( location ) + 1 : 0;
|
||||
needed += (name_len + comment_len + location_len) * sizeof(WCHAR);
|
||||
|
||||
if (needed <= params->size)
|
||||
{
|
||||
info->name = ptr;
|
||||
ntdll_umbstowcs( dests[i].name, name_len, info->name, name_len );
|
||||
info->comment = comment ? ptr + name_len : NULL;
|
||||
memcpy( info->comment, comment, comment_len * sizeof(WCHAR) );
|
||||
info->location = location ? ptr + name_len + comment_len : NULL;
|
||||
memcpy( info->location, location, location_len * sizeof(WCHAR) );
|
||||
info->is_default = dests[i].is_default;
|
||||
info++;
|
||||
ptr += name_len + comment_len + location_len;
|
||||
}
|
||||
free( comment );
|
||||
free( location );
|
||||
}
|
||||
pcupsFreeDests( num, dests );
|
||||
|
||||
if (needed > params->size)
|
||||
{
|
||||
params->size = needed;
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
#else
|
||||
params->num = 0;
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
#endif /* SONAME_LIBCUPS */
|
||||
}
|
||||
|
|
|
@ -107,6 +107,8 @@
|
|||
#define NONAMELESSSTRUCT
|
||||
#define NONAMELESSUNION
|
||||
|
||||
#include "ntstatus.h"
|
||||
#define WIN32_NO_STATUS
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winuser.h"
|
||||
|
@ -917,7 +919,6 @@ extern void *libcups_handle;
|
|||
DO_FUNC(cupsAddOption); \
|
||||
DO_FUNC(cupsFreeDests); \
|
||||
DO_FUNC(cupsFreeOptions); \
|
||||
DO_FUNC(cupsGetDests); \
|
||||
DO_FUNC(cupsGetOption); \
|
||||
DO_FUNC(cupsParseOptions); \
|
||||
DO_FUNC(cupsPrintFile)
|
||||
|
@ -981,137 +982,96 @@ static BOOL get_cups_ppd( const char *printer_name, const WCHAR *ppd )
|
|||
|
||||
return http_status == HTTP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
static WCHAR *get_cups_option( const char *name, int num_options, cups_option_t *options )
|
||||
static BOOL init_unix_printers( void )
|
||||
{
|
||||
const char *value;
|
||||
WCHAR *ret;
|
||||
int len;
|
||||
WCHAR *port, *ppd_dir = NULL, *default_printer = NULL;
|
||||
struct enum_printers_params enum_params;
|
||||
HKEY printer_key, printers_key;
|
||||
HANDLE added_printer;
|
||||
PRINTER_INFO_2W pi2;
|
||||
NTSTATUS status;
|
||||
int i;
|
||||
|
||||
value = pcupsGetOption( name, num_options, options );
|
||||
if (!value) return NULL;
|
||||
|
||||
len = MultiByteToWideChar( CP_UNIXCP, 0, value, -1, NULL, 0 );
|
||||
ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
|
||||
if (ret) MultiByteToWideChar( CP_UNIXCP, 0, value, -1, ret, len );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static cups_ptype_t get_cups_printer_type( const cups_dest_t *dest )
|
||||
{
|
||||
WCHAR *type = get_cups_option( "printer-type", dest->num_options, dest->options ), *end;
|
||||
cups_ptype_t ret = 0;
|
||||
|
||||
if (type && *type)
|
||||
if (RegCreateKeyW( HKEY_LOCAL_MACHINE, PrintersW, &printers_key ) != ERROR_SUCCESS)
|
||||
{
|
||||
ret = (cups_ptype_t)strtoulW( type, &end, 10 );
|
||||
if (*end) ret = 0;
|
||||
}
|
||||
HeapFree( GetProcessHeap(), 0, type );
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL CUPS_LoadPrinters(void)
|
||||
{
|
||||
int i, nrofdests;
|
||||
BOOL hadprinter = FALSE, haddefault = FALSE;
|
||||
cups_dest_t *dests;
|
||||
PRINTER_INFO_2W pi2;
|
||||
WCHAR *port, *ppd_dir = NULL;
|
||||
HKEY hkeyPrinter, hkeyPrinters;
|
||||
WCHAR nameW[MAX_PATH];
|
||||
HANDLE added_printer;
|
||||
cups_ptype_t printer_type;
|
||||
|
||||
if (!libcups_handle) return FALSE;
|
||||
|
||||
if(RegCreateKeyW(HKEY_LOCAL_MACHINE, PrintersW, &hkeyPrinters) !=
|
||||
ERROR_SUCCESS) {
|
||||
ERR("Can't create Printers key\n");
|
||||
return FALSE;
|
||||
ERR( "Can't create Printers key\n" );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
nrofdests = pcupsGetDests(&dests);
|
||||
TRACE("Found %d CUPS %s:\n", nrofdests, (nrofdests == 1) ? "printer" : "printers");
|
||||
for (i=0;i<nrofdests;i++) {
|
||||
MultiByteToWideChar(CP_UNIXCP, 0, dests[i].name, -1, nameW, ARRAY_SIZE(nameW));
|
||||
printer_type = get_cups_printer_type( dests + i );
|
||||
enum_params.size = 10000;
|
||||
enum_params.printers = NULL;
|
||||
do
|
||||
{
|
||||
enum_params.size *= 2;
|
||||
heap_free( enum_params.printers );
|
||||
enum_params.printers = heap_alloc( enum_params.size );
|
||||
status = UNIX_CALL( enum_printers, &enum_params );
|
||||
} while (status == STATUS_BUFFER_OVERFLOW);
|
||||
if (status) goto end;
|
||||
|
||||
TRACE( "Printer %d: %s. printer_type %x\n", i, debugstr_w(nameW), printer_type );
|
||||
TRACE( "Found %d CUPS %s:\n", enum_params.num, (enum_params.num == 1) ? "printer" : "printers" );
|
||||
for (i = 0; i < enum_params.num; i++)
|
||||
{
|
||||
struct printer_info *printer = enum_params.printers + i;
|
||||
|
||||
if (printer_type & 0x2000000 /* CUPS_PRINTER_SCANNER */)
|
||||
if (RegOpenKeyW( printers_key, printer->name, &printer_key ) == ERROR_SUCCESS)
|
||||
{
|
||||
TRACE( "skipping scanner-only device\n" );
|
||||
continue;
|
||||
}
|
||||
|
||||
if (RegOpenKeyW( hkeyPrinters, nameW, &hkeyPrinter ) == ERROR_SUCCESS)
|
||||
{
|
||||
DWORD status = get_dword_from_reg( hkeyPrinter, StatusW );
|
||||
DWORD status = get_dword_from_reg( printer_key, StatusW );
|
||||
/* Printer already in registry, delete the tag added in WINSPOOL_LoadSystemPrinters
|
||||
and continue */
|
||||
TRACE("Printer already exists\n");
|
||||
RegDeleteValueW(hkeyPrinter, May_Delete_Value);
|
||||
RegDeleteValueW( printer_key, May_Delete_Value );
|
||||
/* flag that the PPD file should be checked for an update */
|
||||
set_reg_DWORD( hkeyPrinter, StatusW, status | PRINTER_STATUS_DRIVER_UPDATE_NEEDED );
|
||||
RegCloseKey(hkeyPrinter);
|
||||
set_reg_DWORD( printer_key, StatusW, status | PRINTER_STATUS_DRIVER_UPDATE_NEEDED );
|
||||
RegCloseKey( printer_key );
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ppd_dir && !(ppd_dir = get_ppd_dir())) break;
|
||||
if (!add_printer_driver( nameW, ppd_dir )) continue;
|
||||
if (!add_printer_driver( printer->name, ppd_dir )) continue;
|
||||
|
||||
port = heap_alloc( sizeof(CUPS_Port) + lstrlenW( nameW ) * sizeof(WCHAR) );
|
||||
port = heap_alloc( sizeof(CUPS_Port) + lstrlenW( printer->name ) * sizeof(WCHAR) );
|
||||
lstrcpyW( port, CUPS_Port );
|
||||
lstrcatW( port, nameW );
|
||||
lstrcatW( port, printer->name );
|
||||
|
||||
memset(&pi2, 0, sizeof(PRINTER_INFO_2W));
|
||||
pi2.pPrinterName = nameW;
|
||||
memset( &pi2, 0, sizeof(PRINTER_INFO_2W) );
|
||||
pi2.pPrinterName = printer->name;
|
||||
pi2.pDatatype = rawW;
|
||||
pi2.pPrintProcessor = WinPrintW;
|
||||
pi2.pDriverName = nameW;
|
||||
pi2.pComment = get_cups_option( "printer-info", dests[i].num_options, dests[i].options );
|
||||
pi2.pLocation = get_cups_option( "printer-location", dests[i].num_options, dests[i].options );
|
||||
pi2.pDriverName = printer->name;
|
||||
pi2.pComment = printer->comment;
|
||||
pi2.pLocation = printer->location;
|
||||
pi2.pPortName = port;
|
||||
pi2.pParameters = emptyStringW;
|
||||
pi2.pShareName = emptyStringW;
|
||||
pi2.pSepFile = emptyStringW;
|
||||
|
||||
added_printer = AddPrinterW( NULL, 2, (LPBYTE)&pi2 );
|
||||
added_printer = AddPrinterW( NULL, 2, (BYTE *)&pi2 );
|
||||
if (added_printer) ClosePrinter( added_printer );
|
||||
else if (GetLastError() != ERROR_PRINTER_ALREADY_EXISTS)
|
||||
ERR( "printer '%s' not added by AddPrinter (error %d)\n", debugstr_w(nameW), GetLastError() );
|
||||
ERR( "printer '%s' not added by AddPrinter (error %d)\n", debugstr_w( printer->name ), GetLastError() );
|
||||
|
||||
heap_free( port );
|
||||
HeapFree( GetProcessHeap(), 0, pi2.pComment );
|
||||
HeapFree( GetProcessHeap(), 0, pi2.pLocation );
|
||||
}
|
||||
|
||||
hadprinter = TRUE;
|
||||
if (dests[i].is_default) {
|
||||
SetDefaultPrinterW(nameW);
|
||||
haddefault = TRUE;
|
||||
}
|
||||
if (printer->is_default) default_printer = printer->name;
|
||||
}
|
||||
|
||||
if (!default_printer && enum_params.num) default_printer = enum_params.printers[0].name;
|
||||
if (default_printer) SetDefaultPrinterW( default_printer );
|
||||
|
||||
if (ppd_dir)
|
||||
{
|
||||
RemoveDirectoryW( ppd_dir );
|
||||
HeapFree( GetProcessHeap(), 0, ppd_dir );
|
||||
heap_free( ppd_dir );
|
||||
}
|
||||
|
||||
if (hadprinter && !haddefault) {
|
||||
MultiByteToWideChar(CP_UNIXCP, 0, dests[0].name, -1, nameW, ARRAY_SIZE(nameW));
|
||||
SetDefaultPrinterW(nameW);
|
||||
}
|
||||
pcupsFreeDests(nrofdests, dests);
|
||||
RegCloseKey(hkeyPrinters);
|
||||
end:
|
||||
heap_free( enum_params.printers );
|
||||
RegCloseKey( printers_key );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void set_ppd_overrides( HANDLE printer )
|
||||
{
|
||||
WCHAR *wstr = NULL;
|
||||
|
@ -1493,11 +1453,7 @@ void WINSPOOL_LoadSystemPrinters(void)
|
|||
}
|
||||
|
||||
old_printer_check( FALSE );
|
||||
|
||||
#ifdef SONAME_LIBCUPS
|
||||
CUPS_LoadPrinters();
|
||||
#endif
|
||||
|
||||
init_unix_printers();
|
||||
old_printer_check( TRUE );
|
||||
|
||||
ReleaseMutex( init_mutex );
|
||||
|
|
|
@ -37,6 +37,22 @@ extern void WINSPOOL_LoadSystemPrinters(void) DECLSPEC_HIDDEN;
|
|||
#define FILENAME_DIALOG 100
|
||||
#define EDITBOX 201
|
||||
|
||||
struct printer_info
|
||||
{
|
||||
WCHAR *name;
|
||||
WCHAR *comment;
|
||||
WCHAR *location;
|
||||
BOOL is_default;
|
||||
};
|
||||
|
||||
struct enum_printers_params
|
||||
{
|
||||
struct printer_info *printers;
|
||||
unsigned int size;
|
||||
unsigned int num;
|
||||
};
|
||||
|
||||
#define UNIX_CALL( func, params ) unix_ ## func( params )
|
||||
|
||||
NTSTATUS unix_process_attach( void * ) DECLSPEC_HIDDEN;
|
||||
NTSTATUS unix_enum_printers( void * ) DECLSPEC_HIDDEN;
|
||||
|
|
Loading…
Reference in New Issue