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 "lib/util/util_file.h"
32 : #include "libsmb/namequery.h"
33 : #include "ntdomain.h"
34 : #include "nt_printing.h"
35 : #include "srv_spoolss_util.h"
36 : #include "librpc/gen_ndr/ndr_spoolss.h"
37 : #include "librpc/gen_ndr/ndr_spoolss_scompat.h"
38 : #include "../librpc/gen_ndr/ndr_spoolss_c.h"
39 : #include "rpc_client/init_spoolss.h"
40 : #include "rpc_client/cli_pipe.h"
41 : #include "../libcli/security/security.h"
42 : #include "librpc/gen_ndr/ndr_security.h"
43 : #include "registry.h"
44 : #include "include/printing.h"
45 : #include "secrets.h"
46 : #include "../librpc/gen_ndr/netlogon.h"
47 : #include "rpc_misc.h"
48 : #include "printing/notify.h"
49 : #include "serverid.h"
50 : #include "../libcli/registry/util_reg.h"
51 : #include "smbd/smbd.h"
52 : #include "smbd/globals.h"
53 : #include "auth.h"
54 : #include "messages.h"
55 : #include "rpc_server/spoolss/srv_spoolss_nt.h"
56 : #include "util_tdb.h"
57 : #include "libsmb/libsmb.h"
58 : #include "printing/printer_list.h"
59 : #include "../lib/tsocket/tsocket.h"
60 : #include "rpc_client/cli_winreg_spoolss.h"
61 : #include "../libcli/smb/smbXcli_base.h"
62 : #include "rpc_server/spoolss/srv_spoolss_handle.h"
63 : #include "lib/gencache.h"
64 : #include "rpc_server/rpc_server.h"
65 : #include "librpc/rpc/dcesrv_core.h"
66 : #include "printing/nt_printing_migrate_internal.h"
67 : #include "lib/util/string_wrappers.h"
68 : #include "lib/global_contexts.h"
69 :
70 : /* macros stolen from s4 spoolss server */
71 : #define SPOOLSS_BUFFER_UNION(fn,info,level) \
72 : ((info)?ndr_size_##fn(info, level, 0):0)
73 :
74 : #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
75 : ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
76 :
77 : #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
78 : ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
79 :
80 : #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
81 :
82 : #undef DBGC_CLASS
83 : #define DBGC_CLASS DBGC_RPC_SRV
84 :
85 : #ifndef MAX_OPEN_PRINTER_EXS
86 : #define MAX_OPEN_PRINTER_EXS 50
87 : #endif
88 :
89 : #define GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT 5
90 : #define GLOBAL_SPOOLSS_OS_MINOR_DEFAULT 2
91 : #define GLOBAL_SPOOLSS_OS_BUILD_DEFAULT 3790
92 : #define GLOBAL_SPOOLSS_ARCHITECTURE SPOOLSS_ARCHITECTURE_x64
93 :
94 : static struct printer_handle *printers_list;
95 :
96 : struct printer_session_counter {
97 : struct printer_session_counter *next;
98 : struct printer_session_counter *prev;
99 :
100 : int snum;
101 : uint32_t counter;
102 : };
103 :
104 : static struct printer_session_counter *counter_list;
105 :
106 : struct notify_back_channel {
107 : struct notify_back_channel *prev, *next;
108 :
109 : /* associated client */
110 : struct sockaddr_storage client_address;
111 :
112 : /* print notify back-channel pipe handle*/
113 : struct rpc_pipe_client *cli_pipe;
114 : struct cli_state *cli;
115 : uint32_t active_connections;
116 : };
117 :
118 : static struct notify_back_channel *back_channels;
119 :
120 : /* Map generic permissions to printer object specific permissions */
121 :
122 : const struct standard_mapping printer_std_mapping = {
123 : PRINTER_READ,
124 : PRINTER_WRITE,
125 : PRINTER_EXECUTE,
126 : PRINTER_ALL_ACCESS
127 : };
128 :
129 : /* Map generic permissions to print server object specific permissions */
130 :
131 : const struct standard_mapping printserver_std_mapping = {
132 : SERVER_READ,
133 : SERVER_WRITE,
134 : SERVER_EXECUTE,
135 : SERVER_ALL_ACCESS
136 : };
137 :
138 : /* API table for Xcv Monitor functions */
139 :
140 : struct xcv_api_table {
141 : const char *name;
142 : WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
143 : };
144 :
145 : static void prune_printername_cache(void);
146 :
147 : /********************************************************************
148 : * Canonicalize servername.
149 : ********************************************************************/
150 :
151 520 : static const char *canon_servername(const char *servername)
152 : {
153 520 : const char *pservername = servername;
154 :
155 520 : if (servername == NULL) {
156 0 : return "";
157 : }
158 :
159 1568 : while (*pservername == '\\') {
160 1048 : pservername++;
161 : }
162 520 : return pservername;
163 : }
164 :
165 : /* translate between internal status numbers and NT status numbers */
166 392 : static int nt_printj_status(int v)
167 : {
168 392 : switch (v) {
169 392 : case LPQ_QUEUED:
170 392 : return 0;
171 0 : case LPQ_PAUSED:
172 0 : return JOB_STATUS_PAUSED;
173 0 : case LPQ_SPOOLING:
174 0 : return JOB_STATUS_SPOOLING;
175 0 : case LPQ_PRINTING:
176 0 : return JOB_STATUS_PRINTING;
177 0 : case LPQ_ERROR:
178 0 : return JOB_STATUS_ERROR;
179 0 : case LPQ_DELETING:
180 0 : return JOB_STATUS_DELETING;
181 0 : case LPQ_OFFLINE:
182 0 : return JOB_STATUS_OFFLINE;
183 0 : case LPQ_PAPEROUT:
184 0 : return JOB_STATUS_PAPEROUT;
185 0 : case LPQ_PRINTED:
186 0 : return JOB_STATUS_PRINTED;
187 0 : case LPQ_DELETED:
188 0 : return JOB_STATUS_DELETED;
189 0 : case LPQ_BLOCKED:
190 0 : return JOB_STATUS_BLOCKED_DEVQ;
191 0 : case LPQ_USER_INTERVENTION:
192 0 : return JOB_STATUS_USER_INTERVENTION;
193 : }
194 0 : return 0;
195 : }
196 :
197 1636 : static int nt_printq_status(int v)
198 : {
199 1636 : switch (v) {
200 236 : case LPQ_PAUSED:
201 236 : return PRINTER_STATUS_PAUSED;
202 1400 : case LPQ_QUEUED:
203 : case LPQ_SPOOLING:
204 : case LPQ_PRINTING:
205 1400 : return 0;
206 : }
207 0 : return 0;
208 : }
209 :
210 : /***************************************************************************
211 : Disconnect from the client
212 : ****************************************************************************/
213 :
214 2 : static void srv_spoolss_replycloseprinter(int snum,
215 : struct printer_handle *prn_hnd)
216 : {
217 0 : WERROR result;
218 0 : NTSTATUS status;
219 :
220 : /*
221 : * Tell the specific printing tdb we no longer want messages for this printer
222 : * by deregistering our PID.
223 : */
224 :
225 2 : if (!print_notify_deregister_pid(snum)) {
226 0 : DEBUG(0, ("Failed to register our pid for printer %s\n",
227 : lp_const_servicename(snum)));
228 : }
229 :
230 : /* weird if the test succeeds !!! */
231 2 : if (prn_hnd->notify.cli_chan == NULL ||
232 2 : prn_hnd->notify.cli_chan->cli_pipe == NULL ||
233 2 : prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
234 2 : prn_hnd->notify.cli_chan->active_connections == 0) {
235 0 : DEBUG(0, ("Trying to close unexisting backchannel!\n"));
236 0 : DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
237 0 : TALLOC_FREE(prn_hnd->notify.cli_chan);
238 0 : return;
239 : }
240 :
241 2 : status = dcerpc_spoolss_ReplyClosePrinter(
242 2 : prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
243 : talloc_tos(),
244 : &prn_hnd->notify.cli_hnd,
245 : &result);
246 2 : if (!NT_STATUS_IS_OK(status)) {
247 0 : DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
248 : nt_errstr(status)));
249 0 : result = ntstatus_to_werror(status);
250 2 : } else if (!W_ERROR_IS_OK(result)) {
251 0 : DEBUG(0, ("reply_close_printer failed [%s].\n",
252 : win_errstr(result)));
253 : }
254 :
255 : /* if it's the last connection, deconnect the IPC$ share */
256 2 : if (prn_hnd->notify.cli_chan->active_connections == 1) {
257 :
258 2 : cli_shutdown(prn_hnd->notify.cli_chan->cli);
259 2 : DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
260 2 : TALLOC_FREE(prn_hnd->notify.cli_chan);
261 :
262 2 : if (prn_hnd->notify.msg_ctx != NULL) {
263 2 : messaging_deregister(prn_hnd->notify.msg_ctx,
264 : MSG_PRINTER_NOTIFY2, NULL);
265 : }
266 : }
267 :
268 2 : if (prn_hnd->notify.cli_chan) {
269 0 : prn_hnd->notify.cli_chan->active_connections--;
270 0 : prn_hnd->notify.cli_chan = NULL;
271 : }
272 : }
273 :
274 : /****************************************************************************
275 : Functions to free a printer entry datastruct.
276 : ****************************************************************************/
277 :
278 972 : static int printer_entry_destructor(struct printer_handle *Printer)
279 : {
280 972 : if (Printer->notify.cli_chan != NULL &&
281 2 : Printer->notify.cli_chan->active_connections > 0) {
282 2 : int snum = -1;
283 :
284 2 : switch(Printer->printer_type) {
285 2 : case SPLHND_SERVER:
286 2 : srv_spoolss_replycloseprinter(snum, Printer);
287 2 : break;
288 :
289 0 : case SPLHND_PRINTER:
290 0 : snum = print_queue_snum(Printer->sharename);
291 0 : if (snum != -1) {
292 0 : srv_spoolss_replycloseprinter(snum, Printer);
293 : }
294 0 : break;
295 0 : default:
296 0 : break;
297 : }
298 : }
299 :
300 972 : Printer->notify.flags=0;
301 972 : Printer->notify.options=0;
302 972 : Printer->notify.localmachine[0]='\0';
303 972 : Printer->notify.printerlocal=0;
304 972 : TALLOC_FREE(Printer->notify.option);
305 972 : TALLOC_FREE(Printer->devmode);
306 :
307 : /* Remove from the internal list. */
308 972 : DLIST_REMOVE(printers_list, Printer);
309 972 : return 0;
310 : }
311 :
312 : /****************************************************************************
313 : find printer index by handle
314 : ****************************************************************************/
315 :
316 52178 : static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
317 : struct policy_handle *hnd)
318 : {
319 52178 : struct printer_handle *find_printer = NULL;
320 0 : NTSTATUS status;
321 :
322 52178 : find_printer = find_policy_by_hnd(p,
323 : hnd,
324 : DCESRV_HANDLE_ANY,
325 : struct printer_handle,
326 0 : &status);
327 52178 : if (!NT_STATUS_IS_OK(status)) {
328 0 : DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: %s\n",
329 : nt_errstr(status)));
330 0 : return NULL;
331 : }
332 :
333 52178 : return find_printer;
334 : }
335 :
336 : /****************************************************************************
337 : Close printer index by handle.
338 : ****************************************************************************/
339 :
340 956 : static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
341 : {
342 956 : struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
343 :
344 956 : if (!Printer) {
345 0 : DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
346 : OUR_HANDLE(hnd)));
347 0 : return false;
348 : }
349 :
350 956 : close_policy_hnd(p, hnd);
351 :
352 956 : return true;
353 : }
354 :
355 : /****************************************************************************
356 : Delete a printer given a handle.
357 : ****************************************************************************/
358 :
359 16 : static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
360 : const char *sharename,
361 : struct messaging_context *msg_ctx)
362 : {
363 0 : const struct loadparm_substitution *lp_sub =
364 16 : loadparm_s3_global_substitution();
365 16 : char *cmd = lp_deleteprinter_command(talloc_tos(), lp_sub);
366 16 : char *command = NULL;
367 0 : int ret;
368 16 : bool is_print_op = false;
369 :
370 : /* can't fail if we don't try */
371 :
372 16 : if ( !*cmd )
373 0 : return WERR_OK;
374 :
375 16 : command = talloc_asprintf(ctx,
376 : "%s \"%s\"",
377 : cmd, sharename);
378 16 : if (!command) {
379 0 : return WERR_NOT_ENOUGH_MEMORY;
380 : }
381 16 : if ( token )
382 16 : is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
383 :
384 16 : DEBUG(10,("Running [%s]\n", command));
385 :
386 : /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
387 :
388 16 : if ( is_print_op )
389 0 : become_root();
390 :
391 16 : ret = smbrun(command, NULL, NULL);
392 16 : if (ret == 0) {
393 : /* Tell everyone we updated smb.conf. */
394 16 : messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
395 : }
396 :
397 16 : if ( is_print_op )
398 0 : unbecome_root();
399 :
400 : /********** END SePrintOperatorPrivlege BLOCK **********/
401 :
402 16 : DEBUGADD(10,("returned [%d]\n", ret));
403 :
404 16 : TALLOC_FREE(command);
405 :
406 16 : if (ret != 0)
407 0 : return WERR_INVALID_HANDLE; /* What to return here? */
408 :
409 16 : return WERR_OK;
410 : }
411 :
412 : /****************************************************************************
413 : Delete a printer given a handle.
414 : ****************************************************************************/
415 :
416 16 : static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
417 : {
418 16 : struct dcesrv_call_state *dce_call = p->dce_call;
419 0 : struct auth_session_info *session_info =
420 16 : dcesrv_call_session_info(dce_call);
421 16 : struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
422 0 : WERROR result;
423 :
424 16 : if (!Printer) {
425 0 : DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
426 : OUR_HANDLE(hnd)));
427 0 : return WERR_INVALID_HANDLE;
428 : }
429 :
430 : /*
431 : * It turns out that Windows allows delete printer on a handle
432 : * opened by an admin user, then used on a pipe handle created
433 : * by an anonymous user..... but they're working on security.... riiight !
434 : * JRA.
435 : */
436 :
437 16 : if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
438 0 : DEBUG(3, ("delete_printer_handle: denied by handle\n"));
439 0 : return WERR_ACCESS_DENIED;
440 : }
441 :
442 : /* this does not need a become root since the access check has been
443 : done on the handle already */
444 :
445 16 : result = winreg_delete_printer_key_internal(p->mem_ctx,
446 : get_session_info_system(),
447 : p->msg_ctx,
448 16 : Printer->sharename,
449 : "");
450 16 : if (!W_ERROR_IS_OK(result)) {
451 0 : DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
452 0 : return WERR_INVALID_HANDLE;
453 : }
454 :
455 16 : result = delete_printer_hook(p->mem_ctx, session_info->security_token,
456 16 : Printer->sharename, p->msg_ctx);
457 16 : if (!W_ERROR_IS_OK(result)) {
458 0 : return result;
459 : }
460 16 : prune_printername_cache();
461 16 : return WERR_OK;
462 : }
463 :
464 : /****************************************************************************
465 : Return the snum of a printer corresponding to an handle.
466 : ****************************************************************************/
467 :
468 24720 : static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
469 : int *number, struct share_params **params)
470 : {
471 24720 : struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
472 :
473 24720 : if (!Printer) {
474 0 : DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
475 : OUR_HANDLE(hnd)));
476 0 : return false;
477 : }
478 :
479 24720 : switch (Printer->printer_type) {
480 24720 : case SPLHND_PRINTER:
481 24720 : DEBUG(4,("short name:%s\n", Printer->sharename));
482 24720 : *number = print_queue_snum(Printer->sharename);
483 24720 : return (*number != -1);
484 0 : case SPLHND_SERVER:
485 0 : return false;
486 0 : default:
487 0 : return false;
488 : }
489 : }
490 :
491 : /****************************************************************************
492 : Set printer handle type.
493 : Check if it's \\server or \\server\printer
494 : ****************************************************************************/
495 :
496 972 : static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
497 : {
498 972 : DEBUG(3,("Setting printer type=%s\n", handlename));
499 :
500 : /* it's a print server */
501 972 : if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
502 122 : DEBUGADD(4,("Printer is a print server\n"));
503 122 : Printer->printer_type = SPLHND_SERVER;
504 : }
505 : /* it's a printer (set_printer_hnd_name() will handle port monitors */
506 : else {
507 850 : DEBUGADD(4,("Printer is a printer\n"));
508 850 : Printer->printer_type = SPLHND_PRINTER;
509 : }
510 :
511 972 : return true;
512 : }
513 :
514 372 : static void prune_printername_cache_fn(const char *key, const char *value,
515 : time_t timeout, void *private_data)
516 : {
517 372 : gencache_del(key);
518 372 : }
519 :
520 132 : static void prune_printername_cache(void)
521 : {
522 132 : gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
523 132 : }
524 :
525 : /****************************************************************************
526 : Set printer handle name.. Accept names like \\server, \\server\printer,
527 : \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
528 : the MSDN docs regarding OpenPrinter() for details on the XcvData() and
529 : XcvDataPort() interface.
530 : ****************************************************************************/
531 :
532 972 : static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
533 : const struct auth_session_info *session_info,
534 : struct messaging_context *msg_ctx,
535 : struct printer_handle *Printer,
536 : const char *handlename)
537 : {
538 0 : int snum;
539 972 : int n_services=lp_numservices();
540 0 : char *aprinter;
541 0 : const char *printername;
542 972 : const char *servername = NULL;
543 0 : fstring sname;
544 972 : bool found = false;
545 972 : struct spoolss_PrinterInfo2 *info2 = NULL;
546 0 : WERROR result;
547 0 : char *p;
548 :
549 : /*
550 : * Hopefully nobody names his printers like this. Maybe \ or ,
551 : * are illegal in printer names even?
552 : */
553 972 : const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
554 0 : char *cache_key;
555 0 : char *tmp;
556 :
557 972 : DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
558 : (unsigned long)strlen(handlename)));
559 :
560 972 : aprinter = discard_const_p(char, handlename);
561 972 : if ( *handlename == '\\' ) {
562 252 : servername = canon_servername(handlename);
563 252 : if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
564 122 : *aprinter = '\0';
565 122 : aprinter++;
566 : }
567 252 : if (!is_myname_or_ipaddr(servername)) {
568 12 : return WERR_INVALID_PRINTER_NAME;
569 : }
570 240 : Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
571 240 : if (Printer->servername == NULL) {
572 0 : return WERR_NOT_ENOUGH_MEMORY;
573 : }
574 : }
575 :
576 960 : if (Printer->printer_type == SPLHND_SERVER) {
577 118 : return WERR_OK;
578 : }
579 :
580 842 : if (Printer->printer_type != SPLHND_PRINTER) {
581 0 : return WERR_INVALID_HANDLE;
582 : }
583 :
584 842 : DEBUGADD(5, ("searching for [%s]\n", aprinter));
585 :
586 842 : p = strchr(aprinter, ',');
587 842 : if (p != NULL) {
588 504 : char *p2 = p;
589 504 : p++;
590 504 : if (*p == ' ') {
591 308 : p++;
592 : }
593 504 : if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
594 140 : *p2 = '\0';
595 364 : } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
596 140 : *p2 = '\0';
597 : }
598 : }
599 :
600 842 : if (p) {
601 504 : DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
602 : }
603 :
604 : /* check for the Port Monitor Interface */
605 842 : if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
606 0 : Printer->printer_type = SPLHND_PORTMON_TCP;
607 0 : fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
608 0 : found = true;
609 : }
610 842 : else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
611 0 : Printer->printer_type = SPLHND_PORTMON_LOCAL;
612 0 : fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
613 0 : found = true;
614 : }
615 :
616 842 : cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s", aprinter);
617 842 : if (cache_key == NULL) {
618 0 : return WERR_NOT_ENOUGH_MEMORY;
619 : }
620 :
621 : /*
622 : * With hundreds of printers, the "for" loop iterating all
623 : * shares can be quite expensive, as it is done on every
624 : * OpenPrinter. The loop maps "aprinter" to "sname", the
625 : * result of which we cache in gencache.
626 : */
627 842 : if (gencache_get(cache_key, talloc_tos(), &tmp, NULL)) {
628 462 : found = (strcmp(tmp, printer_not_found) != 0);
629 462 : if (!found) {
630 32 : DEBUG(4, ("Printer %s not found\n", aprinter));
631 32 : TALLOC_FREE(tmp);
632 32 : return WERR_INVALID_PRINTER_NAME;
633 : }
634 430 : fstrcpy(sname, tmp);
635 430 : TALLOC_FREE(tmp);
636 : }
637 :
638 : /* Search all sharenames first as this is easier than pulling
639 : the printer_info_2 off of disk. Don't use find_service() since
640 : that calls out to map_username() */
641 :
642 : /* do another loop to look for printernames */
643 23566 : for (snum = 0; !found && snum < n_services; snum++) {
644 22848 : const char *printer = lp_const_servicename(snum);
645 :
646 : /* no point going on if this is not a printer */
647 22848 : if (!(lp_snum_ok(snum) && lp_printable(snum))) {
648 20970 : continue;
649 : }
650 :
651 : /* ignore [printers] share */
652 1878 : if (strequal(printer, "printers")) {
653 0 : continue;
654 : }
655 :
656 1878 : fstrcpy(sname, printer);
657 1878 : if (strequal(aprinter, printer)) {
658 84 : found = true;
659 84 : break;
660 : }
661 :
662 : /* no point looking up the printer object if
663 : we aren't allowing printername != sharename */
664 1794 : if (lp_force_printername(snum)) {
665 0 : continue;
666 : }
667 :
668 1794 : result = winreg_get_printer_internal(mem_ctx,
669 : session_info,
670 : msg_ctx,
671 : sname,
672 : &info2);
673 1794 : if ( !W_ERROR_IS_OK(result) ) {
674 54 : DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
675 : sname, win_errstr(result)));
676 54 : continue;
677 : }
678 :
679 1740 : printername = strrchr(info2->printername, '\\');
680 1740 : if (printername == NULL) {
681 1740 : printername = info2->printername;
682 : } else {
683 0 : printername++;
684 : }
685 :
686 1740 : if (strequal(printername, aprinter)) {
687 8 : found = true;
688 8 : break;
689 : }
690 :
691 1732 : DEBUGADD(10, ("printername: %s\n", printername));
692 :
693 1732 : TALLOC_FREE(info2);
694 : }
695 :
696 810 : if (!found) {
697 288 : gencache_set(cache_key, printer_not_found,
698 288 : time(NULL) + 300);
699 288 : TALLOC_FREE(cache_key);
700 288 : DEBUGADD(4,("Printer not found\n"));
701 288 : return WERR_INVALID_PRINTER_NAME;
702 : }
703 :
704 522 : gencache_set(cache_key, sname, time(NULL) + 300);
705 522 : TALLOC_FREE(cache_key);
706 :
707 522 : DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
708 :
709 522 : strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
710 :
711 522 : return WERR_OK;
712 : }
713 :
714 : /****************************************************************************
715 : Find first available printer slot. creates a printer handle for you.
716 : ****************************************************************************/
717 :
718 972 : static WERROR open_printer_hnd(struct pipes_struct *p,
719 : struct policy_handle *hnd,
720 : const char *name,
721 : uint32_t access_granted)
722 : {
723 0 : struct printer_handle *new_printer;
724 0 : WERROR result;
725 :
726 972 : DEBUG(10,("open_printer_hnd: name [%s]\n", name));
727 :
728 972 : new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
729 972 : if (new_printer == NULL) {
730 0 : return WERR_NOT_ENOUGH_MEMORY;
731 : }
732 972 : talloc_set_destructor(new_printer, printer_entry_destructor);
733 :
734 : /* This also steals the printer_handle on the policy_handle */
735 972 : if (!create_policy_hnd(p, hnd, 0, new_printer)) {
736 0 : TALLOC_FREE(new_printer);
737 0 : return WERR_INVALID_HANDLE;
738 : }
739 :
740 : /* Add to the internal list. */
741 972 : DLIST_ADD(printers_list, new_printer);
742 :
743 972 : new_printer->notify.option=NULL;
744 :
745 972 : if (!set_printer_hnd_printertype(new_printer, name)) {
746 0 : close_printer_handle(p, hnd);
747 0 : return WERR_INVALID_HANDLE;
748 : }
749 :
750 972 : result = set_printer_hnd_name(p->mem_ctx,
751 : get_session_info_system(),
752 : p->msg_ctx,
753 : new_printer, name);
754 972 : if (!W_ERROR_IS_OK(result)) {
755 332 : close_printer_handle(p, hnd);
756 332 : return result;
757 : }
758 :
759 640 : new_printer->access_granted = access_granted;
760 :
761 640 : DBG_INFO("%d printer handles active\n", (int)num_pipe_handles());
762 :
763 640 : return WERR_OK;
764 : }
765 :
766 : /***************************************************************************
767 : check to see if the client notify handle is monitoring the notification
768 : given by (notify_type, notify_field).
769 : **************************************************************************/
770 :
771 0 : static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
772 : uint16_t notify_field)
773 : {
774 0 : return true;
775 : }
776 :
777 0 : static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
778 : uint16_t notify_field)
779 : {
780 0 : struct spoolss_NotifyOption *option = p->notify.option;
781 0 : uint32_t i, j;
782 :
783 : /*
784 : * Flags should always be zero when the change notify
785 : * is registered by the client's spooler. A user Win32 app
786 : * might use the flags though instead of the NOTIFY_OPTION_INFO
787 : * --jerry
788 : */
789 :
790 0 : if (!option) {
791 0 : return false;
792 : }
793 :
794 0 : if (p->notify.flags)
795 0 : return is_monitoring_event_flags(
796 : p->notify.flags, notify_type, notify_field);
797 :
798 0 : for (i = 0; i < option->count; i++) {
799 :
800 : /* Check match for notify_type */
801 :
802 0 : if (option->types[i].type != notify_type)
803 0 : continue;
804 :
805 : /* Check match for field */
806 :
807 0 : for (j = 0; j < option->types[i].count; j++) {
808 0 : if (option->types[i].fields[j].field == notify_field) {
809 0 : return true;
810 : }
811 : }
812 : }
813 :
814 0 : DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
815 : p->servername, p->sharename, notify_type, notify_field));
816 :
817 0 : return false;
818 : }
819 :
820 : #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
821 : _data->data.integer[0] = _integer; \
822 : _data->data.integer[1] = 0;
823 :
824 :
825 : #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
826 : _data->data.string.string = talloc_strdup(mem_ctx, _p); \
827 : if (!_data->data.string.string) {\
828 : _data->data.string.size = 0; \
829 : } \
830 : _data->data.string.size = strlen_m_term(_p) * 2;
831 :
832 : #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
833 : _data->data.devmode.devmode = _devmode;
834 :
835 0 : static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
836 : struct tm *t,
837 : const char **pp,
838 : uint32_t *plen)
839 : {
840 0 : struct spoolss_Time st;
841 0 : uint32_t len = 16;
842 0 : char *p;
843 :
844 0 : if (!init_systemtime(&st, t)) {
845 0 : return;
846 : }
847 :
848 0 : p = talloc_array(mem_ctx, char, len);
849 0 : if (!p) {
850 0 : return;
851 : }
852 :
853 : /*
854 : * Systemtime must be linearized as a set of UINT16's.
855 : * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
856 : */
857 :
858 0 : SSVAL(p, 0, st.year);
859 0 : SSVAL(p, 2, st.month);
860 0 : SSVAL(p, 4, st.day_of_week);
861 0 : SSVAL(p, 6, st.day);
862 0 : SSVAL(p, 8, st.hour);
863 0 : SSVAL(p, 10, st.minute);
864 0 : SSVAL(p, 12, st.second);
865 0 : SSVAL(p, 14, st.millisecond);
866 :
867 0 : *pp = p;
868 0 : *plen = len;
869 : }
870 :
871 : /* Convert a notification message to a struct spoolss_Notify */
872 :
873 0 : static void notify_one_value(struct spoolss_notify_msg *msg,
874 : struct spoolss_Notify *data,
875 : TALLOC_CTX *mem_ctx)
876 : {
877 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
878 0 : }
879 :
880 0 : static void notify_string(struct spoolss_notify_msg *msg,
881 : struct spoolss_Notify *data,
882 : TALLOC_CTX *mem_ctx)
883 : {
884 : /* The length of the message includes the trailing \0 */
885 :
886 0 : data->data.string.size = msg->len * 2;
887 0 : data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
888 0 : if (!data->data.string.string) {
889 0 : data->data.string.size = 0;
890 0 : return;
891 : }
892 : }
893 :
894 0 : static void notify_system_time(struct spoolss_notify_msg *msg,
895 : struct spoolss_Notify *data,
896 : TALLOC_CTX *mem_ctx)
897 : {
898 0 : data->data.string.string = NULL;
899 0 : data->data.string.size = 0;
900 :
901 0 : if (msg->len != sizeof(time_t)) {
902 0 : DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
903 : msg->len));
904 0 : return;
905 : }
906 :
907 0 : init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
908 : &data->data.string.string,
909 : &data->data.string.size);
910 : }
911 :
912 : struct notify2_message_table {
913 : const char *name;
914 : void (*fn)(struct spoolss_notify_msg *msg,
915 : struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
916 : };
917 :
918 : static struct notify2_message_table printer_notify_table[] = {
919 : /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
920 : /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
921 : /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
922 : /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
923 : /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
924 : /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
925 : /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
926 : /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
927 : /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
928 : /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
929 : /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
930 : /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
931 : /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
932 : /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
933 : /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
934 : /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
935 : /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
936 : /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
937 : /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
938 : };
939 :
940 : static struct notify2_message_table job_notify_table[] = {
941 : /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
942 : /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
943 : /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
944 : /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
945 : /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
946 : /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
947 : /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
948 : /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
949 : /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
950 : /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
951 : /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
952 : /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
953 : /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
954 : /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
955 : /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
956 : /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
957 : /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
958 : /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
959 : /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
960 : /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
961 : /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
962 : /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
963 : /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
964 : /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
965 : };
966 :
967 :
968 : /***********************************************************************
969 : Allocate talloc context for container object
970 : **********************************************************************/
971 :
972 0 : static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
973 : {
974 0 : if ( !ctr )
975 0 : return;
976 :
977 0 : ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
978 :
979 0 : return;
980 : }
981 :
982 : /***********************************************************************
983 : release all allocated memory and zero out structure
984 : **********************************************************************/
985 :
986 0 : static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
987 : {
988 0 : if ( !ctr )
989 0 : return;
990 :
991 0 : if ( ctr->ctx )
992 0 : talloc_destroy(ctr->ctx);
993 :
994 0 : ZERO_STRUCTP(ctr);
995 :
996 0 : return;
997 : }
998 :
999 : /***********************************************************************
1000 : **********************************************************************/
1001 :
1002 0 : static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1003 : {
1004 0 : if ( !ctr )
1005 0 : return NULL;
1006 :
1007 0 : return ctr->ctx;
1008 : }
1009 :
1010 : /***********************************************************************
1011 : **********************************************************************/
1012 :
1013 0 : static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1014 : {
1015 0 : if ( !ctr || !ctr->msg_groups )
1016 0 : return NULL;
1017 :
1018 0 : if ( idx >= ctr->num_groups )
1019 0 : return NULL;
1020 :
1021 0 : return &ctr->msg_groups[idx];
1022 :
1023 : }
1024 :
1025 : /***********************************************************************
1026 : How many groups of change messages do we have ?
1027 : **********************************************************************/
1028 :
1029 0 : static uint32_t notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1030 : {
1031 0 : if ( !ctr )
1032 0 : return 0;
1033 :
1034 0 : return ctr->num_groups;
1035 : }
1036 :
1037 : /***********************************************************************
1038 : Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1039 : **********************************************************************/
1040 :
1041 0 : static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1042 : {
1043 0 : SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
1044 0 : SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
1045 0 : SPOOLSS_NOTIFY_MSG *msg_list = NULL;
1046 0 : uint32_t i, new_slot;
1047 :
1048 0 : if ( !ctr || !msg )
1049 0 : return 0;
1050 :
1051 : /* loop over all groups looking for a matching printer name */
1052 :
1053 0 : for ( i=0; i<ctr->num_groups; i++ ) {
1054 0 : if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1055 0 : break;
1056 : }
1057 :
1058 : /* add a new group? */
1059 :
1060 0 : if ( i == ctr->num_groups ) {
1061 0 : ctr->num_groups++;
1062 :
1063 0 : if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1064 0 : DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1065 0 : return 0;
1066 : }
1067 0 : ctr->msg_groups = groups;
1068 :
1069 : /* clear the new entry and set the printer name */
1070 :
1071 0 : ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1072 0 : fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1073 : }
1074 :
1075 : /* add the change messages; 'i' is the correct index now regardless */
1076 :
1077 0 : msg_grp = &ctr->msg_groups[i];
1078 :
1079 0 : msg_grp->num_msgs++;
1080 :
1081 0 : if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1082 0 : DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1083 0 : return 0;
1084 : }
1085 0 : msg_grp->msgs = msg_list;
1086 :
1087 0 : new_slot = msg_grp->num_msgs-1;
1088 0 : memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1089 :
1090 : /* need to allocate own copy of data */
1091 :
1092 0 : if ( msg->len != 0 )
1093 0 : msg_grp->msgs[new_slot].notify.data = (char *)
1094 0 : talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1095 :
1096 0 : return ctr->num_groups;
1097 : }
1098 :
1099 : static void construct_info_data(struct spoolss_Notify *info_data,
1100 : enum spoolss_NotifyType type,
1101 : uint16_t field, int id);
1102 :
1103 : /***********************************************************************
1104 : Send a change notification message on all handles which have a call
1105 : back registered
1106 : **********************************************************************/
1107 :
1108 0 : static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1109 : struct printer_handle *prn_hnd,
1110 : SPOOLSS_NOTIFY_MSG *messages,
1111 : uint32_t num_msgs,
1112 : struct spoolss_Notify **_notifies,
1113 : size_t *_count)
1114 : {
1115 0 : struct spoolss_Notify *notifies;
1116 0 : SPOOLSS_NOTIFY_MSG *msg;
1117 0 : size_t count = 0;
1118 0 : uint32_t id;
1119 0 : uint32_t i;
1120 :
1121 0 : notifies = talloc_zero_array(mem_ctx,
1122 : struct spoolss_Notify, num_msgs);
1123 0 : if (!notifies) {
1124 0 : return ENOMEM;
1125 : }
1126 :
1127 0 : for (i = 0; i < num_msgs; i++) {
1128 :
1129 0 : msg = &messages[i];
1130 :
1131 : /* Are we monitoring this event? */
1132 :
1133 0 : if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1134 0 : continue;
1135 : }
1136 :
1137 0 : DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1138 : "for printer [%s]\n",
1139 : msg->type, msg->field, prn_hnd->sharename));
1140 :
1141 : /*
1142 : * if the is a printer notification handle and not a job
1143 : * notification type, then set the id to 0.
1144 : * Otherwise just use what was specified in the message.
1145 : *
1146 : * When registering change notification on a print server
1147 : * handle we always need to send back the id (snum) matching
1148 : * the printer for which the change took place.
1149 : * For change notify registered on a printer handle,
1150 : * this does not matter and the id should be 0.
1151 : *
1152 : * --jerry
1153 : */
1154 :
1155 0 : if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1156 0 : (prn_hnd->printer_type == SPLHND_PRINTER)) {
1157 0 : id = 0;
1158 : } else {
1159 0 : id = msg->id;
1160 : }
1161 :
1162 : /* Convert unix jobid to smb jobid */
1163 :
1164 0 : if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1165 0 : id = sysjob_to_jobid(msg->id);
1166 :
1167 0 : if (id == -1) {
1168 0 : DEBUG(3, ("no such unix jobid %d\n",
1169 : msg->id));
1170 0 : continue;
1171 : }
1172 : }
1173 :
1174 0 : construct_info_data(¬ifies[count],
1175 0 : msg->type, msg->field, id);
1176 :
1177 0 : switch(msg->type) {
1178 0 : case PRINTER_NOTIFY_TYPE:
1179 0 : if (printer_notify_table[msg->field].fn) {
1180 0 : printer_notify_table[msg->field].fn(msg,
1181 0 : ¬ifies[count], mem_ctx);
1182 : }
1183 0 : break;
1184 :
1185 0 : case JOB_NOTIFY_TYPE:
1186 0 : if (job_notify_table[msg->field].fn) {
1187 0 : job_notify_table[msg->field].fn(msg,
1188 0 : ¬ifies[count], mem_ctx);
1189 : }
1190 0 : break;
1191 :
1192 0 : default:
1193 0 : DEBUG(5, ("Unknown notification type %d\n",
1194 : msg->type));
1195 0 : continue;
1196 : }
1197 :
1198 0 : count++;
1199 : }
1200 :
1201 0 : *_notifies = notifies;
1202 0 : *_count = count;
1203 :
1204 0 : return 0;
1205 : }
1206 :
1207 0 : static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1208 : struct printer_handle *prn_hnd,
1209 : SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1210 : {
1211 0 : struct spoolss_Notify *notifies;
1212 0 : size_t count = 0;
1213 0 : union spoolss_ReplyPrinterInfo info;
1214 0 : struct spoolss_NotifyInfo info0;
1215 0 : uint32_t reply_result;
1216 0 : NTSTATUS status;
1217 0 : WERROR werr;
1218 0 : int ret;
1219 :
1220 : /* Is there notification on this handle? */
1221 0 : if (prn_hnd->notify.cli_chan == NULL ||
1222 0 : prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1223 0 : prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1224 0 : prn_hnd->notify.cli_chan->active_connections == 0) {
1225 0 : return 0;
1226 : }
1227 :
1228 0 : DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1229 : prn_hnd->servername, prn_hnd->sharename));
1230 :
1231 : /* For this printer? Print servers always receive notifications. */
1232 0 : if ((prn_hnd->printer_type == SPLHND_PRINTER) &&
1233 0 : (!strequal(msg_group->printername, prn_hnd->sharename))) {
1234 0 : return 0;
1235 : }
1236 :
1237 0 : DEBUG(10,("Our printer\n"));
1238 :
1239 : /* build the array of change notifications */
1240 0 : ret = build_notify2_messages(mem_ctx, prn_hnd,
1241 : msg_group->msgs,
1242 : msg_group->num_msgs,
1243 : ¬ifies, &count);
1244 0 : if (ret) {
1245 0 : return ret;
1246 : }
1247 :
1248 0 : info0.version = 0x2;
1249 0 : info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1250 0 : info0.count = count;
1251 0 : info0.notifies = notifies;
1252 :
1253 0 : info.info0 = &info0;
1254 :
1255 0 : status = dcerpc_spoolss_RouterReplyPrinterEx(
1256 0 : prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1257 : mem_ctx,
1258 : &prn_hnd->notify.cli_hnd,
1259 : prn_hnd->notify.change, /* color */
1260 : prn_hnd->notify.flags,
1261 : &reply_result,
1262 : 0, /* reply_type, must be 0 */
1263 : info, &werr);
1264 0 : if (!NT_STATUS_IS_OK(status)) {
1265 0 : DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1266 : "failed: %s\n",
1267 : prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1268 : nt_errstr(status)));
1269 0 : werr = ntstatus_to_werror(status);
1270 0 : } else if (!W_ERROR_IS_OK(werr)) {
1271 0 : DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1272 : "failed: %s\n",
1273 : prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1274 : win_errstr(werr)));
1275 : }
1276 0 : switch (reply_result) {
1277 0 : case 0:
1278 0 : break;
1279 0 : case PRINTER_NOTIFY_INFO_DISCARDED:
1280 : case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1281 : case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1282 0 : break;
1283 0 : default:
1284 0 : break;
1285 : }
1286 :
1287 0 : return 0;
1288 : }
1289 :
1290 0 : static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1291 : {
1292 0 : struct printer_handle *p;
1293 0 : TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1294 0 : SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1295 0 : int ret;
1296 :
1297 0 : if ( !msg_group ) {
1298 0 : DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1299 0 : return;
1300 : }
1301 :
1302 0 : if (!msg_group->msgs) {
1303 0 : DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1304 0 : return;
1305 : }
1306 :
1307 0 : DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1308 :
1309 : /* loop over all printers */
1310 :
1311 0 : for (p = printers_list; p; p = p->next) {
1312 0 : ret = send_notify2_printer(mem_ctx, p, msg_group);
1313 0 : if (ret) {
1314 0 : goto done;
1315 : }
1316 : }
1317 :
1318 0 : done:
1319 0 : DEBUG(8,("send_notify2_changes: Exit...\n"));
1320 0 : return;
1321 : }
1322 :
1323 : /***********************************************************************
1324 : **********************************************************************/
1325 :
1326 0 : static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1327 : {
1328 :
1329 0 : uint32_t tv_sec, tv_usec;
1330 0 : size_t offset = 0;
1331 :
1332 : /* Unpack message */
1333 :
1334 0 : offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1335 0 : msg->printer);
1336 :
1337 0 : offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1338 : &tv_sec, &tv_usec,
1339 : &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1340 :
1341 0 : if (msg->len == 0)
1342 0 : tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1343 : &msg->notify.value[0], &msg->notify.value[1]);
1344 : else
1345 0 : tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1346 : &msg->len, &msg->notify.data);
1347 :
1348 0 : DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1349 : msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1350 :
1351 0 : tv->tv_sec = tv_sec;
1352 0 : tv->tv_usec = tv_usec;
1353 :
1354 0 : if (msg->len == 0)
1355 0 : DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1356 : msg->notify.value[1]));
1357 : else
1358 0 : dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1359 :
1360 0 : return true;
1361 : }
1362 :
1363 : /********************************************************************
1364 : Receive a notify2 message list
1365 : ********************************************************************/
1366 :
1367 0 : static void receive_notify2_message_list(struct messaging_context *msg,
1368 : void *private_data,
1369 : uint32_t msg_type,
1370 : struct server_id server_id,
1371 : DATA_BLOB *data)
1372 : {
1373 0 : size_t msg_count, i, num_groups;
1374 0 : char *buf = (char *)data->data;
1375 0 : char *msg_ptr;
1376 0 : size_t msg_len;
1377 0 : SPOOLSS_NOTIFY_MSG notify;
1378 0 : SPOOLSS_NOTIFY_MSG_CTR messages;
1379 :
1380 0 : if (data->length < 4) {
1381 0 : DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1382 0 : return;
1383 : }
1384 :
1385 0 : msg_count = IVAL(buf, 0);
1386 0 : msg_ptr = buf + 4;
1387 :
1388 0 : DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1389 :
1390 0 : if (msg_count == 0) {
1391 0 : DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1392 0 : return;
1393 : }
1394 :
1395 : /* initialize the container */
1396 :
1397 0 : ZERO_STRUCT( messages );
1398 0 : notify_msg_ctr_init( &messages );
1399 :
1400 : /*
1401 : * build message groups for each printer identified
1402 : * in a change_notify msg. Remember that a PCN message
1403 : * includes the handle returned for the srv_spoolss_replyopenprinter()
1404 : * call. Therefore messages are grouped according to printer handle.
1405 : */
1406 :
1407 0 : for ( i=0; i<msg_count; i++ ) {
1408 0 : struct timeval msg_tv;
1409 :
1410 0 : if (msg_ptr + 4 - buf > data->length) {
1411 0 : DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1412 0 : return;
1413 : }
1414 :
1415 0 : msg_len = IVAL(msg_ptr,0);
1416 0 : msg_ptr += 4;
1417 :
1418 0 : if (msg_ptr + msg_len - buf > data->length) {
1419 0 : DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1420 0 : return;
1421 : }
1422 :
1423 : /* unpack messages */
1424 :
1425 0 : ZERO_STRUCT( notify );
1426 0 : notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1427 0 : msg_ptr += msg_len;
1428 :
1429 : /* add to correct list in container */
1430 :
1431 0 : notify_msg_ctr_addmsg( &messages, ¬ify );
1432 :
1433 : /* free memory that might have been allocated by notify2_unpack_msg() */
1434 :
1435 0 : if ( notify.len != 0 )
1436 0 : SAFE_FREE( notify.notify.data );
1437 : }
1438 :
1439 : /* process each group of messages */
1440 :
1441 0 : num_groups = notify_msg_ctr_numgroups( &messages );
1442 0 : for ( i=0; i<num_groups; i++ )
1443 0 : send_notify2_changes( &messages, i );
1444 :
1445 :
1446 : /* cleanup */
1447 :
1448 0 : DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1449 : (uint32_t)msg_count ));
1450 :
1451 0 : notify_msg_ctr_destroy( &messages );
1452 :
1453 0 : return;
1454 : }
1455 :
1456 : /********************************************************************
1457 : Send a message to ourself about new driver being installed
1458 : so we can upgrade the information for each printer bound to this
1459 : driver
1460 : ********************************************************************/
1461 :
1462 0 : static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1463 : struct messaging_context *msg_ctx)
1464 : {
1465 0 : int len = strlen(drivername);
1466 :
1467 0 : if (!len)
1468 0 : return false;
1469 :
1470 0 : DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1471 : drivername));
1472 :
1473 0 : messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1474 : MSG_PRINTER_DRVUPGRADE,
1475 0 : (const uint8_t *)drivername, len+1);
1476 :
1477 0 : return true;
1478 : }
1479 :
1480 28 : void srv_spoolss_cleanup(void)
1481 : {
1482 0 : struct printer_session_counter *session_counter;
1483 :
1484 28 : for (session_counter = counter_list;
1485 68 : session_counter != NULL;
1486 40 : session_counter = counter_list) {
1487 40 : DLIST_REMOVE(counter_list, session_counter);
1488 40 : TALLOC_FREE(session_counter);
1489 : }
1490 28 : }
1491 :
1492 : /**********************************************************************
1493 : callback to receive a MSG_PRINTER_DRVUPGRADE message and iterate
1494 : over all printers, upgrading ones as necessary
1495 : This is now *ONLY* called inside the background lpq updater. JRA.
1496 : **********************************************************************/
1497 :
1498 0 : void do_drv_upgrade_printer(struct messaging_context *msg,
1499 : void *private_data,
1500 : uint32_t msg_type,
1501 : struct server_id server_id,
1502 : DATA_BLOB *data)
1503 : {
1504 0 : TALLOC_CTX *tmp_ctx;
1505 0 : const struct auth_session_info *session_info = get_session_info_system();
1506 0 : struct spoolss_PrinterInfo2 *pinfo2;
1507 0 : WERROR result;
1508 0 : const char *drivername;
1509 0 : int snum;
1510 0 : int n_services = lp_numservices();
1511 0 : struct dcerpc_binding_handle *b = NULL;
1512 :
1513 0 : tmp_ctx = talloc_new(NULL);
1514 0 : if (!tmp_ctx) return;
1515 :
1516 0 : drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1517 0 : if (!drivername) {
1518 0 : DEBUG(0, ("do_drv_upgrade_printer: Out of memory ?!\n"));
1519 0 : goto done;
1520 : }
1521 :
1522 0 : DEBUG(10, ("do_drv_upgrade_printer: "
1523 : "Got message for new driver [%s]\n", drivername));
1524 :
1525 : /* Iterate the printer list */
1526 :
1527 0 : for (snum = 0; snum < n_services; snum++) {
1528 0 : if (!lp_snum_ok(snum) || !lp_printable(snum)) {
1529 0 : continue;
1530 : }
1531 :
1532 : /* ignore [printers] share */
1533 0 : if (strequal(lp_const_servicename(snum), "printers")) {
1534 0 : continue;
1535 : }
1536 :
1537 0 : if (b == NULL) {
1538 0 : result = winreg_printer_binding_handle(tmp_ctx,
1539 : session_info,
1540 : msg,
1541 : &b);
1542 0 : if (!W_ERROR_IS_OK(result)) {
1543 0 : break;
1544 : }
1545 : }
1546 :
1547 0 : result = winreg_get_printer(tmp_ctx, b,
1548 : lp_const_servicename(snum),
1549 : &pinfo2);
1550 :
1551 0 : if (!W_ERROR_IS_OK(result)) {
1552 0 : continue;
1553 : }
1554 :
1555 0 : if (!pinfo2->drivername) {
1556 0 : continue;
1557 : }
1558 :
1559 0 : if (strcmp(drivername, pinfo2->drivername) != 0) {
1560 0 : continue;
1561 : }
1562 :
1563 0 : DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1564 :
1565 : /* all we care about currently is the change_id */
1566 0 : result = winreg_printer_update_changeid(tmp_ctx, b,
1567 0 : pinfo2->printername);
1568 :
1569 0 : if (!W_ERROR_IS_OK(result)) {
1570 0 : DEBUG(3, ("do_drv_upgrade_printer: "
1571 : "Failed to update changeid [%s]\n",
1572 : win_errstr(result)));
1573 : }
1574 : }
1575 :
1576 : /* all done */
1577 0 : done:
1578 0 : talloc_free(tmp_ctx);
1579 : }
1580 :
1581 : /********************************************************************
1582 : Update the cache for all printq's with a registered client
1583 : connection
1584 : ********************************************************************/
1585 :
1586 0 : void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1587 : {
1588 0 : struct printer_handle *printer = printers_list;
1589 0 : int snum;
1590 :
1591 : /* loop through all printers and update the cache where
1592 : a client is connected */
1593 0 : while (printer) {
1594 0 : if ((printer->printer_type == SPLHND_PRINTER) &&
1595 0 : ((printer->notify.cli_chan != NULL) &&
1596 0 : (printer->notify.cli_chan->active_connections > 0))) {
1597 0 : snum = print_queue_snum(printer->sharename);
1598 0 : print_queue_status(msg_ctx, snum, NULL, NULL);
1599 : }
1600 :
1601 0 : printer = printer->next;
1602 : }
1603 :
1604 0 : return;
1605 : }
1606 :
1607 : /****************************************************************
1608 : _spoolss_OpenPrinter
1609 : ****************************************************************/
1610 :
1611 194 : WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1612 : struct spoolss_OpenPrinter *r)
1613 : {
1614 0 : struct spoolss_OpenPrinterEx e;
1615 0 : struct spoolss_UserLevel1 level1;
1616 0 : WERROR werr;
1617 :
1618 194 : ZERO_STRUCT(level1);
1619 :
1620 194 : e.in.printername = r->in.printername;
1621 194 : e.in.datatype = r->in.datatype;
1622 194 : e.in.devmode_ctr = r->in.devmode_ctr;
1623 194 : e.in.access_mask = r->in.access_mask;
1624 194 : e.in.userlevel_ctr.level = 1;
1625 194 : e.in.userlevel_ctr.user_info.level1 = &level1;
1626 :
1627 194 : e.out.handle = r->out.handle;
1628 :
1629 194 : werr = _spoolss_OpenPrinterEx(p, &e);
1630 :
1631 194 : if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAMETER)) {
1632 : /* OpenPrinterEx returns this for a bad
1633 : * printer name. We must return WERR_INVALID_PRINTER_NAME
1634 : * instead.
1635 : */
1636 4 : werr = WERR_INVALID_PRINTER_NAME;
1637 : }
1638 :
1639 194 : return werr;
1640 : }
1641 :
1642 2850 : static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1643 : struct spoolss_DeviceMode *orig,
1644 : struct spoolss_DeviceMode **dest)
1645 : {
1646 0 : struct spoolss_DeviceMode *dm;
1647 :
1648 2850 : dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1649 2850 : if (!dm) {
1650 0 : return WERR_NOT_ENOUGH_MEMORY;
1651 : }
1652 :
1653 : /* copy all values, then duplicate strings and structs */
1654 2850 : *dm = *orig;
1655 :
1656 2850 : dm->devicename = talloc_strdup(dm, orig->devicename);
1657 2850 : if (!dm->devicename) {
1658 0 : return WERR_NOT_ENOUGH_MEMORY;
1659 : }
1660 2850 : dm->formname = talloc_strdup(dm, orig->formname);
1661 2850 : if (!dm->formname) {
1662 0 : return WERR_NOT_ENOUGH_MEMORY;
1663 : }
1664 2850 : if (orig->driverextra_data.data) {
1665 1392 : dm->driverextra_data.data =
1666 1392 : (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1667 : orig->driverextra_data.length);
1668 1392 : if (!dm->driverextra_data.data) {
1669 0 : return WERR_NOT_ENOUGH_MEMORY;
1670 : }
1671 : }
1672 :
1673 2850 : *dest = dm;
1674 2850 : return WERR_OK;
1675 : }
1676 :
1677 : /****************************************************************
1678 : _spoolss_OpenPrinterEx
1679 : ****************************************************************/
1680 :
1681 988 : WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1682 : struct spoolss_OpenPrinterEx *r)
1683 : {
1684 988 : struct dcesrv_call_state *dce_call = p->dce_call;
1685 988 : struct dcesrv_connection *dcesrv_conn = dce_call->conn;
1686 0 : const struct tsocket_address *remote_address =
1687 988 : dcesrv_connection_get_remote_address(dcesrv_conn);
1688 0 : struct auth_session_info *session_info =
1689 988 : dcesrv_call_session_info(dce_call);
1690 0 : int snum;
1691 0 : char *raddr;
1692 0 : char *rhost;
1693 988 : struct printer_handle *Printer=NULL;
1694 0 : WERROR result;
1695 0 : int rc;
1696 :
1697 988 : if (!r->in.printername) {
1698 0 : return WERR_INVALID_PARAMETER;
1699 : }
1700 :
1701 988 : if (!*r->in.printername) {
1702 8 : return WERR_INVALID_PARAMETER;
1703 : }
1704 :
1705 980 : if (r->in.userlevel_ctr.level > 3) {
1706 0 : return WERR_INVALID_PARAMETER;
1707 : }
1708 980 : if ((r->in.userlevel_ctr.level == 1 && !r->in.userlevel_ctr.user_info.level1) ||
1709 956 : (r->in.userlevel_ctr.level == 2 && !r->in.userlevel_ctr.user_info.level2) ||
1710 956 : (r->in.userlevel_ctr.level == 3 && !r->in.userlevel_ctr.user_info.level3)) {
1711 24 : return WERR_INVALID_PARAMETER;
1712 : }
1713 :
1714 : /*
1715 : * The printcap printer share inventory is updated on client
1716 : * enumeration. For clients that do not perform enumeration prior to
1717 : * access, such as cupssmbadd, we reinitialise the printer share
1718 : * inventory on open as well.
1719 : */
1720 956 : become_root();
1721 956 : delete_and_reload_printers();
1722 956 : unbecome_root();
1723 :
1724 : /* some sanity check because you can open a printer or a print server */
1725 : /* aka: \\server\printer or \\server */
1726 :
1727 956 : DEBUGADD(3,("checking name: %s\n", r->in.printername));
1728 :
1729 956 : result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1730 956 : if (!W_ERROR_IS_OK(result)) {
1731 332 : DEBUG(3,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1732 : "for printer %s\n", r->in.printername));
1733 332 : ZERO_STRUCTP(r->out.handle);
1734 332 : return result;
1735 : }
1736 :
1737 624 : Printer = find_printer_index_by_hnd(p, r->out.handle);
1738 624 : if ( !Printer ) {
1739 0 : DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1740 : "handle we created for printer %s\n", r->in.printername));
1741 0 : close_printer_handle(p, r->out.handle);
1742 0 : ZERO_STRUCTP(r->out.handle);
1743 0 : return WERR_INVALID_PARAMETER;
1744 : }
1745 :
1746 : /*
1747 : * First case: the user is opening the print server:
1748 : *
1749 : * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1750 : * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1751 : *
1752 : * Then both Win2k and WinNT clients try an OpenPrinterEx with
1753 : * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1754 : * or if the user is listed in the smb.conf printer admin parameter.
1755 : *
1756 : * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1757 : * client view printer folder, but does not show the MSAPW.
1758 : *
1759 : * Note: this test needs code to check access rights here too. Jeremy
1760 : * could you look at this?
1761 : *
1762 : * Second case: the user is opening a printer:
1763 : * NT doesn't let us connect to a printer if the connecting user
1764 : * doesn't have print permission.
1765 : *
1766 : * Third case: user is opening a Port Monitor
1767 : * access checks same as opening a handle to the print server.
1768 : */
1769 :
1770 624 : switch (Printer->printer_type )
1771 : {
1772 118 : case SPLHND_SERVER:
1773 : case SPLHND_PORTMON_TCP:
1774 : case SPLHND_PORTMON_LOCAL:
1775 : /* Printserver handles use global struct... */
1776 :
1777 118 : snum = -1;
1778 :
1779 118 : if (r->in.access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
1780 90 : r->in.access_mask |= SERVER_ACCESS_ADMINISTER;
1781 90 : r->in.access_mask |= SERVER_ACCESS_ENUMERATE;
1782 : }
1783 :
1784 : /* Map standard access rights to object specific access rights */
1785 :
1786 118 : se_map_standard(&r->in.access_mask,
1787 : &printserver_std_mapping);
1788 :
1789 : /* Deny any object specific bits that don't apply to print
1790 : servers (i.e printer and job specific bits) */
1791 :
1792 118 : r->in.access_mask &= SEC_MASK_SPECIFIC;
1793 :
1794 118 : if (r->in.access_mask &
1795 : ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1796 0 : DEBUG(3, ("access DENIED for non-printserver bits\n"));
1797 0 : close_printer_handle(p, r->out.handle);
1798 0 : ZERO_STRUCTP(r->out.handle);
1799 0 : return WERR_ACCESS_DENIED;
1800 : }
1801 :
1802 : /* Allow admin access */
1803 :
1804 118 : if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1805 : {
1806 94 : if (!lp_show_add_printer_wizard()) {
1807 0 : close_printer_handle(p, r->out.handle);
1808 0 : ZERO_STRUCTP(r->out.handle);
1809 0 : return WERR_ACCESS_DENIED;
1810 : }
1811 :
1812 : /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1813 : and not a printer admin, then fail */
1814 :
1815 94 : if ((session_info->unix_token->uid != sec_initial_uid()) &&
1816 2 : !security_token_has_privilege(
1817 2 : session_info->security_token,
1818 0 : SEC_PRIV_PRINT_OPERATOR) &&
1819 0 : !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
1820 0 : session_info->security_token)) {
1821 0 : close_printer_handle(p, r->out.handle);
1822 0 : ZERO_STRUCTP(r->out.handle);
1823 0 : DEBUG(3,("access DENIED as user is not root, "
1824 : "has no printoperator privilege and is "
1825 : "not a member of the printoperator builtin group\n"));
1826 0 : return WERR_ACCESS_DENIED;
1827 : }
1828 :
1829 94 : r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1830 : }
1831 : else
1832 : {
1833 24 : r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1834 : }
1835 :
1836 118 : DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1837 : ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1838 :
1839 118 : break;
1840 :
1841 506 : case SPLHND_PRINTER:
1842 : /* NT doesn't let us connect to a printer if the connecting user
1843 : doesn't have print permission. */
1844 :
1845 506 : if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1846 0 : close_printer_handle(p, r->out.handle);
1847 0 : ZERO_STRUCTP(r->out.handle);
1848 0 : return WERR_INVALID_HANDLE;
1849 : }
1850 :
1851 506 : if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1852 170 : r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1853 : }
1854 :
1855 506 : se_map_standard(&r->in.access_mask, &printer_std_mapping);
1856 :
1857 : /* map an empty access mask to the minimum access mask */
1858 506 : if (r->in.access_mask == 0x0)
1859 296 : r->in.access_mask = PRINTER_ACCESS_USE;
1860 :
1861 : /*
1862 : * If we are not serving the printer driver for this printer,
1863 : * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1864 : * will keep NT clients happy --jerry
1865 : */
1866 :
1867 506 : if (lp_use_client_driver(snum)
1868 0 : && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1869 : {
1870 0 : r->in.access_mask = PRINTER_ACCESS_USE;
1871 : }
1872 :
1873 : /* check smb.conf parameters and the the sec_desc */
1874 506 : raddr = tsocket_address_inet_addr_string(remote_address,
1875 : p->mem_ctx);
1876 506 : if (raddr == NULL) {
1877 0 : return WERR_NOT_ENOUGH_MEMORY;
1878 : }
1879 :
1880 506 : rc = get_remote_hostname(remote_address,
1881 : &rhost,
1882 : p->mem_ctx);
1883 506 : if (rc < 0) {
1884 0 : return WERR_NOT_ENOUGH_MEMORY;
1885 : }
1886 506 : if (strequal(rhost, "UNKNOWN")) {
1887 506 : rhost = raddr;
1888 : }
1889 :
1890 506 : if (!allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
1891 : rhost, raddr)) {
1892 0 : DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1893 0 : ZERO_STRUCTP(r->out.handle);
1894 0 : return WERR_ACCESS_DENIED;
1895 : }
1896 :
1897 506 : if (!user_ok_token(session_info->unix_info->unix_name,
1898 506 : session_info->info->domain_name,
1899 506 : session_info->security_token, snum) ||
1900 506 : !W_ERROR_IS_OK(print_access_check(session_info,
1901 : p->msg_ctx,
1902 : snum,
1903 : r->in.access_mask))) {
1904 0 : DEBUG(3, ("access DENIED for printer open\n"));
1905 0 : close_printer_handle(p, r->out.handle);
1906 0 : ZERO_STRUCTP(r->out.handle);
1907 0 : return WERR_ACCESS_DENIED;
1908 : }
1909 :
1910 506 : if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1911 4 : DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1912 4 : close_printer_handle(p, r->out.handle);
1913 4 : ZERO_STRUCTP(r->out.handle);
1914 4 : return WERR_ACCESS_DENIED;
1915 : }
1916 :
1917 502 : if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1918 170 : r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1919 : else
1920 332 : r->in.access_mask = PRINTER_ACCESS_USE;
1921 :
1922 502 : DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1923 : ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1924 :
1925 502 : winreg_create_printer_internal(p->mem_ctx,
1926 : get_session_info_system(),
1927 : p->msg_ctx,
1928 : lp_const_servicename(snum));
1929 :
1930 502 : break;
1931 :
1932 0 : default:
1933 : /* sanity check to prevent programmer error */
1934 0 : ZERO_STRUCTP(r->out.handle);
1935 0 : return WERR_INVALID_HANDLE;
1936 : }
1937 :
1938 620 : Printer->access_granted = r->in.access_mask;
1939 :
1940 : /*
1941 : * If the client sent a devmode in the OpenPrinter() call, then
1942 : * save it here in case we get a job submission on this handle
1943 : */
1944 :
1945 620 : if ((Printer->printer_type != SPLHND_SERVER)
1946 502 : && (r->in.devmode_ctr.devmode != NULL)) {
1947 8 : copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1948 : &Printer->devmode);
1949 : }
1950 :
1951 620 : return WERR_OK;
1952 : }
1953 :
1954 : /****************************************************************
1955 : _spoolss_ClosePrinter
1956 : ****************************************************************/
1957 :
1958 620 : WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1959 : struct spoolss_ClosePrinter *r)
1960 : {
1961 620 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1962 :
1963 620 : if (Printer && Printer->document_started) {
1964 0 : struct spoolss_EndDocPrinter e;
1965 :
1966 28 : e.in.handle = r->in.handle;
1967 :
1968 28 : _spoolss_EndDocPrinter(p, &e);
1969 : }
1970 :
1971 620 : if (!close_printer_handle(p, r->in.handle))
1972 0 : return WERR_INVALID_HANDLE;
1973 :
1974 : /* clear the returned printer handle. Observed behavior
1975 : from Win2k server. Don't think this really matters.
1976 : Previous code just copied the value of the closed
1977 : handle. --jerry */
1978 :
1979 620 : ZERO_STRUCTP(r->out.handle);
1980 :
1981 620 : return WERR_OK;
1982 : }
1983 :
1984 : /****************************************************************
1985 : _spoolss_DeletePrinter
1986 : ****************************************************************/
1987 :
1988 16 : WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1989 : struct spoolss_DeletePrinter *r)
1990 : {
1991 16 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1992 0 : WERROR result;
1993 0 : int snum;
1994 :
1995 16 : if (Printer && Printer->document_started) {
1996 0 : struct spoolss_EndDocPrinter e;
1997 :
1998 0 : e.in.handle = r->in.handle;
1999 :
2000 0 : _spoolss_EndDocPrinter(p, &e);
2001 : }
2002 :
2003 16 : if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2004 16 : winreg_delete_printer_key_internal(p->mem_ctx,
2005 : get_session_info_system(),
2006 : p->msg_ctx,
2007 : lp_const_servicename(snum),
2008 : "");
2009 : }
2010 :
2011 16 : result = delete_printer_handle(p, r->in.handle);
2012 :
2013 16 : return result;
2014 : }
2015 :
2016 : /*******************************************************************
2017 : * static function to lookup the version id corresponding to an
2018 : * long architecture string
2019 : ******************************************************************/
2020 :
2021 : static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2022 : SPOOLSS_DRIVER_VERSION_NT35,
2023 : SPOOLSS_DRIVER_VERSION_NT4,
2024 : SPOOLSS_DRIVER_VERSION_200X,
2025 : -1};
2026 :
2027 0 : static int get_version_id(const char *arch)
2028 : {
2029 0 : int i;
2030 :
2031 0 : for (i=0; archi_table[i].long_archi != NULL; i++)
2032 : {
2033 0 : if (strcmp(arch, archi_table[i].long_archi) == 0)
2034 0 : return (archi_table[i].version);
2035 : }
2036 :
2037 0 : return -1;
2038 : }
2039 :
2040 : /****************************************************************
2041 : _spoolss_DeletePrinterDriver
2042 : ****************************************************************/
2043 :
2044 0 : WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2045 : struct spoolss_DeletePrinterDriver *r)
2046 : {
2047 :
2048 0 : struct dcesrv_call_state *dce_call = p->dce_call;
2049 0 : struct auth_session_info *session_info =
2050 0 : dcesrv_call_session_info(dce_call);
2051 0 : struct spoolss_DriverInfo8 *info = NULL;
2052 0 : int version;
2053 0 : WERROR status;
2054 0 : struct dcerpc_binding_handle *b;
2055 0 : TALLOC_CTX *tmp_ctx = NULL;
2056 0 : int i;
2057 0 : bool found;
2058 :
2059 : /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2060 : and not a printer admin, then fail */
2061 :
2062 0 : if ((session_info->unix_token->uid != sec_initial_uid()) &&
2063 0 : !security_token_has_privilege(session_info->security_token,
2064 : SEC_PRIV_PRINT_OPERATOR)) {
2065 0 : return WERR_ACCESS_DENIED;
2066 : }
2067 :
2068 0 : if (r->in.architecture == NULL || r->in.driver == NULL) {
2069 0 : return WERR_INVALID_ENVIRONMENT;
2070 : }
2071 :
2072 : /* check that we have a valid driver name first */
2073 :
2074 0 : if ((version = get_version_id(r->in.architecture)) == -1) {
2075 0 : return WERR_INVALID_ENVIRONMENT;
2076 : }
2077 :
2078 0 : tmp_ctx = talloc_new(p->mem_ctx);
2079 0 : if (!tmp_ctx) {
2080 0 : return WERR_NOT_ENOUGH_MEMORY;
2081 : }
2082 :
2083 0 : status = winreg_printer_binding_handle(tmp_ctx,
2084 : get_session_info_system(),
2085 : p->msg_ctx,
2086 : &b);
2087 0 : if (!W_ERROR_IS_OK(status)) {
2088 0 : goto done;
2089 : }
2090 :
2091 0 : for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2092 0 : status = winreg_get_driver(tmp_ctx, b,
2093 : r->in.architecture, r->in.driver,
2094 0 : drv_cversion[i], &info);
2095 0 : if (!W_ERROR_IS_OK(status)) {
2096 0 : DEBUG(5, ("skipping del of driver with version %d\n",
2097 : drv_cversion[i]));
2098 0 : continue;
2099 : }
2100 0 : found = true;
2101 :
2102 0 : if (printer_driver_in_use(tmp_ctx, b, info)) {
2103 0 : status = WERR_PRINTER_DRIVER_IN_USE;
2104 0 : goto done;
2105 : }
2106 :
2107 0 : status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2108 0 : if (!W_ERROR_IS_OK(status)) {
2109 0 : DEBUG(0, ("failed del of driver with version %d\n",
2110 : drv_cversion[i]));
2111 0 : goto done;
2112 : }
2113 : }
2114 0 : if (found == false) {
2115 0 : DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2116 0 : status = WERR_UNKNOWN_PRINTER_DRIVER;
2117 : } else {
2118 0 : status = WERR_OK;
2119 : }
2120 :
2121 0 : done:
2122 0 : talloc_free(tmp_ctx);
2123 :
2124 0 : return status;
2125 : }
2126 :
2127 0 : static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2128 : struct pipes_struct *p,
2129 : struct spoolss_DeletePrinterDriverEx *r,
2130 : struct dcerpc_binding_handle *b,
2131 : struct spoolss_DriverInfo8 *info)
2132 : {
2133 0 : struct dcesrv_call_state *dce_call = p->dce_call;
2134 0 : struct auth_session_info *session_info =
2135 0 : dcesrv_call_session_info(dce_call);
2136 0 : WERROR status;
2137 0 : bool delete_files;
2138 :
2139 0 : if (printer_driver_in_use(mem_ctx, b, info)) {
2140 0 : status = WERR_PRINTER_DRIVER_IN_USE;
2141 0 : goto done;
2142 : }
2143 :
2144 : /*
2145 : * we have a couple of cases to consider.
2146 : * (1) Are any files in use? If so and DPD_DELETE_ALL_FILES is set,
2147 : * then the delete should fail if **any** files overlap with
2148 : * other drivers
2149 : * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2150 : * non-overlapping files
2151 : * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2152 : * are set, then do not delete any files
2153 : * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2154 : */
2155 :
2156 0 : delete_files = r->in.delete_flags
2157 0 : & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2158 :
2159 :
2160 0 : if (delete_files) {
2161 0 : bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2162 0 : if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2163 0 : status = WERR_PRINTER_DRIVER_IN_USE;
2164 0 : goto done;
2165 : }
2166 : /*
2167 : * printer_driver_files_in_use() has trimmed overlapping files
2168 : * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2169 : */
2170 : }
2171 :
2172 :
2173 0 : status = winreg_del_driver(mem_ctx, b, info, info->version);
2174 0 : if (!W_ERROR_IS_OK(status)) {
2175 0 : goto done;
2176 : }
2177 :
2178 : /*
2179 : * now delete any associated files if delete_files is
2180 : * true. Even if this part fails, we return success
2181 : * because the driver does not exist any more
2182 : */
2183 0 : if (delete_files) {
2184 0 : delete_driver_files(session_info, info);
2185 : }
2186 :
2187 0 : done:
2188 0 : return status;
2189 : }
2190 :
2191 : /****************************************************************
2192 : _spoolss_DeletePrinterDriverEx
2193 : ****************************************************************/
2194 :
2195 0 : WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2196 : struct spoolss_DeletePrinterDriverEx *r)
2197 : {
2198 0 : struct dcesrv_call_state *dce_call = p->dce_call;
2199 0 : struct auth_session_info *session_info =
2200 0 : dcesrv_call_session_info(dce_call);
2201 0 : struct spoolss_DriverInfo8 *info = NULL;
2202 0 : WERROR status;
2203 0 : struct dcerpc_binding_handle *b;
2204 0 : TALLOC_CTX *tmp_ctx = NULL;
2205 0 : int i;
2206 0 : bool found;
2207 :
2208 : /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2209 : and not a printer admin, then fail */
2210 :
2211 0 : if ((session_info->unix_token->uid != sec_initial_uid()) &&
2212 0 : !security_token_has_privilege(session_info->security_token,
2213 : SEC_PRIV_PRINT_OPERATOR)) {
2214 0 : return WERR_ACCESS_DENIED;
2215 : }
2216 :
2217 0 : if (r->in.architecture == NULL || r->in.driver == NULL) {
2218 0 : return WERR_INVALID_ENVIRONMENT;
2219 : }
2220 :
2221 : /* check that we have a valid driver name first */
2222 0 : if (get_version_id(r->in.architecture) == -1) {
2223 : /* this is what NT returns */
2224 0 : return WERR_INVALID_ENVIRONMENT;
2225 : }
2226 :
2227 0 : tmp_ctx = talloc_new(p->mem_ctx);
2228 0 : if (!tmp_ctx) {
2229 0 : return WERR_NOT_ENOUGH_MEMORY;
2230 : }
2231 :
2232 0 : status = winreg_printer_binding_handle(tmp_ctx,
2233 : get_session_info_system(),
2234 : p->msg_ctx,
2235 : &b);
2236 0 : if (!W_ERROR_IS_OK(status)) {
2237 0 : goto done;
2238 : }
2239 :
2240 0 : for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2241 0 : if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2242 0 : && (drv_cversion[i] != r->in.version)) {
2243 0 : continue;
2244 : }
2245 :
2246 : /* check if a driver with this version exists before delete */
2247 0 : status = winreg_get_driver(tmp_ctx, b,
2248 : r->in.architecture, r->in.driver,
2249 0 : drv_cversion[i], &info);
2250 0 : if (!W_ERROR_IS_OK(status)) {
2251 0 : DEBUG(5, ("skipping del of driver with version %d\n",
2252 : drv_cversion[i]));
2253 0 : continue;
2254 : }
2255 0 : found = true;
2256 :
2257 0 : status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2258 0 : if (!W_ERROR_IS_OK(status)) {
2259 0 : DEBUG(0, ("failed to delete driver with version %d\n",
2260 : drv_cversion[i]));
2261 0 : goto done;
2262 : }
2263 : }
2264 0 : if (found == false) {
2265 0 : DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2266 0 : status = WERR_UNKNOWN_PRINTER_DRIVER;
2267 : } else {
2268 0 : status = WERR_OK;
2269 : }
2270 :
2271 0 : done:
2272 0 : talloc_free(tmp_ctx);
2273 0 : return status;
2274 : }
2275 :
2276 :
2277 : /********************************************************************
2278 : GetPrinterData on a printer server Handle.
2279 : ********************************************************************/
2280 :
2281 404 : static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2282 : const char *value,
2283 : enum winreg_Type *type,
2284 : union spoolss_PrinterData *data)
2285 : {
2286 404 : DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2287 :
2288 404 : if (!strcasecmp_m(value, "W3SvcInstalled")) {
2289 28 : *type = REG_DWORD;
2290 28 : SIVAL(&data->value, 0, 0x00);
2291 28 : return WERR_OK;
2292 : }
2293 :
2294 376 : if (!strcasecmp_m(value, "BeepEnabled")) {
2295 24 : *type = REG_DWORD;
2296 24 : SIVAL(&data->value, 0, 0x00);
2297 24 : return WERR_OK;
2298 : }
2299 :
2300 352 : if (!strcasecmp_m(value, "EventLog")) {
2301 24 : *type = REG_DWORD;
2302 : /* formally was 0x1b */
2303 24 : SIVAL(&data->value, 0, 0x00);
2304 24 : return WERR_OK;
2305 : }
2306 :
2307 328 : if (!strcasecmp_m(value, "NetPopup")) {
2308 0 : *type = REG_DWORD;
2309 0 : SIVAL(&data->value, 0, 0x00);
2310 0 : return WERR_OK;
2311 : }
2312 :
2313 328 : if (!strcasecmp_m(value, "MajorVersion")) {
2314 28 : *type = REG_DWORD;
2315 :
2316 : /* Windows NT 4.0 seems to not allow uploading of drivers
2317 : to a server that reports 0x3 as the MajorVersion.
2318 : need to investigate more how Win2k gets around this .
2319 : -- jerry */
2320 :
2321 28 : if (RA_WINNT == get_remote_arch()) {
2322 0 : SIVAL(&data->value, 0, 0x02);
2323 : } else {
2324 28 : SIVAL(&data->value, 0, 0x03);
2325 : }
2326 :
2327 28 : return WERR_OK;
2328 : }
2329 :
2330 300 : if (!strcasecmp_m(value, "MinorVersion")) {
2331 24 : *type = REG_DWORD;
2332 24 : SIVAL(&data->value, 0, 0x00);
2333 24 : return WERR_OK;
2334 : }
2335 :
2336 : /* REG_BINARY
2337 : * uint32_t size = 0x114
2338 : * uint32_t major = 5
2339 : * uint32_t minor = [0|1]
2340 : * uint32_t build = [2195|2600]
2341 : * extra unicode string = e.g. "Service Pack 3"
2342 : */
2343 276 : if (!strcasecmp_m(value, "OSVersion")) {
2344 0 : DATA_BLOB blob;
2345 0 : enum ndr_err_code ndr_err;
2346 0 : struct spoolss_OSVersion os;
2347 :
2348 : /*
2349 : * Set the default OSVersion to:
2350 : *
2351 : * Windows Server 2003R2 SP2 (5.2.3790)
2352 : *
2353 : * used to be Windows 2000 (5.0.2195)
2354 : */
2355 40 : os.major = lp_parm_int(GLOBAL_SECTION_SNUM,
2356 : "spoolss", "os_major",
2357 : GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT);
2358 40 : os.minor = lp_parm_int(GLOBAL_SECTION_SNUM,
2359 : "spoolss", "os_minor",
2360 : GLOBAL_SPOOLSS_OS_MINOR_DEFAULT);
2361 40 : os.build = lp_parm_int(GLOBAL_SECTION_SNUM,
2362 : "spoolss", "os_build",
2363 : GLOBAL_SPOOLSS_OS_BUILD_DEFAULT);
2364 40 : os.extra_string = ""; /* leave extra string empty */
2365 :
2366 40 : ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2367 : (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2368 40 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2369 0 : return WERR_GEN_FAILURE;
2370 : }
2371 :
2372 40 : if (DEBUGLEVEL >= 10) {
2373 0 : NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
2374 : }
2375 :
2376 40 : *type = REG_BINARY;
2377 40 : data->binary = blob;
2378 :
2379 40 : return WERR_OK;
2380 : }
2381 :
2382 :
2383 236 : if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2384 24 : *type = REG_SZ;
2385 :
2386 24 : data->string = talloc_strdup(mem_ctx, SPOOLSS_DEFAULT_SERVER_PATH);
2387 24 : W_ERROR_HAVE_NO_MEMORY(data->string);
2388 :
2389 24 : return WERR_OK;
2390 : }
2391 :
2392 212 : if (!strcasecmp_m(value, "Architecture")) {
2393 160 : *type = REG_SZ;
2394 160 : data->string = talloc_strdup(mem_ctx,
2395 : lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", GLOBAL_SPOOLSS_ARCHITECTURE));
2396 160 : W_ERROR_HAVE_NO_MEMORY(data->string);
2397 :
2398 160 : return WERR_OK;
2399 : }
2400 :
2401 52 : if (!strcasecmp_m(value, "DsPresent")) {
2402 24 : *type = REG_DWORD;
2403 :
2404 : /* only show the publish check box if we are a
2405 : member of a AD domain */
2406 :
2407 24 : if (lp_security() == SEC_ADS) {
2408 0 : SIVAL(&data->value, 0, 0x01);
2409 : } else {
2410 24 : SIVAL(&data->value, 0, 0x00);
2411 : }
2412 24 : return WERR_OK;
2413 : }
2414 :
2415 28 : if (!strcasecmp_m(value, "DNSMachineName")) {
2416 24 : const char *hostname = get_mydnsfullname();
2417 :
2418 24 : if (!hostname) {
2419 0 : return WERR_FILE_NOT_FOUND;
2420 : }
2421 :
2422 24 : *type = REG_SZ;
2423 24 : data->string = talloc_strdup(mem_ctx, hostname);
2424 24 : W_ERROR_HAVE_NO_MEMORY(data->string);
2425 :
2426 24 : return WERR_OK;
2427 : }
2428 :
2429 4 : *type = REG_NONE;
2430 :
2431 4 : return WERR_INVALID_PARAMETER;
2432 : }
2433 :
2434 : /****************************************************************
2435 : _spoolss_GetPrinterData
2436 : ****************************************************************/
2437 :
2438 480 : WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2439 : struct spoolss_GetPrinterData *r)
2440 : {
2441 0 : struct spoolss_GetPrinterDataEx r2;
2442 :
2443 480 : r2.in.handle = r->in.handle;
2444 480 : r2.in.key_name = "PrinterDriverData";
2445 480 : r2.in.value_name = r->in.value_name;
2446 480 : r2.in.offered = r->in.offered;
2447 480 : r2.out.type = r->out.type;
2448 480 : r2.out.data = r->out.data;
2449 480 : r2.out.needed = r->out.needed;
2450 :
2451 480 : return _spoolss_GetPrinterDataEx(p, &r2);
2452 : }
2453 :
2454 : /*********************************************************
2455 : Connect to the client machine.
2456 : **********************************************************/
2457 :
2458 2 : static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe, struct cli_state **pp_cli,
2459 : struct sockaddr_storage *client_ss, const char *remote_machine)
2460 : {
2461 0 : NTSTATUS ret;
2462 0 : struct sockaddr_storage rm_addr;
2463 0 : char addr[INET6_ADDRSTRLEN];
2464 2 : struct cli_credentials *anon_creds = NULL;
2465 :
2466 2 : if ( is_zero_addr(client_ss) ) {
2467 0 : DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2468 : remote_machine));
2469 0 : if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2470 0 : DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2471 0 : return false;
2472 : }
2473 0 : print_sockaddr(addr, sizeof(addr), &rm_addr);
2474 : } else {
2475 2 : rm_addr = *client_ss;
2476 2 : print_sockaddr(addr, sizeof(addr), &rm_addr);
2477 2 : DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2478 : addr));
2479 : }
2480 :
2481 2 : if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2482 0 : DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2483 : addr));
2484 0 : return false;
2485 : }
2486 :
2487 2 : anon_creds = cli_credentials_init_anon(NULL);
2488 2 : if (anon_creds == NULL) {
2489 0 : DBG_ERR("cli_credentials_init_anon() failed\n");
2490 0 : return false;
2491 : }
2492 :
2493 : /* setup the connection */
2494 2 : ret = cli_full_connection_creds( pp_cli, lp_netbios_name(), remote_machine,
2495 : &rm_addr, 0, "IPC$", "IPC",
2496 : anon_creds,
2497 : CLI_FULL_CONNECTION_IPC);
2498 2 : TALLOC_FREE(anon_creds);
2499 2 : if ( !NT_STATUS_IS_OK( ret ) ) {
2500 0 : DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2501 : remote_machine ));
2502 0 : return false;
2503 : }
2504 :
2505 2 : if ( smbXcli_conn_protocol((*pp_cli)->conn) < PROTOCOL_NT1 ) {
2506 0 : DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2507 0 : cli_shutdown(*pp_cli);
2508 0 : return false;
2509 : }
2510 :
2511 : /*
2512 : * Ok - we have an anonymous connection to the IPC$ share.
2513 : * Now start the NT Domain stuff :-).
2514 : */
2515 :
2516 2 : ret = cli_rpc_pipe_open_noauth(*pp_cli, &ndr_table_spoolss, pp_pipe);
2517 2 : if (!NT_STATUS_IS_OK(ret)) {
2518 0 : DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2519 : remote_machine, nt_errstr(ret)));
2520 0 : cli_shutdown(*pp_cli);
2521 0 : return false;
2522 : }
2523 :
2524 2 : return true;
2525 : }
2526 :
2527 : /***************************************************************************
2528 : Connect to the client.
2529 : ****************************************************************************/
2530 :
2531 2 : static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2532 : uint32_t localprinter,
2533 : enum winreg_Type type,
2534 : struct policy_handle *handle,
2535 : struct notify_back_channel **_chan,
2536 : struct sockaddr_storage *client_ss,
2537 : struct messaging_context *msg_ctx)
2538 : {
2539 0 : WERROR result;
2540 0 : NTSTATUS status;
2541 0 : struct notify_back_channel *chan;
2542 :
2543 2 : for (chan = back_channels; chan; chan = chan->next) {
2544 0 : if (memcmp(&chan->client_address, client_ss,
2545 : sizeof(struct sockaddr_storage)) == 0) {
2546 0 : break;
2547 : }
2548 : }
2549 :
2550 : /*
2551 : * If it's the first connection, contact the client
2552 : * and connect to the IPC$ share anonymously
2553 : */
2554 2 : if (!chan) {
2555 0 : fstring unix_printer;
2556 :
2557 : /* the +2 is to strip the leading 2 backslashes */
2558 2 : fstrcpy(unix_printer, printer + 2);
2559 :
2560 2 : chan = talloc_zero(NULL, struct notify_back_channel);
2561 2 : if (!chan) {
2562 0 : return false;
2563 : }
2564 2 : chan->client_address = *client_ss;
2565 :
2566 2 : if (!spoolss_connect_to_client(&chan->cli_pipe, &chan->cli, client_ss, unix_printer)) {
2567 0 : TALLOC_FREE(chan);
2568 0 : return false;
2569 : }
2570 :
2571 2 : DLIST_ADD(back_channels, chan);
2572 :
2573 2 : messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2574 : receive_notify2_message_list);
2575 : }
2576 :
2577 2 : if (chan->cli_pipe == NULL ||
2578 2 : chan->cli_pipe->binding_handle == NULL) {
2579 0 : DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2580 : "NULL %s for printer %s\n",
2581 : chan->cli_pipe == NULL ?
2582 : "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2583 : printer));
2584 0 : return false;
2585 : }
2586 :
2587 : /*
2588 : * Tell the specific printing tdb we want messages for this printer
2589 : * by registering our PID.
2590 : */
2591 :
2592 2 : if (!print_notify_register_pid(snum)) {
2593 0 : DEBUG(0, ("Failed to register our pid for printer %s\n",
2594 : printer));
2595 : }
2596 :
2597 2 : status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2598 : talloc_tos(),
2599 : printer,
2600 : localprinter,
2601 : type,
2602 : 0,
2603 : NULL,
2604 : handle,
2605 : &result);
2606 2 : if (!NT_STATUS_IS_OK(status)) {
2607 0 : DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2608 0 : result = ntstatus_to_werror(status);
2609 2 : } else if (!W_ERROR_IS_OK(result)) {
2610 0 : DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2611 : }
2612 :
2613 2 : chan->active_connections++;
2614 2 : *_chan = chan;
2615 :
2616 2 : return (W_ERROR_IS_OK(result));
2617 : }
2618 :
2619 : /****************************************************************
2620 : ****************************************************************/
2621 :
2622 2 : static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2623 : const struct spoolss_NotifyOption *r)
2624 : {
2625 0 : struct spoolss_NotifyOption *option;
2626 0 : uint32_t i,k;
2627 :
2628 2 : if (!r) {
2629 0 : return NULL;
2630 : }
2631 :
2632 2 : option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2633 2 : if (!option) {
2634 0 : return NULL;
2635 : }
2636 :
2637 2 : *option = *r;
2638 :
2639 2 : if (!option->count) {
2640 0 : return option;
2641 : }
2642 :
2643 2 : option->types = talloc_zero_array(option,
2644 : struct spoolss_NotifyOptionType, option->count);
2645 2 : if (!option->types) {
2646 0 : talloc_free(option);
2647 0 : return NULL;
2648 : }
2649 :
2650 6 : for (i=0; i < option->count; i++) {
2651 4 : option->types[i] = r->types[i];
2652 :
2653 4 : if (option->types[i].count) {
2654 4 : option->types[i].fields = talloc_zero_array(option,
2655 : union spoolss_Field, option->types[i].count);
2656 4 : if (!option->types[i].fields) {
2657 0 : talloc_free(option);
2658 0 : return NULL;
2659 : }
2660 8 : for (k=0; k<option->types[i].count; k++) {
2661 4 : option->types[i].fields[k] =
2662 4 : r->types[i].fields[k];
2663 : }
2664 : }
2665 : }
2666 :
2667 2 : return option;
2668 : }
2669 :
2670 : /****************************************************************
2671 : * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2672 : *
2673 : * before replying OK: status=0 a rpc call is made to the workstation
2674 : * asking ReplyOpenPrinter
2675 : *
2676 : * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2677 : * called from api_spoolss_rffpcnex
2678 : ****************************************************************/
2679 :
2680 2 : WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2681 : struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2682 : {
2683 2 : struct dcesrv_call_state *dce_call = p->dce_call;
2684 2 : struct dcesrv_connection *dcesrv_conn = dce_call->conn;
2685 0 : const struct tsocket_address *remote_address =
2686 2 : dcesrv_connection_get_remote_address(dcesrv_conn);
2687 2 : int snum = -1;
2688 2 : struct spoolss_NotifyOption *option = r->in.notify_options;
2689 0 : struct sockaddr_storage client_ss;
2690 0 : ssize_t client_len;
2691 :
2692 : /* store the notify value in the printer struct */
2693 :
2694 2 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2695 :
2696 2 : if (!Printer) {
2697 0 : DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2698 : "Invalid handle (%s:%u:%u).\n",
2699 : OUR_HANDLE(r->in.handle)));
2700 0 : return WERR_INVALID_HANDLE;
2701 : }
2702 :
2703 2 : Printer->notify.flags = r->in.flags;
2704 2 : Printer->notify.options = r->in.options;
2705 2 : Printer->notify.printerlocal = r->in.printer_local;
2706 2 : Printer->notify.msg_ctx = p->msg_ctx;
2707 :
2708 2 : TALLOC_FREE(Printer->notify.option);
2709 2 : Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2710 :
2711 2 : fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2712 :
2713 : /* Connect to the client machine and send a ReplyOpenPrinter */
2714 :
2715 2 : if ( Printer->printer_type == SPLHND_SERVER)
2716 2 : snum = -1;
2717 0 : else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2718 0 : !get_printer_snum(p, r->in.handle, &snum, NULL) )
2719 0 : return WERR_INVALID_HANDLE;
2720 :
2721 2 : DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2722 : "remote_address is %s\n",
2723 : tsocket_address_string(remote_address, p->mem_ctx)));
2724 :
2725 2 : if (!lp_print_notify_backchannel(snum)) {
2726 0 : DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2727 : "backchannel disabled\n"));
2728 0 : return WERR_RPC_S_SERVER_UNAVAILABLE;
2729 : }
2730 :
2731 2 : client_len = tsocket_address_bsd_sockaddr(remote_address,
2732 : (struct sockaddr *) &client_ss,
2733 : sizeof(struct sockaddr_storage));
2734 2 : if (client_len < 0) {
2735 0 : return WERR_NOT_ENOUGH_MEMORY;
2736 : }
2737 :
2738 2 : if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2739 : Printer->notify.printerlocal, REG_SZ,
2740 : &Printer->notify.cli_hnd,
2741 : &Printer->notify.cli_chan,
2742 : &client_ss, p->msg_ctx)) {
2743 0 : return WERR_RPC_S_SERVER_UNAVAILABLE;
2744 : }
2745 :
2746 2 : return WERR_OK;
2747 : }
2748 :
2749 : /*******************************************************************
2750 : * fill a notify_info_data with the servername
2751 : ********************************************************************/
2752 :
2753 0 : static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2754 : int snum,
2755 : struct spoolss_Notify *data,
2756 : print_queue_struct *queue,
2757 : struct spoolss_PrinterInfo2 *pinfo2,
2758 : TALLOC_CTX *mem_ctx)
2759 : {
2760 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2761 0 : }
2762 :
2763 : /*******************************************************************
2764 : * fill a notify_info_data with the printername (not including the servername).
2765 : ********************************************************************/
2766 :
2767 0 : static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2768 : int snum,
2769 : struct spoolss_Notify *data,
2770 : print_queue_struct *queue,
2771 : struct spoolss_PrinterInfo2 *pinfo2,
2772 : TALLOC_CTX *mem_ctx)
2773 : {
2774 : /* the notify name should not contain the \\server\ part */
2775 0 : const char *p = strrchr(pinfo2->printername, '\\');
2776 :
2777 0 : if (!p) {
2778 0 : p = pinfo2->printername;
2779 : } else {
2780 0 : p++;
2781 : }
2782 :
2783 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2784 0 : }
2785 :
2786 : /*******************************************************************
2787 : * fill a notify_info_data with the servicename
2788 : ********************************************************************/
2789 :
2790 0 : static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2791 : int snum,
2792 : struct spoolss_Notify *data,
2793 : print_queue_struct *queue,
2794 : struct spoolss_PrinterInfo2 *pinfo2,
2795 : TALLOC_CTX *mem_ctx)
2796 : {
2797 0 : const struct loadparm_substitution *lp_sub =
2798 0 : loadparm_s3_global_substitution();
2799 :
2800 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), lp_sub, snum));
2801 0 : }
2802 :
2803 : /*******************************************************************
2804 : * fill a notify_info_data with the port name
2805 : ********************************************************************/
2806 :
2807 0 : static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2808 : int snum,
2809 : struct spoolss_Notify *data,
2810 : print_queue_struct *queue,
2811 : struct spoolss_PrinterInfo2 *pinfo2,
2812 : TALLOC_CTX *mem_ctx)
2813 : {
2814 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2815 0 : }
2816 :
2817 : /*******************************************************************
2818 : * fill a notify_info_data with the printername
2819 : * but it doesn't exist, have to see what to do
2820 : ********************************************************************/
2821 :
2822 0 : static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2823 : int snum,
2824 : struct spoolss_Notify *data,
2825 : print_queue_struct *queue,
2826 : struct spoolss_PrinterInfo2 *pinfo2,
2827 : TALLOC_CTX *mem_ctx)
2828 : {
2829 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2830 0 : }
2831 :
2832 : /*******************************************************************
2833 : * fill a notify_info_data with the comment
2834 : ********************************************************************/
2835 :
2836 0 : static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2837 : int snum,
2838 : struct spoolss_Notify *data,
2839 : print_queue_struct *queue,
2840 : struct spoolss_PrinterInfo2 *pinfo2,
2841 : TALLOC_CTX *mem_ctx)
2842 : {
2843 0 : const struct loadparm_substitution *lp_sub =
2844 0 : loadparm_s3_global_substitution();
2845 0 : const char *p;
2846 :
2847 0 : if (*pinfo2->comment == '\0') {
2848 0 : p = lp_comment(talloc_tos(), lp_sub, snum);
2849 : } else {
2850 0 : p = pinfo2->comment;
2851 : }
2852 :
2853 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2854 0 : }
2855 :
2856 : /*******************************************************************
2857 : * fill a notify_info_data with the comment
2858 : * location = "Room 1, floor 2, building 3"
2859 : ********************************************************************/
2860 :
2861 0 : static void spoolss_notify_location(struct messaging_context *msg_ctx,
2862 : int snum,
2863 : struct spoolss_Notify *data,
2864 : print_queue_struct *queue,
2865 : struct spoolss_PrinterInfo2 *pinfo2,
2866 : TALLOC_CTX *mem_ctx)
2867 : {
2868 0 : const char *loc = pinfo2->location;
2869 0 : NTSTATUS status;
2870 :
2871 0 : status = printer_list_get_printer(mem_ctx,
2872 : pinfo2->sharename,
2873 : NULL,
2874 : &loc,
2875 : NULL);
2876 0 : if (NT_STATUS_IS_OK(status)) {
2877 0 : if (loc == NULL) {
2878 0 : loc = pinfo2->location;
2879 : }
2880 : }
2881 :
2882 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2883 0 : }
2884 :
2885 : /*******************************************************************
2886 : * fill a notify_info_data with the device mode
2887 : * jfm:xxxx don't to it for know but that's a real problem !!!
2888 : ********************************************************************/
2889 :
2890 0 : static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2891 : int snum,
2892 : struct spoolss_Notify *data,
2893 : print_queue_struct *queue,
2894 : struct spoolss_PrinterInfo2 *pinfo2,
2895 : TALLOC_CTX *mem_ctx)
2896 : {
2897 : /* for a dummy implementation we have to zero the fields */
2898 0 : SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2899 0 : }
2900 :
2901 : /*******************************************************************
2902 : * fill a notify_info_data with the separator file name
2903 : ********************************************************************/
2904 :
2905 0 : static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2906 : int snum,
2907 : struct spoolss_Notify *data,
2908 : print_queue_struct *queue,
2909 : struct spoolss_PrinterInfo2 *pinfo2,
2910 : TALLOC_CTX *mem_ctx)
2911 : {
2912 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2913 0 : }
2914 :
2915 : /*******************************************************************
2916 : * fill a notify_info_data with the print processor
2917 : * jfm:xxxx return always winprint to indicate we don't do anything to it
2918 : ********************************************************************/
2919 :
2920 0 : static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2921 : int snum,
2922 : struct spoolss_Notify *data,
2923 : print_queue_struct *queue,
2924 : struct spoolss_PrinterInfo2 *pinfo2,
2925 : TALLOC_CTX *mem_ctx)
2926 : {
2927 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2928 0 : }
2929 :
2930 : /*******************************************************************
2931 : * fill a notify_info_data with the print processor options
2932 : * jfm:xxxx send an empty string
2933 : ********************************************************************/
2934 :
2935 0 : static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2936 : int snum,
2937 : struct spoolss_Notify *data,
2938 : print_queue_struct *queue,
2939 : struct spoolss_PrinterInfo2 *pinfo2,
2940 : TALLOC_CTX *mem_ctx)
2941 : {
2942 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2943 0 : }
2944 :
2945 : /*******************************************************************
2946 : * fill a notify_info_data with the data type
2947 : * jfm:xxxx always send RAW as data type
2948 : ********************************************************************/
2949 :
2950 0 : static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2951 : int snum,
2952 : struct spoolss_Notify *data,
2953 : print_queue_struct *queue,
2954 : struct spoolss_PrinterInfo2 *pinfo2,
2955 : TALLOC_CTX *mem_ctx)
2956 : {
2957 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2958 0 : }
2959 :
2960 : /*******************************************************************
2961 : * fill a notify_info_data with the security descriptor
2962 : * jfm:xxxx send an null pointer to say no security desc
2963 : * have to implement security before !
2964 : ********************************************************************/
2965 :
2966 0 : static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2967 : int snum,
2968 : struct spoolss_Notify *data,
2969 : print_queue_struct *queue,
2970 : struct spoolss_PrinterInfo2 *pinfo2,
2971 : TALLOC_CTX *mem_ctx)
2972 : {
2973 0 : if (pinfo2->secdesc == NULL) {
2974 0 : data->data.sd.sd = NULL;
2975 : } else {
2976 0 : data->data.sd.sd = security_descriptor_copy(mem_ctx,
2977 0 : pinfo2->secdesc);
2978 : }
2979 0 : data->data.sd.sd_size = ndr_size_security_descriptor(data->data.sd.sd,
2980 : 0);
2981 0 : }
2982 :
2983 : /*******************************************************************
2984 : * fill a notify_info_data with the attributes
2985 : * jfm:xxxx a samba printer is always shared
2986 : ********************************************************************/
2987 :
2988 0 : static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2989 : int snum,
2990 : struct spoolss_Notify *data,
2991 : print_queue_struct *queue,
2992 : struct spoolss_PrinterInfo2 *pinfo2,
2993 : TALLOC_CTX *mem_ctx)
2994 : {
2995 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2996 0 : }
2997 :
2998 : /*******************************************************************
2999 : * fill a notify_info_data with the priority
3000 : ********************************************************************/
3001 :
3002 0 : static void spoolss_notify_priority(struct messaging_context *msg_ctx,
3003 : int snum,
3004 : struct spoolss_Notify *data,
3005 : print_queue_struct *queue,
3006 : struct spoolss_PrinterInfo2 *pinfo2,
3007 : TALLOC_CTX *mem_ctx)
3008 : {
3009 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
3010 0 : }
3011 :
3012 : /*******************************************************************
3013 : * fill a notify_info_data with the default priority
3014 : ********************************************************************/
3015 :
3016 0 : static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3017 : int snum,
3018 : struct spoolss_Notify *data,
3019 : print_queue_struct *queue,
3020 : struct spoolss_PrinterInfo2 *pinfo2,
3021 : TALLOC_CTX *mem_ctx)
3022 : {
3023 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3024 0 : }
3025 :
3026 : /*******************************************************************
3027 : * fill a notify_info_data with the start time
3028 : ********************************************************************/
3029 :
3030 0 : static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3031 : int snum,
3032 : struct spoolss_Notify *data,
3033 : print_queue_struct *queue,
3034 : struct spoolss_PrinterInfo2 *pinfo2,
3035 : TALLOC_CTX *mem_ctx)
3036 : {
3037 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3038 0 : }
3039 :
3040 : /*******************************************************************
3041 : * fill a notify_info_data with the until time
3042 : ********************************************************************/
3043 :
3044 0 : static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3045 : int snum,
3046 : struct spoolss_Notify *data,
3047 : print_queue_struct *queue,
3048 : struct spoolss_PrinterInfo2 *pinfo2,
3049 : TALLOC_CTX *mem_ctx)
3050 : {
3051 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3052 0 : }
3053 :
3054 : /*******************************************************************
3055 : * fill a notify_info_data with the status
3056 : ********************************************************************/
3057 :
3058 0 : static void spoolss_notify_status(struct messaging_context *msg_ctx,
3059 : int snum,
3060 : struct spoolss_Notify *data,
3061 : print_queue_struct *queue,
3062 : struct spoolss_PrinterInfo2 *pinfo2,
3063 : TALLOC_CTX *mem_ctx)
3064 : {
3065 0 : print_status_struct status;
3066 :
3067 0 : print_queue_length(msg_ctx, snum, &status);
3068 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3069 0 : }
3070 :
3071 : /*******************************************************************
3072 : * fill a notify_info_data with the number of jobs queued
3073 : ********************************************************************/
3074 :
3075 0 : static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3076 : int snum,
3077 : struct spoolss_Notify *data,
3078 : print_queue_struct *queue,
3079 : struct spoolss_PrinterInfo2 *pinfo2,
3080 : TALLOC_CTX *mem_ctx)
3081 : {
3082 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3083 0 : data, print_queue_length(msg_ctx, snum, NULL));
3084 0 : }
3085 :
3086 : /*******************************************************************
3087 : * fill a notify_info_data with the average ppm
3088 : ********************************************************************/
3089 :
3090 0 : static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3091 : int snum,
3092 : struct spoolss_Notify *data,
3093 : print_queue_struct *queue,
3094 : struct spoolss_PrinterInfo2 *pinfo2,
3095 : TALLOC_CTX *mem_ctx)
3096 : {
3097 : /* always respond 8 pages per minutes */
3098 : /* a little hard ! */
3099 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3100 0 : }
3101 :
3102 : /*******************************************************************
3103 : * fill a notify_info_data with username
3104 : ********************************************************************/
3105 :
3106 0 : static void spoolss_notify_username(struct messaging_context *msg_ctx,
3107 : int snum,
3108 : struct spoolss_Notify *data,
3109 : print_queue_struct *queue,
3110 : struct spoolss_PrinterInfo2 *pinfo2,
3111 : TALLOC_CTX *mem_ctx)
3112 : {
3113 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3114 0 : }
3115 :
3116 : /*******************************************************************
3117 : * fill a notify_info_data with job status
3118 : ********************************************************************/
3119 :
3120 0 : static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3121 : int snum,
3122 : struct spoolss_Notify *data,
3123 : print_queue_struct *queue,
3124 : struct spoolss_PrinterInfo2 *pinfo2,
3125 : TALLOC_CTX *mem_ctx)
3126 : {
3127 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3128 0 : }
3129 :
3130 : /*******************************************************************
3131 : * fill a notify_info_data with job name
3132 : ********************************************************************/
3133 :
3134 0 : static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3135 : int snum,
3136 : struct spoolss_Notify *data,
3137 : print_queue_struct *queue,
3138 : struct spoolss_PrinterInfo2 *pinfo2,
3139 : TALLOC_CTX *mem_ctx)
3140 : {
3141 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3142 0 : }
3143 :
3144 : /*******************************************************************
3145 : * fill a notify_info_data with job status
3146 : ********************************************************************/
3147 :
3148 0 : static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3149 : int snum,
3150 : struct spoolss_Notify *data,
3151 : print_queue_struct *queue,
3152 : struct spoolss_PrinterInfo2 *pinfo2,
3153 : TALLOC_CTX *mem_ctx)
3154 : {
3155 : /*
3156 : * Now we're returning job status codes we just return a "" here. JRA.
3157 : */
3158 :
3159 0 : const char *p = "";
3160 :
3161 : #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3162 : p = "unknown";
3163 :
3164 : switch (queue->status) {
3165 : case LPQ_QUEUED:
3166 : p = "Queued";
3167 : break;
3168 : case LPQ_PAUSED:
3169 : p = ""; /* NT provides the paused string */
3170 : break;
3171 : case LPQ_SPOOLING:
3172 : p = "Spooling";
3173 : break;
3174 : case LPQ_PRINTING:
3175 : p = "Printing";
3176 : break;
3177 : }
3178 : #endif /* NO LONGER NEEDED. */
3179 :
3180 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3181 0 : }
3182 :
3183 : /*******************************************************************
3184 : * fill a notify_info_data with job time
3185 : ********************************************************************/
3186 :
3187 0 : static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3188 : int snum,
3189 : struct spoolss_Notify *data,
3190 : print_queue_struct *queue,
3191 : struct spoolss_PrinterInfo2 *pinfo2,
3192 : TALLOC_CTX *mem_ctx)
3193 : {
3194 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3195 0 : }
3196 :
3197 : /*******************************************************************
3198 : * fill a notify_info_data with job size
3199 : ********************************************************************/
3200 :
3201 0 : static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3202 : int snum,
3203 : struct spoolss_Notify *data,
3204 : print_queue_struct *queue,
3205 : struct spoolss_PrinterInfo2 *pinfo2,
3206 : TALLOC_CTX *mem_ctx)
3207 : {
3208 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3209 0 : }
3210 :
3211 : /*******************************************************************
3212 : * fill a notify_info_data with page info
3213 : ********************************************************************/
3214 0 : static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3215 : int snum,
3216 : struct spoolss_Notify *data,
3217 : print_queue_struct *queue,
3218 : struct spoolss_PrinterInfo2 *pinfo2,
3219 : TALLOC_CTX *mem_ctx)
3220 : {
3221 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3222 0 : }
3223 :
3224 : /*******************************************************************
3225 : * fill a notify_info_data with pages printed info.
3226 : ********************************************************************/
3227 0 : static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3228 : int snum,
3229 : struct spoolss_Notify *data,
3230 : print_queue_struct *queue,
3231 : struct spoolss_PrinterInfo2 *pinfo2,
3232 : TALLOC_CTX *mem_ctx)
3233 : {
3234 : /* Add code when back-end tracks this */
3235 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3236 0 : }
3237 :
3238 : /*******************************************************************
3239 : Fill a notify_info_data with job position.
3240 : ********************************************************************/
3241 :
3242 0 : static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3243 : int snum,
3244 : struct spoolss_Notify *data,
3245 : print_queue_struct *queue,
3246 : struct spoolss_PrinterInfo2 *pinfo2,
3247 : TALLOC_CTX *mem_ctx)
3248 : {
3249 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
3250 0 : }
3251 :
3252 : /*******************************************************************
3253 : Fill a notify_info_data with submitted time.
3254 : ********************************************************************/
3255 :
3256 0 : static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3257 : int snum,
3258 : struct spoolss_Notify *data,
3259 : print_queue_struct *queue,
3260 : struct spoolss_PrinterInfo2 *pinfo2,
3261 : TALLOC_CTX *mem_ctx)
3262 : {
3263 0 : data->data.string.string = NULL;
3264 0 : data->data.string.size = 0;
3265 :
3266 0 : init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3267 : &data->data.string.string,
3268 : &data->data.string.size);
3269 :
3270 0 : }
3271 :
3272 : struct s_notify_info_data_table
3273 : {
3274 : enum spoolss_NotifyType type;
3275 : uint16_t field;
3276 : const char *name;
3277 : enum spoolss_NotifyTable variable_type;
3278 : void (*fn) (struct messaging_context *msg_ctx,
3279 : int snum, struct spoolss_Notify *data,
3280 : print_queue_struct *queue,
3281 : struct spoolss_PrinterInfo2 *pinfo2,
3282 : TALLOC_CTX *mem_ctx);
3283 : };
3284 :
3285 : /* A table describing the various print notification constants and
3286 : whether the notification data is a pointer to a variable sized
3287 : buffer, a one value uint32_t or a two value uint32_t. */
3288 :
3289 : static const struct s_notify_info_data_table notify_info_data_table[] =
3290 : {
3291 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3292 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3293 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3294 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3295 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3296 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3297 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3298 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3299 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3300 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3301 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3302 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3303 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3304 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3305 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3306 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3307 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3308 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3309 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3310 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3311 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3312 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3313 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3314 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3315 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3316 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3317 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3318 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3319 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3320 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3321 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3322 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3323 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3324 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3325 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3326 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3327 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3328 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3329 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3330 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3331 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3332 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3333 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3334 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3335 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3336 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3337 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3338 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3339 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3340 : };
3341 :
3342 : /*******************************************************************
3343 : Return the variable_type of info_data structure.
3344 : ********************************************************************/
3345 :
3346 0 : static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3347 : uint16_t field)
3348 : {
3349 0 : int i=0;
3350 :
3351 0 : for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3352 0 : if ( (notify_info_data_table[i].type == type) &&
3353 0 : (notify_info_data_table[i].field == field) ) {
3354 0 : return notify_info_data_table[i].variable_type;
3355 : }
3356 : }
3357 :
3358 0 : DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3359 :
3360 0 : return (enum spoolss_NotifyTable) 0;
3361 : }
3362 :
3363 : /****************************************************************************
3364 : ****************************************************************************/
3365 :
3366 0 : static bool search_notify(enum spoolss_NotifyType type,
3367 : uint16_t field,
3368 : int *value)
3369 : {
3370 0 : int i;
3371 :
3372 0 : for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3373 0 : if (notify_info_data_table[i].type == type &&
3374 0 : notify_info_data_table[i].field == field &&
3375 0 : notify_info_data_table[i].fn != NULL) {
3376 0 : *value = i;
3377 0 : return true;
3378 : }
3379 : }
3380 :
3381 0 : return false;
3382 : }
3383 :
3384 : /****************************************************************************
3385 : ****************************************************************************/
3386 :
3387 0 : static void construct_info_data(struct spoolss_Notify *info_data,
3388 : enum spoolss_NotifyType type,
3389 : uint16_t field, int id)
3390 : {
3391 0 : info_data->type = type;
3392 0 : info_data->field.field = field;
3393 0 : info_data->variable_type = variable_type_of_notify_info_data(type, field);
3394 0 : info_data->job_id = id;
3395 0 : }
3396 :
3397 : /*******************************************************************
3398 : *
3399 : * fill a notify_info struct with info asked
3400 : *
3401 : ********************************************************************/
3402 :
3403 0 : static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3404 : struct printer_handle *print_hnd,
3405 : struct spoolss_NotifyInfo *info,
3406 : struct spoolss_PrinterInfo2 *pinfo2,
3407 : int snum,
3408 : const struct spoolss_NotifyOptionType *option_type,
3409 : uint32_t id,
3410 : TALLOC_CTX *mem_ctx)
3411 : {
3412 0 : const struct loadparm_substitution *lp_sub =
3413 0 : loadparm_s3_global_substitution();
3414 0 : int field_num,j;
3415 0 : enum spoolss_NotifyType type;
3416 0 : uint16_t field;
3417 :
3418 0 : struct spoolss_Notify *current_data;
3419 :
3420 0 : type = option_type->type;
3421 :
3422 0 : DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3423 : (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3424 : option_type->count, lp_servicename(talloc_tos(), lp_sub, snum)));
3425 :
3426 0 : for(field_num=0; field_num < option_type->count; field_num++) {
3427 0 : field = option_type->fields[field_num].field;
3428 :
3429 0 : DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3430 :
3431 0 : if (!search_notify(type, field, &j) )
3432 0 : continue;
3433 :
3434 0 : info->notifies = talloc_realloc(info, info->notifies,
3435 : struct spoolss_Notify,
3436 : info->count + 1);
3437 0 : if (info->notifies == NULL) {
3438 0 : DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3439 0 : return false;
3440 : }
3441 :
3442 0 : current_data = &info->notifies[info->count];
3443 :
3444 0 : construct_info_data(current_data, type, field, id);
3445 :
3446 0 : DEBUG(10, ("construct_notify_printer_info: "
3447 : "calling [%s] snum=%d printername=[%s])\n",
3448 : notify_info_data_table[j].name, snum,
3449 : pinfo2->printername));
3450 :
3451 0 : notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3452 : NULL, pinfo2, mem_ctx);
3453 :
3454 0 : info->count++;
3455 : }
3456 :
3457 0 : return true;
3458 : }
3459 :
3460 : /*******************************************************************
3461 : *
3462 : * fill a notify_info struct with info asked
3463 : *
3464 : ********************************************************************/
3465 :
3466 0 : static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3467 : print_queue_struct *queue,
3468 : struct spoolss_NotifyInfo *info,
3469 : struct spoolss_PrinterInfo2 *pinfo2,
3470 : int snum,
3471 : const struct spoolss_NotifyOptionType *option_type,
3472 : uint32_t id,
3473 : TALLOC_CTX *mem_ctx)
3474 : {
3475 0 : int field_num,j;
3476 0 : enum spoolss_NotifyType type;
3477 0 : uint16_t field;
3478 0 : struct spoolss_Notify *current_data;
3479 :
3480 0 : DEBUG(4,("construct_notify_jobs_info\n"));
3481 :
3482 0 : type = option_type->type;
3483 :
3484 0 : DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3485 : (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3486 : option_type->count));
3487 :
3488 0 : for(field_num=0; field_num<option_type->count; field_num++) {
3489 0 : field = option_type->fields[field_num].field;
3490 :
3491 0 : if (!search_notify(type, field, &j) )
3492 0 : continue;
3493 :
3494 0 : info->notifies = talloc_realloc(info, info->notifies,
3495 : struct spoolss_Notify,
3496 : info->count + 1);
3497 0 : if (info->notifies == NULL) {
3498 0 : DEBUG(2,("construct_notify_jobs_info: failed to enlarge buffer info->data!\n"));
3499 0 : return false;
3500 : }
3501 :
3502 0 : current_data=&(info->notifies[info->count]);
3503 :
3504 0 : construct_info_data(current_data, type, field, id);
3505 0 : notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3506 : queue, pinfo2, mem_ctx);
3507 0 : info->count++;
3508 : }
3509 :
3510 0 : return true;
3511 : }
3512 :
3513 : /*
3514 : * JFM: The enumeration is not that simple, it's even non obvious.
3515 : *
3516 : * let's take an example: I want to monitor the PRINTER SERVER for
3517 : * the printer's name and the number of jobs currently queued.
3518 : * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3519 : * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3520 : *
3521 : * I have 3 printers on the back of my server.
3522 : *
3523 : * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3524 : * structures.
3525 : * Number Data Id
3526 : * 1 printer 1 name 1
3527 : * 2 printer 1 cjob 1
3528 : * 3 printer 2 name 2
3529 : * 4 printer 2 cjob 2
3530 : * 5 printer 3 name 3
3531 : * 6 printer 3 name 3
3532 : *
3533 : * that's the print server case, the printer case is even worse.
3534 : */
3535 :
3536 : /*******************************************************************
3537 : *
3538 : * enumerate all printers on the printserver
3539 : * fill a notify_info struct with info asked
3540 : *
3541 : ********************************************************************/
3542 :
3543 4 : static WERROR printserver_notify_info(struct pipes_struct *p,
3544 : struct policy_handle *hnd,
3545 : struct spoolss_NotifyInfo *info,
3546 : TALLOC_CTX *mem_ctx)
3547 : {
3548 0 : const struct loadparm_substitution *lp_sub =
3549 4 : loadparm_s3_global_substitution();
3550 0 : int snum;
3551 4 : struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3552 4 : int n_services=lp_numservices();
3553 0 : int i;
3554 0 : struct spoolss_NotifyOption *option;
3555 0 : struct spoolss_NotifyOptionType option_type;
3556 4 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3557 0 : WERROR result;
3558 :
3559 4 : DEBUG(4,("printserver_notify_info\n"));
3560 :
3561 4 : if (!Printer)
3562 0 : return WERR_INVALID_HANDLE;
3563 :
3564 4 : option = Printer->notify.option;
3565 :
3566 4 : info->version = 2;
3567 4 : info->notifies = NULL;
3568 4 : info->count = 0;
3569 :
3570 : /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3571 : sending a ffpcn() request first */
3572 :
3573 4 : if ( !option )
3574 0 : return WERR_INVALID_HANDLE;
3575 :
3576 12 : for (i=0; i<option->count; i++) {
3577 8 : option_type = option->types[i];
3578 :
3579 8 : if (option_type.type != PRINTER_NOTIFY_TYPE)
3580 4 : continue;
3581 :
3582 492 : for (snum = 0; snum < n_services; snum++) {
3583 488 : if (!lp_browseable(snum) ||
3584 488 : !lp_snum_ok(snum) ||
3585 488 : !lp_printable(snum)) {
3586 468 : continue; /* skip */
3587 : }
3588 :
3589 : /* Maybe we should use the SYSTEM session_info here... */
3590 20 : result = winreg_get_printer_internal(mem_ctx,
3591 : get_session_info_system(),
3592 : p->msg_ctx,
3593 20 : lp_servicename(talloc_tos(), lp_sub, snum),
3594 : &pinfo2);
3595 20 : if (!W_ERROR_IS_OK(result)) {
3596 20 : DEBUG(4, ("printserver_notify_info: "
3597 : "Failed to get printer [%s]\n",
3598 : lp_servicename(talloc_tos(), lp_sub, snum)));
3599 20 : continue;
3600 : }
3601 :
3602 :
3603 0 : construct_notify_printer_info(p->msg_ctx,
3604 : Printer, info,
3605 : pinfo2, snum,
3606 : &option_type, snum,
3607 : mem_ctx);
3608 :
3609 0 : TALLOC_FREE(pinfo2);
3610 : }
3611 : }
3612 :
3613 : #if 0
3614 : /*
3615 : * Debugging information, don't delete.
3616 : */
3617 :
3618 : DEBUG(1,("dumping the NOTIFY_INFO\n"));
3619 : DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3620 : DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3621 :
3622 : for (i=0; i<info->count; i++) {
3623 : DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3624 : i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3625 : info->data[i].id, info->data[i].size, info->data[i].enc_type));
3626 : }
3627 : #endif
3628 :
3629 4 : return WERR_OK;
3630 : }
3631 :
3632 : /*******************************************************************
3633 : *
3634 : * fill a notify_info struct with info asked
3635 : *
3636 : ********************************************************************/
3637 :
3638 0 : static WERROR printer_notify_info(struct pipes_struct *p,
3639 : struct policy_handle *hnd,
3640 : struct spoolss_NotifyInfo *info,
3641 : TALLOC_CTX *mem_ctx)
3642 : {
3643 0 : const struct loadparm_substitution *lp_sub =
3644 0 : loadparm_s3_global_substitution();
3645 0 : int snum;
3646 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3647 0 : int i;
3648 0 : uint32_t id;
3649 0 : struct spoolss_NotifyOption *option;
3650 0 : struct spoolss_NotifyOptionType option_type;
3651 0 : int count,j;
3652 0 : print_queue_struct *queue=NULL;
3653 0 : print_status_struct status;
3654 0 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3655 0 : WERROR result;
3656 0 : struct tdb_print_db *pdb;
3657 :
3658 0 : DEBUG(4,("printer_notify_info\n"));
3659 :
3660 0 : if (!Printer)
3661 0 : return WERR_INVALID_HANDLE;
3662 :
3663 0 : option = Printer->notify.option;
3664 0 : id = 0x0;
3665 :
3666 0 : info->version = 2;
3667 0 : info->notifies = NULL;
3668 0 : info->count = 0;
3669 :
3670 : /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3671 : sending a ffpcn() request first */
3672 :
3673 0 : if ( !option )
3674 0 : return WERR_INVALID_HANDLE;
3675 :
3676 0 : if (!get_printer_snum(p, hnd, &snum, NULL)) {
3677 0 : return WERR_INVALID_HANDLE;
3678 : }
3679 :
3680 0 : pdb = get_print_db_byname(Printer->sharename);
3681 0 : if (pdb == NULL) {
3682 0 : return WERR_INVALID_HANDLE;
3683 : }
3684 :
3685 : /* Maybe we should use the SYSTEM session_info here... */
3686 0 : result = winreg_get_printer_internal(mem_ctx,
3687 : get_session_info_system(),
3688 : p->msg_ctx,
3689 0 : lp_servicename(talloc_tos(), lp_sub, snum), &pinfo2);
3690 0 : if (!W_ERROR_IS_OK(result)) {
3691 0 : result = WERR_INVALID_HANDLE;
3692 0 : goto err_pdb_drop;
3693 : }
3694 :
3695 : /*
3696 : * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3697 : * correct servername.
3698 : */
3699 0 : pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3700 0 : if (pinfo2->servername == NULL) {
3701 0 : result = WERR_NOT_ENOUGH_MEMORY;
3702 0 : goto err_pdb_drop;
3703 : }
3704 :
3705 0 : for (i = 0; i < option->count; i++) {
3706 0 : option_type = option->types[i];
3707 :
3708 0 : switch (option_type.type) {
3709 0 : case PRINTER_NOTIFY_TYPE:
3710 0 : if (construct_notify_printer_info(p->msg_ctx,
3711 : Printer, info,
3712 : pinfo2, snum,
3713 : &option_type, id,
3714 : mem_ctx)) {
3715 0 : id--;
3716 : }
3717 0 : break;
3718 :
3719 0 : case JOB_NOTIFY_TYPE:
3720 :
3721 0 : count = print_queue_status(p->msg_ctx, snum, &queue,
3722 : &status);
3723 :
3724 0 : for (j = 0; j < count; j++) {
3725 0 : uint32_t jobid;
3726 0 : jobid = sysjob_to_jobid_pdb(pdb,
3727 0 : queue[j].sysjob);
3728 0 : if (jobid == (uint32_t)-1) {
3729 0 : DEBUG(2, ("ignoring untracked job %d\n",
3730 : queue[j].sysjob));
3731 0 : continue;
3732 : }
3733 : /* FIXME check return value */
3734 0 : construct_notify_jobs_info(p->msg_ctx,
3735 0 : &queue[j], info,
3736 : pinfo2, snum,
3737 : &option_type,
3738 : jobid,
3739 : mem_ctx);
3740 : }
3741 :
3742 0 : SAFE_FREE(queue);
3743 0 : break;
3744 : }
3745 : }
3746 :
3747 : /*
3748 : * Debugging information, don't delete.
3749 : */
3750 : /*
3751 : DEBUG(1,("dumping the NOTIFY_INFO\n"));
3752 : DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3753 : DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3754 :
3755 : for (i=0; i<info->count; i++) {
3756 : DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3757 : i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3758 : info->data[i].id, info->data[i].size, info->data[i].enc_type));
3759 : }
3760 : */
3761 :
3762 0 : talloc_free(pinfo2);
3763 0 : result = WERR_OK;
3764 0 : err_pdb_drop:
3765 0 : release_print_db(pdb);
3766 0 : return result;
3767 : }
3768 :
3769 : /****************************************************************
3770 : _spoolss_RouterRefreshPrinterChangeNotify
3771 : ****************************************************************/
3772 :
3773 4 : WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3774 : struct spoolss_RouterRefreshPrinterChangeNotify *r)
3775 : {
3776 0 : struct spoolss_NotifyInfo *info;
3777 :
3778 4 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3779 4 : WERROR result = WERR_INVALID_HANDLE;
3780 :
3781 : /* we always have a spoolss_NotifyInfo struct */
3782 4 : info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3783 4 : if (!info) {
3784 0 : result = WERR_NOT_ENOUGH_MEMORY;
3785 0 : goto done;
3786 : }
3787 :
3788 4 : *r->out.info = info;
3789 :
3790 4 : if (!Printer) {
3791 0 : DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3792 : "Invalid handle (%s:%u:%u).\n",
3793 : OUR_HANDLE(r->in.handle)));
3794 0 : goto done;
3795 : }
3796 :
3797 4 : DEBUG(4,("Printer type %x\n",Printer->printer_type));
3798 :
3799 : /*
3800 : * We are now using the change value, and
3801 : * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3802 : * I don't have a global notification system, I'm sending back all the
3803 : * information even when _NOTHING_ has changed.
3804 : */
3805 :
3806 : /* We need to keep track of the change value to send back in
3807 : RRPCN replies otherwise our updates are ignored. */
3808 :
3809 4 : Printer->notify.fnpcn = true;
3810 :
3811 4 : if (Printer->notify.cli_chan != NULL &&
3812 4 : Printer->notify.cli_chan->active_connections > 0) {
3813 4 : DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3814 : "Saving change value in request [%x]\n",
3815 : r->in.change_low));
3816 4 : Printer->notify.change = r->in.change_low;
3817 : }
3818 :
3819 : /* just ignore the spoolss_NotifyOption */
3820 :
3821 4 : switch (Printer->printer_type) {
3822 4 : case SPLHND_SERVER:
3823 4 : result = printserver_notify_info(p, r->in.handle,
3824 : info, p->mem_ctx);
3825 4 : break;
3826 :
3827 0 : case SPLHND_PRINTER:
3828 0 : result = printer_notify_info(p, r->in.handle,
3829 : info, p->mem_ctx);
3830 0 : break;
3831 : }
3832 :
3833 4 : Printer->notify.fnpcn = false;
3834 :
3835 4 : done:
3836 4 : return result;
3837 : }
3838 :
3839 : /********************************************************************
3840 : ********************************************************************/
3841 :
3842 4076 : static WERROR create_printername(TALLOC_CTX *mem_ctx,
3843 : const char *servername,
3844 : const char *printername,
3845 : const char **printername_p)
3846 : {
3847 : /* FIXME: add lp_force_printername() */
3848 :
3849 4076 : if (servername == NULL) {
3850 1732 : *printername_p = talloc_strdup(mem_ctx, printername);
3851 1732 : W_ERROR_HAVE_NO_MEMORY(*printername_p);
3852 1732 : return WERR_OK;
3853 : }
3854 :
3855 2344 : if (servername[0] == '\\' && servername[1] == '\\') {
3856 2344 : servername += 2;
3857 : }
3858 :
3859 2344 : *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3860 2344 : W_ERROR_HAVE_NO_MEMORY(*printername_p);
3861 :
3862 2344 : return WERR_OK;
3863 : }
3864 :
3865 : /********************************************************************
3866 : ********************************************************************/
3867 :
3868 2936 : static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3869 : const char *printername)
3870 : {
3871 2936 : if (dm == NULL) {
3872 94 : return;
3873 : }
3874 :
3875 2842 : dm->devicename = talloc_strndup(dm, printername,
3876 2842 : MIN(strlen(printername), 31));
3877 : }
3878 :
3879 : /********************************************************************
3880 : * construct_printer_info_0
3881 : * fill a printer_info_0 struct
3882 : ********************************************************************/
3883 :
3884 276 : static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3885 : const struct auth_session_info *session_info,
3886 : struct messaging_context *msg_ctx,
3887 : struct spoolss_PrinterInfo2 *info2,
3888 : const char *servername,
3889 : struct spoolss_PrinterInfo0 *r,
3890 : int snum)
3891 : {
3892 0 : int count;
3893 0 : struct printer_session_counter *session_counter;
3894 0 : struct timeval setuptime;
3895 0 : print_status_struct status;
3896 0 : WERROR result;
3897 0 : int os_major, os_minor, os_build;
3898 0 : const char *architecture;
3899 0 : uint32_t processor_architecture, processor_type;
3900 :
3901 276 : result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3902 276 : if (!W_ERROR_IS_OK(result)) {
3903 0 : return result;
3904 : }
3905 :
3906 276 : if (servername) {
3907 140 : r->servername = talloc_strdup(mem_ctx, servername);
3908 140 : W_ERROR_HAVE_NO_MEMORY(r->servername);
3909 : } else {
3910 136 : r->servername = NULL;
3911 : }
3912 :
3913 276 : count = print_queue_length(msg_ctx, snum, &status);
3914 :
3915 : /* check if we already have a counter for this printer */
3916 660 : for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3917 620 : if (session_counter->snum == snum)
3918 236 : break;
3919 : }
3920 :
3921 : /* it's the first time, add it to the list */
3922 276 : if (session_counter == NULL) {
3923 40 : session_counter = talloc_zero(counter_list, struct printer_session_counter);
3924 40 : W_ERROR_HAVE_NO_MEMORY(session_counter);
3925 40 : session_counter->snum = snum;
3926 40 : session_counter->counter = 0;
3927 40 : DLIST_ADD(counter_list, session_counter);
3928 : }
3929 :
3930 : /* increment it */
3931 276 : session_counter->counter++;
3932 :
3933 276 : r->cjobs = count;
3934 276 : r->total_jobs = 0;
3935 276 : r->total_bytes = 0;
3936 :
3937 276 : get_startup_time(&setuptime);
3938 276 : init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3939 :
3940 : /* JFM:
3941 : * the global_counter should be stored in a TDB as it's common to all the clients
3942 : * and should be zeroed on samba startup
3943 : */
3944 276 : r->global_counter = session_counter->counter;
3945 276 : r->total_pages = 0;
3946 :
3947 : /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3948 276 : os_major = lp_parm_int(GLOBAL_SECTION_SNUM,
3949 : "spoolss", "os_major",
3950 : GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT);
3951 276 : os_minor = lp_parm_int(GLOBAL_SECTION_SNUM,
3952 : "spoolss", "os_minor",
3953 : GLOBAL_SPOOLSS_OS_MINOR_DEFAULT);
3954 276 : os_build = lp_parm_int(GLOBAL_SECTION_SNUM,
3955 : "spoolss", "os_build",
3956 : GLOBAL_SPOOLSS_OS_BUILD_DEFAULT);
3957 :
3958 276 : SCVAL(&r->version, 0, os_major);
3959 276 : SCVAL(&r->version, 1, os_minor);
3960 276 : SSVAL(&r->version, 2, os_build);
3961 :
3962 276 : architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
3963 : "spoolss",
3964 : "architecture",
3965 : GLOBAL_SPOOLSS_ARCHITECTURE);
3966 :
3967 276 : if (strequal(architecture, SPOOLSS_ARCHITECTURE_x64)) {
3968 276 : processor_architecture = PROCESSOR_ARCHITECTURE_AMD64;
3969 276 : processor_type = PROCESSOR_AMD_X8664;
3970 0 : } else if (strequal(architecture, SPOOLSS_ARCHITECTURE_ARM64)) {
3971 0 : processor_architecture = PROCESSOR_ARCHITECTURE_ARM64;
3972 0 : processor_type = PROCESSOR_ARM820;
3973 : } else {
3974 0 : processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3975 0 : processor_type = PROCESSOR_INTEL_PENTIUM;
3976 : }
3977 :
3978 276 : r->free_build = SPOOLSS_RELEASE_BUILD;
3979 276 : r->spooling = 0;
3980 276 : r->max_spooling = 0;
3981 276 : r->session_counter = session_counter->counter;
3982 276 : r->num_error_out_of_paper = 0x0;
3983 276 : r->num_error_not_ready = 0x0; /* number of print failure */
3984 276 : r->job_error = 0x0;
3985 276 : r->number_of_processors = 0x1;
3986 276 : r->processor_type = processor_type;
3987 276 : r->high_part_total_bytes = 0x0;
3988 :
3989 : /* ChangeID in milliseconds*/
3990 276 : winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3991 : info2->sharename, &r->change_id);
3992 :
3993 276 : r->last_error = WERR_OK;
3994 276 : r->status = nt_printq_status(status.status);
3995 276 : r->enumerate_network_printers = 0x0;
3996 276 : r->c_setprinter = 0x0;
3997 276 : r->processor_architecture = processor_architecture;
3998 276 : r->processor_level = 0x6; /* 6 ???*/
3999 276 : r->ref_ic = 0;
4000 276 : r->reserved2 = 0;
4001 276 : r->reserved3 = 0;
4002 :
4003 276 : return WERR_OK;
4004 : }
4005 :
4006 :
4007 : /********************************************************************
4008 : * construct_printer_info1
4009 : * fill a spoolss_PrinterInfo1 struct
4010 : ********************************************************************/
4011 :
4012 528 : static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
4013 : const struct spoolss_PrinterInfo2 *info2,
4014 : uint32_t flags,
4015 : const char *servername,
4016 : struct spoolss_PrinterInfo1 *r,
4017 : int snum)
4018 : {
4019 0 : const struct loadparm_substitution *lp_sub =
4020 528 : loadparm_s3_global_substitution();
4021 0 : WERROR result;
4022 :
4023 528 : r->flags = flags;
4024 :
4025 528 : if (info2->comment == NULL || info2->comment[0] == '\0') {
4026 388 : r->comment = lp_comment(mem_ctx, lp_sub, snum);
4027 : } else {
4028 140 : r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
4029 : }
4030 528 : W_ERROR_HAVE_NO_MEMORY(r->comment);
4031 :
4032 528 : result = create_printername(mem_ctx, servername, info2->printername, &r->name);
4033 528 : if (!W_ERROR_IS_OK(result)) {
4034 0 : return result;
4035 : }
4036 :
4037 1056 : r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
4038 : r->name,
4039 528 : info2->drivername,
4040 : r->comment);
4041 528 : W_ERROR_HAVE_NO_MEMORY(r->description);
4042 :
4043 528 : return WERR_OK;
4044 : }
4045 :
4046 : /********************************************************************
4047 : * construct_printer_info2
4048 : * fill a spoolss_PrinterInfo2 struct
4049 : ********************************************************************/
4050 :
4051 1272 : static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4052 : struct messaging_context *msg_ctx,
4053 : const struct spoolss_PrinterInfo2 *info2,
4054 : const char *servername,
4055 : struct spoolss_PrinterInfo2 *r,
4056 : int snum)
4057 : {
4058 0 : const struct loadparm_substitution *lp_sub =
4059 1272 : loadparm_s3_global_substitution();
4060 0 : int count;
4061 0 : print_status_struct status;
4062 0 : WERROR result;
4063 :
4064 1272 : count = print_queue_length(msg_ctx, snum, &status);
4065 :
4066 1272 : if (servername) {
4067 572 : r->servername = talloc_strdup(mem_ctx, servername);
4068 572 : W_ERROR_HAVE_NO_MEMORY(r->servername);
4069 : } else {
4070 700 : r->servername = NULL;
4071 : }
4072 :
4073 1272 : result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4074 1272 : if (!W_ERROR_IS_OK(result)) {
4075 0 : return result;
4076 : }
4077 :
4078 1272 : r->sharename = lp_servicename(mem_ctx, lp_sub, snum);
4079 1272 : W_ERROR_HAVE_NO_MEMORY(r->sharename);
4080 1272 : r->portname = talloc_strdup(mem_ctx, info2->portname);
4081 1272 : W_ERROR_HAVE_NO_MEMORY(r->portname);
4082 1272 : r->drivername = talloc_strdup(mem_ctx, info2->drivername);
4083 1272 : W_ERROR_HAVE_NO_MEMORY(r->drivername);
4084 :
4085 1272 : if (info2->comment[0] == '\0') {
4086 876 : r->comment = lp_comment(mem_ctx, lp_sub, snum);
4087 : } else {
4088 396 : r->comment = talloc_strdup(mem_ctx, info2->comment);
4089 : }
4090 1272 : W_ERROR_HAVE_NO_MEMORY(r->comment);
4091 :
4092 1272 : r->location = talloc_strdup(mem_ctx, info2->location);
4093 1272 : if (info2->location[0] == '\0') {
4094 1192 : const char *loc = NULL;
4095 0 : NTSTATUS nt_status;
4096 :
4097 1192 : nt_status = printer_list_get_printer(mem_ctx,
4098 1192 : info2->sharename,
4099 : NULL,
4100 : &loc,
4101 : NULL);
4102 1192 : if (NT_STATUS_IS_OK(nt_status)) {
4103 0 : if (loc != NULL) {
4104 0 : r->location = talloc_strdup(mem_ctx, loc);
4105 : }
4106 : }
4107 : }
4108 1272 : W_ERROR_HAVE_NO_MEMORY(r->location);
4109 :
4110 1272 : r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4111 1272 : W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4112 1272 : r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4113 1272 : W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4114 1272 : r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4115 1272 : W_ERROR_HAVE_NO_MEMORY(r->datatype);
4116 1272 : r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4117 1272 : W_ERROR_HAVE_NO_MEMORY(r->parameters);
4118 :
4119 1272 : r->attributes = info2->attributes;
4120 :
4121 1272 : r->priority = info2->priority;
4122 1272 : r->defaultpriority = info2->defaultpriority;
4123 1272 : r->starttime = info2->starttime;
4124 1272 : r->untiltime = info2->untiltime;
4125 1272 : r->status = nt_printq_status(status.status);
4126 1272 : r->cjobs = count;
4127 1272 : r->averageppm = info2->averageppm;
4128 :
4129 1272 : if (info2->devmode != NULL) {
4130 1186 : result = copy_devicemode(mem_ctx,
4131 1186 : info2->devmode,
4132 : &r->devmode);
4133 1186 : if (!W_ERROR_IS_OK(result)) {
4134 0 : return result;
4135 : }
4136 86 : } else if (lp_default_devmode(snum)) {
4137 0 : result = spoolss_create_default_devmode(mem_ctx,
4138 0 : info2->printername,
4139 : &r->devmode);
4140 0 : if (!W_ERROR_IS_OK(result)) {
4141 0 : return result;
4142 : }
4143 : } else {
4144 86 : r->devmode = NULL;
4145 86 : DEBUG(8,("Returning NULL Devicemode!\n"));
4146 : }
4147 :
4148 1272 : compose_devicemode_devicename(r->devmode, r->printername);
4149 :
4150 1272 : r->secdesc = NULL;
4151 :
4152 1272 : if (info2->secdesc != NULL) {
4153 : /* don't use talloc_steal() here unless you do a deep steal of all
4154 : the SEC_DESC members */
4155 :
4156 1272 : r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4157 1272 : if (r->secdesc == NULL) {
4158 0 : return WERR_NOT_ENOUGH_MEMORY;
4159 : }
4160 : }
4161 :
4162 1272 : return WERR_OK;
4163 : }
4164 :
4165 : /********************************************************************
4166 : * construct_printer_info3
4167 : * fill a spoolss_PrinterInfo3 struct
4168 : ********************************************************************/
4169 :
4170 144 : static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4171 : const struct spoolss_PrinterInfo2 *info2,
4172 : const char *servername,
4173 : struct spoolss_PrinterInfo3 *r,
4174 : int snum)
4175 : {
4176 : /* These are the components of the SD we are returning. */
4177 :
4178 144 : if (info2->secdesc != NULL) {
4179 : /* don't use talloc_steal() here unless you do a deep steal of all
4180 : the SEC_DESC members */
4181 :
4182 144 : r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4183 144 : if (r->secdesc == NULL) {
4184 0 : return WERR_NOT_ENOUGH_MEMORY;
4185 : }
4186 : }
4187 :
4188 144 : return WERR_OK;
4189 : }
4190 :
4191 : /********************************************************************
4192 : * construct_printer_info4
4193 : * fill a spoolss_PrinterInfo4 struct
4194 : ********************************************************************/
4195 :
4196 168 : static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4197 : const struct spoolss_PrinterInfo2 *info2,
4198 : const char *servername,
4199 : struct spoolss_PrinterInfo4 *r,
4200 : int snum)
4201 : {
4202 0 : WERROR result;
4203 :
4204 168 : result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4205 168 : if (!W_ERROR_IS_OK(result)) {
4206 0 : return result;
4207 : }
4208 :
4209 168 : if (servername) {
4210 8 : r->servername = talloc_strdup(mem_ctx, servername);
4211 8 : W_ERROR_HAVE_NO_MEMORY(r->servername);
4212 : } else {
4213 160 : r->servername = NULL;
4214 : }
4215 :
4216 168 : r->attributes = info2->attributes;
4217 :
4218 168 : return WERR_OK;
4219 : }
4220 :
4221 : /********************************************************************
4222 : * construct_printer_info5
4223 : * fill a spoolss_PrinterInfo5 struct
4224 : ********************************************************************/
4225 :
4226 168 : static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4227 : const struct spoolss_PrinterInfo2 *info2,
4228 : const char *servername,
4229 : struct spoolss_PrinterInfo5 *r,
4230 : int snum)
4231 : {
4232 0 : WERROR result;
4233 :
4234 168 : result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4235 168 : if (!W_ERROR_IS_OK(result)) {
4236 0 : return result;
4237 : }
4238 :
4239 168 : r->portname = talloc_strdup(mem_ctx, info2->portname);
4240 168 : W_ERROR_HAVE_NO_MEMORY(r->portname);
4241 :
4242 168 : r->attributes = info2->attributes;
4243 :
4244 : /*
4245 : * These two are not used by NT+ according to MSDN. However the values
4246 : * we saw on Windows Server 2012 and 2016 are always set to the 0xafc8.
4247 : */
4248 168 : r->device_not_selected_timeout = 0xafc8; /* 45 sec */
4249 168 : r->transmission_retry_timeout = 0xafc8; /* 45 sec */
4250 :
4251 168 : return WERR_OK;
4252 : }
4253 :
4254 : /********************************************************************
4255 : * construct_printer_info_6
4256 : * fill a spoolss_PrinterInfo6 struct
4257 : ********************************************************************/
4258 :
4259 88 : static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4260 : struct messaging_context *msg_ctx,
4261 : const struct spoolss_PrinterInfo2 *info2,
4262 : const char *servername,
4263 : struct spoolss_PrinterInfo6 *r,
4264 : int snum)
4265 : {
4266 0 : print_status_struct status;
4267 :
4268 88 : print_queue_length(msg_ctx, snum, &status);
4269 :
4270 88 : r->status = nt_printq_status(status.status);
4271 :
4272 88 : return WERR_OK;
4273 : }
4274 :
4275 : /********************************************************************
4276 : * construct_printer_info7
4277 : * fill a spoolss_PrinterInfo7 struct
4278 : ********************************************************************/
4279 :
4280 112 : static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4281 : struct messaging_context *msg_ctx,
4282 : const char *servername,
4283 : struct spoolss_PrinterInfo7 *r,
4284 : int snum)
4285 : {
4286 0 : const struct loadparm_substitution *lp_sub =
4287 112 : loadparm_s3_global_substitution();
4288 0 : const struct auth_session_info *session_info;
4289 112 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
4290 0 : char *printer;
4291 0 : WERROR werr;
4292 112 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4293 112 : if (tmp_ctx == NULL) {
4294 0 : return WERR_NOT_ENOUGH_MEMORY;
4295 : }
4296 :
4297 112 : session_info = get_session_info_system();
4298 112 : SMB_ASSERT(session_info != NULL);
4299 :
4300 112 : printer = lp_servicename(tmp_ctx, lp_sub, snum);
4301 112 : if (printer == NULL) {
4302 0 : DEBUG(0, ("invalid printer snum %d\n", snum));
4303 0 : werr = WERR_INVALID_PARAMETER;
4304 0 : goto out_tmp_free;
4305 : }
4306 :
4307 112 : if (is_printer_published(tmp_ctx, session_info, msg_ctx,
4308 : servername, printer, &pinfo2)) {
4309 0 : struct GUID guid;
4310 0 : char *guidstr;
4311 0 : werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
4312 : printer, &guid);
4313 0 : if (!W_ERROR_IS_OK(werr)) {
4314 : /*
4315 : * If we do not have a GUID entry in the registry, then
4316 : * try to retrieve it from AD and store it now.
4317 : */
4318 0 : werr = nt_printer_guid_retrieve(tmp_ctx, printer,
4319 : &guid);
4320 0 : if (!W_ERROR_IS_OK(werr)) {
4321 0 : DBG_NOTICE("Failed to retrieve GUID for "
4322 : "printer [%s] from AD - %s\n",
4323 : printer,
4324 : win_errstr(werr));
4325 0 : if (W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND)) {
4326 : /*
4327 : * If we did not find it in AD, then it
4328 : * is unpublished and we should reflect
4329 : * this in the registry and return
4330 : * success.
4331 : */
4332 0 : DBG_WARNING("Unpublish printer [%s]\n",
4333 : pinfo2->sharename);
4334 0 : nt_printer_publish(tmp_ctx,
4335 : session_info,
4336 : msg_ctx,
4337 : pinfo2,
4338 : DSPRINT_UNPUBLISH);
4339 0 : r->guid = talloc_strdup(mem_ctx, "");
4340 0 : r->action = DSPRINT_UNPUBLISH;
4341 :
4342 0 : if (r->guid == NULL) {
4343 0 : werr = WERR_NOT_ENOUGH_MEMORY;
4344 : } else {
4345 0 : werr = WERR_OK;
4346 : }
4347 : }
4348 0 : goto out_tmp_free;
4349 : }
4350 :
4351 0 : werr = nt_printer_guid_store(msg_ctx, printer, guid);
4352 0 : if (!W_ERROR_IS_OK(werr)) {
4353 0 : DEBUG(3, ("failed to store printer %s guid\n",
4354 : printer));
4355 : }
4356 : }
4357 :
4358 : /* [MS-RPRN] section 2.2: must use curly-braced GUIDs */
4359 0 : guidstr = GUID_string2(mem_ctx, &guid);
4360 0 : if (guidstr == NULL) {
4361 0 : werr = WERR_NOT_ENOUGH_MEMORY;
4362 0 : goto out_tmp_free;
4363 : }
4364 : /* Convert GUID string to uppercase otherwise printers
4365 : * are pruned */
4366 0 : r->guid = talloc_strdup_upper(mem_ctx, guidstr);
4367 0 : r->action = DSPRINT_PUBLISH;
4368 :
4369 0 : TALLOC_FREE(guidstr);
4370 : } else {
4371 112 : r->guid = talloc_strdup(mem_ctx, "");
4372 112 : r->action = DSPRINT_UNPUBLISH;
4373 : }
4374 112 : if (r->guid == NULL) {
4375 0 : werr = WERR_NOT_ENOUGH_MEMORY;
4376 0 : goto out_tmp_free;
4377 : }
4378 :
4379 112 : werr = WERR_OK;
4380 112 : out_tmp_free:
4381 112 : talloc_free(tmp_ctx);
4382 112 : return werr;
4383 : }
4384 :
4385 : /********************************************************************
4386 : * construct_printer_info8
4387 : * fill a spoolss_PrinterInfo8 struct
4388 : ********************************************************************/
4389 :
4390 1664 : static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4391 : const struct spoolss_PrinterInfo2 *info2,
4392 : const char *servername,
4393 : struct spoolss_DeviceModeInfo *r,
4394 : int snum)
4395 : {
4396 0 : WERROR result;
4397 0 : const char *printername;
4398 :
4399 1664 : result = create_printername(mem_ctx, servername, info2->printername, &printername);
4400 1664 : if (!W_ERROR_IS_OK(result)) {
4401 0 : return result;
4402 : }
4403 :
4404 1664 : if (info2->devmode != NULL) {
4405 1656 : result = copy_devicemode(mem_ctx,
4406 1656 : info2->devmode,
4407 : &r->devmode);
4408 1656 : if (!W_ERROR_IS_OK(result)) {
4409 0 : return result;
4410 : }
4411 8 : } else if (lp_default_devmode(snum)) {
4412 0 : result = spoolss_create_default_devmode(mem_ctx,
4413 0 : info2->printername,
4414 : &r->devmode);
4415 0 : if (!W_ERROR_IS_OK(result)) {
4416 0 : return result;
4417 : }
4418 : } else {
4419 8 : r->devmode = NULL;
4420 8 : DEBUG(8,("Returning NULL Devicemode!\n"));
4421 : }
4422 :
4423 1664 : compose_devicemode_devicename(r->devmode, printername);
4424 :
4425 1664 : return WERR_OK;
4426 : }
4427 :
4428 : /********************************************************************
4429 : Spoolss_enumprinters.
4430 : ********************************************************************/
4431 :
4432 180 : static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4433 : const struct auth_session_info *session_info,
4434 : struct messaging_context *msg_ctx,
4435 : const char *servername,
4436 : uint32_t level,
4437 : uint32_t flags,
4438 : union spoolss_PrinterInfo **info_p,
4439 : uint32_t *count_p)
4440 : {
4441 0 : int snum;
4442 0 : int n_services;
4443 180 : union spoolss_PrinterInfo *info = NULL;
4444 180 : uint32_t count = 0;
4445 180 : WERROR result = WERR_OK;
4446 180 : struct dcerpc_binding_handle *b = NULL;
4447 180 : TALLOC_CTX *tmp_ctx = NULL;
4448 :
4449 180 : tmp_ctx = talloc_new(mem_ctx);
4450 180 : if (!tmp_ctx) {
4451 0 : return WERR_NOT_ENOUGH_MEMORY;
4452 : }
4453 :
4454 : /*
4455 : * printer shares are updated on client enumeration. The background
4456 : * printer process updates printer_list.tdb at regular intervals.
4457 : */
4458 180 : become_root();
4459 180 : delete_and_reload_printers();
4460 180 : unbecome_root();
4461 :
4462 180 : n_services = lp_numservices();
4463 180 : *count_p = 0;
4464 180 : *info_p = NULL;
4465 :
4466 12230 : for (snum = 0; snum < n_services; snum++) {
4467 :
4468 0 : const char *printer;
4469 0 : struct spoolss_PrinterInfo2 *info2;
4470 :
4471 12050 : if (!snum_is_shared_printer(snum)) {
4472 11070 : continue;
4473 : }
4474 :
4475 980 : printer = lp_const_servicename(snum);
4476 :
4477 980 : DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4478 : printer, snum));
4479 :
4480 980 : if (b == NULL) {
4481 180 : result = winreg_printer_binding_handle(tmp_ctx,
4482 : session_info,
4483 : msg_ctx,
4484 : &b);
4485 180 : if (!W_ERROR_IS_OK(result)) {
4486 0 : goto out;
4487 : }
4488 : }
4489 :
4490 980 : result = winreg_create_printer(tmp_ctx, b,
4491 : printer);
4492 980 : if (!W_ERROR_IS_OK(result)) {
4493 0 : goto out;
4494 : }
4495 :
4496 980 : info = talloc_realloc(tmp_ctx, info,
4497 : union spoolss_PrinterInfo,
4498 : count + 1);
4499 980 : if (!info) {
4500 0 : result = WERR_NOT_ENOUGH_MEMORY;
4501 0 : goto out;
4502 : }
4503 :
4504 980 : result = winreg_get_printer(tmp_ctx, b,
4505 : printer, &info2);
4506 980 : if (!W_ERROR_IS_OK(result)) {
4507 0 : goto out;
4508 : }
4509 :
4510 980 : switch (level) {
4511 40 : case 0:
4512 40 : result = construct_printer_info0(info, session_info,
4513 : msg_ctx, info2,
4514 : servername,
4515 40 : &info[count].info0, snum);
4516 40 : break;
4517 440 : case 1:
4518 440 : result = construct_printer_info1(info, info2, flags,
4519 : servername,
4520 440 : &info[count].info1, snum);
4521 440 : break;
4522 340 : case 2:
4523 340 : result = construct_printer_info2(info, msg_ctx, info2,
4524 : servername,
4525 340 : &info[count].info2, snum);
4526 340 : break;
4527 80 : case 4:
4528 80 : result = construct_printer_info4(info, info2,
4529 : servername,
4530 80 : &info[count].info4, snum);
4531 80 : break;
4532 80 : case 5:
4533 80 : result = construct_printer_info5(info, info2,
4534 : servername,
4535 80 : &info[count].info5, snum);
4536 80 : break;
4537 :
4538 0 : default:
4539 0 : result = WERR_INVALID_LEVEL;
4540 0 : goto out;
4541 : }
4542 :
4543 980 : if (!W_ERROR_IS_OK(result)) {
4544 0 : goto out;
4545 : }
4546 :
4547 980 : count++;
4548 : }
4549 :
4550 180 : out:
4551 180 : if (W_ERROR_IS_OK(result)) {
4552 180 : *info_p = talloc_move(mem_ctx, &info);
4553 180 : *count_p = count;
4554 : }
4555 :
4556 180 : talloc_free(tmp_ctx);
4557 :
4558 180 : return result;
4559 : }
4560 :
4561 : /********************************************************************
4562 : * handle enumeration of printers at level 0
4563 : ********************************************************************/
4564 :
4565 8 : static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4566 : const struct auth_session_info *session_info,
4567 : struct messaging_context *msg_ctx,
4568 : uint32_t flags,
4569 : const char *servername,
4570 : union spoolss_PrinterInfo **info,
4571 : uint32_t *count)
4572 : {
4573 8 : DEBUG(4,("enum_all_printers_info_0\n"));
4574 :
4575 8 : return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4576 : servername, 0, flags, info, count);
4577 : }
4578 :
4579 :
4580 : /********************************************************************
4581 : ********************************************************************/
4582 :
4583 72 : static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4584 : const struct auth_session_info *session_info,
4585 : struct messaging_context *msg_ctx,
4586 : const char *servername,
4587 : uint32_t flags,
4588 : union spoolss_PrinterInfo **info,
4589 : uint32_t *count)
4590 : {
4591 72 : DEBUG(4,("enum_all_printers_info_1\n"));
4592 :
4593 72 : return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4594 : servername, 1, flags, info, count);
4595 : }
4596 :
4597 : /********************************************************************
4598 : enum_all_printers_info_1_local.
4599 : *********************************************************************/
4600 :
4601 72 : static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4602 : const struct auth_session_info *session_info,
4603 : struct messaging_context *msg_ctx,
4604 : const char *servername,
4605 : union spoolss_PrinterInfo **info,
4606 : uint32_t *count)
4607 : {
4608 72 : DEBUG(4,("enum_all_printers_info_1_local\n"));
4609 :
4610 72 : return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4611 : servername, PRINTER_ENUM_ICON8, info, count);
4612 : }
4613 :
4614 : /********************************************************************
4615 : enum_all_printers_info_1_name.
4616 : *********************************************************************/
4617 :
4618 0 : static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4619 : const struct auth_session_info *session_info,
4620 : struct messaging_context *msg_ctx,
4621 : const char *servername,
4622 : union spoolss_PrinterInfo **info,
4623 : uint32_t *count)
4624 : {
4625 0 : const char *s = servername;
4626 :
4627 0 : DEBUG(4,("enum_all_printers_info_1_name\n"));
4628 :
4629 0 : if (servername != NULL &&
4630 0 : (servername[0] == '\\') && (servername[1] == '\\')) {
4631 0 : s = servername + 2;
4632 : }
4633 :
4634 0 : if (!is_myname_or_ipaddr(s)) {
4635 0 : return WERR_INVALID_NAME;
4636 : }
4637 :
4638 0 : return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4639 : servername, PRINTER_ENUM_ICON8, info, count);
4640 : }
4641 :
4642 : /********************************************************************
4643 : enum_all_printers_info_1_network.
4644 : *********************************************************************/
4645 :
4646 0 : static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4647 : const struct auth_session_info *session_info,
4648 : struct messaging_context *msg_ctx,
4649 : const char *servername,
4650 : union spoolss_PrinterInfo **info,
4651 : uint32_t *count)
4652 : {
4653 0 : const char *s = servername;
4654 :
4655 0 : DEBUG(4,("enum_all_printers_info_1_network\n"));
4656 :
4657 : /* If we respond to a enum_printers level 1 on our name with flags
4658 : set to PRINTER_ENUM_REMOTE with a list of printers then these
4659 : printers incorrectly appear in the APW browse list.
4660 : Specifically the printers for the server appear at the workgroup
4661 : level where all the other servers in the domain are
4662 : listed. Windows responds to this call with a
4663 : WERR_CAN_NOT_COMPLETE so we should do the same. */
4664 :
4665 0 : if (servername != NULL &&
4666 0 : (servername[0] == '\\') && (servername[1] == '\\')) {
4667 0 : s = servername + 2;
4668 : }
4669 :
4670 0 : if (is_myname_or_ipaddr(s)) {
4671 0 : return WERR_CAN_NOT_COMPLETE;
4672 : }
4673 :
4674 0 : return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4675 : servername, PRINTER_ENUM_NAME, info, count);
4676 : }
4677 :
4678 : /********************************************************************
4679 : * api_spoolss_enumprinters
4680 : *
4681 : * called from api_spoolss_enumprinters (see this to understand)
4682 : ********************************************************************/
4683 :
4684 68 : static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4685 : const struct auth_session_info *session_info,
4686 : struct messaging_context *msg_ctx,
4687 : const char *servername,
4688 : union spoolss_PrinterInfo **info,
4689 : uint32_t *count)
4690 : {
4691 68 : DEBUG(4,("enum_all_printers_info_2\n"));
4692 :
4693 68 : return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4694 : servername, 2, 0, info, count);
4695 : }
4696 :
4697 : /********************************************************************
4698 : * handle enumeration of printers at level 1
4699 : ********************************************************************/
4700 :
4701 72 : static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4702 : const struct auth_session_info *session_info,
4703 : struct messaging_context *msg_ctx,
4704 : uint32_t flags,
4705 : const char *servername,
4706 : union spoolss_PrinterInfo **info,
4707 : uint32_t *count)
4708 : {
4709 : /* Not all the flags are equals */
4710 :
4711 72 : if (flags & PRINTER_ENUM_LOCAL) {
4712 72 : return enum_all_printers_info_1_local(mem_ctx, session_info,
4713 : msg_ctx, servername, info, count);
4714 : }
4715 :
4716 0 : if (flags & PRINTER_ENUM_NAME) {
4717 0 : return enum_all_printers_info_1_name(mem_ctx, session_info,
4718 : msg_ctx, servername, info,
4719 : count);
4720 : }
4721 :
4722 0 : if (flags & PRINTER_ENUM_NETWORK) {
4723 0 : return enum_all_printers_info_1_network(mem_ctx, session_info,
4724 : msg_ctx, servername, info,
4725 : count);
4726 : }
4727 :
4728 0 : return WERR_OK; /* NT4sp5 does that */
4729 : }
4730 :
4731 : /********************************************************************
4732 : * handle enumeration of printers at level 2
4733 : ********************************************************************/
4734 :
4735 68 : static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4736 : const struct auth_session_info *session_info,
4737 : struct messaging_context *msg_ctx,
4738 : uint32_t flags,
4739 : const char *servername,
4740 : union spoolss_PrinterInfo **info,
4741 : uint32_t *count)
4742 : {
4743 68 : if (flags & PRINTER_ENUM_LOCAL) {
4744 :
4745 52 : return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4746 : servername,
4747 : info, count);
4748 : }
4749 :
4750 16 : if (flags & PRINTER_ENUM_NAME) {
4751 16 : if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4752 0 : return WERR_INVALID_NAME;
4753 : }
4754 :
4755 16 : return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4756 : servername,
4757 : info, count);
4758 : }
4759 :
4760 0 : if (flags & PRINTER_ENUM_REMOTE) {
4761 0 : return WERR_INVALID_LEVEL;
4762 : }
4763 :
4764 0 : return WERR_OK;
4765 : }
4766 :
4767 : /********************************************************************
4768 : * handle enumeration of printers at level 4
4769 : ********************************************************************/
4770 :
4771 16 : static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4772 : const struct auth_session_info *session_info,
4773 : struct messaging_context *msg_ctx,
4774 : uint32_t flags,
4775 : const char *servername,
4776 : union spoolss_PrinterInfo **info,
4777 : uint32_t *count)
4778 : {
4779 16 : DEBUG(4,("enum_all_printers_info_4\n"));
4780 :
4781 16 : return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4782 : servername, 4, flags, info, count);
4783 : }
4784 :
4785 :
4786 : /********************************************************************
4787 : * handle enumeration of printers at level 5
4788 : ********************************************************************/
4789 :
4790 16 : static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4791 : const struct auth_session_info *session_info,
4792 : struct messaging_context *msg_ctx,
4793 : uint32_t flags,
4794 : const char *servername,
4795 : union spoolss_PrinterInfo **info,
4796 : uint32_t *count)
4797 : {
4798 16 : DEBUG(4,("enum_all_printers_info_5\n"));
4799 :
4800 16 : return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4801 : servername, 5, flags, info, count);
4802 : }
4803 :
4804 : /****************************************************************
4805 : _spoolss_EnumPrinters
4806 : ****************************************************************/
4807 :
4808 180 : WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4809 : struct spoolss_EnumPrinters *r)
4810 : {
4811 180 : const struct auth_session_info *session_info = get_session_info_system();
4812 0 : WERROR result;
4813 :
4814 : /* that's an [in out] buffer */
4815 :
4816 180 : if (!r->in.buffer && (r->in.offered != 0)) {
4817 0 : return WERR_INVALID_PARAMETER;
4818 : }
4819 :
4820 180 : DEBUG(4,("_spoolss_EnumPrinters\n"));
4821 :
4822 180 : *r->out.needed = 0;
4823 180 : *r->out.count = 0;
4824 180 : *r->out.info = NULL;
4825 :
4826 : /*
4827 : * Level 1:
4828 : * flags==PRINTER_ENUM_NAME
4829 : * if name=="" then enumerates all printers
4830 : * if name!="" then enumerate the printer
4831 : * flags==PRINTER_ENUM_REMOTE
4832 : * name is NULL, enumerate printers
4833 : * Level 2: name!="" enumerates printers, name can't be NULL
4834 : * Level 3: doesn't exist
4835 : * Level 4: does a local registry lookup
4836 : * Level 5: same as Level 2
4837 : */
4838 :
4839 180 : if (r->in.server && r->in.server[0] == '\0') {
4840 80 : r->in.server = NULL;
4841 : }
4842 :
4843 180 : switch (r->in.level) {
4844 8 : case 0:
4845 8 : result = enumprinters_level0(p->mem_ctx, session_info,
4846 : p->msg_ctx, r->in.flags,
4847 : r->in.server,
4848 : r->out.info, r->out.count);
4849 8 : break;
4850 72 : case 1:
4851 72 : result = enumprinters_level1(p->mem_ctx, session_info,
4852 : p->msg_ctx, r->in.flags,
4853 : r->in.server,
4854 : r->out.info, r->out.count);
4855 72 : break;
4856 68 : case 2:
4857 68 : result = enumprinters_level2(p->mem_ctx, session_info,
4858 : p->msg_ctx, r->in.flags,
4859 : r->in.server,
4860 : r->out.info, r->out.count);
4861 68 : break;
4862 16 : case 4:
4863 16 : result = enumprinters_level4(p->mem_ctx, session_info,
4864 : p->msg_ctx, r->in.flags,
4865 : r->in.server,
4866 : r->out.info, r->out.count);
4867 16 : break;
4868 16 : case 5:
4869 16 : result = enumprinters_level5(p->mem_ctx, session_info,
4870 : p->msg_ctx, r->in.flags,
4871 : r->in.server,
4872 : r->out.info, r->out.count);
4873 16 : break;
4874 0 : default:
4875 0 : return WERR_INVALID_LEVEL;
4876 : }
4877 :
4878 180 : if (!W_ERROR_IS_OK(result)) {
4879 0 : return result;
4880 : }
4881 :
4882 180 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4883 : spoolss_EnumPrinters,
4884 : *r->out.info, r->in.level,
4885 : *r->out.count);
4886 180 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4887 180 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4888 :
4889 180 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4890 : }
4891 :
4892 : /****************************************************************
4893 : _spoolss_GetPrinter
4894 : ****************************************************************/
4895 :
4896 3512 : WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4897 : struct spoolss_GetPrinter *r)
4898 : {
4899 3512 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4900 3512 : struct spoolss_PrinterInfo2 *info2 = NULL;
4901 3512 : WERROR result = WERR_OK;
4902 0 : int snum;
4903 :
4904 : /* that's an [in out] buffer */
4905 :
4906 3512 : if (!r->in.buffer && (r->in.offered != 0)) {
4907 0 : result = WERR_INVALID_PARAMETER;
4908 0 : goto err_info_free;
4909 : }
4910 :
4911 3512 : *r->out.needed = 0;
4912 :
4913 3512 : if (Printer == NULL) {
4914 0 : result = WERR_INVALID_HANDLE;
4915 0 : goto err_info_free;
4916 : }
4917 :
4918 3512 : if (Printer->printer_type == SPLHND_SERVER) {
4919 :
4920 0 : struct dcerpc_binding_handle *b;
4921 :
4922 72 : if (r->in.level != 3) {
4923 32 : result = WERR_INVALID_LEVEL;
4924 32 : goto err_info_free;
4925 : }
4926 :
4927 40 : result = winreg_printer_binding_handle(p->mem_ctx,
4928 : get_session_info_system(),
4929 : p->msg_ctx,
4930 : &b);
4931 40 : if (!W_ERROR_IS_OK(result)) {
4932 0 : goto err_info_free;
4933 : }
4934 :
4935 40 : result = winreg_get_printserver_secdesc(p->mem_ctx,
4936 : b,
4937 40 : &r->out.info->info3.secdesc);
4938 40 : if (!W_ERROR_IS_OK(result)) {
4939 0 : goto err_info_free;
4940 : }
4941 :
4942 40 : goto done;
4943 : }
4944 :
4945 3440 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4946 0 : result = WERR_INVALID_HANDLE;
4947 0 : goto err_info_free;
4948 : }
4949 :
4950 3440 : result = winreg_get_printer_internal(p->mem_ctx,
4951 : get_session_info_system(),
4952 : p->msg_ctx,
4953 : lp_const_servicename(snum),
4954 : &info2);
4955 3440 : if (!W_ERROR_IS_OK(result)) {
4956 0 : goto err_info_free;
4957 : }
4958 :
4959 3440 : switch (r->in.level) {
4960 236 : case 0:
4961 236 : result = construct_printer_info0(p->mem_ctx,
4962 : get_session_info_system(),
4963 : p->msg_ctx,
4964 : info2,
4965 : Printer->servername,
4966 236 : &r->out.info->info0,
4967 : snum);
4968 236 : break;
4969 88 : case 1:
4970 88 : result = construct_printer_info1(p->mem_ctx, info2,
4971 : PRINTER_ENUM_ICON8,
4972 : Printer->servername,
4973 88 : &r->out.info->info1, snum);
4974 88 : break;
4975 932 : case 2:
4976 932 : result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4977 : Printer->servername,
4978 932 : &r->out.info->info2, snum);
4979 932 : break;
4980 144 : case 3:
4981 144 : result = construct_printer_info3(p->mem_ctx, info2,
4982 : Printer->servername,
4983 144 : &r->out.info->info3, snum);
4984 144 : break;
4985 88 : case 4:
4986 88 : result = construct_printer_info4(p->mem_ctx, info2,
4987 : Printer->servername,
4988 88 : &r->out.info->info4, snum);
4989 88 : break;
4990 88 : case 5:
4991 88 : result = construct_printer_info5(p->mem_ctx, info2,
4992 : Printer->servername,
4993 88 : &r->out.info->info5, snum);
4994 88 : break;
4995 88 : case 6:
4996 88 : result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4997 : Printer->servername,
4998 88 : &r->out.info->info6, snum);
4999 88 : break;
5000 112 : case 7:
5001 112 : result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
5002 : Printer->servername,
5003 112 : &r->out.info->info7, snum);
5004 112 : break;
5005 1664 : case 8:
5006 1664 : result = construct_printer_info8(p->mem_ctx, info2,
5007 : Printer->servername,
5008 1664 : &r->out.info->info8, snum);
5009 1664 : break;
5010 0 : default:
5011 0 : result = WERR_INVALID_LEVEL;
5012 0 : break;
5013 : }
5014 3440 : TALLOC_FREE(info2);
5015 :
5016 3440 : if (!W_ERROR_IS_OK(result)) {
5017 0 : DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
5018 : r->in.level, win_errstr(result)));
5019 0 : goto err_info_free;
5020 : }
5021 3440 : done:
5022 3480 : *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
5023 : r->out.info, r->in.level);
5024 3480 : r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5025 :
5026 3480 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5027 :
5028 32 : err_info_free:
5029 32 : TALLOC_FREE(r->out.info);
5030 32 : return result;
5031 : }
5032 :
5033 : /********************************************************************
5034 : ********************************************************************/
5035 :
5036 : #define FILL_DRIVER_STRING(mem_ctx, in, out) \
5037 : do { \
5038 : if (in && strlen(in)) { \
5039 : out = talloc_strdup(mem_ctx, in); \
5040 : } else { \
5041 : out = talloc_strdup(mem_ctx, ""); \
5042 : } \
5043 : W_ERROR_HAVE_NO_MEMORY(out); \
5044 : } while (0);
5045 :
5046 : #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
5047 : do { \
5048 : if (in && strlen(in)) { \
5049 : out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
5050 : } else { \
5051 : out = talloc_strdup(mem_ctx, ""); \
5052 : } \
5053 : W_ERROR_HAVE_NO_MEMORY(out); \
5054 : } while (0);
5055 :
5056 0 : static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
5057 : const char **string_array,
5058 : const char ***presult,
5059 : const char *cservername,
5060 : const char *arch,
5061 : int version)
5062 : {
5063 0 : size_t i;
5064 0 : size_t num_strings = 0;
5065 0 : const char **array = NULL;
5066 :
5067 0 : if (string_array == NULL) {
5068 0 : return WERR_INVALID_PARAMETER;
5069 : }
5070 :
5071 0 : for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
5072 0 : const char *str = NULL;
5073 :
5074 0 : if (cservername == NULL || arch == NULL) {
5075 0 : FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
5076 : } else {
5077 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
5078 : }
5079 :
5080 0 : if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
5081 0 : TALLOC_FREE(array);
5082 0 : return WERR_NOT_ENOUGH_MEMORY;
5083 : }
5084 : }
5085 :
5086 0 : if (i > 0) {
5087 0 : ADD_TO_ARRAY(mem_ctx, const char *, NULL,
5088 : &array, &num_strings);
5089 : }
5090 :
5091 0 : if (presult != NULL) {
5092 0 : *presult = array;
5093 : } else {
5094 0 : talloc_free(array);
5095 : }
5096 :
5097 0 : return WERR_OK;
5098 : }
5099 :
5100 : /********************************************************************
5101 : * fill a spoolss_DriverInfo1 struct
5102 : ********************************************************************/
5103 :
5104 0 : static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
5105 : struct spoolss_DriverInfo1 *r,
5106 : const struct spoolss_DriverInfo8 *driver,
5107 : const char *servername)
5108 : {
5109 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5110 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5111 :
5112 0 : return WERR_OK;
5113 : }
5114 :
5115 : /********************************************************************
5116 : * fill a spoolss_DriverInfo2 struct
5117 : ********************************************************************/
5118 :
5119 0 : static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
5120 : struct spoolss_DriverInfo2 *r,
5121 : const struct spoolss_DriverInfo8 *driver,
5122 : const char *servername)
5123 :
5124 : {
5125 0 : const char *cservername = canon_servername(servername);
5126 :
5127 0 : r->version = driver->version;
5128 :
5129 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5130 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5131 0 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5132 0 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5133 :
5134 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5135 : driver->architecture,
5136 : driver->version,
5137 : driver->driver_path,
5138 0 : r->driver_path);
5139 :
5140 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5141 : driver->architecture,
5142 : driver->version,
5143 : driver->data_file,
5144 0 : r->data_file);
5145 :
5146 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5147 : driver->architecture,
5148 : driver->version,
5149 : driver->config_file,
5150 0 : r->config_file);
5151 :
5152 0 : return WERR_OK;
5153 : }
5154 :
5155 : /********************************************************************
5156 : * fill a spoolss_DriverInfo3 struct
5157 : ********************************************************************/
5158 :
5159 0 : static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
5160 : struct spoolss_DriverInfo3 *r,
5161 : const struct spoolss_DriverInfo8 *driver,
5162 : const char *servername)
5163 : {
5164 0 : const char *cservername = canon_servername(servername);
5165 :
5166 0 : r->version = driver->version;
5167 :
5168 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5169 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5170 0 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5171 0 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5172 :
5173 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5174 : driver->architecture,
5175 : driver->version,
5176 : driver->driver_path,
5177 0 : r->driver_path);
5178 :
5179 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5180 : driver->architecture,
5181 : driver->version,
5182 : driver->data_file,
5183 0 : r->data_file);
5184 :
5185 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5186 : driver->architecture,
5187 : driver->version,
5188 : driver->config_file,
5189 0 : r->config_file);
5190 :
5191 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5192 : driver->architecture,
5193 : driver->version,
5194 : driver->help_file,
5195 0 : r->help_file);
5196 :
5197 0 : FILL_DRIVER_STRING(mem_ctx,
5198 : driver->monitor_name,
5199 0 : r->monitor_name);
5200 :
5201 0 : FILL_DRIVER_STRING(mem_ctx,
5202 : driver->default_datatype,
5203 0 : r->default_datatype);
5204 :
5205 0 : return string_array_from_driver_info(mem_ctx,
5206 0 : driver->dependent_files,
5207 : &r->dependent_files,
5208 : cservername,
5209 0 : driver->architecture,
5210 0 : driver->version);
5211 : }
5212 :
5213 : /********************************************************************
5214 : * fill a spoolss_DriverInfo4 struct
5215 : ********************************************************************/
5216 :
5217 0 : static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5218 : struct spoolss_DriverInfo4 *r,
5219 : const struct spoolss_DriverInfo8 *driver,
5220 : const char *servername)
5221 : {
5222 0 : const char *cservername = canon_servername(servername);
5223 0 : WERROR result;
5224 :
5225 0 : r->version = driver->version;
5226 :
5227 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5228 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5229 0 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5230 0 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5231 :
5232 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5233 : driver->architecture,
5234 : driver->version,
5235 : driver->driver_path,
5236 0 : r->driver_path);
5237 :
5238 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5239 : driver->architecture,
5240 : driver->version,
5241 : driver->data_file,
5242 0 : r->data_file);
5243 :
5244 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5245 : driver->architecture,
5246 : driver->version,
5247 : driver->config_file,
5248 0 : r->config_file);
5249 :
5250 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5251 : driver->architecture,
5252 : driver->version,
5253 : driver->help_file,
5254 0 : r->help_file);
5255 :
5256 0 : result = string_array_from_driver_info(mem_ctx,
5257 0 : driver->dependent_files,
5258 : &r->dependent_files,
5259 : cservername,
5260 0 : driver->architecture,
5261 0 : driver->version);
5262 0 : if (!W_ERROR_IS_OK(result)) {
5263 0 : return result;
5264 : }
5265 :
5266 0 : FILL_DRIVER_STRING(mem_ctx,
5267 : driver->monitor_name,
5268 0 : r->monitor_name);
5269 :
5270 0 : FILL_DRIVER_STRING(mem_ctx,
5271 : driver->default_datatype,
5272 0 : r->default_datatype);
5273 :
5274 :
5275 0 : result = string_array_from_driver_info(mem_ctx,
5276 0 : driver->previous_names,
5277 : &r->previous_names,
5278 : NULL, NULL, 0);
5279 :
5280 0 : return result;
5281 : }
5282 :
5283 : /********************************************************************
5284 : * fill a spoolss_DriverInfo5 struct
5285 : ********************************************************************/
5286 :
5287 0 : static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5288 : struct spoolss_DriverInfo5 *r,
5289 : const struct spoolss_DriverInfo8 *driver,
5290 : const char *servername)
5291 : {
5292 0 : const char *cservername = canon_servername(servername);
5293 :
5294 0 : r->version = driver->version;
5295 :
5296 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5297 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5298 0 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5299 0 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5300 :
5301 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5302 : driver->architecture,
5303 : driver->version,
5304 : driver->driver_path,
5305 0 : r->driver_path);
5306 :
5307 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5308 : driver->architecture,
5309 : driver->version,
5310 : driver->data_file,
5311 0 : r->data_file);
5312 :
5313 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5314 : driver->architecture,
5315 : driver->version,
5316 : driver->config_file,
5317 0 : r->config_file);
5318 :
5319 0 : r->driver_attributes = 0;
5320 0 : r->config_version = 0;
5321 0 : r->driver_version = 0;
5322 :
5323 0 : return WERR_OK;
5324 : }
5325 : /********************************************************************
5326 : * fill a spoolss_DriverInfo6 struct
5327 : ********************************************************************/
5328 :
5329 0 : static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5330 : struct spoolss_DriverInfo6 *r,
5331 : const struct spoolss_DriverInfo8 *driver,
5332 : const char *servername)
5333 : {
5334 0 : const char *cservername = canon_servername(servername);
5335 0 : WERROR result;
5336 :
5337 0 : r->version = driver->version;
5338 :
5339 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5340 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5341 0 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5342 0 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5343 :
5344 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5345 : driver->architecture,
5346 : driver->version,
5347 : driver->driver_path,
5348 0 : r->driver_path);
5349 :
5350 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5351 : driver->architecture,
5352 : driver->version,
5353 : driver->data_file,
5354 0 : r->data_file);
5355 :
5356 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5357 : driver->architecture,
5358 : driver->version,
5359 : driver->config_file,
5360 0 : r->config_file);
5361 :
5362 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5363 : driver->architecture,
5364 : driver->version,
5365 : driver->help_file,
5366 0 : r->help_file);
5367 :
5368 0 : FILL_DRIVER_STRING(mem_ctx,
5369 : driver->monitor_name,
5370 0 : r->monitor_name);
5371 :
5372 0 : FILL_DRIVER_STRING(mem_ctx,
5373 : driver->default_datatype,
5374 0 : r->default_datatype);
5375 :
5376 0 : result = string_array_from_driver_info(mem_ctx,
5377 0 : driver->dependent_files,
5378 : &r->dependent_files,
5379 : cservername,
5380 0 : driver->architecture,
5381 0 : driver->version);
5382 0 : if (!W_ERROR_IS_OK(result)) {
5383 0 : return result;
5384 : }
5385 :
5386 0 : result = string_array_from_driver_info(mem_ctx,
5387 0 : driver->previous_names,
5388 : &r->previous_names,
5389 : NULL, NULL, 0);
5390 0 : if (!W_ERROR_IS_OK(result)) {
5391 0 : return result;
5392 : }
5393 :
5394 0 : r->driver_date = driver->driver_date;
5395 0 : r->driver_version = driver->driver_version;
5396 :
5397 0 : FILL_DRIVER_STRING(mem_ctx,
5398 : driver->manufacturer_name,
5399 0 : r->manufacturer_name);
5400 0 : FILL_DRIVER_STRING(mem_ctx,
5401 : driver->manufacturer_url,
5402 0 : r->manufacturer_url);
5403 0 : FILL_DRIVER_STRING(mem_ctx,
5404 : driver->hardware_id,
5405 0 : r->hardware_id);
5406 0 : FILL_DRIVER_STRING(mem_ctx,
5407 : driver->provider,
5408 0 : r->provider);
5409 :
5410 0 : return WERR_OK;
5411 : }
5412 :
5413 : /********************************************************************
5414 : * fill a spoolss_DriverInfo8 struct
5415 : ********************************************************************/
5416 :
5417 0 : static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5418 : struct spoolss_DriverInfo8 *r,
5419 : const struct spoolss_DriverInfo8 *driver,
5420 : const char *servername)
5421 : {
5422 0 : const char *cservername = canon_servername(servername);
5423 0 : WERROR result;
5424 :
5425 0 : r->version = driver->version;
5426 :
5427 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5428 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5429 0 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5430 0 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5431 :
5432 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5433 : driver->architecture,
5434 : driver->version,
5435 : driver->driver_path,
5436 0 : r->driver_path);
5437 :
5438 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5439 : driver->architecture,
5440 : driver->version,
5441 : driver->data_file,
5442 0 : r->data_file);
5443 :
5444 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5445 : driver->architecture,
5446 : driver->version,
5447 : driver->config_file,
5448 0 : r->config_file);
5449 :
5450 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5451 : driver->architecture,
5452 : driver->version,
5453 : driver->help_file,
5454 0 : r->help_file);
5455 :
5456 0 : FILL_DRIVER_STRING(mem_ctx,
5457 : driver->monitor_name,
5458 0 : r->monitor_name);
5459 :
5460 0 : FILL_DRIVER_STRING(mem_ctx,
5461 : driver->default_datatype,
5462 0 : r->default_datatype);
5463 :
5464 0 : result = string_array_from_driver_info(mem_ctx,
5465 0 : driver->dependent_files,
5466 : &r->dependent_files,
5467 : cservername,
5468 0 : driver->architecture,
5469 0 : driver->version);
5470 0 : if (!W_ERROR_IS_OK(result)) {
5471 0 : return result;
5472 : }
5473 :
5474 0 : result = string_array_from_driver_info(mem_ctx,
5475 0 : driver->previous_names,
5476 : &r->previous_names,
5477 : NULL, NULL, 0);
5478 0 : if (!W_ERROR_IS_OK(result)) {
5479 0 : return result;
5480 : }
5481 :
5482 0 : r->driver_date = driver->driver_date;
5483 0 : r->driver_version = driver->driver_version;
5484 :
5485 0 : FILL_DRIVER_STRING(mem_ctx,
5486 : driver->manufacturer_name,
5487 0 : r->manufacturer_name);
5488 0 : FILL_DRIVER_STRING(mem_ctx,
5489 : driver->manufacturer_url,
5490 0 : r->manufacturer_url);
5491 0 : FILL_DRIVER_STRING(mem_ctx,
5492 : driver->hardware_id,
5493 0 : r->hardware_id);
5494 0 : FILL_DRIVER_STRING(mem_ctx,
5495 : driver->provider,
5496 0 : r->provider);
5497 :
5498 0 : FILL_DRIVER_STRING(mem_ctx,
5499 : driver->print_processor,
5500 0 : r->print_processor);
5501 0 : FILL_DRIVER_STRING(mem_ctx,
5502 : driver->vendor_setup,
5503 0 : r->vendor_setup);
5504 :
5505 0 : result = string_array_from_driver_info(mem_ctx,
5506 0 : driver->color_profiles,
5507 : &r->color_profiles,
5508 : NULL, NULL, 0);
5509 0 : if (!W_ERROR_IS_OK(result)) {
5510 0 : return result;
5511 : }
5512 :
5513 0 : FILL_DRIVER_STRING(mem_ctx,
5514 : driver->inf_path,
5515 0 : r->inf_path);
5516 :
5517 0 : r->printer_driver_attributes = driver->printer_driver_attributes;
5518 :
5519 0 : result = string_array_from_driver_info(mem_ctx,
5520 0 : driver->core_driver_dependencies,
5521 : &r->core_driver_dependencies,
5522 : NULL, NULL, 0);
5523 0 : if (!W_ERROR_IS_OK(result)) {
5524 0 : return result;
5525 : }
5526 :
5527 0 : r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5528 0 : r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5529 :
5530 0 : return WERR_OK;
5531 : }
5532 :
5533 : #if 0 /* disabled until marshalling issues are resolved - gd */
5534 : /********************************************************************
5535 : ********************************************************************/
5536 :
5537 : static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5538 : struct spoolss_DriverFileInfo *r,
5539 : const char *cservername,
5540 : const char *file_name,
5541 : enum spoolss_DriverFileType file_type,
5542 : uint32_t file_version)
5543 : {
5544 : r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5545 : cservername, file_name);
5546 : W_ERROR_HAVE_NO_MEMORY(r->file_name);
5547 : r->file_type = file_type;
5548 : r->file_version = file_version;
5549 :
5550 : return WERR_OK;
5551 : }
5552 :
5553 : /********************************************************************
5554 : ********************************************************************/
5555 :
5556 : static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5557 : const struct spoolss_DriverInfo8 *driver,
5558 : const char *cservername,
5559 : struct spoolss_DriverFileInfo **info_p,
5560 : uint32_t *count_p)
5561 : {
5562 : struct spoolss_DriverFileInfo *info = NULL;
5563 : uint32_t count = 0;
5564 : WERROR result;
5565 : uint32_t i;
5566 :
5567 : *info_p = NULL;
5568 : *count_p = 0;
5569 :
5570 : if (strlen(driver->driver_path)) {
5571 : info = talloc_realloc(mem_ctx, info,
5572 : struct spoolss_DriverFileInfo,
5573 : count + 1);
5574 : W_ERROR_HAVE_NO_MEMORY(info);
5575 : result = fill_spoolss_DriverFileInfo(info,
5576 : &info[count],
5577 : cservername,
5578 : driver->driver_path,
5579 : SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5580 : 0);
5581 : W_ERROR_NOT_OK_RETURN(result);
5582 : count++;
5583 : }
5584 :
5585 : if (strlen(driver->config_file)) {
5586 : info = talloc_realloc(mem_ctx, info,
5587 : struct spoolss_DriverFileInfo,
5588 : count + 1);
5589 : W_ERROR_HAVE_NO_MEMORY(info);
5590 : result = fill_spoolss_DriverFileInfo(info,
5591 : &info[count],
5592 : cservername,
5593 : driver->config_file,
5594 : SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5595 : 0);
5596 : W_ERROR_NOT_OK_RETURN(result);
5597 : count++;
5598 : }
5599 :
5600 : if (strlen(driver->data_file)) {
5601 : info = talloc_realloc(mem_ctx, info,
5602 : struct spoolss_DriverFileInfo,
5603 : count + 1);
5604 : W_ERROR_HAVE_NO_MEMORY(info);
5605 : result = fill_spoolss_DriverFileInfo(info,
5606 : &info[count],
5607 : cservername,
5608 : driver->data_file,
5609 : SPOOLSS_DRIVER_FILE_TYPE_DATA,
5610 : 0);
5611 : W_ERROR_NOT_OK_RETURN(result);
5612 : count++;
5613 : }
5614 :
5615 : if (strlen(driver->help_file)) {
5616 : info = talloc_realloc(mem_ctx, info,
5617 : struct spoolss_DriverFileInfo,
5618 : count + 1);
5619 : W_ERROR_HAVE_NO_MEMORY(info);
5620 : result = fill_spoolss_DriverFileInfo(info,
5621 : &info[count],
5622 : cservername,
5623 : driver->help_file,
5624 : SPOOLSS_DRIVER_FILE_TYPE_HELP,
5625 : 0);
5626 : W_ERROR_NOT_OK_RETURN(result);
5627 : count++;
5628 : }
5629 :
5630 : for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5631 : info = talloc_realloc(mem_ctx, info,
5632 : struct spoolss_DriverFileInfo,
5633 : count + 1);
5634 : W_ERROR_HAVE_NO_MEMORY(info);
5635 : result = fill_spoolss_DriverFileInfo(info,
5636 : &info[count],
5637 : cservername,
5638 : driver->dependent_files[i],
5639 : SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5640 : 0);
5641 : W_ERROR_NOT_OK_RETURN(result);
5642 : count++;
5643 : }
5644 :
5645 : *info_p = info;
5646 : *count_p = count;
5647 :
5648 : return WERR_OK;
5649 : }
5650 :
5651 : /********************************************************************
5652 : * fill a spoolss_DriverInfo101 struct
5653 : ********************************************************************/
5654 :
5655 : static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5656 : struct spoolss_DriverInfo101 *r,
5657 : const struct spoolss_DriverInfo8 *driver,
5658 : const char *servername)
5659 : {
5660 : const char *cservername = canon_servername(servername);
5661 : WERROR result;
5662 :
5663 : r->version = driver->version;
5664 :
5665 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5666 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5667 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5668 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5669 :
5670 : result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5671 : cservername,
5672 : &r->file_info,
5673 : &r->file_count);
5674 : if (!W_ERROR_IS_OK(result)) {
5675 : return result;
5676 : }
5677 :
5678 : FILL_DRIVER_STRING(mem_ctx,
5679 : driver->monitor_name,
5680 : r->monitor_name);
5681 :
5682 : FILL_DRIVER_STRING(mem_ctx,
5683 : driver->default_datatype,
5684 : r->default_datatype);
5685 :
5686 : result = string_array_from_driver_info(mem_ctx,
5687 : driver->previous_names,
5688 : &r->previous_names,
5689 : NULL, NULL, 0);
5690 : if (!W_ERROR_IS_OK(result)) {
5691 : return result;
5692 : }
5693 :
5694 : r->driver_date = driver->driver_date;
5695 : r->driver_version = driver->driver_version;
5696 :
5697 : FILL_DRIVER_STRING(mem_ctx,
5698 : driver->manufacturer_name,
5699 : r->manufacturer_name);
5700 : FILL_DRIVER_STRING(mem_ctx,
5701 : driver->manufacturer_url,
5702 : r->manufacturer_url);
5703 : FILL_DRIVER_STRING(mem_ctx,
5704 : driver->hardware_id,
5705 : r->hardware_id);
5706 : FILL_DRIVER_STRING(mem_ctx,
5707 : driver->provider,
5708 : r->provider);
5709 :
5710 : return WERR_OK;
5711 : }
5712 : #endif
5713 : /********************************************************************
5714 : ********************************************************************/
5715 :
5716 4 : static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5717 : const struct auth_session_info *session_info,
5718 : struct messaging_context *msg_ctx,
5719 : uint32_t level,
5720 : union spoolss_DriverInfo *r,
5721 : int snum,
5722 : const char *servername,
5723 : const char *architecture,
5724 : uint32_t version)
5725 : {
5726 4 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5727 0 : struct spoolss_DriverInfo8 *driver;
5728 0 : WERROR result;
5729 0 : struct dcerpc_binding_handle *b;
5730 4 : TALLOC_CTX *tmp_ctx = NULL;
5731 :
5732 4 : if (level == 101) {
5733 4 : return WERR_INVALID_LEVEL;
5734 : }
5735 :
5736 0 : tmp_ctx = talloc_new(mem_ctx);
5737 0 : if (!tmp_ctx) {
5738 0 : return WERR_NOT_ENOUGH_MEMORY;
5739 : }
5740 :
5741 0 : result = winreg_printer_binding_handle(tmp_ctx,
5742 : session_info,
5743 : msg_ctx,
5744 : &b);
5745 0 : if (!W_ERROR_IS_OK(result)) {
5746 0 : goto done;
5747 : }
5748 :
5749 0 : result = winreg_get_printer(tmp_ctx, b,
5750 : lp_const_servicename(snum),
5751 : &pinfo2);
5752 0 : if (!W_ERROR_IS_OK(result)) {
5753 0 : DBG_ERR("Failed to get printer info2 for [%s]: %s\n",
5754 : lp_const_servicename(snum), win_errstr(result));
5755 0 : result = WERR_INVALID_PRINTER_NAME;
5756 0 : goto done;
5757 : }
5758 :
5759 0 : if (pinfo2->drivername == NULL || pinfo2->drivername[0] == '\0') {
5760 0 : result = WERR_UNKNOWN_PRINTER_DRIVER;
5761 0 : goto done;
5762 : }
5763 :
5764 0 : DBG_INFO("Construct printer driver [%s] for [%s]\n",
5765 : pinfo2->drivername,
5766 : pinfo2->sharename);
5767 :
5768 0 : result = winreg_get_driver(tmp_ctx, b,
5769 : architecture,
5770 0 : pinfo2->drivername, version, &driver);
5771 :
5772 0 : DBG_INFO("winreg_get_driver() status: %s\n",
5773 : win_errstr(result));
5774 :
5775 0 : if (!W_ERROR_IS_OK(result)) {
5776 : /*
5777 : * Is this a W2k client ?
5778 : */
5779 :
5780 0 : if (version < 3) {
5781 0 : result = WERR_UNKNOWN_PRINTER_DRIVER;
5782 0 : goto done;
5783 : }
5784 :
5785 : /* Yes - try again with a WinNT driver. */
5786 0 : version = 2;
5787 0 : result = winreg_get_driver(tmp_ctx, b,
5788 : architecture,
5789 0 : pinfo2->drivername,
5790 : version, &driver);
5791 0 : DEBUG(8,("construct_printer_driver_level: status: %s\n",
5792 : win_errstr(result)));
5793 0 : if (!W_ERROR_IS_OK(result)) {
5794 0 : result = WERR_UNKNOWN_PRINTER_DRIVER;
5795 0 : goto done;
5796 : }
5797 : }
5798 :
5799 : /* these are allocated on mem_ctx and not tmp_ctx because they are
5800 : * the 'return value' and need to outlive this call */
5801 0 : switch (level) {
5802 0 : case 1:
5803 0 : result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5804 0 : break;
5805 0 : case 2:
5806 0 : result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5807 0 : break;
5808 0 : case 3:
5809 0 : result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5810 0 : break;
5811 0 : case 4:
5812 0 : result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5813 0 : break;
5814 0 : case 5:
5815 0 : result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5816 0 : break;
5817 0 : case 6:
5818 0 : result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5819 0 : break;
5820 0 : case 8:
5821 0 : result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5822 0 : break;
5823 : #if 0 /* disabled until marshalling issues are resolved - gd */
5824 : case 101:
5825 : result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5826 : break;
5827 : #endif
5828 0 : default:
5829 0 : result = WERR_INVALID_LEVEL;
5830 0 : break;
5831 : }
5832 :
5833 0 : done:
5834 0 : talloc_free(tmp_ctx);
5835 0 : return result;
5836 : }
5837 :
5838 : /****************************************************************
5839 : _spoolss_GetPrinterDriver2
5840 : ****************************************************************/
5841 :
5842 4 : WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5843 : struct spoolss_GetPrinterDriver2 *r)
5844 : {
5845 0 : struct printer_handle *printer;
5846 0 : WERROR result;
5847 4 : uint32_t version = r->in.client_major_version;
5848 :
5849 0 : int snum;
5850 :
5851 : /* that's an [in out] buffer */
5852 :
5853 4 : if (!r->in.buffer && (r->in.offered != 0)) {
5854 0 : result = WERR_INVALID_PARAMETER;
5855 0 : goto err_info_free;
5856 : }
5857 :
5858 4 : DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5859 :
5860 4 : if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5861 0 : DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5862 0 : result = WERR_INVALID_PRINTER_NAME;
5863 0 : goto err_info_free;
5864 : }
5865 :
5866 4 : *r->out.needed = 0;
5867 4 : *r->out.server_major_version = 0;
5868 4 : *r->out.server_minor_version = 0;
5869 :
5870 4 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5871 0 : result = WERR_INVALID_HANDLE;
5872 0 : goto err_info_free;
5873 : }
5874 :
5875 4 : if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
5876 0 : DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
5877 : "downgrading to v3\n"));
5878 0 : version = SPOOLSS_DRIVER_VERSION_200X;
5879 : }
5880 :
5881 4 : result = construct_printer_driver_info_level(p->mem_ctx,
5882 : get_session_info_system(),
5883 : p->msg_ctx,
5884 : r->in.level, r->out.info,
5885 : snum, printer->servername,
5886 : r->in.architecture,
5887 : version);
5888 4 : if (!W_ERROR_IS_OK(result)) {
5889 4 : goto err_info_free;
5890 : }
5891 :
5892 0 : *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5893 : r->out.info, r->in.level);
5894 0 : r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5895 :
5896 0 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5897 :
5898 4 : err_info_free:
5899 4 : TALLOC_FREE(r->out.info);
5900 4 : return result;
5901 : }
5902 :
5903 :
5904 : /****************************************************************
5905 : _spoolss_StartPagePrinter
5906 : ****************************************************************/
5907 :
5908 1920 : WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5909 : struct spoolss_StartPagePrinter *r)
5910 : {
5911 1920 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5912 :
5913 1920 : if (!Printer) {
5914 0 : DEBUG(3,("_spoolss_StartPagePrinter: "
5915 : "Error in startpageprinter printer handle\n"));
5916 0 : return WERR_INVALID_HANDLE;
5917 : }
5918 :
5919 1920 : Printer->page_started = true;
5920 1920 : return WERR_OK;
5921 : }
5922 :
5923 : /****************************************************************
5924 : _spoolss_EndPagePrinter
5925 : ****************************************************************/
5926 :
5927 1920 : WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5928 : struct spoolss_EndPagePrinter *r)
5929 : {
5930 0 : int snum;
5931 :
5932 1920 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5933 :
5934 1920 : if (!Printer) {
5935 0 : DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5936 : OUR_HANDLE(r->in.handle)));
5937 0 : return WERR_INVALID_HANDLE;
5938 : }
5939 :
5940 1920 : if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5941 0 : return WERR_INVALID_HANDLE;
5942 :
5943 1920 : Printer->page_started = false;
5944 1920 : print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5945 :
5946 1920 : return WERR_OK;
5947 : }
5948 :
5949 : /****************************************************************
5950 : _spoolss_StartDocPrinter
5951 : ****************************************************************/
5952 :
5953 668 : WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5954 : struct spoolss_StartDocPrinter *r)
5955 : {
5956 668 : struct dcesrv_call_state *dce_call = p->dce_call;
5957 668 : struct dcesrv_connection *dcesrv_conn = dce_call->conn;
5958 0 : const struct tsocket_address *remote_address =
5959 668 : dcesrv_connection_get_remote_address(dcesrv_conn);
5960 0 : struct auth_session_info *session_info =
5961 668 : dcesrv_call_session_info(dce_call);
5962 0 : struct spoolss_DocumentInfo1 *info_1;
5963 0 : int snum;
5964 668 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5965 0 : WERROR werr;
5966 0 : char *rhost;
5967 0 : int rc;
5968 :
5969 668 : if (!Printer) {
5970 0 : DEBUG(2,("_spoolss_StartDocPrinter: "
5971 : "Invalid handle (%s:%u:%u)\n",
5972 : OUR_HANDLE(r->in.handle)));
5973 0 : return WERR_INVALID_HANDLE;
5974 : }
5975 :
5976 668 : if (Printer->jobid) {
5977 0 : DEBUG(2, ("_spoolss_StartDocPrinter: "
5978 : "StartDocPrinter called twice! "
5979 : "(existing jobid = %d)\n", Printer->jobid));
5980 0 : return WERR_INVALID_HANDLE;
5981 : }
5982 :
5983 668 : if (r->in.info_ctr->level != 1) {
5984 0 : return WERR_INVALID_LEVEL;
5985 : }
5986 :
5987 668 : info_1 = r->in.info_ctr->info.info1;
5988 :
5989 : /*
5990 : * a nice thing with NT is it doesn't listen to what you tell it.
5991 : * when asked to send _only_ RAW data, it tries to send data
5992 : * in EMF format.
5993 : *
5994 : * So I add checks like in NT Server ...
5995 : */
5996 :
5997 668 : if (info_1->datatype) {
5998 : /*
5999 : * The v4 driver model used in Windows 8 declares print jobs
6000 : * intended to bypass the XPS processing layer by setting
6001 : * datatype to "XPS_PASS" instead of "RAW".
6002 : */
6003 668 : if ((strcmp(info_1->datatype, "RAW") != 0)
6004 224 : && (strcmp(info_1->datatype, "XPS_PASS") != 0)) {
6005 0 : *r->out.job_id = 0;
6006 0 : return WERR_INVALID_DATATYPE;
6007 : }
6008 : }
6009 :
6010 : /* get the share number of the printer */
6011 668 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6012 0 : return WERR_INVALID_HANDLE;
6013 : }
6014 :
6015 668 : rc = get_remote_hostname(remote_address,
6016 : &rhost,
6017 : p->mem_ctx);
6018 668 : if (rc < 0) {
6019 0 : return WERR_NOT_ENOUGH_MEMORY;
6020 : }
6021 668 : if (strequal(rhost,"UNKNOWN")) {
6022 668 : rhost = tsocket_address_inet_addr_string(remote_address,
6023 : p->mem_ctx);
6024 668 : if (rhost == NULL) {
6025 0 : return WERR_NOT_ENOUGH_MEMORY;
6026 : }
6027 : }
6028 :
6029 668 : werr = print_job_start(session_info,
6030 : p->msg_ctx,
6031 : rhost,
6032 : snum,
6033 : info_1->document_name,
6034 : info_1->output_file,
6035 : Printer->devmode,
6036 : &Printer->jobid);
6037 :
6038 : /* An error occurred in print_job_start() so return an appropriate
6039 : NT error code. */
6040 :
6041 668 : if (!W_ERROR_IS_OK(werr)) {
6042 0 : return werr;
6043 : }
6044 :
6045 668 : Printer->document_started = true;
6046 668 : *r->out.job_id = Printer->jobid;
6047 :
6048 668 : return WERR_OK;
6049 : }
6050 :
6051 : /****************************************************************
6052 : _spoolss_EndDocPrinter
6053 : ****************************************************************/
6054 :
6055 668 : WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
6056 : struct spoolss_EndDocPrinter *r)
6057 : {
6058 668 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6059 0 : NTSTATUS status;
6060 0 : int snum;
6061 :
6062 668 : if (!Printer) {
6063 0 : DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
6064 : OUR_HANDLE(r->in.handle)));
6065 0 : return WERR_INVALID_HANDLE;
6066 : }
6067 :
6068 668 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6069 0 : return WERR_INVALID_HANDLE;
6070 : }
6071 :
6072 668 : Printer->document_started = false;
6073 668 : status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
6074 668 : if (!NT_STATUS_IS_OK(status)) {
6075 292 : DEBUG(2, ("_spoolss_EndDocPrinter: "
6076 : "print_job_end failed [%s]\n",
6077 : nt_errstr(status)));
6078 : }
6079 :
6080 668 : Printer->jobid = 0;
6081 668 : return ntstatus_to_werror(status);
6082 : }
6083 :
6084 : /****************************************************************
6085 : _spoolss_WritePrinter
6086 : ****************************************************************/
6087 :
6088 1920 : WERROR _spoolss_WritePrinter(struct pipes_struct *p,
6089 : struct spoolss_WritePrinter *r)
6090 : {
6091 0 : ssize_t buffer_written;
6092 0 : int snum;
6093 1920 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6094 :
6095 1920 : if (!Printer) {
6096 0 : DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
6097 : OUR_HANDLE(r->in.handle)));
6098 0 : *r->out.num_written = r->in._data_size;
6099 0 : return WERR_INVALID_HANDLE;
6100 : }
6101 :
6102 1920 : if (!get_printer_snum(p, r->in.handle, &snum, NULL))
6103 0 : return WERR_INVALID_HANDLE;
6104 :
6105 : /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
6106 1920 : buffer_written = print_job_write(global_event_context(),p->msg_ctx,
6107 : snum, Printer->jobid,
6108 1920 : (const char *)r->in.data.data,
6109 1920 : (size_t)r->in._data_size);
6110 1920 : if (buffer_written == (ssize_t)-1) {
6111 0 : *r->out.num_written = 0;
6112 0 : if (errno == ENOSPC)
6113 0 : return WERR_NO_SPOOL_SPACE;
6114 : else
6115 0 : return WERR_ACCESS_DENIED;
6116 : }
6117 :
6118 1920 : *r->out.num_written = r->in._data_size;
6119 :
6120 1920 : return WERR_OK;
6121 : }
6122 :
6123 : /********************************************************************
6124 : * api_spoolss_getprinter
6125 : * called from the spoolss dispatcher
6126 : *
6127 : ********************************************************************/
6128 :
6129 104 : static WERROR control_printer(struct policy_handle *handle, uint32_t command,
6130 : struct pipes_struct *p)
6131 : {
6132 104 : struct dcesrv_call_state *dce_call = p->dce_call;
6133 0 : struct auth_session_info *session_info =
6134 104 : dcesrv_call_session_info(dce_call);
6135 0 : int snum;
6136 104 : WERROR errcode = WERR_INVALID_FUNCTION;
6137 104 : struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6138 :
6139 104 : if (!Printer) {
6140 0 : DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
6141 : OUR_HANDLE(handle)));
6142 0 : return WERR_INVALID_HANDLE;
6143 : }
6144 :
6145 104 : if (!get_printer_snum(p, handle, &snum, NULL))
6146 0 : return WERR_INVALID_HANDLE;
6147 :
6148 104 : switch (command) {
6149 52 : case SPOOLSS_PRINTER_CONTROL_PAUSE:
6150 52 : errcode = print_queue_pause(session_info, p->msg_ctx, snum);
6151 52 : break;
6152 40 : case SPOOLSS_PRINTER_CONTROL_RESUME:
6153 : case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
6154 40 : errcode = print_queue_resume(session_info, p->msg_ctx, snum);
6155 40 : break;
6156 12 : case SPOOLSS_PRINTER_CONTROL_PURGE:
6157 12 : errcode = print_queue_purge(session_info, p->msg_ctx, snum);
6158 12 : break;
6159 0 : default:
6160 0 : return WERR_INVALID_LEVEL;
6161 : }
6162 :
6163 104 : return errcode;
6164 : }
6165 :
6166 :
6167 : /****************************************************************
6168 : _spoolss_AbortPrinter
6169 : * From MSDN: "Deletes printer's spool file if printer is configured
6170 : * for spooling"
6171 : ****************************************************************/
6172 :
6173 0 : WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
6174 : struct spoolss_AbortPrinter *r)
6175 : {
6176 0 : struct dcesrv_call_state *dce_call = p->dce_call;
6177 0 : struct auth_session_info *session_info =
6178 0 : dcesrv_call_session_info(dce_call);
6179 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6180 0 : int snum;
6181 0 : WERROR errcode = WERR_OK;
6182 :
6183 0 : if (!Printer) {
6184 0 : DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
6185 : OUR_HANDLE(r->in.handle)));
6186 0 : return WERR_INVALID_HANDLE;
6187 : }
6188 :
6189 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL))
6190 0 : return WERR_INVALID_HANDLE;
6191 :
6192 0 : if (!Printer->document_started) {
6193 0 : return WERR_SPL_NO_STARTDOC;
6194 : }
6195 :
6196 0 : errcode = print_job_delete(session_info,
6197 : p->msg_ctx,
6198 : snum,
6199 : Printer->jobid);
6200 :
6201 0 : return errcode;
6202 : }
6203 :
6204 : /********************************************************************
6205 : * called by spoolss_api_setprinter
6206 : * when updating a printer description
6207 : ********************************************************************/
6208 :
6209 120 : static WERROR update_printer_sec(struct policy_handle *handle,
6210 : struct pipes_struct *p,
6211 : struct sec_desc_buf *secdesc_ctr)
6212 : {
6213 120 : struct spoolss_security_descriptor *new_secdesc = NULL;
6214 120 : struct spoolss_security_descriptor *old_secdesc = NULL;
6215 120 : const char *printer = NULL;
6216 0 : WERROR result;
6217 120 : int snum = -1;
6218 120 : struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6219 0 : struct dcerpc_binding_handle *b;
6220 120 : TALLOC_CTX *tmp_ctx = NULL;
6221 120 : bool ok = false;
6222 :
6223 120 : if (!Printer) {
6224 0 : DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6225 : OUR_HANDLE(handle)));
6226 :
6227 0 : result = WERR_INVALID_HANDLE;
6228 0 : goto done;
6229 : }
6230 :
6231 120 : if (secdesc_ctr == NULL) {
6232 0 : DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6233 0 : result = WERR_INVALID_PARAMETER;
6234 0 : goto done;
6235 : }
6236 :
6237 120 : switch (Printer->printer_type) {
6238 8 : case SPLHND_SERVER:
6239 8 : break;
6240 112 : case SPLHND_PRINTER:
6241 112 : if (!get_printer_snum(p, handle, &snum, NULL)) {
6242 0 : DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6243 : OUR_HANDLE(handle)));
6244 0 : result = WERR_INVALID_HANDLE;
6245 0 : goto done;
6246 : }
6247 112 : printer = lp_const_servicename(snum);
6248 112 : break;
6249 0 : default:
6250 0 : break;
6251 : }
6252 :
6253 : /* Check the user has permissions to change the security
6254 : descriptor. By experimentation with two NT machines, the user
6255 : requires Full Access to the printer to change security
6256 : information. */
6257 :
6258 120 : switch (Printer->printer_type) {
6259 8 : case SPLHND_SERVER:
6260 8 : ok = Printer->access_granted == SERVER_ACCESS_ADMINISTER;
6261 8 : break;
6262 112 : case SPLHND_PRINTER:
6263 112 : ok = Printer->access_granted == PRINTER_ACCESS_ADMINISTER;
6264 112 : break;
6265 0 : default:
6266 0 : break;
6267 : }
6268 :
6269 120 : if (!ok) {
6270 0 : DEBUG(4,("update_printer_sec: updated denied by printer permissions "
6271 : "(access_granted: 0x%08x)\n", Printer->access_granted));
6272 0 : result = WERR_ACCESS_DENIED;
6273 0 : goto done;
6274 : }
6275 :
6276 120 : tmp_ctx = talloc_new(p->mem_ctx);
6277 120 : if (!tmp_ctx) {
6278 0 : return WERR_NOT_ENOUGH_MEMORY;
6279 : }
6280 :
6281 120 : result = winreg_printer_binding_handle(tmp_ctx,
6282 : get_session_info_system(),
6283 : p->msg_ctx,
6284 : &b);
6285 120 : if (!W_ERROR_IS_OK(result)) {
6286 0 : goto done;
6287 : }
6288 :
6289 : /* NT seems to like setting the security descriptor even though
6290 : nothing may have actually changed. */
6291 :
6292 120 : if (printer != NULL) {
6293 112 : result = winreg_get_printer_secdesc(tmp_ctx, b,
6294 : printer,
6295 : &old_secdesc);
6296 : } else {
6297 8 : result = winreg_get_printserver_secdesc(tmp_ctx, b,
6298 : &old_secdesc);
6299 : }
6300 120 : if (!W_ERROR_IS_OK(result)) {
6301 0 : DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6302 0 : result = WERR_INVALID_HANDLE;
6303 0 : goto done;
6304 : }
6305 :
6306 120 : if (DEBUGLEVEL >= 10) {
6307 0 : struct dom_sid_buf buf;
6308 0 : struct security_acl *the_acl;
6309 0 : int i;
6310 :
6311 0 : the_acl = old_secdesc->dacl;
6312 0 : DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6313 : printer, the_acl->num_aces));
6314 :
6315 0 : for (i = 0; i < the_acl->num_aces; i++) {
6316 0 : DEBUG(10, ("%s 0x%08x\n",
6317 : dom_sid_str_buf(
6318 : &the_acl->aces[i].trustee,
6319 : &buf),
6320 : the_acl->aces[i].access_mask));
6321 : }
6322 :
6323 0 : the_acl = secdesc_ctr->sd->dacl;
6324 :
6325 0 : if (the_acl) {
6326 0 : DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6327 : printer, the_acl->num_aces));
6328 :
6329 0 : for (i = 0; i < the_acl->num_aces; i++) {
6330 0 : DEBUG(10, ("%s 0x%08x\n",
6331 : dom_sid_str_buf(
6332 : &the_acl->aces[i].trustee,
6333 : &buf),
6334 : the_acl->aces[i].access_mask));
6335 : }
6336 : } else {
6337 0 : DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6338 : }
6339 : }
6340 :
6341 120 : new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6342 120 : if (new_secdesc == NULL) {
6343 0 : result = WERR_NOT_ENOUGH_MEMORY;
6344 0 : goto done;
6345 : }
6346 :
6347 120 : if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6348 56 : result = WERR_OK;
6349 56 : goto done;
6350 : }
6351 :
6352 64 : if (printer != NULL) {
6353 56 : result = winreg_set_printer_secdesc(tmp_ctx, b,
6354 : printer,
6355 : new_secdesc);
6356 : } else {
6357 8 : result = winreg_set_printserver_secdesc(tmp_ctx, b,
6358 : new_secdesc);
6359 : }
6360 :
6361 120 : done:
6362 120 : talloc_free(tmp_ctx);
6363 120 : return result;
6364 : }
6365 :
6366 : /********************************************************************
6367 : Canonicalize printer info from a client
6368 : ********************************************************************/
6369 :
6370 100 : static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6371 : struct spoolss_SetPrinterInfo2 *info2,
6372 : int snum)
6373 : {
6374 0 : fstring printername;
6375 0 : const char *p;
6376 :
6377 100 : DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6378 : "portname=%s drivername=%s comment=%s location=%s\n",
6379 : info2->servername, info2->printername, info2->sharename,
6380 : info2->portname, info2->drivername, info2->comment,
6381 : info2->location));
6382 :
6383 : /* we force some elements to "correct" values */
6384 100 : info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6385 100 : if (info2->servername == NULL) {
6386 0 : return false;
6387 : }
6388 100 : info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6389 100 : if (info2->sharename == NULL) {
6390 0 : return false;
6391 : }
6392 :
6393 : /* check to see if we allow printername != sharename */
6394 100 : if (lp_force_printername(snum)) {
6395 0 : info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6396 : lp_netbios_name(), info2->sharename);
6397 : } else {
6398 : /* make sure printername is in \\server\printername format */
6399 100 : fstrcpy(printername, info2->printername);
6400 100 : p = printername;
6401 100 : if ( printername[0] == '\\' && printername[1] == '\\' ) {
6402 56 : if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6403 56 : p++;
6404 : }
6405 :
6406 100 : info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6407 : lp_netbios_name(), p);
6408 : }
6409 100 : if (info2->printername == NULL) {
6410 0 : return false;
6411 : }
6412 :
6413 100 : info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6414 100 : info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6415 :
6416 100 : return true;
6417 : }
6418 :
6419 : /****************************************************************************
6420 : ****************************************************************************/
6421 :
6422 0 : static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6423 : {
6424 0 : const struct loadparm_substitution *lp_sub =
6425 0 : loadparm_s3_global_substitution();
6426 0 : char *cmd = lp_addport_command(talloc_tos(), lp_sub);
6427 0 : char *command = NULL;
6428 0 : int ret;
6429 0 : bool is_print_op = false;
6430 :
6431 0 : if ( !*cmd ) {
6432 0 : return WERR_ACCESS_DENIED;
6433 : }
6434 :
6435 0 : command = talloc_asprintf(ctx,
6436 : "%s \"%s\" \"%s\"", cmd, portname, uri );
6437 0 : if (!command) {
6438 0 : return WERR_NOT_ENOUGH_MEMORY;
6439 : }
6440 :
6441 0 : if ( token )
6442 0 : is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6443 :
6444 0 : DEBUG(10,("Running [%s]\n", command));
6445 :
6446 : /********* BEGIN SePrintOperatorPrivilege **********/
6447 :
6448 0 : if ( is_print_op )
6449 0 : become_root();
6450 :
6451 0 : ret = smbrun(command, NULL, NULL);
6452 :
6453 0 : if ( is_print_op )
6454 0 : unbecome_root();
6455 :
6456 : /********* END SePrintOperatorPrivilege **********/
6457 :
6458 0 : DEBUGADD(10,("returned [%d]\n", ret));
6459 :
6460 0 : TALLOC_FREE(command);
6461 :
6462 0 : if ( ret != 0 ) {
6463 0 : return WERR_ACCESS_DENIED;
6464 : }
6465 :
6466 0 : return WERR_OK;
6467 : }
6468 :
6469 : /****************************************************************************
6470 : ****************************************************************************/
6471 :
6472 4902 : static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6473 : int snum)
6474 : {
6475 : /*
6476 : * As we do not know if we are embedded in the file server process
6477 : * or not, we have to pretend that all shares are in use.
6478 : */
6479 4902 : return true;
6480 : }
6481 :
6482 66 : static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6483 : struct spoolss_SetPrinterInfo2 *info2,
6484 : const char *remote_machine,
6485 : struct messaging_context *msg_ctx)
6486 : {
6487 0 : const struct loadparm_substitution *lp_sub =
6488 66 : loadparm_s3_global_substitution();
6489 66 : char *cmd = lp_addprinter_command(talloc_tos(), lp_sub);
6490 0 : char **qlines;
6491 66 : char *command = NULL;
6492 0 : int numlines;
6493 0 : int ret;
6494 0 : int fd;
6495 66 : bool is_print_op = false;
6496 :
6497 66 : if (!remote_machine) {
6498 0 : return false;
6499 : }
6500 :
6501 66 : command = talloc_asprintf(ctx,
6502 : "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6503 : cmd, info2->printername, info2->sharename,
6504 : info2->portname, info2->drivername,
6505 : info2->location, info2->comment, remote_machine);
6506 66 : if (!command) {
6507 0 : return false;
6508 : }
6509 :
6510 66 : if ( token )
6511 66 : is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6512 :
6513 66 : DEBUG(10,("Running [%s]\n", command));
6514 :
6515 : /********* BEGIN SePrintOperatorPrivilege **********/
6516 :
6517 66 : if ( is_print_op )
6518 0 : become_root();
6519 :
6520 66 : ret = smbrun(command, &fd, NULL);
6521 66 : if (ret == 0) {
6522 : /* Tell everyone we updated smb.conf. */
6523 66 : messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
6524 : }
6525 :
6526 66 : if ( is_print_op )
6527 0 : unbecome_root();
6528 :
6529 : /********* END SePrintOperatorPrivilege **********/
6530 :
6531 66 : DEBUGADD(10,("returned [%d]\n", ret));
6532 :
6533 66 : TALLOC_FREE(command);
6534 :
6535 66 : if ( ret != 0 ) {
6536 0 : if (fd != -1)
6537 0 : close(fd);
6538 0 : return false;
6539 : }
6540 :
6541 : /* reload our services immediately */
6542 66 : become_root();
6543 66 : reload_services(NULL, spoolss_conn_snum_used, false);
6544 66 : unbecome_root();
6545 :
6546 66 : numlines = 0;
6547 : /* Get lines and convert them back to dos-codepage */
6548 66 : qlines = fd_lines_load(fd, &numlines, 0, NULL);
6549 66 : DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6550 66 : close(fd);
6551 :
6552 : /* Set the portname to what the script says the portname should be. */
6553 : /* but don't require anything to be return from the script exit a good error code */
6554 :
6555 66 : if (numlines) {
6556 : /* Set the portname to what the script says the portname should be. */
6557 0 : info2->portname = talloc_strdup(ctx, qlines[0]);
6558 0 : DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6559 : }
6560 :
6561 66 : TALLOC_FREE(qlines);
6562 66 : return true;
6563 : }
6564 :
6565 100 : static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6566 : const struct auth_session_info *session_info,
6567 : struct messaging_context *msg_ctx,
6568 : int snum,
6569 : struct spoolss_SetPrinterInfo2 *printer,
6570 : struct spoolss_PrinterInfo2 *old_printer)
6571 : {
6572 100 : bool force_update = (old_printer == NULL);
6573 0 : const char *dnsdomname;
6574 0 : const char *longname;
6575 0 : const char *uncname;
6576 0 : const char *spooling;
6577 0 : DATA_BLOB buffer;
6578 100 : WERROR result = WERR_OK;
6579 0 : struct dcerpc_binding_handle *b;
6580 0 : TALLOC_CTX *tmp_ctx;
6581 0 : bool ok;
6582 :
6583 100 : tmp_ctx = talloc_new(mem_ctx);
6584 100 : if (!tmp_ctx) {
6585 0 : return WERR_NOT_ENOUGH_MEMORY;
6586 : }
6587 :
6588 100 : result = winreg_printer_binding_handle(tmp_ctx,
6589 : session_info,
6590 : msg_ctx,
6591 : &b);
6592 100 : if (!W_ERROR_IS_OK(result)) {
6593 0 : goto done;
6594 : }
6595 :
6596 100 : if (printer->drivername != NULL &&
6597 84 : (force_update ||
6598 84 : !strequal(printer->drivername, old_printer->drivername))) {
6599 24 : ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6600 24 : if (!ok) {
6601 0 : DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6602 0 : result = WERR_INVALID_DATA;
6603 0 : goto done;
6604 : }
6605 24 : result = winreg_set_printer_dataex(tmp_ctx, b,
6606 : printer->sharename,
6607 : SPOOL_DSSPOOLER_KEY,
6608 : SPOOL_REG_DRIVERNAME,
6609 : REG_SZ,
6610 : buffer.data,
6611 24 : buffer.length);
6612 24 : if (!W_ERROR_IS_OK(result)) {
6613 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6614 0 : goto done;
6615 : }
6616 :
6617 24 : if (!force_update) {
6618 8 : DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6619 : printer->drivername));
6620 :
6621 8 : notify_printer_driver(global_event_context(), msg_ctx,
6622 8 : snum, printer->drivername ?
6623 : printer->drivername : "");
6624 : }
6625 : }
6626 :
6627 100 : if (printer->comment != NULL &&
6628 84 : (force_update ||
6629 84 : !strequal(printer->comment, old_printer->comment))) {
6630 34 : ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6631 34 : if (!ok) {
6632 0 : DEBUG(0, ("comment data corrupted\n"));
6633 0 : result = WERR_INVALID_DATA;
6634 0 : goto done;
6635 : }
6636 34 : result = winreg_set_printer_dataex(tmp_ctx, b,
6637 : printer->sharename,
6638 : SPOOL_DSSPOOLER_KEY,
6639 : SPOOL_REG_DESCRIPTION,
6640 : REG_SZ,
6641 : buffer.data,
6642 34 : buffer.length);
6643 34 : if (!W_ERROR_IS_OK(result)) {
6644 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6645 0 : goto done;
6646 : }
6647 :
6648 34 : if (!force_update) {
6649 34 : notify_printer_comment(global_event_context(), msg_ctx,
6650 34 : snum, printer->comment ?
6651 : printer->comment : "");
6652 : }
6653 : }
6654 :
6655 100 : if (printer->sharename != NULL &&
6656 84 : (force_update ||
6657 84 : !strequal(printer->sharename, old_printer->sharename))) {
6658 16 : ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6659 16 : if (!ok) {
6660 0 : DEBUG(0, ("sharename data corrupted\n"));
6661 0 : result = WERR_INVALID_DATA;
6662 0 : goto done;
6663 : }
6664 16 : result = winreg_set_printer_dataex(tmp_ctx, b,
6665 : printer->sharename,
6666 : SPOOL_DSSPOOLER_KEY,
6667 : SPOOL_REG_PRINTSHARENAME,
6668 : REG_SZ,
6669 : buffer.data,
6670 16 : buffer.length);
6671 16 : if (!W_ERROR_IS_OK(result)) {
6672 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6673 0 : goto done;
6674 : }
6675 :
6676 16 : if (!force_update) {
6677 0 : notify_printer_sharename(global_event_context(),
6678 : msg_ctx,
6679 0 : snum, printer->sharename ?
6680 : printer->sharename : "");
6681 : }
6682 :
6683 : /* name change, purge any cache entries for the old */
6684 16 : prune_printername_cache();
6685 : }
6686 :
6687 100 : if (printer->printername != NULL &&
6688 84 : (force_update ||
6689 84 : !strequal(printer->printername, old_printer->printername))) {
6690 0 : const char *p;
6691 :
6692 100 : p = strrchr(printer->printername, '\\' );
6693 100 : if (p != NULL) {
6694 100 : p++;
6695 : } else {
6696 0 : p = printer->printername;
6697 : }
6698 :
6699 100 : ok = push_reg_sz(tmp_ctx, &buffer, p);
6700 100 : if (!ok) {
6701 0 : DEBUG(0, ("printername data corrupted\n"));
6702 0 : result = WERR_INVALID_DATA;
6703 0 : goto done;
6704 : }
6705 100 : result = winreg_set_printer_dataex(tmp_ctx, b,
6706 : printer->sharename,
6707 : SPOOL_DSSPOOLER_KEY,
6708 : SPOOL_REG_PRINTERNAME,
6709 : REG_SZ,
6710 : buffer.data,
6711 100 : buffer.length);
6712 100 : if (!W_ERROR_IS_OK(result)) {
6713 0 : DBG_ERR("Failed to set %s\n", SPOOL_REG_PRINTERNAME);
6714 0 : goto done;
6715 : }
6716 :
6717 100 : if (!force_update) {
6718 84 : notify_printer_printername(global_event_context(),
6719 : msg_ctx, snum, p ? p : "");
6720 : }
6721 :
6722 : /* name change, purge any cache entries for the old */
6723 100 : prune_printername_cache();
6724 : }
6725 :
6726 100 : if (printer->portname != NULL &&
6727 84 : (force_update ||
6728 84 : !strequal(printer->portname, old_printer->portname))) {
6729 16 : ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6730 16 : if (!ok) {
6731 0 : DEBUG(0, ("portname data corrupted\n"));
6732 0 : result = WERR_INVALID_DATA;
6733 0 : goto done;
6734 : }
6735 16 : result = winreg_set_printer_dataex(tmp_ctx, b,
6736 : printer->sharename,
6737 : SPOOL_DSSPOOLER_KEY,
6738 : SPOOL_REG_PORTNAME,
6739 : REG_SZ,
6740 : buffer.data,
6741 16 : buffer.length);
6742 16 : if (!W_ERROR_IS_OK(result)) {
6743 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6744 0 : goto done;
6745 : }
6746 :
6747 16 : if (!force_update) {
6748 0 : notify_printer_port(global_event_context(),
6749 0 : msg_ctx, snum, printer->portname ?
6750 : printer->portname : "");
6751 : }
6752 : }
6753 :
6754 100 : if (printer->location != NULL &&
6755 84 : (force_update ||
6756 84 : !strequal(printer->location, old_printer->location))) {
6757 8 : ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6758 8 : if (!ok) {
6759 0 : DEBUG(0, ("location data corrupted\n"));
6760 0 : result = WERR_INVALID_DATA;
6761 0 : goto done;
6762 : }
6763 8 : result = winreg_set_printer_dataex(tmp_ctx, b,
6764 : printer->sharename,
6765 : SPOOL_DSSPOOLER_KEY,
6766 : SPOOL_REG_LOCATION,
6767 : REG_SZ,
6768 : buffer.data,
6769 8 : buffer.length);
6770 8 : if (!W_ERROR_IS_OK(result)) {
6771 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6772 0 : goto done;
6773 : }
6774 :
6775 8 : if (!force_update) {
6776 8 : notify_printer_location(global_event_context(),
6777 : msg_ctx, snum,
6778 8 : printer->location ?
6779 : printer->location : "");
6780 : }
6781 : }
6782 :
6783 100 : if (printer->sepfile != NULL &&
6784 84 : (force_update ||
6785 84 : !strequal(printer->sepfile, old_printer->sepfile))) {
6786 0 : ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6787 0 : if (!ok) {
6788 0 : DEBUG(0, ("sepfile data corrupted\n"));
6789 0 : result = WERR_INVALID_DATA;
6790 0 : goto done;
6791 : }
6792 0 : result = winreg_set_printer_dataex(tmp_ctx, b,
6793 : printer->sharename,
6794 : SPOOL_DSSPOOLER_KEY,
6795 : SPOOL_REG_PRINTSEPARATORFILE,
6796 : REG_SZ,
6797 : buffer.data,
6798 0 : buffer.length);
6799 0 : if (!W_ERROR_IS_OK(result)) {
6800 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6801 0 : goto done;
6802 : }
6803 :
6804 0 : if (!force_update) {
6805 0 : notify_printer_sepfile(global_event_context(),
6806 : msg_ctx, snum,
6807 0 : printer->sepfile ?
6808 : printer->sepfile : "");
6809 : }
6810 : }
6811 :
6812 100 : if (printer->starttime != 0 &&
6813 0 : (force_update ||
6814 0 : printer->starttime != old_printer->starttime)) {
6815 0 : buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6816 0 : SIVAL(buffer.data, 0, printer->starttime);
6817 0 : result = winreg_set_printer_dataex(tmp_ctx, b,
6818 : printer->sharename,
6819 : SPOOL_DSSPOOLER_KEY,
6820 : SPOOL_REG_PRINTSTARTTIME,
6821 : REG_DWORD,
6822 : buffer.data,
6823 0 : buffer.length);
6824 0 : if (!W_ERROR_IS_OK(result)) {
6825 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6826 0 : goto done;
6827 : }
6828 : }
6829 :
6830 100 : if (printer->untiltime != 0 &&
6831 0 : (force_update ||
6832 0 : printer->untiltime != old_printer->untiltime)) {
6833 0 : buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6834 0 : SIVAL(buffer.data, 0, printer->untiltime);
6835 0 : result = winreg_set_printer_dataex(tmp_ctx, b,
6836 : printer->sharename,
6837 : SPOOL_DSSPOOLER_KEY,
6838 : SPOOL_REG_PRINTENDTIME,
6839 : REG_DWORD,
6840 : buffer.data,
6841 0 : buffer.length);
6842 0 : if (!W_ERROR_IS_OK(result)) {
6843 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6844 0 : goto done;
6845 : }
6846 : }
6847 :
6848 100 : if (force_update || printer->priority != old_printer->priority) {
6849 16 : buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6850 16 : SIVAL(buffer.data, 0, printer->priority);
6851 16 : result = winreg_set_printer_dataex(tmp_ctx, b,
6852 : printer->sharename,
6853 : SPOOL_DSSPOOLER_KEY,
6854 : SPOOL_REG_PRIORITY,
6855 : REG_DWORD,
6856 : buffer.data,
6857 16 : buffer.length);
6858 16 : if (!W_ERROR_IS_OK(result)) {
6859 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6860 0 : goto done;
6861 : }
6862 : }
6863 :
6864 100 : if (force_update || printer->attributes != old_printer->attributes) {
6865 16 : buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6866 16 : SIVAL(buffer.data, 0, (printer->attributes &
6867 : PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6868 16 : result = winreg_set_printer_dataex(tmp_ctx, b,
6869 : printer->sharename,
6870 : SPOOL_DSSPOOLER_KEY,
6871 : SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6872 : REG_DWORD,
6873 : buffer.data,
6874 16 : buffer.length);
6875 16 : if (!W_ERROR_IS_OK(result)) {
6876 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6877 0 : goto done;
6878 : }
6879 :
6880 16 : switch (printer->attributes & 0x3) {
6881 16 : case 0:
6882 16 : spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6883 16 : break;
6884 0 : case 1:
6885 0 : spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6886 0 : break;
6887 0 : case 2:
6888 0 : spooling = SPOOL_REGVAL_PRINTDIRECT;
6889 0 : break;
6890 0 : default:
6891 0 : spooling = "unknown";
6892 : }
6893 16 : ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6894 16 : if (!ok) {
6895 0 : DEBUG(0, ("printSpooling data corrupted\n"));
6896 0 : result = WERR_INVALID_DATA;
6897 0 : goto done;
6898 : }
6899 16 : winreg_set_printer_dataex(tmp_ctx, b,
6900 : printer->sharename,
6901 : SPOOL_DSSPOOLER_KEY,
6902 : SPOOL_REG_PRINTSPOOLING,
6903 : REG_SZ,
6904 : buffer.data,
6905 16 : buffer.length);
6906 : }
6907 :
6908 100 : ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6909 100 : if (!ok) {
6910 0 : DEBUG(0, ("shortServerName data corrupted\n"));
6911 0 : result = WERR_INVALID_DATA;
6912 0 : goto done;
6913 : }
6914 100 : result = winreg_set_printer_dataex(tmp_ctx, b,
6915 : printer->sharename,
6916 : SPOOL_DSSPOOLER_KEY,
6917 : SPOOL_REG_SHORTSERVERNAME,
6918 : REG_SZ,
6919 : buffer.data,
6920 100 : buffer.length);
6921 100 : if (!W_ERROR_IS_OK(result)) {
6922 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6923 0 : goto done;
6924 : }
6925 :
6926 100 : dnsdomname = get_mydnsfullname();
6927 100 : if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6928 100 : longname = talloc_strdup(tmp_ctx, dnsdomname);
6929 : } else {
6930 0 : longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6931 : }
6932 100 : if (longname == NULL) {
6933 0 : result = WERR_NOT_ENOUGH_MEMORY;
6934 0 : goto done;
6935 : }
6936 :
6937 100 : ok = push_reg_sz(tmp_ctx, &buffer, longname);
6938 100 : if (!ok) {
6939 0 : DEBUG(0, ("longname data corrupted\n"));
6940 0 : result = WERR_INVALID_DATA;
6941 0 : goto done;
6942 : }
6943 100 : result = winreg_set_printer_dataex(tmp_ctx, b,
6944 : printer->sharename,
6945 : SPOOL_DSSPOOLER_KEY,
6946 : SPOOL_REG_SERVERNAME,
6947 : REG_SZ,
6948 : buffer.data,
6949 100 : buffer.length);
6950 100 : if (!W_ERROR_IS_OK(result)) {
6951 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6952 0 : goto done;
6953 : }
6954 :
6955 100 : uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6956 : lp_netbios_name(), printer->sharename);
6957 100 : ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6958 100 : if (!ok) {
6959 0 : DEBUG(0, ("uncName data corrupted\n"));
6960 0 : result = WERR_INVALID_DATA;
6961 0 : goto done;
6962 : }
6963 100 : result = winreg_set_printer_dataex(tmp_ctx, b,
6964 : printer->sharename,
6965 : SPOOL_DSSPOOLER_KEY,
6966 : SPOOL_REG_UNCNAME,
6967 : REG_SZ,
6968 : buffer.data,
6969 100 : buffer.length);
6970 100 : if (!W_ERROR_IS_OK(result)) {
6971 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6972 0 : goto done;
6973 : }
6974 :
6975 100 : done:
6976 100 : talloc_free(tmp_ctx);
6977 100 : return result;
6978 : }
6979 :
6980 : /********************************************************************
6981 : * Called by spoolss_api_setprinter
6982 : * when updating a printer description.
6983 : ********************************************************************/
6984 :
6985 84 : static WERROR update_printer(struct pipes_struct *p,
6986 : struct policy_handle *handle,
6987 : struct spoolss_SetPrinterInfoCtr *info_ctr,
6988 : struct spoolss_DeviceMode *devmode)
6989 : {
6990 84 : struct dcesrv_call_state *dce_call = p->dce_call;
6991 84 : struct dcesrv_connection *dcesrv_conn = dce_call->conn;
6992 0 : const struct tsocket_address *remote_address =
6993 84 : dcesrv_connection_get_remote_address(dcesrv_conn);
6994 0 : struct auth_session_info *session_info =
6995 84 : dcesrv_call_session_info(dce_call);
6996 84 : uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6997 84 : struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6998 0 : struct spoolss_PrinterInfo2 *old_printer;
6999 84 : struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
7000 0 : const struct loadparm_substitution *lp_sub =
7001 84 : loadparm_s3_global_substitution();
7002 0 : int snum;
7003 84 : WERROR result = WERR_OK;
7004 0 : TALLOC_CTX *tmp_ctx;
7005 0 : struct dcerpc_binding_handle *b;
7006 :
7007 84 : DEBUG(8,("update_printer\n"));
7008 :
7009 84 : tmp_ctx = talloc_new(p->mem_ctx);
7010 84 : if (tmp_ctx == NULL) {
7011 0 : return WERR_NOT_ENOUGH_MEMORY;
7012 : }
7013 :
7014 84 : if (!Printer) {
7015 0 : result = WERR_INVALID_HANDLE;
7016 0 : goto done;
7017 : }
7018 :
7019 84 : if (!get_printer_snum(p, handle, &snum, NULL)) {
7020 0 : result = WERR_INVALID_HANDLE;
7021 0 : goto done;
7022 : }
7023 :
7024 84 : result = winreg_printer_binding_handle(tmp_ctx,
7025 : get_session_info_system(),
7026 : p->msg_ctx,
7027 : &b);
7028 84 : if (!W_ERROR_IS_OK(result)) {
7029 0 : goto done;
7030 : }
7031 :
7032 84 : result = winreg_get_printer(tmp_ctx, b,
7033 : lp_const_servicename(snum),
7034 : &old_printer);
7035 84 : if (!W_ERROR_IS_OK(result)) {
7036 0 : result = WERR_INVALID_HANDLE;
7037 0 : goto done;
7038 : }
7039 :
7040 : /* Do sanity check on the requested changes for Samba */
7041 84 : if (!check_printer_ok(tmp_ctx, printer, snum)) {
7042 0 : result = WERR_INVALID_PARAMETER;
7043 0 : goto done;
7044 : }
7045 :
7046 : /* FIXME!!! If the driver has changed we really should verify that
7047 : it is installed before doing much else --jerry */
7048 :
7049 : /* Check calling user has permission to update printer description */
7050 84 : if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7051 0 : DEBUG(3, ("update_printer: printer property change denied by handle\n"));
7052 0 : result = WERR_ACCESS_DENIED;
7053 0 : goto done;
7054 : }
7055 :
7056 : /* Call addprinter hook */
7057 : /* Check changes to see if this is really needed */
7058 :
7059 84 : if (*lp_addprinter_command(talloc_tos(), lp_sub) &&
7060 84 : (!strequal(printer->drivername, old_printer->drivername) ||
7061 76 : !strequal(printer->comment, old_printer->comment) ||
7062 42 : !strequal(printer->portname, old_printer->portname) ||
7063 42 : !strequal(printer->location, old_printer->location)) )
7064 : {
7065 0 : char *raddr;
7066 :
7067 50 : raddr = tsocket_address_inet_addr_string(remote_address,
7068 : p->mem_ctx);
7069 50 : if (raddr == NULL) {
7070 0 : result = WERR_NOT_ENOUGH_MEMORY;
7071 0 : goto done;
7072 : }
7073 :
7074 : /* add_printer_hook() will call reload_services() */
7075 50 : if (!add_printer_hook(tmp_ctx, session_info->security_token,
7076 : printer, raddr,
7077 : p->msg_ctx)) {
7078 0 : result = WERR_ACCESS_DENIED;
7079 0 : goto done;
7080 : }
7081 : }
7082 :
7083 84 : result = update_dsspooler(tmp_ctx,
7084 : get_session_info_system(),
7085 : p->msg_ctx,
7086 : snum,
7087 : printer,
7088 : old_printer);
7089 84 : if (!W_ERROR_IS_OK(result)) {
7090 0 : goto done;
7091 : }
7092 :
7093 84 : printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
7094 :
7095 84 : if (devmode == NULL) {
7096 76 : printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
7097 : }
7098 84 : result = winreg_update_printer(tmp_ctx, b,
7099 : printer->sharename,
7100 : printer_mask,
7101 : printer,
7102 : devmode,
7103 : NULL);
7104 :
7105 84 : done:
7106 84 : talloc_free(tmp_ctx);
7107 :
7108 84 : return result;
7109 : }
7110 :
7111 : /****************************************************************************
7112 : ****************************************************************************/
7113 8 : static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
7114 : struct policy_handle *handle,
7115 : struct spoolss_SetPrinterInfo7 *info7)
7116 : {
7117 : #ifdef HAVE_ADS
7118 0 : const struct loadparm_substitution *lp_sub =
7119 6 : loadparm_s3_global_substitution();
7120 6 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7121 0 : WERROR result;
7122 0 : int snum;
7123 0 : struct printer_handle *Printer;
7124 :
7125 6 : if ( lp_security() != SEC_ADS ) {
7126 6 : return WERR_INVALID_LEVEL;
7127 : }
7128 :
7129 0 : Printer = find_printer_index_by_hnd(p, handle);
7130 :
7131 0 : DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
7132 :
7133 0 : if (!Printer)
7134 0 : return WERR_INVALID_HANDLE;
7135 :
7136 0 : if (!get_printer_snum(p, handle, &snum, NULL))
7137 0 : return WERR_INVALID_HANDLE;
7138 :
7139 0 : result = winreg_get_printer_internal(p->mem_ctx,
7140 : get_session_info_system(),
7141 : p->msg_ctx,
7142 0 : lp_servicename(talloc_tos(), lp_sub, snum),
7143 : &pinfo2);
7144 0 : if (!W_ERROR_IS_OK(result)) {
7145 0 : return WERR_INVALID_HANDLE;
7146 : }
7147 :
7148 0 : nt_printer_publish(pinfo2,
7149 : get_session_info_system(),
7150 : p->msg_ctx,
7151 : pinfo2,
7152 0 : info7->action);
7153 :
7154 0 : TALLOC_FREE(pinfo2);
7155 0 : return WERR_OK;
7156 : #else
7157 2 : return WERR_INVALID_LEVEL;
7158 : #endif
7159 : }
7160 :
7161 : /********************************************************************
7162 : ********************************************************************/
7163 :
7164 296 : static WERROR update_printer_devmode(struct pipes_struct *p,
7165 : struct policy_handle *handle,
7166 : struct spoolss_DeviceMode *devmode)
7167 : {
7168 0 : int snum;
7169 296 : struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
7170 296 : uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
7171 :
7172 296 : DEBUG(8,("update_printer_devmode\n"));
7173 :
7174 296 : if (!Printer) {
7175 0 : return WERR_INVALID_HANDLE;
7176 : }
7177 :
7178 296 : if (!get_printer_snum(p, handle, &snum, NULL)) {
7179 0 : return WERR_INVALID_HANDLE;
7180 : }
7181 :
7182 : /* Check calling user has permission to update printer description */
7183 296 : if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7184 0 : DEBUG(3, ("update_printer: printer property change denied by handle\n"));
7185 0 : return WERR_ACCESS_DENIED;
7186 : }
7187 :
7188 296 : return winreg_update_printer_internal(p->mem_ctx,
7189 : get_session_info_system(),
7190 : p->msg_ctx,
7191 : lp_const_servicename(snum),
7192 : info2_mask,
7193 : NULL,
7194 : devmode,
7195 : NULL);
7196 : }
7197 :
7198 :
7199 : /****************************************************************
7200 : _spoolss_SetPrinter
7201 : ****************************************************************/
7202 :
7203 584 : WERROR _spoolss_SetPrinter(struct pipes_struct *p,
7204 : struct spoolss_SetPrinter *r)
7205 : {
7206 0 : WERROR result;
7207 :
7208 584 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7209 :
7210 584 : if (!Printer) {
7211 0 : DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
7212 : OUR_HANDLE(r->in.handle)));
7213 0 : return WERR_INVALID_HANDLE;
7214 : }
7215 :
7216 : /* check the level */
7217 584 : switch (r->in.info_ctr->level) {
7218 104 : case 0:
7219 104 : return control_printer(r->in.handle, r->in.command, p);
7220 84 : case 2:
7221 84 : result = update_printer(p, r->in.handle,
7222 : r->in.info_ctr,
7223 84 : r->in.devmode_ctr->devmode);
7224 84 : if (!W_ERROR_IS_OK(result))
7225 0 : return result;
7226 84 : if (r->in.secdesc_ctr->sd)
7227 28 : result = update_printer_sec(r->in.handle, p,
7228 : r->in.secdesc_ctr);
7229 84 : return result;
7230 92 : case 3:
7231 92 : return update_printer_sec(r->in.handle, p,
7232 : r->in.secdesc_ctr);
7233 0 : case 4: {
7234 0 : struct spoolss_PrinterInfo2 *old_printer;
7235 0 : struct spoolss_SetPrinterInfo2 *set_old_printer;
7236 0 : struct spoolss_SetPrinterInfoCtr *info_ctr;
7237 0 : struct dcerpc_binding_handle *b;
7238 0 : int snum;
7239 0 : TALLOC_CTX *tmp_ctx;
7240 :
7241 0 : tmp_ctx = talloc_new(p->mem_ctx);
7242 0 : if (tmp_ctx == NULL) {
7243 0 : return WERR_NOT_ENOUGH_MEMORY;
7244 : }
7245 :
7246 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7247 0 : TALLOC_FREE(tmp_ctx);
7248 0 : return WERR_INVALID_HANDLE;
7249 : }
7250 :
7251 0 : result = winreg_printer_binding_handle(tmp_ctx,
7252 : get_session_info_system(),
7253 : p->msg_ctx,
7254 : &b);
7255 0 : if (!W_ERROR_IS_OK(result)) {
7256 0 : TALLOC_FREE(tmp_ctx);
7257 0 : return result;
7258 : }
7259 :
7260 0 : result = winreg_get_printer(tmp_ctx, b,
7261 : lp_const_servicename(snum),
7262 : &old_printer);
7263 0 : if (!W_ERROR_IS_OK(result)) {
7264 0 : TALLOC_FREE(tmp_ctx);
7265 0 : return WERR_INVALID_HANDLE;
7266 : }
7267 :
7268 0 : old_printer->servername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->servername);
7269 0 : if (old_printer->servername == NULL) {
7270 0 : TALLOC_FREE(tmp_ctx);
7271 0 : return WERR_NOT_ENOUGH_MEMORY;
7272 : }
7273 :
7274 0 : old_printer->printername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->printername);
7275 0 : if (old_printer->printername == NULL) {
7276 0 : TALLOC_FREE(tmp_ctx);
7277 0 : return WERR_NOT_ENOUGH_MEMORY;
7278 : }
7279 :
7280 0 : old_printer->attributes = r->in.info_ctr->info.info4->attributes;
7281 :
7282 0 : set_old_printer = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfo2);
7283 0 : if (set_old_printer == NULL) {
7284 0 : TALLOC_FREE(tmp_ctx);
7285 0 : return WERR_NOT_ENOUGH_MEMORY;
7286 : }
7287 :
7288 0 : spoolss_printerinfo2_to_setprinterinfo2(old_printer, set_old_printer);
7289 :
7290 0 : info_ctr = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfoCtr);
7291 0 : if (info_ctr == NULL) {
7292 0 : TALLOC_FREE(tmp_ctx);
7293 0 : return WERR_NOT_ENOUGH_MEMORY;
7294 : }
7295 :
7296 0 : info_ctr->level = 2;
7297 0 : info_ctr->info.info2 = set_old_printer;
7298 :
7299 0 : result = update_printer(p, r->in.handle,
7300 : info_ctr,
7301 0 : r->in.devmode_ctr->devmode);
7302 :
7303 0 : if (!W_ERROR_IS_OK(result)) {
7304 0 : TALLOC_FREE(tmp_ctx);
7305 0 : return result;
7306 : }
7307 :
7308 0 : if (r->in.secdesc_ctr->sd) {
7309 0 : result = update_printer_sec(r->in.handle, p,
7310 : r->in.secdesc_ctr);
7311 : }
7312 :
7313 0 : TALLOC_FREE(tmp_ctx);
7314 0 : return result;
7315 : }
7316 8 : case 7:
7317 8 : return publish_or_unpublish_printer(p, r->in.handle,
7318 8 : r->in.info_ctr->info.info7);
7319 296 : case 8:
7320 296 : return update_printer_devmode(p, r->in.handle,
7321 296 : r->in.devmode_ctr->devmode);
7322 0 : default:
7323 0 : return WERR_INVALID_LEVEL;
7324 : }
7325 : }
7326 :
7327 : /****************************************************************
7328 : _spoolss_FindClosePrinterNotify
7329 : ****************************************************************/
7330 :
7331 0 : WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
7332 : struct spoolss_FindClosePrinterNotify *r)
7333 : {
7334 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7335 :
7336 0 : if (!Printer) {
7337 0 : DEBUG(2,("_spoolss_FindClosePrinterNotify: "
7338 : "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
7339 0 : return WERR_INVALID_HANDLE;
7340 : }
7341 :
7342 0 : if (Printer->notify.cli_chan != NULL &&
7343 0 : Printer->notify.cli_chan->active_connections > 0) {
7344 0 : int snum = -1;
7345 :
7346 0 : if (Printer->printer_type == SPLHND_PRINTER) {
7347 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7348 0 : return WERR_INVALID_HANDLE;
7349 : }
7350 : }
7351 :
7352 0 : srv_spoolss_replycloseprinter(snum, Printer);
7353 : }
7354 :
7355 0 : Printer->notify.flags=0;
7356 0 : Printer->notify.options=0;
7357 0 : Printer->notify.localmachine[0]='\0';
7358 0 : Printer->notify.printerlocal=0;
7359 0 : TALLOC_FREE(Printer->notify.option);
7360 :
7361 0 : return WERR_OK;
7362 : }
7363 :
7364 : /****************************************************************
7365 : _spoolss_AddJob
7366 : ****************************************************************/
7367 :
7368 16 : WERROR _spoolss_AddJob(struct pipes_struct *p,
7369 : struct spoolss_AddJob *r)
7370 : {
7371 16 : if (!r->in.buffer && (r->in.offered != 0)) {
7372 0 : return WERR_INVALID_PARAMETER;
7373 : }
7374 :
7375 : /* this is what a NT server returns for AddJob. AddJob must fail on
7376 : * non-local printers */
7377 :
7378 16 : if (r->in.level != 1) {
7379 8 : return WERR_INVALID_LEVEL;
7380 : }
7381 :
7382 8 : return WERR_INVALID_PARAMETER;
7383 : }
7384 :
7385 : /****************************************************************************
7386 : fill_job_info1
7387 : ****************************************************************************/
7388 :
7389 320 : static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
7390 : struct spoolss_JobInfo1 *r,
7391 : const print_queue_struct *queue,
7392 : uint32_t jobid,
7393 : int position, int snum,
7394 : struct spoolss_PrinterInfo2 *pinfo2)
7395 : {
7396 0 : const struct loadparm_substitution *lp_sub =
7397 320 : loadparm_s3_global_substitution();
7398 0 : struct tm *t;
7399 :
7400 320 : t = gmtime(&queue->time);
7401 :
7402 320 : r->job_id = jobid;
7403 :
7404 320 : r->printer_name = lp_servicename(mem_ctx, lp_sub, snum);
7405 320 : W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7406 320 : r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
7407 320 : W_ERROR_HAVE_NO_MEMORY(r->server_name);
7408 320 : r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
7409 320 : W_ERROR_HAVE_NO_MEMORY(r->user_name);
7410 320 : r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
7411 320 : W_ERROR_HAVE_NO_MEMORY(r->document_name);
7412 320 : r->data_type = talloc_strdup(mem_ctx, "RAW");
7413 320 : W_ERROR_HAVE_NO_MEMORY(r->data_type);
7414 320 : r->text_status = talloc_strdup(mem_ctx, "");
7415 320 : W_ERROR_HAVE_NO_MEMORY(r->text_status);
7416 :
7417 320 : r->status = nt_printj_status(queue->status);
7418 320 : r->priority = queue->priority;
7419 320 : r->position = position;
7420 320 : r->total_pages = queue->page_count;
7421 320 : r->pages_printed = 0; /* ??? */
7422 :
7423 320 : init_systemtime(&r->submitted, t);
7424 :
7425 320 : return WERR_OK;
7426 : }
7427 :
7428 : /****************************************************************************
7429 : fill_job_info2
7430 : ****************************************************************************/
7431 :
7432 72 : static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7433 : struct spoolss_JobInfo2 *r,
7434 : const print_queue_struct *queue,
7435 : uint32_t jobid,
7436 : int position, int snum,
7437 : struct spoolss_PrinterInfo2 *pinfo2,
7438 : struct spoolss_DeviceMode *devmode)
7439 : {
7440 0 : const struct loadparm_substitution *lp_sub =
7441 72 : loadparm_s3_global_substitution();
7442 0 : struct tm *t;
7443 :
7444 72 : t = gmtime(&queue->time);
7445 :
7446 72 : r->job_id = jobid;
7447 :
7448 72 : r->printer_name = lp_servicename(mem_ctx, lp_sub, snum);
7449 72 : W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7450 72 : r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
7451 72 : W_ERROR_HAVE_NO_MEMORY(r->server_name);
7452 72 : r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
7453 72 : W_ERROR_HAVE_NO_MEMORY(r->user_name);
7454 72 : r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
7455 72 : W_ERROR_HAVE_NO_MEMORY(r->document_name);
7456 72 : r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
7457 72 : W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7458 72 : r->data_type = talloc_strdup(mem_ctx, "RAW");
7459 72 : W_ERROR_HAVE_NO_MEMORY(r->data_type);
7460 72 : r->print_processor = talloc_strdup(mem_ctx, "winprint");
7461 72 : W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7462 72 : r->parameters = talloc_strdup(mem_ctx, "");
7463 72 : W_ERROR_HAVE_NO_MEMORY(r->parameters);
7464 72 : r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
7465 72 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7466 :
7467 72 : r->devmode = devmode;
7468 :
7469 72 : r->text_status = talloc_strdup(mem_ctx, "");
7470 72 : W_ERROR_HAVE_NO_MEMORY(r->text_status);
7471 :
7472 72 : r->secdesc = NULL;
7473 :
7474 72 : r->status = nt_printj_status(queue->status);
7475 72 : r->priority = queue->priority;
7476 72 : r->position = position;
7477 72 : r->start_time = 0;
7478 72 : r->until_time = 0;
7479 72 : r->total_pages = queue->page_count;
7480 72 : r->size = queue->size;
7481 72 : init_systemtime(&r->submitted, t);
7482 72 : r->time = 0;
7483 72 : r->pages_printed = 0; /* ??? */
7484 :
7485 72 : return WERR_OK;
7486 : }
7487 :
7488 : /****************************************************************************
7489 : Enumjobs at level 1.
7490 : ****************************************************************************/
7491 :
7492 24 : static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7493 : const print_queue_struct *queue,
7494 : uint32_t num_queues, int snum,
7495 : struct spoolss_PrinterInfo2 *pinfo2,
7496 : union spoolss_JobInfo **info_p,
7497 : uint32_t *count)
7498 : {
7499 0 : union spoolss_JobInfo *info;
7500 0 : int i;
7501 24 : WERROR result = WERR_OK;
7502 0 : uint32_t num_filled;
7503 0 : struct tdb_print_db *pdb;
7504 :
7505 24 : info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7506 24 : if (info == NULL) {
7507 0 : result = WERR_NOT_ENOUGH_MEMORY;
7508 0 : goto err_out;
7509 : }
7510 :
7511 24 : pdb = get_print_db_byname(pinfo2->sharename);
7512 24 : if (pdb == NULL) {
7513 0 : result = WERR_INVALID_PARAMETER;
7514 0 : goto err_info_free;
7515 : }
7516 :
7517 24 : num_filled = 0;
7518 216 : for (i = 0; i < num_queues; i++) {
7519 192 : uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7520 192 : if (jobid == (uint32_t)-1) {
7521 0 : DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7522 0 : continue;
7523 : }
7524 :
7525 192 : result = fill_job_info1(info,
7526 192 : &info[num_filled].info1,
7527 192 : &queue[i],
7528 : jobid,
7529 : i,
7530 : snum,
7531 : pinfo2);
7532 192 : if (!W_ERROR_IS_OK(result)) {
7533 0 : goto err_pdb_drop;
7534 : }
7535 :
7536 192 : num_filled++;
7537 : }
7538 :
7539 24 : release_print_db(pdb);
7540 24 : *info_p = info;
7541 24 : *count = num_filled;
7542 :
7543 24 : return WERR_OK;
7544 :
7545 0 : err_pdb_drop:
7546 0 : release_print_db(pdb);
7547 0 : err_info_free:
7548 0 : TALLOC_FREE(info);
7549 0 : err_out:
7550 0 : *count = 0;
7551 0 : return result;
7552 : }
7553 :
7554 : /****************************************************************************
7555 : Enumjobs at level 2.
7556 : ****************************************************************************/
7557 :
7558 16 : static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7559 : const print_queue_struct *queue,
7560 : uint32_t num_queues, int snum,
7561 : struct spoolss_PrinterInfo2 *pinfo2,
7562 : union spoolss_JobInfo **info_p,
7563 : uint32_t *count)
7564 : {
7565 0 : union spoolss_JobInfo *info;
7566 0 : int i;
7567 16 : WERROR result = WERR_OK;
7568 0 : uint32_t num_filled;
7569 0 : struct tdb_print_db *pdb;
7570 :
7571 16 : info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7572 16 : if (info == NULL) {
7573 0 : result = WERR_NOT_ENOUGH_MEMORY;
7574 0 : goto err_out;
7575 : }
7576 :
7577 16 : pdb = get_print_db_byname(pinfo2->sharename);
7578 16 : if (pdb == NULL) {
7579 0 : result = WERR_INVALID_PARAMETER;
7580 0 : goto err_info_free;
7581 : }
7582 :
7583 16 : num_filled = 0;
7584 88 : for (i = 0; i< num_queues; i++) {
7585 0 : struct spoolss_DeviceMode *devmode;
7586 72 : uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7587 72 : if (jobid == (uint32_t)-1) {
7588 0 : DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7589 0 : continue;
7590 : }
7591 :
7592 72 : result = spoolss_create_default_devmode(info,
7593 : pinfo2->printername,
7594 : &devmode);
7595 72 : if (!W_ERROR_IS_OK(result)) {
7596 0 : DEBUG(3, ("Can't proceed w/o a devmode!\n"));
7597 0 : goto err_pdb_drop;
7598 : }
7599 :
7600 72 : result = fill_job_info2(info,
7601 72 : &info[num_filled].info2,
7602 72 : &queue[i],
7603 : jobid,
7604 : i,
7605 : snum,
7606 : pinfo2,
7607 : devmode);
7608 72 : if (!W_ERROR_IS_OK(result)) {
7609 0 : goto err_pdb_drop;
7610 : }
7611 72 : num_filled++;
7612 : }
7613 :
7614 16 : release_print_db(pdb);
7615 16 : *info_p = info;
7616 16 : *count = num_filled;
7617 :
7618 16 : return WERR_OK;
7619 :
7620 0 : err_pdb_drop:
7621 0 : release_print_db(pdb);
7622 0 : err_info_free:
7623 0 : TALLOC_FREE(info);
7624 0 : err_out:
7625 0 : *count = 0;
7626 0 : return result;
7627 : }
7628 :
7629 : /****************************************************************************
7630 : Enumjobs at level 3.
7631 : ****************************************************************************/
7632 :
7633 0 : static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7634 : const print_queue_struct *queue,
7635 : uint32_t num_queues, int snum,
7636 : struct spoolss_PrinterInfo2 *pinfo2,
7637 : union spoolss_JobInfo **info_p,
7638 : uint32_t *count)
7639 : {
7640 0 : union spoolss_JobInfo *info;
7641 0 : int i;
7642 0 : WERROR result = WERR_OK;
7643 0 : uint32_t num_filled;
7644 0 : struct tdb_print_db *pdb;
7645 :
7646 0 : info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7647 0 : if (info == NULL) {
7648 0 : result = WERR_NOT_ENOUGH_MEMORY;
7649 0 : goto err_out;
7650 : }
7651 :
7652 0 : pdb = get_print_db_byname(pinfo2->sharename);
7653 0 : if (pdb == NULL) {
7654 0 : result = WERR_INVALID_PARAMETER;
7655 0 : goto err_info_free;
7656 : }
7657 :
7658 0 : num_filled = 0;
7659 0 : for (i = 0; i < num_queues; i++) {
7660 0 : uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7661 0 : if (jobid == (uint32_t)-1) {
7662 0 : DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7663 0 : continue;
7664 : }
7665 :
7666 0 : info[num_filled].info3.job_id = jobid;
7667 : /* next_job_id is overwritten on next iteration */
7668 0 : info[num_filled].info3.next_job_id = 0;
7669 0 : info[num_filled].info3.reserved = 0;
7670 :
7671 0 : if (num_filled > 0) {
7672 0 : info[num_filled - 1].info3.next_job_id = jobid;
7673 : }
7674 0 : num_filled++;
7675 : }
7676 :
7677 0 : release_print_db(pdb);
7678 0 : *info_p = info;
7679 0 : *count = num_filled;
7680 :
7681 0 : return WERR_OK;
7682 :
7683 0 : err_info_free:
7684 0 : TALLOC_FREE(info);
7685 0 : err_out:
7686 0 : *count = 0;
7687 0 : return result;
7688 : }
7689 :
7690 : /****************************************************************
7691 : _spoolss_EnumJobs
7692 : ****************************************************************/
7693 :
7694 98 : WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7695 : struct spoolss_EnumJobs *r)
7696 : {
7697 0 : WERROR result;
7698 98 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7699 0 : int snum;
7700 0 : print_status_struct prt_status;
7701 98 : print_queue_struct *queue = NULL;
7702 0 : uint32_t count;
7703 :
7704 : /* that's an [in out] buffer */
7705 :
7706 98 : if (!r->in.buffer && (r->in.offered != 0)) {
7707 0 : return WERR_INVALID_PARAMETER;
7708 : }
7709 :
7710 98 : if ((r->in.level != 1) && (r->in.level != 2) && (r->in.level != 3)) {
7711 12 : DEBUG(4, ("EnumJobs level %d not supported\n", r->in.level));
7712 12 : return WERR_INVALID_LEVEL;
7713 : }
7714 :
7715 86 : DEBUG(4,("_spoolss_EnumJobs\n"));
7716 :
7717 86 : *r->out.needed = 0;
7718 86 : *r->out.count = 0;
7719 86 : *r->out.info = NULL;
7720 :
7721 : /* lookup the printer snum and tdb entry */
7722 :
7723 86 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7724 0 : return WERR_INVALID_HANDLE;
7725 : }
7726 :
7727 86 : result = winreg_get_printer_internal(p->mem_ctx,
7728 : get_session_info_system(),
7729 : p->msg_ctx,
7730 : lp_const_servicename(snum),
7731 : &pinfo2);
7732 86 : if (!W_ERROR_IS_OK(result)) {
7733 0 : return result;
7734 : }
7735 :
7736 86 : count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7737 86 : DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7738 : count, prt_status.status, prt_status.message));
7739 :
7740 86 : if (count == 0) {
7741 46 : SAFE_FREE(queue);
7742 46 : TALLOC_FREE(pinfo2);
7743 46 : return WERR_OK;
7744 : }
7745 :
7746 40 : switch (r->in.level) {
7747 24 : case 1:
7748 24 : result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7749 : pinfo2, r->out.info, r->out.count);
7750 24 : break;
7751 16 : case 2:
7752 16 : result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7753 : pinfo2, r->out.info, r->out.count);
7754 16 : break;
7755 0 : case 3:
7756 0 : result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7757 : pinfo2, r->out.info, r->out.count);
7758 0 : break;
7759 0 : default:
7760 0 : SMB_ASSERT(false); /* level checked on entry */
7761 : break;
7762 : }
7763 :
7764 40 : SAFE_FREE(queue);
7765 40 : TALLOC_FREE(pinfo2);
7766 :
7767 40 : if (!W_ERROR_IS_OK(result)) {
7768 0 : return result;
7769 : }
7770 :
7771 40 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7772 : spoolss_EnumJobs,
7773 : *r->out.info, r->in.level,
7774 : *r->out.count);
7775 40 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7776 40 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7777 :
7778 40 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7779 : }
7780 :
7781 : /****************************************************************
7782 : _spoolss_ScheduleJob
7783 : ****************************************************************/
7784 :
7785 0 : WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7786 : struct spoolss_ScheduleJob *r)
7787 : {
7788 0 : return WERR_OK;
7789 : }
7790 :
7791 : /****************************************************************
7792 : ****************************************************************/
7793 :
7794 32 : static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7795 : struct messaging_context *msg_ctx,
7796 : const char *printer_name,
7797 : uint32_t job_id,
7798 : struct spoolss_SetJobInfo1 *r)
7799 : {
7800 0 : char *old_doc_name;
7801 :
7802 32 : if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7803 0 : return WERR_INVALID_HANDLE;
7804 : }
7805 :
7806 32 : if (strequal(old_doc_name, r->document_name)) {
7807 0 : return WERR_OK;
7808 : }
7809 :
7810 32 : if (!print_job_set_name(global_event_context(), msg_ctx,
7811 : printer_name, job_id, r->document_name)) {
7812 0 : return WERR_INVALID_HANDLE;
7813 : }
7814 :
7815 32 : return WERR_OK;
7816 : }
7817 :
7818 : /****************************************************************
7819 : _spoolss_SetJob
7820 : ****************************************************************/
7821 :
7822 640 : WERROR _spoolss_SetJob(struct pipes_struct *p,
7823 : struct spoolss_SetJob *r)
7824 : {
7825 640 : struct dcesrv_call_state *dce_call = p->dce_call;
7826 0 : struct auth_session_info *session_info =
7827 640 : dcesrv_call_session_info(dce_call);
7828 0 : int snum;
7829 640 : WERROR errcode = WERR_INVALID_FUNCTION;
7830 :
7831 640 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7832 0 : return WERR_INVALID_HANDLE;
7833 : }
7834 :
7835 640 : if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7836 238 : return WERR_INVALID_PRINTER_NAME;
7837 : }
7838 :
7839 402 : switch (r->in.command) {
7840 306 : case SPOOLSS_JOB_CONTROL_CANCEL:
7841 : case SPOOLSS_JOB_CONTROL_DELETE:
7842 306 : errcode = print_job_delete(session_info, p->msg_ctx,
7843 : snum, r->in.job_id);
7844 306 : if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7845 306 : errcode = WERR_OK;
7846 : }
7847 306 : break;
7848 32 : case SPOOLSS_JOB_CONTROL_PAUSE:
7849 32 : errcode = print_job_pause(session_info, p->msg_ctx,
7850 : snum, r->in.job_id);
7851 32 : break;
7852 32 : case SPOOLSS_JOB_CONTROL_RESTART:
7853 : case SPOOLSS_JOB_CONTROL_RESUME:
7854 32 : errcode = print_job_resume(session_info, p->msg_ctx,
7855 : snum, r->in.job_id);
7856 32 : break;
7857 32 : case SPOOLSS_JOB_CONTROL_NOOP:
7858 32 : errcode = WERR_OK;
7859 32 : break;
7860 0 : default:
7861 0 : return WERR_INVALID_LEVEL;
7862 : }
7863 :
7864 402 : if (!W_ERROR_IS_OK(errcode)) {
7865 0 : return errcode;
7866 : }
7867 :
7868 402 : if (r->in.ctr == NULL) {
7869 370 : return errcode;
7870 : }
7871 :
7872 32 : switch (r->in.ctr->level) {
7873 32 : case 1:
7874 32 : errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7875 : lp_const_servicename(snum),
7876 : r->in.job_id,
7877 32 : r->in.ctr->info.info1);
7878 32 : break;
7879 0 : case 2:
7880 : case 3:
7881 : case 4:
7882 : default:
7883 0 : return WERR_INVALID_LEVEL;
7884 : }
7885 :
7886 32 : return errcode;
7887 : }
7888 :
7889 : /****************************************************************************
7890 : Enumerates all printer drivers by level and architecture.
7891 : ****************************************************************************/
7892 :
7893 460 : static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7894 : const struct auth_session_info *session_info,
7895 : struct messaging_context *msg_ctx,
7896 : const char *servername,
7897 : const char *architecture,
7898 : uint32_t level,
7899 : union spoolss_DriverInfo **info_p,
7900 : uint32_t *count_p)
7901 : {
7902 0 : int i;
7903 0 : uint32_t version;
7904 0 : struct spoolss_DriverInfo8 *driver;
7905 460 : union spoolss_DriverInfo *info = NULL;
7906 460 : uint32_t count = 0;
7907 460 : WERROR result = WERR_OK;
7908 0 : uint32_t num_drivers;
7909 0 : const char **drivers;
7910 0 : struct dcerpc_binding_handle *b;
7911 460 : TALLOC_CTX *tmp_ctx = NULL;
7912 :
7913 460 : *count_p = 0;
7914 460 : *info_p = NULL;
7915 :
7916 460 : tmp_ctx = talloc_new(mem_ctx);
7917 460 : if (!tmp_ctx) {
7918 0 : return WERR_NOT_ENOUGH_MEMORY;
7919 : }
7920 :
7921 460 : result = winreg_printer_binding_handle(tmp_ctx,
7922 : session_info,
7923 : msg_ctx,
7924 : &b);
7925 460 : if (!W_ERROR_IS_OK(result)) {
7926 0 : goto out;
7927 : }
7928 :
7929 2300 : for (version=0; version<DRIVER_MAX_VERSION; version++) {
7930 1840 : result = winreg_get_driver_list(tmp_ctx, b,
7931 : architecture, version,
7932 : &num_drivers, &drivers);
7933 1840 : if (!W_ERROR_IS_OK(result)) {
7934 0 : goto out;
7935 : }
7936 1840 : DEBUG(4, ("we have:[%d] drivers in environment"
7937 : " [%s] and version [%d]\n",
7938 : num_drivers, architecture, version));
7939 :
7940 1840 : if (num_drivers != 0) {
7941 0 : info = talloc_realloc(tmp_ctx, info,
7942 : union spoolss_DriverInfo,
7943 : count + num_drivers);
7944 0 : if (!info) {
7945 0 : DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7946 : "failed to enlarge driver info buffer!\n"));
7947 0 : result = WERR_NOT_ENOUGH_MEMORY;
7948 0 : goto out;
7949 : }
7950 : }
7951 :
7952 1840 : for (i = 0; i < num_drivers; i++) {
7953 0 : DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7954 :
7955 0 : result = winreg_get_driver(tmp_ctx, b,
7956 0 : architecture, drivers[i],
7957 : version, &driver);
7958 0 : if (!W_ERROR_IS_OK(result)) {
7959 0 : goto out;
7960 : }
7961 :
7962 0 : switch (level) {
7963 0 : case 1:
7964 0 : result = fill_printer_driver_info1(info, &info[count+i].info1,
7965 : driver, servername);
7966 0 : break;
7967 0 : case 2:
7968 0 : result = fill_printer_driver_info2(info, &info[count+i].info2,
7969 : driver, servername);
7970 0 : break;
7971 0 : case 3:
7972 0 : result = fill_printer_driver_info3(info, &info[count+i].info3,
7973 : driver, servername);
7974 0 : break;
7975 0 : case 4:
7976 0 : result = fill_printer_driver_info4(info, &info[count+i].info4,
7977 : driver, servername);
7978 0 : break;
7979 0 : case 5:
7980 0 : result = fill_printer_driver_info5(info, &info[count+i].info5,
7981 : driver, servername);
7982 0 : break;
7983 0 : case 6:
7984 0 : result = fill_printer_driver_info6(info, &info[count+i].info6,
7985 : driver, servername);
7986 0 : break;
7987 0 : case 8:
7988 0 : result = fill_printer_driver_info8(info, &info[count+i].info8,
7989 : driver, servername);
7990 0 : break;
7991 0 : default:
7992 0 : result = WERR_INVALID_LEVEL;
7993 0 : break;
7994 : }
7995 :
7996 0 : TALLOC_FREE(driver);
7997 :
7998 0 : if (!W_ERROR_IS_OK(result)) {
7999 0 : goto out;
8000 : }
8001 : }
8002 :
8003 1840 : count += num_drivers;
8004 1840 : TALLOC_FREE(drivers);
8005 : }
8006 :
8007 460 : out:
8008 460 : if (W_ERROR_IS_OK(result)) {
8009 460 : *info_p = talloc_move(mem_ctx, &info);
8010 460 : *count_p = count;
8011 : }
8012 :
8013 460 : talloc_free(tmp_ctx);
8014 460 : return result;
8015 : }
8016 :
8017 : /****************************************************************************
8018 : Enumerates all printer drivers by level.
8019 : ****************************************************************************/
8020 :
8021 108 : static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
8022 : const struct auth_session_info *session_info,
8023 : struct messaging_context *msg_ctx,
8024 : const char *servername,
8025 : const char *architecture,
8026 : uint32_t level,
8027 : union spoolss_DriverInfo **info_p,
8028 : uint32_t *count_p)
8029 : {
8030 0 : uint32_t a,i;
8031 108 : WERROR result = WERR_OK;
8032 :
8033 108 : if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
8034 :
8035 440 : for (a=0; archi_table[a].long_archi != NULL; a++) {
8036 :
8037 396 : union spoolss_DriverInfo *info = NULL;
8038 396 : uint32_t count = 0;
8039 :
8040 396 : result = enumprinterdrivers_level_by_architecture(mem_ctx,
8041 : session_info,
8042 : msg_ctx,
8043 : servername,
8044 396 : archi_table[a].long_archi,
8045 : level,
8046 : &info,
8047 : &count);
8048 396 : if (!W_ERROR_IS_OK(result)) {
8049 0 : continue;
8050 : }
8051 :
8052 396 : for (i=0; i < count; i++) {
8053 0 : ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
8054 : info[i], info_p, count_p);
8055 : }
8056 : }
8057 :
8058 44 : return result;
8059 : }
8060 :
8061 64 : return enumprinterdrivers_level_by_architecture(mem_ctx,
8062 : session_info,
8063 : msg_ctx,
8064 : servername,
8065 : architecture,
8066 : level,
8067 : info_p,
8068 : count_p);
8069 : }
8070 :
8071 : /****************************************************************
8072 : _spoolss_EnumPrinterDrivers
8073 : ****************************************************************/
8074 :
8075 108 : WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
8076 : struct spoolss_EnumPrinterDrivers *r)
8077 : {
8078 0 : const char *cservername;
8079 0 : WERROR result;
8080 :
8081 : /* that's an [in out] buffer */
8082 :
8083 108 : if (!r->in.buffer && (r->in.offered != 0)) {
8084 0 : return WERR_INVALID_PARAMETER;
8085 : }
8086 :
8087 108 : DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
8088 :
8089 108 : *r->out.needed = 0;
8090 108 : *r->out.count = 0;
8091 108 : *r->out.info = NULL;
8092 :
8093 108 : cservername = canon_servername(r->in.server);
8094 :
8095 108 : if (!is_myname_or_ipaddr(cservername)) {
8096 0 : return WERR_UNKNOWN_PRINTER_DRIVER;
8097 : }
8098 :
8099 108 : result = enumprinterdrivers_level(p->mem_ctx,
8100 : get_session_info_system(),
8101 : p->msg_ctx,
8102 : cservername,
8103 : r->in.environment,
8104 : r->in.level,
8105 : r->out.info,
8106 : r->out.count);
8107 108 : if (!W_ERROR_IS_OK(result)) {
8108 0 : return result;
8109 : }
8110 :
8111 108 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8112 : spoolss_EnumPrinterDrivers,
8113 : *r->out.info, r->in.level,
8114 : *r->out.count);
8115 108 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8116 108 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8117 :
8118 108 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8119 : }
8120 :
8121 : /****************************************************************
8122 : _spoolss_EnumForms
8123 : ****************************************************************/
8124 :
8125 560 : WERROR _spoolss_EnumForms(struct pipes_struct *p,
8126 : struct spoolss_EnumForms *r)
8127 : {
8128 0 : WERROR result;
8129 :
8130 560 : *r->out.count = 0;
8131 560 : *r->out.needed = 0;
8132 560 : *r->out.info = NULL;
8133 :
8134 : /* that's an [in out] buffer */
8135 :
8136 560 : if (!r->in.buffer && (r->in.offered != 0) ) {
8137 0 : return WERR_INVALID_PARAMETER;
8138 : }
8139 :
8140 560 : DEBUG(4,("_spoolss_EnumForms\n"));
8141 560 : DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
8142 560 : DEBUGADD(5,("Info level [%d]\n", r->in.level));
8143 :
8144 560 : switch (r->in.level) {
8145 536 : case 1:
8146 536 : result = winreg_printer_enumforms1_internal(p->mem_ctx,
8147 : get_session_info_system(),
8148 : p->msg_ctx,
8149 : r->out.count,
8150 : r->out.info);
8151 536 : break;
8152 24 : default:
8153 24 : result = WERR_INVALID_LEVEL;
8154 24 : break;
8155 : }
8156 :
8157 560 : if (!W_ERROR_IS_OK(result)) {
8158 24 : return result;
8159 : }
8160 :
8161 536 : if (*r->out.count == 0) {
8162 0 : return WERR_NO_MORE_ITEMS;
8163 : }
8164 :
8165 536 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8166 : spoolss_EnumForms,
8167 : *r->out.info, r->in.level,
8168 : *r->out.count);
8169 536 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8170 536 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8171 :
8172 536 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8173 : }
8174 :
8175 : /****************************************************************
8176 : _spoolss_GetForm
8177 : ****************************************************************/
8178 :
8179 5040 : WERROR _spoolss_GetForm(struct pipes_struct *p,
8180 : struct spoolss_GetForm *r)
8181 : {
8182 0 : WERROR result;
8183 :
8184 : /* that's an [in out] buffer */
8185 :
8186 5040 : if (!r->in.buffer && (r->in.offered != 0)) {
8187 0 : TALLOC_FREE(r->out.info);
8188 0 : return WERR_INVALID_PARAMETER;
8189 : }
8190 :
8191 5040 : DEBUG(4,("_spoolss_GetForm\n"));
8192 5040 : DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
8193 5040 : DEBUGADD(5,("Info level [%d]\n", r->in.level));
8194 :
8195 5040 : switch (r->in.level) {
8196 5040 : case 1:
8197 5040 : result = winreg_printer_getform1_internal(p->mem_ctx,
8198 : get_session_info_system(),
8199 : p->msg_ctx,
8200 : r->in.form_name,
8201 5040 : &r->out.info->info1);
8202 5040 : break;
8203 0 : default:
8204 0 : result = WERR_INVALID_LEVEL;
8205 0 : break;
8206 : }
8207 :
8208 5040 : if (!W_ERROR_IS_OK(result)) {
8209 0 : TALLOC_FREE(r->out.info);
8210 0 : return result;
8211 : }
8212 :
8213 5040 : *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
8214 : r->out.info, r->in.level);
8215 5040 : r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8216 :
8217 5040 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8218 : }
8219 :
8220 : /****************************************************************************
8221 : ****************************************************************************/
8222 :
8223 8 : static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
8224 : struct spoolss_PortInfo1 *r,
8225 : const char *name)
8226 : {
8227 8 : r->port_name = talloc_strdup(mem_ctx, name);
8228 8 : W_ERROR_HAVE_NO_MEMORY(r->port_name);
8229 :
8230 8 : return WERR_OK;
8231 : }
8232 :
8233 : /****************************************************************************
8234 : TODO: This probably needs distinguish between TCP/IP and Local ports
8235 : somehow.
8236 : ****************************************************************************/
8237 :
8238 16 : static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
8239 : struct spoolss_PortInfo2 *r,
8240 : const char *name)
8241 : {
8242 16 : r->port_name = talloc_strdup(mem_ctx, name);
8243 16 : W_ERROR_HAVE_NO_MEMORY(r->port_name);
8244 :
8245 16 : r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
8246 16 : W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8247 :
8248 16 : r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
8249 16 : W_ERROR_HAVE_NO_MEMORY(r->description);
8250 :
8251 16 : r->port_type = SPOOLSS_PORT_TYPE_WRITE;
8252 16 : r->reserved = 0;
8253 :
8254 16 : return WERR_OK;
8255 : }
8256 :
8257 :
8258 : /****************************************************************************
8259 : wrapper around the enum ports command
8260 : ****************************************************************************/
8261 :
8262 24 : static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
8263 : {
8264 0 : const struct loadparm_substitution *lp_sub =
8265 24 : loadparm_s3_global_substitution();
8266 24 : char *cmd = lp_enumports_command(talloc_tos(), lp_sub);
8267 24 : char **qlines = NULL;
8268 24 : char *command = NULL;
8269 0 : int numlines;
8270 0 : int ret;
8271 0 : int fd;
8272 :
8273 24 : *count = 0;
8274 24 : *lines = NULL;
8275 :
8276 : /* if no hook then just fill in the default port */
8277 :
8278 24 : if ( !*cmd ) {
8279 24 : if (!(qlines = talloc_array( NULL, char*, 2 ))) {
8280 0 : return WERR_NOT_ENOUGH_MEMORY;
8281 : }
8282 24 : if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
8283 0 : TALLOC_FREE(qlines);
8284 0 : return WERR_NOT_ENOUGH_MEMORY;
8285 : }
8286 24 : qlines[1] = NULL;
8287 24 : numlines = 1;
8288 : }
8289 : else {
8290 : /* we have a valid enumport command */
8291 :
8292 0 : command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
8293 0 : if (!command) {
8294 0 : return WERR_NOT_ENOUGH_MEMORY;
8295 : }
8296 :
8297 0 : DEBUG(10,("Running [%s]\n", command));
8298 0 : ret = smbrun(command, &fd, NULL);
8299 0 : DEBUG(10,("Returned [%d]\n", ret));
8300 0 : TALLOC_FREE(command);
8301 0 : if (ret != 0) {
8302 0 : if (fd != -1) {
8303 0 : close(fd);
8304 : }
8305 0 : return WERR_ACCESS_DENIED;
8306 : }
8307 :
8308 0 : numlines = 0;
8309 0 : qlines = fd_lines_load(fd, &numlines, 0, NULL);
8310 0 : DEBUGADD(10,("Lines returned = [%d]\n", numlines));
8311 0 : close(fd);
8312 : }
8313 :
8314 24 : *count = numlines;
8315 24 : *lines = qlines;
8316 :
8317 24 : return WERR_OK;
8318 : }
8319 :
8320 : /****************************************************************************
8321 : enumports level 1.
8322 : ****************************************************************************/
8323 :
8324 8 : static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
8325 : union spoolss_PortInfo **info_p,
8326 : uint32_t *count)
8327 : {
8328 8 : union spoolss_PortInfo *info = NULL;
8329 8 : int i=0;
8330 8 : WERROR result = WERR_OK;
8331 8 : char **qlines = NULL;
8332 8 : int numlines = 0;
8333 :
8334 8 : result = enumports_hook(talloc_tos(), &numlines, &qlines );
8335 8 : if (!W_ERROR_IS_OK(result)) {
8336 0 : goto out;
8337 : }
8338 :
8339 8 : if (numlines) {
8340 8 : info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8341 8 : if (!info) {
8342 0 : DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
8343 0 : result = WERR_NOT_ENOUGH_MEMORY;
8344 0 : goto out;
8345 : }
8346 :
8347 16 : for (i=0; i<numlines; i++) {
8348 8 : DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8349 8 : result = fill_port_1(info, &info[i].info1, qlines[i]);
8350 8 : if (!W_ERROR_IS_OK(result)) {
8351 0 : goto out;
8352 : }
8353 : }
8354 : }
8355 8 : TALLOC_FREE(qlines);
8356 :
8357 0 : out:
8358 8 : if (!W_ERROR_IS_OK(result)) {
8359 0 : TALLOC_FREE(info);
8360 0 : TALLOC_FREE(qlines);
8361 0 : *count = 0;
8362 0 : *info_p = NULL;
8363 0 : return result;
8364 : }
8365 :
8366 8 : *info_p = info;
8367 8 : *count = numlines;
8368 :
8369 8 : return WERR_OK;
8370 : }
8371 :
8372 : /****************************************************************************
8373 : enumports level 2.
8374 : ****************************************************************************/
8375 :
8376 16 : static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
8377 : union spoolss_PortInfo **info_p,
8378 : uint32_t *count)
8379 : {
8380 16 : union spoolss_PortInfo *info = NULL;
8381 16 : int i=0;
8382 16 : WERROR result = WERR_OK;
8383 16 : char **qlines = NULL;
8384 16 : int numlines = 0;
8385 :
8386 16 : result = enumports_hook(talloc_tos(), &numlines, &qlines );
8387 16 : if (!W_ERROR_IS_OK(result)) {
8388 0 : goto out;
8389 : }
8390 :
8391 16 : if (numlines) {
8392 16 : info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8393 16 : if (!info) {
8394 0 : DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
8395 0 : result = WERR_NOT_ENOUGH_MEMORY;
8396 0 : goto out;
8397 : }
8398 :
8399 32 : for (i=0; i<numlines; i++) {
8400 16 : DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8401 16 : result = fill_port_2(info, &info[i].info2, qlines[i]);
8402 16 : if (!W_ERROR_IS_OK(result)) {
8403 0 : goto out;
8404 : }
8405 : }
8406 : }
8407 16 : TALLOC_FREE(qlines);
8408 :
8409 0 : out:
8410 16 : if (!W_ERROR_IS_OK(result)) {
8411 0 : TALLOC_FREE(info);
8412 0 : TALLOC_FREE(qlines);
8413 0 : *count = 0;
8414 0 : *info_p = NULL;
8415 0 : return result;
8416 : }
8417 :
8418 16 : *info_p = info;
8419 16 : *count = numlines;
8420 :
8421 16 : return WERR_OK;
8422 : }
8423 :
8424 : /****************************************************************
8425 : _spoolss_EnumPorts
8426 : ****************************************************************/
8427 :
8428 24 : WERROR _spoolss_EnumPorts(struct pipes_struct *p,
8429 : struct spoolss_EnumPorts *r)
8430 : {
8431 0 : WERROR result;
8432 :
8433 : /* that's an [in out] buffer */
8434 :
8435 24 : if (!r->in.buffer && (r->in.offered != 0)) {
8436 0 : return WERR_INVALID_PARAMETER;
8437 : }
8438 :
8439 24 : DEBUG(4,("_spoolss_EnumPorts\n"));
8440 :
8441 24 : *r->out.count = 0;
8442 24 : *r->out.needed = 0;
8443 24 : *r->out.info = NULL;
8444 :
8445 24 : switch (r->in.level) {
8446 8 : case 1:
8447 8 : result = enumports_level_1(p->mem_ctx, r->out.info,
8448 : r->out.count);
8449 8 : break;
8450 16 : case 2:
8451 16 : result = enumports_level_2(p->mem_ctx, r->out.info,
8452 : r->out.count);
8453 16 : break;
8454 0 : default:
8455 0 : return WERR_INVALID_LEVEL;
8456 : }
8457 :
8458 24 : if (!W_ERROR_IS_OK(result)) {
8459 0 : return result;
8460 : }
8461 :
8462 24 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8463 : spoolss_EnumPorts,
8464 : *r->out.info, r->in.level,
8465 : *r->out.count);
8466 24 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8467 24 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8468 :
8469 24 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8470 : }
8471 :
8472 : /****************************************************************************
8473 : ****************************************************************************/
8474 :
8475 96 : static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
8476 : const char *server,
8477 : struct spoolss_SetPrinterInfoCtr *info_ctr,
8478 : struct spoolss_DeviceMode *devmode,
8479 : struct security_descriptor *secdesc,
8480 : struct spoolss_UserLevelCtr *user_ctr,
8481 : struct policy_handle *handle)
8482 : {
8483 96 : struct dcesrv_call_state *dce_call = p->dce_call;
8484 96 : struct dcesrv_connection *dcesrv_conn = dce_call->conn;
8485 0 : const struct tsocket_address *remote_address =
8486 96 : dcesrv_connection_get_remote_address(dcesrv_conn);
8487 0 : struct auth_session_info *session_info =
8488 96 : dcesrv_call_session_info(dce_call);
8489 96 : struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8490 96 : uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8491 0 : const struct loadparm_substitution *lp_sub =
8492 96 : loadparm_s3_global_substitution();
8493 0 : int snum;
8494 96 : WERROR err = WERR_OK;
8495 :
8496 : /* samba does not have a concept of local, non-shared printers yet, so
8497 : * make sure we always setup sharename - gd */
8498 96 : if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8499 96 : (info2->printername != NULL && info2->printername[0] != '\0')) {
8500 80 : DEBUG(5, ("spoolss_addprinterex_level_2: "
8501 : "no sharename has been set, setting printername %s as sharename\n",
8502 : info2->printername));
8503 80 : info2->sharename = info2->printername;
8504 : }
8505 :
8506 : /* check to see if the printer already exists */
8507 96 : if ((snum = print_queue_snum(info2->sharename)) != -1) {
8508 16 : DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8509 : info2->sharename));
8510 16 : return WERR_PRINTER_ALREADY_EXISTS;
8511 : }
8512 :
8513 80 : if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8514 80 : if ((snum = print_queue_snum(info2->printername)) != -1) {
8515 0 : DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8516 : info2->printername));
8517 0 : return WERR_PRINTER_ALREADY_EXISTS;
8518 : }
8519 : }
8520 :
8521 : /* validate printer info struct */
8522 80 : if (!info2->printername || strlen(info2->printername) == 0) {
8523 16 : return WERR_INVALID_PRINTER_NAME;
8524 : }
8525 64 : if (!info2->portname || strlen(info2->portname) == 0) {
8526 16 : return WERR_UNKNOWN_PORT;
8527 : }
8528 48 : if (!info2->drivername || strlen(info2->drivername) == 0) {
8529 16 : return WERR_UNKNOWN_PRINTER_DRIVER;
8530 : }
8531 32 : if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8532 16 : return WERR_UNKNOWN_PRINTPROCESSOR;
8533 : }
8534 :
8535 : /* FIXME!!! smbd should check to see if the driver is installed before
8536 : trying to add a printer like this --jerry */
8537 :
8538 16 : if (*lp_addprinter_command(talloc_tos(), lp_sub) ) {
8539 0 : char *raddr;
8540 :
8541 16 : raddr = tsocket_address_inet_addr_string(remote_address,
8542 : p->mem_ctx);
8543 16 : if (raddr == NULL) {
8544 0 : return WERR_NOT_ENOUGH_MEMORY;
8545 : }
8546 :
8547 16 : if ( !add_printer_hook(p->mem_ctx, session_info->security_token,
8548 : info2, raddr,
8549 : p->msg_ctx) ) {
8550 0 : return WERR_ACCESS_DENIED;
8551 : }
8552 : } else {
8553 0 : DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8554 : "smb.conf parameter \"addprinter command\" is defined. This "
8555 : "parameter must exist for this call to succeed\n",
8556 : info2->sharename ));
8557 : }
8558 :
8559 16 : if ((snum = print_queue_snum(info2->sharename)) == -1) {
8560 0 : return WERR_ACCESS_DENIED;
8561 : }
8562 :
8563 : /* you must be a printer admin to add a new printer */
8564 16 : if (!W_ERROR_IS_OK(print_access_check(session_info,
8565 : p->msg_ctx,
8566 : snum,
8567 : PRINTER_ACCESS_ADMINISTER))) {
8568 0 : return WERR_ACCESS_DENIED;
8569 : }
8570 :
8571 : /*
8572 : * Do sanity check on the requested changes for Samba.
8573 : */
8574 :
8575 16 : if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8576 0 : return WERR_INVALID_PARAMETER;
8577 : }
8578 :
8579 16 : if (devmode == NULL) {
8580 16 : info2_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
8581 : }
8582 :
8583 16 : err = update_dsspooler(p->mem_ctx,
8584 : get_session_info_system(),
8585 : p->msg_ctx,
8586 : 0,
8587 : info2,
8588 : NULL);
8589 16 : if (!W_ERROR_IS_OK(err)) {
8590 0 : return err;
8591 : }
8592 :
8593 16 : err = winreg_update_printer_internal(p->mem_ctx,
8594 : get_session_info_system(),
8595 : p->msg_ctx,
8596 : info2->sharename,
8597 : info2_mask,
8598 : info2,
8599 : devmode,
8600 : secdesc);
8601 16 : if (!W_ERROR_IS_OK(err)) {
8602 0 : return err;
8603 : }
8604 :
8605 16 : err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8606 16 : if (!W_ERROR_IS_OK(err)) {
8607 : /* Handle open failed - remove addition. */
8608 0 : ZERO_STRUCTP(handle);
8609 0 : return err;
8610 : }
8611 :
8612 16 : return WERR_OK;
8613 : }
8614 :
8615 : /****************************************************************
8616 : _spoolss_AddPrinterEx
8617 : ****************************************************************/
8618 :
8619 96 : WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8620 : struct spoolss_AddPrinterEx *r)
8621 : {
8622 96 : switch (r->in.info_ctr->level) {
8623 0 : case 1:
8624 : /* we don't handle yet */
8625 : /* but I know what to do ... */
8626 0 : return WERR_INVALID_LEVEL;
8627 96 : case 2:
8628 96 : return spoolss_addprinterex_level_2(p, r->in.server,
8629 : r->in.info_ctr,
8630 96 : r->in.devmode_ctr->devmode,
8631 96 : r->in.secdesc_ctr->sd,
8632 : r->in.userlevel_ctr,
8633 : r->out.handle);
8634 0 : default:
8635 0 : return WERR_INVALID_LEVEL;
8636 : }
8637 : }
8638 :
8639 : /****************************************************************
8640 : _spoolss_AddPrinter
8641 : ****************************************************************/
8642 :
8643 72 : WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8644 : struct spoolss_AddPrinter *r)
8645 : {
8646 0 : struct spoolss_AddPrinterEx a;
8647 0 : struct spoolss_UserLevelCtr userlevel_ctr;
8648 :
8649 72 : ZERO_STRUCT(userlevel_ctr);
8650 :
8651 72 : userlevel_ctr.level = 1;
8652 :
8653 72 : a.in.server = r->in.server;
8654 72 : a.in.info_ctr = r->in.info_ctr;
8655 72 : a.in.devmode_ctr = r->in.devmode_ctr;
8656 72 : a.in.secdesc_ctr = r->in.secdesc_ctr;
8657 72 : a.in.userlevel_ctr = &userlevel_ctr;
8658 72 : a.out.handle = r->out.handle;
8659 :
8660 72 : return _spoolss_AddPrinterEx(p, &a);
8661 : }
8662 :
8663 : /****************************************************************
8664 : _spoolss_AddPrinterDriverEx
8665 : ****************************************************************/
8666 :
8667 0 : WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8668 : struct spoolss_AddPrinterDriverEx *r)
8669 : {
8670 0 : struct dcesrv_call_state *dce_call = p->dce_call;
8671 0 : struct auth_session_info *session_info =
8672 0 : dcesrv_call_session_info(dce_call);
8673 0 : WERROR err = WERR_OK;
8674 0 : const char *driver_name = NULL;
8675 0 : const char *driver_directory = NULL;
8676 0 : uint32_t version;
8677 :
8678 : /*
8679 : * we only support the semantics of AddPrinterDriver()
8680 : * i.e. only copy files that are newer than existing ones
8681 : */
8682 :
8683 0 : if (r->in.flags == 0) {
8684 0 : return WERR_INVALID_PARAMETER;
8685 : }
8686 :
8687 0 : if (!(r->in.flags & APD_COPY_ALL_FILES) &&
8688 0 : !(r->in.flags & APD_COPY_NEW_FILES)) {
8689 0 : return WERR_ACCESS_DENIED;
8690 : }
8691 :
8692 : /* FIXME */
8693 0 : if (r->in.info_ctr->level != 3 &&
8694 0 : r->in.info_ctr->level != 6 &&
8695 0 : r->in.info_ctr->level != 8) {
8696 0 : DEBUG(0,("%s: level %d not yet implemented\n", __func__,
8697 : r->in.info_ctr->level));
8698 0 : return WERR_INVALID_LEVEL;
8699 : }
8700 :
8701 0 : DEBUG(5,("Cleaning driver's information\n"));
8702 0 : err = clean_up_driver_struct(p->mem_ctx,
8703 : session_info,
8704 0 : r->in.info_ctr,
8705 : r->in.flags,
8706 : &driver_directory);
8707 0 : if (!W_ERROR_IS_OK(err)) {
8708 0 : DBG_ERR("clean_up_driver_struct failed - %s\n",
8709 : win_errstr(err));
8710 0 : goto done;
8711 : }
8712 :
8713 0 : DEBUG(5,("Moving driver to final destination\n"));
8714 0 : err = move_driver_to_download_area(session_info,
8715 0 : r->in.info_ctr,
8716 : driver_directory);
8717 0 : if (!W_ERROR_IS_OK(err)) {
8718 0 : DBG_ERR("move_driver_to_download_area failed - %s\n",
8719 : win_errstr(err));
8720 0 : goto done;
8721 : }
8722 :
8723 0 : err = winreg_add_driver_internal(p->mem_ctx,
8724 : get_session_info_system(),
8725 : p->msg_ctx,
8726 : r->in.info_ctr,
8727 : &driver_name,
8728 : &version);
8729 0 : if (!W_ERROR_IS_OK(err)) {
8730 0 : DBG_ERR("winreg_add_driver_internal failed - %s\n",
8731 : win_errstr(err));
8732 0 : goto done;
8733 : }
8734 :
8735 : /*
8736 : * I think this is where the DrvUpgradePrinter() hook would be
8737 : * be called in a driver's interface DLL on a Windows NT 4.0/2k
8738 : * server. Right now, we just need to send ourselves a message
8739 : * to update each printer bound to this driver. --jerry
8740 : */
8741 :
8742 0 : if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8743 0 : DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8744 : __func__, driver_name));
8745 : }
8746 :
8747 0 : done:
8748 0 : return err;
8749 : }
8750 :
8751 : /****************************************************************
8752 : _spoolss_AddPrinterDriver
8753 : ****************************************************************/
8754 :
8755 0 : WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8756 : struct spoolss_AddPrinterDriver *r)
8757 : {
8758 0 : struct spoolss_AddPrinterDriverEx a;
8759 :
8760 0 : switch (r->in.info_ctr->level) {
8761 0 : case 2:
8762 : case 3:
8763 : case 4:
8764 : case 5:
8765 0 : break;
8766 0 : default:
8767 0 : return WERR_INVALID_LEVEL;
8768 : }
8769 :
8770 0 : a.in.servername = r->in.servername;
8771 0 : a.in.info_ctr = r->in.info_ctr;
8772 0 : a.in.flags = APD_COPY_NEW_FILES;
8773 :
8774 0 : return _spoolss_AddPrinterDriverEx(p, &a);
8775 : }
8776 :
8777 : /****************************************************************************
8778 : ****************************************************************************/
8779 :
8780 : struct _spoolss_paths {
8781 : int type;
8782 : const char *share;
8783 : const char *dir;
8784 : };
8785 :
8786 : enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8787 :
8788 : static const struct _spoolss_paths spoolss_paths[]= {
8789 : { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8790 : { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8791 : };
8792 :
8793 208 : static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8794 : const char *servername,
8795 : const char *environment,
8796 : int component,
8797 : char **path)
8798 : {
8799 208 : const char *pservername = NULL;
8800 0 : const char *long_archi;
8801 0 : const char *short_archi;
8802 :
8803 208 : *path = NULL;
8804 :
8805 : /* environment may be empty */
8806 208 : if (environment && strlen(environment)) {
8807 208 : long_archi = environment;
8808 : } else {
8809 0 : long_archi = lp_parm_const_string(GLOBAL_SECTION_SNUM,
8810 : "spoolss", "architecture",
8811 : GLOBAL_SPOOLSS_ARCHITECTURE);
8812 : }
8813 :
8814 : /* servername may be empty */
8815 208 : if (servername && strlen(servername)) {
8816 144 : pservername = canon_servername(servername);
8817 :
8818 144 : if (!is_myname_or_ipaddr(pservername)) {
8819 0 : return WERR_INVALID_PARAMETER;
8820 : }
8821 : }
8822 :
8823 208 : if (!(short_archi = get_short_archi(long_archi))) {
8824 0 : return WERR_INVALID_ENVIRONMENT;
8825 : }
8826 :
8827 208 : switch (component) {
8828 208 : case SPOOLSS_PRTPROCS_PATH:
8829 : case SPOOLSS_DRIVER_PATH:
8830 208 : if (pservername) {
8831 144 : *path = talloc_asprintf(mem_ctx,
8832 : "\\\\%s\\%s\\%s",
8833 : pservername,
8834 144 : spoolss_paths[component].share,
8835 : short_archi);
8836 : } else {
8837 64 : *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8838 : SPOOLSS_DEFAULT_SERVER_PATH,
8839 64 : spoolss_paths[component].dir,
8840 : short_archi);
8841 : }
8842 208 : break;
8843 0 : default:
8844 0 : return WERR_INVALID_PARAMETER;
8845 : }
8846 :
8847 208 : if (!*path) {
8848 0 : return WERR_NOT_ENOUGH_MEMORY;
8849 : }
8850 :
8851 208 : return WERR_OK;
8852 : }
8853 :
8854 : /****************************************************************************
8855 : ****************************************************************************/
8856 :
8857 168 : static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8858 : const char *servername,
8859 : const char *environment,
8860 : struct spoolss_DriverDirectoryInfo1 *r)
8861 : {
8862 0 : WERROR werr;
8863 168 : char *path = NULL;
8864 :
8865 168 : werr = compose_spoolss_server_path(mem_ctx,
8866 : servername,
8867 : environment,
8868 : SPOOLSS_DRIVER_PATH,
8869 : &path);
8870 168 : if (!W_ERROR_IS_OK(werr)) {
8871 0 : return werr;
8872 : }
8873 :
8874 168 : DEBUG(4,("printer driver directory: [%s]\n", path));
8875 :
8876 168 : r->directory_name = path;
8877 :
8878 168 : return WERR_OK;
8879 : }
8880 :
8881 : /****************************************************************
8882 : _spoolss_GetPrinterDriverDirectory
8883 : ****************************************************************/
8884 :
8885 168 : WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8886 : struct spoolss_GetPrinterDriverDirectory *r)
8887 : {
8888 0 : WERROR werror;
8889 :
8890 : /* that's an [in out] buffer */
8891 :
8892 168 : if (!r->in.buffer && (r->in.offered != 0)) {
8893 0 : TALLOC_FREE(r->out.info);
8894 0 : return WERR_INVALID_PARAMETER;
8895 : }
8896 :
8897 168 : DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8898 : r->in.level));
8899 :
8900 168 : *r->out.needed = 0;
8901 :
8902 : /* r->in.level is ignored */
8903 :
8904 168 : werror = getprinterdriverdir_level_1(p->mem_ctx,
8905 : r->in.server,
8906 : r->in.environment,
8907 168 : &r->out.info->info1);
8908 168 : if (!W_ERROR_IS_OK(werror)) {
8909 0 : TALLOC_FREE(r->out.info);
8910 0 : return werror;
8911 : }
8912 :
8913 168 : *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8914 : r->out.info, r->in.level);
8915 168 : r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8916 :
8917 168 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8918 : }
8919 :
8920 : /****************************************************************
8921 : _spoolss_EnumPrinterData
8922 : ****************************************************************/
8923 :
8924 152 : WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8925 : struct spoolss_EnumPrinterData *r)
8926 : {
8927 0 : WERROR result;
8928 0 : struct spoolss_EnumPrinterDataEx r2;
8929 0 : uint32_t count;
8930 152 : struct spoolss_PrinterEnumValues *info, *val = NULL;
8931 0 : uint32_t needed;
8932 :
8933 152 : r2.in.handle = r->in.handle;
8934 152 : r2.in.key_name = "PrinterDriverData";
8935 152 : r2.in.offered = 0;
8936 152 : r2.out.count = &count;
8937 152 : r2.out.info = &info;
8938 152 : r2.out.needed = &needed;
8939 :
8940 152 : result = _spoolss_EnumPrinterDataEx(p, &r2);
8941 152 : if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8942 112 : r2.in.offered = needed;
8943 112 : result = _spoolss_EnumPrinterDataEx(p, &r2);
8944 : }
8945 152 : if (!W_ERROR_IS_OK(result)) {
8946 0 : return result;
8947 : }
8948 :
8949 : /*
8950 : * The NT machine wants to know the biggest size of value and data
8951 : *
8952 : * cf: MSDN EnumPrinterData remark section
8953 : */
8954 :
8955 152 : if (!r->in.value_offered && !r->in.data_offered) {
8956 48 : uint32_t biggest_valuesize = 0;
8957 48 : uint32_t biggest_datasize = 0;
8958 0 : int i, name_length;
8959 :
8960 48 : DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8961 :
8962 132 : for (i=0; i<count; i++) {
8963 :
8964 84 : name_length = strlen(info[i].value_name);
8965 84 : if (strlen(info[i].value_name) > biggest_valuesize) {
8966 28 : biggest_valuesize = name_length;
8967 : }
8968 :
8969 84 : if (info[i].data_length > biggest_datasize) {
8970 28 : biggest_datasize = info[i].data_length;
8971 : }
8972 :
8973 84 : DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8974 : biggest_datasize));
8975 : }
8976 :
8977 : /* the value is an UNICODE string but real_value_size is the length
8978 : in bytes including the trailing 0 */
8979 :
8980 48 : *r->out.value_needed = 2 * (1 + biggest_valuesize);
8981 48 : *r->out.data_needed = biggest_datasize;
8982 :
8983 48 : DEBUG(6,("final values: [%d], [%d]\n",
8984 : *r->out.value_needed, *r->out.data_needed));
8985 :
8986 48 : return WERR_OK;
8987 : }
8988 :
8989 104 : if (r->in.enum_index < count) {
8990 84 : val = &info[r->in.enum_index];
8991 : }
8992 :
8993 104 : if (val == NULL) {
8994 : /* out_value should default to "" or else NT4 has
8995 : problems unmarshalling the response */
8996 :
8997 20 : if (r->in.value_offered) {
8998 20 : *r->out.value_needed = 1;
8999 20 : r->out.value_name = talloc_strdup(r, "");
9000 20 : if (!r->out.value_name) {
9001 0 : return WERR_NOT_ENOUGH_MEMORY;
9002 : }
9003 : } else {
9004 0 : r->out.value_name = NULL;
9005 0 : *r->out.value_needed = 0;
9006 : }
9007 :
9008 : /* the data is counted in bytes */
9009 :
9010 20 : *r->out.data_needed = r->in.data_offered;
9011 :
9012 20 : result = WERR_NO_MORE_ITEMS;
9013 : } else {
9014 : /*
9015 : * the value is:
9016 : * - counted in bytes in the request
9017 : * - counted in UNICODE chars in the max reply
9018 : * - counted in bytes in the real size
9019 : *
9020 : * take a pause *before* coding not *during* coding
9021 : */
9022 :
9023 : /* name */
9024 84 : if (r->in.value_offered) {
9025 84 : r->out.value_name = talloc_strdup(r, val->value_name);
9026 84 : if (!r->out.value_name) {
9027 0 : return WERR_NOT_ENOUGH_MEMORY;
9028 : }
9029 84 : *r->out.value_needed = val->value_name_len;
9030 : } else {
9031 0 : r->out.value_name = NULL;
9032 0 : *r->out.value_needed = 0;
9033 : }
9034 :
9035 : /* type */
9036 :
9037 84 : *r->out.type = val->type;
9038 :
9039 : /* data - counted in bytes */
9040 :
9041 : /*
9042 : * See the section "Dynamically Typed Query Parameters"
9043 : * in MS-RPRN.
9044 : */
9045 :
9046 84 : if (r->out.data && val->data && val->data->data &&
9047 84 : val->data_length && r->in.data_offered) {
9048 84 : memcpy(r->out.data, val->data->data,
9049 84 : MIN(val->data_length,r->in.data_offered));
9050 : }
9051 :
9052 84 : *r->out.data_needed = val->data_length;
9053 :
9054 84 : result = WERR_OK;
9055 : }
9056 :
9057 104 : return result;
9058 : }
9059 :
9060 : /****************************************************************
9061 : _spoolss_SetPrinterData
9062 : ****************************************************************/
9063 :
9064 168 : WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
9065 : struct spoolss_SetPrinterData *r)
9066 : {
9067 0 : struct spoolss_SetPrinterDataEx r2;
9068 :
9069 168 : r2.in.handle = r->in.handle;
9070 168 : r2.in.key_name = "PrinterDriverData";
9071 168 : r2.in.value_name = r->in.value_name;
9072 168 : r2.in.type = r->in.type;
9073 168 : r2.in.data = r->in.data;
9074 168 : r2.in.offered = r->in.offered;
9075 :
9076 168 : return _spoolss_SetPrinterDataEx(p, &r2);
9077 : }
9078 :
9079 : /****************************************************************
9080 : _spoolss_ResetPrinter
9081 : ****************************************************************/
9082 :
9083 0 : WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
9084 : struct spoolss_ResetPrinter *r)
9085 : {
9086 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9087 0 : int snum;
9088 :
9089 0 : DEBUG(5,("_spoolss_ResetPrinter\n"));
9090 :
9091 : /*
9092 : * All we do is to check to see if the handle and queue is valid.
9093 : * This call really doesn't mean anything to us because we only
9094 : * support RAW printing. --jerry
9095 : */
9096 :
9097 0 : if (!Printer) {
9098 0 : DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
9099 : OUR_HANDLE(r->in.handle)));
9100 0 : return WERR_INVALID_HANDLE;
9101 : }
9102 :
9103 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9104 0 : return WERR_INVALID_HANDLE;
9105 :
9106 :
9107 : /* blindly return success */
9108 0 : return WERR_OK;
9109 : }
9110 :
9111 : /****************************************************************
9112 : _spoolss_DeletePrinterData
9113 : ****************************************************************/
9114 :
9115 168 : WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
9116 : struct spoolss_DeletePrinterData *r)
9117 : {
9118 0 : struct spoolss_DeletePrinterDataEx r2;
9119 :
9120 168 : r2.in.handle = r->in.handle;
9121 168 : r2.in.key_name = "PrinterDriverData";
9122 168 : r2.in.value_name = r->in.value_name;
9123 :
9124 168 : return _spoolss_DeletePrinterDataEx(p, &r2);
9125 : }
9126 :
9127 : /****************************************************************
9128 : _spoolss_AddForm
9129 : ****************************************************************/
9130 :
9131 576 : WERROR _spoolss_AddForm(struct pipes_struct *p,
9132 : struct spoolss_AddForm *r)
9133 : {
9134 576 : struct dcesrv_call_state *dce_call = p->dce_call;
9135 0 : struct auth_session_info *session_info =
9136 576 : dcesrv_call_session_info(dce_call);
9137 0 : struct spoolss_AddFormInfo1 *form;
9138 576 : int snum = -1;
9139 576 : WERROR status = WERR_OK;
9140 576 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9141 0 : struct dcerpc_binding_handle *b;
9142 576 : TALLOC_CTX *tmp_ctx = NULL;
9143 :
9144 576 : DEBUG(5,("_spoolss_AddForm\n"));
9145 :
9146 576 : if (!Printer) {
9147 0 : DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
9148 : OUR_HANDLE(r->in.handle)));
9149 0 : return WERR_INVALID_HANDLE;
9150 : }
9151 :
9152 : /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
9153 : and not a printer admin, then fail */
9154 :
9155 576 : if ((session_info->unix_token->uid != sec_initial_uid()) &&
9156 0 : !security_token_has_privilege(session_info->security_token,
9157 : SEC_PRIV_PRINT_OPERATOR)) {
9158 0 : DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
9159 0 : return WERR_ACCESS_DENIED;
9160 : }
9161 :
9162 576 : if (r->in.info_ctr->level != 1) {
9163 0 : return WERR_INVALID_LEVEL;
9164 : }
9165 :
9166 576 : form = r->in.info_ctr->info.info1;
9167 576 : if (!form) {
9168 0 : return WERR_INVALID_PARAMETER;
9169 : }
9170 :
9171 576 : switch (form->flags) {
9172 480 : case SPOOLSS_FORM_USER:
9173 : case SPOOLSS_FORM_BUILTIN:
9174 : case SPOOLSS_FORM_PRINTER:
9175 480 : break;
9176 96 : default:
9177 96 : return WERR_INVALID_PARAMETER;
9178 : }
9179 :
9180 480 : tmp_ctx = talloc_new(p->mem_ctx);
9181 480 : if (!tmp_ctx) {
9182 0 : return WERR_NOT_ENOUGH_MEMORY;
9183 : }
9184 :
9185 480 : status = winreg_printer_binding_handle(tmp_ctx,
9186 : get_session_info_system(),
9187 : p->msg_ctx,
9188 : &b);
9189 480 : if (!W_ERROR_IS_OK(status)) {
9190 0 : goto done;
9191 : }
9192 :
9193 480 : status = winreg_printer_addform1(tmp_ctx, b, form);
9194 480 : if (!W_ERROR_IS_OK(status)) {
9195 384 : goto done;
9196 : }
9197 :
9198 : /*
9199 : * ChangeID must always be set if this is a printer
9200 : */
9201 96 : if (Printer->printer_type == SPLHND_PRINTER) {
9202 80 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9203 0 : status = WERR_INVALID_HANDLE;
9204 0 : goto done;
9205 : }
9206 :
9207 80 : status = winreg_printer_update_changeid(tmp_ctx, b,
9208 : lp_const_servicename(snum));
9209 : }
9210 :
9211 16 : done:
9212 480 : talloc_free(tmp_ctx);
9213 480 : return status;
9214 : }
9215 :
9216 : /****************************************************************
9217 : _spoolss_DeleteForm
9218 : ****************************************************************/
9219 :
9220 384 : WERROR _spoolss_DeleteForm(struct pipes_struct *p,
9221 : struct spoolss_DeleteForm *r)
9222 : {
9223 384 : struct dcesrv_call_state *dce_call = p->dce_call;
9224 0 : struct auth_session_info *session_info =
9225 384 : dcesrv_call_session_info(dce_call);
9226 384 : const char *form_name = r->in.form_name;
9227 384 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9228 384 : int snum = -1;
9229 384 : WERROR status = WERR_OK;
9230 0 : struct dcerpc_binding_handle *b;
9231 384 : TALLOC_CTX *tmp_ctx = NULL;
9232 :
9233 384 : DEBUG(5,("_spoolss_DeleteForm\n"));
9234 :
9235 384 : if (!Printer) {
9236 0 : DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
9237 : OUR_HANDLE(r->in.handle)));
9238 0 : return WERR_INVALID_HANDLE;
9239 : }
9240 :
9241 384 : if ((session_info->unix_token->uid != sec_initial_uid()) &&
9242 0 : !security_token_has_privilege(session_info->security_token,
9243 : SEC_PRIV_PRINT_OPERATOR)) {
9244 0 : DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
9245 0 : return WERR_ACCESS_DENIED;
9246 : }
9247 :
9248 384 : tmp_ctx = talloc_new(p->mem_ctx);
9249 384 : if (!tmp_ctx) {
9250 0 : return WERR_NOT_ENOUGH_MEMORY;
9251 : }
9252 :
9253 384 : status = winreg_printer_binding_handle(tmp_ctx,
9254 : get_session_info_system(),
9255 : p->msg_ctx,
9256 : &b);
9257 384 : if (!W_ERROR_IS_OK(status)) {
9258 0 : goto done;
9259 : }
9260 :
9261 384 : status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
9262 384 : if (!W_ERROR_IS_OK(status)) {
9263 288 : goto done;
9264 : }
9265 :
9266 : /*
9267 : * ChangeID must always be set if this is a printer
9268 : */
9269 96 : if (Printer->printer_type == SPLHND_PRINTER) {
9270 80 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9271 0 : status = WERR_INVALID_HANDLE;
9272 0 : goto done;
9273 : }
9274 :
9275 80 : status = winreg_printer_update_changeid(tmp_ctx, b,
9276 : lp_const_servicename(snum));
9277 : }
9278 :
9279 16 : done:
9280 384 : talloc_free(tmp_ctx);
9281 384 : return status;
9282 : }
9283 :
9284 : /****************************************************************
9285 : _spoolss_SetForm
9286 : ****************************************************************/
9287 :
9288 80 : WERROR _spoolss_SetForm(struct pipes_struct *p,
9289 : struct spoolss_SetForm *r)
9290 : {
9291 80 : struct dcesrv_call_state *dce_call = p->dce_call;
9292 0 : struct auth_session_info *session_info =
9293 80 : dcesrv_call_session_info(dce_call);
9294 0 : struct spoolss_AddFormInfo1 *form;
9295 80 : const char *form_name = r->in.form_name;
9296 80 : int snum = -1;
9297 80 : WERROR status = WERR_OK;
9298 0 : struct dcerpc_binding_handle *b;
9299 80 : TALLOC_CTX *tmp_ctx = NULL;
9300 :
9301 80 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9302 :
9303 80 : DEBUG(5,("_spoolss_SetForm\n"));
9304 :
9305 80 : if (!Printer) {
9306 0 : DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
9307 : OUR_HANDLE(r->in.handle)));
9308 0 : return WERR_INVALID_HANDLE;
9309 : }
9310 :
9311 : /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
9312 : and not a printer admin, then fail */
9313 :
9314 80 : if ((session_info->unix_token->uid != sec_initial_uid()) &&
9315 0 : !security_token_has_privilege(session_info->security_token,
9316 : SEC_PRIV_PRINT_OPERATOR)) {
9317 0 : DEBUG(2,("_spoolss_SetForm: denied by insufficient permissions.\n"));
9318 0 : return WERR_ACCESS_DENIED;
9319 : }
9320 :
9321 80 : if (r->in.info_ctr->level != 1) {
9322 0 : return WERR_INVALID_LEVEL;
9323 : }
9324 :
9325 80 : form = r->in.info_ctr->info.info1;
9326 80 : if (!form) {
9327 0 : return WERR_INVALID_PARAMETER;
9328 : }
9329 :
9330 80 : tmp_ctx = talloc_new(p->mem_ctx);
9331 80 : if (!tmp_ctx) {
9332 0 : return WERR_NOT_ENOUGH_MEMORY;
9333 : }
9334 :
9335 80 : status = winreg_printer_binding_handle(tmp_ctx,
9336 : get_session_info_system(),
9337 : p->msg_ctx,
9338 : &b);
9339 80 : if (!W_ERROR_IS_OK(status)) {
9340 0 : goto done;
9341 : }
9342 :
9343 80 : status = winreg_printer_setform1(tmp_ctx, b,
9344 : form_name,
9345 : form);
9346 80 : if (!W_ERROR_IS_OK(status)) {
9347 0 : goto done;
9348 : }
9349 :
9350 : /*
9351 : * ChangeID must always be set if this is a printer
9352 : */
9353 80 : if (Printer->printer_type == SPLHND_PRINTER) {
9354 80 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9355 0 : status = WERR_INVALID_HANDLE;
9356 0 : goto done;
9357 : }
9358 :
9359 80 : status = winreg_printer_update_changeid(tmp_ctx, b,
9360 : lp_const_servicename(snum));
9361 : }
9362 :
9363 0 : done:
9364 80 : talloc_free(tmp_ctx);
9365 80 : return status;
9366 : }
9367 :
9368 : /****************************************************************************
9369 : fill_print_processor1
9370 : ****************************************************************************/
9371 :
9372 24 : static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
9373 : struct spoolss_PrintProcessorInfo1 *r,
9374 : const char *print_processor_name)
9375 : {
9376 24 : r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
9377 24 : W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
9378 :
9379 24 : return WERR_OK;
9380 : }
9381 :
9382 : /****************************************************************************
9383 : enumprintprocessors level 1.
9384 : ****************************************************************************/
9385 :
9386 24 : static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
9387 : union spoolss_PrintProcessorInfo **info_p,
9388 : uint32_t *count)
9389 : {
9390 0 : union spoolss_PrintProcessorInfo *info;
9391 0 : WERROR result;
9392 :
9393 24 : info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
9394 24 : W_ERROR_HAVE_NO_MEMORY(info);
9395 :
9396 24 : *count = 1;
9397 :
9398 24 : result = fill_print_processor1(info, &info[0].info1, "winprint");
9399 24 : if (!W_ERROR_IS_OK(result)) {
9400 0 : goto out;
9401 : }
9402 :
9403 24 : out:
9404 24 : if (!W_ERROR_IS_OK(result)) {
9405 0 : TALLOC_FREE(info);
9406 0 : *count = 0;
9407 0 : return result;
9408 : }
9409 :
9410 24 : *info_p = info;
9411 :
9412 24 : return WERR_OK;
9413 : }
9414 :
9415 : /****************************************************************
9416 : _spoolss_EnumPrintProcessors
9417 : ****************************************************************/
9418 :
9419 48 : WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
9420 : struct spoolss_EnumPrintProcessors *r)
9421 : {
9422 0 : WERROR result;
9423 :
9424 : /* that's an [in out] buffer */
9425 :
9426 48 : if (!r->in.buffer && (r->in.offered != 0)) {
9427 0 : return WERR_INVALID_PARAMETER;
9428 : }
9429 :
9430 48 : DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
9431 :
9432 : /*
9433 : * Enumerate the print processors ...
9434 : *
9435 : * Just reply with "winprint", to keep NT happy
9436 : * and I can use my nice printer checker.
9437 : */
9438 :
9439 48 : *r->out.count = 0;
9440 48 : *r->out.needed = 0;
9441 48 : *r->out.info = NULL;
9442 :
9443 48 : if (!get_short_archi(r->in.environment)) {
9444 4 : return WERR_INVALID_ENVIRONMENT;
9445 : }
9446 :
9447 44 : switch (r->in.level) {
9448 24 : case 1:
9449 24 : result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
9450 : r->out.count);
9451 24 : break;
9452 20 : default:
9453 20 : return WERR_INVALID_LEVEL;
9454 : }
9455 :
9456 24 : if (!W_ERROR_IS_OK(result)) {
9457 0 : return result;
9458 : }
9459 :
9460 24 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9461 : spoolss_EnumPrintProcessors,
9462 : *r->out.info, r->in.level,
9463 : *r->out.count);
9464 24 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9465 24 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9466 :
9467 24 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9468 : }
9469 :
9470 : /****************************************************************************
9471 : fill_printprocdatatype1
9472 : ****************************************************************************/
9473 :
9474 16 : static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
9475 : struct spoolss_PrintProcDataTypesInfo1 *r,
9476 : const char *name_array)
9477 : {
9478 16 : r->name_array = talloc_strdup(mem_ctx, name_array);
9479 16 : W_ERROR_HAVE_NO_MEMORY(r->name_array);
9480 :
9481 16 : return WERR_OK;
9482 : }
9483 :
9484 : /****************************************************************************
9485 : enumprintprocdatatypes level 1.
9486 : ****************************************************************************/
9487 :
9488 16 : static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
9489 : union spoolss_PrintProcDataTypesInfo **info_p,
9490 : uint32_t *count)
9491 : {
9492 0 : WERROR result;
9493 0 : union spoolss_PrintProcDataTypesInfo *info;
9494 :
9495 16 : info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
9496 16 : W_ERROR_HAVE_NO_MEMORY(info);
9497 :
9498 16 : *count = 1;
9499 :
9500 16 : result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9501 16 : if (!W_ERROR_IS_OK(result)) {
9502 0 : goto out;
9503 : }
9504 :
9505 16 : out:
9506 16 : if (!W_ERROR_IS_OK(result)) {
9507 0 : TALLOC_FREE(info);
9508 0 : *count = 0;
9509 0 : return result;
9510 : }
9511 :
9512 16 : *info_p = info;
9513 :
9514 16 : return WERR_OK;
9515 : }
9516 :
9517 : /****************************************************************
9518 : _spoolss_EnumPrintProcessorDataTypes
9519 : ****************************************************************/
9520 :
9521 44 : WERROR _spoolss_EnumPrintProcessorDataTypes(struct pipes_struct *p,
9522 : struct spoolss_EnumPrintProcessorDataTypes *r)
9523 : {
9524 0 : WERROR result;
9525 :
9526 : /* that's an [in out] buffer */
9527 :
9528 44 : if (!r->in.buffer && (r->in.offered != 0)) {
9529 0 : return WERR_INVALID_PARAMETER;
9530 : }
9531 :
9532 44 : DEBUG(5,("_spoolss_EnumPrintProcessorDataTypes\n"));
9533 :
9534 44 : *r->out.count = 0;
9535 44 : *r->out.needed = 0;
9536 44 : *r->out.info = NULL;
9537 :
9538 44 : if (r->in.print_processor_name == NULL ||
9539 40 : !strequal(r->in.print_processor_name, "winprint")) {
9540 8 : return WERR_UNKNOWN_PRINTPROCESSOR;
9541 : }
9542 :
9543 36 : switch (r->in.level) {
9544 16 : case 1:
9545 16 : result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9546 : r->out.count);
9547 16 : break;
9548 20 : default:
9549 20 : return WERR_INVALID_LEVEL;
9550 : }
9551 :
9552 16 : if (!W_ERROR_IS_OK(result)) {
9553 0 : return result;
9554 : }
9555 :
9556 16 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9557 : spoolss_EnumPrintProcessorDataTypes,
9558 : *r->out.info, r->in.level,
9559 : *r->out.count);
9560 16 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9561 16 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9562 :
9563 16 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9564 : }
9565 :
9566 : /****************************************************************************
9567 : fill_monitor_1
9568 : ****************************************************************************/
9569 :
9570 16 : static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9571 : struct spoolss_MonitorInfo1 *r,
9572 : const char *monitor_name)
9573 : {
9574 16 : r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9575 16 : W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9576 :
9577 16 : return WERR_OK;
9578 : }
9579 :
9580 : /****************************************************************************
9581 : fill_monitor_2
9582 : ****************************************************************************/
9583 :
9584 16 : static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9585 : struct spoolss_MonitorInfo2 *r,
9586 : const char *monitor_name,
9587 : const char *environment,
9588 : const char *dll_name)
9589 : {
9590 16 : r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9591 16 : W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9592 16 : r->environment = talloc_strdup(mem_ctx, environment);
9593 16 : W_ERROR_HAVE_NO_MEMORY(r->environment);
9594 16 : r->dll_name = talloc_strdup(mem_ctx, dll_name);
9595 16 : W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9596 :
9597 16 : return WERR_OK;
9598 : }
9599 :
9600 : /****************************************************************************
9601 : enumprintmonitors level 1.
9602 : ****************************************************************************/
9603 :
9604 8 : static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9605 : union spoolss_MonitorInfo **info_p,
9606 : uint32_t *count)
9607 : {
9608 0 : union spoolss_MonitorInfo *info;
9609 8 : WERROR result = WERR_OK;
9610 :
9611 8 : info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9612 8 : W_ERROR_HAVE_NO_MEMORY(info);
9613 :
9614 8 : *count = 2;
9615 :
9616 8 : result = fill_monitor_1(info, &info[0].info1,
9617 : SPL_LOCAL_PORT);
9618 8 : if (!W_ERROR_IS_OK(result)) {
9619 0 : goto out;
9620 : }
9621 :
9622 8 : result = fill_monitor_1(info, &info[1].info1,
9623 : SPL_TCPIP_PORT);
9624 8 : if (!W_ERROR_IS_OK(result)) {
9625 0 : goto out;
9626 : }
9627 :
9628 8 : out:
9629 8 : if (!W_ERROR_IS_OK(result)) {
9630 0 : TALLOC_FREE(info);
9631 0 : *count = 0;
9632 0 : return result;
9633 : }
9634 :
9635 8 : *info_p = info;
9636 :
9637 8 : return WERR_OK;
9638 : }
9639 :
9640 : /****************************************************************************
9641 : enumprintmonitors level 2.
9642 : ****************************************************************************/
9643 :
9644 8 : static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9645 : union spoolss_MonitorInfo **info_p,
9646 : uint32_t *count)
9647 : {
9648 0 : union spoolss_MonitorInfo *info;
9649 8 : WERROR result = WERR_OK;
9650 0 : const char *architecture;
9651 :
9652 8 : info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9653 8 : W_ERROR_HAVE_NO_MEMORY(info);
9654 :
9655 8 : *count = 2;
9656 :
9657 8 : architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
9658 : "spoolss",
9659 : "architecture",
9660 : GLOBAL_SPOOLSS_ARCHITECTURE);
9661 :
9662 8 : result = fill_monitor_2(info, &info[0].info2,
9663 : SPL_LOCAL_PORT,
9664 : architecture,
9665 : "localmon.dll");
9666 8 : if (!W_ERROR_IS_OK(result)) {
9667 0 : goto out;
9668 : }
9669 :
9670 8 : result = fill_monitor_2(info, &info[1].info2,
9671 : SPL_TCPIP_PORT,
9672 : architecture,
9673 : "tcpmon.dll");
9674 8 : if (!W_ERROR_IS_OK(result)) {
9675 0 : goto out;
9676 : }
9677 :
9678 8 : out:
9679 8 : if (!W_ERROR_IS_OK(result)) {
9680 0 : TALLOC_FREE(info);
9681 0 : *count = 0;
9682 0 : return result;
9683 : }
9684 :
9685 8 : *info_p = info;
9686 :
9687 8 : return WERR_OK;
9688 : }
9689 :
9690 : /****************************************************************
9691 : _spoolss_EnumMonitors
9692 : ****************************************************************/
9693 :
9694 16 : WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9695 : struct spoolss_EnumMonitors *r)
9696 : {
9697 0 : WERROR result;
9698 :
9699 : /* that's an [in out] buffer */
9700 :
9701 16 : if (!r->in.buffer && (r->in.offered != 0)) {
9702 0 : return WERR_INVALID_PARAMETER;
9703 : }
9704 :
9705 16 : DEBUG(5,("_spoolss_EnumMonitors\n"));
9706 :
9707 : /*
9708 : * Enumerate the print monitors ...
9709 : *
9710 : * Just reply with "Local Port", to keep NT happy
9711 : * and I can use my nice printer checker.
9712 : */
9713 :
9714 16 : *r->out.count = 0;
9715 16 : *r->out.needed = 0;
9716 16 : *r->out.info = NULL;
9717 :
9718 16 : switch (r->in.level) {
9719 8 : case 1:
9720 8 : result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9721 : r->out.count);
9722 8 : break;
9723 8 : case 2:
9724 8 : result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9725 : r->out.count);
9726 8 : break;
9727 0 : default:
9728 0 : return WERR_INVALID_LEVEL;
9729 : }
9730 :
9731 16 : if (!W_ERROR_IS_OK(result)) {
9732 0 : return result;
9733 : }
9734 :
9735 16 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9736 : spoolss_EnumMonitors,
9737 : *r->out.info, r->in.level,
9738 : *r->out.count);
9739 16 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9740 16 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9741 :
9742 16 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9743 : }
9744 :
9745 : /****************************************************************************
9746 : ****************************************************************************/
9747 :
9748 128 : static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9749 : const print_queue_struct *queue,
9750 : int count, int snum,
9751 : struct spoolss_PrinterInfo2 *pinfo2,
9752 : uint32_t jobid,
9753 : int sysjob,
9754 : struct spoolss_JobInfo1 *r)
9755 : {
9756 128 : int i = 0;
9757 128 : bool found = false;
9758 :
9759 576 : for (i=0; i<count; i++) {
9760 576 : if (queue[i].sysjob == sysjob) {
9761 128 : found = true;
9762 128 : break;
9763 : }
9764 : }
9765 :
9766 128 : if (found == false) {
9767 : /* NT treats not found as bad param... yet another bad choice */
9768 0 : return WERR_INVALID_PARAMETER;
9769 : }
9770 :
9771 128 : return fill_job_info1(mem_ctx,
9772 : r,
9773 128 : &queue[i],
9774 : jobid,
9775 : i,
9776 : snum,
9777 : pinfo2);
9778 : }
9779 :
9780 : /****************************************************************************
9781 : ****************************************************************************/
9782 :
9783 0 : static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9784 : const print_queue_struct *queue,
9785 : int count, int snum,
9786 : struct spoolss_PrinterInfo2 *pinfo2,
9787 : uint32_t jobid,
9788 : int sysjob,
9789 : struct spoolss_JobInfo2 *r)
9790 : {
9791 0 : int i = 0;
9792 0 : bool found = false;
9793 0 : struct spoolss_DeviceMode *devmode;
9794 0 : WERROR result;
9795 :
9796 0 : for (i=0; i<count; i++) {
9797 0 : if (queue[i].sysjob == sysjob) {
9798 0 : found = true;
9799 0 : break;
9800 : }
9801 : }
9802 :
9803 0 : if (found == false) {
9804 : /* NT treats not found as bad param... yet another bad
9805 : choice */
9806 0 : return WERR_INVALID_PARAMETER;
9807 : }
9808 :
9809 : /*
9810 : * if the print job does not have a DEVMODE associated with it,
9811 : * just use the one for the printer. A NULL devicemode is not
9812 : * a failure condition
9813 : */
9814 :
9815 0 : devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9816 0 : if (!devmode) {
9817 0 : result = spoolss_create_default_devmode(mem_ctx,
9818 : pinfo2->printername,
9819 : &devmode);
9820 0 : if (!W_ERROR_IS_OK(result)) {
9821 0 : DEBUG(3, ("Can't proceed w/o a devmode!\n"));
9822 0 : return result;
9823 : }
9824 : }
9825 :
9826 0 : return fill_job_info2(mem_ctx,
9827 : r,
9828 0 : &queue[i],
9829 : jobid,
9830 : i,
9831 : snum,
9832 : pinfo2,
9833 : devmode);
9834 : }
9835 :
9836 : /****************************************************************
9837 : _spoolss_GetJob
9838 : ****************************************************************/
9839 :
9840 2048 : WERROR _spoolss_GetJob(struct pipes_struct *p,
9841 : struct spoolss_GetJob *r)
9842 : {
9843 2048 : WERROR result = WERR_OK;
9844 2048 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9845 0 : const char *svc_name;
9846 0 : int sysjob;
9847 0 : int snum;
9848 0 : int count;
9849 0 : struct tdb_print_db *pdb;
9850 2048 : print_queue_struct *queue = NULL;
9851 0 : print_status_struct prt_status;
9852 :
9853 : /* that's an [in out] buffer */
9854 :
9855 2048 : if (!r->in.buffer && (r->in.offered != 0)) {
9856 0 : result = WERR_INVALID_PARAMETER;
9857 0 : goto err_jinfo_free;
9858 : }
9859 :
9860 2048 : DEBUG(5,("_spoolss_GetJob\n"));
9861 :
9862 2048 : *r->out.needed = 0;
9863 :
9864 2048 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9865 0 : result = WERR_INVALID_HANDLE;
9866 0 : goto err_jinfo_free;
9867 : }
9868 :
9869 2048 : svc_name = lp_const_servicename(snum);
9870 2048 : if (svc_name == NULL) {
9871 0 : result = WERR_INVALID_PARAMETER;
9872 0 : goto err_jinfo_free;
9873 : }
9874 :
9875 2048 : result = winreg_get_printer_internal(p->mem_ctx,
9876 : get_session_info_system(),
9877 : p->msg_ctx,
9878 : svc_name,
9879 : &pinfo2);
9880 2048 : if (!W_ERROR_IS_OK(result)) {
9881 0 : goto err_jinfo_free;
9882 : }
9883 :
9884 2048 : pdb = get_print_db_byname(svc_name);
9885 2048 : if (pdb == NULL) {
9886 0 : DEBUG(3, ("failed to get print db for svc %s\n", svc_name));
9887 0 : result = WERR_INVALID_PARAMETER;
9888 0 : goto err_pinfo_free;
9889 : }
9890 :
9891 2048 : sysjob = jobid_to_sysjob_pdb(pdb, r->in.job_id);
9892 2048 : release_print_db(pdb);
9893 2048 : if (sysjob == -1) {
9894 1920 : DEBUG(3, ("no sysjob for spoolss jobid %u\n", r->in.job_id));
9895 1920 : result = WERR_INVALID_PARAMETER;
9896 1920 : goto err_pinfo_free;
9897 : }
9898 :
9899 128 : count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9900 :
9901 128 : DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9902 : count, prt_status.status, prt_status.message));
9903 :
9904 128 : switch (r->in.level) {
9905 128 : case 1:
9906 128 : result = getjob_level_1(p->mem_ctx,
9907 : queue, count, snum, pinfo2,
9908 : r->in.job_id, sysjob,
9909 128 : &r->out.info->info1);
9910 128 : break;
9911 0 : case 2:
9912 0 : result = getjob_level_2(p->mem_ctx,
9913 : queue, count, snum, pinfo2,
9914 : r->in.job_id, sysjob,
9915 0 : &r->out.info->info2);
9916 0 : break;
9917 0 : default:
9918 0 : result = WERR_INVALID_LEVEL;
9919 0 : break;
9920 : }
9921 :
9922 128 : SAFE_FREE(queue);
9923 128 : TALLOC_FREE(pinfo2);
9924 :
9925 128 : if (!W_ERROR_IS_OK(result)) {
9926 0 : goto err_jinfo_free;
9927 : }
9928 :
9929 128 : *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9930 : r->in.level);
9931 128 : r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9932 :
9933 128 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9934 :
9935 1920 : err_pinfo_free:
9936 1920 : TALLOC_FREE(pinfo2);
9937 0 : err_jinfo_free:
9938 1920 : TALLOC_FREE(r->out.info);
9939 1920 : return result;
9940 : }
9941 :
9942 : /****************************************************************
9943 : _spoolss_GetPrinterDataEx
9944 : ****************************************************************/
9945 :
9946 3180 : WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9947 : struct spoolss_GetPrinterDataEx *r)
9948 : {
9949 :
9950 3180 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9951 0 : const char *printer;
9952 3180 : int snum = 0;
9953 3180 : WERROR result = WERR_OK;
9954 0 : DATA_BLOB blob;
9955 3180 : enum winreg_Type val_type = REG_NONE;
9956 3180 : uint8_t *val_data = NULL;
9957 3180 : uint32_t val_size = 0;
9958 0 : struct dcerpc_binding_handle *b;
9959 0 : TALLOC_CTX *tmp_ctx;
9960 :
9961 3180 : DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9962 :
9963 3180 : DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9964 : r->in.key_name, r->in.value_name));
9965 :
9966 : /* in case of problem, return some default values */
9967 :
9968 3180 : *r->out.needed = 0;
9969 3180 : *r->out.type = REG_NONE;
9970 :
9971 3180 : tmp_ctx = talloc_new(p->mem_ctx);
9972 3180 : if (!tmp_ctx) {
9973 0 : return WERR_NOT_ENOUGH_MEMORY;
9974 : }
9975 :
9976 3180 : if (!Printer) {
9977 0 : DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9978 : OUR_HANDLE(r->in.handle)));
9979 0 : result = WERR_INVALID_HANDLE;
9980 0 : goto done;
9981 : }
9982 :
9983 : /* Is the handle to a printer or to the server? */
9984 :
9985 3180 : if (Printer->printer_type == SPLHND_SERVER) {
9986 :
9987 0 : union spoolss_PrinterData data;
9988 :
9989 404 : result = getprinterdata_printer_server(tmp_ctx,
9990 : r->in.value_name,
9991 : r->out.type,
9992 : &data);
9993 404 : if (!W_ERROR_IS_OK(result)) {
9994 4 : goto done;
9995 : }
9996 :
9997 400 : result = push_spoolss_PrinterData(tmp_ctx, &blob,
9998 400 : *r->out.type, &data);
9999 400 : if (!W_ERROR_IS_OK(result)) {
10000 0 : goto done;
10001 : }
10002 :
10003 400 : *r->out.needed = blob.length;
10004 :
10005 400 : if (r->in.offered >= *r->out.needed) {
10006 204 : memcpy(r->out.data, blob.data, blob.length);
10007 : }
10008 :
10009 400 : result = WERR_OK;
10010 400 : goto done;
10011 : }
10012 :
10013 : /* check to see if the keyname is valid */
10014 2776 : if (!strlen(r->in.key_name)) {
10015 0 : result = WERR_INVALID_PARAMETER;
10016 0 : goto done;
10017 : }
10018 :
10019 2776 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10020 0 : result = WERR_INVALID_HANDLE;
10021 0 : goto done;
10022 : }
10023 2776 : printer = lp_const_servicename(snum);
10024 :
10025 2776 : result = winreg_printer_binding_handle(tmp_ctx,
10026 : get_session_info_system(),
10027 : p->msg_ctx,
10028 : &b);
10029 2776 : if (!W_ERROR_IS_OK(result)) {
10030 0 : goto done;
10031 : }
10032 :
10033 : /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
10034 3076 : if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
10035 300 : strequal(r->in.value_name, "ChangeId")) {
10036 128 : *r->out.type = REG_DWORD;
10037 128 : *r->out.needed = 4;
10038 128 : if (r->in.offered >= *r->out.needed) {
10039 64 : uint32_t changeid = 0;
10040 :
10041 64 : result = winreg_printer_get_changeid(tmp_ctx, b,
10042 : printer,
10043 : &changeid);
10044 64 : if (!W_ERROR_IS_OK(result)) {
10045 0 : goto done;
10046 : }
10047 :
10048 64 : SIVAL(r->out.data, 0, changeid);
10049 64 : result = WERR_OK;
10050 : }
10051 128 : goto done;
10052 : }
10053 :
10054 2648 : result = winreg_get_printer_dataex(tmp_ctx, b,
10055 : printer,
10056 : r->in.key_name,
10057 : r->in.value_name,
10058 : &val_type,
10059 : &val_data,
10060 : &val_size);
10061 2648 : if (!W_ERROR_IS_OK(result)) {
10062 4 : goto done;
10063 : }
10064 :
10065 2644 : *r->out.needed = val_size;
10066 2644 : *r->out.type = val_type;
10067 :
10068 2644 : if (r->in.offered >= *r->out.needed) {
10069 1340 : memcpy(r->out.data, val_data, val_size);
10070 : }
10071 :
10072 1304 : done:
10073 : /* NOTE: do not replace type when returning WERR_MORE_DATA */
10074 :
10075 3180 : if (W_ERROR_IS_OK(result)) {
10076 3172 : result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
10077 : }
10078 :
10079 3180 : talloc_free(tmp_ctx);
10080 3180 : return result;
10081 : }
10082 :
10083 : /****************************************************************
10084 : _spoolss_SetPrinterDataEx
10085 : ****************************************************************/
10086 :
10087 1368 : WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
10088 : struct spoolss_SetPrinterDataEx *r)
10089 : {
10090 0 : const struct loadparm_substitution *lp_sub =
10091 1368 : loadparm_s3_global_substitution();
10092 1368 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
10093 1368 : int snum = 0;
10094 1368 : WERROR result = WERR_OK;
10095 1368 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10096 0 : char *oid_string;
10097 0 : struct dcerpc_binding_handle *b;
10098 0 : TALLOC_CTX *tmp_ctx;
10099 :
10100 1368 : DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
10101 :
10102 : /* From MSDN documentation of SetPrinterDataEx: pass request to
10103 : SetPrinterData if key is "PrinterDriverData" */
10104 :
10105 1368 : if (!Printer) {
10106 0 : DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
10107 : OUR_HANDLE(r->in.handle)));
10108 0 : return WERR_INVALID_HANDLE;
10109 : }
10110 :
10111 1368 : if (Printer->printer_type == SPLHND_SERVER) {
10112 0 : DEBUG(10,("_spoolss_SetPrinterDataEx: "
10113 : "Not implemented for server handles yet\n"));
10114 0 : return WERR_INVALID_PARAMETER;
10115 : }
10116 :
10117 1368 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10118 0 : return WERR_INVALID_HANDLE;
10119 : }
10120 :
10121 : /*
10122 : * Access check : NT returns "access denied" if you make a
10123 : * SetPrinterData call without the necessary privilege.
10124 : * we were originally returning OK if nothing changed
10125 : * which made Win2k issue **a lot** of SetPrinterData
10126 : * when connecting to a printer --jerry
10127 : */
10128 :
10129 1368 : if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10130 0 : DEBUG(3, ("_spoolss_SetPrinterDataEx: "
10131 : "change denied by handle access permissions\n"));
10132 0 : return WERR_ACCESS_DENIED;
10133 : }
10134 :
10135 1368 : tmp_ctx = talloc_new(p->mem_ctx);
10136 1368 : if (!tmp_ctx) {
10137 0 : return WERR_NOT_ENOUGH_MEMORY;
10138 : }
10139 :
10140 1368 : result = winreg_printer_binding_handle(tmp_ctx,
10141 : get_session_info_system(),
10142 : p->msg_ctx,
10143 : &b);
10144 1368 : if (!W_ERROR_IS_OK(result)) {
10145 0 : goto done;
10146 : }
10147 :
10148 1368 : result = winreg_get_printer(tmp_ctx, b,
10149 1368 : lp_servicename(talloc_tos(), lp_sub, snum),
10150 : &pinfo2);
10151 1368 : if (!W_ERROR_IS_OK(result)) {
10152 0 : goto done;
10153 : }
10154 :
10155 : /* check for OID in valuename */
10156 :
10157 1368 : oid_string = strchr(r->in.value_name, ',');
10158 1368 : if (oid_string) {
10159 0 : *oid_string = '\0';
10160 0 : oid_string++;
10161 : }
10162 :
10163 : /* save the registry data */
10164 :
10165 1368 : result = winreg_set_printer_dataex(tmp_ctx, b,
10166 1368 : pinfo2->sharename,
10167 : r->in.key_name,
10168 : r->in.value_name,
10169 : r->in.type,
10170 : r->in.data,
10171 : r->in.offered);
10172 :
10173 1368 : if (W_ERROR_IS_OK(result)) {
10174 : /* save the OID if one was specified */
10175 1368 : if (oid_string) {
10176 0 : char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
10177 : r->in.key_name, SPOOL_OID_KEY);
10178 0 : if (!str) {
10179 0 : result = WERR_NOT_ENOUGH_MEMORY;
10180 0 : goto done;
10181 : }
10182 :
10183 : /*
10184 : * I'm not checking the status here on purpose. Don't know
10185 : * if this is right, but I'm returning the status from the
10186 : * previous set_printer_dataex() call. I have no idea if
10187 : * this is right. --jerry
10188 : */
10189 0 : winreg_set_printer_dataex(tmp_ctx, b,
10190 0 : pinfo2->sharename,
10191 : str,
10192 : r->in.value_name,
10193 : REG_SZ,
10194 : (uint8_t *) oid_string,
10195 0 : strlen(oid_string) + 1);
10196 : }
10197 :
10198 1368 : result = winreg_printer_update_changeid(tmp_ctx, b,
10199 : lp_const_servicename(snum));
10200 :
10201 : }
10202 :
10203 0 : done:
10204 1368 : talloc_free(tmp_ctx);
10205 1368 : return result;
10206 : }
10207 :
10208 : /****************************************************************
10209 : _spoolss_DeletePrinterDataEx
10210 : ****************************************************************/
10211 :
10212 1368 : WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
10213 : struct spoolss_DeletePrinterDataEx *r)
10214 : {
10215 0 : const char *printer;
10216 1368 : int snum=0;
10217 1368 : WERROR status = WERR_OK;
10218 1368 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10219 :
10220 1368 : DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
10221 :
10222 1368 : if (!Printer) {
10223 0 : DEBUG(2,("_spoolss_DeletePrinterDataEx: "
10224 : "Invalid handle (%s:%u:%u).\n",
10225 : OUR_HANDLE(r->in.handle)));
10226 0 : return WERR_INVALID_HANDLE;
10227 : }
10228 :
10229 1368 : if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10230 0 : DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
10231 : "printer properties change denied by handle\n"));
10232 0 : return WERR_ACCESS_DENIED;
10233 : }
10234 :
10235 1368 : if (!r->in.value_name || !r->in.key_name) {
10236 0 : return WERR_NOT_ENOUGH_MEMORY;
10237 : }
10238 :
10239 1368 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10240 0 : return WERR_INVALID_HANDLE;
10241 : }
10242 1368 : printer = lp_const_servicename(snum);
10243 :
10244 1368 : status = winreg_delete_printer_dataex_internal(p->mem_ctx,
10245 : get_session_info_system(),
10246 : p->msg_ctx,
10247 : printer,
10248 : r->in.key_name,
10249 : r->in.value_name);
10250 1368 : if (W_ERROR_IS_OK(status)) {
10251 1368 : status = winreg_printer_update_changeid_internal(p->mem_ctx,
10252 : get_session_info_system(),
10253 : p->msg_ctx,
10254 : printer);
10255 : }
10256 :
10257 1368 : return status;
10258 : }
10259 :
10260 : /****************************************************************
10261 : _spoolss_EnumPrinterKey
10262 : ****************************************************************/
10263 :
10264 3384 : WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
10265 : struct spoolss_EnumPrinterKey *r)
10266 : {
10267 0 : uint32_t num_keys;
10268 3384 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10269 3384 : int snum = 0;
10270 3384 : WERROR result = WERR_FILE_NOT_FOUND;
10271 3384 : const char **array = NULL;
10272 0 : DATA_BLOB blob;
10273 :
10274 3384 : DEBUG(4,("_spoolss_EnumPrinterKey\n"));
10275 :
10276 3384 : if (!Printer) {
10277 0 : DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
10278 : OUR_HANDLE(r->in.handle)));
10279 0 : return WERR_INVALID_HANDLE;
10280 : }
10281 :
10282 3384 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10283 0 : return WERR_INVALID_HANDLE;
10284 : }
10285 :
10286 3384 : result = winreg_enum_printer_key_internal(p->mem_ctx,
10287 : get_session_info_system(),
10288 : p->msg_ctx,
10289 : lp_const_servicename(snum),
10290 : r->in.key_name,
10291 : &num_keys,
10292 : &array);
10293 3384 : if (!W_ERROR_IS_OK(result)) {
10294 0 : goto done;
10295 : }
10296 :
10297 3384 : if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
10298 0 : result = WERR_NOT_ENOUGH_MEMORY;
10299 0 : goto done;
10300 : }
10301 :
10302 3384 : *r->out._ndr_size = r->in.offered / 2;
10303 3384 : *r->out.needed = blob.length;
10304 :
10305 3384 : if (r->in.offered < *r->out.needed) {
10306 1304 : result = WERR_MORE_DATA;
10307 : } else {
10308 2080 : result = WERR_OK;
10309 2080 : r->out.key_buffer->string_array = array;
10310 : }
10311 :
10312 3384 : done:
10313 3384 : if (!W_ERROR_IS_OK(result)) {
10314 1304 : TALLOC_FREE(array);
10315 1304 : if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
10316 0 : *r->out.needed = 0;
10317 : }
10318 : }
10319 :
10320 3384 : return result;
10321 : }
10322 :
10323 : /****************************************************************
10324 : _spoolss_DeletePrinterKey
10325 : ****************************************************************/
10326 :
10327 216 : WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
10328 : struct spoolss_DeletePrinterKey *r)
10329 : {
10330 216 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10331 216 : int snum=0;
10332 0 : WERROR status;
10333 0 : const char *printer;
10334 0 : struct dcerpc_binding_handle *b;
10335 0 : TALLOC_CTX *tmp_ctx;
10336 :
10337 216 : DEBUG(5,("_spoolss_DeletePrinterKey\n"));
10338 :
10339 216 : if (!Printer) {
10340 0 : DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
10341 : OUR_HANDLE(r->in.handle)));
10342 0 : return WERR_INVALID_HANDLE;
10343 : }
10344 :
10345 : /* if keyname == NULL, return error */
10346 216 : if ( !r->in.key_name )
10347 0 : return WERR_INVALID_PARAMETER;
10348 :
10349 216 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10350 0 : return WERR_INVALID_HANDLE;
10351 : }
10352 :
10353 216 : if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10354 0 : DEBUG(3, ("_spoolss_DeletePrinterKey: "
10355 : "printer properties change denied by handle\n"));
10356 0 : return WERR_ACCESS_DENIED;
10357 : }
10358 :
10359 216 : printer = lp_const_servicename(snum);
10360 :
10361 216 : tmp_ctx = talloc_new(p->mem_ctx);
10362 216 : if (!tmp_ctx) {
10363 0 : return WERR_NOT_ENOUGH_MEMORY;
10364 : }
10365 :
10366 216 : status = winreg_printer_binding_handle(tmp_ctx,
10367 : get_session_info_system(),
10368 : p->msg_ctx,
10369 : &b);
10370 216 : if (!W_ERROR_IS_OK(status)) {
10371 0 : goto done;
10372 : }
10373 :
10374 : /* delete the key and all subkeys */
10375 216 : status = winreg_delete_printer_key(tmp_ctx, b,
10376 : printer,
10377 : r->in.key_name);
10378 216 : if (W_ERROR_IS_OK(status)) {
10379 216 : status = winreg_printer_update_changeid(tmp_ctx, b,
10380 : printer);
10381 : }
10382 :
10383 0 : done:
10384 216 : talloc_free(tmp_ctx);
10385 216 : return status;
10386 : }
10387 :
10388 : /****************************************************************
10389 : _spoolss_EnumPrinterDataEx
10390 : ****************************************************************/
10391 :
10392 2860 : WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
10393 : struct spoolss_EnumPrinterDataEx *r)
10394 : {
10395 2860 : uint32_t count = 0;
10396 2860 : struct spoolss_PrinterEnumValues *info = NULL;
10397 2860 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10398 0 : int snum;
10399 0 : WERROR result;
10400 :
10401 2860 : DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
10402 :
10403 2860 : *r->out.count = 0;
10404 2860 : *r->out.needed = 0;
10405 2860 : *r->out.info = NULL;
10406 :
10407 2860 : if (!Printer) {
10408 0 : DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
10409 : OUR_HANDLE(r->in.handle)));
10410 0 : return WERR_INVALID_HANDLE;
10411 : }
10412 :
10413 : /*
10414 : * first check for a keyname of NULL or "". Win2k seems to send
10415 : * this a lot and we should send back WERR_INVALID_PARAMETER
10416 : * no need to spend time looking up the printer in this case.
10417 : * --jerry
10418 : */
10419 :
10420 2860 : if (!strlen(r->in.key_name)) {
10421 4 : result = WERR_INVALID_PARAMETER;
10422 4 : goto done;
10423 : }
10424 :
10425 2856 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10426 0 : return WERR_INVALID_HANDLE;
10427 : }
10428 :
10429 : /* now look for a match on the key name */
10430 2856 : result = winreg_enum_printer_dataex_internal(p->mem_ctx,
10431 : get_session_info_system(),
10432 : p->msg_ctx,
10433 : lp_const_servicename(snum),
10434 : r->in.key_name,
10435 : &count,
10436 : &info);
10437 2856 : if (!W_ERROR_IS_OK(result)) {
10438 0 : goto done;
10439 : }
10440 :
10441 2856 : *r->out.count = count;
10442 2856 : *r->out.info = info;
10443 :
10444 2860 : done:
10445 2860 : if (!W_ERROR_IS_OK(result)) {
10446 4 : return result;
10447 : }
10448 :
10449 2856 : *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
10450 : spoolss_EnumPrinterDataEx,
10451 : *r->out.info,
10452 : *r->out.count);
10453 2856 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
10454 2856 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
10455 :
10456 2856 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
10457 : }
10458 :
10459 : /****************************************************************************
10460 : ****************************************************************************/
10461 :
10462 40 : static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
10463 : const char *servername,
10464 : const char *environment,
10465 : struct spoolss_PrintProcessorDirectoryInfo1 *r)
10466 : {
10467 0 : WERROR werr;
10468 40 : char *path = NULL;
10469 :
10470 40 : werr = compose_spoolss_server_path(mem_ctx,
10471 : servername,
10472 : environment,
10473 : SPOOLSS_PRTPROCS_PATH,
10474 : &path);
10475 40 : if (!W_ERROR_IS_OK(werr)) {
10476 0 : return werr;
10477 : }
10478 :
10479 40 : DEBUG(4,("print processor directory: [%s]\n", path));
10480 :
10481 40 : r->directory_name = path;
10482 :
10483 40 : return WERR_OK;
10484 : }
10485 :
10486 : /****************************************************************
10487 : _spoolss_GetPrintProcessorDirectory
10488 : ****************************************************************/
10489 :
10490 40 : WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
10491 : struct spoolss_GetPrintProcessorDirectory *r)
10492 : {
10493 0 : WERROR result;
10494 40 : char *prnproc_share = NULL;
10495 40 : bool prnproc_share_exists = false;
10496 0 : int snum;
10497 :
10498 : /* that's an [in out] buffer */
10499 :
10500 40 : if (!r->in.buffer && (r->in.offered != 0)) {
10501 0 : result = WERR_INVALID_PARAMETER;
10502 0 : goto err_info_free;
10503 : }
10504 :
10505 40 : DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
10506 : r->in.level));
10507 :
10508 40 : *r->out.needed = 0;
10509 :
10510 : /* r->in.level is ignored */
10511 :
10512 : /* We always should reply with a local print processor directory so that
10513 : * users are not forced to have a [prnproc$] share on the Samba spoolss
10514 : * server, if users decide to do so, lets announce it though - Guenther */
10515 :
10516 40 : snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
10517 40 : if (!prnproc_share) {
10518 0 : result = WERR_NOT_ENOUGH_MEMORY;
10519 0 : goto err_info_free;
10520 : }
10521 40 : if (snum != -1) {
10522 0 : prnproc_share_exists = true;
10523 : }
10524 :
10525 40 : result = getprintprocessordirectory_level_1(p->mem_ctx,
10526 : prnproc_share_exists ? r->in.server : NULL,
10527 : r->in.environment,
10528 40 : &r->out.info->info1);
10529 40 : if (!W_ERROR_IS_OK(result)) {
10530 0 : goto err_info_free;
10531 : }
10532 :
10533 40 : *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
10534 : r->out.info, r->in.level);
10535 40 : r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10536 :
10537 40 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10538 :
10539 0 : err_info_free:
10540 0 : TALLOC_FREE(r->out.info);
10541 0 : return result;
10542 : }
10543 :
10544 : /*******************************************************************
10545 : ********************************************************************/
10546 :
10547 0 : static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10548 : const char *dllname)
10549 : {
10550 0 : enum ndr_err_code ndr_err;
10551 0 : struct spoolss_MonitorUi ui;
10552 :
10553 0 : ui.dll_name = dllname;
10554 :
10555 0 : ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10556 : (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10557 0 : if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10558 0 : NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10559 : }
10560 0 : return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10561 : }
10562 :
10563 : /*******************************************************************
10564 : Streams the monitor UI DLL name in UNICODE
10565 : *******************************************************************/
10566 :
10567 0 : static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10568 : struct security_token *token, DATA_BLOB *in,
10569 : DATA_BLOB *out, uint32_t *needed)
10570 : {
10571 0 : const char *dllname = "tcpmonui.dll";
10572 :
10573 0 : *needed = (strlen(dllname)+1) * 2;
10574 :
10575 0 : if (out->length < *needed) {
10576 0 : return WERR_INSUFFICIENT_BUFFER;
10577 : }
10578 :
10579 0 : if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10580 0 : return WERR_NOT_ENOUGH_MEMORY;
10581 : }
10582 :
10583 0 : return WERR_OK;
10584 : }
10585 :
10586 : /*******************************************************************
10587 : ********************************************************************/
10588 :
10589 0 : static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10590 : struct spoolss_PortData1 *port1,
10591 : const DATA_BLOB *buf)
10592 : {
10593 0 : enum ndr_err_code ndr_err;
10594 0 : ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10595 : (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10596 0 : if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10597 0 : NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10598 : }
10599 0 : return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10600 : }
10601 :
10602 : /*******************************************************************
10603 : ********************************************************************/
10604 :
10605 0 : static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10606 : struct spoolss_PortData2 *port2,
10607 : const DATA_BLOB *buf)
10608 : {
10609 0 : enum ndr_err_code ndr_err;
10610 0 : ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10611 : (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10612 0 : if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10613 0 : NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10614 : }
10615 0 : return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10616 : }
10617 :
10618 : /*******************************************************************
10619 : Create a new TCP/IP port
10620 : *******************************************************************/
10621 :
10622 0 : static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10623 : struct security_token *token, DATA_BLOB *in,
10624 : DATA_BLOB *out, uint32_t *needed)
10625 : {
10626 0 : struct spoolss_PortData1 port1;
10627 0 : struct spoolss_PortData2 port2;
10628 0 : char *device_uri = NULL;
10629 0 : uint32_t version;
10630 :
10631 0 : const char *portname;
10632 0 : const char *hostaddress;
10633 0 : const char *queue;
10634 0 : uint32_t port_number;
10635 0 : uint32_t protocol;
10636 :
10637 : /* peek for spoolss_PortData version */
10638 :
10639 0 : if (!in || (in->length < (128 + 4))) {
10640 0 : return WERR_GEN_FAILURE;
10641 : }
10642 :
10643 0 : version = IVAL(in->data, 128);
10644 :
10645 0 : switch (version) {
10646 0 : case 1:
10647 0 : ZERO_STRUCT(port1);
10648 :
10649 0 : if (!pull_port_data_1(mem_ctx, &port1, in)) {
10650 0 : return WERR_NOT_ENOUGH_MEMORY;
10651 : }
10652 :
10653 0 : portname = port1.portname;
10654 0 : hostaddress = port1.hostaddress;
10655 0 : queue = port1.queue;
10656 0 : protocol = port1.protocol;
10657 0 : port_number = port1.port_number;
10658 :
10659 0 : break;
10660 0 : case 2:
10661 0 : ZERO_STRUCT(port2);
10662 :
10663 0 : if (!pull_port_data_2(mem_ctx, &port2, in)) {
10664 0 : return WERR_NOT_ENOUGH_MEMORY;
10665 : }
10666 :
10667 0 : portname = port2.portname;
10668 0 : hostaddress = port2.hostaddress;
10669 0 : queue = port2.queue;
10670 0 : protocol = port2.protocol;
10671 0 : port_number = port2.port_number;
10672 :
10673 0 : break;
10674 0 : default:
10675 0 : DEBUG(1,("xcvtcp_addport: "
10676 : "unknown version of port_data: %d\n", version));
10677 0 : return WERR_UNKNOWN_PORT;
10678 : }
10679 :
10680 : /* create the device URI and call the add_port_hook() */
10681 :
10682 0 : switch (protocol) {
10683 0 : case PROTOCOL_RAWTCP_TYPE:
10684 0 : device_uri = talloc_asprintf(mem_ctx,
10685 : "socket://%s:%d/", hostaddress,
10686 : port_number);
10687 0 : break;
10688 :
10689 0 : case PROTOCOL_LPR_TYPE:
10690 0 : device_uri = talloc_asprintf(mem_ctx,
10691 : "lpr://%s/%s", hostaddress, queue );
10692 0 : break;
10693 :
10694 0 : default:
10695 0 : return WERR_UNKNOWN_PORT;
10696 : }
10697 :
10698 0 : if (!device_uri) {
10699 0 : return WERR_NOT_ENOUGH_MEMORY;
10700 : }
10701 :
10702 0 : return add_port_hook(mem_ctx, token, portname, device_uri);
10703 : }
10704 :
10705 : /*******************************************************************
10706 : *******************************************************************/
10707 :
10708 : struct xcv_api_table xcvtcp_cmds[] = {
10709 : { "MonitorUI", xcvtcp_monitorui },
10710 : { "AddPort", xcvtcp_addport},
10711 : { NULL, NULL }
10712 : };
10713 :
10714 0 : static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10715 : struct security_token *token, const char *command,
10716 : DATA_BLOB *inbuf,
10717 : DATA_BLOB *outbuf,
10718 : uint32_t *needed )
10719 : {
10720 0 : int i;
10721 :
10722 0 : DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10723 :
10724 0 : for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10725 0 : if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10726 0 : return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10727 : }
10728 :
10729 0 : return WERR_INVALID_FUNCTION;
10730 : }
10731 :
10732 : /*******************************************************************
10733 : *******************************************************************/
10734 : #if 0 /* don't support management using the "Local Port" monitor */
10735 :
10736 : static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10737 : struct security_token *token, DATA_BLOB *in,
10738 : DATA_BLOB *out, uint32_t *needed)
10739 : {
10740 : const char *dllname = "localui.dll";
10741 :
10742 : *needed = (strlen(dllname)+1) * 2;
10743 :
10744 : if (out->length < *needed) {
10745 : return WERR_INSUFFICIENT_BUFFER;
10746 : }
10747 :
10748 : if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10749 : return WERR_NOT_ENOUGH_MEMORY;
10750 : }
10751 :
10752 : return WERR_OK;
10753 : }
10754 :
10755 : /*******************************************************************
10756 : *******************************************************************/
10757 :
10758 : struct xcv_api_table xcvlocal_cmds[] = {
10759 : { "MonitorUI", xcvlocal_monitorui },
10760 : { NULL, NULL }
10761 : };
10762 : #else
10763 : struct xcv_api_table xcvlocal_cmds[] = {
10764 : { NULL, NULL }
10765 : };
10766 : #endif
10767 :
10768 :
10769 :
10770 : /*******************************************************************
10771 : *******************************************************************/
10772 :
10773 0 : static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10774 : struct security_token *token, const char *command,
10775 : DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10776 : uint32_t *needed)
10777 : {
10778 0 : int i;
10779 :
10780 0 : DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10781 :
10782 0 : for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10783 0 : if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10784 0 : return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10785 : }
10786 0 : return WERR_INVALID_FUNCTION;
10787 : }
10788 :
10789 : /****************************************************************
10790 : _spoolss_XcvData
10791 : ****************************************************************/
10792 :
10793 0 : WERROR _spoolss_XcvData(struct pipes_struct *p,
10794 : struct spoolss_XcvData *r)
10795 : {
10796 0 : struct dcesrv_call_state *dce_call = p->dce_call;
10797 0 : struct auth_session_info *session_info =
10798 0 : dcesrv_call_session_info(dce_call);
10799 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10800 0 : DATA_BLOB out_data = data_blob_null;
10801 0 : WERROR werror;
10802 :
10803 0 : if (!Printer) {
10804 0 : DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10805 : OUR_HANDLE(r->in.handle)));
10806 0 : return WERR_INVALID_HANDLE;
10807 : }
10808 :
10809 : /* Has to be a handle to the TCP/IP port monitor */
10810 :
10811 0 : if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10812 0 : DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10813 0 : return WERR_INVALID_HANDLE;
10814 : }
10815 :
10816 : /* requires administrative access to the server */
10817 :
10818 0 : if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10819 0 : DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10820 0 : return WERR_ACCESS_DENIED;
10821 : }
10822 :
10823 : /* Allocate the outgoing buffer */
10824 :
10825 0 : if (r->in.out_data_size) {
10826 0 : out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10827 0 : if (out_data.data == NULL) {
10828 0 : return WERR_NOT_ENOUGH_MEMORY;
10829 : }
10830 : }
10831 :
10832 0 : switch ( Printer->printer_type ) {
10833 0 : case SPLHND_PORTMON_TCP:
10834 0 : werror = process_xcvtcp_command(p->mem_ctx,
10835 : session_info->security_token,
10836 : r->in.function_name,
10837 : &r->in.in_data, &out_data,
10838 : r->out.needed);
10839 0 : break;
10840 0 : case SPLHND_PORTMON_LOCAL:
10841 0 : werror = process_xcvlocal_command(p->mem_ctx,
10842 : session_info->security_token,
10843 : r->in.function_name,
10844 : &r->in.in_data, &out_data,
10845 : r->out.needed);
10846 0 : break;
10847 0 : default:
10848 0 : werror = WERR_INVALID_PRINT_MONITOR;
10849 : }
10850 :
10851 0 : if (!W_ERROR_IS_OK(werror)) {
10852 0 : return werror;
10853 : }
10854 :
10855 0 : *r->out.status_code = 0;
10856 :
10857 0 : if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10858 0 : memcpy(r->out.out_data, out_data.data,
10859 0 : MIN(r->in.out_data_size, out_data.length));
10860 : }
10861 :
10862 0 : return WERR_OK;
10863 : }
10864 :
10865 : /****************************************************************
10866 : _spoolss_AddPrintProcessor
10867 : ****************************************************************/
10868 :
10869 4 : WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10870 : struct spoolss_AddPrintProcessor *r)
10871 : {
10872 : /* for now, just indicate success and ignore the add. We'll
10873 : automatically set the winprint processor for printer
10874 : entries later. Used to debug the LexMark Optra S 1855 PCL
10875 : driver --jerry */
10876 :
10877 4 : return WERR_OK;
10878 : }
10879 :
10880 : /****************************************************************
10881 : _spoolss_AddPort
10882 : ****************************************************************/
10883 :
10884 4 : WERROR _spoolss_AddPort(struct pipes_struct *p,
10885 : struct spoolss_AddPort *r)
10886 : {
10887 : /* do what w2k3 does */
10888 :
10889 4 : return WERR_NOT_SUPPORTED;
10890 : }
10891 :
10892 : /****************************************************************
10893 : _spoolss_GetPrinterDriver
10894 : ****************************************************************/
10895 :
10896 0 : WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10897 : struct spoolss_GetPrinterDriver *r)
10898 : {
10899 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10900 0 : return WERR_NOT_SUPPORTED;
10901 : }
10902 :
10903 : /****************************************************************
10904 : _spoolss_ReadPrinter
10905 : ****************************************************************/
10906 :
10907 0 : WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10908 : struct spoolss_ReadPrinter *r)
10909 : {
10910 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10911 0 : return WERR_NOT_SUPPORTED;
10912 : }
10913 :
10914 : /****************************************************************
10915 : _spoolss_WaitForPrinterChange
10916 : ****************************************************************/
10917 :
10918 0 : WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10919 : struct spoolss_WaitForPrinterChange *r)
10920 : {
10921 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10922 0 : return WERR_NOT_SUPPORTED;
10923 : }
10924 :
10925 : /****************************************************************
10926 : _spoolss_ConfigurePort
10927 : ****************************************************************/
10928 :
10929 0 : WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10930 : struct spoolss_ConfigurePort *r)
10931 : {
10932 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10933 0 : return WERR_NOT_SUPPORTED;
10934 : }
10935 :
10936 : /****************************************************************
10937 : _spoolss_DeletePort
10938 : ****************************************************************/
10939 :
10940 0 : WERROR _spoolss_DeletePort(struct pipes_struct *p,
10941 : struct spoolss_DeletePort *r)
10942 : {
10943 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10944 0 : return WERR_NOT_SUPPORTED;
10945 : }
10946 :
10947 : /****************************************************************
10948 : _spoolss_CreatePrinterIC
10949 : ****************************************************************/
10950 :
10951 0 : WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10952 : struct spoolss_CreatePrinterIC *r)
10953 : {
10954 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10955 0 : return WERR_NOT_SUPPORTED;
10956 : }
10957 :
10958 : /****************************************************************
10959 : _spoolss_PlayGDIScriptOnPrinterIC
10960 : ****************************************************************/
10961 :
10962 0 : WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10963 : struct spoolss_PlayGDIScriptOnPrinterIC *r)
10964 : {
10965 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10966 0 : return WERR_NOT_SUPPORTED;
10967 : }
10968 :
10969 : /****************************************************************
10970 : _spoolss_DeletePrinterIC
10971 : ****************************************************************/
10972 :
10973 0 : WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10974 : struct spoolss_DeletePrinterIC *r)
10975 : {
10976 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10977 0 : return WERR_NOT_SUPPORTED;
10978 : }
10979 :
10980 : /****************************************************************
10981 : _spoolss_AddPrinterConnection
10982 : ****************************************************************/
10983 :
10984 0 : WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10985 : struct spoolss_AddPrinterConnection *r)
10986 : {
10987 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10988 0 : return WERR_NOT_SUPPORTED;
10989 : }
10990 :
10991 : /****************************************************************
10992 : _spoolss_DeletePrinterConnection
10993 : ****************************************************************/
10994 :
10995 0 : WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10996 : struct spoolss_DeletePrinterConnection *r)
10997 : {
10998 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10999 0 : return WERR_NOT_SUPPORTED;
11000 : }
11001 :
11002 : /****************************************************************
11003 : _spoolss_PrinterMessageBox
11004 : ****************************************************************/
11005 :
11006 0 : WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
11007 : struct spoolss_PrinterMessageBox *r)
11008 : {
11009 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11010 0 : return WERR_NOT_SUPPORTED;
11011 : }
11012 :
11013 : /****************************************************************
11014 : _spoolss_AddMonitor
11015 : ****************************************************************/
11016 :
11017 0 : WERROR _spoolss_AddMonitor(struct pipes_struct *p,
11018 : struct spoolss_AddMonitor *r)
11019 : {
11020 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11021 0 : return WERR_NOT_SUPPORTED;
11022 : }
11023 :
11024 : /****************************************************************
11025 : _spoolss_DeleteMonitor
11026 : ****************************************************************/
11027 :
11028 0 : WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
11029 : struct spoolss_DeleteMonitor *r)
11030 : {
11031 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11032 0 : return WERR_NOT_SUPPORTED;
11033 : }
11034 :
11035 : /****************************************************************
11036 : _spoolss_DeletePrintProcessor
11037 : ****************************************************************/
11038 :
11039 0 : WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
11040 : struct spoolss_DeletePrintProcessor *r)
11041 : {
11042 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11043 0 : return WERR_NOT_SUPPORTED;
11044 : }
11045 :
11046 : /****************************************************************
11047 : _spoolss_AddPrintProvidor
11048 : ****************************************************************/
11049 :
11050 0 : WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
11051 : struct spoolss_AddPrintProvidor *r)
11052 : {
11053 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11054 0 : return WERR_NOT_SUPPORTED;
11055 : }
11056 :
11057 : /****************************************************************
11058 : _spoolss_DeletePrintProvidor
11059 : ****************************************************************/
11060 :
11061 0 : WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
11062 : struct spoolss_DeletePrintProvidor *r)
11063 : {
11064 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11065 0 : return WERR_NOT_SUPPORTED;
11066 : }
11067 :
11068 : /****************************************************************
11069 : _spoolss_FindFirstPrinterChangeNotification
11070 : ****************************************************************/
11071 :
11072 0 : WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
11073 : struct spoolss_FindFirstPrinterChangeNotification *r)
11074 : {
11075 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11076 0 : return WERR_NOT_SUPPORTED;
11077 : }
11078 :
11079 : /****************************************************************
11080 : _spoolss_FindNextPrinterChangeNotification
11081 : ****************************************************************/
11082 :
11083 0 : WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
11084 : struct spoolss_FindNextPrinterChangeNotification *r)
11085 : {
11086 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11087 0 : return WERR_NOT_SUPPORTED;
11088 : }
11089 :
11090 : /****************************************************************
11091 : _spoolss_RouterFindFirstPrinterChangeNotificationOld
11092 : ****************************************************************/
11093 :
11094 0 : WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
11095 : struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
11096 : {
11097 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11098 0 : return WERR_NOT_SUPPORTED;
11099 : }
11100 :
11101 : /****************************************************************
11102 : _spoolss_ReplyOpenPrinter
11103 : ****************************************************************/
11104 :
11105 0 : WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
11106 : struct spoolss_ReplyOpenPrinter *r)
11107 : {
11108 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11109 0 : return WERR_NOT_SUPPORTED;
11110 : }
11111 :
11112 : /****************************************************************
11113 : _spoolss_RouterReplyPrinter
11114 : ****************************************************************/
11115 :
11116 0 : WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
11117 : struct spoolss_RouterReplyPrinter *r)
11118 : {
11119 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11120 0 : return WERR_NOT_SUPPORTED;
11121 : }
11122 :
11123 : /****************************************************************
11124 : _spoolss_ReplyClosePrinter
11125 : ****************************************************************/
11126 :
11127 0 : WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
11128 : struct spoolss_ReplyClosePrinter *r)
11129 : {
11130 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11131 0 : return WERR_NOT_SUPPORTED;
11132 : }
11133 :
11134 : /****************************************************************
11135 : _spoolss_AddPortEx
11136 : ****************************************************************/
11137 :
11138 0 : WERROR _spoolss_AddPortEx(struct pipes_struct *p,
11139 : struct spoolss_AddPortEx *r)
11140 : {
11141 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11142 0 : return WERR_NOT_SUPPORTED;
11143 : }
11144 :
11145 : /****************************************************************
11146 : _spoolss_RouterFindFirstPrinterChangeNotification
11147 : ****************************************************************/
11148 :
11149 0 : WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
11150 : struct spoolss_RouterFindFirstPrinterChangeNotification *r)
11151 : {
11152 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11153 0 : return WERR_NOT_SUPPORTED;
11154 : }
11155 :
11156 : /****************************************************************
11157 : _spoolss_SpoolerInit
11158 : ****************************************************************/
11159 :
11160 0 : WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
11161 : struct spoolss_SpoolerInit *r)
11162 : {
11163 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11164 0 : return WERR_NOT_SUPPORTED;
11165 : }
11166 :
11167 : /****************************************************************
11168 : _spoolss_ResetPrinterEx
11169 : ****************************************************************/
11170 :
11171 0 : WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
11172 : struct spoolss_ResetPrinterEx *r)
11173 : {
11174 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11175 0 : return WERR_NOT_SUPPORTED;
11176 : }
11177 :
11178 : /****************************************************************
11179 : _spoolss_RouterReplyPrinterEx
11180 : ****************************************************************/
11181 :
11182 0 : WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
11183 : struct spoolss_RouterReplyPrinterEx *r)
11184 : {
11185 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11186 0 : return WERR_NOT_SUPPORTED;
11187 : }
11188 :
11189 : /****************************************************************
11190 : _spoolss_44
11191 : ****************************************************************/
11192 :
11193 0 : WERROR _spoolss_44(struct pipes_struct *p,
11194 : struct spoolss_44 *r)
11195 : {
11196 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11197 0 : return WERR_NOT_SUPPORTED;
11198 : }
11199 :
11200 : /****************************************************************
11201 : _spoolss_SetPort
11202 : ****************************************************************/
11203 :
11204 0 : WERROR _spoolss_SetPort(struct pipes_struct *p,
11205 : struct spoolss_SetPort *r)
11206 : {
11207 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11208 0 : return WERR_NOT_SUPPORTED;
11209 : }
11210 :
11211 : /****************************************************************
11212 : _spoolss_4a
11213 : ****************************************************************/
11214 :
11215 0 : WERROR _spoolss_4a(struct pipes_struct *p,
11216 : struct spoolss_4a *r)
11217 : {
11218 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11219 0 : return WERR_NOT_SUPPORTED;
11220 : }
11221 :
11222 : /****************************************************************
11223 : _spoolss_4b
11224 : ****************************************************************/
11225 :
11226 0 : WERROR _spoolss_4b(struct pipes_struct *p,
11227 : struct spoolss_4b *r)
11228 : {
11229 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11230 0 : return WERR_NOT_SUPPORTED;
11231 : }
11232 :
11233 : /****************************************************************
11234 : _spoolss_4c
11235 : ****************************************************************/
11236 :
11237 0 : WERROR _spoolss_4c(struct pipes_struct *p,
11238 : struct spoolss_4c *r)
11239 : {
11240 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11241 0 : return WERR_NOT_SUPPORTED;
11242 : }
11243 :
11244 : /****************************************************************
11245 : _spoolss_53
11246 : ****************************************************************/
11247 :
11248 0 : WERROR _spoolss_53(struct pipes_struct *p,
11249 : struct spoolss_53 *r)
11250 : {
11251 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11252 0 : return WERR_NOT_SUPPORTED;
11253 : }
11254 :
11255 : /****************************************************************
11256 : _spoolss_AddPerMachineConnection
11257 : ****************************************************************/
11258 :
11259 4 : WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
11260 : struct spoolss_AddPerMachineConnection *r)
11261 : {
11262 4 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11263 4 : return WERR_NOT_SUPPORTED;
11264 : }
11265 :
11266 : /****************************************************************
11267 : _spoolss_DeletePerMachineConnection
11268 : ****************************************************************/
11269 :
11270 0 : WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
11271 : struct spoolss_DeletePerMachineConnection *r)
11272 : {
11273 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11274 0 : return WERR_NOT_SUPPORTED;
11275 : }
11276 :
11277 : /****************************************************************
11278 : _spoolss_EnumPerMachineConnections
11279 : ****************************************************************/
11280 :
11281 0 : WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
11282 : struct spoolss_EnumPerMachineConnections *r)
11283 : {
11284 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11285 0 : return WERR_NOT_SUPPORTED;
11286 : }
11287 :
11288 : /****************************************************************
11289 : _spoolss_5a
11290 : ****************************************************************/
11291 :
11292 0 : WERROR _spoolss_5a(struct pipes_struct *p,
11293 : struct spoolss_5a *r)
11294 : {
11295 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11296 0 : return WERR_NOT_SUPPORTED;
11297 : }
11298 :
11299 : /****************************************************************
11300 : _spoolss_5b
11301 : ****************************************************************/
11302 :
11303 0 : WERROR _spoolss_5b(struct pipes_struct *p,
11304 : struct spoolss_5b *r)
11305 : {
11306 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11307 0 : return WERR_NOT_SUPPORTED;
11308 : }
11309 :
11310 : /****************************************************************
11311 : _spoolss_5c
11312 : ****************************************************************/
11313 :
11314 0 : WERROR _spoolss_5c(struct pipes_struct *p,
11315 : struct spoolss_5c *r)
11316 : {
11317 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11318 0 : return WERR_NOT_SUPPORTED;
11319 : }
11320 :
11321 : /****************************************************************
11322 : _spoolss_5d
11323 : ****************************************************************/
11324 :
11325 0 : WERROR _spoolss_5d(struct pipes_struct *p,
11326 : struct spoolss_5d *r)
11327 : {
11328 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11329 0 : return WERR_NOT_SUPPORTED;
11330 : }
11331 :
11332 : /****************************************************************
11333 : _spoolss_5e
11334 : ****************************************************************/
11335 :
11336 0 : WERROR _spoolss_5e(struct pipes_struct *p,
11337 : struct spoolss_5e *r)
11338 : {
11339 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11340 0 : return WERR_NOT_SUPPORTED;
11341 : }
11342 :
11343 : /****************************************************************
11344 : _spoolss_5f
11345 : ****************************************************************/
11346 :
11347 0 : WERROR _spoolss_5f(struct pipes_struct *p,
11348 : struct spoolss_5f *r)
11349 : {
11350 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11351 0 : return WERR_NOT_SUPPORTED;
11352 : }
11353 :
11354 : /****************************************************************
11355 : _spoolss_60
11356 : ****************************************************************/
11357 :
11358 0 : WERROR _spoolss_60(struct pipes_struct *p,
11359 : struct spoolss_60 *r)
11360 : {
11361 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11362 0 : return WERR_NOT_SUPPORTED;
11363 : }
11364 :
11365 : /****************************************************************
11366 : _spoolss_SendRecvBidiData
11367 : ****************************************************************/
11368 :
11369 0 : WERROR _spoolss_SendRecvBidiData(struct pipes_struct *p,
11370 : struct spoolss_SendRecvBidiData *r)
11371 : {
11372 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11373 0 : return WERR_NOT_SUPPORTED;
11374 : }
11375 :
11376 : /****************************************************************
11377 : _spoolss_62
11378 : ****************************************************************/
11379 :
11380 0 : WERROR _spoolss_62(struct pipes_struct *p,
11381 : struct spoolss_62 *r)
11382 : {
11383 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11384 0 : return WERR_NOT_SUPPORTED;
11385 : }
11386 :
11387 : /****************************************************************
11388 : _spoolss_63
11389 : ****************************************************************/
11390 :
11391 0 : WERROR _spoolss_63(struct pipes_struct *p,
11392 : struct spoolss_63 *r)
11393 : {
11394 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11395 0 : return WERR_NOT_SUPPORTED;
11396 : }
11397 :
11398 : /****************************************************************
11399 : _spoolss_64
11400 : ****************************************************************/
11401 :
11402 0 : WERROR _spoolss_64(struct pipes_struct *p,
11403 : struct spoolss_64 *r)
11404 : {
11405 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11406 0 : return WERR_NOT_SUPPORTED;
11407 : }
11408 :
11409 : /****************************************************************
11410 : _spoolss_65
11411 : ****************************************************************/
11412 :
11413 0 : WERROR _spoolss_65(struct pipes_struct *p,
11414 : struct spoolss_65 *r)
11415 : {
11416 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11417 0 : return WERR_NOT_SUPPORTED;
11418 : }
11419 :
11420 : /****************************************************************
11421 : _spoolss_GetCorePrinterDrivers
11422 : ****************************************************************/
11423 :
11424 8 : HRESULT _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
11425 : struct spoolss_GetCorePrinterDrivers *r)
11426 : {
11427 8 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11428 8 : return HRES_ERROR_NOT_SUPPORTED;
11429 : }
11430 :
11431 : /****************************************************************
11432 : _spoolss_67
11433 : ****************************************************************/
11434 :
11435 0 : WERROR _spoolss_67(struct pipes_struct *p,
11436 : struct spoolss_67 *r)
11437 : {
11438 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11439 0 : return WERR_NOT_SUPPORTED;
11440 : }
11441 :
11442 : /****************************************************************
11443 : _spoolss_GetPrinterDriverPackagePath
11444 : ****************************************************************/
11445 :
11446 4 : HRESULT _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
11447 : struct spoolss_GetPrinterDriverPackagePath *r)
11448 : {
11449 4 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11450 4 : return HRES_ERROR_NOT_SUPPORTED;
11451 : }
11452 :
11453 : /****************************************************************
11454 : _spoolss_69
11455 : ****************************************************************/
11456 :
11457 0 : WERROR _spoolss_69(struct pipes_struct *p,
11458 : struct spoolss_69 *r)
11459 : {
11460 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11461 0 : return WERR_NOT_SUPPORTED;
11462 : }
11463 :
11464 : /****************************************************************
11465 : _spoolss_6a
11466 : ****************************************************************/
11467 :
11468 0 : WERROR _spoolss_6a(struct pipes_struct *p,
11469 : struct spoolss_6a *r)
11470 : {
11471 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11472 0 : return WERR_NOT_SUPPORTED;
11473 : }
11474 :
11475 : /****************************************************************
11476 : _spoolss_6b
11477 : ****************************************************************/
11478 :
11479 0 : WERROR _spoolss_6b(struct pipes_struct *p,
11480 : struct spoolss_6b *r)
11481 : {
11482 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11483 0 : return WERR_NOT_SUPPORTED;
11484 : }
11485 :
11486 : /****************************************************************
11487 : _spoolss_6c
11488 : ****************************************************************/
11489 :
11490 0 : WERROR _spoolss_6c(struct pipes_struct *p,
11491 : struct spoolss_6c *r)
11492 : {
11493 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11494 0 : return WERR_NOT_SUPPORTED;
11495 : }
11496 :
11497 : /****************************************************************
11498 : _spoolss_6d
11499 : ****************************************************************/
11500 :
11501 0 : WERROR _spoolss_6d(struct pipes_struct *p,
11502 : struct spoolss_6d *r)
11503 : {
11504 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11505 0 : return WERR_NOT_SUPPORTED;
11506 : }
11507 :
11508 : /****************************************************************
11509 : _spoolss_GetJobNamedPropertyValue
11510 : ****************************************************************/
11511 :
11512 0 : WERROR _spoolss_GetJobNamedPropertyValue(struct pipes_struct *p,
11513 : struct spoolss_GetJobNamedPropertyValue *r)
11514 : {
11515 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11516 0 : return WERR_NOT_SUPPORTED;
11517 : }
11518 :
11519 : /****************************************************************
11520 : _spoolss_SetJobNamedProperty
11521 : ****************************************************************/
11522 :
11523 0 : WERROR _spoolss_SetJobNamedProperty(struct pipes_struct *p,
11524 : struct spoolss_SetJobNamedProperty *r)
11525 : {
11526 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11527 0 : return WERR_NOT_SUPPORTED;
11528 : }
11529 :
11530 : /****************************************************************
11531 : _spoolss_DeleteJobNamedProperty
11532 : ****************************************************************/
11533 :
11534 0 : WERROR _spoolss_DeleteJobNamedProperty(struct pipes_struct *p,
11535 : struct spoolss_DeleteJobNamedProperty *r)
11536 : {
11537 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11538 0 : return WERR_NOT_SUPPORTED;
11539 : }
11540 :
11541 : /****************************************************************
11542 : _spoolss_EnumJobNamedProperties
11543 : ****************************************************************/
11544 :
11545 0 : WERROR _spoolss_EnumJobNamedProperties(struct pipes_struct *p,
11546 : struct spoolss_EnumJobNamedProperties *r)
11547 : {
11548 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11549 0 : return WERR_NOT_SUPPORTED;
11550 : }
11551 :
11552 : /****************************************************************
11553 : _spoolss_72
11554 : ****************************************************************/
11555 :
11556 0 : WERROR _spoolss_72(struct pipes_struct *p,
11557 : struct spoolss_72 *r)
11558 : {
11559 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11560 0 : return WERR_NOT_SUPPORTED;
11561 : }
11562 :
11563 : /****************************************************************
11564 : _spoolss_73
11565 : ****************************************************************/
11566 :
11567 0 : WERROR _spoolss_73(struct pipes_struct *p,
11568 : struct spoolss_73 *r)
11569 : {
11570 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11571 0 : return WERR_NOT_SUPPORTED;
11572 : }
11573 :
11574 : /****************************************************************
11575 : _spoolss_RpcLogJobInfoForBranchOffice
11576 : ****************************************************************/
11577 :
11578 8 : WERROR _spoolss_LogJobInfoForBranchOffice(struct pipes_struct *p,
11579 : struct spoolss_LogJobInfoForBranchOffice *r)
11580 : {
11581 8 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11582 8 : return WERR_NOT_SUPPORTED;
11583 : }
11584 :
11585 : static NTSTATUS spoolss__op_init_server(struct dcesrv_context *dce_ctx,
11586 : const struct dcesrv_endpoint_server *ep_server);
11587 :
11588 : static NTSTATUS spoolss__op_shutdown_server(struct dcesrv_context *dce_ctx,
11589 : const struct dcesrv_endpoint_server *ep_server);
11590 :
11591 : #define DCESRV_INTERFACE_SPOOLSS_INIT_SERVER \
11592 : spoolss_init_server
11593 :
11594 : #define DCESRV_INTERFACE_SPOOLSS_SHUTDOWN_SERVER \
11595 : spoolss_shutdown_server
11596 :
11597 28 : static NTSTATUS spoolss_init_server(struct dcesrv_context *dce_ctx,
11598 : const struct dcesrv_endpoint_server *ep_server)
11599 : {
11600 28 : struct messaging_context *msg_ctx = global_messaging_context();
11601 0 : bool ok;
11602 :
11603 : /*
11604 : * Migrate the printers first.
11605 : */
11606 28 : ok = nt_printing_tdb_migrate(msg_ctx);
11607 28 : if (!ok) {
11608 0 : return NT_STATUS_UNSUCCESSFUL;
11609 : }
11610 :
11611 28 : return spoolss__op_init_server(dce_ctx, ep_server);
11612 : }
11613 :
11614 28 : static NTSTATUS spoolss_shutdown_server(struct dcesrv_context *dce_ctx,
11615 : const struct dcesrv_endpoint_server *ep_server)
11616 : {
11617 28 : srv_spoolss_cleanup();
11618 :
11619 28 : return spoolss__op_shutdown_server(dce_ctx, ep_server);
11620 : }
11621 :
11622 : /* include the generated boilerplate */
11623 : #include "librpc/gen_ndr/ndr_spoolss_scompat.c"
|