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