Added CUPS printing support.
[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 #include <ctype.h>
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include "windef.h"
14 #include "winbase.h"
15 #include "wingdi.h"
16 #include "wine/wingdi16.h"
17 #include "winuser.h"
18 #include "wine/winuser16.h"
19 #include "commdlg.h"
20 #include "dlgs.h"
21 #include "debugtools.h"
22 #include "cderr.h"
23 #include "winspool.h"
24 #include "winerror.h"
25
26 DEFAULT_DEBUG_CHANNEL(commdlg);
27
28 #include "cdlg.h"
29
30 /* This PRINTDLGA internal structure stores
31  * pointers to several throughout useful structures.
32  * 
33  */
34 typedef struct  
35 {
36   LPDEVMODEA        lpDevMode;
37   struct {
38       LPPRINTDLGA       lpPrintDlg;
39       LPPRINTDLG16      lpPrintDlg16;
40   } dlg;
41   LPPRINTER_INFO_2A lpPrinterInfo;
42   UINT              HelpMessageID;
43   HICON             hCollateIcon;    /* PrintDlg only */
44   HICON             hNoCollateIcon;  /* PrintDlg only */
45   HICON             hPortraitIcon;   /* PrintSetupDlg only */
46   HICON             hLandscapeIcon;  /* PrintSetupDlg only */
47   HWND              hwndUpDown;
48 } PRINT_PTRA;
49
50 /* Debugging info */
51 static struct pd_flags {
52   DWORD flag;
53   LPSTR name;
54 } pd_flags[] = {
55   {PD_SELECTION, "PD_SELECTION "},
56   {PD_PAGENUMS, "PD_PAGENUMS "},
57   {PD_NOSELECTION, "PD_NOSELECTION "},
58   {PD_NOPAGENUMS, "PD_NOPAGENUMS "},
59   {PD_COLLATE, "PD_COLLATE "},
60   {PD_PRINTTOFILE, "PD_PRINTTOFILE "},
61   {PD_PRINTSETUP, "PD_PRINTSETUP "},
62   {PD_NOWARNING, "PD_NOWARNING "},
63   {PD_RETURNDC, "PD_RETURNDC "},
64   {PD_RETURNIC, "PD_RETURNIC "},
65   {PD_RETURNDEFAULT, "PD_RETURNDEFAULT "},
66   {PD_SHOWHELP, "PD_SHOWHELP "},
67   {PD_ENABLEPRINTHOOK, "PD_ENABLEPRINTHOOK "},
68   {PD_ENABLESETUPHOOK, "PD_ENABLESETUPHOOK "},
69   {PD_ENABLEPRINTTEMPLATE, "PD_ENABLEPRINTTEMPLATE "},
70   {PD_ENABLESETUPTEMPLATE, "PD_ENABLESETUPTEMPLATE "},
71   {PD_ENABLEPRINTTEMPLATEHANDLE, "PD_ENABLEPRINTTEMPLATEHANDLE "},
72   {PD_ENABLESETUPTEMPLATEHANDLE, "PD_ENABLESETUPTEMPLATEHANDLE "},
73   {PD_USEDEVMODECOPIES, "PD_USEDEVMODECOPIES[ANDCOLLATE] "},
74   {PD_DISABLEPRINTTOFILE, "PD_DISABLEPRINTTOFILE "},
75   {PD_HIDEPRINTTOFILE, "PD_HIDEPRINTTOFILE "},
76   {PD_NONETWORKBUTTON, "PD_NONETWORKBUTTON "},
77   {-1, NULL}
78 };
79
80 /* Yes these constants are the same, but we're just copying win98 */
81 #define UPDOWN_ID 0x270f
82 #define MAX_COPIES 9999
83
84 /***********************************************************************
85  *    PRINTDLG_GetDefaultPrinterName
86  *
87  * Returns the default printer name in buf.
88  * Even under WinNT/2000 default printer is retrieved via GetProfileString - 
89  * these entries are mapped somewhere in the registry rather than win.ini.
90  *
91  * Returns TRUE on success else FALSE
92  */
93 static BOOL PRINTDLG_GetDefaultPrinterName(LPSTR buf, DWORD len)
94 {
95     char *ptr;
96
97     if(!GetProfileStringA("windows", "device", "", buf, len)) {
98         TRACE("No profile entry for default printer found.\n");
99         return FALSE;
100     }
101     if((ptr = strchr(buf, ',')) == NULL) {
102         FIXME("bad format for default printer (%s)!\n",buf);
103         return FALSE;
104     }
105     *ptr = '\0';
106     return TRUE;
107 }
108
109 /***********************************************************************
110  *    PRINTDLG_OpenDefaultPrinter
111  *
112  * Returns a winspool printer handle to the default printer in *hprn
113  * Caller must call ClosePrinter on the handle
114  *
115  * Returns TRUE on success else FALSE
116  */
117 static BOOL PRINTDLG_OpenDefaultPrinter(HANDLE *hprn)
118 {
119     char buf[260];
120     BOOL res;
121     if(!PRINTDLG_GetDefaultPrinterName(buf, sizeof(buf)))
122         return FALSE;
123     res = OpenPrinterA(buf, hprn, NULL);
124     if (!res)
125         FIXME("Could not open printer %s?!\n",buf);
126     return res;
127 }
128
129 /***********************************************************************
130  *    PRINTDLG_SetUpPrinterListCombo
131  *
132  * Initializes printer list combox.
133  * hDlg:  HWND of dialog
134  * id:    Control id of combo
135  * name:  Name of printer to select
136  *
137  * Initializes combo with list of available printers.  Selects printer 'name'
138  * If name is NULL or does not exist select the default printer.
139  *
140  * Returns number of printers added to list.
141  */
142 static INT PRINTDLG_SetUpPrinterListCombo(HWND hDlg, UINT id, LPCSTR name)
143 {
144     DWORD needed, num;
145     INT i;
146     LPPRINTER_INFO_2A pi;
147     EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
148     pi = HeapAlloc(GetProcessHeap(), 0, needed);
149     EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pi, needed, &needed, 
150                   &num);
151
152     for(i = 0; i < num; i++) {
153         SendDlgItemMessageA(hDlg, id, CB_ADDSTRING, 0,
154                             (LPARAM)pi[i].pPrinterName );
155     }
156     HeapFree(GetProcessHeap(), 0, pi);
157     if(!name ||
158        (i = SendDlgItemMessageA(hDlg, id, CB_FINDSTRINGEXACT, -1,
159                                 (LPARAM)name)) == CB_ERR) {
160
161         char buf[260];
162         FIXME("Can't find '%s' in printer list so trying to find default\n",
163               name);
164         if(!PRINTDLG_GetDefaultPrinterName(buf, sizeof(buf)))
165             return num;
166         i = SendDlgItemMessageA(hDlg, id, CB_FINDSTRINGEXACT, -1, (LPARAM)buf);
167         if(i == CB_ERR)
168             FIXME("Can't find default printer in printer list\n");
169     }
170     SendDlgItemMessageA(hDlg, id, CB_SETCURSEL, i, 0);
171     return num;
172 }
173
174 /***********************************************************************
175  *             PRINTDLG_CreateDevNames          [internal]
176  *
177  *
178  *   creates a DevNames structure.
179  *
180  *  (NB. when we handle unicode the offsets will be in wchars).
181  */
182 static BOOL PRINTDLG_CreateDevNames(HGLOBAL *hmem, char* DeviceDriverName, 
183                                     char* DeviceName, char* OutputPort)
184 {
185     long size;
186     char*   pDevNamesSpace;
187     char*   pTempPtr;
188     LPDEVNAMES lpDevNames;
189     char buf[260];
190
191     size = strlen(DeviceDriverName) + 1
192             + strlen(DeviceName) + 1
193             + strlen(OutputPort) + 1
194             + sizeof(DEVNAMES);
195             
196     if(*hmem)
197         *hmem = GlobalReAlloc(*hmem, size, GMEM_MOVEABLE);
198     else
199         *hmem = GlobalAlloc(GMEM_MOVEABLE, size);
200     if (*hmem == 0)
201         return FALSE;
202
203     pDevNamesSpace = GlobalLock(*hmem);
204     lpDevNames = (LPDEVNAMES) pDevNamesSpace;
205
206     pTempPtr = pDevNamesSpace + sizeof(DEVNAMES);
207     strcpy(pTempPtr, DeviceDriverName);
208     lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
209
210     pTempPtr += strlen(DeviceDriverName) + 1;
211     strcpy(pTempPtr, DeviceName);
212     lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
213         
214     pTempPtr += strlen(DeviceName) + 1;
215     strcpy(pTempPtr, OutputPort);
216     lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
217
218     PRINTDLG_GetDefaultPrinterName(buf, sizeof(buf));
219     lpDevNames->wDefault = (strcmp(buf, DeviceName) == 0) ? 1 : 0;
220     GlobalUnlock(*hmem);
221     return TRUE;
222 }
223
224 static BOOL PRINTDLG_CreateDevNames16(HGLOBAL16 *hmem, char* DeviceDriverName, 
225                                       char* DeviceName, char* OutputPort)
226 {
227     long size;
228     char*   pDevNamesSpace;
229     char*   pTempPtr;
230     LPDEVNAMES lpDevNames;
231     char buf[260];
232
233     size = strlen(DeviceDriverName) + 1
234             + strlen(DeviceName) + 1
235             + strlen(OutputPort) + 1
236             + sizeof(DEVNAMES);
237             
238     if(*hmem)
239         *hmem = GlobalReAlloc16(*hmem, size, GMEM_MOVEABLE);
240     else
241         *hmem = GlobalAlloc16(GMEM_MOVEABLE, size);
242     if (*hmem == 0)
243         return FALSE;
244
245     pDevNamesSpace = GlobalLock16(*hmem);
246     lpDevNames = (LPDEVNAMES) pDevNamesSpace;
247
248     pTempPtr = pDevNamesSpace + sizeof(DEVNAMES);
249     strcpy(pTempPtr, DeviceDriverName);
250     lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
251
252     pTempPtr += strlen(DeviceDriverName) + 1;
253     strcpy(pTempPtr, DeviceName);
254     lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
255         
256     pTempPtr += strlen(DeviceName) + 1;
257     strcpy(pTempPtr, OutputPort);
258     lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
259
260     PRINTDLG_GetDefaultPrinterName(buf, sizeof(buf));
261     lpDevNames->wDefault = (strcmp(buf, DeviceName) == 0) ? 1 : 0;
262     GlobalUnlock16(*hmem);
263     return TRUE;
264 }
265
266
267 /***********************************************************************
268  *             PRINTDLG_UpdatePrintDlg          [internal]
269  *
270  *
271  *   updates the PrintDlg structure for returnvalues.
272  *      
273  * RETURNS
274  *   FALSE if user is not allowed to close (i.e. wrong nTo or nFrom values)
275  *   TRUE  if succesful.
276  */
277 static BOOL PRINTDLG_UpdatePrintDlg(HWND hDlg, 
278                                     PRINT_PTRA* PrintStructures)
279 {
280     LPPRINTDLGA       lppd = PrintStructures->dlg.lpPrintDlg;
281     PDEVMODEA         lpdm = PrintStructures->lpDevMode;
282     LPPRINTER_INFO_2A pi = PrintStructures->lpPrinterInfo;
283
284
285     if(!lpdm) {
286         FIXME("No lpdm ptr?\n");
287         return FALSE;
288     }
289
290
291     if(!(lppd->Flags & PD_PRINTSETUP)) {
292         /* check whether nFromPage and nToPage are within range defined by
293          * nMinPage and nMaxPage
294          */
295         if (IsDlgButtonChecked(hDlg, rad3) == BST_CHECKED) { /* Pages */
296             WORD nToPage;
297             WORD nFromPage;
298             nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
299             nToPage   = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
300             if (nFromPage < lppd->nMinPage || nFromPage > lppd->nMaxPage ||
301                 nToPage < lppd->nMinPage || nToPage > lppd->nMaxPage) {
302                 char resourcestr[256];
303                 char resultstr[256];
304                 LoadStringA(COMDLG32_hInstance, PD32_INVALID_PAGE_RANGE, 
305                             resourcestr, 255);
306                 sprintf(resultstr,resourcestr, lppd->nMinPage, lppd->nMaxPage);
307                 LoadStringA(COMDLG32_hInstance, PD32_PRINT_TITLE, 
308                             resourcestr, 255);
309                 MessageBoxA(hDlg, resultstr, resourcestr,
310                             MB_OK | MB_ICONWARNING);
311                 return FALSE;
312             }
313             lppd->nFromPage = nFromPage;
314             lppd->nToPage   = nToPage;
315         }
316
317         if (IsDlgButtonChecked(hDlg, chx1) == BST_CHECKED) {/* Print to file */
318             lppd->Flags |= PD_PRINTTOFILE;
319             pi->pPortName = "FILE:";
320         }
321
322         if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED) { /* Collate */
323             FIXME("Collate lppd not yet implemented as output\n");
324         }
325
326         /* set PD_Collate and nCopies */
327         if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
328           /*  The application doesn't support multiple copies or collate...
329            */
330             lppd->Flags &= ~PD_COLLATE;
331             lppd->nCopies = 1;
332           /* if the printer driver supports it... store info there
333            * otherwise no collate & multiple copies !
334            */
335             if (lpdm->dmFields & DM_COLLATE)
336                 lpdm->dmCollate = 
337                   (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED);
338             if (lpdm->dmFields & DM_COPIES)
339                 lpdm->dmCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
340         } else {
341             if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
342                 lppd->Flags |= PD_COLLATE;
343             else
344                lppd->Flags &= ~PD_COLLATE;
345             lppd->nCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
346         }
347     }
348     return TRUE;
349 }
350
351
352 /************************************************************************
353  * PRINTDLG_SetUpPaperComboBox
354  *
355  * Initialize either the papersize or inputslot combos of the Printer Setup
356  * dialog.  We store the associated word (eg DMPAPER_A4) as the item data.
357  * We also try to re-select the old selection.
358  */
359 static BOOL PRINTDLG_SetUpPaperComboBox(HWND hDlg,
360                                         int   nIDComboBox,
361                                         char* PrinterName, 
362                                         char* PortName,
363                                         LPDEVMODEA dm)
364 {
365     int     i;
366     DWORD   NrOfEntries;
367     char*   Names;
368     WORD*   Words;
369     DWORD   Sel;
370     WORD    oldWord = 0;
371     int     NamesSize;
372     int     fwCapability_Names;
373     int     fwCapability_Words;
374     
375     TRACE(" Printer: %s, ComboID: %d\n",PrinterName,nIDComboBox);
376     
377     /* query the dialog box for the current selected value */
378     Sel = SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETCURSEL, 0, 0);
379     if(Sel != CB_ERR) {
380         /* we enter here only if a different printer is selected after
381          * the Print Setup dialog is opened. The current settings are
382          * stored into the newly selected printer.
383          */
384         oldWord = SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA,
385                                       Sel, 0);
386         if (dm) {
387             if (nIDComboBox == cmb2)
388                 dm->u1.s1.dmPaperSize = oldWord;
389             else
390                 dm->dmDefaultSource = oldWord;
391         }
392     }
393     else {
394         /* we enter here only when the Print setup dialog is initially
395          * opened. In this case the settings are restored from when
396          * the dialog was last closed.
397          */
398         if (dm) {
399             if (nIDComboBox == cmb2)
400                 oldWord = dm->u1.s1.dmPaperSize;
401             else
402                 oldWord = dm->dmDefaultSource;
403         }
404     }
405
406     if (nIDComboBox == cmb2) {
407          NamesSize          = 64;
408          fwCapability_Names = DC_PAPERNAMES;
409          fwCapability_Words = DC_PAPERS;
410     } else {
411          nIDComboBox        = cmb3;
412          NamesSize          = 24;
413          fwCapability_Names = DC_BINNAMES;
414          fwCapability_Words = DC_BINS;
415     }
416     
417     /* for some printer drivers, DeviceCapabilities calls a VXD to obtain the 
418      * paper settings. As Wine doesn't allow VXDs, this results in a crash.
419      */
420     WARN(" if your printer driver uses VXDs, expect a crash now!\n");
421     NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
422                                       fwCapability_Names, NULL, dm);
423     if (NrOfEntries == 0)
424          WARN("no Name Entries found!\n");
425
426     if(DeviceCapabilitiesA(PrinterName, PortName, fwCapability_Words, NULL, dm)
427        != NrOfEntries) {
428         ERR("Number of caps is different\n");
429         NrOfEntries = 0;
430     }
431
432     Names = HeapAlloc(GetProcessHeap(),0, NrOfEntries*NamesSize);
433     Words = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WORD));
434     NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
435                                       fwCapability_Names, Names, dm);
436     NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
437                                       fwCapability_Words, (LPSTR)Words, dm);
438
439     /* reset any current content in the combobox */
440     SendDlgItemMessageA(hDlg, nIDComboBox, CB_RESETCONTENT, 0, 0);
441     
442     /* store new content */
443     for (i = 0; i < NrOfEntries; i++) {
444         DWORD pos = SendDlgItemMessageA(hDlg, nIDComboBox, CB_ADDSTRING, 0,
445                                         (LPARAM)(&Names[i*NamesSize]) );
446         SendDlgItemMessageA(hDlg, nIDComboBox, CB_SETITEMDATA, pos, 
447                             Words[i]);
448     }
449
450     /* Look for old selection - can't do this is previous loop since
451        item order will change as more items are added */
452     Sel = 0;
453     for (i = 0; i < NrOfEntries; i++) {
454         if(SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) ==
455            oldWord) {
456             Sel = i;
457             break;
458         }
459     }
460     SendDlgItemMessageA(hDlg, nIDComboBox, CB_SETCURSEL, Sel, 0);
461
462     HeapFree(GetProcessHeap(),0,Words);
463     HeapFree(GetProcessHeap(),0,Names);
464     return TRUE;
465 }
466
467 /***********************************************************************
468  *               PRINTDLG_UpdatePrinterInfoTexts               [internal]
469  */
470 static void PRINTDLG_UpdatePrinterInfoTexts(HWND hDlg, LPPRINTER_INFO_2A pi)
471 {
472     char   StatusMsg[256];
473     char   ResourceString[256];
474     int    i;
475
476     /* Status Message */
477     StatusMsg[0]='\0';
478
479     /* add all status messages */
480     for (i = 0; i < 25; i++) {
481         if (pi->Status & (1<<i)) {
482             LoadStringA(COMDLG32_hInstance, PD32_PRINTER_STATUS_PAUSED+i, 
483                         ResourceString, 255);
484             strcat(StatusMsg,ResourceString);
485         }
486     }
487     /* append "ready" */
488     /* FIXME: status==ready must only be appended if really so. 
489               but how to detect? */
490     LoadStringA(COMDLG32_hInstance, PD32_PRINTER_STATUS_READY, 
491                 ResourceString, 255);
492     strcat(StatusMsg,ResourceString);
493   
494     SendDlgItemMessageA(hDlg, stc12, WM_SETTEXT, 0, (LPARAM)StatusMsg);
495
496     /* set all other printer info texts */
497     SendDlgItemMessageA(hDlg, stc11, WM_SETTEXT, 0, (LPARAM)pi->pDriverName);
498     if (pi->pLocation != NULL && pi->pLocation[0] != '\0')
499         SendDlgItemMessageA(hDlg, stc14, WM_SETTEXT, 0,(LPARAM)pi->pLocation);
500     else
501         SendDlgItemMessageA(hDlg, stc14, WM_SETTEXT, 0,(LPARAM)pi->pPortName);
502     SendDlgItemMessageA(hDlg, stc13, WM_SETTEXT, 0, (LPARAM)(pi->pComment ?
503                         pi->pComment : ""));
504     return;
505 }
506
507
508 /*******************************************************************
509  *
510  *                 PRINTDLG_ChangePrinter
511  *
512  */
513 static BOOL PRINTDLG_ChangePrinter(HWND hDlg, char *name,
514                                    PRINT_PTRA *PrintStructures)
515 {
516     LPPRINTDLGA lppd = PrintStructures->dlg.lpPrintDlg;
517     LPDEVMODEA lpdm = NULL;
518     LONG dmSize;
519     DWORD needed;
520     HANDLE hprn;
521
522     if(PrintStructures->lpPrinterInfo)
523         HeapFree(GetProcessHeap(),0, PrintStructures->lpPrinterInfo);
524     if(!OpenPrinterA(name, &hprn, NULL)) {
525         ERR("Can't open printer %s\n", name);
526         return FALSE;
527     }
528     GetPrinterA(hprn, 2, NULL, 0, &needed);
529     PrintStructures->lpPrinterInfo = HeapAlloc(GetProcessHeap(),0,needed);
530     GetPrinterA(hprn, 2, (LPBYTE)PrintStructures->lpPrinterInfo, needed,
531                 &needed);
532     ClosePrinter(hprn);
533
534     PRINTDLG_UpdatePrinterInfoTexts(hDlg, PrintStructures->lpPrinterInfo);
535
536     if(PrintStructures->lpDevMode) {
537         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
538         PrintStructures->lpDevMode = NULL;
539     }
540
541     dmSize = DocumentPropertiesA(0, 0, name, NULL, NULL, 0);
542     if(dmSize == -1) {
543         ERR("DocumentProperties fails on %s\n", debugstr_a(name));
544         return FALSE;
545     }
546     PrintStructures->lpDevMode = HeapAlloc(GetProcessHeap(), 0, dmSize);
547     dmSize = DocumentPropertiesA(0, 0, name, PrintStructures->lpDevMode, NULL,
548                                  DM_OUT_BUFFER);
549     if(lppd->hDevMode && (lpdm = GlobalLock(lppd->hDevMode)) &&
550                           !strcmp(lpdm->dmDeviceName,
551                                   PrintStructures->lpDevMode->dmDeviceName)) {
552       /* Supplied devicemode matches current printer so try to use it */
553         DocumentPropertiesA(0, 0, name, PrintStructures->lpDevMode, lpdm,
554                             DM_OUT_BUFFER | DM_IN_BUFFER);
555     }
556     if(lpdm)
557         GlobalUnlock(lppd->hDevMode);
558
559     lpdm = PrintStructures->lpDevMode;  /* use this as a shortcut */
560
561     if(!(lppd->Flags & PD_PRINTSETUP)) {
562       /* Print range (All/Range/Selection) */
563         SetDlgItemInt(hDlg, edt1, lppd->nFromPage, FALSE);
564         SetDlgItemInt(hDlg, edt2, lppd->nToPage, FALSE);
565         CheckRadioButton(hDlg, rad1, rad3, rad1);               /* default */
566         if (lppd->Flags & PD_NOSELECTION)
567             EnableWindow(GetDlgItem(hDlg, rad2), FALSE);
568         else
569             if (lppd->Flags & PD_SELECTION)
570                 CheckRadioButton(hDlg, rad1, rad3, rad2);
571         if (lppd->Flags & PD_NOPAGENUMS) {
572             EnableWindow(GetDlgItem(hDlg, rad3), FALSE);
573             EnableWindow(GetDlgItem(hDlg, stc2),FALSE);
574             EnableWindow(GetDlgItem(hDlg, edt1), FALSE);
575             EnableWindow(GetDlgItem(hDlg, stc3),FALSE);
576             EnableWindow(GetDlgItem(hDlg, edt2), FALSE);
577         } else {
578             if (lppd->Flags & PD_PAGENUMS)
579                 CheckRadioButton(hDlg, rad1, rad3, rad3);
580         }
581         /* "All xxx pages"... */
582         {
583             char        resourcestr[64];
584             char        result[64];
585             LoadStringA(COMDLG32_hInstance, PD32_PRINT_ALL_X_PAGES, 
586                         resourcestr, 49);
587             sprintf(result,resourcestr,lppd->nMaxPage - lppd->nMinPage + 1);
588             SendDlgItemMessageA(hDlg, rad1, WM_SETTEXT, 0, (LPARAM) result);
589         }
590         
591         /* Collate pages 
592          *
593          * FIXME: The ico3 is not displayed for some reason. I don't know why.
594          */
595         if (lppd->Flags & PD_COLLATE) {
596             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON, 
597                                 (LPARAM)PrintStructures->hCollateIcon);
598             CheckDlgButton(hDlg, chx2, 1);
599         } else {
600             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON, 
601                                 (LPARAM)PrintStructures->hNoCollateIcon);
602             CheckDlgButton(hDlg, chx2, 0);
603         }
604
605         if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
606           /* if printer doesn't support it: no Collate */
607             if (!(lpdm->dmFields & DM_COLLATE)) {
608                 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);    
609                 EnableWindow(GetDlgItem(hDlg, ico3), FALSE);    
610             }
611         }
612
613         /* nCopies */
614         {
615           INT copies;
616           if (lppd->hDevMode == 0)
617               copies = lppd->nCopies;
618           else
619               copies = lpdm->dmCopies;
620           if(copies == 0) copies = 1;
621           else if(copies < 0) copies = MAX_COPIES;
622           SetDlgItemInt(hDlg, edt3, copies, FALSE);
623         }
624
625         if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
626           /* if printer doesn't support it: no nCopies */
627             if (!(lpdm->dmFields & DM_COPIES)) {
628                 EnableWindow(GetDlgItem(hDlg, edt3), FALSE);    
629                 EnableWindow(GetDlgItem(hDlg, stc5), FALSE);    
630             }
631         }
632
633         /* print to file */
634         CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0);
635         if (lppd->Flags & PD_DISABLEPRINTTOFILE)
636             EnableWindow(GetDlgItem(hDlg, chx1), FALSE);    
637         if (lppd->Flags & PD_HIDEPRINTTOFILE)
638             ShowWindow(GetDlgItem(hDlg, chx1), SW_HIDE);
639
640     } else { /* PD_PRINTSETUP */
641       BOOL bPortrait = (lpdm->u1.s1.dmOrientation == DMORIENT_PORTRAIT);
642
643       PRINTDLG_SetUpPaperComboBox(hDlg, cmb2,
644                                   PrintStructures->lpPrinterInfo->pPrinterName,
645                                   PrintStructures->lpPrinterInfo->pPortName,
646                                   lpdm);
647       PRINTDLG_SetUpPaperComboBox(hDlg, cmb3,
648                                   PrintStructures->lpPrinterInfo->pPrinterName,
649                                   PrintStructures->lpPrinterInfo->pPortName,
650                                   lpdm);
651       CheckRadioButton(hDlg, rad1, rad2, bPortrait ? rad1: rad2);
652       SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, (WPARAM) IMAGE_ICON,
653                           (LPARAM)(bPortrait ? PrintStructures->hPortraitIcon :
654                                    PrintStructures->hLandscapeIcon));
655       
656     }
657
658     /* help button */
659     if ((lppd->Flags & PD_SHOWHELP)==0) {
660         /* hide if PD_SHOWHELP not specified */
661         ShowWindow(GetDlgItem(hDlg, pshHelp), SW_HIDE);         
662     }
663     return TRUE;
664 }
665
666 /***********************************************************************
667  *           PRINTDLG_WMInitDialog                      [internal]
668  */
669 static LRESULT PRINTDLG_WMInitDialog(HWND hDlg, WPARAM wParam,
670                                      PRINT_PTRA* PrintStructures)
671 {
672     LPPRINTDLGA lppd = PrintStructures->dlg.lpPrintDlg;
673     DEVNAMES *pdn;
674     DEVMODEA *pdm;
675     char *name = NULL;
676     UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
677
678     /* load Collate ICONs */
679     /* We load these with LoadImage becasue they are not a standard
680        size and we don't want them rescaled */
681     PrintStructures->hCollateIcon =
682       LoadImageA(COMDLG32_hInstance, "PD32_COLLATE", IMAGE_ICON, 0, 0, 0);
683     PrintStructures->hNoCollateIcon = 
684       LoadImageA(COMDLG32_hInstance, "PD32_NOCOLLATE", IMAGE_ICON, 0, 0, 0);
685
686     /* These can be done with LoadIcon */
687     PrintStructures->hPortraitIcon =
688       LoadIconA(COMDLG32_hInstance, "PD32_PORTRAIT");
689     PrintStructures->hLandscapeIcon =
690       LoadIconA(COMDLG32_hInstance, "PD32_LANDSCAPE");
691
692     if(PrintStructures->hCollateIcon == 0 ||
693        PrintStructures->hNoCollateIcon == 0 ||
694        PrintStructures->hPortraitIcon == 0 ||
695        PrintStructures->hLandscapeIcon == 0) {
696         ERR("no icon in resourcefile\n");
697         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
698         EndDialog(hDlg, FALSE);
699     }
700
701     /*
702      * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
703      * must be registered and the Help button must be shown.
704      */
705     if (lppd->Flags & PD_SHOWHELP) {
706         if((PrintStructures->HelpMessageID = 
707             RegisterWindowMessageA(HELPMSGSTRINGA)) == 0) {
708             COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
709             return FALSE;
710         }
711     } else
712         PrintStructures->HelpMessageID = 0;
713
714     if(!(lppd->Flags &PD_PRINTSETUP)) {
715         PrintStructures->hwndUpDown =
716           CreateUpDownControl(WS_CHILD | WS_VISIBLE | WS_BORDER |
717                               UDS_NOTHOUSANDS | UDS_ARROWKEYS |
718                               UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 0, 0, 0, 0,
719                               hDlg, UPDOWN_ID, COMDLG32_hInstance,
720                               GetDlgItem(hDlg, edt3), MAX_COPIES, 1, 1);
721     }
722
723     /* FIXME: I allow more freedom than either Win95 or WinNT,
724      *        which do not agree to what errors should be thrown or not
725      *        in case nToPage or nFromPage is out-of-range.
726      */
727     if (lppd->nMaxPage < lppd->nMinPage)
728         lppd->nMaxPage = lppd->nMinPage;
729     if (lppd->nMinPage == lppd->nMaxPage) 
730         lppd->Flags |= PD_NOPAGENUMS;        
731     if (lppd->nToPage < lppd->nMinPage)
732         lppd->nToPage = lppd->nMinPage;
733     if (lppd->nToPage > lppd->nMaxPage)
734         lppd->nToPage = lppd->nMaxPage;
735     if (lppd->nFromPage < lppd->nMinPage)
736         lppd->nFromPage = lppd->nMinPage;
737     if (lppd->nFromPage > lppd->nMaxPage)
738         lppd->nFromPage = lppd->nMaxPage;
739
740     /* if we have the combo box, fill it */
741     if (GetDlgItem(hDlg,comboID)) {
742         /* Fill Combobox 
743          */
744         pdn = GlobalLock(lppd->hDevNames);
745         pdm = GlobalLock(lppd->hDevMode);
746         if(pdn)
747             name = (char*)pdn + pdn->wDeviceOffset;
748         else if(pdm)
749             name = pdm->dmDeviceName;
750         PRINTDLG_SetUpPrinterListCombo(hDlg, comboID, name);
751         if(pdm) GlobalUnlock(lppd->hDevMode);
752         if(pdn) GlobalUnlock(lppd->hDevNames);
753
754         /* Now find selected printer and update rest of dlg */
755         name = HeapAlloc(GetProcessHeap(),0,256);
756         if (GetDlgItemTextA(hDlg, comboID, name, 255))
757             PRINTDLG_ChangePrinter(hDlg, name, PrintStructures);
758         HeapFree(GetProcessHeap(),0,name);
759     } else {
760         /* else use default printer */
761         char name[200];
762         BOOL ret = PRINTDLG_GetDefaultPrinterName(name, sizeof(name));
763
764         if (ret)
765             PRINTDLG_ChangePrinter(hDlg, name, PrintStructures);
766         else
767             FIXME("No default printer found, expect problems!\n");
768     }
769     return TRUE;
770 }
771
772 /***********************************************************************
773  *           PRINTDLG_WMInitDialog                      [internal]
774  */
775 static LRESULT PRINTDLG_WMInitDialog16(HWND hDlg, WPARAM wParam,
776                                      PRINT_PTRA* PrintStructures)
777 {
778     LPPRINTDLG16 lppd = PrintStructures->dlg.lpPrintDlg16;
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     PrintStructures->hCollateIcon =
786       LoadIconA(COMDLG32_hInstance, "PD32_COLLATE");
787     PrintStructures->hNoCollateIcon = 
788       LoadIconA(COMDLG32_hInstance, "PD32_NOCOLLATE");
789     if(PrintStructures->hCollateIcon == 0 ||
790        PrintStructures->hNoCollateIcon == 0) {
791         ERR("no icon in resourcefile\n");
792         COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
793         EndDialog(hDlg, FALSE);
794     }
795
796     /* load Paper Orientation ICON */
797     /* FIXME: not implemented yet */
798
799     /*
800      * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
801      * must be registered and the Help button must be shown.
802      */
803     if (lppd->Flags & PD_SHOWHELP) {
804         if((PrintStructures->HelpMessageID = 
805             RegisterWindowMessageA(HELPMSGSTRINGA)) == 0) {
806             COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
807             return FALSE;
808         }
809     } else
810         PrintStructures->HelpMessageID = 0;
811
812     /* FIXME: I allow more freedom than either Win95 or WinNT,
813      *        which do not agree to what errors should be thrown or not
814      *        in case nToPage or nFromPage is out-of-range.
815      */
816     if (lppd->nMaxPage < lppd->nMinPage)
817         lppd->nMaxPage = lppd->nMinPage;
818     if (lppd->nMinPage == lppd->nMaxPage) 
819         lppd->Flags |= PD_NOPAGENUMS;        
820     if (lppd->nToPage < lppd->nMinPage)
821         lppd->nToPage = lppd->nMinPage;
822     if (lppd->nToPage > lppd->nMaxPage)
823         lppd->nToPage = lppd->nMaxPage;
824     if (lppd->nFromPage < lppd->nMinPage)
825         lppd->nFromPage = lppd->nMinPage;
826     if (lppd->nFromPage > lppd->nMaxPage)
827         lppd->nFromPage = lppd->nMaxPage;
828
829     /* If the printer combo box is in the dialog, fill it */
830     if (GetDlgItem(hDlg,comboID)) {
831         /* Fill Combobox 
832          */
833         pdn = GlobalLock16(lppd->hDevNames);
834         pdm = GlobalLock16(lppd->hDevMode);
835         if(pdn)
836             name = (char*)pdn + pdn->wDeviceOffset;
837         else if(pdm)
838             name = pdm->dmDeviceName;
839         PRINTDLG_SetUpPrinterListCombo(hDlg, comboID, name);
840         if(pdm) GlobalUnlock16(lppd->hDevMode);
841         if(pdn) GlobalUnlock16(lppd->hDevNames);
842
843         /* Now find selected printer and update rest of dlg */
844         name = HeapAlloc(GetProcessHeap(),0,256);
845         if (GetDlgItemTextA(hDlg, comboID, name, 255))
846             PRINTDLG_ChangePrinter(hDlg, name, PrintStructures);
847     } else {
848         /* else just use default printer */
849         char name[200];
850         BOOL ret = PRINTDLG_GetDefaultPrinterName(name, sizeof(name));
851
852         if (ret)
853             PRINTDLG_ChangePrinter(hDlg, name, PrintStructures);
854         else
855             FIXME("No default printer found, expect problems!\n");
856     }
857     HeapFree(GetProcessHeap(),0,name);
858
859     return TRUE;
860 }
861
862 /***********************************************************************
863  *                              PRINTDLG_WMCommand               [internal]
864  */
865 static LRESULT PRINTDLG_WMCommand(HWND hDlg, WPARAM wParam, 
866                         LPARAM lParam, PRINT_PTRA* PrintStructures)
867 {
868     LPPRINTDLGA lppd = PrintStructures->dlg.lpPrintDlg;
869     UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
870     LPDEVMODEA lpdm = PrintStructures->lpDevMode;
871
872     switch (LOWORD(wParam))  {
873     case IDOK:
874         TRACE(" OK button was hit\n");
875         if (PRINTDLG_UpdatePrintDlg(hDlg, PrintStructures)!=TRUE) {
876             FIXME("Update printdlg was not successful!\n");
877             return(FALSE);
878         }
879         EndDialog(hDlg, TRUE);
880         return(TRUE);
881
882     case IDCANCEL:
883         TRACE(" CANCEL button was hit\n");
884         EndDialog(hDlg, FALSE);
885         return(FALSE);
886
887      case pshHelp:
888         TRACE(" HELP button was hit\n");
889         SendMessageA(lppd->hwndOwner, PrintStructures->HelpMessageID, 
890                                 (WPARAM) hDlg, (LPARAM) lppd);
891         break;
892
893      case chx2:                         /* collate pages checkbox */
894         if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
895             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON, 
896                                     (LPARAM)PrintStructures->hCollateIcon);
897         else
898             SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, (WPARAM) IMAGE_ICON, 
899                                     (LPARAM)PrintStructures->hNoCollateIcon);
900         break;        
901      case edt1:                         /* from page nr editbox */
902      case edt2:                         /* to page nr editbox */
903         if (HIWORD(wParam)==EN_CHANGE) {
904             WORD nToPage;
905             WORD nFromPage;
906             nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
907             nToPage   = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
908             if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
909                 CheckRadioButton(hDlg, rad1, rad3, rad3);
910         }
911         break;
912
913     case edt3:
914         if(HIWORD(wParam) == EN_CHANGE) {
915             INT copies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
916             if(copies <= 1)
917                 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
918             else
919                 EnableWindow(GetDlgItem(hDlg, chx2), TRUE);
920         }
921         break;
922
923      case psh2:                       /* Properties button */
924        {
925          HANDLE hPrinter;
926          char   PrinterName[256];
927
928          GetDlgItemTextA(hDlg, PrinterComboID, PrinterName, 255);
929          if (!OpenPrinterA(PrinterName, &hPrinter, NULL)) {
930              FIXME(" Call to OpenPrinter did not succeed!\n");
931              break;
932          }
933          DocumentPropertiesA(hDlg, hPrinter, PrinterName, 
934                              PrintStructures->lpDevMode,
935                              PrintStructures->lpDevMode,
936                              DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
937          ClosePrinter(hPrinter);
938          break;
939        }
940
941     case rad1: /* Paperorientation */
942         if (lppd->Flags & PD_PRINTSETUP)
943               lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
944         break;
945             
946     case rad2: /* Paperorientation */
947         if (lppd->Flags & PD_PRINTSETUP)
948               lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
949         break;
950             
951     case cmb1:
952     case cmb4:                         /* Printer combobox */
953          if (HIWORD(wParam)==CBN_SELCHANGE) {
954              char   PrinterName[256];
955              GetDlgItemTextA(hDlg, LOWORD(wParam), PrinterName, 255);
956              PRINTDLG_ChangePrinter(hDlg, PrinterName, PrintStructures);
957          }
958          break;
959
960     case cmb2: /* Papersize */
961       {
962           DWORD Sel = SendDlgItemMessageA(hDlg, cmb2, CB_GETCURSEL, 0, 0);
963           if(Sel != CB_ERR)
964               lpdm->u1.s1.dmPaperSize = SendDlgItemMessageA(hDlg, cmb2,
965                                                             CB_GETITEMDATA,
966                                                             Sel, 0);
967       }
968       break;
969
970     case cmb3: /* Bin */
971       {
972           DWORD Sel = SendDlgItemMessageA(hDlg, cmb3, CB_GETCURSEL, 0, 0);
973           if(Sel != CB_ERR)
974               lpdm->dmDefaultSource = SendDlgItemMessageA(hDlg, cmb3,
975                                                           CB_GETITEMDATA, Sel,
976                                                           0);
977       }
978       break; 
979     }
980     if(lppd->Flags & PD_PRINTSETUP) {
981         switch (LOWORD(wParam)) {
982         case rad1:                         /* orientation */
983         case rad2:
984             if (IsDlgButtonChecked(hDlg, rad1) == BST_CHECKED) {
985                 if(lpdm->u1.s1.dmOrientation != DMORIENT_PORTRAIT) {
986                     lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
987                     SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE,
988                                         (WPARAM)IMAGE_ICON,
989                                         (LPARAM)PrintStructures->hPortraitIcon);
990                 }
991             } else {
992                 if(lpdm->u1.s1.dmOrientation != DMORIENT_LANDSCAPE) {
993                     lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
994                     SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE,
995                                         (WPARAM)IMAGE_ICON,
996                                         (LPARAM)PrintStructures->hLandscapeIcon);
997                 }
998             }
999             break;
1000         }
1001     }
1002     return FALSE;
1003 }    
1004
1005 /***********************************************************************
1006  *           PrintDlgProcA                      [internal]
1007  */
1008 BOOL WINAPI PrintDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam,
1009                           LPARAM lParam)
1010 {
1011     PRINT_PTRA* PrintStructures;
1012     LRESULT res=FALSE;
1013
1014     if (uMsg!=WM_INITDIALOG) {
1015         PrintStructures = (PRINT_PTRA*) GetWindowLongA(hDlg, DWL_USER);   
1016         if (!PrintStructures)
1017             return FALSE;
1018     } else {
1019         PrintStructures = (PRINT_PTRA*) lParam;
1020         SetWindowLongA(hDlg, DWL_USER, lParam); 
1021         res = PRINTDLG_WMInitDialog(hDlg, wParam, PrintStructures);
1022
1023         if(PrintStructures->dlg.lpPrintDlg->Flags & PD_ENABLEPRINTHOOK)
1024             res = PrintStructures->dlg.lpPrintDlg->lpfnPrintHook(
1025                 hDlg, uMsg, wParam, (LPARAM)PrintStructures->dlg.lpPrintDlg
1026             ); 
1027         return res;
1028     }
1029   
1030     if(PrintStructures->dlg.lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) {
1031         res = PrintStructures->dlg.lpPrintDlg->lpfnPrintHook(hDlg,uMsg,wParam,
1032                                                          lParam);
1033         if(res) return res;
1034     }
1035
1036     switch (uMsg) {
1037     case WM_COMMAND:
1038         return PRINTDLG_WMCommand(hDlg, wParam, lParam, PrintStructures);
1039
1040     case WM_DESTROY:
1041         DestroyIcon(PrintStructures->hCollateIcon);
1042         DestroyIcon(PrintStructures->hNoCollateIcon);
1043         DestroyIcon(PrintStructures->hPortraitIcon);
1044         DestroyIcon(PrintStructures->hLandscapeIcon);
1045         if(PrintStructures->hwndUpDown)
1046             DestroyWindow(PrintStructures->hwndUpDown);
1047         return FALSE;
1048     }    
1049     return res;
1050 }
1051
1052
1053 /************************************************************
1054  *
1055  *      PRINTDLG_Get16TemplateFrom32             [Internal]
1056  *      Generates a 16 bits template from the Wine 32 bits resource
1057  *
1058  */
1059 static HGLOBAL16 PRINTDLG_Get16TemplateFrom32(char *PrintResourceName)
1060 {
1061         HANDLE hResInfo, hDlgTmpl32;
1062         LPCVOID template32;
1063         DWORD size;
1064         HGLOBAL16 hGlobal16;
1065         LPVOID template;
1066  
1067         if (!(hResInfo = FindResourceA(COMMDLG_hInstance32,
1068                PrintResourceName, RT_DIALOGA)))
1069         {
1070             COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
1071             return 0;
1072         }
1073         if (!(hDlgTmpl32 = LoadResource(COMMDLG_hInstance32, hResInfo )) ||
1074             !(template32 = LockResource( hDlgTmpl32 )))
1075         {
1076             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1077             return 0;
1078         }
1079         size = SizeofResource(COMMDLG_hInstance32, hResInfo);
1080         hGlobal16 = GlobalAlloc16(0, size);
1081         if (!hGlobal16)
1082         {
1083             COMDLG32_SetCommDlgExtendedError(CDERR_MEMALLOCFAILURE);
1084             ERR("alloc failure for %ld bytes\n", size);
1085             return 0;
1086         }
1087         template = GlobalLock16(hGlobal16);
1088         if (!template)
1089         {
1090             COMDLG32_SetCommDlgExtendedError(CDERR_MEMLOCKFAILURE);
1091             ERR("global lock failure for %x handle\n", hGlobal16);
1092             GlobalFree16(hGlobal16);
1093             return 0;
1094         }
1095         ConvertDialog32To16((LPVOID)template32, size, (LPVOID)template);
1096         GlobalUnlock16(hGlobal16);
1097         return hGlobal16;
1098 }
1099
1100 /************************************************************
1101  *
1102  *      PRINTDLG_GetDlgTemplate
1103  *
1104  */
1105 static HGLOBAL PRINTDLG_GetDlgTemplate(PRINTDLGA *lppd)
1106 {
1107     HGLOBAL hDlgTmpl, hResInfo;
1108
1109     if (lppd->Flags & PD_PRINTSETUP) {
1110         if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
1111             hDlgTmpl = lppd->hSetupTemplate;
1112         } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {       
1113             hResInfo = FindResourceA(lppd->hInstance,
1114                                      lppd->lpSetupTemplateName, RT_DIALOGA);
1115             hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
1116         } else {
1117             hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32_SETUP",
1118                                      RT_DIALOGA);
1119             hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
1120         }
1121     } else {
1122         if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
1123             hDlgTmpl = lppd->hPrintTemplate;
1124         } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
1125             hResInfo = FindResourceA(lppd->hInstance,
1126                                      lppd->lpPrintTemplateName,
1127                                      RT_DIALOGA);
1128             hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
1129         } else {
1130             hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32",
1131                                      RT_DIALOGA);
1132             hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
1133         }
1134     }
1135     return hDlgTmpl;
1136 }
1137
1138 /************************************************************
1139  *
1140  *      PRINTDLG_GetDlgTemplate
1141  *
1142  */
1143 static HGLOBAL16 PRINTDLG_GetDlgTemplate16(PRINTDLG16 *lppd)
1144 {
1145     HGLOBAL16 hDlgTmpl, hResInfo;
1146
1147     if (lppd->Flags & PD_PRINTSETUP) {
1148         if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
1149             hDlgTmpl = lppd->hSetupTemplate;
1150         } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {       
1151             hResInfo = FindResource16(lppd->hInstance,
1152                                      MapSL(lppd->lpSetupTemplateName), RT_DIALOGA);
1153             hDlgTmpl = LoadResource16(lppd->hInstance, hResInfo);
1154         } else {
1155             hDlgTmpl = PRINTDLG_Get16TemplateFrom32("PRINT32_SETUP");
1156         }
1157     } else {
1158         if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
1159             hDlgTmpl = lppd->hPrintTemplate;
1160         } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
1161             hResInfo = FindResource16(lppd->hInstance,
1162                                      MapSL(lppd->lpPrintTemplateName),
1163                                      RT_DIALOGA);
1164             hDlgTmpl = LoadResource16(lppd->hInstance, hResInfo);
1165         } else {
1166             hDlgTmpl = PRINTDLG_Get16TemplateFrom32("PRINT32");
1167         }
1168     }
1169     return hDlgTmpl;
1170 }
1171
1172 /***********************************************************************
1173  *
1174  *      PRINTDLG_CreateDC
1175  *
1176  */
1177 static BOOL PRINTDLG_CreateDC(LPPRINTDLGA lppd)
1178 {
1179     DEVNAMES *pdn = GlobalLock(lppd->hDevNames);
1180     DEVMODEA *pdm = GlobalLock(lppd->hDevMode);
1181
1182     if(lppd->Flags & PD_RETURNDC) {
1183         lppd->hDC = CreateDCA((char*)pdn + pdn->wDriverOffset,
1184                               (char*)pdn + pdn->wDeviceOffset,
1185                               (char*)pdn + pdn->wOutputOffset,
1186                               pdm );
1187     } else if(lppd->Flags & PD_RETURNIC) {
1188         lppd->hDC = CreateICA((char*)pdn + pdn->wDriverOffset,
1189                               (char*)pdn + pdn->wDeviceOffset,
1190                               (char*)pdn + pdn->wOutputOffset,
1191                               pdm );
1192     }
1193     GlobalUnlock(lppd->hDevNames);
1194     GlobalUnlock(lppd->hDevMode);
1195     return lppd->hDC ? TRUE : FALSE;
1196 }
1197
1198 static BOOL PRINTDLG_CreateDC16(LPPRINTDLG16 lppd)
1199 {
1200     DEVNAMES *pdn = GlobalLock16(lppd->hDevNames);
1201     DEVMODEA *pdm = GlobalLock16(lppd->hDevMode);
1202
1203     if(lppd->Flags & PD_RETURNDC) {
1204         lppd->hDC = CreateDCA((char*)pdn + pdn->wDriverOffset,
1205                               (char*)pdn + pdn->wDeviceOffset,
1206                               (char*)pdn + pdn->wOutputOffset,
1207                               pdm );
1208     } else if(lppd->Flags & PD_RETURNIC) {
1209         lppd->hDC = CreateICA((char*)pdn + pdn->wDriverOffset,
1210                               (char*)pdn + pdn->wDeviceOffset,
1211                               (char*)pdn + pdn->wOutputOffset,
1212                               pdm );
1213     }
1214     GlobalUnlock16(lppd->hDevNames);
1215     GlobalUnlock16(lppd->hDevMode);
1216     return lppd->hDC ? TRUE : FALSE;
1217 }
1218
1219 /***********************************************************************
1220  *           PrintDlgA   (COMDLG32.17)
1221  *
1222  *  Displays the the PRINT dialog box, which enables the user to specify
1223  *  specific properties of the print job.
1224  *
1225  * RETURNS
1226  *  nonzero if the user pressed the OK button
1227  *  zero    if the user cancelled the window or an error occurred
1228  *
1229  * BUGS
1230  *  PrintDlg:
1231  *  * The Collate Icons do not display, even though they are in the code.
1232  *  * The Properties Button(s) should call DocumentPropertiesA().
1233  *  PrintSetupDlg:
1234  *  * The Paper Orientation Icons are not implemented yet.
1235  *  * The Properties Button(s) should call DocumentPropertiesA().
1236  *  * Settings are not yet taken from a provided DevMode or 
1237  *    default printer settings.
1238  */
1239 BOOL WINAPI PrintDlgA(
1240                       LPPRINTDLGA lppd /* [in/out] ptr to PRINTDLG32 struct */
1241                       )
1242 {
1243     BOOL      bRet = FALSE;
1244     LPVOID   ptr;
1245     HINSTANCE hInst = GetWindowLongA( lppd->hwndOwner, GWL_HINSTANCE );
1246
1247     if(TRACE_ON(commdlg)) {
1248         char flagstr[1000] = "";
1249         struct pd_flags *pflag = pd_flags;
1250         for( ; pflag->name; pflag++) {
1251             if(lppd->Flags & pflag->flag)
1252                 strcat(flagstr, pflag->name);
1253         }
1254         TRACE("(%p): hwndOwner = %08x, hDevMode = %08x, hDevNames = %08x\n"
1255               "pp. %d-%d, min p %d, max p %d, copies %d, hinst %08x\n"
1256               "flags %08lx (%s)\n",
1257               lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
1258               lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
1259               lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
1260     }
1261
1262     if(lppd->lStructSize != sizeof(PRINTDLGA)) {
1263         WARN("structure size failure !!!\n");
1264         COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
1265         return FALSE; 
1266     }
1267
1268     if(lppd->Flags & PD_RETURNDEFAULT) {
1269         PRINTER_INFO_2A *pbuf;
1270         HANDLE hprn;
1271         DWORD needed;
1272
1273         if(lppd->hDevMode || lppd->hDevNames) {
1274             WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
1275             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE); 
1276             return FALSE;
1277         }
1278         if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
1279             WARN("Can't find default printer\n");
1280             COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN); 
1281             return FALSE;
1282         }
1283
1284         GetPrinterA(hprn, 2, NULL, 0, &needed);
1285         pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
1286         GetPrinterA(hprn, 2, (LPBYTE)pbuf, needed, &needed);
1287         ClosePrinter(hprn);
1288         PRINTDLG_CreateDevNames(&(lppd->hDevNames), "winspool",
1289                                   pbuf->pDevMode->dmDeviceName,
1290                                   pbuf->pPortName);
1291         lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
1292                                      pbuf->pDevMode->dmDriverExtra);
1293         ptr = GlobalLock(lppd->hDevMode);
1294         memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
1295                pbuf->pDevMode->dmDriverExtra);
1296         GlobalUnlock(lppd->hDevMode);
1297         HeapFree(GetProcessHeap(), 0, pbuf);
1298         bRet = TRUE;
1299     } else {
1300         HGLOBAL hDlgTmpl;
1301         PRINT_PTRA *PrintStructures;
1302
1303     /* load Dialog resources, 
1304      * depending on Flags indicates Print32 or Print32_setup dialog 
1305      */
1306         hDlgTmpl = PRINTDLG_GetDlgTemplate(lppd);
1307         if (!hDlgTmpl) {
1308             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1309             return FALSE;
1310         }
1311         ptr = LockResource( hDlgTmpl );
1312         if (!ptr) {
1313             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1314             return FALSE;
1315         }
1316
1317         PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1318                                     sizeof(PRINT_PTRA));
1319         PrintStructures->dlg.lpPrintDlg = lppd;
1320
1321         /* and create & process the dialog .
1322          * -1 is failure, 0 is broken hwnd, everything else is ok.
1323          */
1324         bRet = (0<DialogBoxIndirectParamA(hInst, ptr, lppd->hwndOwner,
1325                                            PrintDlgProcA,
1326                                            (LPARAM)PrintStructures));
1327
1328         if(bRet) {
1329             DEVMODEA *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
1330             PRINTER_INFO_2A *pi = PrintStructures->lpPrinterInfo;
1331
1332             if (lppd->hDevMode == 0) {
1333                 TRACE(" No hDevMode yet... Need to create my own\n");
1334                 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE,
1335                                         lpdm->dmSize + lpdm->dmDriverExtra);
1336             } else {
1337                 WORD locks;
1338                 if((locks = (GlobalFlags(lppd->hDevMode) & GMEM_LOCKCOUNT))) {
1339                     WARN("hDevMode has %d locks on it. Unlocking it now\n", locks);
1340                     while(locks--) {
1341                         GlobalUnlock(lppd->hDevMode);
1342                         TRACE("Now got %d locks\n", locks);
1343                     }
1344                 }
1345                 lppd->hDevMode = GlobalReAlloc(lppd->hDevMode,
1346                                                lpdm->dmSize + lpdm->dmDriverExtra,
1347                                                GMEM_MOVEABLE);
1348             }
1349             lpdmReturn = GlobalLock(lppd->hDevMode);
1350             memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
1351
1352             if (lppd->hDevNames != 0) {
1353                 WORD locks;
1354                 if((locks = (GlobalFlags(lppd->hDevNames) & GMEM_LOCKCOUNT))) {
1355                     WARN("hDevNames has %d locks on it. Unlocking it now\n", locks);
1356                     while(locks--)
1357                         GlobalUnlock(lppd->hDevNames);
1358                 }
1359             }
1360             PRINTDLG_CreateDevNames(&(lppd->hDevNames), "winspool",
1361                                     lpdmReturn->dmDeviceName, pi->pPortName);
1362             GlobalUnlock(lppd->hDevMode);
1363         }
1364         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
1365         HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
1366         HeapFree(GetProcessHeap(), 0, PrintStructures);
1367     }
1368     if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
1369         bRet = PRINTDLG_CreateDC(lppd);
1370
1371     TRACE("exit! (%d)\n", bRet);        
1372     return bRet;    
1373 }
1374
1375 /***********************************************************************
1376  *           PrintDlg16   (COMMDLG.20)
1377  * 
1378  *  Displays the the PRINT dialog box, which enables the user to specify
1379  *  specific properties of the print job.
1380  *
1381  * RETURNS
1382  *  nonzero if the user pressed the OK button
1383  *  zero    if the user cancelled the window or an error occurred
1384  *
1385  * BUGS
1386  *  * calls up to the 32-bit versions of the Dialogs, which look different
1387  *  * Customizing is *not* implemented.
1388  */
1389
1390 BOOL16 WINAPI PrintDlg16(
1391               LPPRINTDLG16 lppd /* [in/out] ptr to PRINTDLG struct */
1392 ) {
1393     BOOL      bRet = FALSE;
1394     LPVOID   ptr;
1395     HINSTANCE hInst = GetWindowLongA( lppd->hwndOwner, GWL_HINSTANCE );
1396
1397     if(TRACE_ON(commdlg)) {
1398         char flagstr[1000] = "";
1399         struct pd_flags *pflag = pd_flags;
1400         for( ; pflag->name; pflag++) {
1401             if(lppd->Flags & pflag->flag)
1402                 strcat(flagstr, pflag->name);
1403         }
1404         TRACE("(%p): hwndOwner = %08x, hDevMode = %08x, hDevNames = %08x\n"
1405               "pp. %d-%d, min p %d, max p %d, copies %d, hinst %08x\n"
1406               "flags %08lx (%s)\n",
1407               lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
1408               lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
1409               lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
1410     }
1411
1412     if(lppd->lStructSize != sizeof(PRINTDLG16)) {
1413         ERR("structure size (%ld/%d)\n",lppd->lStructSize,sizeof(PRINTDLG16));
1414         COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
1415         return FALSE;
1416     }
1417
1418     if(lppd->Flags & PD_RETURNDEFAULT) {
1419         PRINTER_INFO_2A *pbuf;
1420         HANDLE hprn;
1421         DWORD needed;
1422
1423         if(lppd->hDevMode || lppd->hDevNames) {
1424             WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
1425             COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE); 
1426             return FALSE;
1427         }
1428         if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
1429             WARN("Can't find default printer\n");
1430             COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN); 
1431             return FALSE;
1432         }
1433
1434         GetPrinterA(hprn, 2, NULL, 0, &needed);
1435         pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
1436         GetPrinterA(hprn, 2, (LPBYTE)pbuf, needed, &needed);
1437         ClosePrinter(hprn);
1438         PRINTDLG_CreateDevNames16(&(lppd->hDevNames), "winspool",
1439                                     pbuf->pDevMode->dmDeviceName,
1440                                     pbuf->pPortName);
1441         lppd->hDevMode = GlobalAlloc16(GMEM_MOVEABLE,pbuf->pDevMode->dmSize+
1442                                      pbuf->pDevMode->dmDriverExtra);
1443         ptr = GlobalLock16(lppd->hDevMode);
1444         memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
1445                pbuf->pDevMode->dmDriverExtra);
1446         GlobalUnlock16(lppd->hDevMode);
1447         HeapFree(GetProcessHeap(), 0, pbuf);
1448         bRet = TRUE;
1449     } else {
1450         HGLOBAL hDlgTmpl;
1451         PRINT_PTRA *PrintStructures;
1452
1453     /* load Dialog resources, 
1454      * depending on Flags indicates Print32 or Print32_setup dialog 
1455      */
1456         hDlgTmpl = PRINTDLG_GetDlgTemplate16(lppd);
1457         if (!hDlgTmpl) {
1458             COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1459             return FALSE;
1460         }
1461         PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1462                                     sizeof(PRINT_PTRA));
1463         PrintStructures->dlg.lpPrintDlg16 = lppd;
1464         PrintStructures->dlg.lpPrintDlg = (LPPRINTDLGA)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(PRINTDLGA));
1465 #define CVAL(x) PrintStructures->dlg.lpPrintDlg->x = lppd->x;
1466 #define MVAL(x) PrintStructures->dlg.lpPrintDlg->x = MapSL(lppd->x);
1467         CVAL(Flags);CVAL(hwndOwner);CVAL(hDC);
1468         CVAL(nFromPage);CVAL(nToPage);CVAL(nMinPage);CVAL(nMaxPage);
1469         CVAL(nCopies);CVAL(hInstance);CVAL(lCustData);
1470         MVAL(lpPrintTemplateName);MVAL(lpSetupTemplateName);
1471         /* Don't copy rest, it is 16 bit specific */
1472 #undef MVAL
1473 #undef CVAL
1474
1475         PrintStructures->lpDevMode = HeapAlloc(GetProcessHeap(),0,sizeof(DEVMODEA));
1476
1477         /* and create & process the dialog .
1478          * -1 is failure, 0 is broken hwnd, everything else is ok.
1479          */
1480         bRet =  (0<DialogBoxIndirectParam16(
1481                  hInst, hDlgTmpl, lppd->hwndOwner,
1482                  (DLGPROC16)GetProcAddress16(GetModuleHandle16("COMMDLG"),(LPCSTR)21),
1483                  (LPARAM)PrintStructures
1484                 )
1485         );
1486         if (!PrintStructures->lpPrinterInfo) bRet = FALSE;
1487         if(bRet) {
1488             DEVMODEA *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
1489             PRINTER_INFO_2A *pi = PrintStructures->lpPrinterInfo;
1490
1491             if (lppd->hDevMode == 0) {
1492                 TRACE(" No hDevMode yet... Need to create my own\n");
1493                 lppd->hDevMode = GlobalAlloc16(GMEM_MOVEABLE,
1494                                         lpdm->dmSize + lpdm->dmDriverExtra);
1495             } else {
1496                 WORD locks;
1497                 if((locks = (GlobalFlags16(lppd->hDevMode)&GMEM_LOCKCOUNT))) {
1498                     WARN("hDevMode has %d locks on it. Unlocking it now\n", locks);
1499                     while(locks--) {
1500                         GlobalUnlock16(lppd->hDevMode);
1501                         TRACE("Now got %d locks\n", locks);
1502                     }
1503                 }
1504                 lppd->hDevMode = GlobalReAlloc16(lppd->hDevMode,
1505                                                lpdm->dmSize + lpdm->dmDriverExtra,
1506                                                GMEM_MOVEABLE);
1507             }
1508             lpdmReturn = GlobalLock16(lppd->hDevMode);
1509             memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
1510
1511             if (lppd->hDevNames != 0) {
1512                 WORD locks;
1513                 if((locks = (GlobalFlags16(lppd->hDevNames)&GMEM_LOCKCOUNT))) {
1514                     WARN("hDevNames has %d locks on it. Unlocking it now\n", locks);
1515                     while(locks--)
1516                         GlobalUnlock16(lppd->hDevNames);
1517                 }
1518             }
1519             PRINTDLG_CreateDevNames16(&(lppd->hDevNames), "winspool",
1520                                     lpdmReturn->dmDeviceName, pi->pPortName);
1521             GlobalUnlock16(lppd->hDevMode);
1522         }
1523         if (!(lppd->Flags & (PD_ENABLESETUPTEMPLATEHANDLE | PD_ENABLESETUPTEMPLATE)))
1524             GlobalFree16(hDlgTmpl); /* created from the 32 bits resource */
1525         HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
1526         HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
1527         HeapFree(GetProcessHeap(), 0, PrintStructures);
1528     }
1529     if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
1530         bRet = PRINTDLG_CreateDC16(lppd);
1531
1532     TRACE("exit! (%d)\n", bRet);        
1533     return bRet;    
1534 }
1535
1536
1537
1538 /***********************************************************************
1539  *           PrintDlgW   (COMDLG32.18)
1540  */
1541 BOOL WINAPI PrintDlgW( LPPRINTDLGW printdlg )
1542 {
1543     FIXME("A really empty stub\n" );
1544     return FALSE;
1545 }
1546
1547 /***********************************************************************
1548  *
1549  *          PageSetupDlg
1550  */
1551
1552 /***********************************************************************
1553  *            PageSetupDlgA  (COMDLG32.15)
1554  */
1555 BOOL WINAPI PageSetupDlgA(LPPAGESETUPDLGA setupdlg) {
1556         FIXME("(%p), stub!\n",setupdlg);
1557         return TRUE;
1558 }
1559 /***********************************************************************
1560  *            PageSetupDlgW  (COMDLG32.16)
1561  */
1562 BOOL WINAPI PageSetupDlgW(LPPAGESETUPDLGW setupdlg) {
1563         FIXME("(%p), stub!\n",setupdlg);
1564         return FALSE;
1565 }
1566
1567 /**********************************************************************
1568  *
1569  *      16 bit commdlg
1570  */
1571
1572 /***********************************************************************
1573  *           PrintDlgProc16   (COMMDLG.21)
1574  */
1575 LRESULT WINAPI PrintDlgProc16(HWND16 hDlg, UINT16 uMsg, WPARAM16 wParam,
1576                             LPARAM lParam)
1577 {
1578     PRINT_PTRA* PrintStructures;
1579     LRESULT res=FALSE;
1580
1581     if (uMsg!=WM_INITDIALOG) {
1582         PrintStructures = (PRINT_PTRA*) GetWindowLongA(hDlg, DWL_USER);   
1583         if (!PrintStructures)
1584             return FALSE;
1585     } else {
1586         PrintStructures = (PRINT_PTRA*) lParam;
1587         SetWindowLongA(hDlg, DWL_USER, lParam); 
1588         res = PRINTDLG_WMInitDialog16(hDlg, wParam, PrintStructures);
1589
1590         if(PrintStructures->dlg.lpPrintDlg16->Flags & PD_ENABLEPRINTHOOK) {
1591             res = CallWindowProc16(
1592                 (WNDPROC16)PrintStructures->dlg.lpPrintDlg16->lpfnPrintHook,
1593                 hDlg, uMsg, wParam, (LPARAM)PrintStructures->dlg.lpPrintDlg16
1594             );
1595         }
1596         return res;
1597     }
1598   
1599     if(PrintStructures->dlg.lpPrintDlg16->Flags & PD_ENABLEPRINTHOOK) {
1600         res = CallWindowProc16(
1601                 (WNDPROC16)PrintStructures->dlg.lpPrintDlg16->lpfnPrintHook,
1602                 hDlg,uMsg, wParam, lParam
1603         );
1604         if(LOWORD(res)) return res;
1605     }
1606
1607     switch (uMsg) {
1608     case WM_COMMAND:
1609         return PRINTDLG_WMCommand(hDlg, wParam, lParam, PrintStructures);
1610
1611     case WM_DESTROY:
1612         DestroyIcon(PrintStructures->hCollateIcon);
1613         DestroyIcon(PrintStructures->hNoCollateIcon);
1614     /* FIXME: don't forget to delete the paper orientation icons here! */
1615
1616         return FALSE;
1617     }    
1618     return res;
1619 }
1620
1621
1622 /***********************************************************************
1623  *           PrintSetupDlgProc16   (COMMDLG.22)
1624  */
1625 LRESULT WINAPI PrintSetupDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
1626                                    LPARAM lParam)
1627 {
1628   switch (wMsg)
1629     {
1630     case WM_INITDIALOG:
1631       TRACE("WM_INITDIALOG lParam=%08lX\n", lParam);
1632       ShowWindow(hWnd, SW_SHOWNORMAL);
1633       return (TRUE);
1634     case WM_COMMAND:
1635       switch (wParam) {
1636       case IDOK:
1637         EndDialog(hWnd, TRUE);
1638         return(TRUE);
1639       case IDCANCEL:
1640         EndDialog(hWnd, FALSE);
1641         return(TRUE);
1642       }
1643       return(FALSE);
1644     }
1645   return FALSE;
1646 }
1647
1648
1649 /***********************************************************************
1650  *      PrintDlgExA
1651  */
1652 HRESULT WINAPI PrintDlgExA(LPVOID lpPrintDlgExA) /* [???] FIXME: LPPRINTDLGEXA */
1653 {
1654         FIXME("stub\n");
1655         return E_NOTIMPL;
1656 }
1657 /***********************************************************************
1658  *      PrintDlgExW
1659  */
1660 HRESULT WINAPI PrintDlgExW(LPVOID lpPrintDlgExW) /* [???] FIXME: LPPRINTDLGEXW */
1661 {
1662         FIXME("stub\n");
1663         return E_NOTIMPL;
1664 }