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