testprogs: add tests for GetPrinterData{Ex} and EnumPrinterDataEx.
[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                 free(buffer);
161                 buffer = NULL;
162         }
163
164         return TRUE;
165 }
166
167 /****************************************************************************
168 ****************************************************************************/
169
170 static BOOL test_GetForm(struct torture_context *tctx,
171                          LPSTR servername,
172                          HANDLE handle,
173                          LPSTR formname)
174 {
175         DWORD levels[]  = { 1, 2 };
176         DWORD success[] = { 1, 0 };
177         DWORD i;
178         LPBYTE buffer = NULL;
179
180         for (i=0; i < ARRAY_SIZE(levels); i++) {
181
182                 DWORD needed = 0;
183                 DWORD err = 0;
184                 char tmp[1024];
185
186                 torture_comment(tctx, "Testing GetForm(%s) level %d", formname, levels[i]);
187
188                 GetForm(handle, formname, levels[i], NULL, 0, &needed);
189                 err = GetLastError();
190                 if (err == ERROR_INSUFFICIENT_BUFFER) {
191                         err = 0;
192                         buffer = malloc(needed);
193                         torture_assert(tctx, buffer, "malloc failed");
194                         if (!GetForm(handle, formname, levels[i], buffer, needed, &needed)) {
195                                 err = GetLastError();
196                         }
197                 }
198                 if (err) {
199                         sprintf(tmp, "GetForm failed level %d on [%s] (buffer size = %d), error: %s\n",
200                                 levels[i], servername, needed, errstr(err));
201                         if (success[i]) {
202                                 torture_fail(tctx, tmp);
203                         } else {
204                                 torture_warning(tctx, tmp);
205                         }
206                 }
207
208                 free(buffer);
209                 buffer = NULL;
210         }
211
212         return TRUE;
213 }
214
215 /****************************************************************************
216 ****************************************************************************/
217
218 static BOOL test_EnumForms(struct torture_context *tctx,
219                            LPSTR servername,
220                            HANDLE handle)
221 {
222         DWORD levels[]  = { 1, 2 };
223         DWORD success[] = { 1, 0 };
224         DWORD i;
225         LPBYTE buffer = NULL;
226
227         for (i=0; i < ARRAY_SIZE(levels); i++) {
228
229                 DWORD needed = 0;
230                 DWORD returned = 0;
231                 DWORD err = 0;
232                 char tmp[1024];
233
234                 torture_comment(tctx, "Testing EnumForms level %d", levels[i]);
235
236                 EnumForms(handle, levels[i], NULL, 0, &needed, &returned);
237                 err = GetLastError();
238                 if (err == ERROR_INSUFFICIENT_BUFFER) {
239                         err = 0;
240                         buffer = malloc(needed);
241                         torture_assert(tctx, buffer, "malloc failed");
242                         if (!EnumForms(handle, levels[i], buffer, needed, &needed, &returned)) {
243                                 err = GetLastError();
244                         }
245                 }
246                 if (err) {
247                         sprintf(tmp, "EnumForms failed level %d on [%s] (buffer size = %d), error: %s\n",
248                                 levels[i], servername, needed, errstr(err));
249                         if (success[i]) {
250                                 torture_fail(tctx, tmp);
251                         } else {
252                                 torture_warning(tctx, tmp);
253                         }
254                 }
255
256                 free(buffer);
257                 buffer = NULL;
258         }
259
260         return TRUE;
261 }
262
263 /****************************************************************************
264 ****************************************************************************/
265
266 static BOOL test_EnumPorts(struct torture_context *tctx,
267                            LPSTR servername)
268 {
269         DWORD levels[]  = { 1, 2 };
270         DWORD success[] = { 1, 1 };
271         DWORD i;
272         LPBYTE buffer = NULL;
273
274         for (i=0; i < ARRAY_SIZE(levels); i++) {
275
276                 DWORD needed = 0;
277                 DWORD returned = 0;
278                 DWORD err = 0;
279                 char tmp[1024];
280
281                 torture_comment(tctx, "Testing EnumPorts level %d", levels[i]);
282
283                 EnumPorts(servername, levels[i], NULL, 0, &needed, &returned);
284                 err = GetLastError();
285                 if (err == ERROR_INSUFFICIENT_BUFFER) {
286                         err = 0;
287                         buffer = malloc(needed);
288                         torture_assert(tctx, buffer, "malloc failed");
289                         if (!EnumPorts(servername, levels[i], buffer, needed, &needed, &returned)) {
290                                 err = GetLastError();
291                         }
292                 }
293                 if (err) {
294                         sprintf(tmp, "EnumPorts failed level %d on [%s] (buffer size = %d), error: %s\n",
295                                 levels[i], servername, needed, errstr(err));
296                         if (success[i]) {
297                                 torture_fail(tctx, tmp);
298                         } else {
299                                 torture_warning(tctx, tmp);
300                         }
301                 }
302
303                 free(buffer);
304                 buffer = NULL;
305         }
306
307         return TRUE;
308 }
309
310 /****************************************************************************
311 ****************************************************************************/
312
313 static BOOL test_EnumMonitors(struct torture_context *tctx,
314                               LPSTR servername)
315 {
316         DWORD levels[]  = { 1, 2 };
317         DWORD success[] = { 1, 1 };
318         DWORD i;
319         LPBYTE buffer = NULL;
320
321         for (i=0; i < ARRAY_SIZE(levels); i++) {
322
323                 DWORD needed = 0;
324                 DWORD returned = 0;
325                 DWORD err = 0;
326                 char tmp[1024];
327
328                 torture_comment(tctx, "Testing EnumMonitors level %d", levels[i]);
329
330                 EnumMonitors(servername, levels[i], NULL, 0, &needed, &returned);
331                 err = GetLastError();
332                 if (err == ERROR_INSUFFICIENT_BUFFER) {
333                         err = 0;
334                         buffer = malloc(needed);
335                         torture_assert(tctx, buffer, "malloc failed");
336                         if (!EnumMonitors(servername, levels[i], buffer, needed, &needed, &returned)) {
337                                 err = GetLastError();
338                         }
339                 }
340                 if (err) {
341                         sprintf(tmp, "EnumMonitors failed level %d on [%s] (buffer size = %d), error: %s\n",
342                                 levels[i], servername, needed, errstr(err));
343                         if (success[i]) {
344                                 torture_fail(tctx, tmp);
345                         } else {
346                                 torture_warning(tctx, tmp);
347                         }
348                 }
349
350                 free(buffer);
351                 buffer = NULL;
352         }
353
354         return TRUE;
355 }
356
357 /****************************************************************************
358 ****************************************************************************/
359
360 static BOOL test_EnumPrintProcessors(struct torture_context *tctx,
361                                      LPSTR servername,
362                                      LPSTR architecture)
363 {
364         DWORD levels[]  = { 1 };
365         DWORD success[] = { 1 };
366         DWORD i;
367         LPBYTE buffer = NULL;
368
369         for (i=0; i < ARRAY_SIZE(levels); i++) {
370
371                 DWORD needed = 0;
372                 DWORD returned = 0;
373                 DWORD err = 0;
374                 char tmp[1024];
375
376                 torture_comment(tctx, "Testing EnumPrintProcessors level %d", levels[i]);
377
378                 EnumPrintProcessors(servername, architecture, levels[i], NULL, 0, &needed, &returned);
379                 err = GetLastError();
380                 if (err == ERROR_INSUFFICIENT_BUFFER) {
381                         err = 0;
382                         buffer = malloc(needed);
383                         torture_assert(tctx, buffer, "malloc failed");
384                         if (!EnumPrintProcessors(servername, architecture, levels[i], buffer, needed, &needed, &returned)) {
385                                 err = GetLastError();
386                         }
387                 }
388                 if (err) {
389                         sprintf(tmp, "EnumPrintProcessors failed level %d on [%s] (buffer size = %d), error: %s\n",
390                                 levels[i], servername, needed, errstr(err));
391                         if (success[i]) {
392                                 torture_fail(tctx, tmp);
393                         } else {
394                                 torture_warning(tctx, tmp);
395                         }
396                 }
397
398                 free(buffer);
399                 buffer = NULL;
400         }
401
402         return TRUE;
403 }
404
405 /****************************************************************************
406 ****************************************************************************/
407
408 static BOOL test_EnumPrintProcessorDatatypes(struct torture_context *tctx,
409                                              LPSTR servername)
410 {
411         DWORD levels[]  = { 1 };
412         DWORD success[] = { 1 };
413         DWORD i;
414         LPBYTE buffer = NULL;
415
416         for (i=0; i < ARRAY_SIZE(levels); i++) {
417
418                 DWORD needed = 0;
419                 DWORD returned = 0;
420                 DWORD err = 0;
421                 char tmp[1024];
422
423                 torture_comment(tctx, "Testing EnumPrintProcessorDatatypes level %d", levels[i]);
424
425                 EnumPrintProcessorDatatypes(servername, "winprint", levels[i], NULL, 0, &needed, &returned);
426                 err = GetLastError();
427                 if (err == ERROR_INSUFFICIENT_BUFFER) {
428                         err = 0;
429                         buffer = malloc(needed);
430                         torture_assert(tctx, buffer, "malloc failed");
431                         if (!EnumPrintProcessorDatatypes(servername, "winprint", levels[i], buffer, needed, &needed, &returned)) {
432                                 err = GetLastError();
433                         }
434                 }
435                 if (err) {
436                         sprintf(tmp, "EnumPrintProcessorDatatypes failed level %d on [%s] (buffer size = %d), error: %s\n",
437                                 levels[i], servername, needed, errstr(err));
438                         if (success[i]) {
439                                 torture_fail(tctx, tmp);
440                         } else {
441                                 torture_warning(tctx, tmp);
442                         }
443                 }
444
445                 free(buffer);
446                 buffer = NULL;
447         }
448
449         return TRUE;
450 }
451
452 /****************************************************************************
453 ****************************************************************************/
454
455 static BOOL test_EnumPrinterKey(struct torture_context *tctx,
456                                 LPSTR servername,
457                                 HANDLE handle,
458                                 LPCSTR key)
459 {
460         LPSTR buffer = NULL;
461         DWORD needed = 0;
462         DWORD err = 0;
463         char tmp[1024];
464
465         torture_comment(tctx, "Testing EnumPrinterKey(%s)", key);
466
467         err = EnumPrinterKey(handle, key, NULL, 0, &needed);
468         if (err == ERROR_MORE_DATA) {
469                 buffer = (LPTSTR)malloc(needed);
470                 torture_assert(tctx, buffer, "malloc failed");
471                 err = EnumPrinterKey(handle, key, buffer, needed, &needed);
472         }
473         if (err) {
474                 sprintf(tmp, "EnumPrinterKey(%s) failed on [%s] (buffer size = %d), error: %s\n",
475                         key, servername, needed, errstr(err));
476                 torture_fail(tctx, tmp);
477         }
478
479         if (tctx->print) {
480                 print_printer_keys(buffer);
481         }
482
483         free(buffer);
484
485         return TRUE;
486 }
487
488 /****************************************************************************
489 ****************************************************************************/
490
491 static BOOL test_GetPrinter(struct torture_context *tctx,
492                             LPSTR printername,
493                             HANDLE handle)
494 {
495         DWORD levels[]  = { 1, 2, 3, 4, 5, 6, 7, 8 };
496         DWORD success[] = { 1, 1, 1, 1, 1, 1, 1, 1 };
497         DWORD i;
498         LPBYTE buffer = NULL;
499
500         for (i=0; i < ARRAY_SIZE(levels); i++) {
501
502                 DWORD needed = 0;
503                 DWORD err = 0;
504                 char tmp[1024];
505
506                 torture_comment(tctx, "Testing GetPrinter level %d", levels[i]);
507
508                 GetPrinter(handle, levels[i], NULL, 0, &needed);
509                 err = GetLastError();
510                 if (err == ERROR_INSUFFICIENT_BUFFER) {
511                         err = 0;
512                         buffer = malloc(needed);
513                         torture_assert(tctx, buffer, "malloc failed");
514                         if (!GetPrinter(handle, levels[i], buffer, needed, &needed)) {
515                                 err = GetLastError();
516                         }
517                 }
518                 if (err) {
519                         sprintf(tmp, "GetPrinter failed level %d on [%s] (buffer size = %d), error: %s\n",
520                                 levels[i], printername, needed, errstr(err));
521                         if (success[i]) {
522                                 torture_fail(tctx, tmp);
523                         } else {
524                                 torture_warning(tctx, tmp);
525                         }
526                 }
527
528                 free(buffer);
529                 buffer = NULL;
530         }
531
532         return TRUE;
533 }
534
535 /****************************************************************************
536 ****************************************************************************/
537
538 static BOOL test_GetPrinterDriver(struct torture_context *tctx,
539                                   LPSTR printername,
540                                   LPSTR architecture,
541                                   HANDLE handle)
542 {
543         DWORD levels[]  = { 1, 2, 3, 4, 5, 6, 8 };
544         DWORD success[] = { 1, 1, 1, 1, 1, 1, 1 };
545         DWORD i;
546         LPBYTE buffer = NULL;
547
548         for (i=0; i < ARRAY_SIZE(levels); i++) {
549
550                 DWORD needed = 0;
551                 DWORD err = 0;
552                 char tmp[1024];
553
554                 torture_comment(tctx, "Testing GetPrinterDriver level %d", levels[i]);
555
556                 GetPrinterDriver(handle, architecture, levels[i], NULL, 0, &needed);
557                 err = GetLastError();
558                 if (err == ERROR_INSUFFICIENT_BUFFER) {
559                         err = 0;
560                         buffer = malloc(needed);
561                         torture_assert(tctx, buffer, "malloc failed");
562                         if (!GetPrinterDriver(handle, architecture, levels[i], buffer, needed, &needed)) {
563                                 err = GetLastError();
564                         }
565                 }
566                 if (err) {
567                         sprintf(tmp, "GetPrinterDriver failed level %d on [%s] (buffer size = %d), error: %s\n",
568                                 levels[i], printername, needed, errstr(err));
569                         if (success[i]) {
570                                 torture_fail(tctx, tmp);
571                         } else {
572                                 torture_warning(tctx, tmp);
573                         }
574                 }
575
576                 free(buffer);
577                 buffer = NULL;
578         }
579
580         return TRUE;
581 }
582
583
584 /****************************************************************************
585 ****************************************************************************/
586
587 static BOOL test_EnumJobs(struct torture_context *tctx,
588                           LPSTR printername,
589                           HANDLE handle)
590 {
591         DWORD levels[]  = { 1, 2, 3, 4 };
592         DWORD success[] = { 1, 1, 1, 1 };
593         DWORD i;
594         LPBYTE buffer = NULL;
595
596         for (i=0; i < ARRAY_SIZE(levels); i++) {
597
598                 DWORD needed = 0;
599                 DWORD returned = 0;
600                 DWORD err = 0;
601                 char tmp[1024];
602
603                 torture_comment(tctx, "Testing EnumJobs level %d", levels[i]);
604
605                 EnumJobs(handle, 0, 100, levels[i], NULL, 0, &needed, &returned);
606                 err = GetLastError();
607                 if (err == ERROR_INSUFFICIENT_BUFFER) {
608                         err = 0;
609                         buffer = malloc(needed);
610                         torture_assert(tctx, buffer, "malloc failed");
611                         if (!EnumJobs(handle, 0, 100, levels[i], buffer, needed, &needed, &returned)) {
612                                 err = GetLastError();
613                         }
614                 }
615                 if (err) {
616                         sprintf(tmp, "EnumJobs failed level %d on [%s] (buffer size = %d), error: %s\n",
617                                 levels[i], printername, needed, errstr(err));
618                         if (success[i]) {
619                                 torture_fail(tctx, tmp);
620                         } else {
621                                 torture_warning(tctx, tmp);
622                         }
623                 }
624
625                 free(buffer);
626                 buffer = NULL;
627         }
628
629         return TRUE;
630 }
631
632 /****************************************************************************
633 ****************************************************************************/
634
635 static BOOL test_EnumPrinterDataEx(struct torture_context *tctx,
636                                    LPSTR servername,
637                                    LPSTR keyname,
638                                    HANDLE handle,
639                                    LPBYTE *buffer_p,
640                                    DWORD *returned_p)
641 {
642         LPBYTE buffer = NULL;
643         DWORD needed = 0;
644         DWORD returned = 0;
645         DWORD err = 0;
646         char tmp[1024];
647
648         torture_comment(tctx, "Testing EnumPrinterDataEx(%s)", keyname);
649
650         err = EnumPrinterDataEx(handle, keyname, NULL, 0, &needed, &returned);
651         if (err == ERROR_MORE_DATA) {
652                 buffer = malloc(needed);
653                 torture_assert(tctx, buffer, "malloc failed");
654                 err = EnumPrinterDataEx(handle, keyname, buffer, needed, &needed, &returned);
655         }
656         if (err) {
657                 sprintf(tmp, "EnumPrinterDataEx(%s) failed on [%s] (buffer size = %d), error: %s\n",
658                         keyname, servername, needed, errstr(err));
659                 torture_fail(tctx, tmp);
660         }
661
662         if (tctx->print) {
663                 DWORD i;
664                 LPPRINTER_ENUM_VALUES v = (LPPRINTER_ENUM_VALUES)buffer;
665                 for (i=0; i < returned; i++) {
666                         print_printer_enum_values(&v[i]);
667                 }
668         }
669
670         if (returned_p) {
671                 *returned_p = returned;
672         }
673
674         if (buffer_p) {
675                 *buffer_p = buffer;
676         } else {
677                 free(buffer);
678         }
679
680         return TRUE;
681 }
682
683
684 /****************************************************************************
685 ****************************************************************************/
686
687 static BOOL test_OnePrinter(struct torture_context *tctx,
688                             LPSTR printername,
689                             LPSTR architecture,
690                             LPPRINTER_DEFAULTS defaults)
691 {
692         HANDLE handle;
693         BOOL ret = TRUE;
694
695         torture_comment(tctx, "Testing Printer %s", printername);
696
697         ret &= test_OpenPrinter(tctx, printername, defaults, &handle);
698         ret &= test_GetPrinter(tctx, printername, handle);
699         ret &= test_GetPrinterDriver(tctx, printername, architecture, handle);
700         ret &= test_EnumForms(tctx, printername, handle);
701         ret &= test_EnumJobs(tctx, printername, handle);
702         ret &= test_EnumPrinterKey(tctx, printername, handle, "");
703         ret &= test_EnumPrinterKey(tctx, printername, handle, "PrinterDriverData");
704         ret &= test_EnumPrinterDataEx(tctx, printername, "PrinterDriverData", handle, NULL, NULL);
705         ret &= test_ClosePrinter(tctx, handle);
706
707         return ret;
708 }
709
710 /****************************************************************************
711 ****************************************************************************/
712
713 static BOOL test_EachPrinter(struct torture_context *tctx,
714                              LPSTR servername,
715                              LPSTR architecture,
716                              LPPRINTER_DEFAULTS defaults)
717 {
718         DWORD needed = 0;
719         DWORD returned = 0;
720         DWORD err = 0;
721         char tmp[1024];
722         DWORD i;
723         DWORD flags = PRINTER_ENUM_NAME;
724         PPRINTER_INFO_1 buffer = NULL;
725         BOOL ret = TRUE;
726
727         torture_comment(tctx, "Testing EnumPrinters level %d", 1);
728
729         EnumPrinters(flags, servername, 1, NULL, 0, &needed, &returned);
730         err = GetLastError();
731         if (err == ERROR_INSUFFICIENT_BUFFER) {
732                 err = 0;
733                 buffer = (PPRINTER_INFO_1)malloc(needed);
734                 torture_assert(tctx, buffer, "malloc failed");
735                 if (!EnumPrinters(flags, servername, 1, (LPBYTE)buffer, needed, &needed, &returned)) {
736                         err = GetLastError();
737                 }
738         }
739         if (err) {
740                 sprintf(tmp, "EnumPrinters failed level %d on [%s] (buffer size = %d), error: %s\n",
741                         1, servername, needed, errstr(err));
742                 torture_fail(tctx, tmp);
743         }
744
745         for (i=0; i < returned; i++) {
746                 ret &= test_OnePrinter(tctx, buffer[i].pName, architecture, defaults);
747         }
748
749         free(buffer);
750
751         return ret;
752 }
753
754 /****************************************************************************
755 ****************************************************************************/
756
757 static BOOL test_GetPrintProcessorDirectory(struct torture_context *tctx,
758                                             LPSTR servername,
759                                             LPSTR architecture)
760 {
761         DWORD levels[]  = { 1 };
762         DWORD success[] = { 1 };
763         DWORD i;
764         LPBYTE buffer = NULL;
765
766         for (i=0; i < ARRAY_SIZE(levels); i++) {
767
768                 DWORD needed = 0;
769                 DWORD err = 0;
770                 char tmp[1024];
771
772                 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %d", levels[i]);
773
774                 GetPrintProcessorDirectory(servername, architecture, levels[i], NULL, 0, &needed);
775                 err = GetLastError();
776                 if (err == ERROR_INSUFFICIENT_BUFFER) {
777                         err = 0;
778                         buffer = malloc(needed);
779                         torture_assert(tctx, buffer, "malloc failed");
780                         if (!GetPrintProcessorDirectory(servername, architecture, levels[i], buffer, needed, &needed)) {
781                                 err = GetLastError();
782                         }
783                 }
784                 if (err) {
785                         sprintf(tmp, "GetPrintProcessorDirectory failed level %d on [%s] (buffer size = %d), error: %s\n",
786                                 levels[i], servername, needed, errstr(err));
787                         if (success[i]) {
788                                 torture_fail(tctx, tmp);
789                         } else {
790                                 torture_warning(tctx, tmp);
791                         }
792                 }
793
794                 free(buffer);
795                 buffer = NULL;
796         }
797
798         return TRUE;
799 }
800
801 /****************************************************************************
802 ****************************************************************************/
803
804 static BOOL test_GetPrinterDriverDirectory(struct torture_context *tctx,
805                                            LPSTR servername,
806                                            LPSTR architecture)
807 {
808         DWORD levels[]  = { 1 };
809         DWORD success[] = { 1 };
810         DWORD i;
811         LPBYTE buffer = NULL;
812
813         for (i=0; i < ARRAY_SIZE(levels); i++) {
814
815                 DWORD needed = 0;
816                 DWORD err = 0;
817                 char tmp[1024];
818
819                 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %d", levels[i]);
820
821                 GetPrinterDriverDirectory(servername, architecture, levels[i], NULL, 0, &needed);
822                 err = GetLastError();
823                 if (err == ERROR_INSUFFICIENT_BUFFER) {
824                         err = 0;
825                         buffer = malloc(needed);
826                         torture_assert(tctx, buffer, "malloc failed");
827                         if (!GetPrinterDriverDirectory(servername, architecture, levels[i], buffer, needed, &needed)) {
828                                 err = GetLastError();
829                         }
830                 }
831                 if (err) {
832                         sprintf(tmp, "GetPrinterDriverDirectory failed level %d on [%s] (buffer size = %d), error: %s\n",
833                                 levels[i], servername, needed, errstr(err));
834                         if (success[i]) {
835                                 torture_fail(tctx, tmp);
836                         } else {
837                                 torture_warning(tctx, tmp);
838                         }
839                 }
840
841                 free(buffer);
842                 buffer = NULL;
843         }
844
845         return TRUE;
846 }
847
848 /****************************************************************************
849 ****************************************************************************/
850
851 static BOOL test_GetPrinterData(struct torture_context *tctx,
852                                 LPSTR servername,
853                                 LPSTR valuename,
854                                 HANDLE handle,
855                                 DWORD *type_p,
856                                 LPBYTE *buffer_p,
857                                 DWORD *size_p)
858 {
859         LPBYTE buffer = NULL;
860         DWORD needed = 0;
861         DWORD type;
862         DWORD err = 0;
863         char tmp[1024];
864
865         torture_comment(tctx, "Testing GetPrinterData(%s)", valuename);
866
867         err = GetPrinterData(handle, valuename, &type, NULL, 0, &needed);
868         if (err == ERROR_MORE_DATA) {
869                 buffer = (LPBYTE)malloc(needed);
870                 torture_assert(tctx, buffer, "malloc failed");
871                 err = GetPrinterData(handle, valuename, &type, buffer, needed, &needed);
872         }
873         if (err) {
874                 sprintf(tmp, "GetPrinterData(%s) failed on [%s] (buffer size = %d), error: %s\n",
875                         valuename, servername, needed, errstr(err));
876                 torture_fail(tctx, tmp);
877         }
878
879         if (tctx->print) {
880                 print_printer_data("PrinterDriverData", valuename, needed, buffer, type);
881         }
882
883         if (type_p) {
884                 *type_p = type;
885         }
886
887         if (size_p) {
888                 *size_p = needed;
889         }
890
891         if (buffer_p) {
892                 *buffer_p = buffer;
893         } else {
894                 free(buffer);
895         }
896
897         return TRUE;
898 }
899
900 /****************************************************************************
901 ****************************************************************************/
902
903 static BOOL test_GetPrinterDataEx(struct torture_context *tctx,
904                                   LPSTR servername,
905                                   LPSTR keyname,
906                                   LPSTR valuename,
907                                   HANDLE handle,
908                                   DWORD *type_p,
909                                   LPBYTE *buffer_p,
910                                   DWORD *size_p)
911 {
912         LPBYTE buffer = NULL;
913         DWORD needed = 0;
914         DWORD type;
915         DWORD err = 0;
916         char tmp[1024];
917
918         torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)", keyname, valuename);
919
920         err = GetPrinterDataEx(handle, keyname, valuename, &type, NULL, 0, &needed);
921         if (err == ERROR_MORE_DATA) {
922                 buffer = (LPBYTE)malloc(needed);
923                 torture_assert(tctx, buffer, "malloc failed");
924                 err = GetPrinterDataEx(handle, keyname, valuename, &type, buffer, needed, &needed);
925         }
926         if (err) {
927                 sprintf(tmp, "GetPrinterDataEx(%s) failed on [%s] (buffer size = %d), error: %s\n",
928                         valuename, servername, needed, errstr(err));
929                 torture_fail(tctx, tmp);
930         }
931
932         if (tctx->print) {
933                 print_printer_data(keyname, valuename, needed, buffer, type);
934         }
935
936         if (type_p) {
937                 *type_p = type;
938         }
939
940         if (size_p) {
941                 *size_p = needed;
942         }
943
944         if (buffer_p) {
945                 *buffer_p = buffer;
946         } else {
947                 free(buffer);
948         }
949
950         return TRUE;
951 }
952
953 /****************************************************************************
954 ****************************************************************************/
955
956 static BOOL test_PrinterData(struct torture_context *tctx,
957                              LPSTR servername,
958                              HANDLE handle)
959 {
960         BOOL ret = TRUE;
961         DWORD i;
962         DWORD type, type_ex;
963         LPBYTE buffer, buffer_ex;
964         DWORD size, size_ex;
965         LPSTR valuenames[] = {
966                 SPLREG_DEFAULT_SPOOL_DIRECTORY,
967                 SPLREG_MAJOR_VERSION,
968                 SPLREG_MINOR_VERSION,
969                 SPLREG_DS_PRESENT,
970                 SPLREG_DNS_MACHINE_NAME,
971                 SPLREG_ARCHITECTURE,
972                 SPLREG_OS_VERSION
973         };
974
975         for (i=0; i < ARRAY_SIZE(valuenames); i++) {
976                 ret &= test_GetPrinterData(tctx, servername, valuenames[i], handle, &type, &buffer, &size);
977                 ret &= test_GetPrinterDataEx(tctx, servername, "random", valuenames[i], handle, &type_ex, &buffer_ex, &size_ex);
978                 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
979                 torture_assert_int_equal(tctx, size, size_ex, "size mismatch");
980                 torture_assert_mem_equal(tctx, buffer, buffer_ex, size, "buffer mismatch");
981                 free(buffer);
982                 free(buffer_ex);
983         }
984
985         return ret;
986 }
987
988 /****************************************************************************
989 ****************************************************************************/
990
991 int main(int argc, char *argv[])
992 {
993         BOOL ret = FALSE;
994         LPSTR servername;
995         LPSTR architecture = "Windows NT x86";
996         HANDLE server_handle;
997         PRINTER_DEFAULTS defaults_admin, defaults_use;
998         struct torture_context *tctx;
999
1000         if (argc < 2) {
1001                 fprintf(stderr, "usage: %s <servername> [print]\n", argv[0]);
1002                 exit(-1);
1003         }
1004
1005         tctx = malloc(sizeof(struct torture_context));
1006         if (!tctx) {
1007                 fprintf(stderr, "out of memory\n");
1008                 exit(-1);
1009         }
1010         memset(tctx, '\0', sizeof(*tctx));
1011
1012         servername = argv[1];
1013
1014         if (argc >= 3) {
1015                 if (strcmp(argv[2], "print") == 0) {
1016                         tctx->print = TRUE;
1017                 }
1018         }
1019
1020         defaults_admin.pDatatype = NULL;
1021         defaults_admin.pDevMode = NULL;
1022         defaults_admin.DesiredAccess = PRINTER_ACCESS_ADMINISTER;
1023
1024         defaults_use.pDatatype = NULL;
1025         defaults_use.pDevMode = NULL;
1026         defaults_use.DesiredAccess = PRINTER_ACCESS_USE;
1027
1028         ret &= test_EnumPrinters(tctx, servername);
1029         ret &= test_EnumDrivers(tctx, servername, architecture);
1030         ret &= test_OpenPrinter(tctx, servername, NULL, &server_handle);
1031 /*      ret &= test_EnumPrinterKey(tctx, servername, server_handle, ""); */
1032         ret &= test_PrinterData(tctx, servername, server_handle);
1033         ret &= test_EnumForms(tctx, servername, server_handle);
1034         ret &= test_ClosePrinter(tctx, server_handle);
1035         ret &= test_EnumPorts(tctx, servername);
1036         ret &= test_EnumMonitors(tctx, servername);
1037         ret &= test_EnumPrintProcessors(tctx, servername, architecture);
1038         ret &= test_EnumPrintProcessorDatatypes(tctx, servername);
1039         ret &= test_GetPrintProcessorDirectory(tctx, servername, architecture);
1040         ret &= test_GetPrinterDriverDirectory(tctx, servername, architecture);
1041         ret &= test_EachPrinter(tctx, servername, architecture, NULL);
1042
1043         if (!ret) {
1044                 if (tctx->last_reason) {
1045                         fprintf(stderr, "failed: %s\n", tctx->last_reason);
1046                 }
1047                 free(tctx);
1048                 return -1;
1049         }
1050
1051         printf("%s run successfully\n", argv[0]);
1052
1053         free(tctx);
1054         return 0;
1055 }