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