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