3edc622901d6d23419a845a88edb439c30206693
[samba.git] / source3 / python / py_spoolss.c
1 /* 
2    Python wrappers for DCERPC/SMB client routines.
3
4    Copyright (C) Tim Potter, 2002
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22 #include "Python.h"
23 #include "python/py_common.h"
24 #include "python/py_spoolss.h"
25 #include "python/py_spoolss_forms.h"
26
27 /* Exceptions this module can raise */
28
29 PyObject *spoolss_error, *spoolss_werror;
30
31 static void py_policy_hnd_dealloc(PyObject* self)
32 {
33         PyObject_Del(self);
34 }
35
36
37
38 static PyMethodDef spoolss_hnd_methods[] = {
39
40         /* Forms */
41
42         { "enumforms", spoolss_enumforms, METH_VARARGS | METH_KEYWORDS,
43           "Enumerate forms" },
44
45         { "setform", spoolss_setform, METH_VARARGS | METH_KEYWORDS,
46           "Modify properties of a form" },
47
48         { "addform", spoolss_addform, METH_VARARGS | METH_KEYWORDS,
49           "Insert a form" },
50
51         { "getform", spoolss_getform, METH_VARARGS | METH_KEYWORDS,
52           "Fetch form properties" },
53
54         { "deleteform", spoolss_deleteform, METH_VARARGS | METH_KEYWORDS,
55           "Delete a form" },
56
57         { NULL }
58
59 };
60 static PyObject *py_policy_hnd_getattr(PyObject *self, char *attrname)
61 {
62         return Py_FindMethod(spoolss_hnd_methods, self, attrname);
63 }
64
65 static PyObject *new_policy_hnd_object(struct cli_state *cli, 
66                                        TALLOC_CTX *mem_ctx, POLICY_HND *pol)
67 {
68         spoolss_policy_hnd_object *o;
69
70         o = PyObject_New(spoolss_policy_hnd_object, &spoolss_policy_hnd_type);
71
72         o->cli = cli;
73         o->mem_ctx = mem_ctx;
74         memcpy(&o->pol, pol, sizeof(POLICY_HND));
75
76         return (PyObject*)o;
77 }
78      
79 PyTypeObject spoolss_policy_hnd_type = {
80         PyObject_HEAD_INIT(NULL)
81         0,
82         "Policy Handle",
83         sizeof(spoolss_policy_hnd_object),
84         0,
85         py_policy_hnd_dealloc, /*tp_dealloc*/
86         0,          /*tp_print*/
87         py_policy_hnd_getattr,          /*tp_getattr*/
88         0,          /*tp_setattr*/
89         0,          /*tp_compare*/
90         0,          /*tp_repr*/
91         0,          /*tp_as_number*/
92         0,          /*tp_as_sequence*/
93         0,          /*tp_as_mapping*/
94         0,          /*tp_hash */
95 };
96
97 /*
98  * Routines to convert from python hashes to Samba structures
99  */
100
101 struct pyconv py_PRINTER_INFO_0[] = {
102         { "printer_name", PY_UNISTR, offsetof(PRINTER_INFO_0, printername) },
103         { "server_name", PY_UNISTR, offsetof(PRINTER_INFO_0, servername) },
104
105         { "cjobs", PY_UINT32, offsetof(PRINTER_INFO_0, cjobs) },
106         { "total_jobs", PY_UINT32, offsetof(PRINTER_INFO_0, total_jobs) },
107         { "total_bytes", PY_UINT32, offsetof(PRINTER_INFO_0, total_bytes) },
108
109         { "year", PY_UINT16, offsetof(PRINTER_INFO_0, year) },
110         { "month", PY_UINT16, offsetof(PRINTER_INFO_0, month) },
111         { "day_of_week", PY_UINT16, offsetof(PRINTER_INFO_0, dayofweek) },
112         { "day", PY_UINT16, offsetof(PRINTER_INFO_0, day) },
113         { "hour", PY_UINT16, offsetof(PRINTER_INFO_0, hour) },
114         { "minute", PY_UINT16, offsetof(PRINTER_INFO_0, minute) },
115         { "second", PY_UINT16, offsetof(PRINTER_INFO_0, second) },
116         { "milliseconds", PY_UINT16, offsetof(PRINTER_INFO_0, milliseconds) },
117
118         { "global_counter", PY_UINT32, offsetof(PRINTER_INFO_0, global_counter) },
119         { "total_pages", PY_UINT32, offsetof(PRINTER_INFO_0, total_pages) },
120
121         { "major_version", PY_UINT16, offsetof(PRINTER_INFO_0, major_version) },
122         { "build_version", PY_UINT16, offsetof(PRINTER_INFO_0, build_version) },
123
124         { "unknown7", PY_UINT32, offsetof(PRINTER_INFO_0, unknown7) },
125         { "unknown8", PY_UINT32, offsetof(PRINTER_INFO_0, unknown8) },
126         { "unknown9", PY_UINT32, offsetof(PRINTER_INFO_0, unknown9) },
127         { "session_counter", PY_UINT32, offsetof(PRINTER_INFO_0, session_counter)},
128         { "unknown11", PY_UINT32, offsetof(PRINTER_INFO_0, unknown11) },
129         { "printer_errors", PY_UINT32, offsetof(PRINTER_INFO_0, printer_errors) },
130         { "unknown13", PY_UINT32, offsetof(PRINTER_INFO_0, unknown13) },
131         { "unknown14", PY_UINT32, offsetof(PRINTER_INFO_0, unknown14) },
132         { "unknown15", PY_UINT32, offsetof(PRINTER_INFO_0, unknown15) },
133         { "unknown16", PY_UINT32, offsetof(PRINTER_INFO_0, unknown16) },
134         { "change_id", PY_UINT32, offsetof(PRINTER_INFO_0, change_id) },
135         { "unknown18", PY_UINT32, offsetof(PRINTER_INFO_0, unknown18) },
136         { "status", PY_UINT32, offsetof(PRINTER_INFO_0, status) },
137         { "unknown20", PY_UINT32, offsetof(PRINTER_INFO_0, unknown20) },
138         { "c_setprinter", PY_UINT32, offsetof(PRINTER_INFO_0, c_setprinter) },
139         { "unknown22", PY_UINT32, offsetof(PRINTER_INFO_0, unknown22) },
140         { "unknown23", PY_UINT32, offsetof(PRINTER_INFO_0, unknown23) },
141         { "unknown24", PY_UINT32, offsetof(PRINTER_INFO_0, unknown24) },
142         { "unknown25", PY_UINT32, offsetof(PRINTER_INFO_0, unknown25) },
143         { "unknown26", PY_UINT32, offsetof(PRINTER_INFO_0, unknown26) },
144         { "unknown27", PY_UINT32, offsetof(PRINTER_INFO_0, unknown27) },
145         { "unknown28", PY_UINT32, offsetof(PRINTER_INFO_0, unknown28) },
146         { "unknown29", PY_UINT32, offsetof(PRINTER_INFO_0, unknown29) },
147
148         { NULL }
149 };      
150
151 struct pyconv py_PRINTER_INFO_1[] = {
152         { "printer_name", PY_UNISTR, offsetof(PRINTER_INFO_1, name) },
153         { "description", PY_UNISTR, offsetof(PRINTER_INFO_1, description) },
154         { "comment", PY_UNISTR, offsetof(PRINTER_INFO_1, comment) },
155         { "flags", PY_UINT32, offsetof(PRINTER_INFO_1, flags) },
156         { NULL }
157 };      
158
159 struct pyconv py_PRINTER_INFO_2[] = {
160         { "server_name", PY_UNISTR, offsetof(PRINTER_INFO_2, servername) },
161         { "printer_name", PY_UNISTR, offsetof(PRINTER_INFO_2, printername) },
162         { "share_name", PY_UNISTR, offsetof(PRINTER_INFO_2, sharename) },
163         { "port_name", PY_UNISTR, offsetof(PRINTER_INFO_2, portname) },
164         { "driver_name", PY_UNISTR, offsetof(PRINTER_INFO_2, drivername) },
165         { "comment", PY_UNISTR, offsetof(PRINTER_INFO_2, comment) },
166         { "location", PY_UNISTR, offsetof(PRINTER_INFO_2, location) },
167         { "datatype", PY_UNISTR, offsetof(PRINTER_INFO_2, datatype) },
168         { "sepfile", PY_UNISTR, offsetof(PRINTER_INFO_2, sepfile) },
169         { "print_processor", PY_UNISTR, offsetof(PRINTER_INFO_2, printprocessor) },
170         { "parameters", PY_UNISTR, offsetof(PRINTER_INFO_2, parameters) },
171         { "attributes", PY_UINT32, offsetof(PRINTER_INFO_2, attributes) },
172         { "default_priority", PY_UINT32, offsetof(PRINTER_INFO_2, defaultpriority) },
173         { "priority", PY_UINT32, offsetof(PRINTER_INFO_2, priority) },
174         { "start_time", PY_UINT32, offsetof(PRINTER_INFO_2, starttime) },
175         { "until_time", PY_UINT32, offsetof(PRINTER_INFO_2, untiltime) },
176         { "status", PY_UINT32, offsetof(PRINTER_INFO_2, status) },
177         { "cjobs", PY_UINT32, offsetof(PRINTER_INFO_2, cjobs) },
178         { "average_ppm", PY_UINT32, offsetof(PRINTER_INFO_2, averageppm) },
179         { NULL }
180 };      
181
182 struct pyconv py_PRINTER_INFO_3[] = {
183         { "flags", PY_UINT32, offsetof(PRINTER_INFO_3, flags) },
184         { NULL }
185 };      
186
187 struct pyconv py_DEVICEMODE[] = {
188         { "device_name", PY_UNISTR, offsetof(DEVICEMODE, devicename) },
189         { "spec_version", PY_UINT16, offsetof(DEVICEMODE, specversion) },
190         { "driver_version", PY_UINT16, offsetof(DEVICEMODE, driverversion) },
191         { "size", PY_UINT16, offsetof(DEVICEMODE, size) },
192         { "fields", PY_UINT16, offsetof(DEVICEMODE, fields) },
193         { "orientation", PY_UINT16, offsetof(DEVICEMODE, orientation) },
194         { "paper_size", PY_UINT16, offsetof(DEVICEMODE, papersize) },
195         { "paper_width", PY_UINT16, offsetof(DEVICEMODE, paperwidth) },
196         { "paper_length", PY_UINT16, offsetof(DEVICEMODE, paperlength) },
197         { "scale", PY_UINT16, offsetof(DEVICEMODE, scale) },
198         { "copies", PY_UINT16, offsetof(DEVICEMODE, copies) },
199         { "default_source", PY_UINT16, offsetof(DEVICEMODE, defaultsource) },
200         { "print_quality", PY_UINT16, offsetof(DEVICEMODE, printquality) },
201         { "color", PY_UINT16, offsetof(DEVICEMODE, color) },
202         { "duplex", PY_UINT16, offsetof(DEVICEMODE, duplex) },
203         { "y_resolution", PY_UINT16, offsetof(DEVICEMODE, yresolution) },
204         { "tt_option", PY_UINT16, offsetof(DEVICEMODE, ttoption) },
205         { "collate", PY_UINT16, offsetof(DEVICEMODE, collate) },
206         { "form_name", PY_UNISTR, offsetof(DEVICEMODE, formname) },
207         { "log_pixels", PY_UINT16, offsetof(DEVICEMODE, logpixels) },
208         { "bits_per_pel", PY_UINT32, offsetof(DEVICEMODE, bitsperpel) },
209         { "pels_width", PY_UINT32, offsetof(DEVICEMODE, pelswidth) },
210         { "pels_height", PY_UINT32, offsetof(DEVICEMODE, pelsheight) },
211         { "display_flags", PY_UINT32, offsetof(DEVICEMODE, displayflags) },
212         { "display_frequency", PY_UINT32, offsetof(DEVICEMODE, displayfrequency) },
213         { "icm_method", PY_UINT32, offsetof(DEVICEMODE, icmmethod) },
214         { "icm_intent", PY_UINT32, offsetof(DEVICEMODE, icmintent) },
215         { "media_type", PY_UINT32, offsetof(DEVICEMODE, mediatype) },
216         { "dither_type", PY_UINT32, offsetof(DEVICEMODE, dithertype) },
217         { "reserved1", PY_UINT32, offsetof(DEVICEMODE, reserved1) },
218         { "reserved2", PY_UINT32, offsetof(DEVICEMODE, reserved2) },
219         { "panning_width", PY_UINT32, offsetof(DEVICEMODE, panningwidth) },
220         { "panning_height", PY_UINT32, offsetof(DEVICEMODE, panningheight) },
221         { NULL }
222 };
223
224 struct pyconv py_DRIVER_INFO_1[] = {
225         { "name", PY_UNISTR, offsetof(DRIVER_INFO_1, name) },
226         { NULL }
227 };
228
229 struct pyconv py_DRIVER_INFO_2[] = {
230         { "version", PY_UINT32, offsetof(DRIVER_INFO_2, version) },
231         { "name", PY_UNISTR, offsetof(DRIVER_INFO_2, name) },
232         { "architecture", PY_UNISTR, offsetof(DRIVER_INFO_2, architecture) },
233         { "driver_path", PY_UNISTR, offsetof(DRIVER_INFO_2, driverpath) },
234         { "data_file", PY_UNISTR, offsetof(DRIVER_INFO_2, datafile) },
235         { "config_file", PY_UNISTR, offsetof(DRIVER_INFO_2, configfile) },
236         { NULL }
237 };
238
239 struct pyconv py_DRIVER_INFO_3[] = {
240         { "version", PY_UINT32, offsetof(DRIVER_INFO_3, version) },
241         { "name", PY_UNISTR, offsetof(DRIVER_INFO_3, name) },
242         { "architecture", PY_UNISTR, offsetof(DRIVER_INFO_3, architecture) },
243         { "driver_path", PY_UNISTR, offsetof(DRIVER_INFO_3, driverpath) },
244         { "data_file", PY_UNISTR, offsetof(DRIVER_INFO_3, datafile) },
245         { "config_file", PY_UNISTR, offsetof(DRIVER_INFO_3, configfile) },
246         { "help_file", PY_UNISTR, offsetof(DRIVER_INFO_3, helpfile) },
247         /* dependentfiles */
248         { "monitor_name", PY_UNISTR, offsetof(DRIVER_INFO_3, monitorname) },
249         { "default_datatype", PY_UNISTR, offsetof(DRIVER_INFO_3, defaultdatatype) },
250         { NULL }
251 };
252
253 struct pyconv py_DRIVER_INFO_6[] = {
254         { "version", PY_UINT32, offsetof(DRIVER_INFO_6, version) },
255         { "name", PY_UNISTR, offsetof(DRIVER_INFO_6, name) },
256         { "architecture", PY_UNISTR, offsetof(DRIVER_INFO_6, architecture) },
257         { "driver_path", PY_UNISTR, offsetof(DRIVER_INFO_6, driverpath) },
258         { "data_file", PY_UNISTR, offsetof(DRIVER_INFO_6, datafile) },
259         { "config_file", PY_UNISTR, offsetof(DRIVER_INFO_6, configfile) },
260         { "help_file", PY_UNISTR, offsetof(DRIVER_INFO_6, helpfile) },
261         /* dependentfiles */
262         { "monitor_name", PY_UNISTR, offsetof(DRIVER_INFO_6, monitorname) },
263         { "default_datatype", PY_UNISTR, offsetof(DRIVER_INFO_6, defaultdatatype) },
264         /* driver_date */
265
266         { "padding", PY_UINT32, offsetof(DRIVER_INFO_6, padding) },
267         { "driver_version_low", PY_UINT32, offsetof(DRIVER_INFO_6, driver_version_low) },
268         { "driver_version_high", PY_UINT32, offsetof(DRIVER_INFO_6, driver_version_high) },
269         { "mfg_name", PY_UNISTR, offsetof(DRIVER_INFO_6, mfgname) },
270         { "oem_url", PY_UNISTR, offsetof(DRIVER_INFO_6, oem_url) },
271         { "hardware_id", PY_UNISTR, offsetof(DRIVER_INFO_6, hardware_id) },
272         { "provider", PY_UNISTR, offsetof(DRIVER_INFO_6, provider) },
273         
274         { NULL }
275 };
276
277 static void fstr_pull(fstring str, UNISTR *uni)
278 {
279         rpcstr_pull(str, uni->buffer, sizeof(fstring), 0, STR_TERMINATE);
280 }
281
282 /* Convert a structure to a Python dict */
283
284 PyObject *from_struct(void *s, struct pyconv *conv)
285 {
286         PyObject *obj, *item;
287         int i;
288
289         obj = PyDict_New();
290
291         for (i = 0; conv[i].name; i++) {
292                 switch (conv[i].type) {
293                 case PY_UNISTR: {
294                         UNISTR *u = (UNISTR *)((char *)s + conv[i].offset);
295                         fstring s = "";
296
297                         if (u->buffer)
298                                 fstr_pull(s, u);
299
300                         item = PyString_FromString(s);
301                         PyDict_SetItemString(obj, conv[i].name, item);
302
303                         break;
304                 }
305                 case PY_UINT32: {
306                         uint32 *u = (uint32 *)((char *)s + conv[i].offset);
307
308                         item = PyInt_FromLong(*u);
309                         PyDict_SetItemString(obj, conv[i].name, item);
310                         
311                         break;
312                 }
313                 case PY_UINT16: {
314                         uint16 *u = (uint16 *)((char *)s + conv[i].offset);
315
316                         item = PyInt_FromLong(*u);
317                         PyDict_SetItemString(obj, conv[i].name, item);
318
319                         break;
320                 }
321                 default:
322                         break;
323                 }
324         }
325
326         return obj;
327 }
328
329 /* Convert a Python dict to a structure */
330
331 void to_struct(void *s, PyObject *dict, struct pyconv *conv)
332 {
333         int i;
334
335         for (i = 0; conv[i].name; i++) {
336                 PyObject *obj;
337                 
338                 obj = PyDict_GetItemString(dict, conv[i].name);
339                 
340                 switch (conv[i].type) {
341                 case PY_UNISTR: {
342                         UNISTR *u = (UNISTR *)((char *)s + conv[i].offset);
343                         char *s = "";
344
345                         if (obj && PyString_Check(obj))
346                                 s = PyString_AsString(obj);
347
348                         init_unistr(u, s);
349                         
350                         break;
351                 }
352                 case PY_UINT32: {
353                         uint32 *u = (uint32 *)((char *)s + conv[i].offset);
354
355                         if (obj && PyInt_Check(obj)) 
356                                 *u = PyInt_AsLong(obj);
357                         else
358                                 *u = 0;
359
360                         break;
361                 }
362                 case PY_UINT16: {
363                         uint16 *u = (uint16 *)((char *)s + conv[i].offset);
364
365                         if (obj && PyInt_Check(obj)) 
366                                 *u = PyInt_AsLong(obj);
367                         else
368                                 *u = 0;
369
370                         break;
371                 }
372                 default:
373                         break;
374                 }
375         }
376 }
377
378 /* Return a cli_state struct opened on the SPOOLSS pipe.  If credentials
379    are passed use them. */
380
381 typedef struct cli_state *(cli_pipe_fn)(
382         struct cli_state *cli, char *system_name,
383         struct ntuser_creds *creds);
384
385 static struct cli_state *open_pipe_creds(char *system_name, PyObject *creds, 
386                                          cli_pipe_fn *connect_fn,
387                                          struct cli_state *cli)
388 {
389         struct ntuser_creds nt_creds;
390
391         if (!cli) {
392                 cli = (struct cli_state *)malloc(sizeof(struct cli_state));
393                 if (!cli)
394                         return NULL;
395         }
396
397         ZERO_STRUCTP(cli);
398
399         /* Extract credentials from the python dictionary and initialise
400            the ntuser_creds struct from them. */
401
402         ZERO_STRUCT(nt_creds);
403         nt_creds.pwd.null_pwd = True;
404
405         if (creds) {
406                 char *username, *password, *domain;
407                 PyObject *username_obj, *password_obj, *domain_obj;
408
409                 /* Check credentials passed are valid.  This means the
410                    username, domain and password keys must exist and be
411                    string objects. */
412
413                 username_obj = PyDict_GetItemString(creds, "username");
414                 domain_obj = PyDict_GetItemString(creds, "domain");
415                 password_obj = PyDict_GetItemString(creds, "password");
416
417                 if (!username_obj || !domain_obj || !password_obj) {
418                 error:
419                         PyErr_SetString(spoolss_error, "invalid credentials");
420                         return NULL;
421                 }
422
423                 if (!PyString_Check(username_obj) || 
424                     !PyString_Check(domain_obj) || 
425                     !PyString_Check(password_obj))
426                         goto error;
427
428                 username = PyString_AsString(username_obj);
429                 domain = PyString_AsString(domain_obj);
430                 password = PyString_AsString(password_obj);
431
432                 if (!username || !domain || !password)
433                         goto error;
434
435                 /* Initialise nt_creds structure with passed creds */
436
437                 fstrcpy(nt_creds.user_name, username);
438                 fstrcpy(nt_creds.domain, domain);
439
440                 if (lp_encrypted_passwords())
441                         pwd_make_lm_nt_16(&nt_creds.pwd, password);
442                 else
443                         pwd_set_cleartext(&nt_creds.pwd, password);
444
445                 nt_creds.pwd.null_pwd = False;
446         }
447
448         /* Now try to connect */
449
450         connect_fn(cli, system_name, &nt_creds);
451
452         return cli;
453 }
454
455 /* Open a printer */
456
457 static PyObject *spoolss_openprinter(PyObject *self, PyObject *args,
458                                      PyObject *kw)
459 {
460         char *full_name, *computer_name = NULL;
461         TALLOC_CTX *mem_ctx;
462         POLICY_HND hnd;
463         WERROR werror;
464         PyObject *result = NULL, *creds = NULL;
465         static char *kwlist[] = { "printername", "creds", "access", NULL };
466         uint32 desired_access = MAXIMUM_ALLOWED_ACCESS;
467         struct cli_state *cli;
468
469         if (!PyArg_ParseTupleAndKeywords(
470                 args, kw, "s|O!i", kwlist, &full_name, &PyDict_Type, &creds,
471                 &desired_access)) {
472
473                 goto done;
474         }
475
476         /* FIXME: Return name format exception for names without a UNC
477            prefix */ 
478
479         computer_name = strdup(full_name + 2);
480
481         if (strchr(computer_name, '\\')) {
482                 char *c = strchr(computer_name, '\\');
483                 *c = 0;
484         }
485
486         if (!(cli = open_pipe_creds(computer_name, creds, 
487                                     cli_spoolss_initialise, NULL))) {
488                 fprintf(stderr, "could not initialise cli state\n");
489                 goto done;
490         }
491
492         if (!(mem_ctx = talloc_init())) {
493                 fprintf(stderr, "unable to initialise talloc context\n");
494                 goto done;
495         }
496
497         werror = cli_spoolss_open_printer_ex(
498                 cli, mem_ctx, full_name, "", desired_access, computer_name, 
499                 "", &hnd);
500
501         if (!W_ERROR_IS_OK(werror)) {
502                 cli_shutdown(cli);
503                 SAFE_FREE(cli);
504                 PyErr_SetObject(spoolss_werror,
505                                 PyInt_FromLong(W_ERROR_V(werror)));
506                 goto done;
507         }
508
509         result = new_policy_hnd_object(cli, mem_ctx, &hnd);
510
511  done:
512         SAFE_FREE(computer_name);
513
514         return result;
515 }
516
517 /* Close a printer */
518
519 static PyObject *spoolss_closeprinter(PyObject *self, PyObject *args)
520 {
521         PyObject *po;
522         spoolss_policy_hnd_object *hnd;
523         WERROR result;
524
525         /* Parse parameters */
526
527         if (!PyArg_ParseTuple(args, "O!", &spoolss_policy_hnd_type, &po))
528                 return NULL;
529
530         hnd = (spoolss_policy_hnd_object *)po;
531
532         /* Call rpc function */
533
534         result = cli_spoolss_close_printer(hnd->cli, hnd->mem_ctx, &hnd->pol);
535
536         /* Cleanup samba stuf */
537
538         cli_shutdown(hnd->cli);
539         talloc_destroy(hnd->mem_ctx);
540
541         /* Return value */
542
543         Py_INCREF(Py_None);
544         return Py_None; 
545 }
546
547 /* Fetch printer driver */
548
549 static PyObject *spoolss_getprinterdriver(PyObject *self, PyObject *args,
550                                           PyObject *kw)
551 {
552         PyObject *po;
553         spoolss_policy_hnd_object *hnd;
554         WERROR werror;
555         PyObject *result;
556         PRINTER_DRIVER_CTR ctr;
557         int level = 1;
558         uint32 needed;
559         char *arch = "Windows NT x86";
560         static char *kwlist[] = {"hnd", "level", "arch", NULL};
561
562         /* Parse parameters */
563
564         if (!PyArg_ParseTupleAndKeywords(args, kw, "O!|is", kwlist, 
565                                          &spoolss_policy_hnd_type, &po, &level, &arch))
566                 return NULL;
567
568         hnd = (spoolss_policy_hnd_object *)po;
569
570         /* Call rpc function */
571
572         werror = cli_spoolss_getprinterdriver(
573                 hnd->cli, hnd->mem_ctx, 0, &needed, &hnd->pol, level,
574                 arch, &ctr);
575
576         if (W_ERROR_V(werror) == ERRinsufficientbuffer)
577                 werror = cli_spoolss_getprinterdriver(
578                         hnd->cli, hnd->mem_ctx, needed, NULL, &hnd->pol,
579                         level, arch, &ctr);
580
581         /* Return value */
582         
583         result = Py_None;
584
585         if (W_ERROR_IS_OK(werror)) {
586                 switch (level) {
587                 case 1:
588                         result = from_struct(&ctr.info1, py_DRIVER_INFO_1);
589                         break;
590                 case 2: 
591                         result = from_struct(&ctr.info2, py_DRIVER_INFO_2);
592                         break;
593                 case 6:
594                         result = from_struct(&ctr.info6, py_DRIVER_INFO_6);
595                         break;
596                 default:
597                         result = Py_None;
598                         break;
599                 }
600         }
601         
602         Py_INCREF(result);
603         return result;
604 }
605
606 /* Enumerate printer drivers */
607
608 static PyObject *spoolss_enumprinterdrivers(PyObject *self, PyObject *args,
609                                             PyObject *kw)
610 {
611         PyObject *po;
612         spoolss_policy_hnd_object *hnd;
613         WERROR werror;
614         PyObject *result;
615         PRINTER_DRIVER_CTR ctr;
616         int level = 1, i;
617         uint32 needed, num_drivers;
618         char *arch = "Windows NT x86";
619         static char *kwlist[] = {"hnd", "level", "arch", NULL};
620
621         /* Parse parameters */
622
623         if (!PyArg_ParseTupleAndKeywords(args, kw, "O!|is", kwlist, 
624                                          &spoolss_policy_hnd_type, &po, &level, &arch))
625                 return NULL;
626         
627         hnd = (spoolss_policy_hnd_object *)po;
628         
629         /* Call rpc function */
630         
631         werror = cli_spoolss_enumprinterdrivers(
632                 hnd->cli, hnd->mem_ctx, 0, &needed, level, arch,
633                 &num_drivers, &ctr);
634
635         if (W_ERROR_V(werror) == ERRinsufficientbuffer)
636                 werror = cli_spoolss_enumprinterdrivers(
637                         hnd->cli, hnd->mem_ctx, needed, NULL, level, arch, 
638                         &num_drivers, &ctr);
639
640         /* Return value */
641         
642         result = Py_None;
643
644         if (!W_ERROR_IS_OK(werror))
645                 goto done;
646
647         switch (level) {
648         case 1:
649                 result = PyList_New(num_drivers);
650                 
651                 for (i = 0; i < num_drivers; i++) {
652                         PyObject *value;
653                         
654                         value = from_struct(&ctr.info1, py_DRIVER_INFO_1);
655                         PyList_SetItem(result, i, value);
656                 }
657                 
658                 break;
659         case 2: 
660                 result = PyList_New(num_drivers);
661
662                 for(i = 0; i < num_drivers; i++) {
663                         PyObject *value;
664
665                         value = from_struct(&ctr.info2, py_DRIVER_INFO_2);
666                         PyList_SetItem(result, i, value);
667                 }
668
669                 break;
670         case 6: 
671                 result = PyList_New(num_drivers);
672
673                 for(i = 0; i < num_drivers; i++) {
674                         PyObject *value;
675
676                         value = from_struct(&ctr.info2, py_DRIVER_INFO_6);
677                         PyList_SetItem(result, i, value);
678                 }
679
680                 break;
681         default:
682                 result = Py_None;
683                 break;
684         }
685         
686  done:
687         Py_INCREF(result);
688         return result;
689 }
690
691 /* Convert a security descriptor to a Python dict */
692
693 static PyObject *PySID_FromSID(DOM_SID *sid)
694 {
695         fstring sidstr;
696
697         if (!sid) {
698                 Py_INCREF(Py_None);
699                 return Py_None;
700         }
701
702         if (sid_to_string(sidstr, sid))
703                 return PyString_FromString(sidstr);
704
705         Py_INCREF(Py_None);
706         return Py_None; 
707 }
708
709 static PyObject *PyACE_FromACE(SEC_ACE *ace)
710 {
711         PyObject *obj;
712
713         if (!ace) {
714                 Py_INCREF(Py_None);
715                 return Py_None;
716         }
717
718         obj = PyDict_New();
719
720         PyDict_SetItemString(obj, "type", PyInt_FromLong(ace->type));
721         PyDict_SetItemString(obj, "flags", PyInt_FromLong(ace->flags));
722         PyDict_SetItemString(obj, "mask", PyInt_FromLong(ace->info.mask));
723
724         PyDict_SetItemString(obj, "trustee", PySID_FromSID(&ace->trustee));
725
726         return obj;
727 }
728
729 static PyObject *PyACL_FromACL(SEC_ACL *acl)
730 {
731         PyObject *obj, *ace_list;
732         int i;
733
734         if (!acl) {
735                 Py_INCREF(Py_None);
736                 return Py_None;
737         }
738
739         obj = PyDict_New();
740
741         PyDict_SetItemString(obj, "revision", PyInt_FromLong(acl->revision));
742
743         ace_list = PyList_New(acl->num_aces);
744
745         for (i = 0; i < acl->num_aces; i++)
746                 PyList_SetItem(ace_list, i, PyACE_FromACE(&acl->ace[i]));
747
748         PyDict_SetItemString(obj, "ace_list", ace_list);
749
750         return obj;
751 }
752
753 static PyObject *PySECDESC_FromSECDESC(SEC_DESC *sd)
754 {
755         PyObject *obj = PyDict_New();
756
757         PyDict_SetItemString(obj, "revision", PyInt_FromLong(sd->revision));
758         PyDict_SetItemString(obj, "type", PyInt_FromLong(sd->type));
759
760         PyDict_SetItemString(obj, "owner_sid", PySID_FromSID(sd->owner_sid));
761         PyDict_SetItemString(obj, "group_sid", PySID_FromSID(sd->grp_sid));
762
763         PyDict_SetItemString(obj, "dacl", PyACL_FromACL(sd->dacl));
764         PyDict_SetItemString(obj, "sacl", PyACL_FromACL(sd->sacl));
765
766         return obj;
767 }
768
769 PyObject *PyDEVICEMODE_FromDEVICEMODE(DEVICEMODE *devmode)
770 {
771         PyObject *obj;
772
773         obj = from_struct(devmode, py_DEVICEMODE);
774
775         PyDict_SetItemString(obj, "private",
776                              PyString_FromStringAndSize(devmode->private, 
777                                                         devmode->driverextra));
778
779         return obj;
780 }
781
782 /* Fetch printer information */
783
784 static PyObject *spoolss_getprinter(PyObject *self, PyObject *args,
785                                     PyObject *kw)
786 {
787         PyObject *po;
788         spoolss_policy_hnd_object *hnd;
789         WERROR werror;
790         PyObject *result;
791         PRINTER_INFO_CTR ctr;
792         int level = 1;
793         uint32 needed;
794         static char *kwlist[] = {"hnd", "level", NULL};
795
796         /* Parse parameters */
797
798         if (!PyArg_ParseTupleAndKeywords(args, kw, "O!|i", kwlist, 
799                                          &spoolss_policy_hnd_type, &po, &level))
800                 return NULL;
801         
802         hnd = (spoolss_policy_hnd_object *)po;
803         
804         /* Call rpc function */
805         
806         werror = cli_spoolss_getprinter(
807                 hnd->cli, hnd->mem_ctx, 0, &needed, &hnd->pol, level, &ctr);
808
809         if (W_ERROR_V(werror) == ERRinsufficientbuffer)
810                 werror = cli_spoolss_getprinter(
811                         hnd->cli, hnd->mem_ctx, needed, NULL, &hnd->pol,
812                         level, &ctr);
813
814         /* Return value */
815
816         result = Py_None;
817
818         if (!W_ERROR_IS_OK(werror))
819                 goto done;
820
821         switch (level) {
822
823         case 0:
824                 result = from_struct(ctr.printers_0, py_PRINTER_INFO_0);
825
826                 break;
827
828         case 1:
829                 result = from_struct(ctr.printers_1, py_PRINTER_INFO_1);
830
831                 break;
832
833         case 2:
834                 result = from_struct(ctr.printers_2, py_PRINTER_INFO_2);
835
836                 PyDict_SetItemString(result, "security_descriptor", 
837                                      PySECDESC_FromSECDESC(
838                                              ctr.printers_2->secdesc));
839                 
840                 PyDict_SetItemString(result, "device_mode",
841                                      PyDEVICEMODE_FromDEVICEMODE(
842                                              ctr.printers_2->devmode));
843
844                 break;
845
846         case 3:
847                 result = from_struct(ctr.printers_3, py_PRINTER_INFO_3);
848
849                 PyDict_SetItemString(result, "security_descriptor",
850                                      PySECDESC_FromSECDESC(
851                                              ctr.printers_3->secdesc));
852                 break;
853
854         default:
855                 result = Py_None;
856                 break;
857         }
858  done:
859         Py_INCREF(result);
860         return result;
861 }
862
863 /* Set printer information */
864
865 static PyObject *spoolss_setprinter(PyObject *self, PyObject *args,
866                                     PyObject *kw)
867 {
868         PyObject *po;
869         spoolss_policy_hnd_object *hnd;
870         WERROR werror;
871         PyObject *result, *info;
872         PRINTER_INFO_CTR ctr;
873         int level = 1;
874         static char *kwlist[] = { "hnd", "dict", "level", NULL };
875         union {
876                 PRINTER_INFO_0 printers_0;
877                 PRINTER_INFO_1 printers_1;
878                 PRINTER_INFO_2 printers_2;
879                 PRINTER_INFO_3 printers_3;
880                 PRINTER_INFO_4 printers_4;
881                 PRINTER_INFO_5 printers_5;
882         } pinfo;
883
884         /* Parse parameters */
885
886         if (!PyArg_ParseTupleAndKeywords(args, kw, "O!O!|i", kwlist, 
887                                          &spoolss_policy_hnd_type, &po, 
888                                          &PyDict_Type, &info, &level))
889                 return NULL;
890         
891         hnd = (spoolss_policy_hnd_object *)po;
892         
893         /* Fill in printer info */
894
895         ZERO_STRUCT(ctr);
896
897         switch (level) {
898         case 1:
899                 ctr.printers_1 = &pinfo.printers_1;
900                 to_struct(&pinfo.printers_1, info, py_PRINTER_INFO_1);
901                 break;
902         default:
903         }
904
905         /* Call rpc function */
906         
907         werror = cli_spoolss_setprinter(hnd->cli, hnd->mem_ctx, &hnd->pol,
908                                         level, &ctr, 0);
909
910         /* Return value */
911
912         result = Py_None;
913
914         if (!W_ERROR_IS_OK(werror))
915                 goto done;
916
917  done:
918         Py_INCREF(result);
919         return result;
920 }
921
922 /* Enumerate printers */
923
924 static PyObject *spoolss_enumprinters(PyObject *self, PyObject *args,
925                                       PyObject *kw)
926 {
927         WERROR werror;
928         PyObject *result, *creds = NULL;
929         PRINTER_INFO_CTR ctr;
930         int level = 1, flags = PRINTER_ENUM_LOCAL, i;
931         uint32 needed, num_printers;
932         static char *kwlist[] = {"server", "name", "level", "flags", 
933                                  "creds", NULL};
934         TALLOC_CTX *mem_ctx = NULL;
935         struct cli_state *cli = NULL;
936         char *server, *name = NULL;
937
938         /* Parse parameters */
939
940         if (!PyArg_ParseTupleAndKeywords(args, kw, "s|siiO!", kwlist, 
941                                          &server, &name, &level, &flags, 
942                                          &PyDict_Type, &creds))
943                 return NULL;
944         
945         if (server[0] == '\\' && server[1] == '\\')
946                 server += 2;
947
948         mem_ctx = talloc_init();
949         cli = open_pipe_creds(server, creds, cli_spoolss_initialise, NULL);
950
951         /* Call rpc function */
952         
953         werror = cli_spoolss_enum_printers(
954                 cli, mem_ctx, 0, &needed, flags, level,
955                 &num_printers, &ctr);
956
957         if (W_ERROR_V(werror) == ERRinsufficientbuffer)
958                 werror = cli_spoolss_enum_printers(
959                         cli, mem_ctx, needed, NULL, flags, level,
960                         &num_printers, &ctr);
961
962         /* Return value */
963         
964         result = Py_None;
965
966         if (!W_ERROR_IS_OK(werror))
967                 goto done;
968
969         result = PyList_New(num_printers);
970
971         switch (level) {
972         case 0: 
973                 for (i = 0; i < num_printers; i++) {
974                         PyObject *value;
975
976                         value = from_struct (
977                                 &ctr.printers_0[i], py_PRINTER_INFO_0);
978
979                         PyList_SetItem(result, i, value);
980                 }
981
982                 break;
983         case 1:
984                 for(i = 0; i < num_printers; i++) {
985                         PyObject *value;
986
987                         value = from_struct(
988                                 &ctr.printers_1[i], py_PRINTER_INFO_1);
989
990                         PyList_SetItem(result, i, value);
991                 }
992                 
993                 break;
994         case 2:
995                 for(i = 0; i < num_printers; i++) {
996                         PyObject *value;
997
998                         value = from_struct(
999                                 &ctr.printers_2[i], py_PRINTER_INFO_2);
1000
1001                         PyList_SetItem(result, i, value);
1002                 }
1003                 
1004                 break;
1005         case 3:
1006                 for(i = 0; i < num_printers; i++) {
1007                         PyObject *value;
1008
1009                         value = from_struct(
1010                                 &ctr.printers_3[i], py_PRINTER_INFO_3);
1011
1012                         PyList_SetItem(result, i, value);
1013                 }
1014                 
1015                 break;
1016         }
1017
1018  done:
1019         Py_INCREF(result);
1020         return result;
1021 }
1022
1023 /* 
1024  * Method dispatch table
1025  */
1026
1027 #include "python/py_spoolss_forms.h"
1028
1029 static PyMethodDef spoolss_methods[] = {
1030
1031         /* Open/close printer handles */
1032         
1033         { "openprinter", spoolss_openprinter, METH_VARARGS | METH_KEYWORDS, 
1034           "Open printer" },
1035         
1036         { "closeprinter", spoolss_closeprinter, METH_VARARGS, 
1037           "Close printer" },
1038
1039         /* Printer drivers */
1040
1041         { "getprinterdriver", spoolss_getprinterdriver, 
1042           METH_VARARGS | METH_KEYWORDS, "Fetch printer driver" },
1043
1044         { "enumprinterdrivers", spoolss_enumprinterdrivers,
1045           METH_VARARGS | METH_KEYWORDS, "Enumerate printer drivers" },
1046
1047         { "getprinter", spoolss_getprinter, METH_VARARGS | METH_KEYWORDS,
1048           "Fetch printer information" },
1049
1050         { "setprinter", spoolss_setprinter, METH_VARARGS | METH_KEYWORDS,
1051           "Set printer information" },
1052
1053         { "enumprinters", spoolss_enumprinters, METH_VARARGS | METH_KEYWORDS,
1054           "Enumerate printers" },
1055
1056         { NULL }
1057 };
1058
1059 /* Initialise constants */
1060
1061 struct spoolss_const {
1062         char *name;
1063         uint32 value;
1064 } spoolss_const_vals[] = {
1065         
1066         /* Access permissions */
1067
1068         { "MAXIMUM_ALLOWED_ACCESS", MAXIMUM_ALLOWED_ACCESS },
1069         { "SERVER_ALL_ACCESS", SERVER_ALL_ACCESS },
1070         { "PRINTER_ALL_ACCESS", PRINTER_ALL_ACCESS },
1071
1072         /* Printer enumeration flags */
1073
1074         { "PRINTER_ENUM_DEFAULT", PRINTER_ENUM_DEFAULT },
1075         { "PRINTER_ENUM_LOCAL", PRINTER_ENUM_LOCAL },
1076         { "PRINTER_ENUM_CONNECTIONS", PRINTER_ENUM_CONNECTIONS },
1077         { "PRINTER_ENUM_FAVORITE", PRINTER_ENUM_FAVORITE },
1078         { "PRINTER_ENUM_NAME", PRINTER_ENUM_NAME },
1079         { "PRINTER_ENUM_REMOTE", PRINTER_ENUM_REMOTE },
1080         { "PRINTER_ENUM_SHARED", PRINTER_ENUM_SHARED },
1081         { "PRINTER_ENUM_NETWORK", PRINTER_ENUM_NETWORK },
1082
1083         { NULL },
1084 };
1085
1086 static void const_init(PyObject *dict)
1087 {
1088         struct spoolss_const *tmp;
1089         PyObject *obj;
1090
1091         for (tmp = spoolss_const_vals; tmp->name; tmp++) {
1092                 obj = PyInt_FromLong(tmp->value);
1093                 PyDict_SetItemString(dict, tmp->name, obj);
1094                 Py_DECREF(obj);
1095         }
1096 }
1097
1098 /* Module initialisation */
1099
1100 void initspoolss(void)
1101 {
1102         PyObject *module, *dict;
1103
1104         /* Initialise module */
1105
1106         module = Py_InitModule("spoolss", spoolss_methods);
1107         dict = PyModule_GetDict(module);
1108
1109         /* Make spools_error global an exception we can raise when an error
1110            occurs. */
1111
1112         spoolss_error = PyErr_NewException("spoolss.error", NULL, NULL);
1113         PyDict_SetItemString(dict, "error", spoolss_error);
1114
1115         spoolss_werror = PyErr_NewException("spoolss.werror", NULL, NULL);
1116         PyDict_SetItemString(dict, "werror", spoolss_werror);
1117
1118         /* Initialise policy handle object */
1119
1120         spoolss_policy_hnd_type.ob_type = &PyType_Type;
1121
1122         /* Initialise constants */
1123
1124         const_init(dict);
1125
1126         /* Do samba initialisation */
1127
1128         py_samba_init();
1129 }