s3-spoolss: fix some debug statements.
[kamenim/samba.git] / source3 / printing / nt_printing_migrate.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *
5  *  Copyright (c) Andreas Schneider            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 #include "includes.h"
22 #include "printing/nt_printing_migrate.h"
23
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 NTSTATUS migrate_form(TALLOC_CTX *mem_ctx,
35                          struct rpc_pipe_client *pipe_hnd,
36                          const char *key_name,
37                          unsigned char *data,
38                          size_t length)
39 {
40         struct spoolss_DevmodeContainer devmode_ctr;
41         struct policy_handle hnd;
42         enum ndr_err_code ndr_err;
43         struct ntprinting_form r;
44         union spoolss_AddFormInfo f;
45         struct spoolss_AddFormInfo1 f1;
46         const char *srv_name_slash;
47         DATA_BLOB blob;
48         NTSTATUS status;
49         WERROR result;
50
51
52         blob = data_blob_const(data, length);
53
54         ZERO_STRUCT(r);
55
56         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
57                    (ndr_pull_flags_fn_t)ndr_pull_ntprinting_form);
58         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
59                 DEBUG(2, ("Form pull failed: %s\n",
60                           ndr_errstr(ndr_err)));
61                 return NT_STATUS_NO_MEMORY;
62         }
63
64         /* Don't migrate builtin forms */
65         if (r.flag == SPOOLSS_FORM_BUILTIN) {
66                 return NT_STATUS_OK;
67         }
68
69         DEBUG(2, ("Migrating Form: %s\n", key_name));
70
71         srv_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
72         if (srv_name_slash == NULL) {
73                 return NT_STATUS_NO_MEMORY;
74         }
75
76         ZERO_STRUCT(devmode_ctr);
77
78         status = rpccli_spoolss_OpenPrinter(pipe_hnd,
79                                             mem_ctx,
80                                             srv_name_slash,
81                                             NULL,
82                                             devmode_ctr,
83                                             SEC_FLAG_MAXIMUM_ALLOWED,
84                                             &hnd,
85                                             &result);
86         if (!NT_STATUS_IS_OK(status)) {
87                 if (!W_ERROR_IS_OK(result)) {
88                         status = werror_to_ntstatus(result);
89                 }
90                 DEBUG(2, ("OpenPrinter(%s) failed: %s\n",
91                           srv_name_slash, nt_errstr(status)));
92                 return status;
93         }
94
95         f1.form_name = key_name;
96         f1.flags = r.flag;
97
98         f1.size.width = r.width;
99         f1.size.height = r.length;
100
101         f1.area.top = r.top;
102         f1.area.right = r.right;
103         f1.area.bottom = r.bottom;
104         f1.area.left = r.left;
105
106         f.info1 = &f1;
107
108         status = rpccli_spoolss_AddForm(pipe_hnd,
109                                         mem_ctx,
110                                         &hnd,
111                                         1,
112                                         f,
113                                         &result);
114         if (!NT_STATUS_IS_OK(status)) {
115                 DEBUG(2, ("AddForm(%s) refused -- %s.\n",
116                           f.info1->form_name, nt_errstr(status)));
117         }
118
119         rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
120
121         return status;
122 }
123
124 static NTSTATUS migrate_driver(TALLOC_CTX *mem_ctx,
125                                struct rpc_pipe_client *pipe_hnd,
126                                const char *key_name,
127                                unsigned char *data,
128                                size_t length)
129 {
130         const char *srv_name_slash;
131         enum ndr_err_code ndr_err;
132         struct ntprinting_driver r;
133         struct spoolss_AddDriverInfoCtr d;
134         struct spoolss_AddDriverInfo3 d3;
135         struct spoolss_StringArray a;
136         DATA_BLOB blob;
137         NTSTATUS status;
138         WERROR result;
139
140         blob = data_blob_const(data, length);
141
142         ZERO_STRUCT(r);
143
144         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
145                    (ndr_pull_flags_fn_t)ndr_pull_ntprinting_driver);
146         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
147                 DEBUG(2, ("Driver pull failed: %s\n",
148                           ndr_errstr(ndr_err)));
149                 return NT_STATUS_NO_MEMORY;
150         }
151
152         DEBUG(2, ("Migrating Printer Driver: %s\n", key_name));
153
154         srv_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
155         if (srv_name_slash == NULL) {
156                 return NT_STATUS_NO_MEMORY;
157         }
158
159         ZERO_STRUCT(d3);
160         ZERO_STRUCT(a);
161
162         a.string = r.dependent_files;
163
164         d3.architecture = r.environment;
165         d3.config_file = r.configfile;
166         d3.data_file = r.datafile;
167         d3.default_datatype = r.defaultdatatype;
168         d3.dependent_files = &a;
169         d3.driver_path = r.driverpath;
170         d3.help_file = r.helpfile;
171         d3.monitor_name = r.monitorname;
172         d3.driver_name = r.name;
173         d3.version = r.version;
174
175         d.level = 3;
176         d.info.info3 = &d3;
177
178         status = rpccli_spoolss_AddPrinterDriver(pipe_hnd,
179                                                  mem_ctx,
180                                                  srv_name_slash,
181                                                  &d,
182                                                  &result);
183         if (!NT_STATUS_IS_OK(status)) {
184                 if (!W_ERROR_IS_OK(result)) {
185                         status = werror_to_ntstatus(result);
186                 }
187                 DEBUG(2, ("AddPrinterDriver(%s) refused -- %s.\n",
188                           d3.driver_name, nt_errstr(status)));
189         }
190
191         return status;
192 }
193
194 static NTSTATUS migrate_printer(TALLOC_CTX *mem_ctx,
195                                 struct rpc_pipe_client *pipe_hnd,
196                                 const char *key_name,
197                                 unsigned char *data,
198                                 size_t length)
199 {
200         struct policy_handle hnd;
201         enum ndr_err_code ndr_err;
202         struct ntprinting_printer r;
203         struct spoolss_SetPrinterInfo2 info2;
204         struct spoolss_DeviceMode dm;
205         struct spoolss_SetPrinterInfoCtr info_ctr;
206         struct spoolss_DevmodeContainer devmode_ctr;
207         struct sec_desc_buf secdesc_ctr;
208         DATA_BLOB blob;
209         NTSTATUS status;
210         WERROR result;
211         int j;
212
213         if (strequal(key_name, "printers")) {
214                 return NT_STATUS_OK;
215         }
216
217         blob = data_blob_const(data, length);
218
219         ZERO_STRUCT(r);
220
221         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
222                    (ndr_pull_flags_fn_t) ndr_pull_ntprinting_printer);
223         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
224                 DEBUG(2, ("printer pull failed: %s\n",
225                           ndr_errstr(ndr_err)));
226                 return NT_STATUS_NO_MEMORY;
227         }
228
229         DEBUG(2, ("Migrating Printer: %s\n", key_name));
230
231         ZERO_STRUCT(devmode_ctr);
232
233         status = rpccli_spoolss_OpenPrinter(pipe_hnd,
234                                             mem_ctx,
235                                             key_name,
236                                             NULL,
237                                             devmode_ctr,
238                                             SEC_FLAG_MAXIMUM_ALLOWED,
239                                             &hnd,
240                                             &result);
241         if (!NT_STATUS_IS_OK(status)) {
242                 if (!W_ERROR_IS_OK(result)) {
243                         status = werror_to_ntstatus(result);
244                 }
245                 DEBUG(2, ("OpenPrinter(%s) failed: %s\n",
246                           key_name, win_errstr(result)));
247                 return status;
248         }
249
250         /* Create printer info level 2 */
251         ZERO_STRUCT(info2);
252         ZERO_STRUCT(secdesc_ctr);
253
254         info2.attributes = r.info.attributes;
255         info2.averageppm = r.info.averageppm;
256         info2.cjobs = r.info.cjobs;
257         info2.comment = r.info.comment;
258         info2.datatype = r.info.datatype;
259         info2.defaultpriority = r.info.default_priority;
260         info2.drivername = r.info.drivername;
261         info2.location = r.info.location;
262         info2.parameters = r.info.parameters;
263         info2.portname = r.info.portname;
264         info2.printername = r.info.printername;
265         info2.printprocessor = r.info.printprocessor;
266         info2.priority = r.info.priority;
267         info2.sepfile = r.info.sepfile;
268         info2.sharename = r.info.sharename;
269         info2.starttime = r.info.starttime;
270         info2.status = r.info.status;
271         info2.untiltime = r.info.untiltime;
272
273         /* Create Device Mode */
274         if (r.devmode != NULL) {
275                 ZERO_STRUCT(dm);
276
277                 dm.bitsperpel              = r.devmode->bitsperpel;
278                 dm.collate                 = r.devmode->collate;
279                 dm.color                   = r.devmode->color;
280                 dm.copies                  = r.devmode->copies;
281                 dm.defaultsource           = r.devmode->defaultsource;
282                 dm.devicename              = r.devmode->devicename;
283                 dm.displayflags            = r.devmode->displayflags;
284                 dm.displayfrequency        = r.devmode->displayfrequency;
285                 dm.dithertype              = r.devmode->dithertype;
286                 dm.driverversion           = r.devmode->driverversion;
287                 dm.duplex                  = r.devmode->duplex;
288                 dm.fields                  = r.devmode->fields;
289                 dm.formname                = r.devmode->formname;
290                 dm.icmintent               = r.devmode->icmintent;
291                 dm.icmmethod               = r.devmode->icmmethod;
292                 dm.logpixels               = r.devmode->logpixels;
293                 dm.mediatype               = r.devmode->mediatype;
294                 dm.orientation             = r.devmode->orientation;
295                 dm.panningheight           = r.devmode->pelsheight;
296                 dm.panningwidth            = r.devmode->panningwidth;
297                 dm.paperlength             = r.devmode->paperlength;
298                 dm.papersize               = r.devmode->papersize;
299                 dm.paperwidth              = r.devmode->paperwidth;
300                 dm.pelsheight              = r.devmode->pelsheight;
301                 dm.pelswidth               = r.devmode->pelswidth;
302                 dm.printquality            = r.devmode->printquality;
303                 dm.scale                   = r.devmode->scale;
304                 dm.specversion             = r.devmode->specversion;
305                 dm.ttoption                = r.devmode->ttoption;
306                 dm.yresolution             = r.devmode->yresolution;
307
308                 if (r.devmode->nt_dev_private != NULL) {
309                         dm.driverextra_data.data   = r.devmode->nt_dev_private->data;
310                         dm.driverextra_data.length = r.devmode->nt_dev_private->length;
311                         dm.__driverextra_length    = r.devmode->nt_dev_private->length;
312                 }
313
314                 devmode_ctr.devmode = &dm;
315
316                 info2.devmode_ptr = 1;
317         }
318
319         info_ctr.info.info2 = &info2;
320         info_ctr.level = 2;
321
322         status = rpccli_spoolss_SetPrinter(pipe_hnd,
323                                            mem_ctx,
324                                            &hnd,
325                                            &info_ctr,
326                                            &devmode_ctr,
327                                            &secdesc_ctr,
328                                            0, /* command */
329                                            &result);
330         if (!NT_STATUS_IS_OK(status)) {
331                 DEBUG(2, ("SetPrinter(%s) level 2 refused -- %s.\n",
332                           key_name, nt_errstr(status)));
333                 goto done;
334         }
335
336         /* migrate printerdata */
337         for (j = 0; j < r.count; j++) {
338                 char *valuename;
339                 char *keyname;
340
341                 if (r.printer_data[j].type == REG_NONE) {
342                         continue;
343                 }
344
345                 keyname = CONST_DISCARD(char *, r.printer_data[j].name);
346                 valuename = strchr(keyname, '\\');
347                 if (valuename == NULL) {
348                         continue;
349                 } else {
350                         valuename[0] = '\0';
351                         valuename++;
352                 }
353
354                 status = rpccli_spoolss_SetPrinterDataEx(pipe_hnd,
355                                                          mem_ctx,
356                                                          &hnd,
357                                                          keyname,
358                                                          valuename,
359                                                          r.printer_data[j].type,
360                                                          r.printer_data[j].data.data,
361                                                          r.printer_data[j].data.length,
362                                                          &result);
363                 if (!NT_STATUS_IS_OK(status)) {
364                         DEBUG(2, ("SetPrinterDataEx: printer [%s], keyname [%s], "
365                                   "valuename [%s] refused -- %s.\n",
366                                   key_name, keyname, valuename,
367                                   nt_errstr(status)));
368                         break;
369                 }
370         }
371
372  done:
373         rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
374
375         return status;
376 }
377
378 static NTSTATUS migrate_secdesc(TALLOC_CTX *mem_ctx,
379                                 struct rpc_pipe_client *pipe_hnd,
380                                 const char *key_name,
381                                 unsigned char *data,
382                                 size_t length)
383 {
384         struct policy_handle hnd;
385         enum ndr_err_code ndr_err;
386         struct sec_desc_buf secdesc_ctr;
387         struct spoolss_SetPrinterInfo3 info3;
388         struct spoolss_SetPrinterInfoCtr info_ctr;
389         struct spoolss_DevmodeContainer devmode_ctr;
390         DATA_BLOB blob;
391         NTSTATUS status;
392         WERROR result;
393
394         if (strequal(key_name, "printers")) {
395                 return NT_STATUS_OK;
396         }
397
398         blob = data_blob_const(data, length);
399
400         ZERO_STRUCT(secdesc_ctr);
401
402         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &secdesc_ctr,
403                    (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
404         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
405                 DEBUG(2, ("security descriptor pull failed: %s\n",
406                           ndr_errstr(ndr_err)));
407                 return NT_STATUS_NO_MEMORY;
408         }
409
410         DEBUG(2, ("Migrating Security Descriptor: %s\n", key_name));
411
412         ZERO_STRUCT(devmode_ctr);
413
414         status = rpccli_spoolss_OpenPrinter(pipe_hnd,
415                                             mem_ctx,
416                                             key_name,
417                                             NULL,
418                                             devmode_ctr,
419                                             SEC_FLAG_MAXIMUM_ALLOWED,
420                                             &hnd,
421                                             &result);
422         if (!NT_STATUS_IS_OK(status)) {
423                 if (W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME, result)) {
424                         DEBUG(3, ("Ignoring missing printer %s\n", key_name));
425                         return NT_STATUS_OK;
426                 }
427                 if (!W_ERROR_IS_OK(result)) {
428                         status = werror_to_ntstatus(result);
429                 }
430                 DEBUG(2, ("OpenPrinter(%s) failed: %s\n",
431                           key_name, nt_errstr(status)));
432                 return status;
433         }
434
435         ZERO_STRUCT(devmode_ctr);
436
437         info3.sec_desc_ptr = 1;
438
439         info_ctr.info.info3 = &info3;
440         info_ctr.level = 3;
441
442         status = rpccli_spoolss_SetPrinter(pipe_hnd,
443                                            mem_ctx,
444                                            &hnd,
445                                            &info_ctr,
446                                            &devmode_ctr,
447                                            &secdesc_ctr,
448                                            0, /* command */
449                                            &result);
450         if (!NT_STATUS_IS_OK(status)) {
451                 DEBUG(2, ("SetPrinter(%s) level 3 refused -- %s.\n",
452                           key_name, nt_errstr(status)));
453         }
454
455         rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
456
457         return status;
458 }
459
460 static int rename_file_with_suffix(TALLOC_CTX *mem_ctx,
461                                    const char *path,
462                                    const char *suffix)
463 {
464         int rc = -1;
465         char *dst_path;
466
467         dst_path = talloc_asprintf(mem_ctx, "%s%s", path, suffix);
468         if (dst_path == NULL) {
469                 DEBUG(3, ("error out of memory\n"));
470                 return rc;
471         }
472
473         rc = (rename(path, dst_path) != 0);
474
475         if (rc == 0) {
476                 DEBUG(5, ("moved '%s' to '%s'\n", path, dst_path));
477         } else if (errno == ENOENT) {
478                 DEBUG(3, ("file '%s' does not exist - so not moved\n", path));
479                 rc = 0;
480         } else {
481                 DEBUG(3, ("error renaming %s to %s: %s\n", path, dst_path,
482                           strerror(errno)));
483         }
484
485         TALLOC_FREE(dst_path);
486         return rc;
487 }
488
489 static NTSTATUS migrate_internal(TALLOC_CTX *mem_ctx,
490                                  const char *tdb_path,
491                                  struct rpc_pipe_client *pipe_hnd)
492 {
493         const char *backup_suffix = ".bak";
494         TDB_DATA kbuf, newkey, dbuf;
495         TDB_CONTEXT *tdb;
496         NTSTATUS status;
497         int rc;
498
499         tdb = tdb_open_log(tdb_path, 0, TDB_DEFAULT, O_RDONLY, 0600);
500         if (tdb == NULL && errno == ENOENT) {
501                 /* if we have no printers database then migration is
502                    considered successful */
503                 DEBUG(4, ("No printers database to migrate in %s\n", tdb_path));
504                 return NT_STATUS_OK;
505         }
506         if (tdb == NULL) {
507                 DEBUG(2, ("Failed to open tdb file: %s\n", tdb_path));
508                 return NT_STATUS_NO_SUCH_FILE;
509         }
510
511         for (kbuf = tdb_firstkey(tdb);
512              kbuf.dptr;
513              newkey = tdb_nextkey(tdb, kbuf), free(kbuf.dptr), kbuf = newkey)
514         {
515                 dbuf = tdb_fetch(tdb, kbuf);
516                 if (!dbuf.dptr) {
517                         continue;
518                 }
519
520                 if (strncmp((const char *) kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
521                         status = migrate_form(mem_ctx,
522                                               pipe_hnd,
523                                               (const char *) kbuf.dptr + strlen(FORMS_PREFIX),
524                                               dbuf.dptr,
525                                               dbuf.dsize);
526                         SAFE_FREE(dbuf.dptr);
527                         if (!NT_STATUS_IS_OK(status)) {
528                                 tdb_close(tdb);
529                                 return status;
530                         }
531                         continue;
532                 }
533
534                 if (strncmp((const char *) kbuf.dptr, DRIVERS_PREFIX, strlen(DRIVERS_PREFIX)) == 0) {
535                         status = migrate_driver(mem_ctx,
536                                                 pipe_hnd,
537                                                 (const char *) kbuf.dptr + strlen(DRIVERS_PREFIX),
538                                                 dbuf.dptr,
539                                                 dbuf.dsize);
540                         SAFE_FREE(dbuf.dptr);
541                         if (!NT_STATUS_IS_OK(status)) {
542                                 tdb_close(tdb);
543                                 return status;
544                         }
545                         continue;
546                 }
547
548                 if (strncmp((const char *) kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
549                         status = migrate_printer(mem_ctx,
550                                                  pipe_hnd,
551                                                  (const char *) kbuf.dptr + strlen(PRINTERS_PREFIX),
552                                                  dbuf.dptr,
553                                                  dbuf.dsize);
554                         SAFE_FREE(dbuf.dptr);
555                         if (!NT_STATUS_IS_OK(status)) {
556                                 tdb_close(tdb);
557                                 return status;
558                         }
559                         continue;
560                 }
561
562                 if (strncmp((const char *) kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
563                         status = migrate_secdesc(mem_ctx,
564                                                  pipe_hnd,
565                                                  (const char *) kbuf.dptr + strlen(SECDESC_PREFIX),
566                                                  dbuf.dptr,
567                                                  dbuf.dsize);
568                         SAFE_FREE(dbuf.dptr);
569                         if (!NT_STATUS_IS_OK(status)) {
570                                 tdb_close(tdb);
571                                 return status;
572                         }
573                         continue;
574                 }
575         }
576
577         tdb_close(tdb);
578
579         rc = rename_file_with_suffix(mem_ctx, tdb_path, backup_suffix);
580         if (rc != 0) {
581                 DEBUG(0, ("Error moving tdb to '%s%s'\n",
582                           tdb_path, backup_suffix));
583         }
584
585         return NT_STATUS_OK;
586 }
587
588 bool nt_printing_tdb_migrate(struct messaging_context *msg_ctx)
589 {
590         const char *drivers_path = state_path("ntdrivers.tdb");
591         const char *printers_path = state_path("ntprinters.tdb");
592         const char *forms_path = state_path("ntforms.tdb");
593         bool drivers_exists = file_exist(drivers_path);
594         bool printers_exists = file_exist(printers_path);
595         bool forms_exists = file_exist(forms_path);
596         struct auth_serversupplied_info *server_info;
597         struct rpc_pipe_client *spoolss_pipe = NULL;
598         TALLOC_CTX *tmp_ctx = talloc_stackframe();
599         NTSTATUS status;
600
601         if (!drivers_exists && !printers_exists && !forms_exists) {
602                 return true;
603         }
604
605         status = make_server_info_system(tmp_ctx, &server_info);
606         if (!NT_STATUS_IS_OK(status)) {
607                 DEBUG(0, ("Couldn't create server_info: %s\n",
608                           nt_errstr(status)));
609                 talloc_free(tmp_ctx);
610                 return false;
611         }
612
613         status = rpc_pipe_open_internal(tmp_ctx,
614                                         &ndr_table_spoolss.syntax_id,
615                                         server_info,
616                                         NULL,
617                                         msg_ctx,
618                                         &spoolss_pipe);
619         if (!NT_STATUS_IS_OK(status)) {
620                 DEBUG(0, ("Couldn't open internal spoolss pipe: %s\n",
621                           nt_errstr(status)));
622                 talloc_free(tmp_ctx);
623                 return false;
624         }
625
626         if (drivers_exists) {
627                 status = migrate_internal(tmp_ctx, drivers_path, spoolss_pipe);
628                 if (!NT_STATUS_IS_OK(status)) {
629                         DEBUG(0, ("Couldn't migrate drivers tdb file: %s\n",
630                           nt_errstr(status)));
631                         talloc_free(tmp_ctx);
632                         return false;
633                 }
634         }
635
636         if (printers_exists) {
637                 status = migrate_internal(tmp_ctx, printers_path, spoolss_pipe);
638                 if (!NT_STATUS_IS_OK(status)) {
639                         DEBUG(0, ("Couldn't migrate printers tdb file: %s\n",
640                                   nt_errstr(status)));
641                         talloc_free(tmp_ctx);
642                         return false;
643                 }
644         }
645
646         if (forms_exists) {
647                 status = migrate_internal(tmp_ctx, forms_path, spoolss_pipe);
648                 if (!NT_STATUS_IS_OK(status)) {
649                         DEBUG(0, ("Couldn't migrate forms tdb file: %s\n",
650                                   nt_errstr(status)));
651                         talloc_free(tmp_ctx);
652                         return false;
653                 }
654         }
655
656         talloc_free(tmp_ctx);
657         return true;
658 }