import HEAD into svn+ssh://svn.samba.org/home/svn/samba/trunk
[metze/old/v3-2-winbind-ndr.git] / source / python / py_spoolss_printers.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 "python/py_spoolss.h"
22
23 /* Open a printer */
24
25 PyObject *spoolss_openprinter(PyObject *self, PyObject *args, PyObject *kw)
26 {
27         char *unc_name, *server, *errstr;
28         TALLOC_CTX *mem_ctx = NULL;
29         POLICY_HND hnd;
30         WERROR werror;
31         PyObject *result = NULL, *creds = NULL;
32         static char *kwlist[] = { "printername", "creds", "access", NULL };
33         uint32 desired_access = MAXIMUM_ALLOWED_ACCESS;
34         struct cli_state *cli;
35
36         if (!PyArg_ParseTupleAndKeywords(
37                     args, kw, "s|Oi", kwlist, &unc_name, &creds,
38                     &desired_access))
39                 return NULL;
40
41         if (unc_name[0] != '\\' || unc_name[1] != '\\') {
42                 PyErr_SetString(PyExc_ValueError, "UNC name required");
43                 return NULL;
44         }
45
46         server = strdup(unc_name + 2);
47
48         if (strchr(server, '\\')) {
49                 char *c = strchr(server, '\\');
50                 *c = 0;
51         }
52
53         if (creds && creds != Py_None && !PyDict_Check(creds)) {
54                 PyErr_SetString(PyExc_TypeError, 
55                                 "credentials must be dictionary or None");
56                 return NULL;
57         }
58
59         if (!(cli = open_pipe_creds(server, creds, PI_SPOOLSS, &errstr))) {
60                 PyErr_SetString(spoolss_error, errstr);
61                 free(errstr);
62                 goto done;
63         }
64
65         if (!(mem_ctx = talloc_init("spoolss_openprinter"))) {
66                 PyErr_SetString(spoolss_error, 
67                                 "unable to init talloc context\n");
68                 goto done;
69         }
70
71         werror = cli_spoolss_open_printer_ex(
72                 cli, mem_ctx, unc_name, "", desired_access, server, 
73                 "", &hnd);
74
75         if (!W_ERROR_IS_OK(werror)) {
76                 PyErr_SetObject(spoolss_werror, py_werror_tuple(werror));
77                 goto done;
78         }
79
80         result = new_spoolss_policy_hnd_object(cli, mem_ctx, &hnd);
81
82  done:
83         if (!result) {
84                 if (cli)
85                         cli_shutdown(cli);
86
87                 if (mem_ctx)
88                         talloc_destroy(mem_ctx);
89         }
90
91         SAFE_FREE(server);
92
93         return result;
94 }
95
96 /* Close a printer */
97
98 PyObject *spoolss_closeprinter(PyObject *self, PyObject *args)
99 {
100         PyObject *po;
101         spoolss_policy_hnd_object *hnd;
102         WERROR result;
103
104         /* Parse parameters */
105
106         if (!PyArg_ParseTuple(args, "O!", &spoolss_policy_hnd_type, &po))
107                 return NULL;
108
109         hnd = (spoolss_policy_hnd_object *)po;
110
111         /* Call rpc function */
112
113         result = cli_spoolss_close_printer(hnd->cli, hnd->mem_ctx, &hnd->pol);
114
115         /* Return value */
116
117         Py_INCREF(Py_None);
118         return Py_None; 
119 }
120
121 /* Fetch printer information */
122
123 PyObject *spoolss_hnd_getprinter(PyObject *self, PyObject *args, PyObject *kw)
124 {
125         spoolss_policy_hnd_object *hnd = (spoolss_policy_hnd_object *)self;
126         WERROR werror;
127         PyObject *result = NULL;
128         PRINTER_INFO_CTR ctr;
129         int level = 1;
130         uint32 needed;
131         static char *kwlist[] = {"level", NULL};
132         
133         /* Parse parameters */
134
135         if (!PyArg_ParseTupleAndKeywords(args, kw, "|i", kwlist, &level))
136                 return NULL;
137         
138         ZERO_STRUCT(ctr);
139
140         /* Call rpc function */
141         
142         werror = cli_spoolss_getprinter(
143                 hnd->cli, hnd->mem_ctx, 0, &needed, &hnd->pol, level, &ctr);
144
145         if (W_ERROR_V(werror) == ERRinsufficientbuffer)
146                 werror = cli_spoolss_getprinter(
147                         hnd->cli, hnd->mem_ctx, needed, NULL, &hnd->pol,
148                         level, &ctr);
149
150         /* Return value */
151
152         if (!W_ERROR_IS_OK(werror)) {
153                 PyErr_SetObject(spoolss_werror, py_werror_tuple(werror));
154                 return NULL;
155         }
156
157         result = Py_None;
158
159         switch (level) {
160                 
161         case 0:
162                 py_from_PRINTER_INFO_0(&result, ctr.printers_0);
163                 break;
164
165         case 1:
166                 py_from_PRINTER_INFO_1(&result, ctr.printers_1);
167                 break;
168
169         case 2:
170                 py_from_PRINTER_INFO_2(&result, ctr.printers_2);
171                 break;
172
173         case 3:
174                 py_from_PRINTER_INFO_3(&result, ctr.printers_3);
175                 break;
176         }
177
178         Py_INCREF(result);
179         return result;
180 }
181
182 /* Set printer information */
183
184 PyObject *spoolss_hnd_setprinter(PyObject *self, PyObject *args, PyObject *kw)
185 {
186         spoolss_policy_hnd_object *hnd = (spoolss_policy_hnd_object *)self;
187         WERROR werror;
188         PyObject *info;
189         PRINTER_INFO_CTR ctr;
190         uint32 level;
191         static char *kwlist[] = {"dict", NULL};
192         union {
193                 PRINTER_INFO_1 printers_1;
194                 PRINTER_INFO_2 printers_2;
195                 PRINTER_INFO_3 printers_3;
196         } pinfo;
197
198         /* Parse parameters */
199
200         if (!PyArg_ParseTupleAndKeywords(
201                     args, kw, "O!", kwlist, &PyDict_Type, &info))
202                 return NULL;
203         
204         if (!get_level_value(info, &level)) {
205                 PyErr_SetString(spoolss_error, "invalid info level");
206                 return NULL;
207         }
208
209         if (level < 1 && level > 3) {
210                 PyErr_SetString(spoolss_error, "unsupported info level");
211                 return NULL;
212         }
213
214         /* Fill in printer info */
215
216         ZERO_STRUCT(ctr);
217
218         switch (level) {
219         case 1:
220                 ctr.printers_1 = &pinfo.printers_1;
221
222                 if (!py_to_PRINTER_INFO_1(ctr.printers_1, info)){
223                         PyErr_SetString(spoolss_error, 
224                                         "error converting printer to info 1");
225                         return NULL;
226                 }
227
228                 break;
229         case 2:
230                 ctr.printers_2 = &pinfo.printers_2;
231
232                 if (!py_to_PRINTER_INFO_2(ctr.printers_2, info,
233                                           hnd->mem_ctx)){
234                         PyErr_SetString(spoolss_error, 
235                                         "error converting printer to info 2");
236                         return NULL;
237                 }
238
239                 break;
240         case 3:
241                 ctr.printers_3 = &pinfo.printers_3;
242
243                 if (!py_to_PRINTER_INFO_3(ctr.printers_3, info,
244                                           hnd->mem_ctx)) {
245                         PyErr_SetString(spoolss_error,
246                                         "error converting to printer info 3");
247                         return NULL;
248                 }
249
250                 break;
251         default:
252                 PyErr_SetString(spoolss_error, "unsupported info level");
253                 return NULL;
254         }
255
256         /* Call rpc function */
257         
258         werror = cli_spoolss_setprinter(hnd->cli, hnd->mem_ctx, &hnd->pol,
259                                         level, &ctr, 0);
260
261         /* Return value */
262
263         if (!W_ERROR_IS_OK(werror)) {
264                 PyErr_SetObject(spoolss_werror, py_werror_tuple(werror));
265                 return NULL;
266         }
267
268         Py_INCREF(Py_None);
269         return Py_None;
270 }
271
272 /* Enumerate printers */
273
274 PyObject *spoolss_enumprinters(PyObject *self, PyObject *args, PyObject *kw)
275 {
276         WERROR werror;
277         PyObject *result = NULL, *creds = NULL;
278         PRINTER_INFO_CTR ctr;
279         int level = 1, flags = PRINTER_ENUM_LOCAL, i;
280         uint32 needed, num_printers;
281         static char *kwlist[] = {"server", "name", "level", "flags", 
282                                  "creds", NULL};
283         TALLOC_CTX *mem_ctx = NULL;
284         struct cli_state *cli = NULL;
285         char *server, *errstr, *name = NULL;
286
287         /* Parse parameters */
288
289         if (!PyArg_ParseTupleAndKeywords(
290                     args, kw, "s|siiO", kwlist, &server, &name, &level, 
291                     &flags, &creds))
292                 return NULL;
293         
294         if (server[0] != '\\' || server[1] != '\\') {
295                 PyErr_SetString(PyExc_ValueError, "UNC name required");
296                 return NULL;
297         }
298
299         server += 2;
300
301         if (creds && creds != Py_None && !PyDict_Check(creds)) {
302                 PyErr_SetString(PyExc_TypeError, 
303                                 "credentials must be dictionary or None");
304                 return NULL;
305         }
306
307         if (!(cli = open_pipe_creds(server, creds, PI_SPOOLSS, &errstr))) {
308                 PyErr_SetString(spoolss_error, errstr);
309                 free(errstr);
310                 goto done;
311         }
312
313         if (!(mem_ctx = talloc_init("spoolss_enumprinters"))) {
314                 PyErr_SetString(
315                         spoolss_error, "unable to init talloc context\n");
316                 goto done;
317         }
318
319         /* This RPC is weird.  By setting the server name to different
320            values we can get different behaviour.  If however the server
321            name is not specified, we default it to being the full server
322            name as this is probably what the caller intended.  To pass a
323            NULL name, pass a value of "" */
324
325         if (!name)
326                 name = server;
327         else {
328                 if (!name[0])
329                         name = NULL;
330         }
331
332         /* Call rpc function */
333         
334         werror = cli_spoolss_enum_printers(
335                 cli, mem_ctx, 0, &needed, name, flags, level,
336                 &num_printers, &ctr);
337
338         if (W_ERROR_V(werror) == ERRinsufficientbuffer)
339                 werror = cli_spoolss_enum_printers(
340                         cli, mem_ctx, needed, NULL, name, flags, 
341                         level, &num_printers, &ctr);
342
343         if (!W_ERROR_IS_OK(werror)) {
344                 PyErr_SetObject(spoolss_werror, py_werror_tuple(werror));
345                 goto done;
346         }
347
348         /* Return value */
349         
350         switch (level) {
351         case 0: 
352                 result = PyDict_New();
353
354                 for (i = 0; i < num_printers; i++) {
355                         PyObject *value;
356                         fstring s;
357
358                         rpcstr_pull(s, ctr.printers_0[i].printername.buffer,
359                                     sizeof(fstring), -1, STR_TERMINATE);
360
361                         py_from_PRINTER_INFO_0(&value, &ctr.printers_0[i]);
362
363                         PyDict_SetItemString(
364                                 value, "level", PyInt_FromLong(0));
365
366                         PyDict_SetItemString(result, s, value);
367                 }
368
369                 break;
370         case 1:
371                 result = PyDict_New();
372
373                 for(i = 0; i < num_printers; i++) {
374                         PyObject *value;
375                         fstring s;
376
377                         rpcstr_pull(s, ctr.printers_1[i].name.buffer,
378                                     sizeof(fstring), -1, STR_TERMINATE);
379
380                         py_from_PRINTER_INFO_1(&value, &ctr.printers_1[i]);
381
382                         PyDict_SetItemString(
383                                 value, "level", PyInt_FromLong(1));
384
385                         PyDict_SetItemString(result, s, value);
386                 }
387                 
388                 break;
389         case 2:
390                 result = PyDict_New();
391
392                 for(i = 0; i < num_printers; i++) {
393                         PyObject *value;
394                         fstring s;
395
396                         rpcstr_pull(s, ctr.printers_2[i].printername.buffer,
397                                     sizeof(fstring), -1, STR_TERMINATE);
398
399                         py_from_PRINTER_INFO_2(&value, &ctr.printers_2[i]);
400
401                         PyDict_SetItemString(
402                                 value, "level", PyInt_FromLong(2));
403
404                         PyDict_SetItemString(result, s, value);
405                 }
406                 
407                 break;
408         default:
409                 PyErr_SetString(spoolss_error, "unknown info level");
410                 goto done;
411         }
412
413 done:
414         if (cli)
415                 cli_shutdown(cli);
416
417         if (mem_ctx)
418                 talloc_destroy(mem_ctx);
419
420         return result;
421 }
422
423 /* Add a printer */
424
425 PyObject *spoolss_addprinterex(PyObject *self, PyObject *args, PyObject *kw)
426 {
427         static char *kwlist[] = { "server", "printername", "info", "creds", 
428                                   NULL};
429         char *printername, *server, *errstr;
430         PyObject *info, *result = NULL, *creds = NULL;
431         struct cli_state *cli = NULL;
432         TALLOC_CTX *mem_ctx = NULL;
433         PRINTER_INFO_CTR ctr;
434         PRINTER_INFO_2 info2;
435         WERROR werror;
436
437         if (!PyArg_ParseTupleAndKeywords(
438                     args, kw, "ssO!|O!", kwlist, &server, &printername,
439                     &PyDict_Type, &info, &PyDict_Type, &creds))
440                 return NULL;
441
442         if (!(cli = open_pipe_creds(server, creds, PI_SPOOLSS, &errstr))) {
443                 PyErr_SetString(spoolss_error, errstr);
444                 free(errstr);
445                 goto done;
446         }
447
448         if (!(mem_ctx = talloc_init("spoolss_addprinterex"))) {
449                 PyErr_SetString(
450                         spoolss_error, "unable to init talloc context\n");
451                 goto done;
452         }
453
454         if (!py_to_PRINTER_INFO_2(&info2, info, mem_ctx)) {
455                 PyErr_SetString(spoolss_error,
456                                 "error converting to printer info 2");
457                 goto done;
458         }
459
460         ctr.printers_2 = &info2;
461
462         werror = cli_spoolss_addprinterex(cli, mem_ctx, 2, &ctr);
463
464         Py_INCREF(Py_None);
465         result = Py_None;
466
467 done:
468         if (cli)
469                 cli_shutdown(cli);
470
471         if (mem_ctx)
472                 talloc_destroy(mem_ctx);
473
474         return result;
475 }