d097bf378bab56877754bcbe56c2ec14e00b7c0d
[abartlet/samba.git/.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, 1 };
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                 if (tctx->samba3 && levels[i] == 2) {
245                         torture_comment(tctx, "skipping level %d enum against samba\n", levels[i]);
246                         continue;
247                 }
248
249                 EnumForms(handle, levels[i], NULL, 0, &needed, &returned);
250                 err = GetLastError();
251                 if (err == ERROR_INSUFFICIENT_BUFFER) {
252                         err = 0;
253                         buffer = malloc(needed);
254                         torture_assert(tctx, buffer, "malloc failed");
255                         if (!EnumForms(handle, levels[i], buffer, needed, &needed, &returned)) {
256                                 err = GetLastError();
257                         }
258                 }
259                 if (err) {
260                         sprintf(tmp, "EnumForms failed level %d on [%s] (buffer size = %d), error: %s\n",
261                                 levels[i], servername, needed, errstr(err));
262                         if (success[i]) {
263                                 torture_fail(tctx, tmp);
264                         } else {
265                                 torture_warning(tctx, tmp);
266                         }
267                 }
268
269                 if (tctx->print) {
270                         print_form_info_bylevel(levels[i], buffer, returned);
271                 }
272
273                 free(buffer);
274                 buffer = NULL;
275         }
276
277         return TRUE;
278 }
279
280 /****************************************************************************
281 ****************************************************************************/
282
283 static BOOL test_EnumPorts(struct torture_context *tctx,
284                            LPSTR servername)
285 {
286         DWORD levels[]  = { 1, 2 };
287         DWORD success[] = { 1, 1 };
288         DWORD i;
289         LPBYTE buffer = NULL;
290
291         for (i=0; i < ARRAY_SIZE(levels); i++) {
292
293                 DWORD needed = 0;
294                 DWORD returned = 0;
295                 DWORD err = 0;
296                 char tmp[1024];
297
298                 torture_comment(tctx, "Testing EnumPorts level %d", levels[i]);
299
300                 EnumPorts(servername, levels[i], NULL, 0, &needed, &returned);
301                 err = GetLastError();
302                 if (err == ERROR_INSUFFICIENT_BUFFER) {
303                         err = 0;
304                         buffer = malloc(needed);
305                         torture_assert(tctx, buffer, "malloc failed");
306                         if (!EnumPorts(servername, levels[i], buffer, needed, &needed, &returned)) {
307                                 err = GetLastError();
308                         }
309                 }
310                 if (err) {
311                         sprintf(tmp, "EnumPorts failed level %d on [%s] (buffer size = %d), error: %s\n",
312                                 levels[i], servername, needed, errstr(err));
313                         if (success[i]) {
314                                 torture_fail(tctx, tmp);
315                         } else {
316                                 torture_warning(tctx, tmp);
317                         }
318                 }
319
320                 if (tctx->print) {
321                         print_port_info_bylevel(levels[i], buffer, returned);
322                 }
323
324                 free(buffer);
325                 buffer = NULL;
326         }
327
328         return TRUE;
329 }
330
331 /****************************************************************************
332 ****************************************************************************/
333
334 static BOOL test_EnumMonitors(struct torture_context *tctx,
335                               LPSTR servername)
336 {
337         DWORD levels[]  = { 1, 2 };
338         DWORD success[] = { 1, 1 };
339         DWORD i;
340         LPBYTE buffer = NULL;
341
342         for (i=0; i < ARRAY_SIZE(levels); i++) {
343
344                 DWORD needed = 0;
345                 DWORD returned = 0;
346                 DWORD err = 0;
347                 char tmp[1024];
348
349                 torture_comment(tctx, "Testing EnumMonitors level %d", levels[i]);
350
351                 EnumMonitors(servername, levels[i], NULL, 0, &needed, &returned);
352                 err = GetLastError();
353                 if (err == ERROR_INSUFFICIENT_BUFFER) {
354                         err = 0;
355                         buffer = malloc(needed);
356                         torture_assert(tctx, buffer, "malloc failed");
357                         if (!EnumMonitors(servername, levels[i], buffer, needed, &needed, &returned)) {
358                                 err = GetLastError();
359                         }
360                 }
361                 if (err) {
362                         sprintf(tmp, "EnumMonitors failed level %d on [%s] (buffer size = %d), error: %s\n",
363                                 levels[i], servername, needed, errstr(err));
364                         if (success[i]) {
365                                 torture_fail(tctx, tmp);
366                         } else {
367                                 torture_warning(tctx, tmp);
368                         }
369                 }
370
371                 if (tctx->print) {
372                         print_monitor_info_bylevel(levels[i], buffer, returned);
373                 }
374
375                 free(buffer);
376                 buffer = NULL;
377         }
378
379         return TRUE;
380 }
381
382 /****************************************************************************
383 ****************************************************************************/
384
385 static BOOL test_EnumPrintProcessors(struct torture_context *tctx,
386                                      LPSTR servername,
387                                      LPSTR architecture)
388 {
389         DWORD levels[]  = { 1 };
390         DWORD success[] = { 1 };
391         DWORD i;
392         LPBYTE buffer = NULL;
393
394         for (i=0; i < ARRAY_SIZE(levels); i++) {
395
396                 DWORD needed = 0;
397                 DWORD returned = 0;
398                 DWORD err = 0;
399                 char tmp[1024];
400
401                 torture_comment(tctx, "Testing EnumPrintProcessors level %d", levels[i]);
402
403                 EnumPrintProcessors(servername, architecture, levels[i], NULL, 0, &needed, &returned);
404                 err = GetLastError();
405                 if (err == ERROR_INSUFFICIENT_BUFFER) {
406                         err = 0;
407                         buffer = malloc(needed);
408                         torture_assert(tctx, buffer, "malloc failed");
409                         if (!EnumPrintProcessors(servername, architecture, levels[i], buffer, needed, &needed, &returned)) {
410                                 err = GetLastError();
411                         }
412                 }
413                 if (err) {
414                         sprintf(tmp, "EnumPrintProcessors failed level %d on [%s] (buffer size = %d), error: %s\n",
415                                 levels[i], servername, needed, errstr(err));
416                         if (success[i]) {
417                                 torture_fail(tctx, tmp);
418                         } else {
419                                 torture_warning(tctx, tmp);
420                         }
421                 }
422
423                 if (tctx->print) {
424                         print_printprocessor_info_bylevel(levels[i], buffer, returned);
425                 }
426
427                 free(buffer);
428                 buffer = NULL;
429         }
430
431         return TRUE;
432 }
433
434 /****************************************************************************
435 ****************************************************************************/
436
437 static BOOL test_EnumPrintProcessorDatatypes(struct torture_context *tctx,
438                                              LPSTR servername)
439 {
440         DWORD levels[]  = { 1 };
441         DWORD success[] = { 1 };
442         DWORD i;
443         LPBYTE buffer = NULL;
444
445         for (i=0; i < ARRAY_SIZE(levels); i++) {
446
447                 DWORD needed = 0;
448                 DWORD returned = 0;
449                 DWORD err = 0;
450                 char tmp[1024];
451
452                 torture_comment(tctx, "Testing EnumPrintProcessorDatatypes level %d", levels[i]);
453
454                 EnumPrintProcessorDatatypes(servername, "winprint", levels[i], NULL, 0, &needed, &returned);
455                 err = GetLastError();
456                 if (err == ERROR_INSUFFICIENT_BUFFER) {
457                         err = 0;
458                         buffer = malloc(needed);
459                         torture_assert(tctx, buffer, "malloc failed");
460                         if (!EnumPrintProcessorDatatypes(servername, "winprint", levels[i], buffer, needed, &needed, &returned)) {
461                                 err = GetLastError();
462                         }
463                 }
464                 if (err) {
465                         sprintf(tmp, "EnumPrintProcessorDatatypes failed level %d on [%s] (buffer size = %d), error: %s\n",
466                                 levels[i], servername, needed, errstr(err));
467                         if (success[i]) {
468                                 torture_fail(tctx, tmp);
469                         } else {
470                                 torture_warning(tctx, tmp);
471                         }
472                 }
473
474                 if (tctx->print) {
475                         print_datatypes_info_bylevel(levels[i], buffer, returned);
476                 }
477
478                 free(buffer);
479                 buffer = NULL;
480         }
481
482         return TRUE;
483 }
484
485 /****************************************************************************
486 ****************************************************************************/
487
488 static BOOL test_EnumPrinterKey(struct torture_context *tctx,
489                                 LPSTR servername,
490                                 HANDLE handle,
491                                 LPCSTR key)
492 {
493         LPSTR buffer = NULL;
494         DWORD needed = 0;
495         DWORD err = 0;
496         char tmp[1024];
497
498         torture_comment(tctx, "Testing EnumPrinterKey(%s)", key);
499
500         err = EnumPrinterKey(handle, key, NULL, 0, &needed);
501         if (err == ERROR_MORE_DATA) {
502                 buffer = (LPTSTR)malloc(needed);
503                 torture_assert(tctx, buffer, "malloc failed");
504                 err = EnumPrinterKey(handle, key, buffer, needed, &needed);
505         }
506         if (err) {
507                 sprintf(tmp, "EnumPrinterKey(%s) failed on [%s] (buffer size = %d), error: %s\n",
508                         key, servername, needed, errstr(err));
509                 torture_fail(tctx, tmp);
510         }
511
512         if (tctx->print) {
513                 print_printer_keys(buffer);
514         }
515
516         free(buffer);
517
518         return TRUE;
519 }
520
521 /****************************************************************************
522 ****************************************************************************/
523
524 static BOOL test_GetPrinter(struct torture_context *tctx,
525                             LPSTR printername,
526                             HANDLE handle)
527 {
528         DWORD levels[]  = { 1, 2, 3, 4, 5, 6, 7, 8 };
529         DWORD success[] = { 1, 1, 1, 1, 1, 1, 1, 1 };
530         DWORD i;
531         LPBYTE buffer = NULL;
532
533         for (i=0; i < ARRAY_SIZE(levels); i++) {
534
535                 DWORD needed = 0;
536                 DWORD err = 0;
537                 char tmp[1024];
538
539                 torture_comment(tctx, "Testing GetPrinter level %d", levels[i]);
540
541                 GetPrinter(handle, levels[i], NULL, 0, &needed);
542                 err = GetLastError();
543                 if (err == ERROR_INSUFFICIENT_BUFFER) {
544                         err = 0;
545                         buffer = malloc(needed);
546                         torture_assert(tctx, buffer, "malloc failed");
547                         if (!GetPrinter(handle, levels[i], buffer, needed, &needed)) {
548                                 err = GetLastError();
549                         }
550                 }
551                 if (err) {
552                         sprintf(tmp, "GetPrinter failed level %d on [%s] (buffer size = %d), error: %s\n",
553                                 levels[i], printername, needed, errstr(err));
554                         if (success[i]) {
555                                 torture_fail(tctx, tmp);
556                         } else {
557                                 torture_warning(tctx, tmp);
558                         }
559                 }
560
561                 if (tctx->print) {
562                         print_printer_info_bylevel(levels[i], buffer, 1);
563                 }
564
565                 free(buffer);
566                 buffer = NULL;
567         }
568
569         return TRUE;
570 }
571
572 /****************************************************************************
573 ****************************************************************************/
574
575 static BOOL test_GetPrinterDriver(struct torture_context *tctx,
576                                   LPSTR printername,
577                                   LPSTR architecture,
578                                   HANDLE handle)
579 {
580         DWORD levels[]  = { 1, 2, 3, 4, 5, 6, 8 };
581         DWORD success[] = { 1, 1, 1, 1, 1, 1, 1 };
582         DWORD i;
583         LPBYTE buffer = NULL;
584
585         for (i=0; i < ARRAY_SIZE(levels); i++) {
586
587                 DWORD needed = 0;
588                 DWORD err = 0;
589                 char tmp[1024];
590
591                 torture_comment(tctx, "Testing GetPrinterDriver level %d", levels[i]);
592
593                 GetPrinterDriver(handle, architecture, levels[i], NULL, 0, &needed);
594                 err = GetLastError();
595                 if (err == ERROR_INSUFFICIENT_BUFFER) {
596                         err = 0;
597                         buffer = malloc(needed);
598                         torture_assert(tctx, buffer, "malloc failed");
599                         if (!GetPrinterDriver(handle, architecture, levels[i], buffer, needed, &needed)) {
600                                 err = GetLastError();
601                         }
602                 }
603                 if (err) {
604                         sprintf(tmp, "GetPrinterDriver failed level %d on [%s] (buffer size = %d), error: %s\n",
605                                 levels[i], printername, needed, errstr(err));
606                         if (success[i]) {
607                                 torture_fail(tctx, tmp);
608                         } else {
609                                 torture_warning(tctx, tmp);
610                         }
611                 }
612
613                 if (tctx->print) {
614                         print_driver_info_bylevel(levels[i], buffer, 1);
615                 }
616
617                 free(buffer);
618                 buffer = NULL;
619         }
620
621         return TRUE;
622 }
623
624
625 /****************************************************************************
626 ****************************************************************************/
627
628 static BOOL test_EnumJobs(struct torture_context *tctx,
629                           LPSTR printername,
630                           HANDLE handle)
631 {
632         DWORD levels[]  = { 1, 2, 3, 4 };
633         DWORD success[] = { 1, 1, 1, 1 };
634         DWORD i;
635         LPBYTE buffer = NULL;
636
637         for (i=0; i < ARRAY_SIZE(levels); i++) {
638
639                 DWORD needed = 0;
640                 DWORD returned = 0;
641                 DWORD err = 0;
642                 char tmp[1024];
643
644                 torture_comment(tctx, "Testing EnumJobs level %d", levels[i]);
645
646                 if (tctx->samba3 && levels[i] == 4) {
647                         torture_comment(tctx, "skipping level %d enum against samba\n", levels[i]);
648                         continue;
649                 }
650
651                 EnumJobs(handle, 0, 100, levels[i], NULL, 0, &needed, &returned);
652                 err = GetLastError();
653                 if (err == ERROR_INSUFFICIENT_BUFFER) {
654                         err = 0;
655                         buffer = malloc(needed);
656                         torture_assert(tctx, buffer, "malloc failed");
657                         if (!EnumJobs(handle, 0, 100, levels[i], buffer, needed, &needed, &returned)) {
658                                 err = GetLastError();
659                         }
660                 }
661                 if (err) {
662                         sprintf(tmp, "EnumJobs failed level %d on [%s] (buffer size = %d), error: %s\n",
663                                 levels[i], printername, needed, errstr(err));
664                         if (success[i]) {
665                                 torture_fail(tctx, tmp);
666                         } else {
667                                 torture_warning(tctx, tmp);
668                         }
669                 }
670
671                 if (tctx->print) {
672                         print_job_info_bylevel(levels[i], buffer, returned);
673                 }
674
675                 free(buffer);
676                 buffer = NULL;
677         }
678
679         return TRUE;
680 }
681
682 /****************************************************************************
683 ****************************************************************************/
684
685 static BOOL test_EnumPrinterDataEx(struct torture_context *tctx,
686                                    LPSTR servername,
687                                    LPSTR keyname,
688                                    HANDLE handle,
689                                    LPBYTE *buffer_p,
690                                    DWORD *returned_p)
691 {
692         LPBYTE buffer = NULL;
693         DWORD needed = 0;
694         DWORD returned = 0;
695         DWORD err = 0;
696         char tmp[1024];
697
698         torture_comment(tctx, "Testing EnumPrinterDataEx(%s)", keyname);
699
700         err = EnumPrinterDataEx(handle, keyname, NULL, 0, &needed, &returned);
701         if (err == ERROR_MORE_DATA) {
702                 buffer = malloc(needed);
703                 torture_assert(tctx, buffer, "malloc failed");
704                 err = EnumPrinterDataEx(handle, keyname, buffer, needed, &needed, &returned);
705         }
706         if (err) {
707                 sprintf(tmp, "EnumPrinterDataEx(%s) failed on [%s] (buffer size = %d), error: %s\n",
708                         keyname, servername, needed, errstr(err));
709                 torture_fail(tctx, tmp);
710         }
711
712         if (tctx->print) {
713                 DWORD i;
714                 LPPRINTER_ENUM_VALUES v = (LPPRINTER_ENUM_VALUES)buffer;
715                 for (i=0; i < returned; i++) {
716                         print_printer_enum_values(&v[i]);
717                 }
718         }
719
720         if (returned_p) {
721                 *returned_p = returned;
722         }
723
724         if (buffer_p) {
725                 *buffer_p = buffer;
726         } else {
727                 free(buffer);
728         }
729
730         return TRUE;
731 }
732
733 /****************************************************************************
734 ****************************************************************************/
735
736 static BOOL test_devicemode_equal(struct torture_context *tctx,
737                                   const DEVMODE *d1,
738                                   const DEVMODE *d2)
739 {
740         if (d1 == d2) {
741                 return TRUE;
742         }
743
744         if (!d1 || !d2) {
745                 torture_comment(tctx, "%s\n", __location__);
746                 return FALSE;
747         }
748
749         torture_assert_str_equal(tctx, (const char *)d1->dmDeviceName, (const char *)d2->dmDeviceName, "dmDeviceName mismatch");
750         torture_assert_int_equal(tctx, d1->dmSpecVersion, d2->dmSpecVersion, "dmSpecVersion mismatch");
751         torture_assert_int_equal(tctx, d1->dmDriverVersion, d2->dmDriverVersion, "dmDriverVersion mismatch");
752         torture_assert_int_equal(tctx, d1->dmSize, d2->dmSize, "size mismatch");
753         torture_assert_int_equal(tctx, d1->dmDriverExtra, d2->dmDriverExtra, "dmDriverExtra mismatch");
754         torture_assert_int_equal(tctx, d1->dmFields, d2->dmFields, "dmFields mismatch");
755
756         torture_assert_int_equal(tctx, d1->dmOrientation, d2->dmOrientation, "dmOrientation mismatch");
757         torture_assert_int_equal(tctx, d1->dmPaperSize, d2->dmPaperSize, "dmPaperSize mismatch");
758         torture_assert_int_equal(tctx, d1->dmPaperLength, d2->dmPaperLength, "dmPaperLength mismatch");
759         torture_assert_int_equal(tctx, d1->dmPaperWidth, d2->dmPaperWidth, "dmPaperWidth mismatch");
760         torture_assert_int_equal(tctx, d1->dmScale, d2->dmScale, "dmScale mismatch");
761         torture_assert_int_equal(tctx, d1->dmCopies, d2->dmCopies, "dmCopies mismatch");
762         torture_assert_int_equal(tctx, d1->dmDefaultSource, d2->dmDefaultSource, "dmDefaultSource mismatch");
763         torture_assert_int_equal(tctx, d1->dmPrintQuality, d2->dmPrintQuality, "dmPrintQuality mismatch");
764
765         torture_assert_int_equal(tctx, d1->dmColor, d2->dmColor, "dmColor mismatch");
766         torture_assert_int_equal(tctx, d1->dmDuplex, d2->dmDuplex, "dmDuplex mismatch");
767         torture_assert_int_equal(tctx, d1->dmYResolution, d2->dmYResolution, "dmYResolution mismatch");
768         torture_assert_int_equal(tctx, d1->dmTTOption, d2->dmTTOption, "dmTTOption mismatch");
769         torture_assert_int_equal(tctx, d1->dmCollate, d2->dmCollate, "dmCollate mismatch");
770         torture_assert_str_equal(tctx, (const char *)d1->dmFormName, (const char *)d2->dmFormName, "dmFormName mismatch");
771         torture_assert_int_equal(tctx, d1->dmLogPixels, d2->dmLogPixels, "dmLogPixels mismatch");
772         torture_assert_int_equal(tctx, d1->dmBitsPerPel, d2->dmBitsPerPel, "dmBitsPerPel mismatch");
773         torture_assert_int_equal(tctx, d1->dmPelsWidth, d2->dmPelsWidth, "dmPelsWidth mismatch");
774         torture_assert_int_equal(tctx, d1->dmPelsHeight, d2->dmPelsHeight, "dmPelsHeight mismatch");
775
776         torture_assert_int_equal(tctx, d1->dmDisplayFlags, d2->dmDisplayFlags, "dmDisplayFlags mismatch");
777         /* or dmNup ? */
778         torture_assert_int_equal(tctx, d1->dmDisplayFrequency, d2->dmDisplayFrequency, "dmDisplayFrequency mismatch");
779
780         torture_assert_int_equal(tctx, d1->dmICMMethod, d2->dmICMMethod, "dmICMMethod mismatch");
781         torture_assert_int_equal(tctx, d1->dmICMIntent, d2->dmICMIntent, "dmICMIntent mismatch");
782         torture_assert_int_equal(tctx, d1->dmMediaType, d2->dmMediaType, "dmMediaType mismatch");
783         torture_assert_int_equal(tctx, d1->dmDitherType, d2->dmDitherType, "dmDitherType mismatch");
784         torture_assert_int_equal(tctx, d1->dmReserved1, d2->dmReserved1, "dmReserved1 mismatch");
785         torture_assert_int_equal(tctx, d1->dmReserved2, d2->dmReserved2, "reserved2 mismatch");
786
787         torture_assert_int_equal(tctx, d1->dmPanningWidth, d2->dmPanningWidth, "dmPanningWidth mismatch");
788         torture_assert_int_equal(tctx, d1->dmPanningHeight, d2->dmPanningHeight, "dmPanningHeight mismatch");
789
790         /* torture_assert_mem_equal(tctx, d1 + d1->dmSize, d2 + d2->dmSize, d1->dmDriverExtra, "private extra data mismatch"); */
791
792         return TRUE;
793 }
794
795 static BOOL test_DeviceModes(struct torture_context *tctx,
796                              LPSTR printername,
797                              HANDLE handle)
798 {
799         PPRINTER_INFO_2 info2 = NULL;
800         PPRINTER_INFO_8 info8 = NULL;
801         DWORD needed = 0;
802         DWORD err = 0;
803         char tmp[1024];
804
805         torture_comment(tctx, "Testing DeviceModes");
806
807         torture_comment(tctx, "Testing GetPrinter level %d", 2);
808
809         GetPrinter(handle, 2, NULL, 0, &needed);
810         err = GetLastError();
811         if (err == ERROR_INSUFFICIENT_BUFFER) {
812                 err = 0;
813                 info2 = (PPRINTER_INFO_2)malloc(needed);
814                 torture_assert(tctx, (LPBYTE)info2, "malloc failed");
815                 if (!GetPrinter(handle, 2, (LPBYTE)info2, needed, &needed)) {
816                         err = GetLastError();
817                 }
818         }
819         if (err) {
820                 sprintf(tmp, "GetPrinter failed level %d on [%s] (buffer size = %d), error: %s\n",
821                         2, printername, needed, errstr(err));
822                 torture_fail(tctx, tmp);
823         }
824
825         if (tctx->print) {
826                 print_printer_info_2(info2);
827         }
828
829         torture_comment(tctx, "Testing GetPrinter level %d", 8);
830
831         GetPrinter(handle, 8, NULL, 0, &needed);
832         err = GetLastError();
833         if (err == ERROR_INSUFFICIENT_BUFFER) {
834                 err = 0;
835                 info8 = (PPRINTER_INFO_8)malloc(needed);
836                 torture_assert(tctx, (LPBYTE)info8, "malloc failed");
837                 if (!GetPrinter(handle, 8, (LPBYTE)info8, needed, &needed)) {
838                         err = GetLastError();
839                 }
840         }
841         if (err) {
842                 sprintf(tmp, "GetPrinter failed level %d on [%s] (buffer size = %d), error: %s\n",
843                         8, printername, needed, errstr(err));
844                 torture_fail(tctx, tmp);
845         }
846
847         if (tctx->print) {
848                 print_printer_info_8(info8);
849         }
850
851         torture_assert(tctx, test_devicemode_equal(tctx, info2->pDevMode, info8->pDevMode), "");
852
853         free(info2);
854         free(info8);
855
856         return TRUE;
857 }
858
859 /****************************************************************************
860 ****************************************************************************/
861
862 static BOOL test_OnePrinter(struct torture_context *tctx,
863                             LPSTR printername,
864                             LPSTR architecture,
865                             LPPRINTER_DEFAULTS defaults)
866 {
867         HANDLE handle;
868         BOOL ret = TRUE;
869
870         torture_comment(tctx, "Testing Printer %s", printername);
871
872         ret &= test_OpenPrinter(tctx, printername, defaults, &handle);
873         ret &= test_GetPrinter(tctx, printername, handle);
874         ret &= test_GetPrinterDriver(tctx, printername, architecture, handle);
875         ret &= test_EnumForms(tctx, printername, handle);
876         ret &= test_EnumJobs(tctx, printername, handle);
877         ret &= test_EnumPrinterKey(tctx, printername, handle, "");
878         ret &= test_EnumPrinterKey(tctx, printername, handle, "PrinterDriverData");
879         ret &= test_EnumPrinterDataEx(tctx, printername, "PrinterDriverData", handle, NULL, NULL);
880         ret &= test_DeviceModes(tctx, printername, handle);
881         ret &= test_ClosePrinter(tctx, handle);
882
883         return ret;
884 }
885
886 /****************************************************************************
887 ****************************************************************************/
888
889 static BOOL test_EachPrinter(struct torture_context *tctx,
890                              LPSTR servername,
891                              LPSTR architecture,
892                              LPPRINTER_DEFAULTS defaults)
893 {
894         DWORD needed = 0;
895         DWORD returned = 0;
896         DWORD err = 0;
897         char tmp[1024];
898         DWORD i;
899         DWORD flags = PRINTER_ENUM_NAME;
900         PPRINTER_INFO_1 buffer = NULL;
901         BOOL ret = TRUE;
902
903         torture_comment(tctx, "Testing EnumPrinters level %d", 1);
904
905         EnumPrinters(flags, servername, 1, NULL, 0, &needed, &returned);
906         err = GetLastError();
907         if (err == ERROR_INSUFFICIENT_BUFFER) {
908                 err = 0;
909                 buffer = (PPRINTER_INFO_1)malloc(needed);
910                 torture_assert(tctx, buffer, "malloc failed");
911                 if (!EnumPrinters(flags, servername, 1, (LPBYTE)buffer, needed, &needed, &returned)) {
912                         err = GetLastError();
913                 }
914         }
915         if (err) {
916                 sprintf(tmp, "EnumPrinters failed level %d on [%s] (buffer size = %d), error: %s\n",
917                         1, servername, needed, errstr(err));
918                 torture_fail(tctx, tmp);
919         }
920
921         for (i=0; i < returned; i++) {
922                 ret &= test_OnePrinter(tctx, buffer[i].pName, architecture, defaults);
923         }
924
925         free(buffer);
926
927         return ret;
928 }
929
930 /****************************************************************************
931 ****************************************************************************/
932
933 static BOOL test_GetPrintProcessorDirectory(struct torture_context *tctx,
934                                             LPSTR servername,
935                                             LPSTR architecture)
936 {
937         DWORD levels[]  = { 1 };
938         DWORD success[] = { 1 };
939         DWORD i;
940         LPBYTE buffer = NULL;
941
942         for (i=0; i < ARRAY_SIZE(levels); i++) {
943
944                 DWORD needed = 0;
945                 DWORD err = 0;
946                 char tmp[1024];
947
948                 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %d", levels[i]);
949
950                 GetPrintProcessorDirectory(servername, architecture, levels[i], NULL, 0, &needed);
951                 err = GetLastError();
952                 if (err == ERROR_INSUFFICIENT_BUFFER) {
953                         err = 0;
954                         buffer = malloc(needed);
955                         torture_assert(tctx, buffer, "malloc failed");
956                         if (!GetPrintProcessorDirectory(servername, architecture, levels[i], buffer, needed, &needed)) {
957                                 err = GetLastError();
958                         }
959                 }
960                 if (err) {
961                         sprintf(tmp, "GetPrintProcessorDirectory failed level %d on [%s] (buffer size = %d), error: %s\n",
962                                 levels[i], servername, needed, errstr(err));
963                         if (success[i]) {
964                                 torture_fail(tctx, tmp);
965                         } else {
966                                 torture_warning(tctx, tmp);
967                         }
968                 }
969
970                 free(buffer);
971                 buffer = NULL;
972         }
973
974         return TRUE;
975 }
976
977 /****************************************************************************
978 ****************************************************************************/
979
980 static BOOL test_GetPrinterDriverDirectory(struct torture_context *tctx,
981                                            LPSTR servername,
982                                            LPSTR architecture)
983 {
984         DWORD levels[]  = { 1 };
985         DWORD success[] = { 1 };
986         DWORD i;
987         LPBYTE buffer = NULL;
988
989         for (i=0; i < ARRAY_SIZE(levels); i++) {
990
991                 DWORD needed = 0;
992                 DWORD err = 0;
993                 char tmp[1024];
994
995                 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %d", levels[i]);
996
997                 GetPrinterDriverDirectory(servername, architecture, levels[i], NULL, 0, &needed);
998                 err = GetLastError();
999                 if (err == ERROR_INSUFFICIENT_BUFFER) {
1000                         err = 0;
1001                         buffer = malloc(needed);
1002                         torture_assert(tctx, buffer, "malloc failed");
1003                         if (!GetPrinterDriverDirectory(servername, architecture, levels[i], buffer, needed, &needed)) {
1004                                 err = GetLastError();
1005                         }
1006                 }
1007                 if (err) {
1008                         sprintf(tmp, "GetPrinterDriverDirectory failed level %d on [%s] (buffer size = %d), error: %s\n",
1009                                 levels[i], servername, needed, errstr(err));
1010                         if (success[i]) {
1011                                 torture_fail(tctx, tmp);
1012                         } else {
1013                                 torture_warning(tctx, tmp);
1014                         }
1015                 }
1016
1017                 free(buffer);
1018                 buffer = NULL;
1019         }
1020
1021         return TRUE;
1022 }
1023
1024 /****************************************************************************
1025 ****************************************************************************/
1026
1027 static BOOL test_GetPrinterData(struct torture_context *tctx,
1028                                 LPSTR servername,
1029                                 LPSTR valuename,
1030                                 HANDLE handle,
1031                                 DWORD *type_p,
1032                                 LPBYTE *buffer_p,
1033                                 DWORD *size_p)
1034 {
1035         LPBYTE buffer = NULL;
1036         DWORD needed = 0;
1037         DWORD type;
1038         DWORD err = 0;
1039         char tmp[1024];
1040
1041         torture_comment(tctx, "Testing GetPrinterData(%s)", valuename);
1042
1043         err = GetPrinterData(handle, valuename, &type, NULL, 0, &needed);
1044         if (err == ERROR_MORE_DATA) {
1045                 buffer = (LPBYTE)malloc(needed);
1046                 torture_assert(tctx, buffer, "malloc failed");
1047                 err = GetPrinterData(handle, valuename, &type, buffer, needed, &needed);
1048         }
1049         if (err) {
1050                 sprintf(tmp, "GetPrinterData(%s) failed on [%s] (buffer size = %d), error: %s\n",
1051                         valuename, servername, needed, errstr(err));
1052                 torture_fail(tctx, tmp);
1053         }
1054
1055         if (tctx->print) {
1056                 print_printer_data("PrinterDriverData", valuename, needed, buffer, type);
1057         }
1058
1059         if (type_p) {
1060                 *type_p = type;
1061         }
1062
1063         if (size_p) {
1064                 *size_p = needed;
1065         }
1066
1067         if (buffer_p) {
1068                 *buffer_p = buffer;
1069         } else {
1070                 free(buffer);
1071         }
1072
1073         return TRUE;
1074 }
1075
1076 /****************************************************************************
1077 ****************************************************************************/
1078
1079 static BOOL test_GetPrinterDataEx(struct torture_context *tctx,
1080                                   LPSTR servername,
1081                                   LPSTR keyname,
1082                                   LPSTR valuename,
1083                                   HANDLE handle,
1084                                   DWORD *type_p,
1085                                   LPBYTE *buffer_p,
1086                                   DWORD *size_p)
1087 {
1088         LPBYTE buffer = NULL;
1089         DWORD needed = 0;
1090         DWORD type;
1091         DWORD err = 0;
1092         char tmp[1024];
1093
1094         torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)", keyname, valuename);
1095
1096         err = GetPrinterDataEx(handle, keyname, valuename, &type, NULL, 0, &needed);
1097         if (err == ERROR_MORE_DATA) {
1098                 buffer = (LPBYTE)malloc(needed);
1099                 torture_assert(tctx, buffer, "malloc failed");
1100                 err = GetPrinterDataEx(handle, keyname, valuename, &type, buffer, needed, &needed);
1101         }
1102         if (err) {
1103                 sprintf(tmp, "GetPrinterDataEx(%s) failed on [%s] (buffer size = %d), error: %s\n",
1104                         valuename, servername, needed, errstr(err));
1105                 torture_fail(tctx, tmp);
1106         }
1107
1108         if (tctx->print) {
1109                 print_printer_data(keyname, valuename, needed, buffer, type);
1110         }
1111
1112         if (type_p) {
1113                 *type_p = type;
1114         }
1115
1116         if (size_p) {
1117                 *size_p = needed;
1118         }
1119
1120         if (buffer_p) {
1121                 *buffer_p = buffer;
1122         } else {
1123                 free(buffer);
1124         }
1125
1126         return TRUE;
1127 }
1128
1129 /****************************************************************************
1130 ****************************************************************************/
1131
1132 static BOOL test_PrinterData(struct torture_context *tctx,
1133                              LPSTR servername,
1134                              HANDLE handle)
1135 {
1136         BOOL ret = TRUE;
1137         DWORD i;
1138         DWORD type, type_ex;
1139         LPBYTE buffer, buffer_ex;
1140         DWORD size, size_ex;
1141         LPSTR valuenames[] = {
1142                 SPLREG_DEFAULT_SPOOL_DIRECTORY,
1143                 SPLREG_MAJOR_VERSION,
1144                 SPLREG_MINOR_VERSION,
1145                 SPLREG_DS_PRESENT,
1146                 SPLREG_DNS_MACHINE_NAME,
1147                 SPLREG_ARCHITECTURE,
1148                 SPLREG_OS_VERSION
1149         };
1150
1151         for (i=0; i < ARRAY_SIZE(valuenames); i++) {
1152                 ret &= test_GetPrinterData(tctx, servername, valuenames[i], handle, &type, &buffer, &size);
1153                 ret &= test_GetPrinterDataEx(tctx, servername, "random", valuenames[i], handle, &type_ex, &buffer_ex, &size_ex);
1154                 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
1155                 torture_assert_int_equal(tctx, size, size_ex, "size mismatch");
1156                 torture_assert_mem_equal(tctx, buffer, buffer_ex, size, "buffer mismatch");
1157                 free(buffer);
1158                 free(buffer_ex);
1159         }
1160
1161         return ret;
1162 }
1163
1164 /****************************************************************************
1165 ****************************************************************************/
1166
1167 const char *get_string_param(const char *str)
1168 {
1169         const char *p;
1170
1171         p = strchr(str, '=');
1172         if (!p) {
1173                 return NULL;
1174         }
1175
1176         return (p+1);
1177 }
1178
1179 /****************************************************************************
1180 ****************************************************************************/
1181
1182 int main(int argc, char *argv[])
1183 {
1184         BOOL ret = FALSE;
1185         LPSTR servername;
1186         LPSTR architecture = "Windows NT x86";
1187         HANDLE server_handle;
1188         PRINTER_DEFAULTS defaults_admin, defaults_use;
1189         struct torture_context *tctx;
1190         int i;
1191
1192         if (argc < 2) {
1193                 fprintf(stderr, "usage: %s <servername> [print] [samba3] [architecture=ARCHITECTURE]\n", argv[0]);
1194                 exit(-1);
1195         }
1196
1197         tctx = malloc(sizeof(struct torture_context));
1198         if (!tctx) {
1199                 fprintf(stderr, "out of memory\n");
1200                 exit(-1);
1201         }
1202         memset(tctx, '\0', sizeof(*tctx));
1203
1204         servername = argv[1];
1205
1206         for (i=1; i < argc; i++) {
1207                 if (strcmp(argv[i], "print") == 0) {
1208                         tctx->print = TRUE;
1209                 }
1210                 if (strcmp(argv[i], "samba3") == 0) {
1211                         tctx->samba3 = TRUE;
1212                 }
1213                 if (strncmp(argv[i], "architecture", strlen("architecture")) == 0) {
1214                         architecture = get_string_param(argv[i]);
1215                 }
1216         }
1217
1218         printf("Running testsuite with architecture: %s\n", architecture);
1219
1220         defaults_admin.pDatatype = NULL;
1221         defaults_admin.pDevMode = NULL;
1222         defaults_admin.DesiredAccess = PRINTER_ACCESS_ADMINISTER;
1223
1224         defaults_use.pDatatype = NULL;
1225         defaults_use.pDevMode = NULL;
1226         defaults_use.DesiredAccess = PRINTER_ACCESS_USE;
1227
1228         ret &= test_EnumPrinters(tctx, servername);
1229         ret &= test_EnumDrivers(tctx, servername, architecture);
1230         ret &= test_OpenPrinter(tctx, servername, NULL, &server_handle);
1231 /*      ret &= test_EnumPrinterKey(tctx, servername, server_handle, ""); */
1232         ret &= test_PrinterData(tctx, servername, server_handle);
1233         ret &= test_EnumForms(tctx, servername, server_handle);
1234         ret &= test_ClosePrinter(tctx, server_handle);
1235         ret &= test_EnumPorts(tctx, servername);
1236         ret &= test_EnumMonitors(tctx, servername);
1237         ret &= test_EnumPrintProcessors(tctx, servername, architecture);
1238         ret &= test_EnumPrintProcessorDatatypes(tctx, servername);
1239         ret &= test_GetPrintProcessorDirectory(tctx, servername, architecture);
1240         ret &= test_GetPrinterDriverDirectory(tctx, servername, architecture);
1241         ret &= test_EachPrinter(tctx, servername, architecture, NULL);
1242
1243         if (!ret) {
1244                 if (tctx->last_reason) {
1245                         fprintf(stderr, "failed: %s\n", tctx->last_reason);
1246                 }
1247                 free(tctx);
1248                 return -1;
1249         }
1250
1251         printf("%s run successfully\n", argv[0]);
1252
1253         free(tctx);
1254         return 0;
1255 }