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