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