s3-rpc_client: move rpc_cli_transport structs and protos to rpc_transport.h
[Samba/gbeck.git] / source3 / printing / nt_printing_migrate.c
blobc62d1c8de5fcef7ab2dea86df52e7b8d8a7d7374
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
5 * Copyright (c) Andreas Schneider 2010.
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.
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.
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/>.
21 #include "includes.h"
22 #include "system/filesys.h"
23 #include "printing/nt_printing_migrate.h"
25 #include "librpc/gen_ndr/ndr_ntprinting.h"
26 #include "librpc/gen_ndr/ndr_spoolss_c.h"
27 #include "rpc_client/cli_spoolss.h"
28 #include "librpc/gen_ndr/ndr_security.h"
29 #include "rpc_server/rpc_ncacn_np.h"
30 #include "auth.h"
32 #define FORMS_PREFIX "FORMS/"
33 #define DRIVERS_PREFIX "DRIVERS/"
34 #define PRINTERS_PREFIX "PRINTERS/"
35 #define SECDESC_PREFIX "SECDESC/"
37 static NTSTATUS migrate_form(TALLOC_CTX *mem_ctx,
38 struct rpc_pipe_client *pipe_hnd,
39 const char *key_name,
40 unsigned char *data,
41 size_t length)
43 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
44 struct spoolss_DevmodeContainer devmode_ctr;
45 struct policy_handle hnd;
46 enum ndr_err_code ndr_err;
47 struct ntprinting_form r;
48 union spoolss_AddFormInfo f;
49 struct spoolss_AddFormInfo1 f1;
50 const char *srv_name_slash;
51 DATA_BLOB blob;
52 NTSTATUS status;
53 WERROR result;
56 blob = data_blob_const(data, length);
58 ZERO_STRUCT(r);
60 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
61 (ndr_pull_flags_fn_t)ndr_pull_ntprinting_form);
62 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
63 DEBUG(2, ("Form pull failed: %s\n",
64 ndr_errstr(ndr_err)));
65 return NT_STATUS_NO_MEMORY;
68 /* Don't migrate builtin forms */
69 if (r.flag == SPOOLSS_FORM_BUILTIN) {
70 return NT_STATUS_OK;
73 DEBUG(2, ("Migrating Form: %s\n", key_name));
75 srv_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
76 if (srv_name_slash == NULL) {
77 return NT_STATUS_NO_MEMORY;
80 ZERO_STRUCT(devmode_ctr);
82 status = dcerpc_spoolss_OpenPrinter(b,
83 mem_ctx,
84 srv_name_slash,
85 NULL,
86 devmode_ctr,
87 SEC_FLAG_MAXIMUM_ALLOWED,
88 &hnd,
89 &result);
90 if (!NT_STATUS_IS_OK(status)) {
91 DEBUG(2, ("dcerpc_spoolss_OpenPrinter(%s) failed: %s\n",
92 srv_name_slash, nt_errstr(status)));
93 return status;
95 if (!W_ERROR_IS_OK(result)) {
96 DEBUG(2, ("OpenPrinter(%s) failed: %s\n",
97 srv_name_slash, win_errstr(result)));
98 status = werror_to_ntstatus(result);
99 return status;
102 f1.form_name = key_name;
103 f1.flags = r.flag;
105 f1.size.width = r.width;
106 f1.size.height = r.length;
108 f1.area.top = r.top;
109 f1.area.right = r.right;
110 f1.area.bottom = r.bottom;
111 f1.area.left = r.left;
113 f.info1 = &f1;
115 status = dcerpc_spoolss_AddForm(b,
116 mem_ctx,
117 &hnd,
120 &result);
121 if (!NT_STATUS_IS_OK(status)) {
122 DEBUG(2, ("dcerpc_spoolss_AddForm(%s) refused -- %s.\n",
123 f.info1->form_name, nt_errstr(status)));
124 } else if (!W_ERROR_IS_OK(result)) {
125 DEBUG(2, ("AddForm(%s) refused -- %s.\n",
126 f.info1->form_name, win_errstr(result)));
127 status = werror_to_ntstatus(result);
130 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &result);
132 return status;
135 static NTSTATUS migrate_driver(TALLOC_CTX *mem_ctx,
136 struct rpc_pipe_client *pipe_hnd,
137 const char *key_name,
138 unsigned char *data,
139 size_t length)
141 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
142 const char *srv_name_slash;
143 enum ndr_err_code ndr_err;
144 struct ntprinting_driver r;
145 struct spoolss_AddDriverInfoCtr d;
146 struct spoolss_AddDriverInfo3 d3;
147 struct spoolss_StringArray a;
148 DATA_BLOB blob;
149 NTSTATUS status;
150 WERROR result;
152 blob = data_blob_const(data, length);
154 ZERO_STRUCT(r);
156 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
157 (ndr_pull_flags_fn_t)ndr_pull_ntprinting_driver);
158 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
159 DEBUG(2, ("Driver pull failed: %s\n",
160 ndr_errstr(ndr_err)));
161 return NT_STATUS_NO_MEMORY;
164 DEBUG(2, ("Migrating Printer Driver: %s\n", key_name));
166 srv_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
167 if (srv_name_slash == NULL) {
168 return NT_STATUS_NO_MEMORY;
171 ZERO_STRUCT(d3);
172 ZERO_STRUCT(a);
174 a.string = r.dependent_files;
176 d3.architecture = r.environment;
177 d3.config_file = r.configfile;
178 d3.data_file = r.datafile;
179 d3.default_datatype = r.defaultdatatype;
180 d3.dependent_files = &a;
181 d3.driver_path = r.driverpath;
182 d3.help_file = r.helpfile;
183 d3.monitor_name = r.monitorname;
184 d3.driver_name = r.name;
185 d3.version = r.version;
187 d.level = 3;
188 d.info.info3 = &d3;
190 status = dcerpc_spoolss_AddPrinterDriver(b,
191 mem_ctx,
192 srv_name_slash,
194 &result);
195 if (!NT_STATUS_IS_OK(status)) {
196 DEBUG(2, ("dcerpc_spoolss_AddPrinterDriver(%s) refused -- %s.\n",
197 d3.driver_name, nt_errstr(status)));
198 } else if (!W_ERROR_IS_OK(result)) {
199 DEBUG(2, ("AddPrinterDriver(%s) refused -- %s.\n",
200 d3.driver_name, win_errstr(result)));
201 status = werror_to_ntstatus(result);
204 return status;
207 static NTSTATUS migrate_printer(TALLOC_CTX *mem_ctx,
208 struct rpc_pipe_client *pipe_hnd,
209 const char *key_name,
210 unsigned char *data,
211 size_t length)
213 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
214 struct policy_handle hnd;
215 enum ndr_err_code ndr_err;
216 struct ntprinting_printer r;
217 struct spoolss_SetPrinterInfo2 info2;
218 struct spoolss_DeviceMode dm;
219 struct spoolss_SetPrinterInfoCtr info_ctr;
220 struct spoolss_DevmodeContainer devmode_ctr;
221 struct sec_desc_buf secdesc_ctr;
222 DATA_BLOB blob;
223 NTSTATUS status;
224 WERROR result;
225 int j;
227 if (strequal(key_name, "printers")) {
228 return NT_STATUS_OK;
231 blob = data_blob_const(data, length);
233 ZERO_STRUCT(r);
235 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
236 (ndr_pull_flags_fn_t) ndr_pull_ntprinting_printer);
237 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
238 DEBUG(2, ("printer pull failed: %s\n",
239 ndr_errstr(ndr_err)));
240 return NT_STATUS_NO_MEMORY;
243 DEBUG(2, ("Migrating Printer: %s\n", key_name));
245 ZERO_STRUCT(devmode_ctr);
247 status = dcerpc_spoolss_OpenPrinter(b,
248 mem_ctx,
249 key_name,
250 NULL,
251 devmode_ctr,
252 SEC_FLAG_MAXIMUM_ALLOWED,
253 &hnd,
254 &result);
255 if (!NT_STATUS_IS_OK(status)) {
256 DEBUG(2, ("dcerpc_spoolss_OpenPrinter(%s) failed: %s\n",
257 key_name, nt_errstr(status)));
258 return status;
260 if (!W_ERROR_IS_OK(result)) {
261 DEBUG(2, ("OpenPrinter(%s) failed: %s\n",
262 key_name, win_errstr(result)));
263 status = werror_to_ntstatus(result);
264 return status;
267 /* Create printer info level 2 */
268 ZERO_STRUCT(info2);
269 ZERO_STRUCT(secdesc_ctr);
271 info2.attributes = r.info.attributes;
272 info2.averageppm = r.info.averageppm;
273 info2.cjobs = r.info.cjobs;
274 info2.comment = r.info.comment;
275 info2.datatype = r.info.datatype;
276 info2.defaultpriority = r.info.default_priority;
277 info2.drivername = r.info.drivername;
278 info2.location = r.info.location;
279 info2.parameters = r.info.parameters;
280 info2.portname = r.info.portname;
281 info2.printername = r.info.printername;
282 info2.printprocessor = r.info.printprocessor;
283 info2.priority = r.info.priority;
284 info2.sepfile = r.info.sepfile;
285 info2.sharename = r.info.sharename;
286 info2.starttime = r.info.starttime;
287 info2.status = r.info.status;
288 info2.untiltime = r.info.untiltime;
290 /* Create Device Mode */
291 if (r.devmode != NULL) {
292 ZERO_STRUCT(dm);
294 dm.bitsperpel = r.devmode->bitsperpel;
295 dm.collate = r.devmode->collate;
296 dm.color = r.devmode->color;
297 dm.copies = r.devmode->copies;
298 dm.defaultsource = r.devmode->defaultsource;
299 dm.devicename = r.devmode->devicename;
300 dm.displayflags = r.devmode->displayflags;
301 dm.displayfrequency = r.devmode->displayfrequency;
302 dm.dithertype = r.devmode->dithertype;
303 dm.driverversion = r.devmode->driverversion;
304 dm.duplex = r.devmode->duplex;
305 dm.fields = r.devmode->fields;
306 dm.formname = r.devmode->formname;
307 dm.icmintent = r.devmode->icmintent;
308 dm.icmmethod = r.devmode->icmmethod;
309 dm.logpixels = r.devmode->logpixels;
310 dm.mediatype = r.devmode->mediatype;
311 dm.orientation = r.devmode->orientation;
312 dm.panningheight = r.devmode->pelsheight;
313 dm.panningwidth = r.devmode->panningwidth;
314 dm.paperlength = r.devmode->paperlength;
315 dm.papersize = r.devmode->papersize;
316 dm.paperwidth = r.devmode->paperwidth;
317 dm.pelsheight = r.devmode->pelsheight;
318 dm.pelswidth = r.devmode->pelswidth;
319 dm.printquality = r.devmode->printquality;
320 dm.scale = r.devmode->scale;
321 dm.specversion = r.devmode->specversion;
322 dm.ttoption = r.devmode->ttoption;
323 dm.yresolution = r.devmode->yresolution;
325 if (r.devmode->nt_dev_private != NULL) {
326 dm.driverextra_data.data = r.devmode->nt_dev_private->data;
327 dm.driverextra_data.length = r.devmode->nt_dev_private->length;
328 dm.__driverextra_length = r.devmode->nt_dev_private->length;
331 devmode_ctr.devmode = &dm;
333 info2.devmode_ptr = 1;
336 info_ctr.info.info2 = &info2;
337 info_ctr.level = 2;
339 status = dcerpc_spoolss_SetPrinter(b,
340 mem_ctx,
341 &hnd,
342 &info_ctr,
343 &devmode_ctr,
344 &secdesc_ctr,
345 0, /* command */
346 &result);
347 if (!NT_STATUS_IS_OK(status)) {
348 DEBUG(2, ("dcerpc_spoolss_SetPrinter(%s) level 2 refused -- %s.\n",
349 key_name, nt_errstr(status)));
350 goto done;
352 if (!W_ERROR_IS_OK(result)) {
353 DEBUG(2, ("SetPrinter(%s) level 2 refused -- %s.\n",
354 key_name, win_errstr(result)));
355 status = werror_to_ntstatus(result);
356 goto done;
359 /* migrate printerdata */
360 for (j = 0; j < r.count; j++) {
361 char *valuename;
362 char *keyname;
364 if (r.printer_data[j].type == REG_NONE) {
365 continue;
368 keyname = CONST_DISCARD(char *, r.printer_data[j].name);
369 valuename = strchr(keyname, '\\');
370 if (valuename == NULL) {
371 continue;
372 } else {
373 valuename[0] = '\0';
374 valuename++;
377 status = dcerpc_spoolss_SetPrinterDataEx(b,
378 mem_ctx,
379 &hnd,
380 keyname,
381 valuename,
382 r.printer_data[j].type,
383 r.printer_data[j].data.data,
384 r.printer_data[j].data.length,
385 &result);
386 if (!NT_STATUS_IS_OK(status)) {
387 DEBUG(2, ("dcerpc_spoolss_SetPrinterDataEx: "
388 "printer [%s], keyname [%s], "
389 "valuename [%s] refused -- %s.\n",
390 key_name, keyname, valuename,
391 nt_errstr(status)));
392 break;
394 if (!W_ERROR_IS_OK(result)) {
395 DEBUG(2, ("SetPrinterDataEx: printer [%s], keyname [%s], "
396 "valuename [%s] refused -- %s.\n",
397 key_name, keyname, valuename,
398 win_errstr(result)));
399 status = werror_to_ntstatus(result);
400 break;
404 done:
405 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &result);
407 return status;
410 static NTSTATUS migrate_secdesc(TALLOC_CTX *mem_ctx,
411 struct rpc_pipe_client *pipe_hnd,
412 const char *key_name,
413 unsigned char *data,
414 size_t length)
416 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
417 struct policy_handle hnd;
418 enum ndr_err_code ndr_err;
419 struct sec_desc_buf secdesc_ctr;
420 struct spoolss_SetPrinterInfo3 info3;
421 struct spoolss_SetPrinterInfoCtr info_ctr;
422 struct spoolss_DevmodeContainer devmode_ctr;
423 DATA_BLOB blob;
424 NTSTATUS status;
425 WERROR result;
427 if (strequal(key_name, "printers")) {
428 return NT_STATUS_OK;
431 blob = data_blob_const(data, length);
433 ZERO_STRUCT(secdesc_ctr);
435 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &secdesc_ctr,
436 (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
437 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
438 DEBUG(2, ("security descriptor pull failed: %s\n",
439 ndr_errstr(ndr_err)));
440 return NT_STATUS_NO_MEMORY;
443 DEBUG(2, ("Migrating Security Descriptor: %s\n", key_name));
445 ZERO_STRUCT(devmode_ctr);
447 status = dcerpc_spoolss_OpenPrinter(b,
448 mem_ctx,
449 key_name,
450 NULL,
451 devmode_ctr,
452 SEC_FLAG_MAXIMUM_ALLOWED,
453 &hnd,
454 &result);
455 if (!NT_STATUS_IS_OK(status)) {
456 DEBUG(2, ("dcerpc_spoolss_OpenPrinter(%s) failed: %s\n",
457 key_name, nt_errstr(status)));
458 return status;
460 if (W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME, result)) {
461 DEBUG(3, ("Ignoring missing printer %s\n", key_name));
462 return NT_STATUS_OK;
464 if (!W_ERROR_IS_OK(result)) {
465 DEBUG(2, ("OpenPrinter(%s) failed: %s\n",
466 key_name, win_errstr(result)));
467 status = werror_to_ntstatus(result);
468 return status;
471 ZERO_STRUCT(devmode_ctr);
473 info3.sec_desc_ptr = 1;
475 info_ctr.info.info3 = &info3;
476 info_ctr.level = 3;
478 status = dcerpc_spoolss_SetPrinter(b,
479 mem_ctx,
480 &hnd,
481 &info_ctr,
482 &devmode_ctr,
483 &secdesc_ctr,
484 0, /* command */
485 &result);
486 if (!NT_STATUS_IS_OK(status)) {
487 DEBUG(2, ("dcerpc_spoolss_SetPrinter(%s) level 3 refused -- %s.\n",
488 key_name, nt_errstr(status)));
489 } else if (!W_ERROR_IS_OK(result)) {
490 DEBUG(2, ("SetPrinter(%s) level 3 refused -- %s.\n",
491 key_name, win_errstr(result)));
492 status = werror_to_ntstatus(result);
495 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &result);
497 return status;
500 static int rename_file_with_suffix(TALLOC_CTX *mem_ctx,
501 const char *path,
502 const char *suffix)
504 int rc = -1;
505 char *dst_path;
507 dst_path = talloc_asprintf(mem_ctx, "%s%s", path, suffix);
508 if (dst_path == NULL) {
509 DEBUG(3, ("error out of memory\n"));
510 return rc;
513 rc = (rename(path, dst_path) != 0);
515 if (rc == 0) {
516 DEBUG(5, ("moved '%s' to '%s'\n", path, dst_path));
517 } else if (errno == ENOENT) {
518 DEBUG(3, ("file '%s' does not exist - so not moved\n", path));
519 rc = 0;
520 } else {
521 DEBUG(3, ("error renaming %s to %s: %s\n", path, dst_path,
522 strerror(errno)));
525 TALLOC_FREE(dst_path);
526 return rc;
529 static NTSTATUS migrate_internal(TALLOC_CTX *mem_ctx,
530 const char *tdb_path,
531 struct rpc_pipe_client *pipe_hnd)
533 const char *backup_suffix = ".bak";
534 TDB_DATA kbuf, newkey, dbuf;
535 TDB_CONTEXT *tdb;
536 NTSTATUS status;
537 int rc;
539 tdb = tdb_open_log(tdb_path, 0, TDB_DEFAULT, O_RDONLY, 0600);
540 if (tdb == NULL && errno == ENOENT) {
541 /* if we have no printers database then migration is
542 considered successful */
543 DEBUG(4, ("No printers database to migrate in %s\n", tdb_path));
544 return NT_STATUS_OK;
546 if (tdb == NULL) {
547 DEBUG(2, ("Failed to open tdb file: %s\n", tdb_path));
548 return NT_STATUS_NO_SUCH_FILE;
551 for (kbuf = tdb_firstkey(tdb);
552 kbuf.dptr;
553 newkey = tdb_nextkey(tdb, kbuf), free(kbuf.dptr), kbuf = newkey)
555 dbuf = tdb_fetch(tdb, kbuf);
556 if (!dbuf.dptr) {
557 continue;
560 if (strncmp((const char *) kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
561 status = migrate_form(mem_ctx,
562 pipe_hnd,
563 (const char *) kbuf.dptr + strlen(FORMS_PREFIX),
564 dbuf.dptr,
565 dbuf.dsize);
566 SAFE_FREE(dbuf.dptr);
567 if (!NT_STATUS_IS_OK(status)) {
568 tdb_close(tdb);
569 return status;
571 continue;
574 if (strncmp((const char *) kbuf.dptr, DRIVERS_PREFIX, strlen(DRIVERS_PREFIX)) == 0) {
575 status = migrate_driver(mem_ctx,
576 pipe_hnd,
577 (const char *) kbuf.dptr + strlen(DRIVERS_PREFIX),
578 dbuf.dptr,
579 dbuf.dsize);
580 SAFE_FREE(dbuf.dptr);
581 if (!NT_STATUS_IS_OK(status)) {
582 tdb_close(tdb);
583 return status;
585 continue;
588 if (strncmp((const char *) kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
589 status = migrate_printer(mem_ctx,
590 pipe_hnd,
591 (const char *) kbuf.dptr + strlen(PRINTERS_PREFIX),
592 dbuf.dptr,
593 dbuf.dsize);
594 SAFE_FREE(dbuf.dptr);
595 if (!NT_STATUS_IS_OK(status)) {
596 tdb_close(tdb);
597 return status;
599 continue;
602 if (strncmp((const char *) kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
603 status = migrate_secdesc(mem_ctx,
604 pipe_hnd,
605 (const char *) kbuf.dptr + strlen(SECDESC_PREFIX),
606 dbuf.dptr,
607 dbuf.dsize);
608 SAFE_FREE(dbuf.dptr);
609 if (!NT_STATUS_IS_OK(status)) {
610 tdb_close(tdb);
611 return status;
613 continue;
617 tdb_close(tdb);
619 rc = rename_file_with_suffix(mem_ctx, tdb_path, backup_suffix);
620 if (rc != 0) {
621 DEBUG(0, ("Error moving tdb to '%s%s'\n",
622 tdb_path, backup_suffix));
625 return NT_STATUS_OK;
628 bool nt_printing_tdb_migrate(struct messaging_context *msg_ctx)
630 const char *drivers_path = state_path("ntdrivers.tdb");
631 const char *printers_path = state_path("ntprinters.tdb");
632 const char *forms_path = state_path("ntforms.tdb");
633 bool drivers_exists = file_exist(drivers_path);
634 bool printers_exists = file_exist(printers_path);
635 bool forms_exists = file_exist(forms_path);
636 struct auth_serversupplied_info *session_info;
637 struct rpc_pipe_client *spoolss_pipe = NULL;
638 TALLOC_CTX *tmp_ctx = talloc_stackframe();
639 NTSTATUS status;
641 if (!drivers_exists && !printers_exists && !forms_exists) {
642 return true;
645 status = make_session_info_system(tmp_ctx, &session_info);
646 if (!NT_STATUS_IS_OK(status)) {
647 DEBUG(0, ("Couldn't create session_info: %s\n",
648 nt_errstr(status)));
649 talloc_free(tmp_ctx);
650 return false;
653 status = rpc_pipe_open_internal(tmp_ctx,
654 &ndr_table_spoolss.syntax_id,
655 session_info,
656 NULL,
657 msg_ctx,
658 &spoolss_pipe);
659 if (!NT_STATUS_IS_OK(status)) {
660 DEBUG(0, ("Couldn't open internal spoolss pipe: %s\n",
661 nt_errstr(status)));
662 talloc_free(tmp_ctx);
663 return false;
666 if (drivers_exists) {
667 status = migrate_internal(tmp_ctx, drivers_path, spoolss_pipe);
668 if (!NT_STATUS_IS_OK(status)) {
669 DEBUG(0, ("Couldn't migrate drivers tdb file: %s\n",
670 nt_errstr(status)));
671 talloc_free(tmp_ctx);
672 return false;
676 if (printers_exists) {
677 status = migrate_internal(tmp_ctx, printers_path, spoolss_pipe);
678 if (!NT_STATUS_IS_OK(status)) {
679 DEBUG(0, ("Couldn't migrate printers tdb file: %s\n",
680 nt_errstr(status)));
681 talloc_free(tmp_ctx);
682 return false;
686 if (forms_exists) {
687 status = migrate_internal(tmp_ctx, forms_path, spoolss_pipe);
688 if (!NT_STATUS_IS_OK(status)) {
689 DEBUG(0, ("Couldn't migrate forms tdb file: %s\n",
690 nt_errstr(status)));
691 talloc_free(tmp_ctx);
692 return false;
696 talloc_free(tmp_ctx);
697 return true;