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