s3:dom_sid Global replace of DOM_SID with struct dom_sid
[idra/samba.git] / source3 / utils / net_printing.c
1 /*
2    Samba Unix/Linux SMB client library
3    Distributed SMB/CIFS Server Management Utility
4    Local printing tdb migration interface
5
6    Copyright (C) Guenther Deschner 2010
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include "includes.h"
23 #include "utils/net.h"
24 #include "librpc/gen_ndr/ndr_ntprinting.h"
25 #include "librpc/gen_ndr/cli_spoolss.h"
26 #include "rpc_client/cli_spoolss.h"
27
28 #define FORMS_PREFIX "FORMS/"
29 #define DRIVERS_PREFIX "DRIVERS/"
30 #define PRINTERS_PREFIX "PRINTERS/"
31 #define SECDESC_PREFIX "SECDESC/"
32
33 static void dump_form(TALLOC_CTX *mem_ctx,
34                       const char *key_name,
35                       unsigned char *data,
36                       size_t length)
37 {
38         enum ndr_err_code ndr_err;
39         DATA_BLOB blob;
40         char *s;
41         struct ntprinting_form r;
42
43         printf("found form: %s\n", key_name);
44
45         blob = data_blob_const(data, length);
46
47         ZERO_STRUCT(r);
48
49         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
50                    (ndr_pull_flags_fn_t)ndr_pull_ntprinting_form);
51         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
52                 d_fprintf(stderr, _("form pull failed: %s\n"),
53                           ndr_errstr(ndr_err));
54                 return;
55         }
56
57         s = NDR_PRINT_STRUCT_STRING(mem_ctx, ntprinting_form, &r);
58         if (s) {
59                 printf("%s\n", s);
60         }
61 }
62
63 static void dump_driver(TALLOC_CTX *mem_ctx,
64                         const char *key_name,
65                         unsigned char *data,
66                         size_t length)
67 {
68         enum ndr_err_code ndr_err;
69         DATA_BLOB blob;
70         char *s;
71         struct ntprinting_driver r;
72
73         printf("found driver: %s\n", key_name);
74
75         blob = data_blob_const(data, length);
76
77         ZERO_STRUCT(r);
78
79         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
80                    (ndr_pull_flags_fn_t)ndr_pull_ntprinting_driver);
81         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
82                 d_fprintf(stderr, _("driver pull failed: %s\n"),
83                           ndr_errstr(ndr_err));
84                 return;
85         }
86
87         s = NDR_PRINT_STRUCT_STRING(mem_ctx, ntprinting_driver, &r);
88         if (s) {
89                 printf("%s\n", s);
90         }
91 }
92
93 static void dump_printer(TALLOC_CTX *mem_ctx,
94                          const char *key_name,
95                          unsigned char *data,
96                          size_t length)
97 {
98         enum ndr_err_code ndr_err;
99         DATA_BLOB blob;
100         char *s;
101         struct ntprinting_printer r;
102
103         printf("found printer: %s\n", key_name);
104
105         blob = data_blob_const(data, length);
106
107         ZERO_STRUCT(r);
108
109         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
110                    (ndr_pull_flags_fn_t)ndr_pull_ntprinting_printer);
111         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
112                 d_fprintf(stderr, _("printer pull failed: %s\n"),
113                           ndr_errstr(ndr_err));
114                 return;
115         }
116
117         s = NDR_PRINT_STRUCT_STRING(mem_ctx, ntprinting_printer, &r);
118         if (s) {
119                 printf("%s\n", s);
120         }
121 }
122
123 static void dump_sd(TALLOC_CTX *mem_ctx,
124                     const char *key_name,
125                     unsigned char *data,
126                     size_t length)
127 {
128         enum ndr_err_code ndr_err;
129         DATA_BLOB blob;
130         char *s;
131         struct sec_desc_buf r;
132
133         printf("found security descriptor: %s\n", key_name);
134
135         blob = data_blob_const(data, length);
136
137         ZERO_STRUCT(r);
138
139         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
140                    (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
141         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
142                 d_fprintf(stderr, _("security descriptor pull failed: %s\n"),
143                           ndr_errstr(ndr_err));
144                 return;
145         }
146
147         s = NDR_PRINT_STRUCT_STRING(mem_ctx, sec_desc_buf, &r);
148         if (s) {
149                 printf("%s\n", s);
150         }
151 }
152
153
154 static int net_printing_dump(struct net_context *c, int argc,
155                              const char **argv)
156 {
157         int ret = -1;
158         TALLOC_CTX *ctx = talloc_stackframe();
159         TDB_CONTEXT *tdb;
160         TDB_DATA kbuf, newkey, dbuf;
161
162         if (argc < 1 || c->display_usage) {
163                 d_fprintf(stderr, "%s\nnet printing dump <file.tdb>\n",
164                           _("Usage:"));
165                 goto done;
166         }
167
168         tdb = tdb_open_log(argv[0], 0, TDB_DEFAULT, O_RDONLY, 0600);
169         if (!tdb) {
170                 d_fprintf(stderr, _("failed to open tdb file: %s\n"), argv[0]);
171                 goto done;
172         }
173
174         for (kbuf = tdb_firstkey(tdb);
175              kbuf.dptr;
176              newkey = tdb_nextkey(tdb, kbuf), free(kbuf.dptr), kbuf=newkey)
177         {
178                 dbuf = tdb_fetch(tdb, kbuf);
179                 if (!dbuf.dptr) {
180                         continue;
181                 }
182
183                 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
184                         dump_form(ctx, (const char *)kbuf.dptr+strlen(FORMS_PREFIX), dbuf.dptr, dbuf.dsize);
185                         SAFE_FREE(dbuf.dptr);
186                         continue;
187                 }
188
189                 if (strncmp((const char *)kbuf.dptr, DRIVERS_PREFIX, strlen(DRIVERS_PREFIX)) == 0) {
190                         dump_driver(ctx, (const char *)kbuf.dptr+strlen(DRIVERS_PREFIX), dbuf.dptr, dbuf.dsize);
191                         SAFE_FREE(dbuf.dptr);
192                         continue;
193                 }
194
195                 if (strncmp((const char *)kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
196                         dump_printer(ctx, (const char *)kbuf.dptr+strlen(PRINTERS_PREFIX), dbuf.dptr, dbuf.dsize);
197                         SAFE_FREE(dbuf.dptr);
198                         continue;
199                 }
200
201                 if (strncmp((const char *)kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
202                         dump_sd(ctx, (const char *)kbuf.dptr+strlen(SECDESC_PREFIX), dbuf.dptr, dbuf.dsize);
203                         SAFE_FREE(dbuf.dptr);
204                         continue;
205                 }
206
207         }
208
209         ret = 0;
210
211  done:
212         talloc_free(ctx);
213         return ret;
214 }
215
216 static NTSTATUS migrate_form(TALLOC_CTX *mem_ctx,
217                          struct rpc_pipe_client *pipe_hnd,
218                          const char *key_name,
219                          unsigned char *data,
220                          size_t length)
221 {
222         struct policy_handle hnd;
223         enum ndr_err_code ndr_err;
224         struct ntprinting_form r;
225         union spoolss_AddFormInfo f;
226         struct spoolss_AddFormInfo1 f1;
227         DATA_BLOB blob;
228         NTSTATUS status;
229         WERROR result;
230
231         blob = data_blob_const(data, length);
232
233         ZERO_STRUCT(r);
234
235         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
236                    (ndr_pull_flags_fn_t)ndr_pull_ntprinting_form);
237         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
238                 d_fprintf(stderr, _("form pull failed: %s\n"),
239                           ndr_errstr(ndr_err));
240                 return NT_STATUS_NO_MEMORY;
241         }
242
243         /* Don't migrate builtin forms */
244         if (r.flag == SPOOLSS_FORM_BUILTIN) {
245                 return NT_STATUS_OK;
246         }
247
248         d_printf(_("Migrating Form: %s\n"), key_name);
249
250         result = rpccli_spoolss_openprinter_ex(pipe_hnd,
251                                                mem_ctx,
252                                                pipe_hnd->srv_name_slash,
253                                                MAXIMUM_ALLOWED_ACCESS,
254                                                &hnd);
255         if (!W_ERROR_IS_OK(result)) {
256                 d_fprintf(stderr, _("OpenPrinter(%s) failed: %s\n"),
257                                   pipe_hnd->srv_name_slash, win_errstr(result));
258                 return werror_to_ntstatus(result);
259         }
260
261         f1.form_name = key_name;
262         f1.flags = r.flag;
263
264         f1.size.width = r.width;
265         f1.size.height = r.length;
266
267         f1.area.top = r.top;
268         f1.area.right = r.right;
269         f1.area.bottom = r.bottom;
270         f1.area.left = r.left;
271
272         f.info1 = &f1;
273
274         status = rpccli_spoolss_AddForm(pipe_hnd,
275                                         mem_ctx,
276                                         &hnd,
277                                         1,
278                                         f,
279                                         &result);
280         if (!NT_STATUS_IS_OK(status)) {
281                 d_printf(_("\tAddForm(%s) refused -- %s.\n"),
282                         f.info1->form_name, nt_errstr(status));
283         }
284
285         rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
286
287         return status;
288 }
289
290 static NTSTATUS migrate_driver(TALLOC_CTX *mem_ctx,
291                                struct rpc_pipe_client *pipe_hnd,
292                                const char *key_name,
293                                unsigned char *data,
294                                size_t length)
295 {
296         enum ndr_err_code ndr_err;
297         struct ntprinting_driver r;
298         struct spoolss_AddDriverInfoCtr d;
299         struct spoolss_AddDriverInfo3 d3;
300         struct spoolss_StringArray a;
301         DATA_BLOB blob;
302         NTSTATUS status;
303         WERROR result;
304
305         blob = data_blob_const(data, length);
306
307         ZERO_STRUCT(r);
308
309         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
310                    (ndr_pull_flags_fn_t)ndr_pull_ntprinting_driver);
311         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
312                 d_fprintf(stderr, _("driver pull failed: %s\n"),
313                           ndr_errstr(ndr_err));
314                 return NT_STATUS_NO_MEMORY;
315         }
316
317         d_printf(_("Migrating Printer Driver: %s\n"), key_name);
318
319         ZERO_STRUCT(d3);
320         ZERO_STRUCT(a);
321
322         a.string = r.dependent_files;
323
324         d3.architecture = r.environment;
325         d3.config_file = r.configfile;
326         d3.data_file = r.datafile;
327         d3.default_datatype = r.defaultdatatype;
328         d3.dependent_files = &a;
329         d3.driver_path = r.driverpath;
330         d3.help_file = r.helpfile;
331         d3.monitor_name = r.monitorname;
332         d3.driver_name = r.name;
333         d3.version = r.version;
334
335         d.info.info3 = &d3;
336         d.level = 3;
337
338         status = rpccli_spoolss_AddPrinterDriver(pipe_hnd,
339                                                  mem_ctx,
340                                                  NULL,
341                                                  &d,
342                                                  &result);
343         if (!NT_STATUS_IS_OK(status)) {
344                 d_printf(_("\tAddDriver driver: [%s] refused -- %s.\n"),
345                         d3.driver_name, nt_errstr(status));
346         }
347
348         return status;
349 }
350
351 static NTSTATUS migrate_printer(TALLOC_CTX *mem_ctx,
352                                 struct rpc_pipe_client *pipe_hnd,
353                                 const char *key_name,
354                                 unsigned char *data,
355                                 size_t length)
356 {
357         struct policy_handle hnd;
358         enum ndr_err_code ndr_err;
359         struct ntprinting_printer r;
360         struct spoolss_SetPrinterInfo2 info2;
361         struct spoolss_DeviceMode dm;
362         struct spoolss_SetPrinterInfoCtr info_ctr;
363         struct spoolss_DevmodeContainer devmode_ctr;
364         struct sec_desc_buf secdesc_ctr;
365         DATA_BLOB blob;
366         NTSTATUS status;
367         WERROR result;
368         int j;
369
370         if (strequal(key_name, "printers")) {
371                 return NT_STATUS_OK;
372         }
373
374         blob = data_blob_const(data, length);
375
376         ZERO_STRUCT(r);
377
378         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
379                    (ndr_pull_flags_fn_t) ndr_pull_ntprinting_printer);
380         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
381                 d_fprintf(stderr, _("printer pull failed: %s\n"),
382                           ndr_errstr(ndr_err));
383                 return NT_STATUS_NO_MEMORY;
384         }
385
386         d_printf(_("Migrating Printer: %s\n"), key_name);
387
388         result = rpccli_spoolss_openprinter_ex(pipe_hnd,
389                                                mem_ctx,
390                                                key_name,
391                                                MAXIMUM_ALLOWED_ACCESS,
392                                                &hnd);
393         if (!W_ERROR_IS_OK(result)) {
394                 d_fprintf(stderr, _("OpenPrinter(%s) failed: %s\n"),
395                                   key_name, win_errstr(result));
396                 return werror_to_ntstatus(result);
397         }
398
399         /* Create printer info level 2 */
400         ZERO_STRUCT(info2);
401         ZERO_STRUCT(devmode_ctr);
402         ZERO_STRUCT(secdesc_ctr);
403
404         info2.attributes = r.info.attributes;
405         info2.averageppm = r.info.averageppm;
406         info2.cjobs = r.info.cjobs;
407         info2.comment = r.info.comment;
408         info2.datatype = r.info.datatype;
409         info2.defaultpriority = r.info.default_priority;
410         info2.drivername = r.info.drivername;
411         info2.location = r.info.location;
412         info2.parameters = r.info.parameters;
413         info2.portname = r.info.portname;
414         info2.printername = r.info.printername;
415         info2.printprocessor = r.info.printprocessor;
416         info2.priority = r.info.priority;
417         info2.sepfile = r.info.sepfile;
418         info2.sharename = r.info.sharename;
419         info2.starttime = r.info.starttime;
420         info2.status = r.info.status;
421         info2.untiltime = r.info.untiltime;
422
423         /* Create Device Mode */
424         if (r.devmode != NULL) {
425                 ZERO_STRUCT(dm);
426
427                 dm.bitsperpel              = r.devmode->bitsperpel;
428                 dm.collate                 = r.devmode->collate;
429                 dm.color                   = r.devmode->color;
430                 dm.copies                  = r.devmode->copies;
431                 dm.defaultsource           = r.devmode->defaultsource;
432                 dm.devicename              = r.devmode->devicename;
433                 dm.displayflags            = r.devmode->displayflags;
434                 dm.displayfrequency        = r.devmode->displayfrequency;
435                 dm.dithertype              = r.devmode->dithertype;
436                 dm.driverversion           = r.devmode->driverversion;
437                 dm.duplex                  = r.devmode->duplex;
438                 dm.fields                  = r.devmode->fields;
439                 dm.formname                = r.devmode->formname;
440                 dm.icmintent               = r.devmode->icmintent;
441                 dm.icmmethod               = r.devmode->icmmethod;
442                 dm.logpixels               = r.devmode->logpixels;
443                 dm.mediatype               = r.devmode->mediatype;
444                 dm.orientation             = r.devmode->orientation;
445                 dm.panningheight           = r.devmode->pelsheight;
446                 dm.panningwidth            = r.devmode->panningwidth;
447                 dm.paperlength             = r.devmode->paperlength;
448                 dm.papersize               = r.devmode->papersize;
449                 dm.paperwidth              = r.devmode->paperwidth;
450                 dm.pelsheight              = r.devmode->pelsheight;
451                 dm.pelswidth               = r.devmode->pelswidth;
452                 dm.printquality            = r.devmode->printquality;
453                 dm.scale                   = r.devmode->scale;
454                 dm.specversion             = r.devmode->specversion;
455                 dm.ttoption                = r.devmode->ttoption;
456                 dm.yresolution             = r.devmode->yresolution;
457
458                 if (r.devmode->nt_dev_private != NULL) {
459                         dm.driverextra_data.data   = r.devmode->nt_dev_private->data;
460                         dm.driverextra_data.length = r.devmode->nt_dev_private->length;
461                         dm.__driverextra_length    = r.devmode->nt_dev_private->length;
462                 }
463
464                 devmode_ctr.devmode = &dm;
465
466                 info2.devmode_ptr = 1;
467         }
468
469         info_ctr.info.info2 = &info2;
470         info_ctr.level = 2;
471
472         status = rpccli_spoolss_SetPrinter(pipe_hnd,
473                                            mem_ctx,
474                                            &hnd,
475                                            &info_ctr,
476                                            &devmode_ctr,
477                                            &secdesc_ctr,
478                                            0, /* command */
479                                            &result);
480         if (!NT_STATUS_IS_OK(status)) {
481                 d_printf(_("\tSetPrinter(%s) level 2 refused -- %s.\n"),
482                         key_name, nt_errstr(status));
483                 goto done;
484         }
485
486         /* migrate printerdata */
487         for (j = 0; j < r.count; j++) {
488                 char *valuename;
489                 char *keyname;
490
491                 if (r.printer_data[j].type == REG_NONE) {
492                         continue;
493                 }
494
495                 keyname = CONST_DISCARD(char *, r.printer_data[j].name);
496                 valuename = strchr(keyname, '\\');
497                 if (valuename == NULL) {
498                         continue;
499                 } else {
500                         valuename[0] = '\0';
501                         valuename++;
502                 }
503
504                 printf("          data: %s\\%s\n", keyname, valuename);
505
506                 status = rpccli_spoolss_SetPrinterDataEx(pipe_hnd,
507                                                          mem_ctx,
508                                                          &hnd,
509                                                          keyname,
510                                                          valuename,
511                                                          r.printer_data[j].type,
512                                                          r.printer_data[j].data.data,
513                                                          r.printer_data[j].data.length,
514                                                          &result);
515                 if (!NT_STATUS_IS_OK(status)) {
516                         d_printf(_("\tSetPrinterDataEx: printer [%s], keyname [%s], valuename [%s] refused -- %s.\n"),
517                                 key_name, keyname, valuename, nt_errstr(status));
518                         break;
519                 }
520         }
521
522  done:
523         rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
524
525         return status;
526 }
527
528 static NTSTATUS migrate_secdesc(TALLOC_CTX *mem_ctx,
529                                 struct rpc_pipe_client *pipe_hnd,
530                                 const char *key_name,
531                                 unsigned char *data,
532                                 size_t length)
533 {
534         struct policy_handle hnd;
535         enum ndr_err_code ndr_err;
536         struct sec_desc_buf secdesc_ctr;
537         struct spoolss_SetPrinterInfo3 info3;
538         struct spoolss_SetPrinterInfoCtr info_ctr;
539         struct spoolss_DevmodeContainer devmode_ctr;
540         DATA_BLOB blob;
541         NTSTATUS status;
542         WERROR result;
543
544         if (strequal(key_name, "printers")) {
545                 return NT_STATUS_OK;
546         }
547
548         blob = data_blob_const(data, length);
549
550         ZERO_STRUCT(secdesc_ctr);
551
552         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &secdesc_ctr,
553                    (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
554         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
555                 d_fprintf(stderr, _("security descriptor pull failed: %s\n"),
556                           ndr_errstr(ndr_err));
557                 return NT_STATUS_NO_MEMORY;
558         }
559
560         d_printf(_("Migrating Security Descriptor: %s\n"), key_name);
561
562         result = rpccli_spoolss_openprinter_ex(pipe_hnd,
563                                                mem_ctx,
564                                                key_name,
565                                                MAXIMUM_ALLOWED_ACCESS,
566                                                &hnd);
567         if (!W_ERROR_IS_OK(result)) {
568                 d_fprintf(stderr, _("\tOpenPrinter(%s) failed: %s\n"),
569                                   key_name, win_errstr(result));
570                 return werror_to_ntstatus(result);
571         }
572
573         ZERO_STRUCT(devmode_ctr);
574
575         info3.sec_desc_ptr = 1;
576
577         info_ctr.info.info3 = &info3;
578         info_ctr.level = 3;
579
580         status = rpccli_spoolss_SetPrinter(pipe_hnd,
581                                            mem_ctx,
582                                            &hnd,
583                                            &info_ctr,
584                                            &devmode_ctr,
585                                            &secdesc_ctr,
586                                            0, /* command */
587                                            &result);
588         if (!NT_STATUS_IS_OK(status)) {
589                 d_printf(_("\tSetPrinter(%s) level 3 refused -- %s.\n"),
590                         key_name, nt_errstr(status));
591         }
592
593         rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
594
595         return status;
596 }
597
598 static NTSTATUS printing_migrate_internal(struct net_context *c,
599                                           const struct dom_sid *domain_sid,
600                                           const char *domain_name,
601                                           struct cli_state *cli,
602                                           struct rpc_pipe_client *pipe_hnd,
603                                           TALLOC_CTX *mem_ctx,
604                                           int argc,
605                                           const char **argv)
606 {
607         TALLOC_CTX *tmp_ctx;
608         TDB_CONTEXT *tdb;
609         TDB_DATA kbuf, newkey, dbuf;
610         NTSTATUS status;
611
612         tmp_ctx = talloc_new(mem_ctx);
613         if (tmp_ctx == NULL) {
614                 return NT_STATUS_NO_MEMORY;
615         }
616
617         tdb = tdb_open_log(argv[0], 0, TDB_DEFAULT, O_RDONLY, 0600);
618         if (tdb == NULL) {
619                 d_fprintf(stderr, _("failed to open tdb file: %s\n"), argv[0]);
620                 status = NT_STATUS_NO_SUCH_FILE;
621                 goto done;
622         }
623
624         for (kbuf = tdb_firstkey(tdb);
625              kbuf.dptr;
626              newkey = tdb_nextkey(tdb, kbuf), free(kbuf.dptr), kbuf = newkey)
627         {
628                 dbuf = tdb_fetch(tdb, kbuf);
629                 if (!dbuf.dptr) {
630                         continue;
631                 }
632
633                 if (strncmp((const char *) kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
634                         migrate_form(tmp_ctx,
635                                      pipe_hnd,
636                                      (const char *) kbuf.dptr + strlen(FORMS_PREFIX),
637                                      dbuf.dptr,
638                                      dbuf.dsize);
639                         SAFE_FREE(dbuf.dptr);
640                         continue;
641                 }
642
643                 if (strncmp((const char *) kbuf.dptr, DRIVERS_PREFIX, strlen(DRIVERS_PREFIX)) == 0) {
644                         migrate_driver(tmp_ctx,
645                                        pipe_hnd,
646                                        (const char *) kbuf.dptr + strlen(DRIVERS_PREFIX),
647                                        dbuf.dptr,
648                                        dbuf.dsize);
649                         SAFE_FREE(dbuf.dptr);
650                         continue;
651                 }
652
653                 if (strncmp((const char *) kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
654                         migrate_printer(tmp_ctx,
655                                         pipe_hnd,
656                                         (const char *) kbuf.dptr + strlen(PRINTERS_PREFIX),
657                                         dbuf.dptr,
658                                         dbuf.dsize);
659                         SAFE_FREE(dbuf.dptr);
660                         continue;
661                 }
662
663                 if (strncmp((const char *) kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
664                         migrate_secdesc(tmp_ctx,
665                                         pipe_hnd,
666                                         (const char *) kbuf.dptr + strlen(SECDESC_PREFIX),
667                                         dbuf.dptr,
668                                         dbuf.dsize);
669                         SAFE_FREE(dbuf.dptr);
670                         continue;
671                 }
672
673         }
674
675         status = NT_STATUS_OK;
676
677  done:
678         talloc_free(tmp_ctx);
679         return status;
680 }
681
682 static int net_printing_migrate(struct net_context *c,
683                                 int argc,
684                                 const char **argv)
685 {
686         if (argc < 1 || c->display_usage) {
687                 d_printf(  "%s\n"
688                            "net printing migrate <file.tdb>\n"
689                            "    %s\n",
690                          _("Usage:"),
691                          _("Migrate tdb printing files to new storage"));
692                 return 0;
693         }
694
695         return run_rpc_command(c,
696                                NULL,
697                                &ndr_table_spoolss.syntax_id,
698                                0,
699                                printing_migrate_internal,
700                                argc,
701                                argv);
702 }
703 /**
704  * 'net printing' entrypoint.
705  * @param argc  Standard main() style argc.
706  * @param argv  Standard main() style argv. Initial components are already
707  *              stripped.
708  **/
709
710 int net_printing(struct net_context *c, int argc, const char **argv)
711 {
712         int ret = -1;
713
714         struct functable func[] = {
715                 {
716                         "dump",
717                         net_printing_dump,
718                         NET_TRANSPORT_LOCAL,
719                         N_("Dump eventlog"),
720                         N_("net printing dump\n"
721                            "    Dump tdb printing file")
722                 },
723
724                 {
725                         "migrate",
726                         net_printing_migrate,
727                         NET_TRANSPORT_LOCAL | NET_TRANSPORT_RPC,
728                         N_("Migrate printer databases"),
729                         N_("net printing migrate\n"
730                            "    Migrate tdb printing files to new storage")
731                 },
732
733         { NULL, NULL, 0, NULL, NULL }
734         };
735
736         ret = net_run_function(c, argc, argv, "net printing", func);
737
738         return ret;
739 }