Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : * RPC Pipe client / server routines
4 : * Copyright (C) Andrew Tridgell 1992-2000,
5 : * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 : * Copyright (C) Jean François Micouleau 1998-2000,
7 : * Copyright (C) Jeremy Allison 2001-2002,
8 : * Copyright (C) Gerald Carter 2000-2004,
9 : * Copyright (C) Tim Potter 2001-2002.
10 : * Copyright (C) Guenther Deschner 2009-2010.
11 : * Copyright (C) Andreas Schneider 2010.
12 : *
13 : * This program is free software; you can redistribute it and/or modify
14 : * it under the terms of the GNU General Public License as published by
15 : * the Free Software Foundation; either version 3 of the License, or
16 : * (at your option) any later version.
17 : *
18 : * This program is distributed in the hope that it will be useful,
19 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 : * GNU General Public License for more details.
22 : *
23 : * You should have received a copy of the GNU General Public License
24 : * along with this program; if not, see <http://www.gnu.org/licenses/>.
25 : */
26 :
27 : /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28 : up, all the errors returned are DOS errors, not NT status codes. */
29 :
30 : #include "includes.h"
31 : #include "libsmb/namequery.h"
32 : #include "ntdomain.h"
33 : #include "nt_printing.h"
34 : #include "srv_spoolss_util.h"
35 : #include "librpc/gen_ndr/ndr_spoolss.h"
36 : #include "librpc/gen_ndr/ndr_spoolss_scompat.h"
37 : #include "../librpc/gen_ndr/ndr_spoolss_c.h"
38 : #include "rpc_client/init_spoolss.h"
39 : #include "rpc_client/cli_pipe.h"
40 : #include "../libcli/security/security.h"
41 : #include "librpc/gen_ndr/ndr_security.h"
42 : #include "registry.h"
43 : #include "include/printing.h"
44 : #include "secrets.h"
45 : #include "../librpc/gen_ndr/netlogon.h"
46 : #include "rpc_misc.h"
47 : #include "printing/notify.h"
48 : #include "serverid.h"
49 : #include "../libcli/registry/util_reg.h"
50 : #include "smbd/smbd.h"
51 : #include "smbd/globals.h"
52 : #include "auth.h"
53 : #include "messages.h"
54 : #include "rpc_server/spoolss/srv_spoolss_nt.h"
55 : #include "util_tdb.h"
56 : #include "libsmb/libsmb.h"
57 : #include "printing/printer_list.h"
58 : #include "../lib/tsocket/tsocket.h"
59 : #include "rpc_client/cli_winreg_spoolss.h"
60 : #include "../libcli/smb/smbXcli_base.h"
61 : #include "rpc_server/spoolss/srv_spoolss_handle.h"
62 : #include "lib/gencache.h"
63 : #include "rpc_server/rpc_server.h"
64 : #include "librpc/rpc/dcesrv_core.h"
65 : #include "printing/nt_printing_migrate_internal.h"
66 : #include "lib/util/string_wrappers.h"
67 : #include "lib/global_contexts.h"
68 :
69 : /* macros stolen from s4 spoolss server */
70 : #define SPOOLSS_BUFFER_UNION(fn,info,level) \
71 : ((info)?ndr_size_##fn(info, level, 0):0)
72 :
73 : #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
74 : ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
75 :
76 : #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
77 : ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
78 :
79 : #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
80 :
81 : #undef DBGC_CLASS
82 : #define DBGC_CLASS DBGC_RPC_SRV
83 :
84 : #ifndef MAX_OPEN_PRINTER_EXS
85 : #define MAX_OPEN_PRINTER_EXS 50
86 : #endif
87 :
88 : #define GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT 5
89 : #define GLOBAL_SPOOLSS_OS_MINOR_DEFAULT 2
90 : #define GLOBAL_SPOOLSS_OS_BUILD_DEFAULT 3790
91 : #define GLOBAL_SPOOLSS_ARCHITECTURE SPOOLSS_ARCHITECTURE_x64
92 :
93 : static struct printer_handle *printers_list;
94 :
95 : struct printer_session_counter {
96 : struct printer_session_counter *next;
97 : struct printer_session_counter *prev;
98 :
99 : int snum;
100 : uint32_t counter;
101 : };
102 :
103 : static struct printer_session_counter *counter_list;
104 :
105 : struct notify_back_channel {
106 : struct notify_back_channel *prev, *next;
107 :
108 : /* associated client */
109 : struct sockaddr_storage client_address;
110 :
111 : /* print notify back-channel pipe handle*/
112 : struct rpc_pipe_client *cli_pipe;
113 : struct cli_state *cli;
114 : uint32_t active_connections;
115 : };
116 :
117 : static struct notify_back_channel *back_channels;
118 :
119 : /* Map generic permissions to printer object specific permissions */
120 :
121 : const struct standard_mapping printer_std_mapping = {
122 : PRINTER_READ,
123 : PRINTER_WRITE,
124 : PRINTER_EXECUTE,
125 : PRINTER_ALL_ACCESS
126 : };
127 :
128 : /* Map generic permissions to print server object specific permissions */
129 :
130 : const struct standard_mapping printserver_std_mapping = {
131 : SERVER_READ,
132 : SERVER_WRITE,
133 : SERVER_EXECUTE,
134 : SERVER_ALL_ACCESS
135 : };
136 :
137 : /* API table for Xcv Monitor functions */
138 :
139 : struct xcv_api_table {
140 : const char *name;
141 : WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
142 : };
143 :
144 : static void prune_printername_cache(void);
145 :
146 : /********************************************************************
147 : * Canonicalize servername.
148 : ********************************************************************/
149 :
150 426 : static const char *canon_servername(const char *servername)
151 : {
152 426 : const char *pservername = servername;
153 :
154 426 : if (servername == NULL) {
155 0 : return "";
156 : }
157 :
158 1583 : while (*pservername == '\\') {
159 860 : pservername++;
160 : }
161 426 : return pservername;
162 : }
163 :
164 : /* translate between internal status numbers and NT status numbers */
165 384 : static int nt_printj_status(int v)
166 : {
167 384 : switch (v) {
168 384 : case LPQ_QUEUED:
169 384 : return 0;
170 0 : case LPQ_PAUSED:
171 0 : return JOB_STATUS_PAUSED;
172 0 : case LPQ_SPOOLING:
173 0 : return JOB_STATUS_SPOOLING;
174 0 : case LPQ_PRINTING:
175 0 : return JOB_STATUS_PRINTING;
176 0 : case LPQ_ERROR:
177 0 : return JOB_STATUS_ERROR;
178 0 : case LPQ_DELETING:
179 0 : return JOB_STATUS_DELETING;
180 0 : case LPQ_OFFLINE:
181 0 : return JOB_STATUS_OFFLINE;
182 0 : case LPQ_PAPEROUT:
183 0 : return JOB_STATUS_PAPEROUT;
184 0 : case LPQ_PRINTED:
185 0 : return JOB_STATUS_PRINTED;
186 0 : case LPQ_DELETED:
187 0 : return JOB_STATUS_DELETED;
188 0 : case LPQ_BLOCKED:
189 0 : return JOB_STATUS_BLOCKED_DEVQ;
190 0 : case LPQ_USER_INTERVENTION:
191 0 : return JOB_STATUS_USER_INTERVENTION;
192 : }
193 0 : return 0;
194 : }
195 :
196 1604 : static int nt_printq_status(int v)
197 : {
198 1604 : switch (v) {
199 216 : case LPQ_PAUSED:
200 216 : return PRINTER_STATUS_PAUSED;
201 1388 : case LPQ_QUEUED:
202 : case LPQ_SPOOLING:
203 : case LPQ_PRINTING:
204 1388 : return 0;
205 : }
206 0 : return 0;
207 : }
208 :
209 : /***************************************************************************
210 : Disconnect from the client
211 : ****************************************************************************/
212 :
213 2 : static void srv_spoolss_replycloseprinter(int snum,
214 : struct printer_handle *prn_hnd)
215 : {
216 : WERROR result;
217 : NTSTATUS status;
218 :
219 : /*
220 : * Tell the specific printing tdb we no longer want messages for this printer
221 : * by deregistering our PID.
222 : */
223 :
224 2 : if (!print_notify_deregister_pid(snum)) {
225 0 : DEBUG(0, ("Failed to register our pid for printer %s\n",
226 : lp_const_servicename(snum)));
227 : }
228 :
229 : /* weird if the test succeeds !!! */
230 3 : if (prn_hnd->notify.cli_chan == NULL ||
231 3 : prn_hnd->notify.cli_chan->cli_pipe == NULL ||
232 3 : prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
233 2 : prn_hnd->notify.cli_chan->active_connections == 0) {
234 0 : DEBUG(0, ("Trying to close unexisting backchannel!\n"));
235 0 : DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
236 0 : TALLOC_FREE(prn_hnd->notify.cli_chan);
237 0 : return;
238 : }
239 :
240 3 : status = dcerpc_spoolss_ReplyClosePrinter(
241 2 : prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
242 : talloc_tos(),
243 : &prn_hnd->notify.cli_hnd,
244 : &result);
245 2 : if (!NT_STATUS_IS_OK(status)) {
246 0 : DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
247 : nt_errstr(status)));
248 0 : result = ntstatus_to_werror(status);
249 2 : } else if (!W_ERROR_IS_OK(result)) {
250 0 : DEBUG(0, ("reply_close_printer failed [%s].\n",
251 : win_errstr(result)));
252 : }
253 :
254 : /* if it's the last connection, deconnect the IPC$ share */
255 2 : if (prn_hnd->notify.cli_chan->active_connections == 1) {
256 :
257 2 : cli_shutdown(prn_hnd->notify.cli_chan->cli);
258 2 : DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
259 2 : TALLOC_FREE(prn_hnd->notify.cli_chan);
260 :
261 2 : if (prn_hnd->notify.msg_ctx != NULL) {
262 2 : messaging_deregister(prn_hnd->notify.msg_ctx,
263 : MSG_PRINTER_NOTIFY2, NULL);
264 : }
265 : }
266 :
267 2 : if (prn_hnd->notify.cli_chan) {
268 0 : prn_hnd->notify.cli_chan->active_connections--;
269 0 : prn_hnd->notify.cli_chan = NULL;
270 : }
271 : }
272 :
273 : /****************************************************************************
274 : Functions to free a printer entry datastruct.
275 : ****************************************************************************/
276 :
277 922 : static int printer_entry_destructor(struct printer_handle *Printer)
278 : {
279 923 : if (Printer->notify.cli_chan != NULL &&
280 2 : Printer->notify.cli_chan->active_connections > 0) {
281 2 : int snum = -1;
282 :
283 2 : switch(Printer->printer_type) {
284 2 : case SPLHND_SERVER:
285 2 : srv_spoolss_replycloseprinter(snum, Printer);
286 2 : break;
287 :
288 0 : case SPLHND_PRINTER:
289 0 : snum = print_queue_snum(Printer->sharename);
290 0 : if (snum != -1) {
291 0 : srv_spoolss_replycloseprinter(snum, Printer);
292 : }
293 0 : break;
294 0 : default:
295 0 : break;
296 : }
297 675 : }
298 :
299 922 : Printer->notify.flags=0;
300 922 : Printer->notify.options=0;
301 922 : Printer->notify.localmachine[0]='\0';
302 922 : Printer->notify.printerlocal=0;
303 922 : TALLOC_FREE(Printer->notify.option);
304 922 : TALLOC_FREE(Printer->devmode);
305 :
306 : /* Remove from the internal list. */
307 922 : DLIST_REMOVE(printers_list, Printer);
308 922 : return 0;
309 : }
310 :
311 : /****************************************************************************
312 : find printer index by handle
313 : ****************************************************************************/
314 :
315 51922 : static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
316 : struct policy_handle *hnd)
317 : {
318 51922 : struct printer_handle *find_printer = NULL;
319 : NTSTATUS status;
320 :
321 51922 : find_printer = find_policy_by_hnd(p,
322 : hnd,
323 : DCESRV_HANDLE_ANY,
324 : struct printer_handle,
325 : &status);
326 51922 : if (!NT_STATUS_IS_OK(status)) {
327 0 : DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
328 0 : return NULL;
329 : }
330 :
331 51922 : return find_printer;
332 : }
333 :
334 : /****************************************************************************
335 : Close printer index by handle.
336 : ****************************************************************************/
337 :
338 914 : static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
339 : {
340 914 : struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
341 :
342 914 : if (!Printer) {
343 0 : DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
344 : OUR_HANDLE(hnd)));
345 0 : return false;
346 : }
347 :
348 914 : close_policy_hnd(p, hnd);
349 :
350 914 : return true;
351 : }
352 :
353 : /****************************************************************************
354 : Delete a printer given a handle.
355 : ****************************************************************************/
356 :
357 16 : static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
358 : const char *sharename,
359 : struct messaging_context *msg_ctx)
360 : {
361 12 : const struct loadparm_substitution *lp_sub =
362 4 : loadparm_s3_global_substitution();
363 16 : char *cmd = lp_deleteprinter_command(talloc_tos(), lp_sub);
364 16 : char *command = NULL;
365 : int ret;
366 16 : bool is_print_op = false;
367 :
368 : /* can't fail if we don't try */
369 :
370 16 : if ( !*cmd )
371 0 : return WERR_OK;
372 :
373 16 : command = talloc_asprintf(ctx,
374 : "%s \"%s\"",
375 : cmd, sharename);
376 16 : if (!command) {
377 0 : return WERR_NOT_ENOUGH_MEMORY;
378 : }
379 16 : if ( token )
380 16 : is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
381 :
382 16 : DEBUG(10,("Running [%s]\n", command));
383 :
384 : /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
385 :
386 16 : if ( is_print_op )
387 0 : become_root();
388 :
389 16 : ret = smbrun(command, NULL, NULL);
390 12 : if (ret == 0) {
391 : /* Tell everyone we updated smb.conf. */
392 12 : messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
393 : }
394 :
395 12 : if ( is_print_op )
396 0 : unbecome_root();
397 :
398 : /********** END SePrintOperatorPrivlege BLOCK **********/
399 :
400 12 : DEBUGADD(10,("returned [%d]\n", ret));
401 :
402 12 : TALLOC_FREE(command);
403 :
404 12 : if (ret != 0)
405 0 : return WERR_INVALID_HANDLE; /* What to return here? */
406 :
407 12 : return WERR_OK;
408 : }
409 :
410 : /****************************************************************************
411 : Delete a printer given a handle.
412 : ****************************************************************************/
413 :
414 16 : static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
415 : {
416 16 : struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
417 : WERROR result;
418 :
419 16 : if (!Printer) {
420 0 : DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
421 : OUR_HANDLE(hnd)));
422 0 : return WERR_INVALID_HANDLE;
423 : }
424 :
425 : /*
426 : * It turns out that Windows allows delete printer on a handle
427 : * opened by an admin user, then used on a pipe handle created
428 : * by an anonymous user..... but they're working on security.... riiight !
429 : * JRA.
430 : */
431 :
432 16 : if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
433 0 : DEBUG(3, ("delete_printer_handle: denied by handle\n"));
434 0 : return WERR_ACCESS_DENIED;
435 : }
436 :
437 : /* this does not need a become root since the access check has been
438 : done on the handle already */
439 :
440 16 : result = winreg_delete_printer_key_internal(p->mem_ctx,
441 : get_session_info_system(),
442 : p->msg_ctx,
443 16 : Printer->sharename,
444 : "");
445 16 : if (!W_ERROR_IS_OK(result)) {
446 0 : DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
447 0 : return WERR_INVALID_HANDLE;
448 : }
449 :
450 28 : result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
451 16 : Printer->sharename, p->msg_ctx);
452 12 : if (!W_ERROR_IS_OK(result)) {
453 0 : return result;
454 : }
455 12 : prune_printername_cache();
456 12 : return WERR_OK;
457 : }
458 :
459 : /****************************************************************************
460 : Return the snum of a printer corresponding to an handle.
461 : ****************************************************************************/
462 :
463 24670 : static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
464 : int *number, struct share_params **params)
465 : {
466 24670 : struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
467 :
468 24670 : if (!Printer) {
469 0 : DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
470 : OUR_HANDLE(hnd)));
471 0 : return false;
472 : }
473 :
474 24670 : switch (Printer->printer_type) {
475 24670 : case SPLHND_PRINTER:
476 24670 : DEBUG(4,("short name:%s\n", Printer->sharename));
477 24670 : *number = print_queue_snum(Printer->sharename);
478 24670 : return (*number != -1);
479 0 : case SPLHND_SERVER:
480 0 : return false;
481 0 : default:
482 0 : return false;
483 : }
484 : }
485 :
486 : /****************************************************************************
487 : Set printer handle type.
488 : Check if it's \\server or \\server\printer
489 : ****************************************************************************/
490 :
491 934 : static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
492 : {
493 934 : DEBUG(3,("Setting printer type=%s\n", handlename));
494 :
495 : /* it's a print server */
496 934 : if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
497 92 : DEBUGADD(4,("Printer is a print server\n"));
498 92 : Printer->printer_type = SPLHND_SERVER;
499 : }
500 : /* it's a printer (set_printer_hnd_name() will handle port monitors */
501 : else {
502 842 : DEBUGADD(4,("Printer is a printer\n"));
503 842 : Printer->printer_type = SPLHND_PRINTER;
504 : }
505 :
506 934 : return true;
507 : }
508 :
509 366 : static void prune_printername_cache_fn(const char *key, const char *value,
510 : time_t timeout, void *private_data)
511 : {
512 366 : gencache_del(key);
513 366 : }
514 :
515 128 : static void prune_printername_cache(void)
516 : {
517 128 : gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
518 128 : }
519 :
520 : /****************************************************************************
521 : Set printer handle name.. Accept names like \\server, \\server\printer,
522 : \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
523 : the MSDN docs regarding OpenPrinter() for details on the XcvData() and
524 : XcvDataPort() interface.
525 : ****************************************************************************/
526 :
527 934 : static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
528 : const struct auth_session_info *session_info,
529 : struct messaging_context *msg_ctx,
530 : struct printer_handle *Printer,
531 : const char *handlename)
532 : {
533 : int snum;
534 934 : int n_services=lp_numservices();
535 : char *aprinter;
536 : const char *printername;
537 934 : const char *servername = NULL;
538 : fstring sname;
539 934 : bool found = false;
540 934 : struct spoolss_PrinterInfo2 *info2 = NULL;
541 : WERROR result;
542 : char *p;
543 :
544 : /*
545 : * Hopefully nobody names his printers like this. Maybe \ or ,
546 : * are illegal in printer names even?
547 : */
548 934 : const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
549 : char *cache_key;
550 : char *tmp;
551 :
552 934 : DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
553 : (unsigned long)strlen(handlename)));
554 :
555 934 : aprinter = discard_const_p(char, handlename);
556 934 : if ( *handlename == '\\' ) {
557 214 : servername = canon_servername(handlename);
558 214 : if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
559 114 : *aprinter = '\0';
560 114 : aprinter++;
561 : }
562 214 : if (!is_myname_or_ipaddr(servername)) {
563 12 : return WERR_INVALID_PRINTER_NAME;
564 : }
565 202 : Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
566 202 : if (Printer->servername == NULL) {
567 0 : return WERR_NOT_ENOUGH_MEMORY;
568 : }
569 : }
570 :
571 922 : if (Printer->printer_type == SPLHND_SERVER) {
572 88 : return WERR_OK;
573 : }
574 :
575 834 : if (Printer->printer_type != SPLHND_PRINTER) {
576 0 : return WERR_INVALID_HANDLE;
577 : }
578 :
579 834 : DEBUGADD(5, ("searching for [%s]\n", aprinter));
580 :
581 834 : p = strchr(aprinter, ',');
582 834 : if (p != NULL) {
583 504 : char *p2 = p;
584 504 : p++;
585 504 : if (*p == ' ') {
586 308 : p++;
587 : }
588 504 : if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
589 140 : *p2 = '\0';
590 364 : } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
591 140 : *p2 = '\0';
592 : }
593 : }
594 :
595 834 : if (p) {
596 504 : DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
597 : }
598 :
599 : /* check for the Port Monitor Interface */
600 834 : if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
601 0 : Printer->printer_type = SPLHND_PORTMON_TCP;
602 0 : fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
603 0 : found = true;
604 : }
605 834 : else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
606 0 : Printer->printer_type = SPLHND_PORTMON_LOCAL;
607 0 : fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
608 0 : found = true;
609 : }
610 :
611 834 : cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s", aprinter);
612 834 : if (cache_key == NULL) {
613 0 : return WERR_NOT_ENOUGH_MEMORY;
614 : }
615 :
616 : /*
617 : * With hundreds of printers, the "for" loop iterating all
618 : * shares can be quite expensive, as it is done on every
619 : * OpenPrinter. The loop maps "aprinter" to "sname", the
620 : * result of which we cache in gencache.
621 : */
622 834 : if (gencache_get(cache_key, talloc_tos(), &tmp, NULL)) {
623 458 : found = (strcmp(tmp, printer_not_found) != 0);
624 458 : if (!found) {
625 32 : DEBUG(4, ("Printer %s not found\n", aprinter));
626 32 : TALLOC_FREE(tmp);
627 32 : return WERR_INVALID_PRINTER_NAME;
628 : }
629 426 : fstrcpy(sname, tmp);
630 426 : TALLOC_FREE(tmp);
631 : }
632 :
633 : /* Search all sharenames first as this is easier than pulling
634 : the printer_info_2 off of disk. Don't use find_service() since
635 : that calls out to map_username() */
636 :
637 : /* do another loop to look for printernames */
638 20488 : for (snum = 0; !found && snum < n_services; snum++) {
639 19774 : const char *printer = lp_const_servicename(snum);
640 :
641 : /* no point going on if this is not a printer */
642 19774 : if (!(lp_snum_ok(snum) && lp_printable(snum))) {
643 17906 : continue;
644 : }
645 :
646 : /* ignore [printers] share */
647 1868 : if (strequal(printer, "printers")) {
648 0 : continue;
649 : }
650 :
651 1868 : fstrcpy(sname, printer);
652 1868 : if (strequal(aprinter, printer)) {
653 80 : found = true;
654 80 : break;
655 : }
656 :
657 : /* no point looking up the printer object if
658 : we aren't allowing printername != sharename */
659 1788 : if (lp_force_printername(snum)) {
660 0 : continue;
661 : }
662 :
663 1788 : result = winreg_get_printer_internal(mem_ctx,
664 : session_info,
665 : msg_ctx,
666 : sname,
667 : &info2);
668 1788 : if ( !W_ERROR_IS_OK(result) ) {
669 48 : DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
670 : sname, win_errstr(result)));
671 48 : continue;
672 : }
673 :
674 1740 : printername = strrchr(info2->printername, '\\');
675 1740 : if (printername == NULL) {
676 1740 : printername = info2->printername;
677 : } else {
678 0 : printername++;
679 : }
680 :
681 1740 : if (strequal(printername, aprinter)) {
682 8 : found = true;
683 8 : break;
684 : }
685 :
686 1732 : DEBUGADD(10, ("printername: %s\n", printername));
687 :
688 1732 : TALLOC_FREE(info2);
689 : }
690 :
691 802 : if (!found) {
692 288 : gencache_set(cache_key, printer_not_found,
693 288 : time(NULL) + 300);
694 288 : TALLOC_FREE(cache_key);
695 288 : DEBUGADD(4,("Printer not found\n"));
696 288 : return WERR_INVALID_PRINTER_NAME;
697 : }
698 :
699 514 : gencache_set(cache_key, sname, time(NULL) + 300);
700 514 : TALLOC_FREE(cache_key);
701 :
702 514 : DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
703 :
704 514 : strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
705 :
706 514 : return WERR_OK;
707 : }
708 :
709 : /****************************************************************************
710 : Find first available printer slot. creates a printer handle for you.
711 : ****************************************************************************/
712 :
713 934 : static WERROR open_printer_hnd(struct pipes_struct *p,
714 : struct policy_handle *hnd,
715 : const char *name,
716 : uint32_t access_granted)
717 : {
718 : struct printer_handle *new_printer;
719 : WERROR result;
720 :
721 934 : DEBUG(10,("open_printer_hnd: name [%s]\n", name));
722 :
723 934 : new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
724 934 : if (new_printer == NULL) {
725 0 : return WERR_NOT_ENOUGH_MEMORY;
726 : }
727 934 : talloc_set_destructor(new_printer, printer_entry_destructor);
728 :
729 : /* This also steals the printer_handle on the policy_handle */
730 934 : if (!create_policy_hnd(p, hnd, 0, new_printer)) {
731 0 : TALLOC_FREE(new_printer);
732 0 : return WERR_INVALID_HANDLE;
733 : }
734 :
735 : /* Add to the internal list. */
736 934 : DLIST_ADD(printers_list, new_printer);
737 :
738 934 : new_printer->notify.option=NULL;
739 :
740 934 : if (!set_printer_hnd_printertype(new_printer, name)) {
741 0 : close_printer_handle(p, hnd);
742 0 : return WERR_INVALID_HANDLE;
743 : }
744 :
745 934 : result = set_printer_hnd_name(p->mem_ctx,
746 : get_session_info_system(),
747 : p->msg_ctx,
748 : new_printer, name);
749 934 : if (!W_ERROR_IS_OK(result)) {
750 332 : close_printer_handle(p, hnd);
751 332 : return result;
752 : }
753 :
754 602 : new_printer->access_granted = access_granted;
755 :
756 602 : DBG_INFO("%d printer handles active\n", (int)num_pipe_handles());
757 :
758 602 : return WERR_OK;
759 : }
760 :
761 : /***************************************************************************
762 : check to see if the client motify handle is monitoring the notification
763 : given by (notify_type, notify_field).
764 : **************************************************************************/
765 :
766 0 : static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
767 : uint16_t notify_field)
768 : {
769 0 : return true;
770 : }
771 :
772 0 : static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
773 : uint16_t notify_field)
774 : {
775 0 : struct spoolss_NotifyOption *option = p->notify.option;
776 : uint32_t i, j;
777 :
778 : /*
779 : * Flags should always be zero when the change notify
780 : * is registered by the client's spooler. A user Win32 app
781 : * might use the flags though instead of the NOTIFY_OPTION_INFO
782 : * --jerry
783 : */
784 :
785 0 : if (!option) {
786 0 : return false;
787 : }
788 :
789 0 : if (p->notify.flags)
790 0 : return is_monitoring_event_flags(
791 : p->notify.flags, notify_type, notify_field);
792 :
793 0 : for (i = 0; i < option->count; i++) {
794 :
795 : /* Check match for notify_type */
796 :
797 0 : if (option->types[i].type != notify_type)
798 0 : continue;
799 :
800 : /* Check match for field */
801 :
802 0 : for (j = 0; j < option->types[i].count; j++) {
803 0 : if (option->types[i].fields[j].field == notify_field) {
804 0 : return true;
805 : }
806 : }
807 : }
808 :
809 0 : DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
810 : p->servername, p->sharename, notify_type, notify_field));
811 :
812 0 : return false;
813 : }
814 :
815 : #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
816 : _data->data.integer[0] = _integer; \
817 : _data->data.integer[1] = 0;
818 :
819 :
820 : #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
821 : _data->data.string.string = talloc_strdup(mem_ctx, _p); \
822 : if (!_data->data.string.string) {\
823 : _data->data.string.size = 0; \
824 : } \
825 : _data->data.string.size = strlen_m_term(_p) * 2;
826 :
827 : #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
828 : _data->data.devmode.devmode = _devmode;
829 :
830 0 : static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
831 : struct tm *t,
832 : const char **pp,
833 : uint32_t *plen)
834 : {
835 : struct spoolss_Time st;
836 0 : uint32_t len = 16;
837 : char *p;
838 :
839 0 : if (!init_systemtime(&st, t)) {
840 0 : return;
841 : }
842 :
843 0 : p = talloc_array(mem_ctx, char, len);
844 0 : if (!p) {
845 0 : return;
846 : }
847 :
848 : /*
849 : * Systemtime must be linearized as a set of UINT16's.
850 : * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
851 : */
852 :
853 0 : SSVAL(p, 0, st.year);
854 0 : SSVAL(p, 2, st.month);
855 0 : SSVAL(p, 4, st.day_of_week);
856 0 : SSVAL(p, 6, st.day);
857 0 : SSVAL(p, 8, st.hour);
858 0 : SSVAL(p, 10, st.minute);
859 0 : SSVAL(p, 12, st.second);
860 0 : SSVAL(p, 14, st.millisecond);
861 :
862 0 : *pp = p;
863 0 : *plen = len;
864 : }
865 :
866 : /* Convert a notification message to a struct spoolss_Notify */
867 :
868 0 : static void notify_one_value(struct spoolss_notify_msg *msg,
869 : struct spoolss_Notify *data,
870 : TALLOC_CTX *mem_ctx)
871 : {
872 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
873 0 : }
874 :
875 0 : static void notify_string(struct spoolss_notify_msg *msg,
876 : struct spoolss_Notify *data,
877 : TALLOC_CTX *mem_ctx)
878 : {
879 : /* The length of the message includes the trailing \0 */
880 :
881 0 : data->data.string.size = msg->len * 2;
882 0 : data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
883 0 : if (!data->data.string.string) {
884 0 : data->data.string.size = 0;
885 0 : return;
886 : }
887 : }
888 :
889 0 : static void notify_system_time(struct spoolss_notify_msg *msg,
890 : struct spoolss_Notify *data,
891 : TALLOC_CTX *mem_ctx)
892 : {
893 0 : data->data.string.string = NULL;
894 0 : data->data.string.size = 0;
895 :
896 0 : if (msg->len != sizeof(time_t)) {
897 0 : DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
898 : msg->len));
899 0 : return;
900 : }
901 :
902 0 : init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
903 : &data->data.string.string,
904 : &data->data.string.size);
905 : }
906 :
907 : struct notify2_message_table {
908 : const char *name;
909 : void (*fn)(struct spoolss_notify_msg *msg,
910 : struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
911 : };
912 :
913 : static struct notify2_message_table printer_notify_table[] = {
914 : /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
915 : /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
916 : /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
917 : /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
918 : /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
919 : /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
920 : /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
921 : /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
922 : /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
923 : /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
924 : /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
925 : /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
926 : /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
927 : /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
928 : /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
929 : /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
930 : /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
931 : /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
932 : /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
933 : };
934 :
935 : static struct notify2_message_table job_notify_table[] = {
936 : /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
937 : /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
938 : /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
939 : /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
940 : /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
941 : /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
942 : /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
943 : /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
944 : /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
945 : /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
946 : /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
947 : /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
948 : /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
949 : /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
950 : /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
951 : /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
952 : /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
953 : /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
954 : /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
955 : /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
956 : /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
957 : /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
958 : /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
959 : /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
960 : };
961 :
962 :
963 : /***********************************************************************
964 : Allocate talloc context for container object
965 : **********************************************************************/
966 :
967 0 : static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
968 : {
969 0 : if ( !ctr )
970 0 : return;
971 :
972 0 : ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
973 :
974 0 : return;
975 : }
976 :
977 : /***********************************************************************
978 : release all allocated memory and zero out structure
979 : **********************************************************************/
980 :
981 0 : static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
982 : {
983 0 : if ( !ctr )
984 0 : return;
985 :
986 0 : if ( ctr->ctx )
987 0 : talloc_destroy(ctr->ctx);
988 :
989 0 : ZERO_STRUCTP(ctr);
990 :
991 0 : return;
992 : }
993 :
994 : /***********************************************************************
995 : **********************************************************************/
996 :
997 0 : static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
998 : {
999 0 : if ( !ctr )
1000 0 : return NULL;
1001 :
1002 0 : return ctr->ctx;
1003 : }
1004 :
1005 : /***********************************************************************
1006 : **********************************************************************/
1007 :
1008 0 : static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1009 : {
1010 0 : if ( !ctr || !ctr->msg_groups )
1011 0 : return NULL;
1012 :
1013 0 : if ( idx >= ctr->num_groups )
1014 0 : return NULL;
1015 :
1016 0 : return &ctr->msg_groups[idx];
1017 :
1018 : }
1019 :
1020 : /***********************************************************************
1021 : How many groups of change messages do we have ?
1022 : **********************************************************************/
1023 :
1024 0 : static uint32_t notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1025 : {
1026 0 : if ( !ctr )
1027 0 : return 0;
1028 :
1029 0 : return ctr->num_groups;
1030 : }
1031 :
1032 : /***********************************************************************
1033 : Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1034 : **********************************************************************/
1035 :
1036 0 : static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1037 : {
1038 0 : SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
1039 0 : SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
1040 0 : SPOOLSS_NOTIFY_MSG *msg_list = NULL;
1041 : uint32_t i, new_slot;
1042 :
1043 0 : if ( !ctr || !msg )
1044 0 : return 0;
1045 :
1046 : /* loop over all groups looking for a matching printer name */
1047 :
1048 0 : for ( i=0; i<ctr->num_groups; i++ ) {
1049 0 : if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1050 0 : break;
1051 : }
1052 :
1053 : /* add a new group? */
1054 :
1055 0 : if ( i == ctr->num_groups ) {
1056 0 : ctr->num_groups++;
1057 :
1058 0 : if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1059 0 : DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1060 0 : return 0;
1061 : }
1062 0 : ctr->msg_groups = groups;
1063 :
1064 : /* clear the new entry and set the printer name */
1065 :
1066 0 : ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1067 0 : fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1068 : }
1069 :
1070 : /* add the change messages; 'i' is the correct index now regardless */
1071 :
1072 0 : msg_grp = &ctr->msg_groups[i];
1073 :
1074 0 : msg_grp->num_msgs++;
1075 :
1076 0 : if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1077 0 : DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1078 0 : return 0;
1079 : }
1080 0 : msg_grp->msgs = msg_list;
1081 :
1082 0 : new_slot = msg_grp->num_msgs-1;
1083 0 : memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1084 :
1085 : /* need to allocate own copy of data */
1086 :
1087 0 : if ( msg->len != 0 )
1088 0 : msg_grp->msgs[new_slot].notify.data = (char *)
1089 0 : talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1090 :
1091 0 : return ctr->num_groups;
1092 : }
1093 :
1094 : static void construct_info_data(struct spoolss_Notify *info_data,
1095 : enum spoolss_NotifyType type,
1096 : uint16_t field, int id);
1097 :
1098 : /***********************************************************************
1099 : Send a change notifation message on all handles which have a call
1100 : back registered
1101 : **********************************************************************/
1102 :
1103 0 : static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1104 : struct printer_handle *prn_hnd,
1105 : SPOOLSS_NOTIFY_MSG *messages,
1106 : uint32_t num_msgs,
1107 : struct spoolss_Notify **_notifies,
1108 : size_t *_count)
1109 : {
1110 : struct spoolss_Notify *notifies;
1111 : SPOOLSS_NOTIFY_MSG *msg;
1112 0 : size_t count = 0;
1113 : uint32_t id;
1114 : uint32_t i;
1115 :
1116 0 : notifies = talloc_zero_array(mem_ctx,
1117 : struct spoolss_Notify, num_msgs);
1118 0 : if (!notifies) {
1119 0 : return ENOMEM;
1120 : }
1121 :
1122 0 : for (i = 0; i < num_msgs; i++) {
1123 :
1124 0 : msg = &messages[i];
1125 :
1126 : /* Are we monitoring this event? */
1127 :
1128 0 : if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1129 0 : continue;
1130 : }
1131 :
1132 0 : DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1133 : "for printer [%s]\n",
1134 : msg->type, msg->field, prn_hnd->sharename));
1135 :
1136 : /*
1137 : * if the is a printer notification handle and not a job
1138 : * notification type, then set the id to 0.
1139 : * Otherwise just use what was specified in the message.
1140 : *
1141 : * When registering change notification on a print server
1142 : * handle we always need to send back the id (snum) matching
1143 : * the printer for which the change took place.
1144 : * For change notify registered on a printer handle,
1145 : * this does not matter and the id should be 0.
1146 : *
1147 : * --jerry
1148 : */
1149 :
1150 0 : if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1151 0 : (prn_hnd->printer_type == SPLHND_PRINTER)) {
1152 0 : id = 0;
1153 : } else {
1154 0 : id = msg->id;
1155 : }
1156 :
1157 : /* Convert unix jobid to smb jobid */
1158 :
1159 0 : if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1160 0 : id = sysjob_to_jobid(msg->id);
1161 :
1162 0 : if (id == -1) {
1163 0 : DEBUG(3, ("no such unix jobid %d\n",
1164 : msg->id));
1165 0 : continue;
1166 : }
1167 : }
1168 :
1169 0 : construct_info_data(¬ifies[count],
1170 0 : msg->type, msg->field, id);
1171 :
1172 0 : switch(msg->type) {
1173 0 : case PRINTER_NOTIFY_TYPE:
1174 0 : if (printer_notify_table[msg->field].fn) {
1175 0 : printer_notify_table[msg->field].fn(msg,
1176 0 : ¬ifies[count], mem_ctx);
1177 : }
1178 0 : break;
1179 :
1180 0 : case JOB_NOTIFY_TYPE:
1181 0 : if (job_notify_table[msg->field].fn) {
1182 0 : job_notify_table[msg->field].fn(msg,
1183 0 : ¬ifies[count], mem_ctx);
1184 : }
1185 0 : break;
1186 :
1187 0 : default:
1188 0 : DEBUG(5, ("Unknown notification type %d\n",
1189 : msg->type));
1190 0 : continue;
1191 : }
1192 :
1193 0 : count++;
1194 : }
1195 :
1196 0 : *_notifies = notifies;
1197 0 : *_count = count;
1198 :
1199 0 : return 0;
1200 : }
1201 :
1202 0 : static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1203 : struct printer_handle *prn_hnd,
1204 : SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1205 : {
1206 : struct spoolss_Notify *notifies;
1207 0 : size_t count = 0;
1208 : union spoolss_ReplyPrinterInfo info;
1209 : struct spoolss_NotifyInfo info0;
1210 : uint32_t reply_result;
1211 : NTSTATUS status;
1212 : WERROR werr;
1213 : int ret;
1214 :
1215 : /* Is there notification on this handle? */
1216 0 : if (prn_hnd->notify.cli_chan == NULL ||
1217 0 : prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1218 0 : prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1219 0 : prn_hnd->notify.cli_chan->active_connections == 0) {
1220 0 : return 0;
1221 : }
1222 :
1223 0 : DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1224 : prn_hnd->servername, prn_hnd->sharename));
1225 :
1226 : /* For this printer? Print servers always receive notifications. */
1227 0 : if ((prn_hnd->printer_type == SPLHND_PRINTER) &&
1228 0 : (!strequal(msg_group->printername, prn_hnd->sharename))) {
1229 0 : return 0;
1230 : }
1231 :
1232 0 : DEBUG(10,("Our printer\n"));
1233 :
1234 : /* build the array of change notifications */
1235 0 : ret = build_notify2_messages(mem_ctx, prn_hnd,
1236 : msg_group->msgs,
1237 : msg_group->num_msgs,
1238 : ¬ifies, &count);
1239 0 : if (ret) {
1240 0 : return ret;
1241 : }
1242 :
1243 0 : info0.version = 0x2;
1244 0 : info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1245 0 : info0.count = count;
1246 0 : info0.notifies = notifies;
1247 :
1248 0 : info.info0 = &info0;
1249 :
1250 0 : status = dcerpc_spoolss_RouterReplyPrinterEx(
1251 0 : prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1252 : mem_ctx,
1253 : &prn_hnd->notify.cli_hnd,
1254 : prn_hnd->notify.change, /* color */
1255 : prn_hnd->notify.flags,
1256 : &reply_result,
1257 : 0, /* reply_type, must be 0 */
1258 : info, &werr);
1259 0 : if (!NT_STATUS_IS_OK(status)) {
1260 0 : DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1261 : "failed: %s\n",
1262 : prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1263 : nt_errstr(status)));
1264 0 : werr = ntstatus_to_werror(status);
1265 0 : } else if (!W_ERROR_IS_OK(werr)) {
1266 0 : DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1267 : "failed: %s\n",
1268 : prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1269 : win_errstr(werr)));
1270 : }
1271 0 : switch (reply_result) {
1272 0 : case 0:
1273 0 : break;
1274 0 : case PRINTER_NOTIFY_INFO_DISCARDED:
1275 : case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1276 : case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1277 0 : break;
1278 0 : default:
1279 0 : break;
1280 : }
1281 :
1282 0 : return 0;
1283 : }
1284 :
1285 0 : static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1286 : {
1287 : struct printer_handle *p;
1288 0 : TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1289 0 : SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1290 : int ret;
1291 :
1292 0 : if ( !msg_group ) {
1293 0 : DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1294 0 : return;
1295 : }
1296 :
1297 0 : if (!msg_group->msgs) {
1298 0 : DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1299 0 : return;
1300 : }
1301 :
1302 0 : DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1303 :
1304 : /* loop over all printers */
1305 :
1306 0 : for (p = printers_list; p; p = p->next) {
1307 0 : ret = send_notify2_printer(mem_ctx, p, msg_group);
1308 0 : if (ret) {
1309 0 : goto done;
1310 : }
1311 : }
1312 :
1313 0 : done:
1314 0 : DEBUG(8,("send_notify2_changes: Exit...\n"));
1315 0 : return;
1316 : }
1317 :
1318 : /***********************************************************************
1319 : **********************************************************************/
1320 :
1321 0 : static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1322 : {
1323 :
1324 : uint32_t tv_sec, tv_usec;
1325 0 : size_t offset = 0;
1326 :
1327 : /* Unpack message */
1328 :
1329 0 : offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1330 0 : msg->printer);
1331 :
1332 0 : offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1333 : &tv_sec, &tv_usec,
1334 : &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1335 :
1336 0 : if (msg->len == 0)
1337 0 : tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1338 : &msg->notify.value[0], &msg->notify.value[1]);
1339 : else
1340 0 : tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1341 : &msg->len, &msg->notify.data);
1342 :
1343 0 : DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1344 : msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1345 :
1346 0 : tv->tv_sec = tv_sec;
1347 0 : tv->tv_usec = tv_usec;
1348 :
1349 0 : if (msg->len == 0)
1350 0 : DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1351 : msg->notify.value[1]));
1352 : else
1353 0 : dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1354 :
1355 0 : return true;
1356 : }
1357 :
1358 : /********************************************************************
1359 : Receive a notify2 message list
1360 : ********************************************************************/
1361 :
1362 0 : static void receive_notify2_message_list(struct messaging_context *msg,
1363 : void *private_data,
1364 : uint32_t msg_type,
1365 : struct server_id server_id,
1366 : DATA_BLOB *data)
1367 : {
1368 : size_t msg_count, i, num_groups;
1369 0 : char *buf = (char *)data->data;
1370 : char *msg_ptr;
1371 : size_t msg_len;
1372 : SPOOLSS_NOTIFY_MSG notify;
1373 : SPOOLSS_NOTIFY_MSG_CTR messages;
1374 :
1375 0 : if (data->length < 4) {
1376 0 : DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1377 0 : return;
1378 : }
1379 :
1380 0 : msg_count = IVAL(buf, 0);
1381 0 : msg_ptr = buf + 4;
1382 :
1383 0 : DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1384 :
1385 0 : if (msg_count == 0) {
1386 0 : DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1387 0 : return;
1388 : }
1389 :
1390 : /* initialize the container */
1391 :
1392 0 : ZERO_STRUCT( messages );
1393 0 : notify_msg_ctr_init( &messages );
1394 :
1395 : /*
1396 : * build message groups for each printer identified
1397 : * in a change_notify msg. Remember that a PCN message
1398 : * includes the handle returned for the srv_spoolss_replyopenprinter()
1399 : * call. Therefore messages are grouped according to printer handle.
1400 : */
1401 :
1402 0 : for ( i=0; i<msg_count; i++ ) {
1403 : struct timeval msg_tv;
1404 :
1405 0 : if (msg_ptr + 4 - buf > data->length) {
1406 0 : DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1407 0 : return;
1408 : }
1409 :
1410 0 : msg_len = IVAL(msg_ptr,0);
1411 0 : msg_ptr += 4;
1412 :
1413 0 : if (msg_ptr + msg_len - buf > data->length) {
1414 0 : DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1415 0 : return;
1416 : }
1417 :
1418 : /* unpack messages */
1419 :
1420 0 : ZERO_STRUCT( notify );
1421 0 : notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1422 0 : msg_ptr += msg_len;
1423 :
1424 : /* add to correct list in container */
1425 :
1426 0 : notify_msg_ctr_addmsg( &messages, ¬ify );
1427 :
1428 : /* free memory that might have been allocated by notify2_unpack_msg() */
1429 :
1430 0 : if ( notify.len != 0 )
1431 0 : SAFE_FREE( notify.notify.data );
1432 : }
1433 :
1434 : /* process each group of messages */
1435 :
1436 0 : num_groups = notify_msg_ctr_numgroups( &messages );
1437 0 : for ( i=0; i<num_groups; i++ )
1438 0 : send_notify2_changes( &messages, i );
1439 :
1440 :
1441 : /* cleanup */
1442 :
1443 0 : DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1444 : (uint32_t)msg_count ));
1445 :
1446 0 : notify_msg_ctr_destroy( &messages );
1447 :
1448 0 : return;
1449 : }
1450 :
1451 : /********************************************************************
1452 : Send a message to ourself about new driver being installed
1453 : so we can upgrade the information for each printer bound to this
1454 : driver
1455 : ********************************************************************/
1456 :
1457 0 : static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1458 : struct messaging_context *msg_ctx)
1459 : {
1460 0 : int len = strlen(drivername);
1461 :
1462 0 : if (!len)
1463 0 : return false;
1464 :
1465 0 : DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1466 : drivername));
1467 :
1468 0 : messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1469 : MSG_PRINTER_DRVUPGRADE,
1470 0 : (const uint8_t *)drivername, len+1);
1471 :
1472 0 : return true;
1473 : }
1474 :
1475 1 : void srv_spoolss_cleanup(void)
1476 : {
1477 : struct printer_session_counter *session_counter;
1478 :
1479 2 : for (session_counter = counter_list;
1480 0 : session_counter != NULL;
1481 0 : session_counter = counter_list) {
1482 0 : DLIST_REMOVE(counter_list, session_counter);
1483 0 : TALLOC_FREE(session_counter);
1484 : }
1485 1 : }
1486 :
1487 : /**********************************************************************
1488 : callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1489 : over all printers, upgrading ones as necessary
1490 : This is now *ONLY* called inside the background lpq updater. JRA.
1491 : **********************************************************************/
1492 :
1493 0 : void do_drv_upgrade_printer(struct messaging_context *msg,
1494 : void *private_data,
1495 : uint32_t msg_type,
1496 : struct server_id server_id,
1497 : DATA_BLOB *data)
1498 : {
1499 : TALLOC_CTX *tmp_ctx;
1500 0 : const struct auth_session_info *session_info = get_session_info_system();
1501 : struct spoolss_PrinterInfo2 *pinfo2;
1502 : WERROR result;
1503 : const char *drivername;
1504 : int snum;
1505 0 : int n_services = lp_numservices();
1506 0 : struct dcerpc_binding_handle *b = NULL;
1507 :
1508 0 : tmp_ctx = talloc_new(NULL);
1509 0 : if (!tmp_ctx) return;
1510 :
1511 0 : drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1512 0 : if (!drivername) {
1513 0 : DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1514 0 : goto done;
1515 : }
1516 :
1517 0 : DEBUG(10, ("do_drv_upgrade_printer: "
1518 : "Got message for new driver [%s]\n", drivername));
1519 :
1520 : /* Iterate the printer list */
1521 :
1522 0 : for (snum = 0; snum < n_services; snum++) {
1523 0 : if (!lp_snum_ok(snum) || !lp_printable(snum)) {
1524 0 : continue;
1525 : }
1526 :
1527 : /* ignore [printers] share */
1528 0 : if (strequal(lp_const_servicename(snum), "printers")) {
1529 0 : continue;
1530 : }
1531 :
1532 0 : if (b == NULL) {
1533 0 : result = winreg_printer_binding_handle(tmp_ctx,
1534 : session_info,
1535 : msg,
1536 : &b);
1537 0 : if (!W_ERROR_IS_OK(result)) {
1538 0 : break;
1539 : }
1540 : }
1541 :
1542 0 : result = winreg_get_printer(tmp_ctx, b,
1543 : lp_const_servicename(snum),
1544 : &pinfo2);
1545 :
1546 0 : if (!W_ERROR_IS_OK(result)) {
1547 0 : continue;
1548 : }
1549 :
1550 0 : if (!pinfo2->drivername) {
1551 0 : continue;
1552 : }
1553 :
1554 0 : if (strcmp(drivername, pinfo2->drivername) != 0) {
1555 0 : continue;
1556 : }
1557 :
1558 0 : DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1559 :
1560 : /* all we care about currently is the change_id */
1561 0 : result = winreg_printer_update_changeid(tmp_ctx, b,
1562 0 : pinfo2->printername);
1563 :
1564 0 : if (!W_ERROR_IS_OK(result)) {
1565 0 : DEBUG(3, ("do_drv_upgrade_printer: "
1566 : "Failed to update changeid [%s]\n",
1567 : win_errstr(result)));
1568 : }
1569 : }
1570 :
1571 : /* all done */
1572 0 : done:
1573 0 : talloc_free(tmp_ctx);
1574 : }
1575 :
1576 : /********************************************************************
1577 : Update the cache for all printq's with a registered client
1578 : connection
1579 : ********************************************************************/
1580 :
1581 1054 : void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1582 : {
1583 1054 : struct printer_handle *printer = printers_list;
1584 : int snum;
1585 :
1586 : /* loop through all printers and update the cache where
1587 : a client is connected */
1588 1793 : while (printer) {
1589 9 : if ((printer->printer_type == SPLHND_PRINTER) &&
1590 4 : ((printer->notify.cli_chan != NULL) &&
1591 0 : (printer->notify.cli_chan->active_connections > 0))) {
1592 0 : snum = print_queue_snum(printer->sharename);
1593 0 : print_queue_status(msg_ctx, snum, NULL, NULL);
1594 : }
1595 :
1596 5 : printer = printer->next;
1597 : }
1598 :
1599 1054 : return;
1600 : }
1601 :
1602 : /****************************************************************
1603 : _spoolss_OpenPrinter
1604 : ****************************************************************/
1605 :
1606 166 : WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1607 : struct spoolss_OpenPrinter *r)
1608 : {
1609 : struct spoolss_OpenPrinterEx e;
1610 : struct spoolss_UserLevel1 level1;
1611 : WERROR werr;
1612 :
1613 166 : ZERO_STRUCT(level1);
1614 :
1615 166 : e.in.printername = r->in.printername;
1616 166 : e.in.datatype = r->in.datatype;
1617 166 : e.in.devmode_ctr = r->in.devmode_ctr;
1618 166 : e.in.access_mask = r->in.access_mask;
1619 166 : e.in.userlevel_ctr.level = 1;
1620 166 : e.in.userlevel_ctr.user_info.level1 = &level1;
1621 :
1622 166 : e.out.handle = r->out.handle;
1623 :
1624 166 : werr = _spoolss_OpenPrinterEx(p, &e);
1625 :
1626 166 : if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAMETER)) {
1627 : /* OpenPrinterEx returns this for a bad
1628 : * printer name. We must return WERR_INVALID_PRINTER_NAME
1629 : * instead.
1630 : */
1631 4 : werr = WERR_INVALID_PRINTER_NAME;
1632 : }
1633 :
1634 166 : return werr;
1635 : }
1636 :
1637 2830 : static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1638 : struct spoolss_DeviceMode *orig,
1639 : struct spoolss_DeviceMode **dest)
1640 : {
1641 : struct spoolss_DeviceMode *dm;
1642 :
1643 2830 : dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1644 2830 : if (!dm) {
1645 0 : return WERR_NOT_ENOUGH_MEMORY;
1646 : }
1647 :
1648 : /* copy all values, then duplicate strings and structs */
1649 2830 : *dm = *orig;
1650 :
1651 2830 : dm->devicename = talloc_strdup(dm, orig->devicename);
1652 2830 : if (!dm->devicename) {
1653 0 : return WERR_NOT_ENOUGH_MEMORY;
1654 : }
1655 2830 : dm->formname = talloc_strdup(dm, orig->formname);
1656 2830 : if (!dm->formname) {
1657 0 : return WERR_NOT_ENOUGH_MEMORY;
1658 : }
1659 2830 : if (orig->driverextra_data.data) {
1660 1768 : dm->driverextra_data.data =
1661 1768 : (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1662 : orig->driverextra_data.length);
1663 1768 : if (!dm->driverextra_data.data) {
1664 0 : return WERR_NOT_ENOUGH_MEMORY;
1665 : }
1666 : }
1667 :
1668 2830 : *dest = dm;
1669 2830 : return WERR_OK;
1670 : }
1671 :
1672 : /****************************************************************
1673 : _spoolss_OpenPrinterEx
1674 : ****************************************************************/
1675 :
1676 950 : WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1677 : struct spoolss_OpenPrinterEx *r)
1678 : {
1679 : int snum;
1680 : char *raddr;
1681 : char *rhost;
1682 950 : struct printer_handle *Printer=NULL;
1683 : WERROR result;
1684 : int rc;
1685 :
1686 950 : if (!r->in.printername) {
1687 0 : return WERR_INVALID_PARAMETER;
1688 : }
1689 :
1690 950 : if (!*r->in.printername) {
1691 8 : return WERR_INVALID_PARAMETER;
1692 : }
1693 :
1694 942 : if (r->in.userlevel_ctr.level > 3) {
1695 0 : return WERR_INVALID_PARAMETER;
1696 : }
1697 1618 : if ((r->in.userlevel_ctr.level == 1 && !r->in.userlevel_ctr.user_info.level1) ||
1698 1594 : (r->in.userlevel_ctr.level == 2 && !r->in.userlevel_ctr.user_info.level2) ||
1699 918 : (r->in.userlevel_ctr.level == 3 && !r->in.userlevel_ctr.user_info.level3)) {
1700 24 : return WERR_INVALID_PARAMETER;
1701 : }
1702 :
1703 : /*
1704 : * The printcap printer share inventory is updated on client
1705 : * enumeration. For clients that do not perform enumeration prior to
1706 : * access, such as cupssmbadd, we reinitialise the printer share
1707 : * inventory on open as well.
1708 : */
1709 918 : become_root();
1710 918 : delete_and_reload_printers();
1711 918 : unbecome_root();
1712 :
1713 : /* some sanity check because you can open a printer or a print server */
1714 : /* aka: \\server\printer or \\server */
1715 :
1716 918 : DEBUGADD(3,("checking name: %s\n", r->in.printername));
1717 :
1718 918 : result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1719 918 : if (!W_ERROR_IS_OK(result)) {
1720 332 : DEBUG(3,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1721 : "for printer %s\n", r->in.printername));
1722 332 : ZERO_STRUCTP(r->out.handle);
1723 332 : return result;
1724 : }
1725 :
1726 586 : Printer = find_printer_index_by_hnd(p, r->out.handle);
1727 586 : if ( !Printer ) {
1728 0 : DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1729 : "handle we created for printer %s\n", r->in.printername));
1730 0 : close_printer_handle(p, r->out.handle);
1731 0 : ZERO_STRUCTP(r->out.handle);
1732 0 : return WERR_INVALID_PARAMETER;
1733 : }
1734 :
1735 : /*
1736 : * First case: the user is opening the print server:
1737 : *
1738 : * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1739 : * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1740 : *
1741 : * Then both Win2k and WinNT clients try an OpenPrinterEx with
1742 : * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1743 : * or if the user is listed in the smb.conf printer admin parameter.
1744 : *
1745 : * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1746 : * client view printer folder, but does not show the MSAPW.
1747 : *
1748 : * Note: this test needs code to check access rights here too. Jeremy
1749 : * could you look at this?
1750 : *
1751 : * Second case: the user is opening a printer:
1752 : * NT doesn't let us connect to a printer if the connecting user
1753 : * doesn't have print permission.
1754 : *
1755 : * Third case: user is opening a Port Monitor
1756 : * access checks same as opening a handle to the print server.
1757 : */
1758 :
1759 586 : switch (Printer->printer_type )
1760 : {
1761 88 : case SPLHND_SERVER:
1762 : case SPLHND_PORTMON_TCP:
1763 : case SPLHND_PORTMON_LOCAL:
1764 : /* Printserver handles use global struct... */
1765 :
1766 88 : snum = -1;
1767 :
1768 88 : if (r->in.access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
1769 62 : r->in.access_mask |= SERVER_ACCESS_ADMINISTER;
1770 62 : r->in.access_mask |= SERVER_ACCESS_ENUMERATE;
1771 : }
1772 :
1773 : /* Map standard access rights to object specific access rights */
1774 :
1775 88 : se_map_standard(&r->in.access_mask,
1776 : &printserver_std_mapping);
1777 :
1778 : /* Deny any object specific bits that don't apply to print
1779 : servers (i.e printer and job specific bits) */
1780 :
1781 88 : r->in.access_mask &= SEC_MASK_SPECIFIC;
1782 :
1783 88 : if (r->in.access_mask &
1784 : ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1785 0 : DEBUG(3, ("access DENIED for non-printserver bits\n"));
1786 0 : close_printer_handle(p, r->out.handle);
1787 0 : ZERO_STRUCTP(r->out.handle);
1788 0 : return WERR_ACCESS_DENIED;
1789 : }
1790 :
1791 : /* Allow admin access */
1792 :
1793 88 : if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1794 : {
1795 66 : if (!lp_show_add_printer_wizard()) {
1796 0 : close_printer_handle(p, r->out.handle);
1797 0 : ZERO_STRUCTP(r->out.handle);
1798 0 : return WERR_ACCESS_DENIED;
1799 : }
1800 :
1801 : /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1802 : and not a printer admin, then fail */
1803 :
1804 67 : if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1805 2 : !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1806 0 : !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
1807 0 : p->session_info->security_token)) {
1808 0 : close_printer_handle(p, r->out.handle);
1809 0 : ZERO_STRUCTP(r->out.handle);
1810 0 : DEBUG(3,("access DENIED as user is not root, "
1811 : "has no printoperator privilege and is "
1812 : "not a member of the printoperator builtin group\n"));
1813 0 : return WERR_ACCESS_DENIED;
1814 : }
1815 :
1816 66 : r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1817 : }
1818 : else
1819 : {
1820 22 : r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1821 : }
1822 :
1823 88 : DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1824 : ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1825 :
1826 88 : break;
1827 :
1828 498 : case SPLHND_PRINTER:
1829 : /* NT doesn't let us connect to a printer if the connecting user
1830 : doesn't have print permission. */
1831 :
1832 498 : if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1833 0 : close_printer_handle(p, r->out.handle);
1834 0 : ZERO_STRUCTP(r->out.handle);
1835 0 : return WERR_INVALID_HANDLE;
1836 : }
1837 :
1838 498 : if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1839 164 : r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1840 : }
1841 :
1842 498 : se_map_standard(&r->in.access_mask, &printer_std_mapping);
1843 :
1844 : /* map an empty access mask to the minimum access mask */
1845 498 : if (r->in.access_mask == 0x0)
1846 294 : r->in.access_mask = PRINTER_ACCESS_USE;
1847 :
1848 : /*
1849 : * If we are not serving the printer driver for this printer,
1850 : * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1851 : * will keep NT clients happy --jerry
1852 : */
1853 :
1854 498 : if (lp_use_client_driver(snum)
1855 0 : && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1856 : {
1857 0 : r->in.access_mask = PRINTER_ACCESS_USE;
1858 : }
1859 :
1860 : /* check smb.conf parameters and the the sec_desc */
1861 498 : raddr = tsocket_address_inet_addr_string(p->remote_address,
1862 : p->mem_ctx);
1863 498 : if (raddr == NULL) {
1864 0 : return WERR_NOT_ENOUGH_MEMORY;
1865 : }
1866 :
1867 498 : rc = get_remote_hostname(p->remote_address,
1868 : &rhost,
1869 : p->mem_ctx);
1870 498 : if (rc < 0) {
1871 0 : return WERR_NOT_ENOUGH_MEMORY;
1872 : }
1873 498 : if (strequal(rhost, "UNKNOWN")) {
1874 0 : rhost = raddr;
1875 : }
1876 :
1877 498 : if (!allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
1878 : rhost, raddr)) {
1879 0 : DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1880 0 : ZERO_STRUCTP(r->out.handle);
1881 0 : return WERR_ACCESS_DENIED;
1882 : }
1883 :
1884 867 : if (!user_ok_token(p->session_info->unix_info->unix_name,
1885 498 : p->session_info->info->domain_name,
1886 867 : p->session_info->security_token, snum) ||
1887 498 : !W_ERROR_IS_OK(print_access_check(p->session_info,
1888 : p->msg_ctx,
1889 : snum,
1890 : r->in.access_mask))) {
1891 0 : DEBUG(3, ("access DENIED for printer open\n"));
1892 0 : close_printer_handle(p, r->out.handle);
1893 0 : ZERO_STRUCTP(r->out.handle);
1894 0 : return WERR_ACCESS_DENIED;
1895 : }
1896 :
1897 498 : if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1898 4 : DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1899 4 : close_printer_handle(p, r->out.handle);
1900 4 : ZERO_STRUCTP(r->out.handle);
1901 4 : return WERR_ACCESS_DENIED;
1902 : }
1903 :
1904 494 : if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1905 164 : r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1906 : else
1907 330 : r->in.access_mask = PRINTER_ACCESS_USE;
1908 :
1909 494 : DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1910 : ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1911 :
1912 494 : winreg_create_printer_internal(p->mem_ctx,
1913 : get_session_info_system(),
1914 : p->msg_ctx,
1915 : lp_const_servicename(snum));
1916 :
1917 494 : break;
1918 :
1919 0 : default:
1920 : /* sanity check to prevent programmer error */
1921 0 : ZERO_STRUCTP(r->out.handle);
1922 0 : return WERR_INVALID_HANDLE;
1923 : }
1924 :
1925 582 : Printer->access_granted = r->in.access_mask;
1926 :
1927 : /*
1928 : * If the client sent a devmode in the OpenPrinter() call, then
1929 : * save it here in case we get a job submission on this handle
1930 : */
1931 :
1932 582 : if ((Printer->printer_type != SPLHND_SERVER)
1933 494 : && (r->in.devmode_ctr.devmode != NULL)) {
1934 8 : copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1935 : &Printer->devmode);
1936 : }
1937 :
1938 582 : return WERR_OK;
1939 : }
1940 :
1941 : /****************************************************************
1942 : _spoolss_ClosePrinter
1943 : ****************************************************************/
1944 :
1945 582 : WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1946 : struct spoolss_ClosePrinter *r)
1947 : {
1948 582 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1949 :
1950 582 : if (Printer && Printer->document_started) {
1951 : struct spoolss_EndDocPrinter e;
1952 :
1953 28 : e.in.handle = r->in.handle;
1954 :
1955 28 : _spoolss_EndDocPrinter(p, &e);
1956 : }
1957 :
1958 578 : if (!close_printer_handle(p, r->in.handle))
1959 0 : return WERR_INVALID_HANDLE;
1960 :
1961 : /* clear the returned printer handle. Observed behavior
1962 : from Win2k server. Don't think this really matters.
1963 : Previous code just copied the value of the closed
1964 : handle. --jerry */
1965 :
1966 578 : ZERO_STRUCTP(r->out.handle);
1967 :
1968 578 : return WERR_OK;
1969 : }
1970 :
1971 : /****************************************************************
1972 : _spoolss_DeletePrinter
1973 : ****************************************************************/
1974 :
1975 16 : WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1976 : struct spoolss_DeletePrinter *r)
1977 : {
1978 16 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1979 : WERROR result;
1980 : int snum;
1981 :
1982 16 : if (Printer && Printer->document_started) {
1983 : struct spoolss_EndDocPrinter e;
1984 :
1985 0 : e.in.handle = r->in.handle;
1986 :
1987 0 : _spoolss_EndDocPrinter(p, &e);
1988 : }
1989 :
1990 16 : if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
1991 16 : winreg_delete_printer_key_internal(p->mem_ctx,
1992 : get_session_info_system(),
1993 : p->msg_ctx,
1994 : lp_const_servicename(snum),
1995 : "");
1996 : }
1997 :
1998 16 : result = delete_printer_handle(p, r->in.handle);
1999 :
2000 12 : return result;
2001 : }
2002 :
2003 : /*******************************************************************
2004 : * static function to lookup the version id corresponding to an
2005 : * long architecture string
2006 : ******************************************************************/
2007 :
2008 : static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2009 : SPOOLSS_DRIVER_VERSION_NT35,
2010 : SPOOLSS_DRIVER_VERSION_NT4,
2011 : SPOOLSS_DRIVER_VERSION_200X,
2012 : -1};
2013 :
2014 0 : static int get_version_id(const char *arch)
2015 : {
2016 : int i;
2017 :
2018 0 : for (i=0; archi_table[i].long_archi != NULL; i++)
2019 : {
2020 0 : if (strcmp(arch, archi_table[i].long_archi) == 0)
2021 0 : return (archi_table[i].version);
2022 : }
2023 :
2024 0 : return -1;
2025 : }
2026 :
2027 : /****************************************************************
2028 : _spoolss_DeletePrinterDriver
2029 : ****************************************************************/
2030 :
2031 0 : WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2032 : struct spoolss_DeletePrinterDriver *r)
2033 : {
2034 :
2035 0 : struct spoolss_DriverInfo8 *info = NULL;
2036 : int version;
2037 : WERROR status;
2038 : struct dcerpc_binding_handle *b;
2039 0 : TALLOC_CTX *tmp_ctx = NULL;
2040 : int i;
2041 : bool found;
2042 :
2043 : /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2044 : and not a printer admin, then fail */
2045 :
2046 0 : if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2047 0 : !security_token_has_privilege(p->session_info->security_token,
2048 : SEC_PRIV_PRINT_OPERATOR)) {
2049 0 : return WERR_ACCESS_DENIED;
2050 : }
2051 :
2052 0 : if (r->in.architecture == NULL || r->in.driver == NULL) {
2053 0 : return WERR_INVALID_ENVIRONMENT;
2054 : }
2055 :
2056 : /* check that we have a valid driver name first */
2057 :
2058 0 : if ((version = get_version_id(r->in.architecture)) == -1) {
2059 0 : return WERR_INVALID_ENVIRONMENT;
2060 : }
2061 :
2062 0 : tmp_ctx = talloc_new(p->mem_ctx);
2063 0 : if (!tmp_ctx) {
2064 0 : return WERR_NOT_ENOUGH_MEMORY;
2065 : }
2066 :
2067 0 : status = winreg_printer_binding_handle(tmp_ctx,
2068 : get_session_info_system(),
2069 : p->msg_ctx,
2070 : &b);
2071 0 : if (!W_ERROR_IS_OK(status)) {
2072 0 : goto done;
2073 : }
2074 :
2075 0 : for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2076 0 : status = winreg_get_driver(tmp_ctx, b,
2077 : r->in.architecture, r->in.driver,
2078 0 : drv_cversion[i], &info);
2079 0 : if (!W_ERROR_IS_OK(status)) {
2080 0 : DEBUG(5, ("skipping del of driver with version %d\n",
2081 : drv_cversion[i]));
2082 0 : continue;
2083 : }
2084 0 : found = true;
2085 :
2086 0 : if (printer_driver_in_use(tmp_ctx, b, info)) {
2087 0 : status = WERR_PRINTER_DRIVER_IN_USE;
2088 0 : goto done;
2089 : }
2090 :
2091 0 : status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2092 0 : if (!W_ERROR_IS_OK(status)) {
2093 0 : DEBUG(0, ("failed del of driver with version %d\n",
2094 : drv_cversion[i]));
2095 0 : goto done;
2096 : }
2097 : }
2098 0 : if (found == false) {
2099 0 : DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2100 0 : status = WERR_UNKNOWN_PRINTER_DRIVER;
2101 : } else {
2102 0 : status = WERR_OK;
2103 : }
2104 :
2105 0 : done:
2106 0 : talloc_free(tmp_ctx);
2107 :
2108 0 : return status;
2109 : }
2110 :
2111 0 : static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2112 : struct pipes_struct *p,
2113 : struct spoolss_DeletePrinterDriverEx *r,
2114 : struct dcerpc_binding_handle *b,
2115 : struct spoolss_DriverInfo8 *info)
2116 : {
2117 : WERROR status;
2118 : bool delete_files;
2119 :
2120 0 : if (printer_driver_in_use(mem_ctx, b, info)) {
2121 0 : status = WERR_PRINTER_DRIVER_IN_USE;
2122 0 : goto done;
2123 : }
2124 :
2125 : /*
2126 : * we have a couple of cases to consider.
2127 : * (1) Are any files in use? If so and DPD_DELETE_ALL_FILES is set,
2128 : * then the delete should fail if **any** files overlap with
2129 : * other drivers
2130 : * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2131 : * non-overlapping files
2132 : * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2133 : * are set, then do not delete any files
2134 : * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2135 : */
2136 :
2137 0 : delete_files = r->in.delete_flags
2138 0 : & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2139 :
2140 :
2141 0 : if (delete_files) {
2142 0 : bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2143 0 : if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2144 0 : status = WERR_PRINTER_DRIVER_IN_USE;
2145 0 : goto done;
2146 : }
2147 : /*
2148 : * printer_driver_files_in_use() has trimmed overlapping files
2149 : * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2150 : */
2151 : }
2152 :
2153 :
2154 0 : status = winreg_del_driver(mem_ctx, b, info, info->version);
2155 0 : if (!W_ERROR_IS_OK(status)) {
2156 0 : goto done;
2157 : }
2158 :
2159 : /*
2160 : * now delete any associated files if delete_files is
2161 : * true. Even if this part failes, we return succes
2162 : * because the driver doesn not exist any more
2163 : */
2164 0 : if (delete_files) {
2165 0 : delete_driver_files(p->session_info, info);
2166 : }
2167 :
2168 0 : done:
2169 0 : return status;
2170 : }
2171 :
2172 : /****************************************************************
2173 : _spoolss_DeletePrinterDriverEx
2174 : ****************************************************************/
2175 :
2176 0 : WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2177 : struct spoolss_DeletePrinterDriverEx *r)
2178 : {
2179 0 : struct spoolss_DriverInfo8 *info = NULL;
2180 : WERROR status;
2181 : struct dcerpc_binding_handle *b;
2182 0 : TALLOC_CTX *tmp_ctx = NULL;
2183 : int i;
2184 : bool found;
2185 :
2186 : /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2187 : and not a printer admin, then fail */
2188 :
2189 0 : if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2190 0 : !security_token_has_privilege(p->session_info->security_token,
2191 : SEC_PRIV_PRINT_OPERATOR)) {
2192 0 : return WERR_ACCESS_DENIED;
2193 : }
2194 :
2195 0 : if (r->in.architecture == NULL || r->in.driver == NULL) {
2196 0 : return WERR_INVALID_ENVIRONMENT;
2197 : }
2198 :
2199 : /* check that we have a valid driver name first */
2200 0 : if (get_version_id(r->in.architecture) == -1) {
2201 : /* this is what NT returns */
2202 0 : return WERR_INVALID_ENVIRONMENT;
2203 : }
2204 :
2205 0 : tmp_ctx = talloc_new(p->mem_ctx);
2206 0 : if (!tmp_ctx) {
2207 0 : return WERR_NOT_ENOUGH_MEMORY;
2208 : }
2209 :
2210 0 : status = winreg_printer_binding_handle(tmp_ctx,
2211 : get_session_info_system(),
2212 : p->msg_ctx,
2213 : &b);
2214 0 : if (!W_ERROR_IS_OK(status)) {
2215 0 : goto done;
2216 : }
2217 :
2218 0 : for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2219 0 : if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2220 0 : && (drv_cversion[i] != r->in.version)) {
2221 0 : continue;
2222 : }
2223 :
2224 : /* check if a driver with this version exists before delete */
2225 0 : status = winreg_get_driver(tmp_ctx, b,
2226 : r->in.architecture, r->in.driver,
2227 0 : drv_cversion[i], &info);
2228 0 : if (!W_ERROR_IS_OK(status)) {
2229 0 : DEBUG(5, ("skipping del of driver with version %d\n",
2230 : drv_cversion[i]));
2231 0 : continue;
2232 : }
2233 0 : found = true;
2234 :
2235 0 : status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2236 0 : if (!W_ERROR_IS_OK(status)) {
2237 0 : DEBUG(0, ("failed to delete driver with version %d\n",
2238 : drv_cversion[i]));
2239 0 : goto done;
2240 : }
2241 : }
2242 0 : if (found == false) {
2243 0 : DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2244 0 : status = WERR_UNKNOWN_PRINTER_DRIVER;
2245 : } else {
2246 0 : status = WERR_OK;
2247 : }
2248 :
2249 0 : done:
2250 0 : talloc_free(tmp_ctx);
2251 0 : return status;
2252 : }
2253 :
2254 :
2255 : /********************************************************************
2256 : GetPrinterData on a printer server Handle.
2257 : ********************************************************************/
2258 :
2259 348 : static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2260 : const char *value,
2261 : enum winreg_Type *type,
2262 : union spoolss_PrinterData *data)
2263 : {
2264 348 : DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2265 :
2266 348 : if (!strcasecmp_m(value, "W3SvcInstalled")) {
2267 28 : *type = REG_DWORD;
2268 28 : SIVAL(&data->value, 0, 0x00);
2269 28 : return WERR_OK;
2270 : }
2271 :
2272 320 : if (!strcasecmp_m(value, "BeepEnabled")) {
2273 24 : *type = REG_DWORD;
2274 24 : SIVAL(&data->value, 0, 0x00);
2275 24 : return WERR_OK;
2276 : }
2277 :
2278 296 : if (!strcasecmp_m(value, "EventLog")) {
2279 24 : *type = REG_DWORD;
2280 : /* formally was 0x1b */
2281 24 : SIVAL(&data->value, 0, 0x00);
2282 24 : return WERR_OK;
2283 : }
2284 :
2285 272 : if (!strcasecmp_m(value, "NetPopup")) {
2286 0 : *type = REG_DWORD;
2287 0 : SIVAL(&data->value, 0, 0x00);
2288 0 : return WERR_OK;
2289 : }
2290 :
2291 272 : if (!strcasecmp_m(value, "MajorVersion")) {
2292 28 : *type = REG_DWORD;
2293 :
2294 : /* Windows NT 4.0 seems to not allow uploading of drivers
2295 : to a server that reports 0x3 as the MajorVersion.
2296 : need to investigate more how Win2k gets around this .
2297 : -- jerry */
2298 :
2299 28 : if (RA_WINNT == get_remote_arch()) {
2300 0 : SIVAL(&data->value, 0, 0x02);
2301 : } else {
2302 28 : SIVAL(&data->value, 0, 0x03);
2303 : }
2304 :
2305 28 : return WERR_OK;
2306 : }
2307 :
2308 244 : if (!strcasecmp_m(value, "MinorVersion")) {
2309 24 : *type = REG_DWORD;
2310 24 : SIVAL(&data->value, 0, 0x00);
2311 24 : return WERR_OK;
2312 : }
2313 :
2314 : /* REG_BINARY
2315 : * uint32_t size = 0x114
2316 : * uint32_t major = 5
2317 : * uint32_t minor = [0|1]
2318 : * uint32_t build = [2195|2600]
2319 : * extra unicode string = e.g. "Service Pack 3"
2320 : */
2321 220 : if (!strcasecmp_m(value, "OSVersion")) {
2322 : DATA_BLOB blob;
2323 : enum ndr_err_code ndr_err;
2324 : struct spoolss_OSVersion os;
2325 :
2326 : /*
2327 : * Set the default OSVersion to:
2328 : *
2329 : * Windows Server 2003R2 SP2 (5.2.3790)
2330 : *
2331 : * used to be Windows 2000 (5.0.2195)
2332 : */
2333 40 : os.major = lp_parm_int(GLOBAL_SECTION_SNUM,
2334 : "spoolss", "os_major",
2335 : GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT);
2336 40 : os.minor = lp_parm_int(GLOBAL_SECTION_SNUM,
2337 : "spoolss", "os_minor",
2338 : GLOBAL_SPOOLSS_OS_MINOR_DEFAULT);
2339 40 : os.build = lp_parm_int(GLOBAL_SECTION_SNUM,
2340 : "spoolss", "os_build",
2341 : GLOBAL_SPOOLSS_OS_BUILD_DEFAULT);
2342 40 : os.extra_string = ""; /* leave extra string empty */
2343 :
2344 40 : ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2345 : (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2346 40 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2347 0 : return WERR_GEN_FAILURE;
2348 : }
2349 :
2350 40 : if (DEBUGLEVEL >= 10) {
2351 0 : NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
2352 : }
2353 :
2354 40 : *type = REG_BINARY;
2355 40 : data->binary = blob;
2356 :
2357 40 : return WERR_OK;
2358 : }
2359 :
2360 :
2361 180 : if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2362 24 : *type = REG_SZ;
2363 :
2364 24 : data->string = talloc_strdup(mem_ctx, SPOOLSS_DEFAULT_SERVER_PATH);
2365 24 : W_ERROR_HAVE_NO_MEMORY(data->string);
2366 :
2367 24 : return WERR_OK;
2368 : }
2369 :
2370 156 : if (!strcasecmp_m(value, "Architecture")) {
2371 104 : *type = REG_SZ;
2372 104 : data->string = talloc_strdup(mem_ctx,
2373 : lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", GLOBAL_SPOOLSS_ARCHITECTURE));
2374 104 : W_ERROR_HAVE_NO_MEMORY(data->string);
2375 :
2376 104 : return WERR_OK;
2377 : }
2378 :
2379 52 : if (!strcasecmp_m(value, "DsPresent")) {
2380 24 : *type = REG_DWORD;
2381 :
2382 : /* only show the publish check box if we are a
2383 : member of a AD domain */
2384 :
2385 24 : if (lp_security() == SEC_ADS) {
2386 0 : SIVAL(&data->value, 0, 0x01);
2387 : } else {
2388 24 : SIVAL(&data->value, 0, 0x00);
2389 : }
2390 24 : return WERR_OK;
2391 : }
2392 :
2393 28 : if (!strcasecmp_m(value, "DNSMachineName")) {
2394 24 : const char *hostname = get_mydnsfullname();
2395 :
2396 24 : if (!hostname) {
2397 0 : return WERR_FILE_NOT_FOUND;
2398 : }
2399 :
2400 24 : *type = REG_SZ;
2401 24 : data->string = talloc_strdup(mem_ctx, hostname);
2402 24 : W_ERROR_HAVE_NO_MEMORY(data->string);
2403 :
2404 24 : return WERR_OK;
2405 : }
2406 :
2407 4 : *type = REG_NONE;
2408 :
2409 4 : return WERR_INVALID_PARAMETER;
2410 : }
2411 :
2412 : /****************************************************************
2413 : _spoolss_GetPrinterData
2414 : ****************************************************************/
2415 :
2416 424 : WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2417 : struct spoolss_GetPrinterData *r)
2418 : {
2419 : struct spoolss_GetPrinterDataEx r2;
2420 :
2421 424 : r2.in.handle = r->in.handle;
2422 424 : r2.in.key_name = "PrinterDriverData";
2423 424 : r2.in.value_name = r->in.value_name;
2424 424 : r2.in.offered = r->in.offered;
2425 424 : r2.out.type = r->out.type;
2426 424 : r2.out.data = r->out.data;
2427 424 : r2.out.needed = r->out.needed;
2428 :
2429 424 : return _spoolss_GetPrinterDataEx(p, &r2);
2430 : }
2431 :
2432 : /*********************************************************
2433 : Connect to the client machine.
2434 : **********************************************************/
2435 :
2436 2 : static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe, struct cli_state **pp_cli,
2437 : struct sockaddr_storage *client_ss, const char *remote_machine)
2438 : {
2439 : NTSTATUS ret;
2440 : struct sockaddr_storage rm_addr;
2441 : char addr[INET6_ADDRSTRLEN];
2442 2 : struct cli_credentials *anon_creds = NULL;
2443 :
2444 2 : if ( is_zero_addr(client_ss) ) {
2445 0 : DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2446 : remote_machine));
2447 0 : if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2448 0 : DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2449 0 : return false;
2450 : }
2451 0 : print_sockaddr(addr, sizeof(addr), &rm_addr);
2452 : } else {
2453 2 : rm_addr = *client_ss;
2454 2 : print_sockaddr(addr, sizeof(addr), &rm_addr);
2455 2 : DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2456 : addr));
2457 : }
2458 :
2459 2 : if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2460 0 : DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2461 : addr));
2462 0 : return false;
2463 : }
2464 :
2465 2 : anon_creds = cli_credentials_init_anon(NULL);
2466 2 : if (anon_creds == NULL) {
2467 0 : DBG_ERR("cli_credentials_init_anon() failed\n");
2468 0 : return false;
2469 : }
2470 :
2471 : /* setup the connection */
2472 2 : ret = cli_full_connection_creds( pp_cli, lp_netbios_name(), remote_machine,
2473 : &rm_addr, 0, "IPC$", "IPC",
2474 : anon_creds,
2475 : CLI_FULL_CONNECTION_IPC);
2476 2 : TALLOC_FREE(anon_creds);
2477 2 : if ( !NT_STATUS_IS_OK( ret ) ) {
2478 0 : DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2479 : remote_machine ));
2480 0 : return false;
2481 : }
2482 :
2483 2 : if ( smbXcli_conn_protocol((*pp_cli)->conn) < PROTOCOL_NT1 ) {
2484 0 : DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2485 0 : cli_shutdown(*pp_cli);
2486 0 : return false;
2487 : }
2488 :
2489 : /*
2490 : * Ok - we have an anonymous connection to the IPC$ share.
2491 : * Now start the NT Domain stuff :-).
2492 : */
2493 :
2494 2 : ret = cli_rpc_pipe_open_noauth(*pp_cli, &ndr_table_spoolss, pp_pipe);
2495 2 : if (!NT_STATUS_IS_OK(ret)) {
2496 0 : DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2497 : remote_machine, nt_errstr(ret)));
2498 0 : cli_shutdown(*pp_cli);
2499 0 : return false;
2500 : }
2501 :
2502 2 : return true;
2503 : }
2504 :
2505 : /***************************************************************************
2506 : Connect to the client.
2507 : ****************************************************************************/
2508 :
2509 2 : static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2510 : uint32_t localprinter,
2511 : enum winreg_Type type,
2512 : struct policy_handle *handle,
2513 : struct notify_back_channel **_chan,
2514 : struct sockaddr_storage *client_ss,
2515 : struct messaging_context *msg_ctx)
2516 : {
2517 : WERROR result;
2518 : NTSTATUS status;
2519 : struct notify_back_channel *chan;
2520 :
2521 2 : for (chan = back_channels; chan; chan = chan->next) {
2522 0 : if (memcmp(&chan->client_address, client_ss,
2523 : sizeof(struct sockaddr_storage)) == 0) {
2524 0 : break;
2525 : }
2526 : }
2527 :
2528 : /*
2529 : * If it's the first connection, contact the client
2530 : * and connect to the IPC$ share anonymously
2531 : */
2532 2 : if (!chan) {
2533 : fstring unix_printer;
2534 :
2535 : /* the +2 is to strip the leading 2 backslashs */
2536 2 : fstrcpy(unix_printer, printer + 2);
2537 :
2538 2 : chan = talloc_zero(NULL, struct notify_back_channel);
2539 2 : if (!chan) {
2540 0 : return false;
2541 : }
2542 2 : chan->client_address = *client_ss;
2543 :
2544 2 : if (!spoolss_connect_to_client(&chan->cli_pipe, &chan->cli, client_ss, unix_printer)) {
2545 0 : TALLOC_FREE(chan);
2546 0 : return false;
2547 : }
2548 :
2549 2 : DLIST_ADD(back_channels, chan);
2550 :
2551 2 : messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2552 : receive_notify2_message_list);
2553 : }
2554 :
2555 3 : if (chan->cli_pipe == NULL ||
2556 2 : chan->cli_pipe->binding_handle == NULL) {
2557 0 : DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2558 : "NULL %s for printer %s\n",
2559 : chan->cli_pipe == NULL ?
2560 : "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2561 : printer));
2562 0 : return false;
2563 : }
2564 :
2565 : /*
2566 : * Tell the specific printing tdb we want messages for this printer
2567 : * by registering our PID.
2568 : */
2569 :
2570 2 : if (!print_notify_register_pid(snum)) {
2571 0 : DEBUG(0, ("Failed to register our pid for printer %s\n",
2572 : printer));
2573 : }
2574 :
2575 2 : status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2576 : talloc_tos(),
2577 : printer,
2578 : localprinter,
2579 : type,
2580 : 0,
2581 : NULL,
2582 : handle,
2583 : &result);
2584 2 : if (!NT_STATUS_IS_OK(status)) {
2585 0 : DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2586 0 : result = ntstatus_to_werror(status);
2587 2 : } else if (!W_ERROR_IS_OK(result)) {
2588 0 : DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2589 : }
2590 :
2591 2 : chan->active_connections++;
2592 2 : *_chan = chan;
2593 :
2594 2 : return (W_ERROR_IS_OK(result));
2595 : }
2596 :
2597 : /****************************************************************
2598 : ****************************************************************/
2599 :
2600 2 : static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2601 : const struct spoolss_NotifyOption *r)
2602 : {
2603 : struct spoolss_NotifyOption *option;
2604 : uint32_t i,k;
2605 :
2606 2 : if (!r) {
2607 0 : return NULL;
2608 : }
2609 :
2610 2 : option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2611 2 : if (!option) {
2612 0 : return NULL;
2613 : }
2614 :
2615 2 : *option = *r;
2616 :
2617 2 : if (!option->count) {
2618 0 : return option;
2619 : }
2620 :
2621 2 : option->types = talloc_zero_array(option,
2622 : struct spoolss_NotifyOptionType, option->count);
2623 2 : if (!option->types) {
2624 0 : talloc_free(option);
2625 0 : return NULL;
2626 : }
2627 :
2628 6 : for (i=0; i < option->count; i++) {
2629 4 : option->types[i] = r->types[i];
2630 :
2631 4 : if (option->types[i].count) {
2632 4 : option->types[i].fields = talloc_zero_array(option,
2633 : union spoolss_Field, option->types[i].count);
2634 4 : if (!option->types[i].fields) {
2635 0 : talloc_free(option);
2636 0 : return NULL;
2637 : }
2638 8 : for (k=0; k<option->types[i].count; k++) {
2639 4 : option->types[i].fields[k] =
2640 4 : r->types[i].fields[k];
2641 : }
2642 : }
2643 : }
2644 :
2645 2 : return option;
2646 : }
2647 :
2648 : /****************************************************************
2649 : * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2650 : *
2651 : * before replying OK: status=0 a rpc call is made to the workstation
2652 : * asking ReplyOpenPrinter
2653 : *
2654 : * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2655 : * called from api_spoolss_rffpcnex
2656 : ****************************************************************/
2657 :
2658 2 : WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2659 : struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2660 : {
2661 2 : int snum = -1;
2662 2 : struct spoolss_NotifyOption *option = r->in.notify_options;
2663 : struct sockaddr_storage client_ss;
2664 : ssize_t client_len;
2665 :
2666 : /* store the notify value in the printer struct */
2667 :
2668 2 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2669 :
2670 2 : if (!Printer) {
2671 0 : DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2672 : "Invalid handle (%s:%u:%u).\n",
2673 : OUR_HANDLE(r->in.handle)));
2674 0 : return WERR_INVALID_HANDLE;
2675 : }
2676 :
2677 2 : Printer->notify.flags = r->in.flags;
2678 2 : Printer->notify.options = r->in.options;
2679 2 : Printer->notify.printerlocal = r->in.printer_local;
2680 2 : Printer->notify.msg_ctx = p->msg_ctx;
2681 :
2682 2 : TALLOC_FREE(Printer->notify.option);
2683 2 : Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2684 :
2685 2 : fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2686 :
2687 : /* Connect to the client machine and send a ReplyOpenPrinter */
2688 :
2689 2 : if ( Printer->printer_type == SPLHND_SERVER)
2690 2 : snum = -1;
2691 0 : else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2692 0 : !get_printer_snum(p, r->in.handle, &snum, NULL) )
2693 0 : return WERR_INVALID_HANDLE;
2694 :
2695 2 : DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2696 : "remote_address is %s\n",
2697 : tsocket_address_string(p->remote_address, p->mem_ctx)));
2698 :
2699 2 : if (!lp_print_notify_backchannel(snum)) {
2700 0 : DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2701 : "backchannel disabled\n"));
2702 0 : return WERR_RPC_S_SERVER_UNAVAILABLE;
2703 : }
2704 :
2705 2 : client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2706 : (struct sockaddr *) &client_ss,
2707 : sizeof(struct sockaddr_storage));
2708 2 : if (client_len < 0) {
2709 0 : return WERR_NOT_ENOUGH_MEMORY;
2710 : }
2711 :
2712 2 : if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2713 : Printer->notify.printerlocal, REG_SZ,
2714 : &Printer->notify.cli_hnd,
2715 : &Printer->notify.cli_chan,
2716 : &client_ss, p->msg_ctx)) {
2717 0 : return WERR_RPC_S_SERVER_UNAVAILABLE;
2718 : }
2719 :
2720 2 : return WERR_OK;
2721 : }
2722 :
2723 : /*******************************************************************
2724 : * fill a notify_info_data with the servername
2725 : ********************************************************************/
2726 :
2727 0 : static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2728 : int snum,
2729 : struct spoolss_Notify *data,
2730 : print_queue_struct *queue,
2731 : struct spoolss_PrinterInfo2 *pinfo2,
2732 : TALLOC_CTX *mem_ctx)
2733 : {
2734 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2735 0 : }
2736 :
2737 : /*******************************************************************
2738 : * fill a notify_info_data with the printername (not including the servername).
2739 : ********************************************************************/
2740 :
2741 0 : static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2742 : int snum,
2743 : struct spoolss_Notify *data,
2744 : print_queue_struct *queue,
2745 : struct spoolss_PrinterInfo2 *pinfo2,
2746 : TALLOC_CTX *mem_ctx)
2747 : {
2748 : /* the notify name should not contain the \\server\ part */
2749 0 : const char *p = strrchr(pinfo2->printername, '\\');
2750 :
2751 0 : if (!p) {
2752 0 : p = pinfo2->printername;
2753 : } else {
2754 0 : p++;
2755 : }
2756 :
2757 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2758 0 : }
2759 :
2760 : /*******************************************************************
2761 : * fill a notify_info_data with the servicename
2762 : ********************************************************************/
2763 :
2764 0 : static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2765 : int snum,
2766 : struct spoolss_Notify *data,
2767 : print_queue_struct *queue,
2768 : struct spoolss_PrinterInfo2 *pinfo2,
2769 : TALLOC_CTX *mem_ctx)
2770 : {
2771 0 : const struct loadparm_substitution *lp_sub =
2772 0 : loadparm_s3_global_substitution();
2773 :
2774 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), lp_sub, snum));
2775 0 : }
2776 :
2777 : /*******************************************************************
2778 : * fill a notify_info_data with the port name
2779 : ********************************************************************/
2780 :
2781 0 : static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2782 : int snum,
2783 : struct spoolss_Notify *data,
2784 : print_queue_struct *queue,
2785 : struct spoolss_PrinterInfo2 *pinfo2,
2786 : TALLOC_CTX *mem_ctx)
2787 : {
2788 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2789 0 : }
2790 :
2791 : /*******************************************************************
2792 : * fill a notify_info_data with the printername
2793 : * but it doesn't exist, have to see what to do
2794 : ********************************************************************/
2795 :
2796 0 : static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2797 : int snum,
2798 : struct spoolss_Notify *data,
2799 : print_queue_struct *queue,
2800 : struct spoolss_PrinterInfo2 *pinfo2,
2801 : TALLOC_CTX *mem_ctx)
2802 : {
2803 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2804 0 : }
2805 :
2806 : /*******************************************************************
2807 : * fill a notify_info_data with the comment
2808 : ********************************************************************/
2809 :
2810 0 : static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2811 : int snum,
2812 : struct spoolss_Notify *data,
2813 : print_queue_struct *queue,
2814 : struct spoolss_PrinterInfo2 *pinfo2,
2815 : TALLOC_CTX *mem_ctx)
2816 : {
2817 0 : const struct loadparm_substitution *lp_sub =
2818 0 : loadparm_s3_global_substitution();
2819 : const char *p;
2820 :
2821 0 : if (*pinfo2->comment == '\0') {
2822 0 : p = lp_comment(talloc_tos(), lp_sub, snum);
2823 : } else {
2824 0 : p = pinfo2->comment;
2825 : }
2826 :
2827 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2828 0 : }
2829 :
2830 : /*******************************************************************
2831 : * fill a notify_info_data with the comment
2832 : * location = "Room 1, floor 2, building 3"
2833 : ********************************************************************/
2834 :
2835 0 : static void spoolss_notify_location(struct messaging_context *msg_ctx,
2836 : int snum,
2837 : struct spoolss_Notify *data,
2838 : print_queue_struct *queue,
2839 : struct spoolss_PrinterInfo2 *pinfo2,
2840 : TALLOC_CTX *mem_ctx)
2841 : {
2842 0 : const char *loc = pinfo2->location;
2843 : NTSTATUS status;
2844 :
2845 0 : status = printer_list_get_printer(mem_ctx,
2846 : pinfo2->sharename,
2847 : NULL,
2848 : &loc,
2849 : NULL);
2850 0 : if (NT_STATUS_IS_OK(status)) {
2851 0 : if (loc == NULL) {
2852 0 : loc = pinfo2->location;
2853 : }
2854 : }
2855 :
2856 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2857 0 : }
2858 :
2859 : /*******************************************************************
2860 : * fill a notify_info_data with the device mode
2861 : * jfm:xxxx don't to it for know but that's a real problem !!!
2862 : ********************************************************************/
2863 :
2864 0 : static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2865 : int snum,
2866 : struct spoolss_Notify *data,
2867 : print_queue_struct *queue,
2868 : struct spoolss_PrinterInfo2 *pinfo2,
2869 : TALLOC_CTX *mem_ctx)
2870 : {
2871 : /* for a dummy implementation we have to zero the fields */
2872 0 : SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2873 0 : }
2874 :
2875 : /*******************************************************************
2876 : * fill a notify_info_data with the separator file name
2877 : ********************************************************************/
2878 :
2879 0 : static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2880 : int snum,
2881 : struct spoolss_Notify *data,
2882 : print_queue_struct *queue,
2883 : struct spoolss_PrinterInfo2 *pinfo2,
2884 : TALLOC_CTX *mem_ctx)
2885 : {
2886 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2887 0 : }
2888 :
2889 : /*******************************************************************
2890 : * fill a notify_info_data with the print processor
2891 : * jfm:xxxx return always winprint to indicate we don't do anything to it
2892 : ********************************************************************/
2893 :
2894 0 : static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2895 : int snum,
2896 : struct spoolss_Notify *data,
2897 : print_queue_struct *queue,
2898 : struct spoolss_PrinterInfo2 *pinfo2,
2899 : TALLOC_CTX *mem_ctx)
2900 : {
2901 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2902 0 : }
2903 :
2904 : /*******************************************************************
2905 : * fill a notify_info_data with the print processor options
2906 : * jfm:xxxx send an empty string
2907 : ********************************************************************/
2908 :
2909 0 : static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2910 : int snum,
2911 : struct spoolss_Notify *data,
2912 : print_queue_struct *queue,
2913 : struct spoolss_PrinterInfo2 *pinfo2,
2914 : TALLOC_CTX *mem_ctx)
2915 : {
2916 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2917 0 : }
2918 :
2919 : /*******************************************************************
2920 : * fill a notify_info_data with the data type
2921 : * jfm:xxxx always send RAW as data type
2922 : ********************************************************************/
2923 :
2924 0 : static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2925 : int snum,
2926 : struct spoolss_Notify *data,
2927 : print_queue_struct *queue,
2928 : struct spoolss_PrinterInfo2 *pinfo2,
2929 : TALLOC_CTX *mem_ctx)
2930 : {
2931 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2932 0 : }
2933 :
2934 : /*******************************************************************
2935 : * fill a notify_info_data with the security descriptor
2936 : * jfm:xxxx send an null pointer to say no security desc
2937 : * have to implement security before !
2938 : ********************************************************************/
2939 :
2940 0 : static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2941 : int snum,
2942 : struct spoolss_Notify *data,
2943 : print_queue_struct *queue,
2944 : struct spoolss_PrinterInfo2 *pinfo2,
2945 : TALLOC_CTX *mem_ctx)
2946 : {
2947 0 : if (pinfo2->secdesc == NULL) {
2948 0 : data->data.sd.sd = NULL;
2949 : } else {
2950 0 : data->data.sd.sd = security_descriptor_copy(mem_ctx,
2951 0 : pinfo2->secdesc);
2952 : }
2953 0 : data->data.sd.sd_size = ndr_size_security_descriptor(data->data.sd.sd,
2954 : 0);
2955 0 : }
2956 :
2957 : /*******************************************************************
2958 : * fill a notify_info_data with the attributes
2959 : * jfm:xxxx a samba printer is always shared
2960 : ********************************************************************/
2961 :
2962 0 : static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2963 : int snum,
2964 : struct spoolss_Notify *data,
2965 : print_queue_struct *queue,
2966 : struct spoolss_PrinterInfo2 *pinfo2,
2967 : TALLOC_CTX *mem_ctx)
2968 : {
2969 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2970 0 : }
2971 :
2972 : /*******************************************************************
2973 : * fill a notify_info_data with the priority
2974 : ********************************************************************/
2975 :
2976 0 : static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2977 : int snum,
2978 : struct spoolss_Notify *data,
2979 : print_queue_struct *queue,
2980 : struct spoolss_PrinterInfo2 *pinfo2,
2981 : TALLOC_CTX *mem_ctx)
2982 : {
2983 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2984 0 : }
2985 :
2986 : /*******************************************************************
2987 : * fill a notify_info_data with the default priority
2988 : ********************************************************************/
2989 :
2990 0 : static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2991 : int snum,
2992 : struct spoolss_Notify *data,
2993 : print_queue_struct *queue,
2994 : struct spoolss_PrinterInfo2 *pinfo2,
2995 : TALLOC_CTX *mem_ctx)
2996 : {
2997 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2998 0 : }
2999 :
3000 : /*******************************************************************
3001 : * fill a notify_info_data with the start time
3002 : ********************************************************************/
3003 :
3004 0 : static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3005 : int snum,
3006 : struct spoolss_Notify *data,
3007 : print_queue_struct *queue,
3008 : struct spoolss_PrinterInfo2 *pinfo2,
3009 : TALLOC_CTX *mem_ctx)
3010 : {
3011 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3012 0 : }
3013 :
3014 : /*******************************************************************
3015 : * fill a notify_info_data with the until time
3016 : ********************************************************************/
3017 :
3018 0 : static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3019 : int snum,
3020 : struct spoolss_Notify *data,
3021 : print_queue_struct *queue,
3022 : struct spoolss_PrinterInfo2 *pinfo2,
3023 : TALLOC_CTX *mem_ctx)
3024 : {
3025 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3026 0 : }
3027 :
3028 : /*******************************************************************
3029 : * fill a notify_info_data with the status
3030 : ********************************************************************/
3031 :
3032 0 : static void spoolss_notify_status(struct messaging_context *msg_ctx,
3033 : int snum,
3034 : struct spoolss_Notify *data,
3035 : print_queue_struct *queue,
3036 : struct spoolss_PrinterInfo2 *pinfo2,
3037 : TALLOC_CTX *mem_ctx)
3038 : {
3039 : print_status_struct status;
3040 :
3041 0 : print_queue_length(msg_ctx, snum, &status);
3042 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3043 0 : }
3044 :
3045 : /*******************************************************************
3046 : * fill a notify_info_data with the number of jobs queued
3047 : ********************************************************************/
3048 :
3049 0 : static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3050 : int snum,
3051 : struct spoolss_Notify *data,
3052 : print_queue_struct *queue,
3053 : struct spoolss_PrinterInfo2 *pinfo2,
3054 : TALLOC_CTX *mem_ctx)
3055 : {
3056 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3057 : data, print_queue_length(msg_ctx, snum, NULL));
3058 0 : }
3059 :
3060 : /*******************************************************************
3061 : * fill a notify_info_data with the average ppm
3062 : ********************************************************************/
3063 :
3064 0 : static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3065 : int snum,
3066 : struct spoolss_Notify *data,
3067 : print_queue_struct *queue,
3068 : struct spoolss_PrinterInfo2 *pinfo2,
3069 : TALLOC_CTX *mem_ctx)
3070 : {
3071 : /* always respond 8 pages per minutes */
3072 : /* a little hard ! */
3073 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3074 0 : }
3075 :
3076 : /*******************************************************************
3077 : * fill a notify_info_data with username
3078 : ********************************************************************/
3079 :
3080 0 : static void spoolss_notify_username(struct messaging_context *msg_ctx,
3081 : int snum,
3082 : struct spoolss_Notify *data,
3083 : print_queue_struct *queue,
3084 : struct spoolss_PrinterInfo2 *pinfo2,
3085 : TALLOC_CTX *mem_ctx)
3086 : {
3087 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3088 0 : }
3089 :
3090 : /*******************************************************************
3091 : * fill a notify_info_data with job status
3092 : ********************************************************************/
3093 :
3094 0 : static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3095 : int snum,
3096 : struct spoolss_Notify *data,
3097 : print_queue_struct *queue,
3098 : struct spoolss_PrinterInfo2 *pinfo2,
3099 : TALLOC_CTX *mem_ctx)
3100 : {
3101 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3102 0 : }
3103 :
3104 : /*******************************************************************
3105 : * fill a notify_info_data with job name
3106 : ********************************************************************/
3107 :
3108 0 : static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3109 : int snum,
3110 : struct spoolss_Notify *data,
3111 : print_queue_struct *queue,
3112 : struct spoolss_PrinterInfo2 *pinfo2,
3113 : TALLOC_CTX *mem_ctx)
3114 : {
3115 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3116 0 : }
3117 :
3118 : /*******************************************************************
3119 : * fill a notify_info_data with job status
3120 : ********************************************************************/
3121 :
3122 0 : static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3123 : int snum,
3124 : struct spoolss_Notify *data,
3125 : print_queue_struct *queue,
3126 : struct spoolss_PrinterInfo2 *pinfo2,
3127 : TALLOC_CTX *mem_ctx)
3128 : {
3129 : /*
3130 : * Now we're returning job status codes we just return a "" here. JRA.
3131 : */
3132 :
3133 0 : const char *p = "";
3134 :
3135 : #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3136 : p = "unknown";
3137 :
3138 : switch (queue->status) {
3139 : case LPQ_QUEUED:
3140 : p = "Queued";
3141 : break;
3142 : case LPQ_PAUSED:
3143 : p = ""; /* NT provides the paused string */
3144 : break;
3145 : case LPQ_SPOOLING:
3146 : p = "Spooling";
3147 : break;
3148 : case LPQ_PRINTING:
3149 : p = "Printing";
3150 : break;
3151 : }
3152 : #endif /* NO LONGER NEEDED. */
3153 :
3154 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3155 0 : }
3156 :
3157 : /*******************************************************************
3158 : * fill a notify_info_data with job time
3159 : ********************************************************************/
3160 :
3161 0 : static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3162 : int snum,
3163 : struct spoolss_Notify *data,
3164 : print_queue_struct *queue,
3165 : struct spoolss_PrinterInfo2 *pinfo2,
3166 : TALLOC_CTX *mem_ctx)
3167 : {
3168 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3169 0 : }
3170 :
3171 : /*******************************************************************
3172 : * fill a notify_info_data with job size
3173 : ********************************************************************/
3174 :
3175 0 : static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3176 : int snum,
3177 : struct spoolss_Notify *data,
3178 : print_queue_struct *queue,
3179 : struct spoolss_PrinterInfo2 *pinfo2,
3180 : TALLOC_CTX *mem_ctx)
3181 : {
3182 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3183 0 : }
3184 :
3185 : /*******************************************************************
3186 : * fill a notify_info_data with page info
3187 : ********************************************************************/
3188 0 : static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3189 : int snum,
3190 : struct spoolss_Notify *data,
3191 : print_queue_struct *queue,
3192 : struct spoolss_PrinterInfo2 *pinfo2,
3193 : TALLOC_CTX *mem_ctx)
3194 : {
3195 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3196 0 : }
3197 :
3198 : /*******************************************************************
3199 : * fill a notify_info_data with pages printed info.
3200 : ********************************************************************/
3201 0 : static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3202 : int snum,
3203 : struct spoolss_Notify *data,
3204 : print_queue_struct *queue,
3205 : struct spoolss_PrinterInfo2 *pinfo2,
3206 : TALLOC_CTX *mem_ctx)
3207 : {
3208 : /* Add code when back-end tracks this */
3209 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3210 0 : }
3211 :
3212 : /*******************************************************************
3213 : Fill a notify_info_data with job position.
3214 : ********************************************************************/
3215 :
3216 0 : static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3217 : int snum,
3218 : struct spoolss_Notify *data,
3219 : print_queue_struct *queue,
3220 : struct spoolss_PrinterInfo2 *pinfo2,
3221 : TALLOC_CTX *mem_ctx)
3222 : {
3223 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
3224 0 : }
3225 :
3226 : /*******************************************************************
3227 : Fill a notify_info_data with submitted time.
3228 : ********************************************************************/
3229 :
3230 0 : static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3231 : int snum,
3232 : struct spoolss_Notify *data,
3233 : print_queue_struct *queue,
3234 : struct spoolss_PrinterInfo2 *pinfo2,
3235 : TALLOC_CTX *mem_ctx)
3236 : {
3237 0 : data->data.string.string = NULL;
3238 0 : data->data.string.size = 0;
3239 :
3240 0 : init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3241 : &data->data.string.string,
3242 : &data->data.string.size);
3243 :
3244 0 : }
3245 :
3246 : struct s_notify_info_data_table
3247 : {
3248 : enum spoolss_NotifyType type;
3249 : uint16_t field;
3250 : const char *name;
3251 : enum spoolss_NotifyTable variable_type;
3252 : void (*fn) (struct messaging_context *msg_ctx,
3253 : int snum, struct spoolss_Notify *data,
3254 : print_queue_struct *queue,
3255 : struct spoolss_PrinterInfo2 *pinfo2,
3256 : TALLOC_CTX *mem_ctx);
3257 : };
3258 :
3259 : /* A table describing the various print notification constants and
3260 : whether the notification data is a pointer to a variable sized
3261 : buffer, a one value uint32_t or a two value uint32_t. */
3262 :
3263 : static const struct s_notify_info_data_table notify_info_data_table[] =
3264 : {
3265 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3266 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3267 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3268 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3269 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3270 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3271 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3272 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3273 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3274 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3275 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3276 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3277 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3278 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3279 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3280 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3281 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3282 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3283 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3284 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3285 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3286 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3287 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3288 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3289 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3290 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3291 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3292 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3293 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3294 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3295 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3296 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3297 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3298 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3299 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3300 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3301 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3302 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3303 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3304 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3305 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3306 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3307 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3308 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3309 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3310 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3311 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3312 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3313 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3314 : };
3315 :
3316 : /*******************************************************************
3317 : Return the variable_type of info_data structure.
3318 : ********************************************************************/
3319 :
3320 0 : static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3321 : uint16_t field)
3322 : {
3323 0 : int i=0;
3324 :
3325 0 : for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3326 0 : if ( (notify_info_data_table[i].type == type) &&
3327 0 : (notify_info_data_table[i].field == field) ) {
3328 0 : return notify_info_data_table[i].variable_type;
3329 : }
3330 : }
3331 :
3332 0 : DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3333 :
3334 0 : return (enum spoolss_NotifyTable) 0;
3335 : }
3336 :
3337 : /****************************************************************************
3338 : ****************************************************************************/
3339 :
3340 0 : static bool search_notify(enum spoolss_NotifyType type,
3341 : uint16_t field,
3342 : int *value)
3343 : {
3344 : int i;
3345 :
3346 0 : for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3347 0 : if (notify_info_data_table[i].type == type &&
3348 0 : notify_info_data_table[i].field == field &&
3349 0 : notify_info_data_table[i].fn != NULL) {
3350 0 : *value = i;
3351 0 : return true;
3352 : }
3353 : }
3354 :
3355 0 : return false;
3356 : }
3357 :
3358 : /****************************************************************************
3359 : ****************************************************************************/
3360 :
3361 0 : static void construct_info_data(struct spoolss_Notify *info_data,
3362 : enum spoolss_NotifyType type,
3363 : uint16_t field, int id)
3364 : {
3365 0 : info_data->type = type;
3366 0 : info_data->field.field = field;
3367 0 : info_data->variable_type = variable_type_of_notify_info_data(type, field);
3368 0 : info_data->job_id = id;
3369 0 : }
3370 :
3371 : /*******************************************************************
3372 : *
3373 : * fill a notify_info struct with info asked
3374 : *
3375 : ********************************************************************/
3376 :
3377 0 : static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3378 : struct printer_handle *print_hnd,
3379 : struct spoolss_NotifyInfo *info,
3380 : struct spoolss_PrinterInfo2 *pinfo2,
3381 : int snum,
3382 : const struct spoolss_NotifyOptionType *option_type,
3383 : uint32_t id,
3384 : TALLOC_CTX *mem_ctx)
3385 : {
3386 0 : const struct loadparm_substitution *lp_sub =
3387 0 : loadparm_s3_global_substitution();
3388 : int field_num,j;
3389 : enum spoolss_NotifyType type;
3390 : uint16_t field;
3391 :
3392 : struct spoolss_Notify *current_data;
3393 :
3394 0 : type = option_type->type;
3395 :
3396 0 : DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3397 : (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3398 : option_type->count, lp_servicename(talloc_tos(), lp_sub, snum)));
3399 :
3400 0 : for(field_num=0; field_num < option_type->count; field_num++) {
3401 0 : field = option_type->fields[field_num].field;
3402 :
3403 0 : DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3404 :
3405 0 : if (!search_notify(type, field, &j) )
3406 0 : continue;
3407 :
3408 0 : info->notifies = talloc_realloc(info, info->notifies,
3409 : struct spoolss_Notify,
3410 : info->count + 1);
3411 0 : if (info->notifies == NULL) {
3412 0 : DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3413 0 : return false;
3414 : }
3415 :
3416 0 : current_data = &info->notifies[info->count];
3417 :
3418 0 : construct_info_data(current_data, type, field, id);
3419 :
3420 0 : DEBUG(10, ("construct_notify_printer_info: "
3421 : "calling [%s] snum=%d printername=[%s])\n",
3422 : notify_info_data_table[j].name, snum,
3423 : pinfo2->printername));
3424 :
3425 0 : notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3426 : NULL, pinfo2, mem_ctx);
3427 :
3428 0 : info->count++;
3429 : }
3430 :
3431 0 : return true;
3432 : }
3433 :
3434 : /*******************************************************************
3435 : *
3436 : * fill a notify_info struct with info asked
3437 : *
3438 : ********************************************************************/
3439 :
3440 0 : static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3441 : print_queue_struct *queue,
3442 : struct spoolss_NotifyInfo *info,
3443 : struct spoolss_PrinterInfo2 *pinfo2,
3444 : int snum,
3445 : const struct spoolss_NotifyOptionType *option_type,
3446 : uint32_t id,
3447 : TALLOC_CTX *mem_ctx)
3448 : {
3449 : int field_num,j;
3450 : enum spoolss_NotifyType type;
3451 : uint16_t field;
3452 : struct spoolss_Notify *current_data;
3453 :
3454 0 : DEBUG(4,("construct_notify_jobs_info\n"));
3455 :
3456 0 : type = option_type->type;
3457 :
3458 0 : DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3459 : (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3460 : option_type->count));
3461 :
3462 0 : for(field_num=0; field_num<option_type->count; field_num++) {
3463 0 : field = option_type->fields[field_num].field;
3464 :
3465 0 : if (!search_notify(type, field, &j) )
3466 0 : continue;
3467 :
3468 0 : info->notifies = talloc_realloc(info, info->notifies,
3469 : struct spoolss_Notify,
3470 : info->count + 1);
3471 0 : if (info->notifies == NULL) {
3472 0 : DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3473 0 : return false;
3474 : }
3475 :
3476 0 : current_data=&(info->notifies[info->count]);
3477 :
3478 0 : construct_info_data(current_data, type, field, id);
3479 0 : notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3480 : queue, pinfo2, mem_ctx);
3481 0 : info->count++;
3482 : }
3483 :
3484 0 : return true;
3485 : }
3486 :
3487 : /*
3488 : * JFM: The enumeration is not that simple, it's even non obvious.
3489 : *
3490 : * let's take an example: I want to monitor the PRINTER SERVER for
3491 : * the printer's name and the number of jobs currently queued.
3492 : * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3493 : * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3494 : *
3495 : * I have 3 printers on the back of my server.
3496 : *
3497 : * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3498 : * structures.
3499 : * Number Data Id
3500 : * 1 printer 1 name 1
3501 : * 2 printer 1 cjob 1
3502 : * 3 printer 2 name 2
3503 : * 4 printer 2 cjob 2
3504 : * 5 printer 3 name 3
3505 : * 6 printer 3 name 3
3506 : *
3507 : * that's the print server case, the printer case is even worse.
3508 : */
3509 :
3510 : /*******************************************************************
3511 : *
3512 : * enumerate all printers on the printserver
3513 : * fill a notify_info struct with info asked
3514 : *
3515 : ********************************************************************/
3516 :
3517 4 : static WERROR printserver_notify_info(struct pipes_struct *p,
3518 : struct policy_handle *hnd,
3519 : struct spoolss_NotifyInfo *info,
3520 : TALLOC_CTX *mem_ctx)
3521 : {
3522 2 : const struct loadparm_substitution *lp_sub =
3523 2 : loadparm_s3_global_substitution();
3524 : int snum;
3525 4 : struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3526 4 : int n_services=lp_numservices();
3527 : int i;
3528 : struct spoolss_NotifyOption *option;
3529 : struct spoolss_NotifyOptionType option_type;
3530 4 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3531 : WERROR result;
3532 :
3533 4 : DEBUG(4,("printserver_notify_info\n"));
3534 :
3535 4 : if (!Printer)
3536 0 : return WERR_INVALID_HANDLE;
3537 :
3538 4 : option = Printer->notify.option;
3539 :
3540 4 : info->version = 2;
3541 4 : info->notifies = NULL;
3542 4 : info->count = 0;
3543 :
3544 : /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3545 : sending a ffpcn() request first */
3546 :
3547 4 : if ( !option )
3548 0 : return WERR_INVALID_HANDLE;
3549 :
3550 12 : for (i=0; i<option->count; i++) {
3551 8 : option_type = option->types[i];
3552 :
3553 8 : if (option_type.type != PRINTER_NOTIFY_TYPE)
3554 4 : continue;
3555 :
3556 416 : for (snum = 0; snum < n_services; snum++) {
3557 618 : if (!lp_browseable(snum) ||
3558 618 : !lp_snum_ok(snum) ||
3559 412 : !lp_printable(snum)) {
3560 392 : continue; /* skip */
3561 : }
3562 :
3563 : /* Maybe we should use the SYSTEM session_info here... */
3564 20 : result = winreg_get_printer_internal(mem_ctx,
3565 : get_session_info_system(),
3566 : p->msg_ctx,
3567 20 : lp_servicename(talloc_tos(), lp_sub, snum),
3568 : &pinfo2);
3569 20 : if (!W_ERROR_IS_OK(result)) {
3570 20 : DEBUG(4, ("printserver_notify_info: "
3571 : "Failed to get printer [%s]\n",
3572 : lp_servicename(talloc_tos(), lp_sub, snum)));
3573 20 : continue;
3574 : }
3575 :
3576 :
3577 0 : construct_notify_printer_info(p->msg_ctx,
3578 : Printer, info,
3579 : pinfo2, snum,
3580 : &option_type, snum,
3581 : mem_ctx);
3582 :
3583 0 : TALLOC_FREE(pinfo2);
3584 : }
3585 : }
3586 :
3587 : #if 0
3588 : /*
3589 : * Debugging information, don't delete.
3590 : */
3591 :
3592 : DEBUG(1,("dumping the NOTIFY_INFO\n"));
3593 : DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3594 : DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3595 :
3596 : for (i=0; i<info->count; i++) {
3597 : DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3598 : i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3599 : info->data[i].id, info->data[i].size, info->data[i].enc_type));
3600 : }
3601 : #endif
3602 :
3603 4 : return WERR_OK;
3604 : }
3605 :
3606 : /*******************************************************************
3607 : *
3608 : * fill a notify_info struct with info asked
3609 : *
3610 : ********************************************************************/
3611 :
3612 0 : static WERROR printer_notify_info(struct pipes_struct *p,
3613 : struct policy_handle *hnd,
3614 : struct spoolss_NotifyInfo *info,
3615 : TALLOC_CTX *mem_ctx)
3616 : {
3617 0 : const struct loadparm_substitution *lp_sub =
3618 0 : loadparm_s3_global_substitution();
3619 : int snum;
3620 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3621 : int i;
3622 : uint32_t id;
3623 : struct spoolss_NotifyOption *option;
3624 : struct spoolss_NotifyOptionType option_type;
3625 : int count,j;
3626 0 : print_queue_struct *queue=NULL;
3627 : print_status_struct status;
3628 0 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3629 : WERROR result;
3630 : struct tdb_print_db *pdb;
3631 :
3632 0 : DEBUG(4,("printer_notify_info\n"));
3633 :
3634 0 : if (!Printer)
3635 0 : return WERR_INVALID_HANDLE;
3636 :
3637 0 : option = Printer->notify.option;
3638 0 : id = 0x0;
3639 :
3640 0 : info->version = 2;
3641 0 : info->notifies = NULL;
3642 0 : info->count = 0;
3643 :
3644 : /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3645 : sending a ffpcn() request first */
3646 :
3647 0 : if ( !option )
3648 0 : return WERR_INVALID_HANDLE;
3649 :
3650 0 : if (!get_printer_snum(p, hnd, &snum, NULL)) {
3651 0 : return WERR_INVALID_HANDLE;
3652 : }
3653 :
3654 0 : pdb = get_print_db_byname(Printer->sharename);
3655 0 : if (pdb == NULL) {
3656 0 : return WERR_INVALID_HANDLE;
3657 : }
3658 :
3659 : /* Maybe we should use the SYSTEM session_info here... */
3660 0 : result = winreg_get_printer_internal(mem_ctx,
3661 : get_session_info_system(),
3662 : p->msg_ctx,
3663 0 : lp_servicename(talloc_tos(), lp_sub, snum), &pinfo2);
3664 0 : if (!W_ERROR_IS_OK(result)) {
3665 0 : result = WERR_INVALID_HANDLE;
3666 0 : goto err_pdb_drop;
3667 : }
3668 :
3669 : /*
3670 : * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3671 : * correct servername.
3672 : */
3673 0 : pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3674 0 : if (pinfo2->servername == NULL) {
3675 0 : result = WERR_NOT_ENOUGH_MEMORY;
3676 0 : goto err_pdb_drop;
3677 : }
3678 :
3679 0 : for (i = 0; i < option->count; i++) {
3680 0 : option_type = option->types[i];
3681 :
3682 0 : switch (option_type.type) {
3683 0 : case PRINTER_NOTIFY_TYPE:
3684 0 : if (construct_notify_printer_info(p->msg_ctx,
3685 : Printer, info,
3686 : pinfo2, snum,
3687 : &option_type, id,
3688 : mem_ctx)) {
3689 0 : id--;
3690 : }
3691 0 : break;
3692 :
3693 0 : case JOB_NOTIFY_TYPE:
3694 :
3695 0 : count = print_queue_status(p->msg_ctx, snum, &queue,
3696 : &status);
3697 :
3698 0 : for (j = 0; j < count; j++) {
3699 : uint32_t jobid;
3700 0 : jobid = sysjob_to_jobid_pdb(pdb,
3701 0 : queue[j].sysjob);
3702 0 : if (jobid == (uint32_t)-1) {
3703 0 : DEBUG(2, ("ignoring untracked job %d\n",
3704 : queue[j].sysjob));
3705 0 : continue;
3706 : }
3707 : /* FIXME check return value */
3708 0 : construct_notify_jobs_info(p->msg_ctx,
3709 0 : &queue[j], info,
3710 : pinfo2, snum,
3711 : &option_type,
3712 : jobid,
3713 : mem_ctx);
3714 : }
3715 :
3716 0 : SAFE_FREE(queue);
3717 0 : break;
3718 : }
3719 : }
3720 :
3721 : /*
3722 : * Debugging information, don't delete.
3723 : */
3724 : /*
3725 : DEBUG(1,("dumping the NOTIFY_INFO\n"));
3726 : DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3727 : DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3728 :
3729 : for (i=0; i<info->count; i++) {
3730 : DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3731 : i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3732 : info->data[i].id, info->data[i].size, info->data[i].enc_type));
3733 : }
3734 : */
3735 :
3736 0 : talloc_free(pinfo2);
3737 0 : result = WERR_OK;
3738 0 : err_pdb_drop:
3739 0 : release_print_db(pdb);
3740 0 : return result;
3741 : }
3742 :
3743 : /****************************************************************
3744 : _spoolss_RouterRefreshPrinterChangeNotify
3745 : ****************************************************************/
3746 :
3747 4 : WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3748 : struct spoolss_RouterRefreshPrinterChangeNotify *r)
3749 : {
3750 : struct spoolss_NotifyInfo *info;
3751 :
3752 4 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3753 4 : WERROR result = WERR_INVALID_HANDLE;
3754 :
3755 : /* we always have a spoolss_NotifyInfo struct */
3756 4 : info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3757 4 : if (!info) {
3758 0 : result = WERR_NOT_ENOUGH_MEMORY;
3759 0 : goto done;
3760 : }
3761 :
3762 4 : *r->out.info = info;
3763 :
3764 4 : if (!Printer) {
3765 0 : DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3766 : "Invalid handle (%s:%u:%u).\n",
3767 : OUR_HANDLE(r->in.handle)));
3768 0 : goto done;
3769 : }
3770 :
3771 4 : DEBUG(4,("Printer type %x\n",Printer->printer_type));
3772 :
3773 : /*
3774 : * We are now using the change value, and
3775 : * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3776 : * I don't have a global notification system, I'm sending back all the
3777 : * information even when _NOTHING_ has changed.
3778 : */
3779 :
3780 : /* We need to keep track of the change value to send back in
3781 : RRPCN replies otherwise our updates are ignored. */
3782 :
3783 4 : Printer->notify.fnpcn = true;
3784 :
3785 6 : if (Printer->notify.cli_chan != NULL &&
3786 4 : Printer->notify.cli_chan->active_connections > 0) {
3787 4 : DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3788 : "Saving change value in request [%x]\n",
3789 : r->in.change_low));
3790 4 : Printer->notify.change = r->in.change_low;
3791 : }
3792 :
3793 : /* just ignore the spoolss_NotifyOption */
3794 :
3795 4 : switch (Printer->printer_type) {
3796 4 : case SPLHND_SERVER:
3797 4 : result = printserver_notify_info(p, r->in.handle,
3798 : info, p->mem_ctx);
3799 4 : break;
3800 :
3801 0 : case SPLHND_PRINTER:
3802 0 : result = printer_notify_info(p, r->in.handle,
3803 : info, p->mem_ctx);
3804 0 : break;
3805 : }
3806 :
3807 4 : Printer->notify.fnpcn = false;
3808 :
3809 4 : done:
3810 4 : return result;
3811 : }
3812 :
3813 : /********************************************************************
3814 : ********************************************************************/
3815 :
3816 3951 : static WERROR create_printername(TALLOC_CTX *mem_ctx,
3817 : const char *servername,
3818 : const char *printername,
3819 : const char **printername_p)
3820 : {
3821 : /* FIXME: add lp_force_printername() */
3822 :
3823 3951 : if (servername == NULL) {
3824 1667 : *printername_p = talloc_strdup(mem_ctx, printername);
3825 1667 : W_ERROR_HAVE_NO_MEMORY(*printername_p);
3826 1667 : return WERR_OK;
3827 : }
3828 :
3829 2284 : if (servername[0] == '\\' && servername[1] == '\\') {
3830 2284 : servername += 2;
3831 : }
3832 :
3833 2284 : *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3834 2284 : W_ERROR_HAVE_NO_MEMORY(*printername_p);
3835 :
3836 2284 : return WERR_OK;
3837 : }
3838 :
3839 : /********************************************************************
3840 : ********************************************************************/
3841 :
3842 2912 : static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3843 : const char *printername)
3844 : {
3845 2912 : if (dm == NULL) {
3846 90 : return;
3847 : }
3848 :
3849 2822 : dm->devicename = talloc_strndup(dm, printername,
3850 2822 : MIN(strlen(printername), 31));
3851 : }
3852 :
3853 : /********************************************************************
3854 : * construct_printer_info_0
3855 : * fill a printer_info_0 struct
3856 : ********************************************************************/
3857 :
3858 272 : static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3859 : const struct auth_session_info *session_info,
3860 : struct messaging_context *msg_ctx,
3861 : struct spoolss_PrinterInfo2 *info2,
3862 : const char *servername,
3863 : struct spoolss_PrinterInfo0 *r,
3864 : int snum)
3865 : {
3866 : int count;
3867 : struct printer_session_counter *session_counter;
3868 : struct timeval setuptime;
3869 : print_status_struct status;
3870 : WERROR result;
3871 : int os_major, os_minor, os_build;
3872 : const char *architecture;
3873 : uint32_t processor_architecture, processor_type;
3874 :
3875 272 : result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3876 272 : if (!W_ERROR_IS_OK(result)) {
3877 0 : return result;
3878 : }
3879 :
3880 272 : if (servername) {
3881 136 : r->servername = talloc_strdup(mem_ctx, servername);
3882 136 : W_ERROR_HAVE_NO_MEMORY(r->servername);
3883 : } else {
3884 136 : r->servername = NULL;
3885 : }
3886 :
3887 272 : count = print_queue_length(msg_ctx, snum, &status);
3888 :
3889 : /* check if we already have a counter for this printer */
3890 628 : for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3891 588 : if (session_counter->snum == snum)
3892 232 : break;
3893 : }
3894 :
3895 : /* it's the first time, add it to the list */
3896 272 : if (session_counter == NULL) {
3897 40 : session_counter = talloc_zero(counter_list, struct printer_session_counter);
3898 40 : W_ERROR_HAVE_NO_MEMORY(session_counter);
3899 40 : session_counter->snum = snum;
3900 40 : session_counter->counter = 0;
3901 40 : DLIST_ADD(counter_list, session_counter);
3902 : }
3903 :
3904 : /* increment it */
3905 272 : session_counter->counter++;
3906 :
3907 272 : r->cjobs = count;
3908 272 : r->total_jobs = 0;
3909 272 : r->total_bytes = 0;
3910 :
3911 272 : get_startup_time(&setuptime);
3912 272 : init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3913 :
3914 : /* JFM:
3915 : * the global_counter should be stored in a TDB as it's common to all the clients
3916 : * and should be zeroed on samba startup
3917 : */
3918 272 : r->global_counter = session_counter->counter;
3919 272 : r->total_pages = 0;
3920 :
3921 : /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3922 272 : os_major = lp_parm_int(GLOBAL_SECTION_SNUM,
3923 : "spoolss", "os_major",
3924 : GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT);
3925 272 : os_minor = lp_parm_int(GLOBAL_SECTION_SNUM,
3926 : "spoolss", "os_minor",
3927 : GLOBAL_SPOOLSS_OS_MINOR_DEFAULT);
3928 272 : os_build = lp_parm_int(GLOBAL_SECTION_SNUM,
3929 : "spoolss", "os_build",
3930 : GLOBAL_SPOOLSS_OS_BUILD_DEFAULT);
3931 :
3932 272 : SCVAL(&r->version, 0, os_major);
3933 272 : SCVAL(&r->version, 1, os_minor);
3934 272 : SSVAL(&r->version, 2, os_build);
3935 :
3936 272 : architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
3937 : "spoolss",
3938 : "architecture",
3939 : GLOBAL_SPOOLSS_ARCHITECTURE);
3940 :
3941 272 : if (strequal(architecture, SPOOLSS_ARCHITECTURE_x64)) {
3942 272 : processor_architecture = PROCESSOR_ARCHITECTURE_AMD64;
3943 272 : processor_type = PROCESSOR_AMD_X8664;
3944 0 : } else if (strequal(architecture, SPOOLSS_ARCHITECTURE_ARM64)) {
3945 0 : processor_architecture = PROCESSOR_ARCHITECTURE_ARM64;
3946 0 : processor_type = PROCESSOR_ARM820;
3947 : } else {
3948 0 : processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3949 0 : processor_type = PROCESSOR_INTEL_PENTIUM;
3950 : }
3951 :
3952 272 : r->free_build = SPOOLSS_RELEASE_BUILD;
3953 272 : r->spooling = 0;
3954 272 : r->max_spooling = 0;
3955 272 : r->session_counter = session_counter->counter;
3956 272 : r->num_error_out_of_paper = 0x0;
3957 272 : r->num_error_not_ready = 0x0; /* number of print failure */
3958 272 : r->job_error = 0x0;
3959 272 : r->number_of_processors = 0x1;
3960 272 : r->processor_type = processor_type;
3961 272 : r->high_part_total_bytes = 0x0;
3962 :
3963 : /* ChangeID in milliseconds*/
3964 272 : winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3965 : info2->sharename, &r->change_id);
3966 :
3967 272 : r->last_error = WERR_OK;
3968 272 : r->status = nt_printq_status(status.status);
3969 272 : r->enumerate_network_printers = 0x0;
3970 272 : r->c_setprinter = 0x0;
3971 272 : r->processor_architecture = processor_architecture;
3972 272 : r->processor_level = 0x6; /* 6 ???*/
3973 272 : r->ref_ic = 0;
3974 272 : r->reserved2 = 0;
3975 272 : r->reserved3 = 0;
3976 :
3977 272 : return WERR_OK;
3978 : }
3979 :
3980 :
3981 : /********************************************************************
3982 : * construct_printer_info1
3983 : * fill a spoolss_PrinterInfo1 struct
3984 : ********************************************************************/
3985 :
3986 439 : static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3987 : const struct spoolss_PrinterInfo2 *info2,
3988 : uint32_t flags,
3989 : const char *servername,
3990 : struct spoolss_PrinterInfo1 *r,
3991 : int snum)
3992 : {
3993 311 : const struct loadparm_substitution *lp_sub =
3994 128 : loadparm_s3_global_substitution();
3995 : WERROR result;
3996 :
3997 439 : r->flags = flags;
3998 :
3999 439 : if (info2->comment == NULL || info2->comment[0] == '\0') {
4000 339 : r->comment = lp_comment(mem_ctx, lp_sub, snum);
4001 : } else {
4002 100 : r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
4003 : }
4004 439 : W_ERROR_HAVE_NO_MEMORY(r->comment);
4005 :
4006 439 : result = create_printername(mem_ctx, servername, info2->printername, &r->name);
4007 439 : if (!W_ERROR_IS_OK(result)) {
4008 0 : return result;
4009 : }
4010 :
4011 567 : r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
4012 : r->name,
4013 128 : info2->drivername,
4014 : r->comment);
4015 439 : W_ERROR_HAVE_NO_MEMORY(r->description);
4016 :
4017 439 : return WERR_OK;
4018 : }
4019 :
4020 : /********************************************************************
4021 : * construct_printer_info2
4022 : * fill a spoolss_PrinterInfo2 struct
4023 : ********************************************************************/
4024 :
4025 1248 : static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4026 : struct messaging_context *msg_ctx,
4027 : const struct spoolss_PrinterInfo2 *info2,
4028 : const char *servername,
4029 : struct spoolss_PrinterInfo2 *r,
4030 : int snum)
4031 : {
4032 930 : const struct loadparm_substitution *lp_sub =
4033 318 : loadparm_s3_global_substitution();
4034 : int count;
4035 : print_status_struct status;
4036 : WERROR result;
4037 :
4038 1248 : count = print_queue_length(msg_ctx, snum, &status);
4039 :
4040 1248 : if (servername) {
4041 548 : r->servername = talloc_strdup(mem_ctx, servername);
4042 548 : W_ERROR_HAVE_NO_MEMORY(r->servername);
4043 : } else {
4044 700 : r->servername = NULL;
4045 : }
4046 :
4047 1248 : result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4048 1248 : if (!W_ERROR_IS_OK(result)) {
4049 0 : return result;
4050 : }
4051 :
4052 1248 : r->sharename = lp_servicename(mem_ctx, lp_sub, snum);
4053 1248 : W_ERROR_HAVE_NO_MEMORY(r->sharename);
4054 1248 : r->portname = talloc_strdup(mem_ctx, info2->portname);
4055 1248 : W_ERROR_HAVE_NO_MEMORY(r->portname);
4056 1248 : r->drivername = talloc_strdup(mem_ctx, info2->drivername);
4057 1248 : W_ERROR_HAVE_NO_MEMORY(r->drivername);
4058 :
4059 1248 : if (info2->comment[0] == '\0') {
4060 852 : r->comment = lp_comment(mem_ctx, lp_sub, snum);
4061 : } else {
4062 396 : r->comment = talloc_strdup(mem_ctx, info2->comment);
4063 : }
4064 1248 : W_ERROR_HAVE_NO_MEMORY(r->comment);
4065 :
4066 1248 : r->location = talloc_strdup(mem_ctx, info2->location);
4067 1248 : if (info2->location[0] == '\0') {
4068 1168 : const char *loc = NULL;
4069 : NTSTATUS nt_status;
4070 :
4071 1168 : nt_status = printer_list_get_printer(mem_ctx,
4072 298 : info2->sharename,
4073 : NULL,
4074 : &loc,
4075 : NULL);
4076 1168 : if (NT_STATUS_IS_OK(nt_status)) {
4077 0 : if (loc != NULL) {
4078 0 : r->location = talloc_strdup(mem_ctx, loc);
4079 : }
4080 : }
4081 : }
4082 1248 : W_ERROR_HAVE_NO_MEMORY(r->location);
4083 :
4084 1248 : r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4085 1248 : W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4086 1248 : r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4087 1248 : W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4088 1248 : r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4089 1248 : W_ERROR_HAVE_NO_MEMORY(r->datatype);
4090 1248 : r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4091 1248 : W_ERROR_HAVE_NO_MEMORY(r->parameters);
4092 :
4093 1248 : r->attributes = info2->attributes;
4094 :
4095 1248 : r->priority = info2->priority;
4096 1248 : r->defaultpriority = info2->defaultpriority;
4097 1248 : r->starttime = info2->starttime;
4098 1248 : r->untiltime = info2->untiltime;
4099 1248 : r->status = nt_printq_status(status.status);
4100 1248 : r->cjobs = count;
4101 1248 : r->averageppm = info2->averageppm;
4102 :
4103 1248 : if (info2->devmode != NULL) {
4104 1166 : result = copy_devicemode(mem_ctx,
4105 318 : info2->devmode,
4106 : &r->devmode);
4107 1166 : if (!W_ERROR_IS_OK(result)) {
4108 0 : return result;
4109 : }
4110 82 : } else if (lp_default_devmode(snum)) {
4111 0 : result = spoolss_create_default_devmode(mem_ctx,
4112 0 : info2->printername,
4113 : &r->devmode);
4114 0 : if (!W_ERROR_IS_OK(result)) {
4115 0 : return result;
4116 : }
4117 : } else {
4118 82 : r->devmode = NULL;
4119 82 : DEBUG(8,("Returning NULL Devicemode!\n"));
4120 : }
4121 :
4122 1248 : compose_devicemode_devicename(r->devmode, r->printername);
4123 :
4124 1248 : r->secdesc = NULL;
4125 :
4126 1248 : if (info2->secdesc != NULL) {
4127 : /* don't use talloc_steal() here unless you do a deep steal of all
4128 : the SEC_DESC members */
4129 :
4130 1248 : r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4131 1248 : if (r->secdesc == NULL) {
4132 0 : return WERR_NOT_ENOUGH_MEMORY;
4133 : }
4134 : }
4135 :
4136 1248 : return WERR_OK;
4137 : }
4138 :
4139 : /********************************************************************
4140 : * construct_printer_info3
4141 : * fill a spoolss_PrinterInfo3 struct
4142 : ********************************************************************/
4143 :
4144 140 : static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4145 : const struct spoolss_PrinterInfo2 *info2,
4146 : const char *servername,
4147 : struct spoolss_PrinterInfo3 *r,
4148 : int snum)
4149 : {
4150 : /* These are the components of the SD we are returning. */
4151 :
4152 140 : if (info2->secdesc != NULL) {
4153 : /* don't use talloc_steal() here unless you do a deep steal of all
4154 : the SEC_DESC members */
4155 :
4156 140 : r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4157 140 : if (r->secdesc == NULL) {
4158 0 : return WERR_NOT_ENOUGH_MEMORY;
4159 : }
4160 : }
4161 :
4162 140 : return WERR_OK;
4163 : }
4164 :
4165 : /********************************************************************
4166 : * construct_printer_info4
4167 : * fill a spoolss_PrinterInfo4 struct
4168 : ********************************************************************/
4169 :
4170 164 : static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4171 : const struct spoolss_PrinterInfo2 *info2,
4172 : const char *servername,
4173 : struct spoolss_PrinterInfo4 *r,
4174 : int snum)
4175 : {
4176 : WERROR result;
4177 :
4178 164 : result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4179 164 : if (!W_ERROR_IS_OK(result)) {
4180 0 : return result;
4181 : }
4182 :
4183 164 : if (servername) {
4184 4 : r->servername = talloc_strdup(mem_ctx, servername);
4185 4 : W_ERROR_HAVE_NO_MEMORY(r->servername);
4186 : } else {
4187 160 : r->servername = NULL;
4188 : }
4189 :
4190 164 : r->attributes = info2->attributes;
4191 :
4192 164 : return WERR_OK;
4193 : }
4194 :
4195 : /********************************************************************
4196 : * construct_printer_info5
4197 : * fill a spoolss_PrinterInfo5 struct
4198 : ********************************************************************/
4199 :
4200 164 : static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4201 : const struct spoolss_PrinterInfo2 *info2,
4202 : const char *servername,
4203 : struct spoolss_PrinterInfo5 *r,
4204 : int snum)
4205 : {
4206 : WERROR result;
4207 :
4208 164 : result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4209 164 : if (!W_ERROR_IS_OK(result)) {
4210 0 : return result;
4211 : }
4212 :
4213 164 : r->portname = talloc_strdup(mem_ctx, info2->portname);
4214 164 : W_ERROR_HAVE_NO_MEMORY(r->portname);
4215 :
4216 164 : r->attributes = info2->attributes;
4217 :
4218 : /*
4219 : * These two are not used by NT+ according to MSDN. However the values
4220 : * we saw on Windows Server 2012 and 2016 are always set to the 0xafc8.
4221 : */
4222 164 : r->device_not_selected_timeout = 0xafc8; /* 45 sec */
4223 164 : r->transmission_retry_timeout = 0xafc8; /* 45 sec */
4224 :
4225 164 : return WERR_OK;
4226 : }
4227 :
4228 : /********************************************************************
4229 : * construct_printer_info_6
4230 : * fill a spoolss_PrinterInfo6 struct
4231 : ********************************************************************/
4232 :
4233 84 : static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4234 : struct messaging_context *msg_ctx,
4235 : const struct spoolss_PrinterInfo2 *info2,
4236 : const char *servername,
4237 : struct spoolss_PrinterInfo6 *r,
4238 : int snum)
4239 : {
4240 : print_status_struct status;
4241 :
4242 84 : print_queue_length(msg_ctx, snum, &status);
4243 :
4244 84 : r->status = nt_printq_status(status.status);
4245 :
4246 84 : return WERR_OK;
4247 : }
4248 :
4249 : /********************************************************************
4250 : * construct_printer_info7
4251 : * fill a spoolss_PrinterInfo7 struct
4252 : ********************************************************************/
4253 :
4254 108 : static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4255 : struct messaging_context *msg_ctx,
4256 : const char *servername,
4257 : struct spoolss_PrinterInfo7 *r,
4258 : int snum)
4259 : {
4260 80 : const struct loadparm_substitution *lp_sub =
4261 28 : loadparm_s3_global_substitution();
4262 : const struct auth_session_info *session_info;
4263 108 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
4264 : char *printer;
4265 : WERROR werr;
4266 108 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4267 108 : if (tmp_ctx == NULL) {
4268 0 : return WERR_NOT_ENOUGH_MEMORY;
4269 : }
4270 :
4271 108 : session_info = get_session_info_system();
4272 108 : SMB_ASSERT(session_info != NULL);
4273 :
4274 108 : printer = lp_servicename(tmp_ctx, lp_sub, snum);
4275 108 : if (printer == NULL) {
4276 0 : DEBUG(0, ("invalid printer snum %d\n", snum));
4277 0 : werr = WERR_INVALID_PARAMETER;
4278 0 : goto out_tmp_free;
4279 : }
4280 :
4281 108 : if (is_printer_published(tmp_ctx, session_info, msg_ctx,
4282 : servername, printer, &pinfo2)) {
4283 : struct GUID guid;
4284 : char *guidstr;
4285 0 : werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
4286 : printer, &guid);
4287 0 : if (!W_ERROR_IS_OK(werr)) {
4288 : /*
4289 : * If we do not have a GUID entry in the registry, then
4290 : * try to retrieve it from AD and store it now.
4291 : */
4292 0 : werr = nt_printer_guid_retrieve(tmp_ctx, printer,
4293 : &guid);
4294 0 : if (!W_ERROR_IS_OK(werr)) {
4295 0 : DBG_NOTICE("Failed to retrieve GUID for "
4296 : "printer [%s] from AD - %s\n",
4297 : printer,
4298 : win_errstr(werr));
4299 0 : if (W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND)) {
4300 : /*
4301 : * If we did not find it in AD, then it
4302 : * is unpublished and we should reflect
4303 : * this in the registry and return
4304 : * success.
4305 : */
4306 0 : DBG_WARNING("Unpublish printer [%s]\n",
4307 : pinfo2->sharename);
4308 0 : nt_printer_publish(tmp_ctx,
4309 : session_info,
4310 : msg_ctx,
4311 : pinfo2,
4312 : DSPRINT_UNPUBLISH);
4313 0 : r->guid = talloc_strdup(mem_ctx, "");
4314 0 : r->action = DSPRINT_UNPUBLISH;
4315 :
4316 0 : if (r->guid == NULL) {
4317 0 : werr = WERR_NOT_ENOUGH_MEMORY;
4318 : } else {
4319 0 : werr = WERR_OK;
4320 : }
4321 : }
4322 0 : goto out_tmp_free;
4323 : }
4324 :
4325 0 : werr = nt_printer_guid_store(msg_ctx, printer, guid);
4326 0 : if (!W_ERROR_IS_OK(werr)) {
4327 0 : DEBUG(3, ("failed to store printer %s guid\n",
4328 : printer));
4329 : }
4330 : }
4331 :
4332 : /* [MS-RPRN] section 2.2: must use curly-braced GUIDs */
4333 0 : guidstr = GUID_string2(mem_ctx, &guid);
4334 0 : if (guidstr == NULL) {
4335 0 : werr = WERR_NOT_ENOUGH_MEMORY;
4336 0 : goto out_tmp_free;
4337 : }
4338 : /* Convert GUID string to uppercase otherwise printers
4339 : * are pruned */
4340 0 : r->guid = talloc_strdup_upper(mem_ctx, guidstr);
4341 0 : r->action = DSPRINT_PUBLISH;
4342 :
4343 0 : TALLOC_FREE(guidstr);
4344 : } else {
4345 108 : r->guid = talloc_strdup(mem_ctx, "");
4346 108 : r->action = DSPRINT_UNPUBLISH;
4347 : }
4348 108 : if (r->guid == NULL) {
4349 0 : werr = WERR_NOT_ENOUGH_MEMORY;
4350 0 : goto out_tmp_free;
4351 : }
4352 :
4353 108 : werr = WERR_OK;
4354 108 : out_tmp_free:
4355 108 : talloc_free(tmp_ctx);
4356 108 : return werr;
4357 : }
4358 :
4359 : /********************************************************************
4360 : * construct_printer_info8
4361 : * fill a spoolss_PrinterInfo8 struct
4362 : ********************************************************************/
4363 :
4364 1664 : static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4365 : const struct spoolss_PrinterInfo2 *info2,
4366 : const char *servername,
4367 : struct spoolss_DeviceModeInfo *r,
4368 : int snum)
4369 : {
4370 : WERROR result;
4371 : const char *printername;
4372 :
4373 1664 : result = create_printername(mem_ctx, servername, info2->printername, &printername);
4374 1664 : if (!W_ERROR_IS_OK(result)) {
4375 0 : return result;
4376 : }
4377 :
4378 1664 : if (info2->devmode != NULL) {
4379 1656 : result = copy_devicemode(mem_ctx,
4380 416 : info2->devmode,
4381 : &r->devmode);
4382 1656 : if (!W_ERROR_IS_OK(result)) {
4383 0 : return result;
4384 : }
4385 8 : } else if (lp_default_devmode(snum)) {
4386 0 : result = spoolss_create_default_devmode(mem_ctx,
4387 0 : info2->printername,
4388 : &r->devmode);
4389 0 : if (!W_ERROR_IS_OK(result)) {
4390 0 : return result;
4391 : }
4392 : } else {
4393 8 : r->devmode = NULL;
4394 8 : DEBUG(8,("Returning NULL Devicemode!\n"));
4395 : }
4396 :
4397 1664 : compose_devicemode_devicename(r->devmode, printername);
4398 :
4399 1664 : return WERR_OK;
4400 : }
4401 :
4402 : /********************************************************************
4403 : Spoolss_enumprinters.
4404 : ********************************************************************/
4405 :
4406 164 : static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4407 : const struct auth_session_info *session_info,
4408 : struct messaging_context *msg_ctx,
4409 : const char *servername,
4410 : uint32_t level,
4411 : uint32_t flags,
4412 : union spoolss_PrinterInfo **info_p,
4413 : uint32_t *count_p)
4414 : {
4415 : int snum;
4416 : int n_services;
4417 164 : union spoolss_PrinterInfo *info = NULL;
4418 164 : uint32_t count = 0;
4419 164 : WERROR result = WERR_OK;
4420 164 : struct dcerpc_binding_handle *b = NULL;
4421 164 : TALLOC_CTX *tmp_ctx = NULL;
4422 :
4423 164 : tmp_ctx = talloc_new(mem_ctx);
4424 164 : if (!tmp_ctx) {
4425 0 : return WERR_NOT_ENOUGH_MEMORY;
4426 : }
4427 :
4428 : /*
4429 : * printer shares are updated on client enumeration. The background
4430 : * printer process updates printer_list.tdb at regular intervals.
4431 : */
4432 164 : become_root();
4433 164 : delete_and_reload_printers();
4434 164 : unbecome_root();
4435 :
4436 164 : n_services = lp_numservices();
4437 164 : *count_p = 0;
4438 164 : *info_p = NULL;
4439 :
4440 9126 : for (snum = 0; snum < n_services; snum++) {
4441 :
4442 : const char *printer;
4443 : struct spoolss_PrinterInfo2 *info2;
4444 :
4445 8962 : if (!snum_is_shared_printer(snum)) {
4446 8087 : continue;
4447 : }
4448 :
4449 875 : printer = lp_const_servicename(snum);
4450 :
4451 875 : DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4452 : printer, snum));
4453 :
4454 875 : if (b == NULL) {
4455 164 : result = winreg_printer_binding_handle(tmp_ctx,
4456 : session_info,
4457 : msg_ctx,
4458 : &b);
4459 164 : if (!W_ERROR_IS_OK(result)) {
4460 0 : goto out;
4461 : }
4462 : }
4463 :
4464 875 : result = winreg_create_printer(tmp_ctx, b,
4465 : printer);
4466 875 : if (!W_ERROR_IS_OK(result)) {
4467 0 : goto out;
4468 : }
4469 :
4470 875 : info = talloc_realloc(tmp_ctx, info,
4471 : union spoolss_PrinterInfo,
4472 : count + 1);
4473 875 : if (!info) {
4474 0 : result = WERR_NOT_ENOUGH_MEMORY;
4475 0 : goto out;
4476 : }
4477 :
4478 875 : result = winreg_get_printer(tmp_ctx, b,
4479 : printer, &info2);
4480 875 : if (!W_ERROR_IS_OK(result)) {
4481 0 : goto out;
4482 : }
4483 :
4484 875 : switch (level) {
4485 40 : case 0:
4486 40 : result = construct_printer_info0(info, session_info,
4487 : msg_ctx, info2,
4488 : servername,
4489 40 : &info[count].info0, snum);
4490 40 : break;
4491 355 : case 1:
4492 355 : result = construct_printer_info1(info, info2, flags,
4493 : servername,
4494 355 : &info[count].info1, snum);
4495 355 : break;
4496 320 : case 2:
4497 320 : result = construct_printer_info2(info, msg_ctx, info2,
4498 : servername,
4499 320 : &info[count].info2, snum);
4500 320 : break;
4501 80 : case 4:
4502 80 : result = construct_printer_info4(info, info2,
4503 : servername,
4504 80 : &info[count].info4, snum);
4505 80 : break;
4506 80 : case 5:
4507 80 : result = construct_printer_info5(info, info2,
4508 : servername,
4509 80 : &info[count].info5, snum);
4510 80 : break;
4511 :
4512 0 : default:
4513 0 : result = WERR_INVALID_LEVEL;
4514 0 : goto out;
4515 : }
4516 :
4517 875 : if (!W_ERROR_IS_OK(result)) {
4518 0 : goto out;
4519 : }
4520 :
4521 875 : count++;
4522 : }
4523 :
4524 164 : out:
4525 164 : if (W_ERROR_IS_OK(result)) {
4526 164 : *info_p = talloc_move(mem_ctx, &info);
4527 164 : *count_p = count;
4528 : }
4529 :
4530 164 : talloc_free(tmp_ctx);
4531 :
4532 164 : return result;
4533 : }
4534 :
4535 : /********************************************************************
4536 : * handle enumeration of printers at level 0
4537 : ********************************************************************/
4538 :
4539 8 : static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4540 : const struct auth_session_info *session_info,
4541 : struct messaging_context *msg_ctx,
4542 : uint32_t flags,
4543 : const char *servername,
4544 : union spoolss_PrinterInfo **info,
4545 : uint32_t *count)
4546 : {
4547 8 : DEBUG(4,("enum_all_printers_info_0\n"));
4548 :
4549 8 : return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4550 : servername, 0, flags, info, count);
4551 : }
4552 :
4553 :
4554 : /********************************************************************
4555 : ********************************************************************/
4556 :
4557 60 : static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4558 : const struct auth_session_info *session_info,
4559 : struct messaging_context *msg_ctx,
4560 : const char *servername,
4561 : uint32_t flags,
4562 : union spoolss_PrinterInfo **info,
4563 : uint32_t *count)
4564 : {
4565 60 : DEBUG(4,("enum_all_printers_info_1\n"));
4566 :
4567 60 : return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4568 : servername, 1, flags, info, count);
4569 : }
4570 :
4571 : /********************************************************************
4572 : enum_all_printers_info_1_local.
4573 : *********************************************************************/
4574 :
4575 60 : static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4576 : const struct auth_session_info *session_info,
4577 : struct messaging_context *msg_ctx,
4578 : const char *servername,
4579 : union spoolss_PrinterInfo **info,
4580 : uint32_t *count)
4581 : {
4582 60 : DEBUG(4,("enum_all_printers_info_1_local\n"));
4583 :
4584 60 : return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4585 : servername, PRINTER_ENUM_ICON8, info, count);
4586 : }
4587 :
4588 : /********************************************************************
4589 : enum_all_printers_info_1_name.
4590 : *********************************************************************/
4591 :
4592 0 : static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4593 : const struct auth_session_info *session_info,
4594 : struct messaging_context *msg_ctx,
4595 : const char *servername,
4596 : union spoolss_PrinterInfo **info,
4597 : uint32_t *count)
4598 : {
4599 0 : const char *s = servername;
4600 :
4601 0 : DEBUG(4,("enum_all_printers_info_1_name\n"));
4602 :
4603 0 : if (servername != NULL &&
4604 0 : (servername[0] == '\\') && (servername[1] == '\\')) {
4605 0 : s = servername + 2;
4606 : }
4607 :
4608 0 : if (!is_myname_or_ipaddr(s)) {
4609 0 : return WERR_INVALID_NAME;
4610 : }
4611 :
4612 0 : return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4613 : servername, PRINTER_ENUM_ICON8, info, count);
4614 : }
4615 :
4616 : /********************************************************************
4617 : enum_all_printers_info_1_network.
4618 : *********************************************************************/
4619 :
4620 0 : static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4621 : const struct auth_session_info *session_info,
4622 : struct messaging_context *msg_ctx,
4623 : const char *servername,
4624 : union spoolss_PrinterInfo **info,
4625 : uint32_t *count)
4626 : {
4627 0 : const char *s = servername;
4628 :
4629 0 : DEBUG(4,("enum_all_printers_info_1_network\n"));
4630 :
4631 : /* If we respond to a enum_printers level 1 on our name with flags
4632 : set to PRINTER_ENUM_REMOTE with a list of printers then these
4633 : printers incorrectly appear in the APW browse list.
4634 : Specifically the printers for the server appear at the workgroup
4635 : level where all the other servers in the domain are
4636 : listed. Windows responds to this call with a
4637 : WERR_CAN_NOT_COMPLETE so we should do the same. */
4638 :
4639 0 : if (servername != NULL &&
4640 0 : (servername[0] == '\\') && (servername[1] == '\\')) {
4641 0 : s = servername + 2;
4642 : }
4643 :
4644 0 : if (is_myname_or_ipaddr(s)) {
4645 0 : return WERR_CAN_NOT_COMPLETE;
4646 : }
4647 :
4648 0 : return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4649 : servername, PRINTER_ENUM_NAME, info, count);
4650 : }
4651 :
4652 : /********************************************************************
4653 : * api_spoolss_enumprinters
4654 : *
4655 : * called from api_spoolss_enumprinters (see this to understand)
4656 : ********************************************************************/
4657 :
4658 64 : static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4659 : const struct auth_session_info *session_info,
4660 : struct messaging_context *msg_ctx,
4661 : const char *servername,
4662 : union spoolss_PrinterInfo **info,
4663 : uint32_t *count)
4664 : {
4665 64 : DEBUG(4,("enum_all_printers_info_2\n"));
4666 :
4667 64 : return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4668 : servername, 2, 0, info, count);
4669 : }
4670 :
4671 : /********************************************************************
4672 : * handle enumeration of printers at level 1
4673 : ********************************************************************/
4674 :
4675 60 : static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4676 : const struct auth_session_info *session_info,
4677 : struct messaging_context *msg_ctx,
4678 : uint32_t flags,
4679 : const char *servername,
4680 : union spoolss_PrinterInfo **info,
4681 : uint32_t *count)
4682 : {
4683 : /* Not all the flags are equals */
4684 :
4685 60 : if (flags & PRINTER_ENUM_LOCAL) {
4686 60 : return enum_all_printers_info_1_local(mem_ctx, session_info,
4687 : msg_ctx, servername, info, count);
4688 : }
4689 :
4690 0 : if (flags & PRINTER_ENUM_NAME) {
4691 0 : return enum_all_printers_info_1_name(mem_ctx, session_info,
4692 : msg_ctx, servername, info,
4693 : count);
4694 : }
4695 :
4696 0 : if (flags & PRINTER_ENUM_NETWORK) {
4697 0 : return enum_all_printers_info_1_network(mem_ctx, session_info,
4698 : msg_ctx, servername, info,
4699 : count);
4700 : }
4701 :
4702 0 : return WERR_OK; /* NT4sp5 does that */
4703 : }
4704 :
4705 : /********************************************************************
4706 : * handle enumeration of printers at level 2
4707 : ********************************************************************/
4708 :
4709 64 : static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4710 : const struct auth_session_info *session_info,
4711 : struct messaging_context *msg_ctx,
4712 : uint32_t flags,
4713 : const char *servername,
4714 : union spoolss_PrinterInfo **info,
4715 : uint32_t *count)
4716 : {
4717 64 : if (flags & PRINTER_ENUM_LOCAL) {
4718 :
4719 48 : return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4720 : servername,
4721 : info, count);
4722 : }
4723 :
4724 16 : if (flags & PRINTER_ENUM_NAME) {
4725 16 : if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4726 0 : return WERR_INVALID_NAME;
4727 : }
4728 :
4729 16 : return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4730 : servername,
4731 : info, count);
4732 : }
4733 :
4734 0 : if (flags & PRINTER_ENUM_REMOTE) {
4735 0 : return WERR_INVALID_LEVEL;
4736 : }
4737 :
4738 0 : return WERR_OK;
4739 : }
4740 :
4741 : /********************************************************************
4742 : * handle enumeration of printers at level 4
4743 : ********************************************************************/
4744 :
4745 16 : static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4746 : const struct auth_session_info *session_info,
4747 : struct messaging_context *msg_ctx,
4748 : uint32_t flags,
4749 : const char *servername,
4750 : union spoolss_PrinterInfo **info,
4751 : uint32_t *count)
4752 : {
4753 16 : DEBUG(4,("enum_all_printers_info_4\n"));
4754 :
4755 16 : return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4756 : servername, 4, flags, info, count);
4757 : }
4758 :
4759 :
4760 : /********************************************************************
4761 : * handle enumeration of printers at level 5
4762 : ********************************************************************/
4763 :
4764 16 : static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4765 : const struct auth_session_info *session_info,
4766 : struct messaging_context *msg_ctx,
4767 : uint32_t flags,
4768 : const char *servername,
4769 : union spoolss_PrinterInfo **info,
4770 : uint32_t *count)
4771 : {
4772 16 : DEBUG(4,("enum_all_printers_info_5\n"));
4773 :
4774 16 : return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4775 : servername, 5, flags, info, count);
4776 : }
4777 :
4778 : /****************************************************************
4779 : _spoolss_EnumPrinters
4780 : ****************************************************************/
4781 :
4782 164 : WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4783 : struct spoolss_EnumPrinters *r)
4784 : {
4785 164 : const struct auth_session_info *session_info = get_session_info_system();
4786 : WERROR result;
4787 :
4788 : /* that's an [in out] buffer */
4789 :
4790 164 : if (!r->in.buffer && (r->in.offered != 0)) {
4791 0 : return WERR_INVALID_PARAMETER;
4792 : }
4793 :
4794 164 : DEBUG(4,("_spoolss_EnumPrinters\n"));
4795 :
4796 164 : *r->out.needed = 0;
4797 164 : *r->out.count = 0;
4798 164 : *r->out.info = NULL;
4799 :
4800 : /*
4801 : * Level 1:
4802 : * flags==PRINTER_ENUM_NAME
4803 : * if name=="" then enumerates all printers
4804 : * if name!="" then enumerate the printer
4805 : * flags==PRINTER_ENUM_REMOTE
4806 : * name is NULL, enumerate printers
4807 : * Level 2: name!="" enumerates printers, name can't be NULL
4808 : * Level 3: doesn't exist
4809 : * Level 4: does a local registry lookup
4810 : * Level 5: same as Level 2
4811 : */
4812 :
4813 164 : if (r->in.server && r->in.server[0] == '\0') {
4814 80 : r->in.server = NULL;
4815 : }
4816 :
4817 164 : switch (r->in.level) {
4818 8 : case 0:
4819 8 : result = enumprinters_level0(p->mem_ctx, session_info,
4820 : p->msg_ctx, r->in.flags,
4821 : r->in.server,
4822 : r->out.info, r->out.count);
4823 8 : break;
4824 60 : case 1:
4825 60 : result = enumprinters_level1(p->mem_ctx, session_info,
4826 : p->msg_ctx, r->in.flags,
4827 : r->in.server,
4828 : r->out.info, r->out.count);
4829 60 : break;
4830 64 : case 2:
4831 64 : result = enumprinters_level2(p->mem_ctx, session_info,
4832 : p->msg_ctx, r->in.flags,
4833 : r->in.server,
4834 : r->out.info, r->out.count);
4835 64 : break;
4836 16 : case 4:
4837 16 : result = enumprinters_level4(p->mem_ctx, session_info,
4838 : p->msg_ctx, r->in.flags,
4839 : r->in.server,
4840 : r->out.info, r->out.count);
4841 16 : break;
4842 16 : case 5:
4843 16 : result = enumprinters_level5(p->mem_ctx, session_info,
4844 : p->msg_ctx, r->in.flags,
4845 : r->in.server,
4846 : r->out.info, r->out.count);
4847 16 : break;
4848 0 : default:
4849 0 : return WERR_INVALID_LEVEL;
4850 : }
4851 :
4852 164 : if (!W_ERROR_IS_OK(result)) {
4853 0 : return result;
4854 : }
4855 :
4856 164 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4857 : spoolss_EnumPrinters,
4858 : *r->out.info, r->in.level,
4859 : *r->out.count);
4860 164 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4861 164 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4862 :
4863 164 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4864 : }
4865 :
4866 : /****************************************************************
4867 : _spoolss_GetPrinter
4868 : ****************************************************************/
4869 :
4870 3480 : WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4871 : struct spoolss_GetPrinter *r)
4872 : {
4873 3480 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4874 3480 : struct spoolss_PrinterInfo2 *info2 = NULL;
4875 3480 : WERROR result = WERR_OK;
4876 : int snum;
4877 :
4878 : /* that's an [in out] buffer */
4879 :
4880 3480 : if (!r->in.buffer && (r->in.offered != 0)) {
4881 0 : result = WERR_INVALID_PARAMETER;
4882 0 : goto err_info_free;
4883 : }
4884 :
4885 3480 : *r->out.needed = 0;
4886 :
4887 3480 : if (Printer == NULL) {
4888 0 : result = WERR_INVALID_HANDLE;
4889 0 : goto err_info_free;
4890 : }
4891 :
4892 3480 : if (Printer->printer_type == SPLHND_SERVER) {
4893 :
4894 : struct dcerpc_binding_handle *b;
4895 :
4896 72 : if (r->in.level != 3) {
4897 32 : result = WERR_INVALID_LEVEL;
4898 56 : goto err_info_free;
4899 : }
4900 :
4901 40 : result = winreg_printer_binding_handle(p->mem_ctx,
4902 : get_session_info_system(),
4903 : p->msg_ctx,
4904 : &b);
4905 40 : if (!W_ERROR_IS_OK(result)) {
4906 0 : goto err_info_free;
4907 : }
4908 :
4909 40 : result = winreg_get_printserver_secdesc(p->mem_ctx,
4910 : b,
4911 40 : &r->out.info->info3.secdesc);
4912 40 : if (!W_ERROR_IS_OK(result)) {
4913 0 : goto err_info_free;
4914 : }
4915 :
4916 40 : goto done;
4917 : }
4918 :
4919 3408 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4920 0 : result = WERR_INVALID_HANDLE;
4921 0 : goto err_info_free;
4922 : }
4923 :
4924 3408 : result = winreg_get_printer_internal(p->mem_ctx,
4925 : get_session_info_system(),
4926 : p->msg_ctx,
4927 : lp_const_servicename(snum),
4928 : &info2);
4929 3408 : if (!W_ERROR_IS_OK(result)) {
4930 0 : goto err_info_free;
4931 : }
4932 :
4933 3408 : switch (r->in.level) {
4934 232 : case 0:
4935 405 : result = construct_printer_info0(p->mem_ctx,
4936 : get_session_info_system(),
4937 : p->msg_ctx,
4938 : info2,
4939 : Printer->servername,
4940 232 : &r->out.info->info0,
4941 : snum);
4942 232 : break;
4943 84 : case 1:
4944 146 : result = construct_printer_info1(p->mem_ctx, info2,
4945 : PRINTER_ENUM_ICON8,
4946 : Printer->servername,
4947 84 : &r->out.info->info1, snum);
4948 84 : break;
4949 928 : case 2:
4950 1623 : result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4951 : Printer->servername,
4952 928 : &r->out.info->info2, snum);
4953 928 : break;
4954 140 : case 3:
4955 244 : result = construct_printer_info3(p->mem_ctx, info2,
4956 : Printer->servername,
4957 140 : &r->out.info->info3, snum);
4958 140 : break;
4959 84 : case 4:
4960 146 : result = construct_printer_info4(p->mem_ctx, info2,
4961 : Printer->servername,
4962 84 : &r->out.info->info4, snum);
4963 84 : break;
4964 84 : case 5:
4965 146 : result = construct_printer_info5(p->mem_ctx, info2,
4966 : Printer->servername,
4967 84 : &r->out.info->info5, snum);
4968 84 : break;
4969 84 : case 6:
4970 146 : result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4971 : Printer->servername,
4972 84 : &r->out.info->info6, snum);
4973 84 : break;
4974 108 : case 7:
4975 188 : result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4976 : Printer->servername,
4977 108 : &r->out.info->info7, snum);
4978 108 : break;
4979 1664 : case 8:
4980 2912 : result = construct_printer_info8(p->mem_ctx, info2,
4981 : Printer->servername,
4982 1664 : &r->out.info->info8, snum);
4983 1664 : break;
4984 0 : default:
4985 0 : result = WERR_INVALID_LEVEL;
4986 0 : break;
4987 : }
4988 3408 : TALLOC_FREE(info2);
4989 :
4990 3408 : if (!W_ERROR_IS_OK(result)) {
4991 0 : DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4992 : r->in.level, win_errstr(result)));
4993 0 : goto err_info_free;
4994 : }
4995 3408 : done:
4996 3448 : *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4997 : r->out.info, r->in.level);
4998 3448 : r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4999 :
5000 3448 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5001 :
5002 32 : err_info_free:
5003 32 : TALLOC_FREE(r->out.info);
5004 32 : return result;
5005 : }
5006 :
5007 : /********************************************************************
5008 : ********************************************************************/
5009 :
5010 : #define FILL_DRIVER_STRING(mem_ctx, in, out) \
5011 : do { \
5012 : if (in && strlen(in)) { \
5013 : out = talloc_strdup(mem_ctx, in); \
5014 : } else { \
5015 : out = talloc_strdup(mem_ctx, ""); \
5016 : } \
5017 : W_ERROR_HAVE_NO_MEMORY(out); \
5018 : } while (0);
5019 :
5020 : #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
5021 : do { \
5022 : if (in && strlen(in)) { \
5023 : out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
5024 : } else { \
5025 : out = talloc_strdup(mem_ctx, ""); \
5026 : } \
5027 : W_ERROR_HAVE_NO_MEMORY(out); \
5028 : } while (0);
5029 :
5030 0 : static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
5031 : const char **string_array,
5032 : const char ***presult,
5033 : const char *cservername,
5034 : const char *arch,
5035 : int version)
5036 : {
5037 : size_t i;
5038 0 : size_t num_strings = 0;
5039 0 : const char **array = NULL;
5040 :
5041 0 : if (string_array == NULL) {
5042 0 : return WERR_INVALID_PARAMETER;
5043 : }
5044 :
5045 0 : for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
5046 0 : const char *str = NULL;
5047 :
5048 0 : if (cservername == NULL || arch == NULL) {
5049 0 : FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
5050 : } else {
5051 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
5052 : }
5053 :
5054 0 : if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
5055 0 : TALLOC_FREE(array);
5056 0 : return WERR_NOT_ENOUGH_MEMORY;
5057 : }
5058 : }
5059 :
5060 0 : if (i > 0) {
5061 0 : ADD_TO_ARRAY(mem_ctx, const char *, NULL,
5062 : &array, &num_strings);
5063 : }
5064 :
5065 0 : if (presult != NULL) {
5066 0 : *presult = array;
5067 : } else {
5068 0 : talloc_free(array);
5069 : }
5070 :
5071 0 : return WERR_OK;
5072 : }
5073 :
5074 : /********************************************************************
5075 : * fill a spoolss_DriverInfo1 struct
5076 : ********************************************************************/
5077 :
5078 0 : static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
5079 : struct spoolss_DriverInfo1 *r,
5080 : const struct spoolss_DriverInfo8 *driver,
5081 : const char *servername)
5082 : {
5083 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5084 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5085 :
5086 0 : return WERR_OK;
5087 : }
5088 :
5089 : /********************************************************************
5090 : * fill a spoolss_DriverInfo2 struct
5091 : ********************************************************************/
5092 :
5093 0 : static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
5094 : struct spoolss_DriverInfo2 *r,
5095 : const struct spoolss_DriverInfo8 *driver,
5096 : const char *servername)
5097 :
5098 : {
5099 0 : const char *cservername = canon_servername(servername);
5100 :
5101 0 : r->version = driver->version;
5102 :
5103 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5104 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5105 0 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5106 0 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5107 :
5108 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5109 : driver->architecture,
5110 : driver->version,
5111 : driver->driver_path,
5112 : r->driver_path);
5113 :
5114 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5115 : driver->architecture,
5116 : driver->version,
5117 : driver->data_file,
5118 : r->data_file);
5119 :
5120 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5121 : driver->architecture,
5122 : driver->version,
5123 : driver->config_file,
5124 : r->config_file);
5125 :
5126 0 : return WERR_OK;
5127 : }
5128 :
5129 : /********************************************************************
5130 : * fill a spoolss_DriverInfo3 struct
5131 : ********************************************************************/
5132 :
5133 0 : static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
5134 : struct spoolss_DriverInfo3 *r,
5135 : const struct spoolss_DriverInfo8 *driver,
5136 : const char *servername)
5137 : {
5138 0 : const char *cservername = canon_servername(servername);
5139 :
5140 0 : r->version = driver->version;
5141 :
5142 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5143 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5144 0 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5145 0 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5146 :
5147 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5148 : driver->architecture,
5149 : driver->version,
5150 : driver->driver_path,
5151 : r->driver_path);
5152 :
5153 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5154 : driver->architecture,
5155 : driver->version,
5156 : driver->data_file,
5157 : r->data_file);
5158 :
5159 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5160 : driver->architecture,
5161 : driver->version,
5162 : driver->config_file,
5163 : r->config_file);
5164 :
5165 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5166 : driver->architecture,
5167 : driver->version,
5168 : driver->help_file,
5169 : r->help_file);
5170 :
5171 0 : FILL_DRIVER_STRING(mem_ctx,
5172 : driver->monitor_name,
5173 : r->monitor_name);
5174 :
5175 0 : FILL_DRIVER_STRING(mem_ctx,
5176 : driver->default_datatype,
5177 : r->default_datatype);
5178 :
5179 0 : return string_array_from_driver_info(mem_ctx,
5180 0 : driver->dependent_files,
5181 : &r->dependent_files,
5182 : cservername,
5183 0 : driver->architecture,
5184 0 : driver->version);
5185 : }
5186 :
5187 : /********************************************************************
5188 : * fill a spoolss_DriverInfo4 struct
5189 : ********************************************************************/
5190 :
5191 0 : static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5192 : struct spoolss_DriverInfo4 *r,
5193 : const struct spoolss_DriverInfo8 *driver,
5194 : const char *servername)
5195 : {
5196 0 : const char *cservername = canon_servername(servername);
5197 : WERROR result;
5198 :
5199 0 : r->version = driver->version;
5200 :
5201 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5202 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5203 0 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5204 0 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5205 :
5206 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5207 : driver->architecture,
5208 : driver->version,
5209 : driver->driver_path,
5210 : r->driver_path);
5211 :
5212 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5213 : driver->architecture,
5214 : driver->version,
5215 : driver->data_file,
5216 : r->data_file);
5217 :
5218 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5219 : driver->architecture,
5220 : driver->version,
5221 : driver->config_file,
5222 : r->config_file);
5223 :
5224 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5225 : driver->architecture,
5226 : driver->version,
5227 : driver->help_file,
5228 : r->help_file);
5229 :
5230 0 : result = string_array_from_driver_info(mem_ctx,
5231 0 : driver->dependent_files,
5232 : &r->dependent_files,
5233 : cservername,
5234 0 : driver->architecture,
5235 0 : driver->version);
5236 0 : if (!W_ERROR_IS_OK(result)) {
5237 0 : return result;
5238 : }
5239 :
5240 0 : FILL_DRIVER_STRING(mem_ctx,
5241 : driver->monitor_name,
5242 : r->monitor_name);
5243 :
5244 0 : FILL_DRIVER_STRING(mem_ctx,
5245 : driver->default_datatype,
5246 : r->default_datatype);
5247 :
5248 :
5249 0 : result = string_array_from_driver_info(mem_ctx,
5250 0 : driver->previous_names,
5251 : &r->previous_names,
5252 : NULL, NULL, 0);
5253 :
5254 0 : return result;
5255 : }
5256 :
5257 : /********************************************************************
5258 : * fill a spoolss_DriverInfo5 struct
5259 : ********************************************************************/
5260 :
5261 0 : static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5262 : struct spoolss_DriverInfo5 *r,
5263 : const struct spoolss_DriverInfo8 *driver,
5264 : const char *servername)
5265 : {
5266 0 : const char *cservername = canon_servername(servername);
5267 :
5268 0 : r->version = driver->version;
5269 :
5270 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5271 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5272 0 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5273 0 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5274 :
5275 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5276 : driver->architecture,
5277 : driver->version,
5278 : driver->driver_path,
5279 : r->driver_path);
5280 :
5281 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5282 : driver->architecture,
5283 : driver->version,
5284 : driver->data_file,
5285 : r->data_file);
5286 :
5287 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5288 : driver->architecture,
5289 : driver->version,
5290 : driver->config_file,
5291 : r->config_file);
5292 :
5293 0 : r->driver_attributes = 0;
5294 0 : r->config_version = 0;
5295 0 : r->driver_version = 0;
5296 :
5297 0 : return WERR_OK;
5298 : }
5299 : /********************************************************************
5300 : * fill a spoolss_DriverInfo6 struct
5301 : ********************************************************************/
5302 :
5303 0 : static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5304 : struct spoolss_DriverInfo6 *r,
5305 : const struct spoolss_DriverInfo8 *driver,
5306 : const char *servername)
5307 : {
5308 0 : const char *cservername = canon_servername(servername);
5309 : WERROR result;
5310 :
5311 0 : r->version = driver->version;
5312 :
5313 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5314 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5315 0 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5316 0 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5317 :
5318 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5319 : driver->architecture,
5320 : driver->version,
5321 : driver->driver_path,
5322 : r->driver_path);
5323 :
5324 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5325 : driver->architecture,
5326 : driver->version,
5327 : driver->data_file,
5328 : r->data_file);
5329 :
5330 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5331 : driver->architecture,
5332 : driver->version,
5333 : driver->config_file,
5334 : r->config_file);
5335 :
5336 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5337 : driver->architecture,
5338 : driver->version,
5339 : driver->help_file,
5340 : r->help_file);
5341 :
5342 0 : FILL_DRIVER_STRING(mem_ctx,
5343 : driver->monitor_name,
5344 : r->monitor_name);
5345 :
5346 0 : FILL_DRIVER_STRING(mem_ctx,
5347 : driver->default_datatype,
5348 : r->default_datatype);
5349 :
5350 0 : result = string_array_from_driver_info(mem_ctx,
5351 0 : driver->dependent_files,
5352 : &r->dependent_files,
5353 : cservername,
5354 0 : driver->architecture,
5355 0 : driver->version);
5356 0 : if (!W_ERROR_IS_OK(result)) {
5357 0 : return result;
5358 : }
5359 :
5360 0 : result = string_array_from_driver_info(mem_ctx,
5361 0 : driver->previous_names,
5362 : &r->previous_names,
5363 : NULL, NULL, 0);
5364 0 : if (!W_ERROR_IS_OK(result)) {
5365 0 : return result;
5366 : }
5367 :
5368 0 : r->driver_date = driver->driver_date;
5369 0 : r->driver_version = driver->driver_version;
5370 :
5371 0 : FILL_DRIVER_STRING(mem_ctx,
5372 : driver->manufacturer_name,
5373 : r->manufacturer_name);
5374 0 : FILL_DRIVER_STRING(mem_ctx,
5375 : driver->manufacturer_url,
5376 : r->manufacturer_url);
5377 0 : FILL_DRIVER_STRING(mem_ctx,
5378 : driver->hardware_id,
5379 : r->hardware_id);
5380 0 : FILL_DRIVER_STRING(mem_ctx,
5381 : driver->provider,
5382 : r->provider);
5383 :
5384 0 : return WERR_OK;
5385 : }
5386 :
5387 : /********************************************************************
5388 : * fill a spoolss_DriverInfo8 struct
5389 : ********************************************************************/
5390 :
5391 0 : static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5392 : struct spoolss_DriverInfo8 *r,
5393 : const struct spoolss_DriverInfo8 *driver,
5394 : const char *servername)
5395 : {
5396 0 : const char *cservername = canon_servername(servername);
5397 : WERROR result;
5398 :
5399 0 : r->version = driver->version;
5400 :
5401 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5402 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5403 0 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5404 0 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5405 :
5406 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5407 : driver->architecture,
5408 : driver->version,
5409 : driver->driver_path,
5410 : r->driver_path);
5411 :
5412 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5413 : driver->architecture,
5414 : driver->version,
5415 : driver->data_file,
5416 : r->data_file);
5417 :
5418 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5419 : driver->architecture,
5420 : driver->version,
5421 : driver->config_file,
5422 : r->config_file);
5423 :
5424 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5425 : driver->architecture,
5426 : driver->version,
5427 : driver->help_file,
5428 : r->help_file);
5429 :
5430 0 : FILL_DRIVER_STRING(mem_ctx,
5431 : driver->monitor_name,
5432 : r->monitor_name);
5433 :
5434 0 : FILL_DRIVER_STRING(mem_ctx,
5435 : driver->default_datatype,
5436 : r->default_datatype);
5437 :
5438 0 : result = string_array_from_driver_info(mem_ctx,
5439 0 : driver->dependent_files,
5440 : &r->dependent_files,
5441 : cservername,
5442 0 : driver->architecture,
5443 0 : driver->version);
5444 0 : if (!W_ERROR_IS_OK(result)) {
5445 0 : return result;
5446 : }
5447 :
5448 0 : result = string_array_from_driver_info(mem_ctx,
5449 0 : driver->previous_names,
5450 : &r->previous_names,
5451 : NULL, NULL, 0);
5452 0 : if (!W_ERROR_IS_OK(result)) {
5453 0 : return result;
5454 : }
5455 :
5456 0 : r->driver_date = driver->driver_date;
5457 0 : r->driver_version = driver->driver_version;
5458 :
5459 0 : FILL_DRIVER_STRING(mem_ctx,
5460 : driver->manufacturer_name,
5461 : r->manufacturer_name);
5462 0 : FILL_DRIVER_STRING(mem_ctx,
5463 : driver->manufacturer_url,
5464 : r->manufacturer_url);
5465 0 : FILL_DRIVER_STRING(mem_ctx,
5466 : driver->hardware_id,
5467 : r->hardware_id);
5468 0 : FILL_DRIVER_STRING(mem_ctx,
5469 : driver->provider,
5470 : r->provider);
5471 :
5472 0 : FILL_DRIVER_STRING(mem_ctx,
5473 : driver->print_processor,
5474 : r->print_processor);
5475 0 : FILL_DRIVER_STRING(mem_ctx,
5476 : driver->vendor_setup,
5477 : r->vendor_setup);
5478 :
5479 0 : result = string_array_from_driver_info(mem_ctx,
5480 0 : driver->color_profiles,
5481 : &r->color_profiles,
5482 : NULL, NULL, 0);
5483 0 : if (!W_ERROR_IS_OK(result)) {
5484 0 : return result;
5485 : }
5486 :
5487 0 : FILL_DRIVER_STRING(mem_ctx,
5488 : driver->inf_path,
5489 : r->inf_path);
5490 :
5491 0 : r->printer_driver_attributes = driver->printer_driver_attributes;
5492 :
5493 0 : result = string_array_from_driver_info(mem_ctx,
5494 0 : driver->core_driver_dependencies,
5495 : &r->core_driver_dependencies,
5496 : NULL, NULL, 0);
5497 0 : if (!W_ERROR_IS_OK(result)) {
5498 0 : return result;
5499 : }
5500 :
5501 0 : r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5502 0 : r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5503 :
5504 0 : return WERR_OK;
5505 : }
5506 :
5507 : #if 0 /* disabled until marshalling issues are resolved - gd */
5508 : /********************************************************************
5509 : ********************************************************************/
5510 :
5511 : static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5512 : struct spoolss_DriverFileInfo *r,
5513 : const char *cservername,
5514 : const char *file_name,
5515 : enum spoolss_DriverFileType file_type,
5516 : uint32_t file_version)
5517 : {
5518 : r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5519 : cservername, file_name);
5520 : W_ERROR_HAVE_NO_MEMORY(r->file_name);
5521 : r->file_type = file_type;
5522 : r->file_version = file_version;
5523 :
5524 : return WERR_OK;
5525 : }
5526 :
5527 : /********************************************************************
5528 : ********************************************************************/
5529 :
5530 : static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5531 : const struct spoolss_DriverInfo8 *driver,
5532 : const char *cservername,
5533 : struct spoolss_DriverFileInfo **info_p,
5534 : uint32_t *count_p)
5535 : {
5536 : struct spoolss_DriverFileInfo *info = NULL;
5537 : uint32_t count = 0;
5538 : WERROR result;
5539 : uint32_t i;
5540 :
5541 : *info_p = NULL;
5542 : *count_p = 0;
5543 :
5544 : if (strlen(driver->driver_path)) {
5545 : info = talloc_realloc(mem_ctx, info,
5546 : struct spoolss_DriverFileInfo,
5547 : count + 1);
5548 : W_ERROR_HAVE_NO_MEMORY(info);
5549 : result = fill_spoolss_DriverFileInfo(info,
5550 : &info[count],
5551 : cservername,
5552 : driver->driver_path,
5553 : SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5554 : 0);
5555 : W_ERROR_NOT_OK_RETURN(result);
5556 : count++;
5557 : }
5558 :
5559 : if (strlen(driver->config_file)) {
5560 : info = talloc_realloc(mem_ctx, info,
5561 : struct spoolss_DriverFileInfo,
5562 : count + 1);
5563 : W_ERROR_HAVE_NO_MEMORY(info);
5564 : result = fill_spoolss_DriverFileInfo(info,
5565 : &info[count],
5566 : cservername,
5567 : driver->config_file,
5568 : SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5569 : 0);
5570 : W_ERROR_NOT_OK_RETURN(result);
5571 : count++;
5572 : }
5573 :
5574 : if (strlen(driver->data_file)) {
5575 : info = talloc_realloc(mem_ctx, info,
5576 : struct spoolss_DriverFileInfo,
5577 : count + 1);
5578 : W_ERROR_HAVE_NO_MEMORY(info);
5579 : result = fill_spoolss_DriverFileInfo(info,
5580 : &info[count],
5581 : cservername,
5582 : driver->data_file,
5583 : SPOOLSS_DRIVER_FILE_TYPE_DATA,
5584 : 0);
5585 : W_ERROR_NOT_OK_RETURN(result);
5586 : count++;
5587 : }
5588 :
5589 : if (strlen(driver->help_file)) {
5590 : info = talloc_realloc(mem_ctx, info,
5591 : struct spoolss_DriverFileInfo,
5592 : count + 1);
5593 : W_ERROR_HAVE_NO_MEMORY(info);
5594 : result = fill_spoolss_DriverFileInfo(info,
5595 : &info[count],
5596 : cservername,
5597 : driver->help_file,
5598 : SPOOLSS_DRIVER_FILE_TYPE_HELP,
5599 : 0);
5600 : W_ERROR_NOT_OK_RETURN(result);
5601 : count++;
5602 : }
5603 :
5604 : for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5605 : info = talloc_realloc(mem_ctx, info,
5606 : struct spoolss_DriverFileInfo,
5607 : count + 1);
5608 : W_ERROR_HAVE_NO_MEMORY(info);
5609 : result = fill_spoolss_DriverFileInfo(info,
5610 : &info[count],
5611 : cservername,
5612 : driver->dependent_files[i],
5613 : SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5614 : 0);
5615 : W_ERROR_NOT_OK_RETURN(result);
5616 : count++;
5617 : }
5618 :
5619 : *info_p = info;
5620 : *count_p = count;
5621 :
5622 : return WERR_OK;
5623 : }
5624 :
5625 : /********************************************************************
5626 : * fill a spoolss_DriverInfo101 struct
5627 : ********************************************************************/
5628 :
5629 : static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5630 : struct spoolss_DriverInfo101 *r,
5631 : const struct spoolss_DriverInfo8 *driver,
5632 : const char *servername)
5633 : {
5634 : const char *cservername = canon_servername(servername);
5635 : WERROR result;
5636 :
5637 : r->version = driver->version;
5638 :
5639 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5640 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5641 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5642 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5643 :
5644 : result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5645 : cservername,
5646 : &r->file_info,
5647 : &r->file_count);
5648 : if (!W_ERROR_IS_OK(result)) {
5649 : return result;
5650 : }
5651 :
5652 : FILL_DRIVER_STRING(mem_ctx,
5653 : driver->monitor_name,
5654 : r->monitor_name);
5655 :
5656 : FILL_DRIVER_STRING(mem_ctx,
5657 : driver->default_datatype,
5658 : r->default_datatype);
5659 :
5660 : result = string_array_from_driver_info(mem_ctx,
5661 : driver->previous_names,
5662 : &r->previous_names,
5663 : NULL, NULL, 0);
5664 : if (!W_ERROR_IS_OK(result)) {
5665 : return result;
5666 : }
5667 :
5668 : r->driver_date = driver->driver_date;
5669 : r->driver_version = driver->driver_version;
5670 :
5671 : FILL_DRIVER_STRING(mem_ctx,
5672 : driver->manufacturer_name,
5673 : r->manufacturer_name);
5674 : FILL_DRIVER_STRING(mem_ctx,
5675 : driver->manufacturer_url,
5676 : r->manufacturer_url);
5677 : FILL_DRIVER_STRING(mem_ctx,
5678 : driver->hardware_id,
5679 : r->hardware_id);
5680 : FILL_DRIVER_STRING(mem_ctx,
5681 : driver->provider,
5682 : r->provider);
5683 :
5684 : return WERR_OK;
5685 : }
5686 : #endif
5687 : /********************************************************************
5688 : ********************************************************************/
5689 :
5690 4 : static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5691 : const struct auth_session_info *session_info,
5692 : struct messaging_context *msg_ctx,
5693 : uint32_t level,
5694 : union spoolss_DriverInfo *r,
5695 : int snum,
5696 : const char *servername,
5697 : const char *architecture,
5698 : uint32_t version)
5699 : {
5700 4 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5701 : struct spoolss_DriverInfo8 *driver;
5702 : WERROR result;
5703 : struct dcerpc_binding_handle *b;
5704 4 : TALLOC_CTX *tmp_ctx = NULL;
5705 :
5706 4 : if (level == 101) {
5707 4 : return WERR_INVALID_LEVEL;
5708 : }
5709 :
5710 0 : tmp_ctx = talloc_new(mem_ctx);
5711 0 : if (!tmp_ctx) {
5712 0 : return WERR_NOT_ENOUGH_MEMORY;
5713 : }
5714 :
5715 0 : result = winreg_printer_binding_handle(tmp_ctx,
5716 : session_info,
5717 : msg_ctx,
5718 : &b);
5719 0 : if (!W_ERROR_IS_OK(result)) {
5720 0 : goto done;
5721 : }
5722 :
5723 0 : result = winreg_get_printer(tmp_ctx, b,
5724 : lp_const_servicename(snum),
5725 : &pinfo2);
5726 0 : if (!W_ERROR_IS_OK(result)) {
5727 0 : DBG_ERR("Failed to get printer info2 for [%s]: %s\n",
5728 : lp_const_servicename(snum), win_errstr(result));
5729 0 : result = WERR_INVALID_PRINTER_NAME;
5730 0 : goto done;
5731 : }
5732 :
5733 0 : if (pinfo2->drivername == NULL || pinfo2->drivername[0] == '\0') {
5734 0 : result = WERR_UNKNOWN_PRINTER_DRIVER;
5735 0 : goto done;
5736 : }
5737 :
5738 0 : DBG_INFO("Construct printer driver [%s] for [%s]\n",
5739 : pinfo2->drivername,
5740 : pinfo2->sharename);
5741 :
5742 0 : result = winreg_get_driver(tmp_ctx, b,
5743 : architecture,
5744 0 : pinfo2->drivername, version, &driver);
5745 :
5746 0 : DBG_INFO("winreg_get_driver() status: %s\n",
5747 : win_errstr(result));
5748 :
5749 0 : if (!W_ERROR_IS_OK(result)) {
5750 : /*
5751 : * Is this a W2k client ?
5752 : */
5753 :
5754 0 : if (version < 3) {
5755 0 : result = WERR_UNKNOWN_PRINTER_DRIVER;
5756 0 : goto done;
5757 : }
5758 :
5759 : /* Yes - try again with a WinNT driver. */
5760 0 : version = 2;
5761 0 : result = winreg_get_driver(tmp_ctx, b,
5762 : architecture,
5763 0 : pinfo2->drivername,
5764 : version, &driver);
5765 0 : DEBUG(8,("construct_printer_driver_level: status: %s\n",
5766 : win_errstr(result)));
5767 0 : if (!W_ERROR_IS_OK(result)) {
5768 0 : result = WERR_UNKNOWN_PRINTER_DRIVER;
5769 0 : goto done;
5770 : }
5771 : }
5772 :
5773 : /* these are allocated on mem_ctx and not tmp_ctx because they are
5774 : * the 'return value' and need to utlive this call */
5775 0 : switch (level) {
5776 0 : case 1:
5777 0 : result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5778 0 : break;
5779 0 : case 2:
5780 0 : result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5781 0 : break;
5782 0 : case 3:
5783 0 : result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5784 0 : break;
5785 0 : case 4:
5786 0 : result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5787 0 : break;
5788 0 : case 5:
5789 0 : result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5790 0 : break;
5791 0 : case 6:
5792 0 : result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5793 0 : break;
5794 0 : case 8:
5795 0 : result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5796 0 : break;
5797 : #if 0 /* disabled until marshalling issues are resolved - gd */
5798 : case 101:
5799 : result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5800 : break;
5801 : #endif
5802 0 : default:
5803 0 : result = WERR_INVALID_LEVEL;
5804 0 : break;
5805 : }
5806 :
5807 0 : done:
5808 0 : talloc_free(tmp_ctx);
5809 0 : return result;
5810 : }
5811 :
5812 : /****************************************************************
5813 : _spoolss_GetPrinterDriver2
5814 : ****************************************************************/
5815 :
5816 4 : WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5817 : struct spoolss_GetPrinterDriver2 *r)
5818 : {
5819 : struct printer_handle *printer;
5820 : WERROR result;
5821 4 : uint32_t version = r->in.client_major_version;
5822 :
5823 : int snum;
5824 :
5825 : /* that's an [in out] buffer */
5826 :
5827 4 : if (!r->in.buffer && (r->in.offered != 0)) {
5828 0 : result = WERR_INVALID_PARAMETER;
5829 0 : goto err_info_free;
5830 : }
5831 :
5832 4 : DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5833 :
5834 4 : if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5835 0 : DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5836 0 : result = WERR_INVALID_PRINTER_NAME;
5837 0 : goto err_info_free;
5838 : }
5839 :
5840 4 : *r->out.needed = 0;
5841 4 : *r->out.server_major_version = 0;
5842 4 : *r->out.server_minor_version = 0;
5843 :
5844 4 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5845 0 : result = WERR_INVALID_HANDLE;
5846 0 : goto err_info_free;
5847 : }
5848 :
5849 4 : if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
5850 0 : DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
5851 : "downgrading to v3\n"));
5852 0 : version = SPOOLSS_DRIVER_VERSION_200X;
5853 : }
5854 :
5855 4 : result = construct_printer_driver_info_level(p->mem_ctx,
5856 : get_session_info_system(),
5857 : p->msg_ctx,
5858 : r->in.level, r->out.info,
5859 : snum, printer->servername,
5860 : r->in.architecture,
5861 : version);
5862 4 : if (!W_ERROR_IS_OK(result)) {
5863 4 : goto err_info_free;
5864 : }
5865 :
5866 0 : *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5867 : r->out.info, r->in.level);
5868 0 : r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5869 :
5870 0 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5871 :
5872 4 : err_info_free:
5873 4 : TALLOC_FREE(r->out.info);
5874 4 : return result;
5875 : }
5876 :
5877 :
5878 : /****************************************************************
5879 : _spoolss_StartPagePrinter
5880 : ****************************************************************/
5881 :
5882 1920 : WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5883 : struct spoolss_StartPagePrinter *r)
5884 : {
5885 1920 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5886 :
5887 1920 : if (!Printer) {
5888 0 : DEBUG(3,("_spoolss_StartPagePrinter: "
5889 : "Error in startpageprinter printer handle\n"));
5890 0 : return WERR_INVALID_HANDLE;
5891 : }
5892 :
5893 1920 : Printer->page_started = true;
5894 1920 : return WERR_OK;
5895 : }
5896 :
5897 : /****************************************************************
5898 : _spoolss_EndPagePrinter
5899 : ****************************************************************/
5900 :
5901 1920 : WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5902 : struct spoolss_EndPagePrinter *r)
5903 : {
5904 : int snum;
5905 :
5906 1920 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5907 :
5908 1920 : if (!Printer) {
5909 0 : DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5910 : OUR_HANDLE(r->in.handle)));
5911 0 : return WERR_INVALID_HANDLE;
5912 : }
5913 :
5914 1920 : if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5915 0 : return WERR_INVALID_HANDLE;
5916 :
5917 1920 : Printer->page_started = false;
5918 1920 : print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5919 :
5920 1920 : return WERR_OK;
5921 : }
5922 :
5923 : /****************************************************************
5924 : _spoolss_StartDocPrinter
5925 : ****************************************************************/
5926 :
5927 668 : WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5928 : struct spoolss_StartDocPrinter *r)
5929 : {
5930 : struct spoolss_DocumentInfo1 *info_1;
5931 : int snum;
5932 668 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5933 : WERROR werr;
5934 : char *rhost;
5935 : int rc;
5936 :
5937 668 : if (!Printer) {
5938 0 : DEBUG(2,("_spoolss_StartDocPrinter: "
5939 : "Invalid handle (%s:%u:%u)\n",
5940 : OUR_HANDLE(r->in.handle)));
5941 0 : return WERR_INVALID_HANDLE;
5942 : }
5943 :
5944 668 : if (Printer->jobid) {
5945 0 : DEBUG(2, ("_spoolss_StartDocPrinter: "
5946 : "StartDocPrinter called twice! "
5947 : "(existing jobid = %d)\n", Printer->jobid));
5948 0 : return WERR_INVALID_HANDLE;
5949 : }
5950 :
5951 668 : if (r->in.info_ctr->level != 1) {
5952 0 : return WERR_INVALID_LEVEL;
5953 : }
5954 :
5955 668 : info_1 = r->in.info_ctr->info.info1;
5956 :
5957 : /*
5958 : * a nice thing with NT is it doesn't listen to what you tell it.
5959 : * when asked to send _only_ RAW datas, it tries to send datas
5960 : * in EMF format.
5961 : *
5962 : * So I add checks like in NT Server ...
5963 : */
5964 :
5965 668 : if (info_1->datatype) {
5966 : /*
5967 : * The v4 driver model used in Windows 8 declares print jobs
5968 : * intended to bypass the XPS processing layer by setting
5969 : * datatype to "XPS_PASS" instead of "RAW".
5970 : */
5971 668 : if ((strcmp(info_1->datatype, "RAW") != 0)
5972 224 : && (strcmp(info_1->datatype, "XPS_PASS") != 0)) {
5973 0 : *r->out.job_id = 0;
5974 0 : return WERR_INVALID_DATATYPE;
5975 : }
5976 : }
5977 :
5978 : /* get the share number of the printer */
5979 668 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5980 0 : return WERR_INVALID_HANDLE;
5981 : }
5982 :
5983 668 : rc = get_remote_hostname(p->remote_address,
5984 : &rhost,
5985 : p->mem_ctx);
5986 668 : if (rc < 0) {
5987 0 : return WERR_NOT_ENOUGH_MEMORY;
5988 : }
5989 668 : if (strequal(rhost,"UNKNOWN")) {
5990 0 : rhost = tsocket_address_inet_addr_string(p->remote_address,
5991 : p->mem_ctx);
5992 0 : if (rhost == NULL) {
5993 0 : return WERR_NOT_ENOUGH_MEMORY;
5994 : }
5995 : }
5996 :
5997 668 : werr = print_job_start(p->session_info,
5998 : p->msg_ctx,
5999 : rhost,
6000 : snum,
6001 : info_1->document_name,
6002 : info_1->output_file,
6003 : Printer->devmode,
6004 : &Printer->jobid);
6005 :
6006 : /* An error occurred in print_job_start() so return an appropriate
6007 : NT error code. */
6008 :
6009 668 : if (!W_ERROR_IS_OK(werr)) {
6010 0 : return werr;
6011 : }
6012 :
6013 668 : Printer->document_started = true;
6014 668 : *r->out.job_id = Printer->jobid;
6015 :
6016 668 : return WERR_OK;
6017 : }
6018 :
6019 : /****************************************************************
6020 : _spoolss_EndDocPrinter
6021 : ****************************************************************/
6022 :
6023 668 : WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
6024 : struct spoolss_EndDocPrinter *r)
6025 : {
6026 668 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6027 : NTSTATUS status;
6028 : int snum;
6029 :
6030 668 : if (!Printer) {
6031 0 : DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
6032 : OUR_HANDLE(r->in.handle)));
6033 0 : return WERR_INVALID_HANDLE;
6034 : }
6035 :
6036 668 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6037 0 : return WERR_INVALID_HANDLE;
6038 : }
6039 :
6040 668 : Printer->document_started = false;
6041 668 : status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
6042 664 : if (!NT_STATUS_IS_OK(status)) {
6043 288 : DEBUG(2, ("_spoolss_EndDocPrinter: "
6044 : "print_job_end failed [%s]\n",
6045 : nt_errstr(status)));
6046 : }
6047 :
6048 664 : Printer->jobid = 0;
6049 664 : return ntstatus_to_werror(status);
6050 : }
6051 :
6052 : /****************************************************************
6053 : _spoolss_WritePrinter
6054 : ****************************************************************/
6055 :
6056 1920 : WERROR _spoolss_WritePrinter(struct pipes_struct *p,
6057 : struct spoolss_WritePrinter *r)
6058 : {
6059 : ssize_t buffer_written;
6060 : int snum;
6061 1920 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6062 :
6063 1920 : if (!Printer) {
6064 0 : DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
6065 : OUR_HANDLE(r->in.handle)));
6066 0 : *r->out.num_written = r->in._data_size;
6067 0 : return WERR_INVALID_HANDLE;
6068 : }
6069 :
6070 1920 : if (!get_printer_snum(p, r->in.handle, &snum, NULL))
6071 0 : return WERR_INVALID_HANDLE;
6072 :
6073 : /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
6074 3360 : buffer_written = print_job_write(global_event_context(),p->msg_ctx,
6075 : snum, Printer->jobid,
6076 1920 : (const char *)r->in.data.data,
6077 1920 : (size_t)r->in._data_size);
6078 1920 : if (buffer_written == (ssize_t)-1) {
6079 0 : *r->out.num_written = 0;
6080 0 : if (errno == ENOSPC)
6081 0 : return WERR_NO_SPOOL_SPACE;
6082 : else
6083 0 : return WERR_ACCESS_DENIED;
6084 : }
6085 :
6086 1920 : *r->out.num_written = r->in._data_size;
6087 :
6088 1920 : return WERR_OK;
6089 : }
6090 :
6091 : /********************************************************************
6092 : * api_spoolss_getprinter
6093 : * called from the spoolss dispatcher
6094 : *
6095 : ********************************************************************/
6096 :
6097 104 : static WERROR control_printer(struct policy_handle *handle, uint32_t command,
6098 : struct pipes_struct *p)
6099 : {
6100 104 : const struct auth_session_info *session_info = p->session_info;
6101 : int snum;
6102 104 : WERROR errcode = WERR_INVALID_FUNCTION;
6103 104 : struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6104 :
6105 104 : if (!Printer) {
6106 0 : DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
6107 : OUR_HANDLE(handle)));
6108 0 : return WERR_INVALID_HANDLE;
6109 : }
6110 :
6111 104 : if (!get_printer_snum(p, handle, &snum, NULL))
6112 0 : return WERR_INVALID_HANDLE;
6113 :
6114 104 : switch (command) {
6115 52 : case SPOOLSS_PRINTER_CONTROL_PAUSE:
6116 52 : errcode = print_queue_pause(session_info, p->msg_ctx, snum);
6117 52 : break;
6118 40 : case SPOOLSS_PRINTER_CONTROL_RESUME:
6119 : case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
6120 40 : errcode = print_queue_resume(session_info, p->msg_ctx, snum);
6121 40 : break;
6122 12 : case SPOOLSS_PRINTER_CONTROL_PURGE:
6123 12 : errcode = print_queue_purge(session_info, p->msg_ctx, snum);
6124 12 : break;
6125 0 : default:
6126 0 : return WERR_INVALID_LEVEL;
6127 : }
6128 :
6129 104 : return errcode;
6130 : }
6131 :
6132 :
6133 : /****************************************************************
6134 : _spoolss_AbortPrinter
6135 : * From MSDN: "Deletes printer's spool file if printer is configured
6136 : * for spooling"
6137 : ****************************************************************/
6138 :
6139 0 : WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
6140 : struct spoolss_AbortPrinter *r)
6141 : {
6142 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6143 : int snum;
6144 0 : WERROR errcode = WERR_OK;
6145 :
6146 0 : if (!Printer) {
6147 0 : DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
6148 : OUR_HANDLE(r->in.handle)));
6149 0 : return WERR_INVALID_HANDLE;
6150 : }
6151 :
6152 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL))
6153 0 : return WERR_INVALID_HANDLE;
6154 :
6155 0 : if (!Printer->document_started) {
6156 0 : return WERR_SPL_NO_STARTDOC;
6157 : }
6158 :
6159 0 : errcode = print_job_delete(p->session_info,
6160 : p->msg_ctx,
6161 : snum,
6162 : Printer->jobid);
6163 :
6164 0 : return errcode;
6165 : }
6166 :
6167 : /********************************************************************
6168 : * called by spoolss_api_setprinter
6169 : * when updating a printer description
6170 : ********************************************************************/
6171 :
6172 120 : static WERROR update_printer_sec(struct policy_handle *handle,
6173 : struct pipes_struct *p,
6174 : struct sec_desc_buf *secdesc_ctr)
6175 : {
6176 120 : struct spoolss_security_descriptor *new_secdesc = NULL;
6177 120 : struct spoolss_security_descriptor *old_secdesc = NULL;
6178 120 : const char *printer = NULL;
6179 : WERROR result;
6180 120 : int snum = -1;
6181 120 : struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6182 : struct dcerpc_binding_handle *b;
6183 120 : TALLOC_CTX *tmp_ctx = NULL;
6184 120 : bool ok = false;
6185 :
6186 120 : if (!Printer) {
6187 0 : DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6188 : OUR_HANDLE(handle)));
6189 :
6190 0 : result = WERR_INVALID_HANDLE;
6191 0 : goto done;
6192 : }
6193 :
6194 120 : if (secdesc_ctr == NULL) {
6195 0 : DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6196 0 : result = WERR_INVALID_PARAMETER;
6197 0 : goto done;
6198 : }
6199 :
6200 120 : switch (Printer->printer_type) {
6201 8 : case SPLHND_SERVER:
6202 8 : break;
6203 112 : case SPLHND_PRINTER:
6204 112 : if (!get_printer_snum(p, handle, &snum, NULL)) {
6205 0 : DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6206 : OUR_HANDLE(handle)));
6207 0 : result = WERR_INVALID_HANDLE;
6208 0 : goto done;
6209 : }
6210 112 : printer = lp_const_servicename(snum);
6211 112 : break;
6212 0 : default:
6213 0 : break;
6214 : }
6215 :
6216 : /* Check the user has permissions to change the security
6217 : descriptor. By experimentation with two NT machines, the user
6218 : requires Full Access to the printer to change security
6219 : information. */
6220 :
6221 120 : switch (Printer->printer_type) {
6222 8 : case SPLHND_SERVER:
6223 8 : ok = Printer->access_granted == SERVER_ACCESS_ADMINISTER;
6224 8 : break;
6225 112 : case SPLHND_PRINTER:
6226 112 : ok = Printer->access_granted == PRINTER_ACCESS_ADMINISTER;
6227 112 : break;
6228 0 : default:
6229 0 : break;
6230 : }
6231 :
6232 120 : if (!ok) {
6233 0 : DEBUG(4,("update_printer_sec: updated denied by printer permissions "
6234 : "(access_granted: 0x%08x)\n", Printer->access_granted));
6235 0 : result = WERR_ACCESS_DENIED;
6236 0 : goto done;
6237 : }
6238 :
6239 120 : tmp_ctx = talloc_new(p->mem_ctx);
6240 120 : if (!tmp_ctx) {
6241 0 : return WERR_NOT_ENOUGH_MEMORY;
6242 : }
6243 :
6244 120 : result = winreg_printer_binding_handle(tmp_ctx,
6245 : get_session_info_system(),
6246 : p->msg_ctx,
6247 : &b);
6248 120 : if (!W_ERROR_IS_OK(result)) {
6249 0 : goto done;
6250 : }
6251 :
6252 : /* NT seems to like setting the security descriptor even though
6253 : nothing may have actually changed. */
6254 :
6255 120 : if (printer != NULL) {
6256 112 : result = winreg_get_printer_secdesc(tmp_ctx, b,
6257 : printer,
6258 : &old_secdesc);
6259 : } else {
6260 8 : result = winreg_get_printserver_secdesc(tmp_ctx, b,
6261 : &old_secdesc);
6262 : }
6263 120 : if (!W_ERROR_IS_OK(result)) {
6264 0 : DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6265 0 : result = WERR_INVALID_HANDLE;
6266 0 : goto done;
6267 : }
6268 :
6269 120 : if (DEBUGLEVEL >= 10) {
6270 : struct dom_sid_buf buf;
6271 : struct security_acl *the_acl;
6272 : int i;
6273 :
6274 0 : the_acl = old_secdesc->dacl;
6275 0 : DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6276 : printer, the_acl->num_aces));
6277 :
6278 0 : for (i = 0; i < the_acl->num_aces; i++) {
6279 0 : DEBUG(10, ("%s 0x%08x\n",
6280 : dom_sid_str_buf(
6281 : &the_acl->aces[i].trustee,
6282 : &buf),
6283 : the_acl->aces[i].access_mask));
6284 : }
6285 :
6286 0 : the_acl = secdesc_ctr->sd->dacl;
6287 :
6288 0 : if (the_acl) {
6289 0 : DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6290 : printer, the_acl->num_aces));
6291 :
6292 0 : for (i = 0; i < the_acl->num_aces; i++) {
6293 0 : DEBUG(10, ("%s 0x%08x\n",
6294 : dom_sid_str_buf(
6295 : &the_acl->aces[i].trustee,
6296 : &buf),
6297 : the_acl->aces[i].access_mask));
6298 : }
6299 : } else {
6300 0 : DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6301 : }
6302 : }
6303 :
6304 120 : new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6305 120 : if (new_secdesc == NULL) {
6306 0 : result = WERR_NOT_ENOUGH_MEMORY;
6307 0 : goto done;
6308 : }
6309 :
6310 120 : if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6311 56 : result = WERR_OK;
6312 56 : goto done;
6313 : }
6314 :
6315 64 : if (printer != NULL) {
6316 56 : result = winreg_set_printer_secdesc(tmp_ctx, b,
6317 : printer,
6318 : new_secdesc);
6319 : } else {
6320 8 : result = winreg_set_printserver_secdesc(tmp_ctx, b,
6321 : new_secdesc);
6322 : }
6323 :
6324 120 : done:
6325 120 : talloc_free(tmp_ctx);
6326 120 : return result;
6327 : }
6328 :
6329 : /********************************************************************
6330 : Canonicalize printer info from a client
6331 : ********************************************************************/
6332 :
6333 100 : static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6334 : struct spoolss_SetPrinterInfo2 *info2,
6335 : int snum)
6336 : {
6337 : fstring printername;
6338 : const char *p;
6339 :
6340 100 : DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6341 : "portname=%s drivername=%s comment=%s location=%s\n",
6342 : info2->servername, info2->printername, info2->sharename,
6343 : info2->portname, info2->drivername, info2->comment,
6344 : info2->location));
6345 :
6346 : /* we force some elements to "correct" values */
6347 100 : info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6348 100 : if (info2->servername == NULL) {
6349 0 : return false;
6350 : }
6351 100 : info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6352 100 : if (info2->sharename == NULL) {
6353 0 : return false;
6354 : }
6355 :
6356 : /* check to see if we allow printername != sharename */
6357 100 : if (lp_force_printername(snum)) {
6358 0 : info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6359 : lp_netbios_name(), info2->sharename);
6360 : } else {
6361 : /* make sure printername is in \\server\printername format */
6362 100 : fstrcpy(printername, info2->printername);
6363 100 : p = printername;
6364 100 : if ( printername[0] == '\\' && printername[1] == '\\' ) {
6365 56 : if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6366 56 : p++;
6367 : }
6368 :
6369 100 : info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6370 : lp_netbios_name(), p);
6371 : }
6372 100 : if (info2->printername == NULL) {
6373 0 : return false;
6374 : }
6375 :
6376 100 : info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6377 100 : info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6378 :
6379 100 : return true;
6380 : }
6381 :
6382 : /****************************************************************************
6383 : ****************************************************************************/
6384 :
6385 0 : static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6386 : {
6387 0 : const struct loadparm_substitution *lp_sub =
6388 0 : loadparm_s3_global_substitution();
6389 0 : char *cmd = lp_addport_command(talloc_tos(), lp_sub);
6390 0 : char *command = NULL;
6391 : int ret;
6392 0 : bool is_print_op = false;
6393 :
6394 0 : if ( !*cmd ) {
6395 0 : return WERR_ACCESS_DENIED;
6396 : }
6397 :
6398 0 : command = talloc_asprintf(ctx,
6399 : "%s \"%s\" \"%s\"", cmd, portname, uri );
6400 0 : if (!command) {
6401 0 : return WERR_NOT_ENOUGH_MEMORY;
6402 : }
6403 :
6404 0 : if ( token )
6405 0 : is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6406 :
6407 0 : DEBUG(10,("Running [%s]\n", command));
6408 :
6409 : /********* BEGIN SePrintOperatorPrivilege **********/
6410 :
6411 0 : if ( is_print_op )
6412 0 : become_root();
6413 :
6414 0 : ret = smbrun(command, NULL, NULL);
6415 :
6416 0 : if ( is_print_op )
6417 0 : unbecome_root();
6418 :
6419 : /********* END SePrintOperatorPrivilege **********/
6420 :
6421 0 : DEBUGADD(10,("returned [%d]\n", ret));
6422 :
6423 0 : TALLOC_FREE(command);
6424 :
6425 0 : if ( ret != 0 ) {
6426 0 : return WERR_ACCESS_DENIED;
6427 : }
6428 :
6429 0 : return WERR_OK;
6430 : }
6431 :
6432 : /****************************************************************************
6433 : ****************************************************************************/
6434 :
6435 4198 : static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6436 : int snum)
6437 : {
6438 : /*
6439 : * As we do not know if we are embedded in the file server process
6440 : * or not, we have to pretend that all shares are in use.
6441 : */
6442 4198 : return true;
6443 : }
6444 :
6445 66 : static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6446 : struct spoolss_SetPrinterInfo2 *info2,
6447 : const char *remote_machine,
6448 : struct messaging_context *msg_ctx)
6449 : {
6450 52 : const struct loadparm_substitution *lp_sub =
6451 14 : loadparm_s3_global_substitution();
6452 66 : char *cmd = lp_addprinter_command(talloc_tos(), lp_sub);
6453 : char **qlines;
6454 66 : char *command = NULL;
6455 : int numlines;
6456 : int ret;
6457 : int fd;
6458 66 : bool is_print_op = false;
6459 :
6460 66 : if (!remote_machine) {
6461 0 : return false;
6462 : }
6463 :
6464 66 : command = talloc_asprintf(ctx,
6465 : "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6466 : cmd, info2->printername, info2->sharename,
6467 : info2->portname, info2->drivername,
6468 : info2->location, info2->comment, remote_machine);
6469 66 : if (!command) {
6470 0 : return false;
6471 : }
6472 :
6473 66 : if ( token )
6474 66 : is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6475 :
6476 66 : DEBUG(10,("Running [%s]\n", command));
6477 :
6478 : /********* BEGIN SePrintOperatorPrivilege **********/
6479 :
6480 66 : if ( is_print_op )
6481 0 : become_root();
6482 :
6483 66 : ret = smbrun(command, &fd, NULL);
6484 66 : if (ret == 0) {
6485 : /* Tell everyone we updated smb.conf. */
6486 66 : messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
6487 : }
6488 :
6489 66 : if ( is_print_op )
6490 0 : unbecome_root();
6491 :
6492 : /********* END SePrintOperatorPrivilege **********/
6493 :
6494 66 : DEBUGADD(10,("returned [%d]\n", ret));
6495 :
6496 66 : TALLOC_FREE(command);
6497 :
6498 66 : if ( ret != 0 ) {
6499 0 : if (fd != -1)
6500 0 : close(fd);
6501 0 : return false;
6502 : }
6503 :
6504 : /* reload our services immediately */
6505 66 : become_root();
6506 66 : reload_services(NULL, spoolss_conn_snum_used, false);
6507 66 : unbecome_root();
6508 :
6509 66 : numlines = 0;
6510 : /* Get lines and convert them back to dos-codepage */
6511 66 : qlines = fd_lines_load(fd, &numlines, 0, NULL);
6512 66 : DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6513 66 : close(fd);
6514 :
6515 : /* Set the portname to what the script says the portname should be. */
6516 : /* but don't require anything to be return from the script exit a good error code */
6517 :
6518 66 : if (numlines) {
6519 : /* Set the portname to what the script says the portname should be. */
6520 0 : info2->portname = talloc_strdup(ctx, qlines[0]);
6521 0 : DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6522 : }
6523 :
6524 66 : TALLOC_FREE(qlines);
6525 66 : return true;
6526 : }
6527 :
6528 100 : static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6529 : const struct auth_session_info *session_info,
6530 : struct messaging_context *msg_ctx,
6531 : int snum,
6532 : struct spoolss_SetPrinterInfo2 *printer,
6533 : struct spoolss_PrinterInfo2 *old_printer)
6534 : {
6535 100 : bool force_update = (old_printer == NULL);
6536 : const char *dnsdomname;
6537 : const char *longname;
6538 : const char *uncname;
6539 : const char *spooling;
6540 : DATA_BLOB buffer;
6541 100 : WERROR result = WERR_OK;
6542 : struct dcerpc_binding_handle *b;
6543 : TALLOC_CTX *tmp_ctx;
6544 : bool ok;
6545 :
6546 100 : tmp_ctx = talloc_new(mem_ctx);
6547 100 : if (!tmp_ctx) {
6548 0 : return WERR_NOT_ENOUGH_MEMORY;
6549 : }
6550 :
6551 100 : result = winreg_printer_binding_handle(tmp_ctx,
6552 : session_info,
6553 : msg_ctx,
6554 : &b);
6555 100 : if (!W_ERROR_IS_OK(result)) {
6556 0 : goto done;
6557 : }
6558 :
6559 100 : if (printer->drivername != NULL &&
6560 84 : (force_update ||
6561 84 : !strequal(printer->drivername, old_printer->drivername))) {
6562 24 : ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6563 24 : if (!ok) {
6564 0 : DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6565 0 : result = WERR_INVALID_DATA;
6566 0 : goto done;
6567 : }
6568 24 : result = winreg_set_printer_dataex(tmp_ctx, b,
6569 : printer->sharename,
6570 : SPOOL_DSSPOOLER_KEY,
6571 : SPOOL_REG_DRIVERNAME,
6572 : REG_SZ,
6573 : buffer.data,
6574 24 : buffer.length);
6575 24 : if (!W_ERROR_IS_OK(result)) {
6576 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6577 0 : goto done;
6578 : }
6579 :
6580 24 : if (!force_update) {
6581 8 : DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6582 : printer->drivername));
6583 :
6584 8 : notify_printer_driver(global_event_context(), msg_ctx,
6585 8 : snum, printer->drivername ?
6586 : printer->drivername : "");
6587 : }
6588 : }
6589 :
6590 100 : if (printer->comment != NULL &&
6591 84 : (force_update ||
6592 84 : !strequal(printer->comment, old_printer->comment))) {
6593 34 : ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6594 34 : if (!ok) {
6595 0 : DEBUG(0, ("comment data corrupted\n"));
6596 0 : result = WERR_INVALID_DATA;
6597 0 : goto done;
6598 : }
6599 34 : result = winreg_set_printer_dataex(tmp_ctx, b,
6600 : printer->sharename,
6601 : SPOOL_DSSPOOLER_KEY,
6602 : SPOOL_REG_DESCRIPTION,
6603 : REG_SZ,
6604 : buffer.data,
6605 34 : buffer.length);
6606 34 : if (!W_ERROR_IS_OK(result)) {
6607 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6608 0 : goto done;
6609 : }
6610 :
6611 34 : if (!force_update) {
6612 34 : notify_printer_comment(global_event_context(), msg_ctx,
6613 34 : snum, printer->comment ?
6614 : printer->comment : "");
6615 : }
6616 : }
6617 :
6618 100 : if (printer->sharename != NULL &&
6619 84 : (force_update ||
6620 84 : !strequal(printer->sharename, old_printer->sharename))) {
6621 16 : ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6622 16 : if (!ok) {
6623 0 : DEBUG(0, ("sharename data corrupted\n"));
6624 0 : result = WERR_INVALID_DATA;
6625 0 : goto done;
6626 : }
6627 16 : result = winreg_set_printer_dataex(tmp_ctx, b,
6628 : printer->sharename,
6629 : SPOOL_DSSPOOLER_KEY,
6630 : SPOOL_REG_PRINTSHARENAME,
6631 : REG_SZ,
6632 : buffer.data,
6633 16 : buffer.length);
6634 16 : if (!W_ERROR_IS_OK(result)) {
6635 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6636 0 : goto done;
6637 : }
6638 :
6639 16 : if (!force_update) {
6640 0 : notify_printer_sharename(global_event_context(),
6641 : msg_ctx,
6642 0 : snum, printer->sharename ?
6643 : printer->sharename : "");
6644 : }
6645 :
6646 : /* name change, purge any cache entries for the old */
6647 16 : prune_printername_cache();
6648 : }
6649 :
6650 100 : if (printer->printername != NULL &&
6651 84 : (force_update ||
6652 84 : !strequal(printer->printername, old_printer->printername))) {
6653 : const char *p;
6654 :
6655 100 : p = strrchr(printer->printername, '\\' );
6656 100 : if (p != NULL) {
6657 100 : p++;
6658 : } else {
6659 0 : p = printer->printername;
6660 : }
6661 :
6662 100 : ok = push_reg_sz(tmp_ctx, &buffer, p);
6663 100 : if (!ok) {
6664 0 : DEBUG(0, ("printername data corrupted\n"));
6665 0 : result = WERR_INVALID_DATA;
6666 0 : goto done;
6667 : }
6668 100 : result = winreg_set_printer_dataex(tmp_ctx, b,
6669 : printer->sharename,
6670 : SPOOL_DSSPOOLER_KEY,
6671 : SPOOL_REG_PRINTERNAME,
6672 : REG_SZ,
6673 : buffer.data,
6674 100 : buffer.length);
6675 100 : if (!W_ERROR_IS_OK(result)) {
6676 0 : DBG_ERR("Failed to set %s\n", SPOOL_REG_PRINTERNAME);
6677 0 : goto done;
6678 : }
6679 :
6680 100 : if (!force_update) {
6681 84 : notify_printer_printername(global_event_context(),
6682 : msg_ctx, snum, p ? p : "");
6683 : }
6684 :
6685 : /* name change, purge any cache entries for the old */
6686 100 : prune_printername_cache();
6687 : }
6688 :
6689 100 : if (printer->portname != NULL &&
6690 84 : (force_update ||
6691 84 : !strequal(printer->portname, old_printer->portname))) {
6692 16 : ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6693 16 : if (!ok) {
6694 0 : DEBUG(0, ("portname data corrupted\n"));
6695 0 : result = WERR_INVALID_DATA;
6696 0 : goto done;
6697 : }
6698 16 : result = winreg_set_printer_dataex(tmp_ctx, b,
6699 : printer->sharename,
6700 : SPOOL_DSSPOOLER_KEY,
6701 : SPOOL_REG_PORTNAME,
6702 : REG_SZ,
6703 : buffer.data,
6704 16 : buffer.length);
6705 16 : if (!W_ERROR_IS_OK(result)) {
6706 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6707 0 : goto done;
6708 : }
6709 :
6710 16 : if (!force_update) {
6711 0 : notify_printer_port(global_event_context(),
6712 0 : msg_ctx, snum, printer->portname ?
6713 : printer->portname : "");
6714 : }
6715 : }
6716 :
6717 100 : if (printer->location != NULL &&
6718 84 : (force_update ||
6719 84 : !strequal(printer->location, old_printer->location))) {
6720 8 : ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6721 8 : if (!ok) {
6722 0 : DEBUG(0, ("location data corrupted\n"));
6723 0 : result = WERR_INVALID_DATA;
6724 0 : goto done;
6725 : }
6726 8 : result = winreg_set_printer_dataex(tmp_ctx, b,
6727 : printer->sharename,
6728 : SPOOL_DSSPOOLER_KEY,
6729 : SPOOL_REG_LOCATION,
6730 : REG_SZ,
6731 : buffer.data,
6732 8 : buffer.length);
6733 8 : if (!W_ERROR_IS_OK(result)) {
6734 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6735 0 : goto done;
6736 : }
6737 :
6738 8 : if (!force_update) {
6739 8 : notify_printer_location(global_event_context(),
6740 : msg_ctx, snum,
6741 8 : printer->location ?
6742 : printer->location : "");
6743 : }
6744 : }
6745 :
6746 100 : if (printer->sepfile != NULL &&
6747 84 : (force_update ||
6748 84 : !strequal(printer->sepfile, old_printer->sepfile))) {
6749 0 : ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6750 0 : if (!ok) {
6751 0 : DEBUG(0, ("sepfile data corrupted\n"));
6752 0 : result = WERR_INVALID_DATA;
6753 0 : goto done;
6754 : }
6755 0 : result = winreg_set_printer_dataex(tmp_ctx, b,
6756 : printer->sharename,
6757 : SPOOL_DSSPOOLER_KEY,
6758 : SPOOL_REG_PRINTSEPARATORFILE,
6759 : REG_SZ,
6760 : buffer.data,
6761 0 : buffer.length);
6762 0 : if (!W_ERROR_IS_OK(result)) {
6763 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6764 0 : goto done;
6765 : }
6766 :
6767 0 : if (!force_update) {
6768 0 : notify_printer_sepfile(global_event_context(),
6769 : msg_ctx, snum,
6770 0 : printer->sepfile ?
6771 : printer->sepfile : "");
6772 : }
6773 : }
6774 :
6775 100 : if (printer->starttime != 0 &&
6776 0 : (force_update ||
6777 0 : printer->starttime != old_printer->starttime)) {
6778 0 : buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6779 0 : SIVAL(buffer.data, 0, printer->starttime);
6780 0 : result = winreg_set_printer_dataex(tmp_ctx, b,
6781 : printer->sharename,
6782 : SPOOL_DSSPOOLER_KEY,
6783 : SPOOL_REG_PRINTSTARTTIME,
6784 : REG_DWORD,
6785 : buffer.data,
6786 0 : buffer.length);
6787 0 : if (!W_ERROR_IS_OK(result)) {
6788 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6789 0 : goto done;
6790 : }
6791 : }
6792 :
6793 100 : if (printer->untiltime != 0 &&
6794 0 : (force_update ||
6795 0 : printer->untiltime != old_printer->untiltime)) {
6796 0 : buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6797 0 : SIVAL(buffer.data, 0, printer->untiltime);
6798 0 : result = winreg_set_printer_dataex(tmp_ctx, b,
6799 : printer->sharename,
6800 : SPOOL_DSSPOOLER_KEY,
6801 : SPOOL_REG_PRINTENDTIME,
6802 : REG_DWORD,
6803 : buffer.data,
6804 0 : buffer.length);
6805 0 : if (!W_ERROR_IS_OK(result)) {
6806 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6807 0 : goto done;
6808 : }
6809 : }
6810 :
6811 100 : if (force_update || printer->priority != old_printer->priority) {
6812 16 : buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6813 16 : SIVAL(buffer.data, 0, printer->priority);
6814 16 : result = winreg_set_printer_dataex(tmp_ctx, b,
6815 : printer->sharename,
6816 : SPOOL_DSSPOOLER_KEY,
6817 : SPOOL_REG_PRIORITY,
6818 : REG_DWORD,
6819 : buffer.data,
6820 16 : buffer.length);
6821 16 : if (!W_ERROR_IS_OK(result)) {
6822 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6823 0 : goto done;
6824 : }
6825 : }
6826 :
6827 100 : if (force_update || printer->attributes != old_printer->attributes) {
6828 16 : buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6829 16 : SIVAL(buffer.data, 0, (printer->attributes &
6830 : PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6831 16 : result = winreg_set_printer_dataex(tmp_ctx, b,
6832 : printer->sharename,
6833 : SPOOL_DSSPOOLER_KEY,
6834 : SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6835 : REG_DWORD,
6836 : buffer.data,
6837 16 : buffer.length);
6838 16 : if (!W_ERROR_IS_OK(result)) {
6839 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6840 0 : goto done;
6841 : }
6842 :
6843 16 : switch (printer->attributes & 0x3) {
6844 16 : case 0:
6845 16 : spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6846 16 : break;
6847 0 : case 1:
6848 0 : spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6849 0 : break;
6850 0 : case 2:
6851 0 : spooling = SPOOL_REGVAL_PRINTDIRECT;
6852 0 : break;
6853 0 : default:
6854 0 : spooling = "unknown";
6855 : }
6856 16 : ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6857 16 : if (!ok) {
6858 0 : DEBUG(0, ("printSpooling data corrupted\n"));
6859 0 : result = WERR_INVALID_DATA;
6860 0 : goto done;
6861 : }
6862 16 : winreg_set_printer_dataex(tmp_ctx, b,
6863 : printer->sharename,
6864 : SPOOL_DSSPOOLER_KEY,
6865 : SPOOL_REG_PRINTSPOOLING,
6866 : REG_SZ,
6867 : buffer.data,
6868 16 : buffer.length);
6869 : }
6870 :
6871 100 : ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6872 100 : if (!ok) {
6873 0 : DEBUG(0, ("shortServerName data corrupted\n"));
6874 0 : result = WERR_INVALID_DATA;
6875 0 : goto done;
6876 : }
6877 100 : result = winreg_set_printer_dataex(tmp_ctx, b,
6878 : printer->sharename,
6879 : SPOOL_DSSPOOLER_KEY,
6880 : SPOOL_REG_SHORTSERVERNAME,
6881 : REG_SZ,
6882 : buffer.data,
6883 100 : buffer.length);
6884 100 : if (!W_ERROR_IS_OK(result)) {
6885 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6886 0 : goto done;
6887 : }
6888 :
6889 100 : dnsdomname = get_mydnsfullname();
6890 100 : if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6891 100 : longname = talloc_strdup(tmp_ctx, dnsdomname);
6892 : } else {
6893 0 : longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6894 : }
6895 100 : if (longname == NULL) {
6896 0 : result = WERR_NOT_ENOUGH_MEMORY;
6897 0 : goto done;
6898 : }
6899 :
6900 100 : ok = push_reg_sz(tmp_ctx, &buffer, longname);
6901 100 : if (!ok) {
6902 0 : DEBUG(0, ("longname data corrupted\n"));
6903 0 : result = WERR_INVALID_DATA;
6904 0 : goto done;
6905 : }
6906 100 : result = winreg_set_printer_dataex(tmp_ctx, b,
6907 : printer->sharename,
6908 : SPOOL_DSSPOOLER_KEY,
6909 : SPOOL_REG_SERVERNAME,
6910 : REG_SZ,
6911 : buffer.data,
6912 100 : buffer.length);
6913 100 : if (!W_ERROR_IS_OK(result)) {
6914 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6915 0 : goto done;
6916 : }
6917 :
6918 100 : uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6919 : lp_netbios_name(), printer->sharename);
6920 100 : ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6921 100 : if (!ok) {
6922 0 : DEBUG(0, ("uncName data corrupted\n"));
6923 0 : result = WERR_INVALID_DATA;
6924 0 : goto done;
6925 : }
6926 100 : result = winreg_set_printer_dataex(tmp_ctx, b,
6927 : printer->sharename,
6928 : SPOOL_DSSPOOLER_KEY,
6929 : SPOOL_REG_UNCNAME,
6930 : REG_SZ,
6931 : buffer.data,
6932 100 : buffer.length);
6933 100 : if (!W_ERROR_IS_OK(result)) {
6934 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6935 0 : goto done;
6936 : }
6937 :
6938 175 : done:
6939 100 : talloc_free(tmp_ctx);
6940 100 : return result;
6941 : }
6942 :
6943 : /********************************************************************
6944 : * Called by spoolss_api_setprinter
6945 : * when updating a printer description.
6946 : ********************************************************************/
6947 :
6948 84 : static WERROR update_printer(struct pipes_struct *p,
6949 : struct policy_handle *handle,
6950 : struct spoolss_SetPrinterInfoCtr *info_ctr,
6951 : struct spoolss_DeviceMode *devmode)
6952 : {
6953 84 : uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6954 84 : struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6955 : struct spoolss_PrinterInfo2 *old_printer;
6956 84 : struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6957 63 : const struct loadparm_substitution *lp_sub =
6958 21 : loadparm_s3_global_substitution();
6959 : int snum;
6960 84 : WERROR result = WERR_OK;
6961 : TALLOC_CTX *tmp_ctx;
6962 : struct dcerpc_binding_handle *b;
6963 :
6964 84 : DEBUG(8,("update_printer\n"));
6965 :
6966 84 : tmp_ctx = talloc_new(p->mem_ctx);
6967 84 : if (tmp_ctx == NULL) {
6968 0 : return WERR_NOT_ENOUGH_MEMORY;
6969 : }
6970 :
6971 84 : if (!Printer) {
6972 0 : result = WERR_INVALID_HANDLE;
6973 0 : goto done;
6974 : }
6975 :
6976 84 : if (!get_printer_snum(p, handle, &snum, NULL)) {
6977 0 : result = WERR_INVALID_HANDLE;
6978 0 : goto done;
6979 : }
6980 :
6981 84 : result = winreg_printer_binding_handle(tmp_ctx,
6982 : get_session_info_system(),
6983 : p->msg_ctx,
6984 : &b);
6985 84 : if (!W_ERROR_IS_OK(result)) {
6986 0 : goto done;
6987 : }
6988 :
6989 84 : result = winreg_get_printer(tmp_ctx, b,
6990 : lp_const_servicename(snum),
6991 : &old_printer);
6992 84 : if (!W_ERROR_IS_OK(result)) {
6993 0 : result = WERR_INVALID_HANDLE;
6994 0 : goto done;
6995 : }
6996 :
6997 : /* Do sanity check on the requested changes for Samba */
6998 84 : if (!check_printer_ok(tmp_ctx, printer, snum)) {
6999 0 : result = WERR_INVALID_PARAMETER;
7000 0 : goto done;
7001 : }
7002 :
7003 : /* FIXME!!! If the driver has changed we really should verify that
7004 : it is installed before doing much else --jerry */
7005 :
7006 : /* Check calling user has permission to update printer description */
7007 84 : if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7008 0 : DEBUG(3, ("update_printer: printer property change denied by handle\n"));
7009 0 : result = WERR_ACCESS_DENIED;
7010 0 : goto done;
7011 : }
7012 :
7013 : /* Call addprinter hook */
7014 : /* Check changes to see if this is really needed */
7015 :
7016 147 : if (*lp_addprinter_command(talloc_tos(), lp_sub) &&
7017 141 : (!strequal(printer->drivername, old_printer->drivername) ||
7018 105 : !strequal(printer->comment, old_printer->comment) ||
7019 71 : !strequal(printer->portname, old_printer->portname) ||
7020 42 : !strequal(printer->location, old_printer->location)) )
7021 : {
7022 : char *raddr;
7023 :
7024 50 : raddr = tsocket_address_inet_addr_string(p->remote_address,
7025 : p->mem_ctx);
7026 50 : if (raddr == NULL) {
7027 0 : result = WERR_NOT_ENOUGH_MEMORY;
7028 0 : goto done;
7029 : }
7030 :
7031 : /* add_printer_hook() will call reload_services() */
7032 50 : if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
7033 : printer, raddr,
7034 : p->msg_ctx)) {
7035 0 : result = WERR_ACCESS_DENIED;
7036 0 : goto done;
7037 : }
7038 : }
7039 :
7040 84 : result = update_dsspooler(tmp_ctx,
7041 : get_session_info_system(),
7042 : p->msg_ctx,
7043 : snum,
7044 : printer,
7045 : old_printer);
7046 84 : if (!W_ERROR_IS_OK(result)) {
7047 0 : goto done;
7048 : }
7049 :
7050 84 : printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
7051 :
7052 84 : if (devmode == NULL) {
7053 76 : printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
7054 : }
7055 84 : result = winreg_update_printer(tmp_ctx, b,
7056 : printer->sharename,
7057 : printer_mask,
7058 : printer,
7059 : devmode,
7060 : NULL);
7061 :
7062 84 : done:
7063 84 : talloc_free(tmp_ctx);
7064 :
7065 84 : return result;
7066 : }
7067 :
7068 : /****************************************************************************
7069 : ****************************************************************************/
7070 8 : static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
7071 : struct policy_handle *handle,
7072 : struct spoolss_SetPrinterInfo7 *info7)
7073 : {
7074 : #ifdef HAVE_ADS
7075 4 : const struct loadparm_substitution *lp_sub =
7076 2 : loadparm_s3_global_substitution();
7077 6 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7078 : WERROR result;
7079 : int snum;
7080 : struct printer_handle *Printer;
7081 :
7082 6 : if ( lp_security() != SEC_ADS ) {
7083 6 : return WERR_INVALID_LEVEL;
7084 : }
7085 :
7086 0 : Printer = find_printer_index_by_hnd(p, handle);
7087 :
7088 0 : DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
7089 :
7090 0 : if (!Printer)
7091 0 : return WERR_INVALID_HANDLE;
7092 :
7093 0 : if (!get_printer_snum(p, handle, &snum, NULL))
7094 0 : return WERR_INVALID_HANDLE;
7095 :
7096 0 : result = winreg_get_printer_internal(p->mem_ctx,
7097 : get_session_info_system(),
7098 : p->msg_ctx,
7099 0 : lp_servicename(talloc_tos(), lp_sub, snum),
7100 : &pinfo2);
7101 0 : if (!W_ERROR_IS_OK(result)) {
7102 0 : return WERR_INVALID_HANDLE;
7103 : }
7104 :
7105 0 : nt_printer_publish(pinfo2,
7106 : get_session_info_system(),
7107 : p->msg_ctx,
7108 : pinfo2,
7109 0 : info7->action);
7110 :
7111 0 : TALLOC_FREE(pinfo2);
7112 0 : return WERR_OK;
7113 : #else
7114 2 : return WERR_INVALID_LEVEL;
7115 : #endif
7116 : }
7117 :
7118 : /********************************************************************
7119 : ********************************************************************/
7120 :
7121 296 : static WERROR update_printer_devmode(struct pipes_struct *p,
7122 : struct policy_handle *handle,
7123 : struct spoolss_DeviceMode *devmode)
7124 : {
7125 : int snum;
7126 296 : struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
7127 296 : uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
7128 :
7129 296 : DEBUG(8,("update_printer_devmode\n"));
7130 :
7131 296 : if (!Printer) {
7132 0 : return WERR_INVALID_HANDLE;
7133 : }
7134 :
7135 296 : if (!get_printer_snum(p, handle, &snum, NULL)) {
7136 0 : return WERR_INVALID_HANDLE;
7137 : }
7138 :
7139 : /* Check calling user has permission to update printer description */
7140 296 : if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7141 0 : DEBUG(3, ("update_printer: printer property change denied by handle\n"));
7142 0 : return WERR_ACCESS_DENIED;
7143 : }
7144 :
7145 296 : return winreg_update_printer_internal(p->mem_ctx,
7146 : get_session_info_system(),
7147 : p->msg_ctx,
7148 : lp_const_servicename(snum),
7149 : info2_mask,
7150 : NULL,
7151 : devmode,
7152 : NULL);
7153 : }
7154 :
7155 :
7156 : /****************************************************************
7157 : _spoolss_SetPrinter
7158 : ****************************************************************/
7159 :
7160 584 : WERROR _spoolss_SetPrinter(struct pipes_struct *p,
7161 : struct spoolss_SetPrinter *r)
7162 : {
7163 : WERROR result;
7164 :
7165 584 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7166 :
7167 584 : if (!Printer) {
7168 0 : DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
7169 : OUR_HANDLE(r->in.handle)));
7170 0 : return WERR_INVALID_HANDLE;
7171 : }
7172 :
7173 : /* check the level */
7174 584 : switch (r->in.info_ctr->level) {
7175 104 : case 0:
7176 104 : return control_printer(r->in.handle, r->in.command, p);
7177 84 : case 2:
7178 84 : result = update_printer(p, r->in.handle,
7179 : r->in.info_ctr,
7180 84 : r->in.devmode_ctr->devmode);
7181 84 : if (!W_ERROR_IS_OK(result))
7182 0 : return result;
7183 84 : if (r->in.secdesc_ctr->sd)
7184 28 : result = update_printer_sec(r->in.handle, p,
7185 : r->in.secdesc_ctr);
7186 84 : return result;
7187 92 : case 3:
7188 92 : return update_printer_sec(r->in.handle, p,
7189 : r->in.secdesc_ctr);
7190 0 : case 4: {
7191 : struct spoolss_PrinterInfo2 *old_printer;
7192 : struct spoolss_SetPrinterInfo2 *set_old_printer;
7193 : struct spoolss_SetPrinterInfoCtr *info_ctr;
7194 : struct dcerpc_binding_handle *b;
7195 : int snum;
7196 : TALLOC_CTX *tmp_ctx;
7197 :
7198 0 : tmp_ctx = talloc_new(p->mem_ctx);
7199 0 : if (tmp_ctx == NULL) {
7200 0 : return WERR_NOT_ENOUGH_MEMORY;
7201 : }
7202 :
7203 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7204 0 : TALLOC_FREE(tmp_ctx);
7205 0 : return WERR_INVALID_HANDLE;
7206 : }
7207 :
7208 0 : result = winreg_printer_binding_handle(tmp_ctx,
7209 : get_session_info_system(),
7210 : p->msg_ctx,
7211 : &b);
7212 0 : if (!W_ERROR_IS_OK(result)) {
7213 0 : TALLOC_FREE(tmp_ctx);
7214 0 : return result;
7215 : }
7216 :
7217 0 : result = winreg_get_printer(tmp_ctx, b,
7218 : lp_const_servicename(snum),
7219 : &old_printer);
7220 0 : if (!W_ERROR_IS_OK(result)) {
7221 0 : TALLOC_FREE(tmp_ctx);
7222 0 : return WERR_INVALID_HANDLE;
7223 : }
7224 :
7225 0 : old_printer->servername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->servername);
7226 0 : if (old_printer->servername == NULL) {
7227 0 : TALLOC_FREE(tmp_ctx);
7228 0 : return WERR_NOT_ENOUGH_MEMORY;
7229 : }
7230 :
7231 0 : old_printer->printername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->printername);
7232 0 : if (old_printer->printername == NULL) {
7233 0 : TALLOC_FREE(tmp_ctx);
7234 0 : return WERR_NOT_ENOUGH_MEMORY;
7235 : }
7236 :
7237 0 : old_printer->attributes = r->in.info_ctr->info.info4->attributes;
7238 :
7239 0 : set_old_printer = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfo2);
7240 0 : if (set_old_printer == NULL) {
7241 0 : TALLOC_FREE(tmp_ctx);
7242 0 : return WERR_NOT_ENOUGH_MEMORY;
7243 : }
7244 :
7245 0 : spoolss_printerinfo2_to_setprinterinfo2(old_printer, set_old_printer);
7246 :
7247 0 : info_ctr = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfoCtr);
7248 0 : if (info_ctr == NULL) {
7249 0 : TALLOC_FREE(tmp_ctx);
7250 0 : return WERR_NOT_ENOUGH_MEMORY;
7251 : }
7252 :
7253 0 : info_ctr->level = 2;
7254 0 : info_ctr->info.info2 = set_old_printer;
7255 :
7256 0 : result = update_printer(p, r->in.handle,
7257 : info_ctr,
7258 0 : r->in.devmode_ctr->devmode);
7259 :
7260 0 : if (!W_ERROR_IS_OK(result)) {
7261 0 : TALLOC_FREE(tmp_ctx);
7262 0 : return result;
7263 : }
7264 :
7265 0 : if (r->in.secdesc_ctr->sd) {
7266 0 : result = update_printer_sec(r->in.handle, p,
7267 : r->in.secdesc_ctr);
7268 : }
7269 :
7270 0 : TALLOC_FREE(tmp_ctx);
7271 0 : return result;
7272 : }
7273 8 : case 7:
7274 8 : return publish_or_unpublish_printer(p, r->in.handle,
7275 8 : r->in.info_ctr->info.info7);
7276 296 : case 8:
7277 296 : return update_printer_devmode(p, r->in.handle,
7278 296 : r->in.devmode_ctr->devmode);
7279 0 : default:
7280 0 : return WERR_INVALID_LEVEL;
7281 : }
7282 : }
7283 :
7284 : /****************************************************************
7285 : _spoolss_FindClosePrinterNotify
7286 : ****************************************************************/
7287 :
7288 0 : WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
7289 : struct spoolss_FindClosePrinterNotify *r)
7290 : {
7291 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7292 :
7293 0 : if (!Printer) {
7294 0 : DEBUG(2,("_spoolss_FindClosePrinterNotify: "
7295 : "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
7296 0 : return WERR_INVALID_HANDLE;
7297 : }
7298 :
7299 0 : if (Printer->notify.cli_chan != NULL &&
7300 0 : Printer->notify.cli_chan->active_connections > 0) {
7301 0 : int snum = -1;
7302 :
7303 0 : if (Printer->printer_type == SPLHND_PRINTER) {
7304 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7305 0 : return WERR_INVALID_HANDLE;
7306 : }
7307 : }
7308 :
7309 0 : srv_spoolss_replycloseprinter(snum, Printer);
7310 : }
7311 :
7312 0 : Printer->notify.flags=0;
7313 0 : Printer->notify.options=0;
7314 0 : Printer->notify.localmachine[0]='\0';
7315 0 : Printer->notify.printerlocal=0;
7316 0 : TALLOC_FREE(Printer->notify.option);
7317 :
7318 0 : return WERR_OK;
7319 : }
7320 :
7321 : /****************************************************************
7322 : _spoolss_AddJob
7323 : ****************************************************************/
7324 :
7325 16 : WERROR _spoolss_AddJob(struct pipes_struct *p,
7326 : struct spoolss_AddJob *r)
7327 : {
7328 16 : if (!r->in.buffer && (r->in.offered != 0)) {
7329 0 : return WERR_INVALID_PARAMETER;
7330 : }
7331 :
7332 : /* this is what a NT server returns for AddJob. AddJob must fail on
7333 : * non-local printers */
7334 :
7335 16 : if (r->in.level != 1) {
7336 8 : return WERR_INVALID_LEVEL;
7337 : }
7338 :
7339 8 : return WERR_INVALID_PARAMETER;
7340 : }
7341 :
7342 : /****************************************************************************
7343 : fill_job_info1
7344 : ****************************************************************************/
7345 :
7346 320 : static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
7347 : struct spoolss_JobInfo1 *r,
7348 : const print_queue_struct *queue,
7349 : uint32_t jobid,
7350 : int position, int snum,
7351 : struct spoolss_PrinterInfo2 *pinfo2)
7352 : {
7353 160 : const struct loadparm_substitution *lp_sub =
7354 160 : loadparm_s3_global_substitution();
7355 : struct tm *t;
7356 :
7357 320 : t = gmtime(&queue->time);
7358 :
7359 320 : r->job_id = jobid;
7360 :
7361 320 : r->printer_name = lp_servicename(mem_ctx, lp_sub, snum);
7362 320 : W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7363 320 : r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
7364 320 : W_ERROR_HAVE_NO_MEMORY(r->server_name);
7365 320 : r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
7366 320 : W_ERROR_HAVE_NO_MEMORY(r->user_name);
7367 320 : r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
7368 320 : W_ERROR_HAVE_NO_MEMORY(r->document_name);
7369 320 : r->data_type = talloc_strdup(mem_ctx, "RAW");
7370 320 : W_ERROR_HAVE_NO_MEMORY(r->data_type);
7371 320 : r->text_status = talloc_strdup(mem_ctx, "");
7372 320 : W_ERROR_HAVE_NO_MEMORY(r->text_status);
7373 :
7374 320 : r->status = nt_printj_status(queue->status);
7375 320 : r->priority = queue->priority;
7376 320 : r->position = position;
7377 320 : r->total_pages = queue->page_count;
7378 320 : r->pages_printed = 0; /* ??? */
7379 :
7380 320 : init_systemtime(&r->submitted, t);
7381 :
7382 320 : return WERR_OK;
7383 : }
7384 :
7385 : /****************************************************************************
7386 : fill_job_info2
7387 : ****************************************************************************/
7388 :
7389 64 : static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7390 : struct spoolss_JobInfo2 *r,
7391 : const print_queue_struct *queue,
7392 : uint32_t jobid,
7393 : int position, int snum,
7394 : struct spoolss_PrinterInfo2 *pinfo2,
7395 : struct spoolss_DeviceMode *devmode)
7396 : {
7397 32 : const struct loadparm_substitution *lp_sub =
7398 32 : loadparm_s3_global_substitution();
7399 : struct tm *t;
7400 :
7401 64 : t = gmtime(&queue->time);
7402 :
7403 64 : r->job_id = jobid;
7404 :
7405 64 : r->printer_name = lp_servicename(mem_ctx, lp_sub, snum);
7406 64 : W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7407 64 : r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
7408 64 : W_ERROR_HAVE_NO_MEMORY(r->server_name);
7409 64 : r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
7410 64 : W_ERROR_HAVE_NO_MEMORY(r->user_name);
7411 64 : r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
7412 64 : W_ERROR_HAVE_NO_MEMORY(r->document_name);
7413 64 : r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
7414 64 : W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7415 64 : r->data_type = talloc_strdup(mem_ctx, "RAW");
7416 64 : W_ERROR_HAVE_NO_MEMORY(r->data_type);
7417 64 : r->print_processor = talloc_strdup(mem_ctx, "winprint");
7418 64 : W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7419 64 : r->parameters = talloc_strdup(mem_ctx, "");
7420 64 : W_ERROR_HAVE_NO_MEMORY(r->parameters);
7421 64 : r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
7422 64 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7423 :
7424 64 : r->devmode = devmode;
7425 :
7426 64 : r->text_status = talloc_strdup(mem_ctx, "");
7427 64 : W_ERROR_HAVE_NO_MEMORY(r->text_status);
7428 :
7429 64 : r->secdesc = NULL;
7430 :
7431 64 : r->status = nt_printj_status(queue->status);
7432 64 : r->priority = queue->priority;
7433 64 : r->position = position;
7434 64 : r->start_time = 0;
7435 64 : r->until_time = 0;
7436 64 : r->total_pages = queue->page_count;
7437 64 : r->size = queue->size;
7438 64 : init_systemtime(&r->submitted, t);
7439 64 : r->time = 0;
7440 64 : r->pages_printed = 0; /* ??? */
7441 :
7442 64 : return WERR_OK;
7443 : }
7444 :
7445 : /****************************************************************************
7446 : Enumjobs at level 1.
7447 : ****************************************************************************/
7448 :
7449 24 : static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7450 : const print_queue_struct *queue,
7451 : uint32_t num_queues, int snum,
7452 : struct spoolss_PrinterInfo2 *pinfo2,
7453 : union spoolss_JobInfo **info_p,
7454 : uint32_t *count)
7455 : {
7456 : union spoolss_JobInfo *info;
7457 : int i;
7458 24 : WERROR result = WERR_OK;
7459 : uint32_t num_filled;
7460 : struct tdb_print_db *pdb;
7461 :
7462 24 : info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7463 24 : if (info == NULL) {
7464 0 : result = WERR_NOT_ENOUGH_MEMORY;
7465 0 : goto err_out;
7466 : }
7467 :
7468 24 : pdb = get_print_db_byname(pinfo2->sharename);
7469 24 : if (pdb == NULL) {
7470 0 : result = WERR_INVALID_PARAMETER;
7471 0 : goto err_info_free;
7472 : }
7473 :
7474 24 : num_filled = 0;
7475 216 : for (i = 0; i < num_queues; i++) {
7476 192 : uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7477 192 : if (jobid == (uint32_t)-1) {
7478 0 : DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7479 0 : continue;
7480 : }
7481 :
7482 288 : result = fill_job_info1(info,
7483 192 : &info[num_filled].info1,
7484 192 : &queue[i],
7485 : jobid,
7486 : i,
7487 : snum,
7488 : pinfo2);
7489 192 : if (!W_ERROR_IS_OK(result)) {
7490 0 : goto err_pdb_drop;
7491 : }
7492 :
7493 192 : num_filled++;
7494 : }
7495 :
7496 24 : release_print_db(pdb);
7497 24 : *info_p = info;
7498 24 : *count = num_filled;
7499 :
7500 24 : return WERR_OK;
7501 :
7502 0 : err_pdb_drop:
7503 0 : release_print_db(pdb);
7504 0 : err_info_free:
7505 0 : TALLOC_FREE(info);
7506 0 : err_out:
7507 0 : *count = 0;
7508 0 : return result;
7509 : }
7510 :
7511 : /****************************************************************************
7512 : Enumjobs at level 2.
7513 : ****************************************************************************/
7514 :
7515 8 : static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7516 : const print_queue_struct *queue,
7517 : uint32_t num_queues, int snum,
7518 : struct spoolss_PrinterInfo2 *pinfo2,
7519 : union spoolss_JobInfo **info_p,
7520 : uint32_t *count)
7521 : {
7522 : union spoolss_JobInfo *info;
7523 : int i;
7524 8 : WERROR result = WERR_OK;
7525 : uint32_t num_filled;
7526 : struct tdb_print_db *pdb;
7527 :
7528 8 : info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7529 8 : if (info == NULL) {
7530 0 : result = WERR_NOT_ENOUGH_MEMORY;
7531 0 : goto err_out;
7532 : }
7533 :
7534 8 : pdb = get_print_db_byname(pinfo2->sharename);
7535 8 : if (pdb == NULL) {
7536 0 : result = WERR_INVALID_PARAMETER;
7537 0 : goto err_info_free;
7538 : }
7539 :
7540 8 : num_filled = 0;
7541 72 : for (i = 0; i< num_queues; i++) {
7542 : struct spoolss_DeviceMode *devmode;
7543 64 : uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7544 64 : if (jobid == (uint32_t)-1) {
7545 0 : DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7546 0 : continue;
7547 : }
7548 :
7549 64 : result = spoolss_create_default_devmode(info,
7550 : pinfo2->printername,
7551 : &devmode);
7552 64 : if (!W_ERROR_IS_OK(result)) {
7553 0 : DEBUG(3, ("Can't proceed w/o a devmode!"));
7554 0 : goto err_pdb_drop;
7555 : }
7556 :
7557 128 : result = fill_job_info2(info,
7558 64 : &info[num_filled].info2,
7559 64 : &queue[i],
7560 : jobid,
7561 : i,
7562 : snum,
7563 : pinfo2,
7564 : devmode);
7565 64 : if (!W_ERROR_IS_OK(result)) {
7566 0 : goto err_pdb_drop;
7567 : }
7568 64 : num_filled++;
7569 : }
7570 :
7571 8 : release_print_db(pdb);
7572 8 : *info_p = info;
7573 8 : *count = num_filled;
7574 :
7575 8 : return WERR_OK;
7576 :
7577 0 : err_pdb_drop:
7578 0 : release_print_db(pdb);
7579 0 : err_info_free:
7580 0 : TALLOC_FREE(info);
7581 0 : err_out:
7582 0 : *count = 0;
7583 0 : return result;
7584 : }
7585 :
7586 : /****************************************************************************
7587 : Enumjobs at level 3.
7588 : ****************************************************************************/
7589 :
7590 0 : static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7591 : const print_queue_struct *queue,
7592 : uint32_t num_queues, int snum,
7593 : struct spoolss_PrinterInfo2 *pinfo2,
7594 : union spoolss_JobInfo **info_p,
7595 : uint32_t *count)
7596 : {
7597 : union spoolss_JobInfo *info;
7598 : int i;
7599 0 : WERROR result = WERR_OK;
7600 : uint32_t num_filled;
7601 : struct tdb_print_db *pdb;
7602 :
7603 0 : info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7604 0 : if (info == NULL) {
7605 0 : result = WERR_NOT_ENOUGH_MEMORY;
7606 0 : goto err_out;
7607 : }
7608 :
7609 0 : pdb = get_print_db_byname(pinfo2->sharename);
7610 0 : if (pdb == NULL) {
7611 0 : result = WERR_INVALID_PARAMETER;
7612 0 : goto err_info_free;
7613 : }
7614 :
7615 0 : num_filled = 0;
7616 0 : for (i = 0; i < num_queues; i++) {
7617 0 : uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7618 0 : if (jobid == (uint32_t)-1) {
7619 0 : DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7620 0 : continue;
7621 : }
7622 :
7623 0 : info[num_filled].info3.job_id = jobid;
7624 : /* next_job_id is overwritten on next iteration */
7625 0 : info[num_filled].info3.next_job_id = 0;
7626 0 : info[num_filled].info3.reserved = 0;
7627 :
7628 0 : if (num_filled > 0) {
7629 0 : info[num_filled - 1].info3.next_job_id = jobid;
7630 : }
7631 0 : num_filled++;
7632 : }
7633 :
7634 0 : release_print_db(pdb);
7635 0 : *info_p = info;
7636 0 : *count = num_filled;
7637 :
7638 0 : return WERR_OK;
7639 :
7640 0 : err_info_free:
7641 0 : TALLOC_FREE(info);
7642 0 : err_out:
7643 0 : *count = 0;
7644 0 : return result;
7645 : }
7646 :
7647 : /****************************************************************
7648 : _spoolss_EnumJobs
7649 : ****************************************************************/
7650 :
7651 88 : WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7652 : struct spoolss_EnumJobs *r)
7653 : {
7654 : WERROR result;
7655 88 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7656 : int snum;
7657 : print_status_struct prt_status;
7658 88 : print_queue_struct *queue = NULL;
7659 : uint32_t count;
7660 :
7661 : /* that's an [in out] buffer */
7662 :
7663 88 : if (!r->in.buffer && (r->in.offered != 0)) {
7664 0 : return WERR_INVALID_PARAMETER;
7665 : }
7666 :
7667 88 : if ((r->in.level != 1) && (r->in.level != 2) && (r->in.level != 3)) {
7668 12 : DEBUG(4, ("EnumJobs level %d not supported\n", r->in.level));
7669 12 : return WERR_INVALID_LEVEL;
7670 : }
7671 :
7672 76 : DEBUG(4,("_spoolss_EnumJobs\n"));
7673 :
7674 76 : *r->out.needed = 0;
7675 76 : *r->out.count = 0;
7676 76 : *r->out.info = NULL;
7677 :
7678 : /* lookup the printer snum and tdb entry */
7679 :
7680 76 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7681 0 : return WERR_INVALID_HANDLE;
7682 : }
7683 :
7684 76 : result = winreg_get_printer_internal(p->mem_ctx,
7685 : get_session_info_system(),
7686 : p->msg_ctx,
7687 : lp_const_servicename(snum),
7688 : &pinfo2);
7689 76 : if (!W_ERROR_IS_OK(result)) {
7690 0 : return result;
7691 : }
7692 :
7693 76 : count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7694 76 : DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7695 : count, prt_status.status, prt_status.message));
7696 :
7697 76 : if (count == 0) {
7698 44 : SAFE_FREE(queue);
7699 44 : TALLOC_FREE(pinfo2);
7700 44 : return WERR_OK;
7701 : }
7702 :
7703 32 : switch (r->in.level) {
7704 24 : case 1:
7705 24 : result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7706 : pinfo2, r->out.info, r->out.count);
7707 24 : break;
7708 8 : case 2:
7709 8 : result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7710 : pinfo2, r->out.info, r->out.count);
7711 8 : break;
7712 0 : case 3:
7713 0 : result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7714 : pinfo2, r->out.info, r->out.count);
7715 0 : break;
7716 0 : default:
7717 0 : SMB_ASSERT(false); /* level checked on entry */
7718 : break;
7719 : }
7720 :
7721 32 : SAFE_FREE(queue);
7722 32 : TALLOC_FREE(pinfo2);
7723 :
7724 32 : if (!W_ERROR_IS_OK(result)) {
7725 0 : return result;
7726 : }
7727 :
7728 32 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7729 : spoolss_EnumJobs,
7730 : *r->out.info, r->in.level,
7731 : *r->out.count);
7732 32 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7733 32 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7734 :
7735 32 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7736 : }
7737 :
7738 : /****************************************************************
7739 : _spoolss_ScheduleJob
7740 : ****************************************************************/
7741 :
7742 0 : WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7743 : struct spoolss_ScheduleJob *r)
7744 : {
7745 0 : return WERR_OK;
7746 : }
7747 :
7748 : /****************************************************************
7749 : ****************************************************************/
7750 :
7751 32 : static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7752 : struct messaging_context *msg_ctx,
7753 : const char *printer_name,
7754 : uint32_t job_id,
7755 : struct spoolss_SetJobInfo1 *r)
7756 : {
7757 : char *old_doc_name;
7758 :
7759 32 : if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7760 0 : return WERR_INVALID_HANDLE;
7761 : }
7762 :
7763 32 : if (strequal(old_doc_name, r->document_name)) {
7764 0 : return WERR_OK;
7765 : }
7766 :
7767 32 : if (!print_job_set_name(global_event_context(), msg_ctx,
7768 : printer_name, job_id, r->document_name)) {
7769 0 : return WERR_INVALID_HANDLE;
7770 : }
7771 :
7772 32 : return WERR_OK;
7773 : }
7774 :
7775 : /****************************************************************
7776 : _spoolss_SetJob
7777 : ****************************************************************/
7778 :
7779 640 : WERROR _spoolss_SetJob(struct pipes_struct *p,
7780 : struct spoolss_SetJob *r)
7781 : {
7782 640 : const struct auth_session_info *session_info = p->session_info;
7783 : int snum;
7784 640 : WERROR errcode = WERR_INVALID_FUNCTION;
7785 :
7786 640 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7787 0 : return WERR_INVALID_HANDLE;
7788 : }
7789 :
7790 640 : if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7791 251 : return WERR_INVALID_PRINTER_NAME;
7792 : }
7793 :
7794 389 : switch (r->in.command) {
7795 293 : case SPOOLSS_JOB_CONTROL_CANCEL:
7796 : case SPOOLSS_JOB_CONTROL_DELETE:
7797 293 : errcode = print_job_delete(session_info, p->msg_ctx,
7798 : snum, r->in.job_id);
7799 293 : if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7800 293 : errcode = WERR_OK;
7801 : }
7802 293 : break;
7803 32 : case SPOOLSS_JOB_CONTROL_PAUSE:
7804 32 : errcode = print_job_pause(session_info, p->msg_ctx,
7805 : snum, r->in.job_id);
7806 32 : break;
7807 32 : case SPOOLSS_JOB_CONTROL_RESTART:
7808 : case SPOOLSS_JOB_CONTROL_RESUME:
7809 32 : errcode = print_job_resume(session_info, p->msg_ctx,
7810 : snum, r->in.job_id);
7811 32 : break;
7812 32 : case SPOOLSS_JOB_CONTROL_NOOP:
7813 32 : errcode = WERR_OK;
7814 32 : break;
7815 0 : default:
7816 0 : return WERR_INVALID_LEVEL;
7817 : }
7818 :
7819 389 : if (!W_ERROR_IS_OK(errcode)) {
7820 0 : return errcode;
7821 : }
7822 :
7823 389 : if (r->in.ctr == NULL) {
7824 357 : return errcode;
7825 : }
7826 :
7827 32 : switch (r->in.ctr->level) {
7828 32 : case 1:
7829 32 : errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7830 : lp_const_servicename(snum),
7831 : r->in.job_id,
7832 32 : r->in.ctr->info.info1);
7833 32 : break;
7834 0 : case 2:
7835 : case 3:
7836 : case 4:
7837 : default:
7838 0 : return WERR_INVALID_LEVEL;
7839 : }
7840 :
7841 32 : return errcode;
7842 : }
7843 :
7844 : /****************************************************************************
7845 : Enumerates all printer drivers by level and architecture.
7846 : ****************************************************************************/
7847 :
7848 460 : static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7849 : const struct auth_session_info *session_info,
7850 : struct messaging_context *msg_ctx,
7851 : const char *servername,
7852 : const char *architecture,
7853 : uint32_t level,
7854 : union spoolss_DriverInfo **info_p,
7855 : uint32_t *count_p)
7856 : {
7857 : int i;
7858 : uint32_t version;
7859 : struct spoolss_DriverInfo8 *driver;
7860 460 : union spoolss_DriverInfo *info = NULL;
7861 460 : uint32_t count = 0;
7862 460 : WERROR result = WERR_OK;
7863 : uint32_t num_drivers;
7864 : const char **drivers;
7865 : struct dcerpc_binding_handle *b;
7866 460 : TALLOC_CTX *tmp_ctx = NULL;
7867 :
7868 460 : *count_p = 0;
7869 460 : *info_p = NULL;
7870 :
7871 460 : tmp_ctx = talloc_new(mem_ctx);
7872 460 : if (!tmp_ctx) {
7873 0 : return WERR_NOT_ENOUGH_MEMORY;
7874 : }
7875 :
7876 460 : result = winreg_printer_binding_handle(tmp_ctx,
7877 : session_info,
7878 : msg_ctx,
7879 : &b);
7880 460 : if (!W_ERROR_IS_OK(result)) {
7881 0 : goto out;
7882 : }
7883 :
7884 2300 : for (version=0; version<DRIVER_MAX_VERSION; version++) {
7885 1840 : result = winreg_get_driver_list(tmp_ctx, b,
7886 : architecture, version,
7887 : &num_drivers, &drivers);
7888 1840 : if (!W_ERROR_IS_OK(result)) {
7889 0 : goto out;
7890 : }
7891 1840 : DEBUG(4, ("we have:[%d] drivers in environment"
7892 : " [%s] and version [%d]\n",
7893 : num_drivers, architecture, version));
7894 :
7895 1840 : if (num_drivers != 0) {
7896 0 : info = talloc_realloc(tmp_ctx, info,
7897 : union spoolss_DriverInfo,
7898 : count + num_drivers);
7899 0 : if (!info) {
7900 0 : DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7901 : "failed to enlarge driver info buffer!\n"));
7902 0 : result = WERR_NOT_ENOUGH_MEMORY;
7903 0 : goto out;
7904 : }
7905 : }
7906 :
7907 1840 : for (i = 0; i < num_drivers; i++) {
7908 0 : DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7909 :
7910 0 : result = winreg_get_driver(tmp_ctx, b,
7911 0 : architecture, drivers[i],
7912 : version, &driver);
7913 0 : if (!W_ERROR_IS_OK(result)) {
7914 0 : goto out;
7915 : }
7916 :
7917 0 : switch (level) {
7918 0 : case 1:
7919 0 : result = fill_printer_driver_info1(info, &info[count+i].info1,
7920 : driver, servername);
7921 0 : break;
7922 0 : case 2:
7923 0 : result = fill_printer_driver_info2(info, &info[count+i].info2,
7924 : driver, servername);
7925 0 : break;
7926 0 : case 3:
7927 0 : result = fill_printer_driver_info3(info, &info[count+i].info3,
7928 : driver, servername);
7929 0 : break;
7930 0 : case 4:
7931 0 : result = fill_printer_driver_info4(info, &info[count+i].info4,
7932 : driver, servername);
7933 0 : break;
7934 0 : case 5:
7935 0 : result = fill_printer_driver_info5(info, &info[count+i].info5,
7936 : driver, servername);
7937 0 : break;
7938 0 : case 6:
7939 0 : result = fill_printer_driver_info6(info, &info[count+i].info6,
7940 : driver, servername);
7941 0 : break;
7942 0 : case 8:
7943 0 : result = fill_printer_driver_info8(info, &info[count+i].info8,
7944 : driver, servername);
7945 0 : break;
7946 0 : default:
7947 0 : result = WERR_INVALID_LEVEL;
7948 0 : break;
7949 : }
7950 :
7951 0 : TALLOC_FREE(driver);
7952 :
7953 0 : if (!W_ERROR_IS_OK(result)) {
7954 0 : goto out;
7955 : }
7956 : }
7957 :
7958 1840 : count += num_drivers;
7959 1840 : TALLOC_FREE(drivers);
7960 : }
7961 :
7962 460 : out:
7963 460 : if (W_ERROR_IS_OK(result)) {
7964 460 : *info_p = talloc_move(mem_ctx, &info);
7965 460 : *count_p = count;
7966 : }
7967 :
7968 460 : talloc_free(tmp_ctx);
7969 460 : return result;
7970 : }
7971 :
7972 : /****************************************************************************
7973 : Enumerates all printer drivers by level.
7974 : ****************************************************************************/
7975 :
7976 108 : static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7977 : const struct auth_session_info *session_info,
7978 : struct messaging_context *msg_ctx,
7979 : const char *servername,
7980 : const char *architecture,
7981 : uint32_t level,
7982 : union spoolss_DriverInfo **info_p,
7983 : uint32_t *count_p)
7984 : {
7985 : uint32_t a,i;
7986 108 : WERROR result = WERR_OK;
7987 :
7988 108 : if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7989 :
7990 440 : for (a=0; archi_table[a].long_archi != NULL; a++) {
7991 :
7992 396 : union spoolss_DriverInfo *info = NULL;
7993 396 : uint32_t count = 0;
7994 :
7995 396 : result = enumprinterdrivers_level_by_architecture(mem_ctx,
7996 : session_info,
7997 : msg_ctx,
7998 : servername,
7999 99 : archi_table[a].long_archi,
8000 : level,
8001 : &info,
8002 : &count);
8003 396 : if (!W_ERROR_IS_OK(result)) {
8004 0 : continue;
8005 : }
8006 :
8007 396 : for (i=0; i < count; i++) {
8008 0 : ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
8009 : info[i], info_p, count_p);
8010 : }
8011 : }
8012 :
8013 44 : return result;
8014 : }
8015 :
8016 64 : return enumprinterdrivers_level_by_architecture(mem_ctx,
8017 : session_info,
8018 : msg_ctx,
8019 : servername,
8020 : architecture,
8021 : level,
8022 : info_p,
8023 : count_p);
8024 : }
8025 :
8026 : /****************************************************************
8027 : _spoolss_EnumPrinterDrivers
8028 : ****************************************************************/
8029 :
8030 108 : WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
8031 : struct spoolss_EnumPrinterDrivers *r)
8032 : {
8033 : const char *cservername;
8034 : WERROR result;
8035 :
8036 : /* that's an [in out] buffer */
8037 :
8038 108 : if (!r->in.buffer && (r->in.offered != 0)) {
8039 0 : return WERR_INVALID_PARAMETER;
8040 : }
8041 :
8042 108 : DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
8043 :
8044 108 : *r->out.needed = 0;
8045 108 : *r->out.count = 0;
8046 108 : *r->out.info = NULL;
8047 :
8048 108 : cservername = canon_servername(r->in.server);
8049 :
8050 108 : if (!is_myname_or_ipaddr(cservername)) {
8051 0 : return WERR_UNKNOWN_PRINTER_DRIVER;
8052 : }
8053 :
8054 108 : result = enumprinterdrivers_level(p->mem_ctx,
8055 : get_session_info_system(),
8056 : p->msg_ctx,
8057 : cservername,
8058 : r->in.environment,
8059 : r->in.level,
8060 : r->out.info,
8061 : r->out.count);
8062 108 : if (!W_ERROR_IS_OK(result)) {
8063 0 : return result;
8064 : }
8065 :
8066 108 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8067 : spoolss_EnumPrinterDrivers,
8068 : *r->out.info, r->in.level,
8069 : *r->out.count);
8070 108 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8071 108 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8072 :
8073 108 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8074 : }
8075 :
8076 : /****************************************************************
8077 : _spoolss_EnumForms
8078 : ****************************************************************/
8079 :
8080 560 : WERROR _spoolss_EnumForms(struct pipes_struct *p,
8081 : struct spoolss_EnumForms *r)
8082 : {
8083 : WERROR result;
8084 :
8085 560 : *r->out.count = 0;
8086 560 : *r->out.needed = 0;
8087 560 : *r->out.info = NULL;
8088 :
8089 : /* that's an [in out] buffer */
8090 :
8091 560 : if (!r->in.buffer && (r->in.offered != 0) ) {
8092 0 : return WERR_INVALID_PARAMETER;
8093 : }
8094 :
8095 560 : DEBUG(4,("_spoolss_EnumForms\n"));
8096 560 : DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
8097 560 : DEBUGADD(5,("Info level [%d]\n", r->in.level));
8098 :
8099 560 : switch (r->in.level) {
8100 536 : case 1:
8101 536 : result = winreg_printer_enumforms1_internal(p->mem_ctx,
8102 : get_session_info_system(),
8103 : p->msg_ctx,
8104 : r->out.count,
8105 : r->out.info);
8106 536 : break;
8107 24 : default:
8108 24 : result = WERR_INVALID_LEVEL;
8109 24 : break;
8110 : }
8111 :
8112 560 : if (!W_ERROR_IS_OK(result)) {
8113 24 : return result;
8114 : }
8115 :
8116 536 : if (*r->out.count == 0) {
8117 0 : return WERR_NO_MORE_ITEMS;
8118 : }
8119 :
8120 536 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8121 : spoolss_EnumForms,
8122 : *r->out.info, r->in.level,
8123 : *r->out.count);
8124 536 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8125 536 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8126 :
8127 536 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8128 : }
8129 :
8130 : /****************************************************************
8131 : _spoolss_GetForm
8132 : ****************************************************************/
8133 :
8134 5040 : WERROR _spoolss_GetForm(struct pipes_struct *p,
8135 : struct spoolss_GetForm *r)
8136 : {
8137 : WERROR result;
8138 :
8139 : /* that's an [in out] buffer */
8140 :
8141 5040 : if (!r->in.buffer && (r->in.offered != 0)) {
8142 0 : TALLOC_FREE(r->out.info);
8143 0 : return WERR_INVALID_PARAMETER;
8144 : }
8145 :
8146 5040 : DEBUG(4,("_spoolss_GetForm\n"));
8147 5040 : DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
8148 5040 : DEBUGADD(5,("Info level [%d]\n", r->in.level));
8149 :
8150 5040 : switch (r->in.level) {
8151 5040 : case 1:
8152 5040 : result = winreg_printer_getform1_internal(p->mem_ctx,
8153 : get_session_info_system(),
8154 : p->msg_ctx,
8155 : r->in.form_name,
8156 5040 : &r->out.info->info1);
8157 5040 : break;
8158 0 : default:
8159 0 : result = WERR_INVALID_LEVEL;
8160 0 : break;
8161 : }
8162 :
8163 5040 : if (!W_ERROR_IS_OK(result)) {
8164 0 : TALLOC_FREE(r->out.info);
8165 0 : return result;
8166 : }
8167 :
8168 5040 : *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
8169 : r->out.info, r->in.level);
8170 5040 : r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8171 :
8172 5040 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8173 : }
8174 :
8175 : /****************************************************************************
8176 : ****************************************************************************/
8177 :
8178 8 : static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
8179 : struct spoolss_PortInfo1 *r,
8180 : const char *name)
8181 : {
8182 8 : r->port_name = talloc_strdup(mem_ctx, name);
8183 8 : W_ERROR_HAVE_NO_MEMORY(r->port_name);
8184 :
8185 8 : return WERR_OK;
8186 : }
8187 :
8188 : /****************************************************************************
8189 : TODO: This probably needs distinguish between TCP/IP and Local ports
8190 : somehow.
8191 : ****************************************************************************/
8192 :
8193 16 : static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
8194 : struct spoolss_PortInfo2 *r,
8195 : const char *name)
8196 : {
8197 16 : r->port_name = talloc_strdup(mem_ctx, name);
8198 16 : W_ERROR_HAVE_NO_MEMORY(r->port_name);
8199 :
8200 16 : r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
8201 16 : W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8202 :
8203 16 : r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
8204 16 : W_ERROR_HAVE_NO_MEMORY(r->description);
8205 :
8206 16 : r->port_type = SPOOLSS_PORT_TYPE_WRITE;
8207 16 : r->reserved = 0;
8208 :
8209 16 : return WERR_OK;
8210 : }
8211 :
8212 :
8213 : /****************************************************************************
8214 : wrapper around the enumer ports command
8215 : ****************************************************************************/
8216 :
8217 24 : static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
8218 : {
8219 18 : const struct loadparm_substitution *lp_sub =
8220 6 : loadparm_s3_global_substitution();
8221 24 : char *cmd = lp_enumports_command(talloc_tos(), lp_sub);
8222 24 : char **qlines = NULL;
8223 24 : char *command = NULL;
8224 : int numlines;
8225 : int ret;
8226 : int fd;
8227 :
8228 24 : *count = 0;
8229 24 : *lines = NULL;
8230 :
8231 : /* if no hook then just fill in the default port */
8232 :
8233 24 : if ( !*cmd ) {
8234 24 : if (!(qlines = talloc_array( NULL, char*, 2 ))) {
8235 0 : return WERR_NOT_ENOUGH_MEMORY;
8236 : }
8237 24 : if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
8238 0 : TALLOC_FREE(qlines);
8239 0 : return WERR_NOT_ENOUGH_MEMORY;
8240 : }
8241 24 : qlines[1] = NULL;
8242 24 : numlines = 1;
8243 : }
8244 : else {
8245 : /* we have a valid enumport command */
8246 :
8247 0 : command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
8248 0 : if (!command) {
8249 0 : return WERR_NOT_ENOUGH_MEMORY;
8250 : }
8251 :
8252 0 : DEBUG(10,("Running [%s]\n", command));
8253 0 : ret = smbrun(command, &fd, NULL);
8254 0 : DEBUG(10,("Returned [%d]\n", ret));
8255 0 : TALLOC_FREE(command);
8256 0 : if (ret != 0) {
8257 0 : if (fd != -1) {
8258 0 : close(fd);
8259 : }
8260 0 : return WERR_ACCESS_DENIED;
8261 : }
8262 :
8263 0 : numlines = 0;
8264 0 : qlines = fd_lines_load(fd, &numlines, 0, NULL);
8265 0 : DEBUGADD(10,("Lines returned = [%d]\n", numlines));
8266 0 : close(fd);
8267 : }
8268 :
8269 24 : *count = numlines;
8270 24 : *lines = qlines;
8271 :
8272 24 : return WERR_OK;
8273 : }
8274 :
8275 : /****************************************************************************
8276 : enumports level 1.
8277 : ****************************************************************************/
8278 :
8279 8 : static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
8280 : union spoolss_PortInfo **info_p,
8281 : uint32_t *count)
8282 : {
8283 8 : union spoolss_PortInfo *info = NULL;
8284 8 : int i=0;
8285 8 : WERROR result = WERR_OK;
8286 8 : char **qlines = NULL;
8287 8 : int numlines = 0;
8288 :
8289 8 : result = enumports_hook(talloc_tos(), &numlines, &qlines );
8290 8 : if (!W_ERROR_IS_OK(result)) {
8291 0 : goto out;
8292 : }
8293 :
8294 8 : if (numlines) {
8295 8 : info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8296 8 : if (!info) {
8297 0 : DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
8298 0 : result = WERR_NOT_ENOUGH_MEMORY;
8299 0 : goto out;
8300 : }
8301 :
8302 16 : for (i=0; i<numlines; i++) {
8303 8 : DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8304 8 : result = fill_port_1(info, &info[i].info1, qlines[i]);
8305 8 : if (!W_ERROR_IS_OK(result)) {
8306 0 : goto out;
8307 : }
8308 : }
8309 : }
8310 14 : TALLOC_FREE(qlines);
8311 :
8312 6 : out:
8313 8 : if (!W_ERROR_IS_OK(result)) {
8314 0 : TALLOC_FREE(info);
8315 0 : TALLOC_FREE(qlines);
8316 0 : *count = 0;
8317 0 : *info_p = NULL;
8318 0 : return result;
8319 : }
8320 :
8321 8 : *info_p = info;
8322 8 : *count = numlines;
8323 :
8324 8 : return WERR_OK;
8325 : }
8326 :
8327 : /****************************************************************************
8328 : enumports level 2.
8329 : ****************************************************************************/
8330 :
8331 16 : static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
8332 : union spoolss_PortInfo **info_p,
8333 : uint32_t *count)
8334 : {
8335 16 : union spoolss_PortInfo *info = NULL;
8336 16 : int i=0;
8337 16 : WERROR result = WERR_OK;
8338 16 : char **qlines = NULL;
8339 16 : int numlines = 0;
8340 :
8341 16 : result = enumports_hook(talloc_tos(), &numlines, &qlines );
8342 16 : if (!W_ERROR_IS_OK(result)) {
8343 0 : goto out;
8344 : }
8345 :
8346 16 : if (numlines) {
8347 16 : info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8348 16 : if (!info) {
8349 0 : DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
8350 0 : result = WERR_NOT_ENOUGH_MEMORY;
8351 0 : goto out;
8352 : }
8353 :
8354 32 : for (i=0; i<numlines; i++) {
8355 16 : DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8356 16 : result = fill_port_2(info, &info[i].info2, qlines[i]);
8357 16 : if (!W_ERROR_IS_OK(result)) {
8358 0 : goto out;
8359 : }
8360 : }
8361 : }
8362 28 : TALLOC_FREE(qlines);
8363 :
8364 12 : out:
8365 16 : if (!W_ERROR_IS_OK(result)) {
8366 0 : TALLOC_FREE(info);
8367 0 : TALLOC_FREE(qlines);
8368 0 : *count = 0;
8369 0 : *info_p = NULL;
8370 0 : return result;
8371 : }
8372 :
8373 16 : *info_p = info;
8374 16 : *count = numlines;
8375 :
8376 16 : return WERR_OK;
8377 : }
8378 :
8379 : /****************************************************************
8380 : _spoolss_EnumPorts
8381 : ****************************************************************/
8382 :
8383 24 : WERROR _spoolss_EnumPorts(struct pipes_struct *p,
8384 : struct spoolss_EnumPorts *r)
8385 : {
8386 : WERROR result;
8387 :
8388 : /* that's an [in out] buffer */
8389 :
8390 24 : if (!r->in.buffer && (r->in.offered != 0)) {
8391 0 : return WERR_INVALID_PARAMETER;
8392 : }
8393 :
8394 24 : DEBUG(4,("_spoolss_EnumPorts\n"));
8395 :
8396 24 : *r->out.count = 0;
8397 24 : *r->out.needed = 0;
8398 24 : *r->out.info = NULL;
8399 :
8400 24 : switch (r->in.level) {
8401 8 : case 1:
8402 8 : result = enumports_level_1(p->mem_ctx, r->out.info,
8403 : r->out.count);
8404 8 : break;
8405 16 : case 2:
8406 16 : result = enumports_level_2(p->mem_ctx, r->out.info,
8407 : r->out.count);
8408 16 : break;
8409 0 : default:
8410 0 : return WERR_INVALID_LEVEL;
8411 : }
8412 :
8413 24 : if (!W_ERROR_IS_OK(result)) {
8414 0 : return result;
8415 : }
8416 :
8417 24 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8418 : spoolss_EnumPorts,
8419 : *r->out.info, r->in.level,
8420 : *r->out.count);
8421 24 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8422 24 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8423 :
8424 24 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8425 : }
8426 :
8427 : /****************************************************************************
8428 : ****************************************************************************/
8429 :
8430 96 : static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
8431 : const char *server,
8432 : struct spoolss_SetPrinterInfoCtr *info_ctr,
8433 : struct spoolss_DeviceMode *devmode,
8434 : struct security_descriptor *secdesc,
8435 : struct spoolss_UserLevelCtr *user_ctr,
8436 : struct policy_handle *handle)
8437 : {
8438 96 : struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8439 96 : uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8440 72 : const struct loadparm_substitution *lp_sub =
8441 24 : loadparm_s3_global_substitution();
8442 : int snum;
8443 96 : WERROR err = WERR_OK;
8444 :
8445 : /* samba does not have a concept of local, non-shared printers yet, so
8446 : * make sure we always setup sharename - gd */
8447 168 : if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8448 156 : (info2->printername != NULL && info2->printername[0] != '\0')) {
8449 80 : DEBUG(5, ("spoolss_addprinterex_level_2: "
8450 : "no sharename has been set, setting printername %s as sharename\n",
8451 : info2->printername));
8452 80 : info2->sharename = info2->printername;
8453 : }
8454 :
8455 : /* check to see if the printer already exists */
8456 96 : if ((snum = print_queue_snum(info2->sharename)) != -1) {
8457 16 : DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8458 : info2->sharename));
8459 16 : return WERR_PRINTER_ALREADY_EXISTS;
8460 : }
8461 :
8462 80 : if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8463 80 : if ((snum = print_queue_snum(info2->printername)) != -1) {
8464 0 : DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8465 : info2->printername));
8466 0 : return WERR_PRINTER_ALREADY_EXISTS;
8467 : }
8468 : }
8469 :
8470 : /* validate printer info struct */
8471 80 : if (!info2->printername || strlen(info2->printername) == 0) {
8472 16 : return WERR_INVALID_PRINTER_NAME;
8473 : }
8474 64 : if (!info2->portname || strlen(info2->portname) == 0) {
8475 16 : return WERR_UNKNOWN_PORT;
8476 : }
8477 48 : if (!info2->drivername || strlen(info2->drivername) == 0) {
8478 16 : return WERR_UNKNOWN_PRINTER_DRIVER;
8479 : }
8480 32 : if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8481 16 : return WERR_UNKNOWN_PRINTPROCESSOR;
8482 : }
8483 :
8484 : /* FIXME!!! smbd should check to see if the driver is installed before
8485 : trying to add a printer like this --jerry */
8486 :
8487 16 : if (*lp_addprinter_command(talloc_tos(), lp_sub) ) {
8488 : char *raddr;
8489 :
8490 16 : raddr = tsocket_address_inet_addr_string(p->remote_address,
8491 : p->mem_ctx);
8492 16 : if (raddr == NULL) {
8493 0 : return WERR_NOT_ENOUGH_MEMORY;
8494 : }
8495 :
8496 16 : if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
8497 : info2, raddr,
8498 : p->msg_ctx) ) {
8499 0 : return WERR_ACCESS_DENIED;
8500 : }
8501 : } else {
8502 0 : DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8503 : "smb.conf parameter \"addprinter command\" is defined. This "
8504 : "parameter must exist for this call to succeed\n",
8505 : info2->sharename ));
8506 : }
8507 :
8508 16 : if ((snum = print_queue_snum(info2->sharename)) == -1) {
8509 0 : return WERR_ACCESS_DENIED;
8510 : }
8511 :
8512 : /* you must be a printer admin to add a new printer */
8513 16 : if (!W_ERROR_IS_OK(print_access_check(p->session_info,
8514 : p->msg_ctx,
8515 : snum,
8516 : PRINTER_ACCESS_ADMINISTER))) {
8517 0 : return WERR_ACCESS_DENIED;
8518 : }
8519 :
8520 : /*
8521 : * Do sanity check on the requested changes for Samba.
8522 : */
8523 :
8524 16 : if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8525 0 : return WERR_INVALID_PARAMETER;
8526 : }
8527 :
8528 16 : if (devmode == NULL) {
8529 16 : info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8530 : }
8531 :
8532 16 : err = update_dsspooler(p->mem_ctx,
8533 : get_session_info_system(),
8534 : p->msg_ctx,
8535 : 0,
8536 : info2,
8537 : NULL);
8538 16 : if (!W_ERROR_IS_OK(err)) {
8539 0 : return err;
8540 : }
8541 :
8542 16 : err = winreg_update_printer_internal(p->mem_ctx,
8543 : get_session_info_system(),
8544 : p->msg_ctx,
8545 : info2->sharename,
8546 : info2_mask,
8547 : info2,
8548 : devmode,
8549 : secdesc);
8550 16 : if (!W_ERROR_IS_OK(err)) {
8551 0 : return err;
8552 : }
8553 :
8554 16 : err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8555 16 : if (!W_ERROR_IS_OK(err)) {
8556 : /* Handle open failed - remove addition. */
8557 0 : ZERO_STRUCTP(handle);
8558 0 : return err;
8559 : }
8560 :
8561 16 : return WERR_OK;
8562 : }
8563 :
8564 : /****************************************************************
8565 : _spoolss_AddPrinterEx
8566 : ****************************************************************/
8567 :
8568 96 : WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8569 : struct spoolss_AddPrinterEx *r)
8570 : {
8571 96 : switch (r->in.info_ctr->level) {
8572 0 : case 1:
8573 : /* we don't handle yet */
8574 : /* but I know what to do ... */
8575 0 : return WERR_INVALID_LEVEL;
8576 96 : case 2:
8577 240 : return spoolss_addprinterex_level_2(p, r->in.server,
8578 : r->in.info_ctr,
8579 96 : r->in.devmode_ctr->devmode,
8580 96 : r->in.secdesc_ctr->sd,
8581 : r->in.userlevel_ctr,
8582 : r->out.handle);
8583 0 : default:
8584 0 : return WERR_INVALID_LEVEL;
8585 : }
8586 : }
8587 :
8588 : /****************************************************************
8589 : _spoolss_AddPrinter
8590 : ****************************************************************/
8591 :
8592 72 : WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8593 : struct spoolss_AddPrinter *r)
8594 : {
8595 : struct spoolss_AddPrinterEx a;
8596 : struct spoolss_UserLevelCtr userlevel_ctr;
8597 :
8598 72 : ZERO_STRUCT(userlevel_ctr);
8599 :
8600 72 : userlevel_ctr.level = 1;
8601 :
8602 72 : a.in.server = r->in.server;
8603 72 : a.in.info_ctr = r->in.info_ctr;
8604 72 : a.in.devmode_ctr = r->in.devmode_ctr;
8605 72 : a.in.secdesc_ctr = r->in.secdesc_ctr;
8606 72 : a.in.userlevel_ctr = &userlevel_ctr;
8607 72 : a.out.handle = r->out.handle;
8608 :
8609 72 : return _spoolss_AddPrinterEx(p, &a);
8610 : }
8611 :
8612 : /****************************************************************
8613 : _spoolss_AddPrinterDriverEx
8614 : ****************************************************************/
8615 :
8616 0 : WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8617 : struct spoolss_AddPrinterDriverEx *r)
8618 : {
8619 0 : WERROR err = WERR_OK;
8620 0 : const char *driver_name = NULL;
8621 0 : const char *driver_directory = NULL;
8622 : uint32_t version;
8623 :
8624 : /*
8625 : * we only support the semantics of AddPrinterDriver()
8626 : * i.e. only copy files that are newer than existing ones
8627 : */
8628 :
8629 0 : if (r->in.flags == 0) {
8630 0 : return WERR_INVALID_PARAMETER;
8631 : }
8632 :
8633 0 : if (!(r->in.flags & APD_COPY_ALL_FILES) &&
8634 0 : !(r->in.flags & APD_COPY_NEW_FILES)) {
8635 0 : return WERR_ACCESS_DENIED;
8636 : }
8637 :
8638 : /* FIXME */
8639 0 : if (r->in.info_ctr->level != 3 &&
8640 0 : r->in.info_ctr->level != 6 &&
8641 0 : r->in.info_ctr->level != 8) {
8642 0 : DEBUG(0,("%s: level %d not yet implemented\n", __func__,
8643 : r->in.info_ctr->level));
8644 0 : return WERR_INVALID_LEVEL;
8645 : }
8646 :
8647 0 : DEBUG(5,("Cleaning driver's information\n"));
8648 0 : err = clean_up_driver_struct(p->mem_ctx,
8649 0 : p->session_info,
8650 0 : r->in.info_ctr,
8651 : r->in.flags,
8652 : &driver_directory);
8653 0 : if (!W_ERROR_IS_OK(err)) {
8654 0 : DBG_ERR("clean_up_driver_struct failed - %s\n",
8655 : win_errstr(err));
8656 0 : goto done;
8657 : }
8658 :
8659 0 : DEBUG(5,("Moving driver to final destination\n"));
8660 0 : err = move_driver_to_download_area(p->session_info,
8661 0 : r->in.info_ctr,
8662 : driver_directory);
8663 0 : if (!W_ERROR_IS_OK(err)) {
8664 0 : DBG_ERR("move_driver_to_download_area failed - %s\n",
8665 : win_errstr(err));
8666 0 : goto done;
8667 : }
8668 :
8669 0 : err = winreg_add_driver_internal(p->mem_ctx,
8670 : get_session_info_system(),
8671 : p->msg_ctx,
8672 : r->in.info_ctr,
8673 : &driver_name,
8674 : &version);
8675 0 : if (!W_ERROR_IS_OK(err)) {
8676 0 : DBG_ERR("winreg_add_driver_internal failed - %s\n",
8677 : win_errstr(err));
8678 0 : goto done;
8679 : }
8680 :
8681 : /*
8682 : * I think this is where he DrvUpgradePrinter() hook would be
8683 : * be called in a driver's interface DLL on a Windows NT 4.0/2k
8684 : * server. Right now, we just need to send ourselves a message
8685 : * to update each printer bound to this driver. --jerry
8686 : */
8687 :
8688 0 : if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8689 0 : DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8690 : __func__, driver_name));
8691 : }
8692 :
8693 0 : done:
8694 0 : return err;
8695 : }
8696 :
8697 : /****************************************************************
8698 : _spoolss_AddPrinterDriver
8699 : ****************************************************************/
8700 :
8701 0 : WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8702 : struct spoolss_AddPrinterDriver *r)
8703 : {
8704 : struct spoolss_AddPrinterDriverEx a;
8705 :
8706 0 : switch (r->in.info_ctr->level) {
8707 0 : case 2:
8708 : case 3:
8709 : case 4:
8710 : case 5:
8711 0 : break;
8712 0 : default:
8713 0 : return WERR_INVALID_LEVEL;
8714 : }
8715 :
8716 0 : a.in.servername = r->in.servername;
8717 0 : a.in.info_ctr = r->in.info_ctr;
8718 0 : a.in.flags = APD_COPY_NEW_FILES;
8719 :
8720 0 : return _spoolss_AddPrinterDriverEx(p, &a);
8721 : }
8722 :
8723 : /****************************************************************************
8724 : ****************************************************************************/
8725 :
8726 : struct _spoolss_paths {
8727 : int type;
8728 : const char *share;
8729 : const char *dir;
8730 : };
8731 :
8732 : enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8733 :
8734 : static const struct _spoolss_paths spoolss_paths[]= {
8735 : { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8736 : { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8737 : };
8738 :
8739 152 : static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8740 : const char *servername,
8741 : const char *environment,
8742 : int component,
8743 : char **path)
8744 : {
8745 152 : const char *pservername = NULL;
8746 : const char *long_archi;
8747 : const char *short_archi;
8748 :
8749 152 : *path = NULL;
8750 :
8751 : /* environment may be empty */
8752 152 : if (environment && strlen(environment)) {
8753 152 : long_archi = environment;
8754 : } else {
8755 0 : long_archi = lp_parm_const_string(GLOBAL_SECTION_SNUM,
8756 : "spoolss", "architecture",
8757 : GLOBAL_SPOOLSS_ARCHITECTURE);
8758 : }
8759 :
8760 : /* servername may be empty */
8761 152 : if (servername && strlen(servername)) {
8762 88 : pservername = canon_servername(servername);
8763 :
8764 88 : if (!is_myname_or_ipaddr(pservername)) {
8765 0 : return WERR_INVALID_PARAMETER;
8766 : }
8767 : }
8768 :
8769 152 : if (!(short_archi = get_short_archi(long_archi))) {
8770 0 : return WERR_INVALID_ENVIRONMENT;
8771 : }
8772 :
8773 152 : switch (component) {
8774 152 : case SPOOLSS_PRTPROCS_PATH:
8775 : case SPOOLSS_DRIVER_PATH:
8776 152 : if (pservername) {
8777 88 : *path = talloc_asprintf(mem_ctx,
8778 : "\\\\%s\\%s\\%s",
8779 : pservername,
8780 36 : spoolss_paths[component].share,
8781 : short_archi);
8782 : } else {
8783 64 : *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8784 : SPOOLSS_DEFAULT_SERVER_PATH,
8785 16 : spoolss_paths[component].dir,
8786 : short_archi);
8787 : }
8788 152 : break;
8789 0 : default:
8790 0 : return WERR_INVALID_PARAMETER;
8791 : }
8792 :
8793 152 : if (!*path) {
8794 0 : return WERR_NOT_ENOUGH_MEMORY;
8795 : }
8796 :
8797 152 : return WERR_OK;
8798 : }
8799 :
8800 : /****************************************************************************
8801 : ****************************************************************************/
8802 :
8803 112 : static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8804 : const char *servername,
8805 : const char *environment,
8806 : struct spoolss_DriverDirectoryInfo1 *r)
8807 : {
8808 : WERROR werr;
8809 112 : char *path = NULL;
8810 :
8811 112 : werr = compose_spoolss_server_path(mem_ctx,
8812 : servername,
8813 : environment,
8814 : SPOOLSS_DRIVER_PATH,
8815 : &path);
8816 112 : if (!W_ERROR_IS_OK(werr)) {
8817 0 : return werr;
8818 : }
8819 :
8820 112 : DEBUG(4,("printer driver directory: [%s]\n", path));
8821 :
8822 112 : r->directory_name = path;
8823 :
8824 112 : return WERR_OK;
8825 : }
8826 :
8827 : /****************************************************************
8828 : _spoolss_GetPrinterDriverDirectory
8829 : ****************************************************************/
8830 :
8831 112 : WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8832 : struct spoolss_GetPrinterDriverDirectory *r)
8833 : {
8834 : WERROR werror;
8835 :
8836 : /* that's an [in out] buffer */
8837 :
8838 112 : if (!r->in.buffer && (r->in.offered != 0)) {
8839 0 : TALLOC_FREE(r->out.info);
8840 0 : return WERR_INVALID_PARAMETER;
8841 : }
8842 :
8843 112 : DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8844 : r->in.level));
8845 :
8846 112 : *r->out.needed = 0;
8847 :
8848 : /* r->in.level is ignored */
8849 :
8850 112 : werror = getprinterdriverdir_level_1(p->mem_ctx,
8851 : r->in.server,
8852 : r->in.environment,
8853 112 : &r->out.info->info1);
8854 112 : if (!W_ERROR_IS_OK(werror)) {
8855 0 : TALLOC_FREE(r->out.info);
8856 0 : return werror;
8857 : }
8858 :
8859 112 : *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8860 : r->out.info, r->in.level);
8861 112 : r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8862 :
8863 112 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8864 : }
8865 :
8866 : /****************************************************************
8867 : _spoolss_EnumPrinterData
8868 : ****************************************************************/
8869 :
8870 152 : WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8871 : struct spoolss_EnumPrinterData *r)
8872 : {
8873 : WERROR result;
8874 : struct spoolss_EnumPrinterDataEx r2;
8875 : uint32_t count;
8876 152 : struct spoolss_PrinterEnumValues *info, *val = NULL;
8877 : uint32_t needed;
8878 :
8879 152 : r2.in.handle = r->in.handle;
8880 152 : r2.in.key_name = "PrinterDriverData";
8881 152 : r2.in.offered = 0;
8882 152 : r2.out.count = &count;
8883 152 : r2.out.info = &info;
8884 152 : r2.out.needed = &needed;
8885 :
8886 152 : result = _spoolss_EnumPrinterDataEx(p, &r2);
8887 152 : if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8888 112 : r2.in.offered = needed;
8889 112 : result = _spoolss_EnumPrinterDataEx(p, &r2);
8890 : }
8891 152 : if (!W_ERROR_IS_OK(result)) {
8892 0 : return result;
8893 : }
8894 :
8895 : /*
8896 : * The NT machine wants to know the biggest size of value and data
8897 : *
8898 : * cf: MSDN EnumPrinterData remark section
8899 : */
8900 :
8901 152 : if (!r->in.value_offered && !r->in.data_offered) {
8902 48 : uint32_t biggest_valuesize = 0;
8903 48 : uint32_t biggest_datasize = 0;
8904 : int i, name_length;
8905 :
8906 48 : DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8907 :
8908 132 : for (i=0; i<count; i++) {
8909 :
8910 84 : name_length = strlen(info[i].value_name);
8911 84 : if (strlen(info[i].value_name) > biggest_valuesize) {
8912 28 : biggest_valuesize = name_length;
8913 : }
8914 :
8915 84 : if (info[i].data_length > biggest_datasize) {
8916 28 : biggest_datasize = info[i].data_length;
8917 : }
8918 :
8919 84 : DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8920 : biggest_datasize));
8921 : }
8922 :
8923 : /* the value is an UNICODE string but real_value_size is the length
8924 : in bytes including the trailing 0 */
8925 :
8926 48 : *r->out.value_needed = 2 * (1 + biggest_valuesize);
8927 48 : *r->out.data_needed = biggest_datasize;
8928 :
8929 48 : DEBUG(6,("final values: [%d], [%d]\n",
8930 : *r->out.value_needed, *r->out.data_needed));
8931 :
8932 48 : return WERR_OK;
8933 : }
8934 :
8935 104 : if (r->in.enum_index < count) {
8936 84 : val = &info[r->in.enum_index];
8937 : }
8938 :
8939 104 : if (val == NULL) {
8940 : /* out_value should default to "" or else NT4 has
8941 : problems unmarshalling the response */
8942 :
8943 20 : if (r->in.value_offered) {
8944 20 : *r->out.value_needed = 1;
8945 20 : r->out.value_name = talloc_strdup(r, "");
8946 20 : if (!r->out.value_name) {
8947 0 : return WERR_NOT_ENOUGH_MEMORY;
8948 : }
8949 : } else {
8950 0 : r->out.value_name = NULL;
8951 0 : *r->out.value_needed = 0;
8952 : }
8953 :
8954 : /* the data is counted in bytes */
8955 :
8956 20 : *r->out.data_needed = r->in.data_offered;
8957 :
8958 20 : result = WERR_NO_MORE_ITEMS;
8959 : } else {
8960 : /*
8961 : * the value is:
8962 : * - counted in bytes in the request
8963 : * - counted in UNICODE chars in the max reply
8964 : * - counted in bytes in the real size
8965 : *
8966 : * take a pause *before* coding not *during* coding
8967 : */
8968 :
8969 : /* name */
8970 84 : if (r->in.value_offered) {
8971 84 : r->out.value_name = talloc_strdup(r, val->value_name);
8972 84 : if (!r->out.value_name) {
8973 0 : return WERR_NOT_ENOUGH_MEMORY;
8974 : }
8975 84 : *r->out.value_needed = val->value_name_len;
8976 : } else {
8977 0 : r->out.value_name = NULL;
8978 0 : *r->out.value_needed = 0;
8979 : }
8980 :
8981 : /* type */
8982 :
8983 84 : *r->out.type = val->type;
8984 :
8985 : /* data - counted in bytes */
8986 :
8987 : /*
8988 : * See the section "Dynamically Typed Query Parameters"
8989 : * in MS-RPRN.
8990 : */
8991 :
8992 147 : if (r->out.data && val->data && val->data->data &&
8993 147 : val->data_length && r->in.data_offered) {
8994 84 : memcpy(r->out.data, val->data->data,
8995 84 : MIN(val->data_length,r->in.data_offered));
8996 : }
8997 :
8998 84 : *r->out.data_needed = val->data_length;
8999 :
9000 84 : result = WERR_OK;
9001 : }
9002 :
9003 104 : return result;
9004 : }
9005 :
9006 : /****************************************************************
9007 : _spoolss_SetPrinterData
9008 : ****************************************************************/
9009 :
9010 168 : WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
9011 : struct spoolss_SetPrinterData *r)
9012 : {
9013 : struct spoolss_SetPrinterDataEx r2;
9014 :
9015 168 : r2.in.handle = r->in.handle;
9016 168 : r2.in.key_name = "PrinterDriverData";
9017 168 : r2.in.value_name = r->in.value_name;
9018 168 : r2.in.type = r->in.type;
9019 168 : r2.in.data = r->in.data;
9020 168 : r2.in.offered = r->in.offered;
9021 :
9022 168 : return _spoolss_SetPrinterDataEx(p, &r2);
9023 : }
9024 :
9025 : /****************************************************************
9026 : _spoolss_ResetPrinter
9027 : ****************************************************************/
9028 :
9029 0 : WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
9030 : struct spoolss_ResetPrinter *r)
9031 : {
9032 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9033 : int snum;
9034 :
9035 0 : DEBUG(5,("_spoolss_ResetPrinter\n"));
9036 :
9037 : /*
9038 : * All we do is to check to see if the handle and queue is valid.
9039 : * This call really doesn't mean anything to us because we only
9040 : * support RAW printing. --jerry
9041 : */
9042 :
9043 0 : if (!Printer) {
9044 0 : DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
9045 : OUR_HANDLE(r->in.handle)));
9046 0 : return WERR_INVALID_HANDLE;
9047 : }
9048 :
9049 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9050 0 : return WERR_INVALID_HANDLE;
9051 :
9052 :
9053 : /* blindly return success */
9054 0 : return WERR_OK;
9055 : }
9056 :
9057 : /****************************************************************
9058 : _spoolss_DeletePrinterData
9059 : ****************************************************************/
9060 :
9061 168 : WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
9062 : struct spoolss_DeletePrinterData *r)
9063 : {
9064 : struct spoolss_DeletePrinterDataEx r2;
9065 :
9066 168 : r2.in.handle = r->in.handle;
9067 168 : r2.in.key_name = "PrinterDriverData";
9068 168 : r2.in.value_name = r->in.value_name;
9069 :
9070 168 : return _spoolss_DeletePrinterDataEx(p, &r2);
9071 : }
9072 :
9073 : /****************************************************************
9074 : _spoolss_AddForm
9075 : ****************************************************************/
9076 :
9077 576 : WERROR _spoolss_AddForm(struct pipes_struct *p,
9078 : struct spoolss_AddForm *r)
9079 : {
9080 : struct spoolss_AddFormInfo1 *form;
9081 576 : int snum = -1;
9082 576 : WERROR status = WERR_OK;
9083 576 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9084 : struct dcerpc_binding_handle *b;
9085 576 : TALLOC_CTX *tmp_ctx = NULL;
9086 :
9087 576 : DEBUG(5,("_spoolss_AddForm\n"));
9088 :
9089 576 : if (!Printer) {
9090 0 : DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
9091 : OUR_HANDLE(r->in.handle)));
9092 0 : return WERR_INVALID_HANDLE;
9093 : }
9094 :
9095 : /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
9096 : and not a printer admin, then fail */
9097 :
9098 576 : if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
9099 0 : !security_token_has_privilege(p->session_info->security_token,
9100 : SEC_PRIV_PRINT_OPERATOR)) {
9101 0 : DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
9102 0 : return WERR_ACCESS_DENIED;
9103 : }
9104 :
9105 576 : if (r->in.info_ctr->level != 1) {
9106 0 : return WERR_INVALID_LEVEL;
9107 : }
9108 :
9109 576 : form = r->in.info_ctr->info.info1;
9110 576 : if (!form) {
9111 0 : return WERR_INVALID_PARAMETER;
9112 : }
9113 :
9114 576 : switch (form->flags) {
9115 480 : case SPOOLSS_FORM_USER:
9116 : case SPOOLSS_FORM_BUILTIN:
9117 : case SPOOLSS_FORM_PRINTER:
9118 480 : break;
9119 96 : default:
9120 96 : return WERR_INVALID_PARAMETER;
9121 : }
9122 :
9123 480 : tmp_ctx = talloc_new(p->mem_ctx);
9124 480 : if (!tmp_ctx) {
9125 0 : return WERR_NOT_ENOUGH_MEMORY;
9126 : }
9127 :
9128 480 : status = winreg_printer_binding_handle(tmp_ctx,
9129 : get_session_info_system(),
9130 : p->msg_ctx,
9131 : &b);
9132 480 : if (!W_ERROR_IS_OK(status)) {
9133 0 : goto done;
9134 : }
9135 :
9136 480 : status = winreg_printer_addform1(tmp_ctx, b, form);
9137 480 : if (!W_ERROR_IS_OK(status)) {
9138 384 : goto done;
9139 : }
9140 :
9141 : /*
9142 : * ChangeID must always be set if this is a printer
9143 : */
9144 96 : if (Printer->printer_type == SPLHND_PRINTER) {
9145 80 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9146 0 : status = WERR_INVALID_HANDLE;
9147 0 : goto done;
9148 : }
9149 :
9150 80 : status = winreg_printer_update_changeid(tmp_ctx, b,
9151 : lp_const_servicename(snum));
9152 : }
9153 :
9154 376 : done:
9155 480 : talloc_free(tmp_ctx);
9156 480 : return status;
9157 : }
9158 :
9159 : /****************************************************************
9160 : _spoolss_DeleteForm
9161 : ****************************************************************/
9162 :
9163 384 : WERROR _spoolss_DeleteForm(struct pipes_struct *p,
9164 : struct spoolss_DeleteForm *r)
9165 : {
9166 384 : const char *form_name = r->in.form_name;
9167 384 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9168 384 : int snum = -1;
9169 384 : WERROR status = WERR_OK;
9170 : struct dcerpc_binding_handle *b;
9171 384 : TALLOC_CTX *tmp_ctx = NULL;
9172 :
9173 384 : DEBUG(5,("_spoolss_DeleteForm\n"));
9174 :
9175 384 : if (!Printer) {
9176 0 : DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
9177 : OUR_HANDLE(r->in.handle)));
9178 0 : return WERR_INVALID_HANDLE;
9179 : }
9180 :
9181 384 : if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
9182 0 : !security_token_has_privilege(p->session_info->security_token,
9183 : SEC_PRIV_PRINT_OPERATOR)) {
9184 0 : DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
9185 0 : return WERR_ACCESS_DENIED;
9186 : }
9187 :
9188 384 : tmp_ctx = talloc_new(p->mem_ctx);
9189 384 : if (!tmp_ctx) {
9190 0 : return WERR_NOT_ENOUGH_MEMORY;
9191 : }
9192 :
9193 384 : status = winreg_printer_binding_handle(tmp_ctx,
9194 : get_session_info_system(),
9195 : p->msg_ctx,
9196 : &b);
9197 384 : if (!W_ERROR_IS_OK(status)) {
9198 0 : goto done;
9199 : }
9200 :
9201 384 : status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
9202 384 : if (!W_ERROR_IS_OK(status)) {
9203 288 : goto done;
9204 : }
9205 :
9206 : /*
9207 : * ChangeID must always be set if this is a printer
9208 : */
9209 96 : if (Printer->printer_type == SPLHND_PRINTER) {
9210 80 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9211 0 : status = WERR_INVALID_HANDLE;
9212 0 : goto done;
9213 : }
9214 :
9215 80 : status = winreg_printer_update_changeid(tmp_ctx, b,
9216 : lp_const_servicename(snum));
9217 : }
9218 :
9219 304 : done:
9220 384 : talloc_free(tmp_ctx);
9221 384 : return status;
9222 : }
9223 :
9224 : /****************************************************************
9225 : _spoolss_SetForm
9226 : ****************************************************************/
9227 :
9228 80 : WERROR _spoolss_SetForm(struct pipes_struct *p,
9229 : struct spoolss_SetForm *r)
9230 : {
9231 : struct spoolss_AddFormInfo1 *form;
9232 80 : const char *form_name = r->in.form_name;
9233 80 : int snum = -1;
9234 80 : WERROR status = WERR_OK;
9235 : struct dcerpc_binding_handle *b;
9236 80 : TALLOC_CTX *tmp_ctx = NULL;
9237 :
9238 80 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9239 :
9240 80 : DEBUG(5,("_spoolss_SetForm\n"));
9241 :
9242 80 : if (!Printer) {
9243 0 : DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
9244 : OUR_HANDLE(r->in.handle)));
9245 0 : return WERR_INVALID_HANDLE;
9246 : }
9247 :
9248 : /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
9249 : and not a printer admin, then fail */
9250 :
9251 80 : if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
9252 0 : !security_token_has_privilege(p->session_info->security_token,
9253 : SEC_PRIV_PRINT_OPERATOR)) {
9254 0 : DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
9255 0 : return WERR_ACCESS_DENIED;
9256 : }
9257 :
9258 80 : if (r->in.info_ctr->level != 1) {
9259 0 : return WERR_INVALID_LEVEL;
9260 : }
9261 :
9262 80 : form = r->in.info_ctr->info.info1;
9263 80 : if (!form) {
9264 0 : return WERR_INVALID_PARAMETER;
9265 : }
9266 :
9267 80 : tmp_ctx = talloc_new(p->mem_ctx);
9268 80 : if (!tmp_ctx) {
9269 0 : return WERR_NOT_ENOUGH_MEMORY;
9270 : }
9271 :
9272 80 : status = winreg_printer_binding_handle(tmp_ctx,
9273 : get_session_info_system(),
9274 : p->msg_ctx,
9275 : &b);
9276 80 : if (!W_ERROR_IS_OK(status)) {
9277 0 : goto done;
9278 : }
9279 :
9280 80 : status = winreg_printer_setform1(tmp_ctx, b,
9281 : form_name,
9282 : form);
9283 80 : if (!W_ERROR_IS_OK(status)) {
9284 0 : goto done;
9285 : }
9286 :
9287 : /*
9288 : * ChangeID must always be set if this is a printer
9289 : */
9290 80 : if (Printer->printer_type == SPLHND_PRINTER) {
9291 80 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9292 0 : status = WERR_INVALID_HANDLE;
9293 0 : goto done;
9294 : }
9295 :
9296 80 : status = winreg_printer_update_changeid(tmp_ctx, b,
9297 : lp_const_servicename(snum));
9298 : }
9299 :
9300 60 : done:
9301 80 : talloc_free(tmp_ctx);
9302 80 : return status;
9303 : }
9304 :
9305 : /****************************************************************************
9306 : fill_print_processor1
9307 : ****************************************************************************/
9308 :
9309 24 : static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
9310 : struct spoolss_PrintProcessorInfo1 *r,
9311 : const char *print_processor_name)
9312 : {
9313 24 : r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
9314 24 : W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
9315 :
9316 24 : return WERR_OK;
9317 : }
9318 :
9319 : /****************************************************************************
9320 : enumprintprocessors level 1.
9321 : ****************************************************************************/
9322 :
9323 24 : static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
9324 : union spoolss_PrintProcessorInfo **info_p,
9325 : uint32_t *count)
9326 : {
9327 : union spoolss_PrintProcessorInfo *info;
9328 : WERROR result;
9329 :
9330 24 : info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
9331 24 : W_ERROR_HAVE_NO_MEMORY(info);
9332 :
9333 24 : *count = 1;
9334 :
9335 24 : result = fill_print_processor1(info, &info[0].info1, "winprint");
9336 24 : if (!W_ERROR_IS_OK(result)) {
9337 0 : goto out;
9338 : }
9339 :
9340 42 : out:
9341 24 : if (!W_ERROR_IS_OK(result)) {
9342 0 : TALLOC_FREE(info);
9343 0 : *count = 0;
9344 0 : return result;
9345 : }
9346 :
9347 24 : *info_p = info;
9348 :
9349 24 : return WERR_OK;
9350 : }
9351 :
9352 : /****************************************************************
9353 : _spoolss_EnumPrintProcessors
9354 : ****************************************************************/
9355 :
9356 48 : WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
9357 : struct spoolss_EnumPrintProcessors *r)
9358 : {
9359 : WERROR result;
9360 :
9361 : /* that's an [in out] buffer */
9362 :
9363 48 : if (!r->in.buffer && (r->in.offered != 0)) {
9364 0 : return WERR_INVALID_PARAMETER;
9365 : }
9366 :
9367 48 : DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
9368 :
9369 : /*
9370 : * Enumerate the print processors ...
9371 : *
9372 : * Just reply with "winprint", to keep NT happy
9373 : * and I can use my nice printer checker.
9374 : */
9375 :
9376 48 : *r->out.count = 0;
9377 48 : *r->out.needed = 0;
9378 48 : *r->out.info = NULL;
9379 :
9380 48 : if (!get_short_archi(r->in.environment)) {
9381 4 : return WERR_INVALID_ENVIRONMENT;
9382 : }
9383 :
9384 44 : switch (r->in.level) {
9385 24 : case 1:
9386 24 : result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
9387 : r->out.count);
9388 24 : break;
9389 20 : default:
9390 20 : return WERR_INVALID_LEVEL;
9391 : }
9392 :
9393 24 : if (!W_ERROR_IS_OK(result)) {
9394 0 : return result;
9395 : }
9396 :
9397 24 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9398 : spoolss_EnumPrintProcessors,
9399 : *r->out.info, r->in.level,
9400 : *r->out.count);
9401 24 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9402 24 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9403 :
9404 24 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9405 : }
9406 :
9407 : /****************************************************************************
9408 : fill_printprocdatatype1
9409 : ****************************************************************************/
9410 :
9411 16 : static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
9412 : struct spoolss_PrintProcDataTypesInfo1 *r,
9413 : const char *name_array)
9414 : {
9415 16 : r->name_array = talloc_strdup(mem_ctx, name_array);
9416 16 : W_ERROR_HAVE_NO_MEMORY(r->name_array);
9417 :
9418 16 : return WERR_OK;
9419 : }
9420 :
9421 : /****************************************************************************
9422 : enumprintprocdatatypes level 1.
9423 : ****************************************************************************/
9424 :
9425 16 : static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
9426 : union spoolss_PrintProcDataTypesInfo **info_p,
9427 : uint32_t *count)
9428 : {
9429 : WERROR result;
9430 : union spoolss_PrintProcDataTypesInfo *info;
9431 :
9432 16 : info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
9433 16 : W_ERROR_HAVE_NO_MEMORY(info);
9434 :
9435 16 : *count = 1;
9436 :
9437 16 : result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9438 16 : if (!W_ERROR_IS_OK(result)) {
9439 0 : goto out;
9440 : }
9441 :
9442 28 : out:
9443 16 : if (!W_ERROR_IS_OK(result)) {
9444 0 : TALLOC_FREE(info);
9445 0 : *count = 0;
9446 0 : return result;
9447 : }
9448 :
9449 16 : *info_p = info;
9450 :
9451 16 : return WERR_OK;
9452 : }
9453 :
9454 : /****************************************************************
9455 : _spoolss_EnumPrintProcessorDataTypes
9456 : ****************************************************************/
9457 :
9458 44 : WERROR _spoolss_EnumPrintProcessorDataTypes(struct pipes_struct *p,
9459 : struct spoolss_EnumPrintProcessorDataTypes *r)
9460 : {
9461 : WERROR result;
9462 :
9463 : /* that's an [in out] buffer */
9464 :
9465 44 : if (!r->in.buffer && (r->in.offered != 0)) {
9466 0 : return WERR_INVALID_PARAMETER;
9467 : }
9468 :
9469 44 : DEBUG(5,("_spoolss_EnumPrintProcessorDataTypes\n"));
9470 :
9471 44 : *r->out.count = 0;
9472 44 : *r->out.needed = 0;
9473 44 : *r->out.info = NULL;
9474 :
9475 74 : if (r->in.print_processor_name == NULL ||
9476 40 : !strequal(r->in.print_processor_name, "winprint")) {
9477 8 : return WERR_UNKNOWN_PRINTPROCESSOR;
9478 : }
9479 :
9480 36 : switch (r->in.level) {
9481 16 : case 1:
9482 16 : result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9483 : r->out.count);
9484 16 : break;
9485 20 : default:
9486 20 : return WERR_INVALID_LEVEL;
9487 : }
9488 :
9489 16 : if (!W_ERROR_IS_OK(result)) {
9490 0 : return result;
9491 : }
9492 :
9493 16 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9494 : spoolss_EnumPrintProcessorDataTypes,
9495 : *r->out.info, r->in.level,
9496 : *r->out.count);
9497 16 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9498 16 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9499 :
9500 16 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9501 : }
9502 :
9503 : /****************************************************************************
9504 : fill_monitor_1
9505 : ****************************************************************************/
9506 :
9507 16 : static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9508 : struct spoolss_MonitorInfo1 *r,
9509 : const char *monitor_name)
9510 : {
9511 16 : r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9512 16 : W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9513 :
9514 16 : return WERR_OK;
9515 : }
9516 :
9517 : /****************************************************************************
9518 : fill_monitor_2
9519 : ****************************************************************************/
9520 :
9521 16 : static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9522 : struct spoolss_MonitorInfo2 *r,
9523 : const char *monitor_name,
9524 : const char *environment,
9525 : const char *dll_name)
9526 : {
9527 16 : r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9528 16 : W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9529 16 : r->environment = talloc_strdup(mem_ctx, environment);
9530 16 : W_ERROR_HAVE_NO_MEMORY(r->environment);
9531 16 : r->dll_name = talloc_strdup(mem_ctx, dll_name);
9532 16 : W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9533 :
9534 16 : return WERR_OK;
9535 : }
9536 :
9537 : /****************************************************************************
9538 : enumprintmonitors level 1.
9539 : ****************************************************************************/
9540 :
9541 8 : static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9542 : union spoolss_MonitorInfo **info_p,
9543 : uint32_t *count)
9544 : {
9545 : union spoolss_MonitorInfo *info;
9546 8 : WERROR result = WERR_OK;
9547 :
9548 8 : info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9549 8 : W_ERROR_HAVE_NO_MEMORY(info);
9550 :
9551 8 : *count = 2;
9552 :
9553 8 : result = fill_monitor_1(info, &info[0].info1,
9554 : SPL_LOCAL_PORT);
9555 8 : if (!W_ERROR_IS_OK(result)) {
9556 0 : goto out;
9557 : }
9558 :
9559 8 : result = fill_monitor_1(info, &info[1].info1,
9560 : SPL_TCPIP_PORT);
9561 8 : if (!W_ERROR_IS_OK(result)) {
9562 0 : goto out;
9563 : }
9564 :
9565 14 : out:
9566 8 : if (!W_ERROR_IS_OK(result)) {
9567 0 : TALLOC_FREE(info);
9568 0 : *count = 0;
9569 0 : return result;
9570 : }
9571 :
9572 8 : *info_p = info;
9573 :
9574 8 : return WERR_OK;
9575 : }
9576 :
9577 : /****************************************************************************
9578 : enumprintmonitors level 2.
9579 : ****************************************************************************/
9580 :
9581 8 : static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9582 : union spoolss_MonitorInfo **info_p,
9583 : uint32_t *count)
9584 : {
9585 : union spoolss_MonitorInfo *info;
9586 8 : WERROR result = WERR_OK;
9587 : const char *architecture;
9588 :
9589 8 : info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9590 8 : W_ERROR_HAVE_NO_MEMORY(info);
9591 :
9592 8 : *count = 2;
9593 :
9594 8 : architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
9595 : "spoolss",
9596 : "architecture",
9597 : GLOBAL_SPOOLSS_ARCHITECTURE);
9598 :
9599 8 : result = fill_monitor_2(info, &info[0].info2,
9600 : SPL_LOCAL_PORT,
9601 : architecture,
9602 : "localmon.dll");
9603 8 : if (!W_ERROR_IS_OK(result)) {
9604 0 : goto out;
9605 : }
9606 :
9607 8 : result = fill_monitor_2(info, &info[1].info2,
9608 : SPL_TCPIP_PORT,
9609 : architecture,
9610 : "tcpmon.dll");
9611 8 : if (!W_ERROR_IS_OK(result)) {
9612 0 : goto out;
9613 : }
9614 :
9615 14 : out:
9616 8 : if (!W_ERROR_IS_OK(result)) {
9617 0 : TALLOC_FREE(info);
9618 0 : *count = 0;
9619 0 : return result;
9620 : }
9621 :
9622 8 : *info_p = info;
9623 :
9624 8 : return WERR_OK;
9625 : }
9626 :
9627 : /****************************************************************
9628 : _spoolss_EnumMonitors
9629 : ****************************************************************/
9630 :
9631 16 : WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9632 : struct spoolss_EnumMonitors *r)
9633 : {
9634 : WERROR result;
9635 :
9636 : /* that's an [in out] buffer */
9637 :
9638 16 : if (!r->in.buffer && (r->in.offered != 0)) {
9639 0 : return WERR_INVALID_PARAMETER;
9640 : }
9641 :
9642 16 : DEBUG(5,("_spoolss_EnumMonitors\n"));
9643 :
9644 : /*
9645 : * Enumerate the print monitors ...
9646 : *
9647 : * Just reply with "Local Port", to keep NT happy
9648 : * and I can use my nice printer checker.
9649 : */
9650 :
9651 16 : *r->out.count = 0;
9652 16 : *r->out.needed = 0;
9653 16 : *r->out.info = NULL;
9654 :
9655 16 : switch (r->in.level) {
9656 8 : case 1:
9657 8 : result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9658 : r->out.count);
9659 8 : break;
9660 8 : case 2:
9661 8 : result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9662 : r->out.count);
9663 8 : break;
9664 0 : default:
9665 0 : return WERR_INVALID_LEVEL;
9666 : }
9667 :
9668 16 : if (!W_ERROR_IS_OK(result)) {
9669 0 : return result;
9670 : }
9671 :
9672 16 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9673 : spoolss_EnumMonitors,
9674 : *r->out.info, r->in.level,
9675 : *r->out.count);
9676 16 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9677 16 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9678 :
9679 16 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9680 : }
9681 :
9682 : /****************************************************************************
9683 : ****************************************************************************/
9684 :
9685 128 : static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9686 : const print_queue_struct *queue,
9687 : int count, int snum,
9688 : struct spoolss_PrinterInfo2 *pinfo2,
9689 : uint32_t jobid,
9690 : int sysjob,
9691 : struct spoolss_JobInfo1 *r)
9692 : {
9693 128 : int i = 0;
9694 128 : bool found = false;
9695 :
9696 576 : for (i=0; i<count; i++) {
9697 576 : if (queue[i].sysjob == sysjob) {
9698 128 : found = true;
9699 128 : break;
9700 : }
9701 : }
9702 :
9703 128 : if (found == false) {
9704 : /* NT treats not found as bad param... yet another bad choice */
9705 0 : return WERR_INVALID_PARAMETER;
9706 : }
9707 :
9708 128 : return fill_job_info1(mem_ctx,
9709 : r,
9710 128 : &queue[i],
9711 : jobid,
9712 : i,
9713 : snum,
9714 : pinfo2);
9715 : }
9716 :
9717 : /****************************************************************************
9718 : ****************************************************************************/
9719 :
9720 0 : static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9721 : const print_queue_struct *queue,
9722 : int count, int snum,
9723 : struct spoolss_PrinterInfo2 *pinfo2,
9724 : uint32_t jobid,
9725 : int sysjob,
9726 : struct spoolss_JobInfo2 *r)
9727 : {
9728 0 : int i = 0;
9729 0 : bool found = false;
9730 : struct spoolss_DeviceMode *devmode;
9731 : WERROR result;
9732 :
9733 0 : for (i=0; i<count; i++) {
9734 0 : if (queue[i].sysjob == sysjob) {
9735 0 : found = true;
9736 0 : break;
9737 : }
9738 : }
9739 :
9740 0 : if (found == false) {
9741 : /* NT treats not found as bad param... yet another bad
9742 : choice */
9743 0 : return WERR_INVALID_PARAMETER;
9744 : }
9745 :
9746 : /*
9747 : * if the print job does not have a DEVMODE associated with it,
9748 : * just use the one for the printer. A NULL devicemode is not
9749 : * a failure condition
9750 : */
9751 :
9752 0 : devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9753 0 : if (!devmode) {
9754 0 : result = spoolss_create_default_devmode(mem_ctx,
9755 : pinfo2->printername,
9756 : &devmode);
9757 0 : if (!W_ERROR_IS_OK(result)) {
9758 0 : DEBUG(3, ("Can't proceed w/o a devmode!"));
9759 0 : return result;
9760 : }
9761 : }
9762 :
9763 0 : return fill_job_info2(mem_ctx,
9764 : r,
9765 0 : &queue[i],
9766 : jobid,
9767 : i,
9768 : snum,
9769 : pinfo2,
9770 : devmode);
9771 : }
9772 :
9773 : /****************************************************************
9774 : _spoolss_GetJob
9775 : ****************************************************************/
9776 :
9777 2048 : WERROR _spoolss_GetJob(struct pipes_struct *p,
9778 : struct spoolss_GetJob *r)
9779 : {
9780 2048 : WERROR result = WERR_OK;
9781 2048 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9782 : const char *svc_name;
9783 : int sysjob;
9784 : int snum;
9785 : int count;
9786 : struct tdb_print_db *pdb;
9787 2048 : print_queue_struct *queue = NULL;
9788 : print_status_struct prt_status;
9789 :
9790 : /* that's an [in out] buffer */
9791 :
9792 2048 : if (!r->in.buffer && (r->in.offered != 0)) {
9793 0 : result = WERR_INVALID_PARAMETER;
9794 0 : goto err_jinfo_free;
9795 : }
9796 :
9797 2048 : DEBUG(5,("_spoolss_GetJob\n"));
9798 :
9799 2048 : *r->out.needed = 0;
9800 :
9801 2048 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9802 0 : result = WERR_INVALID_HANDLE;
9803 0 : goto err_jinfo_free;
9804 : }
9805 :
9806 2048 : svc_name = lp_const_servicename(snum);
9807 2048 : if (svc_name == NULL) {
9808 0 : result = WERR_INVALID_PARAMETER;
9809 0 : goto err_jinfo_free;
9810 : }
9811 :
9812 2048 : result = winreg_get_printer_internal(p->mem_ctx,
9813 : get_session_info_system(),
9814 : p->msg_ctx,
9815 : svc_name,
9816 : &pinfo2);
9817 2048 : if (!W_ERROR_IS_OK(result)) {
9818 0 : goto err_jinfo_free;
9819 : }
9820 :
9821 2048 : pdb = get_print_db_byname(svc_name);
9822 2048 : if (pdb == NULL) {
9823 0 : DEBUG(3, ("failed to get print db for svc %s\n", svc_name));
9824 0 : result = WERR_INVALID_PARAMETER;
9825 0 : goto err_pinfo_free;
9826 : }
9827 :
9828 2048 : sysjob = jobid_to_sysjob_pdb(pdb, r->in.job_id);
9829 2048 : release_print_db(pdb);
9830 2048 : if (sysjob == -1) {
9831 1920 : DEBUG(3, ("no sysjob for spoolss jobid %u\n", r->in.job_id));
9832 1920 : result = WERR_INVALID_PARAMETER;
9833 1920 : goto err_pinfo_free;
9834 : }
9835 :
9836 128 : count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9837 :
9838 128 : DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9839 : count, prt_status.status, prt_status.message));
9840 :
9841 128 : switch (r->in.level) {
9842 128 : case 1:
9843 128 : result = getjob_level_1(p->mem_ctx,
9844 : queue, count, snum, pinfo2,
9845 : r->in.job_id, sysjob,
9846 128 : &r->out.info->info1);
9847 128 : break;
9848 0 : case 2:
9849 0 : result = getjob_level_2(p->mem_ctx,
9850 : queue, count, snum, pinfo2,
9851 : r->in.job_id, sysjob,
9852 0 : &r->out.info->info2);
9853 0 : break;
9854 0 : default:
9855 0 : result = WERR_INVALID_LEVEL;
9856 0 : break;
9857 : }
9858 :
9859 128 : SAFE_FREE(queue);
9860 128 : TALLOC_FREE(pinfo2);
9861 :
9862 128 : if (!W_ERROR_IS_OK(result)) {
9863 0 : goto err_jinfo_free;
9864 : }
9865 :
9866 128 : *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9867 : r->in.level);
9868 128 : r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9869 :
9870 128 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9871 :
9872 1920 : err_pinfo_free:
9873 3360 : TALLOC_FREE(pinfo2);
9874 1440 : err_jinfo_free:
9875 1920 : TALLOC_FREE(r->out.info);
9876 1920 : return result;
9877 : }
9878 :
9879 : /****************************************************************
9880 : _spoolss_GetPrinterDataEx
9881 : ****************************************************************/
9882 :
9883 3124 : WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9884 : struct spoolss_GetPrinterDataEx *r)
9885 : {
9886 :
9887 3124 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9888 : const char *printer;
9889 3124 : int snum = 0;
9890 3124 : WERROR result = WERR_OK;
9891 : DATA_BLOB blob;
9892 3124 : enum winreg_Type val_type = REG_NONE;
9893 3124 : uint8_t *val_data = NULL;
9894 3124 : uint32_t val_size = 0;
9895 : struct dcerpc_binding_handle *b;
9896 : TALLOC_CTX *tmp_ctx;
9897 :
9898 3124 : DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9899 :
9900 3124 : DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9901 : r->in.key_name, r->in.value_name));
9902 :
9903 : /* in case of problem, return some default values */
9904 :
9905 3124 : *r->out.needed = 0;
9906 3124 : *r->out.type = REG_NONE;
9907 :
9908 3124 : tmp_ctx = talloc_new(p->mem_ctx);
9909 3124 : if (!tmp_ctx) {
9910 0 : return WERR_NOT_ENOUGH_MEMORY;
9911 : }
9912 :
9913 3124 : if (!Printer) {
9914 0 : DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9915 : OUR_HANDLE(r->in.handle)));
9916 0 : result = WERR_INVALID_HANDLE;
9917 0 : goto done;
9918 : }
9919 :
9920 : /* Is the handle to a printer or to the server? */
9921 :
9922 3124 : if (Printer->printer_type == SPLHND_SERVER) {
9923 :
9924 : union spoolss_PrinterData data;
9925 :
9926 348 : result = getprinterdata_printer_server(tmp_ctx,
9927 : r->in.value_name,
9928 : r->out.type,
9929 : &data);
9930 348 : if (!W_ERROR_IS_OK(result)) {
9931 4 : goto done;
9932 : }
9933 :
9934 344 : result = push_spoolss_PrinterData(tmp_ctx, &blob,
9935 344 : *r->out.type, &data);
9936 344 : if (!W_ERROR_IS_OK(result)) {
9937 0 : goto done;
9938 : }
9939 :
9940 344 : *r->out.needed = blob.length;
9941 :
9942 344 : if (r->in.offered >= *r->out.needed) {
9943 176 : memcpy(r->out.data, blob.data, blob.length);
9944 : }
9945 :
9946 344 : result = WERR_OK;
9947 344 : goto done;
9948 : }
9949 :
9950 : /* check to see if the keyname is valid */
9951 2776 : if (!strlen(r->in.key_name)) {
9952 0 : result = WERR_INVALID_PARAMETER;
9953 0 : goto done;
9954 : }
9955 :
9956 2776 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9957 0 : result = WERR_INVALID_HANDLE;
9958 0 : goto done;
9959 : }
9960 2776 : printer = lp_const_servicename(snum);
9961 :
9962 2776 : result = winreg_printer_binding_handle(tmp_ctx,
9963 : get_session_info_system(),
9964 : p->msg_ctx,
9965 : &b);
9966 2776 : if (!W_ERROR_IS_OK(result)) {
9967 0 : goto done;
9968 : }
9969 :
9970 : /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9971 3076 : if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9972 300 : strequal(r->in.value_name, "ChangeId")) {
9973 128 : *r->out.type = REG_DWORD;
9974 128 : *r->out.needed = 4;
9975 128 : if (r->in.offered >= *r->out.needed) {
9976 64 : uint32_t changeid = 0;
9977 :
9978 64 : result = winreg_printer_get_changeid(tmp_ctx, b,
9979 : printer,
9980 : &changeid);
9981 64 : if (!W_ERROR_IS_OK(result)) {
9982 0 : goto done;
9983 : }
9984 :
9985 64 : SIVAL(r->out.data, 0, changeid);
9986 64 : result = WERR_OK;
9987 : }
9988 128 : goto done;
9989 : }
9990 :
9991 2648 : result = winreg_get_printer_dataex(tmp_ctx, b,
9992 : printer,
9993 : r->in.key_name,
9994 : r->in.value_name,
9995 : &val_type,
9996 : &val_data,
9997 : &val_size);
9998 2648 : if (!W_ERROR_IS_OK(result)) {
9999 4 : goto done;
10000 : }
10001 :
10002 2644 : *r->out.needed = val_size;
10003 2644 : *r->out.type = val_type;
10004 :
10005 2644 : if (r->in.offered >= *r->out.needed) {
10006 1340 : memcpy(r->out.data, val_data, val_size);
10007 : }
10008 :
10009 3633 : done:
10010 : /* NOTE: do not replace type when returning WERR_MORE_DATA */
10011 :
10012 3124 : if (W_ERROR_IS_OK(result)) {
10013 3116 : result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
10014 : }
10015 :
10016 3124 : talloc_free(tmp_ctx);
10017 3124 : return result;
10018 : }
10019 :
10020 : /****************************************************************
10021 : _spoolss_SetPrinterDataEx
10022 : ****************************************************************/
10023 :
10024 1368 : WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
10025 : struct spoolss_SetPrinterDataEx *r)
10026 : {
10027 1026 : const struct loadparm_substitution *lp_sub =
10028 342 : loadparm_s3_global_substitution();
10029 1368 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
10030 1368 : int snum = 0;
10031 1368 : WERROR result = WERR_OK;
10032 1368 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10033 : char *oid_string;
10034 : struct dcerpc_binding_handle *b;
10035 : TALLOC_CTX *tmp_ctx;
10036 :
10037 1368 : DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
10038 :
10039 : /* From MSDN documentation of SetPrinterDataEx: pass request to
10040 : SetPrinterData if key is "PrinterDriverData" */
10041 :
10042 1368 : if (!Printer) {
10043 0 : DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
10044 : OUR_HANDLE(r->in.handle)));
10045 0 : return WERR_INVALID_HANDLE;
10046 : }
10047 :
10048 1368 : if (Printer->printer_type == SPLHND_SERVER) {
10049 0 : DEBUG(10,("_spoolss_SetPrinterDataEx: "
10050 : "Not implemented for server handles yet\n"));
10051 0 : return WERR_INVALID_PARAMETER;
10052 : }
10053 :
10054 1368 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10055 0 : return WERR_INVALID_HANDLE;
10056 : }
10057 :
10058 : /*
10059 : * Access check : NT returns "access denied" if you make a
10060 : * SetPrinterData call without the necessary privildge.
10061 : * we were originally returning OK if nothing changed
10062 : * which made Win2k issue **a lot** of SetPrinterData
10063 : * when connecting to a printer --jerry
10064 : */
10065 :
10066 1368 : if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10067 0 : DEBUG(3, ("_spoolss_SetPrinterDataEx: "
10068 : "change denied by handle access permissions\n"));
10069 0 : return WERR_ACCESS_DENIED;
10070 : }
10071 :
10072 1368 : tmp_ctx = talloc_new(p->mem_ctx);
10073 1368 : if (!tmp_ctx) {
10074 0 : return WERR_NOT_ENOUGH_MEMORY;
10075 : }
10076 :
10077 1368 : result = winreg_printer_binding_handle(tmp_ctx,
10078 : get_session_info_system(),
10079 : p->msg_ctx,
10080 : &b);
10081 1368 : if (!W_ERROR_IS_OK(result)) {
10082 0 : goto done;
10083 : }
10084 :
10085 2394 : result = winreg_get_printer(tmp_ctx, b,
10086 1368 : lp_servicename(talloc_tos(), lp_sub, snum),
10087 : &pinfo2);
10088 1368 : if (!W_ERROR_IS_OK(result)) {
10089 0 : goto done;
10090 : }
10091 :
10092 : /* check for OID in valuename */
10093 :
10094 1368 : oid_string = strchr(r->in.value_name, ',');
10095 1368 : if (oid_string) {
10096 0 : *oid_string = '\0';
10097 0 : oid_string++;
10098 : }
10099 :
10100 : /* save the registry data */
10101 :
10102 2394 : result = winreg_set_printer_dataex(tmp_ctx, b,
10103 1368 : pinfo2->sharename,
10104 : r->in.key_name,
10105 : r->in.value_name,
10106 : r->in.type,
10107 : r->in.data,
10108 : r->in.offered);
10109 :
10110 1368 : if (W_ERROR_IS_OK(result)) {
10111 : /* save the OID if one was specified */
10112 1368 : if (oid_string) {
10113 0 : char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
10114 : r->in.key_name, SPOOL_OID_KEY);
10115 0 : if (!str) {
10116 0 : result = WERR_NOT_ENOUGH_MEMORY;
10117 0 : goto done;
10118 : }
10119 :
10120 : /*
10121 : * I'm not checking the status here on purpose. Don't know
10122 : * if this is right, but I'm returning the status from the
10123 : * previous set_printer_dataex() call. I have no idea if
10124 : * this is right. --jerry
10125 : */
10126 0 : winreg_set_printer_dataex(tmp_ctx, b,
10127 0 : pinfo2->sharename,
10128 : str,
10129 : r->in.value_name,
10130 : REG_SZ,
10131 : (uint8_t *) oid_string,
10132 0 : strlen(oid_string) + 1);
10133 : }
10134 :
10135 1368 : result = winreg_printer_update_changeid(tmp_ctx, b,
10136 : lp_const_servicename(snum));
10137 :
10138 : }
10139 :
10140 1026 : done:
10141 1368 : talloc_free(tmp_ctx);
10142 1368 : return result;
10143 : }
10144 :
10145 : /****************************************************************
10146 : _spoolss_DeletePrinterDataEx
10147 : ****************************************************************/
10148 :
10149 1368 : WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
10150 : struct spoolss_DeletePrinterDataEx *r)
10151 : {
10152 : const char *printer;
10153 1368 : int snum=0;
10154 1368 : WERROR status = WERR_OK;
10155 1368 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10156 :
10157 1368 : DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
10158 :
10159 1368 : if (!Printer) {
10160 0 : DEBUG(2,("_spoolss_DeletePrinterDataEx: "
10161 : "Invalid handle (%s:%u:%u).\n",
10162 : OUR_HANDLE(r->in.handle)));
10163 0 : return WERR_INVALID_HANDLE;
10164 : }
10165 :
10166 1368 : if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10167 0 : DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
10168 : "printer properties change denied by handle\n"));
10169 0 : return WERR_ACCESS_DENIED;
10170 : }
10171 :
10172 1368 : if (!r->in.value_name || !r->in.key_name) {
10173 0 : return WERR_NOT_ENOUGH_MEMORY;
10174 : }
10175 :
10176 1368 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10177 0 : return WERR_INVALID_HANDLE;
10178 : }
10179 1368 : printer = lp_const_servicename(snum);
10180 :
10181 1368 : status = winreg_delete_printer_dataex_internal(p->mem_ctx,
10182 : get_session_info_system(),
10183 : p->msg_ctx,
10184 : printer,
10185 : r->in.key_name,
10186 : r->in.value_name);
10187 1368 : if (W_ERROR_IS_OK(status)) {
10188 1368 : status = winreg_printer_update_changeid_internal(p->mem_ctx,
10189 : get_session_info_system(),
10190 : p->msg_ctx,
10191 : printer);
10192 : }
10193 :
10194 1368 : return status;
10195 : }
10196 :
10197 : /****************************************************************
10198 : _spoolss_EnumPrinterKey
10199 : ****************************************************************/
10200 :
10201 3384 : WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
10202 : struct spoolss_EnumPrinterKey *r)
10203 : {
10204 : uint32_t num_keys;
10205 3384 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10206 3384 : int snum = 0;
10207 3384 : WERROR result = WERR_FILE_NOT_FOUND;
10208 3384 : const char **array = NULL;
10209 : DATA_BLOB blob;
10210 :
10211 3384 : DEBUG(4,("_spoolss_EnumPrinterKey\n"));
10212 :
10213 3384 : if (!Printer) {
10214 0 : DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
10215 : OUR_HANDLE(r->in.handle)));
10216 0 : return WERR_INVALID_HANDLE;
10217 : }
10218 :
10219 3384 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10220 0 : return WERR_INVALID_HANDLE;
10221 : }
10222 :
10223 3384 : result = winreg_enum_printer_key_internal(p->mem_ctx,
10224 : get_session_info_system(),
10225 : p->msg_ctx,
10226 : lp_const_servicename(snum),
10227 : r->in.key_name,
10228 : &num_keys,
10229 : &array);
10230 3384 : if (!W_ERROR_IS_OK(result)) {
10231 0 : goto done;
10232 : }
10233 :
10234 3384 : if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
10235 0 : result = WERR_NOT_ENOUGH_MEMORY;
10236 0 : goto done;
10237 : }
10238 :
10239 3384 : *r->out._ndr_size = r->in.offered / 2;
10240 3384 : *r->out.needed = blob.length;
10241 :
10242 3384 : if (r->in.offered < *r->out.needed) {
10243 1304 : result = WERR_MORE_DATA;
10244 : } else {
10245 2080 : result = WERR_OK;
10246 2080 : r->out.key_buffer->string_array = array;
10247 : }
10248 :
10249 3384 : done:
10250 3384 : if (!W_ERROR_IS_OK(result)) {
10251 1304 : TALLOC_FREE(array);
10252 1304 : if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
10253 0 : *r->out.needed = 0;
10254 : }
10255 : }
10256 :
10257 3384 : return result;
10258 : }
10259 :
10260 : /****************************************************************
10261 : _spoolss_DeletePrinterKey
10262 : ****************************************************************/
10263 :
10264 216 : WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
10265 : struct spoolss_DeletePrinterKey *r)
10266 : {
10267 216 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10268 216 : int snum=0;
10269 : WERROR status;
10270 : const char *printer;
10271 : struct dcerpc_binding_handle *b;
10272 : TALLOC_CTX *tmp_ctx;
10273 :
10274 216 : DEBUG(5,("_spoolss_DeletePrinterKey\n"));
10275 :
10276 216 : if (!Printer) {
10277 0 : DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
10278 : OUR_HANDLE(r->in.handle)));
10279 0 : return WERR_INVALID_HANDLE;
10280 : }
10281 :
10282 : /* if keyname == NULL, return error */
10283 216 : if ( !r->in.key_name )
10284 0 : return WERR_INVALID_PARAMETER;
10285 :
10286 216 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10287 0 : return WERR_INVALID_HANDLE;
10288 : }
10289 :
10290 216 : if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10291 0 : DEBUG(3, ("_spoolss_DeletePrinterKey: "
10292 : "printer properties change denied by handle\n"));
10293 0 : return WERR_ACCESS_DENIED;
10294 : }
10295 :
10296 216 : printer = lp_const_servicename(snum);
10297 :
10298 216 : tmp_ctx = talloc_new(p->mem_ctx);
10299 216 : if (!tmp_ctx) {
10300 0 : return WERR_NOT_ENOUGH_MEMORY;
10301 : }
10302 :
10303 216 : status = winreg_printer_binding_handle(tmp_ctx,
10304 : get_session_info_system(),
10305 : p->msg_ctx,
10306 : &b);
10307 216 : if (!W_ERROR_IS_OK(status)) {
10308 0 : goto done;
10309 : }
10310 :
10311 : /* delete the key and all subkeys */
10312 216 : status = winreg_delete_printer_key(tmp_ctx, b,
10313 : printer,
10314 : r->in.key_name);
10315 216 : if (W_ERROR_IS_OK(status)) {
10316 216 : status = winreg_printer_update_changeid(tmp_ctx, b,
10317 : printer);
10318 : }
10319 :
10320 162 : done:
10321 216 : talloc_free(tmp_ctx);
10322 216 : return status;
10323 : }
10324 :
10325 : /****************************************************************
10326 : _spoolss_EnumPrinterDataEx
10327 : ****************************************************************/
10328 :
10329 2860 : WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
10330 : struct spoolss_EnumPrinterDataEx *r)
10331 : {
10332 2860 : uint32_t count = 0;
10333 2860 : struct spoolss_PrinterEnumValues *info = NULL;
10334 2860 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10335 : int snum;
10336 : WERROR result;
10337 :
10338 2860 : DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
10339 :
10340 2860 : *r->out.count = 0;
10341 2860 : *r->out.needed = 0;
10342 2860 : *r->out.info = NULL;
10343 :
10344 2860 : if (!Printer) {
10345 0 : DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
10346 : OUR_HANDLE(r->in.handle)));
10347 0 : return WERR_INVALID_HANDLE;
10348 : }
10349 :
10350 : /*
10351 : * first check for a keyname of NULL or "". Win2k seems to send
10352 : * this a lot and we should send back WERR_INVALID_PARAMETER
10353 : * no need to spend time looking up the printer in this case.
10354 : * --jerry
10355 : */
10356 :
10357 2860 : if (!strlen(r->in.key_name)) {
10358 4 : result = WERR_INVALID_PARAMETER;
10359 4 : goto done;
10360 : }
10361 :
10362 2856 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10363 0 : return WERR_INVALID_HANDLE;
10364 : }
10365 :
10366 : /* now look for a match on the key name */
10367 2856 : result = winreg_enum_printer_dataex_internal(p->mem_ctx,
10368 : get_session_info_system(),
10369 : p->msg_ctx,
10370 : lp_const_servicename(snum),
10371 : r->in.key_name,
10372 : &count,
10373 : &info);
10374 2856 : if (!W_ERROR_IS_OK(result)) {
10375 0 : goto done;
10376 : }
10377 :
10378 : #if 0 /* FIXME - gd */
10379 : /* housekeeping information in the reply */
10380 :
10381 : /* Fix from Martin Zielinski <mz@seh.de> - ensure
10382 : * the hand marshalled container size is a multiple
10383 : * of 4 bytes for RPC alignment.
10384 : */
10385 :
10386 : if (needed % 4) {
10387 : needed += 4-(needed % 4);
10388 : }
10389 : #endif
10390 2856 : *r->out.count = count;
10391 2856 : *r->out.info = info;
10392 :
10393 2860 : done:
10394 2860 : if (!W_ERROR_IS_OK(result)) {
10395 4 : return result;
10396 : }
10397 :
10398 2856 : *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
10399 : spoolss_EnumPrinterDataEx,
10400 : *r->out.info,
10401 : *r->out.count);
10402 2856 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
10403 2856 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
10404 :
10405 2856 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
10406 : }
10407 :
10408 : /****************************************************************************
10409 : ****************************************************************************/
10410 :
10411 40 : static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
10412 : const char *servername,
10413 : const char *environment,
10414 : struct spoolss_PrintProcessorDirectoryInfo1 *r)
10415 : {
10416 : WERROR werr;
10417 40 : char *path = NULL;
10418 :
10419 40 : werr = compose_spoolss_server_path(mem_ctx,
10420 : servername,
10421 : environment,
10422 : SPOOLSS_PRTPROCS_PATH,
10423 : &path);
10424 40 : if (!W_ERROR_IS_OK(werr)) {
10425 0 : return werr;
10426 : }
10427 :
10428 40 : DEBUG(4,("print processor directory: [%s]\n", path));
10429 :
10430 40 : r->directory_name = path;
10431 :
10432 40 : return WERR_OK;
10433 : }
10434 :
10435 : /****************************************************************
10436 : _spoolss_GetPrintProcessorDirectory
10437 : ****************************************************************/
10438 :
10439 40 : WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
10440 : struct spoolss_GetPrintProcessorDirectory *r)
10441 : {
10442 : WERROR result;
10443 40 : char *prnproc_share = NULL;
10444 40 : bool prnproc_share_exists = false;
10445 : int snum;
10446 :
10447 : /* that's an [in out] buffer */
10448 :
10449 40 : if (!r->in.buffer && (r->in.offered != 0)) {
10450 0 : result = WERR_INVALID_PARAMETER;
10451 0 : goto err_info_free;
10452 : }
10453 :
10454 40 : DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
10455 : r->in.level));
10456 :
10457 40 : *r->out.needed = 0;
10458 :
10459 : /* r->in.level is ignored */
10460 :
10461 : /* We always should reply with a local print processor directory so that
10462 : * users are not forced to have a [prnproc$] share on the Samba spoolss
10463 : * server, if users decide to do so, lets announce it though - Guenther */
10464 :
10465 40 : snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
10466 40 : if (!prnproc_share) {
10467 0 : result = WERR_NOT_ENOUGH_MEMORY;
10468 0 : goto err_info_free;
10469 : }
10470 40 : if (snum != -1) {
10471 0 : prnproc_share_exists = true;
10472 : }
10473 :
10474 40 : result = getprintprocessordirectory_level_1(p->mem_ctx,
10475 : prnproc_share_exists ? r->in.server : NULL,
10476 : r->in.environment,
10477 40 : &r->out.info->info1);
10478 40 : if (!W_ERROR_IS_OK(result)) {
10479 0 : goto err_info_free;
10480 : }
10481 :
10482 40 : *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
10483 : r->out.info, r->in.level);
10484 40 : r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10485 :
10486 40 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10487 :
10488 0 : err_info_free:
10489 0 : TALLOC_FREE(r->out.info);
10490 0 : return result;
10491 : }
10492 :
10493 : /*******************************************************************
10494 : ********************************************************************/
10495 :
10496 0 : static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10497 : const char *dllname)
10498 : {
10499 : enum ndr_err_code ndr_err;
10500 : struct spoolss_MonitorUi ui;
10501 :
10502 0 : ui.dll_name = dllname;
10503 :
10504 0 : ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10505 : (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10506 0 : if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10507 0 : NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10508 : }
10509 0 : return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10510 : }
10511 :
10512 : /*******************************************************************
10513 : Streams the monitor UI DLL name in UNICODE
10514 : *******************************************************************/
10515 :
10516 0 : static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10517 : struct security_token *token, DATA_BLOB *in,
10518 : DATA_BLOB *out, uint32_t *needed)
10519 : {
10520 0 : const char *dllname = "tcpmonui.dll";
10521 :
10522 0 : *needed = (strlen(dllname)+1) * 2;
10523 :
10524 0 : if (out->length < *needed) {
10525 0 : return WERR_INSUFFICIENT_BUFFER;
10526 : }
10527 :
10528 0 : if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10529 0 : return WERR_NOT_ENOUGH_MEMORY;
10530 : }
10531 :
10532 0 : return WERR_OK;
10533 : }
10534 :
10535 : /*******************************************************************
10536 : ********************************************************************/
10537 :
10538 0 : static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10539 : struct spoolss_PortData1 *port1,
10540 : const DATA_BLOB *buf)
10541 : {
10542 : enum ndr_err_code ndr_err;
10543 0 : ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10544 : (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10545 0 : if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10546 0 : NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10547 : }
10548 0 : return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10549 : }
10550 :
10551 : /*******************************************************************
10552 : ********************************************************************/
10553 :
10554 0 : static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10555 : struct spoolss_PortData2 *port2,
10556 : const DATA_BLOB *buf)
10557 : {
10558 : enum ndr_err_code ndr_err;
10559 0 : ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10560 : (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10561 0 : if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10562 0 : NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10563 : }
10564 0 : return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10565 : }
10566 :
10567 : /*******************************************************************
10568 : Create a new TCP/IP port
10569 : *******************************************************************/
10570 :
10571 0 : static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10572 : struct security_token *token, DATA_BLOB *in,
10573 : DATA_BLOB *out, uint32_t *needed)
10574 : {
10575 : struct spoolss_PortData1 port1;
10576 : struct spoolss_PortData2 port2;
10577 0 : char *device_uri = NULL;
10578 : uint32_t version;
10579 :
10580 : const char *portname;
10581 : const char *hostaddress;
10582 : const char *queue;
10583 : uint32_t port_number;
10584 : uint32_t protocol;
10585 :
10586 : /* peek for spoolss_PortData version */
10587 :
10588 0 : if (!in || (in->length < (128 + 4))) {
10589 0 : return WERR_GEN_FAILURE;
10590 : }
10591 :
10592 0 : version = IVAL(in->data, 128);
10593 :
10594 0 : switch (version) {
10595 0 : case 1:
10596 0 : ZERO_STRUCT(port1);
10597 :
10598 0 : if (!pull_port_data_1(mem_ctx, &port1, in)) {
10599 0 : return WERR_NOT_ENOUGH_MEMORY;
10600 : }
10601 :
10602 0 : portname = port1.portname;
10603 0 : hostaddress = port1.hostaddress;
10604 0 : queue = port1.queue;
10605 0 : protocol = port1.protocol;
10606 0 : port_number = port1.port_number;
10607 :
10608 0 : break;
10609 0 : case 2:
10610 0 : ZERO_STRUCT(port2);
10611 :
10612 0 : if (!pull_port_data_2(mem_ctx, &port2, in)) {
10613 0 : return WERR_NOT_ENOUGH_MEMORY;
10614 : }
10615 :
10616 0 : portname = port2.portname;
10617 0 : hostaddress = port2.hostaddress;
10618 0 : queue = port2.queue;
10619 0 : protocol = port2.protocol;
10620 0 : port_number = port2.port_number;
10621 :
10622 0 : break;
10623 0 : default:
10624 0 : DEBUG(1,("xcvtcp_addport: "
10625 : "unknown version of port_data: %d\n", version));
10626 0 : return WERR_UNKNOWN_PORT;
10627 : }
10628 :
10629 : /* create the device URI and call the add_port_hook() */
10630 :
10631 0 : switch (protocol) {
10632 0 : case PROTOCOL_RAWTCP_TYPE:
10633 0 : device_uri = talloc_asprintf(mem_ctx,
10634 : "socket://%s:%d/", hostaddress,
10635 : port_number);
10636 0 : break;
10637 :
10638 0 : case PROTOCOL_LPR_TYPE:
10639 0 : device_uri = talloc_asprintf(mem_ctx,
10640 : "lpr://%s/%s", hostaddress, queue );
10641 0 : break;
10642 :
10643 0 : default:
10644 0 : return WERR_UNKNOWN_PORT;
10645 : }
10646 :
10647 0 : if (!device_uri) {
10648 0 : return WERR_NOT_ENOUGH_MEMORY;
10649 : }
10650 :
10651 0 : return add_port_hook(mem_ctx, token, portname, device_uri);
10652 : }
10653 :
10654 : /*******************************************************************
10655 : *******************************************************************/
10656 :
10657 : struct xcv_api_table xcvtcp_cmds[] = {
10658 : { "MonitorUI", xcvtcp_monitorui },
10659 : { "AddPort", xcvtcp_addport},
10660 : { NULL, NULL }
10661 : };
10662 :
10663 0 : static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10664 : struct security_token *token, const char *command,
10665 : DATA_BLOB *inbuf,
10666 : DATA_BLOB *outbuf,
10667 : uint32_t *needed )
10668 : {
10669 : int i;
10670 :
10671 0 : DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10672 :
10673 0 : for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10674 0 : if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10675 0 : return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10676 : }
10677 :
10678 0 : return WERR_INVALID_FUNCTION;
10679 : }
10680 :
10681 : /*******************************************************************
10682 : *******************************************************************/
10683 : #if 0 /* don't support management using the "Local Port" monitor */
10684 :
10685 : static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10686 : struct security_token *token, DATA_BLOB *in,
10687 : DATA_BLOB *out, uint32_t *needed)
10688 : {
10689 : const char *dllname = "localui.dll";
10690 :
10691 : *needed = (strlen(dllname)+1) * 2;
10692 :
10693 : if (out->length < *needed) {
10694 : return WERR_INSUFFICIENT_BUFFER;
10695 : }
10696 :
10697 : if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10698 : return WERR_NOT_ENOUGH_MEMORY;
10699 : }
10700 :
10701 : return WERR_OK;
10702 : }
10703 :
10704 : /*******************************************************************
10705 : *******************************************************************/
10706 :
10707 : struct xcv_api_table xcvlocal_cmds[] = {
10708 : { "MonitorUI", xcvlocal_monitorui },
10709 : { NULL, NULL }
10710 : };
10711 : #else
10712 : struct xcv_api_table xcvlocal_cmds[] = {
10713 : { NULL, NULL }
10714 : };
10715 : #endif
10716 :
10717 :
10718 :
10719 : /*******************************************************************
10720 : *******************************************************************/
10721 :
10722 0 : static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10723 : struct security_token *token, const char *command,
10724 : DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10725 : uint32_t *needed)
10726 : {
10727 : int i;
10728 :
10729 0 : DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10730 :
10731 0 : for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10732 0 : if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10733 0 : return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10734 : }
10735 0 : return WERR_INVALID_FUNCTION;
10736 : }
10737 :
10738 : /****************************************************************
10739 : _spoolss_XcvData
10740 : ****************************************************************/
10741 :
10742 0 : WERROR _spoolss_XcvData(struct pipes_struct *p,
10743 : struct spoolss_XcvData *r)
10744 : {
10745 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10746 0 : DATA_BLOB out_data = data_blob_null;
10747 : WERROR werror;
10748 :
10749 0 : if (!Printer) {
10750 0 : DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10751 : OUR_HANDLE(r->in.handle)));
10752 0 : return WERR_INVALID_HANDLE;
10753 : }
10754 :
10755 : /* Has to be a handle to the TCP/IP port monitor */
10756 :
10757 0 : if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10758 0 : DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10759 0 : return WERR_INVALID_HANDLE;
10760 : }
10761 :
10762 : /* requires administrative access to the server */
10763 :
10764 0 : if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10765 0 : DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10766 0 : return WERR_ACCESS_DENIED;
10767 : }
10768 :
10769 : /* Allocate the outgoing buffer */
10770 :
10771 0 : if (r->in.out_data_size) {
10772 0 : out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10773 0 : if (out_data.data == NULL) {
10774 0 : return WERR_NOT_ENOUGH_MEMORY;
10775 : }
10776 : }
10777 :
10778 0 : switch ( Printer->printer_type ) {
10779 0 : case SPLHND_PORTMON_TCP:
10780 0 : werror = process_xcvtcp_command(p->mem_ctx,
10781 0 : p->session_info->security_token,
10782 : r->in.function_name,
10783 : &r->in.in_data, &out_data,
10784 : r->out.needed);
10785 0 : break;
10786 0 : case SPLHND_PORTMON_LOCAL:
10787 0 : werror = process_xcvlocal_command(p->mem_ctx,
10788 0 : p->session_info->security_token,
10789 : r->in.function_name,
10790 : &r->in.in_data, &out_data,
10791 : r->out.needed);
10792 0 : break;
10793 0 : default:
10794 0 : werror = WERR_INVALID_PRINT_MONITOR;
10795 : }
10796 :
10797 0 : if (!W_ERROR_IS_OK(werror)) {
10798 0 : return werror;
10799 : }
10800 :
10801 0 : *r->out.status_code = 0;
10802 :
10803 0 : if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10804 0 : memcpy(r->out.out_data, out_data.data,
10805 0 : MIN(r->in.out_data_size, out_data.length));
10806 : }
10807 :
10808 0 : return WERR_OK;
10809 : }
10810 :
10811 : /****************************************************************
10812 : _spoolss_AddPrintProcessor
10813 : ****************************************************************/
10814 :
10815 4 : WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10816 : struct spoolss_AddPrintProcessor *r)
10817 : {
10818 : /* for now, just indicate success and ignore the add. We'll
10819 : automatically set the winprint processor for printer
10820 : entries later. Used to debug the LexMark Optra S 1855 PCL
10821 : driver --jerry */
10822 :
10823 4 : return WERR_OK;
10824 : }
10825 :
10826 : /****************************************************************
10827 : _spoolss_AddPort
10828 : ****************************************************************/
10829 :
10830 4 : WERROR _spoolss_AddPort(struct pipes_struct *p,
10831 : struct spoolss_AddPort *r)
10832 : {
10833 : /* do what w2k3 does */
10834 :
10835 4 : return WERR_NOT_SUPPORTED;
10836 : }
10837 :
10838 : /****************************************************************
10839 : _spoolss_GetPrinterDriver
10840 : ****************************************************************/
10841 :
10842 0 : WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10843 : struct spoolss_GetPrinterDriver *r)
10844 : {
10845 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10846 0 : return WERR_NOT_SUPPORTED;
10847 : }
10848 :
10849 : /****************************************************************
10850 : _spoolss_ReadPrinter
10851 : ****************************************************************/
10852 :
10853 0 : WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10854 : struct spoolss_ReadPrinter *r)
10855 : {
10856 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10857 0 : return WERR_NOT_SUPPORTED;
10858 : }
10859 :
10860 : /****************************************************************
10861 : _spoolss_WaitForPrinterChange
10862 : ****************************************************************/
10863 :
10864 0 : WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10865 : struct spoolss_WaitForPrinterChange *r)
10866 : {
10867 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10868 0 : return WERR_NOT_SUPPORTED;
10869 : }
10870 :
10871 : /****************************************************************
10872 : _spoolss_ConfigurePort
10873 : ****************************************************************/
10874 :
10875 0 : WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10876 : struct spoolss_ConfigurePort *r)
10877 : {
10878 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10879 0 : return WERR_NOT_SUPPORTED;
10880 : }
10881 :
10882 : /****************************************************************
10883 : _spoolss_DeletePort
10884 : ****************************************************************/
10885 :
10886 0 : WERROR _spoolss_DeletePort(struct pipes_struct *p,
10887 : struct spoolss_DeletePort *r)
10888 : {
10889 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10890 0 : return WERR_NOT_SUPPORTED;
10891 : }
10892 :
10893 : /****************************************************************
10894 : _spoolss_CreatePrinterIC
10895 : ****************************************************************/
10896 :
10897 0 : WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10898 : struct spoolss_CreatePrinterIC *r)
10899 : {
10900 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10901 0 : return WERR_NOT_SUPPORTED;
10902 : }
10903 :
10904 : /****************************************************************
10905 : _spoolss_PlayGDIScriptOnPrinterIC
10906 : ****************************************************************/
10907 :
10908 0 : WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10909 : struct spoolss_PlayGDIScriptOnPrinterIC *r)
10910 : {
10911 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10912 0 : return WERR_NOT_SUPPORTED;
10913 : }
10914 :
10915 : /****************************************************************
10916 : _spoolss_DeletePrinterIC
10917 : ****************************************************************/
10918 :
10919 0 : WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10920 : struct spoolss_DeletePrinterIC *r)
10921 : {
10922 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10923 0 : return WERR_NOT_SUPPORTED;
10924 : }
10925 :
10926 : /****************************************************************
10927 : _spoolss_AddPrinterConnection
10928 : ****************************************************************/
10929 :
10930 0 : WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10931 : struct spoolss_AddPrinterConnection *r)
10932 : {
10933 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10934 0 : return WERR_NOT_SUPPORTED;
10935 : }
10936 :
10937 : /****************************************************************
10938 : _spoolss_DeletePrinterConnection
10939 : ****************************************************************/
10940 :
10941 0 : WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10942 : struct spoolss_DeletePrinterConnection *r)
10943 : {
10944 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10945 0 : return WERR_NOT_SUPPORTED;
10946 : }
10947 :
10948 : /****************************************************************
10949 : _spoolss_PrinterMessageBox
10950 : ****************************************************************/
10951 :
10952 0 : WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10953 : struct spoolss_PrinterMessageBox *r)
10954 : {
10955 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10956 0 : return WERR_NOT_SUPPORTED;
10957 : }
10958 :
10959 : /****************************************************************
10960 : _spoolss_AddMonitor
10961 : ****************************************************************/
10962 :
10963 0 : WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10964 : struct spoolss_AddMonitor *r)
10965 : {
10966 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10967 0 : return WERR_NOT_SUPPORTED;
10968 : }
10969 :
10970 : /****************************************************************
10971 : _spoolss_DeleteMonitor
10972 : ****************************************************************/
10973 :
10974 0 : WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10975 : struct spoolss_DeleteMonitor *r)
10976 : {
10977 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10978 0 : return WERR_NOT_SUPPORTED;
10979 : }
10980 :
10981 : /****************************************************************
10982 : _spoolss_DeletePrintProcessor
10983 : ****************************************************************/
10984 :
10985 0 : WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10986 : struct spoolss_DeletePrintProcessor *r)
10987 : {
10988 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10989 0 : return WERR_NOT_SUPPORTED;
10990 : }
10991 :
10992 : /****************************************************************
10993 : _spoolss_AddPrintProvidor
10994 : ****************************************************************/
10995 :
10996 0 : WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10997 : struct spoolss_AddPrintProvidor *r)
10998 : {
10999 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11000 0 : return WERR_NOT_SUPPORTED;
11001 : }
11002 :
11003 : /****************************************************************
11004 : _spoolss_DeletePrintProvidor
11005 : ****************************************************************/
11006 :
11007 0 : WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
11008 : struct spoolss_DeletePrintProvidor *r)
11009 : {
11010 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11011 0 : return WERR_NOT_SUPPORTED;
11012 : }
11013 :
11014 : /****************************************************************
11015 : _spoolss_FindFirstPrinterChangeNotification
11016 : ****************************************************************/
11017 :
11018 0 : WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
11019 : struct spoolss_FindFirstPrinterChangeNotification *r)
11020 : {
11021 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11022 0 : return WERR_NOT_SUPPORTED;
11023 : }
11024 :
11025 : /****************************************************************
11026 : _spoolss_FindNextPrinterChangeNotification
11027 : ****************************************************************/
11028 :
11029 0 : WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
11030 : struct spoolss_FindNextPrinterChangeNotification *r)
11031 : {
11032 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11033 0 : return WERR_NOT_SUPPORTED;
11034 : }
11035 :
11036 : /****************************************************************
11037 : _spoolss_RouterFindFirstPrinterChangeNotificationOld
11038 : ****************************************************************/
11039 :
11040 0 : WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
11041 : struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
11042 : {
11043 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11044 0 : return WERR_NOT_SUPPORTED;
11045 : }
11046 :
11047 : /****************************************************************
11048 : _spoolss_ReplyOpenPrinter
11049 : ****************************************************************/
11050 :
11051 0 : WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
11052 : struct spoolss_ReplyOpenPrinter *r)
11053 : {
11054 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11055 0 : return WERR_NOT_SUPPORTED;
11056 : }
11057 :
11058 : /****************************************************************
11059 : _spoolss_RouterReplyPrinter
11060 : ****************************************************************/
11061 :
11062 0 : WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
11063 : struct spoolss_RouterReplyPrinter *r)
11064 : {
11065 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11066 0 : return WERR_NOT_SUPPORTED;
11067 : }
11068 :
11069 : /****************************************************************
11070 : _spoolss_ReplyClosePrinter
11071 : ****************************************************************/
11072 :
11073 0 : WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
11074 : struct spoolss_ReplyClosePrinter *r)
11075 : {
11076 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11077 0 : return WERR_NOT_SUPPORTED;
11078 : }
11079 :
11080 : /****************************************************************
11081 : _spoolss_AddPortEx
11082 : ****************************************************************/
11083 :
11084 0 : WERROR _spoolss_AddPortEx(struct pipes_struct *p,
11085 : struct spoolss_AddPortEx *r)
11086 : {
11087 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11088 0 : return WERR_NOT_SUPPORTED;
11089 : }
11090 :
11091 : /****************************************************************
11092 : _spoolss_RouterFindFirstPrinterChangeNotification
11093 : ****************************************************************/
11094 :
11095 0 : WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
11096 : struct spoolss_RouterFindFirstPrinterChangeNotification *r)
11097 : {
11098 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11099 0 : return WERR_NOT_SUPPORTED;
11100 : }
11101 :
11102 : /****************************************************************
11103 : _spoolss_SpoolerInit
11104 : ****************************************************************/
11105 :
11106 0 : WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
11107 : struct spoolss_SpoolerInit *r)
11108 : {
11109 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11110 0 : return WERR_NOT_SUPPORTED;
11111 : }
11112 :
11113 : /****************************************************************
11114 : _spoolss_ResetPrinterEx
11115 : ****************************************************************/
11116 :
11117 0 : WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
11118 : struct spoolss_ResetPrinterEx *r)
11119 : {
11120 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11121 0 : return WERR_NOT_SUPPORTED;
11122 : }
11123 :
11124 : /****************************************************************
11125 : _spoolss_RouterReplyPrinterEx
11126 : ****************************************************************/
11127 :
11128 0 : WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
11129 : struct spoolss_RouterReplyPrinterEx *r)
11130 : {
11131 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11132 0 : return WERR_NOT_SUPPORTED;
11133 : }
11134 :
11135 : /****************************************************************
11136 : _spoolss_44
11137 : ****************************************************************/
11138 :
11139 0 : WERROR _spoolss_44(struct pipes_struct *p,
11140 : struct spoolss_44 *r)
11141 : {
11142 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11143 0 : return WERR_NOT_SUPPORTED;
11144 : }
11145 :
11146 : /****************************************************************
11147 : _spoolss_SetPort
11148 : ****************************************************************/
11149 :
11150 0 : WERROR _spoolss_SetPort(struct pipes_struct *p,
11151 : struct spoolss_SetPort *r)
11152 : {
11153 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11154 0 : return WERR_NOT_SUPPORTED;
11155 : }
11156 :
11157 : /****************************************************************
11158 : _spoolss_4a
11159 : ****************************************************************/
11160 :
11161 0 : WERROR _spoolss_4a(struct pipes_struct *p,
11162 : struct spoolss_4a *r)
11163 : {
11164 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11165 0 : return WERR_NOT_SUPPORTED;
11166 : }
11167 :
11168 : /****************************************************************
11169 : _spoolss_4b
11170 : ****************************************************************/
11171 :
11172 0 : WERROR _spoolss_4b(struct pipes_struct *p,
11173 : struct spoolss_4b *r)
11174 : {
11175 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11176 0 : return WERR_NOT_SUPPORTED;
11177 : }
11178 :
11179 : /****************************************************************
11180 : _spoolss_4c
11181 : ****************************************************************/
11182 :
11183 0 : WERROR _spoolss_4c(struct pipes_struct *p,
11184 : struct spoolss_4c *r)
11185 : {
11186 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11187 0 : return WERR_NOT_SUPPORTED;
11188 : }
11189 :
11190 : /****************************************************************
11191 : _spoolss_53
11192 : ****************************************************************/
11193 :
11194 0 : WERROR _spoolss_53(struct pipes_struct *p,
11195 : struct spoolss_53 *r)
11196 : {
11197 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11198 0 : return WERR_NOT_SUPPORTED;
11199 : }
11200 :
11201 : /****************************************************************
11202 : _spoolss_AddPerMachineConnection
11203 : ****************************************************************/
11204 :
11205 4 : WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
11206 : struct spoolss_AddPerMachineConnection *r)
11207 : {
11208 4 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11209 4 : return WERR_NOT_SUPPORTED;
11210 : }
11211 :
11212 : /****************************************************************
11213 : _spoolss_DeletePerMachineConnection
11214 : ****************************************************************/
11215 :
11216 0 : WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
11217 : struct spoolss_DeletePerMachineConnection *r)
11218 : {
11219 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11220 0 : return WERR_NOT_SUPPORTED;
11221 : }
11222 :
11223 : /****************************************************************
11224 : _spoolss_EnumPerMachineConnections
11225 : ****************************************************************/
11226 :
11227 0 : WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
11228 : struct spoolss_EnumPerMachineConnections *r)
11229 : {
11230 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11231 0 : return WERR_NOT_SUPPORTED;
11232 : }
11233 :
11234 : /****************************************************************
11235 : _spoolss_5a
11236 : ****************************************************************/
11237 :
11238 0 : WERROR _spoolss_5a(struct pipes_struct *p,
11239 : struct spoolss_5a *r)
11240 : {
11241 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11242 0 : return WERR_NOT_SUPPORTED;
11243 : }
11244 :
11245 : /****************************************************************
11246 : _spoolss_5b
11247 : ****************************************************************/
11248 :
11249 0 : WERROR _spoolss_5b(struct pipes_struct *p,
11250 : struct spoolss_5b *r)
11251 : {
11252 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11253 0 : return WERR_NOT_SUPPORTED;
11254 : }
11255 :
11256 : /****************************************************************
11257 : _spoolss_5c
11258 : ****************************************************************/
11259 :
11260 0 : WERROR _spoolss_5c(struct pipes_struct *p,
11261 : struct spoolss_5c *r)
11262 : {
11263 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11264 0 : return WERR_NOT_SUPPORTED;
11265 : }
11266 :
11267 : /****************************************************************
11268 : _spoolss_5d
11269 : ****************************************************************/
11270 :
11271 0 : WERROR _spoolss_5d(struct pipes_struct *p,
11272 : struct spoolss_5d *r)
11273 : {
11274 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11275 0 : return WERR_NOT_SUPPORTED;
11276 : }
11277 :
11278 : /****************************************************************
11279 : _spoolss_5e
11280 : ****************************************************************/
11281 :
11282 0 : WERROR _spoolss_5e(struct pipes_struct *p,
11283 : struct spoolss_5e *r)
11284 : {
11285 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11286 0 : return WERR_NOT_SUPPORTED;
11287 : }
11288 :
11289 : /****************************************************************
11290 : _spoolss_5f
11291 : ****************************************************************/
11292 :
11293 0 : WERROR _spoolss_5f(struct pipes_struct *p,
11294 : struct spoolss_5f *r)
11295 : {
11296 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11297 0 : return WERR_NOT_SUPPORTED;
11298 : }
11299 :
11300 : /****************************************************************
11301 : _spoolss_60
11302 : ****************************************************************/
11303 :
11304 0 : WERROR _spoolss_60(struct pipes_struct *p,
11305 : struct spoolss_60 *r)
11306 : {
11307 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11308 0 : return WERR_NOT_SUPPORTED;
11309 : }
11310 :
11311 : /****************************************************************
11312 : _spoolss_SendRecvBidiData
11313 : ****************************************************************/
11314 :
11315 0 : WERROR _spoolss_SendRecvBidiData(struct pipes_struct *p,
11316 : struct spoolss_SendRecvBidiData *r)
11317 : {
11318 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11319 0 : return WERR_NOT_SUPPORTED;
11320 : }
11321 :
11322 : /****************************************************************
11323 : _spoolss_62
11324 : ****************************************************************/
11325 :
11326 0 : WERROR _spoolss_62(struct pipes_struct *p,
11327 : struct spoolss_62 *r)
11328 : {
11329 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11330 0 : return WERR_NOT_SUPPORTED;
11331 : }
11332 :
11333 : /****************************************************************
11334 : _spoolss_63
11335 : ****************************************************************/
11336 :
11337 0 : WERROR _spoolss_63(struct pipes_struct *p,
11338 : struct spoolss_63 *r)
11339 : {
11340 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11341 0 : return WERR_NOT_SUPPORTED;
11342 : }
11343 :
11344 : /****************************************************************
11345 : _spoolss_64
11346 : ****************************************************************/
11347 :
11348 0 : WERROR _spoolss_64(struct pipes_struct *p,
11349 : struct spoolss_64 *r)
11350 : {
11351 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11352 0 : return WERR_NOT_SUPPORTED;
11353 : }
11354 :
11355 : /****************************************************************
11356 : _spoolss_65
11357 : ****************************************************************/
11358 :
11359 0 : WERROR _spoolss_65(struct pipes_struct *p,
11360 : struct spoolss_65 *r)
11361 : {
11362 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11363 0 : return WERR_NOT_SUPPORTED;
11364 : }
11365 :
11366 : /****************************************************************
11367 : _spoolss_GetCorePrinterDrivers
11368 : ****************************************************************/
11369 :
11370 8 : HRESULT _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
11371 : struct spoolss_GetCorePrinterDrivers *r)
11372 : {
11373 8 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11374 8 : return HRES_ERROR_NOT_SUPPORTED;
11375 : }
11376 :
11377 : /****************************************************************
11378 : _spoolss_67
11379 : ****************************************************************/
11380 :
11381 0 : WERROR _spoolss_67(struct pipes_struct *p,
11382 : struct spoolss_67 *r)
11383 : {
11384 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11385 0 : return WERR_NOT_SUPPORTED;
11386 : }
11387 :
11388 : /****************************************************************
11389 : _spoolss_GetPrinterDriverPackagePath
11390 : ****************************************************************/
11391 :
11392 4 : HRESULT _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
11393 : struct spoolss_GetPrinterDriverPackagePath *r)
11394 : {
11395 4 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11396 4 : return HRES_ERROR_NOT_SUPPORTED;
11397 : }
11398 :
11399 : /****************************************************************
11400 : _spoolss_69
11401 : ****************************************************************/
11402 :
11403 0 : WERROR _spoolss_69(struct pipes_struct *p,
11404 : struct spoolss_69 *r)
11405 : {
11406 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11407 0 : return WERR_NOT_SUPPORTED;
11408 : }
11409 :
11410 : /****************************************************************
11411 : _spoolss_6a
11412 : ****************************************************************/
11413 :
11414 0 : WERROR _spoolss_6a(struct pipes_struct *p,
11415 : struct spoolss_6a *r)
11416 : {
11417 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11418 0 : return WERR_NOT_SUPPORTED;
11419 : }
11420 :
11421 : /****************************************************************
11422 : _spoolss_6b
11423 : ****************************************************************/
11424 :
11425 0 : WERROR _spoolss_6b(struct pipes_struct *p,
11426 : struct spoolss_6b *r)
11427 : {
11428 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11429 0 : return WERR_NOT_SUPPORTED;
11430 : }
11431 :
11432 : /****************************************************************
11433 : _spoolss_6c
11434 : ****************************************************************/
11435 :
11436 0 : WERROR _spoolss_6c(struct pipes_struct *p,
11437 : struct spoolss_6c *r)
11438 : {
11439 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11440 0 : return WERR_NOT_SUPPORTED;
11441 : }
11442 :
11443 : /****************************************************************
11444 : _spoolss_6d
11445 : ****************************************************************/
11446 :
11447 0 : WERROR _spoolss_6d(struct pipes_struct *p,
11448 : struct spoolss_6d *r)
11449 : {
11450 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11451 0 : return WERR_NOT_SUPPORTED;
11452 : }
11453 :
11454 : /****************************************************************
11455 : _spoolss_GetJobNamedPropertyValue
11456 : ****************************************************************/
11457 :
11458 0 : WERROR _spoolss_GetJobNamedPropertyValue(struct pipes_struct *p,
11459 : struct spoolss_GetJobNamedPropertyValue *r)
11460 : {
11461 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11462 0 : return WERR_NOT_SUPPORTED;
11463 : }
11464 :
11465 : /****************************************************************
11466 : _spoolss_SetJobNamedProperty
11467 : ****************************************************************/
11468 :
11469 0 : WERROR _spoolss_SetJobNamedProperty(struct pipes_struct *p,
11470 : struct spoolss_SetJobNamedProperty *r)
11471 : {
11472 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11473 0 : return WERR_NOT_SUPPORTED;
11474 : }
11475 :
11476 : /****************************************************************
11477 : _spoolss_DeleteJobNamedProperty
11478 : ****************************************************************/
11479 :
11480 0 : WERROR _spoolss_DeleteJobNamedProperty(struct pipes_struct *p,
11481 : struct spoolss_DeleteJobNamedProperty *r)
11482 : {
11483 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11484 0 : return WERR_NOT_SUPPORTED;
11485 : }
11486 :
11487 : /****************************************************************
11488 : _spoolss_EnumJobNamedProperties
11489 : ****************************************************************/
11490 :
11491 0 : WERROR _spoolss_EnumJobNamedProperties(struct pipes_struct *p,
11492 : struct spoolss_EnumJobNamedProperties *r)
11493 : {
11494 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11495 0 : return WERR_NOT_SUPPORTED;
11496 : }
11497 :
11498 : /****************************************************************
11499 : _spoolss_72
11500 : ****************************************************************/
11501 :
11502 0 : WERROR _spoolss_72(struct pipes_struct *p,
11503 : struct spoolss_72 *r)
11504 : {
11505 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11506 0 : return WERR_NOT_SUPPORTED;
11507 : }
11508 :
11509 : /****************************************************************
11510 : _spoolss_73
11511 : ****************************************************************/
11512 :
11513 0 : WERROR _spoolss_73(struct pipes_struct *p,
11514 : struct spoolss_73 *r)
11515 : {
11516 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11517 0 : return WERR_NOT_SUPPORTED;
11518 : }
11519 :
11520 : /****************************************************************
11521 : _spoolss_RpcLogJobInfoForBranchOffice
11522 : ****************************************************************/
11523 :
11524 8 : WERROR _spoolss_LogJobInfoForBranchOffice(struct pipes_struct *p,
11525 : struct spoolss_LogJobInfoForBranchOffice *r)
11526 : {
11527 8 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11528 8 : return WERR_NOT_SUPPORTED;
11529 : }
11530 :
11531 : static NTSTATUS spoolss__op_init_server(struct dcesrv_context *dce_ctx,
11532 : const struct dcesrv_endpoint_server *ep_server);
11533 :
11534 : static NTSTATUS spoolss__op_shutdown_server(struct dcesrv_context *dce_ctx,
11535 : const struct dcesrv_endpoint_server *ep_server);
11536 :
11537 : #define DCESRV_INTERFACE_SPOOLSS_INIT_SERVER \
11538 : spoolss_init_server
11539 :
11540 : #define DCESRV_INTERFACE_SPOOLSS_SHUTDOWN_SERVER \
11541 : spoolss_shutdown_server
11542 :
11543 60 : static NTSTATUS spoolss_init_server(struct dcesrv_context *dce_ctx,
11544 : const struct dcesrv_endpoint_server *ep_server)
11545 : {
11546 60 : struct messaging_context *msg_ctx = global_messaging_context();
11547 : NTSTATUS status;
11548 : bool ok;
11549 :
11550 60 : status = dcesrv_init_ep_server(dce_ctx, "winreg");
11551 60 : if (!NT_STATUS_IS_OK(status)) {
11552 0 : return status;
11553 : }
11554 :
11555 : /*
11556 : * Migrate the printers first.
11557 : */
11558 60 : ok = nt_printing_tdb_migrate(msg_ctx);
11559 60 : if (!ok) {
11560 0 : return NT_STATUS_UNSUCCESSFUL;
11561 : }
11562 :
11563 60 : return spoolss__op_init_server(dce_ctx, ep_server);
11564 : }
11565 :
11566 1 : static NTSTATUS spoolss_shutdown_server(struct dcesrv_context *dce_ctx,
11567 : const struct dcesrv_endpoint_server *ep_server)
11568 : {
11569 1 : srv_spoolss_cleanup();
11570 :
11571 1 : return spoolss__op_shutdown_server(dce_ctx, ep_server);
11572 : }
11573 :
11574 : /* include the generated boilerplate */
11575 : #include "librpc/gen_ndr/ndr_spoolss_scompat.c"
|