From 12c3579bcb79a3de261fda5f396c7d625dcd7db8 Mon Sep 17 00:00:00 2001 From: Piotr Caban Date: Tue, 10 Oct 2023 18:04:59 +0200 Subject: [PATCH] gdi32: Add GdiGetDevmodeForPage implementation. --- dlls/gdi32/dc.c | 214 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 208 insertions(+), 6 deletions(-) diff --git a/dlls/gdi32/dc.c b/dlls/gdi32/dc.c index 106dbe4deba..c21bc99a6b6 100644 --- a/dlls/gdi32/dc.c +++ b/dlls/gdi32/dc.c @@ -25,6 +25,7 @@ #include "ntuser.h" #include "ddrawgdi.h" #include "winnls.h" +#include "winppi.h" #include "wine/list.h" #include "wine/debug.h" @@ -68,6 +69,47 @@ struct print DEVMODEW *devmode; }; +BOOL WINAPI SeekPrinter( HANDLE, LARGE_INTEGER, LARGE_INTEGER*, DWORD, BOOL ); + +enum +{ + EMRI_METAFILE = 1, + EMRI_ENGINE_FONT, + EMRI_DEVMODE, + EMRI_TYPE1_FONT, + EMRI_PRESTARTPAGE, + EMRI_DESIGNVECTOR, + EMRI_SUBSET_FONT, + EMRI_DELTA_FONT, + EMRI_FORM_METAFILE, + EMRI_BW_METAFILE, + EMRI_BW_FORM_METAFILE, + EMRI_METAFILE_DATA, + EMRI_METAFILE_EXT, + EMRI_BW_METAFILE_EXT, + EMRI_ENGINE_FONT_EXT, + EMRI_TYPE1_FONT_EXT, + EMRI_DESIGNVECTOR_EXT, + EMRI_SUBSET_FONT_EXT, + EMRI_DELTA_FONT_EXT, + EMRI_PS_JOB_DATA, + EMRI_EMBED_FONT_EXT, + EMRI_HEADER = 65536 +}; + +struct spool_handle +{ + HANDLE spool; + + int devmodes_no; + int devmodes_size; + struct + { + int page; + DEVMODEW *devmode; + } *devmodes; +}; + DC_ATTR *get_dc_attr( HDC hdc ) { DWORD type = gdi_handle_type( hdc ); @@ -2670,8 +2712,41 @@ ULONG WINAPI DdQueryDisplaySettingsUniqueness(void) HANDLE WINAPI GdiGetSpoolFileHandle( WCHAR *printer_name, DEVMODEW *devmode, WCHAR *doc_name ) { - FIXME( "%s %p %s\n", wine_dbgstr_w(printer_name), devmode, wine_dbgstr_w(doc_name) ); - return NULL; + struct spool_handle *ret; + HANDLE spool; + + TRACE( "%s %p %s\n", wine_dbgstr_w(printer_name), devmode, wine_dbgstr_w(doc_name) ); + + if (!devmode) return NULL; + if (!OpenPrinterW( doc_name, &spool, NULL )) return NULL; + + ret = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ret) ); + if (!ret) + { + ClosePrinter( spool ); + return NULL; + } + ret->spool = spool; + + ret->devmodes = HeapAlloc( GetProcessHeap(), 0, sizeof(*ret->devmodes) * 8); + if (!ret->devmodes) + { + GdiDeleteSpoolFileHandle( ret ); + return NULL; + } + ret->devmodes_size = 8; + + ret->devmodes[0].devmode = HeapAlloc( GetProcessHeap(), 0, + devmode->dmSize + devmode->dmDriverExtra ); + if (!ret->devmodes[0].devmode) + { + GdiDeleteSpoolFileHandle( ret ); + return NULL; + } + memcpy( ret->devmodes[0].devmode, devmode, devmode->dmSize + devmode->dmDriverExtra ); + ret->devmodes[0].page = 0; + ret->devmodes_no = 1; + return ret; } /******************************************************************* @@ -2679,8 +2754,108 @@ HANDLE WINAPI GdiGetSpoolFileHandle( WCHAR *printer_name, */ BOOL WINAPI GdiDeleteSpoolFileHandle( HANDLE h ) { - FIXME( "%p\n", h ); - return FALSE; + struct spool_handle *sh = (struct spool_handle *)h; + int i; + + TRACE( "%p\n", h ); + + if (!sh) + return FALSE; + + ClosePrinter( sh->spool ); + for (i = 0; i < sh->devmodes_no; i++) + HeapFree( GetProcessHeap(), 0, sh->devmodes[i].devmode ); + HeapFree( GetProcessHeap(), 0, sh->devmodes ); + return TRUE; +} + +static BOOL read_emfspool_record( struct spool_handle *sh ) +{ + struct record_hdr + { + unsigned int ulID; + unsigned int cjSize; + } hdr; + LARGE_INTEGER pos; + BOOL ret; + DWORD r; + + if (!sh->spool) return FALSE; + + ret = ReadPrinter( sh->spool, &hdr, sizeof(hdr), &r ); + if (!ret || r != sizeof(hdr)) + { + ClosePrinter( sh->spool ); + sh->spool = NULL; + return FALSE; + } + TRACE( "parsing record %u\n", hdr.ulID ); + + if (hdr.ulID == EMRI_HEADER) + hdr.cjSize -= sizeof(hdr); + + switch (hdr.ulID) + { + case EMRI_DEVMODE: + /* remove unused devmode */ + if (sh->devmodes_no - 2 >= 0 && sh->devmodes[sh->devmodes_no - 2].page == + sh->devmodes[sh->devmodes_no - 1].page) + { + HeapFree( GetProcessHeap(), 0, sh->devmodes[sh->devmodes_no - 1].devmode ); + sh->devmodes_no--; + } + else if (sh->devmodes_no == sh->devmodes_size) + { + void *alloc = HeapReAlloc( GetProcessHeap(), 0, sh->devmodes, sh->devmodes_size * 2 ); + + if (!alloc) + { + ClosePrinter( sh->spool ); + sh->spool = NULL; + return FALSE; + } + sh->devmodes = alloc; + sh->devmodes_size *= 2; + } + + sh->devmodes[sh->devmodes_no].devmode = HeapAlloc( GetProcessHeap(), 0, hdr.cjSize ); + if (!sh->devmodes[sh->devmodes_no].devmode) + { + ClosePrinter( sh->spool ); + sh->spool = NULL; + return FALSE; + } + + ret = ReadPrinter( sh->spool, sh->devmodes[sh->devmodes_no].devmode, hdr.cjSize, &r ); + if (!ret || r != hdr.cjSize) + { + ClosePrinter( sh->spool ); + sh->spool = NULL; + return FALSE; + } + sh->devmodes[sh->devmodes_no].page = sh->devmodes[sh->devmodes_no - 1].page; + sh->devmodes_no++; + return TRUE; + + case EMRI_METAFILE: + case EMRI_FORM_METAFILE: + case EMRI_BW_METAFILE: + case EMRI_BW_FORM_METAFILE: + case EMRI_METAFILE_EXT: + case EMRI_BW_METAFILE_EXT: + sh->devmodes[sh->devmodes_no - 1].page++; + /* fall through */ + default: + pos.QuadPart = hdr.cjSize; + ret = SeekPrinter( sh->spool, pos, NULL, FILE_CURRENT, FALSE ); + if (!ret) + { + ClosePrinter( sh->spool ); + sh->spool = NULL; + return FALSE; + } + return TRUE; + } } /******************************************************************* @@ -2688,6 +2863,33 @@ BOOL WINAPI GdiDeleteSpoolFileHandle( HANDLE h ) */ BOOL WINAPI GdiGetDevmodeForPage( HANDLE h, DWORD page, DEVMODEW **cur, DEVMODEW **prev ) { - FIXME( "%p %ld %p %p\n", h, page, cur, prev ); - return FALSE; + struct spool_handle *sh = (struct spool_handle *)h; + int i; + + TRACE( "%p %ld %p %p\n", h, page, cur, prev ); + + if (!sh) + return FALSE; + + i = 0; + while (1) + { + if (sh->devmodes[i].page >= page) + { + if (cur) *cur = sh->devmodes[i].devmode; + if (prev) + { + if (!i || sh->devmodes[i - 1].page != page - 1) + *prev = sh->devmodes[i].devmode; + else + *prev = sh->devmodes[i - 1].devmode; + } + return TRUE; + } + + if (i + 1 < sh->devmodes_no) + i++; + else if (!read_emfspool_record( sh )) + return FALSE; + } } -- 2.11.4.GIT