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