Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : * RPC Pipe client / server routines
4 : * Copyright (C) Andrew Tridgell 1992-2000,
5 : * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 : * Copyright (C) Jean François Micouleau 1998-2000,
7 : * Copyright (C) Jeremy Allison 2001-2002,
8 : * Copyright (C) Gerald Carter 2000-2004,
9 : * Copyright (C) Tim Potter 2001-2002.
10 : * Copyright (C) Guenther Deschner 2009-2010.
11 : * Copyright (C) Andreas Schneider 2010.
12 : *
13 : * This program is free software; you can redistribute it and/or modify
14 : * it under the terms of the GNU General Public License as published by
15 : * the Free Software Foundation; either version 3 of the License, or
16 : * (at your option) any later version.
17 : *
18 : * This program is distributed in the hope that it will be useful,
19 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 : * GNU General Public License for more details.
22 : *
23 : * You should have received a copy of the GNU General Public License
24 : * along with this program; if not, see <http://www.gnu.org/licenses/>.
25 : */
26 :
27 : /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28 : up, all the errors returned are DOS errors, not NT status codes. */
29 :
30 : #include "includes.h"
31 : #include "libsmb/namequery.h"
32 : #include "ntdomain.h"
33 : #include "nt_printing.h"
34 : #include "srv_spoolss_util.h"
35 : #include "librpc/gen_ndr/ndr_spoolss.h"
36 : #include "librpc/gen_ndr/ndr_spoolss_scompat.h"
37 : #include "../librpc/gen_ndr/ndr_spoolss_c.h"
38 : #include "rpc_client/init_spoolss.h"
39 : #include "rpc_client/cli_pipe.h"
40 : #include "../libcli/security/security.h"
41 : #include "librpc/gen_ndr/ndr_security.h"
42 : #include "registry.h"
43 : #include "include/printing.h"
44 : #include "secrets.h"
45 : #include "../librpc/gen_ndr/netlogon.h"
46 : #include "rpc_misc.h"
47 : #include "printing/notify.h"
48 : #include "serverid.h"
49 : #include "../libcli/registry/util_reg.h"
50 : #include "smbd/smbd.h"
51 : #include "smbd/globals.h"
52 : #include "auth.h"
53 : #include "messages.h"
54 : #include "rpc_server/spoolss/srv_spoolss_nt.h"
55 : #include "util_tdb.h"
56 : #include "libsmb/libsmb.h"
57 : #include "printing/printer_list.h"
58 : #include "../lib/tsocket/tsocket.h"
59 : #include "rpc_client/cli_winreg_spoolss.h"
60 : #include "../libcli/smb/smbXcli_base.h"
61 : #include "rpc_server/spoolss/srv_spoolss_handle.h"
62 : #include "lib/gencache.h"
63 : #include "rpc_server/rpc_server.h"
64 : #include "librpc/rpc/dcesrv_core.h"
65 : #include "printing/nt_printing_migrate_internal.h"
66 : #include "lib/util/string_wrappers.h"
67 : #include "lib/global_contexts.h"
68 :
69 : /* macros stolen from s4 spoolss server */
70 : #define SPOOLSS_BUFFER_UNION(fn,info,level) \
71 : ((info)?ndr_size_##fn(info, level, 0):0)
72 :
73 : #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
74 : ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
75 :
76 : #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
77 : ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
78 :
79 : #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
80 :
81 : #undef DBGC_CLASS
82 : #define DBGC_CLASS DBGC_RPC_SRV
83 :
84 : #ifndef MAX_OPEN_PRINTER_EXS
85 : #define MAX_OPEN_PRINTER_EXS 50
86 : #endif
87 :
88 : #define GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT 5
89 : #define GLOBAL_SPOOLSS_OS_MINOR_DEFAULT 2
90 : #define GLOBAL_SPOOLSS_OS_BUILD_DEFAULT 3790
91 : #define GLOBAL_SPOOLSS_ARCHITECTURE SPOOLSS_ARCHITECTURE_x64
92 :
93 : static struct printer_handle *printers_list;
94 :
95 : struct printer_session_counter {
96 : struct printer_session_counter *next;
97 : struct printer_session_counter *prev;
98 :
99 : int snum;
100 : uint32_t counter;
101 : };
102 :
103 : static struct printer_session_counter *counter_list;
104 :
105 : struct notify_back_channel {
106 : struct notify_back_channel *prev, *next;
107 :
108 : /* associated client */
109 : struct sockaddr_storage client_address;
110 :
111 : /* print notify back-channel pipe handle*/
112 : struct rpc_pipe_client *cli_pipe;
113 : struct cli_state *cli;
114 : uint32_t active_connections;
115 : };
116 :
117 : static struct notify_back_channel *back_channels;
118 :
119 : /* Map generic permissions to printer object specific permissions */
120 :
121 : const struct standard_mapping printer_std_mapping = {
122 : PRINTER_READ,
123 : PRINTER_WRITE,
124 : PRINTER_EXECUTE,
125 : PRINTER_ALL_ACCESS
126 : };
127 :
128 : /* Map generic permissions to print server object specific permissions */
129 :
130 : const struct standard_mapping printserver_std_mapping = {
131 : SERVER_READ,
132 : SERVER_WRITE,
133 : SERVER_EXECUTE,
134 : SERVER_ALL_ACCESS
135 : };
136 :
137 : /* API table for Xcv Monitor functions */
138 :
139 : struct xcv_api_table {
140 : const char *name;
141 : WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
142 : };
143 :
144 : static void prune_printername_cache(void);
145 :
146 : /********************************************************************
147 : * Canonicalize servername.
148 : ********************************************************************/
149 :
150 520 : static const char *canon_servername(const char *servername)
151 : {
152 520 : const char *pservername = servername;
153 :
154 520 : if (servername == NULL) {
155 0 : return "";
156 : }
157 :
158 1568 : while (*pservername == '\\') {
159 1048 : pservername++;
160 : }
161 520 : return pservername;
162 : }
163 :
164 : /* translate between internal status numbers and NT status numbers */
165 392 : static int nt_printj_status(int v)
166 : {
167 392 : switch (v) {
168 392 : case LPQ_QUEUED:
169 392 : return 0;
170 0 : case LPQ_PAUSED:
171 0 : return JOB_STATUS_PAUSED;
172 0 : case LPQ_SPOOLING:
173 0 : return JOB_STATUS_SPOOLING;
174 0 : case LPQ_PRINTING:
175 0 : return JOB_STATUS_PRINTING;
176 0 : case LPQ_ERROR:
177 0 : return JOB_STATUS_ERROR;
178 0 : case LPQ_DELETING:
179 0 : return JOB_STATUS_DELETING;
180 0 : case LPQ_OFFLINE:
181 0 : return JOB_STATUS_OFFLINE;
182 0 : case LPQ_PAPEROUT:
183 0 : return JOB_STATUS_PAPEROUT;
184 0 : case LPQ_PRINTED:
185 0 : return JOB_STATUS_PRINTED;
186 0 : case LPQ_DELETED:
187 0 : return JOB_STATUS_DELETED;
188 0 : case LPQ_BLOCKED:
189 0 : return JOB_STATUS_BLOCKED_DEVQ;
190 0 : case LPQ_USER_INTERVENTION:
191 0 : return JOB_STATUS_USER_INTERVENTION;
192 : }
193 0 : return 0;
194 : }
195 :
196 1636 : static int nt_printq_status(int v)
197 : {
198 1636 : switch (v) {
199 233 : case LPQ_PAUSED:
200 233 : return PRINTER_STATUS_PAUSED;
201 1403 : case LPQ_QUEUED:
202 : case LPQ_SPOOLING:
203 : case LPQ_PRINTING:
204 1403 : return 0;
205 : }
206 0 : return 0;
207 : }
208 :
209 : /***************************************************************************
210 : Disconnect from the client
211 : ****************************************************************************/
212 :
213 2 : static void srv_spoolss_replycloseprinter(int snum,
214 : struct printer_handle *prn_hnd)
215 : {
216 0 : WERROR result;
217 0 : NTSTATUS status;
218 :
219 : /*
220 : * Tell the specific printing tdb we no longer want messages for this printer
221 : * by deregistering our PID.
222 : */
223 :
224 2 : if (!print_notify_deregister_pid(snum)) {
225 0 : DEBUG(0, ("Failed to register our pid for printer %s\n",
226 : lp_const_servicename(snum)));
227 : }
228 :
229 : /* weird if the test succeeds !!! */
230 2 : if (prn_hnd->notify.cli_chan == NULL ||
231 2 : prn_hnd->notify.cli_chan->cli_pipe == NULL ||
232 2 : prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
233 2 : prn_hnd->notify.cli_chan->active_connections == 0) {
234 0 : DEBUG(0, ("Trying to close unexisting backchannel!\n"));
235 0 : DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
236 0 : TALLOC_FREE(prn_hnd->notify.cli_chan);
237 0 : return;
238 : }
239 :
240 2 : status = dcerpc_spoolss_ReplyClosePrinter(
241 2 : prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
242 : talloc_tos(),
243 : &prn_hnd->notify.cli_hnd,
244 : &result);
245 2 : if (!NT_STATUS_IS_OK(status)) {
246 0 : DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
247 : nt_errstr(status)));
248 0 : result = ntstatus_to_werror(status);
249 2 : } else if (!W_ERROR_IS_OK(result)) {
250 0 : DEBUG(0, ("reply_close_printer failed [%s].\n",
251 : win_errstr(result)));
252 : }
253 :
254 : /* if it's the last connection, deconnect the IPC$ share */
255 2 : if (prn_hnd->notify.cli_chan->active_connections == 1) {
256 :
257 2 : cli_shutdown(prn_hnd->notify.cli_chan->cli);
258 2 : DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
259 2 : TALLOC_FREE(prn_hnd->notify.cli_chan);
260 :
261 2 : if (prn_hnd->notify.msg_ctx != NULL) {
262 2 : messaging_deregister(prn_hnd->notify.msg_ctx,
263 : MSG_PRINTER_NOTIFY2, NULL);
264 : }
265 : }
266 :
267 2 : if (prn_hnd->notify.cli_chan) {
268 0 : prn_hnd->notify.cli_chan->active_connections--;
269 0 : prn_hnd->notify.cli_chan = NULL;
270 : }
271 : }
272 :
273 : /****************************************************************************
274 : Functions to free a printer entry datastruct.
275 : ****************************************************************************/
276 :
277 972 : static int printer_entry_destructor(struct printer_handle *Printer)
278 : {
279 972 : if (Printer->notify.cli_chan != NULL &&
280 2 : Printer->notify.cli_chan->active_connections > 0) {
281 2 : int snum = -1;
282 :
283 2 : switch(Printer->printer_type) {
284 2 : case SPLHND_SERVER:
285 2 : srv_spoolss_replycloseprinter(snum, Printer);
286 2 : break;
287 :
288 0 : case SPLHND_PRINTER:
289 0 : snum = print_queue_snum(Printer->sharename);
290 0 : if (snum != -1) {
291 0 : srv_spoolss_replycloseprinter(snum, Printer);
292 : }
293 0 : break;
294 0 : default:
295 0 : break;
296 : }
297 : }
298 :
299 972 : Printer->notify.flags=0;
300 972 : Printer->notify.options=0;
301 972 : Printer->notify.localmachine[0]='\0';
302 972 : Printer->notify.printerlocal=0;
303 972 : TALLOC_FREE(Printer->notify.option);
304 972 : TALLOC_FREE(Printer->devmode);
305 :
306 : /* Remove from the internal list. */
307 972 : DLIST_REMOVE(printers_list, Printer);
308 972 : return 0;
309 : }
310 :
311 : /****************************************************************************
312 : find printer index by handle
313 : ****************************************************************************/
314 :
315 52178 : static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
316 : struct policy_handle *hnd)
317 : {
318 52178 : struct printer_handle *find_printer = NULL;
319 0 : NTSTATUS status;
320 :
321 52178 : find_printer = find_policy_by_hnd(p,
322 : hnd,
323 : DCESRV_HANDLE_ANY,
324 : struct printer_handle,
325 0 : &status);
326 52178 : if (!NT_STATUS_IS_OK(status)) {
327 0 : DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: %s\n",
328 : nt_errstr(status)));
329 0 : return NULL;
330 : }
331 :
332 52178 : return find_printer;
333 : }
334 :
335 : /****************************************************************************
336 : Close printer index by handle.
337 : ****************************************************************************/
338 :
339 956 : static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
340 : {
341 956 : struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
342 :
343 956 : if (!Printer) {
344 0 : DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
345 : OUR_HANDLE(hnd)));
346 0 : return false;
347 : }
348 :
349 956 : close_policy_hnd(p, hnd);
350 :
351 956 : return true;
352 : }
353 :
354 : /****************************************************************************
355 : Delete a printer given a handle.
356 : ****************************************************************************/
357 :
358 16 : static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
359 : const char *sharename,
360 : struct messaging_context *msg_ctx)
361 : {
362 0 : const struct loadparm_substitution *lp_sub =
363 16 : loadparm_s3_global_substitution();
364 16 : char *cmd = lp_deleteprinter_command(talloc_tos(), lp_sub);
365 16 : char *command = NULL;
366 0 : int ret;
367 16 : bool is_print_op = false;
368 :
369 : /* can't fail if we don't try */
370 :
371 16 : if ( !*cmd )
372 0 : return WERR_OK;
373 :
374 16 : command = talloc_asprintf(ctx,
375 : "%s \"%s\"",
376 : cmd, sharename);
377 16 : if (!command) {
378 0 : return WERR_NOT_ENOUGH_MEMORY;
379 : }
380 16 : if ( token )
381 16 : is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
382 :
383 16 : DEBUG(10,("Running [%s]\n", command));
384 :
385 : /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
386 :
387 16 : if ( is_print_op )
388 0 : become_root();
389 :
390 16 : ret = smbrun(command, NULL, NULL);
391 16 : if (ret == 0) {
392 : /* Tell everyone we updated smb.conf. */
393 16 : messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
394 : }
395 :
396 16 : if ( is_print_op )
397 0 : unbecome_root();
398 :
399 : /********** END SePrintOperatorPrivlege BLOCK **********/
400 :
401 16 : DEBUGADD(10,("returned [%d]\n", ret));
402 :
403 16 : TALLOC_FREE(command);
404 :
405 16 : if (ret != 0)
406 0 : return WERR_INVALID_HANDLE; /* What to return here? */
407 :
408 16 : return WERR_OK;
409 : }
410 :
411 : /****************************************************************************
412 : Delete a printer given a handle.
413 : ****************************************************************************/
414 :
415 16 : static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
416 : {
417 16 : struct dcesrv_call_state *dce_call = p->dce_call;
418 0 : struct auth_session_info *session_info =
419 16 : dcesrv_call_session_info(dce_call);
420 16 : struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
421 0 : WERROR result;
422 :
423 16 : if (!Printer) {
424 0 : DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
425 : OUR_HANDLE(hnd)));
426 0 : return WERR_INVALID_HANDLE;
427 : }
428 :
429 : /*
430 : * It turns out that Windows allows delete printer on a handle
431 : * opened by an admin user, then used on a pipe handle created
432 : * by an anonymous user..... but they're working on security.... riiight !
433 : * JRA.
434 : */
435 :
436 16 : if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
437 0 : DEBUG(3, ("delete_printer_handle: denied by handle\n"));
438 0 : return WERR_ACCESS_DENIED;
439 : }
440 :
441 : /* this does not need a become root since the access check has been
442 : done on the handle already */
443 :
444 16 : result = winreg_delete_printer_key_internal(p->mem_ctx,
445 : get_session_info_system(),
446 : p->msg_ctx,
447 16 : Printer->sharename,
448 : "");
449 16 : if (!W_ERROR_IS_OK(result)) {
450 0 : DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
451 0 : return WERR_INVALID_HANDLE;
452 : }
453 :
454 16 : result = delete_printer_hook(p->mem_ctx, session_info->security_token,
455 16 : Printer->sharename, p->msg_ctx);
456 16 : if (!W_ERROR_IS_OK(result)) {
457 0 : return result;
458 : }
459 16 : prune_printername_cache();
460 16 : return WERR_OK;
461 : }
462 :
463 : /****************************************************************************
464 : Return the snum of a printer corresponding to an handle.
465 : ****************************************************************************/
466 :
467 24720 : static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
468 : int *number, struct share_params **params)
469 : {
470 24720 : struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
471 :
472 24720 : if (!Printer) {
473 0 : DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
474 : OUR_HANDLE(hnd)));
475 0 : return false;
476 : }
477 :
478 24720 : switch (Printer->printer_type) {
479 24720 : case SPLHND_PRINTER:
480 24720 : DEBUG(4,("short name:%s\n", Printer->sharename));
481 24720 : *number = print_queue_snum(Printer->sharename);
482 24720 : return (*number != -1);
483 0 : case SPLHND_SERVER:
484 0 : return false;
485 0 : default:
486 0 : return false;
487 : }
488 : }
489 :
490 : /****************************************************************************
491 : Set printer handle type.
492 : Check if it's \\server or \\server\printer
493 : ****************************************************************************/
494 :
495 972 : static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
496 : {
497 972 : DEBUG(3,("Setting printer type=%s\n", handlename));
498 :
499 : /* it's a print server */
500 972 : if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
501 122 : DEBUGADD(4,("Printer is a print server\n"));
502 122 : Printer->printer_type = SPLHND_SERVER;
503 : }
504 : /* it's a printer (set_printer_hnd_name() will handle port monitors */
505 : else {
506 850 : DEBUGADD(4,("Printer is a printer\n"));
507 850 : Printer->printer_type = SPLHND_PRINTER;
508 : }
509 :
510 972 : return true;
511 : }
512 :
513 372 : static void prune_printername_cache_fn(const char *key, const char *value,
514 : time_t timeout, void *private_data)
515 : {
516 372 : gencache_del(key);
517 372 : }
518 :
519 132 : static void prune_printername_cache(void)
520 : {
521 132 : gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
522 132 : }
523 :
524 : /****************************************************************************
525 : Set printer handle name.. Accept names like \\server, \\server\printer,
526 : \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
527 : the MSDN docs regarding OpenPrinter() for details on the XcvData() and
528 : XcvDataPort() interface.
529 : ****************************************************************************/
530 :
531 972 : static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
532 : const struct auth_session_info *session_info,
533 : struct messaging_context *msg_ctx,
534 : struct printer_handle *Printer,
535 : const char *handlename)
536 : {
537 0 : int snum;
538 972 : int n_services=lp_numservices();
539 0 : char *aprinter;
540 0 : const char *printername;
541 972 : const char *servername = NULL;
542 0 : fstring sname;
543 972 : bool found = false;
544 972 : struct spoolss_PrinterInfo2 *info2 = NULL;
545 0 : WERROR result;
546 0 : char *p;
547 :
548 : /*
549 : * Hopefully nobody names his printers like this. Maybe \ or ,
550 : * are illegal in printer names even?
551 : */
552 972 : const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
553 0 : char *cache_key;
554 0 : char *tmp;
555 :
556 972 : DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
557 : (unsigned long)strlen(handlename)));
558 :
559 972 : aprinter = discard_const_p(char, handlename);
560 972 : if ( *handlename == '\\' ) {
561 252 : servername = canon_servername(handlename);
562 252 : if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
563 122 : *aprinter = '\0';
564 122 : aprinter++;
565 : }
566 252 : if (!is_myname_or_ipaddr(servername)) {
567 12 : return WERR_INVALID_PRINTER_NAME;
568 : }
569 240 : Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
570 240 : if (Printer->servername == NULL) {
571 0 : return WERR_NOT_ENOUGH_MEMORY;
572 : }
573 : }
574 :
575 960 : if (Printer->printer_type == SPLHND_SERVER) {
576 118 : return WERR_OK;
577 : }
578 :
579 842 : if (Printer->printer_type != SPLHND_PRINTER) {
580 0 : return WERR_INVALID_HANDLE;
581 : }
582 :
583 842 : DEBUGADD(5, ("searching for [%s]\n", aprinter));
584 :
585 842 : p = strchr(aprinter, ',');
586 842 : if (p != NULL) {
587 504 : char *p2 = p;
588 504 : p++;
589 504 : if (*p == ' ') {
590 308 : p++;
591 : }
592 504 : if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
593 140 : *p2 = '\0';
594 364 : } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
595 140 : *p2 = '\0';
596 : }
597 : }
598 :
599 842 : if (p) {
600 504 : DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
601 : }
602 :
603 : /* check for the Port Monitor Interface */
604 842 : if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
605 0 : Printer->printer_type = SPLHND_PORTMON_TCP;
606 0 : fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
607 0 : found = true;
608 : }
609 842 : else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
610 0 : Printer->printer_type = SPLHND_PORTMON_LOCAL;
611 0 : fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
612 0 : found = true;
613 : }
614 :
615 842 : cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s", aprinter);
616 842 : if (cache_key == NULL) {
617 0 : return WERR_NOT_ENOUGH_MEMORY;
618 : }
619 :
620 : /*
621 : * With hundreds of printers, the "for" loop iterating all
622 : * shares can be quite expensive, as it is done on every
623 : * OpenPrinter. The loop maps "aprinter" to "sname", the
624 : * result of which we cache in gencache.
625 : */
626 842 : if (gencache_get(cache_key, talloc_tos(), &tmp, NULL)) {
627 462 : found = (strcmp(tmp, printer_not_found) != 0);
628 462 : if (!found) {
629 32 : DEBUG(4, ("Printer %s not found\n", aprinter));
630 32 : TALLOC_FREE(tmp);
631 32 : return WERR_INVALID_PRINTER_NAME;
632 : }
633 430 : fstrcpy(sname, tmp);
634 430 : TALLOC_FREE(tmp);
635 : }
636 :
637 : /* Search all sharenames first as this is easier than pulling
638 : the printer_info_2 off of disk. Don't use find_service() since
639 : that calls out to map_username() */
640 :
641 : /* do another loop to look for printernames */
642 23566 : for (snum = 0; !found && snum < n_services; snum++) {
643 22848 : const char *printer = lp_const_servicename(snum);
644 :
645 : /* no point going on if this is not a printer */
646 22848 : if (!(lp_snum_ok(snum) && lp_printable(snum))) {
647 20970 : continue;
648 : }
649 :
650 : /* ignore [printers] share */
651 1878 : if (strequal(printer, "printers")) {
652 0 : continue;
653 : }
654 :
655 1878 : fstrcpy(sname, printer);
656 1878 : if (strequal(aprinter, printer)) {
657 84 : found = true;
658 84 : break;
659 : }
660 :
661 : /* no point looking up the printer object if
662 : we aren't allowing printername != sharename */
663 1794 : if (lp_force_printername(snum)) {
664 0 : continue;
665 : }
666 :
667 1794 : result = winreg_get_printer_internal(mem_ctx,
668 : session_info,
669 : msg_ctx,
670 : sname,
671 : &info2);
672 1794 : if ( !W_ERROR_IS_OK(result) ) {
673 54 : DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
674 : sname, win_errstr(result)));
675 54 : continue;
676 : }
677 :
678 1740 : printername = strrchr(info2->printername, '\\');
679 1740 : if (printername == NULL) {
680 1740 : printername = info2->printername;
681 : } else {
682 0 : printername++;
683 : }
684 :
685 1740 : if (strequal(printername, aprinter)) {
686 8 : found = true;
687 8 : break;
688 : }
689 :
690 1732 : DEBUGADD(10, ("printername: %s\n", printername));
691 :
692 1732 : TALLOC_FREE(info2);
693 : }
694 :
695 810 : if (!found) {
696 288 : gencache_set(cache_key, printer_not_found,
697 288 : time(NULL) + 300);
698 288 : TALLOC_FREE(cache_key);
699 288 : DEBUGADD(4,("Printer not found\n"));
700 288 : return WERR_INVALID_PRINTER_NAME;
701 : }
702 :
703 522 : gencache_set(cache_key, sname, time(NULL) + 300);
704 522 : TALLOC_FREE(cache_key);
705 :
706 522 : DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
707 :
708 522 : strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
709 :
710 522 : return WERR_OK;
711 : }
712 :
713 : /****************************************************************************
714 : Find first available printer slot. creates a printer handle for you.
715 : ****************************************************************************/
716 :
717 972 : static WERROR open_printer_hnd(struct pipes_struct *p,
718 : struct policy_handle *hnd,
719 : const char *name,
720 : uint32_t access_granted)
721 : {
722 0 : struct printer_handle *new_printer;
723 0 : WERROR result;
724 :
725 972 : DEBUG(10,("open_printer_hnd: name [%s]\n", name));
726 :
727 972 : new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
728 972 : if (new_printer == NULL) {
729 0 : return WERR_NOT_ENOUGH_MEMORY;
730 : }
731 972 : talloc_set_destructor(new_printer, printer_entry_destructor);
732 :
733 : /* This also steals the printer_handle on the policy_handle */
734 972 : if (!create_policy_hnd(p, hnd, 0, new_printer)) {
735 0 : TALLOC_FREE(new_printer);
736 0 : return WERR_INVALID_HANDLE;
737 : }
738 :
739 : /* Add to the internal list. */
740 972 : DLIST_ADD(printers_list, new_printer);
741 :
742 972 : new_printer->notify.option=NULL;
743 :
744 972 : if (!set_printer_hnd_printertype(new_printer, name)) {
745 0 : close_printer_handle(p, hnd);
746 0 : return WERR_INVALID_HANDLE;
747 : }
748 :
749 972 : result = set_printer_hnd_name(p->mem_ctx,
750 : get_session_info_system(),
751 : p->msg_ctx,
752 : new_printer, name);
753 972 : if (!W_ERROR_IS_OK(result)) {
754 332 : close_printer_handle(p, hnd);
755 332 : return result;
756 : }
757 :
758 640 : new_printer->access_granted = access_granted;
759 :
760 640 : DBG_INFO("%d printer handles active\n", (int)num_pipe_handles());
761 :
762 640 : return WERR_OK;
763 : }
764 :
765 : /***************************************************************************
766 : check to see if the client notify handle is monitoring the notification
767 : given by (notify_type, notify_field).
768 : **************************************************************************/
769 :
770 0 : static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
771 : uint16_t notify_field)
772 : {
773 0 : return true;
774 : }
775 :
776 0 : static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
777 : uint16_t notify_field)
778 : {
779 0 : struct spoolss_NotifyOption *option = p->notify.option;
780 0 : uint32_t i, j;
781 :
782 : /*
783 : * Flags should always be zero when the change notify
784 : * is registered by the client's spooler. A user Win32 app
785 : * might use the flags though instead of the NOTIFY_OPTION_INFO
786 : * --jerry
787 : */
788 :
789 0 : if (!option) {
790 0 : return false;
791 : }
792 :
793 0 : if (p->notify.flags)
794 0 : return is_monitoring_event_flags(
795 : p->notify.flags, notify_type, notify_field);
796 :
797 0 : for (i = 0; i < option->count; i++) {
798 :
799 : /* Check match for notify_type */
800 :
801 0 : if (option->types[i].type != notify_type)
802 0 : continue;
803 :
804 : /* Check match for field */
805 :
806 0 : for (j = 0; j < option->types[i].count; j++) {
807 0 : if (option->types[i].fields[j].field == notify_field) {
808 0 : return true;
809 : }
810 : }
811 : }
812 :
813 0 : DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
814 : p->servername, p->sharename, notify_type, notify_field));
815 :
816 0 : return false;
817 : }
818 :
819 : #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
820 : _data->data.integer[0] = _integer; \
821 : _data->data.integer[1] = 0;
822 :
823 :
824 : #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
825 : _data->data.string.string = talloc_strdup(mem_ctx, _p); \
826 : if (!_data->data.string.string) {\
827 : _data->data.string.size = 0; \
828 : } \
829 : _data->data.string.size = strlen_m_term(_p) * 2;
830 :
831 : #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
832 : _data->data.devmode.devmode = _devmode;
833 :
834 0 : static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
835 : struct tm *t,
836 : const char **pp,
837 : uint32_t *plen)
838 : {
839 0 : struct spoolss_Time st;
840 0 : uint32_t len = 16;
841 0 : char *p;
842 :
843 0 : if (!init_systemtime(&st, t)) {
844 0 : return;
845 : }
846 :
847 0 : p = talloc_array(mem_ctx, char, len);
848 0 : if (!p) {
849 0 : return;
850 : }
851 :
852 : /*
853 : * Systemtime must be linearized as a set of UINT16's.
854 : * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
855 : */
856 :
857 0 : SSVAL(p, 0, st.year);
858 0 : SSVAL(p, 2, st.month);
859 0 : SSVAL(p, 4, st.day_of_week);
860 0 : SSVAL(p, 6, st.day);
861 0 : SSVAL(p, 8, st.hour);
862 0 : SSVAL(p, 10, st.minute);
863 0 : SSVAL(p, 12, st.second);
864 0 : SSVAL(p, 14, st.millisecond);
865 :
866 0 : *pp = p;
867 0 : *plen = len;
868 : }
869 :
870 : /* Convert a notification message to a struct spoolss_Notify */
871 :
872 0 : static void notify_one_value(struct spoolss_notify_msg *msg,
873 : struct spoolss_Notify *data,
874 : TALLOC_CTX *mem_ctx)
875 : {
876 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
877 0 : }
878 :
879 0 : static void notify_string(struct spoolss_notify_msg *msg,
880 : struct spoolss_Notify *data,
881 : TALLOC_CTX *mem_ctx)
882 : {
883 : /* The length of the message includes the trailing \0 */
884 :
885 0 : data->data.string.size = msg->len * 2;
886 0 : data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
887 0 : if (!data->data.string.string) {
888 0 : data->data.string.size = 0;
889 0 : return;
890 : }
891 : }
892 :
893 0 : static void notify_system_time(struct spoolss_notify_msg *msg,
894 : struct spoolss_Notify *data,
895 : TALLOC_CTX *mem_ctx)
896 : {
897 0 : data->data.string.string = NULL;
898 0 : data->data.string.size = 0;
899 :
900 0 : if (msg->len != sizeof(time_t)) {
901 0 : DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
902 : msg->len));
903 0 : return;
904 : }
905 :
906 0 : init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
907 : &data->data.string.string,
908 : &data->data.string.size);
909 : }
910 :
911 : struct notify2_message_table {
912 : const char *name;
913 : void (*fn)(struct spoolss_notify_msg *msg,
914 : struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
915 : };
916 :
917 : static struct notify2_message_table printer_notify_table[] = {
918 : /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
919 : /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
920 : /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
921 : /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
922 : /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
923 : /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
924 : /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
925 : /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
926 : /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
927 : /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
928 : /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
929 : /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
930 : /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
931 : /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
932 : /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
933 : /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
934 : /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
935 : /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
936 : /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
937 : };
938 :
939 : static struct notify2_message_table job_notify_table[] = {
940 : /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
941 : /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
942 : /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
943 : /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
944 : /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
945 : /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
946 : /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
947 : /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
948 : /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
949 : /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
950 : /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
951 : /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
952 : /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
953 : /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
954 : /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
955 : /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
956 : /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
957 : /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
958 : /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
959 : /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
960 : /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
961 : /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
962 : /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
963 : /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
964 : };
965 :
966 :
967 : /***********************************************************************
968 : Allocate talloc context for container object
969 : **********************************************************************/
970 :
971 0 : static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
972 : {
973 0 : if ( !ctr )
974 0 : return;
975 :
976 0 : ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
977 :
978 0 : return;
979 : }
980 :
981 : /***********************************************************************
982 : release all allocated memory and zero out structure
983 : **********************************************************************/
984 :
985 0 : static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
986 : {
987 0 : if ( !ctr )
988 0 : return;
989 :
990 0 : if ( ctr->ctx )
991 0 : talloc_destroy(ctr->ctx);
992 :
993 0 : ZERO_STRUCTP(ctr);
994 :
995 0 : return;
996 : }
997 :
998 : /***********************************************************************
999 : **********************************************************************/
1000 :
1001 0 : static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1002 : {
1003 0 : if ( !ctr )
1004 0 : return NULL;
1005 :
1006 0 : return ctr->ctx;
1007 : }
1008 :
1009 : /***********************************************************************
1010 : **********************************************************************/
1011 :
1012 0 : static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1013 : {
1014 0 : if ( !ctr || !ctr->msg_groups )
1015 0 : return NULL;
1016 :
1017 0 : if ( idx >= ctr->num_groups )
1018 0 : return NULL;
1019 :
1020 0 : return &ctr->msg_groups[idx];
1021 :
1022 : }
1023 :
1024 : /***********************************************************************
1025 : How many groups of change messages do we have ?
1026 : **********************************************************************/
1027 :
1028 0 : static uint32_t notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1029 : {
1030 0 : if ( !ctr )
1031 0 : return 0;
1032 :
1033 0 : return ctr->num_groups;
1034 : }
1035 :
1036 : /***********************************************************************
1037 : Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1038 : **********************************************************************/
1039 :
1040 0 : static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1041 : {
1042 0 : SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
1043 0 : SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
1044 0 : SPOOLSS_NOTIFY_MSG *msg_list = NULL;
1045 0 : uint32_t i, new_slot;
1046 :
1047 0 : if ( !ctr || !msg )
1048 0 : return 0;
1049 :
1050 : /* loop over all groups looking for a matching printer name */
1051 :
1052 0 : for ( i=0; i<ctr->num_groups; i++ ) {
1053 0 : if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1054 0 : break;
1055 : }
1056 :
1057 : /* add a new group? */
1058 :
1059 0 : if ( i == ctr->num_groups ) {
1060 0 : ctr->num_groups++;
1061 :
1062 0 : if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1063 0 : DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1064 0 : return 0;
1065 : }
1066 0 : ctr->msg_groups = groups;
1067 :
1068 : /* clear the new entry and set the printer name */
1069 :
1070 0 : ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1071 0 : fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1072 : }
1073 :
1074 : /* add the change messages; 'i' is the correct index now regardless */
1075 :
1076 0 : msg_grp = &ctr->msg_groups[i];
1077 :
1078 0 : msg_grp->num_msgs++;
1079 :
1080 0 : if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1081 0 : DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1082 0 : return 0;
1083 : }
1084 0 : msg_grp->msgs = msg_list;
1085 :
1086 0 : new_slot = msg_grp->num_msgs-1;
1087 0 : memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1088 :
1089 : /* need to allocate own copy of data */
1090 :
1091 0 : if ( msg->len != 0 )
1092 0 : msg_grp->msgs[new_slot].notify.data = (char *)
1093 0 : talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1094 :
1095 0 : return ctr->num_groups;
1096 : }
1097 :
1098 : static void construct_info_data(struct spoolss_Notify *info_data,
1099 : enum spoolss_NotifyType type,
1100 : uint16_t field, int id);
1101 :
1102 : /***********************************************************************
1103 : Send a change notification message on all handles which have a call
1104 : back registered
1105 : **********************************************************************/
1106 :
1107 0 : static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1108 : struct printer_handle *prn_hnd,
1109 : SPOOLSS_NOTIFY_MSG *messages,
1110 : uint32_t num_msgs,
1111 : struct spoolss_Notify **_notifies,
1112 : size_t *_count)
1113 : {
1114 0 : struct spoolss_Notify *notifies;
1115 0 : SPOOLSS_NOTIFY_MSG *msg;
1116 0 : size_t count = 0;
1117 0 : uint32_t id;
1118 0 : uint32_t i;
1119 :
1120 0 : notifies = talloc_zero_array(mem_ctx,
1121 : struct spoolss_Notify, num_msgs);
1122 0 : if (!notifies) {
1123 0 : return ENOMEM;
1124 : }
1125 :
1126 0 : for (i = 0; i < num_msgs; i++) {
1127 :
1128 0 : msg = &messages[i];
1129 :
1130 : /* Are we monitoring this event? */
1131 :
1132 0 : if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1133 0 : continue;
1134 : }
1135 :
1136 0 : DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1137 : "for printer [%s]\n",
1138 : msg->type, msg->field, prn_hnd->sharename));
1139 :
1140 : /*
1141 : * if the is a printer notification handle and not a job
1142 : * notification type, then set the id to 0.
1143 : * Otherwise just use what was specified in the message.
1144 : *
1145 : * When registering change notification on a print server
1146 : * handle we always need to send back the id (snum) matching
1147 : * the printer for which the change took place.
1148 : * For change notify registered on a printer handle,
1149 : * this does not matter and the id should be 0.
1150 : *
1151 : * --jerry
1152 : */
1153 :
1154 0 : if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1155 0 : (prn_hnd->printer_type == SPLHND_PRINTER)) {
1156 0 : id = 0;
1157 : } else {
1158 0 : id = msg->id;
1159 : }
1160 :
1161 : /* Convert unix jobid to smb jobid */
1162 :
1163 0 : if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1164 0 : id = sysjob_to_jobid(msg->id);
1165 :
1166 0 : if (id == -1) {
1167 0 : DEBUG(3, ("no such unix jobid %d\n",
1168 : msg->id));
1169 0 : continue;
1170 : }
1171 : }
1172 :
1173 0 : construct_info_data(¬ifies[count],
1174 0 : msg->type, msg->field, id);
1175 :
1176 0 : switch(msg->type) {
1177 0 : case PRINTER_NOTIFY_TYPE:
1178 0 : if (printer_notify_table[msg->field].fn) {
1179 0 : printer_notify_table[msg->field].fn(msg,
1180 0 : ¬ifies[count], mem_ctx);
1181 : }
1182 0 : break;
1183 :
1184 0 : case JOB_NOTIFY_TYPE:
1185 0 : if (job_notify_table[msg->field].fn) {
1186 0 : job_notify_table[msg->field].fn(msg,
1187 0 : ¬ifies[count], mem_ctx);
1188 : }
1189 0 : break;
1190 :
1191 0 : default:
1192 0 : DEBUG(5, ("Unknown notification type %d\n",
1193 : msg->type));
1194 0 : continue;
1195 : }
1196 :
1197 0 : count++;
1198 : }
1199 :
1200 0 : *_notifies = notifies;
1201 0 : *_count = count;
1202 :
1203 0 : return 0;
1204 : }
1205 :
1206 0 : static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1207 : struct printer_handle *prn_hnd,
1208 : SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1209 : {
1210 0 : struct spoolss_Notify *notifies;
1211 0 : size_t count = 0;
1212 0 : union spoolss_ReplyPrinterInfo info;
1213 0 : struct spoolss_NotifyInfo info0;
1214 0 : uint32_t reply_result;
1215 0 : NTSTATUS status;
1216 0 : WERROR werr;
1217 0 : int ret;
1218 :
1219 : /* Is there notification on this handle? */
1220 0 : if (prn_hnd->notify.cli_chan == NULL ||
1221 0 : prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1222 0 : prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1223 0 : prn_hnd->notify.cli_chan->active_connections == 0) {
1224 0 : return 0;
1225 : }
1226 :
1227 0 : DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1228 : prn_hnd->servername, prn_hnd->sharename));
1229 :
1230 : /* For this printer? Print servers always receive notifications. */
1231 0 : if ((prn_hnd->printer_type == SPLHND_PRINTER) &&
1232 0 : (!strequal(msg_group->printername, prn_hnd->sharename))) {
1233 0 : return 0;
1234 : }
1235 :
1236 0 : DEBUG(10,("Our printer\n"));
1237 :
1238 : /* build the array of change notifications */
1239 0 : ret = build_notify2_messages(mem_ctx, prn_hnd,
1240 : msg_group->msgs,
1241 : msg_group->num_msgs,
1242 : ¬ifies, &count);
1243 0 : if (ret) {
1244 0 : return ret;
1245 : }
1246 :
1247 0 : info0.version = 0x2;
1248 0 : info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1249 0 : info0.count = count;
1250 0 : info0.notifies = notifies;
1251 :
1252 0 : info.info0 = &info0;
1253 :
1254 0 : status = dcerpc_spoolss_RouterReplyPrinterEx(
1255 0 : prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1256 : mem_ctx,
1257 : &prn_hnd->notify.cli_hnd,
1258 : prn_hnd->notify.change, /* color */
1259 : prn_hnd->notify.flags,
1260 : &reply_result,
1261 : 0, /* reply_type, must be 0 */
1262 : info, &werr);
1263 0 : if (!NT_STATUS_IS_OK(status)) {
1264 0 : DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1265 : "failed: %s\n",
1266 : prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1267 : nt_errstr(status)));
1268 0 : werr = ntstatus_to_werror(status);
1269 0 : } else if (!W_ERROR_IS_OK(werr)) {
1270 0 : DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1271 : "failed: %s\n",
1272 : prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1273 : win_errstr(werr)));
1274 : }
1275 0 : switch (reply_result) {
1276 0 : case 0:
1277 0 : break;
1278 0 : case PRINTER_NOTIFY_INFO_DISCARDED:
1279 : case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1280 : case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1281 0 : break;
1282 0 : default:
1283 0 : break;
1284 : }
1285 :
1286 0 : return 0;
1287 : }
1288 :
1289 0 : static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1290 : {
1291 0 : struct printer_handle *p;
1292 0 : TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1293 0 : SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1294 0 : int ret;
1295 :
1296 0 : if ( !msg_group ) {
1297 0 : DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1298 0 : return;
1299 : }
1300 :
1301 0 : if (!msg_group->msgs) {
1302 0 : DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1303 0 : return;
1304 : }
1305 :
1306 0 : DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1307 :
1308 : /* loop over all printers */
1309 :
1310 0 : for (p = printers_list; p; p = p->next) {
1311 0 : ret = send_notify2_printer(mem_ctx, p, msg_group);
1312 0 : if (ret) {
1313 0 : goto done;
1314 : }
1315 : }
1316 :
1317 0 : done:
1318 0 : DEBUG(8,("send_notify2_changes: Exit...\n"));
1319 0 : return;
1320 : }
1321 :
1322 : /***********************************************************************
1323 : **********************************************************************/
1324 :
1325 0 : static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1326 : {
1327 :
1328 0 : uint32_t tv_sec, tv_usec;
1329 0 : size_t offset = 0;
1330 :
1331 : /* Unpack message */
1332 :
1333 0 : offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1334 0 : msg->printer);
1335 :
1336 0 : offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1337 : &tv_sec, &tv_usec,
1338 : &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1339 :
1340 0 : if (msg->len == 0)
1341 0 : tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1342 : &msg->notify.value[0], &msg->notify.value[1]);
1343 : else
1344 0 : tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1345 : &msg->len, &msg->notify.data);
1346 :
1347 0 : DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1348 : msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1349 :
1350 0 : tv->tv_sec = tv_sec;
1351 0 : tv->tv_usec = tv_usec;
1352 :
1353 0 : if (msg->len == 0)
1354 0 : DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1355 : msg->notify.value[1]));
1356 : else
1357 0 : dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1358 :
1359 0 : return true;
1360 : }
1361 :
1362 : /********************************************************************
1363 : Receive a notify2 message list
1364 : ********************************************************************/
1365 :
1366 0 : static void receive_notify2_message_list(struct messaging_context *msg,
1367 : void *private_data,
1368 : uint32_t msg_type,
1369 : struct server_id server_id,
1370 : DATA_BLOB *data)
1371 : {
1372 0 : size_t msg_count, i, num_groups;
1373 0 : char *buf = (char *)data->data;
1374 0 : char *msg_ptr;
1375 0 : size_t msg_len;
1376 0 : SPOOLSS_NOTIFY_MSG notify;
1377 0 : SPOOLSS_NOTIFY_MSG_CTR messages;
1378 :
1379 0 : if (data->length < 4) {
1380 0 : DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1381 0 : return;
1382 : }
1383 :
1384 0 : msg_count = IVAL(buf, 0);
1385 0 : msg_ptr = buf + 4;
1386 :
1387 0 : DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1388 :
1389 0 : if (msg_count == 0) {
1390 0 : DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1391 0 : return;
1392 : }
1393 :
1394 : /* initialize the container */
1395 :
1396 0 : ZERO_STRUCT( messages );
1397 0 : notify_msg_ctr_init( &messages );
1398 :
1399 : /*
1400 : * build message groups for each printer identified
1401 : * in a change_notify msg. Remember that a PCN message
1402 : * includes the handle returned for the srv_spoolss_replyopenprinter()
1403 : * call. Therefore messages are grouped according to printer handle.
1404 : */
1405 :
1406 0 : for ( i=0; i<msg_count; i++ ) {
1407 0 : struct timeval msg_tv;
1408 :
1409 0 : if (msg_ptr + 4 - buf > data->length) {
1410 0 : DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1411 0 : return;
1412 : }
1413 :
1414 0 : msg_len = IVAL(msg_ptr,0);
1415 0 : msg_ptr += 4;
1416 :
1417 0 : if (msg_ptr + msg_len - buf > data->length) {
1418 0 : DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1419 0 : return;
1420 : }
1421 :
1422 : /* unpack messages */
1423 :
1424 0 : ZERO_STRUCT( notify );
1425 0 : notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1426 0 : msg_ptr += msg_len;
1427 :
1428 : /* add to correct list in container */
1429 :
1430 0 : notify_msg_ctr_addmsg( &messages, ¬ify );
1431 :
1432 : /* free memory that might have been allocated by notify2_unpack_msg() */
1433 :
1434 0 : if ( notify.len != 0 )
1435 0 : SAFE_FREE( notify.notify.data );
1436 : }
1437 :
1438 : /* process each group of messages */
1439 :
1440 0 : num_groups = notify_msg_ctr_numgroups( &messages );
1441 0 : for ( i=0; i<num_groups; i++ )
1442 0 : send_notify2_changes( &messages, i );
1443 :
1444 :
1445 : /* cleanup */
1446 :
1447 0 : DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1448 : (uint32_t)msg_count ));
1449 :
1450 0 : notify_msg_ctr_destroy( &messages );
1451 :
1452 0 : return;
1453 : }
1454 :
1455 : /********************************************************************
1456 : Send a message to ourself about new driver being installed
1457 : so we can upgrade the information for each printer bound to this
1458 : driver
1459 : ********************************************************************/
1460 :
1461 0 : static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1462 : struct messaging_context *msg_ctx)
1463 : {
1464 0 : int len = strlen(drivername);
1465 :
1466 0 : if (!len)
1467 0 : return false;
1468 :
1469 0 : DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1470 : drivername));
1471 :
1472 0 : messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1473 : MSG_PRINTER_DRVUPGRADE,
1474 0 : (const uint8_t *)drivername, len+1);
1475 :
1476 0 : return true;
1477 : }
1478 :
1479 28 : void srv_spoolss_cleanup(void)
1480 : {
1481 0 : struct printer_session_counter *session_counter;
1482 :
1483 28 : for (session_counter = counter_list;
1484 68 : session_counter != NULL;
1485 40 : session_counter = counter_list) {
1486 40 : DLIST_REMOVE(counter_list, session_counter);
1487 40 : TALLOC_FREE(session_counter);
1488 : }
1489 28 : }
1490 :
1491 : /**********************************************************************
1492 : callback to receive a MSG_PRINTER_DRVUPGRADE message and iterate
1493 : over all printers, upgrading ones as necessary
1494 : This is now *ONLY* called inside the background lpq updater. JRA.
1495 : **********************************************************************/
1496 :
1497 0 : void do_drv_upgrade_printer(struct messaging_context *msg,
1498 : void *private_data,
1499 : uint32_t msg_type,
1500 : struct server_id server_id,
1501 : DATA_BLOB *data)
1502 : {
1503 0 : TALLOC_CTX *tmp_ctx;
1504 0 : const struct auth_session_info *session_info = get_session_info_system();
1505 0 : struct spoolss_PrinterInfo2 *pinfo2;
1506 0 : WERROR result;
1507 0 : const char *drivername;
1508 0 : int snum;
1509 0 : int n_services = lp_numservices();
1510 0 : struct dcerpc_binding_handle *b = NULL;
1511 :
1512 0 : tmp_ctx = talloc_new(NULL);
1513 0 : if (!tmp_ctx) return;
1514 :
1515 0 : drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1516 0 : if (!drivername) {
1517 0 : DEBUG(0, ("do_drv_upgrade_printer: Out of memory ?!\n"));
1518 0 : goto done;
1519 : }
1520 :
1521 0 : DEBUG(10, ("do_drv_upgrade_printer: "
1522 : "Got message for new driver [%s]\n", drivername));
1523 :
1524 : /* Iterate the printer list */
1525 :
1526 0 : for (snum = 0; snum < n_services; snum++) {
1527 0 : if (!lp_snum_ok(snum) || !lp_printable(snum)) {
1528 0 : continue;
1529 : }
1530 :
1531 : /* ignore [printers] share */
1532 0 : if (strequal(lp_const_servicename(snum), "printers")) {
1533 0 : continue;
1534 : }
1535 :
1536 0 : if (b == NULL) {
1537 0 : result = winreg_printer_binding_handle(tmp_ctx,
1538 : session_info,
1539 : msg,
1540 : &b);
1541 0 : if (!W_ERROR_IS_OK(result)) {
1542 0 : break;
1543 : }
1544 : }
1545 :
1546 0 : result = winreg_get_printer(tmp_ctx, b,
1547 : lp_const_servicename(snum),
1548 : &pinfo2);
1549 :
1550 0 : if (!W_ERROR_IS_OK(result)) {
1551 0 : continue;
1552 : }
1553 :
1554 0 : if (!pinfo2->drivername) {
1555 0 : continue;
1556 : }
1557 :
1558 0 : if (strcmp(drivername, pinfo2->drivername) != 0) {
1559 0 : continue;
1560 : }
1561 :
1562 0 : DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1563 :
1564 : /* all we care about currently is the change_id */
1565 0 : result = winreg_printer_update_changeid(tmp_ctx, b,
1566 0 : pinfo2->printername);
1567 :
1568 0 : if (!W_ERROR_IS_OK(result)) {
1569 0 : DEBUG(3, ("do_drv_upgrade_printer: "
1570 : "Failed to update changeid [%s]\n",
1571 : win_errstr(result)));
1572 : }
1573 : }
1574 :
1575 : /* all done */
1576 0 : done:
1577 0 : talloc_free(tmp_ctx);
1578 : }
1579 :
1580 : /********************************************************************
1581 : Update the cache for all printq's with a registered client
1582 : connection
1583 : ********************************************************************/
1584 :
1585 0 : void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1586 : {
1587 0 : struct printer_handle *printer = printers_list;
1588 0 : int snum;
1589 :
1590 : /* loop through all printers and update the cache where
1591 : a client is connected */
1592 0 : while (printer) {
1593 0 : if ((printer->printer_type == SPLHND_PRINTER) &&
1594 0 : ((printer->notify.cli_chan != NULL) &&
1595 0 : (printer->notify.cli_chan->active_connections > 0))) {
1596 0 : snum = print_queue_snum(printer->sharename);
1597 0 : print_queue_status(msg_ctx, snum, NULL, NULL);
1598 : }
1599 :
1600 0 : printer = printer->next;
1601 : }
1602 :
1603 0 : return;
1604 : }
1605 :
1606 : /****************************************************************
1607 : _spoolss_OpenPrinter
1608 : ****************************************************************/
1609 :
1610 194 : WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1611 : struct spoolss_OpenPrinter *r)
1612 : {
1613 0 : struct spoolss_OpenPrinterEx e;
1614 0 : struct spoolss_UserLevel1 level1;
1615 0 : WERROR werr;
1616 :
1617 194 : ZERO_STRUCT(level1);
1618 :
1619 194 : e.in.printername = r->in.printername;
1620 194 : e.in.datatype = r->in.datatype;
1621 194 : e.in.devmode_ctr = r->in.devmode_ctr;
1622 194 : e.in.access_mask = r->in.access_mask;
1623 194 : e.in.userlevel_ctr.level = 1;
1624 194 : e.in.userlevel_ctr.user_info.level1 = &level1;
1625 :
1626 194 : e.out.handle = r->out.handle;
1627 :
1628 194 : werr = _spoolss_OpenPrinterEx(p, &e);
1629 :
1630 194 : if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAMETER)) {
1631 : /* OpenPrinterEx returns this for a bad
1632 : * printer name. We must return WERR_INVALID_PRINTER_NAME
1633 : * instead.
1634 : */
1635 4 : werr = WERR_INVALID_PRINTER_NAME;
1636 : }
1637 :
1638 194 : return werr;
1639 : }
1640 :
1641 2850 : static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1642 : struct spoolss_DeviceMode *orig,
1643 : struct spoolss_DeviceMode **dest)
1644 : {
1645 0 : struct spoolss_DeviceMode *dm;
1646 :
1647 2850 : dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1648 2850 : if (!dm) {
1649 0 : return WERR_NOT_ENOUGH_MEMORY;
1650 : }
1651 :
1652 : /* copy all values, then duplicate strings and structs */
1653 2850 : *dm = *orig;
1654 :
1655 2850 : dm->devicename = talloc_strdup(dm, orig->devicename);
1656 2850 : if (!dm->devicename) {
1657 0 : return WERR_NOT_ENOUGH_MEMORY;
1658 : }
1659 2850 : dm->formname = talloc_strdup(dm, orig->formname);
1660 2850 : if (!dm->formname) {
1661 0 : return WERR_NOT_ENOUGH_MEMORY;
1662 : }
1663 2850 : if (orig->driverextra_data.data) {
1664 1392 : dm->driverextra_data.data =
1665 1392 : (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1666 : orig->driverextra_data.length);
1667 1392 : if (!dm->driverextra_data.data) {
1668 0 : return WERR_NOT_ENOUGH_MEMORY;
1669 : }
1670 : }
1671 :
1672 2850 : *dest = dm;
1673 2850 : return WERR_OK;
1674 : }
1675 :
1676 : /****************************************************************
1677 : _spoolss_OpenPrinterEx
1678 : ****************************************************************/
1679 :
1680 988 : WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1681 : struct spoolss_OpenPrinterEx *r)
1682 : {
1683 988 : struct dcesrv_call_state *dce_call = p->dce_call;
1684 988 : struct dcesrv_connection *dcesrv_conn = dce_call->conn;
1685 0 : const struct tsocket_address *remote_address =
1686 988 : dcesrv_connection_get_remote_address(dcesrv_conn);
1687 0 : struct auth_session_info *session_info =
1688 988 : dcesrv_call_session_info(dce_call);
1689 0 : int snum;
1690 0 : char *raddr;
1691 0 : char *rhost;
1692 988 : struct printer_handle *Printer=NULL;
1693 0 : WERROR result;
1694 0 : int rc;
1695 :
1696 988 : if (!r->in.printername) {
1697 0 : return WERR_INVALID_PARAMETER;
1698 : }
1699 :
1700 988 : if (!*r->in.printername) {
1701 8 : return WERR_INVALID_PARAMETER;
1702 : }
1703 :
1704 980 : if (r->in.userlevel_ctr.level > 3) {
1705 0 : return WERR_INVALID_PARAMETER;
1706 : }
1707 980 : if ((r->in.userlevel_ctr.level == 1 && !r->in.userlevel_ctr.user_info.level1) ||
1708 956 : (r->in.userlevel_ctr.level == 2 && !r->in.userlevel_ctr.user_info.level2) ||
1709 956 : (r->in.userlevel_ctr.level == 3 && !r->in.userlevel_ctr.user_info.level3)) {
1710 24 : return WERR_INVALID_PARAMETER;
1711 : }
1712 :
1713 : /*
1714 : * The printcap printer share inventory is updated on client
1715 : * enumeration. For clients that do not perform enumeration prior to
1716 : * access, such as cupssmbadd, we reinitialise the printer share
1717 : * inventory on open as well.
1718 : */
1719 956 : become_root();
1720 956 : delete_and_reload_printers();
1721 956 : unbecome_root();
1722 :
1723 : /* some sanity check because you can open a printer or a print server */
1724 : /* aka: \\server\printer or \\server */
1725 :
1726 956 : DEBUGADD(3,("checking name: %s\n", r->in.printername));
1727 :
1728 956 : result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1729 956 : if (!W_ERROR_IS_OK(result)) {
1730 332 : DEBUG(3,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1731 : "for printer %s\n", r->in.printername));
1732 332 : ZERO_STRUCTP(r->out.handle);
1733 332 : return result;
1734 : }
1735 :
1736 624 : Printer = find_printer_index_by_hnd(p, r->out.handle);
1737 624 : if ( !Printer ) {
1738 0 : DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1739 : "handle we created for printer %s\n", r->in.printername));
1740 0 : close_printer_handle(p, r->out.handle);
1741 0 : ZERO_STRUCTP(r->out.handle);
1742 0 : return WERR_INVALID_PARAMETER;
1743 : }
1744 :
1745 : /*
1746 : * First case: the user is opening the print server:
1747 : *
1748 : * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1749 : * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1750 : *
1751 : * Then both Win2k and WinNT clients try an OpenPrinterEx with
1752 : * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1753 : * or if the user is listed in the smb.conf printer admin parameter.
1754 : *
1755 : * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1756 : * client view printer folder, but does not show the MSAPW.
1757 : *
1758 : * Note: this test needs code to check access rights here too. Jeremy
1759 : * could you look at this?
1760 : *
1761 : * Second case: the user is opening a printer:
1762 : * NT doesn't let us connect to a printer if the connecting user
1763 : * doesn't have print permission.
1764 : *
1765 : * Third case: user is opening a Port Monitor
1766 : * access checks same as opening a handle to the print server.
1767 : */
1768 :
1769 624 : switch (Printer->printer_type )
1770 : {
1771 118 : case SPLHND_SERVER:
1772 : case SPLHND_PORTMON_TCP:
1773 : case SPLHND_PORTMON_LOCAL:
1774 : /* Printserver handles use global struct... */
1775 :
1776 118 : snum = -1;
1777 :
1778 118 : if (r->in.access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
1779 90 : r->in.access_mask |= SERVER_ACCESS_ADMINISTER;
1780 90 : r->in.access_mask |= SERVER_ACCESS_ENUMERATE;
1781 : }
1782 :
1783 : /* Map standard access rights to object specific access rights */
1784 :
1785 118 : se_map_standard(&r->in.access_mask,
1786 : &printserver_std_mapping);
1787 :
1788 : /* Deny any object specific bits that don't apply to print
1789 : servers (i.e printer and job specific bits) */
1790 :
1791 118 : r->in.access_mask &= SEC_MASK_SPECIFIC;
1792 :
1793 118 : if (r->in.access_mask &
1794 : ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1795 0 : DEBUG(3, ("access DENIED for non-printserver bits\n"));
1796 0 : close_printer_handle(p, r->out.handle);
1797 0 : ZERO_STRUCTP(r->out.handle);
1798 0 : return WERR_ACCESS_DENIED;
1799 : }
1800 :
1801 : /* Allow admin access */
1802 :
1803 118 : if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1804 : {
1805 94 : if (!lp_show_add_printer_wizard()) {
1806 0 : close_printer_handle(p, r->out.handle);
1807 0 : ZERO_STRUCTP(r->out.handle);
1808 0 : return WERR_ACCESS_DENIED;
1809 : }
1810 :
1811 : /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1812 : and not a printer admin, then fail */
1813 :
1814 94 : if ((session_info->unix_token->uid != sec_initial_uid()) &&
1815 2 : !security_token_has_privilege(
1816 2 : session_info->security_token,
1817 0 : SEC_PRIV_PRINT_OPERATOR) &&
1818 0 : !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
1819 0 : session_info->security_token)) {
1820 0 : close_printer_handle(p, r->out.handle);
1821 0 : ZERO_STRUCTP(r->out.handle);
1822 0 : DEBUG(3,("access DENIED as user is not root, "
1823 : "has no printoperator privilege and is "
1824 : "not a member of the printoperator builtin group\n"));
1825 0 : return WERR_ACCESS_DENIED;
1826 : }
1827 :
1828 94 : r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1829 : }
1830 : else
1831 : {
1832 24 : r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1833 : }
1834 :
1835 118 : DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1836 : ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1837 :
1838 118 : break;
1839 :
1840 506 : case SPLHND_PRINTER:
1841 : /* NT doesn't let us connect to a printer if the connecting user
1842 : doesn't have print permission. */
1843 :
1844 506 : if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1845 0 : close_printer_handle(p, r->out.handle);
1846 0 : ZERO_STRUCTP(r->out.handle);
1847 0 : return WERR_INVALID_HANDLE;
1848 : }
1849 :
1850 506 : if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1851 170 : r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1852 : }
1853 :
1854 506 : se_map_standard(&r->in.access_mask, &printer_std_mapping);
1855 :
1856 : /* map an empty access mask to the minimum access mask */
1857 506 : if (r->in.access_mask == 0x0)
1858 296 : r->in.access_mask = PRINTER_ACCESS_USE;
1859 :
1860 : /*
1861 : * If we are not serving the printer driver for this printer,
1862 : * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1863 : * will keep NT clients happy --jerry
1864 : */
1865 :
1866 506 : if (lp_use_client_driver(snum)
1867 0 : && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1868 : {
1869 0 : r->in.access_mask = PRINTER_ACCESS_USE;
1870 : }
1871 :
1872 : /* check smb.conf parameters and the the sec_desc */
1873 506 : raddr = tsocket_address_inet_addr_string(remote_address,
1874 : p->mem_ctx);
1875 506 : if (raddr == NULL) {
1876 0 : return WERR_NOT_ENOUGH_MEMORY;
1877 : }
1878 :
1879 506 : rc = get_remote_hostname(remote_address,
1880 : &rhost,
1881 : p->mem_ctx);
1882 506 : if (rc < 0) {
1883 0 : return WERR_NOT_ENOUGH_MEMORY;
1884 : }
1885 506 : if (strequal(rhost, "UNKNOWN")) {
1886 506 : rhost = raddr;
1887 : }
1888 :
1889 506 : if (!allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
1890 : rhost, raddr)) {
1891 0 : DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1892 0 : ZERO_STRUCTP(r->out.handle);
1893 0 : return WERR_ACCESS_DENIED;
1894 : }
1895 :
1896 506 : if (!user_ok_token(session_info->unix_info->unix_name,
1897 506 : session_info->info->domain_name,
1898 506 : session_info->security_token, snum) ||
1899 506 : !W_ERROR_IS_OK(print_access_check(session_info,
1900 : p->msg_ctx,
1901 : snum,
1902 : r->in.access_mask))) {
1903 0 : DEBUG(3, ("access DENIED for printer open\n"));
1904 0 : close_printer_handle(p, r->out.handle);
1905 0 : ZERO_STRUCTP(r->out.handle);
1906 0 : return WERR_ACCESS_DENIED;
1907 : }
1908 :
1909 506 : if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1910 4 : DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1911 4 : close_printer_handle(p, r->out.handle);
1912 4 : ZERO_STRUCTP(r->out.handle);
1913 4 : return WERR_ACCESS_DENIED;
1914 : }
1915 :
1916 502 : if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1917 170 : r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1918 : else
1919 332 : r->in.access_mask = PRINTER_ACCESS_USE;
1920 :
1921 502 : DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1922 : ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1923 :
1924 502 : winreg_create_printer_internal(p->mem_ctx,
1925 : get_session_info_system(),
1926 : p->msg_ctx,
1927 : lp_const_servicename(snum));
1928 :
1929 502 : break;
1930 :
1931 0 : default:
1932 : /* sanity check to prevent programmer error */
1933 0 : ZERO_STRUCTP(r->out.handle);
1934 0 : return WERR_INVALID_HANDLE;
1935 : }
1936 :
1937 620 : Printer->access_granted = r->in.access_mask;
1938 :
1939 : /*
1940 : * If the client sent a devmode in the OpenPrinter() call, then
1941 : * save it here in case we get a job submission on this handle
1942 : */
1943 :
1944 620 : if ((Printer->printer_type != SPLHND_SERVER)
1945 502 : && (r->in.devmode_ctr.devmode != NULL)) {
1946 8 : copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1947 : &Printer->devmode);
1948 : }
1949 :
1950 620 : return WERR_OK;
1951 : }
1952 :
1953 : /****************************************************************
1954 : _spoolss_ClosePrinter
1955 : ****************************************************************/
1956 :
1957 620 : WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1958 : struct spoolss_ClosePrinter *r)
1959 : {
1960 620 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1961 :
1962 620 : if (Printer && Printer->document_started) {
1963 0 : struct spoolss_EndDocPrinter e;
1964 :
1965 28 : e.in.handle = r->in.handle;
1966 :
1967 28 : _spoolss_EndDocPrinter(p, &e);
1968 : }
1969 :
1970 620 : if (!close_printer_handle(p, r->in.handle))
1971 0 : return WERR_INVALID_HANDLE;
1972 :
1973 : /* clear the returned printer handle. Observed behavior
1974 : from Win2k server. Don't think this really matters.
1975 : Previous code just copied the value of the closed
1976 : handle. --jerry */
1977 :
1978 620 : ZERO_STRUCTP(r->out.handle);
1979 :
1980 620 : return WERR_OK;
1981 : }
1982 :
1983 : /****************************************************************
1984 : _spoolss_DeletePrinter
1985 : ****************************************************************/
1986 :
1987 16 : WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1988 : struct spoolss_DeletePrinter *r)
1989 : {
1990 16 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1991 0 : WERROR result;
1992 0 : int snum;
1993 :
1994 16 : if (Printer && Printer->document_started) {
1995 0 : struct spoolss_EndDocPrinter e;
1996 :
1997 0 : e.in.handle = r->in.handle;
1998 :
1999 0 : _spoolss_EndDocPrinter(p, &e);
2000 : }
2001 :
2002 16 : if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2003 16 : winreg_delete_printer_key_internal(p->mem_ctx,
2004 : get_session_info_system(),
2005 : p->msg_ctx,
2006 : lp_const_servicename(snum),
2007 : "");
2008 : }
2009 :
2010 16 : result = delete_printer_handle(p, r->in.handle);
2011 :
2012 16 : return result;
2013 : }
2014 :
2015 : /*******************************************************************
2016 : * static function to lookup the version id corresponding to an
2017 : * long architecture string
2018 : ******************************************************************/
2019 :
2020 : static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2021 : SPOOLSS_DRIVER_VERSION_NT35,
2022 : SPOOLSS_DRIVER_VERSION_NT4,
2023 : SPOOLSS_DRIVER_VERSION_200X,
2024 : -1};
2025 :
2026 0 : static int get_version_id(const char *arch)
2027 : {
2028 0 : int i;
2029 :
2030 0 : for (i=0; archi_table[i].long_archi != NULL; i++)
2031 : {
2032 0 : if (strcmp(arch, archi_table[i].long_archi) == 0)
2033 0 : return (archi_table[i].version);
2034 : }
2035 :
2036 0 : return -1;
2037 : }
2038 :
2039 : /****************************************************************
2040 : _spoolss_DeletePrinterDriver
2041 : ****************************************************************/
2042 :
2043 0 : WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2044 : struct spoolss_DeletePrinterDriver *r)
2045 : {
2046 :
2047 0 : struct dcesrv_call_state *dce_call = p->dce_call;
2048 0 : struct auth_session_info *session_info =
2049 0 : dcesrv_call_session_info(dce_call);
2050 0 : struct spoolss_DriverInfo8 *info = NULL;
2051 0 : int version;
2052 0 : WERROR status;
2053 0 : struct dcerpc_binding_handle *b;
2054 0 : TALLOC_CTX *tmp_ctx = NULL;
2055 0 : int i;
2056 0 : bool found;
2057 :
2058 : /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2059 : and not a printer admin, then fail */
2060 :
2061 0 : if ((session_info->unix_token->uid != sec_initial_uid()) &&
2062 0 : !security_token_has_privilege(session_info->security_token,
2063 : SEC_PRIV_PRINT_OPERATOR)) {
2064 0 : return WERR_ACCESS_DENIED;
2065 : }
2066 :
2067 0 : if (r->in.architecture == NULL || r->in.driver == NULL) {
2068 0 : return WERR_INVALID_ENVIRONMENT;
2069 : }
2070 :
2071 : /* check that we have a valid driver name first */
2072 :
2073 0 : if ((version = get_version_id(r->in.architecture)) == -1) {
2074 0 : return WERR_INVALID_ENVIRONMENT;
2075 : }
2076 :
2077 0 : tmp_ctx = talloc_new(p->mem_ctx);
2078 0 : if (!tmp_ctx) {
2079 0 : return WERR_NOT_ENOUGH_MEMORY;
2080 : }
2081 :
2082 0 : status = winreg_printer_binding_handle(tmp_ctx,
2083 : get_session_info_system(),
2084 : p->msg_ctx,
2085 : &b);
2086 0 : if (!W_ERROR_IS_OK(status)) {
2087 0 : goto done;
2088 : }
2089 :
2090 0 : for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2091 0 : status = winreg_get_driver(tmp_ctx, b,
2092 : r->in.architecture, r->in.driver,
2093 0 : drv_cversion[i], &info);
2094 0 : if (!W_ERROR_IS_OK(status)) {
2095 0 : DEBUG(5, ("skipping del of driver with version %d\n",
2096 : drv_cversion[i]));
2097 0 : continue;
2098 : }
2099 0 : found = true;
2100 :
2101 0 : if (printer_driver_in_use(tmp_ctx, b, info)) {
2102 0 : status = WERR_PRINTER_DRIVER_IN_USE;
2103 0 : goto done;
2104 : }
2105 :
2106 0 : status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2107 0 : if (!W_ERROR_IS_OK(status)) {
2108 0 : DEBUG(0, ("failed del of driver with version %d\n",
2109 : drv_cversion[i]));
2110 0 : goto done;
2111 : }
2112 : }
2113 0 : if (found == false) {
2114 0 : DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2115 0 : status = WERR_UNKNOWN_PRINTER_DRIVER;
2116 : } else {
2117 0 : status = WERR_OK;
2118 : }
2119 :
2120 0 : done:
2121 0 : talloc_free(tmp_ctx);
2122 :
2123 0 : return status;
2124 : }
2125 :
2126 0 : static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2127 : struct pipes_struct *p,
2128 : struct spoolss_DeletePrinterDriverEx *r,
2129 : struct dcerpc_binding_handle *b,
2130 : struct spoolss_DriverInfo8 *info)
2131 : {
2132 0 : struct dcesrv_call_state *dce_call = p->dce_call;
2133 0 : struct auth_session_info *session_info =
2134 0 : dcesrv_call_session_info(dce_call);
2135 0 : WERROR status;
2136 0 : bool delete_files;
2137 :
2138 0 : if (printer_driver_in_use(mem_ctx, b, info)) {
2139 0 : status = WERR_PRINTER_DRIVER_IN_USE;
2140 0 : goto done;
2141 : }
2142 :
2143 : /*
2144 : * we have a couple of cases to consider.
2145 : * (1) Are any files in use? If so and DPD_DELETE_ALL_FILES is set,
2146 : * then the delete should fail if **any** files overlap with
2147 : * other drivers
2148 : * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2149 : * non-overlapping files
2150 : * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2151 : * are set, then do not delete any files
2152 : * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2153 : */
2154 :
2155 0 : delete_files = r->in.delete_flags
2156 0 : & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2157 :
2158 :
2159 0 : if (delete_files) {
2160 0 : bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2161 0 : if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2162 0 : status = WERR_PRINTER_DRIVER_IN_USE;
2163 0 : goto done;
2164 : }
2165 : /*
2166 : * printer_driver_files_in_use() has trimmed overlapping files
2167 : * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2168 : */
2169 : }
2170 :
2171 :
2172 0 : status = winreg_del_driver(mem_ctx, b, info, info->version);
2173 0 : if (!W_ERROR_IS_OK(status)) {
2174 0 : goto done;
2175 : }
2176 :
2177 : /*
2178 : * now delete any associated files if delete_files is
2179 : * true. Even if this part fails, we return success
2180 : * because the driver does not exist any more
2181 : */
2182 0 : if (delete_files) {
2183 0 : delete_driver_files(session_info, info);
2184 : }
2185 :
2186 0 : done:
2187 0 : return status;
2188 : }
2189 :
2190 : /****************************************************************
2191 : _spoolss_DeletePrinterDriverEx
2192 : ****************************************************************/
2193 :
2194 0 : WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2195 : struct spoolss_DeletePrinterDriverEx *r)
2196 : {
2197 0 : struct dcesrv_call_state *dce_call = p->dce_call;
2198 0 : struct auth_session_info *session_info =
2199 0 : dcesrv_call_session_info(dce_call);
2200 0 : struct spoolss_DriverInfo8 *info = NULL;
2201 0 : WERROR status;
2202 0 : struct dcerpc_binding_handle *b;
2203 0 : TALLOC_CTX *tmp_ctx = NULL;
2204 0 : int i;
2205 0 : bool found;
2206 :
2207 : /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2208 : and not a printer admin, then fail */
2209 :
2210 0 : if ((session_info->unix_token->uid != sec_initial_uid()) &&
2211 0 : !security_token_has_privilege(session_info->security_token,
2212 : SEC_PRIV_PRINT_OPERATOR)) {
2213 0 : return WERR_ACCESS_DENIED;
2214 : }
2215 :
2216 0 : if (r->in.architecture == NULL || r->in.driver == NULL) {
2217 0 : return WERR_INVALID_ENVIRONMENT;
2218 : }
2219 :
2220 : /* check that we have a valid driver name first */
2221 0 : if (get_version_id(r->in.architecture) == -1) {
2222 : /* this is what NT returns */
2223 0 : return WERR_INVALID_ENVIRONMENT;
2224 : }
2225 :
2226 0 : tmp_ctx = talloc_new(p->mem_ctx);
2227 0 : if (!tmp_ctx) {
2228 0 : return WERR_NOT_ENOUGH_MEMORY;
2229 : }
2230 :
2231 0 : status = winreg_printer_binding_handle(tmp_ctx,
2232 : get_session_info_system(),
2233 : p->msg_ctx,
2234 : &b);
2235 0 : if (!W_ERROR_IS_OK(status)) {
2236 0 : goto done;
2237 : }
2238 :
2239 0 : for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2240 0 : if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2241 0 : && (drv_cversion[i] != r->in.version)) {
2242 0 : continue;
2243 : }
2244 :
2245 : /* check if a driver with this version exists before delete */
2246 0 : status = winreg_get_driver(tmp_ctx, b,
2247 : r->in.architecture, r->in.driver,
2248 0 : drv_cversion[i], &info);
2249 0 : if (!W_ERROR_IS_OK(status)) {
2250 0 : DEBUG(5, ("skipping del of driver with version %d\n",
2251 : drv_cversion[i]));
2252 0 : continue;
2253 : }
2254 0 : found = true;
2255 :
2256 0 : status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2257 0 : if (!W_ERROR_IS_OK(status)) {
2258 0 : DEBUG(0, ("failed to delete driver with version %d\n",
2259 : drv_cversion[i]));
2260 0 : goto done;
2261 : }
2262 : }
2263 0 : if (found == false) {
2264 0 : DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2265 0 : status = WERR_UNKNOWN_PRINTER_DRIVER;
2266 : } else {
2267 0 : status = WERR_OK;
2268 : }
2269 :
2270 0 : done:
2271 0 : talloc_free(tmp_ctx);
2272 0 : return status;
2273 : }
2274 :
2275 :
2276 : /********************************************************************
2277 : GetPrinterData on a printer server Handle.
2278 : ********************************************************************/
2279 :
2280 404 : static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2281 : const char *value,
2282 : enum winreg_Type *type,
2283 : union spoolss_PrinterData *data)
2284 : {
2285 404 : DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2286 :
2287 404 : if (!strcasecmp_m(value, "W3SvcInstalled")) {
2288 28 : *type = REG_DWORD;
2289 28 : SIVAL(&data->value, 0, 0x00);
2290 28 : return WERR_OK;
2291 : }
2292 :
2293 376 : if (!strcasecmp_m(value, "BeepEnabled")) {
2294 24 : *type = REG_DWORD;
2295 24 : SIVAL(&data->value, 0, 0x00);
2296 24 : return WERR_OK;
2297 : }
2298 :
2299 352 : if (!strcasecmp_m(value, "EventLog")) {
2300 24 : *type = REG_DWORD;
2301 : /* formally was 0x1b */
2302 24 : SIVAL(&data->value, 0, 0x00);
2303 24 : return WERR_OK;
2304 : }
2305 :
2306 328 : if (!strcasecmp_m(value, "NetPopup")) {
2307 0 : *type = REG_DWORD;
2308 0 : SIVAL(&data->value, 0, 0x00);
2309 0 : return WERR_OK;
2310 : }
2311 :
2312 328 : if (!strcasecmp_m(value, "MajorVersion")) {
2313 28 : *type = REG_DWORD;
2314 :
2315 : /* Windows NT 4.0 seems to not allow uploading of drivers
2316 : to a server that reports 0x3 as the MajorVersion.
2317 : need to investigate more how Win2k gets around this .
2318 : -- jerry */
2319 :
2320 28 : if (RA_WINNT == get_remote_arch()) {
2321 0 : SIVAL(&data->value, 0, 0x02);
2322 : } else {
2323 28 : SIVAL(&data->value, 0, 0x03);
2324 : }
2325 :
2326 28 : return WERR_OK;
2327 : }
2328 :
2329 300 : if (!strcasecmp_m(value, "MinorVersion")) {
2330 24 : *type = REG_DWORD;
2331 24 : SIVAL(&data->value, 0, 0x00);
2332 24 : return WERR_OK;
2333 : }
2334 :
2335 : /* REG_BINARY
2336 : * uint32_t size = 0x114
2337 : * uint32_t major = 5
2338 : * uint32_t minor = [0|1]
2339 : * uint32_t build = [2195|2600]
2340 : * extra unicode string = e.g. "Service Pack 3"
2341 : */
2342 276 : if (!strcasecmp_m(value, "OSVersion")) {
2343 0 : DATA_BLOB blob;
2344 0 : enum ndr_err_code ndr_err;
2345 0 : struct spoolss_OSVersion os;
2346 :
2347 : /*
2348 : * Set the default OSVersion to:
2349 : *
2350 : * Windows Server 2003R2 SP2 (5.2.3790)
2351 : *
2352 : * used to be Windows 2000 (5.0.2195)
2353 : */
2354 40 : os.major = lp_parm_int(GLOBAL_SECTION_SNUM,
2355 : "spoolss", "os_major",
2356 : GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT);
2357 40 : os.minor = lp_parm_int(GLOBAL_SECTION_SNUM,
2358 : "spoolss", "os_minor",
2359 : GLOBAL_SPOOLSS_OS_MINOR_DEFAULT);
2360 40 : os.build = lp_parm_int(GLOBAL_SECTION_SNUM,
2361 : "spoolss", "os_build",
2362 : GLOBAL_SPOOLSS_OS_BUILD_DEFAULT);
2363 40 : os.extra_string = ""; /* leave extra string empty */
2364 :
2365 40 : ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2366 : (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2367 40 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2368 0 : return WERR_GEN_FAILURE;
2369 : }
2370 :
2371 40 : if (DEBUGLEVEL >= 10) {
2372 0 : NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
2373 : }
2374 :
2375 40 : *type = REG_BINARY;
2376 40 : data->binary = blob;
2377 :
2378 40 : return WERR_OK;
2379 : }
2380 :
2381 :
2382 236 : if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2383 24 : *type = REG_SZ;
2384 :
2385 24 : data->string = talloc_strdup(mem_ctx, SPOOLSS_DEFAULT_SERVER_PATH);
2386 24 : W_ERROR_HAVE_NO_MEMORY(data->string);
2387 :
2388 24 : return WERR_OK;
2389 : }
2390 :
2391 212 : if (!strcasecmp_m(value, "Architecture")) {
2392 160 : *type = REG_SZ;
2393 160 : data->string = talloc_strdup(mem_ctx,
2394 : lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", GLOBAL_SPOOLSS_ARCHITECTURE));
2395 160 : W_ERROR_HAVE_NO_MEMORY(data->string);
2396 :
2397 160 : return WERR_OK;
2398 : }
2399 :
2400 52 : if (!strcasecmp_m(value, "DsPresent")) {
2401 24 : *type = REG_DWORD;
2402 :
2403 : /* only show the publish check box if we are a
2404 : member of a AD domain */
2405 :
2406 24 : if (lp_security() == SEC_ADS) {
2407 0 : SIVAL(&data->value, 0, 0x01);
2408 : } else {
2409 24 : SIVAL(&data->value, 0, 0x00);
2410 : }
2411 24 : return WERR_OK;
2412 : }
2413 :
2414 28 : if (!strcasecmp_m(value, "DNSMachineName")) {
2415 24 : const char *hostname = get_mydnsfullname();
2416 :
2417 24 : if (!hostname) {
2418 0 : return WERR_FILE_NOT_FOUND;
2419 : }
2420 :
2421 24 : *type = REG_SZ;
2422 24 : data->string = talloc_strdup(mem_ctx, hostname);
2423 24 : W_ERROR_HAVE_NO_MEMORY(data->string);
2424 :
2425 24 : return WERR_OK;
2426 : }
2427 :
2428 4 : *type = REG_NONE;
2429 :
2430 4 : return WERR_INVALID_PARAMETER;
2431 : }
2432 :
2433 : /****************************************************************
2434 : _spoolss_GetPrinterData
2435 : ****************************************************************/
2436 :
2437 480 : WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2438 : struct spoolss_GetPrinterData *r)
2439 : {
2440 0 : struct spoolss_GetPrinterDataEx r2;
2441 :
2442 480 : r2.in.handle = r->in.handle;
2443 480 : r2.in.key_name = "PrinterDriverData";
2444 480 : r2.in.value_name = r->in.value_name;
2445 480 : r2.in.offered = r->in.offered;
2446 480 : r2.out.type = r->out.type;
2447 480 : r2.out.data = r->out.data;
2448 480 : r2.out.needed = r->out.needed;
2449 :
2450 480 : return _spoolss_GetPrinterDataEx(p, &r2);
2451 : }
2452 :
2453 : /*********************************************************
2454 : Connect to the client machine.
2455 : **********************************************************/
2456 :
2457 2 : static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe, struct cli_state **pp_cli,
2458 : struct sockaddr_storage *client_ss, const char *remote_machine)
2459 : {
2460 0 : NTSTATUS ret;
2461 0 : struct sockaddr_storage rm_addr;
2462 0 : char addr[INET6_ADDRSTRLEN];
2463 2 : struct cli_credentials *anon_creds = NULL;
2464 :
2465 2 : if ( is_zero_addr(client_ss) ) {
2466 0 : DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2467 : remote_machine));
2468 0 : if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2469 0 : DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2470 0 : return false;
2471 : }
2472 0 : print_sockaddr(addr, sizeof(addr), &rm_addr);
2473 : } else {
2474 2 : rm_addr = *client_ss;
2475 2 : print_sockaddr(addr, sizeof(addr), &rm_addr);
2476 2 : DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2477 : addr));
2478 : }
2479 :
2480 2 : if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2481 0 : DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2482 : addr));
2483 0 : return false;
2484 : }
2485 :
2486 2 : anon_creds = cli_credentials_init_anon(NULL);
2487 2 : if (anon_creds == NULL) {
2488 0 : DBG_ERR("cli_credentials_init_anon() failed\n");
2489 0 : return false;
2490 : }
2491 :
2492 : /* setup the connection */
2493 2 : ret = cli_full_connection_creds( pp_cli, lp_netbios_name(), remote_machine,
2494 : &rm_addr, 0, "IPC$", "IPC",
2495 : anon_creds,
2496 : CLI_FULL_CONNECTION_IPC);
2497 2 : TALLOC_FREE(anon_creds);
2498 2 : if ( !NT_STATUS_IS_OK( ret ) ) {
2499 0 : DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2500 : remote_machine ));
2501 0 : return false;
2502 : }
2503 :
2504 2 : if ( smbXcli_conn_protocol((*pp_cli)->conn) < PROTOCOL_NT1 ) {
2505 0 : DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2506 0 : cli_shutdown(*pp_cli);
2507 0 : return false;
2508 : }
2509 :
2510 : /*
2511 : * Ok - we have an anonymous connection to the IPC$ share.
2512 : * Now start the NT Domain stuff :-).
2513 : */
2514 :
2515 2 : ret = cli_rpc_pipe_open_noauth(*pp_cli, &ndr_table_spoolss, pp_pipe);
2516 2 : if (!NT_STATUS_IS_OK(ret)) {
2517 0 : DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2518 : remote_machine, nt_errstr(ret)));
2519 0 : cli_shutdown(*pp_cli);
2520 0 : return false;
2521 : }
2522 :
2523 2 : return true;
2524 : }
2525 :
2526 : /***************************************************************************
2527 : Connect to the client.
2528 : ****************************************************************************/
2529 :
2530 2 : static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2531 : uint32_t localprinter,
2532 : enum winreg_Type type,
2533 : struct policy_handle *handle,
2534 : struct notify_back_channel **_chan,
2535 : struct sockaddr_storage *client_ss,
2536 : struct messaging_context *msg_ctx)
2537 : {
2538 0 : WERROR result;
2539 0 : NTSTATUS status;
2540 0 : struct notify_back_channel *chan;
2541 :
2542 2 : for (chan = back_channels; chan; chan = chan->next) {
2543 0 : if (memcmp(&chan->client_address, client_ss,
2544 : sizeof(struct sockaddr_storage)) == 0) {
2545 0 : break;
2546 : }
2547 : }
2548 :
2549 : /*
2550 : * If it's the first connection, contact the client
2551 : * and connect to the IPC$ share anonymously
2552 : */
2553 2 : if (!chan) {
2554 0 : fstring unix_printer;
2555 :
2556 : /* the +2 is to strip the leading 2 backslashes */
2557 2 : fstrcpy(unix_printer, printer + 2);
2558 :
2559 2 : chan = talloc_zero(NULL, struct notify_back_channel);
2560 2 : if (!chan) {
2561 0 : return false;
2562 : }
2563 2 : chan->client_address = *client_ss;
2564 :
2565 2 : if (!spoolss_connect_to_client(&chan->cli_pipe, &chan->cli, client_ss, unix_printer)) {
2566 0 : TALLOC_FREE(chan);
2567 0 : return false;
2568 : }
2569 :
2570 2 : DLIST_ADD(back_channels, chan);
2571 :
2572 2 : messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2573 : receive_notify2_message_list);
2574 : }
2575 :
2576 2 : if (chan->cli_pipe == NULL ||
2577 2 : chan->cli_pipe->binding_handle == NULL) {
2578 0 : DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2579 : "NULL %s for printer %s\n",
2580 : chan->cli_pipe == NULL ?
2581 : "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2582 : printer));
2583 0 : return false;
2584 : }
2585 :
2586 : /*
2587 : * Tell the specific printing tdb we want messages for this printer
2588 : * by registering our PID.
2589 : */
2590 :
2591 2 : if (!print_notify_register_pid(snum)) {
2592 0 : DEBUG(0, ("Failed to register our pid for printer %s\n",
2593 : printer));
2594 : }
2595 :
2596 2 : status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2597 : talloc_tos(),
2598 : printer,
2599 : localprinter,
2600 : type,
2601 : 0,
2602 : NULL,
2603 : handle,
2604 : &result);
2605 2 : if (!NT_STATUS_IS_OK(status)) {
2606 0 : DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2607 0 : result = ntstatus_to_werror(status);
2608 2 : } else if (!W_ERROR_IS_OK(result)) {
2609 0 : DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2610 : }
2611 :
2612 2 : chan->active_connections++;
2613 2 : *_chan = chan;
2614 :
2615 2 : return (W_ERROR_IS_OK(result));
2616 : }
2617 :
2618 : /****************************************************************
2619 : ****************************************************************/
2620 :
2621 2 : static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2622 : const struct spoolss_NotifyOption *r)
2623 : {
2624 0 : struct spoolss_NotifyOption *option;
2625 0 : uint32_t i,k;
2626 :
2627 2 : if (!r) {
2628 0 : return NULL;
2629 : }
2630 :
2631 2 : option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2632 2 : if (!option) {
2633 0 : return NULL;
2634 : }
2635 :
2636 2 : *option = *r;
2637 :
2638 2 : if (!option->count) {
2639 0 : return option;
2640 : }
2641 :
2642 2 : option->types = talloc_zero_array(option,
2643 : struct spoolss_NotifyOptionType, option->count);
2644 2 : if (!option->types) {
2645 0 : talloc_free(option);
2646 0 : return NULL;
2647 : }
2648 :
2649 6 : for (i=0; i < option->count; i++) {
2650 4 : option->types[i] = r->types[i];
2651 :
2652 4 : if (option->types[i].count) {
2653 4 : option->types[i].fields = talloc_zero_array(option,
2654 : union spoolss_Field, option->types[i].count);
2655 4 : if (!option->types[i].fields) {
2656 0 : talloc_free(option);
2657 0 : return NULL;
2658 : }
2659 8 : for (k=0; k<option->types[i].count; k++) {
2660 4 : option->types[i].fields[k] =
2661 4 : r->types[i].fields[k];
2662 : }
2663 : }
2664 : }
2665 :
2666 2 : return option;
2667 : }
2668 :
2669 : /****************************************************************
2670 : * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2671 : *
2672 : * before replying OK: status=0 a rpc call is made to the workstation
2673 : * asking ReplyOpenPrinter
2674 : *
2675 : * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2676 : * called from api_spoolss_rffpcnex
2677 : ****************************************************************/
2678 :
2679 2 : WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2680 : struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2681 : {
2682 2 : struct dcesrv_call_state *dce_call = p->dce_call;
2683 2 : struct dcesrv_connection *dcesrv_conn = dce_call->conn;
2684 0 : const struct tsocket_address *remote_address =
2685 2 : dcesrv_connection_get_remote_address(dcesrv_conn);
2686 2 : int snum = -1;
2687 2 : struct spoolss_NotifyOption *option = r->in.notify_options;
2688 0 : struct sockaddr_storage client_ss;
2689 0 : ssize_t client_len;
2690 :
2691 : /* store the notify value in the printer struct */
2692 :
2693 2 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2694 :
2695 2 : if (!Printer) {
2696 0 : DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2697 : "Invalid handle (%s:%u:%u).\n",
2698 : OUR_HANDLE(r->in.handle)));
2699 0 : return WERR_INVALID_HANDLE;
2700 : }
2701 :
2702 2 : Printer->notify.flags = r->in.flags;
2703 2 : Printer->notify.options = r->in.options;
2704 2 : Printer->notify.printerlocal = r->in.printer_local;
2705 2 : Printer->notify.msg_ctx = p->msg_ctx;
2706 :
2707 2 : TALLOC_FREE(Printer->notify.option);
2708 2 : Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2709 :
2710 2 : fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2711 :
2712 : /* Connect to the client machine and send a ReplyOpenPrinter */
2713 :
2714 2 : if ( Printer->printer_type == SPLHND_SERVER)
2715 2 : snum = -1;
2716 0 : else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2717 0 : !get_printer_snum(p, r->in.handle, &snum, NULL) )
2718 0 : return WERR_INVALID_HANDLE;
2719 :
2720 2 : DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2721 : "remote_address is %s\n",
2722 : tsocket_address_string(remote_address, p->mem_ctx)));
2723 :
2724 2 : if (!lp_print_notify_backchannel(snum)) {
2725 0 : DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2726 : "backchannel disabled\n"));
2727 0 : return WERR_RPC_S_SERVER_UNAVAILABLE;
2728 : }
2729 :
2730 2 : client_len = tsocket_address_bsd_sockaddr(remote_address,
2731 : (struct sockaddr *) &client_ss,
2732 : sizeof(struct sockaddr_storage));
2733 2 : if (client_len < 0) {
2734 0 : return WERR_NOT_ENOUGH_MEMORY;
2735 : }
2736 :
2737 2 : if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2738 : Printer->notify.printerlocal, REG_SZ,
2739 : &Printer->notify.cli_hnd,
2740 : &Printer->notify.cli_chan,
2741 : &client_ss, p->msg_ctx)) {
2742 0 : return WERR_RPC_S_SERVER_UNAVAILABLE;
2743 : }
2744 :
2745 2 : return WERR_OK;
2746 : }
2747 :
2748 : /*******************************************************************
2749 : * fill a notify_info_data with the servername
2750 : ********************************************************************/
2751 :
2752 0 : static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2753 : int snum,
2754 : struct spoolss_Notify *data,
2755 : print_queue_struct *queue,
2756 : struct spoolss_PrinterInfo2 *pinfo2,
2757 : TALLOC_CTX *mem_ctx)
2758 : {
2759 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2760 0 : }
2761 :
2762 : /*******************************************************************
2763 : * fill a notify_info_data with the printername (not including the servername).
2764 : ********************************************************************/
2765 :
2766 0 : static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2767 : int snum,
2768 : struct spoolss_Notify *data,
2769 : print_queue_struct *queue,
2770 : struct spoolss_PrinterInfo2 *pinfo2,
2771 : TALLOC_CTX *mem_ctx)
2772 : {
2773 : /* the notify name should not contain the \\server\ part */
2774 0 : const char *p = strrchr(pinfo2->printername, '\\');
2775 :
2776 0 : if (!p) {
2777 0 : p = pinfo2->printername;
2778 : } else {
2779 0 : p++;
2780 : }
2781 :
2782 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2783 0 : }
2784 :
2785 : /*******************************************************************
2786 : * fill a notify_info_data with the servicename
2787 : ********************************************************************/
2788 :
2789 0 : static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2790 : int snum,
2791 : struct spoolss_Notify *data,
2792 : print_queue_struct *queue,
2793 : struct spoolss_PrinterInfo2 *pinfo2,
2794 : TALLOC_CTX *mem_ctx)
2795 : {
2796 0 : const struct loadparm_substitution *lp_sub =
2797 0 : loadparm_s3_global_substitution();
2798 :
2799 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), lp_sub, snum));
2800 0 : }
2801 :
2802 : /*******************************************************************
2803 : * fill a notify_info_data with the port name
2804 : ********************************************************************/
2805 :
2806 0 : static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2807 : int snum,
2808 : struct spoolss_Notify *data,
2809 : print_queue_struct *queue,
2810 : struct spoolss_PrinterInfo2 *pinfo2,
2811 : TALLOC_CTX *mem_ctx)
2812 : {
2813 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2814 0 : }
2815 :
2816 : /*******************************************************************
2817 : * fill a notify_info_data with the printername
2818 : * but it doesn't exist, have to see what to do
2819 : ********************************************************************/
2820 :
2821 0 : static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2822 : int snum,
2823 : struct spoolss_Notify *data,
2824 : print_queue_struct *queue,
2825 : struct spoolss_PrinterInfo2 *pinfo2,
2826 : TALLOC_CTX *mem_ctx)
2827 : {
2828 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2829 0 : }
2830 :
2831 : /*******************************************************************
2832 : * fill a notify_info_data with the comment
2833 : ********************************************************************/
2834 :
2835 0 : static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2836 : int snum,
2837 : struct spoolss_Notify *data,
2838 : print_queue_struct *queue,
2839 : struct spoolss_PrinterInfo2 *pinfo2,
2840 : TALLOC_CTX *mem_ctx)
2841 : {
2842 0 : const struct loadparm_substitution *lp_sub =
2843 0 : loadparm_s3_global_substitution();
2844 0 : const char *p;
2845 :
2846 0 : if (*pinfo2->comment == '\0') {
2847 0 : p = lp_comment(talloc_tos(), lp_sub, snum);
2848 : } else {
2849 0 : p = pinfo2->comment;
2850 : }
2851 :
2852 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2853 0 : }
2854 :
2855 : /*******************************************************************
2856 : * fill a notify_info_data with the comment
2857 : * location = "Room 1, floor 2, building 3"
2858 : ********************************************************************/
2859 :
2860 0 : static void spoolss_notify_location(struct messaging_context *msg_ctx,
2861 : int snum,
2862 : struct spoolss_Notify *data,
2863 : print_queue_struct *queue,
2864 : struct spoolss_PrinterInfo2 *pinfo2,
2865 : TALLOC_CTX *mem_ctx)
2866 : {
2867 0 : const char *loc = pinfo2->location;
2868 0 : NTSTATUS status;
2869 :
2870 0 : status = printer_list_get_printer(mem_ctx,
2871 : pinfo2->sharename,
2872 : NULL,
2873 : &loc,
2874 : NULL);
2875 0 : if (NT_STATUS_IS_OK(status)) {
2876 0 : if (loc == NULL) {
2877 0 : loc = pinfo2->location;
2878 : }
2879 : }
2880 :
2881 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2882 0 : }
2883 :
2884 : /*******************************************************************
2885 : * fill a notify_info_data with the device mode
2886 : * jfm:xxxx don't to it for know but that's a real problem !!!
2887 : ********************************************************************/
2888 :
2889 0 : static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2890 : int snum,
2891 : struct spoolss_Notify *data,
2892 : print_queue_struct *queue,
2893 : struct spoolss_PrinterInfo2 *pinfo2,
2894 : TALLOC_CTX *mem_ctx)
2895 : {
2896 : /* for a dummy implementation we have to zero the fields */
2897 0 : SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2898 0 : }
2899 :
2900 : /*******************************************************************
2901 : * fill a notify_info_data with the separator file name
2902 : ********************************************************************/
2903 :
2904 0 : static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2905 : int snum,
2906 : struct spoolss_Notify *data,
2907 : print_queue_struct *queue,
2908 : struct spoolss_PrinterInfo2 *pinfo2,
2909 : TALLOC_CTX *mem_ctx)
2910 : {
2911 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2912 0 : }
2913 :
2914 : /*******************************************************************
2915 : * fill a notify_info_data with the print processor
2916 : * jfm:xxxx return always winprint to indicate we don't do anything to it
2917 : ********************************************************************/
2918 :
2919 0 : static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2920 : int snum,
2921 : struct spoolss_Notify *data,
2922 : print_queue_struct *queue,
2923 : struct spoolss_PrinterInfo2 *pinfo2,
2924 : TALLOC_CTX *mem_ctx)
2925 : {
2926 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2927 0 : }
2928 :
2929 : /*******************************************************************
2930 : * fill a notify_info_data with the print processor options
2931 : * jfm:xxxx send an empty string
2932 : ********************************************************************/
2933 :
2934 0 : static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2935 : int snum,
2936 : struct spoolss_Notify *data,
2937 : print_queue_struct *queue,
2938 : struct spoolss_PrinterInfo2 *pinfo2,
2939 : TALLOC_CTX *mem_ctx)
2940 : {
2941 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2942 0 : }
2943 :
2944 : /*******************************************************************
2945 : * fill a notify_info_data with the data type
2946 : * jfm:xxxx always send RAW as data type
2947 : ********************************************************************/
2948 :
2949 0 : static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2950 : int snum,
2951 : struct spoolss_Notify *data,
2952 : print_queue_struct *queue,
2953 : struct spoolss_PrinterInfo2 *pinfo2,
2954 : TALLOC_CTX *mem_ctx)
2955 : {
2956 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2957 0 : }
2958 :
2959 : /*******************************************************************
2960 : * fill a notify_info_data with the security descriptor
2961 : * jfm:xxxx send an null pointer to say no security desc
2962 : * have to implement security before !
2963 : ********************************************************************/
2964 :
2965 0 : static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2966 : int snum,
2967 : struct spoolss_Notify *data,
2968 : print_queue_struct *queue,
2969 : struct spoolss_PrinterInfo2 *pinfo2,
2970 : TALLOC_CTX *mem_ctx)
2971 : {
2972 0 : if (pinfo2->secdesc == NULL) {
2973 0 : data->data.sd.sd = NULL;
2974 : } else {
2975 0 : data->data.sd.sd = security_descriptor_copy(mem_ctx,
2976 0 : pinfo2->secdesc);
2977 : }
2978 0 : data->data.sd.sd_size = ndr_size_security_descriptor(data->data.sd.sd,
2979 : 0);
2980 0 : }
2981 :
2982 : /*******************************************************************
2983 : * fill a notify_info_data with the attributes
2984 : * jfm:xxxx a samba printer is always shared
2985 : ********************************************************************/
2986 :
2987 0 : static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2988 : int snum,
2989 : struct spoolss_Notify *data,
2990 : print_queue_struct *queue,
2991 : struct spoolss_PrinterInfo2 *pinfo2,
2992 : TALLOC_CTX *mem_ctx)
2993 : {
2994 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2995 0 : }
2996 :
2997 : /*******************************************************************
2998 : * fill a notify_info_data with the priority
2999 : ********************************************************************/
3000 :
3001 0 : static void spoolss_notify_priority(struct messaging_context *msg_ctx,
3002 : int snum,
3003 : struct spoolss_Notify *data,
3004 : print_queue_struct *queue,
3005 : struct spoolss_PrinterInfo2 *pinfo2,
3006 : TALLOC_CTX *mem_ctx)
3007 : {
3008 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
3009 0 : }
3010 :
3011 : /*******************************************************************
3012 : * fill a notify_info_data with the default priority
3013 : ********************************************************************/
3014 :
3015 0 : static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3016 : int snum,
3017 : struct spoolss_Notify *data,
3018 : print_queue_struct *queue,
3019 : struct spoolss_PrinterInfo2 *pinfo2,
3020 : TALLOC_CTX *mem_ctx)
3021 : {
3022 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3023 0 : }
3024 :
3025 : /*******************************************************************
3026 : * fill a notify_info_data with the start time
3027 : ********************************************************************/
3028 :
3029 0 : static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3030 : int snum,
3031 : struct spoolss_Notify *data,
3032 : print_queue_struct *queue,
3033 : struct spoolss_PrinterInfo2 *pinfo2,
3034 : TALLOC_CTX *mem_ctx)
3035 : {
3036 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3037 0 : }
3038 :
3039 : /*******************************************************************
3040 : * fill a notify_info_data with the until time
3041 : ********************************************************************/
3042 :
3043 0 : static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3044 : int snum,
3045 : struct spoolss_Notify *data,
3046 : print_queue_struct *queue,
3047 : struct spoolss_PrinterInfo2 *pinfo2,
3048 : TALLOC_CTX *mem_ctx)
3049 : {
3050 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3051 0 : }
3052 :
3053 : /*******************************************************************
3054 : * fill a notify_info_data with the status
3055 : ********************************************************************/
3056 :
3057 0 : static void spoolss_notify_status(struct messaging_context *msg_ctx,
3058 : int snum,
3059 : struct spoolss_Notify *data,
3060 : print_queue_struct *queue,
3061 : struct spoolss_PrinterInfo2 *pinfo2,
3062 : TALLOC_CTX *mem_ctx)
3063 : {
3064 0 : print_status_struct status;
3065 :
3066 0 : print_queue_length(msg_ctx, snum, &status);
3067 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3068 0 : }
3069 :
3070 : /*******************************************************************
3071 : * fill a notify_info_data with the number of jobs queued
3072 : ********************************************************************/
3073 :
3074 0 : static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3075 : int snum,
3076 : struct spoolss_Notify *data,
3077 : print_queue_struct *queue,
3078 : struct spoolss_PrinterInfo2 *pinfo2,
3079 : TALLOC_CTX *mem_ctx)
3080 : {
3081 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3082 0 : data, print_queue_length(msg_ctx, snum, NULL));
3083 0 : }
3084 :
3085 : /*******************************************************************
3086 : * fill a notify_info_data with the average ppm
3087 : ********************************************************************/
3088 :
3089 0 : static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3090 : int snum,
3091 : struct spoolss_Notify *data,
3092 : print_queue_struct *queue,
3093 : struct spoolss_PrinterInfo2 *pinfo2,
3094 : TALLOC_CTX *mem_ctx)
3095 : {
3096 : /* always respond 8 pages per minutes */
3097 : /* a little hard ! */
3098 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3099 0 : }
3100 :
3101 : /*******************************************************************
3102 : * fill a notify_info_data with username
3103 : ********************************************************************/
3104 :
3105 0 : static void spoolss_notify_username(struct messaging_context *msg_ctx,
3106 : int snum,
3107 : struct spoolss_Notify *data,
3108 : print_queue_struct *queue,
3109 : struct spoolss_PrinterInfo2 *pinfo2,
3110 : TALLOC_CTX *mem_ctx)
3111 : {
3112 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3113 0 : }
3114 :
3115 : /*******************************************************************
3116 : * fill a notify_info_data with job status
3117 : ********************************************************************/
3118 :
3119 0 : static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3120 : int snum,
3121 : struct spoolss_Notify *data,
3122 : print_queue_struct *queue,
3123 : struct spoolss_PrinterInfo2 *pinfo2,
3124 : TALLOC_CTX *mem_ctx)
3125 : {
3126 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3127 0 : }
3128 :
3129 : /*******************************************************************
3130 : * fill a notify_info_data with job name
3131 : ********************************************************************/
3132 :
3133 0 : static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3134 : int snum,
3135 : struct spoolss_Notify *data,
3136 : print_queue_struct *queue,
3137 : struct spoolss_PrinterInfo2 *pinfo2,
3138 : TALLOC_CTX *mem_ctx)
3139 : {
3140 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3141 0 : }
3142 :
3143 : /*******************************************************************
3144 : * fill a notify_info_data with job status
3145 : ********************************************************************/
3146 :
3147 0 : static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3148 : int snum,
3149 : struct spoolss_Notify *data,
3150 : print_queue_struct *queue,
3151 : struct spoolss_PrinterInfo2 *pinfo2,
3152 : TALLOC_CTX *mem_ctx)
3153 : {
3154 : /*
3155 : * Now we're returning job status codes we just return a "" here. JRA.
3156 : */
3157 :
3158 0 : const char *p = "";
3159 :
3160 : #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3161 : p = "unknown";
3162 :
3163 : switch (queue->status) {
3164 : case LPQ_QUEUED:
3165 : p = "Queued";
3166 : break;
3167 : case LPQ_PAUSED:
3168 : p = ""; /* NT provides the paused string */
3169 : break;
3170 : case LPQ_SPOOLING:
3171 : p = "Spooling";
3172 : break;
3173 : case LPQ_PRINTING:
3174 : p = "Printing";
3175 : break;
3176 : }
3177 : #endif /* NO LONGER NEEDED. */
3178 :
3179 0 : SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3180 0 : }
3181 :
3182 : /*******************************************************************
3183 : * fill a notify_info_data with job time
3184 : ********************************************************************/
3185 :
3186 0 : static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3187 : int snum,
3188 : struct spoolss_Notify *data,
3189 : print_queue_struct *queue,
3190 : struct spoolss_PrinterInfo2 *pinfo2,
3191 : TALLOC_CTX *mem_ctx)
3192 : {
3193 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3194 0 : }
3195 :
3196 : /*******************************************************************
3197 : * fill a notify_info_data with job size
3198 : ********************************************************************/
3199 :
3200 0 : static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3201 : int snum,
3202 : struct spoolss_Notify *data,
3203 : print_queue_struct *queue,
3204 : struct spoolss_PrinterInfo2 *pinfo2,
3205 : TALLOC_CTX *mem_ctx)
3206 : {
3207 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3208 0 : }
3209 :
3210 : /*******************************************************************
3211 : * fill a notify_info_data with page info
3212 : ********************************************************************/
3213 0 : static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3214 : int snum,
3215 : struct spoolss_Notify *data,
3216 : print_queue_struct *queue,
3217 : struct spoolss_PrinterInfo2 *pinfo2,
3218 : TALLOC_CTX *mem_ctx)
3219 : {
3220 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3221 0 : }
3222 :
3223 : /*******************************************************************
3224 : * fill a notify_info_data with pages printed info.
3225 : ********************************************************************/
3226 0 : static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3227 : int snum,
3228 : struct spoolss_Notify *data,
3229 : print_queue_struct *queue,
3230 : struct spoolss_PrinterInfo2 *pinfo2,
3231 : TALLOC_CTX *mem_ctx)
3232 : {
3233 : /* Add code when back-end tracks this */
3234 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3235 0 : }
3236 :
3237 : /*******************************************************************
3238 : Fill a notify_info_data with job position.
3239 : ********************************************************************/
3240 :
3241 0 : static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3242 : int snum,
3243 : struct spoolss_Notify *data,
3244 : print_queue_struct *queue,
3245 : struct spoolss_PrinterInfo2 *pinfo2,
3246 : TALLOC_CTX *mem_ctx)
3247 : {
3248 0 : SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
3249 0 : }
3250 :
3251 : /*******************************************************************
3252 : Fill a notify_info_data with submitted time.
3253 : ********************************************************************/
3254 :
3255 0 : static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3256 : int snum,
3257 : struct spoolss_Notify *data,
3258 : print_queue_struct *queue,
3259 : struct spoolss_PrinterInfo2 *pinfo2,
3260 : TALLOC_CTX *mem_ctx)
3261 : {
3262 0 : data->data.string.string = NULL;
3263 0 : data->data.string.size = 0;
3264 :
3265 0 : init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3266 : &data->data.string.string,
3267 : &data->data.string.size);
3268 :
3269 0 : }
3270 :
3271 : struct s_notify_info_data_table
3272 : {
3273 : enum spoolss_NotifyType type;
3274 : uint16_t field;
3275 : const char *name;
3276 : enum spoolss_NotifyTable variable_type;
3277 : void (*fn) (struct messaging_context *msg_ctx,
3278 : int snum, struct spoolss_Notify *data,
3279 : print_queue_struct *queue,
3280 : struct spoolss_PrinterInfo2 *pinfo2,
3281 : TALLOC_CTX *mem_ctx);
3282 : };
3283 :
3284 : /* A table describing the various print notification constants and
3285 : whether the notification data is a pointer to a variable sized
3286 : buffer, a one value uint32_t or a two value uint32_t. */
3287 :
3288 : static const struct s_notify_info_data_table notify_info_data_table[] =
3289 : {
3290 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3291 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3292 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3293 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3294 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3295 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3296 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3297 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3298 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3299 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3300 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3301 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3302 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3303 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3304 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3305 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3306 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3307 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3308 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3309 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3310 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3311 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3312 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3313 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3314 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3315 : { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3316 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3317 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3318 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3319 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3320 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3321 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3322 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3323 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3324 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3325 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3326 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3327 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3328 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3329 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3330 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3331 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3332 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3333 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3334 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3335 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3336 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3337 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3338 : { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3339 : };
3340 :
3341 : /*******************************************************************
3342 : Return the variable_type of info_data structure.
3343 : ********************************************************************/
3344 :
3345 0 : static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3346 : uint16_t field)
3347 : {
3348 0 : int i=0;
3349 :
3350 0 : for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3351 0 : if ( (notify_info_data_table[i].type == type) &&
3352 0 : (notify_info_data_table[i].field == field) ) {
3353 0 : return notify_info_data_table[i].variable_type;
3354 : }
3355 : }
3356 :
3357 0 : DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3358 :
3359 0 : return (enum spoolss_NotifyTable) 0;
3360 : }
3361 :
3362 : /****************************************************************************
3363 : ****************************************************************************/
3364 :
3365 0 : static bool search_notify(enum spoolss_NotifyType type,
3366 : uint16_t field,
3367 : int *value)
3368 : {
3369 0 : int i;
3370 :
3371 0 : for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3372 0 : if (notify_info_data_table[i].type == type &&
3373 0 : notify_info_data_table[i].field == field &&
3374 0 : notify_info_data_table[i].fn != NULL) {
3375 0 : *value = i;
3376 0 : return true;
3377 : }
3378 : }
3379 :
3380 0 : return false;
3381 : }
3382 :
3383 : /****************************************************************************
3384 : ****************************************************************************/
3385 :
3386 0 : static void construct_info_data(struct spoolss_Notify *info_data,
3387 : enum spoolss_NotifyType type,
3388 : uint16_t field, int id)
3389 : {
3390 0 : info_data->type = type;
3391 0 : info_data->field.field = field;
3392 0 : info_data->variable_type = variable_type_of_notify_info_data(type, field);
3393 0 : info_data->job_id = id;
3394 0 : }
3395 :
3396 : /*******************************************************************
3397 : *
3398 : * fill a notify_info struct with info asked
3399 : *
3400 : ********************************************************************/
3401 :
3402 0 : static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3403 : struct printer_handle *print_hnd,
3404 : struct spoolss_NotifyInfo *info,
3405 : struct spoolss_PrinterInfo2 *pinfo2,
3406 : int snum,
3407 : const struct spoolss_NotifyOptionType *option_type,
3408 : uint32_t id,
3409 : TALLOC_CTX *mem_ctx)
3410 : {
3411 0 : const struct loadparm_substitution *lp_sub =
3412 0 : loadparm_s3_global_substitution();
3413 0 : int field_num,j;
3414 0 : enum spoolss_NotifyType type;
3415 0 : uint16_t field;
3416 :
3417 0 : struct spoolss_Notify *current_data;
3418 :
3419 0 : type = option_type->type;
3420 :
3421 0 : DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3422 : (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3423 : option_type->count, lp_servicename(talloc_tos(), lp_sub, snum)));
3424 :
3425 0 : for(field_num=0; field_num < option_type->count; field_num++) {
3426 0 : field = option_type->fields[field_num].field;
3427 :
3428 0 : DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3429 :
3430 0 : if (!search_notify(type, field, &j) )
3431 0 : continue;
3432 :
3433 0 : info->notifies = talloc_realloc(info, info->notifies,
3434 : struct spoolss_Notify,
3435 : info->count + 1);
3436 0 : if (info->notifies == NULL) {
3437 0 : DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3438 0 : return false;
3439 : }
3440 :
3441 0 : current_data = &info->notifies[info->count];
3442 :
3443 0 : construct_info_data(current_data, type, field, id);
3444 :
3445 0 : DEBUG(10, ("construct_notify_printer_info: "
3446 : "calling [%s] snum=%d printername=[%s])\n",
3447 : notify_info_data_table[j].name, snum,
3448 : pinfo2->printername));
3449 :
3450 0 : notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3451 : NULL, pinfo2, mem_ctx);
3452 :
3453 0 : info->count++;
3454 : }
3455 :
3456 0 : return true;
3457 : }
3458 :
3459 : /*******************************************************************
3460 : *
3461 : * fill a notify_info struct with info asked
3462 : *
3463 : ********************************************************************/
3464 :
3465 0 : static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3466 : print_queue_struct *queue,
3467 : struct spoolss_NotifyInfo *info,
3468 : struct spoolss_PrinterInfo2 *pinfo2,
3469 : int snum,
3470 : const struct spoolss_NotifyOptionType *option_type,
3471 : uint32_t id,
3472 : TALLOC_CTX *mem_ctx)
3473 : {
3474 0 : int field_num,j;
3475 0 : enum spoolss_NotifyType type;
3476 0 : uint16_t field;
3477 0 : struct spoolss_Notify *current_data;
3478 :
3479 0 : DEBUG(4,("construct_notify_jobs_info\n"));
3480 :
3481 0 : type = option_type->type;
3482 :
3483 0 : DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3484 : (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3485 : option_type->count));
3486 :
3487 0 : for(field_num=0; field_num<option_type->count; field_num++) {
3488 0 : field = option_type->fields[field_num].field;
3489 :
3490 0 : if (!search_notify(type, field, &j) )
3491 0 : continue;
3492 :
3493 0 : info->notifies = talloc_realloc(info, info->notifies,
3494 : struct spoolss_Notify,
3495 : info->count + 1);
3496 0 : if (info->notifies == NULL) {
3497 0 : DEBUG(2,("construct_notify_jobs_info: failed to enlarge buffer info->data!\n"));
3498 0 : return false;
3499 : }
3500 :
3501 0 : current_data=&(info->notifies[info->count]);
3502 :
3503 0 : construct_info_data(current_data, type, field, id);
3504 0 : notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3505 : queue, pinfo2, mem_ctx);
3506 0 : info->count++;
3507 : }
3508 :
3509 0 : return true;
3510 : }
3511 :
3512 : /*
3513 : * JFM: The enumeration is not that simple, it's even non obvious.
3514 : *
3515 : * let's take an example: I want to monitor the PRINTER SERVER for
3516 : * the printer's name and the number of jobs currently queued.
3517 : * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3518 : * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3519 : *
3520 : * I have 3 printers on the back of my server.
3521 : *
3522 : * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3523 : * structures.
3524 : * Number Data Id
3525 : * 1 printer 1 name 1
3526 : * 2 printer 1 cjob 1
3527 : * 3 printer 2 name 2
3528 : * 4 printer 2 cjob 2
3529 : * 5 printer 3 name 3
3530 : * 6 printer 3 name 3
3531 : *
3532 : * that's the print server case, the printer case is even worse.
3533 : */
3534 :
3535 : /*******************************************************************
3536 : *
3537 : * enumerate all printers on the printserver
3538 : * fill a notify_info struct with info asked
3539 : *
3540 : ********************************************************************/
3541 :
3542 4 : static WERROR printserver_notify_info(struct pipes_struct *p,
3543 : struct policy_handle *hnd,
3544 : struct spoolss_NotifyInfo *info,
3545 : TALLOC_CTX *mem_ctx)
3546 : {
3547 0 : const struct loadparm_substitution *lp_sub =
3548 4 : loadparm_s3_global_substitution();
3549 0 : int snum;
3550 4 : struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3551 4 : int n_services=lp_numservices();
3552 0 : int i;
3553 0 : struct spoolss_NotifyOption *option;
3554 0 : struct spoolss_NotifyOptionType option_type;
3555 4 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3556 0 : WERROR result;
3557 :
3558 4 : DEBUG(4,("printserver_notify_info\n"));
3559 :
3560 4 : if (!Printer)
3561 0 : return WERR_INVALID_HANDLE;
3562 :
3563 4 : option = Printer->notify.option;
3564 :
3565 4 : info->version = 2;
3566 4 : info->notifies = NULL;
3567 4 : info->count = 0;
3568 :
3569 : /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3570 : sending a ffpcn() request first */
3571 :
3572 4 : if ( !option )
3573 0 : return WERR_INVALID_HANDLE;
3574 :
3575 12 : for (i=0; i<option->count; i++) {
3576 8 : option_type = option->types[i];
3577 :
3578 8 : if (option_type.type != PRINTER_NOTIFY_TYPE)
3579 4 : continue;
3580 :
3581 492 : for (snum = 0; snum < n_services; snum++) {
3582 488 : if (!lp_browseable(snum) ||
3583 488 : !lp_snum_ok(snum) ||
3584 488 : !lp_printable(snum)) {
3585 468 : continue; /* skip */
3586 : }
3587 :
3588 : /* Maybe we should use the SYSTEM session_info here... */
3589 20 : result = winreg_get_printer_internal(mem_ctx,
3590 : get_session_info_system(),
3591 : p->msg_ctx,
3592 20 : lp_servicename(talloc_tos(), lp_sub, snum),
3593 : &pinfo2);
3594 20 : if (!W_ERROR_IS_OK(result)) {
3595 20 : DEBUG(4, ("printserver_notify_info: "
3596 : "Failed to get printer [%s]\n",
3597 : lp_servicename(talloc_tos(), lp_sub, snum)));
3598 20 : continue;
3599 : }
3600 :
3601 :
3602 0 : construct_notify_printer_info(p->msg_ctx,
3603 : Printer, info,
3604 : pinfo2, snum,
3605 : &option_type, snum,
3606 : mem_ctx);
3607 :
3608 0 : TALLOC_FREE(pinfo2);
3609 : }
3610 : }
3611 :
3612 : #if 0
3613 : /*
3614 : * Debugging information, don't delete.
3615 : */
3616 :
3617 : DEBUG(1,("dumping the NOTIFY_INFO\n"));
3618 : DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3619 : DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3620 :
3621 : for (i=0; i<info->count; i++) {
3622 : DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3623 : i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3624 : info->data[i].id, info->data[i].size, info->data[i].enc_type));
3625 : }
3626 : #endif
3627 :
3628 4 : return WERR_OK;
3629 : }
3630 :
3631 : /*******************************************************************
3632 : *
3633 : * fill a notify_info struct with info asked
3634 : *
3635 : ********************************************************************/
3636 :
3637 0 : static WERROR printer_notify_info(struct pipes_struct *p,
3638 : struct policy_handle *hnd,
3639 : struct spoolss_NotifyInfo *info,
3640 : TALLOC_CTX *mem_ctx)
3641 : {
3642 0 : const struct loadparm_substitution *lp_sub =
3643 0 : loadparm_s3_global_substitution();
3644 0 : int snum;
3645 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3646 0 : int i;
3647 0 : uint32_t id;
3648 0 : struct spoolss_NotifyOption *option;
3649 0 : struct spoolss_NotifyOptionType option_type;
3650 0 : int count,j;
3651 0 : print_queue_struct *queue=NULL;
3652 0 : print_status_struct status;
3653 0 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3654 0 : WERROR result;
3655 0 : struct tdb_print_db *pdb;
3656 :
3657 0 : DEBUG(4,("printer_notify_info\n"));
3658 :
3659 0 : if (!Printer)
3660 0 : return WERR_INVALID_HANDLE;
3661 :
3662 0 : option = Printer->notify.option;
3663 0 : id = 0x0;
3664 :
3665 0 : info->version = 2;
3666 0 : info->notifies = NULL;
3667 0 : info->count = 0;
3668 :
3669 : /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3670 : sending a ffpcn() request first */
3671 :
3672 0 : if ( !option )
3673 0 : return WERR_INVALID_HANDLE;
3674 :
3675 0 : if (!get_printer_snum(p, hnd, &snum, NULL)) {
3676 0 : return WERR_INVALID_HANDLE;
3677 : }
3678 :
3679 0 : pdb = get_print_db_byname(Printer->sharename);
3680 0 : if (pdb == NULL) {
3681 0 : return WERR_INVALID_HANDLE;
3682 : }
3683 :
3684 : /* Maybe we should use the SYSTEM session_info here... */
3685 0 : result = winreg_get_printer_internal(mem_ctx,
3686 : get_session_info_system(),
3687 : p->msg_ctx,
3688 0 : lp_servicename(talloc_tos(), lp_sub, snum), &pinfo2);
3689 0 : if (!W_ERROR_IS_OK(result)) {
3690 0 : result = WERR_INVALID_HANDLE;
3691 0 : goto err_pdb_drop;
3692 : }
3693 :
3694 : /*
3695 : * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3696 : * correct servername.
3697 : */
3698 0 : pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3699 0 : if (pinfo2->servername == NULL) {
3700 0 : result = WERR_NOT_ENOUGH_MEMORY;
3701 0 : goto err_pdb_drop;
3702 : }
3703 :
3704 0 : for (i = 0; i < option->count; i++) {
3705 0 : option_type = option->types[i];
3706 :
3707 0 : switch (option_type.type) {
3708 0 : case PRINTER_NOTIFY_TYPE:
3709 0 : if (construct_notify_printer_info(p->msg_ctx,
3710 : Printer, info,
3711 : pinfo2, snum,
3712 : &option_type, id,
3713 : mem_ctx)) {
3714 0 : id--;
3715 : }
3716 0 : break;
3717 :
3718 0 : case JOB_NOTIFY_TYPE:
3719 :
3720 0 : count = print_queue_status(p->msg_ctx, snum, &queue,
3721 : &status);
3722 :
3723 0 : for (j = 0; j < count; j++) {
3724 0 : uint32_t jobid;
3725 0 : jobid = sysjob_to_jobid_pdb(pdb,
3726 0 : queue[j].sysjob);
3727 0 : if (jobid == (uint32_t)-1) {
3728 0 : DEBUG(2, ("ignoring untracked job %d\n",
3729 : queue[j].sysjob));
3730 0 : continue;
3731 : }
3732 : /* FIXME check return value */
3733 0 : construct_notify_jobs_info(p->msg_ctx,
3734 0 : &queue[j], info,
3735 : pinfo2, snum,
3736 : &option_type,
3737 : jobid,
3738 : mem_ctx);
3739 : }
3740 :
3741 0 : SAFE_FREE(queue);
3742 0 : break;
3743 : }
3744 : }
3745 :
3746 : /*
3747 : * Debugging information, don't delete.
3748 : */
3749 : /*
3750 : DEBUG(1,("dumping the NOTIFY_INFO\n"));
3751 : DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3752 : DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3753 :
3754 : for (i=0; i<info->count; i++) {
3755 : DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3756 : i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3757 : info->data[i].id, info->data[i].size, info->data[i].enc_type));
3758 : }
3759 : */
3760 :
3761 0 : talloc_free(pinfo2);
3762 0 : result = WERR_OK;
3763 0 : err_pdb_drop:
3764 0 : release_print_db(pdb);
3765 0 : return result;
3766 : }
3767 :
3768 : /****************************************************************
3769 : _spoolss_RouterRefreshPrinterChangeNotify
3770 : ****************************************************************/
3771 :
3772 4 : WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3773 : struct spoolss_RouterRefreshPrinterChangeNotify *r)
3774 : {
3775 0 : struct spoolss_NotifyInfo *info;
3776 :
3777 4 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3778 4 : WERROR result = WERR_INVALID_HANDLE;
3779 :
3780 : /* we always have a spoolss_NotifyInfo struct */
3781 4 : info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3782 4 : if (!info) {
3783 0 : result = WERR_NOT_ENOUGH_MEMORY;
3784 0 : goto done;
3785 : }
3786 :
3787 4 : *r->out.info = info;
3788 :
3789 4 : if (!Printer) {
3790 0 : DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3791 : "Invalid handle (%s:%u:%u).\n",
3792 : OUR_HANDLE(r->in.handle)));
3793 0 : goto done;
3794 : }
3795 :
3796 4 : DEBUG(4,("Printer type %x\n",Printer->printer_type));
3797 :
3798 : /*
3799 : * We are now using the change value, and
3800 : * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3801 : * I don't have a global notification system, I'm sending back all the
3802 : * information even when _NOTHING_ has changed.
3803 : */
3804 :
3805 : /* We need to keep track of the change value to send back in
3806 : RRPCN replies otherwise our updates are ignored. */
3807 :
3808 4 : Printer->notify.fnpcn = true;
3809 :
3810 4 : if (Printer->notify.cli_chan != NULL &&
3811 4 : Printer->notify.cli_chan->active_connections > 0) {
3812 4 : DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3813 : "Saving change value in request [%x]\n",
3814 : r->in.change_low));
3815 4 : Printer->notify.change = r->in.change_low;
3816 : }
3817 :
3818 : /* just ignore the spoolss_NotifyOption */
3819 :
3820 4 : switch (Printer->printer_type) {
3821 4 : case SPLHND_SERVER:
3822 4 : result = printserver_notify_info(p, r->in.handle,
3823 : info, p->mem_ctx);
3824 4 : break;
3825 :
3826 0 : case SPLHND_PRINTER:
3827 0 : result = printer_notify_info(p, r->in.handle,
3828 : info, p->mem_ctx);
3829 0 : break;
3830 : }
3831 :
3832 4 : Printer->notify.fnpcn = false;
3833 :
3834 4 : done:
3835 4 : return result;
3836 : }
3837 :
3838 : /********************************************************************
3839 : ********************************************************************/
3840 :
3841 4076 : static WERROR create_printername(TALLOC_CTX *mem_ctx,
3842 : const char *servername,
3843 : const char *printername,
3844 : const char **printername_p)
3845 : {
3846 : /* FIXME: add lp_force_printername() */
3847 :
3848 4076 : if (servername == NULL) {
3849 1732 : *printername_p = talloc_strdup(mem_ctx, printername);
3850 1732 : W_ERROR_HAVE_NO_MEMORY(*printername_p);
3851 1732 : return WERR_OK;
3852 : }
3853 :
3854 2344 : if (servername[0] == '\\' && servername[1] == '\\') {
3855 2344 : servername += 2;
3856 : }
3857 :
3858 2344 : *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3859 2344 : W_ERROR_HAVE_NO_MEMORY(*printername_p);
3860 :
3861 2344 : return WERR_OK;
3862 : }
3863 :
3864 : /********************************************************************
3865 : ********************************************************************/
3866 :
3867 2936 : static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3868 : const char *printername)
3869 : {
3870 2936 : if (dm == NULL) {
3871 94 : return;
3872 : }
3873 :
3874 2842 : dm->devicename = talloc_strndup(dm, printername,
3875 2842 : MIN(strlen(printername), 31));
3876 : }
3877 :
3878 : /********************************************************************
3879 : * construct_printer_info_0
3880 : * fill a printer_info_0 struct
3881 : ********************************************************************/
3882 :
3883 276 : static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3884 : const struct auth_session_info *session_info,
3885 : struct messaging_context *msg_ctx,
3886 : struct spoolss_PrinterInfo2 *info2,
3887 : const char *servername,
3888 : struct spoolss_PrinterInfo0 *r,
3889 : int snum)
3890 : {
3891 0 : int count;
3892 0 : struct printer_session_counter *session_counter;
3893 0 : struct timeval setuptime;
3894 0 : print_status_struct status;
3895 0 : WERROR result;
3896 0 : int os_major, os_minor, os_build;
3897 0 : const char *architecture;
3898 0 : uint32_t processor_architecture, processor_type;
3899 :
3900 276 : result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3901 276 : if (!W_ERROR_IS_OK(result)) {
3902 0 : return result;
3903 : }
3904 :
3905 276 : if (servername) {
3906 140 : r->servername = talloc_strdup(mem_ctx, servername);
3907 140 : W_ERROR_HAVE_NO_MEMORY(r->servername);
3908 : } else {
3909 136 : r->servername = NULL;
3910 : }
3911 :
3912 276 : count = print_queue_length(msg_ctx, snum, &status);
3913 :
3914 : /* check if we already have a counter for this printer */
3915 660 : for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3916 620 : if (session_counter->snum == snum)
3917 236 : break;
3918 : }
3919 :
3920 : /* it's the first time, add it to the list */
3921 276 : if (session_counter == NULL) {
3922 40 : session_counter = talloc_zero(counter_list, struct printer_session_counter);
3923 40 : W_ERROR_HAVE_NO_MEMORY(session_counter);
3924 40 : session_counter->snum = snum;
3925 40 : session_counter->counter = 0;
3926 40 : DLIST_ADD(counter_list, session_counter);
3927 : }
3928 :
3929 : /* increment it */
3930 276 : session_counter->counter++;
3931 :
3932 276 : r->cjobs = count;
3933 276 : r->total_jobs = 0;
3934 276 : r->total_bytes = 0;
3935 :
3936 276 : get_startup_time(&setuptime);
3937 276 : init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3938 :
3939 : /* JFM:
3940 : * the global_counter should be stored in a TDB as it's common to all the clients
3941 : * and should be zeroed on samba startup
3942 : */
3943 276 : r->global_counter = session_counter->counter;
3944 276 : r->total_pages = 0;
3945 :
3946 : /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3947 276 : os_major = lp_parm_int(GLOBAL_SECTION_SNUM,
3948 : "spoolss", "os_major",
3949 : GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT);
3950 276 : os_minor = lp_parm_int(GLOBAL_SECTION_SNUM,
3951 : "spoolss", "os_minor",
3952 : GLOBAL_SPOOLSS_OS_MINOR_DEFAULT);
3953 276 : os_build = lp_parm_int(GLOBAL_SECTION_SNUM,
3954 : "spoolss", "os_build",
3955 : GLOBAL_SPOOLSS_OS_BUILD_DEFAULT);
3956 :
3957 276 : SCVAL(&r->version, 0, os_major);
3958 276 : SCVAL(&r->version, 1, os_minor);
3959 276 : SSVAL(&r->version, 2, os_build);
3960 :
3961 276 : architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
3962 : "spoolss",
3963 : "architecture",
3964 : GLOBAL_SPOOLSS_ARCHITECTURE);
3965 :
3966 276 : if (strequal(architecture, SPOOLSS_ARCHITECTURE_x64)) {
3967 276 : processor_architecture = PROCESSOR_ARCHITECTURE_AMD64;
3968 276 : processor_type = PROCESSOR_AMD_X8664;
3969 0 : } else if (strequal(architecture, SPOOLSS_ARCHITECTURE_ARM64)) {
3970 0 : processor_architecture = PROCESSOR_ARCHITECTURE_ARM64;
3971 0 : processor_type = PROCESSOR_ARM820;
3972 : } else {
3973 0 : processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3974 0 : processor_type = PROCESSOR_INTEL_PENTIUM;
3975 : }
3976 :
3977 276 : r->free_build = SPOOLSS_RELEASE_BUILD;
3978 276 : r->spooling = 0;
3979 276 : r->max_spooling = 0;
3980 276 : r->session_counter = session_counter->counter;
3981 276 : r->num_error_out_of_paper = 0x0;
3982 276 : r->num_error_not_ready = 0x0; /* number of print failure */
3983 276 : r->job_error = 0x0;
3984 276 : r->number_of_processors = 0x1;
3985 276 : r->processor_type = processor_type;
3986 276 : r->high_part_total_bytes = 0x0;
3987 :
3988 : /* ChangeID in milliseconds*/
3989 276 : winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3990 : info2->sharename, &r->change_id);
3991 :
3992 276 : r->last_error = WERR_OK;
3993 276 : r->status = nt_printq_status(status.status);
3994 276 : r->enumerate_network_printers = 0x0;
3995 276 : r->c_setprinter = 0x0;
3996 276 : r->processor_architecture = processor_architecture;
3997 276 : r->processor_level = 0x6; /* 6 ???*/
3998 276 : r->ref_ic = 0;
3999 276 : r->reserved2 = 0;
4000 276 : r->reserved3 = 0;
4001 :
4002 276 : return WERR_OK;
4003 : }
4004 :
4005 :
4006 : /********************************************************************
4007 : * construct_printer_info1
4008 : * fill a spoolss_PrinterInfo1 struct
4009 : ********************************************************************/
4010 :
4011 528 : static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
4012 : const struct spoolss_PrinterInfo2 *info2,
4013 : uint32_t flags,
4014 : const char *servername,
4015 : struct spoolss_PrinterInfo1 *r,
4016 : int snum)
4017 : {
4018 0 : const struct loadparm_substitution *lp_sub =
4019 528 : loadparm_s3_global_substitution();
4020 0 : WERROR result;
4021 :
4022 528 : r->flags = flags;
4023 :
4024 528 : if (info2->comment == NULL || info2->comment[0] == '\0') {
4025 388 : r->comment = lp_comment(mem_ctx, lp_sub, snum);
4026 : } else {
4027 140 : r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
4028 : }
4029 528 : W_ERROR_HAVE_NO_MEMORY(r->comment);
4030 :
4031 528 : result = create_printername(mem_ctx, servername, info2->printername, &r->name);
4032 528 : if (!W_ERROR_IS_OK(result)) {
4033 0 : return result;
4034 : }
4035 :
4036 1056 : r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
4037 : r->name,
4038 528 : info2->drivername,
4039 : r->comment);
4040 528 : W_ERROR_HAVE_NO_MEMORY(r->description);
4041 :
4042 528 : return WERR_OK;
4043 : }
4044 :
4045 : /********************************************************************
4046 : * construct_printer_info2
4047 : * fill a spoolss_PrinterInfo2 struct
4048 : ********************************************************************/
4049 :
4050 1272 : static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4051 : struct messaging_context *msg_ctx,
4052 : const struct spoolss_PrinterInfo2 *info2,
4053 : const char *servername,
4054 : struct spoolss_PrinterInfo2 *r,
4055 : int snum)
4056 : {
4057 0 : const struct loadparm_substitution *lp_sub =
4058 1272 : loadparm_s3_global_substitution();
4059 0 : int count;
4060 0 : print_status_struct status;
4061 0 : WERROR result;
4062 :
4063 1272 : count = print_queue_length(msg_ctx, snum, &status);
4064 :
4065 1272 : if (servername) {
4066 572 : r->servername = talloc_strdup(mem_ctx, servername);
4067 572 : W_ERROR_HAVE_NO_MEMORY(r->servername);
4068 : } else {
4069 700 : r->servername = NULL;
4070 : }
4071 :
4072 1272 : result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4073 1272 : if (!W_ERROR_IS_OK(result)) {
4074 0 : return result;
4075 : }
4076 :
4077 1272 : r->sharename = lp_servicename(mem_ctx, lp_sub, snum);
4078 1272 : W_ERROR_HAVE_NO_MEMORY(r->sharename);
4079 1272 : r->portname = talloc_strdup(mem_ctx, info2->portname);
4080 1272 : W_ERROR_HAVE_NO_MEMORY(r->portname);
4081 1272 : r->drivername = talloc_strdup(mem_ctx, info2->drivername);
4082 1272 : W_ERROR_HAVE_NO_MEMORY(r->drivername);
4083 :
4084 1272 : if (info2->comment[0] == '\0') {
4085 876 : r->comment = lp_comment(mem_ctx, lp_sub, snum);
4086 : } else {
4087 396 : r->comment = talloc_strdup(mem_ctx, info2->comment);
4088 : }
4089 1272 : W_ERROR_HAVE_NO_MEMORY(r->comment);
4090 :
4091 1272 : r->location = talloc_strdup(mem_ctx, info2->location);
4092 1272 : if (info2->location[0] == '\0') {
4093 1192 : const char *loc = NULL;
4094 0 : NTSTATUS nt_status;
4095 :
4096 1192 : nt_status = printer_list_get_printer(mem_ctx,
4097 1192 : info2->sharename,
4098 : NULL,
4099 : &loc,
4100 : NULL);
4101 1192 : if (NT_STATUS_IS_OK(nt_status)) {
4102 0 : if (loc != NULL) {
4103 0 : r->location = talloc_strdup(mem_ctx, loc);
4104 : }
4105 : }
4106 : }
4107 1272 : W_ERROR_HAVE_NO_MEMORY(r->location);
4108 :
4109 1272 : r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4110 1272 : W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4111 1272 : r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4112 1272 : W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4113 1272 : r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4114 1272 : W_ERROR_HAVE_NO_MEMORY(r->datatype);
4115 1272 : r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4116 1272 : W_ERROR_HAVE_NO_MEMORY(r->parameters);
4117 :
4118 1272 : r->attributes = info2->attributes;
4119 :
4120 1272 : r->priority = info2->priority;
4121 1272 : r->defaultpriority = info2->defaultpriority;
4122 1272 : r->starttime = info2->starttime;
4123 1272 : r->untiltime = info2->untiltime;
4124 1272 : r->status = nt_printq_status(status.status);
4125 1272 : r->cjobs = count;
4126 1272 : r->averageppm = info2->averageppm;
4127 :
4128 1272 : if (info2->devmode != NULL) {
4129 1186 : result = copy_devicemode(mem_ctx,
4130 1186 : info2->devmode,
4131 : &r->devmode);
4132 1186 : if (!W_ERROR_IS_OK(result)) {
4133 0 : return result;
4134 : }
4135 86 : } else if (lp_default_devmode(snum)) {
4136 0 : result = spoolss_create_default_devmode(mem_ctx,
4137 0 : info2->printername,
4138 : &r->devmode);
4139 0 : if (!W_ERROR_IS_OK(result)) {
4140 0 : return result;
4141 : }
4142 : } else {
4143 86 : r->devmode = NULL;
4144 86 : DEBUG(8,("Returning NULL Devicemode!\n"));
4145 : }
4146 :
4147 1272 : compose_devicemode_devicename(r->devmode, r->printername);
4148 :
4149 1272 : r->secdesc = NULL;
4150 :
4151 1272 : if (info2->secdesc != NULL) {
4152 : /* don't use talloc_steal() here unless you do a deep steal of all
4153 : the SEC_DESC members */
4154 :
4155 1272 : r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4156 1272 : if (r->secdesc == NULL) {
4157 0 : return WERR_NOT_ENOUGH_MEMORY;
4158 : }
4159 : }
4160 :
4161 1272 : return WERR_OK;
4162 : }
4163 :
4164 : /********************************************************************
4165 : * construct_printer_info3
4166 : * fill a spoolss_PrinterInfo3 struct
4167 : ********************************************************************/
4168 :
4169 144 : static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4170 : const struct spoolss_PrinterInfo2 *info2,
4171 : const char *servername,
4172 : struct spoolss_PrinterInfo3 *r,
4173 : int snum)
4174 : {
4175 : /* These are the components of the SD we are returning. */
4176 :
4177 144 : if (info2->secdesc != NULL) {
4178 : /* don't use talloc_steal() here unless you do a deep steal of all
4179 : the SEC_DESC members */
4180 :
4181 144 : r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4182 144 : if (r->secdesc == NULL) {
4183 0 : return WERR_NOT_ENOUGH_MEMORY;
4184 : }
4185 : }
4186 :
4187 144 : return WERR_OK;
4188 : }
4189 :
4190 : /********************************************************************
4191 : * construct_printer_info4
4192 : * fill a spoolss_PrinterInfo4 struct
4193 : ********************************************************************/
4194 :
4195 168 : static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4196 : const struct spoolss_PrinterInfo2 *info2,
4197 : const char *servername,
4198 : struct spoolss_PrinterInfo4 *r,
4199 : int snum)
4200 : {
4201 0 : WERROR result;
4202 :
4203 168 : result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4204 168 : if (!W_ERROR_IS_OK(result)) {
4205 0 : return result;
4206 : }
4207 :
4208 168 : if (servername) {
4209 8 : r->servername = talloc_strdup(mem_ctx, servername);
4210 8 : W_ERROR_HAVE_NO_MEMORY(r->servername);
4211 : } else {
4212 160 : r->servername = NULL;
4213 : }
4214 :
4215 168 : r->attributes = info2->attributes;
4216 :
4217 168 : return WERR_OK;
4218 : }
4219 :
4220 : /********************************************************************
4221 : * construct_printer_info5
4222 : * fill a spoolss_PrinterInfo5 struct
4223 : ********************************************************************/
4224 :
4225 168 : static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4226 : const struct spoolss_PrinterInfo2 *info2,
4227 : const char *servername,
4228 : struct spoolss_PrinterInfo5 *r,
4229 : int snum)
4230 : {
4231 0 : WERROR result;
4232 :
4233 168 : result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4234 168 : if (!W_ERROR_IS_OK(result)) {
4235 0 : return result;
4236 : }
4237 :
4238 168 : r->portname = talloc_strdup(mem_ctx, info2->portname);
4239 168 : W_ERROR_HAVE_NO_MEMORY(r->portname);
4240 :
4241 168 : r->attributes = info2->attributes;
4242 :
4243 : /*
4244 : * These two are not used by NT+ according to MSDN. However the values
4245 : * we saw on Windows Server 2012 and 2016 are always set to the 0xafc8.
4246 : */
4247 168 : r->device_not_selected_timeout = 0xafc8; /* 45 sec */
4248 168 : r->transmission_retry_timeout = 0xafc8; /* 45 sec */
4249 :
4250 168 : return WERR_OK;
4251 : }
4252 :
4253 : /********************************************************************
4254 : * construct_printer_info_6
4255 : * fill a spoolss_PrinterInfo6 struct
4256 : ********************************************************************/
4257 :
4258 88 : static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4259 : struct messaging_context *msg_ctx,
4260 : const struct spoolss_PrinterInfo2 *info2,
4261 : const char *servername,
4262 : struct spoolss_PrinterInfo6 *r,
4263 : int snum)
4264 : {
4265 0 : print_status_struct status;
4266 :
4267 88 : print_queue_length(msg_ctx, snum, &status);
4268 :
4269 88 : r->status = nt_printq_status(status.status);
4270 :
4271 88 : return WERR_OK;
4272 : }
4273 :
4274 : /********************************************************************
4275 : * construct_printer_info7
4276 : * fill a spoolss_PrinterInfo7 struct
4277 : ********************************************************************/
4278 :
4279 112 : static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4280 : struct messaging_context *msg_ctx,
4281 : const char *servername,
4282 : struct spoolss_PrinterInfo7 *r,
4283 : int snum)
4284 : {
4285 0 : const struct loadparm_substitution *lp_sub =
4286 112 : loadparm_s3_global_substitution();
4287 0 : const struct auth_session_info *session_info;
4288 112 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
4289 0 : char *printer;
4290 0 : WERROR werr;
4291 112 : TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4292 112 : if (tmp_ctx == NULL) {
4293 0 : return WERR_NOT_ENOUGH_MEMORY;
4294 : }
4295 :
4296 112 : session_info = get_session_info_system();
4297 112 : SMB_ASSERT(session_info != NULL);
4298 :
4299 112 : printer = lp_servicename(tmp_ctx, lp_sub, snum);
4300 112 : if (printer == NULL) {
4301 0 : DEBUG(0, ("invalid printer snum %d\n", snum));
4302 0 : werr = WERR_INVALID_PARAMETER;
4303 0 : goto out_tmp_free;
4304 : }
4305 :
4306 112 : if (is_printer_published(tmp_ctx, session_info, msg_ctx,
4307 : servername, printer, &pinfo2)) {
4308 0 : struct GUID guid;
4309 0 : char *guidstr;
4310 0 : werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
4311 : printer, &guid);
4312 0 : if (!W_ERROR_IS_OK(werr)) {
4313 : /*
4314 : * If we do not have a GUID entry in the registry, then
4315 : * try to retrieve it from AD and store it now.
4316 : */
4317 0 : werr = nt_printer_guid_retrieve(tmp_ctx, printer,
4318 : &guid);
4319 0 : if (!W_ERROR_IS_OK(werr)) {
4320 0 : DBG_NOTICE("Failed to retrieve GUID for "
4321 : "printer [%s] from AD - %s\n",
4322 : printer,
4323 : win_errstr(werr));
4324 0 : if (W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND)) {
4325 : /*
4326 : * If we did not find it in AD, then it
4327 : * is unpublished and we should reflect
4328 : * this in the registry and return
4329 : * success.
4330 : */
4331 0 : DBG_WARNING("Unpublish printer [%s]\n",
4332 : pinfo2->sharename);
4333 0 : nt_printer_publish(tmp_ctx,
4334 : session_info,
4335 : msg_ctx,
4336 : pinfo2,
4337 : DSPRINT_UNPUBLISH);
4338 0 : r->guid = talloc_strdup(mem_ctx, "");
4339 0 : r->action = DSPRINT_UNPUBLISH;
4340 :
4341 0 : if (r->guid == NULL) {
4342 0 : werr = WERR_NOT_ENOUGH_MEMORY;
4343 : } else {
4344 0 : werr = WERR_OK;
4345 : }
4346 : }
4347 0 : goto out_tmp_free;
4348 : }
4349 :
4350 0 : werr = nt_printer_guid_store(msg_ctx, printer, guid);
4351 0 : if (!W_ERROR_IS_OK(werr)) {
4352 0 : DEBUG(3, ("failed to store printer %s guid\n",
4353 : printer));
4354 : }
4355 : }
4356 :
4357 : /* [MS-RPRN] section 2.2: must use curly-braced GUIDs */
4358 0 : guidstr = GUID_string2(mem_ctx, &guid);
4359 0 : if (guidstr == NULL) {
4360 0 : werr = WERR_NOT_ENOUGH_MEMORY;
4361 0 : goto out_tmp_free;
4362 : }
4363 : /* Convert GUID string to uppercase otherwise printers
4364 : * are pruned */
4365 0 : r->guid = talloc_strdup_upper(mem_ctx, guidstr);
4366 0 : r->action = DSPRINT_PUBLISH;
4367 :
4368 0 : TALLOC_FREE(guidstr);
4369 : } else {
4370 112 : r->guid = talloc_strdup(mem_ctx, "");
4371 112 : r->action = DSPRINT_UNPUBLISH;
4372 : }
4373 112 : if (r->guid == NULL) {
4374 0 : werr = WERR_NOT_ENOUGH_MEMORY;
4375 0 : goto out_tmp_free;
4376 : }
4377 :
4378 112 : werr = WERR_OK;
4379 112 : out_tmp_free:
4380 112 : talloc_free(tmp_ctx);
4381 112 : return werr;
4382 : }
4383 :
4384 : /********************************************************************
4385 : * construct_printer_info8
4386 : * fill a spoolss_PrinterInfo8 struct
4387 : ********************************************************************/
4388 :
4389 1664 : static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4390 : const struct spoolss_PrinterInfo2 *info2,
4391 : const char *servername,
4392 : struct spoolss_DeviceModeInfo *r,
4393 : int snum)
4394 : {
4395 0 : WERROR result;
4396 0 : const char *printername;
4397 :
4398 1664 : result = create_printername(mem_ctx, servername, info2->printername, &printername);
4399 1664 : if (!W_ERROR_IS_OK(result)) {
4400 0 : return result;
4401 : }
4402 :
4403 1664 : if (info2->devmode != NULL) {
4404 1656 : result = copy_devicemode(mem_ctx,
4405 1656 : info2->devmode,
4406 : &r->devmode);
4407 1656 : if (!W_ERROR_IS_OK(result)) {
4408 0 : return result;
4409 : }
4410 8 : } else if (lp_default_devmode(snum)) {
4411 0 : result = spoolss_create_default_devmode(mem_ctx,
4412 0 : info2->printername,
4413 : &r->devmode);
4414 0 : if (!W_ERROR_IS_OK(result)) {
4415 0 : return result;
4416 : }
4417 : } else {
4418 8 : r->devmode = NULL;
4419 8 : DEBUG(8,("Returning NULL Devicemode!\n"));
4420 : }
4421 :
4422 1664 : compose_devicemode_devicename(r->devmode, printername);
4423 :
4424 1664 : return WERR_OK;
4425 : }
4426 :
4427 : /********************************************************************
4428 : Spoolss_enumprinters.
4429 : ********************************************************************/
4430 :
4431 180 : static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4432 : const struct auth_session_info *session_info,
4433 : struct messaging_context *msg_ctx,
4434 : const char *servername,
4435 : uint32_t level,
4436 : uint32_t flags,
4437 : union spoolss_PrinterInfo **info_p,
4438 : uint32_t *count_p)
4439 : {
4440 0 : int snum;
4441 0 : int n_services;
4442 180 : union spoolss_PrinterInfo *info = NULL;
4443 180 : uint32_t count = 0;
4444 180 : WERROR result = WERR_OK;
4445 180 : struct dcerpc_binding_handle *b = NULL;
4446 180 : TALLOC_CTX *tmp_ctx = NULL;
4447 :
4448 180 : tmp_ctx = talloc_new(mem_ctx);
4449 180 : if (!tmp_ctx) {
4450 0 : return WERR_NOT_ENOUGH_MEMORY;
4451 : }
4452 :
4453 : /*
4454 : * printer shares are updated on client enumeration. The background
4455 : * printer process updates printer_list.tdb at regular intervals.
4456 : */
4457 180 : become_root();
4458 180 : delete_and_reload_printers();
4459 180 : unbecome_root();
4460 :
4461 180 : n_services = lp_numservices();
4462 180 : *count_p = 0;
4463 180 : *info_p = NULL;
4464 :
4465 12230 : for (snum = 0; snum < n_services; snum++) {
4466 :
4467 0 : const char *printer;
4468 0 : struct spoolss_PrinterInfo2 *info2;
4469 :
4470 12050 : if (!snum_is_shared_printer(snum)) {
4471 11070 : continue;
4472 : }
4473 :
4474 980 : printer = lp_const_servicename(snum);
4475 :
4476 980 : DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4477 : printer, snum));
4478 :
4479 980 : if (b == NULL) {
4480 180 : result = winreg_printer_binding_handle(tmp_ctx,
4481 : session_info,
4482 : msg_ctx,
4483 : &b);
4484 180 : if (!W_ERROR_IS_OK(result)) {
4485 0 : goto out;
4486 : }
4487 : }
4488 :
4489 980 : result = winreg_create_printer(tmp_ctx, b,
4490 : printer);
4491 980 : if (!W_ERROR_IS_OK(result)) {
4492 0 : goto out;
4493 : }
4494 :
4495 980 : info = talloc_realloc(tmp_ctx, info,
4496 : union spoolss_PrinterInfo,
4497 : count + 1);
4498 980 : if (!info) {
4499 0 : result = WERR_NOT_ENOUGH_MEMORY;
4500 0 : goto out;
4501 : }
4502 :
4503 980 : result = winreg_get_printer(tmp_ctx, b,
4504 : printer, &info2);
4505 980 : if (!W_ERROR_IS_OK(result)) {
4506 0 : goto out;
4507 : }
4508 :
4509 980 : switch (level) {
4510 40 : case 0:
4511 40 : result = construct_printer_info0(info, session_info,
4512 : msg_ctx, info2,
4513 : servername,
4514 40 : &info[count].info0, snum);
4515 40 : break;
4516 440 : case 1:
4517 440 : result = construct_printer_info1(info, info2, flags,
4518 : servername,
4519 440 : &info[count].info1, snum);
4520 440 : break;
4521 340 : case 2:
4522 340 : result = construct_printer_info2(info, msg_ctx, info2,
4523 : servername,
4524 340 : &info[count].info2, snum);
4525 340 : break;
4526 80 : case 4:
4527 80 : result = construct_printer_info4(info, info2,
4528 : servername,
4529 80 : &info[count].info4, snum);
4530 80 : break;
4531 80 : case 5:
4532 80 : result = construct_printer_info5(info, info2,
4533 : servername,
4534 80 : &info[count].info5, snum);
4535 80 : break;
4536 :
4537 0 : default:
4538 0 : result = WERR_INVALID_LEVEL;
4539 0 : goto out;
4540 : }
4541 :
4542 980 : if (!W_ERROR_IS_OK(result)) {
4543 0 : goto out;
4544 : }
4545 :
4546 980 : count++;
4547 : }
4548 :
4549 180 : out:
4550 180 : if (W_ERROR_IS_OK(result)) {
4551 180 : *info_p = talloc_move(mem_ctx, &info);
4552 180 : *count_p = count;
4553 : }
4554 :
4555 180 : talloc_free(tmp_ctx);
4556 :
4557 180 : return result;
4558 : }
4559 :
4560 : /********************************************************************
4561 : * handle enumeration of printers at level 0
4562 : ********************************************************************/
4563 :
4564 8 : static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4565 : const struct auth_session_info *session_info,
4566 : struct messaging_context *msg_ctx,
4567 : uint32_t flags,
4568 : const char *servername,
4569 : union spoolss_PrinterInfo **info,
4570 : uint32_t *count)
4571 : {
4572 8 : DEBUG(4,("enum_all_printers_info_0\n"));
4573 :
4574 8 : return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4575 : servername, 0, flags, info, count);
4576 : }
4577 :
4578 :
4579 : /********************************************************************
4580 : ********************************************************************/
4581 :
4582 72 : static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4583 : const struct auth_session_info *session_info,
4584 : struct messaging_context *msg_ctx,
4585 : const char *servername,
4586 : uint32_t flags,
4587 : union spoolss_PrinterInfo **info,
4588 : uint32_t *count)
4589 : {
4590 72 : DEBUG(4,("enum_all_printers_info_1\n"));
4591 :
4592 72 : return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4593 : servername, 1, flags, info, count);
4594 : }
4595 :
4596 : /********************************************************************
4597 : enum_all_printers_info_1_local.
4598 : *********************************************************************/
4599 :
4600 72 : static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4601 : const struct auth_session_info *session_info,
4602 : struct messaging_context *msg_ctx,
4603 : const char *servername,
4604 : union spoolss_PrinterInfo **info,
4605 : uint32_t *count)
4606 : {
4607 72 : DEBUG(4,("enum_all_printers_info_1_local\n"));
4608 :
4609 72 : return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4610 : servername, PRINTER_ENUM_ICON8, info, count);
4611 : }
4612 :
4613 : /********************************************************************
4614 : enum_all_printers_info_1_name.
4615 : *********************************************************************/
4616 :
4617 0 : static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4618 : const struct auth_session_info *session_info,
4619 : struct messaging_context *msg_ctx,
4620 : const char *servername,
4621 : union spoolss_PrinterInfo **info,
4622 : uint32_t *count)
4623 : {
4624 0 : const char *s = servername;
4625 :
4626 0 : DEBUG(4,("enum_all_printers_info_1_name\n"));
4627 :
4628 0 : if (servername != NULL &&
4629 0 : (servername[0] == '\\') && (servername[1] == '\\')) {
4630 0 : s = servername + 2;
4631 : }
4632 :
4633 0 : if (!is_myname_or_ipaddr(s)) {
4634 0 : return WERR_INVALID_NAME;
4635 : }
4636 :
4637 0 : return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4638 : servername, PRINTER_ENUM_ICON8, info, count);
4639 : }
4640 :
4641 : /********************************************************************
4642 : enum_all_printers_info_1_network.
4643 : *********************************************************************/
4644 :
4645 0 : static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4646 : const struct auth_session_info *session_info,
4647 : struct messaging_context *msg_ctx,
4648 : const char *servername,
4649 : union spoolss_PrinterInfo **info,
4650 : uint32_t *count)
4651 : {
4652 0 : const char *s = servername;
4653 :
4654 0 : DEBUG(4,("enum_all_printers_info_1_network\n"));
4655 :
4656 : /* If we respond to a enum_printers level 1 on our name with flags
4657 : set to PRINTER_ENUM_REMOTE with a list of printers then these
4658 : printers incorrectly appear in the APW browse list.
4659 : Specifically the printers for the server appear at the workgroup
4660 : level where all the other servers in the domain are
4661 : listed. Windows responds to this call with a
4662 : WERR_CAN_NOT_COMPLETE so we should do the same. */
4663 :
4664 0 : if (servername != NULL &&
4665 0 : (servername[0] == '\\') && (servername[1] == '\\')) {
4666 0 : s = servername + 2;
4667 : }
4668 :
4669 0 : if (is_myname_or_ipaddr(s)) {
4670 0 : return WERR_CAN_NOT_COMPLETE;
4671 : }
4672 :
4673 0 : return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4674 : servername, PRINTER_ENUM_NAME, info, count);
4675 : }
4676 :
4677 : /********************************************************************
4678 : * api_spoolss_enumprinters
4679 : *
4680 : * called from api_spoolss_enumprinters (see this to understand)
4681 : ********************************************************************/
4682 :
4683 68 : static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4684 : const struct auth_session_info *session_info,
4685 : struct messaging_context *msg_ctx,
4686 : const char *servername,
4687 : union spoolss_PrinterInfo **info,
4688 : uint32_t *count)
4689 : {
4690 68 : DEBUG(4,("enum_all_printers_info_2\n"));
4691 :
4692 68 : return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4693 : servername, 2, 0, info, count);
4694 : }
4695 :
4696 : /********************************************************************
4697 : * handle enumeration of printers at level 1
4698 : ********************************************************************/
4699 :
4700 72 : static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4701 : const struct auth_session_info *session_info,
4702 : struct messaging_context *msg_ctx,
4703 : uint32_t flags,
4704 : const char *servername,
4705 : union spoolss_PrinterInfo **info,
4706 : uint32_t *count)
4707 : {
4708 : /* Not all the flags are equals */
4709 :
4710 72 : if (flags & PRINTER_ENUM_LOCAL) {
4711 72 : return enum_all_printers_info_1_local(mem_ctx, session_info,
4712 : msg_ctx, servername, info, count);
4713 : }
4714 :
4715 0 : if (flags & PRINTER_ENUM_NAME) {
4716 0 : return enum_all_printers_info_1_name(mem_ctx, session_info,
4717 : msg_ctx, servername, info,
4718 : count);
4719 : }
4720 :
4721 0 : if (flags & PRINTER_ENUM_NETWORK) {
4722 0 : return enum_all_printers_info_1_network(mem_ctx, session_info,
4723 : msg_ctx, servername, info,
4724 : count);
4725 : }
4726 :
4727 0 : return WERR_OK; /* NT4sp5 does that */
4728 : }
4729 :
4730 : /********************************************************************
4731 : * handle enumeration of printers at level 2
4732 : ********************************************************************/
4733 :
4734 68 : static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4735 : const struct auth_session_info *session_info,
4736 : struct messaging_context *msg_ctx,
4737 : uint32_t flags,
4738 : const char *servername,
4739 : union spoolss_PrinterInfo **info,
4740 : uint32_t *count)
4741 : {
4742 68 : if (flags & PRINTER_ENUM_LOCAL) {
4743 :
4744 52 : return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4745 : servername,
4746 : info, count);
4747 : }
4748 :
4749 16 : if (flags & PRINTER_ENUM_NAME) {
4750 16 : if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4751 0 : return WERR_INVALID_NAME;
4752 : }
4753 :
4754 16 : return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4755 : servername,
4756 : info, count);
4757 : }
4758 :
4759 0 : if (flags & PRINTER_ENUM_REMOTE) {
4760 0 : return WERR_INVALID_LEVEL;
4761 : }
4762 :
4763 0 : return WERR_OK;
4764 : }
4765 :
4766 : /********************************************************************
4767 : * handle enumeration of printers at level 4
4768 : ********************************************************************/
4769 :
4770 16 : static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4771 : const struct auth_session_info *session_info,
4772 : struct messaging_context *msg_ctx,
4773 : uint32_t flags,
4774 : const char *servername,
4775 : union spoolss_PrinterInfo **info,
4776 : uint32_t *count)
4777 : {
4778 16 : DEBUG(4,("enum_all_printers_info_4\n"));
4779 :
4780 16 : return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4781 : servername, 4, flags, info, count);
4782 : }
4783 :
4784 :
4785 : /********************************************************************
4786 : * handle enumeration of printers at level 5
4787 : ********************************************************************/
4788 :
4789 16 : static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4790 : const struct auth_session_info *session_info,
4791 : struct messaging_context *msg_ctx,
4792 : uint32_t flags,
4793 : const char *servername,
4794 : union spoolss_PrinterInfo **info,
4795 : uint32_t *count)
4796 : {
4797 16 : DEBUG(4,("enum_all_printers_info_5\n"));
4798 :
4799 16 : return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4800 : servername, 5, flags, info, count);
4801 : }
4802 :
4803 : /****************************************************************
4804 : _spoolss_EnumPrinters
4805 : ****************************************************************/
4806 :
4807 180 : WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4808 : struct spoolss_EnumPrinters *r)
4809 : {
4810 180 : const struct auth_session_info *session_info = get_session_info_system();
4811 0 : WERROR result;
4812 :
4813 : /* that's an [in out] buffer */
4814 :
4815 180 : if (!r->in.buffer && (r->in.offered != 0)) {
4816 0 : return WERR_INVALID_PARAMETER;
4817 : }
4818 :
4819 180 : DEBUG(4,("_spoolss_EnumPrinters\n"));
4820 :
4821 180 : *r->out.needed = 0;
4822 180 : *r->out.count = 0;
4823 180 : *r->out.info = NULL;
4824 :
4825 : /*
4826 : * Level 1:
4827 : * flags==PRINTER_ENUM_NAME
4828 : * if name=="" then enumerates all printers
4829 : * if name!="" then enumerate the printer
4830 : * flags==PRINTER_ENUM_REMOTE
4831 : * name is NULL, enumerate printers
4832 : * Level 2: name!="" enumerates printers, name can't be NULL
4833 : * Level 3: doesn't exist
4834 : * Level 4: does a local registry lookup
4835 : * Level 5: same as Level 2
4836 : */
4837 :
4838 180 : if (r->in.server && r->in.server[0] == '\0') {
4839 80 : r->in.server = NULL;
4840 : }
4841 :
4842 180 : switch (r->in.level) {
4843 8 : case 0:
4844 8 : result = enumprinters_level0(p->mem_ctx, session_info,
4845 : p->msg_ctx, r->in.flags,
4846 : r->in.server,
4847 : r->out.info, r->out.count);
4848 8 : break;
4849 72 : case 1:
4850 72 : result = enumprinters_level1(p->mem_ctx, session_info,
4851 : p->msg_ctx, r->in.flags,
4852 : r->in.server,
4853 : r->out.info, r->out.count);
4854 72 : break;
4855 68 : case 2:
4856 68 : result = enumprinters_level2(p->mem_ctx, session_info,
4857 : p->msg_ctx, r->in.flags,
4858 : r->in.server,
4859 : r->out.info, r->out.count);
4860 68 : break;
4861 16 : case 4:
4862 16 : result = enumprinters_level4(p->mem_ctx, session_info,
4863 : p->msg_ctx, r->in.flags,
4864 : r->in.server,
4865 : r->out.info, r->out.count);
4866 16 : break;
4867 16 : case 5:
4868 16 : result = enumprinters_level5(p->mem_ctx, session_info,
4869 : p->msg_ctx, r->in.flags,
4870 : r->in.server,
4871 : r->out.info, r->out.count);
4872 16 : break;
4873 0 : default:
4874 0 : return WERR_INVALID_LEVEL;
4875 : }
4876 :
4877 180 : if (!W_ERROR_IS_OK(result)) {
4878 0 : return result;
4879 : }
4880 :
4881 180 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4882 : spoolss_EnumPrinters,
4883 : *r->out.info, r->in.level,
4884 : *r->out.count);
4885 180 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4886 180 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4887 :
4888 180 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4889 : }
4890 :
4891 : /****************************************************************
4892 : _spoolss_GetPrinter
4893 : ****************************************************************/
4894 :
4895 3512 : WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4896 : struct spoolss_GetPrinter *r)
4897 : {
4898 3512 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4899 3512 : struct spoolss_PrinterInfo2 *info2 = NULL;
4900 3512 : WERROR result = WERR_OK;
4901 0 : int snum;
4902 :
4903 : /* that's an [in out] buffer */
4904 :
4905 3512 : if (!r->in.buffer && (r->in.offered != 0)) {
4906 0 : result = WERR_INVALID_PARAMETER;
4907 0 : goto err_info_free;
4908 : }
4909 :
4910 3512 : *r->out.needed = 0;
4911 :
4912 3512 : if (Printer == NULL) {
4913 0 : result = WERR_INVALID_HANDLE;
4914 0 : goto err_info_free;
4915 : }
4916 :
4917 3512 : if (Printer->printer_type == SPLHND_SERVER) {
4918 :
4919 0 : struct dcerpc_binding_handle *b;
4920 :
4921 72 : if (r->in.level != 3) {
4922 32 : result = WERR_INVALID_LEVEL;
4923 32 : goto err_info_free;
4924 : }
4925 :
4926 40 : result = winreg_printer_binding_handle(p->mem_ctx,
4927 : get_session_info_system(),
4928 : p->msg_ctx,
4929 : &b);
4930 40 : if (!W_ERROR_IS_OK(result)) {
4931 0 : goto err_info_free;
4932 : }
4933 :
4934 40 : result = winreg_get_printserver_secdesc(p->mem_ctx,
4935 : b,
4936 40 : &r->out.info->info3.secdesc);
4937 40 : if (!W_ERROR_IS_OK(result)) {
4938 0 : goto err_info_free;
4939 : }
4940 :
4941 40 : goto done;
4942 : }
4943 :
4944 3440 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4945 0 : result = WERR_INVALID_HANDLE;
4946 0 : goto err_info_free;
4947 : }
4948 :
4949 3440 : result = winreg_get_printer_internal(p->mem_ctx,
4950 : get_session_info_system(),
4951 : p->msg_ctx,
4952 : lp_const_servicename(snum),
4953 : &info2);
4954 3440 : if (!W_ERROR_IS_OK(result)) {
4955 0 : goto err_info_free;
4956 : }
4957 :
4958 3440 : switch (r->in.level) {
4959 236 : case 0:
4960 236 : result = construct_printer_info0(p->mem_ctx,
4961 : get_session_info_system(),
4962 : p->msg_ctx,
4963 : info2,
4964 : Printer->servername,
4965 236 : &r->out.info->info0,
4966 : snum);
4967 236 : break;
4968 88 : case 1:
4969 88 : result = construct_printer_info1(p->mem_ctx, info2,
4970 : PRINTER_ENUM_ICON8,
4971 : Printer->servername,
4972 88 : &r->out.info->info1, snum);
4973 88 : break;
4974 932 : case 2:
4975 932 : result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4976 : Printer->servername,
4977 932 : &r->out.info->info2, snum);
4978 932 : break;
4979 144 : case 3:
4980 144 : result = construct_printer_info3(p->mem_ctx, info2,
4981 : Printer->servername,
4982 144 : &r->out.info->info3, snum);
4983 144 : break;
4984 88 : case 4:
4985 88 : result = construct_printer_info4(p->mem_ctx, info2,
4986 : Printer->servername,
4987 88 : &r->out.info->info4, snum);
4988 88 : break;
4989 88 : case 5:
4990 88 : result = construct_printer_info5(p->mem_ctx, info2,
4991 : Printer->servername,
4992 88 : &r->out.info->info5, snum);
4993 88 : break;
4994 88 : case 6:
4995 88 : result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4996 : Printer->servername,
4997 88 : &r->out.info->info6, snum);
4998 88 : break;
4999 112 : case 7:
5000 112 : result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
5001 : Printer->servername,
5002 112 : &r->out.info->info7, snum);
5003 112 : break;
5004 1664 : case 8:
5005 1664 : result = construct_printer_info8(p->mem_ctx, info2,
5006 : Printer->servername,
5007 1664 : &r->out.info->info8, snum);
5008 1664 : break;
5009 0 : default:
5010 0 : result = WERR_INVALID_LEVEL;
5011 0 : break;
5012 : }
5013 3440 : TALLOC_FREE(info2);
5014 :
5015 3440 : if (!W_ERROR_IS_OK(result)) {
5016 0 : DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
5017 : r->in.level, win_errstr(result)));
5018 0 : goto err_info_free;
5019 : }
5020 3440 : done:
5021 3480 : *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
5022 : r->out.info, r->in.level);
5023 3480 : r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5024 :
5025 3480 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5026 :
5027 32 : err_info_free:
5028 32 : TALLOC_FREE(r->out.info);
5029 32 : return result;
5030 : }
5031 :
5032 : /********************************************************************
5033 : ********************************************************************/
5034 :
5035 : #define FILL_DRIVER_STRING(mem_ctx, in, out) \
5036 : do { \
5037 : if (in && strlen(in)) { \
5038 : out = talloc_strdup(mem_ctx, in); \
5039 : } else { \
5040 : out = talloc_strdup(mem_ctx, ""); \
5041 : } \
5042 : W_ERROR_HAVE_NO_MEMORY(out); \
5043 : } while (0);
5044 :
5045 : #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
5046 : do { \
5047 : if (in && strlen(in)) { \
5048 : out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
5049 : } else { \
5050 : out = talloc_strdup(mem_ctx, ""); \
5051 : } \
5052 : W_ERROR_HAVE_NO_MEMORY(out); \
5053 : } while (0);
5054 :
5055 0 : static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
5056 : const char **string_array,
5057 : const char ***presult,
5058 : const char *cservername,
5059 : const char *arch,
5060 : int version)
5061 : {
5062 0 : size_t i;
5063 0 : size_t num_strings = 0;
5064 0 : const char **array = NULL;
5065 :
5066 0 : if (string_array == NULL) {
5067 0 : return WERR_INVALID_PARAMETER;
5068 : }
5069 :
5070 0 : for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
5071 0 : const char *str = NULL;
5072 :
5073 0 : if (cservername == NULL || arch == NULL) {
5074 0 : FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
5075 : } else {
5076 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
5077 : }
5078 :
5079 0 : if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
5080 0 : TALLOC_FREE(array);
5081 0 : return WERR_NOT_ENOUGH_MEMORY;
5082 : }
5083 : }
5084 :
5085 0 : if (i > 0) {
5086 0 : ADD_TO_ARRAY(mem_ctx, const char *, NULL,
5087 : &array, &num_strings);
5088 : }
5089 :
5090 0 : if (presult != NULL) {
5091 0 : *presult = array;
5092 : } else {
5093 0 : talloc_free(array);
5094 : }
5095 :
5096 0 : return WERR_OK;
5097 : }
5098 :
5099 : /********************************************************************
5100 : * fill a spoolss_DriverInfo1 struct
5101 : ********************************************************************/
5102 :
5103 0 : static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
5104 : struct spoolss_DriverInfo1 *r,
5105 : const struct spoolss_DriverInfo8 *driver,
5106 : const char *servername)
5107 : {
5108 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5109 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5110 :
5111 0 : return WERR_OK;
5112 : }
5113 :
5114 : /********************************************************************
5115 : * fill a spoolss_DriverInfo2 struct
5116 : ********************************************************************/
5117 :
5118 0 : static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
5119 : struct spoolss_DriverInfo2 *r,
5120 : const struct spoolss_DriverInfo8 *driver,
5121 : const char *servername)
5122 :
5123 : {
5124 0 : const char *cservername = canon_servername(servername);
5125 :
5126 0 : r->version = driver->version;
5127 :
5128 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5129 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5130 0 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5131 0 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5132 :
5133 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5134 : driver->architecture,
5135 : driver->version,
5136 : driver->driver_path,
5137 0 : r->driver_path);
5138 :
5139 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5140 : driver->architecture,
5141 : driver->version,
5142 : driver->data_file,
5143 0 : r->data_file);
5144 :
5145 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5146 : driver->architecture,
5147 : driver->version,
5148 : driver->config_file,
5149 0 : r->config_file);
5150 :
5151 0 : return WERR_OK;
5152 : }
5153 :
5154 : /********************************************************************
5155 : * fill a spoolss_DriverInfo3 struct
5156 : ********************************************************************/
5157 :
5158 0 : static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
5159 : struct spoolss_DriverInfo3 *r,
5160 : const struct spoolss_DriverInfo8 *driver,
5161 : const char *servername)
5162 : {
5163 0 : const char *cservername = canon_servername(servername);
5164 :
5165 0 : r->version = driver->version;
5166 :
5167 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5168 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5169 0 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5170 0 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5171 :
5172 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5173 : driver->architecture,
5174 : driver->version,
5175 : driver->driver_path,
5176 0 : r->driver_path);
5177 :
5178 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5179 : driver->architecture,
5180 : driver->version,
5181 : driver->data_file,
5182 0 : r->data_file);
5183 :
5184 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5185 : driver->architecture,
5186 : driver->version,
5187 : driver->config_file,
5188 0 : r->config_file);
5189 :
5190 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5191 : driver->architecture,
5192 : driver->version,
5193 : driver->help_file,
5194 0 : r->help_file);
5195 :
5196 0 : FILL_DRIVER_STRING(mem_ctx,
5197 : driver->monitor_name,
5198 0 : r->monitor_name);
5199 :
5200 0 : FILL_DRIVER_STRING(mem_ctx,
5201 : driver->default_datatype,
5202 0 : r->default_datatype);
5203 :
5204 0 : return string_array_from_driver_info(mem_ctx,
5205 0 : driver->dependent_files,
5206 : &r->dependent_files,
5207 : cservername,
5208 0 : driver->architecture,
5209 0 : driver->version);
5210 : }
5211 :
5212 : /********************************************************************
5213 : * fill a spoolss_DriverInfo4 struct
5214 : ********************************************************************/
5215 :
5216 0 : static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5217 : struct spoolss_DriverInfo4 *r,
5218 : const struct spoolss_DriverInfo8 *driver,
5219 : const char *servername)
5220 : {
5221 0 : const char *cservername = canon_servername(servername);
5222 0 : WERROR result;
5223 :
5224 0 : r->version = driver->version;
5225 :
5226 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5227 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5228 0 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5229 0 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5230 :
5231 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5232 : driver->architecture,
5233 : driver->version,
5234 : driver->driver_path,
5235 0 : r->driver_path);
5236 :
5237 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5238 : driver->architecture,
5239 : driver->version,
5240 : driver->data_file,
5241 0 : r->data_file);
5242 :
5243 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5244 : driver->architecture,
5245 : driver->version,
5246 : driver->config_file,
5247 0 : r->config_file);
5248 :
5249 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5250 : driver->architecture,
5251 : driver->version,
5252 : driver->help_file,
5253 0 : r->help_file);
5254 :
5255 0 : result = string_array_from_driver_info(mem_ctx,
5256 0 : driver->dependent_files,
5257 : &r->dependent_files,
5258 : cservername,
5259 0 : driver->architecture,
5260 0 : driver->version);
5261 0 : if (!W_ERROR_IS_OK(result)) {
5262 0 : return result;
5263 : }
5264 :
5265 0 : FILL_DRIVER_STRING(mem_ctx,
5266 : driver->monitor_name,
5267 0 : r->monitor_name);
5268 :
5269 0 : FILL_DRIVER_STRING(mem_ctx,
5270 : driver->default_datatype,
5271 0 : r->default_datatype);
5272 :
5273 :
5274 0 : result = string_array_from_driver_info(mem_ctx,
5275 0 : driver->previous_names,
5276 : &r->previous_names,
5277 : NULL, NULL, 0);
5278 :
5279 0 : return result;
5280 : }
5281 :
5282 : /********************************************************************
5283 : * fill a spoolss_DriverInfo5 struct
5284 : ********************************************************************/
5285 :
5286 0 : static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5287 : struct spoolss_DriverInfo5 *r,
5288 : const struct spoolss_DriverInfo8 *driver,
5289 : const char *servername)
5290 : {
5291 0 : const char *cservername = canon_servername(servername);
5292 :
5293 0 : r->version = driver->version;
5294 :
5295 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5296 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5297 0 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5298 0 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5299 :
5300 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5301 : driver->architecture,
5302 : driver->version,
5303 : driver->driver_path,
5304 0 : r->driver_path);
5305 :
5306 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5307 : driver->architecture,
5308 : driver->version,
5309 : driver->data_file,
5310 0 : r->data_file);
5311 :
5312 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5313 : driver->architecture,
5314 : driver->version,
5315 : driver->config_file,
5316 0 : r->config_file);
5317 :
5318 0 : r->driver_attributes = 0;
5319 0 : r->config_version = 0;
5320 0 : r->driver_version = 0;
5321 :
5322 0 : return WERR_OK;
5323 : }
5324 : /********************************************************************
5325 : * fill a spoolss_DriverInfo6 struct
5326 : ********************************************************************/
5327 :
5328 0 : static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5329 : struct spoolss_DriverInfo6 *r,
5330 : const struct spoolss_DriverInfo8 *driver,
5331 : const char *servername)
5332 : {
5333 0 : const char *cservername = canon_servername(servername);
5334 0 : WERROR result;
5335 :
5336 0 : r->version = driver->version;
5337 :
5338 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5339 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5340 0 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5341 0 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5342 :
5343 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5344 : driver->architecture,
5345 : driver->version,
5346 : driver->driver_path,
5347 0 : r->driver_path);
5348 :
5349 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5350 : driver->architecture,
5351 : driver->version,
5352 : driver->data_file,
5353 0 : r->data_file);
5354 :
5355 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5356 : driver->architecture,
5357 : driver->version,
5358 : driver->config_file,
5359 0 : r->config_file);
5360 :
5361 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5362 : driver->architecture,
5363 : driver->version,
5364 : driver->help_file,
5365 0 : r->help_file);
5366 :
5367 0 : FILL_DRIVER_STRING(mem_ctx,
5368 : driver->monitor_name,
5369 0 : r->monitor_name);
5370 :
5371 0 : FILL_DRIVER_STRING(mem_ctx,
5372 : driver->default_datatype,
5373 0 : r->default_datatype);
5374 :
5375 0 : result = string_array_from_driver_info(mem_ctx,
5376 0 : driver->dependent_files,
5377 : &r->dependent_files,
5378 : cservername,
5379 0 : driver->architecture,
5380 0 : driver->version);
5381 0 : if (!W_ERROR_IS_OK(result)) {
5382 0 : return result;
5383 : }
5384 :
5385 0 : result = string_array_from_driver_info(mem_ctx,
5386 0 : driver->previous_names,
5387 : &r->previous_names,
5388 : NULL, NULL, 0);
5389 0 : if (!W_ERROR_IS_OK(result)) {
5390 0 : return result;
5391 : }
5392 :
5393 0 : r->driver_date = driver->driver_date;
5394 0 : r->driver_version = driver->driver_version;
5395 :
5396 0 : FILL_DRIVER_STRING(mem_ctx,
5397 : driver->manufacturer_name,
5398 0 : r->manufacturer_name);
5399 0 : FILL_DRIVER_STRING(mem_ctx,
5400 : driver->manufacturer_url,
5401 0 : r->manufacturer_url);
5402 0 : FILL_DRIVER_STRING(mem_ctx,
5403 : driver->hardware_id,
5404 0 : r->hardware_id);
5405 0 : FILL_DRIVER_STRING(mem_ctx,
5406 : driver->provider,
5407 0 : r->provider);
5408 :
5409 0 : return WERR_OK;
5410 : }
5411 :
5412 : /********************************************************************
5413 : * fill a spoolss_DriverInfo8 struct
5414 : ********************************************************************/
5415 :
5416 0 : static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5417 : struct spoolss_DriverInfo8 *r,
5418 : const struct spoolss_DriverInfo8 *driver,
5419 : const char *servername)
5420 : {
5421 0 : const char *cservername = canon_servername(servername);
5422 0 : WERROR result;
5423 :
5424 0 : r->version = driver->version;
5425 :
5426 0 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5427 0 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5428 0 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5429 0 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5430 :
5431 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5432 : driver->architecture,
5433 : driver->version,
5434 : driver->driver_path,
5435 0 : r->driver_path);
5436 :
5437 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5438 : driver->architecture,
5439 : driver->version,
5440 : driver->data_file,
5441 0 : r->data_file);
5442 :
5443 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5444 : driver->architecture,
5445 : driver->version,
5446 : driver->config_file,
5447 0 : r->config_file);
5448 :
5449 0 : FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5450 : driver->architecture,
5451 : driver->version,
5452 : driver->help_file,
5453 0 : r->help_file);
5454 :
5455 0 : FILL_DRIVER_STRING(mem_ctx,
5456 : driver->monitor_name,
5457 0 : r->monitor_name);
5458 :
5459 0 : FILL_DRIVER_STRING(mem_ctx,
5460 : driver->default_datatype,
5461 0 : r->default_datatype);
5462 :
5463 0 : result = string_array_from_driver_info(mem_ctx,
5464 0 : driver->dependent_files,
5465 : &r->dependent_files,
5466 : cservername,
5467 0 : driver->architecture,
5468 0 : driver->version);
5469 0 : if (!W_ERROR_IS_OK(result)) {
5470 0 : return result;
5471 : }
5472 :
5473 0 : result = string_array_from_driver_info(mem_ctx,
5474 0 : driver->previous_names,
5475 : &r->previous_names,
5476 : NULL, NULL, 0);
5477 0 : if (!W_ERROR_IS_OK(result)) {
5478 0 : return result;
5479 : }
5480 :
5481 0 : r->driver_date = driver->driver_date;
5482 0 : r->driver_version = driver->driver_version;
5483 :
5484 0 : FILL_DRIVER_STRING(mem_ctx,
5485 : driver->manufacturer_name,
5486 0 : r->manufacturer_name);
5487 0 : FILL_DRIVER_STRING(mem_ctx,
5488 : driver->manufacturer_url,
5489 0 : r->manufacturer_url);
5490 0 : FILL_DRIVER_STRING(mem_ctx,
5491 : driver->hardware_id,
5492 0 : r->hardware_id);
5493 0 : FILL_DRIVER_STRING(mem_ctx,
5494 : driver->provider,
5495 0 : r->provider);
5496 :
5497 0 : FILL_DRIVER_STRING(mem_ctx,
5498 : driver->print_processor,
5499 0 : r->print_processor);
5500 0 : FILL_DRIVER_STRING(mem_ctx,
5501 : driver->vendor_setup,
5502 0 : r->vendor_setup);
5503 :
5504 0 : result = string_array_from_driver_info(mem_ctx,
5505 0 : driver->color_profiles,
5506 : &r->color_profiles,
5507 : NULL, NULL, 0);
5508 0 : if (!W_ERROR_IS_OK(result)) {
5509 0 : return result;
5510 : }
5511 :
5512 0 : FILL_DRIVER_STRING(mem_ctx,
5513 : driver->inf_path,
5514 0 : r->inf_path);
5515 :
5516 0 : r->printer_driver_attributes = driver->printer_driver_attributes;
5517 :
5518 0 : result = string_array_from_driver_info(mem_ctx,
5519 0 : driver->core_driver_dependencies,
5520 : &r->core_driver_dependencies,
5521 : NULL, NULL, 0);
5522 0 : if (!W_ERROR_IS_OK(result)) {
5523 0 : return result;
5524 : }
5525 :
5526 0 : r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5527 0 : r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5528 :
5529 0 : return WERR_OK;
5530 : }
5531 :
5532 : #if 0 /* disabled until marshalling issues are resolved - gd */
5533 : /********************************************************************
5534 : ********************************************************************/
5535 :
5536 : static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5537 : struct spoolss_DriverFileInfo *r,
5538 : const char *cservername,
5539 : const char *file_name,
5540 : enum spoolss_DriverFileType file_type,
5541 : uint32_t file_version)
5542 : {
5543 : r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5544 : cservername, file_name);
5545 : W_ERROR_HAVE_NO_MEMORY(r->file_name);
5546 : r->file_type = file_type;
5547 : r->file_version = file_version;
5548 :
5549 : return WERR_OK;
5550 : }
5551 :
5552 : /********************************************************************
5553 : ********************************************************************/
5554 :
5555 : static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5556 : const struct spoolss_DriverInfo8 *driver,
5557 : const char *cservername,
5558 : struct spoolss_DriverFileInfo **info_p,
5559 : uint32_t *count_p)
5560 : {
5561 : struct spoolss_DriverFileInfo *info = NULL;
5562 : uint32_t count = 0;
5563 : WERROR result;
5564 : uint32_t i;
5565 :
5566 : *info_p = NULL;
5567 : *count_p = 0;
5568 :
5569 : if (strlen(driver->driver_path)) {
5570 : info = talloc_realloc(mem_ctx, info,
5571 : struct spoolss_DriverFileInfo,
5572 : count + 1);
5573 : W_ERROR_HAVE_NO_MEMORY(info);
5574 : result = fill_spoolss_DriverFileInfo(info,
5575 : &info[count],
5576 : cservername,
5577 : driver->driver_path,
5578 : SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5579 : 0);
5580 : W_ERROR_NOT_OK_RETURN(result);
5581 : count++;
5582 : }
5583 :
5584 : if (strlen(driver->config_file)) {
5585 : info = talloc_realloc(mem_ctx, info,
5586 : struct spoolss_DriverFileInfo,
5587 : count + 1);
5588 : W_ERROR_HAVE_NO_MEMORY(info);
5589 : result = fill_spoolss_DriverFileInfo(info,
5590 : &info[count],
5591 : cservername,
5592 : driver->config_file,
5593 : SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5594 : 0);
5595 : W_ERROR_NOT_OK_RETURN(result);
5596 : count++;
5597 : }
5598 :
5599 : if (strlen(driver->data_file)) {
5600 : info = talloc_realloc(mem_ctx, info,
5601 : struct spoolss_DriverFileInfo,
5602 : count + 1);
5603 : W_ERROR_HAVE_NO_MEMORY(info);
5604 : result = fill_spoolss_DriverFileInfo(info,
5605 : &info[count],
5606 : cservername,
5607 : driver->data_file,
5608 : SPOOLSS_DRIVER_FILE_TYPE_DATA,
5609 : 0);
5610 : W_ERROR_NOT_OK_RETURN(result);
5611 : count++;
5612 : }
5613 :
5614 : if (strlen(driver->help_file)) {
5615 : info = talloc_realloc(mem_ctx, info,
5616 : struct spoolss_DriverFileInfo,
5617 : count + 1);
5618 : W_ERROR_HAVE_NO_MEMORY(info);
5619 : result = fill_spoolss_DriverFileInfo(info,
5620 : &info[count],
5621 : cservername,
5622 : driver->help_file,
5623 : SPOOLSS_DRIVER_FILE_TYPE_HELP,
5624 : 0);
5625 : W_ERROR_NOT_OK_RETURN(result);
5626 : count++;
5627 : }
5628 :
5629 : for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5630 : info = talloc_realloc(mem_ctx, info,
5631 : struct spoolss_DriverFileInfo,
5632 : count + 1);
5633 : W_ERROR_HAVE_NO_MEMORY(info);
5634 : result = fill_spoolss_DriverFileInfo(info,
5635 : &info[count],
5636 : cservername,
5637 : driver->dependent_files[i],
5638 : SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5639 : 0);
5640 : W_ERROR_NOT_OK_RETURN(result);
5641 : count++;
5642 : }
5643 :
5644 : *info_p = info;
5645 : *count_p = count;
5646 :
5647 : return WERR_OK;
5648 : }
5649 :
5650 : /********************************************************************
5651 : * fill a spoolss_DriverInfo101 struct
5652 : ********************************************************************/
5653 :
5654 : static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5655 : struct spoolss_DriverInfo101 *r,
5656 : const struct spoolss_DriverInfo8 *driver,
5657 : const char *servername)
5658 : {
5659 : const char *cservername = canon_servername(servername);
5660 : WERROR result;
5661 :
5662 : r->version = driver->version;
5663 :
5664 : r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5665 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5666 : r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5667 : W_ERROR_HAVE_NO_MEMORY(r->architecture);
5668 :
5669 : result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5670 : cservername,
5671 : &r->file_info,
5672 : &r->file_count);
5673 : if (!W_ERROR_IS_OK(result)) {
5674 : return result;
5675 : }
5676 :
5677 : FILL_DRIVER_STRING(mem_ctx,
5678 : driver->monitor_name,
5679 : r->monitor_name);
5680 :
5681 : FILL_DRIVER_STRING(mem_ctx,
5682 : driver->default_datatype,
5683 : r->default_datatype);
5684 :
5685 : result = string_array_from_driver_info(mem_ctx,
5686 : driver->previous_names,
5687 : &r->previous_names,
5688 : NULL, NULL, 0);
5689 : if (!W_ERROR_IS_OK(result)) {
5690 : return result;
5691 : }
5692 :
5693 : r->driver_date = driver->driver_date;
5694 : r->driver_version = driver->driver_version;
5695 :
5696 : FILL_DRIVER_STRING(mem_ctx,
5697 : driver->manufacturer_name,
5698 : r->manufacturer_name);
5699 : FILL_DRIVER_STRING(mem_ctx,
5700 : driver->manufacturer_url,
5701 : r->manufacturer_url);
5702 : FILL_DRIVER_STRING(mem_ctx,
5703 : driver->hardware_id,
5704 : r->hardware_id);
5705 : FILL_DRIVER_STRING(mem_ctx,
5706 : driver->provider,
5707 : r->provider);
5708 :
5709 : return WERR_OK;
5710 : }
5711 : #endif
5712 : /********************************************************************
5713 : ********************************************************************/
5714 :
5715 4 : static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5716 : const struct auth_session_info *session_info,
5717 : struct messaging_context *msg_ctx,
5718 : uint32_t level,
5719 : union spoolss_DriverInfo *r,
5720 : int snum,
5721 : const char *servername,
5722 : const char *architecture,
5723 : uint32_t version)
5724 : {
5725 4 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5726 0 : struct spoolss_DriverInfo8 *driver;
5727 0 : WERROR result;
5728 0 : struct dcerpc_binding_handle *b;
5729 4 : TALLOC_CTX *tmp_ctx = NULL;
5730 :
5731 4 : if (level == 101) {
5732 4 : return WERR_INVALID_LEVEL;
5733 : }
5734 :
5735 0 : tmp_ctx = talloc_new(mem_ctx);
5736 0 : if (!tmp_ctx) {
5737 0 : return WERR_NOT_ENOUGH_MEMORY;
5738 : }
5739 :
5740 0 : result = winreg_printer_binding_handle(tmp_ctx,
5741 : session_info,
5742 : msg_ctx,
5743 : &b);
5744 0 : if (!W_ERROR_IS_OK(result)) {
5745 0 : goto done;
5746 : }
5747 :
5748 0 : result = winreg_get_printer(tmp_ctx, b,
5749 : lp_const_servicename(snum),
5750 : &pinfo2);
5751 0 : if (!W_ERROR_IS_OK(result)) {
5752 0 : DBG_ERR("Failed to get printer info2 for [%s]: %s\n",
5753 : lp_const_servicename(snum), win_errstr(result));
5754 0 : result = WERR_INVALID_PRINTER_NAME;
5755 0 : goto done;
5756 : }
5757 :
5758 0 : if (pinfo2->drivername == NULL || pinfo2->drivername[0] == '\0') {
5759 0 : result = WERR_UNKNOWN_PRINTER_DRIVER;
5760 0 : goto done;
5761 : }
5762 :
5763 0 : DBG_INFO("Construct printer driver [%s] for [%s]\n",
5764 : pinfo2->drivername,
5765 : pinfo2->sharename);
5766 :
5767 0 : result = winreg_get_driver(tmp_ctx, b,
5768 : architecture,
5769 0 : pinfo2->drivername, version, &driver);
5770 :
5771 0 : DBG_INFO("winreg_get_driver() status: %s\n",
5772 : win_errstr(result));
5773 :
5774 0 : if (!W_ERROR_IS_OK(result)) {
5775 : /*
5776 : * Is this a W2k client ?
5777 : */
5778 :
5779 0 : if (version < 3) {
5780 0 : result = WERR_UNKNOWN_PRINTER_DRIVER;
5781 0 : goto done;
5782 : }
5783 :
5784 : /* Yes - try again with a WinNT driver. */
5785 0 : version = 2;
5786 0 : result = winreg_get_driver(tmp_ctx, b,
5787 : architecture,
5788 0 : pinfo2->drivername,
5789 : version, &driver);
5790 0 : DEBUG(8,("construct_printer_driver_level: status: %s\n",
5791 : win_errstr(result)));
5792 0 : if (!W_ERROR_IS_OK(result)) {
5793 0 : result = WERR_UNKNOWN_PRINTER_DRIVER;
5794 0 : goto done;
5795 : }
5796 : }
5797 :
5798 : /* these are allocated on mem_ctx and not tmp_ctx because they are
5799 : * the 'return value' and need to outlive this call */
5800 0 : switch (level) {
5801 0 : case 1:
5802 0 : result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5803 0 : break;
5804 0 : case 2:
5805 0 : result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5806 0 : break;
5807 0 : case 3:
5808 0 : result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5809 0 : break;
5810 0 : case 4:
5811 0 : result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5812 0 : break;
5813 0 : case 5:
5814 0 : result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5815 0 : break;
5816 0 : case 6:
5817 0 : result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5818 0 : break;
5819 0 : case 8:
5820 0 : result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5821 0 : break;
5822 : #if 0 /* disabled until marshalling issues are resolved - gd */
5823 : case 101:
5824 : result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5825 : break;
5826 : #endif
5827 0 : default:
5828 0 : result = WERR_INVALID_LEVEL;
5829 0 : break;
5830 : }
5831 :
5832 0 : done:
5833 0 : talloc_free(tmp_ctx);
5834 0 : return result;
5835 : }
5836 :
5837 : /****************************************************************
5838 : _spoolss_GetPrinterDriver2
5839 : ****************************************************************/
5840 :
5841 4 : WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5842 : struct spoolss_GetPrinterDriver2 *r)
5843 : {
5844 0 : struct printer_handle *printer;
5845 0 : WERROR result;
5846 4 : uint32_t version = r->in.client_major_version;
5847 :
5848 0 : int snum;
5849 :
5850 : /* that's an [in out] buffer */
5851 :
5852 4 : if (!r->in.buffer && (r->in.offered != 0)) {
5853 0 : result = WERR_INVALID_PARAMETER;
5854 0 : goto err_info_free;
5855 : }
5856 :
5857 4 : DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5858 :
5859 4 : if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5860 0 : DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5861 0 : result = WERR_INVALID_PRINTER_NAME;
5862 0 : goto err_info_free;
5863 : }
5864 :
5865 4 : *r->out.needed = 0;
5866 4 : *r->out.server_major_version = 0;
5867 4 : *r->out.server_minor_version = 0;
5868 :
5869 4 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5870 0 : result = WERR_INVALID_HANDLE;
5871 0 : goto err_info_free;
5872 : }
5873 :
5874 4 : if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
5875 0 : DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
5876 : "downgrading to v3\n"));
5877 0 : version = SPOOLSS_DRIVER_VERSION_200X;
5878 : }
5879 :
5880 4 : result = construct_printer_driver_info_level(p->mem_ctx,
5881 : get_session_info_system(),
5882 : p->msg_ctx,
5883 : r->in.level, r->out.info,
5884 : snum, printer->servername,
5885 : r->in.architecture,
5886 : version);
5887 4 : if (!W_ERROR_IS_OK(result)) {
5888 4 : goto err_info_free;
5889 : }
5890 :
5891 0 : *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5892 : r->out.info, r->in.level);
5893 0 : r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5894 :
5895 0 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5896 :
5897 4 : err_info_free:
5898 4 : TALLOC_FREE(r->out.info);
5899 4 : return result;
5900 : }
5901 :
5902 :
5903 : /****************************************************************
5904 : _spoolss_StartPagePrinter
5905 : ****************************************************************/
5906 :
5907 1920 : WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5908 : struct spoolss_StartPagePrinter *r)
5909 : {
5910 1920 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5911 :
5912 1920 : if (!Printer) {
5913 0 : DEBUG(3,("_spoolss_StartPagePrinter: "
5914 : "Error in startpageprinter printer handle\n"));
5915 0 : return WERR_INVALID_HANDLE;
5916 : }
5917 :
5918 1920 : Printer->page_started = true;
5919 1920 : return WERR_OK;
5920 : }
5921 :
5922 : /****************************************************************
5923 : _spoolss_EndPagePrinter
5924 : ****************************************************************/
5925 :
5926 1920 : WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5927 : struct spoolss_EndPagePrinter *r)
5928 : {
5929 0 : int snum;
5930 :
5931 1920 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5932 :
5933 1920 : if (!Printer) {
5934 0 : DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5935 : OUR_HANDLE(r->in.handle)));
5936 0 : return WERR_INVALID_HANDLE;
5937 : }
5938 :
5939 1920 : if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5940 0 : return WERR_INVALID_HANDLE;
5941 :
5942 1920 : Printer->page_started = false;
5943 1920 : print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5944 :
5945 1920 : return WERR_OK;
5946 : }
5947 :
5948 : /****************************************************************
5949 : _spoolss_StartDocPrinter
5950 : ****************************************************************/
5951 :
5952 668 : WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5953 : struct spoolss_StartDocPrinter *r)
5954 : {
5955 668 : struct dcesrv_call_state *dce_call = p->dce_call;
5956 668 : struct dcesrv_connection *dcesrv_conn = dce_call->conn;
5957 0 : const struct tsocket_address *remote_address =
5958 668 : dcesrv_connection_get_remote_address(dcesrv_conn);
5959 0 : struct auth_session_info *session_info =
5960 668 : dcesrv_call_session_info(dce_call);
5961 0 : struct spoolss_DocumentInfo1 *info_1;
5962 0 : int snum;
5963 668 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5964 0 : WERROR werr;
5965 0 : char *rhost;
5966 0 : int rc;
5967 :
5968 668 : if (!Printer) {
5969 0 : DEBUG(2,("_spoolss_StartDocPrinter: "
5970 : "Invalid handle (%s:%u:%u)\n",
5971 : OUR_HANDLE(r->in.handle)));
5972 0 : return WERR_INVALID_HANDLE;
5973 : }
5974 :
5975 668 : if (Printer->jobid) {
5976 0 : DEBUG(2, ("_spoolss_StartDocPrinter: "
5977 : "StartDocPrinter called twice! "
5978 : "(existing jobid = %d)\n", Printer->jobid));
5979 0 : return WERR_INVALID_HANDLE;
5980 : }
5981 :
5982 668 : if (r->in.info_ctr->level != 1) {
5983 0 : return WERR_INVALID_LEVEL;
5984 : }
5985 :
5986 668 : info_1 = r->in.info_ctr->info.info1;
5987 :
5988 : /*
5989 : * a nice thing with NT is it doesn't listen to what you tell it.
5990 : * when asked to send _only_ RAW data, it tries to send data
5991 : * in EMF format.
5992 : *
5993 : * So I add checks like in NT Server ...
5994 : */
5995 :
5996 668 : if (info_1->datatype) {
5997 : /*
5998 : * The v4 driver model used in Windows 8 declares print jobs
5999 : * intended to bypass the XPS processing layer by setting
6000 : * datatype to "XPS_PASS" instead of "RAW".
6001 : */
6002 668 : if ((strcmp(info_1->datatype, "RAW") != 0)
6003 224 : && (strcmp(info_1->datatype, "XPS_PASS") != 0)) {
6004 0 : *r->out.job_id = 0;
6005 0 : return WERR_INVALID_DATATYPE;
6006 : }
6007 : }
6008 :
6009 : /* get the share number of the printer */
6010 668 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6011 0 : return WERR_INVALID_HANDLE;
6012 : }
6013 :
6014 668 : rc = get_remote_hostname(remote_address,
6015 : &rhost,
6016 : p->mem_ctx);
6017 668 : if (rc < 0) {
6018 0 : return WERR_NOT_ENOUGH_MEMORY;
6019 : }
6020 668 : if (strequal(rhost,"UNKNOWN")) {
6021 668 : rhost = tsocket_address_inet_addr_string(remote_address,
6022 : p->mem_ctx);
6023 668 : if (rhost == NULL) {
6024 0 : return WERR_NOT_ENOUGH_MEMORY;
6025 : }
6026 : }
6027 :
6028 668 : werr = print_job_start(session_info,
6029 : p->msg_ctx,
6030 : rhost,
6031 : snum,
6032 : info_1->document_name,
6033 : info_1->output_file,
6034 : Printer->devmode,
6035 : &Printer->jobid);
6036 :
6037 : /* An error occurred in print_job_start() so return an appropriate
6038 : NT error code. */
6039 :
6040 668 : if (!W_ERROR_IS_OK(werr)) {
6041 0 : return werr;
6042 : }
6043 :
6044 668 : Printer->document_started = true;
6045 668 : *r->out.job_id = Printer->jobid;
6046 :
6047 668 : return WERR_OK;
6048 : }
6049 :
6050 : /****************************************************************
6051 : _spoolss_EndDocPrinter
6052 : ****************************************************************/
6053 :
6054 668 : WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
6055 : struct spoolss_EndDocPrinter *r)
6056 : {
6057 668 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6058 0 : NTSTATUS status;
6059 0 : int snum;
6060 :
6061 668 : if (!Printer) {
6062 0 : DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
6063 : OUR_HANDLE(r->in.handle)));
6064 0 : return WERR_INVALID_HANDLE;
6065 : }
6066 :
6067 668 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6068 0 : return WERR_INVALID_HANDLE;
6069 : }
6070 :
6071 668 : Printer->document_started = false;
6072 668 : status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
6073 668 : if (!NT_STATUS_IS_OK(status)) {
6074 292 : DEBUG(2, ("_spoolss_EndDocPrinter: "
6075 : "print_job_end failed [%s]\n",
6076 : nt_errstr(status)));
6077 : }
6078 :
6079 668 : Printer->jobid = 0;
6080 668 : return ntstatus_to_werror(status);
6081 : }
6082 :
6083 : /****************************************************************
6084 : _spoolss_WritePrinter
6085 : ****************************************************************/
6086 :
6087 1920 : WERROR _spoolss_WritePrinter(struct pipes_struct *p,
6088 : struct spoolss_WritePrinter *r)
6089 : {
6090 0 : ssize_t buffer_written;
6091 0 : int snum;
6092 1920 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6093 :
6094 1920 : if (!Printer) {
6095 0 : DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
6096 : OUR_HANDLE(r->in.handle)));
6097 0 : *r->out.num_written = r->in._data_size;
6098 0 : return WERR_INVALID_HANDLE;
6099 : }
6100 :
6101 1920 : if (!get_printer_snum(p, r->in.handle, &snum, NULL))
6102 0 : return WERR_INVALID_HANDLE;
6103 :
6104 : /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
6105 1920 : buffer_written = print_job_write(global_event_context(),p->msg_ctx,
6106 : snum, Printer->jobid,
6107 1920 : (const char *)r->in.data.data,
6108 1920 : (size_t)r->in._data_size);
6109 1920 : if (buffer_written == (ssize_t)-1) {
6110 0 : *r->out.num_written = 0;
6111 0 : if (errno == ENOSPC)
6112 0 : return WERR_NO_SPOOL_SPACE;
6113 : else
6114 0 : return WERR_ACCESS_DENIED;
6115 : }
6116 :
6117 1920 : *r->out.num_written = r->in._data_size;
6118 :
6119 1920 : return WERR_OK;
6120 : }
6121 :
6122 : /********************************************************************
6123 : * api_spoolss_getprinter
6124 : * called from the spoolss dispatcher
6125 : *
6126 : ********************************************************************/
6127 :
6128 104 : static WERROR control_printer(struct policy_handle *handle, uint32_t command,
6129 : struct pipes_struct *p)
6130 : {
6131 104 : struct dcesrv_call_state *dce_call = p->dce_call;
6132 0 : struct auth_session_info *session_info =
6133 104 : dcesrv_call_session_info(dce_call);
6134 0 : int snum;
6135 104 : WERROR errcode = WERR_INVALID_FUNCTION;
6136 104 : struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6137 :
6138 104 : if (!Printer) {
6139 0 : DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
6140 : OUR_HANDLE(handle)));
6141 0 : return WERR_INVALID_HANDLE;
6142 : }
6143 :
6144 104 : if (!get_printer_snum(p, handle, &snum, NULL))
6145 0 : return WERR_INVALID_HANDLE;
6146 :
6147 104 : switch (command) {
6148 52 : case SPOOLSS_PRINTER_CONTROL_PAUSE:
6149 52 : errcode = print_queue_pause(session_info, p->msg_ctx, snum);
6150 52 : break;
6151 40 : case SPOOLSS_PRINTER_CONTROL_RESUME:
6152 : case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
6153 40 : errcode = print_queue_resume(session_info, p->msg_ctx, snum);
6154 40 : break;
6155 12 : case SPOOLSS_PRINTER_CONTROL_PURGE:
6156 12 : errcode = print_queue_purge(session_info, p->msg_ctx, snum);
6157 12 : break;
6158 0 : default:
6159 0 : return WERR_INVALID_LEVEL;
6160 : }
6161 :
6162 104 : return errcode;
6163 : }
6164 :
6165 :
6166 : /****************************************************************
6167 : _spoolss_AbortPrinter
6168 : * From MSDN: "Deletes printer's spool file if printer is configured
6169 : * for spooling"
6170 : ****************************************************************/
6171 :
6172 0 : WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
6173 : struct spoolss_AbortPrinter *r)
6174 : {
6175 0 : struct dcesrv_call_state *dce_call = p->dce_call;
6176 0 : struct auth_session_info *session_info =
6177 0 : dcesrv_call_session_info(dce_call);
6178 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6179 0 : int snum;
6180 0 : WERROR errcode = WERR_OK;
6181 :
6182 0 : if (!Printer) {
6183 0 : DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
6184 : OUR_HANDLE(r->in.handle)));
6185 0 : return WERR_INVALID_HANDLE;
6186 : }
6187 :
6188 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL))
6189 0 : return WERR_INVALID_HANDLE;
6190 :
6191 0 : if (!Printer->document_started) {
6192 0 : return WERR_SPL_NO_STARTDOC;
6193 : }
6194 :
6195 0 : errcode = print_job_delete(session_info,
6196 : p->msg_ctx,
6197 : snum,
6198 : Printer->jobid);
6199 :
6200 0 : return errcode;
6201 : }
6202 :
6203 : /********************************************************************
6204 : * called by spoolss_api_setprinter
6205 : * when updating a printer description
6206 : ********************************************************************/
6207 :
6208 120 : static WERROR update_printer_sec(struct policy_handle *handle,
6209 : struct pipes_struct *p,
6210 : struct sec_desc_buf *secdesc_ctr)
6211 : {
6212 120 : struct spoolss_security_descriptor *new_secdesc = NULL;
6213 120 : struct spoolss_security_descriptor *old_secdesc = NULL;
6214 120 : const char *printer = NULL;
6215 0 : WERROR result;
6216 120 : int snum = -1;
6217 120 : struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6218 0 : struct dcerpc_binding_handle *b;
6219 120 : TALLOC_CTX *tmp_ctx = NULL;
6220 120 : bool ok = false;
6221 :
6222 120 : if (!Printer) {
6223 0 : DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6224 : OUR_HANDLE(handle)));
6225 :
6226 0 : result = WERR_INVALID_HANDLE;
6227 0 : goto done;
6228 : }
6229 :
6230 120 : if (secdesc_ctr == NULL) {
6231 0 : DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6232 0 : result = WERR_INVALID_PARAMETER;
6233 0 : goto done;
6234 : }
6235 :
6236 120 : switch (Printer->printer_type) {
6237 8 : case SPLHND_SERVER:
6238 8 : break;
6239 112 : case SPLHND_PRINTER:
6240 112 : if (!get_printer_snum(p, handle, &snum, NULL)) {
6241 0 : DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6242 : OUR_HANDLE(handle)));
6243 0 : result = WERR_INVALID_HANDLE;
6244 0 : goto done;
6245 : }
6246 112 : printer = lp_const_servicename(snum);
6247 112 : break;
6248 0 : default:
6249 0 : break;
6250 : }
6251 :
6252 : /* Check the user has permissions to change the security
6253 : descriptor. By experimentation with two NT machines, the user
6254 : requires Full Access to the printer to change security
6255 : information. */
6256 :
6257 120 : switch (Printer->printer_type) {
6258 8 : case SPLHND_SERVER:
6259 8 : ok = Printer->access_granted == SERVER_ACCESS_ADMINISTER;
6260 8 : break;
6261 112 : case SPLHND_PRINTER:
6262 112 : ok = Printer->access_granted == PRINTER_ACCESS_ADMINISTER;
6263 112 : break;
6264 0 : default:
6265 0 : break;
6266 : }
6267 :
6268 120 : if (!ok) {
6269 0 : DEBUG(4,("update_printer_sec: updated denied by printer permissions "
6270 : "(access_granted: 0x%08x)\n", Printer->access_granted));
6271 0 : result = WERR_ACCESS_DENIED;
6272 0 : goto done;
6273 : }
6274 :
6275 120 : tmp_ctx = talloc_new(p->mem_ctx);
6276 120 : if (!tmp_ctx) {
6277 0 : return WERR_NOT_ENOUGH_MEMORY;
6278 : }
6279 :
6280 120 : result = winreg_printer_binding_handle(tmp_ctx,
6281 : get_session_info_system(),
6282 : p->msg_ctx,
6283 : &b);
6284 120 : if (!W_ERROR_IS_OK(result)) {
6285 0 : goto done;
6286 : }
6287 :
6288 : /* NT seems to like setting the security descriptor even though
6289 : nothing may have actually changed. */
6290 :
6291 120 : if (printer != NULL) {
6292 112 : result = winreg_get_printer_secdesc(tmp_ctx, b,
6293 : printer,
6294 : &old_secdesc);
6295 : } else {
6296 8 : result = winreg_get_printserver_secdesc(tmp_ctx, b,
6297 : &old_secdesc);
6298 : }
6299 120 : if (!W_ERROR_IS_OK(result)) {
6300 0 : DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6301 0 : result = WERR_INVALID_HANDLE;
6302 0 : goto done;
6303 : }
6304 :
6305 120 : if (DEBUGLEVEL >= 10) {
6306 0 : struct dom_sid_buf buf;
6307 0 : struct security_acl *the_acl;
6308 0 : int i;
6309 :
6310 0 : the_acl = old_secdesc->dacl;
6311 0 : DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6312 : printer, the_acl->num_aces));
6313 :
6314 0 : for (i = 0; i < the_acl->num_aces; i++) {
6315 0 : DEBUG(10, ("%s 0x%08x\n",
6316 : dom_sid_str_buf(
6317 : &the_acl->aces[i].trustee,
6318 : &buf),
6319 : the_acl->aces[i].access_mask));
6320 : }
6321 :
6322 0 : the_acl = secdesc_ctr->sd->dacl;
6323 :
6324 0 : if (the_acl) {
6325 0 : DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6326 : printer, the_acl->num_aces));
6327 :
6328 0 : for (i = 0; i < the_acl->num_aces; i++) {
6329 0 : DEBUG(10, ("%s 0x%08x\n",
6330 : dom_sid_str_buf(
6331 : &the_acl->aces[i].trustee,
6332 : &buf),
6333 : the_acl->aces[i].access_mask));
6334 : }
6335 : } else {
6336 0 : DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6337 : }
6338 : }
6339 :
6340 120 : new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6341 120 : if (new_secdesc == NULL) {
6342 0 : result = WERR_NOT_ENOUGH_MEMORY;
6343 0 : goto done;
6344 : }
6345 :
6346 120 : if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6347 56 : result = WERR_OK;
6348 56 : goto done;
6349 : }
6350 :
6351 64 : if (printer != NULL) {
6352 56 : result = winreg_set_printer_secdesc(tmp_ctx, b,
6353 : printer,
6354 : new_secdesc);
6355 : } else {
6356 8 : result = winreg_set_printserver_secdesc(tmp_ctx, b,
6357 : new_secdesc);
6358 : }
6359 :
6360 120 : done:
6361 120 : talloc_free(tmp_ctx);
6362 120 : return result;
6363 : }
6364 :
6365 : /********************************************************************
6366 : Canonicalize printer info from a client
6367 : ********************************************************************/
6368 :
6369 100 : static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6370 : struct spoolss_SetPrinterInfo2 *info2,
6371 : int snum)
6372 : {
6373 0 : fstring printername;
6374 0 : const char *p;
6375 :
6376 100 : DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6377 : "portname=%s drivername=%s comment=%s location=%s\n",
6378 : info2->servername, info2->printername, info2->sharename,
6379 : info2->portname, info2->drivername, info2->comment,
6380 : info2->location));
6381 :
6382 : /* we force some elements to "correct" values */
6383 100 : info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6384 100 : if (info2->servername == NULL) {
6385 0 : return false;
6386 : }
6387 100 : info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6388 100 : if (info2->sharename == NULL) {
6389 0 : return false;
6390 : }
6391 :
6392 : /* check to see if we allow printername != sharename */
6393 100 : if (lp_force_printername(snum)) {
6394 0 : info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6395 : lp_netbios_name(), info2->sharename);
6396 : } else {
6397 : /* make sure printername is in \\server\printername format */
6398 100 : fstrcpy(printername, info2->printername);
6399 100 : p = printername;
6400 100 : if ( printername[0] == '\\' && printername[1] == '\\' ) {
6401 56 : if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6402 56 : p++;
6403 : }
6404 :
6405 100 : info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6406 : lp_netbios_name(), p);
6407 : }
6408 100 : if (info2->printername == NULL) {
6409 0 : return false;
6410 : }
6411 :
6412 100 : info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6413 100 : info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6414 :
6415 100 : return true;
6416 : }
6417 :
6418 : /****************************************************************************
6419 : ****************************************************************************/
6420 :
6421 0 : static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6422 : {
6423 0 : const struct loadparm_substitution *lp_sub =
6424 0 : loadparm_s3_global_substitution();
6425 0 : char *cmd = lp_addport_command(talloc_tos(), lp_sub);
6426 0 : char *command = NULL;
6427 0 : int ret;
6428 0 : bool is_print_op = false;
6429 :
6430 0 : if ( !*cmd ) {
6431 0 : return WERR_ACCESS_DENIED;
6432 : }
6433 :
6434 0 : command = talloc_asprintf(ctx,
6435 : "%s \"%s\" \"%s\"", cmd, portname, uri );
6436 0 : if (!command) {
6437 0 : return WERR_NOT_ENOUGH_MEMORY;
6438 : }
6439 :
6440 0 : if ( token )
6441 0 : is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6442 :
6443 0 : DEBUG(10,("Running [%s]\n", command));
6444 :
6445 : /********* BEGIN SePrintOperatorPrivilege **********/
6446 :
6447 0 : if ( is_print_op )
6448 0 : become_root();
6449 :
6450 0 : ret = smbrun(command, NULL, NULL);
6451 :
6452 0 : if ( is_print_op )
6453 0 : unbecome_root();
6454 :
6455 : /********* END SePrintOperatorPrivilege **********/
6456 :
6457 0 : DEBUGADD(10,("returned [%d]\n", ret));
6458 :
6459 0 : TALLOC_FREE(command);
6460 :
6461 0 : if ( ret != 0 ) {
6462 0 : return WERR_ACCESS_DENIED;
6463 : }
6464 :
6465 0 : return WERR_OK;
6466 : }
6467 :
6468 : /****************************************************************************
6469 : ****************************************************************************/
6470 :
6471 4902 : static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6472 : int snum)
6473 : {
6474 : /*
6475 : * As we do not know if we are embedded in the file server process
6476 : * or not, we have to pretend that all shares are in use.
6477 : */
6478 4902 : return true;
6479 : }
6480 :
6481 66 : static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6482 : struct spoolss_SetPrinterInfo2 *info2,
6483 : const char *remote_machine,
6484 : struct messaging_context *msg_ctx)
6485 : {
6486 0 : const struct loadparm_substitution *lp_sub =
6487 66 : loadparm_s3_global_substitution();
6488 66 : char *cmd = lp_addprinter_command(talloc_tos(), lp_sub);
6489 0 : char **qlines;
6490 66 : char *command = NULL;
6491 0 : int numlines;
6492 0 : int ret;
6493 0 : int fd;
6494 66 : bool is_print_op = false;
6495 :
6496 66 : if (!remote_machine) {
6497 0 : return false;
6498 : }
6499 :
6500 66 : command = talloc_asprintf(ctx,
6501 : "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6502 : cmd, info2->printername, info2->sharename,
6503 : info2->portname, info2->drivername,
6504 : info2->location, info2->comment, remote_machine);
6505 66 : if (!command) {
6506 0 : return false;
6507 : }
6508 :
6509 66 : if ( token )
6510 66 : is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6511 :
6512 66 : DEBUG(10,("Running [%s]\n", command));
6513 :
6514 : /********* BEGIN SePrintOperatorPrivilege **********/
6515 :
6516 66 : if ( is_print_op )
6517 0 : become_root();
6518 :
6519 66 : ret = smbrun(command, &fd, NULL);
6520 66 : if (ret == 0) {
6521 : /* Tell everyone we updated smb.conf. */
6522 66 : messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
6523 : }
6524 :
6525 66 : if ( is_print_op )
6526 0 : unbecome_root();
6527 :
6528 : /********* END SePrintOperatorPrivilege **********/
6529 :
6530 66 : DEBUGADD(10,("returned [%d]\n", ret));
6531 :
6532 66 : TALLOC_FREE(command);
6533 :
6534 66 : if ( ret != 0 ) {
6535 0 : if (fd != -1)
6536 0 : close(fd);
6537 0 : return false;
6538 : }
6539 :
6540 : /* reload our services immediately */
6541 66 : become_root();
6542 66 : reload_services(NULL, spoolss_conn_snum_used, false);
6543 66 : unbecome_root();
6544 :
6545 66 : numlines = 0;
6546 : /* Get lines and convert them back to dos-codepage */
6547 66 : qlines = fd_lines_load(fd, &numlines, 0, NULL);
6548 66 : DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6549 66 : close(fd);
6550 :
6551 : /* Set the portname to what the script says the portname should be. */
6552 : /* but don't require anything to be return from the script exit a good error code */
6553 :
6554 66 : if (numlines) {
6555 : /* Set the portname to what the script says the portname should be. */
6556 0 : info2->portname = talloc_strdup(ctx, qlines[0]);
6557 0 : DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6558 : }
6559 :
6560 66 : TALLOC_FREE(qlines);
6561 66 : return true;
6562 : }
6563 :
6564 100 : static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6565 : const struct auth_session_info *session_info,
6566 : struct messaging_context *msg_ctx,
6567 : int snum,
6568 : struct spoolss_SetPrinterInfo2 *printer,
6569 : struct spoolss_PrinterInfo2 *old_printer)
6570 : {
6571 100 : bool force_update = (old_printer == NULL);
6572 0 : const char *dnsdomname;
6573 0 : const char *longname;
6574 0 : const char *uncname;
6575 0 : const char *spooling;
6576 0 : DATA_BLOB buffer;
6577 100 : WERROR result = WERR_OK;
6578 0 : struct dcerpc_binding_handle *b;
6579 0 : TALLOC_CTX *tmp_ctx;
6580 0 : bool ok;
6581 :
6582 100 : tmp_ctx = talloc_new(mem_ctx);
6583 100 : if (!tmp_ctx) {
6584 0 : return WERR_NOT_ENOUGH_MEMORY;
6585 : }
6586 :
6587 100 : result = winreg_printer_binding_handle(tmp_ctx,
6588 : session_info,
6589 : msg_ctx,
6590 : &b);
6591 100 : if (!W_ERROR_IS_OK(result)) {
6592 0 : goto done;
6593 : }
6594 :
6595 100 : if (printer->drivername != NULL &&
6596 84 : (force_update ||
6597 84 : !strequal(printer->drivername, old_printer->drivername))) {
6598 24 : ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6599 24 : if (!ok) {
6600 0 : DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6601 0 : result = WERR_INVALID_DATA;
6602 0 : goto done;
6603 : }
6604 24 : result = winreg_set_printer_dataex(tmp_ctx, b,
6605 : printer->sharename,
6606 : SPOOL_DSSPOOLER_KEY,
6607 : SPOOL_REG_DRIVERNAME,
6608 : REG_SZ,
6609 : buffer.data,
6610 24 : buffer.length);
6611 24 : if (!W_ERROR_IS_OK(result)) {
6612 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6613 0 : goto done;
6614 : }
6615 :
6616 24 : if (!force_update) {
6617 8 : DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6618 : printer->drivername));
6619 :
6620 8 : notify_printer_driver(global_event_context(), msg_ctx,
6621 8 : snum, printer->drivername ?
6622 : printer->drivername : "");
6623 : }
6624 : }
6625 :
6626 100 : if (printer->comment != NULL &&
6627 84 : (force_update ||
6628 84 : !strequal(printer->comment, old_printer->comment))) {
6629 34 : ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6630 34 : if (!ok) {
6631 0 : DEBUG(0, ("comment data corrupted\n"));
6632 0 : result = WERR_INVALID_DATA;
6633 0 : goto done;
6634 : }
6635 34 : result = winreg_set_printer_dataex(tmp_ctx, b,
6636 : printer->sharename,
6637 : SPOOL_DSSPOOLER_KEY,
6638 : SPOOL_REG_DESCRIPTION,
6639 : REG_SZ,
6640 : buffer.data,
6641 34 : buffer.length);
6642 34 : if (!W_ERROR_IS_OK(result)) {
6643 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6644 0 : goto done;
6645 : }
6646 :
6647 34 : if (!force_update) {
6648 34 : notify_printer_comment(global_event_context(), msg_ctx,
6649 34 : snum, printer->comment ?
6650 : printer->comment : "");
6651 : }
6652 : }
6653 :
6654 100 : if (printer->sharename != NULL &&
6655 84 : (force_update ||
6656 84 : !strequal(printer->sharename, old_printer->sharename))) {
6657 16 : ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6658 16 : if (!ok) {
6659 0 : DEBUG(0, ("sharename data corrupted\n"));
6660 0 : result = WERR_INVALID_DATA;
6661 0 : goto done;
6662 : }
6663 16 : result = winreg_set_printer_dataex(tmp_ctx, b,
6664 : printer->sharename,
6665 : SPOOL_DSSPOOLER_KEY,
6666 : SPOOL_REG_PRINTSHARENAME,
6667 : REG_SZ,
6668 : buffer.data,
6669 16 : buffer.length);
6670 16 : if (!W_ERROR_IS_OK(result)) {
6671 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6672 0 : goto done;
6673 : }
6674 :
6675 16 : if (!force_update) {
6676 0 : notify_printer_sharename(global_event_context(),
6677 : msg_ctx,
6678 0 : snum, printer->sharename ?
6679 : printer->sharename : "");
6680 : }
6681 :
6682 : /* name change, purge any cache entries for the old */
6683 16 : prune_printername_cache();
6684 : }
6685 :
6686 100 : if (printer->printername != NULL &&
6687 84 : (force_update ||
6688 84 : !strequal(printer->printername, old_printer->printername))) {
6689 0 : const char *p;
6690 :
6691 100 : p = strrchr(printer->printername, '\\' );
6692 100 : if (p != NULL) {
6693 100 : p++;
6694 : } else {
6695 0 : p = printer->printername;
6696 : }
6697 :
6698 100 : ok = push_reg_sz(tmp_ctx, &buffer, p);
6699 100 : if (!ok) {
6700 0 : DEBUG(0, ("printername data corrupted\n"));
6701 0 : result = WERR_INVALID_DATA;
6702 0 : goto done;
6703 : }
6704 100 : result = winreg_set_printer_dataex(tmp_ctx, b,
6705 : printer->sharename,
6706 : SPOOL_DSSPOOLER_KEY,
6707 : SPOOL_REG_PRINTERNAME,
6708 : REG_SZ,
6709 : buffer.data,
6710 100 : buffer.length);
6711 100 : if (!W_ERROR_IS_OK(result)) {
6712 0 : DBG_ERR("Failed to set %s\n", SPOOL_REG_PRINTERNAME);
6713 0 : goto done;
6714 : }
6715 :
6716 100 : if (!force_update) {
6717 84 : notify_printer_printername(global_event_context(),
6718 : msg_ctx, snum, p ? p : "");
6719 : }
6720 :
6721 : /* name change, purge any cache entries for the old */
6722 100 : prune_printername_cache();
6723 : }
6724 :
6725 100 : if (printer->portname != NULL &&
6726 84 : (force_update ||
6727 84 : !strequal(printer->portname, old_printer->portname))) {
6728 16 : ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6729 16 : if (!ok) {
6730 0 : DEBUG(0, ("portname data corrupted\n"));
6731 0 : result = WERR_INVALID_DATA;
6732 0 : goto done;
6733 : }
6734 16 : result = winreg_set_printer_dataex(tmp_ctx, b,
6735 : printer->sharename,
6736 : SPOOL_DSSPOOLER_KEY,
6737 : SPOOL_REG_PORTNAME,
6738 : REG_SZ,
6739 : buffer.data,
6740 16 : buffer.length);
6741 16 : if (!W_ERROR_IS_OK(result)) {
6742 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6743 0 : goto done;
6744 : }
6745 :
6746 16 : if (!force_update) {
6747 0 : notify_printer_port(global_event_context(),
6748 0 : msg_ctx, snum, printer->portname ?
6749 : printer->portname : "");
6750 : }
6751 : }
6752 :
6753 100 : if (printer->location != NULL &&
6754 84 : (force_update ||
6755 84 : !strequal(printer->location, old_printer->location))) {
6756 8 : ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6757 8 : if (!ok) {
6758 0 : DEBUG(0, ("location data corrupted\n"));
6759 0 : result = WERR_INVALID_DATA;
6760 0 : goto done;
6761 : }
6762 8 : result = winreg_set_printer_dataex(tmp_ctx, b,
6763 : printer->sharename,
6764 : SPOOL_DSSPOOLER_KEY,
6765 : SPOOL_REG_LOCATION,
6766 : REG_SZ,
6767 : buffer.data,
6768 8 : buffer.length);
6769 8 : if (!W_ERROR_IS_OK(result)) {
6770 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6771 0 : goto done;
6772 : }
6773 :
6774 8 : if (!force_update) {
6775 8 : notify_printer_location(global_event_context(),
6776 : msg_ctx, snum,
6777 8 : printer->location ?
6778 : printer->location : "");
6779 : }
6780 : }
6781 :
6782 100 : if (printer->sepfile != NULL &&
6783 84 : (force_update ||
6784 84 : !strequal(printer->sepfile, old_printer->sepfile))) {
6785 0 : ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6786 0 : if (!ok) {
6787 0 : DEBUG(0, ("sepfile data corrupted\n"));
6788 0 : result = WERR_INVALID_DATA;
6789 0 : goto done;
6790 : }
6791 0 : result = winreg_set_printer_dataex(tmp_ctx, b,
6792 : printer->sharename,
6793 : SPOOL_DSSPOOLER_KEY,
6794 : SPOOL_REG_PRINTSEPARATORFILE,
6795 : REG_SZ,
6796 : buffer.data,
6797 0 : buffer.length);
6798 0 : if (!W_ERROR_IS_OK(result)) {
6799 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6800 0 : goto done;
6801 : }
6802 :
6803 0 : if (!force_update) {
6804 0 : notify_printer_sepfile(global_event_context(),
6805 : msg_ctx, snum,
6806 0 : printer->sepfile ?
6807 : printer->sepfile : "");
6808 : }
6809 : }
6810 :
6811 100 : if (printer->starttime != 0 &&
6812 0 : (force_update ||
6813 0 : printer->starttime != old_printer->starttime)) {
6814 0 : buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6815 0 : SIVAL(buffer.data, 0, printer->starttime);
6816 0 : result = winreg_set_printer_dataex(tmp_ctx, b,
6817 : printer->sharename,
6818 : SPOOL_DSSPOOLER_KEY,
6819 : SPOOL_REG_PRINTSTARTTIME,
6820 : REG_DWORD,
6821 : buffer.data,
6822 0 : buffer.length);
6823 0 : if (!W_ERROR_IS_OK(result)) {
6824 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6825 0 : goto done;
6826 : }
6827 : }
6828 :
6829 100 : if (printer->untiltime != 0 &&
6830 0 : (force_update ||
6831 0 : printer->untiltime != old_printer->untiltime)) {
6832 0 : buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6833 0 : SIVAL(buffer.data, 0, printer->untiltime);
6834 0 : result = winreg_set_printer_dataex(tmp_ctx, b,
6835 : printer->sharename,
6836 : SPOOL_DSSPOOLER_KEY,
6837 : SPOOL_REG_PRINTENDTIME,
6838 : REG_DWORD,
6839 : buffer.data,
6840 0 : buffer.length);
6841 0 : if (!W_ERROR_IS_OK(result)) {
6842 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6843 0 : goto done;
6844 : }
6845 : }
6846 :
6847 100 : if (force_update || printer->priority != old_printer->priority) {
6848 16 : buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6849 16 : SIVAL(buffer.data, 0, printer->priority);
6850 16 : result = winreg_set_printer_dataex(tmp_ctx, b,
6851 : printer->sharename,
6852 : SPOOL_DSSPOOLER_KEY,
6853 : SPOOL_REG_PRIORITY,
6854 : REG_DWORD,
6855 : buffer.data,
6856 16 : buffer.length);
6857 16 : if (!W_ERROR_IS_OK(result)) {
6858 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6859 0 : goto done;
6860 : }
6861 : }
6862 :
6863 100 : if (force_update || printer->attributes != old_printer->attributes) {
6864 16 : buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6865 16 : SIVAL(buffer.data, 0, (printer->attributes &
6866 : PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6867 16 : result = winreg_set_printer_dataex(tmp_ctx, b,
6868 : printer->sharename,
6869 : SPOOL_DSSPOOLER_KEY,
6870 : SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6871 : REG_DWORD,
6872 : buffer.data,
6873 16 : buffer.length);
6874 16 : if (!W_ERROR_IS_OK(result)) {
6875 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6876 0 : goto done;
6877 : }
6878 :
6879 16 : switch (printer->attributes & 0x3) {
6880 16 : case 0:
6881 16 : spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6882 16 : break;
6883 0 : case 1:
6884 0 : spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6885 0 : break;
6886 0 : case 2:
6887 0 : spooling = SPOOL_REGVAL_PRINTDIRECT;
6888 0 : break;
6889 0 : default:
6890 0 : spooling = "unknown";
6891 : }
6892 16 : ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6893 16 : if (!ok) {
6894 0 : DEBUG(0, ("printSpooling data corrupted\n"));
6895 0 : result = WERR_INVALID_DATA;
6896 0 : goto done;
6897 : }
6898 16 : winreg_set_printer_dataex(tmp_ctx, b,
6899 : printer->sharename,
6900 : SPOOL_DSSPOOLER_KEY,
6901 : SPOOL_REG_PRINTSPOOLING,
6902 : REG_SZ,
6903 : buffer.data,
6904 16 : buffer.length);
6905 : }
6906 :
6907 100 : ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6908 100 : if (!ok) {
6909 0 : DEBUG(0, ("shortServerName data corrupted\n"));
6910 0 : result = WERR_INVALID_DATA;
6911 0 : goto done;
6912 : }
6913 100 : result = winreg_set_printer_dataex(tmp_ctx, b,
6914 : printer->sharename,
6915 : SPOOL_DSSPOOLER_KEY,
6916 : SPOOL_REG_SHORTSERVERNAME,
6917 : REG_SZ,
6918 : buffer.data,
6919 100 : buffer.length);
6920 100 : if (!W_ERROR_IS_OK(result)) {
6921 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6922 0 : goto done;
6923 : }
6924 :
6925 100 : dnsdomname = get_mydnsfullname();
6926 100 : if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6927 100 : longname = talloc_strdup(tmp_ctx, dnsdomname);
6928 : } else {
6929 0 : longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6930 : }
6931 100 : if (longname == NULL) {
6932 0 : result = WERR_NOT_ENOUGH_MEMORY;
6933 0 : goto done;
6934 : }
6935 :
6936 100 : ok = push_reg_sz(tmp_ctx, &buffer, longname);
6937 100 : if (!ok) {
6938 0 : DEBUG(0, ("longname data corrupted\n"));
6939 0 : result = WERR_INVALID_DATA;
6940 0 : goto done;
6941 : }
6942 100 : result = winreg_set_printer_dataex(tmp_ctx, b,
6943 : printer->sharename,
6944 : SPOOL_DSSPOOLER_KEY,
6945 : SPOOL_REG_SERVERNAME,
6946 : REG_SZ,
6947 : buffer.data,
6948 100 : buffer.length);
6949 100 : if (!W_ERROR_IS_OK(result)) {
6950 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6951 0 : goto done;
6952 : }
6953 :
6954 100 : uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6955 : lp_netbios_name(), printer->sharename);
6956 100 : ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6957 100 : if (!ok) {
6958 0 : DEBUG(0, ("uncName data corrupted\n"));
6959 0 : result = WERR_INVALID_DATA;
6960 0 : goto done;
6961 : }
6962 100 : result = winreg_set_printer_dataex(tmp_ctx, b,
6963 : printer->sharename,
6964 : SPOOL_DSSPOOLER_KEY,
6965 : SPOOL_REG_UNCNAME,
6966 : REG_SZ,
6967 : buffer.data,
6968 100 : buffer.length);
6969 100 : if (!W_ERROR_IS_OK(result)) {
6970 0 : DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6971 0 : goto done;
6972 : }
6973 :
6974 100 : done:
6975 100 : talloc_free(tmp_ctx);
6976 100 : return result;
6977 : }
6978 :
6979 : /********************************************************************
6980 : * Called by spoolss_api_setprinter
6981 : * when updating a printer description.
6982 : ********************************************************************/
6983 :
6984 84 : static WERROR update_printer(struct pipes_struct *p,
6985 : struct policy_handle *handle,
6986 : struct spoolss_SetPrinterInfoCtr *info_ctr,
6987 : struct spoolss_DeviceMode *devmode)
6988 : {
6989 84 : struct dcesrv_call_state *dce_call = p->dce_call;
6990 84 : struct dcesrv_connection *dcesrv_conn = dce_call->conn;
6991 0 : const struct tsocket_address *remote_address =
6992 84 : dcesrv_connection_get_remote_address(dcesrv_conn);
6993 0 : struct auth_session_info *session_info =
6994 84 : dcesrv_call_session_info(dce_call);
6995 84 : uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6996 84 : struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6997 0 : struct spoolss_PrinterInfo2 *old_printer;
6998 84 : struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6999 0 : const struct loadparm_substitution *lp_sub =
7000 84 : loadparm_s3_global_substitution();
7001 0 : int snum;
7002 84 : WERROR result = WERR_OK;
7003 0 : TALLOC_CTX *tmp_ctx;
7004 0 : struct dcerpc_binding_handle *b;
7005 :
7006 84 : DEBUG(8,("update_printer\n"));
7007 :
7008 84 : tmp_ctx = talloc_new(p->mem_ctx);
7009 84 : if (tmp_ctx == NULL) {
7010 0 : return WERR_NOT_ENOUGH_MEMORY;
7011 : }
7012 :
7013 84 : if (!Printer) {
7014 0 : result = WERR_INVALID_HANDLE;
7015 0 : goto done;
7016 : }
7017 :
7018 84 : if (!get_printer_snum(p, handle, &snum, NULL)) {
7019 0 : result = WERR_INVALID_HANDLE;
7020 0 : goto done;
7021 : }
7022 :
7023 84 : result = winreg_printer_binding_handle(tmp_ctx,
7024 : get_session_info_system(),
7025 : p->msg_ctx,
7026 : &b);
7027 84 : if (!W_ERROR_IS_OK(result)) {
7028 0 : goto done;
7029 : }
7030 :
7031 84 : result = winreg_get_printer(tmp_ctx, b,
7032 : lp_const_servicename(snum),
7033 : &old_printer);
7034 84 : if (!W_ERROR_IS_OK(result)) {
7035 0 : result = WERR_INVALID_HANDLE;
7036 0 : goto done;
7037 : }
7038 :
7039 : /* Do sanity check on the requested changes for Samba */
7040 84 : if (!check_printer_ok(tmp_ctx, printer, snum)) {
7041 0 : result = WERR_INVALID_PARAMETER;
7042 0 : goto done;
7043 : }
7044 :
7045 : /* FIXME!!! If the driver has changed we really should verify that
7046 : it is installed before doing much else --jerry */
7047 :
7048 : /* Check calling user has permission to update printer description */
7049 84 : if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7050 0 : DEBUG(3, ("update_printer: printer property change denied by handle\n"));
7051 0 : result = WERR_ACCESS_DENIED;
7052 0 : goto done;
7053 : }
7054 :
7055 : /* Call addprinter hook */
7056 : /* Check changes to see if this is really needed */
7057 :
7058 84 : if (*lp_addprinter_command(talloc_tos(), lp_sub) &&
7059 84 : (!strequal(printer->drivername, old_printer->drivername) ||
7060 76 : !strequal(printer->comment, old_printer->comment) ||
7061 42 : !strequal(printer->portname, old_printer->portname) ||
7062 42 : !strequal(printer->location, old_printer->location)) )
7063 : {
7064 0 : char *raddr;
7065 :
7066 50 : raddr = tsocket_address_inet_addr_string(remote_address,
7067 : p->mem_ctx);
7068 50 : if (raddr == NULL) {
7069 0 : result = WERR_NOT_ENOUGH_MEMORY;
7070 0 : goto done;
7071 : }
7072 :
7073 : /* add_printer_hook() will call reload_services() */
7074 50 : if (!add_printer_hook(tmp_ctx, session_info->security_token,
7075 : printer, raddr,
7076 : p->msg_ctx)) {
7077 0 : result = WERR_ACCESS_DENIED;
7078 0 : goto done;
7079 : }
7080 : }
7081 :
7082 84 : result = update_dsspooler(tmp_ctx,
7083 : get_session_info_system(),
7084 : p->msg_ctx,
7085 : snum,
7086 : printer,
7087 : old_printer);
7088 84 : if (!W_ERROR_IS_OK(result)) {
7089 0 : goto done;
7090 : }
7091 :
7092 84 : printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
7093 :
7094 84 : if (devmode == NULL) {
7095 76 : printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
7096 : }
7097 84 : result = winreg_update_printer(tmp_ctx, b,
7098 : printer->sharename,
7099 : printer_mask,
7100 : printer,
7101 : devmode,
7102 : NULL);
7103 :
7104 84 : done:
7105 84 : talloc_free(tmp_ctx);
7106 :
7107 84 : return result;
7108 : }
7109 :
7110 : /****************************************************************************
7111 : ****************************************************************************/
7112 8 : static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
7113 : struct policy_handle *handle,
7114 : struct spoolss_SetPrinterInfo7 *info7)
7115 : {
7116 : #ifdef HAVE_ADS
7117 0 : const struct loadparm_substitution *lp_sub =
7118 6 : loadparm_s3_global_substitution();
7119 6 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7120 0 : WERROR result;
7121 0 : int snum;
7122 0 : struct printer_handle *Printer;
7123 :
7124 6 : if ( lp_security() != SEC_ADS ) {
7125 6 : return WERR_INVALID_LEVEL;
7126 : }
7127 :
7128 0 : Printer = find_printer_index_by_hnd(p, handle);
7129 :
7130 0 : DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
7131 :
7132 0 : if (!Printer)
7133 0 : return WERR_INVALID_HANDLE;
7134 :
7135 0 : if (!get_printer_snum(p, handle, &snum, NULL))
7136 0 : return WERR_INVALID_HANDLE;
7137 :
7138 0 : result = winreg_get_printer_internal(p->mem_ctx,
7139 : get_session_info_system(),
7140 : p->msg_ctx,
7141 0 : lp_servicename(talloc_tos(), lp_sub, snum),
7142 : &pinfo2);
7143 0 : if (!W_ERROR_IS_OK(result)) {
7144 0 : return WERR_INVALID_HANDLE;
7145 : }
7146 :
7147 0 : nt_printer_publish(pinfo2,
7148 : get_session_info_system(),
7149 : p->msg_ctx,
7150 : pinfo2,
7151 0 : info7->action);
7152 :
7153 0 : TALLOC_FREE(pinfo2);
7154 0 : return WERR_OK;
7155 : #else
7156 2 : return WERR_INVALID_LEVEL;
7157 : #endif
7158 : }
7159 :
7160 : /********************************************************************
7161 : ********************************************************************/
7162 :
7163 296 : static WERROR update_printer_devmode(struct pipes_struct *p,
7164 : struct policy_handle *handle,
7165 : struct spoolss_DeviceMode *devmode)
7166 : {
7167 0 : int snum;
7168 296 : struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
7169 296 : uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
7170 :
7171 296 : DEBUG(8,("update_printer_devmode\n"));
7172 :
7173 296 : if (!Printer) {
7174 0 : return WERR_INVALID_HANDLE;
7175 : }
7176 :
7177 296 : if (!get_printer_snum(p, handle, &snum, NULL)) {
7178 0 : return WERR_INVALID_HANDLE;
7179 : }
7180 :
7181 : /* Check calling user has permission to update printer description */
7182 296 : if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7183 0 : DEBUG(3, ("update_printer: printer property change denied by handle\n"));
7184 0 : return WERR_ACCESS_DENIED;
7185 : }
7186 :
7187 296 : return winreg_update_printer_internal(p->mem_ctx,
7188 : get_session_info_system(),
7189 : p->msg_ctx,
7190 : lp_const_servicename(snum),
7191 : info2_mask,
7192 : NULL,
7193 : devmode,
7194 : NULL);
7195 : }
7196 :
7197 :
7198 : /****************************************************************
7199 : _spoolss_SetPrinter
7200 : ****************************************************************/
7201 :
7202 584 : WERROR _spoolss_SetPrinter(struct pipes_struct *p,
7203 : struct spoolss_SetPrinter *r)
7204 : {
7205 0 : WERROR result;
7206 :
7207 584 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7208 :
7209 584 : if (!Printer) {
7210 0 : DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
7211 : OUR_HANDLE(r->in.handle)));
7212 0 : return WERR_INVALID_HANDLE;
7213 : }
7214 :
7215 : /* check the level */
7216 584 : switch (r->in.info_ctr->level) {
7217 104 : case 0:
7218 104 : return control_printer(r->in.handle, r->in.command, p);
7219 84 : case 2:
7220 84 : result = update_printer(p, r->in.handle,
7221 : r->in.info_ctr,
7222 84 : r->in.devmode_ctr->devmode);
7223 84 : if (!W_ERROR_IS_OK(result))
7224 0 : return result;
7225 84 : if (r->in.secdesc_ctr->sd)
7226 28 : result = update_printer_sec(r->in.handle, p,
7227 : r->in.secdesc_ctr);
7228 84 : return result;
7229 92 : case 3:
7230 92 : return update_printer_sec(r->in.handle, p,
7231 : r->in.secdesc_ctr);
7232 0 : case 4: {
7233 0 : struct spoolss_PrinterInfo2 *old_printer;
7234 0 : struct spoolss_SetPrinterInfo2 *set_old_printer;
7235 0 : struct spoolss_SetPrinterInfoCtr *info_ctr;
7236 0 : struct dcerpc_binding_handle *b;
7237 0 : int snum;
7238 0 : TALLOC_CTX *tmp_ctx;
7239 :
7240 0 : tmp_ctx = talloc_new(p->mem_ctx);
7241 0 : if (tmp_ctx == NULL) {
7242 0 : return WERR_NOT_ENOUGH_MEMORY;
7243 : }
7244 :
7245 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7246 0 : TALLOC_FREE(tmp_ctx);
7247 0 : return WERR_INVALID_HANDLE;
7248 : }
7249 :
7250 0 : result = winreg_printer_binding_handle(tmp_ctx,
7251 : get_session_info_system(),
7252 : p->msg_ctx,
7253 : &b);
7254 0 : if (!W_ERROR_IS_OK(result)) {
7255 0 : TALLOC_FREE(tmp_ctx);
7256 0 : return result;
7257 : }
7258 :
7259 0 : result = winreg_get_printer(tmp_ctx, b,
7260 : lp_const_servicename(snum),
7261 : &old_printer);
7262 0 : if (!W_ERROR_IS_OK(result)) {
7263 0 : TALLOC_FREE(tmp_ctx);
7264 0 : return WERR_INVALID_HANDLE;
7265 : }
7266 :
7267 0 : old_printer->servername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->servername);
7268 0 : if (old_printer->servername == NULL) {
7269 0 : TALLOC_FREE(tmp_ctx);
7270 0 : return WERR_NOT_ENOUGH_MEMORY;
7271 : }
7272 :
7273 0 : old_printer->printername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->printername);
7274 0 : if (old_printer->printername == NULL) {
7275 0 : TALLOC_FREE(tmp_ctx);
7276 0 : return WERR_NOT_ENOUGH_MEMORY;
7277 : }
7278 :
7279 0 : old_printer->attributes = r->in.info_ctr->info.info4->attributes;
7280 :
7281 0 : set_old_printer = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfo2);
7282 0 : if (set_old_printer == NULL) {
7283 0 : TALLOC_FREE(tmp_ctx);
7284 0 : return WERR_NOT_ENOUGH_MEMORY;
7285 : }
7286 :
7287 0 : spoolss_printerinfo2_to_setprinterinfo2(old_printer, set_old_printer);
7288 :
7289 0 : info_ctr = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfoCtr);
7290 0 : if (info_ctr == NULL) {
7291 0 : TALLOC_FREE(tmp_ctx);
7292 0 : return WERR_NOT_ENOUGH_MEMORY;
7293 : }
7294 :
7295 0 : info_ctr->level = 2;
7296 0 : info_ctr->info.info2 = set_old_printer;
7297 :
7298 0 : result = update_printer(p, r->in.handle,
7299 : info_ctr,
7300 0 : r->in.devmode_ctr->devmode);
7301 :
7302 0 : if (!W_ERROR_IS_OK(result)) {
7303 0 : TALLOC_FREE(tmp_ctx);
7304 0 : return result;
7305 : }
7306 :
7307 0 : if (r->in.secdesc_ctr->sd) {
7308 0 : result = update_printer_sec(r->in.handle, p,
7309 : r->in.secdesc_ctr);
7310 : }
7311 :
7312 0 : TALLOC_FREE(tmp_ctx);
7313 0 : return result;
7314 : }
7315 8 : case 7:
7316 8 : return publish_or_unpublish_printer(p, r->in.handle,
7317 8 : r->in.info_ctr->info.info7);
7318 296 : case 8:
7319 296 : return update_printer_devmode(p, r->in.handle,
7320 296 : r->in.devmode_ctr->devmode);
7321 0 : default:
7322 0 : return WERR_INVALID_LEVEL;
7323 : }
7324 : }
7325 :
7326 : /****************************************************************
7327 : _spoolss_FindClosePrinterNotify
7328 : ****************************************************************/
7329 :
7330 0 : WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
7331 : struct spoolss_FindClosePrinterNotify *r)
7332 : {
7333 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7334 :
7335 0 : if (!Printer) {
7336 0 : DEBUG(2,("_spoolss_FindClosePrinterNotify: "
7337 : "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
7338 0 : return WERR_INVALID_HANDLE;
7339 : }
7340 :
7341 0 : if (Printer->notify.cli_chan != NULL &&
7342 0 : Printer->notify.cli_chan->active_connections > 0) {
7343 0 : int snum = -1;
7344 :
7345 0 : if (Printer->printer_type == SPLHND_PRINTER) {
7346 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7347 0 : return WERR_INVALID_HANDLE;
7348 : }
7349 : }
7350 :
7351 0 : srv_spoolss_replycloseprinter(snum, Printer);
7352 : }
7353 :
7354 0 : Printer->notify.flags=0;
7355 0 : Printer->notify.options=0;
7356 0 : Printer->notify.localmachine[0]='\0';
7357 0 : Printer->notify.printerlocal=0;
7358 0 : TALLOC_FREE(Printer->notify.option);
7359 :
7360 0 : return WERR_OK;
7361 : }
7362 :
7363 : /****************************************************************
7364 : _spoolss_AddJob
7365 : ****************************************************************/
7366 :
7367 16 : WERROR _spoolss_AddJob(struct pipes_struct *p,
7368 : struct spoolss_AddJob *r)
7369 : {
7370 16 : if (!r->in.buffer && (r->in.offered != 0)) {
7371 0 : return WERR_INVALID_PARAMETER;
7372 : }
7373 :
7374 : /* this is what a NT server returns for AddJob. AddJob must fail on
7375 : * non-local printers */
7376 :
7377 16 : if (r->in.level != 1) {
7378 8 : return WERR_INVALID_LEVEL;
7379 : }
7380 :
7381 8 : return WERR_INVALID_PARAMETER;
7382 : }
7383 :
7384 : /****************************************************************************
7385 : fill_job_info1
7386 : ****************************************************************************/
7387 :
7388 320 : static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
7389 : struct spoolss_JobInfo1 *r,
7390 : const print_queue_struct *queue,
7391 : uint32_t jobid,
7392 : int position, int snum,
7393 : struct spoolss_PrinterInfo2 *pinfo2)
7394 : {
7395 0 : const struct loadparm_substitution *lp_sub =
7396 320 : loadparm_s3_global_substitution();
7397 0 : struct tm *t;
7398 :
7399 320 : t = gmtime(&queue->time);
7400 :
7401 320 : r->job_id = jobid;
7402 :
7403 320 : r->printer_name = lp_servicename(mem_ctx, lp_sub, snum);
7404 320 : W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7405 320 : r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
7406 320 : W_ERROR_HAVE_NO_MEMORY(r->server_name);
7407 320 : r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
7408 320 : W_ERROR_HAVE_NO_MEMORY(r->user_name);
7409 320 : r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
7410 320 : W_ERROR_HAVE_NO_MEMORY(r->document_name);
7411 320 : r->data_type = talloc_strdup(mem_ctx, "RAW");
7412 320 : W_ERROR_HAVE_NO_MEMORY(r->data_type);
7413 320 : r->text_status = talloc_strdup(mem_ctx, "");
7414 320 : W_ERROR_HAVE_NO_MEMORY(r->text_status);
7415 :
7416 320 : r->status = nt_printj_status(queue->status);
7417 320 : r->priority = queue->priority;
7418 320 : r->position = position;
7419 320 : r->total_pages = queue->page_count;
7420 320 : r->pages_printed = 0; /* ??? */
7421 :
7422 320 : init_systemtime(&r->submitted, t);
7423 :
7424 320 : return WERR_OK;
7425 : }
7426 :
7427 : /****************************************************************************
7428 : fill_job_info2
7429 : ****************************************************************************/
7430 :
7431 72 : static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7432 : struct spoolss_JobInfo2 *r,
7433 : const print_queue_struct *queue,
7434 : uint32_t jobid,
7435 : int position, int snum,
7436 : struct spoolss_PrinterInfo2 *pinfo2,
7437 : struct spoolss_DeviceMode *devmode)
7438 : {
7439 0 : const struct loadparm_substitution *lp_sub =
7440 72 : loadparm_s3_global_substitution();
7441 0 : struct tm *t;
7442 :
7443 72 : t = gmtime(&queue->time);
7444 :
7445 72 : r->job_id = jobid;
7446 :
7447 72 : r->printer_name = lp_servicename(mem_ctx, lp_sub, snum);
7448 72 : W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7449 72 : r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
7450 72 : W_ERROR_HAVE_NO_MEMORY(r->server_name);
7451 72 : r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
7452 72 : W_ERROR_HAVE_NO_MEMORY(r->user_name);
7453 72 : r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
7454 72 : W_ERROR_HAVE_NO_MEMORY(r->document_name);
7455 72 : r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
7456 72 : W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7457 72 : r->data_type = talloc_strdup(mem_ctx, "RAW");
7458 72 : W_ERROR_HAVE_NO_MEMORY(r->data_type);
7459 72 : r->print_processor = talloc_strdup(mem_ctx, "winprint");
7460 72 : W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7461 72 : r->parameters = talloc_strdup(mem_ctx, "");
7462 72 : W_ERROR_HAVE_NO_MEMORY(r->parameters);
7463 72 : r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
7464 72 : W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7465 :
7466 72 : r->devmode = devmode;
7467 :
7468 72 : r->text_status = talloc_strdup(mem_ctx, "");
7469 72 : W_ERROR_HAVE_NO_MEMORY(r->text_status);
7470 :
7471 72 : r->secdesc = NULL;
7472 :
7473 72 : r->status = nt_printj_status(queue->status);
7474 72 : r->priority = queue->priority;
7475 72 : r->position = position;
7476 72 : r->start_time = 0;
7477 72 : r->until_time = 0;
7478 72 : r->total_pages = queue->page_count;
7479 72 : r->size = queue->size;
7480 72 : init_systemtime(&r->submitted, t);
7481 72 : r->time = 0;
7482 72 : r->pages_printed = 0; /* ??? */
7483 :
7484 72 : return WERR_OK;
7485 : }
7486 :
7487 : /****************************************************************************
7488 : Enumjobs at level 1.
7489 : ****************************************************************************/
7490 :
7491 24 : static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7492 : const print_queue_struct *queue,
7493 : uint32_t num_queues, int snum,
7494 : struct spoolss_PrinterInfo2 *pinfo2,
7495 : union spoolss_JobInfo **info_p,
7496 : uint32_t *count)
7497 : {
7498 0 : union spoolss_JobInfo *info;
7499 0 : int i;
7500 24 : WERROR result = WERR_OK;
7501 0 : uint32_t num_filled;
7502 0 : struct tdb_print_db *pdb;
7503 :
7504 24 : info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7505 24 : if (info == NULL) {
7506 0 : result = WERR_NOT_ENOUGH_MEMORY;
7507 0 : goto err_out;
7508 : }
7509 :
7510 24 : pdb = get_print_db_byname(pinfo2->sharename);
7511 24 : if (pdb == NULL) {
7512 0 : result = WERR_INVALID_PARAMETER;
7513 0 : goto err_info_free;
7514 : }
7515 :
7516 24 : num_filled = 0;
7517 216 : for (i = 0; i < num_queues; i++) {
7518 192 : uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7519 192 : if (jobid == (uint32_t)-1) {
7520 0 : DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7521 0 : continue;
7522 : }
7523 :
7524 192 : result = fill_job_info1(info,
7525 192 : &info[num_filled].info1,
7526 192 : &queue[i],
7527 : jobid,
7528 : i,
7529 : snum,
7530 : pinfo2);
7531 192 : if (!W_ERROR_IS_OK(result)) {
7532 0 : goto err_pdb_drop;
7533 : }
7534 :
7535 192 : num_filled++;
7536 : }
7537 :
7538 24 : release_print_db(pdb);
7539 24 : *info_p = info;
7540 24 : *count = num_filled;
7541 :
7542 24 : return WERR_OK;
7543 :
7544 0 : err_pdb_drop:
7545 0 : release_print_db(pdb);
7546 0 : err_info_free:
7547 0 : TALLOC_FREE(info);
7548 0 : err_out:
7549 0 : *count = 0;
7550 0 : return result;
7551 : }
7552 :
7553 : /****************************************************************************
7554 : Enumjobs at level 2.
7555 : ****************************************************************************/
7556 :
7557 16 : static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7558 : const print_queue_struct *queue,
7559 : uint32_t num_queues, int snum,
7560 : struct spoolss_PrinterInfo2 *pinfo2,
7561 : union spoolss_JobInfo **info_p,
7562 : uint32_t *count)
7563 : {
7564 0 : union spoolss_JobInfo *info;
7565 0 : int i;
7566 16 : WERROR result = WERR_OK;
7567 0 : uint32_t num_filled;
7568 0 : struct tdb_print_db *pdb;
7569 :
7570 16 : info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7571 16 : if (info == NULL) {
7572 0 : result = WERR_NOT_ENOUGH_MEMORY;
7573 0 : goto err_out;
7574 : }
7575 :
7576 16 : pdb = get_print_db_byname(pinfo2->sharename);
7577 16 : if (pdb == NULL) {
7578 0 : result = WERR_INVALID_PARAMETER;
7579 0 : goto err_info_free;
7580 : }
7581 :
7582 16 : num_filled = 0;
7583 88 : for (i = 0; i< num_queues; i++) {
7584 0 : struct spoolss_DeviceMode *devmode;
7585 72 : uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7586 72 : if (jobid == (uint32_t)-1) {
7587 0 : DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7588 0 : continue;
7589 : }
7590 :
7591 72 : result = spoolss_create_default_devmode(info,
7592 : pinfo2->printername,
7593 : &devmode);
7594 72 : if (!W_ERROR_IS_OK(result)) {
7595 0 : DEBUG(3, ("Can't proceed w/o a devmode!\n"));
7596 0 : goto err_pdb_drop;
7597 : }
7598 :
7599 72 : result = fill_job_info2(info,
7600 72 : &info[num_filled].info2,
7601 72 : &queue[i],
7602 : jobid,
7603 : i,
7604 : snum,
7605 : pinfo2,
7606 : devmode);
7607 72 : if (!W_ERROR_IS_OK(result)) {
7608 0 : goto err_pdb_drop;
7609 : }
7610 72 : num_filled++;
7611 : }
7612 :
7613 16 : release_print_db(pdb);
7614 16 : *info_p = info;
7615 16 : *count = num_filled;
7616 :
7617 16 : return WERR_OK;
7618 :
7619 0 : err_pdb_drop:
7620 0 : release_print_db(pdb);
7621 0 : err_info_free:
7622 0 : TALLOC_FREE(info);
7623 0 : err_out:
7624 0 : *count = 0;
7625 0 : return result;
7626 : }
7627 :
7628 : /****************************************************************************
7629 : Enumjobs at level 3.
7630 : ****************************************************************************/
7631 :
7632 0 : static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7633 : const print_queue_struct *queue,
7634 : uint32_t num_queues, int snum,
7635 : struct spoolss_PrinterInfo2 *pinfo2,
7636 : union spoolss_JobInfo **info_p,
7637 : uint32_t *count)
7638 : {
7639 0 : union spoolss_JobInfo *info;
7640 0 : int i;
7641 0 : WERROR result = WERR_OK;
7642 0 : uint32_t num_filled;
7643 0 : struct tdb_print_db *pdb;
7644 :
7645 0 : info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7646 0 : if (info == NULL) {
7647 0 : result = WERR_NOT_ENOUGH_MEMORY;
7648 0 : goto err_out;
7649 : }
7650 :
7651 0 : pdb = get_print_db_byname(pinfo2->sharename);
7652 0 : if (pdb == NULL) {
7653 0 : result = WERR_INVALID_PARAMETER;
7654 0 : goto err_info_free;
7655 : }
7656 :
7657 0 : num_filled = 0;
7658 0 : for (i = 0; i < num_queues; i++) {
7659 0 : uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7660 0 : if (jobid == (uint32_t)-1) {
7661 0 : DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7662 0 : continue;
7663 : }
7664 :
7665 0 : info[num_filled].info3.job_id = jobid;
7666 : /* next_job_id is overwritten on next iteration */
7667 0 : info[num_filled].info3.next_job_id = 0;
7668 0 : info[num_filled].info3.reserved = 0;
7669 :
7670 0 : if (num_filled > 0) {
7671 0 : info[num_filled - 1].info3.next_job_id = jobid;
7672 : }
7673 0 : num_filled++;
7674 : }
7675 :
7676 0 : release_print_db(pdb);
7677 0 : *info_p = info;
7678 0 : *count = num_filled;
7679 :
7680 0 : return WERR_OK;
7681 :
7682 0 : err_info_free:
7683 0 : TALLOC_FREE(info);
7684 0 : err_out:
7685 0 : *count = 0;
7686 0 : return result;
7687 : }
7688 :
7689 : /****************************************************************
7690 : _spoolss_EnumJobs
7691 : ****************************************************************/
7692 :
7693 98 : WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7694 : struct spoolss_EnumJobs *r)
7695 : {
7696 0 : WERROR result;
7697 98 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7698 0 : int snum;
7699 0 : print_status_struct prt_status;
7700 98 : print_queue_struct *queue = NULL;
7701 0 : uint32_t count;
7702 :
7703 : /* that's an [in out] buffer */
7704 :
7705 98 : if (!r->in.buffer && (r->in.offered != 0)) {
7706 0 : return WERR_INVALID_PARAMETER;
7707 : }
7708 :
7709 98 : if ((r->in.level != 1) && (r->in.level != 2) && (r->in.level != 3)) {
7710 12 : DEBUG(4, ("EnumJobs level %d not supported\n", r->in.level));
7711 12 : return WERR_INVALID_LEVEL;
7712 : }
7713 :
7714 86 : DEBUG(4,("_spoolss_EnumJobs\n"));
7715 :
7716 86 : *r->out.needed = 0;
7717 86 : *r->out.count = 0;
7718 86 : *r->out.info = NULL;
7719 :
7720 : /* lookup the printer snum and tdb entry */
7721 :
7722 86 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7723 0 : return WERR_INVALID_HANDLE;
7724 : }
7725 :
7726 86 : result = winreg_get_printer_internal(p->mem_ctx,
7727 : get_session_info_system(),
7728 : p->msg_ctx,
7729 : lp_const_servicename(snum),
7730 : &pinfo2);
7731 86 : if (!W_ERROR_IS_OK(result)) {
7732 0 : return result;
7733 : }
7734 :
7735 86 : count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7736 86 : DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7737 : count, prt_status.status, prt_status.message));
7738 :
7739 86 : if (count == 0) {
7740 46 : SAFE_FREE(queue);
7741 46 : TALLOC_FREE(pinfo2);
7742 46 : return WERR_OK;
7743 : }
7744 :
7745 40 : switch (r->in.level) {
7746 24 : case 1:
7747 24 : result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7748 : pinfo2, r->out.info, r->out.count);
7749 24 : break;
7750 16 : case 2:
7751 16 : result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7752 : pinfo2, r->out.info, r->out.count);
7753 16 : break;
7754 0 : case 3:
7755 0 : result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7756 : pinfo2, r->out.info, r->out.count);
7757 0 : break;
7758 0 : default:
7759 0 : SMB_ASSERT(false); /* level checked on entry */
7760 : break;
7761 : }
7762 :
7763 40 : SAFE_FREE(queue);
7764 40 : TALLOC_FREE(pinfo2);
7765 :
7766 40 : if (!W_ERROR_IS_OK(result)) {
7767 0 : return result;
7768 : }
7769 :
7770 40 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7771 : spoolss_EnumJobs,
7772 : *r->out.info, r->in.level,
7773 : *r->out.count);
7774 40 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7775 40 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7776 :
7777 40 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7778 : }
7779 :
7780 : /****************************************************************
7781 : _spoolss_ScheduleJob
7782 : ****************************************************************/
7783 :
7784 0 : WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7785 : struct spoolss_ScheduleJob *r)
7786 : {
7787 0 : return WERR_OK;
7788 : }
7789 :
7790 : /****************************************************************
7791 : ****************************************************************/
7792 :
7793 32 : static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7794 : struct messaging_context *msg_ctx,
7795 : const char *printer_name,
7796 : uint32_t job_id,
7797 : struct spoolss_SetJobInfo1 *r)
7798 : {
7799 0 : char *old_doc_name;
7800 :
7801 32 : if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7802 0 : return WERR_INVALID_HANDLE;
7803 : }
7804 :
7805 32 : if (strequal(old_doc_name, r->document_name)) {
7806 0 : return WERR_OK;
7807 : }
7808 :
7809 32 : if (!print_job_set_name(global_event_context(), msg_ctx,
7810 : printer_name, job_id, r->document_name)) {
7811 0 : return WERR_INVALID_HANDLE;
7812 : }
7813 :
7814 32 : return WERR_OK;
7815 : }
7816 :
7817 : /****************************************************************
7818 : _spoolss_SetJob
7819 : ****************************************************************/
7820 :
7821 640 : WERROR _spoolss_SetJob(struct pipes_struct *p,
7822 : struct spoolss_SetJob *r)
7823 : {
7824 640 : struct dcesrv_call_state *dce_call = p->dce_call;
7825 0 : struct auth_session_info *session_info =
7826 640 : dcesrv_call_session_info(dce_call);
7827 0 : int snum;
7828 640 : WERROR errcode = WERR_INVALID_FUNCTION;
7829 :
7830 640 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7831 0 : return WERR_INVALID_HANDLE;
7832 : }
7833 :
7834 640 : if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7835 245 : return WERR_INVALID_PRINTER_NAME;
7836 : }
7837 :
7838 395 : switch (r->in.command) {
7839 299 : case SPOOLSS_JOB_CONTROL_CANCEL:
7840 : case SPOOLSS_JOB_CONTROL_DELETE:
7841 299 : errcode = print_job_delete(session_info, p->msg_ctx,
7842 : snum, r->in.job_id);
7843 299 : if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7844 299 : errcode = WERR_OK;
7845 : }
7846 299 : break;
7847 32 : case SPOOLSS_JOB_CONTROL_PAUSE:
7848 32 : errcode = print_job_pause(session_info, p->msg_ctx,
7849 : snum, r->in.job_id);
7850 32 : break;
7851 32 : case SPOOLSS_JOB_CONTROL_RESTART:
7852 : case SPOOLSS_JOB_CONTROL_RESUME:
7853 32 : errcode = print_job_resume(session_info, p->msg_ctx,
7854 : snum, r->in.job_id);
7855 32 : break;
7856 32 : case SPOOLSS_JOB_CONTROL_NOOP:
7857 32 : errcode = WERR_OK;
7858 32 : break;
7859 0 : default:
7860 0 : return WERR_INVALID_LEVEL;
7861 : }
7862 :
7863 395 : if (!W_ERROR_IS_OK(errcode)) {
7864 0 : return errcode;
7865 : }
7866 :
7867 395 : if (r->in.ctr == NULL) {
7868 363 : return errcode;
7869 : }
7870 :
7871 32 : switch (r->in.ctr->level) {
7872 32 : case 1:
7873 32 : errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7874 : lp_const_servicename(snum),
7875 : r->in.job_id,
7876 32 : r->in.ctr->info.info1);
7877 32 : break;
7878 0 : case 2:
7879 : case 3:
7880 : case 4:
7881 : default:
7882 0 : return WERR_INVALID_LEVEL;
7883 : }
7884 :
7885 32 : return errcode;
7886 : }
7887 :
7888 : /****************************************************************************
7889 : Enumerates all printer drivers by level and architecture.
7890 : ****************************************************************************/
7891 :
7892 460 : static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7893 : const struct auth_session_info *session_info,
7894 : struct messaging_context *msg_ctx,
7895 : const char *servername,
7896 : const char *architecture,
7897 : uint32_t level,
7898 : union spoolss_DriverInfo **info_p,
7899 : uint32_t *count_p)
7900 : {
7901 0 : int i;
7902 0 : uint32_t version;
7903 0 : struct spoolss_DriverInfo8 *driver;
7904 460 : union spoolss_DriverInfo *info = NULL;
7905 460 : uint32_t count = 0;
7906 460 : WERROR result = WERR_OK;
7907 0 : uint32_t num_drivers;
7908 0 : const char **drivers;
7909 0 : struct dcerpc_binding_handle *b;
7910 460 : TALLOC_CTX *tmp_ctx = NULL;
7911 :
7912 460 : *count_p = 0;
7913 460 : *info_p = NULL;
7914 :
7915 460 : tmp_ctx = talloc_new(mem_ctx);
7916 460 : if (!tmp_ctx) {
7917 0 : return WERR_NOT_ENOUGH_MEMORY;
7918 : }
7919 :
7920 460 : result = winreg_printer_binding_handle(tmp_ctx,
7921 : session_info,
7922 : msg_ctx,
7923 : &b);
7924 460 : if (!W_ERROR_IS_OK(result)) {
7925 0 : goto out;
7926 : }
7927 :
7928 2300 : for (version=0; version<DRIVER_MAX_VERSION; version++) {
7929 1840 : result = winreg_get_driver_list(tmp_ctx, b,
7930 : architecture, version,
7931 : &num_drivers, &drivers);
7932 1840 : if (!W_ERROR_IS_OK(result)) {
7933 0 : goto out;
7934 : }
7935 1840 : DEBUG(4, ("we have:[%d] drivers in environment"
7936 : " [%s] and version [%d]\n",
7937 : num_drivers, architecture, version));
7938 :
7939 1840 : if (num_drivers != 0) {
7940 0 : info = talloc_realloc(tmp_ctx, info,
7941 : union spoolss_DriverInfo,
7942 : count + num_drivers);
7943 0 : if (!info) {
7944 0 : DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7945 : "failed to enlarge driver info buffer!\n"));
7946 0 : result = WERR_NOT_ENOUGH_MEMORY;
7947 0 : goto out;
7948 : }
7949 : }
7950 :
7951 1840 : for (i = 0; i < num_drivers; i++) {
7952 0 : DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7953 :
7954 0 : result = winreg_get_driver(tmp_ctx, b,
7955 0 : architecture, drivers[i],
7956 : version, &driver);
7957 0 : if (!W_ERROR_IS_OK(result)) {
7958 0 : goto out;
7959 : }
7960 :
7961 0 : switch (level) {
7962 0 : case 1:
7963 0 : result = fill_printer_driver_info1(info, &info[count+i].info1,
7964 : driver, servername);
7965 0 : break;
7966 0 : case 2:
7967 0 : result = fill_printer_driver_info2(info, &info[count+i].info2,
7968 : driver, servername);
7969 0 : break;
7970 0 : case 3:
7971 0 : result = fill_printer_driver_info3(info, &info[count+i].info3,
7972 : driver, servername);
7973 0 : break;
7974 0 : case 4:
7975 0 : result = fill_printer_driver_info4(info, &info[count+i].info4,
7976 : driver, servername);
7977 0 : break;
7978 0 : case 5:
7979 0 : result = fill_printer_driver_info5(info, &info[count+i].info5,
7980 : driver, servername);
7981 0 : break;
7982 0 : case 6:
7983 0 : result = fill_printer_driver_info6(info, &info[count+i].info6,
7984 : driver, servername);
7985 0 : break;
7986 0 : case 8:
7987 0 : result = fill_printer_driver_info8(info, &info[count+i].info8,
7988 : driver, servername);
7989 0 : break;
7990 0 : default:
7991 0 : result = WERR_INVALID_LEVEL;
7992 0 : break;
7993 : }
7994 :
7995 0 : TALLOC_FREE(driver);
7996 :
7997 0 : if (!W_ERROR_IS_OK(result)) {
7998 0 : goto out;
7999 : }
8000 : }
8001 :
8002 1840 : count += num_drivers;
8003 1840 : TALLOC_FREE(drivers);
8004 : }
8005 :
8006 460 : out:
8007 460 : if (W_ERROR_IS_OK(result)) {
8008 460 : *info_p = talloc_move(mem_ctx, &info);
8009 460 : *count_p = count;
8010 : }
8011 :
8012 460 : talloc_free(tmp_ctx);
8013 460 : return result;
8014 : }
8015 :
8016 : /****************************************************************************
8017 : Enumerates all printer drivers by level.
8018 : ****************************************************************************/
8019 :
8020 108 : static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
8021 : const struct auth_session_info *session_info,
8022 : struct messaging_context *msg_ctx,
8023 : const char *servername,
8024 : const char *architecture,
8025 : uint32_t level,
8026 : union spoolss_DriverInfo **info_p,
8027 : uint32_t *count_p)
8028 : {
8029 0 : uint32_t a,i;
8030 108 : WERROR result = WERR_OK;
8031 :
8032 108 : if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
8033 :
8034 440 : for (a=0; archi_table[a].long_archi != NULL; a++) {
8035 :
8036 396 : union spoolss_DriverInfo *info = NULL;
8037 396 : uint32_t count = 0;
8038 :
8039 396 : result = enumprinterdrivers_level_by_architecture(mem_ctx,
8040 : session_info,
8041 : msg_ctx,
8042 : servername,
8043 396 : archi_table[a].long_archi,
8044 : level,
8045 : &info,
8046 : &count);
8047 396 : if (!W_ERROR_IS_OK(result)) {
8048 0 : continue;
8049 : }
8050 :
8051 396 : for (i=0; i < count; i++) {
8052 0 : ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
8053 : info[i], info_p, count_p);
8054 : }
8055 : }
8056 :
8057 44 : return result;
8058 : }
8059 :
8060 64 : return enumprinterdrivers_level_by_architecture(mem_ctx,
8061 : session_info,
8062 : msg_ctx,
8063 : servername,
8064 : architecture,
8065 : level,
8066 : info_p,
8067 : count_p);
8068 : }
8069 :
8070 : /****************************************************************
8071 : _spoolss_EnumPrinterDrivers
8072 : ****************************************************************/
8073 :
8074 108 : WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
8075 : struct spoolss_EnumPrinterDrivers *r)
8076 : {
8077 0 : const char *cservername;
8078 0 : WERROR result;
8079 :
8080 : /* that's an [in out] buffer */
8081 :
8082 108 : if (!r->in.buffer && (r->in.offered != 0)) {
8083 0 : return WERR_INVALID_PARAMETER;
8084 : }
8085 :
8086 108 : DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
8087 :
8088 108 : *r->out.needed = 0;
8089 108 : *r->out.count = 0;
8090 108 : *r->out.info = NULL;
8091 :
8092 108 : cservername = canon_servername(r->in.server);
8093 :
8094 108 : if (!is_myname_or_ipaddr(cservername)) {
8095 0 : return WERR_UNKNOWN_PRINTER_DRIVER;
8096 : }
8097 :
8098 108 : result = enumprinterdrivers_level(p->mem_ctx,
8099 : get_session_info_system(),
8100 : p->msg_ctx,
8101 : cservername,
8102 : r->in.environment,
8103 : r->in.level,
8104 : r->out.info,
8105 : r->out.count);
8106 108 : if (!W_ERROR_IS_OK(result)) {
8107 0 : return result;
8108 : }
8109 :
8110 108 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8111 : spoolss_EnumPrinterDrivers,
8112 : *r->out.info, r->in.level,
8113 : *r->out.count);
8114 108 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8115 108 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8116 :
8117 108 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8118 : }
8119 :
8120 : /****************************************************************
8121 : _spoolss_EnumForms
8122 : ****************************************************************/
8123 :
8124 560 : WERROR _spoolss_EnumForms(struct pipes_struct *p,
8125 : struct spoolss_EnumForms *r)
8126 : {
8127 0 : WERROR result;
8128 :
8129 560 : *r->out.count = 0;
8130 560 : *r->out.needed = 0;
8131 560 : *r->out.info = NULL;
8132 :
8133 : /* that's an [in out] buffer */
8134 :
8135 560 : if (!r->in.buffer && (r->in.offered != 0) ) {
8136 0 : return WERR_INVALID_PARAMETER;
8137 : }
8138 :
8139 560 : DEBUG(4,("_spoolss_EnumForms\n"));
8140 560 : DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
8141 560 : DEBUGADD(5,("Info level [%d]\n", r->in.level));
8142 :
8143 560 : switch (r->in.level) {
8144 536 : case 1:
8145 536 : result = winreg_printer_enumforms1_internal(p->mem_ctx,
8146 : get_session_info_system(),
8147 : p->msg_ctx,
8148 : r->out.count,
8149 : r->out.info);
8150 536 : break;
8151 24 : default:
8152 24 : result = WERR_INVALID_LEVEL;
8153 24 : break;
8154 : }
8155 :
8156 560 : if (!W_ERROR_IS_OK(result)) {
8157 24 : return result;
8158 : }
8159 :
8160 536 : if (*r->out.count == 0) {
8161 0 : return WERR_NO_MORE_ITEMS;
8162 : }
8163 :
8164 536 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8165 : spoolss_EnumForms,
8166 : *r->out.info, r->in.level,
8167 : *r->out.count);
8168 536 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8169 536 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8170 :
8171 536 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8172 : }
8173 :
8174 : /****************************************************************
8175 : _spoolss_GetForm
8176 : ****************************************************************/
8177 :
8178 5040 : WERROR _spoolss_GetForm(struct pipes_struct *p,
8179 : struct spoolss_GetForm *r)
8180 : {
8181 0 : WERROR result;
8182 :
8183 : /* that's an [in out] buffer */
8184 :
8185 5040 : if (!r->in.buffer && (r->in.offered != 0)) {
8186 0 : TALLOC_FREE(r->out.info);
8187 0 : return WERR_INVALID_PARAMETER;
8188 : }
8189 :
8190 5040 : DEBUG(4,("_spoolss_GetForm\n"));
8191 5040 : DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
8192 5040 : DEBUGADD(5,("Info level [%d]\n", r->in.level));
8193 :
8194 5040 : switch (r->in.level) {
8195 5040 : case 1:
8196 5040 : result = winreg_printer_getform1_internal(p->mem_ctx,
8197 : get_session_info_system(),
8198 : p->msg_ctx,
8199 : r->in.form_name,
8200 5040 : &r->out.info->info1);
8201 5040 : break;
8202 0 : default:
8203 0 : result = WERR_INVALID_LEVEL;
8204 0 : break;
8205 : }
8206 :
8207 5040 : if (!W_ERROR_IS_OK(result)) {
8208 0 : TALLOC_FREE(r->out.info);
8209 0 : return result;
8210 : }
8211 :
8212 5040 : *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
8213 : r->out.info, r->in.level);
8214 5040 : r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8215 :
8216 5040 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8217 : }
8218 :
8219 : /****************************************************************************
8220 : ****************************************************************************/
8221 :
8222 8 : static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
8223 : struct spoolss_PortInfo1 *r,
8224 : const char *name)
8225 : {
8226 8 : r->port_name = talloc_strdup(mem_ctx, name);
8227 8 : W_ERROR_HAVE_NO_MEMORY(r->port_name);
8228 :
8229 8 : return WERR_OK;
8230 : }
8231 :
8232 : /****************************************************************************
8233 : TODO: This probably needs distinguish between TCP/IP and Local ports
8234 : somehow.
8235 : ****************************************************************************/
8236 :
8237 16 : static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
8238 : struct spoolss_PortInfo2 *r,
8239 : const char *name)
8240 : {
8241 16 : r->port_name = talloc_strdup(mem_ctx, name);
8242 16 : W_ERROR_HAVE_NO_MEMORY(r->port_name);
8243 :
8244 16 : r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
8245 16 : W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8246 :
8247 16 : r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
8248 16 : W_ERROR_HAVE_NO_MEMORY(r->description);
8249 :
8250 16 : r->port_type = SPOOLSS_PORT_TYPE_WRITE;
8251 16 : r->reserved = 0;
8252 :
8253 16 : return WERR_OK;
8254 : }
8255 :
8256 :
8257 : /****************************************************************************
8258 : wrapper around the enum ports command
8259 : ****************************************************************************/
8260 :
8261 24 : static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
8262 : {
8263 0 : const struct loadparm_substitution *lp_sub =
8264 24 : loadparm_s3_global_substitution();
8265 24 : char *cmd = lp_enumports_command(talloc_tos(), lp_sub);
8266 24 : char **qlines = NULL;
8267 24 : char *command = NULL;
8268 0 : int numlines;
8269 0 : int ret;
8270 0 : int fd;
8271 :
8272 24 : *count = 0;
8273 24 : *lines = NULL;
8274 :
8275 : /* if no hook then just fill in the default port */
8276 :
8277 24 : if ( !*cmd ) {
8278 24 : if (!(qlines = talloc_array( NULL, char*, 2 ))) {
8279 0 : return WERR_NOT_ENOUGH_MEMORY;
8280 : }
8281 24 : if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
8282 0 : TALLOC_FREE(qlines);
8283 0 : return WERR_NOT_ENOUGH_MEMORY;
8284 : }
8285 24 : qlines[1] = NULL;
8286 24 : numlines = 1;
8287 : }
8288 : else {
8289 : /* we have a valid enumport command */
8290 :
8291 0 : command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
8292 0 : if (!command) {
8293 0 : return WERR_NOT_ENOUGH_MEMORY;
8294 : }
8295 :
8296 0 : DEBUG(10,("Running [%s]\n", command));
8297 0 : ret = smbrun(command, &fd, NULL);
8298 0 : DEBUG(10,("Returned [%d]\n", ret));
8299 0 : TALLOC_FREE(command);
8300 0 : if (ret != 0) {
8301 0 : if (fd != -1) {
8302 0 : close(fd);
8303 : }
8304 0 : return WERR_ACCESS_DENIED;
8305 : }
8306 :
8307 0 : numlines = 0;
8308 0 : qlines = fd_lines_load(fd, &numlines, 0, NULL);
8309 0 : DEBUGADD(10,("Lines returned = [%d]\n", numlines));
8310 0 : close(fd);
8311 : }
8312 :
8313 24 : *count = numlines;
8314 24 : *lines = qlines;
8315 :
8316 24 : return WERR_OK;
8317 : }
8318 :
8319 : /****************************************************************************
8320 : enumports level 1.
8321 : ****************************************************************************/
8322 :
8323 8 : static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
8324 : union spoolss_PortInfo **info_p,
8325 : uint32_t *count)
8326 : {
8327 8 : union spoolss_PortInfo *info = NULL;
8328 8 : int i=0;
8329 8 : WERROR result = WERR_OK;
8330 8 : char **qlines = NULL;
8331 8 : int numlines = 0;
8332 :
8333 8 : result = enumports_hook(talloc_tos(), &numlines, &qlines );
8334 8 : if (!W_ERROR_IS_OK(result)) {
8335 0 : goto out;
8336 : }
8337 :
8338 8 : if (numlines) {
8339 8 : info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8340 8 : if (!info) {
8341 0 : DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
8342 0 : result = WERR_NOT_ENOUGH_MEMORY;
8343 0 : goto out;
8344 : }
8345 :
8346 16 : for (i=0; i<numlines; i++) {
8347 8 : DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8348 8 : result = fill_port_1(info, &info[i].info1, qlines[i]);
8349 8 : if (!W_ERROR_IS_OK(result)) {
8350 0 : goto out;
8351 : }
8352 : }
8353 : }
8354 8 : TALLOC_FREE(qlines);
8355 :
8356 0 : out:
8357 8 : if (!W_ERROR_IS_OK(result)) {
8358 0 : TALLOC_FREE(info);
8359 0 : TALLOC_FREE(qlines);
8360 0 : *count = 0;
8361 0 : *info_p = NULL;
8362 0 : return result;
8363 : }
8364 :
8365 8 : *info_p = info;
8366 8 : *count = numlines;
8367 :
8368 8 : return WERR_OK;
8369 : }
8370 :
8371 : /****************************************************************************
8372 : enumports level 2.
8373 : ****************************************************************************/
8374 :
8375 16 : static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
8376 : union spoolss_PortInfo **info_p,
8377 : uint32_t *count)
8378 : {
8379 16 : union spoolss_PortInfo *info = NULL;
8380 16 : int i=0;
8381 16 : WERROR result = WERR_OK;
8382 16 : char **qlines = NULL;
8383 16 : int numlines = 0;
8384 :
8385 16 : result = enumports_hook(talloc_tos(), &numlines, &qlines );
8386 16 : if (!W_ERROR_IS_OK(result)) {
8387 0 : goto out;
8388 : }
8389 :
8390 16 : if (numlines) {
8391 16 : info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8392 16 : if (!info) {
8393 0 : DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
8394 0 : result = WERR_NOT_ENOUGH_MEMORY;
8395 0 : goto out;
8396 : }
8397 :
8398 32 : for (i=0; i<numlines; i++) {
8399 16 : DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8400 16 : result = fill_port_2(info, &info[i].info2, qlines[i]);
8401 16 : if (!W_ERROR_IS_OK(result)) {
8402 0 : goto out;
8403 : }
8404 : }
8405 : }
8406 16 : TALLOC_FREE(qlines);
8407 :
8408 0 : out:
8409 16 : if (!W_ERROR_IS_OK(result)) {
8410 0 : TALLOC_FREE(info);
8411 0 : TALLOC_FREE(qlines);
8412 0 : *count = 0;
8413 0 : *info_p = NULL;
8414 0 : return result;
8415 : }
8416 :
8417 16 : *info_p = info;
8418 16 : *count = numlines;
8419 :
8420 16 : return WERR_OK;
8421 : }
8422 :
8423 : /****************************************************************
8424 : _spoolss_EnumPorts
8425 : ****************************************************************/
8426 :
8427 24 : WERROR _spoolss_EnumPorts(struct pipes_struct *p,
8428 : struct spoolss_EnumPorts *r)
8429 : {
8430 0 : WERROR result;
8431 :
8432 : /* that's an [in out] buffer */
8433 :
8434 24 : if (!r->in.buffer && (r->in.offered != 0)) {
8435 0 : return WERR_INVALID_PARAMETER;
8436 : }
8437 :
8438 24 : DEBUG(4,("_spoolss_EnumPorts\n"));
8439 :
8440 24 : *r->out.count = 0;
8441 24 : *r->out.needed = 0;
8442 24 : *r->out.info = NULL;
8443 :
8444 24 : switch (r->in.level) {
8445 8 : case 1:
8446 8 : result = enumports_level_1(p->mem_ctx, r->out.info,
8447 : r->out.count);
8448 8 : break;
8449 16 : case 2:
8450 16 : result = enumports_level_2(p->mem_ctx, r->out.info,
8451 : r->out.count);
8452 16 : break;
8453 0 : default:
8454 0 : return WERR_INVALID_LEVEL;
8455 : }
8456 :
8457 24 : if (!W_ERROR_IS_OK(result)) {
8458 0 : return result;
8459 : }
8460 :
8461 24 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8462 : spoolss_EnumPorts,
8463 : *r->out.info, r->in.level,
8464 : *r->out.count);
8465 24 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8466 24 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8467 :
8468 24 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8469 : }
8470 :
8471 : /****************************************************************************
8472 : ****************************************************************************/
8473 :
8474 96 : static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
8475 : const char *server,
8476 : struct spoolss_SetPrinterInfoCtr *info_ctr,
8477 : struct spoolss_DeviceMode *devmode,
8478 : struct security_descriptor *secdesc,
8479 : struct spoolss_UserLevelCtr *user_ctr,
8480 : struct policy_handle *handle)
8481 : {
8482 96 : struct dcesrv_call_state *dce_call = p->dce_call;
8483 96 : struct dcesrv_connection *dcesrv_conn = dce_call->conn;
8484 0 : const struct tsocket_address *remote_address =
8485 96 : dcesrv_connection_get_remote_address(dcesrv_conn);
8486 0 : struct auth_session_info *session_info =
8487 96 : dcesrv_call_session_info(dce_call);
8488 96 : struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8489 96 : uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8490 0 : const struct loadparm_substitution *lp_sub =
8491 96 : loadparm_s3_global_substitution();
8492 0 : int snum;
8493 96 : WERROR err = WERR_OK;
8494 :
8495 : /* samba does not have a concept of local, non-shared printers yet, so
8496 : * make sure we always setup sharename - gd */
8497 96 : if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8498 96 : (info2->printername != NULL && info2->printername[0] != '\0')) {
8499 80 : DEBUG(5, ("spoolss_addprinterex_level_2: "
8500 : "no sharename has been set, setting printername %s as sharename\n",
8501 : info2->printername));
8502 80 : info2->sharename = info2->printername;
8503 : }
8504 :
8505 : /* check to see if the printer already exists */
8506 96 : if ((snum = print_queue_snum(info2->sharename)) != -1) {
8507 16 : DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8508 : info2->sharename));
8509 16 : return WERR_PRINTER_ALREADY_EXISTS;
8510 : }
8511 :
8512 80 : if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8513 80 : if ((snum = print_queue_snum(info2->printername)) != -1) {
8514 0 : DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8515 : info2->printername));
8516 0 : return WERR_PRINTER_ALREADY_EXISTS;
8517 : }
8518 : }
8519 :
8520 : /* validate printer info struct */
8521 80 : if (!info2->printername || strlen(info2->printername) == 0) {
8522 16 : return WERR_INVALID_PRINTER_NAME;
8523 : }
8524 64 : if (!info2->portname || strlen(info2->portname) == 0) {
8525 16 : return WERR_UNKNOWN_PORT;
8526 : }
8527 48 : if (!info2->drivername || strlen(info2->drivername) == 0) {
8528 16 : return WERR_UNKNOWN_PRINTER_DRIVER;
8529 : }
8530 32 : if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8531 16 : return WERR_UNKNOWN_PRINTPROCESSOR;
8532 : }
8533 :
8534 : /* FIXME!!! smbd should check to see if the driver is installed before
8535 : trying to add a printer like this --jerry */
8536 :
8537 16 : if (*lp_addprinter_command(talloc_tos(), lp_sub) ) {
8538 0 : char *raddr;
8539 :
8540 16 : raddr = tsocket_address_inet_addr_string(remote_address,
8541 : p->mem_ctx);
8542 16 : if (raddr == NULL) {
8543 0 : return WERR_NOT_ENOUGH_MEMORY;
8544 : }
8545 :
8546 16 : if ( !add_printer_hook(p->mem_ctx, session_info->security_token,
8547 : info2, raddr,
8548 : p->msg_ctx) ) {
8549 0 : return WERR_ACCESS_DENIED;
8550 : }
8551 : } else {
8552 0 : DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8553 : "smb.conf parameter \"addprinter command\" is defined. This "
8554 : "parameter must exist for this call to succeed\n",
8555 : info2->sharename ));
8556 : }
8557 :
8558 16 : if ((snum = print_queue_snum(info2->sharename)) == -1) {
8559 0 : return WERR_ACCESS_DENIED;
8560 : }
8561 :
8562 : /* you must be a printer admin to add a new printer */
8563 16 : if (!W_ERROR_IS_OK(print_access_check(session_info,
8564 : p->msg_ctx,
8565 : snum,
8566 : PRINTER_ACCESS_ADMINISTER))) {
8567 0 : return WERR_ACCESS_DENIED;
8568 : }
8569 :
8570 : /*
8571 : * Do sanity check on the requested changes for Samba.
8572 : */
8573 :
8574 16 : if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8575 0 : return WERR_INVALID_PARAMETER;
8576 : }
8577 :
8578 16 : if (devmode == NULL) {
8579 16 : info2_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
8580 : }
8581 :
8582 16 : err = update_dsspooler(p->mem_ctx,
8583 : get_session_info_system(),
8584 : p->msg_ctx,
8585 : 0,
8586 : info2,
8587 : NULL);
8588 16 : if (!W_ERROR_IS_OK(err)) {
8589 0 : return err;
8590 : }
8591 :
8592 16 : err = winreg_update_printer_internal(p->mem_ctx,
8593 : get_session_info_system(),
8594 : p->msg_ctx,
8595 : info2->sharename,
8596 : info2_mask,
8597 : info2,
8598 : devmode,
8599 : secdesc);
8600 16 : if (!W_ERROR_IS_OK(err)) {
8601 0 : return err;
8602 : }
8603 :
8604 16 : err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8605 16 : if (!W_ERROR_IS_OK(err)) {
8606 : /* Handle open failed - remove addition. */
8607 0 : ZERO_STRUCTP(handle);
8608 0 : return err;
8609 : }
8610 :
8611 16 : return WERR_OK;
8612 : }
8613 :
8614 : /****************************************************************
8615 : _spoolss_AddPrinterEx
8616 : ****************************************************************/
8617 :
8618 96 : WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8619 : struct spoolss_AddPrinterEx *r)
8620 : {
8621 96 : switch (r->in.info_ctr->level) {
8622 0 : case 1:
8623 : /* we don't handle yet */
8624 : /* but I know what to do ... */
8625 0 : return WERR_INVALID_LEVEL;
8626 96 : case 2:
8627 96 : return spoolss_addprinterex_level_2(p, r->in.server,
8628 : r->in.info_ctr,
8629 96 : r->in.devmode_ctr->devmode,
8630 96 : r->in.secdesc_ctr->sd,
8631 : r->in.userlevel_ctr,
8632 : r->out.handle);
8633 0 : default:
8634 0 : return WERR_INVALID_LEVEL;
8635 : }
8636 : }
8637 :
8638 : /****************************************************************
8639 : _spoolss_AddPrinter
8640 : ****************************************************************/
8641 :
8642 72 : WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8643 : struct spoolss_AddPrinter *r)
8644 : {
8645 0 : struct spoolss_AddPrinterEx a;
8646 0 : struct spoolss_UserLevelCtr userlevel_ctr;
8647 :
8648 72 : ZERO_STRUCT(userlevel_ctr);
8649 :
8650 72 : userlevel_ctr.level = 1;
8651 :
8652 72 : a.in.server = r->in.server;
8653 72 : a.in.info_ctr = r->in.info_ctr;
8654 72 : a.in.devmode_ctr = r->in.devmode_ctr;
8655 72 : a.in.secdesc_ctr = r->in.secdesc_ctr;
8656 72 : a.in.userlevel_ctr = &userlevel_ctr;
8657 72 : a.out.handle = r->out.handle;
8658 :
8659 72 : return _spoolss_AddPrinterEx(p, &a);
8660 : }
8661 :
8662 : /****************************************************************
8663 : _spoolss_AddPrinterDriverEx
8664 : ****************************************************************/
8665 :
8666 0 : WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8667 : struct spoolss_AddPrinterDriverEx *r)
8668 : {
8669 0 : struct dcesrv_call_state *dce_call = p->dce_call;
8670 0 : struct auth_session_info *session_info =
8671 0 : dcesrv_call_session_info(dce_call);
8672 0 : WERROR err = WERR_OK;
8673 0 : const char *driver_name = NULL;
8674 0 : const char *driver_directory = NULL;
8675 0 : uint32_t version;
8676 :
8677 : /*
8678 : * we only support the semantics of AddPrinterDriver()
8679 : * i.e. only copy files that are newer than existing ones
8680 : */
8681 :
8682 0 : if (r->in.flags == 0) {
8683 0 : return WERR_INVALID_PARAMETER;
8684 : }
8685 :
8686 0 : if (!(r->in.flags & APD_COPY_ALL_FILES) &&
8687 0 : !(r->in.flags & APD_COPY_NEW_FILES)) {
8688 0 : return WERR_ACCESS_DENIED;
8689 : }
8690 :
8691 : /* FIXME */
8692 0 : if (r->in.info_ctr->level != 3 &&
8693 0 : r->in.info_ctr->level != 6 &&
8694 0 : r->in.info_ctr->level != 8) {
8695 0 : DEBUG(0,("%s: level %d not yet implemented\n", __func__,
8696 : r->in.info_ctr->level));
8697 0 : return WERR_INVALID_LEVEL;
8698 : }
8699 :
8700 0 : DEBUG(5,("Cleaning driver's information\n"));
8701 0 : err = clean_up_driver_struct(p->mem_ctx,
8702 : session_info,
8703 0 : r->in.info_ctr,
8704 : r->in.flags,
8705 : &driver_directory);
8706 0 : if (!W_ERROR_IS_OK(err)) {
8707 0 : DBG_ERR("clean_up_driver_struct failed - %s\n",
8708 : win_errstr(err));
8709 0 : goto done;
8710 : }
8711 :
8712 0 : DEBUG(5,("Moving driver to final destination\n"));
8713 0 : err = move_driver_to_download_area(session_info,
8714 0 : r->in.info_ctr,
8715 : driver_directory);
8716 0 : if (!W_ERROR_IS_OK(err)) {
8717 0 : DBG_ERR("move_driver_to_download_area failed - %s\n",
8718 : win_errstr(err));
8719 0 : goto done;
8720 : }
8721 :
8722 0 : err = winreg_add_driver_internal(p->mem_ctx,
8723 : get_session_info_system(),
8724 : p->msg_ctx,
8725 : r->in.info_ctr,
8726 : &driver_name,
8727 : &version);
8728 0 : if (!W_ERROR_IS_OK(err)) {
8729 0 : DBG_ERR("winreg_add_driver_internal failed - %s\n",
8730 : win_errstr(err));
8731 0 : goto done;
8732 : }
8733 :
8734 : /*
8735 : * I think this is where the DrvUpgradePrinter() hook would be
8736 : * be called in a driver's interface DLL on a Windows NT 4.0/2k
8737 : * server. Right now, we just need to send ourselves a message
8738 : * to update each printer bound to this driver. --jerry
8739 : */
8740 :
8741 0 : if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8742 0 : DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8743 : __func__, driver_name));
8744 : }
8745 :
8746 0 : done:
8747 0 : return err;
8748 : }
8749 :
8750 : /****************************************************************
8751 : _spoolss_AddPrinterDriver
8752 : ****************************************************************/
8753 :
8754 0 : WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8755 : struct spoolss_AddPrinterDriver *r)
8756 : {
8757 0 : struct spoolss_AddPrinterDriverEx a;
8758 :
8759 0 : switch (r->in.info_ctr->level) {
8760 0 : case 2:
8761 : case 3:
8762 : case 4:
8763 : case 5:
8764 0 : break;
8765 0 : default:
8766 0 : return WERR_INVALID_LEVEL;
8767 : }
8768 :
8769 0 : a.in.servername = r->in.servername;
8770 0 : a.in.info_ctr = r->in.info_ctr;
8771 0 : a.in.flags = APD_COPY_NEW_FILES;
8772 :
8773 0 : return _spoolss_AddPrinterDriverEx(p, &a);
8774 : }
8775 :
8776 : /****************************************************************************
8777 : ****************************************************************************/
8778 :
8779 : struct _spoolss_paths {
8780 : int type;
8781 : const char *share;
8782 : const char *dir;
8783 : };
8784 :
8785 : enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8786 :
8787 : static const struct _spoolss_paths spoolss_paths[]= {
8788 : { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8789 : { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8790 : };
8791 :
8792 208 : static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8793 : const char *servername,
8794 : const char *environment,
8795 : int component,
8796 : char **path)
8797 : {
8798 208 : const char *pservername = NULL;
8799 0 : const char *long_archi;
8800 0 : const char *short_archi;
8801 :
8802 208 : *path = NULL;
8803 :
8804 : /* environment may be empty */
8805 208 : if (environment && strlen(environment)) {
8806 208 : long_archi = environment;
8807 : } else {
8808 0 : long_archi = lp_parm_const_string(GLOBAL_SECTION_SNUM,
8809 : "spoolss", "architecture",
8810 : GLOBAL_SPOOLSS_ARCHITECTURE);
8811 : }
8812 :
8813 : /* servername may be empty */
8814 208 : if (servername && strlen(servername)) {
8815 144 : pservername = canon_servername(servername);
8816 :
8817 144 : if (!is_myname_or_ipaddr(pservername)) {
8818 0 : return WERR_INVALID_PARAMETER;
8819 : }
8820 : }
8821 :
8822 208 : if (!(short_archi = get_short_archi(long_archi))) {
8823 0 : return WERR_INVALID_ENVIRONMENT;
8824 : }
8825 :
8826 208 : switch (component) {
8827 208 : case SPOOLSS_PRTPROCS_PATH:
8828 : case SPOOLSS_DRIVER_PATH:
8829 208 : if (pservername) {
8830 144 : *path = talloc_asprintf(mem_ctx,
8831 : "\\\\%s\\%s\\%s",
8832 : pservername,
8833 144 : spoolss_paths[component].share,
8834 : short_archi);
8835 : } else {
8836 64 : *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8837 : SPOOLSS_DEFAULT_SERVER_PATH,
8838 64 : spoolss_paths[component].dir,
8839 : short_archi);
8840 : }
8841 208 : break;
8842 0 : default:
8843 0 : return WERR_INVALID_PARAMETER;
8844 : }
8845 :
8846 208 : if (!*path) {
8847 0 : return WERR_NOT_ENOUGH_MEMORY;
8848 : }
8849 :
8850 208 : return WERR_OK;
8851 : }
8852 :
8853 : /****************************************************************************
8854 : ****************************************************************************/
8855 :
8856 168 : static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8857 : const char *servername,
8858 : const char *environment,
8859 : struct spoolss_DriverDirectoryInfo1 *r)
8860 : {
8861 0 : WERROR werr;
8862 168 : char *path = NULL;
8863 :
8864 168 : werr = compose_spoolss_server_path(mem_ctx,
8865 : servername,
8866 : environment,
8867 : SPOOLSS_DRIVER_PATH,
8868 : &path);
8869 168 : if (!W_ERROR_IS_OK(werr)) {
8870 0 : return werr;
8871 : }
8872 :
8873 168 : DEBUG(4,("printer driver directory: [%s]\n", path));
8874 :
8875 168 : r->directory_name = path;
8876 :
8877 168 : return WERR_OK;
8878 : }
8879 :
8880 : /****************************************************************
8881 : _spoolss_GetPrinterDriverDirectory
8882 : ****************************************************************/
8883 :
8884 168 : WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8885 : struct spoolss_GetPrinterDriverDirectory *r)
8886 : {
8887 0 : WERROR werror;
8888 :
8889 : /* that's an [in out] buffer */
8890 :
8891 168 : if (!r->in.buffer && (r->in.offered != 0)) {
8892 0 : TALLOC_FREE(r->out.info);
8893 0 : return WERR_INVALID_PARAMETER;
8894 : }
8895 :
8896 168 : DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8897 : r->in.level));
8898 :
8899 168 : *r->out.needed = 0;
8900 :
8901 : /* r->in.level is ignored */
8902 :
8903 168 : werror = getprinterdriverdir_level_1(p->mem_ctx,
8904 : r->in.server,
8905 : r->in.environment,
8906 168 : &r->out.info->info1);
8907 168 : if (!W_ERROR_IS_OK(werror)) {
8908 0 : TALLOC_FREE(r->out.info);
8909 0 : return werror;
8910 : }
8911 :
8912 168 : *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8913 : r->out.info, r->in.level);
8914 168 : r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8915 :
8916 168 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8917 : }
8918 :
8919 : /****************************************************************
8920 : _spoolss_EnumPrinterData
8921 : ****************************************************************/
8922 :
8923 152 : WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8924 : struct spoolss_EnumPrinterData *r)
8925 : {
8926 0 : WERROR result;
8927 0 : struct spoolss_EnumPrinterDataEx r2;
8928 0 : uint32_t count;
8929 152 : struct spoolss_PrinterEnumValues *info, *val = NULL;
8930 0 : uint32_t needed;
8931 :
8932 152 : r2.in.handle = r->in.handle;
8933 152 : r2.in.key_name = "PrinterDriverData";
8934 152 : r2.in.offered = 0;
8935 152 : r2.out.count = &count;
8936 152 : r2.out.info = &info;
8937 152 : r2.out.needed = &needed;
8938 :
8939 152 : result = _spoolss_EnumPrinterDataEx(p, &r2);
8940 152 : if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8941 112 : r2.in.offered = needed;
8942 112 : result = _spoolss_EnumPrinterDataEx(p, &r2);
8943 : }
8944 152 : if (!W_ERROR_IS_OK(result)) {
8945 0 : return result;
8946 : }
8947 :
8948 : /*
8949 : * The NT machine wants to know the biggest size of value and data
8950 : *
8951 : * cf: MSDN EnumPrinterData remark section
8952 : */
8953 :
8954 152 : if (!r->in.value_offered && !r->in.data_offered) {
8955 48 : uint32_t biggest_valuesize = 0;
8956 48 : uint32_t biggest_datasize = 0;
8957 0 : int i, name_length;
8958 :
8959 48 : DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8960 :
8961 132 : for (i=0; i<count; i++) {
8962 :
8963 84 : name_length = strlen(info[i].value_name);
8964 84 : if (strlen(info[i].value_name) > biggest_valuesize) {
8965 28 : biggest_valuesize = name_length;
8966 : }
8967 :
8968 84 : if (info[i].data_length > biggest_datasize) {
8969 28 : biggest_datasize = info[i].data_length;
8970 : }
8971 :
8972 84 : DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8973 : biggest_datasize));
8974 : }
8975 :
8976 : /* the value is an UNICODE string but real_value_size is the length
8977 : in bytes including the trailing 0 */
8978 :
8979 48 : *r->out.value_needed = 2 * (1 + biggest_valuesize);
8980 48 : *r->out.data_needed = biggest_datasize;
8981 :
8982 48 : DEBUG(6,("final values: [%d], [%d]\n",
8983 : *r->out.value_needed, *r->out.data_needed));
8984 :
8985 48 : return WERR_OK;
8986 : }
8987 :
8988 104 : if (r->in.enum_index < count) {
8989 84 : val = &info[r->in.enum_index];
8990 : }
8991 :
8992 104 : if (val == NULL) {
8993 : /* out_value should default to "" or else NT4 has
8994 : problems unmarshalling the response */
8995 :
8996 20 : if (r->in.value_offered) {
8997 20 : *r->out.value_needed = 1;
8998 20 : r->out.value_name = talloc_strdup(r, "");
8999 20 : if (!r->out.value_name) {
9000 0 : return WERR_NOT_ENOUGH_MEMORY;
9001 : }
9002 : } else {
9003 0 : r->out.value_name = NULL;
9004 0 : *r->out.value_needed = 0;
9005 : }
9006 :
9007 : /* the data is counted in bytes */
9008 :
9009 20 : *r->out.data_needed = r->in.data_offered;
9010 :
9011 20 : result = WERR_NO_MORE_ITEMS;
9012 : } else {
9013 : /*
9014 : * the value is:
9015 : * - counted in bytes in the request
9016 : * - counted in UNICODE chars in the max reply
9017 : * - counted in bytes in the real size
9018 : *
9019 : * take a pause *before* coding not *during* coding
9020 : */
9021 :
9022 : /* name */
9023 84 : if (r->in.value_offered) {
9024 84 : r->out.value_name = talloc_strdup(r, val->value_name);
9025 84 : if (!r->out.value_name) {
9026 0 : return WERR_NOT_ENOUGH_MEMORY;
9027 : }
9028 84 : *r->out.value_needed = val->value_name_len;
9029 : } else {
9030 0 : r->out.value_name = NULL;
9031 0 : *r->out.value_needed = 0;
9032 : }
9033 :
9034 : /* type */
9035 :
9036 84 : *r->out.type = val->type;
9037 :
9038 : /* data - counted in bytes */
9039 :
9040 : /*
9041 : * See the section "Dynamically Typed Query Parameters"
9042 : * in MS-RPRN.
9043 : */
9044 :
9045 84 : if (r->out.data && val->data && val->data->data &&
9046 84 : val->data_length && r->in.data_offered) {
9047 84 : memcpy(r->out.data, val->data->data,
9048 84 : MIN(val->data_length,r->in.data_offered));
9049 : }
9050 :
9051 84 : *r->out.data_needed = val->data_length;
9052 :
9053 84 : result = WERR_OK;
9054 : }
9055 :
9056 104 : return result;
9057 : }
9058 :
9059 : /****************************************************************
9060 : _spoolss_SetPrinterData
9061 : ****************************************************************/
9062 :
9063 168 : WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
9064 : struct spoolss_SetPrinterData *r)
9065 : {
9066 0 : struct spoolss_SetPrinterDataEx r2;
9067 :
9068 168 : r2.in.handle = r->in.handle;
9069 168 : r2.in.key_name = "PrinterDriverData";
9070 168 : r2.in.value_name = r->in.value_name;
9071 168 : r2.in.type = r->in.type;
9072 168 : r2.in.data = r->in.data;
9073 168 : r2.in.offered = r->in.offered;
9074 :
9075 168 : return _spoolss_SetPrinterDataEx(p, &r2);
9076 : }
9077 :
9078 : /****************************************************************
9079 : _spoolss_ResetPrinter
9080 : ****************************************************************/
9081 :
9082 0 : WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
9083 : struct spoolss_ResetPrinter *r)
9084 : {
9085 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9086 0 : int snum;
9087 :
9088 0 : DEBUG(5,("_spoolss_ResetPrinter\n"));
9089 :
9090 : /*
9091 : * All we do is to check to see if the handle and queue is valid.
9092 : * This call really doesn't mean anything to us because we only
9093 : * support RAW printing. --jerry
9094 : */
9095 :
9096 0 : if (!Printer) {
9097 0 : DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
9098 : OUR_HANDLE(r->in.handle)));
9099 0 : return WERR_INVALID_HANDLE;
9100 : }
9101 :
9102 0 : if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9103 0 : return WERR_INVALID_HANDLE;
9104 :
9105 :
9106 : /* blindly return success */
9107 0 : return WERR_OK;
9108 : }
9109 :
9110 : /****************************************************************
9111 : _spoolss_DeletePrinterData
9112 : ****************************************************************/
9113 :
9114 168 : WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
9115 : struct spoolss_DeletePrinterData *r)
9116 : {
9117 0 : struct spoolss_DeletePrinterDataEx r2;
9118 :
9119 168 : r2.in.handle = r->in.handle;
9120 168 : r2.in.key_name = "PrinterDriverData";
9121 168 : r2.in.value_name = r->in.value_name;
9122 :
9123 168 : return _spoolss_DeletePrinterDataEx(p, &r2);
9124 : }
9125 :
9126 : /****************************************************************
9127 : _spoolss_AddForm
9128 : ****************************************************************/
9129 :
9130 576 : WERROR _spoolss_AddForm(struct pipes_struct *p,
9131 : struct spoolss_AddForm *r)
9132 : {
9133 576 : struct dcesrv_call_state *dce_call = p->dce_call;
9134 0 : struct auth_session_info *session_info =
9135 576 : dcesrv_call_session_info(dce_call);
9136 0 : struct spoolss_AddFormInfo1 *form;
9137 576 : int snum = -1;
9138 576 : WERROR status = WERR_OK;
9139 576 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9140 0 : struct dcerpc_binding_handle *b;
9141 576 : TALLOC_CTX *tmp_ctx = NULL;
9142 :
9143 576 : DEBUG(5,("_spoolss_AddForm\n"));
9144 :
9145 576 : if (!Printer) {
9146 0 : DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
9147 : OUR_HANDLE(r->in.handle)));
9148 0 : return WERR_INVALID_HANDLE;
9149 : }
9150 :
9151 : /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
9152 : and not a printer admin, then fail */
9153 :
9154 576 : if ((session_info->unix_token->uid != sec_initial_uid()) &&
9155 0 : !security_token_has_privilege(session_info->security_token,
9156 : SEC_PRIV_PRINT_OPERATOR)) {
9157 0 : DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
9158 0 : return WERR_ACCESS_DENIED;
9159 : }
9160 :
9161 576 : if (r->in.info_ctr->level != 1) {
9162 0 : return WERR_INVALID_LEVEL;
9163 : }
9164 :
9165 576 : form = r->in.info_ctr->info.info1;
9166 576 : if (!form) {
9167 0 : return WERR_INVALID_PARAMETER;
9168 : }
9169 :
9170 576 : switch (form->flags) {
9171 480 : case SPOOLSS_FORM_USER:
9172 : case SPOOLSS_FORM_BUILTIN:
9173 : case SPOOLSS_FORM_PRINTER:
9174 480 : break;
9175 96 : default:
9176 96 : return WERR_INVALID_PARAMETER;
9177 : }
9178 :
9179 480 : tmp_ctx = talloc_new(p->mem_ctx);
9180 480 : if (!tmp_ctx) {
9181 0 : return WERR_NOT_ENOUGH_MEMORY;
9182 : }
9183 :
9184 480 : status = winreg_printer_binding_handle(tmp_ctx,
9185 : get_session_info_system(),
9186 : p->msg_ctx,
9187 : &b);
9188 480 : if (!W_ERROR_IS_OK(status)) {
9189 0 : goto done;
9190 : }
9191 :
9192 480 : status = winreg_printer_addform1(tmp_ctx, b, form);
9193 480 : if (!W_ERROR_IS_OK(status)) {
9194 384 : goto done;
9195 : }
9196 :
9197 : /*
9198 : * ChangeID must always be set if this is a printer
9199 : */
9200 96 : if (Printer->printer_type == SPLHND_PRINTER) {
9201 80 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9202 0 : status = WERR_INVALID_HANDLE;
9203 0 : goto done;
9204 : }
9205 :
9206 80 : status = winreg_printer_update_changeid(tmp_ctx, b,
9207 : lp_const_servicename(snum));
9208 : }
9209 :
9210 16 : done:
9211 480 : talloc_free(tmp_ctx);
9212 480 : return status;
9213 : }
9214 :
9215 : /****************************************************************
9216 : _spoolss_DeleteForm
9217 : ****************************************************************/
9218 :
9219 384 : WERROR _spoolss_DeleteForm(struct pipes_struct *p,
9220 : struct spoolss_DeleteForm *r)
9221 : {
9222 384 : struct dcesrv_call_state *dce_call = p->dce_call;
9223 0 : struct auth_session_info *session_info =
9224 384 : dcesrv_call_session_info(dce_call);
9225 384 : const char *form_name = r->in.form_name;
9226 384 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9227 384 : int snum = -1;
9228 384 : WERROR status = WERR_OK;
9229 0 : struct dcerpc_binding_handle *b;
9230 384 : TALLOC_CTX *tmp_ctx = NULL;
9231 :
9232 384 : DEBUG(5,("_spoolss_DeleteForm\n"));
9233 :
9234 384 : if (!Printer) {
9235 0 : DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
9236 : OUR_HANDLE(r->in.handle)));
9237 0 : return WERR_INVALID_HANDLE;
9238 : }
9239 :
9240 384 : if ((session_info->unix_token->uid != sec_initial_uid()) &&
9241 0 : !security_token_has_privilege(session_info->security_token,
9242 : SEC_PRIV_PRINT_OPERATOR)) {
9243 0 : DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
9244 0 : return WERR_ACCESS_DENIED;
9245 : }
9246 :
9247 384 : tmp_ctx = talloc_new(p->mem_ctx);
9248 384 : if (!tmp_ctx) {
9249 0 : return WERR_NOT_ENOUGH_MEMORY;
9250 : }
9251 :
9252 384 : status = winreg_printer_binding_handle(tmp_ctx,
9253 : get_session_info_system(),
9254 : p->msg_ctx,
9255 : &b);
9256 384 : if (!W_ERROR_IS_OK(status)) {
9257 0 : goto done;
9258 : }
9259 :
9260 384 : status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
9261 384 : if (!W_ERROR_IS_OK(status)) {
9262 288 : goto done;
9263 : }
9264 :
9265 : /*
9266 : * ChangeID must always be set if this is a printer
9267 : */
9268 96 : if (Printer->printer_type == SPLHND_PRINTER) {
9269 80 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9270 0 : status = WERR_INVALID_HANDLE;
9271 0 : goto done;
9272 : }
9273 :
9274 80 : status = winreg_printer_update_changeid(tmp_ctx, b,
9275 : lp_const_servicename(snum));
9276 : }
9277 :
9278 16 : done:
9279 384 : talloc_free(tmp_ctx);
9280 384 : return status;
9281 : }
9282 :
9283 : /****************************************************************
9284 : _spoolss_SetForm
9285 : ****************************************************************/
9286 :
9287 80 : WERROR _spoolss_SetForm(struct pipes_struct *p,
9288 : struct spoolss_SetForm *r)
9289 : {
9290 80 : struct dcesrv_call_state *dce_call = p->dce_call;
9291 0 : struct auth_session_info *session_info =
9292 80 : dcesrv_call_session_info(dce_call);
9293 0 : struct spoolss_AddFormInfo1 *form;
9294 80 : const char *form_name = r->in.form_name;
9295 80 : int snum = -1;
9296 80 : WERROR status = WERR_OK;
9297 0 : struct dcerpc_binding_handle *b;
9298 80 : TALLOC_CTX *tmp_ctx = NULL;
9299 :
9300 80 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9301 :
9302 80 : DEBUG(5,("_spoolss_SetForm\n"));
9303 :
9304 80 : if (!Printer) {
9305 0 : DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
9306 : OUR_HANDLE(r->in.handle)));
9307 0 : return WERR_INVALID_HANDLE;
9308 : }
9309 :
9310 : /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
9311 : and not a printer admin, then fail */
9312 :
9313 80 : if ((session_info->unix_token->uid != sec_initial_uid()) &&
9314 0 : !security_token_has_privilege(session_info->security_token,
9315 : SEC_PRIV_PRINT_OPERATOR)) {
9316 0 : DEBUG(2,("_spoolss_SetForm: denied by insufficient permissions.\n"));
9317 0 : return WERR_ACCESS_DENIED;
9318 : }
9319 :
9320 80 : if (r->in.info_ctr->level != 1) {
9321 0 : return WERR_INVALID_LEVEL;
9322 : }
9323 :
9324 80 : form = r->in.info_ctr->info.info1;
9325 80 : if (!form) {
9326 0 : return WERR_INVALID_PARAMETER;
9327 : }
9328 :
9329 80 : tmp_ctx = talloc_new(p->mem_ctx);
9330 80 : if (!tmp_ctx) {
9331 0 : return WERR_NOT_ENOUGH_MEMORY;
9332 : }
9333 :
9334 80 : status = winreg_printer_binding_handle(tmp_ctx,
9335 : get_session_info_system(),
9336 : p->msg_ctx,
9337 : &b);
9338 80 : if (!W_ERROR_IS_OK(status)) {
9339 0 : goto done;
9340 : }
9341 :
9342 80 : status = winreg_printer_setform1(tmp_ctx, b,
9343 : form_name,
9344 : form);
9345 80 : if (!W_ERROR_IS_OK(status)) {
9346 0 : goto done;
9347 : }
9348 :
9349 : /*
9350 : * ChangeID must always be set if this is a printer
9351 : */
9352 80 : if (Printer->printer_type == SPLHND_PRINTER) {
9353 80 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9354 0 : status = WERR_INVALID_HANDLE;
9355 0 : goto done;
9356 : }
9357 :
9358 80 : status = winreg_printer_update_changeid(tmp_ctx, b,
9359 : lp_const_servicename(snum));
9360 : }
9361 :
9362 0 : done:
9363 80 : talloc_free(tmp_ctx);
9364 80 : return status;
9365 : }
9366 :
9367 : /****************************************************************************
9368 : fill_print_processor1
9369 : ****************************************************************************/
9370 :
9371 24 : static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
9372 : struct spoolss_PrintProcessorInfo1 *r,
9373 : const char *print_processor_name)
9374 : {
9375 24 : r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
9376 24 : W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
9377 :
9378 24 : return WERR_OK;
9379 : }
9380 :
9381 : /****************************************************************************
9382 : enumprintprocessors level 1.
9383 : ****************************************************************************/
9384 :
9385 24 : static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
9386 : union spoolss_PrintProcessorInfo **info_p,
9387 : uint32_t *count)
9388 : {
9389 0 : union spoolss_PrintProcessorInfo *info;
9390 0 : WERROR result;
9391 :
9392 24 : info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
9393 24 : W_ERROR_HAVE_NO_MEMORY(info);
9394 :
9395 24 : *count = 1;
9396 :
9397 24 : result = fill_print_processor1(info, &info[0].info1, "winprint");
9398 24 : if (!W_ERROR_IS_OK(result)) {
9399 0 : goto out;
9400 : }
9401 :
9402 24 : out:
9403 24 : if (!W_ERROR_IS_OK(result)) {
9404 0 : TALLOC_FREE(info);
9405 0 : *count = 0;
9406 0 : return result;
9407 : }
9408 :
9409 24 : *info_p = info;
9410 :
9411 24 : return WERR_OK;
9412 : }
9413 :
9414 : /****************************************************************
9415 : _spoolss_EnumPrintProcessors
9416 : ****************************************************************/
9417 :
9418 48 : WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
9419 : struct spoolss_EnumPrintProcessors *r)
9420 : {
9421 0 : WERROR result;
9422 :
9423 : /* that's an [in out] buffer */
9424 :
9425 48 : if (!r->in.buffer && (r->in.offered != 0)) {
9426 0 : return WERR_INVALID_PARAMETER;
9427 : }
9428 :
9429 48 : DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
9430 :
9431 : /*
9432 : * Enumerate the print processors ...
9433 : *
9434 : * Just reply with "winprint", to keep NT happy
9435 : * and I can use my nice printer checker.
9436 : */
9437 :
9438 48 : *r->out.count = 0;
9439 48 : *r->out.needed = 0;
9440 48 : *r->out.info = NULL;
9441 :
9442 48 : if (!get_short_archi(r->in.environment)) {
9443 4 : return WERR_INVALID_ENVIRONMENT;
9444 : }
9445 :
9446 44 : switch (r->in.level) {
9447 24 : case 1:
9448 24 : result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
9449 : r->out.count);
9450 24 : break;
9451 20 : default:
9452 20 : return WERR_INVALID_LEVEL;
9453 : }
9454 :
9455 24 : if (!W_ERROR_IS_OK(result)) {
9456 0 : return result;
9457 : }
9458 :
9459 24 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9460 : spoolss_EnumPrintProcessors,
9461 : *r->out.info, r->in.level,
9462 : *r->out.count);
9463 24 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9464 24 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9465 :
9466 24 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9467 : }
9468 :
9469 : /****************************************************************************
9470 : fill_printprocdatatype1
9471 : ****************************************************************************/
9472 :
9473 16 : static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
9474 : struct spoolss_PrintProcDataTypesInfo1 *r,
9475 : const char *name_array)
9476 : {
9477 16 : r->name_array = talloc_strdup(mem_ctx, name_array);
9478 16 : W_ERROR_HAVE_NO_MEMORY(r->name_array);
9479 :
9480 16 : return WERR_OK;
9481 : }
9482 :
9483 : /****************************************************************************
9484 : enumprintprocdatatypes level 1.
9485 : ****************************************************************************/
9486 :
9487 16 : static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
9488 : union spoolss_PrintProcDataTypesInfo **info_p,
9489 : uint32_t *count)
9490 : {
9491 0 : WERROR result;
9492 0 : union spoolss_PrintProcDataTypesInfo *info;
9493 :
9494 16 : info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
9495 16 : W_ERROR_HAVE_NO_MEMORY(info);
9496 :
9497 16 : *count = 1;
9498 :
9499 16 : result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9500 16 : if (!W_ERROR_IS_OK(result)) {
9501 0 : goto out;
9502 : }
9503 :
9504 16 : out:
9505 16 : if (!W_ERROR_IS_OK(result)) {
9506 0 : TALLOC_FREE(info);
9507 0 : *count = 0;
9508 0 : return result;
9509 : }
9510 :
9511 16 : *info_p = info;
9512 :
9513 16 : return WERR_OK;
9514 : }
9515 :
9516 : /****************************************************************
9517 : _spoolss_EnumPrintProcessorDataTypes
9518 : ****************************************************************/
9519 :
9520 44 : WERROR _spoolss_EnumPrintProcessorDataTypes(struct pipes_struct *p,
9521 : struct spoolss_EnumPrintProcessorDataTypes *r)
9522 : {
9523 0 : WERROR result;
9524 :
9525 : /* that's an [in out] buffer */
9526 :
9527 44 : if (!r->in.buffer && (r->in.offered != 0)) {
9528 0 : return WERR_INVALID_PARAMETER;
9529 : }
9530 :
9531 44 : DEBUG(5,("_spoolss_EnumPrintProcessorDataTypes\n"));
9532 :
9533 44 : *r->out.count = 0;
9534 44 : *r->out.needed = 0;
9535 44 : *r->out.info = NULL;
9536 :
9537 44 : if (r->in.print_processor_name == NULL ||
9538 40 : !strequal(r->in.print_processor_name, "winprint")) {
9539 8 : return WERR_UNKNOWN_PRINTPROCESSOR;
9540 : }
9541 :
9542 36 : switch (r->in.level) {
9543 16 : case 1:
9544 16 : result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9545 : r->out.count);
9546 16 : break;
9547 20 : default:
9548 20 : return WERR_INVALID_LEVEL;
9549 : }
9550 :
9551 16 : if (!W_ERROR_IS_OK(result)) {
9552 0 : return result;
9553 : }
9554 :
9555 16 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9556 : spoolss_EnumPrintProcessorDataTypes,
9557 : *r->out.info, r->in.level,
9558 : *r->out.count);
9559 16 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9560 16 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9561 :
9562 16 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9563 : }
9564 :
9565 : /****************************************************************************
9566 : fill_monitor_1
9567 : ****************************************************************************/
9568 :
9569 16 : static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9570 : struct spoolss_MonitorInfo1 *r,
9571 : const char *monitor_name)
9572 : {
9573 16 : r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9574 16 : W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9575 :
9576 16 : return WERR_OK;
9577 : }
9578 :
9579 : /****************************************************************************
9580 : fill_monitor_2
9581 : ****************************************************************************/
9582 :
9583 16 : static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9584 : struct spoolss_MonitorInfo2 *r,
9585 : const char *monitor_name,
9586 : const char *environment,
9587 : const char *dll_name)
9588 : {
9589 16 : r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9590 16 : W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9591 16 : r->environment = talloc_strdup(mem_ctx, environment);
9592 16 : W_ERROR_HAVE_NO_MEMORY(r->environment);
9593 16 : r->dll_name = talloc_strdup(mem_ctx, dll_name);
9594 16 : W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9595 :
9596 16 : return WERR_OK;
9597 : }
9598 :
9599 : /****************************************************************************
9600 : enumprintmonitors level 1.
9601 : ****************************************************************************/
9602 :
9603 8 : static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9604 : union spoolss_MonitorInfo **info_p,
9605 : uint32_t *count)
9606 : {
9607 0 : union spoolss_MonitorInfo *info;
9608 8 : WERROR result = WERR_OK;
9609 :
9610 8 : info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9611 8 : W_ERROR_HAVE_NO_MEMORY(info);
9612 :
9613 8 : *count = 2;
9614 :
9615 8 : result = fill_monitor_1(info, &info[0].info1,
9616 : SPL_LOCAL_PORT);
9617 8 : if (!W_ERROR_IS_OK(result)) {
9618 0 : goto out;
9619 : }
9620 :
9621 8 : result = fill_monitor_1(info, &info[1].info1,
9622 : SPL_TCPIP_PORT);
9623 8 : if (!W_ERROR_IS_OK(result)) {
9624 0 : goto out;
9625 : }
9626 :
9627 8 : out:
9628 8 : if (!W_ERROR_IS_OK(result)) {
9629 0 : TALLOC_FREE(info);
9630 0 : *count = 0;
9631 0 : return result;
9632 : }
9633 :
9634 8 : *info_p = info;
9635 :
9636 8 : return WERR_OK;
9637 : }
9638 :
9639 : /****************************************************************************
9640 : enumprintmonitors level 2.
9641 : ****************************************************************************/
9642 :
9643 8 : static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9644 : union spoolss_MonitorInfo **info_p,
9645 : uint32_t *count)
9646 : {
9647 0 : union spoolss_MonitorInfo *info;
9648 8 : WERROR result = WERR_OK;
9649 0 : const char *architecture;
9650 :
9651 8 : info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9652 8 : W_ERROR_HAVE_NO_MEMORY(info);
9653 :
9654 8 : *count = 2;
9655 :
9656 8 : architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
9657 : "spoolss",
9658 : "architecture",
9659 : GLOBAL_SPOOLSS_ARCHITECTURE);
9660 :
9661 8 : result = fill_monitor_2(info, &info[0].info2,
9662 : SPL_LOCAL_PORT,
9663 : architecture,
9664 : "localmon.dll");
9665 8 : if (!W_ERROR_IS_OK(result)) {
9666 0 : goto out;
9667 : }
9668 :
9669 8 : result = fill_monitor_2(info, &info[1].info2,
9670 : SPL_TCPIP_PORT,
9671 : architecture,
9672 : "tcpmon.dll");
9673 8 : if (!W_ERROR_IS_OK(result)) {
9674 0 : goto out;
9675 : }
9676 :
9677 8 : out:
9678 8 : if (!W_ERROR_IS_OK(result)) {
9679 0 : TALLOC_FREE(info);
9680 0 : *count = 0;
9681 0 : return result;
9682 : }
9683 :
9684 8 : *info_p = info;
9685 :
9686 8 : return WERR_OK;
9687 : }
9688 :
9689 : /****************************************************************
9690 : _spoolss_EnumMonitors
9691 : ****************************************************************/
9692 :
9693 16 : WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9694 : struct spoolss_EnumMonitors *r)
9695 : {
9696 0 : WERROR result;
9697 :
9698 : /* that's an [in out] buffer */
9699 :
9700 16 : if (!r->in.buffer && (r->in.offered != 0)) {
9701 0 : return WERR_INVALID_PARAMETER;
9702 : }
9703 :
9704 16 : DEBUG(5,("_spoolss_EnumMonitors\n"));
9705 :
9706 : /*
9707 : * Enumerate the print monitors ...
9708 : *
9709 : * Just reply with "Local Port", to keep NT happy
9710 : * and I can use my nice printer checker.
9711 : */
9712 :
9713 16 : *r->out.count = 0;
9714 16 : *r->out.needed = 0;
9715 16 : *r->out.info = NULL;
9716 :
9717 16 : switch (r->in.level) {
9718 8 : case 1:
9719 8 : result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9720 : r->out.count);
9721 8 : break;
9722 8 : case 2:
9723 8 : result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9724 : r->out.count);
9725 8 : break;
9726 0 : default:
9727 0 : return WERR_INVALID_LEVEL;
9728 : }
9729 :
9730 16 : if (!W_ERROR_IS_OK(result)) {
9731 0 : return result;
9732 : }
9733 :
9734 16 : *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9735 : spoolss_EnumMonitors,
9736 : *r->out.info, r->in.level,
9737 : *r->out.count);
9738 16 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9739 16 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9740 :
9741 16 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9742 : }
9743 :
9744 : /****************************************************************************
9745 : ****************************************************************************/
9746 :
9747 128 : static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9748 : const print_queue_struct *queue,
9749 : int count, int snum,
9750 : struct spoolss_PrinterInfo2 *pinfo2,
9751 : uint32_t jobid,
9752 : int sysjob,
9753 : struct spoolss_JobInfo1 *r)
9754 : {
9755 128 : int i = 0;
9756 128 : bool found = false;
9757 :
9758 576 : for (i=0; i<count; i++) {
9759 576 : if (queue[i].sysjob == sysjob) {
9760 128 : found = true;
9761 128 : break;
9762 : }
9763 : }
9764 :
9765 128 : if (found == false) {
9766 : /* NT treats not found as bad param... yet another bad choice */
9767 0 : return WERR_INVALID_PARAMETER;
9768 : }
9769 :
9770 128 : return fill_job_info1(mem_ctx,
9771 : r,
9772 128 : &queue[i],
9773 : jobid,
9774 : i,
9775 : snum,
9776 : pinfo2);
9777 : }
9778 :
9779 : /****************************************************************************
9780 : ****************************************************************************/
9781 :
9782 0 : static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9783 : const print_queue_struct *queue,
9784 : int count, int snum,
9785 : struct spoolss_PrinterInfo2 *pinfo2,
9786 : uint32_t jobid,
9787 : int sysjob,
9788 : struct spoolss_JobInfo2 *r)
9789 : {
9790 0 : int i = 0;
9791 0 : bool found = false;
9792 0 : struct spoolss_DeviceMode *devmode;
9793 0 : WERROR result;
9794 :
9795 0 : for (i=0; i<count; i++) {
9796 0 : if (queue[i].sysjob == sysjob) {
9797 0 : found = true;
9798 0 : break;
9799 : }
9800 : }
9801 :
9802 0 : if (found == false) {
9803 : /* NT treats not found as bad param... yet another bad
9804 : choice */
9805 0 : return WERR_INVALID_PARAMETER;
9806 : }
9807 :
9808 : /*
9809 : * if the print job does not have a DEVMODE associated with it,
9810 : * just use the one for the printer. A NULL devicemode is not
9811 : * a failure condition
9812 : */
9813 :
9814 0 : devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9815 0 : if (!devmode) {
9816 0 : result = spoolss_create_default_devmode(mem_ctx,
9817 : pinfo2->printername,
9818 : &devmode);
9819 0 : if (!W_ERROR_IS_OK(result)) {
9820 0 : DEBUG(3, ("Can't proceed w/o a devmode!\n"));
9821 0 : return result;
9822 : }
9823 : }
9824 :
9825 0 : return fill_job_info2(mem_ctx,
9826 : r,
9827 0 : &queue[i],
9828 : jobid,
9829 : i,
9830 : snum,
9831 : pinfo2,
9832 : devmode);
9833 : }
9834 :
9835 : /****************************************************************
9836 : _spoolss_GetJob
9837 : ****************************************************************/
9838 :
9839 2048 : WERROR _spoolss_GetJob(struct pipes_struct *p,
9840 : struct spoolss_GetJob *r)
9841 : {
9842 2048 : WERROR result = WERR_OK;
9843 2048 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9844 0 : const char *svc_name;
9845 0 : int sysjob;
9846 0 : int snum;
9847 0 : int count;
9848 0 : struct tdb_print_db *pdb;
9849 2048 : print_queue_struct *queue = NULL;
9850 0 : print_status_struct prt_status;
9851 :
9852 : /* that's an [in out] buffer */
9853 :
9854 2048 : if (!r->in.buffer && (r->in.offered != 0)) {
9855 0 : result = WERR_INVALID_PARAMETER;
9856 0 : goto err_jinfo_free;
9857 : }
9858 :
9859 2048 : DEBUG(5,("_spoolss_GetJob\n"));
9860 :
9861 2048 : *r->out.needed = 0;
9862 :
9863 2048 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9864 0 : result = WERR_INVALID_HANDLE;
9865 0 : goto err_jinfo_free;
9866 : }
9867 :
9868 2048 : svc_name = lp_const_servicename(snum);
9869 2048 : if (svc_name == NULL) {
9870 0 : result = WERR_INVALID_PARAMETER;
9871 0 : goto err_jinfo_free;
9872 : }
9873 :
9874 2048 : result = winreg_get_printer_internal(p->mem_ctx,
9875 : get_session_info_system(),
9876 : p->msg_ctx,
9877 : svc_name,
9878 : &pinfo2);
9879 2048 : if (!W_ERROR_IS_OK(result)) {
9880 0 : goto err_jinfo_free;
9881 : }
9882 :
9883 2048 : pdb = get_print_db_byname(svc_name);
9884 2048 : if (pdb == NULL) {
9885 0 : DEBUG(3, ("failed to get print db for svc %s\n", svc_name));
9886 0 : result = WERR_INVALID_PARAMETER;
9887 0 : goto err_pinfo_free;
9888 : }
9889 :
9890 2048 : sysjob = jobid_to_sysjob_pdb(pdb, r->in.job_id);
9891 2048 : release_print_db(pdb);
9892 2048 : if (sysjob == -1) {
9893 1920 : DEBUG(3, ("no sysjob for spoolss jobid %u\n", r->in.job_id));
9894 1920 : result = WERR_INVALID_PARAMETER;
9895 1920 : goto err_pinfo_free;
9896 : }
9897 :
9898 128 : count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9899 :
9900 128 : DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9901 : count, prt_status.status, prt_status.message));
9902 :
9903 128 : switch (r->in.level) {
9904 128 : case 1:
9905 128 : result = getjob_level_1(p->mem_ctx,
9906 : queue, count, snum, pinfo2,
9907 : r->in.job_id, sysjob,
9908 128 : &r->out.info->info1);
9909 128 : break;
9910 0 : case 2:
9911 0 : result = getjob_level_2(p->mem_ctx,
9912 : queue, count, snum, pinfo2,
9913 : r->in.job_id, sysjob,
9914 0 : &r->out.info->info2);
9915 0 : break;
9916 0 : default:
9917 0 : result = WERR_INVALID_LEVEL;
9918 0 : break;
9919 : }
9920 :
9921 128 : SAFE_FREE(queue);
9922 128 : TALLOC_FREE(pinfo2);
9923 :
9924 128 : if (!W_ERROR_IS_OK(result)) {
9925 0 : goto err_jinfo_free;
9926 : }
9927 :
9928 128 : *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9929 : r->in.level);
9930 128 : r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9931 :
9932 128 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9933 :
9934 1920 : err_pinfo_free:
9935 1920 : TALLOC_FREE(pinfo2);
9936 0 : err_jinfo_free:
9937 1920 : TALLOC_FREE(r->out.info);
9938 1920 : return result;
9939 : }
9940 :
9941 : /****************************************************************
9942 : _spoolss_GetPrinterDataEx
9943 : ****************************************************************/
9944 :
9945 3180 : WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9946 : struct spoolss_GetPrinterDataEx *r)
9947 : {
9948 :
9949 3180 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9950 0 : const char *printer;
9951 3180 : int snum = 0;
9952 3180 : WERROR result = WERR_OK;
9953 0 : DATA_BLOB blob;
9954 3180 : enum winreg_Type val_type = REG_NONE;
9955 3180 : uint8_t *val_data = NULL;
9956 3180 : uint32_t val_size = 0;
9957 0 : struct dcerpc_binding_handle *b;
9958 0 : TALLOC_CTX *tmp_ctx;
9959 :
9960 3180 : DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9961 :
9962 3180 : DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9963 : r->in.key_name, r->in.value_name));
9964 :
9965 : /* in case of problem, return some default values */
9966 :
9967 3180 : *r->out.needed = 0;
9968 3180 : *r->out.type = REG_NONE;
9969 :
9970 3180 : tmp_ctx = talloc_new(p->mem_ctx);
9971 3180 : if (!tmp_ctx) {
9972 0 : return WERR_NOT_ENOUGH_MEMORY;
9973 : }
9974 :
9975 3180 : if (!Printer) {
9976 0 : DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9977 : OUR_HANDLE(r->in.handle)));
9978 0 : result = WERR_INVALID_HANDLE;
9979 0 : goto done;
9980 : }
9981 :
9982 : /* Is the handle to a printer or to the server? */
9983 :
9984 3180 : if (Printer->printer_type == SPLHND_SERVER) {
9985 :
9986 0 : union spoolss_PrinterData data;
9987 :
9988 404 : result = getprinterdata_printer_server(tmp_ctx,
9989 : r->in.value_name,
9990 : r->out.type,
9991 : &data);
9992 404 : if (!W_ERROR_IS_OK(result)) {
9993 4 : goto done;
9994 : }
9995 :
9996 400 : result = push_spoolss_PrinterData(tmp_ctx, &blob,
9997 400 : *r->out.type, &data);
9998 400 : if (!W_ERROR_IS_OK(result)) {
9999 0 : goto done;
10000 : }
10001 :
10002 400 : *r->out.needed = blob.length;
10003 :
10004 400 : if (r->in.offered >= *r->out.needed) {
10005 204 : memcpy(r->out.data, blob.data, blob.length);
10006 : }
10007 :
10008 400 : result = WERR_OK;
10009 400 : goto done;
10010 : }
10011 :
10012 : /* check to see if the keyname is valid */
10013 2776 : if (!strlen(r->in.key_name)) {
10014 0 : result = WERR_INVALID_PARAMETER;
10015 0 : goto done;
10016 : }
10017 :
10018 2776 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10019 0 : result = WERR_INVALID_HANDLE;
10020 0 : goto done;
10021 : }
10022 2776 : printer = lp_const_servicename(snum);
10023 :
10024 2776 : result = winreg_printer_binding_handle(tmp_ctx,
10025 : get_session_info_system(),
10026 : p->msg_ctx,
10027 : &b);
10028 2776 : if (!W_ERROR_IS_OK(result)) {
10029 0 : goto done;
10030 : }
10031 :
10032 : /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
10033 3076 : if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
10034 300 : strequal(r->in.value_name, "ChangeId")) {
10035 128 : *r->out.type = REG_DWORD;
10036 128 : *r->out.needed = 4;
10037 128 : if (r->in.offered >= *r->out.needed) {
10038 64 : uint32_t changeid = 0;
10039 :
10040 64 : result = winreg_printer_get_changeid(tmp_ctx, b,
10041 : printer,
10042 : &changeid);
10043 64 : if (!W_ERROR_IS_OK(result)) {
10044 0 : goto done;
10045 : }
10046 :
10047 64 : SIVAL(r->out.data, 0, changeid);
10048 64 : result = WERR_OK;
10049 : }
10050 128 : goto done;
10051 : }
10052 :
10053 2648 : result = winreg_get_printer_dataex(tmp_ctx, b,
10054 : printer,
10055 : r->in.key_name,
10056 : r->in.value_name,
10057 : &val_type,
10058 : &val_data,
10059 : &val_size);
10060 2648 : if (!W_ERROR_IS_OK(result)) {
10061 4 : goto done;
10062 : }
10063 :
10064 2644 : *r->out.needed = val_size;
10065 2644 : *r->out.type = val_type;
10066 :
10067 2644 : if (r->in.offered >= *r->out.needed) {
10068 1340 : memcpy(r->out.data, val_data, val_size);
10069 : }
10070 :
10071 1304 : done:
10072 : /* NOTE: do not replace type when returning WERR_MORE_DATA */
10073 :
10074 3180 : if (W_ERROR_IS_OK(result)) {
10075 3172 : result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
10076 : }
10077 :
10078 3180 : talloc_free(tmp_ctx);
10079 3180 : return result;
10080 : }
10081 :
10082 : /****************************************************************
10083 : _spoolss_SetPrinterDataEx
10084 : ****************************************************************/
10085 :
10086 1368 : WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
10087 : struct spoolss_SetPrinterDataEx *r)
10088 : {
10089 0 : const struct loadparm_substitution *lp_sub =
10090 1368 : loadparm_s3_global_substitution();
10091 1368 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
10092 1368 : int snum = 0;
10093 1368 : WERROR result = WERR_OK;
10094 1368 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10095 0 : char *oid_string;
10096 0 : struct dcerpc_binding_handle *b;
10097 0 : TALLOC_CTX *tmp_ctx;
10098 :
10099 1368 : DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
10100 :
10101 : /* From MSDN documentation of SetPrinterDataEx: pass request to
10102 : SetPrinterData if key is "PrinterDriverData" */
10103 :
10104 1368 : if (!Printer) {
10105 0 : DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
10106 : OUR_HANDLE(r->in.handle)));
10107 0 : return WERR_INVALID_HANDLE;
10108 : }
10109 :
10110 1368 : if (Printer->printer_type == SPLHND_SERVER) {
10111 0 : DEBUG(10,("_spoolss_SetPrinterDataEx: "
10112 : "Not implemented for server handles yet\n"));
10113 0 : return WERR_INVALID_PARAMETER;
10114 : }
10115 :
10116 1368 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10117 0 : return WERR_INVALID_HANDLE;
10118 : }
10119 :
10120 : /*
10121 : * Access check : NT returns "access denied" if you make a
10122 : * SetPrinterData call without the necessary privilege.
10123 : * we were originally returning OK if nothing changed
10124 : * which made Win2k issue **a lot** of SetPrinterData
10125 : * when connecting to a printer --jerry
10126 : */
10127 :
10128 1368 : if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10129 0 : DEBUG(3, ("_spoolss_SetPrinterDataEx: "
10130 : "change denied by handle access permissions\n"));
10131 0 : return WERR_ACCESS_DENIED;
10132 : }
10133 :
10134 1368 : tmp_ctx = talloc_new(p->mem_ctx);
10135 1368 : if (!tmp_ctx) {
10136 0 : return WERR_NOT_ENOUGH_MEMORY;
10137 : }
10138 :
10139 1368 : result = winreg_printer_binding_handle(tmp_ctx,
10140 : get_session_info_system(),
10141 : p->msg_ctx,
10142 : &b);
10143 1368 : if (!W_ERROR_IS_OK(result)) {
10144 0 : goto done;
10145 : }
10146 :
10147 1368 : result = winreg_get_printer(tmp_ctx, b,
10148 1368 : lp_servicename(talloc_tos(), lp_sub, snum),
10149 : &pinfo2);
10150 1368 : if (!W_ERROR_IS_OK(result)) {
10151 0 : goto done;
10152 : }
10153 :
10154 : /* check for OID in valuename */
10155 :
10156 1368 : oid_string = strchr(r->in.value_name, ',');
10157 1368 : if (oid_string) {
10158 0 : *oid_string = '\0';
10159 0 : oid_string++;
10160 : }
10161 :
10162 : /* save the registry data */
10163 :
10164 1368 : result = winreg_set_printer_dataex(tmp_ctx, b,
10165 1368 : pinfo2->sharename,
10166 : r->in.key_name,
10167 : r->in.value_name,
10168 : r->in.type,
10169 : r->in.data,
10170 : r->in.offered);
10171 :
10172 1368 : if (W_ERROR_IS_OK(result)) {
10173 : /* save the OID if one was specified */
10174 1368 : if (oid_string) {
10175 0 : char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
10176 : r->in.key_name, SPOOL_OID_KEY);
10177 0 : if (!str) {
10178 0 : result = WERR_NOT_ENOUGH_MEMORY;
10179 0 : goto done;
10180 : }
10181 :
10182 : /*
10183 : * I'm not checking the status here on purpose. Don't know
10184 : * if this is right, but I'm returning the status from the
10185 : * previous set_printer_dataex() call. I have no idea if
10186 : * this is right. --jerry
10187 : */
10188 0 : winreg_set_printer_dataex(tmp_ctx, b,
10189 0 : pinfo2->sharename,
10190 : str,
10191 : r->in.value_name,
10192 : REG_SZ,
10193 : (uint8_t *) oid_string,
10194 0 : strlen(oid_string) + 1);
10195 : }
10196 :
10197 1368 : result = winreg_printer_update_changeid(tmp_ctx, b,
10198 : lp_const_servicename(snum));
10199 :
10200 : }
10201 :
10202 0 : done:
10203 1368 : talloc_free(tmp_ctx);
10204 1368 : return result;
10205 : }
10206 :
10207 : /****************************************************************
10208 : _spoolss_DeletePrinterDataEx
10209 : ****************************************************************/
10210 :
10211 1368 : WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
10212 : struct spoolss_DeletePrinterDataEx *r)
10213 : {
10214 0 : const char *printer;
10215 1368 : int snum=0;
10216 1368 : WERROR status = WERR_OK;
10217 1368 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10218 :
10219 1368 : DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
10220 :
10221 1368 : if (!Printer) {
10222 0 : DEBUG(2,("_spoolss_DeletePrinterDataEx: "
10223 : "Invalid handle (%s:%u:%u).\n",
10224 : OUR_HANDLE(r->in.handle)));
10225 0 : return WERR_INVALID_HANDLE;
10226 : }
10227 :
10228 1368 : if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10229 0 : DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
10230 : "printer properties change denied by handle\n"));
10231 0 : return WERR_ACCESS_DENIED;
10232 : }
10233 :
10234 1368 : if (!r->in.value_name || !r->in.key_name) {
10235 0 : return WERR_NOT_ENOUGH_MEMORY;
10236 : }
10237 :
10238 1368 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10239 0 : return WERR_INVALID_HANDLE;
10240 : }
10241 1368 : printer = lp_const_servicename(snum);
10242 :
10243 1368 : status = winreg_delete_printer_dataex_internal(p->mem_ctx,
10244 : get_session_info_system(),
10245 : p->msg_ctx,
10246 : printer,
10247 : r->in.key_name,
10248 : r->in.value_name);
10249 1368 : if (W_ERROR_IS_OK(status)) {
10250 1368 : status = winreg_printer_update_changeid_internal(p->mem_ctx,
10251 : get_session_info_system(),
10252 : p->msg_ctx,
10253 : printer);
10254 : }
10255 :
10256 1368 : return status;
10257 : }
10258 :
10259 : /****************************************************************
10260 : _spoolss_EnumPrinterKey
10261 : ****************************************************************/
10262 :
10263 3384 : WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
10264 : struct spoolss_EnumPrinterKey *r)
10265 : {
10266 0 : uint32_t num_keys;
10267 3384 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10268 3384 : int snum = 0;
10269 3384 : WERROR result = WERR_FILE_NOT_FOUND;
10270 3384 : const char **array = NULL;
10271 0 : DATA_BLOB blob;
10272 :
10273 3384 : DEBUG(4,("_spoolss_EnumPrinterKey\n"));
10274 :
10275 3384 : if (!Printer) {
10276 0 : DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
10277 : OUR_HANDLE(r->in.handle)));
10278 0 : return WERR_INVALID_HANDLE;
10279 : }
10280 :
10281 3384 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10282 0 : return WERR_INVALID_HANDLE;
10283 : }
10284 :
10285 3384 : result = winreg_enum_printer_key_internal(p->mem_ctx,
10286 : get_session_info_system(),
10287 : p->msg_ctx,
10288 : lp_const_servicename(snum),
10289 : r->in.key_name,
10290 : &num_keys,
10291 : &array);
10292 3384 : if (!W_ERROR_IS_OK(result)) {
10293 0 : goto done;
10294 : }
10295 :
10296 3384 : if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
10297 0 : result = WERR_NOT_ENOUGH_MEMORY;
10298 0 : goto done;
10299 : }
10300 :
10301 3384 : *r->out._ndr_size = r->in.offered / 2;
10302 3384 : *r->out.needed = blob.length;
10303 :
10304 3384 : if (r->in.offered < *r->out.needed) {
10305 1304 : result = WERR_MORE_DATA;
10306 : } else {
10307 2080 : result = WERR_OK;
10308 2080 : r->out.key_buffer->string_array = array;
10309 : }
10310 :
10311 3384 : done:
10312 3384 : if (!W_ERROR_IS_OK(result)) {
10313 1304 : TALLOC_FREE(array);
10314 1304 : if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
10315 0 : *r->out.needed = 0;
10316 : }
10317 : }
10318 :
10319 3384 : return result;
10320 : }
10321 :
10322 : /****************************************************************
10323 : _spoolss_DeletePrinterKey
10324 : ****************************************************************/
10325 :
10326 216 : WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
10327 : struct spoolss_DeletePrinterKey *r)
10328 : {
10329 216 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10330 216 : int snum=0;
10331 0 : WERROR status;
10332 0 : const char *printer;
10333 0 : struct dcerpc_binding_handle *b;
10334 0 : TALLOC_CTX *tmp_ctx;
10335 :
10336 216 : DEBUG(5,("_spoolss_DeletePrinterKey\n"));
10337 :
10338 216 : if (!Printer) {
10339 0 : DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
10340 : OUR_HANDLE(r->in.handle)));
10341 0 : return WERR_INVALID_HANDLE;
10342 : }
10343 :
10344 : /* if keyname == NULL, return error */
10345 216 : if ( !r->in.key_name )
10346 0 : return WERR_INVALID_PARAMETER;
10347 :
10348 216 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10349 0 : return WERR_INVALID_HANDLE;
10350 : }
10351 :
10352 216 : if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10353 0 : DEBUG(3, ("_spoolss_DeletePrinterKey: "
10354 : "printer properties change denied by handle\n"));
10355 0 : return WERR_ACCESS_DENIED;
10356 : }
10357 :
10358 216 : printer = lp_const_servicename(snum);
10359 :
10360 216 : tmp_ctx = talloc_new(p->mem_ctx);
10361 216 : if (!tmp_ctx) {
10362 0 : return WERR_NOT_ENOUGH_MEMORY;
10363 : }
10364 :
10365 216 : status = winreg_printer_binding_handle(tmp_ctx,
10366 : get_session_info_system(),
10367 : p->msg_ctx,
10368 : &b);
10369 216 : if (!W_ERROR_IS_OK(status)) {
10370 0 : goto done;
10371 : }
10372 :
10373 : /* delete the key and all subkeys */
10374 216 : status = winreg_delete_printer_key(tmp_ctx, b,
10375 : printer,
10376 : r->in.key_name);
10377 216 : if (W_ERROR_IS_OK(status)) {
10378 216 : status = winreg_printer_update_changeid(tmp_ctx, b,
10379 : printer);
10380 : }
10381 :
10382 0 : done:
10383 216 : talloc_free(tmp_ctx);
10384 216 : return status;
10385 : }
10386 :
10387 : /****************************************************************
10388 : _spoolss_EnumPrinterDataEx
10389 : ****************************************************************/
10390 :
10391 2860 : WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
10392 : struct spoolss_EnumPrinterDataEx *r)
10393 : {
10394 2860 : uint32_t count = 0;
10395 2860 : struct spoolss_PrinterEnumValues *info = NULL;
10396 2860 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10397 0 : int snum;
10398 0 : WERROR result;
10399 :
10400 2860 : DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
10401 :
10402 2860 : *r->out.count = 0;
10403 2860 : *r->out.needed = 0;
10404 2860 : *r->out.info = NULL;
10405 :
10406 2860 : if (!Printer) {
10407 0 : DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
10408 : OUR_HANDLE(r->in.handle)));
10409 0 : return WERR_INVALID_HANDLE;
10410 : }
10411 :
10412 : /*
10413 : * first check for a keyname of NULL or "". Win2k seems to send
10414 : * this a lot and we should send back WERR_INVALID_PARAMETER
10415 : * no need to spend time looking up the printer in this case.
10416 : * --jerry
10417 : */
10418 :
10419 2860 : if (!strlen(r->in.key_name)) {
10420 4 : result = WERR_INVALID_PARAMETER;
10421 4 : goto done;
10422 : }
10423 :
10424 2856 : if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10425 0 : return WERR_INVALID_HANDLE;
10426 : }
10427 :
10428 : /* now look for a match on the key name */
10429 2856 : result = winreg_enum_printer_dataex_internal(p->mem_ctx,
10430 : get_session_info_system(),
10431 : p->msg_ctx,
10432 : lp_const_servicename(snum),
10433 : r->in.key_name,
10434 : &count,
10435 : &info);
10436 2856 : if (!W_ERROR_IS_OK(result)) {
10437 0 : goto done;
10438 : }
10439 :
10440 2856 : *r->out.count = count;
10441 2856 : *r->out.info = info;
10442 :
10443 2860 : done:
10444 2860 : if (!W_ERROR_IS_OK(result)) {
10445 4 : return result;
10446 : }
10447 :
10448 2856 : *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
10449 : spoolss_EnumPrinterDataEx,
10450 : *r->out.info,
10451 : *r->out.count);
10452 2856 : *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
10453 2856 : *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
10454 :
10455 2856 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
10456 : }
10457 :
10458 : /****************************************************************************
10459 : ****************************************************************************/
10460 :
10461 40 : static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
10462 : const char *servername,
10463 : const char *environment,
10464 : struct spoolss_PrintProcessorDirectoryInfo1 *r)
10465 : {
10466 0 : WERROR werr;
10467 40 : char *path = NULL;
10468 :
10469 40 : werr = compose_spoolss_server_path(mem_ctx,
10470 : servername,
10471 : environment,
10472 : SPOOLSS_PRTPROCS_PATH,
10473 : &path);
10474 40 : if (!W_ERROR_IS_OK(werr)) {
10475 0 : return werr;
10476 : }
10477 :
10478 40 : DEBUG(4,("print processor directory: [%s]\n", path));
10479 :
10480 40 : r->directory_name = path;
10481 :
10482 40 : return WERR_OK;
10483 : }
10484 :
10485 : /****************************************************************
10486 : _spoolss_GetPrintProcessorDirectory
10487 : ****************************************************************/
10488 :
10489 40 : WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
10490 : struct spoolss_GetPrintProcessorDirectory *r)
10491 : {
10492 0 : WERROR result;
10493 40 : char *prnproc_share = NULL;
10494 40 : bool prnproc_share_exists = false;
10495 0 : int snum;
10496 :
10497 : /* that's an [in out] buffer */
10498 :
10499 40 : if (!r->in.buffer && (r->in.offered != 0)) {
10500 0 : result = WERR_INVALID_PARAMETER;
10501 0 : goto err_info_free;
10502 : }
10503 :
10504 40 : DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
10505 : r->in.level));
10506 :
10507 40 : *r->out.needed = 0;
10508 :
10509 : /* r->in.level is ignored */
10510 :
10511 : /* We always should reply with a local print processor directory so that
10512 : * users are not forced to have a [prnproc$] share on the Samba spoolss
10513 : * server, if users decide to do so, lets announce it though - Guenther */
10514 :
10515 40 : snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
10516 40 : if (!prnproc_share) {
10517 0 : result = WERR_NOT_ENOUGH_MEMORY;
10518 0 : goto err_info_free;
10519 : }
10520 40 : if (snum != -1) {
10521 0 : prnproc_share_exists = true;
10522 : }
10523 :
10524 40 : result = getprintprocessordirectory_level_1(p->mem_ctx,
10525 : prnproc_share_exists ? r->in.server : NULL,
10526 : r->in.environment,
10527 40 : &r->out.info->info1);
10528 40 : if (!W_ERROR_IS_OK(result)) {
10529 0 : goto err_info_free;
10530 : }
10531 :
10532 40 : *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
10533 : r->out.info, r->in.level);
10534 40 : r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10535 :
10536 40 : return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10537 :
10538 0 : err_info_free:
10539 0 : TALLOC_FREE(r->out.info);
10540 0 : return result;
10541 : }
10542 :
10543 : /*******************************************************************
10544 : ********************************************************************/
10545 :
10546 0 : static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10547 : const char *dllname)
10548 : {
10549 0 : enum ndr_err_code ndr_err;
10550 0 : struct spoolss_MonitorUi ui;
10551 :
10552 0 : ui.dll_name = dllname;
10553 :
10554 0 : ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10555 : (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10556 0 : if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10557 0 : NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10558 : }
10559 0 : return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10560 : }
10561 :
10562 : /*******************************************************************
10563 : Streams the monitor UI DLL name in UNICODE
10564 : *******************************************************************/
10565 :
10566 0 : static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10567 : struct security_token *token, DATA_BLOB *in,
10568 : DATA_BLOB *out, uint32_t *needed)
10569 : {
10570 0 : const char *dllname = "tcpmonui.dll";
10571 :
10572 0 : *needed = (strlen(dllname)+1) * 2;
10573 :
10574 0 : if (out->length < *needed) {
10575 0 : return WERR_INSUFFICIENT_BUFFER;
10576 : }
10577 :
10578 0 : if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10579 0 : return WERR_NOT_ENOUGH_MEMORY;
10580 : }
10581 :
10582 0 : return WERR_OK;
10583 : }
10584 :
10585 : /*******************************************************************
10586 : ********************************************************************/
10587 :
10588 0 : static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10589 : struct spoolss_PortData1 *port1,
10590 : const DATA_BLOB *buf)
10591 : {
10592 0 : enum ndr_err_code ndr_err;
10593 0 : ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10594 : (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10595 0 : if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10596 0 : NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10597 : }
10598 0 : return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10599 : }
10600 :
10601 : /*******************************************************************
10602 : ********************************************************************/
10603 :
10604 0 : static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10605 : struct spoolss_PortData2 *port2,
10606 : const DATA_BLOB *buf)
10607 : {
10608 0 : enum ndr_err_code ndr_err;
10609 0 : ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10610 : (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10611 0 : if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10612 0 : NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10613 : }
10614 0 : return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10615 : }
10616 :
10617 : /*******************************************************************
10618 : Create a new TCP/IP port
10619 : *******************************************************************/
10620 :
10621 0 : static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10622 : struct security_token *token, DATA_BLOB *in,
10623 : DATA_BLOB *out, uint32_t *needed)
10624 : {
10625 0 : struct spoolss_PortData1 port1;
10626 0 : struct spoolss_PortData2 port2;
10627 0 : char *device_uri = NULL;
10628 0 : uint32_t version;
10629 :
10630 0 : const char *portname;
10631 0 : const char *hostaddress;
10632 0 : const char *queue;
10633 0 : uint32_t port_number;
10634 0 : uint32_t protocol;
10635 :
10636 : /* peek for spoolss_PortData version */
10637 :
10638 0 : if (!in || (in->length < (128 + 4))) {
10639 0 : return WERR_GEN_FAILURE;
10640 : }
10641 :
10642 0 : version = IVAL(in->data, 128);
10643 :
10644 0 : switch (version) {
10645 0 : case 1:
10646 0 : ZERO_STRUCT(port1);
10647 :
10648 0 : if (!pull_port_data_1(mem_ctx, &port1, in)) {
10649 0 : return WERR_NOT_ENOUGH_MEMORY;
10650 : }
10651 :
10652 0 : portname = port1.portname;
10653 0 : hostaddress = port1.hostaddress;
10654 0 : queue = port1.queue;
10655 0 : protocol = port1.protocol;
10656 0 : port_number = port1.port_number;
10657 :
10658 0 : break;
10659 0 : case 2:
10660 0 : ZERO_STRUCT(port2);
10661 :
10662 0 : if (!pull_port_data_2(mem_ctx, &port2, in)) {
10663 0 : return WERR_NOT_ENOUGH_MEMORY;
10664 : }
10665 :
10666 0 : portname = port2.portname;
10667 0 : hostaddress = port2.hostaddress;
10668 0 : queue = port2.queue;
10669 0 : protocol = port2.protocol;
10670 0 : port_number = port2.port_number;
10671 :
10672 0 : break;
10673 0 : default:
10674 0 : DEBUG(1,("xcvtcp_addport: "
10675 : "unknown version of port_data: %d\n", version));
10676 0 : return WERR_UNKNOWN_PORT;
10677 : }
10678 :
10679 : /* create the device URI and call the add_port_hook() */
10680 :
10681 0 : switch (protocol) {
10682 0 : case PROTOCOL_RAWTCP_TYPE:
10683 0 : device_uri = talloc_asprintf(mem_ctx,
10684 : "socket://%s:%d/", hostaddress,
10685 : port_number);
10686 0 : break;
10687 :
10688 0 : case PROTOCOL_LPR_TYPE:
10689 0 : device_uri = talloc_asprintf(mem_ctx,
10690 : "lpr://%s/%s", hostaddress, queue );
10691 0 : break;
10692 :
10693 0 : default:
10694 0 : return WERR_UNKNOWN_PORT;
10695 : }
10696 :
10697 0 : if (!device_uri) {
10698 0 : return WERR_NOT_ENOUGH_MEMORY;
10699 : }
10700 :
10701 0 : return add_port_hook(mem_ctx, token, portname, device_uri);
10702 : }
10703 :
10704 : /*******************************************************************
10705 : *******************************************************************/
10706 :
10707 : struct xcv_api_table xcvtcp_cmds[] = {
10708 : { "MonitorUI", xcvtcp_monitorui },
10709 : { "AddPort", xcvtcp_addport},
10710 : { NULL, NULL }
10711 : };
10712 :
10713 0 : static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10714 : struct security_token *token, const char *command,
10715 : DATA_BLOB *inbuf,
10716 : DATA_BLOB *outbuf,
10717 : uint32_t *needed )
10718 : {
10719 0 : int i;
10720 :
10721 0 : DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10722 :
10723 0 : for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10724 0 : if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10725 0 : return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10726 : }
10727 :
10728 0 : return WERR_INVALID_FUNCTION;
10729 : }
10730 :
10731 : /*******************************************************************
10732 : *******************************************************************/
10733 : #if 0 /* don't support management using the "Local Port" monitor */
10734 :
10735 : static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10736 : struct security_token *token, DATA_BLOB *in,
10737 : DATA_BLOB *out, uint32_t *needed)
10738 : {
10739 : const char *dllname = "localui.dll";
10740 :
10741 : *needed = (strlen(dllname)+1) * 2;
10742 :
10743 : if (out->length < *needed) {
10744 : return WERR_INSUFFICIENT_BUFFER;
10745 : }
10746 :
10747 : if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10748 : return WERR_NOT_ENOUGH_MEMORY;
10749 : }
10750 :
10751 : return WERR_OK;
10752 : }
10753 :
10754 : /*******************************************************************
10755 : *******************************************************************/
10756 :
10757 : struct xcv_api_table xcvlocal_cmds[] = {
10758 : { "MonitorUI", xcvlocal_monitorui },
10759 : { NULL, NULL }
10760 : };
10761 : #else
10762 : struct xcv_api_table xcvlocal_cmds[] = {
10763 : { NULL, NULL }
10764 : };
10765 : #endif
10766 :
10767 :
10768 :
10769 : /*******************************************************************
10770 : *******************************************************************/
10771 :
10772 0 : static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10773 : struct security_token *token, const char *command,
10774 : DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10775 : uint32_t *needed)
10776 : {
10777 0 : int i;
10778 :
10779 0 : DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10780 :
10781 0 : for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10782 0 : if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10783 0 : return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10784 : }
10785 0 : return WERR_INVALID_FUNCTION;
10786 : }
10787 :
10788 : /****************************************************************
10789 : _spoolss_XcvData
10790 : ****************************************************************/
10791 :
10792 0 : WERROR _spoolss_XcvData(struct pipes_struct *p,
10793 : struct spoolss_XcvData *r)
10794 : {
10795 0 : struct dcesrv_call_state *dce_call = p->dce_call;
10796 0 : struct auth_session_info *session_info =
10797 0 : dcesrv_call_session_info(dce_call);
10798 0 : struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10799 0 : DATA_BLOB out_data = data_blob_null;
10800 0 : WERROR werror;
10801 :
10802 0 : if (!Printer) {
10803 0 : DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10804 : OUR_HANDLE(r->in.handle)));
10805 0 : return WERR_INVALID_HANDLE;
10806 : }
10807 :
10808 : /* Has to be a handle to the TCP/IP port monitor */
10809 :
10810 0 : if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10811 0 : DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10812 0 : return WERR_INVALID_HANDLE;
10813 : }
10814 :
10815 : /* requires administrative access to the server */
10816 :
10817 0 : if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10818 0 : DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10819 0 : return WERR_ACCESS_DENIED;
10820 : }
10821 :
10822 : /* Allocate the outgoing buffer */
10823 :
10824 0 : if (r->in.out_data_size) {
10825 0 : out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10826 0 : if (out_data.data == NULL) {
10827 0 : return WERR_NOT_ENOUGH_MEMORY;
10828 : }
10829 : }
10830 :
10831 0 : switch ( Printer->printer_type ) {
10832 0 : case SPLHND_PORTMON_TCP:
10833 0 : werror = process_xcvtcp_command(p->mem_ctx,
10834 : session_info->security_token,
10835 : r->in.function_name,
10836 : &r->in.in_data, &out_data,
10837 : r->out.needed);
10838 0 : break;
10839 0 : case SPLHND_PORTMON_LOCAL:
10840 0 : werror = process_xcvlocal_command(p->mem_ctx,
10841 : session_info->security_token,
10842 : r->in.function_name,
10843 : &r->in.in_data, &out_data,
10844 : r->out.needed);
10845 0 : break;
10846 0 : default:
10847 0 : werror = WERR_INVALID_PRINT_MONITOR;
10848 : }
10849 :
10850 0 : if (!W_ERROR_IS_OK(werror)) {
10851 0 : return werror;
10852 : }
10853 :
10854 0 : *r->out.status_code = 0;
10855 :
10856 0 : if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10857 0 : memcpy(r->out.out_data, out_data.data,
10858 0 : MIN(r->in.out_data_size, out_data.length));
10859 : }
10860 :
10861 0 : return WERR_OK;
10862 : }
10863 :
10864 : /****************************************************************
10865 : _spoolss_AddPrintProcessor
10866 : ****************************************************************/
10867 :
10868 4 : WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10869 : struct spoolss_AddPrintProcessor *r)
10870 : {
10871 : /* for now, just indicate success and ignore the add. We'll
10872 : automatically set the winprint processor for printer
10873 : entries later. Used to debug the LexMark Optra S 1855 PCL
10874 : driver --jerry */
10875 :
10876 4 : return WERR_OK;
10877 : }
10878 :
10879 : /****************************************************************
10880 : _spoolss_AddPort
10881 : ****************************************************************/
10882 :
10883 4 : WERROR _spoolss_AddPort(struct pipes_struct *p,
10884 : struct spoolss_AddPort *r)
10885 : {
10886 : /* do what w2k3 does */
10887 :
10888 4 : return WERR_NOT_SUPPORTED;
10889 : }
10890 :
10891 : /****************************************************************
10892 : _spoolss_GetPrinterDriver
10893 : ****************************************************************/
10894 :
10895 0 : WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10896 : struct spoolss_GetPrinterDriver *r)
10897 : {
10898 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10899 0 : return WERR_NOT_SUPPORTED;
10900 : }
10901 :
10902 : /****************************************************************
10903 : _spoolss_ReadPrinter
10904 : ****************************************************************/
10905 :
10906 0 : WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10907 : struct spoolss_ReadPrinter *r)
10908 : {
10909 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10910 0 : return WERR_NOT_SUPPORTED;
10911 : }
10912 :
10913 : /****************************************************************
10914 : _spoolss_WaitForPrinterChange
10915 : ****************************************************************/
10916 :
10917 0 : WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10918 : struct spoolss_WaitForPrinterChange *r)
10919 : {
10920 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10921 0 : return WERR_NOT_SUPPORTED;
10922 : }
10923 :
10924 : /****************************************************************
10925 : _spoolss_ConfigurePort
10926 : ****************************************************************/
10927 :
10928 0 : WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10929 : struct spoolss_ConfigurePort *r)
10930 : {
10931 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10932 0 : return WERR_NOT_SUPPORTED;
10933 : }
10934 :
10935 : /****************************************************************
10936 : _spoolss_DeletePort
10937 : ****************************************************************/
10938 :
10939 0 : WERROR _spoolss_DeletePort(struct pipes_struct *p,
10940 : struct spoolss_DeletePort *r)
10941 : {
10942 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10943 0 : return WERR_NOT_SUPPORTED;
10944 : }
10945 :
10946 : /****************************************************************
10947 : _spoolss_CreatePrinterIC
10948 : ****************************************************************/
10949 :
10950 0 : WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10951 : struct spoolss_CreatePrinterIC *r)
10952 : {
10953 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10954 0 : return WERR_NOT_SUPPORTED;
10955 : }
10956 :
10957 : /****************************************************************
10958 : _spoolss_PlayGDIScriptOnPrinterIC
10959 : ****************************************************************/
10960 :
10961 0 : WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10962 : struct spoolss_PlayGDIScriptOnPrinterIC *r)
10963 : {
10964 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10965 0 : return WERR_NOT_SUPPORTED;
10966 : }
10967 :
10968 : /****************************************************************
10969 : _spoolss_DeletePrinterIC
10970 : ****************************************************************/
10971 :
10972 0 : WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10973 : struct spoolss_DeletePrinterIC *r)
10974 : {
10975 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10976 0 : return WERR_NOT_SUPPORTED;
10977 : }
10978 :
10979 : /****************************************************************
10980 : _spoolss_AddPrinterConnection
10981 : ****************************************************************/
10982 :
10983 0 : WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10984 : struct spoolss_AddPrinterConnection *r)
10985 : {
10986 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10987 0 : return WERR_NOT_SUPPORTED;
10988 : }
10989 :
10990 : /****************************************************************
10991 : _spoolss_DeletePrinterConnection
10992 : ****************************************************************/
10993 :
10994 0 : WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10995 : struct spoolss_DeletePrinterConnection *r)
10996 : {
10997 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10998 0 : return WERR_NOT_SUPPORTED;
10999 : }
11000 :
11001 : /****************************************************************
11002 : _spoolss_PrinterMessageBox
11003 : ****************************************************************/
11004 :
11005 0 : WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
11006 : struct spoolss_PrinterMessageBox *r)
11007 : {
11008 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11009 0 : return WERR_NOT_SUPPORTED;
11010 : }
11011 :
11012 : /****************************************************************
11013 : _spoolss_AddMonitor
11014 : ****************************************************************/
11015 :
11016 0 : WERROR _spoolss_AddMonitor(struct pipes_struct *p,
11017 : struct spoolss_AddMonitor *r)
11018 : {
11019 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11020 0 : return WERR_NOT_SUPPORTED;
11021 : }
11022 :
11023 : /****************************************************************
11024 : _spoolss_DeleteMonitor
11025 : ****************************************************************/
11026 :
11027 0 : WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
11028 : struct spoolss_DeleteMonitor *r)
11029 : {
11030 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11031 0 : return WERR_NOT_SUPPORTED;
11032 : }
11033 :
11034 : /****************************************************************
11035 : _spoolss_DeletePrintProcessor
11036 : ****************************************************************/
11037 :
11038 0 : WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
11039 : struct spoolss_DeletePrintProcessor *r)
11040 : {
11041 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11042 0 : return WERR_NOT_SUPPORTED;
11043 : }
11044 :
11045 : /****************************************************************
11046 : _spoolss_AddPrintProvidor
11047 : ****************************************************************/
11048 :
11049 0 : WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
11050 : struct spoolss_AddPrintProvidor *r)
11051 : {
11052 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11053 0 : return WERR_NOT_SUPPORTED;
11054 : }
11055 :
11056 : /****************************************************************
11057 : _spoolss_DeletePrintProvidor
11058 : ****************************************************************/
11059 :
11060 0 : WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
11061 : struct spoolss_DeletePrintProvidor *r)
11062 : {
11063 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11064 0 : return WERR_NOT_SUPPORTED;
11065 : }
11066 :
11067 : /****************************************************************
11068 : _spoolss_FindFirstPrinterChangeNotification
11069 : ****************************************************************/
11070 :
11071 0 : WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
11072 : struct spoolss_FindFirstPrinterChangeNotification *r)
11073 : {
11074 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11075 0 : return WERR_NOT_SUPPORTED;
11076 : }
11077 :
11078 : /****************************************************************
11079 : _spoolss_FindNextPrinterChangeNotification
11080 : ****************************************************************/
11081 :
11082 0 : WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
11083 : struct spoolss_FindNextPrinterChangeNotification *r)
11084 : {
11085 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11086 0 : return WERR_NOT_SUPPORTED;
11087 : }
11088 :
11089 : /****************************************************************
11090 : _spoolss_RouterFindFirstPrinterChangeNotificationOld
11091 : ****************************************************************/
11092 :
11093 0 : WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
11094 : struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
11095 : {
11096 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11097 0 : return WERR_NOT_SUPPORTED;
11098 : }
11099 :
11100 : /****************************************************************
11101 : _spoolss_ReplyOpenPrinter
11102 : ****************************************************************/
11103 :
11104 0 : WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
11105 : struct spoolss_ReplyOpenPrinter *r)
11106 : {
11107 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11108 0 : return WERR_NOT_SUPPORTED;
11109 : }
11110 :
11111 : /****************************************************************
11112 : _spoolss_RouterReplyPrinter
11113 : ****************************************************************/
11114 :
11115 0 : WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
11116 : struct spoolss_RouterReplyPrinter *r)
11117 : {
11118 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11119 0 : return WERR_NOT_SUPPORTED;
11120 : }
11121 :
11122 : /****************************************************************
11123 : _spoolss_ReplyClosePrinter
11124 : ****************************************************************/
11125 :
11126 0 : WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
11127 : struct spoolss_ReplyClosePrinter *r)
11128 : {
11129 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11130 0 : return WERR_NOT_SUPPORTED;
11131 : }
11132 :
11133 : /****************************************************************
11134 : _spoolss_AddPortEx
11135 : ****************************************************************/
11136 :
11137 0 : WERROR _spoolss_AddPortEx(struct pipes_struct *p,
11138 : struct spoolss_AddPortEx *r)
11139 : {
11140 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11141 0 : return WERR_NOT_SUPPORTED;
11142 : }
11143 :
11144 : /****************************************************************
11145 : _spoolss_RouterFindFirstPrinterChangeNotification
11146 : ****************************************************************/
11147 :
11148 0 : WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
11149 : struct spoolss_RouterFindFirstPrinterChangeNotification *r)
11150 : {
11151 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11152 0 : return WERR_NOT_SUPPORTED;
11153 : }
11154 :
11155 : /****************************************************************
11156 : _spoolss_SpoolerInit
11157 : ****************************************************************/
11158 :
11159 0 : WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
11160 : struct spoolss_SpoolerInit *r)
11161 : {
11162 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11163 0 : return WERR_NOT_SUPPORTED;
11164 : }
11165 :
11166 : /****************************************************************
11167 : _spoolss_ResetPrinterEx
11168 : ****************************************************************/
11169 :
11170 0 : WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
11171 : struct spoolss_ResetPrinterEx *r)
11172 : {
11173 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11174 0 : return WERR_NOT_SUPPORTED;
11175 : }
11176 :
11177 : /****************************************************************
11178 : _spoolss_RouterReplyPrinterEx
11179 : ****************************************************************/
11180 :
11181 0 : WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
11182 : struct spoolss_RouterReplyPrinterEx *r)
11183 : {
11184 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11185 0 : return WERR_NOT_SUPPORTED;
11186 : }
11187 :
11188 : /****************************************************************
11189 : _spoolss_44
11190 : ****************************************************************/
11191 :
11192 0 : WERROR _spoolss_44(struct pipes_struct *p,
11193 : struct spoolss_44 *r)
11194 : {
11195 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11196 0 : return WERR_NOT_SUPPORTED;
11197 : }
11198 :
11199 : /****************************************************************
11200 : _spoolss_SetPort
11201 : ****************************************************************/
11202 :
11203 0 : WERROR _spoolss_SetPort(struct pipes_struct *p,
11204 : struct spoolss_SetPort *r)
11205 : {
11206 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11207 0 : return WERR_NOT_SUPPORTED;
11208 : }
11209 :
11210 : /****************************************************************
11211 : _spoolss_4a
11212 : ****************************************************************/
11213 :
11214 0 : WERROR _spoolss_4a(struct pipes_struct *p,
11215 : struct spoolss_4a *r)
11216 : {
11217 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11218 0 : return WERR_NOT_SUPPORTED;
11219 : }
11220 :
11221 : /****************************************************************
11222 : _spoolss_4b
11223 : ****************************************************************/
11224 :
11225 0 : WERROR _spoolss_4b(struct pipes_struct *p,
11226 : struct spoolss_4b *r)
11227 : {
11228 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11229 0 : return WERR_NOT_SUPPORTED;
11230 : }
11231 :
11232 : /****************************************************************
11233 : _spoolss_4c
11234 : ****************************************************************/
11235 :
11236 0 : WERROR _spoolss_4c(struct pipes_struct *p,
11237 : struct spoolss_4c *r)
11238 : {
11239 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11240 0 : return WERR_NOT_SUPPORTED;
11241 : }
11242 :
11243 : /****************************************************************
11244 : _spoolss_53
11245 : ****************************************************************/
11246 :
11247 0 : WERROR _spoolss_53(struct pipes_struct *p,
11248 : struct spoolss_53 *r)
11249 : {
11250 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11251 0 : return WERR_NOT_SUPPORTED;
11252 : }
11253 :
11254 : /****************************************************************
11255 : _spoolss_AddPerMachineConnection
11256 : ****************************************************************/
11257 :
11258 4 : WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
11259 : struct spoolss_AddPerMachineConnection *r)
11260 : {
11261 4 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11262 4 : return WERR_NOT_SUPPORTED;
11263 : }
11264 :
11265 : /****************************************************************
11266 : _spoolss_DeletePerMachineConnection
11267 : ****************************************************************/
11268 :
11269 0 : WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
11270 : struct spoolss_DeletePerMachineConnection *r)
11271 : {
11272 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11273 0 : return WERR_NOT_SUPPORTED;
11274 : }
11275 :
11276 : /****************************************************************
11277 : _spoolss_EnumPerMachineConnections
11278 : ****************************************************************/
11279 :
11280 0 : WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
11281 : struct spoolss_EnumPerMachineConnections *r)
11282 : {
11283 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11284 0 : return WERR_NOT_SUPPORTED;
11285 : }
11286 :
11287 : /****************************************************************
11288 : _spoolss_5a
11289 : ****************************************************************/
11290 :
11291 0 : WERROR _spoolss_5a(struct pipes_struct *p,
11292 : struct spoolss_5a *r)
11293 : {
11294 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11295 0 : return WERR_NOT_SUPPORTED;
11296 : }
11297 :
11298 : /****************************************************************
11299 : _spoolss_5b
11300 : ****************************************************************/
11301 :
11302 0 : WERROR _spoolss_5b(struct pipes_struct *p,
11303 : struct spoolss_5b *r)
11304 : {
11305 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11306 0 : return WERR_NOT_SUPPORTED;
11307 : }
11308 :
11309 : /****************************************************************
11310 : _spoolss_5c
11311 : ****************************************************************/
11312 :
11313 0 : WERROR _spoolss_5c(struct pipes_struct *p,
11314 : struct spoolss_5c *r)
11315 : {
11316 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11317 0 : return WERR_NOT_SUPPORTED;
11318 : }
11319 :
11320 : /****************************************************************
11321 : _spoolss_5d
11322 : ****************************************************************/
11323 :
11324 0 : WERROR _spoolss_5d(struct pipes_struct *p,
11325 : struct spoolss_5d *r)
11326 : {
11327 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11328 0 : return WERR_NOT_SUPPORTED;
11329 : }
11330 :
11331 : /****************************************************************
11332 : _spoolss_5e
11333 : ****************************************************************/
11334 :
11335 0 : WERROR _spoolss_5e(struct pipes_struct *p,
11336 : struct spoolss_5e *r)
11337 : {
11338 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11339 0 : return WERR_NOT_SUPPORTED;
11340 : }
11341 :
11342 : /****************************************************************
11343 : _spoolss_5f
11344 : ****************************************************************/
11345 :
11346 0 : WERROR _spoolss_5f(struct pipes_struct *p,
11347 : struct spoolss_5f *r)
11348 : {
11349 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11350 0 : return WERR_NOT_SUPPORTED;
11351 : }
11352 :
11353 : /****************************************************************
11354 : _spoolss_60
11355 : ****************************************************************/
11356 :
11357 0 : WERROR _spoolss_60(struct pipes_struct *p,
11358 : struct spoolss_60 *r)
11359 : {
11360 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11361 0 : return WERR_NOT_SUPPORTED;
11362 : }
11363 :
11364 : /****************************************************************
11365 : _spoolss_SendRecvBidiData
11366 : ****************************************************************/
11367 :
11368 0 : WERROR _spoolss_SendRecvBidiData(struct pipes_struct *p,
11369 : struct spoolss_SendRecvBidiData *r)
11370 : {
11371 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11372 0 : return WERR_NOT_SUPPORTED;
11373 : }
11374 :
11375 : /****************************************************************
11376 : _spoolss_62
11377 : ****************************************************************/
11378 :
11379 0 : WERROR _spoolss_62(struct pipes_struct *p,
11380 : struct spoolss_62 *r)
11381 : {
11382 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11383 0 : return WERR_NOT_SUPPORTED;
11384 : }
11385 :
11386 : /****************************************************************
11387 : _spoolss_63
11388 : ****************************************************************/
11389 :
11390 0 : WERROR _spoolss_63(struct pipes_struct *p,
11391 : struct spoolss_63 *r)
11392 : {
11393 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11394 0 : return WERR_NOT_SUPPORTED;
11395 : }
11396 :
11397 : /****************************************************************
11398 : _spoolss_64
11399 : ****************************************************************/
11400 :
11401 0 : WERROR _spoolss_64(struct pipes_struct *p,
11402 : struct spoolss_64 *r)
11403 : {
11404 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11405 0 : return WERR_NOT_SUPPORTED;
11406 : }
11407 :
11408 : /****************************************************************
11409 : _spoolss_65
11410 : ****************************************************************/
11411 :
11412 0 : WERROR _spoolss_65(struct pipes_struct *p,
11413 : struct spoolss_65 *r)
11414 : {
11415 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11416 0 : return WERR_NOT_SUPPORTED;
11417 : }
11418 :
11419 : /****************************************************************
11420 : _spoolss_GetCorePrinterDrivers
11421 : ****************************************************************/
11422 :
11423 8 : HRESULT _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
11424 : struct spoolss_GetCorePrinterDrivers *r)
11425 : {
11426 8 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11427 8 : return HRES_ERROR_NOT_SUPPORTED;
11428 : }
11429 :
11430 : /****************************************************************
11431 : _spoolss_67
11432 : ****************************************************************/
11433 :
11434 0 : WERROR _spoolss_67(struct pipes_struct *p,
11435 : struct spoolss_67 *r)
11436 : {
11437 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11438 0 : return WERR_NOT_SUPPORTED;
11439 : }
11440 :
11441 : /****************************************************************
11442 : _spoolss_GetPrinterDriverPackagePath
11443 : ****************************************************************/
11444 :
11445 4 : HRESULT _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
11446 : struct spoolss_GetPrinterDriverPackagePath *r)
11447 : {
11448 4 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11449 4 : return HRES_ERROR_NOT_SUPPORTED;
11450 : }
11451 :
11452 : /****************************************************************
11453 : _spoolss_69
11454 : ****************************************************************/
11455 :
11456 0 : WERROR _spoolss_69(struct pipes_struct *p,
11457 : struct spoolss_69 *r)
11458 : {
11459 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11460 0 : return WERR_NOT_SUPPORTED;
11461 : }
11462 :
11463 : /****************************************************************
11464 : _spoolss_6a
11465 : ****************************************************************/
11466 :
11467 0 : WERROR _spoolss_6a(struct pipes_struct *p,
11468 : struct spoolss_6a *r)
11469 : {
11470 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11471 0 : return WERR_NOT_SUPPORTED;
11472 : }
11473 :
11474 : /****************************************************************
11475 : _spoolss_6b
11476 : ****************************************************************/
11477 :
11478 0 : WERROR _spoolss_6b(struct pipes_struct *p,
11479 : struct spoolss_6b *r)
11480 : {
11481 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11482 0 : return WERR_NOT_SUPPORTED;
11483 : }
11484 :
11485 : /****************************************************************
11486 : _spoolss_6c
11487 : ****************************************************************/
11488 :
11489 0 : WERROR _spoolss_6c(struct pipes_struct *p,
11490 : struct spoolss_6c *r)
11491 : {
11492 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11493 0 : return WERR_NOT_SUPPORTED;
11494 : }
11495 :
11496 : /****************************************************************
11497 : _spoolss_6d
11498 : ****************************************************************/
11499 :
11500 0 : WERROR _spoolss_6d(struct pipes_struct *p,
11501 : struct spoolss_6d *r)
11502 : {
11503 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11504 0 : return WERR_NOT_SUPPORTED;
11505 : }
11506 :
11507 : /****************************************************************
11508 : _spoolss_GetJobNamedPropertyValue
11509 : ****************************************************************/
11510 :
11511 0 : WERROR _spoolss_GetJobNamedPropertyValue(struct pipes_struct *p,
11512 : struct spoolss_GetJobNamedPropertyValue *r)
11513 : {
11514 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11515 0 : return WERR_NOT_SUPPORTED;
11516 : }
11517 :
11518 : /****************************************************************
11519 : _spoolss_SetJobNamedProperty
11520 : ****************************************************************/
11521 :
11522 0 : WERROR _spoolss_SetJobNamedProperty(struct pipes_struct *p,
11523 : struct spoolss_SetJobNamedProperty *r)
11524 : {
11525 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11526 0 : return WERR_NOT_SUPPORTED;
11527 : }
11528 :
11529 : /****************************************************************
11530 : _spoolss_DeleteJobNamedProperty
11531 : ****************************************************************/
11532 :
11533 0 : WERROR _spoolss_DeleteJobNamedProperty(struct pipes_struct *p,
11534 : struct spoolss_DeleteJobNamedProperty *r)
11535 : {
11536 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11537 0 : return WERR_NOT_SUPPORTED;
11538 : }
11539 :
11540 : /****************************************************************
11541 : _spoolss_EnumJobNamedProperties
11542 : ****************************************************************/
11543 :
11544 0 : WERROR _spoolss_EnumJobNamedProperties(struct pipes_struct *p,
11545 : struct spoolss_EnumJobNamedProperties *r)
11546 : {
11547 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11548 0 : return WERR_NOT_SUPPORTED;
11549 : }
11550 :
11551 : /****************************************************************
11552 : _spoolss_72
11553 : ****************************************************************/
11554 :
11555 0 : WERROR _spoolss_72(struct pipes_struct *p,
11556 : struct spoolss_72 *r)
11557 : {
11558 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11559 0 : return WERR_NOT_SUPPORTED;
11560 : }
11561 :
11562 : /****************************************************************
11563 : _spoolss_73
11564 : ****************************************************************/
11565 :
11566 0 : WERROR _spoolss_73(struct pipes_struct *p,
11567 : struct spoolss_73 *r)
11568 : {
11569 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11570 0 : return WERR_NOT_SUPPORTED;
11571 : }
11572 :
11573 : /****************************************************************
11574 : _spoolss_RpcLogJobInfoForBranchOffice
11575 : ****************************************************************/
11576 :
11577 8 : WERROR _spoolss_LogJobInfoForBranchOffice(struct pipes_struct *p,
11578 : struct spoolss_LogJobInfoForBranchOffice *r)
11579 : {
11580 8 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11581 8 : return WERR_NOT_SUPPORTED;
11582 : }
11583 :
11584 : static NTSTATUS spoolss__op_init_server(struct dcesrv_context *dce_ctx,
11585 : const struct dcesrv_endpoint_server *ep_server);
11586 :
11587 : static NTSTATUS spoolss__op_shutdown_server(struct dcesrv_context *dce_ctx,
11588 : const struct dcesrv_endpoint_server *ep_server);
11589 :
11590 : #define DCESRV_INTERFACE_SPOOLSS_INIT_SERVER \
11591 : spoolss_init_server
11592 :
11593 : #define DCESRV_INTERFACE_SPOOLSS_SHUTDOWN_SERVER \
11594 : spoolss_shutdown_server
11595 :
11596 28 : static NTSTATUS spoolss_init_server(struct dcesrv_context *dce_ctx,
11597 : const struct dcesrv_endpoint_server *ep_server)
11598 : {
11599 28 : struct messaging_context *msg_ctx = global_messaging_context();
11600 0 : bool ok;
11601 :
11602 : /*
11603 : * Migrate the printers first.
11604 : */
11605 28 : ok = nt_printing_tdb_migrate(msg_ctx);
11606 28 : if (!ok) {
11607 0 : return NT_STATUS_UNSUCCESSFUL;
11608 : }
11609 :
11610 28 : return spoolss__op_init_server(dce_ctx, ep_server);
11611 : }
11612 :
11613 28 : static NTSTATUS spoolss_shutdown_server(struct dcesrv_context *dce_ctx,
11614 : const struct dcesrv_endpoint_server *ep_server)
11615 : {
11616 28 : srv_spoolss_cleanup();
11617 :
11618 28 : return spoolss__op_shutdown_server(dce_ctx, ep_server);
11619 : }
11620 :
11621 : /* include the generated boilerplate */
11622 : #include "librpc/gen_ndr/ndr_spoolss_scompat.c"
|