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