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