wintrust: Use helper function for setting confidence in SoftpubCheckCert.
[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 does_not_exist_dll[]= "does_not_exist.dll";
42 static CHAR does_not_exist[]    = "does_not_exist";
43 static CHAR empty[]             = "";
44 static CHAR env_x86[]           = "Windows NT x86";
45 static CHAR env_win9x_case[]    = "windowS 4.0";
46 static CHAR illegal_name[]      = "illegal,name";
47 static CHAR invalid_env[]       = "invalid_env";
48 static CHAR LocalPortA[]        = "Local Port";
49 static CHAR portname_com1[]     = "COM1:";
50 static CHAR portname_file[]     = "FILE:";
51 static CHAR portname_lpt1[]     = "LPT1:";
52 static CHAR server_does_not_exist[] = "\\does_not_exist";
53 static CHAR version_dll[]       = "version.dll";
54 static CHAR winetest[]          = "winetest";
55 static CHAR xcv_localport[]     = ",XcvMonitor Local Port";
56
57 static WCHAR cmd_MonitorUIW[] = {'M','o','n','i','t','o','r','U','I',0};
58 static WCHAR cmd_PortIsValidW[] = {'P','o','r','t','I','s','V','a','l','i','d',0};
59 static WCHAR emptyW[] = {0};
60
61 static WCHAR portname_com1W[] = {'C','O','M','1',':',0};
62 static WCHAR portname_com2W[] = {'C','O','M','2',':',0};
63 static WCHAR portname_fileW[] = {'F','I','L','E',':',0};
64 static WCHAR portname_lpt1W[] = {'L','P','T','1',':',0};
65 static WCHAR portname_lpt2W[] = {'L','P','T','2',':',0};
66
67 static HANDLE  hwinspool;
68 static BOOL  (WINAPI * pGetDefaultPrinterA)(LPSTR, LPDWORD);
69 static BOOL  (WINAPI * pSetDefaultPrinterA)(LPCSTR);
70 static DWORD (WINAPI * pXcvDataW)(HANDLE, LPCWSTR, PBYTE, DWORD, PBYTE, DWORD, PDWORD, PDWORD);
71 static BOOL  (WINAPI * pAddPortExA)(LPSTR, DWORD, LPBYTE, LPSTR);
72
73
74 /* ################################ */
75
76 struct monitor_entry {
77     LPSTR  env;
78     CHAR  dllname[32];
79 };
80
81 static LPSTR default_printer = NULL;
82 static LPSTR local_server = NULL;
83 static LPSTR tempdirA = NULL;
84 static LPSTR tempfileA = NULL;
85 static LPWSTR tempdirW = NULL;
86 static LPWSTR tempfileW = NULL;
87
88 /* ################################ */
89 /* report common behavior only once */
90 static DWORD deactivated_spooler_reported = 0;
91 #define RETURN_ON_DEACTIVATED_SPOOLER(res) \
92     if ((res == 0) && (GetLastError() == RPC_S_SERVER_UNAVAILABLE)) \
93     { \
94         if (!deactivated_spooler_reported) { \
95             deactivated_spooler_reported++; \
96             skip("The Service 'Spooler' is required for many test\n"); \
97         } \
98         return; \
99     }
100
101 static DWORD access_denied_reported = 0;
102 #define RETURN_ON_ACCESS_DENIED(res) \
103     if ((res == 0) && (GetLastError() == ERROR_ACCESS_DENIED)) \
104     { \
105         if (!access_denied_reported) { \
106             access_denied_reported++; \
107             skip("More Access-Rights are required for many test\n"); \
108         } \
109         return; \
110     }
111
112 /* ################################ */
113
114 static void find_default_printer(VOID)
115 {
116     static  char    buffer[DEFAULT_PRINTER_SIZE];
117     DWORD   needed;
118     DWORD   res;
119     LPSTR   ptr;
120
121     if ((default_printer == NULL) && (pGetDefaultPrinterA))
122     {
123         /* w2k and above */
124         needed = sizeof(buffer);
125         res = pGetDefaultPrinterA(buffer, &needed);
126         if(res)  default_printer = buffer;
127         trace("default_printer: '%s'\n", default_printer);
128     }
129     if (default_printer == NULL)
130     {
131         HKEY hwindows;
132         DWORD   type;
133         /* NT 3.x and above */
134         if (RegOpenKeyEx(HKEY_CURRENT_USER, 
135                         "Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows",
136                         0, KEY_QUERY_VALUE, &hwindows) == NO_ERROR) {
137
138             needed = sizeof(buffer);
139             if (RegQueryValueEx(hwindows, "device", NULL, 
140                                 &type, (LPBYTE)buffer, &needed) == NO_ERROR) {
141
142                 ptr = strchr(buffer, ',');
143                 if (ptr) {
144                     ptr[0] = '\0';
145                     default_printer = buffer;
146                 }
147             }
148             RegCloseKey(hwindows);
149         }
150         trace("default_printer: '%s'\n", default_printer);
151     }
152     if (default_printer == NULL)
153     {
154         /* win9x */
155         needed = sizeof(buffer);
156         res = GetProfileStringA("windows", "device", "*", buffer, needed);
157         if(res) {
158             ptr = strchr(buffer, ',');
159             if (ptr) {
160                 ptr[0] = '\0';
161                 default_printer = buffer;
162             }
163         }
164         trace("default_printer: '%s'\n", default_printer);
165     }
166 }
167
168
169 static struct monitor_entry * find_installed_monitor(void)
170 {
171     MONITOR_INFO_2A mi2a; 
172     static struct  monitor_entry * entry = NULL;
173     DWORD   num_tests;
174     DWORD   i = 0;
175
176     static struct monitor_entry  monitor_table[] = {
177         {env_win9x_case, "localspl.dll"},
178         {env_x86,        "localspl.dll"},
179         {env_win9x_case, "localmon.dll"},
180         {env_x86,        "localmon.dll"},
181         {env_win9x_case, "tcpmon.dll"},
182         {env_x86,        "tcpmon.dll"},
183         {env_win9x_case, "usbmon.dll"},
184         {env_x86,        "usbmon.dll"},
185         {env_win9x_case, "mspp32.dll"},
186         {env_x86,        "win32spl.dll"},
187         {env_x86,        "redmonnt.dll"},
188         {env_x86,        "redmon35.dll"},
189         {env_win9x_case, "redmon95.dll"},
190         {env_x86,        "pdfcmnnt.dll"},
191         {env_win9x_case, "pdfcmn95.dll"},
192     };
193
194     if (entry) return entry;
195
196     num_tests = (sizeof(monitor_table)/sizeof(struct monitor_entry));
197
198     /* cleanup */
199     DeleteMonitorA(NULL, env_x86, winetest);
200     DeleteMonitorA(NULL, env_win9x_case, winetest);
201
202     /* find a usable monitor from the table */
203     mi2a.pName = winetest;
204     while ((entry == NULL) && (i < num_tests)) {
205         entry = &monitor_table[i];
206         i++;
207         mi2a.pEnvironment = entry->env;
208         mi2a.pDLLName = entry->dllname;
209
210         if (AddMonitorA(NULL, 2, (LPBYTE) &mi2a)) {
211             /* we got one */
212             trace("using '%s', '%s'\n", entry->env, entry->dllname);
213             DeleteMonitorA(NULL, entry->env, winetest);
214         }
215         else
216         {
217             entry = NULL;
218         }
219     }
220     return entry;
221 }
222
223
224 /* ########################### */
225
226 static void find_local_server(VOID)
227 {
228     static  char    buffer[MAX_PATH];
229     DWORD   res;
230     DWORD   size;
231
232     size = sizeof(buffer) - 3 ;
233     buffer[0] = '\\';
234     buffer[1] = '\\';
235     buffer[2] = '\0';
236
237     SetLastError(0xdeadbeef);
238     res = GetComputerNameA(&buffer[2], &size);
239     trace("returned %d with %d and %d: '%s'\n", res, GetLastError(), size, buffer);
240
241     ok( res != 0, "returned %d with %d and %d: '%s' (expected '!= 0')\n",
242         res, GetLastError(), size, buffer);
243
244     if (res) local_server = buffer;
245 }
246
247 /* ########################### */
248
249 static void find_tempfile(VOID)
250 {
251     static CHAR buffer_dirA[MAX_PATH];
252     static CHAR buffer_fileA[MAX_PATH];
253     static WCHAR buffer_dirW[MAX_PATH];
254     static WCHAR buffer_fileW[MAX_PATH];
255     DWORD   res;
256     int     resint;
257
258     memset(buffer_dirA, 0, MAX_PATH - 1);
259     buffer_dirA[MAX_PATH - 1] = '\0';
260     SetLastError(0xdeadbeef);
261     res = GetTempPathA(MAX_PATH, buffer_dirA);
262     ok(res, "returned %u with %u and '%s' (expected '!= 0')\n", res, GetLastError(), buffer_dirA);
263     if (res == 0) return;
264
265     memset(buffer_fileA, 0, MAX_PATH - 1);
266     buffer_fileA[MAX_PATH - 1] = '\0';
267     SetLastError(0xdeadbeef);
268     res = GetTempFileNameA(buffer_dirA, winetest, 0, buffer_fileA);
269     ok(res, "returned %u with %u and '%s' (expected '!= 0')\n", res, GetLastError(), buffer_fileA);
270     if (res == 0) return;
271
272     SetLastError(0xdeadbeef);
273     resint = MultiByteToWideChar(CP_ACP, 0, buffer_dirA, -1, buffer_dirW, MAX_PATH);
274     ok(res, "returned %u with %u (expected '!= 0')\n", resint, GetLastError());
275     if (resint == 0) return;
276
277     SetLastError(0xdeadbeef);
278     resint = MultiByteToWideChar(CP_ACP, 0, buffer_fileA, -1, buffer_fileW, MAX_PATH);
279     ok(res, "returned %u with %u (expected '!= 0')\n", resint, GetLastError());
280     if (resint == 0) return;
281
282     tempdirA  = buffer_dirA;
283     tempfileA = buffer_fileA;
284     tempdirW  = buffer_dirW;
285     tempfileW = buffer_fileW;
286     trace("tempfile: '%s'\n", tempfileA);
287 }
288
289 /* ########################### */
290
291 static void test_AddMonitor(void)
292 {
293     MONITOR_INFO_2A mi2a; 
294     struct  monitor_entry * entry = NULL;
295     DWORD   res;
296
297     entry = find_installed_monitor();
298
299     SetLastError(MAGIC_DEAD);
300     res = AddMonitorA(NULL, 1, NULL);
301     ok(!res && (GetLastError() == ERROR_INVALID_LEVEL), 
302         "returned %d with %d (expected '0' with ERROR_INVALID_LEVEL)\n",
303         res, GetLastError());
304
305     SetLastError(MAGIC_DEAD);
306     res = AddMonitorA(NULL, 3, NULL);
307     ok(!res && (GetLastError() == ERROR_INVALID_LEVEL), 
308         "returned %d with %d (expected '0' with ERROR_INVALID_LEVEL)\n",
309         res, GetLastError());
310
311     if (0)
312     {
313     /* This test crash with win9x on vmware (works with win9x on qemu 0.8.1) */
314     SetLastError(MAGIC_DEAD);
315     res = AddMonitorA(NULL, 2, NULL);
316     /* NT: unchanged,  9x: ERROR_PRIVILEGE_NOT_HELD */
317     ok(!res &&
318         ((GetLastError() == MAGIC_DEAD) ||
319          (GetLastError() == ERROR_PRIVILEGE_NOT_HELD)), 
320         "returned %d with %d (expected '0' with: MAGIC_DEAD or "
321         "ERROR_PRIVILEGE_NOT_HELD)\n", res, GetLastError());
322     }
323
324     ZeroMemory(&mi2a, sizeof(MONITOR_INFO_2A));
325     SetLastError(MAGIC_DEAD);
326     res = AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
327     RETURN_ON_DEACTIVATED_SPOOLER(res)
328     RETURN_ON_ACCESS_DENIED(res)
329
330     /* NT: ERROR_INVALID_PARAMETER,  9x: ERROR_INVALID_ENVIRONMENT */
331     ok(!res && ((GetLastError() == ERROR_INVALID_PARAMETER) ||
332                 (GetLastError() == ERROR_INVALID_ENVIRONMENT)), 
333         "returned %d with %d (expected '0' with: ERROR_INVALID_PARAMETER or "
334         "ERROR_INVALID_ENVIRONMENT)\n", res, GetLastError());
335
336     if (!entry) {
337         skip("No usable Monitor found\n");
338         return;
339     }
340
341     if (0)
342     {
343     /* The Test is deactivated, because when mi2a.pName is NULL, the subkey
344        HKLM\System\CurrentControlSet\Control\Print\Monitors\C:\WINDOWS\SYSTEM
345        or HKLM\System\CurrentControlSet\Control\Print\Monitors\ì
346        is created on win9x and we do not want to hit this bug here. */
347
348     mi2a.pEnvironment = entry->env;
349     SetLastError(MAGIC_DEAD);
350     res = AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
351     /* NT: ERROR_INVALID_PARAMETER,  9x: ERROR_PRIVILEGE_NOT_HELD */
352     }
353
354     mi2a.pEnvironment = entry->env;
355     mi2a.pName = empty;
356     SetLastError(MAGIC_DEAD);
357     res = AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
358     /* NT: ERROR_INVALID_PARAMETER,  9x: ERROR_PRIVILEGE_NOT_HELD */
359     ok( !res &&
360         ((GetLastError() == ERROR_INVALID_PARAMETER) ||
361          (GetLastError() == ERROR_PRIVILEGE_NOT_HELD)), 
362         "returned %d with %d (expected '0' with: ERROR_INVALID_PARAMETER or "
363         "ERROR_PRIVILEGE_NOT_HELD)\n",
364         res, GetLastError());
365
366     mi2a.pName = winetest;
367     SetLastError(MAGIC_DEAD);
368     res = AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
369     /* NT: ERROR_INVALID_PARAMETER,  9x: ERROR_PRIVILEGE_NOT_HELD */
370     ok( !res &&
371         ((GetLastError() == ERROR_INVALID_PARAMETER) ||
372          (GetLastError() == ERROR_PRIVILEGE_NOT_HELD)), 
373         "returned %d with %d (expected '0' with: ERROR_INVALID_PARAMETER or "
374         "ERROR_PRIVILEGE_NOT_HELD)\n",
375         res, GetLastError());
376
377     mi2a.pDLLName = empty;
378     SetLastError(MAGIC_DEAD);
379     res = AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
380     ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
381         "returned %d with %d (expected '0' with ERROR_INVALID_PARAMETER)\n",
382         res, GetLastError());
383
384     mi2a.pDLLName = does_not_exist_dll;
385     SetLastError(MAGIC_DEAD);
386     res = AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
387     /* NT: ERROR_MOD_NOT_FOUND,  9x: ERROR_INVALID_PARAMETER */
388     ok( !res &&
389         ((GetLastError() == ERROR_MOD_NOT_FOUND) ||
390         (GetLastError() == ERROR_INVALID_PARAMETER)),
391         "returned %d with %d (expected '0' with: ERROR_MOD_NOT_FOUND or "
392         "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
393
394     mi2a.pDLLName = version_dll;
395     SetLastError(MAGIC_DEAD);
396     res = AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
397     /* NT: ERROR_PROC_NOT_FOUND,  9x: ERROR_INVALID_PARAMETER */
398     ok( !res &&
399         ((GetLastError() == ERROR_PROC_NOT_FOUND) ||
400         (GetLastError() == ERROR_INVALID_PARAMETER)),
401         "returned %d with %d (expected '0' with: ERROR_PROC_NOT_FOUND or "
402         "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
403     if (res) DeleteMonitorA(NULL, entry->env, winetest);
404
405    /* Test AddMonitor with real options */
406     mi2a.pDLLName = entry->dllname;
407     SetLastError(MAGIC_DEAD);
408     res = AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
409     ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError());
410
411     /* add a monitor twice */
412     SetLastError(MAGIC_DEAD);
413     res = AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
414     /* NT: ERROR_PRINT_MONITOR_ALREADY_INSTALLED (3006), 9x: ERROR_ALREADY_EXISTS (183) */
415     ok( !res &&
416         ((GetLastError() == ERROR_PRINT_MONITOR_ALREADY_INSTALLED) ||
417         (GetLastError() == ERROR_ALREADY_EXISTS)), 
418         "returned %d with %d (expected '0' with: "
419         "ERROR_PRINT_MONITOR_ALREADY_INSTALLED or ERROR_ALREADY_EXISTS)\n",
420         res, GetLastError());
421
422     DeleteMonitorA(NULL, entry->env, winetest);
423     SetLastError(MAGIC_DEAD);
424     res = AddMonitorA(empty, 2, (LPBYTE) &mi2a);
425     ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError());
426
427     /* cleanup */
428     DeleteMonitorA(NULL, entry->env, winetest);
429
430 }
431
432 /* ########################### */
433
434 static void test_AddPort(void)
435 {
436     DWORD   res;
437
438     SetLastError(0xdeadbeef);
439     res = AddPortA(NULL, 0, NULL);
440     RETURN_ON_DEACTIVATED_SPOOLER(res)
441     /* NT: RPC_X_NULL_REF_POINTER, 9x: ERROR_INVALID_PARAMETER */
442     ok( !res && ((GetLastError() == RPC_X_NULL_REF_POINTER) || 
443                  (GetLastError() == ERROR_INVALID_PARAMETER)),
444         "returned %d with %d (expected '0' with ERROR_NOT_SUPPORTED or "
445         "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
446
447
448     SetLastError(0xdeadbeef);
449     res = AddPortA(NULL, 0, empty);
450     /* Allowed only for (Printer-)Administrators */
451     RETURN_ON_ACCESS_DENIED(res)
452
453     /* XP: ERROR_NOT_SUPPORTED, NT351 and 9x: ERROR_INVALID_PARAMETER */
454     ok( !res && ((GetLastError() == ERROR_NOT_SUPPORTED) || 
455                  (GetLastError() == ERROR_INVALID_PARAMETER)),
456         "returned %d with %d (expected '0' with ERROR_NOT_SUPPORTED or "
457         "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
458
459
460     SetLastError(0xdeadbeef);
461     res = AddPortA(NULL, 0, does_not_exist);
462     /* XP: ERROR_NOT_SUPPORTED, NT351 and 9x: ERROR_INVALID_PARAMETER */
463     ok( !res && ((GetLastError() == ERROR_NOT_SUPPORTED) || 
464                  (GetLastError() == ERROR_INVALID_PARAMETER)),
465         "returned %d with %d (expected '0' with ERROR_NOT_SUPPORTED or "
466         "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
467
468 }
469
470 /* ########################### */
471
472 static void test_AddPortEx(void)
473 {
474     PORT_INFO_2A pi;
475     DWORD   res;
476
477
478     if (!pAddPortExA) {
479         skip("AddPortEx not supported\n");
480         return;
481     }
482
483     /* start test with a clean system */
484     DeletePortA(NULL, 0, tempfileA);
485
486     pi.pPortName = tempfileA;
487     SetLastError(0xdeadbeef);
488     res = pAddPortExA(NULL, 1, (LPBYTE) &pi, LocalPortA);
489     RETURN_ON_DEACTIVATED_SPOOLER(res)
490
491     /* Allowed only for (Printer-)Administrators.
492        W2K+XP: ERROR_INVALID_PARAMETER  */
493     if (!res && (GetLastError() == ERROR_INVALID_PARAMETER)) {
494         skip("ACCESS_DENIED (ERROR_INVALID_PARAMETER)\n");
495         return;
496     }
497     ok( res, "got %u with %u (expected '!= 0')\n", res, GetLastError());
498
499     /* Add a port, that already exist */
500     SetLastError(0xdeadbeef);
501     res = pAddPortExA(NULL, 1, (LPBYTE) &pi, LocalPortA);
502     ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
503         "got %u with %u (expected '0' with ERROR_INVALID_PARAMETER)\n",
504         res, GetLastError());
505     DeletePortA(NULL, 0, tempfileA);
506
507
508     /* the Monitorname must match */
509     SetLastError(0xdeadbeef);
510     res = pAddPortExA(NULL, 1, (LPBYTE) &pi, NULL);
511     ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
512         "got %u with %u (expected '0' with ERROR_INVALID_PARAMETER)\n",
513         res, GetLastError());
514     if (res) DeletePortA(NULL, 0, tempfileA);
515
516     SetLastError(0xdeadbeef);
517     res = pAddPortExA(NULL, 1, (LPBYTE) &pi, empty);
518     ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
519         "got %u with %u (expected '0' with ERROR_INVALID_PARAMETER)\n",
520         res, GetLastError());
521     if (res) DeletePortA(NULL, 0, tempfileA);
522
523     SetLastError(0xdeadbeef);
524     res = pAddPortExA(NULL, 1, (LPBYTE) &pi, does_not_exist);
525     ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
526         "got %u with %u (expected '0' with ERROR_INVALID_PARAMETER)\n",
527         res, GetLastError());
528     if (res) DeletePortA(NULL, 0, tempfileA);
529
530
531     /* We need a Portname */
532     SetLastError(0xdeadbeef);
533     res = pAddPortExA(NULL, 1, NULL, LocalPortA);
534     ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
535         "got %u with %u (expected '0' with ERROR_INVALID_PARAMETER)\n",
536         res, GetLastError());
537
538     pi.pPortName = NULL;
539     SetLastError(0xdeadbeef);
540     res = pAddPortExA(NULL, 1, (LPBYTE) &pi, LocalPortA);
541     ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
542         "got %u with %u (expected '0' with ERROR_INVALID_PARAMETER)\n",
543         res, GetLastError());
544     if (res) DeletePortA(NULL, 0, tempfileA);
545
546
547     /*  level 2 is documented as supported for Printmonitors,
548         but that is not supported for "Local Port" (localspl.dll) and
549         AddPortEx fails with ERROR_INVALID_LEVEL */
550
551     pi.pPortName = tempfileA;
552     pi.pMonitorName = LocalPortA;
553     pi.pDescription = winetest;
554     pi.fPortType = PORT_TYPE_WRITE;
555
556     SetLastError(0xdeadbeef);
557     res = pAddPortExA(NULL, 2, (LPBYTE) &pi, LocalPortA);
558     ok( !res && (GetLastError() == ERROR_INVALID_LEVEL),
559         "got %u with %u (expected '0' with ERROR_INVALID_LEVEL)\n",
560         res, GetLastError());
561     if (res) DeletePortA(NULL, 0, tempfileA);
562
563
564     /* invalid levels */
565     SetLastError(0xdeadbeef);
566     res = pAddPortExA(NULL, 0, (LPBYTE) &pi, LocalPortA);
567     ok( !res && (GetLastError() == ERROR_INVALID_LEVEL),
568         "got %u with %u (expected '0' with ERROR_INVALID_LEVEL)\n",
569         res, GetLastError());
570
571     SetLastError(0xdeadbeef);
572     res = pAddPortExA(NULL, 3, (LPBYTE) &pi, LocalPortA);
573     ok( !res && (GetLastError() == ERROR_INVALID_LEVEL),
574         "got %u with %u (expected '0' with ERROR_INVALID_LEVEL)\n",
575         res, GetLastError());
576
577
578     /* cleanup */
579     DeletePortA(NULL, 0, tempfileA);
580
581 }
582
583 /* ########################### */
584
585 static void test_ConfigurePort(void)
586 {
587     DWORD   res;
588
589
590     SetLastError(0xdeadbeef);
591     res = ConfigurePortA(NULL, 0, NULL);
592     RETURN_ON_DEACTIVATED_SPOOLER(res)
593     /* NT: RPC_X_NULL_REF_POINTER, 9x: ERROR_INVALID_PARAMETER */
594     ok( !res && ((GetLastError() == RPC_X_NULL_REF_POINTER) || 
595                  (GetLastError() == ERROR_INVALID_PARAMETER)),
596         "returned %d with %d (expected '0' with ERROR_NOT_SUPPORTED or "
597         "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
598
599     SetLastError(0xdeadbeef);
600     res = ConfigurePortA(NULL, 0, empty);
601     /* Allowed only for (Printer-)Administrators */
602     RETURN_ON_ACCESS_DENIED(res)
603
604     /* XP: ERROR_NOT_SUPPORTED, NT351 and 9x: ERROR_INVALID_PARAMETER */
605     ok( !res && ((GetLastError() == ERROR_NOT_SUPPORTED) || 
606                  (GetLastError() == ERROR_INVALID_PARAMETER)),
607         "returned %d with %d (expected '0' with ERROR_NOT_SUPPORTED or "
608         "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
609
610
611     SetLastError(0xdeadbeef);
612     res = ConfigurePortA(NULL, 0, does_not_exist);
613     /* XP: ERROR_NOT_SUPPORTED, NT351 and 9x: ERROR_INVALID_PARAMETER */
614     ok( !res && ((GetLastError() == ERROR_NOT_SUPPORTED) || 
615                  (GetLastError() == ERROR_INVALID_PARAMETER)),
616         "returned %d with %d (expected '0' with ERROR_NOT_SUPPORTED or "
617         "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
618
619
620     /*  Testing-Results:
621         - Case of Portnames is ignored 
622         - Portname without ":" => NT: ERROR_NOT_SUPPORTED, 9x: Dialog comes up
623         - Empty Servername (LPT1:) => NT: ERROR_NOT_SUPPORTED, 9x: Dialog comes up
624
625         - Port not present =>  9x: ERROR_INVALID_PARAMETER, NT:ERROR_NOT_SUPPORTED
626         - "FILE:" => 9x:Success, NT:ERROR_CANCELED
627         - Cancel ("Local Port") => ERROR_CANCELED
628         - Cancel ("Redirected Port") => Success
629     */
630     if (winetest_interactive > 0) {
631         SetLastError(0xdeadbeef);
632         res = ConfigurePortA(NULL, 0, portname_com1);
633         trace("'%s' returned %d with %d\n", portname_com1, res, GetLastError());
634
635         SetLastError(0xdeadbeef);
636         res = ConfigurePortA(NULL, 0, portname_lpt1);
637         trace("'%s' returned %d with %d\n", portname_lpt1, res, GetLastError());
638
639         SetLastError(0xdeadbeef);
640         res = ConfigurePortA(NULL, 0, portname_file);
641         trace("'%s' returned %d with %d\n", portname_file, res, GetLastError());
642     }
643 }
644
645 /* ########################### */
646
647 static void test_DeleteMonitor(void)
648 {
649     MONITOR_INFO_2A         mi2a;
650     struct monitor_entry  * entry = NULL;
651     DWORD                   res;
652
653
654     entry = find_installed_monitor();
655
656     if (!entry) {
657         skip("No usable Monitor found\n");
658         return;
659     }
660
661     mi2a.pName = winetest;
662     mi2a.pEnvironment = entry->env;
663     mi2a.pDLLName = entry->dllname;
664
665     /* Testing DeleteMonitor with real options */
666     AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
667
668     SetLastError(MAGIC_DEAD);
669     res = DeleteMonitorA(NULL, entry->env, winetest);
670     ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError());
671
672     /* Delete the Monitor twice */
673     SetLastError(MAGIC_DEAD);
674     res = DeleteMonitorA(NULL, entry->env, winetest);
675     /* NT: ERROR_UNKNOWN_PRINT_MONITOR (3000), 9x: ERROR_INVALID_PARAMETER (87) */
676     ok( !res &&
677         ((GetLastError() == ERROR_UNKNOWN_PRINT_MONITOR) ||
678         (GetLastError() == ERROR_INVALID_PARAMETER)), 
679         "returned %d with %d (expected '0' with: ERROR_UNKNOWN_PRINT_MONITOR"
680         " or ERROR_INVALID_PARAMETER)\n", res, GetLastError());
681
682     /* the environment */
683     AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
684     SetLastError(MAGIC_DEAD);
685     res = DeleteMonitorA(NULL, NULL, winetest);
686     ok(res, "returned %d with %d (expected '!=0')\n", res, GetLastError());
687
688     AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
689     SetLastError(MAGIC_DEAD);
690     res = DeleteMonitorA(NULL, empty, winetest);
691     ok(res, "returned %d with %d (expected '!=0')\n", res, GetLastError());
692
693     AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
694     SetLastError(MAGIC_DEAD);
695     res = DeleteMonitorA(NULL, invalid_env, winetest);
696     ok( res ||
697         (!res && GetLastError() == ERROR_INVALID_ENVIRONMENT) /* Vista/W2K8 */,
698         "returned %d with %d\n", res, GetLastError());
699
700     /* the monitor-name */
701     AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
702     SetLastError(MAGIC_DEAD);
703     res = DeleteMonitorA(NULL, entry->env, NULL);
704     /* NT: ERROR_INVALID_PARAMETER (87),  9x: ERROR_INVALID_NAME (123)*/
705     ok( !res &&
706         ((GetLastError() == ERROR_INVALID_PARAMETER) ||
707         (GetLastError() == ERROR_INVALID_NAME)),
708         "returned %d with %d (expected '0' with: ERROR_INVALID_PARAMETER or "
709         "ERROR_INVALID_NAME)\n", res, GetLastError());
710
711     AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
712     SetLastError(MAGIC_DEAD);
713     res = DeleteMonitorA(NULL, entry->env, empty);
714     /* NT: ERROR_INVALID_PARAMETER (87),  9x: ERROR_INVALID_NAME (123)*/
715     ok( !res && 
716         ((GetLastError() == ERROR_INVALID_PARAMETER) ||
717         (GetLastError() == ERROR_INVALID_NAME)),
718         "returned %d with %d (expected '0' with: ERROR_INVALID_PARAMETER or "
719         "ERROR_INVALID_NAME)\n", res, GetLastError());
720
721     AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
722     SetLastError(MAGIC_DEAD);
723     res = DeleteMonitorA(empty, entry->env, winetest);
724     ok(res, "returned %d with %d (expected '!=0')\n", res, GetLastError());
725
726     /* cleanup */
727     DeleteMonitorA(NULL, entry->env, winetest);
728 }
729
730 /* ########################### */
731
732 static void test_DeletePort(void)
733 {
734     DWORD   res;
735
736     SetLastError(0xdeadbeef);
737     res = DeletePortA(NULL, 0, NULL);
738     RETURN_ON_DEACTIVATED_SPOOLER(res)
739
740     SetLastError(0xdeadbeef);
741     res = DeletePortA(NULL, 0, empty);
742     /* Allowed only for (Printer-)Administrators */
743     RETURN_ON_ACCESS_DENIED(res)
744
745     /* XP: ERROR_NOT_SUPPORTED, NT351 and 9x: ERROR_INVALID_PARAMETER */
746     ok( !res && ((GetLastError() == ERROR_NOT_SUPPORTED) || 
747                  (GetLastError() == ERROR_INVALID_PARAMETER)),
748         "returned %d with %d (expected '0' with ERROR_NOT_SUPPORTED or "
749         "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
750
751
752     SetLastError(0xdeadbeef);
753     res = DeletePortA(NULL, 0, does_not_exist);
754     /* XP: ERROR_NOT_SUPPORTED, NT351 and 9x: ERROR_INVALID_PARAMETER */
755     ok( !res && ((GetLastError() == ERROR_NOT_SUPPORTED) || 
756                  (GetLastError() == ERROR_INVALID_PARAMETER)),
757         "returned %d with %d (expected '0' with ERROR_NOT_SUPPORTED or "
758         "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
759
760 }
761
762 /* ########################### */
763
764 static void test_EnumForms(LPSTR pName)
765 {
766     DWORD   res;
767     HANDLE  hprinter = 0;
768     LPBYTE  buffer;
769     DWORD   cbBuf;
770     DWORD   pcbNeeded;
771     DWORD   pcReturned;
772     DWORD   level;
773     UINT    i;
774     const char *formtype;
775     static const char * const formtypes[] = { "FORM_USER", "FORM_BUILTIN", "FORM_PRINTER", "FORM_flag_unknown" };
776 #define FORMTYPE_MAX 2
777     PFORM_INFO_1A pFI_1a;
778     PFORM_INFO_2A pFI_2a;
779
780     res = OpenPrinter(pName, &hprinter, NULL);
781     RETURN_ON_DEACTIVATED_SPOOLER(res)
782     if (!res || !hprinter)
783     {
784         /* Open the local Prinserver is not supported on win9x */
785         if (pName) skip("Failed to open '%s' (not supported on win9x)\n", pName);
786         return;
787     }
788
789     /* valid levels are 1 and 2 */
790     for(level = 0; level < 4; level++) {
791         cbBuf = 0xdeadbeef;
792         pcReturned = 0xdeadbeef;
793         SetLastError(0xdeadbeef);
794         res = EnumFormsA(hprinter, level, NULL, 0, &cbBuf, &pcReturned);
795
796         /* EnumForms is not implemented in win9x */
797         if (!res && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) continue;
798
799         /* EnumForms for the Server not implemented on all NT-Versions */
800         if (!res && (GetLastError() == ERROR_INVALID_HANDLE) && !pName) continue;
801
802         /* Level 2 for EnumForms is not supported on all systems */
803         if (!res && (GetLastError() == ERROR_INVALID_LEVEL) && (level == 2)) continue;
804
805         /* use only a short test, when we test with an invalid level */
806         if(!level || (level > 2)) {
807             ok( (!res && (GetLastError() == ERROR_INVALID_LEVEL)) ||
808                 (res && (pcReturned == 0)),
809                 "(%d) returned %d with %d and 0x%08x (expected '0' with "
810                 "ERROR_INVALID_LEVEL or '!=0' and 0x0)\n",
811                 level, res, GetLastError(), pcReturned);
812             continue;
813         }
814
815         ok((!res) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
816             "(%d) returned %d with %d (expected '0' with "
817             "ERROR_INSUFFICIENT_BUFFER)\n", level, res, GetLastError());
818
819         buffer = HeapAlloc(GetProcessHeap(), 0, cbBuf *2);
820         if (buffer == NULL) continue;
821
822         SetLastError(0xdeadbeef);
823         res = EnumFormsA(hprinter, level, buffer, cbBuf, &pcbNeeded, &pcReturned);
824         ok(res, "(%d) returned %d with %d (expected '!=0')\n",
825                 level, res, GetLastError());
826
827         if (winetest_debug > 1) {
828             trace("dumping %d forms level %d\n", pcReturned, level);
829             pFI_1a = (PFORM_INFO_1A)buffer;
830             pFI_2a = (PFORM_INFO_2A)buffer;
831             for (i = 0; i < pcReturned; i++)
832             {
833                 /* first part is same in FORM_INFO_1 and FORM_INFO_2 */
834                 formtype = (pFI_1a->Flags <= FORMTYPE_MAX) ? formtypes[pFI_1a->Flags] : formtypes[3];
835                 trace("%u (%s): %.03fmm x %.03fmm, %s\n", i, pFI_1a->pName,
836                       (float)pFI_1a->Size.cx/1000, (float)pFI_1a->Size.cy/1000, formtype);
837
838                 if (level == 1) pFI_1a ++;
839                 else {
840                     /* output additional FORM_INFO_2 fields */
841                     trace("\tkeyword=%s strtype=%u muidll=%s resid=%u dispname=%s langid=%u\n",
842                           pFI_2a->pKeyword, pFI_2a->StringType, pFI_2a->pMuiDll,
843                           pFI_2a->dwResourceId, pFI_2a->pDisplayName, pFI_2a->wLangId);
844
845                     /* offset pointer pFI_1a by 1*sizeof(FORM_INFO_2A) Bytes */
846                     pFI_2a ++;
847                     pFI_1a = (PFORM_INFO_1A)pFI_2a;
848                 }
849             }
850         }
851
852         SetLastError(0xdeadbeef);
853         res = EnumFormsA(hprinter, level, buffer, cbBuf+1, &pcbNeeded, &pcReturned);
854         ok( res, "(%d) returned %d with %d (expected '!=0')\n",
855             level, res, GetLastError());
856
857         SetLastError(0xdeadbeef);
858         res = EnumFormsA(hprinter, level, buffer, cbBuf-1, &pcbNeeded, &pcReturned);
859         ok( !res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
860             "(%d) returned %d with %d (expected '0' with "
861             "ERROR_INSUFFICIENT_BUFFER)\n", level, res, GetLastError());
862
863
864         SetLastError(0xdeadbeef);
865         res = EnumFormsA(hprinter, level, NULL, cbBuf, &pcbNeeded, &pcReturned);
866         ok( !res && (GetLastError() == ERROR_INVALID_USER_BUFFER) ,
867             "(%d) returned %d with %d (expected '0' with "
868             "ERROR_INVALID_USER_BUFFER)\n", level, res, GetLastError());
869
870
871         SetLastError(0xdeadbeef);
872         res = EnumFormsA(hprinter, level, buffer, cbBuf, NULL, &pcReturned);
873         ok( !res && (GetLastError() == RPC_X_NULL_REF_POINTER) ,
874             "(%d) returned %d with %d (expected '0' with "
875             "RPC_X_NULL_REF_POINTER)\n", level, res, GetLastError());
876
877         SetLastError(0xdeadbeef);
878         res = EnumFormsA(hprinter, level, buffer, cbBuf, &pcbNeeded, NULL);
879         ok( !res && (GetLastError() == RPC_X_NULL_REF_POINTER) ,
880             "(%d) returned %d with %d (expected '0' with "
881             "RPC_X_NULL_REF_POINTER)\n", level, res, GetLastError());
882
883         SetLastError(0xdeadbeef);
884         res = EnumFormsA(0, level, buffer, cbBuf, &pcbNeeded, &pcReturned);
885         ok( !res && (GetLastError() == ERROR_INVALID_HANDLE) ,
886             "(%d) returned %d with %d (expected '0' with "
887             "ERROR_INVALID_HANDLE)\n", level, res, GetLastError());
888
889         HeapFree(GetProcessHeap(), 0, buffer);
890     } /* for(level ... */
891
892     ClosePrinter(hprinter);
893 }
894
895 /* ########################### */
896
897 static void test_EnumMonitors(void)
898 {
899     DWORD   res;
900     LPBYTE  buffer;
901     DWORD   cbBuf;
902     DWORD   pcbNeeded;
903     DWORD   pcReturned;
904     DWORD   level;
905
906     /* valid levels are 1 and 2 */
907     for(level = 0; level < 4; level++) {
908         cbBuf = MAGIC_DEAD;
909         pcReturned = MAGIC_DEAD;
910         SetLastError(MAGIC_DEAD);
911         res = EnumMonitorsA(NULL, level, NULL, 0, &cbBuf, &pcReturned);
912
913         RETURN_ON_DEACTIVATED_SPOOLER(res)
914
915         /* not implemented yet in wine */
916         if (!res && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) continue;
917
918
919         /* use only a short test, when we test with an invalid level */
920         if(!level || (level > 2)) {
921             ok( (!res && (GetLastError() == ERROR_INVALID_LEVEL)) ||
922                 (res && (pcReturned == 0)),
923                 "(%d) returned %d with %d and 0x%08x (expected '0' with "
924                 "ERROR_INVALID_LEVEL or '!=0' and 0x0)\n",
925                 level, res, GetLastError(), pcReturned);
926             continue;
927         }        
928
929         /* Level 2 is not supported on win9x */
930         if (!res && (GetLastError() == ERROR_INVALID_LEVEL)) {
931             skip("Level %d not supported\n", level);
932             continue;
933         }
934
935         ok((!res) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
936             "(%d) returned %d with %d (expected '0' with "
937             "ERROR_INSUFFICIENT_BUFFER)\n", level, res, GetLastError());
938
939         if (!cbBuf) {
940             skip("no valid buffer size returned\n");
941             continue;
942         }
943
944         buffer = HeapAlloc(GetProcessHeap(), 0, cbBuf *2);
945         if (buffer == NULL) continue;
946
947         SetLastError(MAGIC_DEAD);
948         pcbNeeded = MAGIC_DEAD;
949         res = EnumMonitorsA(NULL, level, buffer, cbBuf, &pcbNeeded, &pcReturned);
950         ok(res, "(%d) returned %d with %d (expected '!=0')\n",
951                 level, res, GetLastError());
952         ok(pcbNeeded == cbBuf, "(%d) returned %d (expected %d)\n",
953                 level, pcbNeeded, cbBuf);
954         /* We can validate the returned Data with the Registry here */
955
956
957         SetLastError(MAGIC_DEAD);
958         pcReturned = MAGIC_DEAD;
959         pcbNeeded = MAGIC_DEAD;
960         res = EnumMonitorsA(NULL, level, buffer, cbBuf+1, &pcbNeeded, &pcReturned);
961         ok(res, "(%d) returned %d with %d (expected '!=0')\n", level,
962                 res, GetLastError());
963         ok(pcbNeeded == cbBuf, "(%d) returned %d (expected %d)\n", level,
964                 pcbNeeded, cbBuf);
965
966         SetLastError(MAGIC_DEAD);
967         pcbNeeded = MAGIC_DEAD;
968         res = EnumMonitorsA(NULL, level, buffer, cbBuf-1, &pcbNeeded, &pcReturned);
969         ok( !res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
970             "(%d) returned %d with %d (expected '0' with "
971             "ERROR_INSUFFICIENT_BUFFER)\n", level, res, GetLastError());
972
973         ok(pcbNeeded == cbBuf, "(%d) returned %d (expected %d)\n", level,
974                 pcbNeeded, cbBuf);
975
976 /*
977       Do not add the next test:
978       w2k+:  RPC_X_NULL_REF_POINTER 
979       NT3.5: ERROR_INVALID_USER_BUFFER
980       win9x: crash in winspool.drv
981
982       res = EnumMonitorsA(NULL, level, NULL, cbBuf, &pcbNeeded, &pcReturned);
983 */
984
985         SetLastError(MAGIC_DEAD);
986         pcbNeeded = MAGIC_DEAD;
987         pcReturned = MAGIC_DEAD;
988         res = EnumMonitorsA(NULL, level, buffer, cbBuf, NULL, &pcReturned);
989         ok( res || (!res && (GetLastError() == RPC_X_NULL_REF_POINTER)) ,
990             "(%d) returned %d with %d (expected '!=0' or '0' with "
991             "RPC_X_NULL_REF_POINTER)\n", level, res, GetLastError());
992
993         pcbNeeded = MAGIC_DEAD;
994         pcReturned = MAGIC_DEAD;
995         SetLastError(MAGIC_DEAD);
996         res = EnumMonitorsA(NULL, level, buffer, cbBuf, &pcbNeeded, NULL);
997         ok( res || (!res && (GetLastError() == RPC_X_NULL_REF_POINTER)) ,
998             "(%d) returned %d with %d (expected '!=0' or '0' with "
999             "RPC_X_NULL_REF_POINTER)\n", level, res, GetLastError());
1000
1001         HeapFree(GetProcessHeap(), 0, buffer);
1002     } /* for(level ... */
1003 }
1004
1005 /* ########################### */
1006
1007 static void test_EnumPorts(void)
1008 {
1009     DWORD   res;
1010     DWORD   level;
1011     LPBYTE  buffer;
1012     DWORD   cbBuf;
1013     DWORD   pcbNeeded;
1014     DWORD   pcReturned;
1015
1016     /* valid levels are 1 and 2 */
1017     for(level = 0; level < 4; level++) {
1018
1019         cbBuf = 0xdeadbeef;
1020         pcReturned = 0xdeadbeef;
1021         SetLastError(0xdeadbeef);
1022         res = EnumPortsA(NULL, level, NULL, 0, &cbBuf, &pcReturned);
1023         RETURN_ON_DEACTIVATED_SPOOLER(res)
1024
1025         /* use only a short test, when we test with an invalid level */
1026         if(!level || (level > 2)) {
1027             /* NT: ERROR_INVALID_LEVEL, 9x: success */
1028             ok( (!res && (GetLastError() == ERROR_INVALID_LEVEL)) ||
1029                 (res && (pcReturned == 0)),
1030                 "(%d) returned %d with %d and 0x%08x (expected '0' with "
1031                 "ERROR_INVALID_LEVEL or '!=0' and 0x0)\n",
1032                 level, res, GetLastError(), pcReturned);
1033             continue;
1034         }        
1035
1036         
1037         /* Level 2 is not supported on NT 3.x */
1038         if (!res && (GetLastError() == ERROR_INVALID_LEVEL)) {
1039             skip("Level %d not supported\n", level);
1040             continue;
1041         }
1042
1043         ok((!res) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1044             "(%d) returned %d with %d (expected '0' with "
1045             "ERROR_INSUFFICIENT_BUFFER)\n", level, res, GetLastError());
1046
1047         buffer = HeapAlloc(GetProcessHeap(), 0, cbBuf *2);
1048         if (buffer == NULL) continue;
1049
1050         pcbNeeded = 0xdeadbeef;
1051         SetLastError(0xdeadbeef);
1052         res = EnumPortsA(NULL, level, buffer, cbBuf, &pcbNeeded, &pcReturned);
1053         ok(res, "(%d) returned %d with %d (expected '!=0')\n", level, res, GetLastError());
1054         ok(pcbNeeded == cbBuf, "(%d) returned %d (expected %d)\n", level, pcbNeeded, cbBuf);
1055         /* ToDo: Compare the returned Data with the Registry / "win.ini",[Ports] here */
1056
1057         pcbNeeded = 0xdeadbeef;
1058         pcReturned = 0xdeadbeef;
1059         SetLastError(0xdeadbeef);
1060         res = EnumPortsA(NULL, level, buffer, cbBuf+1, &pcbNeeded, &pcReturned);
1061         ok(res, "(%d) returned %d with %d (expected '!=0')\n", level, res, GetLastError());
1062         ok(pcbNeeded == cbBuf, "(%d) returned %d (expected %d)\n", level, pcbNeeded, cbBuf);
1063
1064         pcbNeeded = 0xdeadbeef;
1065         SetLastError(0xdeadbeef);
1066         res = EnumPortsA(NULL, level, buffer, cbBuf-1, &pcbNeeded, &pcReturned);
1067         ok( !res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1068             "(%d) returned %d with %d (expected '0' with "
1069             "ERROR_INSUFFICIENT_BUFFER)\n", level, res, GetLastError());
1070         ok(pcbNeeded == cbBuf, "(%d) returned %d (expected %d)\n", level, pcbNeeded, cbBuf);
1071
1072         /*
1073           Do not add this test:
1074           res = EnumPortsA(NULL, level, NULL, cbBuf, &pcbNeeded, &pcReturned);
1075           w2k+:  RPC_X_NULL_REF_POINTER 
1076           NT3.5: ERROR_INVALID_USER_BUFFER
1077           win9x: crash in winspool.drv
1078          */
1079
1080         SetLastError(0xdeadbeef);
1081         res = EnumPorts(NULL, level, buffer, cbBuf, NULL, &pcReturned);
1082         /* NT: RPC_X_NULL_REF_POINTER (1780),  9x: success */
1083         ok( (!res && (GetLastError() == RPC_X_NULL_REF_POINTER) ) ||
1084             ( res && (GetLastError() == ERROR_SUCCESS) ),
1085             "(%d) returned %d with %d (expected '0' with "
1086             "RPC_X_NULL_REF_POINTER or '!=0' with NO_ERROR)\n",
1087             level, res, GetLastError());
1088
1089
1090         SetLastError(0xdeadbeef);
1091         res = EnumPorts(NULL, level, buffer, cbBuf, &pcbNeeded, NULL);
1092         /* NT: RPC_X_NULL_REF_POINTER (1780),  9x: success */
1093         ok( (!res && (GetLastError() == RPC_X_NULL_REF_POINTER) ) ||
1094             ( res && (GetLastError() == ERROR_SUCCESS) ),
1095             "(%d) returned %d with %d (expected '0' with "
1096             "RPC_X_NULL_REF_POINTER or '!=0' with NO_ERROR)\n",
1097             level, res, GetLastError());
1098
1099         HeapFree(GetProcessHeap(), 0, buffer);
1100     }
1101 }
1102
1103 /* ########################### */
1104
1105 static void test_EnumPrinterDrivers(void)
1106 {
1107     DWORD   res;
1108     LPBYTE  buffer;
1109     DWORD   cbBuf;
1110     DWORD   pcbNeeded;
1111     DWORD   pcReturned;
1112     DWORD   level;
1113
1114     /* 1-3 for w95/w98/NT4; 1-3+6 for me; 1-6 for w2k/xp/2003; 1-6+8 for vista */
1115     for(level = 0; level < 10; level++) {
1116         cbBuf = 0xdeadbeef;
1117         pcReturned = 0xdeadbeef;
1118         SetLastError(0xdeadbeef);
1119         res = EnumPrinterDriversA(NULL, NULL, level, NULL, 0, &cbBuf, &pcReturned);
1120         RETURN_ON_DEACTIVATED_SPOOLER(res)
1121
1122         /* use only a short test, when we test with an invalid level */
1123         if(!level || (level == 7) || (level > 8)) {
1124
1125             ok( (!res && (GetLastError() == ERROR_INVALID_LEVEL)) ||
1126                 (res && (pcReturned == 0)),
1127                 "(%d) got %u with %u and 0x%x "
1128                 "(expected '0' with ERROR_INVALID_LEVEL or '!=0' and 0x0)\n",
1129                 level, res, GetLastError(), pcReturned);
1130             continue;
1131         }
1132
1133         /* some level are not supported in all windows versions */
1134         if (!res && (GetLastError() == ERROR_INVALID_LEVEL)) {
1135             skip("Level %d not supported\n", level);
1136             continue;
1137         }
1138
1139         ok( ((!res) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) ||
1140             (res && (default_printer == NULL)),
1141             "(%u) got %u with %u for %s (expected '0' with "
1142             "ERROR_INSUFFICIENT_BUFFER or '!= 0' without a printer)\n",
1143             level, res, GetLastError(), default_printer);
1144
1145         if (!cbBuf) {
1146             skip("no valid buffer size returned\n");
1147             continue;
1148         }
1149
1150         buffer = HeapAlloc(GetProcessHeap(), 0, cbBuf + 4);
1151         if (buffer == NULL) continue;
1152
1153         SetLastError(0xdeadbeef);
1154         pcbNeeded = 0xdeadbeef;
1155         res = EnumPrinterDriversA(NULL, NULL, level, buffer, cbBuf, &pcbNeeded, &pcReturned);
1156         ok(res, "(%u) got %u with %u (expected '!=0')\n", level, res, GetLastError());
1157         ok(pcbNeeded == cbBuf, "(%d) returned %d (expected %d)\n", level, pcbNeeded, cbBuf);
1158
1159         /* validate the returned Data here */
1160         if (level > 1) {
1161             LPDRIVER_INFO_2A di = (LPDRIVER_INFO_2A) buffer;
1162
1163             ok( strrchr(di->pDriverPath, '\\') != NULL,
1164                 "(%u) got %s for %s (expected a full path)\n",
1165                 level, di->pDriverPath, di->pName);
1166
1167         }
1168
1169         SetLastError(0xdeadbeef);
1170         pcReturned = 0xdeadbeef;
1171         pcbNeeded = 0xdeadbeef;
1172         res = EnumPrinterDriversA(NULL, NULL, level, buffer, cbBuf+1, &pcbNeeded, &pcReturned);
1173         ok(res, "(%u) got %u with %u (expected '!=0')\n", level, res, GetLastError());
1174         ok(pcbNeeded == cbBuf, "(%u) returned %u (expected %u)\n", level, pcbNeeded, cbBuf);
1175
1176         SetLastError(0xdeadbeef);
1177         pcbNeeded = 0xdeadbeef;
1178         res = EnumPrinterDriversA(NULL, NULL, level, buffer, cbBuf-1, &pcbNeeded, &pcReturned);
1179         ok( !res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1180             "(%u) got %u with %u (expected '0' with ERROR_INSUFFICIENT_BUFFER)\n",
1181             level, res, GetLastError());
1182         ok(pcbNeeded == cbBuf, "(%u) returned %u (expected %u)\n", level, pcbNeeded, cbBuf);
1183
1184 /*
1185       Do not add the next test:
1186       NT: ERROR_INVALID_USER_BUFFER
1187       win9x: crash or 100% CPU
1188
1189       res = EnumPrinterDriversA(NULL, NULL, level, NULL, cbBuf, &pcbNeeded, &pcReturned);
1190 */
1191
1192         SetLastError(0xdeadbeef);
1193         pcbNeeded = 0xdeadbeef;
1194         pcReturned = 0xdeadbeef;
1195         res = EnumPrinterDriversA(NULL, NULL, level, buffer, cbBuf, NULL, &pcReturned);
1196         ok( res || (!res && (GetLastError() == RPC_X_NULL_REF_POINTER)) ,
1197             "(%u) got %u with %u (expected '!=0' or '0' with "
1198             "RPC_X_NULL_REF_POINTER)\n", level, res, GetLastError());
1199
1200         pcbNeeded = 0xdeadbeef;
1201         pcReturned = 0xdeadbeef;
1202         SetLastError(0xdeadbeef);
1203         res = EnumPrinterDriversA(NULL, NULL, level, buffer, cbBuf, &pcbNeeded, NULL);
1204         ok( res || (!res && (GetLastError() == RPC_X_NULL_REF_POINTER)) ,
1205             "(%u) got %u with %u (expected '!=0' or '0' with "
1206             "RPC_X_NULL_REF_POINTER)\n", level, res, GetLastError());
1207
1208         HeapFree(GetProcessHeap(), 0, buffer);
1209     } /* for(level ... */
1210 }
1211
1212 /* ########################### */
1213
1214 static void test_GetDefaultPrinter(void)
1215 {
1216     BOOL    retval;
1217     DWORD   exact = DEFAULT_PRINTER_SIZE;
1218     DWORD   size;
1219     char    buffer[DEFAULT_PRINTER_SIZE];
1220
1221     if (!pGetDefaultPrinterA)  return;
1222         /* only supported on NT like OSes starting with win2k */
1223
1224     SetLastError(ERROR_SUCCESS);
1225     retval = pGetDefaultPrinterA(buffer, &exact);
1226     if (!retval || !exact || !strlen(buffer) ||
1227         (ERROR_SUCCESS != GetLastError())) {
1228         if ((ERROR_FILE_NOT_FOUND == GetLastError()) ||
1229             (ERROR_INVALID_NAME == GetLastError()))
1230             trace("this test requires a default printer to be set\n");
1231         else {
1232                 ok( 0, "function call GetDefaultPrinterA failed unexpected!\n"
1233                 "function returned %s\n"
1234                 "last error 0x%08x\n"
1235                 "returned buffer size 0x%08x\n"
1236                 "returned buffer content %s\n",
1237                 retval ? "true" : "false", GetLastError(), exact, buffer);
1238         }
1239         return;
1240     }
1241     SetLastError(ERROR_SUCCESS);
1242     retval = pGetDefaultPrinterA(NULL, NULL); 
1243     ok( !retval, "function result wrong! False expected\n");
1244     ok( ERROR_INVALID_PARAMETER == GetLastError(),
1245         "Last error wrong! ERROR_INVALID_PARAMETER expected, got 0x%08x\n",
1246         GetLastError());
1247
1248     SetLastError(ERROR_SUCCESS);
1249     retval = pGetDefaultPrinterA(buffer, NULL); 
1250     ok( !retval, "function result wrong! False expected\n");
1251     ok( ERROR_INVALID_PARAMETER == GetLastError(),
1252         "Last error wrong! ERROR_INVALID_PARAMETER expected, got 0x%08x\n",
1253         GetLastError());
1254
1255     SetLastError(ERROR_SUCCESS);
1256     size = 0;
1257     retval = pGetDefaultPrinterA(NULL, &size); 
1258     ok( !retval, "function result wrong! False expected\n");
1259     ok( ERROR_INSUFFICIENT_BUFFER == GetLastError(),
1260         "Last error wrong! ERROR_INSUFFICIENT_BUFFER expected, got 0x%08x\n",
1261         GetLastError());
1262     ok( size == exact, "Parameter size wrong! %d expected got %d\n",
1263         exact, size);
1264
1265     SetLastError(ERROR_SUCCESS);
1266     size = DEFAULT_PRINTER_SIZE;
1267     retval = pGetDefaultPrinterA(NULL, &size); 
1268     ok( !retval, "function result wrong! False expected\n");
1269     ok( ERROR_INSUFFICIENT_BUFFER == GetLastError(),
1270         "Last error wrong! ERROR_INSUFFICIENT_BUFFER expected, got 0x%08x\n",
1271         GetLastError());
1272     ok( size == exact, "Parameter size wrong! %d expected got %d\n",
1273         exact, size);
1274
1275     size = 0;
1276     retval = pGetDefaultPrinterA(buffer, &size); 
1277     ok( !retval, "function result wrong! False expected\n");
1278     ok( ERROR_INSUFFICIENT_BUFFER == GetLastError(),
1279         "Last error wrong! ERROR_INSUFFICIENT_BUFFER expected, got 0x%08x\n",
1280         GetLastError());
1281     ok( size == exact, "Parameter size wrong! %d expected got %d\n",
1282         exact, size);
1283
1284     size = exact;
1285     retval = pGetDefaultPrinterA(buffer, &size); 
1286     ok( retval, "function result wrong! True expected\n");
1287     ok( size == exact, "Parameter size wrong! %d expected got %d\n",
1288         exact, size);
1289 }
1290
1291 static void test_GetPrinterDriverDirectory(void)
1292 {
1293     LPBYTE      buffer = NULL;
1294     DWORD       cbBuf = 0, pcbNeeded = 0;
1295     BOOL        res;
1296
1297
1298     SetLastError(MAGIC_DEAD);
1299     res = GetPrinterDriverDirectoryA( NULL, NULL, 1, NULL, 0, &cbBuf);
1300     trace("first call returned 0x%04x, with %d: buffer size 0x%08x\n",
1301     res, GetLastError(), cbBuf);
1302
1303     RETURN_ON_DEACTIVATED_SPOOLER(res)
1304     ok((res == 0) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1305         "returned %d with lasterror=%d (expected '0' with "
1306         "ERROR_INSUFFICIENT_BUFFER)\n", res, GetLastError());
1307
1308     if (!cbBuf) {
1309         skip("no valid buffer size returned\n");
1310         return;
1311     }
1312
1313     buffer = HeapAlloc( GetProcessHeap(), 0, cbBuf*2);
1314     if (buffer == NULL)  return ;
1315
1316     res = GetPrinterDriverDirectoryA(NULL, NULL, 1, buffer, cbBuf, &pcbNeeded);
1317     ok( res, "expected result != 0, got %d\n", res);
1318     ok( cbBuf == pcbNeeded, "pcbNeeded set to %d instead of %d\n",
1319                             pcbNeeded, cbBuf);
1320
1321     res = GetPrinterDriverDirectoryA(NULL, NULL, 1, buffer, cbBuf*2, &pcbNeeded);
1322     ok( res, "expected result != 0, got %d\n", res);
1323     ok( cbBuf == pcbNeeded, "pcbNeeded set to %d instead of %d\n",
1324                             pcbNeeded, cbBuf);
1325  
1326     SetLastError(MAGIC_DEAD);
1327     res = GetPrinterDriverDirectoryA( NULL, NULL, 1, buffer, cbBuf-1, &pcbNeeded);
1328     ok( !res , "expected result == 0, got %d\n", res);
1329     ok( cbBuf == pcbNeeded, "pcbNeeded set to %d instead of %d\n",
1330                             pcbNeeded, cbBuf);
1331     
1332     ok( ERROR_INSUFFICIENT_BUFFER == GetLastError(),
1333         "last error set to %d instead of ERROR_INSUFFICIENT_BUFFER\n",
1334         GetLastError());
1335
1336 /*
1337     Do not add the next test:
1338     XPsp2: crash in this app, when the spooler is not running 
1339     NT3.5: ERROR_INVALID_USER_BUFFER
1340     win9x: ERROR_INVALID_PARAMETER
1341
1342     pcbNeeded = MAGIC_DEAD;
1343     SetLastError(MAGIC_DEAD);
1344     res = GetPrinterDriverDirectoryA( NULL, NULL, 1, NULL, cbBuf, &pcbNeeded);
1345 */
1346
1347     SetLastError(MAGIC_DEAD);
1348     res = GetPrinterDriverDirectoryA( NULL, NULL, 1, buffer, cbBuf, NULL);
1349     ok( (!res && RPC_X_NULL_REF_POINTER == GetLastError()) || res,
1350          "expected either result == 0 and "
1351          "last error == RPC_X_NULL_REF_POINTER or result != 0 "
1352          "got result %d and last error == %d\n", res, GetLastError());
1353
1354     SetLastError(MAGIC_DEAD);
1355     res = GetPrinterDriverDirectoryA( NULL, NULL, 1, NULL, cbBuf, NULL);
1356     ok(res || (GetLastError() == RPC_X_NULL_REF_POINTER),
1357         "returned %d with %d (expected '!=0' or '0' with "
1358         "RPC_X_NULL_REF_POINTER)\n", res, GetLastError());
1359  
1360  
1361     /* with a valid buffer, but level is too large */
1362     buffer[0] = '\0';
1363     SetLastError(MAGIC_DEAD);
1364     res = GetPrinterDriverDirectoryA(NULL, NULL, 2, buffer, cbBuf, &pcbNeeded);
1365
1366     /* Level not checked in win9x and wine:*/
1367     if((res != FALSE) && buffer[0])
1368     {
1369         trace("Level '2' not checked '%s'\n", buffer);
1370     }
1371     else
1372     {
1373         ok( !res && (GetLastError() == ERROR_INVALID_LEVEL),
1374         "returned %d with lasterror=%d (expected '0' with "
1375         "ERROR_INVALID_LEVEL)\n", res, GetLastError());
1376     }
1377
1378     /* printing environments are case insensitive */
1379     /* "Windows 4.0" is valid for win9x and NT */
1380     buffer[0] = '\0';
1381     SetLastError(MAGIC_DEAD);
1382     res = GetPrinterDriverDirectoryA(NULL, env_win9x_case, 1, 
1383                                         buffer, cbBuf*2, &pcbNeeded);
1384
1385     if(!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
1386         cbBuf = pcbNeeded;
1387         buffer = HeapReAlloc(GetProcessHeap(), 0, buffer, cbBuf*2);
1388         if (buffer == NULL)  return ;
1389
1390         SetLastError(MAGIC_DEAD);
1391         res = GetPrinterDriverDirectoryA(NULL, env_win9x_case, 1, 
1392                                         buffer, cbBuf*2, &pcbNeeded);
1393     }
1394
1395     ok(res && buffer[0], "returned %d with "
1396         "lasterror=%d and len=%d (expected '1' with 'len > 0')\n", 
1397         res, GetLastError(), lstrlenA((char *)buffer));
1398
1399     buffer[0] = '\0';
1400     SetLastError(MAGIC_DEAD);
1401     res = GetPrinterDriverDirectoryA(NULL, env_x86, 1, 
1402                                         buffer, cbBuf*2, &pcbNeeded);
1403
1404     if(!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
1405         cbBuf = pcbNeeded;
1406         buffer = HeapReAlloc(GetProcessHeap(), 0, buffer, cbBuf*2);
1407         if (buffer == NULL)  return ;
1408
1409         buffer[0] = '\0';
1410         SetLastError(MAGIC_DEAD);
1411         res = GetPrinterDriverDirectoryA(NULL, env_x86, 1, 
1412                                         buffer, cbBuf*2, &pcbNeeded);
1413     }
1414
1415     /* "Windows NT x86" is invalid for win9x */
1416     ok( (res && buffer[0]) ||
1417         (!res && (GetLastError() == ERROR_INVALID_ENVIRONMENT)), 
1418         "returned %d with lasterror=%d and len=%d (expected '!= 0' with "
1419         "'len > 0' or '0' with ERROR_INVALID_ENVIRONMENT)\n",
1420         res, GetLastError(), lstrlenA((char *)buffer));
1421
1422     /* A setup program (PDFCreator_0.8.0) use empty strings */
1423     SetLastError(MAGIC_DEAD);
1424     res = GetPrinterDriverDirectoryA(empty, empty, 1, buffer, cbBuf*2, &pcbNeeded);
1425     ok(res, "returned %d with %d (expected '!=0')\n", res, GetLastError() );
1426
1427     SetLastError(MAGIC_DEAD);
1428     res = GetPrinterDriverDirectoryA(NULL, empty, 1, buffer, cbBuf*2, &pcbNeeded);
1429     ok(res, "returned %d with %d (expected '!=0')\n", res, GetLastError() );
1430
1431     SetLastError(MAGIC_DEAD);
1432     res = GetPrinterDriverDirectoryA(empty, NULL, 1, buffer, cbBuf*2, &pcbNeeded);
1433     ok(res, "returned %d with %d (expected '!=0')\n", res, GetLastError() );
1434
1435     HeapFree( GetProcessHeap(), 0, buffer);
1436 }
1437
1438 /* ##### */
1439
1440 static void test_GetPrintProcessorDirectory(void)
1441 {
1442     LPBYTE      buffer = NULL;
1443     DWORD       cbBuf = 0;
1444     DWORD       pcbNeeded = 0;
1445     BOOL        res;
1446
1447
1448     SetLastError(0xdeadbeef);
1449     res = GetPrintProcessorDirectoryA(NULL, NULL, 1, NULL, 0, &cbBuf);
1450     /* The deactivated Spooler is caught here on NT3.51 */
1451     RETURN_ON_DEACTIVATED_SPOOLER(res)
1452     ok( !res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1453         "returned %d with %d (expected '0' with ERROR_INSUFFICIENT_BUFFER)\n",
1454         res, GetLastError());
1455
1456     buffer = HeapAlloc(GetProcessHeap(), 0, cbBuf*2);
1457     if(buffer == NULL)  return;
1458
1459     buffer[0] = '\0';
1460     SetLastError(0xdeadbeef);
1461     res = GetPrintProcessorDirectoryA(NULL, NULL, 1, buffer, cbBuf, &pcbNeeded);
1462     ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError());
1463
1464     SetLastError(0xdeadbeef);
1465     buffer[0] = '\0';
1466     res = GetPrintProcessorDirectoryA(NULL, NULL, 1, buffer, cbBuf*2, &pcbNeeded);
1467     ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError());
1468  
1469     /* Buffer to small */
1470     buffer[0] = '\0';
1471     SetLastError(0xdeadbeef);
1472     res = GetPrintProcessorDirectoryA( NULL, NULL, 1, buffer, cbBuf-1, &pcbNeeded);
1473     ok( !res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1474         "returned %d with %d (expected '0' with ERROR_INSUFFICIENT_BUFFER)\n",
1475         res, GetLastError());
1476
1477     if (0)
1478     {
1479     /* XPsp2: the program will crash here, when the spooler is not running  */
1480     /*        GetPrinterDriverDirectory has the same bug */
1481     pcbNeeded = 0;
1482     SetLastError(0xdeadbeef);
1483     res = GetPrintProcessorDirectoryA( NULL, NULL, 1, NULL, cbBuf, &pcbNeeded);
1484     }
1485
1486     buffer[0] = '\0';
1487     SetLastError(0xdeadbeef);
1488     res = GetPrintProcessorDirectoryA( NULL, NULL, 1, buffer, cbBuf, NULL);
1489     /* NT: RPC_X_NULL_REF_POINTER, 9x: res != 0  */
1490     ok( res || (GetLastError() == RPC_X_NULL_REF_POINTER),
1491         "returned %d with %d (expected '!= 0' or '0' with "
1492         "RPC_X_NULL_REF_POINTER)\n", res, GetLastError());
1493
1494
1495     buffer[0] = '\0';
1496     SetLastError(0xdeadbeef);
1497     res = GetPrintProcessorDirectoryA( NULL, NULL, 1, NULL, cbBuf, NULL);
1498     /* NT: RPC_X_NULL_REF_POINTER, 9x: res != 0  */
1499     ok( res || (GetLastError() == RPC_X_NULL_REF_POINTER),
1500         "returned %d with %d (expected '!= 0' or '0' with "
1501         "RPC_X_NULL_REF_POINTER)\n", res, GetLastError());
1502
1503  
1504     /* with a valid buffer, but level is invalid */
1505     buffer[0] = '\0';
1506     SetLastError(0xdeadbeef);
1507     res = GetPrintProcessorDirectoryA(NULL, NULL, 2, buffer, cbBuf, &pcbNeeded);
1508     if (res && buffer[0])
1509     {
1510         /* Level is ignored in win9x*/
1511         trace("invalid level (2) was ignored\n");
1512     }
1513     else
1514     {
1515         ok( !res && (GetLastError() == ERROR_INVALID_LEVEL),
1516             "returned %d with %d (expected '0' with ERROR_INVALID_LEVEL)\n",
1517             res, GetLastError());
1518     }
1519
1520     /* Empty environment is the same as the default environment */
1521     buffer[0] = '\0';
1522     SetLastError(0xdeadbeef);
1523     res = GetPrintProcessorDirectoryA(NULL, empty, 1, buffer, cbBuf*2, &pcbNeeded);
1524     ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError());
1525
1526     /* "Windows 4.0" is valid for win9x and NT */
1527     buffer[0] = '\0';
1528     SetLastError(0xdeadbeef);
1529     res = GetPrintProcessorDirectoryA(NULL, env_win9x_case, 1, buffer, cbBuf*2, &pcbNeeded);
1530     ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError());
1531
1532
1533     /* "Windows NT x86" is invalid for win9x */
1534     buffer[0] = '\0';
1535     SetLastError(0xdeadbeef);
1536     res = GetPrintProcessorDirectoryA(NULL, env_x86, 1, buffer, cbBuf*2, &pcbNeeded);
1537     ok( res || (GetLastError() == ERROR_INVALID_ENVIRONMENT), 
1538         "returned %d with %d (expected '!= 0' or '0' with "
1539         "ERROR_INVALID_ENVIRONMENT)\n", res, GetLastError());
1540
1541     /* invalid on all Systems */
1542     buffer[0] = '\0';
1543     SetLastError(0xdeadbeef);
1544     res = GetPrintProcessorDirectoryA(NULL, invalid_env, 1, buffer, cbBuf*2, &pcbNeeded);
1545     ok( !res && (GetLastError() == ERROR_INVALID_ENVIRONMENT), 
1546         "returned %d with %d (expected '0' with ERROR_INVALID_ENVIRONMENT)\n",
1547         res, GetLastError());
1548
1549     /* Empty servername is the same as the local computer */
1550     buffer[0] = '\0';
1551     SetLastError(0xdeadbeef);
1552     res = GetPrintProcessorDirectoryA(empty, NULL, 1, buffer, cbBuf*2, &pcbNeeded);
1553     ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError());
1554
1555     /* invalid on all Systems */
1556     buffer[0] = '\0';
1557     SetLastError(0xdeadbeef);
1558     res = GetPrintProcessorDirectoryA(server_does_not_exist, NULL, 1, buffer, cbBuf*2, &pcbNeeded);
1559     ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER), 
1560         "returned %d with %d (expected '0' with ERROR_INVALID_PARAMETER)\n",
1561         res, GetLastError());
1562
1563     HeapFree(GetProcessHeap(), 0, buffer);
1564 }
1565
1566 /* ##### */
1567
1568 static void test_OpenPrinter(void)
1569 {
1570     PRINTER_DEFAULTSA   defaults;
1571     HANDLE              hprinter;
1572     DWORD               res;
1573
1574     SetLastError(MAGIC_DEAD);
1575     res = OpenPrinter(NULL, NULL, NULL);    
1576     /* The deactivated Spooler is caught here on NT3.51 */
1577     RETURN_ON_DEACTIVATED_SPOOLER(res)
1578     ok(!res && (GetLastError() == ERROR_INVALID_PARAMETER),
1579         "returned %d with %d (expected '0' with ERROR_INVALID_PARAMETER)\n",
1580         res, GetLastError());
1581
1582
1583     /* Get Handle for the local Printserver (NT only)*/
1584     hprinter = (HANDLE) MAGIC_DEAD;
1585     SetLastError(MAGIC_DEAD);
1586     res = OpenPrinter(NULL, &hprinter, NULL);
1587     /* The deactivated Spooler is caught here on XPsp2 */
1588     RETURN_ON_DEACTIVATED_SPOOLER(res)
1589     ok(res || (!res && GetLastError() == ERROR_INVALID_PARAMETER),
1590         "returned %d with %d (expected '!=0' or '0' with ERROR_INVALID_PARAMETER)\n",
1591         res, GetLastError());
1592     if(res) {
1593         ClosePrinter(hprinter);
1594
1595         defaults.pDatatype=NULL;
1596         defaults.pDevMode=NULL;
1597
1598         defaults.DesiredAccess=0;
1599         hprinter = (HANDLE) MAGIC_DEAD;
1600         SetLastError(MAGIC_DEAD);
1601         res = OpenPrinter(NULL, &hprinter, &defaults);
1602         ok(res, "returned %d with %d (expected '!=0')\n", res, GetLastError());
1603         if (res) ClosePrinter(hprinter);
1604
1605         defaults.DesiredAccess=-1;
1606         hprinter = (HANDLE) MAGIC_DEAD;
1607         SetLastError(MAGIC_DEAD);
1608         res = OpenPrinter(NULL, &hprinter, &defaults);
1609         todo_wine {
1610         ok(!res && GetLastError() == ERROR_ACCESS_DENIED,
1611             "returned %d with %d (expected '0' with ERROR_ACCESS_DENIED)\n", 
1612             res, GetLastError());
1613         }
1614         if (res) ClosePrinter(hprinter);
1615
1616     }
1617
1618
1619     if (local_server != NULL) {
1620         hprinter = (HANDLE) 0xdeadbeef;
1621         SetLastError(0xdeadbeef);
1622         res = OpenPrinter(local_server, &hprinter, NULL);
1623         ok(res || (!res && GetLastError() == ERROR_INVALID_PARAMETER),
1624             "returned %d with %d (expected '!=0' or '0' with ERROR_INVALID_PARAMETER)\n",
1625             res, GetLastError());
1626         if(res) ClosePrinter(hprinter);
1627     }
1628
1629     /* Invalid Printername */
1630     hprinter = (HANDLE) MAGIC_DEAD;
1631     SetLastError(MAGIC_DEAD);
1632     res = OpenPrinter(illegal_name, &hprinter, NULL);
1633     ok(!res && ((GetLastError() == ERROR_INVALID_PRINTER_NAME) || 
1634                 (GetLastError() == ERROR_INVALID_PARAMETER) ),
1635        "returned %d with %d (expected '0' with: ERROR_INVALID_PARAMETER or"
1636        "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
1637     if(res) ClosePrinter(hprinter);
1638
1639     hprinter = (HANDLE) MAGIC_DEAD;
1640     SetLastError(MAGIC_DEAD);
1641     res = OpenPrinter(empty, &hprinter, NULL);
1642     /* NT: ERROR_INVALID_PRINTER_NAME,  9x: ERROR_INVALID_PARAMETER */
1643     ok( !res &&
1644         ((GetLastError() == ERROR_INVALID_PRINTER_NAME) || 
1645         (GetLastError() == ERROR_INVALID_PARAMETER) ),
1646         "returned %d with %d (expected '0' with: ERROR_INVALID_PRINTER_NAME"
1647         " or ERROR_INVALID_PARAMETER)\n", res, GetLastError());
1648     if(res) ClosePrinter(hprinter);
1649
1650
1651     /* Get Handle for the default Printer */
1652     if (default_printer)
1653     {
1654         hprinter = (HANDLE) MAGIC_DEAD;
1655         SetLastError(MAGIC_DEAD);
1656         res = OpenPrinter(default_printer, &hprinter, NULL);
1657         if((!res) && (GetLastError() == RPC_S_SERVER_UNAVAILABLE))
1658         {
1659             trace("The Service 'Spooler' is required for '%s'\n", default_printer);
1660             return;
1661         }
1662         ok(res, "returned %d with %d (expected '!=0')\n", res, GetLastError());
1663         if(res) ClosePrinter(hprinter);
1664
1665         SetLastError(MAGIC_DEAD);
1666         res = OpenPrinter(default_printer, NULL, NULL);
1667         /* NT: FALSE with ERROR_INVALID_PARAMETER, 9x: TRUE */
1668         ok(res || (GetLastError() == ERROR_INVALID_PARAMETER),
1669             "returned %d with %d (expected '!=0' or '0' with "
1670             "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
1671
1672         defaults.pDatatype=NULL;
1673         defaults.pDevMode=NULL;
1674         defaults.DesiredAccess=0;
1675
1676         hprinter = (HANDLE) MAGIC_DEAD;
1677         SetLastError(MAGIC_DEAD);
1678         res = OpenPrinter(default_printer, &hprinter, &defaults);
1679         ok(res || GetLastError() == ERROR_ACCESS_DENIED,
1680             "returned %d with %d (expected '!=0' or '0' with "
1681             "ERROR_ACCESS_DENIED)\n", res, GetLastError());
1682         if(res) ClosePrinter(hprinter);
1683
1684         defaults.pDatatype = empty;
1685
1686         hprinter = (HANDLE) MAGIC_DEAD;
1687         SetLastError(MAGIC_DEAD);
1688         res = OpenPrinter(default_printer, &hprinter, &defaults);
1689         /* stop here, when a remote Printserver has no RPC-Service running */
1690         RETURN_ON_DEACTIVATED_SPOOLER(res)
1691         ok(res || ((GetLastError() == ERROR_INVALID_DATATYPE) ||
1692                    (GetLastError() == ERROR_ACCESS_DENIED)),
1693             "returned %d with %d (expected '!=0' or '0' with: "
1694             "ERROR_INVALID_DATATYPE or ERROR_ACCESS_DENIED)\n",
1695             res, GetLastError());
1696         if(res) ClosePrinter(hprinter);
1697
1698
1699         defaults.pDatatype=NULL;
1700         defaults.DesiredAccess=PRINTER_ACCESS_USE;
1701
1702         hprinter = (HANDLE) MAGIC_DEAD;
1703         SetLastError(MAGIC_DEAD);
1704         res = OpenPrinter(default_printer, &hprinter, &defaults);
1705         ok(res || GetLastError() == ERROR_ACCESS_DENIED,
1706             "returned %d with %d (expected '!=0' or '0' with "
1707             "ERROR_ACCESS_DENIED)\n", res, GetLastError());
1708         if(res) ClosePrinter(hprinter);
1709
1710
1711         defaults.DesiredAccess=PRINTER_ALL_ACCESS;
1712         hprinter = (HANDLE) MAGIC_DEAD;
1713         SetLastError(MAGIC_DEAD);
1714         res = OpenPrinter(default_printer, &hprinter, &defaults);
1715         ok(res || GetLastError() == ERROR_ACCESS_DENIED,
1716             "returned %d with %d (expected '!=0' or '0' with "
1717             "ERROR_ACCESS_DENIED)\n", res, GetLastError());
1718         if(res) ClosePrinter(hprinter);
1719     }
1720
1721 }
1722
1723
1724 static void test_SetDefaultPrinter(void)
1725 {
1726     DWORD   res;
1727     DWORD   size = DEFAULT_PRINTER_SIZE;
1728     CHAR    buffer[DEFAULT_PRINTER_SIZE];
1729     CHAR    org_value[DEFAULT_PRINTER_SIZE];
1730
1731
1732     if (!pSetDefaultPrinterA)  return;
1733         /* only supported on win2k and above */
1734
1735     /* backup the original value */
1736     org_value[0] = '\0';
1737     SetLastError(MAGIC_DEAD);
1738     res = GetProfileStringA("windows", "device", NULL, org_value, size);
1739
1740     /* first part: with the default Printer */
1741     SetLastError(MAGIC_DEAD);
1742     res = pSetDefaultPrinterA("no_printer_with_this_name");
1743
1744     RETURN_ON_DEACTIVATED_SPOOLER(res)
1745     /* spooler is running or we have no spooler here*/
1746
1747     /* Not implemented in wine */
1748     if (!res && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) {
1749         trace("SetDefaultPrinterA() not implemented yet.\n");
1750         return;
1751     }
1752
1753     ok(!res && (GetLastError() == ERROR_INVALID_PRINTER_NAME),
1754         "returned %d with %d (expected '0' with "
1755         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
1756
1757     WriteProfileStringA("windows", "device", org_value);
1758     SetLastError(MAGIC_DEAD);
1759     res = pSetDefaultPrinterA("");
1760     ok(res || (!res && (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
1761         "returned %d with %d (expected '!=0' or '0' with "
1762         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
1763
1764     WriteProfileStringA("windows", "device", org_value);
1765     SetLastError(MAGIC_DEAD);
1766     res = pSetDefaultPrinterA(NULL);
1767     ok(res || (!res && (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
1768         "returned %d with %d (expected '!=0' or '0' with "
1769         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
1770
1771     WriteProfileStringA("windows", "device", org_value);
1772     SetLastError(MAGIC_DEAD);
1773     res = pSetDefaultPrinterA(default_printer);
1774     ok(res || (!res && (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
1775         "returned %d with %d (expected '!=0' or '0' with "
1776         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
1777
1778
1779     /* second part: always without a default Printer */
1780     WriteProfileStringA("windows", "device", NULL);    
1781     SetLastError(MAGIC_DEAD);
1782     res = pSetDefaultPrinterA("no_printer_with_this_name");
1783
1784     ok(!res && (GetLastError() == ERROR_INVALID_PRINTER_NAME),
1785         "returned %d with %d (expected '0' with "
1786         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
1787
1788     WriteProfileStringA("windows", "device", NULL);    
1789     SetLastError(MAGIC_DEAD);
1790     res = pSetDefaultPrinterA("");
1791     /* we get ERROR_INVALID_PRINTER_NAME when no printer is installed */
1792     ok(res || (!res && (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
1793          "returned %d with %d (expected '!=0' or '0' with "
1794          "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
1795
1796     WriteProfileStringA("windows", "device", NULL);    
1797     SetLastError(MAGIC_DEAD);
1798     res = pSetDefaultPrinterA(NULL);
1799     /* we get ERROR_INVALID_PRINTER_NAME when no printer is installed */
1800     ok(res || (!res && (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
1801         "returned %d with %d (expected '!=0' or '0' with "
1802         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
1803
1804     WriteProfileStringA("windows", "device", NULL);    
1805     SetLastError(MAGIC_DEAD);
1806     res = pSetDefaultPrinterA(default_printer);
1807     ok(res || (!res && (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
1808         "returned %d with %d (expected '!=0' or '0' with "
1809         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
1810
1811     /* restore the original value */
1812     res = pSetDefaultPrinterA(default_printer);          /* the nice way */
1813     WriteProfileStringA("windows", "device", org_value); /* the old way */
1814
1815     buffer[0] = '\0';
1816     SetLastError(MAGIC_DEAD);
1817     res = GetProfileStringA("windows", "device", NULL, buffer, size);
1818     ok(!lstrcmpA(org_value, buffer), "'%s' (expected '%s')\n", buffer, org_value);
1819
1820 }
1821
1822 /* ########################### */
1823
1824 static void test_XcvDataW_MonitorUI(void)
1825 {
1826     DWORD   res;
1827     HANDLE  hXcv;
1828     BYTE    buffer[MAX_PATH + 4];
1829     DWORD   needed;
1830     DWORD   status;
1831     DWORD   len;
1832     PRINTER_DEFAULTSA pd;
1833
1834     /* api is not present before w2k */
1835     if (pXcvDataW == NULL) return;
1836
1837     pd.pDatatype = NULL;
1838     pd.pDevMode  = NULL;
1839     pd.DesiredAccess = SERVER_ACCESS_ADMINISTER;
1840
1841     hXcv = NULL;
1842     SetLastError(0xdeadbeef);
1843     res = OpenPrinter(xcv_localport, &hXcv, &pd);
1844     RETURN_ON_DEACTIVATED_SPOOLER(res)
1845     RETURN_ON_ACCESS_DENIED(res)
1846
1847     ok(res, "returned %d with %u and handle %p (expected '!= 0')\n", res, GetLastError(), hXcv);
1848     if (!res) return;
1849
1850     /* ask for needed size */
1851     needed = (DWORD) 0xdeadbeef;
1852     status = (DWORD) 0xdeadbeef;
1853     SetLastError(0xdeadbeef);
1854     res = pXcvDataW(hXcv, cmd_MonitorUIW, NULL, 0, NULL, 0, &needed, &status);
1855     ok( res && (status == ERROR_INSUFFICIENT_BUFFER) && (needed <= MAX_PATH),
1856         "returned %d with %u and %u for status %u (expected '!= 0' and "
1857         "'<= MAX_PATH' for status ERROR_INSUFFICIENT_BUFFER)\n",
1858         res, GetLastError(), needed, status);
1859
1860     if (needed > MAX_PATH) {
1861         ClosePrinter(hXcv);
1862         skip("buffer overflow (%u)\n", needed);
1863         return;
1864     }
1865     len = needed;       /* Size is in bytes */
1866
1867     /* the command is required */
1868     needed = (DWORD) 0xdeadbeef;
1869     status = (DWORD) 0xdeadbeef;
1870     SetLastError(0xdeadbeef);
1871     res = pXcvDataW(hXcv, emptyW, NULL, 0, NULL, 0, &needed, &status);
1872     ok( res && (status == ERROR_INVALID_PARAMETER),
1873         "returned %d with %u and %u for status %u (expected '!= 0' with "
1874         "ERROR_INVALID_PARAMETER)\n", res, GetLastError(), needed, status);
1875
1876     needed = (DWORD) 0xdeadbeef;
1877     status = (DWORD) 0xdeadbeef;
1878     SetLastError(0xdeadbeef);
1879     res = pXcvDataW(hXcv, NULL, NULL, 0, buffer, MAX_PATH, &needed, &status);
1880     ok( !res && (GetLastError() == RPC_X_NULL_REF_POINTER),
1881         "returned %d with %u and %u for status %u (expected '0' with "
1882         "RPC_X_NULL_REF_POINTER)\n", res, GetLastError(), needed, status);
1883
1884     /* "PDWORD needed" is checked before RPC-Errors */
1885     needed = (DWORD) 0xdeadbeef;
1886     status = (DWORD) 0xdeadbeef;
1887     SetLastError(0xdeadbeef);
1888     res = pXcvDataW(hXcv, cmd_MonitorUIW, NULL, 0, buffer, len, NULL, &status);
1889     ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
1890         "returned %d with %u and %u for status %u (expected '0' with "
1891         "ERROR_INVALID_PARAMETER)\n", res, GetLastError(), needed, status);
1892
1893     needed = (DWORD) 0xdeadbeef;
1894     status = (DWORD) 0xdeadbeef;
1895     SetLastError(0xdeadbeef);
1896     res = pXcvDataW(hXcv, cmd_MonitorUIW, NULL, 0, NULL, len, &needed, &status);
1897     ok( !res && (GetLastError() == RPC_X_NULL_REF_POINTER),
1898         "returned %d with %u and %u for status %u (expected '0' with "
1899         "RPC_X_NULL_REF_POINTER)\n", res, GetLastError(), needed, status);
1900
1901     needed = (DWORD) 0xdeadbeef;
1902     status = (DWORD) 0xdeadbeef;
1903     SetLastError(0xdeadbeef);
1904     res = pXcvDataW(hXcv, cmd_MonitorUIW, NULL, 0, buffer, len, &needed, NULL);
1905     ok( !res && (GetLastError() == RPC_X_NULL_REF_POINTER),
1906         "returned %d with %u and %u for status %u (expected '0' with "
1907         "RPC_X_NULL_REF_POINTER)\n", res, GetLastError(), needed, status);
1908
1909     /* off by one: larger  */
1910     needed = (DWORD) 0xdeadbeef;
1911     status = (DWORD) 0xdeadbeef;
1912     SetLastError(0xdeadbeef);
1913     res = pXcvDataW(hXcv, cmd_MonitorUIW, NULL, 0, buffer, len+1, &needed, &status);
1914     ok( res && (status == ERROR_SUCCESS),
1915         "returned %d with %u and %u for status %u (expected '!= 0' for status "
1916         "ERROR_SUCCESS)\n", res, GetLastError(), needed, status);
1917
1918     /* off by one: smaller */
1919     /* the buffer is not modified for NT4, w2k, XP */
1920     needed = (DWORD) 0xdeadbeef;
1921     status = (DWORD) 0xdeadbeef;
1922     SetLastError(0xdeadbeef);
1923     res = pXcvDataW(hXcv, cmd_MonitorUIW, NULL, 0, buffer, len-1, &needed, &status);
1924     ok( res && (status == ERROR_INSUFFICIENT_BUFFER),
1925         "returned %d with %u and %u for status %u (expected '!= 0' for status "
1926         "ERROR_INSUFFICIENT_BUFFER)\n", res, GetLastError(), needed, status);
1927
1928
1929     /* Normal use. The DLL-Name without a Path is returned */
1930     memset(buffer, 0, len);
1931     needed = (DWORD) 0xdeadbeef;
1932     status = (DWORD) 0xdeadbeef;
1933     SetLastError(0xdeadbeef);
1934     res = pXcvDataW(hXcv, cmd_MonitorUIW, NULL, 0, buffer, len, &needed, &status);
1935     ok( res && (status == ERROR_SUCCESS),
1936         "returned %d with %u and %u for status %u (expected '!= 0' for status "
1937         "ERROR_SUCCESS)\n", res, GetLastError(), needed, status);
1938
1939     ClosePrinter(hXcv);
1940 }
1941
1942 /* ########################### */
1943
1944 static void test_XcvDataW_PortIsValid(void)
1945 {
1946     DWORD   res;
1947     HANDLE  hXcv;
1948     DWORD   needed;
1949     DWORD   status;
1950     PRINTER_DEFAULTSA   pd;
1951
1952     /* api is not present before w2k */
1953     if (pXcvDataW == NULL) return;
1954
1955     pd.pDatatype = NULL;
1956     pd.pDevMode  = NULL;
1957     pd.DesiredAccess = SERVER_ACCESS_ADMINISTER;
1958
1959     hXcv = NULL;
1960     SetLastError(0xdeadbeef);
1961     res = OpenPrinter(xcv_localport, &hXcv, &pd);
1962
1963     RETURN_ON_DEACTIVATED_SPOOLER(res)
1964     RETURN_ON_ACCESS_DENIED(res)
1965
1966     ok(res, "returned %d with %u and handle %p (expected '!= 0')\n", res, GetLastError(), hXcv);
1967     if (!res) return;
1968
1969
1970     /* "PDWORD needed" is always required */
1971     needed = (DWORD) 0xdeadbeef;
1972     status = (DWORD) 0xdeadbeef;
1973     SetLastError(0xdeadbeef);
1974     res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) portname_lpt1W, sizeof(portname_lpt1W), NULL, 0, NULL, &status);
1975     ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
1976         "returned %d with %u and %u for status %u (expected '!= 0' with ERROR_INVALID_PARAMETER)\n",
1977          res, GetLastError(), needed, status);
1978
1979     /* an empty name is not allowed */
1980     needed = (DWORD) 0xdeadbeef;
1981     status = (DWORD) 0xdeadbeef;
1982     SetLastError(0xdeadbeef);
1983     res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) emptyW, sizeof(emptyW), NULL, 0, &needed, &status);
1984     ok( res && ((status == ERROR_FILE_NOT_FOUND) || (status == ERROR_PATH_NOT_FOUND)),
1985         "returned %d with %u and %u for status %u (expected '!= 0' for status: "
1986         "ERROR_FILE_NOT_FOUND or ERROR_PATH_NOT_FOUND)\n",
1987         res, GetLastError(), needed, status);
1988
1989     /* a directory is not allowed */
1990     needed = (DWORD) 0xdeadbeef;
1991     status = (DWORD) 0xdeadbeef;
1992     SetLastError(0xdeadbeef);
1993     res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) tempdirW, (lstrlenW(tempdirW) + 1) * sizeof(WCHAR), NULL, 0, &needed, &status);
1994     /* XP: ERROR_PATH_NOT_FOUND, w2k ERROR_ACCESS_DENIED */
1995     ok( res && ((status == ERROR_PATH_NOT_FOUND) || (status == ERROR_ACCESS_DENIED)),
1996         "returned %d with %u and %u for status %u (expected '!= 0' for status: "
1997         "ERROR_PATH_NOT_FOUND or ERROR_ACCESS_DENIED)\n",
1998         res, GetLastError(), needed, status);
1999
2000     /* more valid well known Ports */
2001     needed = (DWORD) 0xdeadbeef;
2002     status = (DWORD) 0xdeadbeef;
2003     SetLastError(0xdeadbeef);
2004     res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) portname_lpt1W, sizeof(portname_lpt1W), NULL, 0, &needed, &status);
2005     ok( res && (status == ERROR_SUCCESS),
2006         "returned %d with %u and %u for status %u (expected '!= 0' for ERROR_SUCCESS)\n",
2007         res, GetLastError(), needed, status);
2008
2009     needed = (DWORD) 0xdeadbeef;
2010     status = (DWORD) 0xdeadbeef;
2011     SetLastError(0xdeadbeef);
2012     res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) portname_lpt2W, sizeof(portname_lpt2W), NULL, 0, &needed, &status);
2013     ok( res && (status == ERROR_SUCCESS),
2014         "returned %d with %u and %u for status %u (expected '!= 0' for ERROR_SUCCESS)\n",
2015         res, GetLastError(), needed, status);
2016
2017     needed = (DWORD) 0xdeadbeef;
2018     status = (DWORD) 0xdeadbeef;
2019     SetLastError(0xdeadbeef);
2020     res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) portname_com1W, sizeof(portname_com1W), NULL, 0, &needed, &status);
2021     ok( res && (status == ERROR_SUCCESS),
2022         "returned %d with %u and %u for status %u (expected '!= 0' for ERROR_SUCCESS)\n",
2023         res, GetLastError(), needed, status);
2024
2025     needed = (DWORD) 0xdeadbeef;
2026     status = (DWORD) 0xdeadbeef;
2027     SetLastError(0xdeadbeef);
2028     res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) portname_com2W, sizeof(portname_com2W), NULL, 0, &needed, &status);
2029     ok( res && (status == ERROR_SUCCESS),
2030         "returned %d with %u and %u for status %u (expected '!= 0' for ERROR_SUCCESS)\n",
2031         res, GetLastError(), needed, status);
2032
2033     needed = (DWORD) 0xdeadbeef;
2034     status = (DWORD) 0xdeadbeef;
2035     SetLastError(0xdeadbeef);
2036     res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) portname_fileW, sizeof(portname_fileW), NULL, 0, &needed, &status);
2037     ok( res && (status == ERROR_SUCCESS),
2038         "returned %d with %u and %u for status %u (expected '!= 0' with  ERROR_SUCCESS)\n",
2039         res, GetLastError(), needed, status);
2040
2041
2042     /* a normal, writable file is allowed */
2043     needed = (DWORD) 0xdeadbeef;
2044     status = (DWORD) 0xdeadbeef;
2045     SetLastError(0xdeadbeef);
2046     res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) tempfileW, (lstrlenW(tempfileW) + 1) * sizeof(WCHAR), NULL, 0, &needed, &status);
2047     ok( res && (status == ERROR_SUCCESS),
2048         "returned %d with %u and %u for status %u (expected '!= 0' with ERROR_SUCCESS)\n",
2049         res, GetLastError(), needed, status);
2050
2051     ClosePrinter(hXcv);
2052 }
2053
2054 /* ########################### */
2055
2056 static void test_GetPrinterDriver(void)
2057 {
2058     HANDLE hprn;
2059     BOOL ret;
2060     BYTE *buf;
2061     INT level;
2062     DWORD needed, filled;
2063
2064     if (!default_printer)
2065     {
2066         skip("There is no default printer installed\n");
2067         return;
2068     }
2069
2070     hprn = 0;
2071     ret = OpenPrinter(default_printer, &hprn, NULL);
2072     if (!ret)
2073     {
2074         skip("Unable to open the default printer (%s)\n", default_printer);
2075         return;
2076     }
2077     ok(hprn != 0, "wrong hprn %p\n", hprn);
2078
2079     for (level = -1; level <= 7; level++)
2080     {
2081         SetLastError(0xdeadbeef);
2082         needed = (DWORD)-1;
2083         ret = GetPrinterDriver(hprn, NULL, level, NULL, 0, &needed);
2084         ok(!ret, "level %d: GetPrinterDriver should fail\n", level);
2085         if (level >= 1 && level <= 6)
2086         {
2087             /* Not all levels are supported on all Windows-Versions */
2088             if(GetLastError() == ERROR_INVALID_LEVEL) continue;
2089             ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "wrong error %d\n", GetLastError());
2090             ok(needed > 0,"not expected needed buffer size %d\n", needed);
2091         }
2092         else
2093         {
2094             /* ERROR_OUTOFMEMORY found on win9x */
2095             ok( ((GetLastError() == ERROR_INVALID_LEVEL) ||
2096                  (GetLastError() == ERROR_OUTOFMEMORY)),
2097                 "%d: returned %d with %d (expected '0' with: "
2098                 "ERROR_INVALID_LEVEL or ERROR_OUTOFMEMORY)\n",
2099                 level, ret, GetLastError());
2100             /* needed is modified in win9x. The modified Value depends on the
2101                default Printer. testing for "needed == (DWORD)-1" will fail */
2102             continue;
2103         }
2104
2105         buf = HeapAlloc(GetProcessHeap(), 0, needed);
2106
2107         SetLastError(0xdeadbeef);
2108         filled = -1;
2109         ret = GetPrinterDriver(hprn, NULL, level, buf, needed, &filled);
2110         ok(ret, "level %d: GetPrinterDriver error %d\n", level, GetLastError());
2111         ok(needed == filled, "needed %d != filled %d\n", needed, filled);
2112
2113         if (level == 2)
2114         {
2115             DRIVER_INFO_2 *di_2 = (DRIVER_INFO_2 *)buf;
2116             DWORD calculated = sizeof(*di_2);
2117
2118             /* MSDN is wrong: The Drivers on the win9x-CD's have cVersion=0x0400
2119                NT351: 1, NT4.0+w2k(Kernelmode): 2, w2k and above(Usermode): 3  */
2120             ok( (di_2->cVersion <= 3) ||
2121                 (di_2->cVersion == 0x0400), "di_2->cVersion = %d\n", di_2->cVersion);
2122             ok(di_2->pName != NULL, "not expected NULL ptr\n");
2123             ok(di_2->pEnvironment != NULL, "not expected NULL ptr\n");
2124             ok(di_2->pDriverPath != NULL, "not expected NULL ptr\n");
2125             ok(di_2->pDataFile != NULL, "not expected NULL ptr\n");
2126             ok(di_2->pConfigFile != NULL, "not expected NULL ptr\n");
2127
2128             trace("cVersion %d\n", di_2->cVersion);
2129             trace("pName %s\n", di_2->pName);
2130             calculated += strlen(di_2->pName) + 1;
2131             trace("pEnvironment %s\n", di_2->pEnvironment);
2132             calculated += strlen(di_2->pEnvironment) + 1;
2133             trace("pDriverPath %s\n", di_2->pDriverPath);
2134             calculated += strlen(di_2->pDriverPath) + 1;
2135             trace("pDataFile %s\n", di_2->pDataFile);
2136             calculated += strlen(di_2->pDataFile) + 1;
2137             trace("pConfigFile %s\n", di_2->pConfigFile);
2138             calculated += strlen(di_2->pConfigFile) + 1;
2139
2140             /* XP allocates memory for both ANSI and unicode names */
2141             ok(filled >= calculated,"calculated %d != filled %d\n", calculated, filled);
2142         }
2143
2144         HeapFree(GetProcessHeap(), 0, buf);
2145     }
2146
2147     SetLastError(0xdeadbeef);
2148     ret = ClosePrinter(hprn);
2149     ok(ret, "ClosePrinter error %d\n", GetLastError());
2150 }
2151
2152 static void test_DEVMODE(const DEVMODE *dm, LONG dmSize, LPCSTR exp_prn_name)
2153 {
2154     /* On NT3.51, some fields in DEVMODE are empty/zero
2155       (dmDeviceName, dmSpecVersion, dmDriverVersion and dmDriverExtra)
2156        We skip the Tests on this Platform */
2157     if (dm->dmSpecVersion || dm->dmDriverVersion || dm->dmDriverExtra) {
2158     /* The 0-terminated Printername can be larger (MAX_PATH) than CCHDEVICENAME */
2159         ok(!strncmp(exp_prn_name, (LPCSTR)dm->dmDeviceName, CCHDEVICENAME -1),
2160             "expected '%s', got '%s'\n", exp_prn_name, dm->dmDeviceName);
2161         ok(dm->dmSize + dm->dmDriverExtra == dmSize,
2162             "%u != %d\n", dm->dmSize + dm->dmDriverExtra, dmSize);
2163     }
2164     trace("dmFields %08x\n", dm->dmFields);
2165 }
2166
2167 static void test_DocumentProperties(void)
2168 {
2169     HANDLE hprn;
2170     LONG dm_size, ret;
2171     DEVMODE *dm;
2172
2173     if (!default_printer)
2174     {
2175         skip("There is no default printer installed\n");
2176         return;
2177     }
2178
2179     hprn = 0;
2180     ret = OpenPrinter(default_printer, &hprn, NULL);
2181     if (!ret)
2182     {
2183         skip("Unable to open the default printer (%s)\n", default_printer);
2184         return;
2185     }
2186     ok(hprn != 0, "wrong hprn %p\n", hprn);
2187
2188     dm_size = DocumentProperties(0, hprn, NULL, NULL, NULL, 0);
2189     trace("DEVMODE required size %d\n", dm_size);
2190     ok(dm_size >= sizeof(DEVMODE), "unexpected DocumentProperties ret value %d\n", dm_size);
2191
2192     dm = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dm_size);
2193
2194     ret = DocumentProperties(0, hprn, NULL, dm, dm, DM_OUT_BUFFER);
2195     ok(ret == IDOK, "DocumentProperties ret value %d != expected IDOK\n", ret);
2196
2197     test_DEVMODE(dm, dm_size, default_printer);
2198
2199     HeapFree(GetProcessHeap(), 0, dm);
2200
2201     SetLastError(0xdeadbeef);
2202     ret = ClosePrinter(hprn);
2203     ok(ret, "ClosePrinter error %d\n", GetLastError());
2204 }
2205
2206 static void test_EnumPrinters(void)
2207 {
2208     DWORD neededA, neededW, num;
2209     DWORD ret;
2210
2211     SetLastError(0xdeadbeef);
2212     neededA = -1;
2213     ret = EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &neededA, &num);
2214     RETURN_ON_DEACTIVATED_SPOOLER(ret)
2215     if (!ret)
2216     {
2217         /* We have 1 or more printers */
2218         ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "gle %d\n", GetLastError());
2219         ok(neededA > 0, "Expected neededA to show the number of needed bytes\n");
2220     }
2221     else
2222     {
2223         /* We don't have any printers defined */
2224         ok(GetLastError() == S_OK, "gle %d\n", GetLastError());
2225         ok(neededA == 0, "Expected neededA to be zero\n");
2226     }
2227     ok(num == 0, "num %d\n", num);
2228
2229     SetLastError(0xdeadbeef);
2230     neededW = -1;
2231     ret = EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &neededW, &num);
2232     /* EnumPrintersW is not supported on all platforms */
2233     if (!ret && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
2234     {
2235         skip("EnumPrintersW is not implemented\n");
2236         return;
2237     }
2238
2239     if (!ret)
2240     {
2241         /* We have 1 or more printers */
2242         ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "gle %d\n", GetLastError());
2243         ok(neededW > 0, "Expected neededW to show the number of needed bytes\n");
2244     }
2245     else
2246     {
2247         /* We don't have any printers defined */
2248         ok(GetLastError() == S_OK, "gle %d\n", GetLastError());
2249         ok(neededW == 0, "Expected neededW to be zero\n");
2250     }
2251     ok(num == 0, "num %d\n", num);
2252
2253     /* Outlook2003 relies on the buffer size returned by EnumPrintersA being big enough
2254        to hold the buffer returned by EnumPrintersW */
2255     ok(neededA == neededW, "neededA %d neededW %d\n", neededA, neededW);
2256 }
2257
2258 static void test_DeviceCapabilities(void)
2259 {
2260     HANDLE hComdlg32;
2261     BOOL (WINAPI *pPrintDlgA)(PRINTDLGA *);
2262     PRINTDLGA prn_dlg;
2263     DEVMODE *dm;
2264     DEVNAMES *dn;
2265     const char *driver, *device, *port;
2266     WORD *papers;
2267     POINT *paper_size;
2268     POINTS ext;
2269     struct
2270     {
2271         char name[64];
2272     } *paper_name;
2273     INT n_papers, n_paper_size, n_paper_names, n_copies, ret;
2274     DWORD fields;
2275
2276     hComdlg32 = LoadLibrary("comdlg32.dll");
2277     assert(hComdlg32);
2278     pPrintDlgA = (void *)GetProcAddress(hComdlg32, "PrintDlgA");
2279     assert(pPrintDlgA);
2280
2281     memset(&prn_dlg, 0, sizeof(prn_dlg));
2282     prn_dlg.lStructSize = sizeof(prn_dlg);
2283     prn_dlg.Flags = PD_RETURNDEFAULT;
2284     ret = pPrintDlgA(&prn_dlg);
2285     FreeLibrary(hComdlg32);
2286     if (!ret)
2287     {
2288         skip("PrintDlg returned no default printer\n");
2289         return;
2290     }
2291     ok(prn_dlg.hDevMode != 0, "PrintDlg returned hDevMode == NULL\n");
2292     ok(prn_dlg.hDevNames != 0, "PrintDlg returned hDevNames == NULL\n");
2293
2294     dm = GlobalLock(prn_dlg.hDevMode);
2295     ok(dm != NULL, "GlobalLock(prn_dlg.hDevMode) failed\n");
2296     trace("dmDeviceName \"%s\"\n", dm->dmDeviceName);
2297
2298     dn = GlobalLock(prn_dlg.hDevNames);
2299     ok(dn != NULL, "GlobalLock(prn_dlg.hDevNames) failed\n");
2300     ok(dn->wDriverOffset, "expected not 0 wDriverOffset\n");
2301     ok(dn->wDeviceOffset, "expected not 0 wDeviceOffset\n");
2302     ok(dn->wOutputOffset, "expected not 0 wOutputOffset\n");
2303     ok(dn->wDefault == DN_DEFAULTPRN, "expected DN_DEFAULTPRN got %x\n", dn->wDefault);
2304     driver = (const char *)dn + dn->wDriverOffset;
2305     device = (const char *)dn + dn->wDeviceOffset;
2306     port = (const char *)dn + dn->wOutputOffset;
2307     trace("driver \"%s\" device \"%s\" port \"%s\"\n", driver, device, port);
2308
2309     test_DEVMODE(dm, dm->dmSize + dm->dmDriverExtra, device);
2310
2311     n_papers = DeviceCapabilities(device, port, DC_PAPERS, NULL, NULL);
2312     ok(n_papers > 0, "DeviceCapabilities DC_PAPERS failed\n");
2313     papers = HeapAlloc(GetProcessHeap(), 0, sizeof(*papers) * n_papers);
2314     ret = DeviceCapabilities(device, port, DC_PAPERS, (LPSTR)papers, NULL);
2315     ok(ret == n_papers, "expected %d, got %d\n", n_papers, ret);
2316 #if VERBOSE
2317     for (ret = 0; ret < n_papers; ret++)
2318         trace("papers[%d] = %d\n", ret, papers[ret]);
2319 #endif
2320     HeapFree(GetProcessHeap(), 0, papers);
2321
2322     n_paper_size = DeviceCapabilities(device, port, DC_PAPERSIZE, NULL, NULL);
2323     ok(n_paper_size > 0, "DeviceCapabilities DC_PAPERSIZE failed\n");
2324     ok(n_paper_size == n_papers, "n_paper_size %d != n_papers %d\n", n_paper_size, n_papers);
2325     paper_size = HeapAlloc(GetProcessHeap(), 0, sizeof(*paper_size) * n_paper_size);
2326     ret = DeviceCapabilities(device, port, DC_PAPERSIZE, (LPSTR)paper_size, NULL);
2327     ok(ret == n_paper_size, "expected %d, got %d\n", n_paper_size, ret);
2328 #if VERBOSE
2329     for (ret = 0; ret < n_paper_size; ret++)
2330         trace("paper_size[%d] = %d x %d\n", ret, paper_size[ret].x, paper_size[ret].y);
2331 #endif
2332     HeapFree(GetProcessHeap(), 0, paper_size);
2333
2334     n_paper_names = DeviceCapabilities(device, port, DC_PAPERNAMES, NULL, NULL);
2335     ok(n_paper_names > 0, "DeviceCapabilities DC_PAPERNAMES failed\n");
2336     ok(n_paper_names == n_papers, "n_paper_names %d != n_papers %d\n", n_paper_names, n_papers);
2337     paper_name = HeapAlloc(GetProcessHeap(), 0, sizeof(*paper_name) * n_paper_names);
2338     ret = DeviceCapabilities(device, port, DC_PAPERNAMES, (LPSTR)paper_name, NULL);
2339     ok(ret == n_paper_names, "expected %d, got %d\n", n_paper_names, ret);
2340 #if VERBOSE
2341     for (ret = 0; ret < n_paper_names; ret++)
2342         trace("paper_name[%u] = %s\n", ret, paper_name[ret].name);
2343 #endif
2344     HeapFree(GetProcessHeap(), 0, paper_name);
2345
2346     n_copies = DeviceCapabilities(device, port, DC_COPIES, NULL, dm);
2347     ok(n_copies > 0, "DeviceCapabilities DC_COPIES failed\n");
2348     trace("n_copies = %d\n", n_copies);
2349
2350     /* these capabilities not available on all printer drivers */
2351     if (0)
2352     {
2353         ret = DeviceCapabilities(device, port, DC_MAXEXTENT, NULL, NULL);
2354         ok(ret != -1, "DeviceCapabilities DC_MAXEXTENT failed\n");
2355         ext = MAKEPOINTS(ret);
2356         trace("max ext = %d x %d\n", ext.x, ext.y);
2357
2358         ret = DeviceCapabilities(device, port, DC_MINEXTENT, NULL, NULL);
2359         ok(ret != -1, "DeviceCapabilities DC_MINEXTENT failed\n");
2360         ext = MAKEPOINTS(ret);
2361         trace("min ext = %d x %d\n", ext.x, ext.y);
2362     }
2363
2364     fields = DeviceCapabilities(device, port, DC_FIELDS, NULL, NULL);
2365     ok(fields != (DWORD)-1, "DeviceCapabilities DC_FIELDS failed\n");
2366     ok(fields == dm->dmFields, "fields %x != dm->dmFields %x\n", fields, dm->dmFields);
2367
2368     GlobalUnlock(prn_dlg.hDevMode);
2369     GlobalFree(prn_dlg.hDevMode);
2370     GlobalUnlock(prn_dlg.hDevNames);
2371     GlobalFree(prn_dlg.hDevNames);
2372 }
2373
2374 START_TEST(info)
2375 {
2376     hwinspool = GetModuleHandleA("winspool.drv");
2377     pGetDefaultPrinterA = (void *) GetProcAddress(hwinspool, "GetDefaultPrinterA");
2378     pSetDefaultPrinterA = (void *) GetProcAddress(hwinspool, "SetDefaultPrinterA");
2379     pXcvDataW = (void *) GetProcAddress(hwinspool, "XcvDataW");
2380     pAddPortExA = (void *) GetProcAddress(hwinspool, "AddPortExA");
2381
2382     find_default_printer();
2383     find_local_server();
2384     find_tempfile();
2385
2386     test_AddMonitor();
2387     test_AddPort();
2388     test_AddPortEx();
2389     test_ConfigurePort();
2390     test_DeleteMonitor();
2391     test_DeletePort();
2392     test_DeviceCapabilities();
2393     test_DocumentProperties();
2394     test_EnumForms(NULL);
2395     if (default_printer) test_EnumForms(default_printer);
2396     test_EnumMonitors();
2397     test_EnumPorts();
2398     test_EnumPrinterDrivers();
2399     test_EnumPrinters();
2400     test_GetDefaultPrinter();
2401     test_GetPrinterDriverDirectory();
2402     test_GetPrintProcessorDirectory();
2403     test_OpenPrinter();
2404     test_GetPrinterDriver();
2405     test_SetDefaultPrinter();
2406     test_XcvDataW_MonitorUI();
2407     test_XcvDataW_PortIsValid();
2408
2409     /* Cleanup our temporary file */
2410     DeleteFileA(tempfileA);
2411 }