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