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