Release 1.6-rc2.
[wine/testsucceed.git] / dlls / winspool.drv / tests / info.c
blob3990fb80532539f9643acf2e2eea7a0db50b4381
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 defaultspooldirectory[] = "DefaultSpoolDirectory";
42 static CHAR does_not_exist_dll[]= "does_not_exist.dll";
43 static CHAR does_not_exist[] = "does_not_exist";
44 static CHAR empty[] = "";
45 static CHAR env_x64[] = "Windows x64";
46 static CHAR env_x86[] = "Windows NT x86";
47 static CHAR env_win9x_case[] = "windowS 4.0";
48 static CHAR illegal_name[] = "illegal,name";
49 static CHAR invalid_env[] = "invalid_env";
50 static CHAR LocalPortA[] = "Local Port";
51 static CHAR portname_com1[] = "COM1:";
52 static CHAR portname_file[] = "FILE:";
53 static CHAR portname_lpt1[] = "LPT1:";
54 static CHAR server_does_not_exist[] = "\\\\does_not_exist";
55 static CHAR version_dll[] = "version.dll";
56 static CHAR winetest[] = "winetest";
57 static CHAR xcv_localport[] = ",XcvMonitor Local Port";
59 static WCHAR cmd_MonitorUIW[] = {'M','o','n','i','t','o','r','U','I',0};
60 static WCHAR cmd_PortIsValidW[] = {'P','o','r','t','I','s','V','a','l','i','d',0};
61 static WCHAR emptyW[] = {0};
63 static WCHAR portname_com1W[] = {'C','O','M','1',':',0};
64 static WCHAR portname_com2W[] = {'C','O','M','2',':',0};
65 static WCHAR portname_fileW[] = {'F','I','L','E',':',0};
66 static WCHAR portname_lpt1W[] = {'L','P','T','1',':',0};
67 static WCHAR portname_lpt2W[] = {'L','P','T','2',':',0};
69 static HANDLE hwinspool;
70 static BOOL (WINAPI * pAddPortExA)(LPSTR, DWORD, LPBYTE, LPSTR);
71 static BOOL (WINAPI * pEnumPrinterDriversW)(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD);
72 static BOOL (WINAPI * pGetDefaultPrinterA)(LPSTR, LPDWORD);
73 static DWORD (WINAPI * pGetPrinterDataExA)(HANDLE, LPCSTR, LPCSTR, LPDWORD, LPBYTE, DWORD, LPDWORD);
74 static BOOL (WINAPI * pGetPrinterDriverW)(HANDLE, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD);
75 static BOOL (WINAPI * pGetPrinterW)(HANDLE, DWORD, LPBYTE, DWORD, LPDWORD);
76 static BOOL (WINAPI * pSetDefaultPrinterA)(LPCSTR);
77 static DWORD (WINAPI * pXcvDataW)(HANDLE, LPCWSTR, PBYTE, DWORD, PBYTE, DWORD, PDWORD, PDWORD);
78 static BOOL (WINAPI * pIsValidDevmodeW)(PDEVMODEW, SIZE_T);
81 /* ################################ */
83 struct monitor_entry {
84 LPSTR env;
85 CHAR dllname[32];
88 static LPSTR default_printer = NULL;
89 static LPSTR local_server = NULL;
90 static LPSTR tempdirA = NULL;
91 static LPSTR tempfileA = NULL;
92 static LPWSTR tempdirW = NULL;
93 static LPWSTR tempfileW = NULL;
95 static BOOL is_spooler_deactivated(DWORD res, DWORD lasterror)
97 if (!res && lasterror == RPC_S_SERVER_UNAVAILABLE)
99 static int deactivated_spooler_reported = 0;
100 if (!deactivated_spooler_reported)
102 deactivated_spooler_reported = 1;
103 skip("The service 'Spooler' is required for many tests\n");
105 return TRUE;
107 return FALSE;
110 static BOOL is_access_denied(DWORD res, DWORD lasterror)
112 if (!res && lasterror == ERROR_ACCESS_DENIED)
114 static int access_denied_reported = 0;
115 if (!access_denied_reported)
117 access_denied_reported = 1;
118 skip("More access rights are required for many tests\n");
120 return TRUE;
122 return FALSE;
125 static BOOL on_win9x = FALSE;
127 static BOOL check_win9x(void)
129 if (pGetPrinterW)
131 SetLastError(0xdeadbeef);
132 pGetPrinterW(NULL, 0, NULL, 0, NULL);
133 return (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED);
135 else
137 return TRUE;
141 static void find_default_printer(VOID)
143 static char buffer[DEFAULT_PRINTER_SIZE];
144 DWORD needed;
145 DWORD res;
146 LPSTR ptr;
148 if ((default_printer == NULL) && (pGetDefaultPrinterA))
150 /* w2k and above */
151 needed = sizeof(buffer);
152 res = pGetDefaultPrinterA(buffer, &needed);
153 if(res) default_printer = buffer;
154 trace("default_printer: '%s'\n", default_printer ? default_printer : "(null)");
156 if (default_printer == NULL)
158 HKEY hwindows;
159 DWORD type;
160 /* NT 3.x and above */
161 if (RegOpenKeyEx(HKEY_CURRENT_USER,
162 "Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows",
163 0, KEY_QUERY_VALUE, &hwindows) == NO_ERROR) {
165 needed = sizeof(buffer);
166 if (RegQueryValueEx(hwindows, "device", NULL,
167 &type, (LPBYTE)buffer, &needed) == NO_ERROR) {
169 ptr = strchr(buffer, ',');
170 if (ptr) {
171 ptr[0] = '\0';
172 default_printer = buffer;
175 RegCloseKey(hwindows);
177 trace("default_printer: '%s'\n", default_printer ? default_printer : "(null)");
179 if (default_printer == NULL)
181 /* win9x */
182 needed = sizeof(buffer);
183 res = GetProfileStringA("windows", "device", "*", buffer, needed);
184 if(res) {
185 ptr = strchr(buffer, ',');
186 if (ptr) {
187 ptr[0] = '\0';
188 default_printer = buffer;
191 trace("default_printer: '%s'\n", default_printer ? default_printer : "(null)");
196 static struct monitor_entry * find_installed_monitor(void)
198 MONITOR_INFO_2A mi2a;
199 static struct monitor_entry * entry = NULL;
200 DWORD num_tests;
201 DWORD i = 0;
203 static struct monitor_entry monitor_table[] = {
204 {env_win9x_case, "localspl.dll"},
205 {env_x86, "localspl.dll"},
206 {env_x64, "localspl.dll"},
207 {env_win9x_case, "localmon.dll"},
208 {env_x86, "localmon.dll"},
209 {env_win9x_case, "tcpmon.dll"},
210 {env_x86, "tcpmon.dll"},
211 {env_win9x_case, "usbmon.dll"},
212 {env_x86, "usbmon.dll"},
213 {env_win9x_case, "mspp32.dll"},
214 {env_x86, "win32spl.dll"},
215 {env_x86, "redmonnt.dll"},
216 {env_x86, "redmon35.dll"},
217 {env_win9x_case, "redmon95.dll"},
218 {env_x86, "pdfcmnnt.dll"},
219 {env_win9x_case, "pdfcmn95.dll"},
222 if (entry) return entry;
224 num_tests = (sizeof(monitor_table)/sizeof(struct monitor_entry));
226 /* cleanup */
227 DeleteMonitorA(NULL, env_x64, winetest);
228 DeleteMonitorA(NULL, env_x86, winetest);
229 DeleteMonitorA(NULL, env_win9x_case, winetest);
231 /* find a usable monitor from the table */
232 mi2a.pName = winetest;
233 while ((entry == NULL) && (i < num_tests)) {
234 entry = &monitor_table[i];
235 i++;
236 mi2a.pEnvironment = entry->env;
237 mi2a.pDLLName = entry->dllname;
239 if (AddMonitorA(NULL, 2, (LPBYTE) &mi2a)) {
240 /* we got one */
241 trace("using '%s', '%s'\n", entry->env, entry->dllname);
242 DeleteMonitorA(NULL, entry->env, winetest);
244 else
246 entry = NULL;
249 return entry;
253 /* ########################### */
255 static void find_local_server(VOID)
257 static char buffer[MAX_PATH];
258 DWORD res;
259 DWORD size;
261 size = sizeof(buffer) - 3 ;
262 buffer[0] = '\\';
263 buffer[1] = '\\';
264 buffer[2] = '\0';
266 SetLastError(0xdeadbeef);
267 res = GetComputerNameA(&buffer[2], &size);
268 trace("returned %d with %d and %d: '%s'\n", res, GetLastError(), size, buffer);
270 ok( res != 0, "returned %d with %d and %d: '%s' (expected '!= 0')\n",
271 res, GetLastError(), size, buffer);
273 if (res) local_server = buffer;
276 /* ########################### */
278 static void find_tempfile(VOID)
280 static CHAR buffer_dirA[MAX_PATH];
281 static CHAR buffer_fileA[MAX_PATH];
282 static WCHAR buffer_dirW[MAX_PATH];
283 static WCHAR buffer_fileW[MAX_PATH];
284 DWORD res;
285 int resint;
287 memset(buffer_dirA, 0, MAX_PATH - 1);
288 buffer_dirA[MAX_PATH - 1] = '\0';
289 SetLastError(0xdeadbeef);
290 res = GetTempPathA(MAX_PATH, buffer_dirA);
291 ok(res, "returned %u with %u and '%s' (expected '!= 0')\n", res, GetLastError(), buffer_dirA);
292 if (res == 0) return;
294 memset(buffer_fileA, 0, MAX_PATH - 1);
295 buffer_fileA[MAX_PATH - 1] = '\0';
296 SetLastError(0xdeadbeef);
297 res = GetTempFileNameA(buffer_dirA, winetest, 0, buffer_fileA);
298 ok(res, "returned %u with %u and '%s' (expected '!= 0')\n", res, GetLastError(), buffer_fileA);
299 if (res == 0) return;
301 SetLastError(0xdeadbeef);
302 resint = MultiByteToWideChar(CP_ACP, 0, buffer_dirA, -1, buffer_dirW, MAX_PATH);
303 ok(res, "returned %u with %u (expected '!= 0')\n", resint, GetLastError());
304 if (resint == 0) return;
306 SetLastError(0xdeadbeef);
307 resint = MultiByteToWideChar(CP_ACP, 0, buffer_fileA, -1, buffer_fileW, MAX_PATH);
308 ok(res, "returned %u with %u (expected '!= 0')\n", resint, GetLastError());
309 if (resint == 0) return;
311 tempdirA = buffer_dirA;
312 tempfileA = buffer_fileA;
313 tempdirW = buffer_dirW;
314 tempfileW = buffer_fileW;
315 trace("tempfile: '%s'\n", tempfileA);
318 /* ########################### */
320 static void test_AddMonitor(void)
322 MONITOR_INFO_2A mi2a;
323 struct monitor_entry * entry = NULL;
324 DWORD res;
326 entry = find_installed_monitor();
328 SetLastError(MAGIC_DEAD);
329 res = AddMonitorA(NULL, 1, NULL);
330 ok(!res && (GetLastError() == ERROR_INVALID_LEVEL),
331 "returned %d with %d (expected '0' with ERROR_INVALID_LEVEL)\n",
332 res, GetLastError());
334 SetLastError(MAGIC_DEAD);
335 res = AddMonitorA(NULL, 3, NULL);
336 ok(!res && (GetLastError() == ERROR_INVALID_LEVEL),
337 "returned %d with %d (expected '0' with ERROR_INVALID_LEVEL)\n",
338 res, GetLastError());
340 if (0)
342 /* This test crashes win9x on vmware (works with win9x on qemu 0.8.1) */
343 SetLastError(MAGIC_DEAD);
344 res = AddMonitorA(NULL, 2, NULL);
345 /* NT: unchanged, 9x: ERROR_PRIVILEGE_NOT_HELD */
346 ok(!res &&
347 ((GetLastError() == MAGIC_DEAD) ||
348 (GetLastError() == ERROR_PRIVILEGE_NOT_HELD)),
349 "returned %d with %d (expected '0' with: MAGIC_DEAD or "
350 "ERROR_PRIVILEGE_NOT_HELD)\n", res, GetLastError());
353 ZeroMemory(&mi2a, sizeof(MONITOR_INFO_2A));
354 SetLastError(MAGIC_DEAD);
355 res = AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
356 if (is_spooler_deactivated(res, GetLastError())) return;
357 if (is_access_denied(res, GetLastError())) return;
359 /* NT: ERROR_INVALID_PARAMETER, 9x: ERROR_INVALID_ENVIRONMENT */
360 ok(!res && ((GetLastError() == ERROR_INVALID_PARAMETER) ||
361 (GetLastError() == ERROR_INVALID_ENVIRONMENT)),
362 "returned %d with %d (expected '0' with: ERROR_INVALID_PARAMETER or "
363 "ERROR_INVALID_ENVIRONMENT)\n", res, GetLastError());
365 if (!entry) {
366 skip("No usable Monitor found\n");
367 return;
370 if (0)
372 /* The test is deactivated, because when mi2a.pName is NULL, the subkey
373 HKLM\System\CurrentControlSet\Control\Print\Monitors\C:\WINDOWS\SYSTEM
374 or HKLM\System\CurrentControlSet\Control\Print\Monitors\ì
375 is created on win9x and we do not want to hit this bug here. */
377 mi2a.pEnvironment = entry->env;
378 SetLastError(MAGIC_DEAD);
379 res = AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
380 ok(res, "AddMonitor error %d\n", GetLastError());
381 /* NT: ERROR_INVALID_PARAMETER, 9x: ERROR_PRIVILEGE_NOT_HELD */
384 mi2a.pEnvironment = entry->env;
385 mi2a.pName = empty;
386 SetLastError(MAGIC_DEAD);
387 res = AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
388 /* NT: ERROR_INVALID_PARAMETER, 9x: ERROR_PRIVILEGE_NOT_HELD */
389 ok( !res &&
390 ((GetLastError() == ERROR_INVALID_PARAMETER) ||
391 (GetLastError() == ERROR_PRIVILEGE_NOT_HELD)),
392 "returned %d with %d (expected '0' with: ERROR_INVALID_PARAMETER or "
393 "ERROR_PRIVILEGE_NOT_HELD)\n",
394 res, GetLastError());
396 mi2a.pName = winetest;
397 SetLastError(MAGIC_DEAD);
398 res = AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
399 /* NT: ERROR_INVALID_PARAMETER, 9x: ERROR_PRIVILEGE_NOT_HELD */
400 ok( !res &&
401 ((GetLastError() == ERROR_INVALID_PARAMETER) ||
402 (GetLastError() == ERROR_PRIVILEGE_NOT_HELD)),
403 "returned %d with %d (expected '0' with: ERROR_INVALID_PARAMETER or "
404 "ERROR_PRIVILEGE_NOT_HELD)\n",
405 res, GetLastError());
407 mi2a.pDLLName = empty;
408 SetLastError(MAGIC_DEAD);
409 res = AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
410 ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
411 "returned %d with %d (expected '0' with ERROR_INVALID_PARAMETER)\n",
412 res, GetLastError());
414 mi2a.pDLLName = does_not_exist_dll;
415 SetLastError(MAGIC_DEAD);
416 res = AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
417 /* NT: ERROR_MOD_NOT_FOUND, 9x: ERROR_INVALID_PARAMETER */
418 ok( !res &&
419 ((GetLastError() == ERROR_MOD_NOT_FOUND) ||
420 (GetLastError() == ERROR_INVALID_PARAMETER)),
421 "returned %d with %d (expected '0' with: ERROR_MOD_NOT_FOUND or "
422 "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
424 mi2a.pDLLName = version_dll;
425 SetLastError(MAGIC_DEAD);
426 res = AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
427 /* NT: ERROR_PROC_NOT_FOUND, 9x: ERROR_INVALID_PARAMETER */
428 ok( !res &&
429 ((GetLastError() == ERROR_PROC_NOT_FOUND) ||
430 (GetLastError() == ERROR_INVALID_PARAMETER)),
431 "returned %d with %d (expected '0' with: ERROR_PROC_NOT_FOUND or "
432 "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
433 if (res) DeleteMonitorA(NULL, entry->env, winetest);
435 /* Test AddMonitor with real options */
436 mi2a.pDLLName = entry->dllname;
437 SetLastError(MAGIC_DEAD);
438 res = AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
439 ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError());
441 /* add a monitor twice */
442 SetLastError(MAGIC_DEAD);
443 res = AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
444 /* NT: ERROR_PRINT_MONITOR_ALREADY_INSTALLED (3006), 9x: ERROR_ALREADY_EXISTS (183) */
445 ok( !res &&
446 ((GetLastError() == ERROR_PRINT_MONITOR_ALREADY_INSTALLED) ||
447 (GetLastError() == ERROR_ALREADY_EXISTS)),
448 "returned %d with %d (expected '0' with: "
449 "ERROR_PRINT_MONITOR_ALREADY_INSTALLED or ERROR_ALREADY_EXISTS)\n",
450 res, GetLastError());
452 DeleteMonitorA(NULL, entry->env, winetest);
453 SetLastError(MAGIC_DEAD);
454 res = AddMonitorA(empty, 2, (LPBYTE) &mi2a);
455 ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError());
457 /* cleanup */
458 DeleteMonitorA(NULL, entry->env, winetest);
462 /* ########################### */
464 static void test_AddPort(void)
466 DWORD res;
468 SetLastError(0xdeadbeef);
469 res = AddPortA(NULL, 0, NULL);
470 if (is_spooler_deactivated(res, GetLastError())) return;
471 /* NT: RPC_X_NULL_REF_POINTER, 9x: ERROR_INVALID_PARAMETER */
472 ok( !res && ((GetLastError() == RPC_X_NULL_REF_POINTER) ||
473 (GetLastError() == ERROR_INVALID_PARAMETER)),
474 "returned %d with %d (expected '0' with ERROR_NOT_SUPPORTED or "
475 "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
478 SetLastError(0xdeadbeef);
479 res = AddPortA(NULL, 0, empty);
480 /* Allowed only for (Printer-)Administrators */
481 if (is_access_denied(res, GetLastError())) return;
483 /* XP: ERROR_NOT_SUPPORTED, NT351 and 9x: ERROR_INVALID_PARAMETER */
484 ok( !res && ((GetLastError() == ERROR_NOT_SUPPORTED) ||
485 (GetLastError() == ERROR_INVALID_PARAMETER)),
486 "returned %d with %d (expected '0' with ERROR_NOT_SUPPORTED or "
487 "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
490 SetLastError(0xdeadbeef);
491 res = AddPortA(NULL, 0, does_not_exist);
492 /* XP: ERROR_NOT_SUPPORTED, NT351 and 9x: ERROR_INVALID_PARAMETER */
493 ok( !res && ((GetLastError() == ERROR_NOT_SUPPORTED) ||
494 (GetLastError() == ERROR_INVALID_PARAMETER)),
495 "returned %d with %d (expected '0' with ERROR_NOT_SUPPORTED or "
496 "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
500 /* ########################### */
502 static void test_AddPortEx(void)
504 PORT_INFO_2A pi;
505 DWORD res;
508 if (!pAddPortExA) {
509 win_skip("AddPortEx not supported\n");
510 return;
513 /* start test with a clean system */
514 DeletePortA(NULL, 0, tempfileA);
516 pi.pPortName = tempfileA;
517 SetLastError(0xdeadbeef);
518 res = pAddPortExA(NULL, 1, (LPBYTE) &pi, LocalPortA);
519 if (is_spooler_deactivated(res, GetLastError())) return;
521 /* Allowed only for (Printer-)Administrators.
522 W2K+XP: ERROR_INVALID_PARAMETER */
523 if (!res && (GetLastError() == ERROR_INVALID_PARAMETER)) {
524 skip("ACCESS_DENIED (ERROR_INVALID_PARAMETER)\n");
525 return;
527 ok( res, "got %u with %u (expected '!= 0')\n", res, GetLastError());
529 /* add a port that already exists */
530 SetLastError(0xdeadbeef);
531 res = pAddPortExA(NULL, 1, (LPBYTE) &pi, LocalPortA);
532 ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
533 "got %u with %u (expected '0' with ERROR_INVALID_PARAMETER)\n",
534 res, GetLastError());
535 DeletePortA(NULL, 0, tempfileA);
538 /* the Monitorname must match */
539 SetLastError(0xdeadbeef);
540 res = pAddPortExA(NULL, 1, (LPBYTE) &pi, NULL);
541 ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
542 "got %u with %u (expected '0' with ERROR_INVALID_PARAMETER)\n",
543 res, GetLastError());
544 if (res) DeletePortA(NULL, 0, tempfileA);
546 SetLastError(0xdeadbeef);
547 res = pAddPortExA(NULL, 1, (LPBYTE) &pi, empty);
548 ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
549 "got %u with %u (expected '0' with ERROR_INVALID_PARAMETER)\n",
550 res, GetLastError());
551 if (res) DeletePortA(NULL, 0, tempfileA);
553 SetLastError(0xdeadbeef);
554 res = pAddPortExA(NULL, 1, (LPBYTE) &pi, does_not_exist);
555 ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
556 "got %u with %u (expected '0' with ERROR_INVALID_PARAMETER)\n",
557 res, GetLastError());
558 if (res) DeletePortA(NULL, 0, tempfileA);
561 /* We need a Portname */
562 SetLastError(0xdeadbeef);
563 res = pAddPortExA(NULL, 1, NULL, LocalPortA);
564 ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
565 "got %u with %u (expected '0' with ERROR_INVALID_PARAMETER)\n",
566 res, GetLastError());
568 pi.pPortName = NULL;
569 SetLastError(0xdeadbeef);
570 res = pAddPortExA(NULL, 1, (LPBYTE) &pi, LocalPortA);
571 ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
572 "got %u with %u (expected '0' with ERROR_INVALID_PARAMETER)\n",
573 res, GetLastError());
574 if (res) DeletePortA(NULL, 0, tempfileA);
577 /* level 2 is documented as supported for Printmonitors,
578 but that is not supported for "Local Port" (localspl.dll) and
579 AddPortEx fails with ERROR_INVALID_LEVEL */
581 pi.pPortName = tempfileA;
582 pi.pMonitorName = LocalPortA;
583 pi.pDescription = winetest;
584 pi.fPortType = PORT_TYPE_WRITE;
586 SetLastError(0xdeadbeef);
587 res = pAddPortExA(NULL, 2, (LPBYTE) &pi, LocalPortA);
588 ok( !res && (GetLastError() == ERROR_INVALID_LEVEL),
589 "got %u with %u (expected '0' with ERROR_INVALID_LEVEL)\n",
590 res, GetLastError());
591 if (res) DeletePortA(NULL, 0, tempfileA);
594 /* invalid levels */
595 SetLastError(0xdeadbeef);
596 res = pAddPortExA(NULL, 0, (LPBYTE) &pi, LocalPortA);
597 ok( !res && (GetLastError() == ERROR_INVALID_LEVEL),
598 "got %u with %u (expected '0' with ERROR_INVALID_LEVEL)\n",
599 res, GetLastError());
601 SetLastError(0xdeadbeef);
602 res = pAddPortExA(NULL, 3, (LPBYTE) &pi, LocalPortA);
603 ok( !res && (GetLastError() == ERROR_INVALID_LEVEL),
604 "got %u with %u (expected '0' with ERROR_INVALID_LEVEL)\n",
605 res, GetLastError());
608 /* cleanup */
609 DeletePortA(NULL, 0, tempfileA);
613 /* ########################### */
615 static void test_ConfigurePort(void)
617 DWORD res;
620 SetLastError(0xdeadbeef);
621 res = ConfigurePortA(NULL, 0, NULL);
622 if (is_spooler_deactivated(res, GetLastError())) return;
623 /* NT: RPC_X_NULL_REF_POINTER, 9x: ERROR_INVALID_PARAMETER */
624 ok( !res && ((GetLastError() == RPC_X_NULL_REF_POINTER) ||
625 (GetLastError() == ERROR_INVALID_PARAMETER)),
626 "returned %d with %d (expected '0' with ERROR_NOT_SUPPORTED or "
627 "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
629 SetLastError(0xdeadbeef);
630 res = ConfigurePortA(NULL, 0, empty);
631 /* Allowed only for (Printer-)Administrators */
632 if (is_access_denied(res, GetLastError())) return;
634 /* XP: ERROR_NOT_SUPPORTED, NT351 and 9x: ERROR_INVALID_PARAMETER */
635 ok( !res && ((GetLastError() == ERROR_NOT_SUPPORTED) ||
636 (GetLastError() == ERROR_INVALID_PARAMETER)),
637 "returned %d with %d (expected '0' with ERROR_NOT_SUPPORTED or "
638 "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
641 SetLastError(0xdeadbeef);
642 res = ConfigurePortA(NULL, 0, does_not_exist);
643 /* XP: ERROR_NOT_SUPPORTED, NT351 and 9x: ERROR_INVALID_PARAMETER */
644 ok( !res && ((GetLastError() == ERROR_NOT_SUPPORTED) ||
645 (GetLastError() == ERROR_INVALID_PARAMETER)),
646 "returned %d with %d (expected '0' with ERROR_NOT_SUPPORTED or "
647 "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
650 /* Testing-Results:
651 - Case of Portnames is ignored
652 - Portname without ":" => NT: ERROR_NOT_SUPPORTED, 9x: Dialog comes up
653 - Empty Servername (LPT1:) => NT: ERROR_NOT_SUPPORTED, 9x: Dialog comes up
655 - Port not present => 9x: ERROR_INVALID_PARAMETER, NT:ERROR_NOT_SUPPORTED
656 - "FILE:" => 9x:Success, NT:ERROR_CANCELED
657 - Cancel ("Local Port") => ERROR_CANCELED
658 - Cancel ("Redirected Port") => Success
660 if (winetest_interactive > 0) {
661 SetLastError(0xdeadbeef);
662 res = ConfigurePortA(NULL, 0, portname_com1);
663 trace("'%s' returned %d with %d\n", portname_com1, res, GetLastError());
665 SetLastError(0xdeadbeef);
666 res = ConfigurePortA(NULL, 0, portname_lpt1);
667 trace("'%s' returned %d with %d\n", portname_lpt1, res, GetLastError());
669 SetLastError(0xdeadbeef);
670 res = ConfigurePortA(NULL, 0, portname_file);
671 trace("'%s' returned %d with %d\n", portname_file, res, GetLastError());
675 /* ########################### */
677 static void test_DeleteMonitor(void)
679 MONITOR_INFO_2A mi2a;
680 struct monitor_entry * entry = NULL;
681 DWORD res;
684 entry = find_installed_monitor();
686 if (!entry) {
687 skip("No usable Monitor found\n");
688 return;
691 mi2a.pName = winetest;
692 mi2a.pEnvironment = entry->env;
693 mi2a.pDLLName = entry->dllname;
695 /* Testing DeleteMonitor with real options */
696 AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
698 SetLastError(MAGIC_DEAD);
699 res = DeleteMonitorA(NULL, entry->env, winetest);
700 ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError());
702 /* Delete the Monitor twice */
703 SetLastError(MAGIC_DEAD);
704 res = DeleteMonitorA(NULL, entry->env, winetest);
705 /* NT: ERROR_UNKNOWN_PRINT_MONITOR (3000), 9x: ERROR_INVALID_PARAMETER (87) */
706 ok( !res &&
707 ((GetLastError() == ERROR_UNKNOWN_PRINT_MONITOR) ||
708 (GetLastError() == ERROR_INVALID_PARAMETER)),
709 "returned %d with %d (expected '0' with: ERROR_UNKNOWN_PRINT_MONITOR"
710 " or ERROR_INVALID_PARAMETER)\n", res, GetLastError());
712 /* the environment */
713 AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
714 SetLastError(MAGIC_DEAD);
715 res = DeleteMonitorA(NULL, NULL, winetest);
716 ok(res, "returned %d with %d (expected '!=0')\n", res, GetLastError());
718 AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
719 SetLastError(MAGIC_DEAD);
720 res = DeleteMonitorA(NULL, empty, winetest);
721 ok(res, "returned %d with %d (expected '!=0')\n", res, GetLastError());
723 AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
724 SetLastError(MAGIC_DEAD);
725 res = DeleteMonitorA(NULL, invalid_env, winetest);
726 ok( res ||
727 (!res && GetLastError() == ERROR_INVALID_ENVIRONMENT) /* Vista/W2K8 */,
728 "returned %d with %d\n", res, GetLastError());
730 /* the monitor-name */
731 AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
732 SetLastError(MAGIC_DEAD);
733 res = DeleteMonitorA(NULL, entry->env, NULL);
734 /* NT: ERROR_INVALID_PARAMETER (87), 9x: ERROR_INVALID_NAME (123)*/
735 ok( !res &&
736 ((GetLastError() == ERROR_INVALID_PARAMETER) ||
737 (GetLastError() == ERROR_INVALID_NAME)),
738 "returned %d with %d (expected '0' with: ERROR_INVALID_PARAMETER or "
739 "ERROR_INVALID_NAME)\n", res, GetLastError());
741 AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
742 SetLastError(MAGIC_DEAD);
743 res = DeleteMonitorA(NULL, entry->env, empty);
744 /* NT: ERROR_INVALID_PARAMETER (87), 9x: ERROR_INVALID_NAME (123)*/
745 ok( !res &&
746 ((GetLastError() == ERROR_INVALID_PARAMETER) ||
747 (GetLastError() == ERROR_INVALID_NAME)),
748 "returned %d with %d (expected '0' with: ERROR_INVALID_PARAMETER or "
749 "ERROR_INVALID_NAME)\n", res, GetLastError());
751 AddMonitorA(NULL, 2, (LPBYTE) &mi2a);
752 SetLastError(MAGIC_DEAD);
753 res = DeleteMonitorA(empty, entry->env, winetest);
754 ok(res, "returned %d with %d (expected '!=0')\n", res, GetLastError());
756 /* cleanup */
757 DeleteMonitorA(NULL, entry->env, winetest);
760 /* ########################### */
762 static void test_DeletePort(void)
764 DWORD res;
766 SetLastError(0xdeadbeef);
767 res = DeletePortA(NULL, 0, NULL);
768 if (is_spooler_deactivated(res, GetLastError())) return;
770 SetLastError(0xdeadbeef);
771 res = DeletePortA(NULL, 0, empty);
772 /* Allowed only for (Printer-)Administrators */
773 if (is_access_denied(res, GetLastError())) return;
775 /* XP: ERROR_NOT_SUPPORTED, NT351 and 9x: ERROR_INVALID_PARAMETER */
776 ok( !res && ((GetLastError() == ERROR_NOT_SUPPORTED) ||
777 (GetLastError() == ERROR_INVALID_PARAMETER)),
778 "returned %d with %d (expected '0' with ERROR_NOT_SUPPORTED or "
779 "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
782 SetLastError(0xdeadbeef);
783 res = DeletePortA(NULL, 0, does_not_exist);
784 /* XP: ERROR_NOT_SUPPORTED, NT351 and 9x: ERROR_INVALID_PARAMETER */
785 ok( !res && ((GetLastError() == ERROR_NOT_SUPPORTED) ||
786 (GetLastError() == ERROR_INVALID_PARAMETER)),
787 "returned %d with %d (expected '0' with ERROR_NOT_SUPPORTED or "
788 "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
792 /* ########################### */
794 static void test_EnumForms(LPSTR pName)
796 DWORD res;
797 HANDLE hprinter = 0;
798 LPBYTE buffer;
799 DWORD cbBuf;
800 DWORD pcbNeeded;
801 DWORD pcReturned;
802 DWORD level;
803 UINT i;
804 const char *formtype;
805 static const char * const formtypes[] = { "FORM_USER", "FORM_BUILTIN", "FORM_PRINTER", "FORM_flag_unknown" };
806 #define FORMTYPE_MAX 2
807 PFORM_INFO_1A pFI_1a;
808 PFORM_INFO_2A pFI_2a;
810 res = OpenPrinter(pName, &hprinter, NULL);
811 if (is_spooler_deactivated(res, GetLastError())) return;
812 if (!res || !hprinter)
814 /* opening the local Printserver is not supported on win9x */
815 if (pName) skip("Failed to open '%s' (not supported on win9x)\n", pName);
816 return;
819 /* valid levels are 1 and 2 */
820 for(level = 0; level < 4; level++) {
821 cbBuf = 0xdeadbeef;
822 pcReturned = 0xdeadbeef;
823 SetLastError(0xdeadbeef);
824 res = EnumFormsA(hprinter, level, NULL, 0, &cbBuf, &pcReturned);
826 /* EnumForms is not implemented on win9x */
827 if (!res && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) continue;
829 /* EnumForms for the server is not implemented on all NT-versions */
830 if (!res && (GetLastError() == ERROR_INVALID_HANDLE) && !pName) continue;
832 /* Level 2 for EnumForms is not supported on all systems */
833 if (!res && (GetLastError() == ERROR_INVALID_LEVEL) && (level == 2)) continue;
835 /* use only a short test when testing an invalid level */
836 if(!level || (level > 2)) {
837 ok( (!res && (GetLastError() == ERROR_INVALID_LEVEL)) ||
838 (res && (pcReturned == 0)),
839 "(%d) returned %d with %d and 0x%08x (expected '0' with "
840 "ERROR_INVALID_LEVEL or '!=0' and 0x0)\n",
841 level, res, GetLastError(), pcReturned);
842 continue;
845 ok((!res) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
846 "(%d) returned %d with %d (expected '0' with "
847 "ERROR_INSUFFICIENT_BUFFER)\n", level, res, GetLastError());
849 buffer = HeapAlloc(GetProcessHeap(), 0, cbBuf *2);
850 if (buffer == NULL) continue;
852 SetLastError(0xdeadbeef);
853 res = EnumFormsA(hprinter, level, buffer, cbBuf, &pcbNeeded, &pcReturned);
854 ok(res, "(%d) returned %d with %d (expected '!=0')\n",
855 level, res, GetLastError());
857 if (winetest_debug > 1) {
858 trace("dumping %d forms level %d\n", pcReturned, level);
859 pFI_1a = (PFORM_INFO_1A)buffer;
860 pFI_2a = (PFORM_INFO_2A)buffer;
861 for (i = 0; i < pcReturned; i++)
863 /* first part is same in FORM_INFO_1 and FORM_INFO_2 */
864 formtype = (pFI_1a->Flags <= FORMTYPE_MAX) ? formtypes[pFI_1a->Flags] : formtypes[3];
865 trace("%u (%s): %.03fmm x %.03fmm, %s\n", i, pFI_1a->pName,
866 (float)pFI_1a->Size.cx/1000, (float)pFI_1a->Size.cy/1000, formtype);
868 if (level == 1) pFI_1a ++;
869 else {
870 /* output additional FORM_INFO_2 fields */
871 trace("\tkeyword=%s strtype=%u muidll=%s resid=%u dispname=%s langid=%u\n",
872 pFI_2a->pKeyword, pFI_2a->StringType, pFI_2a->pMuiDll,
873 pFI_2a->dwResourceId, pFI_2a->pDisplayName, pFI_2a->wLangId);
875 /* offset pointer pFI_1a by 1*sizeof(FORM_INFO_2A) Bytes */
876 pFI_2a ++;
877 pFI_1a = (PFORM_INFO_1A)pFI_2a;
882 SetLastError(0xdeadbeef);
883 res = EnumFormsA(hprinter, level, buffer, cbBuf+1, &pcbNeeded, &pcReturned);
884 ok( res, "(%d) returned %d with %d (expected '!=0')\n",
885 level, res, GetLastError());
887 SetLastError(0xdeadbeef);
888 res = EnumFormsA(hprinter, level, buffer, cbBuf-1, &pcbNeeded, &pcReturned);
889 ok( !res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
890 "(%d) returned %d with %d (expected '0' with "
891 "ERROR_INSUFFICIENT_BUFFER)\n", level, res, GetLastError());
894 SetLastError(0xdeadbeef);
895 res = EnumFormsA(hprinter, level, NULL, cbBuf, &pcbNeeded, &pcReturned);
896 ok( !res && (GetLastError() == ERROR_INVALID_USER_BUFFER) ,
897 "(%d) returned %d with %d (expected '0' with "
898 "ERROR_INVALID_USER_BUFFER)\n", level, res, GetLastError());
901 SetLastError(0xdeadbeef);
902 res = EnumFormsA(hprinter, level, buffer, cbBuf, NULL, &pcReturned);
903 ok( !res && (GetLastError() == RPC_X_NULL_REF_POINTER) ,
904 "(%d) returned %d with %d (expected '0' with "
905 "RPC_X_NULL_REF_POINTER)\n", level, res, GetLastError());
907 SetLastError(0xdeadbeef);
908 res = EnumFormsA(hprinter, level, buffer, cbBuf, &pcbNeeded, NULL);
909 ok( !res && (GetLastError() == RPC_X_NULL_REF_POINTER) ,
910 "(%d) returned %d with %d (expected '0' with "
911 "RPC_X_NULL_REF_POINTER)\n", level, res, GetLastError());
913 SetLastError(0xdeadbeef);
914 res = EnumFormsA(0, level, buffer, cbBuf, &pcbNeeded, &pcReturned);
915 ok( !res && (GetLastError() == ERROR_INVALID_HANDLE) ,
916 "(%d) returned %d with %d (expected '0' with "
917 "ERROR_INVALID_HANDLE)\n", level, res, GetLastError());
919 HeapFree(GetProcessHeap(), 0, buffer);
920 } /* for(level ... */
922 ClosePrinter(hprinter);
925 /* ########################### */
927 static void test_EnumMonitors(void)
929 DWORD res;
930 LPBYTE buffer;
931 DWORD cbBuf;
932 DWORD pcbNeeded;
933 DWORD pcReturned;
934 DWORD level;
936 /* valid levels are 1 and 2 */
937 for(level = 0; level < 4; level++) {
938 cbBuf = MAGIC_DEAD;
939 pcReturned = MAGIC_DEAD;
940 SetLastError(MAGIC_DEAD);
941 res = EnumMonitorsA(NULL, level, NULL, 0, &cbBuf, &pcReturned);
942 if (is_spooler_deactivated(res, GetLastError())) return;
943 /* not implemented yet in wine */
944 if (!res && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) continue;
947 /* use only a short test when testing an invalid level */
948 if(!level || (level > 2)) {
949 ok( (!res && (GetLastError() == ERROR_INVALID_LEVEL)) ||
950 (res && (pcReturned == 0)),
951 "(%d) returned %d with %d and 0x%08x (expected '0' with "
952 "ERROR_INVALID_LEVEL or '!=0' and 0x0)\n",
953 level, res, GetLastError(), pcReturned);
954 continue;
957 /* Level 2 is not supported on win9x */
958 if (!res && (GetLastError() == ERROR_INVALID_LEVEL)) {
959 skip("Level %d not supported\n", level);
960 continue;
963 ok((!res) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
964 "(%d) returned %d with %d (expected '0' with "
965 "ERROR_INSUFFICIENT_BUFFER)\n", level, res, GetLastError());
967 if (!cbBuf) {
968 skip("no valid buffer size returned\n");
969 continue;
972 buffer = HeapAlloc(GetProcessHeap(), 0, cbBuf *2);
973 if (buffer == NULL) continue;
975 SetLastError(MAGIC_DEAD);
976 pcbNeeded = MAGIC_DEAD;
977 res = EnumMonitorsA(NULL, level, buffer, cbBuf, &pcbNeeded, &pcReturned);
978 ok(res, "(%d) returned %d with %d (expected '!=0')\n",
979 level, res, GetLastError());
980 ok(pcbNeeded == cbBuf, "(%d) returned %d (expected %d)\n",
981 level, pcbNeeded, cbBuf);
982 /* We can validate the returned Data with the Registry here */
985 SetLastError(MAGIC_DEAD);
986 pcReturned = MAGIC_DEAD;
987 pcbNeeded = MAGIC_DEAD;
988 res = EnumMonitorsA(NULL, level, buffer, cbBuf+1, &pcbNeeded, &pcReturned);
989 ok(res, "(%d) returned %d with %d (expected '!=0')\n", level,
990 res, GetLastError());
991 ok(pcbNeeded == cbBuf, "(%d) returned %d (expected %d)\n", level,
992 pcbNeeded, cbBuf);
994 SetLastError(MAGIC_DEAD);
995 pcbNeeded = MAGIC_DEAD;
996 res = EnumMonitorsA(NULL, level, buffer, cbBuf-1, &pcbNeeded, &pcReturned);
997 ok( !res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
998 "(%d) returned %d with %d (expected '0' with "
999 "ERROR_INSUFFICIENT_BUFFER)\n", level, res, GetLastError());
1001 ok(pcbNeeded == cbBuf, "(%d) returned %d (expected %d)\n", level,
1002 pcbNeeded, cbBuf);
1005 Do not add the next test:
1006 w2k+: RPC_X_NULL_REF_POINTER
1007 NT3.5: ERROR_INVALID_USER_BUFFER
1008 win9x: crash in winspool.drv
1010 res = EnumMonitorsA(NULL, level, NULL, cbBuf, &pcbNeeded, &pcReturned);
1013 SetLastError(MAGIC_DEAD);
1014 pcbNeeded = MAGIC_DEAD;
1015 pcReturned = MAGIC_DEAD;
1016 res = EnumMonitorsA(NULL, level, buffer, cbBuf, NULL, &pcReturned);
1017 ok( res || (!res && (GetLastError() == RPC_X_NULL_REF_POINTER)) ,
1018 "(%d) returned %d with %d (expected '!=0' or '0' with "
1019 "RPC_X_NULL_REF_POINTER)\n", level, res, GetLastError());
1021 pcbNeeded = MAGIC_DEAD;
1022 pcReturned = MAGIC_DEAD;
1023 SetLastError(MAGIC_DEAD);
1024 res = EnumMonitorsA(NULL, level, buffer, cbBuf, &pcbNeeded, NULL);
1025 ok( res || (!res && (GetLastError() == RPC_X_NULL_REF_POINTER)) ,
1026 "(%d) returned %d with %d (expected '!=0' or '0' with "
1027 "RPC_X_NULL_REF_POINTER)\n", level, res, GetLastError());
1029 HeapFree(GetProcessHeap(), 0, buffer);
1030 } /* for(level ... */
1033 /* ########################### */
1035 static void test_EnumPorts(void)
1037 DWORD res;
1038 DWORD level;
1039 LPBYTE buffer;
1040 DWORD cbBuf;
1041 DWORD pcbNeeded;
1042 DWORD pcReturned;
1044 /* valid levels are 1 and 2 */
1045 for(level = 0; level < 4; level++) {
1047 cbBuf = 0xdeadbeef;
1048 pcReturned = 0xdeadbeef;
1049 SetLastError(0xdeadbeef);
1050 res = EnumPortsA(NULL, level, NULL, 0, &cbBuf, &pcReturned);
1051 if (is_spooler_deactivated(res, GetLastError())) return;
1053 /* use only a short test when testing an invalid level */
1054 if(!level || (level > 2)) {
1055 /* NT: ERROR_INVALID_LEVEL, 9x: success */
1056 ok( (!res && (GetLastError() == ERROR_INVALID_LEVEL)) ||
1057 (res && (pcReturned == 0)),
1058 "(%d) returned %d with %d and 0x%08x (expected '0' with "
1059 "ERROR_INVALID_LEVEL or '!=0' and 0x0)\n",
1060 level, res, GetLastError(), pcReturned);
1061 continue;
1065 /* Level 2 is not supported on NT 3.x */
1066 if (!res && (GetLastError() == ERROR_INVALID_LEVEL)) {
1067 skip("Level %d not supported\n", level);
1068 continue;
1071 ok((!res) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1072 "(%d) returned %d with %d (expected '0' with "
1073 "ERROR_INSUFFICIENT_BUFFER)\n", level, res, GetLastError());
1075 buffer = HeapAlloc(GetProcessHeap(), 0, cbBuf *2);
1076 if (buffer == NULL) continue;
1078 pcbNeeded = 0xdeadbeef;
1079 SetLastError(0xdeadbeef);
1080 res = EnumPortsA(NULL, level, buffer, cbBuf, &pcbNeeded, &pcReturned);
1081 ok(res, "(%d) returned %d with %d (expected '!=0')\n", level, res, GetLastError());
1082 ok(pcbNeeded == cbBuf, "(%d) returned %d (expected %d)\n", level, pcbNeeded, cbBuf);
1083 /* ToDo: Compare the returned Data with the Registry / "win.ini",[Ports] here */
1085 pcbNeeded = 0xdeadbeef;
1086 pcReturned = 0xdeadbeef;
1087 SetLastError(0xdeadbeef);
1088 res = EnumPortsA(NULL, level, buffer, cbBuf+1, &pcbNeeded, &pcReturned);
1089 ok(res, "(%d) returned %d with %d (expected '!=0')\n", level, res, GetLastError());
1090 ok(pcbNeeded == cbBuf, "(%d) returned %d (expected %d)\n", level, pcbNeeded, cbBuf);
1092 pcbNeeded = 0xdeadbeef;
1093 SetLastError(0xdeadbeef);
1094 res = EnumPortsA(NULL, level, buffer, cbBuf-1, &pcbNeeded, &pcReturned);
1095 ok( !res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1096 "(%d) returned %d with %d (expected '0' with "
1097 "ERROR_INSUFFICIENT_BUFFER)\n", level, res, GetLastError());
1098 ok(pcbNeeded == cbBuf, "(%d) returned %d (expected %d)\n", level, pcbNeeded, cbBuf);
1101 Do not add this test:
1102 res = EnumPortsA(NULL, level, NULL, cbBuf, &pcbNeeded, &pcReturned);
1103 w2k+: RPC_X_NULL_REF_POINTER
1104 NT3.5: ERROR_INVALID_USER_BUFFER
1105 win9x: crash in winspool.drv
1108 SetLastError(0xdeadbeef);
1109 res = EnumPorts(NULL, level, buffer, cbBuf, NULL, &pcReturned);
1110 /* NT: RPC_X_NULL_REF_POINTER (1780), 9x: success */
1111 ok( (!res && (GetLastError() == RPC_X_NULL_REF_POINTER) ) ||
1112 ( res && (GetLastError() == ERROR_SUCCESS) ),
1113 "(%d) returned %d with %d (expected '0' with "
1114 "RPC_X_NULL_REF_POINTER or '!=0' with NO_ERROR)\n",
1115 level, res, GetLastError());
1118 SetLastError(0xdeadbeef);
1119 res = EnumPorts(NULL, level, buffer, cbBuf, &pcbNeeded, NULL);
1120 /* NT: RPC_X_NULL_REF_POINTER (1780), 9x: success */
1121 ok( (!res && (GetLastError() == RPC_X_NULL_REF_POINTER) ) ||
1122 ( res && (GetLastError() == ERROR_SUCCESS) ),
1123 "(%d) returned %d with %d (expected '0' with "
1124 "RPC_X_NULL_REF_POINTER or '!=0' with NO_ERROR)\n",
1125 level, res, GetLastError());
1127 HeapFree(GetProcessHeap(), 0, buffer);
1131 /* ########################### */
1133 static void test_EnumPrinterDrivers(void)
1135 static char env_all[] = "all";
1137 DWORD res;
1138 LPBYTE buffer;
1139 DWORD cbBuf;
1140 DWORD pcbNeeded;
1141 DWORD pcReturned;
1142 DWORD level;
1144 /* 1-3 for w95/w98/NT4; 1-3+6 for me; 1-6 for w2k/xp/2003; 1-6+8 for vista */
1145 for(level = 0; level < 10; level++) {
1146 cbBuf = 0xdeadbeef;
1147 pcReturned = 0xdeadbeef;
1148 SetLastError(0xdeadbeef);
1149 res = EnumPrinterDriversA(NULL, NULL, level, NULL, 0, &cbBuf, &pcReturned);
1150 if (is_spooler_deactivated(res, GetLastError())) return;
1152 /* use only a short test when testing an invalid level */
1153 if(!level || (level == 7) || (level > 8)) {
1155 ok( (!res && (GetLastError() == ERROR_INVALID_LEVEL)) ||
1156 (res && (pcReturned == 0)),
1157 "(%d) got %u with %u and 0x%x "
1158 "(expected '0' with ERROR_INVALID_LEVEL or '!=0' and 0x0)\n",
1159 level, res, GetLastError(), pcReturned);
1160 continue;
1163 /* some levels are not supported on all windows versions */
1164 if (!res && (GetLastError() == ERROR_INVALID_LEVEL)) {
1165 skip("Level %d not supported\n", level);
1166 continue;
1169 ok( ((!res) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) ||
1170 (res && (default_printer == NULL)),
1171 "(%u) got %u with %u for %s (expected '0' with "
1172 "ERROR_INSUFFICIENT_BUFFER or '!= 0' without a printer)\n",
1173 level, res, GetLastError(), default_printer);
1175 if (!cbBuf) {
1176 skip("no valid buffer size returned\n");
1177 continue;
1180 /* EnumPrinterDriversA returns the same number of bytes as EnumPrinterDriversW */
1181 if (!on_win9x && pEnumPrinterDriversW)
1183 DWORD double_needed;
1184 DWORD double_returned;
1185 pEnumPrinterDriversW(NULL, NULL, level, NULL, 0, &double_needed, &double_returned);
1186 ok(double_needed == cbBuf, "level %d: EnumPrinterDriversA returned different size %d than EnumPrinterDriversW (%d)\n", level, cbBuf, double_needed);
1189 buffer = HeapAlloc(GetProcessHeap(), 0, cbBuf + 4);
1190 if (buffer == NULL) continue;
1192 SetLastError(0xdeadbeef);
1193 pcbNeeded = 0xdeadbeef;
1194 res = EnumPrinterDriversA(NULL, NULL, level, buffer, cbBuf, &pcbNeeded, &pcReturned);
1195 ok(res, "(%u) got %u with %u (expected '!=0')\n", level, res, GetLastError());
1196 ok(pcbNeeded == cbBuf, "(%d) returned %d (expected %d)\n", level, pcbNeeded, cbBuf);
1198 /* validate the returned data here */
1199 if (level > 1) {
1200 LPDRIVER_INFO_2A di = (LPDRIVER_INFO_2A) buffer;
1202 ok( strrchr(di->pDriverPath, '\\') != NULL,
1203 "(%u) got %s for %s (expected a full path)\n",
1204 level, di->pDriverPath, di->pName);
1208 SetLastError(0xdeadbeef);
1209 pcReturned = 0xdeadbeef;
1210 pcbNeeded = 0xdeadbeef;
1211 res = EnumPrinterDriversA(NULL, NULL, level, buffer, cbBuf+1, &pcbNeeded, &pcReturned);
1212 ok(res, "(%u) got %u with %u (expected '!=0')\n", level, res, GetLastError());
1213 ok(pcbNeeded == cbBuf, "(%u) returned %u (expected %u)\n", level, pcbNeeded, cbBuf);
1215 SetLastError(0xdeadbeef);
1216 pcbNeeded = 0xdeadbeef;
1217 res = EnumPrinterDriversA(NULL, NULL, level, buffer, cbBuf-1, &pcbNeeded, &pcReturned);
1218 ok( !res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1219 "(%u) got %u with %u (expected '0' with ERROR_INSUFFICIENT_BUFFER)\n",
1220 level, res, GetLastError());
1221 ok(pcbNeeded == cbBuf, "(%u) returned %u (expected %u)\n", level, pcbNeeded, cbBuf);
1224 Do not add the next test:
1225 NT: ERROR_INVALID_USER_BUFFER
1226 win9x: crash or 100% CPU
1228 res = EnumPrinterDriversA(NULL, NULL, level, NULL, cbBuf, &pcbNeeded, &pcReturned);
1231 SetLastError(0xdeadbeef);
1232 pcbNeeded = 0xdeadbeef;
1233 pcReturned = 0xdeadbeef;
1234 res = EnumPrinterDriversA(NULL, NULL, level, buffer, cbBuf, NULL, &pcReturned);
1235 ok( res || (!res && (GetLastError() == RPC_X_NULL_REF_POINTER)) ,
1236 "(%u) got %u with %u (expected '!=0' or '0' with "
1237 "RPC_X_NULL_REF_POINTER)\n", level, res, GetLastError());
1239 pcbNeeded = 0xdeadbeef;
1240 pcReturned = 0xdeadbeef;
1241 SetLastError(0xdeadbeef);
1242 res = EnumPrinterDriversA(NULL, NULL, level, buffer, cbBuf, &pcbNeeded, NULL);
1243 ok( res || (!res && (GetLastError() == RPC_X_NULL_REF_POINTER)) ,
1244 "(%u) got %u with %u (expected '!=0' or '0' with "
1245 "RPC_X_NULL_REF_POINTER)\n", level, res, GetLastError());
1247 HeapFree(GetProcessHeap(), 0, buffer);
1248 } /* for(level ... */
1250 pcbNeeded = 0;
1251 pcReturned = 0;
1252 SetLastError(0xdeadbeef);
1253 res = EnumPrinterDriversA(NULL, env_all, 1, NULL, 0, &pcbNeeded, &pcReturned);
1254 if (res)
1256 skip("no printer drivers found\n");
1257 return;
1259 if (GetLastError() == ERROR_INVALID_ENVIRONMENT)
1261 win_skip("NT4 and below don't support the 'all' environment value\n");
1262 return;
1264 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "unexpected error %u\n", GetLastError());
1266 buffer = HeapAlloc(GetProcessHeap(), 0, pcbNeeded);
1267 res = EnumPrinterDriversA(NULL, env_all, 1, buffer, pcbNeeded, &pcbNeeded, &pcReturned);
1268 ok(res, "EnumPrinterDriversA failed %u\n", GetLastError());
1269 if (res && pcReturned > 0)
1271 DRIVER_INFO_1 *di_1 = (DRIVER_INFO_1 *)buffer;
1272 ok((LPBYTE) di_1->pName == NULL || (LPBYTE) di_1->pName < buffer ||
1273 (LPBYTE) di_1->pName >= (LPBYTE)(di_1 + pcReturned),
1274 "Driver Information not in sequence; pName %p, top of data %p\n",
1275 di_1->pName, di_1 + pcReturned);
1278 HeapFree(GetProcessHeap(), 0, buffer);
1281 /* ########################### */
1283 static void test_EnumPrintProcessors(void)
1285 DWORD res;
1286 LPBYTE buffer;
1287 DWORD cbBuf;
1288 DWORD pcbNeeded;
1289 DWORD pcReturned;
1292 cbBuf = 0xdeadbeef;
1293 pcReturned = 0xdeadbeef;
1294 SetLastError(0xdeadbeef);
1295 res = EnumPrintProcessorsA(NULL, NULL, 1, NULL, 0, &cbBuf, &pcReturned);
1296 if (is_spooler_deactivated(res, GetLastError())) return;
1298 if (res && !cbBuf) {
1299 skip("No Printprocessor installed\n");
1300 return;
1303 ok((!res) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1304 "got %u with %u (expected '0' with ERROR_INSUFFICIENT_BUFFER)\n",
1305 res, GetLastError());
1307 buffer = HeapAlloc(GetProcessHeap(), 0, cbBuf + 4);
1308 if (buffer == NULL)
1309 return;
1311 SetLastError(0xdeadbeef);
1312 pcbNeeded = 0xdeadbeef;
1313 res = EnumPrintProcessorsA(NULL, NULL, 1, buffer, cbBuf, &pcbNeeded, &pcReturned);
1314 ok(res, "got %u with %u (expected '!=0')\n", res, GetLastError());
1315 /* validate the returned data here. */
1318 SetLastError(0xdeadbeef);
1319 pcReturned = 0xdeadbeef;
1320 pcbNeeded = 0xdeadbeef;
1321 res = EnumPrintProcessorsA(NULL, NULL, 1, buffer, cbBuf+1, &pcbNeeded, &pcReturned);
1322 ok(res, "got %u with %u (expected '!=0')\n", res, GetLastError());
1324 SetLastError(0xdeadbeef);
1325 pcbNeeded = 0xdeadbeef;
1326 res = EnumPrintProcessorsA(NULL, NULL, 1, buffer, cbBuf-1, &pcbNeeded, &pcReturned);
1327 ok( !res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1328 "got %u with %u (expected '0' with ERROR_INSUFFICIENT_BUFFER)\n",
1329 res, GetLastError());
1331 /* only level 1 is valid */
1332 if (0) {
1333 /* both tests crash on win98se */
1334 SetLastError(0xdeadbeef);
1335 pcbNeeded = 0xdeadbeef;
1336 pcReturned = 0xdeadbeef;
1337 res = EnumPrintProcessorsA(NULL, NULL, 0, buffer, cbBuf, &pcbNeeded, &pcReturned);
1338 ok( !res && (GetLastError() == ERROR_INVALID_LEVEL),
1339 "got %u with %u (expected '0' with ERROR_INVALID_LEVEL)\n",
1340 res, GetLastError());
1342 SetLastError(0xdeadbeef);
1343 pcbNeeded = 0xdeadbeef;
1344 res = EnumPrintProcessorsA(NULL, NULL, 2, buffer, cbBuf, &pcbNeeded, &pcReturned);
1345 ok( !res && (GetLastError() == ERROR_INVALID_LEVEL),
1346 "got %u with %u (expected '0' with ERROR_INVALID_LEVEL)\n",
1347 res, GetLastError());
1350 /* an empty environment is ignored */
1351 SetLastError(0xdeadbeef);
1352 pcbNeeded = 0xdeadbeef;
1353 res = EnumPrintProcessorsA(NULL, empty, 1, buffer, cbBuf, &pcbNeeded, &pcReturned);
1354 ok(res, "got %u with %u (expected '!=0')\n", res, GetLastError());
1356 /* the environment is checked */
1357 SetLastError(0xdeadbeef);
1358 pcbNeeded = 0xdeadbeef;
1359 res = EnumPrintProcessorsA(NULL, invalid_env, 1, buffer, cbBuf, &pcbNeeded, &pcReturned);
1360 /* NT5: ERROR_INVALID_ENVIRONMENT, NT4: res != 0, 9x: ERROR_INVALID_PARAMETER */
1361 ok( broken(res) || /* NT4 */
1362 (GetLastError() == ERROR_INVALID_ENVIRONMENT) ||
1363 (GetLastError() == ERROR_INVALID_PARAMETER),
1364 "got %u with %u (expected '0' with ERROR_INVALID_ENVIRONMENT or "
1365 "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
1368 /* failure-Codes for NULL */
1369 if (0) {
1370 /* this test crashes on win98se */
1371 SetLastError(0xdeadbeef);
1372 pcbNeeded = 0xdeadbeef;
1373 pcReturned = 0xdeadbeef;
1374 res = EnumPrintProcessorsA(NULL, NULL, 1, NULL, cbBuf, &pcbNeeded, &pcReturned);
1375 ok( !res && (GetLastError() == ERROR_INVALID_USER_BUFFER) ,
1376 "got %u with %u (expected '0' with ERROR_INVALID_USER_BUFFER)\n",
1377 res, GetLastError());
1380 SetLastError(0xdeadbeef);
1381 pcbNeeded = 0xdeadbeef;
1382 pcReturned = 0xdeadbeef;
1383 res = EnumPrintProcessorsA(NULL, NULL, 1, buffer, cbBuf, NULL, &pcReturned);
1384 /* the NULL is ignored on win9x */
1385 ok( broken(res) || (!res && (GetLastError() == RPC_X_NULL_REF_POINTER)),
1386 "got %u with %u (expected '0' with RPC_X_NULL_REF_POINTER)\n",
1387 res, GetLastError());
1389 pcbNeeded = 0xdeadbeef;
1390 pcReturned = 0xdeadbeef;
1391 SetLastError(0xdeadbeef);
1392 res = EnumPrintProcessorsA(NULL, NULL, 1, buffer, cbBuf, &pcbNeeded, NULL);
1393 /* the NULL is ignored on win9x */
1394 ok( broken(res) || (!res && (GetLastError() == RPC_X_NULL_REF_POINTER)),
1395 "got %u with %u (expected '0' with RPC_X_NULL_REF_POINTER)\n",
1396 res, GetLastError());
1398 HeapFree(GetProcessHeap(), 0, buffer);
1402 /* ########################### */
1404 static void test_GetDefaultPrinter(void)
1406 BOOL retval;
1407 DWORD exact = DEFAULT_PRINTER_SIZE;
1408 DWORD size;
1409 char buffer[DEFAULT_PRINTER_SIZE];
1411 if (!pGetDefaultPrinterA) return;
1412 /* only supported on NT like OSes starting with win2k */
1414 SetLastError(ERROR_SUCCESS);
1415 retval = pGetDefaultPrinterA(buffer, &exact);
1416 if (!retval || !exact || !strlen(buffer) ||
1417 (ERROR_SUCCESS != GetLastError())) {
1418 if ((ERROR_FILE_NOT_FOUND == GetLastError()) ||
1419 (ERROR_INVALID_NAME == GetLastError()))
1420 trace("this test requires a default printer to be set\n");
1421 else {
1422 ok( 0, "function call GetDefaultPrinterA failed unexpected!\n"
1423 "function returned %s\n"
1424 "last error 0x%08x\n"
1425 "returned buffer size 0x%08x\n"
1426 "returned buffer content %s\n",
1427 retval ? "true" : "false", GetLastError(), exact, buffer);
1429 return;
1431 SetLastError(ERROR_SUCCESS);
1432 retval = pGetDefaultPrinterA(NULL, NULL);
1433 ok( !retval, "function result wrong! False expected\n");
1434 ok( ERROR_INVALID_PARAMETER == GetLastError(),
1435 "Last error wrong! ERROR_INVALID_PARAMETER expected, got 0x%08x\n",
1436 GetLastError());
1438 SetLastError(ERROR_SUCCESS);
1439 retval = pGetDefaultPrinterA(buffer, NULL);
1440 ok( !retval, "function result wrong! False expected\n");
1441 ok( ERROR_INVALID_PARAMETER == GetLastError(),
1442 "Last error wrong! ERROR_INVALID_PARAMETER expected, got 0x%08x\n",
1443 GetLastError());
1445 SetLastError(ERROR_SUCCESS);
1446 size = 0;
1447 retval = pGetDefaultPrinterA(NULL, &size);
1448 ok( !retval, "function result wrong! False expected\n");
1449 ok( ERROR_INSUFFICIENT_BUFFER == GetLastError(),
1450 "Last error wrong! ERROR_INSUFFICIENT_BUFFER expected, got 0x%08x\n",
1451 GetLastError());
1452 ok( size == exact, "Parameter size wrong! %d expected got %d\n",
1453 exact, size);
1455 SetLastError(ERROR_SUCCESS);
1456 size = DEFAULT_PRINTER_SIZE;
1457 retval = pGetDefaultPrinterA(NULL, &size);
1458 ok( !retval, "function result wrong! False expected\n");
1459 ok( ERROR_INSUFFICIENT_BUFFER == GetLastError(),
1460 "Last error wrong! ERROR_INSUFFICIENT_BUFFER expected, got 0x%08x\n",
1461 GetLastError());
1462 ok( size == exact, "Parameter size wrong! %d expected got %d\n",
1463 exact, size);
1465 size = 0;
1466 retval = pGetDefaultPrinterA(buffer, &size);
1467 ok( !retval, "function result wrong! False expected\n");
1468 ok( ERROR_INSUFFICIENT_BUFFER == GetLastError(),
1469 "Last error wrong! ERROR_INSUFFICIENT_BUFFER expected, got 0x%08x\n",
1470 GetLastError());
1471 ok( size == exact, "Parameter size wrong! %d expected got %d\n",
1472 exact, size);
1474 size = exact;
1475 retval = pGetDefaultPrinterA(buffer, &size);
1476 ok( retval, "function result wrong! True expected\n");
1477 ok( size == exact, "Parameter size wrong! %d expected got %d\n",
1478 exact, size);
1481 static void test_GetPrinterDriverDirectory(void)
1483 LPBYTE buffer = NULL;
1484 DWORD cbBuf = 0, pcbNeeded = 0;
1485 BOOL res;
1488 SetLastError(MAGIC_DEAD);
1489 res = GetPrinterDriverDirectoryA( NULL, NULL, 1, NULL, 0, &cbBuf);
1490 if (is_spooler_deactivated(res, GetLastError())) return;
1492 trace("first call returned 0x%04x, with %d: buffer size 0x%08x\n",
1493 res, GetLastError(), cbBuf);
1495 ok((res == 0) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1496 "returned %d with lasterror=%d (expected '0' with "
1497 "ERROR_INSUFFICIENT_BUFFER)\n", res, GetLastError());
1499 if (!cbBuf) {
1500 skip("no valid buffer size returned\n");
1501 return;
1504 buffer = HeapAlloc( GetProcessHeap(), 0, cbBuf*2);
1505 if (buffer == NULL) return ;
1507 res = GetPrinterDriverDirectoryA(NULL, NULL, 1, buffer, cbBuf, &pcbNeeded);
1508 ok( res, "expected result != 0, got %d\n", res);
1509 ok( cbBuf == pcbNeeded, "pcbNeeded set to %d instead of %d\n",
1510 pcbNeeded, cbBuf);
1512 res = GetPrinterDriverDirectoryA(NULL, NULL, 1, buffer, cbBuf*2, &pcbNeeded);
1513 ok( res, "expected result != 0, got %d\n", res);
1514 ok( cbBuf == pcbNeeded, "pcbNeeded set to %d instead of %d\n",
1515 pcbNeeded, cbBuf);
1517 SetLastError(MAGIC_DEAD);
1518 res = GetPrinterDriverDirectoryA( NULL, NULL, 1, buffer, cbBuf-1, &pcbNeeded);
1519 ok( !res , "expected result == 0, got %d\n", res);
1520 ok( cbBuf == pcbNeeded, "pcbNeeded set to %d instead of %d\n",
1521 pcbNeeded, cbBuf);
1523 ok( ERROR_INSUFFICIENT_BUFFER == GetLastError(),
1524 "last error set to %d instead of ERROR_INSUFFICIENT_BUFFER\n",
1525 GetLastError());
1528 Do not add the next test:
1529 XPsp2: crash in this app, when the spooler is not running
1530 NT3.5: ERROR_INVALID_USER_BUFFER
1531 win9x: ERROR_INVALID_PARAMETER
1533 pcbNeeded = MAGIC_DEAD;
1534 SetLastError(MAGIC_DEAD);
1535 res = GetPrinterDriverDirectoryA( NULL, NULL, 1, NULL, cbBuf, &pcbNeeded);
1538 SetLastError(MAGIC_DEAD);
1539 res = GetPrinterDriverDirectoryA( NULL, NULL, 1, buffer, cbBuf, NULL);
1540 /* w7 with deactivated spooler: ERROR_INVALID_PARAMETER,
1541 NT: RPC_X_NULL_REF_POINTER */
1542 ok( res || (GetLastError() == RPC_X_NULL_REF_POINTER) ||
1543 (GetLastError() == ERROR_INVALID_PARAMETER),
1544 "returned %d with %d (expected '!=0' or '0' with RPC_X_NULL_REF_POINTER "
1545 "or '0' with ERROR_INVALID_PARAMETER)\n", res, GetLastError());
1547 SetLastError(MAGIC_DEAD);
1548 res = GetPrinterDriverDirectoryA( NULL, NULL, 1, NULL, cbBuf, NULL);
1549 /* w7 with deactivated spooler: ERROR_INVALID_PARAMETER,
1550 NT: RPC_X_NULL_REF_POINTER */
1551 ok( res || (GetLastError() == RPC_X_NULL_REF_POINTER) ||
1552 (GetLastError() == ERROR_INVALID_PARAMETER),
1553 "returned %d with %d (expected '!=0' or '0' with RPC_X_NULL_REF_POINTER "
1554 "or '0' with ERROR_INVALID_PARAMETER)\n", res, GetLastError());
1556 /* with a valid buffer, but level is too large */
1557 buffer[0] = '\0';
1558 SetLastError(MAGIC_DEAD);
1559 res = GetPrinterDriverDirectoryA(NULL, NULL, 2, buffer, cbBuf, &pcbNeeded);
1561 /* Level not checked in win9x and wine:*/
1562 if((res != FALSE) && buffer[0])
1564 trace("Level '2' not checked '%s'\n", buffer);
1566 else
1568 ok( !res && (GetLastError() == ERROR_INVALID_LEVEL),
1569 "returned %d with lasterror=%d (expected '0' with "
1570 "ERROR_INVALID_LEVEL)\n", res, GetLastError());
1573 /* printing environments are case insensitive */
1574 /* "Windows 4.0" is valid for win9x and NT */
1575 buffer[0] = '\0';
1576 SetLastError(MAGIC_DEAD);
1577 res = GetPrinterDriverDirectoryA(NULL, env_win9x_case, 1,
1578 buffer, cbBuf*2, &pcbNeeded);
1580 if(!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
1581 cbBuf = pcbNeeded;
1582 buffer = HeapReAlloc(GetProcessHeap(), 0, buffer, cbBuf*2);
1583 if (buffer == NULL) return ;
1585 SetLastError(MAGIC_DEAD);
1586 res = GetPrinterDriverDirectoryA(NULL, env_win9x_case, 1,
1587 buffer, cbBuf*2, &pcbNeeded);
1590 ok(res && buffer[0], "returned %d with "
1591 "lasterror=%d and len=%d (expected '1' with 'len > 0')\n",
1592 res, GetLastError(), lstrlenA((char *)buffer));
1594 buffer[0] = '\0';
1595 SetLastError(MAGIC_DEAD);
1596 res = GetPrinterDriverDirectoryA(NULL, env_x86, 1,
1597 buffer, cbBuf*2, &pcbNeeded);
1599 if(!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
1600 cbBuf = pcbNeeded;
1601 buffer = HeapReAlloc(GetProcessHeap(), 0, buffer, cbBuf*2);
1602 if (buffer == NULL) return ;
1604 buffer[0] = '\0';
1605 SetLastError(MAGIC_DEAD);
1606 res = GetPrinterDriverDirectoryA(NULL, env_x86, 1,
1607 buffer, cbBuf*2, &pcbNeeded);
1610 /* "Windows NT x86" is invalid for win9x */
1611 ok( (res && buffer[0]) ||
1612 (!res && (GetLastError() == ERROR_INVALID_ENVIRONMENT)),
1613 "returned %d with lasterror=%d and len=%d (expected '!= 0' with "
1614 "'len > 0' or '0' with ERROR_INVALID_ENVIRONMENT)\n",
1615 res, GetLastError(), lstrlenA((char *)buffer));
1617 /* A setup program (PDFCreator_0.8.0) use empty strings */
1618 SetLastError(MAGIC_DEAD);
1619 res = GetPrinterDriverDirectoryA(empty, empty, 1, buffer, cbBuf*2, &pcbNeeded);
1620 ok(res, "returned %d with %d (expected '!=0')\n", res, GetLastError() );
1622 SetLastError(MAGIC_DEAD);
1623 res = GetPrinterDriverDirectoryA(NULL, empty, 1, buffer, cbBuf*2, &pcbNeeded);
1624 ok(res, "returned %d with %d (expected '!=0')\n", res, GetLastError() );
1626 SetLastError(MAGIC_DEAD);
1627 res = GetPrinterDriverDirectoryA(empty, NULL, 1, buffer, cbBuf*2, &pcbNeeded);
1628 ok(res, "returned %d with %d (expected '!=0')\n", res, GetLastError() );
1630 HeapFree( GetProcessHeap(), 0, buffer);
1633 /* ##### */
1635 static void test_GetPrintProcessorDirectory(void)
1637 LPBYTE buffer = NULL;
1638 DWORD cbBuf = 0;
1639 DWORD pcbNeeded = 0;
1640 BOOL res;
1643 SetLastError(0xdeadbeef);
1644 res = GetPrintProcessorDirectoryA(NULL, NULL, 1, NULL, 0, &cbBuf);
1645 if (is_spooler_deactivated(res, GetLastError())) return;
1647 ok( !res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1648 "returned %d with %d (expected '0' with ERROR_INSUFFICIENT_BUFFER)\n",
1649 res, GetLastError());
1651 buffer = HeapAlloc(GetProcessHeap(), 0, cbBuf*2);
1652 if(buffer == NULL) return;
1654 buffer[0] = '\0';
1655 SetLastError(0xdeadbeef);
1656 res = GetPrintProcessorDirectoryA(NULL, NULL, 1, buffer, cbBuf, &pcbNeeded);
1657 ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError());
1659 SetLastError(0xdeadbeef);
1660 buffer[0] = '\0';
1661 res = GetPrintProcessorDirectoryA(NULL, NULL, 1, buffer, cbBuf*2, &pcbNeeded);
1662 ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError());
1664 /* Buffer to small */
1665 buffer[0] = '\0';
1666 SetLastError(0xdeadbeef);
1667 res = GetPrintProcessorDirectoryA( NULL, NULL, 1, buffer, cbBuf-1, &pcbNeeded);
1668 ok( !res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
1669 "returned %d with %d (expected '0' with ERROR_INSUFFICIENT_BUFFER)\n",
1670 res, GetLastError());
1672 if (0)
1674 /* XPsp2: the program will crash here, when the spooler is not running */
1675 /* GetPrinterDriverDirectory has the same bug */
1676 pcbNeeded = 0;
1677 SetLastError(0xdeadbeef);
1678 res = GetPrintProcessorDirectoryA( NULL, NULL, 1, NULL, cbBuf, &pcbNeeded);
1679 /* NT: ERROR_INVALID_USER_BUFFER, 9x: res != 0 */
1680 ok( (!res && (GetLastError() == ERROR_INVALID_USER_BUFFER)) ||
1681 broken(res),
1682 "returned %d with %d (expected '0' with ERROR_INVALID_USER_BUFFER)\n",
1683 res, GetLastError());
1686 buffer[0] = '\0';
1687 SetLastError(0xdeadbeef);
1688 res = GetPrintProcessorDirectoryA( NULL, NULL, 1, buffer, cbBuf, NULL);
1689 /* w7 with deactivated spooler: ERROR_INVALID_PARAMETER,
1690 NT: RPC_X_NULL_REF_POINTER, 9x: res != 0 */
1691 ok( !res && ((GetLastError() == RPC_X_NULL_REF_POINTER) ||
1692 (GetLastError() == ERROR_INVALID_PARAMETER)),
1693 "returned %d with %d (expected '0' with RPC_X_NULL_REF_POINTER "
1694 "or with ERROR_INVALID_PARAMETER)\n", res, GetLastError());
1696 buffer[0] = '\0';
1697 SetLastError(0xdeadbeef);
1698 res = GetPrintProcessorDirectoryA( NULL, NULL, 1, NULL, cbBuf, NULL);
1699 /* w7 with deactivated spooler: ERROR_INVALID_PARAMETER,
1700 NT: RPC_X_NULL_REF_POINTER, 9x: res != 0 */
1701 ok( !res && ((GetLastError() == RPC_X_NULL_REF_POINTER) ||
1702 (GetLastError() == ERROR_INVALID_PARAMETER)),
1703 "returned %d with %d (expected '0' with RPC_X_NULL_REF_POINTER "
1704 "or with ERROR_INVALID_PARAMETER)\n", res, GetLastError());
1706 /* with a valid buffer, but level is invalid */
1707 buffer[0] = '\0';
1708 SetLastError(0xdeadbeef);
1709 res = GetPrintProcessorDirectoryA(NULL, NULL, 0, buffer, cbBuf, &pcbNeeded);
1710 /* Level is ignored in win9x*/
1711 ok( (!res && (GetLastError() == ERROR_INVALID_LEVEL)) ||
1712 broken(res && buffer[0]),
1713 "returned %d with %d (expected '0' with ERROR_INVALID_LEVEL)\n",
1714 res, GetLastError());
1716 buffer[0] = '\0';
1717 SetLastError(0xdeadbeef);
1718 res = GetPrintProcessorDirectoryA(NULL, NULL, 2, buffer, cbBuf, &pcbNeeded);
1719 /* Level is ignored on win9x*/
1720 ok( (!res && (GetLastError() == ERROR_INVALID_LEVEL)) ||
1721 broken(res && buffer[0]),
1722 "returned %d with %d (expected '0' with ERROR_INVALID_LEVEL)\n",
1723 res, GetLastError());
1725 /* Empty environment is the same as the default environment */
1726 buffer[0] = '\0';
1727 SetLastError(0xdeadbeef);
1728 res = GetPrintProcessorDirectoryA(NULL, empty, 1, buffer, cbBuf*2, &pcbNeeded);
1729 ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError());
1731 /* "Windows 4.0" is valid for win9x and NT */
1732 buffer[0] = '\0';
1733 SetLastError(0xdeadbeef);
1734 res = GetPrintProcessorDirectoryA(NULL, env_win9x_case, 1, buffer, cbBuf*2, &pcbNeeded);
1735 ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError());
1738 /* "Windows NT x86" is invalid for win9x */
1739 buffer[0] = '\0';
1740 SetLastError(0xdeadbeef);
1741 res = GetPrintProcessorDirectoryA(NULL, env_x86, 1, buffer, cbBuf*2, &pcbNeeded);
1742 ok( res || (GetLastError() == ERROR_INVALID_ENVIRONMENT),
1743 "returned %d with %d (expected '!= 0' or '0' with "
1744 "ERROR_INVALID_ENVIRONMENT)\n", res, GetLastError());
1746 /* invalid on all systems */
1747 buffer[0] = '\0';
1748 SetLastError(0xdeadbeef);
1749 res = GetPrintProcessorDirectoryA(NULL, invalid_env, 1, buffer, cbBuf*2, &pcbNeeded);
1750 ok( !res && (GetLastError() == ERROR_INVALID_ENVIRONMENT),
1751 "returned %d with %d (expected '0' with ERROR_INVALID_ENVIRONMENT)\n",
1752 res, GetLastError());
1754 /* Empty servername is the same as the local computer */
1755 buffer[0] = '\0';
1756 SetLastError(0xdeadbeef);
1757 res = GetPrintProcessorDirectoryA(empty, NULL, 1, buffer, cbBuf*2, &pcbNeeded);
1758 ok(res, "returned %d with %d (expected '!= 0')\n", res, GetLastError());
1760 /* invalid on all systems */
1761 buffer[0] = '\0';
1762 SetLastError(0xdeadbeef);
1763 res = GetPrintProcessorDirectoryA(server_does_not_exist, NULL, 1, buffer, cbBuf*2, &pcbNeeded);
1764 ok( !res, "expected failure\n");
1765 ok( GetLastError() == RPC_S_SERVER_UNAVAILABLE || /* NT */
1766 GetLastError() == ERROR_INVALID_PARAMETER || /* 9x */
1767 GetLastError() == RPC_S_INVALID_NET_ADDR, /* Some Vista */
1768 "unexpected last error %d\n", GetLastError());
1770 HeapFree(GetProcessHeap(), 0, buffer);
1773 /* ##### */
1775 static void test_OpenPrinter(void)
1777 PRINTER_DEFAULTSA defaults;
1778 HANDLE hprinter;
1779 DWORD res;
1781 SetLastError(MAGIC_DEAD);
1782 res = OpenPrinter(NULL, NULL, NULL);
1783 if (is_spooler_deactivated(res, GetLastError())) return;
1785 ok(!res && (GetLastError() == ERROR_INVALID_PARAMETER),
1786 "returned %d with %d (expected '0' with ERROR_INVALID_PARAMETER)\n",
1787 res, GetLastError());
1790 /* Get Handle for the local Printserver (NT only)*/
1791 hprinter = (HANDLE) MAGIC_DEAD;
1792 SetLastError(MAGIC_DEAD);
1793 res = OpenPrinter(NULL, &hprinter, NULL);
1794 if (is_spooler_deactivated(res, GetLastError())) return;
1795 ok(res || (!res && GetLastError() == ERROR_INVALID_PARAMETER),
1796 "returned %d with %d (expected '!=0' or '0' with ERROR_INVALID_PARAMETER)\n",
1797 res, GetLastError());
1798 if(res) {
1799 ClosePrinter(hprinter);
1801 defaults.pDatatype=NULL;
1802 defaults.pDevMode=NULL;
1804 defaults.DesiredAccess=0;
1805 hprinter = (HANDLE) MAGIC_DEAD;
1806 SetLastError(MAGIC_DEAD);
1807 res = OpenPrinter(NULL, &hprinter, &defaults);
1808 ok(res, "returned %d with %d (expected '!=0')\n", res, GetLastError());
1809 if (res) ClosePrinter(hprinter);
1811 defaults.DesiredAccess=-1;
1812 hprinter = (HANDLE) MAGIC_DEAD;
1813 SetLastError(MAGIC_DEAD);
1814 res = OpenPrinter(NULL, &hprinter, &defaults);
1815 todo_wine {
1816 ok(!res && GetLastError() == ERROR_ACCESS_DENIED,
1817 "returned %d with %d (expected '0' with ERROR_ACCESS_DENIED)\n",
1818 res, GetLastError());
1820 if (res) ClosePrinter(hprinter);
1825 if (local_server != NULL) {
1826 hprinter = (HANDLE) 0xdeadbeef;
1827 SetLastError(0xdeadbeef);
1828 res = OpenPrinter(local_server, &hprinter, NULL);
1829 ok(res || (!res && GetLastError() == ERROR_INVALID_PARAMETER),
1830 "returned %d with %d (expected '!=0' or '0' with ERROR_INVALID_PARAMETER)\n",
1831 res, GetLastError());
1832 if(res) ClosePrinter(hprinter);
1835 /* Invalid Printername */
1836 hprinter = (HANDLE) MAGIC_DEAD;
1837 SetLastError(MAGIC_DEAD);
1838 res = OpenPrinter(illegal_name, &hprinter, NULL);
1839 ok(!res && ((GetLastError() == ERROR_INVALID_PRINTER_NAME) ||
1840 (GetLastError() == ERROR_INVALID_PARAMETER) ),
1841 "returned %d with %d (expected '0' with: ERROR_INVALID_PARAMETER or"
1842 "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
1843 if(res) ClosePrinter(hprinter);
1845 hprinter = (HANDLE) MAGIC_DEAD;
1846 SetLastError(MAGIC_DEAD);
1847 res = OpenPrinter(empty, &hprinter, NULL);
1848 /* NT: ERROR_INVALID_PRINTER_NAME, 9x: ERROR_INVALID_PARAMETER */
1849 ok( !res &&
1850 ((GetLastError() == ERROR_INVALID_PRINTER_NAME) ||
1851 (GetLastError() == ERROR_INVALID_PARAMETER) ),
1852 "returned %d with %d (expected '0' with: ERROR_INVALID_PRINTER_NAME"
1853 " or ERROR_INVALID_PARAMETER)\n", res, GetLastError());
1854 if(res) ClosePrinter(hprinter);
1857 /* get handle for the default printer */
1858 if (default_printer)
1860 hprinter = (HANDLE) MAGIC_DEAD;
1861 SetLastError(MAGIC_DEAD);
1862 res = OpenPrinter(default_printer, &hprinter, NULL);
1863 if((!res) && (GetLastError() == RPC_S_SERVER_UNAVAILABLE))
1865 trace("The service 'Spooler' is required for '%s'\n", default_printer);
1866 return;
1868 ok(res, "returned %d with %d (expected '!=0')\n", res, GetLastError());
1869 if(res) ClosePrinter(hprinter);
1871 SetLastError(MAGIC_DEAD);
1872 res = OpenPrinter(default_printer, NULL, NULL);
1873 /* NT: FALSE with ERROR_INVALID_PARAMETER, 9x: TRUE */
1874 ok(res || (GetLastError() == ERROR_INVALID_PARAMETER),
1875 "returned %d with %d (expected '!=0' or '0' with "
1876 "ERROR_INVALID_PARAMETER)\n", res, GetLastError());
1878 defaults.pDatatype=NULL;
1879 defaults.pDevMode=NULL;
1880 defaults.DesiredAccess=0;
1882 hprinter = (HANDLE) MAGIC_DEAD;
1883 SetLastError(MAGIC_DEAD);
1884 res = OpenPrinter(default_printer, &hprinter, &defaults);
1885 ok(res || GetLastError() == ERROR_ACCESS_DENIED,
1886 "returned %d with %d (expected '!=0' or '0' with "
1887 "ERROR_ACCESS_DENIED)\n", res, GetLastError());
1888 if(res) ClosePrinter(hprinter);
1890 defaults.pDatatype = empty;
1892 hprinter = (HANDLE) MAGIC_DEAD;
1893 SetLastError(MAGIC_DEAD);
1894 res = OpenPrinter(default_printer, &hprinter, &defaults);
1895 /* stop here, when a remote Printserver has no RPC-Service running */
1896 if (is_spooler_deactivated(res, GetLastError())) return;
1897 ok(res || ((GetLastError() == ERROR_INVALID_DATATYPE) ||
1898 (GetLastError() == ERROR_ACCESS_DENIED)),
1899 "returned %d with %d (expected '!=0' or '0' with: "
1900 "ERROR_INVALID_DATATYPE or ERROR_ACCESS_DENIED)\n",
1901 res, GetLastError());
1902 if(res) ClosePrinter(hprinter);
1905 defaults.pDatatype=NULL;
1906 defaults.DesiredAccess=PRINTER_ACCESS_USE;
1908 hprinter = (HANDLE) MAGIC_DEAD;
1909 SetLastError(MAGIC_DEAD);
1910 res = OpenPrinter(default_printer, &hprinter, &defaults);
1911 ok(res || GetLastError() == ERROR_ACCESS_DENIED,
1912 "returned %d with %d (expected '!=0' or '0' with "
1913 "ERROR_ACCESS_DENIED)\n", res, GetLastError());
1914 if(res) ClosePrinter(hprinter);
1917 defaults.DesiredAccess=PRINTER_ALL_ACCESS;
1918 hprinter = (HANDLE) MAGIC_DEAD;
1919 SetLastError(MAGIC_DEAD);
1920 res = OpenPrinter(default_printer, &hprinter, &defaults);
1921 ok(res || GetLastError() == ERROR_ACCESS_DENIED,
1922 "returned %d with %d (expected '!=0' or '0' with "
1923 "ERROR_ACCESS_DENIED)\n", res, GetLastError());
1924 if(res) ClosePrinter(hprinter);
1930 static void test_SetDefaultPrinter(void)
1932 DWORD res;
1933 DWORD size = DEFAULT_PRINTER_SIZE;
1934 CHAR buffer[DEFAULT_PRINTER_SIZE];
1935 CHAR org_value[DEFAULT_PRINTER_SIZE];
1937 if (!default_printer)
1939 skip("There is no default printer installed\n");
1940 return;
1943 if (!pSetDefaultPrinterA) return;
1944 /* only supported on win2k and above */
1946 /* backup the original value */
1947 org_value[0] = '\0';
1948 SetLastError(MAGIC_DEAD);
1949 res = GetProfileStringA("windows", "device", NULL, org_value, size);
1950 ok(res, "GetProfileString error %d\n", GetLastError());
1952 /* first part: with the default Printer */
1953 SetLastError(MAGIC_DEAD);
1954 res = pSetDefaultPrinterA("no_printer_with_this_name");
1955 if (is_spooler_deactivated(res, GetLastError())) return;
1957 /* Not implemented in wine */
1958 if (!res && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) {
1959 trace("SetDefaultPrinterA() not implemented yet.\n");
1960 return;
1963 ok(!res && (GetLastError() == ERROR_INVALID_PRINTER_NAME),
1964 "returned %d with %d (expected '0' with "
1965 "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
1967 WriteProfileStringA("windows", "device", org_value);
1968 SetLastError(MAGIC_DEAD);
1969 res = pSetDefaultPrinterA("");
1970 ok(res || (!res && (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
1971 "returned %d with %d (expected '!=0' or '0' with "
1972 "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
1974 WriteProfileStringA("windows", "device", org_value);
1975 SetLastError(MAGIC_DEAD);
1976 res = pSetDefaultPrinterA(NULL);
1977 ok(res || (!res && (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
1978 "returned %d with %d (expected '!=0' or '0' with "
1979 "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
1981 WriteProfileStringA("windows", "device", org_value);
1982 SetLastError(MAGIC_DEAD);
1983 res = pSetDefaultPrinterA(default_printer);
1984 ok(res || (!res && (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
1985 "returned %d with %d (expected '!=0' or '0' with "
1986 "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
1989 /* second part: always without a default Printer */
1990 WriteProfileStringA("windows", "device", NULL);
1991 SetLastError(MAGIC_DEAD);
1992 res = pSetDefaultPrinterA("no_printer_with_this_name");
1994 ok(!res && (GetLastError() == ERROR_INVALID_PRINTER_NAME),
1995 "returned %d with %d (expected '0' with "
1996 "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
1998 WriteProfileStringA("windows", "device", NULL);
1999 SetLastError(MAGIC_DEAD);
2000 res = pSetDefaultPrinterA("");
2001 if (is_spooler_deactivated(res, GetLastError()))
2002 goto restore_old_printer;
2004 /* we get ERROR_INVALID_PRINTER_NAME when no printer is installed */
2005 ok(res || (!res && (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
2006 "returned %d with %d (expected '!=0' or '0' with "
2007 "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
2009 WriteProfileStringA("windows", "device", NULL);
2010 SetLastError(MAGIC_DEAD);
2011 res = pSetDefaultPrinterA(NULL);
2012 /* we get ERROR_INVALID_PRINTER_NAME when no printer is installed */
2013 ok(res || (!res && (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
2014 "returned %d with %d (expected '!=0' or '0' with "
2015 "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
2017 WriteProfileStringA("windows", "device", NULL);
2018 SetLastError(MAGIC_DEAD);
2019 res = pSetDefaultPrinterA(default_printer);
2020 ok(res || (!res && (GetLastError() == ERROR_INVALID_PRINTER_NAME)),
2021 "returned %d with %d (expected '!=0' or '0' with "
2022 "ERROR_INVALID_PRINTER_NAME)\n", res, GetLastError());
2024 /* restore the original value */
2025 restore_old_printer:
2026 res = pSetDefaultPrinterA(default_printer); /* the nice way */
2027 ok(res, "SetDefaultPrinter error %d\n", GetLastError());
2028 WriteProfileStringA("windows", "device", org_value); /* the old way */
2030 buffer[0] = '\0';
2031 SetLastError(MAGIC_DEAD);
2032 res = GetProfileStringA("windows", "device", NULL, buffer, size);
2033 ok(res, "GetProfileString error %d\n", GetLastError());
2034 ok(!lstrcmpA(org_value, buffer), "'%s' (expected '%s')\n", buffer, org_value);
2038 /* ########################### */
2040 static void test_XcvDataW_MonitorUI(void)
2042 DWORD res;
2043 HANDLE hXcv;
2044 BYTE buffer[MAX_PATH + 4];
2045 DWORD needed;
2046 DWORD status;
2047 DWORD len;
2048 PRINTER_DEFAULTSA pd;
2050 /* api is not present before w2k */
2051 if (pXcvDataW == NULL) return;
2053 pd.pDatatype = NULL;
2054 pd.pDevMode = NULL;
2055 pd.DesiredAccess = SERVER_ACCESS_ADMINISTER;
2057 hXcv = NULL;
2058 SetLastError(0xdeadbeef);
2059 res = OpenPrinter(xcv_localport, &hXcv, &pd);
2060 if (is_spooler_deactivated(res, GetLastError())) return;
2061 if (is_access_denied(res, GetLastError())) return;
2063 ok(res, "returned %d with %u and handle %p (expected '!= 0')\n", res, GetLastError(), hXcv);
2064 if (!res) return;
2066 /* ask for needed size */
2067 needed = (DWORD) 0xdeadbeef;
2068 status = (DWORD) 0xdeadbeef;
2069 SetLastError(0xdeadbeef);
2070 res = pXcvDataW(hXcv, cmd_MonitorUIW, NULL, 0, NULL, 0, &needed, &status);
2071 ok( res && (status == ERROR_INSUFFICIENT_BUFFER) && (needed <= MAX_PATH),
2072 "returned %d with %u and %u for status %u (expected '!= 0' and "
2073 "'<= MAX_PATH' for status ERROR_INSUFFICIENT_BUFFER)\n",
2074 res, GetLastError(), needed, status);
2076 if (needed > MAX_PATH) {
2077 ClosePrinter(hXcv);
2078 skip("buffer overflow (%u)\n", needed);
2079 return;
2081 len = needed; /* Size is in bytes */
2083 /* the command is required */
2084 needed = (DWORD) 0xdeadbeef;
2085 status = (DWORD) 0xdeadbeef;
2086 SetLastError(0xdeadbeef);
2087 res = pXcvDataW(hXcv, emptyW, NULL, 0, NULL, 0, &needed, &status);
2088 ok( res && (status == ERROR_INVALID_PARAMETER),
2089 "returned %d with %u and %u for status %u (expected '!= 0' with "
2090 "ERROR_INVALID_PARAMETER)\n", res, GetLastError(), needed, status);
2092 needed = (DWORD) 0xdeadbeef;
2093 status = (DWORD) 0xdeadbeef;
2094 SetLastError(0xdeadbeef);
2095 res = pXcvDataW(hXcv, NULL, NULL, 0, buffer, MAX_PATH, &needed, &status);
2096 ok( !res && (GetLastError() == RPC_X_NULL_REF_POINTER),
2097 "returned %d with %u and %u for status %u (expected '0' with "
2098 "RPC_X_NULL_REF_POINTER)\n", res, GetLastError(), needed, status);
2100 /* "PDWORD needed" is checked before RPC-Errors */
2101 needed = (DWORD) 0xdeadbeef;
2102 status = (DWORD) 0xdeadbeef;
2103 SetLastError(0xdeadbeef);
2104 res = pXcvDataW(hXcv, cmd_MonitorUIW, NULL, 0, buffer, len, NULL, &status);
2105 ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
2106 "returned %d with %u and %u for status %u (expected '0' with "
2107 "ERROR_INVALID_PARAMETER)\n", res, GetLastError(), needed, status);
2109 needed = (DWORD) 0xdeadbeef;
2110 status = (DWORD) 0xdeadbeef;
2111 SetLastError(0xdeadbeef);
2112 res = pXcvDataW(hXcv, cmd_MonitorUIW, NULL, 0, NULL, len, &needed, &status);
2113 ok( !res && (GetLastError() == RPC_X_NULL_REF_POINTER),
2114 "returned %d with %u and %u for status %u (expected '0' with "
2115 "RPC_X_NULL_REF_POINTER)\n", res, GetLastError(), needed, status);
2117 needed = (DWORD) 0xdeadbeef;
2118 status = (DWORD) 0xdeadbeef;
2119 SetLastError(0xdeadbeef);
2120 res = pXcvDataW(hXcv, cmd_MonitorUIW, NULL, 0, buffer, len, &needed, NULL);
2121 ok( !res && (GetLastError() == RPC_X_NULL_REF_POINTER),
2122 "returned %d with %u and %u for status %u (expected '0' with "
2123 "RPC_X_NULL_REF_POINTER)\n", res, GetLastError(), needed, status);
2125 /* off by one: larger */
2126 needed = (DWORD) 0xdeadbeef;
2127 status = (DWORD) 0xdeadbeef;
2128 SetLastError(0xdeadbeef);
2129 res = pXcvDataW(hXcv, cmd_MonitorUIW, NULL, 0, buffer, len+1, &needed, &status);
2130 ok( res && (status == ERROR_SUCCESS),
2131 "returned %d with %u and %u for status %u (expected '!= 0' for status "
2132 "ERROR_SUCCESS)\n", res, GetLastError(), needed, status);
2134 /* off by one: smaller */
2135 /* the buffer is not modified for NT4, w2k, XP */
2136 needed = (DWORD) 0xdeadbeef;
2137 status = (DWORD) 0xdeadbeef;
2138 SetLastError(0xdeadbeef);
2139 res = pXcvDataW(hXcv, cmd_MonitorUIW, NULL, 0, buffer, len-1, &needed, &status);
2140 ok( res && (status == ERROR_INSUFFICIENT_BUFFER),
2141 "returned %d with %u and %u for status %u (expected '!= 0' for status "
2142 "ERROR_INSUFFICIENT_BUFFER)\n", res, GetLastError(), needed, status);
2145 /* Normal use. The DLL-Name without a Path is returned */
2146 memset(buffer, 0, len);
2147 needed = (DWORD) 0xdeadbeef;
2148 status = (DWORD) 0xdeadbeef;
2149 SetLastError(0xdeadbeef);
2150 res = pXcvDataW(hXcv, cmd_MonitorUIW, NULL, 0, buffer, len, &needed, &status);
2151 ok( res && (status == ERROR_SUCCESS),
2152 "returned %d with %u and %u for status %u (expected '!= 0' for status "
2153 "ERROR_SUCCESS)\n", res, GetLastError(), needed, status);
2155 ClosePrinter(hXcv);
2158 /* ########################### */
2160 static void test_XcvDataW_PortIsValid(void)
2162 DWORD res;
2163 HANDLE hXcv;
2164 DWORD needed;
2165 DWORD status;
2166 PRINTER_DEFAULTSA pd;
2168 /* api is not present before w2k */
2169 if (pXcvDataW == NULL) return;
2171 pd.pDatatype = NULL;
2172 pd.pDevMode = NULL;
2173 pd.DesiredAccess = SERVER_ACCESS_ADMINISTER;
2175 hXcv = NULL;
2176 SetLastError(0xdeadbeef);
2177 res = OpenPrinter(xcv_localport, &hXcv, &pd);
2178 if (is_spooler_deactivated(res, GetLastError())) return;
2179 if (is_access_denied(res, GetLastError())) return;
2181 ok(res, "returned %d with %u and handle %p (expected '!= 0')\n", res, GetLastError(), hXcv);
2182 if (!res) return;
2185 /* "PDWORD needed" is always required */
2186 needed = (DWORD) 0xdeadbeef;
2187 status = (DWORD) 0xdeadbeef;
2188 SetLastError(0xdeadbeef);
2189 res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) portname_lpt1W, sizeof(portname_lpt1W), NULL, 0, NULL, &status);
2190 ok( !res && (GetLastError() == ERROR_INVALID_PARAMETER),
2191 "returned %d with %u and %u for status %u (expected '!= 0' with ERROR_INVALID_PARAMETER)\n",
2192 res, GetLastError(), needed, status);
2194 /* an empty name is not allowed */
2195 needed = (DWORD) 0xdeadbeef;
2196 status = (DWORD) 0xdeadbeef;
2197 SetLastError(0xdeadbeef);
2198 res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) emptyW, sizeof(emptyW), NULL, 0, &needed, &status);
2199 ok( res && ((status == ERROR_FILE_NOT_FOUND) || (status == ERROR_PATH_NOT_FOUND)),
2200 "returned %d with %u and %u for status %u (expected '!= 0' for status: "
2201 "ERROR_FILE_NOT_FOUND or ERROR_PATH_NOT_FOUND)\n",
2202 res, GetLastError(), needed, status);
2204 /* a directory is not allowed */
2205 needed = (DWORD) 0xdeadbeef;
2206 status = (DWORD) 0xdeadbeef;
2207 SetLastError(0xdeadbeef);
2208 res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) tempdirW, (lstrlenW(tempdirW) + 1) * sizeof(WCHAR), NULL, 0, &needed, &status);
2209 /* XP: ERROR_PATH_NOT_FOUND, w2k ERROR_ACCESS_DENIED */
2210 ok( res && ((status == ERROR_PATH_NOT_FOUND) || (status == ERROR_ACCESS_DENIED)),
2211 "returned %d with %u and %u for status %u (expected '!= 0' for status: "
2212 "ERROR_PATH_NOT_FOUND or ERROR_ACCESS_DENIED)\n",
2213 res, GetLastError(), needed, status);
2215 /* more valid well known ports */
2216 needed = (DWORD) 0xdeadbeef;
2217 status = (DWORD) 0xdeadbeef;
2218 SetLastError(0xdeadbeef);
2219 res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) portname_lpt1W, sizeof(portname_lpt1W), NULL, 0, &needed, &status);
2220 ok( res && (status == ERROR_SUCCESS),
2221 "returned %d with %u and %u for status %u (expected '!= 0' for ERROR_SUCCESS)\n",
2222 res, GetLastError(), needed, status);
2224 needed = (DWORD) 0xdeadbeef;
2225 status = (DWORD) 0xdeadbeef;
2226 SetLastError(0xdeadbeef);
2227 res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) portname_lpt2W, sizeof(portname_lpt2W), NULL, 0, &needed, &status);
2228 ok( res && (status == ERROR_SUCCESS),
2229 "returned %d with %u and %u for status %u (expected '!= 0' for ERROR_SUCCESS)\n",
2230 res, GetLastError(), needed, status);
2232 needed = (DWORD) 0xdeadbeef;
2233 status = (DWORD) 0xdeadbeef;
2234 SetLastError(0xdeadbeef);
2235 res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) portname_com1W, sizeof(portname_com1W), NULL, 0, &needed, &status);
2236 ok( res && (status == ERROR_SUCCESS),
2237 "returned %d with %u and %u for status %u (expected '!= 0' for ERROR_SUCCESS)\n",
2238 res, GetLastError(), needed, status);
2240 needed = (DWORD) 0xdeadbeef;
2241 status = (DWORD) 0xdeadbeef;
2242 SetLastError(0xdeadbeef);
2243 res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) portname_com2W, sizeof(portname_com2W), NULL, 0, &needed, &status);
2244 ok( res && (status == ERROR_SUCCESS),
2245 "returned %d with %u and %u for status %u (expected '!= 0' for ERROR_SUCCESS)\n",
2246 res, GetLastError(), needed, status);
2248 needed = (DWORD) 0xdeadbeef;
2249 status = (DWORD) 0xdeadbeef;
2250 SetLastError(0xdeadbeef);
2251 res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) portname_fileW, sizeof(portname_fileW), NULL, 0, &needed, &status);
2252 ok( res && (status == ERROR_SUCCESS),
2253 "returned %d with %u and %u for status %u (expected '!= 0' with ERROR_SUCCESS)\n",
2254 res, GetLastError(), needed, status);
2257 /* a normal, writable file is allowed */
2258 needed = (DWORD) 0xdeadbeef;
2259 status = (DWORD) 0xdeadbeef;
2260 SetLastError(0xdeadbeef);
2261 res = pXcvDataW(hXcv, cmd_PortIsValidW, (PBYTE) tempfileW, (lstrlenW(tempfileW) + 1) * sizeof(WCHAR), NULL, 0, &needed, &status);
2262 ok( res && (status == ERROR_SUCCESS),
2263 "returned %d with %u and %u for status %u (expected '!= 0' with ERROR_SUCCESS)\n",
2264 res, GetLastError(), needed, status);
2266 ClosePrinter(hXcv);
2269 /* ########################### */
2271 static void test_GetPrinter(void)
2273 HANDLE hprn;
2274 BOOL ret;
2275 BYTE *buf;
2276 INT level;
2277 DWORD needed, filled;
2279 if (!default_printer)
2281 skip("There is no default printer installed\n");
2282 return;
2285 hprn = 0;
2286 ret = OpenPrinter(default_printer, &hprn, NULL);
2287 if (!ret)
2289 skip("Unable to open the default printer (%s)\n", default_printer);
2290 return;
2292 ok(hprn != 0, "wrong hprn %p\n", hprn);
2294 for (level = 1; level <= 9; level++)
2296 SetLastError(0xdeadbeef);
2297 needed = (DWORD)-1;
2298 ret = GetPrinter(hprn, level, NULL, 0, &needed);
2299 if (ret)
2301 win_skip("Level %d is not supported on Win9x/WinMe\n", level);
2302 ok(GetLastError() == ERROR_SUCCESS, "wrong error %d\n", GetLastError());
2303 ok(needed == 0,"Expected 0, got %d\n", needed);
2304 continue;
2306 ok(!ret, "level %d: GetPrinter should fail\n", level);
2307 /* Not all levels are supported on all Windows-Versions */
2308 if (GetLastError() == ERROR_INVALID_LEVEL ||
2309 GetLastError() == ERROR_NOT_SUPPORTED /* Win9x/WinMe */)
2311 skip("Level %d not supported\n", level);
2312 continue;
2314 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "wrong error %d\n", GetLastError());
2315 ok(needed > 0,"not expected needed buffer size %d\n", needed);
2317 /* GetPrinterA returns the same number of bytes as GetPrinterW */
2318 if (!on_win9x && !ret && pGetPrinterW && level != 6 && level != 7)
2320 DWORD double_needed;
2321 ret = pGetPrinterW(hprn, level, NULL, 0, &double_needed);
2322 ok(!ret, "level %d: GetPrinter error %d\n", level, GetLastError());
2323 ok(double_needed == needed, "level %d: GetPrinterA returned different size %d than GetPrinterW (%d)\n", level, needed, double_needed);
2326 buf = HeapAlloc(GetProcessHeap(), 0, needed);
2328 SetLastError(0xdeadbeef);
2329 filled = -1;
2330 ret = GetPrinter(hprn, level, buf, needed, &filled);
2331 ok(ret, "level %d: GetPrinter error %d\n", level, GetLastError());
2332 ok(needed == filled, "needed %d != filled %d\n", needed, filled);
2334 if (level == 2)
2336 PRINTER_INFO_2 *pi_2 = (PRINTER_INFO_2 *)buf;
2338 ok(pi_2->pPrinterName!= NULL, "not expected NULL ptr\n");
2339 ok(pi_2->pDriverName!= NULL, "not expected NULL ptr\n");
2341 trace("pPrinterName %s\n", pi_2->pPrinterName);
2342 trace("pDriverName %s\n", pi_2->pDriverName);
2345 HeapFree(GetProcessHeap(), 0, buf);
2348 SetLastError(0xdeadbeef);
2349 ret = ClosePrinter(hprn);
2350 ok(ret, "ClosePrinter error %d\n", GetLastError());
2353 /* ########################### */
2355 static void test_GetPrinterData(void)
2357 HANDLE hprn = 0;
2358 DWORD res;
2359 DWORD type;
2360 CHAR buffer[MAX_PATH + 1];
2361 DWORD needed;
2362 DWORD len;
2364 /* ToDo: test parameter validation, test with the default printer */
2366 SetLastError(0xdeadbeef);
2367 res = OpenPrinter(NULL, &hprn, NULL);
2368 if (!res)
2370 /* printserver not available on win9x */
2371 if (!on_win9x)
2372 win_skip("Unable to open the printserver: %d\n", GetLastError());
2373 return;
2376 memset(buffer, '#', sizeof(buffer));
2377 buffer[MAX_PATH] = 0;
2378 type = 0xdeadbeef;
2379 needed = 0xdeadbeef;
2380 SetLastError(0xdeadbeef);
2381 res = GetPrinterDataA(hprn, defaultspooldirectory, &type, (LPBYTE) buffer, sizeof(buffer), &needed);
2383 len = lstrlenA(buffer) + sizeof(CHAR);
2384 /* NT4 and w2k require a buffer to save the UNICODE result also for the ANSI function */
2385 ok( !res && (type == REG_SZ) && ((needed == len) || (needed == (len * sizeof(WCHAR)))),
2386 "got %d, type %d, needed: %d and '%s' (expected ERROR_SUCCESS, REG_SZ and %d)\n",
2387 res, type, needed, buffer, len);
2389 needed = 0xdeadbeef;
2390 SetLastError(0xdeadbeef);
2391 res = GetPrinterDataA(hprn, defaultspooldirectory, NULL, NULL, 0, &needed);
2392 ok( (res == ERROR_MORE_DATA) && ((needed == len) || (needed == (len * sizeof(WCHAR)))),
2393 "got %d, needed: %d (expected ERROR_MORE_DATA and %d)\n", res, needed, len);
2395 /* ToDo: test SPLREG_* */
2397 SetLastError(0xdeadbeef);
2398 res = ClosePrinter(hprn);
2399 ok(res, "ClosePrinter error %d\n", GetLastError());
2402 /* ########################### */
2404 static void test_GetPrinterDataEx(void)
2406 HANDLE hprn = 0;
2407 DWORD res;
2408 DWORD type;
2409 CHAR buffer[MAX_PATH + 1];
2410 DWORD needed;
2411 DWORD len;
2413 /* not present before w2k */
2414 if (!pGetPrinterDataExA) {
2415 win_skip("GetPrinterDataEx not found\n");
2416 return;
2419 /* ToDo: test parameter validation, test with the default printer */
2421 SetLastError(0xdeadbeef);
2422 res = OpenPrinter(NULL, &hprn, NULL);
2423 if (!res)
2425 win_skip("Unable to open the printserver: %d\n", GetLastError());
2426 return;
2429 /* keyname is ignored, when hprn is a HANDLE for a printserver */
2430 memset(buffer, '#', sizeof(buffer));
2431 buffer[MAX_PATH] = 0;
2432 type = 0xdeadbeef;
2433 needed = 0xdeadbeef;
2434 SetLastError(0xdeadbeef);
2435 res = pGetPrinterDataExA(hprn, NULL, defaultspooldirectory, &type,
2436 (LPBYTE) buffer, sizeof(buffer), &needed);
2438 len = lstrlenA(buffer) + sizeof(CHAR);
2439 /* NT4 and w2k require a buffer to save the UNICODE result also for the ANSI function */
2440 ok( !res && (type == REG_SZ) && ((needed == len) || (needed == (len * sizeof(WCHAR)))),
2441 "got %d, type %d, needed: %d and '%s' (expected ERROR_SUCCESS, REG_SZ and %d)\n",
2442 res, type, needed, buffer, len);
2444 memset(buffer, '#', sizeof(buffer));
2445 buffer[MAX_PATH] = 0;
2446 type = 0xdeadbeef;
2447 needed = 0xdeadbeef;
2448 SetLastError(0xdeadbeef);
2449 res = pGetPrinterDataExA(hprn, "", defaultspooldirectory, &type,
2450 (LPBYTE) buffer, sizeof(buffer), &needed);
2451 len = lstrlenA(buffer) + sizeof(CHAR);
2452 ok( !res && (type == REG_SZ) && ((needed == len) || (needed == (len * sizeof(WCHAR)))),
2453 "got %d, type %d, needed: %d and '%s' (expected ERROR_SUCCESS, REG_SZ and %d)\n",
2454 res, type, needed, buffer, len);
2456 memset(buffer, '#', sizeof(buffer));
2457 buffer[MAX_PATH] = 0;
2458 type = 0xdeadbeef;
2459 needed = 0xdeadbeef;
2460 SetLastError(0xdeadbeef);
2461 /* Wine uses GetPrinterDataEx with "PrinterDriverData" to implement GetPrinterData */
2462 res = pGetPrinterDataExA(hprn, "PrinterDriverData", defaultspooldirectory,
2463 &type, (LPBYTE) buffer, sizeof(buffer), &needed);
2464 len = lstrlenA(buffer) + sizeof(CHAR);
2465 ok( !res && (type == REG_SZ) && ((needed == len) || (needed == (len * sizeof(WCHAR)))),
2466 "got %d, type %d, needed: %d and '%s' (expected ERROR_SUCCESS, REG_SZ and %d)\n",
2467 res, type, needed, buffer, len);
2470 memset(buffer, '#', sizeof(buffer));
2471 buffer[MAX_PATH] = 0;
2472 type = 0xdeadbeef;
2473 needed = 0xdeadbeef;
2474 SetLastError(0xdeadbeef);
2475 res = pGetPrinterDataExA(hprn, does_not_exist, defaultspooldirectory, &type,
2476 (LPBYTE) buffer, sizeof(buffer), &needed);
2477 len = lstrlenA(buffer) + sizeof(CHAR);
2478 ok( !res && (type == REG_SZ) && ((needed == len) || (needed == (len * sizeof(WCHAR)))),
2479 "got %d, type %d, needed: %d and '%s' (expected ERROR_SUCCESS, REG_SZ and %d)\n",
2480 res, type, needed, buffer, len);
2482 needed = 0xdeadbeef;
2483 SetLastError(0xdeadbeef);
2484 /* vista and w2k8 have a bug in GetPrinterDataEx:
2485 the current LastError value is returned as result */
2486 res = pGetPrinterDataExA(hprn, NULL, defaultspooldirectory, NULL, NULL, 0, &needed);
2487 ok( ((res == ERROR_MORE_DATA) || broken(res == 0xdeadbeef)) &&
2488 ((needed == len) || (needed == (len * sizeof(WCHAR)))),
2489 "got %d, needed: %d (expected ERROR_MORE_DATA and %d)\n", res, needed, len);
2491 needed = 0xdeadbeef;
2492 SetLastError(0xdeaddead);
2493 res = pGetPrinterDataExA(hprn, NULL, defaultspooldirectory, NULL, NULL, 0, &needed);
2494 ok( ((res == ERROR_MORE_DATA) || broken(res == 0xdeaddead)) &&
2495 ((needed == len) || (needed == (len * sizeof(WCHAR)))),
2496 "got %d, needed: %d (expected ERROR_MORE_DATA and %d)\n", res, needed, len);
2498 SetLastError(0xdeadbeef);
2499 res = ClosePrinter(hprn);
2500 ok(res, "ClosePrinter error %d\n", GetLastError());
2503 /* ########################### */
2505 static void test_GetPrinterDriver(void)
2507 HANDLE hprn;
2508 BOOL ret;
2509 BYTE *buf;
2510 INT level;
2511 DWORD needed, filled;
2513 if (!default_printer)
2515 skip("There is no default printer installed\n");
2516 return;
2519 hprn = 0;
2520 ret = OpenPrinter(default_printer, &hprn, NULL);
2521 if (!ret)
2523 skip("Unable to open the default printer (%s)\n", default_printer);
2524 return;
2526 ok(hprn != 0, "wrong hprn %p\n", hprn);
2528 for (level = -1; level <= 7; level++)
2530 SetLastError(0xdeadbeef);
2531 needed = (DWORD)-1;
2532 ret = GetPrinterDriver(hprn, NULL, level, NULL, 0, &needed);
2533 ok(!ret, "level %d: GetPrinterDriver should fail\n", level);
2534 if (level >= 1 && level <= 6)
2536 /* Not all levels are supported on all Windows-Versions */
2537 if(GetLastError() == ERROR_INVALID_LEVEL) continue;
2538 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "wrong error %d\n", GetLastError());
2539 ok(needed > 0,"not expected needed buffer size %d\n", needed);
2541 else
2543 /* ERROR_OUTOFMEMORY found on win9x */
2544 ok( ((GetLastError() == ERROR_INVALID_LEVEL) ||
2545 (GetLastError() == ERROR_OUTOFMEMORY)),
2546 "%d: returned %d with %d (expected '0' with: "
2547 "ERROR_INVALID_LEVEL or ERROR_OUTOFMEMORY)\n",
2548 level, ret, GetLastError());
2549 /* needed is modified in win9x. The modified Value depends on the
2550 default Printer. testing for "needed == (DWORD)-1" will fail */
2551 continue;
2554 /* GetPrinterDriverA returns the same number of bytes as GetPrinterDriverW */
2555 if (!on_win9x && !ret && pGetPrinterDriverW)
2557 DWORD double_needed;
2558 ret = pGetPrinterDriverW(hprn, NULL, level, NULL, 0, &double_needed);
2559 ok(!ret, "level %d: GetPrinterDriver error %d\n", level, GetLastError());
2560 ok(double_needed == needed, "GetPrinterDriverA returned different size %d than GetPrinterDriverW (%d)\n", needed, double_needed);
2563 buf = HeapAlloc(GetProcessHeap(), 0, needed);
2565 SetLastError(0xdeadbeef);
2566 filled = -1;
2567 ret = GetPrinterDriver(hprn, NULL, level, buf, needed, &filled);
2568 ok(ret, "level %d: GetPrinterDriver error %d\n", level, GetLastError());
2569 ok(needed == filled, "needed %d != filled %d\n", needed, filled);
2571 if (level == 2)
2573 DRIVER_INFO_2 *di_2 = (DRIVER_INFO_2 *)buf;
2574 DWORD calculated = sizeof(*di_2);
2575 HANDLE hf;
2577 /* MSDN is wrong: The Drivers on the win9x-CD's have cVersion=0x0400
2578 NT351: 1, NT4.0+w2k(Kernelmode): 2, w2k-win7(Usermode): 3, win8 and above(Usermode): 4 */
2579 ok( (di_2->cVersion <= 4) ||
2580 (di_2->cVersion == 0x0400), "di_2->cVersion = %d\n", di_2->cVersion);
2581 ok(di_2->pName != NULL, "not expected NULL ptr\n");
2582 ok(di_2->pEnvironment != NULL, "not expected NULL ptr\n");
2583 ok(di_2->pDriverPath != NULL, "not expected NULL ptr\n");
2584 ok(di_2->pDataFile != NULL, "not expected NULL ptr\n");
2585 ok(di_2->pConfigFile != NULL, "not expected NULL ptr\n");
2587 trace("cVersion %d\n", di_2->cVersion);
2588 trace("pName %s\n", di_2->pName);
2589 calculated += strlen(di_2->pName) + 1;
2590 trace("pEnvironment %s\n", di_2->pEnvironment);
2591 calculated += strlen(di_2->pEnvironment) + 1;
2592 trace("pDriverPath %s\n", di_2->pDriverPath);
2593 calculated += strlen(di_2->pDriverPath) + 1;
2594 trace("pDataFile %s\n", di_2->pDataFile);
2595 calculated += strlen(di_2->pDataFile) + 1;
2596 trace("pConfigFile %s\n", di_2->pConfigFile);
2597 calculated += strlen(di_2->pConfigFile) + 1;
2599 hf = CreateFileA(di_2->pDriverPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
2600 if(hf != INVALID_HANDLE_VALUE)
2601 CloseHandle(hf);
2602 todo_wine
2603 ok(hf != INVALID_HANDLE_VALUE, "Could not open %s\n", di_2->pDriverPath);
2605 hf = CreateFileA(di_2->pDataFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
2606 if(hf != INVALID_HANDLE_VALUE)
2607 CloseHandle(hf);
2608 ok(hf != INVALID_HANDLE_VALUE, "Could not open %s\n", di_2->pDataFile);
2610 hf = CreateFileA(di_2->pConfigFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
2611 if(hf != INVALID_HANDLE_VALUE)
2612 CloseHandle(hf);
2613 todo_wine
2614 ok(hf != INVALID_HANDLE_VALUE, "Could not open %s\n", di_2->pConfigFile);
2616 /* XP allocates memory for both ANSI and unicode names */
2617 ok(filled >= calculated,"calculated %d != filled %d\n", calculated, filled);
2619 /* Obscure test - demonstrate that Windows zero fills the buffer, even on failure */
2620 ret = GetPrinterDriver(hprn, NULL, level, buf, needed - 2, &filled);
2621 ok(!ret, "level %d: GetPrinterDriver succeeded with less buffer than it should\n", level);
2622 ok(di_2->pDataFile == NULL ||
2623 broken(di_2->pDataFile != NULL), /* Win9x/WinMe */
2624 "Even on failure, GetPrinterDriver clears the buffer to zeros\n");
2627 HeapFree(GetProcessHeap(), 0, buf);
2630 SetLastError(0xdeadbeef);
2631 ret = ClosePrinter(hprn);
2632 ok(ret, "ClosePrinter error %d\n", GetLastError());
2635 static void test_DEVMODE(const DEVMODE *dm, LONG dmSize, LPCSTR exp_prn_name)
2637 /* On NT3.51, some fields in DEVMODE are empty/zero
2638 (dmDeviceName, dmSpecVersion, dmDriverVersion and dmDriverExtra)
2639 We skip the Tests on this Platform */
2640 if (dm->dmSpecVersion || dm->dmDriverVersion || dm->dmDriverExtra) {
2641 /* The 0-terminated Printername can be larger (MAX_PATH) than CCHDEVICENAME */
2642 ok(!strncmp(exp_prn_name, (LPCSTR)dm->dmDeviceName, CCHDEVICENAME -1) ||
2643 !strncmp(exp_prn_name, (LPCSTR)dm->dmDeviceName, CCHDEVICENAME -2), /* XP+ */
2644 "expected '%s', got '%s'\n", exp_prn_name, dm->dmDeviceName);
2645 ok(dm->dmSize + dm->dmDriverExtra == dmSize,
2646 "%u != %d\n", dm->dmSize + dm->dmDriverExtra, dmSize);
2648 trace("dmFields %08x\n", dm->dmFields);
2651 static void test_DocumentProperties(void)
2653 HANDLE hprn;
2654 LONG dm_size, ret;
2655 DEVMODE *dm;
2656 char empty_str[] = "";
2658 if (!default_printer)
2660 skip("There is no default printer installed\n");
2661 return;
2664 hprn = 0;
2665 ret = OpenPrinter(default_printer, &hprn, NULL);
2666 if (!ret)
2668 skip("Unable to open the default printer (%s)\n", default_printer);
2669 return;
2671 ok(hprn != 0, "wrong hprn %p\n", hprn);
2673 dm_size = DocumentProperties(0, hprn, NULL, NULL, NULL, 0);
2674 trace("DEVMODE required size %d\n", dm_size);
2675 ok(dm_size >= sizeof(DEVMODE), "unexpected DocumentProperties ret value %d\n", dm_size);
2677 dm = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dm_size);
2679 ret = DocumentProperties(0, hprn, NULL, dm, dm, DM_OUT_BUFFER);
2680 ok(ret == IDOK, "DocumentProperties ret value %d != expected IDOK\n", ret);
2682 ret = DocumentProperties(0, hprn, empty_str, dm, dm, DM_OUT_BUFFER);
2683 ok(ret == IDOK, "DocumentProperties ret value %d != expected IDOK\n", ret);
2685 test_DEVMODE(dm, dm_size, default_printer);
2687 HeapFree(GetProcessHeap(), 0, dm);
2689 SetLastError(0xdeadbeef);
2690 ret = ClosePrinter(hprn);
2691 ok(ret, "ClosePrinter error %d\n", GetLastError());
2694 static void test_EnumPrinters(void)
2696 DWORD neededA, neededW, num;
2697 DWORD ret;
2699 SetLastError(0xdeadbeef);
2700 neededA = -1;
2701 ret = EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &neededA, &num);
2702 if (is_spooler_deactivated(ret, GetLastError())) return;
2703 if (!ret)
2705 /* We have 1 or more printers */
2706 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "gle %d\n", GetLastError());
2707 ok(neededA > 0, "Expected neededA to show the number of needed bytes\n");
2709 else
2711 /* We don't have any printers defined */
2712 ok(GetLastError() == S_OK, "gle %d\n", GetLastError());
2713 ok(neededA == 0, "Expected neededA to be zero\n");
2715 ok(num == 0, "num %d\n", num);
2717 SetLastError(0xdeadbeef);
2718 neededW = -1;
2719 ret = EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &neededW, &num);
2720 /* EnumPrintersW is not supported on all platforms */
2721 if (!ret && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
2723 win_skip("EnumPrintersW is not implemented\n");
2724 return;
2727 if (!ret)
2729 /* We have 1 or more printers */
2730 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "gle %d\n", GetLastError());
2731 ok(neededW > 0, "Expected neededW to show the number of needed bytes\n");
2733 else
2735 /* We don't have any printers defined */
2736 ok(GetLastError() == S_OK, "gle %d\n", GetLastError());
2737 ok(neededW == 0, "Expected neededW to be zero\n");
2739 ok(num == 0, "num %d\n", num);
2741 /* Outlook2003 relies on the buffer size returned by EnumPrintersA being big enough
2742 to hold the buffer returned by EnumPrintersW */
2743 ok(neededA == neededW, "neededA %d neededW %d\n", neededA, neededW);
2746 static void test_DeviceCapabilities(void)
2748 HANDLE hComdlg32;
2749 BOOL (WINAPI *pPrintDlgA)(PRINTDLGA *);
2750 PRINTDLGA prn_dlg;
2751 DEVMODE *dm;
2752 DEVNAMES *dn;
2753 const char *driver, *device, *port;
2754 WORD *papers;
2755 POINT *paper_size;
2756 POINTS ext;
2757 struct
2759 char name[64];
2760 } *paper_name;
2761 INT n_papers, n_paper_size, n_paper_names, n_copies, ret;
2762 DWORD fields;
2764 hComdlg32 = LoadLibrary("comdlg32.dll");
2765 assert(hComdlg32);
2766 pPrintDlgA = (void *)GetProcAddress(hComdlg32, "PrintDlgA");
2767 assert(pPrintDlgA);
2769 memset(&prn_dlg, 0, sizeof(prn_dlg));
2770 prn_dlg.lStructSize = sizeof(prn_dlg);
2771 prn_dlg.Flags = PD_RETURNDEFAULT;
2772 ret = pPrintDlgA(&prn_dlg);
2773 FreeLibrary(hComdlg32);
2774 if (!ret)
2776 skip("PrintDlg returned no default printer\n");
2777 return;
2779 ok(prn_dlg.hDevMode != 0, "PrintDlg returned hDevMode == NULL\n");
2780 ok(prn_dlg.hDevNames != 0, "PrintDlg returned hDevNames == NULL\n");
2782 dm = GlobalLock(prn_dlg.hDevMode);
2783 ok(dm != NULL, "GlobalLock(prn_dlg.hDevMode) failed\n");
2784 trace("dmDeviceName \"%s\"\n", dm->dmDeviceName);
2786 dn = GlobalLock(prn_dlg.hDevNames);
2787 ok(dn != NULL, "GlobalLock(prn_dlg.hDevNames) failed\n");
2788 ok(dn->wDriverOffset, "expected not 0 wDriverOffset\n");
2789 ok(dn->wDeviceOffset, "expected not 0 wDeviceOffset\n");
2790 ok(dn->wOutputOffset, "expected not 0 wOutputOffset\n");
2791 ok(dn->wDefault == DN_DEFAULTPRN, "expected DN_DEFAULTPRN got %x\n", dn->wDefault);
2792 driver = (const char *)dn + dn->wDriverOffset;
2793 device = (const char *)dn + dn->wDeviceOffset;
2794 port = (const char *)dn + dn->wOutputOffset;
2795 trace("driver \"%s\" device \"%s\" port \"%s\"\n", driver, device, port);
2797 test_DEVMODE(dm, dm->dmSize + dm->dmDriverExtra, device);
2799 n_papers = DeviceCapabilities(device, port, DC_PAPERS, NULL, NULL);
2800 ok(n_papers > 0, "DeviceCapabilities DC_PAPERS failed\n");
2801 papers = HeapAlloc(GetProcessHeap(), 0, sizeof(*papers) * n_papers);
2802 ret = DeviceCapabilities(device, port, DC_PAPERS, (LPSTR)papers, NULL);
2803 ok(ret == n_papers, "expected %d, got %d\n", n_papers, ret);
2804 #ifdef VERBOSE
2805 for (ret = 0; ret < n_papers; ret++)
2806 trace("papers[%d] = %d\n", ret, papers[ret]);
2807 #endif
2808 HeapFree(GetProcessHeap(), 0, papers);
2810 n_paper_size = DeviceCapabilities(device, port, DC_PAPERSIZE, NULL, NULL);
2811 ok(n_paper_size > 0, "DeviceCapabilities DC_PAPERSIZE failed\n");
2812 ok(n_paper_size == n_papers, "n_paper_size %d != n_papers %d\n", n_paper_size, n_papers);
2813 paper_size = HeapAlloc(GetProcessHeap(), 0, sizeof(*paper_size) * n_paper_size);
2814 ret = DeviceCapabilities(device, port, DC_PAPERSIZE, (LPSTR)paper_size, NULL);
2815 ok(ret == n_paper_size, "expected %d, got %d\n", n_paper_size, ret);
2816 #ifdef VERBOSE
2817 for (ret = 0; ret < n_paper_size; ret++)
2818 trace("paper_size[%d] = %d x %d\n", ret, paper_size[ret].x, paper_size[ret].y);
2819 #endif
2820 HeapFree(GetProcessHeap(), 0, paper_size);
2822 n_paper_names = DeviceCapabilities(device, port, DC_PAPERNAMES, NULL, NULL);
2823 ok(n_paper_names > 0, "DeviceCapabilities DC_PAPERNAMES failed\n");
2824 ok(n_paper_names == n_papers, "n_paper_names %d != n_papers %d\n", n_paper_names, n_papers);
2825 paper_name = HeapAlloc(GetProcessHeap(), 0, sizeof(*paper_name) * n_paper_names);
2826 ret = DeviceCapabilities(device, port, DC_PAPERNAMES, (LPSTR)paper_name, NULL);
2827 ok(ret == n_paper_names, "expected %d, got %d\n", n_paper_names, ret);
2828 #ifdef VERBOSE
2829 for (ret = 0; ret < n_paper_names; ret++)
2830 trace("paper_name[%u] = %s\n", ret, paper_name[ret].name);
2831 #endif
2832 HeapFree(GetProcessHeap(), 0, paper_name);
2834 n_copies = DeviceCapabilities(device, port, DC_COPIES, NULL, dm);
2835 ok(n_copies > 0, "DeviceCapabilities DC_COPIES failed\n");
2836 trace("n_copies = %d\n", n_copies);
2838 /* these capabilities are not available on all printer drivers */
2839 if (0)
2841 ret = DeviceCapabilities(device, port, DC_MAXEXTENT, NULL, NULL);
2842 ok(ret != -1, "DeviceCapabilities DC_MAXEXTENT failed\n");
2843 ext = MAKEPOINTS(ret);
2844 trace("max ext = %d x %d\n", ext.x, ext.y);
2846 ret = DeviceCapabilities(device, port, DC_MINEXTENT, NULL, NULL);
2847 ok(ret != -1, "DeviceCapabilities DC_MINEXTENT failed\n");
2848 ext = MAKEPOINTS(ret);
2849 trace("min ext = %d x %d\n", ext.x, ext.y);
2852 fields = DeviceCapabilities(device, port, DC_FIELDS, NULL, NULL);
2853 ok(fields != (DWORD)-1, "DeviceCapabilities DC_FIELDS failed\n");
2854 ok(fields == (dm->dmFields | DM_FORMNAME) ||
2855 fields == ((dm->dmFields | DM_FORMNAME | DM_PAPERSIZE) & ~(DM_PAPERLENGTH|DM_PAPERWIDTH)) ||
2856 broken(fields == dm->dmFields), /* Win9x/WinMe */
2857 "fields %x, dm->dmFields %x\n", fields, dm->dmFields);
2859 GlobalUnlock(prn_dlg.hDevMode);
2860 GlobalFree(prn_dlg.hDevMode);
2861 GlobalUnlock(prn_dlg.hDevNames);
2862 GlobalFree(prn_dlg.hDevNames);
2865 static void test_IsValidDevmodeW(void)
2867 BOOL br;
2869 if (!pIsValidDevmodeW)
2871 win_skip("IsValidDevmodeW not implemented.\n");
2872 return;
2875 br = pIsValidDevmodeW(NULL, 0);
2876 ok(br == FALSE, "Got %d\n", br);
2878 br = pIsValidDevmodeW(NULL, 1);
2879 ok(br == FALSE, "Got %d\n", br);
2881 br = pIsValidDevmodeW(NULL, sizeof(DEVMODEW));
2882 ok(br == FALSE, "Got %d\n", br);
2885 static void test_OpenPrinter_defaults(void)
2887 HANDLE printer;
2888 BOOL ret;
2889 DWORD needed;
2890 short default_size;
2891 ADDJOB_INFO_1 *add_job;
2892 JOB_INFO_2 *job_info;
2893 DEVMODE my_dm;
2894 PRINTER_DEFAULTS prn_def;
2895 PRINTER_INFO_2 *pi;
2897 if (!default_printer)
2899 skip("There is no default printer installed\n");
2900 return;
2903 /* Printer opened with NULL defaults. Retrieve default paper size
2904 and confirm that jobs have this size. */
2906 ret = OpenPrinter( default_printer, &printer, NULL );
2907 if (!ret)
2909 skip("Unable to open the default printer (%s)\n", default_printer);
2910 return;
2913 ret = GetPrinter( printer, 2, NULL, 0, &needed );
2914 ok( !ret, "got %d\n", ret );
2915 pi = HeapAlloc( GetProcessHeap(), 0, needed );
2916 ret = GetPrinter( printer, 2, (BYTE *)pi, needed, &needed );
2917 ok( ret, "got %d\n", ret );
2918 default_size = pi->pDevMode->u1.s1.dmPaperSize;
2919 HeapFree( GetProcessHeap(), 0, pi );
2921 ret = AddJob( printer, 1, NULL, 0, &needed );
2922 ok( !ret, "got %d\n", ret );
2923 add_job = HeapAlloc( GetProcessHeap(), 0, needed );
2924 ret = AddJob( printer, 1, (BYTE *)add_job, needed, &needed );
2925 ok( ret, "got %d\n", ret );
2927 ret = GetJob( printer, add_job->JobId, 2, NULL, 0, &needed );
2928 ok( !ret, "got %d\n", ret );
2929 job_info = HeapAlloc( GetProcessHeap(), 0, needed );
2930 ret = GetJob( printer, add_job->JobId, 2, (BYTE *)job_info, needed, &needed );
2931 ok( ret, "got %d\n", ret );
2933 todo_wine
2934 ok( job_info->pDevMode != NULL, "got NULL devmode\n");
2935 if (job_info->pDevMode)
2936 ok( job_info->pDevMode->u1.s1.dmPaperSize == default_size, "got %d default %d\n",
2937 job_info->pDevMode->u1.s1.dmPaperSize, default_size );
2939 HeapFree( GetProcessHeap(), 0, job_info );
2940 ScheduleJob( printer, add_job->JobId ); /* remove the empty job */
2941 HeapFree( GetProcessHeap(), 0, add_job );
2942 ClosePrinter( printer );
2944 /* Printer opened with something other than the default paper size. */
2946 memset( &my_dm, 0, sizeof(my_dm) );
2947 my_dm.dmSize = sizeof(my_dm);
2948 my_dm.dmFields = DM_PAPERSIZE;
2949 my_dm.u1.s1.dmPaperSize = (default_size == DMPAPER_A4) ? DMPAPER_LETTER : DMPAPER_A4;
2951 prn_def.pDatatype = NULL;
2952 prn_def.pDevMode = &my_dm;
2953 prn_def.DesiredAccess = PRINTER_ACCESS_USE;
2955 ret = OpenPrinter( default_printer, &printer, &prn_def );
2956 ok( ret, "got %d\n", ret );
2958 /* GetPrinter stills returns default size */
2959 ret = GetPrinter( printer, 2, NULL, 0, &needed );
2960 ok( !ret, "got %d\n", ret );
2961 pi = HeapAlloc( GetProcessHeap(), 0, needed );
2962 ret = GetPrinter( printer, 2, (BYTE *)pi, needed, &needed );
2963 ok( ret, "got %d\n", ret );
2964 ok( pi->pDevMode->u1.s1.dmPaperSize == default_size, "got %d default %d\n",
2965 pi->pDevMode->u1.s1.dmPaperSize, default_size );
2967 HeapFree( GetProcessHeap(), 0, pi );
2969 /* However the GetJob has the new size */
2970 ret = AddJob( printer, 1, NULL, 0, &needed );
2971 ok( !ret, "got %d\n", ret );
2972 add_job = HeapAlloc( GetProcessHeap(), 0, needed );
2973 ret = AddJob( printer, 1, (BYTE *)add_job, needed, &needed );
2974 ok( ret, "got %d\n", ret );
2976 ret = GetJob( printer, add_job->JobId, 2, NULL, 0, &needed );
2977 ok( !ret, "got %d\n", ret );
2978 job_info = HeapAlloc( GetProcessHeap(), 0, needed );
2979 ret = GetJob( printer, add_job->JobId, 2, (BYTE *)job_info, needed, &needed );
2980 ok( ret, "got %d\n", ret );
2982 ok( job_info->pDevMode->dmFields == DM_PAPERSIZE, "got %08x\n",
2983 job_info->pDevMode->dmFields );
2984 ok( job_info->pDevMode->u1.s1.dmPaperSize == my_dm.u1.s1.dmPaperSize,
2985 "got %d new size %d\n",
2986 job_info->pDevMode->u1.s1.dmPaperSize, my_dm.u1.s1.dmPaperSize );
2988 HeapFree( GetProcessHeap(), 0, job_info );
2989 ScheduleJob( printer, add_job->JobId ); /* remove the empty job */
2990 HeapFree( GetProcessHeap(), 0, add_job );
2991 ClosePrinter( printer );
2994 START_TEST(info)
2996 hwinspool = LoadLibrary("winspool.drv");
2997 pAddPortExA = (void *) GetProcAddress(hwinspool, "AddPortExA");
2998 pEnumPrinterDriversW = (void *) GetProcAddress(hwinspool, "EnumPrinterDriversW");
2999 pGetDefaultPrinterA = (void *) GetProcAddress(hwinspool, "GetDefaultPrinterA");
3000 pGetPrinterDataExA = (void *) GetProcAddress(hwinspool, "GetPrinterDataExA");
3001 pGetPrinterDriverW = (void *) GetProcAddress(hwinspool, "GetPrinterDriverW");
3002 pGetPrinterW = (void *) GetProcAddress(hwinspool, "GetPrinterW");
3003 pSetDefaultPrinterA = (void *) GetProcAddress(hwinspool, "SetDefaultPrinterA");
3004 pXcvDataW = (void *) GetProcAddress(hwinspool, "XcvDataW");
3005 pIsValidDevmodeW = (void *) GetProcAddress(hwinspool, "IsValidDevmodeW");
3007 on_win9x = check_win9x();
3008 if (on_win9x)
3009 win_skip("Several W-functions are not available on Win9x/WinMe\n");
3011 find_default_printer();
3012 find_local_server();
3013 find_tempfile();
3015 test_AddMonitor();
3016 test_AddPort();
3017 test_AddPortEx();
3018 test_ConfigurePort();
3019 test_DeleteMonitor();
3020 test_DeletePort();
3021 test_DeviceCapabilities();
3022 test_DocumentProperties();
3023 test_EnumForms(NULL);
3024 if (default_printer) test_EnumForms(default_printer);
3025 test_EnumMonitors();
3026 test_EnumPorts();
3027 test_EnumPrinterDrivers();
3028 test_EnumPrinters();
3029 test_EnumPrintProcessors();
3030 test_GetDefaultPrinter();
3031 test_GetPrinterDriverDirectory();
3032 test_GetPrintProcessorDirectory();
3033 test_OpenPrinter();
3034 test_GetPrinter();
3035 test_GetPrinterData();
3036 test_GetPrinterDataEx();
3037 test_GetPrinterDriver();
3038 test_SetDefaultPrinter();
3039 test_XcvDataW_MonitorUI();
3040 test_XcvDataW_PortIsValid();
3041 test_IsValidDevmodeW();
3042 test_OpenPrinter_defaults();
3044 /* Cleanup our temporary file */
3045 DeleteFileA(tempfileA);