cabinet: Add initial tests for FDI.
[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",GetLastError(),pbuf->pPrinterName);
2063             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2064             return FALSE;
2065         }
2066         ClosePrinter(hprn);
2067
2068         PRINTDLG_CreateDevNames(&(lppd->hDevNames),
2069                                   dbuf->pDriverPath,
2070                                   pbuf->pPrinterName,
2071                                   pbuf->pPortName);
2072         lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
2073                                      pbuf->pDevMode->dmDriverExtra);
2074         ptr = GlobalLock(lppd->hDevMode);
2075         memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
2076                pbuf->pDevMode->dmDriverExtra);
2077         GlobalUnlock(lppd->hDevMode);
2078         HeapFree(GetProcessHeap(), 0, pbuf);
2079         HeapFree(GetProcessHeap(), 0, dbuf);
2080         bRet = TRUE;
2081     } else {
2082         HGLOBAL hDlgTmpl;
2083         PRINT_PTRA *PrintStructures;
2084
2085     /* load Dialog resources,
2086      * depending on Flags indicates Print32 or Print32_setup dialog
2087      */
2088         hDlgTmpl = PRINTDLG_GetDlgTemplateA(lppd);
2089         if (!hDlgTmpl) {
2090             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2091             return FALSE;
2092         }
2093         ptr = LockResource( hDlgTmpl );
2094         if (!ptr) {
2095             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2096             return FALSE;
2097         }
2098
2099         PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2100                                     sizeof(PRINT_PTRA));
2101         PrintStructures->lpPrintDlg = lppd;
2102
2103         /* and create & process the dialog .
2104          * -1 is failure, 0 is broken hwnd, everything else is ok.
2105          */
2106         bRet = (0<DialogBoxIndirectParamA(hInst, ptr, lppd->hwndOwner,
2107                                            PrintDlgProcA,
2108                                            (LPARAM)PrintStructures));
2109
2110         if(bRet) {
2111             DEVMODEA *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
2112             PRINTER_INFO_2A *pi = PrintStructures->lpPrinterInfo;
2113             DRIVER_INFO_3A *di = PrintStructures->lpDriverInfo;
2114
2115             if (lppd->hDevMode == 0) {
2116                 TRACE(" No hDevMode yet... Need to create my own\n");
2117                 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE,
2118                                         lpdm->dmSize + lpdm->dmDriverExtra);
2119             } else {
2120                 lppd->hDevMode = GlobalReAlloc(lppd->hDevMode,
2121                                                lpdm->dmSize + lpdm->dmDriverExtra,
2122                                                GMEM_MOVEABLE);
2123             }
2124             lpdmReturn = GlobalLock(lppd->hDevMode);
2125             memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
2126
2127             PRINTDLG_CreateDevNames(&(lppd->hDevNames),
2128                     di->pDriverPath,
2129                     pi->pPrinterName,
2130                     pi->pPortName
2131             );
2132             GlobalUnlock(lppd->hDevMode);
2133         }
2134         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
2135         HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
2136         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo);
2137         HeapFree(GetProcessHeap(), 0, PrintStructures);
2138     }
2139     if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
2140         bRet = PRINTDLG_CreateDCA(lppd);
2141
2142     TRACE("exit! (%d)\n", bRet);
2143     return bRet;
2144 }
2145
2146 /***********************************************************************
2147  *           PrintDlgW   (COMDLG32.@)
2148  *
2149  * See PrintDlgA.
2150  */
2151 BOOL WINAPI PrintDlgW(LPPRINTDLGW lppd)
2152 {
2153     BOOL      bRet = FALSE;
2154     LPVOID    ptr;
2155     HINSTANCE hInst;
2156
2157     if (!lppd)
2158     {
2159         COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION);
2160         return FALSE;
2161     }
2162
2163     hInst = (HINSTANCE)GetWindowLongPtrW( lppd->hwndOwner, GWLP_HINSTANCE );
2164     if(TRACE_ON(commdlg)) {
2165         char flagstr[1000] = "";
2166         const struct pd_flags *pflag = pd_flags;
2167         for( ; pflag->name; pflag++) {
2168             if(lppd->Flags & pflag->flag)
2169                 strcat(flagstr, pflag->name);
2170         }
2171         TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
2172               "pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
2173               "flags %08x (%s)\n",
2174               lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
2175               lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
2176               lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
2177     }
2178
2179     if(lppd->lStructSize != sizeof(PRINTDLGW)) {
2180         WARN("structure size failure !!!\n");
2181         COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
2182         return FALSE;
2183     }
2184
2185     if(lppd->Flags & PD_RETURNDEFAULT) {
2186         PRINTER_INFO_2W *pbuf;
2187         DRIVER_INFO_3W  *dbuf;
2188         HANDLE hprn;
2189         DWORD needed;
2190
2191         if(lppd->hDevMode || lppd->hDevNames) {
2192             WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
2193             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2194             return FALSE;
2195         }
2196         if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
2197             WARN("Can't find default printer\n");
2198             COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
2199             return FALSE;
2200         }
2201
2202         GetPrinterW(hprn, 2, NULL, 0, &needed);
2203         pbuf = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*needed);
2204         GetPrinterW(hprn, 2, (LPBYTE)pbuf, needed, &needed);
2205
2206         GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
2207         dbuf = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*needed);
2208         if (!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) {
2209             ERR("GetPrinterDriverA failed, le %d, fix your config for printer %s!\n",GetLastError(),debugstr_w(pbuf->pPrinterName));
2210             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2211             return FALSE;
2212         }
2213         ClosePrinter(hprn);
2214
2215         PRINTDLG_CreateDevNamesW(&(lppd->hDevNames),
2216                                   dbuf->pDriverPath,
2217                                   pbuf->pPrinterName,
2218                                   pbuf->pPortName);
2219         lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
2220                                      pbuf->pDevMode->dmDriverExtra);
2221         ptr = GlobalLock(lppd->hDevMode);
2222         memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
2223                pbuf->pDevMode->dmDriverExtra);
2224         GlobalUnlock(lppd->hDevMode);
2225         HeapFree(GetProcessHeap(), 0, pbuf);
2226         HeapFree(GetProcessHeap(), 0, dbuf);
2227         bRet = TRUE;
2228     } else {
2229         HGLOBAL hDlgTmpl;
2230         PRINT_PTRW *PrintStructures;
2231
2232     /* load Dialog resources,
2233      * depending on Flags indicates Print32 or Print32_setup dialog
2234      */
2235         hDlgTmpl = PRINTDLG_GetDlgTemplateW(lppd);
2236         if (!hDlgTmpl) {
2237             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2238             return FALSE;
2239         }
2240         ptr = LockResource( hDlgTmpl );
2241         if (!ptr) {
2242             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2243             return FALSE;
2244         }
2245
2246         PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2247                                     sizeof(PRINT_PTRW));
2248         PrintStructures->lpPrintDlg = lppd;
2249
2250         /* and create & process the dialog .
2251          * -1 is failure, 0 is broken hwnd, everything else is ok.
2252          */
2253         bRet = (0<DialogBoxIndirectParamW(hInst, ptr, lppd->hwndOwner,
2254                                            PrintDlgProcW,
2255                                            (LPARAM)PrintStructures));
2256
2257         if(bRet) {
2258             DEVMODEW *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
2259             PRINTER_INFO_2W *pi = PrintStructures->lpPrinterInfo;
2260             DRIVER_INFO_3W *di = PrintStructures->lpDriverInfo;
2261
2262             if (lppd->hDevMode == 0) {
2263                 TRACE(" No hDevMode yet... Need to create my own\n");
2264                 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE,
2265                                         lpdm->dmSize + lpdm->dmDriverExtra);
2266             } else {
2267                 WORD locks;
2268                 if((locks = (GlobalFlags(lppd->hDevMode) & GMEM_LOCKCOUNT))) {
2269                     WARN("hDevMode has %d locks on it. Unlocking it now\n", locks);
2270                     while(locks--) {
2271                         GlobalUnlock(lppd->hDevMode);
2272                         TRACE("Now got %d locks\n", locks);
2273                     }
2274                 }
2275                 lppd->hDevMode = GlobalReAlloc(lppd->hDevMode,
2276                                                lpdm->dmSize + lpdm->dmDriverExtra,
2277                                                GMEM_MOVEABLE);
2278             }
2279             lpdmReturn = GlobalLock(lppd->hDevMode);
2280             memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
2281
2282             if (lppd->hDevNames != 0) {
2283                 WORD locks;
2284                 if((locks = (GlobalFlags(lppd->hDevNames) & GMEM_LOCKCOUNT))) {
2285                     WARN("hDevNames has %d locks on it. Unlocking it now\n", locks);
2286                     while(locks--)
2287                         GlobalUnlock(lppd->hDevNames);
2288                 }
2289             }
2290             PRINTDLG_CreateDevNamesW(&(lppd->hDevNames),
2291                     di->pDriverPath,
2292                     pi->pPrinterName,
2293                     pi->pPortName
2294             );
2295             GlobalUnlock(lppd->hDevMode);
2296         }
2297         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
2298         HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
2299         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo);
2300         HeapFree(GetProcessHeap(), 0, PrintStructures);
2301     }
2302     if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
2303         bRet = PRINTDLG_CreateDCW(lppd);
2304
2305     TRACE("exit! (%d)\n", bRet);
2306     return bRet;
2307 }
2308
2309 /***********************************************************************
2310  *
2311  *          PageSetupDlg
2312  * rad1 - portrait
2313  * rad2 - landscape
2314  * cmb1 - printer select (not in standard dialog template)
2315  * cmb2 - paper size
2316  * cmb3 - source (tray?)
2317  * edt4 - border left
2318  * edt5 - border top
2319  * edt6 - border right
2320  * edt7 - border bottom
2321  * psh3 - "Printer..."
2322  */
2323
2324 typedef struct {
2325     LPPAGESETUPDLGA     dlga; /* Handler to user defined struct */
2326     PRINTDLGA           pdlg;
2327     HWND                hDlg; /* Page Setup dialog handler */
2328     PAGESETUPDLGA       curdlg; /* Stores the current dialog state */
2329     RECT                rtDrawRect; /* Drawing rect for page */
2330 } PageSetupDataA;
2331
2332 typedef struct {
2333     LPPAGESETUPDLGW     dlga;
2334     PRINTDLGW           pdlg;
2335 } PageSetupDataW;
2336
2337
2338 static HGLOBAL PRINTDLG_GetPGSTemplateA(const PAGESETUPDLGA *lppd)
2339 {
2340     HRSRC hResInfo;
2341     HGLOBAL hDlgTmpl;
2342         
2343     if(lppd->Flags & PSD_ENABLEPAGESETUPTEMPLATEHANDLE) {
2344         hDlgTmpl = lppd->hPageSetupTemplate;
2345     } else if(lppd->Flags & PSD_ENABLEPAGESETUPTEMPLATE) {
2346         hResInfo = FindResourceA(lppd->hInstance,
2347                                  lppd->lpPageSetupTemplateName, (LPSTR)RT_DIALOG);
2348         hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2349     } else {
2350         hResInfo = FindResourceA(COMDLG32_hInstance,(LPCSTR)PAGESETUPDLGORD,(LPSTR)RT_DIALOG);
2351         hDlgTmpl = LoadResource(COMDLG32_hInstance,hResInfo);
2352     }
2353     return hDlgTmpl;
2354 }
2355
2356 static HGLOBAL PRINTDLG_GetPGSTemplateW(const PAGESETUPDLGW *lppd)
2357 {
2358     HRSRC hResInfo;
2359     HGLOBAL hDlgTmpl;
2360
2361     if(lppd->Flags & PSD_ENABLEPAGESETUPTEMPLATEHANDLE) {
2362         hDlgTmpl = lppd->hPageSetupTemplate;
2363     } else if(lppd->Flags & PSD_ENABLEPAGESETUPTEMPLATE) {
2364         hResInfo = FindResourceW(lppd->hInstance,
2365                                  lppd->lpPageSetupTemplateName, (LPWSTR)RT_DIALOG);
2366         hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2367     } else {
2368         hResInfo = FindResourceW(COMDLG32_hInstance,(LPCWSTR)PAGESETUPDLGORD,(LPWSTR)RT_DIALOG);
2369         hDlgTmpl = LoadResource(COMDLG32_hInstance,hResInfo);
2370     }
2371     return hDlgTmpl;
2372 }
2373
2374 static DWORD
2375 _c_10mm2size(PAGESETUPDLGA *dlga,DWORD size) {
2376     if (dlga->Flags & PSD_INTHOUSANDTHSOFINCHES)
2377         return 10*size*100/254;
2378     /* If we don't have a flag, we can choose one. Use millimeters
2379      * to avoid confusing me
2380      */
2381     dlga->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
2382     return 10*size;
2383 }
2384
2385
2386 static DWORD
2387 _c_inch2size(PAGESETUPDLGA *dlga,DWORD size) {
2388     if (dlga->Flags & PSD_INTHOUSANDTHSOFINCHES)
2389         return size;
2390     if (dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS)
2391         return (size*254)/100;
2392     /* if we don't have a flag, we can choose one. Use millimeters
2393      * to avoid confusing me
2394      */
2395     dlga->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
2396     return (size*254)/100;
2397 }
2398
2399 static void
2400 _c_size2strA(PageSetupDataA *pda,DWORD size,LPSTR strout) {
2401     strcpy(strout,"<undef>");
2402     if (pda->dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS) {
2403         sprintf(strout,"%d",(size)/100);
2404         return;
2405     }
2406     if (pda->dlga->Flags & PSD_INTHOUSANDTHSOFINCHES) {
2407         sprintf(strout,"%din",(size)/1000);
2408         return;
2409     }
2410     pda->dlga->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
2411     sprintf(strout,"%d",(size)/100);
2412     return;
2413 }
2414 static void
2415 _c_size2strW(PageSetupDataW *pda,DWORD size,LPWSTR strout) {
2416     static const char mm_fmt[] = "%.2f mm";
2417     static const char in_fmt[] = "%.2f in";
2418     char buf[20];
2419     if (pda->dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS) {
2420         sprintf(buf, mm_fmt, (size * 1.0) / 100.0);
2421     } else if (pda->dlga->Flags & PSD_INTHOUSANDTHSOFINCHES) {
2422         sprintf(buf, in_fmt, (size * 1.0) / 1000.0);
2423     } else {
2424         pda->dlga->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
2425         sprintf(buf, mm_fmt, (size * 1.0) / 100.0);
2426     }
2427
2428     MultiByteToWideChar(CP_ACP, 0, buf, -1, strout, 20);
2429 }
2430
2431 static DWORD
2432 _c_str2sizeA(const PAGESETUPDLGA *dlga, LPCSTR strin) {
2433     float       val;
2434     char        rest[200];
2435
2436     rest[0]='\0';
2437     if (!sscanf(strin,"%f%s",&val,rest))
2438         return 0;
2439
2440     if (!strcmp(rest,"in") || !strcmp(rest,"inch")) {
2441         if (dlga->Flags & PSD_INTHOUSANDTHSOFINCHES)
2442             return 1000*val;
2443         else
2444             return val*25.4*100;
2445     }
2446     if (!strcmp(rest,"cm")) { rest[0]='m'; val = val*10.0; }
2447     if (!strcmp(rest,"m")) { strcpy(rest,"mm"); val = val*1000.0; }
2448
2449     if (!strcmp(rest,"mm")) {
2450         if (dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS)
2451             return 100*val;
2452         else
2453             return 1000.0*val/25.4;
2454     }
2455     if (rest[0]=='\0') {
2456         /* use application supplied default */
2457         if (dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS) {
2458             /* 100*mm */
2459             return 100.0*val;
2460         }
2461         if (dlga->Flags & PSD_INTHOUSANDTHSOFINCHES) {
2462             /* 1000*inch */
2463             return 1000.0*val;
2464         }
2465     }
2466     ERR("Did not find a conversion for type '%s'!\n",rest);
2467     return 0;
2468 }
2469
2470
2471 static DWORD
2472 _c_str2sizeW(const PAGESETUPDLGW *dlga, LPCWSTR strin) {
2473     char        buf[200];
2474
2475     /* this W -> A transition is OK */
2476     /* we need a unicode version of sscanf to avoid it */
2477     WideCharToMultiByte(CP_ACP, 0, strin, -1, buf, sizeof(buf), NULL, NULL);
2478     return _c_str2sizeA((const PAGESETUPDLGA *)dlga, buf);
2479 }
2480
2481
2482 /****************************************************************************
2483  * PRINTDLG_PS_UpdateDlgStructA
2484  *
2485  * Updates pda->dlga structure 
2486  * Function calls when user presses OK button
2487  *
2488  * PARAMS
2489  *  hDlg        [in]     main window dialog HANDLE
2490  *  pda         [in/out] ptr to PageSetupDataA structure
2491  *
2492  * RETURNS
2493  *  TRUE
2494  */
2495 static BOOL
2496 PRINTDLG_PS_UpdateDlgStructA(HWND hDlg, PageSetupDataA *pda) {
2497     DEVNAMES    *dn;
2498     DEVMODEA    *dm;
2499     DWORD       paperword;
2500
2501     memcpy(pda->dlga, &pda->curdlg, sizeof(pda->curdlg));
2502     pda->dlga->hDevMode  = pda->pdlg.hDevMode;
2503     pda->dlga->hDevNames = pda->pdlg.hDevNames;
2504     
2505     dn = GlobalLock(pda->pdlg.hDevNames);
2506     dm = GlobalLock(pda->pdlg.hDevMode);
2507
2508     /* Save paper orientation into device context */
2509     if(pda->curdlg.ptPaperSize.x > pda->curdlg.ptPaperSize.y)
2510         dm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
2511     else
2512         dm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
2513
2514     /* Save paper size into the device context */
2515     paperword = SendDlgItemMessageA(hDlg,cmb2,CB_GETITEMDATA,
2516         SendDlgItemMessageA(hDlg, cmb2, CB_GETCURSEL, 0, 0), 0);
2517     if (paperword != CB_ERR)
2518         dm->u1.s1.dmPaperSize = paperword;
2519     else
2520         FIXME("could not get dialog text for papersize cmbbox?\n");
2521
2522     /* Save paper source into the device context */
2523     paperword = SendDlgItemMessageA(hDlg,cmb1,CB_GETITEMDATA,
2524         SendDlgItemMessageA(hDlg, cmb1, CB_GETCURSEL, 0, 0), 0);
2525     if (paperword != CB_ERR)
2526         dm->dmDefaultSource = paperword;
2527     else
2528         FIXME("could not get dialog text for papersize cmbbox?\n");
2529
2530     GlobalUnlock(pda->pdlg.hDevNames);
2531     GlobalUnlock(pda->pdlg.hDevMode);
2532
2533     return TRUE;
2534 }
2535
2536 static BOOL
2537 PRINTDLG_PS_UpdateDlgStructW(HWND hDlg, PageSetupDataW *pda) {
2538     DEVNAMES    *dn;
2539     DEVMODEW    *dm;
2540     LPWSTR      devname,portname;
2541     WCHAR       papername[64];
2542     WCHAR       buf[200];
2543
2544     dn = GlobalLock(pda->pdlg.hDevNames);
2545     dm = GlobalLock(pda->pdlg.hDevMode);
2546     devname     = ((WCHAR*)dn)+dn->wDeviceOffset;
2547     portname    = ((WCHAR*)dn)+dn->wOutputOffset;
2548
2549     /* Save paper size into device context */
2550     PRINTDLG_SetUpPaperComboBoxW(hDlg,cmb2,devname,portname,dm);
2551     /* Save paper source into device context */
2552     PRINTDLG_SetUpPaperComboBoxW(hDlg,cmb3,devname,portname,dm);
2553
2554     if (GetDlgItemTextW(hDlg,cmb2,papername,sizeof(papername))>0) {
2555         PRINTDLG_PaperSizeW(&(pda->pdlg),papername,&(pda->dlga->ptPaperSize));
2556         pda->dlga->ptPaperSize.x = _c_10mm2size((LPPAGESETUPDLGA)pda->dlga,pda->dlga->ptPaperSize.x);
2557         pda->dlga->ptPaperSize.y = _c_10mm2size((LPPAGESETUPDLGA)pda->dlga,pda->dlga->ptPaperSize.y);
2558     } else
2559         FIXME("could not get dialog text for papersize cmbbox?\n");
2560 #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); }
2561     GETVAL(edt4,pda->dlga->rtMargin.left);
2562     GETVAL(edt5,pda->dlga->rtMargin.top);
2563     GETVAL(edt6,pda->dlga->rtMargin.right);
2564     GETVAL(edt7,pda->dlga->rtMargin.bottom);
2565 #undef GETVAL
2566
2567     /* If we are in landscape, swap x and y of page size */
2568     if (IsDlgButtonChecked(hDlg, rad2)) {
2569         DWORD tmp;
2570         tmp = pda->dlga->ptPaperSize.x;
2571         pda->dlga->ptPaperSize.x = pda->dlga->ptPaperSize.y;
2572         pda->dlga->ptPaperSize.y = tmp;
2573     }
2574
2575     /* Save orientation */
2576     if (pda->dlga->ptPaperSize.x > pda->dlga->ptPaperSize.y)
2577         dm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
2578     else
2579         dm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
2580
2581     GlobalUnlock(pda->pdlg.hDevNames);
2582     GlobalUnlock(pda->pdlg.hDevMode);
2583     return TRUE;
2584 }
2585
2586 /**********************************************************************************************
2587  * PRINTDLG_PS_ChangeActivePrinerA
2588  *
2589  * Redefines hDevMode and hDevNames HANDLES and initialises it.
2590  * 
2591  * PARAMS
2592  *      name    [in]     Name of a printer for activation
2593  *      pda     [in/out] ptr to PageSetupDataA structure
2594  *      
2595  * RETURN 
2596  *      TRUE if success
2597  *      FALSE if fail
2598  */
2599 static BOOL
2600 PRINTDLG_PS_ChangeActivePrinterA(LPSTR name, PageSetupDataA *pda){
2601         HANDLE            hprn;
2602         DWORD             needed;
2603         LPPRINTER_INFO_2A lpPrinterInfo;
2604         LPDRIVER_INFO_3A  lpDriverInfo;
2605         DEVMODEA          *pDevMode, *dm;
2606         
2607         if(!OpenPrinterA(name, &hprn, NULL)){
2608                 ERR("Can't open printer %s\n", name);
2609                 return FALSE;
2610         }
2611         GetPrinterA(hprn, 2, NULL, 0, &needed);
2612         lpPrinterInfo = HeapAlloc(GetProcessHeap(), 0, needed);
2613         GetPrinterA(hprn, 2, (LPBYTE)lpPrinterInfo, needed, &needed);
2614         GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
2615         lpDriverInfo  = HeapAlloc(GetProcessHeap(), 0, needed);
2616         if(!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)lpDriverInfo, needed, &needed)) {
2617                 ERR("GetPrinterDriverA failed for %s, fix your config!\n", lpPrinterInfo->pPrinterName);
2618                 return FALSE;
2619         }
2620         ClosePrinter(hprn);
2621         
2622         needed = DocumentPropertiesA(0, 0, name, NULL, NULL, 0);
2623         if(needed == -1) {
2624                 ERR("DocumentProperties fails on %s\n", debugstr_a(name));
2625                 return FALSE;
2626         }
2627         pDevMode = HeapAlloc(GetProcessHeap(), 0, needed);
2628         DocumentPropertiesA(0, 0, name, pDevMode, NULL, DM_OUT_BUFFER);
2629
2630         pda->pdlg.hDevMode = GlobalReAlloc(pda->pdlg.hDevMode,
2631                                          pDevMode->dmSize + pDevMode->dmDriverExtra,
2632                                                          GMEM_MOVEABLE);
2633         dm = GlobalLock(pda->pdlg.hDevMode);
2634         memcpy(dm, pDevMode, pDevMode->dmSize + pDevMode->dmDriverExtra);
2635         
2636         PRINTDLG_CreateDevNames(&(pda->pdlg.hDevNames),
2637                         lpDriverInfo->pDriverPath,
2638                         lpPrinterInfo->pPrinterName,
2639                         lpPrinterInfo->pPortName);
2640         
2641         GlobalUnlock(pda->pdlg.hDevMode);
2642         HeapFree(GetProcessHeap(), 0, pDevMode);
2643         HeapFree(GetProcessHeap(), 0, lpPrinterInfo);
2644         HeapFree(GetProcessHeap(), 0, lpDriverInfo);
2645         return TRUE;
2646 }
2647
2648 /****************************************************************************************
2649  *  PRINTDLG_PS_ChangePrinterA
2650  *
2651  *  Fills Printers, Paper and Source combo
2652  *
2653  *  RETURNS 
2654  *   TRUE
2655  */
2656 static BOOL
2657 PRINTDLG_PS_ChangePrinterA(HWND hDlg, PageSetupDataA *pda) {
2658     DEVNAMES    *dn;
2659     DEVMODEA    *dm;
2660     LPSTR       devname,portname;
2661         
2662     dn = GlobalLock(pda->pdlg.hDevNames);
2663     dm = GlobalLock(pda->pdlg.hDevMode);
2664     devname         = ((char*)dn)+dn->wDeviceOffset;
2665     portname    = ((char*)dn)+dn->wOutputOffset;
2666     PRINTDLG_SetUpPrinterListComboA(hDlg, cmb1, devname);
2667     PRINTDLG_SetUpPaperComboBoxA(hDlg,cmb2,devname,portname,dm);
2668     PRINTDLG_SetUpPaperComboBoxA(hDlg,cmb3,devname,portname,dm);
2669     GlobalUnlock(pda->pdlg.hDevNames);
2670     GlobalUnlock(pda->pdlg.hDevMode);
2671     return TRUE;
2672 }
2673
2674 static BOOL
2675 PRINTDLG_PS_ChangePrinterW(HWND hDlg, PageSetupDataW *pda) {
2676     DEVNAMES    *dn;
2677     DEVMODEW    *dm;
2678     LPWSTR      devname,portname;
2679
2680     dn = GlobalLock(pda->pdlg.hDevNames);
2681     dm = GlobalLock(pda->pdlg.hDevMode);
2682     devname     = ((WCHAR*)dn)+dn->wDeviceOffset;
2683     portname    = ((WCHAR*)dn)+dn->wOutputOffset;
2684     PRINTDLG_SetUpPaperComboBoxW(hDlg,cmb2,devname,portname,dm);
2685     PRINTDLG_SetUpPaperComboBoxW(hDlg,cmb3,devname,portname,dm);
2686     GlobalUnlock(pda->pdlg.hDevNames);
2687     GlobalUnlock(pda->pdlg.hDevMode);
2688     return TRUE;
2689 }
2690
2691 /******************************************************************************************
2692  * PRINTDLG_PS_ChangePaperPrev 
2693  * 
2694  * Changes paper preview size / position
2695  *
2696  * PARAMS:
2697  *      pda             [i] Pointer for current PageSetupDataA structure
2698  *
2699  * RETURNS:
2700  *  always - TRUE
2701  */
2702 static BOOL 
2703 PRINTDLG_PS_ChangePaperPrev(const PageSetupDataA *pda)
2704 {
2705     LONG width, height, x, y;
2706     RECT rtTmp;
2707     
2708     if(pda->curdlg.ptPaperSize.x > pda->curdlg.ptPaperSize.y) {
2709         width  = pda->rtDrawRect.right - pda->rtDrawRect.left;
2710         height = pda->curdlg.ptPaperSize.y * width / pda->curdlg.ptPaperSize.x;
2711     } else {
2712         height = pda->rtDrawRect.bottom - pda->rtDrawRect.top;
2713         width  = pda->curdlg.ptPaperSize.x * height / pda->curdlg.ptPaperSize.y;
2714     }
2715     x = (pda->rtDrawRect.right + pda->rtDrawRect.left - width) / 2;
2716     y = (pda->rtDrawRect.bottom + pda->rtDrawRect.top - height) / 2;
2717     TRACE("rtDrawRect(%d, %d, %d, %d) x=%d, y=%d, w=%d, h=%d\n",
2718         pda->rtDrawRect.left, pda->rtDrawRect.top, pda->rtDrawRect.right, pda->rtDrawRect.bottom,
2719         x, y, width, height);
2720
2721 #define SHADOW 4
2722     MoveWindow(GetDlgItem(pda->hDlg, rct2), x+width, y+SHADOW, SHADOW, height, FALSE);
2723     MoveWindow(GetDlgItem(pda->hDlg, rct3), x+SHADOW, y+height, width, SHADOW, FALSE);
2724     MoveWindow(GetDlgItem(pda->hDlg, rct1), x, y, width, height, FALSE);
2725     memcpy(&rtTmp, &pda->rtDrawRect, sizeof(RECT));
2726     rtTmp.right  += SHADOW;
2727     rtTmp.bottom += SHADOW;
2728 #undef SHADOW 
2729
2730     InvalidateRect(pda->hDlg, &rtTmp, TRUE);
2731     return TRUE;
2732 }
2733
2734 #define GETVAL(idc,val) \
2735 if(msg == EN_CHANGE){ \
2736     if (GetDlgItemTextA(hDlg,idc,buf,sizeof(buf)) > 0)\
2737         val = _c_str2sizeA(pda->dlga,buf); \
2738     else\
2739         FIXME("could not get dlgitemtexta for %x\n",id);  \
2740 }
2741
2742 /********************************************************************************
2743  * PRINTDLG_PS_WMCommandA
2744  * process WM_COMMAND message for PageSetupDlgA
2745  *
2746  * PARAMS
2747  *  hDlg        [in]    Main dialog HANDLE 
2748  *  wParam      [in]    WM_COMMAND wParam
2749  *  lParam      [in]    WM_COMMAND lParam
2750  *  pda         [in/out] ptr to PageSetupDataA
2751  */
2752
2753 static BOOL
2754 PRINTDLG_PS_WMCommandA(
2755     HWND hDlg, WPARAM wParam, LPARAM lParam, PageSetupDataA *pda
2756 ) {
2757     WORD msg = HIWORD(wParam);
2758     WORD id  = LOWORD(wParam);
2759     char buf[200];
2760         
2761     TRACE("loword (lparam) %d, wparam 0x%lx, lparam %08lx\n",
2762             LOWORD(lParam),wParam,lParam);
2763     switch (id)  {
2764     case IDOK:
2765         if (!PRINTDLG_PS_UpdateDlgStructA(hDlg, pda))
2766             return(FALSE);
2767         EndDialog(hDlg, TRUE);
2768         return TRUE ;
2769
2770     case IDCANCEL:
2771         EndDialog(hDlg, FALSE);
2772         return FALSE ;
2773
2774     case psh3: {
2775         pda->pdlg.Flags         = 0;
2776         pda->pdlg.hwndOwner     = hDlg;
2777         if (PrintDlgA(&(pda->pdlg)))
2778             PRINTDLG_PS_ChangePrinterA(hDlg,pda);
2779         }
2780         return TRUE;
2781     case rad1:
2782             if (pda->curdlg.ptPaperSize.x > pda->curdlg.ptPaperSize.y){
2783                 DWORD tmp = pda->curdlg.ptPaperSize.x;
2784                 pda->curdlg.ptPaperSize.x = pda->curdlg.ptPaperSize.y;
2785                 pda->curdlg.ptPaperSize.y = tmp;
2786             }
2787             PRINTDLG_PS_ChangePaperPrev(pda);
2788         break;
2789     case rad2:
2790             if (pda->curdlg.ptPaperSize.y > pda->curdlg.ptPaperSize.x){
2791                 DWORD tmp = pda->curdlg.ptPaperSize.x;
2792                 pda->curdlg.ptPaperSize.x = pda->curdlg.ptPaperSize.y;
2793                 pda->curdlg.ptPaperSize.y = tmp;
2794             }
2795             PRINTDLG_PS_ChangePaperPrev(pda);
2796             break;
2797     case cmb1: /* Printer combo */
2798             if(msg == CBN_SELCHANGE){
2799                 char crPrinterName[256];
2800                 GetDlgItemTextA(hDlg, id, crPrinterName, 255);
2801                 PRINTDLG_PS_ChangeActivePrinterA(crPrinterName, pda);
2802                 PRINTDLG_PS_ChangePrinterA(hDlg, pda);
2803             }
2804             break;
2805     case cmb2: /* Paper combo */
2806         if(msg == CBN_SELCHANGE){
2807             DWORD paperword = SendDlgItemMessageA(hDlg,cmb2,CB_GETITEMDATA,
2808                 SendDlgItemMessageA(hDlg, cmb2, CB_GETCURSEL, 0, 0), 0);
2809             if (paperword != CB_ERR) {
2810                 PRINTDLG_PaperSizeA(&(pda->pdlg), paperword,&(pda->curdlg.ptPaperSize));
2811                 pda->curdlg.ptPaperSize.x = _c_10mm2size(pda->dlga,pda->curdlg.ptPaperSize.x);
2812                 pda->curdlg.ptPaperSize.y = _c_10mm2size(pda->dlga,pda->curdlg.ptPaperSize.y);
2813             
2814                 if (IsDlgButtonChecked(hDlg, rad2)) {
2815                     DWORD tmp = pda->curdlg.ptPaperSize.x;
2816                     pda->curdlg.ptPaperSize.x = pda->curdlg.ptPaperSize.y;
2817                     pda->curdlg.ptPaperSize.y = tmp;
2818                 }
2819                 PRINTDLG_PS_ChangePaperPrev(pda);
2820             } else
2821                 FIXME("could not get dialog text for papersize cmbbox?\n");
2822         }    
2823         break;
2824     case cmb3:
2825         if(msg == CBN_SELCHANGE){
2826             DEVMODEA *dm = GlobalLock(pda->pdlg.hDevMode);
2827             dm->dmDefaultSource = SendDlgItemMessageA(hDlg, cmb3,CB_GETITEMDATA,
2828                 SendDlgItemMessageA(hDlg, cmb3, CB_GETCURSEL, 0, 0), 0);
2829             GlobalUnlock(pda->pdlg.hDevMode);
2830         }
2831         break;
2832     case psh2:                       /* Printer Properties button */
2833        {
2834             HANDLE hPrinter;
2835             char   PrinterName[256];
2836             DEVMODEA *dm;
2837             LRESULT  count;
2838             int      i;
2839             
2840             GetDlgItemTextA(hDlg, cmb1, PrinterName, 255);
2841             if (!OpenPrinterA(PrinterName, &hPrinter, NULL)) {
2842                 FIXME("Call to OpenPrinter did not succeed!\n");
2843                 break;
2844             }
2845             dm = GlobalLock(pda->pdlg.hDevMode);
2846             DocumentPropertiesA(hDlg, hPrinter, PrinterName, dm, dm,
2847                                 DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
2848             ClosePrinter(hPrinter);
2849             /* Changing paper */
2850             PRINTDLG_PaperSizeA(&(pda->pdlg), dm->u1.s1.dmPaperSize, &(pda->curdlg.ptPaperSize));
2851             pda->curdlg.ptPaperSize.x = _c_10mm2size(pda->dlga, pda->curdlg.ptPaperSize.x);
2852             pda->curdlg.ptPaperSize.y = _c_10mm2size(pda->dlga, pda->curdlg.ptPaperSize.y);
2853             if (dm->u1.s1.dmOrientation == DMORIENT_LANDSCAPE){
2854                 DWORD tmp = pda->curdlg.ptPaperSize.x;
2855                 pda->curdlg.ptPaperSize.x = pda->curdlg.ptPaperSize.y;
2856                 pda->curdlg.ptPaperSize.y = tmp;
2857                 CheckRadioButton(hDlg, rad1, rad2, rad2);
2858             }
2859             else
2860                 CheckRadioButton(hDlg, rad1, rad2, rad1);
2861             /* Changing paper preview */
2862             PRINTDLG_PS_ChangePaperPrev(pda);
2863             /* Selecting paper in combo */
2864             count = SendDlgItemMessageA(hDlg, cmb2, CB_GETCOUNT, 0, 0);
2865             if(count != CB_ERR){ 
2866                 for(i=0; i<count; ++i){
2867                     if(SendDlgItemMessageA(hDlg, cmb2, CB_GETITEMDATA, i, 0) == dm->u1.s1.dmPaperSize) {
2868                         SendDlgItemMessageA(hDlg, cmb2, CB_SETCURSEL, i, 0);
2869                         break;
2870                     }
2871                 }
2872             }
2873                                                                             
2874             GlobalUnlock(pda->pdlg.hDevMode);
2875             break;
2876         }       
2877     case edt4:
2878         GETVAL(id, pda->curdlg.rtMargin.left);
2879         break;
2880     case edt5:
2881         GETVAL(id, pda->curdlg.rtMargin.right);
2882         break;
2883     case edt6:
2884         GETVAL(id, pda->curdlg.rtMargin.top);
2885         break;
2886     case edt7:
2887         GETVAL(id, pda->curdlg.rtMargin.bottom);
2888         break;
2889     }
2890     InvalidateRect(GetDlgItem(hDlg, rct1), NULL, TRUE);
2891     return FALSE;
2892 }
2893 #undef GETVAL                      
2894
2895 static BOOL
2896 PRINTDLG_PS_WMCommandW(
2897     HWND hDlg, WPARAM wParam, LPARAM lParam, PageSetupDataW *pda
2898 ) {
2899     TRACE("loword (lparam) %d, wparam 0x%lx, lparam %08lx\n",
2900             LOWORD(lParam),wParam,lParam);
2901     switch (LOWORD(wParam))  {
2902     case IDOK:
2903         if (!PRINTDLG_PS_UpdateDlgStructW(hDlg, pda))
2904             return(FALSE);
2905         EndDialog(hDlg, TRUE);
2906         return TRUE ;
2907
2908     case IDCANCEL:
2909         EndDialog(hDlg, FALSE);
2910         return FALSE ;
2911
2912     case psh3: {
2913         pda->pdlg.Flags         = 0;
2914         pda->pdlg.hwndOwner     = hDlg;
2915         if (PrintDlgW(&(pda->pdlg)))
2916             PRINTDLG_PS_ChangePrinterW(hDlg,pda);
2917         return TRUE;
2918     }
2919     }
2920     return FALSE;
2921 }
2922
2923
2924 /***********************************************************************
2925  *           DefaultPagePaintHook
2926  * Default hook paint procedure that receives WM_PSD_* messages from the dialog box 
2927  * whenever the sample page is redrawn.
2928 */
2929
2930 static UINT_PTR
2931 PRINTDLG_DefaultPagePaintHook(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam,
2932                               const PageSetupDataA *pda)
2933 {
2934     LPRECT lprc = (LPRECT) lParam;
2935     HDC hdc = (HDC) wParam;
2936     HPEN hpen, holdpen;
2937     LOGFONTW lf;
2938     HFONT hfont, holdfont;
2939     INT oldbkmode;
2940     TRACE("uMsg: WM_USER+%d\n",uMsg-WM_USER);
2941     /* Call user paint hook if enable */
2942     if (pda->dlga->Flags & PSD_ENABLEPAGEPAINTHOOK)
2943         if (pda->dlga->lpfnPagePaintHook(hwndDlg, uMsg, wParam, lParam))
2944             return TRUE;
2945
2946     switch (uMsg) {
2947        /* LPPAGESETUPDLG in lParam */
2948        case WM_PSD_PAGESETUPDLG:
2949        /* Inform about the sample page rectangle */
2950        case WM_PSD_FULLPAGERECT:
2951        /* Inform about the margin rectangle */
2952        case WM_PSD_MINMARGINRECT:
2953             return FALSE;
2954
2955         /* Draw dashed rectangle showing margins */
2956         case WM_PSD_MARGINRECT:
2957             hpen = CreatePen(PS_DASH, 1, GetSysColor(COLOR_3DSHADOW));
2958             holdpen = SelectObject(hdc, hpen);
2959             Rectangle(hdc, lprc->left, lprc->top, lprc->right, lprc->bottom);
2960             DeleteObject(SelectObject(hdc, holdpen));
2961             return TRUE;
2962         /* Draw the fake document */
2963         case WM_PSD_GREEKTEXTRECT:
2964             /* select a nice scalable font, because we want the text really small */
2965             SystemParametersInfoW(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0);
2966             lf.lfHeight = 6; /* value chosen based on visual effect */
2967             hfont = CreateFontIndirectW(&lf);
2968             holdfont = SelectObject(hdc, hfont);
2969
2970             /* if text not loaded, then do so now */
2971             if (wszFakeDocumentText[0] == '\0')
2972                  LoadStringW(COMDLG32_hInstance,
2973                         IDS_FAKEDOCTEXT,
2974                         wszFakeDocumentText,
2975                         sizeof(wszFakeDocumentText)/sizeof(wszFakeDocumentText[0]));
2976
2977             oldbkmode = SetBkMode(hdc, TRANSPARENT);
2978             DrawTextW(hdc, wszFakeDocumentText, -1, lprc, DT_TOP|DT_LEFT|DT_NOPREFIX|DT_WORDBREAK);
2979             SetBkMode(hdc, oldbkmode);
2980
2981             DeleteObject(SelectObject(hdc, holdfont));
2982             return TRUE;
2983
2984         /* Envelope stamp */
2985         case WM_PSD_ENVSTAMPRECT:
2986         /* Return address */
2987         case WM_PSD_YAFULLPAGERECT:
2988             FIXME("envelope/stamp is not implemented\n");
2989             return FALSE;
2990         default:
2991             FIXME("Unknown message %x\n",uMsg);
2992             return FALSE;
2993     }
2994     return TRUE;
2995 }
2996
2997 /***********************************************************************
2998  *           PagePaintProc
2999  * The main paint procedure for the PageSetupDlg function.
3000  * The Page Setup dialog box includes an image of a sample page that shows how
3001  * the user's selections affect the appearance of the printed output.
3002  * The image consists of a rectangle that represents the selected paper
3003  * or envelope type, with a dotted-line rectangle representing
3004  * the current margins, and partial (Greek text) characters
3005  * to show how text looks on the printed page. 
3006  *
3007  * The following messages in the order sends to user hook procedure:
3008  *   WM_PSD_PAGESETUPDLG    Draw the contents of the sample page
3009  *   WM_PSD_FULLPAGERECT    Inform about the bounding rectangle
3010  *   WM_PSD_MINMARGINRECT   Inform about the margin rectangle (min margin?)
3011  *   WM_PSD_MARGINRECT      Draw the margin rectangle
3012  *   WM_PSD_GREEKTEXTRECT   Draw the Greek text inside the margin rectangle
3013  * If any of first three messages returns TRUE, painting done.
3014  *
3015  * PARAMS:
3016  *   hWnd   [in] Handle to the Page Setup dialog box
3017  *   uMsg   [in] Received message
3018  *
3019  * TODO:
3020  *   WM_PSD_ENVSTAMPRECT    Draw in the envelope-stamp rectangle (for envelopes only)
3021  *   WM_PSD_YAFULLPAGERECT  Draw the return address portion (for envelopes and other paper sizes)
3022  *
3023  * RETURNS:
3024  *   FALSE if all done correctly
3025  *
3026  */
3027
3028
3029 static LRESULT CALLBACK
3030 PRINTDLG_PagePaintProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
3031 {
3032     PAINTSTRUCT ps;
3033     RECT rcClient, rcMargin;
3034     HPEN hpen, holdpen;
3035     HDC hdc;
3036     HBRUSH hbrush, holdbrush;
3037     PageSetupDataA *pda;
3038     int papersize=0, orientation=0; /* FIXME: set this values for user paint hook */
3039     double scalx, scaly;
3040 #define CALLPAINTHOOK(msg,lprc) PRINTDLG_DefaultPagePaintHook( hWnd, msg, (WPARAM)hdc, (LPARAM)lprc, pda)
3041
3042     if (uMsg != WM_PAINT)
3043         return CallWindowProcA(lpfnStaticWndProc, hWnd, uMsg, wParam, lParam);
3044
3045     /* Processing WM_PAINT message */
3046     pda = (PageSetupDataA*)GetPropA(hWnd, "__WINE_PAGESETUPDLGDATA");
3047     if (!pda) {
3048         WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
3049         return FALSE;
3050     }
3051     if (PRINTDLG_DefaultPagePaintHook(hWnd, WM_PSD_PAGESETUPDLG, MAKELONG(papersize, orientation), (LPARAM)pda->dlga, pda))
3052         return FALSE;
3053
3054     hdc = BeginPaint(hWnd, &ps);
3055     GetClientRect(hWnd, &rcClient);
3056     
3057     scalx = rcClient.right  / (double)pda->curdlg.ptPaperSize.x;
3058     scaly = rcClient.bottom / (double)pda->curdlg.ptPaperSize.y; 
3059     rcMargin = rcClient;
3060  
3061     rcMargin.left   += (LONG)pda->curdlg.rtMargin.left   * scalx;
3062     rcMargin.top    += (LONG)pda->curdlg.rtMargin.top    * scalx;
3063     rcMargin.right  -= (LONG)pda->curdlg.rtMargin.right  * scaly;
3064     rcMargin.bottom -= (LONG)pda->curdlg.rtMargin.bottom * scaly;
3065     
3066     /* if the space is too small then we make sure to not draw anything */
3067     rcMargin.left = min(rcMargin.left, rcMargin.right);
3068     rcMargin.top = min(rcMargin.top, rcMargin.bottom);
3069
3070     if (!CALLPAINTHOOK(WM_PSD_FULLPAGERECT, &rcClient) &&
3071         !CALLPAINTHOOK(WM_PSD_MINMARGINRECT, &rcMargin) )
3072     {
3073         /* fill background */
3074         hbrush = GetSysColorBrush(COLOR_3DHIGHLIGHT);
3075         FillRect(hdc, &rcClient, hbrush);
3076         holdbrush = SelectObject(hdc, hbrush);
3077
3078         hpen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));
3079         holdpen = SelectObject(hdc, hpen);
3080         
3081         /* paint left edge */
3082         MoveToEx(hdc, rcClient.left, rcClient.top, NULL);
3083         LineTo(hdc, rcClient.left, rcClient.bottom-1);
3084
3085         /* paint top edge */
3086         MoveToEx(hdc, rcClient.left, rcClient.top, NULL);
3087         LineTo(hdc, rcClient.right, rcClient.top);
3088
3089         hpen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DDKSHADOW));
3090         DeleteObject(SelectObject(hdc, hpen));
3091
3092         /* paint right edge */
3093         MoveToEx(hdc, rcClient.right-1, rcClient.top, NULL);
3094         LineTo(hdc, rcClient.right-1, rcClient.bottom);
3095
3096         /* paint bottom edge */
3097         MoveToEx(hdc, rcClient.left, rcClient.bottom-1, NULL);
3098         LineTo(hdc, rcClient.right, rcClient.bottom-1);
3099
3100         DeleteObject(SelectObject(hdc, holdpen));
3101         DeleteObject(SelectObject(hdc, holdbrush));
3102
3103         CALLPAINTHOOK(WM_PSD_MARGINRECT, &rcMargin);
3104
3105         /* give text a bit of a space from the frame */
3106         rcMargin.left += 2;
3107         rcMargin.top += 2;
3108         rcMargin.right -= 2;
3109         rcMargin.bottom -= 2;
3110         
3111         /* if the space is too small then we make sure to not draw anything */
3112         rcMargin.left = min(rcMargin.left, rcMargin.right);
3113         rcMargin.top = min(rcMargin.top, rcMargin.bottom);
3114
3115         CALLPAINTHOOK(WM_PSD_GREEKTEXTRECT, &rcMargin);
3116     }
3117
3118     EndPaint(hWnd, &ps);
3119     return FALSE;
3120 #undef CALLPAINTHOOK
3121 }
3122
3123 /***********************************************************************
3124  *           PRINTDLG_PageDlgProcA
3125  * Message handler for PageSetupDlgA
3126  */
3127 static INT_PTR CALLBACK
3128 PRINTDLG_PageDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
3129 {
3130     DEVMODEA            *dm;
3131     PageSetupDataA      *pda;
3132     INT_PTR             res = FALSE;
3133     HWND                hDrawWnd;
3134
3135     if (uMsg == WM_INITDIALOG) { /*Init dialog*/
3136         pda = (PageSetupDataA*)lParam;
3137         pda->hDlg   = hDlg; /* saving handle to main window to PageSetupDataA structure */
3138         memcpy(&pda->curdlg, pda->dlga, sizeof(pda->curdlg));
3139         
3140         hDrawWnd = GetDlgItem(hDlg, rct1); 
3141         TRACE("set property to %p\n", pda);
3142         SetPropA(hDlg, "__WINE_PAGESETUPDLGDATA", pda);
3143         SetPropA(hDrawWnd, "__WINE_PAGESETUPDLGDATA", pda);
3144         GetWindowRect(hDrawWnd, &pda->rtDrawRect); /* Calculating rect in client coordinates where paper draws */
3145         ScreenToClient(hDlg, (LPPOINT)&pda->rtDrawRect);
3146         ScreenToClient(hDlg, (LPPOINT)(&pda->rtDrawRect.right));
3147         lpfnStaticWndProc = (WNDPROC)SetWindowLongPtrW(
3148             hDrawWnd,
3149             GWLP_WNDPROC,
3150             (ULONG_PTR)PRINTDLG_PagePaintProc);
3151         
3152         /* FIXME: Paint hook. Must it be at begin of initializtion or at end? */
3153         res = TRUE;
3154         if (pda->dlga->Flags & PSD_ENABLEPAGESETUPHOOK) {
3155             if (!pda->dlga->lpfnPageSetupHook(hDlg,uMsg,wParam,(LPARAM)pda->dlga))
3156                 FIXME("Setup page hook failed?\n");
3157         }
3158
3159         /* if printer button disabled */
3160         if (pda->dlga->Flags & PSD_DISABLEPRINTER)
3161             EnableWindow(GetDlgItem(hDlg, psh3), FALSE);
3162         /* if margin edit boxes disabled */
3163         if (pda->dlga->Flags & PSD_DISABLEMARGINS) {
3164             EnableWindow(GetDlgItem(hDlg, edt4), FALSE);
3165             EnableWindow(GetDlgItem(hDlg, edt5), FALSE);
3166             EnableWindow(GetDlgItem(hDlg, edt6), FALSE);
3167             EnableWindow(GetDlgItem(hDlg, edt7), FALSE);
3168         }
3169         /* Set orientation radiobutton properly */
3170         if(pda->dlga->hDevMode)
3171         {
3172             dm = GlobalLock(pda->dlga->hDevMode);
3173             if (dm->u1.s1.dmOrientation == DMORIENT_LANDSCAPE)
3174                 CheckRadioButton(hDlg, rad1, rad2, rad2);
3175             else /* this is default if papersize is not set */
3176                 CheckRadioButton(hDlg, rad1, rad2, rad1);
3177             GlobalUnlock(pda->dlga->hDevMode);
3178         }
3179
3180         /* if orientation disabled */
3181         if (pda->dlga->Flags & PSD_DISABLEORIENTATION) {
3182             EnableWindow(GetDlgItem(hDlg,rad1),FALSE);
3183             EnableWindow(GetDlgItem(hDlg,rad2),FALSE);
3184         }
3185         /* We fill them out enabled or not */
3186         if (pda->dlga->Flags & PSD_MARGINS) {
3187             char str[100];
3188             _c_size2strA(pda,pda->dlga->rtMargin.left,str);
3189             SetDlgItemTextA(hDlg,edt4,str);
3190             _c_size2strA(pda,pda->dlga->rtMargin.top,str);
3191             SetDlgItemTextA(hDlg,edt5,str);
3192             _c_size2strA(pda,pda->dlga->rtMargin.right,str);
3193             SetDlgItemTextA(hDlg,edt6,str);
3194             _c_size2strA(pda,pda->dlga->rtMargin.bottom,str);
3195             SetDlgItemTextA(hDlg,edt7,str);
3196         } else {
3197             /* default is 1 inch */
3198             DWORD size = _c_inch2size(pda->dlga,1000);
3199             char        str[20];
3200             _c_size2strA(pda,size,str);
3201             SetDlgItemTextA(hDlg,edt4,str);
3202             SetDlgItemTextA(hDlg,edt5,str);
3203             SetDlgItemTextA(hDlg,edt6,str);
3204             SetDlgItemTextA(hDlg,edt7,str);
3205             pda->curdlg.rtMargin.left   = size;
3206             pda->curdlg.rtMargin.top    = size;
3207             pda->curdlg.rtMargin.right  = size;
3208             pda->curdlg.rtMargin.bottom = size;
3209         }
3210         /* if paper disabled */
3211         if (pda->dlga->Flags & PSD_DISABLEPAPER) {
3212             EnableWindow(GetDlgItem(hDlg,cmb2),FALSE);
3213             EnableWindow(GetDlgItem(hDlg,cmb3),FALSE);
3214         }
3215         /* filling combos: printer, paper, source. selecting current printer (from DEVMODEA) */
3216         PRINTDLG_PS_ChangePrinterA(hDlg, pda);
3217         dm = GlobalLock(pda->pdlg.hDevMode);
3218         if(dm){
3219             dm->dmDefaultSource = 15; /*FIXME: Automatic select. Does it always 15 at start? */
3220             PRINTDLG_PaperSizeA(&(pda->pdlg), dm->u1.s1.dmPaperSize, &pda->curdlg.ptPaperSize);
3221             GlobalUnlock(pda->pdlg.hDevMode);
3222             pda->curdlg.ptPaperSize.x = _c_10mm2size(pda->dlga, pda->curdlg.ptPaperSize.x);
3223             pda->curdlg.ptPaperSize.y = _c_10mm2size(pda->dlga, pda->curdlg.ptPaperSize.y);
3224             if (IsDlgButtonChecked(hDlg, rad2) == BST_CHECKED) { /* Landscape orientation */
3225                 DWORD tmp = pda->curdlg.ptPaperSize.y;
3226                 pda->curdlg.ptPaperSize.y = pda->curdlg.ptPaperSize.x;
3227                 pda->curdlg.ptPaperSize.x = tmp;
3228             }
3229         } else 
3230             WARN("GlobalLock(pda->pdlg.hDevMode) fail? hDevMode=%p\n", pda->pdlg.hDevMode);
3231         /* Drawing paper prev */
3232         PRINTDLG_PS_ChangePaperPrev(pda);
3233         return TRUE;
3234     } else {
3235         pda = (PageSetupDataA*)GetPropA(hDlg,"__WINE_PAGESETUPDLGDATA");
3236         if (!pda) {
3237             WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
3238             return FALSE;
3239         }
3240         if (pda->dlga->Flags & PSD_ENABLEPAGESETUPHOOK) {
3241             res = pda->dlga->lpfnPageSetupHook(hDlg,uMsg,wParam,lParam);
3242             if (res) return res;
3243         }
3244     }
3245     switch (uMsg) {
3246     case WM_COMMAND:
3247         return PRINTDLG_PS_WMCommandA(hDlg, wParam, lParam, pda);
3248     }
3249     return FALSE;
3250 }
3251
3252 static INT_PTR CALLBACK
3253 PageDlgProcW(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
3254 {
3255     static const WCHAR __WINE_PAGESETUPDLGDATA[] = 
3256         { '_', '_', 'W', 'I', 'N', 'E', '_', 'P', 'A', 'G', 'E', 
3257           'S', 'E', 'T', 'U', 'P', 'D', 'L', 'G', 'D', 'A', 'T', 'A', 0 };
3258     PageSetupDataW      *pda;
3259     LPDEVMODEW          dm;
3260     BOOL                res = FALSE;
3261
3262     if (uMsg==WM_INITDIALOG) {
3263         res = TRUE;
3264         pda = (PageSetupDataW*)lParam;
3265         SetPropW(hDlg, __WINE_PAGESETUPDLGDATA, pda);
3266         if (pda->dlga->Flags & PSD_ENABLEPAGESETUPHOOK) {
3267             res = pda->dlga->lpfnPageSetupHook(hDlg,uMsg,wParam,(LPARAM)pda->dlga);
3268             if (!res) {
3269                 FIXME("Setup page hook failed?\n");
3270                 res = TRUE;
3271             }
3272         }
3273
3274         if (pda->dlga->Flags & PSD_ENABLEPAGEPAINTHOOK) {
3275             FIXME("PagePaintHook not yet implemented!\n");
3276         }
3277         if (pda->dlga->Flags & PSD_DISABLEPRINTER)
3278             EnableWindow(GetDlgItem(hDlg, psh3), FALSE);
3279         if (pda->dlga->Flags & PSD_DISABLEMARGINS) {
3280             EnableWindow(GetDlgItem(hDlg, edt4), FALSE);
3281             EnableWindow(GetDlgItem(hDlg, edt5), FALSE);
3282             EnableWindow(GetDlgItem(hDlg, edt6), FALSE);
3283             EnableWindow(GetDlgItem(hDlg, edt7), FALSE);
3284         }
3285
3286         if(pda->dlga->hDevMode)
3287         {
3288             dm = GlobalLock(pda->dlga->hDevMode);
3289             /* Landscape orientation */
3290             if (dm->u1.s1.dmOrientation == DMORIENT_LANDSCAPE)
3291                 CheckRadioButton(hDlg, rad1, rad2, rad2);
3292             else /* this is default if papersize is not set */
3293                 CheckRadioButton(hDlg, rad1, rad2, rad1);
3294             GlobalUnlock(pda->dlga->hDevMode);
3295         }
3296
3297         if (pda->dlga->Flags & PSD_DISABLEORIENTATION) {
3298             EnableWindow(GetDlgItem(hDlg,rad1),FALSE);
3299             EnableWindow(GetDlgItem(hDlg,rad2),FALSE);
3300         }
3301         /* We fill them out enabled or not */
3302         if (pda->dlga->Flags & PSD_MARGINS) {
3303             WCHAR str[100];
3304             _c_size2strW(pda,pda->dlga->rtMargin.left,str);
3305             SetDlgItemTextW(hDlg,edt4,str);
3306             _c_size2strW(pda,pda->dlga->rtMargin.top,str);
3307             SetDlgItemTextW(hDlg,edt5,str);
3308             _c_size2strW(pda,pda->dlga->rtMargin.right,str);
3309             SetDlgItemTextW(hDlg,edt6,str);
3310             _c_size2strW(pda,pda->dlga->rtMargin.bottom,str);
3311             SetDlgItemTextW(hDlg,edt7,str);
3312         } else {
3313             /* default is 1 inch */
3314             DWORD size = _c_inch2size((LPPAGESETUPDLGA)pda->dlga,1000);
3315             WCHAR       str[20];
3316             _c_size2strW(pda,size,str);
3317             SetDlgItemTextW(hDlg,edt4,str);
3318             SetDlgItemTextW(hDlg,edt5,str);
3319             SetDlgItemTextW(hDlg,edt6,str);
3320             SetDlgItemTextW(hDlg,edt7,str);
3321         }
3322         PRINTDLG_PS_ChangePrinterW(hDlg,pda);
3323         if (pda->dlga->Flags & PSD_DISABLEPAPER) {
3324             EnableWindow(GetDlgItem(hDlg,cmb2),FALSE);
3325             EnableWindow(GetDlgItem(hDlg,cmb3),FALSE);
3326         }
3327
3328         return TRUE;
3329     } else {
3330         pda = (PageSetupDataW*)GetPropW(hDlg, __WINE_PAGESETUPDLGDATA);
3331         if (!pda) {
3332             WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
3333             return FALSE;
3334         }
3335         if (pda->dlga->Flags & PSD_ENABLEPAGESETUPHOOK) {
3336             res = pda->dlga->lpfnPageSetupHook(hDlg,uMsg,wParam,lParam);
3337             if (res) return res;
3338         }
3339     }
3340     switch (uMsg) {
3341     case WM_COMMAND:
3342         return PRINTDLG_PS_WMCommandW(hDlg, wParam, lParam, pda);
3343     }
3344     return FALSE;
3345 }
3346
3347 /***********************************************************************
3348  *            PageSetupDlgA  (COMDLG32.@)
3349  *
3350  *  Displays the the PAGE SETUP dialog box, which enables the user to specify
3351  *  specific properties of a printed page such as
3352  *  size, source, orientation and the width of the page margins.
3353  *
3354  * PARAMS
3355  *  setupdlg [IO] PAGESETUPDLGA struct
3356  *
3357  * RETURNS
3358  *  TRUE    if the user pressed the OK button
3359  *  FALSE   if the user cancelled the window or an error occurred
3360  *
3361  * NOTES
3362  *    The values of hDevMode and hDevNames are filled on output and can be
3363  *    changed in PAGESETUPDLG when they are passed in PageSetupDlg.
3364  * 
3365  */
3366
3367 BOOL WINAPI PageSetupDlgA(LPPAGESETUPDLGA setupdlg) {
3368     HGLOBAL             hDlgTmpl;
3369     LPVOID              ptr;
3370     BOOL                bRet;
3371     PageSetupDataA      *pda;
3372     PRINTDLGA           pdlg;
3373
3374     /* TRACE */
3375     if(TRACE_ON(commdlg)) {
3376         char flagstr[1000] = "";
3377         const struct pd_flags *pflag = psd_flags;
3378         for( ; pflag->name; pflag++) {
3379             if(setupdlg->Flags & pflag->flag) {
3380                 strcat(flagstr, pflag->name);
3381                 strcat(flagstr, "|");
3382             }
3383         }
3384         TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
3385               "hinst %p, flags %08x (%s)\n",
3386               setupdlg, setupdlg->hwndOwner, setupdlg->hDevMode,
3387               setupdlg->hDevNames,
3388               setupdlg->hInstance, setupdlg->Flags, flagstr);
3389     }
3390     /* Checking setupdlg structure */
3391     if (setupdlg == NULL) {
3392            COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION);
3393            return FALSE;
3394     }
3395     if(setupdlg->lStructSize != sizeof(PAGESETUPDLGA)) {
3396            COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
3397            return FALSE;
3398     }
3399     if ((setupdlg->Flags & PSD_ENABLEPAGEPAINTHOOK) &&
3400         (setupdlg->lpfnPagePaintHook == NULL)) {
3401             COMDLG32_SetCommDlgExtendedError(CDERR_NOHOOK);
3402             return FALSE;
3403         }
3404
3405     /* Initialize default printer struct. If no printer device info is specified
3406        retrieve the default printer data. */
3407     memset(&pdlg,0,sizeof(pdlg));
3408     pdlg.lStructSize    = sizeof(pdlg);
3409     if (setupdlg->hDevMode && setupdlg->hDevNames) {
3410         pdlg.hDevMode = setupdlg->hDevMode;
3411         pdlg.hDevNames = setupdlg->hDevNames;
3412     } else {
3413         pdlg.Flags = PD_RETURNDEFAULT;
3414         bRet = PrintDlgA(&pdlg);
3415         if (!bRet){
3416             if (!(setupdlg->Flags & PSD_NOWARNING)) {
3417                 char errstr[256];
3418                 LoadStringA(COMDLG32_hInstance, PD32_NO_DEFAULT_PRINTER, errstr, 255);
3419                 MessageBoxA(setupdlg->hwndOwner, errstr, 0, MB_OK | MB_ICONERROR);
3420             }
3421             return FALSE;
3422         }
3423     }
3424
3425     /* short cut exit, just return default values */
3426     if (setupdlg->Flags & PSD_RETURNDEFAULT) {
3427         DEVMODEA *dm;
3428
3429         setupdlg->hDevMode = pdlg.hDevMode;
3430         setupdlg->hDevNames = pdlg.hDevNames;
3431         dm = GlobalLock(pdlg.hDevMode);
3432         PRINTDLG_PaperSizeA(&pdlg, dm->u1.s1.dmPaperSize, &setupdlg->ptPaperSize);
3433         GlobalUnlock(pdlg.hDevMode);
3434         setupdlg->ptPaperSize.x=_c_10mm2size(setupdlg,setupdlg->ptPaperSize.x);
3435         setupdlg->ptPaperSize.y=_c_10mm2size(setupdlg,setupdlg->ptPaperSize.y);
3436         return TRUE;
3437     }
3438
3439     /* get dialog template */
3440     hDlgTmpl = PRINTDLG_GetPGSTemplateA(setupdlg);
3441     if (!hDlgTmpl) {
3442         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
3443         return FALSE;
3444     }
3445     ptr = LockResource( hDlgTmpl );
3446     if (!ptr) {
3447         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
3448         return FALSE;
3449     }
3450     
3451     pda = HeapAlloc(GetProcessHeap(),0,sizeof(*pda));
3452     pda->dlga = setupdlg;
3453     memcpy(&pda->pdlg,&pdlg,sizeof(pdlg));
3454
3455     bRet = (0<DialogBoxIndirectParamA(
3456                 setupdlg->hInstance,
3457                 ptr,
3458                 setupdlg->hwndOwner,
3459                 PRINTDLG_PageDlgProcA,
3460                 (LPARAM)pda)
3461     );
3462
3463     HeapFree(GetProcessHeap(),0,pda);
3464     return bRet;
3465 }
3466 /***********************************************************************
3467  *            PageSetupDlgW  (COMDLG32.@)
3468  *
3469  * See PageSetupDlgA.
3470  */
3471 BOOL WINAPI PageSetupDlgW(LPPAGESETUPDLGW setupdlg) {
3472     HGLOBAL             hDlgTmpl;
3473     LPVOID              ptr;
3474     BOOL                bRet;
3475     PageSetupDataW      *pdw;
3476     PRINTDLGW           pdlg;
3477
3478     FIXME("Unicode implementation is not done yet\n");
3479     if(TRACE_ON(commdlg)) {
3480         char flagstr[1000] = "";
3481         const struct pd_flags *pflag = psd_flags;
3482         for( ; pflag->name; pflag++) {
3483             if(setupdlg->Flags & pflag->flag) {
3484                 strcat(flagstr, pflag->name);
3485                 strcat(flagstr, "|");
3486             }
3487         }
3488         TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
3489               "hinst %p, flags %08x (%s)\n",
3490               setupdlg, setupdlg->hwndOwner, setupdlg->hDevMode,
3491               setupdlg->hDevNames,
3492               setupdlg->hInstance, setupdlg->Flags, flagstr);
3493     }
3494
3495     /* Initialize default printer struct. If no printer device info is specified
3496        retrieve the default printer data. */
3497     memset(&pdlg,0,sizeof(pdlg));
3498     pdlg.lStructSize    = sizeof(pdlg);
3499     if (setupdlg->hDevMode && setupdlg->hDevNames) {
3500         pdlg.hDevMode = setupdlg->hDevMode;
3501         pdlg.hDevNames = setupdlg->hDevNames;
3502     } else {
3503         pdlg.Flags = PD_RETURNDEFAULT;
3504         bRet = PrintDlgW(&pdlg);
3505         if (!bRet){
3506             if (!(setupdlg->Flags & PSD_NOWARNING)) {
3507                 WCHAR errstr[256];
3508                 LoadStringW(COMDLG32_hInstance, PD32_NO_DEFAULT_PRINTER, errstr, 255);
3509                 MessageBoxW(setupdlg->hwndOwner, errstr, 0, MB_OK | MB_ICONERROR);
3510             }
3511             return FALSE;
3512         }
3513     }
3514
3515     /* short cut exit, just return default values */
3516     if (setupdlg->Flags & PSD_RETURNDEFAULT) {
3517         static const WCHAR a4[] = {'A','4',0};
3518         setupdlg->hDevMode      = pdlg.hDevMode;
3519         setupdlg->hDevNames     = pdlg.hDevNames;
3520         /* FIXME: Just return "A4" for now. */
3521         PRINTDLG_PaperSizeW(&pdlg,a4,&setupdlg->ptPaperSize);
3522         setupdlg->ptPaperSize.x=_c_10mm2size((LPPAGESETUPDLGA)setupdlg,setupdlg->ptPaperSize.x);
3523         setupdlg->ptPaperSize.y=_c_10mm2size((LPPAGESETUPDLGA)setupdlg,setupdlg->ptPaperSize.y);
3524         return TRUE;
3525     }
3526     hDlgTmpl = PRINTDLG_GetPGSTemplateW(setupdlg);
3527     if (!hDlgTmpl) {
3528         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
3529         return FALSE;
3530     }
3531     ptr = LockResource( hDlgTmpl );
3532     if (!ptr) {
3533         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
3534         return FALSE;
3535     }
3536     pdw = HeapAlloc(GetProcessHeap(),0,sizeof(*pdw));
3537     pdw->dlga = setupdlg;
3538     memcpy(&pdw->pdlg,&pdlg,sizeof(pdlg));
3539
3540     bRet = (0<DialogBoxIndirectParamW(
3541                 setupdlg->hInstance,
3542                 ptr,
3543                 setupdlg->hwndOwner,
3544                 PageDlgProcW,
3545                 (LPARAM)pdw)
3546     );
3547     return bRet;
3548 }
3549
3550 /***********************************************************************
3551  *      PrintDlgExA (COMDLG32.@)
3552  *
3553  * See PrintDlgExW.
3554  *
3555  * FIXME
3556  *   Stub
3557  */
3558 HRESULT WINAPI PrintDlgExA(LPPRINTDLGEXA lpPrintDlgExA)
3559 {
3560         FIXME("stub\n");
3561         return E_NOTIMPL;
3562 }
3563
3564 /***********************************************************************
3565  *      PrintDlgExW (COMDLG32.@)
3566  *
3567  * Display the the PRINT dialog box, which enables the user to specify
3568  * specific properties of the print job.  The property sheet can also have
3569  * additional application-specific and driver-specific property pages.
3570  *  
3571  * PARAMS
3572  *  lppd  [IO] ptr to PRINTDLGEX struct
3573  * 
3574  * RETURNS
3575  *  Success: S_OK
3576  *  Failure: One of the following COM error codes:
3577  *    E_OUTOFMEMORY Insufficient memory.
3578  *    E_INVALIDARG  One or more arguments are invalid.
3579  *    E_POINTER     Invalid pointer.
3580  *    E_HANDLE      Invalid handle.
3581  *    E_FAIL        Unspecified error.
3582  *  
3583  * FIXME
3584  *   Stub
3585  */
3586 HRESULT WINAPI PrintDlgExW(LPPRINTDLGEXW lpPrintDlgExW)
3587 {
3588         FIXME("stub\n");
3589         return E_NOTIMPL;
3590 }