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