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