Module: wine Branch: master Commit: 4496c64aa1ea820cd91e4b0ae140f4affaaf17b5 URL: https://gitlab.winehq.org/wine/wine/-/commit/4496c64aa1ea820cd91e4b0ae140f4a...
Author: Piotr Caban piotr@codeweavers.com Date: Thu Apr 27 17:50:14 2023 +0200
gdi32: Support creating EMRI_DEVMODE records in spool files.
---
dlls/gdi32/dc.c | 51 ++++++++++++++++++++++++++++++++++++++++++------ dlls/gdi32/emfdc.c | 13 +++++++++++- dlls/gdi32/gdi_private.h | 3 ++- 3 files changed, 59 insertions(+), 8 deletions(-)
diff --git a/dlls/gdi32/dc.c b/dlls/gdi32/dc.c index 72e30647943..b1ca342f8e3 100644 --- a/dlls/gdi32/dc.c +++ b/dlls/gdi32/dc.c @@ -54,7 +54,8 @@ struct graphics_driver enum print_flags { CALL_START_PAGE = 0x1, - CALL_END_PAGE = 0x2 + CALL_END_PAGE = 0x2, + WRITE_DEVMODE = 0x4, };
struct print @@ -62,6 +63,7 @@ struct print HANDLE printer; WCHAR *output; enum print_flags flags; + DEVMODEW *devmode; };
DC_ATTR *get_dc_attr( HDC hdc ) @@ -202,6 +204,29 @@ done: return driver->entry_point; }
+static BOOL print_copy_devmode( struct print *print, const DEVMODEW *devmode ) +{ + size_t size; + + if (!print) return TRUE; + if (!print->devmode && !devmode) return TRUE; + HeapFree( GetProcessHeap(), 0, print->devmode ); + + if (!devmode) + { + print->devmode = NULL; + print->flags |= WRITE_DEVMODE; + return TRUE; + } + + size = devmode->dmSize + devmode->dmDriverExtra; + print->devmode = HeapAlloc( GetProcessHeap(), 0, size ); + if (!print->devmode) return FALSE; + memcpy(print->devmode, devmode, size); + print->flags |= WRITE_DEVMODE; + return TRUE; +} + /*********************************************************************** * CreateDCW (GDI32.@) */ @@ -262,10 +287,13 @@ HDC WINAPI CreateDCW( LPCWSTR driver, LPCWSTR device, LPCWSTR output, ClosePrinter( hspool ); return 0; } - else if (!(print = HeapAlloc( GetProcessHeap(), 0, sizeof(*print) ))) + else if (!(print = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*print) )) || + !print_copy_devmode( print, devmode )) { + HeapFree( GetProcessHeap(), 0, print ); ClosePrinter( hspool ); HeapFree( GetProcessHeap(), 0, port ); + return 0; }
if (display) @@ -295,13 +323,13 @@ HDC WINAPI CreateDCW( LPCWSTR driver, LPCWSTR device, LPCWSTR output, } print->printer = hspool; print->output = port; - print->flags = 0; dc_attr->print = (UINT_PTR)print; } else if (hspool) { ClosePrinter( hspool ); HeapFree( GetProcessHeap(), 0, port ); + HeapFree( GetProcessHeap(), 0, print->devmode ); HeapFree( GetProcessHeap(), 0, print ); }
@@ -431,6 +459,7 @@ static void delete_print_dc( DC_ATTR *dc_attr )
ClosePrinter( print->printer ); HeapFree( GetProcessHeap(), 0, print->output ); + HeapFree( GetProcessHeap(), 0, print->devmode ); HeapFree( GetProcessHeap(), 0, print ); dc_attr->print = 0; } @@ -471,7 +500,15 @@ HDC WINAPI ResetDCA( HDC hdc, const DEVMODEA *devmode ) */ HDC WINAPI ResetDCW( HDC hdc, const DEVMODEW *devmode ) { - return NtGdiResetDC( hdc, devmode, NULL, NULL, NULL ) ? hdc : 0; + struct print *print; + DC_ATTR *dc_attr; + + if (!(dc_attr = get_dc_attr( hdc ))) return 0; + print = get_dc_print( dc_attr ); + if (print && print->flags & CALL_END_PAGE) return 0; + if (!NtGdiResetDC( hdc, devmode, NULL, NULL, NULL )) return 0; + if (print && !print_copy_devmode( print, devmode )) return 0; + return hdc; }
/*********************************************************************** @@ -2404,9 +2441,11 @@ INT WINAPI EndPage( HDC hdc ) print = get_dc_print( dc_attr ); if (print) { - print->flags = (print->flags & ~CALL_END_PAGE) | CALL_START_PAGE; + BOOL write = print->flags & WRITE_DEVMODE; + + print->flags = (print->flags & ~(CALL_END_PAGE | WRITE_DEVMODE)) | CALL_START_PAGE; if (dc_attr->emf) - return spool_end_page( dc_attr, print->printer ); + return spool_end_page( dc_attr, print->printer, print->devmode, write ); } return NtGdiEndPage( hdc ); } diff --git a/dlls/gdi32/emfdc.c b/dlls/gdi32/emfdc.c index f580f21fc1e..ef316fe42a1 100644 --- a/dlls/gdi32/emfdc.c +++ b/dlls/gdi32/emfdc.c @@ -2807,7 +2807,7 @@ int spool_start_page( DC_ATTR *dc_attr, HANDLE hspool ) return StartPagePrinter( hspool ); }
-int spool_end_page( DC_ATTR *dc_attr, HANDLE hspool ) +int spool_end_page( DC_ATTR *dc_attr, HANDLE hspool, const DEVMODEW *devmode, BOOL write_devmode ) { struct record_hdr { @@ -2831,9 +2831,20 @@ int spool_end_page( DC_ATTR *dc_attr, HANDLE hspool ) if (!WritePrinter( hspool, &record_hdr, sizeof(record_hdr), &written )) return 0; if (!WritePrinter( hspool, emf->emh, emf->emh->nBytes, &written )) return 0;
+ if (write_devmode) + { + record_hdr.ulID = EMRI_DEVMODE; + record_hdr.cjSize = devmode ? devmode->dmSize + devmode->dmDriverExtra : 0; + if (!WritePrinter( hspool, &record_hdr, sizeof(record_hdr), &written )) return 0; + if (devmode && !WritePrinter( hspool, (BYTE *)devmode, + record_hdr.cjSize, &written )) return 0; + } + metafile_ext.hdr.ulID = EMRI_METAFILE_EXT; metafile_ext.hdr.cjSize = sizeof(metafile_ext) - sizeof(struct record_hdr); metafile_ext.pos.QuadPart = emf->emh->nBytes + sizeof(record_hdr); + if (write_devmode) + metafile_ext.pos.QuadPart += record_hdr.cjSize + sizeof(record_hdr); if (!WritePrinter( hspool, &metafile_ext, sizeof(metafile_ext), &written )) return 0;
emf_reset( dc_attr, NULL ); diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h index 6f8f4630b6f..b8f914fe1f4 100644 --- a/dlls/gdi32/gdi_private.h +++ b/dlls/gdi32/gdi_private.h @@ -283,7 +283,8 @@ extern HENHMETAFILE EMF_Create_HENHMETAFILE( ENHMETAHEADER *emh, DWORD filesize, extern BOOL spool_start_doc( DC_ATTR *dc_attr, HANDLE hspool, const DOCINFOW *doc_info ) DECLSPEC_HIDDEN; extern int spool_start_page( DC_ATTR *dc_attr, HANDLE hspool ) DECLSPEC_HIDDEN; -extern int spool_end_page( DC_ATTR *dc_attr, HANDLE hspool ) DECLSPEC_HIDDEN; +extern int spool_end_page( DC_ATTR *dc_attr, HANDLE hspool, const DEVMODEW *devmode, + BOOL write_devmode ) DECLSPEC_HIDDEN; extern int spool_end_doc( DC_ATTR *dc_attr, HANDLE hspool ) DECLSPEC_HIDDEN; extern int spool_abort_doc( DC_ATTR *dc_attr, HANDLE hspool ) DECLSPEC_HIDDEN;