1 /*
2  * Copyright (C) 2003, 2004 Stefan Leichter
3  * Copyright (C) 2005, 2006 Detlef Riekenberg
4  * Copyright (C) 2006 Dmitry Timoshkov
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 #include <stdarg.h>
22 #include <assert.h>
23 
24 #define NONAMELESSSTRUCT
25 #define NONAMELESSUNION
26 
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winerror.h"
30 #include "wingdi.h"
31 #include "winnls.h"
32 #include "winuser.h"
33 #include "winreg.h"
34 #include "winspool.h"
35 #include "commdlg.h"
36 #include "wine/test.h"
37 
38 #define MAGIC_DEAD  0xdeadbeef
39 #define DEFAULT_PRINTER_SIZE 1000
40 
41 static CHAR defaultspooldirectory[] = "DefaultSpoolDirectory";
42 static CHAR does_not_exist_dll[]= "does_not_exist.dll";
43 static CHAR does_not_exist[]    = "does_not_exist";
44 static CHAR empty[]             = "";
45 static CHAR env_x64[]           = "Windows x64";
46 static CHAR env_x86[]           = "Windows NT x86";
47 static CHAR env_win9x_case[]    = "windowS 4.0";
48 static CHAR illegal_name[]      = "illegal,name";
49 static CHAR invalid_env[]       = "invalid_env";
50 static CHAR LocalPortA[]        = "Local Port";
51 static CHAR portname_com1[]     = "COM1:";
52 static CHAR portname_file[]     = "FILE:";
53 static CHAR portname_lpt1[]     = "LPT1:";
54 static CHAR server_does_not_exist[] = "\\\\does_not_exist";
55 static CHAR version_dll[]       = "version.dll";
56 static CHAR winetest[]          = "winetest";
57 static CHAR xcv_localport[]     = ",XcvMonitor Local Port";
58 
59 static const WCHAR cmd_MonitorUIW[] = {'M','o','n','i','t','o','r','U','I',0};
60 static const WCHAR cmd_PortIsValidW[] = {'P','o','r','t','I','s','V','a','l','i','d',0};
61 static WCHAR emptyW[] = {0};
62 
63 static WCHAR portname_com1W[] = {'C','O','M','1',':',0};
64 static WCHAR portname_com2W[] = {'C','O','M','2',':',0};
65 static WCHAR portname_fileW[] = {'F','I','L','E',':',0};
66 static WCHAR portname_lpt1W[] = {'L','P','T','1',':',0};
67 static WCHAR portname_lpt2W[] = {'L','P','T','2',':',0};
68 
69 static HANDLE  hwinspool;
70 static BOOL  (WINAPI * pAddPortExA)(LPSTR, DWORD, LPBYTE, LPSTR);
71 static BOOL  (WINAPI * pEnumPrinterDriversW)(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
72 static BOOL  (WINAPI * pGetDefaultPrinterA)(LPSTR, LPDWORD);
73 static DWORD (WINAPI * pGetPrinterDataExA)(HANDLE, LPCSTR, LPCSTR, LPDWORD, LPBYTE, DWORD, LPDWORD);
74 static BOOL  (WINAPI * pGetPrinterDriverW)(HANDLE, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD);
75 static BOOL  (WINAPI * pGetPrinterW)(HANDLE, DWORD, LPBYTE, DWORD, LPDWORD);
76 static BOOL  (WINAPI * pSetDefaultPrinterA)(LPCSTR);
77 static DWORD (WINAPI * pXcvDataW)(HANDLE, LPCWSTR, PBYTE, DWORD, PBYTE, DWORD, PDWORD, PDWORD);
78 static BOOL  (WINAPI * pIsValidDevmodeW)(PDEVMODEW, SIZE_T);
79 
80 
81 /* ################################ */
82 
83 struct monitor_entry {
84     LPSTR  env;
85     CHAR  dllname[32];
86 };
87 
88 static LPSTR default_printer = NULL;
89 static LPSTR local_server = NULL;
90 static LPSTR tempdirA = NULL;
91 static LPSTR tempfileA = NULL;
92 static LPWSTR tempdirW = NULL;
93 static LPWSTR tempfileW = NULL;
94 
95 static BOOL is_spooler_deactivated(DWORD res, DWORD lasterror)
96 {
97     if (!res && lasterror == RPC_S_SERVER_UNAVAILABLE)
98     {
99         static int deactivated_spooler_reported = 0;
100         if (!deactivated_spooler_reported)
101         {
102             deactivated_spooler_reported = 1;
103             skip("The service 'Spooler' is required for many tests\n");
104         }
105         return TRUE;
106     }
107     return FALSE;
108 }
109 
110 static BOOL is_access_denied(DWORD res, DWORD lasterror)
111 {
112     if (!res && lasterror == ERROR_ACCESS_DENIED)
113     {
114         static int access_denied_reported = 0;
115         if (!access_denied_reported)
116         {
117             access_denied_reported = 1;
118             skip("More access rights are required for many tests\n");
119         }
120         return TRUE;
121     }
122     return FALSE;
123 }
124 
125 static BOOL on_win9x = FALSE;
126 
127 static BOOL check_win9x(void)
128 {
129     if (pGetPrinterW)
130     {
131         SetLastError(0xdeadbeef);
132         pGetPrinterW(NULL, 0, NULL, 0, NULL);
133         return (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED);
134     }
135     else
136     {
137         return TRUE;
138     }
139 }
140 
141 static void find_default_printer(VOID)
142 {
143     static  char    buffer[DEFAULT_PRINTER_SIZE];
144     DWORD   needed;
145     DWORD   res;
146     LPSTR   ptr;
147 
148     if ((default_printer == NULL) && (pGetDefaultPrinterA))
149     {
150         /* w2k and above */
151         needed = sizeof(buffer);
152         res = pGetDefaultPrinterA(buffer, &needed);
153         if(res)  default_printer = buffer;
154         trace("default_printer: '%s'\n", default_printer ? default_printer : "(null)");
155     }
156     if (default_printer == NULL)
157     {
158         HKEY hwindows;
159         DWORD   type;
160         /* NT 3.x and above */
161         if (RegOpenKeyExA(HKEY_CURRENT_USER,
162                           "Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows",
163                           0, KEY_QUERY_VALUE, &hwindows) == NO_ERROR) {
164 
165             needed = sizeof(buffer);
166             if (RegQueryValueExA(hwindows, "device", NULL, &type, (LPBYTE)buffer, &needed) == NO_ERROR) {
167                 ptr = strchr(buffer, ',');
168                 if (ptr) {
169                     ptr[0] = '\0';
170                     default_printer = buffer;
171                 }
172             }
173             RegCloseKey(hwindows);
174         }
175         trace("default_printer: '%s'\n", default_printer ? default_printer : "(null)");
176     }
177     if (default_printer == NULL)
178     {
179         /* win9x */
180         needed = sizeof(buffer);
181         res = GetProfileStringA("windows", "device", "*", buffer, needed);
182         if(res) {
183             ptr = strchr(buffer, ',');
184             if (ptr) {
185                 ptr[0] = '\0';
186                 default_printer = buffer;
187             }
188         }
189         trace("default_printer: '%s'\n", default_printer ? default_printer : "(null)");
190     }
191 }
192 
193 
194 static struct monitor_entry * find_installed_monitor(void)
195 {
196     MONITOR_INFO_2A mi2a;
197     static struct  monitor_entry * entry = NULL;
198     DWORD   num_tests;
199     DWORD   i = 0;
200 
201     static struct monitor_entry  monitor_table[] = {
202         {env_win9x_case, "localspl.dll"},
203         {env_x86,        "localspl.dll"},
204         {env_x64,        "localspl.dll"},
205         {env_win9x_case, "localmon.dll"},
206         {env_x86,        "localmon.dll"},
207         {env_win9x_case, "tcpmon.dll"},
208         {env_x86,        "tcpmon.dll"},
209         {env_win9x_case, "usbmon.dll"},
210         {env_x86,        "usbmon.dll"},
211         {env_win9x_case, "mspp32.dll"},
212         {env_x86,        "win32spl.dll"},
213         {env_x86,        "redmonnt.dll"},
214         {env_x86,        "redmon35.dll"},
215         {env_win9x_case, "redmon95.dll"},
216         {env_x86,        "pdfcmnnt.dll"},
217         {env_win9x_case, "pdfcmn95.dll"},
218     };
219 
220     if (entry) return entry;
221 
222     num_tests = (sizeof(monitor_table)/sizeof(struct monitor_entry));
223 
224     /* cleanup */
225     DeleteMonitorA(NULL, env_x64, winetest);
226     DeleteMonitorA(NULL, env_x86, winetest);
227     DeleteMonitorA(NULL, env_win9x_case, winetest);
228 
229     /* find a usable monitor from the table */
230     mi2a.pName = winetest;
231     while ((entry == NULL) && (i < num_tests)) {
232         entry = &monitor_table[i];
233         i++;
234         mi2a.pEnvironment = entry->env;
235         mi2a.pDLLName = entry->dllname;
236 
237         if (AddMonitorA(NULL, 2, (LPBYTE) &mi2a)) {
238             /* we got one */
239             trace("using '%s', '%s'\n", entry->env, entry->dllname);
240             DeleteMonitorA(NULL, entry->env, winetest);
241         }
242         else
243         {
244             entry = NULL;
245         }
246     }
247     return entry;
248 }
249 
250 
251 /* ########################### */
252 
253 static void find_local_server(VOID)
254 {
255     static  char    buffer[MAX_PATH];
256     DWORD   res;
257     DWORD   size;
258 
259     size = sizeof(buffer) - 3 ;
260     buffer[0] = '\\';
261     buffer[1] = '\\';
262     buffer[2] = '\0';
263 
264     SetLastError(0xdeadbeef);
265     res = GetComputerNameA(&buffer[2], &size);
266     trace("returned %d with %d and %d: '%s'\n", res, GetLastError(), size, buffer);
267 
268     ok( res != 0, "returned %d with %d and %d: '%s' (expected '!= 0')\n",
269         res, GetLastError(), size, buffer);
270 
271     if (res) local_server = buffer;
272 }
273 
274 /* ########################### */
275 
276 static void find_tempfile(VOID)
277 {
278     static CHAR buffer_dirA[MAX_PATH];
279     static CHAR buffer_fileA[MAX_PATH];
280     static WCHAR buffer_dirW[MAX_PATH];
281     static WCHAR buffer_fileW[MAX_PATH];
282     DWORD   res;
283     int     resint;
284 
285     memset(buffer_dirA, 0, MAX_PATH - 1);
286     buffer_dirA[MAX_PATH - 1] = '\0';
287     SetLastError(0xdeadbeef);
288     res = GetTempPathA(MAX_PATH, buffer_dirA);
289     ok(res, "returned %u with %u and '%s' (expected '!= 0')\n", res, GetLastError(), buffer_dirA);
290     if (res == 0) return;
291 
292     memset(buffer_fileA, 0, MAX_PATH - 1);
293     buffer_fileA[MAX_PATH - 1] = '\0';
294     SetLastError(0xdeadbeef);
295     res = GetTempFileNameA(buffer_dirA, winetest, 0, buffer_fileA);
296     ok(res, "returned %u with %u and '%s' (expected '!= 0')\n", res, GetLastError(), buffer_fileA);
297     if (res == 0) return;
298 
299     SetLastError(0xdeadbeef);
300     resint = MultiByteToWideChar(CP_ACP, 0, buffer_dirA, -1, buffer_dirW, MAX_PATH);
301     ok(res, "returned %u with %u (expected '!= 0')\n", resint, GetLastError());
302     if (resint == 0) return;
303 
304     SetLastError(0xdeadbeef);
305     resint = MultiByteToWideChar(CP_ACP, 0, buffer_fileA, -1, buffer_fileW, MAX_PATH);
306     ok(res, "returned %u with %u (expected '!= 0')\n", resint, GetLastError());
307     if (resint == 0) return;
308 
309     tempdirA  = buffer_dirA;
310     tempfileA = buffer_fileA;
311     tempdirW  = buffer_dirW;
312     tempfileW = buffer_fileW;
313     trace("tempfile: '%s'\n", tempfileA);
314 }
315 
316 /* ########################### */
317 
318 static void test_AddMonitor(void)
319 {
320     MONITOR_INFO_2A mi2a;
321     struct  monitor_entry * entry = NULL;
322     DWORD   res;
323 
324     entry = find_installed_monitor();
325 
326     SetLastError(MAGIC_DEAD);
327     res = AddMonitorA(NULL, 1, NULL);
328     ok(!res && (GetLastError() == ERROR_INVALID_LEVEL),
329         "returned %d with %d (expected '0' with ERROR_INVALID_LEVEL)\n",
330         res, GetLastError());
331 
332     SetLastError(MAGIC_DEAD);
333     res = AddMonitorA(NULL, 3, NULL);
334     ok(!res && (GetLastError() == ERROR_INVALID_LEVEL),
335         "returned %d with %d (expected '0' with ERROR_INVALID_LEVEL)\n",
336         res, GetLastError());
337 
338     if (0)
339     {
340     /* This test crashes win9x on vmware (works with win9x on qemu 0.8.1) */
341     SetLastError(MAGIC_DEAD);
342     res = AddMonitorA(NULL, 2, NULL);
343     /* NT: unchanged,  9x: ERROR_PRIVILEGE_NOT_HELD */
344     ok(!res &&
345         ((GetLastError() == MAGIC_DEAD) ||
346          (GetLastError() == ERROR_PRIVILEGE_NOT_HELD)),
347         "returned %d with %d (expected '0' with: MAGIC_DEAD or "
348         "ERROR_PRIVILEGE_NOT_HELD)\n", res, GetLastError());
349     }
350 
351     ZeroMemory(&mi2a, sizeof(MONITOR_INFO_2A));
352     SetLastError(MAGIC_DEAD);
353     res = AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
354     if (is_spooler_deactivated(res, GetLastError())) return;
355     if (is_access_denied(res, GetLastError())) return;
356 
357     /* NT: ERROR_INVALID_PARAMETER,  9x: ERROR_INVALID_ENVIRONMENT */
358     ok(!res && ((GetLastError() == ERROR_INVALID_PARAMETER) ||
359                 (GetLastError() == ERROR_INVALID_ENVIRONMENT)),
360         "returned %d with %d (expected '0' with: ERROR_INVALID_PARAMETER or "
361         "ERROR_INVALID_ENVIRONMENT)\n", res, GetLastError());
362 
363     if (!entry) {
364         skip("No usable Monitor found\n");
365         return;
366     }
367 
368     if (0)
369     {
370     /* The test is deactivated, because when mi2a.pName is NULL, the subkey
371        HKLM\System\CurrentControlSet\Control\Print\Monitors\C:\WINDOWS\SYSTEM
372        or HKLM\System\CurrentControlSet\Control\Print\Monitors\ì
373        is created on win9x and we do not want to hit this bug here. */
374 
375     mi2a.pEnvironment = entry->env;
376     SetLastError(MAGIC_DEAD);
377     res = AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
378     ok(res, "AddMonitor error %d\n", GetLastError());
379     /* NT: ERROR_INVALID_PARAMETER,  9x: ERROR_PRIVILEGE_NOT_HELD */
380     }
381 
382     mi2a.pEnvironment = entry->env;
383     mi2a.pName = empty;
384     SetLastError(MAGIC_DEAD);
385     res = AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
386     /* NT: ERROR_INVALID_PARAMETER,  9x: ERROR_PRIVILEGE_NOT_HELD */
387     ok( !res &&
388         ((GetLastError() == ERROR_INVALID_PARAMETER) ||
389          (GetLastError() == ERROR_PRIVILEGE_NOT_HELD)),
390         "returned %d with %d (expected '0' with: ERROR_INVALID_PARAMETER or "
391         "ERROR_PRIVILEGE_NOT_HELD)\n",
392         res, GetLastError());
393 
394     mi2a.pName = winetest;
395     SetLastError(MAGIC_DEAD);
396     res = AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
397     /* NT: ERROR_INVALID_PARAMETER,  9x: ERROR_PRIVILEGE_NOT_HELD */
398     ok( !res &&
399         ((GetLastError() == ERROR_INVALID_PARAMETER) ||
400          (GetLastError() == ERROR_PRIVILEGE_NOT_HELD)),
401         "returned %d with %d (expected '0' with: ERROR_INVALID_PARAMETER or "
402         "ERROR_PRIVILEGE_NOT_HELD)\n",
403         res, GetLastError());
404 
405     mi2a.pDLLName = empty;
406     SetLastError(MAGIC_DEAD);
407     res = AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
408     ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
409         "returned %d with %d (expected '0' with ERROR_INVALID_PARAMETER)\n",
410         res, GetLastError());
411 
412     mi2a.pDLLName = does_not_exist_dll;
413     SetLastError(MAGIC_DEAD);
414     res = AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
415     /* NT: ERROR_MOD_NOT_FOUND,  9x: ERROR_INVALID_PARAMETER */
416     ok( !res &&
417         ((GetLastError() == ERROR_MOD_NOT_FOUND) ||
418         (GetLastError() == ERROR_INVALID_PARAMETER)),
419         "returned %d with %d (expected '0' with: ERROR_MOD_NOT_FOUND or "
420         "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
421 
422     mi2a.pDLLName = version_dll;
423     SetLastError(MAGIC_DEAD);
424     res = AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
425     /* NT: ERROR_PROC_NOT_FOUND,  9x: ERROR_INVALID_PARAMETER */
426     ok( !res &&
427         ((GetLastError() == ERROR_PROC_NOT_FOUND) ||
428         (GetLastError() == ERROR_INVALID_PARAMETER)),
429         "returned %d with %d (expected '0' with: ERROR_PROC_NOT_FOUND or "
430         "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
431     if (res) DeleteMonitorA(NULL, entry->env, winetest);
432 
433    /* Test AddMonitor with real options */
434     mi2a.pDLLName = entry->dllname;
435     SetLastError(MAGIC_DEAD);
436     res = AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
437     /* Some apps depend on the result of GetLastError() also on success of AddMonitor */
438     ok(res && (GetLastError() == ERROR_SUCCESS),
439         "returned %d with %d (expected '!= 0' with ERROR_SUCCESS)\n", res, GetLastError());
440 
441     /* add a monitor twice */
442     SetLastError(MAGIC_DEAD);
443     res = AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
444     /* NT: ERROR_PRINT_MONITOR_ALREADY_INSTALLED (3006), 9x: ERROR_ALREADY_EXISTS (183) */
445     ok( !res &&
446         ((GetLastError() == ERROR_PRINT_MONITOR_ALREADY_INSTALLED) ||
447         (GetLastError() == ERROR_ALREADY_EXISTS)),
448         "returned %d with %d (expected '0' with: "
449         "ERROR_PRINT_MONITOR_ALREADY_INSTALLED or ERROR_ALREADY_EXISTS)\n",
450         res, GetLastError());
451 
452     DeleteMonitorA(NULL, entry->env, winetest);
453     SetLastError(MAGIC_DEAD);
454     res = AddMonitorA(empty, 2, (LPBYTE) &mi2a);
455     ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError());
456 
457     /* cleanup */
458     DeleteMonitorA(NULL, entry->env, winetest);
459 
460 }
461 
462 /* ########################### */
463 
464 static void test_AddPort(void)
465 {
466     DWORD   res;
467 
468     SetLastError(0xdeadbeef);
469     res = AddPortA(NULL, 0, NULL);
470     if (is_spooler_deactivated(res, GetLastError())) return;
471     /* NT: RPC_X_NULL_REF_POINTER, 9x: ERROR_INVALID_PARAMETER */
472     ok( !res && ((GetLastError() == RPC_X_NULL_REF_POINTER) ||
473                  (GetLastError() == ERROR_INVALID_PARAMETER)),
474         "returned %d with %d (expected '0' with ERROR_NOT_SUPPORTED or "
475         "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
476 
477 
478     SetLastError(0xdeadbeef);
479     res = AddPortA(NULL, 0, empty);
480     /* Allowed only for (Printer-)Administrators */
481     if (is_access_denied(res, GetLastError())) return;
482 
483     /* XP: ERROR_NOT_SUPPORTED, NT351 and 9x: ERROR_INVALID_PARAMETER */
484     ok( !res && ((GetLastError() == ERROR_NOT_SUPPORTED) ||
485                  (GetLastError() == ERROR_INVALID_PARAMETER)),
486         "returned %d with %d (expected '0' with ERROR_NOT_SUPPORTED or "
487         "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
488 
489 
490     SetLastError(0xdeadbeef);
491     res = AddPortA(NULL, 0, does_not_exist);
492     /* XP: ERROR_NOT_SUPPORTED, NT351 and 9x: ERROR_INVALID_PARAMETER */
493     ok( !res && ((GetLastError() == ERROR_NOT_SUPPORTED) ||
494                  (GetLastError() == ERROR_INVALID_PARAMETER)),
495         "returned %d with %d (expected '0' with ERROR_NOT_SUPPORTED or "
496         "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
497 
498 }
499 
500 /* ########################### */
501 
502 static void test_AddPortEx(void)
503 {
504     PORT_INFO_2A pi;
505     DWORD   res;
506 
507 
508     if (!pAddPortExA) {
509         win_skip("AddPortEx not supported\n");
510         return;
511     }
512 
513     /* start test with a clean system */
514     DeletePortA(NULL, 0, tempfileA);
515 
516     pi.pPortName = tempfileA;
517     SetLastError(0xdeadbeef);
518     res = pAddPortExA(NULL, 1, (LPBYTE) &pi, LocalPortA);
519     if (is_spooler_deactivated(res, GetLastError())) return;
520 
521     /* Allowed only for (Printer-)Administrators.
522        W2K+XP: ERROR_INVALID_PARAMETER  */
523     if (!res && (GetLastError() == ERROR_INVALID_PARAMETER)) {
524         skip("ACCESS_DENIED (ERROR_INVALID_PARAMETER)\n");
525         return;
526     }
527     ok( res, "got %u with %u (expected '!= 0')\n", res, GetLastError());
528 
529     /* add a port that already exists */
530     SetLastError(0xdeadbeef);
531     res = pAddPortExA(NULL, 1, (LPBYTE) &pi, LocalPortA);
532     ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
533         "got %u with %u (expected '0' with ERROR_INVALID_PARAMETER)\n",
534         res, GetLastError());
535     DeletePortA(NULL, 0, tempfileA);
536 
537 
538     /* the Monitorname must match */
539     SetLastError(0xdeadbeef);
540     res = pAddPortExA(NULL, 1, (LPBYTE) &pi, NULL);
541     ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
542         "got %u with %u (expected '0' with ERROR_INVALID_PARAMETER)\n",
543         res, GetLastError());
544     if (res) DeletePortA(NULL, 0, tempfileA);
545 
546     SetLastError(0xdeadbeef);
547     res = pAddPortExA(NULL, 1, (LPBYTE) &pi, empty);
548     ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
549         "got %u with %u (expected '0' with ERROR_INVALID_PARAMETER)\n",
550         res, GetLastError());
551     if (res) DeletePortA(NULL, 0, tempfileA);
552 
553     SetLastError(0xdeadbeef);
554     res = pAddPortExA(NULL, 1, (LPBYTE) &pi, does_not_exist);
555     ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
556         "got %u with %u (expected '0' with ERROR_INVALID_PARAMETER)\n",
557         res, GetLastError());
558     if (res) DeletePortA(NULL, 0, tempfileA);
559 
560 
561     /* We need a Portname */
562     SetLastError(0xdeadbeef);
563     res = pAddPortExA(NULL, 1, NULL, LocalPortA);
564     ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
565         "got %u with %u (expected '0' with ERROR_INVALID_PARAMETER)\n",
566         res, GetLastError());
567 
568     pi.pPortName = NULL;
569     SetLastError(0xdeadbeef);
570     res = pAddPortExA(NULL, 1, (LPBYTE) &pi, LocalPortA);
571     ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
572         "got %u with %u (expected '0' with ERROR_INVALID_PARAMETER)\n",
573         res, GetLastError());
574     if (res) DeletePortA(NULL, 0, tempfileA);
575 
576 
577     /*  level 2 is documented as supported for Printmonitors,
578         but that is not supported for "Local Port" (localspl.dll) and
579         AddPortEx fails with ERROR_INVALID_LEVEL */
580 
581     pi.pPortName = tempfileA;
582     pi.pMonitorName = LocalPortA;
583     pi.pDescription = winetest;
584     pi.fPortType = PORT_TYPE_WRITE;
585 
586     SetLastError(0xdeadbeef);
587     res = pAddPortExA(NULL, 2, (LPBYTE) &pi, LocalPortA);
588     ok( !res && (GetLastError() == ERROR_INVALID_LEVEL),
589         "got %u with %u (expected '0' with ERROR_INVALID_LEVEL)\n",
590         res, GetLastError());
591     if (res) DeletePortA(NULL, 0, tempfileA);
592 
593 
594     /* invalid levels */
595     SetLastError(0xdeadbeef);
596     res = pAddPortExA(NULL, 0, (LPBYTE) &pi, LocalPortA);
597     ok( !res && (GetLastError() == ERROR_INVALID_LEVEL),
598         "got %u with %u (expected '0' with ERROR_INVALID_LEVEL)\n",
599         res, GetLastError());
600 
601     SetLastError(0xdeadbeef);
602     res = pAddPortExA(NULL, 3, (LPBYTE) &pi, LocalPortA);
603     ok( !res && (GetLastError() == ERROR_INVALID_LEVEL),
604         "got %u with %u (expected '0' with ERROR_INVALID_LEVEL)\n",
605         res, GetLastError());
606 
607 
608     /* cleanup */
609     DeletePortA(NULL, 0, tempfileA);
610 
611 }
612 
613 /* ########################### */
614 
615 static void test_ConfigurePort(void)
616 {
617     DWORD   res;
618 
619 
620     SetLastError(0xdeadbeef);
621     res = ConfigurePortA(NULL, 0, NULL);
622     if (is_spooler_deactivated(res, GetLastError())) return;
623     /* NT: RPC_X_NULL_REF_POINTER, 9x: ERROR_INVALID_PARAMETER */
624     ok( !res && ((GetLastError() == RPC_X_NULL_REF_POINTER) ||
625                  (GetLastError() == ERROR_INVALID_PARAMETER)),
626         "returned %d with %d (expected '0' with ERROR_NOT_SUPPORTED or "
627         "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
628 
629     SetLastError(0xdeadbeef);
630     res = ConfigurePortA(NULL, 0, empty);
631     /* Allowed only for (Printer-)Administrators */
632     if (is_access_denied(res, GetLastError())) return;
633 
634     /* XP: ERROR_NOT_SUPPORTED, NT351 and 9x: ERROR_INVALID_PARAMETER */
635     ok( !res && ((GetLastError() == ERROR_NOT_SUPPORTED) ||
636                  (GetLastError() == ERROR_INVALID_PARAMETER)),
637         "returned %d with %d (expected '0' with ERROR_NOT_SUPPORTED or "
638         "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
639 
640 
641     SetLastError(0xdeadbeef);
642     res = ConfigurePortA(NULL, 0, does_not_exist);
643     /* XP: ERROR_NOT_SUPPORTED, NT351 and 9x: ERROR_INVALID_PARAMETER */
644     ok( !res && ((GetLastError() == ERROR_NOT_SUPPORTED) ||
645                  (GetLastError() == ERROR_INVALID_PARAMETER)),
646         "returned %d with %d (expected '0' with ERROR_NOT_SUPPORTED or "
647         "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
648 
649 
650     /*  Testing-Results:
651         - Case of Portnames is ignored
652         - Portname without ":" => NT: ERROR_NOT_SUPPORTED, 9x: Dialog comes up
653         - Empty Servername (LPT1:) => NT: ERROR_NOT_SUPPORTED, 9x: Dialog comes up
654 
655         - Port not present =>  9x: ERROR_INVALID_PARAMETER, NT:ERROR_NOT_SUPPORTED
656         - "FILE:" => 9x:Success, NT:ERROR_CANCELED
657         - Cancel ("Local Port") => ERROR_CANCELED
658         - Cancel ("Redirected Port") => Success
659     */
660     if (winetest_interactive > 0) {
661         SetLastError(0xdeadbeef);
662         res = ConfigurePortA(NULL, 0, portname_com1);
663         trace("'%s' returned %d with %d\n", portname_com1, res, GetLastError());
664 
665         SetLastError(0xdeadbeef);
666         res = ConfigurePortA(NULL, 0, portname_lpt1);
667         trace("'%s' returned %d with %d\n", portname_lpt1, res, GetLastError());
668 
669         SetLastError(0xdeadbeef);
670         res = ConfigurePortA(NULL, 0, portname_file);
671         trace("'%s' returned %d with %d\n", portname_file, res, GetLastError());
672     }
673 }
674 
675 /* ########################### */
676 
677 static void test_ClosePrinter(void)
678 {
679     HANDLE printer = 0;
680     BOOL res;
681 
682     /* NULL is handled */
683     SetLastError(0xdeadbeef);
684     res = ClosePrinter(NULL);
685     ok(!res && (GetLastError() == ERROR_INVALID_HANDLE),
686         "got %d with %d (expected FALSE with ERROR_INVALID_HANDLE)\n",
687         res, GetLastError());
688 
689     /* A random value as HANDLE is handled */
690     SetLastError(0xdeadbeef);
691     res = ClosePrinter( (void *) -1);
692     if (is_spooler_deactivated(res, GetLastError())) return;
693     ok(!res && (GetLastError() == ERROR_INVALID_HANDLE),
694         "got %d with %d (expected FALSE with ERROR_INVALID_HANDLE)\n",
695          res, GetLastError());
696 
697 
698     /* Normal use (The Spooler service is needed) */
699     SetLastError(0xdeadbeef);
700     res = OpenPrinterA(default_printer, &printer, NULL);
701     if (is_spooler_deactivated(res, GetLastError())) return;
702     if (res)
703     {
704         SetLastError(0xdeadbeef);
705         res = ClosePrinter(printer);
706         ok(res, "got %d with %d (expected TRUE)\n", res, GetLastError());
707 
708 
709         /* double free is handled */
710         SetLastError(0xdeadbeef);
711         res = ClosePrinter(printer);
712         ok(!res && (GetLastError() == ERROR_INVALID_HANDLE),
713             "got %d with %d (expected FALSE with ERROR_INVALID_HANDLE)\n",
714             res, GetLastError());
715 
716     }
717 }
718 
719 /* ########################### */
720 
721 static void test_DeleteMonitor(void)
722 {
723     MONITOR_INFO_2A         mi2a;
724     struct monitor_entry  * entry = NULL;
725     DWORD                   res;
726 
727 
728     entry = find_installed_monitor();
729 
730     if (!entry) {
731         skip("No usable Monitor found\n");
732         return;
733     }
734 
735     mi2a.pName = winetest;
736     mi2a.pEnvironment = entry->env;
737     mi2a.pDLLName = entry->dllname;
738 
739     /* Testing DeleteMonitor with real options */
740     AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
741 
742     SetLastError(MAGIC_DEAD);
743     res = DeleteMonitorA(NULL, entry->env, winetest);
744     ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError());
745 
746     /* Delete the Monitor twice */
747     SetLastError(MAGIC_DEAD);
748     res = DeleteMonitorA(NULL, entry->env, winetest);
749     /* NT: ERROR_UNKNOWN_PRINT_MONITOR (3000), 9x: ERROR_INVALID_PARAMETER (87) */
750     ok( !res &&
751         ((GetLastError() == ERROR_UNKNOWN_PRINT_MONITOR) ||
752         (GetLastError() == ERROR_INVALID_PARAMETER)),
753         "returned %d with %d (expected '0' with: ERROR_UNKNOWN_PRINT_MONITOR"
754         " or ERROR_INVALID_PARAMETER)\n", res, GetLastError());
755 
756     /* the environment */
757     AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
758     SetLastError(MAGIC_DEAD);
759     res = DeleteMonitorA(NULL, NULL, winetest);
760     ok(res, "returned %d with %d (expected '!=0')\n", res, GetLastError());
761 
762     AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
763     SetLastError(MAGIC_DEAD);
764     res = DeleteMonitorA(NULL, empty, winetest);
765     ok(res, "returned %d with %d (expected '!=0')\n", res, GetLastError());
766 
767     AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
768     SetLastError(MAGIC_DEAD);
769     res = DeleteMonitorA(NULL, invalid_env, winetest);
770     ok( res || GetLastError() == ERROR_INVALID_ENVIRONMENT /* Vista/W2K8 */,
771         "returned %d with %d\n", res, GetLastError());
772 
773     /* the monitor-name */
774     AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
775     SetLastError(MAGIC_DEAD);
776     res = DeleteMonitorA(NULL, entry->env, NULL);
777     /* NT: ERROR_INVALID_PARAMETER (87),  9x: ERROR_INVALID_NAME (123)*/
778     ok( !res &&
779         ((GetLastError() == ERROR_INVALID_PARAMETER) ||
780         (GetLastError() == ERROR_INVALID_NAME)),
781         "returned %d with %d (expected '0' with: ERROR_INVALID_PARAMETER or "
782         "ERROR_INVALID_NAME)\n", res, GetLastError());
783 
784     AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
785     SetLastError(MAGIC_DEAD);
786     res = DeleteMonitorA(NULL, entry->env, empty);
787     /* NT: ERROR_INVALID_PARAMETER (87),  9x: ERROR_INVALID_NAME (123)*/
788     ok( !res &&
789         ((GetLastError() == ERROR_INVALID_PARAMETER) ||
790         (GetLastError() == ERROR_INVALID_NAME)),
791         "returned %d with %d (expected '0' with: ERROR_INVALID_PARAMETER or "
792         "ERROR_INVALID_NAME)\n", res, GetLastError());
793 
794     AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
795     SetLastError(MAGIC_DEAD);
796     res = DeleteMonitorA(empty, entry->env, winetest);
797     ok(res, "returned %d with %d (expected '!=0')\n", res, GetLastError());
798 
799     /* cleanup */
800     DeleteMonitorA(NULL, entry->env, winetest);
801 }
802 
803 /* ########################### */
804 
805 static void test_DeletePort(void)
806 {
807     DWORD   res;
808 
809     SetLastError(0xdeadbeef);
810     res = DeletePortA(NULL, 0, NULL);
811     if (is_spooler_deactivated(res, GetLastError())) return;
812 
813     SetLastError(0xdeadbeef);
814     res = DeletePortA(NULL, 0, empty);
815     /* Allowed only for (Printer-)Administrators */
816     if (is_access_denied(res, GetLastError())) return;
817 
818     /* XP: ERROR_NOT_SUPPORTED, NT351 and 9x: ERROR_INVALID_PARAMETER */
819     ok( !res && ((GetLastError() == ERROR_NOT_SUPPORTED) ||
820                  (GetLastError() == ERROR_INVALID_PARAMETER)),
821         "returned %d with %d (expected '0' with ERROR_NOT_SUPPORTED or "
822         "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
823 
824 
825     SetLastError(0xdeadbeef);
826     res = DeletePortA(NULL, 0, does_not_exist);
827     /* XP: ERROR_NOT_SUPPORTED, NT351 and 9x: ERROR_INVALID_PARAMETER */
828     ok( !res && ((GetLastError() == ERROR_NOT_SUPPORTED) ||
829                  (GetLastError() == ERROR_INVALID_PARAMETER)),
830         "returned %d with %d (expected '0' with ERROR_NOT_SUPPORTED or "
831         "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
832 
833 }
834 
835 /* ########################### */
836 
837 static void test_EnumForms(LPSTR pName)
838 {
839     DWORD   res;
840     HANDLE  hprinter = 0;
841     LPBYTE  buffer;
842     DWORD   cbBuf;
843     DWORD   pcbNeeded;
844     DWORD   pcReturned;
845     DWORD   level;
846     UINT    i;
847     const char *formtype;
848     static const char * const formtypes[] = { "FORM_USER", "FORM_BUILTIN", "FORM_PRINTER", "FORM_flag_unknown" };
849 #define FORMTYPE_MAX 2
850     PFORM_INFO_1A pFI_1a;
851     PFORM_INFO_2A pFI_2a;
852 
853     res = OpenPrinterA(pName, &hprinter, NULL);
854     if (is_spooler_deactivated(res, GetLastError())) return;
855     if (!res || !hprinter)
856     {
857         /* opening the local Printserver is not supported on win9x */
858         if (pName) skip("Failed to open '%s' (not supported on win9x)\n", pName);
859         return;
860     }
861 
862     /* valid levels are 1 and 2 */
863     for(level = 0; level < 4; level++) {
864         cbBuf = 0xdeadbeef;
865         pcReturned = 0xdeadbeef;
866         SetLastError(0xdeadbeef);
867         res = EnumFormsA(hprinter, level, NULL, 0, &cbBuf, &pcReturned);
868 
869         /* EnumForms is not implemented on win9x */
870         if (!res && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) continue;
871 
872         /* EnumForms for the server is not implemented on all NT-versions */
873         if (!res && (GetLastError() == ERROR_INVALID_HANDLE) && !pName) continue;
874 
875         /* Level 2 for EnumForms is not supported on all systems */
876         if (!res && (GetLastError() == ERROR_INVALID_LEVEL) && (level == 2)) continue;
877 
878         /* use only a short test when testing an invalid level */
879         if(!level || (level > 2)) {
880             ok( (!res && (GetLastError() == ERROR_INVALID_LEVEL)) ||
881                 (res && (pcReturned == 0)),
882                 "(%d) returned %d with %d and 0x%08x (expected '0' with "
883                 "ERROR_INVALID_LEVEL or '!=0' and 0x0)\n",
884                 level, res, GetLastError(), pcReturned);
885             continue;
886         }
887 
888         ok((!res) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
889             "(%d) returned %d with %d (expected '0' with "
890             "ERROR_INSUFFICIENT_BUFFER)\n", level, res, GetLastError());
891 
892         buffer = HeapAlloc(GetProcessHeap(), 0, cbBuf *2);
893         if (buffer == NULL) continue;
894 
895         SetLastError(0xdeadbeef);
896         res = EnumFormsA(hprinter, level, buffer, cbBuf, &pcbNeeded, &pcReturned);
897         ok(res, "(%d) returned %d with %d (expected '!=0')\n",
898                 level, res, GetLastError());
899 
900         if (winetest_debug > 1) {
901             trace("dumping %d forms level %d\n", pcReturned, level);
902             pFI_1a = (PFORM_INFO_1A)buffer;
903             pFI_2a = (PFORM_INFO_2A)buffer;
904             for (i = 0; i < pcReturned; i++)
905             {
906                 /* first part is same in FORM_INFO_1 and FORM_INFO_2 */
907                 formtype = (pFI_1a->Flags <= FORMTYPE_MAX) ? formtypes[pFI_1a->Flags] : formtypes[3];
908                 trace("%u (%s): %.03fmm x %.03fmm, %s\n", i, pFI_1a->pName,
909                       (float)pFI_1a->Size.cx/1000, (float)pFI_1a->Size.cy/1000, formtype);
910 
911                 if (level == 1) pFI_1a ++;
912                 else {
913                     /* output additional FORM_INFO_2 fields */
914                     trace("\tkeyword=%s strtype=%u muidll=%s resid=%u dispname=%s langid=%u\n",
915                           pFI_2a->pKeyword, pFI_2a->StringType, pFI_2a->pMuiDll,
916                           pFI_2a->dwResourceId, pFI_2a->pDisplayName, pFI_2a->wLangId);
917 
918                     /* offset pointer pFI_1a by 1*sizeof(FORM_INFO_2A) Bytes */
919                     pFI_2a ++;
920                     pFI_1a = (PFORM_INFO_1A)pFI_2a;
921                 }
922             }
923         }
924 
925         SetLastError(0xdeadbeef);
926         res = EnumFormsA(hprinter, level, buffer, cbBuf+1, &pcbNeeded, &pcReturned);
927         ok( res, "(%d) returned %d with %d (expected '!=0')\n",
928             level, res, GetLastError());
929 
930         SetLastError(0xdeadbeef);
931         res = EnumFormsA(hprinter, level, buffer, cbBuf-1, &pcbNeeded, &pcReturned);
932         ok( !res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
933             "(%d) returned %d with %d (expected '0' with "
934             "ERROR_INSUFFICIENT_BUFFER)\n", level, res, GetLastError());
935 
936 
937         SetLastError(0xdeadbeef);
938         res = EnumFormsA(hprinter, level, NULL, cbBuf, &pcbNeeded, &pcReturned);
939         ok( !res && (GetLastError() == ERROR_INVALID_USER_BUFFER) ,
940             "(%d) returned %d with %d (expected '0' with "
941             "ERROR_INVALID_USER_BUFFER)\n", level, res, GetLastError());
942 
943 
944         SetLastError(0xdeadbeef);
945         res = EnumFormsA(hprinter, level, buffer, cbBuf, NULL, &pcReturned);
946         ok( !res && (GetLastError() == RPC_X_NULL_REF_POINTER) ,
947             "(%d) returned %d with %d (expected '0' with "
948             "RPC_X_NULL_REF_POINTER)\n", level, res, GetLastError());
949 
950         SetLastError(0xdeadbeef);
951         res = EnumFormsA(hprinter, level, buffer, cbBuf, &pcbNeeded, NULL);
952         ok( !res && (GetLastError() == RPC_X_NULL_REF_POINTER) ,
953             "(%d) returned %d with %d (expected '0' with "
954             "RPC_X_NULL_REF_POINTER)\n", level, res, GetLastError());
955 
956         SetLastError(0xdeadbeef);
957         res = EnumFormsA(0, level, buffer, cbBuf, &pcbNeeded, &pcReturned);
958         ok( !res && (GetLastError() == ERROR_INVALID_HANDLE) ,
959             "(%d) returned %d with %d (expected '0' with "
960             "ERROR_INVALID_HANDLE)\n", level, res, GetLastError());
961 
962         HeapFree(GetProcessHeap(), 0, buffer);
963     } /* for(level ... */
964 
965     ClosePrinter(hprinter);
966 }
967 
968 /* ########################### */
969 
970 static void test_EnumMonitors(void)
971 {
972     DWORD   res;
973     LPBYTE  buffer;
974     DWORD   cbBuf;
975     DWORD   pcbNeeded;
976     DWORD   pcReturned;
977     DWORD   level;
978 
979     /* valid levels are 1 and 2 */
980     for(level = 0; level < 4; level++) {
981         cbBuf = MAGIC_DEAD;
982         pcReturned = MAGIC_DEAD;
983         SetLastError(MAGIC_DEAD);
984         res = EnumMonitorsA(NULL, level, NULL, 0, &cbBuf, &pcReturned);
985         if (is_spooler_deactivated(res, GetLastError())) return;
986         /* not implemented yet in wine */
987         if (!res && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) continue;
988 
989 
990         /* use only a short test when testing an invalid level */
991         if(!level || (level > 2)) {
992             ok( (!res && (GetLastError() == ERROR_INVALID_LEVEL)) ||
993                 (res && (pcReturned == 0)),
994                 "(%d) returned %d with %d and 0x%08x (expected '0' with "
995                 "ERROR_INVALID_LEVEL or '!=0' and 0x0)\n",
996                 level, res, GetLastError(), pcReturned);
997             continue;
998         }
999 
1000         /* Level 2 is not supported on win9x */
1001         if (!res && (GetLastError() == ERROR_INVALID_LEVEL)) {
1002             skip("Level %d not supported\n", level);
1003             continue;
1004         }
1005 
1006         ok((!res) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1007             "(%d) returned %d with %d (expected '0' with "
1008             "ERROR_INSUFFICIENT_BUFFER)\n", level, res, GetLastError());
1009 
1010         if (!cbBuf) {
1011             skip("no valid buffer size returned\n");
1012             continue;
1013         }
1014 
1015         buffer = HeapAlloc(GetProcessHeap(), 0, cbBuf *2);
1016         if (buffer == NULL) continue;
1017 
1018         SetLastError(MAGIC_DEAD);
1019         pcbNeeded = MAGIC_DEAD;
1020         res = EnumMonitorsA(NULL, level, buffer, cbBuf, &pcbNeeded, &pcReturned);
1021         ok(res, "(%d) returned %d with %d (expected '!=0')\n",
1022                 level, res, GetLastError());
1023         ok(pcbNeeded == cbBuf, "(%d) returned %d (expected %d)\n",
1024                 level, pcbNeeded, cbBuf);
1025         /* We can validate the returned Data with the Registry here */
1026 
1027 
1028         SetLastError(MAGIC_DEAD);
1029         pcReturned = MAGIC_DEAD;
1030         pcbNeeded = MAGIC_DEAD;
1031         res = EnumMonitorsA(NULL, level, buffer, cbBuf+1, &pcbNeeded, &pcReturned);
1032         ok(res, "(%d) returned %d with %d (expected '!=0')\n", level,
1033                 res, GetLastError());
1034         ok(pcbNeeded == cbBuf, "(%d) returned %d (expected %d)\n", level,
1035                 pcbNeeded, cbBuf);
1036 
1037         SetLastError(MAGIC_DEAD);
1038         pcbNeeded = MAGIC_DEAD;
1039         res = EnumMonitorsA(NULL, level, buffer, cbBuf-1, &pcbNeeded, &pcReturned);
1040         ok( !res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1041             "(%d) returned %d with %d (expected '0' with "
1042             "ERROR_INSUFFICIENT_BUFFER)\n", level, res, GetLastError());
1043 
1044         ok(pcbNeeded == cbBuf, "(%d) returned %d (expected %d)\n", level,
1045                 pcbNeeded, cbBuf);
1046 
1047 /*
1048       Do not add the next test:
1049       w2k+:  RPC_X_NULL_REF_POINTER
1050       NT3.5: ERROR_INVALID_USER_BUFFER
1051       win9x: crash in winspool.drv
1052 
1053       res = EnumMonitorsA(NULL, level, NULL, cbBuf, &pcbNeeded, &pcReturned);
1054 */
1055 
1056         SetLastError(MAGIC_DEAD);
1057         pcbNeeded = MAGIC_DEAD;
1058         pcReturned = MAGIC_DEAD;
1059         res = EnumMonitorsA(NULL, level, buffer, cbBuf, NULL, &pcReturned);
1060         ok( res || GetLastError() == RPC_X_NULL_REF_POINTER,
1061             "(%d) returned %d with %d (expected '!=0' or '0' with "
1062             "RPC_X_NULL_REF_POINTER)\n", level, res, GetLastError());
1063 
1064         pcbNeeded = MAGIC_DEAD;
1065         pcReturned = MAGIC_DEAD;
1066         SetLastError(MAGIC_DEAD);
1067         res = EnumMonitorsA(NULL, level, buffer, cbBuf, &pcbNeeded, NULL);
1068         ok( res || GetLastError() == RPC_X_NULL_REF_POINTER,
1069             "(%d) returned %d with %d (expected '!=0' or '0' with "
1070             "RPC_X_NULL_REF_POINTER)\n", level, res, GetLastError());
1071 
1072         HeapFree(GetProcessHeap(), 0, buffer);
1073     } /* for(level ... */
1074 }
1075 
1076 /* ########################### */
1077 
1078 static void test_EnumPorts(void)
1079 {
1080     DWORD   res;
1081     DWORD   level;
1082     LPBYTE  buffer;
1083     DWORD   cbBuf;
1084     DWORD   pcbNeeded;
1085     DWORD   pcReturned;
1086 
1087     /* valid levels are 1 and 2 */
1088     for(level = 0; level < 4; level++) {
1089 
1090         cbBuf = 0xdeadbeef;
1091         pcReturned = 0xdeadbeef;
1092         SetLastError(0xdeadbeef);
1093         res = EnumPortsA(NULL, level, NULL, 0, &cbBuf, &pcReturned);
1094         if (is_spooler_deactivated(res, GetLastError())) return;
1095 
1096         /* use only a short test when testing an invalid level */
1097         if(!level || (level > 2)) {
1098             /* NT: ERROR_INVALID_LEVEL, 9x: success */
1099             ok( (!res && (GetLastError() == ERROR_INVALID_LEVEL)) ||
1100                 (res && (pcReturned == 0)),
1101                 "(%d) returned %d with %d and 0x%08x (expected '0' with "
1102                 "ERROR_INVALID_LEVEL or '!=0' and 0x0)\n",
1103                 level, res, GetLastError(), pcReturned);
1104             continue;
1105         }
1106 
1107 
1108         /* Level 2 is not supported on NT 3.x */
1109         if (!res && (GetLastError() == ERROR_INVALID_LEVEL)) {
1110             skip("Level %d not supported\n", level);
1111             continue;
1112         }
1113 
1114         ok((!res) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1115             "(%d) returned %d with %d (expected '0' with "
1116             "ERROR_INSUFFICIENT_BUFFER)\n", level, res, GetLastError());
1117 
1118         buffer = HeapAlloc(GetProcessHeap(), 0, cbBuf *2);
1119         if (buffer == NULL) continue;
1120 
1121         pcbNeeded = 0xdeadbeef;
1122         SetLastError(0xdeadbeef);
1123         res = EnumPortsA(NULL, level, buffer, cbBuf, &pcbNeeded, &pcReturned);
1124         ok(res, "(%d) returned %d with %d (expected '!=0')\n", level, res, GetLastError());
1125         ok(pcbNeeded == cbBuf, "(%d) returned %d (expected %d)\n", level, pcbNeeded, cbBuf);
1126         /* ToDo: Compare the returned Data with the Registry / "win.ini",[Ports] here */
1127 
1128         pcbNeeded = 0xdeadbeef;
1129         pcReturned = 0xdeadbeef;
1130         SetLastError(0xdeadbeef);
1131         res = EnumPortsA(NULL, level, buffer, cbBuf+1, &pcbNeeded, &pcReturned);
1132         ok(res, "(%d) returned %d with %d (expected '!=0')\n", level, res, GetLastError());
1133         ok(pcbNeeded == cbBuf, "(%d) returned %d (expected %d)\n", level, pcbNeeded, cbBuf);
1134 
1135         pcbNeeded = 0xdeadbeef;
1136         SetLastError(0xdeadbeef);
1137         res = EnumPortsA(NULL, level, buffer, cbBuf-1, &pcbNeeded, &pcReturned);
1138         ok( !res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1139             "(%d) returned %d with %d (expected '0' with "
1140             "ERROR_INSUFFICIENT_BUFFER)\n", level, res, GetLastError());
1141         ok(pcbNeeded == cbBuf, "(%d) returned %d (expected %d)\n", level, pcbNeeded, cbBuf);
1142 
1143         /*
1144           Do not add this test:
1145           res = EnumPortsA(NULL, level, NULL, cbBuf, &pcbNeeded, &pcReturned);
1146           w2k+:  RPC_X_NULL_REF_POINTER
1147           NT3.5: ERROR_INVALID_USER_BUFFER
1148           win9x: crash in winspool.drv
1149          */
1150 
1151         SetLastError(0xdeadbeef);
1152         res = EnumPortsA(NULL, level, buffer, cbBuf, NULL, &pcReturned);
1153         /* NT: RPC_X_NULL_REF_POINTER (1780),  9x: success */
1154         ok( (!res && (GetLastError() == RPC_X_NULL_REF_POINTER) ) ||
1155             ( res && (GetLastError() == ERROR_SUCCESS) ),
1156             "(%d) returned %d with %d (expected '0' with "
1157             "RPC_X_NULL_REF_POINTER or '!=0' with NO_ERROR)\n",
1158             level, res, GetLastError());
1159 
1160 
1161         SetLastError(0xdeadbeef);
1162         res = EnumPortsA(NULL, level, buffer, cbBuf, &pcbNeeded, NULL);
1163         /* NT: RPC_X_NULL_REF_POINTER (1780),  9x: success */
1164         ok( (!res && (GetLastError() == RPC_X_NULL_REF_POINTER) ) ||
1165             ( res && (GetLastError() == ERROR_SUCCESS) ),
1166             "(%d) returned %d with %d (expected '0' with "
1167             "RPC_X_NULL_REF_POINTER or '!=0' with NO_ERROR)\n",
1168             level, res, GetLastError());
1169 
1170         HeapFree(GetProcessHeap(), 0, buffer);
1171     }
1172 }
1173 
1174 /* ########################### */
1175 
1176 static void test_EnumPrinterDrivers(void)
1177 {
1178     static char env_all[] = "all";
1179 
1180     DWORD   res;
1181     LPBYTE  buffer;
1182     DWORD   cbBuf;
1183     DWORD   pcbNeeded;
1184     DWORD   pcReturned;
1185     DWORD   level;
1186 
1187     /* 1-3 for w95/w98/NT4; 1-3+6 for me; 1-6 for w2k/xp/2003; 1-6+8 for vista */
1188     for(level = 0; level < 10; level++) {
1189         cbBuf = 0xdeadbeef;
1190         pcReturned = 0xdeadbeef;
1191         SetLastError(0xdeadbeef);
1192         res = EnumPrinterDriversA(NULL, NULL, level, NULL, 0, &cbBuf, &pcReturned);
1193         if (is_spooler_deactivated(res, GetLastError())) return;
1194 
1195         /* use only a short test when testing an invalid level */
1196         if(!level || (level == 7) || (level > 8)) {
1197 
1198             ok( (!res && (GetLastError() == ERROR_INVALID_LEVEL)) ||
1199                 (res && (pcReturned == 0)),
1200                 "(%d) got %u with %u and 0x%x "
1201                 "(expected '0' with ERROR_INVALID_LEVEL or '!=0' and 0x0)\n",
1202                 level, res, GetLastError(), pcReturned);
1203             continue;
1204         }
1205 
1206         /* some levels are not supported on all windows versions */
1207         if (!res && (GetLastError() == ERROR_INVALID_LEVEL)) {
1208             skip("Level %d not supported\n", level);
1209             continue;
1210         }
1211 
1212         ok( ((!res) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) ||
1213             (res && (default_printer == NULL)),
1214             "(%u) got %u with %u for %s (expected '0' with "
1215             "ERROR_INSUFFICIENT_BUFFER or '!= 0' without a printer)\n",
1216             level, res, GetLastError(), default_printer);
1217 
1218         if (!cbBuf) {
1219             skip("no valid buffer size returned\n");
1220             continue;
1221         }
1222 
1223         /* EnumPrinterDriversA returns the same number of bytes as EnumPrinterDriversW */
1224         if (!on_win9x && pEnumPrinterDriversW)
1225         {
1226             DWORD double_needed;
1227             DWORD double_returned;
1228             pEnumPrinterDriversW(NULL, NULL, level, NULL, 0, &double_needed, &double_returned);
1229             ok(double_needed == cbBuf, "level %d: EnumPrinterDriversA returned different size %d than EnumPrinterDriversW (%d)\n", level, cbBuf, double_needed);
1230         }
1231 
1232         buffer = HeapAlloc(GetProcessHeap(), 0, cbBuf + 4);
1233         if (buffer == NULL) continue;
1234 
1235         SetLastError(0xdeadbeef);
1236         pcbNeeded = 0xdeadbeef;
1237         res = EnumPrinterDriversA(NULL, NULL, level, buffer, cbBuf, &pcbNeeded, &pcReturned);
1238         ok(res, "(%u) got %u with %u (expected '!=0')\n", level, res, GetLastError());
1239         ok(pcbNeeded == cbBuf, "(%d) returned %d (expected %d)\n", level, pcbNeeded, cbBuf);
1240 
1241         /* validate the returned data here */
1242         if (level > 1) {
1243             LPDRIVER_INFO_2A di = (LPDRIVER_INFO_2A) buffer;
1244 
1245             ok( strrchr(di->pDriverPath, '\\') != NULL,
1246                 "(%u) got %s for %s (expected a full path)\n",
1247                 level, di->pDriverPath, di->pName);
1248 
1249         }
1250 
1251         SetLastError(0xdeadbeef);
1252         pcReturned = 0xdeadbeef;
1253         pcbNeeded = 0xdeadbeef;
1254         res = EnumPrinterDriversA(NULL, NULL, level, buffer, cbBuf+1, &pcbNeeded, &pcReturned);
1255         ok(res, "(%u) got %u with %u (expected '!=0')\n", level, res, GetLastError());
1256         ok(pcbNeeded == cbBuf, "(%u) returned %u (expected %u)\n", level, pcbNeeded, cbBuf);
1257 
1258         SetLastError(0xdeadbeef);
1259         pcbNeeded = 0xdeadbeef;
1260         res = EnumPrinterDriversA(NULL, NULL, level, buffer, cbBuf-1, &pcbNeeded, &pcReturned);
1261         ok( !res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1262             "(%u) got %u with %u (expected '0' with ERROR_INSUFFICIENT_BUFFER)\n",
1263             level, res, GetLastError());
1264         ok(pcbNeeded == cbBuf, "(%u) returned %u (expected %u)\n", level, pcbNeeded, cbBuf);
1265 
1266 /*
1267       Do not add the next test:
1268       NT: ERROR_INVALID_USER_BUFFER
1269       win9x: crash or 100% CPU
1270 
1271       res = EnumPrinterDriversA(NULL, NULL, level, NULL, cbBuf, &pcbNeeded, &pcReturned);
1272 */
1273 
1274         SetLastError(0xdeadbeef);
1275         pcbNeeded = 0xdeadbeef;
1276         pcReturned = 0xdeadbeef;
1277         res = EnumPrinterDriversA(NULL, NULL, level, buffer, cbBuf, NULL, &pcReturned);
1278         ok( res || GetLastError() == RPC_X_NULL_REF_POINTER,
1279             "(%u) got %u with %u (expected '!=0' or '0' with "
1280             "RPC_X_NULL_REF_POINTER)\n", level, res, GetLastError());
1281 
1282         pcbNeeded = 0xdeadbeef;
1283         pcReturned = 0xdeadbeef;
1284         SetLastError(0xdeadbeef);
1285         res = EnumPrinterDriversA(NULL, NULL, level, buffer, cbBuf, &pcbNeeded, NULL);
1286         ok( res || GetLastError() == RPC_X_NULL_REF_POINTER,
1287             "(%u) got %u with %u (expected '!=0' or '0' with "
1288             "RPC_X_NULL_REF_POINTER)\n", level, res, GetLastError());
1289 
1290         HeapFree(GetProcessHeap(), 0, buffer);
1291     } /* for(level ... */
1292 
1293     pcbNeeded = 0;
1294     pcReturned = 0;
1295     SetLastError(0xdeadbeef);
1296     res = EnumPrinterDriversA(NULL, env_all, 1, NULL, 0, &pcbNeeded, &pcReturned);
1297     if (res)
1298     {
1299         skip("no printer drivers found\n");
1300         return;
1301     }
1302     if (GetLastError() == ERROR_INVALID_ENVIRONMENT)
1303     {
1304         win_skip("NT4 and below don't support the 'all' environment value\n");
1305         return;
1306     }
1307     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "unexpected error %u\n", GetLastError());
1308 
1309     buffer = HeapAlloc(GetProcessHeap(), 0, pcbNeeded);
1310     res = EnumPrinterDriversA(NULL, env_all, 1, buffer, pcbNeeded, &pcbNeeded, &pcReturned);
1311     ok(res, "EnumPrinterDriversA failed %u\n", GetLastError());
1312     if (res && pcReturned > 0)
1313     {
1314         DRIVER_INFO_1A *di_1 = (DRIVER_INFO_1A *)buffer;
1315         ok((LPBYTE) di_1->pName == NULL || (LPBYTE) di_1->pName < buffer ||
1316             (LPBYTE) di_1->pName >= (LPBYTE)(di_1 + pcReturned),
1317             "Driver Information not in sequence; pName %p, top of data %p\n",
1318             di_1->pName, di_1 + pcReturned);
1319     }
1320 
1321     HeapFree(GetProcessHeap(), 0, buffer);
1322 }
1323 
1324 /* ########################### */
1325 
1326 static void test_EnumPrintProcessors(void)
1327 {
1328     DWORD   res;
1329     LPBYTE  buffer;
1330     DWORD   cbBuf;
1331     DWORD   pcbNeeded;
1332     DWORD   pcReturned;
1333 
1334 
1335     cbBuf = 0xdeadbeef;
1336     pcReturned = 0xdeadbeef;
1337     SetLastError(0xdeadbeef);
1338     res = EnumPrintProcessorsA(NULL, NULL, 1, NULL, 0, &cbBuf, &pcReturned);
1339     if (is_spooler_deactivated(res, GetLastError())) return;
1340 
1341     if (res && !cbBuf) {
1342         skip("No Printprocessor installed\n");
1343         return;
1344     }
1345 
1346     ok((!res) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1347         "got %u with %u (expected '0' with ERROR_INSUFFICIENT_BUFFER)\n",
1348         res, GetLastError());
1349 
1350     buffer = HeapAlloc(GetProcessHeap(), 0, cbBuf + 4);
1351     if (buffer == NULL)
1352         return;
1353 
1354     SetLastError(0xdeadbeef);
1355     pcbNeeded = 0xdeadbeef;
1356     res = EnumPrintProcessorsA(NULL, NULL, 1, buffer, cbBuf, &pcbNeeded, &pcReturned);
1357     ok(res, "got %u with %u (expected '!=0')\n", res, GetLastError());
1358     /* validate the returned data here. */
1359 
1360 
1361     SetLastError(0xdeadbeef);
1362     pcReturned = 0xdeadbeef;
1363     pcbNeeded = 0xdeadbeef;
1364     res = EnumPrintProcessorsA(NULL, NULL, 1, buffer, cbBuf+1, &pcbNeeded, &pcReturned);
1365     ok(res, "got %u with %u (expected '!=0')\n", res, GetLastError());
1366 
1367     SetLastError(0xdeadbeef);
1368     pcbNeeded = 0xdeadbeef;
1369     res = EnumPrintProcessorsA(NULL, NULL, 1, buffer, cbBuf-1, &pcbNeeded, &pcReturned);
1370     ok( !res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1371         "got %u with %u (expected '0' with ERROR_INSUFFICIENT_BUFFER)\n",
1372         res, GetLastError());
1373 
1374     /* only level 1 is valid */
1375     if (0) {
1376         /* both tests crash on win98se */
1377         SetLastError(0xdeadbeef);
1378         pcbNeeded = 0xdeadbeef;
1379         pcReturned = 0xdeadbeef;
1380         res = EnumPrintProcessorsA(NULL, NULL, 0, buffer, cbBuf, &pcbNeeded, &pcReturned);
1381         ok( !res && (GetLastError() == ERROR_INVALID_LEVEL),
1382             "got %u with %u (expected '0' with ERROR_INVALID_LEVEL)\n",
1383             res, GetLastError());
1384 
1385         SetLastError(0xdeadbeef);
1386         pcbNeeded = 0xdeadbeef;
1387         res = EnumPrintProcessorsA(NULL, NULL, 2, buffer, cbBuf, &pcbNeeded, &pcReturned);
1388         ok( !res && (GetLastError() == ERROR_INVALID_LEVEL),
1389             "got %u with %u (expected '0' with ERROR_INVALID_LEVEL)\n",
1390             res, GetLastError());
1391     }
1392 
1393     /* an empty environment is ignored */
1394     SetLastError(0xdeadbeef);
1395     pcbNeeded = 0xdeadbeef;
1396     res = EnumPrintProcessorsA(NULL, empty, 1, buffer, cbBuf, &pcbNeeded, &pcReturned);
1397     ok(res, "got %u with %u (expected '!=0')\n", res, GetLastError());
1398 
1399     /* the environment is checked */
1400     SetLastError(0xdeadbeef);
1401     pcbNeeded = 0xdeadbeef;
1402     res = EnumPrintProcessorsA(NULL, invalid_env, 1, buffer, cbBuf, &pcbNeeded, &pcReturned);
1403     /* NT5: ERROR_INVALID_ENVIRONMENT, NT4: res != 0, 9x: ERROR_INVALID_PARAMETER */
1404     ok( broken(res) || /* NT4 */
1405         (GetLastError() == ERROR_INVALID_ENVIRONMENT) ||
1406         (GetLastError() == ERROR_INVALID_PARAMETER),
1407         "got %u with %u (expected '0' with ERROR_INVALID_ENVIRONMENT or "
1408         "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
1409 
1410 
1411     /* failure-Codes for NULL */
1412     if (0) {
1413         /* this test crashes on win98se */
1414         SetLastError(0xdeadbeef);
1415         pcbNeeded = 0xdeadbeef;
1416         pcReturned = 0xdeadbeef;
1417         res = EnumPrintProcessorsA(NULL, NULL, 1, NULL, cbBuf, &pcbNeeded, &pcReturned);
1418         ok( !res && (GetLastError() == ERROR_INVALID_USER_BUFFER) ,
1419             "got %u with %u (expected '0' with ERROR_INVALID_USER_BUFFER)\n",
1420             res, GetLastError());
1421     }
1422 
1423     SetLastError(0xdeadbeef);
1424     pcbNeeded = 0xdeadbeef;
1425     pcReturned = 0xdeadbeef;
1426     res = EnumPrintProcessorsA(NULL, NULL, 1, buffer, cbBuf, NULL, &pcReturned);
1427     /* the NULL is ignored on win9x */
1428     ok( broken(res) || (!res && (GetLastError() == RPC_X_NULL_REF_POINTER)),
1429         "got %u with %u (expected '0' with RPC_X_NULL_REF_POINTER)\n",
1430         res, GetLastError());
1431 
1432     pcbNeeded = 0xdeadbeef;
1433     pcReturned = 0xdeadbeef;
1434     SetLastError(0xdeadbeef);
1435     res = EnumPrintProcessorsA(NULL, NULL, 1, buffer, cbBuf, &pcbNeeded, NULL);
1436     /* the NULL is ignored on win9x */
1437     ok( broken(res) || (!res && (GetLastError() == RPC_X_NULL_REF_POINTER)),
1438         "got %u with %u (expected '0' with RPC_X_NULL_REF_POINTER)\n",
1439         res, GetLastError());
1440 
1441     HeapFree(GetProcessHeap(), 0, buffer);
1442 
1443 }
1444 
1445 /* ########################### */
1446 
1447 static void test_GetDefaultPrinter(void)
1448 {
1449     BOOL    retval;
1450     DWORD   exact = DEFAULT_PRINTER_SIZE;
1451     DWORD   size;
1452     char    buffer[DEFAULT_PRINTER_SIZE];
1453 
1454     if (!pGetDefaultPrinterA)  return;
1455 	/* only supported on NT like OSes starting with win2k */
1456 
1457     SetLastError(ERROR_SUCCESS);
1458     retval = pGetDefaultPrinterA(buffer, &exact);
1459     if (!retval || !exact || !strlen(buffer) ||
1460 	(ERROR_SUCCESS != GetLastError())) {
1461 	if ((ERROR_FILE_NOT_FOUND == GetLastError()) ||
1462 	    (ERROR_INVALID_NAME == GetLastError()))
1463 	    trace("this test requires a default printer to be set\n");
1464 	else {
1465 		ok( 0, "function call GetDefaultPrinterA failed unexpected!\n"
1466 		"function returned %s\n"
1467 		"last error 0x%08x\n"
1468 		"returned buffer size 0x%08x\n"
1469 		"returned buffer content %s\n",
1470 		retval ? "true" : "false", GetLastError(), exact, buffer);
1471 	}
1472 	return;
1473     }
1474     SetLastError(ERROR_SUCCESS);
1475     retval = pGetDefaultPrinterA(NULL, NULL);
1476     ok( !retval, "function result wrong! False expected\n");
1477     ok( ERROR_INVALID_PARAMETER == GetLastError(),
1478 	"Last error wrong! ERROR_INVALID_PARAMETER expected, got 0x%08x\n",
1479 	GetLastError());
1480 
1481     SetLastError(ERROR_SUCCESS);
1482     retval = pGetDefaultPrinterA(buffer, NULL);
1483     ok( !retval, "function result wrong! False expected\n");
1484     ok( ERROR_INVALID_PARAMETER == GetLastError(),
1485 	"Last error wrong! ERROR_INVALID_PARAMETER expected, got 0x%08x\n",
1486 	GetLastError());
1487 
1488     SetLastError(ERROR_SUCCESS);
1489     size = 0;
1490     retval = pGetDefaultPrinterA(NULL, &size);
1491     ok( !retval, "function result wrong! False expected\n");
1492     ok( ERROR_INSUFFICIENT_BUFFER == GetLastError(),
1493 	"Last error wrong! ERROR_INSUFFICIENT_BUFFER expected, got 0x%08x\n",
1494 	GetLastError());
1495     ok( size == exact, "Parameter size wrong! %d expected got %d\n",
1496 	exact, size);
1497 
1498     SetLastError(ERROR_SUCCESS);
1499     size = DEFAULT_PRINTER_SIZE;
1500     retval = pGetDefaultPrinterA(NULL, &size);
1501     ok( !retval, "function result wrong! False expected\n");
1502     ok( ERROR_INSUFFICIENT_BUFFER == GetLastError(),
1503 	"Last error wrong! ERROR_INSUFFICIENT_BUFFER expected, got 0x%08x\n",
1504 	GetLastError());
1505     ok( size == exact, "Parameter size wrong! %d expected got %d\n",
1506 	exact, size);
1507 
1508     size = 0;
1509     retval = pGetDefaultPrinterA(buffer, &size);
1510     ok( !retval, "function result wrong! False expected\n");
1511     ok( ERROR_INSUFFICIENT_BUFFER == GetLastError(),
1512 	"Last error wrong! ERROR_INSUFFICIENT_BUFFER expected, got 0x%08x\n",
1513 	GetLastError());
1514     ok( size == exact, "Parameter size wrong! %d expected got %d\n",
1515 	exact, size);
1516 
1517     size = exact;
1518     retval = pGetDefaultPrinterA(buffer, &size);
1519     ok( retval, "function result wrong! True expected\n");
1520     ok( size == exact, "Parameter size wrong! %d expected got %d\n",
1521 	exact, size);
1522 }
1523 
1524 static void test_GetPrinterDriverDirectory(void)
1525 {
1526     LPBYTE      buffer = NULL;
1527     DWORD       cbBuf = 0, pcbNeeded = 0;
1528     BOOL        res;
1529 
1530 
1531     SetLastError(MAGIC_DEAD);
1532     res = GetPrinterDriverDirectoryA( NULL, NULL, 1, NULL, 0, &cbBuf);
1533     if (is_spooler_deactivated(res, GetLastError())) return;
1534 
1535     trace("first call returned 0x%04x, with %d: buffer size 0x%08x\n",
1536           res, GetLastError(), cbBuf);
1537 
1538     ok((res == 0) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1539         "returned %d with lasterror=%d (expected '0' with "
1540         "ERROR_INSUFFICIENT_BUFFER)\n", res, GetLastError());
1541 
1542     if (!cbBuf) {
1543         skip("no valid buffer size returned\n");
1544         return;
1545     }
1546 
1547     buffer = HeapAlloc( GetProcessHeap(), 0, cbBuf*2);
1548     if (buffer == NULL)  return ;
1549 
1550     res = GetPrinterDriverDirectoryA(NULL, NULL, 1, buffer, cbBuf, &pcbNeeded);
1551     ok( res, "expected result != 0, got %d\n", res);
1552     ok( cbBuf == pcbNeeded, "pcbNeeded set to %d instead of %d\n",
1553                             pcbNeeded, cbBuf);
1554 
1555     res = GetPrinterDriverDirectoryA(NULL, NULL, 1, buffer, cbBuf*2, &pcbNeeded);
1556     ok( res, "expected result != 0, got %d\n", res);
1557     ok( cbBuf == pcbNeeded, "pcbNeeded set to %d instead of %d\n",
1558                             pcbNeeded, cbBuf);
1559 
1560     SetLastError(MAGIC_DEAD);
1561     res = GetPrinterDriverDirectoryA( NULL, NULL, 1, buffer, cbBuf-1, &pcbNeeded);
1562     ok( !res , "expected result == 0, got %d\n", res);
1563     ok( cbBuf == pcbNeeded, "pcbNeeded set to %d instead of %d\n",
1564                             pcbNeeded, cbBuf);
1565 
1566     ok( ERROR_INSUFFICIENT_BUFFER == GetLastError(),
1567         "last error set to %d instead of ERROR_INSUFFICIENT_BUFFER\n",
1568         GetLastError());
1569 
1570 /*
1571     Do not add the next test:
1572     XPsp2: crash in this app, when the spooler is not running
1573     NT3.5: ERROR_INVALID_USER_BUFFER
1574     win9x: ERROR_INVALID_PARAMETER
1575 
1576     pcbNeeded = MAGIC_DEAD;
1577     SetLastError(MAGIC_DEAD);
1578     res = GetPrinterDriverDirectoryA( NULL, NULL, 1, NULL, cbBuf, &pcbNeeded);
1579 */
1580 
1581     SetLastError(MAGIC_DEAD);
1582     res = GetPrinterDriverDirectoryA( NULL, NULL, 1, buffer, cbBuf, NULL);
1583     /* w7 with deactivated spooler: ERROR_INVALID_PARAMETER,
1584        NT: RPC_X_NULL_REF_POINTER  */
1585     ok( res || (GetLastError() == RPC_X_NULL_REF_POINTER) ||
1586                (GetLastError() == ERROR_INVALID_PARAMETER),
1587         "returned %d with %d (expected '!=0' or '0' with RPC_X_NULL_REF_POINTER "
1588         "or '0' with ERROR_INVALID_PARAMETER)\n", res, GetLastError());
1589 
1590     SetLastError(MAGIC_DEAD);
1591     res = GetPrinterDriverDirectoryA( NULL, NULL, 1, NULL, cbBuf, NULL);
1592     /* w7 with deactivated spooler: ERROR_INVALID_PARAMETER,
1593        NT: RPC_X_NULL_REF_POINTER  */
1594     ok( res || (GetLastError() == RPC_X_NULL_REF_POINTER) ||
1595                (GetLastError() == ERROR_INVALID_PARAMETER),
1596         "returned %d with %d (expected '!=0' or '0' with RPC_X_NULL_REF_POINTER "
1597         "or '0' with ERROR_INVALID_PARAMETER)\n", res, GetLastError());
1598 
1599     /* with a valid buffer, but level is too large */
1600     buffer[0] = '\0';
1601     SetLastError(MAGIC_DEAD);
1602     res = GetPrinterDriverDirectoryA(NULL, NULL, 2, buffer, cbBuf, &pcbNeeded);
1603 
1604     /* Level not checked in win9x and wine:*/
1605     if((res != FALSE) && buffer[0])
1606     {
1607         trace("Level '2' not checked '%s'\n", buffer);
1608     }
1609     else
1610     {
1611         ok( !res && (GetLastError() == ERROR_INVALID_LEVEL),
1612         "returned %d with lasterror=%d (expected '0' with "
1613         "ERROR_INVALID_LEVEL)\n", res, GetLastError());
1614     }
1615 
1616     /* printing environments are case insensitive */
1617     /* "Windows 4.0" is valid for win9x and NT */
1618     buffer[0] = '\0';
1619     SetLastError(MAGIC_DEAD);
1620     res = GetPrinterDriverDirectoryA(NULL, env_win9x_case, 1,
1621                                         buffer, cbBuf*2, &pcbNeeded);
1622 
1623     if(!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
1624         cbBuf = pcbNeeded;
1625         buffer = HeapReAlloc(GetProcessHeap(), 0, buffer, cbBuf*2);
1626         if (buffer == NULL)  return ;
1627 
1628         SetLastError(MAGIC_DEAD);
1629         res = GetPrinterDriverDirectoryA(NULL, env_win9x_case, 1,
1630                                         buffer, cbBuf*2, &pcbNeeded);
1631     }
1632 
1633     ok(res && buffer[0], "returned %d with "
1634         "lasterror=%d and len=%d (expected '1' with 'len > 0')\n",
1635         res, GetLastError(), lstrlenA((char *)buffer));
1636 
1637     buffer[0] = '\0';
1638     SetLastError(MAGIC_DEAD);
1639     res = GetPrinterDriverDirectoryA(NULL, env_x86, 1,
1640                                         buffer, cbBuf*2, &pcbNeeded);
1641 
1642     if(!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
1643         cbBuf = pcbNeeded;
1644         buffer = HeapReAlloc(GetProcessHeap(), 0, buffer, cbBuf*2);
1645         if (buffer == NULL)  return ;
1646 
1647         buffer[0] = '\0';
1648         SetLastError(MAGIC_DEAD);
1649         res = GetPrinterDriverDirectoryA(NULL, env_x86, 1,
1650                                         buffer, cbBuf*2, &pcbNeeded);
1651     }
1652 
1653     /* "Windows NT x86" is invalid for win9x */
1654     ok( (res && buffer[0]) ||
1655         (!res && (GetLastError() == ERROR_INVALID_ENVIRONMENT)),
1656         "returned %d with lasterror=%d and len=%d (expected '!= 0' with "
1657         "'len > 0' or '0' with ERROR_INVALID_ENVIRONMENT)\n",
1658         res, GetLastError(), lstrlenA((char *)buffer));
1659 
1660     /* A setup program (PDFCreator_0.8.0) use empty strings */
1661     SetLastError(MAGIC_DEAD);
1662     res = GetPrinterDriverDirectoryA(empty, empty, 1, buffer, cbBuf*2, &pcbNeeded);
1663     ok(res, "returned %d with %d (expected '!=0')\n", res, GetLastError() );
1664 
1665     SetLastError(MAGIC_DEAD);
1666     res = GetPrinterDriverDirectoryA(NULL, empty, 1, buffer, cbBuf*2, &pcbNeeded);
1667     ok(res, "returned %d with %d (expected '!=0')\n", res, GetLastError() );
1668 
1669     SetLastError(MAGIC_DEAD);
1670     res = GetPrinterDriverDirectoryA(empty, NULL, 1, buffer, cbBuf*2, &pcbNeeded);
1671     ok(res, "returned %d with %d (expected '!=0')\n", res, GetLastError() );
1672 
1673     HeapFree( GetProcessHeap(), 0, buffer);
1674 }
1675 
1676 /* ##### */
1677 
1678 static void test_GetPrintProcessorDirectory(void)
1679 {
1680     LPBYTE      buffer = NULL;
1681     DWORD       cbBuf = 0;
1682     DWORD       pcbNeeded = 0;
1683     BOOL        res;
1684 
1685 
1686     SetLastError(0xdeadbeef);
1687     res = GetPrintProcessorDirectoryA(NULL, NULL, 1, NULL, 0, &cbBuf);
1688     if (is_spooler_deactivated(res, GetLastError())) return;
1689 
1690     ok( !res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1691         "returned %d with %d (expected '0' with ERROR_INSUFFICIENT_BUFFER)\n",
1692         res, GetLastError());
1693 
1694     buffer = HeapAlloc(GetProcessHeap(), 0, cbBuf*2);
1695     if(buffer == NULL)  return;
1696 
1697     buffer[0] = '\0';
1698     SetLastError(0xdeadbeef);
1699     res = GetPrintProcessorDirectoryA(NULL, NULL, 1, buffer, cbBuf, &pcbNeeded);
1700     ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError());
1701 
1702     SetLastError(0xdeadbeef);
1703     buffer[0] = '\0';
1704     res = GetPrintProcessorDirectoryA(NULL, NULL, 1, buffer, cbBuf*2, &pcbNeeded);
1705     ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError());
1706 
1707     /* Buffer too small */
1708     buffer[0] = '\0';
1709     SetLastError(0xdeadbeef);
1710     res = GetPrintProcessorDirectoryA( NULL, NULL, 1, buffer, cbBuf-1, &pcbNeeded);
1711     ok( !res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1712         "returned %d with %d (expected '0' with ERROR_INSUFFICIENT_BUFFER)\n",
1713         res, GetLastError());
1714 
1715     if (0)
1716     {
1717     /* XPsp2: the program will crash here, when the spooler is not running  */
1718     /*        GetPrinterDriverDirectory has the same bug */
1719     pcbNeeded = 0;
1720     SetLastError(0xdeadbeef);
1721     res = GetPrintProcessorDirectoryA( NULL, NULL, 1, NULL, cbBuf, &pcbNeeded);
1722     /* NT: ERROR_INVALID_USER_BUFFER, 9x: res != 0  */
1723     ok( (!res && (GetLastError() == ERROR_INVALID_USER_BUFFER)) ||
1724         broken(res),
1725         "returned %d with %d (expected '0' with ERROR_INVALID_USER_BUFFER)\n",
1726         res, GetLastError());
1727     }
1728 
1729     buffer[0] = '\0';
1730     SetLastError(0xdeadbeef);
1731     res = GetPrintProcessorDirectoryA( NULL, NULL, 1, buffer, cbBuf, NULL);
1732     /* w7 with deactivated spooler: ERROR_INVALID_PARAMETER,
1733        NT: RPC_X_NULL_REF_POINTER, 9x: res != 0  */
1734     ok( !res && ((GetLastError() == RPC_X_NULL_REF_POINTER) ||
1735                  (GetLastError() == ERROR_INVALID_PARAMETER)),
1736         "returned %d with %d (expected '0' with RPC_X_NULL_REF_POINTER "
1737         "or with ERROR_INVALID_PARAMETER)\n", res, GetLastError());
1738 
1739     buffer[0] = '\0';
1740     SetLastError(0xdeadbeef);
1741     res = GetPrintProcessorDirectoryA( NULL, NULL, 1, NULL, cbBuf, NULL);
1742     /* w7 with deactivated spooler: ERROR_INVALID_PARAMETER,
1743        NT: RPC_X_NULL_REF_POINTER, 9x: res != 0  */
1744     ok( !res && ((GetLastError() == RPC_X_NULL_REF_POINTER) ||
1745                  (GetLastError() == ERROR_INVALID_PARAMETER)),
1746         "returned %d with %d (expected '0' with RPC_X_NULL_REF_POINTER "
1747         "or with ERROR_INVALID_PARAMETER)\n", res, GetLastError());
1748 
1749     /* with a valid buffer, but level is invalid */
1750     buffer[0] = '\0';
1751     SetLastError(0xdeadbeef);
1752     res = GetPrintProcessorDirectoryA(NULL, NULL, 0, buffer, cbBuf, &pcbNeeded);
1753     /* Level is ignored in win9x*/
1754     ok( (!res && (GetLastError() == ERROR_INVALID_LEVEL)) ||
1755         broken(res && buffer[0]),
1756         "returned %d with %d (expected '0' with ERROR_INVALID_LEVEL)\n",
1757         res, GetLastError());
1758 
1759     buffer[0] = '\0';
1760     SetLastError(0xdeadbeef);
1761     res = GetPrintProcessorDirectoryA(NULL, NULL, 2, buffer, cbBuf, &pcbNeeded);
1762     /* Level is ignored on win9x*/
1763     ok( (!res && (GetLastError() == ERROR_INVALID_LEVEL)) ||
1764         broken(res && buffer[0]),
1765         "returned %d with %d (expected '0' with ERROR_INVALID_LEVEL)\n",
1766         res, GetLastError());
1767 
1768     /* Empty environment is the same as the default environment */
1769     buffer[0] = '\0';
1770     SetLastError(0xdeadbeef);
1771     res = GetPrintProcessorDirectoryA(NULL, empty, 1, buffer, cbBuf*2, &pcbNeeded);
1772     ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError());
1773 
1774     /* "Windows 4.0" is valid for win9x and NT */
1775     buffer[0] = '\0';
1776     SetLastError(0xdeadbeef);
1777     res = GetPrintProcessorDirectoryA(NULL, env_win9x_case, 1, buffer, cbBuf*2, &pcbNeeded);
1778     ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError());
1779 
1780 
1781     /* "Windows NT x86" is invalid for win9x */
1782     buffer[0] = '\0';
1783     SetLastError(0xdeadbeef);
1784     res = GetPrintProcessorDirectoryA(NULL, env_x86, 1, buffer, cbBuf*2, &pcbNeeded);
1785     ok( res || (GetLastError() == ERROR_INVALID_ENVIRONMENT),
1786         "returned %d with %d (expected '!= 0' or '0' with "
1787         "ERROR_INVALID_ENVIRONMENT)\n", res, GetLastError());
1788 
1789     /* invalid on all systems */
1790     buffer[0] = '\0';
1791     SetLastError(0xdeadbeef);
1792     res = GetPrintProcessorDirectoryA(NULL, invalid_env, 1, buffer, cbBuf*2, &pcbNeeded);
1793     ok( !res && (GetLastError() == ERROR_INVALID_ENVIRONMENT),
1794         "returned %d with %d (expected '0' with ERROR_INVALID_ENVIRONMENT)\n",
1795         res, GetLastError());
1796 
1797     /* Empty servername is the same as the local computer */
1798     buffer[0] = '\0';
1799     SetLastError(0xdeadbeef);
1800     res = GetPrintProcessorDirectoryA(empty, NULL, 1, buffer, cbBuf*2, &pcbNeeded);
1801     ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError());
1802 
1803     /* invalid on all systems */
1804     buffer[0] = '\0';
1805     SetLastError(0xdeadbeef);
1806     res = GetPrintProcessorDirectoryA(server_does_not_exist, NULL, 1, buffer, cbBuf*2, &pcbNeeded);
1807     ok( !res, "expected failure\n");
1808     ok( GetLastError() == RPC_S_SERVER_UNAVAILABLE || /* NT */
1809         GetLastError() == ERROR_INVALID_PARAMETER ||  /* 9x */
1810         GetLastError() == RPC_S_INVALID_NET_ADDR,     /* Some Vista */
1811         "unexpected last error %d\n", GetLastError());
1812 
1813     HeapFree(GetProcessHeap(), 0, buffer);
1814 }
1815 
1816 /* ##### */
1817 
1818 static void test_OpenPrinter(void)
1819 {
1820     PRINTER_DEFAULTSA   defaults;
1821     HANDLE              hprinter;
1822     DWORD               res;
1823 
1824     SetLastError(MAGIC_DEAD);
1825     res = OpenPrinterA(NULL, NULL, NULL);
1826     if (is_spooler_deactivated(res, GetLastError())) return;
1827 
1828     ok(!res && (GetLastError() == ERROR_INVALID_PARAMETER),
1829         "returned %d with %d (expected '0' with ERROR_INVALID_PARAMETER)\n",
1830         res, GetLastError());
1831 
1832 
1833     /* Get Handle for the local Printserver (NT only)*/
1834     hprinter = (HANDLE) MAGIC_DEAD;
1835     SetLastError(MAGIC_DEAD);
1836     res = OpenPrinterA(NULL, &hprinter, NULL);
1837     if (is_spooler_deactivated(res, GetLastError())) return;
1838     ok(res || GetLastError() == ERROR_INVALID_PARAMETER,
1839         "returned %d with %d (expected '!=0' or '0' with ERROR_INVALID_PARAMETER)\n",
1840         res, GetLastError());
1841     if(res) {
1842         ClosePrinter(hprinter);
1843 
1844         defaults.pDatatype=NULL;
1845         defaults.pDevMode=NULL;
1846 
1847         defaults.DesiredAccess=0;
1848         hprinter = (HANDLE) MAGIC_DEAD;
1849         SetLastError(MAGIC_DEAD);
1850         res = OpenPrinterA(NULL, &hprinter, &defaults);
1851         ok(res, "returned %d with %d (expected '!=0')\n", res, GetLastError());
1852         if (res) ClosePrinter(hprinter);
1853 
1854         defaults.DesiredAccess=-1;
1855         hprinter = (HANDLE) MAGIC_DEAD;
1856         SetLastError(MAGIC_DEAD);
1857         res = OpenPrinterA(NULL, &hprinter, &defaults);
1858         todo_wine {
1859         ok(!res && GetLastError() == ERROR_ACCESS_DENIED,
1860             "returned %d with %d (expected '0' with ERROR_ACCESS_DENIED)\n",
1861             res, GetLastError());
1862         }
1863         if (res) ClosePrinter(hprinter);
1864 
1865     }
1866 
1867 
1868     if (local_server != NULL) {
1869         hprinter = (HANDLE) 0xdeadbeef;
1870         SetLastError(0xdeadbeef);
1871         res = OpenPrinterA(local_server, &hprinter, NULL);
1872         ok(res || GetLastError() == ERROR_INVALID_PARAMETER,
1873             "returned %d with %d (expected '!=0' or '0' with ERROR_INVALID_PARAMETER)\n",
1874             res, GetLastError());
1875         if(res) ClosePrinter(hprinter);
1876     }
1877 
1878     /* Invalid Printername */
1879     hprinter = (HANDLE) MAGIC_DEAD;
1880     SetLastError(MAGIC_DEAD);
1881     res = OpenPrinterA(illegal_name, &hprinter, NULL);
1882     ok(!res && ((GetLastError() == ERROR_INVALID_PRINTER_NAME) ||
1883                 (GetLastError() == ERROR_INVALID_PARAMETER) ),
1884        "returned %d with %d (expected '0' with: ERROR_INVALID_PARAMETER or"
1885        "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
1886     if(res) ClosePrinter(hprinter);
1887 
1888     hprinter = (HANDLE) MAGIC_DEAD;
1889     SetLastError(MAGIC_DEAD);
1890     res = OpenPrinterA(empty, &hprinter, NULL);
1891     /* NT: ERROR_INVALID_PRINTER_NAME,  9x: ERROR_INVALID_PARAMETER */
1892     ok( !res &&
1893         ((GetLastError() == ERROR_INVALID_PRINTER_NAME) ||
1894         (GetLastError() == ERROR_INVALID_PARAMETER) ),
1895         "returned %d with %d (expected '0' with: ERROR_INVALID_PRINTER_NAME"
1896         " or ERROR_INVALID_PARAMETER)\n", res, GetLastError());
1897     if(res) ClosePrinter(hprinter);
1898 
1899 
1900     /* get handle for the default printer */
1901     if (default_printer)
1902     {
1903         hprinter = (HANDLE) MAGIC_DEAD;
1904         SetLastError(MAGIC_DEAD);
1905         res = OpenPrinterA(default_printer, &hprinter, NULL);
1906         if((!res) && (GetLastError() == RPC_S_SERVER_UNAVAILABLE))
1907         {
1908             trace("The service 'Spooler' is required for '%s'\n", default_printer);
1909             return;
1910         }
1911         ok(res, "returned %d with %d (expected '!=0')\n", res, GetLastError());
1912         if(res) ClosePrinter(hprinter);
1913 
1914         SetLastError(MAGIC_DEAD);
1915         res = OpenPrinterA(default_printer, NULL, NULL);
1916         /* NT: FALSE with ERROR_INVALID_PARAMETER, 9x: TRUE */
1917         ok(res || (GetLastError() == ERROR_INVALID_PARAMETER),
1918             "returned %d with %d (expected '!=0' or '0' with "
1919             "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
1920 
1921         defaults.pDatatype=NULL;
1922         defaults.pDevMode=NULL;
1923         defaults.DesiredAccess=0;
1924 
1925         hprinter = (HANDLE) MAGIC_DEAD;
1926         SetLastError(MAGIC_DEAD);
1927         res = OpenPrinterA(default_printer, &hprinter, &defaults);
1928         ok(res || GetLastError() == ERROR_ACCESS_DENIED,
1929             "returned %d with %d (expected '!=0' or '0' with "
1930             "ERROR_ACCESS_DENIED)\n", res, GetLastError());
1931         if(res) ClosePrinter(hprinter);
1932 
1933         defaults.pDatatype = empty;
1934 
1935         hprinter = (HANDLE) MAGIC_DEAD;
1936         SetLastError(MAGIC_DEAD);
1937         res = OpenPrinterA(default_printer, &hprinter, &defaults);
1938         /* stop here, when a remote Printserver has no RPC-Service running */
1939         if (is_spooler_deactivated(res, GetLastError())) return;
1940         ok(res || ((GetLastError() == ERROR_INVALID_DATATYPE) ||
1941                    (GetLastError() == ERROR_ACCESS_DENIED)),
1942             "returned %d with %d (expected '!=0' or '0' with: "
1943             "ERROR_INVALID_DATATYPE or ERROR_ACCESS_DENIED)\n",
1944             res, GetLastError());
1945         if(res) ClosePrinter(hprinter);
1946 
1947 
1948         defaults.pDatatype=NULL;
1949         defaults.DesiredAccess=PRINTER_ACCESS_USE;
1950 
1951         hprinter = (HANDLE) MAGIC_DEAD;
1952         SetLastError(MAGIC_DEAD);
1953         res = OpenPrinterA(default_printer, &hprinter, &defaults);
1954         ok(res || GetLastError() == ERROR_ACCESS_DENIED,
1955             "returned %d with %d (expected '!=0' or '0' with "
1956             "ERROR_ACCESS_DENIED)\n", res, GetLastError());
1957         if(res) ClosePrinter(hprinter);
1958 
1959 
1960         defaults.DesiredAccess=PRINTER_ALL_ACCESS;
1961         hprinter = (HANDLE) MAGIC_DEAD;
1962         SetLastError(MAGIC_DEAD);
1963         res = OpenPrinterA(default_printer, &hprinter, &defaults);
1964         ok(res || GetLastError() == ERROR_ACCESS_DENIED,
1965             "returned %d with %d (expected '!=0' or '0' with "
1966             "ERROR_ACCESS_DENIED)\n", res, GetLastError());
1967         if(res) ClosePrinter(hprinter);
1968     }
1969 
1970 }
1971 
1972 
1973 static void test_SetDefaultPrinter(void)
1974 {
1975     DWORD   res;
1976     DWORD   size = DEFAULT_PRINTER_SIZE;
1977     CHAR    buffer[DEFAULT_PRINTER_SIZE];
1978     CHAR    org_value[DEFAULT_PRINTER_SIZE];
1979 
1980     if (!default_printer)
1981     {
1982         skip("There is no default printer installed\n");
1983         return;
1984     }
1985 
1986     if (!pSetDefaultPrinterA)  return;
1987 	/* only supported on win2k and above */
1988 
1989     /* backup the original value */
1990     org_value[0] = '\0';
1991     SetLastError(MAGIC_DEAD);
1992     res = GetProfileStringA("windows", "device", NULL, org_value, size);
1993     ok(res, "GetProfileString error %d\n", GetLastError());
1994 
1995     /* first part: with the default Printer */
1996     SetLastError(MAGIC_DEAD);
1997     res = pSetDefaultPrinterA("no_printer_with_this_name");
1998     if (is_spooler_deactivated(res, GetLastError())) return;
1999 
2000     /* Not implemented in wine */
2001     if (!res && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) {
2002         trace("SetDefaultPrinterA() not implemented yet.\n");
2003         return;
2004     }
2005 
2006     ok(!res && (GetLastError() == ERROR_INVALID_PRINTER_NAME),
2007         "returned %d with %d (expected '0' with "
2008         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
2009 
2010     WriteProfileStringA("windows", "device", org_value);
2011     SetLastError(MAGIC_DEAD);
2012     res = pSetDefaultPrinterA("");
2013     ok(res || GetLastError() == ERROR_INVALID_PRINTER_NAME,
2014         "returned %d with %d (expected '!=0' or '0' with "
2015         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
2016 
2017     WriteProfileStringA("windows", "device", org_value);
2018     SetLastError(MAGIC_DEAD);
2019     res = pSetDefaultPrinterA(NULL);
2020     ok(res || GetLastError() == ERROR_INVALID_PRINTER_NAME,
2021         "returned %d with %d (expected '!=0' or '0' with "
2022         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
2023 
2024     WriteProfileStringA("windows", "device", org_value);
2025     SetLastError(MAGIC_DEAD);
2026     res = pSetDefaultPrinterA(default_printer);
2027     ok(res || GetLastError() == ERROR_INVALID_PRINTER_NAME,
2028         "returned %d with %d (expected '!=0' or '0' with "
2029         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
2030 
2031 
2032     /* second part: always without a default Printer */
2033     WriteProfileStringA("windows", "device", NULL);
2034     SetLastError(MAGIC_DEAD);
2035     res = pSetDefaultPrinterA("no_printer_with_this_name");
2036 
2037     ok(!res && (GetLastError() == ERROR_INVALID_PRINTER_NAME),
2038         "returned %d with %d (expected '0' with "
2039         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
2040 
2041     WriteProfileStringA("windows", "device", NULL);
2042     SetLastError(MAGIC_DEAD);
2043     res = pSetDefaultPrinterA("");
2044     if (is_spooler_deactivated(res, GetLastError()))
2045         goto restore_old_printer;
2046 
2047     /* we get ERROR_INVALID_PRINTER_NAME when no printer is installed */
2048     ok(res || GetLastError() == ERROR_INVALID_PRINTER_NAME,
2049          "returned %d with %d (expected '!=0' or '0' with "
2050          "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
2051 
2052     WriteProfileStringA("windows", "device", NULL);
2053     SetLastError(MAGIC_DEAD);
2054     res = pSetDefaultPrinterA(NULL);
2055     /* we get ERROR_INVALID_PRINTER_NAME when no printer is installed */
2056     ok(res || GetLastError() == ERROR_INVALID_PRINTER_NAME,
2057         "returned %d with %d (expected '!=0' or '0' with "
2058         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
2059 
2060     WriteProfileStringA("windows", "device", NULL);
2061     SetLastError(MAGIC_DEAD);
2062     res = pSetDefaultPrinterA(default_printer);
2063     ok(res || GetLastError() == ERROR_INVALID_PRINTER_NAME,
2064         "returned %d with %d (expected '!=0' or '0' with "
2065         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
2066 
2067     /* restore the original value */
2068 restore_old_printer:
2069     res = pSetDefaultPrinterA(default_printer);          /* the nice way */
2070     ok(res, "SetDefaultPrinter error %d\n", GetLastError());
2071     WriteProfileStringA("windows", "device", org_value); /* the old way */
2072 
2073     buffer[0] = '\0';
2074     SetLastError(MAGIC_DEAD);
2075     res = GetProfileStringA("windows", "device", NULL, buffer, size);
2076     ok(res, "GetProfileString error %d\n", GetLastError());
2077     ok(!lstrcmpA(org_value, buffer), "'%s' (expected '%s')\n", buffer, org_value);
2078 
2079 }
2080 
2081 /* ########################### */
2082 
2083 static void test_XcvDataW_MonitorUI(void)
2084 {
2085     DWORD   res;
2086     HANDLE  hXcv;
2087     BYTE    buffer[MAX_PATH + 4];
2088     DWORD   needed;
2089     DWORD   status;
2090     DWORD   len;
2091     PRINTER_DEFAULTSA pd;
2092 
2093     /* api is not present before w2k */
2094     if (pXcvDataW == NULL) return;
2095 
2096     pd.pDatatype = NULL;
2097     pd.pDevMode  = NULL;
2098     pd.DesiredAccess = SERVER_ACCESS_ADMINISTER;
2099 
2100     hXcv = NULL;
2101     SetLastError(0xdeadbeef);
2102     res = OpenPrinterA(xcv_localport, &hXcv, &pd);
2103     if (is_spooler_deactivated(res, GetLastError())) return;
2104     if (is_access_denied(res, GetLastError())) return;
2105 
2106     ok(res, "returned %d with %u and handle %p (expected '!= 0')\n", res, GetLastError(), hXcv);
2107     if (!res) return;
2108 
2109     /* ask for needed size */
2110     needed = (DWORD) 0xdeadbeef;
2111     status = (DWORD) 0xdeadbeef;
2112     SetLastError(0xdeadbeef);
2113     res = pXcvDataW(hXcv, cmd_MonitorUIW, NULL, 0, NULL, 0, &needed, &status);
2114     ok( res && (status == ERROR_INSUFFICIENT_BUFFER) && (needed <= MAX_PATH),
2115         "returned %d with %u and %u for status %u (expected '!= 0' and "
2116         "'<= MAX_PATH' for status ERROR_INSUFFICIENT_BUFFER)\n",
2117         res, GetLastError(), needed, status);
2118 
2119     if (needed > MAX_PATH) {
2120         ClosePrinter(hXcv);
2121         skip("buffer overflow (%u)\n", needed);
2122         return;
2123     }
2124     len = needed;       /* Size is in bytes */
2125 
2126     /* the command is required */
2127     needed = (DWORD) 0xdeadbeef;
2128     status = (DWORD) 0xdeadbeef;
2129     SetLastError(0xdeadbeef);
2130     res = pXcvDataW(hXcv, emptyW, NULL, 0, NULL, 0, &needed, &status);
2131     ok( res && (status == ERROR_INVALID_PARAMETER),
2132         "returned %d with %u and %u for status %u (expected '!= 0' with "
2133         "ERROR_INVALID_PARAMETER)\n", res, GetLastError(), needed, status);
2134 
2135     needed = (DWORD) 0xdeadbeef;
2136     status = (DWORD) 0xdeadbeef;
2137     SetLastError(0xdeadbeef);
2138     res = pXcvDataW(hXcv, NULL, NULL, 0, buffer, MAX_PATH, &needed, &status);
2139     ok( !res && (GetLastError() == RPC_X_NULL_REF_POINTER),
2140         "returned %d with %u and %u for status %u (expected '0' with "
2141         "RPC_X_NULL_REF_POINTER)\n", res, GetLastError(), needed, status);
2142 
2143     /* "PDWORD needed" is checked before RPC-Errors */
2144     needed = (DWORD) 0xdeadbeef;
2145     status = (DWORD) 0xdeadbeef;
2146     SetLastError(0xdeadbeef);
2147     res = pXcvDataW(hXcv, cmd_MonitorUIW, NULL, 0, buffer, len, NULL, &status);
2148     ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
2149         "returned %d with %u and %u for status %u (expected '0' with "
2150         "ERROR_INVALID_PARAMETER)\n", res, GetLastError(), needed, status);
2151 
2152     needed = (DWORD) 0xdeadbeef;
2153     status = (DWORD) 0xdeadbeef;
2154     SetLastError(0xdeadbeef);
2155     res = pXcvDataW(hXcv, cmd_MonitorUIW, NULL, 0, NULL, len, &needed, &status);
2156     ok( !res && (GetLastError() == RPC_X_NULL_REF_POINTER),
2157         "returned %d with %u and %u for status %u (expected '0' with "
2158         "RPC_X_NULL_REF_POINTER)\n", res, GetLastError(), needed, status);
2159 
2160     needed = (DWORD) 0xdeadbeef;
2161     status = (DWORD) 0xdeadbeef;
2162     SetLastError(0xdeadbeef);
2163     res = pXcvDataW(hXcv, cmd_MonitorUIW, NULL, 0, buffer, len, &needed, NULL);
2164     ok( !res && (GetLastError() == RPC_X_NULL_REF_POINTER),
2165         "returned %d with %u and %u for status %u (expected '0' with "
2166         "RPC_X_NULL_REF_POINTER)\n", res, GetLastError(), needed, status);
2167 
2168     /* off by one: larger  */
2169     needed = (DWORD) 0xdeadbeef;
2170     status = (DWORD) 0xdeadbeef;
2171     SetLastError(0xdeadbeef);
2172     res = pXcvDataW(hXcv, cmd_MonitorUIW, NULL, 0, buffer, len+1, &needed, &status);
2173     ok( res && (status == ERROR_SUCCESS),
2174         "returned %d with %u and %u for status %u (expected '!= 0' for status "
2175         "ERROR_SUCCESS)\n", res, GetLastError(), needed, status);
2176 
2177     /* off by one: smaller */
2178     /* the buffer is not modified for NT4, w2k, XP */
2179     needed = (DWORD) 0xdeadbeef;
2180     status = (DWORD) 0xdeadbeef;
2181     SetLastError(0xdeadbeef);
2182     res = pXcvDataW(hXcv, cmd_MonitorUIW, NULL, 0, buffer, len-1, &needed, &status);
2183     ok( res && (status == ERROR_INSUFFICIENT_BUFFER),
2184         "returned %d with %u and %u for status %u (expected '!= 0' for status "
2185         "ERROR_INSUFFICIENT_BUFFER)\n", res, GetLastError(), needed, status);
2186 
2187 
2188     /* Normal use. The DLL-Name without a Path is returned */
2189     memset(buffer, 0, len);
2190     needed = (DWORD) 0xdeadbeef;
2191     status = (DWORD) 0xdeadbeef;
2192     SetLastError(0xdeadbeef);
2193     res = pXcvDataW(hXcv, cmd_MonitorUIW, NULL, 0, buffer, len, &needed, &status);
2194     ok( res && (status == ERROR_SUCCESS),
2195         "returned %d with %u and %u for status %u (expected '!= 0' for status "
2196         "ERROR_SUCCESS)\n", res, GetLastError(), needed, status);
2197 
2198     ClosePrinter(hXcv);
2199 }
2200 
2201 /* ########################### */
2202 
2203 static void test_XcvDataW_PortIsValid(void)
2204 {
2205     DWORD   res;
2206     HANDLE  hXcv;
2207     DWORD   needed;
2208     DWORD   status;
2209     PRINTER_DEFAULTSA   pd;
2210 
2211     /* api is not present before w2k */
2212     if (pXcvDataW == NULL) return;
2213 
2214     pd.pDatatype = NULL;
2215     pd.pDevMode  = NULL;
2216     pd.DesiredAccess = SERVER_ACCESS_ADMINISTER;
2217 
2218     hXcv = NULL;
2219     SetLastError(0xdeadbeef);
2220     res = OpenPrinterA(xcv_localport, &hXcv, &pd);
2221     if (is_spooler_deactivated(res, GetLastError())) return;
2222     if (is_access_denied(res, GetLastError())) return;
2223 
2224     ok(res, "returned %d with %u and handle %p (expected '!= 0')\n", res, GetLastError(), hXcv);
2225     if (!res) return;
2226 
2227 
2228     /* "PDWORD needed" is always required */
2229     needed = (DWORD) 0xdeadbeef;
2230     status = (DWORD) 0xdeadbeef;
2231     SetLastError(0xdeadbeef);
2232     res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) portname_lpt1W, sizeof(portname_lpt1W), NULL, 0, NULL, &status);
2233     ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
2234         "returned %d with %u and %u for status %u (expected '!= 0' with ERROR_INVALID_PARAMETER)\n",
2235          res, GetLastError(), needed, status);
2236 
2237     /* an empty name is not allowed */
2238     needed = (DWORD) 0xdeadbeef;
2239     status = (DWORD) 0xdeadbeef;
2240     SetLastError(0xdeadbeef);
2241     res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) emptyW, sizeof(emptyW), NULL, 0, &needed, &status);
2242     ok( res && ((status == ERROR_FILE_NOT_FOUND) || (status == ERROR_PATH_NOT_FOUND)),
2243         "returned %d with %u and %u for status %u (expected '!= 0' for status: "
2244         "ERROR_FILE_NOT_FOUND or ERROR_PATH_NOT_FOUND)\n",
2245         res, GetLastError(), needed, status);
2246 
2247     /* a directory is not allowed */
2248     needed = (DWORD) 0xdeadbeef;
2249     status = (DWORD) 0xdeadbeef;
2250     SetLastError(0xdeadbeef);
2251     res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) tempdirW, (lstrlenW(tempdirW) + 1) * sizeof(WCHAR), NULL, 0, &needed, &status);
2252     /* XP: ERROR_PATH_NOT_FOUND, w2k ERROR_ACCESS_DENIED */
2253     ok( res && ((status == ERROR_PATH_NOT_FOUND) || (status == ERROR_ACCESS_DENIED)),
2254         "returned %d with %u and %u for status %u (expected '!= 0' for status: "
2255         "ERROR_PATH_NOT_FOUND or ERROR_ACCESS_DENIED)\n",
2256         res, GetLastError(), needed, status);
2257 
2258     /* more valid well known ports */
2259     needed = (DWORD) 0xdeadbeef;
2260     status = (DWORD) 0xdeadbeef;
2261     SetLastError(0xdeadbeef);
2262     res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) portname_lpt1W, sizeof(portname_lpt1W), NULL, 0, &needed, &status);
2263     ok( res && (status == ERROR_SUCCESS),
2264         "returned %d with %u and %u for status %u (expected '!= 0' for ERROR_SUCCESS)\n",
2265         res, GetLastError(), needed, status);
2266 
2267     needed = (DWORD) 0xdeadbeef;
2268     status = (DWORD) 0xdeadbeef;
2269     SetLastError(0xdeadbeef);
2270     res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) portname_lpt2W, sizeof(portname_lpt2W), NULL, 0, &needed, &status);
2271     ok( res && (status == ERROR_SUCCESS),
2272         "returned %d with %u and %u for status %u (expected '!= 0' for ERROR_SUCCESS)\n",
2273         res, GetLastError(), needed, status);
2274 
2275     needed = (DWORD) 0xdeadbeef;
2276     status = (DWORD) 0xdeadbeef;
2277     SetLastError(0xdeadbeef);
2278     res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) portname_com1W, sizeof(portname_com1W), NULL, 0, &needed, &status);
2279     ok( res && (status == ERROR_SUCCESS),
2280         "returned %d with %u and %u for status %u (expected '!= 0' for ERROR_SUCCESS)\n",
2281         res, GetLastError(), needed, status);
2282 
2283     needed = (DWORD) 0xdeadbeef;
2284     status = (DWORD) 0xdeadbeef;
2285     SetLastError(0xdeadbeef);
2286     res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) portname_com2W, sizeof(portname_com2W), NULL, 0, &needed, &status);
2287     ok( res && (status == ERROR_SUCCESS),
2288         "returned %d with %u and %u for status %u (expected '!= 0' for ERROR_SUCCESS)\n",
2289         res, GetLastError(), needed, status);
2290 
2291     needed = (DWORD) 0xdeadbeef;
2292     status = (DWORD) 0xdeadbeef;
2293     SetLastError(0xdeadbeef);
2294     res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) portname_fileW, sizeof(portname_fileW), NULL, 0, &needed, &status);
2295     ok( res && (status == ERROR_SUCCESS),
2296         "returned %d with %u and %u for status %u (expected '!= 0' with  ERROR_SUCCESS)\n",
2297         res, GetLastError(), needed, status);
2298 
2299 
2300     /* a normal, writable file is allowed */
2301     needed = (DWORD) 0xdeadbeef;
2302     status = (DWORD) 0xdeadbeef;
2303     SetLastError(0xdeadbeef);
2304     res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) tempfileW, (lstrlenW(tempfileW) + 1) * sizeof(WCHAR), NULL, 0, &needed, &status);
2305     ok( res && (status == ERROR_SUCCESS),
2306         "returned %d with %u and %u for status %u (expected '!= 0' with ERROR_SUCCESS)\n",
2307         res, GetLastError(), needed, status);
2308 
2309     ClosePrinter(hXcv);
2310 }
2311 
2312 /* ########################### */
2313 
2314 static void test_GetPrinter(void)
2315 {
2316     HANDLE hprn;
2317     BOOL ret;
2318     BYTE *buf;
2319     INT level;
2320     DWORD needed, filled;
2321 
2322     if (!default_printer)
2323     {
2324         skip("There is no default printer installed\n");
2325         return;
2326     }
2327 
2328     hprn = 0;
2329     ret = OpenPrinterA(default_printer, &hprn, NULL);
2330     if (!ret)
2331     {
2332         skip("Unable to open the default printer (%s)\n", default_printer);
2333         return;
2334     }
2335     ok(hprn != 0, "wrong hprn %p\n", hprn);
2336 
2337     for (level = 1; level <= 9; level++)
2338     {
2339         SetLastError(0xdeadbeef);
2340         needed = (DWORD)-1;
2341         ret = GetPrinterA(hprn, level, NULL, 0, &needed);
2342         if (ret)
2343         {
2344             win_skip("Level %d is not supported on Win9x/WinMe\n", level);
2345             ok(GetLastError() == ERROR_SUCCESS, "wrong error %d\n", GetLastError());
2346             ok(needed == 0,"Expected 0, got %d\n", needed);
2347             continue;
2348         }
2349         ok(!ret, "level %d: GetPrinter should fail\n", level);
2350         /* Not all levels are supported on all Windows-Versions */
2351         if (GetLastError() == ERROR_INVALID_LEVEL ||
2352             GetLastError() == ERROR_NOT_SUPPORTED /* Win9x/WinMe */)
2353         {
2354             skip("Level %d not supported\n", level);
2355             continue;
2356         }
2357         ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "wrong error %d\n", GetLastError());
2358         ok(needed > 0,"not expected needed buffer size %d\n", needed);
2359 
2360         /* GetPrinterA returns the same number of bytes as GetPrinterW */
2361         if (!on_win9x && !ret && pGetPrinterW && level != 6 && level != 7)
2362         {
2363             DWORD double_needed;
2364             ret = pGetPrinterW(hprn, level, NULL, 0, &double_needed);
2365             ok(!ret, "level %d: GetPrinter error %d\n", level, GetLastError());
2366             ok(double_needed == needed, "level %d: GetPrinterA returned different size %d than GetPrinterW (%d)\n", level, needed, double_needed);
2367         }
2368 
2369         buf = HeapAlloc(GetProcessHeap(), 0, needed);
2370 
2371         SetLastError(0xdeadbeef);
2372         filled = -1;
2373         ret = GetPrinterA(hprn, level, buf, needed, &filled);
2374         ok(ret, "level %d: GetPrinter error %d\n", level, GetLastError());
2375         ok(needed == filled, "needed %d != filled %d\n", needed, filled);
2376 
2377         if (level == 2)
2378         {
2379             PRINTER_INFO_2A *pi_2 = (PRINTER_INFO_2A *)buf;
2380 
2381             ok(pi_2->pPrinterName!= NULL, "not expected NULL ptr\n");
2382             ok(pi_2->pDriverName!= NULL, "not expected NULL ptr\n");
2383 
2384             trace("pPrinterName %s\n", pi_2->pPrinterName);
2385             trace("pDriverName %s\n", pi_2->pDriverName);
2386         }
2387 
2388         HeapFree(GetProcessHeap(), 0, buf);
2389     }
2390 
2391     SetLastError(0xdeadbeef);
2392     ret = ClosePrinter(hprn);
2393     ok(ret, "ClosePrinter error %d\n", GetLastError());
2394 }
2395 
2396 /* ########################### */
2397 
2398 static void test_GetPrinterData(void)
2399 {
2400     HANDLE hprn = 0;
2401     DWORD res;
2402     DWORD type;
2403     CHAR  buffer[MAX_PATH + 1];
2404     DWORD needed;
2405     DWORD len;
2406 
2407     /* ToDo: test parameter validation, test with the default printer */
2408 
2409     SetLastError(0xdeadbeef);
2410     res = OpenPrinterA(NULL, &hprn, NULL);
2411     if (!res)
2412     {
2413         /* printserver not available on win9x */
2414         if (!on_win9x)
2415             win_skip("Unable to open the printserver: %d\n", GetLastError());
2416         return;
2417     }
2418 
2419     memset(buffer, '#', sizeof(buffer));
2420     buffer[MAX_PATH] = 0;
2421     type = 0xdeadbeef;
2422     needed = 0xdeadbeef;
2423     SetLastError(0xdeadbeef);
2424     res = GetPrinterDataA(hprn, defaultspooldirectory, &type, (LPBYTE) buffer, sizeof(buffer), &needed);
2425 
2426     len = lstrlenA(buffer) + sizeof(CHAR);
2427     /* NT4 and w2k require a buffer to save the UNICODE result also for the ANSI function */
2428     ok( !res && (type == REG_SZ) && ((needed == len) || (needed == (len * sizeof(WCHAR)))),
2429         "got %d, type %d, needed: %d and '%s' (expected ERROR_SUCCESS, REG_SZ and %d)\n",
2430         res, type, needed, buffer, len);
2431 
2432     needed = 0xdeadbeef;
2433     SetLastError(0xdeadbeef);
2434     res = GetPrinterDataA(hprn, defaultspooldirectory, NULL, NULL, 0, &needed);
2435     ok( (res == ERROR_MORE_DATA) && ((needed == len) || (needed == (len * sizeof(WCHAR)))),
2436         "got %d, needed: %d (expected ERROR_MORE_DATA and %d)\n", res, needed, len);
2437 
2438     /* ToDo: test SPLREG_*  */
2439 
2440     SetLastError(0xdeadbeef);
2441     res = ClosePrinter(hprn);
2442     ok(res, "ClosePrinter error %d\n", GetLastError());
2443 }
2444 
2445 /* ########################### */
2446 
2447 static void test_GetPrinterDataEx(void)
2448 {
2449     HANDLE hprn = 0;
2450     DWORD res;
2451     DWORD type;
2452     CHAR  buffer[MAX_PATH + 1];
2453     DWORD needed;
2454     DWORD len;
2455 
2456     /* not present before w2k */
2457     if (!pGetPrinterDataExA) {
2458         win_skip("GetPrinterDataEx not found\n");
2459         return;
2460     }
2461 
2462     /* ToDo: test parameter validation, test with the default printer */
2463 
2464     SetLastError(0xdeadbeef);
2465     res = OpenPrinterA(NULL, &hprn, NULL);
2466     if (!res)
2467     {
2468         win_skip("Unable to open the printserver: %d\n", GetLastError());
2469         return;
2470     }
2471 
2472     /* keyname is ignored, when hprn is a HANDLE for a printserver */
2473     memset(buffer, '#', sizeof(buffer));
2474     buffer[MAX_PATH] = 0;
2475     type = 0xdeadbeef;
2476     needed = 0xdeadbeef;
2477     SetLastError(0xdeadbeef);
2478     res = pGetPrinterDataExA(hprn, NULL, defaultspooldirectory, &type,
2479                              (LPBYTE) buffer, sizeof(buffer), &needed);
2480 
2481     len = lstrlenA(buffer) + sizeof(CHAR);
2482     /* NT4 and w2k require a buffer to save the UNICODE result also for the ANSI function */
2483     ok( !res && (type == REG_SZ) && ((needed == len) || (needed == (len * sizeof(WCHAR)))),
2484         "got %d, type %d, needed: %d and '%s' (expected ERROR_SUCCESS, REG_SZ and %d)\n",
2485         res, type, needed, buffer, len);
2486 
2487     memset(buffer, '#', sizeof(buffer));
2488     buffer[MAX_PATH] = 0;
2489     type = 0xdeadbeef;
2490     needed = 0xdeadbeef;
2491     SetLastError(0xdeadbeef);
2492     res = pGetPrinterDataExA(hprn, "", defaultspooldirectory, &type,
2493                              (LPBYTE) buffer, sizeof(buffer), &needed);
2494     len = lstrlenA(buffer) + sizeof(CHAR);
2495     ok( !res && (type == REG_SZ) && ((needed == len) || (needed == (len * sizeof(WCHAR)))),
2496         "got %d, type %d, needed: %d and '%s' (expected ERROR_SUCCESS, REG_SZ and %d)\n",
2497         res, type, needed, buffer, len);
2498 
2499     memset(buffer, '#', sizeof(buffer));
2500     buffer[MAX_PATH] = 0;
2501     type = 0xdeadbeef;
2502     needed = 0xdeadbeef;
2503     SetLastError(0xdeadbeef);
2504     /* Wine uses GetPrinterDataEx with "PrinterDriverData" to implement GetPrinterData */
2505     res = pGetPrinterDataExA(hprn, "PrinterDriverData", defaultspooldirectory,
2506                              &type, (LPBYTE) buffer, sizeof(buffer), &needed);
2507     len = lstrlenA(buffer) + sizeof(CHAR);
2508     ok( !res && (type == REG_SZ) && ((needed == len) || (needed == (len * sizeof(WCHAR)))),
2509         "got %d, type %d, needed: %d and '%s' (expected ERROR_SUCCESS, REG_SZ and %d)\n",
2510         res, type, needed, buffer, len);
2511 
2512 
2513     memset(buffer, '#', sizeof(buffer));
2514     buffer[MAX_PATH] = 0;
2515     type = 0xdeadbeef;
2516     needed = 0xdeadbeef;
2517     SetLastError(0xdeadbeef);
2518     res = pGetPrinterDataExA(hprn, does_not_exist, defaultspooldirectory, &type,
2519                              (LPBYTE) buffer, sizeof(buffer), &needed);
2520     len = lstrlenA(buffer) + sizeof(CHAR);
2521     ok( !res && (type == REG_SZ) && ((needed == len) || (needed == (len * sizeof(WCHAR)))),
2522         "got %d, type %d, needed: %d and '%s' (expected ERROR_SUCCESS, REG_SZ and %d)\n",
2523         res, type, needed, buffer, len);
2524 
2525     needed = 0xdeadbeef;
2526     SetLastError(0xdeadbeef);
2527     /* vista and w2k8 have a bug in GetPrinterDataEx:
2528        the current LastError value is returned as result */
2529     res = pGetPrinterDataExA(hprn, NULL, defaultspooldirectory, NULL, NULL, 0, &needed);
2530     ok( ((res == ERROR_MORE_DATA) || broken(res == 0xdeadbeef)) &&
2531         ((needed == len) || (needed == (len * sizeof(WCHAR)))),
2532         "got %d, needed: %d (expected ERROR_MORE_DATA and %d)\n", res, needed, len);
2533 
2534     needed = 0xdeadbeef;
2535     SetLastError(0xdeaddead);
2536     res = pGetPrinterDataExA(hprn, NULL, defaultspooldirectory, NULL, NULL, 0, &needed);
2537     ok( ((res == ERROR_MORE_DATA) || broken(res == 0xdeaddead)) &&
2538         ((needed == len) || (needed == (len * sizeof(WCHAR)))),
2539         "got %d, needed: %d (expected ERROR_MORE_DATA and %d)\n", res, needed, len);
2540 
2541     SetLastError(0xdeadbeef);
2542     res = ClosePrinter(hprn);
2543     ok(res, "ClosePrinter error %d\n", GetLastError());
2544 }
2545 
2546 /* ########################### */
2547 
2548 static void test_GetPrinterDriver(void)
2549 {
2550     HANDLE hprn;
2551     BOOL ret;
2552     BYTE *buf;
2553     INT level;
2554     DWORD needed, filled;
2555 
2556     if (!default_printer)
2557     {
2558         skip("There is no default printer installed\n");
2559         return;
2560     }
2561 
2562     hprn = 0;
2563     ret = OpenPrinterA(default_printer, &hprn, NULL);
2564     if (!ret)
2565     {
2566         skip("Unable to open the default printer (%s)\n", default_printer);
2567         return;
2568     }
2569     ok(hprn != 0, "wrong hprn %p\n", hprn);
2570 
2571     for (level = -1; level <= 7; level++)
2572     {
2573         SetLastError(0xdeadbeef);
2574         needed = (DWORD)-1;
2575         ret = GetPrinterDriverA(hprn, NULL, level, NULL, 0, &needed);
2576         ok(!ret, "level %d: GetPrinterDriver should fail\n", level);
2577         if (level >= 1 && level <= 6)
2578         {
2579             /* Not all levels are supported on all Windows-Versions */
2580             if(GetLastError() == ERROR_INVALID_LEVEL) continue;
2581             ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "wrong error %d\n", GetLastError());
2582             ok(needed > 0,"not expected needed buffer size %d\n", needed);
2583         }
2584         else
2585         {
2586             /* ERROR_OUTOFMEMORY found on win9x */
2587             ok( ((GetLastError() == ERROR_INVALID_LEVEL) ||
2588                  (GetLastError() == ERROR_OUTOFMEMORY)),
2589                 "%d: returned %d with %d (expected '0' with: "
2590                 "ERROR_INVALID_LEVEL or ERROR_OUTOFMEMORY)\n",
2591                 level, ret, GetLastError());
2592             /* needed is modified in win9x. The modified Value depends on the
2593                default Printer. testing for "needed == (DWORD)-1" will fail */
2594             continue;
2595         }
2596 
2597         /* GetPrinterDriverA returns the same number of bytes as GetPrinterDriverW */
2598         if (!on_win9x && !ret && pGetPrinterDriverW)
2599         {
2600             DWORD double_needed;
2601             ret = pGetPrinterDriverW(hprn, NULL, level, NULL, 0, &double_needed);
2602             ok(!ret, "level %d: GetPrinterDriver error %d\n", level, GetLastError());
2603             ok(double_needed == needed, "GetPrinterDriverA returned different size %d than GetPrinterDriverW (%d)\n", needed, double_needed);
2604         }
2605 
2606         buf = HeapAlloc(GetProcessHeap(), 0, needed);
2607 
2608         SetLastError(0xdeadbeef);
2609         filled = -1;
2610         ret = GetPrinterDriverA(hprn, NULL, level, buf, needed, &filled);
2611         ok(ret, "level %d: GetPrinterDriver error %d\n", level, GetLastError());
2612         ok(needed == filled, "needed %d != filled %d\n", needed, filled);
2613 
2614         if (level == 2)
2615         {
2616             DRIVER_INFO_2A *di_2 = (DRIVER_INFO_2A *)buf;
2617             DWORD calculated = sizeof(*di_2);
2618             HANDLE hf;
2619 
2620             /* MSDN is wrong: The Drivers on the win9x-CD's have cVersion=0x0400
2621                NT351: 1, NT4.0+w2k(Kernelmode): 2, w2k-win7(Usermode): 3, win8 and above(Usermode): 4 */
2622             ok( (di_2->cVersion <= 4) ||
2623                 (di_2->cVersion == 0x0400), "di_2->cVersion = %d\n", di_2->cVersion);
2624             ok(di_2->pName != NULL, "not expected NULL ptr\n");
2625             ok(di_2->pEnvironment != NULL, "not expected NULL ptr\n");
2626             ok(di_2->pDriverPath != NULL, "not expected NULL ptr\n");
2627             ok(di_2->pDataFile != NULL, "not expected NULL ptr\n");
2628             ok(di_2->pConfigFile != NULL, "not expected NULL ptr\n");
2629 
2630             trace("cVersion %d\n", di_2->cVersion);
2631             trace("pName %s\n", di_2->pName);
2632             calculated += strlen(di_2->pName) + 1;
2633             trace("pEnvironment %s\n", di_2->pEnvironment);
2634             calculated += strlen(di_2->pEnvironment) + 1;
2635             trace("pDriverPath %s\n", di_2->pDriverPath);
2636             calculated += strlen(di_2->pDriverPath) + 1;
2637             trace("pDataFile %s\n", di_2->pDataFile);
2638             calculated += strlen(di_2->pDataFile) + 1;
2639             trace("pConfigFile %s\n", di_2->pConfigFile);
2640             calculated += strlen(di_2->pConfigFile) + 1;
2641 
2642             hf = CreateFileA(di_2->pDriverPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
2643             if(hf != INVALID_HANDLE_VALUE)
2644                 CloseHandle(hf);
2645             todo_wine
2646             ok(hf != INVALID_HANDLE_VALUE, "Could not open %s\n", di_2->pDriverPath);
2647 
2648             hf = CreateFileA(di_2->pDataFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
2649             if(hf != INVALID_HANDLE_VALUE)
2650                 CloseHandle(hf);
2651             ok(hf != INVALID_HANDLE_VALUE, "Could not open %s\n", di_2->pDataFile);
2652 
2653             hf = CreateFileA(di_2->pConfigFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
2654             if(hf != INVALID_HANDLE_VALUE)
2655                 CloseHandle(hf);
2656             todo_wine
2657             ok(hf != INVALID_HANDLE_VALUE, "Could not open %s\n", di_2->pConfigFile);
2658 
2659             /* XP allocates memory for both ANSI and unicode names */
2660             ok(filled >= calculated,"calculated %d != filled %d\n", calculated, filled);
2661 
2662             /* Obscure test - demonstrate that Windows zero fills the buffer, even on failure */
2663             ret = GetPrinterDriverA(hprn, NULL, level, buf, needed - 2, &filled);
2664             ok(!ret, "level %d: GetPrinterDriver succeeded with less buffer than it should\n", level);
2665             ok(di_2->pDataFile == NULL ||
2666                broken(di_2->pDataFile != NULL), /* Win9x/WinMe */
2667                "Even on failure, GetPrinterDriver clears the buffer to zeros\n");
2668         }
2669 
2670         HeapFree(GetProcessHeap(), 0, buf);
2671     }
2672 
2673     SetLastError(0xdeadbeef);
2674     ret = ClosePrinter(hprn);
2675     ok(ret, "ClosePrinter error %d\n", GetLastError());
2676 }
2677 
2678 static void test_DEVMODEA(const DEVMODEA *dm, LONG dmSize, LPCSTR exp_prn_name)
2679 {
2680     /* On NT3.51, some fields in DEVMODEA are empty/zero
2681       (dmDeviceName, dmSpecVersion, dmDriverVersion and dmDriverExtra)
2682        We skip the Tests on this Platform */
2683     if (dm->dmSpecVersion || dm->dmDriverVersion || dm->dmDriverExtra) {
2684     /* The 0-terminated Printername can be larger (MAX_PATH) than CCHDEVICENAME */
2685         ok(!strncmp(exp_prn_name, (LPCSTR)dm->dmDeviceName, CCHDEVICENAME -1) ||
2686            !strncmp(exp_prn_name, (LPCSTR)dm->dmDeviceName, CCHDEVICENAME -2), /* XP+ */
2687             "expected '%s', got '%s'\n", exp_prn_name, dm->dmDeviceName);
2688         ok(dm->dmSize + dm->dmDriverExtra == dmSize,
2689             "%u != %d\n", dm->dmSize + dm->dmDriverExtra, dmSize);
2690     }
2691     trace("dmFields %08x\n", dm->dmFields);
2692 }
2693 
2694 static void test_DocumentProperties(void)
2695 {
2696     HANDLE hprn;
2697     LONG dm_size, ret;
2698     DEVMODEA *dm;
2699     char empty_str[] = "";
2700 
2701     if (!default_printer)
2702     {
2703         skip("There is no default printer installed\n");
2704         return;
2705     }
2706 
2707     hprn = 0;
2708     ret = OpenPrinterA(default_printer, &hprn, NULL);
2709     if (!ret)
2710     {
2711         skip("Unable to open the default printer (%s)\n", default_printer);
2712         return;
2713     }
2714     ok(hprn != 0, "wrong hprn %p\n", hprn);
2715 
2716     dm_size = DocumentPropertiesA(0, hprn, NULL, NULL, NULL, 0);
2717     trace("DEVMODEA required size %d\n", dm_size);
2718     ok(dm_size >= sizeof(DEVMODEA), "unexpected DocumentPropertiesA ret value %d\n", dm_size);
2719 
2720     dm = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dm_size);
2721 
2722     ret = DocumentPropertiesA(0, hprn, NULL, dm, dm, DM_OUT_BUFFER);
2723     ok(ret == IDOK, "DocumentPropertiesA ret value %d != expected IDOK\n", ret);
2724 
2725     ret = DocumentPropertiesA(0, hprn, empty_str, dm, dm, DM_OUT_BUFFER);
2726     ok(ret == IDOK, "DocumentPropertiesA ret value %d != expected IDOK\n", ret);
2727 
2728     test_DEVMODEA(dm, dm_size, default_printer);
2729 
2730     HeapFree(GetProcessHeap(), 0, dm);
2731 
2732     SetLastError(0xdeadbeef);
2733     ret = ClosePrinter(hprn);
2734     ok(ret, "ClosePrinter error %d\n", GetLastError());
2735 }
2736 
2737 static void test_EnumPrinters(void)
2738 {
2739     DWORD neededA, neededW, num;
2740     DWORD ret;
2741 
2742     SetLastError(0xdeadbeef);
2743     neededA = -1;
2744     ret = EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &neededA, &num);
2745     if (is_spooler_deactivated(ret, GetLastError())) return;
2746     if (!ret)
2747     {
2748         /* We have 1 or more printers */
2749         ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "gle %d\n", GetLastError());
2750         ok(neededA > 0, "Expected neededA to show the number of needed bytes\n");
2751     }
2752     else
2753     {
2754         /* We don't have any printers defined */
2755         ok(GetLastError() == S_OK, "gle %d\n", GetLastError());
2756         ok(neededA == 0, "Expected neededA to be zero\n");
2757     }
2758     ok(num == 0, "num %d\n", num);
2759 
2760     SetLastError(0xdeadbeef);
2761     neededW = -1;
2762     ret = EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &neededW, &num);
2763     /* EnumPrintersW is not supported on all platforms */
2764     if (!ret && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
2765     {
2766         win_skip("EnumPrintersW is not implemented\n");
2767         return;
2768     }
2769 
2770     if (!ret)
2771     {
2772         /* We have 1 or more printers */
2773         ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "gle %d\n", GetLastError());
2774         ok(neededW > 0, "Expected neededW to show the number of needed bytes\n");
2775     }
2776     else
2777     {
2778         /* We don't have any printers defined */
2779         ok(GetLastError() == S_OK, "gle %d\n", GetLastError());
2780         ok(neededW == 0, "Expected neededW to be zero\n");
2781     }
2782     ok(num == 0, "num %d\n", num);
2783 
2784     /* Outlook2003 relies on the buffer size returned by EnumPrintersA being big enough
2785        to hold the buffer returned by EnumPrintersW */
2786     ok(neededA == neededW, "neededA %d neededW %d\n", neededA, neededW);
2787 }
2788 
2789 static void test_DeviceCapabilities(void)
2790 {
2791     HANDLE hComdlg32;
2792     BOOL (WINAPI *pPrintDlgA)(PRINTDLGA *);
2793     PRINTDLGA prn_dlg;
2794     DEVMODEA *dm;
2795     DEVNAMES *dn;
2796     const char *driver, *device, *port;
2797     WORD *papers;
2798     POINT *paper_size;
2799     POINTS ext;
2800     struct
2801     {
2802         char name[64];
2803     } *paper_name;
2804     INT n_papers, n_paper_size, n_paper_names, n_copies, ret;
2805     DWORD fields;
2806 
2807     hComdlg32 = LoadLibraryA("comdlg32.dll");
2808     assert(hComdlg32);
2809     pPrintDlgA = (void *)GetProcAddress(hComdlg32, "PrintDlgA");
2810     assert(pPrintDlgA);
2811 
2812     memset(&prn_dlg, 0, sizeof(prn_dlg));
2813     prn_dlg.lStructSize = sizeof(prn_dlg);
2814     prn_dlg.Flags = PD_RETURNDEFAULT;
2815     ret = pPrintDlgA(&prn_dlg);
2816     FreeLibrary(hComdlg32);
2817     if (!ret)
2818     {
2819         skip("PrintDlg returned no default printer\n");
2820         return;
2821     }
2822     ok(prn_dlg.hDevMode != 0, "PrintDlg returned hDevMode == NULL\n");
2823     ok(prn_dlg.hDevNames != 0, "PrintDlg returned hDevNames == NULL\n");
2824 
2825     dm = GlobalLock(prn_dlg.hDevMode);
2826     ok(dm != NULL, "GlobalLock(prn_dlg.hDevMode) failed\n");
2827     trace("dmDeviceName \"%s\"\n", dm->dmDeviceName);
2828 
2829     dn = GlobalLock(prn_dlg.hDevNames);
2830     ok(dn != NULL, "GlobalLock(prn_dlg.hDevNames) failed\n");
2831     ok(dn->wDriverOffset, "expected not 0 wDriverOffset\n");
2832     ok(dn->wDeviceOffset, "expected not 0 wDeviceOffset\n");
2833     ok(dn->wOutputOffset, "expected not 0 wOutputOffset\n");
2834     ok(dn->wDefault == DN_DEFAULTPRN, "expected DN_DEFAULTPRN got %x\n", dn->wDefault);
2835     driver = (const char *)dn + dn->wDriverOffset;
2836     device = (const char *)dn + dn->wDeviceOffset;
2837     port = (const char *)dn + dn->wOutputOffset;
2838     trace("driver \"%s\" device \"%s\" port \"%s\"\n", driver, device, port);
2839 
2840     test_DEVMODEA(dm, dm->dmSize + dm->dmDriverExtra, device);
2841 
2842     n_papers = DeviceCapabilitiesA(device, port, DC_PAPERS, NULL, NULL);
2843     ok(n_papers > 0, "DeviceCapabilitiesA DC_PAPERS failed\n");
2844     papers = HeapAlloc(GetProcessHeap(), 0, sizeof(*papers) * n_papers);
2845     ret = DeviceCapabilitiesA(device, port, DC_PAPERS, (LPSTR)papers, NULL);
2846     ok(ret == n_papers, "expected %d, got %d\n", n_papers, ret);
2847 #ifdef VERBOSE
2848     for (ret = 0; ret < n_papers; ret++)
2849         trace("papers[%d] = %d\n", ret, papers[ret]);
2850 #endif
2851     HeapFree(GetProcessHeap(), 0, papers);
2852 
2853     n_paper_size = DeviceCapabilitiesA(device, port, DC_PAPERSIZE, NULL, NULL);
2854     ok(n_paper_size > 0, "DeviceCapabilitiesA DC_PAPERSIZE failed\n");
2855     ok(n_paper_size == n_papers, "n_paper_size %d != n_papers %d\n", n_paper_size, n_papers);
2856     paper_size = HeapAlloc(GetProcessHeap(), 0, sizeof(*paper_size) * n_paper_size);
2857     ret = DeviceCapabilitiesA(device, port, DC_PAPERSIZE, (LPSTR)paper_size, NULL);
2858     ok(ret == n_paper_size, "expected %d, got %d\n", n_paper_size, ret);
2859 #ifdef VERBOSE
2860     for (ret = 0; ret < n_paper_size; ret++)
2861         trace("paper_size[%d] = %d x %d\n", ret, paper_size[ret].x, paper_size[ret].y);
2862 #endif
2863     HeapFree(GetProcessHeap(), 0, paper_size);
2864 
2865     n_paper_names = DeviceCapabilitiesA(device, port, DC_PAPERNAMES, NULL, NULL);
2866     ok(n_paper_names > 0, "DeviceCapabilitiesA DC_PAPERNAMES failed\n");
2867     ok(n_paper_names == n_papers, "n_paper_names %d != n_papers %d\n", n_paper_names, n_papers);
2868     paper_name = HeapAlloc(GetProcessHeap(), 0, sizeof(*paper_name) * n_paper_names);
2869     ret = DeviceCapabilitiesA(device, port, DC_PAPERNAMES, (LPSTR)paper_name, NULL);
2870     ok(ret == n_paper_names, "expected %d, got %d\n", n_paper_names, ret);
2871 #ifdef VERBOSE
2872     for (ret = 0; ret < n_paper_names; ret++)
2873         trace("paper_name[%u] = %s\n", ret, paper_name[ret].name);
2874 #endif
2875     HeapFree(GetProcessHeap(), 0, paper_name);
2876 
2877     n_copies = DeviceCapabilitiesA(device, port, DC_COPIES, NULL, dm);
2878     ok(n_copies > 0, "DeviceCapabilitiesA DC_COPIES failed\n");
2879     trace("n_copies = %d\n", n_copies);
2880 
2881     /* these capabilities are not available on all printer drivers */
2882     if (0)
2883     {
2884         ret = DeviceCapabilitiesA(device, port, DC_MAXEXTENT, NULL, NULL);
2885         ok(ret != -1, "DeviceCapabilitiesA DC_MAXEXTENT failed\n");
2886         ext = MAKEPOINTS(ret);
2887         trace("max ext = %d x %d\n", ext.x, ext.y);
2888 
2889         ret = DeviceCapabilitiesA(device, port, DC_MINEXTENT, NULL, NULL);
2890         ok(ret != -1, "DeviceCapabilitiesA DC_MINEXTENT failed\n");
2891         ext = MAKEPOINTS(ret);
2892         trace("min ext = %d x %d\n", ext.x, ext.y);
2893     }
2894 
2895     fields = DeviceCapabilitiesA(device, port, DC_FIELDS, NULL, NULL);
2896     ok(fields != (DWORD)-1, "DeviceCapabilitiesA DC_FIELDS failed\n");
2897     ok(fields == (dm->dmFields | DM_FORMNAME) ||
2898        fields == ((dm->dmFields | DM_FORMNAME | DM_PAPERSIZE) & ~(DM_PAPERLENGTH|DM_PAPERWIDTH)) ||
2899         broken(fields == dm->dmFields), /* Win9x/WinMe */
2900         "fields %x, dm->dmFields %x\n", fields, dm->dmFields);
2901 
2902     GlobalUnlock(prn_dlg.hDevMode);
2903     GlobalFree(prn_dlg.hDevMode);
2904     GlobalUnlock(prn_dlg.hDevNames);
2905     GlobalFree(prn_dlg.hDevNames);
2906 }
2907 
2908 static void test_IsValidDevmodeW(void)
2909 {
2910     BOOL br;
2911 
2912     if (!pIsValidDevmodeW)
2913     {
2914         win_skip("IsValidDevmodeW not implemented.\n");
2915         return;
2916     }
2917 
2918     br = pIsValidDevmodeW(NULL, 0);
2919     ok(br == FALSE, "Got %d\n", br);
2920 
2921     br = pIsValidDevmodeW(NULL, 1);
2922     ok(br == FALSE, "Got %d\n", br);
2923 
2924     br = pIsValidDevmodeW(NULL, sizeof(DEVMODEW));
2925     ok(br == FALSE, "Got %d\n", br);
2926 }
2927 
2928 static void test_OpenPrinter_defaults(void)
2929 {
2930     HANDLE printer;
2931     BOOL ret;
2932     DWORD needed;
2933     short default_size;
2934     ADDJOB_INFO_1A *add_job;
2935     JOB_INFO_2A *job_info;
2936     DEVMODEA my_dm;
2937     PRINTER_DEFAULTSA prn_def;
2938     PRINTER_INFO_2A *pi;
2939 
2940     if (!default_printer)
2941     {
2942         skip("There is no default printer installed\n");
2943         return;
2944     }
2945 
2946     /* Printer opened with NULL defaults.  Retrieve default paper size
2947        and confirm that jobs have this size. */
2948 
2949     ret = OpenPrinterA( default_printer, &printer, NULL );
2950     if (!ret)
2951     {
2952         skip("Unable to open the default printer (%s)\n", default_printer);
2953         return;
2954     }
2955 
2956     ret = GetPrinterA( printer, 2, NULL, 0, &needed );
2957     ok( !ret, "got %d\n", ret );
2958     pi = HeapAlloc( GetProcessHeap(), 0, needed );
2959     ret = GetPrinterA( printer, 2, (BYTE *)pi, needed, &needed );
2960     ok( ret, "GetPrinterA() failed le=%d\n", GetLastError() );
2961     default_size = pi->pDevMode->u1.s1.dmPaperSize;
2962     HeapFree( GetProcessHeap(), 0, pi );
2963 
2964     needed = 0;
2965     SetLastError( 0xdeadbeef );
2966     ret = AddJobA( printer, 1, NULL, 0, &needed );
2967     ok( !ret, "got %d\n", ret );
2968     if (GetLastError() == ERROR_NOT_SUPPORTED) /* win8 */
2969     {
2970         win_skip( "AddJob is not supported on this platform\n" );
2971         ClosePrinter( printer );
2972         return;
2973     }
2974     ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError() );
2975     ok( needed > sizeof(ADDJOB_INFO_1A), "AddJob needs %u bytes\n", needed);
2976     add_job = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, needed );
2977     ret = AddJobA( printer, 1, (BYTE *)add_job, needed, &needed );
2978     ok( ret, "AddJobA() failed le=%d\n", GetLastError() );
2979 
2980     ret = GetJobA( printer, add_job->JobId, 2, NULL, 0, &needed );
2981     ok( !ret, "got %d\n", ret );
2982     job_info = HeapAlloc( GetProcessHeap(), 0, needed );
2983     ret = GetJobA( printer, add_job->JobId, 2, (BYTE *)job_info, needed, &needed );
2984     ok( ret, "GetJobA() failed le=%d\n", GetLastError() );
2985 
2986 todo_wine
2987     ok( job_info->pDevMode != NULL, "got NULL DEVMODEA\n");
2988     if (job_info->pDevMode)
2989         ok( job_info->pDevMode->u1.s1.dmPaperSize == default_size, "got %d default %d\n",
2990             job_info->pDevMode->u1.s1.dmPaperSize, default_size );
2991 
2992     HeapFree( GetProcessHeap(), 0, job_info );
2993     ScheduleJob( printer, add_job->JobId ); /* remove the empty job */
2994     HeapFree( GetProcessHeap(), 0, add_job );
2995     ClosePrinter( printer );
2996 
2997     /* Printer opened with something other than the default paper size. */
2998 
2999     memset( &my_dm, 0, sizeof(my_dm) );
3000     my_dm.dmSize = sizeof(my_dm);
3001     my_dm.dmFields = DM_PAPERSIZE;
3002     my_dm.u1.s1.dmPaperSize = (default_size == DMPAPER_A4) ? DMPAPER_LETTER : DMPAPER_A4;
3003 
3004     prn_def.pDatatype = NULL;
3005     prn_def.pDevMode = &my_dm;
3006     prn_def.DesiredAccess = PRINTER_ACCESS_USE;
3007 
3008     ret = OpenPrinterA( default_printer, &printer, &prn_def );
3009     ok( ret, "OpenPrinterA() failed le=%d\n", GetLastError() );
3010 
3011     /* GetPrinter stills returns default size */
3012     ret = GetPrinterA( printer, 2, NULL, 0, &needed );
3013     ok( !ret, "got %d\n", ret );
3014     pi = HeapAlloc( GetProcessHeap(), 0, needed );
3015     ret = GetPrinterA( printer, 2, (BYTE *)pi, needed, &needed );
3016     ok( ret, "GetPrinterA() failed le=%d\n", GetLastError() );
3017     ok( pi->pDevMode->u1.s1.dmPaperSize == default_size, "got %d default %d\n",
3018         pi->pDevMode->u1.s1.dmPaperSize, default_size );
3019 
3020     HeapFree( GetProcessHeap(), 0, pi );
3021 
3022     /* However the GetJobA has the new size */
3023     ret = AddJobA( printer, 1, NULL, 0, &needed );
3024     ok( !ret, "got %d\n", ret );
3025     add_job = HeapAlloc( GetProcessHeap(), 0, needed );
3026     ret = AddJobA( printer, 1, (BYTE *)add_job, needed, &needed );
3027     ok( ret, "AddJobA() failed le=%d\n", GetLastError() );
3028 
3029     ret = GetJobA( printer, add_job->JobId, 2, NULL, 0, &needed );
3030     ok( !ret, "got %d\n", ret );
3031     job_info = HeapAlloc( GetProcessHeap(), 0, needed );
3032     ret = GetJobA( printer, add_job->JobId, 2, (BYTE *)job_info, needed, &needed );
3033     ok( ret, "GetJobA() failed le=%d\n", GetLastError() );
3034 
3035     ok( job_info->pDevMode->dmFields == DM_PAPERSIZE, "got %08x\n",
3036         job_info->pDevMode->dmFields );
3037     ok( job_info->pDevMode->u1.s1.dmPaperSize == my_dm.u1.s1.dmPaperSize,
3038         "got %d new size %d\n",
3039         job_info->pDevMode->u1.s1.dmPaperSize, my_dm.u1.s1.dmPaperSize );
3040 
3041     HeapFree( GetProcessHeap(), 0, job_info );
3042     ScheduleJob( printer, add_job->JobId ); /* remove the empty job */
3043     HeapFree( GetProcessHeap(), 0, add_job );
3044     ClosePrinter( printer );
3045 }
3046 
3047 START_TEST(info)
3048 {
3049     hwinspool = LoadLibraryA("winspool.drv");
3050     pAddPortExA = (void *) GetProcAddress(hwinspool, "AddPortExA");
3051     pEnumPrinterDriversW = (void *) GetProcAddress(hwinspool, "EnumPrinterDriversW");
3052     pGetDefaultPrinterA = (void *) GetProcAddress(hwinspool, "GetDefaultPrinterA");
3053     pGetPrinterDataExA = (void *) GetProcAddress(hwinspool, "GetPrinterDataExA");
3054     pGetPrinterDriverW = (void *) GetProcAddress(hwinspool, "GetPrinterDriverW");
3055     pGetPrinterW = (void *) GetProcAddress(hwinspool, "GetPrinterW");
3056     pSetDefaultPrinterA = (void *) GetProcAddress(hwinspool, "SetDefaultPrinterA");
3057     pXcvDataW = (void *) GetProcAddress(hwinspool, "XcvDataW");
3058     pIsValidDevmodeW = (void *) GetProcAddress(hwinspool, "IsValidDevmodeW");
3059 
3060     on_win9x = check_win9x();
3061     if (on_win9x)
3062         win_skip("Several W-functions are not available on Win9x/WinMe\n");
3063 
3064     find_default_printer();
3065     find_local_server();
3066     find_tempfile();
3067 
3068     test_AddMonitor();
3069     test_AddPort();
3070     test_AddPortEx();
3071     test_ConfigurePort();
3072     test_ClosePrinter();
3073     test_DeleteMonitor();
3074     test_DeletePort();
3075     test_DeviceCapabilities();
3076     test_DocumentProperties();
3077     test_EnumForms(NULL);
3078     if (default_printer) test_EnumForms(default_printer);
3079     test_EnumMonitors();
3080 
3081     if (!winetest_interactive)
3082         skip("ROSTESTS-211: Skipping test_EnumPorts().\n");
3083     else
3084         test_EnumPorts();
3085 
3086     test_EnumPrinterDrivers();
3087     test_EnumPrinters();
3088 
3089     if (!winetest_interactive)
3090         skip("ROSTESTS-211: Skipping test_EnumPrintProcessors().\n");
3091     else
3092         test_EnumPrintProcessors();
3093 
3094     test_GetDefaultPrinter();
3095     test_GetPrinterDriverDirectory();
3096     test_GetPrintProcessorDirectory();
3097     test_IsValidDevmodeW();
3098     test_OpenPrinter();
3099     test_OpenPrinter_defaults();
3100     test_GetPrinter();
3101     test_GetPrinterData();
3102     test_GetPrinterDataEx();
3103     test_GetPrinterDriver();
3104     test_SetDefaultPrinter();
3105     test_XcvDataW_MonitorUI();
3106     test_XcvDataW_PortIsValid();
3107 
3108     /* Cleanup our temporary file */
3109     DeleteFileA(tempfileA);
3110 }
3111