s3-spoolss: Fix bug #8351 forms migration.
[kai/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 "rpc_client/rpc_client.h"
25 #include "librpc/gen_ndr/ndr_ntprinting.h"
26 #include "librpc/gen_ndr/ndr_spoolss_c.h"
27 #include "librpc/gen_ndr/ndr_security.h"
28 #include "rpc_client/cli_winreg_spoolss.h"
29
30 NTSTATUS printing_tdb_migrate_form(TALLOC_CTX *mem_ctx,
31                                    struct rpc_pipe_client *winreg_pipe,
32                                    const char *key_name,
33                                    unsigned char *data,
34                                    size_t length)
35 {
36         struct dcerpc_binding_handle *b = winreg_pipe->binding_handle;
37         enum ndr_err_code ndr_err;
38         struct ntprinting_form r;
39         struct spoolss_AddFormInfo1 f1;
40         DATA_BLOB blob;
41         WERROR result;
42
43         blob = data_blob_const(data, length);
44
45         ZERO_STRUCT(r);
46
47         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
48                    (ndr_pull_flags_fn_t)ndr_pull_ntprinting_form);
49         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
50                 DEBUG(2, ("Form pull failed: %s\n",
51                           ndr_errstr(ndr_err)));
52                 return NT_STATUS_NO_MEMORY;
53         }
54
55         /* Don't migrate builtin forms */
56         if (r.flag == SPOOLSS_FORM_BUILTIN) {
57                 return NT_STATUS_OK;
58         }
59
60         DEBUG(2, ("Migrating Form: %s\n", key_name));
61
62         f1.form_name = key_name;
63         f1.flags = r.flag;
64
65         f1.size.width = r.width;
66         f1.size.height = r.length;
67
68         f1.area.top = r.top;
69         f1.area.right = r.right;
70         f1.area.bottom = r.bottom;
71         f1.area.left = r.left;
72
73         result = winreg_printer_addform1(mem_ctx,
74                                          b,
75                                          &f1);
76         if (W_ERROR_EQUAL(result, WERR_FILE_EXISTS)) {
77                 /* Don't migrate form if it already exists. */
78                 result = WERR_OK;
79         }
80         if (!W_ERROR_IS_OK(result)) {
81                 return werror_to_ntstatus(result);
82         }
83
84         return NT_STATUS_OK;
85 }
86
87 NTSTATUS printing_tdb_migrate_driver(TALLOC_CTX *mem_ctx,
88                                      struct rpc_pipe_client *winreg_pipe,
89                                      const char *key_name,
90                                      unsigned char *data,
91                                      size_t length)
92 {
93         struct dcerpc_binding_handle *b = winreg_pipe->binding_handle;
94         enum ndr_err_code ndr_err;
95         struct ntprinting_driver r;
96         struct spoolss_AddDriverInfoCtr d;
97         struct spoolss_AddDriverInfo3 d3;
98         struct spoolss_StringArray a;
99         DATA_BLOB blob;
100         WERROR result;
101         const char *driver_name;
102         uint32_t driver_version;
103
104         blob = data_blob_const(data, length);
105
106         ZERO_STRUCT(r);
107
108         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
109                    (ndr_pull_flags_fn_t)ndr_pull_ntprinting_driver);
110         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
111                 DEBUG(2, ("Driver pull failed: %s\n",
112                           ndr_errstr(ndr_err)));
113                 return NT_STATUS_NO_MEMORY;
114         }
115
116         DEBUG(2, ("Migrating Printer Driver: %s\n", key_name));
117
118         ZERO_STRUCT(d3);
119         ZERO_STRUCT(a);
120
121         a.string = r.dependent_files;
122
123         d3.architecture = r.environment;
124         d3.config_file = r.configfile;
125         d3.data_file = r.datafile;
126         d3.default_datatype = r.defaultdatatype;
127         d3.dependent_files = &a;
128         d3.driver_path = r.driverpath;
129         d3.help_file = r.helpfile;
130         d3.monitor_name = r.monitorname;
131         d3.driver_name = r.name;
132         d3.version = r.version;
133
134         d.level = 3;
135         d.info.info3 = &d3;
136
137         result = winreg_add_driver(mem_ctx,
138                                    b,
139                                    &d,
140                                    &driver_name,
141                                    &driver_version);
142         if (!W_ERROR_IS_OK(result)) {
143                 return werror_to_ntstatus(result);
144         }
145
146         return NT_STATUS_OK;
147 }
148
149 NTSTATUS printing_tdb_migrate_printer(TALLOC_CTX *mem_ctx,
150                                       struct rpc_pipe_client *winreg_pipe,
151                                       const char *key_name,
152                                       unsigned char *data,
153                                       size_t length)
154 {
155         struct dcerpc_binding_handle *b = winreg_pipe->binding_handle;
156         enum ndr_err_code ndr_err;
157         struct ntprinting_printer r;
158         struct spoolss_SetPrinterInfo2 info2;
159         struct spoolss_DeviceMode dm;
160         struct spoolss_DevmodeContainer devmode_ctr;
161         DATA_BLOB blob;
162         NTSTATUS status;
163         WERROR result;
164         int j;
165         uint32_t info2_mask = (SPOOLSS_PRINTER_INFO_ALL)
166                                 & ~SPOOLSS_PRINTER_INFO_SECDESC;
167
168         if (strequal(key_name, "printers")) {
169                 return NT_STATUS_OK;
170         }
171
172         blob = data_blob_const(data, length);
173
174         ZERO_STRUCT(r);
175
176         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
177                    (ndr_pull_flags_fn_t) ndr_pull_ntprinting_printer);
178         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
179                 DEBUG(2, ("printer pull failed: %s\n",
180                           ndr_errstr(ndr_err)));
181                 return NT_STATUS_NO_MEMORY;
182         }
183
184         DEBUG(2, ("Migrating Printer: %s\n", key_name));
185
186         ZERO_STRUCT(devmode_ctr);
187
188         /* Create printer info level 2 */
189         ZERO_STRUCT(info2);
190
191         info2.attributes = r.info.attributes;
192         info2.averageppm = r.info.averageppm;
193         info2.cjobs = r.info.cjobs;
194         info2.comment = r.info.comment;
195         info2.datatype = r.info.datatype;
196         info2.defaultpriority = r.info.default_priority;
197         info2.drivername = r.info.drivername;
198         info2.location = r.info.location;
199         info2.parameters = r.info.parameters;
200         info2.portname = r.info.portname;
201         info2.printername = r.info.printername;
202         info2.printprocessor = r.info.printprocessor;
203         info2.priority = r.info.priority;
204         info2.sepfile = r.info.sepfile;
205         info2.sharename = r.info.sharename;
206         info2.starttime = r.info.starttime;
207         info2.status = r.info.status;
208         info2.untiltime = r.info.untiltime;
209
210         /* Create Device Mode */
211         if (r.devmode == NULL) {
212                 info2_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
213         } else {
214                 ZERO_STRUCT(dm);
215
216                 dm.bitsperpel              = r.devmode->bitsperpel;
217                 dm.collate                 = r.devmode->collate;
218                 dm.color                   = r.devmode->color;
219                 dm.copies                  = r.devmode->copies;
220                 dm.defaultsource           = r.devmode->defaultsource;
221                 dm.devicename              = r.devmode->devicename;
222                 dm.displayflags            = r.devmode->displayflags;
223                 dm.displayfrequency        = r.devmode->displayfrequency;
224                 dm.dithertype              = r.devmode->dithertype;
225                 dm.driverversion           = r.devmode->driverversion;
226                 dm.duplex                  = r.devmode->duplex;
227                 dm.fields                  = r.devmode->fields;
228                 dm.formname                = r.devmode->formname;
229                 dm.icmintent               = r.devmode->icmintent;
230                 dm.icmmethod               = r.devmode->icmmethod;
231                 dm.logpixels               = r.devmode->logpixels;
232                 dm.mediatype               = r.devmode->mediatype;
233                 dm.orientation             = r.devmode->orientation;
234                 dm.panningheight           = r.devmode->pelsheight;
235                 dm.panningwidth            = r.devmode->panningwidth;
236                 dm.paperlength             = r.devmode->paperlength;
237                 dm.papersize               = r.devmode->papersize;
238                 dm.paperwidth              = r.devmode->paperwidth;
239                 dm.pelsheight              = r.devmode->pelsheight;
240                 dm.pelswidth               = r.devmode->pelswidth;
241                 dm.printquality            = r.devmode->printquality;
242                 dm.size                    = r.devmode->size;
243                 dm.scale                   = r.devmode->scale;
244                 dm.specversion             = r.devmode->specversion;
245                 dm.ttoption                = r.devmode->ttoption;
246                 dm.yresolution             = r.devmode->yresolution;
247
248                 if (r.devmode->nt_dev_private != NULL) {
249                         dm.driverextra_data.data   = r.devmode->nt_dev_private->data;
250                         dm.driverextra_data.length = r.devmode->nt_dev_private->length;
251                         dm.__driverextra_length    = r.devmode->nt_dev_private->length;
252                 }
253
254                 devmode_ctr.devmode = &dm;
255
256                 info2.devmode_ptr = 1;
257         }
258
259         result = winreg_update_printer(mem_ctx, b,
260                                        key_name,
261                                        info2_mask,
262                                        &info2,
263                                        &dm,
264                                        NULL);
265         if (!W_ERROR_IS_OK(result)) {
266                 DEBUG(2, ("SetPrinter(%s) level 2 refused -- %s.\n",
267                           key_name, win_errstr(result)));
268                 status = werror_to_ntstatus(result);
269                 goto done;
270         }
271
272         /* migrate printerdata */
273         for (j = 0; j < r.count; j++) {
274                 char *valuename;
275                 const char *keyname;
276
277                 if (r.printer_data[j].type == REG_NONE) {
278                         continue;
279                 }
280
281                 keyname = r.printer_data[j].name;
282                 valuename = strchr(keyname, '\\');
283                 if (valuename == NULL) {
284                         continue;
285                 } else {
286                         valuename[0] = '\0';
287                         valuename++;
288                 }
289
290                 result = winreg_set_printer_dataex(mem_ctx, b,
291                                                    key_name,
292                                                    keyname,
293                                                    valuename,
294                                                    r.printer_data[j].type,
295                                                    r.printer_data[j].data.data,
296                                                    r.printer_data[j].data.length);
297                 if (!W_ERROR_IS_OK(result)) {
298                         DEBUG(2, ("SetPrinterDataEx: printer [%s], keyname [%s], "
299                                   "valuename [%s] refused -- %s.\n",
300                                   key_name, keyname, valuename,
301                                   win_errstr(result)));
302                         status = werror_to_ntstatus(result);
303                         break;
304                 }
305         }
306
307         status = NT_STATUS_OK;
308  done:
309
310         return status;
311 }
312
313 NTSTATUS printing_tdb_migrate_secdesc(TALLOC_CTX *mem_ctx,
314                                       struct rpc_pipe_client *winreg_pipe,
315                                       const char *key_name,
316                                       unsigned char *data,
317                                       size_t length)
318 {
319         struct dcerpc_binding_handle *b = winreg_pipe->binding_handle;
320         enum ndr_err_code ndr_err;
321         struct sec_desc_buf secdesc_ctr;
322         DATA_BLOB blob;
323         WERROR result;
324
325         if (strequal(key_name, "printers")) {
326                 return NT_STATUS_OK;
327         }
328
329         blob = data_blob_const(data, length);
330
331         ZERO_STRUCT(secdesc_ctr);
332
333         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &secdesc_ctr,
334                    (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
335         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
336                 DEBUG(2, ("security descriptor pull failed: %s\n",
337                           ndr_errstr(ndr_err)));
338                 return NT_STATUS_NO_MEMORY;
339         }
340
341         DEBUG(2, ("Migrating Security Descriptor: %s\n", key_name));
342
343         result = winreg_set_printer_secdesc(mem_ctx, b,
344                                             key_name,
345                                             secdesc_ctr.sd);
346         if (!W_ERROR_IS_OK(result)) {
347                 return werror_to_ntstatus(result);
348         }
349
350         return NT_STATUS_OK;
351 }