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