Implement A->W call for GetNamedSecurityInfo.
[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     /* display the collate/no_collate icon */
1208     SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1209                         (LPARAM)PrintStructures->hNoCollateIcon);
1210
1211     if(PrintStructures->hCollateIcon == 0 ||
1212        PrintStructures->hNoCollateIcon == 0 ||
1213        PrintStructures->hPortraitIcon == 0 ||
1214        PrintStructures->hLandscapeIcon == 0) {
1215         ERR("no icon in resourcefile\n");
1216         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1217         EndDialog(hDlg, FALSE);
1218     }
1219
1220     /*
1221      * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
1222      * must be registered and the Help button must be shown.
1223      */
1224     if (lppd->Flags & PD_SHOWHELP) {
1225         if((PrintStructures->HelpMessageID =
1226             RegisterWindowMessageA(HELPMSGSTRINGA)) == 0) {
1227             COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
1228             return FALSE;
1229         }
1230     } else
1231         PrintStructures->HelpMessageID = 0;
1232
1233     if(!(lppd->Flags &PD_PRINTSETUP)) {
1234         PrintStructures->hwndUpDown =
1235           CreateUpDownControl(WS_CHILD | WS_VISIBLE | WS_BORDER |
1236                               UDS_NOTHOUSANDS | UDS_ARROWKEYS |
1237                               UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 0, 0, 0, 0,
1238                               hDlg, UPDOWN_ID, COMDLG32_hInstance,
1239                               GetDlgItem(hDlg, edt3), MAX_COPIES, 1, 1);
1240     }
1241
1242     /* FIXME: I allow more freedom than either Win95 or WinNT,
1243      *        which do not agree to what errors should be thrown or not
1244      *        in case nToPage or nFromPage is out-of-range.
1245      */
1246     if (lppd->nMaxPage < lppd->nMinPage)
1247         lppd->nMaxPage = lppd->nMinPage;
1248     if (lppd->nMinPage == lppd->nMaxPage)
1249         lppd->Flags |= PD_NOPAGENUMS;
1250     if (lppd->nToPage < lppd->nMinPage)
1251         lppd->nToPage = lppd->nMinPage;
1252     if (lppd->nToPage > lppd->nMaxPage)
1253         lppd->nToPage = lppd->nMaxPage;
1254     if (lppd->nFromPage < lppd->nMinPage)
1255         lppd->nFromPage = lppd->nMinPage;
1256     if (lppd->nFromPage > lppd->nMaxPage)
1257         lppd->nFromPage = lppd->nMaxPage;
1258
1259     /* if we have the combo box, fill it */
1260     if (GetDlgItem(hDlg,comboID)) {
1261         /* Fill Combobox
1262          */
1263         pdn = GlobalLock(lppd->hDevNames);
1264         pdm = GlobalLock(lppd->hDevMode);
1265         if(pdn)
1266             name = (char*)pdn + pdn->wDeviceOffset;
1267         else if(pdm)
1268             name = pdm->dmDeviceName;
1269         PRINTDLG_SetUpPrinterListComboA(hDlg, comboID, name);
1270         if(pdm) GlobalUnlock(lppd->hDevMode);
1271         if(pdn) GlobalUnlock(lppd->hDevNames);
1272
1273         /* Now find selected printer and update rest of dlg */
1274         name = HeapAlloc(GetProcessHeap(),0,256);
1275         if (GetDlgItemTextA(hDlg, comboID, name, 255))
1276             PRINTDLG_ChangePrinterA(hDlg, name, PrintStructures);
1277         HeapFree(GetProcessHeap(),0,name);
1278     } else {
1279         /* else use default printer */
1280         char name[200];
1281         DWORD dwBufLen = sizeof(name);
1282         BOOL ret = GetDefaultPrinterA(name, &dwBufLen);
1283
1284         if (ret)
1285             PRINTDLG_ChangePrinterA(hDlg, name, PrintStructures);
1286         else
1287             FIXME("No default printer found, expect problems!\n");
1288     }
1289     return TRUE;
1290 }
1291
1292 static LRESULT PRINTDLG_WMInitDialogW(HWND hDlg, WPARAM wParam,
1293                                      PRINT_PTRW* PrintStructures)
1294 {
1295     LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
1296     DEVNAMES *pdn;
1297     DEVMODEW *pdm;
1298     WCHAR *name = NULL;
1299     UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1300
1301     /* load Collate ICONs */
1302     /* We load these with LoadImage because they are not a standard
1303        size and we don't want them rescaled */
1304     PrintStructures->hCollateIcon =
1305       LoadImageA(COMDLG32_hInstance, "PD32_COLLATE", IMAGE_ICON, 0, 0, 0);
1306     PrintStructures->hNoCollateIcon =
1307       LoadImageA(COMDLG32_hInstance, "PD32_NOCOLLATE", IMAGE_ICON, 0, 0, 0);
1308
1309     /* These can be done with LoadIcon */
1310     PrintStructures->hPortraitIcon =
1311       LoadIconA(COMDLG32_hInstance, "PD32_PORTRAIT");
1312     PrintStructures->hLandscapeIcon =
1313       LoadIconA(COMDLG32_hInstance, "PD32_LANDSCAPE");
1314
1315     /* display the collate/no_collate icon */
1316     SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1317                         (LPARAM)PrintStructures->hNoCollateIcon);
1318
1319     if(PrintStructures->hCollateIcon == 0 ||
1320        PrintStructures->hNoCollateIcon == 0 ||
1321        PrintStructures->hPortraitIcon == 0 ||
1322        PrintStructures->hLandscapeIcon == 0) {
1323         ERR("no icon in resourcefile\n");
1324         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1325         EndDialog(hDlg, FALSE);
1326     }
1327
1328     /*
1329      * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
1330      * must be registered and the Help button must be shown.
1331      */
1332     if (lppd->Flags & PD_SHOWHELP) {
1333         if((PrintStructures->HelpMessageID =
1334             RegisterWindowMessageA(HELPMSGSTRINGA)) == 0) {
1335             COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
1336             return FALSE;
1337         }
1338     } else
1339         PrintStructures->HelpMessageID = 0;
1340
1341     if(!(lppd->Flags &PD_PRINTSETUP)) {
1342         PrintStructures->hwndUpDown =
1343           CreateUpDownControl(WS_CHILD | WS_VISIBLE | WS_BORDER |
1344                               UDS_NOTHOUSANDS | UDS_ARROWKEYS |
1345                               UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 0, 0, 0, 0,
1346                               hDlg, UPDOWN_ID, COMDLG32_hInstance,
1347                               GetDlgItem(hDlg, edt3), MAX_COPIES, 1, 1);
1348     }
1349
1350     /* FIXME: I allow more freedom than either Win95 or WinNT,
1351      *        which do not agree to what errors should be thrown or not
1352      *        in case nToPage or nFromPage is out-of-range.
1353      */
1354     if (lppd->nMaxPage < lppd->nMinPage)
1355         lppd->nMaxPage = lppd->nMinPage;
1356     if (lppd->nMinPage == lppd->nMaxPage)
1357         lppd->Flags |= PD_NOPAGENUMS;
1358     if (lppd->nToPage < lppd->nMinPage)
1359         lppd->nToPage = lppd->nMinPage;
1360     if (lppd->nToPage > lppd->nMaxPage)
1361         lppd->nToPage = lppd->nMaxPage;
1362     if (lppd->nFromPage < lppd->nMinPage)
1363         lppd->nFromPage = lppd->nMinPage;
1364     if (lppd->nFromPage > lppd->nMaxPage)
1365         lppd->nFromPage = lppd->nMaxPage;
1366
1367     /* if we have the combo box, fill it */
1368     if (GetDlgItem(hDlg,comboID)) {
1369         /* Fill Combobox
1370          */
1371         pdn = GlobalLock(lppd->hDevNames);
1372         pdm = GlobalLock(lppd->hDevMode);
1373         if(pdn)
1374             name = (WCHAR*)pdn + pdn->wDeviceOffset;
1375         else if(pdm)
1376             name = pdm->dmDeviceName;
1377         PRINTDLG_SetUpPrinterListComboW(hDlg, comboID, name);
1378         if(pdm) GlobalUnlock(lppd->hDevMode);
1379         if(pdn) GlobalUnlock(lppd->hDevNames);
1380
1381         /* Now find selected printer and update rest of dlg */
1382         /* ansi is ok here */
1383         name = HeapAlloc(GetProcessHeap(),0,256*sizeof(WCHAR));
1384         if (GetDlgItemTextW(hDlg, comboID, name, 255))
1385             PRINTDLG_ChangePrinterW(hDlg, name, PrintStructures);
1386         HeapFree(GetProcessHeap(),0,name);
1387     } else {
1388         /* else use default printer */
1389         WCHAR name[200];
1390         DWORD dwBufLen = sizeof(name) / sizeof(WCHAR);
1391         BOOL ret = GetDefaultPrinterW(name, &dwBufLen);
1392
1393         if (ret)
1394             PRINTDLG_ChangePrinterW(hDlg, name, PrintStructures);
1395         else
1396             FIXME("No default printer found, expect problems!\n");
1397     }
1398     return TRUE;
1399 }
1400
1401 /***********************************************************************
1402  *                              PRINTDLG_WMCommand               [internal]
1403  */
1404 LRESULT PRINTDLG_WMCommandA(HWND hDlg, WPARAM wParam,
1405                         LPARAM lParam, PRINT_PTRA* PrintStructures)
1406 {
1407     LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
1408     UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1409     LPDEVMODEA lpdm = PrintStructures->lpDevMode;
1410
1411     switch (LOWORD(wParam))  {
1412     case IDOK:
1413         TRACE(" OK button was hit\n");
1414         if (PRINTDLG_UpdatePrintDlgA(hDlg, PrintStructures)!=TRUE) {
1415             FIXME("Update printdlg was not successful!\n");
1416             return(FALSE);
1417         }
1418         EndDialog(hDlg, TRUE);
1419         return(TRUE);
1420
1421     case IDCANCEL:
1422         TRACE(" CANCEL button was hit\n");
1423         EndDialog(hDlg, FALSE);
1424         return(FALSE);
1425
1426      case pshHelp:
1427         TRACE(" HELP button was hit\n");
1428         SendMessageA(lppd->hwndOwner, PrintStructures->HelpMessageID,
1429                                 (WPARAM) hDlg, (LPARAM) lppd);
1430         break;
1431
1432      case chx2:                         /* collate pages checkbox */
1433         if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
1434             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1435                                     (LPARAM)PrintStructures->hCollateIcon);
1436         else
1437             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1438                                     (LPARAM)PrintStructures->hNoCollateIcon);
1439         break;
1440      case edt1:                         /* from page nr editbox */
1441      case edt2:                         /* to page nr editbox */
1442         if (HIWORD(wParam)==EN_CHANGE) {
1443             WORD nToPage;
1444             WORD nFromPage;
1445             nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
1446             nToPage   = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
1447             if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
1448                 CheckRadioButton(hDlg, rad1, rad3, rad3);
1449         }
1450         break;
1451
1452     case edt3:
1453         if(HIWORD(wParam) == EN_CHANGE) {
1454             INT copies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
1455             if(copies <= 1)
1456                 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1457             else
1458                 EnableWindow(GetDlgItem(hDlg, chx2), TRUE);
1459         }
1460         break;
1461
1462 #if 0
1463      case psh1:                       /* Print Setup */
1464         {
1465             PRINTDLG16  pdlg;
1466
1467             if (!PrintStructures->dlg.lpPrintDlg16) {
1468                 FIXME("The 32bit print dialog does not have this button!?\n");
1469                 break;
1470             }
1471
1472             memcpy(&pdlg,PrintStructures->dlg.lpPrintDlg16,sizeof(pdlg));
1473             pdlg.Flags |= PD_PRINTSETUP;
1474             pdlg.hwndOwner = HWND_16(hDlg);
1475             if (!PrintDlg16(&pdlg))
1476                 break;
1477         }
1478         break;
1479 #endif
1480      case psh2:                       /* Properties button */
1481        {
1482          HANDLE hPrinter;
1483          char   PrinterName[256];
1484
1485          GetDlgItemTextA(hDlg, PrinterComboID, PrinterName, 255);
1486          if (!OpenPrinterA(PrinterName, &hPrinter, NULL)) {
1487              FIXME(" Call to OpenPrinter did not succeed!\n");
1488              break;
1489          }
1490          DocumentPropertiesA(hDlg, hPrinter, PrinterName,
1491                              PrintStructures->lpDevMode,
1492                              PrintStructures->lpDevMode,
1493                              DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
1494          ClosePrinter(hPrinter);
1495          break;
1496        }
1497
1498     case rad1: /* Paperorientation */
1499         if (lppd->Flags & PD_PRINTSETUP)
1500         {
1501               lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1502               SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1503                           (LPARAM)(PrintStructures->hPortraitIcon));
1504         }
1505         break;
1506
1507     case rad2: /* Paperorientation */
1508         if (lppd->Flags & PD_PRINTSETUP)
1509         {
1510               lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1511               SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1512                           (LPARAM)(PrintStructures->hLandscapeIcon));
1513         }
1514         break;
1515
1516     case cmb1: /* Printer Combobox in PRINT SETUP, quality combobox in PRINT */
1517          if (PrinterComboID != wParam) {
1518              FIXME("No handling for print quality combo box yet.\n");
1519              break;
1520          }
1521          /* FALLTHROUGH */
1522     case cmb4:                         /* Printer combobox */
1523          if (HIWORD(wParam)==CBN_SELCHANGE) {
1524              char   PrinterName[256];
1525              GetDlgItemTextA(hDlg, LOWORD(wParam), PrinterName, 255);
1526              PRINTDLG_ChangePrinterA(hDlg, PrinterName, PrintStructures);
1527          }
1528          break;
1529
1530     case cmb2: /* Papersize */
1531       {
1532           DWORD Sel = SendDlgItemMessageA(hDlg, cmb2, CB_GETCURSEL, 0, 0);
1533           if(Sel != CB_ERR)
1534               lpdm->u1.s1.dmPaperSize = SendDlgItemMessageA(hDlg, cmb2,
1535                                                             CB_GETITEMDATA,
1536                                                             Sel, 0);
1537       }
1538       break;
1539
1540     case cmb3: /* Bin */
1541       {
1542           DWORD Sel = SendDlgItemMessageA(hDlg, cmb3, CB_GETCURSEL, 0, 0);
1543           if(Sel != CB_ERR)
1544               lpdm->dmDefaultSource = SendDlgItemMessageA(hDlg, cmb3,
1545                                                           CB_GETITEMDATA, Sel,
1546                                                           0);
1547       }
1548       break;
1549     }
1550     if(lppd->Flags & PD_PRINTSETUP) {
1551         switch (LOWORD(wParam)) {
1552         case rad1:                         /* orientation */
1553         case rad2:
1554             if (IsDlgButtonChecked(hDlg, rad1) == BST_CHECKED) {
1555                 if(lpdm->u1.s1.dmOrientation != DMORIENT_PORTRAIT) {
1556                     lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1557                     SendDlgItemMessageA(hDlg, stc10, STM_SETIMAGE,
1558                                         (WPARAM)IMAGE_ICON,
1559                                         (LPARAM)PrintStructures->hPortraitIcon);
1560                     SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE,
1561                                         (WPARAM)IMAGE_ICON,
1562                                         (LPARAM)PrintStructures->hPortraitIcon);
1563                 }
1564             } else {
1565                 if(lpdm->u1.s1.dmOrientation != DMORIENT_LANDSCAPE) {
1566                     lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1567                     SendDlgItemMessageA(hDlg, stc10, STM_SETIMAGE,
1568                                         (WPARAM)IMAGE_ICON,
1569                                         (LPARAM)PrintStructures->hLandscapeIcon);
1570                     SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE,
1571                                         (WPARAM)IMAGE_ICON,
1572                                         (LPARAM)PrintStructures->hLandscapeIcon);
1573                 }
1574             }
1575             break;
1576         }
1577     }
1578     return FALSE;
1579 }
1580
1581 static LRESULT PRINTDLG_WMCommandW(HWND hDlg, WPARAM wParam,
1582                         LPARAM lParam, PRINT_PTRW* PrintStructures)
1583 {
1584     LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
1585     UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1586     LPDEVMODEW lpdm = PrintStructures->lpDevMode;
1587
1588     switch (LOWORD(wParam))  {
1589     case IDOK:
1590         TRACE(" OK button was hit\n");
1591         if (PRINTDLG_UpdatePrintDlgW(hDlg, PrintStructures)!=TRUE) {
1592             FIXME("Update printdlg was not successful!\n");
1593             return(FALSE);
1594         }
1595         EndDialog(hDlg, TRUE);
1596         return(TRUE);
1597
1598     case IDCANCEL:
1599         TRACE(" CANCEL button was hit\n");
1600         EndDialog(hDlg, FALSE);
1601         return(FALSE);
1602
1603      case pshHelp:
1604         TRACE(" HELP button was hit\n");
1605         SendMessageW(lppd->hwndOwner, PrintStructures->HelpMessageID,
1606                                 (WPARAM) hDlg, (LPARAM) lppd);
1607         break;
1608
1609      case chx2:                         /* collate pages checkbox */
1610         if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
1611             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1612                                     (LPARAM)PrintStructures->hCollateIcon);
1613         else
1614             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1615                                     (LPARAM)PrintStructures->hNoCollateIcon);
1616         break;
1617      case edt1:                         /* from page nr editbox */
1618      case edt2:                         /* to page nr editbox */
1619         if (HIWORD(wParam)==EN_CHANGE) {
1620             WORD nToPage;
1621             WORD nFromPage;
1622             nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
1623             nToPage   = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
1624             if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
1625                 CheckRadioButton(hDlg, rad1, rad3, rad3);
1626         }
1627         break;
1628
1629     case edt3:
1630         if(HIWORD(wParam) == EN_CHANGE) {
1631             INT copies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
1632             if(copies <= 1)
1633                 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1634             else
1635                 EnableWindow(GetDlgItem(hDlg, chx2), TRUE);
1636         }
1637         break;
1638
1639      case psh1:                       /* Print Setup */
1640         {
1641                 ERR("psh1 is called from 16bit code only, we should not get here.\n");
1642         }
1643         break;
1644      case psh2:                       /* Properties button */
1645        {
1646          HANDLE hPrinter;
1647          WCHAR  PrinterName[256];
1648
1649          if (!GetDlgItemTextW(hDlg, PrinterComboID, PrinterName, 255)) break;
1650          if (!OpenPrinterW(PrinterName, &hPrinter, NULL)) {
1651              FIXME(" Call to OpenPrinter did not succeed!\n");
1652              break;
1653          }
1654          DocumentPropertiesW(hDlg, hPrinter, PrinterName,
1655                              PrintStructures->lpDevMode,
1656                              PrintStructures->lpDevMode,
1657                              DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
1658          ClosePrinter(hPrinter);
1659          break;
1660        }
1661
1662     case rad1: /* Paperorientation */
1663         if (lppd->Flags & PD_PRINTSETUP)
1664         {
1665               lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1666               SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1667                           (LPARAM)(PrintStructures->hPortraitIcon));
1668         }
1669         break;
1670
1671     case rad2: /* Paperorientation */
1672         if (lppd->Flags & PD_PRINTSETUP)
1673         {
1674               lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1675               SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1676                           (LPARAM)(PrintStructures->hLandscapeIcon));
1677         }
1678         break;
1679
1680     case cmb1: /* Printer Combobox in PRINT SETUP, quality combobox in PRINT */
1681          if (PrinterComboID != wParam) {
1682              FIXME("No handling for print quality combo box yet.\n");
1683              break;
1684          }
1685          /* FALLTHROUGH */
1686     case cmb4:                         /* Printer combobox */
1687          if (HIWORD(wParam)==CBN_SELCHANGE) {
1688              WCHAR   PrinterName[256];
1689              GetDlgItemTextW(hDlg, LOWORD(wParam), PrinterName, 255);
1690              PRINTDLG_ChangePrinterW(hDlg, PrinterName, PrintStructures);
1691          }
1692          break;
1693
1694     case cmb2: /* Papersize */
1695       {
1696           DWORD Sel = SendDlgItemMessageA(hDlg, cmb2, CB_GETCURSEL, 0, 0);
1697           if(Sel != CB_ERR)
1698               lpdm->u1.s1.dmPaperSize = SendDlgItemMessageA(hDlg, cmb2,
1699                                                             CB_GETITEMDATA,
1700                                                             Sel, 0);
1701       }
1702       break;
1703
1704     case cmb3: /* Bin */
1705       {
1706           DWORD Sel = SendDlgItemMessageA(hDlg, cmb3, CB_GETCURSEL, 0, 0);
1707           if(Sel != CB_ERR)
1708               lpdm->dmDefaultSource = SendDlgItemMessageW(hDlg, cmb3,
1709                                                           CB_GETITEMDATA, Sel,
1710                                                           0);
1711       }
1712       break;
1713     }
1714     if(lppd->Flags & PD_PRINTSETUP) {
1715         switch (LOWORD(wParam)) {
1716         case rad1:                         /* orientation */
1717         case rad2:
1718             if (IsDlgButtonChecked(hDlg, rad1) == BST_CHECKED) {
1719                 if(lpdm->u1.s1.dmOrientation != DMORIENT_PORTRAIT) {
1720                     lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1721                     SendDlgItemMessageA(hDlg, stc10, STM_SETIMAGE,
1722                                         (WPARAM)IMAGE_ICON,
1723                                         (LPARAM)PrintStructures->hPortraitIcon);
1724                     SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE,
1725                                         (WPARAM)IMAGE_ICON,
1726                                         (LPARAM)PrintStructures->hPortraitIcon);
1727                 }
1728             } else {
1729                 if(lpdm->u1.s1.dmOrientation != DMORIENT_LANDSCAPE) {
1730                     lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1731                     SendDlgItemMessageA(hDlg, stc10, STM_SETIMAGE,
1732                                         (WPARAM)IMAGE_ICON,
1733                                         (LPARAM)PrintStructures->hLandscapeIcon);
1734                     SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE,
1735                                         (WPARAM)IMAGE_ICON,
1736                                         (LPARAM)PrintStructures->hLandscapeIcon);
1737                 }
1738             }
1739             break;
1740         }
1741     }
1742     return FALSE;
1743 }
1744
1745 /***********************************************************************
1746  *           PrintDlgProcA                      [internal]
1747  */
1748 INT_PTR CALLBACK PrintDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam,
1749                           LPARAM lParam)
1750 {
1751     PRINT_PTRA* PrintStructures;
1752     INT_PTR res = FALSE;
1753
1754     if (uMsg!=WM_INITDIALOG) {
1755         PrintStructures = (PRINT_PTRA*)GetPropA(hDlg,"__WINE_PRINTDLGDATA");
1756         if (!PrintStructures)
1757             return FALSE;
1758     } else {
1759         PrintStructures = (PRINT_PTRA*) lParam;
1760         SetPropA(hDlg,"__WINE_PRINTDLGDATA",PrintStructures);
1761         res = PRINTDLG_WMInitDialog(hDlg, wParam, PrintStructures);
1762
1763         if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK)
1764             res = PrintStructures->lpPrintDlg->lpfnPrintHook(
1765                 hDlg, uMsg, wParam, (LPARAM)PrintStructures->lpPrintDlg
1766             );
1767         return res;
1768     }
1769
1770     if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) {
1771         res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg,uMsg,wParam,
1772                                                          lParam);
1773         if(res) return res;
1774     }
1775
1776     switch (uMsg) {
1777     case WM_COMMAND:
1778         return PRINTDLG_WMCommandA(hDlg, wParam, lParam, PrintStructures);
1779
1780     case WM_DESTROY:
1781         DestroyIcon(PrintStructures->hCollateIcon);
1782         DestroyIcon(PrintStructures->hNoCollateIcon);
1783         DestroyIcon(PrintStructures->hPortraitIcon);
1784         DestroyIcon(PrintStructures->hLandscapeIcon);
1785         if(PrintStructures->hwndUpDown)
1786             DestroyWindow(PrintStructures->hwndUpDown);
1787         return FALSE;
1788     }
1789     return res;
1790 }
1791
1792 INT_PTR CALLBACK PrintDlgProcW(HWND hDlg, UINT uMsg, WPARAM wParam,
1793                           LPARAM lParam)
1794 {
1795     static const WCHAR propW[] = {'_','_','W','I','N','E','_','P','R','I','N','T','D','L','G','D','A','T','A',0};
1796     PRINT_PTRW* PrintStructures;
1797     INT_PTR res = FALSE;
1798
1799     if (uMsg!=WM_INITDIALOG) {
1800         PrintStructures = (PRINT_PTRW*) GetPropW(hDlg, propW);
1801         if (!PrintStructures)
1802             return FALSE;
1803     } else {
1804         PrintStructures = (PRINT_PTRW*) lParam;
1805         SetPropW(hDlg, propW, PrintStructures);
1806         res = PRINTDLG_WMInitDialogW(hDlg, wParam, PrintStructures);
1807
1808         if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK)
1809             res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg, uMsg, wParam, (LPARAM)PrintStructures->lpPrintDlg);
1810         return res;
1811     }
1812
1813     if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) {
1814         res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg,uMsg,wParam, lParam);
1815         if(res) return res;
1816     }
1817
1818     switch (uMsg) {
1819     case WM_COMMAND:
1820         return PRINTDLG_WMCommandW(hDlg, wParam, lParam, PrintStructures);
1821
1822     case WM_DESTROY:
1823         DestroyIcon(PrintStructures->hCollateIcon);
1824         DestroyIcon(PrintStructures->hNoCollateIcon);
1825         DestroyIcon(PrintStructures->hPortraitIcon);
1826         DestroyIcon(PrintStructures->hLandscapeIcon);
1827         if(PrintStructures->hwndUpDown)
1828             DestroyWindow(PrintStructures->hwndUpDown);
1829         return FALSE;
1830     }
1831     return res;
1832 }
1833
1834 /************************************************************
1835  *
1836  *      PRINTDLG_GetDlgTemplate
1837  *
1838  */
1839 static HGLOBAL PRINTDLG_GetDlgTemplateA(PRINTDLGA *lppd)
1840 {
1841     HRSRC hResInfo;
1842     HGLOBAL hDlgTmpl;
1843
1844     if (lppd->Flags & PD_PRINTSETUP) {
1845         if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
1846             hDlgTmpl = lppd->hSetupTemplate;
1847         } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {
1848             hResInfo = FindResourceA(lppd->hInstance,
1849                                      lppd->lpSetupTemplateName, (LPSTR)RT_DIALOG);
1850             hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
1851         } else {
1852             hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32_SETUP",
1853                                      (LPSTR)RT_DIALOG);
1854             hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
1855         }
1856     } else {
1857         if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
1858             hDlgTmpl = lppd->hPrintTemplate;
1859         } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
1860             hResInfo = FindResourceA(lppd->hInstance,
1861                                      lppd->lpPrintTemplateName,
1862                                      (LPSTR)RT_DIALOG);
1863             hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
1864         } else {
1865             hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32",
1866                                      (LPSTR)RT_DIALOG);
1867             hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
1868         }
1869     }
1870     return hDlgTmpl;
1871 }
1872
1873 static HGLOBAL PRINTDLG_GetDlgTemplateW(PRINTDLGW *lppd)
1874 {
1875     HRSRC hResInfo;
1876     HGLOBAL hDlgTmpl;
1877     static const WCHAR xpsetup[] = { 'P','R','I','N','T','3','2','_','S','E','T','U','P',0};
1878     static const WCHAR xprint[] = { 'P','R','I','N','T','3','2',0};
1879
1880     if (lppd->Flags & PD_PRINTSETUP) {
1881         if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
1882             hDlgTmpl = lppd->hSetupTemplate;
1883         } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {
1884             hResInfo = FindResourceW(lppd->hInstance,
1885                                      lppd->lpSetupTemplateName, (LPWSTR)RT_DIALOG);
1886             hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
1887         } else {
1888             hResInfo = FindResourceW(COMDLG32_hInstance, xpsetup, (LPWSTR)RT_DIALOG);
1889             hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
1890         }
1891     } else {
1892         if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
1893             hDlgTmpl = lppd->hPrintTemplate;
1894         } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
1895             hResInfo = FindResourceW(lppd->hInstance,
1896                                      lppd->lpPrintTemplateName,
1897                                      (LPWSTR)RT_DIALOG);
1898             hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
1899         } else {
1900             hResInfo = FindResourceW(COMDLG32_hInstance, xprint, (LPWSTR)RT_DIALOG);
1901             hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
1902         }
1903     }
1904     return hDlgTmpl;
1905 }
1906
1907 /***********************************************************************
1908  *
1909  *      PRINTDLG_CreateDC
1910  *
1911  */
1912 static BOOL PRINTDLG_CreateDCA(LPPRINTDLGA lppd)
1913 {
1914     DEVNAMES *pdn = GlobalLock(lppd->hDevNames);
1915     DEVMODEA *pdm = GlobalLock(lppd->hDevMode);
1916
1917     if(lppd->Flags & PD_RETURNDC) {
1918         lppd->hDC = CreateDCA((char*)pdn + pdn->wDriverOffset,
1919                               (char*)pdn + pdn->wDeviceOffset,
1920                               (char*)pdn + pdn->wOutputOffset,
1921                               pdm );
1922     } else if(lppd->Flags & PD_RETURNIC) {
1923         lppd->hDC = CreateICA((char*)pdn + pdn->wDriverOffset,
1924                               (char*)pdn + pdn->wDeviceOffset,
1925                               (char*)pdn + pdn->wOutputOffset,
1926                               pdm );
1927     }
1928     GlobalUnlock(lppd->hDevNames);
1929     GlobalUnlock(lppd->hDevMode);
1930     return lppd->hDC ? TRUE : FALSE;
1931 }
1932
1933 static BOOL PRINTDLG_CreateDCW(LPPRINTDLGW lppd)
1934 {
1935     DEVNAMES *pdn = GlobalLock(lppd->hDevNames);
1936     DEVMODEW *pdm = GlobalLock(lppd->hDevMode);
1937
1938     if(lppd->Flags & PD_RETURNDC) {
1939         lppd->hDC = CreateDCW((WCHAR*)pdn + pdn->wDriverOffset,
1940                               (WCHAR*)pdn + pdn->wDeviceOffset,
1941                               (WCHAR*)pdn + pdn->wOutputOffset,
1942                               pdm );
1943     } else if(lppd->Flags & PD_RETURNIC) {
1944         lppd->hDC = CreateICW((WCHAR*)pdn + pdn->wDriverOffset,
1945                               (WCHAR*)pdn + pdn->wDeviceOffset,
1946                               (WCHAR*)pdn + pdn->wOutputOffset,
1947                               pdm );
1948     }
1949     GlobalUnlock(lppd->hDevNames);
1950     GlobalUnlock(lppd->hDevMode);
1951     return lppd->hDC ? TRUE : FALSE;
1952 }
1953
1954 /***********************************************************************
1955  *           PrintDlgA   (COMDLG32.@)
1956  *
1957  *  Displays the the PRINT dialog box, which enables the user to specify
1958  *  specific properties of the print job.
1959  *
1960  * RETURNS
1961  *  nonzero if the user pressed the OK button
1962  *  zero    if the user cancelled the window or an error occurred
1963  *
1964  * BUGS
1965  *  PrintDlg:
1966  *  * The Collate Icons do not display, even though they are in the code.
1967  *  * The Properties Button(s) should call DocumentPropertiesA().
1968  *  PrintSetupDlg:
1969  *  * The Paper Orientation Icons are not implemented yet.
1970  *  * The Properties Button(s) should call DocumentPropertiesA().
1971  *  * Settings are not yet taken from a provided DevMode or
1972  *    default printer settings.
1973  */
1974
1975 BOOL WINAPI PrintDlgA(
1976                       LPPRINTDLGA lppd /* [in/out] ptr to PRINTDLG32 struct */
1977                       )
1978 {
1979     BOOL      bRet = FALSE;
1980     LPVOID   ptr;
1981     HINSTANCE hInst = (HINSTANCE)GetWindowLongA( lppd->hwndOwner, GWL_HINSTANCE );
1982
1983     if(TRACE_ON(commdlg)) {
1984         char flagstr[1000] = "";
1985         struct pd_flags *pflag = pd_flags;
1986         for( ; pflag->name; pflag++) {
1987             if(lppd->Flags & pflag->flag)
1988                 strcat(flagstr, pflag->name);
1989         }
1990         TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
1991               "pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
1992               "flags %08lx (%s)\n",
1993               lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
1994               lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
1995               lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
1996     }
1997
1998     if(lppd->lStructSize != sizeof(PRINTDLGA)) {
1999         WARN("structure size failure !!!\n");
2000         COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
2001         return FALSE;
2002     }
2003
2004     if(lppd->Flags & PD_RETURNDEFAULT) {
2005         PRINTER_INFO_2A *pbuf;
2006         DRIVER_INFO_3A  *dbuf;
2007         HANDLE hprn;
2008         DWORD needed;
2009
2010         if(lppd->hDevMode || lppd->hDevNames) {
2011             WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
2012             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2013             return FALSE;
2014         }
2015         if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
2016             WARN("Can't find default printer\n");
2017             COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
2018             return FALSE;
2019         }
2020
2021         GetPrinterA(hprn, 2, NULL, 0, &needed);
2022         pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
2023         GetPrinterA(hprn, 2, (LPBYTE)pbuf, needed, &needed);
2024
2025         GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
2026         dbuf = HeapAlloc(GetProcessHeap(),0,needed);
2027         if (!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) {
2028             ERR("GetPrinterDriverA failed, le %ld, fix your config for printer %s!\n",GetLastError(),pbuf->pPrinterName);
2029             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2030             return FALSE;
2031         }
2032         ClosePrinter(hprn);
2033
2034         PRINTDLG_CreateDevNames(&(lppd->hDevNames),
2035                                   dbuf->pDriverPath,
2036                                   pbuf->pPrinterName,
2037                                   pbuf->pPortName);
2038         lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
2039                                      pbuf->pDevMode->dmDriverExtra);
2040         ptr = GlobalLock(lppd->hDevMode);
2041         memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
2042                pbuf->pDevMode->dmDriverExtra);
2043         GlobalUnlock(lppd->hDevMode);
2044         HeapFree(GetProcessHeap(), 0, pbuf);
2045         HeapFree(GetProcessHeap(), 0, dbuf);
2046         bRet = TRUE;
2047     } else {
2048         HGLOBAL hDlgTmpl;
2049         PRINT_PTRA *PrintStructures;
2050
2051     /* load Dialog resources,
2052      * depending on Flags indicates Print32 or Print32_setup dialog
2053      */
2054         hDlgTmpl = PRINTDLG_GetDlgTemplateA(lppd);
2055         if (!hDlgTmpl) {
2056             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2057             return FALSE;
2058         }
2059         ptr = LockResource( hDlgTmpl );
2060         if (!ptr) {
2061             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2062             return FALSE;
2063         }
2064
2065         PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2066                                     sizeof(PRINT_PTRA));
2067         PrintStructures->lpPrintDlg = lppd;
2068
2069         /* and create & process the dialog .
2070          * -1 is failure, 0 is broken hwnd, everything else is ok.
2071          */
2072         bRet = (0<DialogBoxIndirectParamA(hInst, ptr, lppd->hwndOwner,
2073                                            PrintDlgProcA,
2074                                            (LPARAM)PrintStructures));
2075
2076         if(bRet) {
2077             DEVMODEA *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
2078             PRINTER_INFO_2A *pi = PrintStructures->lpPrinterInfo;
2079             DRIVER_INFO_3A *di = PrintStructures->lpDriverInfo;
2080
2081             if (lppd->hDevMode == 0) {
2082                 TRACE(" No hDevMode yet... Need to create my own\n");
2083                 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE,
2084                                         lpdm->dmSize + lpdm->dmDriverExtra);
2085             } else {
2086                 WORD locks;
2087                 if((locks = (GlobalFlags(lppd->hDevMode) & GMEM_LOCKCOUNT))) {
2088                     WARN("hDevMode has %d locks on it. Unlocking it now\n", locks);
2089                     while(locks--) {
2090                         GlobalUnlock(lppd->hDevMode);
2091                         TRACE("Now got %d locks\n", locks);
2092                     }
2093                 }
2094                 lppd->hDevMode = GlobalReAlloc(lppd->hDevMode,
2095                                                lpdm->dmSize + lpdm->dmDriverExtra,
2096                                                GMEM_MOVEABLE);
2097             }
2098             lpdmReturn = GlobalLock(lppd->hDevMode);
2099             memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
2100
2101             if (lppd->hDevNames != 0) {
2102                 WORD locks;
2103                 if((locks = (GlobalFlags(lppd->hDevNames) & GMEM_LOCKCOUNT))) {
2104                     WARN("hDevNames has %d locks on it. Unlocking it now\n", locks);
2105                     while(locks--)
2106                         GlobalUnlock(lppd->hDevNames);
2107                 }
2108             }
2109             PRINTDLG_CreateDevNames(&(lppd->hDevNames),
2110                     di->pDriverPath,
2111                     pi->pPrinterName,
2112                     pi->pPortName
2113             );
2114             GlobalUnlock(lppd->hDevMode);
2115         }
2116         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
2117         HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
2118         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo);
2119         HeapFree(GetProcessHeap(), 0, PrintStructures);
2120     }
2121     if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
2122         bRet = PRINTDLG_CreateDCA(lppd);
2123
2124     TRACE("exit! (%d)\n", bRet);
2125     return bRet;
2126 }
2127
2128 /***********************************************************************
2129  *           PrintDlgW   (COMDLG32.@)
2130  */
2131 BOOL WINAPI PrintDlgW(
2132                       LPPRINTDLGW lppd /* [in/out] ptr to PRINTDLG32 struct */
2133                       )
2134 {
2135     BOOL      bRet = FALSE;
2136     LPVOID   ptr;
2137     HINSTANCE hInst = (HINSTANCE)GetWindowLongW( lppd->hwndOwner, GWL_HINSTANCE );
2138
2139     if(TRACE_ON(commdlg)) {
2140         char flagstr[1000] = "";
2141         struct pd_flags *pflag = pd_flags;
2142         for( ; pflag->name; pflag++) {
2143             if(lppd->Flags & pflag->flag)
2144                 strcat(flagstr, pflag->name);
2145         }
2146         TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
2147               "pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
2148               "flags %08lx (%s)\n",
2149               lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
2150               lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
2151               lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
2152     }
2153
2154     if(lppd->lStructSize != sizeof(PRINTDLGW)) {
2155         WARN("structure size failure !!!\n");
2156         COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
2157         return FALSE;
2158     }
2159
2160     if(lppd->Flags & PD_RETURNDEFAULT) {
2161         PRINTER_INFO_2W *pbuf;
2162         DRIVER_INFO_3W  *dbuf;
2163         HANDLE hprn;
2164         DWORD needed;
2165
2166         if(lppd->hDevMode || lppd->hDevNames) {
2167             WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
2168             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2169             return FALSE;
2170         }
2171         if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
2172             WARN("Can't find default printer\n");
2173             COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
2174             return FALSE;
2175         }
2176
2177         GetPrinterW(hprn, 2, NULL, 0, &needed);
2178         pbuf = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*needed);
2179         GetPrinterW(hprn, 2, (LPBYTE)pbuf, needed, &needed);
2180
2181         GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
2182         dbuf = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*needed);
2183         if (!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) {
2184             ERR("GetPrinterDriverA failed, le %ld, fix your config for printer %s!\n",GetLastError(),debugstr_w(pbuf->pPrinterName));
2185             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2186             return FALSE;
2187         }
2188         ClosePrinter(hprn);
2189
2190         PRINTDLG_CreateDevNamesW(&(lppd->hDevNames),
2191                                   dbuf->pDriverPath,
2192                                   pbuf->pPrinterName,
2193                                   pbuf->pPortName);
2194         lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
2195                                      pbuf->pDevMode->dmDriverExtra);
2196         ptr = GlobalLock(lppd->hDevMode);
2197         memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
2198                pbuf->pDevMode->dmDriverExtra);
2199         GlobalUnlock(lppd->hDevMode);
2200         HeapFree(GetProcessHeap(), 0, pbuf);
2201         HeapFree(GetProcessHeap(), 0, dbuf);
2202         bRet = TRUE;
2203     } else {
2204         HGLOBAL hDlgTmpl;
2205         PRINT_PTRW *PrintStructures;
2206
2207     /* load Dialog resources,
2208      * depending on Flags indicates Print32 or Print32_setup dialog
2209      */
2210         hDlgTmpl = PRINTDLG_GetDlgTemplateW(lppd);
2211         if (!hDlgTmpl) {
2212             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2213             return FALSE;
2214         }
2215         ptr = LockResource( hDlgTmpl );
2216         if (!ptr) {
2217             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2218             return FALSE;
2219         }
2220
2221         PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2222                                     sizeof(PRINT_PTRW));
2223         PrintStructures->lpPrintDlg = lppd;
2224
2225         /* and create & process the dialog .
2226          * -1 is failure, 0 is broken hwnd, everything else is ok.
2227          */
2228         bRet = (0<DialogBoxIndirectParamW(hInst, ptr, lppd->hwndOwner,
2229                                            PrintDlgProcW,
2230                                            (LPARAM)PrintStructures));
2231
2232         if(bRet) {
2233             DEVMODEW *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
2234             PRINTER_INFO_2W *pi = PrintStructures->lpPrinterInfo;
2235             DRIVER_INFO_3W *di = PrintStructures->lpDriverInfo;
2236
2237             if (lppd->hDevMode == 0) {
2238                 TRACE(" No hDevMode yet... Need to create my own\n");
2239                 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE,
2240                                         lpdm->dmSize + lpdm->dmDriverExtra);
2241             } else {
2242                 WORD locks;
2243                 if((locks = (GlobalFlags(lppd->hDevMode) & GMEM_LOCKCOUNT))) {
2244                     WARN("hDevMode has %d locks on it. Unlocking it now\n", locks);
2245                     while(locks--) {
2246                         GlobalUnlock(lppd->hDevMode);
2247                         TRACE("Now got %d locks\n", locks);
2248                     }
2249                 }
2250                 lppd->hDevMode = GlobalReAlloc(lppd->hDevMode,
2251                                                lpdm->dmSize + lpdm->dmDriverExtra,
2252                                                GMEM_MOVEABLE);
2253             }
2254             lpdmReturn = GlobalLock(lppd->hDevMode);
2255             memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
2256
2257             if (lppd->hDevNames != 0) {
2258                 WORD locks;
2259                 if((locks = (GlobalFlags(lppd->hDevNames) & GMEM_LOCKCOUNT))) {
2260                     WARN("hDevNames has %d locks on it. Unlocking it now\n", locks);
2261                     while(locks--)
2262                         GlobalUnlock(lppd->hDevNames);
2263                 }
2264             }
2265             PRINTDLG_CreateDevNamesW(&(lppd->hDevNames),
2266                     di->pDriverPath,
2267                     pi->pPrinterName,
2268                     pi->pPortName
2269             );
2270             GlobalUnlock(lppd->hDevMode);
2271         }
2272         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
2273         HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
2274         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo);
2275         HeapFree(GetProcessHeap(), 0, PrintStructures);
2276     }
2277     if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
2278         bRet = PRINTDLG_CreateDCW(lppd);
2279
2280     TRACE("exit! (%d)\n", bRet);
2281     return bRet;
2282 }
2283
2284 /***********************************************************************
2285  *
2286  *          PageSetupDlg
2287  * rad1 - portrait
2288  * rad2 - landscape
2289  * cmb2 - paper size
2290  * cmb3 - source (tray?)
2291  * edt4 - border left
2292  * edt5 - border top
2293  * edt6 - border right
2294  * edt7 - border bottom
2295  * psh3 - "Printer..."
2296  */
2297
2298 typedef struct {
2299     LPPAGESETUPDLGA     dlga;
2300     PRINTDLGA           pdlg;
2301 } PageSetupDataA;
2302
2303 typedef struct {
2304     LPPAGESETUPDLGW     dlga;
2305     PRINTDLGW           pdlg;
2306 } PageSetupDataW;
2307
2308 static HGLOBAL PRINTDLG_GetPGSTemplateA(PAGESETUPDLGA *lppd)
2309 {
2310     HRSRC hResInfo;
2311     HGLOBAL hDlgTmpl;
2312
2313     if(lppd->Flags & PSD_ENABLEPAGESETUPTEMPLATEHANDLE) {
2314         hDlgTmpl = lppd->hPageSetupTemplate;
2315     } else if(lppd->Flags & PSD_ENABLEPAGESETUPTEMPLATE) {
2316         hResInfo = FindResourceA(lppd->hInstance,
2317                                  lppd->lpPageSetupTemplateName, (LPSTR)RT_DIALOG);
2318         hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2319     } else {
2320         hResInfo = FindResourceA(COMDLG32_hInstance,(LPCSTR)PAGESETUPDLGORD,(LPSTR)RT_DIALOG);
2321         hDlgTmpl = LoadResource(COMDLG32_hInstance,hResInfo);
2322     }
2323     return hDlgTmpl;
2324 }
2325
2326 static HGLOBAL PRINTDLG_GetPGSTemplateW(PAGESETUPDLGW *lppd)
2327 {
2328     HRSRC hResInfo;
2329     HGLOBAL hDlgTmpl;
2330
2331     if(lppd->Flags & PSD_ENABLEPAGESETUPTEMPLATEHANDLE) {
2332         hDlgTmpl = lppd->hPageSetupTemplate;
2333     } else if(lppd->Flags & PSD_ENABLEPAGESETUPTEMPLATE) {
2334         hResInfo = FindResourceW(lppd->hInstance,
2335                                  lppd->lpPageSetupTemplateName, (LPWSTR)RT_DIALOG);
2336         hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2337     } else {
2338         hResInfo = FindResourceW(COMDLG32_hInstance,(LPCWSTR)PAGESETUPDLGORD,(LPWSTR)RT_DIALOG);
2339         hDlgTmpl = LoadResource(COMDLG32_hInstance,hResInfo);
2340     }
2341     return hDlgTmpl;
2342 }
2343
2344 static DWORD
2345 _c_10mm2size(PAGESETUPDLGA *dlga,DWORD size) {
2346     if (dlga->Flags & PSD_INTHOUSANDTHSOFINCHES)
2347         return 10*size*10/25.4;
2348     /* If we don't have a flag, we can choose one. Use millimeters
2349      * to avoid confusing me
2350      */
2351     dlga->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
2352     return 10*size;
2353 }
2354
2355
2356 static DWORD
2357 _c_inch2size(PAGESETUPDLGA *dlga,DWORD size) {
2358     if (dlga->Flags & PSD_INTHOUSANDTHSOFINCHES)
2359         return size;
2360     if (dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS)
2361         return (size*254)/10;
2362     /* if we don't have a flag, we can choose one. Use millimeters
2363      * to avoid confusing me
2364      */
2365     dlga->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
2366     return (size*254)/10;
2367 }
2368
2369 static void
2370 _c_size2strA(PageSetupDataA *pda,DWORD size,LPSTR strout) {
2371     strcpy(strout,"<undef>");
2372     if (pda->dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS) {
2373         sprintf(strout,"%.2fmm",(size*1.0)/100.0);
2374         return;
2375     }
2376     if (pda->dlga->Flags & PSD_INTHOUSANDTHSOFINCHES) {
2377         sprintf(strout,"%.2fin",(size*1.0)/1000.0);
2378         return;
2379     }
2380     pda->dlga->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
2381     sprintf(strout,"%.2fmm",(size*1.0)/100.0);
2382     return;
2383 }
2384 static void
2385 _c_size2strW(PageSetupDataW *pda,DWORD size,LPSTR strout) {
2386     strcpy(strout,"<undef>");
2387     if (pda->dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS) {
2388         sprintf(strout,"%.2fmm",(size*1.0)/100.0);
2389         return;
2390     }
2391     if (pda->dlga->Flags & PSD_INTHOUSANDTHSOFINCHES) {
2392         sprintf(strout,"%.2fin",(size*1.0)/1000.0);
2393         return;
2394     }
2395     pda->dlga->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
2396     sprintf(strout,"%.2fmm",(size*1.0)/100.0);
2397     return;
2398 }
2399
2400 static DWORD
2401 _c_str2size(PAGESETUPDLGA *dlga,LPCSTR strin) {
2402     float       val;
2403     char        rest[200];
2404
2405     rest[0]='\0';
2406     if (!sscanf(strin,"%f%s",&val,rest))
2407         return 0;
2408
2409     if (!strcmp(rest,"in") || !strcmp(rest,"inch")) {
2410         if (dlga->Flags & PSD_INTHOUSANDTHSOFINCHES)
2411             return 1000*val;
2412         else
2413             return val*25.4*100;
2414     }
2415     if (!strcmp(rest,"cm")) { rest[0]='m'; val = val*10.0; }
2416     if (!strcmp(rest,"m")) { strcpy(rest,"mm"); val = val*1000.0; }
2417
2418     if (!strcmp(rest,"mm")) {
2419         if (dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS)
2420             return 100*val;
2421         else
2422             return 1000.0*val/25.4;
2423     }
2424     if (rest[0]=='\0') {
2425         /* use application supplied default */
2426         if (dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS) {
2427             /* 100*mm */
2428             return 100.0*val;
2429         }
2430         if (dlga->Flags & PSD_INTHOUSANDTHSOFINCHES) {
2431             /* 1000*inch */
2432             return 1000.0*val;
2433         }
2434     }
2435     ERR("Did not find a conversion for type '%s'!\n",rest);
2436     return 0;
2437 }
2438
2439
2440 /*
2441  * This is called on finish and will update the output fields of the
2442  * struct.
2443  */
2444 static BOOL
2445 PRINTDLG_PS_UpdateDlgStructA(HWND hDlg, PageSetupDataA *pda) {
2446     DEVNAMES    *dn;
2447     DEVMODEA    *dm;
2448     LPSTR       devname,portname;
2449     char        papername[64];
2450     char        buf[200];
2451
2452     dn = GlobalLock(pda->pdlg.hDevNames);
2453     dm = GlobalLock(pda->pdlg.hDevMode);
2454     devname     = ((char*)dn)+dn->wDeviceOffset;
2455     portname    = ((char*)dn)+dn->wOutputOffset;
2456     PRINTDLG_SetUpPaperComboBoxA(hDlg,cmb2,devname,portname,dm);
2457     PRINTDLG_SetUpPaperComboBoxA(hDlg,cmb3,devname,portname,dm);
2458
2459     if (GetDlgItemTextA(hDlg,cmb2,papername,sizeof(papername))>0) {
2460         PRINTDLG_PaperSizeA(&(pda->pdlg),papername,&(pda->dlga->ptPaperSize));
2461         pda->dlga->ptPaperSize.x = _c_10mm2size(pda->dlga,pda->dlga->ptPaperSize.x);
2462         pda->dlga->ptPaperSize.y = _c_10mm2size(pda->dlga,pda->dlga->ptPaperSize.y);
2463     } else
2464         FIXME("could not get dialog text for papersize cmbbox?\n");
2465 #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); }
2466     GETVAL(edt4,pda->dlga->rtMargin.left);
2467     GETVAL(edt5,pda->dlga->rtMargin.top);
2468     GETVAL(edt6,pda->dlga->rtMargin.right);
2469     GETVAL(edt7,pda->dlga->rtMargin.bottom);
2470 #undef GETVAL
2471
2472     /* If we are in landscape, swap x and y of page size */
2473     if (IsDlgButtonChecked(hDlg, rad2)) {
2474         DWORD tmp;
2475         tmp = pda->dlga->ptPaperSize.x;
2476         pda->dlga->ptPaperSize.x = pda->dlga->ptPaperSize.y;
2477         pda->dlga->ptPaperSize.y = tmp;
2478     }
2479     GlobalUnlock(pda->pdlg.hDevNames);
2480     GlobalUnlock(pda->pdlg.hDevMode);
2481     return TRUE;
2482 }
2483
2484 static BOOL
2485 PRINTDLG_PS_UpdateDlgStructW(HWND hDlg, PageSetupDataW *pda) {
2486     DEVNAMES    *dn;
2487     DEVMODEW    *dm;
2488     LPWSTR      devname,portname;
2489     WCHAR       papername[64];
2490
2491     char        buf[200];
2492
2493     dn = GlobalLock(pda->pdlg.hDevNames);
2494     dm = GlobalLock(pda->pdlg.hDevMode);
2495     devname     = ((WCHAR*)dn)+dn->wDeviceOffset;
2496     portname    = ((WCHAR*)dn)+dn->wOutputOffset;
2497     PRINTDLG_SetUpPaperComboBoxW(hDlg,cmb2,devname,portname,dm);
2498     PRINTDLG_SetUpPaperComboBoxW(hDlg,cmb3,devname,portname,dm);
2499
2500     if (GetDlgItemTextW(hDlg,cmb2,papername,sizeof(papername))>0) {
2501         PRINTDLG_PaperSizeW(&(pda->pdlg),papername,&(pda->dlga->ptPaperSize));
2502         pda->dlga->ptPaperSize.x = _c_10mm2size((LPPAGESETUPDLGA)pda->dlga,pda->dlga->ptPaperSize.x);
2503         pda->dlga->ptPaperSize.y = _c_10mm2size((LPPAGESETUPDLGA)pda->dlga,pda->dlga->ptPaperSize.y);
2504     } else
2505         FIXME("could not get dialog text for papersize cmbbox?\n");
2506 #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); }
2507     GETVAL(edt4,pda->dlga->rtMargin.left);
2508     GETVAL(edt5,pda->dlga->rtMargin.top);
2509     GETVAL(edt6,pda->dlga->rtMargin.right);
2510     GETVAL(edt7,pda->dlga->rtMargin.bottom);
2511 #undef GETVAL
2512
2513     /* If we are in landscape, swap x and y of page size */
2514     if (IsDlgButtonChecked(hDlg, rad2)) {
2515         DWORD tmp;
2516         tmp = pda->dlga->ptPaperSize.x;
2517         pda->dlga->ptPaperSize.x = pda->dlga->ptPaperSize.y;
2518         pda->dlga->ptPaperSize.y = tmp;
2519     }
2520     GlobalUnlock(pda->pdlg.hDevNames);
2521     GlobalUnlock(pda->pdlg.hDevMode);
2522     return TRUE;
2523 }
2524
2525 /*
2526  * This is called after returning from PrintDlg().
2527  */
2528 static BOOL
2529 PRINTDLG_PS_ChangePrinterA(HWND hDlg, PageSetupDataA *pda) {
2530     DEVNAMES    *dn;
2531     DEVMODEA    *dm;
2532     LPSTR       devname,portname;
2533
2534     dn = GlobalLock(pda->pdlg.hDevNames);
2535     dm = GlobalLock(pda->pdlg.hDevMode);
2536     devname     = ((char*)dn)+dn->wDeviceOffset;
2537     portname    = ((char*)dn)+dn->wOutputOffset;
2538     PRINTDLG_SetUpPaperComboBoxA(hDlg,cmb2,devname,portname,dm);
2539     PRINTDLG_SetUpPaperComboBoxA(hDlg,cmb3,devname,portname,dm);
2540     GlobalUnlock(pda->pdlg.hDevNames);
2541     GlobalUnlock(pda->pdlg.hDevMode);
2542     return TRUE;
2543 }
2544
2545 static BOOL
2546 PRINTDLG_PS_ChangePrinterW(HWND hDlg, PageSetupDataW *pda) {
2547     DEVNAMES    *dn;
2548     DEVMODEW    *dm;
2549     LPWSTR      devname,portname;
2550
2551     dn = GlobalLock(pda->pdlg.hDevNames);
2552     dm = GlobalLock(pda->pdlg.hDevMode);
2553     devname     = ((WCHAR*)dn)+dn->wDeviceOffset;
2554     portname    = ((WCHAR*)dn)+dn->wOutputOffset;
2555     PRINTDLG_SetUpPaperComboBoxW(hDlg,cmb2,devname,portname,dm);
2556     PRINTDLG_SetUpPaperComboBoxW(hDlg,cmb3,devname,portname,dm);
2557     GlobalUnlock(pda->pdlg.hDevNames);
2558     GlobalUnlock(pda->pdlg.hDevMode);
2559     return TRUE;
2560 }
2561
2562 static BOOL
2563 PRINTDLG_PS_WMCommandA(
2564     HWND hDlg, WPARAM wParam, LPARAM lParam, PageSetupDataA *pda
2565 ) {
2566     switch (LOWORD(wParam))  {
2567     case IDOK:
2568         if (!PRINTDLG_PS_UpdateDlgStructA(hDlg, pda))
2569             return(FALSE);
2570         EndDialog(hDlg, TRUE);
2571         return TRUE ;
2572
2573     case IDCANCEL:
2574         EndDialog(hDlg, FALSE);
2575         return FALSE ;
2576
2577     case psh3: {
2578         pda->pdlg.Flags         = 0;
2579         pda->pdlg.hwndOwner     = hDlg;
2580         if (PrintDlgA(&(pda->pdlg)))
2581             PRINTDLG_PS_ChangePrinterA(hDlg,pda);
2582         return TRUE;
2583     }
2584     }
2585     FIXME("loword (lparam) %d, wparam 0x%x, lparam %08lx, STUB mostly.\n",
2586             LOWORD(lParam),wParam,lParam
2587     );
2588     return FALSE;
2589 }
2590
2591 static BOOL
2592 PRINTDLG_PS_WMCommandW(
2593     HWND hDlg, WPARAM wParam, LPARAM lParam, PageSetupDataW *pda
2594 ) {
2595     switch (LOWORD(wParam))  {
2596     case IDOK:
2597         if (!PRINTDLG_PS_UpdateDlgStructW(hDlg, pda))
2598             return(FALSE);
2599         EndDialog(hDlg, TRUE);
2600         return TRUE ;
2601
2602     case IDCANCEL:
2603         EndDialog(hDlg, FALSE);
2604         return FALSE ;
2605
2606     case psh3: {
2607         pda->pdlg.Flags         = 0;
2608         pda->pdlg.hwndOwner     = hDlg;
2609         if (PrintDlgW(&(pda->pdlg)))
2610             PRINTDLG_PS_ChangePrinterW(hDlg,pda);
2611         return TRUE;
2612     }
2613     }
2614     FIXME("loword (lparam) %d, wparam 0x%x, lparam %08lx, STUB mostly.\n",
2615             LOWORD(lParam),wParam,lParam
2616     );
2617     return FALSE;
2618 }
2619
2620
2621 static INT_PTR CALLBACK
2622 PageDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
2623 {
2624     PageSetupDataA      *pda;
2625     INT_PTR             res = FALSE;
2626
2627     if (uMsg==WM_INITDIALOG) {
2628         res = TRUE;
2629         pda = (PageSetupDataA*)lParam;
2630         SetPropA(hDlg,"__WINE_PAGESETUPDLGDATA",pda);
2631         if (pda->dlga->Flags & PSD_ENABLEPAGESETUPHOOK) {
2632             res = pda->dlga->lpfnPageSetupHook(hDlg,uMsg,wParam,(LPARAM)pda->dlga);
2633             if (!res) {
2634                 FIXME("Setup page hook failed?\n");
2635                 res = TRUE;
2636             }
2637         }
2638         if (pda->dlga->Flags & PSD_ENABLEPAGEPAINTHOOK) {
2639             FIXME("PagePaintHook not yet implemented!\n");
2640         }
2641         if (pda->dlga->Flags & PSD_DISABLEPRINTER)
2642             EnableWindow(GetDlgItem(hDlg, psh3), FALSE);
2643         if (pda->dlga->Flags & PSD_DISABLEMARGINS) {
2644             EnableWindow(GetDlgItem(hDlg, edt4), FALSE);
2645             EnableWindow(GetDlgItem(hDlg, edt5), FALSE);
2646             EnableWindow(GetDlgItem(hDlg, edt6), FALSE);
2647             EnableWindow(GetDlgItem(hDlg, edt7), FALSE);
2648         }
2649         /* width larger as height -> landscape */
2650         if (pda->dlga->ptPaperSize.x > pda->dlga->ptPaperSize.y)
2651             CheckRadioButton(hDlg, rad1, rad2, rad2);
2652         else /* this is default if papersize is not set */
2653             CheckRadioButton(hDlg, rad1, rad2, rad1);
2654         if (pda->dlga->Flags & PSD_DISABLEORIENTATION) {
2655             EnableWindow(GetDlgItem(hDlg,rad1),FALSE);
2656             EnableWindow(GetDlgItem(hDlg,rad2),FALSE);
2657         }
2658         /* We fill them out enabled or not */
2659         if (pda->dlga->Flags & PSD_MARGINS) {
2660             char str[100];
2661             _c_size2strA(pda,pda->dlga->rtMargin.left,str);
2662             SetDlgItemTextA(hDlg,edt4,str);
2663             _c_size2strA(pda,pda->dlga->rtMargin.top,str);
2664             SetDlgItemTextA(hDlg,edt5,str);
2665             _c_size2strA(pda,pda->dlga->rtMargin.right,str);
2666             SetDlgItemTextA(hDlg,edt6,str);
2667             _c_size2strA(pda,pda->dlga->rtMargin.bottom,str);
2668             SetDlgItemTextA(hDlg,edt7,str);
2669         } else {
2670             /* default is 1 inch */
2671             DWORD size = _c_inch2size(pda->dlga,1000);
2672             char        str[20];
2673             _c_size2strA(pda,size,str);
2674             SetDlgItemTextA(hDlg,edt4,str);
2675             SetDlgItemTextA(hDlg,edt5,str);
2676             SetDlgItemTextA(hDlg,edt6,str);
2677             SetDlgItemTextA(hDlg,edt7,str);
2678         }
2679         PRINTDLG_PS_ChangePrinterA(hDlg,pda);
2680         if (pda->dlga->Flags & PSD_DISABLEPAPER) {
2681             EnableWindow(GetDlgItem(hDlg,cmb2),FALSE);
2682             EnableWindow(GetDlgItem(hDlg,cmb3),FALSE);
2683         }
2684         return TRUE;
2685     } else {
2686         pda = (PageSetupDataA*)GetPropA(hDlg,"__WINE_PAGESETUPDLGDATA");
2687         if (!pda) {
2688             WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
2689             return FALSE;
2690         }
2691         if (pda->dlga->Flags & PSD_ENABLEPAGESETUPHOOK) {
2692             res = pda->dlga->lpfnPageSetupHook(hDlg,uMsg,wParam,lParam);
2693             if (res) return res;
2694         }
2695     }
2696     switch (uMsg) {
2697     case WM_COMMAND:
2698         return PRINTDLG_PS_WMCommandA(hDlg, wParam, lParam, pda);
2699     }
2700     return FALSE;
2701 }
2702
2703 static INT_PTR CALLBACK
2704 PageDlgProcW(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
2705 {
2706     PageSetupDataW      *pda;
2707     BOOL                res = FALSE;
2708
2709     if (uMsg==WM_INITDIALOG) {
2710         res = TRUE;
2711         pda = (PageSetupDataW*)lParam;
2712         SetPropA(hDlg,"__WINE_PAGESETUPDLGDATA",pda);
2713         if (pda->dlga->Flags & PSD_ENABLEPAGESETUPHOOK) {
2714             res = pda->dlga->lpfnPageSetupHook(hDlg,uMsg,wParam,(LPARAM)pda->dlga);
2715             if (!res) {
2716                 FIXME("Setup page hook failed?\n");
2717                 res = TRUE;
2718             }
2719         }
2720         if (pda->dlga->Flags & PSD_ENABLEPAGEPAINTHOOK) {
2721             FIXME("PagePaintHook not yet implemented!\n");
2722         }
2723         if (pda->dlga->Flags & PSD_DISABLEPRINTER)
2724             EnableWindow(GetDlgItem(hDlg, psh3), FALSE);
2725         if (pda->dlga->Flags & PSD_DISABLEMARGINS) {
2726             EnableWindow(GetDlgItem(hDlg, edt4), FALSE);
2727             EnableWindow(GetDlgItem(hDlg, edt5), FALSE);
2728             EnableWindow(GetDlgItem(hDlg, edt6), FALSE);
2729             EnableWindow(GetDlgItem(hDlg, edt7), FALSE);
2730         }
2731         /* width larger as height -> landscape */
2732         if (pda->dlga->ptPaperSize.x > pda->dlga->ptPaperSize.y)
2733             CheckRadioButton(hDlg, rad1, rad2, rad2);
2734         else /* this is default if papersize is not set */
2735             CheckRadioButton(hDlg, rad1, rad2, rad1);
2736         if (pda->dlga->Flags & PSD_DISABLEORIENTATION) {
2737             EnableWindow(GetDlgItem(hDlg,rad1),FALSE);
2738             EnableWindow(GetDlgItem(hDlg,rad2),FALSE);
2739         }
2740         /* We fill them out enabled or not */
2741         if (pda->dlga->Flags & PSD_MARGINS) {
2742             char str[100];
2743             _c_size2strW(pda,pda->dlga->rtMargin.left,str);
2744             SetDlgItemTextA(hDlg,edt4,str);
2745             _c_size2strW(pda,pda->dlga->rtMargin.top,str);
2746             SetDlgItemTextA(hDlg,edt5,str);
2747             _c_size2strW(pda,pda->dlga->rtMargin.right,str);
2748             SetDlgItemTextA(hDlg,edt6,str);
2749             _c_size2strW(pda,pda->dlga->rtMargin.bottom,str);
2750             SetDlgItemTextA(hDlg,edt7,str);
2751         } else {
2752             /* default is 1 inch */
2753             DWORD size = _c_inch2size((LPPAGESETUPDLGA)pda->dlga,1000);
2754             char        str[20];
2755             _c_size2strW(pda,size,str);
2756             SetDlgItemTextA(hDlg,edt4,str);
2757             SetDlgItemTextA(hDlg,edt5,str);
2758             SetDlgItemTextA(hDlg,edt6,str);
2759             SetDlgItemTextA(hDlg,edt7,str);
2760         }
2761         PRINTDLG_PS_ChangePrinterW(hDlg,pda);
2762         if (pda->dlga->Flags & PSD_DISABLEPAPER) {
2763             EnableWindow(GetDlgItem(hDlg,cmb2),FALSE);
2764             EnableWindow(GetDlgItem(hDlg,cmb3),FALSE);
2765         }
2766         return TRUE;
2767     } else {
2768         pda = (PageSetupDataW*)GetPropA(hDlg,"__WINE_PAGESETUPDLGDATA");
2769         if (!pda) {
2770             WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
2771             return FALSE;
2772         }
2773         if (pda->dlga->Flags & PSD_ENABLEPAGESETUPHOOK) {
2774             res = pda->dlga->lpfnPageSetupHook(hDlg,uMsg,wParam,lParam);
2775             if (res) return res;
2776         }
2777     }
2778     switch (uMsg) {
2779     case WM_COMMAND:
2780         return PRINTDLG_PS_WMCommandW(hDlg, wParam, lParam, pda);
2781     }
2782     return FALSE;
2783 }
2784
2785 /***********************************************************************
2786  *            PageSetupDlgA  (COMDLG32.@)
2787  */
2788 BOOL WINAPI PageSetupDlgA(LPPAGESETUPDLGA setupdlg) {
2789     HGLOBAL             hDlgTmpl;
2790     LPVOID              ptr;
2791     BOOL                bRet;
2792     PageSetupDataA      *pda;
2793     PRINTDLGA           pdlg;
2794
2795     if(TRACE_ON(commdlg)) {
2796         char flagstr[1000] = "";
2797         struct pd_flags *pflag = psd_flags;
2798         for( ; pflag->name; pflag++) {
2799             if(setupdlg->Flags & pflag->flag) {
2800                 strcat(flagstr, pflag->name);
2801                 strcat(flagstr, "|");
2802             }
2803         }
2804         TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
2805               "hinst %p, flags %08lx (%s)\n",
2806               setupdlg, setupdlg->hwndOwner, setupdlg->hDevMode,
2807               setupdlg->hDevNames,
2808               setupdlg->hInstance, setupdlg->Flags, flagstr);
2809     }
2810
2811     /* First get default printer data, we need it right after that. */
2812     memset(&pdlg,0,sizeof(pdlg));
2813     pdlg.lStructSize    = sizeof(pdlg);
2814     pdlg.Flags          = PD_RETURNDEFAULT;
2815     bRet = PrintDlgA(&pdlg);
2816     if (!bRet) return FALSE;
2817
2818     /* short cut exit, just return default values */
2819     if (setupdlg->Flags & PSD_RETURNDEFAULT) {
2820         setupdlg->hDevMode      = pdlg.hDevMode;
2821         setupdlg->hDevNames     = pdlg.hDevNames;
2822         /* FIXME: Just return "A4" for now. */
2823         PRINTDLG_PaperSizeA(&pdlg,"A4",&setupdlg->ptPaperSize);
2824         setupdlg->ptPaperSize.x=_c_10mm2size(setupdlg,setupdlg->ptPaperSize.x);
2825         setupdlg->ptPaperSize.y=_c_10mm2size(setupdlg,setupdlg->ptPaperSize.y);
2826         return TRUE;
2827     }
2828     hDlgTmpl = PRINTDLG_GetPGSTemplateA(setupdlg);
2829     if (!hDlgTmpl) {
2830         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2831         return FALSE;
2832     }
2833     ptr = LockResource( hDlgTmpl );
2834     if (!ptr) {
2835         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2836         return FALSE;
2837     }
2838     pda = HeapAlloc(GetProcessHeap(),0,sizeof(*pda));
2839     pda->dlga = setupdlg;
2840     memcpy(&pda->pdlg,&pdlg,sizeof(pdlg));
2841
2842     bRet = (0<DialogBoxIndirectParamA(
2843                 setupdlg->hInstance,
2844                 ptr,
2845                 setupdlg->hwndOwner,
2846                 PageDlgProcA,
2847                 (LPARAM)pda)
2848     );
2849     return bRet;
2850 }
2851 /***********************************************************************
2852  *            PageSetupDlgW  (COMDLG32.@)
2853  */
2854 BOOL WINAPI PageSetupDlgW(LPPAGESETUPDLGW setupdlg) {
2855     HGLOBAL             hDlgTmpl;
2856     LPVOID              ptr;
2857     BOOL                bRet;
2858     PageSetupDataW      *pdw;
2859     PRINTDLGW           pdlg;
2860
2861     if(TRACE_ON(commdlg)) {
2862         char flagstr[1000] = "";
2863         struct pd_flags *pflag = psd_flags;
2864         for( ; pflag->name; pflag++) {
2865             if(setupdlg->Flags & pflag->flag) {
2866                 strcat(flagstr, pflag->name);
2867                 strcat(flagstr, "|");
2868             }
2869         }
2870         TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
2871               "hinst %p, flags %08lx (%s)\n",
2872               setupdlg, setupdlg->hwndOwner, setupdlg->hDevMode,
2873               setupdlg->hDevNames,
2874               setupdlg->hInstance, setupdlg->Flags, flagstr);
2875     }
2876
2877     /* First get default printer data, we need it right after that. */
2878     memset(&pdlg,0,sizeof(pdlg));
2879     pdlg.lStructSize    = sizeof(pdlg);
2880     pdlg.Flags          = PD_RETURNDEFAULT;
2881     bRet = PrintDlgW(&pdlg);
2882     if (!bRet) return FALSE;
2883
2884     /* short cut exit, just return default values */
2885     if (setupdlg->Flags & PSD_RETURNDEFAULT) {
2886         static const WCHAR a4[] = {'A','4',0};
2887         setupdlg->hDevMode      = pdlg.hDevMode;
2888         setupdlg->hDevNames     = pdlg.hDevNames;
2889         /* FIXME: Just return "A4" for now. */
2890         PRINTDLG_PaperSizeW(&pdlg,a4,&setupdlg->ptPaperSize);
2891         setupdlg->ptPaperSize.x=_c_10mm2size((LPPAGESETUPDLGA)setupdlg,setupdlg->ptPaperSize.x);
2892         setupdlg->ptPaperSize.y=_c_10mm2size((LPPAGESETUPDLGA)setupdlg,setupdlg->ptPaperSize.y);
2893         return TRUE;
2894     }
2895     hDlgTmpl = PRINTDLG_GetPGSTemplateW(setupdlg);
2896     if (!hDlgTmpl) {
2897         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2898         return FALSE;
2899     }
2900     ptr = LockResource( hDlgTmpl );
2901     if (!ptr) {
2902         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2903         return FALSE;
2904     }
2905     pdw = HeapAlloc(GetProcessHeap(),0,sizeof(*pdw));
2906     pdw->dlga = setupdlg;
2907     memcpy(&pdw->pdlg,&pdlg,sizeof(pdlg));
2908
2909     bRet = (0<DialogBoxIndirectParamW(
2910                 setupdlg->hInstance,
2911                 ptr,
2912                 setupdlg->hwndOwner,
2913                 PageDlgProcW,
2914                 (LPARAM)pdw)
2915     );
2916     return bRet;
2917 }
2918
2919 /***********************************************************************
2920  *      PrintDlgExA (COMDLG32.@)
2921  */
2922 HRESULT WINAPI PrintDlgExA(LPVOID lpPrintDlgExA) /* [???] FIXME: LPPRINTDLGEXA */
2923 {
2924         FIXME("stub\n");
2925         return E_NOTIMPL;
2926 }
2927 /***********************************************************************
2928  *      PrintDlgExW (COMDLG32.@)
2929  */
2930 HRESULT WINAPI PrintDlgExW(LPVOID lpPrintDlgExW) /* [???] FIXME: LPPRINTDLGEXW */
2931 {
2932         FIXME("stub\n");
2933         return E_NOTIMPL;
2934 }