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