nicer measurement of failures and collisions
[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 "python/py_spoolss.h"
22
23 /* Exceptions this module can raise */
24
25 PyObject *spoolss_error, *spoolss_werror;
26
27 /*
28  * Routines to convert from python hashes to Samba structures
29  */
30
31 struct cli_state *open_pipe_creds(char *system_name, PyObject *creds, 
32                                   cli_pipe_fn *connect_fn,
33                                   struct cli_state *cli)
34 {
35         struct ntuser_creds nt_creds;
36
37         if (!cli) {
38                 cli = (struct cli_state *)malloc(sizeof(struct cli_state));
39                 if (!cli)
40                         return NULL;
41         }
42
43         ZERO_STRUCTP(cli);
44
45         /* Extract credentials from the python dictionary and initialise
46            the ntuser_creds struct from them. */
47
48         ZERO_STRUCT(nt_creds);
49         nt_creds.pwd.null_pwd = True;
50
51         if (creds && PyDict_Size(creds) > 0) {
52                 char *username, *password, *domain;
53                 PyObject *username_obj, *password_obj, *domain_obj;
54
55                 /* Check credentials passed are valid.  This means the
56                    username, domain and password keys must exist and be
57                    string objects. */
58
59                 username_obj = PyDict_GetItemString(creds, "username");
60                 domain_obj = PyDict_GetItemString(creds, "domain");
61                 password_obj = PyDict_GetItemString(creds, "password");
62
63                 if (!username_obj || !domain_obj || !password_obj) {
64                 error:
65                         PyErr_SetString(spoolss_error, "invalid credentials");
66                         return NULL;
67                 }
68
69                 if (!PyString_Check(username_obj) || 
70                     !PyString_Check(domain_obj) || 
71                     !PyString_Check(password_obj))
72                         goto error;
73
74                 username = PyString_AsString(username_obj);
75                 domain = PyString_AsString(domain_obj);
76                 password = PyString_AsString(password_obj);
77
78                 if (!username || !domain || !password)
79                         goto error;
80
81                 /* Initialise nt_creds structure with passed creds */
82
83                 fstrcpy(nt_creds.user_name, username);
84                 fstrcpy(nt_creds.domain, domain);
85
86                 if (lp_encrypted_passwords())
87                         pwd_make_lm_nt_16(&nt_creds.pwd, password);
88                 else
89                         pwd_set_cleartext(&nt_creds.pwd, password);
90
91                 nt_creds.pwd.null_pwd = False;
92         }
93
94         /* Now try to connect */
95
96         connect_fn(cli, system_name, &nt_creds);
97
98         return cli;
99 }
100
101 PyObject *new_policy_hnd_object(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
102                                 POLICY_HND *pol)
103 {
104         spoolss_policy_hnd_object *o;
105
106         o = PyObject_New(spoolss_policy_hnd_object, &spoolss_policy_hnd_type);
107
108         o->cli = cli;
109         o->mem_ctx = mem_ctx;
110         memcpy(&o->pol, pol, sizeof(POLICY_HND));
111
112         return (PyObject*)o;
113 }
114      
115 /* 
116  * Method dispatch table
117  */
118
119 static PyMethodDef spoolss_methods[] = {
120
121         /* Open/close printer handles */
122         
123         { "openprinter", spoolss_openprinter, METH_VARARGS | METH_KEYWORDS, 
124           "openprinter(printername, [creds, access]) -> <spoolss hnd object>
125
126 Open a printer given by printername in UNC format.  Optionally a 
127 dictionary of (username, password) may be given in which case they are
128 used when opening the RPC pipe.  An access mask may also be given which
129 defaults to MAXIMUM_ALLOWED_ACCESS.
130
131 Example:
132
133 >>> hnd = spoolss.openprinter(\"\\\\\\\\NPSD-PDC2\\\\meanie\")
134 "},
135         
136         { "closeprinter", spoolss_closeprinter, METH_VARARGS, 
137           "closeprinter()
138
139 Close a printer handle opened with openprinter or addprinter.
140
141 Example:
142
143 >>> spoolss.closeprinter(hnd)
144 "},
145
146         /* Server enumeratation functions */
147
148         { "enumprinters", spoolss_enumprinters, METH_VARARGS | METH_KEYWORDS,
149           "enumprinters(server, [creds, level, flags]) -> list
150
151 Return a list of printers on a print server.  The credentials, info level
152 and flags may be specified as keyword arguments.
153
154 Example:
155
156 >>> print spoolss.enumprinters(\"\\\\\\\\npsd-pdc2\")
157 [{'comment': 'i am a comment', 'printer_name': 'meanie', 'flags': 8388608, 
158   'description': 'meanie,Generic / Text Only,i am a location'}, 
159  {'comment': '', 'printer_name': 'fileprint', 'flags': 8388608, 
160   'description': 'fileprint,Generic / Text Only,'}]
161 "},
162
163         { "enumports", spoolss_enumports, METH_VARARGS | METH_KEYWORDS,
164           "enumports(server, [creds, level]) -> list
165
166 Return a list of ports on a print server.
167
168 Example:
169
170 >>> print spoolss.enumports(\"\\\\\\\\npsd-pdc2\")
171 [{'name': 'LPT1:'}, {'name': 'LPT2:'}, {'name': 'COM1:'}, {'name': 'COM2:'}, 
172  {'name': 'FILE:'}, {'name': '\\\\nautilus1\\zpekt3r'}]
173 "},
174
175         { "enumprinterdrivers", spoolss_enumprinterdrivers, METH_VARARGS |
176           METH_KEYWORDS, 
177 "enumprinterdrivers(server, [level, arch, creds]) -> list
178
179 Return a list of printer drivers.
180 "},
181         /* Miscellaneous other commands */
182
183         { "getprinterdriverdir", spoolss_getprinterdriverdir, METH_VARARGS |
184           METH_KEYWORDS, "getprinterdriverdir(server, [creds]) -> string
185
186 Return the printer driver directory for a given architecture.  The 
187 architecture defaults to \"Windows NT x86\".
188 "},
189
190         /* Other stuff - this should really go into a samba config module
191            but for the moment let's leave it here. */
192
193         { "setup_logging", py_setup_logging, METH_VARARGS | METH_KEYWORDS, 
194           "" },
195
196         { "get_debuglevel", get_debuglevel, METH_VARARGS, "" },
197         { "set_debuglevel", set_debuglevel, METH_VARARGS, "" },
198
199         { NULL }
200 };
201
202 /* Methods attached to a spoolss handle object */
203
204 static PyMethodDef spoolss_hnd_methods[] = {
205
206         /* Printer info */
207
208         { "getprinter", spoolss_getprinter, METH_VARARGS | METH_KEYWORDS,
209           "getprinter([level]) -> dict
210
211 Return a dictionary of print information.  The info level defaults to 1.
212
213 Example:
214
215 >>> hnd.getprinter()
216 {'comment': 'i am a comment', 'printer_name': '\\\\NPSD-PDC2\\meanie', 
217  'description': '\\\\NPSD-PDC2\\meanie,Generic / Text Only,i am a location',
218  'flags': 8388608}
219 "},
220
221         { "setprinter", spoolss_setprinter, METH_VARARGS | METH_KEYWORDS,
222           "setprinter(dict) -> None
223
224 Set printer information.
225 "},
226
227         /* Printer drivers */
228
229         { "getprinterdriver", spoolss_getprinterdriver, 
230           METH_VARARGS | METH_KEYWORDS, 
231           "getprinterdriver([level = 1, arch = \"Windows NT x86\"] -> dict
232
233 Return a dictionary of printer driver information.
234 "},
235
236         /* Forms */
237
238         { "enumforms", spoolss_enumforms, METH_VARARGS | METH_KEYWORDS,
239           "enumforms([level = 1]) -> list
240
241 Return a list of forms supported by a printer.
242 "},
243
244         { "setform", spoolss_setform, METH_VARARGS | METH_KEYWORDS,
245           "setform(dict) -> None
246
247 Set the form given by the dictionary argument.
248 "},
249
250         { "addform", spoolss_addform, METH_VARARGS | METH_KEYWORDS,
251           "Insert a form" },
252
253         { "getform", spoolss_getform, METH_VARARGS | METH_KEYWORDS,
254           "Fetch form properties" },
255
256         { "deleteform", spoolss_deleteform, METH_VARARGS | METH_KEYWORDS,
257           "Delete a form" },
258
259         { NULL }
260
261 };
262
263 static void py_policy_hnd_dealloc(PyObject* self)
264 {
265         PyObject_Del(self);
266 }
267
268 static PyObject *py_policy_hnd_getattr(PyObject *self, char *attrname)
269 {
270         return Py_FindMethod(spoolss_hnd_methods, self, attrname);
271 }
272
273 static char spoolss_type_doc[] = 
274 "Python wrapper for Windows NT SPOOLSS rpc pipe.";
275
276 PyTypeObject spoolss_policy_hnd_type = {
277         PyObject_HEAD_INIT(NULL)
278         0,
279         "spoolss.hnd",
280         sizeof(spoolss_policy_hnd_object),
281         0,
282         py_policy_hnd_dealloc,  /* tp_dealloc*/
283         0,                      /* tp_print*/
284         py_policy_hnd_getattr,  /* tp_getattr*/
285         0,                      /* tp_setattr*/
286         0,                      /* tp_compare*/
287         0,                      /* tp_repr*/
288         0,                      /* tp_as_number*/
289         0,                      /* tp_as_sequence*/
290         0,                      /* tp_as_mapping*/
291         0,                      /* tp_hash */
292         0,                      /* tp_call */
293         0,                      /* tp_str */
294         0,                      /* tp_getattro */
295         0,                      /* tp_setattro */
296         0,                      /* tp_as_buffer*/
297         Py_TPFLAGS_DEFAULT,     /* tp_flags */
298         spoolss_type_doc,       /* tp_doc */
299 };
300
301 /* Initialise constants */
302
303 struct spoolss_const {
304         char *name;
305         uint32 value;
306 } spoolss_const_vals[] = {
307         
308         /* Access permissions */
309
310         { "MAXIMUM_ALLOWED_ACCESS", MAXIMUM_ALLOWED_ACCESS },
311         { "SERVER_ALL_ACCESS", SERVER_ALL_ACCESS },
312         { "SERVER_READ", SERVER_READ },
313         { "SERVER_WRITE", SERVER_WRITE },
314         { "SERVER_EXECUTE", SERVER_EXECUTE },
315         { "SERVER_ACCESS_ADMINISTER", SERVER_ACCESS_ADMINISTER },
316         { "SERVER_ACCESS_ENUMERATE", SERVER_ACCESS_ENUMERATE },
317         { "PRINTER_ALL_ACCESS", PRINTER_ALL_ACCESS },
318         { "PRINTER_READ", PRINTER_READ },
319         { "PRINTER_WRITE", PRINTER_WRITE },
320         { "PRINTER_EXECUTE", PRINTER_EXECUTE },
321         { "PRINTER_ACCESS_ADMINISTER", PRINTER_ACCESS_ADMINISTER },
322         { "PRINTER_ACCESS_USE", PRINTER_ACCESS_USE },
323         { "JOB_ACCESS_ADMINISTER", JOB_ACCESS_ADMINISTER },
324         { "JOB_ALL_ACCESS", JOB_ALL_ACCESS },
325         { "JOB_READ", JOB_READ },
326         { "JOB_WRITE", JOB_WRITE },
327         { "JOB_EXECUTE", JOB_EXECUTE },
328         { "STANDARD_RIGHTS_ALL_ACCESS", STANDARD_RIGHTS_ALL_ACCESS },
329         { "STANDARD_RIGHTS_EXECUTE_ACCESS", STANDARD_RIGHTS_EXECUTE_ACCESS },
330         { "STANDARD_RIGHTS_READ_ACCESS", STANDARD_RIGHTS_READ_ACCESS },
331         { "STANDARD_RIGHTS_REQUIRED_ACCESS", STANDARD_RIGHTS_REQUIRED_ACCESS },
332         { "STANDARD_RIGHTS_WRITE_ACCESS", STANDARD_RIGHTS_WRITE_ACCESS },
333
334         /* Printer enumeration flags */
335
336         { "PRINTER_ENUM_DEFAULT", PRINTER_ENUM_DEFAULT },
337         { "PRINTER_ENUM_LOCAL", PRINTER_ENUM_LOCAL },
338         { "PRINTER_ENUM_CONNECTIONS", PRINTER_ENUM_CONNECTIONS },
339         { "PRINTER_ENUM_FAVORITE", PRINTER_ENUM_FAVORITE },
340         { "PRINTER_ENUM_NAME", PRINTER_ENUM_NAME },
341         { "PRINTER_ENUM_REMOTE", PRINTER_ENUM_REMOTE },
342         { "PRINTER_ENUM_SHARED", PRINTER_ENUM_SHARED },
343         { "PRINTER_ENUM_NETWORK", PRINTER_ENUM_NETWORK },
344
345         /* Form types */
346
347         { "FORM_USER", FORM_USER },
348         { "FORM_BUILTIN", FORM_BUILTIN },
349         { "FORM_PRINTER", FORM_PRINTER },
350
351         /* WERRORs */
352
353         { "WERR_OK", 0 },
354         { "WERR_BADFILE", 2 },
355         { "WERR_ACCESS_DENIED", 5 },
356         { "WERR_BADFID", 6 },
357         { "WERR_BADFUNC", 1 },
358         { "WERR_INSUFFICIENT_BUFFER", 122 },
359         { "WERR_NO_SUCH_SHARE", 67 },
360         { "WERR_ALREADY_EXISTS", 80 },
361         { "WERR_INVALID_PARAM", 87 },
362         { "WERR_NOT_SUPPORTED", 50 },
363         { "WERR_BAD_PASSWORD", 86 },
364         { "WERR_NOMEM", 8 },
365         { "WERR_INVALID_NAME", 123 },
366         { "WERR_UNKNOWN_LEVEL", 124 },
367         { "WERR_OBJECT_PATH_INVALID", 161 },
368         { "WERR_NO_MORE_ITEMS", 259 },
369         { "WERR_MORE_DATA", 234 },
370         { "WERR_UNKNOWN_PRINTER_DRIVER", 1797 },
371         { "WERR_INVALID_PRINTER_NAME", 1801 },
372         { "WERR_PRINTER_ALREADY_EXISTS", 1802 },
373         { "WERR_INVALID_DATATYPE", 1804 },
374         { "WERR_INVALID_ENVIRONMENT", 1805 },
375         { "WERR_INVALID_FORM_NAME", 1902 },
376         { "WERR_INVALID_FORM_SIZE", 1903 },
377         { "WERR_BUF_TOO_SMALL", 2123 },
378         { "WERR_JOB_NOT_FOUND", 2151 },
379         { "WERR_DEST_NOT_FOUND", 2152 },
380         { "WERR_NOT_LOCAL_DOMAIN", 2320 },
381         { "WERR_PRINTER_DRIVER_IN_USE", 3001 },
382         { "WERR_STATUS_MORE_ENTRIES  ", 0x0105 },
383
384         { NULL },
385 };
386
387 static void const_init(PyObject *dict)
388 {
389         struct spoolss_const *tmp;
390         PyObject *obj;
391
392         for (tmp = spoolss_const_vals; tmp->name; tmp++) {
393                 obj = PyInt_FromLong(tmp->value);
394                 PyDict_SetItemString(dict, tmp->name, obj);
395                 Py_DECREF(obj);
396         }
397 }
398
399 /* Module initialisation */
400
401 void initspoolss(void)
402 {
403         PyObject *module, *dict;
404
405         /* Initialise module */
406
407         module = Py_InitModule("spoolss", spoolss_methods);
408         dict = PyModule_GetDict(module);
409
410         /* Make spools_error global an exception we can raise when an error
411            occurs. */
412
413         spoolss_error = PyErr_NewException("spoolss.error", NULL, NULL);
414         PyDict_SetItemString(dict, "error", spoolss_error);
415
416         spoolss_werror = PyErr_NewException("spoolss.werror", NULL, NULL);
417         PyDict_SetItemString(dict, "werror", spoolss_werror);
418
419         /* Initialise policy handle object */
420
421         spoolss_policy_hnd_type.ob_type = &PyType_Type;
422
423         PyDict_SetItemString(dict, "spoolss.hnd", 
424                              (PyObject *)&spoolss_policy_hnd_type);
425
426         /* Initialise constants */
427
428         const_init(dict);
429
430         /* Do samba initialisation */
431
432         py_samba_init();
433 }