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
49 WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
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 {
61 LPDEVMODEA lpDevMode;
62 LPPRINTDLGA lpPrintDlg;
63 LPPRINTER_INFO_2A lpPrinterInfo;
64 LPDRIVER_INFO_3A lpDriverInfo;
65 UINT HelpMessageID;
66 HICON hCollateIcon; /* PrintDlg only */
67 HICON hNoCollateIcon; /* PrintDlg only */
68 HICON hPortraitIcon; /* PrintSetupDlg only */
69 HICON hLandscapeIcon; /* PrintSetupDlg only */
70 HWND hwndUpDown;
71 } PRINT_PTRA;
72
73 typedef struct
74 {
75 LPDEVMODEW lpDevMode;
76 LPPRINTDLGW lpPrintDlg;
77 LPPRINTER_INFO_2W lpPrinterInfo;
78 LPDRIVER_INFO_3W lpDriverInfo;
79 UINT HelpMessageID;
80 HICON hCollateIcon; /* PrintDlg only */
81 HICON hNoCollateIcon; /* PrintDlg only */
82 HICON hPortraitIcon; /* PrintSetupDlg only */
83 HICON hLandscapeIcon; /* PrintSetupDlg only */
84 HWND hwndUpDown;
85 } PRINT_PTRW;
86
87 /* Debugging info */
88 struct pd_flags
89 {
90 DWORD flag;
91 LPCSTR name;
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 */
140 static WNDPROC lpfnStaticWndProc;
141 static WNDPROC edit_wndproc;
142 /* the text of the fake document to render for the Page Setup dialog */
143 static WCHAR wszFakeDocumentText[1024];
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
strdupW(LPCWSTR p)153 static LPWSTR strdupW(LPCWSTR p)
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 */
get_driver_infoW(HANDLE hprn)171 static DRIVER_INFO_3W * get_driver_infoW(HANDLE hprn)
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
get_driver_infoA(HANDLE hprn)191 static DRIVER_INFO_3A * get_driver_infoA(HANDLE hprn)
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 */
get_printer_infoW(HANDLE hprn)218 static PRINTER_INFO_2W * get_printer_infoW(HANDLE hprn)
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
get_printer_infoA(HANDLE hprn)238 static PRINTER_INFO_2A * get_printer_infoA(HANDLE hprn)
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 */
update_devmode_handleW(HGLOBAL hdm,DEVMODEW * dm)264 static HGLOBAL update_devmode_handleW(HGLOBAL hdm, DEVMODEW *dm)
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
update_devmode_handleA(HGLOBAL hdm,DEVMODEA * dm)292 static HGLOBAL update_devmode_handleA(HGLOBAL hdm, DEVMODEA *dm)
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 */
convert_to_devmodeA(const DEVMODEW * dmW)325 static DEVMODEA *convert_to_devmodeA(const DEVMODEW *dmW)
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
337 WideCharToMultiByte(CP_ACP, 0, dmW->dmDeviceName, -1,
338 (LPSTR)dmA->dmDeviceName, CCHDEVICENAME, NULL, NULL);
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));
349 WideCharToMultiByte(CP_ACP, 0, dmW->dmFormName, -1,
350 (LPSTR)dmA->dmFormName, CCHFORMNAME, NULL, NULL);
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 */
PRINTDLG_OpenDefaultPrinter(HANDLE * hprn)368 static BOOL PRINTDLG_OpenDefaultPrinter(HANDLE *hprn)
369 {
370 WCHAR buf[260];
371 DWORD dwBufLen = ARRAY_SIZE(buf);
372 BOOL res;
373 if(!GetDefaultPrinterW(buf, &dwBufLen))
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 */
PRINTDLG_SetUpPrinterListComboA(HWND hDlg,UINT id,LPCSTR name)394 static INT PRINTDLG_SetUpPrinterListComboA(HWND hDlg, UINT id, LPCSTR name)
395 {
396 DWORD needed, num;
397 INT i;
398 LPPRINTER_INFO_2A pi;
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];
416 DWORD dwBufLen = ARRAY_SIZE(buf);
417 if (name != NULL)
418 WARN("Can't find %s in printer list so trying to find default\n",
419 debugstr_a(name));
420 if(!GetDefaultPrinterA(buf, &dwBufLen))
421 return num;
422 i = SendDlgItemMessageA(hDlg, id, CB_FINDSTRINGEXACT, -1, (LPARAM)buf);
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
PRINTDLG_SetUpPrinterListComboW(HWND hDlg,UINT id,LPCWSTR name)430 static INT PRINTDLG_SetUpPrinterListComboW(HWND hDlg, UINT id, LPCWSTR name)
431 {
432 DWORD needed, num;
433 INT i;
434 LPPRINTER_INFO_2W pi;
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];
449 DWORD dwBufLen = ARRAY_SIZE(buf);
450 if (name != NULL)
451 WARN("Can't find %s in printer list so trying to find default\n",
452 debugstr_w(name));
453 if(!GetDefaultPrinterW(buf, &dwBufLen))
454 return num;
455 i = SendDlgItemMessageW(hDlg, id, CB_FINDSTRINGEXACT, -1, (LPARAM)buf);
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 */
PRINTDLG_CreateDevNames(HGLOBAL * hmem,const char * DeviceDriverName,const char * DeviceName,const char * OutputPort)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];
484 DWORD dwBufLen = ARRAY_SIZE(buf);
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
524 GetDefaultPrinterA(buf, &dwBufLen);
525 lpDevNames->wDefault = (strcmp(buf, DeviceName) == 0) ? 1 : 0;
526 GlobalUnlock(*hmem);
527 return TRUE;
528 }
529
PRINTDLG_CreateDevNamesW(HGLOBAL * hmem,LPCWSTR DeviceDriverName,LPCWSTR DeviceName,LPCWSTR OutputPort)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
578 GetDefaultPrinterW(bufW, &dwBufLen);
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 */
PRINTDLG_UpdatePrintDlgA(HWND hDlg,PRINT_PTRA * PrintStructures)594 static BOOL PRINTDLG_UpdatePrintDlgA(HWND hDlg,
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];
626 LoadStringW(COMDLG32_hInstance, PD32_INVALID_PAGE_RANGE, resourcestr, 255);
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);
688 lpdm->dmFields |= DM_PRINTQUALITY | DM_YRESOLUTION;
689 lpdm->u1.s1.dmPrintQuality = LOWORD(dpi);
690 lpdm->dmYResolution = HIWORD(dpi);
691 }
692 }
693 }
694 return TRUE;
695 }
696
PRINTDLG_UpdatePrintDlgW(HWND hDlg,PRINT_PTRW * PrintStructures)697 static BOOL PRINTDLG_UpdatePrintDlgW(HWND hDlg,
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];
730 LoadStringW(COMDLG32_hInstance, PD32_INVALID_PAGE_RANGE,
731 resourcestr, 255);
732 args[0] = lppd->nMinPage;
733 args[1] = lppd->nMaxPage;
734 FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ARGUMENT_ARRAY,
735 resourcestr, 0, 0, resultstr,
736 ARRAY_SIZE(resultstr),
737 (__ms_va_list*)args);
738 LoadStringW(COMDLG32_hInstance, PD32_PRINT_TITLE,
739 resourcestr, 255);
740 MessageBoxW(hDlg, resultstr, resourcestr,
741 MB_OK | MB_ICONWARNING);
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 */
PRINTDLG_SetUpPaperComboBoxA(HWND hDlg,int nIDComboBox,char * PrinterName,char * PortName,LPDEVMODEA dm)798 static BOOL PRINTDLG_SetUpPaperComboBoxA(HWND hDlg,
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);
903 HeapFree(GetProcessHeap(),0,Names);
904 return TRUE;
905 }
906
PRINTDLG_SetUpPaperComboBoxW(HWND hDlg,int nIDComboBox,const WCHAR * PrinterName,const WCHAR * PortName,LPDEVMODEW dm)907 static BOOL PRINTDLG_SetUpPaperComboBoxW(HWND hDlg,
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);
1013 HeapFree(GetProcessHeap(),0,Names);
1014 return TRUE;
1015 }
1016
1017
1018 /***********************************************************************
1019 * PRINTDLG_UpdatePrinterInfoTexts [internal]
1020 */
PRINTDLG_UpdatePrinterInfoTextsA(HWND hDlg,const PRINTER_INFO_2A * pi)1021 static void PRINTDLG_UpdatePrinterInfoTextsA(HWND hDlg, const PRINTER_INFO_2A *pi)
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)) {
1033 LoadStringA(COMDLG32_hInstance, PD32_PRINTER_STATUS_PAUSED+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? */
1041 LoadStringA(COMDLG32_hInstance, PD32_PRINTER_STATUS_READY,
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
PRINTDLG_UpdatePrinterInfoTextsW(HWND hDlg,const PRINTER_INFO_2W * pi)1057 static void PRINTDLG_UpdatePrinterInfoTextsW(HWND hDlg, const PRINTER_INFO_2W *pi)
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)) {
1070 LoadStringW(COMDLG32_hInstance, PD32_PRINTER_STATUS_PAUSED+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? */
1078 LoadStringW(COMDLG32_hInstance, PD32_PRINTER_STATUS_READY,
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 */
PRINTDLG_ChangePrinterA(HWND hDlg,char * name,PRINT_PTRA * PrintStructures)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,
1143 DM_OUT_BUFFER | DM_IN_BUFFER);
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);
1165 EnableWindow(GetDlgItem(hDlg, stc2),FALSE);
1166 EnableWindow(GetDlgItem(hDlg, edt1), FALSE);
1167 EnableWindow(GetDlgItem(hDlg, stc3),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 if (lppd->Flags & PD_COLLATE) {
1176 SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
1177 (LPARAM)PrintStructures->hCollateIcon);
1178 CheckDlgButton(hDlg, chx2, 1);
1179 } else {
1180 SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
1181 (LPARAM)PrintStructures->hNoCollateIcon);
1182 CheckDlgButton(hDlg, chx2, 0);
1183 }
1184
1185 if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
1186 /* if printer doesn't support it: no Collate */
1187 if (!(lpdm->dmFields & DM_COLLATE)) {
1188 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1189 EnableWindow(GetDlgItem(hDlg, ico3), FALSE);
1190 }
1191 }
1192
1193 /* nCopies */
1194 {
1195 INT copies;
1196 if (lppd->hDevMode == 0)
1197 copies = lppd->nCopies;
1198 else
1199 copies = lpdm->u1.s1.dmCopies;
1200 if(copies == 0) copies = 1;
1201 else if(copies < 0) copies = MAX_COPIES;
1202 SetDlgItemInt(hDlg, edt3, copies, FALSE);
1203 }
1204
1205 if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
1206 /* if printer doesn't support it: no nCopies */
1207 if (!(lpdm->dmFields & DM_COPIES)) {
1208 EnableWindow(GetDlgItem(hDlg, edt3), FALSE);
1209 EnableWindow(GetDlgItem(hDlg, stc5), FALSE);
1210 }
1211 }
1212
1213 /* print to file */
1214 CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0);
1215 if (lppd->Flags & PD_DISABLEPRINTTOFILE)
1216 EnableWindow(GetDlgItem(hDlg, chx1), FALSE);
1217 if (lppd->Flags & PD_HIDEPRINTTOFILE)
1218 ShowWindow(GetDlgItem(hDlg, chx1), SW_HIDE);
1219
1220 /* Fill print quality combo, PrintDlg16 */
1221 if(GetDlgItem(hDlg, cmb1))
1222 {
1223 DWORD numResolutions = DeviceCapabilitiesA(PrintStructures->lpPrinterInfo->pPrinterName,
1224 PrintStructures->lpPrinterInfo->pPortName,
1225 DC_ENUMRESOLUTIONS, NULL, lpdm);
1226
1227 if(numResolutions != -1)
1228 {
1229 HWND hQuality = GetDlgItem(hDlg, cmb1);
1230 LONG* Resolutions;
1231 char buf[255];
1232 DWORD i;
1233 int dpiX, dpiY;
1234 HDC hPrinterDC = CreateDCA(PrintStructures->lpPrinterInfo->pDriverName,
1235 PrintStructures->lpPrinterInfo->pPrinterName,
1236 0, lpdm);
1237
1238 Resolutions = HeapAlloc(GetProcessHeap(), 0, numResolutions*sizeof(LONG)*2);
1239 DeviceCapabilitiesA(PrintStructures->lpPrinterInfo->pPrinterName,
1240 PrintStructures->lpPrinterInfo->pPortName,
1241 DC_ENUMRESOLUTIONS, (LPSTR)Resolutions, lpdm);
1242
1243 dpiX = GetDeviceCaps(hPrinterDC, LOGPIXELSX);
1244 dpiY = GetDeviceCaps(hPrinterDC, LOGPIXELSY);
1245 DeleteDC(hPrinterDC);
1246
1247 SendMessageA(hQuality, CB_RESETCONTENT, 0, 0);
1248 for(i = 0; i < (numResolutions * 2); i += 2)
1249 {
1250 BOOL IsDefault = FALSE;
1251 LRESULT Index;
1252
1253 if(Resolutions[i] == Resolutions[i+1])
1254 {
1255 if(dpiX == Resolutions[i])
1256 IsDefault = TRUE;
1257 sprintf(buf, "%d dpi", Resolutions[i]);
1258 } else
1259 {
1260 if(dpiX == Resolutions[i] && dpiY == Resolutions[i+1])
1261 IsDefault = TRUE;
1262 sprintf(buf, "%d dpi x %d dpi", Resolutions[i], Resolutions[i+1]);
1263 }
1264
1265 Index = SendMessageA(hQuality, CB_ADDSTRING, 0, (LPARAM)buf);
1266
1267 if(IsDefault)
1268 SendMessageA(hQuality, CB_SETCURSEL, Index, 0);
1269
1270 SendMessageA(hQuality, CB_SETITEMDATA, Index, MAKELONG(dpiX,dpiY));
1271 }
1272 HeapFree(GetProcessHeap(), 0, Resolutions);
1273 }
1274 }
1275 } else { /* PD_PRINTSETUP */
1276 BOOL bPortrait = (lpdm->u1.s1.dmOrientation == DMORIENT_PORTRAIT);
1277
1278 PRINTDLG_SetUpPaperComboBoxA(hDlg, cmb2,
1279 PrintStructures->lpPrinterInfo->pPrinterName,
1280 PrintStructures->lpPrinterInfo->pPortName,
1281 lpdm);
1282 PRINTDLG_SetUpPaperComboBoxA(hDlg, cmb3,
1283 PrintStructures->lpPrinterInfo->pPrinterName,
1284 PrintStructures->lpPrinterInfo->pPortName,
1285 lpdm);
1286 CheckRadioButton(hDlg, rad1, rad2, bPortrait ? rad1: rad2);
1287 SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
1288 (LPARAM)(bPortrait ? PrintStructures->hPortraitIcon :
1289 PrintStructures->hLandscapeIcon));
1290
1291 }
1292
1293 /* help button */
1294 if ((lppd->Flags & PD_SHOWHELP)==0) {
1295 /* hide if PD_SHOWHELP not specified */
1296 ShowWindow(GetDlgItem(hDlg, pshHelp), SW_HIDE);
1297 }
1298 return TRUE;
1299 }
1300
PRINTDLG_ChangePrinterW(HWND hDlg,WCHAR * name,PRINT_PTRW * PrintStructures)1301 static BOOL PRINTDLG_ChangePrinterW(HWND hDlg, WCHAR *name,
1302 PRINT_PTRW *PrintStructures)
1303 {
1304 LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
1305 LPDEVMODEW lpdm = NULL;
1306 LONG dmSize;
1307 DWORD needed;
1308 HANDLE hprn;
1309
1310 HeapFree(GetProcessHeap(),0, PrintStructures->lpPrinterInfo);
1311 HeapFree(GetProcessHeap(),0, PrintStructures->lpDriverInfo);
1312 if(!OpenPrinterW(name, &hprn, NULL)) {
1313 ERR("Can't open printer %s\n", debugstr_w(name));
1314 return FALSE;
1315 }
1316 GetPrinterW(hprn, 2, NULL, 0, &needed);
1317 PrintStructures->lpPrinterInfo = HeapAlloc(GetProcessHeap(),0,needed);
1318 GetPrinterW(hprn, 2, (LPBYTE)PrintStructures->lpPrinterInfo, needed,
1319 &needed);
1320 GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
1321 PrintStructures->lpDriverInfo = HeapAlloc(GetProcessHeap(),0,needed);
1322 if (!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)PrintStructures->lpDriverInfo,
1323 needed, &needed)) {
1324 ERR("GetPrinterDriverA failed for %s, fix your config!\n",debugstr_w(PrintStructures->lpPrinterInfo->pPrinterName));
1325 return FALSE;
1326 }
1327 ClosePrinter(hprn);
1328
1329 PRINTDLG_UpdatePrinterInfoTextsW(hDlg, PrintStructures->lpPrinterInfo);
1330
1331 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
1332 PrintStructures->lpDevMode = NULL;
1333
1334 dmSize = DocumentPropertiesW(0, 0, name, NULL, NULL, 0);
1335 if(dmSize == -1) {
1336 ERR("DocumentProperties fails on %s\n", debugstr_w(name));
1337 return FALSE;
1338 }
1339 PrintStructures->lpDevMode = HeapAlloc(GetProcessHeap(), 0, dmSize);
1340 dmSize = DocumentPropertiesW(0, 0, name, PrintStructures->lpDevMode, NULL,
1341 DM_OUT_BUFFER);
1342 if(lppd->hDevMode && (lpdm = GlobalLock(lppd->hDevMode)) &&
1343 !lstrcmpW(lpdm->dmDeviceName,
1344 PrintStructures->lpDevMode->dmDeviceName)) {
1345 /* Supplied devicemode matches current printer so try to use it */
1346 DocumentPropertiesW(0, 0, name, PrintStructures->lpDevMode, lpdm,
1347 DM_OUT_BUFFER | DM_IN_BUFFER);
1348 }
1349 if(lpdm)
1350 GlobalUnlock(lppd->hDevMode);
1351
1352 lpdm = PrintStructures->lpDevMode; /* use this as a shortcut */
1353
1354 if(!(lppd->Flags & PD_PRINTSETUP)) {
1355 /* Print range (All/Range/Selection) */
1356 if(lppd->nFromPage != 0xffff)
1357 SetDlgItemInt(hDlg, edt1, lppd->nFromPage, FALSE);
1358 if(lppd->nToPage != 0xffff)
1359 SetDlgItemInt(hDlg, edt2, lppd->nToPage, FALSE);
1360
1361 CheckRadioButton(hDlg, rad1, rad3, rad1); /* default */
1362 if (lppd->Flags & PD_NOSELECTION)
1363 EnableWindow(GetDlgItem(hDlg, rad2), FALSE);
1364 else
1365 if (lppd->Flags & PD_SELECTION)
1366 CheckRadioButton(hDlg, rad1, rad3, rad2);
1367 if (lppd->Flags & PD_NOPAGENUMS) {
1368 EnableWindow(GetDlgItem(hDlg, rad3), FALSE);
1369 EnableWindow(GetDlgItem(hDlg, stc2),FALSE);
1370 EnableWindow(GetDlgItem(hDlg, edt1), FALSE);
1371 EnableWindow(GetDlgItem(hDlg, stc3),FALSE);
1372 EnableWindow(GetDlgItem(hDlg, edt2), FALSE);
1373 } else {
1374 if (lppd->Flags & PD_PAGENUMS)
1375 CheckRadioButton(hDlg, rad1, rad3, rad3);
1376 }
1377
1378 /* Collate pages */
1379 if (lppd->Flags & PD_COLLATE) {
1380 SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
1381 (LPARAM)PrintStructures->hCollateIcon);
1382 CheckDlgButton(hDlg, chx2, 1);
1383 } else {
1384 SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
1385 (LPARAM)PrintStructures->hNoCollateIcon);
1386 CheckDlgButton(hDlg, chx2, 0);
1387 }
1388
1389 if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
1390 /* if printer doesn't support it: no Collate */
1391 if (!(lpdm->dmFields & DM_COLLATE)) {
1392 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1393 EnableWindow(GetDlgItem(hDlg, ico3), FALSE);
1394 }
1395 }
1396
1397 /* nCopies */
1398 {
1399 INT copies;
1400 if (lppd->hDevMode == 0)
1401 copies = lppd->nCopies;
1402 else
1403 copies = lpdm->u1.s1.dmCopies;
1404 if(copies == 0) copies = 1;
1405 else if(copies < 0) copies = MAX_COPIES;
1406 SetDlgItemInt(hDlg, edt3, copies, FALSE);
1407 }
1408
1409 if (lppd->Flags & PD_USEDEVMODECOPIESANDCOLLATE) {
1410 /* if printer doesn't support it: no nCopies */
1411 if (!(lpdm->dmFields & DM_COPIES)) {
1412 EnableWindow(GetDlgItem(hDlg, edt3), FALSE);
1413 EnableWindow(GetDlgItem(hDlg, stc5), FALSE);
1414 }
1415 }
1416
1417 /* print to file */
1418 CheckDlgButton(hDlg, chx1, (lppd->Flags & PD_PRINTTOFILE) ? 1 : 0);
1419 if (lppd->Flags & PD_DISABLEPRINTTOFILE)
1420 EnableWindow(GetDlgItem(hDlg, chx1), FALSE);
1421 if (lppd->Flags & PD_HIDEPRINTTOFILE)
1422 ShowWindow(GetDlgItem(hDlg, chx1), SW_HIDE);
1423
1424 } else { /* PD_PRINTSETUP */
1425 BOOL bPortrait = (lpdm->u1.s1.dmOrientation == DMORIENT_PORTRAIT);
1426
1427 PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb2,
1428 PrintStructures->lpPrinterInfo->pPrinterName,
1429 PrintStructures->lpPrinterInfo->pPortName,
1430 lpdm);
1431 PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb3,
1432 PrintStructures->lpPrinterInfo->pPrinterName,
1433 PrintStructures->lpPrinterInfo->pPortName,
1434 lpdm);
1435 CheckRadioButton(hDlg, rad1, rad2, bPortrait ? rad1: rad2);
1436 SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
1437 (LPARAM)(bPortrait ? PrintStructures->hPortraitIcon :
1438 PrintStructures->hLandscapeIcon));
1439
1440 }
1441
1442 /* help button */
1443 if ((lppd->Flags & PD_SHOWHELP)==0) {
1444 /* hide if PD_SHOWHELP not specified */
1445 ShowWindow(GetDlgItem(hDlg, pshHelp), SW_HIDE);
1446 }
1447 return TRUE;
1448 }
1449
1450 /***********************************************************************
1451 * check_printer_setup [internal]
1452 */
check_printer_setup(HWND hDlg)1453 static LRESULT check_printer_setup(HWND hDlg)
1454 {
1455 DWORD needed,num;
1456 WCHAR resourcestr[256],resultstr[256];
1457
1458 EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &num);
1459 if(needed == 0)
1460 {
1461 EnumPrintersW(PRINTER_ENUM_CONNECTIONS, NULL, 2, NULL, 0, &needed, &num);
1462 }
1463 if(needed > 0)
1464 return TRUE;
1465 else
1466 {
1467 LoadStringW(COMDLG32_hInstance, PD32_NO_DEVICES,resultstr, 255);
1468 LoadStringW(COMDLG32_hInstance, PD32_PRINT_TITLE,resourcestr, 255);
1469 MessageBoxW(hDlg, resultstr, resourcestr,MB_OK | MB_ICONWARNING);
1470 return FALSE;
1471 }
1472 }
1473
1474 /***********************************************************************
1475 * PRINTDLG_WMInitDialog [internal]
1476 */
PRINTDLG_WMInitDialog(HWND hDlg,PRINT_PTRA * PrintStructures)1477 static LRESULT PRINTDLG_WMInitDialog(HWND hDlg,
1478 PRINT_PTRA* PrintStructures)
1479 {
1480 LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
1481 DEVNAMES *pdn;
1482 DEVMODEA *pdm;
1483 char *name = NULL;
1484 UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1485
1486 /* load Collate ICONs */
1487 /* We load these with LoadImage because they are not a standard
1488 size and we don't want them rescaled */
1489 PrintStructures->hCollateIcon =
1490 LoadImageA(COMDLG32_hInstance, "PD32_COLLATE", IMAGE_ICON, 0, 0, 0);
1491 PrintStructures->hNoCollateIcon =
1492 LoadImageA(COMDLG32_hInstance, "PD32_NOCOLLATE", IMAGE_ICON, 0, 0, 0);
1493
1494 /* These can be done with LoadIcon */
1495 PrintStructures->hPortraitIcon =
1496 LoadIconA(COMDLG32_hInstance, "PD32_PORTRAIT");
1497 PrintStructures->hLandscapeIcon =
1498 LoadIconA(COMDLG32_hInstance, "PD32_LANDSCAPE");
1499
1500 /* display the collate/no_collate icon */
1501 SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
1502 (LPARAM)PrintStructures->hNoCollateIcon);
1503
1504 if(PrintStructures->hCollateIcon == 0 ||
1505 PrintStructures->hNoCollateIcon == 0 ||
1506 PrintStructures->hPortraitIcon == 0 ||
1507 PrintStructures->hLandscapeIcon == 0) {
1508 ERR("no icon in resource file\n");
1509 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1510 EndDialog(hDlg, FALSE);
1511 }
1512
1513 /*
1514 * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
1515 * must be registered and the Help button must be shown.
1516 */
1517 if (lppd->Flags & PD_SHOWHELP) {
1518 if((PrintStructures->HelpMessageID =
1519 RegisterWindowMessageA(HELPMSGSTRINGA)) == 0) {
1520 COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
1521 return FALSE;
1522 }
1523 } else
1524 PrintStructures->HelpMessageID = 0;
1525
1526 if(!(lppd->Flags &PD_PRINTSETUP)) {
1527 PrintStructures->hwndUpDown =
1528 CreateUpDownControl(WS_CHILD | WS_VISIBLE | WS_BORDER |
1529 UDS_NOTHOUSANDS | UDS_ARROWKEYS |
1530 UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 0, 0, 0, 0,
1531 hDlg, UPDOWN_ID, COMDLG32_hInstance,
1532 GetDlgItem(hDlg, edt3), MAX_COPIES, 1, 1);
1533 }
1534
1535 /* FIXME: I allow more freedom than either Win95 or WinNT,
1536 * which do not agree on what errors should be thrown or not
1537 * in case nToPage or nFromPage is out-of-range.
1538 */
1539 if (lppd->nMaxPage < lppd->nMinPage)
1540 lppd->nMaxPage = lppd->nMinPage;
1541 if (lppd->nMinPage == lppd->nMaxPage)
1542 lppd->Flags |= PD_NOPAGENUMS;
1543 if (lppd->nToPage < lppd->nMinPage)
1544 lppd->nToPage = lppd->nMinPage;
1545 if (lppd->nToPage > lppd->nMaxPage)
1546 lppd->nToPage = lppd->nMaxPage;
1547 if (lppd->nFromPage < lppd->nMinPage)
1548 lppd->nFromPage = lppd->nMinPage;
1549 if (lppd->nFromPage > lppd->nMaxPage)
1550 lppd->nFromPage = lppd->nMaxPage;
1551
1552 /* if we have the combo box, fill it */
1553 if (GetDlgItem(hDlg,comboID)) {
1554 /* Fill Combobox
1555 */
1556 pdn = GlobalLock(lppd->hDevNames);
1557 pdm = GlobalLock(lppd->hDevMode);
1558 if(pdn)
1559 name = (char*)pdn + pdn->wDeviceOffset;
1560 else if(pdm)
1561 name = (char*)pdm->dmDeviceName;
1562 PRINTDLG_SetUpPrinterListComboA(hDlg, comboID, name);
1563 if(pdm) GlobalUnlock(lppd->hDevMode);
1564 if(pdn) GlobalUnlock(lppd->hDevNames);
1565
1566 /* Now find selected printer and update rest of dlg */
1567 name = HeapAlloc(GetProcessHeap(),0,256);
1568 if (GetDlgItemTextA(hDlg, comboID, name, 255))
1569 PRINTDLG_ChangePrinterA(hDlg, name, PrintStructures);
1570 HeapFree(GetProcessHeap(),0,name);
1571 } else {
1572 /* else use default printer */
1573 char name[200];
1574 DWORD dwBufLen = ARRAY_SIZE(name);
1575 BOOL ret = GetDefaultPrinterA(name, &dwBufLen);
1576
1577 if (ret)
1578 PRINTDLG_ChangePrinterA(hDlg, name, PrintStructures);
1579 else
1580 FIXME("No default printer found, expect problems!\n");
1581 }
1582 return TRUE;
1583 }
1584
PRINTDLG_WMInitDialogW(HWND hDlg,PRINT_PTRW * PrintStructures)1585 static LRESULT PRINTDLG_WMInitDialogW(HWND hDlg,
1586 PRINT_PTRW* PrintStructures)
1587 {
1588 LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
1589 DEVNAMES *pdn;
1590 DEVMODEW *pdm;
1591 WCHAR *name = NULL;
1592 UINT comboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1593
1594 /* load Collate ICONs */
1595 /* We load these with LoadImage because they are not a standard
1596 size and we don't want them rescaled */
1597 PrintStructures->hCollateIcon =
1598 LoadImageW(COMDLG32_hInstance, pd32_collateW, IMAGE_ICON, 0, 0, 0);
1599 PrintStructures->hNoCollateIcon =
1600 LoadImageW(COMDLG32_hInstance, pd32_nocollateW, IMAGE_ICON, 0, 0, 0);
1601
1602 /* These can be done with LoadIcon */
1603 PrintStructures->hPortraitIcon =
1604 LoadIconW(COMDLG32_hInstance, pd32_portraitW);
1605 PrintStructures->hLandscapeIcon =
1606 LoadIconW(COMDLG32_hInstance, pd32_landscapeW);
1607
1608 /* display the collate/no_collate icon */
1609 SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
1610 (LPARAM)PrintStructures->hNoCollateIcon);
1611
1612 if(PrintStructures->hCollateIcon == 0 ||
1613 PrintStructures->hNoCollateIcon == 0 ||
1614 PrintStructures->hPortraitIcon == 0 ||
1615 PrintStructures->hLandscapeIcon == 0) {
1616 ERR("no icon in resource file\n");
1617 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
1618 EndDialog(hDlg, FALSE);
1619 }
1620
1621 /*
1622 * if lppd->Flags PD_SHOWHELP is specified, a HELPMESGSTRING message
1623 * must be registered and the Help button must be shown.
1624 */
1625 if (lppd->Flags & PD_SHOWHELP) {
1626 if((PrintStructures->HelpMessageID =
1627 RegisterWindowMessageW(HELPMSGSTRINGW)) == 0) {
1628 COMDLG32_SetCommDlgExtendedError(CDERR_REGISTERMSGFAIL);
1629 return FALSE;
1630 }
1631 } else
1632 PrintStructures->HelpMessageID = 0;
1633
1634 if(!(lppd->Flags &PD_PRINTSETUP)) {
1635 PrintStructures->hwndUpDown =
1636 CreateUpDownControl(WS_CHILD | WS_VISIBLE | WS_BORDER |
1637 UDS_NOTHOUSANDS | UDS_ARROWKEYS |
1638 UDS_ALIGNRIGHT | UDS_SETBUDDYINT, 0, 0, 0, 0,
1639 hDlg, UPDOWN_ID, COMDLG32_hInstance,
1640 GetDlgItem(hDlg, edt3), MAX_COPIES, 1, 1);
1641 }
1642
1643 /* FIXME: I allow more freedom than either Win95 or WinNT,
1644 * which do not agree to what errors should be thrown or not
1645 * in case nToPage or nFromPage is out-of-range.
1646 */
1647 if (lppd->nMaxPage < lppd->nMinPage)
1648 lppd->nMaxPage = lppd->nMinPage;
1649 if (lppd->nMinPage == lppd->nMaxPage)
1650 lppd->Flags |= PD_NOPAGENUMS;
1651 if (lppd->nToPage < lppd->nMinPage)
1652 lppd->nToPage = lppd->nMinPage;
1653 if (lppd->nToPage > lppd->nMaxPage)
1654 lppd->nToPage = lppd->nMaxPage;
1655 if (lppd->nFromPage < lppd->nMinPage)
1656 lppd->nFromPage = lppd->nMinPage;
1657 if (lppd->nFromPage > lppd->nMaxPage)
1658 lppd->nFromPage = lppd->nMaxPage;
1659
1660 /* if we have the combo box, fill it */
1661 if (GetDlgItem(hDlg,comboID)) {
1662 /* Fill Combobox
1663 */
1664 pdn = GlobalLock(lppd->hDevNames);
1665 pdm = GlobalLock(lppd->hDevMode);
1666 if(pdn)
1667 name = (WCHAR*)pdn + pdn->wDeviceOffset;
1668 else if(pdm)
1669 name = pdm->dmDeviceName;
1670 PRINTDLG_SetUpPrinterListComboW(hDlg, comboID, name);
1671 if(pdm) GlobalUnlock(lppd->hDevMode);
1672 if(pdn) GlobalUnlock(lppd->hDevNames);
1673
1674 /* Now find selected printer and update rest of dlg */
1675 /* ansi is ok here */
1676 name = HeapAlloc(GetProcessHeap(),0,256*sizeof(WCHAR));
1677 if (GetDlgItemTextW(hDlg, comboID, name, 255))
1678 PRINTDLG_ChangePrinterW(hDlg, name, PrintStructures);
1679 HeapFree(GetProcessHeap(),0,name);
1680 } else {
1681 /* else use default printer */
1682 WCHAR name[200];
1683 DWORD dwBufLen = ARRAY_SIZE(name);
1684 BOOL ret = GetDefaultPrinterW(name, &dwBufLen);
1685
1686 if (ret)
1687 PRINTDLG_ChangePrinterW(hDlg, name, PrintStructures);
1688 else
1689 FIXME("No default printer found, expect problems!\n");
1690 }
1691 return TRUE;
1692 }
1693
1694 /***********************************************************************
1695 * PRINTDLG_WMCommand [internal]
1696 */
PRINTDLG_WMCommandA(HWND hDlg,WPARAM wParam,PRINT_PTRA * PrintStructures)1697 static LRESULT PRINTDLG_WMCommandA(HWND hDlg, WPARAM wParam,
1698 PRINT_PTRA* PrintStructures)
1699 {
1700 LPPRINTDLGA lppd = PrintStructures->lpPrintDlg;
1701 UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1702 LPDEVMODEA lpdm = PrintStructures->lpDevMode;
1703
1704 switch (LOWORD(wParam)) {
1705 case IDOK:
1706 TRACE(" OK button was hit\n");
1707 if (!PRINTDLG_UpdatePrintDlgA(hDlg, PrintStructures)) {
1708 FIXME("Update printdlg was not successful!\n");
1709 return(FALSE);
1710 }
1711 EndDialog(hDlg, TRUE);
1712 return(TRUE);
1713
1714 case IDCANCEL:
1715 TRACE(" CANCEL button was hit\n");
1716 EndDialog(hDlg, FALSE);
1717 return(FALSE);
1718
1719 case pshHelp:
1720 TRACE(" HELP button was hit\n");
1721 SendMessageA(lppd->hwndOwner, PrintStructures->HelpMessageID,
1722 (WPARAM) hDlg, (LPARAM) lppd);
1723 break;
1724
1725 case chx2: /* collate pages checkbox */
1726 if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
1727 SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
1728 (LPARAM)PrintStructures->hCollateIcon);
1729 else
1730 SendDlgItemMessageA(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
1731 (LPARAM)PrintStructures->hNoCollateIcon);
1732 break;
1733 case edt1: /* from page nr editbox */
1734 case edt2: /* to page nr editbox */
1735 if (HIWORD(wParam)==EN_CHANGE) {
1736 WORD nToPage;
1737 WORD nFromPage;
1738 nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
1739 nToPage = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
1740 if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
1741 CheckRadioButton(hDlg, rad1, rad3, rad3);
1742 }
1743 break;
1744
1745 case edt3:
1746 if(HIWORD(wParam) == EN_CHANGE) {
1747 INT copies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
1748 if(copies <= 1)
1749 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1750 else
1751 EnableWindow(GetDlgItem(hDlg, chx2), TRUE);
1752 }
1753 break;
1754
1755 case psh2: /* Properties button */
1756 {
1757 HANDLE hPrinter;
1758 char PrinterName[256];
1759
1760 GetDlgItemTextA(hDlg, PrinterComboID, PrinterName, 255);
1761 if (!OpenPrinterA(PrinterName, &hPrinter, NULL)) {
1762 FIXME(" Call to OpenPrinter did not succeed!\n");
1763 break;
1764 }
1765 DocumentPropertiesA(hDlg, hPrinter, PrinterName,
1766 PrintStructures->lpDevMode,
1767 PrintStructures->lpDevMode,
1768 DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
1769 ClosePrinter(hPrinter);
1770 break;
1771 }
1772
1773 case rad1: /* Paperorientation */
1774 if (lppd->Flags & PD_PRINTSETUP)
1775 {
1776 lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1777 SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
1778 (LPARAM)(PrintStructures->hPortraitIcon));
1779 }
1780 break;
1781
1782 case rad2: /* Paperorientation */
1783 if (lppd->Flags & PD_PRINTSETUP)
1784 {
1785 lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1786 SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
1787 (LPARAM)(PrintStructures->hLandscapeIcon));
1788 }
1789 break;
1790
1791 case cmb1: /* Printer Combobox in PRINT SETUP, quality combobox in PRINT16 */
1792 if (PrinterComboID != LOWORD(wParam)) {
1793 break;
1794 }
1795 /* FALLTHROUGH */
1796 case cmb4: /* Printer combobox */
1797 if (HIWORD(wParam)==CBN_SELCHANGE) {
1798 char *PrinterName;
1799 INT index = SendDlgItemMessageW(hDlg, LOWORD(wParam), CB_GETCURSEL, 0, 0);
1800 INT length = SendDlgItemMessageW(hDlg, LOWORD(wParam), CB_GETLBTEXTLEN, index, 0);
1801 PrinterName = HeapAlloc(GetProcessHeap(),0,length+1);
1802 SendDlgItemMessageA(hDlg, LOWORD(wParam), CB_GETLBTEXT, index, (LPARAM)PrinterName);
1803 PRINTDLG_ChangePrinterA(hDlg, PrinterName, PrintStructures);
1804 HeapFree(GetProcessHeap(),0,PrinterName);
1805 }
1806 break;
1807
1808 case cmb2: /* Papersize */
1809 {
1810 DWORD Sel = SendDlgItemMessageA(hDlg, cmb2, CB_GETCURSEL, 0, 0);
1811 if(Sel != CB_ERR) {
1812 lpdm->u1.s1.dmPaperSize = SendDlgItemMessageA(hDlg, cmb2,
1813 CB_GETITEMDATA,
1814 Sel, 0);
1815 GetDlgItemTextA(hDlg, cmb2, (char *)lpdm->dmFormName, CCHFORMNAME);
1816 }
1817 }
1818 break;
1819
1820 case cmb3: /* Bin */
1821 {
1822 DWORD Sel = SendDlgItemMessageA(hDlg, cmb3, CB_GETCURSEL, 0, 0);
1823 if(Sel != CB_ERR)
1824 lpdm->u1.s1.dmDefaultSource = SendDlgItemMessageA(hDlg, cmb3,
1825 CB_GETITEMDATA, Sel,
1826 0);
1827 }
1828 break;
1829 }
1830 if(lppd->Flags & PD_PRINTSETUP) {
1831 switch (LOWORD(wParam)) {
1832 case rad1: /* orientation */
1833 case rad2:
1834 if (IsDlgButtonChecked(hDlg, rad1) == BST_CHECKED) {
1835 if(lpdm->u1.s1.dmOrientation != DMORIENT_PORTRAIT) {
1836 lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1837 SendDlgItemMessageA(hDlg, stc10, STM_SETIMAGE, IMAGE_ICON,
1838 (LPARAM)PrintStructures->hPortraitIcon);
1839 SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
1840 (LPARAM)PrintStructures->hPortraitIcon);
1841 }
1842 } else {
1843 if(lpdm->u1.s1.dmOrientation != DMORIENT_LANDSCAPE) {
1844 lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1845 SendDlgItemMessageA(hDlg, stc10, STM_SETIMAGE, IMAGE_ICON,
1846 (LPARAM)PrintStructures->hLandscapeIcon);
1847 SendDlgItemMessageA(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
1848 (LPARAM)PrintStructures->hLandscapeIcon);
1849 }
1850 }
1851 break;
1852 }
1853 }
1854 return FALSE;
1855 }
1856
PRINTDLG_WMCommandW(HWND hDlg,WPARAM wParam,PRINT_PTRW * PrintStructures)1857 static LRESULT PRINTDLG_WMCommandW(HWND hDlg, WPARAM wParam,
1858 PRINT_PTRW* PrintStructures)
1859 {
1860 LPPRINTDLGW lppd = PrintStructures->lpPrintDlg;
1861 UINT PrinterComboID = (lppd->Flags & PD_PRINTSETUP) ? cmb1 : cmb4;
1862 LPDEVMODEW lpdm = PrintStructures->lpDevMode;
1863
1864 switch (LOWORD(wParam)) {
1865 case IDOK:
1866 TRACE(" OK button was hit\n");
1867 if (!PRINTDLG_UpdatePrintDlgW(hDlg, PrintStructures)) {
1868 FIXME("Update printdlg was not successful!\n");
1869 return(FALSE);
1870 }
1871 EndDialog(hDlg, TRUE);
1872 return(TRUE);
1873
1874 case IDCANCEL:
1875 TRACE(" CANCEL button was hit\n");
1876 EndDialog(hDlg, FALSE);
1877 return(FALSE);
1878
1879 case pshHelp:
1880 TRACE(" HELP button was hit\n");
1881 SendMessageW(lppd->hwndOwner, PrintStructures->HelpMessageID,
1882 (WPARAM) hDlg, (LPARAM) lppd);
1883 break;
1884
1885 case chx2: /* collate pages checkbox */
1886 if (IsDlgButtonChecked(hDlg, chx2) == BST_CHECKED)
1887 SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
1888 (LPARAM)PrintStructures->hCollateIcon);
1889 else
1890 SendDlgItemMessageW(hDlg, ico3, STM_SETIMAGE, IMAGE_ICON,
1891 (LPARAM)PrintStructures->hNoCollateIcon);
1892 break;
1893 case edt1: /* from page nr editbox */
1894 case edt2: /* to page nr editbox */
1895 if (HIWORD(wParam)==EN_CHANGE) {
1896 WORD nToPage;
1897 WORD nFromPage;
1898 nFromPage = GetDlgItemInt(hDlg, edt1, NULL, FALSE);
1899 nToPage = GetDlgItemInt(hDlg, edt2, NULL, FALSE);
1900 if (nFromPage != lppd->nFromPage || nToPage != lppd->nToPage)
1901 CheckRadioButton(hDlg, rad1, rad3, rad3);
1902 }
1903 break;
1904
1905 case edt3:
1906 if(HIWORD(wParam) == EN_CHANGE) {
1907 INT copies = GetDlgItemInt(hDlg, edt3, NULL, FALSE);
1908 if(copies <= 1)
1909 EnableWindow(GetDlgItem(hDlg, chx2), FALSE);
1910 else
1911 EnableWindow(GetDlgItem(hDlg, chx2), TRUE);
1912 }
1913 break;
1914
1915 case psh2: /* Properties button */
1916 {
1917 HANDLE hPrinter;
1918 WCHAR PrinterName[256];
1919
1920 if (!GetDlgItemTextW(hDlg, PrinterComboID, PrinterName, 255)) break;
1921 if (!OpenPrinterW(PrinterName, &hPrinter, NULL)) {
1922 FIXME(" Call to OpenPrinter did not succeed!\n");
1923 break;
1924 }
1925 DocumentPropertiesW(hDlg, hPrinter, PrinterName,
1926 PrintStructures->lpDevMode,
1927 PrintStructures->lpDevMode,
1928 DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
1929 ClosePrinter(hPrinter);
1930 break;
1931 }
1932
1933 case rad1: /* Paperorientation */
1934 if (lppd->Flags & PD_PRINTSETUP)
1935 {
1936 lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1937 SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
1938 (LPARAM)(PrintStructures->hPortraitIcon));
1939 }
1940 break;
1941
1942 case rad2: /* Paperorientation */
1943 if (lppd->Flags & PD_PRINTSETUP)
1944 {
1945 lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
1946 SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
1947 (LPARAM)(PrintStructures->hLandscapeIcon));
1948 }
1949 break;
1950
1951 case cmb1: /* Printer Combobox in PRINT SETUP */
1952 /* FALLTHROUGH */
1953 case cmb4: /* Printer combobox */
1954 if (HIWORD(wParam)==CBN_SELCHANGE) {
1955 WCHAR *PrinterName;
1956 INT index = SendDlgItemMessageW(hDlg, LOWORD(wParam), CB_GETCURSEL, 0, 0);
1957 INT length = SendDlgItemMessageW(hDlg, LOWORD(wParam), CB_GETLBTEXTLEN, index, 0);
1958
1959 PrinterName = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(length+1));
1960 SendDlgItemMessageW(hDlg, LOWORD(wParam), CB_GETLBTEXT, index, (LPARAM)PrinterName);
1961 PRINTDLG_ChangePrinterW(hDlg, PrinterName, PrintStructures);
1962 HeapFree(GetProcessHeap(),0,PrinterName);
1963 }
1964 break;
1965
1966 case cmb2: /* Papersize */
1967 {
1968 DWORD Sel = SendDlgItemMessageW(hDlg, cmb2, CB_GETCURSEL, 0, 0);
1969 if(Sel != CB_ERR) {
1970 lpdm->u1.s1.dmPaperSize = SendDlgItemMessageW(hDlg, cmb2,
1971 CB_GETITEMDATA,
1972 Sel, 0);
1973 GetDlgItemTextW(hDlg, cmb2, lpdm->dmFormName, CCHFORMNAME);
1974 }
1975 }
1976 break;
1977
1978 case cmb3: /* Bin */
1979 {
1980 DWORD Sel = SendDlgItemMessageW(hDlg, cmb3, CB_GETCURSEL, 0, 0);
1981 if(Sel != CB_ERR)
1982 lpdm->u1.s1.dmDefaultSource = SendDlgItemMessageW(hDlg, cmb3,
1983 CB_GETITEMDATA, Sel,
1984 0);
1985 }
1986 break;
1987 }
1988 if(lppd->Flags & PD_PRINTSETUP) {
1989 switch (LOWORD(wParam)) {
1990 case rad1: /* orientation */
1991 case rad2:
1992 if (IsDlgButtonChecked(hDlg, rad1) == BST_CHECKED) {
1993 if(lpdm->u1.s1.dmOrientation != DMORIENT_PORTRAIT) {
1994 lpdm->u1.s1.dmOrientation = DMORIENT_PORTRAIT;
1995 SendDlgItemMessageW(hDlg, stc10, STM_SETIMAGE, IMAGE_ICON,
1996 (LPARAM)PrintStructures->hPortraitIcon);
1997 SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
1998 (LPARAM)PrintStructures->hPortraitIcon);
1999 }
2000 } else {
2001 if(lpdm->u1.s1.dmOrientation != DMORIENT_LANDSCAPE) {
2002 lpdm->u1.s1.dmOrientation = DMORIENT_LANDSCAPE;
2003 SendDlgItemMessageW(hDlg, stc10, STM_SETIMAGE, IMAGE_ICON,
2004 (LPARAM)PrintStructures->hLandscapeIcon);
2005 SendDlgItemMessageW(hDlg, ico1, STM_SETIMAGE, IMAGE_ICON,
2006 (LPARAM)PrintStructures->hLandscapeIcon);
2007 }
2008 }
2009 break;
2010 }
2011 }
2012 return FALSE;
2013 }
2014
2015 /***********************************************************************
2016 * PrintDlgProcA [internal]
2017 */
PrintDlgProcA(HWND hDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)2018 static INT_PTR CALLBACK PrintDlgProcA(HWND hDlg, UINT uMsg, WPARAM wParam,
2019 LPARAM lParam)
2020 {
2021 PRINT_PTRA* PrintStructures;
2022 INT_PTR res = FALSE;
2023
2024 if (uMsg!=WM_INITDIALOG) {
2025 PrintStructures = GetPropW(hDlg, printdlg_prop);
2026 if (!PrintStructures)
2027 return FALSE;
2028 } else {
2029 PrintStructures = (PRINT_PTRA*) lParam;
2030 SetPropW(hDlg, printdlg_prop, PrintStructures);
2031 if(!check_printer_setup(hDlg))
2032 {
2033 EndDialog(hDlg,FALSE);
2034 return FALSE;
2035 }
2036 res = PRINTDLG_WMInitDialog(hDlg, PrintStructures);
2037
2038 if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK)
2039 res = PrintStructures->lpPrintDlg->lpfnPrintHook(
2040 hDlg, uMsg, wParam, (LPARAM)PrintStructures->lpPrintDlg
2041 );
2042 return res;
2043 }
2044
2045 if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) {
2046 res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg,uMsg,wParam,
2047 lParam);
2048 if(res) return res;
2049 }
2050
2051 switch (uMsg) {
2052 case WM_COMMAND:
2053 return PRINTDLG_WMCommandA(hDlg, wParam, PrintStructures);
2054
2055 case WM_DESTROY:
2056 DestroyIcon(PrintStructures->hCollateIcon);
2057 DestroyIcon(PrintStructures->hNoCollateIcon);
2058 DestroyIcon(PrintStructures->hPortraitIcon);
2059 DestroyIcon(PrintStructures->hLandscapeIcon);
2060 if(PrintStructures->hwndUpDown)
2061 DestroyWindow(PrintStructures->hwndUpDown);
2062 return FALSE;
2063 }
2064 return res;
2065 }
2066
PrintDlgProcW(HWND hDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)2067 static INT_PTR CALLBACK PrintDlgProcW(HWND hDlg, UINT uMsg, WPARAM wParam,
2068 LPARAM lParam)
2069 {
2070 PRINT_PTRW* PrintStructures;
2071 INT_PTR res = FALSE;
2072
2073 if (uMsg!=WM_INITDIALOG) {
2074 PrintStructures = GetPropW(hDlg, printdlg_prop);
2075 if (!PrintStructures)
2076 return FALSE;
2077 } else {
2078 PrintStructures = (PRINT_PTRW*) lParam;
2079 SetPropW(hDlg, printdlg_prop, PrintStructures);
2080 if(!check_printer_setup(hDlg))
2081 {
2082 EndDialog(hDlg,FALSE);
2083 return FALSE;
2084 }
2085 res = PRINTDLG_WMInitDialogW(hDlg, PrintStructures);
2086
2087 if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK)
2088 res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg, uMsg, wParam, (LPARAM)PrintStructures->lpPrintDlg);
2089 return res;
2090 }
2091
2092 if(PrintStructures->lpPrintDlg->Flags & PD_ENABLEPRINTHOOK) {
2093 res = PrintStructures->lpPrintDlg->lpfnPrintHook(hDlg,uMsg,wParam, lParam);
2094 if(res) return res;
2095 }
2096
2097 switch (uMsg) {
2098 case WM_COMMAND:
2099 return PRINTDLG_WMCommandW(hDlg, wParam, PrintStructures);
2100
2101 case WM_DESTROY:
2102 DestroyIcon(PrintStructures->hCollateIcon);
2103 DestroyIcon(PrintStructures->hNoCollateIcon);
2104 DestroyIcon(PrintStructures->hPortraitIcon);
2105 DestroyIcon(PrintStructures->hLandscapeIcon);
2106 if(PrintStructures->hwndUpDown)
2107 DestroyWindow(PrintStructures->hwndUpDown);
2108 return FALSE;
2109 }
2110 return res;
2111 }
2112
2113 /************************************************************
2114 *
2115 * PRINTDLG_GetDlgTemplate
2116 *
2117 */
PRINTDLG_GetDlgTemplateA(const PRINTDLGA * lppd)2118 static HGLOBAL PRINTDLG_GetDlgTemplateA(const PRINTDLGA *lppd)
2119 {
2120 HRSRC hResInfo;
2121 HGLOBAL hDlgTmpl;
2122
2123 if (lppd->Flags & PD_PRINTSETUP) {
2124 if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
2125 hDlgTmpl = lppd->hSetupTemplate;
2126 } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {
2127 hResInfo = FindResourceA(lppd->hInstance,
2128 lppd->lpSetupTemplateName, (LPSTR)RT_DIALOG);
2129 hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2130 } else {
2131 hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32_SETUP",
2132 (LPSTR)RT_DIALOG);
2133 hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
2134 }
2135 } else {
2136 if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
2137 hDlgTmpl = lppd->hPrintTemplate;
2138 } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
2139 hResInfo = FindResourceA(lppd->hInstance,
2140 lppd->lpPrintTemplateName,
2141 (LPSTR)RT_DIALOG);
2142 hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2143 } else {
2144 hResInfo = FindResourceA(COMDLG32_hInstance, "PRINT32",
2145 (LPSTR)RT_DIALOG);
2146 hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
2147 }
2148 }
2149 return hDlgTmpl;
2150 }
2151
PRINTDLG_GetDlgTemplateW(const PRINTDLGW * lppd)2152 static HGLOBAL PRINTDLG_GetDlgTemplateW(const PRINTDLGW *lppd)
2153 {
2154 HRSRC hResInfo;
2155 HGLOBAL hDlgTmpl;
2156 static const WCHAR xpsetup[] = { 'P','R','I','N','T','3','2','_','S','E','T','U','P',0};
2157 static const WCHAR xprint[] = { 'P','R','I','N','T','3','2',0};
2158
2159 if (lppd->Flags & PD_PRINTSETUP) {
2160 if(lppd->Flags & PD_ENABLESETUPTEMPLATEHANDLE) {
2161 hDlgTmpl = lppd->hSetupTemplate;
2162 } else if(lppd->Flags & PD_ENABLESETUPTEMPLATE) {
2163 hResInfo = FindResourceW(lppd->hInstance,
2164 lppd->lpSetupTemplateName, (LPWSTR)RT_DIALOG);
2165 hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2166 } else {
2167 hResInfo = FindResourceW(COMDLG32_hInstance, xpsetup, (LPWSTR)RT_DIALOG);
2168 hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
2169 }
2170 } else {
2171 if(lppd->Flags & PD_ENABLEPRINTTEMPLATEHANDLE) {
2172 hDlgTmpl = lppd->hPrintTemplate;
2173 } else if(lppd->Flags & PD_ENABLEPRINTTEMPLATE) {
2174 hResInfo = FindResourceW(lppd->hInstance,
2175 lppd->lpPrintTemplateName,
2176 (LPWSTR)RT_DIALOG);
2177 hDlgTmpl = LoadResource(lppd->hInstance, hResInfo);
2178 } else {
2179 hResInfo = FindResourceW(COMDLG32_hInstance, xprint, (LPWSTR)RT_DIALOG);
2180 hDlgTmpl = LoadResource(COMDLG32_hInstance, hResInfo);
2181 }
2182 }
2183 return hDlgTmpl;
2184 }
2185
2186 /***********************************************************************
2187 *
2188 * PRINTDLG_CreateDC
2189 *
2190 */
PRINTDLG_CreateDCA(LPPRINTDLGA lppd)2191 static BOOL PRINTDLG_CreateDCA(LPPRINTDLGA lppd)
2192 {
2193 DEVNAMES *pdn = GlobalLock(lppd->hDevNames);
2194 DEVMODEA *pdm = GlobalLock(lppd->hDevMode);
2195
2196 if(lppd->Flags & PD_RETURNDC) {
2197 lppd->hDC = CreateDCA((char*)pdn + pdn->wDriverOffset,
2198 (char*)pdn + pdn->wDeviceOffset,
2199 (char*)pdn + pdn->wOutputOffset,
2200 pdm );
2201 } else if(lppd->Flags & PD_RETURNIC) {
2202 lppd->hDC = CreateICA((char*)pdn + pdn->wDriverOffset,
2203 (char*)pdn + pdn->wDeviceOffset,
2204 (char*)pdn + pdn->wOutputOffset,
2205 pdm );
2206 }
2207 GlobalUnlock(lppd->hDevNames);
2208 GlobalUnlock(lppd->hDevMode);
2209 return lppd->hDC != NULL;
2210 }
2211
PRINTDLG_CreateDCW(LPPRINTDLGW lppd)2212 static BOOL PRINTDLG_CreateDCW(LPPRINTDLGW lppd)
2213 {
2214 DEVNAMES *pdn = GlobalLock(lppd->hDevNames);
2215 DEVMODEW *pdm = GlobalLock(lppd->hDevMode);
2216
2217 if(lppd->Flags & PD_RETURNDC) {
2218 lppd->hDC = CreateDCW((WCHAR*)pdn + pdn->wDriverOffset,
2219 (WCHAR*)pdn + pdn->wDeviceOffset,
2220 (WCHAR*)pdn + pdn->wOutputOffset,
2221 pdm );
2222 } else if(lppd->Flags & PD_RETURNIC) {
2223 lppd->hDC = CreateICW((WCHAR*)pdn + pdn->wDriverOffset,
2224 (WCHAR*)pdn + pdn->wDeviceOffset,
2225 (WCHAR*)pdn + pdn->wOutputOffset,
2226 pdm );
2227 }
2228 GlobalUnlock(lppd->hDevNames);
2229 GlobalUnlock(lppd->hDevMode);
2230 return lppd->hDC != NULL;
2231 }
2232
2233 /***********************************************************************
2234 * PrintDlgA (COMDLG32.@)
2235 *
2236 * Displays the PRINT dialog box, which enables the user to specify
2237 * specific properties of the print job.
2238 *
2239 * PARAMS
2240 * lppd [IO] ptr to PRINTDLG32 struct
2241 *
2242 * RETURNS
2243 * nonzero if the user pressed the OK button
2244 * zero if the user cancelled the window or an error occurred
2245 *
2246 * BUGS
2247 * PrintDlg:
2248 * * The Collate Icons do not display, even though they are in the code.
2249 * * The Properties Button(s) should call DocumentPropertiesA().
2250 */
2251
PrintDlgA(LPPRINTDLGA lppd)2252 BOOL WINAPI PrintDlgA(LPPRINTDLGA lppd)
2253 {
2254 BOOL bRet = FALSE;
2255 LPVOID ptr;
2256 HINSTANCE hInst;
2257
2258 if (!lppd)
2259 {
2260 COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION);
2261 return FALSE;
2262 }
2263
2264 if(TRACE_ON(commdlg)) {
2265 char flagstr[1000] = "";
2266 const struct pd_flags *pflag = pd_flags;
2267 for( ; pflag->name; pflag++) {
2268 if(lppd->Flags & pflag->flag)
2269 strcat(flagstr, pflag->name);
2270 }
2271 TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
2272 "pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
2273 "flags %08x (%s)\n",
2274 lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
2275 lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
2276 lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
2277 }
2278
2279 if(lppd->lStructSize != sizeof(PRINTDLGA)) {
2280 WARN("structure size failure!!!\n");
2281 COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
2282 return FALSE;
2283 }
2284
2285 if(lppd->Flags & PD_RETURNDEFAULT) {
2286 PRINTER_INFO_2A *pbuf;
2287 DRIVER_INFO_3A *dbuf;
2288 HANDLE hprn;
2289 DWORD needed;
2290
2291 if(lppd->hDevMode || lppd->hDevNames) {
2292 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
2293 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2294 return FALSE;
2295 }
2296 if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
2297 WARN("Can't find default printer\n");
2298 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
2299 return FALSE;
2300 }
2301
2302 GetPrinterA(hprn, 2, NULL, 0, &needed);
2303 pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
2304 GetPrinterA(hprn, 2, (LPBYTE)pbuf, needed, &needed);
2305
2306 GetPrinterDriverA(hprn, NULL, 3, NULL, 0, &needed);
2307 dbuf = HeapAlloc(GetProcessHeap(),0,needed);
2308 if (!GetPrinterDriverA(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) {
2309 ERR("GetPrinterDriverA failed, le %d, fix your config for printer %s!\n",
2310 GetLastError(),pbuf->pPrinterName);
2311 HeapFree(GetProcessHeap(), 0, dbuf);
2312 HeapFree(GetProcessHeap(), 0, pbuf);
2313 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2314 return FALSE;
2315 }
2316 ClosePrinter(hprn);
2317
2318 PRINTDLG_CreateDevNames(&(lppd->hDevNames),
2319 dbuf->pDriverPath,
2320 pbuf->pPrinterName,
2321 pbuf->pPortName);
2322 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
2323 pbuf->pDevMode->dmDriverExtra);
2324 ptr = GlobalLock(lppd->hDevMode);
2325 memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
2326 pbuf->pDevMode->dmDriverExtra);
2327 GlobalUnlock(lppd->hDevMode);
2328 HeapFree(GetProcessHeap(), 0, pbuf);
2329 HeapFree(GetProcessHeap(), 0, dbuf);
2330 bRet = TRUE;
2331 } else {
2332 HGLOBAL hDlgTmpl;
2333 PRINT_PTRA *PrintStructures;
2334
2335 /* load Dialog resources,
2336 * depending on Flags indicates Print32 or Print32_setup dialog
2337 */
2338 hDlgTmpl = PRINTDLG_GetDlgTemplateA(lppd);
2339 if (!hDlgTmpl) {
2340 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2341 return FALSE;
2342 }
2343 ptr = LockResource( hDlgTmpl );
2344 if (!ptr) {
2345 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2346 return FALSE;
2347 }
2348
2349 PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2350 sizeof(PRINT_PTRA));
2351 PrintStructures->lpPrintDlg = lppd;
2352
2353 /* and create & process the dialog .
2354 * -1 is failure, 0 is broken hwnd, everything else is ok.
2355 */
2356 hInst = COMDLG32_hInstance;
2357 if (lppd->Flags & (PD_ENABLESETUPTEMPLATE | PD_ENABLEPRINTTEMPLATE)) hInst = lppd->hInstance;
2358 bRet = (0<DialogBoxIndirectParamA(hInst, ptr, lppd->hwndOwner,
2359 PrintDlgProcA,
2360 (LPARAM)PrintStructures));
2361
2362 if(bRet) {
2363 DEVMODEA *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
2364 PRINTER_INFO_2A *pi = PrintStructures->lpPrinterInfo;
2365 DRIVER_INFO_3A *di = PrintStructures->lpDriverInfo;
2366
2367 if (lppd->hDevMode == 0) {
2368 TRACE(" No hDevMode yet... Need to create my own\n");
2369 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE,
2370 lpdm->dmSize + lpdm->dmDriverExtra);
2371 } else {
2372 lppd->hDevMode = GlobalReAlloc(lppd->hDevMode,
2373 lpdm->dmSize + lpdm->dmDriverExtra,
2374 GMEM_MOVEABLE);
2375 }
2376 lpdmReturn = GlobalLock(lppd->hDevMode);
2377 memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
2378
2379 PRINTDLG_CreateDevNames(&(lppd->hDevNames),
2380 di->pDriverPath,
2381 pi->pPrinterName,
2382 pi->pPortName
2383 );
2384 GlobalUnlock(lppd->hDevMode);
2385 }
2386 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
2387 HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
2388 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo);
2389 HeapFree(GetProcessHeap(), 0, PrintStructures);
2390 }
2391 if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
2392 bRet = PRINTDLG_CreateDCA(lppd);
2393
2394 TRACE("exit! (%d)\n", bRet);
2395 return bRet;
2396 }
2397
2398 /***********************************************************************
2399 * PrintDlgW (COMDLG32.@)
2400 *
2401 * See PrintDlgA.
2402 */
PrintDlgW(LPPRINTDLGW lppd)2403 BOOL WINAPI PrintDlgW(LPPRINTDLGW lppd)
2404 {
2405 BOOL bRet = FALSE;
2406 LPVOID ptr;
2407 HINSTANCE hInst;
2408
2409 if (!lppd)
2410 {
2411 COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION);
2412 return FALSE;
2413 }
2414
2415 if(TRACE_ON(commdlg)) {
2416 char flagstr[1000] = "";
2417 const struct pd_flags *pflag = pd_flags;
2418 for( ; pflag->name; pflag++) {
2419 if(lppd->Flags & pflag->flag)
2420 strcat(flagstr, pflag->name);
2421 }
2422 TRACE("(%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
2423 "pp. %d-%d, min p %d, max p %d, copies %d, hinst %p\n"
2424 "flags %08x (%s)\n",
2425 lppd, lppd->hwndOwner, lppd->hDevMode, lppd->hDevNames,
2426 lppd->nFromPage, lppd->nToPage, lppd->nMinPage, lppd->nMaxPage,
2427 lppd->nCopies, lppd->hInstance, lppd->Flags, flagstr);
2428 }
2429
2430 if(lppd->lStructSize != sizeof(PRINTDLGW)) {
2431 WARN("structure size failure!!!\n");
2432 COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
2433 return FALSE;
2434 }
2435
2436 if(lppd->Flags & PD_RETURNDEFAULT) {
2437 PRINTER_INFO_2W *pbuf;
2438 DRIVER_INFO_3W *dbuf;
2439 HANDLE hprn;
2440 DWORD needed;
2441
2442 if(lppd->hDevMode || lppd->hDevNames) {
2443 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
2444 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2445 return FALSE;
2446 }
2447 if(!PRINTDLG_OpenDefaultPrinter(&hprn)) {
2448 WARN("Can't find default printer\n");
2449 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
2450 return FALSE;
2451 }
2452
2453 GetPrinterW(hprn, 2, NULL, 0, &needed);
2454 pbuf = HeapAlloc(GetProcessHeap(), 0, needed);
2455 GetPrinterW(hprn, 2, (LPBYTE)pbuf, needed, &needed);
2456
2457 GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
2458 dbuf = HeapAlloc(GetProcessHeap(),0,needed);
2459 if (!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)dbuf, needed, &needed)) {
2460 ERR("GetPrinterDriverA failed, le %d, fix your config for printer %s!\n",
2461 GetLastError(),debugstr_w(pbuf->pPrinterName));
2462 HeapFree(GetProcessHeap(), 0, dbuf);
2463 HeapFree(GetProcessHeap(), 0, pbuf);
2464 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
2465 return FALSE;
2466 }
2467 ClosePrinter(hprn);
2468
2469 PRINTDLG_CreateDevNamesW(&(lppd->hDevNames),
2470 dbuf->pDriverPath,
2471 pbuf->pPrinterName,
2472 pbuf->pPortName);
2473 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, pbuf->pDevMode->dmSize +
2474 pbuf->pDevMode->dmDriverExtra);
2475 ptr = GlobalLock(lppd->hDevMode);
2476 memcpy(ptr, pbuf->pDevMode, pbuf->pDevMode->dmSize +
2477 pbuf->pDevMode->dmDriverExtra);
2478 GlobalUnlock(lppd->hDevMode);
2479 HeapFree(GetProcessHeap(), 0, pbuf);
2480 HeapFree(GetProcessHeap(), 0, dbuf);
2481 bRet = TRUE;
2482 } else {
2483 HGLOBAL hDlgTmpl;
2484 PRINT_PTRW *PrintStructures;
2485
2486 /* load Dialog resources,
2487 * depending on Flags indicates Print32 or Print32_setup dialog
2488 */
2489 hDlgTmpl = PRINTDLG_GetDlgTemplateW(lppd);
2490 if (!hDlgTmpl) {
2491 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2492 return FALSE;
2493 }
2494 ptr = LockResource( hDlgTmpl );
2495 if (!ptr) {
2496 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
2497 return FALSE;
2498 }
2499
2500 PrintStructures = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2501 sizeof(PRINT_PTRW));
2502 PrintStructures->lpPrintDlg = lppd;
2503
2504 /* and create & process the dialog .
2505 * -1 is failure, 0 is broken hwnd, everything else is ok.
2506 */
2507 hInst = COMDLG32_hInstance;
2508 if (lppd->Flags & (PD_ENABLESETUPTEMPLATE | PD_ENABLEPRINTTEMPLATE)) hInst = lppd->hInstance;
2509 bRet = (0<DialogBoxIndirectParamW(hInst, ptr, lppd->hwndOwner,
2510 PrintDlgProcW,
2511 (LPARAM)PrintStructures));
2512
2513 if(bRet) {
2514 DEVMODEW *lpdm = PrintStructures->lpDevMode, *lpdmReturn;
2515 PRINTER_INFO_2W *pi = PrintStructures->lpPrinterInfo;
2516 DRIVER_INFO_3W *di = PrintStructures->lpDriverInfo;
2517
2518 if (lppd->hDevMode == 0) {
2519 TRACE(" No hDevMode yet... Need to create my own\n");
2520 lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE,
2521 lpdm->dmSize + lpdm->dmDriverExtra);
2522 } else {
2523 WORD locks;
2524 if((locks = (GlobalFlags(lppd->hDevMode) & GMEM_LOCKCOUNT))) {
2525 WARN("hDevMode has %d locks on it. Unlocking it now\n", locks);
2526 while(locks--) {
2527 GlobalUnlock(lppd->hDevMode);
2528 TRACE("Now got %d locks\n", locks);
2529 }
2530 }
2531 lppd->hDevMode = GlobalReAlloc(lppd->hDevMode,
2532 lpdm->dmSize + lpdm->dmDriverExtra,
2533 GMEM_MOVEABLE);
2534 }
2535 lpdmReturn = GlobalLock(lppd->hDevMode);
2536 memcpy(lpdmReturn, lpdm, lpdm->dmSize + lpdm->dmDriverExtra);
2537
2538 if (lppd->hDevNames != 0) {
2539 WORD locks;
2540 if((locks = (GlobalFlags(lppd->hDevNames) & GMEM_LOCKCOUNT))) {
2541 WARN("hDevNames has %d locks on it. Unlocking it now\n", locks);
2542 while(locks--)
2543 GlobalUnlock(lppd->hDevNames);
2544 }
2545 }
2546 PRINTDLG_CreateDevNamesW(&(lppd->hDevNames),
2547 di->pDriverPath,
2548 pi->pPrinterName,
2549 pi->pPortName
2550 );
2551 GlobalUnlock(lppd->hDevMode);
2552 }
2553 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDevMode);
2554 HeapFree(GetProcessHeap(), 0, PrintStructures->lpPrinterInfo);
2555 HeapFree(GetProcessHeap(), 0, PrintStructures->lpDriverInfo);
2556 HeapFree(GetProcessHeap(), 0, PrintStructures);
2557 }
2558 if(bRet && (lppd->Flags & PD_RETURNDC || lppd->Flags & PD_RETURNIC))
2559 bRet = PRINTDLG_CreateDCW(lppd);
2560
2561 TRACE("exit! (%d)\n", bRet);
2562 return bRet;
2563 }
2564
2565 /***********************************************************************
2566 *
2567 * PageSetupDlg
2568 * rad1 - portrait
2569 * rad2 - landscape
2570 * cmb1 - printer select (not in standard dialog template)
2571 * cmb2 - paper size
2572 * cmb3 - source (tray?)
2573 * edt4 - border left
2574 * edt5 - border top
2575 * edt6 - border right
2576 * edt7 - border bottom
2577 * psh3 - "Printer..."
2578 */
2579
2580 typedef struct
2581 {
2582 BOOL unicode;
2583 union
2584 {
2585 LPPAGESETUPDLGA dlga;
2586 LPPAGESETUPDLGW dlgw;
2587 } u;
2588 HWND hDlg; /* Page Setup dialog handle */
2589 RECT rtDrawRect; /* Drawing rect for page */
2590 } pagesetup_data;
2591
pagesetup_get_flags(const pagesetup_data * data)2592 static inline DWORD pagesetup_get_flags(const pagesetup_data *data)
2593 {
2594 return data->u.dlgw->Flags;
2595 }
2596
is_metric(const pagesetup_data * data)2597 static inline BOOL is_metric(const pagesetup_data *data)
2598 {
2599 return pagesetup_get_flags(data) & PSD_INHUNDREDTHSOFMILLIMETERS;
2600 }
2601
tenths_mm_to_size(const pagesetup_data * data,LONG size)2602 static inline LONG tenths_mm_to_size(const pagesetup_data *data, LONG size)
2603 {
2604 if (is_metric(data))
2605 return 10 * size;
2606 else
2607 return 10 * size * 100 / 254;
2608 }
2609
thousandths_inch_to_size(const pagesetup_data * data,LONG size)2610 static inline LONG thousandths_inch_to_size(const pagesetup_data *data, LONG size)
2611 {
2612 if (is_metric(data))
2613 return size * 254 / 100;
2614 else
2615 return size;
2616 }
2617
get_decimal_sep(void)2618 static WCHAR get_decimal_sep(void)
2619 {
2620 static WCHAR sep;
2621
2622 if(!sep)
2623 {
2624 WCHAR buf[] = {'.', 0};
2625 GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, buf, ARRAY_SIZE(buf));
2626 sep = buf[0];
2627 }
2628 return sep;
2629 }
2630
size2str(const pagesetup_data * data,DWORD size,LPWSTR strout)2631 static void size2str(const pagesetup_data *data, DWORD size, LPWSTR strout)
2632 {
2633 static const WCHAR integer_fmt[] = {'%','d',0};
2634 static const WCHAR hundredths_fmt[] = {'%','d','%','c','%','0','2','d',0};
2635 static const WCHAR thousandths_fmt[] = {'%','d','%','c','%','0','3','d',0};
2636
2637 /* FIXME use LOCALE_SDECIMAL when the edit parsing code can cope */
2638
2639 if (is_metric(data))
2640 {
2641 if(size % 100)
2642 wsprintfW(strout, hundredths_fmt, size / 100, get_decimal_sep(), size % 100);
2643 else
2644 wsprintfW(strout, integer_fmt, size / 100);
2645 }
2646 else
2647 {
2648 if(size % 1000)
2649 wsprintfW(strout, thousandths_fmt, size / 1000, get_decimal_sep(), size % 1000);
2650 else
2651 wsprintfW(strout, integer_fmt, size / 1000);
2652
2653 }
2654 }
2655
is_default_metric(void)2656 static inline BOOL is_default_metric(void)
2657 {
2658 DWORD system;
2659 GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_IMEASURE | LOCALE_RETURN_NUMBER,
2660 (LPWSTR)&system, sizeof(system));
2661 return system == 0;
2662 }
2663
2664 /**********************************************
2665 * rotate_rect
2666 * Cyclically permute the four members of rc
2667 * If sense is TRUE l -> t -> r -> b
2668 * otherwise l <- t <- r <- b
2669 */
rotate_rect(RECT * rc,BOOL sense)2670 static inline void rotate_rect(RECT *rc, BOOL sense)
2671 {
2672 INT tmp;
2673 if(sense)
2674 {
2675 tmp = rc->bottom;
2676 rc->bottom = rc->right;
2677 rc->right = rc->top;
2678 rc->top = rc->left;
2679 rc->left = tmp;
2680 }
2681 else
2682 {
2683 tmp = rc->left;
2684 rc->left = rc->top;
2685 rc->top = rc->right;
2686 rc->right = rc->bottom;
2687 rc->bottom = tmp;
2688 }
2689 }
2690
pagesetup_set_orientation(pagesetup_data * data,WORD orient)2691 static void pagesetup_set_orientation(pagesetup_data *data, WORD orient)
2692 {
2693 DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
2694
2695 assert(orient == DMORIENT_PORTRAIT || orient == DMORIENT_LANDSCAPE);
2696
2697 if(data->unicode)
2698 dm->u1.s1.dmOrientation = orient;
2699 else
2700 {
2701 DEVMODEA *dmA = (DEVMODEA *)dm;
2702 dmA->u1.s1.dmOrientation = orient;
2703 }
2704 GlobalUnlock(data->u.dlgw->hDevMode);
2705 }
2706
pagesetup_get_orientation(const pagesetup_data * data)2707 static WORD pagesetup_get_orientation(const pagesetup_data *data)
2708 {
2709 DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
2710 WORD orient;
2711
2712 if(data->unicode)
2713 orient = dm->u1.s1.dmOrientation;
2714 else
2715 {
2716 DEVMODEA *dmA = (DEVMODEA *)dm;
2717 orient = dmA->u1.s1.dmOrientation;
2718 }
2719 GlobalUnlock(data->u.dlgw->hDevMode);
2720 return orient;
2721 }
2722
pagesetup_set_papersize(pagesetup_data * data,WORD paper)2723 static void pagesetup_set_papersize(pagesetup_data *data, WORD paper)
2724 {
2725 DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
2726
2727 if(data->unicode)
2728 dm->u1.s1.dmPaperSize = paper;
2729 else
2730 {
2731 DEVMODEA *dmA = (DEVMODEA *)dm;
2732 dmA->u1.s1.dmPaperSize = paper;
2733 }
2734 GlobalUnlock(data->u.dlgw->hDevMode);
2735 }
2736
pagesetup_get_papersize(const pagesetup_data * data)2737 static WORD pagesetup_get_papersize(const pagesetup_data *data)
2738 {
2739 DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
2740 WORD paper;
2741
2742 if(data->unicode)
2743 paper = dm->u1.s1.dmPaperSize;
2744 else
2745 {
2746 DEVMODEA *dmA = (DEVMODEA *)dm;
2747 paper = dmA->u1.s1.dmPaperSize;
2748 }
2749 GlobalUnlock(data->u.dlgw->hDevMode);
2750 return paper;
2751 }
2752
pagesetup_set_defaultsource(pagesetup_data * data,WORD source)2753 static void pagesetup_set_defaultsource(pagesetup_data *data, WORD source)
2754 {
2755 DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
2756
2757 if(data->unicode)
2758 dm->u1.s1.dmDefaultSource = source;
2759 else
2760 {
2761 DEVMODEA *dmA = (DEVMODEA *)dm;
2762 dmA->u1.s1.dmDefaultSource = source;
2763 }
2764 GlobalUnlock(data->u.dlgw->hDevMode);
2765 }
2766
2767 typedef enum
2768 {
2769 devnames_driver_name,
2770 devnames_device_name,
2771 devnames_output_name
2772 } devnames_name;
2773
2774
get_devname_offset(const DEVNAMES * dn,devnames_name which)2775 static inline WORD get_devname_offset(const DEVNAMES *dn, devnames_name which)
2776 {
2777 switch(which)
2778 {
2779 case devnames_driver_name: return dn->wDriverOffset;
2780 case devnames_device_name: return dn->wDeviceOffset;
2781 case devnames_output_name: return dn->wOutputOffset;
2782 }
2783 ERR("Shouldn't be here\n");
2784 return 0;
2785 }
2786
pagesetup_get_a_devname(const pagesetup_data * data,devnames_name which)2787 static WCHAR *pagesetup_get_a_devname(const pagesetup_data *data, devnames_name which)
2788 {
2789 DEVNAMES *dn;
2790 WCHAR *name;
2791
2792 dn = GlobalLock(data->u.dlgw->hDevNames);
2793 if(data->unicode)
2794 name = strdupW((WCHAR *)dn + get_devname_offset(dn, which));
2795 else
2796 {
2797 int len = MultiByteToWideChar(CP_ACP, 0, (char*)dn + get_devname_offset(dn, which), -1, NULL, 0);
2798 name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2799 MultiByteToWideChar(CP_ACP, 0, (char*)dn + get_devname_offset(dn, which), -1, name, len);
2800 }
2801 GlobalUnlock(data->u.dlgw->hDevNames);
2802 return name;
2803 }
2804
pagesetup_get_drvname(const pagesetup_data * data)2805 static WCHAR *pagesetup_get_drvname(const pagesetup_data *data)
2806 {
2807 return pagesetup_get_a_devname(data, devnames_driver_name);
2808 }
2809
pagesetup_get_devname(const pagesetup_data * data)2810 static WCHAR *pagesetup_get_devname(const pagesetup_data *data)
2811 {
2812 return pagesetup_get_a_devname(data, devnames_device_name);
2813 }
2814
pagesetup_get_portname(const pagesetup_data * data)2815 static WCHAR *pagesetup_get_portname(const pagesetup_data *data)
2816 {
2817 return pagesetup_get_a_devname(data, devnames_output_name);
2818 }
2819
pagesetup_release_a_devname(const pagesetup_data * data,WCHAR * name)2820 static void pagesetup_release_a_devname(const pagesetup_data *data, WCHAR *name)
2821 {
2822 HeapFree(GetProcessHeap(), 0, name);
2823 }
2824
pagesetup_set_devnames(pagesetup_data * data,LPCWSTR drv,LPCWSTR devname,LPCWSTR port)2825 static void pagesetup_set_devnames(pagesetup_data *data, LPCWSTR drv, LPCWSTR devname, LPCWSTR port)
2826 {
2827 DEVNAMES *dn;
2828 WCHAR def[256];
2829 DWORD len = sizeof(DEVNAMES), drv_len, dev_len, port_len;
2830
2831 if(data->unicode)
2832 {
2833 drv_len = (lstrlenW(drv) + 1) * sizeof(WCHAR);
2834 dev_len = (lstrlenW(devname) + 1) * sizeof(WCHAR);
2835 port_len = (lstrlenW(port) + 1) * sizeof(WCHAR);
2836 }
2837 else
2838 {
2839 drv_len = WideCharToMultiByte(CP_ACP, 0, drv, -1, NULL, 0, NULL, NULL);
2840 dev_len = WideCharToMultiByte(CP_ACP, 0, devname, -1, NULL, 0, NULL, NULL);
2841 port_len = WideCharToMultiByte(CP_ACP, 0, port, -1, NULL, 0, NULL, NULL);
2842 }
2843 len += drv_len + dev_len + port_len;
2844
2845 if(data->u.dlgw->hDevNames)
2846 data->u.dlgw->hDevNames = GlobalReAlloc(data->u.dlgw->hDevNames, len, GMEM_MOVEABLE);
2847 else
2848 data->u.dlgw->hDevNames = GlobalAlloc(GMEM_MOVEABLE, len);
2849
2850 dn = GlobalLock(data->u.dlgw->hDevNames);
2851
2852 if(data->unicode)
2853 {
2854 WCHAR *ptr = (WCHAR *)(dn + 1);
2855 len = sizeof(DEVNAMES) / sizeof(WCHAR);
2856 dn->wDriverOffset = len;
2857 lstrcpyW(ptr, drv);
2858 ptr += drv_len / sizeof(WCHAR);
2859 len += drv_len / sizeof(WCHAR);
2860 dn->wDeviceOffset = len;
2861 lstrcpyW(ptr, devname);
2862 ptr += dev_len / sizeof(WCHAR);
2863 len += dev_len / sizeof(WCHAR);
2864 dn->wOutputOffset = len;
2865 lstrcpyW(ptr, port);
2866 }
2867 else
2868 {
2869 char *ptr = (char *)(dn + 1);
2870 len = sizeof(DEVNAMES);
2871 dn->wDriverOffset = len;
2872 WideCharToMultiByte(CP_ACP, 0, drv, -1, ptr, drv_len, NULL, NULL);
2873 ptr += drv_len;
2874 len += drv_len;
2875 dn->wDeviceOffset = len;
2876 WideCharToMultiByte(CP_ACP, 0, devname, -1, ptr, dev_len, NULL, NULL);
2877 ptr += dev_len;
2878 len += dev_len;
2879 dn->wOutputOffset = len;
2880 WideCharToMultiByte(CP_ACP, 0, port, -1, ptr, port_len, NULL, NULL);
2881 }
2882
2883 dn->wDefault = 0;
2884 len = ARRAY_SIZE(def);
2885 GetDefaultPrinterW(def, &len);
2886 if(!lstrcmpW(def, devname))
2887 dn->wDefault = 1;
2888
2889 GlobalUnlock(data->u.dlgw->hDevNames);
2890 }
2891
pagesetup_get_devmode(const pagesetup_data * data)2892 static DEVMODEW *pagesetup_get_devmode(const pagesetup_data *data)
2893 {
2894 DEVMODEW *dm = GlobalLock(data->u.dlgw->hDevMode);
2895 DEVMODEW *ret;
2896
2897 if(data->unicode)
2898 {
2899 /* We make a copy even in the unicode case because the ptr
2900 may get passed back to us in pagesetup_set_devmode. */
2901 ret = HeapAlloc(GetProcessHeap(), 0, dm->dmSize + dm->dmDriverExtra);
2902 memcpy(ret, dm, dm->dmSize + dm->dmDriverExtra);
2903 }
2904 else
2905 ret = GdiConvertToDevmodeW((DEVMODEA *)dm);
2906
2907 GlobalUnlock(data->u.dlgw->hDevMode);
2908 return ret;
2909 }
2910
pagesetup_release_devmode(const pagesetup_data * data,DEVMODEW * dm)2911 static void pagesetup_release_devmode(const pagesetup_data *data, DEVMODEW *dm)
2912 {
2913 HeapFree(GetProcessHeap(), 0, dm);
2914 }
2915
pagesetup_set_devmode(pagesetup_data * data,DEVMODEW * dm)2916 static void pagesetup_set_devmode(pagesetup_data *data, DEVMODEW *dm)
2917 {
2918 DEVMODEA *dmA = NULL;
2919 void *src, *dst;
2920 DWORD size;
2921
2922 if(data->unicode)
2923 {
2924 size = dm->dmSize + dm->dmDriverExtra;
2925 src = dm;
2926 }
2927 else
2928 {
2929 dmA = convert_to_devmodeA(dm);
2930 size = dmA->dmSize + dmA->dmDriverExtra;
2931 src = dmA;
2932 }
2933
2934 if(data->u.dlgw->hDevMode)
2935 data->u.dlgw->hDevMode = GlobalReAlloc(data->u.dlgw->hDevMode, size,
2936 GMEM_MOVEABLE);
2937 else
2938 data->u.dlgw->hDevMode = GlobalAlloc(GMEM_MOVEABLE, size);
2939
2940 dst = GlobalLock(data->u.dlgw->hDevMode);
2941 memcpy(dst, src, size);
2942 GlobalUnlock(data->u.dlgw->hDevMode);
2943 HeapFree(GetProcessHeap(), 0, dmA);
2944 }
2945
pagesetup_get_papersize_pt(const pagesetup_data * data)2946 static inline POINT *pagesetup_get_papersize_pt(const pagesetup_data *data)
2947 {
2948 return &data->u.dlgw->ptPaperSize;
2949 }
2950
pagesetup_get_margin_rect(const pagesetup_data * data)2951 static inline RECT *pagesetup_get_margin_rect(const pagesetup_data *data)
2952 {
2953 return &data->u.dlgw->rtMargin;
2954 }
2955
2956 typedef enum
2957 {
2958 page_setup_hook,
2959 page_paint_hook
2960 } hook_type;
2961
pagesetup_get_hook(const pagesetup_data * data,hook_type which)2962 static inline LPPAGESETUPHOOK pagesetup_get_hook(const pagesetup_data *data, hook_type which)
2963 {
2964 switch(which)
2965 {
2966 case page_setup_hook: return data->u.dlgw->lpfnPageSetupHook;
2967 case page_paint_hook: return data->u.dlgw->lpfnPagePaintHook;
2968 }
2969 return NULL;
2970 }
2971
2972 /* This should only be used in calls to hook procs so we return the ptr
2973 already cast to LPARAM */
pagesetup_get_dlg_struct(const pagesetup_data * data)2974 static inline LPARAM pagesetup_get_dlg_struct(const pagesetup_data *data)
2975 {
2976 return (LPARAM)data->u.dlgw;
2977 }
2978
swap_point(POINT * pt)2979 static inline void swap_point(POINT *pt)
2980 {
2981 LONG tmp = pt->x;
2982 pt->x = pt->y;
2983 pt->y = tmp;
2984 }
2985
pagesetup_update_papersize(pagesetup_data * data)2986 static BOOL pagesetup_update_papersize(pagesetup_data *data)
2987 {
2988 DEVMODEW *dm;
2989 LPWSTR devname, portname;
2990 int i, num;
2991 WORD *words = NULL, paperword;
2992 POINT *points = NULL;
2993 BOOL retval = FALSE;
2994
2995 dm = pagesetup_get_devmode(data);
2996 devname = pagesetup_get_devname(data);
2997 portname = pagesetup_get_portname(data);
2998
2999 num = DeviceCapabilitiesW(devname, portname, DC_PAPERS, NULL, dm);
3000 if (num <= 0)
3001 {
3002 FIXME("No papernames found for %s/%s\n", debugstr_w(devname), debugstr_w(portname));
3003 goto end;
3004 }
3005
3006 words = HeapAlloc(GetProcessHeap(), 0, num * sizeof(WORD));
3007 points = HeapAlloc(GetProcessHeap(), 0, num * sizeof(POINT));
3008
3009 if (num != DeviceCapabilitiesW(devname, portname, DC_PAPERS, (LPWSTR)words, dm))
3010 {
3011 FIXME("Number of returned words is not %d\n", num);
3012 goto end;
3013 }
3014
3015 if (num != DeviceCapabilitiesW(devname, portname, DC_PAPERSIZE, (LPWSTR)points, dm))
3016 {
3017 FIXME("Number of returned sizes is not %d\n", num);
3018 goto end;
3019 }
3020
3021 paperword = pagesetup_get_papersize(data);
3022
3023 for (i = 0; i < num; i++)
3024 if (words[i] == paperword)
3025 break;
3026
3027 if (i == num)
3028 {
3029 FIXME("Papersize %d not found in list?\n", paperword);
3030 goto end;
3031 }
3032
3033 /* this is _10ths_ of a millimeter */
3034 pagesetup_get_papersize_pt(data)->x = tenths_mm_to_size(data, points[i].x);
3035 pagesetup_get_papersize_pt(data)->y = tenths_mm_to_size(data, points[i].y);
3036
3037 if(pagesetup_get_orientation(data) == DMORIENT_LANDSCAPE)
3038 swap_point(pagesetup_get_papersize_pt(data));
3039
3040 retval = TRUE;
3041
3042 end:
3043 HeapFree(GetProcessHeap(), 0, words);
3044 HeapFree(GetProcessHeap(), 0, points);
3045 pagesetup_release_a_devname(data, portname);
3046 pagesetup_release_a_devname(data, devname);
3047 pagesetup_release_devmode(data, dm);
3048
3049 return retval;
3050 }
3051
3052 /**********************************************************************************************
3053 * pagesetup_change_printer
3054 *
3055 * Redefines hDevMode and hDevNames HANDLES and initialises it.
3056 *
3057 */
pagesetup_change_printer(LPWSTR name,pagesetup_data * data)3058 static BOOL pagesetup_change_printer(LPWSTR name, pagesetup_data *data)
3059 {
3060 HANDLE hprn;
3061 DWORD needed;
3062 PRINTER_INFO_2W *prn_info = NULL;
3063 DRIVER_INFO_3W *drv_info = NULL;
3064 DEVMODEW *dm = NULL;
3065 BOOL retval = FALSE;
3066
3067 if(!OpenPrinterW(name, &hprn, NULL))
3068 {
3069 ERR("Can't open printer %s\n", debugstr_w(name));
3070 goto end;
3071 }
3072
3073 GetPrinterW(hprn, 2, NULL, 0, &needed);
3074 prn_info = HeapAlloc(GetProcessHeap(), 0, needed);
3075 GetPrinterW(hprn, 2, (LPBYTE)prn_info, needed, &needed);
3076 GetPrinterDriverW(hprn, NULL, 3, NULL, 0, &needed);
3077 drv_info = HeapAlloc(GetProcessHeap(), 0, needed);
3078 if(!GetPrinterDriverW(hprn, NULL, 3, (LPBYTE)drv_info, needed, &needed))
3079 {
3080 ERR("GetPrinterDriverA failed for %s, fix your config!\n", debugstr_w(prn_info->pPrinterName));
3081 goto end;
3082 }
3083 ClosePrinter(hprn);
3084
3085 needed = DocumentPropertiesW(0, 0, name, NULL, NULL, 0);
3086 if(needed == -1)
3087 {
3088 ERR("DocumentProperties fails on %s\n", debugstr_w(name));
3089 goto end;
3090 }
3091
3092 dm = HeapAlloc(GetProcessHeap(), 0, needed);
3093 DocumentPropertiesW(0, 0, name, dm, NULL, DM_OUT_BUFFER);
3094
3095 pagesetup_set_devmode(data, dm);
3096 pagesetup_set_devnames(data, drv_info->pDriverPath, prn_info->pPrinterName,
3097 prn_info->pPortName);
3098
3099 retval = TRUE;
3100 end:
3101 HeapFree(GetProcessHeap(), 0, dm);
3102 HeapFree(GetProcessHeap(), 0, prn_info);
3103 HeapFree(GetProcessHeap(), 0, drv_info);
3104 return retval;
3105 }
3106
3107 /****************************************************************************************
3108 * pagesetup_init_combos
3109 *
3110 * Fills Printers, Paper and Source combos
3111 *
3112 */
pagesetup_init_combos(HWND hDlg,pagesetup_data * data)3113 static void pagesetup_init_combos(HWND hDlg, pagesetup_data *data)
3114 {
3115 DEVMODEW *dm;
3116 LPWSTR devname, portname;
3117
3118 dm = pagesetup_get_devmode(data);
3119 devname = pagesetup_get_devname(data);
3120 portname = pagesetup_get_portname(data);
3121
3122 PRINTDLG_SetUpPrinterListComboW(hDlg, cmb1, devname);
3123 PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb2, devname, portname, dm);
3124 PRINTDLG_SetUpPaperComboBoxW(hDlg, cmb3, devname, portname, dm);
3125
3126 pagesetup_release_a_devname(data, portname);
3127 pagesetup_release_a_devname(data, devname);
3128 pagesetup_release_devmode(data, dm);
3129 }
3130
3131
3132 /****************************************************************************************
3133 * pagesetup_change_printer_dialog
3134 *
3135 * Pops up another dialog that lets the user pick another printer.
3136 *
3137 * For now we display the PrintDlg, this should display a striped down version of it.
3138 */
pagesetup_change_printer_dialog(HWND hDlg,pagesetup_data * data)3139 static void pagesetup_change_printer_dialog(HWND hDlg, pagesetup_data *data)
3140 {
3141 PRINTDLGW prnt;
3142 LPWSTR drvname, devname, portname;
3143 DEVMODEW *tmp_dm, *dm;
3144
3145 memset(&prnt, 0, sizeof(prnt));
3146 prnt.lStructSize = sizeof(prnt);
3147 prnt.Flags = 0;
3148 prnt.hwndOwner = hDlg;
3149
3150 drvname = pagesetup_get_drvname(data);
3151 devname = pagesetup_get_devname(data);
3152 portname = pagesetup_get_portname(data);
3153 prnt.hDevNames = 0;
3154 PRINTDLG_CreateDevNamesW(&prnt.hDevNames, drvname, devname, portname);
3155 pagesetup_release_a_devname(data, portname);
3156 pagesetup_release_a_devname(data, devname);
3157 pagesetup_release_a_devname(data, drvname);
3158
3159 tmp_dm = pagesetup_get_devmode(data);
3160 prnt.hDevMode = GlobalAlloc(GMEM_MOVEABLE, tmp_dm->dmSize + tmp_dm->dmDriverExtra);
3161 dm = GlobalLock(prnt.hDevMode);
3162 memcpy(dm, tmp_dm, tmp_dm->dmSize + tmp_dm->dmDriverExtra);
3163 GlobalUnlock(prnt.hDevMode);
3164 pagesetup_release_devmode(data, tmp_dm);
3165
3166 if (PrintDlgW(&prnt))
3167 {
3168 DEVMODEW *dm = GlobalLock(prnt.hDevMode);
3169 DEVNAMES *dn = GlobalLock(prnt.hDevNames);
3170
3171 pagesetup_set_devnames(data, (WCHAR*)dn + dn->wDriverOffset,
3172 (WCHAR*)dn + dn->wDeviceOffset, (WCHAR *)dn + dn->wOutputOffset);
3173 pagesetup_set_devmode(data, dm);
3174 GlobalUnlock(prnt.hDevNames);
3175 GlobalUnlock(prnt.hDevMode);
3176 pagesetup_init_combos(hDlg, data);
3177 }
3178
3179 GlobalFree(prnt.hDevMode);
3180 GlobalFree(prnt.hDevNames);
3181
3182 }
3183
3184 /******************************************************************************************
3185 * pagesetup_change_preview
3186 *
3187 * Changes paper preview size / position
3188 *
3189 */
pagesetup_change_preview(const pagesetup_data * data)3190 static void pagesetup_change_preview(const pagesetup_data *data)
3191 {
3192 LONG width, height, x, y;
3193 RECT tmp;
3194 const int shadow = 4;
3195
3196 if(pagesetup_get_orientation(data) == DMORIENT_LANDSCAPE)
3197 {
3198 width = data->rtDrawRect.right - data->rtDrawRect.left;
3199 height = pagesetup_get_papersize_pt(data)->y * width / pagesetup_get_papersize_pt(data)->x;
3200 }
3201 else
3202 {
3203 height = data->rtDrawRect.bottom - data->rtDrawRect.top;
3204 width = pagesetup_get_papersize_pt(data)->x * height / pagesetup_get_papersize_pt(data)->y;
3205 }
3206 x = (data->rtDrawRect.right + data->rtDrawRect.left - width) / 2;
3207 y = (data->rtDrawRect.bottom + data->rtDrawRect.top - height) / 2;
3208 TRACE("draw rect %s x=%d, y=%d, w=%d, h=%d\n",
3209 wine_dbgstr_rect(&data->rtDrawRect), x, y, width, height);
3210
3211 MoveWindow(GetDlgItem(data->hDlg, rct2), x + width, y + shadow, shadow, height, FALSE);
3212 MoveWindow(GetDlgItem(data->hDlg, rct3), x + shadow, y + height, width, shadow, FALSE);
3213 MoveWindow(GetDlgItem(data->hDlg, rct1), x, y, width, height, FALSE);
3214
3215 tmp = data->rtDrawRect;
3216 tmp.right += shadow;
3217 tmp.bottom += shadow;
3218 InvalidateRect(data->hDlg, &tmp, TRUE);
3219 }
3220
element_from_margin_id(RECT * rc,WORD id)3221 static inline LONG *element_from_margin_id(RECT *rc, WORD id)
3222 {
3223 switch(id)
3224 {
3225 case edt4: return &rc->left;
3226 case edt5: return &rc->top;
3227 case edt6: return &rc->right;
3228 case edt7: return &rc->bottom;
3229 }
3230 return NULL;
3231 }
3232
update_margin_edits(HWND hDlg,const pagesetup_data * data,WORD id)3233 static void update_margin_edits(HWND hDlg, const pagesetup_data *data, WORD id)
3234 {
3235 WCHAR str[100];
3236 WORD idx;
3237
3238 for(idx = edt4; idx <= edt7; idx++)
3239 {
3240 if(id == 0 || id == idx)
3241 {
3242 size2str(data, *element_from_margin_id(pagesetup_get_margin_rect(data), idx), str);
3243 SetDlgItemTextW(hDlg, idx, str);
3244 }
3245 }
3246 }
3247
margin_edit_notification(HWND hDlg,const pagesetup_data * data,WORD msg,WORD id)3248 static void margin_edit_notification(HWND hDlg, const pagesetup_data *data, WORD msg, WORD id)
3249 {
3250 switch (msg)
3251 {
3252 case EN_CHANGE:
3253 {
3254 WCHAR buf[10];
3255 LONG val = 0;
3256 LONG *value = element_from_margin_id(pagesetup_get_margin_rect(data), id);
3257
3258 if (GetDlgItemTextW(hDlg, id, buf, ARRAY_SIZE(buf)) != 0)
3259 {
3260 WCHAR *end;
3261 WCHAR decimal = get_decimal_sep();
3262
3263 val = wcstol(buf, &end, 10);
3264 if(end != buf || *end == decimal)
3265 {
3266 int mult = is_metric(data) ? 100 : 1000;
3267 val *= mult;
3268 if(*end == decimal)
3269 {
3270 while(mult > 1)
3271 {
3272 end++;
3273 mult /= 10;
3274 if(iswdigit(*end))
3275 val += (*end - '0') * mult;
3276 else
3277 break;
3278 }
3279 }
3280 }
3281 }
3282 *value = val;
3283 return;
3284 }
3285
3286 case EN_KILLFOCUS:
3287 update_margin_edits(hDlg, data, id);
3288 return;
3289 }
3290 }
3291
set_margin_groupbox_title(HWND hDlg,const pagesetup_data * data)3292 static void set_margin_groupbox_title(HWND hDlg, const pagesetup_data *data)
3293 {
3294 WCHAR title[256];
3295
3296 if(LoadStringW(COMDLG32_hInstance, is_metric(data) ? PD32_MARGINS_IN_MILLIMETERS : PD32_MARGINS_IN_INCHES,
3297 title, ARRAY_SIZE(title)))
3298 SetDlgItemTextW(hDlg, grp4, title);
3299 }
3300
pagesetup_update_orientation_buttons(HWND hDlg,const pagesetup_data * data)3301 static void pagesetup_update_orientation_buttons(HWND hDlg, const pagesetup_data *data)
3302 {
3303 if (pagesetup_get_orientation(data) == DMORIENT_LANDSCAPE)
3304 CheckRadioButton(hDlg, rad1, rad2, rad2);
3305 else
3306 CheckRadioButton(hDlg, rad1, rad2, rad1);
3307 }
3308
3309 /****************************************************************************************
3310 * pagesetup_printer_properties
3311 *
3312 * Handle invocation of the 'Properties' button (not present in the default template).
3313 */
pagesetup_printer_properties(HWND hDlg,pagesetup_data * data)3314 static void pagesetup_printer_properties(HWND hDlg, pagesetup_data *data)
3315 {
3316 HANDLE hprn;
3317 LPWSTR devname;
3318 DEVMODEW *dm;
3319 LRESULT count;
3320 int i;
3321
3322 devname = pagesetup_get_devname(data);
3323
3324 if (!OpenPrinterW(devname, &hprn, NULL))
3325 {
3326 FIXME("Call to OpenPrinter did not succeed!\n");
3327 pagesetup_release_a_devname(data, devname);
3328 return;
3329 }
3330
3331 dm = pagesetup_get_devmode(data);
3332 DocumentPropertiesW(hDlg, hprn, devname, dm, dm, DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
3333 pagesetup_set_devmode(data, dm);
3334 pagesetup_release_devmode(data, dm);
3335 pagesetup_release_a_devname(data, devname);
3336 ClosePrinter(hprn);
3337
3338 /* Changing paper */
3339 pagesetup_update_papersize(data);
3340 pagesetup_update_orientation_buttons(hDlg, data);
3341
3342 /* Changing paper preview */
3343 pagesetup_change_preview(data);
3344
3345 /* Selecting paper in combo */
3346 count = SendDlgItemMessageW(hDlg, cmb2, CB_GETCOUNT, 0, 0);
3347 if(count != CB_ERR)
3348 {
3349 WORD paperword = pagesetup_get_papersize(data);
3350 for(i = 0; i < count; i++)
3351 {
3352 if(SendDlgItemMessageW(hDlg, cmb2, CB_GETITEMDATA, i, 0) == paperword) {
3353 SendDlgItemMessageW(hDlg, cmb2, CB_SETCURSEL, i, 0);
3354 break;
3355 }
3356 }
3357 }
3358 }
3359
3360 /********************************************************************************
3361 * pagesetup_wm_command
3362 * process WM_COMMAND message for PageSetupDlg
3363 *
3364 * PARAMS
3365 * hDlg [in] Main dialog HANDLE
3366 * wParam [in] WM_COMMAND wParam
3367 * lParam [in] WM_COMMAND lParam
3368 * pda [in/out] ptr to PageSetupDataA
3369 */
3370
pagesetup_wm_command(HWND hDlg,WPARAM wParam,LPARAM lParam,pagesetup_data * data)3371 static BOOL pagesetup_wm_command(HWND hDlg, WPARAM wParam, LPARAM lParam, pagesetup_data *data)
3372 {
3373 WORD msg = HIWORD(wParam);
3374 WORD id = LOWORD(wParam);
3375
3376 TRACE("loword (lparam) %d, wparam 0x%lx, lparam %08lx\n",
3377 LOWORD(lParam),wParam,lParam);
3378 switch (id) {
3379 case IDOK:
3380 EndDialog(hDlg, TRUE);
3381 return TRUE ;
3382
3383 case IDCANCEL:
3384 EndDialog(hDlg, FALSE);
3385 return FALSE ;
3386
3387 case psh3: /* Printer... */
3388 pagesetup_change_printer_dialog(hDlg, data);
3389 return TRUE;
3390
3391 case rad1: /* Portrait */
3392 case rad2: /* Landscape */
3393 if((id == rad1 && pagesetup_get_orientation(data) == DMORIENT_LANDSCAPE) ||
3394 (id == rad2 && pagesetup_get_orientation(data) == DMORIENT_PORTRAIT))
3395 {
3396 pagesetup_set_orientation(data, (id == rad1) ? DMORIENT_PORTRAIT : DMORIENT_LANDSCAPE);
3397 pagesetup_update_papersize(data);
3398 rotate_rect(pagesetup_get_margin_rect(data), (id == rad2));
3399 update_margin_edits(hDlg, data, 0);
3400 pagesetup_change_preview(data);
3401 }
3402 break;
3403 case cmb1: /* Printer combo */
3404 if(msg == CBN_SELCHANGE)
3405 {
3406 WCHAR *name;
3407 INT index = SendDlgItemMessageW(hDlg, id, CB_GETCURSEL, 0, 0);
3408 INT length = SendDlgItemMessageW(hDlg, id, CB_GETLBTEXTLEN, index, 0);
3409 name = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(length+1));
3410 SendDlgItemMessageW(hDlg, id, CB_GETLBTEXT, index, (LPARAM)name);
3411 pagesetup_change_printer(name, data);
3412 pagesetup_init_combos(hDlg, data);
3413 HeapFree(GetProcessHeap(),0,name);
3414 }
3415 break;
3416 case cmb2: /* Paper combo */
3417 if(msg == CBN_SELCHANGE)
3418 {
3419 DWORD paperword = SendDlgItemMessageW(hDlg, cmb2, CB_GETITEMDATA,
3420 SendDlgItemMessageW(hDlg, cmb2, CB_GETCURSEL, 0, 0), 0);
3421 if (paperword != CB_ERR)
3422 {
3423 pagesetup_set_papersize(data, paperword);
3424 pagesetup_update_papersize(data);
3425 pagesetup_change_preview(data);
3426 } else
3427 FIXME("could not get dialog text for papersize cmbbox?\n");
3428 }
3429 break;
3430 case cmb3: /* Paper Source */
3431 if(msg == CBN_SELCHANGE)
3432 {
3433 WORD source = SendDlgItemMessageW(hDlg, cmb3, CB_GETITEMDATA,
3434 SendDlgItemMessageW(hDlg, cmb3, CB_GETCURSEL, 0, 0), 0);
3435 pagesetup_set_defaultsource(data, source);
3436 }
3437 break;
3438 case psh2: /* Printer Properties button */
3439 pagesetup_printer_properties(hDlg, data);
3440 break;
3441 case edt4:
3442 case edt5:
3443 case edt6:
3444 case edt7:
3445 margin_edit_notification(hDlg, data, msg, id);
3446 break;
3447 }
3448 InvalidateRect(GetDlgItem(hDlg, rct1), NULL, TRUE);
3449 return FALSE;
3450 }
3451
3452 /***********************************************************************
3453 * default_page_paint_hook
3454 * Default hook paint procedure that receives WM_PSD_* messages from the dialog box
3455 * whenever the sample page is redrawn.
3456 */
default_page_paint_hook(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam,const pagesetup_data * data)3457 static UINT_PTR default_page_paint_hook(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam,
3458 const pagesetup_data *data)
3459 {
3460 LPRECT lprc = (LPRECT) lParam;
3461 HDC hdc = (HDC) wParam;
3462 HPEN hpen, holdpen;
3463 LOGFONTW lf;
3464 HFONT hfont, holdfont;
3465 INT oldbkmode;
3466 TRACE("uMsg: WM_USER+%d\n",uMsg-WM_USER);
3467 /* Call user paint hook if enable */
3468 if (pagesetup_get_flags(data) & PSD_ENABLEPAGEPAINTHOOK)
3469 if (pagesetup_get_hook(data, page_paint_hook)(hwndDlg, uMsg, wParam, lParam))
3470 return TRUE;
3471
3472 switch (uMsg) {
3473 /* LPPAGESETUPDLG in lParam */
3474 case WM_PSD_PAGESETUPDLG:
3475 /* Inform about the sample page rectangle */
3476 case WM_PSD_FULLPAGERECT:
3477 /* Inform about the margin rectangle */
3478 case WM_PSD_MINMARGINRECT:
3479 return FALSE;
3480
3481 /* Draw dashed rectangle showing margins */
3482 case WM_PSD_MARGINRECT:
3483 hpen = CreatePen(PS_DASH, 1, GetSysColor(COLOR_3DSHADOW));
3484 holdpen = SelectObject(hdc, hpen);
3485 Rectangle(hdc, lprc->left, lprc->top, lprc->right, lprc->bottom);
3486 DeleteObject(SelectObject(hdc, holdpen));
3487 return TRUE;
3488 /* Draw the fake document */
3489 case WM_PSD_GREEKTEXTRECT:
3490 /* select a nice scalable font, because we want the text really small */
3491 SystemParametersInfoW(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0);
3492 lf.lfHeight = 6; /* value chosen based on visual effect */
3493 hfont = CreateFontIndirectW(&lf);
3494 holdfont = SelectObject(hdc, hfont);
3495
3496 /* if text not loaded, then do so now */
3497 if (wszFakeDocumentText[0] == '\0')
3498 LoadStringW(COMDLG32_hInstance,
3499 IDS_FAKEDOCTEXT,
3500 wszFakeDocumentText,
3501 ARRAY_SIZE(wszFakeDocumentText));
3502
3503 oldbkmode = SetBkMode(hdc, TRANSPARENT);
3504 DrawTextW(hdc, wszFakeDocumentText, -1, lprc, DT_TOP|DT_LEFT|DT_NOPREFIX|DT_WORDBREAK);
3505 SetBkMode(hdc, oldbkmode);
3506
3507 DeleteObject(SelectObject(hdc, holdfont));
3508 return TRUE;
3509
3510 /* Envelope stamp */
3511 case WM_PSD_ENVSTAMPRECT:
3512 /* Return address */
3513 case WM_PSD_YAFULLPAGERECT:
3514 FIXME("envelope/stamp is not implemented\n");
3515 return FALSE;
3516 default:
3517 FIXME("Unknown message %x\n",uMsg);
3518 return FALSE;
3519 }
3520 return TRUE;
3521 }
3522
3523 /***********************************************************************
3524 * PagePaintProc
3525 * The main paint procedure for the PageSetupDlg function.
3526 * The Page Setup dialog box includes an image of a sample page that shows how
3527 * the user's selections affect the appearance of the printed output.
3528 * The image consists of a rectangle that represents the selected paper
3529 * or envelope type, with a dotted-line rectangle representing
3530 * the current margins, and partial (Greek text) characters
3531 * to show how text looks on the printed page.
3532 *
3533 * The following messages in the order sends to user hook procedure:
3534 * WM_PSD_PAGESETUPDLG Draw the contents of the sample page
3535 * WM_PSD_FULLPAGERECT Inform about the bounding rectangle
3536 * WM_PSD_MINMARGINRECT Inform about the margin rectangle (min margin?)
3537 * WM_PSD_MARGINRECT Draw the margin rectangle
3538 * WM_PSD_GREEKTEXTRECT Draw the Greek text inside the margin rectangle
3539 * If any of first three messages returns TRUE, painting done.
3540 *
3541 * PARAMS:
3542 * hWnd [in] Handle to the Page Setup dialog box
3543 * uMsg [in] Received message
3544 *
3545 * TODO:
3546 * WM_PSD_ENVSTAMPRECT Draw in the envelope-stamp rectangle (for envelopes only)
3547 * WM_PSD_YAFULLPAGERECT Draw the return address portion (for envelopes and other paper sizes)
3548 *
3549 * RETURNS:
3550 * FALSE if all done correctly
3551 *
3552 */
3553
3554
3555 static LRESULT CALLBACK
PRINTDLG_PagePaintProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)3556 PRINTDLG_PagePaintProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
3557 {
3558 PAINTSTRUCT ps;
3559 RECT rcClient, rcMargin;
3560 HPEN hpen, holdpen;
3561 HDC hdc;
3562 HBRUSH hbrush, holdbrush;
3563 pagesetup_data *data;
3564 int papersize=0, orientation=0; /* FIXME: set these values for the user paint hook */
3565 double scalx, scaly;
3566
3567 if (uMsg != WM_PAINT)
3568 return CallWindowProcA(lpfnStaticWndProc, hWnd, uMsg, wParam, lParam);
3569
3570 /* Processing WM_PAINT message */
3571 data = GetPropW(hWnd, pagesetupdlg_prop);
3572 if (!data) {
3573 WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
3574 return FALSE;
3575 }
3576 if (default_page_paint_hook(hWnd, WM_PSD_PAGESETUPDLG, MAKELONG(papersize, orientation),
3577 pagesetup_get_dlg_struct(data), data))
3578 return FALSE;
3579
3580 hdc = BeginPaint(hWnd, &ps);
3581 GetClientRect(hWnd, &rcClient);
3582
3583 scalx = rcClient.right / (double)pagesetup_get_papersize_pt(data)->x;
3584 scaly = rcClient.bottom / (double)pagesetup_get_papersize_pt(data)->y;
3585 rcMargin = rcClient;
3586
3587 rcMargin.left += pagesetup_get_margin_rect(data)->left * scalx;
3588 rcMargin.top += pagesetup_get_margin_rect(data)->top * scaly;
3589 rcMargin.right -= pagesetup_get_margin_rect(data)->right * scalx;
3590 rcMargin.bottom -= pagesetup_get_margin_rect(data)->bottom * scaly;
3591
3592 /* if the space is too small then we make sure to not draw anything */
3593 rcMargin.left = min(rcMargin.left, rcMargin.right);
3594 rcMargin.top = min(rcMargin.top, rcMargin.bottom);
3595
3596 if (!default_page_paint_hook(hWnd, WM_PSD_FULLPAGERECT, (WPARAM)hdc, (LPARAM)&rcClient, data) &&
3597 !default_page_paint_hook(hWnd, WM_PSD_MINMARGINRECT, (WPARAM)hdc, (LPARAM)&rcMargin, data) )
3598 {
3599 /* fill background */
3600 hbrush = GetSysColorBrush(COLOR_3DHIGHLIGHT);
3601 FillRect(hdc, &rcClient, hbrush);
3602 holdbrush = SelectObject(hdc, hbrush);
3603
3604 hpen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));
3605 holdpen = SelectObject(hdc, hpen);
3606
3607 /* paint left edge */
3608 MoveToEx(hdc, rcClient.left, rcClient.top, NULL);
3609 LineTo(hdc, rcClient.left, rcClient.bottom-1);
3610
3611 /* paint top edge */
3612 MoveToEx(hdc, rcClient.left, rcClient.top, NULL);
3613 LineTo(hdc, rcClient.right, rcClient.top);
3614
3615 hpen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DDKSHADOW));
3616 DeleteObject(SelectObject(hdc, hpen));
3617
3618 /* paint right edge */
3619 MoveToEx(hdc, rcClient.right-1, rcClient.top, NULL);
3620 LineTo(hdc, rcClient.right-1, rcClient.bottom);
3621
3622 /* paint bottom edge */
3623 MoveToEx(hdc, rcClient.left, rcClient.bottom-1, NULL);
3624 LineTo(hdc, rcClient.right, rcClient.bottom-1);
3625
3626 DeleteObject(SelectObject(hdc, holdpen));
3627 DeleteObject(SelectObject(hdc, holdbrush));
3628
3629 default_page_paint_hook(hWnd, WM_PSD_MARGINRECT, (WPARAM)hdc, (LPARAM)&rcMargin, data);
3630
3631 /* give text a bit of a space from the frame */
3632 InflateRect(&rcMargin, -2, -2);
3633
3634 /* if the space is too small then we make sure to not draw anything */
3635 rcMargin.left = min(rcMargin.left, rcMargin.right);
3636 rcMargin.top = min(rcMargin.top, rcMargin.bottom);
3637
3638 default_page_paint_hook(hWnd, WM_PSD_GREEKTEXTRECT, (WPARAM)hdc, (LPARAM)&rcMargin, data);
3639 }
3640
3641 EndPaint(hWnd, &ps);
3642 return FALSE;
3643 }
3644
3645 /*******************************************************
3646 * The margin edit controls are subclassed to filter
3647 * anything other than numbers and the decimal separator.
3648 */
pagesetup_margin_editproc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)3649 static LRESULT CALLBACK pagesetup_margin_editproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
3650 {
3651 if (msg == WM_CHAR)
3652 {
3653 WCHAR decimal = get_decimal_sep();
3654 WCHAR wc = (WCHAR)wparam;
3655 if(!iswdigit(wc) && wc != decimal && wc != VK_BACK) return 0;
3656 }
3657 return CallWindowProcW(edit_wndproc, hwnd, msg, wparam, lparam);
3658 }
3659
subclass_margin_edits(HWND hDlg)3660 static void subclass_margin_edits(HWND hDlg)
3661 {
3662 int id;
3663 WNDPROC old_proc;
3664
3665 for(id = edt4; id <= edt7; id++)
3666 {
3667 old_proc = (WNDPROC)SetWindowLongPtrW(GetDlgItem(hDlg, id),
3668 GWLP_WNDPROC,
3669 (ULONG_PTR)pagesetup_margin_editproc);
3670 InterlockedCompareExchangePointer((void**)&edit_wndproc, old_proc, NULL);
3671 }
3672 }
3673
3674 /***********************************************************************
3675 * pagesetup_dlg_proc
3676 *
3677 * Message handler for PageSetupDlg
3678 */
pagesetup_dlg_proc(HWND hDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)3679 static INT_PTR CALLBACK pagesetup_dlg_proc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
3680 {
3681 pagesetup_data *data;
3682 INT_PTR res = FALSE;
3683 HWND hDrawWnd;
3684
3685 if (uMsg == WM_INITDIALOG) { /*Init dialog*/
3686 data = (pagesetup_data *)lParam;
3687 data->hDlg = hDlg;
3688
3689 hDrawWnd = GetDlgItem(hDlg, rct1);
3690 TRACE("set property to %p\n", data);
3691 SetPropW(hDlg, pagesetupdlg_prop, data);
3692 SetPropW(hDrawWnd, pagesetupdlg_prop, data);
3693 GetWindowRect(hDrawWnd, &data->rtDrawRect); /* Calculating rect in client coordinates where paper draws */
3694 MapWindowPoints( 0, hDlg, (LPPOINT)&data->rtDrawRect, 2 );
3695 lpfnStaticWndProc = (WNDPROC)SetWindowLongPtrW(
3696 hDrawWnd,
3697 GWLP_WNDPROC,
3698 (ULONG_PTR)PRINTDLG_PagePaintProc);
3699
3700 /* FIXME: Paint hook. Must it be at begin of initialization or at end? */
3701 res = TRUE;
3702 if (pagesetup_get_flags(data) & PSD_ENABLEPAGESETUPHOOK)
3703 {
3704 if (!pagesetup_get_hook(data, page_setup_hook)(hDlg, uMsg, wParam,
3705 pagesetup_get_dlg_struct(data)))
3706 FIXME("Setup page hook failed?\n");
3707 }
3708
3709 /* if printer button disabled */
3710 if (pagesetup_get_flags(data) & PSD_DISABLEPRINTER)
3711 EnableWindow(GetDlgItem(hDlg, psh3), FALSE);
3712 /* if margin edit boxes disabled */
3713 if (pagesetup_get_flags(data) & PSD_DISABLEMARGINS)
3714 {
3715 EnableWindow(GetDlgItem(hDlg, edt4), FALSE);
3716 EnableWindow(GetDlgItem(hDlg, edt5), FALSE);
3717 EnableWindow(GetDlgItem(hDlg, edt6), FALSE);
3718 EnableWindow(GetDlgItem(hDlg, edt7), FALSE);
3719 }
3720
3721 /* Set orientation radiobuttons properly */
3722 pagesetup_update_orientation_buttons(hDlg, data);
3723
3724 /* if orientation disabled */
3725 if (pagesetup_get_flags(data) & PSD_DISABLEORIENTATION)
3726 {
3727 EnableWindow(GetDlgItem(hDlg,rad1),FALSE);
3728 EnableWindow(GetDlgItem(hDlg,rad2),FALSE);
3729 }
3730
3731 /* We fill them out enabled or not */
3732 if (!(pagesetup_get_flags(data) & PSD_MARGINS))
3733 {
3734 /* default is 1 inch */
3735 LONG size = thousandths_inch_to_size(data, 1000);
3736 SetRect(pagesetup_get_margin_rect(data), size, size, size, size);
3737 }
3738 update_margin_edits(hDlg, data, 0);
3739 subclass_margin_edits(hDlg);
3740 set_margin_groupbox_title(hDlg, data);
3741
3742 /* if paper disabled */
3743 if (pagesetup_get_flags(data) & PSD_DISABLEPAPER)
3744 {
3745 EnableWindow(GetDlgItem(hDlg,cmb2),FALSE);
3746 EnableWindow(GetDlgItem(hDlg,cmb3),FALSE);
3747 }
3748
3749 /* filling combos: printer, paper, source. selecting current printer (from DEVMODEA) */
3750 pagesetup_init_combos(hDlg, data);
3751 pagesetup_update_papersize(data);
3752 pagesetup_set_defaultsource(data, DMBIN_FORMSOURCE); /* FIXME: This is the auto select bin. Is this correct? */
3753
3754 /* Drawing paper prev */
3755 pagesetup_change_preview(data);
3756 return TRUE;
3757 } else {
3758 data = GetPropW(hDlg, pagesetupdlg_prop);
3759 if (!data)
3760 {
3761 WARN("__WINE_PAGESETUPDLGDATA prop not set?\n");
3762 return FALSE;
3763 }
3764 if (pagesetup_get_flags(data) & PSD_ENABLEPAGESETUPHOOK)
3765 {
3766 res = pagesetup_get_hook(data, page_setup_hook)(hDlg, uMsg, wParam, lParam);
3767 if (res) return res;
3768 }
3769 }
3770 switch (uMsg) {
3771 case WM_COMMAND:
3772 return pagesetup_wm_command(hDlg, wParam, lParam, data);
3773 }
3774 return FALSE;
3775 }
3776
get_default_printer(void)3777 static WCHAR *get_default_printer(void)
3778 {
3779 WCHAR *name = NULL;
3780 DWORD len = 0;
3781
3782 GetDefaultPrinterW(NULL, &len);
3783 if(len)
3784 {
3785 name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3786 GetDefaultPrinterW(name, &len);
3787 }
3788 return name;
3789 }
3790
pagesetup_dump_dlg_struct(const pagesetup_data * data)3791 static void pagesetup_dump_dlg_struct(const pagesetup_data *data)
3792 {
3793 if(TRACE_ON(commdlg))
3794 {
3795 char flagstr[1000] = "";
3796 const struct pd_flags *pflag = psd_flags;
3797 for( ; pflag->name; pflag++)
3798 {
3799 if(pagesetup_get_flags(data) & pflag->flag)
3800 {
3801 strcat(flagstr, pflag->name);
3802 strcat(flagstr, "|");
3803 }
3804 }
3805 TRACE("%s: (%p): hwndOwner = %p, hDevMode = %p, hDevNames = %p\n"
3806 "hinst %p, flags %08x (%s)\n",
3807 data->unicode ? "unicode" : "ansi",
3808 data->u.dlgw, data->u.dlgw->hwndOwner, data->u.dlgw->hDevMode,
3809 data->u.dlgw->hDevNames, data->u.dlgw->hInstance,
3810 pagesetup_get_flags(data), flagstr);
3811 }
3812 }
3813
pagesetup_get_template(pagesetup_data * data)3814 static void *pagesetup_get_template(pagesetup_data *data)
3815 {
3816 HRSRC res;
3817 HGLOBAL tmpl_handle;
3818
3819 if(pagesetup_get_flags(data) & PSD_ENABLEPAGESETUPTEMPLATEHANDLE)
3820 {
3821 tmpl_handle = data->u.dlgw->hPageSetupTemplate;
3822 }
3823 else if(pagesetup_get_flags(data) & PSD_ENABLEPAGESETUPTEMPLATE)
3824 {
3825 if(data->unicode)
3826 res = FindResourceW(data->u.dlgw->hInstance,
3827 data->u.dlgw->lpPageSetupTemplateName, (LPWSTR)RT_DIALOG);
3828 else
3829 res = FindResourceA(data->u.dlga->hInstance,
3830 data->u.dlga->lpPageSetupTemplateName, (LPSTR)RT_DIALOG);
3831 tmpl_handle = LoadResource(data->u.dlgw->hInstance, res);
3832 }
3833 else
3834 {
3835 res = FindResourceW(COMDLG32_hInstance, MAKEINTRESOURCEW(PAGESETUPDLGORD),
3836 (LPWSTR)RT_DIALOG);
3837 tmpl_handle = LoadResource(COMDLG32_hInstance, res);
3838 }
3839 return LockResource(tmpl_handle);
3840 }
3841
pagesetup_common(pagesetup_data * data)3842 static BOOL pagesetup_common(pagesetup_data *data)
3843 {
3844 BOOL ret;
3845 void *tmpl;
3846
3847 if(!pagesetup_get_dlg_struct(data))
3848 {
3849 COMDLG32_SetCommDlgExtendedError(CDERR_INITIALIZATION);
3850 return FALSE;
3851 }
3852
3853 pagesetup_dump_dlg_struct(data);
3854
3855 if(data->u.dlgw->lStructSize != sizeof(PAGESETUPDLGW))
3856 {
3857 COMDLG32_SetCommDlgExtendedError(CDERR_STRUCTSIZE);
3858 return FALSE;
3859 }
3860
3861 if ((pagesetup_get_flags(data) & PSD_ENABLEPAGEPAINTHOOK) &&
3862 (pagesetup_get_hook(data, page_paint_hook) == NULL))
3863 {
3864 COMDLG32_SetCommDlgExtendedError(CDERR_NOHOOK);
3865 return FALSE;
3866 }
3867
3868 if(!(pagesetup_get_flags(data) & (PSD_INTHOUSANDTHSOFINCHES | PSD_INHUNDREDTHSOFMILLIMETERS)))
3869 data->u.dlgw->Flags |= is_default_metric() ?
3870 PSD_INHUNDREDTHSOFMILLIMETERS : PSD_INTHOUSANDTHSOFINCHES;
3871
3872 if (!data->u.dlgw->hDevMode || !data->u.dlgw->hDevNames)
3873 {
3874 WCHAR *def = get_default_printer();
3875 if(!def)
3876 {
3877 if (!(pagesetup_get_flags(data) & PSD_NOWARNING))
3878 {
3879 WCHAR errstr[256];
3880 LoadStringW(COMDLG32_hInstance, PD32_NO_DEFAULT_PRINTER, errstr, 255);
3881 MessageBoxW(data->u.dlgw->hwndOwner, errstr, 0, MB_OK | MB_ICONERROR);
3882 }
3883 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
3884 return FALSE;
3885 }
3886 pagesetup_change_printer(def, data);
3887 HeapFree(GetProcessHeap(), 0, def);
3888 }
3889
3890 if (pagesetup_get_flags(data) & PSD_RETURNDEFAULT)
3891 {
3892 pagesetup_update_papersize(data);
3893 return TRUE;
3894 }
3895
3896 tmpl = pagesetup_get_template(data);
3897
3898 ret = DialogBoxIndirectParamW(data->u.dlgw->hInstance, tmpl,
3899 data->u.dlgw->hwndOwner,
3900 pagesetup_dlg_proc, (LPARAM)data) > 0;
3901 return ret;
3902 }
3903
3904 /***********************************************************************
3905 * PageSetupDlgA (COMDLG32.@)
3906 *
3907 * Displays the PAGE SETUP dialog box, which enables the user to specify
3908 * specific properties of a printed page such as
3909 * size, source, orientation and the width of the page margins.
3910 *
3911 * PARAMS
3912 * setupdlg [IO] PAGESETUPDLGA struct
3913 *
3914 * RETURNS
3915 * TRUE if the user pressed the OK button
3916 * FALSE if the user cancelled the window or an error occurred
3917 *
3918 * NOTES
3919 * The values of hDevMode and hDevNames are filled on output and can be
3920 * changed in PAGESETUPDLG when they are passed in PageSetupDlg.
3921 *
3922 */
PageSetupDlgA(LPPAGESETUPDLGA setupdlg)3923 BOOL WINAPI PageSetupDlgA(LPPAGESETUPDLGA setupdlg)
3924 {
3925 pagesetup_data data;
3926
3927 data.unicode = FALSE;
3928 data.u.dlga = setupdlg;
3929
3930 return pagesetup_common(&data);
3931 }
3932
3933 /***********************************************************************
3934 * PageSetupDlgW (COMDLG32.@)
3935 *
3936 * See PageSetupDlgA.
3937 */
PageSetupDlgW(LPPAGESETUPDLGW setupdlg)3938 BOOL WINAPI PageSetupDlgW(LPPAGESETUPDLGW setupdlg)
3939 {
3940 pagesetup_data data;
3941
3942 data.unicode = TRUE;
3943 data.u.dlgw = setupdlg;
3944
3945 return pagesetup_common(&data);
3946 }
3947
pdlgex_to_pdlg(const PRINTDLGEXW * pdlgex,PRINTDLGW * pdlg)3948 static void pdlgex_to_pdlg(const PRINTDLGEXW *pdlgex, PRINTDLGW *pdlg)
3949 {
3950 pdlg->lStructSize = sizeof(*pdlg);
3951 pdlg->hwndOwner = pdlgex->hwndOwner;
3952 pdlg->hDevMode = pdlgex->hDevMode;
3953 pdlg->hDevNames = pdlgex->hDevNames;
3954 pdlg->hDC = pdlgex->hDC;
3955 pdlg->Flags = pdlgex->Flags;
3956 if ((pdlgex->Flags & PD_NOPAGENUMS) || !pdlgex->nPageRanges || !pdlgex->lpPageRanges)
3957 {
3958 pdlg->nFromPage = 0;
3959 pdlg->nToPage = 65534;
3960 }
3961 else
3962 {
3963 pdlg->nFromPage = pdlgex->lpPageRanges[0].nFromPage;
3964 pdlg->nToPage = pdlgex->lpPageRanges[0].nToPage;
3965 }
3966 pdlg->nMinPage = pdlgex->nMinPage;
3967 pdlg->nMaxPage = pdlgex->nMaxPage;
3968 pdlg->nCopies = pdlgex->nCopies;
3969 pdlg->hInstance = pdlgex->hInstance;
3970 pdlg->lCustData = 0;
3971 pdlg->lpfnPrintHook = NULL;
3972 pdlg->lpfnSetupHook = NULL;
3973 pdlg->lpPrintTemplateName = pdlgex->lpPrintTemplateName;
3974 pdlg->lpSetupTemplateName = NULL;
3975 pdlg->hPrintTemplate = NULL;
3976 pdlg->hSetupTemplate = NULL;
3977 }
3978
3979 /* Only copy fields that are supposed to be changed. */
pdlg_to_pdlgex(const PRINTDLGW * pdlg,PRINTDLGEXW * pdlgex)3980 static void pdlg_to_pdlgex(const PRINTDLGW *pdlg, PRINTDLGEXW *pdlgex)
3981 {
3982 pdlgex->hDevMode = pdlg->hDevMode;
3983 pdlgex->hDevNames = pdlg->hDevNames;
3984 pdlgex->hDC = pdlg->hDC;
3985 if (!(pdlgex->Flags & PD_NOPAGENUMS) && pdlgex->nPageRanges && pdlgex->lpPageRanges)
3986 {
3987 pdlgex->lpPageRanges[0].nFromPage = pdlg->nFromPage;
3988 pdlgex->lpPageRanges[0].nToPage = pdlg->nToPage;
3989 }
3990 pdlgex->nMinPage = pdlg->nMinPage;
3991 pdlgex->nMaxPage = pdlg->nMaxPage;
3992 pdlgex->nCopies = pdlg->nCopies;
3993 }
3994
3995 struct callback_data
3996 {
3997 IPrintDialogCallback *callback;
3998 IObjectWithSite *object;
3999 };
4000
pdlgex_hook_proc(HWND hwnd,UINT msg,WPARAM wp,LPARAM lp)4001 static UINT_PTR CALLBACK pdlgex_hook_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
4002 {
4003 if (msg == WM_INITDIALOG)
4004 {
4005 PRINTDLGW *pd = (PRINTDLGW *)lp;
4006 struct callback_data *cb = (struct callback_data *)pd->lCustData;
4007
4008 if (cb->callback)
4009 {
4010 cb->callback->lpVtbl->SelectionChange(cb->callback);
4011 cb->callback->lpVtbl->InitDone(cb->callback);
4012 }
4013 }
4014 else
4015 {
4016 /* FIXME: store interface pointer somewhere in window properties and call it
4017 HRESULT hres;
4018 cb->callback->lpVtbl->HandleMessage(cb->callback, hwnd, msg, wp, lp, &hres);
4019 */
4020 }
4021
4022 return 0;
4023 }
4024
4025 /***********************************************************************
4026 * PrintDlgExA (COMDLG32.@)
4027 *
4028 * See PrintDlgExW.
4029 *
4030 * BUGS
4031 * Only a Stub
4032 *
4033 */
PrintDlgExA(LPPRINTDLGEXA lppd)4034 HRESULT WINAPI PrintDlgExA(LPPRINTDLGEXA lppd)
4035 {
4036 PRINTER_INFO_2A *pbuf;
4037 DRIVER_INFO_3A *dbuf;
4038 DEVMODEA *dm;
4039 HRESULT hr = S_OK;
4040 HANDLE hprn;
4041
4042 if ((lppd == NULL) || (lppd->lStructSize != sizeof(PRINTDLGEXA)))
4043 return E_INVALIDARG;
4044
4045 if (!IsWindow(lppd->hwndOwner))
4046 return E_HANDLE;
4047
4048 if (lppd->nStartPage != START_PAGE_GENERAL)
4049 {
4050 if (!lppd->nPropertyPages)
4051 return E_INVALIDARG;
4052
4053 FIXME("custom property sheets (%d at %p) not supported\n", lppd->nPropertyPages, lppd->lphPropertyPages);
4054 }
4055
4056 /* Use PD_NOPAGENUMS or set nMaxPageRanges and lpPageRanges */
4057 if (!(lppd->Flags & PD_NOPAGENUMS) && (!lppd->nMaxPageRanges || !lppd->lpPageRanges))
4058 {
4059 return E_INVALIDARG;
4060 }
4061
4062 if (lppd->Flags & PD_RETURNDEFAULT)
4063 {
4064 if (lppd->hDevMode || lppd->hDevNames)
4065 {
4066 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
4067 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
4068 return E_INVALIDARG;
4069 }
4070 if (!PRINTDLG_OpenDefaultPrinter(&hprn))
4071 {
4072 WARN("Can't find default printer\n");
4073 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
4074 return E_FAIL;
4075 }
4076
4077 pbuf = get_printer_infoA(hprn);
4078 if (!pbuf)
4079 {
4080 ClosePrinter(hprn);
4081 return E_FAIL;
4082 }
4083
4084 dbuf = get_driver_infoA(hprn);
4085 if (!dbuf)
4086 {
4087 HeapFree(GetProcessHeap(), 0, pbuf);
4088 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
4089 ClosePrinter(hprn);
4090 return E_FAIL;
4091 }
4092 dm = pbuf->pDevMode;
4093 }
4094 else
4095 {
4096 PRINTDLGA pdlg;
4097 struct callback_data cb_data = { 0 };
4098
4099 FIXME("(%p) semi-stub\n", lppd);
4100
4101 if (lppd->lpCallback)
4102 {
4103 IUnknown_QueryInterface((IUnknown *)lppd->lpCallback, &IID_IPrintDialogCallback, (void **)&cb_data.callback);
4104 IUnknown_QueryInterface((IUnknown *)lppd->lpCallback, &IID_IObjectWithSite, (void **)&cb_data.object);
4105 }
4106
4107 /*
4108 * PRINTDLGEXA/W and PRINTDLGA/W layout is the same for A and W variants.
4109 */
4110 pdlgex_to_pdlg((const PRINTDLGEXW *)lppd, (PRINTDLGW *)&pdlg);
4111 pdlg.Flags |= PD_ENABLEPRINTHOOK;
4112 pdlg.lpfnPrintHook = pdlgex_hook_proc;
4113 pdlg.lCustData = (LPARAM)&cb_data;
4114
4115 if (PrintDlgA(&pdlg))
4116 {
4117 pdlg_to_pdlgex((const PRINTDLGW *)&pdlg, (PRINTDLGEXW *)lppd);
4118 lppd->dwResultAction = PD_RESULT_PRINT;
4119 }
4120 else
4121 lppd->dwResultAction = PD_RESULT_CANCEL;
4122
4123 if (cb_data.callback)
4124 cb_data.callback->lpVtbl->Release(cb_data.callback);
4125 if (cb_data.object)
4126 cb_data.object->lpVtbl->Release(cb_data.object);
4127
4128 return S_OK;
4129 }
4130
4131 ClosePrinter(hprn);
4132
4133 PRINTDLG_CreateDevNames(&(lppd->hDevNames), dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName);
4134 if (!lppd->hDevNames)
4135 hr = E_FAIL;
4136
4137 lppd->hDevMode = update_devmode_handleA(lppd->hDevMode, dm);
4138 if (hr == S_OK && lppd->hDevMode) {
4139 if (lppd->Flags & PD_RETURNDC) {
4140 lppd->hDC = CreateDCA(dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName, dm);
4141 if (!lppd->hDC)
4142 hr = E_FAIL;
4143 }
4144 else if (lppd->Flags & PD_RETURNIC) {
4145 lppd->hDC = CreateICA(dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName, dm);
4146 if (!lppd->hDC)
4147 hr = E_FAIL;
4148 }
4149 }
4150 else
4151 hr = E_FAIL;
4152
4153 HeapFree(GetProcessHeap(), 0, pbuf);
4154 HeapFree(GetProcessHeap(), 0, dbuf);
4155
4156 return hr;
4157 }
4158
4159 /***********************************************************************
4160 * PrintDlgExW (COMDLG32.@)
4161 *
4162 * Display the property sheet style PRINT dialog box
4163 *
4164 * PARAMS
4165 * lppd [IO] ptr to PRINTDLGEX struct
4166 *
4167 * RETURNS
4168 * Success: S_OK
4169 * Failure: One of the following COM error codes:
4170 * E_OUTOFMEMORY Insufficient memory.
4171 * E_INVALIDARG One or more arguments are invalid.
4172 * E_POINTER Invalid pointer.
4173 * E_HANDLE Invalid handle.
4174 * E_FAIL Unspecified error.
4175 *
4176 * NOTES
4177 * This Dialog enables the user to specify specific properties of the print job.
4178 * The property sheet can also have additional application-specific and
4179 * driver-specific property pages.
4180 *
4181 * BUGS
4182 * Not fully implemented
4183 *
4184 */
PrintDlgExW(LPPRINTDLGEXW lppd)4185 HRESULT WINAPI PrintDlgExW(LPPRINTDLGEXW lppd)
4186 {
4187 PRINTER_INFO_2W *pbuf;
4188 DRIVER_INFO_3W *dbuf;
4189 DEVMODEW *dm;
4190 HRESULT hr = S_OK;
4191 HANDLE hprn;
4192
4193 if ((lppd == NULL) || (lppd->lStructSize != sizeof(PRINTDLGEXW))) {
4194 return E_INVALIDARG;
4195 }
4196
4197 if (!IsWindow(lppd->hwndOwner)) {
4198 return E_HANDLE;
4199 }
4200
4201 if (lppd->nStartPage != START_PAGE_GENERAL)
4202 {
4203 if (!lppd->nPropertyPages)
4204 return E_INVALIDARG;
4205
4206 FIXME("custom property sheets (%d at %p) not supported\n", lppd->nPropertyPages, lppd->lphPropertyPages);
4207 }
4208
4209 /* Use PD_NOPAGENUMS or set nMaxPageRanges and lpPageRanges */
4210 if (!(lppd->Flags & PD_NOPAGENUMS) && (!lppd->nMaxPageRanges || !lppd->lpPageRanges))
4211 {
4212 return E_INVALIDARG;
4213 }
4214
4215 if (lppd->Flags & PD_RETURNDEFAULT) {
4216
4217 if (lppd->hDevMode || lppd->hDevNames) {
4218 WARN("hDevMode or hDevNames non-zero for PD_RETURNDEFAULT\n");
4219 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
4220 return E_INVALIDARG;
4221 }
4222 if (!PRINTDLG_OpenDefaultPrinter(&hprn)) {
4223 WARN("Can't find default printer\n");
4224 COMDLG32_SetCommDlgExtendedError(PDERR_NODEFAULTPRN);
4225 return E_FAIL;
4226 }
4227
4228 pbuf = get_printer_infoW(hprn);
4229 if (!pbuf)
4230 {
4231 ClosePrinter(hprn);
4232 return E_FAIL;
4233 }
4234
4235 dbuf = get_driver_infoW(hprn);
4236 if (!dbuf)
4237 {
4238 HeapFree(GetProcessHeap(), 0, pbuf);
4239 COMDLG32_SetCommDlgExtendedError(PDERR_RETDEFFAILURE);
4240 ClosePrinter(hprn);
4241 return E_FAIL;
4242 }
4243 dm = pbuf->pDevMode;
4244 }
4245 else
4246 {
4247 PRINTDLGW pdlg;
4248 struct callback_data cb_data = { 0 };
4249
4250 FIXME("(%p) semi-stub\n", lppd);
4251
4252 if (lppd->lpCallback)
4253 {
4254 IUnknown_QueryInterface((IUnknown *)lppd->lpCallback, &IID_IPrintDialogCallback, (void **)&cb_data.callback);
4255 IUnknown_QueryInterface((IUnknown *)lppd->lpCallback, &IID_IObjectWithSite, (void **)&cb_data.object);
4256 }
4257
4258 pdlgex_to_pdlg(lppd, &pdlg);
4259 pdlg.Flags |= PD_ENABLEPRINTHOOK;
4260 pdlg.lpfnPrintHook = pdlgex_hook_proc;
4261 pdlg.lCustData = (LPARAM)&cb_data;
4262
4263 if (PrintDlgW(&pdlg))
4264 {
4265 pdlg_to_pdlgex(&pdlg, lppd);
4266 lppd->dwResultAction = PD_RESULT_PRINT;
4267 }
4268 else
4269 lppd->dwResultAction = PD_RESULT_CANCEL;
4270
4271 if (cb_data.callback)
4272 cb_data.callback->lpVtbl->Release(cb_data.callback);
4273 if (cb_data.object)
4274 cb_data.object->lpVtbl->Release(cb_data.object);
4275
4276 return S_OK;
4277 }
4278
4279 ClosePrinter(hprn);
4280
4281 PRINTDLG_CreateDevNamesW(&(lppd->hDevNames), dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName);
4282 if (!lppd->hDevNames)
4283 hr = E_FAIL;
4284
4285 lppd->hDevMode = update_devmode_handleW(lppd->hDevMode, dm);
4286 if (hr == S_OK && lppd->hDevMode) {
4287 if (lppd->Flags & PD_RETURNDC) {
4288 lppd->hDC = CreateDCW(dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName, dm);
4289 if (!lppd->hDC)
4290 hr = E_FAIL;
4291 }
4292 else if (lppd->Flags & PD_RETURNIC) {
4293 lppd->hDC = CreateICW(dbuf->pDriverPath, pbuf->pPrinterName, pbuf->pPortName, dm);
4294 if (!lppd->hDC)
4295 hr = E_FAIL;
4296 }
4297 }
4298 else
4299 hr = E_FAIL;
4300
4301 HeapFree(GetProcessHeap(), 0, pbuf);
4302 HeapFree(GetProcessHeap(), 0, dbuf);
4303
4304 return hr;
4305 }
4306