kernelbase: Reimplement LOCALE_*CTRYNAME in GetLocaleInfoW/Ex using the locale.nls...
[wine.git] / dlls / winspool.drv / cups.c
blob766f5c9bb0918296c65324caed0dea80c1b5babc
1 /*
2 * CUPS functions
4 * Copyright 2021 Huw Davies
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #if 0
21 #pragma makedep unix
22 #endif
24 #include "config.h"
26 #include <stdarg.h>
27 #include <string.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <sys/types.h>
31 #include <unistd.h>
32 #include <dlfcn.h>
33 #include <fcntl.h>
34 #include <errno.h>
35 #include <signal.h>
36 #include <sys/wait.h>
37 #ifdef HAVE_CUPS_CUPS_H
38 #include <cups/cups.h>
39 #endif
40 #ifdef HAVE_CUPS_PPD_H
41 #include <cups/ppd.h>
42 #endif
44 #ifdef HAVE_APPLICATIONSERVICES_APPLICATIONSERVICES_H
45 #define GetCurrentProcess GetCurrentProcess_Mac
46 #define GetCurrentThread GetCurrentThread_Mac
47 #define LoadResource LoadResource_Mac
48 #define AnimatePalette AnimatePalette_Mac
49 #define EqualRgn EqualRgn_Mac
50 #define FillRgn FillRgn_Mac
51 #define FrameRgn FrameRgn_Mac
52 #define GetPixel GetPixel_Mac
53 #define InvertRgn InvertRgn_Mac
54 #define LineTo LineTo_Mac
55 #define OffsetRgn OffsetRgn_Mac
56 #define PaintRgn PaintRgn_Mac
57 #define Polygon Polygon_Mac
58 #define ResizePalette ResizePalette_Mac
59 #define SetRectRgn SetRectRgn_Mac
60 #define EqualRect EqualRect_Mac
61 #define FillRect FillRect_Mac
62 #define FrameRect FrameRect_Mac
63 #define GetCursor GetCursor_Mac
64 #define InvertRect InvertRect_Mac
65 #define OffsetRect OffsetRect_Mac
66 #define PtInRect PtInRect_Mac
67 #define SetCursor SetCursor_Mac
68 #define SetRect SetRect_Mac
69 #define ShowCursor ShowCursor_Mac
70 #define UnionRect UnionRect_Mac
71 #include <ApplicationServices/ApplicationServices.h>
72 #undef GetCurrentProcess
73 #undef GetCurrentThread
74 #undef LoadResource
75 #undef AnimatePalette
76 #undef EqualRgn
77 #undef FillRgn
78 #undef FrameRgn
79 #undef GetPixel
80 #undef InvertRgn
81 #undef LineTo
82 #undef OffsetRgn
83 #undef PaintRgn
84 #undef Polygon
85 #undef ResizePalette
86 #undef SetRectRgn
87 #undef EqualRect
88 #undef FillRect
89 #undef FrameRect
90 #undef GetCursor
91 #undef InvertRect
92 #undef OffsetRect
93 #undef PtInRect
94 #undef SetCursor
95 #undef SetRect
96 #undef ShowCursor
97 #undef UnionRect
98 #endif
100 #include "ntstatus.h"
101 #define WIN32_NO_STATUS
102 #include "windef.h"
103 #include "winbase.h"
104 #include "winternl.h"
105 #include "winuser.h"
106 #include "winerror.h"
107 #include "winreg.h"
108 #include "wingdi.h"
109 #include "winspool.h"
110 #include "ddk/winsplp.h"
111 #include "wine/debug.h"
112 #include "wine/unixlib.h"
114 #include "wspool.h"
116 WINE_DEFAULT_DEBUG_CHANNEL(winspool);
118 static const WCHAR CUPS_Port[] = { 'C','U','P','S',':',0 };
119 static const WCHAR LPR_Port[] = { 'L','P','R',':',0 };
121 #ifdef SONAME_LIBCUPS
123 static void *libcups_handle;
125 #define CUPS_FUNCS \
126 DO_FUNC(cupsAddOption); \
127 DO_FUNC(cupsFreeDests); \
128 DO_FUNC(cupsFreeOptions); \
129 DO_FUNC(cupsGetDests); \
130 DO_FUNC(cupsGetOption); \
131 DO_FUNC(cupsParseOptions); \
132 DO_FUNC(cupsPrintFile)
133 #define CUPS_OPT_FUNCS \
134 DO_FUNC(cupsGetNamedDest); \
135 DO_FUNC(cupsGetPPD); \
136 DO_FUNC(cupsGetPPD3); \
137 DO_FUNC(cupsLastErrorString)
139 #define DO_FUNC(f) static typeof(f) *p##f
140 CUPS_FUNCS;
141 #undef DO_FUNC
142 static cups_dest_t * (*pcupsGetNamedDest)(http_t *, const char *, const char *);
143 static const char * (*pcupsGetPPD)(const char *);
144 static http_status_t (*pcupsGetPPD3)(http_t *, const char *, time_t *, char *, size_t);
145 static const char * (*pcupsLastErrorString)(void);
147 #endif /* SONAME_LIBCUPS */
149 static NTSTATUS process_attach( void *args )
151 #ifdef SONAME_LIBCUPS
152 libcups_handle = dlopen( SONAME_LIBCUPS, RTLD_NOW );
153 TRACE( "%p: %s loaded\n", libcups_handle, SONAME_LIBCUPS );
154 if (!libcups_handle) return STATUS_DLL_NOT_FOUND;
156 #define DO_FUNC(x) \
157 p##x = dlsym( libcups_handle, #x ); \
158 if (!p##x) \
160 ERR( "failed to load symbol %s\n", #x ); \
161 libcups_handle = NULL; \
162 return STATUS_ENTRYPOINT_NOT_FOUND; \
164 CUPS_FUNCS;
165 #undef DO_FUNC
166 #define DO_FUNC(x) p##x = dlsym( libcups_handle, #x )
167 CUPS_OPT_FUNCS;
168 #undef DO_FUNC
169 return STATUS_SUCCESS;
170 #else /* SONAME_LIBCUPS */
171 return STATUS_NOT_SUPPORTED;
172 #endif /* SONAME_LIBCUPS */
175 static BOOL copy_file( const char *src, const char *dst )
177 int fds[2] = { -1, -1 }, num;
178 char buf[1024];
179 BOOL ret = FALSE;
181 fds[0] = open( src, O_RDONLY );
182 fds[1] = open( dst, O_CREAT | O_TRUNC | O_WRONLY, 0666 );
183 if (fds[0] == -1 || fds[1] == -1) goto fail;
185 while ((num = read( fds[0], buf, sizeof(buf) )) != 0)
187 if (num == -1) goto fail;
188 if (write( fds[1], buf, num ) != num) goto fail;
190 ret = TRUE;
192 fail:
193 if (fds[1] != -1) close( fds[1] );
194 if (fds[0] != -1) close( fds[0] );
195 return ret;
198 static char *get_unix_file_name( LPCWSTR path )
200 UNICODE_STRING nt_name;
201 OBJECT_ATTRIBUTES attr;
202 NTSTATUS status;
203 ULONG size = 256;
204 char *buffer;
206 nt_name.Buffer = (WCHAR *)path;
207 nt_name.MaximumLength = nt_name.Length = wcslen( path ) * sizeof(WCHAR);
208 InitializeObjectAttributes( &attr, &nt_name, 0, 0, NULL );
209 for (;;)
211 if (!(buffer = malloc( size ))) return NULL;
212 status = wine_nt_to_unix_file_name( &attr, buffer, &size, FILE_OPEN_IF );
213 if (status != STATUS_BUFFER_TOO_SMALL) break;
214 free( buffer );
216 if (status && status != STATUS_NO_SUCH_FILE)
218 free( buffer );
219 return NULL;
221 return buffer;
225 #ifdef SONAME_LIBCUPS
226 static WCHAR *cups_get_optionW( const char *opt_name, int num_options, cups_option_t *options )
228 const char *value;
229 WCHAR *ret;
230 int len;
232 value = pcupsGetOption( opt_name, num_options, options );
233 if (!value) return NULL;
235 len = strlen( value ) + 1;
236 ret = malloc( len * sizeof(WCHAR) );
237 if (ret) ntdll_umbstowcs( value, len, ret, len );
239 return ret;
242 static cups_ptype_t cups_get_printer_type( const cups_dest_t *dest )
244 const char *value;
245 cups_ptype_t ret;
246 char *end;
248 value = pcupsGetOption( "printer-type", dest->num_options, dest->options );
249 if (!value) return 0;
250 ret = (cups_ptype_t)strtoul( value, &end, 10 );
251 if (*end) ret = 0;
252 return ret;
255 static BOOL cups_is_scanner( cups_dest_t *dest )
257 return cups_get_printer_type( dest ) & 0x2000000 /* CUPS_PRINTER_SCANNER */;
260 static http_status_t cupsGetPPD3_wrapper( http_t *http, const char *name, time_t *modtime,
261 char *buffer, size_t bufsize )
263 const char *ppd;
265 if (pcupsGetPPD3) return pcupsGetPPD3( http, name, modtime, buffer, bufsize );
266 if (!pcupsGetPPD) return HTTP_NOT_FOUND;
268 TRACE( "No cupsGetPPD3 implementation, so calling cupsGetPPD\n" );
270 *modtime = 0;
271 ppd = pcupsGetPPD( name );
273 TRACE( "cupsGetPPD returns %s\n", debugstr_a(ppd) );
275 if (!ppd) return HTTP_NOT_FOUND;
277 if (rename( ppd, buffer ) == -1)
279 BOOL res = copy_file( ppd, buffer );
280 unlink( ppd );
281 if (!res) return HTTP_NOT_FOUND;
283 return HTTP_OK;
286 /*****************************************************************************
287 * get_cups_jobs_ticket_options
289 * Explicitly set CUPS options based on any %cupsJobTicket lines.
290 * The CUPS scheduler only looks for these in Print-File requests, and since
291 * cupsPrintFile uses Create-Job / Send-Document, the ticket lines don't get
292 * parsed.
294 static int get_cups_job_ticket_options( const char *file, int num_options, cups_option_t **options )
296 FILE *fp = fopen( file, "r" );
297 char buf[257]; /* DSC max of 256 + '\0' */
298 const char *ps_adobe = "%!PS-Adobe-";
299 const char *cups_job = "%cupsJobTicket:";
301 if (!fp) return num_options;
302 if (!fgets( buf, sizeof(buf), fp )) goto end;
303 if (strncmp( buf, ps_adobe, strlen( ps_adobe ) )) goto end;
304 while (fgets( buf, sizeof(buf), fp ))
306 if (strncmp( buf, cups_job, strlen( cups_job ) )) break;
307 num_options = pcupsParseOptions( buf + strlen( cups_job ), num_options, options );
310 end:
311 fclose( fp );
312 return num_options;
315 static int get_cups_default_options( const char *printer, int num_options, cups_option_t **options )
317 cups_dest_t *dest;
318 int i;
320 if (!pcupsGetNamedDest) return num_options;
322 dest = pcupsGetNamedDest( NULL, printer, NULL );
323 if (!dest) return num_options;
325 for (i = 0; i < dest->num_options; i++)
327 if (!pcupsGetOption( dest->options[i].name, num_options, *options ))
328 num_options = pcupsAddOption( dest->options[i].name, dest->options[i].value,
329 num_options, options );
332 pcupsFreeDests( 1, dest );
333 return num_options;
335 #endif /* SONAME_LIBCUPS */
337 static NTSTATUS enum_printers( void *args )
339 const struct enum_printers_params *params = args;
340 #ifdef SONAME_LIBCUPS
341 unsigned int num, i, name_len, comment_len, location_len, needed;
342 WCHAR *comment, *location, *ptr;
343 struct printer_info *info;
344 cups_dest_t *dests;
346 *params->num = 0;
347 if (!pcupsGetDests) return STATUS_NOT_SUPPORTED;
349 num = pcupsGetDests( &dests );
351 for (i = 0; i < num; i++)
353 if (cups_is_scanner( dests + i ))
355 TRACE( "Printer %d: %s - skipping scanner\n", i, debugstr_a( dests[i].name ) );
356 continue;
358 TRACE( "Printer %d: %s\n", i, debugstr_a( dests[i].name ) );
359 (*params->num)++;
362 needed = sizeof( *info ) * *params->num;
363 info = params->printers;
364 ptr = (WCHAR *)(info + *params->num);
366 for (i = 0; i < num; i++)
368 if (cups_is_scanner( dests + i )) continue;
370 comment = cups_get_optionW( "printer-info", dests[i].num_options, dests[i].options );
371 location = cups_get_optionW( "printer-location", dests[i].num_options, dests[i].options );
373 name_len = strlen( dests[i].name ) + 1;
374 comment_len = comment ? wcslen( comment ) + 1 : 0;
375 location_len = location ? wcslen( location ) + 1 : 0;
376 needed += (name_len + comment_len + location_len) * sizeof(WCHAR);
378 if (needed <= *params->size)
380 info->name = ptr;
381 ntdll_umbstowcs( dests[i].name, name_len, info->name, name_len );
382 info->comment = comment ? ptr + name_len : NULL;
383 memcpy( info->comment, comment, comment_len * sizeof(WCHAR) );
384 info->location = location ? ptr + name_len + comment_len : NULL;
385 memcpy( info->location, location, location_len * sizeof(WCHAR) );
386 info->is_default = dests[i].is_default;
387 info++;
388 ptr += name_len + comment_len + location_len;
390 free( comment );
391 free( location );
393 pcupsFreeDests( num, dests );
395 if (needed > *params->size)
397 *params->size = needed;
398 return STATUS_BUFFER_OVERFLOW;
400 return STATUS_SUCCESS;
401 #else
402 *params->num = 0;
403 return STATUS_NOT_SUPPORTED;
404 #endif /* SONAME_LIBCUPS */
407 static NTSTATUS get_ppd( void *args )
409 const struct get_ppd_params *params = args;
410 char *unix_ppd = get_unix_file_name( params->ppd );
411 NTSTATUS status = STATUS_SUCCESS;
413 TRACE( "(%s, %s)\n", debugstr_w( params->printer ), debugstr_w( params->ppd ) );
415 if (!unix_ppd) return STATUS_NO_SUCH_FILE;
417 if (!params->printer) /* unlink */
419 unlink( unix_ppd );
421 else
423 #ifdef SONAME_LIBCUPS
424 http_status_t http_status;
425 time_t modtime = 0;
426 char *printer_name;
427 int len;
429 len = wcslen( params->printer );
430 printer_name = malloc( len * 3 + 1 );
431 ntdll_wcstoumbs( params->printer, len + 1, printer_name, len * 3 + 1, FALSE );
433 http_status = cupsGetPPD3_wrapper( 0, printer_name, &modtime, unix_ppd, strlen( unix_ppd ) + 1 );
434 if (http_status != HTTP_OK)
436 unlink( unix_ppd );
437 status = STATUS_DEVICE_UNREACHABLE;
439 free( printer_name );
440 #else
441 status = STATUS_NOT_SUPPORTED;
442 #endif
444 free( unix_ppd );
445 return status;
448 static NTSTATUS get_default_page_size( void *args )
450 #ifdef HAVE_APPLICATIONSERVICES_APPLICATIONSERVICES_H
451 const struct get_default_page_size_params *params = args;
452 NTSTATUS status = STATUS_UNSUCCESSFUL;
453 PMPrintSession session = NULL;
454 PMPageFormat format = NULL;
455 CFStringRef paper_name;
456 PMPaper paper;
457 CFRange range;
458 int size;
460 if (PMCreateSession( &session )) goto end;
461 if (PMCreatePageFormat( &format )) goto end;
462 if (PMSessionDefaultPageFormat( session, format )) goto end;
463 if (PMGetPageFormatPaper( format, &paper )) goto end;
464 if (PMPaperGetPPDPaperName( paper, &paper_name )) goto end;
466 range.location = 0;
467 range.length = CFStringGetLength( paper_name );
468 size = (range.length + 1) * sizeof(WCHAR);
470 if (*params->name_size >= size)
472 CFStringGetCharacters( paper_name, range, (UniChar*)params->name );
473 params->name[range.length] = 0;
474 status = STATUS_SUCCESS;
476 else
477 status = STATUS_BUFFER_OVERFLOW;
478 *params->name_size = size;
480 end:
481 if (format) PMRelease( format );
482 if (session) PMRelease( session );
483 return status;
484 #else
485 return STATUS_NOT_IMPLEMENTED;
486 #endif
489 /*****************************************************************************
490 * schedule_pipe
492 static BOOL schedule_pipe( const WCHAR *cmd, const WCHAR *filename )
494 char *unixname, *cmdA;
495 DWORD len;
496 int fds[2] = { -1, -1 }, file_fd = -1, no_read;
497 BOOL ret = FALSE;
498 char buf[1024];
499 pid_t pid, wret;
500 int status;
502 if (!(unixname = get_unix_file_name( filename ))) return FALSE;
504 len = wcslen( cmd );
505 cmdA = malloc( len * 3 + 1);
506 ntdll_wcstoumbs( cmd, len + 1, cmdA, len * 3 + 1, FALSE );
508 TRACE( "printing with: %s\n", cmdA );
510 if ((file_fd = open( unixname, O_RDONLY )) == -1) goto end;
512 if (pipe( fds ))
514 ERR( "pipe() failed!\n" );
515 goto end;
518 if ((pid = fork()) == 0)
520 close( 0 );
521 dup2( fds[0], 0 );
522 close( fds[1] );
524 /* reset signals that we previously set to SIG_IGN */
525 signal( SIGPIPE, SIG_DFL );
527 execl( "/bin/sh", "/bin/sh", "-c", cmdA, NULL );
528 _exit( 1 );
530 else if (pid == -1)
532 ERR( "fork() failed!\n" );
533 goto end;
536 close( fds[0] );
537 fds[0] = -1;
538 while ((no_read = read( file_fd, buf, sizeof(buf) )) > 0)
539 write( fds[1], buf, no_read );
541 close( fds[1] );
542 fds[1] = -1;
544 /* reap child */
545 do {
546 wret = waitpid( pid, &status, 0 );
547 } while (wret < 0 && errno == EINTR);
548 if (wret < 0)
550 ERR( "waitpid() failed!\n" );
551 goto end;
553 if (!WIFEXITED(status) || WEXITSTATUS(status))
555 ERR( "child process failed! %d\n", status );
556 goto end;
559 ret = TRUE;
561 end:
562 if (file_fd != -1) close( file_fd );
563 if (fds[0] != -1) close( fds[0] );
564 if (fds[1] != -1) close( fds[1] );
566 free( cmdA );
567 free( unixname );
568 return ret;
571 /*****************************************************************************
572 * schedule_unixfile
574 static BOOL schedule_unixfile( const WCHAR *output, const WCHAR *filename )
576 char *unixname, *outputA;
577 DWORD len;
578 BOOL ret;
580 if (!(unixname = get_unix_file_name( filename ))) return FALSE;
582 len = wcslen( output );
583 outputA = malloc( len * 3 + 1);
584 ntdll_wcstoumbs( output, len + 1, outputA, len * 3 + 1, FALSE );
586 ret = copy_file( unixname, outputA );
588 free( outputA );
589 free( unixname );
590 return ret;
593 /*****************************************************************************
594 * schedule_lpr
596 static BOOL schedule_lpr( const WCHAR *printer_name, const WCHAR *filename )
598 static const WCHAR lpr[] = { 'l','p','r',' ','-','P','\'' };
599 static const WCHAR quote[] = { '\'',0 };
600 int printer_len = wcslen( printer_name );
601 WCHAR *cmd;
602 BOOL ret;
604 cmd = malloc( printer_len * sizeof(WCHAR) + sizeof(lpr) + sizeof(quote) );
605 memcpy( cmd, lpr, sizeof(lpr) );
606 memcpy( cmd + ARRAY_SIZE(lpr), printer_name, printer_len * sizeof(WCHAR) );
607 memcpy( cmd + ARRAY_SIZE(lpr) + printer_len, quote, sizeof(quote) );
609 ret = schedule_pipe( cmd, filename );
611 free( cmd );
612 return ret;
615 /*****************************************************************************
616 * schedule_cups
618 static BOOL schedule_cups( const WCHAR *printer_name, const WCHAR *filename, const WCHAR *document_title )
620 #ifdef SONAME_LIBCUPS
621 if (pcupsPrintFile)
623 char *unixname, *queue, *unix_doc_title;
624 cups_option_t *options = NULL;
625 int num_options = 0, i;
626 DWORD len;
627 BOOL ret;
629 if (!(unixname = get_unix_file_name( filename ))) return FALSE;
630 len = wcslen( printer_name );
631 queue = malloc( len * 3 + 1);
632 ntdll_wcstoumbs( printer_name, len + 1, queue, len * 3 + 1, FALSE );
634 len = wcslen( document_title );
635 unix_doc_title = malloc( len * 3 + 1 );
636 ntdll_wcstoumbs( document_title, len + 1, unix_doc_title, len + 3 + 1, FALSE );
638 num_options = get_cups_job_ticket_options( unixname, num_options, &options );
639 num_options = get_cups_default_options( queue, num_options, &options );
641 TRACE( "printing via cups with options:\n" );
642 for (i = 0; i < num_options; i++)
643 TRACE( "\t%d: %s = %s\n", i, options[i].name, options[i].value );
645 ret = pcupsPrintFile( queue, unixname, unix_doc_title, num_options, options );
646 if (ret == 0 && pcupsLastErrorString)
647 WARN( "cupsPrintFile failed with error %s\n", debugstr_a( pcupsLastErrorString() ) );
649 pcupsFreeOptions( num_options, options );
651 free( unix_doc_title );
652 free( queue );
653 free( unixname );
654 return ret;
656 else
657 #endif
659 return schedule_lpr( printer_name, filename );
663 static NTSTATUS schedule_job( void *args )
665 const struct schedule_job_params *params = args;
667 if (params->wine_port[0] == '|')
668 return schedule_pipe( params->wine_port + 1, params->filename );
670 if (params->wine_port[0])
671 return schedule_unixfile( params->wine_port, params->filename );
673 if (!wcsncmp( params->port, LPR_Port, ARRAY_SIZE(LPR_Port) - 1 ))
674 return schedule_lpr( params->port + ARRAY_SIZE(LPR_Port) - 1, params->filename );
676 if (!wcsncmp( params->port, CUPS_Port, ARRAY_SIZE(CUPS_Port) - 1 ))
677 return schedule_cups( params->port + ARRAY_SIZE(CUPS_Port) - 1, params->filename, params->document_title );
679 return FALSE;
682 const unixlib_entry_t __wine_unix_call_funcs[] =
684 process_attach,
685 enum_printers,
686 get_default_page_size,
687 get_ppd,
688 schedule_job,
691 #ifdef _WIN64
693 typedef ULONG PTR32;
695 struct printer_info32
697 PTR32 name;
698 PTR32 comment;
699 PTR32 location;
700 BOOL is_default;
703 static NTSTATUS wow64_enum_printers( void *args )
705 struct
707 PTR32 printers;
708 PTR32 size;
709 PTR32 num;
710 } const *params32 = args;
712 NTSTATUS status;
713 unsigned int i;
714 struct enum_printers_params params =
716 ULongToPtr( params32->printers ),
717 ULongToPtr( params32->size ),
718 ULongToPtr( params32->num )
721 if (!(status = enum_printers( &params )))
723 /* convert structures in place */
724 struct printer_info *info = ULongToPtr( params32->printers );
725 struct printer_info32 *info32 = (struct printer_info32 *)info;
726 unsigned int num = *(unsigned int *)ULongToPtr( params32->num );
728 for (i = 0; i < num; i++)
730 info32[i].name = PtrToUlong(info[i].name);
731 info32[i].comment = PtrToUlong(info[i].comment);
732 info32[i].location = PtrToUlong(info[i].location);
733 info32[i].is_default = info[i].is_default;
736 return status;
739 static NTSTATUS wow64_get_default_page_size( void *args )
741 struct
743 PTR32 name;
744 PTR32 name_size;
745 } const *params32 = args;
747 struct get_default_page_size_params params =
749 ULongToPtr( params32->name ),
750 ULongToPtr( params32->name_size )
753 return get_default_page_size( &params );
756 static NTSTATUS wow64_get_ppd( void *args )
758 struct
760 PTR32 printer;
761 PTR32 ppd;
762 } const *params32 = args;
764 struct get_ppd_params params =
766 ULongToPtr( params32->printer ),
767 ULongToPtr( params32->ppd )
770 return get_ppd( &params );
773 static NTSTATUS wow64_schedule_job( void *args )
775 struct
777 PTR32 filename;
778 PTR32 port;
779 PTR32 document_title;
780 PTR32 wine_port;
781 } const *params32 = args;
783 struct schedule_job_params params =
785 ULongToPtr( params32->filename ),
786 ULongToPtr( params32->port ),
787 ULongToPtr( params32->document_title ),
788 ULongToPtr( params32->wine_port )
791 return schedule_job( &params );
794 const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
796 process_attach,
797 wow64_enum_printers,
798 wow64_get_default_page_size,
799 wow64_get_ppd,
800 wow64_schedule_job,
803 #endif /* _WIN64 */