comdlg32/tests: Skip remaining tests if StartDoc fails.
[wine] / dlls / comdlg32 / tests / printdlg.c
1 /* 
2  * Unit test suite for comdlg32 API functions: printer dialogs
3  *
4  * Copyright 2006-2007 Detlef Riekenberg
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  */
21
22 #include <stdarg.h>
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winerror.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29 #include "objbase.h"
30
31 #include "cderr.h"
32 #include "commdlg.h"
33
34 #include "wine/test.h"
35
36 /* ########################### */
37
38 static HMODULE  hcomdlg32;
39 static HRESULT (WINAPI * pPrintDlgExA)(LPPRINTDLGEXA);
40 static HRESULT (WINAPI * pPrintDlgExW)(LPPRINTDLGEXW);
41
42 /* ########################### */
43
44 static const CHAR emptyA[] = "";
45 static const CHAR PrinterPortsA[] = "PrinterPorts";
46
47 /* ########################### */
48
49 static LPCSTR load_functions(void)
50 {
51     LPCSTR  ptr;
52
53     ptr = "comdlg32.dll";
54     hcomdlg32 = GetModuleHandleA(ptr);
55
56     ptr = "PrintDlgExA";
57     pPrintDlgExA = (void *) GetProcAddress(hcomdlg32, ptr);
58     if (!pPrintDlgExA) return ptr;
59
60     ptr = "PrintDlgExW";
61     pPrintDlgExW = (void *) GetProcAddress(hcomdlg32, ptr);
62     if (!pPrintDlgExW) return ptr;
63
64     return NULL;
65
66 }
67
68 /* ########################### */
69
70 static void test_PageSetupDlgA(void)
71 {
72     LPPAGESETUPDLGA pDlg;
73     DWORD res;
74
75     pDlg = HeapAlloc(GetProcessHeap(), 0, (sizeof(PAGESETUPDLGA)) * 2);
76     if (!pDlg) return;
77
78     SetLastError(0xdeadbeef);
79     res = PageSetupDlgA(NULL);
80     ok( !res && (CommDlgExtendedError() == CDERR_INITIALIZATION),
81         "returned %u with %u and 0x%x (expected '0' and "
82         "CDERR_INITIALIZATION)\n", res, GetLastError(), CommDlgExtendedError());
83
84     ZeroMemory(pDlg, sizeof(PAGESETUPDLGA));
85     pDlg->lStructSize = sizeof(PAGESETUPDLGA) -1;
86     SetLastError(0xdeadbeef);
87     res = PageSetupDlgA(pDlg);
88     ok( !res && (CommDlgExtendedError() == CDERR_STRUCTSIZE),
89         "returned %u with %u and 0x%x (expected '0' and "
90         "CDERR_STRUCTSIZE)\n", res, GetLastError(), CommDlgExtendedError());
91
92     ZeroMemory(pDlg, sizeof(PAGESETUPDLGA));
93     pDlg->lStructSize = sizeof(PAGESETUPDLGA) +1;
94     pDlg->Flags = PSD_RETURNDEFAULT;
95     SetLastError(0xdeadbeef);
96     res = PageSetupDlgA(pDlg);
97     ok( !res && (CommDlgExtendedError() == CDERR_STRUCTSIZE),
98         "returned %u with %u and 0x%x (expected '0' and CDERR_STRUCTSIZE)\n",
99         res, GetLastError(), CommDlgExtendedError());
100
101
102     ZeroMemory(pDlg, sizeof(PAGESETUPDLGA));
103     pDlg->lStructSize = sizeof(PAGESETUPDLGA);
104     pDlg->Flags = PSD_RETURNDEFAULT | PSD_NOWARNING;
105     SetLastError(0xdeadbeef);
106     res = PageSetupDlgA(pDlg);
107     ok( res || (CommDlgExtendedError() == PDERR_NODEFAULTPRN),
108         "returned %u with %u and 0x%x (expected '!= 0' or '0' and "
109         "PDERR_NODEFAULTPRN)\n", res, GetLastError(), CommDlgExtendedError());
110
111     if (!res && (CommDlgExtendedError() == PDERR_NODEFAULTPRN)) {
112         skip("No printer configured.\n");
113         HeapFree(GetProcessHeap(), 0, pDlg);
114         return;
115     }
116
117     ok( pDlg->hDevMode && pDlg->hDevNames,
118         "got %p and %p (expected '!= NULL' for both)\n",
119         pDlg->hDevMode, pDlg->hDevNames);
120
121     GlobalFree(pDlg->hDevMode);
122     GlobalFree(pDlg->hDevNames);
123
124     HeapFree(GetProcessHeap(), 0, pDlg);
125
126 }
127
128 /* ########################### */
129
130 static void test_PrintDlgA(void)
131 {
132     DWORD       res;
133     LPPRINTDLGA pDlg;
134     DEVNAMES    *pDevNames;
135     LPCSTR driver;
136     LPCSTR device;
137     LPCSTR port;
138     CHAR   buffer[MAX_PATH];
139     LPSTR  ptr;
140
141
142     pDlg = HeapAlloc(GetProcessHeap(), 0, (sizeof(PRINTDLGA)) * 2);
143     if (!pDlg) return;
144
145
146     /* will crash with unpatched wine */
147     SetLastError(0xdeadbeef);
148     res = PrintDlgA(NULL);
149     ok( !res && (CommDlgExtendedError() == CDERR_INITIALIZATION),
150         "returned %d with 0x%x and 0x%x (expected '0' and "
151         "CDERR_INITIALIZATION)\n", res, GetLastError(), CommDlgExtendedError());
152
153     ZeroMemory(pDlg, sizeof(PRINTDLGA));
154     pDlg->lStructSize = sizeof(PRINTDLGA) - 1;
155     SetLastError(0xdeadbeef);
156     res = PrintDlgA(pDlg);
157     ok( !res && (CommDlgExtendedError() == CDERR_STRUCTSIZE),
158         "returned %d with 0x%x and 0x%x (expected '0' and "
159         "CDERR_STRUCTSIZE)\n", res, GetLastError(), CommDlgExtendedError());
160
161     ZeroMemory(pDlg, sizeof(PRINTDLGA));
162     pDlg->lStructSize = sizeof(PRINTDLGA) + 1;
163     pDlg->Flags = PD_RETURNDEFAULT;
164     SetLastError(0xdeadbeef);
165     res = PrintDlgA(pDlg);
166     ok( !res && (CommDlgExtendedError() == CDERR_STRUCTSIZE),
167         "returned %u with %u and 0x%x (expected '0' and "
168         "CDERR_STRUCTSIZE)\n", res, GetLastError(), CommDlgExtendedError());
169
170
171     ZeroMemory(pDlg, sizeof(PRINTDLGA));
172     pDlg->lStructSize = sizeof(PRINTDLGA);
173     pDlg->Flags = PD_RETURNDEFAULT;
174     SetLastError(0xdeadbeef);
175     res = PrintDlgA(pDlg);
176     ok( res || (CommDlgExtendedError() == PDERR_NODEFAULTPRN),
177         "returned %d with 0x%x and 0x%x (expected '!= 0' or '0' and "
178         "PDERR_NODEFAULTPRN)\n", res, GetLastError(), CommDlgExtendedError());
179
180     if (!res && (CommDlgExtendedError() == PDERR_NODEFAULTPRN)) {
181         skip("No printer configured.\n");
182         HeapFree(GetProcessHeap(), 0, pDlg);
183         return;
184     }
185
186     ok(pDlg->hDevNames != NULL, "(expected '!= NULL')\n");
187     pDevNames = GlobalLock(pDlg->hDevNames);
188     ok(pDevNames != NULL, "(expected '!= NULL')\n");
189
190     if (pDevNames) {
191         ok(pDevNames->wDriverOffset, "(expected '!= 0' for wDriverOffset)\n");
192         ok(pDevNames->wDeviceOffset, "(expected '!= 0' for wDeviceOffset)\n");
193         ok(pDevNames->wOutputOffset, "(expected '!= 0' for wOutputOffset)\n");
194         ok(pDevNames->wDefault == DN_DEFAULTPRN, "got 0x%x (expected DN_DEFAULTPRN)\n", pDevNames->wDefault);
195
196         driver = (LPCSTR)pDevNames + pDevNames->wDriverOffset;
197         device = (LPCSTR)pDevNames + pDevNames->wDeviceOffset;
198         port = (LPCSTR)pDevNames + pDevNames->wOutputOffset;
199         trace("driver '%s' device '%s' port '%s'\n", driver, device, port);
200
201         /* The Driver Entry does not include a Path */
202         ptr = strrchr(driver, '\\');
203         todo_wine {
204         ok( ptr == NULL, "got %p for '%s' (expected NULL for a simple name)\n", ptr, driver);
205         }
206
207         /* The Driver Entry does not have an extension (fixed to ".drv") */
208         ptr = strrchr(driver, '.');
209         todo_wine {
210         ok( ptr == NULL, "got %p for '%s' (expected NULL for no extension)\n", ptr, driver);
211         }
212
213
214         buffer[0] = '\0';
215         SetLastError(0xdeadbeef);
216         res = GetProfileStringA(PrinterPortsA, device, emptyA, buffer, sizeof(buffer));
217         ptr = strchr(buffer, ',');
218         ok( (res > 1) && (ptr != NULL),
219             "got %u with %u and %p for '%s' (expected '>1' and '!= NULL')\n",
220             res, GetLastError(), ptr, buffer);
221
222         if (ptr) ptr[0] = '\0';
223         todo_wine {
224         ok( lstrcmpiA(driver, buffer) == 0,
225             "got driver '%s' (expected '%s')\n", driver, buffer);
226         }
227
228     }
229
230     GlobalUnlock(pDlg->hDevNames);
231
232     GlobalFree(pDlg->hDevMode);
233     GlobalFree(pDlg->hDevNames);
234     HeapFree(GetProcessHeap(), 0, pDlg);
235
236 }
237
238 /* ########################### */
239
240 static void test_PrintDlgExW(void)
241 {
242     LPPRINTDLGEXW pDlg;
243     HRESULT res;
244
245     /* Set CommDlgExtendedError != 0 */
246     PrintDlg(NULL);
247     SetLastError(0xdeadbeef);
248     res = pPrintDlgExW(NULL);
249     ok( (res == E_INVALIDARG),
250         "got 0x%x with %u and %u (expected 'E_INVALIDARG')\n",
251         res, GetLastError(), CommDlgExtendedError());
252
253
254     pDlg = HeapAlloc(GetProcessHeap(), 0, (sizeof(PRINTDLGEXW)) + 8);
255     if (!pDlg) return;
256
257     /* lStructSize must be exact */
258     ZeroMemory(pDlg, sizeof(PRINTDLGEXW));
259     pDlg->lStructSize = sizeof(PRINTDLGEXW) - 1;
260     PrintDlg(NULL);
261     SetLastError(0xdeadbeef);
262     res = pPrintDlgExW(pDlg);
263     ok( (res == E_INVALIDARG),
264         "got 0x%x with %u and %u (expected 'E_INVALIDARG')\n",
265         res, GetLastError(), CommDlgExtendedError());
266
267
268     ZeroMemory(pDlg, sizeof(PRINTDLGEXW));
269     pDlg->lStructSize = sizeof(PRINTDLGEXW) + 1;
270     PrintDlg(NULL);
271     SetLastError(0xdeadbeef);
272     res = pPrintDlgExW(pDlg);
273     ok( (res == E_INVALIDARG),
274         "got 0x%x with %u and %u (expected 'E_INVALIDARG')\n",
275         res, GetLastError(), CommDlgExtendedError());
276
277
278     ZeroMemory(pDlg, sizeof(PRINTDLGEXW));
279     pDlg->lStructSize = sizeof(PRINTDLGEXW);
280     SetLastError(0xdeadbeef);
281     res = pPrintDlgExW(pDlg);
282     ok( (res == E_HANDLE),
283         "got 0x%x with %u and %u (expected 'E_HANDLE')\n",
284         res, GetLastError(), CommDlgExtendedError());
285
286
287     HeapFree(GetProcessHeap(), 0, pDlg);
288     return;
289
290 }
291
292 static BOOL abort_proc_called = FALSE;
293 static BOOL CALLBACK abort_proc(HDC hdc, int error) { return abort_proc_called = TRUE; }
294 static void test_abort_proc(void)
295 {
296     HDC print_dc;
297     RECT rect = {0, 0, 100, 100};
298     DOCINFOA doc_info = {0};
299     PRINTDLGA pd = {0};
300     char filename[MAX_PATH];
301     int job_id;
302
303     if (!GetTempFileNameA(".", "prn", 0, filename))
304     {
305         skip("Failed to create a temporary file name\n");
306         return;
307     }
308
309     pd.lStructSize = sizeof(pd);
310     pd.Flags = PD_RETURNDEFAULT | PD_ALLPAGES | PD_RETURNDC | PD_PRINTTOFILE;
311     pd.nFromPage = 1;
312     pd.nToPage = 1;
313     pd.nCopies = 1;
314
315     if (!PrintDlgA(&pd))
316     {
317         skip("No default printer available.\n");
318         ok(DeleteFileA(filename), "Failed to delete temporary file\n");
319         return;
320     }
321
322     ok(pd.hDC != NULL, "PrintDlg didn't return a DC.\n");
323     if (!(print_dc = pd.hDC))
324     {
325         ok(DeleteFileA(filename), "Failed to delete temporary file\n");
326         return;
327     }
328
329     ok(SetAbortProc(print_dc, abort_proc) > 0, "SetAbortProc failed\n");
330     ok(!abort_proc_called, "AbortProc got called unexpectedly by SetAbortProc.\n");
331     abort_proc_called = FALSE;
332
333     doc_info.cbSize = sizeof(doc_info);
334     doc_info.lpszDocName = "Some document";
335     doc_info.lpszOutput = filename;
336
337     job_id = StartDocA(print_dc, &doc_info);
338     ok(job_id > 0, "StartDocA failed ret %d gle %d\n", job_id, GetLastError());
339     if(job_id <= 0)
340     {
341         skip("StartDoc failed\n");
342         goto end;
343     }
344
345     ok(abort_proc_called, "AbortProc didn't get called by StartDoc.\n");
346     abort_proc_called = FALSE;
347
348     ok(StartPage(print_dc) > 0, "StartPage failed\n");
349     ok(!abort_proc_called, "AbortProc got called unexpectedly by StartPage.\n");
350     abort_proc_called = FALSE;
351
352     ok(FillRect(print_dc, &rect, (HBRUSH)(COLOR_BACKGROUND + 1)), "FillRect failed\n");
353     ok(!abort_proc_called, "AbortProc got called unexpectedly by StretchBlt.\n");
354     abort_proc_called = FALSE;
355
356     ok(EndPage(print_dc) > 0, "EndPage failed\n");
357     ok(!abort_proc_called, "AbortProc got called unexpectedly by EndPage.\n");
358     abort_proc_called = FALSE;
359
360     ok(EndDoc(print_dc) > 0, "EndDoc failed\n");
361     ok(!abort_proc_called, "AbortProc got called unexpectedly by EndDoc.\n");
362     abort_proc_called = FALSE;
363
364     ok(DeleteDC(print_dc), "DeleteDC failed\n");
365     ok(!abort_proc_called, "AbortProc got called unexpectedly by DeleteDC.\n");
366     abort_proc_called = FALSE;
367
368 end:
369     ok(DeleteFileA(filename), "Failed to delete temporary file\n");
370 }
371
372 /* ########################### */
373
374 START_TEST(printdlg)
375 {
376     LPCSTR  ptr;
377
378     ptr = load_functions();
379
380     test_PageSetupDlgA();
381     test_PrintDlgA();
382     test_abort_proc();
383
384     /* PrintDlgEx not present before w2k */
385     if (ptr) {
386         skip("%s\n", ptr);
387         return;
388     }
389
390     test_PrintDlgExW();
391 }