ReactOS  0.4.15-dev-1018-g0695ecb
printdlg.c
Go to the documentation of this file.
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  * Copyright 2010 Vitaly Perov
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 #include <ctype.h>
25 #include <stdlib.h>
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <assert.h>
30 
31 #define COBJMACROS
32 #define NONAMELESSUNION
33 #define NONAMELESSSTRUCT
34 #include "windef.h"
35 #include "winbase.h"
36 #include "wingdi.h"
37 #include "winuser.h"
38 #include "winspool.h"
39 #include "winerror.h"
40 #include "objbase.h"
41 #include "commdlg.h"
42 
43 #include "wine/debug.h"
44 
45 #include "dlgs.h"
46 #include "cderr.h"
47 #include "cdlg.h"
48 
50 
51 /* Yes these constants are the same, but we're just copying win98 */
52 #define UPDOWN_ID 0x270f
53 #define MAX_COPIES 9999
54 
55 /* This PRINTDLGA internal structure stores
56  * pointers to several throughout useful structures.
57  */
58 
59 typedef struct
60 {
66  HICON hCollateIcon; /* PrintDlg only */
67  HICON hNoCollateIcon; /* PrintDlg only */
68  HICON hPortraitIcon; /* PrintSetupDlg only */
69  HICON hLandscapeIcon; /* PrintSetupDlg only */
71 } PRINT_PTRA;
72 
73 typedef struct
74 {
80  HICON hCollateIcon; /* PrintDlg only */
81  HICON hNoCollateIcon; /* PrintDlg only */
82  HICON hPortraitIcon; /* PrintSetupDlg only */
83  HICON hLandscapeIcon; /* PrintSetupDlg only */
85 } PRINT_PTRW;
86 
87 /* Debugging info */
88 struct pd_flags
89 {
92 };
93 
94 static const struct pd_flags psd_flags[] = {
95  {PSD_MINMARGINS,"PSD_MINMARGINS"},
96  {PSD_MARGINS,"PSD_MARGINS"},
97  {PSD_INTHOUSANDTHSOFINCHES,"PSD_INTHOUSANDTHSOFINCHES"},
98  {PSD_INHUNDREDTHSOFMILLIMETERS,"PSD_INHUNDREDTHSOFMILLIMETERS"},
99  {PSD_DISABLEMARGINS,"PSD_DISABLEMARGINS"},
100  {PSD_DISABLEPRINTER,"PSD_DISABLEPRINTER"},
101  {PSD_NOWARNING,"PSD_NOWARNING"},
102  {PSD_DISABLEORIENTATION,"PSD_DISABLEORIENTATION"},
103  {PSD_RETURNDEFAULT,"PSD_RETURNDEFAULT"},
104  {PSD_DISABLEPAPER,"PSD_DISABLEPAPER"},
105  {PSD_SHOWHELP,"PSD_SHOWHELP"},
106  {PSD_ENABLEPAGESETUPHOOK,"PSD_ENABLEPAGESETUPHOOK"},
107  {PSD_ENABLEPAGESETUPTEMPLATE,"PSD_ENABLEPAGESETUPTEMPLATE"},
108  {PSD_ENABLEPAGESETUPTEMPLATEHANDLE,"PSD_ENABLEPAGESETUPTEMPLATEHANDLE"},
109  {PSD_ENABLEPAGEPAINTHOOK,"PSD_ENABLEPAGEPAINTHOOK"},
110  {PSD_DISABLEPAGEPAINTING,"PSD_DISABLEPAGEPAINTING"},
111  {-1, NULL}
112 };
113 
114 static const struct pd_flags pd_flags[] = {
115  {PD_SELECTION, "PD_SELECTION "},
116  {PD_PAGENUMS, "PD_PAGENUMS "},
117  {PD_NOSELECTION, "PD_NOSELECTION "},
118  {PD_NOPAGENUMS, "PD_NOPAGENUMS "},
119  {PD_COLLATE, "PD_COLLATE "},
120  {PD_PRINTTOFILE, "PD_PRINTTOFILE "},
121  {PD_PRINTSETUP, "PD_PRINTSETUP "},
122  {PD_NOWARNING, "PD_NOWARNING "},
123  {PD_RETURNDC, "PD_RETURNDC "},
124  {PD_RETURNIC, "PD_RETURNIC "},
125  {PD_RETURNDEFAULT, "PD_RETURNDEFAULT "},
126  {PD_SHOWHELP, "PD_SHOWHELP "},
127  {PD_ENABLEPRINTHOOK, "PD_ENABLEPRINTHOOK "},
128  {PD_ENABLESETUPHOOK, "PD_ENABLESETUPHOOK "},
129  {PD_ENABLEPRINTTEMPLATE, "PD_ENABLEPRINTTEMPLATE "},
130  {PD_ENABLESETUPTEMPLATE, "PD_ENABLESETUPTEMPLATE "},
131  {PD_ENABLEPRINTTEMPLATEHANDLE, "PD_ENABLEPRINTTEMPLATEHANDLE "},
132  {PD_ENABLESETUPTEMPLATEHANDLE, "PD_ENABLESETUPTEMPLATEHANDLE "},
133  {PD_USEDEVMODECOPIES, "PD_USEDEVMODECOPIES[ANDCOLLATE] "},
134  {PD_DISABLEPRINTTOFILE, "PD_DISABLEPRINTTOFILE "},
135  {PD_HIDEPRINTTOFILE, "PD_HIDEPRINTTOFILE "},
136  {PD_NONETWORKBUTTON, "PD_NONETWORKBUTTON "},
137  {-1, NULL}
138 };
139 /* address of wndproc for subclassed Static control */
142 /* the text of the fake document to render for the Page Setup dialog */
144 static const WCHAR pd32_collateW[] = { 'P', 'D', '3', '2', '_', 'C', 'O', 'L', 'L', 'A', 'T', 'E', 0 };
145 static const WCHAR pd32_nocollateW[] = { 'P', 'D', '3', '2', '_', 'N', 'O', 'C', 'O', 'L', 'L', 'A', 'T', 'E', 0 };
146 static const WCHAR pd32_portraitW[] = { 'P', 'D', '3', '2', '_', 'P', 'O', 'R', 'T', 'R', 'A', 'I', 'T', 0 };
147 static const WCHAR pd32_landscapeW[] = { 'P', 'D', '3', '2', '_', 'L', 'A', 'N', 'D', 'S', 'C', 'A', 'P', 'E', 0 };
148 static const WCHAR printdlg_prop[] = {'_','_','W','I','N','E','_','P','R','I','N','T','D','L','G','D','A','T','A',0};
149 static const WCHAR pagesetupdlg_prop[] = { '_', '_', 'W', 'I', 'N', 'E', '_', 'P', 'A', 'G', 'E',
150  'S', 'E', 'T', 'U', 'P', 'D', 'L', 'G', 'D', 'A', 'T', 'A', 0 };
151 
152 
154 {
155  LPWSTR ret;
156  DWORD len;
157 
158  if(!p) return NULL;
159  len = (lstrlenW(p) + 1) * sizeof(WCHAR);
160  ret = HeapAlloc(GetProcessHeap(), 0, len);
161  memcpy(ret, p, len);
162  return ret;
163 }
164 
165 /***********************************************************************
166  * get_driver_info [internal]
167  *
168  * get DRIVER_INFO_3W for the current printer handle,
169  * alloc the buffer, when needed
170  */
172 {
173  DRIVER_INFO_3W *di3 = NULL;
174  DWORD needed = 0;
175  BOOL res;
176 
177  res = GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
178  if (!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
179  di3 = HeapAlloc(GetProcessHeap(), 0, needed);
180  res = GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)di3, needed, &needed);
181  }
182 
183  if (res)
184  return di3;
185 
186  TRACE("GetPrinterDriverW failed with %u\n", GetLastError());
187  HeapFree(GetProcessHeap(), 0, di3);
188  return NULL;
189 }
190 
192 {
193  DRIVER_INFO_3A *di3 = NULL;
194  DWORD needed = 0;
195  BOOL res;
196 
197  res = GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
198  if (!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
199  di3 = HeapAlloc(GetProcessHeap(), 0, needed);
200  res = GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)di3, needed, &needed);
201  }
202 
203  if (res)
204  return di3;
205 
206  TRACE("GetPrinterDriverA failed with %u\n", GetLastError());
207  HeapFree(GetProcessHeap(), 0, di3);
208  return NULL;
209 }
210 
211 
212 /***********************************************************************
213  * get_printer_info [internal]
214  *
215  * get PRINTER_INFO_2W for the current printer handle,
216  * alloc the buffer, when needed
217  */
219 {
220  PRINTER_INFO_2W *pi2 = NULL;
221  DWORD needed = 0;
222  BOOL res;
223 
224  res = GetPrinterW(hprn, 2, NULL, 0, &needed);
225  if (!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
226  pi2 = HeapAlloc(GetProcessHeap(), 0, needed);
227  res = GetPrinterW(hprn, 2, (LPBYTE)pi2, needed, &needed);
228  }
229 
230  if (res)
231  return pi2;
232 
233  TRACE("GetPrinterW failed with %u\n", GetLastError());
234  HeapFree(GetProcessHeap(), 0, pi2);
235  return NULL;
236 }
237 
239 {
240  PRINTER_INFO_2A *pi2 = NULL;
241  DWORD needed = 0;
242  BOOL res;
243 
244  res = GetPrinterA(hprn, 2, NULL, 0, &needed);
245  if (!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
246  pi2 = HeapAlloc(GetProcessHeap(), 0, needed);
247  res = GetPrinterA(hprn, 2, (LPBYTE)pi2, needed, &needed);
248  }
249 
250  if (res)
251  return pi2;
252 
253  TRACE("GetPrinterA failed with %u\n", GetLastError());
254  HeapFree(GetProcessHeap(), 0, pi2);
255  return NULL;
256 }
257 
258 
259 /***********************************************************************
260  * update_devmode_handle [internal]
261  *
262  * update a devmode handle for the given DEVMODE, alloc the buffer, when needed
263  */
265 {
266  SIZE_T size = GlobalSize(hdm);
267  LPVOID ptr;
268 
269  /* Increase / alloc the global memory block, when needed */
270  if ((dm->dmSize + dm->dmDriverExtra) > size) {
271  if (hdm)
272  hdm = GlobalReAlloc(hdm, dm->dmSize + dm->dmDriverExtra, 0);
273  else
274  hdm = GlobalAlloc(GMEM_MOVEABLE, dm->dmSize + dm->dmDriverExtra);
275  }
276 
277  if (hdm) {
278  ptr = GlobalLock(hdm);
279  if (ptr) {
280  memcpy(ptr, dm, dm->dmSize + dm->dmDriverExtra);
281  GlobalUnlock(hdm);
282  }
283  else
284  {
285  GlobalFree(hdm);
286  hdm = NULL;
287  }
288  }
289  return hdm;
290 }
291 
293 {
294  SIZE_T size = GlobalSize(hdm);
295  LPVOID ptr;
296 
297  /* Increase / alloc the global memory block, when needed */
298  if ((dm->dmSize + dm->dmDriverExtra) > size) {
299  if (hdm)
300  hdm = GlobalReAlloc(hdm, dm->dmSize + dm->dmDriverExtra, 0);
301  else
302  hdm = GlobalAlloc(GMEM_MOVEABLE, dm->dmSize + dm->dmDriverExtra);
303  }
304 
305  if (hdm) {
306  ptr = GlobalLock(hdm);
307  if (ptr) {
308  memcpy(ptr, dm, dm->dmSize + dm->dmDriverExtra);
309  GlobalUnlock(hdm);
310  }
311  else
312  {
313  GlobalFree(hdm);
314  hdm = NULL;
315  }
316  }
317  return hdm;
318 }
319 
320 /***********************************************************
321  * convert_to_devmodeA
322  *
323  * Creates an ansi copy of supplied devmode
324  */
326 {
327  DEVMODEA *dmA;
328  DWORD size;
329 
330  if (!dmW) return NULL;
331  size = dmW->dmSize - CCHDEVICENAME -
332  ((dmW->dmSize > FIELD_OFFSET(DEVMODEW, dmFormName)) ? CCHFORMNAME : 0);
333 
334  dmA = HeapAlloc(GetProcessHeap(), 0, size + dmW->dmDriverExtra);
335  if (!dmA) return NULL;
336 
339 
340  if (FIELD_OFFSET(DEVMODEW, dmFormName) >= dmW->dmSize)
341  {
342  memcpy(&dmA->dmSpecVersion, &dmW->dmSpecVersion,
343  dmW->dmSize - FIELD_OFFSET(DEVMODEW, dmSpecVersion));
344  }
345  else
346  {
347  memcpy(&dmA->dmSpecVersion, &dmW->dmSpecVersion,
348  FIELD_OFFSET(DEVMODEW, dmFormName) - FIELD_OFFSET(DEVMODEW, dmSpecVersion));
351 
352  memcpy(&dmA->dmLogPixels, &dmW->dmLogPixels, dmW->dmSize - FIELD_OFFSET(DEVMODEW, dmLogPixels));
353  }
354 
355  dmA->dmSize = size;
356  memcpy((char *)dmA + dmA->dmSize, (const char *)dmW + dmW->dmSize, dmW->dmDriverExtra);
357  return dmA;
358 }
359 
360 /***********************************************************************
361  * PRINTDLG_OpenDefaultPrinter
362  *
363  * Returns a winspool printer handle to the default printer in *hprn
364  * Caller must call ClosePrinter on the handle
365  *
366  * Returns TRUE on success else FALSE
367  */
369 {
370  WCHAR buf[260];
372  BOOL res;
374  return FALSE;
375  res = OpenPrinterW(buf, hprn, NULL);
376  if (!res)
377  WARN("Could not open printer %s\n", debugstr_w(buf));
378  return res;
379 }
380 
381 /***********************************************************************
382  * PRINTDLG_SetUpPrinterListCombo
383  *
384  * Initializes printer list combox.
385  * hDlg: HWND of dialog
386  * id: Control id of combo
387  * name: Name of printer to select
388  *
389  * Initializes combo with list of available printers. Selects printer 'name'
390  * If name is NULL or does not exist select the default printer.
391  *
392  * Returns number of printers added to list.
393  */
395 {
396  DWORD needed, num;
397  INT i;
399  EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
400  pi = HeapAlloc(GetProcessHeap(), 0, needed);
401  EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pi, needed, &needed,
402  &num);
403 
404  SendDlgItemMessageA(hDlg, id, CB_RESETCONTENT, 0, 0);
405 
406  for(i = 0; i < num; i++) {
407  SendDlgItemMessageA(hDlg, id, CB_ADDSTRING, 0,
408  (LPARAM)pi[i].pPrinterName );
409  }
410  HeapFree(GetProcessHeap(), 0, pi);
411  if(!name ||
412  (i = SendDlgItemMessageA(hDlg, id, CB_FINDSTRINGEXACT, -1,
413  (LPARAM)name)) == CB_ERR) {
414 
415  char buf[260];
417  if (name != NULL)
418  WARN("Can't find %s in printer list so trying to find default\n",
419  debugstr_a(name));
421  return num;
423  if(i == CB_ERR)
424  FIXME("Can't find default printer in printer list\n");
425  }
426  SendDlgItemMessageA(hDlg, id, CB_SETCURSEL, i, 0);
427  return num;
428 }
429 
431 {
432  DWORD needed, num;
433  INT i;
435  EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
436  pi = HeapAlloc(GetProcessHeap(), 0, needed);
437  EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pi, needed, &needed,
438  &num);
439 
440  for(i = 0; i < num; i++) {
441  SendDlgItemMessageW(hDlg, id, CB_ADDSTRING, 0,
442  (LPARAM)pi[i].pPrinterName );
443  }
444  HeapFree(GetProcessHeap(), 0, pi);
445  if(!name ||
446  (i = SendDlgItemMessageW(hDlg, id, CB_FINDSTRINGEXACT, -1,
447  (LPARAM)name)) == CB_ERR) {
448  WCHAR buf[260];
450  if (name != NULL)
451  WARN("Can't find %s in printer list so trying to find default\n",
452  debugstr_w(name));
454  return num;
456  if(i == CB_ERR)
457  TRACE("Can't find default printer in printer list\n");
458  }
459  SendDlgItemMessageW(hDlg, id, CB_SETCURSEL, i, 0);
460  return num;
461 }
462 
463 #ifdef __REACTOS__
464 static const CHAR cDriverName[] = "winspool";
465 static const WCHAR wDriverName[] = L"winspool";
466 #endif
467 
468 /***********************************************************************
469  * PRINTDLG_CreateDevNames [internal]
470  *
471  *
472  * creates a DevNames structure.
473  *
474  * (NB. when we handle unicode the offsets will be in wchars).
475  */
476 static BOOL PRINTDLG_CreateDevNames(HGLOBAL *hmem, const char* DeviceDriverName,
477  const char* DeviceName, const char* OutputPort)
478 {
479  long size;
480  char* pDevNamesSpace;
481  char* pTempPtr;
482  LPDEVNAMES lpDevNames;
483  char buf[260];
485  const char *p;
486 
487  p = strrchr( DeviceDriverName, '\\' );
488  if (p) DeviceDriverName = p + 1;
489 #ifndef __REACTOS__
490  size = strlen(DeviceDriverName) + 1
491 #else
492  size = strlen(cDriverName) + 1
493 #endif
494  + strlen(DeviceName) + 1
495  + strlen(OutputPort) + 1
496  + sizeof(DEVNAMES);
497 
498  if(*hmem)
499  *hmem = GlobalReAlloc(*hmem, size, GMEM_MOVEABLE);
500  else
501  *hmem = GlobalAlloc(GMEM_MOVEABLE, size);
502  if (*hmem == 0)
503  return FALSE;
504 
505  pDevNamesSpace = GlobalLock(*hmem);
506  lpDevNames = (LPDEVNAMES) pDevNamesSpace;
507 
508  pTempPtr = pDevNamesSpace + sizeof(DEVNAMES);
509 #ifndef __REACTOS__
510  strcpy(pTempPtr, DeviceDriverName);
511 #else
512  strcpy(pTempPtr, cDriverName);
513 #endif
514  lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
515 
516  pTempPtr += strlen(DeviceDriverName) + 1;
517  strcpy(pTempPtr, DeviceName);
518  lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
519 
520  pTempPtr += strlen(DeviceName) + 1;
521  strcpy(pTempPtr, OutputPort);
522  lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
523 
525  lpDevNames->wDefault = (strcmp(buf, DeviceName) == 0) ? 1 : 0;
526  GlobalUnlock(*hmem);
527  return TRUE;
528 }
529 
530 static BOOL PRINTDLG_CreateDevNamesW(HGLOBAL *hmem, LPCWSTR DeviceDriverName,
531  LPCWSTR DeviceName, LPCWSTR OutputPort)
532 {
533  long size;
534  LPWSTR pDevNamesSpace;
535  LPWSTR pTempPtr;
536  LPDEVNAMES lpDevNames;
537  WCHAR bufW[260];
538  DWORD dwBufLen = ARRAY_SIZE(bufW);
539  const WCHAR *p;
540 
541  p = wcsrchr( DeviceDriverName, '\\' );
542  if (p) DeviceDriverName = p + 1;
543 #ifndef __REACTOS__
544  size = sizeof(WCHAR)*lstrlenW(DeviceDriverName) + 2
545 #else
546  size = sizeof(WCHAR)*lstrlenW(wDriverName) + 2
547 #endif
548  + sizeof(WCHAR)*lstrlenW(DeviceName) + 2
549  + sizeof(WCHAR)*lstrlenW(OutputPort) + 2
550  + sizeof(DEVNAMES);
551 
552  if(*hmem)
553  *hmem = GlobalReAlloc(*hmem, size, GMEM_MOVEABLE);
554  else
555  *hmem = GlobalAlloc(GMEM_MOVEABLE, size);
556  if (*hmem == 0)
557  return FALSE;
558 
559  pDevNamesSpace = GlobalLock(*hmem);
560  lpDevNames = (LPDEVNAMES) pDevNamesSpace;
561 
562  pTempPtr = (LPWSTR)((LPDEVNAMES)pDevNamesSpace + 1);
563 #ifndef __REACTOS__
564  lstrcpyW(pTempPtr, DeviceDriverName);
565 #else
566  lstrcpyW(pTempPtr, wDriverName);
567 #endif
568  lpDevNames->wDriverOffset = pTempPtr - pDevNamesSpace;
569 
570  pTempPtr += lstrlenW(DeviceDriverName) + 1;
571  lstrcpyW(pTempPtr, DeviceName);
572  lpDevNames->wDeviceOffset = pTempPtr - pDevNamesSpace;
573 
574  pTempPtr += lstrlenW(DeviceName) + 1;
575  lstrcpyW(pTempPtr, OutputPort);
576  lpDevNames->wOutputOffset = pTempPtr - pDevNamesSpace;
577 
579  lpDevNames->wDefault = (lstrcmpW(bufW, DeviceName) == 0) ? 1 : 0;
580  GlobalUnlock(*hmem);
581  return TRUE;
582 }
583 
584 /***********************************************************************
585  * PRINTDLG_UpdatePrintDlg [internal]
586  *
587  *
588  * updates the PrintDlg structure for return values.
589  *
590  * RETURNS
591  * FALSE if user is not allowed to close (i.e. wrong nTo or nFrom values)
592  * TRUE if successful.
593  */
595  PRINT_PTRA* PrintStructures)
596 {
597  LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
598  PDEVMODEA lpdm = PrintStructures->lpDevMode;
599  LPPRINTER_INFO_2A pi = PrintStructures->lpPrinterInfo;
600 
601 
602  if(!lpdm) {
603  FIXME("No lpdm ptr?\n");
604  return FALSE;
605  }
606 
607 
608  if(!(lppd->Flags & PD_PRINTSETUP)) {
609  /* check whether nFromPage and nToPage are within range defined by
610  * nMinPage and nMaxPage
611  */
612  if (IsDlgButtonChecked(hDlg, rad3) == BST_CHECKED) { /* Pages */
613  WORD nToPage;
614  WORD nFromPage;
615  BOOL translated;
616  nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
617  nToPage = GetDlgItemInt(hDlg, edt2, &translated, FALSE);
618 
619  /* if no ToPage value is entered, use the FromPage value */
620  if(!translated) nToPage = nFromPage;
621 
622  if (nFromPage < lppd->nMinPage || nFromPage > lppd->nMaxPage ||
623  nToPage < lppd->nMinPage || nToPage > lppd->nMaxPage) {
624  WCHAR resourcestr[256];
625  WCHAR resultstr[256];
627  wsprintfW(resultstr,resourcestr, lppd->nMinPage, lppd->nMaxPage);
628  LoadStringW(COMDLG32_hInstance, PD32_PRINT_TITLE, resourcestr, 255);
629  MessageBoxW(hDlg, resultstr, resourcestr, MB_OK | MB_ICONWARNING);
630  return FALSE;
631  }
632  lppd->nFromPage = nFromPage;
633  lppd->nToPage = nToPage;
634  lppd->Flags |= PD_PAGENUMS;
635  }
636  else
637  lppd->Flags &= ~PD_PAGENUMS;
638 
639  if (IsDlgButtonChecked(hDlg, rad2) == BST_CHECKED) /* Selection */
640  lppd->Flags |= PD_SELECTION;
641  else
642  lppd->Flags &= ~PD_SELECTION;
643 
644  if (IsDlgButtonChecked(hDlg, chx1) == BST_CHECKED) {/* Print to file */
645  static char file[] = "FILE:";
646  lppd->Flags |= PD_PRINTTOFILE;
647  pi->pPortName = file;
648  }
649 
650  if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED) { /* Collate */
651  FIXME("Collate lppd not yet implemented as output\n");
652  }
653 
654  /* set PD_Collate and nCopies */
655  if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
656  /* The application doesn't support multiple copies or collate...
657  */
658  lppd->Flags &= ~PD_COLLATE;
659  lppd->nCopies = 1;
660  /* if the printer driver supports it... store info there
661  * otherwise no collate & multiple copies !
662  */
663  if (lpdm->dmFields & DM_COLLATE)
664  lpdm->dmCollate =
665  (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED);
666  if (lpdm->dmFields & DM_COPIES)
667  lpdm->u1.s1.dmCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
668  } else {
669  /* Application is responsible for multiple copies */
670  if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
671  lppd->Flags |= PD_COLLATE;
672  else
673  lppd->Flags &= ~PD_COLLATE;
674  lppd->nCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
675  /* multiple copies already included in the document. Driver must print only one copy */
676  lpdm->u1.s1.dmCopies = 1;
677  }
678 
679  /* Print quality, PrintDlg16 */
680  if(GetDlgItem(hDlg, cmb1))
681  {
682  HWND hQuality = GetDlgItem(hDlg, cmb1);
683  int Sel = SendMessageA(hQuality, CB_GETCURSEL, 0, 0);
684 
685  if(Sel != CB_ERR)
686  {
687  LONG dpi = SendMessageA(hQuality, CB_GETITEMDATA, Sel, 0);
689  lpdm->u1.s1.dmPrintQuality = LOWORD(dpi);
690  lpdm->dmYResolution = HIWORD(dpi);
691  }
692  }
693  }
694  return TRUE;
695 }
696 
698  PRINT_PTRW* PrintStructures)
699 {
700  LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
701  PDEVMODEW lpdm = PrintStructures->lpDevMode;
702  LPPRINTER_INFO_2W pi = PrintStructures->lpPrinterInfo;
703 
704 
705  if(!lpdm) {
706  FIXME("No lpdm ptr?\n");
707  return FALSE;
708  }
709 
710 
711  if(!(lppd->Flags & PD_PRINTSETUP)) {
712  /* check whether nFromPage and nToPage are within range defined by
713  * nMinPage and nMaxPage
714  */
715  if (IsDlgButtonChecked(hDlg, rad3) == BST_CHECKED) { /* Pages */
716  WORD nToPage;
717  WORD nFromPage;
718  BOOL translated;
719  nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
720  nToPage = GetDlgItemInt(hDlg, edt2, &translated, FALSE);
721 
722  /* if no ToPage value is entered, use the FromPage value */
723  if(!translated) nToPage = nFromPage;
724 
725  if (nFromPage < lppd->nMinPage || nFromPage > lppd->nMaxPage ||
726  nToPage < lppd->nMinPage || nToPage > lppd->nMaxPage) {
727  WCHAR resourcestr[256];
728  WCHAR resultstr[256];
729  DWORD_PTR args[2];
731  resourcestr, 255);
732  args[0] = lppd->nMinPage;
733  args[1] = lppd->nMaxPage;
735  resourcestr, 0, 0, resultstr,
736  ARRAY_SIZE(resultstr),
737  (__ms_va_list*)args);
739  resourcestr, 255);
740  MessageBoxW(hDlg, resultstr, resourcestr,
742  return FALSE;
743  }
744  lppd->nFromPage = nFromPage;
745  lppd->nToPage = nToPage;
746  lppd->Flags |= PD_PAGENUMS;
747  }
748  else
749  lppd->Flags &= ~PD_PAGENUMS;
750 
751  if (IsDlgButtonChecked(hDlg, rad2) == BST_CHECKED) /* Selection */
752  lppd->Flags |= PD_SELECTION;
753  else
754  lppd->Flags &= ~PD_SELECTION;
755 
756  if (IsDlgButtonChecked(hDlg, chx1) == BST_CHECKED) {/* Print to file */
757  static WCHAR file[] = {'F','I','L','E',':',0};
758  lppd->Flags |= PD_PRINTTOFILE;
759  pi->pPortName = file;
760  }
761 
762  if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED) { /* Collate */
763  FIXME("Collate lppd not yet implemented as output\n");
764  }
765 
766  /* set PD_Collate and nCopies */
767  if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
768  /* The application doesn't support multiple copies or collate...
769  */
770  lppd->Flags &= ~PD_COLLATE;
771  lppd->nCopies = 1;
772  /* if the printer driver supports it... store info there
773  * otherwise no collate & multiple copies !
774  */
775  if (lpdm->dmFields & DM_COLLATE)
776  lpdm->dmCollate =
777  (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED);
778  if (lpdm->dmFields & DM_COPIES)
779  lpdm->u1.s1.dmCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
780  } else {
781  if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
782  lppd->Flags |= PD_COLLATE;
783  else
784  lppd->Flags &= ~PD_COLLATE;
785  lppd->nCopies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
786  }
787  }
788  return TRUE;
789 }
790 
791 /************************************************************************
792  * PRINTDLG_SetUpPaperComboBox
793  *
794  * Initialize either the papersize or inputslot combos of the Printer Setup
795  * dialog. We store the associated word (eg DMPAPER_A4) as the item data.
796  * We also try to re-select the old selection.
797  */
799  int nIDComboBox,
800  char* PrinterName,
801  char* PortName,
802  LPDEVMODEA dm)
803 {
804  int i;
805  int NrOfEntries;
806  char* Names;
807  WORD* Words;
808  DWORD Sel, old_Sel;
809  WORD oldWord = 0, newWord = 0; /* DMPAPER_ and DMBIN_ start at 1 */
810  int NamesSize;
811  int fwCapability_Names;
812  int fwCapability_Words;
813 
814  TRACE(" Printer: %s, Port: %s, ComboID: %d\n",PrinterName,PortName,nIDComboBox);
815 
816  /* query the dialog box for the current selected value */
817  Sel = SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETCURSEL, 0, 0);
818  if(Sel != CB_ERR) {
819  /* we enter here only if a different printer is selected after
820  * the Print Setup dialog is opened. The current settings are
821  * stored into the newly selected printer.
822  */
823  oldWord = SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA,
824  Sel, 0);
825  if(oldWord >= DMPAPER_USER) /* DMPAPER_USER == DMBIN_USER */
826  oldWord = 0; /* There's no point in trying to keep custom
827  paper / bin sizes across printers */
828  }
829 
830  if (dm)
831  newWord = (nIDComboBox == cmb2) ? dm->u1.s1.dmPaperSize : dm->u1.s1.dmDefaultSource;
832 
833  if (nIDComboBox == cmb2) {
834  NamesSize = 64;
835  fwCapability_Names = DC_PAPERNAMES;
836  fwCapability_Words = DC_PAPERS;
837  } else {
838  nIDComboBox = cmb3;
839  NamesSize = 24;
840  fwCapability_Names = DC_BINNAMES;
841  fwCapability_Words = DC_BINS;
842  }
843 
844  NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
845  fwCapability_Names, NULL, dm);
846  if (NrOfEntries == 0)
847  WARN("no Name Entries found!\n");
848  else if (NrOfEntries < 0)
849  return FALSE;
850 
851  if(DeviceCapabilitiesA(PrinterName, PortName, fwCapability_Words, NULL, dm)
852  != NrOfEntries) {
853  ERR("Number of caps is different\n");
854  NrOfEntries = 0;
855  }
856 
857  Names = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(char)*NamesSize);
858  Words = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WORD));
859  DeviceCapabilitiesA(PrinterName, PortName, fwCapability_Names, Names, dm);
860  NrOfEntries = DeviceCapabilitiesA(PrinterName, PortName,
861  fwCapability_Words, (LPSTR)Words, dm);
862 
863  /* reset any current content in the combobox */
864  SendDlgItemMessageA(hDlg, nIDComboBox, CB_RESETCONTENT, 0, 0);
865 
866  /* store new content */
867  for (i = 0; i < NrOfEntries; i++) {
868  DWORD pos = SendDlgItemMessageA(hDlg, nIDComboBox, CB_ADDSTRING, 0,
869  (LPARAM)(&Names[i*NamesSize]) );
870  SendDlgItemMessageA(hDlg, nIDComboBox, CB_SETITEMDATA, pos,
871  Words[i]);
872  }
873 
874  /* Look for old selection or the new default.
875  Can't do this is previous loop since item order will change as more items are added */
876  Sel = 0;
877  old_Sel = NrOfEntries;
878  for (i = 0; i < NrOfEntries; i++) {
879  if(SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) ==
880  oldWord) {
881  old_Sel = i;
882  break;
883  }
884  if(SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) == newWord)
885  Sel = i;
886  }
887 
888  if(old_Sel < NrOfEntries)
889  {
890  if (dm)
891  {
892  if(nIDComboBox == cmb2)
893  dm->u1.s1.dmPaperSize = oldWord;
894  else
895  dm->u1.s1.dmDefaultSource = oldWord;
896  }
897  Sel = old_Sel;
898  }
899 
900  SendDlgItemMessageA(hDlg, nIDComboBox, CB_SETCURSEL, Sel, 0);
901 
902  HeapFree(GetProcessHeap(),0,Words);
904  return TRUE;
905 }
906 
908  int nIDComboBox,
909  const WCHAR* PrinterName,
910  const WCHAR* PortName,
911  LPDEVMODEW dm)
912 {
913  int i;
914  int NrOfEntries;
915  WCHAR* Names;
916  WORD* Words;
917  DWORD Sel, old_Sel;
918  WORD oldWord = 0, newWord = 0; /* DMPAPER_ and DMBIN_ start at 1 */
919  int NamesSize;
920  int fwCapability_Names;
921  int fwCapability_Words;
922 
923  TRACE(" Printer: %s, Port: %s, ComboID: %d\n",debugstr_w(PrinterName),debugstr_w(PortName),nIDComboBox);
924 
925  /* query the dialog box for the current selected value */
926  Sel = SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETCURSEL, 0, 0);
927  if(Sel != CB_ERR) {
928  /* we enter here only if a different printer is selected after
929  * the Print Setup dialog is opened. The current settings are
930  * stored into the newly selected printer.
931  */
932  oldWord = SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETITEMDATA,
933  Sel, 0);
934 
935  if(oldWord >= DMPAPER_USER) /* DMPAPER_USER == DMBIN_USER */
936  oldWord = 0; /* There's no point in trying to keep custom
937  paper / bin sizes across printers */
938  }
939 
940  if (dm)
941  newWord = (nIDComboBox == cmb2) ? dm->u1.s1.dmPaperSize : dm->u1.s1.dmDefaultSource;
942 
943  if (nIDComboBox == cmb2) {
944  NamesSize = 64;
945  fwCapability_Names = DC_PAPERNAMES;
946  fwCapability_Words = DC_PAPERS;
947  } else {
948  nIDComboBox = cmb3;
949  NamesSize = 24;
950  fwCapability_Names = DC_BINNAMES;
951  fwCapability_Words = DC_BINS;
952  }
953 
954  NrOfEntries = DeviceCapabilitiesW(PrinterName, PortName,
955  fwCapability_Names, NULL, dm);
956  if (NrOfEntries == 0)
957  WARN("no Name Entries found!\n");
958  else if (NrOfEntries < 0)
959  return FALSE;
960 
961  if(DeviceCapabilitiesW(PrinterName, PortName, fwCapability_Words, NULL, dm)
962  != NrOfEntries) {
963  ERR("Number of caps is different\n");
964  NrOfEntries = 0;
965  }
966 
967  Names = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WCHAR)*NamesSize);
968  Words = HeapAlloc(GetProcessHeap(),0, NrOfEntries*sizeof(WORD));
969  DeviceCapabilitiesW(PrinterName, PortName, fwCapability_Names, Names, dm);
970  NrOfEntries = DeviceCapabilitiesW(PrinterName, PortName,
971  fwCapability_Words, Words, dm);
972 
973  /* reset any current content in the combobox */
974  SendDlgItemMessageW(hDlg, nIDComboBox, CB_RESETCONTENT, 0, 0);
975 
976  /* store new content */
977  for (i = 0; i < NrOfEntries; i++) {
978  DWORD pos = SendDlgItemMessageW(hDlg, nIDComboBox, CB_ADDSTRING, 0,
979  (LPARAM)(&Names[i*NamesSize]) );
980  SendDlgItemMessageW(hDlg, nIDComboBox, CB_SETITEMDATA, pos,
981  Words[i]);
982  }
983 
984  /* Look for old selection or the new default.
985  Can't do this is previous loop since item order will change as more items are added */
986  Sel = 0;
987  old_Sel = NrOfEntries;
988  for (i = 0; i < NrOfEntries; i++) {
989  if(SendDlgItemMessageW(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) ==
990  oldWord) {
991  old_Sel = i;
992  break;
993  }
994  if(SendDlgItemMessageA(hDlg, nIDComboBox, CB_GETITEMDATA, i, 0) == newWord)
995  Sel = i;
996  }
997 
998  if(old_Sel < NrOfEntries)
999  {
1000  if (dm)
1001  {
1002  if(nIDComboBox == cmb2)
1003  dm->u1.s1.dmPaperSize = oldWord;
1004  else
1005  dm->u1.s1.dmDefaultSource = oldWord;
1006  }
1007  Sel = old_Sel;
1008  }
1009 
1010  SendDlgItemMessageW(hDlg, nIDComboBox, CB_SETCURSEL, Sel, 0);
1011 
1012  HeapFree(GetProcessHeap(),0,Words);
1014  return TRUE;
1015 }
1016 
1017 
1018 /***********************************************************************
1019  * PRINTDLG_UpdatePrinterInfoTexts [internal]
1020  */
1022 {
1023  char StatusMsg[256];
1024  char ResourceString[256];
1025  int i;
1026 
1027  /* Status Message */
1028  StatusMsg[0]='\0';
1029 
1030  /* add all status messages */
1031  for (i = 0; i < 25; i++) {
1032  if (pi->Status & (1<<i)) {
1034  ResourceString, 255);
1035  strcat(StatusMsg,ResourceString);
1036  }
1037  }
1038  /* append "ready" */
1039  /* FIXME: status==ready must only be appended if really so.
1040  but how to detect? */
1042  ResourceString, 255);
1043  strcat(StatusMsg,ResourceString);
1044  SetDlgItemTextA(hDlg, stc12, StatusMsg);
1045 
1046  /* set all other printer info texts */
1047  SetDlgItemTextA(hDlg, stc11, pi->pDriverName);
1048 
1049  if (pi->pLocation != NULL && pi->pLocation[0] != '\0')
1050  SetDlgItemTextA(hDlg, stc14, pi->pLocation);
1051  else
1052  SetDlgItemTextA(hDlg, stc14, pi->pPortName);
1053  SetDlgItemTextA(hDlg, stc13, pi->pComment ? pi->pComment : "");
1054  return;
1055 }
1056 
1058 {
1059  WCHAR StatusMsg[256];
1060  WCHAR ResourceString[256];
1061  static const WCHAR emptyW[] = {0};
1062  int i;
1063 
1064  /* Status Message */
1065  StatusMsg[0]='\0';
1066 
1067  /* add all status messages */
1068  for (i = 0; i < 25; i++) {
1069  if (pi->Status & (1<<i)) {
1071  ResourceString, 255);
1072  lstrcatW(StatusMsg,ResourceString);
1073  }
1074  }
1075  /* append "ready" */
1076  /* FIXME: status==ready must only be appended if really so.
1077  but how to detect? */
1079  ResourceString, 255);
1080  lstrcatW(StatusMsg,ResourceString);
1081  SetDlgItemTextW(hDlg, stc12, StatusMsg);
1082 
1083  /* set all other printer info texts */
1084  SetDlgItemTextW(hDlg, stc11, pi->pDriverName);
1085  if (pi->pLocation != NULL && pi->pLocation[0] != '\0')
1086  SetDlgItemTextW(hDlg, stc14, pi->pLocation);
1087  else
1088  SetDlgItemTextW(hDlg, stc14, pi->pPortName);
1089  SetDlgItemTextW(hDlg, stc13, pi->pComment ? pi->pComment : emptyW);
1090 }
1091 
1092 
1093 /*******************************************************************
1094  *
1095  * PRINTDLG_ChangePrinter
1096  *
1097  */
1098 static BOOL PRINTDLG_ChangePrinterA(HWND hDlg, char *name, PRINT_PTRA *PrintStructures)
1099 {
1100  LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
1101  LPDEVMODEA lpdm = NULL;
1102  LONG dmSize;
1103  DWORD needed;
1104  HANDLE hprn;
1105 
1106  HeapFree(GetProcessHeap(),0, PrintStructures->lpPrinterInfo);
1107  HeapFree(GetProcessHeap(),0, PrintStructures->lpDriverInfo);
1108  if(!OpenPrinterA(name, &hprn, NULL)) {
1109  ERR("Can't open printer %s\n", name);
1110  return FALSE;
1111  }
1112  GetPrinterA(hprn, 2, NULL, 0, &needed);
1113  PrintStructures->lpPrinterInfo = HeapAlloc(GetProcessHeap(),0,needed);
1114  GetPrinterA(hprn, 2, (LPBYTE)PrintStructures->lpPrinterInfo, needed,
1115  &needed);
1116  GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
1117  PrintStructures->lpDriverInfo = HeapAlloc(GetProcessHeap(),0,needed);
1118  if (!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)PrintStructures->lpDriverInfo,
1119  needed, &needed)) {
1120  ERR("GetPrinterDriverA failed for %s, fix your config!\n",PrintStructures->lpPrinterInfo->pPrinterName);
1121  return FALSE;
1122  }
1123  ClosePrinter(hprn);
1124 
1125  PRINTDLG_UpdatePrinterInfoTextsA(hDlg, PrintStructures->lpPrinterInfo);
1126 
1127  HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
1128  PrintStructures->lpDevMode = NULL;
1129 
1130  dmSize = DocumentPropertiesA(0, 0, name, NULL, NULL, 0);
1131  if(dmSize == -1) {
1132  ERR("DocumentProperties fails on %s\n", debugstr_a(name));
1133  return FALSE;
1134  }
1135  PrintStructures->lpDevMode = HeapAlloc(GetProcessHeap(), 0, dmSize);
1136  dmSize = DocumentPropertiesA(0, 0, name, PrintStructures->lpDevMode, NULL,
1137  DM_OUT_BUFFER);
1138  if(lppd->hDevMode && (lpdm = GlobalLock(lppd->hDevMode)) &&
1139  !lstrcmpA( (LPSTR) lpdm->dmDeviceName,
1140  (LPSTR) PrintStructures->lpDevMode->dmDeviceName)) {
1141  /* Supplied devicemode matches current printer so try to use it */
1142  DocumentPropertiesA(0, 0, name, PrintStructures->lpDevMode, lpdm,
1144  }
1145  if(lpdm)
1146  GlobalUnlock(lppd->hDevMode);
1147 
1148  lpdm = PrintStructures->lpDevMode; /* use this as a shortcut */
1149 
1150  if(!(lppd->Flags & PD_PRINTSETUP)) {
1151  /* Print range (All/Range/Selection) */
1152  if(lppd->nFromPage != 0xffff)
1153  SetDlgItemInt(hDlg, edt1, lppd->nFromPage, FALSE);
1154  if(lppd->nToPage != 0xffff)
1155  SetDlgItemInt(hDlg, edt2, lppd->nToPage, FALSE);
1156 
1157  CheckRadioButton(hDlg, rad1, rad3, rad1); /* default */
1158  if (lppd->Flags & PD_NOSELECTION)
1159  EnableWindow(GetDlgItem(hDlg, rad2), FALSE);
1160  else
1161  if (lppd->Flags & PD_SELECTION)
1162  CheckRadioButton(hDlg, rad1, rad3, rad2);
1163  if (lppd->Flags & PD_NOPAGENUMS) {
1164  EnableWindow(GetDlgItem(hDlg, rad3), FALSE);
1166  EnableWindow(GetDlgItem(hDlg, edt1), FALSE);
1168  EnableWindow(GetDlgItem(hDlg, edt2), FALSE);
1169  } else {
1170  if (lppd->Flags & PD_PAGENUMS)
1171  CheckRadioButton(hDlg, rad1, rad3, rad3);
1172  }
1173 
1174  /* Collate pages
1175  *
1176  * FIXME: The ico3 is not displayed for some reason. I don't know why.
1177  */
1178  if (lppd->Flags & PD_COLLATE) {
1180  (LPARAM)PrintStructures->hCollateIcon);
1181  CheckDlgButton(hDlg, chx2, 1);
1182  } else {
1184  (LPARAM)PrintStructures->hNoCollateIcon);
1185  CheckDlgButton(hDlg, chx2, 0);
1186  }
1187 
1188  if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
1189  /* if printer doesn't support it: no Collate */
1190  if (!(lpdm->dmFields & DM_COLLATE)) {
1191  EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1192  EnableWindow(GetDlgItem(hDlg, ico3), FALSE);
1193  }
1194  }
1195 
1196  /* nCopies */
1197  {
1198  INT copies;
1199  if (lppd->hDevMode == 0)
1200  copies = lppd->nCopies;
1201  else
1202  copies = lpdm->u1.s1.dmCopies;
1203  if(copies == 0) copies = 1;
1204  else if(copies < 0) copies = MAX_COPIES;
1205  SetDlgItemInt(hDlg, edt3, copies, FALSE);
1206  }
1207 
1208  if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
1209  /* if printer doesn't support it: no nCopies */
1210  if (!(lpdm->dmFields & DM_COPIES)) {
1211  EnableWindow(GetDlgItem(hDlg, edt3), FALSE);
1212  EnableWindow(GetDlgItem(hDlg, stc5), FALSE);
1213  }
1214  }
1215 
1216  /* print to file */
1217  CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0);
1218  if (lppd->Flags & PD_DISABLEPRINTTOFILE)
1219  EnableWindow(GetDlgItem(hDlg, chx1), FALSE);
1220  if (lppd->Flags & PD_HIDEPRINTTOFILE)
1221  ShowWindow(GetDlgItem(hDlg, chx1), SW_HIDE);
1222 
1223  /* Fill print quality combo, PrintDlg16 */
1224  if(GetDlgItem(hDlg, cmb1))
1225  {
1226  DWORD numResolutions = DeviceCapabilitiesA(PrintStructures->lpPrinterInfo->pPrinterName,
1227  PrintStructures->lpPrinterInfo->pPortName,
1228  DC_ENUMRESOLUTIONS, NULL, lpdm);
1229 
1230  if(numResolutions != -1)
1231  {
1232  HWND hQuality = GetDlgItem(hDlg, cmb1);
1233  LONG* Resolutions;
1234  char buf[255];
1235  DWORD i;
1236  int dpiX, dpiY;
1237  HDC hPrinterDC = CreateDCA(PrintStructures->lpPrinterInfo->pDriverName,
1238  PrintStructures->lpPrinterInfo->pPrinterName,
1239  0, lpdm);
1240 
1241  Resolutions = HeapAlloc(GetProcessHeap(), 0, numResolutions*sizeof(LONG)*2);
1243  PrintStructures->lpPrinterInfo->pPortName,
1244  DC_ENUMRESOLUTIONS, (LPSTR)Resolutions, lpdm);
1245 
1246  dpiX = GetDeviceCaps(hPrinterDC, LOGPIXELSX);
1247  dpiY = GetDeviceCaps(hPrinterDC, LOGPIXELSY);
1248  DeleteDC(hPrinterDC);
1249 
1250  SendMessageA(hQuality, CB_RESETCONTENT, 0, 0);
1251  for(i = 0; i < (numResolutions * 2); i += 2)
1252  {
1253  BOOL IsDefault = FALSE;
1254  LRESULT Index;
1255 
1256  if(Resolutions[i] == Resolutions[i+1])
1257  {
1258  if(dpiX == Resolutions[i])
1259  IsDefault = TRUE;
1260  sprintf(buf, "%d dpi", Resolutions[i]);
1261  } else
1262  {
1263  if(dpiX == Resolutions[i] && dpiY == Resolutions[i+1])
1264  IsDefault = TRUE;
1265  sprintf(buf, "%d dpi x %d dpi", Resolutions[i], Resolutions[i+1]);
1266  }
1267 
1268  Index = SendMessageA(hQuality, CB_ADDSTRING, 0, (LPARAM)buf);
1269 
1270  if(IsDefault)
1271  SendMessageA(hQuality, CB_SETCURSEL, Index, 0);
1272 
1273  SendMessageA(hQuality, CB_SETITEMDATA, Index, MAKELONG(dpiX,dpiY));
1274  }
1275  HeapFree(GetProcessHeap(), 0, Resolutions);
1276  }
1277  }
1278  } else { /* PD_PRINTSETUP */
1279  BOOL bPortrait = (lpdm->u1.s1.dmOrientation == DMORIENT_PORTRAIT);
1280 
1282  PrintStructures->lpPrinterInfo->pPrinterName,
1283  PrintStructures->lpPrinterInfo->pPortName,
1284  lpdm);
1286  PrintStructures->lpPrinterInfo->pPrinterName,
1287  PrintStructures->lpPrinterInfo->pPortName,
1288  lpdm);
1289  CheckRadioButton(hDlg, rad1, rad2, bPortrait ? rad1: rad2);
1291  (LPARAM)(bPortrait ? PrintStructures->hPortraitIcon :
1292  PrintStructures->hLandscapeIcon));
1293 
1294  }
1295 
1296  /* help button */
1297  if ((lppd->Flags & PD_SHOWHELP)==0) {
1298  /* hide if PD_SHOWHELP not specified */
1300  }
1301  return TRUE;
1302 }
1303 
1305  PRINT_PTRW *PrintStructures)
1306 {
1307  LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
1308  LPDEVMODEW lpdm = NULL;
1309  LONG dmSize;
1310  DWORD needed;
1311  HANDLE hprn;
1312 
1313  HeapFree(GetProcessHeap(),0, PrintStructures->lpPrinterInfo);
1314  HeapFree(GetProcessHeap(),0, PrintStructures->lpDriverInfo);
1315  if(!OpenPrinterW(name, &hprn, NULL)) {
1316  ERR("Can't open printer %s\n", debugstr_w(name));
1317  return FALSE;
1318  }
1319  GetPrinterW(hprn, 2, NULL, 0, &needed);
1320  PrintStructures->lpPrinterInfo = HeapAlloc(GetProcessHeap(),0,needed);
1321  GetPrinterW(hprn, 2, (LPBYTE)PrintStructures->lpPrinterInfo, needed,
1322  &needed);
1323  GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
1324  PrintStructures->lpDriverInfo = HeapAlloc(GetProcessHeap(),0,needed);
1325  if (!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)PrintStructures->lpDriverInfo,
1326  needed, &needed)) {
1327  ERR("GetPrinterDriverA failed for %s, fix your config!\n",debugstr_w(PrintStructures->lpPrinterInfo->pPrinterName));
1328  return FALSE;
1329  }
1330  ClosePrinter(hprn);
1331 
1332  PRINTDLG_UpdatePrinterInfoTextsW(hDlg, PrintStructures->lpPrinterInfo);
1333 
1334  HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
1335  PrintStructures->lpDevMode = NULL;
1336 
1337  dmSize = DocumentPropertiesW(0, 0, name, NULL, NULL, 0);
1338  if(dmSize == -1) {
1339  ERR("DocumentProperties fails on %s\n", debugstr_w(name));
1340  return FALSE;
1341  }
1342  PrintStructures->lpDevMode = HeapAlloc(GetProcessHeap(), 0, dmSize);
1343  dmSize = DocumentPropertiesW(0, 0, name, PrintStructures->lpDevMode, NULL,
1344  DM_OUT_BUFFER);
1345  if(lppd->hDevMode && (lpdm = GlobalLock(lppd->hDevMode)) &&
1346  !lstrcmpW(lpdm->dmDeviceName,
1347  PrintStructures->lpDevMode->dmDeviceName)) {
1348  /* Supplied devicemode matches current printer so try to use it */
1349  DocumentPropertiesW(0, 0, name, PrintStructures->lpDevMode, lpdm,
1351  }
1352  if(lpdm)
1353  GlobalUnlock(lppd->hDevMode);
1354 
1355  lpdm = PrintStructures->lpDevMode; /* use this as a shortcut */
1356 
1357  if(!(lppd->Flags & PD_PRINTSETUP)) {
1358  /* Print range (All/Range/Selection) */
1359  if(lppd->nFromPage != 0xffff)
1360  SetDlgItemInt(hDlg, edt1, lppd->nFromPage, FALSE);
1361  if(lppd->nToPage != 0xffff)
1362  SetDlgItemInt(hDlg, edt2, lppd->nToPage, FALSE);
1363 
1364  CheckRadioButton(hDlg, rad1, rad3, rad1); /* default */
1365  if (lppd->Flags & PD_NOSELECTION)
1366  EnableWindow(GetDlgItem(hDlg, rad2), FALSE);
1367  else
1368  if (lppd->Flags & PD_SELECTION)
1369  CheckRadioButton(hDlg, rad1, rad3, rad2);
1370  if (lppd->Flags & PD_NOPAGENUMS) {
1371  EnableWindow(GetDlgItem(hDlg, rad3), FALSE);
1373  EnableWindow(GetDlgItem(hDlg, edt1), FALSE);
1375  EnableWindow(GetDlgItem(hDlg, edt2), FALSE);
1376  } else {
1377  if (lppd->Flags & PD_PAGENUMS)
1378  CheckRadioButton(hDlg, rad1, rad3, rad3);
1379  }
1380 
1381  /* Collate pages
1382  *
1383  * FIXME: The ico3 is not displayed for some reason. I don't know why.
1384  */
1385  if (lppd->Flags & PD_COLLATE) {
1387  (LPARAM)PrintStructures->hCollateIcon);
1388  CheckDlgButton(hDlg, chx2, 1);
1389  } else {
1391  (LPARAM)PrintStructures->hNoCollateIcon);
1392  CheckDlgButton(hDlg, chx2, 0);
1393  }
1394 
1395  if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
1396  /* if printer doesn't support it: no Collate */
1397  if (!(lpdm->dmFields & DM_COLLATE)) {
1398  EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1399  EnableWindow(GetDlgItem(hDlg, ico3), FALSE);
1400  }
1401  }
1402 
1403  /* nCopies */
1404  {
1405  INT copies;
1406  if (lppd->hDevMode == 0)
1407  copies = lppd->nCopies;
1408  else
1409  copies = lpdm->u1.s1.dmCopies;
1410  if(copies == 0) copies = 1;
1411  else if(copies < 0) copies = MAX_COPIES;
1412  SetDlgItemInt(hDlg, edt3, copies, FALSE);
1413  }
1414 
1415  if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
1416  /* if printer doesn't support it: no nCopies */
1417  if (!(lpdm->dmFields & DM_COPIES)) {
1418  EnableWindow(GetDlgItem(hDlg, edt3), FALSE);
1419  EnableWindow(GetDlgItem(hDlg, stc5), FALSE);
1420  }
1421  }
1422 
1423  /* print to file */
1424  CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0);
1425  if (lppd->Flags & PD_DISABLEPRINTTOFILE)
1426  EnableWindow(GetDlgItem(hDlg, chx1), FALSE);
1427  if (lppd->Flags & PD_HIDEPRINTTOFILE)
1428  ShowWindow(GetDlgItem(hDlg, chx1), SW_HIDE);
1429 
1430  } else { /* PD_PRINTSETUP */
1431  BOOL bPortrait = (lpdm->u1.s1.dmOrientation == DMORIENT_PORTRAIT);
1432 
1434  PrintStructures->lpPrinterInfo->pPrinterName,
1435  PrintStructures->lpPrinterInfo->pPortName,
1436  lpdm);
1438  PrintStructures->lpPrinterInfo->pPrinterName,
1439  PrintStructures->lpPrinterInfo->pPortName,
1440  lpdm);
1441  CheckRadioButton(hDlg, rad1, rad2, bPortrait ? rad1: rad2);
1443  (LPARAM)(bPortrait ? PrintStructures->hPortraitIcon :
1444  PrintStructures->hLandscapeIcon));
1445 
1446  }
1447 
1448  /* help button */
1449  if ((lppd->Flags & PD_SHOWHELP)==0) {
1450  /* hide if PD_SHOWHELP not specified */
1452  }
1453  return TRUE;
1454 }
1455 
1456  /***********************************************************************
1457  * check_printer_setup [internal]
1458  */
1460 {
1461  DWORD needed,num;
1462  WCHAR resourcestr[256],resultstr[256];
1463 
1464  EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
1465  if(needed == 0)
1466  {
1467  EnumPrintersW(PRINTER_ENUM_CONNECTIONS, NULL, 2, NULL, 0, &needed, &num);
1468  }
1469  if(needed > 0)
1470  return TRUE;
1471  else
1472  {
1474  LoadStringW(COMDLG32_hInstance, PD32_PRINT_TITLE,resourcestr, 255);
1475  MessageBoxW(hDlg, resultstr, resourcestr,MB_OK | MB_ICONWARNING);
1476  return FALSE;
1477  }
1478 }
1479 
1480 /***********************************************************************
1481  * PRINTDLG_WMInitDialog [internal]
1482  */
1484  PRINT_PTRA* PrintStructures)
1485 {
1486  LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
1487  DEVNAMES *pdn;
1488  DEVMODEA *pdm;
1489  char *name = NULL;
1490  UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1491 
1492  /* load Collate ICONs */
1493  /* We load these with LoadImage because they are not a standard
1494  size and we don't want them rescaled */
1495  PrintStructures->hCollateIcon =
1496  LoadImageA(COMDLG32_hInstance, "PD32_COLLATE", IMAGE_ICON, 0, 0, 0);
1497  PrintStructures->hNoCollateIcon =
1498  LoadImageA(COMDLG32_hInstance, "PD32_NOCOLLATE", IMAGE_ICON, 0, 0, 0);
1499 
1500  /* These can be done with LoadIcon */
1501  PrintStructures->hPortraitIcon =
1502  LoadIconA(COMDLG32_hInstance, "PD32_PORTRAIT");
1503  PrintStructures->hLandscapeIcon =
1504  LoadIconA(COMDLG32_hInstance, "PD32_LANDSCAPE");
1505 
1506  /* display the collate/no_collate icon */
1508  (LPARAM)PrintStructures->hNoCollateIcon);
1509 
1510  if(PrintStructures->hCollateIcon == 0 ||
1511  PrintStructures->hNoCollateIcon == 0 ||
1512  PrintStructures->hPortraitIcon == 0 ||
1513  PrintStructures->hLandscapeIcon == 0) {
1514  ERR("no icon in resource file\n");
1516  EndDialog(hDlg, FALSE);
1517  }
1518 
1519  /*
1520  * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
1521  * must be registered and the Help button must be shown.
1522  */
1523  if (lppd->Flags & PD_SHOWHELP) {
1524  if((PrintStructures->HelpMessageID =
1527  return FALSE;
1528  }
1529  } else
1530  PrintStructures->HelpMessageID = 0;
1531 
1532  if(!(lppd->Flags &PD_PRINTSETUP)) {
1533  PrintStructures->hwndUpDown =
1536  UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 0, 0, 0, 0,
1538  GetDlgItem(hDlg, edt3), MAX_COPIES, 1, 1);
1539  }
1540 
1541  /* FIXME: I allow more freedom than either Win95 or WinNT,
1542  * which do not agree on what errors should be thrown or not
1543  * in case nToPage or nFromPage is out-of-range.
1544  */
1545  if (lppd->nMaxPage < lppd->nMinPage)
1546  lppd->nMaxPage = lppd->nMinPage;
1547  if (lppd->nMinPage == lppd->nMaxPage)
1548  lppd->Flags |= PD_NOPAGENUMS;
1549  if (lppd->nToPage < lppd->nMinPage)
1550  lppd->nToPage = lppd->nMinPage;
1551  if (lppd->nToPage > lppd->nMaxPage)
1552  lppd->nToPage = lppd->nMaxPage;
1553  if (lppd->nFromPage < lppd->nMinPage)
1554  lppd->nFromPage = lppd->nMinPage;
1555  if (lppd->nFromPage > lppd->nMaxPage)
1556  lppd->nFromPage = lppd->nMaxPage;
1557 
1558  /* if we have the combo box, fill it */
1559  if (GetDlgItem(hDlg,comboID)) {
1560  /* Fill Combobox
1561  */
1562  pdn = GlobalLock(lppd->hDevNames);
1563  pdm = GlobalLock(lppd->hDevMode);
1564  if(pdn)
1565  name = (char*)pdn + pdn->wDeviceOffset;
1566  else if(pdm)
1567  name = (char*)pdm->dmDeviceName;
1568  PRINTDLG_SetUpPrinterListComboA(hDlg, comboID, name);
1569  if(pdm) GlobalUnlock(lppd->hDevMode);
1570  if(pdn) GlobalUnlock(lppd->hDevNames);
1571 
1572  /* Now find selected printer and update rest of dlg */
1573  name = HeapAlloc(GetProcessHeap(),0,256);
1574  if (GetDlgItemTextA(hDlg, comboID, name, 255))
1575  PRINTDLG_ChangePrinterA(hDlg, name, PrintStructures);
1577  } else {
1578  /* else use default printer */
1579  char name[200];
1582 
1583  if (ret)
1584  PRINTDLG_ChangePrinterA(hDlg, name, PrintStructures);
1585  else
1586  FIXME("No default printer found, expect problems!\n");
1587  }
1588  return TRUE;
1589 }
1590 
1592  PRINT_PTRW* PrintStructures)
1593 {
1594  LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
1595  DEVNAMES *pdn;
1596  DEVMODEW *pdm;
1597  WCHAR *name = NULL;
1598  UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1599 
1600  /* load Collate ICONs */
1601  /* We load these with LoadImage because they are not a standard
1602  size and we don't want them rescaled */
1603  PrintStructures->hCollateIcon =
1605  PrintStructures->hNoCollateIcon =
1607 
1608  /* These can be done with LoadIcon */
1609  PrintStructures->hPortraitIcon =
1611  PrintStructures->hLandscapeIcon =
1613 
1614  /* display the collate/no_collate icon */
1616  (LPARAM)PrintStructures->hNoCollateIcon);
1617 
1618  if(PrintStructures->hCollateIcon == 0 ||
1619  PrintStructures->hNoCollateIcon == 0 ||
1620  PrintStructures->hPortraitIcon == 0 ||
1621  PrintStructures->hLandscapeIcon == 0) {
1622  ERR("no icon in resource file\n");
1624  EndDialog(hDlg, FALSE);
1625  }
1626 
1627  /*
1628  * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
1629  * must be registered and the Help button must be shown.
1630  */
1631  if (lppd->Flags & PD_SHOWHELP) {
1632  if((PrintStructures->HelpMessageID =
1635  return FALSE;
1636  }
1637  } else
1638  PrintStructures->HelpMessageID = 0;
1639 
1640  if(!(lppd->Flags &PD_PRINTSETUP)) {
1641  PrintStructures->hwndUpDown =
1644  UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 0, 0, 0, 0,
1646  GetDlgItem(hDlg, edt3), MAX_COPIES, 1, 1);
1647  }
1648 
1649  /* FIXME: I allow more freedom than either Win95 or WinNT,
1650  * which do not agree to what errors should be thrown or not
1651  * in case nToPage or nFromPage is out-of-range.
1652  */
1653  if (lppd->nMaxPage < lppd->nMinPage)
1654  lppd->nMaxPage = lppd->nMinPage;
1655  if (lppd->nMinPage == lppd->nMaxPage)
1656  lppd->Flags |= PD_NOPAGENUMS;
1657  if (lppd->nToPage < lppd->nMinPage)
1658  lppd->nToPage = lppd->nMinPage;
1659  if (lppd->nToPage > lppd->nMaxPage)
1660  lppd->nToPage = lppd->nMaxPage;
1661  if (lppd->nFromPage < lppd->nMinPage)
1662  lppd->nFromPage = lppd->nMinPage;
1663  if (lppd->nFromPage > lppd->nMaxPage)
1664  lppd->nFromPage = lppd->nMaxPage;
1665 
1666  /* if we have the combo box, fill it */
1667  if (GetDlgItem(hDlg,comboID)) {
1668  /* Fill Combobox
1669  */
1670  pdn = GlobalLock(lppd->hDevNames);
1671  pdm = GlobalLock(lppd->hDevMode);
1672  if(pdn)
1673  name = (WCHAR*)pdn + pdn->wDeviceOffset;
1674  else if(pdm)
1675  name = pdm->dmDeviceName;
1676  PRINTDLG_SetUpPrinterListComboW(hDlg, comboID, name);
1677  if(pdm) GlobalUnlock(lppd->hDevMode);
1678  if(pdn) GlobalUnlock(lppd->hDevNames);
1679 
1680  /* Now find selected printer and update rest of dlg */
1681  /* ansi is ok here */
1682  name = HeapAlloc(GetProcessHeap(),0,256*sizeof(WCHAR));
1683  if (GetDlgItemTextW(hDlg, comboID, name, 255))
1684  PRINTDLG_ChangePrinterW(hDlg, name, PrintStructures);
1686  } else {
1687  /* else use default printer */
1688  WCHAR name[200];
1691 
1692  if (ret)
1693  PRINTDLG_ChangePrinterW(hDlg, name, PrintStructures);
1694  else
1695  FIXME("No default printer found, expect problems!\n");
1696  }
1697  return TRUE;
1698 }
1699 
1700 /***********************************************************************
1701  * PRINTDLG_WMCommand [internal]
1702  */
1704  PRINT_PTRA* PrintStructures)
1705 {
1706  LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
1707  UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1708  LPDEVMODEA lpdm = PrintStructures->lpDevMode;
1709 
1710  switch (LOWORD(wParam)) {
1711  case IDOK:
1712  TRACE(" OK button was hit\n");
1713  if (!PRINTDLG_UpdatePrintDlgA(hDlg, PrintStructures)) {
1714  FIXME("Update printdlg was not successful!\n");
1715  return(FALSE);
1716  }
1717  EndDialog(hDlg, TRUE);
1718  return(TRUE);
1719 
1720  case IDCANCEL:
1721  TRACE(" CANCEL button was hit\n");
1722  EndDialog(hDlg, FALSE);
1723  return(FALSE);
1724 
1725  case pshHelp:
1726  TRACE(" HELP button was hit\n");
1727  SendMessageA(lppd->hwndOwner, PrintStructures->HelpMessageID,
1728  (WPARAM) hDlg, (LPARAM) lppd);
1729  break;
1730 
1731  case chx2: /* collate pages checkbox */
1732  if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
1734  (LPARAM)PrintStructures->hCollateIcon);
1735  else
1737  (LPARAM)PrintStructures->hNoCollateIcon);
1738  break;
1739  case edt1: /* from page nr editbox */
1740  case edt2: /* to page nr editbox */
1741  if (HIWORD(wParam)==EN_CHANGE) {
1742  WORD nToPage;
1743  WORD nFromPage;
1744  nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
1745  nToPage = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
1746  if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
1747  CheckRadioButton(hDlg, rad1, rad3, rad3);
1748  }
1749  break;
1750 
1751  case edt3:
1752  if(HIWORD(wParam) == EN_CHANGE) {
1753  INT copies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
1754  if(copies <= 1)
1755  EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1756  else
1757  EnableWindow(GetDlgItem(hDlg, chx2), TRUE);
1758  }
1759  break;
1760 
1761  case psh2: /* Properties button */
1762  {
1763  HANDLE hPrinter;
1764  char PrinterName[256];
1765 
1766  GetDlgItemTextA(hDlg, PrinterComboID, PrinterName, 255);
1767  if (!OpenPrinterA(PrinterName, &hPrinter, NULL)) {
1768  FIXME(" Call to OpenPrinter did not succeed!\n");
1769  break;
1770  }
1771  DocumentPropertiesA(hDlg, hPrinter, PrinterName,
1772  PrintStructures->lpDevMode,
1773  PrintStructures->lpDevMode,
1775  ClosePrinter(hPrinter);
1776  break;
1777  }
1778 
1779  case rad1: /* Paperorientation */
1780  if (lppd->Flags & PD_PRINTSETUP)
1781  {
1782  lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1784  (LPARAM)(PrintStructures->hPortraitIcon));
1785  }
1786  break;
1787 
1788  case rad2: /* Paperorientation */
1789  if (lppd->Flags & PD_PRINTSETUP)
1790  {
1791  lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1793  (LPARAM)(PrintStructures->hLandscapeIcon));
1794  }
1795  break;
1796 
1797  case cmb1: /* Printer Combobox in PRINT SETUP, quality combobox in PRINT16 */
1798  if (PrinterComboID != LOWORD(wParam)) {
1799  break;
1800  }
1801  /* FALLTHROUGH */
1802  case cmb4: /* Printer combobox */
1803  if (HIWORD(wParam)==CBN_SELCHANGE) {
1804  char *PrinterName;
1807  PrinterName = HeapAlloc(GetProcessHeap(),0,length+1);
1808  SendDlgItemMessageA(hDlg, LOWORD(wParam), CB_GETLBTEXT, index, (LPARAM)PrinterName);
1809  PRINTDLG_ChangePrinterA(hDlg, PrinterName, PrintStructures);
1810  HeapFree(GetProcessHeap(),0,PrinterName);
1811  }
1812  break;
1813 
1814  case cmb2: /* Papersize */
1815  {
1816  DWORD Sel = SendDlgItemMessageA(hDlg, cmb2, CB_GETCURSEL, 0, 0);
1817  if(Sel != CB_ERR) {
1818  lpdm->u1.s1.dmPaperSize = SendDlgItemMessageA(hDlg, cmb2,
1820  Sel, 0);
1821  GetDlgItemTextA(hDlg, cmb2, (char *)lpdm->dmFormName, CCHFORMNAME);
1822  }
1823  }
1824  break;
1825 
1826  case cmb3: /* Bin */
1827  {
1828  DWORD Sel = SendDlgItemMessageA(hDlg, cmb3, CB_GETCURSEL, 0, 0);
1829  if(Sel != CB_ERR)
1830  lpdm->u1.s1.dmDefaultSource = SendDlgItemMessageA(hDlg, cmb3,
1831  CB_GETITEMDATA, Sel,
1832  0);
1833  }
1834  break;
1835  }
1836  if(lppd->Flags & PD_PRINTSETUP) {
1837  switch (LOWORD(wParam)) {
1838  case rad1: /* orientation */
1839  case rad2:
1840  if (IsDlgButtonChecked(hDlg, rad1) == BST_CHECKED) {
1841  if(lpdm->u1.s1.dmOrientation != DMORIENT_PORTRAIT) {
1842  lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1844  (LPARAM)PrintStructures->hPortraitIcon);
1846  (LPARAM)PrintStructures->hPortraitIcon);
1847  }
1848  } else {
1849  if(lpdm->u1.s1.dmOrientation != DMORIENT_LANDSCAPE) {
1850  lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1852  (LPARAM)PrintStructures->hLandscapeIcon);
1854  (LPARAM)PrintStructures->hLandscapeIcon);
1855  }
1856  }
1857  break;
1858  }
1859  }
1860  return FALSE;
1861 }
1862 
1864  PRINT_PTRW* PrintStructures)
1865 {
1866  LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
1867  UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1868  LPDEVMODEW lpdm = PrintStructures->lpDevMode;
1869 
1870  switch (LOWORD(wParam)) {
1871  case IDOK:
1872  TRACE(" OK button was hit\n");
1873  if (!PRINTDLG_UpdatePrintDlgW(hDlg, PrintStructures)) {
1874  FIXME("Update printdlg was not successful!\n");
1875  return(FALSE);
1876  }
1877  EndDialog(hDlg, TRUE);
1878  return(TRUE);
1879 
1880  case IDCANCEL:
1881  TRACE(" CANCEL button was hit\n");
1882  EndDialog(hDlg, FALSE);
1883  return(FALSE);
1884 
1885  case pshHelp:
1886  TRACE(" HELP button was hit\n");
1887  SendMessageW(lppd->hwndOwner, PrintStructures->HelpMessageID,
1888  (WPARAM) hDlg, (LPARAM) lppd);
1889  break;
1890 
1891  case chx2: /* collate pages checkbox */
1892  if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
1894  (LPARAM)PrintStructures->hCollateIcon);
1895  else
1897  (LPARAM)PrintStructures->hNoCollateIcon);
1898  break;
1899  case edt1: /* from page nr editbox */
1900  case edt2: /* to page nr editbox */
1901  if (HIWORD(wParam)==EN_CHANGE) {
1902  WORD nToPage;
1903  WORD nFromPage;
1904  nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
1905  nToPage = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
1906  if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
1907  CheckRadioButton(hDlg, rad1, rad3, rad3);
1908  }
1909  break;
1910 
1911  case edt3:
1912  if(HIWORD(wParam) == EN_CHANGE) {
1913  INT copies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
1914  if(copies <= 1)
1915  EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1916  else
1917  EnableWindow(GetDlgItem(hDlg, chx2), TRUE);
1918  }
1919  break;
1920 
1921  case psh2: /* Properties button */
1922  {
1923  HANDLE hPrinter;
1924  WCHAR PrinterName[256];
1925 
1926  if (!GetDlgItemTextW(hDlg, PrinterComboID, PrinterName, 255)) break;
1927  if (!OpenPrinterW(PrinterName, &hPrinter, NULL)) {
1928  FIXME(" Call to OpenPrinter did not succeed!\n");
1929  break;
1930  }
1931  DocumentPropertiesW(hDlg, hPrinter, PrinterName,
1932  PrintStructures->lpDevMode,
1933  PrintStructures->lpDevMode,
1935  ClosePrinter(hPrinter);
1936  break;
1937  }
1938 
1939  case rad1: /* Paperorientation */
1940  if (lppd->Flags & PD_PRINTSETUP)
1941  {
1942  lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1944  (LPARAM)(PrintStructures->hPortraitIcon));
1945  }
1946  break;
1947 
1948  case rad2: /* Paperorientation */
1949  if (lppd->Flags & PD_PRINTSETUP)
1950  {
1951  lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1953  (LPARAM)(PrintStructures->hLandscapeIcon));
1954  }
1955  break;
1956 
1957  case cmb1: /* Printer Combobox in PRINT SETUP */
1958  /* FALLTHROUGH */
1959  case cmb4: /* Printer combobox */
1960  if (HIWORD(wParam)==CBN_SELCHANGE) {
1961  WCHAR *PrinterName;
1964 
1965  PrinterName = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(length+1));
1966  SendDlgItemMessageW(hDlg, LOWORD(wParam), CB_GETLBTEXT, index, (LPARAM)PrinterName);
1967  PRINTDLG_ChangePrinterW(hDlg, PrinterName, PrintStructures);
1968  HeapFree(GetProcessHeap(),0,PrinterName);
1969  }
1970  break;
1971 
1972  case cmb2: /* Papersize */
1973  {
1974  DWORD Sel = SendDlgItemMessageW(hDlg, cmb2, CB_GETCURSEL, 0, 0);
1975  if(Sel != CB_ERR) {
1976  lpdm->u1.s1.dmPaperSize = SendDlgItemMessageW(hDlg, cmb2,
1978  Sel, 0);
1979  GetDlgItemTextW(hDlg, cmb2, lpdm->dmFormName, CCHFORMNAME);
1980  }
1981  }
1982  break;
1983 
1984  case cmb3: /* Bin */
1985  {
1986  DWORD Sel = SendDlgItemMessageW(hDlg, cmb3, CB_GETCURSEL, 0, 0);
1987  if(Sel != CB_ERR)
1988  lpdm->u1.s1.dmDefaultSource = SendDlgItemMessageW(hDlg, cmb3,
1989  CB_GETITEMDATA, Sel,
1990  0);
1991  }
1992  break;
1993  }
1994  if(lppd->Flags & PD_PRINTSETUP) {
1995  switch (LOWORD(wParam)) {
1996  case rad1: /* orientation */
1997  case rad2:
1998  if (IsDlgButtonChecked(hDlg, rad1) == BST_CHECKED) {
1999  if(lpdm->u1.s1.dmOrientation != DMORIENT_PORTRAIT) {
2000  lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
2002  (LPARAM)PrintStructures->hPortraitIcon);
2004  (LPARAM)PrintStructures->hPortraitIcon);
2005  }
2006  } else {
2007  if(lpdm->u1.s1.dmOrientation != DMORIENT_LANDSCAPE) {
2008  lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
2010  (LPARAM)PrintStructures->hLandscapeIcon);
2012  (LPARAM)PrintStructures->hLandscapeIcon);
2013  }
2014  }
2015  break;
2016  }
2017  }
2018  return FALSE;
2019 }
2020 
2021 /***********************************************************************
2022  * PrintDlgProcA [internal]
2023  */
2025  LPARAM lParam)
2026 {
2027  PRINT_PTRA* PrintStructures;
2028  INT_PTR res = FALSE;
2029 
2030  if (uMsg!=WM_INITDIALOG) {
2031  PrintStructures = GetPropW(hDlg, printdlg_prop);
2032  if (!PrintStructures)
2033  return FALSE;
2034  } else {
2035  PrintStructures = (PRINT_PTRA*) lParam;
2036  SetPropW(hDlg, printdlg_prop, PrintStructures);
2037  if(!check_printer_setup(hDlg))
2038  {
2039  EndDialog(hDlg,FALSE);
2040  return FALSE;
2041  }
2042  res = PRINTDLG_WMInitDialog(hDlg, PrintStructures);
2043 
2044  if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK)
2045  res = PrintStructures->lpPrintDlg->lpfnPrintHook(
2046  hDlg, uMsg, wParam, (LPARAM)PrintStructures->lpPrintDlg
2047  );
2048  return res;
2049  }
2050 
2051  if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) {
2052  res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg,uMsg,wParam,
2053  lParam);
2054  if(res) return res;
2055  }
2056 
2057  switch (uMsg) {
2058  case WM_COMMAND:
2059  return PRINTDLG_WMCommandA(hDlg, wParam, PrintStructures);
2060 
2061  case WM_DESTROY:
2062  DestroyIcon(PrintStructures->hCollateIcon);
2063  DestroyIcon(PrintStructures->hNoCollateIcon);
2064  DestroyIcon(PrintStructures->hPortraitIcon);
2065  DestroyIcon(PrintStructures->hLandscapeIcon);
2066  if(PrintStructures->hwndUpDown)
2067  DestroyWindow(PrintStructures->hwndUpDown);
2068  return FALSE;
2069  }
2070  return res;
2071 }
2072 
2074  LPARAM lParam)
2075 {
2076  PRINT_PTRW* PrintStructures;
2077  INT_PTR res = FALSE;
2078 
2079  if (uMsg!=WM_INITDIALOG) {
2080  PrintStructures = GetPropW(hDlg, printdlg_prop);
2081  if (!PrintStructures)
2082  return FALSE;
2083  } else {
2084  PrintStructures = (PRINT_PTRW*) lParam;
2085  SetPropW(hDlg, printdlg_prop, PrintStructures);
2086  if(!check_printer_setup(hDlg))
2087  {
2088  EndDialog(hDlg,FALSE);
2089  return FALSE;
2090  }
2091  res = PRINTDLG_WMInitDialogW(hDlg, PrintStructures);
2092 
2093  if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK)
2094  res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg, uMsg, wParam, (LPARAM)PrintStructures->lpPrintDlg);
2095  return res;
2096  }
2097 
2098  if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) {
2099  res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg,uMsg,wParam, lParam);
2100  if(res) return res;
2101  }
2102 
2103  switch (uMsg) {
2104  case WM_COMMAND:
2105  return PRINTDLG_WMCommandW(hDlg, wParam, PrintStructures);
2106 
2107  case WM_DESTROY:
2108  DestroyIcon(PrintStructures->hCollateIcon);
2109  DestroyIcon(PrintStructures->hNoCollateIcon);
2110  DestroyIcon(PrintStructures->hPortraitIcon);
2111  DestroyIcon(PrintStructures->hLandscapeIcon);
2112  if(PrintStructures->hwndUpDown)
2113  DestroyWindow(PrintStructures->hwndUpDown);
2114  return FALSE;
2115  }
2116  return res;
2117 }
2118 
2119 /************************************************************
2120  *
2121  * PRINTDLG_GetDlgTemplate
2122  *
2123  */
2125 {
2126  HRSRC hResInfo;
2127  HGLOBAL hDlgTmpl;
2128 
2129  if (lppd->Flags & PD_PRINTSETUP) {
2130  if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
2131  hDlgTmpl = lppd->hSetupTemplate;
2132  } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {
2133  hResInfo = FindResourceA(lppd->hInstance,
2135  hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2136  } else {
2137  hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32_SETUP",
2138  (LPSTR)RT_DIALOG);
2139  hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
2140  }
2141  } else {
2142  if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
2143  hDlgTmpl = lppd->hPrintTemplate;
2144  } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
2145  hResInfo = FindResourceA(lppd->hInstance,
2146  lppd->lpPrintTemplateName,
2147  (LPSTR)RT_DIALOG);
2148  hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2149  } else {
2150  hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32",
2151  (LPSTR)RT_DIALOG);
2152  hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
2153  }
2154  }
2155  return hDlgTmpl;
2156 }
2157 
2159 {
2160  HRSRC hResInfo;
2161  HGLOBAL hDlgTmpl;
2162  static const WCHAR xpsetup[] = { 'P','R','I','N','T','3','2','_','S','E','T','U','P',0};
2163  static const WCHAR xprint[] = { 'P','R','I','N','T','3','2',0};
2164 
2165  if (lppd->Flags & PD_PRINTSETUP) {
2166  if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
2167  hDlgTmpl = lppd->hSetupTemplate;
2168  } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {
2169  hResInfo = FindResourceW(lppd->hInstance,
2171  hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2172  } else {
2173  hResInfo = FindResourceW(COMDLG32_hInstance, xpsetup, (LPWSTR)RT_DIALOG);
2174  hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
2175  }
2176  } else {
2177  if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
2178  hDlgTmpl = lppd->hPrintTemplate;
2179  } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
2180  hResInfo = FindResourceW(lppd->hInstance,
2181  lppd->lpPrintTemplateName,
2182  (LPWSTR)RT_DIALOG);
2183  hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2184  } else {
2185  hResInfo = FindResourceW(COMDLG32_hInstance, xprint, (LPWSTR)RT_DIALOG);
2186  hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
2187  }
2188  }
2189  return hDlgTmpl;
2190 }
2191 
2192 /***********************************************************************
2193  *
2194  * PRINTDLG_CreateDC
2195  *
2196  */
2198 {
2199  DEVNAMES *pdn = GlobalLock(lppd->hDevNames);
2200  DEVMODEA *pdm = GlobalLock(lppd->hDevMode);
2201 
2202  if(lppd->Flags & PD_RETURNDC) {
2203  lppd->hDC = CreateDCA((char*)pdn + pdn->wDriverOffset,
2204  (char*)pdn + pdn->wDeviceOffset,
2205  (char*)pdn + pdn->wOutputOffset,
2206  pdm );
2207  } else if(lppd->Flags & PD_RETURNIC) {
2208  lppd->hDC = CreateICA((char*)pdn + pdn->wDriverOffset,
2209  (char*)pdn + pdn->wDeviceOffset,
2210  (char*)pdn + pdn->wOutputOffset,
2211  pdm );
2212  }
2213  GlobalUnlock(lppd->hDevNames);
2214  GlobalUnlock(lppd->hDevMode);
2215  return lppd->hDC != NULL;
2216 }
2217 
2219 {
2220  DEVNAMES *pdn = GlobalLock(lppd->hDevNames);
2221  DEVMODEW *pdm = GlobalLock(lppd->hDevMode);
2222 
2223  if(lppd->Flags & PD_RETURNDC) {
2224  lppd->hDC = CreateDCW((WCHAR*)pdn + pdn->wDriverOffset,
2225  (WCHAR*)pdn + pdn->wDeviceOffset,
2226  (WCHAR*)pdn + pdn->wOutputOffset,
2227  pdm );
2228  } else if(lppd->Flags & PD_RETURNIC) {
2229  lppd->hDC = CreateICW((WCHAR*)pdn + pdn->wDriverOffset,
2230  (WCHAR*)pdn + pdn->wDeviceOffset,
2231  (WCHAR*)pdn + pdn->wOutputOffset,
2232  pdm );
2233  }
2234  GlobalUnlock(lppd->hDevNames);
2235  GlobalUnlock(lppd->hDevMode);
2236  return lppd->hDC != NULL;
2237 }
2238 
2239 /***********************************************************************
2240  * PrintDlgA (COMDLG32.@)
2241  *
2242  * Displays the PRINT dialog box, which enables the user to specify
2243  * specific properties of the print job.
2244  *
2245  * PARAMS
2246  * lppd [IO] ptr to PRINTDLG32 struct
2247  *
2248  * RETURNS
2249  * nonzero if the user pressed the OK button
2250  * zero if the user cancelled the window or an error occurred
2251  *
2252  * BUGS
2253  * PrintDlg:
2254  * * The Collate Icons do not display, even though they are in the code.
2255  * * The Properties Button(s) should call DocumentPropertiesA().
2256  */
2257 
2259 {
2260  BOOL bRet = FALSE;
2261  LPVOID ptr;
2262  HINSTANCE hInst;
2263 
2264  if (!lppd)
2265  {
2267  return FALSE;
2268  }
2269 
2270  if(TRACE_ON(commdlg)) {
2271  char flagstr[1000] = "";
2272  const struct pd_flags *pflag = pd_flags;
2273  for( ; pflag->name; pflag++) {
2274  if(lppd->Flags & pflag->flag)
2275  strcat(flagstr, pflag->name);
2276  }
2277  TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
2278  "pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
2279  "flags %08x (%s)\n",
2280  lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
2281  lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
2282  lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
2283  }
2284 
2285  if(lppd->lStructSize != sizeof(PRINTDLGA)) {
2286  WARN("structure size failure!!!\n");
2288  return FALSE;
2289  }
2290 
2291  if(lppd->Flags & PD_RETURNDEFAULT) {
2293  DRIVER_INFO_3A *dbuf;
2294  HANDLE hprn;
2295  DWORD needed;
2296 
2297  if(lppd->hDevMode || lppd->hDevNames) {
2298  WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
2300  return FALSE;
2301  }
2302  if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
2303  WARN("Can't find default printer\n");
2305  return FALSE;
2306  }
2307 
2308  GetPrinterA(hprn, 2, NULL, 0, &needed);
2309  pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
2310  GetPrinterA(hprn, 2, (LPBYTE)pbuf, needed, &needed);
2311 
2312  GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
2313  dbuf = HeapAlloc(GetProcessHeap(),0,needed);
2314  if (!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) {
2315  ERR("GetPrinterDriverA failed, le %d, fix your config for printer %s!\n",
2316  GetLastError(),pbuf->pPrinterName);
2317  HeapFree(GetProcessHeap(), 0, dbuf);
2318  HeapFree(GetProcessHeap(), 0, pbuf);
2320  return FALSE;
2321  }
2322  ClosePrinter(hprn);
2323 
2325  dbuf->pDriverPath,
2326  pbuf->pPrinterName,
2327  pbuf->pPortName);
2328  lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
2329  pbuf->pDevMode->dmDriverExtra);
2330  ptr = GlobalLock(lppd->hDevMode);
2331  memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
2332  pbuf->pDevMode->dmDriverExtra);
2333  GlobalUnlock(lppd->hDevMode);
2334  HeapFree(GetProcessHeap(), 0, pbuf);
2335  HeapFree(GetProcessHeap(), 0, dbuf);
2336  bRet = TRUE;
2337  } else {
2338  HGLOBAL hDlgTmpl;
2339  PRINT_PTRA *PrintStructures;
2340 
2341  /* load Dialog resources,
2342  * depending on Flags indicates Print32 or Print32_setup dialog
2343  */
2344  hDlgTmpl = PRINTDLG_GetDlgTemplateA(lppd);
2345  if (!hDlgTmpl) {
2347  return FALSE;
2348  }
2349  ptr = LockResource( hDlgTmpl );
2350  if (!ptr) {
2352  return FALSE;
2353  }
2354 
2355  PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2356  sizeof(PRINT_PTRA));
2357  PrintStructures->lpPrintDlg = lppd;
2358 
2359  /* and create & process the dialog .
2360  * -1 is failure, 0 is broken hwnd, everything else is ok.
2361  */
2364  bRet = (0<DialogBoxIndirectParamA(hInst, ptr, lppd->hwndOwner,
2365  PrintDlgProcA,
2366  (LPARAM)PrintStructures));
2367 
2368  if(bRet) {
2369  DEVMODEA *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
2370  PRINTER_INFO_2A *pi = PrintStructures->lpPrinterInfo;
2371  DRIVER_INFO_3A *di = PrintStructures->lpDriverInfo;
2372 
2373  if (lppd->hDevMode == 0) {
2374  TRACE(" No hDevMode yet... Need to create my own\n");
2376  lpdm->dmSize + lpdm->dmDriverExtra);
2377  } else {
2378  lppd->hDevMode = GlobalReAlloc(lppd->hDevMode,
2379  lpdm->dmSize + lpdm->dmDriverExtra,
2380  GMEM_MOVEABLE);
2381  }
2382  lpdmReturn = GlobalLock(lppd->hDevMode);
2383  memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
2384 
2386  di->pDriverPath,
2387  pi->pPrinterName,
2388  pi->pPortName
2389  );
2390  GlobalUnlock(lppd->hDevMode);
2391  }
2392  HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
2393  HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
2394  HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo);
2395  HeapFree(GetProcessHeap(), 0, PrintStructures);
2396  }
2397  if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
2398  bRet = PRINTDLG_CreateDCA(lppd);
2399 
2400  TRACE("exit! (%d)\n", bRet);
2401  return bRet;
2402 }
2403 
2404 /***********************************************************************
2405  * PrintDlgW (COMDLG32.@)
2406  *
2407  * See PrintDlgA.
2408  */
2410 {
2411  BOOL bRet = FALSE;
2412  LPVOID ptr;
2413  HINSTANCE hInst;
2414 
2415  if (!lppd)
2416  {
2418  return FALSE;
2419  }
2420 
2421  if(TRACE_ON(commdlg)) {
2422  char flagstr[1000] = "";
2423  const struct pd_flags *pflag = pd_flags;
2424  for( ; pflag->name; pflag++) {
2425  if(lppd->Flags & pflag->flag)
2426  strcat(flagstr, pflag->name);
2427  }
2428  TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
2429  "pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
2430  "flags %08x (%s)\n",
2431  lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
2432  lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
2433  lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
2434  }
2435 
2436  if(lppd->lStructSize != sizeof(PRINTDLGW)) {
2437  WARN("structure size failure!!!\n");
2439  return FALSE;
2440  }
2441 
2442  if(lppd->Flags & PD_RETURNDEFAULT) {
2444  DRIVER_INFO_3W *dbuf;
2445  HANDLE hprn;
2446  DWORD needed;
2447 
2448  if(lppd->hDevMode || lppd->hDevNames) {
2449  WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
2451  return FALSE;
2452  }
2453  if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
2454  WARN("Can't find default printer\n");
2456  return FALSE;
2457  }
2458 
2459  GetPrinterW(hprn, 2, NULL, 0, &needed);
2460  pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
2461  GetPrinterW(hprn, 2, (LPBYTE)pbuf, needed, &needed);
2462 
2463  GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
2464  dbuf = HeapAlloc(GetProcessHeap(),0,needed);
2465  if (!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) {
2466  ERR("GetPrinterDriverA failed, le %d, fix your config for printer %s!\n",
2467  GetLastError(),debugstr_w(pbuf->pPrinterName));
2468  HeapFree(GetProcessHeap(), 0, dbuf);
2469  HeapFree(GetProcessHeap(), 0, pbuf);
2471  return FALSE;
2472  }
2473  ClosePrinter(hprn);
2474 
2476  dbuf->pDriverPath,
2477  pbuf->pPrinterName,
2478  pbuf->pPortName);
2479  lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
2480  pbuf->pDevMode->dmDriverExtra);
2481  ptr = GlobalLock(lppd->hDevMode);
2482  memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
2483  pbuf->pDevMode->dmDriverExtra);
2484  GlobalUnlock(lppd->hDevMode);
2485  HeapFree(GetProcessHeap(), 0, pbuf);
2486  HeapFree(GetProcessHeap(), 0, dbuf);
2487  bRet = TRUE;
2488  } else {
2489  HGLOBAL hDlgTmpl;
2490  PRINT_PTRW *PrintStructures;
2491 
2492  /* load Dialog resources,
2493  * depending on Flags indicates Print32 or Print32_setup dialog
2494  */
2495  hDlgTmpl = PRINTDLG_GetDlgTemplateW(lppd);
2496  if (!hDlgTmpl) {
2498  return FALSE;
2499  }
2500  ptr = LockResource( hDlgTmpl );
2501  if (!ptr) {
2503  return FALSE;
2504  }
2505 
2506  PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2507  sizeof(PRINT_PTRW));
2508  PrintStructures->lpPrintDlg = lppd;
2509 
2510  /* and create & process the dialog .
2511  * -1 is failure, 0 is broken hwnd, everything else is ok.
2512  */
2515  bRet = (0<DialogBoxIndirectParamW(hInst, ptr, lppd->hwndOwner,
2516  PrintDlgProcW,
2517  (LPARAM)PrintStructures));
2518 
2519  if(bRet) {
2520  DEVMODEW *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
2521  PRINTER_INFO_2W *pi = PrintStructures->lpPrinterInfo;
2522  DRIVER_INFO_3W *di = PrintStructures->lpDriverInfo;
2523 
2524  if (lppd->hDevMode == 0) {
2525  TRACE(" No hDevMode yet... Need to create my own\n");
2527  lpdm->dmSize + lpdm->dmDriverExtra);
2528  } else {
2529  WORD locks;
2530  if((locks = (GlobalFlags(lppd->hDevMode) & GMEM_LOCKCOUNT))) {
2531  WARN("hDevMode has %d locks on it. Unlocking it now\n", locks);
2532  while(locks--) {
2533  GlobalUnlock(lppd->hDevMode);
2534  TRACE("Now got %d locks\n", locks);
2535  }
2536  }
2537  lppd->hDevMode = GlobalReAlloc(lppd->hDevMode,
2538  lpdm->dmSize + lpdm->dmDriverExtra,
2539  GMEM_MOVEABLE);
2540  }
2541  lpdmReturn = GlobalLock(lppd->hDevMode);
2542  memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
2543 
2544  if (lppd->hDevNames != 0) {
2545  WORD locks;
2546  if((locks = (GlobalFlags(lppd->hDevNames) & GMEM_LOCKCOUNT))) {
2547  WARN("hDevNames has %d locks on it. Unlocking it now\n", locks);
2548  while(locks--)
2549  GlobalUnlock(lppd->hDevNames);
2550  }
2551  }
2553  di->pDriverPath,
2554  pi->pPrinterName,
2555  pi->pPortName
2556  );
2557  GlobalUnlock(lppd->hDevMode);
2558  }
2559  HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
2560  HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
2561  HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo);
2562  HeapFree(GetProcessHeap(), 0, PrintStructures);
2563  }
2564  if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
2565  bRet = PRINTDLG_CreateDCW(lppd);
2566 
2567  TRACE("exit! (%d)\n", bRet);
2568  return bRet;
2569 }
2570 
2571 /***********************************************************************
2572  *
2573  * PageSetupDlg
2574  * rad1 - portrait
2575  * rad2 - landscape
2576  * cmb1 - printer select (not in standard dialog template)
2577  * cmb2 - paper size
2578  * cmb3 - source (tray?)
2579  * edt4 - border left
2580  * edt5 - border top
2581  * edt6 - border right
2582  * edt7 - border bottom
2583  * psh3 - "Printer..."
2584  */
2585 
2586 typedef struct
2587 {
2589  union
2590  {
2593  } u;
2594  HWND hDlg; /* Page Setup dialog handle */
2595  RECT rtDrawRect; /* Drawing rect for page */
2596 } pagesetup_data;
2597 
2599 {
2600  return data->u.dlgw->Flags;
2601 }
2602 
2603 static inline BOOL is_metric(const pagesetup_data *data)
2604 {
2606 }
2607 
2609 {
2610  if (is_metric(data))
2611  return 10 * size;
2612  else
2613  return 10 * size * 100 / 254;
2614 }
2615 
2617 {
2618  if (is_metric(data))
2619  return size * 254 / 100;
2620  else
2621  return size;
2622 }
2623 
2625 {
2626  static WCHAR sep;
2627 
2628  if(!sep)
2629  {
2630  WCHAR buf[] = {'.', 0};
2632  sep = buf[0];
2633  }
2634  return sep;
2635 }
2636 
2637 static void size2str(const pagesetup_data *data, DWORD size, LPWSTR strout)
2638 {
2639  static const WCHAR integer_fmt[] = {'%','d',0};
2640  static const WCHAR hundredths_fmt[] = {'%','d','%','c','%','0','2','d',0};
2641  static const WCHAR thousandths_fmt[] = {'%','d','%','c','%','0','3','d',0};
2642 
2643  /* FIXME use LOCALE_SDECIMAL when the edit parsing code can cope */
2644 
2645  if (is_metric(data))
2646  {
2647  if(size % 100)
2648  wsprintfW(strout, hundredths_fmt, size / 100, get_decimal_sep(), size % 100);
2649  else
2650  wsprintfW(strout, integer_fmt, size / 100);
2651  }
2652  else
2653  {
2654  if(size % 1000)
2655  wsprintfW(strout, thousandths_fmt, size / 1000, get_decimal_sep(), size % 1000);
2656  else
2657  wsprintfW(strout, integer_fmt, size / 1000);
2658 
2659  }
2660 }
2661 
2662 static inline BOOL is_default_metric(void)
2663 {
2664  DWORD system;
2665  GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_IMEASURE | LOCALE_RETURN_NUMBER,
2666  (LPWSTR)&system, sizeof(system));
2667  return system == 0;
2668 }
2669 
2670 /**********************************************
2671  * rotate_rect
2672  * Cyclically permute the four members of rc
2673  * If sense is TRUE l -> t -> r -> b
2674  * otherwise l <- t <- r <- b
2675  */
2676 static inline void rotate_rect(RECT *rc, BOOL sense)
2677 {
2678  INT tmp;
2679  if(sense)
2680  {
2681  tmp = rc->bottom;
2682  rc->bottom = rc->right;
2683  rc->right = rc->top;
2684  rc->top = rc->left;
2685  rc->left = tmp;
2686  }
2687  else
2688  {
2689  tmp = rc->left;
2690  rc->left = rc->top;
2691  rc->top = rc->right;
2692  rc->right = rc->bottom;
2693  rc->bottom = tmp;
2694  }
2695 }
2696 
2698 {
2699  DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
2700 
2701  assert(orient == DMORIENT_PORTRAIT || orient == DMORIENT_LANDSCAPE);
2702 
2703  if(data->unicode)
2704  dm->u1.s1.dmOrientation = orient;
2705  else
2706  {
2707  DEVMODEA *dmA = (DEVMODEA *)dm;
2708  dmA->u1.s1.dmOrientation = orient;
2709  }
2710  GlobalUnlock(data->u.dlgw->hDevMode);
2711 }
2712 
2714 {
2715  DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
2716  WORD orient;
2717 
2718  if(data->unicode)
2719  orient = dm->u1.s1.dmOrientation;
2720  else
2721  {
2722  DEVMODEA *dmA = (DEVMODEA *)dm;
2723  orient = dmA->u1.s1.dmOrientation;
2724  }
2725  GlobalUnlock(data->u.dlgw->hDevMode);
2726  return orient;
2727 }
2728 
2730 {
2731  DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
2732 
2733  if(data->unicode)
2734  dm->u1.s1.dmPaperSize = paper;
2735  else
2736  {
2737  DEVMODEA *dmA = (DEVMODEA *)dm;
2738  dmA->u1.s1.dmPaperSize = paper;
2739  }
2740  GlobalUnlock(data->u.dlgw->hDevMode);
2741 }
2742 
2744 {
2745  DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
2746  WORD paper;
2747 
2748  if(data->unicode)
2749  paper = dm->u1.s1.dmPaperSize;
2750  else
2751  {
2752  DEVMODEA *dmA = (DEVMODEA *)dm;
2753  paper = dmA->u1.s1.dmPaperSize;
2754  }
2755  GlobalUnlock(data->u.dlgw->hDevMode);
2756  return paper;
2757 }
2758 
2760 {
2761  DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
2762 
2763  if(data->unicode)
2764  dm->u1.s1.dmDefaultSource = source;
2765  else
2766  {
2767  DEVMODEA *dmA = (DEVMODEA *)dm;
2768  dmA->u1.s1.dmDefaultSource = source;
2769  }
2770  GlobalUnlock(data->u.dlgw->hDevMode);
2771 }
2772 
2773 typedef enum
2774 {
2778 } devnames_name;
2779 
2780 
2782 {
2783  switch(which)
2784  {
2785  case devnames_driver_name: return dn->wDriverOffset;
2786  case devnames_device_name: return dn->wDeviceOffset;
2787  case devnames_output_name: return dn->wOutputOffset;
2788  }
2789  ERR("Shouldn't be here\n");
2790  return 0;
2791 }
2792 
2794 {
2795  DEVNAMES *dn;
2796  WCHAR *name;
2797 
2798  dn = GlobalLock(data->u.dlgw->hDevNames);
2799  if(data->unicode)
2800  name = strdupW((WCHAR *)dn + get_devname_offset(dn, which));
2801  else
2802  {
2803  int len = MultiByteToWideChar(CP_ACP, 0, (char*)dn + get_devname_offset(dn, which), -1, NULL, 0);
2804  name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2805  MultiByteToWideChar(CP_ACP, 0, (char*)dn + get_devname_offset(dn, which), -1, name, len);
2806  }
2807  GlobalUnlock(data->u.dlgw->hDevNames);
2808  return name;
2809 }
2810 
2812 {
2814 }
2815 
2817 {
2819 }
2820 
2822 {
2824 }
2825 
2827 {
2828  HeapFree(GetProcessHeap(), 0, name);
2829 }
2830 
2832 {
2833  DEVNAMES *dn;
2834  WCHAR def[256];
2835  DWORD len = sizeof(DEVNAMES), drv_len, dev_len, port_len;
2836 
2837  if(data->unicode)
2838  {
2839  drv_len = (lstrlenW(drv) + 1) * sizeof(WCHAR);
2840  dev_len = (lstrlenW(devname) + 1) * sizeof(WCHAR);
2841  port_len = (lstrlenW(port) + 1) * sizeof(WCHAR);
2842  }
2843  else
2844  {
2845  drv_len = WideCharToMultiByte(CP_ACP, 0, drv, -1, NULL, 0, NULL, NULL);
2846  dev_len = WideCharToMultiByte(CP_ACP, 0, devname, -1, NULL, 0, NULL, NULL);
2847  port_len = WideCharToMultiByte(CP_ACP, 0, port, -1, NULL, 0, NULL, NULL);
2848  }
2849  len += drv_len + dev_len + port_len;
2850 
2851  if(data->u.dlgw->hDevNames)
2852  data->u.dlgw->hDevNames = GlobalReAlloc(data->u.dlgw->hDevNames, len, GMEM_MOVEABLE);
2853  else
2854  data->u.dlgw->hDevNames = GlobalAlloc(GMEM_MOVEABLE, len);
2855 
2856  dn = GlobalLock(data->u.dlgw->hDevNames);
2857 
2858  if(data->unicode)
2859  {
2860  WCHAR *ptr = (WCHAR *)(dn + 1);
2861  len = sizeof(DEVNAMES) / sizeof(WCHAR);
2862  dn->wDriverOffset = len;
2863  lstrcpyW(ptr, drv);
2864  ptr += drv_len / sizeof(WCHAR);
2865  len += drv_len / sizeof(WCHAR);
2866  dn->wDeviceOffset = len;
2867  lstrcpyW(ptr, devname);
2868  ptr += dev_len / sizeof(WCHAR);
2869  len += dev_len / sizeof(WCHAR);
2870  dn->wOutputOffset = len;
2871  lstrcpyW(ptr, port);
2872  }
2873  else
2874  {
2875  char *ptr = (char *)(dn + 1);
2876  len = sizeof(DEVNAMES);
2877  dn->wDriverOffset = len;
2878  WideCharToMultiByte(CP_ACP, 0, drv, -1, ptr, drv_len, NULL, NULL);
2879  ptr += drv_len;
2880  len += drv_len;
2881  dn->wDeviceOffset = len;
2882  WideCharToMultiByte(CP_ACP, 0, devname, -1, ptr, dev_len, NULL, NULL);
2883  ptr += dev_len;
2884  len += dev_len;
2885  dn->wOutputOffset = len;
2886  WideCharToMultiByte(CP_ACP, 0, port, -1, ptr, port_len, NULL, NULL);
2887  }
2888 
2889  dn->wDefault = 0;
2890  len = ARRAY_SIZE(def);
2891  GetDefaultPrinterW(def, &len);
2892  if(!lstrcmpW(def, devname))
2893  dn->wDefault = 1;
2894 
2895  GlobalUnlock(data->u.dlgw->hDevNames);
2896 }
2897 
2899 {
2900  DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
2901  DEVMODEW *ret;
2902 
2903  if(data->unicode)
2904  {
2905  /* We make a copy even in the unicode case because the ptr
2906  may get passed back to us in pagesetup_set_devmode. */
2907  ret = HeapAlloc(GetProcessHeap(), 0, dm->dmSize + dm->dmDriverExtra);
2908  memcpy(ret, dm, dm->dmSize + dm->dmDriverExtra);
2909  }
2910  else
2912 
2913  GlobalUnlock(data->u.dlgw->hDevMode);
2914  return ret;
2915 }
2916 
2918 {
2919  HeapFree(GetProcessHeap(), 0, dm);
2920 }
2921 
2923 {
2924  DEVMODEA *dmA = NULL;
2925  void *src, *dst;
2926  DWORD size;
2927 
2928  if(data->unicode)
2929  {
2930  size = dm->dmSize + dm->dmDriverExtra;
2931  src = dm;
2932  }
2933  else
2934  {
2935  dmA = convert_to_devmodeA(dm);
2936  size = dmA->dmSize + dmA->dmDriverExtra;
2937  src = dmA;
2938  }
2939 
2940  if(data->u.dlgw->hDevMode)
2941  data->u.dlgw->hDevMode = GlobalReAlloc(data->u.dlgw->hDevMode, size,
2942  GMEM_MOVEABLE);
2943  else
2944  data->u.dlgw->hDevMode = GlobalAlloc(GMEM_MOVEABLE, size);
2945 
2946  dst = GlobalLock(data->u.dlgw->hDevMode);
2947  memcpy(dst, src, size);
2948  GlobalUnlock(data->u.dlgw->hDevMode);
2949  HeapFree(GetProcessHeap(), 0, dmA);
2950 }
2951 
2953 {
2954  return &data->u.dlgw->ptPaperSize;
2955 }
2956 
2958 {
2959  return &data->u.dlgw->rtMargin;
2960 }
2961 
2962 typedef enum
2963 {
2966 } hook_type;
2967 
2969 {
2970  switch(which)
2971  {
2972  case page_setup_hook: return data->u.dlgw->lpfnPageSetupHook;
2973  case page_paint_hook: return data->u.dlgw->lpfnPagePaintHook;
2974  }
2975  return NULL;
2976 }
2977 
2978 /* This should only be used in calls to hook procs so we return the ptr
2979  already cast to LPARAM */
2981 {
2982  return (LPARAM)data->u.dlgw;
2983 }
2984 
2985 static inline void swap_point(POINT *pt)
2986 {
2987  LONG tmp = pt->x;
2988  pt->x = pt->y;
2989  pt->y = tmp;
2990 }
2991 
2993 {
2994  DEVMODEW *dm;
2995  LPWSTR devname, portname;
2996  int i, num;
2997  WORD *words = NULL, paperword;
2998  POINT *points = NULL;
2999  BOOL retval = FALSE;
3000 
3002  devname = pagesetup_get_devname(data);
3003  portname = pagesetup_get_portname(data);
3004 
3005  num = DeviceCapabilitiesW(devname, portname, DC_PAPERS, NULL, dm);
3006  if (num <= 0)
3007  {
3008  FIXME("No papernames found for %s/%s\n", debugstr_w(devname), debugstr_w(portname));
3009  goto end;
3010  }
3011 
3012  words = HeapAlloc(GetProcessHeap(), 0, num * sizeof(WORD));
3013  points = HeapAlloc(GetProcessHeap(), 0, num * sizeof(POINT));
3014 
3015  if (num != DeviceCapabilitiesW(devname, portname, DC_PAPERS, (LPWSTR)words, dm))
3016  {
3017  FIXME("Number of returned words is not %d\n", num);
3018  goto end;
3019  }
3020 
3021  if (num != DeviceCapabilitiesW(devname, portname, DC_PAPERSIZE, (LPWSTR)points, dm))
3022  {
3023  FIXME("Number of returned sizes is not %d\n", num);
3024  goto end;
3025  }
3026 
3027  paperword = pagesetup_get_papersize(data);
3028 
3029  for (i = 0; i < num; i++)
3030  if (words[i] == paperword)
3031  break;
3032 
3033  if (i == num)
3034  {
3035  FIXME("Papersize %d not found in list?\n", paperword);
3036  goto end;
3037  }
3038 
3039  /* this is _10ths_ of a millimeter */
3042 
3045 
3046  retval = TRUE;
3047 
3048 end:
3049  HeapFree(GetProcessHeap(), 0, words);
3051  pagesetup_release_a_devname(data, portname);
3054 
3055  return retval;
3056 }
3057 
3058 /**********************************************************************************************
3059  * pagesetup_change_printer
3060  *
3061  * Redefines hDevMode and hDevNames HANDLES and initialises it.
3062  *
3063  */
3065 {
3066  HANDLE hprn;
3067  DWORD needed;
3068  PRINTER_INFO_2W *prn_info = NULL;
3069  DRIVER_INFO_3W *drv_info = NULL;
3070  DEVMODEW *dm = NULL;
3071  BOOL retval = FALSE;
3072 
3073  if(!OpenPrinterW(name, &hprn, NULL))
3074  {
3075  ERR("Can't open printer %s\n", debugstr_w(name));
3076  goto end;
3077  }
3078 
3079  GetPrinterW(hprn, 2, NULL, 0, &needed);
3080  prn_info = HeapAlloc(GetProcessHeap(), 0, needed);
3081  GetPrinterW(hprn, 2, (LPBYTE)prn_info, needed, &needed);
3082  GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
3083  drv_info = HeapAlloc(GetProcessHeap(), 0, needed);
3084  if(!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)drv_info, needed, &needed))
3085  {
3086  ERR("GetPrinterDriverA failed for %s, fix your config!\n", debugstr_w(prn_info->pPrinterName));
3087  goto end;
3088  }
3089  ClosePrinter(hprn);
3090 
3091  needed = DocumentPropertiesW(0, 0, name, NULL, NULL, 0);
3092  if(needed == -1)
3093  {
3094  ERR("DocumentProperties fails on %s\n", debugstr_w(name));
3095  goto end;
3096  }
3097 
3098  dm = HeapAlloc(GetProcessHeap(), 0, needed);
3100 
3102  pagesetup_set_devnames(data, drv_info->pDriverPath, prn_info->pPrinterName,
3103  prn_info->pPortName);
3104 
3105  retval = TRUE;
3106 end:
3107  HeapFree(GetProcessHeap(), 0, dm);
3108  HeapFree(GetProcessHeap(), 0, prn_info);
3109  HeapFree(GetProcessHeap(), 0, drv_info);
3110  return retval;
3111 }
3112 
3113 /****************************************************************************************
3114  * pagesetup_init_combos
3115  *
3116  * Fills Printers, Paper and Source combos
3117  *
3118  */
3120 {
3121  DEVMODEW *dm;
3122  LPWSTR devname, portname;
3123 
3125  devname = pagesetup_get_devname(data);
3126  portname = pagesetup_get_portname(data);
3127 
3128  PRINTDLG_SetUpPrinterListComboW(hDlg, cmb1, devname);
3129  PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb2, devname, portname, dm);
3130  PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb3, devname, portname, dm);
3131 
3132  pagesetup_release_a_devname(data, portname);
3135 }
3136 
3137 
3138 /****************************************************************************************
3139  * pagesetup_change_printer_dialog
3140  *
3141  * Pops up another dialog that lets the user pick another printer.
3142  *
3143  * For now we display the PrintDlg, this should display a striped down version of it.
3144  */
3146 {
3147  PRINTDLGW prnt;
3148  LPWSTR drvname, devname, portname;
3149  DEVMODEW *tmp_dm, *dm;
3150 
3151  memset(&prnt, 0, sizeof(prnt));
3152  prnt.lStructSize = sizeof(prnt);
3153  prnt.Flags = 0;
3154  prnt.hwndOwner = hDlg;
3155 
3156  drvname = pagesetup_get_drvname(data);
3157  devname = pagesetup_get_devname(data);
3158  portname = pagesetup_get_portname(data);
3159  prnt.hDevNames = 0;
3160  PRINTDLG_CreateDevNamesW(&prnt.hDevNames, drvname, devname, portname);
3161  pagesetup_release_a_devname(data, portname);
3164 
3165  tmp_dm = pagesetup_get_devmode(data);
3166  prnt.hDevMode = GlobalAlloc(GMEM_MOVEABLE, tmp_dm->dmSize + tmp_dm->dmDriverExtra);
3167  dm = GlobalLock(prnt.hDevMode);
3168  memcpy(dm, tmp_dm, tmp_dm->dmSize + tmp_dm->dmDriverExtra);
3169  GlobalUnlock(prnt.hDevMode);
3171 
3172  if (PrintDlgW(&prnt))
3173  {
3174  DEVMODEW *dm = GlobalLock(prnt.hDevMode);
3175  DEVNAMES *dn = GlobalLock(prnt.hDevNames);
3176 
3178  (WCHAR*)dn + dn->wDeviceOffset, (WCHAR *)dn + dn->wOutputOffset);
3180  GlobalUnlock(prnt.hDevNames);
3181  GlobalUnlock(prnt.hDevMode);
3182  pagesetup_init_combos(hDlg, data);
3183  }
3184 
3185  GlobalFree(prnt.hDevMode);
3186  GlobalFree(prnt.hDevNames);
3187 
3188 }
3189 
3190 /******************************************************************************************
3191  * pagesetup_change_preview
3192  *
3193  * Changes paper preview size / position
3194  *
3195  */
3197 {
3198  LONG width, height, x, y;
3199  RECT tmp;
3200  const int shadow = 4;
3201 
3203  {
3204  width = data->rtDrawRect.right - data->rtDrawRect.left;
3206  }
3207  else
3208  {
3209  height = data->rtDrawRect.bottom - data->rtDrawRect.top;
3211  }
3212  x = (data->rtDrawRect.right + data->rtDrawRect.left - width) / 2;
3213  y = (data->rtDrawRect.bottom + data->rtDrawRect.top - height) / 2;
3214  TRACE("draw rect %s x=%d, y=%d, w=%d, h=%d\n",
3215  wine_dbgstr_rect(&data->rtDrawRect), x, y, width, height);
3216 
3217  MoveWindow(GetDlgItem(data->hDlg, rct2), x + width, y + shadow, shadow, height, FALSE);
3218  MoveWindow(GetDlgItem(data->hDlg, rct3), x + shadow, y + height, width, shadow, FALSE);
3219  MoveWindow(GetDlgItem(data->hDlg, rct1), x, y, width, height, FALSE);
3220 
3221  tmp = data->rtDrawRect;
3222  tmp.right += shadow;
3223  tmp.bottom += shadow;
3224  InvalidateRect(data->hDlg, &tmp, TRUE);
3225 }
3226 
3227 static inline LONG *element_from_margin_id(RECT *rc, WORD id)
3228 {
3229  switch(id)
3230  {
3231  case edt4: return &rc->left;
3232  case edt5: return &rc->top;
3233  case edt6: return &rc->right;
3234  case edt7: return &rc->bottom;
3235  }
3236  return NULL;
3237 }
3238 
3239 static void update_margin_edits(HWND hDlg, const pagesetup_data *data, WORD id)
3240 {
3241  WCHAR str[100];
3242  WORD idx;
3243 
3244  for(idx = edt4; idx <= edt7; idx++)
3245  {
3246  if(id == 0 || id == idx)
3247  {
3249  SetDlgItemTextW(hDlg, idx, str);
3250  }
3251  }
3252 }
3253 
3255 {
3256  switch (msg)
3257  {
3258  case EN_CHANGE:
3259  {
3260  WCHAR buf[10];
3261  LONG val = 0;
3263 
3264  if (GetDlgItemTextW(hDlg, id, buf, ARRAY_SIZE(buf)) != 0)
3265  {
3266  WCHAR *end;
3267  WCHAR decimal = get_decimal_sep();
3268 
3269  val = wcstol(buf, &end, 10);
3270  if(end != buf || *end == decimal)
3271  {
3272  int mult = is_metric(data) ? 100 : 1000;
3273  val *= mult;
3274  if(*end == decimal)
3275  {
3276  while(mult > 1)
3277  {
3278  end++;
3279  mult /= 10;
3280  if(iswdigit(*end))
3281  val += (*end - '0') * mult;
3282  else
3283  break;
3284  }
3285  }
3286  }
3287  }
3288  *value = val;
3289  return;
3290  }
3291 
3292  case EN_KILLFOCUS:
3293  update_margin_edits(hDlg, data, id);
3294  return;
3295  }
3296 }
3297 
3299 {
3300  WCHAR title[256];
3301 
3303  title, ARRAY_SIZE(title)))
3304  SetDlgItemTextW(hDlg, grp4, title);
3305 }
3306 
3308 {
3310  CheckRadioButton(hDlg, rad1, rad2, rad2);
3311  else
3312  CheckRadioButton(hDlg, rad1, rad2, rad1);
3313 }
3314 
3315 /****************************************************************************************
3316  * pagesetup_printer_properties
3317  *
3318  * Handle invocation of the 'Properties' button (not present in the default template).
3319  */
3321 {
3322  HANDLE hprn;
3323  LPWSTR devname;
3324  DEVMODEW *dm;
3325  LRESULT count;
3326  int i;
3327 
3328  devname = pagesetup_get_devname(data);
3329 
3330  if (!OpenPrinterW(devname, &hprn, NULL))
3331  {
3332  FIXME("Call to OpenPrinter did not succeed!\n");
3334  return;
3335  }
3336 
3338  DocumentPropertiesW(hDlg, hprn, devname, dm, dm, DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
3342  ClosePrinter(hprn);
3343 
3344  /* Changing paper */
3347 
3348  /* Changing paper preview */
3350 
3351  /* Selecting paper in combo */
3352  count = SendDlgItemMessageW(hDlg, cmb2, CB_GETCOUNT, 0, 0);
3353  if(count != CB_ERR)
3354  {
3355  WORD paperword = pagesetup_get_papersize(data);
3356  for(i = 0; i < count; i++)
3357  {
3358  if(SendDlgItemMessageW(hDlg, cmb2, CB_GETITEMDATA, i, 0) == paperword) {
3359  SendDlgItemMessageW(hDlg, cmb2, CB_SETCURSEL, i, 0);
3360  break;
3361  }
3362  }
3363  }
3364 }
3365 
3366 /********************************************************************************
3367  * pagesetup_wm_command
3368  * process WM_COMMAND message for PageSetupDlg
3369  *
3370  * PARAMS
3371  * hDlg [in] Main dialog HANDLE
3372  * wParam [in] WM_COMMAND wParam
3373  * lParam [in] WM_COMMAND lParam
3374  * pda [in/out] ptr to PageSetupDataA
3375  */
3376 
3378 {
3379  WORD msg = HIWORD(wParam);
3380  WORD id = LOWORD(wParam);
3381 
3382  TRACE("loword (lparam) %d, wparam 0x%lx, lparam %08lx\n",
3384  switch (id) {
3385  case IDOK:
3386  EndDialog(hDlg, TRUE);
3387  return TRUE ;
3388 
3389  case IDCANCEL:
3390  EndDialog(hDlg, FALSE);
3391  return FALSE ;
3392 
3393  case psh3: /* Printer... */
3395  return TRUE;
3396 
3397  case rad1: /* Portrait */
3398  case rad2: /* Landscape */
3401  {
3405  update_margin_edits(hDlg, data, 0);
3407  }
3408  break;
3409  case cmb1: /* Printer combo */
3410  if(msg == CBN_SELCHANGE)
3411  {
3412  WCHAR *name;
3413  INT index = SendDlgItemMessageW(hDlg, id, CB_GETCURSEL, 0, 0);
3415  name = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(length+1));
3418  pagesetup_init_combos(hDlg, data);
3420  }
3421  break;
3422  case cmb2: /* Paper combo */
3423  if(msg == CBN_SELCHANGE)
3424  {
3425  DWORD paperword = SendDlgItemMessageW(hDlg, cmb2, CB_GETITEMDATA,
3426  SendDlgItemMessageW(hDlg, cmb2, CB_GETCURSEL, 0, 0), 0);
3427  if (paperword != CB_ERR)
3428  {
3429  pagesetup_set_papersize(data, paperword);
3432  } else
3433  FIXME("could not get dialog text for papersize cmbbox?\n");
3434  }
3435  break;
3436  case cmb3: /* Paper Source */
3437  if(msg == CBN_SELCHANGE)
3438  {
3440  SendDlgItemMessageW(hDlg, cmb3, CB_GETCURSEL, 0, 0), 0);
3442  }
3443  break;
3444  case psh2: /* Printer Properties button */
3446  break;
3447  case edt4:
3448  case edt5:
3449  case edt6:
3450  case edt7:
3451  margin_edit_notification(hDlg, data, msg, id);
3452  break;
3453  }
3455  return FALSE;
3456 }
3457 
3458 /***********************************************************************
3459  * default_page_paint_hook
3460  * Default hook paint procedure that receives WM_PSD_* messages from the dialog box
3461  * whenever the sample page is redrawn.
3462  */
3464  const pagesetup_data *data)
3465 {
3466  LPRECT lprc = (LPRECT) lParam;
3467  HDC hdc = (HDC) wParam;
3468  HPEN hpen, holdpen;
3469  LOGFONTW lf;
3470  HFONT hfont, holdfont;
3471  INT oldbkmode;
3472  TRACE("uMsg: WM_USER+%d\n",uMsg-WM_USER);
3473  /* Call user paint hook if enable */
3475  if (pagesetup_get_hook(data, page_paint_hook)(hwndDlg, uMsg, wParam, lParam))
3476  return TRUE;
3477 
3478  switch (uMsg) {
3479  /* LPPAGESETUPDLG in lParam */
3480  case WM_PSD_PAGESETUPDLG:
3481  /* Inform about the sample page rectangle */
3482  case WM_PSD_FULLPAGERECT:
3483  /* Inform about the margin rectangle */
3484  case WM_PSD_MINMARGINRECT:
3485  return FALSE;
3486 
3487  /* Draw dashed rectangle showing margins */
3488  case WM_PSD_MARGINRECT:
3490  holdpen = SelectObject(hdc, hpen);
3492  DeleteObject(SelectObject(hdc, holdpen));
3493  return TRUE;
3494  /* Draw the fake document */
3495  case WM_PSD_GREEKTEXTRECT:
3496  /* select a nice scalable font, because we want the text really small */
3497  SystemParametersInfoW(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0);
3498  lf.lfHeight = 6; /* value chosen based on visual effect */
3499  hfont = CreateFontIndirectW(&lf);
3500  holdfont = SelectObject(hdc, hfont);
3501 
3502  /* if text not loaded, then do so now */
3503  if (wszFakeDocumentText[0] == '\0')
3508 
3509  oldbkmode = SetBkMode(hdc, TRANSPARENT);
3511  SetBkMode(hdc, oldbkmode);
3512 
3513  DeleteObject(SelectObject(hdc, holdfont));
3514  return TRUE;
3515 
3516  /* Envelope stamp */
3517  case WM_PSD_ENVSTAMPRECT:
3518  /* Return address */
3519  case WM_PSD_YAFULLPAGERECT:
3520  FIXME("envelope/stamp is not implemented\n");
3521  return FALSE;
3522  default:
3523  FIXME("Unknown message %x\n",uMsg);
3524  return FALSE;
3525  }
3526  return TRUE;
3527 }
3528 
3529 /***********************************************************************
3530  * PagePaintProc
3531  * The main paint procedure for the PageSetupDlg function.
3532  * The Page Setup dialog box includes an image of a sample page that shows how
3533  * the user's selections affect the appearance of the printed output.
3534  * The image consists of a rectangle that represents the selected paper
3535  * or envelope type, with a dotted-line rectangle representing
3536  * the current margins, and partial (Greek text) characters
3537  * to show how text looks on the printed page.
3538  *
3539  * The following messages in the order sends to user hook procedure:
3540  * WM_PSD_PAGESETUPDLG Draw the contents of the sample page
3541  * WM_PSD_FULLPAGERECT Inform about the bounding rectangle
3542  * WM_PSD_MINMARGINRECT Inform about the margin rectangle (min margin?)
3543  * WM_PSD_MARGINRECT Draw the margin rectangle
3544  * WM_PSD_GREEKTEXTRECT Draw the Greek text inside the margin rectangle
3545  * If any of first three messages returns TRUE, painting done.
3546  *
3547  * PARAMS:
3548  * hWnd [in] Handle to the Page Setup dialog box
3549  * uMsg [in] Received message
3550  *
3551  * TODO:
3552  * WM_PSD_ENVSTAMPRECT Draw in the envelope-stamp rectangle (for envelopes only)
3553  * WM_PSD_YAFULLPAGERECT Draw the return address portion (for envelopes and other paper sizes)
3554  *
3555  * RETURNS:
3556  * FALSE if all done correctly
3557  *
3558  */
3559 
3560 
3561 static LRESULT CALLBACK
3563 {
3564  PAINTSTRUCT ps;
3565  RECT rcClient, rcMargin;
3566  HPEN hpen, holdpen;
3567  HDC hdc;
3568  HBRUSH hbrush, holdbrush;
3570  int papersize=0, orientation=0; /* FIXME: set these values for the user paint hook */
3571  double scalx, scaly;
3572 
3573  if (uMsg != WM_PAINT)
3575 
3576  /* Processing WM_PAINT message */
3578  if (!data) {
3579  WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
3580  return FALSE;
3581  }
3582  if (default_page_paint_hook(hWnd, WM_PSD_PAGESETUPDLG, MAKELONG(papersize, orientation),
3584  return FALSE;
3585 
3586  hdc = BeginPaint(hWnd, &ps);
3587  GetClientRect(hWnd, &rcClient);
3588 
3589  scalx = rcClient.right / (double)pagesetup_get_papersize_pt(data)->x;
3590  scaly = rcClient.bottom / (double)pagesetup_get_papersize_pt(data)->y;
3591  rcMargin = rcClient;
3592 
3593  rcMargin.left += pagesetup_get_margin_rect(data)->left * scalx;
3594  rcMargin.top += pagesetup_get_margin_rect(data)->top * scaly;
3595  rcMargin.right -= pagesetup_get_margin_rect(data)->right * scalx;
3596  rcMargin.bottom -= pagesetup_get_margin_rect(data)->bottom * scaly;
3597 
3598  /* if the space is too small then we make sure to not draw anything */
3599  rcMargin.left = min(rcMargin.left, rcMargin.right);
3600  rcMargin.top = min(rcMargin.top, rcMargin.bottom);
3601 
3604  {
3605  /* fill background */
3607  FillRect(hdc, &rcClient, hbrush);
3608  holdbrush = SelectObject(hdc, hbrush);
3609 
3611  holdpen = SelectObject(hdc, hpen);
3612 
3613  /* paint left edge */
3614  MoveToEx(hdc, rcClient.left, rcClient.top, NULL);
3615  LineTo(hdc, rcClient.left, rcClient.bottom-1);
3616 
3617  /* paint top edge */
3618  MoveToEx(hdc, rcClient.left, rcClient.top, NULL);
3619  LineTo(hdc, rcClient.right, rcClient.top);
3620 
3623 
3624  /* paint right edge */
3625  MoveToEx(hdc, rcClient.right-1, rcClient.top, NULL);
3626  LineTo(hdc, rcClient.right-1, rcClient.bottom);
3627 
3628  /* paint bottom edge */
3629  MoveToEx(hdc, rcClient.left, rcClient.bottom-1, NULL);
3630  LineTo(hdc, rcClient.right, rcClient.bottom-1);
3631 
3632  DeleteObject(SelectObject(hdc, holdpen));
3633  DeleteObject(SelectObject(hdc, holdbrush));
3634 
3636 
3637  /* give text a bit of a space from the frame */
3638  InflateRect(&rcMargin, -2, -2);
3639 
3640  /* if the space is too small then we make sure to not draw anything */
3641  rcMargin.left = min(rcMargin.left, rcMargin.right);
3642  rcMargin.top = min(rcMargin.top, rcMargin.bottom);
3643 
3645  }
3646 
3647  EndPaint(hWnd, &ps);
3648  return FALSE;
3649 }
3650 
3651 /*******************************************************
3652  * The margin edit controls are subclassed to filter
3653  * anything other than numbers and the decimal separator.
3654  */
3656 {
3657  if (msg == WM_CHAR)
3658  {
3659  WCHAR decimal = get_decimal_sep();
3660  WCHAR wc = (WCHAR)wparam;
3661  if(!iswdigit(wc) && wc != decimal && wc != VK_BACK) return 0;
3662  }
3664 }
3665 
3666 static void subclass_margin_edits(HWND hDlg)
3667 {
3668  int id;
3669  WNDPROC old_proc;
3670 
3671  for(id = edt4; id <= edt7; id++)
3672  {
3674  GWLP_WNDPROC,
3677  }
3678 }
3679 
3680 /***********************************************************************
3681  * pagesetup_dlg_proc
3682  *
3683  * Message handler for PageSetupDlg
3684  */
3686 {
3688  INT_PTR res = FALSE;
3689  HWND hDrawWnd;
3690 
3691  if (uMsg == WM_INITDIALOG) { /*Init dialog*/
3692  data = (pagesetup_data *)lParam;
3693  data->hDlg = hDlg;
3694 
3695  hDrawWnd = GetDlgItem(hDlg, rct1);
3696  TRACE("set property to %p\n", data);
3698  SetPropW(hDrawWnd, pagesetupdlg_prop, data);
3699  GetWindowRect(hDrawWnd, &data->rtDrawRect); /* Calculating rect in client coordinates where paper draws */
3700  MapWindowPoints( 0, hDlg, (LPPOINT)&data->rtDrawRect, 2 );
3702  hDrawWnd,
3703  GWLP_WNDPROC,
3705 
3706  /* FIXME: Paint hook. Must it be at begin of initialization or at end? */
3707  res = TRUE;
3709  {
3710  if (!pagesetup_get_hook(data, page_setup_hook)(hDlg, uMsg, wParam,
3712  FIXME("Setup page hook failed?\n");
3713  }
3714 
3715  /* if printer button disabled */
3717  EnableWindow(GetDlgItem(hDlg, psh3), FALSE);
3718  /* if margin edit boxes disabled */
3720  {
3721  EnableWindow(GetDlgItem(hDlg, edt4), FALSE);
3722  EnableWindow(GetDlgItem(hDlg, edt5), FALSE);
3723  EnableWindow(GetDlgItem(hDlg, edt6), FALSE);
3724  EnableWindow(GetDlgItem(hDlg, edt7), FALSE);
3725  }
3726 
3727  /* Set orientation radiobuttons properly */
3729 
3730  /* if orientation disabled */
3732  {
3735  }
3736 
3737  /* We fill them out enabled or not */
3739  {
3740  /* default is 1 inch */
3743  }
3744  update_margin_edits(hDlg, data, 0);
3745  subclass_margin_edits(hDlg);
3747 
3748  /* if paper disabled */
3750  {
3753  }
3754 
3755  /* filling combos: printer, paper, source. selecting current printer (from DEVMODEA) */
3756  pagesetup_init_combos(hDlg, data);
3758  pagesetup_set_defaultsource(data, DMBIN_FORMSOURCE); /* FIXME: This is the auto select bin. Is this correct? */
3759 
3760  /* Drawing paper prev */
3762  return TRUE;
3763  } else {
3764  data = GetPropW(hDlg, pagesetupdlg_prop);
3765  if (!data)
3766  {
3767  WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
3768  return FALSE;
3769  }
3771  {
3773  if (res) return res;
3774  }
3775  }
3776  switch (uMsg) {
3777  case WM_COMMAND:
3778  return pagesetup_wm_command(hDlg, wParam, lParam, data);
3779  }
3780  return FALSE;
3781 }
3782 
3784 {
3785  WCHAR *name = NULL;
3786  DWORD len = 0;
3787 
3789  if(len)
3790  {
3791  name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3793  }
3794  return name;
3795 }
3796 
3798 {
3799  if(TRACE_ON(commdlg))
3800  {
3801  char flagstr[1000] = "";
3802  const struct pd_flags *pflag = psd_flags;
3803  for( ; pflag->name; pflag++)
3804  {
3805  if(pagesetup_get_flags(data) & pflag->flag)
3806  {
3807  strcat(flagstr, pflag->name);
3808  strcat(flagstr, "|");
3809  }
3810  }
3811  TRACE("%s: (%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
3812  "hinst %p, flags %08x (%s)\n",
3813  data->unicode ? "unicode" : "ansi",
3814  data->u.dlgw, data->u.dlgw->hwndOwner, data->u.dlgw->hDevMode,
3815  data->u.dlgw->hDevNames, data->u.dlgw->hInstance,
3816  pagesetup_get_flags(data), flagstr);
3817  }
3818 }
3819 
3821 {
3822  HRSRC res;
3823  HGLOBAL tmpl_handle;
3824 
3826  {
3827  tmpl_handle = data->u.dlgw->hPageSetupTemplate;
3828  }
3830  {
3831  if(data->unicode)
3832  res = FindResourceW(data->u.dlgw->hInstance,
3833  data->u.dlgw->lpPageSetupTemplateName, (LPWSTR)RT_DIALOG);
3834  else
3835  res = FindResourceA(data->u.dlga->hInstance,
3836  data->u.dlga->lpPageSetupTemplateName, (LPSTR)RT_DIALOG);
3837  tmpl_handle = LoadResource(data->u.dlgw->hInstance, res);
3838  }
3839  else
3840  {
3842  (LPWSTR)RT_DIALOG);
3843  tmpl_handle = LoadResource(COMDLG32_hInstance, res);
3844  }
3845  return LockResource(tmpl_handle);
3846 }
3847 
3849 {
3850  BOOL ret;
3851  void *tmpl;
3852 
3854  {
3856  return FALSE;
3857  }
3858 
3860 
3861  if(data->u.dlgw->lStructSize != sizeof(PAGESETUPDLGW))
3862  {
3864  return FALSE;
3865  }
3866 
3869  {
3871  return FALSE;
3872  }
3873 
3875  data->u.dlgw->Flags |= is_default_metric() ?
3877 
3878  if (!data->u.dlgw->hDevMode || !data->u.dlgw->hDevNames)
3879  {
3880  WCHAR *def = get_default_printer();
3881  if(!def)
3882  {
3884  {
3885  WCHAR errstr[256];
3887  MessageBoxW(data->u.dlgw->hwndOwner, errstr, 0, MB_OK | MB_ICONERROR);
3888  }
3890  return FALSE;
3891  }
3893  HeapFree(GetProcessHeap(), 0, def);
3894  }
3895 
3897  {
3899  return TRUE;
3900  }
3901 
3902  tmpl = pagesetup_get_template(data);
3903 
3904  ret = DialogBoxIndirectParamW(data->u.dlgw->hInstance, tmpl,
3905  data->u.dlgw->hwndOwner,
3907  return ret;
3908 }
3909 
3910 /***********************************************************************
3911  * PageSetupDlgA (COMDLG32.@)
3912  *
3913  * Displays the PAGE SETUP dialog box, which enables the user to specify
3914  * specific properties of a printed page such as
3915  * size, source, orientation and the width of the page margins.
3916  *
3917  * PARAMS
3918  * setupdlg [IO] PAGESETUPDLGA struct
3919  *
3920  * RETURNS
3921  * TRUE if the user pressed the OK button
3922  * FALSE if the user cancelled the window or an error occurred
3923  *
3924  * NOTES
3925  * The values of hDevMode and hDevNames are filled on output and can be
3926  * changed in PAGESETUPDLG when they are passed in PageSetupDlg.
3927  *
3928  */
3930 {
3932 
3933  data.unicode = FALSE;
3934  data.u.dlga = setupdlg;
3935 
3936  return pagesetup_common(&data);
3937 }
3938 
3939 /***********************************************************************
3940  * PageSetupDlgW (COMDLG32.@)
3941  *
3942  * See PageSetupDlgA.
3943  */
3945 {
3947 
3948  data.unicode = TRUE;
3949  data.u.dlgw = setupdlg;
3950 
3951  return pagesetup_common(&data);
3952 }
3953 
3954 static void pdlgex_to_pdlg(const PRINTDLGEXW *pdlgex, PRINTDLGW *pdlg)
3955 {
3956  pdlg->lStructSize = sizeof(*pdlg);
3957  pdlg->hwndOwner = pdlgex->hwndOwner;
3958  pdlg->hDevMode = pdlgex->hDevMode;
3959  pdlg->hDevNames = pdlgex->hDevNames;
3960  pdlg->hDC = pdlgex->hDC;
3961  pdlg->Flags = pdlgex->Flags;
3962  if ((pdlgex->Flags & PD_NOPAGENUMS) || !pdlgex->nPageRanges || !pdlgex->lpPageRanges)
3963  {
3964  pdlg->nFromPage = 0;
3965  pdlg->nToPage = 65534;
3966  }
3967  else
3968  {
3969  pdlg->nFromPage = pdlgex->lpPageRanges[0].nFromPage;
3970  pdlg->nToPage = pdlgex->lpPageRanges[0].nToPage;
3971  }
3972  pdlg->nMinPage = pdlgex->nMinPage;
3973  pdlg->nMaxPage = pdlgex->nMaxPage;
3974  pdlg->nCopies = pdlgex->nCopies;
3975  pdlg->hInstance = pdlgex->hInstance;
3976  pdlg->lCustData = 0;
3977  pdlg->lpfnPrintHook = NULL;
3978  pdlg->lpfnSetupHook = NULL;
3979  pdlg->lpPrintTemplateName = pdlgex->lpPrintTemplateName;
3980  pdlg->lpSetupTemplateName = NULL;
3981  pdlg->hPrintTemplate = NULL;
3982  pdlg->hSetupTemplate = NULL;
3983 }
3984 
3985 /* Only copy fields that are supposed to be changed. */
3986 static void pdlg_to_pdlgex(const PRINTDLGW *pdlg, PRINTDLGEXW *pdlgex)
3987 {
3988  pdlgex->hDevMode = pdlg->hDevMode;
3989  pdlgex->hDevNames = pdlg->hDevNames;
3990  pdlgex->hDC = pdlg->hDC;
3991  if (!(pdlgex->Flags & PD_NOPAGENUMS) && pdlgex->nPageRanges && pdlgex->lpPageRanges)
3992  {
3993  pdlgex->lpPageRanges[0].nFromPage = pdlg->nFromPage;
3994  pdlgex->lpPageRanges[0].nToPage = pdlg->nToPage;
3995  }
3996  pdlgex->nMinPage = pdlg->nMinPage;
3997  pdlgex->nMaxPage = pdlg->nMaxPage;
3998  pdlgex->nCopies = pdlg->nCopies;
3999 }
4000 
4002 {
4003  IPrintDialogCallback *callback;
4005 };
4006 
4008 {
4009  if (msg == WM_INITDIALOG)
4010  {
4011  PRINTDLGW *pd = (PRINTDLGW *)lp;
4012  struct callback_data *cb = (struct callback_data *)pd->lCustData;
4013 
4014  if (cb->callback)
4015  {
4016  cb->callback->lpVtbl->SelectionChange(cb->callback);
4017  cb->callback->lpVtbl->InitDone(cb->callback);
4018  }
4019  }
4020  else
4021  {
4022 /* FIXME: store interface pointer somewhere in window properties and call it
4023  HRESULT hres;
4024  cb->callback->lpVtbl->HandleMessage(cb->callback, hwnd, msg, wp, lp, &hres);
4025 */
4026  }
4027 
4028  return 0;
4029 }
4030 
4031 /***********************************************************************
4032  * PrintDlgExA (COMDLG32.@)
4033  *
4034  * See PrintDlgExW.
4035  *
4036  * BUGS
4037  * Only a Stub
4038  *
4039  */
4040 HRESULT WINAPI PrintDlgExA(LPPRINTDLGEXA lppd)
4041 {
4043  DRIVER_INFO_3A *dbuf;
4044  DEVMODEA *dm;
4045  HRESULT hr = S_OK;
4046  HANDLE hprn;
4047 
4048  if ((lppd == NULL) || (lppd->lStructSize != sizeof(PRINTDLGEXA)))
4049  return E_INVALIDARG;
4050 
4051  if (!IsWindow(lppd->hwndOwner))
4052  return E_HANDLE;
4053 
4054  if (lppd->nStartPage != START_PAGE_GENERAL)
4055  {
4056  if (!lppd->nPropertyPages)
4057  return E_INVALIDARG;
4058 
4059  FIXME("custom property sheets (%d at %p) not supported\n", lppd->nPropertyPages, lppd->lphPropertyPages);
4060  }
4061 
4062  /* Use PD_NOPAGENUMS or set nMaxPageRanges and lpPageRanges */
4063  if (!(lppd->Flags & PD_NOPAGENUMS) && (!lppd->nMaxPageRanges || !lppd->lpPageRanges))
4064  {
4065  return E_INVALIDARG;
4066  }
4067 
4068  if (lppd->Flags & PD_RETURNDEFAULT)
4069  {
4070  if (lppd->hDevMode || lppd->hDevNames)
4071  {
4072  WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
4074  return E_INVALIDARG;
4075  }
4076  if (!PRINTDLG_OpenDefaultPrinter(&hprn))
4077  {
4078  WARN("Can't find default printer\n");
4080  return E_FAIL;
4081  }
4082 
4083  pbuf = get_printer_infoA(hprn);
4084  if (!pbuf)
4085  {
4086  ClosePrinter(hprn);
4087  return E_FAIL;
4088  }
4089 
4090  dbuf = get_driver_infoA(hprn);
4091  if (!dbuf)
4092  {
4093  HeapFree(GetProcessHeap(), 0, pbuf);
4095  ClosePrinter(hprn);
4096  return E_FAIL;
4097  }
4098  dm = pbuf->pDevMode;
4099  }
4100  else
4101  {
4102  PRINTDLGA pdlg;
4103  struct callback_data cb_data = { 0 };
4104 
4105  FIXME("(%p) semi-stub\n", lppd);
4106 
4107  if (lppd->lpCallback)
4108  {
4109  IUnknown_QueryInterface((IUnknown *)lppd->lpCallback, &IID_IPrintDialogCallback, (void **)&cb_data.callback);
4110  IUnknown_QueryInterface((IUnknown *)lppd->lpCallback, &IID_IObjectWithSite, (void **)&cb_data.object);
4111  }
4112 
4113  /*
4114  * PRINTDLGEXA/W and PRINTDLGA/W layout is the same for A and W variants.
4115  */
4116  pdlgex_to_pdlg((const PRINTDLGEXW *)lppd, (PRINTDLGW *)&pdlg);
4117  pdlg.Flags |= PD_ENABLEPRINTHOOK;
4119  pdlg.lCustData = (LPARAM)&cb_data;
4120 
4121  if (PrintDlgA(&pdlg))
4122  {
4123  pdlg_to_pdlgex((const PRINTDLGW *)&pdlg, (PRINTDLGEXW *)lppd);
4124  lppd->dwResultAction = PD_RESULT_PRINT;
4125  }
4126  else
4127  lppd->dwResultAction = PD_RESULT_CANCEL;
4128 
4129  if (cb_data.callback)
4130  cb_data.callback->lpVtbl->Release(cb_data.callback);
4131  if (cb_data.object)
4132  cb_data.object->lpVtbl->Release(cb_data.object);
4133 
4134  return S_OK;
4135  }
4136 
4137  ClosePrinter(hprn);
4138 
4139  PRINTDLG_CreateDevNames(&(lppd->hDevNames), dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName);
4140  if (!lppd->hDevNames)
4141  hr = E_FAIL;
4142 
4143  lppd->hDevMode = update_devmode_handleA(lppd->hDevMode, dm);
4144  if (hr == S_OK && lppd->hDevMode) {
4145  if (lppd->Flags & PD_RETURNDC) {
4146  lppd->hDC = Create