Initial import
[samba] / 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 = SMB_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 = rpccli_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 = rpccli_spoolss_close_printer(
114                 hnd->cli, hnd->mem_ctx, &hnd->pol);
115
116         /* Return value */
117
118         Py_INCREF(Py_None);
119         return Py_None; 
120 }
121
122 /* Fetch printer information */
123
124 PyObject *spoolss_hnd_getprinter(PyObject *self, PyObject *args, PyObject *kw)
125 {
126         spoolss_policy_hnd_object *hnd = (spoolss_policy_hnd_object *)self;
127         WERROR werror;
128         PyObject *result = NULL;
129         PRINTER_INFO_CTR ctr;
130         int level = 1;
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 = rpccli_spoolss_getprinter(
143                 hnd->cli, hnd->mem_ctx, &hnd->pol, level, &ctr);
144
145         /* Return value */
146
147         if (!W_ERROR_IS_OK(werror)) {
148                 PyErr_SetObject(spoolss_werror, py_werror_tuple(werror));
149                 return NULL;
150         }
151
152         result = Py_None;
153
154         switch (level) {
155                 
156         case 0:
157                 py_from_PRINTER_INFO_0(&result, ctr.printers_0);
158                 break;
159
160         case 1:
161                 py_from_PRINTER_INFO_1(&result, ctr.printers_1);
162                 break;
163
164         case 2:
165                 py_from_PRINTER_INFO_2(&result, ctr.printers_2);
166                 break;
167
168         case 3:
169                 py_from_PRINTER_INFO_3(&result, ctr.printers_3);
170                 break;
171         }
172
173         Py_INCREF(result);
174         return result;
175 }
176
177 /* Set printer information */
178
179 PyObject *spoolss_hnd_setprinter(PyObject *self, PyObject *args, PyObject *kw)
180 {
181         spoolss_policy_hnd_object *hnd = (spoolss_policy_hnd_object *)self;
182         WERROR werror;
183         PyObject *info;
184         PRINTER_INFO_CTR ctr;
185         uint32 level;
186         static char *kwlist[] = {"dict", NULL};
187         union {
188                 PRINTER_INFO_1 printers_1;
189                 PRINTER_INFO_2 printers_2;
190                 PRINTER_INFO_3 printers_3;
191         } pinfo;
192
193         /* Parse parameters */
194
195         if (!PyArg_ParseTupleAndKeywords(
196                     args, kw, "O!", kwlist, &PyDict_Type, &info))
197                 return NULL;
198         
199         if (!get_level_value(info, &level)) {
200                 PyErr_SetString(spoolss_error, "invalid info level");
201                 return NULL;
202         }
203
204         if (level < 1 && level > 3) {
205                 PyErr_SetString(spoolss_error, "unsupported info level");
206                 return NULL;
207         }
208
209         /* Fill in printer info */
210
211         ZERO_STRUCT(ctr);
212
213         switch (level) {
214         case 1:
215                 ctr.printers_1 = &pinfo.printers_1;
216
217                 if (!py_to_PRINTER_INFO_1(ctr.printers_1, info)){
218                         PyErr_SetString(spoolss_error, 
219                                         "error converting printer to info 1");
220                         return NULL;
221                 }
222
223                 break;
224         case 2:
225                 ctr.printers_2 = &pinfo.printers_2;
226
227                 if (!py_to_PRINTER_INFO_2(ctr.printers_2, info,
228                                           hnd->mem_ctx)){
229                         PyErr_SetString(spoolss_error, 
230                                         "error converting printer to info 2");
231                         return NULL;
232                 }
233
234                 break;
235         case 3:
236                 ctr.printers_3 = &pinfo.printers_3;
237
238                 if (!py_to_PRINTER_INFO_3(ctr.printers_3, info,
239                                           hnd->mem_ctx)) {
240                         PyErr_SetString(spoolss_error,
241                                         "error converting to printer info 3");
242                         return NULL;
243                 }
244
245                 break;
246         default:
247                 PyErr_SetString(spoolss_error, "unsupported info level");
248                 return NULL;
249         }
250
251         /* Call rpc function */
252         
253         werror = rpccli_spoolss_setprinter(
254                 hnd->cli, hnd->mem_ctx, &hnd->pol, level, &ctr, 0);
255
256         /* Return value */
257
258         if (!W_ERROR_IS_OK(werror)) {
259                 PyErr_SetObject(spoolss_werror, py_werror_tuple(werror));
260                 return NULL;
261         }
262
263         Py_INCREF(Py_None);
264         return Py_None;
265 }
266
267 /* Enumerate printers */
268
269 PyObject *spoolss_enumprinters(PyObject *self, PyObject *args, PyObject *kw)
270 {
271         WERROR werror;
272         PyObject *result = NULL, *creds = NULL;
273         PRINTER_INFO_CTR ctr;
274         int level = 1, flags = PRINTER_ENUM_LOCAL, i;
275         uint32 num_printers;
276         static char *kwlist[] = {"server", "name", "level", "flags", 
277                                  "creds", NULL};
278         TALLOC_CTX *mem_ctx = NULL;
279         struct cli_state *cli = NULL;
280         char *server, *errstr, *name = NULL;
281
282         /* Parse parameters */
283
284         if (!PyArg_ParseTupleAndKeywords(
285                     args, kw, "s|siiO", kwlist, &server, &name, &level, 
286                     &flags, &creds))
287                 return NULL;
288         
289         if (server[0] != '\\' || server[1] != '\\') {
290                 PyErr_SetString(PyExc_ValueError, "UNC name required");
291                 return NULL;
292         }
293
294         server += 2;
295
296         if (creds && creds != Py_None && !PyDict_Check(creds)) {
297                 PyErr_SetString(PyExc_TypeError, 
298                                 "credentials must be dictionary or None");
299                 return NULL;
300         }
301
302         if (!(cli = open_pipe_creds(server, creds, PI_SPOOLSS, &errstr))) {
303                 PyErr_SetString(spoolss_error, errstr);
304                 free(errstr);
305                 goto done;
306         }
307
308         if (!(mem_ctx = talloc_init("spoolss_enumprinters"))) {
309                 PyErr_SetString(
310                         spoolss_error, "unable to init talloc context\n");
311                 goto done;
312         }
313
314         /* This RPC is weird.  By setting the server name to different
315            values we can get different behaviour.  If however the server
316            name is not specified, we default it to being the full server
317            name as this is probably what the caller intended.  To pass a
318            NULL name, pass a value of "" */
319
320         if (!name)
321                 name = server;
322         else {
323                 if (!name[0])
324                         name = NULL;
325         }
326
327         /* Call rpc function */
328         
329         werror = rpccli_spoolss_enum_printers(
330                 cli, mem_ctx, name, flags, level, &num_printers, &ctr);
331
332         if (!W_ERROR_IS_OK(werror)) {
333                 PyErr_SetObject(spoolss_werror, py_werror_tuple(werror));
334                 goto done;
335         }
336
337         /* Return value */
338         
339         switch (level) {
340         case 0: 
341                 result = PyDict_New();
342
343                 for (i = 0; i < num_printers; i++) {
344                         PyObject *value;
345                         fstring s;
346
347                         rpcstr_pull(s, ctr.printers_0[i].printername.buffer,
348                                     sizeof(fstring), -1, STR_TERMINATE);
349
350                         py_from_PRINTER_INFO_0(&value, &ctr.printers_0[i]);
351
352                         PyDict_SetItemString(
353                                 value, "level", PyInt_FromLong(0));
354
355                         PyDict_SetItemString(result, s, value);
356                 }
357
358                 break;
359         case 1:
360                 result = PyDict_New();
361
362                 for(i = 0; i < num_printers; i++) {
363                         PyObject *value;
364                         fstring s;
365
366                         rpcstr_pull(s, ctr.printers_1[i].name.buffer,
367                                     sizeof(fstring), -1, STR_TERMINATE);
368
369                         py_from_PRINTER_INFO_1(&value, &ctr.printers_1[i]);
370
371                         PyDict_SetItemString(
372                                 value, "level", PyInt_FromLong(1));
373
374                         PyDict_SetItemString(result, s, value);
375                 }
376                 
377                 break;
378         case 2:
379                 result = PyDict_New();
380
381                 for(i = 0; i < num_printers; i++) {
382                         PyObject *value;
383                         fstring s;
384
385                         rpcstr_pull(s, ctr.printers_2[i].printername.buffer,
386                                     sizeof(fstring), -1, STR_TERMINATE);
387
388                         py_from_PRINTER_INFO_2(&value, &ctr.printers_2[i]);
389
390                         PyDict_SetItemString(
391                                 value, "level", PyInt_FromLong(2));
392
393                         PyDict_SetItemString(result, s, value);
394                 }
395                 
396                 break;
397         default:
398                 PyErr_SetString(spoolss_error, "unknown info level");
399                 goto done;
400         }
401
402 done:
403         if (cli)
404                 cli_shutdown(cli);
405
406         if (mem_ctx)
407                 talloc_destroy(mem_ctx);
408
409         return result;
410 }
411
412 /* Add a printer */
413
414 PyObject *spoolss_addprinterex(PyObject *self, PyObject *args, PyObject *kw)
415 {
416         static char *kwlist[] = { "server", "printername", "info", "creds", 
417                                   NULL};
418         char *printername, *server, *errstr;
419         PyObject *info, *result = NULL, *creds = NULL;
420         struct cli_state *cli = NULL;
421         TALLOC_CTX *mem_ctx = NULL;
422         PRINTER_INFO_CTR ctr;
423         PRINTER_INFO_2 info2;
424         WERROR werror;
425
426         if (!PyArg_ParseTupleAndKeywords(
427                     args, kw, "ssO!|O!", kwlist, &server, &printername,
428                     &PyDict_Type, &info, &PyDict_Type, &creds))
429                 return NULL;
430
431         if (!(cli = open_pipe_creds(server, creds, PI_SPOOLSS, &errstr))) {
432                 PyErr_SetString(spoolss_error, errstr);
433                 free(errstr);
434                 goto done;
435         }
436
437         if (!(mem_ctx = talloc_init("spoolss_addprinterex"))) {
438                 PyErr_SetString(
439                         spoolss_error, "unable to init talloc context\n");
440                 goto done;
441         }
442
443         if (!py_to_PRINTER_INFO_2(&info2, info, mem_ctx)) {
444                 PyErr_SetString(spoolss_error,
445                                 "error converting to printer info 2");
446                 goto done;
447         }
448
449         ctr.printers_2 = &info2;
450
451         werror = rpccli_spoolss_addprinterex(cli, mem_ctx, 2, &ctr);
452
453         Py_INCREF(Py_None);
454         result = Py_None;
455
456 done:
457         if (cli)
458                 cli_shutdown(cli);
459
460         if (mem_ctx)
461                 talloc_destroy(mem_ctx);
462
463         return result;
464 }