/* * Unix SMB/CIFS implementation. * RPC Pipe client / server routines * * Copyright (c) Andreas Schneider 2010. * Copyright (C) Bjoern Baumbach 2011 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ #include "includes.h" #include "printing/nt_printing_migrate.h" #include "rpc_client/rpc_client.h" #include "librpc/gen_ndr/ndr_ntprinting.h" #include "librpc/gen_ndr/ndr_spoolss_c.h" #include "librpc/gen_ndr/ndr_security.h" #include "rpc_client/cli_winreg_spoolss.h" static const char *driver_file_basename(const char *file) { const char *basefile; basefile = strrchr(file, '\\'); if (basefile == NULL) { basefile = file; } else { basefile++; } return basefile; } NTSTATUS printing_tdb_migrate_form(TALLOC_CTX *mem_ctx, struct rpc_pipe_client *winreg_pipe, const char *key_name, unsigned char *data, size_t length) { struct dcerpc_binding_handle *b = winreg_pipe->binding_handle; enum ndr_err_code ndr_err; struct ntprinting_form r; struct spoolss_AddFormInfo1 f1; DATA_BLOB blob; WERROR result; blob = data_blob_const(data, length); ZERO_STRUCT(r); ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r, (ndr_pull_flags_fn_t)ndr_pull_ntprinting_form); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(2, ("Form pull failed: %s\n", ndr_errstr(ndr_err))); return NT_STATUS_NO_MEMORY; } /* Don't migrate builtin forms */ if (r.flag == SPOOLSS_FORM_BUILTIN) { return NT_STATUS_OK; } DEBUG(2, ("Migrating Form: %s\n", key_name)); f1.form_name = key_name; f1.flags = r.flag; f1.size.width = r.width; f1.size.height = r.length; f1.area.top = r.top; f1.area.right = r.right; f1.area.bottom = r.bottom; f1.area.left = r.left; result = winreg_printer_addform1(mem_ctx, b, &f1); if (W_ERROR_EQUAL(result, WERR_FILE_EXISTS)) { /* Don't migrate form if it already exists. */ result = WERR_OK; } if (!W_ERROR_IS_OK(result)) { return werror_to_ntstatus(result); } return NT_STATUS_OK; } NTSTATUS printing_tdb_migrate_driver(TALLOC_CTX *mem_ctx, struct rpc_pipe_client *winreg_pipe, const char *key_name, unsigned char *data, size_t length, bool do_string_conversion) { struct dcerpc_binding_handle *b = winreg_pipe->binding_handle; enum ndr_err_code ndr_err; struct ntprinting_driver r; struct spoolss_AddDriverInfoCtr d; struct spoolss_AddDriverInfo3 d3; struct spoolss_StringArray a; DATA_BLOB blob; WERROR result; const char *driver_name; uint32_t driver_version; int i; blob = data_blob_const(data, length); ZERO_STRUCT(r); if (do_string_conversion) { r.string_flags = LIBNDR_FLAG_STR_ASCII; } ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r, (ndr_pull_flags_fn_t)ndr_pull_ntprinting_driver); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(2, ("Driver pull failed: %s\n", ndr_errstr(ndr_err))); return NT_STATUS_NO_MEMORY; } DEBUG(2, ("Migrating Printer Driver: %s\n", key_name)); ZERO_STRUCT(d3); ZERO_STRUCT(a); /* remove paths from file names */ if (r.dependent_files != NULL) { for (i = 0 ; r.dependent_files[i] != NULL; i++) { r.dependent_files[i] = driver_file_basename(r.dependent_files[i]); } } a.string = r.dependent_files; r.driverpath = driver_file_basename(r.driverpath); r.configfile = driver_file_basename(r.configfile); r.datafile = driver_file_basename(r.datafile); r.helpfile = driver_file_basename(r.helpfile); d3.architecture = r.environment; d3.config_file = r.configfile; d3.data_file = r.datafile; d3.default_datatype = r.defaultdatatype; d3.dependent_files = &a; d3.driver_path = r.driverpath; d3.help_file = r.helpfile; d3.monitor_name = r.monitorname; d3.driver_name = r.name; d3.version = r.version; d.level = 3; d.info.info3 = &d3; result = winreg_add_driver(mem_ctx, b, &d, &driver_name, &driver_version); if (!W_ERROR_IS_OK(result)) { return werror_to_ntstatus(result); } return NT_STATUS_OK; } NTSTATUS printing_tdb_migrate_printer(TALLOC_CTX *mem_ctx, struct rpc_pipe_client *winreg_pipe, const char *key_name, unsigned char *data, size_t length, bool do_string_conversion) { struct dcerpc_binding_handle *b = winreg_pipe->binding_handle; enum ndr_err_code ndr_err; struct ntprinting_printer r; struct spoolss_SetPrinterInfo2 info2; struct spoolss_DeviceMode dm; struct spoolss_DevmodeContainer devmode_ctr; DATA_BLOB blob; NTSTATUS status; WERROR result; int j; uint32_t info2_mask = (SPOOLSS_PRINTER_INFO_ALL) & ~SPOOLSS_PRINTER_INFO_SECDESC; if (strequal(key_name, "printers")) { return NT_STATUS_OK; } blob = data_blob_const(data, length); ZERO_STRUCT(r); if (do_string_conversion) { r.info.string_flags = LIBNDR_FLAG_STR_ASCII; } ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r, (ndr_pull_flags_fn_t) ndr_pull_ntprinting_printer); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(2, ("printer pull failed: %s\n", ndr_errstr(ndr_err))); return NT_STATUS_NO_MEMORY; } DEBUG(2, ("Migrating Printer: %s\n", key_name)); ZERO_STRUCT(devmode_ctr); /* Create printer info level 2 */ ZERO_STRUCT(info2); info2.attributes = r.info.attributes; info2.averageppm = r.info.averageppm; info2.cjobs = r.info.cjobs; info2.comment = r.info.comment; info2.datatype = r.info.datatype; info2.defaultpriority = r.info.default_priority; info2.drivername = r.info.drivername; info2.location = r.info.location; info2.parameters = r.info.parameters; info2.portname = r.info.portname; info2.printername = r.info.printername; info2.printprocessor = r.info.printprocessor; info2.priority = r.info.priority; info2.sepfile = r.info.sepfile; info2.sharename = r.info.sharename; info2.starttime = r.info.starttime; info2.status = r.info.status; info2.untiltime = r.info.untiltime; /* Create Device Mode */ if (r.devmode == NULL) { info2_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE; } else { ZERO_STRUCT(dm); dm.bitsperpel = r.devmode->bitsperpel; dm.collate = r.devmode->collate; dm.color = r.devmode->color; dm.copies = r.devmode->copies; dm.defaultsource = r.devmode->defaultsource; dm.devicename = r.devmode->devicename; dm.displayflags = r.devmode->displayflags; dm.displayfrequency = r.devmode->displayfrequency; dm.dithertype = r.devmode->dithertype; dm.driverversion = r.devmode->driverversion; dm.duplex = r.devmode->duplex; dm.fields = r.devmode->fields; dm.formname = r.devmode->formname; dm.icmintent = r.devmode->icmintent; dm.icmmethod = r.devmode->icmmethod; dm.logpixels = r.devmode->logpixels; dm.mediatype = r.devmode->mediatype; dm.orientation = r.devmode->orientation; dm.panningheight = r.devmode->pelsheight; dm.panningwidth = r.devmode->panningwidth; dm.paperlength = r.devmode->paperlength; dm.papersize = r.devmode->papersize; dm.paperwidth = r.devmode->paperwidth; dm.pelsheight = r.devmode->pelsheight; dm.pelswidth = r.devmode->pelswidth; dm.printquality = r.devmode->printquality; dm.size = r.devmode->size; dm.scale = r.devmode->scale; dm.specversion = r.devmode->specversion; dm.ttoption = r.devmode->ttoption; dm.yresolution = r.devmode->yresolution; if (r.devmode->nt_dev_private != NULL) { dm.driverextra_data.data = r.devmode->nt_dev_private->data; dm.driverextra_data.length = r.devmode->nt_dev_private->length; dm.__driverextra_length = r.devmode->nt_dev_private->length; } devmode_ctr.devmode = &dm; } result = winreg_update_printer(mem_ctx, b, key_name, info2_mask, &info2, &dm, NULL); if (!W_ERROR_IS_OK(result)) { DEBUG(2, ("SetPrinter(%s) level 2 refused -- %s.\n", key_name, win_errstr(result))); status = werror_to_ntstatus(result); goto done; } /* migrate printerdata */ for (j = 0; j < r.count; j++) { char *valuename; const char *keyname; if (r.printer_data[j].type == REG_NONE) { continue; } keyname = r.printer_data[j].name; valuename = strchr(keyname, '\\'); if (valuename == NULL) { continue; } else { valuename[0] = '\0'; valuename++; } result = winreg_set_printer_dataex(mem_ctx, b, key_name, keyname, valuename, r.printer_data[j].type, r.printer_data[j].data.data, r.printer_data[j].data.length); if (!W_ERROR_IS_OK(result)) { DEBUG(2, ("SetPrinterDataEx: printer [%s], keyname [%s], " "valuename [%s] refused -- %s.\n", key_name, keyname, valuename, win_errstr(result))); status = werror_to_ntstatus(result); break; } } status = NT_STATUS_OK; done: return status; } NTSTATUS printing_tdb_migrate_secdesc(TALLOC_CTX *mem_ctx, struct rpc_pipe_client *winreg_pipe, const char *key_name, unsigned char *data, size_t length) { struct dcerpc_binding_handle *b = winreg_pipe->binding_handle; enum ndr_err_code ndr_err; struct sec_desc_buf secdesc_ctr; DATA_BLOB blob; WERROR result; if (strequal(key_name, "printers")) { return NT_STATUS_OK; } blob = data_blob_const(data, length); ZERO_STRUCT(secdesc_ctr); ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &secdesc_ctr, (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(2, ("security descriptor pull failed: %s\n", ndr_errstr(ndr_err))); return NT_STATUS_NO_MEMORY; } DEBUG(2, ("Migrating Security Descriptor: %s\n", key_name)); result = winreg_set_printer_secdesc(mem_ctx, b, key_name, secdesc_ctr.sd); if (!W_ERROR_IS_OK(result)) { return werror_to_ntstatus(result); } return NT_STATUS_OK; }