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