1 /* 2 * Unit test suite for comdlg32 API functions: printer dialogs 3 * 4 * Copyright 2006-2007 Detlef Riekenberg 5 * Copyright 2013 Dmitry Timoshkov 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 * 21 */ 22 23 #define COBJMACROS 24 #define CONST_VTABLE 25 #define WIN32_NO_STATUS 26 27 #include <wine/test.h> 28 29 //#include <stdarg.h> 30 #include <stdio.h> 31 32 //#include "windef.h" 33 //#include "winbase.h" 34 //#include "winerror.h" 35 #include <wingdi.h> 36 #include <winuser.h> 37 #include <objbase.h> 38 39 #include <cderr.h> 40 #include <commdlg.h> 41 #include <dlgs.h> 42 43 /* ########################### */ 44 45 extern const IID IID_IObjectWithSite; 46 47 static HMODULE hcomdlg32; 48 static HRESULT (WINAPI * pPrintDlgExW)(LPPRINTDLGEXW); 49 50 /* ########################### */ 51 52 static const CHAR emptyA[] = ""; 53 static const CHAR PrinterPortsA[] = "PrinterPorts"; 54 55 /* ########################### */ 56 57 static void test_PageSetupDlgA(void) 58 { 59 LPPAGESETUPDLGA pDlg; 60 DWORD res; 61 62 pDlg = HeapAlloc(GetProcessHeap(), 0, (sizeof(PAGESETUPDLGA)) * 2); 63 if (!pDlg) return; 64 65 SetLastError(0xdeadbeef); 66 res = PageSetupDlgA(NULL); 67 ok( !res && (CommDlgExtendedError() == CDERR_INITIALIZATION), 68 "returned %u with %u and 0x%x (expected '0' and " 69 "CDERR_INITIALIZATION)\n", res, GetLastError(), CommDlgExtendedError()); 70 71 ZeroMemory(pDlg, sizeof(PAGESETUPDLGA)); 72 pDlg->lStructSize = sizeof(PAGESETUPDLGA) -1; 73 SetLastError(0xdeadbeef); 74 res = PageSetupDlgA(pDlg); 75 ok( !res && (CommDlgExtendedError() == CDERR_STRUCTSIZE), 76 "returned %u with %u and 0x%x (expected '0' and " 77 "CDERR_STRUCTSIZE)\n", res, GetLastError(), CommDlgExtendedError()); 78 79 ZeroMemory(pDlg, sizeof(PAGESETUPDLGA)); 80 pDlg->lStructSize = sizeof(PAGESETUPDLGA) +1; 81 pDlg->Flags = PSD_RETURNDEFAULT; 82 SetLastError(0xdeadbeef); 83 res = PageSetupDlgA(pDlg); 84 ok( !res && (CommDlgExtendedError() == CDERR_STRUCTSIZE), 85 "returned %u with %u and 0x%x (expected '0' and CDERR_STRUCTSIZE)\n", 86 res, GetLastError(), CommDlgExtendedError()); 87 88 89 ZeroMemory(pDlg, sizeof(PAGESETUPDLGA)); 90 pDlg->lStructSize = sizeof(PAGESETUPDLGA); 91 pDlg->Flags = PSD_RETURNDEFAULT | PSD_NOWARNING; 92 SetLastError(0xdeadbeef); 93 res = PageSetupDlgA(pDlg); 94 ok( res || (CommDlgExtendedError() == PDERR_NODEFAULTPRN), 95 "returned %u with %u and 0x%x (expected '!= 0' or '0' and " 96 "PDERR_NODEFAULTPRN)\n", res, GetLastError(), CommDlgExtendedError()); 97 98 if (!res && (CommDlgExtendedError() == PDERR_NODEFAULTPRN)) { 99 skip("No printer configured.\n"); 100 HeapFree(GetProcessHeap(), 0, pDlg); 101 return; 102 } 103 104 ok( pDlg->hDevMode && pDlg->hDevNames, 105 "got %p and %p (expected '!= NULL' for both)\n", 106 pDlg->hDevMode, pDlg->hDevNames); 107 108 GlobalFree(pDlg->hDevMode); 109 GlobalFree(pDlg->hDevNames); 110 111 HeapFree(GetProcessHeap(), 0, pDlg); 112 113 } 114 115 /* ########################### */ 116 117 static UINT_PTR CALLBACK print_hook_proc(HWND hdlg, UINT msg, WPARAM wp, LPARAM lp) 118 { 119 if (msg == WM_INITDIALOG) 120 { 121 /* some driver popup a dialog and hung the test or silently limit the number of copies, 122 when trying to set more than 999 copies */ 123 SetDlgItemInt(hdlg, edt3, 123, FALSE); 124 PostMessageA(hdlg, WM_COMMAND, IDOK, FALSE); 125 } 126 return 0; 127 } 128 129 static void test_PrintDlgA(void) 130 { 131 DWORD res, n_copies = 0; 132 LPPRINTDLGA pDlg; 133 DEVNAMES *pDevNames; 134 LPCSTR driver; 135 LPCSTR device; 136 LPCSTR port; 137 CHAR buffer[MAX_PATH]; 138 LPSTR ptr; 139 DEVMODEA *dm; 140 141 pDlg = HeapAlloc(GetProcessHeap(), 0, (sizeof(PRINTDLGA)) * 2); 142 if (!pDlg) return; 143 144 145 /* will crash with unpatched wine */ 146 SetLastError(0xdeadbeef); 147 res = PrintDlgA(NULL); 148 ok( !res && (CommDlgExtendedError() == CDERR_INITIALIZATION), 149 "returned %d with 0x%x and 0x%x (expected '0' and " 150 "CDERR_INITIALIZATION)\n", res, GetLastError(), CommDlgExtendedError()); 151 152 ZeroMemory(pDlg, sizeof(PRINTDLGA)); 153 pDlg->lStructSize = sizeof(PRINTDLGA) - 1; 154 SetLastError(0xdeadbeef); 155 res = PrintDlgA(pDlg); 156 ok( !res && (CommDlgExtendedError() == CDERR_STRUCTSIZE), 157 "returned %d with 0x%x and 0x%x (expected '0' and " 158 "CDERR_STRUCTSIZE)\n", res, GetLastError(), CommDlgExtendedError()); 159 160 ZeroMemory(pDlg, sizeof(PRINTDLGA)); 161 pDlg->lStructSize = sizeof(PRINTDLGA) + 1; 162 pDlg->Flags = PD_RETURNDEFAULT; 163 SetLastError(0xdeadbeef); 164 res = PrintDlgA(pDlg); 165 ok( !res && (CommDlgExtendedError() == CDERR_STRUCTSIZE), 166 "returned %u with %u and 0x%x (expected '0' and " 167 "CDERR_STRUCTSIZE)\n", res, GetLastError(), CommDlgExtendedError()); 168 169 170 ZeroMemory(pDlg, sizeof(PRINTDLGA)); 171 pDlg->lStructSize = sizeof(PRINTDLGA); 172 pDlg->Flags = PD_RETURNDEFAULT; 173 SetLastError(0xdeadbeef); 174 res = PrintDlgA(pDlg); 175 ok( res || (CommDlgExtendedError() == PDERR_NODEFAULTPRN), 176 "returned %d with 0x%x and 0x%x (expected '!= 0' or '0' and " 177 "PDERR_NODEFAULTPRN)\n", res, GetLastError(), CommDlgExtendedError()); 178 179 if (!res && (CommDlgExtendedError() == PDERR_NODEFAULTPRN)) { 180 skip("No printer configured.\n"); 181 HeapFree(GetProcessHeap(), 0, pDlg); 182 return; 183 } 184 185 ok(pDlg->hDevNames != NULL, "(expected '!= NULL')\n"); 186 pDevNames = GlobalLock(pDlg->hDevNames); 187 ok(pDevNames != NULL, "(expected '!= NULL')\n"); 188 189 if (pDevNames) { 190 ok(pDevNames->wDriverOffset, "(expected '!= 0' for wDriverOffset)\n"); 191 ok(pDevNames->wDeviceOffset, "(expected '!= 0' for wDeviceOffset)\n"); 192 ok(pDevNames->wOutputOffset, "(expected '!= 0' for wOutputOffset)\n"); 193 ok(pDevNames->wDefault == DN_DEFAULTPRN, "got 0x%x (expected DN_DEFAULTPRN)\n", pDevNames->wDefault); 194 195 driver = (LPCSTR)pDevNames + pDevNames->wDriverOffset; 196 device = (LPCSTR)pDevNames + pDevNames->wDeviceOffset; 197 port = (LPCSTR)pDevNames + pDevNames->wOutputOffset; 198 trace("driver '%s' device '%s' port '%s'\n", driver, device, port); 199 200 /* The Driver Entry does not include a Path */ 201 ptr = strrchr(driver, '\\'); 202 ok( ptr == NULL, "got %p for '%s' (expected NULL for a simple name)\n", ptr, driver); 203 204 /* The Driver Entry does not have an extension (fixed to ".drv") */ 205 ptr = strrchr(driver, '.'); 206 todo_wine { 207 ok( ptr == NULL, "got %p for '%s' (expected NULL for no extension)\n", ptr, driver); 208 } 209 210 211 buffer[0] = '\0'; 212 SetLastError(0xdeadbeef); 213 res = GetProfileStringA(PrinterPortsA, device, emptyA, buffer, sizeof(buffer)); 214 ptr = strchr(buffer, ','); 215 ok( (res > 1) && (ptr != NULL), 216 "got %u with %u and %p for '%s' (expected '>1' and '!= NULL')\n", 217 res, GetLastError(), ptr, buffer); 218 219 if (ptr) ptr[0] = '\0'; 220 ok( lstrcmpiA(driver, buffer) == 0, 221 "got driver '%s' (expected '%s')\n", driver, buffer); 222 223 n_copies = DeviceCapabilitiesA(device, port, DC_COPIES, NULL, NULL); 224 ok(n_copies > 0, "DeviceCapabilities(DC_COPIES) failed\n"); 225 } 226 227 GlobalUnlock(pDlg->hDevNames); 228 GlobalFree(pDlg->hDevMode); 229 GlobalFree(pDlg->hDevNames); 230 231 /* if device doesn't support printing of multiple copies then 232 * an attempt to set number of copies > 1 in print dialog would 233 * cause the PrintDlg under Windows display the MessageBox and 234 * the test will hang waiting for user response. 235 */ 236 if (n_copies > 1) 237 { 238 ZeroMemory(pDlg, sizeof(*pDlg)); 239 pDlg->lStructSize = sizeof(*pDlg); 240 pDlg->Flags = PD_ENABLEPRINTHOOK; 241 pDlg->lpfnPrintHook = print_hook_proc; 242 res = PrintDlgA(pDlg); 243 ok(res, "PrintDlg error %#x\n", CommDlgExtendedError()); 244 /* Version of Microsoft XPS Document Writer driver shipped before Win7 245 * reports that it can print multiple copies, but returns 1. 246 */ 247 ok(pDlg->nCopies == 123 || broken(pDlg->nCopies == 1), "expected nCopies 123, got %d\n", pDlg->nCopies); 248 ok(pDlg->hDevMode != 0, "hDevMode should not be 0\n"); 249 dm = GlobalLock(pDlg->hDevMode); 250 /* some broken drivers use always PD_USEDEVMODECOPIES */ 251 ok((S1(U1(*dm)).dmCopies == 1) || broken(S1(U1(*dm)).dmCopies == 123), 252 "expected dm->dmCopies 1, got %d\n", S1(U1(*dm)).dmCopies); 253 GlobalUnlock(pDlg->hDevMode); 254 GlobalFree(pDlg->hDevMode); 255 GlobalFree(pDlg->hDevNames); 256 257 ZeroMemory(pDlg, sizeof(*pDlg)); 258 pDlg->lStructSize = sizeof(*pDlg); 259 pDlg->Flags = PD_ENABLEPRINTHOOK | PD_USEDEVMODECOPIES; 260 pDlg->lpfnPrintHook = print_hook_proc; 261 res = PrintDlgA(pDlg); 262 ok(res, "PrintDlg error %#x\n", CommDlgExtendedError()); 263 ok(pDlg->nCopies == 1, "expected nCopies 1, got %d\n", pDlg->nCopies); 264 ok(pDlg->hDevMode != 0, "hDevMode should not be 0\n"); 265 dm = GlobalLock(pDlg->hDevMode); 266 ok(S1(U1(*dm)).dmCopies == 123, "expected dm->dmCopies 123, got %d\n", S1(U1(*dm)).dmCopies); 267 GlobalUnlock(pDlg->hDevMode); 268 GlobalFree(pDlg->hDevMode); 269 GlobalFree(pDlg->hDevNames); 270 } 271 272 HeapFree(GetProcessHeap(), 0, pDlg); 273 } 274 275 /* ########################### */ 276 277 static HRESULT WINAPI callback_QueryInterface(IPrintDialogCallback *iface, 278 REFIID riid, void **ppv) 279 { 280 ok(0, "callback_QueryInterface(%s): unexpected call\n", wine_dbgstr_guid(riid)); 281 return E_NOINTERFACE; 282 } 283 284 static ULONG WINAPI callback_AddRef(IPrintDialogCallback *iface) 285 { 286 trace("callback_AddRef\n"); 287 return 2; 288 } 289 290 static ULONG WINAPI callback_Release(IPrintDialogCallback *iface) 291 { 292 trace("callback_Release\n"); 293 return 1; 294 } 295 296 static HRESULT WINAPI callback_InitDone(IPrintDialogCallback *iface) 297 { 298 trace("callback_InitDone\n"); 299 return S_OK; 300 } 301 302 static HRESULT WINAPI callback_SelectionChange(IPrintDialogCallback *iface) 303 { 304 trace("callback_SelectionChange\n"); 305 return S_OK; 306 } 307 308 static HRESULT WINAPI callback_HandleMessage(IPrintDialogCallback *iface, 309 HWND hdlg, UINT msg, WPARAM wp, LPARAM lp, LRESULT *res) 310 { 311 trace("callback_HandleMessage %p,%04x,%lx,%lx,%p\n", hdlg, msg, wp, lp, res); 312 /* *res = PD_RESULT_PRINT; */ 313 return S_OK; 314 } 315 316 static const IPrintDialogCallbackVtbl callback_Vtbl = 317 { 318 callback_QueryInterface, 319 callback_AddRef, 320 callback_Release, 321 callback_InitDone, 322 callback_SelectionChange, 323 callback_HandleMessage 324 }; 325 326 static IPrintDialogCallback callback = { &callback_Vtbl }; 327 328 static HRESULT WINAPI unknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) 329 { 330 trace("unknown_QueryInterface %s\n", wine_dbgstr_guid(riid)); 331 332 if (IsEqualGUID(riid, &IID_IPrintDialogCallback)) 333 { 334 *ppv = &callback; 335 return S_OK; 336 } 337 else if (IsEqualGUID(riid, &IID_IObjectWithSite)) 338 { 339 *ppv = NULL; 340 return E_NOINTERFACE; 341 } 342 343 ok(0, "unexpected IID %s\n", wine_dbgstr_guid(riid)); 344 *ppv = NULL; 345 return E_NOINTERFACE; 346 } 347 348 static ULONG WINAPI unknown_AddRef(IUnknown *iface) 349 { 350 trace("unknown_AddRef\n"); 351 return 2; 352 } 353 354 static ULONG WINAPI unknown_Release(IUnknown *iface) 355 { 356 trace("unknown_Release\n"); 357 return 1; 358 } 359 360 static const IUnknownVtbl unknown_Vtbl = 361 { 362 unknown_QueryInterface, 363 unknown_AddRef, 364 unknown_Release 365 }; 366 367 static IUnknown unknown = { &unknown_Vtbl }; 368 369 static void test_PrintDlgExW(void) 370 { 371 PRINTPAGERANGE pagerange[2]; 372 LPPRINTDLGEXW pDlg; 373 DEVNAMES *dn; 374 HRESULT res; 375 376 /* PrintDlgEx not present before w2k */ 377 if (!pPrintDlgExW) { 378 skip("PrintDlgExW not available\n"); 379 return; 380 } 381 382 if (0) /* Crashes on Win10 */ 383 { 384 /* Set CommDlgExtendedError != 0 */ 385 PrintDlgA(NULL); 386 SetLastError(0xdeadbeef); 387 res = pPrintDlgExW(NULL); 388 ok( (res == E_INVALIDARG), 389 "got 0x%x with %u and %u (expected 'E_INVALIDARG')\n", 390 res, GetLastError(), CommDlgExtendedError() ); 391 } 392 393 pDlg = HeapAlloc(GetProcessHeap(), 0, (sizeof(PRINTDLGEXW)) + 8); 394 if (!pDlg) return; 395 396 /* lStructSize must be exact */ 397 ZeroMemory(pDlg, sizeof(PRINTDLGEXW)); 398 pDlg->lStructSize = sizeof(PRINTDLGEXW) - 1; 399 PrintDlgA(NULL); 400 SetLastError(0xdeadbeef); 401 res = pPrintDlgExW(pDlg); 402 ok( (res == E_INVALIDARG), 403 "got 0x%x with %u and %u (expected 'E_INVALIDARG')\n", 404 res, GetLastError(), CommDlgExtendedError()); 405 406 407 ZeroMemory(pDlg, sizeof(PRINTDLGEXW)); 408 pDlg->lStructSize = sizeof(PRINTDLGEXW) + 1; 409 PrintDlgA(NULL); 410 SetLastError(0xdeadbeef); 411 res = pPrintDlgExW(pDlg); 412 ok( (res == E_INVALIDARG), 413 "got 0x%x with %u and %u (expected 'E_INVALIDARG')\n", 414 res, GetLastError(), CommDlgExtendedError()); 415 416 417 ZeroMemory(pDlg, sizeof(PRINTDLGEXW)); 418 pDlg->lStructSize = sizeof(PRINTDLGEXW); 419 SetLastError(0xdeadbeef); 420 res = pPrintDlgExW(pDlg); 421 ok( (res == E_HANDLE), 422 "got 0x%x with %u and %u (expected 'E_HANDLE')\n", 423 res, GetLastError(), CommDlgExtendedError()); 424 425 /* nStartPage must be START_PAGE_GENERAL for the general page or a valid property sheet index */ 426 ZeroMemory(pDlg, sizeof(PRINTDLGEXW)); 427 pDlg->lStructSize = sizeof(PRINTDLGEXW); 428 pDlg->hwndOwner = GetDesktopWindow(); 429 pDlg->Flags = PD_RETURNDEFAULT | PD_NOWARNING | PD_NOPAGENUMS; 430 res = pPrintDlgExW(pDlg); 431 ok((res == E_INVALIDARG), "got 0x%x (expected 'E_INVALIDARG')\n", res); 432 433 /* Use PD_NOPAGENUMS or set nMaxPageRanges and lpPageRanges */ 434 ZeroMemory(pDlg, sizeof(PRINTDLGEXW)); 435 pDlg->lStructSize = sizeof(PRINTDLGEXW); 436 pDlg->hwndOwner = GetDesktopWindow(); 437 pDlg->Flags = PD_RETURNDEFAULT | PD_NOWARNING; 438 pDlg->nStartPage = START_PAGE_GENERAL; 439 res = pPrintDlgExW(pDlg); 440 ok((res == E_INVALIDARG), "got 0x%x (expected 'E_INVALIDARG')\n", res); 441 442 /* this is invalid: a valid lpPageRanges with 0 for nMaxPageRanges */ 443 ZeroMemory(pDlg, sizeof(PRINTDLGEXW)); 444 pDlg->lStructSize = sizeof(PRINTDLGEXW); 445 pDlg->hwndOwner = GetDesktopWindow(); 446 pDlg->Flags = PD_RETURNDEFAULT | PD_NOWARNING; 447 pDlg->lpPageRanges = pagerange; 448 pDlg->nStartPage = START_PAGE_GENERAL; 449 res = pPrintDlgExW(pDlg); 450 ok((res == E_INVALIDARG), "got 0x%x (expected 'E_INVALIDARG')\n", res); 451 452 /* this is invalid: NULL for lpPageRanges with a valid nMaxPageRanges */ 453 ZeroMemory(pDlg, sizeof(PRINTDLGEXW)); 454 pDlg->lStructSize = sizeof(PRINTDLGEXW); 455 pDlg->hwndOwner = GetDesktopWindow(); 456 pDlg->Flags = PD_RETURNDEFAULT | PD_NOWARNING; 457 pDlg->nMaxPageRanges = 1; 458 pDlg->nStartPage = START_PAGE_GENERAL; 459 res = pPrintDlgExW(pDlg); 460 ok((res == E_INVALIDARG), "got 0x%x (expected 'E_INVALIDARG')\n", res); 461 462 /* this works: lpPageRanges with a valid nMaxPageRanges */ 463 ZeroMemory(pDlg, sizeof(PRINTDLGEXW)); 464 pDlg->lStructSize = sizeof(PRINTDLGEXW); 465 pDlg->hwndOwner = GetDesktopWindow(); 466 pDlg->Flags = PD_RETURNDEFAULT | PD_NOWARNING; 467 pDlg->nMaxPageRanges = 1; 468 pDlg->lpPageRanges = pagerange; 469 pDlg->nStartPage = START_PAGE_GENERAL; 470 res = pPrintDlgExW(pDlg); 471 if (res == E_FAIL) 472 { 473 skip("No printer configured.\n"); 474 HeapFree(GetProcessHeap(), 0, pDlg); 475 return; 476 } 477 478 ok(res == S_OK, "got 0x%x (expected S_OK)\n", res); 479 480 dn = GlobalLock(pDlg->hDevNames); 481 ok(dn != NULL, "expected '!= NULL' for GlobalLock(%p)\n",pDlg->hDevNames); 482 if (dn) 483 { 484 ok(dn->wDriverOffset, "(expected '!= 0' for wDriverOffset)\n"); 485 ok(dn->wDeviceOffset, "(expected '!= 0' for wDeviceOffset)\n"); 486 ok(dn->wOutputOffset, "(expected '!= 0' for wOutputOffset)\n"); 487 ok(dn->wDefault == DN_DEFAULTPRN, "got 0x%x (expected DN_DEFAULTPRN)\n", dn->wDefault); 488 489 GlobalUnlock(pDlg->hDevNames); 490 } 491 GlobalFree(pDlg->hDevMode); 492 GlobalFree(pDlg->hDevNames); 493 494 /* this works also: PD_NOPAGENUMS */ 495 ZeroMemory(pDlg, sizeof(PRINTDLGEXW)); 496 pDlg->lStructSize = sizeof(PRINTDLGEXW); 497 pDlg->hwndOwner = GetDesktopWindow(); 498 pDlg->Flags = PD_RETURNDEFAULT | PD_NOWARNING | PD_NOPAGENUMS; 499 pDlg->nStartPage = START_PAGE_GENERAL; 500 res = pPrintDlgExW(pDlg); 501 ok(res == S_OK, "got 0x%x (expected S_OK)\n", res); 502 GlobalFree(pDlg->hDevMode); 503 GlobalFree(pDlg->hDevNames); 504 505 /* this works: PD_RETURNDC with PD_RETURNDEFAULT */ 506 ZeroMemory(pDlg, sizeof(PRINTDLGEXW)); 507 pDlg->lStructSize = sizeof(PRINTDLGEXW); 508 pDlg->hwndOwner = GetDesktopWindow(); 509 pDlg->Flags = PD_RETURNDEFAULT | PD_NOWARNING | PD_NOPAGENUMS | PD_RETURNDC; 510 pDlg->nStartPage = START_PAGE_GENERAL; 511 res = pPrintDlgExW(pDlg); 512 ok(res == S_OK, "got 0x%x (expected S_OK)\n", res); 513 ok(pDlg->hDC != NULL, "HDC missing for PD_RETURNDC\n"); 514 GlobalFree(pDlg->hDevMode); 515 GlobalFree(pDlg->hDevNames); 516 DeleteDC(pDlg->hDC); 517 518 /* this works: PD_RETURNIC with PD_RETURNDEFAULT */ 519 ZeroMemory(pDlg, sizeof(PRINTDLGEXW)); 520 pDlg->lStructSize = sizeof(PRINTDLGEXW); 521 pDlg->hwndOwner = GetDesktopWindow(); 522 pDlg->Flags = PD_RETURNDEFAULT | PD_NOWARNING | PD_NOPAGENUMS | PD_RETURNIC; 523 pDlg->nStartPage = START_PAGE_GENERAL; 524 res = pPrintDlgExW(pDlg); 525 ok(res == S_OK, "got 0x%x (expected S_OK)\n", res); 526 ok(pDlg->hDC != NULL, "HDC missing for PD_RETURNIC\n"); 527 GlobalFree(pDlg->hDevMode); 528 GlobalFree(pDlg->hDevNames); 529 DeleteDC(pDlg->hDC); 530 531 /* interactive PrintDlgEx tests */ 532 533 if (!winetest_interactive) 534 { 535 skip("interactive PrintDlgEx tests (set WINETEST_INTERACTIVE=1)\n"); 536 HeapFree(GetProcessHeap(), 0, pDlg); 537 return; 538 } 539 540 ZeroMemory(pDlg, sizeof(PRINTDLGEXW)); 541 pDlg->lStructSize = sizeof(PRINTDLGEXW); 542 pDlg->hwndOwner = GetDesktopWindow(); 543 pDlg->Flags = PD_NOPAGENUMS | PD_RETURNIC; 544 pDlg->nStartPage = START_PAGE_GENERAL; 545 pDlg->lpCallback = &unknown; 546 pDlg->dwResultAction = S_OK; 547 res = pPrintDlgExW(pDlg); 548 ok(res == S_OK, "got 0x%x (expected S_OK)\n", res); 549 ok(pDlg->dwResultAction == PD_RESULT_PRINT, "expected PD_RESULT_PRINT, got %#x\n", pDlg->dwResultAction); 550 ok(pDlg->hDC != NULL, "HDC missing for PD_RETURNIC\n"); 551 GlobalFree(pDlg->hDevMode); 552 GlobalFree(pDlg->hDevNames); 553 DeleteDC(pDlg->hDC); 554 555 HeapFree(GetProcessHeap(), 0, pDlg); 556 } 557 558 static BOOL abort_proc_called = FALSE; 559 static BOOL CALLBACK abort_proc(HDC hdc, int error) { return abort_proc_called = TRUE; } 560 static void test_abort_proc(void) 561 { 562 HDC print_dc; 563 RECT rect = {0, 0, 100, 100}; 564 DOCINFOA doc_info = {0}; 565 PRINTDLGA pd = {0}; 566 char filename[MAX_PATH]; 567 int job_id; 568 569 if (!GetTempFileNameA(".", "prn", 0, filename)) 570 { 571 skip("Failed to create a temporary file name\n"); 572 return; 573 } 574 575 pd.lStructSize = sizeof(pd); 576 pd.Flags = PD_RETURNDEFAULT | PD_ALLPAGES | PD_RETURNDC | PD_PRINTTOFILE; 577 pd.nFromPage = 1; 578 pd.nToPage = 1; 579 pd.nCopies = 1; 580 581 if (!PrintDlgA(&pd)) 582 { 583 skip("No default printer available.\n"); 584 goto end; 585 } 586 GlobalFree(pd.hDevMode); 587 GlobalFree(pd.hDevNames); 588 589 ok(pd.hDC != NULL, "PrintDlg didn't return a DC.\n"); 590 if (!(print_dc = pd.hDC)) 591 goto end; 592 593 ok(SetAbortProc(print_dc, abort_proc) > 0, "SetAbortProc failed\n"); 594 ok(!abort_proc_called, "AbortProc got called unexpectedly by SetAbortProc.\n"); 595 abort_proc_called = FALSE; 596 597 doc_info.cbSize = sizeof(doc_info); 598 doc_info.lpszDocName = "Some document"; 599 doc_info.lpszOutput = filename; 600 601 job_id = StartDocA(print_dc, &doc_info); 602 603 ok(job_id > 0 || 604 GetLastError() == ERROR_SPL_NO_STARTDOC, /* Vista can fail with this error when using the XPS driver */ 605 "StartDocA failed ret %d gle %d\n", job_id, GetLastError()); 606 607 if(job_id <= 0) 608 { 609 skip("StartDoc failed\n"); 610 goto end; 611 } 612 613 /* StartDoc may or may not call abort proc */ 614 615 abort_proc_called = FALSE; 616 ok(StartPage(print_dc) > 0, "StartPage failed\n"); 617 ok(!abort_proc_called, "AbortProc got called unexpectedly by StartPage.\n"); 618 abort_proc_called = FALSE; 619 620 /* following functions sometimes call abort proc too */ 621 ok(FillRect(print_dc, &rect, (HBRUSH)(COLOR_BACKGROUND + 1)), "FillRect failed\n"); 622 ok(EndPage(print_dc) > 0, "EndPage failed\n"); 623 ok(EndDoc(print_dc) > 0, "EndDoc failed\n"); 624 625 abort_proc_called = FALSE; 626 ok(DeleteDC(print_dc), "DeleteDC failed\n"); 627 ok(!abort_proc_called, "AbortProc got called unexpectedly by DeleteDC.\n"); 628 abort_proc_called = FALSE; 629 630 end: 631 SetLastError(0xdeadbeef); 632 if(!DeleteFileA(filename)) 633 trace("Failed to delete temporary file (err = %x)\n", GetLastError()); 634 } 635 636 /* ########################### */ 637 638 START_TEST(printdlg) 639 { 640 hcomdlg32 = GetModuleHandleA("comdlg32.dll"); 641 pPrintDlgExW = (void *) GetProcAddress(hcomdlg32, "PrintDlgExW"); 642 643 test_PageSetupDlgA(); 644 test_PrintDlgA(); 645 test_PrintDlgExW(); 646 test_abort_proc(); 647 } 648