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