push 87b6981010d7405c33b14cddcceec21b47729eba
[wine/hacks.git] / dlls / winspool.drv / tests / info.c
blob79f47dabfc648d6a317e250d3a8a1118b9ee2708
1 /*
2 * Copyright (C) 2003, 2004 Stefan Leichter
3 * Copyright (C) 2005, 2006 Detlef Riekenberg
4 * Copyright (C) 2006 Dmitry Timoshkov
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.
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.
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
21 #include <stdarg.h>
22 #include <assert.h>
24 #define NONAMELESSSTRUCT
25 #define NONAMELESSUNION
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"
38 #define MAGIC_DEAD 0xdeadbeef
39 #define DEFAULT_PRINTER_SIZE 1000
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";
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};
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};
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);
78 /* ################################ */
80 struct monitor_entry {
81 LPSTR env;
82 CHAR dllname[32];
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;
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"); \
102 return; \
105 static DWORD access_denied_reported = 0;
106 #define RETURN_ON_ACCESS_DENIED(res) \
107 if ((res == 0) && (GetLastError() == ERROR_ACCESS_DENIED)) \
109 if (!access_denied_reported) { \
110 access_denied_reported++; \
111 skip("More Access-Rights are required for many test\n"); \
113 return; \
116 /* ################################ */
118 static BOOL on_win9x = FALSE;
120 static BOOL check_win9x(void)
122 if (pGetPrinterW)
124 SetLastError(0xdeadbeef);
125 pGetPrinterW(NULL, 0, NULL, 0, NULL);
126 return (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED);
128 else
130 return TRUE;
134 static void find_default_printer(VOID)
136 static char buffer[DEFAULT_PRINTER_SIZE];
137 DWORD needed;
138 DWORD res;
139 LPSTR ptr;
141 if ((default_printer == NULL) && (pGetDefaultPrinterA))
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);
149 if (default_printer == NULL)
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) {
158 needed = sizeof(buffer);
159 if (RegQueryValueEx(hwindows, "device", NULL,
160 &type, (LPBYTE)buffer, &needed) == NO_ERROR) {
162 ptr = strchr(buffer, ',');
163 if (ptr) {
164 ptr[0] = '\0';
165 default_printer = buffer;
168 RegCloseKey(hwindows);
170 trace("default_printer: '%s'\n", default_printer);
172 if (default_printer == NULL)
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;
184 trace("default_printer: '%s'\n", default_printer);
189 static struct monitor_entry * find_installed_monitor(void)
191 MONITOR_INFO_2A mi2a;
192 static struct monitor_entry * entry = NULL;
193 DWORD num_tests;
194 DWORD i = 0;
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"},
215 if (entry) return entry;
217 num_tests = (sizeof(monitor_table)/sizeof(struct monitor_entry));
219 /* cleanup */
220 DeleteMonitorA(NULL, env_x64, winetest);
221 DeleteMonitorA(NULL, env_x86, winetest);
222 DeleteMonitorA(NULL, env_win9x_case, winetest);
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;
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);
237 else
239 entry = NULL;
242 return entry;
246 /* ########################### */
248 static void find_local_server(VOID)
250 static char buffer[MAX_PATH];
251 DWORD res;
252 DWORD size;
254 size = sizeof(buffer) - 3 ;
255 buffer[0] = '\\';
256 buffer[1] = '\\';
257 buffer[2] = '\0';
259 SetLastError(0xdeadbeef);
260 res = GetComputerNameA(&buffer[2], &size);
261 trace("returned %d with %d and %d: '%s'\n", res, GetLastError(), size, buffer);
263 ok( res != 0, "returned %d with %d and %d: '%s' (expected '!= 0')\n",
264 res, GetLastError(), size, buffer);
266 if (res) local_server = buffer;
269 /* ########################### */
271 static void find_tempfile(VOID)
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;
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;
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;
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;
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;
304 tempdirA = buffer_dirA;
305 tempfileA = buffer_fileA;
306 tempdirW = buffer_dirW;
307 tempfileW = buffer_fileW;
308 trace("tempfile: '%s'\n", tempfileA);
311 /* ########################### */
313 static void test_AddMonitor(void)
315 MONITOR_INFO_2A mi2a;
316 struct monitor_entry * entry = NULL;
317 DWORD res;
319 entry = find_installed_monitor();
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());
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());
333 if (0)
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());
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)
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());
358 if (!entry) {
359 skip("No usable Monitor found\n");
360 return;
363 if (0)
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. */
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 */
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());
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());
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());
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());
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);
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());
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());
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());
449 /* cleanup */
450 DeleteMonitorA(NULL, entry->env, winetest);
454 /* ########################### */
456 static void test_AddPort(void)
458 DWORD res;
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());
470 SetLastError(0xdeadbeef);
471 res = AddPortA(NULL, 0, empty);
472 /* Allowed only for (Printer-)Administrators */
473 RETURN_ON_ACCESS_DENIED(res)
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());
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());
492 /* ########################### */
494 static void test_AddPortEx(void)
496 PORT_INFO_2A pi;
497 DWORD res;
500 if (!pAddPortExA) {
501 win_skip("AddPortEx not supported\n");
502 return;
505 /* start test with a clean system */
506 DeletePortA(NULL, 0, tempfileA);
508 pi.pPortName = tempfileA;
509 SetLastError(0xdeadbeef);
510 res = pAddPortExA(NULL, 1, (LPBYTE) &pi, LocalPortA);
511 RETURN_ON_DEACTIVATED_SPOOLER(res)
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;
519 ok( res, "got %u with %u (expected '!= 0')\n", res, GetLastError());
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);
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);
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);
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);
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());
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);
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 */
573 pi.pPortName = tempfileA;
574 pi.pMonitorName = LocalPortA;
575 pi.pDescription = winetest;
576 pi.fPortType = PORT_TYPE_WRITE;
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);
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());
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());
600 /* cleanup */
601 DeletePortA(NULL, 0, tempfileA);
605 /* ########################### */
607 static void test_ConfigurePort(void)
609 DWORD res;
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());
621 SetLastError(0xdeadbeef);
622 res = ConfigurePortA(NULL, 0, empty);
623 /* Allowed only for (Printer-)Administrators */
624 RETURN_ON_ACCESS_DENIED(res)
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());
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());
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
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
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());
657 SetLastError(0xdeadbeef);
658 res = ConfigurePortA(NULL, 0, portname_lpt1);
659 trace("'%s' returned %d with %d\n", portname_lpt1, res, GetLastError());
661 SetLastError(0xdeadbeef);
662 res = ConfigurePortA(NULL, 0, portname_file);
663 trace("'%s' returned %d with %d\n", portname_file, res, GetLastError());
667 /* ########################### */
669 static void test_DeleteMonitor(void)
671 MONITOR_INFO_2A mi2a;
672 struct monitor_entry * entry = NULL;
673 DWORD res;
676 entry = find_installed_monitor();
678 if (!entry) {
679 skip("No usable Monitor found\n");
680 return;
683 mi2a.pName = winetest;
684 mi2a.pEnvironment = entry->env;
685 mi2a.pDLLName = entry->dllname;
687 /* Testing DeleteMonitor with real options */
688 AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
690 SetLastError(MAGIC_DEAD);
691 res = DeleteMonitorA(NULL, entry->env, winetest);
692 ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError());
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());
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());
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());
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());
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());
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());
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());
748 /* cleanup */
749 DeleteMonitorA(NULL, entry->env, winetest);
752 /* ########################### */
754 static void test_DeletePort(void)
756 DWORD res;
758 SetLastError(0xdeadbeef);
759 res = DeletePortA(NULL, 0, NULL);
760 RETURN_ON_DEACTIVATED_SPOOLER(res)
762 SetLastError(0xdeadbeef);
763 res = DeletePortA(NULL, 0, empty);
764 /* Allowed only for (Printer-)Administrators */
765 RETURN_ON_ACCESS_DENIED(res)
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());
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());
784 /* ########################### */
786 static void test_EnumForms(LPSTR pName)
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;
802 res = OpenPrinter(pName, &hprinter, NULL);
803 RETURN_ON_DEACTIVATED_SPOOLER(res)
804 if (!res || !hprinter)
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;
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);
818 /* EnumForms is not implemented in win9x */
819 if (!res && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) continue;
821 /* EnumForms for the Server not implemented on all NT-Versions */
822 if (!res && (GetLastError() == ERROR_INVALID_HANDLE) && !pName) continue;
824 /* Level 2 for EnumForms is not supported on all systems */
825 if (!res && (GetLastError() == ERROR_INVALID_LEVEL) && (level == 2)) continue;
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;
837 ok((!res) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
838 "(%d) returned %d with %d (expected '0' with "
839 "ERROR_INSUFFICIENT_BUFFER)\n", level, res, GetLastError());
841 buffer = HeapAlloc(GetProcessHeap(), 0, cbBuf *2);
842 if (buffer == NULL) continue;
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());
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++)
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);
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);
867 /* offset pointer pFI_1a by 1*sizeof(FORM_INFO_2A) Bytes */
868 pFI_2a ++;
869 pFI_1a = (PFORM_INFO_1A)pFI_2a;
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());
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());
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());
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());
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());
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());
911 HeapFree(GetProcessHeap(), 0, buffer);
912 } /* for(level ... */
914 ClosePrinter(hprinter);
917 /* ########################### */
919 static void test_EnumMonitors(void)
921 DWORD res;
922 LPBYTE buffer;
923 DWORD cbBuf;
924 DWORD pcbNeeded;
925 DWORD pcReturned;
926 DWORD level;
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);
935 RETURN_ON_DEACTIVATED_SPOOLER(res)
937 /* not implemented yet in wine */
938 if (!res && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) continue;
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;
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;
957 ok((!res) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
958 "(%d) returned %d with %d (expected '0' with "
959 "ERROR_INSUFFICIENT_BUFFER)\n", level, res, GetLastError());
961 if (!cbBuf) {
962 skip("no valid buffer size returned\n");
963 continue;
966 buffer = HeapAlloc(GetProcessHeap(), 0, cbBuf *2);
967 if (buffer == NULL) continue;
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 */
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);
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());
995 ok(pcbNeeded == cbBuf, "(%d) returned %d (expected %d)\n", level,
996 pcbNeeded, cbBuf);
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
1004 res = EnumMonitorsA(NULL, level, NULL, cbBuf, &pcbNeeded, &pcReturned);
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());
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());
1023 HeapFree(GetProcessHeap(), 0, buffer);
1024 } /* for(level ... */
1027 /* ########################### */
1029 static void test_EnumPorts(void)
1031 DWORD res;
1032 DWORD level;
1033 LPBYTE buffer;
1034 DWORD cbBuf;
1035 DWORD pcbNeeded;
1036 DWORD pcReturned;
1038 /* valid levels are 1 and 2 */
1039 for(level = 0; level < 4; level++) {
1041 cbBuf = 0xdeadbeef;
1042 pcReturned = 0xdeadbeef;
1043 SetLastError(0xdeadbeef);
1044 res = EnumPortsA(NULL, level, NULL, 0, &cbBuf, &pcReturned);
1045 RETURN_ON_DEACTIVATED_SPOOLER(res)
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;
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;
1065 ok((!res) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1066 "(%d) returned %d with %d (expected '0' with "
1067 "ERROR_INSUFFICIENT_BUFFER)\n", level, res, GetLastError());
1069 buffer = HeapAlloc(GetProcessHeap(), 0, cbBuf *2);
1070 if (buffer == NULL) continue;
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 */
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);
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);
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
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());
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());
1121 HeapFree(GetProcessHeap(), 0, buffer);
1125 /* ########################### */
1127 static void test_EnumPrinterDrivers(void)
1129 static char env_all[] = "all";
1131 DWORD res;
1132 LPBYTE buffer;
1133 DWORD cbBuf;
1134 DWORD pcbNeeded;
1135 DWORD pcReturned;
1136 DWORD level;
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)
1146 /* use only a short test, when we test with an invalid level */
1147 if(!level || (level == 7) || (level > 8)) {
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;
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;
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);
1169 if (!cbBuf) {
1170 skip("no valid buffer size returned\n");
1171 continue;
1174 /* EnumPrinterDriversA returns the same number of bytes as EnumPrinterDriversW */
1175 if (!on_win9x && pEnumPrinterDriversW)
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);
1183 buffer = HeapAlloc(GetProcessHeap(), 0, cbBuf + 4);
1184 if (buffer == NULL) continue;
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);
1192 /* validate the returned Data here */
1193 if (level > 1) {
1194 LPDRIVER_INFO_2A di = (LPDRIVER_INFO_2A) buffer;
1196 ok( strrchr(di->pDriverPath, '\\') != NULL,
1197 "(%u) got %s for %s (expected a full path)\n",
1198 level, di->pDriverPath, di->pName);
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);
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);
1218 Do not add the next test:
1219 NT: ERROR_INVALID_USER_BUFFER
1220 win9x: crash or 100% CPU
1222 res = EnumPrinterDriversA(NULL, NULL, level, NULL, cbBuf, &pcbNeeded, &pcReturned);
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());
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());
1241 HeapFree(GetProcessHeap(), 0, buffer);
1242 } /* for(level ... */
1244 pcbNeeded = 0;
1245 pcReturned = 0;
1246 SetLastError(0xdeadbeef);
1247 res = EnumPrinterDriversA(NULL, env_all, 1, NULL, 0, &pcbNeeded, &pcReturned);
1248 if (res)
1250 skip("no printer drivers found\n");
1251 return;
1253 if (GetLastError() == ERROR_INVALID_ENVIRONMENT)
1255 win_skip("NT4 and below don't support the 'all' environment value\n");
1256 return;
1258 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "unexpected error %u\n", GetLastError());
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)
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);
1272 HeapFree(GetProcessHeap(), 0, buffer);
1275 /* ########################### */
1277 static void test_EnumPrintProcessors(void)
1279 DWORD res;
1280 LPBYTE buffer;
1281 DWORD cbBuf;
1282 DWORD pcbNeeded;
1283 DWORD pcReturned;
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)
1292 if (res && !cbBuf) {
1293 skip("No Printprocessor installed\n");
1294 return;
1297 ok((!res) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1298 "got %u with %u (expected '0' with ERROR_INSUFFICIENT_BUFFER)\n",
1299 res, GetLastError());
1301 buffer = HeapAlloc(GetProcessHeap(), 0, cbBuf + 4);
1302 if (buffer == NULL)
1303 return;
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. */
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());
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());
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());
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());
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());
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());
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());
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());
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());
1392 HeapFree(GetProcessHeap(), 0, buffer);
1396 /* ########################### */
1398 static void test_GetDefaultPrinter(void)
1400 BOOL retval;
1401 DWORD exact = DEFAULT_PRINTER_SIZE;
1402 DWORD size;
1403 char buffer[DEFAULT_PRINTER_SIZE];
1405 if (!pGetDefaultPrinterA) return;
1406 /* only supported on NT like OSes starting with win2k */
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);
1423 return;
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());
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());
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);
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);
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);
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);
1475 static void test_GetPrinterDriverDirectory(void)
1477 LPBYTE buffer = NULL;
1478 DWORD cbBuf = 0, pcbNeeded = 0;
1479 BOOL res;
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);
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());
1492 if (!cbBuf) {
1493 skip("no valid buffer size returned\n");
1494 return;
1497 buffer = HeapAlloc( GetProcessHeap(), 0, cbBuf*2);
1498 if (buffer == NULL) return ;
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);
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);
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);
1516 ok( ERROR_INSUFFICIENT_BUFFER == GetLastError(),
1517 "last error set to %d instead of ERROR_INSUFFICIENT_BUFFER\n",
1518 GetLastError());
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
1526 pcbNeeded = MAGIC_DEAD;
1527 SetLastError(MAGIC_DEAD);
1528 res = GetPrinterDriverDirectoryA( NULL, NULL, 1, NULL, cbBuf, &pcbNeeded);
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());
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());
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);
1550 /* Level not checked in win9x and wine:*/
1551 if((res != FALSE) && buffer[0])
1553 trace("Level '2' not checked '%s'\n", buffer);
1555 else
1557 ok( !res && (GetLastError() == ERROR_INVALID_LEVEL),
1558 "returned %d with lasterror=%d (expected '0' with "
1559 "ERROR_INVALID_LEVEL)\n", res, GetLastError());
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);
1569 if(!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
1570 cbBuf = pcbNeeded;
1571 buffer = HeapReAlloc(GetProcessHeap(), 0, buffer, cbBuf*2);
1572 if (buffer == NULL) return ;
1574 SetLastError(MAGIC_DEAD);
1575 res = GetPrinterDriverDirectoryA(NULL, env_win9x_case, 1,
1576 buffer, cbBuf*2, &pcbNeeded);
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));
1583 buffer[0] = '\0';
1584 SetLastError(MAGIC_DEAD);
1585 res = GetPrinterDriverDirectoryA(NULL, env_x86, 1,
1586 buffer, cbBuf*2, &pcbNeeded);
1588 if(!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
1589 cbBuf = pcbNeeded;
1590 buffer = HeapReAlloc(GetProcessHeap(), 0, buffer, cbBuf*2);
1591 if (buffer == NULL) return ;
1593 buffer[0] = '\0';
1594 SetLastError(MAGIC_DEAD);
1595 res = GetPrinterDriverDirectoryA(NULL, env_x86, 1,
1596 buffer, cbBuf*2, &pcbNeeded);
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));
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() );
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() );
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() );
1619 HeapFree( GetProcessHeap(), 0, buffer);
1622 /* ##### */
1624 static void test_GetPrintProcessorDirectory(void)
1626 LPBYTE buffer = NULL;
1627 DWORD cbBuf = 0;
1628 DWORD pcbNeeded = 0;
1629 BOOL res;
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());
1640 buffer = HeapAlloc(GetProcessHeap(), 0, cbBuf*2);
1641 if(buffer == NULL) return;
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());
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());
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());
1661 if (0)
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());
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());
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());
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());
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());
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());
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());
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());
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());
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());
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());
1757 HeapFree(GetProcessHeap(), 0, buffer);
1760 /* ##### */
1762 static void test_OpenPrinter(void)
1764 PRINTER_DEFAULTSA defaults;
1765 HANDLE hprinter;
1766 DWORD res;
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());
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);
1789 defaults.pDatatype=NULL;
1790 defaults.pDevMode=NULL;
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);
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());
1808 if (res) ClosePrinter(hprinter);
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);
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);
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);
1845 /* Get Handle for the default Printer */
1846 if (default_printer)
1848 hprinter = (HANDLE) MAGIC_DEAD;
1849 SetLastError(MAGIC_DEAD);
1850 res = OpenPrinter(default_printer, &hprinter, NULL);
1851 if((!res) && (GetLastError() == RPC_S_SERVER_UNAVAILABLE))
1853 trace("The Service 'Spooler' is required for '%s'\n", default_printer);
1854 return;
1856 ok(res, "returned %d with %d (expected '!=0')\n", res, GetLastError());
1857 if(res) ClosePrinter(hprinter);
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());
1866 defaults.pDatatype=NULL;
1867 defaults.pDevMode=NULL;
1868 defaults.DesiredAccess=0;
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);
1878 defaults.pDatatype = empty;
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);
1893 defaults.pDatatype=NULL;
1894 defaults.DesiredAccess=PRINTER_ACCESS_USE;
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);
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);
1918 static void test_SetDefaultPrinter(void)
1920 DWORD res;
1921 DWORD size = DEFAULT_PRINTER_SIZE;
1922 CHAR buffer[DEFAULT_PRINTER_SIZE];
1923 CHAR org_value[DEFAULT_PRINTER_SIZE];
1926 if (!pSetDefaultPrinterA) return;
1927 /* only supported on win2k and above */
1929 /* backup the original value */
1930 org_value[0] = '\0';
1931 SetLastError(MAGIC_DEAD);
1932 res = GetProfileStringA("windows", "device", NULL, org_value, size);
1934 /* first part: with the default Printer */
1935 SetLastError(MAGIC_DEAD);
1936 res = pSetDefaultPrinterA("no_printer_with_this_name");
1938 RETURN_ON_DEACTIVATED_SPOOLER(res)
1939 /* spooler is running or we have no spooler here*/
1941 /* Not implemented in wine */
1942 if (!res && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) {
1943 trace("SetDefaultPrinterA() not implemented yet.\n");
1944 return;
1947 ok(!res && (GetLastError() == ERROR_INVALID_PRINTER_NAME),
1948 "returned %d with %d (expected '0' with "
1949 "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
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());
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());
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());
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");
1978 ok(!res && (GetLastError() == ERROR_INVALID_PRINTER_NAME),
1979 "returned %d with %d (expected '0' with "
1980 "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
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());
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());
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());
2005 /* restore the original value */
2006 res = pSetDefaultPrinterA(default_printer); /* the nice way */
2007 WriteProfileStringA("windows", "device", org_value); /* the old way */
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);
2016 /* ########################### */
2018 static void test_XcvDataW_MonitorUI(void)
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;
2028 /* api is not present before w2k */
2029 if (pXcvDataW == NULL) return;
2031 pd.pDatatype = NULL;
2032 pd.pDevMode = NULL;
2033 pd.DesiredAccess = SERVER_ACCESS_ADMINISTER;
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)
2041 ok(res, "returned %d with %u and handle %p (expected '!= 0')\n", res, GetLastError(), hXcv);
2042 if (!res) return;
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);
2054 if (needed > MAX_PATH) {
2055 ClosePrinter(hXcv);
2056 skip("buffer overflow (%u)\n", needed);
2057 return;
2059 len = needed; /* Size is in bytes */
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);
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);
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);
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);
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);
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);
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);
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);
2133 ClosePrinter(hXcv);
2136 /* ########################### */
2138 static void test_XcvDataW_PortIsValid(void)
2140 DWORD res;
2141 HANDLE hXcv;
2142 DWORD needed;
2143 DWORD status;
2144 PRINTER_DEFAULTSA pd;
2146 /* api is not present before w2k */
2147 if (pXcvDataW == NULL) return;
2149 pd.pDatatype = NULL;
2150 pd.pDevMode = NULL;
2151 pd.DesiredAccess = SERVER_ACCESS_ADMINISTER;
2153 hXcv = NULL;
2154 SetLastError(0xdeadbeef);
2155 res = OpenPrinter(xcv_localport, &hXcv, &pd);
2157 RETURN_ON_DEACTIVATED_SPOOLER(res)
2158 RETURN_ON_ACCESS_DENIED(res)
2160 ok(res, "returned %d with %u and handle %p (expected '!= 0')\n", res, GetLastError(), hXcv);
2161 if (!res) return;
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);
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);
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);
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);
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);
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);
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);
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);
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);
2245 ClosePrinter(hXcv);
2248 /* ########################### */
2250 static void test_GetPrinter(void)
2252 HANDLE hprn;
2253 BOOL ret;
2254 BYTE *buf;
2255 INT level;
2256 DWORD needed, filled;
2258 if (!default_printer)
2260 skip("There is no default printer installed\n");
2261 return;
2264 hprn = 0;
2265 ret = OpenPrinter(default_printer, &hprn, NULL);
2266 if (!ret)
2268 skip("Unable to open the default printer (%s)\n", default_printer);
2269 return;
2271 ok(hprn != 0, "wrong hprn %p\n", hprn);
2273 for (level = 1; level <= 9; level++)
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);
2284 /* GetPrinterA returns the same number of bytes as GetPrinterW */
2285 if (!on_win9x && !ret && pGetPrinterW && level != 6 && level != 7)
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);
2292 buf = HeapAlloc(GetProcessHeap(), 0, needed);
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);
2299 if (level == 2)
2301 PRINTER_INFO_2 *pi_2 = (PRINTER_INFO_2 *)buf;
2303 ok(pi_2->pPrinterName!= NULL, "not expected NULL ptr\n");
2304 ok(pi_2->pDriverName!= NULL, "not expected NULL ptr\n");
2306 trace("pPrinterName %s\n", pi_2->pPrinterName);
2307 trace("pDriverName %s\n", pi_2->pDriverName);
2310 HeapFree(GetProcessHeap(), 0, buf);
2313 SetLastError(0xdeadbeef);
2314 ret = ClosePrinter(hprn);
2315 ok(ret, "ClosePrinter error %d\n", GetLastError());
2318 /* ########################### */
2320 static void test_GetPrinterDriver(void)
2322 HANDLE hprn;
2323 BOOL ret;
2324 BYTE *buf;
2325 INT level;
2326 DWORD needed, filled;
2328 if (!default_printer)
2330 skip("There is no default printer installed\n");
2331 return;
2334 hprn = 0;
2335 ret = OpenPrinter(default_printer, &hprn, NULL);
2336 if (!ret)
2338 skip("Unable to open the default printer (%s)\n", default_printer);
2339 return;
2341 ok(hprn != 0, "wrong hprn %p\n", hprn);
2343 for (level = -1; level <= 7; level++)
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)
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);
2356 else
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;
2369 /* GetPrinterDriverA returns the same number of bytes as GetPrinterDriverW */
2370 if (!on_win9x && !ret && pGetPrinterDriverW)
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);
2377 buf = HeapAlloc(GetProcessHeap(), 0, needed);
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);
2385 if (level == 2)
2387 DRIVER_INFO_2 *di_2 = (DRIVER_INFO_2 *)buf;
2388 DWORD calculated = sizeof(*di_2);
2389 HANDLE hf;
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");
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;
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);
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);
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);
2431 /* XP allocates memory for both ANSI and unicode names */
2432 ok(filled >= calculated,"calculated %d != filled %d\n", calculated, filled);
2434 /* Obscure test - demonstrate that Windows zero fills the buffer, even on failure */
2435 if (di_2->pDataFile)
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");
2443 HeapFree(GetProcessHeap(), 0, buf);
2446 SetLastError(0xdeadbeef);
2447 ret = ClosePrinter(hprn);
2448 ok(ret, "ClosePrinter error %d\n", GetLastError());
2451 static void test_DEVMODE(const DEVMODE *dm, LONG dmSize, LPCSTR exp_prn_name)
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);
2464 trace("dmFields %08x\n", dm->dmFields);
2467 static void test_DocumentProperties(void)
2469 HANDLE hprn;
2470 LONG dm_size, ret;
2471 DEVMODE *dm;
2473 if (!default_printer)
2475 skip("There is no default printer installed\n");
2476 return;
2479 hprn = 0;
2480 ret = OpenPrinter(default_printer, &hprn, NULL);
2481 if (!ret)
2483 skip("Unable to open the default printer (%s)\n", default_printer);
2484 return;
2486 ok(hprn != 0, "wrong hprn %p\n", hprn);
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);
2492 dm = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dm_size);
2494 ret = DocumentProperties(0, hprn, NULL, dm, dm, DM_OUT_BUFFER);
2495 ok(ret == IDOK, "DocumentProperties ret value %d != expected IDOK\n", ret);
2497 test_DEVMODE(dm, dm_size, default_printer);
2499 HeapFree(GetProcessHeap(), 0, dm);
2501 SetLastError(0xdeadbeef);
2502 ret = ClosePrinter(hprn);
2503 ok(ret, "ClosePrinter error %d\n", GetLastError());
2506 static void test_EnumPrinters(void)
2508 DWORD neededA, neededW, num;
2509 DWORD ret;
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)
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");
2521 else
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");
2527 ok(num == 0, "num %d\n", num);
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))
2535 win_skip("EnumPrintersW is not implemented\n");
2536 return;
2539 if (!ret)
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");
2545 else
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");
2551 ok(num == 0, "num %d\n", num);
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);
2558 static void test_DeviceCapabilities(void)
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
2571 char name[64];
2572 } *paper_name;
2573 INT n_papers, n_paper_size, n_paper_names, n_copies, ret;
2574 DWORD fields;
2576 hComdlg32 = LoadLibrary("comdlg32.dll");
2577 assert(hComdlg32);
2578 pPrintDlgA = (void *)GetProcAddress(hComdlg32, "PrintDlgA");
2579 assert(pPrintDlgA);
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)
2588 skip("PrintDlg returned no default printer\n");
2589 return;
2591 ok(prn_dlg.hDevMode != 0, "PrintDlg returned hDevMode == NULL\n");
2592 ok(prn_dlg.hDevNames != 0, "PrintDlg returned hDevNames == NULL\n");
2594 dm = GlobalLock(prn_dlg.hDevMode);
2595 ok(dm != NULL, "GlobalLock(prn_dlg.hDevMode) failed\n");
2596 trace("dmDeviceName \"%s\"\n", dm->dmDeviceName);
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);
2609 test_DEVMODE(dm, dm->dmSize + dm->dmDriverExtra, device);
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);
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);
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);
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);
2650 /* these capabilities not available on all printer drivers */
2651 if (0)
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);
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);
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);
2670 GlobalUnlock(prn_dlg.hDevMode);
2671 GlobalFree(prn_dlg.hDevMode);
2672 GlobalUnlock(prn_dlg.hDevNames);
2673 GlobalFree(prn_dlg.hDevNames);
2676 START_TEST(info)
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");
2687 on_win9x = check_win9x();
2688 if (on_win9x)
2689 win_skip("Several W-functions are not available on Win9x/WinMe\n");
2691 find_default_printer();
2692 find_local_server();
2693 find_tempfile();
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();
2720 /* Cleanup our temporary file */
2721 DeleteFileA(tempfileA);