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 2 : static const char *canon_servername(const char *servername)
151 : {
152 2 : const char *pservername = servername;
153 :
154 2 : if (servername == NULL) {
155 0 : return "";
156 : }
157 :
158 7 : while (*pservername == '\\') {
159 4 : pservername++;
160 : }
161 2 : return pservername;
162 : }
163 :
164 : /* translate between internal status numbers and NT status numbers */
165 0 : static int nt_printj_status(int v)
166 : {
167 0 : switch (v) {
168 0 : case LPQ_QUEUED:
169 0 : 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 0 : static int nt_printq_status(int v)
197 : {
198 0 : switch (v) {
199 0 : case LPQ_PAUSED:
200 0 : return PRINTER_STATUS_PAUSED;
201 0 : case LPQ_QUEUED:
202 : case LPQ_SPOOLING:
203 : case LPQ_PRINTING:
204 0 : 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 2 : static int printer_entry_destructor(struct printer_handle *Printer)
278 : {
279 3 : 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 0 : }
298 :
299 2 : Printer->notify.flags=0;
300 2 : Printer->notify.options=0;
301 2 : Printer->notify.localmachine[0]='\0';
302 2 : Printer->notify.printerlocal=0;
303 2 : TALLOC_FREE(Printer->notify.option);
304 2 : TALLOC_FREE(Printer->devmode);
305 :
306 : /* Remove from the internal list. */
307 2 : DLIST_REMOVE(printers_list, Printer);
308 2 : return 0;
309 : }
310 :
311 : /****************************************************************************
312 : find printer index by handle
313 : ****************************************************************************/
314 :
315 16 : static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
316 : struct policy_handle *hnd)
317 : {
318 16 : struct printer_handle *find_printer = NULL;
319 : NTSTATUS status;
320 :
321 16 : find_printer = find_policy_by_hnd(p,
322 : hnd,
323 : DCESRV_HANDLE_ANY,
324 : struct printer_handle,
325 : &status);
326 16 : 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 16 : return find_printer;
332 : }
333 :
334 : /****************************************************************************
335 : Close printer index by handle.
336 : ****************************************************************************/
337 :
338 2 : static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
339 : {
340 2 : struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
341 :
342 2 : 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 2 : close_policy_hnd(p, hnd);
349 :
350 2 : return true;
351 : }
352 :
353 : /****************************************************************************
354 : Delete a printer given a handle.
355 : ****************************************************************************/
356 :
357 0 : static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
358 : const char *sharename,
359 : struct messaging_context *msg_ctx)
360 : {
361 0 : const struct loadparm_substitution *lp_sub =
362 0 : loadparm_s3_global_substitution();
363 0 : char *cmd = lp_deleteprinter_command(talloc_tos(), lp_sub);
364 0 : char *command = NULL;
365 : int ret;
366 0 : bool is_print_op = false;
367 :
368 : /* can't fail if we don't try */
369 :
370 0 : if ( !*cmd )
371 0 : return WERR_OK;
372 :
373 0 : command = talloc_asprintf(ctx,
374 : "%s \"%s\"",
375 : cmd, sharename);
376 0 : if (!command) {
377 0 : return WERR_NOT_ENOUGH_MEMORY;
378 : }
379 0 : if ( token )
380 0 : is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
381 :
382 0 : DEBUG(10,("Running [%s]\n", command));
383 :
384 : /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
385 :
386 0 : if ( is_print_op )
387 0 : become_root();
388 :
389 0 : ret = smbrun(command, NULL, NULL);
390 0 : if (ret == 0) {
391 : /* Tell everyone we updated smb.conf. */
392 0 : messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
393 : }
394 :
395 0 : if ( is_print_op )
396 0 : unbecome_root();
397 :
398 : /********** END SePrintOperatorPrivlege BLOCK **********/
399 :
400 0 : DEBUGADD(10,("returned [%d]\n", ret));
401 :
402 0 : TALLOC_FREE(command);
403 :
404 0 : if (ret != 0)
405 0 : return WERR_INVALID_HANDLE; /* What to return here? */
406 :
407 0 : return WERR_OK;
408 : }
409 :
410 : /****************************************************************************
411 : Delete a printer given a handle.
412 : ****************************************************************************/
413 :
414 0 : static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
415 : {
416 0 : struct dcesrv_call_state *dce_call = p->dce_call;
417 0 : struct auth_session_info *session_info =
418 0 : dcesrv_call_session_info(dce_call);
419 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
420 : WERROR result;
421 :
422 0 : if (!Printer) {
423 0 : DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
424 : OUR_HANDLE(hnd)));
425 0 : return WERR_INVALID_HANDLE;
426 : }
427 :
428 : /*
429 : * It turns out that Windows allows delete printer on a handle
430 : * opened by an admin user, then used on a pipe handle created
431 : * by an anonymous user..... but they're working on security.... riiight !
432 : * JRA.
433 : */
434 :
435 0 : if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
436 0 : DEBUG(3, ("delete_printer_handle: denied by handle\n"));
437 0 : return WERR_ACCESS_DENIED;
438 : }
439 :
440 : /* this does not need a become root since the access check has been
441 : done on the handle already */
442 :
443 0 : result = winreg_delete_printer_key_internal(p->mem_ctx,
444 : get_session_info_system(),
445 : p->msg_ctx,
446 0 : Printer->sharename,
447 : "");
448 0 : if (!W_ERROR_IS_OK(result)) {
449 0 : DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
450 0 : return WERR_INVALID_HANDLE;
451 : }
452 :
453 0 : result = delete_printer_hook(p->mem_ctx, session_info->security_token,
454 0 : Printer->sharename, p->msg_ctx);
455 0 : if (!W_ERROR_IS_OK(result)) {
456 0 : return result;
457 : }
458 0 : prune_printername_cache();
459 0 : return WERR_OK;
460 : }
461 :
462 : /****************************************************************************
463 : Return the snum of a printer corresponding to an handle.
464 : ****************************************************************************/
465 :
466 0 : static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
467 : int *number, struct share_params **params)
468 : {
469 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
470 :
471 0 : if (!Printer) {
472 0 : DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
473 : OUR_HANDLE(hnd)));
474 0 : return false;
475 : }
476 :
477 0 : switch (Printer->printer_type) {
478 0 : case SPLHND_PRINTER:
479 0 : DEBUG(4,("short name:%s\n", Printer->sharename));
480 0 : *number = print_queue_snum(Printer->sharename);
481 0 : return (*number != -1);
482 0 : case SPLHND_SERVER:
483 0 : return false;
484 0 : default:
485 0 : return false;
486 : }
487 : }
488 :
489 : /****************************************************************************
490 : Set printer handle type.
491 : Check if it's \\server or \\server\printer
492 : ****************************************************************************/
493 :
494 2 : static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
495 : {
496 2 : DEBUG(3,("Setting printer type=%s\n", handlename));
497 :
498 : /* it's a print server */
499 2 : if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
500 2 : DEBUGADD(4,("Printer is a print server\n"));
501 2 : Printer->printer_type = SPLHND_SERVER;
502 : }
503 : /* it's a printer (set_printer_hnd_name() will handle port monitors */
504 : else {
505 0 : DEBUGADD(4,("Printer is a printer\n"));
506 0 : Printer->printer_type = SPLHND_PRINTER;
507 : }
508 :
509 2 : return true;
510 : }
511 :
512 0 : static void prune_printername_cache_fn(const char *key, const char *value,
513 : time_t timeout, void *private_data)
514 : {
515 0 : gencache_del(key);
516 0 : }
517 :
518 0 : static void prune_printername_cache(void)
519 : {
520 0 : gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
521 0 : }
522 :
523 : /****************************************************************************
524 : Set printer handle name.. Accept names like \\server, \\server\printer,
525 : \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
526 : the MSDN docs regarding OpenPrinter() for details on the XcvData() and
527 : XcvDataPort() interface.
528 : ****************************************************************************/
529 :
530 2 : static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
531 : const struct auth_session_info *session_info,
532 : struct messaging_context *msg_ctx,
533 : struct printer_handle *Printer,
534 : const char *handlename)
535 : {
536 : int snum;
537 2 : int n_services=lp_numservices();
538 : char *aprinter;
539 : const char *printername;
540 2 : const char *servername = NULL;
541 : fstring sname;
542 2 : bool found = false;
543 2 : struct spoolss_PrinterInfo2 *info2 = NULL;
544 : WERROR result;
545 : char *p;
546 :
547 : /*
548 : * Hopefully nobody names his printers like this. Maybe \ or ,
549 : * are illegal in printer names even?
550 : */
551 2 : const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
552 : char *cache_key;
553 : char *tmp;
554 :
555 2 : DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
556 : (unsigned long)strlen(handlename)));
557 :
558 2 : aprinter = discard_const_p(char, handlename);
559 2 : if ( *handlename == '\\' ) {
560 2 : servername = canon_servername(handlename);
561 2 : if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
562 0 : *aprinter = '\0';
563 0 : aprinter++;
564 : }
565 2 : if (!is_myname_or_ipaddr(servername)) {
566 0 : return WERR_INVALID_PRINTER_NAME;
567 : }
568 2 : Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
569 2 : if (Printer->servername == NULL) {
570 0 : return WERR_NOT_ENOUGH_MEMORY;
571 : }
572 : }
573 :
574 2 : if (Printer->printer_type == SPLHND_SERVER) {
575 2 : return WERR_OK;
576 : }
577 :
578 0 : if (Printer->printer_type != SPLHND_PRINTER) {
579 0 : return WERR_INVALID_HANDLE;
580 : }
581 :
582 0 : DEBUGADD(5, ("searching for [%s]\n", aprinter));
583 :
584 0 : p = strchr(aprinter, ',');
585 0 : if (p != NULL) {
586 0 : char *p2 = p;
587 0 : p++;
588 0 : if (*p == ' ') {
589 0 : p++;
590 : }
591 0 : if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
592 0 : *p2 = '\0';
593 0 : } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
594 0 : *p2 = '\0';
595 : }
596 : }
597 :
598 0 : if (p) {
599 0 : DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
600 : }
601 :
602 : /* check for the Port Monitor Interface */
603 0 : if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
604 0 : Printer->printer_type = SPLHND_PORTMON_TCP;
605 0 : fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
606 0 : found = true;
607 : }
608 0 : else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
609 0 : Printer->printer_type = SPLHND_PORTMON_LOCAL;
610 0 : fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
611 0 : found = true;
612 : }
613 :
614 0 : cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s", aprinter);
615 0 : if (cache_key == NULL) {
616 0 : return WERR_NOT_ENOUGH_MEMORY;
617 : }
618 :
619 : /*
620 : * With hundreds of printers, the "for" loop iterating all
621 : * shares can be quite expensive, as it is done on every
622 : * OpenPrinter. The loop maps "aprinter" to "sname", the
623 : * result of which we cache in gencache.
624 : */
625 0 : if (gencache_get(cache_key, talloc_tos(), &tmp, NULL)) {
626 0 : found = (strcmp(tmp, printer_not_found) != 0);
627 0 : if (!found) {
628 0 : DEBUG(4, ("Printer %s not found\n", aprinter));
629 0 : TALLOC_FREE(tmp);
630 0 : return WERR_INVALID_PRINTER_NAME;
631 : }
632 0 : fstrcpy(sname, tmp);
633 0 : TALLOC_FREE(tmp);
634 : }
635 :
636 : /* Search all sharenames first as this is easier than pulling
637 : the printer_info_2 off of disk. Don't use find_service() since
638 : that calls out to map_username() */
639 :
640 : /* do another loop to look for printernames */
641 0 : for (snum = 0; !found && snum < n_services; snum++) {
642 0 : const char *printer = lp_const_servicename(snum);
643 :
644 : /* no point going on if this is not a printer */
645 0 : if (!(lp_snum_ok(snum) && lp_printable(snum))) {
646 0 : continue;
647 : }
648 :
649 : /* ignore [printers] share */
650 0 : if (strequal(printer, "printers")) {
651 0 : continue;
652 : }
653 :
654 0 : fstrcpy(sname, printer);
655 0 : if (strequal(aprinter, printer)) {
656 0 : found = true;
657 0 : break;
658 : }
659 :
660 : /* no point looking up the printer object if
661 : we aren't allowing printername != sharename */
662 0 : if (lp_force_printername(snum)) {
663 0 : continue;
664 : }
665 :
666 0 : result = winreg_get_printer_internal(mem_ctx,
667 : session_info,
668 : msg_ctx,
669 : sname,
670 : &info2);
671 0 : if ( !W_ERROR_IS_OK(result) ) {
672 0 : DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
673 : sname, win_errstr(result)));
674 0 : continue;
675 : }
676 :
677 0 : printername = strrchr(info2->printername, '\\');
678 0 : if (printername == NULL) {
679 0 : printername = info2->printername;
680 : } else {
681 0 : printername++;
682 : }
683 :
684 0 : if (strequal(printername, aprinter)) {
685 0 : found = true;
686 0 : break;
687 : }
688 :
689 0 : DEBUGADD(10, ("printername: %s\n", printername));
690 :
691 0 : TALLOC_FREE(info2);
692 : }
693 :
694 0 : if (!found) {
695 0 : gencache_set(cache_key, printer_not_found,
696 0 : time(NULL) + 300);
697 0 : TALLOC_FREE(cache_key);
698 0 : DEBUGADD(4,("Printer not found\n"));
699 0 : return WERR_INVALID_PRINTER_NAME;
700 : }
701 :
702 0 : gencache_set(cache_key, sname, time(NULL) + 300);
703 0 : TALLOC_FREE(cache_key);
704 :
705 0 : DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
706 :
707 0 : strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
708 :
709 0 : return WERR_OK;
710 : }
711 :
712 : /****************************************************************************
713 : Find first available printer slot. creates a printer handle for you.
714 : ****************************************************************************/
715 :
716 2 : static WERROR open_printer_hnd(struct pipes_struct *p,
717 : struct policy_handle *hnd,
718 : const char *name,
719 : uint32_t access_granted)
720 : {
721 : struct printer_handle *new_printer;
722 : WERROR result;
723 :
724 2 : DEBUG(10,("open_printer_hnd: name [%s]\n", name));
725 :
726 2 : new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
727 2 : if (new_printer == NULL) {
728 0 : return WERR_NOT_ENOUGH_MEMORY;
729 : }
730 2 : talloc_set_destructor(new_printer, printer_entry_destructor);
731 :
732 : /* This also steals the printer_handle on the policy_handle */
733 2 : if (!create_policy_hnd(p, hnd, 0, new_printer)) {
734 0 : TALLOC_FREE(new_printer);
735 0 : return WERR_INVALID_HANDLE;
736 : }
737 :
738 : /* Add to the internal list. */
739 2 : DLIST_ADD(printers_list, new_printer);
740 :
741 2 : new_printer->notify.option=NULL;
742 :
743 2 : if (!set_printer_hnd_printertype(new_printer, name)) {
744 0 : close_printer_handle(p, hnd);
745 0 : return WERR_INVALID_HANDLE;
746 : }
747 :
748 2 : result = set_printer_hnd_name(p->mem_ctx,
749 : get_session_info_system(),
750 : p->msg_ctx,
751 : new_printer, name);
752 2 : if (!W_ERROR_IS_OK(result)) {
753 0 : close_printer_handle(p, hnd);
754 0 : return result;
755 : }
756 :
757 2 : new_printer->access_granted = access_granted;
758 :
759 2 : DBG_INFO("%d printer handles active\n", (int)num_pipe_handles());
760 :
761 2 : return WERR_OK;
762 : }
763 :
764 : /***************************************************************************
765 : check to see if the client motify handle is monitoring the notification
766 : given by (notify_type, notify_field).
767 : **************************************************************************/
768 :
769 0 : static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
770 : uint16_t notify_field)
771 : {
772 0 : return true;
773 : }
774 :
775 0 : static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
776 : uint16_t notify_field)
777 : {
778 0 : struct spoolss_NotifyOption *option = p->notify.option;
779 : uint32_t i, j;
780 :
781 : /*
782 : * Flags should always be zero when the change notify
783 : * is registered by the client's spooler. A user Win32 app
784 : * might use the flags though instead of the NOTIFY_OPTION_INFO
785 : * --jerry
786 : */
787 :
788 0 : if (!option) {
789 0 : return false;
790 : }
791 :
792 0 : if (p->notify.flags)
793 0 : return is_monitoring_event_flags(
794 : p->notify.flags, notify_type, notify_field);
795 :
796 0 : for (i = 0; i < option->count; i++) {
797 :
798 : /* Check match for notify_type */
799 :
800 0 : if (option->types[i].type != notify_type)
801 0 : continue;
802 :
803 : /* Check match for field */
804 :
805 0 : for (j = 0; j < option->types[i].count; j++) {
806 0 : if (option->types[i].fields[j].field == notify_field) {
807 0 : return true;
808 : }
809 : }
810 : }
811 :
812 0 : DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
813 : p->servername, p->sharename, notify_type, notify_field));
814 :
815 0 : return false;
816 : }
817 :
818 : #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
819 : _data->data.integer[0] = _integer; \
820 : _data->data.integer[1] = 0;
821 :
822 :
823 : #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
824 : _data->data.string.string = talloc_strdup(mem_ctx, _p); \
825 : if (!_data->data.string.string) {\
826 : _data->data.string.size = 0; \
827 : } \
828 : _data->data.string.size = strlen_m_term(_p) * 2;
829 :
830 : #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
831 : _data->data.devmode.devmode = _devmode;
832 :
833 0 : static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
834 : struct tm *t,
835 : const char **pp,
836 : uint32_t *plen)
837 : {
838 : struct spoolss_Time st;
839 0 : uint32_t len = 16;
840 : char *p;
841 :
842 0 : if (!init_systemtime(&st, t)) {
843 0 : return;
844 : }
845 :
846 0 : p = talloc_array(mem_ctx, char, len);
847 0 : if (!p) {
848 0 : return;
849 : }
850 :
851 : /*
852 : * Systemtime must be linearized as a set of UINT16's.
853 : * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
854 : */
855 :
856 0 : SSVAL(p, 0, st.year);
857 0 : SSVAL(p, 2, st.month);
858 0 : SSVAL(p, 4, st.day_of_week);
859 0 : SSVAL(p, 6, st.day);
860 0 : SSVAL(p, 8, st.hour);
861 0 : SSVAL(p, 10, st.minute);
862 0 : SSVAL(p, 12, st.second);
863 0 : SSVAL(p, 14, st.millisecond);
864 :
865 0 : *pp = p;
866 0 : *plen = len;
867 : }
868 :
869 : /* Convert a notification message to a struct spoolss_Notify */
870 :
871 0 : static void notify_one_value(struct spoolss_notify_msg *msg,
872 : struct spoolss_Notify *data,
873 : TALLOC_CTX *mem_ctx)
874 : {
875 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
876 0 : }
877 :
878 0 : static void notify_string(struct spoolss_notify_msg *msg,
879 : struct spoolss_Notify *data,
880 : TALLOC_CTX *mem_ctx)
881 : {
882 : /* The length of the message includes the trailing \0 */
883 :
884 0 : data->data.string.size = msg->len * 2;
885 0 : data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
886 0 : if (!data->data.string.string) {
887 0 : data->data.string.size = 0;
888 0 : return;
889 : }
890 : }
891 :
892 0 : static void notify_system_time(struct spoolss_notify_msg *msg,
893 : struct spoolss_Notify *data,
894 : TALLOC_CTX *mem_ctx)
895 : {
896 0 : data->data.string.string = NULL;
897 0 : data->data.string.size = 0;
898 :
899 0 : if (msg->len != sizeof(time_t)) {
900 0 : DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
901 : msg->len));
902 0 : return;
903 : }
904 :
905 0 : init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
906 : &data->data.string.string,
907 : &data->data.string.size);
908 : }
909 :
910 : struct notify2_message_table {
911 : const char *name;
912 : void (*fn)(struct spoolss_notify_msg *msg,
913 : struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
914 : };
915 :
916 : static struct notify2_message_table printer_notify_table[] = {
917 : /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
918 : /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
919 : /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
920 : /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
921 : /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
922 : /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
923 : /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
924 : /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
925 : /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
926 : /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
927 : /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
928 : /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
929 : /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
930 : /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
931 : /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
932 : /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
933 : /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
934 : /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
935 : /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
936 : };
937 :
938 : static struct notify2_message_table job_notify_table[] = {
939 : /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
940 : /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
941 : /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
942 : /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
943 : /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
944 : /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
945 : /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
946 : /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
947 : /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
948 : /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
949 : /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
950 : /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
951 : /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
952 : /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
953 : /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
954 : /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
955 : /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
956 : /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
957 : /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
958 : /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
959 : /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
960 : /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
961 : /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
962 : /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
963 : };
964 :
965 :
966 : /***********************************************************************
967 : Allocate talloc context for container object
968 : **********************************************************************/
969 :
970 0 : static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
971 : {
972 0 : if ( !ctr )
973 0 : return;
974 :
975 0 : ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
976 :
977 0 : return;
978 : }
979 :
980 : /***********************************************************************
981 : release all allocated memory and zero out structure
982 : **********************************************************************/
983 :
984 0 : static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
985 : {
986 0 : if ( !ctr )
987 0 : return;
988 :
989 0 : if ( ctr->ctx )
990 0 : talloc_destroy(ctr->ctx);
991 :
992 0 : ZERO_STRUCTP(ctr);
993 :
994 0 : return;
995 : }
996 :
997 : /***********************************************************************
998 : **********************************************************************/
999 :
1000 0 : static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1001 : {
1002 0 : if ( !ctr )
1003 0 : return NULL;
1004 :
1005 0 : return ctr->ctx;
1006 : }
1007 :
1008 : /***********************************************************************
1009 : **********************************************************************/
1010 :
1011 0 : static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1012 : {
1013 0 : if ( !ctr || !ctr->msg_groups )
1014 0 : return NULL;
1015 :
1016 0 : if ( idx >= ctr->num_groups )
1017 0 : return NULL;
1018 :
1019 0 : return &ctr->msg_groups[idx];
1020 :
1021 : }
1022 :
1023 : /***********************************************************************
1024 : How many groups of change messages do we have ?
1025 : **********************************************************************/
1026 :
1027 0 : static uint32_t notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1028 : {
1029 0 : if ( !ctr )
1030 0 : return 0;
1031 :
1032 0 : return ctr->num_groups;
1033 : }
1034 :
1035 : /***********************************************************************
1036 : Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1037 : **********************************************************************/
1038 :
1039 0 : static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1040 : {
1041 0 : SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
1042 0 : SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
1043 0 : SPOOLSS_NOTIFY_MSG *msg_list = NULL;
1044 : uint32_t i, new_slot;
1045 :
1046 0 : if ( !ctr || !msg )
1047 0 : return 0;
1048 :
1049 : /* loop over all groups looking for a matching printer name */
1050 :
1051 0 : for ( i=0; i<ctr->num_groups; i++ ) {
1052 0 : if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1053 0 : break;
1054 : }
1055 :
1056 : /* add a new group? */
1057 :
1058 0 : if ( i == ctr->num_groups ) {
1059 0 : ctr->num_groups++;
1060 :
1061 0 : if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1062 0 : DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1063 0 : return 0;
1064 : }
1065 0 : ctr->msg_groups = groups;
1066 :
1067 : /* clear the new entry and set the printer name */
1068 :
1069 0 : ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1070 0 : fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1071 : }
1072 :
1073 : /* add the change messages; 'i' is the correct index now regardless */
1074 :
1075 0 : msg_grp = &ctr->msg_groups[i];
1076 :
1077 0 : msg_grp->num_msgs++;
1078 :
1079 0 : if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1080 0 : DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1081 0 : return 0;
1082 : }
1083 0 : msg_grp->msgs = msg_list;
1084 :
1085 0 : new_slot = msg_grp->num_msgs-1;
1086 0 : memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1087 :
1088 : /* need to allocate own copy of data */
1089 :
1090 0 : if ( msg->len != 0 )
1091 0 : msg_grp->msgs[new_slot].notify.data = (char *)
1092 0 : talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1093 :
1094 0 : return ctr->num_groups;
1095 : }
1096 :
1097 : static void construct_info_data(struct spoolss_Notify *info_data,
1098 : enum spoolss_NotifyType type,
1099 : uint16_t field, int id);
1100 :
1101 : /***********************************************************************
1102 : Send a change notifation message on all handles which have a call
1103 : back registered
1104 : **********************************************************************/
1105 :
1106 0 : static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1107 : struct printer_handle *prn_hnd,
1108 : SPOOLSS_NOTIFY_MSG *messages,
1109 : uint32_t num_msgs,
1110 : struct spoolss_Notify **_notifies,
1111 : size_t *_count)
1112 : {
1113 : struct spoolss_Notify *notifies;
1114 : SPOOLSS_NOTIFY_MSG *msg;
1115 0 : size_t count = 0;
1116 : uint32_t id;
1117 : uint32_t i;
1118 :
1119 0 : notifies = talloc_zero_array(mem_ctx,
1120 : struct spoolss_Notify, num_msgs);
1121 0 : if (!notifies) {
1122 0 : return ENOMEM;
1123 : }
1124 :
1125 0 : for (i = 0; i < num_msgs; i++) {
1126 :
1127 0 : msg = &messages[i];
1128 :
1129 : /* Are we monitoring this event? */
1130 :
1131 0 : if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1132 0 : continue;
1133 : }
1134 :
1135 0 : DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1136 : "for printer [%s]\n",
1137 : msg->type, msg->field, prn_hnd->sharename));
1138 :
1139 : /*
1140 : * if the is a printer notification handle and not a job
1141 : * notification type, then set the id to 0.
1142 : * Otherwise just use what was specified in the message.
1143 : *
1144 : * When registering change notification on a print server
1145 : * handle we always need to send back the id (snum) matching
1146 : * the printer for which the change took place.
1147 : * For change notify registered on a printer handle,
1148 : * this does not matter and the id should be 0.
1149 : *
1150 : * --jerry
1151 : */
1152 :
1153 0 : if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1154 0 : (prn_hnd->printer_type == SPLHND_PRINTER)) {
1155 0 : id = 0;
1156 : } else {
1157 0 : id = msg->id;
1158 : }
1159 :
1160 : /* Convert unix jobid to smb jobid */
1161 :
1162 0 : if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1163 0 : id = sysjob_to_jobid(msg->id);
1164 :
1165 0 : if (id == -1) {
1166 0 : DEBUG(3, ("no such unix jobid %d\n",
1167 : msg->id));
1168 0 : continue;
1169 : }
1170 : }
1171 :
1172 0 : construct_info_data(¬ifies[count],
1173 0 : msg->type, msg->field, id);
1174 :
1175 0 : switch(msg->type) {
1176 0 : case PRINTER_NOTIFY_TYPE:
1177 0 : if (printer_notify_table[msg->field].fn) {
1178 0 : printer_notify_table[msg->field].fn(msg,
1179 0 : ¬ifies[count], mem_ctx);
1180 : }
1181 0 : break;
1182 :
1183 0 : case JOB_NOTIFY_TYPE:
1184 0 : if (job_notify_table[msg->field].fn) {
1185 0 : job_notify_table[msg->field].fn(msg,
1186 0 : ¬ifies[count], mem_ctx);
1187 : }
1188 0 : break;
1189 :
1190 0 : default:
1191 0 : DEBUG(5, ("Unknown notification type %d\n",
1192 : msg->type));
1193 0 : continue;
1194 : }
1195 :
1196 0 : count++;
1197 : }
1198 :
1199 0 : *_notifies = notifies;
1200 0 : *_count = count;
1201 :
1202 0 : return 0;
1203 : }
1204 :
1205 0 : static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1206 : struct printer_handle *prn_hnd,
1207 : SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1208 : {
1209 : struct spoolss_Notify *notifies;
1210 0 : size_t count = 0;
1211 : union spoolss_ReplyPrinterInfo info;
1212 : struct spoolss_NotifyInfo info0;
1213 : uint32_t reply_result;
1214 : NTSTATUS status;
1215 : WERROR werr;
1216 : int ret;
1217 :
1218 : /* Is there notification on this handle? */
1219 0 : if (prn_hnd->notify.cli_chan == NULL ||
1220 0 : prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1221 0 : prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1222 0 : prn_hnd->notify.cli_chan->active_connections == 0) {
1223 0 : return 0;
1224 : }
1225 :
1226 0 : DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1227 : prn_hnd->servername, prn_hnd->sharename));
1228 :
1229 : /* For this printer? Print servers always receive notifications. */
1230 0 : if ((prn_hnd->printer_type == SPLHND_PRINTER) &&
1231 0 : (!strequal(msg_group->printername, prn_hnd->sharename))) {
1232 0 : return 0;
1233 : }
1234 :
1235 0 : DEBUG(10,("Our printer\n"));
1236 :
1237 : /* build the array of change notifications */
1238 0 : ret = build_notify2_messages(mem_ctx, prn_hnd,
1239 : msg_group->msgs,
1240 : msg_group->num_msgs,
1241 : ¬ifies, &count);
1242 0 : if (ret) {
1243 0 : return ret;
1244 : }
1245 :
1246 0 : info0.version = 0x2;
1247 0 : info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1248 0 : info0.count = count;
1249 0 : info0.notifies = notifies;
1250 :
1251 0 : info.info0 = &info0;
1252 :
1253 0 : status = dcerpc_spoolss_RouterReplyPrinterEx(
1254 0 : prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1255 : mem_ctx,
1256 : &prn_hnd->notify.cli_hnd,
1257 : prn_hnd->notify.change, /* color */
1258 : prn_hnd->notify.flags,
1259 : &reply_result,
1260 : 0, /* reply_type, must be 0 */
1261 : info, &werr);
1262 0 : if (!NT_STATUS_IS_OK(status)) {
1263 0 : DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1264 : "failed: %s\n",
1265 : prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1266 : nt_errstr(status)));
1267 0 : werr = ntstatus_to_werror(status);
1268 0 : } else if (!W_ERROR_IS_OK(werr)) {
1269 0 : DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1270 : "failed: %s\n",
1271 : prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1272 : win_errstr(werr)));
1273 : }
1274 0 : switch (reply_result) {
1275 0 : case 0:
1276 0 : break;
1277 0 : case PRINTER_NOTIFY_INFO_DISCARDED:
1278 : case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1279 : case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1280 0 : break;
1281 0 : default:
1282 0 : break;
1283 : }
1284 :
1285 0 : return 0;
1286 : }
1287 :
1288 0 : static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1289 : {
1290 : struct printer_handle *p;
1291 0 : TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1292 0 : SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1293 : int ret;
1294 :
1295 0 : if ( !msg_group ) {
1296 0 : DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1297 0 : return;
1298 : }
1299 :
1300 0 : if (!msg_group->msgs) {
1301 0 : DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1302 0 : return;
1303 : }
1304 :
1305 0 : DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1306 :
1307 : /* loop over all printers */
1308 :
1309 0 : for (p = printers_list; p; p = p->next) {
1310 0 : ret = send_notify2_printer(mem_ctx, p, msg_group);
1311 0 : if (ret) {
1312 0 : goto done;
1313 : }
1314 : }
1315 :
1316 0 : done:
1317 0 : DEBUG(8,("send_notify2_changes: Exit...\n"));
1318 0 : return;
1319 : }
1320 :
1321 : /***********************************************************************
1322 : **********************************************************************/
1323 :
1324 0 : static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1325 : {
1326 :
1327 : uint32_t tv_sec, tv_usec;
1328 0 : size_t offset = 0;
1329 :
1330 : /* Unpack message */
1331 :
1332 0 : offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1333 0 : msg->printer);
1334 :
1335 0 : offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1336 : &tv_sec, &tv_usec,
1337 : &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1338 :
1339 0 : if (msg->len == 0)
1340 0 : tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1341 : &msg->notify.value[0], &msg->notify.value[1]);
1342 : else
1343 0 : tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1344 : &msg->len, &msg->notify.data);
1345 :
1346 0 : DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1347 : msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1348 :
1349 0 : tv->tv_sec = tv_sec;
1350 0 : tv->tv_usec = tv_usec;
1351 :
1352 0 : if (msg->len == 0)
1353 0 : DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1354 : msg->notify.value[1]));
1355 : else
1356 0 : dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1357 :
1358 0 : return true;
1359 : }
1360 :
1361 : /********************************************************************
1362 : Receive a notify2 message list
1363 : ********************************************************************/
1364 :
1365 0 : static void receive_notify2_message_list(struct messaging_context *msg,
1366 : void *private_data,
1367 : uint32_t msg_type,
1368 : struct server_id server_id,
1369 : DATA_BLOB *data)
1370 : {
1371 : size_t msg_count, i, num_groups;
1372 0 : char *buf = (char *)data->data;
1373 : char *msg_ptr;
1374 : size_t msg_len;
1375 : SPOOLSS_NOTIFY_MSG notify;
1376 : SPOOLSS_NOTIFY_MSG_CTR messages;
1377 :
1378 0 : if (data->length < 4) {
1379 0 : DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1380 0 : return;
1381 : }
1382 :
1383 0 : msg_count = IVAL(buf, 0);
1384 0 : msg_ptr = buf + 4;
1385 :
1386 0 : DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1387 :
1388 0 : if (msg_count == 0) {
1389 0 : DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1390 0 : return;
1391 : }
1392 :
1393 : /* initialize the container */
1394 :
1395 0 : ZERO_STRUCT( messages );
1396 0 : notify_msg_ctr_init( &messages );
1397 :
1398 : /*
1399 : * build message groups for each printer identified
1400 : * in a change_notify msg. Remember that a PCN message
1401 : * includes the handle returned for the srv_spoolss_replyopenprinter()
1402 : * call. Therefore messages are grouped according to printer handle.
1403 : */
1404 :
1405 0 : for ( i=0; i<msg_count; i++ ) {
1406 : struct timeval msg_tv;
1407 :
1408 0 : if (msg_ptr + 4 - buf > data->length) {
1409 0 : DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1410 0 : return;
1411 : }
1412 :
1413 0 : msg_len = IVAL(msg_ptr,0);
1414 0 : msg_ptr += 4;
1415 :
1416 0 : if (msg_ptr + msg_len - buf > data->length) {
1417 0 : DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1418 0 : return;
1419 : }
1420 :
1421 : /* unpack messages */
1422 :
1423 0 : ZERO_STRUCT( notify );
1424 0 : notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1425 0 : msg_ptr += msg_len;
1426 :
1427 : /* add to correct list in container */
1428 :
1429 0 : notify_msg_ctr_addmsg( &messages, ¬ify );
1430 :
1431 : /* free memory that might have been allocated by notify2_unpack_msg() */
1432 :
1433 0 : if ( notify.len != 0 )
1434 0 : SAFE_FREE( notify.notify.data );
1435 : }
1436 :
1437 : /* process each group of messages */
1438 :
1439 0 : num_groups = notify_msg_ctr_numgroups( &messages );
1440 0 : for ( i=0; i<num_groups; i++ )
1441 0 : send_notify2_changes( &messages, i );
1442 :
1443 :
1444 : /* cleanup */
1445 :
1446 0 : DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1447 : (uint32_t)msg_count ));
1448 :
1449 0 : notify_msg_ctr_destroy( &messages );
1450 :
1451 0 : return;
1452 : }
1453 :
1454 : /********************************************************************
1455 : Send a message to ourself about new driver being installed
1456 : so we can upgrade the information for each printer bound to this
1457 : driver
1458 : ********************************************************************/
1459 :
1460 0 : static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1461 : struct messaging_context *msg_ctx)
1462 : {
1463 0 : int len = strlen(drivername);
1464 :
1465 0 : if (!len)
1466 0 : return false;
1467 :
1468 0 : DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1469 : drivername));
1470 :
1471 0 : messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1472 : MSG_PRINTER_DRVUPGRADE,
1473 0 : (const uint8_t *)drivername, len+1);
1474 :
1475 0 : return true;
1476 : }
1477 :
1478 2 : void srv_spoolss_cleanup(void)
1479 : {
1480 : struct printer_session_counter *session_counter;
1481 :
1482 3 : for (session_counter = counter_list;
1483 1 : session_counter != NULL;
1484 0 : session_counter = counter_list) {
1485 0 : DLIST_REMOVE(counter_list, session_counter);
1486 0 : TALLOC_FREE(session_counter);
1487 : }
1488 2 : }
1489 :
1490 : /**********************************************************************
1491 : callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1492 : over all printers, upgrading ones as necessary
1493 : This is now *ONLY* called inside the background lpq updater. JRA.
1494 : **********************************************************************/
1495 :
1496 0 : void do_drv_upgrade_printer(struct messaging_context *msg,
1497 : void *private_data,
1498 : uint32_t msg_type,
1499 : struct server_id server_id,
1500 : DATA_BLOB *data)
1501 : {
1502 : TALLOC_CTX *tmp_ctx;
1503 0 : const struct auth_session_info *session_info = get_session_info_system();
1504 : struct spoolss_PrinterInfo2 *pinfo2;
1505 : WERROR result;
1506 : const char *drivername;
1507 : int snum;
1508 0 : int n_services = lp_numservices();
1509 0 : struct dcerpc_binding_handle *b = NULL;
1510 :
1511 0 : tmp_ctx = talloc_new(NULL);
1512 0 : if (!tmp_ctx) return;
1513 :
1514 0 : drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1515 0 : if (!drivername) {
1516 0 : DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1517 0 : goto done;
1518 : }
1519 :
1520 0 : DEBUG(10, ("do_drv_upgrade_printer: "
1521 : "Got message for new driver [%s]\n", drivername));
1522 :
1523 : /* Iterate the printer list */
1524 :
1525 0 : for (snum = 0; snum < n_services; snum++) {
1526 0 : if (!lp_snum_ok(snum) || !lp_printable(snum)) {
1527 0 : continue;
1528 : }
1529 :
1530 : /* ignore [printers] share */
1531 0 : if (strequal(lp_const_servicename(snum), "printers")) {
1532 0 : continue;
1533 : }
1534 :
1535 0 : if (b == NULL) {
1536 0 : result = winreg_printer_binding_handle(tmp_ctx,
1537 : session_info,
1538 : msg,
1539 : &b);
1540 0 : if (!W_ERROR_IS_OK(result)) {
1541 0 : break;
1542 : }
1543 : }
1544 :
1545 0 : result = winreg_get_printer(tmp_ctx, b,
1546 : lp_const_servicename(snum),
1547 : &pinfo2);
1548 :
1549 0 : if (!W_ERROR_IS_OK(result)) {
1550 0 : continue;
1551 : }
1552 :
1553 0 : if (!pinfo2->drivername) {
1554 0 : continue;
1555 : }
1556 :
1557 0 : if (strcmp(drivername, pinfo2->drivername) != 0) {
1558 0 : continue;
1559 : }
1560 :
1561 0 : DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1562 :
1563 : /* all we care about currently is the change_id */
1564 0 : result = winreg_printer_update_changeid(tmp_ctx, b,
1565 0 : pinfo2->printername);
1566 :
1567 0 : if (!W_ERROR_IS_OK(result)) {
1568 0 : DEBUG(3, ("do_drv_upgrade_printer: "
1569 : "Failed to update changeid [%s]\n",
1570 : win_errstr(result)));
1571 : }
1572 : }
1573 :
1574 : /* all done */
1575 0 : done:
1576 0 : talloc_free(tmp_ctx);
1577 : }
1578 :
1579 : /********************************************************************
1580 : Update the cache for all printq's with a registered client
1581 : connection
1582 : ********************************************************************/
1583 :
1584 0 : void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1585 : {
1586 0 : struct printer_handle *printer = printers_list;
1587 : int snum;
1588 :
1589 : /* loop through all printers and update the cache where
1590 : a client is connected */
1591 0 : while (printer) {
1592 0 : if ((printer->printer_type == SPLHND_PRINTER) &&
1593 0 : ((printer->notify.cli_chan != NULL) &&
1594 0 : (printer->notify.cli_chan->active_connections > 0))) {
1595 0 : snum = print_queue_snum(printer->sharename);
1596 0 : print_queue_status(msg_ctx, snum, NULL, NULL);
1597 : }
1598 :
1599 0 : printer = printer->next;
1600 : }
1601 :
1602 0 : return;
1603 : }
1604 :
1605 : /****************************************************************
1606 : _spoolss_OpenPrinter
1607 : ****************************************************************/
1608 :
1609 2 : WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1610 : struct spoolss_OpenPrinter *r)
1611 : {
1612 : struct spoolss_OpenPrinterEx e;
1613 : struct spoolss_UserLevel1 level1;
1614 : WERROR werr;
1615 :
1616 2 : ZERO_STRUCT(level1);
1617 :
1618 2 : e.in.printername = r->in.printername;
1619 2 : e.in.datatype = r->in.datatype;
1620 2 : e.in.devmode_ctr = r->in.devmode_ctr;
1621 2 : e.in.access_mask = r->in.access_mask;
1622 2 : e.in.userlevel_ctr.level = 1;
1623 2 : e.in.userlevel_ctr.user_info.level1 = &level1;
1624 :
1625 2 : e.out.handle = r->out.handle;
1626 :
1627 2 : werr = _spoolss_OpenPrinterEx(p, &e);
1628 :
1629 2 : if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAMETER)) {
1630 : /* OpenPrinterEx returns this for a bad
1631 : * printer name. We must return WERR_INVALID_PRINTER_NAME
1632 : * instead.
1633 : */
1634 0 : werr = WERR_INVALID_PRINTER_NAME;
1635 : }
1636 :
1637 2 : return werr;
1638 : }
1639 :
1640 0 : static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1641 : struct spoolss_DeviceMode *orig,
1642 : struct spoolss_DeviceMode **dest)
1643 : {
1644 : struct spoolss_DeviceMode *dm;
1645 :
1646 0 : dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1647 0 : if (!dm) {
1648 0 : return WERR_NOT_ENOUGH_MEMORY;
1649 : }
1650 :
1651 : /* copy all values, then duplicate strings and structs */
1652 0 : *dm = *orig;
1653 :
1654 0 : dm->devicename = talloc_strdup(dm, orig->devicename);
1655 0 : if (!dm->devicename) {
1656 0 : return WERR_NOT_ENOUGH_MEMORY;
1657 : }
1658 0 : dm->formname = talloc_strdup(dm, orig->formname);
1659 0 : if (!dm->formname) {
1660 0 : return WERR_NOT_ENOUGH_MEMORY;
1661 : }
1662 0 : if (orig->driverextra_data.data) {
1663 0 : dm->driverextra_data.data =
1664 0 : (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1665 : orig->driverextra_data.length);
1666 0 : if (!dm->driverextra_data.data) {
1667 0 : return WERR_NOT_ENOUGH_MEMORY;
1668 : }
1669 : }
1670 :
1671 0 : *dest = dm;
1672 0 : return WERR_OK;
1673 : }
1674 :
1675 : /****************************************************************
1676 : _spoolss_OpenPrinterEx
1677 : ****************************************************************/
1678 :
1679 2 : WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1680 : struct spoolss_OpenPrinterEx *r)
1681 : {
1682 2 : struct dcesrv_call_state *dce_call = p->dce_call;
1683 2 : struct dcesrv_connection *dcesrv_conn = dce_call->conn;
1684 1 : const struct tsocket_address *remote_address =
1685 1 : dcesrv_connection_get_remote_address(dcesrv_conn);
1686 1 : struct auth_session_info *session_info =
1687 1 : dcesrv_call_session_info(dce_call);
1688 : int snum;
1689 : char *raddr;
1690 : char *rhost;
1691 2 : struct printer_handle *Printer=NULL;
1692 : WERROR result;
1693 : int rc;
1694 :
1695 2 : if (!r->in.printername) {
1696 0 : return WERR_INVALID_PARAMETER;
1697 : }
1698 :
1699 2 : if (!*r->in.printername) {
1700 0 : return WERR_INVALID_PARAMETER;
1701 : }
1702 :
1703 2 : if (r->in.userlevel_ctr.level > 3) {
1704 0 : return WERR_INVALID_PARAMETER;
1705 : }
1706 3 : if ((r->in.userlevel_ctr.level == 1 && !r->in.userlevel_ctr.user_info.level1) ||
1707 3 : (r->in.userlevel_ctr.level == 2 && !r->in.userlevel_ctr.user_info.level2) ||
1708 2 : (r->in.userlevel_ctr.level == 3 && !r->in.userlevel_ctr.user_info.level3)) {
1709 0 : return WERR_INVALID_PARAMETER;
1710 : }
1711 :
1712 : /*
1713 : * The printcap printer share inventory is updated on client
1714 : * enumeration. For clients that do not perform enumeration prior to
1715 : * access, such as cupssmbadd, we reinitialise the printer share
1716 : * inventory on open as well.
1717 : */
1718 2 : become_root();
1719 2 : delete_and_reload_printers();
1720 2 : unbecome_root();
1721 :
1722 : /* some sanity check because you can open a printer or a print server */
1723 : /* aka: \\server\printer or \\server */
1724 :
1725 2 : DEBUGADD(3,("checking name: %s\n", r->in.printername));
1726 :
1727 2 : result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1728 2 : if (!W_ERROR_IS_OK(result)) {
1729 0 : DEBUG(3,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1730 : "for printer %s\n", r->in.printername));
1731 0 : ZERO_STRUCTP(r->out.handle);
1732 0 : return result;
1733 : }
1734 :
1735 2 : Printer = find_printer_index_by_hnd(p, r->out.handle);
1736 2 : if ( !Printer ) {
1737 0 : DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1738 : "handle we created for printer %s\n", r->in.printername));
1739 0 : close_printer_handle(p, r->out.handle);
1740 0 : ZERO_STRUCTP(r->out.handle);
1741 0 : return WERR_INVALID_PARAMETER;
1742 : }
1743 :
1744 : /*
1745 : * First case: the user is opening the print server:
1746 : *
1747 : * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1748 : * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1749 : *
1750 : * Then both Win2k and WinNT clients try an OpenPrinterEx with
1751 : * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1752 : * or if the user is listed in the smb.conf printer admin parameter.
1753 : *
1754 : * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1755 : * client view printer folder, but does not show the MSAPW.
1756 : *
1757 : * Note: this test needs code to check access rights here too. Jeremy
1758 : * could you look at this?
1759 : *
1760 : * Second case: the user is opening a printer:
1761 : * NT doesn't let us connect to a printer if the connecting user
1762 : * doesn't have print permission.
1763 : *
1764 : * Third case: user is opening a Port Monitor
1765 : * access checks same as opening a handle to the print server.
1766 : */
1767 :
1768 2 : switch (Printer->printer_type )
1769 : {
1770 2 : case SPLHND_SERVER:
1771 : case SPLHND_PORTMON_TCP:
1772 : case SPLHND_PORTMON_LOCAL:
1773 : /* Printserver handles use global struct... */
1774 :
1775 2 : snum = -1;
1776 :
1777 2 : if (r->in.access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
1778 2 : r->in.access_mask |= SERVER_ACCESS_ADMINISTER;
1779 2 : r->in.access_mask |= SERVER_ACCESS_ENUMERATE;
1780 : }
1781 :
1782 : /* Map standard access rights to object specific access rights */
1783 :
1784 2 : se_map_standard(&r->in.access_mask,
1785 : &printserver_std_mapping);
1786 :
1787 : /* Deny any object specific bits that don't apply to print
1788 : servers (i.e printer and job specific bits) */
1789 :
1790 2 : r->in.access_mask &= SEC_MASK_SPECIFIC;
1791 :
1792 2 : if (r->in.access_mask &
1793 : ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1794 0 : DEBUG(3, ("access DENIED for non-printserver bits\n"));
1795 0 : close_printer_handle(p, r->out.handle);
1796 0 : ZERO_STRUCTP(r->out.handle);
1797 0 : return WERR_ACCESS_DENIED;
1798 : }
1799 :
1800 : /* Allow admin access */
1801 :
1802 2 : if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1803 : {
1804 2 : if (!lp_show_add_printer_wizard()) {
1805 0 : close_printer_handle(p, r->out.handle);
1806 0 : ZERO_STRUCTP(r->out.handle);
1807 0 : return WERR_ACCESS_DENIED;
1808 : }
1809 :
1810 : /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1811 : and not a printer admin, then fail */
1812 :
1813 3 : if ((session_info->unix_token->uid != sec_initial_uid()) &&
1814 2 : !security_token_has_privilege(
1815 2 : session_info->security_token,
1816 0 : SEC_PRIV_PRINT_OPERATOR) &&
1817 0 : !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
1818 0 : session_info->security_token)) {
1819 0 : close_printer_handle(p, r->out.handle);
1820 0 : ZERO_STRUCTP(r->out.handle);
1821 0 : DEBUG(3,("access DENIED as user is not root, "
1822 : "has no printoperator privilege and is "
1823 : "not a member of the printoperator builtin group\n"));
1824 0 : return WERR_ACCESS_DENIED;
1825 : }
1826 :
1827 2 : r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1828 : }
1829 : else
1830 : {
1831 0 : r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1832 : }
1833 :
1834 2 : DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1835 : ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1836 :
1837 2 : break;
1838 :
1839 0 : case SPLHND_PRINTER:
1840 : /* NT doesn't let us connect to a printer if the connecting user
1841 : doesn't have print permission. */
1842 :
1843 0 : if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1844 0 : close_printer_handle(p, r->out.handle);
1845 0 : ZERO_STRUCTP(r->out.handle);
1846 0 : return WERR_INVALID_HANDLE;
1847 : }
1848 :
1849 0 : if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1850 0 : r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1851 : }
1852 :
1853 0 : se_map_standard(&r->in.access_mask, &printer_std_mapping);
1854 :
1855 : /* map an empty access mask to the minimum access mask */
1856 0 : if (r->in.access_mask == 0x0)
1857 0 : r->in.access_mask = PRINTER_ACCESS_USE;
1858 :
1859 : /*
1860 : * If we are not serving the printer driver for this printer,
1861 : * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1862 : * will keep NT clients happy --jerry
1863 : */
1864 :
1865 0 : if (lp_use_client_driver(snum)
1866 0 : && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1867 : {
1868 0 : r->in.access_mask = PRINTER_ACCESS_USE;
1869 : }
1870 :
1871 : /* check smb.conf parameters and the the sec_desc */
1872 0 : raddr = tsocket_address_inet_addr_string(remote_address,
1873 : p->mem_ctx);
1874 0 : if (raddr == NULL) {
1875 0 : return WERR_NOT_ENOUGH_MEMORY;
1876 : }
1877 :
1878 0 : rc = get_remote_hostname(remote_address,
1879 : &rhost,
1880 : p->mem_ctx);
1881 0 : if (rc < 0) {
1882 0 : return WERR_NOT_ENOUGH_MEMORY;
1883 : }
1884 0 : if (strequal(rhost, "UNKNOWN")) {
1885 0 : rhost = raddr;
1886 : }
1887 :
1888 0 : if (!allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
1889 : rhost, raddr)) {
1890 0 : DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1891 0 : ZERO_STRUCTP(r->out.handle);
1892 0 : return WERR_ACCESS_DENIED;
1893 : }
1894 :
1895 0 : if (!user_ok_token(session_info->unix_info->unix_name,
1896 0 : session_info->info->domain_name,
1897 0 : session_info->security_token, snum) ||
1898 0 : !W_ERROR_IS_OK(print_access_check(session_info,
1899 : p->msg_ctx,
1900 : snum,
1901 : r->in.access_mask))) {
1902 0 : DEBUG(3, ("access DENIED for printer open\n"));
1903 0 : close_printer_handle(p, r->out.handle);
1904 0 : ZERO_STRUCTP(r->out.handle);
1905 0 : return WERR_ACCESS_DENIED;
1906 : }
1907 :
1908 0 : if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1909 0 : DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1910 0 : close_printer_handle(p, r->out.handle);
1911 0 : ZERO_STRUCTP(r->out.handle);
1912 0 : return WERR_ACCESS_DENIED;
1913 : }
1914 :
1915 0 : if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1916 0 : r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1917 : else
1918 0 : r->in.access_mask = PRINTER_ACCESS_USE;
1919 :
1920 0 : DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1921 : ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1922 :
1923 0 : winreg_create_printer_internal(p->mem_ctx,
1924 : get_session_info_system(),
1925 : p->msg_ctx,
1926 : lp_const_servicename(snum));
1927 :
1928 0 : break;
1929 :
1930 0 : default:
1931 : /* sanity check to prevent programmer error */
1932 0 : ZERO_STRUCTP(r->out.handle);
1933 0 : return WERR_INVALID_HANDLE;
1934 : }
1935 :
1936 2 : Printer->access_granted = r->in.access_mask;
1937 :
1938 : /*
1939 : * If the client sent a devmode in the OpenPrinter() call, then
1940 : * save it here in case we get a job submission on this handle
1941 : */
1942 :
1943 2 : if ((Printer->printer_type != SPLHND_SERVER)
1944 0 : && (r->in.devmode_ctr.devmode != NULL)) {
1945 0 : copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1946 : &Printer->devmode);
1947 : }
1948 :
1949 2 : return WERR_OK;
1950 : }
1951 :
1952 : /****************************************************************
1953 : _spoolss_ClosePrinter
1954 : ****************************************************************/
1955 :
1956 2 : WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1957 : struct spoolss_ClosePrinter *r)
1958 : {
1959 2 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1960 :
1961 2 : if (Printer && Printer->document_started) {
1962 : struct spoolss_EndDocPrinter e;
1963 :
1964 0 : e.in.handle = r->in.handle;
1965 :
1966 0 : _spoolss_EndDocPrinter(p, &e);
1967 : }
1968 :
1969 2 : if (!close_printer_handle(p, r->in.handle))
1970 0 : return WERR_INVALID_HANDLE;
1971 :
1972 : /* clear the returned printer handle. Observed behavior
1973 : from Win2k server. Don't think this really matters.
1974 : Previous code just copied the value of the closed
1975 : handle. --jerry */
1976 :
1977 2 : ZERO_STRUCTP(r->out.handle);
1978 :
1979 2 : return WERR_OK;
1980 : }
1981 :
1982 : /****************************************************************
1983 : _spoolss_DeletePrinter
1984 : ****************************************************************/
1985 :
1986 0 : WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1987 : struct spoolss_DeletePrinter *r)
1988 : {
1989 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1990 : WERROR result;
1991 : int snum;
1992 :
1993 0 : if (Printer && Printer->document_started) {
1994 : struct spoolss_EndDocPrinter e;
1995 :
1996 0 : e.in.handle = r->in.handle;
1997 :
1998 0 : _spoolss_EndDocPrinter(p, &e);
1999 : }
2000 :
2001 0 : if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2002 0 : winreg_delete_printer_key_internal(p->mem_ctx,
2003 : get_session_info_system(),
2004 : p->msg_ctx,
2005 : lp_const_servicename(snum),
2006 : "");
2007 : }
2008 :
2009 0 : result = delete_printer_handle(p, r->in.handle);
2010 :
2011 0 : return result;
2012 : }
2013 :
2014 : /*******************************************************************
2015 : * static function to lookup the version id corresponding to an
2016 : * long architecture string
2017 : ******************************************************************/
2018 :
2019 : static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2020 : SPOOLSS_DRIVER_VERSION_NT35,
2021 : SPOOLSS_DRIVER_VERSION_NT4,
2022 : SPOOLSS_DRIVER_VERSION_200X,
2023 : -1};
2024 :
2025 0 : static int get_version_id(const char *arch)
2026 : {
2027 : int i;
2028 :
2029 0 : for (i=0; archi_table[i].long_archi != NULL; i++)
2030 : {
2031 0 : if (strcmp(arch, archi_table[i].long_archi) == 0)
2032 0 : return (archi_table[i].version);
2033 : }
2034 :
2035 0 : return -1;
2036 : }
2037 :
2038 : /****************************************************************
2039 : _spoolss_DeletePrinterDriver
2040 : ****************************************************************/
2041 :
2042 0 : WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2043 : struct spoolss_DeletePrinterDriver *r)
2044 : {
2045 :
2046 0 : struct dcesrv_call_state *dce_call = p->dce_call;
2047 0 : struct auth_session_info *session_info =
2048 0 : dcesrv_call_session_info(dce_call);
2049 0 : struct spoolss_DriverInfo8 *info = NULL;
2050 : int version;
2051 : WERROR status;
2052 : struct dcerpc_binding_handle *b;
2053 0 : TALLOC_CTX *tmp_ctx = NULL;
2054 : int i;
2055 : bool found;
2056 :
2057 : /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2058 : and not a printer admin, then fail */
2059 :
2060 0 : if ((session_info->unix_token->uid != sec_initial_uid()) &&
2061 0 : !security_token_has_privilege(session_info->security_token,
2062 : SEC_PRIV_PRINT_OPERATOR)) {
2063 0 : return WERR_ACCESS_DENIED;
2064 : }
2065 :
2066 0 : if (r->in.architecture == NULL || r->in.driver == NULL) {
2067 0 : return WERR_INVALID_ENVIRONMENT;
2068 : }
2069 :
2070 : /* check that we have a valid driver name first */
2071 :
2072 0 : if ((version = get_version_id(r->in.architecture)) == -1) {
2073 0 : return WERR_INVALID_ENVIRONMENT;
2074 : }
2075 :
2076 0 : tmp_ctx = talloc_new(p->mem_ctx);
2077 0 : if (!tmp_ctx) {
2078 0 : return WERR_NOT_ENOUGH_MEMORY;
2079 : }
2080 :
2081 0 : status = winreg_printer_binding_handle(tmp_ctx,
2082 : get_session_info_system(),
2083 : p->msg_ctx,
2084 : &b);
2085 0 : if (!W_ERROR_IS_OK(status)) {
2086 0 : goto done;
2087 : }
2088 :
2089 0 : for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2090 0 : status = winreg_get_driver(tmp_ctx, b,
2091 : r->in.architecture, r->in.driver,
2092 0 : drv_cversion[i], &info);
2093 0 : if (!W_ERROR_IS_OK(status)) {
2094 0 : DEBUG(5, ("skipping del of driver with version %d\n",
2095 : drv_cversion[i]));
2096 0 : continue;
2097 : }
2098 0 : found = true;
2099 :
2100 0 : if (printer_driver_in_use(tmp_ctx, b, info)) {
2101 0 : status = WERR_PRINTER_DRIVER_IN_USE;
2102 0 : goto done;
2103 : }
2104 :
2105 0 : status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2106 0 : if (!W_ERROR_IS_OK(status)) {
2107 0 : DEBUG(0, ("failed del of driver with version %d\n",
2108 : drv_cversion[i]));
2109 0 : goto done;
2110 : }
2111 : }
2112 0 : if (found == false) {
2113 0 : DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2114 0 : status = WERR_UNKNOWN_PRINTER_DRIVER;
2115 : } else {
2116 0 : status = WERR_OK;
2117 : }
2118 :
2119 0 : done:
2120 0 : talloc_free(tmp_ctx);
2121 :
2122 0 : return status;
2123 : }
2124 :
2125 0 : static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2126 : struct pipes_struct *p,
2127 : struct spoolss_DeletePrinterDriverEx *r,
2128 : struct dcerpc_binding_handle *b,
2129 : struct spoolss_DriverInfo8 *info)
2130 : {
2131 0 : struct dcesrv_call_state *dce_call = p->dce_call;
2132 0 : struct auth_session_info *session_info =
2133 0 : dcesrv_call_session_info(dce_call);
2134 : WERROR status;
2135 : bool delete_files;
2136 :
2137 0 : if (printer_driver_in_use(mem_ctx, b, info)) {
2138 0 : status = WERR_PRINTER_DRIVER_IN_USE;
2139 0 : goto done;
2140 : }
2141 :
2142 : /*
2143 : * we have a couple of cases to consider.
2144 : * (1) Are any files in use? If so and DPD_DELETE_ALL_FILES is set,
2145 : * then the delete should fail if **any** files overlap with
2146 : * other drivers
2147 : * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2148 : * non-overlapping files
2149 : * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2150 : * are set, then do not delete any files
2151 : * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2152 : */
2153 :
2154 0 : delete_files = r->in.delete_flags
2155 0 : & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2156 :
2157 :
2158 0 : if (delete_files) {
2159 0 : bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2160 0 : if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2161 0 : status = WERR_PRINTER_DRIVER_IN_USE;
2162 0 : goto done;
2163 : }
2164 : /*
2165 : * printer_driver_files_in_use() has trimmed overlapping files
2166 : * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2167 : */
2168 : }
2169 :
2170 :
2171 0 : status = winreg_del_driver(mem_ctx, b, info, info->version);
2172 0 : if (!W_ERROR_IS_OK(status)) {
2173 0 : goto done;
2174 : }
2175 :
2176 : /*
2177 : * now delete any associated files if delete_files is
2178 : * true. Even if this part failes, we return succes
2179 : * because the driver doesn not exist any more
2180 : */
2181 0 : if (delete_files) {
2182 0 : delete_driver_files(session_info, info);
2183 : }
2184 :
2185 0 : done:
2186 0 : return status;
2187 : }
2188 :
2189 : /****************************************************************
2190 : _spoolss_DeletePrinterDriverEx
2191 : ****************************************************************/
2192 :
2193 0 : WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2194 : struct spoolss_DeletePrinterDriverEx *r)
2195 : {
2196 0 : struct dcesrv_call_state *dce_call = p->dce_call;
2197 0 : struct auth_session_info *session_info =
2198 0 : dcesrv_call_session_info(dce_call);
2199 0 : struct spoolss_DriverInfo8 *info = NULL;
2200 : WERROR status;
2201 : struct dcerpc_binding_handle *b;
2202 0 : TALLOC_CTX *tmp_ctx = NULL;
2203 : int i;
2204 : bool found;
2205 :
2206 : /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2207 : and not a printer admin, then fail */
2208 :
2209 0 : if ((session_info->unix_token->uid != sec_initial_uid()) &&
2210 0 : !security_token_has_privilege(session_info->security_token,
2211 : SEC_PRIV_PRINT_OPERATOR)) {
2212 0 : return WERR_ACCESS_DENIED;
2213 : }
2214 :
2215 0 : if (r->in.architecture == NULL || r->in.driver == NULL) {
2216 0 : return WERR_INVALID_ENVIRONMENT;
2217 : }
2218 :
2219 : /* check that we have a valid driver name first */
2220 0 : if (get_version_id(r->in.architecture) == -1) {
2221 : /* this is what NT returns */
2222 0 : return WERR_INVALID_ENVIRONMENT;
2223 : }
2224 :
2225 0 : tmp_ctx = talloc_new(p->mem_ctx);
2226 0 : if (!tmp_ctx) {
2227 0 : return WERR_NOT_ENOUGH_MEMORY;
2228 : }
2229 :
2230 0 : status = winreg_printer_binding_handle(tmp_ctx,
2231 : get_session_info_system(),
2232 : p->msg_ctx,
2233 : &b);
2234 0 : if (!W_ERROR_IS_OK(status)) {
2235 0 : goto done;
2236 : }
2237 :
2238 0 : for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2239 0 : if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2240 0 : && (drv_cversion[i] != r->in.version)) {
2241 0 : continue;
2242 : }
2243 :
2244 : /* check if a driver with this version exists before delete */
2245 0 : status = winreg_get_driver(tmp_ctx, b,
2246 : r->in.architecture, r->in.driver,
2247 0 : drv_cversion[i], &info);
2248 0 : if (!W_ERROR_IS_OK(status)) {
2249 0 : DEBUG(5, ("skipping del of driver with version %d\n",
2250 : drv_cversion[i]));
2251 0 : continue;
2252 : }
2253 0 : found = true;
2254 :
2255 0 : status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2256 0 : if (!W_ERROR_IS_OK(status)) {
2257 0 : DEBUG(0, ("failed to delete driver with version %d\n",
2258 : drv_cversion[i]));
2259 0 : goto done;
2260 : }
2261 : }
2262 0 : if (found == false) {
2263 0 : DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2264 0 : status = WERR_UNKNOWN_PRINTER_DRIVER;
2265 : } else {
2266 0 : status = WERR_OK;
2267 : }
2268 :
2269 0 : done:
2270 0 : talloc_free(tmp_ctx);
2271 0 : return status;
2272 : }
2273 :
2274 :
2275 : /********************************************************************
2276 : GetPrinterData on a printer server Handle.
2277 : ********************************************************************/
2278 :
2279 0 : static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2280 : const char *value,
2281 : enum winreg_Type *type,
2282 : union spoolss_PrinterData *data)
2283 : {
2284 0 : DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2285 :
2286 0 : if (!strcasecmp_m(value, "W3SvcInstalled")) {
2287 0 : *type = REG_DWORD;
2288 0 : SIVAL(&data->value, 0, 0x00);
2289 0 : return WERR_OK;
2290 : }
2291 :
2292 0 : if (!strcasecmp_m(value, "BeepEnabled")) {
2293 0 : *type = REG_DWORD;
2294 0 : SIVAL(&data->value, 0, 0x00);
2295 0 : return WERR_OK;
2296 : }
2297 :
2298 0 : if (!strcasecmp_m(value, "EventLog")) {
2299 0 : *type = REG_DWORD;
2300 : /* formally was 0x1b */
2301 0 : SIVAL(&data->value, 0, 0x00);
2302 0 : return WERR_OK;
2303 : }
2304 :
2305 0 : if (!strcasecmp_m(value, "NetPopup")) {
2306 0 : *type = REG_DWORD;
2307 0 : SIVAL(&data->value, 0, 0x00);
2308 0 : return WERR_OK;
2309 : }
2310 :
2311 0 : if (!strcasecmp_m(value, "MajorVersion")) {
2312 0 : *type = REG_DWORD;
2313 :
2314 : /* Windows NT 4.0 seems to not allow uploading of drivers
2315 : to a server that reports 0x3 as the MajorVersion.
2316 : need to investigate more how Win2k gets around this .
2317 : -- jerry */
2318 :
2319 0 : if (RA_WINNT == get_remote_arch()) {
2320 0 : SIVAL(&data->value, 0, 0x02);
2321 : } else {
2322 0 : SIVAL(&data->value, 0, 0x03);
2323 : }
2324 :
2325 0 : return WERR_OK;
2326 : }
2327 :
2328 0 : if (!strcasecmp_m(value, "MinorVersion")) {
2329 0 : *type = REG_DWORD;
2330 0 : SIVAL(&data->value, 0, 0x00);
2331 0 : return WERR_OK;
2332 : }
2333 :
2334 : /* REG_BINARY
2335 : * uint32_t size = 0x114
2336 : * uint32_t major = 5
2337 : * uint32_t minor = [0|1]
2338 : * uint32_t build = [2195|2600]
2339 : * extra unicode string = e.g. "Service Pack 3"
2340 : */
2341 0 : if (!strcasecmp_m(value, "OSVersion")) {
2342 : DATA_BLOB blob;
2343 : enum ndr_err_code ndr_err;
2344 : struct spoolss_OSVersion os;
2345 :
2346 : /*
2347 : * Set the default OSVersion to:
2348 : *
2349 : * Windows Server 2003R2 SP2 (5.2.3790)
2350 : *
2351 : * used to be Windows 2000 (5.0.2195)
2352 : */
2353 0 : os.major = lp_parm_int(GLOBAL_SECTION_SNUM,
2354 : "spoolss", "os_major",
2355 : GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT);
2356 0 : os.minor = lp_parm_int(GLOBAL_SECTION_SNUM,
2357 : "spoolss", "os_minor",
2358 : GLOBAL_SPOOLSS_OS_MINOR_DEFAULT);
2359 0 : os.build = lp_parm_int(GLOBAL_SECTION_SNUM,
2360 : "spoolss", "os_build",
2361 : GLOBAL_SPOOLSS_OS_BUILD_DEFAULT);
2362 0 : os.extra_string = ""; /* leave extra string empty */
2363 :
2364 0 : ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2365 : (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2366 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2367 0 : return WERR_GEN_FAILURE;
2368 : }
2369 :
2370 0 : if (DEBUGLEVEL >= 10) {
2371 0 : NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
2372 : }
2373 :
2374 0 : *type = REG_BINARY;
2375 0 : data->binary = blob;
2376 :
2377 0 : return WERR_OK;
2378 : }
2379 :
2380 :
2381 0 : if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2382 0 : *type = REG_SZ;
2383 :
2384 0 : data->string = talloc_strdup(mem_ctx, SPOOLSS_DEFAULT_SERVER_PATH);
2385 0 : W_ERROR_HAVE_NO_MEMORY(data->string);
2386 :
2387 0 : return WERR_OK;
2388 : }
2389 :
2390 0 : if (!strcasecmp_m(value, "Architecture")) {
2391 0 : *type = REG_SZ;
2392 0 : data->string = talloc_strdup(mem_ctx,
2393 : lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", GLOBAL_SPOOLSS_ARCHITECTURE));
2394 0 : W_ERROR_HAVE_NO_MEMORY(data->string);
2395 :
2396 0 : return WERR_OK;
2397 : }
2398 :
2399 0 : if (!strcasecmp_m(value, "DsPresent")) {
2400 0 : *type = REG_DWORD;
2401 :
2402 : /* only show the publish check box if we are a
2403 : member of a AD domain */
2404 :
2405 0 : if (lp_security() == SEC_ADS) {
2406 0 : SIVAL(&data->value, 0, 0x01);
2407 : } else {
2408 0 : SIVAL(&data->value, 0, 0x00);
2409 : }
2410 0 : return WERR_OK;
2411 : }
2412 :
2413 0 : if (!strcasecmp_m(value, "DNSMachineName")) {
2414 0 : const char *hostname = get_mydnsfullname();
2415 :
2416 0 : if (!hostname) {
2417 0 : return WERR_FILE_NOT_FOUND;
2418 : }
2419 :
2420 0 : *type = REG_SZ;
2421 0 : data->string = talloc_strdup(mem_ctx, hostname);
2422 0 : W_ERROR_HAVE_NO_MEMORY(data->string);
2423 :
2424 0 : return WERR_OK;
2425 : }
2426 :
2427 0 : *type = REG_NONE;
2428 :
2429 0 : return WERR_INVALID_PARAMETER;
2430 : }
2431 :
2432 : /****************************************************************
2433 : _spoolss_GetPrinterData
2434 : ****************************************************************/
2435 :
2436 0 : WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2437 : struct spoolss_GetPrinterData *r)
2438 : {
2439 : struct spoolss_GetPrinterDataEx r2;
2440 :
2441 0 : r2.in.handle = r->in.handle;
2442 0 : r2.in.key_name = "PrinterDriverData";
2443 0 : r2.in.value_name = r->in.value_name;
2444 0 : r2.in.offered = r->in.offered;
2445 0 : r2.out.type = r->out.type;
2446 0 : r2.out.data = r->out.data;
2447 0 : r2.out.needed = r->out.needed;
2448 :
2449 0 : return _spoolss_GetPrinterDataEx(p, &r2);
2450 : }
2451 :
2452 : /*********************************************************
2453 : Connect to the client machine.
2454 : **********************************************************/
2455 :
2456 2 : static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe, struct cli_state **pp_cli,
2457 : struct sockaddr_storage *client_ss, const char *remote_machine)
2458 : {
2459 : NTSTATUS ret;
2460 : struct sockaddr_storage rm_addr;
2461 : char addr[INET6_ADDRSTRLEN];
2462 2 : struct cli_credentials *anon_creds = NULL;
2463 :
2464 2 : if ( is_zero_addr(client_ss) ) {
2465 0 : DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2466 : remote_machine));
2467 0 : if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2468 0 : DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2469 0 : return false;
2470 : }
2471 0 : print_sockaddr(addr, sizeof(addr), &rm_addr);
2472 : } else {
2473 2 : rm_addr = *client_ss;
2474 2 : print_sockaddr(addr, sizeof(addr), &rm_addr);
2475 2 : DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2476 : addr));
2477 : }
2478 :
2479 2 : if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2480 0 : DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2481 : addr));
2482 0 : return false;
2483 : }
2484 :
2485 2 : anon_creds = cli_credentials_init_anon(NULL);
2486 2 : if (anon_creds == NULL) {
2487 0 : DBG_ERR("cli_credentials_init_anon() failed\n");
2488 0 : return false;
2489 : }
2490 :
2491 : /* setup the connection */
2492 2 : ret = cli_full_connection_creds( pp_cli, lp_netbios_name(), remote_machine,
2493 : &rm_addr, 0, "IPC$", "IPC",
2494 : anon_creds,
2495 : CLI_FULL_CONNECTION_IPC);
2496 2 : TALLOC_FREE(anon_creds);
2497 2 : if ( !NT_STATUS_IS_OK( ret ) ) {
2498 0 : DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2499 : remote_machine ));
2500 0 : return false;
2501 : }
2502 :
2503 2 : if ( smbXcli_conn_protocol((*pp_cli)->conn) < PROTOCOL_NT1 ) {
2504 0 : DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2505 0 : cli_shutdown(*pp_cli);
2506 0 : return false;
2507 : }
2508 :
2509 : /*
2510 : * Ok - we have an anonymous connection to the IPC$ share.
2511 : * Now start the NT Domain stuff :-).
2512 : */
2513 :
2514 2 : ret = cli_rpc_pipe_open_noauth(*pp_cli, &ndr_table_spoolss, pp_pipe);
2515 2 : if (!NT_STATUS_IS_OK(ret)) {
2516 0 : DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2517 : remote_machine, nt_errstr(ret)));
2518 0 : cli_shutdown(*pp_cli);
2519 0 : return false;
2520 : }
2521 :
2522 2 : return true;
2523 : }
2524 :
2525 : /***************************************************************************
2526 : Connect to the client.
2527 : ****************************************************************************/
2528 :
2529 2 : static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2530 : uint32_t localprinter,
2531 : enum winreg_Type type,
2532 : struct policy_handle *handle,
2533 : struct notify_back_channel **_chan,
2534 : struct sockaddr_storage *client_ss,
2535 : struct messaging_context *msg_ctx)
2536 : {
2537 : WERROR result;
2538 : NTSTATUS status;
2539 : struct notify_back_channel *chan;
2540 :
2541 2 : for (chan = back_channels; chan; chan = chan->next) {
2542 0 : if (memcmp(&chan->client_address, client_ss,
2543 : sizeof(struct sockaddr_storage)) == 0) {
2544 0 : break;
2545 : }
2546 : }
2547 :
2548 : /*
2549 : * If it's the first connection, contact the client
2550 : * and connect to the IPC$ share anonymously
2551 : */
2552 2 : if (!chan) {
2553 : fstring unix_printer;
2554 :
2555 : /* the +2 is to strip the leading 2 backslashs */
2556 2 : fstrcpy(unix_printer, printer + 2);
2557 :
2558 2 : chan = talloc_zero(NULL, struct notify_back_channel);
2559 2 : if (!chan) {
2560 0 : return false;
2561 : }
2562 2 : chan->client_address = *client_ss;
2563 :
2564 2 : if (!spoolss_connect_to_client(&chan->cli_pipe, &chan->cli, client_ss, unix_printer)) {
2565 0 : TALLOC_FREE(chan);
2566 0 : return false;
2567 : }
2568 :
2569 2 : DLIST_ADD(back_channels, chan);
2570 :
2571 2 : messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2572 : receive_notify2_message_list);
2573 : }
2574 :
2575 3 : if (chan->cli_pipe == NULL ||
2576 2 : chan->cli_pipe->binding_handle == NULL) {
2577 0 : DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2578 : "NULL %s for printer %s\n",
2579 : chan->cli_pipe == NULL ?
2580 : "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2581 : printer));
2582 0 : return false;
2583 : }
2584 :
2585 : /*
2586 : * Tell the specific printing tdb we want messages for this printer
2587 : * by registering our PID.
2588 : */
2589 :
2590 2 : if (!print_notify_register_pid(snum)) {
2591 0 : DEBUG(0, ("Failed to register our pid for printer %s\n",
2592 : printer));
2593 : }
2594 :
2595 2 : status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2596 : talloc_tos(),
2597 : printer,
2598 : localprinter,
2599 : type,
2600 : 0,
2601 : NULL,
2602 : handle,
2603 : &result);
2604 2 : if (!NT_STATUS_IS_OK(status)) {
2605 0 : DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2606 0 : result = ntstatus_to_werror(status);
2607 2 : } else if (!W_ERROR_IS_OK(result)) {
2608 0 : DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2609 : }
2610 :
2611 2 : chan->active_connections++;
2612 2 : *_chan = chan;
2613 :
2614 2 : return (W_ERROR_IS_OK(result));
2615 : }
2616 :
2617 : /****************************************************************
2618 : ****************************************************************/
2619 :
2620 2 : static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2621 : const struct spoolss_NotifyOption *r)
2622 : {
2623 : struct spoolss_NotifyOption *option;
2624 : uint32_t i,k;
2625 :
2626 2 : if (!r) {
2627 0 : return NULL;
2628 : }
2629 :
2630 2 : option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2631 2 : if (!option) {
2632 0 : return NULL;
2633 : }
2634 :
2635 2 : *option = *r;
2636 :
2637 2 : if (!option->count) {
2638 0 : return option;
2639 : }
2640 :
2641 2 : option->types = talloc_zero_array(option,
2642 : struct spoolss_NotifyOptionType, option->count);
2643 2 : if (!option->types) {
2644 0 : talloc_free(option);
2645 0 : return NULL;
2646 : }
2647 :
2648 6 : for (i=0; i < option->count; i++) {
2649 4 : option->types[i] = r->types[i];
2650 :
2651 4 : if (option->types[i].count) {
2652 4 : option->types[i].fields = talloc_zero_array(option,
2653 : union spoolss_Field, option->types[i].count);
2654 4 : if (!option->types[i].fields) {
2655 0 : talloc_free(option);
2656 0 : return NULL;
2657 : }
2658 8 : for (k=0; k<option->types[i].count; k++) {
2659 4 : option->types[i].fields[k] =
2660 4 : r->types[i].fields[k];
2661 : }
2662 : }
2663 : }
2664 :
2665 2 : return option;
2666 : }
2667 :
2668 : /****************************************************************
2669 : * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2670 : *
2671 : * before replying OK: status=0 a rpc call is made to the workstation
2672 : * asking ReplyOpenPrinter
2673 : *
2674 : * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2675 : * called from api_spoolss_rffpcnex
2676 : ****************************************************************/
2677 :
2678 2 : WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2679 : struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2680 : {
2681 2 : struct dcesrv_call_state *dce_call = p->dce_call;
2682 2 : struct dcesrv_connection *dcesrv_conn = dce_call->conn;
2683 1 : const struct tsocket_address *remote_address =
2684 1 : dcesrv_connection_get_remote_address(dcesrv_conn);
2685 2 : int snum = -1;
2686 2 : struct spoolss_NotifyOption *option = r->in.notify_options;
2687 : struct sockaddr_storage client_ss;
2688 : ssize_t client_len;
2689 :
2690 : /* store the notify value in the printer struct */
2691 :
2692 2 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2693 :
2694 2 : if (!Printer) {
2695 0 : DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2696 : "Invalid handle (%s:%u:%u).\n",
2697 : OUR_HANDLE(r->in.handle)));
2698 0 : return WERR_INVALID_HANDLE;
2699 : }
2700 :
2701 2 : Printer->notify.flags = r->in.flags;
2702 2 : Printer->notify.options = r->in.options;
2703 2 : Printer->notify.printerlocal = r->in.printer_local;
2704 2 : Printer->notify.msg_ctx = p->msg_ctx;
2705 :
2706 2 : TALLOC_FREE(Printer->notify.option);
2707 2 : Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2708 :
2709 2 : fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2710 :
2711 : /* Connect to the client machine and send a ReplyOpenPrinter */
2712 :
2713 2 : if ( Printer->printer_type == SPLHND_SERVER)
2714 2 : snum = -1;
2715 0 : else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2716 0 : !get_printer_snum(p, r->in.handle, &snum, NULL) )
2717 0 : return WERR_INVALID_HANDLE;
2718 :
2719 2 : DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2720 : "remote_address is %s\n",
2721 : tsocket_address_string(remote_address, p->mem_ctx)));
2722 :
2723 2 : if (!lp_print_notify_backchannel(snum)) {
2724 0 : DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2725 : "backchannel disabled\n"));
2726 0 : return WERR_RPC_S_SERVER_UNAVAILABLE;
2727 : }
2728 :
2729 2 : client_len = tsocket_address_bsd_sockaddr(remote_address,
2730 : (struct sockaddr *) &client_ss,
2731 : sizeof(struct sockaddr_storage));
2732 2 : if (client_len < 0) {
2733 0 : return WERR_NOT_ENOUGH_MEMORY;
2734 : }
2735 :
2736 2 : if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2737 : Printer->notify.printerlocal, REG_SZ,
2738 : &Printer->notify.cli_hnd,
2739 : &Printer->notify.cli_chan,
2740 : &client_ss, p->msg_ctx)) {
2741 0 : return WERR_RPC_S_SERVER_UNAVAILABLE;
2742 : }
2743 :
2744 2 : return WERR_OK;
2745 : }
2746 :
2747 : /*******************************************************************
2748 : * fill a notify_info_data with the servername
2749 : ********************************************************************/
2750 :
2751 0 : static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2752 : int snum,
2753 : struct spoolss_Notify *data,
2754 : print_queue_struct *queue,
2755 : struct spoolss_PrinterInfo2 *pinfo2,
2756 : TALLOC_CTX *mem_ctx)
2757 : {
2758 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2759 0 : }
2760 :
2761 : /*******************************************************************
2762 : * fill a notify_info_data with the printername (not including the servername).
2763 : ********************************************************************/
2764 :
2765 0 : static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2766 : int snum,
2767 : struct spoolss_Notify *data,
2768 : print_queue_struct *queue,
2769 : struct spoolss_PrinterInfo2 *pinfo2,
2770 : TALLOC_CTX *mem_ctx)
2771 : {
2772 : /* the notify name should not contain the \\server\ part */
2773 0 : const char *p = strrchr(pinfo2->printername, '\\');
2774 :
2775 0 : if (!p) {
2776 0 : p = pinfo2->printername;
2777 : } else {
2778 0 : p++;
2779 : }
2780 :
2781 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2782 0 : }
2783 :
2784 : /*******************************************************************
2785 : * fill a notify_info_data with the servicename
2786 : ********************************************************************/
2787 :
2788 0 : static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2789 : int snum,
2790 : struct spoolss_Notify *data,
2791 : print_queue_struct *queue,
2792 : struct spoolss_PrinterInfo2 *pinfo2,
2793 : TALLOC_CTX *mem_ctx)
2794 : {
2795 0 : const struct loadparm_substitution *lp_sub =
2796 0 : loadparm_s3_global_substitution();
2797 :
2798 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), lp_sub, snum));
2799 0 : }
2800 :
2801 : /*******************************************************************
2802 : * fill a notify_info_data with the port name
2803 : ********************************************************************/
2804 :
2805 0 : static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2806 : int snum,
2807 : struct spoolss_Notify *data,
2808 : print_queue_struct *queue,
2809 : struct spoolss_PrinterInfo2 *pinfo2,
2810 : TALLOC_CTX *mem_ctx)
2811 : {
2812 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2813 0 : }
2814 :
2815 : /*******************************************************************
2816 : * fill a notify_info_data with the printername
2817 : * but it doesn't exist, have to see what to do
2818 : ********************************************************************/
2819 :
2820 0 : static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2821 : int snum,
2822 : struct spoolss_Notify *data,
2823 : print_queue_struct *queue,
2824 : struct spoolss_PrinterInfo2 *pinfo2,
2825 : TALLOC_CTX *mem_ctx)
2826 : {
2827 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2828 0 : }
2829 :
2830 : /*******************************************************************
2831 : * fill a notify_info_data with the comment
2832 : ********************************************************************/
2833 :
2834 0 : static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2835 : int snum,
2836 : struct spoolss_Notify *data,
2837 : print_queue_struct *queue,
2838 : struct spoolss_PrinterInfo2 *pinfo2,
2839 : TALLOC_CTX *mem_ctx)
2840 : {
2841 0 : const struct loadparm_substitution *lp_sub =
2842 0 : loadparm_s3_global_substitution();
2843 : const char *p;
2844 :
2845 0 : if (*pinfo2->comment == '\0') {
2846 0 : p = lp_comment(talloc_tos(), lp_sub, snum);
2847 : } else {
2848 0 : p = pinfo2->comment;
2849 : }
2850 :
2851 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2852 0 : }
2853 :
2854 : /*******************************************************************
2855 : * fill a notify_info_data with the comment
2856 : * location = "Room 1, floor 2, building 3"
2857 : ********************************************************************/
2858 :
2859 0 : static void spoolss_notify_location(struct messaging_context *msg_ctx,
2860 : int snum,
2861 : struct spoolss_Notify *data,
2862 : print_queue_struct *queue,
2863 : struct spoolss_PrinterInfo2 *pinfo2,
2864 : TALLOC_CTX *mem_ctx)
2865 : {
2866 0 : const char *loc = pinfo2->location;
2867 : NTSTATUS status;
2868 :
2869 0 : status = printer_list_get_printer(mem_ctx,
2870 : pinfo2->sharename,
2871 : NULL,
2872 : &loc,
2873 : NULL);
2874 0 : if (NT_STATUS_IS_OK(status)) {
2875 0 : if (loc == NULL) {
2876 0 : loc = pinfo2->location;
2877 : }
2878 : }
2879 :
2880 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2881 0 : }
2882 :
2883 : /*******************************************************************
2884 : * fill a notify_info_data with the device mode
2885 : * jfm:xxxx don't to it for know but that's a real problem !!!
2886 : ********************************************************************/
2887 :
2888 0 : static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2889 : int snum,
2890 : struct spoolss_Notify *data,
2891 : print_queue_struct *queue,
2892 : struct spoolss_PrinterInfo2 *pinfo2,
2893 : TALLOC_CTX *mem_ctx)
2894 : {
2895 : /* for a dummy implementation we have to zero the fields */
2896 0 : SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2897 0 : }
2898 :
2899 : /*******************************************************************
2900 : * fill a notify_info_data with the separator file name
2901 : ********************************************************************/
2902 :
2903 0 : static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2904 : int snum,
2905 : struct spoolss_Notify *data,
2906 : print_queue_struct *queue,
2907 : struct spoolss_PrinterInfo2 *pinfo2,
2908 : TALLOC_CTX *mem_ctx)
2909 : {
2910 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2911 0 : }
2912 :
2913 : /*******************************************************************
2914 : * fill a notify_info_data with the print processor
2915 : * jfm:xxxx return always winprint to indicate we don't do anything to it
2916 : ********************************************************************/
2917 :
2918 0 : static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2919 : int snum,
2920 : struct spoolss_Notify *data,
2921 : print_queue_struct *queue,
2922 : struct spoolss_PrinterInfo2 *pinfo2,
2923 : TALLOC_CTX *mem_ctx)
2924 : {
2925 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2926 0 : }
2927 :
2928 : /*******************************************************************
2929 : * fill a notify_info_data with the print processor options
2930 : * jfm:xxxx send an empty string
2931 : ********************************************************************/
2932 :
2933 0 : static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2934 : int snum,
2935 : struct spoolss_Notify *data,
2936 : print_queue_struct *queue,
2937 : struct spoolss_PrinterInfo2 *pinfo2,
2938 : TALLOC_CTX *mem_ctx)
2939 : {
2940 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2941 0 : }
2942 :
2943 : /*******************************************************************
2944 : * fill a notify_info_data with the data type
2945 : * jfm:xxxx always send RAW as data type
2946 : ********************************************************************/
2947 :
2948 0 : static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2949 : int snum,
2950 : struct spoolss_Notify *data,
2951 : print_queue_struct *queue,
2952 : struct spoolss_PrinterInfo2 *pinfo2,
2953 : TALLOC_CTX *mem_ctx)
2954 : {
2955 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2956 0 : }
2957 :
2958 : /*******************************************************************
2959 : * fill a notify_info_data with the security descriptor
2960 : * jfm:xxxx send an null pointer to say no security desc
2961 : * have to implement security before !
2962 : ********************************************************************/
2963 :
2964 0 : static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2965 : int snum,
2966 : struct spoolss_Notify *data,
2967 : print_queue_struct *queue,
2968 : struct spoolss_PrinterInfo2 *pinfo2,
2969 : TALLOC_CTX *mem_ctx)
2970 : {
2971 0 : if (pinfo2->secdesc == NULL) {
2972 0 : data->data.sd.sd = NULL;
2973 : } else {
2974 0 : data->data.sd.sd = security_descriptor_copy(mem_ctx,
2975 0 : pinfo2->secdesc);
2976 : }
2977 0 : data->data.sd.sd_size = ndr_size_security_descriptor(data->data.sd.sd,
2978 : 0);
2979 0 : }
2980 :
2981 : /*******************************************************************
2982 : * fill a notify_info_data with the attributes
2983 : * jfm:xxxx a samba printer is always shared
2984 : ********************************************************************/
2985 :
2986 0 : static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2987 : int snum,
2988 : struct spoolss_Notify *data,
2989 : print_queue_struct *queue,
2990 : struct spoolss_PrinterInfo2 *pinfo2,
2991 : TALLOC_CTX *mem_ctx)
2992 : {
2993 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2994 0 : }
2995 :
2996 : /*******************************************************************
2997 : * fill a notify_info_data with the priority
2998 : ********************************************************************/
2999 :
3000 0 : static void spoolss_notify_priority(struct messaging_context *msg_ctx,
3001 : int snum,
3002 : struct spoolss_Notify *data,
3003 : print_queue_struct *queue,
3004 : struct spoolss_PrinterInfo2 *pinfo2,
3005 : TALLOC_CTX *mem_ctx)
3006 : {
3007 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
3008 0 : }
3009 :
3010 : /*******************************************************************
3011 : * fill a notify_info_data with the default priority
3012 : ********************************************************************/
3013 :
3014 0 : static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3015 : int snum,
3016 : struct spoolss_Notify *data,
3017 : print_queue_struct *queue,
3018 : struct spoolss_PrinterInfo2 *pinfo2,
3019 : TALLOC_CTX *mem_ctx)
3020 : {
3021 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3022 0 : }
3023 :
3024 : /*******************************************************************
3025 : * fill a notify_info_data with the start time
3026 : ********************************************************************/
3027 :
3028 0 : static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3029 : int snum,
3030 : struct spoolss_Notify *data,
3031 : print_queue_struct *queue,
3032 : struct spoolss_PrinterInfo2 *pinfo2,
3033 : TALLOC_CTX *mem_ctx)
3034 : {
3035 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3036 0 : }
3037 :
3038 : /*******************************************************************
3039 : * fill a notify_info_data with the until time
3040 : ********************************************************************/
3041 :
3042 0 : static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3043 : int snum,
3044 : struct spoolss_Notify *data,
3045 : print_queue_struct *queue,
3046 : struct spoolss_PrinterInfo2 *pinfo2,
3047 : TALLOC_CTX *mem_ctx)
3048 : {
3049 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3050 0 : }
3051 :
3052 : /*******************************************************************
3053 : * fill a notify_info_data with the status
3054 : ********************************************************************/
3055 :
3056 0 : static void spoolss_notify_status(struct messaging_context *msg_ctx,
3057 : int snum,
3058 : struct spoolss_Notify *data,
3059 : print_queue_struct *queue,
3060 : struct spoolss_PrinterInfo2 *pinfo2,
3061 : TALLOC_CTX *mem_ctx)
3062 : {
3063 : print_status_struct status;
3064 :
3065 0 : print_queue_length(msg_ctx, snum, &status);
3066 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3067 0 : }
3068 :
3069 : /*******************************************************************
3070 : * fill a notify_info_data with the number of jobs queued
3071 : ********************************************************************/
3072 :
3073 0 : static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3074 : int snum,
3075 : struct spoolss_Notify *data,
3076 : print_queue_struct *queue,
3077 : struct spoolss_PrinterInfo2 *pinfo2,
3078 : TALLOC_CTX *mem_ctx)
3079 : {
3080 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3081 : data, print_queue_length(msg_ctx, snum, NULL));
3082 0 : }
3083 :
3084 : /*******************************************************************
3085 : * fill a notify_info_data with the average ppm
3086 : ********************************************************************/
3087 :
3088 0 : static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3089 : int snum,
3090 : struct spoolss_Notify *data,
3091 : print_queue_struct *queue,
3092 : struct spoolss_PrinterInfo2 *pinfo2,
3093 : TALLOC_CTX *mem_ctx)
3094 : {
3095 : /* always respond 8 pages per minutes */
3096 : /* a little hard ! */
3097 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3098 0 : }
3099 :
3100 : /*******************************************************************
3101 : * fill a notify_info_data with username
3102 : ********************************************************************/
3103 :
3104 0 : static void spoolss_notify_username(struct messaging_context *msg_ctx,
3105 : int snum,
3106 : struct spoolss_Notify *data,
3107 : print_queue_struct *queue,
3108 : struct spoolss_PrinterInfo2 *pinfo2,
3109 : TALLOC_CTX *mem_ctx)
3110 : {
3111 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3112 0 : }
3113 :
3114 : /*******************************************************************
3115 : * fill a notify_info_data with job status
3116 : ********************************************************************/
3117 :
3118 0 : static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3119 : int snum,
3120 : struct spoolss_Notify *data,
3121 : print_queue_struct *queue,
3122 : struct spoolss_PrinterInfo2 *pinfo2,
3123 : TALLOC_CTX *mem_ctx)
3124 : {
3125 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3126 0 : }
3127 :
3128 : /*******************************************************************
3129 : * fill a notify_info_data with job name
3130 : ********************************************************************/
3131 :
3132 0 : static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3133 : int snum,
3134 : struct spoolss_Notify *data,
3135 : print_queue_struct *queue,
3136 : struct spoolss_PrinterInfo2 *pinfo2,
3137 : TALLOC_CTX *mem_ctx)
3138 : {
3139 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3140 0 : }
3141 :
3142 : /*******************************************************************
3143 : * fill a notify_info_data with job status
3144 : ********************************************************************/
3145 :
3146 0 : static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3147 : int snum,
3148 : struct spoolss_Notify *data,
3149 : print_queue_struct *queue,
3150 : struct spoolss_PrinterInfo2 *pinfo2,
3151 : TALLOC_CTX *mem_ctx)
3152 : {
3153 : /*
3154 : * Now we're returning job status codes we just return a "" here. JRA.
3155 : */
3156 :
3157 0 : const char *p = "";
3158 :
3159 : #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3160 : p = "unknown";
3161 :
3162 : switch (queue->status) {
3163 : case LPQ_QUEUED:
3164 : p = "Queued";
3165 : break;
3166 : case LPQ_PAUSED:
3167 : p = ""; /* NT provides the paused string */
3168 : break;
3169 : case LPQ_SPOOLING:
3170 : p = "Spooling";
3171 : break;
3172 : case LPQ_PRINTING:
3173 : p = "Printing";
3174 : break;
3175 : }
3176 : #endif /* NO LONGER NEEDED. */
3177 :
3178 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3179 0 : }
3180 :
3181 : /*******************************************************************
3182 : * fill a notify_info_data with job time
3183 : ********************************************************************/
3184 :
3185 0 : static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3186 : int snum,
3187 : struct spoolss_Notify *data,
3188 : print_queue_struct *queue,
3189 : struct spoolss_PrinterInfo2 *pinfo2,
3190 : TALLOC_CTX *mem_ctx)
3191 : {
3192 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3193 0 : }
3194 :
3195 : /*******************************************************************
3196 : * fill a notify_info_data with job size
3197 : ********************************************************************/
3198 :
3199 0 : static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3200 : int snum,
3201 : struct spoolss_Notify *data,
3202 : print_queue_struct *queue,
3203 : struct spoolss_PrinterInfo2 *pinfo2,
3204 : TALLOC_CTX *mem_ctx)
3205 : {
3206 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3207 0 : }
3208 :
3209 : /*******************************************************************
3210 : * fill a notify_info_data with page info
3211 : ********************************************************************/
3212 0 : static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3213 : int snum,
3214 : struct spoolss_Notify *data,
3215 : print_queue_struct *queue,
3216 : struct spoolss_PrinterInfo2 *pinfo2,
3217 : TALLOC_CTX *mem_ctx)
3218 : {
3219 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3220 0 : }
3221 :
3222 : /*******************************************************************
3223 : * fill a notify_info_data with pages printed info.
3224 : ********************************************************************/
3225 0 : static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3226 : int snum,
3227 : struct spoolss_Notify *data,
3228 : print_queue_struct *queue,
3229 : struct spoolss_PrinterInfo2 *pinfo2,
3230 : TALLOC_CTX *mem_ctx)
3231 : {
3232 : /* Add code when back-end tracks this */
3233 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3234 0 : }
3235 :
3236 : /*******************************************************************
3237 : Fill a notify_info_data with job position.
3238 : ********************************************************************/
3239 :
3240 0 : static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3241 : int snum,
3242 : struct spoolss_Notify *data,
3243 : print_queue_struct *queue,
3244 : struct spoolss_PrinterInfo2 *pinfo2,
3245 : TALLOC_CTX *mem_ctx)
3246 : {
3247 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
3248 0 : }
3249 :
3250 : /*******************************************************************
3251 : Fill a notify_info_data with submitted time.
3252 : ********************************************************************/
3253 :
3254 0 : static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3255 : int snum,
3256 : struct spoolss_Notify *data,
3257 : print_queue_struct *queue,
3258 : struct spoolss_PrinterInfo2 *pinfo2,
3259 : TALLOC_CTX *mem_ctx)
3260 : {
3261 0 : data->data.string.string = NULL;
3262 0 : data->data.string.size = 0;
3263 :
3264 0 : init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3265 : &data->data.string.string,
3266 : &data->data.string.size);
3267 :
3268 0 : }
3269 :
3270 : struct s_notify_info_data_table
3271 : {
3272 : enum spoolss_NotifyType type;
3273 : uint16_t field;
3274 : const char *name;
3275 : enum spoolss_NotifyTable variable_type;
3276 : void (*fn) (struct messaging_context *msg_ctx,
3277 : int snum, struct spoolss_Notify *data,
3278 : print_queue_struct *queue,
3279 : struct spoolss_PrinterInfo2 *pinfo2,
3280 : TALLOC_CTX *mem_ctx);
3281 : };
3282 :
3283 : /* A table describing the various print notification constants and
3284 : whether the notification data is a pointer to a variable sized
3285 : buffer, a one value uint32_t or a two value uint32_t. */
3286 :
3287 : static const struct s_notify_info_data_table notify_info_data_table[] =
3288 : {
3289 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3290 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3291 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3292 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3293 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3294 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3295 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3296 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3297 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3298 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3299 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3300 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3301 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3302 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3303 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3304 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3305 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3306 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3307 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3308 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3309 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3310 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3311 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3312 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3313 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3314 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3315 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3316 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3317 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3318 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3319 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3320 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3321 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3322 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3323 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3324 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3325 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3326 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3327 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3328 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3329 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3330 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3331 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3332 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3333 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3334 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3335 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3336 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3337 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3338 : };
3339 :
3340 : /*******************************************************************
3341 : Return the variable_type of info_data structure.
3342 : ********************************************************************/
3343 :
3344 0 : static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3345 : uint16_t field)
3346 : {
3347 0 : int i=0;
3348 :
3349 0 : for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3350 0 : if ( (notify_info_data_table[i].type == type) &&
3351 0 : (notify_info_data_table[i].field == field) ) {
3352 0 : return notify_info_data_table[i].variable_type;
3353 : }
3354 : }
3355 :
3356 0 : DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3357 :
3358 0 : return (enum spoolss_NotifyTable) 0;
3359 : }
3360 :
3361 : /****************************************************************************
3362 : ****************************************************************************/
3363 :
3364 0 : static bool search_notify(enum spoolss_NotifyType type,
3365 : uint16_t field,
3366 : int *value)
3367 : {
3368 : int i;
3369 :
3370 0 : for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3371 0 : if (notify_info_data_table[i].type == type &&
3372 0 : notify_info_data_table[i].field == field &&
3373 0 : notify_info_data_table[i].fn != NULL) {
3374 0 : *value = i;
3375 0 : return true;
3376 : }
3377 : }
3378 :
3379 0 : return false;
3380 : }
3381 :
3382 : /****************************************************************************
3383 : ****************************************************************************/
3384 :
3385 0 : static void construct_info_data(struct spoolss_Notify *info_data,
3386 : enum spoolss_NotifyType type,
3387 : uint16_t field, int id)
3388 : {
3389 0 : info_data->type = type;
3390 0 : info_data->field.field = field;
3391 0 : info_data->variable_type = variable_type_of_notify_info_data(type, field);
3392 0 : info_data->job_id = id;
3393 0 : }
3394 :
3395 : /*******************************************************************
3396 : *
3397 : * fill a notify_info struct with info asked
3398 : *
3399 : ********************************************************************/
3400 :
3401 0 : static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3402 : struct printer_handle *print_hnd,
3403 : struct spoolss_NotifyInfo *info,
3404 : struct spoolss_PrinterInfo2 *pinfo2,
3405 : int snum,
3406 : const struct spoolss_NotifyOptionType *option_type,
3407 : uint32_t id,
3408 : TALLOC_CTX *mem_ctx)
3409 : {
3410 0 : const struct loadparm_substitution *lp_sub =
3411 0 : loadparm_s3_global_substitution();
3412 : int field_num,j;
3413 : enum spoolss_NotifyType type;
3414 : uint16_t field;
3415 :
3416 : struct spoolss_Notify *current_data;
3417 :
3418 0 : type = option_type->type;
3419 :
3420 0 : DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3421 : (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3422 : option_type->count, lp_servicename(talloc_tos(), lp_sub, snum)));
3423 :
3424 0 : for(field_num=0; field_num < option_type->count; field_num++) {
3425 0 : field = option_type->fields[field_num].field;
3426 :
3427 0 : DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3428 :
3429 0 : if (!search_notify(type, field, &j) )
3430 0 : continue;
3431 :
3432 0 : info->notifies = talloc_realloc(info, info->notifies,
3433 : struct spoolss_Notify,
3434 : info->count + 1);
3435 0 : if (info->notifies == NULL) {
3436 0 : DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3437 0 : return false;
3438 : }
3439 :
3440 0 : current_data = &info->notifies[info->count];
3441 :
3442 0 : construct_info_data(current_data, type, field, id);
3443 :
3444 0 : DEBUG(10, ("construct_notify_printer_info: "
3445 : "calling [%s] snum=%d printername=[%s])\n",
3446 : notify_info_data_table[j].name, snum,
3447 : pinfo2->printername));
3448 :
3449 0 : notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3450 : NULL, pinfo2, mem_ctx);
3451 :
3452 0 : info->count++;
3453 : }
3454 :
3455 0 : return true;
3456 : }
3457 :
3458 : /*******************************************************************
3459 : *
3460 : * fill a notify_info struct with info asked
3461 : *
3462 : ********************************************************************/
3463 :
3464 0 : static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3465 : print_queue_struct *queue,
3466 : struct spoolss_NotifyInfo *info,
3467 : struct spoolss_PrinterInfo2 *pinfo2,
3468 : int snum,
3469 : const struct spoolss_NotifyOptionType *option_type,
3470 : uint32_t id,
3471 : TALLOC_CTX *mem_ctx)
3472 : {
3473 : int field_num,j;
3474 : enum spoolss_NotifyType type;
3475 : uint16_t field;
3476 : struct spoolss_Notify *current_data;
3477 :
3478 0 : DEBUG(4,("construct_notify_jobs_info\n"));
3479 :
3480 0 : type = option_type->type;
3481 :
3482 0 : DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3483 : (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3484 : option_type->count));
3485 :
3486 0 : for(field_num=0; field_num<option_type->count; field_num++) {
3487 0 : field = option_type->fields[field_num].field;
3488 :
3489 0 : if (!search_notify(type, field, &j) )
3490 0 : continue;
3491 :
3492 0 : info->notifies = talloc_realloc(info, info->notifies,
3493 : struct spoolss_Notify,
3494 : info->count + 1);
3495 0 : if (info->notifies == NULL) {
3496 0 : DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3497 0 : return false;
3498 : }
3499 :
3500 0 : current_data=&(info->notifies[info->count]);
3501 :
3502 0 : construct_info_data(current_data, type, field, id);
3503 0 : notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3504 : queue, pinfo2, mem_ctx);
3505 0 : info->count++;
3506 : }
3507 :
3508 0 : return true;
3509 : }
3510 :
3511 : /*
3512 : * JFM: The enumeration is not that simple, it's even non obvious.
3513 : *
3514 : * let's take an example: I want to monitor the PRINTER SERVER for
3515 : * the printer's name and the number of jobs currently queued.
3516 : * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3517 : * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3518 : *
3519 : * I have 3 printers on the back of my server.
3520 : *
3521 : * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3522 : * structures.
3523 : * Number Data Id
3524 : * 1 printer 1 name 1
3525 : * 2 printer 1 cjob 1
3526 : * 3 printer 2 name 2
3527 : * 4 printer 2 cjob 2
3528 : * 5 printer 3 name 3
3529 : * 6 printer 3 name 3
3530 : *
3531 : * that's the print server case, the printer case is even worse.
3532 : */
3533 :
3534 : /*******************************************************************
3535 : *
3536 : * enumerate all printers on the printserver
3537 : * fill a notify_info struct with info asked
3538 : *
3539 : ********************************************************************/
3540 :
3541 4 : static WERROR printserver_notify_info(struct pipes_struct *p,
3542 : struct policy_handle *hnd,
3543 : struct spoolss_NotifyInfo *info,
3544 : TALLOC_CTX *mem_ctx)
3545 : {
3546 2 : const struct loadparm_substitution *lp_sub =
3547 2 : loadparm_s3_global_substitution();
3548 : int snum;
3549 4 : struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3550 4 : int n_services=lp_numservices();
3551 : int i;
3552 : struct spoolss_NotifyOption *option;
3553 : struct spoolss_NotifyOptionType option_type;
3554 4 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3555 : WERROR result;
3556 :
3557 4 : DEBUG(4,("printserver_notify_info\n"));
3558 :
3559 4 : if (!Printer)
3560 0 : return WERR_INVALID_HANDLE;
3561 :
3562 4 : option = Printer->notify.option;
3563 :
3564 4 : info->version = 2;
3565 4 : info->notifies = NULL;
3566 4 : info->count = 0;
3567 :
3568 : /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3569 : sending a ffpcn() request first */
3570 :
3571 4 : if ( !option )
3572 0 : return WERR_INVALID_HANDLE;
3573 :
3574 12 : for (i=0; i<option->count; i++) {
3575 8 : option_type = option->types[i];
3576 :
3577 8 : if (option_type.type != PRINTER_NOTIFY_TYPE)
3578 4 : continue;
3579 :
3580 448 : for (snum = 0; snum < n_services; snum++) {
3581 666 : if (!lp_browseable(snum) ||
3582 666 : !lp_snum_ok(snum) ||
3583 444 : !lp_printable(snum)) {
3584 424 : continue; /* skip */
3585 : }
3586 :
3587 : /* Maybe we should use the SYSTEM session_info here... */
3588 20 : result = winreg_get_printer_internal(mem_ctx,
3589 : get_session_info_system(),
3590 : p->msg_ctx,
3591 20 : lp_servicename(talloc_tos(), lp_sub, snum),
3592 : &pinfo2);
3593 20 : if (!W_ERROR_IS_OK(result)) {
3594 20 : DEBUG(4, ("printserver_notify_info: "
3595 : "Failed to get printer [%s]\n",
3596 : lp_servicename(talloc_tos(), lp_sub, snum)));
3597 20 : continue;
3598 : }
3599 :
3600 :
3601 0 : construct_notify_printer_info(p->msg_ctx,
3602 : Printer, info,
3603 : pinfo2, snum,
3604 : &option_type, snum,
3605 : mem_ctx);
3606 :
3607 0 : TALLOC_FREE(pinfo2);
3608 : }
3609 : }
3610 :
3611 : #if 0
3612 : /*
3613 : * Debugging information, don't delete.
3614 : */
3615 :
3616 : DEBUG(1,("dumping the NOTIFY_INFO\n"));
3617 : DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3618 : DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3619 :
3620 : for (i=0; i<info->count; i++) {
3621 : DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3622 : i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3623 : info->data[i].id, info->data[i].size, info->data[i].enc_type));
3624 : }
3625 : #endif
3626 :
3627 4 : return WERR_OK;
3628 : }
3629 :
3630 : /*******************************************************************
3631 : *
3632 : * fill a notify_info struct with info asked
3633 : *
3634 : ********************************************************************/
3635 :
3636 0 : static WERROR printer_notify_info(struct pipes_struct *p,
3637 : struct policy_handle *hnd,
3638 : struct spoolss_NotifyInfo *info,
3639 : TALLOC_CTX *mem_ctx)
3640 : {
3641 0 : const struct loadparm_substitution *lp_sub =
3642 0 : loadparm_s3_global_substitution();
3643 : int snum;
3644 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3645 : int i;
3646 : uint32_t id;
3647 : struct spoolss_NotifyOption *option;
3648 : struct spoolss_NotifyOptionType option_type;
3649 : int count,j;
3650 0 : print_queue_struct *queue=NULL;
3651 : print_status_struct status;
3652 0 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3653 : WERROR result;
3654 : struct tdb_print_db *pdb;
3655 :
3656 0 : DEBUG(4,("printer_notify_info\n"));
3657 :
3658 0 : if (!Printer)
3659 0 : return WERR_INVALID_HANDLE;
3660 :
3661 0 : option = Printer->notify.option;
3662 0 : id = 0x0;
3663 :
3664 0 : info->version = 2;
3665 0 : info->notifies = NULL;
3666 0 : info->count = 0;
3667 :
3668 : /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3669 : sending a ffpcn() request first */
3670 :
3671 0 : if ( !option )
3672 0 : return WERR_INVALID_HANDLE;
3673 :
3674 0 : if (!get_printer_snum(p, hnd, &snum, NULL)) {
3675 0 : return WERR_INVALID_HANDLE;
3676 : }
3677 :
3678 0 : pdb = get_print_db_byname(Printer->sharename);
3679 0 : if (pdb == NULL) {
3680 0 : return WERR_INVALID_HANDLE;
3681 : }
3682 :
3683 : /* Maybe we should use the SYSTEM session_info here... */
3684 0 : result = winreg_get_printer_internal(mem_ctx,
3685 : get_session_info_system(),
3686 : p->msg_ctx,
3687 0 : lp_servicename(talloc_tos(), lp_sub, snum), &pinfo2);
3688 0 : if (!W_ERROR_IS_OK(result)) {
3689 0 : result = WERR_INVALID_HANDLE;
3690 0 : goto err_pdb_drop;
3691 : }
3692 :
3693 : /*
3694 : * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3695 : * correct servername.
3696 : */
3697 0 : pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3698 0 : if (pinfo2->servername == NULL) {
3699 0 : result = WERR_NOT_ENOUGH_MEMORY;
3700 0 : goto err_pdb_drop;
3701 : }
3702 :
3703 0 : for (i = 0; i < option->count; i++) {
3704 0 : option_type = option->types[i];
3705 :
3706 0 : switch (option_type.type) {
3707 0 : case PRINTER_NOTIFY_TYPE:
3708 0 : if (construct_notify_printer_info(p->msg_ctx,
3709 : Printer, info,
3710 : pinfo2, snum,
3711 : &option_type, id,
3712 : mem_ctx)) {
3713 0 : id--;
3714 : }
3715 0 : break;
3716 :
3717 0 : case JOB_NOTIFY_TYPE:
3718 :
3719 0 : count = print_queue_status(p->msg_ctx, snum, &queue,
3720 : &status);
3721 :
3722 0 : for (j = 0; j < count; j++) {
3723 : uint32_t jobid;
3724 0 : jobid = sysjob_to_jobid_pdb(pdb,
3725 0 : queue[j].sysjob);
3726 0 : if (jobid == (uint32_t)-1) {
3727 0 : DEBUG(2, ("ignoring untracked job %d\n",
3728 : queue[j].sysjob));
3729 0 : continue;
3730 : }
3731 : /* FIXME check return value */
3732 0 : construct_notify_jobs_info(p->msg_ctx,
3733 0 : &queue[j], info,
3734 : pinfo2, snum,
3735 : &option_type,
3736 : jobid,
3737 : mem_ctx);
3738 : }
3739 :
3740 0 : SAFE_FREE(queue);
3741 0 : break;
3742 : }
3743 : }
3744 :
3745 : /*
3746 : * Debugging information, don't delete.
3747 : */
3748 : /*
3749 : DEBUG(1,("dumping the NOTIFY_INFO\n"));
3750 : DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3751 : DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3752 :
3753 : for (i=0; i<info->count; i++) {
3754 : DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3755 : i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3756 : info->data[i].id, info->data[i].size, info->data[i].enc_type));
3757 : }
3758 : */
3759 :
3760 0 : talloc_free(pinfo2);
3761 0 : result = WERR_OK;
3762 0 : err_pdb_drop:
3763 0 : release_print_db(pdb);
3764 0 : return result;
3765 : }
3766 :
3767 : /****************************************************************
3768 : _spoolss_RouterRefreshPrinterChangeNotify
3769 : ****************************************************************/
3770 :
3771 4 : WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3772 : struct spoolss_RouterRefreshPrinterChangeNotify *r)
3773 : {
3774 : struct spoolss_NotifyInfo *info;
3775 :
3776 4 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3777 4 : WERROR result = WERR_INVALID_HANDLE;
3778 :
3779 : /* we always have a spoolss_NotifyInfo struct */
3780 4 : info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3781 4 : if (!info) {
3782 0 : result = WERR_NOT_ENOUGH_MEMORY;
3783 0 : goto done;
3784 : }
3785 :
3786 4 : *r->out.info = info;
3787 :
3788 4 : if (!Printer) {
3789 0 : DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3790 : "Invalid handle (%s:%u:%u).\n",
3791 : OUR_HANDLE(r->in.handle)));
3792 0 : goto done;
3793 : }
3794 :
3795 4 : DEBUG(4,("Printer type %x\n",Printer->printer_type));
3796 :
3797 : /*
3798 : * We are now using the change value, and
3799 : * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3800 : * I don't have a global notification system, I'm sending back all the
3801 : * information even when _NOTHING_ has changed.
3802 : */
3803 :
3804 : /* We need to keep track of the change value to send back in
3805 : RRPCN replies otherwise our updates are ignored. */
3806 :
3807 4 : Printer->notify.fnpcn = true;
3808 :
3809 6 : if (Printer->notify.cli_chan != NULL &&
3810 4 : Printer->notify.cli_chan->active_connections > 0) {
3811 4 : DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3812 : "Saving change value in request [%x]\n",
3813 : r->in.change_low));
3814 4 : Printer->notify.change = r->in.change_low;
3815 : }
3816 :
3817 : /* just ignore the spoolss_NotifyOption */
3818 :
3819 4 : switch (Printer->printer_type) {
3820 4 : case SPLHND_SERVER:
3821 4 : result = printserver_notify_info(p, r->in.handle,
3822 : info, p->mem_ctx);
3823 4 : break;
3824 :
3825 0 : case SPLHND_PRINTER:
3826 0 : result = printer_notify_info(p, r->in.handle,
3827 : info, p->mem_ctx);
3828 0 : break;
3829 : }
3830 :
3831 4 : Printer->notify.fnpcn = false;
3832 :
3833 4 : done:
3834 4 : return result;
3835 : }
3836 :
3837 : /********************************************************************
3838 : ********************************************************************/
3839 :
3840 0 : static WERROR create_printername(TALLOC_CTX *mem_ctx,
3841 : const char *servername,
3842 : const char *printername,
3843 : const char **printername_p)
3844 : {
3845 : /* FIXME: add lp_force_printername() */
3846 :
3847 0 : if (servername == NULL) {
3848 0 : *printername_p = talloc_strdup(mem_ctx, printername);
3849 0 : W_ERROR_HAVE_NO_MEMORY(*printername_p);
3850 0 : return WERR_OK;
3851 : }
3852 :
3853 0 : if (servername[0] == '\\' && servername[1] == '\\') {
3854 0 : servername += 2;
3855 : }
3856 :
3857 0 : *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3858 0 : W_ERROR_HAVE_NO_MEMORY(*printername_p);
3859 :
3860 0 : return WERR_OK;
3861 : }
3862 :
3863 : /********************************************************************
3864 : ********************************************************************/
3865 :
3866 0 : static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3867 : const char *printername)
3868 : {
3869 0 : if (dm == NULL) {
3870 0 : return;
3871 : }
3872 :
3873 0 : dm->devicename = talloc_strndup(dm, printername,
3874 0 : MIN(strlen(printername), 31));
3875 : }
3876 :
3877 : /********************************************************************
3878 : * construct_printer_info_0
3879 : * fill a printer_info_0 struct
3880 : ********************************************************************/
3881 :
3882 0 : static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3883 : const struct auth_session_info *session_info,
3884 : struct messaging_context *msg_ctx,
3885 : struct spoolss_PrinterInfo2 *info2,
3886 : const char *servername,
3887 : struct spoolss_PrinterInfo0 *r,
3888 : int snum)
3889 : {
3890 : int count;
3891 : struct printer_session_counter *session_counter;
3892 : struct timeval setuptime;
3893 : print_status_struct status;
3894 : WERROR result;
3895 : int os_major, os_minor, os_build;
3896 : const char *architecture;
3897 : uint32_t processor_architecture, processor_type;
3898 :
3899 0 : result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3900 0 : if (!W_ERROR_IS_OK(result)) {
3901 0 : return result;
3902 : }
3903 :
3904 0 : if (servername) {
3905 0 : r->servername = talloc_strdup(mem_ctx, servername);
3906 0 : W_ERROR_HAVE_NO_MEMORY(r->servername);
3907 : } else {
3908 0 : r->servername = NULL;
3909 : }
3910 :
3911 0 : count = print_queue_length(msg_ctx, snum, &status);
3912 :
3913 : /* check if we already have a counter for this printer */
3914 0 : for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3915 0 : if (session_counter->snum == snum)
3916 0 : break;
3917 : }
3918 :
3919 : /* it's the first time, add it to the list */
3920 0 : if (session_counter == NULL) {
3921 0 : session_counter = talloc_zero(counter_list, struct printer_session_counter);
3922 0 : W_ERROR_HAVE_NO_MEMORY(session_counter);
3923 0 : session_counter->snum = snum;
3924 0 : session_counter->counter = 0;
3925 0 : DLIST_ADD(counter_list, session_counter);
3926 : }
3927 :
3928 : /* increment it */
3929 0 : session_counter->counter++;
3930 :
3931 0 : r->cjobs = count;
3932 0 : r->total_jobs = 0;
3933 0 : r->total_bytes = 0;
3934 :
3935 0 : get_startup_time(&setuptime);
3936 0 : init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3937 :
3938 : /* JFM:
3939 : * the global_counter should be stored in a TDB as it's common to all the clients
3940 : * and should be zeroed on samba startup
3941 : */
3942 0 : r->global_counter = session_counter->counter;
3943 0 : r->total_pages = 0;
3944 :
3945 : /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3946 0 : os_major = lp_parm_int(GLOBAL_SECTION_SNUM,
3947 : "spoolss", "os_major",
3948 : GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT);
3949 0 : os_minor = lp_parm_int(GLOBAL_SECTION_SNUM,
3950 : "spoolss", "os_minor",
3951 : GLOBAL_SPOOLSS_OS_MINOR_DEFAULT);
3952 0 : os_build = lp_parm_int(GLOBAL_SECTION_SNUM,
3953 : "spoolss", "os_build",
3954 : GLOBAL_SPOOLSS_OS_BUILD_DEFAULT);
3955 :
3956 0 : SCVAL(&r->version, 0, os_major);
3957 0 : SCVAL(&r->version, 1, os_minor);
3958 0 : SSVAL(&r->version, 2, os_build);
3959 :
3960 0 : architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
3961 : "spoolss",
3962 : "architecture",
3963 : GLOBAL_SPOOLSS_ARCHITECTURE);
3964 :
3965 0 : if (strequal(architecture, SPOOLSS_ARCHITECTURE_x64)) {
3966 0 : processor_architecture = PROCESSOR_ARCHITECTURE_AMD64;
3967 0 : processor_type = PROCESSOR_AMD_X8664;
3968 0 : } else if (strequal(architecture, SPOOLSS_ARCHITECTURE_ARM64)) {
3969 0 : processor_architecture = PROCESSOR_ARCHITECTURE_ARM64;
3970 0 : processor_type = PROCESSOR_ARM820;
3971 : } else {
3972 0 : processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3973 0 : processor_type = PROCESSOR_INTEL_PENTIUM;
3974 : }
3975 :
3976 0 : r->free_build = SPOOLSS_RELEASE_BUILD;
3977 0 : r->spooling = 0;
3978 0 : r->max_spooling = 0;
3979 0 : r->session_counter = session_counter->counter;
3980 0 : r->num_error_out_of_paper = 0x0;
3981 0 : r->num_error_not_ready = 0x0; /* number of print failure */
3982 0 : r->job_error = 0x0;
3983 0 : r->number_of_processors = 0x1;
3984 0 : r->processor_type = processor_type;
3985 0 : r->high_part_total_bytes = 0x0;
3986 :
3987 : /* ChangeID in milliseconds*/
3988 0 : winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3989 : info2->sharename, &r->change_id);
3990 :
3991 0 : r->last_error = WERR_OK;
3992 0 : r->status = nt_printq_status(status.status);
3993 0 : r->enumerate_network_printers = 0x0;
3994 0 : r->c_setprinter = 0x0;
3995 0 : r->processor_architecture = processor_architecture;
3996 0 : r->processor_level = 0x6; /* 6 ???*/
3997 0 : r->ref_ic = 0;
3998 0 : r->reserved2 = 0;
3999 0 : r->reserved3 = 0;
4000 :
4001 0 : return WERR_OK;
4002 : }
4003 :
4004 :
4005 : /********************************************************************
4006 : * construct_printer_info1
4007 : * fill a spoolss_PrinterInfo1 struct
4008 : ********************************************************************/
4009 :
4010 0 : static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
4011 : const struct spoolss_PrinterInfo2 *info2,
4012 : uint32_t flags,
4013 : const char *servername,
4014 : struct spoolss_PrinterInfo1 *r,
4015 : int snum)
4016 : {
4017 0 : const struct loadparm_substitution *lp_sub =
4018 0 : loadparm_s3_global_substitution();
4019 : WERROR result;
4020 :
4021 0 : r->flags = flags;
4022 :
4023 0 : if (info2->comment == NULL || info2->comment[0] == '\0') {
4024 0 : r->comment = lp_comment(mem_ctx, lp_sub, snum);
4025 : } else {
4026 0 : r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
4027 : }
4028 0 : W_ERROR_HAVE_NO_MEMORY(r->comment);
4029 :
4030 0 : result = create_printername(mem_ctx, servername, info2->printername, &r->name);
4031 0 : if (!W_ERROR_IS_OK(result)) {
4032 0 : return result;
4033 : }
4034 :
4035 0 : r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
4036 : r->name,
4037 0 : info2->drivername,
4038 : r->comment);
4039 0 : W_ERROR_HAVE_NO_MEMORY(r->description);
4040 :
4041 0 : return WERR_OK;
4042 : }
4043 :
4044 : /********************************************************************
4045 : * construct_printer_info2
4046 : * fill a spoolss_PrinterInfo2 struct
4047 : ********************************************************************/
4048 :
4049 0 : static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4050 : struct messaging_context *msg_ctx,
4051 : const struct spoolss_PrinterInfo2 *info2,
4052 : const char *servername,
4053 : struct spoolss_PrinterInfo2 *r,
4054 : int snum)
4055 : {
4056 0 : const struct loadparm_substitution *lp_sub =
4057 0 : loadparm_s3_global_substitution();
4058 : int count;
4059 : print_status_struct status;
4060 : WERROR result;
4061 :
4062 0 : count = print_queue_length(msg_ctx, snum, &status);
4063 :
4064 0 : if (servername) {
4065 0 : r->servername = talloc_strdup(mem_ctx, servername);
4066 0 : W_ERROR_HAVE_NO_MEMORY(r->servername);
4067 : } else {
4068 0 : r->servername = NULL;
4069 : }
4070 :
4071 0 : result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4072 0 : if (!W_ERROR_IS_OK(result)) {
4073 0 : return result;
4074 : }
4075 :
4076 0 : r->sharename = lp_servicename(mem_ctx, lp_sub, snum);
4077 0 : W_ERROR_HAVE_NO_MEMORY(r->sharename);
4078 0 : r->portname = talloc_strdup(mem_ctx, info2->portname);
4079 0 : W_ERROR_HAVE_NO_MEMORY(r->portname);
4080 0 : r->drivername = talloc_strdup(mem_ctx, info2->drivername);
4081 0 : W_ERROR_HAVE_NO_MEMORY(r->drivername);
4082 :
4083 0 : if (info2->comment[0] == '\0') {
4084 0 : r->comment = lp_comment(mem_ctx, lp_sub, snum);
4085 : } else {
4086 0 : r->comment = talloc_strdup(mem_ctx, info2->comment);
4087 : }
4088 0 : W_ERROR_HAVE_NO_MEMORY(r->comment);
4089 :
4090 0 : r->location = talloc_strdup(mem_ctx, info2->location);
4091 0 : if (info2->location[0] == '\0') {
4092 0 : const char *loc = NULL;
4093 : NTSTATUS nt_status;
4094 :
4095 0 : nt_status = printer_list_get_printer(mem_ctx,
4096 0 : info2->sharename,
4097 : NULL,
4098 : &loc,
4099 : NULL);
4100 0 : if (NT_STATUS_IS_OK(nt_status)) {
4101 0 : if (loc != NULL) {
4102 0 : r->location = talloc_strdup(mem_ctx, loc);
4103 : }
4104 : }
4105 : }
4106 0 : W_ERROR_HAVE_NO_MEMORY(r->location);
4107 :
4108 0 : r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4109 0 : W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4110 0 : r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4111 0 : W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4112 0 : r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4113 0 : W_ERROR_HAVE_NO_MEMORY(r->datatype);
4114 0 : r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4115 0 : W_ERROR_HAVE_NO_MEMORY(r->parameters);
4116 :
4117 0 : r->attributes = info2->attributes;
4118 :
4119 0 : r->priority = info2->priority;
4120 0 : r->defaultpriority = info2->defaultpriority;
4121 0 : r->starttime = info2->starttime;
4122 0 : r->untiltime = info2->untiltime;
4123 0 : r->status = nt_printq_status(status.status);
4124 0 : r->cjobs = count;
4125 0 : r->averageppm = info2->averageppm;
4126 :
4127 0 : if (info2->devmode != NULL) {
4128 0 : result = copy_devicemode(mem_ctx,
4129 0 : info2->devmode,
4130 : &r->devmode);
4131 0 : if (!W_ERROR_IS_OK(result)) {
4132 0 : return result;
4133 : }
4134 0 : } else if (lp_default_devmode(snum)) {
4135 0 : result = spoolss_create_default_devmode(mem_ctx,
4136 0 : info2->printername,
4137 : &r->devmode);
4138 0 : if (!W_ERROR_IS_OK(result)) {
4139 0 : return result;
4140 : }
4141 : } else {
4142 0 : r->devmode = NULL;
4143 0 : DEBUG(8,("Returning NULL Devicemode!\n"));
4144 : }
4145 :
4146 0 : compose_devicemode_devicename(r->devmode, r->printername);
4147 :
4148 0 : r->secdesc = NULL;
4149 :
4150 0 : if (info2->secdesc != NULL) {
4151 : /* don't use talloc_steal() here unless you do a deep steal of all
4152 : the SEC_DESC members */
4153 :
4154 0 : r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4155 0 : if (r->secdesc == NULL) {
4156 0 : return WERR_NOT_ENOUGH_MEMORY;
4157 : }
4158 : }
4159 :
4160 0 : return WERR_OK;
4161 : }
4162 :
4163 : /********************************************************************
4164 : * construct_printer_info3
4165 : * fill a spoolss_PrinterInfo3 struct
4166 : ********************************************************************/
4167 :
4168 0 : static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4169 : const struct spoolss_PrinterInfo2 *info2,
4170 : const char *servername,
4171 : struct spoolss_PrinterInfo3 *r,
4172 : int snum)
4173 : {
4174 : /* These are the components of the SD we are returning. */
4175 :
4176 0 : if (info2->secdesc != NULL) {
4177 : /* don't use talloc_steal() here unless you do a deep steal of all
4178 : the SEC_DESC members */
4179 :
4180 0 : r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4181 0 : if (r->secdesc == NULL) {
4182 0 : return WERR_NOT_ENOUGH_MEMORY;
4183 : }
4184 : }
4185 :
4186 0 : return WERR_OK;
4187 : }
4188 :
4189 : /********************************************************************
4190 : * construct_printer_info4
4191 : * fill a spoolss_PrinterInfo4 struct
4192 : ********************************************************************/
4193 :
4194 0 : static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4195 : const struct spoolss_PrinterInfo2 *info2,
4196 : const char *servername,
4197 : struct spoolss_PrinterInfo4 *r,
4198 : int snum)
4199 : {
4200 : WERROR result;
4201 :
4202 0 : result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4203 0 : if (!W_ERROR_IS_OK(result)) {
4204 0 : return result;
4205 : }
4206 :
4207 0 : if (servername) {
4208 0 : r->servername = talloc_strdup(mem_ctx, servername);
4209 0 : W_ERROR_HAVE_NO_MEMORY(r->servername);
4210 : } else {
4211 0 : r->servername = NULL;
4212 : }
4213 :
4214 0 : r->attributes = info2->attributes;
4215 :
4216 0 : return WERR_OK;
4217 : }
4218 :
4219 : /********************************************************************
4220 : * construct_printer_info5
4221 : * fill a spoolss_PrinterInfo5 struct
4222 : ********************************************************************/
4223 :
4224 0 : static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4225 : const struct spoolss_PrinterInfo2 *info2,
4226 : const char *servername,
4227 : struct spoolss_PrinterInfo5 *r,
4228 : int snum)
4229 : {
4230 : WERROR result;
4231 :
4232 0 : result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4233 0 : if (!W_ERROR_IS_OK(result)) {
4234 0 : return result;
4235 : }
4236 :
4237 0 : r->portname = talloc_strdup(mem_ctx, info2->portname);
4238 0 : W_ERROR_HAVE_NO_MEMORY(r->portname);
4239 :
4240 0 : r->attributes = info2->attributes;
4241 :
4242 : /*
4243 : * These two are not used by NT+ according to MSDN. However the values
4244 : * we saw on Windows Server 2012 and 2016 are always set to the 0xafc8.
4245 : */
4246 0 : r->device_not_selected_timeout = 0xafc8; /* 45 sec */
4247 0 : r->transmission_retry_timeout = 0xafc8; /* 45 sec */
4248 :
4249 0 : return WERR_OK;
4250 : }
4251 :
4252 : /********************************************************************
4253 : * construct_printer_info_6
4254 : * fill a spoolss_PrinterInfo6 struct
4255 : ********************************************************************/
4256 :
4257 0 : static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4258 : struct messaging_context *msg_ctx,
4259 : const struct spoolss_PrinterInfo2 *info2,
4260 : const char *servername,
4261 : struct spoolss_PrinterInfo6 *r,
4262 : int snum)
4263 : {
4264 : print_status_struct status;
4265 :
4266 0 : print_queue_length(msg_ctx, snum, &status);
4267 :
4268 0 : r->status = nt_printq_status(status.status);
4269 :
4270 0 : return WERR_OK;
4271 : }
4272 :
4273 : /********************************************************************
4274 : * construct_printer_info7
4275 : * fill a spoolss_PrinterInfo7 struct
4276 : ********************************************************************/
4277 :
4278 0 : static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4279 : struct messaging_context *msg_ctx,
4280 : const char *servername,
4281 : struct spoolss_PrinterInfo7 *r,
4282 : int snum)
4283 : {
4284 0 : const struct loadparm_substitution *lp_sub =
4285 0 : loadparm_s3_global_substitution();
4286 : const struct auth_session_info *session_info;
4287 0 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
4288 : char *printer;
4289 : WERROR werr;
4290 0 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4291 0 : if (tmp_ctx == NULL) {
4292 0 : return WERR_NOT_ENOUGH_MEMORY;
4293 : }
4294 :
4295 0 : session_info = get_session_info_system();
4296 0 : SMB_ASSERT(session_info != NULL);
4297 :
4298 0 : printer = lp_servicename(tmp_ctx, lp_sub, snum);
4299 0 : if (printer == NULL) {
4300 0 : DEBUG(0, ("invalid printer snum %d\n", snum));
4301 0 : werr = WERR_INVALID_PARAMETER;
4302 0 : goto out_tmp_free;
4303 : }
4304 :
4305 0 : if (is_printer_published(tmp_ctx, session_info, msg_ctx,
4306 : servername, printer, &pinfo2)) {
4307 : struct GUID guid;
4308 : char *guidstr;
4309 0 : werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
4310 : printer, &guid);
4311 0 : if (!W_ERROR_IS_OK(werr)) {
4312 : /*
4313 : * If we do not have a GUID entry in the registry, then
4314 : * try to retrieve it from AD and store it now.
4315 : */
4316 0 : werr = nt_printer_guid_retrieve(tmp_ctx, printer,
4317 : &guid);
4318 0 : if (!W_ERROR_IS_OK(werr)) {
4319 0 : DBG_NOTICE("Failed to retrieve GUID for "
4320 : "printer [%s] from AD - %s\n",
4321 : printer,
4322 : win_errstr(werr));
4323 0 : if (W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND)) {
4324 : /*
4325 : * If we did not find it in AD, then it
4326 : * is unpublished and we should reflect
4327 : * this in the registry and return
4328 : * success.
4329 : */
4330 0 : DBG_WARNING("Unpublish printer [%s]\n",
4331 : pinfo2->sharename);
4332 0 : nt_printer_publish(tmp_ctx,
4333 : session_info,
4334 : msg_ctx,
4335 : pinfo2,
4336 : DSPRINT_UNPUBLISH);
4337 0 : r->guid = talloc_strdup(mem_ctx, "");
4338 0 : r->action = DSPRINT_UNPUBLISH;
4339 :
4340 0 : if (r->guid == NULL) {
4341 0 : werr = WERR_NOT_ENOUGH_MEMORY;
4342 : } else {
4343 0 : werr = WERR_OK;
4344 : }
4345 : }
4346 0 : goto out_tmp_free;
4347 : }
4348 :
4349 0 : werr = nt_printer_guid_store(msg_ctx, printer, guid);
4350 0 : if (!W_ERROR_IS_OK(werr)) {
4351 0 : DEBUG(3, ("failed to store printer %s guid\n",
4352 : printer));
4353 : }
4354 : }
4355 :
4356 : /* [MS-RPRN] section 2.2: must use curly-braced GUIDs */
4357 0 : guidstr = GUID_string2(mem_ctx, &guid);
4358 0 : if (guidstr == NULL) {
4359 0 : werr = WERR_NOT_ENOUGH_MEMORY;
4360 0 : goto out_tmp_free;
4361 : }
4362 : /* Convert GUID string to uppercase otherwise printers
4363 : * are pruned */
4364 0 : r->guid = talloc_strdup_upper(mem_ctx, guidstr);
4365 0 : r->action = DSPRINT_PUBLISH;
4366 :
4367 0 : TALLOC_FREE(guidstr);
4368 : } else {
4369 0 : r->guid = talloc_strdup(mem_ctx, "");
4370 0 : r->action = DSPRINT_UNPUBLISH;
4371 : }
4372 0 : if (r->guid == NULL) {
4373 0 : werr = WERR_NOT_ENOUGH_MEMORY;
4374 0 : goto out_tmp_free;
4375 : }
4376 :
4377 0 : werr = WERR_OK;
4378 0 : out_tmp_free:
4379 0 : talloc_free(tmp_ctx);
4380 0 : return werr;
4381 : }
4382 :
4383 : /********************************************************************
4384 : * construct_printer_info8
4385 : * fill a spoolss_PrinterInfo8 struct
4386 : ********************************************************************/
4387 :
4388 0 : static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4389 : const struct spoolss_PrinterInfo2 *info2,
4390 : const char *servername,
4391 : struct spoolss_DeviceModeInfo *r,
4392 : int snum)
4393 : {
4394 : WERROR result;
4395 : const char *printername;
4396 :
4397 0 : result = create_printername(mem_ctx, servername, info2->printername, &printername);
4398 0 : if (!W_ERROR_IS_OK(result)) {
4399 0 : return result;
4400 : }
4401 :
4402 0 : if (info2->devmode != NULL) {
4403 0 : result = copy_devicemode(mem_ctx,
4404 0 : info2->devmode,
4405 : &r->devmode);
4406 0 : if (!W_ERROR_IS_OK(result)) {
4407 0 : return result;
4408 : }
4409 0 : } else if (lp_default_devmode(snum)) {
4410 0 : result = spoolss_create_default_devmode(mem_ctx,
4411 0 : info2->printername,
4412 : &r->devmode);
4413 0 : if (!W_ERROR_IS_OK(result)) {
4414 0 : return result;
4415 : }
4416 : } else {
4417 0 : r->devmode = NULL;
4418 0 : DEBUG(8,("Returning NULL Devicemode!\n"));
4419 : }
4420 :
4421 0 : compose_devicemode_devicename(r->devmode, printername);
4422 :
4423 0 : return WERR_OK;
4424 : }
4425 :
4426 : /********************************************************************
4427 : Spoolss_enumprinters.
4428 : ********************************************************************/
4429 :
4430 0 : static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4431 : const struct auth_session_info *session_info,
4432 : struct messaging_context *msg_ctx,
4433 : const char *servername,
4434 : uint32_t level,
4435 : uint32_t flags,
4436 : union spoolss_PrinterInfo **info_p,
4437 : uint32_t *count_p)
4438 : {
4439 : int snum;
4440 : int n_services;
4441 0 : union spoolss_PrinterInfo *info = NULL;
4442 0 : uint32_t count = 0;
4443 0 : WERROR result = WERR_OK;
4444 0 : struct dcerpc_binding_handle *b = NULL;
4445 0 : TALLOC_CTX *tmp_ctx = NULL;
4446 :
4447 0 : tmp_ctx = talloc_new(mem_ctx);
4448 0 : if (!tmp_ctx) {
4449 0 : return WERR_NOT_ENOUGH_MEMORY;
4450 : }
4451 :
4452 : /*
4453 : * printer shares are updated on client enumeration. The background
4454 : * printer process updates printer_list.tdb at regular intervals.
4455 : */
4456 0 : become_root();
4457 0 : delete_and_reload_printers();
4458 0 : unbecome_root();
4459 :
4460 0 : n_services = lp_numservices();
4461 0 : *count_p = 0;
4462 0 : *info_p = NULL;
4463 :
4464 0 : for (snum = 0; snum < n_services; snum++) {
4465 :
4466 : const char *printer;
4467 : struct spoolss_PrinterInfo2 *info2;
4468 :
4469 0 : if (!snum_is_shared_printer(snum)) {
4470 0 : continue;
4471 : }
4472 :
4473 0 : printer = lp_const_servicename(snum);
4474 :
4475 0 : DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4476 : printer, snum));
4477 :
4478 0 : if (b == NULL) {
4479 0 : result = winreg_printer_binding_handle(tmp_ctx,
4480 : session_info,
4481 : msg_ctx,
4482 : &b);
4483 0 : if (!W_ERROR_IS_OK(result)) {
4484 0 : goto out;
4485 : }
4486 : }
4487 :
4488 0 : result = winreg_create_printer(tmp_ctx, b,
4489 : printer);
4490 0 : if (!W_ERROR_IS_OK(result)) {
4491 0 : goto out;
4492 : }
4493 :
4494 0 : info = talloc_realloc(tmp_ctx, info,
4495 : union spoolss_PrinterInfo,
4496 : count + 1);
4497 0 : if (!info) {
4498 0 : result = WERR_NOT_ENOUGH_MEMORY;
4499 0 : goto out;
4500 : }
4501 :
4502 0 : result = winreg_get_printer(tmp_ctx, b,
4503 : printer, &info2);
4504 0 : if (!W_ERROR_IS_OK(result)) {
4505 0 : goto out;
4506 : }
4507 :
4508 0 : switch (level) {
4509 0 : case 0:
4510 0 : result = construct_printer_info0(info, session_info,
4511 : msg_ctx, info2,
4512 : servername,
4513 0 : &info[count].info0, snum);
4514 0 : break;
4515 0 : case 1:
4516 0 : result = construct_printer_info1(info, info2, flags,
4517 : servername,
4518 0 : &info[count].info1, snum);
4519 0 : break;
4520 0 : case 2:
4521 0 : result = construct_printer_info2(info, msg_ctx, info2,
4522 : servername,
4523 0 : &info[count].info2, snum);
4524 0 : break;
4525 0 : case 4:
4526 0 : result = construct_printer_info4(info, info2,
4527 : servername,
4528 0 : &info[count].info4, snum);
4529 0 : break;
4530 0 : case 5:
4531 0 : result = construct_printer_info5(info, info2,
4532 : servername,
4533 0 : &info[count].info5, snum);
4534 0 : break;
4535 :
4536 0 : default:
4537 0 : result = WERR_INVALID_LEVEL;
4538 0 : goto out;
4539 : }
4540 :
4541 0 : if (!W_ERROR_IS_OK(result)) {
4542 0 : goto out;
4543 : }
4544 :
4545 0 : count++;
4546 : }
4547 :
4548 0 : out:
4549 0 : if (W_ERROR_IS_OK(result)) {
4550 0 : *info_p = talloc_move(mem_ctx, &info);
4551 0 : *count_p = count;
4552 : }
4553 :
4554 0 : talloc_free(tmp_ctx);
4555 :
4556 0 : return result;
4557 : }
4558 :
4559 : /********************************************************************
4560 : * handle enumeration of printers at level 0
4561 : ********************************************************************/
4562 :
4563 0 : static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4564 : const struct auth_session_info *session_info,
4565 : struct messaging_context *msg_ctx,
4566 : uint32_t flags,
4567 : const char *servername,
4568 : union spoolss_PrinterInfo **info,
4569 : uint32_t *count)
4570 : {
4571 0 : DEBUG(4,("enum_all_printers_info_0\n"));
4572 :
4573 0 : return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4574 : servername, 0, flags, info, count);
4575 : }
4576 :
4577 :
4578 : /********************************************************************
4579 : ********************************************************************/
4580 :
4581 0 : static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4582 : const struct auth_session_info *session_info,
4583 : struct messaging_context *msg_ctx,
4584 : const char *servername,
4585 : uint32_t flags,
4586 : union spoolss_PrinterInfo **info,
4587 : uint32_t *count)
4588 : {
4589 0 : DEBUG(4,("enum_all_printers_info_1\n"));
4590 :
4591 0 : return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4592 : servername, 1, flags, info, count);
4593 : }
4594 :
4595 : /********************************************************************
4596 : enum_all_printers_info_1_local.
4597 : *********************************************************************/
4598 :
4599 0 : static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4600 : const struct auth_session_info *session_info,
4601 : struct messaging_context *msg_ctx,
4602 : const char *servername,
4603 : union spoolss_PrinterInfo **info,
4604 : uint32_t *count)
4605 : {
4606 0 : DEBUG(4,("enum_all_printers_info_1_local\n"));
4607 :
4608 0 : return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4609 : servername, PRINTER_ENUM_ICON8, info, count);
4610 : }
4611 :
4612 : /********************************************************************
4613 : enum_all_printers_info_1_name.
4614 : *********************************************************************/
4615 :
4616 0 : static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4617 : const struct auth_session_info *session_info,
4618 : struct messaging_context *msg_ctx,
4619 : const char *servername,
4620 : union spoolss_PrinterInfo **info,
4621 : uint32_t *count)
4622 : {
4623 0 : const char *s = servername;
4624 :
4625 0 : DEBUG(4,("enum_all_printers_info_1_name\n"));
4626 :
4627 0 : if (servername != NULL &&
4628 0 : (servername[0] == '\\') && (servername[1] == '\\')) {
4629 0 : s = servername + 2;
4630 : }
4631 :
4632 0 : if (!is_myname_or_ipaddr(s)) {
4633 0 : return WERR_INVALID_NAME;
4634 : }
4635 :
4636 0 : return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4637 : servername, PRINTER_ENUM_ICON8, info, count);
4638 : }
4639 :
4640 : /********************************************************************
4641 : enum_all_printers_info_1_network.
4642 : *********************************************************************/
4643 :
4644 0 : static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4645 : const struct auth_session_info *session_info,
4646 : struct messaging_context *msg_ctx,
4647 : const char *servername,
4648 : union spoolss_PrinterInfo **info,
4649 : uint32_t *count)
4650 : {
4651 0 : const char *s = servername;
4652 :
4653 0 : DEBUG(4,("enum_all_printers_info_1_network\n"));
4654 :
4655 : /* If we respond to a enum_printers level 1 on our name with flags
4656 : set to PRINTER_ENUM_REMOTE with a list of printers then these
4657 : printers incorrectly appear in the APW browse list.
4658 : Specifically the printers for the server appear at the workgroup
4659 : level where all the other servers in the domain are
4660 : listed. Windows responds to this call with a
4661 : WERR_CAN_NOT_COMPLETE so we should do the same. */
4662 :
4663 0 : if (servername != NULL &&
4664 0 : (servername[0] == '\\') && (servername[1] == '\\')) {
4665 0 : s = servername + 2;
4666 : }
4667 :
4668 0 : if (is_myname_or_ipaddr(s)) {
4669 0 : return WERR_CAN_NOT_COMPLETE;
4670 : }
4671 :
4672 0 : return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4673 : servername, PRINTER_ENUM_NAME, info, count);
4674 : }
4675 :
4676 : /********************************************************************
4677 : * api_spoolss_enumprinters
4678 : *
4679 : * called from api_spoolss_enumprinters (see this to understand)
4680 : ********************************************************************/
4681 :
4682 0 : static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4683 : const struct auth_session_info *session_info,
4684 : struct messaging_context *msg_ctx,
4685 : const char *servername,
4686 : union spoolss_PrinterInfo **info,
4687 : uint32_t *count)
4688 : {
4689 0 : DEBUG(4,("enum_all_printers_info_2\n"));
4690 :
4691 0 : return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4692 : servername, 2, 0, info, count);
4693 : }
4694 :
4695 : /********************************************************************
4696 : * handle enumeration of printers at level 1
4697 : ********************************************************************/
4698 :
4699 0 : static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4700 : const struct auth_session_info *session_info,
4701 : struct messaging_context *msg_ctx,
4702 : uint32_t flags,
4703 : const char *servername,
4704 : union spoolss_PrinterInfo **info,
4705 : uint32_t *count)
4706 : {
4707 : /* Not all the flags are equals */
4708 :
4709 0 : if (flags & PRINTER_ENUM_LOCAL) {
4710 0 : return enum_all_printers_info_1_local(mem_ctx, session_info,
4711 : msg_ctx, servername, info, count);
4712 : }
4713 :
4714 0 : if (flags & PRINTER_ENUM_NAME) {
4715 0 : return enum_all_printers_info_1_name(mem_ctx, session_info,
4716 : msg_ctx, servername, info,
4717 : count);
4718 : }
4719 :
4720 0 : if (flags & PRINTER_ENUM_NETWORK) {
4721 0 : return enum_all_printers_info_1_network(mem_ctx, session_info,
4722 : msg_ctx, servername, info,
4723 : count);
4724 : }
4725 :
4726 0 : return WERR_OK; /* NT4sp5 does that */
4727 : }
4728 :
4729 : /********************************************************************
4730 : * handle enumeration of printers at level 2
4731 : ********************************************************************/
4732 :
4733 0 : static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4734 : const struct auth_session_info *session_info,
4735 : struct messaging_context *msg_ctx,
4736 : uint32_t flags,
4737 : const char *servername,
4738 : union spoolss_PrinterInfo **info,
4739 : uint32_t *count)
4740 : {
4741 0 : if (flags & PRINTER_ENUM_LOCAL) {
4742 :
4743 0 : return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4744 : servername,
4745 : info, count);
4746 : }
4747 :
4748 0 : if (flags & PRINTER_ENUM_NAME) {
4749 0 : if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4750 0 : return WERR_INVALID_NAME;
4751 : }
4752 :
4753 0 : return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4754 : servername,
4755 : info, count);
4756 : }
4757 :
4758 0 : if (flags & PRINTER_ENUM_REMOTE) {
4759 0 : return WERR_INVALID_LEVEL;
4760 : }
4761 :
4762 0 : return WERR_OK;
4763 : }
4764 :
4765 : /********************************************************************
4766 : * handle enumeration of printers at level 4
4767 : ********************************************************************/
4768 :
4769 0 : static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4770 : const struct auth_session_info *session_info,
4771 : struct messaging_context *msg_ctx,
4772 : uint32_t flags,
4773 : const char *servername,
4774 : union spoolss_PrinterInfo **info,
4775 : uint32_t *count)
4776 : {
4777 0 : DEBUG(4,("enum_all_printers_info_4\n"));
4778 :
4779 0 : return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4780 : servername, 4, flags, info, count);
4781 : }
4782 :
4783 :
4784 : /********************************************************************
4785 : * handle enumeration of printers at level 5
4786 : ********************************************************************/
4787 :
4788 0 : static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4789 : const struct auth_session_info *session_info,
4790 : struct messaging_context *msg_ctx,
4791 : uint32_t flags,
4792 : const char *servername,
4793 : union spoolss_PrinterInfo **info,
4794 : uint32_t *count)
4795 : {
4796 0 : DEBUG(4,("enum_all_printers_info_5\n"));
4797 :
4798 0 : return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4799 : servername, 5, flags, info, count);
4800 : }
4801 :
4802 : /****************************************************************
4803 : _spoolss_EnumPrinters
4804 : ****************************************************************/
4805 :
4806 0 : WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4807 : struct spoolss_EnumPrinters *r)
4808 : {
4809 0 : const struct auth_session_info *session_info = get_session_info_system();
4810 : WERROR result;
4811 :
4812 : /* that's an [in out] buffer */
4813 :
4814 0 : if (!r->in.buffer && (r->in.offered != 0)) {
4815 0 : return WERR_INVALID_PARAMETER;
4816 : }
4817 :
4818 0 : DEBUG(4,("_spoolss_EnumPrinters\n"));
4819 :
4820 0 : *r->out.needed = 0;
4821 0 : *r->out.count = 0;
4822 0 : *r->out.info = NULL;
4823 :
4824 : /*
4825 : * Level 1:
4826 : * flags==PRINTER_ENUM_NAME
4827 : * if name=="" then enumerates all printers
4828 : * if name!="" then enumerate the printer
4829 : * flags==PRINTER_ENUM_REMOTE
4830 : * name is NULL, enumerate printers
4831 : * Level 2: name!="" enumerates printers, name can't be NULL
4832 : * Level 3: doesn't exist
4833 : * Level 4: does a local registry lookup
4834 : * Level 5: same as Level 2
4835 : */
4836 :
4837 0 : if (r->in.server && r->in.server[0] == '\0') {
4838 0 : r->in.server = NULL;
4839 : }
4840 :
4841 0 : switch (r->in.level) {
4842 0 : case 0:
4843 0 : result = enumprinters_level0(p->mem_ctx, session_info,
4844 : p->msg_ctx, r->in.flags,
4845 : r->in.server,
4846 : r->out.info, r->out.count);
4847 0 : break;
4848 0 : case 1:
4849 0 : result = enumprinters_level1(p->mem_ctx, session_info,
4850 : p->msg_ctx, r->in.flags,
4851 : r->in.server,
4852 : r->out.info, r->out.count);
4853 0 : break;
4854 0 : case 2:
4855 0 : result = enumprinters_level2(p->mem_ctx, session_info,
4856 : p->msg_ctx, r->in.flags,
4857 : r->in.server,
4858 : r->out.info, r->out.count);
4859 0 : break;
4860 0 : case 4:
4861 0 : result = enumprinters_level4(p->mem_ctx, session_info,
4862 : p->msg_ctx, r->in.flags,
4863 : r->in.server,
4864 : r->out.info, r->out.count);
4865 0 : break;
4866 0 : case 5:
4867 0 : result = enumprinters_level5(p->mem_ctx, session_info,
4868 : p->msg_ctx, r->in.flags,
4869 : r->in.server,
4870 : r->out.info, r->out.count);
4871 0 : break;
4872 0 : default:
4873 0 : return WERR_INVALID_LEVEL;
4874 : }
4875 :
4876 0 : if (!W_ERROR_IS_OK(result)) {
4877 0 : return result;
4878 : }
4879 :
4880 0 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4881 : spoolss_EnumPrinters,
4882 : *r->out.info, r->in.level,
4883 : *r->out.count);
4884 0 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4885 0 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4886 :
4887 0 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4888 : }
4889 :
4890 : /****************************************************************
4891 : _spoolss_GetPrinter
4892 : ****************************************************************/
4893 :
4894 0 : WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4895 : struct spoolss_GetPrinter *r)
4896 : {
4897 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4898 0 : struct spoolss_PrinterInfo2 *info2 = NULL;
4899 0 : WERROR result = WERR_OK;
4900 : int snum;
4901 :
4902 : /* that's an [in out] buffer */
4903 :
4904 0 : if (!r->in.buffer && (r->in.offered != 0)) {
4905 0 : result = WERR_INVALID_PARAMETER;
4906 0 : goto err_info_free;
4907 : }
4908 :
4909 0 : *r->out.needed = 0;
4910 :
4911 0 : if (Printer == NULL) {
4912 0 : result = WERR_INVALID_HANDLE;
4913 0 : goto err_info_free;
4914 : }
4915 :
4916 0 : if (Printer->printer_type == SPLHND_SERVER) {
4917 :
4918 : struct dcerpc_binding_handle *b;
4919 :
4920 0 : if (r->in.level != 3) {
4921 0 : result = WERR_INVALID_LEVEL;
4922 0 : goto err_info_free;
4923 : }
4924 :
4925 0 : result = winreg_printer_binding_handle(p->mem_ctx,
4926 : get_session_info_system(),
4927 : p->msg_ctx,
4928 : &b);
4929 0 : if (!W_ERROR_IS_OK(result)) {
4930 0 : goto err_info_free;
4931 : }
4932 :
4933 0 : result = winreg_get_printserver_secdesc(p->mem_ctx,
4934 : b,
4935 0 : &r->out.info->info3.secdesc);
4936 0 : if (!W_ERROR_IS_OK(result)) {
4937 0 : goto err_info_free;
4938 : }
4939 :
4940 0 : goto done;
4941 : }
4942 :
4943 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4944 0 : result = WERR_INVALID_HANDLE;
4945 0 : goto err_info_free;
4946 : }
4947 :
4948 0 : result = winreg_get_printer_internal(p->mem_ctx,
4949 : get_session_info_system(),
4950 : p->msg_ctx,
4951 : lp_const_servicename(snum),
4952 : &info2);
4953 0 : if (!W_ERROR_IS_OK(result)) {
4954 0 : goto err_info_free;
4955 : }
4956 :
4957 0 : switch (r->in.level) {
4958 0 : case 0:
4959 0 : result = construct_printer_info0(p->mem_ctx,
4960 : get_session_info_system(),
4961 : p->msg_ctx,
4962 : info2,
4963 : Printer->servername,
4964 0 : &r->out.info->info0,
4965 : snum);
4966 0 : break;
4967 0 : case 1:
4968 0 : result = construct_printer_info1(p->mem_ctx, info2,
4969 : PRINTER_ENUM_ICON8,
4970 : Printer->servername,
4971 0 : &r->out.info->info1, snum);
4972 0 : break;
4973 0 : case 2:
4974 0 : result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4975 : Printer->servername,
4976 0 : &r->out.info->info2, snum);
4977 0 : break;
4978 0 : case 3:
4979 0 : result = construct_printer_info3(p->mem_ctx, info2,
4980 : Printer->servername,
4981 0 : &r->out.info->info3, snum);
4982 0 : break;
4983 0 : case 4:
4984 0 : result = construct_printer_info4(p->mem_ctx, info2,
4985 : Printer->servername,
4986 0 : &r->out.info->info4, snum);
4987 0 : break;
4988 0 : case 5:
4989 0 : result = construct_printer_info5(p->mem_ctx, info2,
4990 : Printer->servername,
4991 0 : &r->out.info->info5, snum);
4992 0 : break;
4993 0 : case 6:
4994 0 : result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4995 : Printer->servername,
4996 0 : &r->out.info->info6, snum);
4997 0 : break;
4998 0 : case 7:
4999 0 : result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
5000 : Printer->servername,
5001 0 : &r->out.info->info7, snum);
5002 0 : break;
5003 0 : case 8:
5004 0 : result = construct_printer_info8(p->mem_ctx, info2,
5005 : Printer->servername,
5006 0 : &r->out.info->info8, snum);
5007 0 : break;
5008 0 : default:
5009 0 : result = WERR_INVALID_LEVEL;
5010 0 : break;
5011 : }
5012 0 : TALLOC_FREE(info2);
5013 :
5014 0 : if (!W_ERROR_IS_OK(result)) {
5015 0 : DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
5016 : r->in.level, win_errstr(result)));
5017 0 : goto err_info_free;
5018 : }
5019 0 : done:
5020 0 : *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
5021 : r->out.info, r->in.level);
5022 0 : r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5023 :
5024 0 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5025 :
5026 0 : err_info_free:
5027 0 : TALLOC_FREE(r->out.info);
5028 0 : return result;
5029 : }
5030 :
5031 : /********************************************************************
5032 : ********************************************************************/
5033 :
5034 : #define FILL_DRIVER_STRING(mem_ctx, in, out) \
5035 : do { \
5036 : if (in && strlen(in)) { \
5037 : out = talloc_strdup(mem_ctx, in); \
5038 : } else { \
5039 : out = talloc_strdup(mem_ctx, ""); \
5040 : } \
5041 : W_ERROR_HAVE_NO_MEMORY(out); \
5042 : } while (0);
5043 :
5044 : #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
5045 : do { \
5046 : if (in && strlen(in)) { \
5047 : out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
5048 : } else { \
5049 : out = talloc_strdup(mem_ctx, ""); \
5050 : } \
5051 : W_ERROR_HAVE_NO_MEMORY(out); \
5052 : } while (0);
5053 :
5054 0 : static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
5055 : const char **string_array,
5056 : const char ***presult,
5057 : const char *cservername,
5058 : const char *arch,
5059 : int version)
5060 : {
5061 : size_t i;
5062 0 : size_t num_strings = 0;
5063 0 : const char **array = NULL;
5064 :
5065 0 : if (string_array == NULL) {
5066 0 : return WERR_INVALID_PARAMETER;
5067 : }
5068 :
5069 0 : for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
5070 0 : const char *str = NULL;
5071 :
5072 0 : if (cservername == NULL || arch == NULL) {
5073 0 : FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
5074 : } else {
5075 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
5076 : }
5077 :
5078 0 : if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
5079 0 : TALLOC_FREE(array);
5080 0 : return WERR_NOT_ENOUGH_MEMORY;
5081 : }
5082 : }
5083 :
5084 0 : if (i > 0) {
5085 0 : ADD_TO_ARRAY(mem_ctx, const char *, NULL,
5086 : &array, &num_strings);
5087 : }
5088 :
5089 0 : if (presult != NULL) {
5090 0 : *presult = array;
5091 : } else {
5092 0 : talloc_free(array);
5093 : }
5094 :
5095 0 : return WERR_OK;
5096 : }
5097 :
5098 : /********************************************************************
5099 : * fill a spoolss_DriverInfo1 struct
5100 : ********************************************************************/
5101 :
5102 0 : static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
5103 : struct spoolss_DriverInfo1 *r,
5104 : const struct spoolss_DriverInfo8 *driver,
5105 : const char *servername)
5106 : {
5107 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5108 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5109 :
5110 0 : return WERR_OK;
5111 : }
5112 :
5113 : /********************************************************************
5114 : * fill a spoolss_DriverInfo2 struct
5115 : ********************************************************************/
5116 :
5117 0 : static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
5118 : struct spoolss_DriverInfo2 *r,
5119 : const struct spoolss_DriverInfo8 *driver,
5120 : const char *servername)
5121 :
5122 : {
5123 0 : const char *cservername = canon_servername(servername);
5124 :
5125 0 : r->version = driver->version;
5126 :
5127 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5128 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5129 0 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5130 0 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5131 :
5132 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5133 : driver->architecture,
5134 : driver->version,
5135 : driver->driver_path,
5136 : r->driver_path);
5137 :
5138 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5139 : driver->architecture,
5140 : driver->version,
5141 : driver->data_file,
5142 : r->data_file);
5143 :
5144 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5145 : driver->architecture,
5146 : driver->version,
5147 : driver->config_file,
5148 : r->config_file);
5149 :
5150 0 : return WERR_OK;
5151 : }
5152 :
5153 : /********************************************************************
5154 : * fill a spoolss_DriverInfo3 struct
5155 : ********************************************************************/
5156 :
5157 0 : static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
5158 : struct spoolss_DriverInfo3 *r,
5159 : const struct spoolss_DriverInfo8 *driver,
5160 : const char *servername)
5161 : {
5162 0 : const char *cservername = canon_servername(servername);
5163 :
5164 0 : r->version = driver->version;
5165 :
5166 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5167 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5168 0 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5169 0 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5170 :
5171 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5172 : driver->architecture,
5173 : driver->version,
5174 : driver->driver_path,
5175 : r->driver_path);
5176 :
5177 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5178 : driver->architecture,
5179 : driver->version,
5180 : driver->data_file,
5181 : r->data_file);
5182 :
5183 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5184 : driver->architecture,
5185 : driver->version,
5186 : driver->config_file,
5187 : r->config_file);
5188 :
5189 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5190 : driver->architecture,
5191 : driver->version,
5192 : driver->help_file,
5193 : r->help_file);
5194 :
5195 0 : FILL_DRIVER_STRING(mem_ctx,
5196 : driver->monitor_name,
5197 : r->monitor_name);
5198 :
5199 0 : FILL_DRIVER_STRING(mem_ctx,
5200 : driver->default_datatype,
5201 : r->default_datatype);
5202 :
5203 0 : return string_array_from_driver_info(mem_ctx,
5204 0 : driver->dependent_files,
5205 : &r->dependent_files,
5206 : cservername,
5207 0 : driver->architecture,
5208 0 : driver->version);
5209 : }
5210 :
5211 : /********************************************************************
5212 : * fill a spoolss_DriverInfo4 struct
5213 : ********************************************************************/
5214 :
5215 0 : static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5216 : struct spoolss_DriverInfo4 *r,
5217 : const struct spoolss_DriverInfo8 *driver,
5218 : const char *servername)
5219 : {
5220 0 : const char *cservername = canon_servername(servername);
5221 : WERROR result;
5222 :
5223 0 : r->version = driver->version;
5224 :
5225 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5226 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5227 0 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5228 0 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5229 :
5230 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5231 : driver->architecture,
5232 : driver->version,
5233 : driver->driver_path,
5234 : r->driver_path);
5235 :
5236 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5237 : driver->architecture,
5238 : driver->version,
5239 : driver->data_file,
5240 : r->data_file);
5241 :
5242 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5243 : driver->architecture,
5244 : driver->version,
5245 : driver->config_file,
5246 : r->config_file);
5247 :
5248 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5249 : driver->architecture,
5250 : driver->version,
5251 : driver->help_file,
5252 : r->help_file);
5253 :
5254 0 : result = string_array_from_driver_info(mem_ctx,
5255 0 : driver->dependent_files,
5256 : &r->dependent_files,
5257 : cservername,
5258 0 : driver->architecture,
5259 0 : driver->version);
5260 0 : if (!W_ERROR_IS_OK(result)) {
5261 0 : return result;
5262 : }
5263 :
5264 0 : FILL_DRIVER_STRING(mem_ctx,
5265 : driver->monitor_name,
5266 : r->monitor_name);
5267 :
5268 0 : FILL_DRIVER_STRING(mem_ctx,
5269 : driver->default_datatype,
5270 : r->default_datatype);
5271 :
5272 :
5273 0 : result = string_array_from_driver_info(mem_ctx,
5274 0 : driver->previous_names,
5275 : &r->previous_names,
5276 : NULL, NULL, 0);
5277 :
5278 0 : return result;
5279 : }
5280 :
5281 : /********************************************************************
5282 : * fill a spoolss_DriverInfo5 struct
5283 : ********************************************************************/
5284 :
5285 0 : static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5286 : struct spoolss_DriverInfo5 *r,
5287 : const struct spoolss_DriverInfo8 *driver,
5288 : const char *servername)
5289 : {
5290 0 : const char *cservername = canon_servername(servername);
5291 :
5292 0 : r->version = driver->version;
5293 :
5294 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5295 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5296 0 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5297 0 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5298 :
5299 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5300 : driver->architecture,
5301 : driver->version,
5302 : driver->driver_path,
5303 : r->driver_path);
5304 :
5305 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5306 : driver->architecture,
5307 : driver->version,
5308 : driver->data_file,
5309 : r->data_file);
5310 :
5311 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5312 : driver->architecture,
5313 : driver->version,
5314 : driver->config_file,
5315 : r->config_file);
5316 :
5317 0 : r->driver_attributes = 0;
5318 0 : r->config_version = 0;
5319 0 : r->driver_version = 0;
5320 :
5321 0 : return WERR_OK;
5322 : }
5323 : /********************************************************************
5324 : * fill a spoolss_DriverInfo6 struct
5325 : ********************************************************************/
5326 :
5327 0 : static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5328 : struct spoolss_DriverInfo6 *r,
5329 : const struct spoolss_DriverInfo8 *driver,
5330 : const char *servername)
5331 : {
5332 0 : const char *cservername = canon_servername(servername);
5333 : WERROR result;
5334 :
5335 0 : r->version = driver->version;
5336 :
5337 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5338 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5339 0 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5340 0 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5341 :
5342 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5343 : driver->architecture,
5344 : driver->version,
5345 : driver->driver_path,
5346 : r->driver_path);
5347 :
5348 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5349 : driver->architecture,
5350 : driver->version,
5351 : driver->data_file,
5352 : r->data_file);
5353 :
5354 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5355 : driver->architecture,
5356 : driver->version,
5357 : driver->config_file,
5358 : r->config_file);
5359 :
5360 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5361 : driver->architecture,
5362 : driver->version,
5363 : driver->help_file,
5364 : r->help_file);
5365 :
5366 0 : FILL_DRIVER_STRING(mem_ctx,
5367 : driver->monitor_name,
5368 : r->monitor_name);
5369 :
5370 0 : FILL_DRIVER_STRING(mem_ctx,
5371 : driver->default_datatype,
5372 : r->default_datatype);
5373 :
5374 0 : result = string_array_from_driver_info(mem_ctx,
5375 0 : driver->dependent_files,
5376 : &r->dependent_files,
5377 : cservername,
5378 0 : driver->architecture,
5379 0 : driver->version);
5380 0 : if (!W_ERROR_IS_OK(result)) {
5381 0 : return result;
5382 : }
5383 :
5384 0 : result = string_array_from_driver_info(mem_ctx,
5385 0 : driver->previous_names,
5386 : &r->previous_names,
5387 : NULL, NULL, 0);
5388 0 : if (!W_ERROR_IS_OK(result)) {
5389 0 : return result;
5390 : }
5391 :
5392 0 : r->driver_date = driver->driver_date;
5393 0 : r->driver_version = driver->driver_version;
5394 :
5395 0 : FILL_DRIVER_STRING(mem_ctx,
5396 : driver->manufacturer_name,
5397 : r->manufacturer_name);
5398 0 : FILL_DRIVER_STRING(mem_ctx,
5399 : driver->manufacturer_url,
5400 : r->manufacturer_url);
5401 0 : FILL_DRIVER_STRING(mem_ctx,
5402 : driver->hardware_id,
5403 : r->hardware_id);
5404 0 : FILL_DRIVER_STRING(mem_ctx,
5405 : driver->provider,
5406 : r->provider);
5407 :
5408 0 : return WERR_OK;
5409 : }
5410 :
5411 : /********************************************************************
5412 : * fill a spoolss_DriverInfo8 struct
5413 : ********************************************************************/
5414 :
5415 0 : static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5416 : struct spoolss_DriverInfo8 *r,
5417 : const struct spoolss_DriverInfo8 *driver,
5418 : const char *servername)
5419 : {
5420 0 : const char *cservername = canon_servername(servername);
5421 : WERROR result;
5422 :
5423 0 : r->version = driver->version;
5424 :
5425 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5426 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5427 0 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5428 0 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5429 :
5430 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5431 : driver->architecture,
5432 : driver->version,
5433 : driver->driver_path,
5434 : r->driver_path);
5435 :
5436 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5437 : driver->architecture,
5438 : driver->version,
5439 : driver->data_file,
5440 : r->data_file);
5441 :
5442 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5443 : driver->architecture,
5444 : driver->version,
5445 : driver->config_file,
5446 : r->config_file);
5447 :
5448 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5449 : driver->architecture,
5450 : driver->version,
5451 : driver->help_file,
5452 : r->help_file);
5453 :
5454 0 : FILL_DRIVER_STRING(mem_ctx,
5455 : driver->monitor_name,
5456 : r->monitor_name);
5457 :
5458 0 : FILL_DRIVER_STRING(mem_ctx,
5459 : driver->default_datatype,
5460 : r->default_datatype);
5461 :
5462 0 : result = string_array_from_driver_info(mem_ctx,
5463 0 : driver->dependent_files,
5464 : &r->dependent_files,
5465 : cservername,
5466 0 : driver->architecture,
5467 0 : driver->version);
5468 0 : if (!W_ERROR_IS_OK(result)) {
5469 0 : return result;
5470 : }
5471 :
5472 0 : result = string_array_from_driver_info(mem_ctx,
5473 0 : driver->previous_names,
5474 : &r->previous_names,
5475 : NULL, NULL, 0);
5476 0 : if (!W_ERROR_IS_OK(result)) {
5477 0 : return result;
5478 : }
5479 :
5480 0 : r->driver_date = driver->driver_date;
5481 0 : r->driver_version = driver->driver_version;
5482 :
5483 0 : FILL_DRIVER_STRING(mem_ctx,
5484 : driver->manufacturer_name,
5485 : r->manufacturer_name);
5486 0 : FILL_DRIVER_STRING(mem_ctx,
5487 : driver->manufacturer_url,
5488 : r->manufacturer_url);
5489 0 : FILL_DRIVER_STRING(mem_ctx,
5490 : driver->hardware_id,
5491 : r->hardware_id);
5492 0 : FILL_DRIVER_STRING(mem_ctx,
5493 : driver->provider,
5494 : r->provider);
5495 :
5496 0 : FILL_DRIVER_STRING(mem_ctx,
5497 : driver->print_processor,
5498 : r->print_processor);
5499 0 : FILL_DRIVER_STRING(mem_ctx,
5500 : driver->vendor_setup,
5501 : r->vendor_setup);
5502 :
5503 0 : result = string_array_from_driver_info(mem_ctx,
5504 0 : driver->color_profiles,
5505 : &r->color_profiles,
5506 : NULL, NULL, 0);
5507 0 : if (!W_ERROR_IS_OK(result)) {
5508 0 : return result;
5509 : }
5510 :
5511 0 : FILL_DRIVER_STRING(mem_ctx,
5512 : driver->inf_path,
5513 : r->inf_path);
5514 :
5515 0 : r->printer_driver_attributes = driver->printer_driver_attributes;
5516 :
5517 0 : result = string_array_from_driver_info(mem_ctx,
5518 0 : driver->core_driver_dependencies,
5519 : &r->core_driver_dependencies,
5520 : NULL, NULL, 0);
5521 0 : if (!W_ERROR_IS_OK(result)) {
5522 0 : return result;
5523 : }
5524 :
5525 0 : r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5526 0 : r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5527 :
5528 0 : return WERR_OK;
5529 : }
5530 :
5531 : #if 0 /* disabled until marshalling issues are resolved - gd */
5532 : /********************************************************************
5533 : ********************************************************************/
5534 :
5535 : static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5536 : struct spoolss_DriverFileInfo *r,
5537 : const char *cservername,
5538 : const char *file_name,
5539 : enum spoolss_DriverFileType file_type,
5540 : uint32_t file_version)
5541 : {
5542 : r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5543 : cservername, file_name);
5544 : W_ERROR_HAVE_NO_MEMORY(r->file_name);
5545 : r->file_type = file_type;
5546 : r->file_version = file_version;
5547 :
5548 : return WERR_OK;
5549 : }
5550 :
5551 : /********************************************************************
5552 : ********************************************************************/
5553 :
5554 : static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5555 : const struct spoolss_DriverInfo8 *driver,
5556 : const char *cservername,
5557 : struct spoolss_DriverFileInfo **info_p,
5558 : uint32_t *count_p)
5559 : {
5560 : struct spoolss_DriverFileInfo *info = NULL;
5561 : uint32_t count = 0;
5562 : WERROR result;
5563 : uint32_t i;
5564 :
5565 : *info_p = NULL;
5566 : *count_p = 0;
5567 :
5568 : if (strlen(driver->driver_path)) {
5569 : info = talloc_realloc(mem_ctx, info,
5570 : struct spoolss_DriverFileInfo,
5571 : count + 1);
5572 : W_ERROR_HAVE_NO_MEMORY(info);
5573 : result = fill_spoolss_DriverFileInfo(info,
5574 : &info[count],
5575 : cservername,
5576 : driver->driver_path,
5577 : SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5578 : 0);
5579 : W_ERROR_NOT_OK_RETURN(result);
5580 : count++;
5581 : }
5582 :
5583 : if (strlen(driver->config_file)) {
5584 : info = talloc_realloc(mem_ctx, info,
5585 : struct spoolss_DriverFileInfo,
5586 : count + 1);
5587 : W_ERROR_HAVE_NO_MEMORY(info);
5588 : result = fill_spoolss_DriverFileInfo(info,
5589 : &info[count],
5590 : cservername,
5591 : driver->config_file,
5592 : SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5593 : 0);
5594 : W_ERROR_NOT_OK_RETURN(result);
5595 : count++;
5596 : }
5597 :
5598 : if (strlen(driver->data_file)) {
5599 : info = talloc_realloc(mem_ctx, info,
5600 : struct spoolss_DriverFileInfo,
5601 : count + 1);
5602 : W_ERROR_HAVE_NO_MEMORY(info);
5603 : result = fill_spoolss_DriverFileInfo(info,
5604 : &info[count],
5605 : cservername,
5606 : driver->data_file,
5607 : SPOOLSS_DRIVER_FILE_TYPE_DATA,
5608 : 0);
5609 : W_ERROR_NOT_OK_RETURN(result);
5610 : count++;
5611 : }
5612 :
5613 : if (strlen(driver->help_file)) {
5614 : info = talloc_realloc(mem_ctx, info,
5615 : struct spoolss_DriverFileInfo,
5616 : count + 1);
5617 : W_ERROR_HAVE_NO_MEMORY(info);
5618 : result = fill_spoolss_DriverFileInfo(info,
5619 : &info[count],
5620 : cservername,
5621 : driver->help_file,
5622 : SPOOLSS_DRIVER_FILE_TYPE_HELP,
5623 : 0);
5624 : W_ERROR_NOT_OK_RETURN(result);
5625 : count++;
5626 : }
5627 :
5628 : for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5629 : info = talloc_realloc(mem_ctx, info,
5630 : struct spoolss_DriverFileInfo,
5631 : count + 1);
5632 : W_ERROR_HAVE_NO_MEMORY(info);
5633 : result = fill_spoolss_DriverFileInfo(info,
5634 : &info[count],
5635 : cservername,
5636 : driver->dependent_files[i],
5637 : SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5638 : 0);
5639 : W_ERROR_NOT_OK_RETURN(result);
5640 : count++;
5641 : }
5642 :
5643 : *info_p = info;
5644 : *count_p = count;
5645 :
5646 : return WERR_OK;
5647 : }
5648 :
5649 : /********************************************************************
5650 : * fill a spoolss_DriverInfo101 struct
5651 : ********************************************************************/
5652 :
5653 : static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5654 : struct spoolss_DriverInfo101 *r,
5655 : const struct spoolss_DriverInfo8 *driver,
5656 : const char *servername)
5657 : {
5658 : const char *cservername = canon_servername(servername);
5659 : WERROR result;
5660 :
5661 : r->version = driver->version;
5662 :
5663 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5664 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5665 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5666 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5667 :
5668 : result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5669 : cservername,
5670 : &r->file_info,
5671 : &r->file_count);
5672 : if (!W_ERROR_IS_OK(result)) {
5673 : return result;
5674 : }
5675 :
5676 : FILL_DRIVER_STRING(mem_ctx,
5677 : driver->monitor_name,
5678 : r->monitor_name);
5679 :
5680 : FILL_DRIVER_STRING(mem_ctx,
5681 : driver->default_datatype,
5682 : r->default_datatype);
5683 :
5684 : result = string_array_from_driver_info(mem_ctx,
5685 : driver->previous_names,
5686 : &r->previous_names,
5687 : NULL, NULL, 0);
5688 : if (!W_ERROR_IS_OK(result)) {
5689 : return result;
5690 : }
5691 :
5692 : r->driver_date = driver->driver_date;
5693 : r->driver_version = driver->driver_version;
5694 :
5695 : FILL_DRIVER_STRING(mem_ctx,
5696 : driver->manufacturer_name,
5697 : r->manufacturer_name);
5698 : FILL_DRIVER_STRING(mem_ctx,
5699 : driver->manufacturer_url,
5700 : r->manufacturer_url);
5701 : FILL_DRIVER_STRING(mem_ctx,
5702 : driver->hardware_id,
5703 : r->hardware_id);
5704 : FILL_DRIVER_STRING(mem_ctx,
5705 : driver->provider,
5706 : r->provider);
5707 :
5708 : return WERR_OK;
5709 : }
5710 : #endif
5711 : /********************************************************************
5712 : ********************************************************************/
5713 :
5714 0 : static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5715 : const struct auth_session_info *session_info,
5716 : struct messaging_context *msg_ctx,
5717 : uint32_t level,
5718 : union spoolss_DriverInfo *r,
5719 : int snum,
5720 : const char *servername,
5721 : const char *architecture,
5722 : uint32_t version)
5723 : {
5724 0 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5725 : struct spoolss_DriverInfo8 *driver;
5726 : WERROR result;
5727 : struct dcerpc_binding_handle *b;
5728 0 : TALLOC_CTX *tmp_ctx = NULL;
5729 :
5730 0 : if (level == 101) {
5731 0 : return WERR_INVALID_LEVEL;
5732 : }
5733 :
5734 0 : tmp_ctx = talloc_new(mem_ctx);
5735 0 : if (!tmp_ctx) {
5736 0 : return WERR_NOT_ENOUGH_MEMORY;
5737 : }
5738 :
5739 0 : result = winreg_printer_binding_handle(tmp_ctx,
5740 : session_info,
5741 : msg_ctx,
5742 : &b);
5743 0 : if (!W_ERROR_IS_OK(result)) {
5744 0 : goto done;
5745 : }
5746 :
5747 0 : result = winreg_get_printer(tmp_ctx, b,
5748 : lp_const_servicename(snum),
5749 : &pinfo2);
5750 0 : if (!W_ERROR_IS_OK(result)) {
5751 0 : DBG_ERR("Failed to get printer info2 for [%s]: %s\n",
5752 : lp_const_servicename(snum), win_errstr(result));
5753 0 : result = WERR_INVALID_PRINTER_NAME;
5754 0 : goto done;
5755 : }
5756 :
5757 0 : if (pinfo2->drivername == NULL || pinfo2->drivername[0] == '\0') {
5758 0 : result = WERR_UNKNOWN_PRINTER_DRIVER;
5759 0 : goto done;
5760 : }
5761 :
5762 0 : DBG_INFO("Construct printer driver [%s] for [%s]\n",
5763 : pinfo2->drivername,
5764 : pinfo2->sharename);
5765 :
5766 0 : result = winreg_get_driver(tmp_ctx, b,
5767 : architecture,
5768 0 : pinfo2->drivername, version, &driver);
5769 :
5770 0 : DBG_INFO("winreg_get_driver() status: %s\n",
5771 : win_errstr(result));
5772 :
5773 0 : if (!W_ERROR_IS_OK(result)) {
5774 : /*
5775 : * Is this a W2k client ?
5776 : */
5777 :
5778 0 : if (version < 3) {
5779 0 : result = WERR_UNKNOWN_PRINTER_DRIVER;
5780 0 : goto done;
5781 : }
5782 :
5783 : /* Yes - try again with a WinNT driver. */
5784 0 : version = 2;
5785 0 : result = winreg_get_driver(tmp_ctx, b,
5786 : architecture,
5787 0 : pinfo2->drivername,
5788 : version, &driver);
5789 0 : DEBUG(8,("construct_printer_driver_level: status: %s\n",
5790 : win_errstr(result)));
5791 0 : if (!W_ERROR_IS_OK(result)) {
5792 0 : result = WERR_UNKNOWN_PRINTER_DRIVER;
5793 0 : goto done;
5794 : }
5795 : }
5796 :
5797 : /* these are allocated on mem_ctx and not tmp_ctx because they are
5798 : * the 'return value' and need to utlive this call */
5799 0 : switch (level) {
5800 0 : case 1:
5801 0 : result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5802 0 : break;
5803 0 : case 2:
5804 0 : result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5805 0 : break;
5806 0 : case 3:
5807 0 : result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5808 0 : break;
5809 0 : case 4:
5810 0 : result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5811 0 : break;
5812 0 : case 5:
5813 0 : result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5814 0 : break;
5815 0 : case 6:
5816 0 : result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5817 0 : break;
5818 0 : case 8:
5819 0 : result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5820 0 : break;
5821 : #if 0 /* disabled until marshalling issues are resolved - gd */
5822 : case 101:
5823 : result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5824 : break;
5825 : #endif
5826 0 : default:
5827 0 : result = WERR_INVALID_LEVEL;
5828 0 : break;
5829 : }
5830 :
5831 0 : done:
5832 0 : talloc_free(tmp_ctx);
5833 0 : return result;
5834 : }
5835 :
5836 : /****************************************************************
5837 : _spoolss_GetPrinterDriver2
5838 : ****************************************************************/
5839 :
5840 0 : WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5841 : struct spoolss_GetPrinterDriver2 *r)
5842 : {
5843 : struct printer_handle *printer;
5844 : WERROR result;
5845 0 : uint32_t version = r->in.client_major_version;
5846 :
5847 : int snum;
5848 :
5849 : /* that's an [in out] buffer */
5850 :
5851 0 : if (!r->in.buffer && (r->in.offered != 0)) {
5852 0 : result = WERR_INVALID_PARAMETER;
5853 0 : goto err_info_free;
5854 : }
5855 :
5856 0 : DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5857 :
5858 0 : if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5859 0 : DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5860 0 : result = WERR_INVALID_PRINTER_NAME;
5861 0 : goto err_info_free;
5862 : }
5863 :
5864 0 : *r->out.needed = 0;
5865 0 : *r->out.server_major_version = 0;
5866 0 : *r->out.server_minor_version = 0;
5867 :
5868 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5869 0 : result = WERR_INVALID_HANDLE;
5870 0 : goto err_info_free;
5871 : }
5872 :
5873 0 : if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
5874 0 : DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
5875 : "downgrading to v3\n"));
5876 0 : version = SPOOLSS_DRIVER_VERSION_200X;
5877 : }
5878 :
5879 0 : result = construct_printer_driver_info_level(p->mem_ctx,
5880 : get_session_info_system(),
5881 : p->msg_ctx,
5882 : r->in.level, r->out.info,
5883 : snum, printer->servername,
5884 : r->in.architecture,
5885 : version);
5886 0 : if (!W_ERROR_IS_OK(result)) {
5887 0 : goto err_info_free;
5888 : }
5889 :
5890 0 : *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5891 : r->out.info, r->in.level);
5892 0 : r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5893 :
5894 0 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5895 :
5896 0 : err_info_free:
5897 0 : TALLOC_FREE(r->out.info);
5898 0 : return result;
5899 : }
5900 :
5901 :
5902 : /****************************************************************
5903 : _spoolss_StartPagePrinter
5904 : ****************************************************************/
5905 :
5906 0 : WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5907 : struct spoolss_StartPagePrinter *r)
5908 : {
5909 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5910 :
5911 0 : if (!Printer) {
5912 0 : DEBUG(3,("_spoolss_StartPagePrinter: "
5913 : "Error in startpageprinter printer handle\n"));
5914 0 : return WERR_INVALID_HANDLE;
5915 : }
5916 :
5917 0 : Printer->page_started = true;
5918 0 : return WERR_OK;
5919 : }
5920 :
5921 : /****************************************************************
5922 : _spoolss_EndPagePrinter
5923 : ****************************************************************/
5924 :
5925 0 : WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5926 : struct spoolss_EndPagePrinter *r)
5927 : {
5928 : int snum;
5929 :
5930 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5931 :
5932 0 : if (!Printer) {
5933 0 : DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5934 : OUR_HANDLE(r->in.handle)));
5935 0 : return WERR_INVALID_HANDLE;
5936 : }
5937 :
5938 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5939 0 : return WERR_INVALID_HANDLE;
5940 :
5941 0 : Printer->page_started = false;
5942 0 : print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5943 :
5944 0 : return WERR_OK;
5945 : }
5946 :
5947 : /****************************************************************
5948 : _spoolss_StartDocPrinter
5949 : ****************************************************************/
5950 :
5951 0 : WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5952 : struct spoolss_StartDocPrinter *r)
5953 : {
5954 0 : struct dcesrv_call_state *dce_call = p->dce_call;
5955 0 : struct dcesrv_connection *dcesrv_conn = dce_call->conn;
5956 0 : const struct tsocket_address *remote_address =
5957 0 : dcesrv_connection_get_remote_address(dcesrv_conn);
5958 0 : struct auth_session_info *session_info =
5959 0 : dcesrv_call_session_info(dce_call);
5960 : struct spoolss_DocumentInfo1 *info_1;
5961 : int snum;
5962 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5963 : WERROR werr;
5964 : char *rhost;
5965 : int rc;
5966 :
5967 0 : if (!Printer) {
5968 0 : DEBUG(2,("_spoolss_StartDocPrinter: "
5969 : "Invalid handle (%s:%u:%u)\n",
5970 : OUR_HANDLE(r->in.handle)));
5971 0 : return WERR_INVALID_HANDLE;
5972 : }
5973 :
5974 0 : if (Printer->jobid) {
5975 0 : DEBUG(2, ("_spoolss_StartDocPrinter: "
5976 : "StartDocPrinter called twice! "
5977 : "(existing jobid = %d)\n", Printer->jobid));
5978 0 : return WERR_INVALID_HANDLE;
5979 : }
5980 :
5981 0 : if (r->in.info_ctr->level != 1) {
5982 0 : return WERR_INVALID_LEVEL;
5983 : }
5984 :
5985 0 : info_1 = r->in.info_ctr->info.info1;
5986 :
5987 : /*
5988 : * a nice thing with NT is it doesn't listen to what you tell it.
5989 : * when asked to send _only_ RAW datas, it tries to send datas
5990 : * in EMF format.
5991 : *
5992 : * So I add checks like in NT Server ...
5993 : */
5994 :
5995 0 : if (info_1->datatype) {
5996 : /*
5997 : * The v4 driver model used in Windows 8 declares print jobs
5998 : * intended to bypass the XPS processing layer by setting
5999 : * datatype to "XPS_PASS" instead of "RAW".
6000 : */
6001 0 : if ((strcmp(info_1->datatype, "RAW") != 0)
6002 0 : && (strcmp(info_1->datatype, "XPS_PASS") != 0)) {
6003 0 : *r->out.job_id = 0;
6004 0 : return WERR_INVALID_DATATYPE;
6005 : }
6006 : }
6007 :
6008 : /* get the share number of the printer */
6009 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6010 0 : return WERR_INVALID_HANDLE;
6011 : }
6012 :
6013 0 : rc = get_remote_hostname(remote_address,
6014 : &rhost,
6015 : p->mem_ctx);
6016 0 : if (rc < 0) {
6017 0 : return WERR_NOT_ENOUGH_MEMORY;
6018 : }
6019 0 : if (strequal(rhost,"UNKNOWN")) {
6020 0 : rhost = tsocket_address_inet_addr_string(remote_address,
6021 : p->mem_ctx);
6022 0 : if (rhost == NULL) {
6023 0 : return WERR_NOT_ENOUGH_MEMORY;
6024 : }
6025 : }
6026 :
6027 0 : werr = print_job_start(session_info,
6028 : p->msg_ctx,
6029 : rhost,
6030 : snum,
6031 : info_1->document_name,
6032 : info_1->output_file,
6033 : Printer->devmode,
6034 : &Printer->jobid);
6035 :
6036 : /* An error occurred in print_job_start() so return an appropriate
6037 : NT error code. */
6038 :
6039 0 : if (!W_ERROR_IS_OK(werr)) {
6040 0 : return werr;
6041 : }
6042 :
6043 0 : Printer->document_started = true;
6044 0 : *r->out.job_id = Printer->jobid;
6045 :
6046 0 : return WERR_OK;
6047 : }
6048 :
6049 : /****************************************************************
6050 : _spoolss_EndDocPrinter
6051 : ****************************************************************/
6052 :
6053 0 : WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
6054 : struct spoolss_EndDocPrinter *r)
6055 : {
6056 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6057 : NTSTATUS status;
6058 : int snum;
6059 :
6060 0 : if (!Printer) {
6061 0 : DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
6062 : OUR_HANDLE(r->in.handle)));
6063 0 : return WERR_INVALID_HANDLE;
6064 : }
6065 :
6066 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6067 0 : return WERR_INVALID_HANDLE;
6068 : }
6069 :
6070 0 : Printer->document_started = false;
6071 0 : status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
6072 0 : if (!NT_STATUS_IS_OK(status)) {
6073 0 : DEBUG(2, ("_spoolss_EndDocPrinter: "
6074 : "print_job_end failed [%s]\n",
6075 : nt_errstr(status)));
6076 : }
6077 :
6078 0 : Printer->jobid = 0;
6079 0 : return ntstatus_to_werror(status);
6080 : }
6081 :
6082 : /****************************************************************
6083 : _spoolss_WritePrinter
6084 : ****************************************************************/
6085 :
6086 0 : WERROR _spoolss_WritePrinter(struct pipes_struct *p,
6087 : struct spoolss_WritePrinter *r)
6088 : {
6089 : ssize_t buffer_written;
6090 : int snum;
6091 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6092 :
6093 0 : if (!Printer) {
6094 0 : DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
6095 : OUR_HANDLE(r->in.handle)));
6096 0 : *r->out.num_written = r->in._data_size;
6097 0 : return WERR_INVALID_HANDLE;
6098 : }
6099 :
6100 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL))
6101 0 : return WERR_INVALID_HANDLE;
6102 :
6103 : /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
6104 0 : buffer_written = print_job_write(global_event_context(),p->msg_ctx,
6105 : snum, Printer->jobid,
6106 0 : (const char *)r->in.data.data,
6107 0 : (size_t)r->in._data_size);
6108 0 : if (buffer_written == (ssize_t)-1) {
6109 0 : *r->out.num_written = 0;
6110 0 : if (errno == ENOSPC)
6111 0 : return WERR_NO_SPOOL_SPACE;
6112 : else
6113 0 : return WERR_ACCESS_DENIED;
6114 : }
6115 :
6116 0 : *r->out.num_written = r->in._data_size;
6117 :
6118 0 : return WERR_OK;
6119 : }
6120 :
6121 : /********************************************************************
6122 : * api_spoolss_getprinter
6123 : * called from the spoolss dispatcher
6124 : *
6125 : ********************************************************************/
6126 :
6127 0 : static WERROR control_printer(struct policy_handle *handle, uint32_t command,
6128 : struct pipes_struct *p)
6129 : {
6130 0 : struct dcesrv_call_state *dce_call = p->dce_call;
6131 0 : struct auth_session_info *session_info =
6132 0 : dcesrv_call_session_info(dce_call);
6133 : int snum;
6134 0 : WERROR errcode = WERR_INVALID_FUNCTION;
6135 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6136 :
6137 0 : if (!Printer) {
6138 0 : DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
6139 : OUR_HANDLE(handle)));
6140 0 : return WERR_INVALID_HANDLE;
6141 : }
6142 :
6143 0 : if (!get_printer_snum(p, handle, &snum, NULL))
6144 0 : return WERR_INVALID_HANDLE;
6145 :
6146 0 : switch (command) {
6147 0 : case SPOOLSS_PRINTER_CONTROL_PAUSE:
6148 0 : errcode = print_queue_pause(session_info, p->msg_ctx, snum);
6149 0 : break;
6150 0 : case SPOOLSS_PRINTER_CONTROL_RESUME:
6151 : case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
6152 0 : errcode = print_queue_resume(session_info, p->msg_ctx, snum);
6153 0 : break;
6154 0 : case SPOOLSS_PRINTER_CONTROL_PURGE:
6155 0 : errcode = print_queue_purge(session_info, p->msg_ctx, snum);
6156 0 : break;
6157 0 : default:
6158 0 : return WERR_INVALID_LEVEL;
6159 : }
6160 :
6161 0 : return errcode;
6162 : }
6163 :
6164 :
6165 : /****************************************************************
6166 : _spoolss_AbortPrinter
6167 : * From MSDN: "Deletes printer's spool file if printer is configured
6168 : * for spooling"
6169 : ****************************************************************/
6170 :
6171 0 : WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
6172 : struct spoolss_AbortPrinter *r)
6173 : {
6174 0 : struct dcesrv_call_state *dce_call = p->dce_call;
6175 0 : struct auth_session_info *session_info =
6176 0 : dcesrv_call_session_info(dce_call);
6177 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6178 : int snum;
6179 0 : WERROR errcode = WERR_OK;
6180 :
6181 0 : if (!Printer) {
6182 0 : DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
6183 : OUR_HANDLE(r->in.handle)));
6184 0 : return WERR_INVALID_HANDLE;
6185 : }
6186 :
6187 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL))
6188 0 : return WERR_INVALID_HANDLE;
6189 :
6190 0 : if (!Printer->document_started) {
6191 0 : return WERR_SPL_NO_STARTDOC;
6192 : }
6193 :
6194 0 : errcode = print_job_delete(session_info,
6195 : p->msg_ctx,
6196 : snum,
6197 : Printer->jobid);
6198 :
6199 0 : return errcode;
6200 : }
6201 :
6202 : /********************************************************************
6203 : * called by spoolss_api_setprinter
6204 : * when updating a printer description
6205 : ********************************************************************/
6206 :
6207 0 : static WERROR update_printer_sec(struct policy_handle *handle,
6208 : struct pipes_struct *p,
6209 : struct sec_desc_buf *secdesc_ctr)
6210 : {
6211 0 : struct spoolss_security_descriptor *new_secdesc = NULL;
6212 0 : struct spoolss_security_descriptor *old_secdesc = NULL;
6213 0 : const char *printer = NULL;
6214 : WERROR result;
6215 0 : int snum = -1;
6216 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6217 : struct dcerpc_binding_handle *b;
6218 0 : TALLOC_CTX *tmp_ctx = NULL;
6219 0 : bool ok = false;
6220 :
6221 0 : if (!Printer) {
6222 0 : DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6223 : OUR_HANDLE(handle)));
6224 :
6225 0 : result = WERR_INVALID_HANDLE;
6226 0 : goto done;
6227 : }
6228 :
6229 0 : if (secdesc_ctr == NULL) {
6230 0 : DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6231 0 : result = WERR_INVALID_PARAMETER;
6232 0 : goto done;
6233 : }
6234 :
6235 0 : switch (Printer->printer_type) {
6236 0 : case SPLHND_SERVER:
6237 0 : break;
6238 0 : case SPLHND_PRINTER:
6239 0 : if (!get_printer_snum(p, handle, &snum, NULL)) {
6240 0 : DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6241 : OUR_HANDLE(handle)));
6242 0 : result = WERR_INVALID_HANDLE;
6243 0 : goto done;
6244 : }
6245 0 : printer = lp_const_servicename(snum);
6246 0 : break;
6247 0 : default:
6248 0 : break;
6249 : }
6250 :
6251 : /* Check the user has permissions to change the security
6252 : descriptor. By experimentation with two NT machines, the user
6253 : requires Full Access to the printer to change security
6254 : information. */
6255 :
6256 0 : switch (Printer->printer_type) {
6257 0 : case SPLHND_SERVER:
6258 0 : ok = Printer->access_granted == SERVER_ACCESS_ADMINISTER;
6259 0 : break;
6260 0 : case SPLHND_PRINTER:
6261 0 : ok = Printer->access_granted == PRINTER_ACCESS_ADMINISTER;
6262 0 : break;
6263 0 : default:
6264 0 : break;
6265 : }
6266 :
6267 0 : if (!ok) {
6268 0 : DEBUG(4,("update_printer_sec: updated denied by printer permissions "
6269 : "(access_granted: 0x%08x)\n", Printer->access_granted));
6270 0 : result = WERR_ACCESS_DENIED;
6271 0 : goto done;
6272 : }
6273 :
6274 0 : tmp_ctx = talloc_new(p->mem_ctx);
6275 0 : if (!tmp_ctx) {
6276 0 : return WERR_NOT_ENOUGH_MEMORY;
6277 : }
6278 :
6279 0 : result = winreg_printer_binding_handle(tmp_ctx,
6280 : get_session_info_system(),
6281 : p->msg_ctx,
6282 : &b);
6283 0 : if (!W_ERROR_IS_OK(result)) {
6284 0 : goto done;
6285 : }
6286 :
6287 : /* NT seems to like setting the security descriptor even though
6288 : nothing may have actually changed. */
6289 :
6290 0 : if (printer != NULL) {
6291 0 : result = winreg_get_printer_secdesc(tmp_ctx, b,
6292 : printer,
6293 : &old_secdesc);
6294 : } else {
6295 0 : result = winreg_get_printserver_secdesc(tmp_ctx, b,
6296 : &old_secdesc);
6297 : }
6298 0 : if (!W_ERROR_IS_OK(result)) {
6299 0 : DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6300 0 : result = WERR_INVALID_HANDLE;
6301 0 : goto done;
6302 : }
6303 :
6304 0 : if (DEBUGLEVEL >= 10) {
6305 : struct dom_sid_buf buf;
6306 : struct security_acl *the_acl;
6307 : int i;
6308 :
6309 0 : the_acl = old_secdesc->dacl;
6310 0 : DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6311 : printer, the_acl->num_aces));
6312 :
6313 0 : for (i = 0; i < the_acl->num_aces; i++) {
6314 0 : DEBUG(10, ("%s 0x%08x\n",
6315 : dom_sid_str_buf(
6316 : &the_acl->aces[i].trustee,
6317 : &buf),
6318 : the_acl->aces[i].access_mask));
6319 : }
6320 :
6321 0 : the_acl = secdesc_ctr->sd->dacl;
6322 :
6323 0 : if (the_acl) {
6324 0 : DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6325 : printer, the_acl->num_aces));
6326 :
6327 0 : for (i = 0; i < the_acl->num_aces; i++) {
6328 0 : DEBUG(10, ("%s 0x%08x\n",
6329 : dom_sid_str_buf(
6330 : &the_acl->aces[i].trustee,
6331 : &buf),
6332 : the_acl->aces[i].access_mask));
6333 : }
6334 : } else {
6335 0 : DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6336 : }
6337 : }
6338 :
6339 0 : new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6340 0 : if (new_secdesc == NULL) {
6341 0 : result = WERR_NOT_ENOUGH_MEMORY;
6342 0 : goto done;
6343 : }
6344 :
6345 0 : if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6346 0 : result = WERR_OK;
6347 0 : goto done;
6348 : }
6349 :
6350 0 : if (printer != NULL) {
6351 0 : result = winreg_set_printer_secdesc(tmp_ctx, b,
6352 : printer,
6353 : new_secdesc);
6354 : } else {
6355 0 : result = winreg_set_printserver_secdesc(tmp_ctx, b,
6356 : new_secdesc);
6357 : }
6358 :
6359 0 : done:
6360 0 : talloc_free(tmp_ctx);
6361 0 : return result;
6362 : }
6363 :
6364 : /********************************************************************
6365 : Canonicalize printer info from a client
6366 : ********************************************************************/
6367 :
6368 0 : static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6369 : struct spoolss_SetPrinterInfo2 *info2,
6370 : int snum)
6371 : {
6372 : fstring printername;
6373 : const char *p;
6374 :
6375 0 : DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6376 : "portname=%s drivername=%s comment=%s location=%s\n",
6377 : info2->servername, info2->printername, info2->sharename,
6378 : info2->portname, info2->drivername, info2->comment,
6379 : info2->location));
6380 :
6381 : /* we force some elements to "correct" values */
6382 0 : info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6383 0 : if (info2->servername == NULL) {
6384 0 : return false;
6385 : }
6386 0 : info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6387 0 : if (info2->sharename == NULL) {
6388 0 : return false;
6389 : }
6390 :
6391 : /* check to see if we allow printername != sharename */
6392 0 : if (lp_force_printername(snum)) {
6393 0 : info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6394 : lp_netbios_name(), info2->sharename);
6395 : } else {
6396 : /* make sure printername is in \\server\printername format */
6397 0 : fstrcpy(printername, info2->printername);
6398 0 : p = printername;
6399 0 : if ( printername[0] == '\\' && printername[1] == '\\' ) {
6400 0 : if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6401 0 : p++;
6402 : }
6403 :
6404 0 : info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6405 : lp_netbios_name(), p);
6406 : }
6407 0 : if (info2->printername == NULL) {
6408 0 : return false;
6409 : }
6410 :
6411 0 : info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6412 0 : info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6413 :
6414 0 : return true;
6415 : }
6416 :
6417 : /****************************************************************************
6418 : ****************************************************************************/
6419 :
6420 0 : static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6421 : {
6422 0 : const struct loadparm_substitution *lp_sub =
6423 0 : loadparm_s3_global_substitution();
6424 0 : char *cmd = lp_addport_command(talloc_tos(), lp_sub);
6425 0 : char *command = NULL;
6426 : int ret;
6427 0 : bool is_print_op = false;
6428 :
6429 0 : if ( !*cmd ) {
6430 0 : return WERR_ACCESS_DENIED;
6431 : }
6432 :
6433 0 : command = talloc_asprintf(ctx,
6434 : "%s \"%s\" \"%s\"", cmd, portname, uri );
6435 0 : if (!command) {
6436 0 : return WERR_NOT_ENOUGH_MEMORY;
6437 : }
6438 :
6439 0 : if ( token )
6440 0 : is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6441 :
6442 0 : DEBUG(10,("Running [%s]\n", command));
6443 :
6444 : /********* BEGIN SePrintOperatorPrivilege **********/
6445 :
6446 0 : if ( is_print_op )
6447 0 : become_root();
6448 :
6449 0 : ret = smbrun(command, NULL, NULL);
6450 :
6451 0 : if ( is_print_op )
6452 0 : unbecome_root();
6453 :
6454 : /********* END SePrintOperatorPrivilege **********/
6455 :
6456 0 : DEBUGADD(10,("returned [%d]\n", ret));
6457 :
6458 0 : TALLOC_FREE(command);
6459 :
6460 0 : if ( ret != 0 ) {
6461 0 : return WERR_ACCESS_DENIED;
6462 : }
6463 :
6464 0 : return WERR_OK;
6465 : }
6466 :
6467 : /****************************************************************************
6468 : ****************************************************************************/
6469 :
6470 0 : static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6471 : int snum)
6472 : {
6473 : /*
6474 : * As we do not know if we are embedded in the file server process
6475 : * or not, we have to pretend that all shares are in use.
6476 : */
6477 0 : return true;
6478 : }
6479 :
6480 0 : static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6481 : struct spoolss_SetPrinterInfo2 *info2,
6482 : const char *remote_machine,
6483 : struct messaging_context *msg_ctx)
6484 : {
6485 0 : const struct loadparm_substitution *lp_sub =
6486 0 : loadparm_s3_global_substitution();
6487 0 : char *cmd = lp_addprinter_command(talloc_tos(), lp_sub);
6488 : char **qlines;
6489 0 : char *command = NULL;
6490 : int numlines;
6491 : int ret;
6492 : int fd;
6493 0 : bool is_print_op = false;
6494 :
6495 0 : if (!remote_machine) {
6496 0 : return false;
6497 : }
6498 :
6499 0 : command = talloc_asprintf(ctx,
6500 : "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6501 : cmd, info2->printername, info2->sharename,
6502 : info2->portname, info2->drivername,
6503 : info2->location, info2->comment, remote_machine);
6504 0 : if (!command) {
6505 0 : return false;
6506 : }
6507 :
6508 0 : if ( token )
6509 0 : is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6510 :
6511 0 : DEBUG(10,("Running [%s]\n", command));
6512 :
6513 : /********* BEGIN SePrintOperatorPrivilege **********/
6514 :
6515 0 : if ( is_print_op )
6516 0 : become_root();
6517 :
6518 0 : ret = smbrun(command, &fd, NULL);
6519 0 : if (ret == 0) {
6520 : /* Tell everyone we updated smb.conf. */
6521 0 : messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
6522 : }
6523 :
6524 0 : if ( is_print_op )
6525 0 : unbecome_root();
6526 :
6527 : /********* END SePrintOperatorPrivilege **********/
6528 :
6529 0 : DEBUGADD(10,("returned [%d]\n", ret));
6530 :
6531 0 : TALLOC_FREE(command);
6532 :
6533 0 : if ( ret != 0 ) {
6534 0 : if (fd != -1)
6535 0 : close(fd);
6536 0 : return false;
6537 : }
6538 :
6539 : /* reload our services immediately */
6540 0 : become_root();
6541 0 : reload_services(NULL, spoolss_conn_snum_used, false);
6542 0 : unbecome_root();
6543 :
6544 0 : numlines = 0;
6545 : /* Get lines and convert them back to dos-codepage */
6546 0 : qlines = fd_lines_load(fd, &numlines, 0, NULL);
6547 0 : DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6548 0 : close(fd);
6549 :
6550 : /* Set the portname to what the script says the portname should be. */
6551 : /* but don't require anything to be return from the script exit a good error code */
6552 :
6553 0 : if (numlines) {
6554 : /* Set the portname to what the script says the portname should be. */
6555 0 : info2->portname = talloc_strdup(ctx, qlines[0]);
6556 0 : DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6557 : }
6558 :
6559 0 : TALLOC_FREE(qlines);
6560 0 : return true;
6561 : }
6562 :
6563 0 : static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6564 : const struct auth_session_info *session_info,
6565 : struct messaging_context *msg_ctx,
6566 : int snum,
6567 : struct spoolss_SetPrinterInfo2 *printer,
6568 : struct spoolss_PrinterInfo2 *old_printer)
6569 : {
6570 0 : bool force_update = (old_printer == NULL);
6571 : const char *dnsdomname;
6572 : const char *longname;
6573 : const char *uncname;
6574 : const char *spooling;
6575 : DATA_BLOB buffer;
6576 0 : WERROR result = WERR_OK;
6577 : struct dcerpc_binding_handle *b;
6578 : TALLOC_CTX *tmp_ctx;
6579 : bool ok;
6580 :
6581 0 : tmp_ctx = talloc_new(mem_ctx);
6582 0 : if (!tmp_ctx) {
6583 0 : return WERR_NOT_ENOUGH_MEMORY;
6584 : }
6585 :
6586 0 : result = winreg_printer_binding_handle(tmp_ctx,
6587 : session_info,
6588 : msg_ctx,
6589 : &b);
6590 0 : if (!W_ERROR_IS_OK(result)) {
6591 0 : goto done;
6592 : }
6593 :
6594 0 : if (printer->drivername != NULL &&
6595 0 : (force_update ||
6596 0 : !strequal(printer->drivername, old_printer->drivername))) {
6597 0 : ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6598 0 : if (!ok) {
6599 0 : DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6600 0 : result = WERR_INVALID_DATA;
6601 0 : goto done;
6602 : }
6603 0 : result = winreg_set_printer_dataex(tmp_ctx, b,
6604 : printer->sharename,
6605 : SPOOL_DSSPOOLER_KEY,
6606 : SPOOL_REG_DRIVERNAME,
6607 : REG_SZ,
6608 : buffer.data,
6609 0 : buffer.length);
6610 0 : if (!W_ERROR_IS_OK(result)) {
6611 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6612 0 : goto done;
6613 : }
6614 :
6615 0 : if (!force_update) {
6616 0 : DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6617 : printer->drivername));
6618 :
6619 0 : notify_printer_driver(global_event_context(), msg_ctx,
6620 0 : snum, printer->drivername ?
6621 : printer->drivername : "");
6622 : }
6623 : }
6624 :
6625 0 : if (printer->comment != NULL &&
6626 0 : (force_update ||
6627 0 : !strequal(printer->comment, old_printer->comment))) {
6628 0 : ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6629 0 : if (!ok) {
6630 0 : DEBUG(0, ("comment data corrupted\n"));
6631 0 : result = WERR_INVALID_DATA;
6632 0 : goto done;
6633 : }
6634 0 : result = winreg_set_printer_dataex(tmp_ctx, b,
6635 : printer->sharename,
6636 : SPOOL_DSSPOOLER_KEY,
6637 : SPOOL_REG_DESCRIPTION,
6638 : REG_SZ,
6639 : buffer.data,
6640 0 : buffer.length);
6641 0 : if (!W_ERROR_IS_OK(result)) {
6642 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6643 0 : goto done;
6644 : }
6645 :
6646 0 : if (!force_update) {
6647 0 : notify_printer_comment(global_event_context(), msg_ctx,
6648 0 : snum, printer->comment ?
6649 : printer->comment : "");
6650 : }
6651 : }
6652 :
6653 0 : if (printer->sharename != NULL &&
6654 0 : (force_update ||
6655 0 : !strequal(printer->sharename, old_printer->sharename))) {
6656 0 : ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6657 0 : if (!ok) {
6658 0 : DEBUG(0, ("sharename data corrupted\n"));
6659 0 : result = WERR_INVALID_DATA;
6660 0 : goto done;
6661 : }
6662 0 : result = winreg_set_printer_dataex(tmp_ctx, b,
6663 : printer->sharename,
6664 : SPOOL_DSSPOOLER_KEY,
6665 : SPOOL_REG_PRINTSHARENAME,
6666 : REG_SZ,
6667 : buffer.data,
6668 0 : buffer.length);
6669 0 : if (!W_ERROR_IS_OK(result)) {
6670 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6671 0 : goto done;
6672 : }
6673 :
6674 0 : if (!force_update) {
6675 0 : notify_printer_sharename(global_event_context(),
6676 : msg_ctx,
6677 0 : snum, printer->sharename ?
6678 : printer->sharename : "");
6679 : }
6680 :
6681 : /* name change, purge any cache entries for the old */
6682 0 : prune_printername_cache();
6683 : }
6684 :
6685 0 : if (printer->printername != NULL &&
6686 0 : (force_update ||
6687 0 : !strequal(printer->printername, old_printer->printername))) {
6688 : const char *p;
6689 :
6690 0 : p = strrchr(printer->printername, '\\' );
6691 0 : if (p != NULL) {
6692 0 : p++;
6693 : } else {
6694 0 : p = printer->printername;
6695 : }
6696 :
6697 0 : ok = push_reg_sz(tmp_ctx, &buffer, p);
6698 0 : if (!ok) {
6699 0 : DEBUG(0, ("printername data corrupted\n"));
6700 0 : result = WERR_INVALID_DATA;
6701 0 : goto done;
6702 : }
6703 0 : result = winreg_set_printer_dataex(tmp_ctx, b,
6704 : printer->sharename,
6705 : SPOOL_DSSPOOLER_KEY,
6706 : SPOOL_REG_PRINTERNAME,
6707 : REG_SZ,
6708 : buffer.data,
6709 0 : buffer.length);
6710 0 : if (!W_ERROR_IS_OK(result)) {
6711 0 : DBG_ERR("Failed to set %s\n", SPOOL_REG_PRINTERNAME);
6712 0 : goto done;
6713 : }
6714 :
6715 0 : if (!force_update) {
6716 0 : notify_printer_printername(global_event_context(),
6717 : msg_ctx, snum, p ? p : "");
6718 : }
6719 :
6720 : /* name change, purge any cache entries for the old */
6721 0 : prune_printername_cache();
6722 : }
6723 :
6724 0 : if (printer->portname != NULL &&
6725 0 : (force_update ||
6726 0 : !strequal(printer->portname, old_printer->portname))) {
6727 0 : ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6728 0 : if (!ok) {
6729 0 : DEBUG(0, ("portname data corrupted\n"));
6730 0 : result = WERR_INVALID_DATA;
6731 0 : goto done;
6732 : }
6733 0 : result = winreg_set_printer_dataex(tmp_ctx, b,
6734 : printer->sharename,
6735 : SPOOL_DSSPOOLER_KEY,
6736 : SPOOL_REG_PORTNAME,
6737 : REG_SZ,
6738 : buffer.data,
6739 0 : buffer.length);
6740 0 : if (!W_ERROR_IS_OK(result)) {
6741 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6742 0 : goto done;
6743 : }
6744 :
6745 0 : if (!force_update) {
6746 0 : notify_printer_port(global_event_context(),
6747 0 : msg_ctx, snum, printer->portname ?
6748 : printer->portname : "");
6749 : }
6750 : }
6751 :
6752 0 : if (printer->location != NULL &&
6753 0 : (force_update ||
6754 0 : !strequal(printer->location, old_printer->location))) {
6755 0 : ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6756 0 : if (!ok) {
6757 0 : DEBUG(0, ("location data corrupted\n"));
6758 0 : result = WERR_INVALID_DATA;
6759 0 : goto done;
6760 : }
6761 0 : result = winreg_set_printer_dataex(tmp_ctx, b,
6762 : printer->sharename,
6763 : SPOOL_DSSPOOLER_KEY,
6764 : SPOOL_REG_LOCATION,
6765 : REG_SZ,
6766 : buffer.data,
6767 0 : buffer.length);
6768 0 : if (!W_ERROR_IS_OK(result)) {
6769 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6770 0 : goto done;
6771 : }
6772 :
6773 0 : if (!force_update) {
6774 0 : notify_printer_location(global_event_context(),
6775 : msg_ctx, snum,
6776 0 : printer->location ?
6777 : printer->location : "");
6778 : }
6779 : }
6780 :
6781 0 : if (printer->sepfile != NULL &&
6782 0 : (force_update ||
6783 0 : !strequal(printer->sepfile, old_printer->sepfile))) {
6784 0 : ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6785 0 : if (!ok) {
6786 0 : DEBUG(0, ("sepfile data corrupted\n"));
6787 0 : result = WERR_INVALID_DATA;
6788 0 : goto done;
6789 : }
6790 0 : result = winreg_set_printer_dataex(tmp_ctx, b,
6791 : printer->sharename,
6792 : SPOOL_DSSPOOLER_KEY,
6793 : SPOOL_REG_PRINTSEPARATORFILE,
6794 : REG_SZ,
6795 : buffer.data,
6796 0 : buffer.length);
6797 0 : if (!W_ERROR_IS_OK(result)) {
6798 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6799 0 : goto done;
6800 : }
6801 :
6802 0 : if (!force_update) {
6803 0 : notify_printer_sepfile(global_event_context(),
6804 : msg_ctx, snum,
6805 0 : printer->sepfile ?
6806 : printer->sepfile : "");
6807 : }
6808 : }
6809 :
6810 0 : if (printer->starttime != 0 &&
6811 0 : (force_update ||
6812 0 : printer->starttime != old_printer->starttime)) {
6813 0 : buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6814 0 : SIVAL(buffer.data, 0, printer->starttime);
6815 0 : result = winreg_set_printer_dataex(tmp_ctx, b,
6816 : printer->sharename,
6817 : SPOOL_DSSPOOLER_KEY,
6818 : SPOOL_REG_PRINTSTARTTIME,
6819 : REG_DWORD,
6820 : buffer.data,
6821 0 : buffer.length);
6822 0 : if (!W_ERROR_IS_OK(result)) {
6823 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6824 0 : goto done;
6825 : }
6826 : }
6827 :
6828 0 : if (printer->untiltime != 0 &&
6829 0 : (force_update ||
6830 0 : printer->untiltime != old_printer->untiltime)) {
6831 0 : buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6832 0 : SIVAL(buffer.data, 0, printer->untiltime);
6833 0 : result = winreg_set_printer_dataex(tmp_ctx, b,
6834 : printer->sharename,
6835 : SPOOL_DSSPOOLER_KEY,
6836 : SPOOL_REG_PRINTENDTIME,
6837 : REG_DWORD,
6838 : buffer.data,
6839 0 : buffer.length);
6840 0 : if (!W_ERROR_IS_OK(result)) {
6841 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6842 0 : goto done;
6843 : }
6844 : }
6845 :
6846 0 : if (force_update || printer->priority != old_printer->priority) {
6847 0 : buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6848 0 : SIVAL(buffer.data, 0, printer->priority);
6849 0 : result = winreg_set_printer_dataex(tmp_ctx, b,
6850 : printer->sharename,
6851 : SPOOL_DSSPOOLER_KEY,
6852 : SPOOL_REG_PRIORITY,
6853 : REG_DWORD,
6854 : buffer.data,
6855 0 : buffer.length);
6856 0 : if (!W_ERROR_IS_OK(result)) {
6857 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6858 0 : goto done;
6859 : }
6860 : }
6861 :
6862 0 : if (force_update || printer->attributes != old_printer->attributes) {
6863 0 : buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6864 0 : SIVAL(buffer.data, 0, (printer->attributes &
6865 : PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6866 0 : result = winreg_set_printer_dataex(tmp_ctx, b,
6867 : printer->sharename,
6868 : SPOOL_DSSPOOLER_KEY,
6869 : SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6870 : REG_DWORD,
6871 : buffer.data,
6872 0 : buffer.length);
6873 0 : if (!W_ERROR_IS_OK(result)) {
6874 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6875 0 : goto done;
6876 : }
6877 :
6878 0 : switch (printer->attributes & 0x3) {
6879 0 : case 0:
6880 0 : spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6881 0 : break;
6882 0 : case 1:
6883 0 : spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6884 0 : break;
6885 0 : case 2:
6886 0 : spooling = SPOOL_REGVAL_PRINTDIRECT;
6887 0 : break;
6888 0 : default:
6889 0 : spooling = "unknown";
6890 : }
6891 0 : ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6892 0 : if (!ok) {
6893 0 : DEBUG(0, ("printSpooling data corrupted\n"));
6894 0 : result = WERR_INVALID_DATA;
6895 0 : goto done;
6896 : }
6897 0 : winreg_set_printer_dataex(tmp_ctx, b,
6898 : printer->sharename,
6899 : SPOOL_DSSPOOLER_KEY,
6900 : SPOOL_REG_PRINTSPOOLING,
6901 : REG_SZ,
6902 : buffer.data,
6903 0 : buffer.length);
6904 : }
6905 :
6906 0 : ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6907 0 : if (!ok) {
6908 0 : DEBUG(0, ("shortServerName data corrupted\n"));
6909 0 : result = WERR_INVALID_DATA;
6910 0 : goto done;
6911 : }
6912 0 : result = winreg_set_printer_dataex(tmp_ctx, b,
6913 : printer->sharename,
6914 : SPOOL_DSSPOOLER_KEY,
6915 : SPOOL_REG_SHORTSERVERNAME,
6916 : REG_SZ,
6917 : buffer.data,
6918 0 : buffer.length);
6919 0 : if (!W_ERROR_IS_OK(result)) {
6920 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6921 0 : goto done;
6922 : }
6923 :
6924 0 : dnsdomname = get_mydnsfullname();
6925 0 : if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6926 0 : longname = talloc_strdup(tmp_ctx, dnsdomname);
6927 : } else {
6928 0 : longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6929 : }
6930 0 : if (longname == NULL) {
6931 0 : result = WERR_NOT_ENOUGH_MEMORY;
6932 0 : goto done;
6933 : }
6934 :
6935 0 : ok = push_reg_sz(tmp_ctx, &buffer, longname);
6936 0 : if (!ok) {
6937 0 : DEBUG(0, ("longname data corrupted\n"));
6938 0 : result = WERR_INVALID_DATA;
6939 0 : goto done;
6940 : }
6941 0 : result = winreg_set_printer_dataex(tmp_ctx, b,
6942 : printer->sharename,
6943 : SPOOL_DSSPOOLER_KEY,
6944 : SPOOL_REG_SERVERNAME,
6945 : REG_SZ,
6946 : buffer.data,
6947 0 : buffer.length);
6948 0 : if (!W_ERROR_IS_OK(result)) {
6949 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6950 0 : goto done;
6951 : }
6952 :
6953 0 : uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6954 : lp_netbios_name(), printer->sharename);
6955 0 : ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6956 0 : if (!ok) {
6957 0 : DEBUG(0, ("uncName data corrupted\n"));
6958 0 : result = WERR_INVALID_DATA;
6959 0 : goto done;
6960 : }
6961 0 : result = winreg_set_printer_dataex(tmp_ctx, b,
6962 : printer->sharename,
6963 : SPOOL_DSSPOOLER_KEY,
6964 : SPOOL_REG_UNCNAME,
6965 : REG_SZ,
6966 : buffer.data,
6967 0 : buffer.length);
6968 0 : if (!W_ERROR_IS_OK(result)) {
6969 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6970 0 : goto done;
6971 : }
6972 :
6973 0 : done:
6974 0 : talloc_free(tmp_ctx);
6975 0 : return result;
6976 : }
6977 :
6978 : /********************************************************************
6979 : * Called by spoolss_api_setprinter
6980 : * when updating a printer description.
6981 : ********************************************************************/
6982 :
6983 0 : static WERROR update_printer(struct pipes_struct *p,
6984 : struct policy_handle *handle,
6985 : struct spoolss_SetPrinterInfoCtr *info_ctr,
6986 : struct spoolss_DeviceMode *devmode)
6987 : {
6988 0 : struct dcesrv_call_state *dce_call = p->dce_call;
6989 0 : struct dcesrv_connection *dcesrv_conn = dce_call->conn;
6990 0 : const struct tsocket_address *remote_address =
6991 0 : dcesrv_connection_get_remote_address(dcesrv_conn);
6992 0 : struct auth_session_info *session_info =
6993 0 : dcesrv_call_session_info(dce_call);
6994 0 : uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6995 0 : struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6996 : struct spoolss_PrinterInfo2 *old_printer;
6997 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6998 0 : const struct loadparm_substitution *lp_sub =
6999 0 : loadparm_s3_global_substitution();
7000 : int snum;
7001 0 : WERROR result = WERR_OK;
7002 : TALLOC_CTX *tmp_ctx;
7003 : struct dcerpc_binding_handle *b;
7004 :
7005 0 : DEBUG(8,("update_printer\n"));
7006 :
7007 0 : tmp_ctx = talloc_new(p->mem_ctx);
7008 0 : if (tmp_ctx == NULL) {
7009 0 : return WERR_NOT_ENOUGH_MEMORY;
7010 : }
7011 :
7012 0 : if (!Printer) {
7013 0 : result = WERR_INVALID_HANDLE;
7014 0 : goto done;
7015 : }
7016 :
7017 0 : if (!get_printer_snum(p, handle, &snum, NULL)) {
7018 0 : result = WERR_INVALID_HANDLE;
7019 0 : goto done;
7020 : }
7021 :
7022 0 : result = winreg_printer_binding_handle(tmp_ctx,
7023 : get_session_info_system(),
7024 : p->msg_ctx,
7025 : &b);
7026 0 : if (!W_ERROR_IS_OK(result)) {
7027 0 : goto done;
7028 : }
7029 :
7030 0 : result = winreg_get_printer(tmp_ctx, b,
7031 : lp_const_servicename(snum),
7032 : &old_printer);
7033 0 : if (!W_ERROR_IS_OK(result)) {
7034 0 : result = WERR_INVALID_HANDLE;
7035 0 : goto done;
7036 : }
7037 :
7038 : /* Do sanity check on the requested changes for Samba */
7039 0 : if (!check_printer_ok(tmp_ctx, printer, snum)) {
7040 0 : result = WERR_INVALID_PARAMETER;
7041 0 : goto done;
7042 : }
7043 :
7044 : /* FIXME!!! If the driver has changed we really should verify that
7045 : it is installed before doing much else --jerry */
7046 :
7047 : /* Check calling user has permission to update printer description */
7048 0 : if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7049 0 : DEBUG(3, ("update_printer: printer property change denied by handle\n"));
7050 0 : result = WERR_ACCESS_DENIED;
7051 0 : goto done;
7052 : }
7053 :
7054 : /* Call addprinter hook */
7055 : /* Check changes to see if this is really needed */
7056 :
7057 0 : if (*lp_addprinter_command(talloc_tos(), lp_sub) &&
7058 0 : (!strequal(printer->drivername, old_printer->drivername) ||
7059 0 : !strequal(printer->comment, old_printer->comment) ||
7060 0 : !strequal(printer->portname, old_printer->portname) ||
7061 0 : !strequal(printer->location, old_printer->location)) )
7062 : {
7063 : char *raddr;
7064 :
7065 0 : raddr = tsocket_address_inet_addr_string(remote_address,
7066 : p->mem_ctx);
7067 0 : if (raddr == NULL) {
7068 0 : result = WERR_NOT_ENOUGH_MEMORY;
7069 0 : goto done;
7070 : }
7071 :
7072 : /* add_printer_hook() will call reload_services() */
7073 0 : if (!add_printer_hook(tmp_ctx, session_info->security_token,
7074 : printer, raddr,
7075 : p->msg_ctx)) {
7076 0 : result = WERR_ACCESS_DENIED;
7077 0 : goto done;
7078 : }
7079 : }
7080 :
7081 0 : result = update_dsspooler(tmp_ctx,
7082 : get_session_info_system(),
7083 : p->msg_ctx,
7084 : snum,
7085 : printer,
7086 : old_printer);
7087 0 : if (!W_ERROR_IS_OK(result)) {
7088 0 : goto done;
7089 : }
7090 :
7091 0 : printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
7092 :
7093 0 : if (devmode == NULL) {
7094 0 : printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
7095 : }
7096 0 : result = winreg_update_printer(tmp_ctx, b,
7097 : printer->sharename,
7098 : printer_mask,
7099 : printer,
7100 : devmode,
7101 : NULL);
7102 :
7103 0 : done:
7104 0 : talloc_free(tmp_ctx);
7105 :
7106 0 : return result;
7107 : }
7108 :
7109 : /****************************************************************************
7110 : ****************************************************************************/
7111 0 : static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
7112 : struct policy_handle *handle,
7113 : struct spoolss_SetPrinterInfo7 *info7)
7114 : {
7115 : #ifdef HAVE_ADS
7116 0 : const struct loadparm_substitution *lp_sub =
7117 0 : loadparm_s3_global_substitution();
7118 0 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7119 : WERROR result;
7120 : int snum;
7121 : struct printer_handle *Printer;
7122 :
7123 0 : if ( lp_security() != SEC_ADS ) {
7124 0 : return WERR_INVALID_LEVEL;
7125 : }
7126 :
7127 0 : Printer = find_printer_index_by_hnd(p, handle);
7128 :
7129 0 : DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
7130 :
7131 0 : if (!Printer)
7132 0 : return WERR_INVALID_HANDLE;
7133 :
7134 0 : if (!get_printer_snum(p, handle, &snum, NULL))
7135 0 : return WERR_INVALID_HANDLE;
7136 :
7137 0 : result = winreg_get_printer_internal(p->mem_ctx,
7138 : get_session_info_system(),
7139 : p->msg_ctx,
7140 0 : lp_servicename(talloc_tos(), lp_sub, snum),
7141 : &pinfo2);
7142 0 : if (!W_ERROR_IS_OK(result)) {
7143 0 : return WERR_INVALID_HANDLE;
7144 : }
7145 :
7146 0 : nt_printer_publish(pinfo2,
7147 : get_session_info_system(),
7148 : p->msg_ctx,
7149 : pinfo2,
7150 0 : info7->action);
7151 :
7152 0 : TALLOC_FREE(pinfo2);
7153 0 : return WERR_OK;
7154 : #else
7155 : return WERR_INVALID_LEVEL;
7156 : #endif
7157 : }
7158 :
7159 : /********************************************************************
7160 : ********************************************************************/
7161 :
7162 0 : static WERROR update_printer_devmode(struct pipes_struct *p,
7163 : struct policy_handle *handle,
7164 : struct spoolss_DeviceMode *devmode)
7165 : {
7166 : int snum;
7167 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
7168 0 : uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
7169 :
7170 0 : DEBUG(8,("update_printer_devmode\n"));
7171 :
7172 0 : if (!Printer) {
7173 0 : return WERR_INVALID_HANDLE;
7174 : }
7175 :
7176 0 : if (!get_printer_snum(p, handle, &snum, NULL)) {
7177 0 : return WERR_INVALID_HANDLE;
7178 : }
7179 :
7180 : /* Check calling user has permission to update printer description */
7181 0 : if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7182 0 : DEBUG(3, ("update_printer: printer property change denied by handle\n"));
7183 0 : return WERR_ACCESS_DENIED;
7184 : }
7185 :
7186 0 : return winreg_update_printer_internal(p->mem_ctx,
7187 : get_session_info_system(),
7188 : p->msg_ctx,
7189 : lp_const_servicename(snum),
7190 : info2_mask,
7191 : NULL,
7192 : devmode,
7193 : NULL);
7194 : }
7195 :
7196 :
7197 : /****************************************************************
7198 : _spoolss_SetPrinter
7199 : ****************************************************************/
7200 :
7201 0 : WERROR _spoolss_SetPrinter(struct pipes_struct *p,
7202 : struct spoolss_SetPrinter *r)
7203 : {
7204 : WERROR result;
7205 :
7206 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7207 :
7208 0 : if (!Printer) {
7209 0 : DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
7210 : OUR_HANDLE(r->in.handle)));
7211 0 : return WERR_INVALID_HANDLE;
7212 : }
7213 :
7214 : /* check the level */
7215 0 : switch (r->in.info_ctr->level) {
7216 0 : case 0:
7217 0 : return control_printer(r->in.handle, r->in.command, p);
7218 0 : case 2:
7219 0 : result = update_printer(p, r->in.handle,
7220 : r->in.info_ctr,
7221 0 : r->in.devmode_ctr->devmode);
7222 0 : if (!W_ERROR_IS_OK(result))
7223 0 : return result;
7224 0 : if (r->in.secdesc_ctr->sd)
7225 0 : result = update_printer_sec(r->in.handle, p,
7226 : r->in.secdesc_ctr);
7227 0 : return result;
7228 0 : case 3:
7229 0 : return update_printer_sec(r->in.handle, p,
7230 : r->in.secdesc_ctr);
7231 0 : case 4: {
7232 : struct spoolss_PrinterInfo2 *old_printer;
7233 : struct spoolss_SetPrinterInfo2 *set_old_printer;
7234 : struct spoolss_SetPrinterInfoCtr *info_ctr;
7235 : struct dcerpc_binding_handle *b;
7236 : int snum;
7237 : TALLOC_CTX *tmp_ctx;
7238 :
7239 0 : tmp_ctx = talloc_new(p->mem_ctx);
7240 0 : if (tmp_ctx == NULL) {
7241 0 : return WERR_NOT_ENOUGH_MEMORY;
7242 : }
7243 :
7244 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7245 0 : TALLOC_FREE(tmp_ctx);
7246 0 : return WERR_INVALID_HANDLE;
7247 : }
7248 :
7249 0 : result = winreg_printer_binding_handle(tmp_ctx,
7250 : get_session_info_system(),
7251 : p->msg_ctx,
7252 : &b);
7253 0 : if (!W_ERROR_IS_OK(result)) {
7254 0 : TALLOC_FREE(tmp_ctx);
7255 0 : return result;
7256 : }
7257 :
7258 0 : result = winreg_get_printer(tmp_ctx, b,
7259 : lp_const_servicename(snum),
7260 : &old_printer);
7261 0 : if (!W_ERROR_IS_OK(result)) {
7262 0 : TALLOC_FREE(tmp_ctx);
7263 0 : return WERR_INVALID_HANDLE;
7264 : }
7265 :
7266 0 : old_printer->servername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->servername);
7267 0 : if (old_printer->servername == NULL) {
7268 0 : TALLOC_FREE(tmp_ctx);
7269 0 : return WERR_NOT_ENOUGH_MEMORY;
7270 : }
7271 :
7272 0 : old_printer->printername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->printername);
7273 0 : if (old_printer->printername == NULL) {
7274 0 : TALLOC_FREE(tmp_ctx);
7275 0 : return WERR_NOT_ENOUGH_MEMORY;
7276 : }
7277 :
7278 0 : old_printer->attributes = r->in.info_ctr->info.info4->attributes;
7279 :
7280 0 : set_old_printer = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfo2);
7281 0 : if (set_old_printer == NULL) {
7282 0 : TALLOC_FREE(tmp_ctx);
7283 0 : return WERR_NOT_ENOUGH_MEMORY;
7284 : }
7285 :
7286 0 : spoolss_printerinfo2_to_setprinterinfo2(old_printer, set_old_printer);
7287 :
7288 0 : info_ctr = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfoCtr);
7289 0 : if (info_ctr == NULL) {
7290 0 : TALLOC_FREE(tmp_ctx);
7291 0 : return WERR_NOT_ENOUGH_MEMORY;
7292 : }
7293 :
7294 0 : info_ctr->level = 2;
7295 0 : info_ctr->info.info2 = set_old_printer;
7296 :
7297 0 : result = update_printer(p, r->in.handle,
7298 : info_ctr,
7299 0 : r->in.devmode_ctr->devmode);
7300 :
7301 0 : if (!W_ERROR_IS_OK(result)) {
7302 0 : TALLOC_FREE(tmp_ctx);
7303 0 : return result;
7304 : }
7305 :
7306 0 : if (r->in.secdesc_ctr->sd) {
7307 0 : result = update_printer_sec(r->in.handle, p,
7308 : r->in.secdesc_ctr);
7309 : }
7310 :
7311 0 : TALLOC_FREE(tmp_ctx);
7312 0 : return result;
7313 : }
7314 0 : case 7:
7315 0 : return publish_or_unpublish_printer(p, r->in.handle,
7316 0 : r->in.info_ctr->info.info7);
7317 0 : case 8:
7318 0 : return update_printer_devmode(p, r->in.handle,
7319 0 : r->in.devmode_ctr->devmode);
7320 0 : default:
7321 0 : return WERR_INVALID_LEVEL;
7322 : }
7323 : }
7324 :
7325 : /****************************************************************
7326 : _spoolss_FindClosePrinterNotify
7327 : ****************************************************************/
7328 :
7329 0 : WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
7330 : struct spoolss_FindClosePrinterNotify *r)
7331 : {
7332 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7333 :
7334 0 : if (!Printer) {
7335 0 : DEBUG(2,("_spoolss_FindClosePrinterNotify: "
7336 : "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
7337 0 : return WERR_INVALID_HANDLE;
7338 : }
7339 :
7340 0 : if (Printer->notify.cli_chan != NULL &&
7341 0 : Printer->notify.cli_chan->active_connections > 0) {
7342 0 : int snum = -1;
7343 :
7344 0 : if (Printer->printer_type == SPLHND_PRINTER) {
7345 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7346 0 : return WERR_INVALID_HANDLE;
7347 : }
7348 : }
7349 :
7350 0 : srv_spoolss_replycloseprinter(snum, Printer);
7351 : }
7352 :
7353 0 : Printer->notify.flags=0;
7354 0 : Printer->notify.options=0;
7355 0 : Printer->notify.localmachine[0]='\0';
7356 0 : Printer->notify.printerlocal=0;
7357 0 : TALLOC_FREE(Printer->notify.option);
7358 :
7359 0 : return WERR_OK;
7360 : }
7361 :
7362 : /****************************************************************
7363 : _spoolss_AddJob
7364 : ****************************************************************/
7365 :
7366 0 : WERROR _spoolss_AddJob(struct pipes_struct *p,
7367 : struct spoolss_AddJob *r)
7368 : {
7369 0 : if (!r->in.buffer && (r->in.offered != 0)) {
7370 0 : return WERR_INVALID_PARAMETER;
7371 : }
7372 :
7373 : /* this is what a NT server returns for AddJob. AddJob must fail on
7374 : * non-local printers */
7375 :
7376 0 : if (r->in.level != 1) {
7377 0 : return WERR_INVALID_LEVEL;
7378 : }
7379 :
7380 0 : return WERR_INVALID_PARAMETER;
7381 : }
7382 :
7383 : /****************************************************************************
7384 : fill_job_info1
7385 : ****************************************************************************/
7386 :
7387 0 : static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
7388 : struct spoolss_JobInfo1 *r,
7389 : const print_queue_struct *queue,
7390 : uint32_t jobid,
7391 : int position, int snum,
7392 : struct spoolss_PrinterInfo2 *pinfo2)
7393 : {
7394 0 : const struct loadparm_substitution *lp_sub =
7395 0 : loadparm_s3_global_substitution();
7396 : struct tm *t;
7397 :
7398 0 : t = gmtime(&queue->time);
7399 :
7400 0 : r->job_id = jobid;
7401 :
7402 0 : r->printer_name = lp_servicename(mem_ctx, lp_sub, snum);
7403 0 : W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7404 0 : r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
7405 0 : W_ERROR_HAVE_NO_MEMORY(r->server_name);
7406 0 : r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
7407 0 : W_ERROR_HAVE_NO_MEMORY(r->user_name);
7408 0 : r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
7409 0 : W_ERROR_HAVE_NO_MEMORY(r->document_name);
7410 0 : r->data_type = talloc_strdup(mem_ctx, "RAW");
7411 0 : W_ERROR_HAVE_NO_MEMORY(r->data_type);
7412 0 : r->text_status = talloc_strdup(mem_ctx, "");
7413 0 : W_ERROR_HAVE_NO_MEMORY(r->text_status);
7414 :
7415 0 : r->status = nt_printj_status(queue->status);
7416 0 : r->priority = queue->priority;
7417 0 : r->position = position;
7418 0 : r->total_pages = queue->page_count;
7419 0 : r->pages_printed = 0; /* ??? */
7420 :
7421 0 : init_systemtime(&r->submitted, t);
7422 :
7423 0 : return WERR_OK;
7424 : }
7425 :
7426 : /****************************************************************************
7427 : fill_job_info2
7428 : ****************************************************************************/
7429 :
7430 0 : static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7431 : struct spoolss_JobInfo2 *r,
7432 : const print_queue_struct *queue,
7433 : uint32_t jobid,
7434 : int position, int snum,
7435 : struct spoolss_PrinterInfo2 *pinfo2,
7436 : struct spoolss_DeviceMode *devmode)
7437 : {
7438 0 : const struct loadparm_substitution *lp_sub =
7439 0 : loadparm_s3_global_substitution();
7440 : struct tm *t;
7441 :
7442 0 : t = gmtime(&queue->time);
7443 :
7444 0 : r->job_id = jobid;
7445 :
7446 0 : r->printer_name = lp_servicename(mem_ctx, lp_sub, snum);
7447 0 : W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7448 0 : r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
7449 0 : W_ERROR_HAVE_NO_MEMORY(r->server_name);
7450 0 : r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
7451 0 : W_ERROR_HAVE_NO_MEMORY(r->user_name);
7452 0 : r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
7453 0 : W_ERROR_HAVE_NO_MEMORY(r->document_name);
7454 0 : r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
7455 0 : W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7456 0 : r->data_type = talloc_strdup(mem_ctx, "RAW");
7457 0 : W_ERROR_HAVE_NO_MEMORY(r->data_type);
7458 0 : r->print_processor = talloc_strdup(mem_ctx, "winprint");
7459 0 : W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7460 0 : r->parameters = talloc_strdup(mem_ctx, "");
7461 0 : W_ERROR_HAVE_NO_MEMORY(r->parameters);
7462 0 : r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
7463 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7464 :
7465 0 : r->devmode = devmode;
7466 :
7467 0 : r->text_status = talloc_strdup(mem_ctx, "");
7468 0 : W_ERROR_HAVE_NO_MEMORY(r->text_status);
7469 :
7470 0 : r->secdesc = NULL;
7471 :
7472 0 : r->status = nt_printj_status(queue->status);
7473 0 : r->priority = queue->priority;
7474 0 : r->position = position;
7475 0 : r->start_time = 0;
7476 0 : r->until_time = 0;
7477 0 : r->total_pages = queue->page_count;
7478 0 : r->size = queue->size;
7479 0 : init_systemtime(&r->submitted, t);
7480 0 : r->time = 0;
7481 0 : r->pages_printed = 0; /* ??? */
7482 :
7483 0 : return WERR_OK;
7484 : }
7485 :
7486 : /****************************************************************************
7487 : Enumjobs at level 1.
7488 : ****************************************************************************/
7489 :
7490 0 : static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7491 : const print_queue_struct *queue,
7492 : uint32_t num_queues, int snum,
7493 : struct spoolss_PrinterInfo2 *pinfo2,
7494 : union spoolss_JobInfo **info_p,
7495 : uint32_t *count)
7496 : {
7497 : union spoolss_JobInfo *info;
7498 : int i;
7499 0 : WERROR result = WERR_OK;
7500 : uint32_t num_filled;
7501 : struct tdb_print_db *pdb;
7502 :
7503 0 : info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7504 0 : if (info == NULL) {
7505 0 : result = WERR_NOT_ENOUGH_MEMORY;
7506 0 : goto err_out;
7507 : }
7508 :
7509 0 : pdb = get_print_db_byname(pinfo2->sharename);
7510 0 : if (pdb == NULL) {
7511 0 : result = WERR_INVALID_PARAMETER;
7512 0 : goto err_info_free;
7513 : }
7514 :
7515 0 : num_filled = 0;
7516 0 : for (i = 0; i < num_queues; i++) {
7517 0 : uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7518 0 : if (jobid == (uint32_t)-1) {
7519 0 : DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7520 0 : continue;
7521 : }
7522 :
7523 0 : result = fill_job_info1(info,
7524 0 : &info[num_filled].info1,
7525 0 : &queue[i],
7526 : jobid,
7527 : i,
7528 : snum,
7529 : pinfo2);
7530 0 : if (!W_ERROR_IS_OK(result)) {
7531 0 : goto err_pdb_drop;
7532 : }
7533 :
7534 0 : num_filled++;
7535 : }
7536 :
7537 0 : release_print_db(pdb);
7538 0 : *info_p = info;
7539 0 : *count = num_filled;
7540 :
7541 0 : return WERR_OK;
7542 :
7543 0 : err_pdb_drop:
7544 0 : release_print_db(pdb);
7545 0 : err_info_free:
7546 0 : TALLOC_FREE(info);
7547 0 : err_out:
7548 0 : *count = 0;
7549 0 : return result;
7550 : }
7551 :
7552 : /****************************************************************************
7553 : Enumjobs at level 2.
7554 : ****************************************************************************/
7555 :
7556 0 : static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7557 : const print_queue_struct *queue,
7558 : uint32_t num_queues, int snum,
7559 : struct spoolss_PrinterInfo2 *pinfo2,
7560 : union spoolss_JobInfo **info_p,
7561 : uint32_t *count)
7562 : {
7563 : union spoolss_JobInfo *info;
7564 : int i;
7565 0 : WERROR result = WERR_OK;
7566 : uint32_t num_filled;
7567 : struct tdb_print_db *pdb;
7568 :
7569 0 : info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7570 0 : if (info == NULL) {
7571 0 : result = WERR_NOT_ENOUGH_MEMORY;
7572 0 : goto err_out;
7573 : }
7574 :
7575 0 : pdb = get_print_db_byname(pinfo2->sharename);
7576 0 : if (pdb == NULL) {
7577 0 : result = WERR_INVALID_PARAMETER;
7578 0 : goto err_info_free;
7579 : }
7580 :
7581 0 : num_filled = 0;
7582 0 : for (i = 0; i< num_queues; i++) {
7583 : struct spoolss_DeviceMode *devmode;
7584 0 : uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7585 0 : if (jobid == (uint32_t)-1) {
7586 0 : DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7587 0 : continue;
7588 : }
7589 :
7590 0 : result = spoolss_create_default_devmode(info,
7591 : pinfo2->printername,
7592 : &devmode);
7593 0 : if (!W_ERROR_IS_OK(result)) {
7594 0 : DEBUG(3, ("Can't proceed w/o a devmode!"));
7595 0 : goto err_pdb_drop;
7596 : }
7597 :
7598 0 : result = fill_job_info2(info,
7599 0 : &info[num_filled].info2,
7600 0 : &queue[i],
7601 : jobid,
7602 : i,
7603 : snum,
7604 : pinfo2,
7605 : devmode);
7606 0 : if (!W_ERROR_IS_OK(result)) {
7607 0 : goto err_pdb_drop;
7608 : }
7609 0 : num_filled++;
7610 : }
7611 :
7612 0 : release_print_db(pdb);
7613 0 : *info_p = info;
7614 0 : *count = num_filled;
7615 :
7616 0 : return WERR_OK;
7617 :
7618 0 : err_pdb_drop:
7619 0 : release_print_db(pdb);
7620 0 : err_info_free:
7621 0 : TALLOC_FREE(info);
7622 0 : err_out:
7623 0 : *count = 0;
7624 0 : return result;
7625 : }
7626 :
7627 : /****************************************************************************
7628 : Enumjobs at level 3.
7629 : ****************************************************************************/
7630 :
7631 0 : static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7632 : const print_queue_struct *queue,
7633 : uint32_t num_queues, int snum,
7634 : struct spoolss_PrinterInfo2 *pinfo2,
7635 : union spoolss_JobInfo **info_p,
7636 : uint32_t *count)
7637 : {
7638 : union spoolss_JobInfo *info;
7639 : int i;
7640 0 : WERROR result = WERR_OK;
7641 : uint32_t num_filled;
7642 : struct tdb_print_db *pdb;
7643 :
7644 0 : info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7645 0 : if (info == NULL) {
7646 0 : result = WERR_NOT_ENOUGH_MEMORY;
7647 0 : goto err_out;
7648 : }
7649 :
7650 0 : pdb = get_print_db_byname(pinfo2->sharename);
7651 0 : if (pdb == NULL) {
7652 0 : result = WERR_INVALID_PARAMETER;
7653 0 : goto err_info_free;
7654 : }
7655 :
7656 0 : num_filled = 0;
7657 0 : for (i = 0; i < num_queues; i++) {
7658 0 : uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7659 0 : if (jobid == (uint32_t)-1) {
7660 0 : DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7661 0 : continue;
7662 : }
7663 :
7664 0 : info[num_filled].info3.job_id = jobid;
7665 : /* next_job_id is overwritten on next iteration */
7666 0 : info[num_filled].info3.next_job_id = 0;
7667 0 : info[num_filled].info3.reserved = 0;
7668 :
7669 0 : if (num_filled > 0) {
7670 0 : info[num_filled - 1].info3.next_job_id = jobid;
7671 : }
7672 0 : num_filled++;
7673 : }
7674 :
7675 0 : release_print_db(pdb);
7676 0 : *info_p = info;
7677 0 : *count = num_filled;
7678 :
7679 0 : return WERR_OK;
7680 :
7681 0 : err_info_free:
7682 0 : TALLOC_FREE(info);
7683 0 : err_out:
7684 0 : *count = 0;
7685 0 : return result;
7686 : }
7687 :
7688 : /****************************************************************
7689 : _spoolss_EnumJobs
7690 : ****************************************************************/
7691 :
7692 0 : WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7693 : struct spoolss_EnumJobs *r)
7694 : {
7695 : WERROR result;
7696 0 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7697 : int snum;
7698 : print_status_struct prt_status;
7699 0 : print_queue_struct *queue = NULL;
7700 : uint32_t count;
7701 :
7702 : /* that's an [in out] buffer */
7703 :
7704 0 : if (!r->in.buffer && (r->in.offered != 0)) {
7705 0 : return WERR_INVALID_PARAMETER;
7706 : }
7707 :
7708 0 : if ((r->in.level != 1) && (r->in.level != 2) && (r->in.level != 3)) {
7709 0 : DEBUG(4, ("EnumJobs level %d not supported\n", r->in.level));
7710 0 : return WERR_INVALID_LEVEL;
7711 : }
7712 :
7713 0 : DEBUG(4,("_spoolss_EnumJobs\n"));
7714 :
7715 0 : *r->out.needed = 0;
7716 0 : *r->out.count = 0;
7717 0 : *r->out.info = NULL;
7718 :
7719 : /* lookup the printer snum and tdb entry */
7720 :
7721 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7722 0 : return WERR_INVALID_HANDLE;
7723 : }
7724 :
7725 0 : result = winreg_get_printer_internal(p->mem_ctx,
7726 : get_session_info_system(),
7727 : p->msg_ctx,
7728 : lp_const_servicename(snum),
7729 : &pinfo2);
7730 0 : if (!W_ERROR_IS_OK(result)) {
7731 0 : return result;
7732 : }
7733 :
7734 0 : count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7735 0 : DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7736 : count, prt_status.status, prt_status.message));
7737 :
7738 0 : if (count == 0) {
7739 0 : SAFE_FREE(queue);
7740 0 : TALLOC_FREE(pinfo2);
7741 0 : return WERR_OK;
7742 : }
7743 :
7744 0 : switch (r->in.level) {
7745 0 : case 1:
7746 0 : result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7747 : pinfo2, r->out.info, r->out.count);
7748 0 : break;
7749 0 : case 2:
7750 0 : result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7751 : pinfo2, r->out.info, r->out.count);
7752 0 : break;
7753 0 : case 3:
7754 0 : result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7755 : pinfo2, r->out.info, r->out.count);
7756 0 : break;
7757 0 : default:
7758 0 : SMB_ASSERT(false); /* level checked on entry */
7759 : break;
7760 : }
7761 :
7762 0 : SAFE_FREE(queue);
7763 0 : TALLOC_FREE(pinfo2);
7764 :
7765 0 : if (!W_ERROR_IS_OK(result)) {
7766 0 : return result;
7767 : }
7768 :
7769 0 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7770 : spoolss_EnumJobs,
7771 : *r->out.info, r->in.level,
7772 : *r->out.count);
7773 0 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7774 0 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7775 :
7776 0 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7777 : }
7778 :
7779 : /****************************************************************
7780 : _spoolss_ScheduleJob
7781 : ****************************************************************/
7782 :
7783 0 : WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7784 : struct spoolss_ScheduleJob *r)
7785 : {
7786 0 : return WERR_OK;
7787 : }
7788 :
7789 : /****************************************************************
7790 : ****************************************************************/
7791 :
7792 0 : static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7793 : struct messaging_context *msg_ctx,
7794 : const char *printer_name,
7795 : uint32_t job_id,
7796 : struct spoolss_SetJobInfo1 *r)
7797 : {
7798 : char *old_doc_name;
7799 :
7800 0 : if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7801 0 : return WERR_INVALID_HANDLE;
7802 : }
7803 :
7804 0 : if (strequal(old_doc_name, r->document_name)) {
7805 0 : return WERR_OK;
7806 : }
7807 :
7808 0 : if (!print_job_set_name(global_event_context(), msg_ctx,
7809 : printer_name, job_id, r->document_name)) {
7810 0 : return WERR_INVALID_HANDLE;
7811 : }
7812 :
7813 0 : return WERR_OK;
7814 : }
7815 :
7816 : /****************************************************************
7817 : _spoolss_SetJob
7818 : ****************************************************************/
7819 :
7820 0 : WERROR _spoolss_SetJob(struct pipes_struct *p,
7821 : struct spoolss_SetJob *r)
7822 : {
7823 0 : struct dcesrv_call_state *dce_call = p->dce_call;
7824 0 : struct auth_session_info *session_info =
7825 0 : dcesrv_call_session_info(dce_call);
7826 : int snum;
7827 0 : WERROR errcode = WERR_INVALID_FUNCTION;
7828 :
7829 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7830 0 : return WERR_INVALID_HANDLE;
7831 : }
7832 :
7833 0 : if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7834 0 : return WERR_INVALID_PRINTER_NAME;
7835 : }
7836 :
7837 0 : switch (r->in.command) {
7838 0 : case SPOOLSS_JOB_CONTROL_CANCEL:
7839 : case SPOOLSS_JOB_CONTROL_DELETE:
7840 0 : errcode = print_job_delete(session_info, p->msg_ctx,
7841 : snum, r->in.job_id);
7842 0 : if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7843 0 : errcode = WERR_OK;
7844 : }
7845 0 : break;
7846 0 : case SPOOLSS_JOB_CONTROL_PAUSE:
7847 0 : errcode = print_job_pause(session_info, p->msg_ctx,
7848 : snum, r->in.job_id);
7849 0 : break;
7850 0 : case SPOOLSS_JOB_CONTROL_RESTART:
7851 : case SPOOLSS_JOB_CONTROL_RESUME:
7852 0 : errcode = print_job_resume(session_info, p->msg_ctx,
7853 : snum, r->in.job_id);
7854 0 : break;
7855 0 : case SPOOLSS_JOB_CONTROL_NOOP:
7856 0 : errcode = WERR_OK;
7857 0 : break;
7858 0 : default:
7859 0 : return WERR_INVALID_LEVEL;
7860 : }
7861 :
7862 0 : if (!W_ERROR_IS_OK(errcode)) {
7863 0 : return errcode;
7864 : }
7865 :
7866 0 : if (r->in.ctr == NULL) {
7867 0 : return errcode;
7868 : }
7869 :
7870 0 : switch (r->in.ctr->level) {
7871 0 : case 1:
7872 0 : errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7873 : lp_const_servicename(snum),
7874 : r->in.job_id,
7875 0 : r->in.ctr->info.info1);
7876 0 : break;
7877 0 : case 2:
7878 : case 3:
7879 : case 4:
7880 : default:
7881 0 : return WERR_INVALID_LEVEL;
7882 : }
7883 :
7884 0 : return errcode;
7885 : }
7886 :
7887 : /****************************************************************************
7888 : Enumerates all printer drivers by level and architecture.
7889 : ****************************************************************************/
7890 :
7891 0 : static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7892 : const struct auth_session_info *session_info,
7893 : struct messaging_context *msg_ctx,
7894 : const char *servername,
7895 : const char *architecture,
7896 : uint32_t level,
7897 : union spoolss_DriverInfo **info_p,
7898 : uint32_t *count_p)
7899 : {
7900 : int i;
7901 : uint32_t version;
7902 : struct spoolss_DriverInfo8 *driver;
7903 0 : union spoolss_DriverInfo *info = NULL;
7904 0 : uint32_t count = 0;
7905 0 : WERROR result = WERR_OK;
7906 : uint32_t num_drivers;
7907 : const char **drivers;
7908 : struct dcerpc_binding_handle *b;
7909 0 : TALLOC_CTX *tmp_ctx = NULL;
7910 :
7911 0 : *count_p = 0;
7912 0 : *info_p = NULL;
7913 :
7914 0 : tmp_ctx = talloc_new(mem_ctx);
7915 0 : if (!tmp_ctx) {
7916 0 : return WERR_NOT_ENOUGH_MEMORY;
7917 : }
7918 :
7919 0 : result = winreg_printer_binding_handle(tmp_ctx,
7920 : session_info,
7921 : msg_ctx,
7922 : &b);
7923 0 : if (!W_ERROR_IS_OK(result)) {
7924 0 : goto out;
7925 : }
7926 :
7927 0 : for (version=0; version<DRIVER_MAX_VERSION; version++) {
7928 0 : result = winreg_get_driver_list(tmp_ctx, b,
7929 : architecture, version,
7930 : &num_drivers, &drivers);
7931 0 : if (!W_ERROR_IS_OK(result)) {
7932 0 : goto out;
7933 : }
7934 0 : DEBUG(4, ("we have:[%d] drivers in environment"
7935 : " [%s] and version [%d]\n",
7936 : num_drivers, architecture, version));
7937 :
7938 0 : if (num_drivers != 0) {
7939 0 : info = talloc_realloc(tmp_ctx, info,
7940 : union spoolss_DriverInfo,
7941 : count + num_drivers);
7942 0 : if (!info) {
7943 0 : DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7944 : "failed to enlarge driver info buffer!\n"));
7945 0 : result = WERR_NOT_ENOUGH_MEMORY;
7946 0 : goto out;
7947 : }
7948 : }
7949 :
7950 0 : for (i = 0; i < num_drivers; i++) {
7951 0 : DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7952 :
7953 0 : result = winreg_get_driver(tmp_ctx, b,
7954 0 : architecture, drivers[i],
7955 : version, &driver);
7956 0 : if (!W_ERROR_IS_OK(result)) {
7957 0 : goto out;
7958 : }
7959 :
7960 0 : switch (level) {
7961 0 : case 1:
7962 0 : result = fill_printer_driver_info1(info, &info[count+i].info1,
7963 : driver, servername);
7964 0 : break;
7965 0 : case 2:
7966 0 : result = fill_printer_driver_info2(info, &info[count+i].info2,
7967 : driver, servername);
7968 0 : break;
7969 0 : case 3:
7970 0 : result = fill_printer_driver_info3(info, &info[count+i].info3,
7971 : driver, servername);
7972 0 : break;
7973 0 : case 4:
7974 0 : result = fill_printer_driver_info4(info, &info[count+i].info4,
7975 : driver, servername);
7976 0 : break;
7977 0 : case 5:
7978 0 : result = fill_printer_driver_info5(info, &info[count+i].info5,
7979 : driver, servername);
7980 0 : break;
7981 0 : case 6:
7982 0 : result = fill_printer_driver_info6(info, &info[count+i].info6,
7983 : driver, servername);
7984 0 : break;
7985 0 : case 8:
7986 0 : result = fill_printer_driver_info8(info, &info[count+i].info8,
7987 : driver, servername);
7988 0 : break;
7989 0 : default:
7990 0 : result = WERR_INVALID_LEVEL;
7991 0 : break;
7992 : }
7993 :
7994 0 : TALLOC_FREE(driver);
7995 :
7996 0 : if (!W_ERROR_IS_OK(result)) {
7997 0 : goto out;
7998 : }
7999 : }
8000 :
8001 0 : count += num_drivers;
8002 0 : TALLOC_FREE(drivers);
8003 : }
8004 :
8005 0 : out:
8006 0 : if (W_ERROR_IS_OK(result)) {
8007 0 : *info_p = talloc_move(mem_ctx, &info);
8008 0 : *count_p = count;
8009 : }
8010 :
8011 0 : talloc_free(tmp_ctx);
8012 0 : return result;
8013 : }
8014 :
8015 : /****************************************************************************
8016 : Enumerates all printer drivers by level.
8017 : ****************************************************************************/
8018 :
8019 0 : static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
8020 : const struct auth_session_info *session_info,
8021 : struct messaging_context *msg_ctx,
8022 : const char *servername,
8023 : const char *architecture,
8024 : uint32_t level,
8025 : union spoolss_DriverInfo **info_p,
8026 : uint32_t *count_p)
8027 : {
8028 : uint32_t a,i;
8029 0 : WERROR result = WERR_OK;
8030 :
8031 0 : if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
8032 :
8033 0 : for (a=0; archi_table[a].long_archi != NULL; a++) {
8034 :
8035 0 : union spoolss_DriverInfo *info = NULL;
8036 0 : uint32_t count = 0;
8037 :
8038 0 : result = enumprinterdrivers_level_by_architecture(mem_ctx,
8039 : session_info,
8040 : msg_ctx,
8041 : servername,
8042 0 : archi_table[a].long_archi,
8043 : level,
8044 : &info,
8045 : &count);
8046 0 : if (!W_ERROR_IS_OK(result)) {
8047 0 : continue;
8048 : }
8049 :
8050 0 : for (i=0; i < count; i++) {
8051 0 : ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
8052 : info[i], info_p, count_p);
8053 : }
8054 : }
8055 :
8056 0 : return result;
8057 : }
8058 :
8059 0 : return enumprinterdrivers_level_by_architecture(mem_ctx,
8060 : session_info,
8061 : msg_ctx,
8062 : servername,
8063 : architecture,
8064 : level,
8065 : info_p,
8066 : count_p);
8067 : }
8068 :
8069 : /****************************************************************
8070 : _spoolss_EnumPrinterDrivers
8071 : ****************************************************************/
8072 :
8073 0 : WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
8074 : struct spoolss_EnumPrinterDrivers *r)
8075 : {
8076 : const char *cservername;
8077 : WERROR result;
8078 :
8079 : /* that's an [in out] buffer */
8080 :
8081 0 : if (!r->in.buffer && (r->in.offered != 0)) {
8082 0 : return WERR_INVALID_PARAMETER;
8083 : }
8084 :
8085 0 : DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
8086 :
8087 0 : *r->out.needed = 0;
8088 0 : *r->out.count = 0;
8089 0 : *r->out.info = NULL;
8090 :
8091 0 : cservername = canon_servername(r->in.server);
8092 :
8093 0 : if (!is_myname_or_ipaddr(cservername)) {
8094 0 : return WERR_UNKNOWN_PRINTER_DRIVER;
8095 : }
8096 :
8097 0 : result = enumprinterdrivers_level(p->mem_ctx,
8098 : get_session_info_system(),
8099 : p->msg_ctx,
8100 : cservername,
8101 : r->in.environment,
8102 : r->in.level,
8103 : r->out.info,
8104 : r->out.count);
8105 0 : if (!W_ERROR_IS_OK(result)) {
8106 0 : return result;
8107 : }
8108 :
8109 0 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8110 : spoolss_EnumPrinterDrivers,
8111 : *r->out.info, r->in.level,
8112 : *r->out.count);
8113 0 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8114 0 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8115 :
8116 0 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8117 : }
8118 :
8119 : /****************************************************************
8120 : _spoolss_EnumForms
8121 : ****************************************************************/
8122 :
8123 0 : WERROR _spoolss_EnumForms(struct pipes_struct *p,
8124 : struct spoolss_EnumForms *r)
8125 : {
8126 : WERROR result;
8127 :
8128 0 : *r->out.count = 0;
8129 0 : *r->out.needed = 0;
8130 0 : *r->out.info = NULL;
8131 :
8132 : /* that's an [in out] buffer */
8133 :
8134 0 : if (!r->in.buffer && (r->in.offered != 0) ) {
8135 0 : return WERR_INVALID_PARAMETER;
8136 : }
8137 :
8138 0 : DEBUG(4,("_spoolss_EnumForms\n"));
8139 0 : DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
8140 0 : DEBUGADD(5,("Info level [%d]\n", r->in.level));
8141 :
8142 0 : switch (r->in.level) {
8143 0 : case 1:
8144 0 : result = winreg_printer_enumforms1_internal(p->mem_ctx,
8145 : get_session_info_system(),
8146 : p->msg_ctx,
8147 : r->out.count,
8148 : r->out.info);
8149 0 : break;
8150 0 : default:
8151 0 : result = WERR_INVALID_LEVEL;
8152 0 : break;
8153 : }
8154 :
8155 0 : if (!W_ERROR_IS_OK(result)) {
8156 0 : return result;
8157 : }
8158 :
8159 0 : if (*r->out.count == 0) {
8160 0 : return WERR_NO_MORE_ITEMS;
8161 : }
8162 :
8163 0 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8164 : spoolss_EnumForms,
8165 : *r->out.info, r->in.level,
8166 : *r->out.count);
8167 0 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8168 0 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8169 :
8170 0 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8171 : }
8172 :
8173 : /****************************************************************
8174 : _spoolss_GetForm
8175 : ****************************************************************/
8176 :
8177 0 : WERROR _spoolss_GetForm(struct pipes_struct *p,
8178 : struct spoolss_GetForm *r)
8179 : {
8180 : WERROR result;
8181 :
8182 : /* that's an [in out] buffer */
8183 :
8184 0 : if (!r->in.buffer && (r->in.offered != 0)) {
8185 0 : TALLOC_FREE(r->out.info);
8186 0 : return WERR_INVALID_PARAMETER;
8187 : }
8188 :
8189 0 : DEBUG(4,("_spoolss_GetForm\n"));
8190 0 : DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
8191 0 : DEBUGADD(5,("Info level [%d]\n", r->in.level));
8192 :
8193 0 : switch (r->in.level) {
8194 0 : case 1:
8195 0 : result = winreg_printer_getform1_internal(p->mem_ctx,
8196 : get_session_info_system(),
8197 : p->msg_ctx,
8198 : r->in.form_name,
8199 0 : &r->out.info->info1);
8200 0 : break;
8201 0 : default:
8202 0 : result = WERR_INVALID_LEVEL;
8203 0 : break;
8204 : }
8205 :
8206 0 : if (!W_ERROR_IS_OK(result)) {
8207 0 : TALLOC_FREE(r->out.info);
8208 0 : return result;
8209 : }
8210 :
8211 0 : *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
8212 : r->out.info, r->in.level);
8213 0 : r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8214 :
8215 0 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8216 : }
8217 :
8218 : /****************************************************************************
8219 : ****************************************************************************/
8220 :
8221 0 : static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
8222 : struct spoolss_PortInfo1 *r,
8223 : const char *name)
8224 : {
8225 0 : r->port_name = talloc_strdup(mem_ctx, name);
8226 0 : W_ERROR_HAVE_NO_MEMORY(r->port_name);
8227 :
8228 0 : return WERR_OK;
8229 : }
8230 :
8231 : /****************************************************************************
8232 : TODO: This probably needs distinguish between TCP/IP and Local ports
8233 : somehow.
8234 : ****************************************************************************/
8235 :
8236 0 : static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
8237 : struct spoolss_PortInfo2 *r,
8238 : const char *name)
8239 : {
8240 0 : r->port_name = talloc_strdup(mem_ctx, name);
8241 0 : W_ERROR_HAVE_NO_MEMORY(r->port_name);
8242 :
8243 0 : r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
8244 0 : W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8245 :
8246 0 : r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
8247 0 : W_ERROR_HAVE_NO_MEMORY(r->description);
8248 :
8249 0 : r->port_type = SPOOLSS_PORT_TYPE_WRITE;
8250 0 : r->reserved = 0;
8251 :
8252 0 : return WERR_OK;
8253 : }
8254 :
8255 :
8256 : /****************************************************************************
8257 : wrapper around the enumer ports command
8258 : ****************************************************************************/
8259 :
8260 0 : static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
8261 : {
8262 0 : const struct loadparm_substitution *lp_sub =
8263 0 : loadparm_s3_global_substitution();
8264 0 : char *cmd = lp_enumports_command(talloc_tos(), lp_sub);
8265 0 : char **qlines = NULL;
8266 0 : char *command = NULL;
8267 : int numlines;
8268 : int ret;
8269 : int fd;
8270 :
8271 0 : *count = 0;
8272 0 : *lines = NULL;
8273 :
8274 : /* if no hook then just fill in the default port */
8275 :
8276 0 : if ( !*cmd ) {
8277 0 : if (!(qlines = talloc_array( NULL, char*, 2 ))) {
8278 0 : return WERR_NOT_ENOUGH_MEMORY;
8279 : }
8280 0 : if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
8281 0 : TALLOC_FREE(qlines);
8282 0 : return WERR_NOT_ENOUGH_MEMORY;
8283 : }
8284 0 : qlines[1] = NULL;
8285 0 : numlines = 1;
8286 : }
8287 : else {
8288 : /* we have a valid enumport command */
8289 :
8290 0 : command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
8291 0 : if (!command) {
8292 0 : return WERR_NOT_ENOUGH_MEMORY;
8293 : }
8294 :
8295 0 : DEBUG(10,("Running [%s]\n", command));
8296 0 : ret = smbrun(command, &fd, NULL);
8297 0 : DEBUG(10,("Returned [%d]\n", ret));
8298 0 : TALLOC_FREE(command);
8299 0 : if (ret != 0) {
8300 0 : if (fd != -1) {
8301 0 : close(fd);
8302 : }
8303 0 : return WERR_ACCESS_DENIED;
8304 : }
8305 :
8306 0 : numlines = 0;
8307 0 : qlines = fd_lines_load(fd, &numlines, 0, NULL);
8308 0 : DEBUGADD(10,("Lines returned = [%d]\n", numlines));
8309 0 : close(fd);
8310 : }
8311 :
8312 0 : *count = numlines;
8313 0 : *lines = qlines;
8314 :
8315 0 : return WERR_OK;
8316 : }
8317 :
8318 : /****************************************************************************
8319 : enumports level 1.
8320 : ****************************************************************************/
8321 :
8322 0 : static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
8323 : union spoolss_PortInfo **info_p,
8324 : uint32_t *count)
8325 : {
8326 0 : union spoolss_PortInfo *info = NULL;
8327 0 : int i=0;
8328 0 : WERROR result = WERR_OK;
8329 0 : char **qlines = NULL;
8330 0 : int numlines = 0;
8331 :
8332 0 : result = enumports_hook(talloc_tos(), &numlines, &qlines );
8333 0 : if (!W_ERROR_IS_OK(result)) {
8334 0 : goto out;
8335 : }
8336 :
8337 0 : if (numlines) {
8338 0 : info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8339 0 : if (!info) {
8340 0 : DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
8341 0 : result = WERR_NOT_ENOUGH_MEMORY;
8342 0 : goto out;
8343 : }
8344 :
8345 0 : for (i=0; i<numlines; i++) {
8346 0 : DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8347 0 : result = fill_port_1(info, &info[i].info1, qlines[i]);
8348 0 : if (!W_ERROR_IS_OK(result)) {
8349 0 : goto out;
8350 : }
8351 : }
8352 : }
8353 0 : TALLOC_FREE(qlines);
8354 :
8355 0 : out:
8356 0 : if (!W_ERROR_IS_OK(result)) {
8357 0 : TALLOC_FREE(info);
8358 0 : TALLOC_FREE(qlines);
8359 0 : *count = 0;
8360 0 : *info_p = NULL;
8361 0 : return result;
8362 : }
8363 :
8364 0 : *info_p = info;
8365 0 : *count = numlines;
8366 :
8367 0 : return WERR_OK;
8368 : }
8369 :
8370 : /****************************************************************************
8371 : enumports level 2.
8372 : ****************************************************************************/
8373 :
8374 0 : static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
8375 : union spoolss_PortInfo **info_p,
8376 : uint32_t *count)
8377 : {
8378 0 : union spoolss_PortInfo *info = NULL;
8379 0 : int i=0;
8380 0 : WERROR result = WERR_OK;
8381 0 : char **qlines = NULL;
8382 0 : int numlines = 0;
8383 :
8384 0 : result = enumports_hook(talloc_tos(), &numlines, &qlines );
8385 0 : if (!W_ERROR_IS_OK(result)) {
8386 0 : goto out;
8387 : }
8388 :
8389 0 : if (numlines) {
8390 0 : info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8391 0 : if (!info) {
8392 0 : DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
8393 0 : result = WERR_NOT_ENOUGH_MEMORY;
8394 0 : goto out;
8395 : }
8396 :
8397 0 : for (i=0; i<numlines; i++) {
8398 0 : DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8399 0 : result = fill_port_2(info, &info[i].info2, qlines[i]);
8400 0 : if (!W_ERROR_IS_OK(result)) {
8401 0 : goto out;
8402 : }
8403 : }
8404 : }
8405 0 : TALLOC_FREE(qlines);
8406 :
8407 0 : out:
8408 0 : if (!W_ERROR_IS_OK(result)) {
8409 0 : TALLOC_FREE(info);
8410 0 : TALLOC_FREE(qlines);
8411 0 : *count = 0;
8412 0 : *info_p = NULL;
8413 0 : return result;
8414 : }
8415 :
8416 0 : *info_p = info;
8417 0 : *count = numlines;
8418 :
8419 0 : return WERR_OK;
8420 : }
8421 :
8422 : /****************************************************************
8423 : _spoolss_EnumPorts
8424 : ****************************************************************/
8425 :
8426 0 : WERROR _spoolss_EnumPorts(struct pipes_struct *p,
8427 : struct spoolss_EnumPorts *r)
8428 : {
8429 : WERROR result;
8430 :
8431 : /* that's an [in out] buffer */
8432 :
8433 0 : if (!r->in.buffer && (r->in.offered != 0)) {
8434 0 : return WERR_INVALID_PARAMETER;
8435 : }
8436 :
8437 0 : DEBUG(4,("_spoolss_EnumPorts\n"));
8438 :
8439 0 : *r->out.count = 0;
8440 0 : *r->out.needed = 0;
8441 0 : *r->out.info = NULL;
8442 :
8443 0 : switch (r->in.level) {
8444 0 : case 1:
8445 0 : result = enumports_level_1(p->mem_ctx, r->out.info,
8446 : r->out.count);
8447 0 : break;
8448 0 : case 2:
8449 0 : result = enumports_level_2(p->mem_ctx, r->out.info,
8450 : r->out.count);
8451 0 : break;
8452 0 : default:
8453 0 : return WERR_INVALID_LEVEL;
8454 : }
8455 :
8456 0 : if (!W_ERROR_IS_OK(result)) {
8457 0 : return result;
8458 : }
8459 :
8460 0 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8461 : spoolss_EnumPorts,
8462 : *r->out.info, r->in.level,
8463 : *r->out.count);
8464 0 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8465 0 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8466 :
8467 0 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8468 : }
8469 :
8470 : /****************************************************************************
8471 : ****************************************************************************/
8472 :
8473 0 : static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
8474 : const char *server,
8475 : struct spoolss_SetPrinterInfoCtr *info_ctr,
8476 : struct spoolss_DeviceMode *devmode,
8477 : struct security_descriptor *secdesc,
8478 : struct spoolss_UserLevelCtr *user_ctr,
8479 : struct policy_handle *handle)
8480 : {
8481 0 : struct dcesrv_call_state *dce_call = p->dce_call;
8482 0 : struct dcesrv_connection *dcesrv_conn = dce_call->conn;
8483 0 : const struct tsocket_address *remote_address =
8484 0 : dcesrv_connection_get_remote_address(dcesrv_conn);
8485 0 : struct auth_session_info *session_info =
8486 0 : dcesrv_call_session_info(dce_call);
8487 0 : struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8488 0 : uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8489 0 : const struct loadparm_substitution *lp_sub =
8490 0 : loadparm_s3_global_substitution();
8491 : int snum;
8492 0 : WERROR err = WERR_OK;
8493 :
8494 : /* samba does not have a concept of local, non-shared printers yet, so
8495 : * make sure we always setup sharename - gd */
8496 0 : if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8497 0 : (info2->printername != NULL && info2->printername[0] != '\0')) {
8498 0 : DEBUG(5, ("spoolss_addprinterex_level_2: "
8499 : "no sharename has been set, setting printername %s as sharename\n",
8500 : info2->printername));
8501 0 : info2->sharename = info2->printername;
8502 : }
8503 :
8504 : /* check to see if the printer already exists */
8505 0 : if ((snum = print_queue_snum(info2->sharename)) != -1) {
8506 0 : DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8507 : info2->sharename));
8508 0 : return WERR_PRINTER_ALREADY_EXISTS;
8509 : }
8510 :
8511 0 : if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8512 0 : if ((snum = print_queue_snum(info2->printername)) != -1) {
8513 0 : DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8514 : info2->printername));
8515 0 : return WERR_PRINTER_ALREADY_EXISTS;
8516 : }
8517 : }
8518 :
8519 : /* validate printer info struct */
8520 0 : if (!info2->printername || strlen(info2->printername) == 0) {
8521 0 : return WERR_INVALID_PRINTER_NAME;
8522 : }
8523 0 : if (!info2->portname || strlen(info2->portname) == 0) {
8524 0 : return WERR_UNKNOWN_PORT;
8525 : }
8526 0 : if (!info2->drivername || strlen(info2->drivername) == 0) {
8527 0 : return WERR_UNKNOWN_PRINTER_DRIVER;
8528 : }
8529 0 : if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8530 0 : return WERR_UNKNOWN_PRINTPROCESSOR;
8531 : }
8532 :
8533 : /* FIXME!!! smbd should check to see if the driver is installed before
8534 : trying to add a printer like this --jerry */
8535 :
8536 0 : if (*lp_addprinter_command(talloc_tos(), lp_sub) ) {
8537 : char *raddr;
8538 :
8539 0 : raddr = tsocket_address_inet_addr_string(remote_address,
8540 : p->mem_ctx);
8541 0 : if (raddr == NULL) {
8542 0 : return WERR_NOT_ENOUGH_MEMORY;
8543 : }
8544 :
8545 0 : if ( !add_printer_hook(p->mem_ctx, session_info->security_token,
8546 : info2, raddr,
8547 : p->msg_ctx) ) {
8548 0 : return WERR_ACCESS_DENIED;
8549 : }
8550 : } else {
8551 0 : DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8552 : "smb.conf parameter \"addprinter command\" is defined. This "
8553 : "parameter must exist for this call to succeed\n",
8554 : info2->sharename ));
8555 : }
8556 :
8557 0 : if ((snum = print_queue_snum(info2->sharename)) == -1) {
8558 0 : return WERR_ACCESS_DENIED;
8559 : }
8560 :
8561 : /* you must be a printer admin to add a new printer */
8562 0 : if (!W_ERROR_IS_OK(print_access_check(session_info,
8563 : p->msg_ctx,
8564 : snum,
8565 : PRINTER_ACCESS_ADMINISTER))) {
8566 0 : return WERR_ACCESS_DENIED;
8567 : }
8568 :
8569 : /*
8570 : * Do sanity check on the requested changes for Samba.
8571 : */
8572 :
8573 0 : if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8574 0 : return WERR_INVALID_PARAMETER;
8575 : }
8576 :
8577 0 : if (devmode == NULL) {
8578 0 : info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8579 : }
8580 :
8581 0 : err = update_dsspooler(p->mem_ctx,
8582 : get_session_info_system(),
8583 : p->msg_ctx,
8584 : 0,
8585 : info2,
8586 : NULL);
8587 0 : if (!W_ERROR_IS_OK(err)) {
8588 0 : return err;
8589 : }
8590 :
8591 0 : err = winreg_update_printer_internal(p->mem_ctx,
8592 : get_session_info_system(),
8593 : p->msg_ctx,
8594 : info2->sharename,
8595 : info2_mask,
8596 : info2,
8597 : devmode,
8598 : secdesc);
8599 0 : if (!W_ERROR_IS_OK(err)) {
8600 0 : return err;
8601 : }
8602 :
8603 0 : err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8604 0 : if (!W_ERROR_IS_OK(err)) {
8605 : /* Handle open failed - remove addition. */
8606 0 : ZERO_STRUCTP(handle);
8607 0 : return err;
8608 : }
8609 :
8610 0 : return WERR_OK;
8611 : }
8612 :
8613 : /****************************************************************
8614 : _spoolss_AddPrinterEx
8615 : ****************************************************************/
8616 :
8617 0 : WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8618 : struct spoolss_AddPrinterEx *r)
8619 : {
8620 0 : switch (r->in.info_ctr->level) {
8621 0 : case 1:
8622 : /* we don't handle yet */
8623 : /* but I know what to do ... */
8624 0 : return WERR_INVALID_LEVEL;
8625 0 : case 2:
8626 0 : return spoolss_addprinterex_level_2(p, r->in.server,
8627 : r->in.info_ctr,
8628 0 : r->in.devmode_ctr->devmode,
8629 0 : r->in.secdesc_ctr->sd,
8630 : r->in.userlevel_ctr,
8631 : r->out.handle);
8632 0 : default:
8633 0 : return WERR_INVALID_LEVEL;
8634 : }
8635 : }
8636 :
8637 : /****************************************************************
8638 : _spoolss_AddPrinter
8639 : ****************************************************************/
8640 :
8641 0 : WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8642 : struct spoolss_AddPrinter *r)
8643 : {
8644 : struct spoolss_AddPrinterEx a;
8645 : struct spoolss_UserLevelCtr userlevel_ctr;
8646 :
8647 0 : ZERO_STRUCT(userlevel_ctr);
8648 :
8649 0 : userlevel_ctr.level = 1;
8650 :
8651 0 : a.in.server = r->in.server;
8652 0 : a.in.info_ctr = r->in.info_ctr;
8653 0 : a.in.devmode_ctr = r->in.devmode_ctr;
8654 0 : a.in.secdesc_ctr = r->in.secdesc_ctr;
8655 0 : a.in.userlevel_ctr = &userlevel_ctr;
8656 0 : a.out.handle = r->out.handle;
8657 :
8658 0 : return _spoolss_AddPrinterEx(p, &a);
8659 : }
8660 :
8661 : /****************************************************************
8662 : _spoolss_AddPrinterDriverEx
8663 : ****************************************************************/
8664 :
8665 0 : WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8666 : struct spoolss_AddPrinterDriverEx *r)
8667 : {
8668 0 : struct dcesrv_call_state *dce_call = p->dce_call;
8669 0 : struct auth_session_info *session_info =
8670 0 : dcesrv_call_session_info(dce_call);
8671 0 : WERROR err = WERR_OK;
8672 0 : const char *driver_name = NULL;
8673 0 : const char *driver_directory = NULL;
8674 : uint32_t version;
8675 :
8676 : /*
8677 : * we only support the semantics of AddPrinterDriver()
8678 : * i.e. only copy files that are newer than existing ones
8679 : */
8680 :
8681 0 : if (r->in.flags == 0) {
8682 0 : return WERR_INVALID_PARAMETER;
8683 : }
8684 :
8685 0 : if (!(r->in.flags & APD_COPY_ALL_FILES) &&
8686 0 : !(r->in.flags & APD_COPY_NEW_FILES)) {
8687 0 : return WERR_ACCESS_DENIED;
8688 : }
8689 :
8690 : /* FIXME */
8691 0 : if (r->in.info_ctr->level != 3 &&
8692 0 : r->in.info_ctr->level != 6 &&
8693 0 : r->in.info_ctr->level != 8) {
8694 0 : DEBUG(0,("%s: level %d not yet implemented\n", __func__,
8695 : r->in.info_ctr->level));
8696 0 : return WERR_INVALID_LEVEL;
8697 : }
8698 :
8699 0 : DEBUG(5,("Cleaning driver's information\n"));
8700 0 : err = clean_up_driver_struct(p->mem_ctx,
8701 : session_info,
8702 0 : r->in.info_ctr,
8703 : r->in.flags,
8704 : &driver_directory);
8705 0 : if (!W_ERROR_IS_OK(err)) {
8706 0 : DBG_ERR("clean_up_driver_struct failed - %s\n",
8707 : win_errstr(err));
8708 0 : goto done;
8709 : }
8710 :
8711 0 : DEBUG(5,("Moving driver to final destination\n"));
8712 0 : err = move_driver_to_download_area(session_info,
8713 0 : r->in.info_ctr,
8714 : driver_directory);
8715 0 : if (!W_ERROR_IS_OK(err)) {
8716 0 : DBG_ERR("move_driver_to_download_area failed - %s\n",
8717 : win_errstr(err));
8718 0 : goto done;
8719 : }
8720 :
8721 0 : err = winreg_add_driver_internal(p->mem_ctx,
8722 : get_session_info_system(),
8723 : p->msg_ctx,
8724 : r->in.info_ctr,
8725 : &driver_name,
8726 : &version);
8727 0 : if (!W_ERROR_IS_OK(err)) {
8728 0 : DBG_ERR("winreg_add_driver_internal failed - %s\n",
8729 : win_errstr(err));
8730 0 : goto done;
8731 : }
8732 :
8733 : /*
8734 : * I think this is where he DrvUpgradePrinter() hook would be
8735 : * be called in a driver's interface DLL on a Windows NT 4.0/2k
8736 : * server. Right now, we just need to send ourselves a message
8737 : * to update each printer bound to this driver. --jerry
8738 : */
8739 :
8740 0 : if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8741 0 : DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8742 : __func__, driver_name));
8743 : }
8744 :
8745 0 : done:
8746 0 : return err;
8747 : }
8748 :
8749 : /****************************************************************
8750 : _spoolss_AddPrinterDriver
8751 : ****************************************************************/
8752 :
8753 0 : WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8754 : struct spoolss_AddPrinterDriver *r)
8755 : {
8756 : struct spoolss_AddPrinterDriverEx a;
8757 :
8758 0 : switch (r->in.info_ctr->level) {
8759 0 : case 2:
8760 : case 3:
8761 : case 4:
8762 : case 5:
8763 0 : break;
8764 0 : default:
8765 0 : return WERR_INVALID_LEVEL;
8766 : }
8767 :
8768 0 : a.in.servername = r->in.servername;
8769 0 : a.in.info_ctr = r->in.info_ctr;
8770 0 : a.in.flags = APD_COPY_NEW_FILES;
8771 :
8772 0 : return _spoolss_AddPrinterDriverEx(p, &a);
8773 : }
8774 :
8775 : /****************************************************************************
8776 : ****************************************************************************/
8777 :
8778 : struct _spoolss_paths {
8779 : int type;
8780 : const char *share;
8781 : const char *dir;
8782 : };
8783 :
8784 : enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8785 :
8786 : static const struct _spoolss_paths spoolss_paths[]= {
8787 : { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8788 : { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8789 : };
8790 :
8791 0 : static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8792 : const char *servername,
8793 : const char *environment,
8794 : int component,
8795 : char **path)
8796 : {
8797 0 : const char *pservername = NULL;
8798 : const char *long_archi;
8799 : const char *short_archi;
8800 :
8801 0 : *path = NULL;
8802 :
8803 : /* environment may be empty */
8804 0 : if (environment && strlen(environment)) {
8805 0 : long_archi = environment;
8806 : } else {
8807 0 : long_archi = lp_parm_const_string(GLOBAL_SECTION_SNUM,
8808 : "spoolss", "architecture",
8809 : GLOBAL_SPOOLSS_ARCHITECTURE);
8810 : }
8811 :
8812 : /* servername may be empty */
8813 0 : if (servername && strlen(servername)) {
8814 0 : pservername = canon_servername(servername);
8815 :
8816 0 : if (!is_myname_or_ipaddr(pservername)) {
8817 0 : return WERR_INVALID_PARAMETER;
8818 : }
8819 : }
8820 :
8821 0 : if (!(short_archi = get_short_archi(long_archi))) {
8822 0 : return WERR_INVALID_ENVIRONMENT;
8823 : }
8824 :
8825 0 : switch (component) {
8826 0 : case SPOOLSS_PRTPROCS_PATH:
8827 : case SPOOLSS_DRIVER_PATH:
8828 0 : if (pservername) {
8829 0 : *path = talloc_asprintf(mem_ctx,
8830 : "\\\\%s\\%s\\%s",
8831 : pservername,
8832 0 : spoolss_paths[component].share,
8833 : short_archi);
8834 : } else {
8835 0 : *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8836 : SPOOLSS_DEFAULT_SERVER_PATH,
8837 0 : spoolss_paths[component].dir,
8838 : short_archi);
8839 : }
8840 0 : break;
8841 0 : default:
8842 0 : return WERR_INVALID_PARAMETER;
8843 : }
8844 :
8845 0 : if (!*path) {
8846 0 : return WERR_NOT_ENOUGH_MEMORY;
8847 : }
8848 :
8849 0 : return WERR_OK;
8850 : }
8851 :
8852 : /****************************************************************************
8853 : ****************************************************************************/
8854 :
8855 0 : static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8856 : const char *servername,
8857 : const char *environment,
8858 : struct spoolss_DriverDirectoryInfo1 *r)
8859 : {
8860 : WERROR werr;
8861 0 : char *path = NULL;
8862 :
8863 0 : werr = compose_spoolss_server_path(mem_ctx,
8864 : servername,
8865 : environment,
8866 : SPOOLSS_DRIVER_PATH,
8867 : &path);
8868 0 : if (!W_ERROR_IS_OK(werr)) {
8869 0 : return werr;
8870 : }
8871 :
8872 0 : DEBUG(4,("printer driver directory: [%s]\n", path));
8873 :
8874 0 : r->directory_name = path;
8875 :
8876 0 : return WERR_OK;
8877 : }
8878 :
8879 : /****************************************************************
8880 : _spoolss_GetPrinterDriverDirectory
8881 : ****************************************************************/
8882 :
8883 0 : WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8884 : struct spoolss_GetPrinterDriverDirectory *r)
8885 : {
8886 : WERROR werror;
8887 :
8888 : /* that's an [in out] buffer */
8889 :
8890 0 : if (!r->in.buffer && (r->in.offered != 0)) {
8891 0 : TALLOC_FREE(r->out.info);
8892 0 : return WERR_INVALID_PARAMETER;
8893 : }
8894 :
8895 0 : DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8896 : r->in.level));
8897 :
8898 0 : *r->out.needed = 0;
8899 :
8900 : /* r->in.level is ignored */
8901 :
8902 0 : werror = getprinterdriverdir_level_1(p->mem_ctx,
8903 : r->in.server,
8904 : r->in.environment,
8905 0 : &r->out.info->info1);
8906 0 : if (!W_ERROR_IS_OK(werror)) {
8907 0 : TALLOC_FREE(r->out.info);
8908 0 : return werror;
8909 : }
8910 :
8911 0 : *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8912 : r->out.info, r->in.level);
8913 0 : r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8914 :
8915 0 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8916 : }
8917 :
8918 : /****************************************************************
8919 : _spoolss_EnumPrinterData
8920 : ****************************************************************/
8921 :
8922 0 : WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8923 : struct spoolss_EnumPrinterData *r)
8924 : {
8925 : WERROR result;
8926 : struct spoolss_EnumPrinterDataEx r2;
8927 : uint32_t count;
8928 0 : struct spoolss_PrinterEnumValues *info, *val = NULL;
8929 : uint32_t needed;
8930 :
8931 0 : r2.in.handle = r->in.handle;
8932 0 : r2.in.key_name = "PrinterDriverData";
8933 0 : r2.in.offered = 0;
8934 0 : r2.out.count = &count;
8935 0 : r2.out.info = &info;
8936 0 : r2.out.needed = &needed;
8937 :
8938 0 : result = _spoolss_EnumPrinterDataEx(p, &r2);
8939 0 : if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8940 0 : r2.in.offered = needed;
8941 0 : result = _spoolss_EnumPrinterDataEx(p, &r2);
8942 : }
8943 0 : if (!W_ERROR_IS_OK(result)) {
8944 0 : return result;
8945 : }
8946 :
8947 : /*
8948 : * The NT machine wants to know the biggest size of value and data
8949 : *
8950 : * cf: MSDN EnumPrinterData remark section
8951 : */
8952 :
8953 0 : if (!r->in.value_offered && !r->in.data_offered) {
8954 0 : uint32_t biggest_valuesize = 0;
8955 0 : uint32_t biggest_datasize = 0;
8956 : int i, name_length;
8957 :
8958 0 : DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8959 :
8960 0 : for (i=0; i<count; i++) {
8961 :
8962 0 : name_length = strlen(info[i].value_name);
8963 0 : if (strlen(info[i].value_name) > biggest_valuesize) {
8964 0 : biggest_valuesize = name_length;
8965 : }
8966 :
8967 0 : if (info[i].data_length > biggest_datasize) {
8968 0 : biggest_datasize = info[i].data_length;
8969 : }
8970 :
8971 0 : DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8972 : biggest_datasize));
8973 : }
8974 :
8975 : /* the value is an UNICODE string but real_value_size is the length
8976 : in bytes including the trailing 0 */
8977 :
8978 0 : *r->out.value_needed = 2 * (1 + biggest_valuesize);
8979 0 : *r->out.data_needed = biggest_datasize;
8980 :
8981 0 : DEBUG(6,("final values: [%d], [%d]\n",
8982 : *r->out.value_needed, *r->out.data_needed));
8983 :
8984 0 : return WERR_OK;
8985 : }
8986 :
8987 0 : if (r->in.enum_index < count) {
8988 0 : val = &info[r->in.enum_index];
8989 : }
8990 :
8991 0 : if (val == NULL) {
8992 : /* out_value should default to "" or else NT4 has
8993 : problems unmarshalling the response */
8994 :
8995 0 : if (r->in.value_offered) {
8996 0 : *r->out.value_needed = 1;
8997 0 : r->out.value_name = talloc_strdup(r, "");
8998 0 : if (!r->out.value_name) {
8999 0 : return WERR_NOT_ENOUGH_MEMORY;
9000 : }
9001 : } else {
9002 0 : r->out.value_name = NULL;
9003 0 : *r->out.value_needed = 0;
9004 : }
9005 :
9006 : /* the data is counted in bytes */
9007 :
9008 0 : *r->out.data_needed = r->in.data_offered;
9009 :
9010 0 : result = WERR_NO_MORE_ITEMS;
9011 : } else {
9012 : /*
9013 : * the value is:
9014 : * - counted in bytes in the request
9015 : * - counted in UNICODE chars in the max reply
9016 : * - counted in bytes in the real size
9017 : *
9018 : * take a pause *before* coding not *during* coding
9019 : */
9020 :
9021 : /* name */
9022 0 : if (r->in.value_offered) {
9023 0 : r->out.value_name = talloc_strdup(r, val->value_name);
9024 0 : if (!r->out.value_name) {
9025 0 : return WERR_NOT_ENOUGH_MEMORY;
9026 : }
9027 0 : *r->out.value_needed = val->value_name_len;
9028 : } else {
9029 0 : r->out.value_name = NULL;
9030 0 : *r->out.value_needed = 0;
9031 : }
9032 :
9033 : /* type */
9034 :
9035 0 : *r->out.type = val->type;
9036 :
9037 : /* data - counted in bytes */
9038 :
9039 : /*
9040 : * See the section "Dynamically Typed Query Parameters"
9041 : * in MS-RPRN.
9042 : */
9043 :
9044 0 : if (r->out.data && val->data && val->data->data &&
9045 0 : val->data_length && r->in.data_offered) {
9046 0 : memcpy(r->out.data, val->data->data,
9047 0 : MIN(val->data_length,r->in.data_offered));
9048 : }
9049 :
9050 0 : *r->out.data_needed = val->data_length;
9051 :
9052 0 : result = WERR_OK;
9053 : }
9054 :
9055 0 : return result;
9056 : }
9057 :
9058 : /****************************************************************
9059 : _spoolss_SetPrinterData
9060 : ****************************************************************/
9061 :
9062 0 : WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
9063 : struct spoolss_SetPrinterData *r)
9064 : {
9065 : struct spoolss_SetPrinterDataEx r2;
9066 :
9067 0 : r2.in.handle = r->in.handle;
9068 0 : r2.in.key_name = "PrinterDriverData";
9069 0 : r2.in.value_name = r->in.value_name;
9070 0 : r2.in.type = r->in.type;
9071 0 : r2.in.data = r->in.data;
9072 0 : r2.in.offered = r->in.offered;
9073 :
9074 0 : return _spoolss_SetPrinterDataEx(p, &r2);
9075 : }
9076 :
9077 : /****************************************************************
9078 : _spoolss_ResetPrinter
9079 : ****************************************************************/
9080 :
9081 0 : WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
9082 : struct spoolss_ResetPrinter *r)
9083 : {
9084 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9085 : int snum;
9086 :
9087 0 : DEBUG(5,("_spoolss_ResetPrinter\n"));
9088 :
9089 : /*
9090 : * All we do is to check to see if the handle and queue is valid.
9091 : * This call really doesn't mean anything to us because we only
9092 : * support RAW printing. --jerry
9093 : */
9094 :
9095 0 : if (!Printer) {
9096 0 : DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
9097 : OUR_HANDLE(r->in.handle)));
9098 0 : return WERR_INVALID_HANDLE;
9099 : }
9100 :
9101 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9102 0 : return WERR_INVALID_HANDLE;
9103 :
9104 :
9105 : /* blindly return success */
9106 0 : return WERR_OK;
9107 : }
9108 :
9109 : /****************************************************************
9110 : _spoolss_DeletePrinterData
9111 : ****************************************************************/
9112 :
9113 0 : WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
9114 : struct spoolss_DeletePrinterData *r)
9115 : {
9116 : struct spoolss_DeletePrinterDataEx r2;
9117 :
9118 0 : r2.in.handle = r->in.handle;
9119 0 : r2.in.key_name = "PrinterDriverData";
9120 0 : r2.in.value_name = r->in.value_name;
9121 :
9122 0 : return _spoolss_DeletePrinterDataEx(p, &r2);
9123 : }
9124 :
9125 : /****************************************************************
9126 : _spoolss_AddForm
9127 : ****************************************************************/
9128 :
9129 0 : WERROR _spoolss_AddForm(struct pipes_struct *p,
9130 : struct spoolss_AddForm *r)
9131 : {
9132 0 : struct dcesrv_call_state *dce_call = p->dce_call;
9133 0 : struct auth_session_info *session_info =
9134 0 : dcesrv_call_session_info(dce_call);
9135 : struct spoolss_AddFormInfo1 *form;
9136 0 : int snum = -1;
9137 0 : WERROR status = WERR_OK;
9138 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9139 : struct dcerpc_binding_handle *b;
9140 0 : TALLOC_CTX *tmp_ctx = NULL;
9141 :
9142 0 : DEBUG(5,("_spoolss_AddForm\n"));
9143 :
9144 0 : if (!Printer) {
9145 0 : DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
9146 : OUR_HANDLE(r->in.handle)));
9147 0 : return WERR_INVALID_HANDLE;
9148 : }
9149 :
9150 : /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
9151 : and not a printer admin, then fail */
9152 :
9153 0 : if ((session_info->unix_token->uid != sec_initial_uid()) &&
9154 0 : !security_token_has_privilege(session_info->security_token,
9155 : SEC_PRIV_PRINT_OPERATOR)) {
9156 0 : DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
9157 0 : return WERR_ACCESS_DENIED;
9158 : }
9159 :
9160 0 : if (r->in.info_ctr->level != 1) {
9161 0 : return WERR_INVALID_LEVEL;
9162 : }
9163 :
9164 0 : form = r->in.info_ctr->info.info1;
9165 0 : if (!form) {
9166 0 : return WERR_INVALID_PARAMETER;
9167 : }
9168 :
9169 0 : switch (form->flags) {
9170 0 : case SPOOLSS_FORM_USER:
9171 : case SPOOLSS_FORM_BUILTIN:
9172 : case SPOOLSS_FORM_PRINTER:
9173 0 : break;
9174 0 : default:
9175 0 : return WERR_INVALID_PARAMETER;
9176 : }
9177 :
9178 0 : tmp_ctx = talloc_new(p->mem_ctx);
9179 0 : if (!tmp_ctx) {
9180 0 : return WERR_NOT_ENOUGH_MEMORY;
9181 : }
9182 :
9183 0 : status = winreg_printer_binding_handle(tmp_ctx,
9184 : get_session_info_system(),
9185 : p->msg_ctx,
9186 : &b);
9187 0 : if (!W_ERROR_IS_OK(status)) {
9188 0 : goto done;
9189 : }
9190 :
9191 0 : status = winreg_printer_addform1(tmp_ctx, b, form);
9192 0 : if (!W_ERROR_IS_OK(status)) {
9193 0 : goto done;
9194 : }
9195 :
9196 : /*
9197 : * ChangeID must always be set if this is a printer
9198 : */
9199 0 : if (Printer->printer_type == SPLHND_PRINTER) {
9200 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9201 0 : status = WERR_INVALID_HANDLE;
9202 0 : goto done;
9203 : }
9204 :
9205 0 : status = winreg_printer_update_changeid(tmp_ctx, b,
9206 : lp_const_servicename(snum));
9207 : }
9208 :
9209 0 : done:
9210 0 : talloc_free(tmp_ctx);
9211 0 : return status;
9212 : }
9213 :
9214 : /****************************************************************
9215 : _spoolss_DeleteForm
9216 : ****************************************************************/
9217 :
9218 0 : WERROR _spoolss_DeleteForm(struct pipes_struct *p,
9219 : struct spoolss_DeleteForm *r)
9220 : {
9221 0 : struct dcesrv_call_state *dce_call = p->dce_call;
9222 0 : struct auth_session_info *session_info =
9223 0 : dcesrv_call_session_info(dce_call);
9224 0 : const char *form_name = r->in.form_name;
9225 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9226 0 : int snum = -1;
9227 0 : WERROR status = WERR_OK;
9228 : struct dcerpc_binding_handle *b;
9229 0 : TALLOC_CTX *tmp_ctx = NULL;
9230 :
9231 0 : DEBUG(5,("_spoolss_DeleteForm\n"));
9232 :
9233 0 : if (!Printer) {
9234 0 : DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
9235 : OUR_HANDLE(r->in.handle)));
9236 0 : return WERR_INVALID_HANDLE;
9237 : }
9238 :
9239 0 : if ((session_info->unix_token->uid != sec_initial_uid()) &&
9240 0 : !security_token_has_privilege(session_info->security_token,
9241 : SEC_PRIV_PRINT_OPERATOR)) {
9242 0 : DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
9243 0 : return WERR_ACCESS_DENIED;
9244 : }
9245 :
9246 0 : tmp_ctx = talloc_new(p->mem_ctx);
9247 0 : if (!tmp_ctx) {
9248 0 : return WERR_NOT_ENOUGH_MEMORY;
9249 : }
9250 :
9251 0 : status = winreg_printer_binding_handle(tmp_ctx,
9252 : get_session_info_system(),
9253 : p->msg_ctx,
9254 : &b);
9255 0 : if (!W_ERROR_IS_OK(status)) {
9256 0 : goto done;
9257 : }
9258 :
9259 0 : status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
9260 0 : if (!W_ERROR_IS_OK(status)) {
9261 0 : goto done;
9262 : }
9263 :
9264 : /*
9265 : * ChangeID must always be set if this is a printer
9266 : */
9267 0 : if (Printer->printer_type == SPLHND_PRINTER) {
9268 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9269 0 : status = WERR_INVALID_HANDLE;
9270 0 : goto done;
9271 : }
9272 :
9273 0 : status = winreg_printer_update_changeid(tmp_ctx, b,
9274 : lp_const_servicename(snum));
9275 : }
9276 :
9277 0 : done:
9278 0 : talloc_free(tmp_ctx);
9279 0 : return status;
9280 : }
9281 :
9282 : /****************************************************************
9283 : _spoolss_SetForm
9284 : ****************************************************************/
9285 :
9286 0 : WERROR _spoolss_SetForm(struct pipes_struct *p,
9287 : struct spoolss_SetForm *r)
9288 : {
9289 0 : struct dcesrv_call_state *dce_call = p->dce_call;
9290 0 : struct auth_session_info *session_info =
9291 0 : dcesrv_call_session_info(dce_call);
9292 : struct spoolss_AddFormInfo1 *form;
9293 0 : const char *form_name = r->in.form_name;
9294 0 : int snum = -1;
9295 0 : WERROR status = WERR_OK;
9296 : struct dcerpc_binding_handle *b;
9297 0 : TALLOC_CTX *tmp_ctx = NULL;
9298 :
9299 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9300 :
9301 0 : DEBUG(5,("_spoolss_SetForm\n"));
9302 :
9303 0 : if (!Printer) {
9304 0 : DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
9305 : OUR_HANDLE(r->in.handle)));
9306 0 : return WERR_INVALID_HANDLE;
9307 : }
9308 :
9309 : /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
9310 : and not a printer admin, then fail */
9311 :
9312 0 : if ((session_info->unix_token->uid != sec_initial_uid()) &&
9313 0 : !security_token_has_privilege(session_info->security_token,
9314 : SEC_PRIV_PRINT_OPERATOR)) {
9315 0 : DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
9316 0 : return WERR_ACCESS_DENIED;
9317 : }
9318 :
9319 0 : if (r->in.info_ctr->level != 1) {
9320 0 : return WERR_INVALID_LEVEL;
9321 : }
9322 :
9323 0 : form = r->in.info_ctr->info.info1;
9324 0 : if (!form) {
9325 0 : return WERR_INVALID_PARAMETER;
9326 : }
9327 :
9328 0 : tmp_ctx = talloc_new(p->mem_ctx);
9329 0 : if (!tmp_ctx) {
9330 0 : return WERR_NOT_ENOUGH_MEMORY;
9331 : }
9332 :
9333 0 : status = winreg_printer_binding_handle(tmp_ctx,
9334 : get_session_info_system(),
9335 : p->msg_ctx,
9336 : &b);
9337 0 : if (!W_ERROR_IS_OK(status)) {
9338 0 : goto done;
9339 : }
9340 :
9341 0 : status = winreg_printer_setform1(tmp_ctx, b,
9342 : form_name,
9343 : form);
9344 0 : if (!W_ERROR_IS_OK(status)) {
9345 0 : goto done;
9346 : }
9347 :
9348 : /*
9349 : * ChangeID must always be set if this is a printer
9350 : */
9351 0 : if (Printer->printer_type == SPLHND_PRINTER) {
9352 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9353 0 : status = WERR_INVALID_HANDLE;
9354 0 : goto done;
9355 : }
9356 :
9357 0 : status = winreg_printer_update_changeid(tmp_ctx, b,
9358 : lp_const_servicename(snum));
9359 : }
9360 :
9361 0 : done:
9362 0 : talloc_free(tmp_ctx);
9363 0 : return status;
9364 : }
9365 :
9366 : /****************************************************************************
9367 : fill_print_processor1
9368 : ****************************************************************************/
9369 :
9370 0 : static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
9371 : struct spoolss_PrintProcessorInfo1 *r,
9372 : const char *print_processor_name)
9373 : {
9374 0 : r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
9375 0 : W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
9376 :
9377 0 : return WERR_OK;
9378 : }
9379 :
9380 : /****************************************************************************
9381 : enumprintprocessors level 1.
9382 : ****************************************************************************/
9383 :
9384 0 : static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
9385 : union spoolss_PrintProcessorInfo **info_p,
9386 : uint32_t *count)
9387 : {
9388 : union spoolss_PrintProcessorInfo *info;
9389 : WERROR result;
9390 :
9391 0 : info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
9392 0 : W_ERROR_HAVE_NO_MEMORY(info);
9393 :
9394 0 : *count = 1;
9395 :
9396 0 : result = fill_print_processor1(info, &info[0].info1, "winprint");
9397 0 : if (!W_ERROR_IS_OK(result)) {
9398 0 : goto out;
9399 : }
9400 :
9401 0 : out:
9402 0 : if (!W_ERROR_IS_OK(result)) {
9403 0 : TALLOC_FREE(info);
9404 0 : *count = 0;
9405 0 : return result;
9406 : }
9407 :
9408 0 : *info_p = info;
9409 :
9410 0 : return WERR_OK;
9411 : }
9412 :
9413 : /****************************************************************
9414 : _spoolss_EnumPrintProcessors
9415 : ****************************************************************/
9416 :
9417 0 : WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
9418 : struct spoolss_EnumPrintProcessors *r)
9419 : {
9420 : WERROR result;
9421 :
9422 : /* that's an [in out] buffer */
9423 :
9424 0 : if (!r->in.buffer && (r->in.offered != 0)) {
9425 0 : return WERR_INVALID_PARAMETER;
9426 : }
9427 :
9428 0 : DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
9429 :
9430 : /*
9431 : * Enumerate the print processors ...
9432 : *
9433 : * Just reply with "winprint", to keep NT happy
9434 : * and I can use my nice printer checker.
9435 : */
9436 :
9437 0 : *r->out.count = 0;
9438 0 : *r->out.needed = 0;
9439 0 : *r->out.info = NULL;
9440 :
9441 0 : if (!get_short_archi(r->in.environment)) {
9442 0 : return WERR_INVALID_ENVIRONMENT;
9443 : }
9444 :
9445 0 : switch (r->in.level) {
9446 0 : case 1:
9447 0 : result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
9448 : r->out.count);
9449 0 : break;
9450 0 : default:
9451 0 : return WERR_INVALID_LEVEL;
9452 : }
9453 :
9454 0 : if (!W_ERROR_IS_OK(result)) {
9455 0 : return result;
9456 : }
9457 :
9458 0 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9459 : spoolss_EnumPrintProcessors,
9460 : *r->out.info, r->in.level,
9461 : *r->out.count);
9462 0 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9463 0 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9464 :
9465 0 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9466 : }
9467 :
9468 : /****************************************************************************
9469 : fill_printprocdatatype1
9470 : ****************************************************************************/
9471 :
9472 0 : static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
9473 : struct spoolss_PrintProcDataTypesInfo1 *r,
9474 : const char *name_array)
9475 : {
9476 0 : r->name_array = talloc_strdup(mem_ctx, name_array);
9477 0 : W_ERROR_HAVE_NO_MEMORY(r->name_array);
9478 :
9479 0 : return WERR_OK;
9480 : }
9481 :
9482 : /****************************************************************************
9483 : enumprintprocdatatypes level 1.
9484 : ****************************************************************************/
9485 :
9486 0 : static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
9487 : union spoolss_PrintProcDataTypesInfo **info_p,
9488 : uint32_t *count)
9489 : {
9490 : WERROR result;
9491 : union spoolss_PrintProcDataTypesInfo *info;
9492 :
9493 0 : info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
9494 0 : W_ERROR_HAVE_NO_MEMORY(info);
9495 :
9496 0 : *count = 1;
9497 :
9498 0 : result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9499 0 : if (!W_ERROR_IS_OK(result)) {
9500 0 : goto out;
9501 : }
9502 :
9503 0 : out:
9504 0 : if (!W_ERROR_IS_OK(result)) {
9505 0 : TALLOC_FREE(info);
9506 0 : *count = 0;
9507 0 : return result;
9508 : }
9509 :
9510 0 : *info_p = info;
9511 :
9512 0 : return WERR_OK;
9513 : }
9514 :
9515 : /****************************************************************
9516 : _spoolss_EnumPrintProcessorDataTypes
9517 : ****************************************************************/
9518 :
9519 0 : WERROR _spoolss_EnumPrintProcessorDataTypes(struct pipes_struct *p,
9520 : struct spoolss_EnumPrintProcessorDataTypes *r)
9521 : {
9522 : WERROR result;
9523 :
9524 : /* that's an [in out] buffer */
9525 :
9526 0 : if (!r->in.buffer && (r->in.offered != 0)) {
9527 0 : return WERR_INVALID_PARAMETER;
9528 : }
9529 :
9530 0 : DEBUG(5,("_spoolss_EnumPrintProcessorDataTypes\n"));
9531 :
9532 0 : *r->out.count = 0;
9533 0 : *r->out.needed = 0;
9534 0 : *r->out.info = NULL;
9535 :
9536 0 : if (r->in.print_processor_name == NULL ||
9537 0 : !strequal(r->in.print_processor_name, "winprint")) {
9538 0 : return WERR_UNKNOWN_PRINTPROCESSOR;
9539 : }
9540 :
9541 0 : switch (r->in.level) {
9542 0 : case 1:
9543 0 : result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9544 : r->out.count);
9545 0 : break;
9546 0 : default:
9547 0 : return WERR_INVALID_LEVEL;
9548 : }
9549 :
9550 0 : if (!W_ERROR_IS_OK(result)) {
9551 0 : return result;
9552 : }
9553 :
9554 0 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9555 : spoolss_EnumPrintProcessorDataTypes,
9556 : *r->out.info, r->in.level,
9557 : *r->out.count);
9558 0 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9559 0 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9560 :
9561 0 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9562 : }
9563 :
9564 : /****************************************************************************
9565 : fill_monitor_1
9566 : ****************************************************************************/
9567 :
9568 0 : static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9569 : struct spoolss_MonitorInfo1 *r,
9570 : const char *monitor_name)
9571 : {
9572 0 : r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9573 0 : W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9574 :
9575 0 : return WERR_OK;
9576 : }
9577 :
9578 : /****************************************************************************
9579 : fill_monitor_2
9580 : ****************************************************************************/
9581 :
9582 0 : static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9583 : struct spoolss_MonitorInfo2 *r,
9584 : const char *monitor_name,
9585 : const char *environment,
9586 : const char *dll_name)
9587 : {
9588 0 : r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9589 0 : W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9590 0 : r->environment = talloc_strdup(mem_ctx, environment);
9591 0 : W_ERROR_HAVE_NO_MEMORY(r->environment);
9592 0 : r->dll_name = talloc_strdup(mem_ctx, dll_name);
9593 0 : W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9594 :
9595 0 : return WERR_OK;
9596 : }
9597 :
9598 : /****************************************************************************
9599 : enumprintmonitors level 1.
9600 : ****************************************************************************/
9601 :
9602 0 : static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9603 : union spoolss_MonitorInfo **info_p,
9604 : uint32_t *count)
9605 : {
9606 : union spoolss_MonitorInfo *info;
9607 0 : WERROR result = WERR_OK;
9608 :
9609 0 : info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9610 0 : W_ERROR_HAVE_NO_MEMORY(info);
9611 :
9612 0 : *count = 2;
9613 :
9614 0 : result = fill_monitor_1(info, &info[0].info1,
9615 : SPL_LOCAL_PORT);
9616 0 : if (!W_ERROR_IS_OK(result)) {
9617 0 : goto out;
9618 : }
9619 :
9620 0 : result = fill_monitor_1(info, &info[1].info1,
9621 : SPL_TCPIP_PORT);
9622 0 : if (!W_ERROR_IS_OK(result)) {
9623 0 : goto out;
9624 : }
9625 :
9626 0 : out:
9627 0 : if (!W_ERROR_IS_OK(result)) {
9628 0 : TALLOC_FREE(info);
9629 0 : *count = 0;
9630 0 : return result;
9631 : }
9632 :
9633 0 : *info_p = info;
9634 :
9635 0 : return WERR_OK;
9636 : }
9637 :
9638 : /****************************************************************************
9639 : enumprintmonitors level 2.
9640 : ****************************************************************************/
9641 :
9642 0 : static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9643 : union spoolss_MonitorInfo **info_p,
9644 : uint32_t *count)
9645 : {
9646 : union spoolss_MonitorInfo *info;
9647 0 : WERROR result = WERR_OK;
9648 : const char *architecture;
9649 :
9650 0 : info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9651 0 : W_ERROR_HAVE_NO_MEMORY(info);
9652 :
9653 0 : *count = 2;
9654 :
9655 0 : architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
9656 : "spoolss",
9657 : "architecture",
9658 : GLOBAL_SPOOLSS_ARCHITECTURE);
9659 :
9660 0 : result = fill_monitor_2(info, &info[0].info2,
9661 : SPL_LOCAL_PORT,
9662 : architecture,
9663 : "localmon.dll");
9664 0 : if (!W_ERROR_IS_OK(result)) {
9665 0 : goto out;
9666 : }
9667 :
9668 0 : result = fill_monitor_2(info, &info[1].info2,
9669 : SPL_TCPIP_PORT,
9670 : architecture,
9671 : "tcpmon.dll");
9672 0 : if (!W_ERROR_IS_OK(result)) {
9673 0 : goto out;
9674 : }
9675 :
9676 0 : out:
9677 0 : if (!W_ERROR_IS_OK(result)) {
9678 0 : TALLOC_FREE(info);
9679 0 : *count = 0;
9680 0 : return result;
9681 : }
9682 :
9683 0 : *info_p = info;
9684 :
9685 0 : return WERR_OK;
9686 : }
9687 :
9688 : /****************************************************************
9689 : _spoolss_EnumMonitors
9690 : ****************************************************************/
9691 :
9692 0 : WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9693 : struct spoolss_EnumMonitors *r)
9694 : {
9695 : WERROR result;
9696 :
9697 : /* that's an [in out] buffer */
9698 :
9699 0 : if (!r->in.buffer && (r->in.offered != 0)) {
9700 0 : return WERR_INVALID_PARAMETER;
9701 : }
9702 :
9703 0 : DEBUG(5,("_spoolss_EnumMonitors\n"));
9704 :
9705 : /*
9706 : * Enumerate the print monitors ...
9707 : *
9708 : * Just reply with "Local Port", to keep NT happy
9709 : * and I can use my nice printer checker.
9710 : */
9711 :
9712 0 : *r->out.count = 0;
9713 0 : *r->out.needed = 0;
9714 0 : *r->out.info = NULL;
9715 :
9716 0 : switch (r->in.level) {
9717 0 : case 1:
9718 0 : result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9719 : r->out.count);
9720 0 : break;
9721 0 : case 2:
9722 0 : result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9723 : r->out.count);
9724 0 : break;
9725 0 : default:
9726 0 : return WERR_INVALID_LEVEL;
9727 : }
9728 :
9729 0 : if (!W_ERROR_IS_OK(result)) {
9730 0 : return result;
9731 : }
9732 :
9733 0 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9734 : spoolss_EnumMonitors,
9735 : *r->out.info, r->in.level,
9736 : *r->out.count);
9737 0 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9738 0 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9739 :
9740 0 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9741 : }
9742 :
9743 : /****************************************************************************
9744 : ****************************************************************************/
9745 :
9746 0 : static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9747 : const print_queue_struct *queue,
9748 : int count, int snum,
9749 : struct spoolss_PrinterInfo2 *pinfo2,
9750 : uint32_t jobid,
9751 : int sysjob,
9752 : struct spoolss_JobInfo1 *r)
9753 : {
9754 0 : int i = 0;
9755 0 : bool found = false;
9756 :
9757 0 : for (i=0; i<count; i++) {
9758 0 : if (queue[i].sysjob == sysjob) {
9759 0 : found = true;
9760 0 : break;
9761 : }
9762 : }
9763 :
9764 0 : if (found == false) {
9765 : /* NT treats not found as bad param... yet another bad choice */
9766 0 : return WERR_INVALID_PARAMETER;
9767 : }
9768 :
9769 0 : return fill_job_info1(mem_ctx,
9770 : r,
9771 0 : &queue[i],
9772 : jobid,
9773 : i,
9774 : snum,
9775 : pinfo2);
9776 : }
9777 :
9778 : /****************************************************************************
9779 : ****************************************************************************/
9780 :
9781 0 : static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9782 : const print_queue_struct *queue,
9783 : int count, int snum,
9784 : struct spoolss_PrinterInfo2 *pinfo2,
9785 : uint32_t jobid,
9786 : int sysjob,
9787 : struct spoolss_JobInfo2 *r)
9788 : {
9789 0 : int i = 0;
9790 0 : bool found = false;
9791 : struct spoolss_DeviceMode *devmode;
9792 : WERROR result;
9793 :
9794 0 : for (i=0; i<count; i++) {
9795 0 : if (queue[i].sysjob == sysjob) {
9796 0 : found = true;
9797 0 : break;
9798 : }
9799 : }
9800 :
9801 0 : if (found == false) {
9802 : /* NT treats not found as bad param... yet another bad
9803 : choice */
9804 0 : return WERR_INVALID_PARAMETER;
9805 : }
9806 :
9807 : /*
9808 : * if the print job does not have a DEVMODE associated with it,
9809 : * just use the one for the printer. A NULL devicemode is not
9810 : * a failure condition
9811 : */
9812 :
9813 0 : devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9814 0 : if (!devmode) {
9815 0 : result = spoolss_create_default_devmode(mem_ctx,
9816 : pinfo2->printername,
9817 : &devmode);
9818 0 : if (!W_ERROR_IS_OK(result)) {
9819 0 : DEBUG(3, ("Can't proceed w/o a devmode!"));
9820 0 : return result;
9821 : }
9822 : }
9823 :
9824 0 : return fill_job_info2(mem_ctx,
9825 : r,
9826 0 : &queue[i],
9827 : jobid,
9828 : i,
9829 : snum,
9830 : pinfo2,
9831 : devmode);
9832 : }
9833 :
9834 : /****************************************************************
9835 : _spoolss_GetJob
9836 : ****************************************************************/
9837 :
9838 0 : WERROR _spoolss_GetJob(struct pipes_struct *p,
9839 : struct spoolss_GetJob *r)
9840 : {
9841 0 : WERROR result = WERR_OK;
9842 0 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9843 : const char *svc_name;
9844 : int sysjob;
9845 : int snum;
9846 : int count;
9847 : struct tdb_print_db *pdb;
9848 0 : print_queue_struct *queue = NULL;
9849 : print_status_struct prt_status;
9850 :
9851 : /* that's an [in out] buffer */
9852 :
9853 0 : if (!r->in.buffer && (r->in.offered != 0)) {
9854 0 : result = WERR_INVALID_PARAMETER;
9855 0 : goto err_jinfo_free;
9856 : }
9857 :
9858 0 : DEBUG(5,("_spoolss_GetJob\n"));
9859 :
9860 0 : *r->out.needed = 0;
9861 :
9862 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9863 0 : result = WERR_INVALID_HANDLE;
9864 0 : goto err_jinfo_free;
9865 : }
9866 :
9867 0 : svc_name = lp_const_servicename(snum);
9868 0 : if (svc_name == NULL) {
9869 0 : result = WERR_INVALID_PARAMETER;
9870 0 : goto err_jinfo_free;
9871 : }
9872 :
9873 0 : result = winreg_get_printer_internal(p->mem_ctx,
9874 : get_session_info_system(),
9875 : p->msg_ctx,
9876 : svc_name,
9877 : &pinfo2);
9878 0 : if (!W_ERROR_IS_OK(result)) {
9879 0 : goto err_jinfo_free;
9880 : }
9881 :
9882 0 : pdb = get_print_db_byname(svc_name);
9883 0 : if (pdb == NULL) {
9884 0 : DEBUG(3, ("failed to get print db for svc %s\n", svc_name));
9885 0 : result = WERR_INVALID_PARAMETER;
9886 0 : goto err_pinfo_free;
9887 : }
9888 :
9889 0 : sysjob = jobid_to_sysjob_pdb(pdb, r->in.job_id);
9890 0 : release_print_db(pdb);
9891 0 : if (sysjob == -1) {
9892 0 : DEBUG(3, ("no sysjob for spoolss jobid %u\n", r->in.job_id));
9893 0 : result = WERR_INVALID_PARAMETER;
9894 0 : goto err_pinfo_free;
9895 : }
9896 :
9897 0 : count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9898 :
9899 0 : DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9900 : count, prt_status.status, prt_status.message));
9901 :
9902 0 : switch (r->in.level) {
9903 0 : case 1:
9904 0 : result = getjob_level_1(p->mem_ctx,
9905 : queue, count, snum, pinfo2,
9906 : r->in.job_id, sysjob,
9907 0 : &r->out.info->info1);
9908 0 : break;
9909 0 : case 2:
9910 0 : result = getjob_level_2(p->mem_ctx,
9911 : queue, count, snum, pinfo2,
9912 : r->in.job_id, sysjob,
9913 0 : &r->out.info->info2);
9914 0 : break;
9915 0 : default:
9916 0 : result = WERR_INVALID_LEVEL;
9917 0 : break;
9918 : }
9919 :
9920 0 : SAFE_FREE(queue);
9921 0 : TALLOC_FREE(pinfo2);
9922 :
9923 0 : if (!W_ERROR_IS_OK(result)) {
9924 0 : goto err_jinfo_free;
9925 : }
9926 :
9927 0 : *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9928 : r->in.level);
9929 0 : r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9930 :
9931 0 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9932 :
9933 0 : err_pinfo_free:
9934 0 : TALLOC_FREE(pinfo2);
9935 0 : err_jinfo_free:
9936 0 : TALLOC_FREE(r->out.info);
9937 0 : return result;
9938 : }
9939 :
9940 : /****************************************************************
9941 : _spoolss_GetPrinterDataEx
9942 : ****************************************************************/
9943 :
9944 0 : WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9945 : struct spoolss_GetPrinterDataEx *r)
9946 : {
9947 :
9948 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9949 : const char *printer;
9950 0 : int snum = 0;
9951 0 : WERROR result = WERR_OK;
9952 : DATA_BLOB blob;
9953 0 : enum winreg_Type val_type = REG_NONE;
9954 0 : uint8_t *val_data = NULL;
9955 0 : uint32_t val_size = 0;
9956 : struct dcerpc_binding_handle *b;
9957 : TALLOC_CTX *tmp_ctx;
9958 :
9959 0 : DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9960 :
9961 0 : DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9962 : r->in.key_name, r->in.value_name));
9963 :
9964 : /* in case of problem, return some default values */
9965 :
9966 0 : *r->out.needed = 0;
9967 0 : *r->out.type = REG_NONE;
9968 :
9969 0 : tmp_ctx = talloc_new(p->mem_ctx);
9970 0 : if (!tmp_ctx) {
9971 0 : return WERR_NOT_ENOUGH_MEMORY;
9972 : }
9973 :
9974 0 : if (!Printer) {
9975 0 : DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9976 : OUR_HANDLE(r->in.handle)));
9977 0 : result = WERR_INVALID_HANDLE;
9978 0 : goto done;
9979 : }
9980 :
9981 : /* Is the handle to a printer or to the server? */
9982 :
9983 0 : if (Printer->printer_type == SPLHND_SERVER) {
9984 :
9985 : union spoolss_PrinterData data;
9986 :
9987 0 : result = getprinterdata_printer_server(tmp_ctx,
9988 : r->in.value_name,
9989 : r->out.type,
9990 : &data);
9991 0 : if (!W_ERROR_IS_OK(result)) {
9992 0 : goto done;
9993 : }
9994 :
9995 0 : result = push_spoolss_PrinterData(tmp_ctx, &blob,
9996 0 : *r->out.type, &data);
9997 0 : if (!W_ERROR_IS_OK(result)) {
9998 0 : goto done;
9999 : }
10000 :
10001 0 : *r->out.needed = blob.length;
10002 :
10003 0 : if (r->in.offered >= *r->out.needed) {
10004 0 : memcpy(r->out.data, blob.data, blob.length);
10005 : }
10006 :
10007 0 : result = WERR_OK;
10008 0 : goto done;
10009 : }
10010 :
10011 : /* check to see if the keyname is valid */
10012 0 : if (!strlen(r->in.key_name)) {
10013 0 : result = WERR_INVALID_PARAMETER;
10014 0 : goto done;
10015 : }
10016 :
10017 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10018 0 : result = WERR_INVALID_HANDLE;
10019 0 : goto done;
10020 : }
10021 0 : printer = lp_const_servicename(snum);
10022 :
10023 0 : result = winreg_printer_binding_handle(tmp_ctx,
10024 : get_session_info_system(),
10025 : p->msg_ctx,
10026 : &b);
10027 0 : if (!W_ERROR_IS_OK(result)) {
10028 0 : goto done;
10029 : }
10030 :
10031 : /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
10032 0 : if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
10033 0 : strequal(r->in.value_name, "ChangeId")) {
10034 0 : *r->out.type = REG_DWORD;
10035 0 : *r->out.needed = 4;
10036 0 : if (r->in.offered >= *r->out.needed) {
10037 0 : uint32_t changeid = 0;
10038 :
10039 0 : result = winreg_printer_get_changeid(tmp_ctx, b,
10040 : printer,
10041 : &changeid);
10042 0 : if (!W_ERROR_IS_OK(result)) {
10043 0 : goto done;
10044 : }
10045 :
10046 0 : SIVAL(r->out.data, 0, changeid);
10047 0 : result = WERR_OK;
10048 : }
10049 0 : goto done;
10050 : }
10051 :
10052 0 : result = winreg_get_printer_dataex(tmp_ctx, b,
10053 : printer,
10054 : r->in.key_name,
10055 : r->in.value_name,
10056 : &val_type,
10057 : &val_data,
10058 : &val_size);
10059 0 : if (!W_ERROR_IS_OK(result)) {
10060 0 : goto done;
10061 : }
10062 :
10063 0 : *r->out.needed = val_size;
10064 0 : *r->out.type = val_type;
10065 :
10066 0 : if (r->in.offered >= *r->out.needed) {
10067 0 : memcpy(r->out.data, val_data, val_size);
10068 : }
10069 :
10070 0 : done:
10071 : /* NOTE: do not replace type when returning WERR_MORE_DATA */
10072 :
10073 0 : if (W_ERROR_IS_OK(result)) {
10074 0 : result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
10075 : }
10076 :
10077 0 : talloc_free(tmp_ctx);
10078 0 : return result;
10079 : }
10080 :
10081 : /****************************************************************
10082 : _spoolss_SetPrinterDataEx
10083 : ****************************************************************/
10084 :
10085 0 : WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
10086 : struct spoolss_SetPrinterDataEx *r)
10087 : {
10088 0 : const struct loadparm_substitution *lp_sub =
10089 0 : loadparm_s3_global_substitution();
10090 0 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
10091 0 : int snum = 0;
10092 0 : WERROR result = WERR_OK;
10093 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10094 : char *oid_string;
10095 : struct dcerpc_binding_handle *b;
10096 : TALLOC_CTX *tmp_ctx;
10097 :
10098 0 : DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
10099 :
10100 : /* From MSDN documentation of SetPrinterDataEx: pass request to
10101 : SetPrinterData if key is "PrinterDriverData" */
10102 :
10103 0 : if (!Printer) {
10104 0 : DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
10105 : OUR_HANDLE(r->in.handle)));
10106 0 : return WERR_INVALID_HANDLE;
10107 : }
10108 :
10109 0 : if (Printer->printer_type == SPLHND_SERVER) {
10110 0 : DEBUG(10,("_spoolss_SetPrinterDataEx: "
10111 : "Not implemented for server handles yet\n"));
10112 0 : return WERR_INVALID_PARAMETER;
10113 : }
10114 :
10115 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10116 0 : return WERR_INVALID_HANDLE;
10117 : }
10118 :
10119 : /*
10120 : * Access check : NT returns "access denied" if you make a
10121 : * SetPrinterData call without the necessary privildge.
10122 : * we were originally returning OK if nothing changed
10123 : * which made Win2k issue **a lot** of SetPrinterData
10124 : * when connecting to a printer --jerry
10125 : */
10126 :
10127 0 : if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10128 0 : DEBUG(3, ("_spoolss_SetPrinterDataEx: "
10129 : "change denied by handle access permissions\n"));
10130 0 : return WERR_ACCESS_DENIED;
10131 : }
10132 :
10133 0 : tmp_ctx = talloc_new(p->mem_ctx);
10134 0 : if (!tmp_ctx) {
10135 0 : return WERR_NOT_ENOUGH_MEMORY;
10136 : }
10137 :
10138 0 : result = winreg_printer_binding_handle(tmp_ctx,
10139 : get_session_info_system(),
10140 : p->msg_ctx,
10141 : &b);
10142 0 : if (!W_ERROR_IS_OK(result)) {
10143 0 : goto done;
10144 : }
10145 :
10146 0 : result = winreg_get_printer(tmp_ctx, b,
10147 0 : lp_servicename(talloc_tos(), lp_sub, snum),
10148 : &pinfo2);
10149 0 : if (!W_ERROR_IS_OK(result)) {
10150 0 : goto done;
10151 : }
10152 :
10153 : /* check for OID in valuename */
10154 :
10155 0 : oid_string = strchr(r->in.value_name, ',');
10156 0 : if (oid_string) {
10157 0 : *oid_string = '\0';
10158 0 : oid_string++;
10159 : }
10160 :
10161 : /* save the registry data */
10162 :
10163 0 : result = winreg_set_printer_dataex(tmp_ctx, b,
10164 0 : pinfo2->sharename,
10165 : r->in.key_name,
10166 : r->in.value_name,
10167 : r->in.type,
10168 : r->in.data,
10169 : r->in.offered);
10170 :
10171 0 : if (W_ERROR_IS_OK(result)) {
10172 : /* save the OID if one was specified */
10173 0 : if (oid_string) {
10174 0 : char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
10175 : r->in.key_name, SPOOL_OID_KEY);
10176 0 : if (!str) {
10177 0 : result = WERR_NOT_ENOUGH_MEMORY;
10178 0 : goto done;
10179 : }
10180 :
10181 : /*
10182 : * I'm not checking the status here on purpose. Don't know
10183 : * if this is right, but I'm returning the status from the
10184 : * previous set_printer_dataex() call. I have no idea if
10185 : * this is right. --jerry
10186 : */
10187 0 : winreg_set_printer_dataex(tmp_ctx, b,
10188 0 : pinfo2->sharename,
10189 : str,
10190 : r->in.value_name,
10191 : REG_SZ,
10192 : (uint8_t *) oid_string,
10193 0 : strlen(oid_string) + 1);
10194 : }
10195 :
10196 0 : result = winreg_printer_update_changeid(tmp_ctx, b,
10197 : lp_const_servicename(snum));
10198 :
10199 : }
10200 :
10201 0 : done:
10202 0 : talloc_free(tmp_ctx);
10203 0 : return result;
10204 : }
10205 :
10206 : /****************************************************************
10207 : _spoolss_DeletePrinterDataEx
10208 : ****************************************************************/
10209 :
10210 0 : WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
10211 : struct spoolss_DeletePrinterDataEx *r)
10212 : {
10213 : const char *printer;
10214 0 : int snum=0;
10215 0 : WERROR status = WERR_OK;
10216 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10217 :
10218 0 : DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
10219 :
10220 0 : if (!Printer) {
10221 0 : DEBUG(2,("_spoolss_DeletePrinterDataEx: "
10222 : "Invalid handle (%s:%u:%u).\n",
10223 : OUR_HANDLE(r->in.handle)));
10224 0 : return WERR_INVALID_HANDLE;
10225 : }
10226 :
10227 0 : if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10228 0 : DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
10229 : "printer properties change denied by handle\n"));
10230 0 : return WERR_ACCESS_DENIED;
10231 : }
10232 :
10233 0 : if (!r->in.value_name || !r->in.key_name) {
10234 0 : return WERR_NOT_ENOUGH_MEMORY;
10235 : }
10236 :
10237 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10238 0 : return WERR_INVALID_HANDLE;
10239 : }
10240 0 : printer = lp_const_servicename(snum);
10241 :
10242 0 : status = winreg_delete_printer_dataex_internal(p->mem_ctx,
10243 : get_session_info_system(),
10244 : p->msg_ctx,
10245 : printer,
10246 : r->in.key_name,
10247 : r->in.value_name);
10248 0 : if (W_ERROR_IS_OK(status)) {
10249 0 : status = winreg_printer_update_changeid_internal(p->mem_ctx,
10250 : get_session_info_system(),
10251 : p->msg_ctx,
10252 : printer);
10253 : }
10254 :
10255 0 : return status;
10256 : }
10257 :
10258 : /****************************************************************
10259 : _spoolss_EnumPrinterKey
10260 : ****************************************************************/
10261 :
10262 0 : WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
10263 : struct spoolss_EnumPrinterKey *r)
10264 : {
10265 : uint32_t num_keys;
10266 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10267 0 : int snum = 0;
10268 0 : WERROR result = WERR_FILE_NOT_FOUND;
10269 0 : const char **array = NULL;
10270 : DATA_BLOB blob;
10271 :
10272 0 : DEBUG(4,("_spoolss_EnumPrinterKey\n"));
10273 :
10274 0 : if (!Printer) {
10275 0 : DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
10276 : OUR_HANDLE(r->in.handle)));
10277 0 : return WERR_INVALID_HANDLE;
10278 : }
10279 :
10280 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10281 0 : return WERR_INVALID_HANDLE;
10282 : }
10283 :
10284 0 : result = winreg_enum_printer_key_internal(p->mem_ctx,
10285 : get_session_info_system(),
10286 : p->msg_ctx,
10287 : lp_const_servicename(snum),
10288 : r->in.key_name,
10289 : &num_keys,
10290 : &array);
10291 0 : if (!W_ERROR_IS_OK(result)) {
10292 0 : goto done;
10293 : }
10294 :
10295 0 : if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
10296 0 : result = WERR_NOT_ENOUGH_MEMORY;
10297 0 : goto done;
10298 : }
10299 :
10300 0 : *r->out._ndr_size = r->in.offered / 2;
10301 0 : *r->out.needed = blob.length;
10302 :
10303 0 : if (r->in.offered < *r->out.needed) {
10304 0 : result = WERR_MORE_DATA;
10305 : } else {
10306 0 : result = WERR_OK;
10307 0 : r->out.key_buffer->string_array = array;
10308 : }
10309 :
10310 0 : done:
10311 0 : if (!W_ERROR_IS_OK(result)) {
10312 0 : TALLOC_FREE(array);
10313 0 : if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
10314 0 : *r->out.needed = 0;
10315 : }
10316 : }
10317 :
10318 0 : return result;
10319 : }
10320 :
10321 : /****************************************************************
10322 : _spoolss_DeletePrinterKey
10323 : ****************************************************************/
10324 :
10325 0 : WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
10326 : struct spoolss_DeletePrinterKey *r)
10327 : {
10328 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10329 0 : int snum=0;
10330 : WERROR status;
10331 : const char *printer;
10332 : struct dcerpc_binding_handle *b;
10333 : TALLOC_CTX *tmp_ctx;
10334 :
10335 0 : DEBUG(5,("_spoolss_DeletePrinterKey\n"));
10336 :
10337 0 : if (!Printer) {
10338 0 : DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
10339 : OUR_HANDLE(r->in.handle)));
10340 0 : return WERR_INVALID_HANDLE;
10341 : }
10342 :
10343 : /* if keyname == NULL, return error */
10344 0 : if ( !r->in.key_name )
10345 0 : return WERR_INVALID_PARAMETER;
10346 :
10347 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10348 0 : return WERR_INVALID_HANDLE;
10349 : }
10350 :
10351 0 : if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10352 0 : DEBUG(3, ("_spoolss_DeletePrinterKey: "
10353 : "printer properties change denied by handle\n"));
10354 0 : return WERR_ACCESS_DENIED;
10355 : }
10356 :
10357 0 : printer = lp_const_servicename(snum);
10358 :
10359 0 : tmp_ctx = talloc_new(p->mem_ctx);
10360 0 : if (!tmp_ctx) {
10361 0 : return WERR_NOT_ENOUGH_MEMORY;
10362 : }
10363 :
10364 0 : status = winreg_printer_binding_handle(tmp_ctx,
10365 : get_session_info_system(),
10366 : p->msg_ctx,
10367 : &b);
10368 0 : if (!W_ERROR_IS_OK(status)) {
10369 0 : goto done;
10370 : }
10371 :
10372 : /* delete the key and all subkeys */
10373 0 : status = winreg_delete_printer_key(tmp_ctx, b,
10374 : printer,
10375 : r->in.key_name);
10376 0 : if (W_ERROR_IS_OK(status)) {
10377 0 : status = winreg_printer_update_changeid(tmp_ctx, b,
10378 : printer);
10379 : }
10380 :
10381 0 : done:
10382 0 : talloc_free(tmp_ctx);
10383 0 : return status;
10384 : }
10385 :
10386 : /****************************************************************
10387 : _spoolss_EnumPrinterDataEx
10388 : ****************************************************************/
10389 :
10390 0 : WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
10391 : struct spoolss_EnumPrinterDataEx *r)
10392 : {
10393 0 : uint32_t count = 0;
10394 0 : struct spoolss_PrinterEnumValues *info = NULL;
10395 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10396 : int snum;
10397 : WERROR result;
10398 :
10399 0 : DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
10400 :
10401 0 : *r->out.count = 0;
10402 0 : *r->out.needed = 0;
10403 0 : *r->out.info = NULL;
10404 :
10405 0 : if (!Printer) {
10406 0 : DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
10407 : OUR_HANDLE(r->in.handle)));
10408 0 : return WERR_INVALID_HANDLE;
10409 : }
10410 :
10411 : /*
10412 : * first check for a keyname of NULL or "". Win2k seems to send
10413 : * this a lot and we should send back WERR_INVALID_PARAMETER
10414 : * no need to spend time looking up the printer in this case.
10415 : * --jerry
10416 : */
10417 :
10418 0 : if (!strlen(r->in.key_name)) {
10419 0 : result = WERR_INVALID_PARAMETER;
10420 0 : goto done;
10421 : }
10422 :
10423 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10424 0 : return WERR_INVALID_HANDLE;
10425 : }
10426 :
10427 : /* now look for a match on the key name */
10428 0 : result = winreg_enum_printer_dataex_internal(p->mem_ctx,
10429 : get_session_info_system(),
10430 : p->msg_ctx,
10431 : lp_const_servicename(snum),
10432 : r->in.key_name,
10433 : &count,
10434 : &info);
10435 0 : if (!W_ERROR_IS_OK(result)) {
10436 0 : goto done;
10437 : }
10438 :
10439 : #if 0 /* FIXME - gd */
10440 : /* housekeeping information in the reply */
10441 :
10442 : /* Fix from Martin Zielinski <mz@seh.de> - ensure
10443 : * the hand marshalled container size is a multiple
10444 : * of 4 bytes for RPC alignment.
10445 : */
10446 :
10447 : if (needed % 4) {
10448 : needed += 4-(needed % 4);
10449 : }
10450 : #endif
10451 0 : *r->out.count = count;
10452 0 : *r->out.info = info;
10453 :
10454 0 : done:
10455 0 : if (!W_ERROR_IS_OK(result)) {
10456 0 : return result;
10457 : }
10458 :
10459 0 : *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
10460 : spoolss_EnumPrinterDataEx,
10461 : *r->out.info,
10462 : *r->out.count);
10463 0 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
10464 0 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
10465 :
10466 0 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
10467 : }
10468 :
10469 : /****************************************************************************
10470 : ****************************************************************************/
10471 :
10472 0 : static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
10473 : const char *servername,
10474 : const char *environment,
10475 : struct spoolss_PrintProcessorDirectoryInfo1 *r)
10476 : {
10477 : WERROR werr;
10478 0 : char *path = NULL;
10479 :
10480 0 : werr = compose_spoolss_server_path(mem_ctx,
10481 : servername,
10482 : environment,
10483 : SPOOLSS_PRTPROCS_PATH,
10484 : &path);
10485 0 : if (!W_ERROR_IS_OK(werr)) {
10486 0 : return werr;
10487 : }
10488 :
10489 0 : DEBUG(4,("print processor directory: [%s]\n", path));
10490 :
10491 0 : r->directory_name = path;
10492 :
10493 0 : return WERR_OK;
10494 : }
10495 :
10496 : /****************************************************************
10497 : _spoolss_GetPrintProcessorDirectory
10498 : ****************************************************************/
10499 :
10500 0 : WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
10501 : struct spoolss_GetPrintProcessorDirectory *r)
10502 : {
10503 : WERROR result;
10504 0 : char *prnproc_share = NULL;
10505 0 : bool prnproc_share_exists = false;
10506 : int snum;
10507 :
10508 : /* that's an [in out] buffer */
10509 :
10510 0 : if (!r->in.buffer && (r->in.offered != 0)) {
10511 0 : result = WERR_INVALID_PARAMETER;
10512 0 : goto err_info_free;
10513 : }
10514 :
10515 0 : DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
10516 : r->in.level));
10517 :
10518 0 : *r->out.needed = 0;
10519 :
10520 : /* r->in.level is ignored */
10521 :
10522 : /* We always should reply with a local print processor directory so that
10523 : * users are not forced to have a [prnproc$] share on the Samba spoolss
10524 : * server, if users decide to do so, lets announce it though - Guenther */
10525 :
10526 0 : snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
10527 0 : if (!prnproc_share) {
10528 0 : result = WERR_NOT_ENOUGH_MEMORY;
10529 0 : goto err_info_free;
10530 : }
10531 0 : if (snum != -1) {
10532 0 : prnproc_share_exists = true;
10533 : }
10534 :
10535 0 : result = getprintprocessordirectory_level_1(p->mem_ctx,
10536 : prnproc_share_exists ? r->in.server : NULL,
10537 : r->in.environment,
10538 0 : &r->out.info->info1);
10539 0 : if (!W_ERROR_IS_OK(result)) {
10540 0 : goto err_info_free;
10541 : }
10542 :
10543 0 : *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
10544 : r->out.info, r->in.level);
10545 0 : r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10546 :
10547 0 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10548 :
10549 0 : err_info_free:
10550 0 : TALLOC_FREE(r->out.info);
10551 0 : return result;
10552 : }
10553 :
10554 : /*******************************************************************
10555 : ********************************************************************/
10556 :
10557 0 : static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10558 : const char *dllname)
10559 : {
10560 : enum ndr_err_code ndr_err;
10561 : struct spoolss_MonitorUi ui;
10562 :
10563 0 : ui.dll_name = dllname;
10564 :
10565 0 : ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10566 : (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10567 0 : if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10568 0 : NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10569 : }
10570 0 : return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10571 : }
10572 :
10573 : /*******************************************************************
10574 : Streams the monitor UI DLL name in UNICODE
10575 : *******************************************************************/
10576 :
10577 0 : static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10578 : struct security_token *token, DATA_BLOB *in,
10579 : DATA_BLOB *out, uint32_t *needed)
10580 : {
10581 0 : const char *dllname = "tcpmonui.dll";
10582 :
10583 0 : *needed = (strlen(dllname)+1) * 2;
10584 :
10585 0 : if (out->length < *needed) {
10586 0 : return WERR_INSUFFICIENT_BUFFER;
10587 : }
10588 :
10589 0 : if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10590 0 : return WERR_NOT_ENOUGH_MEMORY;
10591 : }
10592 :
10593 0 : return WERR_OK;
10594 : }
10595 :
10596 : /*******************************************************************
10597 : ********************************************************************/
10598 :
10599 0 : static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10600 : struct spoolss_PortData1 *port1,
10601 : const DATA_BLOB *buf)
10602 : {
10603 : enum ndr_err_code ndr_err;
10604 0 : ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10605 : (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10606 0 : if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10607 0 : NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10608 : }
10609 0 : return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10610 : }
10611 :
10612 : /*******************************************************************
10613 : ********************************************************************/
10614 :
10615 0 : static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10616 : struct spoolss_PortData2 *port2,
10617 : const DATA_BLOB *buf)
10618 : {
10619 : enum ndr_err_code ndr_err;
10620 0 : ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10621 : (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10622 0 : if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10623 0 : NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10624 : }
10625 0 : return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10626 : }
10627 :
10628 : /*******************************************************************
10629 : Create a new TCP/IP port
10630 : *******************************************************************/
10631 :
10632 0 : static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10633 : struct security_token *token, DATA_BLOB *in,
10634 : DATA_BLOB *out, uint32_t *needed)
10635 : {
10636 : struct spoolss_PortData1 port1;
10637 : struct spoolss_PortData2 port2;
10638 0 : char *device_uri = NULL;
10639 : uint32_t version;
10640 :
10641 : const char *portname;
10642 : const char *hostaddress;
10643 : const char *queue;
10644 : uint32_t port_number;
10645 : uint32_t protocol;
10646 :
10647 : /* peek for spoolss_PortData version */
10648 :
10649 0 : if (!in || (in->length < (128 + 4))) {
10650 0 : return WERR_GEN_FAILURE;
10651 : }
10652 :
10653 0 : version = IVAL(in->data, 128);
10654 :
10655 0 : switch (version) {
10656 0 : case 1:
10657 0 : ZERO_STRUCT(port1);
10658 :
10659 0 : if (!pull_port_data_1(mem_ctx, &port1, in)) {
10660 0 : return WERR_NOT_ENOUGH_MEMORY;
10661 : }
10662 :
10663 0 : portname = port1.portname;
10664 0 : hostaddress = port1.hostaddress;
10665 0 : queue = port1.queue;
10666 0 : protocol = port1.protocol;
10667 0 : port_number = port1.port_number;
10668 :
10669 0 : break;
10670 0 : case 2:
10671 0 : ZERO_STRUCT(port2);
10672 :
10673 0 : if (!pull_port_data_2(mem_ctx, &port2, in)) {
10674 0 : return WERR_NOT_ENOUGH_MEMORY;
10675 : }
10676 :
10677 0 : portname = port2.portname;
10678 0 : hostaddress = port2.hostaddress;
10679 0 : queue = port2.queue;
10680 0 : protocol = port2.protocol;
10681 0 : port_number = port2.port_number;
10682 :
10683 0 : break;
10684 0 : default:
10685 0 : DEBUG(1,("xcvtcp_addport: "
10686 : "unknown version of port_data: %d\n", version));
10687 0 : return WERR_UNKNOWN_PORT;
10688 : }
10689 :
10690 : /* create the device URI and call the add_port_hook() */
10691 :
10692 0 : switch (protocol) {
10693 0 : case PROTOCOL_RAWTCP_TYPE:
10694 0 : device_uri = talloc_asprintf(mem_ctx,
10695 : "socket://%s:%d/", hostaddress,
10696 : port_number);
10697 0 : break;
10698 :
10699 0 : case PROTOCOL_LPR_TYPE:
10700 0 : device_uri = talloc_asprintf(mem_ctx,
10701 : "lpr://%s/%s", hostaddress, queue );
10702 0 : break;
10703 :
10704 0 : default:
10705 0 : return WERR_UNKNOWN_PORT;
10706 : }
10707 :
10708 0 : if (!device_uri) {
10709 0 : return WERR_NOT_ENOUGH_MEMORY;
10710 : }
10711 :
10712 0 : return add_port_hook(mem_ctx, token, portname, device_uri);
10713 : }
10714 :
10715 : /*******************************************************************
10716 : *******************************************************************/
10717 :
10718 : struct xcv_api_table xcvtcp_cmds[] = {
10719 : { "MonitorUI", xcvtcp_monitorui },
10720 : { "AddPort", xcvtcp_addport},
10721 : { NULL, NULL }
10722 : };
10723 :
10724 0 : static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10725 : struct security_token *token, const char *command,
10726 : DATA_BLOB *inbuf,
10727 : DATA_BLOB *outbuf,
10728 : uint32_t *needed )
10729 : {
10730 : int i;
10731 :
10732 0 : DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10733 :
10734 0 : for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10735 0 : if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10736 0 : return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10737 : }
10738 :
10739 0 : return WERR_INVALID_FUNCTION;
10740 : }
10741 :
10742 : /*******************************************************************
10743 : *******************************************************************/
10744 : #if 0 /* don't support management using the "Local Port" monitor */
10745 :
10746 : static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10747 : struct security_token *token, DATA_BLOB *in,
10748 : DATA_BLOB *out, uint32_t *needed)
10749 : {
10750 : const char *dllname = "localui.dll";
10751 :
10752 : *needed = (strlen(dllname)+1) * 2;
10753 :
10754 : if (out->length < *needed) {
10755 : return WERR_INSUFFICIENT_BUFFER;
10756 : }
10757 :
10758 : if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10759 : return WERR_NOT_ENOUGH_MEMORY;
10760 : }
10761 :
10762 : return WERR_OK;
10763 : }
10764 :
10765 : /*******************************************************************
10766 : *******************************************************************/
10767 :
10768 : struct xcv_api_table xcvlocal_cmds[] = {
10769 : { "MonitorUI", xcvlocal_monitorui },
10770 : { NULL, NULL }
10771 : };
10772 : #else
10773 : struct xcv_api_table xcvlocal_cmds[] = {
10774 : { NULL, NULL }
10775 : };
10776 : #endif
10777 :
10778 :
10779 :
10780 : /*******************************************************************
10781 : *******************************************************************/
10782 :
10783 0 : static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10784 : struct security_token *token, const char *command,
10785 : DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10786 : uint32_t *needed)
10787 : {
10788 : int i;
10789 :
10790 0 : DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10791 :
10792 0 : for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10793 0 : if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10794 0 : return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10795 : }
10796 0 : return WERR_INVALID_FUNCTION;
10797 : }
10798 :
10799 : /****************************************************************
10800 : _spoolss_XcvData
10801 : ****************************************************************/
10802 :
10803 0 : WERROR _spoolss_XcvData(struct pipes_struct *p,
10804 : struct spoolss_XcvData *r)
10805 : {
10806 0 : struct dcesrv_call_state *dce_call = p->dce_call;
10807 0 : struct auth_session_info *session_info =
10808 0 : dcesrv_call_session_info(dce_call);
10809 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10810 0 : DATA_BLOB out_data = data_blob_null;
10811 : WERROR werror;
10812 :
10813 0 : if (!Printer) {
10814 0 : DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10815 : OUR_HANDLE(r->in.handle)));
10816 0 : return WERR_INVALID_HANDLE;
10817 : }
10818 :
10819 : /* Has to be a handle to the TCP/IP port monitor */
10820 :
10821 0 : if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10822 0 : DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10823 0 : return WERR_INVALID_HANDLE;
10824 : }
10825 :
10826 : /* requires administrative access to the server */
10827 :
10828 0 : if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10829 0 : DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10830 0 : return WERR_ACCESS_DENIED;
10831 : }
10832 :
10833 : /* Allocate the outgoing buffer */
10834 :
10835 0 : if (r->in.out_data_size) {
10836 0 : out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10837 0 : if (out_data.data == NULL) {
10838 0 : return WERR_NOT_ENOUGH_MEMORY;
10839 : }
10840 : }
10841 :
10842 0 : switch ( Printer->printer_type ) {
10843 0 : case SPLHND_PORTMON_TCP:
10844 0 : werror = process_xcvtcp_command(p->mem_ctx,
10845 : session_info->security_token,
10846 : r->in.function_name,
10847 : &r->in.in_data, &out_data,
10848 : r->out.needed);
10849 0 : break;
10850 0 : case SPLHND_PORTMON_LOCAL:
10851 0 : werror = process_xcvlocal_command(p->mem_ctx,
10852 : session_info->security_token,
10853 : r->in.function_name,
10854 : &r->in.in_data, &out_data,
10855 : r->out.needed);
10856 0 : break;
10857 0 : default:
10858 0 : werror = WERR_INVALID_PRINT_MONITOR;
10859 : }
10860 :
10861 0 : if (!W_ERROR_IS_OK(werror)) {
10862 0 : return werror;
10863 : }
10864 :
10865 0 : *r->out.status_code = 0;
10866 :
10867 0 : if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10868 0 : memcpy(r->out.out_data, out_data.data,
10869 0 : MIN(r->in.out_data_size, out_data.length));
10870 : }
10871 :
10872 0 : return WERR_OK;
10873 : }
10874 :
10875 : /****************************************************************
10876 : _spoolss_AddPrintProcessor
10877 : ****************************************************************/
10878 :
10879 0 : WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10880 : struct spoolss_AddPrintProcessor *r)
10881 : {
10882 : /* for now, just indicate success and ignore the add. We'll
10883 : automatically set the winprint processor for printer
10884 : entries later. Used to debug the LexMark Optra S 1855 PCL
10885 : driver --jerry */
10886 :
10887 0 : return WERR_OK;
10888 : }
10889 :
10890 : /****************************************************************
10891 : _spoolss_AddPort
10892 : ****************************************************************/
10893 :
10894 0 : WERROR _spoolss_AddPort(struct pipes_struct *p,
10895 : struct spoolss_AddPort *r)
10896 : {
10897 : /* do what w2k3 does */
10898 :
10899 0 : return WERR_NOT_SUPPORTED;
10900 : }
10901 :
10902 : /****************************************************************
10903 : _spoolss_GetPrinterDriver
10904 : ****************************************************************/
10905 :
10906 0 : WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10907 : struct spoolss_GetPrinterDriver *r)
10908 : {
10909 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10910 0 : return WERR_NOT_SUPPORTED;
10911 : }
10912 :
10913 : /****************************************************************
10914 : _spoolss_ReadPrinter
10915 : ****************************************************************/
10916 :
10917 0 : WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10918 : struct spoolss_ReadPrinter *r)
10919 : {
10920 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10921 0 : return WERR_NOT_SUPPORTED;
10922 : }
10923 :
10924 : /****************************************************************
10925 : _spoolss_WaitForPrinterChange
10926 : ****************************************************************/
10927 :
10928 0 : WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10929 : struct spoolss_WaitForPrinterChange *r)
10930 : {
10931 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10932 0 : return WERR_NOT_SUPPORTED;
10933 : }
10934 :
10935 : /****************************************************************
10936 : _spoolss_ConfigurePort
10937 : ****************************************************************/
10938 :
10939 0 : WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10940 : struct spoolss_ConfigurePort *r)
10941 : {
10942 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10943 0 : return WERR_NOT_SUPPORTED;
10944 : }
10945 :
10946 : /****************************************************************
10947 : _spoolss_DeletePort
10948 : ****************************************************************/
10949 :
10950 0 : WERROR _spoolss_DeletePort(struct pipes_struct *p,
10951 : struct spoolss_DeletePort *r)
10952 : {
10953 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10954 0 : return WERR_NOT_SUPPORTED;
10955 : }
10956 :
10957 : /****************************************************************
10958 : _spoolss_CreatePrinterIC
10959 : ****************************************************************/
10960 :
10961 0 : WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10962 : struct spoolss_CreatePrinterIC *r)
10963 : {
10964 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10965 0 : return WERR_NOT_SUPPORTED;
10966 : }
10967 :
10968 : /****************************************************************
10969 : _spoolss_PlayGDIScriptOnPrinterIC
10970 : ****************************************************************/
10971 :
10972 0 : WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10973 : struct spoolss_PlayGDIScriptOnPrinterIC *r)
10974 : {
10975 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10976 0 : return WERR_NOT_SUPPORTED;
10977 : }
10978 :
10979 : /****************************************************************
10980 : _spoolss_DeletePrinterIC
10981 : ****************************************************************/
10982 :
10983 0 : WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10984 : struct spoolss_DeletePrinterIC *r)
10985 : {
10986 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10987 0 : return WERR_NOT_SUPPORTED;
10988 : }
10989 :
10990 : /****************************************************************
10991 : _spoolss_AddPrinterConnection
10992 : ****************************************************************/
10993 :
10994 0 : WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10995 : struct spoolss_AddPrinterConnection *r)
10996 : {
10997 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10998 0 : return WERR_NOT_SUPPORTED;
10999 : }
11000 :
11001 : /****************************************************************
11002 : _spoolss_DeletePrinterConnection
11003 : ****************************************************************/
11004 :
11005 0 : WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
11006 : struct spoolss_DeletePrinterConnection *r)
11007 : {
11008 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11009 0 : return WERR_NOT_SUPPORTED;
11010 : }
11011 :
11012 : /****************************************************************
11013 : _spoolss_PrinterMessageBox
11014 : ****************************************************************/
11015 :
11016 0 : WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
11017 : struct spoolss_PrinterMessageBox *r)
11018 : {
11019 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11020 0 : return WERR_NOT_SUPPORTED;
11021 : }
11022 :
11023 : /****************************************************************
11024 : _spoolss_AddMonitor
11025 : ****************************************************************/
11026 :
11027 0 : WERROR _spoolss_AddMonitor(struct pipes_struct *p,
11028 : struct spoolss_AddMonitor *r)
11029 : {
11030 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11031 0 : return WERR_NOT_SUPPORTED;
11032 : }
11033 :
11034 : /****************************************************************
11035 : _spoolss_DeleteMonitor
11036 : ****************************************************************/
11037 :
11038 0 : WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
11039 : struct spoolss_DeleteMonitor *r)
11040 : {
11041 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11042 0 : return WERR_NOT_SUPPORTED;
11043 : }
11044 :
11045 : /****************************************************************
11046 : _spoolss_DeletePrintProcessor
11047 : ****************************************************************/
11048 :
11049 0 : WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
11050 : struct spoolss_DeletePrintProcessor *r)
11051 : {
11052 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11053 0 : return WERR_NOT_SUPPORTED;
11054 : }
11055 :
11056 : /****************************************************************
11057 : _spoolss_AddPrintProvidor
11058 : ****************************************************************/
11059 :
11060 0 : WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
11061 : struct spoolss_AddPrintProvidor *r)
11062 : {
11063 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11064 0 : return WERR_NOT_SUPPORTED;
11065 : }
11066 :
11067 : /****************************************************************
11068 : _spoolss_DeletePrintProvidor
11069 : ****************************************************************/
11070 :
11071 0 : WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
11072 : struct spoolss_DeletePrintProvidor *r)
11073 : {
11074 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11075 0 : return WERR_NOT_SUPPORTED;
11076 : }
11077 :
11078 : /****************************************************************
11079 : _spoolss_FindFirstPrinterChangeNotification
11080 : ****************************************************************/
11081 :
11082 0 : WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
11083 : struct spoolss_FindFirstPrinterChangeNotification *r)
11084 : {
11085 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11086 0 : return WERR_NOT_SUPPORTED;
11087 : }
11088 :
11089 : /****************************************************************
11090 : _spoolss_FindNextPrinterChangeNotification
11091 : ****************************************************************/
11092 :
11093 0 : WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
11094 : struct spoolss_FindNextPrinterChangeNotification *r)
11095 : {
11096 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11097 0 : return WERR_NOT_SUPPORTED;
11098 : }
11099 :
11100 : /****************************************************************
11101 : _spoolss_RouterFindFirstPrinterChangeNotificationOld
11102 : ****************************************************************/
11103 :
11104 0 : WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
11105 : struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
11106 : {
11107 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11108 0 : return WERR_NOT_SUPPORTED;
11109 : }
11110 :
11111 : /****************************************************************
11112 : _spoolss_ReplyOpenPrinter
11113 : ****************************************************************/
11114 :
11115 0 : WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
11116 : struct spoolss_ReplyOpenPrinter *r)
11117 : {
11118 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11119 0 : return WERR_NOT_SUPPORTED;
11120 : }
11121 :
11122 : /****************************************************************
11123 : _spoolss_RouterReplyPrinter
11124 : ****************************************************************/
11125 :
11126 0 : WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
11127 : struct spoolss_RouterReplyPrinter *r)
11128 : {
11129 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11130 0 : return WERR_NOT_SUPPORTED;
11131 : }
11132 :
11133 : /****************************************************************
11134 : _spoolss_ReplyClosePrinter
11135 : ****************************************************************/
11136 :
11137 0 : WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
11138 : struct spoolss_ReplyClosePrinter *r)
11139 : {
11140 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11141 0 : return WERR_NOT_SUPPORTED;
11142 : }
11143 :
11144 : /****************************************************************
11145 : _spoolss_AddPortEx
11146 : ****************************************************************/
11147 :
11148 0 : WERROR _spoolss_AddPortEx(struct pipes_struct *p,
11149 : struct spoolss_AddPortEx *r)
11150 : {
11151 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11152 0 : return WERR_NOT_SUPPORTED;
11153 : }
11154 :
11155 : /****************************************************************
11156 : _spoolss_RouterFindFirstPrinterChangeNotification
11157 : ****************************************************************/
11158 :
11159 0 : WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
11160 : struct spoolss_RouterFindFirstPrinterChangeNotification *r)
11161 : {
11162 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11163 0 : return WERR_NOT_SUPPORTED;
11164 : }
11165 :
11166 : /****************************************************************
11167 : _spoolss_SpoolerInit
11168 : ****************************************************************/
11169 :
11170 0 : WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
11171 : struct spoolss_SpoolerInit *r)
11172 : {
11173 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11174 0 : return WERR_NOT_SUPPORTED;
11175 : }
11176 :
11177 : /****************************************************************
11178 : _spoolss_ResetPrinterEx
11179 : ****************************************************************/
11180 :
11181 0 : WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
11182 : struct spoolss_ResetPrinterEx *r)
11183 : {
11184 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11185 0 : return WERR_NOT_SUPPORTED;
11186 : }
11187 :
11188 : /****************************************************************
11189 : _spoolss_RouterReplyPrinterEx
11190 : ****************************************************************/
11191 :
11192 0 : WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
11193 : struct spoolss_RouterReplyPrinterEx *r)
11194 : {
11195 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11196 0 : return WERR_NOT_SUPPORTED;
11197 : }
11198 :
11199 : /****************************************************************
11200 : _spoolss_44
11201 : ****************************************************************/
11202 :
11203 0 : WERROR _spoolss_44(struct pipes_struct *p,
11204 : struct spoolss_44 *r)
11205 : {
11206 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11207 0 : return WERR_NOT_SUPPORTED;
11208 : }
11209 :
11210 : /****************************************************************
11211 : _spoolss_SetPort
11212 : ****************************************************************/
11213 :
11214 0 : WERROR _spoolss_SetPort(struct pipes_struct *p,
11215 : struct spoolss_SetPort *r)
11216 : {
11217 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11218 0 : return WERR_NOT_SUPPORTED;
11219 : }
11220 :
11221 : /****************************************************************
11222 : _spoolss_4a
11223 : ****************************************************************/
11224 :
11225 0 : WERROR _spoolss_4a(struct pipes_struct *p,
11226 : struct spoolss_4a *r)
11227 : {
11228 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11229 0 : return WERR_NOT_SUPPORTED;
11230 : }
11231 :
11232 : /****************************************************************
11233 : _spoolss_4b
11234 : ****************************************************************/
11235 :
11236 0 : WERROR _spoolss_4b(struct pipes_struct *p,
11237 : struct spoolss_4b *r)
11238 : {
11239 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11240 0 : return WERR_NOT_SUPPORTED;
11241 : }
11242 :
11243 : /****************************************************************
11244 : _spoolss_4c
11245 : ****************************************************************/
11246 :
11247 0 : WERROR _spoolss_4c(struct pipes_struct *p,
11248 : struct spoolss_4c *r)
11249 : {
11250 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11251 0 : return WERR_NOT_SUPPORTED;
11252 : }
11253 :
11254 : /****************************************************************
11255 : _spoolss_53
11256 : ****************************************************************/
11257 :
11258 0 : WERROR _spoolss_53(struct pipes_struct *p,
11259 : struct spoolss_53 *r)
11260 : {
11261 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11262 0 : return WERR_NOT_SUPPORTED;
11263 : }
11264 :
11265 : /****************************************************************
11266 : _spoolss_AddPerMachineConnection
11267 : ****************************************************************/
11268 :
11269 0 : WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
11270 : struct spoolss_AddPerMachineConnection *r)
11271 : {
11272 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11273 0 : return WERR_NOT_SUPPORTED;
11274 : }
11275 :
11276 : /****************************************************************
11277 : _spoolss_DeletePerMachineConnection
11278 : ****************************************************************/
11279 :
11280 0 : WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
11281 : struct spoolss_DeletePerMachineConnection *r)
11282 : {
11283 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11284 0 : return WERR_NOT_SUPPORTED;
11285 : }
11286 :
11287 : /****************************************************************
11288 : _spoolss_EnumPerMachineConnections
11289 : ****************************************************************/
11290 :
11291 0 : WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
11292 : struct spoolss_EnumPerMachineConnections *r)
11293 : {
11294 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11295 0 : return WERR_NOT_SUPPORTED;
11296 : }
11297 :
11298 : /****************************************************************
11299 : _spoolss_5a
11300 : ****************************************************************/
11301 :
11302 0 : WERROR _spoolss_5a(struct pipes_struct *p,
11303 : struct spoolss_5a *r)
11304 : {
11305 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11306 0 : return WERR_NOT_SUPPORTED;
11307 : }
11308 :
11309 : /****************************************************************
11310 : _spoolss_5b
11311 : ****************************************************************/
11312 :
11313 0 : WERROR _spoolss_5b(struct pipes_struct *p,
11314 : struct spoolss_5b *r)
11315 : {
11316 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11317 0 : return WERR_NOT_SUPPORTED;
11318 : }
11319 :
11320 : /****************************************************************
11321 : _spoolss_5c
11322 : ****************************************************************/
11323 :
11324 0 : WERROR _spoolss_5c(struct pipes_struct *p,
11325 : struct spoolss_5c *r)
11326 : {
11327 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11328 0 : return WERR_NOT_SUPPORTED;
11329 : }
11330 :
11331 : /****************************************************************
11332 : _spoolss_5d
11333 : ****************************************************************/
11334 :
11335 0 : WERROR _spoolss_5d(struct pipes_struct *p,
11336 : struct spoolss_5d *r)
11337 : {
11338 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11339 0 : return WERR_NOT_SUPPORTED;
11340 : }
11341 :
11342 : /****************************************************************
11343 : _spoolss_5e
11344 : ****************************************************************/
11345 :
11346 0 : WERROR _spoolss_5e(struct pipes_struct *p,
11347 : struct spoolss_5e *r)
11348 : {
11349 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11350 0 : return WERR_NOT_SUPPORTED;
11351 : }
11352 :
11353 : /****************************************************************
11354 : _spoolss_5f
11355 : ****************************************************************/
11356 :
11357 0 : WERROR _spoolss_5f(struct pipes_struct *p,
11358 : struct spoolss_5f *r)
11359 : {
11360 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11361 0 : return WERR_NOT_SUPPORTED;
11362 : }
11363 :
11364 : /****************************************************************
11365 : _spoolss_60
11366 : ****************************************************************/
11367 :
11368 0 : WERROR _spoolss_60(struct pipes_struct *p,
11369 : struct spoolss_60 *r)
11370 : {
11371 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11372 0 : return WERR_NOT_SUPPORTED;
11373 : }
11374 :
11375 : /****************************************************************
11376 : _spoolss_SendRecvBidiData
11377 : ****************************************************************/
11378 :
11379 0 : WERROR _spoolss_SendRecvBidiData(struct pipes_struct *p,
11380 : struct spoolss_SendRecvBidiData *r)
11381 : {
11382 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11383 0 : return WERR_NOT_SUPPORTED;
11384 : }
11385 :
11386 : /****************************************************************
11387 : _spoolss_62
11388 : ****************************************************************/
11389 :
11390 0 : WERROR _spoolss_62(struct pipes_struct *p,
11391 : struct spoolss_62 *r)
11392 : {
11393 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11394 0 : return WERR_NOT_SUPPORTED;
11395 : }
11396 :
11397 : /****************************************************************
11398 : _spoolss_63
11399 : ****************************************************************/
11400 :
11401 0 : WERROR _spoolss_63(struct pipes_struct *p,
11402 : struct spoolss_63 *r)
11403 : {
11404 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11405 0 : return WERR_NOT_SUPPORTED;
11406 : }
11407 :
11408 : /****************************************************************
11409 : _spoolss_64
11410 : ****************************************************************/
11411 :
11412 0 : WERROR _spoolss_64(struct pipes_struct *p,
11413 : struct spoolss_64 *r)
11414 : {
11415 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11416 0 : return WERR_NOT_SUPPORTED;
11417 : }
11418 :
11419 : /****************************************************************
11420 : _spoolss_65
11421 : ****************************************************************/
11422 :
11423 0 : WERROR _spoolss_65(struct pipes_struct *p,
11424 : struct spoolss_65 *r)
11425 : {
11426 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11427 0 : return WERR_NOT_SUPPORTED;
11428 : }
11429 :
11430 : /****************************************************************
11431 : _spoolss_GetCorePrinterDrivers
11432 : ****************************************************************/
11433 :
11434 0 : HRESULT _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
11435 : struct spoolss_GetCorePrinterDrivers *r)
11436 : {
11437 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11438 0 : return HRES_ERROR_NOT_SUPPORTED;
11439 : }
11440 :
11441 : /****************************************************************
11442 : _spoolss_67
11443 : ****************************************************************/
11444 :
11445 0 : WERROR _spoolss_67(struct pipes_struct *p,
11446 : struct spoolss_67 *r)
11447 : {
11448 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11449 0 : return WERR_NOT_SUPPORTED;
11450 : }
11451 :
11452 : /****************************************************************
11453 : _spoolss_GetPrinterDriverPackagePath
11454 : ****************************************************************/
11455 :
11456 0 : HRESULT _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
11457 : struct spoolss_GetPrinterDriverPackagePath *r)
11458 : {
11459 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11460 0 : return HRES_ERROR_NOT_SUPPORTED;
11461 : }
11462 :
11463 : /****************************************************************
11464 : _spoolss_69
11465 : ****************************************************************/
11466 :
11467 0 : WERROR _spoolss_69(struct pipes_struct *p,
11468 : struct spoolss_69 *r)
11469 : {
11470 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11471 0 : return WERR_NOT_SUPPORTED;
11472 : }
11473 :
11474 : /****************************************************************
11475 : _spoolss_6a
11476 : ****************************************************************/
11477 :
11478 0 : WERROR _spoolss_6a(struct pipes_struct *p,
11479 : struct spoolss_6a *r)
11480 : {
11481 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11482 0 : return WERR_NOT_SUPPORTED;
11483 : }
11484 :
11485 : /****************************************************************
11486 : _spoolss_6b
11487 : ****************************************************************/
11488 :
11489 0 : WERROR _spoolss_6b(struct pipes_struct *p,
11490 : struct spoolss_6b *r)
11491 : {
11492 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11493 0 : return WERR_NOT_SUPPORTED;
11494 : }
11495 :
11496 : /****************************************************************
11497 : _spoolss_6c
11498 : ****************************************************************/
11499 :
11500 0 : WERROR _spoolss_6c(struct pipes_struct *p,
11501 : struct spoolss_6c *r)
11502 : {
11503 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11504 0 : return WERR_NOT_SUPPORTED;
11505 : }
11506 :
11507 : /****************************************************************
11508 : _spoolss_6d
11509 : ****************************************************************/
11510 :
11511 0 : WERROR _spoolss_6d(struct pipes_struct *p,
11512 : struct spoolss_6d *r)
11513 : {
11514 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11515 0 : return WERR_NOT_SUPPORTED;
11516 : }
11517 :
11518 : /****************************************************************
11519 : _spoolss_GetJobNamedPropertyValue
11520 : ****************************************************************/
11521 :
11522 0 : WERROR _spoolss_GetJobNamedPropertyValue(struct pipes_struct *p,
11523 : struct spoolss_GetJobNamedPropertyValue *r)
11524 : {
11525 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11526 0 : return WERR_NOT_SUPPORTED;
11527 : }
11528 :
11529 : /****************************************************************
11530 : _spoolss_SetJobNamedProperty
11531 : ****************************************************************/
11532 :
11533 0 : WERROR _spoolss_SetJobNamedProperty(struct pipes_struct *p,
11534 : struct spoolss_SetJobNamedProperty *r)
11535 : {
11536 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11537 0 : return WERR_NOT_SUPPORTED;
11538 : }
11539 :
11540 : /****************************************************************
11541 : _spoolss_DeleteJobNamedProperty
11542 : ****************************************************************/
11543 :
11544 0 : WERROR _spoolss_DeleteJobNamedProperty(struct pipes_struct *p,
11545 : struct spoolss_DeleteJobNamedProperty *r)
11546 : {
11547 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11548 0 : return WERR_NOT_SUPPORTED;
11549 : }
11550 :
11551 : /****************************************************************
11552 : _spoolss_EnumJobNamedProperties
11553 : ****************************************************************/
11554 :
11555 0 : WERROR _spoolss_EnumJobNamedProperties(struct pipes_struct *p,
11556 : struct spoolss_EnumJobNamedProperties *r)
11557 : {
11558 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11559 0 : return WERR_NOT_SUPPORTED;
11560 : }
11561 :
11562 : /****************************************************************
11563 : _spoolss_72
11564 : ****************************************************************/
11565 :
11566 0 : WERROR _spoolss_72(struct pipes_struct *p,
11567 : struct spoolss_72 *r)
11568 : {
11569 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11570 0 : return WERR_NOT_SUPPORTED;
11571 : }
11572 :
11573 : /****************************************************************
11574 : _spoolss_73
11575 : ****************************************************************/
11576 :
11577 0 : WERROR _spoolss_73(struct pipes_struct *p,
11578 : struct spoolss_73 *r)
11579 : {
11580 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11581 0 : return WERR_NOT_SUPPORTED;
11582 : }
11583 :
11584 : /****************************************************************
11585 : _spoolss_RpcLogJobInfoForBranchOffice
11586 : ****************************************************************/
11587 :
11588 0 : WERROR _spoolss_LogJobInfoForBranchOffice(struct pipes_struct *p,
11589 : struct spoolss_LogJobInfoForBranchOffice *r)
11590 : {
11591 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11592 0 : return WERR_NOT_SUPPORTED;
11593 : }
11594 :
11595 : static NTSTATUS spoolss__op_init_server(struct dcesrv_context *dce_ctx,
11596 : const struct dcesrv_endpoint_server *ep_server);
11597 :
11598 : static NTSTATUS spoolss__op_shutdown_server(struct dcesrv_context *dce_ctx,
11599 : const struct dcesrv_endpoint_server *ep_server);
11600 :
11601 : #define DCESRV_INTERFACE_SPOOLSS_INIT_SERVER \
11602 : spoolss_init_server
11603 :
11604 : #define DCESRV_INTERFACE_SPOOLSS_SHUTDOWN_SERVER \
11605 : spoolss_shutdown_server
11606 :
11607 2 : static NTSTATUS spoolss_init_server(struct dcesrv_context *dce_ctx,
11608 : const struct dcesrv_endpoint_server *ep_server)
11609 : {
11610 2 : struct messaging_context *msg_ctx = global_messaging_context();
11611 : bool ok;
11612 :
11613 : /*
11614 : * Migrate the printers first.
11615 : */
11616 2 : ok = nt_printing_tdb_migrate(msg_ctx);
11617 2 : if (!ok) {
11618 0 : return NT_STATUS_UNSUCCESSFUL;
11619 : }
11620 :
11621 2 : return spoolss__op_init_server(dce_ctx, ep_server);
11622 : }
11623 :
11624 2 : static NTSTATUS spoolss_shutdown_server(struct dcesrv_context *dce_ctx,
11625 : const struct dcesrv_endpoint_server *ep_server)
11626 : {
11627 2 : srv_spoolss_cleanup();
11628 :
11629 2 : return spoolss__op_shutdown_server(dce_ctx, ep_server);
11630 : }
11631 :
11632 : /* include the generated boilerplate */
11633 : #include "librpc/gen_ndr/ndr_spoolss_scompat.c"
|