This commit was manufactured by cvs2svn to create branch 'SAMBA_3_0'.
[samba.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                 /* These info levels are supported by NT4 and higher
178                    but don't seem to be used by any clients we know of. */
179
180         case 4:
181         case 5:
182         case 6:
183                 break;
184
185                 /* These info levels are only supported by Windows 2000
186                    and higher. */
187
188         case 7:
189         case 8:
190         case 9:
191                 break;
192         }
193
194         Py_INCREF(result);
195         return result;
196 }
197
198 /* Set printer information */
199
200 PyObject *spoolss_hnd_setprinter(PyObject *self, PyObject *args, PyObject *kw)
201 {
202         spoolss_policy_hnd_object *hnd = (spoolss_policy_hnd_object *)self;
203         WERROR werror;
204         PyObject *info;
205         PRINTER_INFO_CTR ctr;
206         uint32 level;
207         static char *kwlist[] = {"dict", NULL};
208         union {
209                 PRINTER_INFO_1 printers_1;
210                 PRINTER_INFO_2 printers_2;
211                 PRINTER_INFO_3 printers_3;
212         } pinfo;
213
214         /* Parse parameters */
215
216         if (!PyArg_ParseTupleAndKeywords(
217                     args, kw, "O!", kwlist, &PyDict_Type, &info))
218                 return NULL;
219         
220         if (!get_level_value(info, &level)) {
221                 PyErr_SetString(spoolss_error, "invalid info level");
222                 return NULL;
223         }
224
225         if (level < 1 && level > 3) {
226                 PyErr_SetString(spoolss_error, "unsupported info level");
227                 return NULL;
228         }
229
230         /* Fill in printer info */
231
232         ZERO_STRUCT(ctr);
233
234         switch (level) {
235         case 1:
236                 ctr.printers_1 = &pinfo.printers_1;
237
238                 if (!py_to_PRINTER_INFO_1(ctr.printers_1, info)){
239                         PyErr_SetString(spoolss_error, 
240                                         "error converting printer to info 1");
241                         return NULL;
242                 }
243
244                 break;
245         case 2:
246                 ctr.printers_2 = &pinfo.printers_2;
247
248                 if (!py_to_PRINTER_INFO_2(ctr.printers_2, info,
249                                           hnd->mem_ctx)){
250                         PyErr_SetString(spoolss_error, 
251                                         "error converting printer to info 2");
252                         return NULL;
253                 }
254
255                 break;
256         case 3:
257                 ctr.printers_3 = &pinfo.printers_3;
258
259                 if (!py_to_PRINTER_INFO_3(ctr.printers_3, info,
260                                           hnd->mem_ctx)) {
261                         PyErr_SetString(spoolss_error,
262                                         "error converting to printer info 3");
263                         return NULL;
264                 }
265
266                 break;
267         default:
268                 PyErr_SetString(spoolss_error, "unsupported info level");
269                 return NULL;
270         }
271
272         /* Call rpc function */
273         
274         werror = cli_spoolss_setprinter(hnd->cli, hnd->mem_ctx, &hnd->pol,
275                                         level, &ctr, 0);
276
277         /* Return value */
278
279         if (!W_ERROR_IS_OK(werror)) {
280                 PyErr_SetObject(spoolss_werror, py_werror_tuple(werror));
281                 return NULL;
282         }
283
284         Py_INCREF(Py_None);
285         return Py_None;
286 }
287
288 /* Enumerate printers */
289
290 PyObject *spoolss_enumprinters(PyObject *self, PyObject *args, PyObject *kw)
291 {
292         WERROR werror;
293         PyObject *result = NULL, *creds = NULL;
294         PRINTER_INFO_CTR ctr;
295         int level = 1, flags = PRINTER_ENUM_LOCAL, i;
296         uint32 needed, num_printers;
297         static char *kwlist[] = {"server", "name", "level", "flags", 
298                                  "creds", NULL};
299         TALLOC_CTX *mem_ctx = NULL;
300         struct cli_state *cli = NULL;
301         char *server, *errstr, *name = NULL;
302
303         /* Parse parameters */
304
305         if (!PyArg_ParseTupleAndKeywords(
306                     args, kw, "s|siiO", kwlist, &server, &name, &level, 
307                     &flags, &creds))
308                 return NULL;
309         
310         if (server[0] != '\\' || server[1] != '\\') {
311                 PyErr_SetString(PyExc_ValueError, "UNC name required");
312                 return NULL;
313         }
314
315         server += 2;
316
317         if (creds && creds != Py_None && !PyDict_Check(creds)) {
318                 PyErr_SetString(PyExc_TypeError, 
319                                 "credentials must be dictionary or None");
320                 return NULL;
321         }
322
323         if (!(cli = open_pipe_creds(server, creds, PI_SPOOLSS, &errstr))) {
324                 PyErr_SetString(spoolss_error, errstr);
325                 free(errstr);
326                 goto done;
327         }
328
329         if (!(mem_ctx = talloc_init("spoolss_enumprinters"))) {
330                 PyErr_SetString(
331                         spoolss_error, "unable to init talloc context\n");
332                 goto done;
333         }
334
335         /* This RPC is weird.  By setting the server name to different
336            values we can get different behaviour.  If however the server
337            name is not specified, we default it to being the full server
338            name as this is probably what the caller intended.  To pass a
339            NULL name, pass a value of "" */
340
341         if (!name)
342                 name = server;
343         else {
344                 if (!name[0])
345                         name = NULL;
346         }
347
348         /* Call rpc function */
349         
350         werror = cli_spoolss_enum_printers(
351                 cli, mem_ctx, 0, &needed, name, flags, level,
352                 &num_printers, &ctr);
353
354         if (W_ERROR_V(werror) == ERRinsufficientbuffer)
355                 werror = cli_spoolss_enum_printers(
356                         cli, mem_ctx, needed, NULL, name, flags, 
357                         level, &num_printers, &ctr);
358
359         if (!W_ERROR_IS_OK(werror)) {
360                 PyErr_SetObject(spoolss_werror, py_werror_tuple(werror));
361                 goto done;
362         }
363
364         /* Return value */
365         
366         switch (level) {
367         case 0: 
368                 result = PyDict_New();
369
370                 for (i = 0; i < num_printers; i++) {
371                         PyObject *value;
372                         fstring s;
373
374                         rpcstr_pull(s, ctr.printers_0[i].printername.buffer,
375                                     sizeof(fstring), -1, STR_TERMINATE);
376
377                         py_from_PRINTER_INFO_0(&value, &ctr.printers_0[i]);
378
379                         PyDict_SetItemString(
380                                 value, "level", PyInt_FromLong(0));
381
382                         PyDict_SetItemString(result, s, value);
383                 }
384
385                 break;
386         case 1:
387                 result = PyDict_New();
388
389                 for(i = 0; i < num_printers; i++) {
390                         PyObject *value;
391                         fstring s;
392
393                         rpcstr_pull(s, ctr.printers_1[i].name.buffer,
394                                     sizeof(fstring), -1, STR_TERMINATE);
395
396                         py_from_PRINTER_INFO_1(&value, &ctr.printers_1[i]);
397
398                         PyDict_SetItemString(
399                                 value, "level", PyInt_FromLong(1));
400
401                         PyDict_SetItemString(result, s, value);
402                 }
403                 
404                 break;
405         case 2:
406                 result = PyDict_New();
407
408                 for(i = 0; i < num_printers; i++) {
409                         PyObject *value;
410                         fstring s;
411
412                         rpcstr_pull(s, ctr.printers_2[i].printername.buffer,
413                                     sizeof(fstring), -1, STR_TERMINATE);
414
415                         py_from_PRINTER_INFO_2(&value, &ctr.printers_2[i]);
416
417                         PyDict_SetItemString(
418                                 value, "level", PyInt_FromLong(2));
419
420                         PyDict_SetItemString(result, s, value);
421                 }
422                 
423                 break;
424         default:
425                 PyErr_SetString(spoolss_error, "unknown info level");
426                 goto done;
427         }
428
429 done:
430         if (cli)
431                 cli_shutdown(cli);
432
433         if (mem_ctx)
434                 talloc_destroy(mem_ctx);
435
436         return result;
437 }
438
439 /* Add a printer */
440
441 PyObject *spoolss_addprinterex(PyObject *self, PyObject *args, PyObject *kw)
442 {
443         static char *kwlist[] = { "server", "printername", "info", "creds", 
444                                   NULL};
445         char *printername, *server, *errstr;
446         PyObject *info, *result = NULL, *creds = NULL;
447         struct cli_state *cli = NULL;
448         TALLOC_CTX *mem_ctx = NULL;
449         PRINTER_INFO_CTR ctr;
450         PRINTER_INFO_2 info2;
451         WERROR werror;
452
453         if (!PyArg_ParseTupleAndKeywords(
454                     args, kw, "ssO!|O!", kwlist, &server, &printername,
455                     &PyDict_Type, &info, &PyDict_Type, &creds))
456                 return NULL;
457
458         if (!(cli = open_pipe_creds(server, creds, PI_SPOOLSS, &errstr))) {
459                 PyErr_SetString(spoolss_error, errstr);
460                 free(errstr);
461                 goto done;
462         }
463
464         if (!(mem_ctx = talloc_init("spoolss_addprinterex"))) {
465                 PyErr_SetString(
466                         spoolss_error, "unable to init talloc context\n");
467                 goto done;
468         }
469
470         if (!py_to_PRINTER_INFO_2(&info2, info, mem_ctx)) {
471                 PyErr_SetString(spoolss_error,
472                                 "error converting to printer info 2");
473                 goto done;
474         }
475
476         ctr.printers_2 = &info2;
477
478         werror = cli_spoolss_addprinterex(cli, mem_ctx, 2, &ctr);
479
480         Py_INCREF(Py_None);
481         result = Py_None;
482
483 done:
484         if (cli)
485                 cli_shutdown(cli);
486
487         if (mem_ctx)
488                 talloc_destroy(mem_ctx);
489
490         return result;
491 }