90cdc816cdfa267efa287e0ed02fddef417a92d2
[ira/wip.git] / testprogs / win32 / spoolss / spoolss.c
1 /*
2    Unix SMB/CIFS implementation.
3    test suite for spoolss rpc operations
4
5    Copyright (C) Guenther Deschner 2009-2010
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 /****************************************************************************
22 ****************************************************************************/
23
24 #include "spoolss.h"
25 #include "string.h"
26 #include "torture.h"
27
28 /****************************************************************************
29 ****************************************************************************/
30
31 static BOOL test_OpenPrinter(struct torture_context *tctx,
32                              LPSTR printername,
33                              LPPRINTER_DEFAULTS defaults,
34                              LPHANDLE handle)
35 {
36         torture_comment(tctx, "Testing OpenPrinter(%s)", printername);
37
38         if (!OpenPrinter(printername, handle, defaults)) {
39                 char tmp[1024];
40                 sprintf(tmp, "failed to open printer %s, error was: 0x%08x\n",
41                         printername, GetLastError());
42                 torture_fail(tctx, tmp);
43         }
44
45         return TRUE;
46 }
47
48 /****************************************************************************
49 ****************************************************************************/
50
51 static BOOL test_ClosePrinter(struct torture_context *tctx,
52                               HANDLE handle)
53 {
54         torture_comment(tctx, "Testing ClosePrinter");
55
56         if (!ClosePrinter(handle)) {
57                 char tmp[1024];
58                 sprintf(tmp, "failed to close printer, error was: %s\n",
59                         errstr(GetLastError()));
60                 torture_fail(tctx, tmp);
61         }
62
63         return TRUE;
64 }
65
66
67 /****************************************************************************
68 ****************************************************************************/
69
70 static BOOL test_EnumPrinters(struct torture_context *tctx,
71                               LPSTR servername)
72 {
73         DWORD levels[]  = { 1, 2, 5 };
74         DWORD success[] = { 1, 1, 1 };
75         DWORD i;
76         DWORD flags = PRINTER_ENUM_NAME;
77         LPBYTE buffer = NULL;
78
79         for (i=0; i < ARRAY_SIZE(levels); i++) {
80
81                 DWORD needed = 0;
82                 DWORD returned = 0;
83                 DWORD err = 0;
84                 char tmp[1024];
85
86                 torture_comment(tctx, "Testing EnumPrinters level %d", levels[i]);
87
88                 EnumPrinters(flags, servername, levels[i], NULL, 0, &needed, &returned);
89                 err = GetLastError();
90                 if (err == ERROR_INSUFFICIENT_BUFFER) {
91                         err = 0;
92                         buffer = malloc(needed);
93                         torture_assert(tctx, buffer, "malloc failed");
94                         if (!EnumPrinters(flags, servername, levels[i], buffer, needed, &needed, &returned)) {
95                                 err = GetLastError();
96                         }
97                 }
98                 if (err) {
99                         sprintf(tmp, "EnumPrinters failed level %d on [%s] (buffer size = %d), error: %s\n",
100                                 levels[i], servername, needed, errstr(err));
101                         if (success[i]) {
102                                 torture_fail(tctx, tmp);
103                         } else {
104                                 torture_warning(tctx, tmp);
105                         }
106                 }
107
108                 if (tctx->print) {
109                         print_printer_info_bylevel(levels[i], buffer, returned);
110                 }
111
112                 free(buffer);
113                 buffer = NULL;
114         }
115
116         return TRUE;
117 }
118
119 /****************************************************************************
120 ****************************************************************************/
121
122 static BOOL test_EnumDrivers(struct torture_context *tctx,
123                              LPSTR servername,
124                              LPSTR architecture)
125 {
126         DWORD levels[]  = { 1, 2, 3, 4, 5, 6 };
127         DWORD success[] = { 1, 1, 1, 1, 1, 1 };
128         DWORD i;
129         LPBYTE buffer = NULL;
130
131         for (i=0; i < ARRAY_SIZE(levels); i++) {
132
133                 DWORD needed = 0;
134                 DWORD returned = 0;
135                 DWORD err = 0;
136                 char tmp[1024];
137
138                 torture_comment(tctx, "Testing EnumPrinterDrivers level %d", levels[i]);
139
140                 EnumPrinterDrivers(servername, architecture, levels[i], NULL, 0, &needed, &returned);
141                 err = GetLastError();
142                 if (err == ERROR_INSUFFICIENT_BUFFER) {
143                         err = 0;
144                         buffer = malloc(needed);
145                         torture_assert(tctx, buffer, "malloc failed");
146                         if (!EnumPrinterDrivers(servername, architecture, levels[i], buffer, needed, &needed, &returned)) {
147                                 err = GetLastError();
148                         }
149                 }
150                 if (err) {
151                         sprintf(tmp, "EnumPrinterDrivers failed level %d on [%s] (buffer size = %d), error: %s\n",
152                                 levels[i], servername, needed, errstr(err));
153                         if (success[i]) {
154                                 torture_fail(tctx, tmp);
155                         } else {
156                                 torture_warning(tctx, tmp);
157                         }
158                 }
159
160                 if (tctx->print) {
161                         print_driver_info_bylevel(levels[i], buffer, returned);
162                 }
163
164                 free(buffer);
165                 buffer = NULL;
166         }
167
168         return TRUE;
169 }
170
171 /****************************************************************************
172 ****************************************************************************/
173
174 static BOOL test_GetForm(struct torture_context *tctx,
175                          LPSTR servername,
176                          HANDLE handle,
177                          LPSTR formname)
178 {
179         DWORD levels[]  = { 1, 2 };
180         DWORD success[] = { 1, 0 };
181         DWORD i;
182         LPBYTE buffer = NULL;
183
184         for (i=0; i < ARRAY_SIZE(levels); i++) {
185
186                 DWORD needed = 0;
187                 DWORD err = 0;
188                 char tmp[1024];
189
190                 torture_comment(tctx, "Testing GetForm(%s) level %d", formname, levels[i]);
191
192                 GetForm(handle, formname, levels[i], NULL, 0, &needed);
193                 err = GetLastError();
194                 if (err == ERROR_INSUFFICIENT_BUFFER) {
195                         err = 0;
196                         buffer = malloc(needed);
197                         torture_assert(tctx, buffer, "malloc failed");
198                         if (!GetForm(handle, formname, levels[i], buffer, needed, &needed)) {
199                                 err = GetLastError();
200                         }
201                 }
202                 if (err) {
203                         sprintf(tmp, "GetForm failed level %d on [%s] (buffer size = %d), error: %s\n",
204                                 levels[i], servername, needed, errstr(err));
205                         if (success[i]) {
206                                 torture_fail(tctx, tmp);
207                         } else {
208                                 torture_warning(tctx, tmp);
209                         }
210                 }
211
212                 if (tctx->print) {
213                         print_form_info_bylevel(levels[i], buffer, 1);
214                 }
215
216                 free(buffer);
217                 buffer = NULL;
218         }
219
220         return TRUE;
221 }
222
223 /****************************************************************************
224 ****************************************************************************/
225
226 static BOOL test_EnumForms(struct torture_context *tctx,
227                            LPSTR servername,
228                            HANDLE handle)
229 {
230         DWORD levels[]  = { 1, 2 };
231         DWORD success[] = { 1, 0 };
232         DWORD i;
233         LPBYTE buffer = NULL;
234
235         for (i=0; i < ARRAY_SIZE(levels); i++) {
236
237                 DWORD needed = 0;
238                 DWORD returned = 0;
239                 DWORD err = 0;
240                 char tmp[1024];
241
242                 torture_comment(tctx, "Testing EnumForms level %d", levels[i]);
243
244                 EnumForms(handle, levels[i], NULL, 0, &needed, &returned);
245                 err = GetLastError();
246                 if (err == ERROR_INSUFFICIENT_BUFFER) {
247                         err = 0;
248                         buffer = malloc(needed);
249                         torture_assert(tctx, buffer, "malloc failed");
250                         if (!EnumForms(handle, levels[i], buffer, needed, &needed, &returned)) {
251                                 err = GetLastError();
252                         }
253                 }
254                 if (err) {
255                         sprintf(tmp, "EnumForms failed level %d on [%s] (buffer size = %d), error: %s\n",
256                                 levels[i], servername, needed, errstr(err));
257                         if (success[i]) {
258                                 torture_fail(tctx, tmp);
259                         } else {
260                                 torture_warning(tctx, tmp);
261                         }
262                 }
263
264                 if (tctx->print) {
265                         print_form_info_bylevel(levels[i], buffer, returned);
266                 }
267
268                 free(buffer);
269                 buffer = NULL;
270         }
271
272         return TRUE;
273 }
274
275 /****************************************************************************
276 ****************************************************************************/
277
278 static BOOL test_EnumPorts(struct torture_context *tctx,
279                            LPSTR servername)
280 {
281         DWORD levels[]  = { 1, 2 };
282         DWORD success[] = { 1, 1 };
283         DWORD i;
284         LPBYTE buffer = NULL;
285
286         for (i=0; i < ARRAY_SIZE(levels); i++) {
287
288                 DWORD needed = 0;
289                 DWORD returned = 0;
290                 DWORD err = 0;
291                 char tmp[1024];
292
293                 torture_comment(tctx, "Testing EnumPorts level %d", levels[i]);
294
295                 EnumPorts(servername, levels[i], NULL, 0, &needed, &returned);
296                 err = GetLastError();
297                 if (err == ERROR_INSUFFICIENT_BUFFER) {
298                         err = 0;
299                         buffer = malloc(needed);
300                         torture_assert(tctx, buffer, "malloc failed");
301                         if (!EnumPorts(servername, levels[i], buffer, needed, &needed, &returned)) {
302                                 err = GetLastError();
303                         }
304                 }
305                 if (err) {
306                         sprintf(tmp, "EnumPorts failed level %d on [%s] (buffer size = %d), error: %s\n",
307                                 levels[i], servername, needed, errstr(err));
308                         if (success[i]) {
309                                 torture_fail(tctx, tmp);
310                         } else {
311                                 torture_warning(tctx, tmp);
312                         }
313                 }
314
315                 if (tctx->print) {
316                         print_port_info_bylevel(levels[i], buffer, returned);
317                 }
318
319                 free(buffer);
320                 buffer = NULL;
321         }
322
323         return TRUE;
324 }
325
326 /****************************************************************************
327 ****************************************************************************/
328
329 static BOOL test_EnumMonitors(struct torture_context *tctx,
330                               LPSTR servername)
331 {
332         DWORD levels[]  = { 1, 2 };
333         DWORD success[] = { 1, 1 };
334         DWORD i;
335         LPBYTE buffer = NULL;
336
337         for (i=0; i < ARRAY_SIZE(levels); i++) {
338
339                 DWORD needed = 0;
340                 DWORD returned = 0;
341                 DWORD err = 0;
342                 char tmp[1024];
343
344                 torture_comment(tctx, "Testing EnumMonitors level %d", levels[i]);
345
346                 EnumMonitors(servername, levels[i], NULL, 0, &needed, &returned);
347                 err = GetLastError();
348                 if (err == ERROR_INSUFFICIENT_BUFFER) {
349                         err = 0;
350                         buffer = malloc(needed);
351                         torture_assert(tctx, buffer, "malloc failed");
352                         if (!EnumMonitors(servername, levels[i], buffer, needed, &needed, &returned)) {
353                                 err = GetLastError();
354                         }
355                 }
356                 if (err) {
357                         sprintf(tmp, "EnumMonitors failed level %d on [%s] (buffer size = %d), error: %s\n",
358                                 levels[i], servername, needed, errstr(err));
359                         if (success[i]) {
360                                 torture_fail(tctx, tmp);
361                         } else {
362                                 torture_warning(tctx, tmp);
363                         }
364                 }
365
366                 free(buffer);
367                 buffer = NULL;
368         }
369
370         return TRUE;
371 }
372
373 /****************************************************************************
374 ****************************************************************************/
375
376 static BOOL test_EnumPrintProcessors(struct torture_context *tctx,
377                                      LPSTR servername,
378                                      LPSTR architecture)
379 {
380         DWORD levels[]  = { 1 };
381         DWORD success[] = { 1 };
382         DWORD i;
383         LPBYTE buffer = NULL;
384
385         for (i=0; i < ARRAY_SIZE(levels); i++) {
386
387                 DWORD needed = 0;
388                 DWORD returned = 0;
389                 DWORD err = 0;
390                 char tmp[1024];
391
392                 torture_comment(tctx, "Testing EnumPrintProcessors level %d", levels[i]);
393
394                 EnumPrintProcessors(servername, architecture, levels[i], NULL, 0, &needed, &returned);
395                 err = GetLastError();
396                 if (err == ERROR_INSUFFICIENT_BUFFER) {
397                         err = 0;
398                         buffer = malloc(needed);
399                         torture_assert(tctx, buffer, "malloc failed");
400                         if (!EnumPrintProcessors(servername, architecture, levels[i], buffer, needed, &needed, &returned)) {
401                                 err = GetLastError();
402                         }
403                 }
404                 if (err) {
405                         sprintf(tmp, "EnumPrintProcessors failed level %d on [%s] (buffer size = %d), error: %s\n",
406                                 levels[i], servername, needed, errstr(err));
407                         if (success[i]) {
408                                 torture_fail(tctx, tmp);
409                         } else {
410                                 torture_warning(tctx, tmp);
411                         }
412                 }
413
414                 free(buffer);
415                 buffer = NULL;
416         }
417
418         return TRUE;
419 }
420
421 /****************************************************************************
422 ****************************************************************************/
423
424 static BOOL test_EnumPrintProcessorDatatypes(struct torture_context *tctx,
425                                              LPSTR servername)
426 {
427         DWORD levels[]  = { 1 };
428         DWORD success[] = { 1 };
429         DWORD i;
430         LPBYTE buffer = NULL;
431
432         for (i=0; i < ARRAY_SIZE(levels); i++) {
433
434                 DWORD needed = 0;
435                 DWORD returned = 0;
436                 DWORD err = 0;
437                 char tmp[1024];
438
439                 torture_comment(tctx, "Testing EnumPrintProcessorDatatypes level %d", levels[i]);
440
441                 EnumPrintProcessorDatatypes(servername, "winprint", levels[i], NULL, 0, &needed, &returned);
442                 err = GetLastError();
443                 if (err == ERROR_INSUFFICIENT_BUFFER) {
444                         err = 0;
445                         buffer = malloc(needed);
446                         torture_assert(tctx, buffer, "malloc failed");
447                         if (!EnumPrintProcessorDatatypes(servername, "winprint", levels[i], buffer, needed, &needed, &returned)) {
448                                 err = GetLastError();
449                         }
450                 }
451                 if (err) {
452                         sprintf(tmp, "EnumPrintProcessorDatatypes failed level %d on [%s] (buffer size = %d), error: %s\n",
453                                 levels[i], servername, needed, errstr(err));
454                         if (success[i]) {
455                                 torture_fail(tctx, tmp);
456                         } else {
457                                 torture_warning(tctx, tmp);
458                         }
459                 }
460
461                 free(buffer);
462                 buffer = NULL;
463         }
464
465         return TRUE;
466 }
467
468 /****************************************************************************
469 ****************************************************************************/
470
471 static BOOL test_EnumPrinterKey(struct torture_context *tctx,
472                                 LPSTR servername,
473                                 HANDLE handle,
474                                 LPCSTR key)
475 {
476         LPSTR buffer = NULL;
477         DWORD needed = 0;
478         DWORD err = 0;
479         char tmp[1024];
480
481         torture_comment(tctx, "Testing EnumPrinterKey(%s)", key);
482
483         err = EnumPrinterKey(handle, key, NULL, 0, &needed);
484         if (err == ERROR_MORE_DATA) {
485                 buffer = (LPTSTR)malloc(needed);
486                 torture_assert(tctx, buffer, "malloc failed");
487                 err = EnumPrinterKey(handle, key, buffer, needed, &needed);
488         }
489         if (err) {
490                 sprintf(tmp, "EnumPrinterKey(%s) failed on [%s] (buffer size = %d), error: %s\n",
491                         key, servername, needed, errstr(err));
492                 torture_fail(tctx, tmp);
493         }
494
495         if (tctx->print) {
496                 print_printer_keys(buffer);
497         }
498
499         free(buffer);
500
501         return TRUE;
502 }
503
504 /****************************************************************************
505 ****************************************************************************/
506
507 static BOOL test_GetPrinter(struct torture_context *tctx,
508                             LPSTR printername,
509                             HANDLE handle)
510 {
511         DWORD levels[]  = { 1, 2, 3, 4, 5, 6, 7, 8 };
512         DWORD success[] = { 1, 1, 1, 1, 1, 1, 1, 1 };
513         DWORD i;
514         LPBYTE buffer = NULL;
515
516         for (i=0; i < ARRAY_SIZE(levels); i++) {
517
518                 DWORD needed = 0;
519                 DWORD err = 0;
520                 char tmp[1024];
521
522                 torture_comment(tctx, "Testing GetPrinter level %d", levels[i]);
523
524                 GetPrinter(handle, levels[i], NULL, 0, &needed);
525                 err = GetLastError();
526                 if (err == ERROR_INSUFFICIENT_BUFFER) {
527                         err = 0;
528                         buffer = malloc(needed);
529                         torture_assert(tctx, buffer, "malloc failed");
530                         if (!GetPrinter(handle, levels[i], buffer, needed, &needed)) {
531                                 err = GetLastError();
532                         }
533                 }
534                 if (err) {
535                         sprintf(tmp, "GetPrinter failed level %d on [%s] (buffer size = %d), error: %s\n",
536                                 levels[i], printername, needed, errstr(err));
537                         if (success[i]) {
538                                 torture_fail(tctx, tmp);
539                         } else {
540                                 torture_warning(tctx, tmp);
541                         }
542                 }
543
544                 if (tctx->print) {
545                         print_printer_info_bylevel(levels[i], buffer, 1);
546                 }
547
548                 free(buffer);
549                 buffer = NULL;
550         }
551
552         return TRUE;
553 }
554
555 /****************************************************************************
556 ****************************************************************************/
557
558 static BOOL test_GetPrinterDriver(struct torture_context *tctx,
559                                   LPSTR printername,
560                                   LPSTR architecture,
561                                   HANDLE handle)
562 {
563         DWORD levels[]  = { 1, 2, 3, 4, 5, 6, 8 };
564         DWORD success[] = { 1, 1, 1, 1, 1, 1, 1 };
565         DWORD i;
566         LPBYTE buffer = NULL;
567
568         for (i=0; i < ARRAY_SIZE(levels); i++) {
569
570                 DWORD needed = 0;
571                 DWORD err = 0;
572                 char tmp[1024];
573
574                 torture_comment(tctx, "Testing GetPrinterDriver level %d", levels[i]);
575
576                 GetPrinterDriver(handle, architecture, levels[i], NULL, 0, &needed);
577                 err = GetLastError();
578                 if (err == ERROR_INSUFFICIENT_BUFFER) {
579                         err = 0;
580                         buffer = malloc(needed);
581                         torture_assert(tctx, buffer, "malloc failed");
582                         if (!GetPrinterDriver(handle, architecture, levels[i], buffer, needed, &needed)) {
583                                 err = GetLastError();
584                         }
585                 }
586                 if (err) {
587                         sprintf(tmp, "GetPrinterDriver failed level %d on [%s] (buffer size = %d), error: %s\n",
588                                 levels[i], printername, needed, errstr(err));
589                         if (success[i]) {
590                                 torture_fail(tctx, tmp);
591                         } else {
592                                 torture_warning(tctx, tmp);
593                         }
594                 }
595
596                 if (tctx->print) {
597                         print_driver_info_bylevel(levels[i], buffer, 1);
598                 }
599
600                 free(buffer);
601                 buffer = NULL;
602         }
603
604         return TRUE;
605 }
606
607
608 /****************************************************************************
609 ****************************************************************************/
610
611 static BOOL test_EnumJobs(struct torture_context *tctx,
612                           LPSTR printername,
613                           HANDLE handle)
614 {
615         DWORD levels[]  = { 1, 2, 3, 4 };
616         DWORD success[] = { 1, 1, 1, 1 };
617         DWORD i;
618         LPBYTE buffer = NULL;
619
620         for (i=0; i < ARRAY_SIZE(levels); i++) {
621
622                 DWORD needed = 0;
623                 DWORD returned = 0;
624                 DWORD err = 0;
625                 char tmp[1024];
626
627                 torture_comment(tctx, "Testing EnumJobs level %d", levels[i]);
628
629                 EnumJobs(handle, 0, 100, levels[i], NULL, 0, &needed, &returned);
630                 err = GetLastError();
631                 if (err == ERROR_INSUFFICIENT_BUFFER) {
632                         err = 0;
633                         buffer = malloc(needed);
634                         torture_assert(tctx, buffer, "malloc failed");
635                         if (!EnumJobs(handle, 0, 100, levels[i], buffer, needed, &needed, &returned)) {
636                                 err = GetLastError();
637                         }
638                 }
639                 if (err) {
640                         sprintf(tmp, "EnumJobs failed level %d on [%s] (buffer size = %d), error: %s\n",
641                                 levels[i], printername, needed, errstr(err));
642                         if (success[i]) {
643                                 torture_fail(tctx, tmp);
644                         } else {
645                                 torture_warning(tctx, tmp);
646                         }
647                 }
648
649                 free(buffer);
650                 buffer = NULL;
651         }
652
653         return TRUE;
654 }
655
656 /****************************************************************************
657 ****************************************************************************/
658
659 static BOOL test_EnumPrinterDataEx(struct torture_context *tctx,
660                                    LPSTR servername,
661                                    LPSTR keyname,
662                                    HANDLE handle,
663                                    LPBYTE *buffer_p,
664                                    DWORD *returned_p)
665 {
666         LPBYTE buffer = NULL;
667         DWORD needed = 0;
668         DWORD returned = 0;
669         DWORD err = 0;
670         char tmp[1024];
671
672         torture_comment(tctx, "Testing EnumPrinterDataEx(%s)", keyname);
673
674         err = EnumPrinterDataEx(handle, keyname, NULL, 0, &needed, &returned);
675         if (err == ERROR_MORE_DATA) {
676                 buffer = malloc(needed);
677                 torture_assert(tctx, buffer, "malloc failed");
678                 err = EnumPrinterDataEx(handle, keyname, buffer, needed, &needed, &returned);
679         }
680         if (err) {
681                 sprintf(tmp, "EnumPrinterDataEx(%s) failed on [%s] (buffer size = %d), error: %s\n",
682                         keyname, servername, needed, errstr(err));
683                 torture_fail(tctx, tmp);
684         }
685
686         if (tctx->print) {
687                 DWORD i;
688                 LPPRINTER_ENUM_VALUES v = (LPPRINTER_ENUM_VALUES)buffer;
689                 for (i=0; i < returned; i++) {
690                         print_printer_enum_values(&v[i]);
691                 }
692         }
693
694         if (returned_p) {
695                 *returned_p = returned;
696         }
697
698         if (buffer_p) {
699                 *buffer_p = buffer;
700         } else {
701                 free(buffer);
702         }
703
704         return TRUE;
705 }
706
707
708 /****************************************************************************
709 ****************************************************************************/
710
711 static BOOL test_OnePrinter(struct torture_context *tctx,
712                             LPSTR printername,
713                             LPSTR architecture,
714                             LPPRINTER_DEFAULTS defaults)
715 {
716         HANDLE handle;
717         BOOL ret = TRUE;
718
719         torture_comment(tctx, "Testing Printer %s", printername);
720
721         ret &= test_OpenPrinter(tctx, printername, defaults, &handle);
722         ret &= test_GetPrinter(tctx, printername, handle);
723         ret &= test_GetPrinterDriver(tctx, printername, architecture, handle);
724         ret &= test_EnumForms(tctx, printername, handle);
725         ret &= test_EnumJobs(tctx, printername, handle);
726         ret &= test_EnumPrinterKey(tctx, printername, handle, "");
727         ret &= test_EnumPrinterKey(tctx, printername, handle, "PrinterDriverData");
728         ret &= test_EnumPrinterDataEx(tctx, printername, "PrinterDriverData", handle, NULL, NULL);
729         ret &= test_ClosePrinter(tctx, handle);
730
731         return ret;
732 }
733
734 /****************************************************************************
735 ****************************************************************************/
736
737 static BOOL test_EachPrinter(struct torture_context *tctx,
738                              LPSTR servername,
739                              LPSTR architecture,
740                              LPPRINTER_DEFAULTS defaults)
741 {
742         DWORD needed = 0;
743         DWORD returned = 0;
744         DWORD err = 0;
745         char tmp[1024];
746         DWORD i;
747         DWORD flags = PRINTER_ENUM_NAME;
748         PPRINTER_INFO_1 buffer = NULL;
749         BOOL ret = TRUE;
750
751         torture_comment(tctx, "Testing EnumPrinters level %d", 1);
752
753         EnumPrinters(flags, servername, 1, NULL, 0, &needed, &returned);
754         err = GetLastError();
755         if (err == ERROR_INSUFFICIENT_BUFFER) {
756                 err = 0;
757                 buffer = (PPRINTER_INFO_1)malloc(needed);
758                 torture_assert(tctx, buffer, "malloc failed");
759                 if (!EnumPrinters(flags, servername, 1, (LPBYTE)buffer, needed, &needed, &returned)) {
760                         err = GetLastError();
761                 }
762         }
763         if (err) {
764                 sprintf(tmp, "EnumPrinters failed level %d on [%s] (buffer size = %d), error: %s\n",
765                         1, servername, needed, errstr(err));
766                 torture_fail(tctx, tmp);
767         }
768
769         for (i=0; i < returned; i++) {
770                 ret &= test_OnePrinter(tctx, buffer[i].pName, architecture, defaults);
771         }
772
773         free(buffer);
774
775         return ret;
776 }
777
778 /****************************************************************************
779 ****************************************************************************/
780
781 static BOOL test_GetPrintProcessorDirectory(struct torture_context *tctx,
782                                             LPSTR servername,
783                                             LPSTR architecture)
784 {
785         DWORD levels[]  = { 1 };
786         DWORD success[] = { 1 };
787         DWORD i;
788         LPBYTE buffer = NULL;
789
790         for (i=0; i < ARRAY_SIZE(levels); i++) {
791
792                 DWORD needed = 0;
793                 DWORD err = 0;
794                 char tmp[1024];
795
796                 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %d", levels[i]);
797
798                 GetPrintProcessorDirectory(servername, architecture, levels[i], NULL, 0, &needed);
799                 err = GetLastError();
800                 if (err == ERROR_INSUFFICIENT_BUFFER) {
801                         err = 0;
802                         buffer = malloc(needed);
803                         torture_assert(tctx, buffer, "malloc failed");
804                         if (!GetPrintProcessorDirectory(servername, architecture, levels[i], buffer, needed, &needed)) {
805                                 err = GetLastError();
806                         }
807                 }
808                 if (err) {
809                         sprintf(tmp, "GetPrintProcessorDirectory failed level %d on [%s] (buffer size = %d), error: %s\n",
810                                 levels[i], servername, needed, errstr(err));
811                         if (success[i]) {
812                                 torture_fail(tctx, tmp);
813                         } else {
814                                 torture_warning(tctx, tmp);
815                         }
816                 }
817
818                 free(buffer);
819                 buffer = NULL;
820         }
821
822         return TRUE;
823 }
824
825 /****************************************************************************
826 ****************************************************************************/
827
828 static BOOL test_GetPrinterDriverDirectory(struct torture_context *tctx,
829                                            LPSTR servername,
830                                            LPSTR architecture)
831 {
832         DWORD levels[]  = { 1 };
833         DWORD success[] = { 1 };
834         DWORD i;
835         LPBYTE buffer = NULL;
836
837         for (i=0; i < ARRAY_SIZE(levels); i++) {
838
839                 DWORD needed = 0;
840                 DWORD err = 0;
841                 char tmp[1024];
842
843                 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %d", levels[i]);
844
845                 GetPrinterDriverDirectory(servername, architecture, levels[i], NULL, 0, &needed);
846                 err = GetLastError();
847                 if (err == ERROR_INSUFFICIENT_BUFFER) {
848                         err = 0;
849                         buffer = malloc(needed);
850                         torture_assert(tctx, buffer, "malloc failed");
851                         if (!GetPrinterDriverDirectory(servername, architecture, levels[i], buffer, needed, &needed)) {
852                                 err = GetLastError();
853                         }
854                 }
855                 if (err) {
856                         sprintf(tmp, "GetPrinterDriverDirectory failed level %d on [%s] (buffer size = %d), error: %s\n",
857                                 levels[i], servername, needed, errstr(err));
858                         if (success[i]) {
859                                 torture_fail(tctx, tmp);
860                         } else {
861                                 torture_warning(tctx, tmp);
862                         }
863                 }
864
865                 free(buffer);
866                 buffer = NULL;
867         }
868
869         return TRUE;
870 }
871
872 /****************************************************************************
873 ****************************************************************************/
874
875 static BOOL test_GetPrinterData(struct torture_context *tctx,
876                                 LPSTR servername,
877                                 LPSTR valuename,
878                                 HANDLE handle,
879                                 DWORD *type_p,
880                                 LPBYTE *buffer_p,
881                                 DWORD *size_p)
882 {
883         LPBYTE buffer = NULL;
884         DWORD needed = 0;
885         DWORD type;
886         DWORD err = 0;
887         char tmp[1024];
888
889         torture_comment(tctx, "Testing GetPrinterData(%s)", valuename);
890
891         err = GetPrinterData(handle, valuename, &type, NULL, 0, &needed);
892         if (err == ERROR_MORE_DATA) {
893                 buffer = (LPBYTE)malloc(needed);
894                 torture_assert(tctx, buffer, "malloc failed");
895                 err = GetPrinterData(handle, valuename, &type, buffer, needed, &needed);
896         }
897         if (err) {
898                 sprintf(tmp, "GetPrinterData(%s) failed on [%s] (buffer size = %d), error: %s\n",
899                         valuename, servername, needed, errstr(err));
900                 torture_fail(tctx, tmp);
901         }
902
903         if (tctx->print) {
904                 print_printer_data("PrinterDriverData", valuename, needed, buffer, type);
905         }
906
907         if (type_p) {
908                 *type_p = type;
909         }
910
911         if (size_p) {
912                 *size_p = needed;
913         }
914
915         if (buffer_p) {
916                 *buffer_p = buffer;
917         } else {
918                 free(buffer);
919         }
920
921         return TRUE;
922 }
923
924 /****************************************************************************
925 ****************************************************************************/
926
927 static BOOL test_GetPrinterDataEx(struct torture_context *tctx,
928                                   LPSTR servername,
929                                   LPSTR keyname,
930                                   LPSTR valuename,
931                                   HANDLE handle,
932                                   DWORD *type_p,
933                                   LPBYTE *buffer_p,
934                                   DWORD *size_p)
935 {
936         LPBYTE buffer = NULL;
937         DWORD needed = 0;
938         DWORD type;
939         DWORD err = 0;
940         char tmp[1024];
941
942         torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)", keyname, valuename);
943
944         err = GetPrinterDataEx(handle, keyname, valuename, &type, NULL, 0, &needed);
945         if (err == ERROR_MORE_DATA) {
946                 buffer = (LPBYTE)malloc(needed);
947                 torture_assert(tctx, buffer, "malloc failed");
948                 err = GetPrinterDataEx(handle, keyname, valuename, &type, buffer, needed, &needed);
949         }
950         if (err) {
951                 sprintf(tmp, "GetPrinterDataEx(%s) failed on [%s] (buffer size = %d), error: %s\n",
952                         valuename, servername, needed, errstr(err));
953                 torture_fail(tctx, tmp);
954         }
955
956         if (tctx->print) {
957                 print_printer_data(keyname, valuename, needed, buffer, type);
958         }
959
960         if (type_p) {
961                 *type_p = type;
962         }
963
964         if (size_p) {
965                 *size_p = needed;
966         }
967
968         if (buffer_p) {
969                 *buffer_p = buffer;
970         } else {
971                 free(buffer);
972         }
973
974         return TRUE;
975 }
976
977 /****************************************************************************
978 ****************************************************************************/
979
980 static BOOL test_PrinterData(struct torture_context *tctx,
981                              LPSTR servername,
982                              HANDLE handle)
983 {
984         BOOL ret = TRUE;
985         DWORD i;
986         DWORD type, type_ex;
987         LPBYTE buffer, buffer_ex;
988         DWORD size, size_ex;
989         LPSTR valuenames[] = {
990                 SPLREG_DEFAULT_SPOOL_DIRECTORY,
991                 SPLREG_MAJOR_VERSION,
992                 SPLREG_MINOR_VERSION,
993                 SPLREG_DS_PRESENT,
994                 SPLREG_DNS_MACHINE_NAME,
995                 SPLREG_ARCHITECTURE,
996                 SPLREG_OS_VERSION
997         };
998
999         for (i=0; i < ARRAY_SIZE(valuenames); i++) {
1000                 ret &= test_GetPrinterData(tctx, servername, valuenames[i], handle, &type, &buffer, &size);
1001                 ret &= test_GetPrinterDataEx(tctx, servername, "random", valuenames[i], handle, &type_ex, &buffer_ex, &size_ex);
1002                 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
1003                 torture_assert_int_equal(tctx, size, size_ex, "size mismatch");
1004                 torture_assert_mem_equal(tctx, buffer, buffer_ex, size, "buffer mismatch");
1005                 free(buffer);
1006                 free(buffer_ex);
1007         }
1008
1009         return ret;
1010 }
1011
1012 /****************************************************************************
1013 ****************************************************************************/
1014
1015 int main(int argc, char *argv[])
1016 {
1017         BOOL ret = FALSE;
1018         LPSTR servername;
1019         LPSTR architecture = "Windows NT x86";
1020         HANDLE server_handle;
1021         PRINTER_DEFAULTS defaults_admin, defaults_use;
1022         struct torture_context *tctx;
1023
1024         if (argc < 2) {
1025                 fprintf(stderr, "usage: %s <servername> [print]\n", argv[0]);
1026                 exit(-1);
1027         }
1028
1029         tctx = malloc(sizeof(struct torture_context));
1030         if (!tctx) {
1031                 fprintf(stderr, "out of memory\n");
1032                 exit(-1);
1033         }
1034         memset(tctx, '\0', sizeof(*tctx));
1035
1036         servername = argv[1];
1037
1038         if (argc >= 3) {
1039                 if (strcmp(argv[2], "print") == 0) {
1040                         tctx->print = TRUE;
1041                 }
1042         }
1043
1044         defaults_admin.pDatatype = NULL;
1045         defaults_admin.pDevMode = NULL;
1046         defaults_admin.DesiredAccess = PRINTER_ACCESS_ADMINISTER;
1047
1048         defaults_use.pDatatype = NULL;
1049         defaults_use.pDevMode = NULL;
1050         defaults_use.DesiredAccess = PRINTER_ACCESS_USE;
1051
1052         ret &= test_EnumPrinters(tctx, servername);
1053         ret &= test_EnumDrivers(tctx, servername, architecture);
1054         ret &= test_OpenPrinter(tctx, servername, NULL, &server_handle);
1055 /*      ret &= test_EnumPrinterKey(tctx, servername, server_handle, ""); */
1056         ret &= test_PrinterData(tctx, servername, server_handle);
1057         ret &= test_EnumForms(tctx, servername, server_handle);
1058         ret &= test_ClosePrinter(tctx, server_handle);
1059         ret &= test_EnumPorts(tctx, servername);
1060         ret &= test_EnumMonitors(tctx, servername);
1061         ret &= test_EnumPrintProcessors(tctx, servername, architecture);
1062         ret &= test_EnumPrintProcessorDatatypes(tctx, servername);
1063         ret &= test_GetPrintProcessorDirectory(tctx, servername, architecture);
1064         ret &= test_GetPrinterDriverDirectory(tctx, servername, architecture);
1065         ret &= test_EachPrinter(tctx, servername, architecture, NULL);
1066
1067         if (!ret) {
1068                 if (tctx->last_reason) {
1069                         fprintf(stderr, "failed: %s\n", tctx->last_reason);
1070                 }
1071                 free(tctx);
1072                 return -1;
1073         }
1074
1075         printf("%s run successfully\n", argv[0]);
1076
1077         free(tctx);
1078         return 0;
1079 }