winemac.drv: Remove workarounds for Mac OS X 10.6 and earlier.
[wine.git] / dlls / winspool.drv / cups.c
blob830f0c91332e62f5abc57b9c8a299519c63df8df
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/unicode.h"
113 #include "wine/unixlib.h"
115 #include "wspool.h"
117 WINE_DEFAULT_DEBUG_CHANNEL(winspool);
119 static const WCHAR CUPS_Port[] = { 'C','U','P','S',':',0 };
120 static const WCHAR LPR_Port[] = { 'L','P','R',':',0 };
122 #ifdef SONAME_LIBCUPS
124 static void *libcups_handle;
126 #define CUPS_FUNCS \
127 DO_FUNC(cupsAddOption); \
128 DO_FUNC(cupsFreeDests); \
129 DO_FUNC(cupsFreeOptions); \
130 DO_FUNC(cupsGetDests); \
131 DO_FUNC(cupsGetOption); \
132 DO_FUNC(cupsParseOptions); \
133 DO_FUNC(cupsPrintFile)
134 #define CUPS_OPT_FUNCS \
135 DO_FUNC(cupsGetNamedDest); \
136 DO_FUNC(cupsGetPPD); \
137 DO_FUNC(cupsGetPPD3); \
138 DO_FUNC(cupsLastErrorString)
140 #define DO_FUNC(f) static typeof(f) *p##f
141 CUPS_FUNCS;
142 #undef DO_FUNC
143 static cups_dest_t * (*pcupsGetNamedDest)(http_t *, const char *, const char *);
144 static const char * (*pcupsGetPPD)(const char *);
145 static http_status_t (*pcupsGetPPD3)(http_t *, const char *, time_t *, char *, size_t);
146 static const char * (*pcupsLastErrorString)(void);
148 #endif /* SONAME_LIBCUPS */
150 static NTSTATUS process_attach( void *args )
152 #ifdef SONAME_LIBCUPS
153 libcups_handle = dlopen( SONAME_LIBCUPS, RTLD_NOW );
154 TRACE( "%p: %s loaded\n", libcups_handle, SONAME_LIBCUPS );
155 if (!libcups_handle) return STATUS_DLL_NOT_FOUND;
157 #define DO_FUNC(x) \
158 p##x = dlsym( libcups_handle, #x ); \
159 if (!p##x) \
161 ERR( "failed to load symbol %s\n", #x ); \
162 libcups_handle = NULL; \
163 return STATUS_ENTRYPOINT_NOT_FOUND; \
165 CUPS_FUNCS;
166 #undef DO_FUNC
167 #define DO_FUNC(x) p##x = dlsym( libcups_handle, #x )
168 CUPS_OPT_FUNCS;
169 #undef DO_FUNC
170 return STATUS_SUCCESS;
171 #else /* SONAME_LIBCUPS */
172 return STATUS_NOT_SUPPORTED;
173 #endif /* SONAME_LIBCUPS */
176 static BOOL copy_file( const char *src, const char *dst )
178 int fds[2] = { -1, -1 }, num;
179 char buf[1024];
180 BOOL ret = FALSE;
182 fds[0] = open( src, O_RDONLY );
183 fds[1] = open( dst, O_CREAT | O_TRUNC | O_WRONLY, 0666 );
184 if (fds[0] == -1 || fds[1] == -1) goto fail;
186 while ((num = read( fds[0], buf, sizeof(buf) )) != 0)
188 if (num == -1) goto fail;
189 if (write( fds[1], buf, num ) != num) goto fail;
191 ret = TRUE;
193 fail:
194 if (fds[1] != -1) close( fds[1] );
195 if (fds[0] != -1) close( fds[0] );
196 return ret;
199 static char *get_unix_file_name( LPCWSTR path )
201 UNICODE_STRING nt_name;
202 OBJECT_ATTRIBUTES attr;
203 NTSTATUS status;
204 ULONG size = 256;
205 char *buffer;
207 nt_name.Buffer = (WCHAR *)path;
208 nt_name.MaximumLength = nt_name.Length = lstrlenW( path ) * sizeof(WCHAR);
209 InitializeObjectAttributes( &attr, &nt_name, 0, 0, NULL );
210 for (;;)
212 if (!(buffer = malloc( size ))) return NULL;
213 status = wine_nt_to_unix_file_name( &attr, buffer, &size, FILE_OPEN_IF );
214 if (status != STATUS_BUFFER_TOO_SMALL) break;
215 free( buffer );
217 if (status && status != STATUS_NO_SUCH_FILE)
219 free( buffer );
220 return NULL;
222 return buffer;
226 #ifdef SONAME_LIBCUPS
227 static WCHAR *cups_get_optionW( const char *opt_name, int num_options, cups_option_t *options )
229 const char *value;
230 WCHAR *ret;
231 int len;
233 value = pcupsGetOption( opt_name, num_options, options );
234 if (!value) return NULL;
236 len = strlen( value ) + 1;
237 ret = malloc( len * sizeof(WCHAR) );
238 if (ret) ntdll_umbstowcs( value, len, ret, len );
240 return ret;
243 static cups_ptype_t cups_get_printer_type( const cups_dest_t *dest )
245 const char *value;
246 cups_ptype_t ret;
247 char *end;
249 value = pcupsGetOption( "printer-type", dest->num_options, dest->options );
250 if (!value) return 0;
251 ret = (cups_ptype_t)strtoul( value, &end, 10 );
252 if (*end) ret = 0;
253 return ret;
256 static BOOL cups_is_scanner( cups_dest_t *dest )
258 return cups_get_printer_type( dest ) & 0x2000000 /* CUPS_PRINTER_SCANNER */;
261 static http_status_t cupsGetPPD3_wrapper( http_t *http, const char *name, time_t *modtime,
262 char *buffer, size_t bufsize )
264 const char *ppd;
266 if (pcupsGetPPD3) return pcupsGetPPD3( http, name, modtime, buffer, bufsize );
267 if (!pcupsGetPPD) return HTTP_NOT_FOUND;
269 TRACE( "No cupsGetPPD3 implementation, so calling cupsGetPPD\n" );
271 *modtime = 0;
272 ppd = pcupsGetPPD( name );
274 TRACE( "cupsGetPPD returns %s\n", debugstr_a(ppd) );
276 if (!ppd) return HTTP_NOT_FOUND;
278 if (rename( ppd, buffer ) == -1)
280 BOOL res = copy_file( ppd, buffer );
281 unlink( ppd );
282 if (!res) return HTTP_NOT_FOUND;
284 return HTTP_OK;
287 /*****************************************************************************
288 * get_cups_jobs_ticket_options
290 * Explicitly set CUPS options based on any %cupsJobTicket lines.
291 * The CUPS scheduler only looks for these in Print-File requests, and since
292 * cupsPrintFile uses Create-Job / Send-Document, the ticket lines don't get
293 * parsed.
295 static int get_cups_job_ticket_options( const char *file, int num_options, cups_option_t **options )
297 FILE *fp = fopen( file, "r" );
298 char buf[257]; /* DSC max of 256 + '\0' */
299 const char *ps_adobe = "%!PS-Adobe-";
300 const char *cups_job = "%cupsJobTicket:";
302 if (!fp) return num_options;
303 if (!fgets( buf, sizeof(buf), fp )) goto end;
304 if (strncmp( buf, ps_adobe, strlen( ps_adobe ) )) goto end;
305 while (fgets( buf, sizeof(buf), fp ))
307 if (strncmp( buf, cups_job, strlen( cups_job ) )) break;
308 num_options = pcupsParseOptions( buf + strlen( cups_job ), num_options, options );
311 end:
312 fclose( fp );
313 return num_options;
316 static int get_cups_default_options( const char *printer, int num_options, cups_option_t **options )
318 cups_dest_t *dest;
319 int i;
321 if (!pcupsGetNamedDest) return num_options;
323 dest = pcupsGetNamedDest( NULL, printer, NULL );
324 if (!dest) return num_options;
326 for (i = 0; i < dest->num_options; i++)
328 if (!pcupsGetOption( dest->options[i].name, num_options, *options ))
329 num_options = pcupsAddOption( dest->options[i].name, dest->options[i].value,
330 num_options, options );
333 pcupsFreeDests( 1, dest );
334 return num_options;
336 #endif /* SONAME_LIBCUPS */
338 static NTSTATUS enum_printers( void *args )
340 const struct enum_printers_params *params = args;
341 #ifdef SONAME_LIBCUPS
342 unsigned int num, i, name_len, comment_len, location_len, needed;
343 WCHAR *comment, *location, *ptr;
344 struct printer_info *info;
345 cups_dest_t *dests;
347 *params->num = 0;
348 if (!pcupsGetDests) return STATUS_NOT_SUPPORTED;
350 num = pcupsGetDests( &dests );
352 for (i = 0; i < num; i++)
354 if (cups_is_scanner( dests + i ))
356 TRACE( "Printer %d: %s - skipping scanner\n", i, debugstr_a( dests[i].name ) );
357 continue;
359 TRACE( "Printer %d: %s\n", i, debugstr_a( dests[i].name ) );
360 (*params->num)++;
363 needed = sizeof( *info ) * *params->num;
364 info = params->printers;
365 ptr = (WCHAR *)(info + *params->num);
367 for (i = 0; i < num; i++)
369 if (cups_is_scanner( dests + i )) continue;
371 comment = cups_get_optionW( "printer-info", dests[i].num_options, dests[i].options );
372 location = cups_get_optionW( "printer-location", dests[i].num_options, dests[i].options );
374 name_len = strlen( dests[i].name ) + 1;
375 comment_len = comment ? strlenW( comment ) + 1 : 0;
376 location_len = location ? strlenW( location ) + 1 : 0;
377 needed += (name_len + comment_len + location_len) * sizeof(WCHAR);
379 if (needed <= *params->size)
381 info->name = ptr;
382 ntdll_umbstowcs( dests[i].name, name_len, info->name, name_len );
383 info->comment = comment ? ptr + name_len : NULL;
384 memcpy( info->comment, comment, comment_len * sizeof(WCHAR) );
385 info->location = location ? ptr + name_len + comment_len : NULL;
386 memcpy( info->location, location, location_len * sizeof(WCHAR) );
387 info->is_default = dests[i].is_default;
388 info++;
389 ptr += name_len + comment_len + location_len;
391 free( comment );
392 free( location );
394 pcupsFreeDests( num, dests );
396 if (needed > *params->size)
398 *params->size = needed;
399 return STATUS_BUFFER_OVERFLOW;
401 return STATUS_SUCCESS;
402 #else
403 *params->num = 0;
404 return STATUS_NOT_SUPPORTED;
405 #endif /* SONAME_LIBCUPS */
408 static NTSTATUS get_ppd( void *args )
410 const struct get_ppd_params *params = args;
411 char *unix_ppd = get_unix_file_name( params->ppd );
412 NTSTATUS status = STATUS_SUCCESS;
414 TRACE( "(%s, %s)\n", debugstr_w( params->printer ), debugstr_w( params->ppd ) );
416 if (!unix_ppd) return STATUS_NO_SUCH_FILE;
418 if (!params->printer) /* unlink */
420 unlink( unix_ppd );
422 else
424 #ifdef SONAME_LIBCUPS
425 http_status_t http_status;
426 time_t modtime = 0;
427 char *printer_name;
428 int len;
430 len = strlenW( params->printer );
431 printer_name = malloc( len * 3 + 1 );
432 ntdll_wcstoumbs( params->printer, len + 1, printer_name, len * 3 + 1, FALSE );
434 http_status = cupsGetPPD3_wrapper( 0, printer_name, &modtime, unix_ppd, strlen( unix_ppd ) + 1 );
435 if (http_status != HTTP_OK)
437 unlink( unix_ppd );
438 status = STATUS_DEVICE_UNREACHABLE;
440 free( printer_name );
441 #else
442 status = STATUS_NOT_SUPPORTED;
443 #endif
445 free( unix_ppd );
446 return status;
449 static NTSTATUS get_default_page_size( void *args )
451 #ifdef HAVE_APPLICATIONSERVICES_APPLICATIONSERVICES_H
452 const struct get_default_page_size_params *params = args;
453 NTSTATUS status = STATUS_UNSUCCESSFUL;
454 PMPrintSession session = NULL;
455 PMPageFormat format = NULL;
456 CFStringRef paper_name;
457 PMPaper paper;
458 CFRange range;
459 int size;
461 if (PMCreateSession( &session )) goto end;
462 if (PMCreatePageFormat( &format )) goto end;
463 if (PMSessionDefaultPageFormat( session, format )) goto end;
464 if (PMGetPageFormatPaper( format, &paper )) goto end;
465 if (PMPaperGetPPDPaperName( paper, &paper_name )) goto end;
467 range.location = 0;
468 range.length = CFStringGetLength( paper_name );
469 size = (range.length + 1) * sizeof(WCHAR);
471 if (*params->name_size >= size)
473 CFStringGetCharacters( paper_name, range, (UniChar*)params->name );
474 params->name[range.length] = 0;
475 status = STATUS_SUCCESS;
477 else
478 status = STATUS_BUFFER_OVERFLOW;
479 *params->name_size = size;
481 end:
482 if (format) PMRelease( format );
483 if (session) PMRelease( session );
484 return status;
485 #else
486 return STATUS_NOT_IMPLEMENTED;
487 #endif
490 /*****************************************************************************
491 * schedule_pipe
493 static BOOL schedule_pipe( const WCHAR *cmd, const WCHAR *filename )
495 char *unixname, *cmdA;
496 DWORD len;
497 int fds[2] = { -1, -1 }, file_fd = -1, no_read;
498 BOOL ret = FALSE;
499 char buf[1024];
500 pid_t pid, wret;
501 int status;
503 if (!(unixname = get_unix_file_name( filename ))) return FALSE;
505 len = strlenW( cmd );
506 cmdA = malloc( len * 3 + 1);
507 ntdll_wcstoumbs( cmd, len + 1, cmdA, len * 3 + 1, FALSE );
509 TRACE( "printing with: %s\n", cmdA );
511 if ((file_fd = open( unixname, O_RDONLY )) == -1) goto end;
513 if (pipe( fds ))
515 ERR( "pipe() failed!\n" );
516 goto end;
519 if ((pid = fork()) == 0)
521 close( 0 );
522 dup2( fds[0], 0 );
523 close( fds[1] );
525 /* reset signals that we previously set to SIG_IGN */
526 signal( SIGPIPE, SIG_DFL );
528 execl( "/bin/sh", "/bin/sh", "-c", cmdA, NULL );
529 _exit( 1 );
531 else if (pid == -1)
533 ERR( "fork() failed!\n" );
534 goto end;
537 close( fds[0] );
538 fds[0] = -1;
539 while ((no_read = read( file_fd, buf, sizeof(buf) )) > 0)
540 write( fds[1], buf, no_read );
542 close( fds[1] );
543 fds[1] = -1;
545 /* reap child */
546 do {
547 wret = waitpid( pid, &status, 0 );
548 } while (wret < 0 && errno == EINTR);
549 if (wret < 0)
551 ERR( "waitpid() failed!\n" );
552 goto end;
554 if (!WIFEXITED(status) || WEXITSTATUS(status))
556 ERR( "child process failed! %d\n", status );
557 goto end;
560 ret = TRUE;
562 end:
563 if (file_fd != -1) close( file_fd );
564 if (fds[0] != -1) close( fds[0] );
565 if (fds[1] != -1) close( fds[1] );
567 free( cmdA );
568 free( unixname );
569 return ret;
572 /*****************************************************************************
573 * schedule_unixfile
575 static BOOL schedule_unixfile( const WCHAR *output, const WCHAR *filename )
577 char *unixname, *outputA;
578 DWORD len;
579 BOOL ret;
581 if (!(unixname = get_unix_file_name( filename ))) return FALSE;
583 len = strlenW( output );
584 outputA = malloc( len * 3 + 1);
585 ntdll_wcstoumbs( output, len + 1, outputA, len * 3 + 1, FALSE );
587 ret = copy_file( unixname, outputA );
589 free( outputA );
590 free( unixname );
591 return ret;
594 /*****************************************************************************
595 * schedule_lpr
597 static BOOL schedule_lpr( const WCHAR *printer_name, const WCHAR *filename )
599 static const WCHAR lpr[] = { 'l','p','r',' ','-','P','\'' };
600 static const WCHAR quote[] = { '\'',0 };
601 int printer_len = strlenW( printer_name );
602 WCHAR *cmd;
603 BOOL ret;
605 cmd = malloc( printer_len * sizeof(WCHAR) + sizeof(lpr) + sizeof(quote) );
606 memcpy( cmd, lpr, sizeof(lpr) );
607 memcpy( cmd + ARRAY_SIZE(lpr), printer_name, printer_len * sizeof(WCHAR) );
608 memcpy( cmd + ARRAY_SIZE(lpr) + printer_len, quote, sizeof(quote) );
610 ret = schedule_pipe( cmd, filename );
612 free( cmd );
613 return ret;
616 /*****************************************************************************
617 * schedule_cups
619 static BOOL schedule_cups( const WCHAR *printer_name, const WCHAR *filename, const WCHAR *document_title )
621 #ifdef SONAME_LIBCUPS
622 if (pcupsPrintFile)
624 char *unixname, *queue, *unix_doc_title;
625 cups_option_t *options = NULL;
626 int num_options = 0, i;
627 DWORD len;
628 BOOL ret;
630 if (!(unixname = get_unix_file_name( filename ))) return FALSE;
631 len = strlenW( printer_name );
632 queue = malloc( len * 3 + 1);
633 ntdll_wcstoumbs( printer_name, len + 1, queue, len * 3 + 1, FALSE );
635 len = strlenW( document_title );
636 unix_doc_title = malloc( len * 3 + 1 );
637 ntdll_wcstoumbs( document_title, len + 1, unix_doc_title, len + 3 + 1, FALSE );
639 num_options = get_cups_job_ticket_options( unixname, num_options, &options );
640 num_options = get_cups_default_options( queue, num_options, &options );
642 TRACE( "printing via cups with options:\n" );
643 for (i = 0; i < num_options; i++)
644 TRACE( "\t%d: %s = %s\n", i, options[i].name, options[i].value );
646 ret = pcupsPrintFile( queue, unixname, unix_doc_title, num_options, options );
647 if (ret == 0 && pcupsLastErrorString)
648 WARN( "cupsPrintFile failed with error %s\n", debugstr_a( pcupsLastErrorString() ) );
650 pcupsFreeOptions( num_options, options );
652 free( unix_doc_title );
653 free( queue );
654 free( unixname );
655 return ret;
657 else
658 #endif
660 return schedule_lpr( printer_name, filename );
664 static NTSTATUS schedule_job( void *args )
666 const struct schedule_job_params *params = args;
668 if (params->wine_port[0] == '|')
669 return schedule_pipe( params->wine_port + 1, params->filename );
671 if (params->wine_port[0])
672 return schedule_unixfile( params->wine_port, params->filename );
674 if (!strncmpW( params->port, LPR_Port, ARRAY_SIZE(LPR_Port) - 1 ))
675 return schedule_lpr( params->port + ARRAY_SIZE(LPR_Port) - 1, params->filename );
677 if (!strncmpW( params->port, CUPS_Port, ARRAY_SIZE(CUPS_Port) - 1 ))
678 return schedule_cups( params->port + ARRAY_SIZE(CUPS_Port) - 1, params->filename, params->document_title );
680 return FALSE;
683 const unixlib_entry_t __wine_unix_call_funcs[] =
685 process_attach,
686 enum_printers,
687 get_default_page_size,
688 get_ppd,
689 schedule_job,
692 #ifdef _WIN64
694 typedef ULONG PTR32;
696 struct printer_info32
698 PTR32 name;
699 PTR32 comment;
700 PTR32 location;
701 BOOL is_default;
704 static NTSTATUS wow64_enum_printers( void *args )
706 struct
708 PTR32 printers;
709 PTR32 size;
710 PTR32 num;
711 } const *params32 = args;
713 NTSTATUS status;
714 unsigned int i;
715 struct enum_printers_params params =
717 ULongToPtr( params32->printers ),
718 ULongToPtr( params32->size ),
719 ULongToPtr( params32->num )
722 if (!(status = enum_printers( &params )))
724 /* convert structures in place */
725 struct printer_info *info = ULongToPtr( params32->printers );
726 struct printer_info32 *info32 = (struct printer_info32 *)info;
727 unsigned int num = *(unsigned int *)ULongToPtr( params32->num );
729 for (i = 0; i < num; i++)
731 info32[i].name = PtrToUlong(info[i].name);
732 info32[i].comment = PtrToUlong(info[i].comment);
733 info32[i].location = PtrToUlong(info[i].location);
734 info32[i].is_default = info[i].is_default;
737 return status;
740 static NTSTATUS wow64_get_default_page_size( void *args )
742 struct
744 PTR32 name;
745 PTR32 name_size;
746 } const *params32 = args;
748 struct get_default_page_size_params params =
750 ULongToPtr( params32->name ),
751 ULongToPtr( params32->name_size )
754 return get_default_page_size( &params );
757 static NTSTATUS wow64_get_ppd( void *args )
759 struct
761 PTR32 printer;
762 PTR32 ppd;
763 } const *params32 = args;
765 struct get_ppd_params params =
767 ULongToPtr( params32->printer ),
768 ULongToPtr( params32->ppd )
771 return get_ppd( &params );
774 static NTSTATUS wow64_schedule_job( void *args )
776 struct
778 PTR32 filename;
779 PTR32 port;
780 PTR32 document_title;
781 PTR32 wine_port;
782 } const *params32 = args;
784 struct schedule_job_params params =
786 ULongToPtr( params32->filename ),
787 ULongToPtr( params32->port ),
788 ULongToPtr( params32->document_title ),
789 ULongToPtr( params32->wine_port )
792 return schedule_job( &params );
795 const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
797 process_attach,
798 wow64_enum_printers,
799 wow64_get_default_page_size,
800 wow64_get_ppd,
801 wow64_schedule_job,
804 #endif /* _WIN64 */