Added LGPL standard comment, and copyright notices where necessary.
[wine] / dlls / commdlg / printdlg.c
1 /*
2  * COMMDLG - Print Dialog
3  *
4  * Copyright 1994 Martin Ayotte
5  * Copyright 1996 Albrecht Kleine
6  * Copyright 1999 Klaas van Gend
7  * Copyright 2000 Huw D M Davies
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 #include <ctype.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include "windef.h"
28 #include "winbase.h"
29 #include "wingdi.h"
30 #include "wine/wingdi16.h"
31 #include "winuser.h"
32 #include "wine/winuser16.h"
33 #include "commdlg.h"
34 #include "dlgs.h"
35 #include "wine/debug.h"
36 #include "cderr.h"
37 #include "winspool.h"
38 #include "winerror.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
41
42 #include "cdlg.h"
43
44 /* This PRINTDLGA internal structure stores
45  * pointers to several throughout useful structures.
46  * 
47  */
48 typedef struct  
49 {
50   LPDEVMODEA        lpDevMode;
51   struct {
52       LPPRINTDLGA       lpPrintDlg;
53       LPPRINTDLG16      lpPrintDlg16;
54   } dlg;
55   LPPRINTER_INFO_2A lpPrinterInfo;
56   LPDRIVER_INFO_3A  lpDriverInfo;
57   UINT              HelpMessageID;
58   HICON             hCollateIcon;    /* PrintDlg only */
59   HICON             hNoCollateIcon;  /* PrintDlg only */
60   HICON             hPortraitIcon;   /* PrintSetupDlg only */
61   HICON             hLandscapeIcon;  /* PrintSetupDlg only */
62   HWND              hwndUpDown;
63 } PRINT_PTRA;
64
65 /* Debugging info */
66 static struct pd_flags {
67   DWORD flag;
68   LPSTR name;
69 } pd_flags[] = {
70   {PD_SELECTION, "PD_SELECTION "},
71   {PD_PAGENUMS, "PD_PAGENUMS "},
72   {PD_NOSELECTION, "PD_NOSELECTION "},
73   {PD_NOPAGENUMS, "PD_NOPAGENUMS "},
74   {PD_COLLATE, "PD_COLLATE "},
75   {PD_PRINTTOFILE, "PD_PRINTTOFILE "},
76   {PD_PRINTSETUP, "PD_PRINTSETUP "},
77   {PD_NOWARNING, "PD_NOWARNING "},
78   {PD_RETURNDC, "PD_RETURNDC "},
79   {PD_RETURNIC, "PD_RETURNIC "},
80   {PD_RETURNDEFAULT, "PD_RETURNDEFAULT "},
81   {PD_SHOWHELP, "PD_SHOWHELP "},
82   {PD_ENABLEPRINTHOOK, "PD_ENABLEPRINTHOOK "},
83   {PD_ENABLESETUPHOOK, "PD_ENABLESETUPHOOK "},
84   {PD_ENABLEPRINTTEMPLATE, "PD_ENABLEPRINTTEMPLATE "},
85   {PD_ENABLESETUPTEMPLATE, "PD_ENABLESETUPTEMPLATE "},
86   {PD_ENABLEPRINTTEMPLATEHANDLE, "PD_ENABLEPRINTTEMPLATEHANDLE "},
87   {PD_ENABLESETUPTEMPLATEHANDLE, "PD_ENABLESETUPTEMPLATEHANDLE "},
88   {PD_USEDEVMODECOPIES, "PD_USEDEVMODECOPIES[ANDCOLLATE] "},
89   {PD_DISABLEPRINTTOFILE, "PD_DISABLEPRINTTOFILE "},
90   {PD_HIDEPRINTTOFILE, "PD_HIDEPRINTTOFILE "},
91   {PD_NONETWORKBUTTON, "PD_NONETWORKBUTTON "},
92   {-1, NULL}
93 };
94
95 /* Debugging info */
96 static struct pd_flags psd_flags[] = {
97   {PSD_MINMARGINS,"PSD_MINMARGINS"},
98   {PSD_MARGINS,"PSD_MARGINS"},
99   {PSD_INTHOUSANDTHSOFINCHES,"PSD_INTHOUSANDTHSOFINCHES"},
100   {PSD_INHUNDREDTHSOFMILLIMETERS,"PSD_INHUNDREDTHSOFMILLIMETERS"},
101   {PSD_DISABLEMARGINS,"PSD_DISABLEMARGINS"},
102   {PSD_DISABLEPRINTER,"PSD_DISABLEPRINTER"},
103   {PSD_NOWARNING,"PSD_NOWARNING"},
104   {PSD_DISABLEORIENTATION,"PSD_DISABLEORIENTATION"},
105   {PSD_RETURNDEFAULT,"PSD_RETURNDEFAULT"},
106   {PSD_DISABLEPAPER,"PSD_DISABLEPAPER"},
107   {PSD_SHOWHELP,"PSD_SHOWHELP"},
108   {PSD_ENABLEPAGESETUPHOOK,"PSD_ENABLEPAGESETUPHOOK"},
109   {PSD_ENABLEPAGESETUPTEMPLATE,"PSD_ENABLEPAGESETUPTEMPLATE"},
110   {PSD_ENABLEPAGESETUPTEMPLATEHANDLE,"PSD_ENABLEPAGESETUPTEMPLATEHANDLE"},
111   {PSD_ENABLEPAGEPAINTHOOK,"PSD_ENABLEPAGEPAINTHOOK"},
112   {PSD_DISABLEPAGEPAINTING,"PSD_DISABLEPAGEPAINTING"},
113   {-1, NULL}
114 };
115
116 /* Yes these constants are the same, but we're just copying win98 */
117 #define UPDOWN_ID 0x270f
118 #define MAX_COPIES 9999
119
120 /***********************************************************************
121  *    PRINTDLG_GetDefaultPrinterName
122  *
123  * Returns the default printer name in buf.
124  * Even under WinNT/2000 default printer is retrieved via GetProfileString - 
125  * these entries are mapped somewhere in the registry rather than win.ini.
126  *
127  * Returns TRUE on success else FALSE
128  */
129 static BOOL PRINTDLG_GetDefaultPrinterName(LPSTR buf, DWORD len)
130 {
131     char *ptr;
132
133     if(!GetProfileStringA("windows", "device", "", buf, len)) {
134         TRACE("No profile entry for default printer found.\n");
135         return FALSE;
136     }
137     if((ptr = strchr(buf, ',')) == NULL) {
138         FIXME("bad format for default printer (%s)!\n",buf);
139         return FALSE;
140     }
141     *ptr = '\0';
142     return TRUE;
143 }
144
145 /***********************************************************************
146  *    PRINTDLG_OpenDefaultPrinter
147  *
148  * Returns a winspool printer handle to the default printer in *hprn
149  * Caller must call ClosePrinter on the handle
150  *
151  * Returns TRUE on success else FALSE
152  */
153 static BOOL PRINTDLG_OpenDefaultPrinter(HANDLE *hprn)
154 {
155     char buf[260];
156     BOOL res;
157     if(!PRINTDLG_GetDefaultPrinterName(buf, sizeof(buf)))
158         return FALSE;
159     res = OpenPrinterA(buf, hprn, NULL);
160     if (!res)
161         FIXME("Could not open printer %s?!\n",buf);
162     return res;
163 }
164
165 /***********************************************************************
166  *    PRINTDLG_SetUpPrinterListCombo
167  *
168  * Initializes printer list combox.
169  * hDlg:  HWND of dialog
170  * id:    Control id of combo
171  * name:  Name of printer to select
172  *
173  * Initializes combo with list of available printers.  Selects printer 'name'
174  * If name is NULL or does not exist select the default printer.
175  *
176  * Returns number of printers added to list.
177  */
178 static INT PRINTDLG_SetUpPrinterListCombo(HWND hDlg, UINT id, LPCSTR name)
179 {
180     DWORD needed, num;
181     INT i;
182     LPPRINTER_INFO_2A pi;
183     EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
184     pi = HeapAlloc(GetProcessHeap(), 0, needed);
185     EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pi, needed, &needed, 
186                   &num);
187
188     for(i = 0; i < num; i++) {
189         SendDlgItemMessageA(hDlg, id, CB_ADDSTRING, 0,
190                             (LPARAM)pi[i].pPrinterName );
191     }
192     HeapFree(GetProcessHeap(), 0, pi);
193     if(!name ||
194        (i = SendDlgItemMessageA(hDlg, id, CB_FINDSTRINGEXACT, -1,
195                                 (LPARAM)name)) == CB_ERR) {
196
197         char buf[260];
198         FIXME("Can't find '%s' in printer list so trying to find default\n",
199               name);
200         if(!PRINTDLG_GetDefaultPrinterName(buf, sizeof(buf)))
201             return num;
202         i = SendDlgItemMessageA(hDlg, id, CB_FINDSTRINGEXACT, -1, (LPARAM)buf);
203         if(i == CB_ERR)
204             FIXME("Can't find default printer in printer list\n");
205     }
206     SendDlgItemMessageA(hDlg, id, CB_SETCURSEL, i, 0);
207     return num;
208 }
209
210 /***********************************************************************
211  *             PRINTDLG_CreateDevNames          [internal]
212  *
213  *
214  *   creates a DevNames structure.
215  *
216  *  (NB. when we handle unicode the offsets will be in wchars).
217  */
218 static BOOL PRINTDLG_CreateDevNames(HGLOBAL *hmem, char* DeviceDriverName, 
219                                     char* DeviceName, char* OutputPort)
220 {
221     long size;
222     char*   pDevNamesSpace;
223     char*   pTempPtr;
224     LPDEVNAMES lpDevNames;
225     char buf[260];
226
227     size = strlen(DeviceDriverName) + 1
228             + strlen(DeviceName) + 1
229             + strlen(OutputPort) + 1
230             + sizeof(DEVNAMES);
231             
232     if(*hmem)
233         *hmem = GlobalReAlloc(*hmem, size, GMEM_MOVEABLE);
234     else
235         *hmem = GlobalAlloc(GMEM_MOVEABLE, size);
236     if (*hmem == 0)
237         return FALSE;
238
239     pDevNamesSpace = GlobalLock(*hmem);
240     lpDevNames = (LPDEVNAMES) pDevNamesSpace;
241
242     pTempPtr = pDevNamesSpace + sizeof(DEVNAMES);
243     strcpy(pTempPtr, DeviceDriverName);
244     lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
245
246     pTempPtr += strlen(DeviceDriverName) + 1;
247     strcpy(pTempPtr, DeviceName);
248     lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
249         
250     pTempPtr += strlen(DeviceName) + 1;
251     strcpy(pTempPtr, OutputPort);
252     lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
253
254     PRINTDLG_GetDefaultPrinterName(buf, sizeof(buf));
255     lpDevNames->wDefault = (strcmp(buf, DeviceName) == 0) ? 1 : 0;
256     GlobalUnlock(*hmem);
257     return TRUE;
258 }
259
260 static BOOL PRINTDLG_CreateDevNames16(HGLOBAL16 *hmem, char* DeviceDriverName, 
261                                       char* DeviceName, char* OutputPort)
262 {
263     long size;
264     char*   pDevNamesSpace;
265     char*   pTempPtr;
266     LPDEVNAMES lpDevNames;
267     char buf[260];
268
269     size = strlen(DeviceDriverName) + 1
270             + strlen(DeviceName) + 1
271             + strlen(OutputPort) + 1
272             + sizeof(DEVNAMES);
273             
274     if(*hmem)
275         *hmem = GlobalReAlloc16(*hmem, size, GMEM_MOVEABLE);
276     else
277         *hmem = GlobalAlloc16(GMEM_MOVEABLE, size);
278     if (*hmem == 0)
279         return FALSE;
280
281     pDevNamesSpace = GlobalLock16(*hmem);
282     lpDevNames = (LPDEVNAMES) pDevNamesSpace;
283
284     pTempPtr = pDevNamesSpace + sizeof(DEVNAMES);
285     strcpy(pTempPtr, DeviceDriverName);
286     lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
287
288     pTempPtr += strlen(DeviceDriverName) + 1;
289     strcpy(pTempPtr, DeviceName);
290     lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
291         
292     pTempPtr += strlen(DeviceName) + 1;
293     strcpy(pTempPtr, OutputPort);
294     lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
295
296     PRINTDLG_GetDefaultPrinterName(buf, sizeof(buf));
297     lpDevNames->wDefault = (strcmp(buf, DeviceName) == 0) ? 1 : 0;
298     GlobalUnlock16(*hmem);
299     return TRUE;
300 }
301
302
303 /***********************************************************************
304  *             PRINTDLG_UpdatePrintDlg          [internal]
305  *
306  *
307  *   updates the PrintDlg structure for returnvalues.
308  *      
309  * RETURNS
310  *   FALSE if user is not allowed to close (i.e. wrong nTo or nFrom values)
311  *   TRUE  if succesful.
312  */
313 static BOOL PRINTDLG_UpdatePrintDlg(HWND hDlg, 
314                                     PRINT_PTRA* PrintStructures)
315 {
316     LPPRINTDLGA       lppd = PrintStructures->dlg.lpPrintDlg;
317     PDEVMODEA         lpdm = PrintStructures->lpDevMode;
318     LPPRINTER_INFO_2A pi = PrintStructures->lpPrinterInfo;
319
320
321     if(!lpdm) {
322         FIXME("No lpdm ptr?\n");
323         return FALSE;
324     }
325
326
327     if(!(lppd->Flags & PD_PRINTSETUP)) {
328         /* check whether nFromPage and nToPage are within range defined by
329          * nMinPage and nMaxPage
330          */
331         if (IsDlgButtonChecked(hDlg, rad3) == BST_CHECKED) { /* Pages */
332             WORD nToPage;
333             WORD nFromPage;
334             nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
335             nToPage   = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
336             if (nFromPage < lppd->nMinPage || nFromPage > lppd->nMaxPage ||
337                 nToPage < lppd->nMinPage || nToPage > lppd->nMaxPage) {
338                 char resourcestr[256];
339                 char resultstr[256];
340                 LoadStringA(COMDLG32_hInstance, PD32_INVALID_PAGE_RANGE, 
341                             resourcestr, 255);
342                 sprintf(resultstr,resourcestr, lppd->nMinPage, lppd->nMaxPage);
343                 LoadStringA(COMDLG32_hInstance, PD32_PRINT_TITLE, 
344                             resourcestr, 255);
345                 MessageBoxA(hDlg, resultstr, resourcestr,
346                             MB_OK | MB_ICONWARNING);
347                 return FALSE;
348             }
349             lppd->nFromPage = nFromPage;
350             lppd->nToPage   = nToPage;
351         }
352
353         if (IsDlgButtonChecked(hDlg, chx1) == BST_CHECKED) {/* Print to file */
354             lppd->Flags |= PD_PRINTTOFILE;
355             pi->pPortName = "FILE:";
356         }
357
358         if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED) { /* Collate */
359             FIXME("Collate lppd not yet implemented as output\n");
360         }
361
362         /* set PD_Collate and nCopies */
363         if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
364           /*  The application doesn't support multiple copies or collate...
365            */
366             lppd->Flags &= ~PD_COLLATE;
367             lppd->nCopies = 1;
368           /* if the printer driver supports it... store info there
369            * otherwise no collate & multiple copies !
370            */
371             if (lpdm->dmFields & DM_COLLATE)
372                 lpdm->dmCollate = 
373                   (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED);
374             if (lpdm->dmFields & DM_COPIES)
375                 lpdm->dmCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
376         } else {
377             if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
378                 lppd->Flags |= PD_COLLATE;
379             else
380                lppd->Flags &= ~PD_COLLATE;
381             lppd->nCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
382         }
383     }
384     return TRUE;
385 }
386
387 static BOOL PRINTDLG_PaperSize(
388         PRINTDLGA       *pdlga,const char *PaperSize,LPPOINT size
389 ) {
390     DEVNAMES    *dn;
391     DEVMODEA    *dm;
392     LPSTR       devname,portname;
393     int         i;
394     INT         NrOfEntries,ret;
395     char        *Names = NULL;
396     POINT       *points = NULL;
397     BOOL        retval = FALSE;
398     
399     dn = GlobalLock(pdlga->hDevNames);
400     dm = GlobalLock(pdlga->hDevMode);
401     devname     = ((char*)dn)+dn->wDeviceOffset;
402     portname    = ((char*)dn)+dn->wOutputOffset;
403
404
405     NrOfEntries = DeviceCapabilitiesA(devname,portname,DC_PAPERNAMES,NULL,dm);
406     if (!NrOfEntries) {
407         FIXME("No papernames found for %s/%s\n",devname,portname);
408         goto out;
409     }
410     if (NrOfEntries == -1) {
411         ERR("Hmm ? DeviceCapabilities() DC_PAPERNAMES failed, ret -1 !\n");
412         goto out;
413     }
414             
415     Names = (char*)HeapAlloc(GetProcessHeap(),0,NrOfEntries*64);
416     if (NrOfEntries != (ret=DeviceCapabilitiesA(devname,portname,DC_PAPERNAMES,Names,dm))) {
417         FIXME("Number of returned vals %d is not %d\n",NrOfEntries,ret);
418         goto out;
419     }
420     for (i=0;i<NrOfEntries;i++)
421         if (!strcmp(PaperSize,Names+(64*i)))
422             break;
423     HeapFree(GetProcessHeap(),0,Names);
424     if (i==NrOfEntries) {
425         FIXME("Papersize %s not found in list?\n",PaperSize);
426         goto out;
427     }
428     points = HeapAlloc(GetProcessHeap(),0,sizeof(points[0])*NrOfEntries);
429     if (NrOfEntries!=(ret=DeviceCapabilitiesA(devname,portname,DC_PAPERSIZE,(LPBYTE)points,dm))) {
430         FIXME("Number of returned sizes %d is not %d?\n",NrOfEntries,ret);
431         goto out;
432     }
433     /* this is _10ths_ of a millimeter */
434     size->x=points[i].x;
435     size->y=points[i].y;
436     FIXME("papersize is %ld x %ld\n",size->x,size->y);
437     retval = TRUE;
438 out:
439     GlobalUnlock(pdlga->hDevNames);
440     GlobalUnlock(pdlga->hDevMode);
441     if (Names) HeapFree(GetProcessHeap(),0,Names);
442     if (points) HeapFree(GetProcessHeap(),0,points);
443     return retval;
444 }
445
446
447 /************************************************************************
448  * PRINTDLG_SetUpPaperComboBox
449  *
450  * Initialize either the papersize or inputslot combos of the Printer Setup
451  * dialog.  We store the associated word (eg DMPAPER_A4) as the item data.
452  * We also try to re-select the old selection.
453  */
454 static BOOL PRINTDLG_SetUpPaperComboBox(HWND hDlg,
455                                         int   nIDComboBox,
456                                         char* PrinterName, 
457                                         char* PortName,
458                                         LPDEVMODEA dm)
459 {
460     int     i;
461     int     NrOfEntries;
462     char*   Names;
463     WORD*   Words;
464     DWORD   Sel;
465     WORD    oldWord = 0;
466     int     NamesSize;
467     int     fwCapability_Names;
468     int     fwCapability_Words;
469     
470     TRACE(" Printer: %s, Port: %s, ComboID: %d\n",PrinterName,PortName,nIDComboBox);
471     
472     /* query the dialog box for the current selected value */
473     Sel = SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETCURSEL, 0, 0);
474     if(Sel != CB_ERR) {
475         /* we enter here only if a different printer is selected after
476          * the Print Setup dialog is opened. The current settings are
477          * stored into the newly selected printer.
478          */
479         oldWord = SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA,
480                                       Sel, 0);
481         if (dm) {
482             if (nIDComboBox == cmb2)
483                 dm->u1.s1.dmPaperSize = oldWord;
484             else
485                 dm->dmDefaultSource = oldWord;
486         }
487     }
488     else {
489         /* we enter here only when the Print setup dialog is initially
490          * opened. In this case the settings are restored from when
491          * the dialog was last closed.
492          */
493         if (dm) {
494             if (nIDComboBox == cmb2)
495                 oldWord = dm->u1.s1.dmPaperSize;
496             else
497                 oldWord = dm->dmDefaultSource;
498         }
499     }
500
501     if (nIDComboBox == cmb2) {
502          NamesSize          = 64;
503          fwCapability_Names = DC_PAPERNAMES;
504          fwCapability_Words = DC_PAPERS;
505     } else {
506          nIDComboBox        = cmb3;
507          NamesSize          = 24;
508          fwCapability_Names = DC_BINNAMES;
509          fwCapability_Words = DC_BINS;
510     }
511     
512     /* for some printer drivers, DeviceCapabilities calls a VXD to obtain the 
513      * paper settings. As Wine doesn't allow VXDs, this results in a crash.
514      */
515     WARN(" if your printer driver uses VXDs, expect a crash now!\n");
516     NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
517                                       fwCapability_Names, NULL, dm);
518     if (NrOfEntries == 0)
519          WARN("no Name Entries found!\n");
520     else if (NrOfEntries < 0)
521          return FALSE;
522
523     if(DeviceCapabilitiesA(PrinterName, PortName, fwCapability_Words, NULL, dm)
524        != NrOfEntries) {
525         ERR("Number of caps is different\n");
526         NrOfEntries = 0;
527     }
528
529     Names = HeapAlloc(GetProcessHeap(),0, NrOfEntries*NamesSize);
530     Words = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WORD));
531     NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
532                                       fwCapability_Names, Names, dm);
533     NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
534                                       fwCapability_Words, (LPSTR)Words, dm);
535
536     /* reset any current content in the combobox */
537     SendDlgItemMessageA(hDlg, nIDComboBox, CB_RESETCONTENT, 0, 0);
538     
539     /* store new content */
540     for (i = 0; i < NrOfEntries; i++) {
541         DWORD pos = SendDlgItemMessageA(hDlg, nIDComboBox, CB_ADDSTRING, 0,
542                                         (LPARAM)(&Names[i*NamesSize]) );
543         SendDlgItemMessageA(hDlg, nIDComboBox, CB_SETITEMDATA, pos, 
544                             Words[i]);
545     }
546
547     /* Look for old selection - can't do this is previous loop since
548        item order will change as more items are added */
549     Sel = 0;
550     for (i = 0; i < NrOfEntries; i++) {
551         if(SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) ==
552            oldWord) {
553             Sel = i;
554             break;
555         }
556     }
557     SendDlgItemMessageA(hDlg, nIDComboBox, CB_SETCURSEL, Sel, 0);
558
559     HeapFree(GetProcessHeap(),0,Words);
560     HeapFree(GetProcessHeap(),0,Names);
561     return TRUE;
562 }
563
564 /***********************************************************************
565  *               PRINTDLG_UpdatePrinterInfoTexts               [internal]
566  */
567 static void PRINTDLG_UpdatePrinterInfoTexts(HWND hDlg, LPPRINTER_INFO_2A pi)
568 {
569     char   StatusMsg[256];
570     char   ResourceString[256];
571     int    i;
572
573     /* Status Message */
574     StatusMsg[0]='\0';
575
576     /* add all status messages */
577     for (i = 0; i < 25; i++) {
578         if (pi->Status & (1<<i)) {
579             LoadStringA(COMDLG32_hInstance, PD32_PRINTER_STATUS_PAUSED+i, 
580                         ResourceString, 255);
581             strcat(StatusMsg,ResourceString);
582         }
583     }
584     /* append "ready" */
585     /* FIXME: status==ready must only be appended if really so. 
586               but how to detect? */
587     LoadStringA(COMDLG32_hInstance, PD32_PRINTER_STATUS_READY, 
588                 ResourceString, 255);
589     strcat(StatusMsg,ResourceString);
590   
591     SendDlgItemMessageA(hDlg, stc12, WM_SETTEXT, 0, (LPARAM)StatusMsg);
592
593     /* set all other printer info texts */
594     SendDlgItemMessageA(hDlg, stc11, WM_SETTEXT, 0, (LPARAM)pi->pDriverName);
595     if (pi->pLocation != NULL && pi->pLocation[0] != '\0')
596         SendDlgItemMessageA(hDlg, stc14, WM_SETTEXT, 0,(LPARAM)pi->pLocation);
597     else
598         SendDlgItemMessageA(hDlg, stc14, WM_SETTEXT, 0,(LPARAM)pi->pPortName);
599     SendDlgItemMessageA(hDlg, stc13, WM_SETTEXT, 0, (LPARAM)(pi->pComment ?
600                         pi->pComment : ""));
601     return;
602 }
603
604
605 /*******************************************************************
606  *
607  *                 PRINTDLG_ChangePrinter
608  *
609  */
610 static BOOL PRINTDLG_ChangePrinter(HWND hDlg, char *name,
611                                    PRINT_PTRA *PrintStructures)
612 {
613     LPPRINTDLGA lppd = PrintStructures->dlg.lpPrintDlg;
614     LPDEVMODEA lpdm = NULL;
615     LONG dmSize;
616     DWORD needed;
617     HANDLE hprn;
618
619     if(PrintStructures->lpPrinterInfo)
620         HeapFree(GetProcessHeap(),0, PrintStructures->lpPrinterInfo);
621     if(PrintStructures->lpDriverInfo)
622         HeapFree(GetProcessHeap(),0, PrintStructures->lpDriverInfo);
623     if(!OpenPrinterA(name, &hprn, NULL)) {
624         ERR("Can't open printer %s\n", name);
625         return FALSE;
626     }
627     GetPrinterA(hprn, 2, NULL, 0, &needed);
628     PrintStructures->lpPrinterInfo = HeapAlloc(GetProcessHeap(),0,needed);
629     GetPrinterA(hprn, 2, (LPBYTE)PrintStructures->lpPrinterInfo, needed,
630                 &needed);
631     GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
632     PrintStructures->lpDriverInfo = HeapAlloc(GetProcessHeap(),0,needed);
633     if (!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)PrintStructures->lpDriverInfo,
634             needed, &needed)) {
635         ERR("GetPrinterDriverA failed for %s, fix your config!\n",PrintStructures->lpPrinterInfo->pPrinterName);
636         return FALSE;
637     }
638     ClosePrinter(hprn);
639
640     PRINTDLG_UpdatePrinterInfoTexts(hDlg, PrintStructures->lpPrinterInfo);
641
642     if(PrintStructures->lpDevMode) {
643         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
644         PrintStructures->lpDevMode = NULL;
645     }
646
647     dmSize = DocumentPropertiesA(0, 0, name, NULL, NULL, 0);
648     if(dmSize == -1) {
649         ERR("DocumentProperties fails on %s\n", debugstr_a(name));
650         return FALSE;
651     }
652     PrintStructures->lpDevMode = HeapAlloc(GetProcessHeap(), 0, dmSize);
653     dmSize = DocumentPropertiesA(0, 0, name, PrintStructures->lpDevMode, NULL,
654                                  DM_OUT_BUFFER);
655     if(lppd->hDevMode && (lpdm = GlobalLock(lppd->hDevMode)) &&
656                           !strcmp(lpdm->dmDeviceName,
657                                   PrintStructures->lpDevMode->dmDeviceName)) {
658       /* Supplied devicemode matches current printer so try to use it */
659         DocumentPropertiesA(0, 0, name, PrintStructures->lpDevMode, lpdm,
660                             DM_OUT_BUFFER | DM_IN_BUFFER);
661     }
662     if(lpdm)
663         GlobalUnlock(lppd->hDevMode);
664
665     lpdm = PrintStructures->lpDevMode;  /* use this as a shortcut */
666
667     if(!(lppd->Flags & PD_PRINTSETUP)) {
668       /* Print range (All/Range/Selection) */
669         SetDlgItemInt(hDlg, edt1, lppd->nFromPage, FALSE);
670         SetDlgItemInt(hDlg, edt2, lppd->nToPage, FALSE);
671         CheckRadioButton(hDlg, rad1, rad3, rad1);               /* default */
672         if (lppd->Flags & PD_NOSELECTION)
673             EnableWindow(GetDlgItem(hDlg, rad2), FALSE);
674         else
675             if (lppd->Flags & PD_SELECTION)
676                 CheckRadioButton(hDlg, rad1, rad3, rad2);
677         if (lppd->Flags & PD_NOPAGENUMS) {
678             EnableWindow(GetDlgItem(hDlg, rad3), FALSE);
679             EnableWindow(GetDlgItem(hDlg, stc2),FALSE);
680             EnableWindow(GetDlgItem(hDlg, edt1), FALSE);
681             EnableWindow(GetDlgItem(hDlg, stc3),FALSE);
682             EnableWindow(GetDlgItem(hDlg, edt2), FALSE);
683         } else {
684             if (lppd->Flags & PD_PAGENUMS)
685                 CheckRadioButton(hDlg, rad1, rad3, rad3);
686         }
687         /* "All xxx pages"... */
688         {
689             char        resourcestr[64];
690             char        result[64];
691             LoadStringA(COMDLG32_hInstance, PD32_PRINT_ALL_X_PAGES, 
692                         resourcestr, 49);
693             sprintf(result,resourcestr,lppd->nMaxPage - lppd->nMinPage + 1);
694             SendDlgItemMessageA(hDlg, rad1, WM_SETTEXT, 0, (LPARAM) result);
695         }
696         
697         /* Collate pages 
698          *
699          * FIXME: The ico3 is not displayed for some reason. I don't know why.
700          */
701         if (lppd->Flags & PD_COLLATE) {
702             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON, 
703                                 (LPARAM)PrintStructures->hCollateIcon);
704             CheckDlgButton(hDlg, chx2, 1);
705         } else {
706             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON, 
707                                 (LPARAM)PrintStructures->hNoCollateIcon);
708             CheckDlgButton(hDlg, chx2, 0);
709         }
710
711         if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
712           /* if printer doesn't support it: no Collate */
713             if (!(lpdm->dmFields & DM_COLLATE)) {
714                 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);    
715                 EnableWindow(GetDlgItem(hDlg, ico3), FALSE);    
716             }
717         }
718
719         /* nCopies */
720         {
721           INT copies;
722           if (lppd->hDevMode == 0)
723               copies = lppd->nCopies;
724           else
725               copies = lpdm->dmCopies;
726           if(copies == 0) copies = 1;
727           else if(copies < 0) copies = MAX_COPIES;
728           SetDlgItemInt(hDlg, edt3, copies, FALSE);
729         }
730
731         if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
732           /* if printer doesn't support it: no nCopies */
733             if (!(lpdm->dmFields & DM_COPIES)) {
734                 EnableWindow(GetDlgItem(hDlg, edt3), FALSE);    
735                 EnableWindow(GetDlgItem(hDlg, stc5), FALSE);    
736             }
737         }
738
739         /* print to file */
740         CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0);
741         if (lppd->Flags & PD_DISABLEPRINTTOFILE)
742             EnableWindow(GetDlgItem(hDlg, chx1), FALSE);    
743         if (lppd->Flags & PD_HIDEPRINTTOFILE)
744             ShowWindow(GetDlgItem(hDlg, chx1), SW_HIDE);
745
746     } else { /* PD_PRINTSETUP */
747       BOOL bPortrait = (lpdm->u1.s1.dmOrientation == DMORIENT_PORTRAIT);
748
749       PRINTDLG_SetUpPaperComboBox(hDlg, cmb2,
750                                   PrintStructures->lpPrinterInfo->pPrinterName,
751                                   PrintStructures->lpPrinterInfo->pPortName,
752                                   lpdm);
753       PRINTDLG_SetUpPaperComboBox(hDlg, cmb3,
754                                   PrintStructures->lpPrinterInfo->pPrinterName,
755                                   PrintStructures->lpPrinterInfo->pPortName,
756                                   lpdm);
757       CheckRadioButton(hDlg, rad1, rad2, bPortrait ? rad1: rad2);
758       SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
759                           (LPARAM)(bPortrait ? PrintStructures->hPortraitIcon :
760                                    PrintStructures->hLandscapeIcon));
761       
762     }
763
764     /* help button */
765     if ((lppd->Flags & PD_SHOWHELP)==0) {
766         /* hide if PD_SHOWHELP not specified */
767         ShowWindow(GetDlgItem(hDlg, pshHelp), SW_HIDE);         
768     }
769     return TRUE;
770 }
771
772 /***********************************************************************
773  *           PRINTDLG_WMInitDialog                      [internal]
774  */
775 static LRESULT PRINTDLG_WMInitDialog(HWND hDlg, WPARAM wParam,
776                                      PRINT_PTRA* PrintStructures)
777 {
778     LPPRINTDLGA lppd = PrintStructures->dlg.lpPrintDlg;
779     DEVNAMES *pdn;
780     DEVMODEA *pdm;
781     char *name = NULL;
782     UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
783
784     /* load Collate ICONs */
785     /* We load these with LoadImage because they are not a standard
786        size and we don't want them rescaled */
787     PrintStructures->hCollateIcon =
788       LoadImageA(COMDLG32_hInstance, "PD32_COLLATE", IMAGE_ICON, 0, 0, 0);
789     PrintStructures->hNoCollateIcon = 
790       LoadImageA(COMDLG32_hInstance, "PD32_NOCOLLATE", IMAGE_ICON, 0, 0, 0);
791
792     /* These can be done with LoadIcon */
793     PrintStructures->hPortraitIcon =
794       LoadIconA(COMDLG32_hInstance, "PD32_PORTRAIT");
795     PrintStructures->hLandscapeIcon =
796       LoadIconA(COMDLG32_hInstance, "PD32_LANDSCAPE");
797
798     if(PrintStructures->hCollateIcon == 0 ||
799        PrintStructures->hNoCollateIcon == 0 ||
800        PrintStructures->hPortraitIcon == 0 ||
801        PrintStructures->hLandscapeIcon == 0) {
802         ERR("no icon in resourcefile\n");
803         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
804         EndDialog(hDlg, FALSE);
805     }
806
807     /*
808      * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
809      * must be registered and the Help button must be shown.
810      */
811     if (lppd->Flags & PD_SHOWHELP) {
812         if((PrintStructures->HelpMessageID = 
813             RegisterWindowMessageA(HELPMSGSTRINGA)) == 0) {
814             COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
815             return FALSE;
816         }
817     } else
818         PrintStructures->HelpMessageID = 0;
819
820     if(!(lppd->Flags &PD_PRINTSETUP)) {
821         PrintStructures->hwndUpDown =
822           CreateUpDownControl(WS_CHILD | WS_VISIBLE | WS_BORDER |
823                               UDS_NOTHOUSANDS | UDS_ARROWKEYS |
824                               UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 0, 0, 0, 0,
825                               hDlg, UPDOWN_ID, COMDLG32_hInstance,
826                               GetDlgItem(hDlg, edt3), MAX_COPIES, 1, 1);
827     }
828
829     /* FIXME: I allow more freedom than either Win95 or WinNT,
830      *        which do not agree to what errors should be thrown or not
831      *        in case nToPage or nFromPage is out-of-range.
832      */
833     if (lppd->nMaxPage < lppd->nMinPage)
834         lppd->nMaxPage = lppd->nMinPage;
835     if (lppd->nMinPage == lppd->nMaxPage) 
836         lppd->Flags |= PD_NOPAGENUMS;        
837     if (lppd->nToPage < lppd->nMinPage)
838         lppd->nToPage = lppd->nMinPage;
839     if (lppd->nToPage > lppd->nMaxPage)
840         lppd->nToPage = lppd->nMaxPage;
841     if (lppd->nFromPage < lppd->nMinPage)
842         lppd->nFromPage = lppd->nMinPage;
843     if (lppd->nFromPage > lppd->nMaxPage)
844         lppd->nFromPage = lppd->nMaxPage;
845
846     /* if we have the combo box, fill it */
847     if (GetDlgItem(hDlg,comboID)) {
848         /* Fill Combobox 
849          */
850         pdn = GlobalLock(lppd->hDevNames);
851         pdm = GlobalLock(lppd->hDevMode);
852         if(pdn)
853             name = (char*)pdn + pdn->wDeviceOffset;
854         else if(pdm)
855             name = pdm->dmDeviceName;
856         PRINTDLG_SetUpPrinterListCombo(hDlg, comboID, name);
857         if(pdm) GlobalUnlock(lppd->hDevMode);
858         if(pdn) GlobalUnlock(lppd->hDevNames);
859
860         /* Now find selected printer and update rest of dlg */
861         name = HeapAlloc(GetProcessHeap(),0,256);
862         if (GetDlgItemTextA(hDlg, comboID, name, 255))
863             PRINTDLG_ChangePrinter(hDlg, name, PrintStructures);
864         HeapFree(GetProcessHeap(),0,name);
865     } else {
866         /* else use default printer */
867         char name[200];
868         BOOL ret = PRINTDLG_GetDefaultPrinterName(name, sizeof(name));
869
870         if (ret)
871             PRINTDLG_ChangePrinter(hDlg, name, PrintStructures);
872         else
873             FIXME("No default printer found, expect problems!\n");
874     }
875     return TRUE;
876 }
877
878 /***********************************************************************
879  *           PRINTDLG_WMInitDialog                      [internal]
880  */
881 static LRESULT PRINTDLG_WMInitDialog16(HWND hDlg, WPARAM wParam,
882                                      PRINT_PTRA* PrintStructures)
883 {
884     LPPRINTDLG16 lppd = PrintStructures->dlg.lpPrintDlg16;
885     DEVNAMES *pdn;
886     DEVMODEA *pdm;
887     char *name = NULL;
888     UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
889
890     /* load Collate ICONs */
891     PrintStructures->hCollateIcon =
892       LoadIconA(COMDLG32_hInstance, "PD32_COLLATE");
893     PrintStructures->hNoCollateIcon = 
894       LoadIconA(COMDLG32_hInstance, "PD32_NOCOLLATE");
895     if(PrintStructures->hCollateIcon == 0 ||
896        PrintStructures->hNoCollateIcon == 0) {
897         ERR("no icon in resourcefile\n");
898         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
899         EndDialog(hDlg, FALSE);
900     }
901
902     /* load Paper Orientation ICON */
903     /* FIXME: not implemented yet */
904
905     /*
906      * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
907      * must be registered and the Help button must be shown.
908      */
909     if (lppd->Flags & PD_SHOWHELP) {
910         if((PrintStructures->HelpMessageID = 
911             RegisterWindowMessageA(HELPMSGSTRINGA)) == 0) {
912             COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
913             return FALSE;
914         }
915     } else
916         PrintStructures->HelpMessageID = 0;
917
918     if (!(lppd->Flags & PD_PRINTSETUP)) {
919         /* We have a print quality combo box. What shall we do? */
920         if (GetDlgItem(hDlg,cmb1)) {
921             char buf [20];
922
923             FIXME("Print quality only displaying currently.\n");
924
925             pdm = GlobalLock16(lppd->hDevMode);
926             if(pdm) {
927                 switch (pdm->dmPrintQuality) {
928                 case DMRES_HIGH         : strcpy(buf,"High");break;
929                 case DMRES_MEDIUM       : strcpy(buf,"Medium");break;
930                 case DMRES_LOW          : strcpy(buf,"Low");break;
931                 case DMRES_DRAFT        : strcpy(buf,"Draft");break;
932                 case 0                  : strcpy(buf,"Default");break;
933                 default                 : sprintf(buf,"%ddpi",pdm->dmPrintQuality);break;
934                 }
935                 GlobalUnlock16(lppd->hDevMode);
936             } else 
937                 strcpy(buf,"Default");
938             SendDlgItemMessageA(hDlg,cmb1,CB_ADDSTRING,0,(LPARAM)buf);
939             SendDlgItemMessageA(hDlg,cmb1,CB_SETCURSEL,0,0);
940             EnableWindow(GetDlgItem(hDlg,cmb1),FALSE);
941         }
942     }
943
944     /* FIXME: I allow more freedom than either Win95 or WinNT,
945      *        which do not agree to what errors should be thrown or not
946      *        in case nToPage or nFromPage is out-of-range.
947      */
948     if (lppd->nMaxPage < lppd->nMinPage)
949         lppd->nMaxPage = lppd->nMinPage;
950     if (lppd->nMinPage == lppd->nMaxPage) 
951         lppd->Flags |= PD_NOPAGENUMS;        
952     if (lppd->nToPage < lppd->nMinPage)
953         lppd->nToPage = lppd->nMinPage;
954     if (lppd->nToPage > lppd->nMaxPage)
955         lppd->nToPage = lppd->nMaxPage;
956     if (lppd->nFromPage < lppd->nMinPage)
957         lppd->nFromPage = lppd->nMinPage;
958     if (lppd->nFromPage > lppd->nMaxPage)
959         lppd->nFromPage = lppd->nMaxPage;
960
961     /* If the printer combo box is in the dialog, fill it */
962     if (GetDlgItem(hDlg,comboID)) {
963         /* Fill Combobox 
964          */
965         pdn = GlobalLock16(lppd->hDevNames);
966         pdm = GlobalLock16(lppd->hDevMode);
967         if(pdn)
968             name = (char*)pdn + pdn->wDeviceOffset;
969         else if(pdm)
970             name = pdm->dmDeviceName;
971         PRINTDLG_SetUpPrinterListCombo(hDlg, comboID, name);
972         if(pdm) GlobalUnlock16(lppd->hDevMode);
973         if(pdn) GlobalUnlock16(lppd->hDevNames);
974
975         /* Now find selected printer and update rest of dlg */
976         name = HeapAlloc(GetProcessHeap(),0,256);
977         if (GetDlgItemTextA(hDlg, comboID, name, 255))
978             PRINTDLG_ChangePrinter(hDlg, name, PrintStructures);
979     } else {
980         /* else just use default printer */
981         char name[200];
982         BOOL ret = PRINTDLG_GetDefaultPrinterName(name, sizeof(name));
983
984         if (ret)
985             PRINTDLG_ChangePrinter(hDlg, name, PrintStructures);
986         else
987             FIXME("No default printer found, expect problems!\n");
988     }
989     HeapFree(GetProcessHeap(),0,name);
990
991     return TRUE;
992 }
993
994 /***********************************************************************
995  *                              PRINTDLG_WMCommand               [internal]
996  */
997 static LRESULT PRINTDLG_WMCommand(HWND hDlg, WPARAM wParam, 
998                         LPARAM lParam, PRINT_PTRA* PrintStructures)
999 {
1000     LPPRINTDLGA lppd = PrintStructures->dlg.lpPrintDlg;
1001     UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1002     LPDEVMODEA lpdm = PrintStructures->lpDevMode;
1003
1004     switch (LOWORD(wParam))  {
1005     case IDOK:
1006         TRACE(" OK button was hit\n");
1007         if (PRINTDLG_UpdatePrintDlg(hDlg, PrintStructures)!=TRUE) {
1008             FIXME("Update printdlg was not successful!\n");
1009             return(FALSE);
1010         }
1011         EndDialog(hDlg, TRUE);
1012         return(TRUE);
1013
1014     case IDCANCEL:
1015         TRACE(" CANCEL button was hit\n");
1016         EndDialog(hDlg, FALSE);
1017         return(FALSE);
1018
1019      case pshHelp:
1020         TRACE(" HELP button was hit\n");
1021         SendMessageA(lppd->hwndOwner, PrintStructures->HelpMessageID, 
1022                                 (WPARAM) hDlg, (LPARAM) lppd);
1023         break;
1024
1025      case chx2:                         /* collate pages checkbox */
1026         if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
1027             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON, 
1028                                     (LPARAM)PrintStructures->hCollateIcon);
1029         else
1030             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON, 
1031                                     (LPARAM)PrintStructures->hNoCollateIcon);
1032         break;        
1033      case edt1:                         /* from page nr editbox */
1034      case edt2:                         /* to page nr editbox */
1035         if (HIWORD(wParam)==EN_CHANGE) {
1036             WORD nToPage;
1037             WORD nFromPage;
1038             nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
1039             nToPage   = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
1040             if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
1041                 CheckRadioButton(hDlg, rad1, rad3, rad3);
1042         }
1043         break;
1044
1045     case edt3:
1046         if(HIWORD(wParam) == EN_CHANGE) {
1047             INT copies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
1048             if(copies <= 1)
1049                 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1050             else
1051                 EnableWindow(GetDlgItem(hDlg, chx2), TRUE);
1052         }
1053         break;
1054
1055      case psh1:                       /* Print Setup */
1056         {
1057             PRINTDLG16  pdlg;
1058             
1059             if (!PrintStructures->dlg.lpPrintDlg16) {
1060                 FIXME("The 32bit print dialog does not have this button!?\n");
1061                 break;
1062             }
1063
1064             memcpy(&pdlg,PrintStructures->dlg.lpPrintDlg16,sizeof(pdlg));
1065             pdlg.Flags |= PD_PRINTSETUP;
1066             pdlg.hwndOwner = hDlg;
1067             if (!PrintDlg16(&pdlg))
1068                 break;
1069         }
1070         break;
1071      case psh2:                       /* Properties button */
1072        {
1073          HANDLE hPrinter;
1074          char   PrinterName[256];
1075
1076          GetDlgItemTextA(hDlg, PrinterComboID, PrinterName, 255);
1077          if (!OpenPrinterA(PrinterName, &hPrinter, NULL)) {
1078              FIXME(" Call to OpenPrinter did not succeed!\n");
1079              break;
1080          }
1081          DocumentPropertiesA(hDlg, hPrinter, PrinterName, 
1082                              PrintStructures->lpDevMode,
1083                              PrintStructures->lpDevMode,
1084                              DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
1085          ClosePrinter(hPrinter);
1086          break;
1087        }
1088
1089     case rad1: /* Paperorientation */
1090         if (lppd->Flags & PD_PRINTSETUP)
1091         {
1092               lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1093               SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1094                           (LPARAM)(PrintStructures->hPortraitIcon));
1095         }
1096         break;
1097             
1098     case rad2: /* Paperorientation */
1099         if (lppd->Flags & PD_PRINTSETUP)
1100         {
1101               lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1102               SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
1103                           (LPARAM)(PrintStructures->hLandscapeIcon));
1104         }
1105         break;
1106             
1107     case cmb1: /* Printer Combobox in PRINT SETUP, quality combobox in PRINT */
1108          if (PrinterComboID != wParam) {
1109              FIXME("No handling for print quality combo box yet.\n");
1110              break;
1111          }
1112          /* FALLTHROUGH */
1113     case cmb4:                         /* Printer combobox */
1114          if (HIWORD(wParam)==CBN_SELCHANGE) {
1115              char   PrinterName[256];
1116              GetDlgItemTextA(hDlg, LOWORD(wParam), PrinterName, 255);
1117              PRINTDLG_ChangePrinter(hDlg, PrinterName, PrintStructures);
1118          }
1119          break;
1120
1121     case cmb2: /* Papersize */
1122       {
1123           DWORD Sel = SendDlgItemMessageA(hDlg, cmb2, CB_GETCURSEL, 0, 0);
1124           if(Sel != CB_ERR)
1125               lpdm->u1.s1.dmPaperSize = SendDlgItemMessageA(hDlg, cmb2,
1126                                                             CB_GETITEMDATA,
1127                                                             Sel, 0);
1128       }
1129       break;
1130
1131     case cmb3: /* Bin */
1132       {
1133           DWORD Sel = SendDlgItemMessageA(hDlg, cmb3, CB_GETCURSEL, 0, 0);
1134           if(Sel != CB_ERR)
1135               lpdm->dmDefaultSource = SendDlgItemMessageA(hDlg, cmb3,
1136                                                           CB_GETITEMDATA, Sel,
1137                                                           0);
1138       }
1139       break; 
1140     }
1141     if(lppd->Flags & PD_PRINTSETUP) {
1142         switch (LOWORD(wParam)) {
1143         case rad1:                         /* orientation */
1144         case rad2:
1145             if (IsDlgButtonChecked(hDlg, rad1) == BST_CHECKED) {
1146                 if(lpdm->u1.s1.dmOrientation != DMORIENT_PORTRAIT) {
1147                     lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1148                     SendDlgItemMessageA(hDlg, stc10, STM_SETIMAGE,
1149                                         (WPARAM)IMAGE_ICON,
1150                                         (LPARAM)PrintStructures->hPortraitIcon);
1151                     SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE,
1152                                         (WPARAM)IMAGE_ICON,
1153                                         (LPARAM)PrintStructures->hPortraitIcon);
1154                 }
1155             } else {
1156                 if(lpdm->u1.s1.dmOrientation != DMORIENT_LANDSCAPE) {
1157                     lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1158                     SendDlgItemMessageA(hDlg, stc10, STM_SETIMAGE,
1159                                         (WPARAM)IMAGE_ICON,
1160                                         (LPARAM)PrintStructures->hLandscapeIcon);
1161                     SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE,
1162                                         (WPARAM)IMAGE_ICON,
1163                                         (LPARAM)PrintStructures->hLandscapeIcon);
1164                 }
1165             }
1166             break;
1167         }
1168     }
1169     return FALSE;
1170 }    
1171
1172 /***********************************************************************
1173  *           PrintDlgProcA                      [internal]
1174  */
1175 BOOL WINAPI PrintDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam,
1176                           LPARAM lParam)
1177 {
1178     PRINT_PTRA* PrintStructures;
1179     LRESULT res=FALSE;
1180
1181     if (uMsg!=WM_INITDIALOG) {
1182         PrintStructures = (PRINT_PTRA*) GetWindowLongA(hDlg, DWL_USER);   
1183         if (!PrintStructures)
1184             return FALSE;
1185     } else {
1186         PrintStructures = (PRINT_PTRA*) lParam;
1187         SetWindowLongA(hDlg, DWL_USER, lParam); 
1188         res = PRINTDLG_WMInitDialog(hDlg, wParam, PrintStructures);
1189
1190         if(PrintStructures->dlg.lpPrintDlg->Flags & PD_ENABLEPRINTHOOK)
1191             res = PrintStructures->dlg.lpPrintDlg->lpfnPrintHook(
1192                 hDlg, uMsg, wParam, (LPARAM)PrintStructures->dlg.lpPrintDlg
1193             ); 
1194         return res;
1195     }
1196   
1197     if(PrintStructures->dlg.lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) {
1198         res = PrintStructures->dlg.lpPrintDlg->lpfnPrintHook(hDlg,uMsg,wParam,
1199                                                          lParam);
1200         if(res) return res;
1201     }
1202
1203     switch (uMsg) {
1204     case WM_COMMAND:
1205         return PRINTDLG_WMCommand(hDlg, wParam, lParam, PrintStructures);
1206
1207     case WM_DESTROY:
1208         DestroyIcon(PrintStructures->hCollateIcon);
1209         DestroyIcon(PrintStructures->hNoCollateIcon);
1210         DestroyIcon(PrintStructures->hPortraitIcon);
1211         DestroyIcon(PrintStructures->hLandscapeIcon);
1212         if(PrintStructures->hwndUpDown)
1213             DestroyWindow(PrintStructures->hwndUpDown);
1214         return FALSE;
1215     }    
1216     return res;
1217 }
1218
1219
1220 /************************************************************
1221  *
1222  *      PRINTDLG_Get16TemplateFrom32             [Internal]
1223  *      Generates a 16 bits template from the Wine 32 bits resource
1224  *
1225  */
1226 static HGLOBAL16 PRINTDLG_Get16TemplateFrom32(char *PrintResourceName)
1227 {
1228         HANDLE hResInfo, hDlgTmpl32;
1229         LPCVOID template32;
1230         DWORD size;
1231         HGLOBAL16 hGlobal16;
1232         LPVOID template;
1233  
1234         if (!(hResInfo = FindResourceA(COMMDLG_hInstance32,
1235                PrintResourceName, RT_DIALOGA)))
1236         {
1237             COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
1238             return 0;
1239         }
1240         if (!(hDlgTmpl32 = LoadResource(COMMDLG_hInstance32, hResInfo )) ||
1241             !(template32 = LockResource( hDlgTmpl32 )))
1242         {
1243             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1244             return 0;
1245         }
1246         size = SizeofResource(COMMDLG_hInstance32, hResInfo);
1247         hGlobal16 = GlobalAlloc16(0, size);
1248         if (!hGlobal16)
1249         {
1250             COMDLG32_SetCommDlgExtendedError(CDERR_MEMALLOCFAILURE);
1251             ERR("alloc failure for %ld bytes\n", size);
1252             return 0;
1253         }
1254         template = GlobalLock16(hGlobal16);
1255         if (!template)
1256         {
1257             COMDLG32_SetCommDlgExtendedError(CDERR_MEMLOCKFAILURE);
1258             ERR("global lock failure for %x handle\n", hGlobal16);
1259             GlobalFree16(hGlobal16);
1260             return 0;
1261         }
1262         ConvertDialog32To16((LPVOID)template32, size, (LPVOID)template);
1263         GlobalUnlock16(hGlobal16);
1264         return hGlobal16;
1265 }
1266
1267 /************************************************************
1268  *
1269  *      PRINTDLG_GetDlgTemplate
1270  *
1271  */
1272 static HGLOBAL PRINTDLG_GetDlgTemplate(PRINTDLGA *lppd)
1273 {
1274     HGLOBAL hDlgTmpl, hResInfo;
1275
1276     if (lppd->Flags & PD_PRINTSETUP) {
1277         if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
1278             hDlgTmpl = lppd->hSetupTemplate;
1279         } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {       
1280             hResInfo = FindResourceA(lppd->hInstance,
1281                                      lppd->lpSetupTemplateName, RT_DIALOGA);
1282             hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
1283         } else {
1284             hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32_SETUP",
1285                                      RT_DIALOGA);
1286             hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
1287         }
1288     } else {
1289         if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
1290             hDlgTmpl = lppd->hPrintTemplate;
1291         } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
1292             hResInfo = FindResourceA(lppd->hInstance,
1293                                      lppd->lpPrintTemplateName,
1294                                      RT_DIALOGA);
1295             hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
1296         } else {
1297             hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32",
1298                                      RT_DIALOGA);
1299             hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
1300         }
1301     }
1302     return hDlgTmpl;
1303 }
1304
1305
1306 /************************************************************
1307  *
1308  *      PRINTDLG_GetDlgTemplate
1309  *
1310  */
1311 static HGLOBAL16 PRINTDLG_GetDlgTemplate16(PRINTDLG16 *lppd)
1312 {
1313     HGLOBAL16 hDlgTmpl, hResInfo;
1314
1315     if (lppd->Flags & PD_PRINTSETUP) {
1316         if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
1317             hDlgTmpl = lppd->hSetupTemplate;
1318         } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {       
1319             hResInfo = FindResource16(lppd->hInstance,
1320                                      MapSL(lppd->lpSetupTemplateName), RT_DIALOGA);
1321             hDlgTmpl = LoadResource16(lppd->hInstance, hResInfo);
1322         } else {
1323             hDlgTmpl = PRINTDLG_Get16TemplateFrom32("PRINT32_SETUP");
1324         }
1325     } else {
1326         if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
1327             hDlgTmpl = lppd->hPrintTemplate;
1328         } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
1329             hResInfo = FindResource16(lppd->hInstance,
1330                                      MapSL(lppd->lpPrintTemplateName),
1331                                      RT_DIALOGA);
1332             hDlgTmpl = LoadResource16(lppd->hInstance, hResInfo);
1333         } else {
1334             hDlgTmpl = PRINTDLG_Get16TemplateFrom32("PRINT32");
1335         }
1336     }
1337     return hDlgTmpl;
1338 }
1339
1340 /***********************************************************************
1341  *
1342  *      PRINTDLG_CreateDC
1343  *
1344  */
1345 static BOOL PRINTDLG_CreateDC(LPPRINTDLGA lppd)
1346 {
1347     DEVNAMES *pdn = GlobalLock(lppd->hDevNames);
1348     DEVMODEA *pdm = GlobalLock(lppd->hDevMode);
1349
1350     if(lppd->Flags & PD_RETURNDC) {
1351         lppd->hDC = CreateDCA((char*)pdn + pdn->wDriverOffset,
1352                               (char*)pdn + pdn->wDeviceOffset,
1353                               (char*)pdn + pdn->wOutputOffset,
1354                               pdm );
1355     } else if(lppd->Flags & PD_RETURNIC) {
1356         lppd->hDC = CreateICA((char*)pdn + pdn->wDriverOffset,
1357                               (char*)pdn + pdn->wDeviceOffset,
1358                               (char*)pdn + pdn->wOutputOffset,
1359                               pdm );
1360     }
1361     GlobalUnlock(lppd->hDevNames);
1362     GlobalUnlock(lppd->hDevMode);
1363     return lppd->hDC ? TRUE : FALSE;
1364 }
1365
1366 static BOOL PRINTDLG_CreateDC16(LPPRINTDLG16 lppd)
1367 {
1368     DEVNAMES *pdn = GlobalLock16(lppd->hDevNames);
1369     DEVMODEA *pdm = GlobalLock16(lppd->hDevMode);
1370
1371     if(lppd->Flags & PD_RETURNDC) {
1372         lppd->hDC = CreateDCA((char*)pdn + pdn->wDriverOffset,
1373                               (char*)pdn + pdn->wDeviceOffset,
1374                               (char*)pdn + pdn->wOutputOffset,
1375                               pdm );
1376     } else if(lppd->Flags & PD_RETURNIC) {
1377         lppd->hDC = CreateICA((char*)pdn + pdn->wDriverOffset,
1378                               (char*)pdn + pdn->wDeviceOffset,
1379                               (char*)pdn + pdn->wOutputOffset,
1380                               pdm );
1381     }
1382     GlobalUnlock16(lppd->hDevNames);
1383     GlobalUnlock16(lppd->hDevMode);
1384     return lppd->hDC ? TRUE : FALSE;
1385 }
1386
1387 /***********************************************************************
1388  *           PrintDlgA   (COMDLG32.@)
1389  *
1390  *  Displays the the PRINT dialog box, which enables the user to specify
1391  *  specific properties of the print job.
1392  *
1393  * RETURNS
1394  *  nonzero if the user pressed the OK button
1395  *  zero    if the user cancelled the window or an error occurred
1396  *
1397  * BUGS
1398  *  PrintDlg:
1399  *  * The Collate Icons do not display, even though they are in the code.
1400  *  * The Properties Button(s) should call DocumentPropertiesA().
1401  *  PrintSetupDlg:
1402  *  * The Paper Orientation Icons are not implemented yet.
1403  *  * The Properties Button(s) should call DocumentPropertiesA().
1404  *  * Settings are not yet taken from a provided DevMode or 
1405  *    default printer settings.
1406  */
1407 BOOL WINAPI PrintDlgA(
1408                       LPPRINTDLGA lppd /* [in/out] ptr to PRINTDLG32 struct */
1409                       )
1410 {
1411     BOOL      bRet = FALSE;
1412     LPVOID   ptr;
1413     HINSTANCE hInst = GetWindowLongA( lppd->hwndOwner, GWL_HINSTANCE );
1414
1415     if(TRACE_ON(commdlg)) {
1416         char flagstr[1000] = "";
1417         struct pd_flags *pflag = pd_flags;
1418         for( ; pflag->name; pflag++) {
1419             if(lppd->Flags & pflag->flag)
1420                 strcat(flagstr, pflag->name);
1421         }
1422         TRACE("(%p): hwndOwner = %08x, hDevMode = %08x, hDevNames = %08x\n"
1423               "pp. %d-%d, min p %d, max p %d, copies %d, hinst %08x\n"
1424               "flags %08lx (%s)\n",
1425               lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
1426               lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
1427               lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
1428     }
1429
1430     if(lppd->lStructSize != sizeof(PRINTDLGA)) {
1431         WARN("structure size failure !!!\n");
1432         COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
1433         return FALSE; 
1434     }
1435
1436     if(lppd->Flags & PD_RETURNDEFAULT) {
1437         PRINTER_INFO_2A *pbuf;
1438         DRIVER_INFO_3A  *dbuf;
1439         HANDLE hprn;
1440         DWORD needed;
1441
1442         if(lppd->hDevMode || lppd->hDevNames) {
1443             WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
1444             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE); 
1445             return FALSE;
1446         }
1447         if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
1448             WARN("Can't find default printer\n");
1449             COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN); 
1450             return FALSE;
1451         }
1452
1453         GetPrinterA(hprn, 2, NULL, 0, &needed);
1454         pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
1455         GetPrinterA(hprn, 2, (LPBYTE)pbuf, needed, &needed);
1456
1457         GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
1458         dbuf = HeapAlloc(GetProcessHeap(),0,needed);
1459         if (!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) {
1460             ERR("GetPrinterDriverA failed, le %ld, fix your config for printer %s!\n",GetLastError(),pbuf->pPrinterName);
1461             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE); 
1462             return FALSE;
1463         }
1464         ClosePrinter(hprn);
1465
1466         PRINTDLG_CreateDevNames(&(lppd->hDevNames),
1467                                   dbuf->pDriverPath,
1468                                   pbuf->pPrinterName,
1469                                   pbuf->pPortName);
1470         lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
1471                                      pbuf->pDevMode->dmDriverExtra);
1472         ptr = GlobalLock(lppd->hDevMode);
1473         memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
1474                pbuf->pDevMode->dmDriverExtra);
1475         GlobalUnlock(lppd->hDevMode);
1476         HeapFree(GetProcessHeap(), 0, pbuf);
1477         HeapFree(GetProcessHeap(), 0, dbuf);
1478         bRet = TRUE;
1479     } else {
1480         HGLOBAL hDlgTmpl;
1481         PRINT_PTRA *PrintStructures;
1482
1483     /* load Dialog resources, 
1484      * depending on Flags indicates Print32 or Print32_setup dialog 
1485      */
1486         hDlgTmpl = PRINTDLG_GetDlgTemplate(lppd);
1487         if (!hDlgTmpl) {
1488             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1489             return FALSE;
1490         }
1491         ptr = LockResource( hDlgTmpl );
1492         if (!ptr) {
1493             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1494             return FALSE;
1495         }
1496
1497         PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1498                                     sizeof(PRINT_PTRA));
1499         PrintStructures->dlg.lpPrintDlg = lppd;
1500
1501         /* and create & process the dialog .
1502          * -1 is failure, 0 is broken hwnd, everything else is ok.
1503          */
1504         bRet = (0<DialogBoxIndirectParamA(hInst, ptr, lppd->hwndOwner,
1505                                            PrintDlgProcA,
1506                                            (LPARAM)PrintStructures));
1507
1508         if(bRet) {
1509             DEVMODEA *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
1510             PRINTER_INFO_2A *pi = PrintStructures->lpPrinterInfo;
1511             DRIVER_INFO_3A *di = PrintStructures->lpDriverInfo;
1512
1513             if (lppd->hDevMode == 0) {
1514                 TRACE(" No hDevMode yet... Need to create my own\n");
1515                 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE,
1516                                         lpdm->dmSize + lpdm->dmDriverExtra);
1517             } else {
1518                 WORD locks;
1519                 if((locks = (GlobalFlags(lppd->hDevMode) & GMEM_LOCKCOUNT))) {
1520                     WARN("hDevMode has %d locks on it. Unlocking it now\n", locks);
1521                     while(locks--) {
1522                         GlobalUnlock(lppd->hDevMode);
1523                         TRACE("Now got %d locks\n", locks);
1524                     }
1525                 }
1526                 lppd->hDevMode = GlobalReAlloc(lppd->hDevMode,
1527                                                lpdm->dmSize + lpdm->dmDriverExtra,
1528                                                GMEM_MOVEABLE);
1529             }
1530             lpdmReturn = GlobalLock(lppd->hDevMode);
1531             memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
1532
1533             if (lppd->hDevNames != 0) {
1534                 WORD locks;
1535                 if((locks = (GlobalFlags(lppd->hDevNames) & GMEM_LOCKCOUNT))) {
1536                     WARN("hDevNames has %d locks on it. Unlocking it now\n", locks);
1537                     while(locks--)
1538                         GlobalUnlock(lppd->hDevNames);
1539                 }
1540             }
1541             PRINTDLG_CreateDevNames(&(lppd->hDevNames),
1542                     di->pDriverPath,
1543                     pi->pPrinterName,
1544                     pi->pPortName
1545             );
1546             GlobalUnlock(lppd->hDevMode);
1547         }
1548         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
1549         HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
1550         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo);
1551         HeapFree(GetProcessHeap(), 0, PrintStructures);
1552     }
1553     if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
1554         bRet = PRINTDLG_CreateDC(lppd);
1555
1556     TRACE("exit! (%d)\n", bRet);        
1557     return bRet;    
1558 }
1559
1560 /***********************************************************************
1561  *           PrintDlg   (COMMDLG.20)
1562  * 
1563  *  Displays the the PRINT dialog box, which enables the user to specify
1564  *  specific properties of the print job.
1565  *
1566  * RETURNS
1567  *  nonzero if the user pressed the OK button
1568  *  zero    if the user cancelled the window or an error occurred
1569  *
1570  * BUGS
1571  *  * calls up to the 32-bit versions of the Dialogs, which look different
1572  *  * Customizing is *not* implemented.
1573  */
1574
1575 BOOL16 WINAPI PrintDlg16(
1576               LPPRINTDLG16 lppd /* [in/out] ptr to PRINTDLG struct */
1577 ) {
1578     BOOL      bRet = FALSE;
1579     LPVOID   ptr;
1580     HINSTANCE hInst = GetWindowLongA( lppd->hwndOwner, GWL_HINSTANCE );
1581
1582     if(TRACE_ON(commdlg)) {
1583         char flagstr[1000] = "";
1584         struct pd_flags *pflag = pd_flags;
1585         for( ; pflag->name; pflag++) {
1586             if(lppd->Flags & pflag->flag)
1587                 strcat(flagstr, pflag->name);
1588         }
1589         TRACE("(%p): hwndOwner = %08x, hDevMode = %08x, hDevNames = %08x\n"
1590               "pp. %d-%d, min p %d, max p %d, copies %d, hinst %08x\n"
1591               "flags %08lx (%s)\n",
1592               lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
1593               lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
1594               lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
1595     }
1596
1597     if(lppd->lStructSize != sizeof(PRINTDLG16)) {
1598         ERR("structure size (%ld/%d)\n",lppd->lStructSize,sizeof(PRINTDLG16));
1599         COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
1600         return FALSE;
1601     }
1602
1603     if(lppd->Flags & PD_RETURNDEFAULT) {
1604         PRINTER_INFO_2A *pbuf;
1605         DRIVER_INFO_3A  *dbuf;
1606         HANDLE hprn;
1607         DWORD needed;
1608
1609         if(lppd->hDevMode || lppd->hDevNames) {
1610             WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
1611             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE); 
1612             return FALSE;
1613         }
1614         if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
1615             WARN("Can't find default printer\n");
1616             COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN); 
1617             return FALSE;
1618         }
1619
1620         GetPrinterA(hprn, 2, NULL, 0, &needed);
1621         pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
1622         GetPrinterA(hprn, 2, (LPBYTE)pbuf, needed, &needed);
1623         GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
1624         dbuf = HeapAlloc(GetProcessHeap(),0,needed);
1625         if (!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) {
1626             ERR("GetPrinterDriverA failed for %s, le %ld, fix your config!\n",
1627                     pbuf->pPrinterName,GetLastError());
1628             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE); 
1629             return FALSE;
1630         }
1631         ClosePrinter(hprn);
1632         PRINTDLG_CreateDevNames16(&(lppd->hDevNames),
1633                                 dbuf->pDriverPath,
1634                                 pbuf->pPrinterName,
1635                                 pbuf->pPortName);
1636         lppd->hDevMode = GlobalAlloc16(GMEM_MOVEABLE,pbuf->pDevMode->dmSize+
1637                                      pbuf->pDevMode->dmDriverExtra);
1638         ptr = GlobalLock16(lppd->hDevMode);
1639         memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
1640                pbuf->pDevMode->dmDriverExtra);
1641         GlobalUnlock16(lppd->hDevMode);
1642         HeapFree(GetProcessHeap(), 0, pbuf);
1643         HeapFree(GetProcessHeap(), 0, dbuf);
1644         bRet = TRUE;
1645     } else {
1646         HGLOBAL hDlgTmpl;
1647         PRINT_PTRA *PrintStructures;
1648
1649     /* load Dialog resources, 
1650      * depending on Flags indicates Print32 or Print32_setup dialog 
1651      */
1652         hDlgTmpl = PRINTDLG_GetDlgTemplate16(lppd);
1653         if (!hDlgTmpl) {
1654             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1655             return FALSE;
1656         }
1657         PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1658                                     sizeof(PRINT_PTRA));
1659         PrintStructures->dlg.lpPrintDlg16 = lppd;
1660         PrintStructures->dlg.lpPrintDlg = (LPPRINTDLGA)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(PRINTDLGA));
1661 #define CVAL(x) PrintStructures->dlg.lpPrintDlg->x = lppd->x;
1662 #define MVAL(x) PrintStructures->dlg.lpPrintDlg->x = MapSL(lppd->x);
1663         CVAL(Flags);CVAL(hwndOwner);CVAL(hDC);
1664         CVAL(nFromPage);CVAL(nToPage);CVAL(nMinPage);CVAL(nMaxPage);
1665         CVAL(nCopies);CVAL(hInstance);CVAL(lCustData);
1666         MVAL(lpPrintTemplateName);MVAL(lpSetupTemplateName);
1667         /* Don't copy rest, it is 16 bit specific */
1668 #undef MVAL
1669 #undef CVAL
1670
1671         PrintStructures->lpDevMode = HeapAlloc(GetProcessHeap(),0,sizeof(DEVMODEA));
1672
1673         /* and create & process the dialog .
1674          * -1 is failure, 0 is broken hwnd, everything else is ok.
1675          */
1676         bRet =  (0<DialogBoxIndirectParam16(
1677                  hInst, hDlgTmpl, lppd->hwndOwner,
1678                  (DLGPROC16)GetProcAddress16(GetModuleHandle16("COMMDLG"),(LPCSTR)21),
1679                  (LPARAM)PrintStructures
1680                 )
1681         );
1682         if (!PrintStructures->lpPrinterInfo) bRet = FALSE;
1683         if(bRet) {
1684             DEVMODEA *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
1685             PRINTER_INFO_2A *pi = PrintStructures->lpPrinterInfo;
1686             DRIVER_INFO_3A *di = PrintStructures->lpDriverInfo;
1687
1688             if (lppd->hDevMode == 0) {
1689                 TRACE(" No hDevMode yet... Need to create my own\n");
1690                 lppd->hDevMode = GlobalAlloc16(GMEM_MOVEABLE,
1691                                         lpdm->dmSize + lpdm->dmDriverExtra);
1692             } else {
1693                 WORD locks;
1694                 if((locks = (GlobalFlags16(lppd->hDevMode)&GMEM_LOCKCOUNT))) {
1695                     WARN("hDevMode has %d locks on it. Unlocking it now\n", locks);
1696                     while(locks--) {
1697                         GlobalUnlock16(lppd->hDevMode);
1698                         TRACE("Now got %d locks\n", locks);
1699                     }
1700                 }
1701                 lppd->hDevMode = GlobalReAlloc16(lppd->hDevMode,
1702                                                lpdm->dmSize + lpdm->dmDriverExtra,
1703                                                GMEM_MOVEABLE);
1704             }
1705             lpdmReturn = GlobalLock16(lppd->hDevMode);
1706             memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
1707
1708             if (lppd->hDevNames != 0) {
1709                 WORD locks;
1710                 if((locks = (GlobalFlags16(lppd->hDevNames)&GMEM_LOCKCOUNT))) {
1711                     WARN("hDevNames has %d locks on it. Unlocking it now\n", locks);
1712                     while(locks--)
1713                         GlobalUnlock16(lppd->hDevNames);
1714                 }
1715             }
1716             PRINTDLG_CreateDevNames16(&(lppd->hDevNames),
1717                     di->pDriverPath,
1718                     pi->pPrinterName,
1719                     pi->pPortName
1720             );
1721             GlobalUnlock16(lppd->hDevMode);
1722         }
1723         if (!(lppd->Flags & (PD_ENABLESETUPTEMPLATEHANDLE | PD_ENABLESETUPTEMPLATE)))
1724             GlobalFree16(hDlgTmpl); /* created from the 32 bits resource */
1725         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
1726         HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
1727         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo);
1728         HeapFree(GetProcessHeap(), 0, PrintStructures);
1729     }
1730     if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
1731         bRet = PRINTDLG_CreateDC16(lppd);
1732
1733     TRACE("exit! (%d)\n", bRet);        
1734     return bRet;    
1735 }
1736
1737
1738
1739 /***********************************************************************
1740  *           PrintDlgW   (COMDLG32.@)
1741  */
1742 BOOL WINAPI PrintDlgW( LPPRINTDLGW printdlg )
1743 {
1744     FIXME("A really empty stub\n" );
1745     return FALSE;
1746 }
1747
1748 /***********************************************************************
1749  *
1750  *          PageSetupDlg
1751  * rad1 - portrait
1752  * rad2 - landscape
1753  * cmb2 - paper size
1754  * cmb3 - source (tray?)
1755  * edt4 - border left
1756  * edt5 - border top
1757  * edt6 - border right
1758  * edt7 - border bottom
1759  * psh3 - "Printer..."
1760  */
1761
1762 typedef struct {
1763     LPPAGESETUPDLGA     dlga;
1764
1765     PRINTDLGA           pdlg;
1766 } PageSetupData;
1767
1768 static HGLOBAL PRINTDLG_GetPGSTemplate(PAGESETUPDLGA *lppd)
1769 {
1770     HGLOBAL hDlgTmpl, hResInfo;
1771
1772     if(lppd->Flags & PSD_ENABLEPAGESETUPTEMPLATEHANDLE) {
1773         hDlgTmpl = lppd->hPageSetupTemplate;
1774     } else if(lppd->Flags & PSD_ENABLEPAGESETUPTEMPLATE) {      
1775         hResInfo = FindResourceA(lppd->hInstance,
1776                                  lppd->lpPageSetupTemplateName, RT_DIALOGA);
1777         hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
1778     } else {
1779         hResInfo = FindResourceA(COMDLG32_hInstance,(LPCSTR)PAGESETUPDLGORD,RT_DIALOGA);
1780         hDlgTmpl = LoadResource(COMDLG32_hInstance,hResInfo);
1781     }
1782     return hDlgTmpl;
1783 }
1784
1785 static DWORD
1786 _c_10mm2size(PAGESETUPDLGA *dlga,DWORD size) {
1787     if (dlga->Flags & PSD_INTHOUSANDTHSOFINCHES)
1788         return 10*size*10/25.4;
1789     /* If we don't have a flag, we can choose one. Use millimeters
1790      * to avoid confusing me
1791      */
1792     dlga->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
1793     FIXME("returning %ld/100 mm \n",size);
1794     return 10*size;
1795 }
1796
1797
1798 static DWORD
1799 _c_inch2size(PAGESETUPDLGA *dlga,DWORD size) {
1800     if (dlga->Flags & PSD_INTHOUSANDTHSOFINCHES)
1801         return size;
1802     if (dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS)
1803         return (size*254)/10;
1804     /* if we don't have a flag, we can choose one. Use millimeters
1805      * to avoid confusing me
1806      */
1807     dlga->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
1808     return (size*254)/10;
1809 }
1810
1811 static void
1812 _c_size2str(PageSetupData *pda,DWORD size,LPSTR strout) {
1813     strcpy(strout,"<undef>");
1814     if (pda->dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS) {
1815         sprintf(strout,"%.2fmm",(size*1.0)/100.0);
1816         return;
1817     }
1818     if (pda->dlga->Flags & PSD_INTHOUSANDTHSOFINCHES) {
1819         sprintf(strout,"%.2fin",(size*1.0)/1000.0);
1820         return;
1821     }
1822     pda->dlga->Flags |= PSD_INHUNDREDTHSOFMILLIMETERS;
1823     sprintf(strout,"%.2fmm",(size*1.0)/100.0);
1824     return;
1825 }
1826
1827 static DWORD
1828 _c_str2size(PageSetupData *pda,LPCSTR strin) {
1829     float       val;
1830     char        rest[200];
1831
1832     rest[0]='\0';
1833     if (!sscanf(strin,"%f%s",&val,rest))
1834         return 0;
1835
1836     if (!strcmp(rest,"in") || !strcmp(rest,"inch")) {
1837         if (pda->dlga->Flags & PSD_INTHOUSANDTHSOFINCHES)
1838             return 1000*val;
1839         else
1840             return val*25.4*100;
1841     }
1842     if (!strcmp(rest,"cm")) { rest[0]='m'; val = val*10.0; }
1843     if (!strcmp(rest,"m")) { strcpy(rest,"mm"); val = val*1000.0; }
1844
1845     if (!strcmp(rest,"mm")) {
1846         if (pda->dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS)
1847             return 100*val;
1848         else
1849             return 1000.0*val/25.4;
1850     }
1851     if (rest[0]=='\0') {
1852         /* use application supplied default */
1853         if (pda->dlga->Flags & PSD_INHUNDREDTHSOFMILLIMETERS) {
1854             /* 100*mm */
1855             return 100.0*val;
1856         }
1857         if (pda->dlga->Flags & PSD_INTHOUSANDTHSOFINCHES) {
1858             /* 1000*inch */
1859             return 1000.0*val;
1860         }
1861     }
1862     ERR("Did not find a conversion for type '%s'!\n",rest);
1863     return 0;
1864 }
1865
1866
1867 /*
1868  * This is called on finish and will update the output fields of the
1869  * struct.
1870  */
1871 static BOOL
1872 PRINTDLG_PS_UpdateDlgStruct(HWND hDlg, PageSetupData *pda) {
1873     DEVNAMES    *dn;
1874     DEVMODEA    *dm;
1875     LPSTR       devname,portname;
1876     char        papername[64];
1877     char        buf[200];
1878     
1879     dn = GlobalLock(pda->pdlg.hDevNames);
1880     dm = GlobalLock(pda->pdlg.hDevMode);
1881     devname     = ((char*)dn)+dn->wDeviceOffset;
1882     portname    = ((char*)dn)+dn->wOutputOffset;
1883     PRINTDLG_SetUpPaperComboBox(hDlg,cmb2,devname,portname,dm);
1884     PRINTDLG_SetUpPaperComboBox(hDlg,cmb3,devname,portname,dm);
1885
1886     if (GetDlgItemTextA(hDlg,cmb2,papername,sizeof(papername))>0) {
1887         PRINTDLG_PaperSize(&(pda->pdlg),papername,&(pda->dlga->ptPaperSize));
1888         pda->dlga->ptPaperSize.x = _c_10mm2size(pda->dlga,pda->dlga->ptPaperSize.x);
1889         pda->dlga->ptPaperSize.y = _c_10mm2size(pda->dlga,pda->dlga->ptPaperSize.y);
1890     } else
1891         FIXME("could not get dialog text for papersize cmbbox?\n");
1892 #define GETVAL(id,val) if (GetDlgItemTextA(hDlg,id,buf,sizeof(buf))>0) { val = _c_str2size(pda,buf); } else { FIXME("could not get dlgitemtexta for %x\n",id); }
1893     GETVAL(edt4,pda->dlga->rtMargin.left);
1894     GETVAL(edt5,pda->dlga->rtMargin.top);
1895     GETVAL(edt6,pda->dlga->rtMargin.right);
1896     GETVAL(edt7,pda->dlga->rtMargin.bottom);
1897 #undef GETVAL
1898
1899     /* If we are in landscape, swap x and y of page size */
1900     if (IsDlgButtonChecked(hDlg, rad2)) {
1901         DWORD tmp;
1902         tmp = pda->dlga->ptPaperSize.x;
1903         pda->dlga->ptPaperSize.x = pda->dlga->ptPaperSize.y;
1904         pda->dlga->ptPaperSize.y = tmp;
1905     }
1906     GlobalUnlock(pda->pdlg.hDevNames);
1907     GlobalUnlock(pda->pdlg.hDevMode);
1908     return TRUE;
1909 }
1910
1911 /*
1912  * This is called after returning from PrintDlg().
1913  */
1914 static BOOL
1915 PRINTDLG_PS_ChangePrinter(HWND hDlg, PageSetupData *pda) {
1916     DEVNAMES    *dn;
1917     DEVMODEA    *dm;
1918     LPSTR       devname,portname;
1919     
1920     dn = GlobalLock(pda->pdlg.hDevNames);
1921     dm = GlobalLock(pda->pdlg.hDevMode);
1922     devname     = ((char*)dn)+dn->wDeviceOffset;
1923     portname    = ((char*)dn)+dn->wOutputOffset;
1924     PRINTDLG_SetUpPaperComboBox(hDlg,cmb2,devname,portname,dm);
1925     PRINTDLG_SetUpPaperComboBox(hDlg,cmb3,devname,portname,dm);
1926     GlobalUnlock(pda->pdlg.hDevNames);
1927     GlobalUnlock(pda->pdlg.hDevMode);
1928     return TRUE;
1929 }
1930
1931 static BOOL
1932 PRINTDLG_PS_WMCommand(
1933     HWND hDlg, WPARAM wParam, LPARAM lParam, PageSetupData *pda
1934 ) {
1935     switch (LOWORD(wParam))  {
1936     case IDOK:
1937         if (!PRINTDLG_PS_UpdateDlgStruct(hDlg, pda))
1938             return(FALSE);
1939         EndDialog(hDlg, TRUE);
1940         return TRUE ;
1941
1942     case IDCANCEL:
1943         EndDialog(hDlg, FALSE);
1944         return FALSE ;
1945
1946     case psh3: {
1947         pda->pdlg.Flags         = 0;
1948         pda->pdlg.hwndOwner     = hDlg;
1949         if (PrintDlgA(&(pda->pdlg)))
1950             PRINTDLG_PS_ChangePrinter(hDlg,pda);
1951         return TRUE;
1952     }
1953     }
1954     FIXME("loword (lparam) %d, wparam 0x%x, lparam %08lx, STUB mostly.\n",
1955             LOWORD(lParam),wParam,lParam
1956     );
1957     return FALSE;
1958 }
1959
1960
1961 static BOOL WINAPI
1962 PageDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
1963 {
1964     PageSetupData       *pda;
1965     BOOL                res = FALSE;
1966
1967     if (uMsg==WM_INITDIALOG) {
1968         res = TRUE;
1969         pda = (PageSetupData*)lParam;
1970         SetPropA(hDlg,"__WINE_PAGESETUPDLGDATA",lParam);
1971         if (pda->dlga->Flags & PSD_ENABLEPAGESETUPHOOK) {
1972             res = pda->dlga->lpfnPageSetupHook(hDlg,uMsg,wParam,lParam);
1973             if (!res) {
1974                 FIXME("Setup page hook failed?\n");
1975                 res = TRUE;
1976             }
1977         }
1978         if (pda->dlga->Flags & PSD_ENABLEPAGEPAINTHOOK) {
1979             FIXME("PagePaintHook not yet implemented!\n");
1980         }
1981         if (pda->dlga->Flags & PSD_DISABLEPRINTER)
1982             EnableWindow(GetDlgItem(hDlg, psh3), FALSE);    
1983         if (pda->dlga->Flags & PSD_DISABLEMARGINS) {
1984             EnableWindow(GetDlgItem(hDlg, edt4), FALSE);    
1985             EnableWindow(GetDlgItem(hDlg, edt5), FALSE);    
1986             EnableWindow(GetDlgItem(hDlg, edt6), FALSE);    
1987             EnableWindow(GetDlgItem(hDlg, edt7), FALSE);    
1988         }
1989         /* width larger as height -> landscape */
1990         if (pda->dlga->ptPaperSize.x > pda->dlga->ptPaperSize.y)
1991             CheckRadioButton(hDlg, rad1, rad2, rad2);
1992         else /* this is default if papersize is not set */
1993             CheckRadioButton(hDlg, rad1, rad2, rad1);
1994         if (pda->dlga->Flags & PSD_DISABLEORIENTATION) {
1995             EnableWindow(GetDlgItem(hDlg,rad1),FALSE);
1996             EnableWindow(GetDlgItem(hDlg,rad2),FALSE);
1997         }
1998         /* We fill them out enabled or not */
1999         if (pda->dlga->Flags & PSD_MARGINS) {
2000             char str[100];
2001             _c_size2str(pda,pda->dlga->rtMargin.left,str);
2002             SetDlgItemTextA(hDlg,edt4,str);
2003             _c_size2str(pda,pda->dlga->rtMargin.top,str);
2004             SetDlgItemTextA(hDlg,edt5,str);
2005             _c_size2str(pda,pda->dlga->rtMargin.right,str);
2006             SetDlgItemTextA(hDlg,edt6,str);
2007             _c_size2str(pda,pda->dlga->rtMargin.bottom,str);
2008             SetDlgItemTextA(hDlg,edt7,str);
2009         } else {
2010             /* default is 1 inch */
2011             DWORD size = _c_inch2size(pda->dlga,1000);
2012             char        str[20];
2013             _c_size2str(pda,size,str);
2014             SetDlgItemTextA(hDlg,edt4,str);
2015             SetDlgItemTextA(hDlg,edt5,str);
2016             SetDlgItemTextA(hDlg,edt6,str);
2017             SetDlgItemTextA(hDlg,edt7,str);
2018         }
2019         PRINTDLG_PS_ChangePrinter(hDlg,pda);
2020         if (pda->dlga->Flags & PSD_DISABLEPAPER) {
2021             EnableWindow(GetDlgItem(hDlg,cmb2),FALSE);
2022             EnableWindow(GetDlgItem(hDlg,cmb3),FALSE);
2023         }
2024         return TRUE;
2025     } else {
2026         pda = (PageSetupData*)GetPropA(hDlg,"__WINE_PAGESETUPDLGDATA");
2027         if (!pda) {
2028             WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
2029             return FALSE;
2030         }
2031         if (pda->dlga->Flags & PSD_ENABLEPAGESETUPHOOK) {
2032             res = pda->dlga->lpfnPageSetupHook(hDlg,uMsg,wParam,lParam);
2033             if (res) return res;
2034         }
2035     }
2036     switch (uMsg) {
2037     case WM_COMMAND:
2038         return PRINTDLG_PS_WMCommand(hDlg, wParam, lParam, pda);
2039     }
2040     return FALSE;
2041 }
2042
2043 /***********************************************************************
2044  *            PageSetupDlgA  (COMDLG32.@)
2045  */
2046 BOOL WINAPI PageSetupDlgA(LPPAGESETUPDLGA setupdlg) {
2047     HGLOBAL             hDlgTmpl;
2048     LPVOID              ptr;
2049     BOOL                bRet;
2050     PageSetupData       *pda;
2051     PRINTDLGA           pdlg;
2052
2053     if(TRACE_ON(commdlg)) {
2054         char flagstr[1000] = "";
2055         struct pd_flags *pflag = psd_flags;
2056         for( ; pflag->name; pflag++) {
2057             if(setupdlg->Flags & pflag->flag) {
2058                 strcat(flagstr, pflag->name);
2059                 strcat(flagstr, "|");
2060             }
2061         }
2062         TRACE("(%p): hwndOwner = %08x, hDevMode = %08x, hDevNames = %08x\n"
2063               "hinst %08x, flags %08lx (%s)\n",
2064               setupdlg, setupdlg->hwndOwner, setupdlg->hDevMode,
2065               setupdlg->hDevNames, 
2066               setupdlg->hInstance, setupdlg->Flags, flagstr);
2067     }
2068
2069     /* First get default printer data, we need it right after that. */
2070     memset(&pdlg,0,sizeof(pdlg));
2071     pdlg.lStructSize    = sizeof(pdlg);
2072     pdlg.Flags          = PD_RETURNDEFAULT;
2073     bRet = PrintDlgA(&pdlg);
2074     if (!bRet) return FALSE;
2075
2076     /* short cut exit, just return default values */
2077     if (setupdlg->Flags & PSD_RETURNDEFAULT) {
2078         setupdlg->hDevMode      = pdlg.hDevMode;
2079         setupdlg->hDevNames     = pdlg.hDevNames;
2080         /* FIXME: Just return "A4" for now. */
2081         PRINTDLG_PaperSize(&pdlg,"A4",&setupdlg->ptPaperSize);
2082         setupdlg->ptPaperSize.x=_c_10mm2size(setupdlg,setupdlg->ptPaperSize.x);
2083         setupdlg->ptPaperSize.y=_c_10mm2size(setupdlg,setupdlg->ptPaperSize.y);
2084         return TRUE;
2085     }
2086     hDlgTmpl = PRINTDLG_GetPGSTemplate(setupdlg);
2087     if (!hDlgTmpl) {
2088         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2089         return FALSE;
2090     }
2091     ptr = LockResource( hDlgTmpl );
2092     if (!ptr) {
2093         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2094         return FALSE;
2095     }
2096     pda = HeapAlloc(GetProcessHeap(),0,sizeof(*pda));
2097     pda->dlga = setupdlg;
2098     memcpy(&pda->pdlg,&pdlg,sizeof(pdlg));
2099
2100     bRet = (0<DialogBoxIndirectParamA(
2101                 setupdlg->hInstance,
2102                 ptr,
2103                 setupdlg->hwndOwner,
2104                 PageDlgProcA,
2105                 (LPARAM)pda)
2106     );
2107     return bRet;
2108 }
2109 /***********************************************************************
2110  *            PageSetupDlgW  (COMDLG32.@)
2111  */
2112 BOOL WINAPI PageSetupDlgW(LPPAGESETUPDLGW setupdlg) {
2113         FIXME("(%p), stub!\n",setupdlg);
2114         return FALSE;
2115 }
2116
2117 /**********************************************************************
2118  *
2119  *      16 bit commdlg
2120  */
2121
2122 /***********************************************************************
2123  *           PrintDlgProc   (COMMDLG.21)
2124  */
2125 LRESULT WINAPI PrintDlgProc16(HWND16 hDlg, UINT16 uMsg, WPARAM16 wParam,
2126                             LPARAM lParam)
2127 {
2128     PRINT_PTRA* PrintStructures;
2129     LRESULT res=FALSE;
2130
2131     if (uMsg!=WM_INITDIALOG) {
2132         PrintStructures = (PRINT_PTRA*) GetWindowLongA(hDlg, DWL_USER);   
2133         if (!PrintStructures)
2134             return FALSE;
2135     } else {
2136         PrintStructures = (PRINT_PTRA*) lParam;
2137         SetWindowLongA(hDlg, DWL_USER, lParam); 
2138         res = PRINTDLG_WMInitDialog16(hDlg, wParam, PrintStructures);
2139
2140         if(PrintStructures->dlg.lpPrintDlg16->Flags & PD_ENABLEPRINTHOOK) {
2141             res = CallWindowProc16(
2142                 (WNDPROC16)PrintStructures->dlg.lpPrintDlg16->lpfnPrintHook,
2143                 hDlg, uMsg, wParam, (LPARAM)PrintStructures->dlg.lpPrintDlg16
2144             );
2145         }
2146         return res;
2147     }
2148   
2149     if(PrintStructures->dlg.lpPrintDlg16->Flags & PD_ENABLEPRINTHOOK) {
2150         res = CallWindowProc16(
2151                 (WNDPROC16)PrintStructures->dlg.lpPrintDlg16->lpfnPrintHook,
2152                 hDlg,uMsg, wParam, lParam
2153         );
2154         if(LOWORD(res)) return res;
2155     }
2156
2157     switch (uMsg) {
2158     case WM_COMMAND: {
2159          /* We need to map those for the 32bit window procedure, compare
2160           * with 32Ato16 mapper in winproc.c
2161           */
2162         return PRINTDLG_WMCommand(
2163                 hDlg,
2164                 MAKEWPARAM(wParam,HIWORD(lParam)),
2165                 LOWORD(lParam),
2166                 PrintStructures
2167         );
2168     }
2169     case WM_DESTROY:
2170         DestroyIcon(PrintStructures->hCollateIcon);
2171         DestroyIcon(PrintStructures->hNoCollateIcon);
2172     /* FIXME: don't forget to delete the paper orientation icons here! */
2173
2174         return FALSE;
2175     }    
2176     return res;
2177 }
2178
2179
2180 /***********************************************************************
2181  *           PrintSetupDlgProc   (COMMDLG.22)
2182  */
2183 LRESULT WINAPI PrintSetupDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
2184                                    LPARAM lParam)
2185 {
2186   switch (wMsg)
2187     {
2188     case WM_INITDIALOG:
2189       TRACE("WM_INITDIALOG lParam=%08lX\n", lParam);
2190       ShowWindow(hWnd, SW_SHOWNORMAL);
2191       return (TRUE);
2192     case WM_COMMAND:
2193       switch (wParam) {
2194       case IDOK:
2195         EndDialog(hWnd, TRUE);
2196         return(TRUE);
2197       case IDCANCEL:
2198         EndDialog(hWnd, FALSE);
2199         return(TRUE);
2200       }
2201       return(FALSE);
2202     }
2203   return FALSE;
2204 }
2205
2206
2207 /***********************************************************************
2208  *      PrintDlgExA (COMDLG32.@)
2209  */
2210 HRESULT WINAPI PrintDlgExA(LPVOID lpPrintDlgExA) /* [???] FIXME: LPPRINTDLGEXA */
2211 {
2212         FIXME("stub\n");
2213         return E_NOTIMPL;
2214 }
2215 /***********************************************************************
2216  *      PrintDlgExW (COMDLG32.@)
2217  */
2218 HRESULT WINAPI PrintDlgExW(LPVOID lpPrintDlgExW) /* [???] FIXME: LPPRINTDLGEXW */
2219 {
2220         FIXME("stub\n");
2221         return E_NOTIMPL;
2222 }