winspool: Move ppd retrieval to cups.c.

Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Huw Davies 2021-10-26 11:18:11 +01:00 committed by Alexandre Julliard
parent 5a163d5537
commit f519535879
3 changed files with 142 additions and 97 deletions

View File

@ -22,6 +22,9 @@
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#ifdef HAVE_CUPS_CUPS_H
#include <cups/cups.h>
#endif
@ -56,6 +59,11 @@ static DWORD ntdll_umbstowcs( const char *src, DWORD srclen, WCHAR *dst, DWORD d
{
return MultiByteToWideChar( CP_UNIXCP, 0, src, srclen, dst, dstlen );
}
static int ntdll_wcstoumbs( const WCHAR *src, DWORD srclen, char *dst, DWORD dstlen, BOOL strict )
{
/* FIXME: strict */
return WideCharToMultiByte( CP_UNIXCP, 0, src, srclen, dst, dstlen, NULL, NULL );
}
#ifdef SONAME_LIBCUPS
@ -111,6 +119,56 @@ NTSTATUS unix_process_attach( void *arg )
#endif /* SONAME_LIBCUPS */
}
static BOOL copy_file( const char *src, const char *dst )
{
int fds[2] = { -1, -1 }, num;
char buf[1024];
BOOL ret = FALSE;
fds[0] = open( src, O_RDONLY );
fds[1] = open( dst, O_CREAT | O_TRUNC | O_WRONLY, 0666 );
if (fds[0] == -1 || fds[1] == -1) goto fail;
while ((num = read( fds[0], buf, sizeof(buf) )) != 0)
{
if (num == -1) goto fail;
if (write( fds[1], buf, num ) != num) goto fail;
}
ret = TRUE;
fail:
if (fds[1] != -1) close( fds[1] );
if (fds[0] != -1) close( fds[0] );
return ret;
}
static char *get_unix_file_name( LPCWSTR path )
{
UNICODE_STRING nt_name;
OBJECT_ATTRIBUTES attr;
NTSTATUS status;
ULONG size = 256;
char *buffer;
nt_name.Buffer = (WCHAR *)path;
nt_name.MaximumLength = nt_name.Length = lstrlenW( path ) * sizeof(WCHAR);
InitializeObjectAttributes( &attr, &nt_name, 0, 0, NULL );
for (;;)
{
if (!(buffer = malloc( size ))) return NULL;
status = wine_nt_to_unix_file_name( &attr, buffer, &size, FILE_OPEN_IF );
if (status != STATUS_BUFFER_TOO_SMALL) break;
free( buffer );
}
if (status && status != STATUS_NO_SUCH_FILE)
{
free( buffer );
return NULL;
}
return buffer;
}
#ifdef SONAME_LIBCUPS
static WCHAR *cups_get_optionW( const char *opt_name, int num_options, cups_option_t *options )
{
@ -145,6 +203,32 @@ static BOOL cups_is_scanner( cups_dest_t *dest )
{
return cups_get_printer_type( dest ) & 0x2000000 /* CUPS_PRINTER_SCANNER */;
}
static http_status_t cupsGetPPD3_wrapper( http_t *http, const char *name, time_t *modtime,
char *buffer, size_t bufsize )
{
const char *ppd;
if (pcupsGetPPD3) return pcupsGetPPD3( http, name, modtime, buffer, bufsize );
if (!pcupsGetPPD) return HTTP_NOT_FOUND;
TRACE( "No cupsGetPPD3 implementation, so calling cupsGetPPD\n" );
*modtime = 0;
ppd = pcupsGetPPD( name );
TRACE( "cupsGetPPD returns %s\n", debugstr_a(ppd) );
if (!ppd) return HTTP_NOT_FOUND;
if (rename( ppd, buffer ) == -1)
{
BOOL res = copy_file( ppd, buffer );
unlink( ppd );
if (!res) return HTTP_NOT_FOUND;
}
return HTTP_OK;
}
#endif /* SONAME_LIBCUPS */
NTSTATUS unix_enum_printers( void *args )
@ -216,3 +300,44 @@ NTSTATUS unix_enum_printers( void *args )
return STATUS_NOT_SUPPORTED;
#endif /* SONAME_LIBCUPS */
}
NTSTATUS unix_get_ppd( void *args )
{
struct get_ppd_params *params = args;
char *unix_ppd = get_unix_file_name( params->ppd );
NTSTATUS status = STATUS_SUCCESS;
TRACE( "(%s, %s)\n", debugstr_w( params->printer ), debugstr_w( params->ppd ) );
if (!unix_ppd) return STATUS_NO_SUCH_FILE;
if (!params->printer) /* unlink */
{
unlink( unix_ppd );
}
else
{
#ifdef SONAME_LIBCUPS
http_status_t http_status;
time_t modtime = 0;
char *printer_name;
int len;
len = strlenW( params->printer );
printer_name = malloc( len * 3 + 1 );
ntdll_wcstoumbs( params->printer, len + 1, printer_name, len * 3 + 1, FALSE );
http_status = cupsGetPPD3_wrapper( 0, printer_name, &modtime, unix_ppd, strlen( unix_ppd ) + 1 );
if (http_status != HTTP_OK)
{
unlink( unix_ppd );
status = STATUS_DEVICE_UNREACHABLE;
}
free( printer_name );
#else
status = STATUS_NOT_SUPPORTED;
#endif
}
free( unix_ppd );
return status;
}

View File

@ -752,29 +752,6 @@ static DWORD WINSPOOL_GetOpenedPrinterRegKey(HANDLE hPrinter, HKEY *phkey)
return open_printer_reg_key( name, phkey );
}
static BOOL copy_file( const char *src, const char *dst )
{
int fds[2] = {-1, -1}, num;
char buf[1024];
BOOL ret = FALSE;
fds[0] = open( src, O_RDONLY );
fds[1] = open( dst, O_CREAT | O_TRUNC | O_WRONLY, 0666 );
if (fds[0] == -1 || fds[1] == -1) goto fail;
while ((num = read( fds[0], buf, sizeof(buf) )) != 0)
{
if (num == -1) goto fail;
if (write( fds[1], buf, num ) != num) goto fail;
}
ret = TRUE;
fail:
if (fds[1] != -1) close( fds[1] );
if (fds[0] != -1) close( fds[0] );
return ret;
}
static BOOL get_internal_fallback_ppd( const WCHAR *ppd )
{
static const WCHAR typeW[] = {'P','P','D','F','I','L','E',0};
@ -817,31 +794,22 @@ static WCHAR *get_ppd_filename( const WCHAR *dir, const WCHAR *file_name )
return ppd;
}
static char *get_dest_name( const WCHAR *printer )
{
int len = WideCharToMultiByte( CP_UNIXCP, 0, printer, -1, NULL, 0, NULL, NULL );
char *dest = heap_alloc( len );
if (dest) WideCharToMultiByte( CP_UNIXCP, 0, printer, -1, dest, len, NULL, NULL );
return dest;
}
static BOOL get_cups_ppd( const char *printer_name, const WCHAR *ppd );
static void unlink_ppd( const WCHAR *ppd );
static BOOL add_printer_driver( const WCHAR *name, const WCHAR *ppd_dir )
{
WCHAR *ppd = get_ppd_filename( ppd_dir, name );
char *dest_name;
struct get_ppd_params ppd_params;
UNICODE_STRING nt_ppd;
DRIVER_INFO_3W di3;
unsigned int i;
BOOL res = FALSE;
if (!ppd) return FALSE;
dest_name = get_dest_name( name );
if (!dest_name) goto end;
RtlInitUnicodeString( &nt_ppd, NULL );
if (!RtlDosPathNameToNtPathName_U( ppd, &nt_ppd, NULL, NULL )) goto end;
res = get_cups_ppd( dest_name, ppd ) || get_internal_fallback_ppd( ppd );
ppd_params.printer = name;
ppd_params.ppd = nt_ppd.Buffer;
res = !UNIX_CALL( get_ppd, &ppd_params ) || get_internal_fallback_ppd( ppd );
if (!res) goto end;
memset( &di3, 0, sizeof(DRIVER_INFO_3W) );
@ -872,10 +840,11 @@ static BOOL add_printer_driver( const WCHAR *name, const WCHAR *ppd_dir )
}
res = TRUE;
}
unlink_ppd( ppd );
ppd_params.printer = NULL; /* unlink the ppd */
UNIX_CALL( get_ppd, &ppd_params );
end:
heap_free( dest_name );
RtlFreeUnicodeString( &nt_ppd );
heap_free( ppd );
return res;
}
@ -904,13 +873,6 @@ static WCHAR *get_ppd_dir( void )
return dir;
}
static void unlink_ppd( const WCHAR *ppd )
{
char *unix_name = wine_get_unix_file_name( ppd );
unlink( unix_name );
HeapFree( GetProcessHeap(), 0, unix_name );
}
#ifdef SONAME_LIBCUPS
extern void *libcups_handle;
@ -932,56 +894,7 @@ extern void *libcups_handle;
CUPS_FUNCS;
#undef DO_FUNC
extern cups_dest_t * (*pcupsGetNamedDest)(http_t *, const char *, const char *);
extern const char * (*pcupsGetPPD)(const char *);
extern http_status_t (*pcupsGetPPD3)(http_t *, const char *, time_t *, char *, size_t);
extern const char * (*pcupsLastErrorString)(void);
static http_status_t cupsGetPPD3_wrapper( http_t *http, const char *name,
time_t *modtime, char *buffer,
size_t bufsize )
{
const char *ppd;
if (pcupsGetPPD3) return pcupsGetPPD3( http, name, modtime, buffer, bufsize );
if (!pcupsGetPPD) return HTTP_NOT_FOUND;
TRACE( "No cupsGetPPD3 implementation, so calling cupsGetPPD\n" );
*modtime = 0;
ppd = pcupsGetPPD( name );
TRACE( "cupsGetPPD returns %s\n", debugstr_a(ppd) );
if (!ppd) return HTTP_NOT_FOUND;
if (rename( ppd, buffer ) == -1)
{
BOOL res = copy_file( ppd, buffer );
unlink( ppd );
if (!res) return HTTP_NOT_FOUND;
}
return HTTP_OK;
}
static BOOL get_cups_ppd( const char *printer_name, const WCHAR *ppd )
{
time_t modtime = 0;
http_status_t http_status;
char *unix_name = wine_get_unix_file_name( ppd );
TRACE( "(%s, %s)\n", debugstr_a(printer_name), debugstr_w(ppd) );
if (!unix_name) return FALSE;
http_status = cupsGetPPD3_wrapper( 0, printer_name, &modtime,
unix_name, strlen( unix_name ) + 1 );
if (http_status != HTTP_OK) unlink( unix_name );
HeapFree( GetProcessHeap(), 0, unix_name );
return http_status == HTTP_OK;
}
#endif
static BOOL init_unix_printers( void )

View File

@ -52,7 +52,14 @@ struct enum_printers_params
unsigned int num;
};
struct get_ppd_params
{
const WCHAR *printer; /* set to NULL to unlink */
const WCHAR *ppd;
};
#define UNIX_CALL( func, params ) unix_ ## func( params )
NTSTATUS unix_process_attach( void * ) DECLSPEC_HIDDEN;
NTSTATUS unix_enum_printers( void * ) DECLSPEC_HIDDEN;
NTSTATUS unix_get_ppd( void * ) DECLSPEC_HIDDEN;