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