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