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 25PyObject *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->pipe_list, 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 98PyObject *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 124PyObject *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 179PyObject *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 269PyObject *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->pipe_list, 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 402done: 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 414PyObject *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->pipe_list, mem_ctx, 2, &ctr); 452 453 Py_INCREF(Py_None); 454 result = Py_None; 455 456done: 457 if (cli) 458 cli_shutdown(cli); 459 460 if (mem_ctx) 461 talloc_destroy(mem_ctx); 462 463 return result; 464} 465