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