Fix gcc 4.0 -Wpointer-sign warnings.
[wine] / dlls / commdlg / printdlg.c
1 /*
2  * COMMDLG - Print Dialog
3  *
4  * Copyright 1994 Martin Ayotte
5  * Copyright 1996 Albrecht Kleine
6  * Copyright 1999 Klaas van Gend
7  * Copyright 2000 Huw D M Davies
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 #include <ctype.h>
24 #include <stdlib.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include <string.h>
28
29 #define NONAMELESSUNION
30 #define NONAMELESSSTRUCT
31 #include "windef.h"
32 #include "winbase.h"
33 #include "wingdi.h"
34 #include "winuser.h"
35 #include "winspool.h"
36 #include "winerror.h"
37
38 #include "wine/debug.h"
39
40 #include "commdlg.h"
41 #include "dlgs.h"
42 #include "cderr.h"
43
44 WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
45
46 #include "cdlg.h"
47 #include "printdlg.h"
48
49 /* Yes these constants are the same, but we're just copying win98 */
50 #define UPDOWN_ID 0x270f
51 #define MAX_COPIES 9999
52
53 /* Debugging info */
54 static struct pd_flags psd_flags[] = {
55   {PSD_MINMARGINS,"PSD_MINMARGINS"},
56   {PSD_MARGINS,"PSD_MARGINS"},
57   {PSD_INTHOUSANDTHSOFINCHES,"PSD_INTHOUSANDTHSOFINCHES"},
58   {PSD_INHUNDREDTHSOFMILLIMETERS,"PSD_INHUNDREDTHSOFMILLIMETERS"},
59   {PSD_DISABLEMARGINS,"PSD_DISABLEMARGINS"},
60   {PSD_DISABLEPRINTER,"PSD_DISABLEPRINTER"},
61   {PSD_NOWARNING,"PSD_NOWARNING"},
62   {PSD_DISABLEORIENTATION,"PSD_DISABLEORIENTATION"},
63   {PSD_RETURNDEFAULT,"PSD_RETURNDEFAULT"},
64   {PSD_DISABLEPAPER,"PSD_DISABLEPAPER"},
65   {PSD_SHOWHELP,"PSD_SHOWHELP"},
66   {PSD_ENABLEPAGESETUPHOOK,"PSD_ENABLEPAGESETUPHOOK"},
67   {PSD_ENABLEPAGESETUPTEMPLATE,"PSD_ENABLEPAGESETUPTEMPLATE"},
68   {PSD_ENABLEPAGESETUPTEMPLATEHANDLE,"PSD_ENABLEPAGESETUPTEMPLATEHANDLE"},
69   {PSD_ENABLEPAGEPAINTHOOK,"PSD_ENABLEPAGEPAINTHOOK"},
70   {PSD_DISABLEPAGEPAINTING,"PSD_DISABLEPAGEPAINTING"},
71   {-1, NULL}
72 };
73
74 /* address of wndproc for subclassed Static control */
75 static WNDPROC lpfnStaticWndProc;
76 /* the text of the fake document to render for the Page Setup dialog */
77 static WCHAR wszFakeDocumentText[1024];
78
79 /***********************************************************************
80  *    PRINTDLG_OpenDefaultPrinter
81  *
82  * Returns a winspool printer handle to the default printer in *hprn
83  * Caller must call ClosePrinter on the handle
84  *
85  * Returns TRUE on success else FALSE
86  */
87 BOOL PRINTDLG_OpenDefaultPrinter(HANDLE *hprn)
88 {
89     WCHAR buf[260];
90     DWORD dwBufLen = sizeof(buf) / sizeof(buf[0]);
91     BOOL res;
92     if(!GetDefaultPrinterW(buf, &dwBufLen))
93         return FALSE;
94     res = OpenPrinterW(buf, hprn, NULL);
95     if (!res)
96         WARN("Could not open printer %s\n", debugstr_w(buf));
97     return res;
98 }
99
100 /***********************************************************************
101  *    PRINTDLG_SetUpPrinterListCombo
102  *
103  * Initializes printer list combox.
104  * hDlg:  HWND of dialog
105  * id:    Control id of combo
106  * name:  Name of printer to select
107  *
108  * Initializes combo with list of available printers.  Selects printer 'name'
109  * If name is NULL or does not exist select the default printer.
110  *
111  * Returns number of printers added to list.
112  */
113 INT PRINTDLG_SetUpPrinterListComboA(HWND hDlg, UINT id, LPCSTR name)
114 {
115     DWORD needed, num;
116     INT i;
117     LPPRINTER_INFO_2A pi;
118     EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
119     pi = HeapAlloc(GetProcessHeap(), 0, needed);
120     EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pi, needed, &needed,
121                   &num);
122
123     for(i = 0; i < num; i++) {
124         SendDlgItemMessageA(hDlg, id, CB_ADDSTRING, 0,
125                             (LPARAM)pi[i].pPrinterName );
126     }
127     HeapFree(GetProcessHeap(), 0, pi);
128     if(!name ||
129        (i = SendDlgItemMessageA(hDlg, id, CB_FINDSTRINGEXACT, -1,
130                                 (LPARAM)name)) == CB_ERR) {
131
132         char buf[260];
133         DWORD dwBufLen = sizeof(buf);
134         FIXME("Can't find '%s' in printer list so trying to find default\n",
135               name);
136         if(!GetDefaultPrinterA(buf, &dwBufLen))
137             return num;
138         i = SendDlgItemMessageA(hDlg, id, CB_FINDSTRINGEXACT, -1, (LPARAM)buf);
139         if(i == CB_ERR)
140             FIXME("Can't find default printer in printer list\n");
141     }
142     SendDlgItemMessageA(hDlg, id, CB_SETCURSEL, i, 0);
143     return num;
144 }
145
146 static INT PRINTDLG_SetUpPrinterListComboW(HWND hDlg, UINT id, LPCWSTR name)
147 {
148     DWORD needed, num;
149     INT i;
150     LPPRINTER_INFO_2W pi;
151     EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
152     pi = HeapAlloc(GetProcessHeap(), 0, needed);
153     EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pi, needed, &needed,
154                   &num);
155
156     for(i = 0; i < num; i++) {
157         SendDlgItemMessageW(hDlg, id, CB_ADDSTRING, 0,
158                             (LPARAM)pi[i].pPrinterName );
159     }
160     HeapFree(GetProcessHeap(), 0, pi);
161     if(!name ||
162        (i = SendDlgItemMessageW(hDlg, id, CB_FINDSTRINGEXACT, -1,
163                                 (LPARAM)name)) == CB_ERR) {
164         WCHAR buf[260];
165         DWORD dwBufLen = sizeof(buf)/sizeof(buf[0]);
166         TRACE("Can't find '%s' in printer list so trying to find default\n",
167               debugstr_w(name));
168         if(!GetDefaultPrinterW(buf, &dwBufLen))
169             return num;
170         i = SendDlgItemMessageW(hDlg, id, CB_FINDSTRINGEXACT, -1, (LPARAM)buf);
171         if(i == CB_ERR)
172             TRACE("Can't find default printer in printer list\n");
173     }
174     SendDlgItemMessageW(hDlg, id, CB_SETCURSEL, i, 0);
175     return num;
176 }
177
178 /***********************************************************************
179  *             PRINTDLG_CreateDevNames          [internal]
180  *
181  *
182  *   creates a DevNames structure.
183  *
184  *  (NB. when we handle unicode the offsets will be in wchars).
185  */
186 static BOOL PRINTDLG_CreateDevNames(HGLOBAL *hmem, char* DeviceDriverName,
187                                     char* DeviceName, char* OutputPort)
188 {
189     long size;
190     char*   pDevNamesSpace;
191     char*   pTempPtr;
192     LPDEVNAMES lpDevNames;
193     char buf[260];
194     DWORD dwBufLen = sizeof(buf);
195
196     size = strlen(DeviceDriverName) + 1
197             + strlen(DeviceName) + 1
198             + strlen(OutputPort) + 1
199             + sizeof(DEVNAMES);
200
201     if(*hmem)
202         *hmem = GlobalReAlloc(*hmem, size, GMEM_MOVEABLE);
203     else
204         *hmem = GlobalAlloc(GMEM_MOVEABLE, size);
205     if (*hmem == 0)
206         return FALSE;
207
208     pDevNamesSpace = GlobalLock(*hmem);
209     lpDevNames = (LPDEVNAMES) pDevNamesSpace;
210
211     pTempPtr = pDevNamesSpace + sizeof(DEVNAMES);
212     strcpy(pTempPtr, DeviceDriverName);
213     lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
214
215     pTempPtr += strlen(DeviceDriverName) + 1;
216     strcpy(pTempPtr, DeviceName);
217     lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
218
219     pTempPtr += strlen(DeviceName) + 1;
220     strcpy(pTempPtr, OutputPort);
221     lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
222
223     GetDefaultPrinterA(buf, &dwBufLen);
224     lpDevNames->wDefault = (strcmp(buf, DeviceName) == 0) ? 1 : 0;
225     GlobalUnlock(*hmem);
226     return TRUE;
227 }
228
229 static BOOL PRINTDLG_CreateDevNamesW(HGLOBAL *hmem, LPCWSTR DeviceDriverName,
230                                     LPCWSTR DeviceName, LPCWSTR OutputPort)
231 {
232     long size;
233     LPWSTR   pDevNamesSpace;
234     LPWSTR   pTempPtr;
235     LPDEVNAMES lpDevNames;
236     WCHAR bufW[260];
237     DWORD dwBufLen = sizeof(bufW) / sizeof(WCHAR);
238
239     size = sizeof(WCHAR)*lstrlenW(DeviceDriverName) + 2
240             + sizeof(WCHAR)*lstrlenW(DeviceName) + 2
241             + sizeof(WCHAR)*lstrlenW(OutputPort) + 2
242             + sizeof(DEVNAMES);
243
244     if(*hmem)
245         *hmem = GlobalReAlloc(*hmem, size, GMEM_MOVEABLE);
246     else
247         *hmem = GlobalAlloc(GMEM_MOVEABLE, size);
248     if (*hmem == 0)
249         return FALSE;
250
251     pDevNamesSpace = GlobalLock(*hmem);
252     lpDevNames = (LPDEVNAMES) pDevNamesSpace;
253
254     pTempPtr = (LPWSTR)((LPDEVNAMES)pDevNamesSpace + 1);
255     lstrcpyW(pTempPtr, DeviceDriverName);
256     lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
257
258     pTempPtr += lstrlenW(DeviceDriverName) + 1;
259     lstrcpyW(pTempPtr, DeviceName);
260     lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
261
262     pTempPtr += lstrlenW(DeviceName) + 1;
263     lstrcpyW(pTempPtr, OutputPort);
264     lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
265
266     GetDefaultPrinterW(bufW, &dwBufLen);
267     lpDevNames->wDefault = (lstrcmpW(bufW, DeviceName) == 0) ? 1 : 0;
268     GlobalUnlock(*hmem);
269     return TRUE;
270 }
271
272 /***********************************************************************
273  *             PRINTDLG_UpdatePrintDlg          [internal]
274  *
275  *
276  *   updates the PrintDlg structure for return values.
277  *
278  * RETURNS
279  *   FALSE if user is not allowed to close (i.e. wrong nTo or nFrom values)
280  *   TRUE  if successful.
281  */
282 static BOOL PRINTDLG_UpdatePrintDlgA(HWND hDlg,
283                                     PRINT_PTRA* PrintStructures)
284 {
285     LPPRINTDLGA       lppd = PrintStructures->lpPrintDlg;
286     PDEVMODEA         lpdm = PrintStructures->lpDevMode;
287     LPPRINTER_INFO_2A pi = PrintStructures->lpPrinterInfo;
288
289
290     if(!lpdm) {
291         FIXME("No lpdm ptr?\n");
292         return FALSE;
293     }
294
295
296     if(!(lppd->Flags & PD_PRINTSETUP)) {
297         /* check whether nFromPage and nToPage are within range defined by
298          * nMinPage and nMaxPage
299          */
300         if (IsDlgButtonChecked(hDlg, rad3) == BST_CHECKED) { /* Pages */
301             WORD nToPage;
302             WORD nFromPage;
303             nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
304             nToPage   = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
305             if (nFromPage < lppd->nMinPage || nFromPage > lppd->nMaxPage ||
306                 nToPage < lppd->nMinPage || nToPage > lppd->nMaxPage) {
307                 char resourcestr[256];
308                 char resultstr[256];
309                 LoadStringA(COMDLG32_hInstance, PD32_INVALID_PAGE_RANGE,
310                             resourcestr, 255);
311                 sprintf(resultstr,resourcestr, lppd->nMinPage, lppd->nMaxPage);
312                 LoadStringA(COMDLG32_hInstance, PD32_PRINT_TITLE,
313                             resourcestr, 255);
314                 MessageBoxA(hDlg, resultstr, resourcestr,
315                             MB_OK | MB_ICONWARNING);
316                 return FALSE;
317             }
318             lppd->nFromPage = nFromPage;
319             lppd->nToPage   = nToPage;
320             lppd->Flags |= PD_PAGENUMS;
321         }
322         else
323             lppd->Flags &= ~PD_PAGENUMS;
324
325         if (IsDlgButtonChecked(hDlg, chx1) == BST_CHECKED) {/* Print to file */
326             lppd->Flags |= PD_PRINTTOFILE;
327             pi->pPortName = "FILE:";
328         }
329
330         if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED) { /* Collate */
331             FIXME("Collate lppd not yet implemented as output\n");
332         }
333
334         /* set PD_Collate and nCopies */
335         if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
336           /*  The application doesn't support multiple copies or collate...
337            */
338             lppd->Flags &= ~PD_COLLATE;
339             lppd->nCopies = 1;
340           /* if the printer driver supports it... store info there
341            * otherwise no collate & multiple copies !
342            */
343             if (lpdm->dmFields & DM_COLLATE)
344                 lpdm->dmCollate =
345                   (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED);
346             if (lpdm->dmFields & DM_COPIES)
347                 lpdm->dmCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
348         } else {
349             if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
350                 lppd->Flags |= PD_COLLATE;
351             else
352                lppd->Flags &= ~PD_COLLATE;
353             lppd->nCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
354         }
355     }
356     return TRUE;
357 }
358
359 static BOOL PRINTDLG_UpdatePrintDlgW(HWND hDlg,
360                                     PRINT_PTRW* PrintStructures)
361 {
362     LPPRINTDLGW       lppd = PrintStructures->lpPrintDlg;
363     PDEVMODEW         lpdm = PrintStructures->lpDevMode;
364     LPPRINTER_INFO_2W pi = PrintStructures->lpPrinterInfo;
365
366
367     if(!lpdm) {
368         FIXME("No lpdm ptr?\n");
369         return FALSE;
370     }
371
372
373     if(!(lppd->Flags & PD_PRINTSETUP)) {
374         /* check whether nFromPage and nToPage are within range defined by
375          * nMinPage and nMaxPage
376          */
377         if (IsDlgButtonChecked(hDlg, rad3) == BST_CHECKED) { /* Pages */
378             WORD nToPage;
379             WORD nFromPage;
380             nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
381             nToPage   = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
382             if (nFromPage < lppd->nMinPage || nFromPage > lppd->nMaxPage ||
383                 nToPage < lppd->nMinPage || nToPage > lppd->nMaxPage) {
384                 WCHAR resourcestr[256];
385                 WCHAR resultstr[256];
386                 LoadStringW(COMDLG32_hInstance, PD32_INVALID_PAGE_RANGE,
387                             resourcestr, 255);
388                 wsprintfW(resultstr,resourcestr, lppd->nMinPage, lppd->nMaxPage);
389                 LoadStringW(COMDLG32_hInstance, PD32_PRINT_TITLE,
390                             resourcestr, 255);
391                 MessageBoxW(hDlg, resultstr, resourcestr,
392                             MB_OK | MB_ICONWARNING);
393                 return FALSE;
394             }
395             lppd->nFromPage = nFromPage;
396             lppd->nToPage   = nToPage;
397         }
398
399         if (IsDlgButtonChecked(hDlg, chx1) == BST_CHECKED) {/* Print to file */
400             static WCHAR file[] = {'F','I','L','E',':',0};
401             lppd->Flags |= PD_PRINTTOFILE;
402             pi->pPortName = file;
403         }
404
405         if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED) { /* Collate */
406             FIXME("Collate lppd not yet implemented as output\n");
407         }
408
409         /* set PD_Collate and nCopies */
410         if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
411           /*  The application doesn't support multiple copies or collate...
412            */
413             lppd->Flags &= ~PD_COLLATE;
414             lppd->nCopies = 1;
415           /* if the printer driver supports it... store info there
416            * otherwise no collate & multiple copies !
417            */
418             if (lpdm->dmFields & DM_COLLATE)
419                 lpdm->dmCollate =
420                   (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED);
421             if (lpdm->dmFields & DM_COPIES)
422                 lpdm->dmCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
423         } else {
424             if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
425                 lppd->Flags |= PD_COLLATE;
426             else
427                lppd->Flags &= ~PD_COLLATE;
428             lppd->nCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
429         }
430     }
431     return TRUE;
432 }
433
434 static BOOL PRINTDLG_PaperSizeA(
435         PRINTDLGA       *pdlga,const char *PaperSize,LPPOINT size
436 ) {
437     DEVNAMES    *dn;
438     DEVMODEA    *dm;
439     LPSTR       devname,portname;
440     int         i;
441     INT         NrOfEntries,ret;
442     char        *Names = NULL;
443     POINT       *points = NULL;
444     BOOL        retval = FALSE;
445
446     dn = GlobalLock(pdlga->hDevNames);
447     dm = GlobalLock(pdlga->hDevMode);
448     devname     = ((char*)dn)+dn->wDeviceOffset;
449     portname    = ((char*)dn)+dn->wOutputOffset;
450
451
452     NrOfEntries = DeviceCapabilitiesA(devname,portname,DC_PAPERNAMES,NULL,dm);
453     if (!NrOfEntries) {
454         FIXME("No papernames found for %s/%s\n",devname,portname);
455         goto out;
456     }
457     if (NrOfEntries == -1) {
458         ERR("Hmm ? DeviceCapabilities() DC_PAPERNAMES failed, ret -1 !\n");
459         goto out;
460     }
461
462     Names = HeapAlloc(GetProcessHeap(),0,NrOfEntries*64);
463     if (NrOfEntries != (ret=DeviceCapabilitiesA(devname,portname,DC_PAPERNAMES,Names,dm))) {
464         FIXME("Number of returned vals %d is not %d\n",NrOfEntries,ret);
465         goto out;
466     }
467     for (i=0;i<NrOfEntries;i++)
468         if (!strcmp(PaperSize,Names+(64*i)))
469             break;
470     HeapFree(GetProcessHeap(),0,Names);
471     if (i==NrOfEntries) {
472         FIXME("Papersize %s not found in list?\n",PaperSize);
473         goto out;
474     }
475     points = HeapAlloc(GetProcessHeap(),0,sizeof(points[0])*NrOfEntries);
476     if (NrOfEntries!=(ret=DeviceCapabilitiesA(devname,portname,DC_PAPERSIZE,(LPBYTE)points,dm))) {
477         FIXME("Number of returned sizes %d is not %d?\n",NrOfEntries,ret);
478         goto out;
479     }
480     /* this is _10ths_ of a millimeter */
481     size->x=points[i].x;
482     size->y=points[i].y;
483     retval = TRUE;
484 out:
485     GlobalUnlock(pdlga->hDevNames);
486     GlobalUnlock(pdlga->hDevMode);
487     HeapFree(GetProcessHeap(),0,Names);
488     HeapFree(GetProcessHeap(),0,points);
489     return retval;
490 }
491
492 static BOOL PRINTDLG_PaperSizeW(
493         PRINTDLGW       *pdlga,const WCHAR *PaperSize,LPPOINT size
494 ) {
495     DEVNAMES    *dn;
496     DEVMODEW    *dm;
497     LPWSTR      devname,portname;
498     int         i;
499     INT         NrOfEntries,ret;
500     WCHAR       *Names = NULL;
501     POINT       *points = NULL;
502     BOOL        retval = FALSE;
503
504     dn = GlobalLock(pdlga->hDevNames);
505     dm = GlobalLock(pdlga->hDevMode);
506     devname     = ((WCHAR*)dn)+dn->wDeviceOffset;
507     portname    = ((WCHAR*)dn)+dn->wOutputOffset;
508
509
510     NrOfEntries = DeviceCapabilitiesW(devname,portname,DC_PAPERNAMES,NULL,dm);
511     if (!NrOfEntries) {
512         FIXME("No papernames found for %s/%s\n",debugstr_w(devname),debugstr_w(portname));
513         goto out;
514     }
515     if (NrOfEntries == -1) {
516         ERR("Hmm ? DeviceCapabilities() DC_PAPERNAMES failed, ret -1 !\n");
517         goto out;
518     }
519
520     Names = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*NrOfEntries*64);
521     if (NrOfEntries != (ret=DeviceCapabilitiesW(devname,portname,DC_PAPERNAMES,Names,dm))) {
522         FIXME("Number of returned vals %d is not %d\n",NrOfEntries,ret);
523         goto out;
524     }
525     for (i=0;i<NrOfEntries;i++)
526         if (!lstrcmpW(PaperSize,Names+(64*i)))
527             break;
528     HeapFree(GetProcessHeap(),0,Names);
529     if (i==NrOfEntries) {
530         FIXME("Papersize %s not found in list?\n",debugstr_w(PaperSize));
531         goto out;
532     }
533     points = HeapAlloc(GetProcessHeap(),0,sizeof(points[0])*NrOfEntries);
534     if (NrOfEntries!=(ret=DeviceCapabilitiesW(devname,portname,DC_PAPERSIZE,(LPWSTR)points,dm))) {
535         FIXME("Number of returned sizes %d is not %d?\n",NrOfEntries,ret);
536         goto out;
537     }
538     /* this is _10ths_ of a millimeter */
539     size->x=points[i].x;
540     size->y=points[i].y;
541     retval = TRUE;
542 out:
543     GlobalUnlock(pdlga->hDevNames);
544     GlobalUnlock(pdlga->hDevMode);
545     HeapFree(GetProcessHeap(),0,Names);
546     HeapFree(GetProcessHeap(),0,points);
547     return retval;
548 }
549
550
551 /************************************************************************
552  * PRINTDLG_SetUpPaperComboBox
553  *
554  * Initialize either the papersize or inputslot combos of the Printer Setup
555  * dialog.  We store the associated word (eg DMPAPER_A4) as the item data.
556  * We also try to re-select the old selection.
557  */
558 static BOOL PRINTDLG_SetUpPaperComboBoxA(HWND hDlg,
559                                         int   nIDComboBox,
560                                         char* PrinterName,
561                                         char* PortName,
562                                         LPDEVMODEA dm)
563 {
564     int     i;
565     int     NrOfEntries;
566     char*   Names;
567     WORD*   Words;
568     DWORD   Sel;
569     WORD    oldWord = 0;
570     int     NamesSize;
571     int     fwCapability_Names;
572     int     fwCapability_Words;
573
574     TRACE(" Printer: %s, Port: %s, ComboID: %d\n",PrinterName,PortName,nIDComboBox);
575
576     /* query the dialog box for the current selected value */
577     Sel = SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETCURSEL, 0, 0);
578     if(Sel != CB_ERR) {
579         /* we enter here only if a different printer is selected after
580          * the Print Setup dialog is opened. The current settings are
581          * stored into the newly selected printer.
582          */
583         oldWord = SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA,
584                                       Sel, 0);
585         if (dm) {
586             if (nIDComboBox == cmb2)
587                 dm->u1.s1.dmPaperSize = oldWord;
588             else
589                 dm->dmDefaultSource = oldWord;
590         }
591     }
592     else {
593         /* we enter here only when the Print setup dialog is initially
594          * opened. In this case the settings are restored from when
595          * the dialog was last closed.
596          */
597         if (dm) {
598             if (nIDComboBox == cmb2)
599                 oldWord = dm->u1.s1.dmPaperSize;
600             else
601                 oldWord = dm->dmDefaultSource;
602         }
603     }
604
605     if (nIDComboBox == cmb2) {
606          NamesSize          = 64;
607          fwCapability_Names = DC_PAPERNAMES;
608          fwCapability_Words = DC_PAPERS;
609     } else {
610          nIDComboBox        = cmb3;
611          NamesSize          = 24;
612          fwCapability_Names = DC_BINNAMES;
613          fwCapability_Words = DC_BINS;
614     }
615
616     /* for some printer drivers, DeviceCapabilities calls a VXD to obtain the
617      * paper settings. As Wine doesn't allow VXDs, this results in a crash.
618      */
619     WARN(" if your printer driver uses VXDs, expect a crash now!\n");
620     NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
621                                       fwCapability_Names, NULL, dm);
622     if (NrOfEntries == 0)
623          WARN("no Name Entries found!\n");
624     else if (NrOfEntries < 0)
625          return FALSE;
626
627     if(DeviceCapabilitiesA(PrinterName, PortName, fwCapability_Words, NULL, dm)
628        != NrOfEntries) {
629         ERR("Number of caps is different\n");
630         NrOfEntries = 0;
631     }
632
633     Names = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(char)*NamesSize);
634     Words = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WORD));
635     NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
636                                       fwCapability_Names, Names, dm);
637     NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
638                                       fwCapability_Words, (LPSTR)Words, dm);
639
640     /* reset any current content in the combobox */
641     SendDlgItemMessageA(hDlg, nIDComboBox, CB_RESETCONTENT, 0, 0);
642
643     /* store new content */
644     for (i = 0; i < NrOfEntries; i++) {
645         DWORD pos = SendDlgItemMessageA(hDlg, nIDComboBox, CB_ADDSTRING, 0,
646                                         (LPARAM)(&Names[i*NamesSize]) );
647         SendDlgItemMessageA(hDlg, nIDComboBox, CB_SETITEMDATA, pos,
648                             Words[i]);
649     }
650
651     /* Look for old selection - can't do this is previous loop since
652        item order will change as more items are added */
653     Sel = 0;
654     for (i = 0; i < NrOfEntries; i++) {
655         if(SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) ==
656            oldWord) {
657             Sel = i;
658             break;
659         }
660     }
661     SendDlgItemMessageA(hDlg, nIDComboBox, CB_SETCURSEL, Sel, 0);
662
663     HeapFree(GetProcessHeap(),0,Words);
664     HeapFree(GetProcessHeap(),0,Names);
665     return TRUE;
666 }
667
668 static BOOL PRINTDLG_SetUpPaperComboBoxW(HWND hDlg,
669                                         int   nIDComboBox,
670                                         WCHAR* PrinterName,
671                                         WCHAR* PortName,
672                                         LPDEVMODEW dm)
673 {
674     int     i;
675     int     NrOfEntries;
676     WCHAR*  Names;
677     WORD*   Words;
678     DWORD   Sel;
679     WORD    oldWord = 0;
680     int     NamesSize;
681     int     fwCapability_Names;
682     int     fwCapability_Words;
683
684     TRACE(" Printer: %s, Port: %s, ComboID: %d\n",debugstr_w(PrinterName),debugstr_w(PortName),nIDComboBox);
685
686     /* query the dialog box for the current selected value */
687     Sel = SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETCURSEL, 0, 0);
688     if(Sel != CB_ERR) {
689         /* we enter here only if a different printer is selected after
690          * the Print Setup dialog is opened. The current settings are
691          * stored into the newly selected printer.
692          */
693         oldWord = SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETITEMDATA,
694                                       Sel, 0);
695         if (dm) {
696             if (nIDComboBox == cmb2)
697                 dm->u1.s1.dmPaperSize = oldWord;
698             else
699                 dm->dmDefaultSource = oldWord;
700         }
701     }
702     else {
703         /* we enter here only when the Print setup dialog is initially
704          * opened. In this case the settings are restored from when
705          * the dialog was last closed.
706          */
707         if (dm) {
708             if (nIDComboBox == cmb2)
709                 oldWord = dm->u1.s1.dmPaperSize;
710             else
711                 oldWord = dm->dmDefaultSource;
712         }
713     }
714
715     if (nIDComboBox == cmb2) {
716          NamesSize          = 64;
717          fwCapability_Names = DC_PAPERNAMES;
718          fwCapability_Words = DC_PAPERS;
719     } else {
720          nIDComboBox        = cmb3;
721          NamesSize          = 24;
722          fwCapability_Names = DC_BINNAMES;
723          fwCapability_Words = DC_BINS;
724     }
725
726     /* for some printer drivers, DeviceCapabilities calls a VXD to obtain the
727      * paper settings. As Wine doesn't allow VXDs, this results in a crash.
728      */
729     WARN(" if your printer driver uses VXDs, expect a crash now!\n");
730     NrOfEntries = DeviceCapabilitiesW(PrinterName, PortName,
731                                       fwCapability_Names, NULL, dm);
732     if (NrOfEntries == 0)
733          WARN("no Name Entries found!\n");
734     else if (NrOfEntries < 0)
735          return FALSE;
736
737     if(DeviceCapabilitiesW(PrinterName, PortName, fwCapability_Words, NULL, dm)
738        != NrOfEntries) {
739         ERR("Number of caps is different\n");
740         NrOfEntries = 0;
741     }
742
743     Names = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WCHAR)*NamesSize);
744     Words = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WORD));
745     NrOfEntries = DeviceCapabilitiesW(PrinterName, PortName,
746                                       fwCapability_Names, Names, dm);
747     NrOfEntries = DeviceCapabilitiesW(PrinterName, PortName,
748                                       fwCapability_Words, (LPWSTR)Words, dm);
749
750     /* reset any current content in the combobox */
751     SendDlgItemMessageW(hDlg, nIDComboBox, CB_RESETCONTENT, 0, 0);
752
753     /* store new content */
754     for (i = 0; i < NrOfEntries; i++) {
755         DWORD pos = SendDlgItemMessageW(hDlg, nIDComboBox, CB_ADDSTRING, 0,
756                                         (LPARAM)(&Names[i*NamesSize]) );
757         SendDlgItemMessageW(hDlg, nIDComboBox, CB_SETITEMDATA, pos,
758                             Words[i]);
759     }
760
761     /* Look for old selection - can't do this is previous loop since
762        item order will change as more items are added */
763     Sel = 0;
764     for (i = 0; i < NrOfEntries; i++) {
765         if(SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) ==
766            oldWord) {
767             Sel = i;
768             break;
769         }
770     }
771     SendDlgItemMessageW(hDlg, nIDComboBox, CB_SETCURSEL, Sel, 0);
772
773     HeapFree(GetProcessHeap(),0,Words);
774     HeapFree(GetProcessHeap(),0,Names);
775     return TRUE;
776 }
777
778
779 /***********************************************************************
780  *               PRINTDLG_UpdatePrinterInfoTexts               [internal]
781  */
782 static void PRINTDLG_UpdatePrinterInfoTextsA(HWND hDlg, LPPRINTER_INFO_2A pi)
783 {
784     char   StatusMsg[256];
785     char   ResourceString[256];
786     int    i;
787
788     /* Status Message */
789     StatusMsg[0]='\0';
790
791     /* add all status messages */
792     for (i = 0; i < 25; i++) {
793         if (pi->Status & (1<<i)) {
794             LoadStringA(COMDLG32_hInstance, PD32_PRINTER_STATUS_PAUSED+i,
795                         ResourceString, 255);
796             strcat(StatusMsg,ResourceString);
797         }
798     }
799     /* append "ready" */
800     /* FIXME: status==ready must only be appended if really so.
801               but how to detect? */
802     LoadStringA(COMDLG32_hInstance, PD32_PRINTER_STATUS_READY,
803                 ResourceString, 255);
804     strcat(StatusMsg,ResourceString);
805     SetDlgItemTextA(hDlg, stc12, StatusMsg);
806
807     /* set all other printer info texts */
808     SetDlgItemTextA(hDlg, stc11, pi->pDriverName);
809     
810     if (pi->pLocation != NULL && pi->pLocation[0] != '\0')
811         SetDlgItemTextA(hDlg, stc14, pi->pLocation);
812     else
813         SetDlgItemTextA(hDlg, stc14, pi->pPortName);
814     SetDlgItemTextA(hDlg, stc13, pi->pComment ? pi->pComment : "");
815     return;
816 }
817
818 static void PRINTDLG_UpdatePrinterInfoTextsW(HWND hDlg, LPPRINTER_INFO_2W pi)
819 {
820     WCHAR   StatusMsg[256];
821     WCHAR   ResourceString[256];
822     static const WCHAR emptyW[] = {0};
823     int    i;
824
825     /* Status Message */
826     StatusMsg[0]='\0';
827
828     /* add all status messages */
829     for (i = 0; i < 25; i++) {
830         if (pi->Status & (1<<i)) {
831             LoadStringW(COMDLG32_hInstance, PD32_PRINTER_STATUS_PAUSED+i,
832                         ResourceString, 255);
833             lstrcatW(StatusMsg,ResourceString);
834         }
835     }
836     /* append "ready" */
837     /* FIXME: status==ready must only be appended if really so.
838               but how to detect? */
839     LoadStringW(COMDLG32_hInstance, PD32_PRINTER_STATUS_READY,
840                 ResourceString, 255);
841     lstrcatW(StatusMsg,ResourceString);
842     SetDlgItemTextW(hDlg, stc12, StatusMsg);
843
844     /* set all other printer info texts */
845     SetDlgItemTextW(hDlg, stc11, pi->pDriverName);
846     if (pi->pLocation != NULL && pi->pLocation[0] != '\0')
847         SetDlgItemTextW(hDlg, stc14, pi->pLocation);
848     else
849         SetDlgItemTextW(hDlg, stc14, pi->pPortName);
850     SetDlgItemTextW(hDlg, stc13, pi->pComment ? pi->pComment : emptyW);
851 }
852
853
854 /*******************************************************************
855  *
856  *                 PRINTDLG_ChangePrinter
857  *
858  */
859 BOOL PRINTDLG_ChangePrinterA(HWND hDlg, char *name,
860                                    PRINT_PTRA *PrintStructures)
861 {
862     LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
863     LPDEVMODEA lpdm = NULL;
864     LONG dmSize;
865     DWORD needed;
866     HANDLE hprn;
867
868     HeapFree(GetProcessHeap(),0, PrintStructures->lpPrinterInfo);
869     HeapFree(GetProcessHeap(),0, PrintStructures->lpDriverInfo);
870     if(!OpenPrinterA(name, &hprn, NULL)) {
871         ERR("Can't open printer %s\n", name);
872         return FALSE;
873     }
874     GetPrinterA(hprn, 2, NULL, 0, &needed);
875     PrintStructures->lpPrinterInfo = HeapAlloc(GetProcessHeap(),0,needed);
876     GetPrinterA(hprn, 2, (LPBYTE)PrintStructures->lpPrinterInfo, needed,
877                 &needed);
878     GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
879     PrintStructures->lpDriverInfo = HeapAlloc(GetProcessHeap(),0,needed);
880     if (!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)PrintStructures->lpDriverInfo,
881             needed, &needed)) {
882         ERR("GetPrinterDriverA failed for %s, fix your config!\n",PrintStructures->lpPrinterInfo->pPrinterName);
883         return FALSE;
884     }
885     ClosePrinter(hprn);
886
887     PRINTDLG_UpdatePrinterInfoTextsA(hDlg, PrintStructures->lpPrinterInfo);
888
889     HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
890     PrintStructures->lpDevMode = NULL;
891
892     dmSize = DocumentPropertiesA(0, 0, name, NULL, NULL, 0);
893     if(dmSize == -1) {
894         ERR("DocumentProperties fails on %s\n", debugstr_a(name));
895         return FALSE;
896     }
897     PrintStructures->lpDevMode = HeapAlloc(GetProcessHeap(), 0, dmSize);
898     dmSize = DocumentPropertiesA(0, 0, name, PrintStructures->lpDevMode, NULL,
899                                  DM_OUT_BUFFER);
900     if(lppd->hDevMode && (lpdm = GlobalLock(lppd->hDevMode)) &&
901                           !strcmp(lpdm->dmDeviceName,
902                                   PrintStructures->lpDevMode->dmDeviceName)) {
903       /* Supplied devicemode matches current printer so try to use it */
904         DocumentPropertiesA(0, 0, name, PrintStructures->lpDevMode, lpdm,
905                             DM_OUT_BUFFER | DM_IN_BUFFER);
906     }
907     if(lpdm)
908         GlobalUnlock(lppd->hDevMode);
909
910     lpdm = PrintStructures->lpDevMode;  /* use this as a shortcut */
911
912     if(!(lppd->Flags & PD_PRINTSETUP)) {
913       /* Print range (All/Range/Selection) */
914         SetDlgItemInt(hDlg, edt1, lppd->nFromPage, FALSE);
915         SetDlgItemInt(hDlg, edt2, lppd->nToPage, FALSE);
916         CheckRadioButton(hDlg, rad1, rad3, rad1);               /* default */
917         if (lppd->Flags & PD_NOSELECTION)
918             EnableWindow(GetDlgItem(hDlg, rad2), FALSE);
919         else
920             if (lppd->Flags & PD_SELECTION)
921                 CheckRadioButton(hDlg, rad1, rad3, rad2);
922         if (lppd->Flags & PD_NOPAGENUMS) {
923             EnableWindow(GetDlgItem(hDlg, rad3), FALSE);
924             EnableWindow(GetDlgItem(hDlg, stc2),FALSE);
925             EnableWindow(GetDlgItem(hDlg, edt1), FALSE);
926             EnableWindow(GetDlgItem(hDlg, stc3),FALSE);
927             EnableWindow(GetDlgItem(hDlg, edt2), FALSE);
928         } else {
929             if (lppd->Flags & PD_PAGENUMS)
930                 CheckRadioButton(hDlg, rad1, rad3, rad3);
931         }
932
933         /* Collate pages
934          *
935          * FIXME: The ico3 is not displayed for some reason. I don't know why.
936          */
937         if (lppd->Flags & PD_COLLATE) {
938             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
939                                 (LPARAM)PrintStructures->hCollateIcon);
940             CheckDlgButton(hDlg, chx2, 1);
941         } else {
942             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
943                                 (LPARAM)PrintStructures->hNoCollateIcon);
944             CheckDlgButton(hDlg, chx2, 0);
945         }
946
947         if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
948           /* if printer doesn't support it: no Collate */
949             if (!(lpdm->dmFields & DM_COLLATE)) {
950                 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
951                 EnableWindow(GetDlgItem(hDlg, ico3), FALSE);
952             }
953         }
954
955         /* nCopies */
956         {
957           INT copies;
958           if (lppd->hDevMode == 0)
959               copies = lppd->nCopies;
960           else
961               copies = lpdm->dmCopies;
962           if(copies == 0) copies = 1;
963           else if(copies < 0) copies = MAX_COPIES;
964           SetDlgItemInt(hDlg, edt3, copies, FALSE);
965         }
966
967         if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
968           /* if printer doesn't support it: no nCopies */
969             if (!(lpdm->dmFields & DM_COPIES)) {
970                 EnableWindow(GetDlgItem(hDlg, edt3), FALSE);
971                 EnableWindow(GetDlgItem(hDlg, stc5), FALSE);
972             }
973         }
974
975         /* print to file */
976         CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0);
977         if (lppd->Flags & PD_DISABLEPRINTTOFILE)
978             EnableWindow(GetDlgItem(hDlg, chx1), FALSE);
979         if (lppd->Flags & PD_HIDEPRINTTOFILE)
980             ShowWindow(GetDlgItem(hDlg, chx1), SW_HIDE);
981
982     } else { /* PD_PRINTSETUP */
983       BOOL bPortrait = (lpdm->u1.s1.dmOrientation == DMORIENT_PORTRAIT);
984
985       PRINTDLG_SetUpPaperComboBoxA(hDlg, cmb2,
986                                   PrintStructures->lpPrinterInfo->pPrinterName,
987                                   PrintStructures->lpPrinterInfo->pPortName,
988                                   lpdm);
989       PRINTDLG_SetUpPaperComboBoxA(hDlg, cmb3,
990                                   PrintStructures->lpPrinterInfo->pPrinterName,
991                                   PrintStructures->lpPrinterInfo->pPortName,
992                                   lpdm);
993       CheckRadioButton(hDlg, rad1, rad2, bPortrait ? rad1: rad2);
994       SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
995                           (LPARAM)(bPortrait ? PrintStructures->hPortraitIcon :
996                                    PrintStructures->hLandscapeIcon));
997
998     }
999
1000     /* help button */
1001     if ((lppd->Flags & PD_SHOWHELP)==0) {
1002         /* hide if PD_SHOWHELP not specified */
1003         ShowWindow(GetDlgItem(hDlg, pshHelp), SW_HIDE);
1004     }
1005     return TRUE;
1006 }
1007
1008 static BOOL PRINTDLG_ChangePrinterW(HWND hDlg, WCHAR *name,
1009                                    PRINT_PTRW *PrintStructures)
1010 {
1011     LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
1012     LPDEVMODEW lpdm = NULL;
1013     LONG dmSize;
1014     DWORD needed;
1015     HANDLE hprn;
1016
1017     HeapFree(GetProcessHeap(),0, PrintStructures->lpPrinterInfo);
1018     HeapFree(GetProcessHeap(),0, PrintStructures->lpDriverInfo);
1019     if(!OpenPrinterW(name, &hprn, NULL)) {
1020         ERR("Can't open printer %s\n", debugstr_w(name));
1021         return FALSE;
1022     }
1023     GetPrinterW(hprn, 2, NULL, 0, &needed);
1024     PrintStructures->lpPrinterInfo = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*needed);
1025     GetPrinterW(hprn, 2, (LPBYTE)PrintStructures->lpPrinterInfo, needed,
1026                 &needed);
1027     GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
1028     PrintStructures->lpDriverInfo = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*needed);
1029     if (!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)PrintStructures->lpDriverInfo,
1030             needed, &needed)) {
1031         ERR("GetPrinterDriverA failed for %s, fix your config!\n",debugstr_w(PrintStructures->lpPrinterInfo->pPrinterName));
1032         return FALSE;
1033     }
1034     ClosePrinter(hprn);
1035
1036     PRINTDLG_UpdatePrinterInfoTextsW(hDlg, PrintStructures->lpPrinterInfo);
1037
1038     HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
1039     PrintStructures->lpDevMode = NULL;
1040
1041     dmSize = DocumentPropertiesW(0, 0, name, NULL, NULL, 0);
1042     if(dmSize == -1) {
1043         ERR("DocumentProperties fails on %s\n", debugstr_w(name));
1044         return FALSE;
1045     }
1046     PrintStructures->lpDevMode = HeapAlloc(GetProcessHeap(), 0, dmSize);
1047     dmSize = DocumentPropertiesW(0, 0, name, PrintStructures->lpDevMode, NULL,
1048                                  DM_OUT_BUFFER);
1049     if(lppd->hDevMode && (lpdm = GlobalLock(lppd->hDevMode)) &&
1050                           !lstrcmpW(lpdm->dmDeviceName,
1051                                   PrintStructures->lpDevMode->dmDeviceName)) {
1052       /* Supplied devicemode matches current printer so try to use it */
1053         DocumentPropertiesW(0, 0, name, PrintStructures->lpDevMode, lpdm,
1054                             DM_OUT_BUFFER | DM_IN_BUFFER);
1055     }
1056     if(lpdm)
1057         GlobalUnlock(lppd->hDevMode);
1058
1059     lpdm = PrintStructures->lpDevMode;  /* use this as a shortcut */
1060
1061     if(!(lppd->Flags & PD_PRINTSETUP)) {
1062       /* Print range (All/Range/Selection) */
1063         SetDlgItemInt(hDlg, edt1, lppd->nFromPage, FALSE);
1064         SetDlgItemInt(hDlg, edt2, lppd->nToPage, FALSE);
1065         CheckRadioButton(hDlg, rad1, rad3, rad1);               /* default */
1066         if (lppd->Flags & PD_NOSELECTION)
1067             EnableWindow(GetDlgItem(hDlg, rad2), FALSE);
1068         else
1069             if (lppd->Flags & PD_SELECTION)
1070                 CheckRadioButton(hDlg, rad1, rad3, rad2);
1071         if (lppd->Flags & PD_NOPAGENUMS) {
1072             EnableWindow(GetDlgItem(hDlg, rad3), FALSE);
1073             EnableWindow(GetDlgItem(hDlg, stc2),FALSE);
1074             EnableWindow(GetDlgItem(hDlg, edt1), FALSE);
1075             EnableWindow(GetDlgItem(hDlg, stc3),FALSE);
1076             EnableWindow(GetDlgItem(hDlg, edt2), FALSE);
1077         } else {
1078             if (lppd->Flags & PD_PAGENUMS)
1079                 CheckRadioButton(hDlg, rad1, rad3, rad3);
1080         }
1081
1082         /* Collate pages
1083          *
1084          * FIXME: The ico3 is not displayed for some reason. I don't know why.
1085          */
1086         if (lppd->Flags & PD_COLLATE) {
1087             SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1088                                 (LPARAM)PrintStructures->hCollateIcon);
1089             CheckDlgButton(hDlg, chx2, 1);
1090         } else {
1091             SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1092                                 (LPARAM)PrintStructures->hNoCollateIcon);
1093             CheckDlgButton(hDlg, chx2, 0);
1094         }
1095
1096         if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
1097           /* if printer doesn't support it: no Collate */
1098             if (!(lpdm->dmFields & DM_COLLATE)) {
1099                 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1100                 EnableWindow(GetDlgItem(hDlg, ico3), FALSE);
1101             }
1102         }
1103
1104         /* nCopies */
1105         {
1106           INT copies;
1107           if (lppd->hDevMode == 0)
1108               copies = lppd->nCopies;
1109           else
1110               copies = lpdm->dmCopies;
1111           if(copies == 0) copies = 1;
1112           else if(copies < 0) copies = MAX_COPIES;
1113           SetDlgItemInt(hDlg, edt3, copies, FALSE);
1114         }
1115
1116         if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
1117           /* if printer doesn't support it: no nCopies */
1118             if (!(lpdm->dmFields & DM_COPIES)) {
1119                 EnableWindow(GetDlgItem(hDlg, edt3), FALSE);
1120                 EnableWindow(GetDlgItem(hDlg, stc5), FALSE);
1121             }
1122         }
1123
1124         /* print to file */
1125         CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0);
1126         if (lppd->Flags & PD_DISABLEPRINTTOFILE)
1127             EnableWindow(GetDlgItem(hDlg, chx1), FALSE);
1128         if (lppd->Flags & PD_HIDEPRINTTOFILE)
1129             ShowWindow(GetDlgItem(hDlg, chx1), SW_HIDE);
1130
1131     } else { /* PD_PRINTSETUP */
1132       BOOL bPortrait = (lpdm->u1.s1.dmOrientation == DMORIENT_PORTRAIT);
1133
1134       PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb2,
1135                                   PrintStructures->lpPrinterInfo->pPrinterName,
1136                                   PrintStructures->lpPrinterInfo->pPortName,
1137                                   lpdm);
1138       PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb3,
1139                                   PrintStructures->lpPrinterInfo->pPrinterName,
1140                                   PrintStructures->lpPrinterInfo->pPortName,
1141                                   lpdm);
1142       CheckRadioButton(hDlg, rad1, rad2, bPortrait ? rad1: rad2);
1143       SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1144                           (LPARAM)(bPortrait ? PrintStructures->hPortraitIcon :
1145                                    PrintStructures->hLandscapeIcon));
1146
1147     }
1148
1149     /* help button */
1150     if ((lppd->Flags & PD_SHOWHELP)==0) {
1151         /* hide if PD_SHOWHELP not specified */
1152         ShowWindow(GetDlgItem(hDlg, pshHelp), SW_HIDE);
1153     }
1154     return TRUE;
1155 }
1156
1157 /***********************************************************************
1158  *           PRINTDLG_WMInitDialog                      [internal]
1159  */
1160 static LRESULT PRINTDLG_WMInitDialog(HWND hDlg, WPARAM wParam,
1161                                      PRINT_PTRA* PrintStructures)
1162 {
1163     LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
1164     DEVNAMES *pdn;
1165     DEVMODEA *pdm;
1166     char *name = NULL;
1167     UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1168
1169     /* load Collate ICONs */
1170     /* We load these with LoadImage because they are not a standard
1171        size and we don't want them rescaled */
1172     PrintStructures->hCollateIcon =
1173       LoadImageA(COMDLG32_hInstance, "PD32_COLLATE", IMAGE_ICON, 0, 0, 0);
1174     PrintStructures->hNoCollateIcon =
1175       LoadImageA(COMDLG32_hInstance, "PD32_NOCOLLATE", IMAGE_ICON, 0, 0, 0);
1176
1177     /* These can be done with LoadIcon */
1178     PrintStructures->hPortraitIcon =
1179       LoadIconA(COMDLG32_hInstance, "PD32_PORTRAIT");
1180     PrintStructures->hLandscapeIcon =
1181       LoadIconA(COMDLG32_hInstance, "PD32_LANDSCAPE");
1182
1183     /* display the collate/no_collate icon */
1184     SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1185                         (LPARAM)PrintStructures->hNoCollateIcon);
1186
1187     if(PrintStructures->hCollateIcon == 0 ||
1188        PrintStructures->hNoCollateIcon == 0 ||
1189        PrintStructures->hPortraitIcon == 0 ||
1190        PrintStructures->hLandscapeIcon == 0) {
1191         ERR("no icon in resourcefile\n");
1192         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1193         EndDialog(hDlg, FALSE);
1194     }
1195
1196     /*
1197      * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
1198      * must be registered and the Help button must be shown.
1199      */
1200     if (lppd->Flags & PD_SHOWHELP) {
1201         if((PrintStructures->HelpMessageID =
1202             RegisterWindowMessageA(HELPMSGSTRINGA)) == 0) {
1203             COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
1204             return FALSE;
1205         }
1206     } else
1207         PrintStructures->HelpMessageID = 0;
1208
1209     if(!(lppd->Flags &PD_PRINTSETUP)) {
1210         PrintStructures->hwndUpDown =
1211           CreateUpDownControl(WS_CHILD | WS_VISIBLE | WS_BORDER |
1212                               UDS_NOTHOUSANDS | UDS_ARROWKEYS |
1213                               UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 0, 0, 0, 0,
1214                               hDlg, UPDOWN_ID, COMDLG32_hInstance,
1215                               GetDlgItem(hDlg, edt3), MAX_COPIES, 1, 1);
1216     }
1217
1218     /* FIXME: I allow more freedom than either Win95 or WinNT,
1219      *        which do not agree to what errors should be thrown or not
1220      *        in case nToPage or nFromPage is out-of-range.
1221      */
1222     if (lppd->nMaxPage < lppd->nMinPage)
1223         lppd->nMaxPage = lppd->nMinPage;
1224     if (lppd->nMinPage == lppd->nMaxPage)
1225         lppd->Flags |= PD_NOPAGENUMS;
1226     if (lppd->nToPage < lppd->nMinPage)
1227         lppd->nToPage = lppd->nMinPage;
1228     if (lppd->nToPage > lppd->nMaxPage)
1229         lppd->nToPage = lppd->nMaxPage;
1230     if (lppd->nFromPage < lppd->nMinPage)
1231         lppd->nFromPage = lppd->nMinPage;
1232     if (lppd->nFromPage > lppd->nMaxPage)
1233         lppd->nFromPage = lppd->nMaxPage;
1234
1235     /* if we have the combo box, fill it */
1236     if (GetDlgItem(hDlg,comboID)) {
1237         /* Fill Combobox
1238          */
1239         pdn = GlobalLock(lppd->hDevNames);
1240         pdm = GlobalLock(lppd->hDevMode);
1241         if(pdn)
1242             name = (char*)pdn + pdn->wDeviceOffset;
1243         else if(pdm)
1244             name = pdm->dmDeviceName;
1245         PRINTDLG_SetUpPrinterListComboA(hDlg, comboID, name);
1246         if(pdm) GlobalUnlock(lppd->hDevMode);
1247         if(pdn) GlobalUnlock(lppd->hDevNames);
1248
1249         /* Now find selected printer and update rest of dlg */
1250         name = HeapAlloc(GetProcessHeap(),0,256);
1251         if (GetDlgItemTextA(hDlg, comboID, name, 255))
1252             PRINTDLG_ChangePrinterA(hDlg, name, PrintStructures);
1253         HeapFree(GetProcessHeap(),0,name);
1254     } else {
1255         /* else use default printer */
1256         char name[200];
1257         DWORD dwBufLen = sizeof(name);
1258         BOOL ret = GetDefaultPrinterA(name, &dwBufLen);
1259
1260         if (ret)
1261             PRINTDLG_ChangePrinterA(hDlg, name, PrintStructures);
1262         else
1263             FIXME("No default printer found, expect problems!\n");
1264     }
1265     return TRUE;
1266 }
1267
1268 static LRESULT PRINTDLG_WMInitDialogW(HWND hDlg, WPARAM wParam,
1269                                      PRINT_PTRW* PrintStructures)
1270 {
1271     const static WCHAR PD32_COLLATE[] = { 'P', 'D', '3', '2', '_', 'C', 'O', 'L', 'L', 'A', 'T', 'E', 0 };
1272     const static WCHAR PD32_NOCOLLATE[] = { 'P', 'D', '3', '2', '_', 'N', 'O', 'C', 'O', 'L', 'L', 'A', 'T', 'E', 0 };
1273     const static WCHAR PD32_PORTRAIT[] = { 'P', 'D', '3', '2', '_', 'P', 'O', 'R', 'T', 'R', 'A', 'I', 'T', 0 };
1274     const static WCHAR PD32_LANDSCAPE[] = { 'P', 'D', '3', '2', '_', 'L', 'A', 'N', 'D', 'S', 'C', 'A', 'P', 'E', 0 };
1275     LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
1276     DEVNAMES *pdn;
1277     DEVMODEW *pdm;
1278     WCHAR *name = NULL;
1279     UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1280
1281     /* load Collate ICONs */
1282     /* We load these with LoadImage because they are not a standard
1283        size and we don't want them rescaled */
1284     PrintStructures->hCollateIcon =
1285       LoadImageW(COMDLG32_hInstance, PD32_COLLATE, IMAGE_ICON, 0, 0, 0);
1286     PrintStructures->hNoCollateIcon =
1287       LoadImageW(COMDLG32_hInstance, PD32_NOCOLLATE, IMAGE_ICON, 0, 0, 0);
1288
1289     /* These can be done with LoadIcon */
1290     PrintStructures->hPortraitIcon =
1291       LoadIconW(COMDLG32_hInstance, PD32_PORTRAIT);
1292     PrintStructures->hLandscapeIcon =
1293       LoadIconW(COMDLG32_hInstance, PD32_LANDSCAPE);
1294
1295     /* display the collate/no_collate icon */
1296     SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1297                         (LPARAM)PrintStructures->hNoCollateIcon);
1298
1299     if(PrintStructures->hCollateIcon == 0 ||
1300        PrintStructures->hNoCollateIcon == 0 ||
1301        PrintStructures->hPortraitIcon == 0 ||
1302        PrintStructures->hLandscapeIcon == 0) {
1303         ERR("no icon in resourcefile\n");
1304         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1305         EndDialog(hDlg, FALSE);
1306     }
1307
1308     /*
1309      * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
1310      * must be registered and the Help button must be shown.
1311      */
1312     if (lppd->Flags & PD_SHOWHELP) {
1313         if((PrintStructures->HelpMessageID =
1314             RegisterWindowMessageW(HELPMSGSTRINGW)) == 0) {
1315             COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
1316             return FALSE;
1317         }
1318     } else
1319         PrintStructures->HelpMessageID = 0;
1320
1321     if(!(lppd->Flags &PD_PRINTSETUP)) {
1322         PrintStructures->hwndUpDown =
1323           CreateUpDownControl(WS_CHILD | WS_VISIBLE | WS_BORDER |
1324                               UDS_NOTHOUSANDS | UDS_ARROWKEYS |
1325                               UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 0, 0, 0, 0,
1326                               hDlg, UPDOWN_ID, COMDLG32_hInstance,
1327                               GetDlgItem(hDlg, edt3), MAX_COPIES, 1, 1);
1328     }
1329
1330     /* FIXME: I allow more freedom than either Win95 or WinNT,
1331      *        which do not agree to what errors should be thrown or not
1332      *        in case nToPage or nFromPage is out-of-range.
1333      */
1334     if (lppd->nMaxPage < lppd->nMinPage)
1335         lppd->nMaxPage = lppd->nMinPage;
1336     if (lppd->nMinPage == lppd->nMaxPage)
1337         lppd->Flags |= PD_NOPAGENUMS;
1338     if (lppd->nToPage < lppd->nMinPage)
1339         lppd->nToPage = lppd->nMinPage;
1340     if (lppd->nToPage > lppd->nMaxPage)
1341         lppd->nToPage = lppd->nMaxPage;
1342     if (lppd->nFromPage < lppd->nMinPage)
1343         lppd->nFromPage = lppd->nMinPage;
1344     if (lppd->nFromPage > lppd->nMaxPage)
1345         lppd->nFromPage = lppd->nMaxPage;
1346
1347     /* if we have the combo box, fill it */
1348     if (GetDlgItem(hDlg,comboID)) {
1349         /* Fill Combobox
1350          */
1351         pdn = GlobalLock(lppd->hDevNames);
1352         pdm = GlobalLock(lppd->hDevMode);
1353         if(pdn)
1354             name = (WCHAR*)pdn + pdn->wDeviceOffset;
1355         else if(pdm)
1356             name = pdm->dmDeviceName;
1357         PRINTDLG_SetUpPrinterListComboW(hDlg, comboID, name);
1358         if(pdm) GlobalUnlock(lppd->hDevMode);
1359         if(pdn) GlobalUnlock(lppd->hDevNames);
1360
1361         /* Now find selected printer and update rest of dlg */
1362         /* ansi is ok here */
1363         name = HeapAlloc(GetProcessHeap(),0,256*sizeof(WCHAR));
1364         if (GetDlgItemTextW(hDlg, comboID, name, 255))
1365             PRINTDLG_ChangePrinterW(hDlg, name, PrintStructures);
1366         HeapFree(GetProcessHeap(),0,name);
1367     } else {
1368         /* else use default printer */
1369         WCHAR name[200];
1370         DWORD dwBufLen = sizeof(name) / sizeof(WCHAR);
1371         BOOL ret = GetDefaultPrinterW(name, &dwBufLen);
1372
1373         if (ret)
1374             PRINTDLG_ChangePrinterW(hDlg, name, PrintStructures);
1375         else
1376             FIXME("No default printer found, expect problems!\n");
1377     }
1378     return TRUE;
1379 }
1380
1381 /***********************************************************************
1382  *                              PRINTDLG_WMCommand               [internal]
1383  */
1384 LRESULT PRINTDLG_WMCommandA(HWND hDlg, WPARAM wParam,
1385                         LPARAM lParam, PRINT_PTRA* PrintStructures)
1386 {
1387     LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
1388     UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1389     LPDEVMODEA lpdm = PrintStructures->lpDevMode;
1390
1391     switch (LOWORD(wParam))  {
1392     case IDOK:
1393         TRACE(" OK button was hit\n");
1394         if (!PRINTDLG_UpdatePrintDlgA(hDlg, PrintStructures)) {
1395             FIXME("Update printdlg was not successful!\n");
1396             return(FALSE);
1397         }
1398         EndDialog(hDlg, TRUE);
1399         return(TRUE);
1400
1401     case IDCANCEL:
1402         TRACE(" CANCEL button was hit\n");
1403         EndDialog(hDlg, FALSE);
1404         return(FALSE);
1405
1406      case pshHelp:
1407         TRACE(" HELP button was hit\n");
1408         SendMessageA(lppd->hwndOwner, PrintStructures->HelpMessageID,
1409                                 (WPARAM) hDlg, (LPARAM) lppd);
1410         break;
1411
1412      case chx2:                         /* collate pages checkbox */
1413         if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
1414             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1415                                     (LPARAM)PrintStructures->hCollateIcon);
1416         else
1417             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1418                                     (LPARAM)PrintStructures->hNoCollateIcon);
1419         break;
1420      case edt1:                         /* from page nr editbox */
1421      case edt2:                         /* to page nr editbox */
1422         if (HIWORD(wParam)==EN_CHANGE) {
1423             WORD nToPage;
1424             WORD nFromPage;
1425             nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
1426             nToPage   = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
1427             if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
1428                 CheckRadioButton(hDlg, rad1, rad3, rad3);
1429         }
1430         break;
1431
1432     case edt3:
1433         if(HIWORD(wParam) == EN_CHANGE) {
1434             INT copies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
1435             if(copies <= 1)
1436                 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1437             else
1438                 EnableWindow(GetDlgItem(hDlg, chx2), TRUE);
1439         }
1440         break;
1441
1442 #if 0
1443      case psh1:                       /* Print Setup */
1444         {
1445             PRINTDLG16  pdlg;
1446
1447             if (!PrintStructures->dlg.lpPrintDlg16) {
1448                 FIXME("The 32bit print dialog does not have this button!?\n");
1449                 break;
1450             }
1451
1452             memcpy(&pdlg,PrintStructures->dlg.lpPrintDlg16,sizeof(pdlg));
1453             pdlg.Flags |= PD_PRINTSETUP;
1454             pdlg.hwndOwner = HWND_16(hDlg);
1455             if (!PrintDlg16(&pdlg))
1456                 break;
1457         }
1458         break;
1459 #endif
1460      case psh2:                       /* Properties button */
1461        {
1462          HANDLE hPrinter;
1463          char   PrinterName[256];
1464
1465          GetDlgItemTextA(hDlg, PrinterComboID, PrinterName, 255);
1466          if (!OpenPrinterA(PrinterName, &hPrinter, NULL)) {
1467              FIXME(" Call to OpenPrinter did not succeed!\n");
1468              break;
1469          }
1470          DocumentPropertiesA(hDlg, hPrinter, PrinterName,
1471                              PrintStructures->lpDevMode,
1472                              PrintStructures->lpDevMode,
1473                              DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
1474          ClosePrinter(hPrinter);
1475          break;
1476        }
1477
1478     case rad1: /* Paperorientation */
1479         if (lppd->Flags & PD_PRINTSETUP)
1480         {
1481               lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1482               SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1483                           (LPARAM)(PrintStructures->hPortraitIcon));
1484         }
1485         break;
1486
1487     case rad2: /* Paperorientation */
1488         if (lppd->Flags & PD_PRINTSETUP)
1489         {
1490               lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1491               SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1492                           (LPARAM)(PrintStructures->hLandscapeIcon));
1493         }
1494         break;
1495
1496     case cmb1: /* Printer Combobox in PRINT SETUP, quality combobox in PRINT */
1497          if (PrinterComboID != LOWORD(wParam)) {
1498              FIXME("No handling for print quality combo box yet.\n");
1499              break;
1500          }
1501          /* FALLTHROUGH */
1502     case cmb4:                         /* Printer combobox */
1503          if (HIWORD(wParam)==CBN_SELCHANGE) {
1504              char   PrinterName[256];
1505              GetDlgItemTextA(hDlg, LOWORD(wParam), PrinterName, 255);
1506              PRINTDLG_ChangePrinterA(hDlg, PrinterName, PrintStructures);
1507          }
1508          break;
1509
1510     case cmb2: /* Papersize */
1511       {
1512           DWORD Sel = SendDlgItemMessageA(hDlg, cmb2, CB_GETCURSEL, 0, 0);
1513           if(Sel != CB_ERR)
1514               lpdm->u1.s1.dmPaperSize = SendDlgItemMessageA(hDlg, cmb2,
1515                                                             CB_GETITEMDATA,
1516                                                             Sel, 0);
1517       }
1518       break;
1519
1520     case cmb3: /* Bin */
1521       {
1522           DWORD Sel = SendDlgItemMessageA(hDlg, cmb3, CB_GETCURSEL, 0, 0);
1523           if(Sel != CB_ERR)
1524               lpdm->dmDefaultSource = SendDlgItemMessageA(hDlg, cmb3,
1525                                                           CB_GETITEMDATA, Sel,
1526                                                           0);
1527       }
1528       break;
1529     }
1530     if(lppd->Flags & PD_PRINTSETUP) {
1531         switch (LOWORD(wParam)) {
1532         case rad1:                         /* orientation */
1533         case rad2:
1534             if (IsDlgButtonChecked(hDlg, rad1) == BST_CHECKED) {
1535                 if(lpdm->u1.s1.dmOrientation != DMORIENT_PORTRAIT) {
1536                     lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1537                     SendDlgItemMessageA(hDlg, stc10, STM_SETIMAGE,
1538                                         (WPARAM)IMAGE_ICON,
1539                                         (LPARAM)PrintStructures->hPortraitIcon);
1540                     SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE,
1541                                         (WPARAM)IMAGE_ICON,
1542                                         (LPARAM)PrintStructures->hPortraitIcon);
1543                 }
1544             } else {
1545                 if(lpdm->u1.s1.dmOrientation != DMORIENT_LANDSCAPE) {
1546                     lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1547                     SendDlgItemMessageA(hDlg, stc10, STM_SETIMAGE,
1548                                         (WPARAM)IMAGE_ICON,
1549                                         (LPARAM)PrintStructures->hLandscapeIcon);
1550                     SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE,
1551                                         (WPARAM)IMAGE_ICON,
1552                                         (LPARAM)PrintStructures->hLandscapeIcon);
1553                 }
1554             }
1555             break;
1556         }
1557     }
1558     return FALSE;
1559 }
1560
1561 static LRESULT PRINTDLG_WMCommandW(HWND hDlg, WPARAM wParam,
1562                         LPARAM lParam, PRINT_PTRW* PrintStructures)
1563 {
1564     LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
1565     UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1566     LPDEVMODEW lpdm = PrintStructures->lpDevMode;
1567
1568     switch (LOWORD(wParam))  {
1569     case IDOK:
1570         TRACE(" OK button was hit\n");
1571         if (!PRINTDLG_UpdatePrintDlgW(hDlg, PrintStructures)) {
1572             FIXME("Update printdlg was not successful!\n");
1573             return(FALSE);
1574         }
1575         EndDialog(hDlg, TRUE);
1576         return(TRUE);
1577
1578     case IDCANCEL:
1579         TRACE(" CANCEL button was hit\n");
1580         EndDialog(hDlg, FALSE);
1581         return(FALSE);
1582
1583      case pshHelp:
1584         TRACE(" HELP button was hit\n");
1585         SendMessageW(lppd->hwndOwner, PrintStructures->HelpMessageID,
1586                                 (WPARAM) hDlg, (LPARAM) lppd);
1587         break;
1588
1589      case chx2:                         /* collate pages checkbox */
1590         if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
1591             SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1592                                     (LPARAM)PrintStructures->hCollateIcon);
1593         else
1594             SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1595                                     (LPARAM)PrintStructures->hNoCollateIcon);
1596         break;
1597      case edt1:                         /* from page nr editbox */
1598      case edt2:                         /* to page nr editbox */
1599         if (HIWORD(wParam)==EN_CHANGE) {
1600             WORD nToPage;
1601             WORD nFromPage;
1602             nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
1603             nToPage   = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
1604             if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
1605                 CheckRadioButton(hDlg, rad1, rad3, rad3);
1606         }
1607         break;
1608
1609     case edt3:
1610         if(HIWORD(wParam) == EN_CHANGE) {
1611             INT copies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
1612             if(copies <= 1)
1613                 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1614             else
1615                 EnableWindow(GetDlgItem(hDlg, chx2), TRUE);
1616         }
1617         break;
1618
1619      case psh1:                       /* Print Setup */
1620         {
1621                 ERR("psh1 is called from 16bit code only, we should not get here.\n");
1622         }
1623         break;
1624      case psh2:                       /* Properties button */
1625        {
1626          HANDLE hPrinter;
1627          WCHAR  PrinterName[256];
1628
1629          if (!GetDlgItemTextW(hDlg, PrinterComboID, PrinterName, 255)) break;
1630          if (!OpenPrinterW(PrinterName, &hPrinter, NULL)) {
1631              FIXME(" Call to OpenPrinter did not succeed!\n");
1632              break;
1633          }
1634          DocumentPropertiesW(hDlg, hPrinter, PrinterName,
1635                              PrintStructures->lpDevMode,
1636                              PrintStructures->lpDevMode,
1637                              DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
1638          ClosePrinter(hPrinter);
1639          break;
1640        }
1641
1642     case rad1: /* Paperorientation */
1643         if (lppd->Flags & PD_PRINTSETUP)
1644         {
1645               lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1646               SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1647                           (LPARAM)(PrintStructures->hPortraitIcon));
1648         }
1649         break;
1650
1651     case rad2: /* Paperorientation */
1652         if (lppd->Flags & PD_PRINTSETUP)
1653         {
1654               lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1655               SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1656                           (LPARAM)(PrintStructures->hLandscapeIcon));
1657         }
1658         break;
1659
1660     case cmb1: /* Printer Combobox in PRINT SETUP, quality combobox in PRINT */
1661          if (PrinterComboID != LOWORD(wParam)) {
1662              FIXME("No handling for print quality combo box yet.\n");
1663              break;
1664          }
1665          /* FALLTHROUGH */
1666     case cmb4:                         /* Printer combobox */
1667          if (HIWORD(wParam)==CBN_SELCHANGE) {
1668              WCHAR   PrinterName[256];
1669              GetDlgItemTextW(hDlg, LOWORD(wParam), PrinterName, 255);
1670              PRINTDLG_ChangePrinterW(hDlg, PrinterName, PrintStructures);
1671          }
1672          break;
1673
1674     case cmb2: /* Papersize */
1675       {
1676           DWORD Sel = SendDlgItemMessageW(hDlg, cmb2, CB_GETCURSEL, 0, 0);
1677           if(Sel != CB_ERR)
1678               lpdm->u1.s1.dmPaperSize = SendDlgItemMessageW(hDlg, cmb2,
1679                                                             CB_GETITEMDATA,
1680                                                             Sel, 0);
1681       }
1682       break;
1683
1684     case cmb3: /* Bin */
1685       {
1686           DWORD Sel = SendDlgItemMessageW(hDlg, cmb3, CB_GETCURSEL, 0, 0);
1687           if(Sel != CB_ERR)
1688               lpdm->dmDefaultSource = SendDlgItemMessageW(hDlg, cmb3,
1689                                                           CB_GETITEMDATA, Sel,
1690                                                           0);
1691       }
1692       break;
1693     }
1694     if(lppd->Flags & PD_PRINTSETUP) {
1695         switch (LOWORD(wParam)) {
1696         case rad1:                         /* orientation */
1697         case rad2:
1698             if (IsDlgButtonChecked(hDlg, rad1) == BST_CHECKED) {
1699                 if(lpdm->u1.s1.dmOrientation != DMORIENT_PORTRAIT) {
1700                     lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1701                     SendDlgItemMessageW(hDlg, stc10, STM_SETIMAGE,
1702                                         (WPARAM)IMAGE_ICON,
1703                                         (LPARAM)PrintStructures->hPortraitIcon);
1704                     SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE,
1705                                         (WPARAM)IMAGE_ICON,
1706                                         (LPARAM)PrintStructures->hPortraitIcon);
1707                 }
1708             } else {
1709                 if(lpdm->u1.s1.dmOrientation != DMORIENT_LANDSCAPE) {
1710                     lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1711                     SendDlgItemMessageW(hDlg, stc10, STM_SETIMAGE,
1712                                         (WPARAM)IMAGE_ICON,
1713                                         (LPARAM)PrintStructures->hLandscapeIcon);
1714                     SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE,
1715                                         (WPARAM)IMAGE_ICON,
1716                                         (LPARAM)PrintStructures->hLandscapeIcon);
1717                 }
1718             }
1719             break;
1720         }
1721     }
1722     return FALSE;
1723 }
1724
1725 /***********************************************************************
1726  *           PrintDlgProcA                      [internal]
1727  */
1728 static INT_PTR CALLBACK PrintDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam,
1729                                       LPARAM lParam)
1730 {
1731     PRINT_PTRA* PrintStructures;
1732     INT_PTR res = FALSE;
1733
1734     if (uMsg!=WM_INITDIALOG) {
1735         PrintStructures = (PRINT_PTRA*)GetPropA(hDlg,"__WINE_PRINTDLGDATA");
1736         if (!PrintStructures)
1737             return FALSE;
1738     } else {
1739         PrintStructures = (PRINT_PTRA*) lParam;
1740         SetPropA(hDlg,"__WINE_PRINTDLGDATA",PrintStructures);
1741         res = PRINTDLG_WMInitDialog(hDlg, wParam, PrintStructures);
1742
1743         if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK)
1744             res = PrintStructures->lpPrintDlg->lpfnPrintHook(
1745                 hDlg, uMsg, wParam, (LPARAM)PrintStructures->lpPrintDlg
1746             );
1747         return res;
1748     }
1749
1750     if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) {
1751         res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg,uMsg,wParam,
1752                                                          lParam);
1753         if(res) return res;
1754     }
1755
1756     switch (uMsg) {
1757     case WM_COMMAND:
1758         return PRINTDLG_WMCommandA(hDlg, wParam, lParam, PrintStructures);
1759
1760     case WM_DESTROY:
1761         DestroyIcon(PrintStructures->hCollateIcon);
1762         DestroyIcon(PrintStructures->hNoCollateIcon);
1763         DestroyIcon(PrintStructures->hPortraitIcon);
1764         DestroyIcon(PrintStructures->hLandscapeIcon);
1765         if(PrintStructures->hwndUpDown)
1766             DestroyWindow(PrintStructures->hwndUpDown);
1767         return FALSE;
1768     }
1769     return res;
1770 }
1771
1772 static INT_PTR CALLBACK PrintDlgProcW(HWND hDlg, UINT uMsg, WPARAM wParam,
1773                                       LPARAM lParam)
1774 {
1775     static const WCHAR propW[] = {'_','_','W','I','N','E','_','P','R','I','N','T','D','L','G','D','A','T','A',0};
1776     PRINT_PTRW* PrintStructures;
1777     INT_PTR res = FALSE;
1778
1779     if (uMsg!=WM_INITDIALOG) {
1780         PrintStructures = (PRINT_PTRW*) GetPropW(hDlg, propW);
1781         if (!PrintStructures)
1782             return FALSE;
1783     } else {
1784         PrintStructures = (PRINT_PTRW*) lParam;
1785         SetPropW(hDlg, propW, PrintStructures);
1786         res = PRINTDLG_WMInitDialogW(hDlg, wParam, PrintStructures);
1787
1788         if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK)
1789             res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg, uMsg, wParam, (LPARAM)PrintStructures->lpPrintDlg);
1790         return res;
1791     }
1792
1793     if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) {
1794         res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg,uMsg,wParam, lParam);
1795         if(res) return res;
1796     }
1797
1798     switch (uMsg) {
1799     case WM_COMMAND:
1800         return PRINTDLG_WMCommandW(hDlg, wParam, lParam, PrintStructures);
1801
1802     case WM_DESTROY:
1803         DestroyIcon(PrintStructures->hCollateIcon);
1804         DestroyIcon(PrintStructures->hNoCollateIcon);
1805         DestroyIcon(PrintStructures->hPortraitIcon);
1806         DestroyIcon(PrintStructures->hLandscapeIcon);
1807         if(PrintStructures->hwndUpDown)
1808             DestroyWindow(PrintStructures->hwndUpDown);
1809         return FALSE;
1810     }
1811     return res;
1812 }
1813
1814 /************************************************************
1815  *
1816  *      PRINTDLG_GetDlgTemplate
1817  *
1818  */
1819 static HGLOBAL PRINTDLG_GetDlgTemplateA(PRINTDLGA *lppd)
1820 {
1821     HRSRC hResInfo;
1822     HGLOBAL hDlgTmpl;
1823
1824     if (lppd->Flags & PD_PRINTSETUP) {
1825         if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
1826             hDlgTmpl = lppd->hSetupTemplate;
1827         } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {
1828             hResInfo = FindResourceA(lppd->hInstance,
1829                                      lppd->lpSetupTemplateName, (LPSTR)RT_DIALOG);
1830             hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
1831         } else {
1832             hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32_SETUP",
1833                                      (LPSTR)RT_DIALOG);
1834             hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
1835         }
1836     } else {
1837         if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
1838             hDlgTmpl = lppd->hPrintTemplate;
1839         } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
1840             hResInfo = FindResourceA(lppd->hInstance,
1841                                      lppd->lpPrintTemplateName,
1842                                      (LPSTR)RT_DIALOG);
1843             hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
1844         } else {
1845             hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32",
1846                                      (LPSTR)RT_DIALOG);
1847             hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
1848         }
1849     }
1850     return hDlgTmpl;
1851 }
1852
1853 static HGLOBAL PRINTDLG_GetDlgTemplateW(PRINTDLGW *lppd)
1854 {
1855     HRSRC hResInfo;
1856     HGLOBAL hDlgTmpl;
1857     static const WCHAR xpsetup[] = { 'P','R','I','N','T','3','2','_','S','E','T','U','P',0};
1858     static const WCHAR xprint[] = { 'P','R','I','N','T','3','2',0};
1859
1860     if (lppd->Flags & PD_PRINTSETUP) {
1861         if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
1862             hDlgTmpl = lppd->hSetupTemplate;
1863         } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {
1864             hResInfo = FindResourceW(lppd->hInstance,
1865                                      lppd->lpSetupTemplateName, (LPWSTR)RT_DIALOG);
1866             hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
1867         } else {
1868             hResInfo = FindResourceW(COMDLG32_hInstance, xpsetup, (LPWSTR)RT_DIALOG);
1869             hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
1870         }
1871     } else {
1872         if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
1873             hDlgTmpl = lppd->hPrintTemplate;
1874         } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
1875             hResInfo = FindResourceW(lppd->hInstance,
1876                                      lppd->lpPrintTemplateName,
1877                                      (LPWSTR)RT_DIALOG);
1878             hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
1879         } else {
1880             hResInfo = FindResourceW(COMDLG32_hInstance, xprint, (LPWSTR)RT_DIALOG);
1881             hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
1882         }
1883     }
1884     return hDlgTmpl;
1885 }
1886
1887 /***********************************************************************
1888  *
1889  *      PRINTDLG_CreateDC
1890  *
1891  */
1892 static BOOL PRINTDLG_CreateDCA(LPPRINTDLGA lppd)
1893 {
1894     DEVNAMES *pdn = GlobalLock(lppd->hDevNames);
1895     DEVMODEA *pdm = GlobalLock(lppd->hDevMode);
1896
1897     if(lppd->Flags & PD_RETURNDC) {
1898         lppd->hDC = CreateDCA((char*)pdn + pdn->wDriverOffset,
1899                               (char*)pdn + pdn->wDeviceOffset,
1900                               (char*)pdn + pdn->wOutputOffset,
1901                               pdm );
1902     } else if(lppd->Flags & PD_RETURNIC) {
1903         lppd->hDC = CreateICA((char*)pdn + pdn->wDriverOffset,
1904                               (char*)pdn + pdn->wDeviceOffset,
1905                               (char*)pdn + pdn->wOutputOffset,
1906                               pdm );
1907     }
1908     GlobalUnlock(lppd->hDevNames);
1909     GlobalUnlock(lppd->hDevMode);
1910     return lppd->hDC ? TRUE : FALSE;
1911 }
1912
1913 static BOOL PRINTDLG_CreateDCW(LPPRINTDLGW lppd)
1914 {
1915     DEVNAMES *pdn = GlobalLock(lppd->hDevNames);
1916     DEVMODEW *pdm = GlobalLock(lppd->hDevMode);
1917
1918     if(lppd->Flags & PD_RETURNDC) {
1919         lppd->hDC = CreateDCW((WCHAR*)pdn + pdn->wDriverOffset,
1920                               (WCHAR*)pdn + pdn->wDeviceOffset,
1921                               (WCHAR*)pdn + pdn->wOutputOffset,
1922                               pdm );
1923     } else if(lppd->Flags & PD_RETURNIC) {
1924         lppd->hDC = CreateICW((WCHAR*)pdn + pdn->wDriverOffset,
1925                               (WCHAR*)pdn + pdn->wDeviceOffset,
1926                               (WCHAR*)pdn + pdn->wOutputOffset,
1927                               pdm );
1928     }
1929     GlobalUnlock(lppd->hDevNames);
1930     GlobalUnlock(lppd->hDevMode);
1931     return lppd->hDC ? TRUE : FALSE;
1932 }
1933
1934 /***********************************************************************
1935  *           PrintDlgA   (COMDLG32.@)
1936  *
1937  *  Displays the the PRINT dialog box, which enables the user to specify
1938  *  specific properties of the print job.
1939  *
1940  * RETURNS
1941  *  nonzero if the user pressed the OK button
1942  *  zero    if the user cancelled the window or an error occurred
1943  *
1944  * BUGS
1945  *  PrintDlg:
1946  *  * The Collate Icons do not display, even though they are in the code.
1947  *  * The Properties Button(s) should call DocumentPropertiesA().
1948  */
1949
1950 BOOL WINAPI PrintDlgA(
1951                       LPPRINTDLGA lppd /* [in/out] ptr to PRINTDLG32 struct */
1952                       )
1953 {
1954     BOOL      bRet = FALSE;
1955     LPVOID   ptr;
1956     HINSTANCE hInst = (HINSTANCE)GetWindowLongPtrA( lppd->hwndOwner, GWLP_HINSTANCE );
1957
1958     if(TRACE_ON(commdlg)) {
1959         char flagstr[1000] = "";
1960         struct pd_flags *pflag = pd_flags;
1961         for( ; pflag->name; pflag++) {
1962             if(lppd->Flags & pflag->flag)
1963                 strcat(flagstr, pflag->name);
1964         }
1965         TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
1966               "pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
1967               "flags %08lx (%s)\n",
1968               lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
1969               lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
1970               lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
1971     }
1972
1973     if(lppd->lStructSize != sizeof(PRINTDLGA)) {
1974         WARN("structure size failure !!!\n");
1975         COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
1976         return FALSE;
1977     }
1978
1979     if(lppd->Flags & PD_RETURNDEFAULT) {
1980         PRINTER_INFO_2A *pbuf;
1981         DRIVER_INFO_3A  *dbuf;
1982         HANDLE hprn;
1983         DWORD needed;
1984
1985         if(lppd->hDevMode || lppd->hDevNames) {
1986             WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
1987             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
1988             return FALSE;
1989         }
1990         if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
1991             WARN("Can't find default printer\n");
1992             COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
1993             return FALSE;
1994         }
1995
1996         GetPrinterA(hprn, 2, NULL, 0, &needed);
1997         pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
1998         GetPrinterA(hprn, 2, (LPBYTE)pbuf, needed, &needed);
1999
2000         GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
2001         dbuf = HeapAlloc(GetProcessHeap(),0,needed);
2002         if (!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) {
2003             ERR("GetPrinterDriverA failed, le %ld, fix your config for printer %s!\n",GetLastError(),pbuf->pPrinterName);
2004             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2005             return FALSE;
2006         }
2007         ClosePrinter(hprn);
2008
2009         PRINTDLG_CreateDevNames(&(lppd->hDevNames),
2010                                   dbuf->pDriverPath,
2011                                   pbuf->pPrinterName,
2012                                   pbuf->pPortName);
2013         lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
2014                                      pbuf->pDevMode->dmDriverExtra);
2015         ptr = GlobalLock(lppd->hDevMode);
2016         memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
2017                pbuf->pDevMode->dmDriverExtra);
2018         GlobalUnlock(lppd->hDevMode);
2019         HeapFree(GetProcessHeap(), 0, pbuf);
2020         HeapFree(GetProcessHeap(), 0, dbuf);
2021         bRet = TRUE;
2022     } else {
2023         HGLOBAL hDlgTmpl;
2024         PRINT_PTRA *PrintStructures;
2025
2026     /* load Dialog resources,
2027      * depending on Flags indicates Print32 or Print32_setup dialog
2028      */
2029         hDlgTmpl = PRINTDLG_GetDlgTemplateA(lppd);
2030         if (!hDlgTmpl) {
2031             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2032             return FALSE;
2033         }
2034         ptr = LockResource( hDlgTmpl );
2035         if (!ptr) {
2036             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2037             return FALSE;
2038         }
2039
2040         PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2041                                     sizeof(PRINT_PTRA));
2042         PrintStructures->lpPrintDlg = lppd;
2043
2044         /* and create & process the dialog .
2045          * -1 is failure, 0 is broken hwnd, everything else is ok.
2046          */
2047         bRet = (0<DialogBoxIndirectParamA(hInst, ptr, lppd->hwndOwner,
2048                                            PrintDlgProcA,
2049                                            (LPARAM)PrintStructures));
2050
2051         if(bRet) {
2052             DEVMODEA *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
2053             PRINTER_INFO_2A *pi = PrintStructures->lpPrinterInfo;
2054             DRIVER_INFO_3A *di = PrintStructures->lpDriverInfo;
2055
2056             if (lppd->hDevMode == 0) {
2057                 TRACE(" No hDevMode yet... Need to create my own\n");
2058                 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE,
2059                                         lpdm->dmSize + lpdm->dmDriverExtra);
2060             } else {
2061                 WORD locks;
2062                 if((locks = (GlobalFlags(lppd->hDevMode) & GMEM_LOCKCOUNT))) {
2063                     WARN("hDevMode has %d locks on it. Unlocking it now\n", locks);
2064                     while(locks--) {
2065                         GlobalUnlock(lppd->hDevMode);
2066                         TRACE("Now got %d locks\n", locks);
2067                     }
2068                 }
2069                 lppd->hDevMode = GlobalReAlloc(lppd->hDevMode,
2070                                                lpdm->dmSize + lpdm->dmDriverExtra,
2071                                                GMEM_MOVEABLE);
2072             }
2073             lpdmReturn = GlobalLock(lppd->hDevMode);
2074             memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
2075
2076             if (lppd->hDevNames != 0) {
2077                 WORD locks;
2078                 if((locks = (GlobalFlags(lppd->hDevNames) & GMEM_LOCKCOUNT))) {
2079                     WARN("hDevNames has %d locks on it. Unlocking it now\n", locks);
2080                     while(locks--)
2081                         GlobalUnlock(lppd->hDevNames);
2082                 }
2083             }
2084             PRINTDLG_CreateDevNames(&(lppd->hDevNames),
2085                     di->pDriverPath,
2086                     pi->pPrinterName,
2087                     pi->pPortName
2088             );
2089             GlobalUnlock(lppd->hDevMode);
2090         }
2091         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
2092         HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
2093         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo);
2094         HeapFree(GetProcessHeap(), 0, PrintStructures);
2095     }
2096     if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
2097         bRet = PRINTDLG_CreateDCA(lppd);
2098
2099     TRACE("exit! (%d)\n", bRet);
2100     return bRet;
2101 }
2102
2103 /***********************************************************************
2104  *           PrintDlgW   (COMDLG32.@)
2105  */
2106 BOOL WINAPI PrintDlgW(
2107                       LPPRINTDLGW lppd /* [in/out] ptr to PRINTDLG32 struct */
2108                       )
2109 {
2110     BOOL      bRet = FALSE;
2111     LPVOID   ptr;
2112     HINSTANCE hInst = (HINSTANCE)GetWindowLongPtrW( lppd->hwndOwner, GWLP_HINSTANCE );
2113
2114     if(TRACE_ON(commdlg)) {
2115         char flagstr[1000] = "";
2116         struct pd_flags *pflag = pd_flags;
2117         for( ; pflag->name; pflag++) {
2118             if(lppd->Flags & pflag->flag)
2119                 strcat(flagstr, pflag->name);
2120         }
2121         TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
2122               "pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
2123               "flags %08lx (%s)\n",
2124               lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
2125               lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
2126               lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
2127     }
2128
2129     if(lppd->lStructSize != sizeof(PRINTDLGW)) {
2130         WARN("structure size failure !!!\n");
2131         COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
2132         return FALSE;
2133     }
2134
2135     if(lppd->Flags & PD_RETURNDEFAULT) {
2136         PRINTER_INFO_2W *pbuf;
2137         DRIVER_INFO_3W  *dbuf;
2138         HANDLE hprn;
2139         DWORD needed;
2140
2141         if(lppd->hDevMode || lppd->hDevNames) {
2142             WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
2143             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2144             return FALSE;
2145         }
2146         if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
2147             WARN("Can't find default printer\n");
2148             COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
2149             return FALSE;
2150         }
2151
2152         GetPrinterW(hprn, 2, NULL, 0, &needed);
2153         pbuf = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*needed);
2154         GetPrinterW(hprn, 2, (LPBYTE)pbuf, needed, &needed);
2155
2156         GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
2157         dbuf = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*needed);
2158         if (!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) {
2159             ERR("GetPrinterDriverA failed, le %ld, fix your config for printer %s!\n",GetLastError(),debugstr_w(pbuf->pPrinterName));
2160             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2161             return FALSE;
2162         }
2163         ClosePrinter(hprn);
2164
2165         PRINTDLG_CreateDevNamesW(&(lppd->hDevNames),
2166                                   dbuf->pDriverPath,
2167                                   pbuf->pPrinterName,
2168                                   pbuf->pPortName);
2169         lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
2170                                      pbuf->pDevMode->dmDriverExtra);
2171         ptr = GlobalLock(lppd->hDevMode);
2172         memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
2173                pbuf->pDevMode->dmDriverExtra);
2174         GlobalUnlock(lppd->hDevMode);
2175         HeapFree(GetProcessHeap(), 0, pbuf);
2176         HeapFree(GetProcessHeap(), 0, dbuf);
2177         bRet = TRUE;
2178     } else {
2179         HGLOBAL hDlgTmpl;
2180         PRINT_PTRW *PrintStructures;
2181
2182     /* load Dialog resources,
2183      * depending on Flags indicates Print32 or Print32_setup dialog
2184      */
2185         hDlgTmpl = PRINTDLG_GetDlgTemplateW(lppd);
2186         if (!hDlgTmpl) {
2187             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2188             return FALSE;
2189         }
2190         ptr = LockResource( hDlgTmpl );
2191         if (!ptr) {
2192             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2193             return FALSE;
2194         }
2195
2196         PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2197                                     sizeof(PRINT_PTRW));
2198         PrintStructures->lpPrintDlg = lppd;
2199
2200         /* and create & process the dialog .
2201          * -1 is failure, 0 is broken hwnd, everything else is ok.
2202          */
2203         bRet = (0<DialogBoxIndirectParamW(hInst, ptr, lppd->hwndOwner,
2204                                            PrintDlgProcW,
2205                                            (LPARAM)PrintStructures));
2206
2207         if(bRet) {
2208             DEVMODEW *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
2209             PRINTER_INFO_2W *pi = PrintStructures->lpPrinterInfo;
2210             DRIVER_INFO_3W *di = PrintStructures->lpDriverInfo;
2211
2212             if (lppd->hDevMode == 0) {
2213                 TRACE(" No hDevMode yet... Need to create my own\n");
2214                 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE,
2215                                         lpdm->dmSize + lpdm->dmDriverExtra);
2216             } else {
2217                 WORD locks;
2218                 if((locks = (GlobalFlags(lppd->hDevMode) & GMEM_LOCKCOUNT))) {
2219                     WARN("hDevMode has %d locks on it. Unlocking it now\n", locks);
2220                     while(locks--) {
2221                         GlobalUnlock(lppd->hDevMode);
2222                         TRACE("Now got %d locks\n", locks);
2223                     }
2224                 }
2225                 lppd->hDevMode = GlobalReAlloc(lppd->hDevMode,
2226                                                lpdm->dmSize + lpdm->dmDriverExtra,
2227                                                GMEM_MOVEABLE);
2228             }
2229             lpdmReturn = GlobalLock(lppd->hDevMode);
2230             memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
2231
2232             if (lppd->hDevNames != 0) {
2233                 WORD locks;
2234                 if((locks = (GlobalFlags(lppd->hDevNames) & GMEM_LOCKCOUNT))) {
2235                     WARN("hDevNames has %d locks on it. Unlocking it now\n", locks);
2236                     while(locks--)
2237                         GlobalUnlock(lppd->hDevNames);
2238                 }
2239             }
2240             PRINTDLG_CreateDevNamesW(&(lppd->hDevNames),
2241                     di->pDriverPath,
2242                     pi->pPrinterName,
2243                     pi->pPortName
2244             );
2245             GlobalUnlock(lppd->hDevMode);
2246         }
2247         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
2248         HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
2249         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo);
2250         HeapFree(GetProcessHeap(), 0, PrintStructures);
2251     }
2252     if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
2253         bRet = PRINTDLG_CreateDCW(lppd);
2254
2255     TRACE("exit! (%d)\n", bRet);
2256     return bRet;
2257 }
2258
2259 /***********************************************************************
2260  *
2261  *          PageSetupDlg
2262  * rad1 - portrait
2263  * rad2 - landscape
2264  * cmb1 - printer select (not in standart dialog template)
2265  * cmb2 - paper size
2266  * cmb3 - source (tray?)
2267  * edt4 - border left
2268  * edt5 - border top
2269  * edt6 - border right
2270  * edt7 - border bottom
2271  * psh3 - "Printer..."
2272  */
2273
2274 typedef struct {
2275     LPPAGESETUPDLGA     dlga;
2276     PRINTDLGA           pdlg;
2277 } PageSetupDataA;
2278
2279 typedef struct {
2280     LPPAGESETUPDLGW     dlga;
2281     PRINTDLGW           pdlg;
2282 } PageSetupDataW;
2283
2284 static HGLOBAL PRINTDLG_GetPGSTemplateA(PAGESETUPDLGA *lppd)
2285 {
2286     HRSRC hResInfo;
2287     HGLOBAL hDlgTmpl;
2288
2289     if(lppd->Flags & PSD_ENABLEPAGESETUPTEMPLATEHANDLE) {
2290         hDlgTmpl = lppd->hPageSetupTemplate;
2291     } else if(lppd->Flags & PSD_ENABLEPAGESETUPTEMPLATE) {
2292         hResInfo = FindResourceA(lppd->hInstance,
2293                                  lppd->lpPageSetupTemplateName, (LPSTR)RT_DIALOG);
2294         hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2295     } else {
2296         hResInfo = FindResourceA(COMDLG32_hInstance,(LPCSTR)PAGESETUPDLGORD,(LPSTR)RT_DIALOG);
2297         hDlgTmpl = LoadResource(COMDLG32_hInstance,hResInfo);
2298     }
2299     return hDlgTmpl;
2300 }
2301
2302 static HGLOBAL PRINTDLG_GetPGSTemplateW(PAGESETUPDLGW *lppd)
2303 {
2304     HRSRC hResInfo;
2305     HGLOBAL hDlgTmpl;
2306
2307     if(lppd->Flags & PSD_ENABLEPAGESETUPTEMPLATEHANDLE) {
2308         hDlgTmpl = lppd->hPageSetupTemplate;
2309     } else if(lppd->Flags & PSD_ENABLEPAGESETUPTEMPLATE) {
2310         hResInfo = FindResourceW(lppd->hInstance,
2311                                  lppd->lpPageSetupTemplateName, (LPWSTR)RT_DIALOG);
2312         hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2313     } else {
2314         hResInfo = FindResourceW(COMDLG32_hInstance,(LPCWSTR)PAGESETUPDLGORD,(LPWSTR)RT_DIALOG);
2315         hDlgTmpl = LoadResource(COMDLG32_hInstance,hResInfo);
2316     }
2317     return hDlgTmpl;
2318 }
2319
2320 static DWORD
2321 _c_10mm2size(PAGESETUPDLGA *dlga,DWORD size) {
2322     if (dlga->Flags & PSD_INTHOUSANDTHSOFINCHES)
2323         return 10*size*10/25.4;
2324     /* If we don't have a flag, we can choose one. Use millimeters
2325      * to avoid confusing me
2326      */
2327     dlga->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
2328     return 10*size;
2329 }
2330
2331
2332 static DWORD
2333 _c_inch2size(PAGESETUPDLGA *dlga,DWORD size) {
2334     if (dlga->Flags & PSD_INTHOUSANDTHSOFINCHES)
2335         return size;
2336     if (dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS)
2337         return (size*254)/10;
2338     /* if we don't have a flag, we can choose one. Use millimeters
2339      * to avoid confusing me
2340      */
2341     dlga->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
2342     return (size*254)/10;
2343 }
2344
2345 static void
2346 _c_size2strA(PageSetupDataA *pda,DWORD size,LPSTR strout) {
2347     strcpy(strout,"<undef>");
2348     if (pda->dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS) {
2349         sprintf(strout,"%.2fmm",(size*1.0)/100.0);
2350         return;
2351     }
2352     if (pda->dlga->Flags & PSD_INTHOUSANDTHSOFINCHES) {
2353         sprintf(strout,"%.2fin",(size*1.0)/1000.0);
2354         return;
2355     }
2356     pda->dlga->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
2357     sprintf(strout,"%.2fmm",(size*1.0)/100.0);
2358     return;
2359 }
2360 static void
2361 _c_size2strW(PageSetupDataW *pda,DWORD size,LPWSTR strout) {
2362     const static WCHAR UNDEF[] = { '<', 'u', 'n', 'd', 'e', 'f', '>', 0 };
2363     const static WCHAR mm_fmt[] = { '%', '.', '2', 'f', 'm', 'm', 0 };
2364     const static WCHAR in_fmt[] = { '%', '.', '2', 'f', 'i', 'n', 0 };
2365     lstrcpyW(strout, UNDEF);
2366     if (pda->dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS) {
2367         wsprintfW(strout,mm_fmt,(size*1.0)/100.0);
2368         return;
2369     }
2370     if (pda->dlga->Flags & PSD_INTHOUSANDTHSOFINCHES) {
2371         wsprintfW(strout,in_fmt,(size*1.0)/1000.0);
2372         return;
2373     }
2374     pda->dlga->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
2375     wsprintfW(strout,mm_fmt,(size*1.0)/100.0);
2376     return;
2377 }
2378
2379 static DWORD
2380 _c_str2sizeA(PAGESETUPDLGA *dlga,LPCSTR strin) {
2381     float       val;
2382     char        rest[200];
2383
2384     rest[0]='\0';
2385     if (!sscanf(strin,"%f%s",&val,rest))
2386         return 0;
2387
2388     if (!strcmp(rest,"in") || !strcmp(rest,"inch")) {
2389         if (dlga->Flags & PSD_INTHOUSANDTHSOFINCHES)
2390             return 1000*val;
2391         else
2392             return val*25.4*100;
2393     }
2394     if (!strcmp(rest,"cm")) { rest[0]='m'; val = val*10.0; }
2395     if (!strcmp(rest,"m")) { strcpy(rest,"mm"); val = val*1000.0; }
2396
2397     if (!strcmp(rest,"mm")) {
2398         if (dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS)
2399             return 100*val;
2400         else
2401             return 1000.0*val/25.4;
2402     }
2403     if (rest[0]=='\0') {
2404         /* use application supplied default */
2405         if (dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS) {
2406             /* 100*mm */
2407             return 100.0*val;
2408         }
2409         if (dlga->Flags & PSD_INTHOUSANDTHSOFINCHES) {
2410             /* 1000*inch */
2411             return 1000.0*val;
2412         }
2413     }
2414     ERR("Did not find a conversion for type '%s'!\n",rest);
2415     return 0;
2416 }
2417
2418
2419 static DWORD
2420 _c_str2sizeW(PAGESETUPDLGW *dlga, LPCWSTR strin) {
2421     char        buf[200];
2422
2423     /* this W -> A transition is OK */
2424     /* we need a unicode version of sscanf to avoid it */
2425     WideCharToMultiByte(CP_ACP, 0, strin, -1, buf, sizeof(buf), NULL, NULL);
2426     return _c_str2sizeA((PAGESETUPDLGA *)dlga, buf);
2427 }
2428
2429
2430 /*
2431  * This is called on finish and will update the output fields of the
2432  * struct.
2433  */
2434 static BOOL
2435 PRINTDLG_PS_UpdateDlgStructA(HWND hDlg, PageSetupDataA *pda) {
2436     DEVNAMES    *dn;
2437     DEVMODEA    *dm;
2438     LPSTR       devname,portname;
2439     char        papername[64];
2440     char        buf[200];
2441
2442     dn = GlobalLock(pda->pdlg.hDevNames);
2443     dm = GlobalLock(pda->pdlg.hDevMode);
2444     devname     = ((char*)dn)+dn->wDeviceOffset;
2445     portname    = ((char*)dn)+dn->wOutputOffset;
2446     PRINTDLG_SetUpPaperComboBoxA(hDlg,cmb2,devname,portname,dm);
2447     PRINTDLG_SetUpPaperComboBoxA(hDlg,cmb3,devname,portname,dm);
2448
2449     if (GetDlgItemTextA(hDlg,cmb2,papername,sizeof(papername))>0) {
2450         PRINTDLG_PaperSizeA(&(pda->pdlg),papername,&(pda->dlga->ptPaperSize));
2451         pda->dlga->ptPaperSize.x = _c_10mm2size(pda->dlga,pda->dlga->ptPaperSize.x);
2452         pda->dlga->ptPaperSize.y = _c_10mm2size(pda->dlga,pda->dlga->ptPaperSize.y);
2453     } else
2454         FIXME("could not get dialog text for papersize cmbbox?\n");
2455 #define GETVAL(id,val) if (GetDlgItemTextA(hDlg,id,buf,sizeof(buf))>0) { val = _c_str2sizeA(pda->dlga,buf); } else { FIXME("could not get dlgitemtexta for %x\n",id); }
2456     GETVAL(edt4,pda->dlga->rtMargin.left);
2457     GETVAL(edt5,pda->dlga->rtMargin.top);
2458     GETVAL(edt6,pda->dlga->rtMargin.right);
2459     GETVAL(edt7,pda->dlga->rtMargin.bottom);
2460 #undef GETVAL
2461
2462     /* If we are in landscape, swap x and y of page size */
2463     if (IsDlgButtonChecked(hDlg, rad2)) {
2464         DWORD tmp;
2465         tmp = pda->dlga->ptPaperSize.x;
2466         pda->dlga->ptPaperSize.x = pda->dlga->ptPaperSize.y;
2467         pda->dlga->ptPaperSize.y = tmp;
2468     }
2469     GlobalUnlock(pda->pdlg.hDevNames);
2470     GlobalUnlock(pda->pdlg.hDevMode);
2471     return TRUE;
2472 }
2473
2474 static BOOL
2475 PRINTDLG_PS_UpdateDlgStructW(HWND hDlg, PageSetupDataW *pda) {
2476     DEVNAMES    *dn;
2477     DEVMODEW    *dm;
2478     LPWSTR      devname,portname;
2479     WCHAR       papername[64];
2480     WCHAR       buf[200];
2481
2482     dn = GlobalLock(pda->pdlg.hDevNames);
2483     dm = GlobalLock(pda->pdlg.hDevMode);
2484     devname     = ((WCHAR*)dn)+dn->wDeviceOffset;
2485     portname    = ((WCHAR*)dn)+dn->wOutputOffset;
2486     PRINTDLG_SetUpPaperComboBoxW(hDlg,cmb2,devname,portname,dm);
2487     PRINTDLG_SetUpPaperComboBoxW(hDlg,cmb3,devname,portname,dm);
2488
2489     if (GetDlgItemTextW(hDlg,cmb2,papername,sizeof(papername))>0) {
2490         PRINTDLG_PaperSizeW(&(pda->pdlg),papername,&(pda->dlga->ptPaperSize));
2491         pda->dlga->ptPaperSize.x = _c_10mm2size((LPPAGESETUPDLGA)pda->dlga,pda->dlga->ptPaperSize.x);
2492         pda->dlga->ptPaperSize.y = _c_10mm2size((LPPAGESETUPDLGA)pda->dlga,pda->dlga->ptPaperSize.y);
2493     } else
2494         FIXME("could not get dialog text for papersize cmbbox?\n");
2495 #define GETVAL(id,val) if (GetDlgItemTextW(hDlg,id,buf,sizeof(buf)/sizeof(buf[0]))>0) { val = _c_str2sizeW(pda->dlga,buf); } else { FIXME("could not get dlgitemtextw for %x\n",id); }
2496     GETVAL(edt4,pda->dlga->rtMargin.left);
2497     GETVAL(edt5,pda->dlga->rtMargin.top);
2498     GETVAL(edt6,pda->dlga->rtMargin.right);
2499     GETVAL(edt7,pda->dlga->rtMargin.bottom);
2500 #undef GETVAL
2501
2502     /* If we are in landscape, swap x and y of page size */
2503     if (IsDlgButtonChecked(hDlg, rad2)) {
2504         DWORD tmp;
2505         tmp = pda->dlga->ptPaperSize.x;
2506         pda->dlga->ptPaperSize.x = pda->dlga->ptPaperSize.y;
2507         pda->dlga->ptPaperSize.y = tmp;
2508     }
2509     GlobalUnlock(pda->pdlg.hDevNames);
2510     GlobalUnlock(pda->pdlg.hDevMode);
2511     return TRUE;
2512 }
2513
2514 /*
2515  * This is called after returning from PrintDlg().
2516  */
2517 static BOOL
2518 PRINTDLG_PS_ChangePrinterA(HWND hDlg, PageSetupDataA *pda) {
2519     DEVNAMES    *dn;
2520     DEVMODEA    *dm;
2521     LPSTR       devname,portname;
2522
2523     dn = GlobalLock(pda->pdlg.hDevNames);
2524     dm = GlobalLock(pda->pdlg.hDevMode);
2525     devname     = ((char*)dn)+dn->wDeviceOffset;
2526     portname    = ((char*)dn)+dn->wOutputOffset;
2527     PRINTDLG_SetUpPaperComboBoxA(hDlg,cmb2,devname,portname,dm);
2528     PRINTDLG_SetUpPaperComboBoxA(hDlg,cmb3,devname,portname,dm);
2529     GlobalUnlock(pda->pdlg.hDevNames);
2530     GlobalUnlock(pda->pdlg.hDevMode);
2531     return TRUE;
2532 }
2533
2534 static BOOL
2535 PRINTDLG_PS_ChangePrinterW(HWND hDlg, PageSetupDataW *pda) {
2536     DEVNAMES    *dn;
2537     DEVMODEW    *dm;
2538     LPWSTR      devname,portname;
2539
2540     dn = GlobalLock(pda->pdlg.hDevNames);
2541     dm = GlobalLock(pda->pdlg.hDevMode);
2542     devname     = ((WCHAR*)dn)+dn->wDeviceOffset;
2543     portname    = ((WCHAR*)dn)+dn->wOutputOffset;
2544     PRINTDLG_SetUpPaperComboBoxW(hDlg,cmb2,devname,portname,dm);
2545     PRINTDLG_SetUpPaperComboBoxW(hDlg,cmb3,devname,portname,dm);
2546     GlobalUnlock(pda->pdlg.hDevNames);
2547     GlobalUnlock(pda->pdlg.hDevMode);
2548     return TRUE;
2549 }
2550
2551 static BOOL
2552 PRINTDLG_PS_WMCommandA(
2553     HWND hDlg, WPARAM wParam, LPARAM lParam, PageSetupDataA *pda
2554 ) {
2555     TRACE("loword (lparam) %d, wparam 0x%x, lparam %08lx\n",
2556             LOWORD(lParam),wParam,lParam);
2557     switch (LOWORD(wParam))  {
2558     case IDOK:
2559         if (!PRINTDLG_PS_UpdateDlgStructA(hDlg, pda))
2560             return(FALSE);
2561         EndDialog(hDlg, TRUE);
2562         return TRUE ;
2563
2564     case IDCANCEL:
2565         EndDialog(hDlg, FALSE);
2566         return FALSE ;
2567
2568     case psh3: {
2569         pda->pdlg.Flags         = 0;
2570         pda->pdlg.hwndOwner     = hDlg;
2571         if (PrintDlgA(&(pda->pdlg)))
2572             PRINTDLG_PS_ChangePrinterA(hDlg,pda);
2573         return TRUE;
2574     }
2575     }
2576     return FALSE;
2577 }
2578
2579 static BOOL
2580 PRINTDLG_PS_WMCommandW(
2581     HWND hDlg, WPARAM wParam, LPARAM lParam, PageSetupDataW *pda
2582 ) {
2583     TRACE("loword (lparam) %d, wparam 0x%x, lparam %08lx\n",
2584             LOWORD(lParam),wParam,lParam);
2585     switch (LOWORD(wParam))  {
2586     case IDOK:
2587         if (!PRINTDLG_PS_UpdateDlgStructW(hDlg, pda))
2588             return(FALSE);
2589         EndDialog(hDlg, TRUE);
2590         return TRUE ;
2591
2592     case IDCANCEL:
2593         EndDialog(hDlg, FALSE);
2594         return FALSE ;
2595
2596     case psh3: {
2597         pda->pdlg.Flags         = 0;
2598         pda->pdlg.hwndOwner     = hDlg;
2599         if (PrintDlgW(&(pda->pdlg)))
2600             PRINTDLG_PS_ChangePrinterW(hDlg,pda);
2601         return TRUE;
2602     }
2603     }
2604     return FALSE;
2605 }
2606
2607
2608 /***********************************************************************
2609  *           DefaultPagePaintHook
2610  * Default hook paint procedure that receives WM_PSD_* messages from the dialog box 
2611  * whenever the sample page is redrawn.
2612 */
2613
2614 static UINT_PTR
2615 PRINTDLG_DefaultPagePaintHook(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam, PageSetupDataA *pda)
2616 {
2617     LPRECT lprc = (LPRECT) lParam;
2618     HDC hdc = (HDC) wParam;
2619     HPEN hpen, holdpen;
2620     LOGFONTW lf;
2621     HFONT hfont, holdfont;
2622     INT oldbkmode;
2623     TRACE("uMsg: WM_USER+%d\n",uMsg-WM_USER);
2624
2625     /* Call user paint hook if enable */
2626     if (pda->dlga->Flags & PSD_ENABLEPAGEPAINTHOOK)
2627         if (pda->dlga->lpfnPagePaintHook(hwndDlg, uMsg, wParam, lParam))
2628             return TRUE;
2629
2630     switch (uMsg) {
2631        /* LPPAGESETUPDLG in lParam */
2632        case WM_PSD_PAGESETUPDLG:
2633        /* Inform about the sample page rectangle */
2634        case WM_PSD_FULLPAGERECT:
2635        /* Inform about the margin rectangle */
2636        case WM_PSD_MINMARGINRECT:
2637             return FALSE;
2638
2639         /* Draw dashed rectangle showing margins */
2640         case WM_PSD_MARGINRECT:
2641             hpen = CreatePen(PS_DASH, 1, GetSysColor(COLOR_3DSHADOW));
2642             holdpen = SelectObject(hdc, hpen);
2643             Rectangle(hdc, lprc->left, lprc->top, lprc->right, lprc->bottom);
2644             DeleteObject(SelectObject(hdc, holdpen));
2645             return TRUE;
2646
2647
2648         /* Draw the fake document */
2649         case WM_PSD_GREEKTEXTRECT:
2650             /* select a nice scalable font, because we want the text really small */
2651             SystemParametersInfoW(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0);
2652             lf.lfHeight = 6; /* value chosen based on visual effect */
2653             hfont = CreateFontIndirectW(&lf);
2654             holdfont = SelectObject(hdc, hfont);
2655
2656             /* if text not loaded, then do so now */
2657             if (wszFakeDocumentText[0] == '\0')
2658                  LoadStringW(COMDLG32_hInstance,
2659                         IDS_FAKEDOCTEXT,
2660                         wszFakeDocumentText,
2661                         sizeof(wszFakeDocumentText)/sizeof(wszFakeDocumentText[0]));
2662
2663             oldbkmode = SetBkMode(hdc, TRANSPARENT);
2664             DrawTextW(hdc, wszFakeDocumentText, -1, lprc, DT_TOP|DT_LEFT|DT_NOPREFIX|DT_WORDBREAK);
2665             SetBkMode(hdc, oldbkmode);
2666
2667             DeleteObject(SelectObject(hdc, holdfont));
2668             return TRUE;
2669
2670         /* Envelope stamp */
2671         case WM_PSD_ENVSTAMPRECT:
2672         /* Return address */
2673         case WM_PSD_YAFULLPAGERECT:
2674             FIXME("envelope/stamp is not implemented\n");
2675             return FALSE;
2676         default:
2677             FIXME("Unknown message %x\n",uMsg);
2678             return FALSE;
2679     }
2680     return TRUE;
2681 }
2682
2683 /***********************************************************************
2684  *           PagePaintProc
2685  * The main paint procedure for the PageSetupDlg function.
2686  * The Page Setup dialog box includes an image of a sample page that shows how
2687  * the user's selections affect the appearance of the printed output.
2688  * The image consists of a rectangle that represents the selected paper
2689  * or envelope type, with a dotted-line rectangle representing
2690  * the current margins, and partial (Greek text) characters
2691  * to show how text looks on the printed page. 
2692  *
2693  * The following messages in the order sends to user hook procedure:
2694  *   WM_PSD_PAGESETUPDLG    Draw the contents of the sample page
2695  *   WM_PSD_FULLPAGERECT    Inform about the bounding rectangle
2696  *   WM_PSD_MINMARGINRECT   Inform about the margin rectangle (min margin?)
2697  *   WM_PSD_MARGINRECT      Draw the margin rectangle
2698  *   WM_PSD_GREEKTEXTRECT   Draw the Greek text inside the margin rectangle
2699  * If any of first three messages returns TRUE, painting done.
2700  *
2701  * PARAMS:
2702  *   hWnd   [in] Handle to the Page Setup dialog box
2703  *   uMsg   [in] Received message
2704  *
2705  * TODO:
2706  *   WM_PSD_ENVSTAMPRECT    Draw in the envelope-stamp rectangle (for envelopes only)
2707  *   WM_PSD_YAFULLPAGERECT  Draw the return address portion (for envelopes and other paper sizes)
2708  *
2709  * RETURNS:
2710  *   FALSE if all done correctly
2711  *
2712  */
2713 static LRESULT CALLBACK
2714 PRINTDLG_PagePaintProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2715 {
2716     PAINTSTRUCT ps;
2717     RECT rcClient, rcMargin;
2718     HPEN hpen, holdpen;
2719     HDC hdc;
2720     HBRUSH hbrush, holdbrush;
2721     PageSetupDataA *pda;
2722     int papersize=0, orientation=0; /* FIXME: set this values */
2723
2724 #define CALLPAINTHOOK(msg,lprc) PRINTDLG_DefaultPagePaintHook( hWnd, msg, (WPARAM)hdc, (LPARAM)lprc, pda)
2725
2726     if (uMsg != WM_PAINT)
2727         return CallWindowProcA(lpfnStaticWndProc, hWnd, uMsg, wParam, lParam);
2728
2729     /* Processing WM_PAINT message */
2730     pda = (PageSetupDataA*)GetPropA(hWnd, "__WINE_PAGESETUPDLGDATA");
2731     if (!pda) {
2732         WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
2733         return FALSE;
2734     }
2735     if (PRINTDLG_DefaultPagePaintHook(hWnd, WM_PSD_PAGESETUPDLG, MAKELONG(papersize, orientation), (LPARAM)pda->dlga, pda))
2736         return FALSE;
2737
2738     hdc = BeginPaint(hWnd, &ps);
2739     GetClientRect(hWnd, &rcClient);
2740
2741     /* FIXME: use real margin values */
2742     rcMargin = rcClient;
2743     rcMargin.left += 5;
2744     rcMargin.top += 5;
2745     rcMargin.right -= 5;
2746     rcMargin.bottom -= 5;
2747
2748     /* if the space is too small then we make sure to not draw anything */
2749     rcMargin.left = min(rcMargin.left, rcMargin.right);
2750     rcMargin.top = min(rcMargin.top, rcMargin.bottom);
2751
2752     if (!CALLPAINTHOOK(WM_PSD_FULLPAGERECT, &rcClient) &&
2753         !CALLPAINTHOOK(WM_PSD_MINMARGINRECT, &rcMargin) )
2754     {
2755         /* fill background */
2756         hbrush = GetSysColorBrush(COLOR_3DHIGHLIGHT);
2757         FillRect(hdc, &rcClient, hbrush);
2758         holdbrush = SelectObject(hdc, hbrush);
2759
2760         hpen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));
2761         holdpen = SelectObject(hdc, hpen);
2762
2763         
2764         /* paint left edge */
2765         MoveToEx(hdc, rcClient.left, rcClient.top, NULL);
2766         LineTo(hdc, rcClient.left, rcClient.bottom-1);
2767
2768         /* paint top edge */
2769         MoveToEx(hdc, rcClient.left, rcClient.top, NULL);
2770         LineTo(hdc, rcClient.right, rcClient.top);
2771
2772         hpen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DDKSHADOW));
2773         DeleteObject(SelectObject(hdc, hpen));
2774
2775         /* paint right edge */
2776         MoveToEx(hdc, rcClient.right-1, rcClient.top, NULL);
2777         LineTo(hdc, rcClient.right-1, rcClient.bottom);
2778
2779         /* paint bottom edge */
2780         MoveToEx(hdc, rcClient.left, rcClient.bottom-1, NULL);
2781         LineTo(hdc, rcClient.right, rcClient.bottom-1);
2782
2783         DeleteObject(SelectObject(hdc, holdpen));
2784         DeleteObject(SelectObject(hdc, holdbrush));
2785
2786
2787         CALLPAINTHOOK(WM_PSD_MARGINRECT, &rcMargin);
2788
2789
2790         /* give text a bit of a space from the frame */
2791         rcMargin.left += 2;
2792         rcMargin.top += 2;
2793         rcMargin.right -= 2;
2794         rcMargin.bottom -= 2;
2795         
2796         /* if the space is too small then we make sure to not draw anything */
2797         rcMargin.left = min(rcMargin.left, rcMargin.right);
2798         rcMargin.top = min(rcMargin.top, rcMargin.bottom);
2799
2800         CALLPAINTHOOK(WM_PSD_GREEKTEXTRECT, &rcMargin);
2801     }
2802
2803     EndPaint(hWnd, &ps);
2804     return FALSE;
2805 #undef CALLPAINTHOOK
2806 }
2807
2808 /***********************************************************************
2809  *           PRINTDLG_PageDlgProcA
2810  * Message handler 
2811  */
2812 static INT_PTR CALLBACK
2813 PRINTDLG_PageDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
2814 {
2815     PageSetupDataA      *pda;
2816     INT_PTR             res = FALSE;
2817
2818     if (uMsg == WM_INITDIALOG) {
2819         pda = (PageSetupDataA*)lParam;
2820         TRACE("set property to %p", pda);
2821         SetPropA(hDlg, "__WINE_PAGESETUPDLGDATA", pda);
2822         SetPropA(GetDlgItem(hDlg, rct1), "__WINE_PAGESETUPDLGDATA", pda);
2823         lpfnStaticWndProc = (WNDPROC)SetWindowLongPtrW(
2824             GetDlgItem(hDlg, rct1),
2825             GWLP_WNDPROC,
2826             (ULONG_PTR)PRINTDLG_PagePaintProc);
2827         res = TRUE;
2828         if (pda->dlga->Flags & PSD_ENABLEPAGESETUPHOOK) {
2829             res = pda->dlga->lpfnPageSetupHook(hDlg,uMsg,wParam,(LPARAM)pda->dlga);
2830             if (!res) {
2831                 FIXME("Setup page hook failed?\n");
2832                 res = TRUE;
2833             }
2834         }
2835
2836         if (pda->dlga->Flags & PSD_DISABLEPRINTER)
2837             EnableWindow(GetDlgItem(hDlg, psh3), FALSE);
2838         if (pda->dlga->Flags & PSD_DISABLEMARGINS) {
2839             EnableWindow(GetDlgItem(hDlg, edt4), FALSE);
2840             EnableWindow(GetDlgItem(hDlg, edt5), FALSE);
2841             EnableWindow(GetDlgItem(hDlg, edt6), FALSE);
2842             EnableWindow(GetDlgItem(hDlg, edt7), FALSE);
2843         }
2844         /* width larger as height -> landscape */
2845         if (pda->dlga->ptPaperSize.x > pda->dlga->ptPaperSize.y)
2846             CheckRadioButton(hDlg, rad1, rad2, rad2);
2847         else /* this is default if papersize is not set */
2848             CheckRadioButton(hDlg, rad1, rad2, rad1);
2849         if (pda->dlga->Flags & PSD_DISABLEORIENTATION) {
2850             EnableWindow(GetDlgItem(hDlg,rad1),FALSE);
2851             EnableWindow(GetDlgItem(hDlg,rad2),FALSE);
2852         }
2853         /* We fill them out enabled or not */
2854         if (pda->dlga->Flags & PSD_MARGINS) {
2855             char str[100];
2856             _c_size2strA(pda,pda->dlga->rtMargin.left,str);
2857             SetDlgItemTextA(hDlg,edt4,str);
2858             _c_size2strA(pda,pda->dlga->rtMargin.top,str);
2859             SetDlgItemTextA(hDlg,edt5,str);
2860             _c_size2strA(pda,pda->dlga->rtMargin.right,str);
2861             SetDlgItemTextA(hDlg,edt6,str);
2862             _c_size2strA(pda,pda->dlga->rtMargin.bottom,str);
2863             SetDlgItemTextA(hDlg,edt7,str);
2864         } else {
2865             /* default is 1 inch */
2866             DWORD size = _c_inch2size(pda->dlga,1000);
2867             char        str[20];
2868             _c_size2strA(pda,size,str);
2869             SetDlgItemTextA(hDlg,edt4,str);
2870             SetDlgItemTextA(hDlg,edt5,str);
2871             SetDlgItemTextA(hDlg,edt6,str);
2872             SetDlgItemTextA(hDlg,edt7,str);
2873         }
2874         PRINTDLG_PS_ChangePrinterA(hDlg,pda);
2875         if (pda->dlga->Flags & PSD_DISABLEPAPER) {
2876             EnableWindow(GetDlgItem(hDlg,cmb2),FALSE);
2877             EnableWindow(GetDlgItem(hDlg,cmb3),FALSE);
2878         }
2879         return TRUE;
2880     } else {
2881         pda = (PageSetupDataA*)GetPropA(hDlg,"__WINE_PAGESETUPDLGDATA");
2882         if (!pda) {
2883             WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
2884             return FALSE;
2885         }
2886         if (pda->dlga->Flags & PSD_ENABLEPAGESETUPHOOK) {
2887             res = pda->dlga->lpfnPageSetupHook(hDlg,uMsg,wParam,lParam);
2888             if (res) return res;
2889         }
2890     }
2891     switch (uMsg) {
2892     case WM_COMMAND:
2893         return PRINTDLG_PS_WMCommandA(hDlg, wParam, lParam, pda);
2894     }
2895     return FALSE;
2896 }
2897
2898 static INT_PTR CALLBACK
2899 PageDlgProcW(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
2900 {
2901     const static WCHAR __WINE_PAGESETUPDLGDATA[] = 
2902         { '_', '_', 'W', 'I', 'N', 'E', '_', 'P', 'A', 'G', 'E', 
2903           'S', 'E', 'T', 'U', 'P', 'D', 'L', 'G', 'D', 'A', 'T', 'A', 0 };
2904     PageSetupDataW      *pda;
2905     BOOL                res = FALSE;
2906
2907     if (uMsg==WM_INITDIALOG) {
2908         res = TRUE;
2909         pda = (PageSetupDataW*)lParam;
2910         SetPropW(hDlg, __WINE_PAGESETUPDLGDATA, pda);
2911         if (pda->dlga->Flags & PSD_ENABLEPAGESETUPHOOK) {
2912             res = pda->dlga->lpfnPageSetupHook(hDlg,uMsg,wParam,(LPARAM)pda->dlga);
2913             if (!res) {
2914                 FIXME("Setup page hook failed?\n");
2915                 res = TRUE;
2916             }
2917         }
2918         if (pda->dlga->Flags & PSD_ENABLEPAGEPAINTHOOK) {
2919             FIXME("PagePaintHook not yet implemented!\n");
2920         }
2921         if (pda->dlga->Flags & PSD_DISABLEPRINTER)
2922             EnableWindow(GetDlgItem(hDlg, psh3), FALSE);
2923         if (pda->dlga->Flags & PSD_DISABLEMARGINS) {
2924             EnableWindow(GetDlgItem(hDlg, edt4), FALSE);
2925             EnableWindow(GetDlgItem(hDlg, edt5), FALSE);
2926             EnableWindow(GetDlgItem(hDlg, edt6), FALSE);
2927             EnableWindow(GetDlgItem(hDlg, edt7), FALSE);
2928         }
2929         /* width larger as height -> landscape */
2930         if (pda->dlga->ptPaperSize.x > pda->dlga->ptPaperSize.y)
2931             CheckRadioButton(hDlg, rad1, rad2, rad2);
2932         else /* this is default if papersize is not set */
2933             CheckRadioButton(hDlg, rad1, rad2, rad1);
2934         if (pda->dlga->Flags & PSD_DISABLEORIENTATION) {
2935             EnableWindow(GetDlgItem(hDlg,rad1),FALSE);
2936             EnableWindow(GetDlgItem(hDlg,rad2),FALSE);
2937         }
2938         /* We fill them out enabled or not */
2939         if (pda->dlga->Flags & PSD_MARGINS) {
2940             WCHAR str[100];
2941             _c_size2strW(pda,pda->dlga->rtMargin.left,str);
2942             SetDlgItemTextW(hDlg,edt4,str);
2943             _c_size2strW(pda,pda->dlga->rtMargin.top,str);
2944             SetDlgItemTextW(hDlg,edt5,str);
2945             _c_size2strW(pda,pda->dlga->rtMargin.right,str);
2946             SetDlgItemTextW(hDlg,edt6,str);
2947             _c_size2strW(pda,pda->dlga->rtMargin.bottom,str);
2948             SetDlgItemTextW(hDlg,edt7,str);
2949         } else {
2950             /* default is 1 inch */
2951             DWORD size = _c_inch2size((LPPAGESETUPDLGA)pda->dlga,1000);
2952             WCHAR       str[20];
2953             _c_size2strW(pda,size,str);
2954             SetDlgItemTextW(hDlg,edt4,str);
2955             SetDlgItemTextW(hDlg,edt5,str);
2956             SetDlgItemTextW(hDlg,edt6,str);
2957             SetDlgItemTextW(hDlg,edt7,str);
2958         }
2959         PRINTDLG_PS_ChangePrinterW(hDlg,pda);
2960         if (pda->dlga->Flags & PSD_DISABLEPAPER) {
2961             EnableWindow(GetDlgItem(hDlg,cmb2),FALSE);
2962             EnableWindow(GetDlgItem(hDlg,cmb3),FALSE);
2963         }
2964         return TRUE;
2965     } else {
2966         pda = (PageSetupDataW*)GetPropW(hDlg, __WINE_PAGESETUPDLGDATA);
2967         if (!pda) {
2968             WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
2969             return FALSE;
2970         }
2971         if (pda->dlga->Flags & PSD_ENABLEPAGESETUPHOOK) {
2972             res = pda->dlga->lpfnPageSetupHook(hDlg,uMsg,wParam,lParam);
2973             if (res) return res;
2974         }
2975     }
2976     switch (uMsg) {
2977     case WM_COMMAND:
2978         return PRINTDLG_PS_WMCommandW(hDlg, wParam, lParam, pda);
2979     }
2980     return FALSE;
2981 }
2982
2983 /***********************************************************************
2984  *            PageSetupDlgA  (COMDLG32.@)
2985  *
2986  *  Displays the the PAGE SETUP dialog box, which enables the user to specify
2987  *  specific properties of a printed page such as
2988  *  size, source, orientation and the width of the page margins.
2989  *
2990  * PARAMS
2991  *  setupdlg [in] PAGESETUPDLGA struct
2992  *
2993  * RETURNS
2994  *  TRUE    if the user pressed the OK button
2995  *  FALSE   if the user cancelled the window or an error occurred
2996  *
2997  * NOTES
2998  *    The values of hDevMode and hDevNames are filled on output and can be
2999  *    changed in PAGESETUPDLG when they are passed in PageSetupDlg.
3000  * BUGS
3001  *  PrintSetupDlg:
3002  *  * The Paper Orientation Icons are not implemented yet.
3003  *  * The Properties Button(s) should call DocumentPropertiesA().
3004  *  * Settings are not yet taken from a provided DevMode or
3005  *    default printer settings.
3006  */
3007
3008 BOOL WINAPI PageSetupDlgA(LPPAGESETUPDLGA setupdlg) {
3009     HGLOBAL             hDlgTmpl;
3010     LPVOID              ptr;
3011     BOOL                bRet;
3012     PageSetupDataA      *pda;
3013     PRINTDLGA           pdlg;
3014
3015     if(TRACE_ON(commdlg)) {
3016         char flagstr[1000] = "";
3017         struct pd_flags *pflag = psd_flags;
3018         for( ; pflag->name; pflag++) {
3019             if(setupdlg->Flags & pflag->flag) {
3020                 strcat(flagstr, pflag->name);
3021                 strcat(flagstr, "|");
3022             }
3023         }
3024         TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
3025               "hinst %p, flags %08lx (%s)\n",
3026               setupdlg, setupdlg->hwndOwner, setupdlg->hDevMode,
3027               setupdlg->hDevNames,
3028               setupdlg->hInstance, setupdlg->Flags, flagstr);
3029     }
3030     if (setupdlg->Flags & PSD_ENABLEPAGEPAINTHOOK)
3031         if (setupdlg->lpfnPagePaintHook == NULL) {
3032             COMDLG32_SetCommDlgExtendedError(CDERR_NOHOOK);
3033             return FALSE;
3034         }
3035
3036     /* First get default printer data, we need it right after that. */
3037     memset(&pdlg,0,sizeof(pdlg));
3038     pdlg.lStructSize    = sizeof(pdlg);
3039     pdlg.Flags          = PD_RETURNDEFAULT;
3040     bRet = PrintDlgA(&pdlg);
3041     if (!bRet) return FALSE;
3042
3043     /* short cut exit, just return default values */
3044     if (setupdlg->Flags & PSD_RETURNDEFAULT) {
3045         setupdlg->hDevMode      = pdlg.hDevMode;
3046         setupdlg->hDevNames     = pdlg.hDevNames;
3047         /* FIXME: Just return "A4" for now. */
3048         PRINTDLG_PaperSizeA(&pdlg,"A4",&setupdlg->ptPaperSize);
3049         setupdlg->ptPaperSize.x=_c_10mm2size(setupdlg,setupdlg->ptPaperSize.x);
3050         setupdlg->ptPaperSize.y=_c_10mm2size(setupdlg,setupdlg->ptPaperSize.y);
3051         return TRUE;
3052     }
3053     hDlgTmpl = PRINTDLG_GetPGSTemplateA(setupdlg);
3054     if (!hDlgTmpl) {
3055         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
3056         return FALSE;
3057     }
3058     ptr = LockResource( hDlgTmpl );
3059     if (!ptr) {
3060         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
3061         return FALSE;
3062     }
3063     pda = HeapAlloc(GetProcessHeap(),0,sizeof(*pda));
3064     pda->dlga = setupdlg;
3065     memcpy(&pda->pdlg,&pdlg,sizeof(pdlg));
3066
3067     bRet = (0<DialogBoxIndirectParamA(
3068                 setupdlg->hInstance,
3069                 ptr,
3070                 setupdlg->hwndOwner,
3071                 PRINTDLG_PageDlgProcA,
3072                 (LPARAM)pda)
3073     );
3074     return bRet;
3075 }
3076 /***********************************************************************
3077  *            PageSetupDlgW  (COMDLG32.@)
3078  */
3079 BOOL WINAPI PageSetupDlgW(LPPAGESETUPDLGW setupdlg) {
3080     HGLOBAL             hDlgTmpl;
3081     LPVOID              ptr;
3082     BOOL                bRet;
3083     PageSetupDataW      *pdw;
3084     PRINTDLGW           pdlg;
3085     FIXME("Unicode implementation is not done yet\n");
3086     if(TRACE_ON(commdlg)) {
3087         char flagstr[1000] = "";
3088         struct pd_flags *pflag = psd_flags;
3089         for( ; pflag->name; pflag++) {
3090             if(setupdlg->Flags & pflag->flag) {
3091                 strcat(flagstr, pflag->name);
3092                 strcat(flagstr, "|");
3093             }
3094         }
3095         TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
3096               "hinst %p, flags %08lx (%s)\n",
3097               setupdlg, setupdlg->hwndOwner, setupdlg->hDevMode,
3098               setupdlg->hDevNames,
3099               setupdlg->hInstance, setupdlg->Flags, flagstr);
3100     }
3101
3102     /* First get default printer data, we need it right after that. */
3103     memset(&pdlg,0,sizeof(pdlg));
3104     pdlg.lStructSize    = sizeof(pdlg);
3105     pdlg.Flags          = PD_RETURNDEFAULT;
3106     bRet = PrintDlgW(&pdlg);
3107     if (!bRet) return FALSE;
3108
3109     /* short cut exit, just return default values */
3110     if (setupdlg->Flags & PSD_RETURNDEFAULT) {
3111         static const WCHAR a4[] = {'A','4',0};
3112         setupdlg->hDevMode      = pdlg.hDevMode;
3113         setupdlg->hDevNames     = pdlg.hDevNames;
3114         /* FIXME: Just return "A4" for now. */
3115         PRINTDLG_PaperSizeW(&pdlg,a4,&setupdlg->ptPaperSize);
3116         setupdlg->ptPaperSize.x=_c_10mm2size((LPPAGESETUPDLGA)setupdlg,setupdlg->ptPaperSize.x);
3117         setupdlg->ptPaperSize.y=_c_10mm2size((LPPAGESETUPDLGA)setupdlg,setupdlg->ptPaperSize.y);
3118         return TRUE;
3119     }
3120     hDlgTmpl = PRINTDLG_GetPGSTemplateW(setupdlg);
3121     if (!hDlgTmpl) {
3122         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
3123         return FALSE;
3124     }
3125     ptr = LockResource( hDlgTmpl );
3126     if (!ptr) {
3127         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
3128         return FALSE;
3129     }
3130     pdw = HeapAlloc(GetProcessHeap(),0,sizeof(*pdw));
3131     pdw->dlga = setupdlg;
3132     memcpy(&pdw->pdlg,&pdlg,sizeof(pdlg));
3133
3134     bRet = (0<DialogBoxIndirectParamW(
3135                 setupdlg->hInstance,
3136                 ptr,
3137                 setupdlg->hwndOwner,
3138                 PageDlgProcW,
3139                 (LPARAM)pdw)
3140     );
3141     return bRet;
3142 }
3143
3144 /***********************************************************************
3145  *      PrintDlgExA (COMDLG32.@)
3146  */
3147 HRESULT WINAPI PrintDlgExA(LPPRINTDLGEXA lpPrintDlgExA)
3148 {
3149         FIXME("stub\n");
3150         return E_NOTIMPL;
3151 }
3152
3153 /***********************************************************************
3154  *      PrintDlgExW (COMDLG32.@)
3155  */
3156 HRESULT WINAPI PrintDlgExW(LPPRINTDLGEXW lpPrintDlgExW)
3157 {
3158         FIXME("stub\n");
3159         return E_NOTIMPL;
3160 }