winspool/tests: Fix 2 failing tests for restricted users.
[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, "returned %d with %d (expected '!=0')\n", res, GetLastError());
697
698     /* the monitor-name */
699     AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
700     SetLastError(MAGIC_DEAD);
701     res = DeleteMonitorA(NULL, entry->env, NULL);
702     /* NT: ERROR_INVALID_PARAMETER (87),  9x: ERROR_INVALID_NAME (123)*/
703     ok( !res &&
704         ((GetLastError() == ERROR_INVALID_PARAMETER) ||
705         (GetLastError() == ERROR_INVALID_NAME)),
706         "returned %d with %d (expected '0' with: ERROR_INVALID_PARAMETER or "
707         "ERROR_INVALID_NAME)\n", res, GetLastError());
708
709     AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
710     SetLastError(MAGIC_DEAD);
711     res = DeleteMonitorA(NULL, entry->env, empty);
712     /* NT: ERROR_INVALID_PARAMETER (87),  9x: ERROR_INVALID_NAME (123)*/
713     ok( !res && 
714         ((GetLastError() == ERROR_INVALID_PARAMETER) ||
715         (GetLastError() == ERROR_INVALID_NAME)),
716         "returned %d with %d (expected '0' with: ERROR_INVALID_PARAMETER or "
717         "ERROR_INVALID_NAME)\n", res, GetLastError());
718
719     AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
720     SetLastError(MAGIC_DEAD);
721     res = DeleteMonitorA(empty, entry->env, winetest);
722     ok(res, "returned %d with %d (expected '!=0')\n", res, GetLastError());
723
724     /* cleanup */
725     DeleteMonitorA(NULL, entry->env, winetest);
726 }
727
728 /* ########################### */
729
730 static void test_DeletePort(void)
731 {
732     DWORD   res;
733
734     SetLastError(0xdeadbeef);
735     res = DeletePortA(NULL, 0, NULL);
736     RETURN_ON_DEACTIVATED_SPOOLER(res)
737
738     SetLastError(0xdeadbeef);
739     res = DeletePortA(NULL, 0, empty);
740     /* Allowed only for (Printer-)Administrators */
741     RETURN_ON_ACCESS_DENIED(res)
742
743     /* XP: ERROR_NOT_SUPPORTED, NT351 and 9x: ERROR_INVALID_PARAMETER */
744     ok( !res && ((GetLastError() == ERROR_NOT_SUPPORTED) || 
745                  (GetLastError() == ERROR_INVALID_PARAMETER)),
746         "returned %d with %d (expected '0' with ERROR_NOT_SUPPORTED or "
747         "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
748
749
750     SetLastError(0xdeadbeef);
751     res = DeletePortA(NULL, 0, does_not_exist);
752     /* XP: ERROR_NOT_SUPPORTED, NT351 and 9x: ERROR_INVALID_PARAMETER */
753     ok( !res && ((GetLastError() == ERROR_NOT_SUPPORTED) || 
754                  (GetLastError() == ERROR_INVALID_PARAMETER)),
755         "returned %d with %d (expected '0' with ERROR_NOT_SUPPORTED or "
756         "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
757
758 }
759
760 /* ########################### */
761
762 static void test_EnumForms(LPSTR pName)
763 {
764     DWORD   res;
765     HANDLE  hprinter = 0;
766     LPBYTE  buffer;
767     DWORD   cbBuf;
768     DWORD   pcbNeeded;
769     DWORD   pcReturned;
770     DWORD   level;
771   
772
773     res = OpenPrinter(pName, &hprinter, NULL);
774     RETURN_ON_DEACTIVATED_SPOOLER(res)
775     if (!res || !hprinter)
776     {
777         /* Open the local Prinserver is not supported on win9x */
778         if (pName) skip("Failed to open '%s' (not supported on win9x)\n", pName);
779         return;
780     }
781
782     /* valid levels are 1 and 2 */
783     for(level = 0; level < 4; level++) {
784         cbBuf = 0xdeadbeef;
785         pcReturned = 0xdeadbeef;
786         SetLastError(0xdeadbeef);
787         res = EnumFormsA(hprinter, level, NULL, 0, &cbBuf, &pcReturned);
788        
789         /* EnumForms is not implemented in win9x */
790         if (!res && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) continue;
791
792         /* EnumForms for the Server not implemented on all NT-Versions */
793         if (!res && (GetLastError() == ERROR_INVALID_HANDLE) && !pName) continue;
794
795         /* Level 2 for EnumForms is not supported on all systems */
796         if (!res && (GetLastError() == ERROR_INVALID_LEVEL) && (level == 2)) continue;
797
798         /* use only a short test, when we test with an invalid level */
799         if(!level || (level > 2)) {
800             ok( (!res && (GetLastError() == ERROR_INVALID_LEVEL)) ||
801                 (res && (pcReturned == 0)),
802                 "(%d) returned %d with %d and 0x%08x (expected '0' with "
803                 "ERROR_INVALID_LEVEL or '!=0' and 0x0)\n",
804                 level, res, GetLastError(), pcReturned);
805             continue;
806         }        
807
808         ok((!res) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
809             "(%d) returned %d with %d (expected '0' with "
810             "ERROR_INSUFFICIENT_BUFFER)\n", level, res, GetLastError());
811
812         buffer = HeapAlloc(GetProcessHeap(), 0, cbBuf *2);
813         if (buffer == NULL) continue;
814
815         SetLastError(0xdeadbeef);
816         res = EnumFormsA(hprinter, level, buffer, cbBuf, &pcbNeeded, &pcReturned);
817         ok(res, "(%d) returned %d with %d (expected '!=0')\n",
818                 level, res, GetLastError());
819         /* We can dump the returned Data here */
820
821
822         SetLastError(0xdeadbeef);
823         res = EnumFormsA(hprinter, level, buffer, cbBuf+1, &pcbNeeded, &pcReturned);
824         ok( res, "(%d) returned %d with %d (expected '!=0')\n",
825             level, res, GetLastError());
826
827         SetLastError(0xdeadbeef);
828         res = EnumFormsA(hprinter, level, buffer, cbBuf-1, &pcbNeeded, &pcReturned);
829         ok( !res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
830             "(%d) returned %d with %d (expected '0' with "
831             "ERROR_INSUFFICIENT_BUFFER)\n", level, res, GetLastError());
832
833
834         SetLastError(0xdeadbeef);
835         res = EnumFormsA(hprinter, level, NULL, cbBuf, &pcbNeeded, &pcReturned);
836         ok( !res && (GetLastError() == ERROR_INVALID_USER_BUFFER) ,
837             "(%d) returned %d with %d (expected '0' with "
838             "ERROR_INVALID_USER_BUFFER)\n", level, res, GetLastError());
839
840
841         SetLastError(0xdeadbeef);
842         res = EnumFormsA(hprinter, level, buffer, cbBuf, NULL, &pcReturned);
843         ok( !res && (GetLastError() == RPC_X_NULL_REF_POINTER) ,
844             "(%d) returned %d with %d (expected '0' with "
845             "RPC_X_NULL_REF_POINTER)\n", level, res, GetLastError());
846
847         SetLastError(0xdeadbeef);
848         res = EnumFormsA(hprinter, level, buffer, cbBuf, &pcbNeeded, NULL);
849         ok( !res && (GetLastError() == RPC_X_NULL_REF_POINTER) ,
850             "(%d) returned %d with %d (expected '0' with "
851             "RPC_X_NULL_REF_POINTER)\n", level, res, GetLastError());
852
853         SetLastError(0xdeadbeef);
854         res = EnumFormsA(0, level, buffer, cbBuf, &pcbNeeded, &pcReturned);
855         ok( !res && (GetLastError() == ERROR_INVALID_HANDLE) ,
856             "(%d) returned %d with %d (expected '0' with "
857             "ERROR_INVALID_HANDLE)\n", level, res, GetLastError());
858
859         HeapFree(GetProcessHeap(), 0, buffer);
860     } /* for(level ... */
861
862     ClosePrinter(hprinter);
863 }
864
865 /* ########################### */
866
867 static void test_EnumMonitors(void)
868 {
869     DWORD   res;
870     LPBYTE  buffer;
871     DWORD   cbBuf;
872     DWORD   pcbNeeded;
873     DWORD   pcReturned;
874     DWORD   level;
875
876     /* valid levels are 1 and 2 */
877     for(level = 0; level < 4; level++) {
878         cbBuf = MAGIC_DEAD;
879         pcReturned = MAGIC_DEAD;
880         SetLastError(MAGIC_DEAD);
881         res = EnumMonitorsA(NULL, level, NULL, 0, &cbBuf, &pcReturned);
882
883         RETURN_ON_DEACTIVATED_SPOOLER(res)
884
885         /* not implemented yet in wine */
886         if (!res && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) continue;
887
888
889         /* use only a short test, when we test with an invalid level */
890         if(!level || (level > 2)) {
891             ok( (!res && (GetLastError() == ERROR_INVALID_LEVEL)) ||
892                 (res && (pcReturned == 0)),
893                 "(%d) returned %d with %d and 0x%08x (expected '0' with "
894                 "ERROR_INVALID_LEVEL or '!=0' and 0x0)\n",
895                 level, res, GetLastError(), pcReturned);
896             continue;
897         }        
898
899         /* Level 2 is not supported on win9x */
900         if (!res && (GetLastError() == ERROR_INVALID_LEVEL)) {
901             skip("Level %d not supported\n", level);
902             continue;
903         }
904
905         ok((!res) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
906             "(%d) returned %d with %d (expected '0' with "
907             "ERROR_INSUFFICIENT_BUFFER)\n", level, res, GetLastError());
908
909         if (!cbBuf) {
910             skip("no valid buffer size returned\n");
911             continue;
912         }
913
914         buffer = HeapAlloc(GetProcessHeap(), 0, cbBuf *2);
915         if (buffer == NULL) continue;
916
917         SetLastError(MAGIC_DEAD);
918         pcbNeeded = MAGIC_DEAD;
919         res = EnumMonitorsA(NULL, level, buffer, cbBuf, &pcbNeeded, &pcReturned);
920         ok(res, "(%d) returned %d with %d (expected '!=0')\n",
921                 level, res, GetLastError());
922         ok(pcbNeeded == cbBuf, "(%d) returned %d (expected %d)\n",
923                 level, pcbNeeded, cbBuf);
924         /* We can validate the returned Data with the Registry here */
925
926
927         SetLastError(MAGIC_DEAD);
928         pcReturned = MAGIC_DEAD;
929         pcbNeeded = MAGIC_DEAD;
930         res = EnumMonitorsA(NULL, level, buffer, cbBuf+1, &pcbNeeded, &pcReturned);
931         ok(res, "(%d) returned %d with %d (expected '!=0')\n", level,
932                 res, GetLastError());
933         ok(pcbNeeded == cbBuf, "(%d) returned %d (expected %d)\n", level,
934                 pcbNeeded, cbBuf);
935
936         SetLastError(MAGIC_DEAD);
937         pcbNeeded = MAGIC_DEAD;
938         res = EnumMonitorsA(NULL, level, buffer, cbBuf-1, &pcbNeeded, &pcReturned);
939         ok( !res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
940             "(%d) returned %d with %d (expected '0' with "
941             "ERROR_INSUFFICIENT_BUFFER)\n", level, res, GetLastError());
942
943         ok(pcbNeeded == cbBuf, "(%d) returned %d (expected %d)\n", level,
944                 pcbNeeded, cbBuf);
945
946 /*
947       Do not add the next test:
948       w2k+:  RPC_X_NULL_REF_POINTER 
949       NT3.5: ERROR_INVALID_USER_BUFFER
950       win9x: crash in winspool.drv
951
952       res = EnumMonitorsA(NULL, level, NULL, cbBuf, &pcbNeeded, &pcReturned);
953 */
954
955         SetLastError(MAGIC_DEAD);
956         pcbNeeded = MAGIC_DEAD;
957         pcReturned = MAGIC_DEAD;
958         res = EnumMonitorsA(NULL, level, buffer, cbBuf, NULL, &pcReturned);
959         ok( res || (!res && (GetLastError() == RPC_X_NULL_REF_POINTER)) ,
960             "(%d) returned %d with %d (expected '!=0' or '0' with "
961             "RPC_X_NULL_REF_POINTER)\n", level, res, GetLastError());
962
963         pcbNeeded = MAGIC_DEAD;
964         pcReturned = MAGIC_DEAD;
965         SetLastError(MAGIC_DEAD);
966         res = EnumMonitorsA(NULL, level, buffer, cbBuf, &pcbNeeded, NULL);
967         ok( res || (!res && (GetLastError() == RPC_X_NULL_REF_POINTER)) ,
968             "(%d) returned %d with %d (expected '!=0' or '0' with "
969             "RPC_X_NULL_REF_POINTER)\n", level, res, GetLastError());
970
971         HeapFree(GetProcessHeap(), 0, buffer);
972     } /* for(level ... */
973 }
974
975 /* ########################### */
976
977 static void test_EnumPorts(void)
978 {
979     DWORD   res;
980     DWORD   level;
981     LPBYTE  buffer;
982     DWORD   cbBuf;
983     DWORD   pcbNeeded;
984     DWORD   pcReturned;
985
986     /* valid levels are 1 and 2 */
987     for(level = 0; level < 4; level++) {
988
989         cbBuf = 0xdeadbeef;
990         pcReturned = 0xdeadbeef;
991         SetLastError(0xdeadbeef);
992         res = EnumPortsA(NULL, level, NULL, 0, &cbBuf, &pcReturned);
993         RETURN_ON_DEACTIVATED_SPOOLER(res)
994
995         /* use only a short test, when we test with an invalid level */
996         if(!level || (level > 2)) {
997             /* NT: ERROR_INVALID_LEVEL, 9x: success */
998             ok( (!res && (GetLastError() == ERROR_INVALID_LEVEL)) ||
999                 (res && (pcReturned == 0)),
1000                 "(%d) returned %d with %d and 0x%08x (expected '0' with "
1001                 "ERROR_INVALID_LEVEL or '!=0' and 0x0)\n",
1002                 level, res, GetLastError(), pcReturned);
1003             continue;
1004         }        
1005
1006         
1007         /* Level 2 is not supported on NT 3.x */
1008         if (!res && (GetLastError() == ERROR_INVALID_LEVEL)) {
1009             skip("Level %d not supported\n", level);
1010             continue;
1011         }
1012
1013         ok((!res) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1014             "(%d) returned %d with %d (expected '0' with "
1015             "ERROR_INSUFFICIENT_BUFFER)\n", level, res, GetLastError());
1016
1017         buffer = HeapAlloc(GetProcessHeap(), 0, cbBuf *2);
1018         if (buffer == NULL) continue;
1019
1020         pcbNeeded = 0xdeadbeef;
1021         SetLastError(0xdeadbeef);
1022         res = EnumPortsA(NULL, level, buffer, cbBuf, &pcbNeeded, &pcReturned);
1023         ok(res, "(%d) returned %d with %d (expected '!=0')\n", level, res, GetLastError());
1024         ok(pcbNeeded == cbBuf, "(%d) returned %d (expected %d)\n", level, pcbNeeded, cbBuf);
1025         /* ToDo: Compare the returned Data with the Registry / "win.ini",[Ports] here */
1026
1027         pcbNeeded = 0xdeadbeef;
1028         pcReturned = 0xdeadbeef;
1029         SetLastError(0xdeadbeef);
1030         res = EnumPortsA(NULL, level, buffer, cbBuf+1, &pcbNeeded, &pcReturned);
1031         ok(res, "(%d) returned %d with %d (expected '!=0')\n", level, res, GetLastError());
1032         ok(pcbNeeded == cbBuf, "(%d) returned %d (expected %d)\n", level, pcbNeeded, cbBuf);
1033
1034         pcbNeeded = 0xdeadbeef;
1035         SetLastError(0xdeadbeef);
1036         res = EnumPortsA(NULL, level, buffer, cbBuf-1, &pcbNeeded, &pcReturned);
1037         ok( !res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1038             "(%d) returned %d with %d (expected '0' with "
1039             "ERROR_INSUFFICIENT_BUFFER)\n", level, res, GetLastError());
1040         ok(pcbNeeded == cbBuf, "(%d) returned %d (expected %d)\n", level, pcbNeeded, cbBuf);
1041
1042         /*
1043           Do not add this test:
1044           res = EnumPortsA(NULL, level, NULL, cbBuf, &pcbNeeded, &pcReturned);
1045           w2k+:  RPC_X_NULL_REF_POINTER 
1046           NT3.5: ERROR_INVALID_USER_BUFFER
1047           win9x: crash in winspool.drv
1048          */
1049
1050         SetLastError(0xdeadbeef);
1051         res = EnumPorts(NULL, level, buffer, cbBuf, NULL, &pcReturned);
1052         /* NT: RPC_X_NULL_REF_POINTER (1780),  9x: success */
1053         ok( (!res && (GetLastError() == RPC_X_NULL_REF_POINTER) ) ||
1054             ( res && (GetLastError() == ERROR_SUCCESS) ),
1055             "(%d) returned %d with %d (expected '0' with "
1056             "RPC_X_NULL_REF_POINTER or '!=0' with NO_ERROR)\n",
1057             level, res, GetLastError());
1058
1059
1060         SetLastError(0xdeadbeef);
1061         res = EnumPorts(NULL, level, buffer, cbBuf, &pcbNeeded, NULL);
1062         /* NT: RPC_X_NULL_REF_POINTER (1780),  9x: success */
1063         ok( (!res && (GetLastError() == RPC_X_NULL_REF_POINTER) ) ||
1064             ( res && (GetLastError() == ERROR_SUCCESS) ),
1065             "(%d) returned %d with %d (expected '0' with "
1066             "RPC_X_NULL_REF_POINTER or '!=0' with NO_ERROR)\n",
1067             level, res, GetLastError());
1068
1069         HeapFree(GetProcessHeap(), 0, buffer);
1070     }
1071 }
1072
1073 /* ########################### */
1074
1075 static void test_EnumPrinterDrivers(void)
1076 {
1077     DWORD   res;
1078     LPBYTE  buffer;
1079     DWORD   cbBuf;
1080     DWORD   pcbNeeded;
1081     DWORD   pcReturned;
1082     DWORD   level;
1083
1084     /* 1-3 for w95/w98/NT4; 1-3+6 for me; 1-6 for w2k/xp/2003; 1-6+8 for vista */
1085     for(level = 0; level < 10; level++) {
1086         cbBuf = 0xdeadbeef;
1087         pcReturned = 0xdeadbeef;
1088         SetLastError(0xdeadbeef);
1089         res = EnumPrinterDriversA(NULL, NULL, level, NULL, 0, &cbBuf, &pcReturned);
1090         RETURN_ON_DEACTIVATED_SPOOLER(res)
1091
1092         /* use only a short test, when we test with an invalid level */
1093         if(!level || (level == 7) || (level > 8)) {
1094
1095             ok( (!res && (GetLastError() == ERROR_INVALID_LEVEL)) ||
1096                 (res && (pcReturned == 0)),
1097                 "(%d) got %u with %u and 0x%x "
1098                 "(expected '0' with ERROR_INVALID_LEVEL or '!=0' and 0x0)\n",
1099                 level, res, GetLastError(), pcReturned);
1100             continue;
1101         }
1102
1103         /* some level are not supported in all windows versions */
1104         if (!res && (GetLastError() == ERROR_INVALID_LEVEL)) {
1105             skip("Level %d not supported\n", level);
1106             continue;
1107         }
1108
1109         ok( ((!res) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) ||
1110             (res && (default_printer == NULL)),
1111             "(%u) got %u with %u for %s (expected '0' with "
1112             "ERROR_INSUFFICIENT_BUFFER or '!= 0' without a printer)\n",
1113             level, res, GetLastError(), default_printer);
1114
1115         if (!cbBuf) {
1116             skip("no valid buffer size returned\n");
1117             continue;
1118         }
1119
1120         buffer = HeapAlloc(GetProcessHeap(), 0, cbBuf + 4);
1121         if (buffer == NULL) continue;
1122
1123         SetLastError(0xdeadbeef);
1124         pcbNeeded = 0xdeadbeef;
1125         res = EnumPrinterDriversA(NULL, NULL, level, buffer, cbBuf, &pcbNeeded, &pcReturned);
1126         ok(res, "(%u) got %u with %u (expected '!=0')\n", level, res, GetLastError());
1127         ok(pcbNeeded == cbBuf, "(%d) returned %d (expected %d)\n", level, pcbNeeded, cbBuf);
1128
1129         /* validate the returned Data here */
1130         if (level > 1) {
1131             LPDRIVER_INFO_2A di = (LPDRIVER_INFO_2A) buffer;
1132
1133             ok( strrchr(di->pDriverPath, '\\') != NULL,
1134                 "(%u) got %s for %s (expected a full path)\n",
1135                 level, di->pDriverPath, di->pName);
1136
1137         }
1138
1139         SetLastError(0xdeadbeef);
1140         pcReturned = 0xdeadbeef;
1141         pcbNeeded = 0xdeadbeef;
1142         res = EnumPrinterDriversA(NULL, NULL, level, buffer, cbBuf+1, &pcbNeeded, &pcReturned);
1143         ok(res, "(%u) got %u with %u (expected '!=0')\n", level, res, GetLastError());
1144         ok(pcbNeeded == cbBuf, "(%u) returned %u (expected %u)\n", level, pcbNeeded, cbBuf);
1145
1146         SetLastError(0xdeadbeef);
1147         pcbNeeded = 0xdeadbeef;
1148         res = EnumPrinterDriversA(NULL, NULL, level, buffer, cbBuf-1, &pcbNeeded, &pcReturned);
1149         ok( !res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1150             "(%u) got %u with %u (expected '0' with ERROR_INSUFFICIENT_BUFFER)\n",
1151             level, res, GetLastError());
1152         ok(pcbNeeded == cbBuf, "(%u) returned %u (expected %u)\n", level, pcbNeeded, cbBuf);
1153
1154 /*
1155       Do not add the next test:
1156       NT: ERROR_INVALID_USER_BUFFER
1157       win9x: crash or 100% CPU
1158
1159       res = EnumPrinterDriversA(NULL, NULL, level, NULL, cbBuf, &pcbNeeded, &pcReturned);
1160 */
1161
1162         SetLastError(0xdeadbeef);
1163         pcbNeeded = 0xdeadbeef;
1164         pcReturned = 0xdeadbeef;
1165         res = EnumPrinterDriversA(NULL, NULL, level, buffer, cbBuf, NULL, &pcReturned);
1166         ok( res || (!res && (GetLastError() == RPC_X_NULL_REF_POINTER)) ,
1167             "(%u) got %u with %u (expected '!=0' or '0' with "
1168             "RPC_X_NULL_REF_POINTER)\n", level, res, GetLastError());
1169
1170         pcbNeeded = 0xdeadbeef;
1171         pcReturned = 0xdeadbeef;
1172         SetLastError(0xdeadbeef);
1173         res = EnumPrinterDriversA(NULL, NULL, level, buffer, cbBuf, &pcbNeeded, NULL);
1174         ok( res || (!res && (GetLastError() == RPC_X_NULL_REF_POINTER)) ,
1175             "(%u) got %u with %u (expected '!=0' or '0' with "
1176             "RPC_X_NULL_REF_POINTER)\n", level, res, GetLastError());
1177
1178         HeapFree(GetProcessHeap(), 0, buffer);
1179     } /* for(level ... */
1180 }
1181
1182 /* ########################### */
1183
1184 static void test_GetDefaultPrinter(void)
1185 {
1186     BOOL    retval;
1187     DWORD   exact = DEFAULT_PRINTER_SIZE;
1188     DWORD   size;
1189     char    buffer[DEFAULT_PRINTER_SIZE];
1190
1191     if (!pGetDefaultPrinterA)  return;
1192         /* only supported on NT like OSes starting with win2k */
1193
1194     SetLastError(ERROR_SUCCESS);
1195     retval = pGetDefaultPrinterA(buffer, &exact);
1196     if (!retval || !exact || !strlen(buffer) ||
1197         (ERROR_SUCCESS != GetLastError())) {
1198         if ((ERROR_FILE_NOT_FOUND == GetLastError()) ||
1199             (ERROR_INVALID_NAME == GetLastError()))
1200             trace("this test requires a default printer to be set\n");
1201         else {
1202                 ok( 0, "function call GetDefaultPrinterA failed unexpected!\n"
1203                 "function returned %s\n"
1204                 "last error 0x%08x\n"
1205                 "returned buffer size 0x%08x\n"
1206                 "returned buffer content %s\n",
1207                 retval ? "true" : "false", GetLastError(), exact, buffer);
1208         }
1209         return;
1210     }
1211     SetLastError(ERROR_SUCCESS);
1212     retval = pGetDefaultPrinterA(NULL, NULL); 
1213     ok( !retval, "function result wrong! False expected\n");
1214     ok( ERROR_INVALID_PARAMETER == GetLastError(),
1215         "Last error wrong! ERROR_INVALID_PARAMETER expected, got 0x%08x\n",
1216         GetLastError());
1217
1218     SetLastError(ERROR_SUCCESS);
1219     retval = pGetDefaultPrinterA(buffer, NULL); 
1220     ok( !retval, "function result wrong! False expected\n");
1221     ok( ERROR_INVALID_PARAMETER == GetLastError(),
1222         "Last error wrong! ERROR_INVALID_PARAMETER expected, got 0x%08x\n",
1223         GetLastError());
1224
1225     SetLastError(ERROR_SUCCESS);
1226     size = 0;
1227     retval = pGetDefaultPrinterA(NULL, &size); 
1228     ok( !retval, "function result wrong! False expected\n");
1229     ok( ERROR_INSUFFICIENT_BUFFER == GetLastError(),
1230         "Last error wrong! ERROR_INSUFFICIENT_BUFFER expected, got 0x%08x\n",
1231         GetLastError());
1232     ok( size == exact, "Parameter size wrong! %d expected got %d\n",
1233         exact, size);
1234
1235     SetLastError(ERROR_SUCCESS);
1236     size = DEFAULT_PRINTER_SIZE;
1237     retval = pGetDefaultPrinterA(NULL, &size); 
1238     ok( !retval, "function result wrong! False expected\n");
1239     ok( ERROR_INSUFFICIENT_BUFFER == GetLastError(),
1240         "Last error wrong! ERROR_INSUFFICIENT_BUFFER expected, got 0x%08x\n",
1241         GetLastError());
1242     ok( size == exact, "Parameter size wrong! %d expected got %d\n",
1243         exact, size);
1244
1245     size = 0;
1246     retval = pGetDefaultPrinterA(buffer, &size); 
1247     ok( !retval, "function result wrong! False expected\n");
1248     ok( ERROR_INSUFFICIENT_BUFFER == GetLastError(),
1249         "Last error wrong! ERROR_INSUFFICIENT_BUFFER expected, got 0x%08x\n",
1250         GetLastError());
1251     ok( size == exact, "Parameter size wrong! %d expected got %d\n",
1252         exact, size);
1253
1254     size = exact;
1255     retval = pGetDefaultPrinterA(buffer, &size); 
1256     ok( retval, "function result wrong! True expected\n");
1257     ok( size == exact, "Parameter size wrong! %d expected got %d\n",
1258         exact, size);
1259 }
1260
1261 static void test_GetPrinterDriverDirectory(void)
1262 {
1263     LPBYTE      buffer = NULL;
1264     DWORD       cbBuf = 0, pcbNeeded = 0;
1265     BOOL        res;
1266
1267
1268     SetLastError(MAGIC_DEAD);
1269     res = GetPrinterDriverDirectoryA( NULL, NULL, 1, NULL, 0, &cbBuf);
1270     trace("first call returned 0x%04x, with %d: buffer size 0x%08x\n",
1271     res, GetLastError(), cbBuf);
1272
1273     RETURN_ON_DEACTIVATED_SPOOLER(res)
1274     ok((res == 0) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1275         "returned %d with lasterror=%d (expected '0' with "
1276         "ERROR_INSUFFICIENT_BUFFER)\n", res, GetLastError());
1277
1278     if (!cbBuf) {
1279         skip("no valid buffer size returned\n");
1280         return;
1281     }
1282
1283     buffer = HeapAlloc( GetProcessHeap(), 0, cbBuf*2);
1284     if (buffer == NULL)  return ;
1285
1286     res = GetPrinterDriverDirectoryA(NULL, NULL, 1, buffer, cbBuf, &pcbNeeded);
1287     ok( res, "expected result != 0, got %d\n", res);
1288     ok( cbBuf == pcbNeeded, "pcbNeeded set to %d instead of %d\n",
1289                             pcbNeeded, cbBuf);
1290
1291     res = GetPrinterDriverDirectoryA(NULL, NULL, 1, buffer, cbBuf*2, &pcbNeeded);
1292     ok( res, "expected result != 0, got %d\n", res);
1293     ok( cbBuf == pcbNeeded, "pcbNeeded set to %d instead of %d\n",
1294                             pcbNeeded, cbBuf);
1295  
1296     SetLastError(MAGIC_DEAD);
1297     res = GetPrinterDriverDirectoryA( NULL, NULL, 1, buffer, cbBuf-1, &pcbNeeded);
1298     ok( !res , "expected result == 0, got %d\n", res);
1299     ok( cbBuf == pcbNeeded, "pcbNeeded set to %d instead of %d\n",
1300                             pcbNeeded, cbBuf);
1301     
1302     ok( ERROR_INSUFFICIENT_BUFFER == GetLastError(),
1303         "last error set to %d instead of ERROR_INSUFFICIENT_BUFFER\n",
1304         GetLastError());
1305
1306 /*
1307     Do not add the next test:
1308     XPsp2: crash in this app, when the spooler is not running 
1309     NT3.5: ERROR_INVALID_USER_BUFFER
1310     win9x: ERROR_INVALID_PARAMETER
1311
1312     pcbNeeded = MAGIC_DEAD;
1313     SetLastError(MAGIC_DEAD);
1314     res = GetPrinterDriverDirectoryA( NULL, NULL, 1, NULL, cbBuf, &pcbNeeded);
1315 */
1316
1317     SetLastError(MAGIC_DEAD);
1318     res = GetPrinterDriverDirectoryA( NULL, NULL, 1, buffer, cbBuf, NULL);
1319     ok( (!res && RPC_X_NULL_REF_POINTER == GetLastError()) || res,
1320          "expected either result == 0 and "
1321          "last error == RPC_X_NULL_REF_POINTER or result != 0 "
1322          "got result %d and last error == %d\n", res, GetLastError());
1323
1324     SetLastError(MAGIC_DEAD);
1325     res = GetPrinterDriverDirectoryA( NULL, NULL, 1, NULL, cbBuf, NULL);
1326     ok(res || (GetLastError() == RPC_X_NULL_REF_POINTER),
1327         "returned %d with %d (expected '!=0' or '0' with "
1328         "RPC_X_NULL_REF_POINTER)\n", res, GetLastError());
1329  
1330  
1331     /* with a valid buffer, but level is too large */
1332     buffer[0] = '\0';
1333     SetLastError(MAGIC_DEAD);
1334     res = GetPrinterDriverDirectoryA(NULL, NULL, 2, buffer, cbBuf, &pcbNeeded);
1335
1336     /* Level not checked in win9x and wine:*/
1337     if((res != FALSE) && buffer[0])
1338     {
1339         trace("Level '2' not checked '%s'\n", buffer);
1340     }
1341     else
1342     {
1343         ok( !res && (GetLastError() == ERROR_INVALID_LEVEL),
1344         "returned %d with lasterror=%d (expected '0' with "
1345         "ERROR_INVALID_LEVEL)\n", res, GetLastError());
1346     }
1347
1348     /* printing environments are case insensitive */
1349     /* "Windows 4.0" is valid for win9x and NT */
1350     buffer[0] = '\0';
1351     SetLastError(MAGIC_DEAD);
1352     res = GetPrinterDriverDirectoryA(NULL, env_win9x_case, 1, 
1353                                         buffer, cbBuf*2, &pcbNeeded);
1354
1355     if(!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
1356         cbBuf = pcbNeeded;
1357         buffer = HeapReAlloc(GetProcessHeap(), 0, buffer, cbBuf*2);
1358         if (buffer == NULL)  return ;
1359
1360         SetLastError(MAGIC_DEAD);
1361         res = GetPrinterDriverDirectoryA(NULL, env_win9x_case, 1, 
1362                                         buffer, cbBuf*2, &pcbNeeded);
1363     }
1364
1365     ok(res && buffer[0], "returned %d with "
1366         "lasterror=%d and len=%d (expected '1' with 'len > 0')\n", 
1367         res, GetLastError(), lstrlenA((char *)buffer));
1368
1369     buffer[0] = '\0';
1370     SetLastError(MAGIC_DEAD);
1371     res = GetPrinterDriverDirectoryA(NULL, env_x86, 1, 
1372                                         buffer, cbBuf*2, &pcbNeeded);
1373
1374     if(!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
1375         cbBuf = pcbNeeded;
1376         buffer = HeapReAlloc(GetProcessHeap(), 0, buffer, cbBuf*2);
1377         if (buffer == NULL)  return ;
1378
1379         buffer[0] = '\0';
1380         SetLastError(MAGIC_DEAD);
1381         res = GetPrinterDriverDirectoryA(NULL, env_x86, 1, 
1382                                         buffer, cbBuf*2, &pcbNeeded);
1383     }
1384
1385     /* "Windows NT x86" is invalid for win9x */
1386     ok( (res && buffer[0]) ||
1387         (!res && (GetLastError() == ERROR_INVALID_ENVIRONMENT)), 
1388         "returned %d with lasterror=%d and len=%d (expected '!= 0' with "
1389         "'len > 0' or '0' with ERROR_INVALID_ENVIRONMENT)\n",
1390         res, GetLastError(), lstrlenA((char *)buffer));
1391
1392     /* A setup program (PDFCreator_0.8.0) use empty strings */
1393     SetLastError(MAGIC_DEAD);
1394     res = GetPrinterDriverDirectoryA(empty, empty, 1, buffer, cbBuf*2, &pcbNeeded);
1395     ok(res, "returned %d with %d (expected '!=0')\n", res, GetLastError() );
1396
1397     SetLastError(MAGIC_DEAD);
1398     res = GetPrinterDriverDirectoryA(NULL, empty, 1, buffer, cbBuf*2, &pcbNeeded);
1399     ok(res, "returned %d with %d (expected '!=0')\n", res, GetLastError() );
1400
1401     SetLastError(MAGIC_DEAD);
1402     res = GetPrinterDriverDirectoryA(empty, NULL, 1, buffer, cbBuf*2, &pcbNeeded);
1403     ok(res, "returned %d with %d (expected '!=0')\n", res, GetLastError() );
1404
1405     HeapFree( GetProcessHeap(), 0, buffer);
1406 }
1407
1408 /* ##### */
1409
1410 static void test_GetPrintProcessorDirectory(void)
1411 {
1412     LPBYTE      buffer = NULL;
1413     DWORD       cbBuf = 0;
1414     DWORD       pcbNeeded = 0;
1415     BOOL        res;
1416
1417
1418     SetLastError(0xdeadbeef);
1419     res = GetPrintProcessorDirectoryA(NULL, NULL, 1, NULL, 0, &cbBuf);
1420     /* The deactivated Spooler is caught here on NT3.51 */
1421     RETURN_ON_DEACTIVATED_SPOOLER(res)
1422     ok( !res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1423         "returned %d with %d (expected '0' with ERROR_INSUFFICIENT_BUFFER)\n",
1424         res, GetLastError());
1425
1426     buffer = HeapAlloc(GetProcessHeap(), 0, cbBuf*2);
1427     if(buffer == NULL)  return;
1428
1429     buffer[0] = '\0';
1430     SetLastError(0xdeadbeef);
1431     res = GetPrintProcessorDirectoryA(NULL, NULL, 1, buffer, cbBuf, &pcbNeeded);
1432     ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError());
1433
1434     SetLastError(0xdeadbeef);
1435     buffer[0] = '\0';
1436     res = GetPrintProcessorDirectoryA(NULL, NULL, 1, buffer, cbBuf*2, &pcbNeeded);
1437     ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError());
1438  
1439     /* Buffer to small */
1440     buffer[0] = '\0';
1441     SetLastError(0xdeadbeef);
1442     res = GetPrintProcessorDirectoryA( NULL, NULL, 1, buffer, cbBuf-1, &pcbNeeded);
1443     ok( !res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1444         "returned %d with %d (expected '0' with ERROR_INSUFFICIENT_BUFFER)\n",
1445         res, GetLastError());
1446
1447     if (0)
1448     {
1449     /* XPsp2: the program will crash here, when the spooler is not running  */
1450     /*        GetPrinterDriverDirectory has the same bug */
1451     pcbNeeded = 0;
1452     SetLastError(0xdeadbeef);
1453     res = GetPrintProcessorDirectoryA( NULL, NULL, 1, NULL, cbBuf, &pcbNeeded);
1454     }
1455
1456     buffer[0] = '\0';
1457     SetLastError(0xdeadbeef);
1458     res = GetPrintProcessorDirectoryA( NULL, NULL, 1, buffer, cbBuf, NULL);
1459     /* NT: RPC_X_NULL_REF_POINTER, 9x: res != 0  */
1460     ok( res || (GetLastError() == RPC_X_NULL_REF_POINTER),
1461         "returned %d with %d (expected '!= 0' or '0' with "
1462         "RPC_X_NULL_REF_POINTER)\n", res, GetLastError());
1463
1464
1465     buffer[0] = '\0';
1466     SetLastError(0xdeadbeef);
1467     res = GetPrintProcessorDirectoryA( NULL, NULL, 1, NULL, cbBuf, NULL);
1468     /* NT: RPC_X_NULL_REF_POINTER, 9x: res != 0  */
1469     ok( res || (GetLastError() == RPC_X_NULL_REF_POINTER),
1470         "returned %d with %d (expected '!= 0' or '0' with "
1471         "RPC_X_NULL_REF_POINTER)\n", res, GetLastError());
1472
1473  
1474     /* with a valid buffer, but level is invalid */
1475     buffer[0] = '\0';
1476     SetLastError(0xdeadbeef);
1477     res = GetPrintProcessorDirectoryA(NULL, NULL, 2, buffer, cbBuf, &pcbNeeded);
1478     if (res && buffer[0])
1479     {
1480         /* Level is ignored in win9x*/
1481         trace("invalid level (2) was ignored\n");
1482     }
1483     else
1484     {
1485         ok( !res && (GetLastError() == ERROR_INVALID_LEVEL),
1486             "returned %d with %d (expected '0' with ERROR_INVALID_LEVEL)\n",
1487             res, GetLastError());
1488     }
1489
1490     /* Empty environment is the same as the default environment */
1491     buffer[0] = '\0';
1492     SetLastError(0xdeadbeef);
1493     res = GetPrintProcessorDirectoryA(NULL, empty, 1, buffer, cbBuf*2, &pcbNeeded);
1494     ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError());
1495
1496     /* "Windows 4.0" is valid for win9x and NT */
1497     buffer[0] = '\0';
1498     SetLastError(0xdeadbeef);
1499     res = GetPrintProcessorDirectoryA(NULL, env_win9x_case, 1, buffer, cbBuf*2, &pcbNeeded);
1500     ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError());
1501
1502
1503     /* "Windows NT x86" is invalid for win9x */
1504     buffer[0] = '\0';
1505     SetLastError(0xdeadbeef);
1506     res = GetPrintProcessorDirectoryA(NULL, env_x86, 1, buffer, cbBuf*2, &pcbNeeded);
1507     ok( res || (GetLastError() == ERROR_INVALID_ENVIRONMENT), 
1508         "returned %d with %d (expected '!= 0' or '0' with "
1509         "ERROR_INVALID_ENVIRONMENT)\n", res, GetLastError());
1510
1511     /* invalid on all Systems */
1512     buffer[0] = '\0';
1513     SetLastError(0xdeadbeef);
1514     res = GetPrintProcessorDirectoryA(NULL, invalid_env, 1, buffer, cbBuf*2, &pcbNeeded);
1515     ok( !res && (GetLastError() == ERROR_INVALID_ENVIRONMENT), 
1516         "returned %d with %d (expected '0' with ERROR_INVALID_ENVIRONMENT)\n",
1517         res, GetLastError());
1518
1519     /* Empty servername is the same as the local computer */
1520     buffer[0] = '\0';
1521     SetLastError(0xdeadbeef);
1522     res = GetPrintProcessorDirectoryA(empty, NULL, 1, buffer, cbBuf*2, &pcbNeeded);
1523     ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError());
1524
1525     /* invalid on all Systems */
1526     buffer[0] = '\0';
1527     SetLastError(0xdeadbeef);
1528     res = GetPrintProcessorDirectoryA(server_does_not_exist, NULL, 1, buffer, cbBuf*2, &pcbNeeded);
1529     ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER), 
1530         "returned %d with %d (expected '0' with ERROR_INVALID_PARAMETER)\n",
1531         res, GetLastError());
1532
1533     HeapFree(GetProcessHeap(), 0, buffer);
1534 }
1535
1536 /* ##### */
1537
1538 static void test_OpenPrinter(void)
1539 {
1540     PRINTER_DEFAULTSA   defaults;
1541     HANDLE              hprinter;
1542     DWORD               res;
1543
1544     SetLastError(MAGIC_DEAD);
1545     res = OpenPrinter(NULL, NULL, NULL);    
1546     /* The deactivated Spooler is caught here on NT3.51 */
1547     RETURN_ON_DEACTIVATED_SPOOLER(res)
1548     ok(!res && (GetLastError() == ERROR_INVALID_PARAMETER),
1549         "returned %d with %d (expected '0' with ERROR_INVALID_PARAMETER)\n",
1550         res, GetLastError());
1551
1552
1553     /* Get Handle for the local Printserver (NT only)*/
1554     hprinter = (HANDLE) MAGIC_DEAD;
1555     SetLastError(MAGIC_DEAD);
1556     res = OpenPrinter(NULL, &hprinter, NULL);
1557     /* The deactivated Spooler is caught here on XPsp2 */
1558     RETURN_ON_DEACTIVATED_SPOOLER(res)
1559     ok(res || (!res && GetLastError() == ERROR_INVALID_PARAMETER),
1560         "returned %d with %d (expected '!=0' or '0' with ERROR_INVALID_PARAMETER)\n",
1561         res, GetLastError());
1562     if(res) {
1563         ClosePrinter(hprinter);
1564
1565         defaults.pDatatype=NULL;
1566         defaults.pDevMode=NULL;
1567
1568         defaults.DesiredAccess=0;
1569         hprinter = (HANDLE) MAGIC_DEAD;
1570         SetLastError(MAGIC_DEAD);
1571         res = OpenPrinter(NULL, &hprinter, &defaults);
1572         ok(res, "returned %d with %d (expected '!=0')\n", res, GetLastError());
1573         if (res) ClosePrinter(hprinter);
1574
1575         defaults.DesiredAccess=-1;
1576         hprinter = (HANDLE) MAGIC_DEAD;
1577         SetLastError(MAGIC_DEAD);
1578         res = OpenPrinter(NULL, &hprinter, &defaults);
1579         todo_wine {
1580         ok(!res && GetLastError() == ERROR_ACCESS_DENIED,
1581             "returned %d with %d (expected '0' with ERROR_ACCESS_DENIED)\n", 
1582             res, GetLastError());
1583         }
1584         if (res) ClosePrinter(hprinter);
1585
1586     }
1587
1588
1589     if (local_server != NULL) {
1590         hprinter = (HANDLE) 0xdeadbeef;
1591         SetLastError(0xdeadbeef);
1592         res = OpenPrinter(local_server, &hprinter, NULL);
1593         ok(res || (!res && GetLastError() == ERROR_INVALID_PARAMETER),
1594             "returned %d with %d (expected '!=0' or '0' with ERROR_INVALID_PARAMETER)\n",
1595             res, GetLastError());
1596         if(res) ClosePrinter(hprinter);
1597     }
1598
1599     /* Invalid Printername */
1600     hprinter = (HANDLE) MAGIC_DEAD;
1601     SetLastError(MAGIC_DEAD);
1602     res = OpenPrinter(illegal_name, &hprinter, NULL);
1603     ok(!res && ((GetLastError() == ERROR_INVALID_PRINTER_NAME) || 
1604                 (GetLastError() == ERROR_INVALID_PARAMETER) ),
1605        "returned %d with %d (expected '0' with: ERROR_INVALID_PARAMETER or"
1606        "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
1607     if(res) ClosePrinter(hprinter);
1608
1609     hprinter = (HANDLE) MAGIC_DEAD;
1610     SetLastError(MAGIC_DEAD);
1611     res = OpenPrinter(empty, &hprinter, NULL);
1612     /* NT: ERROR_INVALID_PRINTER_NAME,  9x: ERROR_INVALID_PARAMETER */
1613     ok( !res &&
1614         ((GetLastError() == ERROR_INVALID_PRINTER_NAME) || 
1615         (GetLastError() == ERROR_INVALID_PARAMETER) ),
1616         "returned %d with %d (expected '0' with: ERROR_INVALID_PRINTER_NAME"
1617         " or ERROR_INVALID_PARAMETER)\n", res, GetLastError());
1618     if(res) ClosePrinter(hprinter);
1619
1620
1621     /* Get Handle for the default Printer */
1622     if (default_printer)
1623     {
1624         hprinter = (HANDLE) MAGIC_DEAD;
1625         SetLastError(MAGIC_DEAD);
1626         res = OpenPrinter(default_printer, &hprinter, NULL);
1627         if((!res) && (GetLastError() == RPC_S_SERVER_UNAVAILABLE))
1628         {
1629             trace("The Service 'Spooler' is required for '%s'\n", default_printer);
1630             return;
1631         }
1632         ok(res, "returned %d with %d (expected '!=0')\n", res, GetLastError());
1633         if(res) ClosePrinter(hprinter);
1634
1635         SetLastError(MAGIC_DEAD);
1636         res = OpenPrinter(default_printer, NULL, NULL);
1637         /* NT: FALSE with ERROR_INVALID_PARAMETER, 9x: TRUE */
1638         ok(res || (GetLastError() == ERROR_INVALID_PARAMETER),
1639             "returned %d with %d (expected '!=0' or '0' with "
1640             "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
1641
1642         defaults.pDatatype=NULL;
1643         defaults.pDevMode=NULL;
1644         defaults.DesiredAccess=0;
1645
1646         hprinter = (HANDLE) MAGIC_DEAD;
1647         SetLastError(MAGIC_DEAD);
1648         res = OpenPrinter(default_printer, &hprinter, &defaults);
1649         ok(res || GetLastError() == ERROR_ACCESS_DENIED,
1650             "returned %d with %d (expected '!=0' or '0' with "
1651             "ERROR_ACCESS_DENIED)\n", res, GetLastError());
1652         if(res) ClosePrinter(hprinter);
1653
1654         defaults.pDatatype = empty;
1655
1656         hprinter = (HANDLE) MAGIC_DEAD;
1657         SetLastError(MAGIC_DEAD);
1658         res = OpenPrinter(default_printer, &hprinter, &defaults);
1659         /* stop here, when a remote Printserver has no RPC-Service running */
1660         RETURN_ON_DEACTIVATED_SPOOLER(res)
1661         ok(res || ((GetLastError() == ERROR_INVALID_DATATYPE) ||
1662                    (GetLastError() == ERROR_ACCESS_DENIED)),
1663             "returned %d with %d (expected '!=0' or '0' with: "
1664             "ERROR_INVALID_DATATYPE or ERROR_ACCESS_DENIED)\n",
1665             res, GetLastError());
1666         if(res) ClosePrinter(hprinter);
1667
1668
1669         defaults.pDatatype=NULL;
1670         defaults.DesiredAccess=PRINTER_ACCESS_USE;
1671
1672         hprinter = (HANDLE) MAGIC_DEAD;
1673         SetLastError(MAGIC_DEAD);
1674         res = OpenPrinter(default_printer, &hprinter, &defaults);
1675         ok(res || GetLastError() == ERROR_ACCESS_DENIED,
1676             "returned %d with %d (expected '!=0' or '0' with "
1677             "ERROR_ACCESS_DENIED)\n", res, GetLastError());
1678         if(res) ClosePrinter(hprinter);
1679
1680
1681         defaults.DesiredAccess=PRINTER_ALL_ACCESS;
1682         hprinter = (HANDLE) MAGIC_DEAD;
1683         SetLastError(MAGIC_DEAD);
1684         res = OpenPrinter(default_printer, &hprinter, &defaults);
1685         ok(res || GetLastError() == ERROR_ACCESS_DENIED,
1686             "returned %d with %d (expected '!=0' or '0' with "
1687             "ERROR_ACCESS_DENIED)\n", res, GetLastError());
1688         if(res) ClosePrinter(hprinter);
1689     }
1690
1691 }
1692
1693
1694 static void test_SetDefaultPrinter(void)
1695 {
1696     DWORD   res;
1697     DWORD   size = DEFAULT_PRINTER_SIZE;
1698     CHAR    buffer[DEFAULT_PRINTER_SIZE];
1699     CHAR    org_value[DEFAULT_PRINTER_SIZE];
1700
1701
1702     if (!pSetDefaultPrinterA)  return;
1703         /* only supported on win2k and above */
1704
1705     /* backup the original value */
1706     org_value[0] = '\0';
1707     SetLastError(MAGIC_DEAD);
1708     res = GetProfileStringA("windows", "device", NULL, org_value, size);
1709
1710     /* first part: with the default Printer */
1711     SetLastError(MAGIC_DEAD);
1712     res = pSetDefaultPrinterA("no_printer_with_this_name");
1713
1714     RETURN_ON_DEACTIVATED_SPOOLER(res)
1715     /* spooler is running or we have no spooler here*/
1716
1717     /* Not implemented in wine */
1718     if (!res && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) {
1719         trace("SetDefaultPrinterA() not implemented yet.\n");
1720         return;
1721     }
1722
1723     ok(!res && (GetLastError() == ERROR_INVALID_PRINTER_NAME),
1724         "returned %d with %d (expected '0' with "
1725         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
1726
1727     WriteProfileStringA("windows", "device", org_value);
1728     SetLastError(MAGIC_DEAD);
1729     res = pSetDefaultPrinterA("");
1730     ok(res || (!res && (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
1731         "returned %d with %d (expected '!=0' or '0' with "
1732         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
1733
1734     WriteProfileStringA("windows", "device", org_value);
1735     SetLastError(MAGIC_DEAD);
1736     res = pSetDefaultPrinterA(NULL);
1737     ok(res || (!res && (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
1738         "returned %d with %d (expected '!=0' or '0' with "
1739         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
1740
1741     WriteProfileStringA("windows", "device", org_value);
1742     SetLastError(MAGIC_DEAD);
1743     res = pSetDefaultPrinterA(default_printer);
1744     ok(res || (!res && (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
1745         "returned %d with %d (expected '!=0' or '0' with "
1746         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
1747
1748
1749     /* second part: always without a default Printer */
1750     WriteProfileStringA("windows", "device", NULL);    
1751     SetLastError(MAGIC_DEAD);
1752     res = pSetDefaultPrinterA("no_printer_with_this_name");
1753
1754     ok(!res && (GetLastError() == ERROR_INVALID_PRINTER_NAME),
1755         "returned %d with %d (expected '0' with "
1756         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
1757
1758     WriteProfileStringA("windows", "device", NULL);    
1759     SetLastError(MAGIC_DEAD);
1760     res = pSetDefaultPrinterA("");
1761     /* we get ERROR_INVALID_PRINTER_NAME when no printer is installed */
1762     ok(res || (!res && (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
1763          "returned %d with %d (expected '!=0' or '0' with "
1764          "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
1765
1766     WriteProfileStringA("windows", "device", NULL);    
1767     SetLastError(MAGIC_DEAD);
1768     res = pSetDefaultPrinterA(NULL);
1769     /* we get ERROR_INVALID_PRINTER_NAME when no printer is installed */
1770     ok(res || (!res && (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
1771         "returned %d with %d (expected '!=0' or '0' with "
1772         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
1773
1774     WriteProfileStringA("windows", "device", NULL);    
1775     SetLastError(MAGIC_DEAD);
1776     res = pSetDefaultPrinterA(default_printer);
1777     ok(res || (!res && (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
1778         "returned %d with %d (expected '!=0' or '0' with "
1779         "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
1780
1781     /* restore the original value */
1782     res = pSetDefaultPrinterA(default_printer);          /* the nice way */
1783     WriteProfileStringA("windows", "device", org_value); /* the old way */
1784
1785     buffer[0] = '\0';
1786     SetLastError(MAGIC_DEAD);
1787     res = GetProfileStringA("windows", "device", NULL, buffer, size);
1788     ok(!lstrcmpA(org_value, buffer), "'%s' (expected '%s')\n", buffer, org_value);
1789
1790 }
1791
1792 /* ########################### */
1793
1794 static void test_XcvDataW_MonitorUI(void)
1795 {
1796     DWORD   res;
1797     HANDLE  hXcv;
1798     BYTE    buffer[MAX_PATH + 4];
1799     DWORD   needed;
1800     DWORD   status;
1801     DWORD   len;
1802     PRINTER_DEFAULTSA pd;
1803
1804     /* api is not present before w2k */
1805     if (pXcvDataW == NULL) return;
1806
1807     pd.pDatatype = NULL;
1808     pd.pDevMode  = NULL;
1809     pd.DesiredAccess = SERVER_ACCESS_ADMINISTER;
1810
1811     hXcv = NULL;
1812     SetLastError(0xdeadbeef);
1813     res = OpenPrinter(xcv_localport, &hXcv, &pd);
1814     RETURN_ON_DEACTIVATED_SPOOLER(res)
1815     RETURN_ON_ACCESS_DENIED(res)
1816
1817     ok(res, "returned %d with %u and handle %p (expected '!= 0')\n", res, GetLastError(), hXcv);
1818     if (!res) return;
1819
1820     /* ask for needed size */
1821     needed = (DWORD) 0xdeadbeef;
1822     status = (DWORD) 0xdeadbeef;
1823     SetLastError(0xdeadbeef);
1824     res = pXcvDataW(hXcv, cmd_MonitorUIW, NULL, 0, NULL, 0, &needed, &status);
1825     ok( res && (status == ERROR_INSUFFICIENT_BUFFER) && (needed <= MAX_PATH),
1826         "returned %d with %u and %u for status %u (expected '!= 0' and "
1827         "'<= MAX_PATH' for status ERROR_INSUFFICIENT_BUFFER)\n",
1828         res, GetLastError(), needed, status);
1829
1830     if (needed > MAX_PATH) {
1831         ClosePrinter(hXcv);
1832         skip("buffer overflow (%u)\n", needed);
1833         return;
1834     }
1835     len = needed;       /* Size is in bytes */
1836
1837     /* the command is required */
1838     needed = (DWORD) 0xdeadbeef;
1839     status = (DWORD) 0xdeadbeef;
1840     SetLastError(0xdeadbeef);
1841     res = pXcvDataW(hXcv, emptyW, NULL, 0, NULL, 0, &needed, &status);
1842     ok( res && (status == ERROR_INVALID_PARAMETER),
1843         "returned %d with %u and %u for status %u (expected '!= 0' with "
1844         "ERROR_INVALID_PARAMETER)\n", res, GetLastError(), needed, status);
1845
1846     needed = (DWORD) 0xdeadbeef;
1847     status = (DWORD) 0xdeadbeef;
1848     SetLastError(0xdeadbeef);
1849     res = pXcvDataW(hXcv, NULL, NULL, 0, buffer, MAX_PATH, &needed, &status);
1850     ok( !res && (GetLastError() == RPC_X_NULL_REF_POINTER),
1851         "returned %d with %u and %u for status %u (expected '0' with "
1852         "RPC_X_NULL_REF_POINTER)\n", res, GetLastError(), needed, status);
1853
1854     /* "PDWORD needed" is checked before RPC-Errors */
1855     needed = (DWORD) 0xdeadbeef;
1856     status = (DWORD) 0xdeadbeef;
1857     SetLastError(0xdeadbeef);
1858     res = pXcvDataW(hXcv, cmd_MonitorUIW, NULL, 0, buffer, len, NULL, &status);
1859     ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
1860         "returned %d with %u and %u for status %u (expected '0' with "
1861         "ERROR_INVALID_PARAMETER)\n", res, GetLastError(), needed, status);
1862
1863     needed = (DWORD) 0xdeadbeef;
1864     status = (DWORD) 0xdeadbeef;
1865     SetLastError(0xdeadbeef);
1866     res = pXcvDataW(hXcv, cmd_MonitorUIW, NULL, 0, NULL, len, &needed, &status);
1867     ok( !res && (GetLastError() == RPC_X_NULL_REF_POINTER),
1868         "returned %d with %u and %u for status %u (expected '0' with "
1869         "RPC_X_NULL_REF_POINTER)\n", res, GetLastError(), needed, status);
1870
1871     needed = (DWORD) 0xdeadbeef;
1872     status = (DWORD) 0xdeadbeef;
1873     SetLastError(0xdeadbeef);
1874     res = pXcvDataW(hXcv, cmd_MonitorUIW, NULL, 0, buffer, len, &needed, NULL);
1875     ok( !res && (GetLastError() == RPC_X_NULL_REF_POINTER),
1876         "returned %d with %u and %u for status %u (expected '0' with "
1877         "RPC_X_NULL_REF_POINTER)\n", res, GetLastError(), needed, status);
1878
1879     /* off by one: larger  */
1880     needed = (DWORD) 0xdeadbeef;
1881     status = (DWORD) 0xdeadbeef;
1882     SetLastError(0xdeadbeef);
1883     res = pXcvDataW(hXcv, cmd_MonitorUIW, NULL, 0, buffer, len+1, &needed, &status);
1884     ok( res && (status == ERROR_SUCCESS),
1885         "returned %d with %u and %u for status %u (expected '!= 0' for status "
1886         "ERROR_SUCCESS)\n", res, GetLastError(), needed, status);
1887
1888     /* off by one: smaller */
1889     /* the buffer is not modified for NT4, w2k, XP */
1890     needed = (DWORD) 0xdeadbeef;
1891     status = (DWORD) 0xdeadbeef;
1892     SetLastError(0xdeadbeef);
1893     res = pXcvDataW(hXcv, cmd_MonitorUIW, NULL, 0, buffer, len-1, &needed, &status);
1894     ok( res && (status == ERROR_INSUFFICIENT_BUFFER),
1895         "returned %d with %u and %u for status %u (expected '!= 0' for status "
1896         "ERROR_INSUFFICIENT_BUFFER)\n", res, GetLastError(), needed, status);
1897
1898
1899     /* Normal use. The DLL-Name without a Path is returned */
1900     memset(buffer, 0, len);
1901     needed = (DWORD) 0xdeadbeef;
1902     status = (DWORD) 0xdeadbeef;
1903     SetLastError(0xdeadbeef);
1904     res = pXcvDataW(hXcv, cmd_MonitorUIW, NULL, 0, buffer, len, &needed, &status);
1905     ok( res && (status == ERROR_SUCCESS),
1906         "returned %d with %u and %u for status %u (expected '!= 0' for status "
1907         "ERROR_SUCCESS)\n", res, GetLastError(), needed, status);
1908
1909     ClosePrinter(hXcv);
1910 }
1911
1912 /* ########################### */
1913
1914 static void test_XcvDataW_PortIsValid(void)
1915 {
1916     DWORD   res;
1917     HANDLE  hXcv;
1918     DWORD   needed;
1919     DWORD   status;
1920     PRINTER_DEFAULTSA   pd;
1921
1922     /* api is not present before w2k */
1923     if (pXcvDataW == NULL) return;
1924
1925     pd.pDatatype = NULL;
1926     pd.pDevMode  = NULL;
1927     pd.DesiredAccess = SERVER_ACCESS_ADMINISTER;
1928
1929     hXcv = NULL;
1930     SetLastError(0xdeadbeef);
1931     res = OpenPrinter(xcv_localport, &hXcv, &pd);
1932
1933     RETURN_ON_DEACTIVATED_SPOOLER(res)
1934     RETURN_ON_ACCESS_DENIED(res)
1935
1936     ok(res, "returned %d with %u and handle %p (expected '!= 0')\n", res, GetLastError(), hXcv);
1937     if (!res) return;
1938
1939
1940     /* "PDWORD needed" is always required */
1941     needed = (DWORD) 0xdeadbeef;
1942     status = (DWORD) 0xdeadbeef;
1943     SetLastError(0xdeadbeef);
1944     res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) portname_lpt1W, sizeof(portname_lpt1W), NULL, 0, NULL, &status);
1945     ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
1946         "returned %d with %u and %u for status %u (expected '!= 0' with ERROR_INVALID_PARAMETER)\n",
1947          res, GetLastError(), needed, status);
1948
1949     /* an empty name is not allowed */
1950     needed = (DWORD) 0xdeadbeef;
1951     status = (DWORD) 0xdeadbeef;
1952     SetLastError(0xdeadbeef);
1953     res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) emptyW, sizeof(emptyW), NULL, 0, &needed, &status);
1954     ok( res && ((status == ERROR_FILE_NOT_FOUND) || (status == ERROR_PATH_NOT_FOUND)),
1955         "returned %d with %u and %u for status %u (expected '!= 0' for status: "
1956         "ERROR_FILE_NOT_FOUND or ERROR_PATH_NOT_FOUND)\n",
1957         res, GetLastError(), needed, status);
1958
1959     /* a directory is not allowed */
1960     needed = (DWORD) 0xdeadbeef;
1961     status = (DWORD) 0xdeadbeef;
1962     SetLastError(0xdeadbeef);
1963     res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) tempdirW, (lstrlenW(tempdirW) + 1) * sizeof(WCHAR), NULL, 0, &needed, &status);
1964     /* XP: ERROR_PATH_NOT_FOUND, w2k ERROR_ACCESS_DENIED */
1965     ok( res && ((status == ERROR_PATH_NOT_FOUND) || (status == ERROR_ACCESS_DENIED)),
1966         "returned %d with %u and %u for status %u (expected '!= 0' for status: "
1967         "ERROR_PATH_NOT_FOUND or ERROR_ACCESS_DENIED)\n",
1968         res, GetLastError(), needed, status);
1969
1970     /* more valid well known Ports */
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, &needed, &status);
1975     ok( res && (status == ERROR_SUCCESS),
1976         "returned %d with %u and %u for status %u (expected '!= 0' for ERROR_SUCCESS)\n",
1977         res, GetLastError(), needed, status);
1978
1979     needed = (DWORD) 0xdeadbeef;
1980     status = (DWORD) 0xdeadbeef;
1981     SetLastError(0xdeadbeef);
1982     res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) portname_lpt2W, sizeof(portname_lpt2W), NULL, 0, &needed, &status);
1983     ok( res && (status == ERROR_SUCCESS),
1984         "returned %d with %u and %u for status %u (expected '!= 0' for ERROR_SUCCESS)\n",
1985         res, GetLastError(), needed, status);
1986
1987     needed = (DWORD) 0xdeadbeef;
1988     status = (DWORD) 0xdeadbeef;
1989     SetLastError(0xdeadbeef);
1990     res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) portname_com1W, sizeof(portname_com1W), NULL, 0, &needed, &status);
1991     ok( res && (status == ERROR_SUCCESS),
1992         "returned %d with %u and %u for status %u (expected '!= 0' for ERROR_SUCCESS)\n",
1993         res, GetLastError(), needed, status);
1994
1995     needed = (DWORD) 0xdeadbeef;
1996     status = (DWORD) 0xdeadbeef;
1997     SetLastError(0xdeadbeef);
1998     res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) portname_com2W, sizeof(portname_com2W), NULL, 0, &needed, &status);
1999     ok( res && (status == ERROR_SUCCESS),
2000         "returned %d with %u and %u for status %u (expected '!= 0' for ERROR_SUCCESS)\n",
2001         res, GetLastError(), needed, status);
2002
2003     needed = (DWORD) 0xdeadbeef;
2004     status = (DWORD) 0xdeadbeef;
2005     SetLastError(0xdeadbeef);
2006     res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) portname_fileW, sizeof(portname_fileW), NULL, 0, &needed, &status);
2007     ok( res && (status == ERROR_SUCCESS),
2008         "returned %d with %u and %u for status %u (expected '!= 0' with  ERROR_SUCCESS)\n",
2009         res, GetLastError(), needed, status);
2010
2011
2012     /* a normal, writable file is allowed */
2013     needed = (DWORD) 0xdeadbeef;
2014     status = (DWORD) 0xdeadbeef;
2015     SetLastError(0xdeadbeef);
2016     res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) tempfileW, (lstrlenW(tempfileW) + 1) * sizeof(WCHAR), NULL, 0, &needed, &status);
2017     ok( res && (status == ERROR_SUCCESS),
2018         "returned %d with %u and %u for status %u (expected '!= 0' with ERROR_SUCCESS)\n",
2019         res, GetLastError(), needed, status);
2020
2021     ClosePrinter(hXcv);
2022 }
2023
2024 /* ########################### */
2025
2026 static void test_GetPrinterDriver(void)
2027 {
2028     HANDLE hprn;
2029     BOOL ret;
2030     BYTE *buf;
2031     INT level;
2032     DWORD needed, filled;
2033
2034     if (!default_printer)
2035     {
2036         skip("There is no default printer installed\n");
2037         return;
2038     }
2039
2040     hprn = 0;
2041     ret = OpenPrinter(default_printer, &hprn, NULL);
2042     if (!ret)
2043     {
2044         skip("Unable to open the default printer (%s)\n", default_printer);
2045         return;
2046     }
2047     ok(hprn != 0, "wrong hprn %p\n", hprn);
2048
2049     for (level = -1; level <= 7; level++)
2050     {
2051         SetLastError(0xdeadbeef);
2052         needed = (DWORD)-1;
2053         ret = GetPrinterDriver(hprn, NULL, level, NULL, 0, &needed);
2054         ok(!ret, "level %d: GetPrinterDriver should fail\n", level);
2055         if (level >= 1 && level <= 6)
2056         {
2057             /* Not all levels are supported on all Windows-Versions */
2058             if(GetLastError() == ERROR_INVALID_LEVEL) continue;
2059             ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "wrong error %d\n", GetLastError());
2060             ok(needed > 0,"not expected needed buffer size %d\n", needed);
2061         }
2062         else
2063         {
2064             /* ERROR_OUTOFMEMORY found on win9x */
2065             ok( ((GetLastError() == ERROR_INVALID_LEVEL) ||
2066                  (GetLastError() == ERROR_OUTOFMEMORY)),
2067                 "%d: returned %d with %d (expected '0' with: "
2068                 "ERROR_INVALID_LEVEL or ERROR_OUTOFMEMORY)\n",
2069                 level, ret, GetLastError());
2070             /* needed is modified in win9x. The modified Value depends on the
2071                default Printer. testing for "needed == (DWORD)-1" will fail */
2072             continue;
2073         }
2074
2075         buf = HeapAlloc(GetProcessHeap(), 0, needed);
2076
2077         SetLastError(0xdeadbeef);
2078         filled = -1;
2079         ret = GetPrinterDriver(hprn, NULL, level, buf, needed, &filled);
2080         ok(ret, "level %d: GetPrinterDriver error %d\n", level, GetLastError());
2081         ok(needed == filled, "needed %d != filled %d\n", needed, filled);
2082
2083         if (level == 2)
2084         {
2085             DRIVER_INFO_2 *di_2 = (DRIVER_INFO_2 *)buf;
2086             DWORD calculated = sizeof(*di_2);
2087
2088             /* MSDN is wrong: The Drivers on the win9x-CD's have cVersion=0x0400
2089                NT351: 1, NT4.0+w2k(Kernelmode): 2, w2k and above(Usermode): 3  */
2090             ok((di_2->cVersion >= 0 && di_2->cVersion <= 3) ||
2091                 (di_2->cVersion == 0x0400), "di_2->cVersion = %d\n", di_2->cVersion);
2092             ok(di_2->pName != NULL, "not expected NULL ptr\n");
2093             ok(di_2->pEnvironment != NULL, "not expected NULL ptr\n");
2094             ok(di_2->pDriverPath != NULL, "not expected NULL ptr\n");
2095             ok(di_2->pDataFile != NULL, "not expected NULL ptr\n");
2096             ok(di_2->pConfigFile != NULL, "not expected NULL ptr\n");
2097
2098             trace("cVersion %d\n", di_2->cVersion);
2099             trace("pName %s\n", di_2->pName);
2100             calculated += strlen(di_2->pName) + 1;
2101             trace("pEnvironment %s\n", di_2->pEnvironment);
2102             calculated += strlen(di_2->pEnvironment) + 1;
2103             trace("pDriverPath %s\n", di_2->pDriverPath);
2104             calculated += strlen(di_2->pDriverPath) + 1;
2105             trace("pDataFile %s\n", di_2->pDataFile);
2106             calculated += strlen(di_2->pDataFile) + 1;
2107             trace("pConfigFile %s\n", di_2->pConfigFile);
2108             calculated += strlen(di_2->pConfigFile) + 1;
2109
2110             /* XP allocates memory for both ANSI and unicode names */
2111             ok(filled >= calculated,"calculated %d != filled %d\n", calculated, filled);
2112         }
2113
2114         HeapFree(GetProcessHeap(), 0, buf);
2115     }
2116
2117     SetLastError(0xdeadbeef);
2118     ret = ClosePrinter(hprn);
2119     ok(ret, "ClosePrinter error %d\n", GetLastError());
2120 }
2121
2122 static void test_DEVMODE(const DEVMODE *dm, LONG dmSize, LPCSTR exp_prn_name)
2123 {
2124     /* On NT3.51, some fields in DEVMODE are empty/zero
2125       (dmDeviceName, dmSpecVersion, dmDriverVersion and dmDriverExtra)
2126        We skip the Tests on this Platform */
2127     if (dm->dmSpecVersion || dm->dmDriverVersion || dm->dmDriverExtra) {
2128     /* The 0-terminated Printername can be larger (MAX_PATH) than CCHDEVICENAME */
2129         ok(!strncmp(exp_prn_name, (LPCSTR)dm->dmDeviceName, CCHDEVICENAME -1),
2130             "expected '%s', got '%s'\n", exp_prn_name, dm->dmDeviceName);
2131         ok(dm->dmSize + dm->dmDriverExtra == dmSize,
2132             "%u != %d\n", dm->dmSize + dm->dmDriverExtra, dmSize);
2133     }
2134     trace("dmFields %08x\n", dm->dmFields);
2135 }
2136
2137 static void test_DocumentProperties(void)
2138 {
2139     HANDLE hprn;
2140     LONG dm_size, ret;
2141     DEVMODE *dm;
2142
2143     if (!default_printer)
2144     {
2145         skip("There is no default printer installed\n");
2146         return;
2147     }
2148
2149     hprn = 0;
2150     ret = OpenPrinter(default_printer, &hprn, NULL);
2151     if (!ret)
2152     {
2153         skip("Unable to open the default printer (%s)\n", default_printer);
2154         return;
2155     }
2156     ok(hprn != 0, "wrong hprn %p\n", hprn);
2157
2158     dm_size = DocumentProperties(0, hprn, NULL, NULL, NULL, 0);
2159     trace("DEVMODE required size %d\n", dm_size);
2160     ok(dm_size >= sizeof(DEVMODE), "unexpected DocumentProperties ret value %d\n", dm_size);
2161
2162     dm = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dm_size);
2163
2164     ret = DocumentProperties(0, hprn, NULL, dm, dm, DM_OUT_BUFFER);
2165     ok(ret == IDOK, "DocumentProperties ret value %d != expected IDOK\n", ret);
2166
2167     test_DEVMODE(dm, dm_size, default_printer);
2168
2169     HeapFree(GetProcessHeap(), 0, dm);
2170
2171     SetLastError(0xdeadbeef);
2172     ret = ClosePrinter(hprn);
2173     ok(ret, "ClosePrinter error %d\n", GetLastError());
2174 }
2175
2176 static void test_EnumPrinters(void)
2177 {
2178     DWORD neededA, neededW, num;
2179     DWORD ret;
2180
2181     SetLastError(0xdeadbeef);
2182     neededA = -1;
2183     ret = EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &neededA, &num);
2184     RETURN_ON_DEACTIVATED_SPOOLER(ret)
2185     if (!ret)
2186     {
2187         /* We have 1 or more printers */
2188         ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "gle %d\n", GetLastError());
2189         ok(neededA > 0, "Expected neededA to show the number of needed bytes\n");
2190     }
2191     else
2192     {
2193         /* We don't have any printers defined */
2194         ok(GetLastError() == S_OK, "gle %d\n", GetLastError());
2195         ok(neededA == 0, "Expected neededA to be zero\n");
2196     }
2197     ok(num == 0, "num %d\n", num);
2198
2199     SetLastError(0xdeadbeef);
2200     neededW = -1;
2201     ret = EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &neededW, &num);
2202     /* EnumPrintersW is not supported on all platforms */
2203     if (!ret && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
2204     {
2205         skip("EnumPrintersW is not implemented\n");
2206         return;
2207     }
2208
2209     if (!ret)
2210     {
2211         /* We have 1 or more printers */
2212         ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "gle %d\n", GetLastError());
2213         ok(neededW > 0, "Expected neededW to show the number of needed bytes\n");
2214     }
2215     else
2216     {
2217         /* We don't have any printers defined */
2218         ok(GetLastError() == S_OK, "gle %d\n", GetLastError());
2219         ok(neededW == 0, "Expected neededW to be zero\n");
2220     }
2221     ok(num == 0, "num %d\n", num);
2222
2223     /* Outlook2003 relies on the buffer size returned by EnumPrintersA being big enough
2224        to hold the buffer returned by EnumPrintersW */
2225     ok(neededA == neededW, "neededA %d neededW %d\n", neededA, neededW);
2226 }
2227
2228 static void test_DeviceCapabilities(void)
2229 {
2230     HANDLE hComdlg32;
2231     BOOL (WINAPI *pPrintDlgA)(PRINTDLGA *);
2232     PRINTDLGA prn_dlg;
2233     DEVMODE *dm;
2234     DEVNAMES *dn;
2235     const char *driver, *device, *port;
2236     WORD *papers;
2237     POINT *paper_size;
2238     POINTS ext;
2239     struct
2240     {
2241         char name[64];
2242     } *paper_name;
2243     INT n_papers, n_paper_size, n_paper_names, n_copies, ret;
2244     DWORD fields;
2245
2246     hComdlg32 = LoadLibrary("comdlg32.dll");
2247     assert(hComdlg32);
2248     pPrintDlgA = (void *)GetProcAddress(hComdlg32, "PrintDlgA");
2249     assert(pPrintDlgA);
2250
2251     memset(&prn_dlg, 0, sizeof(prn_dlg));
2252     prn_dlg.lStructSize = sizeof(prn_dlg);
2253     prn_dlg.Flags = PD_RETURNDEFAULT;
2254     ret = pPrintDlgA(&prn_dlg);
2255     FreeLibrary(hComdlg32);
2256     if (!ret)
2257     {
2258         skip("PrintDlg returned no default printer\n");
2259         return;
2260     }
2261     ok(prn_dlg.hDevMode != 0, "PrintDlg returned hDevMode == NULL\n");
2262     ok(prn_dlg.hDevNames != 0, "PrintDlg returned hDevNames == NULL\n");
2263
2264     dm = GlobalLock(prn_dlg.hDevMode);
2265     ok(dm != NULL, "GlobalLock(prn_dlg.hDevMode) failed\n");
2266     trace("dmDeviceName \"%s\"\n", dm->dmDeviceName);
2267
2268     dn = GlobalLock(prn_dlg.hDevNames);
2269     ok(dn != NULL, "GlobalLock(prn_dlg.hDevNames) failed\n");
2270     ok(dn->wDriverOffset, "expected not 0 wDriverOffset\n");
2271     ok(dn->wDeviceOffset, "expected not 0 wDeviceOffset\n");
2272     ok(dn->wOutputOffset, "expected not 0 wOutputOffset\n");
2273     ok(dn->wDefault == DN_DEFAULTPRN, "expected DN_DEFAULTPRN got %x\n", dn->wDefault);
2274     driver = (const char *)dn + dn->wDriverOffset;
2275     device = (const char *)dn + dn->wDeviceOffset;
2276     port = (const char *)dn + dn->wOutputOffset;
2277     trace("driver \"%s\" device \"%s\" port \"%s\"\n", driver, device, port);
2278
2279     test_DEVMODE(dm, dm->dmSize + dm->dmDriverExtra, device);
2280
2281     n_papers = DeviceCapabilities(device, port, DC_PAPERS, NULL, NULL);
2282     ok(n_papers > 0, "DeviceCapabilities DC_PAPERS failed\n");
2283     papers = HeapAlloc(GetProcessHeap(), 0, sizeof(*papers) * n_papers);
2284     ret = DeviceCapabilities(device, port, DC_PAPERS, (LPSTR)papers, NULL);
2285     ok(ret == n_papers, "expected %d, got %d\n", n_papers, ret);
2286 #if VERBOSE
2287     for (ret = 0; ret < n_papers; ret++)
2288         trace("papers[%d] = %d\n", ret, papers[ret]);
2289 #endif
2290     HeapFree(GetProcessHeap(), 0, papers);
2291
2292     n_paper_size = DeviceCapabilities(device, port, DC_PAPERSIZE, NULL, NULL);
2293     ok(n_paper_size > 0, "DeviceCapabilities DC_PAPERSIZE failed\n");
2294     ok(n_paper_size == n_papers, "n_paper_size %d != n_papers %d\n", n_paper_size, n_papers);
2295     paper_size = HeapAlloc(GetProcessHeap(), 0, sizeof(*paper_size) * n_paper_size);
2296     ret = DeviceCapabilities(device, port, DC_PAPERSIZE, (LPSTR)paper_size, NULL);
2297     ok(ret == n_paper_size, "expected %d, got %d\n", n_paper_size, ret);
2298 #if VERBOSE
2299     for (ret = 0; ret < n_paper_size; ret++)
2300         trace("paper_size[%d] = %d x %d\n", ret, paper_size[ret].x, paper_size[ret].y);
2301 #endif
2302     HeapFree(GetProcessHeap(), 0, paper_size);
2303
2304     n_paper_names = DeviceCapabilities(device, port, DC_PAPERNAMES, NULL, NULL);
2305     ok(n_paper_names > 0, "DeviceCapabilities DC_PAPERNAMES failed\n");
2306     ok(n_paper_names == n_papers, "n_paper_names %d != n_papers %d\n", n_paper_names, n_papers);
2307     paper_name = HeapAlloc(GetProcessHeap(), 0, sizeof(*paper_name) * n_paper_names);
2308     ret = DeviceCapabilities(device, port, DC_PAPERNAMES, (LPSTR)paper_name, NULL);
2309     ok(ret == n_paper_names, "expected %d, got %d\n", n_paper_names, ret);
2310 #if VERBOSE
2311     for (ret = 0; ret < n_paper_names; ret++)
2312         trace("paper_name[%u] = %s\n", ret, paper_name[ret].name);
2313 #endif
2314     HeapFree(GetProcessHeap(), 0, paper_name);
2315
2316     n_copies = DeviceCapabilities(device, port, DC_COPIES, NULL, dm);
2317     ok(n_copies > 0, "DeviceCapabilities DC_COPIES failed\n");
2318     trace("n_copies = %d\n", n_copies);
2319
2320     ret = DeviceCapabilities(device, port, DC_MAXEXTENT, NULL, NULL);
2321     ok(ret != -1, "DeviceCapabilities DC_MAXEXTENT failed\n");
2322     ext = MAKEPOINTS(ret);
2323     trace("max ext = %d x %d\n", ext.x, ext.y);
2324
2325     ret = DeviceCapabilities(device, port, DC_MINEXTENT, NULL, NULL);
2326     ok(ret != -1, "DeviceCapabilities DC_MINEXTENT failed\n");
2327     ext = MAKEPOINTS(ret);
2328     trace("min ext = %d x %d\n", ext.x, ext.y);
2329
2330     fields = DeviceCapabilities(device, port, DC_FIELDS, NULL, NULL);
2331     ok(fields != (DWORD)-1, "DeviceCapabilities DC_FIELDS failed\n");
2332     ok(fields == dm->dmFields, "fields %x != dm->dmFields %x\n", fields, dm->dmFields);
2333
2334     GlobalUnlock(prn_dlg.hDevMode);
2335     GlobalFree(prn_dlg.hDevMode);
2336     GlobalUnlock(prn_dlg.hDevNames);
2337     GlobalFree(prn_dlg.hDevNames);
2338 }
2339
2340 START_TEST(info)
2341 {
2342     hwinspool = GetModuleHandleA("winspool.drv");
2343     pGetDefaultPrinterA = (void *) GetProcAddress(hwinspool, "GetDefaultPrinterA");
2344     pSetDefaultPrinterA = (void *) GetProcAddress(hwinspool, "SetDefaultPrinterA");
2345     pXcvDataW = (void *) GetProcAddress(hwinspool, "XcvDataW");
2346     pAddPortExA = (void *) GetProcAddress(hwinspool, "AddPortExA");
2347
2348     find_default_printer();
2349     find_local_server();
2350     find_tempfile();
2351
2352     test_AddMonitor();
2353     test_AddPort();
2354     test_AddPortEx();
2355     test_ConfigurePort();
2356     test_DeleteMonitor();
2357     test_DeletePort();
2358     test_DeviceCapabilities();
2359     test_DocumentProperties();
2360     test_EnumForms(NULL);
2361     if (default_printer) test_EnumForms(default_printer);
2362     test_EnumMonitors();
2363     test_EnumPorts();
2364     test_EnumPrinterDrivers();
2365     test_EnumPrinters();
2366     test_GetDefaultPrinter();
2367     test_GetPrinterDriverDirectory();
2368     test_GetPrintProcessorDirectory();
2369     test_OpenPrinter();
2370     test_GetPrinterDriver();
2371     test_SetDefaultPrinter();
2372     test_XcvDataW_MonitorUI();
2373     test_XcvDataW_PortIsValid();
2374
2375     /* Cleanup our temporary file */
2376     DeleteFileA(tempfileA);
2377 }